summaryrefslogtreecommitdiff
path: root/gcc/config/m68hc11
diff options
context:
space:
mode:
authorciceron <ciceron@138bc75d-0d04-0410-961f-82ee72b054a4>2004-03-02 22:16:15 +0000
committerciceron <ciceron@138bc75d-0d04-0410-961f-82ee72b054a4>2004-03-02 22:16:15 +0000
commitdb25945d888377526c243eb72e768eea6ea8be42 (patch)
tree6cd18a7c0bc72a7fdeeae48dfbf58d8620d43ce0 /gcc/config/m68hc11
parent90a35510070af6c33fdba022d43f9941da9293d1 (diff)
downloadgcc-db25945d888377526c243eb72e768eea6ea8be42.tar.gz
* config/m68hc11/m68hc11.md (move peephole2): New peepholes to optimize
sequences of moves. (add peepholes): New peepholes to optimize sequences adding small constants. (bset peepholes): New peepholes to transform an OR in a bset form (bclr peepholes): Likewise for bclr form. (cmp peepholes): New peepholes to avoid register copies when comparing. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@78787 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/m68hc11')
-rw-r--r--gcc/config/m68hc11/m68hc11.md335
1 files changed, 335 insertions, 0 deletions
diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md
index 41407332128..08d03cbd6ff 100644
--- a/gcc/config/m68hc11/m68hc11.md
+++ b/gcc/config/m68hc11/m68hc11.md
@@ -6907,6 +6907,61 @@
gen_rtx_POST_INC (HImode,
gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
+;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
+(define_peephole2
+ [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
+ (match_operand:HI 0 "hard_reg_operand" ""))
+ (set (match_dup 0)
+ (match_operand:HI 1 "hard_reg_operand" ""))
+ (set (mem:HI (reg:HI SP_REGNUM))
+ (match_dup 0))]
+ "TARGET_M6812"
+ [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
+ (match_dup 1))
+ (set (match_dup 0) (match_dup 1))]
+ "")
+
+;;
+;; Change: "ldd 0,sp; pulx" into "puld"
+;; This sequence usually appears at end a functions.
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (mem:HI (reg:HI SP_REGNUM)))
+ (use (match_dup 0))
+ (set (match_operand:HI 1 "hard_reg_operand" "")
+ (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
+ "peep2_reg_dead_p (2, operands[1])"
+ [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
+ (use (match_dup 0))]
+ "")
+
+;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
+;; Appears to allocate local variables.
+(define_peephole2
+ [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
+ (match_operand:HI 0 "hard_reg_operand" ""))
+ (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
+ (const_int 0))
+ (set (mem:QI (reg:HI SP_REGNUM))
+ (const_int 0))]
+ "TARGET_M6812"
+ [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
+ (const_int 0))]
+ "")
+
+;; Likewise for HI mode
+(define_peephole2
+ [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
+ (match_operand:HI 0 "hard_reg_operand" ""))
+ (set (mem:HI (reg:HI SP_REGNUM))
+ (const_int 0))]
+ "TARGET_M6812"
+ [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
+ (const_int 0))]
+ "")
+;;--------------------------------------------------------------------
+;;-
+;;--------------------------------------------------------------------
;;
;; Optimize memory<->memory moves when the value is also loaded in
;; a register.
@@ -6971,6 +7026,36 @@
"")
;;
+;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
+;;
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "const_int_operand" ""))
+ (set (match_dup 0)
+ (plus:HI (match_dup 0)
+ (match_operand:HI 2 "general_operand" "")))
+ (match_scratch:QI 3 "d")]
+ "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
+ [(set (match_dup 3) (match_dup 4))
+ (set (match_dup 0) (match_dup 2))
+ (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
+ "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
+
+;;
+;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
+;;
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "const_int_operand" ""))
+ (set (match_dup 0)
+ (plus:HI (match_dup 0)
+ (match_operand:HI 2 "general_operand" "")))]
+ "TARGET_M6812"
+ [(set (match_dup 0) (match_dup 2))
+ (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
+ "")
+
+;;
;; Optimize an address register increment and a compare to use
;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
;; before reload, but can be enabled after).
@@ -7062,6 +7147,31 @@
"")
;;
+;;
+;;
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "hard_reg_operand" "")
+ (ashift:SI (match_operand:SI 1 "general_operand" "")
+ (const_int 1)))
+ (clobber (match_scratch:HI 2 ""))])
+ (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
+ (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
+ "!X_REG_P (operands[1])
+ && peep2_reg_dead_p (2, gen_rtx (REG, HImode, D_REGNUM))
+ && peep2_reg_dead_p (3, gen_rtx (REG, HImode, X_REGNUM))"
+ [(set (reg:HI D_REGNUM) (match_dup 5))
+ (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
+ (set (match_dup 3) (reg:HI D_REGNUM))
+ (set (reg:HI D_REGNUM) (match_dup 6))
+ (parallel [(set (reg:HI D_REGNUM)
+ (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
+ (clobber (reg:HI CC_REGNUM))])
+ (set (match_dup 4) (reg:HI D_REGNUM))]
+ "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
+ operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
+
+;;
;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
;;
(define_peephole2
@@ -7076,6 +7186,25 @@
"")
;;
+;; Remove one load when copying a value to/from memory and also
+;; to a register. Take care not cloberring a possible register used
+;; by operand 2.
+;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
+;;
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "general_operand" ""))
+ (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
+ (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
+ "peep2_reg_dead_p (2, operands[0])
+ && !side_effects_p (operands[1])
+ && !side_effects_p (operands[2])
+ && !reg_mentioned_p (operands[3], operands[2])"
+ [(set (match_dup 3) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))]
+ "")
+
+;;
;; Replace a "ldd <mem>; addd #N; std <mem>" into a
;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register
;; and the constant is small.
@@ -7098,6 +7227,174 @@
"if (reg_mentioned_p (operands[4], operands[1])) FAIL;
if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
+;;--------------------------------------------------------------------
+;;- Bset peephole2
+;;--------------------------------------------------------------------
+;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
+;;
+;; Replace 'ldab <mem>; orab #N; stab <mem>' by 'bset <mem> #N'.
+;; Register D must be dead and there must be no register side effects for mem.
+;; The <mem> *can* be volatile this is why we must not use 'side_effects_p'.
+;; The good side effect is that it makes the sequence atomic.
+;;
+(define_peephole2
+ [(set (match_operand:QI 0 "hard_reg_operand" "")
+ (match_operand:QI 1 "nonimmediate_operand" ""))
+ (set (match_dup 0) (ior:QI (match_dup 0)
+ (match_operand:QI 2 "const_int_operand" "")))
+ (set (match_dup 1) (match_dup 0))]
+ "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
+ && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
+ && peep2_reg_dead_p (3, operands[0])"
+ [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
+ "")
+
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "nonimmediate_operand" ""))
+ (set (match_dup 0) (ior:HI (match_dup 0)
+ (match_operand:HI 2 "const_int_operand" "")))
+ (set (match_dup 1) (match_dup 0))]
+ "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
+ && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
+ && peep2_reg_dead_p (3, operands[0])"
+ [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
+ "")
+
+;;--------------------------------------------------------------------
+;;- Bclr peephole2
+;;--------------------------------------------------------------------
+;; Replace 'ldab <mem>; andab #N; stab <mem>' by 'bclr <mem> #N'.
+;; See Bset peephole2.
+;;
+(define_peephole2
+ [(set (match_operand:QI 0 "hard_reg_operand" "")
+ (match_operand:QI 1 "nonimmediate_operand" ""))
+ (set (match_dup 0) (and:QI (match_dup 0)
+ (match_operand:QI 2 "const_int_operand" "")))
+ (set (match_dup 1) (match_dup 0))]
+ "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
+ && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
+ && peep2_reg_dead_p (3, operands[0])"
+ [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
+ "")
+
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "nonimmediate_operand" ""))
+ (set (match_dup 0) (and:HI (match_dup 0)
+ (match_operand:HI 2 "const_int_operand" "")))
+ (set (match_dup 1) (match_dup 0))]
+ "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
+ && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
+ && peep2_reg_dead_p (3, operands[0])"
+ [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
+ "")
+
+
+;;--------------------------------------------------------------------
+;;- Compare peephole2
+;;--------------------------------------------------------------------
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "hard_reg_operand" ""))
+ (set (match_dup 1) (plus:HI (match_dup 1)
+ (match_operand:HI 2 "const_int_operand" "")))
+ (set (cc0) (match_dup 0))]
+ "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
+ [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
+ (set (cc0) (compare (match_dup 1) (match_dup 2)))]
+ "")
+
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "hard_reg_operand" ""))
+ (set (match_operand:HI 2 "hard_reg_operand" "")
+ (plus:HI (match_dup 2)
+ (match_operand:HI 3 "const_int_operand" "")))
+ (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
+ (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))]
+ "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
+ && !reg_mentioned_p (operands[2], operands[4])
+
+ && ((rtx_equal_p (operands[5], operands[0])
+ && rtx_equal_p (operands[2], operands[1]))
+
+ || (rtx_equal_p (operands[5], operands[1])
+ && rtx_equal_p (operands[2], operands[0])))"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
+ (set (match_dup 4) (match_dup 2))
+ (set (cc0) (compare (match_dup 2) (match_dup 3)))]
+ "")
+
+
+;;--------------------------------------------------------------------
+;;- Load peephole2
+;;--------------------------------------------------------------------
+;;
+;; Optimize initialization of 2 hard regs from the same memory location
+;; Since we can't copy easily X, Y and D to each other, load the 2 registers
+;; from the same memory location.
+;;
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "memory_operand" ""))
+ (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
+ "TARGET_M6811
+ && !side_effects_p (operands[1])
+ && !reg_mentioned_p (operands[0], operands[1])"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 1))]
+ "")
+
+;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
+;;
+(define_peephole2
+ [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
+ (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
+ (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
+ (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
+ (match_scratch:HI 4 "d")]
+ ""
+ [(set (match_dup 4) (const_int 0))
+ (set (match_dup 0) (match_dup 4))
+ (set (match_dup 1) (match_dup 4))
+ (set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 4))]
+ "")
+
+;;
+;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
+;;
+(define_peephole2
+ [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
+ (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
+ (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
+ (match_scratch:HI 3 "d")]
+ ""
+ [(set (match_dup 3) (const_int 0))
+ (set (match_dup 0) (match_dup 3))
+ (set (match_dup 1) (match_dup 3))
+ (set (match_dup 2) (match_dup 3))]
+ "")
+
+;;
+;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
+;;
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
+ (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
+ (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
+ (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
+ (match_scratch:HI 4 "x")]
+ "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
+ [(set (match_dup 4) (const_int 0))
+ (set (match_dup 1) (match_dup 4))
+ (set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 4))]
+ "")
+
;;
;; This peephole catches the address computations generated by the reload
;; pass.
@@ -7367,3 +7664,41 @@
return \"sts\\t%t0\\n\\tld%0\\t%t0\";
}
")
+
+(define_peephole
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "memory_operand" ""))
+ (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
+ "TARGET_M6811
+ && !side_effects_p (operands[1])
+ && !reg_mentioned_p (operands[0], operands[1])"
+ "*
+{
+ rtx ops[2];
+
+ ops[0] = operands[0];
+ ops[1] = operands[1];
+ m68hc11_gen_movhi (insn, ops);
+ ops[0] = operands[2];
+ m68hc11_gen_movhi (insn, ops);
+ return \"\";
+}")
+
+;; Peephole for Z register replacement.
+;; Avoid to use _.tmp register when comparing D and X if we can compare
+;; with soft register
+(define_peephole
+ [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
+ (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
+ (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
+ (reg:HI SOFT_TMP_REGNUM)))]
+ "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
+ "*
+{
+ rtx ops[2];
+
+ ops[0] = operands[0];
+ ops[1] = operands[1];
+ m68hc11_gen_movhi (insn, ops);
+ return \"cp%2\\t%1\";
+}")