summaryrefslogtreecommitdiff
path: root/gcc/config/m68k
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2016-11-18 21:52:32 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2016-11-18 21:52:32 +0000
commit302e06b9e31989971e403fc85f34361850ef997e (patch)
tree9985d818e7b6cf2ddc5531b04e2a1537e4997fd1 /gcc/config/m68k
parent4b373fc1153b1976a6dcfa8043973112f51c5566 (diff)
downloadgcc-302e06b9e31989971e403fc85f34361850ef997e.tar.gz
PR target/25112
* config/m68k/m68k.c (moveq feeding equality comparison): New peepholes. * config/m68k/predicates.md (addq_subq_operand): New predicate. (equality_comparison_operator): Likewise. PR target/25112 * gcc.target/m68k/pr25112: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@242605 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/m68k')
-rw-r--r--gcc/config/m68k/m68k.md40
-rw-r--r--gcc/config/m68k/predicates.md12
2 files changed, 52 insertions, 0 deletions
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 3d7895d264c..7b7f3731f07 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -7641,6 +7641,46 @@
(const_int 0))]
"operands[5] = (operands[0] == operands[3]) ? operands[4] : operands[3];")
+;; We want to turn
+;; moveq const,dX
+;; cmp.l dX,dY
+;; je/jne
+;;
+;; into
+;; addq/subq -const,dY
+;; cmp.l dY, 0
+;; je/jne
+;;
+;; dX and dY must both be dead at the end of the sequence and the constant
+;; must be valid for addq/subq.
+;;
+;; Essentially we're making it trivial for final to realize the comparison
+;; is not needed
+;;
+;; Testing has shown a variant where the operands are reversed in the
+;; comparison never hits, so I have not included that variant.
+;;
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "addq_subq_operand" ""))
+ (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
+ (match_dup 0)))
+ (set (pc) (if_then_else (match_operator 5 "equality_comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand 3 "pc_or_label_operand")
+ (match_operand 4 "pc_or_label_operand")))]
+ "peep2_reg_dead_p (2, operands[0])
+ && peep2_reg_dead_p (2, operands[2])
+ && (operands[3] == pc_rtx || operands[4] == pc_rtx)
+ && DATA_REG_P (operands[2])"
+ [(set (match_dup 2) (plus:SI (match_dup 2) (match_dup 6)))
+ (set (cc0) (compare (match_dup 2) (const_int 0)))
+ (set (pc) (if_then_else (match_op_dup 5 [(cc0) (const_int 0)])
+ (match_dup 3)
+ (match_dup 4)))]
+ "operands[6] = GEN_INT (-INTVAL (operands[1]));")
+
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "pow2_m1_operand" ""))
diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md
index 186436c42b7..bfb548ab86f 100644
--- a/gcc/config/m68k/predicates.md
+++ b/gcc/config/m68k/predicates.md
@@ -245,6 +245,18 @@
|| reload_completed));
})
+;; Used to detect constants that are valid for addq/subq instructions
+(define_predicate "addq_subq_operand"
+ (match_code "const_int")
+{
+ return ((INTVAL (op) <= 8 && INTVAL (op) > 0)
+ || (INTVAL (op) >= -8 && INTVAL (op) < 0));
+})
+
+;; Used to detect equality and non-equality operators
+(define_predicate "equality_comparison_operator"
+ (match_code "eq,ne"))
+
;; Used to detect when an operand is either a register
;; or a constant that is all ones in its lower bits.
;; Used by insv pattern to help detect when we're initializing