summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-09 15:55:18 +0000
committerolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-09 15:55:18 +0000
commit3ba0d068b9e29dbf6f2ca395980a831457217873 (patch)
tree30cb676505d2f7b7820589b606a4a69283685567 /gcc
parent5e8ad22e2a650a94c58548f9ade72b24e1edd274 (diff)
downloadgcc-3ba0d068b9e29dbf6f2ca395980a831457217873.tar.gz
PR target/51244
* config/sh/sh.md: Add negc extu sequence peephole. (movrt, movnegt, movrt_negc, nott): Use t_reg_operand predicate. (*movrt_negc): New insn. * config/sh/sync.md (atomic_test_and_set): Pass gen_t_reg_rtx to gen_movnegt. * config/sh/sh.c (expand_cbranchsi4, sh_emit_scc_to_t, sh_emit_compare_and_branch, sh_emit_compare_and_set): Use get_t_reg_rtx. (sh_expand_t_scc): Pass gen_t_reg_rtx to gen_movnegt. PR target/51244 * gcc.target/sh/pr51244-5: New. * gcc.target/sh/pr51244-6: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@190258 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/sh/sh.c12
-rw-r--r--gcc/config/sh/sh.md57
-rw-r--r--gcc/config/sh/sync.md2
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-5.c50
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-6.c15
7 files changed, 138 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d6631a91108..318278a811a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,17 @@
2012-08-09 Oleg Endo <olegendo@gcc.gnu.org>
+ PR target/51244
+ * config/sh/sh.md: Add negc extu sequence peephole.
+ (movrt, movnegt, movrt_negc, nott): Use t_reg_operand predicate.
+ (*movrt_negc): New insn.
+ * config/sh/sync.md (atomic_test_and_set): Pass gen_t_reg_rtx to
+ gen_movnegt.
+ * config/sh/sh.c (expand_cbranchsi4, sh_emit_scc_to_t,
+ sh_emit_compare_and_branch, sh_emit_compare_and_set): Use get_t_reg_rtx.
+ (sh_expand_t_scc): Pass gen_t_reg_rtx to gen_movnegt.
+
+2012-08-09 Oleg Endo <olegendo@gcc.gnu.org>
+
PR target/50751
* config/sh/sh.md (*extendqisi2_compact_reg, *extendhisi2_compact_reg):
Use arith_reg_operand predicate instead of register_operand.
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 88497c78eaa..afd6d3dae97 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -1893,7 +1893,7 @@ expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability)
branch_expander = gen_branch_false;
default: ;
}
- emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, T_REG),
+ emit_insn (gen_rtx_SET (VOIDmode, get_t_reg_rtx (),
gen_rtx_fmt_ee (comparison, SImode,
operands[1], operands[2])));
jump = emit_jump_insn (branch_expander (operands[3], get_t_reg_rtx ()));
@@ -2129,7 +2129,7 @@ sh_emit_set_t_insn (rtx insn, enum machine_mode mode)
void
sh_emit_scc_to_t (enum rtx_code code, rtx op0, rtx op1)
{
- rtx t_reg = gen_rtx_REG (SImode, T_REG);
+ rtx t_reg = get_t_reg_rtx ();
enum rtx_code oldcode = code;
enum machine_mode mode;
@@ -2304,7 +2304,7 @@ sh_emit_compare_and_branch (rtx *operands, enum machine_mode mode)
}
insn = gen_rtx_SET (VOIDmode,
- gen_rtx_REG (SImode, T_REG),
+ get_t_reg_rtx (),
gen_rtx_fmt_ee (branch_code, SImode, op0, op1));
sh_emit_set_t_insn (insn, mode);
@@ -2369,9 +2369,9 @@ sh_emit_compare_and_set (rtx *operands, enum machine_mode mode)
if (lab)
emit_label (lab);
if (invert)
- emit_insn (gen_movnegt (operands[0]));
+ emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
else
- emit_move_insn (operands[0], gen_rtx_REG (SImode, T_REG));
+ emit_move_insn (operands[0], get_t_reg_rtx ());
}
/* Functions to output assembly code. */
@@ -12121,7 +12121,7 @@ sh_expand_t_scc (rtx operands[])
if ((code == EQ && val == 1) || (code == NE && val == 0))
emit_insn (gen_movt (result, get_t_reg_rtx ()));
else if ((code == EQ && val == 0) || (code == NE && val == 1))
- emit_insn (gen_movnegt (result));
+ emit_insn (gen_movnegt (result, get_t_reg_rtx ()));
else if (code == EQ || code == NE)
emit_insn (gen_move_insn (result, GEN_INT (code == NE)));
else
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 0d6f161acb9..c95c904844c 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -9641,7 +9641,7 @@ label:
(define_insn "movrt"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (xor:SI (reg:SI T_REG) (const_int 1)))]
+ (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
"TARGET_SH2A"
"movrt %0"
[(set_attr "type" "arith")])
@@ -9794,28 +9794,66 @@ label:
(define_expand "movnegt"
[(set (match_operand:SI 0 "arith_reg_dest" "")
- (xor:SI (reg:SI T_REG) (const_int 1)))]
- ""
+ (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))]
+ "TARGET_SH1"
{
if (TARGET_SH2A)
- emit_insn (gen_movrt (operands[0]));
+ emit_insn (gen_movrt (operands[0], operands[1]));
else
{
rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
- emit_insn (gen_movrt_negc (operands[0], val));
+ emit_insn (gen_movrt_negc (operands[0], operands[1], val));
}
DONE;
})
(define_insn "movrt_negc"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (xor:SI (reg:SI T_REG) (const_int 1)))
+ (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
(set (reg:SI T_REG) (const_int 1))
- (use (match_operand:SI 1 "arith_reg_operand" "r"))]
+ (use (match_operand:SI 2 "arith_reg_operand" "r"))]
"TARGET_SH1"
- "negc %1,%0"
+ "negc %2,%0"
[(set_attr "type" "arith")])
+;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
+;; pattern can be used by the combine pass. Using a scratch reg for the
+;; -1 constant results in slightly better register allocations compared to
+;; generating a pseudo reg before reload.
+(define_insn_and_split "*movrt_negc"
+ [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+ (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
+ (clobber (match_scratch:SI 2 "=r"))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1 && ! TARGET_SH2A"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2) (const_int -1))
+ (parallel
+ [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
+ (set (reg:SI T_REG) (const_int 1))
+ (use (match_dup 2))])])
+
+;; In some cases the zero extension does not get combined away and a
+;; sequence like the following might remain:
+;; mov #-1,r2
+;; tst r1,r1
+;; negc r2,r1
+;; extu.b r1,r1
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "arith_reg_dest" "")
+ (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
+ (set (reg:SI T_REG) (const_int 1))
+ (use (match_operand:SI 2 "arith_reg_operand" ""))])
+ (set (match_dup 0)
+ (zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
+ "TARGET_SH1 && REGNO (operands[0]) == REGNO (operands[3])"
+ [(parallel
+ [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
+ (set (reg:SI T_REG) (const_int 1))
+ (use (match_dup 2))])])
+
;; The *negnegt pattern helps the combine pass to figure out how to fold
;; an explicit double T bit negation.
(define_insn_and_split "*negnegt"
@@ -9855,7 +9893,8 @@ label:
[(const_int 0)])
(define_insn_and_split "nott"
- [(set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))]
+ [(set (reg:SI T_REG)
+ (xor:SI (match_operand:SI 0 "t_reg_operand" "") (const_int 1)))]
"TARGET_SH1"
{
gcc_assert (TARGET_SH2A);
diff --git a/gcc/config/sh/sync.md b/gcc/config/sh/sync.md
index 79cd765d87f..6dabf873c17 100644
--- a/gcc/config/sh/sync.md
+++ b/gcc/config/sh/sync.md
@@ -830,7 +830,7 @@
/* The result of the test op is the inverse of what we are
supposed to return. Thus invert the T bit. The inversion will be
potentially optimized away and integrated into surrounding code. */
- emit_insn (gen_movnegt (operands[0]));
+ emit_insn (gen_movnegt (operands[0], get_t_reg_rtx ()));
DONE;
})
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 021ce85fac4..cffdd0b1834 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2012-08-09 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/51244
+ * gcc.target/sh/pr51244-5: New.
+ * gcc.target/sh/pr51244-6: New.
+
2012-08-09 Michael Zolotukhin <michael.v.zolotukhin@intel.com>
* gcc.target/i386/adx-addxcarry32-3.c: New.
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-5.c b/gcc/testsuite/gcc.target/sh/pr51244-5.c
new file mode 100644
index 00000000000..a99889df3c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr51244-5.c
@@ -0,0 +1,50 @@
+/* Check that no unnecessary sign or zero extension insn is generated after
+ a negc or movrt insn that stores the inverted T bit in a reg. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
+/* { dg-final { scan-assembler-not "extu|exts" } } */
+
+int
+test_00 (int a, int b, int* c, short* d, int x)
+{
+ *d = x != 0;
+ *c = -1;
+
+ if (x != 0)
+ return a > 0;
+
+ return 0;
+}
+
+unsigned char
+test_01 (int x)
+{
+ if (x < 58 && x > 47)
+ return 1;
+ return 0;
+}
+
+char
+test_02 (int x)
+{
+ if (x < 58 && x > 47)
+ return 1;
+ return 0;
+}
+
+unsigned short
+test_03 (int x)
+{
+ if (x < 58 && x > 47)
+ return 1;
+ return 0;
+}
+
+short
+test_04 (int x)
+{
+ if (x < 58 && x > 47)
+ return 1;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-6.c b/gcc/testsuite/gcc.target/sh/pr51244-6.c
new file mode 100644
index 00000000000..cfd466197d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr51244-6.c
@@ -0,0 +1,15 @@
+/* Check that no unnecessary sign or zero extension insn is generated after
+ a negc or movrt insn that stores the inverted T bit in a reg. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
+/* { dg-final { scan-assembler-not "extu|exts" } } */
+
+float
+test_00 (float q[4], float m[9])
+{
+ float s0 = m[0] + m[1];
+ float s1 = m[0] - m[1];
+
+ return q[s0 > s1 ? 0 : 1];
+}