From: Jakub Jelinek Date: Fri, 11 Jul 2003 21:04:56 +0000 (+0200) Subject: optabs.c (prepare_cmp_insn): Try cmpmemM first if it exists, then fall back to cmpstrM. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=358b8f011484b845868d977d9bc0caaa096c96a3;p=platform%2Fupstream%2Fgcc.git optabs.c (prepare_cmp_insn): Try cmpmemM first if it exists, then fall back to cmpstrM. * optabs.c (prepare_cmp_insn): Try cmpmemM first if it exists, then fall back to cmpstrM. * builtins.c (expand_builtin_memcmp): Likewise. * config/s390/s390-protos.h (s390_expand_cmpstr): Rename to... (s390_expand_cmpmem): ... this. * config/s390/s390.md (cmpmemdi, cmpmemsi, cmpmem_short_64, cmpmem_short_31, cmpmem_long_64, cmpmem_long_31): Renamed from cmpstr* patterns. Rename call to s390_expand_cmpstr to s390_expand_cmpmem. * config/s390/s390.c (s390_expand_cmpstr): Rename to... (s390_expand_cmpstr): ... this. Rename cmpstr* instructions to cmpmem*. * config/i370/i370.md (cmpmemsi, cmpmemsi_1): Renamed from cmpstr* patterns. * doc/md.texi (cmpstrM): Describe as String compare insn, not Block compare insn. (cmpmemM): Add. * gcc.dg/20030711-1.c: New test. From-SVN: r69243 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b60914a..2c60ad5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2003-07-11 Jakub Jelinek + + * optabs.c (prepare_cmp_insn): Try cmpmemM first if it exists, + then fall back to cmpstrM. + * builtins.c (expand_builtin_memcmp): Likewise. + * config/s390/s390-protos.h (s390_expand_cmpstr): Rename to... + (s390_expand_cmpmem): ... this. + * config/s390/s390.md (cmpmemdi, cmpmemsi, cmpmem_short_64, + cmpmem_short_31, cmpmem_long_64, cmpmem_long_31): Renamed + from cmpstr* patterns. Rename call to s390_expand_cmpstr + to s390_expand_cmpmem. + * config/s390/s390.c (s390_expand_cmpstr): Rename to... + (s390_expand_cmpstr): ... this. Rename cmpstr* instructions + to cmpmem*. + * config/i370/i370.md (cmpmemsi, cmpmemsi_1): Renamed from + cmpstr* patterns. + * doc/md.texi (cmpstrM): Describe as String compare insn, not + Block compare insn. + (cmpmemM): Add. + 2003-07-11 Loren James Rittle * config/i386/freebsd.h (SET_ASM_OP): Remove. diff --git a/gcc/builtins.c b/gcc/builtins.c index 9471215..90cd6ac 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3196,7 +3196,7 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, return expand_expr (result, target, mode, EXPAND_NORMAL); } -#ifdef HAVE_cmpstrsi +#if defined HAVE_cmpmemsi || defined HAVE_cmpstrsi { rtx arg1_rtx, arg2_rtx, arg3_rtx; rtx result; @@ -3206,8 +3206,19 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, = 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; + enum machine_mode insn_mode; + +#ifdef HAVE_cmpmemsi + if (HAVE_cmpmemsi) + 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; + else +#endif + return 0; /* If we don't have POINTER_TYPE, call the function. */ if (arg1_align == 0 || arg2_align == 0) @@ -3223,11 +3234,19 @@ expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target, arg1_rtx = get_memory_rtx (arg1); arg2_rtx = get_memory_rtx (arg2); arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); - if (!HAVE_cmpstrsi) - insn = NULL_RTX; +#ifdef HAVE_cmpmemsi + if (HAVE_cmpmemsi) + insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx, + 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))); + else +#endif + abort (); if (insn) emit_insn (insn); diff --git a/gcc/config/i370/i370.md b/gcc/config/i370/i370.md index 5bdbec8..081c62d 100644 --- a/gcc/config/i370/i370.md +++ b/gcc/config/i370/i370.md @@ -474,10 +474,10 @@ check_label_emit (); ) ; -; cmpstrsi instruction pattern(s). +; cmpmemsi instruction pattern(s). ; -(define_expand "cmpstrsi" +(define_expand "cmpmemsi" [(set (match_operand:SI 0 "general_operand" "") (compare (match_operand:BLK 1 "general_operand" "") (match_operand:BLK 2 "general_operand" ""))) @@ -545,7 +545,7 @@ check_label_emit (); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len); /* Compare! */ - emit_insn (gen_cmpstrsi_1 (result, reg1, reg2)); + emit_insn (gen_cmpmemsi_1 (result, reg1, reg2)); } DONE; }") @@ -569,7 +569,7 @@ check_label_emit (); ; Compare a block that is larger than 255 bytes in length. -(define_insn "cmpstrsi_1" +(define_insn "cmpmemsi_1" [(set (match_operand:SI 0 "register_operand" "+d") (compare (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "+d") 0)) diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 7641fcb..3d3f53a 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -68,7 +68,7 @@ extern void emit_symbolic_move PARAMS ((rtx *)); extern void s390_load_address PARAMS ((rtx, rtx)); extern void s390_expand_movstr PARAMS ((rtx, rtx, rtx)); extern void s390_expand_clrstr PARAMS ((rtx, rtx)); -extern void s390_expand_cmpstr PARAMS ((rtx, rtx, rtx, rtx)); +extern void s390_expand_cmpmem PARAMS ((rtx, rtx, rtx, rtx)); extern rtx s390_return_addr_rtx PARAMS ((int, rtx)); extern void s390_output_symbolic_const PARAMS ((FILE *, rtx)); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 7db180d..07d3032 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -3116,16 +3116,16 @@ s390_expand_clrstr (dst, len) and return the result in TARGET. */ void -s390_expand_cmpstr (target, op0, op1, len) +s390_expand_cmpmem (target, op0, op1, len) rtx target; rtx op0; rtx op1; rtx len; { rtx (*gen_short) PARAMS ((rtx, rtx, rtx)) = - TARGET_64BIT ? gen_cmpstr_short_64 : gen_cmpstr_short_31; + TARGET_64BIT ? gen_cmpmem_short_64 : gen_cmpmem_short_31; rtx (*gen_long) PARAMS ((rtx, rtx, rtx, rtx)) = - TARGET_64BIT ? gen_cmpstr_long_64 : gen_cmpstr_long_31; + TARGET_64BIT ? gen_cmpmem_long_64 : gen_cmpmem_long_31; rtx (*gen_result) PARAMS ((rtx)) = GET_MODE (target) == DImode ? gen_cmpint_di : gen_cmpint_si; diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 703f0d7..fc1af11 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -1958,33 +1958,33 @@ (set_attr "length" "8")]) ; -; cmpstrM instruction pattern(s). +; cmpmemM instruction pattern(s). ; -(define_expand "cmpstrdi" +(define_expand "cmpmemdi" [(set (match_operand:DI 0 "register_operand" "") (compare:DI (match_operand:BLK 1 "memory_operand" "") (match_operand:BLK 2 "memory_operand" "") ) ) (use (match_operand:DI 3 "general_operand" "")) (use (match_operand:DI 4 "" ""))] "TARGET_64BIT" - "s390_expand_cmpstr (operands[0], operands[1], + "s390_expand_cmpmem (operands[0], operands[1], operands[2], operands[3]); DONE;") -(define_expand "cmpstrsi" +(define_expand "cmpmemsi" [(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 "general_operand" "")) (use (match_operand:SI 4 "" ""))] "" - "s390_expand_cmpstr (operands[0], operands[1], + "s390_expand_cmpmem (operands[0], operands[1], operands[2], operands[3]); DONE;") ; Compare a block that is up to 256 bytes in length. ; The block length is taken as (operands[2] % 256) + 1. -(define_insn "cmpstr_short_64" +(define_insn "cmpmem_short_64" [(set (reg:CCS 33) (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q") (match_operand:BLK 1 "memory_operand" "Q,Q"))) @@ -2012,7 +2012,7 @@ (set_attr "atype" "*,agen") (set_attr "length" "*,14")]) -(define_insn "cmpstr_short_31" +(define_insn "cmpmem_short_31" [(set (reg:CCS 33) (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q") (match_operand:BLK 1 "memory_operand" "Q,Q"))) @@ -2042,7 +2042,7 @@ ; Compare a block of arbitrary length. -(define_insn "cmpstr_long_64" +(define_insn "cmpmem_long_64" [(clobber (match_operand:TI 0 "register_operand" "=d")) (clobber (match_operand:TI 1 "register_operand" "=d")) (set (reg:CCS 33) @@ -2055,7 +2055,7 @@ [(set_attr "op_type" "RR") (set_attr "type" "vs")]) -(define_insn "cmpstr_long_31" +(define_insn "cmpmem_long_31" [(clobber (match_operand:DI 0 "register_operand" "=d")) (clobber (match_operand:DI 1 "register_operand" "=d")) (set (reg:CCS 33) diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 7bbdda8..780cbbe 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -2799,7 +2799,7 @@ The use for multiple @code{clrstr@var{m}} is as for @code{movstr@var{m}}. @cindex @code{cmpstr@var{m}} instruction pattern @item @samp{cmpstr@var{m}} -Block compare instruction, with five operands. Operand 0 is the output; +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{movstr@var{m}}. The two memory blocks specified are compared byte by byte in lexicographic order starting at the beginning of each @@ -2809,6 +2809,16 @@ 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 +of @samp{cmpstr@var{m}}. The two memory blocks specified are compared +byte by byte in lexicographic order starting at the beginning of each +block. Unlike @samp{cmpstr@var{m}} the instruction can prefetch +any bytes in the two memory blocks. The effect of the instruction is +to store a value in operand 0 whose sign indicates the result of the +comparison. + @cindex @code{strlen@var{m}} instruction pattern @item @samp{strlen@var{m}} Compute the length of a string, with three operands. diff --git a/gcc/optabs.c b/gcc/optabs.c index b4023e3..3085b85 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -3579,6 +3579,40 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size, if (size == 0) abort (); +#ifdef HAVE_cmpmemqi + if (HAVE_cmpmemqi + && GET_CODE (size) == CONST_INT + && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode))) + { + result_mode = insn_data[(int) CODE_FOR_cmpmemqi].operand[0].mode; + result = gen_reg_rtx (result_mode); + emit_insn (gen_cmpmemqi (result, x, y, size, opalign)); + } + else +#endif +#ifdef HAVE_cmpmemhi + if (HAVE_cmpmemhi + && GET_CODE (size) == CONST_INT + && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode))) + { + result_mode = insn_data[(int) CODE_FOR_cmpmemhi].operand[0].mode; + result = gen_reg_rtx (result_mode); + emit_insn (gen_cmpmemhi (result, x, y, size, opalign)); + } + else +#endif +#ifdef HAVE_cmpmemsi + if (HAVE_cmpmemsi) + { + result_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode; + result = gen_reg_rtx (result_mode); + size = protect_from_queue (size, 0); + emit_insn (gen_cmpmemsi (result, x, y, + convert_to_mode (SImode, size, 1), + opalign)); + } + else +#endif #ifdef HAVE_cmpstrqi if (HAVE_cmpstrqi && GET_CODE (size) == CONST_INT diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a4e85cf..9550b62 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-07-11 Jakub Jelinek + + * gcc.dg/20030711-1.c: New test. + 2003-07-11 Nathan Sidwell PR c++/11050 diff --git a/gcc/testsuite/gcc.dg/20030711-1.c b/gcc/testsuite/gcc.dg/20030711-1.c new file mode 100644 index 0000000..25f515c --- /dev/null +++ b/gcc/testsuite/gcc.dg/20030711-1.c @@ -0,0 +1,25 @@ +/* Test whether strncmp has not been "optimized" into memcmp + nor any code with memcmp semantics. */ +/* { dg-do run { target i?86-*-linux* x86_64-*-linux* ia64-*-linux* alpha*-*-linux* powerpc*-*-linux* s390*-*-linux* sparc*-*-linux* } } */ +/* { dg-options "-O2" } */ +#include +#include + +void __attribute__((noinline)) test (const char *p) +{ + if (__builtin_strncmp (p, "abcdefghijklmnopq", 17) == 0) + abort (); +} + +int main (void) +{ + char *p = mmap (NULL, 131072, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (p == MAP_FAILED) + return 0; + if (munmap (p + 65536, 65536) < 0) + return 0; + __builtin_memcpy (p + 65536 - 5, "abcd", 5); + test (p + 65536 - 5); + return 0; +}