summaryrefslogtreecommitdiff
path: root/gcc/config/sh/sh.md
diff options
context:
space:
mode:
authorolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-12 22:47:15 +0000
committerolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-12 22:47:15 +0000
commit976ca48a8d753a2f2e99e3f65145326e0364556f (patch)
tree94d55263957ec8e75d55f8db163f435cfce79511 /gcc/config/sh/sh.md
parentd79ac9a14880d5f20fd62c72d87c4f3405727350 (diff)
downloadgcc-976ca48a8d753a2f2e99e3f65145326e0364556f.tar.gz
PR target/51244
* config/sh/sh.md: Add splits for inverted compare and branch opportunities. (*cmpeqsi_t): New insn. (cmpgtsi_t, cmpgesi_t): Swap r and N alternatives. (cmpgeusi_t): Use satisfies_constraint_Z. Emit sett insn in replacement insn list and not in the preparation statements. (clrt, sett): Add mt_group attribute. PR target/51244 * gcc.target/sh/pr51244-7.c: New. * gcc.target/sh/pr51244-8.c: New. * gcc.target/sh/pr51244-9.c: New. * gcc.target/sh/pr51244-10.c: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@190331 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/sh/sh.md')
-rw-r--r--gcc/config/sh/sh.md147
1 files changed, 124 insertions, 23 deletions
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index ffa899d3a48..8af99f8e49e 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -742,12 +742,6 @@
}
[(set_attr "type" "mt_group")])
-;; ??? Perhaps should only accept reg/constant if the register is reg 0.
-;; That would still allow reload to create cmpi instructions, but would
-;; perhaps allow forcing the constant into a register when that is better.
-;; Probably should use r0 for mem/imm compares, but force constant into a
-;; register for pseudo/imm compares.
-
(define_insn "cmpeqsi_t"
[(set (reg:SI T_REG)
(eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
@@ -759,24 +753,40 @@
cmp/eq %1,%0"
[(set_attr "type" "mt_group")])
+;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
+;; pattern by itself. What this actually does is:
+;; x == 0: (1 >> 0-0) & 1 = 1
+;; x != 0: (1 >> 0-x) & 1 = 0
+;; Without this the test pr51244-8.c fails on SH2A and SH4A.
+(define_insn_and_split "*cmpeqsi_t"
+ [(set (reg:SI T_REG)
+ (and:SI (lshiftrt:SI
+ (const_int 1)
+ (neg:SI (match_operand:SI 0 "arith_reg_operand" "r")))
+ (const_int 1)))]
+ "TARGET_SH1"
+ "#"
+ "&& 1"
+ [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))])
+
(define_insn "cmpgtsi_t"
[(set (reg:SI T_REG)
(gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
- (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
+ (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
"TARGET_SH1"
"@
- cmp/gt %1,%0
- cmp/pl %0"
+ cmp/pl %0
+ cmp/gt %1,%0"
[(set_attr "type" "mt_group")])
(define_insn "cmpgesi_t"
[(set (reg:SI T_REG)
(ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
- (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
+ (match_operand:SI 1 "arith_reg_or_0_operand" "N,r")))]
"TARGET_SH1"
"@
- cmp/ge %1,%0
- cmp/pz %0"
+ cmp/pz %0
+ cmp/ge %1,%0"
[(set_attr "type" "mt_group")])
;; FIXME: This is actually wrong. There is no way to literally move a
@@ -815,6 +825,99 @@
DONE;
})
+;; Combine patterns to invert compare and branch operations for which we
+;; don't have actual comparison insns. These patterns are used in cases
+;; which appear after the initial cbranchsi expansion, which also does
+;; some condition inversion.
+
+(define_split
+ [(set (pc)
+ (if_then_else (ne (match_operand:SI 0 "arith_reg_operand" "")
+ (match_operand:SI 1 "arith_reg_or_0_operand" ""))
+ (label_ref (match_operand 2))
+ (pc)))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ [(set (reg:SI T_REG) (eq:SI (match_dup 0) (match_dup 1)))
+ (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
+ (label_ref (match_dup 2))
+ (pc)))])
+
+;; FIXME: Similar to the *cmpeqsi_t pattern above, for some reason, on SH4A
+;; and SH2A combine fails to simplify this pattern by itself.
+;; What this actually does is:
+;; x == 0: (1 >> 0-0) & 1 = 1
+;; x != 0: (1 >> 0-x) & 1 = 0
+;; Without this the test pr51244-8.c fails on SH2A and SH4A.
+(define_split
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (lshiftrt:SI
+ (const_int 1)
+ (neg:SI (match_operand:SI 0 "arith_reg_operand" "")))
+ (const_int 1))
+ (const_int 0))
+ (label_ref (match_operand 2))
+ (pc)))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ [(set (reg:SI T_REG) (eq:SI (match_dup 0) (const_int 0)))
+ (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
+ (label_ref (match_dup 2))
+ (pc)))])
+
+(define_split
+ [(set (pc)
+ (if_then_else (le (match_operand:SI 0 "arith_reg_operand" "")
+ (match_operand:SI 1 "arith_reg_or_0_operand" ""))
+ (label_ref (match_operand 2))
+ (pc)))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ [(set (reg:SI T_REG) (gt:SI (match_dup 0) (match_dup 1)))
+ (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
+ (label_ref (match_dup 2))
+ (pc)))])
+
+(define_split
+ [(set (pc)
+ (if_then_else (lt (match_operand:SI 0 "arith_reg_operand" "")
+ (match_operand:SI 1 "arith_reg_or_0_operand" ""))
+ (label_ref (match_operand 2))
+ (pc)))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ [(set (reg:SI T_REG) (ge:SI (match_dup 0) (match_dup 1)))
+ (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
+ (label_ref (match_dup 2))
+ (pc)))])
+
+(define_split
+ [(set (pc)
+ (if_then_else (leu (match_operand:SI 0 "arith_reg_operand" "")
+ (match_operand:SI 1 "arith_reg_operand" ""))
+ (label_ref (match_operand 2))
+ (pc)))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ [(set (reg:SI T_REG) (gtu:SI (match_dup 0) (match_dup 1)))
+ (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
+ (label_ref (match_dup 2))
+ (pc)))])
+
+(define_split
+ [(set (pc)
+ (if_then_else (ltu (match_operand:SI 0 "arith_reg_operand" "")
+ (match_operand:SI 1 "arith_reg_operand" ""))
+ (label_ref (match_operand 2))
+ (pc)))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ [(set (reg:SI T_REG) (geu:SI (match_dup 0) (match_dup 1)))
+ (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
+ (label_ref (match_dup 2))
+ (pc)))])
+
;; -------------------------------------------------------------------------
;; SImode unsigned integer comparisons
;; -------------------------------------------------------------------------
@@ -825,13 +928,10 @@
(match_operand:SI 1 "arith_reg_or_0_operand" "rN")))]
"TARGET_SH1"
"cmp/hs %1,%0"
- "&& operands[1] == CONST0_RTX (SImode)"
- [(pc)]
-{
- emit_insn (gen_sett ());
- DONE;
-}
- [(set_attr "type" "mt_group")])
+ "&& satisfies_constraint_Z (operands[0])"
+ [(set (reg:SI T_REG) (const_int 1))]
+ ""
+ [(set_attr "type" "mt_group")])
(define_insn "cmpgtusi_t"
[(set (reg:SI T_REG)
@@ -839,7 +939,7 @@
(match_operand:SI 1 "arith_reg_operand" "r")))]
"TARGET_SH1"
"cmp/hi %1,%0"
- [(set_attr "type" "mt_group")])
+ [(set_attr "type" "mt_group")])
;; -------------------------------------------------------------------------
@@ -5132,13 +5232,14 @@ label:
(define_insn "clrt"
[(set (reg:SI T_REG) (const_int 0))]
"TARGET_SH1"
- "clrt")
+ "clrt"
+ [(set_attr "type" "mt_group")])
(define_insn "sett"
[(set (reg:SI T_REG) (const_int 1))]
"TARGET_SH1"
- "sett")
-
+ "sett"
+ [(set_attr "type" "mt_group")])
;; Use the combine pass to transform sequences such as
;; mov r5,r0