This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH]: Optimize tst/cmp instructions for HC11/HC12
- From: Stephane Carrez <Stephane dot Carrez at worldnet dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 15 Mar 2002 23:37:39 +0100
- Subject: [PATCH]: Optimize tst/cmp instructions for HC11/HC12
Hi!
The following patch optimizes the code for test and compare for 68hc11/hc12.
I've committed this on 3_1 branch and mainline.
Stephane
2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
* config/m68hc11/m68hc11.md ("tstqi_1"): Try to use ldab instead of tst.
("tstqi" split): Avoid using memory for tstqi on address register.
(splits): Remove constraints.
("cmphi_1_hc12"): New from "cmphi_1" and tuned for 68HC12.
("cmpdf", "cmpsf"): Remove since not used.
("*tbeq", "*tbne", "*tbeq8", "*tbne8"): Also look in cc_status.value2.
(peephole2): New peepholes to optimize tstqi and pre inc/dec addressing.
Index: config/m68hc11/m68hc11.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68hc11/m68hc11.md,v
retrieving revision 1.26
diff -u -p -r1.26 m68hc11.md
--- m68hc11.md 2002/03/15 22:22:56 1.26
+++ m68hc11.md 2002/03/15 22:31:00
@@ -204,28 +204,37 @@
;;
;; Split pattern for (tst:QI) on an address register.
-;; The value is saved in memory and we test the low part only.
;;
(define_split
[(set (cc0)
- (match_operand:QI 0 "hard_addr_reg_operand" "xy"))]
+ (match_operand:QI 0 "hard_addr_reg_operand" ""))]
"z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
- [(set (match_dup 3) (match_dup 2))
- (set (cc0) (match_dup 4))]
- "operands[2] = gen_rtx (REG, HImode, REGNO (operands[0]));
- operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
- operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);")
+ [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
+ (set (match_dup 1) (reg:HI D_REGNUM))])
+ (set (cc0) (reg:QI D_REGNUM))
+ (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
+ (set (match_dup 1) (reg:HI D_REGNUM))])]
+ "operands[1] = gen_rtx (REG, HImode, REGNO (operands[0]));")
(define_insn "tstqi_1"
[(set (cc0)
(match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
""
- "@
- tst\\t%0
- tstb
- #
- tst\\t%b0")
+ "*
+{
+ if (A_REG_P (operands[0]))
+ return \"#\";
+
+ else if (D_REG_P (operands[0]))
+ return \"tstb\";
+
+ else if (dead_register_here (insn, d_reg))
+ return \"ldab\\t%b0\";
+ else
+ return \"tst\\t%b0\";
+}")
+
;;
;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
;; during the Z register replacement. They are used when an operand
@@ -247,8 +256,8 @@
(define_split /* "tstqi_z_used" */
[(set (cc0)
- (match_operand:QI 0 "tst_operand" "m"))
- (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
+ (match_operand:QI 0 "tst_operand" ""))
+ (use (match_operand:HI 1 "hard_reg_operand" ""))
(use (reg:HI 11))]
"z_replacement_completed == 2"
[(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
@@ -288,8 +297,8 @@
;;
(define_split
[(set (cc0)
- (compare (match_operand:HI 0 "hard_reg_operand" "dxy")
- (match_operand:HI 1 "hard_reg_operand" "Aw")))]
+ (compare (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "hard_reg_operand" "")))]
"reload_completed"
[(set (match_dup 2) (match_dup 1))
(set (cc0)
@@ -311,13 +320,13 @@
DONE;
}")
-(define_insn "cmphi_1"
+(define_insn "cmphi_1_hc12"
[(set (cc0)
(compare (match_operand:HI 0 "tst_operand"
- "x,dy,xyd,?xy,d,m,!u,dxy,dxy")
+ "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
(match_operand:HI 1 "cmp_operand"
"i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
- ""
+ "TARGET_M6812"
"*
{
if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
@@ -331,6 +340,26 @@
return \"cp%0\\t%1\";
}")
+(define_insn "cmphi_1_hc11"
+ [(set (cc0)
+ (compare (match_operand:HI 0 "tst_operand"
+ "dx,y,xyd,?xy,d,m,!u,dxy,dxy")
+ (match_operand:HI 1 "cmp_operand"
+ "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
+ "TARGET_M6811"
+ "*
+{
+ if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
+ {
+ cc_status.flags |= CC_REVERSED;
+ return \"cp%1\\t%0\";
+ }
+ else if (H_REG_P (operands[1]))
+ return \"#\";
+ else
+ return \"cp%0\\t%1\";
+}")
+
(define_insn "cmphi_z_used"
[(set (cc0)
(compare (match_operand:HI 0 "tst_operand" "dxy,m")
@@ -342,9 +371,9 @@
(define_split /* "cmphi_z_used" */
[(set (cc0)
- (compare (match_operand:HI 0 "tst_operand" "dxy,m")
- (match_operand:HI 1 "cmp_operand" "m,dxy")))
- (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
+ (compare (match_operand:HI 0 "tst_operand" "")
+ (match_operand:HI 1 "cmp_operand" "")))
+ (use (match_operand:HI 2 "hard_reg_operand" ""))
(use (reg:HI 11))]
"z_replacement_completed == 2"
[(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
@@ -361,8 +390,8 @@
;;
(define_split
[(set (cc0)
- (compare (match_operand:QI 0 "hard_addr_reg_operand" "xy")
- (match_operand:QI 1 "cmp_operand" "uimA")))]
+ (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
+ (match_operand:QI 1 "cmp_operand" "")))]
"z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
[(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
(set (match_dup 3) (reg:HI D_REGNUM))])
@@ -374,8 +403,8 @@
(define_split
[(set (cc0)
- (compare (match_operand:QI 0 "hard_reg_operand" "dxy")
- (match_operand:QI 1 "hard_reg_operand" "dxy")))]
+ (compare (match_operand:QI 0 "hard_reg_operand" "")
+ (match_operand:QI 1 "hard_reg_operand" "")))]
"reload_completed"
[(set (match_dup 3) (match_dup 4))
(set (cc0)
@@ -413,8 +442,8 @@
(define_split /* "bitcmpqi" */
[(set (cc0)
- (and:QI (match_operand:QI 0 "tst_operand" "d")
- (match_operand:QI 1 "hard_addr_reg_operand" "xy")))]
+ (and:QI (match_operand:QI 0 "tst_operand" "")
+ (match_operand:QI 1 "hard_addr_reg_operand" "")))]
"z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
[(set (match_dup 3) (match_dup 2))
(set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
@@ -433,9 +462,9 @@
(define_split /* "bitcmpqi_z_used" */
[(set (cc0)
- (and:QI (match_operand:QI 0 "tst_operand" "d,m")
- (match_operand:QI 1 "cmp_operand" "m,d")))
- (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
+ (and:QI (match_operand:QI 0 "tst_operand" "")
+ (match_operand:QI 1 "cmp_operand" "")))
+ (use (match_operand:HI 2 "hard_reg_operand" ""))
(use (reg:HI 11))]
"z_replacement_completed == 2"
[(set (mem:HI (pre_dec:HI (reg:HI 3))) (match_dup 2))
@@ -534,30 +563,6 @@
(set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
"operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
-(define_expand "cmpdf"
- [(set (cc0)
- (compare (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" "")))]
- "0"
- "
-{
- m68hc11_compare_op0 = operands[0];
- m68hc11_compare_op1 = operands[1];
- DONE;
-}")
-
-(define_expand "cmpsf"
- [(set (cc0)
- (compare (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" "")))]
- "0"
- "
-{
- m68hc11_compare_op0 = operands[0];
- m68hc11_compare_op1 = operands[1];
- DONE;
-}")
-
;;--------------------------------------------------------------------
;;- Move strict_low_part
;;--------------------------------------------------------------------
@@ -5909,7 +5914,8 @@
smaller and a little bit faster. This happens quite often due
to reloading of operands[0]. In that case, flags are set correctly
due to the load instruction. */
- if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+ if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+ || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
return \"beq\\t%l1\";
else
return \"tbeq\\t%0,%l1\";
@@ -5924,7 +5930,8 @@
"TARGET_M6812"
"*
{
- if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+ if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+ || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
return \"bne\\t%l1\";
else
return \"tbne\\t%0,%l1\";
@@ -5942,7 +5949,8 @@
"TARGET_M6812"
"*
{
- if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+ if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+ || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
return \"beq\\t%l1\";
else
return \"tbeq\\tb,%l1\";
@@ -5957,7 +5965,8 @@
"TARGET_M6812"
"*
{
- if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+ if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
+ || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
return \"bne\\t%l1\";
else
return \"tbne\\tb,%l1\";
@@ -6424,6 +6433,65 @@
[(set (match_dup 0) (reg:HI SP_REGNUM))
(set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
"")
+
+;;
+;; Remove a possible move before a compare instruction when that
+;; move will go in a dead register. Compare with the source then.
+;;
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (match_operand:HI 1 "hard_reg_operand" ""))
+ (set (cc0)
+ (compare (match_dup 0)
+ (match_operand:HI 2 "cmp_operand" "")))]
+ "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
+ && peep2_reg_dead_p (2, operands[0])
+ && !reg_mentioned_p (operands[0], operands[2])"
+ [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
+ "")
+
+;;
+;; Optimize an address register increment and a compare to use
+;; a PRE_INC or PRE_DEC addressing mode (disabled on the compare insn
+;; before reload, but can be enabled after).
+;;
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (plus:HI (match_dup 0)
+ (match_operand:HI 1 "const_int_operand" "")))
+ (set (cc0)
+ (compare (match_operand:QI 2 "hard_reg_operand" "")
+ (match_operand:QI 3 "memory_operand" "")))]
+ "TARGET_AUTO_INC_DEC
+ && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
+ && reg_mentioned_p (operands[0], operands[3])"
+ [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
+ "if (INTVAL (operands[1]) == 1)
+ operands[4] = gen_rtx (MEM, QImode,
+ gen_rtx (PRE_INC, HImode, operands[0]));
+ else
+ operands[4] = gen_rtx (MEM, QImode,
+ gen_rtx (PRE_DEC, HImode, operands[0]));
+ ")
+
+(define_peephole2
+ [(set (match_operand:HI 0 "hard_reg_operand" "")
+ (plus:HI (match_dup 0)
+ (match_operand:HI 1 "const_int_operand" "")))
+ (set (cc0)
+ (compare (match_operand:QI 2 "memory_operand" "")
+ (match_operand:QI 3 "hard_reg_operand" "")))]
+ "TARGET_AUTO_INC_DEC
+ && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
+ && reg_mentioned_p (operands[0], operands[2])"
+ [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
+ "if (INTVAL (operands[1]) == 1)
+ operands[4] = gen_rtx (MEM, QImode,
+ gen_rtx (PRE_INC, HImode, operands[0]));
+ else
+ operands[4] = gen_rtx (MEM, QImode,
+ gen_rtx (PRE_DEC, HImode, operands[0]));
+ ")
;;
;; This peephole catches the address computations generated by the reload