re PR target/67675 ([SH] Improve __builtin_strcmp alignment test)
authorOleg Endo <olegendo@gcc.gnu.org>
Fri, 25 Sep 2015 13:09:04 +0000 (13:09 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Fri, 25 Sep 2015 13:09:04 +0000 (13:09 +0000)
gcc/
PR target/67675
* config/sh/sh-mem.cc (sh_expand_cmpstr): Check alignment of addr1 and
addr2 individually.  Don't emit logical or insn if one is known to
be aligned approriately.
(sh_expand_cmpnstr): Likewise.

gcc/testsuite/
PR target/67675
* gcc.target/sh/pr67675.c: New.

From-SVN: r228118

gcc/ChangeLog
gcc/config/sh/sh-mem.cc
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/pr67675.c [new file with mode: 0644]

index 97b6cdc4fe779b1bf31e2784a231e82fab7784c6..1fe4e933737e8b6ba1fc40bd7d70fb4bb832fb50 100644 (file)
@@ -1,3 +1,11 @@
+2015-09-25  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/67675
+       * config/sh/sh-mem.cc (sh_expand_cmpstr): Check alignment of addr1 and
+       addr2 individually.  Don't emit logical or insn if one is known to
+       be aligned approriately.
+       (sh_expand_cmpnstr): Likewise.
+
 2015-09-25  Richard Sandiford  <richard.sandiford@arm.com>
 
        * config/aarch64/aarch64-builtins.c (aarch64_expand_builtin): Force
index 5a0fb9780d0ae431c5f628615d59a5c6828104e3..23a7287ef27c242a4ea21615841e1da0b750b23b 100644 (file)
@@ -224,17 +224,28 @@ sh_expand_cmpstr (rtx *operands)
   rtx_code_label *L_loop_long = gen_label_rtx ();
   rtx_code_label *L_end_loop_long = gen_label_rtx ();
 
-  int align = INTVAL (operands[3]);
-
-  emit_move_insn (tmp0, const0_rtx);
+  const unsigned int addr1_alignment = MEM_ALIGN (operands[1]) / BITS_PER_UNIT;
+  const unsigned int addr2_alignment = MEM_ALIGN (operands[2]) / BITS_PER_UNIT;
 
-  if (align < 4)
+  if (addr1_alignment < 4 && addr2_alignment < 4)
     {
       emit_insn (gen_iorsi3 (tmp1, s1_addr, s2_addr));
       emit_insn (gen_tstsi_t (tmp1, GEN_INT (3)));
       jump = emit_jump_insn (gen_branch_false (L_loop_byte));
       add_int_reg_note (jump, REG_BR_PROB, prob_likely);
     }
+  else if (addr1_alignment < 4 && addr2_alignment >= 4)
+    {
+      emit_insn (gen_tstsi_t (s1_addr, GEN_INT (3)));
+      jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+      add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+    }
+  else if (addr1_alignment >= 4 && addr2_alignment < 4)
+    {
+      emit_insn (gen_tstsi_t (s2_addr, GEN_INT (3)));
+      jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+      add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+    }
 
   addr1 = adjust_automodify_address (addr1, SImode, s1_addr, 0);
   addr2 = adjust_automodify_address (addr2, SImode, s2_addr, 0);
@@ -352,6 +363,9 @@ sh_expand_cmpnstr (rtx *operands)
   rtx len = force_reg (SImode, operands[3]);
   int constp = CONST_INT_P (operands[3]);
 
+  const unsigned int addr1_alignment = MEM_ALIGN (operands[1]) / BITS_PER_UNIT;
+  const unsigned int addr2_alignment = MEM_ALIGN (operands[2]) / BITS_PER_UNIT;
+
   /* Loop on a register count.  */
   if (constp)
     {
@@ -362,7 +376,6 @@ sh_expand_cmpnstr (rtx *operands)
       rtx_code_label *L_loop_long = gen_label_rtx ();
       rtx_code_label *L_end_loop_long = gen_label_rtx ();
 
-      int align = INTVAL (operands[4]);
       int bytes = INTVAL (operands[3]);
       int witers = bytes / 4;
 
@@ -373,13 +386,25 @@ sh_expand_cmpnstr (rtx *operands)
 
          emit_move_insn (tmp0, const0_rtx);
 
-         if (align < 4)
+         if (addr1_alignment < 4 && addr2_alignment < 4)
            {
              emit_insn (gen_iorsi3 (tmp1, s1_addr, s2_addr));
              emit_insn (gen_tstsi_t (tmp1, GEN_INT (3)));
              jump = emit_jump_insn (gen_branch_false (L_loop_byte));
              add_int_reg_note (jump, REG_BR_PROB, prob_likely);
            }
+         else if (addr1_alignment < 4 && addr2_alignment >= 4)
+           {
+             emit_insn (gen_tstsi_t (s1_addr, GEN_INT (3)));
+             jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+             add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+           }
+         else if (addr1_alignment >= 4 && addr2_alignment < 4)
+           {
+             emit_insn (gen_tstsi_t (s2_addr, GEN_INT (3)));
+             jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+             add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+           }
 
          /* word count. Do we have iterations ?  */
          emit_insn (gen_lshrsi3 (lenw, len, GEN_INT (2)));
index 07858088f7db8c3625a96740f22418d15d389371..30bd3a264b43df2d8ae5980f6badb06f23a4ac11 100644 (file)
@@ -1,3 +1,8 @@
+2015-09-25  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/67675
+       * gcc.target/sh/pr67675.c: New.
+
 2015-09-25  Richard Sandiford  <richard.sandiford@arm.com>
 
        * gcc.target/aarch64/fpcr_fpsr_1.c: New file.
diff --git a/gcc/testsuite/gcc.target/sh/pr67675.c b/gcc/testsuite/gcc.target/sh/pr67675.c
new file mode 100644 (file)
index 0000000..e6c5d0d
--- /dev/null
@@ -0,0 +1,62 @@
+/* Check that run time alignment tests are generated only for inputs of
+   unknown alignment.  */
+/* { dg-do compile }  */
+/* { dg-options "-O2" }  */
+/* { dg-final { scan-assembler-not "jmp|bsr|jsr" } }  */
+/* { dg-final { scan-assembler-times {tst      #3,r0} 6 } }  */
+/* { dg-final { scan-assembler-times {or       r[0-9],r[0-9]} 1 } }  */
+
+int
+test_00 (const char* x, const char* y)
+{
+  /* 1x or reg,reg, 1x tst #3,r0  */
+  return __builtin_strcmp (x, y);
+}
+
+int
+test_01 (const char* x, const char* y)
+{
+  /* 1x tst #3,r0  */
+  return __builtin_strcmp (__builtin_assume_aligned (x, 4), y);
+}
+
+int
+test_02 (const char* x, const char* y)
+{
+  /* 1x tst #3,r0  */
+  return __builtin_strcmp (x, __builtin_assume_aligned (y, 4));
+}
+
+int
+test_03 (const char* x, const char* y)
+{
+  return __builtin_strcmp (__builtin_assume_aligned (x, 4),
+                          __builtin_assume_aligned (y, 4));
+}
+
+int
+test_04 (const char* x, const char* y)
+{
+  /* 1x tst #3,r0  */
+  return __builtin_strcmp (x, "1234567");
+}
+
+int
+test_05 (const char* x, const char* y)
+{
+  /* 1x tst #3,r0  */
+  return __builtin_strcmp ("1234567", y);
+}
+
+int
+test_06 (const char* s1)
+{
+  /* 1x tst #3,r0  */
+  return __builtin_strncmp (s1, "abcdabcd", 8);
+}
+
+int
+test_07 (const char* s1)
+{
+  return __builtin_strncmp (__builtin_assume_aligned (s1, 4), "abcdabcd", 8);
+}