summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2015-09-25 13:09:04 +0000
committerolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2015-09-25 13:09:04 +0000
commitb0d054a98e062cb8541c1dd00bdae82d5ee4dc9e (patch)
tree3c86b2d2f88c9494b6dd64f20b22561056c759e7
parente9fd1d1b34815215aa1398fd7be361dd8d6d5593 (diff)
downloadgcc-b0d054a98e062cb8541c1dd00bdae82d5ee4dc9e.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@228118 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/sh/sh-mem.cc37
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/sh/pr67675.c62
4 files changed, 106 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 97b6cdc4fe7..1fe4e933737 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/sh/sh-mem.cc b/gcc/config/sh/sh-mem.cc
index 5a0fb9780d0..23a7287ef27 100644
--- a/gcc/config/sh/sh-mem.cc
+++ b/gcc/config/sh/sh-mem.cc
@@ -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)));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 07858088f7d..30bd3a264b4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..e6c5d0d9b9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr67675.c
@@ -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);
+}