sh-mem.cc (sh_expand_cmpnstr): Fix remaining bytes after words comparisons.
authorChristian Bruel <chrbr@gcc.gnu.org>
Mon, 27 Jan 2014 08:39:49 +0000 (09:39 +0100)
committerChristian Bruel <chrbr@gcc.gnu.org>
Mon, 27 Jan 2014 08:39:49 +0000 (09:39 +0100)
2014-01-27  Christian Bruel  <christian.bruel@st.com>

* config/sh/sh-mem.cc (sh_expand_cmpnstr): Fix remaining bytes after
words comparisons.

From-SVN: r207126

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

index 226b721b4cea76fc4e4eaf081f10ec13771dfb48..7e50d078516afa44b50e7b886854f8a75fc99a2a 100644 (file)
@@ -1,3 +1,8 @@
+2014-01-27  Christian Bruel  <christian.bruel@st.com>
+
+       * config/sh/sh-mem.cc (sh_expand_cmpnstr): Fix remaining bytes after
+       words comparisons.
+
 2014-01-26  John David Anglin  <danglin@gcc.gnu.org>
 
        * config/pa/pa.md (call): Generate indirect long calls to non-local
@@ -17,9 +22,9 @@
 
 2014-01-25  Walter Lee  <walt@tilera.com>
 
-       * config/tilegx/tilegx-c.c (tilegx_cpu_cpp_builtins): 
+       * config/tilegx/tilegx-c.c (tilegx_cpu_cpp_builtins):
        Define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_{1,2}.
-       * config/tilegx/tilepro-c.c (tilepro_cpu_cpp_builtins): 
+       * config/tilegx/tilepro-c.c (tilepro_cpu_cpp_builtins):
        Define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_{1,2,4,8}.
 
 2014-01-25  Walter Lee  <walt@tilera.com>
@@ -46,7 +51,7 @@
        * config/tilepro/tilepro.c (tilepro_expand_builtin): Ditto.
 
 2014-01-25  Richard Sandiford  <rdsandiford@googlemail.com>
-       
+
        * config/mips/constraints.md (kl): Delete.
        * config/mips/mips.md (divmod<mode>4, udivmod<mode>4): Turn into
        define expands, using...
index e29ff775449bf74e871dab255ba72abb4b4f61fc..45af23acb48d124c1fad261ca6d09df40c3edead 100644 (file)
@@ -344,7 +344,6 @@ sh_expand_cmpnstr (rtx *operands)
 
       rtx L_loop_long = gen_label_rtx ();
       rtx L_end_loop_long = gen_label_rtx ();
-      rtx L_small = gen_label_rtx ();
 
       int align = INTVAL (operands[4]);
       int bytes = INTVAL (operands[3]);
@@ -403,33 +402,59 @@ sh_expand_cmpnstr (rtx *operands)
           jump = emit_jump_insn (gen_branch_false (L_loop_long));
           add_int_reg_note (jump, REG_BR_PROB, prob_likely);
 
+         int sbytes = bytes % 4;
+
           /* end loop.  Reached max iterations.  */
-          if (bytes % 4 == 0)
+          if (! sbytes)
             {
-              /* Done.  */
               jump = emit_jump_insn (gen_jump_compact (L_return));
               emit_barrier_after (jump);
             }
           else
             {
-              /* Remaining bytes to read.   */
-              jump = emit_jump_insn (gen_jump_compact (L_small));
+              /* Remaining bytes to check.  */
+
+              addr1 = adjust_automodify_address (addr1, QImode, s1_addr, 0);
+              addr2 = adjust_automodify_address (addr2, QImode, s2_addr, 0);
+
+              while (sbytes--)
+                {
+                  emit_insn (gen_extendqisi2 (tmp1, addr1));
+                  emit_insn (gen_extendqisi2 (tmp2, addr2));
+
+                  emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx));
+                  jump = emit_jump_insn (gen_branch_true (L_end_loop_byte));
+                  add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+                  emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
+                  if (flag_delayed_branch)
+                    emit_insn (gen_zero_extendqisi2 (tmp2,
+                                                     gen_lowpart (QImode,
+                                                                  tmp2)));
+                  jump = emit_jump_insn (gen_branch_false (L_end_loop_byte));
+                  add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+                  addr1 = adjust_address (addr1, QImode,
+                                          GET_MODE_SIZE (QImode));
+                  addr2 = adjust_address (addr2, QImode,
+                                          GET_MODE_SIZE (QImode));
+                }
+
+              jump = emit_jump_insn (gen_jump_compact( L_end_loop_byte));
               emit_barrier_after (jump);
             }
 
           emit_label (L_end_loop_long);
 
           /* Found last word.  Restart it byte per byte. */
-          bytes =  4;
+
           emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr,
                                                   -GET_MODE_SIZE (SImode)));
           emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr,
                                                   -GET_MODE_SIZE (SImode)));
-        }
 
-      emit_label (L_small);
-
-      gcc_assert (bytes <= 7);
+          /* fall thru.  */
+        }
 
       addr1 = adjust_automodify_address (addr1, QImode, s1_addr, 0);
       addr2 = adjust_automodify_address (addr2, QImode, s2_addr, 0);
@@ -445,7 +470,8 @@ sh_expand_cmpnstr (rtx *operands)
 
           emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
           if (flag_delayed_branch)
-            emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2)));
+            emit_insn (gen_zero_extendqisi2 (tmp2,
+                                             gen_lowpart (QImode, tmp2)));
           jump = emit_jump_insn (gen_branch_false (L_end_loop_byte));
           add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
 
index 957921914e9439a247ae2f01f080dccd812cbd64..fa61d5c9874a0cfd1625171d9deea9bf6f3e9511 100644 (file)
@@ -1,3 +1,7 @@
+2014-01-27  Christian Bruel  <christian.bruel@st.com>
+
+       * gcc.target/sh/torture/strncmp.c: New tests.
+
 2014-01-25  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * gcc.dg/unroll_1.c: Add -fenable-rtl-loop2.
diff --git a/gcc/testsuite/gcc.target/sh/torture/strncmp.c b/gcc/testsuite/gcc.target/sh/torture/strncmp.c
new file mode 100644 (file)
index 0000000..cd50f5c
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+const char *s="astc";
+const char *s1="-----BEGIN RSA PRIVATE KEY-----";
+const char *s2="atextaac";
+
+main()
+{
+  if (! __builtin_strncmp ("astb", s, 4))
+    abort();
+
+  if (__builtin_strncmp(s1, "-----BEGIN ", 11))
+    abort();
+
+  if (! __builtin_strncmp ("atextaacb", s2, 9))
+    abort();
+
+  return 0;
+}
+