This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: New peepholes for 68HC11 and 68HC12


Hi!

This patch adds several peepholes:
(from http://savannah.gnu.org/projects/m68hc11/)

  - optimize sequences of moves,
  - optimize 'and' 'or' to use bclr and bset forms,
  - optimize sequences that add a small number

Commited on 3_4 and mainline.

Stephane

2004-03-02 Stephane Carrez <stcarrez@nerim.fr>

	* 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.

Index: config/m68hc11/m68hc11.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68hc11/m68hc11.md,v
retrieving revision 1.54.10.3
diff -u -p -r1.54.10.3 m68hc11.md
--- config/m68hc11/m68hc11.md	2 Mar 2004 21:52:21 -0000	1.54.10.3
+++ config/m68hc11/m68hc11.md	2 Mar 2004 22:05:19 -0000
@@ -6904,6 +6904,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.
@@ -6968,6 +7023,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).
@@ -7059,6 +7144,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
@@ -7073,6 +7183,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.
@@ -7095,6 +7224,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. 
@@ -7364,3 +7661,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\";
+}")

Attachment: pgp00000.pgp
Description: PGP signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]