Hi,

This patch fixes a bug of mine whereas more bytes than needed was read
when processing remaining bytes after an aligned  word at at time loop.
This case was not caught neither by the gcc testsuite not the glibc
tests, Regression test included.

no new regressions with the GCC and glibc testsuites., OK for trunk ?

thanks,
Christian




2014-01-23  Christian Bruel  <christian.br...@st.com>

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

2014-01-23  Christian Bruel  <christian.br...@st.com>

	* gcc.target/sh/torture/strncmp.c: New tests.

Index: gcc/config/sh/sh-mem.cc
===================================================================
--- gcc/config/sh/sh-mem.cc	(revision 206918)
+++ gcc/config/sh/sh-mem.cc	(working copy)
@@ -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,34 +402,60 @@ 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)));
+
+          /* fall thru.  */
         }
 
-      emit_label (L_small);
-
-      gcc_assert (bytes <= 7);
-
       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: gcc/testsuite/gcc.target/sh/torture/strncmp.c
===================================================================
--- gcc/testsuite/gcc.target/sh/torture/strncmp.c	(revision 0)
+++ gcc/testsuite/gcc.target/sh/torture/strncmp.c	(working copy)
@@ -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;
+}
+

Reply via email to