aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorOleg Endo <oleg.endo@t-online.de>2011-09-28 21:43:01 +0000
committerKaz Kojima <kkojima@gcc.gnu.org>2011-09-28 21:43:01 +0000
commit39f2bcb5e15aa41a156ac55a0466aa3bb82bc327 (patch)
treec47ac32fa9af142e7d2c71a947c4b90e2675ddc7 /gcc
parent8c850a5a7f5effe37a4a4261cab48375f5a13f7a (diff)
downloadgcc-39f2bcb5e15aa41a156ac55a0466aa3bb82bc327.zip
gcc-39f2bcb5e15aa41a156ac55a0466aa3bb82bc327.tar.gz
gcc-39f2bcb5e15aa41a156ac55a0466aa3bb82bc327.tar.bz2
re PR bootstrap/49486 (Bootstrap failure)
PR target/49486 * config/sh/sh.md (negdi2): Move expansion into split to allow more combination options. Add T_REG clobber. (abssi2): New expander. (*negdi2, *abssi2, *negabssi2): New insns. (cneg): Change from insn to insn_and_split. Rename to negsi_cond. Add alternative for non-SH4. * gcc.target/sh/pr49468-si.c: New. From-SVN: r179320
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/sh/sh.md123
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49468-si.c22
4 files changed, 129 insertions, 31 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 98d926a..2aae5aa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2011-09-28 Oleg Endo <oleg.endo@t-online.de>
+
+ PR target/49486
+ * config/sh/sh.md (negdi2): Move expansion into split to
+ allow more combination options. Add T_REG clobber.
+ (abssi2): New expander.
+ (*negdi2, *abssi2, *negabssi2): New insns.
+ (cneg): Change from insn to insn_and_split. Rename to
+ negsi_cond. Add alternative for non-SH4.
+
2011-09-28 Richard Sandiford <richard.sandiford@linaro.org>
* config/arm/neon.md (neon_move_lo_quad_<mode>): Delete.
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index f2c4e55..63cb939 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -4282,28 +4282,39 @@ label:
"sub r63, %1, %0"
[(set_attr "type" "arith_media")])
+
+
+;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
+;; combined.
(define_expand "negdi2"
- [(set (match_operand:DI 0 "arith_reg_operand" "")
- (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
+ [(set (match_operand:DI 0 "arith_reg_dest" "")
+ (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))
+ (clobber (reg:SI T_REG))]
""
+ "")
+
+(define_insn_and_split "*negdi2"
+ [(set (match_operand:DI 0 "arith_reg_dest" "=r")
+ (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
+ "TARGET_SH1"
+ "#"
+ "TARGET_SH1"
+ [(const_int 0)]
"
{
- if (TARGET_SH1)
- {
- int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
- int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 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_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 low_dst = operand_subword (operands[0], low_word, 1, DImode);
+ rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
- emit_insn (gen_clrt ());
- emit_insn (gen_negc (low_dst, low_src));
- emit_insn (gen_negc (high_dst, high_src));
- DONE;
- }
+ emit_insn (gen_clrt ());
+ emit_insn (gen_negc (low_dst, low_src));
+ emit_insn (gen_negc (high_dst, high_src));
+ DONE;
}")
(define_insn "negsi2"
@@ -4326,27 +4337,77 @@ label:
(const_int -1)))]
"TARGET_SHMEDIA" "")
-/* The SH4 202 can do zero-offset branches without pipeline stalls.
- This can be used as some kind of conditional execution, which is useful
- for abs. */
-(define_split
+(define_expand "abssi2"
[(set (match_operand:SI 0 "arith_reg_dest" "")
- (plus:SI (xor:SI (neg:SI (reg:SI T_REG))
- (match_operand:SI 1 "arith_reg_operand" ""))
- (reg:SI T_REG)))]
- "TARGET_HARD_SH4"
+ (abs:SI (match_operand:SI 1 "arith_reg_operand" "")))
+ (clobber (reg:SI T_REG))]
+ ""
+ "")
+
+(define_insn_and_split "*abssi2"
+ [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+ (abs:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
+ "TARGET_SH1"
+ "#"
+ "TARGET_SH1"
[(const_int 0)]
- "emit_insn (gen_movsi_i (operands[0], operands[1]));
- emit_insn (gen_cneg (operands[0], operands[0], operands[0]));
- DONE;")
+ "
+{
+ emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
+ emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
+ const1_rtx));
+ DONE;
+}")
-(define_insn "cneg"
+(define_insn_and_split "*negabssi2"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0))
- (match_operand:SI 1 "arith_reg_operand" "0")
- (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
+ (neg:SI (abs:SI (match_operand:SI 1 "arith_reg_operand" "r"))))]
+ "TARGET_SH1"
+ "#"
+ "TARGET_SH1"
+ [(const_int 0)]
+ "
+{
+ emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
+ emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
+ const0_rtx));
+ DONE;
+}")
+
+
+;; The SH4 202 can do zero-offset branches without pipeline stalls.
+;; This can be used as some kind of conditional execution, which is useful
+;; for abs.
+;; Actually the instruction scheduling should decide whether to use a
+;; zero-offset branch or not for any generic case involving a single
+;; instruction on SH4 202.
+
+(define_insn_and_split "negsi_cond"
+ [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
+ (if_then_else:SI (eq:SI (reg:SI T_REG)
+ (match_operand:SI 3 "const_int_operand" "M,N"))
+ (match_operand:SI 1 "arith_reg_operand" "0,0")
+ (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
"TARGET_HARD_SH4"
- "bf 0f\;neg %2,%0\\n0:"
+ "@
+ bt\\t0f\;neg\\t%2,%0\\n0:
+ bf\\t0f\;neg\\t%2,%0\\n0:"
+ "!TARGET_HARD_SH4"
+ [(const_int 0)]
+ "
+{
+ rtx skip_neg_label = gen_label_rtx ();
+
+ emit_insn (gen_movsi (operands[0], operands[1]));
+
+ emit_jump_insn (INTVAL (operands[3])
+ ? gen_branch_true (skip_neg_label)
+ : gen_branch_false (skip_neg_label));
+
+ emit_label_after (skip_neg_label,
+ emit_insn (gen_negsi2 (operands[0], operands[1])));
+ DONE;
+}"
[(set_attr "type" "arith") ;; poor approximation
(set_attr "length" "4")])
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b760725..d19933a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-09-28 Oleg Endo <oleg.endo@t-online.de>
+
+ PR target/49486
+ * gcc.target/sh/pr49468-si.c: New.
+
2011-09-28 Tom de Vries <tom@codesourcery.com>
PR testsuite/50485
diff --git a/gcc/testsuite/gcc.target/sh/pr49468-si.c b/gcc/testsuite/gcc.target/sh/pr49468-si.c
new file mode 100644
index 0000000..69fbe23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr49468-si.c
@@ -0,0 +1,22 @@
+/* Check that 32 bit integer abs is generated as neg instruction and
+ conditional branch instead of default branch-free code. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-final { scan-assembler-times "neg" 2 } } */
+
+
+/* Normal integer absolute value. */
+int
+abs_0 (int i)
+{
+ return (i < 0) ? -i : i;
+}
+
+/* Negated integer absolute value.
+ The generated code should be the same, except that the branch
+ condition is inverted. */
+int
+abs_1 (int i)
+{
+ return (i > 0) ? -i : i;
+}