Patchwork [SH] fix builtin_strncmp

login
register
mail settings
Submitter Christian Bruel
Date Jan. 24, 2014, 8:55 a.m.
Message ID <52E22A6A.7000000@st.com>
Download mbox | patch
Permalink /patch/313824/
State New
Headers show

Comments

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
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

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;
+}
+