aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2003-07-11 23:04:56 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2003-07-11 23:04:56 +0200
commit358b8f011484b845868d977d9bc0caaa096c96a3 (patch)
treea3656da4466c54cd571525ec90e2a1bf57bccbda /gcc
parent8634e925a9f53c086210ee461a0002278bc5c3d2 (diff)
downloadgcc-358b8f011484b845868d977d9bc0caaa096c96a3.zip
gcc-358b8f011484b845868d977d9bc0caaa096c96a3.tar.gz
gcc-358b8f011484b845868d977d9bc0caaa096c96a3.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/builtins.c29
-rw-r--r--gcc/config/i370/i370.md8
-rw-r--r--gcc/config/s390/s390-protos.h2
-rw-r--r--gcc/config/s390/s390.c6
-rw-r--r--gcc/config/s390/s390.md18
-rw-r--r--gcc/doc/md.texi12
-rw-r--r--gcc/optabs.c34
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/20030711-1.c25
10 files changed, 135 insertions, 23 deletions
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 <jakub@redhat.com>
+
+ * 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 <ljrittle@acm.org>
* 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 <jakub@redhat.com>
+
+ * gcc.dg/20030711-1.c: New test.
+
2003-07-11 Nathan Sidwell <nathan@codesourcery.com>
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 <sys/mman.h>
+#include <stdlib.h>
+
+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;
+}