[SH] fix builtin_strncmp

Submitted by Christian Bruel on Jan. 24, 2014, 8:55 a.m.

Details

Message ID 52E22A6A.7000000@st.com
State New
Headers show

Commit Message

Christian Bruel Jan. 24, 2014, 8:55 a.m.
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

Comments

Kaz Kojima Jan. 24, 2014, 10:35 a.m.
Christian Bruel <christian.bruel@st.com> wrote:
> 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 ?

OK.

Regards,
	kaz

Patch hide | download patch | download mbox

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

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

2014-01-23  Christian Bruel  <christian.bruel@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;
+}
+