* Use cmpstr and cmpstrn optabs
@ 2015-07-31 12:16 Richard Sandiford
2015-08-01 9:28 ` Kaz Kojima
2015-08-24 11:19 ` [PING] " Richard Sandiford
0 siblings, 2 replies; 4+ messages in thread
From: Richard Sandiford @ 2015-07-31 12:16 UTC (permalink / raw)
To: gcc-patches
expand_builtin_strcmp has:
if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
|| direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
{
...
machine_mode insn_mode
= insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
...
insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
GEN_INT (MIN (arg1_align, arg2_align)));
...
}
which is mixing the optabs interface and the CODE_FOR_foo/gen_foo
interface. It also doesn't check the predicates of the pattern,
unlike a normal optab expansion.
This patch converts the code to do everything via the optabs interface.
This required a change to the sh.md cmpstrn pattern, where the length
predicate was "immediate_operand" but where the expander code wanted
to handle nonimmediates too. I also removed the now-redundant
force_operand of the length in the rx.md pattern (because the
predicate is now enforced and already an operand).
The check whether "target" has insn_mode is performed by
create_output_operand so we no longer need to check it in
the builtins.c code too.
Bootstrapped & regression-tested on x86_64-linux-gnu. Also tested by
building ft32-elf, s390x-linux-gnu, m32c-elf, rx-elf and sh4-elf
and checking that (with the appropriate target flags) the optabs
are working for various strcmp and strncmp calls. OK to install?
Thanks,
Richard
gcc/
* builtins.c (expand_cmpstr, expand_cmpstrn): New functions.
(expand_builtin_strcmp, expand_builtin_strncmp): Use them. Remove
references to HAVE_cmpstr{,n}si and CODE_FOR_cmpstr{,n}si.
* config/m32c/blkmov.md (cmpstrsi): Fix predicates of operands 1 and 2.
Add predicates for operands 0 and 3.
* config/rx/rx.md (cmpstrnsi): Remove force_operand for the length
operand.
* config/sh/sh.md (cmpstrnsi): Change the length predicate from
immediate_operand to nonmemory_operand.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index d7eb65f..f5da72b 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -4016,6 +4016,53 @@ expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
return NULL_RTX;
}
+/* Try to expand cmpstr operation ICODE with the given operands.
+ Return the result rtx on success, otherwise return null. */
+
+static rtx
+expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
+ HOST_WIDE_INT align)
+{
+ machine_mode insn_mode = insn_data[icode].operand[0].mode;
+
+ if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
+ target = NULL_RTX;
+
+ struct expand_operand ops[4];
+ create_output_operand (&ops[0], target, insn_mode);
+ create_fixed_operand (&ops[1], arg1_rtx);
+ create_fixed_operand (&ops[2], arg2_rtx);
+ create_integer_operand (&ops[3], align);
+ if (maybe_expand_insn (icode, 4, ops))
+ return ops[0].value;
+ return NULL_RTX;
+}
+
+/* Try to expand cmpstrn operation ICODE with the given operands.
+ ARG3_TYPE is the type of ARG3_RTX. Return the result rtx on success,
+ otherwise return null. */
+
+static rtx
+expand_cmpstrn (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
+ tree arg3_type, rtx arg3_rtx, HOST_WIDE_INT align)
+{
+ machine_mode insn_mode = insn_data[icode].operand[0].mode;
+
+ if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
+ target = NULL_RTX;
+
+ struct expand_operand ops[5];
+ create_output_operand (&ops[0], target, insn_mode);
+ create_fixed_operand (&ops[1], arg1_rtx);
+ create_fixed_operand (&ops[2], arg2_rtx);
+ create_convert_operand_from (&ops[3], arg3_rtx, TYPE_MODE (arg3_type),
+ TYPE_UNSIGNED (arg3_type));
+ create_integer_operand (&ops[4], align);
+ if (maybe_expand_insn (icode, 5, ops))
+ return ops[0].value;
+ return NULL_RTX;
+}
+
/* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
if we failed the caller should emit a normal call, otherwise try to get
the result in TARGET, if convenient. */
@@ -4026,15 +4073,15 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return NULL_RTX;
-#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
- if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
- || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
+ insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode);
+ insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
+ if (cmpstr_icode != CODE_FOR_nothing || cmpstrn_icode != CODE_FOR_nothing)
{
rtx arg1_rtx, arg2_rtx;
- rtx result, insn = NULL_RTX;
tree fndecl, fn;
tree arg1 = CALL_EXPR_ARG (exp, 0);
tree arg2 = CALL_EXPR_ARG (exp, 1);
+ rtx result = NULL_RTX;
unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
@@ -4050,33 +4097,17 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
arg1_rtx = get_memory_rtx (arg1, NULL);
arg2_rtx = get_memory_rtx (arg2, NULL);
-#ifdef HAVE_cmpstrsi
/* Try to call cmpstrsi. */
- if (HAVE_cmpstrsi)
- {
- machine_mode insn_mode
- = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
-
- /* Make a place to write the result of the instruction. */
- result = target;
- if (! (result != 0
- && REG_P (result) && GET_MODE (result) == insn_mode
- && REGNO (result) >= FIRST_PSEUDO_REGISTER))
- result = gen_reg_rtx (insn_mode);
-
- insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
- GEN_INT (MIN (arg1_align, arg2_align)));
- }
-#endif
-#ifdef HAVE_cmpstrnsi
+ if (cmpstr_icode != CODE_FOR_nothing)
+ result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx,
+ MIN (arg1_align, arg2_align));
+
/* Try to determine at least one length and call cmpstrnsi. */
- if (!insn && HAVE_cmpstrnsi)
+ if (!result && cmpstrn_icode != CODE_FOR_nothing)
{
tree len;
rtx arg3_rtx;
- machine_mode insn_mode
- = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
tree len1 = c_strlen (arg1, 1);
tree len2 = c_strlen (arg2, 1);
@@ -4110,30 +4141,19 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
len = len2;
/* If both arguments have side effects, we cannot optimize. */
- if (!len || TREE_SIDE_EFFECTS (len))
- goto do_libcall;
-
- arg3_rtx = expand_normal (len);
-
- /* Make a place to write the result of the instruction. */
- result = target;
- if (! (result != 0
- && REG_P (result) && GET_MODE (result) == insn_mode
- && REGNO (result) >= FIRST_PSEUDO_REGISTER))
- result = gen_reg_rtx (insn_mode);
-
- insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
- GEN_INT (MIN (arg1_align, arg2_align)));
+ if (len && !TREE_SIDE_EFFECTS (len))
+ {
+ arg3_rtx = expand_normal (len);
+ result = expand_cmpstrn (cmpstrn_icode, target, arg1_rtx,
+ arg2_rtx, TREE_TYPE (len), arg3_rtx,
+ MIN (arg1_align, arg2_align));
+ }
}
-#endif
- if (insn)
+ if (result)
{
- machine_mode mode;
- emit_insn (insn);
-
/* Return the value in the proper mode for this function. */
- mode = TYPE_MODE (TREE_TYPE (exp));
+ machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
if (GET_MODE (result) == mode)
return result;
if (target == 0)
@@ -4144,16 +4164,12 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
/* Expand the library call ourselves using a stabilized argument
list to avoid re-evaluating the function's arguments twice. */
-#ifdef HAVE_cmpstrnsi
- do_libcall:
-#endif
fndecl = get_callee_fndecl (exp);
fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
gcc_assert (TREE_CODE (fn) == CALL_EXPR);
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
return expand_call (fn, target, target == const0_rtx);
}
-#endif
return NULL_RTX;
}
@@ -4174,12 +4190,12 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
/* If c_strlen can determine an expression for one of the string
lengths, and it doesn't have side effects, then emit cmpstrnsi
using length MIN(strlen(string)+1, arg3). */
-#ifdef HAVE_cmpstrnsi
- if (HAVE_cmpstrnsi)
+ insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
+ if (cmpstrn_icode != CODE_FOR_nothing)
{
tree len, len1, len2;
rtx arg1_rtx, arg2_rtx, arg3_rtx;
- rtx result, insn;
+ rtx result;
tree fndecl, fn;
tree arg1 = CALL_EXPR_ARG (exp, 0);
tree arg2 = CALL_EXPR_ARG (exp, 1);
@@ -4187,8 +4203,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
- machine_mode insn_mode
- = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
len1 = c_strlen (arg1, 1);
len2 = c_strlen (arg2, 1);
@@ -4234,13 +4248,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
if (arg1_align == 0 || arg2_align == 0)
return NULL_RTX;
- /* Make a place to write the result of the instruction. */
- result = target;
- if (! (result != 0
- && REG_P (result) && GET_MODE (result) == insn_mode
- && REGNO (result) >= FIRST_PSEUDO_REGISTER))
- result = gen_reg_rtx (insn_mode);
-
/* Stabilize the arguments in case gen_cmpstrnsi fails. */
arg1 = builtin_save_expr (arg1);
arg2 = builtin_save_expr (arg2);
@@ -4249,12 +4256,11 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
arg1_rtx = get_memory_rtx (arg1, len);
arg2_rtx = get_memory_rtx (arg2, len);
arg3_rtx = expand_normal (len);
- insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
- GEN_INT (MIN (arg1_align, arg2_align)));
- if (insn)
+ result = expand_cmpstrn (cmpstrn_icode, target, arg1_rtx, arg2_rtx,
+ TREE_TYPE (len), arg3_rtx,
+ MIN (arg1_align, arg2_align));
+ if (result)
{
- emit_insn (insn);
-
/* Return the value in the proper mode for this function. */
mode = TYPE_MODE (TREE_TYPE (exp));
if (GET_MODE (result) == mode)
@@ -4274,7 +4280,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
return expand_call (fn, target, target == const0_rtx);
}
-#endif
return NULL_RTX;
}
diff --git a/gcc/config/m32c/blkmov.md b/gcc/config/m32c/blkmov.md
index 88d0406..02ad345 100644
--- a/gcc/config/m32c/blkmov.md
+++ b/gcc/config/m32c/blkmov.md
@@ -178,10 +178,10 @@
;; 3 = alignment
(define_expand "cmpstrsi"
- [(match_operand:HI 0 "" "")
- (match_operand 1 "ap_operand" "")
- (match_operand 2 "ap_operand" "")
- (match_operand 3 "" "")
+ [(match_operand:HI 0 "register_operand" "")
+ (match_operand 1 "memory_operand" "")
+ (match_operand 2 "memory_operand" "")
+ (match_operand 3 "const_int_operand" "")
]
"TARGET_A24"
"if (m32c_expand_cmpstr(operands)) DONE; FAIL;"
diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
index 8b12475..6faf771 100644
--- a/gcc/config/rx/rx.md
+++ b/gcc/config/rx/rx.md
@@ -2315,7 +2315,7 @@
emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
- emit_move_insn (len, force_operand (operands[3], NULL_RTX));
+ emit_move_insn (len, operands[3]);
emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
DONE;
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 61f6637..0885ff3 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -12731,7 +12731,7 @@ label:
[(set (match_operand:SI 0 "register_operand")
(compare:SI (match_operand:BLK 1 "memory_operand")
(match_operand:BLK 2 "memory_operand")))
- (use (match_operand:SI 3 "immediate_operand"))
+ (use (match_operand:SI 3 "nonmemory_operand"))
(use (match_operand:SI 4 "immediate_operand"))]
"TARGET_SH1 && optimize"
{
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Use cmpstr and cmpstrn optabs
2015-07-31 12:16 Use cmpstr and cmpstrn optabs Richard Sandiford
@ 2015-08-01 9:28 ` Kaz Kojima
2015-08-24 11:19 ` [PING] " Richard Sandiford
1 sibling, 0 replies; 4+ messages in thread
From: Kaz Kojima @ 2015-08-01 9:28 UTC (permalink / raw)
To: richard.sandiford; +Cc: gcc-patches
Richard Sandiford <richard.sandiford@arm.com> wrote:
> This patch converts the code to do everything via the optabs interface.
> This required a change to the sh.md cmpstrn pattern, where the length
> predicate was "immediate_operand" but where the expander code wanted
> to handle nonimmediates too. I also removed the now-redundant
> force_operand of the length in the rx.md pattern (because the
> predicate is now enforced and already an operand).
>
> The check whether "target" has insn_mode is performed by
> create_output_operand so we no longer need to check it in
> the builtins.c code too.
>
> Bootstrapped & regression-tested on x86_64-linux-gnu. Also tested by
> building ft32-elf, s390x-linux-gnu, m32c-elf, rx-elf and sh4-elf
> and checking that (with the appropriate target flags) the optabs
> are working for various strcmp and strncmp calls. OK to install?
SH portion looks fine. No new failures with the patch on
sh4-unknown-linux-gnu.
Regards,
kaz
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PING] Use cmpstr and cmpstrn optabs
2015-07-31 12:16 Use cmpstr and cmpstrn optabs Richard Sandiford
2015-08-01 9:28 ` Kaz Kojima
@ 2015-08-24 11:19 ` Richard Sandiford
2015-08-24 17:26 ` Jeff Law
1 sibling, 1 reply; 4+ messages in thread
From: Richard Sandiford @ 2015-08-24 11:19 UTC (permalink / raw)
To: gcc-patches
Originally posted here:
https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02660.html
Kaz approved the SH parts and reported that there were no new failures
on sh4-unknown-linux-gnu (thanks).
Richard Sandiford <richard.sandiford@arm.com> writes:
> expand_builtin_strcmp has:
>
> if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
> || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
> {
> ...
> machine_mode insn_mode
> = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
> ...
> insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
> GEN_INT (MIN (arg1_align, arg2_align)));
> ...
> }
>
> which is mixing the optabs interface and the CODE_FOR_foo/gen_foo
> interface. It also doesn't check the predicates of the pattern,
> unlike a normal optab expansion.
>
> This patch converts the code to do everything via the optabs interface.
> This required a change to the sh.md cmpstrn pattern, where the length
> predicate was "immediate_operand" but where the expander code wanted
> to handle nonimmediates too. I also removed the now-redundant
> force_operand of the length in the rx.md pattern (because the
> predicate is now enforced and already an operand).
>
> The check whether "target" has insn_mode is performed by
> create_output_operand so we no longer need to check it in
> the builtins.c code too.
>
> Bootstrapped & regression-tested on x86_64-linux-gnu. Also tested by
> building ft32-elf, s390x-linux-gnu, m32c-elf, rx-elf and sh4-elf
> and checking that (with the appropriate target flags) the optabs
> are working for various strcmp and strncmp calls. OK to install?
>
> Thanks,
> Richard
>
> gcc/
> * builtins.c (expand_cmpstr, expand_cmpstrn): New functions.
> (expand_builtin_strcmp, expand_builtin_strncmp): Use them. Remove
> references to HAVE_cmpstr{,n}si and CODE_FOR_cmpstr{,n}si.
> * config/m32c/blkmov.md (cmpstrsi): Fix predicates of operands 1 and 2.
> Add predicates for operands 0 and 3.
> * config/rx/rx.md (cmpstrnsi): Remove force_operand for the length
> operand.
> * config/sh/sh.md (cmpstrnsi): Change the length predicate from
> immediate_operand to nonmemory_operand.
>
> diff --git a/gcc/builtins.c b/gcc/builtins.c
> index d7eb65f..f5da72b 100644
> --- a/gcc/builtins.c
> +++ b/gcc/builtins.c
> @@ -4016,6 +4016,53 @@ expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target,
> return NULL_RTX;
> }
>
> +/* Try to expand cmpstr operation ICODE with the given operands.
> + Return the result rtx on success, otherwise return null. */
> +
> +static rtx
> +expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
> + HOST_WIDE_INT align)
> +{
> + machine_mode insn_mode = insn_data[icode].operand[0].mode;
> +
> + if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
> + target = NULL_RTX;
> +
> + struct expand_operand ops[4];
> + create_output_operand (&ops[0], target, insn_mode);
> + create_fixed_operand (&ops[1], arg1_rtx);
> + create_fixed_operand (&ops[2], arg2_rtx);
> + create_integer_operand (&ops[3], align);
> + if (maybe_expand_insn (icode, 4, ops))
> + return ops[0].value;
> + return NULL_RTX;
> +}
> +
> +/* Try to expand cmpstrn operation ICODE with the given operands.
> + ARG3_TYPE is the type of ARG3_RTX. Return the result rtx on success,
> + otherwise return null. */
> +
> +static rtx
> +expand_cmpstrn (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
> + tree arg3_type, rtx arg3_rtx, HOST_WIDE_INT align)
> +{
> + machine_mode insn_mode = insn_data[icode].operand[0].mode;
> +
> + if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
> + target = NULL_RTX;
> +
> + struct expand_operand ops[5];
> + create_output_operand (&ops[0], target, insn_mode);
> + create_fixed_operand (&ops[1], arg1_rtx);
> + create_fixed_operand (&ops[2], arg2_rtx);
> + create_convert_operand_from (&ops[3], arg3_rtx, TYPE_MODE (arg3_type),
> + TYPE_UNSIGNED (arg3_type));
> + create_integer_operand (&ops[4], align);
> + if (maybe_expand_insn (icode, 5, ops))
> + return ops[0].value;
> + return NULL_RTX;
> +}
> +
> /* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX
> if we failed the caller should emit a normal call, otherwise try to get
> the result in TARGET, if convenient. */
> @@ -4026,15 +4073,15 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
> if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
> return NULL_RTX;
>
> -#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
> - if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
> - || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
> + insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode);
> + insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
> + if (cmpstr_icode != CODE_FOR_nothing || cmpstrn_icode != CODE_FOR_nothing)
> {
> rtx arg1_rtx, arg2_rtx;
> - rtx result, insn = NULL_RTX;
> tree fndecl, fn;
> tree arg1 = CALL_EXPR_ARG (exp, 0);
> tree arg2 = CALL_EXPR_ARG (exp, 1);
> + rtx result = NULL_RTX;
>
> unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
> unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
> @@ -4050,33 +4097,17 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
> arg1_rtx = get_memory_rtx (arg1, NULL);
> arg2_rtx = get_memory_rtx (arg2, NULL);
>
> -#ifdef HAVE_cmpstrsi
> /* Try to call cmpstrsi. */
> - if (HAVE_cmpstrsi)
> - {
> - machine_mode insn_mode
> - = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
> -
> - /* Make a place to write the result of the instruction. */
> - result = target;
> - if (! (result != 0
> - && REG_P (result) && GET_MODE (result) == insn_mode
> - && REGNO (result) >= FIRST_PSEUDO_REGISTER))
> - result = gen_reg_rtx (insn_mode);
> -
> - insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
> - GEN_INT (MIN (arg1_align, arg2_align)));
> - }
> -#endif
> -#ifdef HAVE_cmpstrnsi
> + if (cmpstr_icode != CODE_FOR_nothing)
> + result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx,
> + MIN (arg1_align, arg2_align));
> +
> /* Try to determine at least one length and call cmpstrnsi. */
> - if (!insn && HAVE_cmpstrnsi)
> + if (!result && cmpstrn_icode != CODE_FOR_nothing)
> {
> tree len;
> rtx arg3_rtx;
>
> - machine_mode insn_mode
> - = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
> tree len1 = c_strlen (arg1, 1);
> tree len2 = c_strlen (arg2, 1);
>
> @@ -4110,30 +4141,19 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
> len = len2;
>
> /* If both arguments have side effects, we cannot optimize. */
> - if (!len || TREE_SIDE_EFFECTS (len))
> - goto do_libcall;
> -
> - arg3_rtx = expand_normal (len);
> -
> - /* Make a place to write the result of the instruction. */
> - result = target;
> - if (! (result != 0
> - && REG_P (result) && GET_MODE (result) == insn_mode
> - && REGNO (result) >= FIRST_PSEUDO_REGISTER))
> - result = gen_reg_rtx (insn_mode);
> -
> - insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
> - GEN_INT (MIN (arg1_align, arg2_align)));
> + if (len && !TREE_SIDE_EFFECTS (len))
> + {
> + arg3_rtx = expand_normal (len);
> + result = expand_cmpstrn (cmpstrn_icode, target, arg1_rtx,
> + arg2_rtx, TREE_TYPE (len), arg3_rtx,
> + MIN (arg1_align, arg2_align));
> + }
> }
> -#endif
>
> - if (insn)
> + if (result)
> {
> - machine_mode mode;
> - emit_insn (insn);
> -
> /* Return the value in the proper mode for this function. */
> - mode = TYPE_MODE (TREE_TYPE (exp));
> + machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
> if (GET_MODE (result) == mode)
> return result;
> if (target == 0)
> @@ -4144,16 +4164,12 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
>
> /* Expand the library call ourselves using a stabilized argument
> list to avoid re-evaluating the function's arguments twice. */
> -#ifdef HAVE_cmpstrnsi
> - do_libcall:
> -#endif
> fndecl = get_callee_fndecl (exp);
> fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
> gcc_assert (TREE_CODE (fn) == CALL_EXPR);
> CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
> return expand_call (fn, target, target == const0_rtx);
> }
> -#endif
> return NULL_RTX;
> }
>
> @@ -4174,12 +4190,12 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
> /* If c_strlen can determine an expression for one of the string
> lengths, and it doesn't have side effects, then emit cmpstrnsi
> using length MIN(strlen(string)+1, arg3). */
> -#ifdef HAVE_cmpstrnsi
> - if (HAVE_cmpstrnsi)
> + insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
> + if (cmpstrn_icode != CODE_FOR_nothing)
> {
> tree len, len1, len2;
> rtx arg1_rtx, arg2_rtx, arg3_rtx;
> - rtx result, insn;
> + rtx result;
> tree fndecl, fn;
> tree arg1 = CALL_EXPR_ARG (exp, 0);
> tree arg2 = CALL_EXPR_ARG (exp, 1);
> @@ -4187,8 +4203,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
>
> unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
> unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
> - machine_mode insn_mode
> - = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
>
> len1 = c_strlen (arg1, 1);
> len2 = c_strlen (arg2, 1);
> @@ -4234,13 +4248,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
> if (arg1_align == 0 || arg2_align == 0)
> return NULL_RTX;
>
> - /* Make a place to write the result of the instruction. */
> - result = target;
> - if (! (result != 0
> - && REG_P (result) && GET_MODE (result) == insn_mode
> - && REGNO (result) >= FIRST_PSEUDO_REGISTER))
> - result = gen_reg_rtx (insn_mode);
> -
> /* Stabilize the arguments in case gen_cmpstrnsi fails. */
> arg1 = builtin_save_expr (arg1);
> arg2 = builtin_save_expr (arg2);
> @@ -4249,12 +4256,11 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
> arg1_rtx = get_memory_rtx (arg1, len);
> arg2_rtx = get_memory_rtx (arg2, len);
> arg3_rtx = expand_normal (len);
> - insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
> - GEN_INT (MIN (arg1_align, arg2_align)));
> - if (insn)
> + result = expand_cmpstrn (cmpstrn_icode, target, arg1_rtx, arg2_rtx,
> + TREE_TYPE (len), arg3_rtx,
> + MIN (arg1_align, arg2_align));
> + if (result)
> {
> - emit_insn (insn);
> -
> /* Return the value in the proper mode for this function. */
> mode = TYPE_MODE (TREE_TYPE (exp));
> if (GET_MODE (result) == mode)
> @@ -4274,7 +4280,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
> CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
> return expand_call (fn, target, target == const0_rtx);
> }
> -#endif
> return NULL_RTX;
> }
>
> diff --git a/gcc/config/m32c/blkmov.md b/gcc/config/m32c/blkmov.md
> index 88d0406..02ad345 100644
> --- a/gcc/config/m32c/blkmov.md
> +++ b/gcc/config/m32c/blkmov.md
> @@ -178,10 +178,10 @@
> ;; 3 = alignment
>
> (define_expand "cmpstrsi"
> - [(match_operand:HI 0 "" "")
> - (match_operand 1 "ap_operand" "")
> - (match_operand 2 "ap_operand" "")
> - (match_operand 3 "" "")
> + [(match_operand:HI 0 "register_operand" "")
> + (match_operand 1 "memory_operand" "")
> + (match_operand 2 "memory_operand" "")
> + (match_operand 3 "const_int_operand" "")
> ]
> "TARGET_A24"
> "if (m32c_expand_cmpstr(operands)) DONE; FAIL;"
> diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
> index 8b12475..6faf771 100644
> --- a/gcc/config/rx/rx.md
> +++ b/gcc/config/rx/rx.md
> @@ -2315,7 +2315,7 @@
>
> emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
> emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
> - emit_move_insn (len, force_operand (operands[3], NULL_RTX));
> + emit_move_insn (len, operands[3]);
>
> emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
> DONE;
> diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
> index 61f6637..0885ff3 100644
> --- a/gcc/config/sh/sh.md
> +++ b/gcc/config/sh/sh.md
> @@ -12731,7 +12731,7 @@ label:
> [(set (match_operand:SI 0 "register_operand")
> (compare:SI (match_operand:BLK 1 "memory_operand")
> (match_operand:BLK 2 "memory_operand")))
> - (use (match_operand:SI 3 "immediate_operand"))
> + (use (match_operand:SI 3 "nonmemory_operand"))
> (use (match_operand:SI 4 "immediate_operand"))]
> "TARGET_SH1 && optimize"
> {
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PING] Use cmpstr and cmpstrn optabs
2015-08-24 11:19 ` [PING] " Richard Sandiford
@ 2015-08-24 17:26 ` Jeff Law
0 siblings, 0 replies; 4+ messages in thread
From: Jeff Law @ 2015-08-24 17:26 UTC (permalink / raw)
To: gcc-patches, richard.sandiford
On 08/24/2015 05:17 AM, Richard Sandiford wrote:
> Originally posted here:
>
> https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02660.html
>
> Kaz approved the SH parts and reported that there were no new failures
> on sh4-unknown-linux-gnu (thanks).
Sorry, this must have slipped through the cracks. Thanks for pinging it.
>> * builtins.c (expand_cmpstr, expand_cmpstrn): New functions.
>> (expand_builtin_strcmp, expand_builtin_strncmp): Use them. Remove
>> references to HAVE_cmpstr{,n}si and CODE_FOR_cmpstr{,n}si.
>> * config/m32c/blkmov.md (cmpstrsi): Fix predicates of operands 1 and 2.
>> Add predicates for operands 0 and 3.
>> * config/rx/rx.md (cmpstrnsi): Remove force_operand for the length
>> operand.
>> * config/sh/sh.md (cmpstrnsi): Change the length predicate from
>> immediate_operand to nonmemory_operand.
OK.
jeff
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2015-08-24 17:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-31 12:16 Use cmpstr and cmpstrn optabs Richard Sandiford
2015-08-01 9:28 ` Kaz Kojima
2015-08-24 11:19 ` [PING] " Richard Sandiford
2015-08-24 17:26 ` Jeff Law
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).