optabs.c (prepare_cmp_insn): Try cmpmemM first if it exists, then fall back to cmpstrM.
authorJakub Jelinek <jakub@redhat.com>
Fri, 11 Jul 2003 21:04:56 +0000 (23:04 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 11 Jul 2003 21:04:56 +0000 (23:04 +0200)
* 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

gcc/ChangeLog
gcc/builtins.c
gcc/config/i370/i370.md
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.md
gcc/doc/md.texi
gcc/optabs.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/20030711-1.c [new file with mode: 0644]

index b60914a6a069bd6a3ac0e8d3e512ebb00528f73f..2c60ad5cc7b98bc51d0019f19341733f85e05b3f 100644 (file)
@@ -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.
index 94712150ad1f1d78754eaca9faaddaa1385e073c..90cd6acd1655dc98300b6a9ee32567716f36e13f 100644 (file)
@@ -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);
index 5bdbec80abe0d96dcd3306e856c8b77bbadea486..081c62dd8fa278ca44a2db5ff0bf14603a3c7252 100644 (file)
@@ -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))
index 7641fcb20767d35e40b017563407bd2651c5960b..3d3f53a4bc2f4d8c6a0a7c3f4e68250c3c288b22 100644 (file)
@@ -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));
index 7db180d8141a84b8952ccc8014f9a81ae0e3e188..07d30326a9e29deca40865f4472de34003a9424d 100644 (file)
@@ -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;
 
index 703f0d7a48404590a2182bb65175e885d9e8c93f..fc1af11c7eff8948294b3e23dbe2e11f2ac13c0c 100644 (file)
    (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")))
    (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")))
 
 ; 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)
   [(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)
index 7bbdda8e415426250f20b40c018755fea95e83d7..780cbbe9a34c75604925d4b21f1a910a9c9fa2aa 100644 (file)
@@ -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.
index b4023e3eff4a99bf6bbf53fb381063078b4de431..3085b8529ca54e79d684ac7ae715b45ff7640cb1 100644 (file)
@@ -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
index a4e85cf38edf564e8007dea4e5211b3f054d6047..9550b62e69fb9abb824124473d3381e625331e27 100644 (file)
@@ -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 (file)
index 0000000..25f515c
--- /dev/null
@@ -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;
+}