aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/sh/sh.md78
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49468-di.c23
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49468-si.c1
5 files changed, 114 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c0242a9..eabe45f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2012-03-02 Oleg Endo <olegendo@gcc.gnu.org>
+ PR target/49486
+ * config/sh/sh.md (negdi2): Add TARGET_SH1 condition.
+ (absdi2): New expander.
+ (*absdi2, *negabsdi2, negdi_cond): New insns and splits.
+
+2012-03-02 Oleg Endo <olegendo@gcc.gnu.org>
+
* config/sh/sync.md (atomic_exchange<mode>): New expander.
(atomic_exchange<mode>_soft): New insn.
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index b356584..56a0f3c 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -4411,7 +4411,7 @@ label:
[(set (match_operand:DI 0 "arith_reg_dest" "")
(neg:DI (match_operand:DI 1 "arith_reg_operand" "")))
(clobber (reg:SI T_REG))]
- ""
+ "TARGET_SH1"
"")
(define_insn_and_split "*negdi2"
@@ -4531,6 +4531,82 @@ label:
[(set_attr "type" "arith") ;; poor approximation
(set_attr "length" "4")])
+(define_expand "absdi2"
+ [(set (match_operand:DI 0 "arith_reg_dest" "")
+ (abs:DI (match_operand:DI 1 "arith_reg_operand" "")))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "")
+
+(define_insn_and_split "*absdi2"
+ [(set (match_operand:DI 0 "arith_reg_dest" "=r")
+ (abs:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
+ "TARGET_SH1"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
+ rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
+ emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
+ emit_insn (gen_negdi_cond (operands[0], operands[1], operands[1],
+ const1_rtx));
+ DONE;
+})
+
+(define_insn_and_split "*negabsdi2"
+ [(set (match_operand:DI 0 "arith_reg_dest" "=r")
+ (neg:DI (abs:DI (match_operand:DI 1 "arith_reg_operand" "r"))))]
+ "TARGET_SH1"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
+ rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
+
+ emit_insn (gen_cmpgesi_t (high_src, const0_rtx));
+ emit_insn (gen_negdi_cond (operands[0], operands[1], operands[1],
+ const0_rtx));
+ DONE;
+})
+
+(define_insn_and_split "negdi_cond"
+ [(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
+ (if_then_else:DI (eq:SI (reg:SI T_REG)
+ (match_operand:SI 3 "const_int_operand" "M,N"))
+ (match_operand:DI 1 "arith_reg_operand" "r,r")
+ (neg:DI (match_operand:DI 2 "arith_reg_operand" "1,1"))))]
+ "TARGET_SH1"
+ "#"
+ "TARGET_SH1"
+ [(const_int 0)]
+{
+ int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
+ int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
+
+ rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
+ rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
+
+ rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
+ rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
+
+ rtx skip_neg_label = gen_label_rtx ();
+
+ emit_insn (gen_movsi (low_dst, low_src));
+ emit_insn (gen_movsi (high_dst, high_src));
+
+ emit_jump_insn (INTVAL (operands[3])
+ ? gen_branch_true (skip_neg_label)
+ : gen_branch_false (skip_neg_label));
+
+ if (!INTVAL (operands[3]))
+ emit_insn (gen_clrt ());
+
+ emit_insn (gen_negc (low_dst, low_src));
+ emit_label_after (skip_neg_label, emit_insn (gen_negc (high_dst, high_src)));
+ DONE;
+})
;; -------------------------------------------------------------------------
;; Zero extension instructions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4868f33..9c4fc1a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2012-03-02 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/49486
+ * gcc.target/sh/pr49468-si.c: Skip unsupported test for SH64.
+ * gcc.target/sh/pr49468-di.c: New.
+
2012-03-02 Maxim Kuvyrkov <maxim@codesourcery.com>
* gcc.dg/graphite/pr50561.c: Update.
diff --git a/gcc/testsuite/gcc.target/sh/pr49468-di.c b/gcc/testsuite/gcc.target/sh/pr49468-di.c
new file mode 100644
index 0000000..86fe21d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr49468-di.c
@@ -0,0 +1,23 @@
+/* Check that 64 bit integer abs is generated as negc instruction pairs
+ and conditional branch instead of default branch-free code. */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-final { scan-assembler-times "negc" 4 } } */
+
+
+/* Normal integer absolute value. */
+long long
+abs_0 (long long i)
+{
+ return (i < 0) ? -i : i;
+}
+
+/* Negated integer absolute value.
+ The generated code should be the same, except that the branch
+ condition is inverted. */
+long long
+abs_1 (long long i)
+{
+ return (i > 0) ? -i : i;
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr49468-si.c b/gcc/testsuite/gcc.target/sh/pr49468-si.c
index 69fbe23..e581b2a 100644
--- a/gcc/testsuite/gcc.target/sh/pr49468-si.c
+++ b/gcc/testsuite/gcc.target/sh/pr49468-si.c
@@ -1,5 +1,6 @@
/* Check that 32 bit integer abs is generated as neg instruction and
conditional branch instead of default branch-free code. */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-do compile { target "sh*-*-*" } } */
/* { dg-options "-O1" } */
/* { dg-final { scan-assembler-times "neg" 2 } } */