aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorOleg Endo <olegendo@gcc.gnu.org>2015-05-19 08:00:41 +0000
committerOleg Endo <olegendo@gcc.gnu.org>2015-05-19 08:00:41 +0000
commitd0ae0f51fa0dfc1f8dfbc9ea4e51e3389460568c (patch)
tree1fb5e48aebad887c32ed866714017cbe3bdd6479 /gcc
parent07a737f333f0d4352984664c1ab6d344f6e2c88c (diff)
downloadgcc-d0ae0f51fa0dfc1f8dfbc9ea4e51e3389460568c.zip
gcc-d0ae0f51fa0dfc1f8dfbc9ea4e51e3389460568c.tar.gz
gcc-d0ae0f51fa0dfc1f8dfbc9ea4e51e3389460568c.tar.bz2
re PR target/54236 ([SH] Improve addc and subc insn utilization)
gcc/ PR target/54236 * config/sh/sh.md (*round_int_even): New insn_and_split and accompanying new unnamed split. gcc/testsuite/ PR target/54236 * gcc.target/sh/pr54236-2.c: Adjust expected insn counts. From-SVN: r223346
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/sh/sh.md38
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54236-2.c16
4 files changed, 61 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c87f645..dd8f5c7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2015-05-19 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54236
+ * config/sh/sh.md (*round_int_even): New insn_and_split and
+ accompanying new unnamed split.
+
2015-05-19 Richard Sandiford <richard.sandiford@arm.com>
* bitmap.c (bitmap_set_range): Handle count==1 specially.
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index eb6983a..3b66992 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -1998,6 +1998,44 @@
[(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))])
+
+;; The tree optimiziers canonicalize
+;; reg + (reg & 1)
+;; into
+;; (reg + 1) & -2
+;;
+;; On SH2A an add-bclr sequence will be used to handle this.
+;; On non-SH2A re-emit the add-and sequence to improve register utilization.
+(define_insn_and_split "*round_int_even"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (and:SI (plus:SI (match_operand:SI 1 "arith_reg_operand")
+ (const_int 1))
+ (const_int -2)))]
+ "TARGET_SH1 && !TARGET_SH2A && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (match_dup 0) (const_int -2))
+ (set (match_dup 2) (plus:SI (match_dup 1) (const_int 1)))
+ (set (match_dup 0) (and:SI (match_dup 0) (match_dup 2)))]
+{
+ operands[2] = gen_reg_rtx (SImode);
+})
+
+;; If the *round_int_even pattern is combined with another plus,
+;; convert it into an addc pattern to emit an shlr-addc sequence.
+;; This split is taken by combine on non-SH2A and SH2A.
+(define_split
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (and:SI (plus:SI (match_operand:SI 1 "arith_reg_operand")
+ (const_int 1))
+ (const_int -2))
+ (match_operand:SI 2 "arith_reg_operand")))]
+ "TARGET_SH1 && can_create_pseudo_p ()"
+ [(parallel [(set (match_dup 0)
+ (plus:SI (plus:SI (match_dup 1) (match_dup 2))
+ (and:SI (match_dup 1) (const_int 1))))
+ (clobber (reg:SI T_REG))])])
+
;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn.
;; If the 0 constant can be CSE-ed, this becomes a one instruction
;; operation, as opposed to sequences such as
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7987859..2853371 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2015-05-19 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54236
+ * gcc.target/sh/pr54236-2.c: Adjust expected insn counts.
+
2015-05-19 Sameera Deshpande <sameera.deshpande@imgtec.com>
* gcc.target/mips/p5600-bonding.c : New file.
diff --git a/gcc/testsuite/gcc.target/sh/pr54236-2.c b/gcc/testsuite/gcc.target/sh/pr54236-2.c
index b3cf48c..b94c2c0 100644
--- a/gcc/testsuite/gcc.target/sh/pr54236-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr54236-2.c
@@ -4,12 +4,19 @@
/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
-/* { dg-final { scan-assembler-times "addc" 37 } } */
-/* { dg-final { scan-assembler-times "shlr" 23 } } */
+/* { dg-final { scan-assembler-times "addc" 36 } } */
+/* { dg-final { scan-assembler-times "shlr" 22 } } */
/* { dg-final { scan-assembler-times "shll" 14 } } */
-/* { dg-final { scan-assembler-times "add\t" 12 } } */
+/* { dg-final { scan-assembler-times "add\tr" 12 } } */
/* { dg-final { scan-assembler-not "movt" } } */
+/* { dg-final { scan-assembler-times "add\t#1" 1 } } */
+
+/* { dg-final { scan-assembler-times "mov\t#-2" 1 { target { ! sh2a } } } } */
+/* { dg-final { scan-assembler-times "and\tr" 1 { target { ! sh2a } } } } */
+
+/* { dg-final { scan-assembler-times "bclr\t#0" 1 { target { sh2a } } } } */
+
int
test_000 (int a, int c, int b, int d)
{
@@ -125,7 +132,8 @@ test_015 (int a, int c, int b, int d)
int
test_016 (int a, int b, int c, int d)
{
- // 1x shlr, 1x addc
+ // non-SH2A: 1x add #1, 1x mov #-2, 1x and
+ // SH2A: 1x add #1, 1x blcr #0
return a + (a & 1);
}