summaryrefslogtreecommitdiffstats
path: root/gcc
diff options
context:
space:
mode:
authorolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-07-02 19:23:56 +0000
committerolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-07-02 19:23:56 +0000
commita6be78214b09079e38f8950d7a5b06039d017cd4 (patch)
tree38e129004dd353049b54d9731e1f700766fd9cde /gcc
parentb1039d0226ef24ed25257d064ff4c181ce7c4d4c (diff)
downloadppe42-gcc-a6be78214b09079e38f8950d7a5b06039d017cd4.tar.gz
ppe42-gcc-a6be78214b09079e38f8950d7a5b06039d017cd4.zip
PR target/51244
* config/sh/predicates.md (t_reg_operand, negt_reg_operand): New predicates. * config/sh/sh-protos.h (get_t_reg_rtx): New prototype. * config/sh/sh.c (get_t_reg_rtx): New function. Use it when invoking gen_branch_true and gen_branch_false. * config/sh/sh.md: Use get_t_reg_rtx when invoking gen_branch_true and gen_branch_false. (branch_true, branch_false): Use t_reg_operand predicate. (*branch_true, *branch_false): Delete. (movt): Use t_reg_operand predicate. (*negnegt): Use negt_reg_operand predicate and fold little and big endian variants. (*movtt): Use t_reg_operand and fold little and big endian variants. (*movt_qi): Delete. PR target/51244 * gcc.target/sh/pr51244-1.c: Check that movt insn is not generated. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@189177 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/config/sh/predicates.md39
-rw-r--r--gcc/config/sh/sh-protos.h1
-rw-r--r--gcc/config/sh/sh.c27
-rw-r--r--gcc/config/sh/sh.md113
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-1.c2
7 files changed, 98 insertions, 107 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bee63bb8f13..231e624be89 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2012-07-02 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/51244
+ * config/sh/predicates.md (t_reg_operand, negt_reg_operand): New
+ predicates.
+ * config/sh/sh-protos.h (get_t_reg_rtx): New prototype.
+ * config/sh/sh.c (get_t_reg_rtx): New function. Use it when invoking
+ gen_branch_true and gen_branch_false.
+ * config/sh/sh.md: Use get_t_reg_rtx when invoking gen_branch_true and
+ gen_branch_false.
+ (branch_true, branch_false): Use t_reg_operand predicate.
+ (*branch_true, *branch_false): Delete.
+ (movt): Use t_reg_operand predicate.
+ (*negnegt): Use negt_reg_operand predicate and fold little and big
+ endian variants.
+ (*movtt): Use t_reg_operand and fold little and big endian variants.
+ (*movt_qi): Delete.
+
2012-07-02 Steven Bosscher <steven@gcc.gnu.org>
* stmt.c (emit_case_bit_tests): Remove.
diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md
index f75675ec096..d58f657c857 100644
--- a/gcc/config/sh/predicates.md
+++ b/gcc/config/sh/predicates.md
@@ -898,3 +898,42 @@
(match_test "mode != HImode")
(match_test "TARGET_SH4A_ARCH"))))
+;; A predicate describing the T bit register in any form.
+(define_predicate "t_reg_operand"
+ (match_code "reg,subreg,sign_extend,zero_extend")
+{
+ switch (GET_CODE (op))
+ {
+ case REG:
+ return REGNO (op) == T_REG;
+
+ case SUBREG:
+ return REGNO (SUBREG_REG (op)) == T_REG;
+
+ case ZERO_EXTEND:
+ case SIGN_EXTEND:
+ return GET_CODE (XEXP (op, 0)) == SUBREG
+ && REGNO (SUBREG_REG (XEXP (op, 0))) == T_REG;
+
+ default:
+ return 0;
+ }
+})
+
+;; A predicate describing a negated T bit register.
+(define_predicate "negt_reg_operand"
+ (match_code "subreg,xor")
+{
+ switch (GET_CODE (op))
+ {
+ case XOR:
+ return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))
+ && satisfies_constraint_M (XEXP (op, 1));
+
+ case SUBREG:
+ return negt_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)));
+
+ default:
+ return 0;
+ }
+})
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index cb9ad0f203f..3fcfe29a28a 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -109,6 +109,7 @@ extern bool sh_vector_mode_supported_p (enum machine_mode);
#endif /* RTX_CODE */
extern const char *output_jump_label_table (void);
+extern rtx get_t_reg_rtx (void);
extern rtx get_fpscr_rtx (void);
extern int sh_media_register_for_return (void);
extern void sh_expand_prologue (void);
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 7e0c2c17515..77324b66c94 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -1874,7 +1874,7 @@ prepare_cbranch_operands (rtx *operands, enum machine_mode mode,
void
expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability)
{
- rtx (*branch_expander) (rtx) = gen_branch_true;
+ rtx (*branch_expander) (rtx, rtx) = gen_branch_true;
rtx jump;
comparison = prepare_cbranch_operands (operands, SImode, comparison);
@@ -1888,7 +1888,7 @@ expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability)
emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, T_REG),
gen_rtx_fmt_ee (comparison, SImode,
operands[1], operands[2])));
- jump = emit_jump_insn (branch_expander (operands[3]));
+ jump = emit_jump_insn (branch_expander (operands[3], get_t_reg_rtx ()));
if (probability >= 0)
add_reg_note (jump, REG_BR_PROB, GEN_INT (probability));
@@ -1941,7 +1941,7 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
if (TARGET_CMPEQDI_T)
{
emit_insn (gen_cmpeqdi_t (operands[1], operands[2]));
- emit_jump_insn (gen_branch_true (operands[3]));
+ emit_jump_insn (gen_branch_true (operands[3], get_t_reg_rtx ()));
return true;
}
msw_skip = NE;
@@ -1969,7 +1969,7 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
if (TARGET_CMPEQDI_T)
{
emit_insn (gen_cmpeqdi_t (operands[1], operands[2]));
- emit_jump_insn (gen_branch_false (operands[3]));
+ emit_jump_insn (gen_branch_false (operands[3], get_t_reg_rtx ()));
return true;
}
msw_taken = NE;
@@ -2304,9 +2304,9 @@ sh_emit_compare_and_branch (rtx *operands, enum machine_mode mode)
sh_emit_set_t_insn (gen_ieee_ccmpeqsf_t (op0, op1), mode);
if (branch_code == code)
- emit_jump_insn (gen_branch_true (operands[3]));
+ emit_jump_insn (gen_branch_true (operands[3], get_t_reg_rtx ()));
else
- emit_jump_insn (gen_branch_false (operands[3]));
+ emit_jump_insn (gen_branch_false (operands[3], get_t_reg_rtx ()));
}
void
@@ -2340,7 +2340,7 @@ sh_emit_compare_and_set (rtx *operands, enum machine_mode mode)
{
lab = gen_label_rtx ();
sh_emit_scc_to_t (EQ, op0, op1);
- emit_jump_insn (gen_branch_true (lab));
+ emit_jump_insn (gen_branch_true (lab, get_t_reg_rtx ()));
code = GT;
}
else
@@ -3360,7 +3360,7 @@ gen_shifty_op (int code, rtx *operands)
if (code == LSHIFTRT)
{
emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
- emit_insn (gen_movt (operands[0]));
+ emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
return;
}
else if (code == ASHIFT)
@@ -9504,6 +9504,15 @@ reg_unused_after (rtx reg, rtx insn)
#include "ggc.h"
+static GTY(()) rtx t_reg_rtx;
+rtx
+get_t_reg_rtx (void)
+{
+ if (! t_reg_rtx)
+ t_reg_rtx = gen_rtx_REG (SImode, T_REG);
+ return t_reg_rtx;
+}
+
static GTY(()) rtx fpscr_rtx;
rtx
get_fpscr_rtx (void)
@@ -12049,7 +12058,7 @@ sh_expand_t_scc (rtx operands[])
result = gen_reg_rtx (SImode);
val = INTVAL (op1);
if ((code == EQ && val == 1) || (code == NE && val == 0))
- emit_insn (gen_movt (result));
+ emit_insn (gen_movt (result, get_t_reg_rtx ()));
else if ((code == EQ && val == 0) || (code == NE && val == 1))
emit_insn (gen_movnegt (result));
else if (code == EQ || code == NE)
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 852f9fd36ea..4e2425f4888 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -4450,8 +4450,8 @@ label:
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));
+ ? gen_branch_true (skip_neg_label, get_t_reg_rtx ())
+ : gen_branch_false (skip_neg_label, get_t_reg_rtx ()));
emit_label_after (skip_neg_label,
emit_insn (gen_negsi2 (operands[0], operands[1])));
@@ -4519,8 +4519,8 @@ label:
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));
+ ? gen_branch_true (skip_neg_label, get_t_reg_rtx ())
+ : gen_branch_false (skip_neg_label, get_t_reg_rtx ()));
if (!INTVAL (operands[3]))
emit_insn (gen_clrt ());
@@ -7195,66 +7195,22 @@ label:
;; ------------------------------------------------------------------------
(define_insn "branch_true"
- [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_SH1"
-{
- return output_branch (1, insn, operands);
-}
- [(set_attr "type" "cbranch")])
-
-;; The *branch_true patterns help combine when trying to invert conditions.
-(define_insn "*branch_true"
- [(set (pc) (if_then_else (ne (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
+ [(set (pc) (if_then_else (ne (match_operand 1 "t_reg_operand" "")
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_SH1 && TARGET_LITTLE_ENDIAN"
-{
- return output_branch (1, insn, operands);
-}
- [(set_attr "type" "cbranch")])
-
-(define_insn "*branch_true"
- [(set (pc) (if_then_else (ne (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
+ "TARGET_SH1"
{
return output_branch (1, insn, operands);
}
[(set_attr "type" "cbranch")])
(define_insn "branch_false"
- [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_SH1"
-{
- return output_branch (0, insn, operands);
-}
- [(set_attr "type" "cbranch")])
-
-;; The *branch_false patterns help combine when trying to invert conditions.
-(define_insn "*branch_false"
- [(set (pc) (if_then_else (eq (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_SH1 && TARGET_LITTLE_ENDIAN"
-{
- return output_branch (0, insn, operands);
-}
- [(set_attr "type" "cbranch")])
-
-(define_insn "*branch_false"
- [(set (pc) (if_then_else (eq (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
+ [(set (pc) (if_then_else (eq (match_operand 1 "t_reg_operand" "")
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
+ "TARGET_SH1"
{
return output_branch (0, insn, operands);
}
@@ -9672,7 +9628,7 @@ label:
(define_insn "movt"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (eq:SI (reg:SI T_REG) (const_int 1)))]
+ (match_operand:SI 1 "t_reg_operand"))]
"TARGET_SH1"
"movt %0"
[(set_attr "type" "arith")])
@@ -9854,62 +9810,25 @@ label:
"negc %1,%0"
[(set_attr "type" "arith")])
-;; The *negnegt patterns help the combine pass to figure out how to fold
+;; The *negnegt pattern helps the combine pass to figure out how to fold
;; an explicit double T bit negation.
(define_insn_and_split "*negnegt"
[(set (reg:SI T_REG)
- (eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 3)
- (const_int 0)))]
- "! TARGET_LITTLE_ENDIAN"
- "#"
- ""
- [(const_int 0)])
-
-(define_insn_and_split "*negnegt"
- [(set (reg:SI T_REG)
- (eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 0)
- (const_int 0)))]
- "TARGET_LITTLE_ENDIAN"
- "#"
- ""
- [(const_int 0)])
-
-;; The *movtt patterns eliminate redundant T bit to T bit moves / tests.
-(define_insn_and_split "*movtt"
- [(set (reg:SI T_REG)
- (eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
- (const_int 1)))]
- "! TARGET_LITTLE_ENDIAN"
+ (eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
+ "TARGET_SH1"
"#"
""
[(const_int 0)])
+;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
(define_insn_and_split "*movtt"
[(set (reg:SI T_REG)
- (eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
- (const_int 1)))]
- "TARGET_LITTLE_ENDIAN"
+ (eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
+ "TARGET_SH1"
"#"
""
[(const_int 0)])
-;; The *movt_qi patterns help the combine pass convert a movrt_negc pattern
-;; into a movt Rn, xor #1 Rn pattern. This can happen when e.g. a function
-;; returns the inverted T bit value.
-(define_insn "*movt_qi"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (zero_extend:SI (subreg:QI (reg:SI T_REG) 3)))]
- "! TARGET_LITTLE_ENDIAN"
- "movt %0"
- [(set_attr "type" "arith")])
-
-(define_insn "*movt_qi"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (zero_extend:SI (subreg:QI (reg:SI T_REG) 0)))]
- "TARGET_LITTLE_ENDIAN"
- "movt %0"
- [(set_attr "type" "arith")])
-
(define_expand "cstoresf4"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "sh_float_comparison_operator"
@@ -13960,7 +13879,7 @@ label:
else
{
emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
- emit_jump_insn (gen_branch_true (operands[2]));
+ emit_jump_insn (gen_branch_true (operands[2], get_t_reg_rtx ()));
}
DONE;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b62e76f0b4f..916fcfbb606 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-02 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/51244
+ * gcc.target/sh/pr51244-1.c: Check that movt insn is not generated.
+
2012-07-02 Jason Merrill <jason@redhat.com>
PR c++/53821
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-1.c b/gcc/testsuite/gcc.target/sh/pr51244-1.c
index 34e1b023326..601c1c1c269 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-1.c
@@ -4,7 +4,7 @@
/* { dg-do compile { target "sh*-*-*" } } */
/* { dg-options "-O1 -mbranch-cost=2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
-/* { dg-final { scan-assembler-not "tst|negc|extu" } } */
+/* { dg-final { scan-assembler-not "movt|tst|negc|extu" } } */
int
testfunc_00 (int a, int b, int c, int d)
OpenPOWER on IntegriCloud