diff options
author | olegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-08-12 22:47:15 +0000 |
---|---|---|
committer | olegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-08-12 22:47:15 +0000 |
commit | 976ca48a8d753a2f2e99e3f65145326e0364556f (patch) | |
tree | 94d55263957ec8e75d55f8db163f435cfce79511 /gcc/config/sh/sh.md | |
parent | d79ac9a14880d5f20fd62c72d87c4f3405727350 (diff) | |
download | gcc-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.md | 147 |
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 |