diff options
author | olegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-09-25 13:09:04 +0000 |
---|---|---|
committer | olegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-09-25 13:09:04 +0000 |
commit | b0d054a98e062cb8541c1dd00bdae82d5ee4dc9e (patch) | |
tree | 3c86b2d2f88c9494b6dd64f20b22561056c759e7 | |
parent | e9fd1d1b34815215aa1398fd7be361dd8d6d5593 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/sh/sh-mem.cc | 37 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr67675.c | 62 |
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); +} |