Message ID | 87k2tglf9g.fsf@e105548-lin.cambridge.arm.com |
---|---|
State | New |
Headers | show |
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
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" > {
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
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" {