diff options
author | Adrian Straetling <straetling@de.ibm.com> | 2005-07-12 09:20:21 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@gcc.gnu.org> | 2005-07-12 09:20:21 +0000 |
commit | 40c1d5f85484c2c48cc9e663708c77ebb3fc887d (patch) | |
tree | 958e94659cf1699b8af01c3da5cdf919e2da079f /gcc | |
parent | 72f9377893a401cb13337523c1950d047d3c4acf (diff) | |
download | gcc-40c1d5f85484c2c48cc9e663708c77ebb3fc887d.zip gcc-40c1d5f85484c2c48cc9e663708c77ebb3fc887d.tar.gz gcc-40c1d5f85484c2c48cc9e663708c77ebb3fc887d.tar.bz2 |
builtins.c: (expand_builtin_memcmp, expand_builtin_strncmp): s/cmpstrsi/cmpstrnsi
2005-07-12 Adrian Straetling <straetling@de.ibm.com>
* builtins.c: (expand_builtin_memcmp, expand_builtin_strncmp):
s/cmpstrsi/cmpstrnsi
(expand_builtin_strcmp): Rewrite to support both 'cmpstrsi' and
'cmpstrnsi'.
* optabs.c: (prepare_cmp_insn): Add availability of 'cmpstrn'.
(init_optabs): Initialize cmpstrn_optab.
* optabs.h: (enum insn_code cmpstrn_optab): Declare.
* genopinit.c: (optabs[]): Add 'cmpstrn' to initialisation.
* expr.c: (enum insn_code cmpstrn_optab): Declare.
* config/i386/i386.md: s/cmpstr/cmpstrn
* config/c4x/c4x.md: s/cmpstr/cmpstrn
* doc/md.texi: Update documentation.
From-SVN: r101916
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/builtins.c | 235 | ||||
-rw-r--r-- | gcc/config/c4x/c4x.md | 4 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 30 | ||||
-rw-r--r-- | gcc/doc/md.texi | 23 | ||||
-rw-r--r-- | gcc/expr.c | 3 | ||||
-rw-r--r-- | gcc/genopinit.c | 1 | ||||
-rw-r--r-- | gcc/optabs.c | 3 | ||||
-rw-r--r-- | gcc/optabs.h | 1 |
9 files changed, 193 insertions, 122 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f44b1f4..0ab6fde 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2005-07-12 Adrian Straetling <straetling@de.ibm.com> + + * builtins.c: (expand_builtin_memcmp, expand_builtin_strncmp): + s/cmpstrsi/cmpstrnsi + (expand_builtin_strcmp): Rewrite to support both 'cmpstrsi' and + 'cmpstrnsi'. + * optabs.c: (prepare_cmp_insn): Add availability of 'cmpstrn'. + (init_optabs): Initialize cmpstrn_optab. + * optabs.h: (enum insn_code cmpstrn_optab): Declare. + * genopinit.c: (optabs[]): Add 'cmpstrn' to initialisation. + * expr.c: (enum insn_code cmpstrn_optab): Declare. + * config/i386/i386.md: s/cmpstr/cmpstrn + * config/c4x/c4x.md: s/cmpstr/cmpstrn + * doc/md.texi: Update documentation. + 2005-07-11 Richard Henderson <rth@redhat.com> * config/alpha/alpha.c (alpha_gimplify_va_arg_1): Use diff --git a/gcc/builtins.c b/gcc/builtins.c index f308f53..b032fc4 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3449,7 +3449,7 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, return expand_expr (result, target, mode, EXPAND_NORMAL); } -#if defined HAVE_cmpmemsi || defined HAVE_cmpstrsi +#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi { tree arg1 = TREE_VALUE (arglist); tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); @@ -3469,9 +3469,9 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode; else #endif -#ifdef HAVE_cmpstrsi - if (HAVE_cmpstrsi) - insn_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode; +#ifdef HAVE_cmpstrnsi + if (HAVE_cmpstrnsi) + insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode; else #endif return 0; @@ -3504,10 +3504,10 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, GEN_INT (MIN (arg1_align, arg2_align))); else #endif -#ifdef HAVE_cmpstrsi - if (HAVE_cmpstrsi) - insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx, - GEN_INT (MIN (arg1_align, arg2_align))); +#ifdef HAVE_cmpstrnsi + if (HAVE_cmpstrnsi) + insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx, + GEN_INT (MIN (arg1_align, arg2_align))); else #endif gcc_unreachable (); @@ -3558,103 +3558,134 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode) return expand_expr (result, target, mode, EXPAND_NORMAL); } -#ifdef HAVE_cmpstrsi - if (HAVE_cmpstrsi) - { - tree arg1 = TREE_VALUE (arglist); - tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); - tree len, len1, len2; - rtx arg1_rtx, arg2_rtx, arg3_rtx; - rtx result, insn; - tree fndecl, fn; - - int arg1_align - = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; - int arg2_align - = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; - enum machine_mode insn_mode - = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode; +#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi + if (cmpstr_optab[SImode] != CODE_FOR_nothing + || cmpstrn_optab[SImode] != CODE_FOR_nothing) + { + rtx arg1_rtx, arg2_rtx; + rtx result, insn = NULL_RTX; + tree fndecl, fn; + + tree arg1 = TREE_VALUE (arglist); + tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); + int arg1_align + = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; + int arg2_align + = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; + + /* If we don't have POINTER_TYPE, call the function. */ + if (arg1_align == 0 || arg2_align == 0) + return 0; - len1 = c_strlen (arg1, 1); - len2 = c_strlen (arg2, 1); + /* Stabilize the arguments in case gen_cmpstr(n)si fail. */ + arg1 = builtin_save_expr (arg1); + arg2 = builtin_save_expr (arg2); - if (len1) - len1 = size_binop (PLUS_EXPR, ssize_int (1), len1); - if (len2) - len2 = size_binop (PLUS_EXPR, ssize_int (1), len2); + arg1_rtx = get_memory_rtx (arg1); + arg2_rtx = get_memory_rtx (arg2); - /* If we don't have a constant length for the first, use the length - of the second, if we know it. We don't require a constant for - this case; some cost analysis could be done if both are available - but neither is constant. For now, assume they're equally cheap, - unless one has side effects. If both strings have constant lengths, - use the smaller. */ - - if (!len1) - len = len2; - else if (!len2) - len = len1; - else if (TREE_SIDE_EFFECTS (len1)) - len = len2; - else if (TREE_SIDE_EFFECTS (len2)) - len = len1; - else if (TREE_CODE (len1) != INTEGER_CST) - len = len2; - else if (TREE_CODE (len2) != INTEGER_CST) - len = len1; - else if (tree_int_cst_lt (len1, len2)) - len = len1; - else - len = len2; +#ifdef HAVE_cmpstrsi + /* Try to call cmpstrsi. */ + if (HAVE_cmpstrsi) + { + enum 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 +#if HAVE_cmpstrnsi + /* Try to determine at least one length and call cmpstrnsi. */ + if (!insn && HAVE_cmpstrnsi) + { + tree len; + rtx arg3_rtx; + + enum 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); + + if (len1) + len1 = size_binop (PLUS_EXPR, ssize_int (1), len1); + if (len2) + len2 = size_binop (PLUS_EXPR, ssize_int (1), len2); + + /* If we don't have a constant length for the first, use the length + of the second, if we know it. We don't require a constant for + this case; some cost analysis could be done if both are available + but neither is constant. For now, assume they're equally cheap, + unless one has side effects. If both strings have constant lengths, + use the smaller. */ + + if (!len1) + len = len2; + else if (!len2) + len = len1; + else if (TREE_SIDE_EFFECTS (len1)) + len = len2; + else if (TREE_SIDE_EFFECTS (len2)) + len = len1; + else if (TREE_CODE (len1) != INTEGER_CST) + len = len2; + else if (TREE_CODE (len2) != INTEGER_CST) + len = len1; + else if (tree_int_cst_lt (len1, len2)) + len = len1; + else + len = len2; - /* If both arguments have side effects, we cannot optimize. */ - if (!len || TREE_SIDE_EFFECTS (len)) - return 0; + /* If both arguments have side effects, we cannot optimize. */ + if (!len || TREE_SIDE_EFFECTS (len)) + return 0; - /* If we don't have POINTER_TYPE, call the function. */ - if (arg1_align == 0 || arg2_align == 0) - return 0; + /* Stabilize the arguments in case gen_cmpstrnsi fails. */ + arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); - /* 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); + /* 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_cmpstrsi fails. */ - arg1 = builtin_save_expr (arg1); - arg2 = builtin_save_expr (arg2); + insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx, + GEN_INT (MIN (arg1_align, arg2_align))); + } +#endif - arg1_rtx = get_memory_rtx (arg1); - arg2_rtx = get_memory_rtx (arg2); - arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); - insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx, - GEN_INT (MIN (arg1_align, arg2_align))); - if (insn) - { - emit_insn (insn); + if (insn) + { + emit_insn (insn); - /* Return the value in the proper mode for this function. */ - mode = TYPE_MODE (TREE_TYPE (exp)); - if (GET_MODE (result) == mode) - return result; - if (target == 0) - return convert_to_mode (mode, result, 0); - convert_move (target, result, 0); - return target; - } + /* Return the value in the proper mode for this function. */ + mode = TYPE_MODE (TREE_TYPE (exp)); + if (GET_MODE (result) == mode) + return result; + if (target == 0) + return convert_to_mode (mode, result, 0); + convert_move (target, result, 0); + return target; + } - /* Expand the library call ourselves using a stabilized argument - list to avoid re-evaluating the function's arguments twice. */ - arglist = build_tree_list (NULL_TREE, arg2); - arglist = tree_cons (NULL_TREE, arg1, arglist); - fndecl = get_callee_fndecl (exp); - fn = build_function_call_expr (fndecl, arglist); - if (TREE_CODE (fn) == CALL_EXPR) - CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); - return expand_call (fn, target, target == const0_rtx); - } + /* Expand the library call ourselves using a stabilized argument + list to avoid re-evaluating the function's arguments twice. */ + arglist = build_tree_list (NULL_TREE, arg2); + arglist = tree_cons (NULL_TREE, arg1, arglist); + fndecl = get_callee_fndecl (exp); + fn = build_function_call_expr (fndecl, arglist); + if (TREE_CODE (fn) == CALL_EXPR) + CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); + return expand_call (fn, target, target == const0_rtx); + } #endif return 0; } @@ -3679,10 +3710,10 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) } /* If c_strlen can determine an expression for one of the string - lengths, and it doesn't have side effects, then emit cmpstrsi + lengths, and it doesn't have side effects, then emit cmpstrnsi using length MIN(strlen(string)+1, arg3). */ -#ifdef HAVE_cmpstrsi - if (HAVE_cmpstrsi) +#ifdef HAVE_cmpstrnsi + if (HAVE_cmpstrnsi) { tree arg1 = TREE_VALUE (arglist); tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); @@ -3697,7 +3728,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) int arg2_align = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; enum machine_mode insn_mode - = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode; + = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode; len1 = c_strlen (arg1, 1); len2 = c_strlen (arg2, 1); @@ -3750,7 +3781,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) && REGNO (result) >= FIRST_PSEUDO_REGISTER)) result = gen_reg_rtx (insn_mode); - /* Stabilize the arguments in case gen_cmpstrsi fails. */ + /* Stabilize the arguments in case gen_cmpstrnsi fails. */ arg1 = builtin_save_expr (arg1); arg2 = builtin_save_expr (arg2); len = builtin_save_expr (len); @@ -3758,8 +3789,8 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) arg1_rtx = get_memory_rtx (arg1); arg2_rtx = get_memory_rtx (arg2); arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); - insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx, - GEN_INT (MIN (arg1_align, arg2_align))); + insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx, + GEN_INT (MIN (arg1_align, arg2_align))); if (insn) { emit_insn (insn); diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md index f37a49b..5054383 100644 --- a/gcc/config/c4x/c4x.md +++ b/gcc/config/c4x/c4x.md @@ -5714,7 +5714,7 @@ }") -(define_insn "*cmpstrqi" +(define_insn "*cmpstrnqi" [(set (match_operand:QI 0 "ext_reg_operand" "=d") (compare:QI (mem:BLK (match_operand:QI 1 "addr_reg_operand" "+a")) (mem:BLK (match_operand:QI 2 "addr_reg_operand" "+a")))) @@ -5731,7 +5731,7 @@ return \"\"; }") -(define_expand "cmpstrqi" +(define_expand "cmpstrnqi" [(parallel [(set (match_operand:QI 0 "reg_operand" "") (compare:QI (match_operand:BLK 1 "general_operand" "") (match_operand:BLK 2 "general_operand" ""))) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c0823b6..d3a085b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -17446,7 +17446,7 @@ (set_attr "memory" "store") (set_attr "mode" "QI")]) -(define_expand "cmpstrsi" +(define_expand "cmpstrnsi" [(set (match_operand:SI 0 "register_operand" "") (compare:SI (match_operand:BLK 1 "general_operand" "") (match_operand:BLK 2 "general_operand" ""))) @@ -17487,8 +17487,8 @@ emit_move_insn (operands[0], const0_rtx); DONE; } - emit_insn (gen_cmpstrqi_nz_1 (addr1, addr2, countreg, align, - operands[1], operands[2])); + emit_insn (gen_cmpstrnqi_nz_1 (addr1, addr2, countreg, align, + operands[1], operands[2])); } else { @@ -17496,8 +17496,8 @@ emit_insn (gen_cmpdi_1_rex64 (countreg, countreg)); else emit_insn (gen_cmpsi_1 (countreg, countreg)); - emit_insn (gen_cmpstrqi_1 (addr1, addr2, countreg, align, - operands[1], operands[2])); + emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align, + operands[1], operands[2])); } outlow = gen_lowpart (QImode, out); @@ -17528,7 +17528,7 @@ ;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is ;; zero. Emit extra code to make sure that a zero-length compare is EQ. -(define_expand "cmpstrqi_nz_1" +(define_expand "cmpstrnqi_nz_1" [(parallel [(set (reg:CC FLAGS_REG) (compare:CC (match_operand 4 "memory_operand" "") (match_operand 5 "memory_operand" ""))) @@ -17541,7 +17541,7 @@ "" "") -(define_insn "*cmpstrqi_nz_1" +(define_insn "*cmpstrnqi_nz_1" [(set (reg:CC FLAGS_REG) (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0")) (mem:BLK (match_operand:SI 5 "register_operand" "1")))) @@ -17557,7 +17557,7 @@ (set_attr "mode" "QI") (set_attr "prefix_rep" "1")]) -(define_insn "*cmpstrqi_nz_rex_1" +(define_insn "*cmpstrnqi_nz_rex_1" [(set (reg:CC FLAGS_REG) (compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0")) (mem:BLK (match_operand:DI 5 "register_operand" "1")))) @@ -17575,7 +17575,7 @@ ;; The same, but the count is not known to not be zero. -(define_expand "cmpstrqi_1" +(define_expand "cmpstrnqi_1" [(parallel [(set (reg:CC FLAGS_REG) (if_then_else:CC (ne (match_operand 2 "register_operand" "") (const_int 0)) @@ -17591,7 +17591,7 @@ "" "") -(define_insn "*cmpstrqi_1" +(define_insn "*cmpstrnqi_1" [(set (reg:CC FLAGS_REG) (if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2") (const_int 0)) @@ -17610,7 +17610,7 @@ (set_attr "mode" "QI") (set_attr "prefix_rep" "1")]) -(define_insn "*cmpstrqi_rex_1" +(define_insn "*cmpstrnqi_rex_1" [(set (reg:CC FLAGS_REG) (if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2") (const_int 0)) @@ -17693,9 +17693,9 @@ (set_attr "mode" "QI") (set_attr "prefix_rep" "1")]) -;; Peephole optimizations to clean up after cmpstr*. This should be +;; Peephole optimizations to clean up after cmpstrn*. This should be ;; handled in combine, but it is not currently up to the task. -;; When used for their truth value, the cmpstr* expanders generate +;; When used for their truth value, the cmpstrn* expanders generate ;; code like this: ;; ;; repz cmpsb @@ -17706,7 +17706,7 @@ ;; ;; The intermediate three instructions are unnecessary. -;; This one handles cmpstr*_nz_1... +;; This one handles cmpstrn*_nz_1... (define_peephole2 [(parallel[ (set (reg:CC FLAGS_REG) @@ -17738,7 +17738,7 @@ (clobber (match_dup 2))])] "") -;; ...and this one handles cmpstr*_1. +;; ...and this one handles cmpstrn*_1. (define_peephole2 [(parallel[ (set (reg:CC FLAGS_REG) diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 84be6e4..5af0d55 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -3269,8 +3269,8 @@ operand. The use for multiple @code{setmem@var{m}} is as for @code{movmem@var{m}}. -@cindex @code{cmpstr@var{m}} instruction pattern -@item @samp{cmpstr@var{m}} +@cindex @code{cmpstrn@var{m}} instruction pattern +@item @samp{cmpstrn@var{m}} String compare instruction, with five operands. Operand 0 is the output; it has mode @var{m}. The remaining four operands are like the operands of @samp{movmem@var{m}}. The two memory blocks specified are compared @@ -3281,6 +3281,25 @@ that may access an invalid page or segment and cause a fault. The effect of the instruction is to store a value in operand 0 whose sign indicates the result of the comparison. +@cindex @code{cmpstr@var{m}} instruction pattern +@item @samp{cmpstr@var{m}} +String compare instruction, without known maximum length. Operand 0 is the +output; it has mode @var{m}. The second and third operand are the blocks of +memory to be compared; both are @code{mem:BLK} with an address in mode +@code{Pmode}. + +The fourth operand is the known shared alignment of the source and +destination, in the form of a @code{const_int} rtx. Thus, if the +compiler knows that both source and destination are word-aligned, +it may provide the value 4 for this operand. + +The two memory blocks specified are compared byte by byte in lexicographic +order starting at the beginning of each string. The instruction is not allowed +to prefetch more than one byte at a time since either string may end in the +first byte and reading past that may access an invalid page or segment and +cause a fault. The effect of the instruction is to store a value in operand 0 +whose sign indicates the result of the comparison. + @cindex @code{cmpmem@var{m}} instruction pattern @item @samp{cmpmem@var{m}} Block compare instruction, with five operands like the operands @@ -202,9 +202,10 @@ enum insn_code movmem_optab[NUM_MACHINE_MODES]; /* This array records the insn_code of insns to perform block sets. */ enum insn_code setmem_optab[NUM_MACHINE_MODES]; -/* These arrays record the insn_code of two different kinds of insns +/* These arrays record the insn_code of three different kinds of insns to perform block compares. */ enum insn_code cmpstr_optab[NUM_MACHINE_MODES]; +enum insn_code cmpstrn_optab[NUM_MACHINE_MODES]; enum insn_code cmpmem_optab[NUM_MACHINE_MODES]; /* Synchronization primitives. */ diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 409ed08..8bf5747 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -169,6 +169,7 @@ static const char * const optabs[] = "reload_out_optab[$A] = CODE_FOR_$(reload_out$a$)", "movmem_optab[$A] = CODE_FOR_$(movmem$a$)", "cmpstr_optab[$A] = CODE_FOR_$(cmpstr$a$)", + "cmpstrn_optab[$A] = CODE_FOR_$(cmpstrn$a$)", "cmpmem_optab[$A] = CODE_FOR_$(cmpmem$a$)", "setmem_optab[$A] = CODE_FOR_$(setmem$a$)", "sync_add_optab[$A] = CODE_FOR_$(sync_add$I$a$)", diff --git a/gcc/optabs.c b/gcc/optabs.c index 60c4918..2f981ab 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -3426,6 +3426,8 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, if (cmp_code == CODE_FOR_nothing) cmp_code = cmpstr_optab[cmp_mode]; if (cmp_code == CODE_FOR_nothing) + cmp_code = cmpstrn_optab[cmp_mode]; + if (cmp_code == CODE_FOR_nothing) continue; /* Must make sure the size fits the insn's mode. */ @@ -5090,6 +5092,7 @@ init_optabs (void) { movmem_optab[i] = CODE_FOR_nothing; cmpstr_optab[i] = CODE_FOR_nothing; + cmpstrn_optab[i] = CODE_FOR_nothing; cmpmem_optab[i] = CODE_FOR_nothing; setmem_optab[i] = CODE_FOR_nothing; diff --git a/gcc/optabs.h b/gcc/optabs.h index bba0a5c..71f198a 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -450,6 +450,7 @@ extern enum insn_code setmem_optab[NUM_MACHINE_MODES]; /* These arrays record the insn_code of two different kinds of insns to perform block compares. */ extern enum insn_code cmpstr_optab[NUM_MACHINE_MODES]; +extern enum insn_code cmpstrn_optab[NUM_MACHINE_MODES]; extern enum insn_code cmpmem_optab[NUM_MACHINE_MODES]; /* Synchronization primitives. This first set is atomic operation for |