aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleg Endo <olegendo@gcc.gnu.org>2014-05-21 08:06:06 +0000
committerOleg Endo <olegendo@gcc.gnu.org>2014-05-21 08:06:06 +0000
commitc4e5de1b1af1b33acbbe5a2271ff37405d1d17b5 (patch)
treedd5b8b640423eb178d547c1a5e4da925bd8c59a6
parentdecaaec8116ffefcc2a260185c133333834eb083 (diff)
downloadgcc-c4e5de1b1af1b33acbbe5a2271ff37405d1d17b5.zip
gcc-c4e5de1b1af1b33acbbe5a2271ff37405d1d17b5.tar.gz
gcc-c4e5de1b1af1b33acbbe5a2271ff37405d1d17b5.tar.bz2
re PR target/54236 ([SH] Improve addc and subc insn utilization)
gcc/ PR target/54236 * config/sh/sh.md (*addc_r_1): Rename to addc_t_r. Remove empty constraints. (*addc_r_t): Add new insn_and_split. gcc/testsuite/ PR target/54236 * gcc.target/sh/pr54236-3.c: New. From-SVN: r210682
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/sh/sh.md23
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54236-3.c31
4 files changed, 62 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f167e76..e2e3dd3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2014-05-21 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54236
+ * config/sh/sh.md (*addc_r_1): Rename to addc_t_r. Remove empty
+ constraints.
+ (*addc_r_t): Add new insn_and_split.
+
2014-05-21 Jakub Jelinek <jakub@redhat.com>
PR middle-end/61252
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 0250f92..d998af9 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -1830,6 +1830,8 @@
;; We allow a reg or 0 for one of the operands in order to be able to
;; do 'reg + T' sequences. Reload will load the constant 0 into the reg
;; as needed.
+;; FIXME: The load of constant 0 should be split out before reload, or else
+;; it will be difficult to hoist or combine the constant load.
(define_insn "*addc"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
@@ -1898,10 +1900,10 @@
;; can be scheduled much better since the load of the constant can be
;; done earlier, before any comparison insns that store the result in
;; the T bit.
-(define_insn_and_split "*addc_r_1"
- [(set (match_operand:SI 0 "arith_reg_dest" "")
- (plus:SI (match_operand:SI 1 "t_reg_operand" "")
- (match_operand:SI 2 "arith_reg_operand" "")))
+(define_insn_and_split "*addc_t_r"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (match_operand:SI 1 "t_reg_operand")
+ (match_operand:SI 2 "arith_reg_operand")))
(clobber (reg:SI T_REG))]
"TARGET_SH1"
"#"
@@ -1911,6 +1913,19 @@
(match_dup 1)))
(clobber (reg:SI T_REG))])])
+(define_insn_and_split "*addc_r_t"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (match_operand:SI 1 "arith_reg_operand")
+ (match_operand:SI 2 "t_reg_operand")))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "#"
+ "&& 1"
+ [(parallel [(set (match_dup 0)
+ (plus:SI (plus:SI (match_dup 1) (const_int 0))
+ (match_dup 2)))
+ (clobber (reg:SI T_REG))])])
+
;; Use shlr-addc to do 'reg + (reg & 1)'.
(define_insn_and_split "*addc_r_lsb"
[(set (match_operand:SI 0 "arith_reg_dest")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a5d155c..802f654 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-05-21 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54236
+ * gcc.target/sh/pr54236-3.c: New.
+
2014-05-21 Igor Zamyatin <igor.zamyatin@intel.com>
PR c++/60189
diff --git a/gcc/testsuite/gcc.target/sh/pr54236-3.c b/gcc/testsuite/gcc.target/sh/pr54236-3.c
new file mode 100644
index 0000000..fc0d111
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr54236-3.c
@@ -0,0 +1,31 @@
+/* Tests to check the utilization of the addc and subc instructions.
+ If everything works as expected we won't see any movt instructions in
+ these cases. */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+/* { dg-final { scan-assembler-times "addc" 1 } } */
+/* { dg-final { scan-assembler-times "subc" 1 } } */
+/* { dg-final { scan-assembler-not "movt" } } */
+
+int
+test_000 (int* x, unsigned int c)
+{
+ /* 1x addc */
+ int s = 0;
+ unsigned int i;
+ for (i = 0; i < c; ++i)
+ s += ! (x[i] & 0x3000);
+ return s;
+}
+
+int
+test_001 (int* x, unsigned int c)
+{
+ /* 1x subc */
+ int s = 0;
+ unsigned int i;
+ for (i = 0; i < c; ++i)
+ s -= ! (x[i] & 0x3000);
+ return s;
+}