[PATCH/m68k] Convert most text peepholes

Roman Zippel zippel@linux-m68k.org
Wed Sep 19 18:47:00 GMT 2007


Hi,

This converts many of the current text peepholes into rtl peepholes
(only peepholes involving cc0 are left). The primary reason for doing
this is that these cause corrupt frame information, as they manipulate
the stack pointer.

This patch is the result of this discussion:
http://gcc.gnu.org/ml/gcc-patches/2007-02/threads.html#00468
so that these peepholes now work for both m68k/ColdFire.

bye, Roman

200x-xx-xx  Roman Zippel <zippel@linux-m68k.org> 
 
	* config/m68k/m68k.c (strict_low_part_peephole_ok): Don't leave
	the basic block.
	* config/m68k/m68k.md (movsi_m68k): Allow certain constant when
	reload is completed.
	(peephole pattern): Convert most of them to RTL peephole pattern.

---

 gcc/config/m68k/m68k.c  |   16 +-
 gcc/config/m68k/m68k.md |  287 +++++++++++++++++++++++++-----------------------
 2 files changed, 162 insertions(+), 141 deletions(-)

Index: gcc/gcc/config/m68k/m68k.md
===================================================================
--- gcc.orig/gcc/config/m68k/m68k.md
+++ gcc/gcc/config/m68k/m68k.md
@@ -916,13 +916,22 @@
     }
 })
 
-;; General case of fullword move.  The register constraints
-;; force integer constants in range for a moveq to be reloaded
-;; if they are headed for memory.
-(define_insn ""
+;; General case of fullword move.
+(define_insn "*movsi_m68k"
   ;; Notes: make sure no alternative allows g vs g.
   ;; We don't allow f-regs since fixed point cannot go in them.
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<")
+        (match_operand:SI 1 "general_src_operand" "damSnT,n,i"))]
+  "!TARGET_COLDFIRE && reload_completed"
+{
+  return output_move_simode (operands);
+})
+
+;; Before reload is completed the register constraints
+;; force integer constants in range for a moveq to be reloaded
+;; if they are headed for memory.
+(define_insn "*movsi_m68k2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<")
         (match_operand:SI 1 "general_src_operand" "damSKT,n,i"))]
 
   "!TARGET_COLDFIRE"
@@ -7308,153 +7317,163 @@
 ;; and then is moved into an FP register.
 ;; But it is mainly intended to test the support for these optimizations.
 
-(define_peephole
+(define_peephole2
   [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
-   (set (match_operand:DF 0 "register_operand" "=f")
-	(match_operand:DF 1 "register_operand" "ad"))]
-  "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
-{
-  rtx xoperands[2];
-  xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
-  output_asm_insn ("move%.l %1,%@", xoperands);
-  output_asm_insn ("move%.l %1,%-", operands);
-  return "fmove%.d %+,%0";
-})
+   (set (match_operand:DF 0 "register_operand" "")
+	(match_operand:DF 1 "register_operand" ""))]
+  "FP_REG_P (operands[0]) && !FP_REG_P (operands[1])"
+  [(set (mem:SI (reg:SI SP_REG)) (match_dup 1))
+   (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 2))
+   (set (match_dup 0) (mem:DF (post_inc:SI (reg:SI SP_REG))))]
+  "split_di(operands + 1, 1, operands + 1, operands + 2);")
 
 ;; Optimize a stack-adjust followed by a push of an argument.
 ;; This is said to happen frequently with -msoft-float
 ;; when there are consecutive library calls.
 
-(define_peephole
+(define_peephole2
+  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
+   (set (match_operand:SF 0 "push_operand" "")
+	(match_operand:SF 1 "general_operand" ""))]
+  "!reg_mentioned_p (stack_pointer_rtx, operands[0])"
+  [(set (match_dup 0) (match_dup 1))]
+  "operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx);")
+
+(define_peephole2
   [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
-				 (match_operand:SI 0 "const_int_operand" "n")))
-   (set (match_operand:SF 1 "push_operand" "=m")
-	(match_operand:SF 2 "general_operand" "rmfF"))]
-  "INTVAL (operands[0]) >= 4
-   && ! reg_mentioned_p (stack_pointer_rtx, operands[2])"
-{
-  if (INTVAL (operands[0]) > 4)
-    {
-      rtx xoperands[2];
-      xoperands[0] = stack_pointer_rtx;
-      xoperands[1] = GEN_INT (INTVAL (operands[0]) - 4);
-      if (INTVAL (xoperands[1]) <= 8)
-	{
-	  if (!TARGET_COLDFIRE)
-	    output_asm_insn ("addq%.w %1,%0", xoperands);
-	  else
-	    output_asm_insn ("addq%.l %1,%0", xoperands);
-	}
-      else if (TUNE_CPU32 && INTVAL (xoperands[1]) <= 16)
-	{
-	  xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 8);
-	  output_asm_insn ("addq%.w #8,%0\;addq%.w %1,%0", xoperands);
-	}
-      else if (INTVAL (xoperands[1]) <= 0x7FFF)
-        {
-	  if (TUNE_68040)
-	    output_asm_insn ("add%.w %1,%0", xoperands);
-	  else if (MOTOROLA)
-	    output_asm_insn ("lea (%c1,%0),%0", xoperands);
-	  else
-	    output_asm_insn ("lea %0@(%c1),%0", xoperands);
-        }
-      else
-        output_asm_insn ("add%.l %1,%0", xoperands);
-    }
-  if (FP_REG_P (operands[2]))
-    return "fmove%.s %2,%@";
-  return "move%.l %2,%@";
+				 (match_operand:SI 0 "const_int_operand" "")))
+   (set (match_operand:SF 1 "push_operand" "")
+	(match_operand:SF 2 "general_operand" ""))]
+  "INTVAL (operands[0]) > 4
+   && !reg_mentioned_p (stack_pointer_rtx, operands[2])"
+  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 0)))
+   (set (match_dup 1) (match_dup 2))]
+{
+  operands[0] = GEN_INT (INTVAL (operands[0]) - 4);
+  operands[1] = replace_equiv_address (operands[1], stack_pointer_rtx);
 })
 
 ;; Speed up stack adjust followed by a fullword fixedpoint push.
+;; Constant operands need special care, as replacing a "pea X.w" with
+;; "move.l #X,(%sp)" is often not a win.
 
-(define_peephole
+;; Already done by the previous csa pass, left as reference.
+(define_peephole2
+  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))
+   (set (match_operand:SI 0 "push_operand" "")
+	(match_operand:SI 1 "general_operand" ""))]
+  "!reg_mentioned_p (stack_pointer_rtx, operands[1])"
+  [(set (match_dup 0) (match_dup 1))]
+  "operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx);")
+
+;; Try to use moveq, after stack push has been changed into a simple move.
+(define_peephole2
+  [(match_scratch:SI 2 "d")
+   (set (match_operand:SI 0 "memory_operand" "")
+	(match_operand:SI 1 "const_int_operand" ""))]
+  "GET_CODE (XEXP (operands[0], 0)) != PRE_DEC
+   && INTVAL (operands[1]) != 0
+   && IN_RANGE (INTVAL (operands[1]), -0x80, 0x7f)
+   && !valid_mov3q_const (INTVAL (operands[1]))"
+  [(set (match_dup 2) (match_dup 1))
+   (set (match_dup 0) (match_dup 2))])
+
+;; This sequence adds an instruction, but is two bytes shorter.
+(define_peephole2
+  [(match_scratch:SI 2 "d")
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 12)))
+   (set (match_operand:SI 0 "push_operand" "")
+	(match_operand:SI 1 "const_int_operand" ""))]
+  "INTVAL (operands[1]) != 0
+   && IN_RANGE (INTVAL (operands[1]), -0x80, 0x7f)
+   && !valid_mov3q_const (INTVAL (operands[1]))"
+  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 8)))
+   (set (match_dup 2) (match_dup 1))
+   (set (match_dup 0) (match_dup 2))]
+  "operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx);")
+
+;; Changing pea X.w into a move.l is no real win here.
+(define_peephole2
   [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
-				 (match_operand:SI 0 "const_int_operand" "n")))
-   (set (match_operand:SI 1 "push_operand" "=m")
-	(match_operand:SI 2 "general_operand" "g"))]
-  "INTVAL (operands[0]) >= 4
-   && ! reg_mentioned_p (stack_pointer_rtx, operands[2])"
-{
-  if (INTVAL (operands[0]) > 4)
-    {
-      rtx xoperands[2];
-      xoperands[0] = stack_pointer_rtx;
-      xoperands[1] = GEN_INT (INTVAL (operands[0]) - 4);
-      if (INTVAL (xoperands[1]) <= 8)
-	{
-	  if (!TARGET_COLDFIRE)
-	    output_asm_insn ("addq%.w %1,%0", xoperands);
-	  else
-	    output_asm_insn ("addq%.l %1,%0", xoperands);
-	}
-      else if (TUNE_CPU32 && INTVAL (xoperands[1]) <= 16)
-	{
-	  xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 8);
-	  output_asm_insn ("addq%.w #8,%0\;addq%.w %1,%0", xoperands);
-	}
-      else if (INTVAL (xoperands[1]) <= 0x7FFF)
-        {
-	  if (TUNE_68040)
-	    output_asm_insn ("add%.w %1,%0", xoperands);
-	  else if (MOTOROLA)
-	    output_asm_insn ("lea (%c1,%0),%0", xoperands);
-	  else
-	    output_asm_insn ("lea %0@(%c1),%0", xoperands);
-        }
-      else
-        output_asm_insn ("add%.l %1,%0", xoperands);
-    }
-  if (operands[2] == const0_rtx)
-    return "clr%.l %@";
-  return "move%.l %2,%@";
+				 (match_operand:SI 0 "const_int_operand" "")))
+   (set (match_operand:SI 1 "push_operand" "")
+	(match_operand:SI 2 "general_operand" ""))]
+  "INTVAL (operands[0]) > 4
+   && !reg_mentioned_p (stack_pointer_rtx, operands[2])
+   && !(CONST_INT_P (operands[2]) && INTVAL (operands[2]) != 0
+	&& IN_RANGE (INTVAL (operands[2]), -0x8000, 0x7fff)
+	&& !valid_mov3q_const (INTVAL (operands[2])))"
+  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_dup 0)))
+   (set (match_dup 1) (match_dup 2))]
+{
+  operands[0] = GEN_INT (INTVAL (operands[0]) - 4);
+  operands[1] = replace_equiv_address (operands[1], stack_pointer_rtx);
+})
+
+;; Speed up pushing a single byte/two bytes but leaving four bytes of space
+;; (which differs slightly between m680x0 and ColdFire).
+
+(define_peephole2
+  [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -4)))
+   (set (match_operand:QI 0 "memory_operand" "")
+	(match_operand:QI 1 "register_operand" ""))]
+  "!reg_mentioned_p (stack_pointer_rtx, operands[1])
+   && GET_CODE (XEXP (operands[0], 0)) == PLUS
+   && rtx_equal_p (XEXP (XEXP (operands[0], 0), 0), stack_pointer_rtx)
+   && CONST_INT_P (XEXP (XEXP (operands[0], 0), 1))
+   && INTVAL (XEXP (XEXP (operands[0], 0), 1)) == 3"
+  [(set (match_dup 0) (match_dup 1))]
+{
+  rtx addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
+  operands[0] = adjust_automodify_address (operands[0], SImode, addr, -3);
+  operands[1] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
+})
+
+(define_peephole2
+  [(set (match_operand:QI 0 "push_operand" "")
+	(match_operand:QI 1 "register_operand" ""))
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -3)))]
+  "!reg_mentioned_p (stack_pointer_rtx, operands[1])"
+  [(set (match_dup 0) (match_dup 1))]
+{
+  operands[0] = adjust_automodify_address (operands[0], SImode,
+					   XEXP (operands[0], 0), -3);
+  operands[1] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
+})
+
+(define_peephole2
+  [(set (match_operand:HI 0 "push_operand" "")
+	(match_operand:HI 1 "register_operand" ""))
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -2)))]
+  "!reg_mentioned_p (stack_pointer_rtx, operands[1])"
+  [(set (match_dup 0) (match_dup 1))]
+{
+  operands[0] = adjust_automodify_address (operands[0], SImode,
+					   XEXP (operands[0], 0), -2);
+  operands[1] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
 })
 
-;; Speed up pushing a single byte but leaving four bytes of space.
-
-(define_peephole
-  [(set (mem:QI (pre_dec:SI (reg:SI SP_REG)))
-	(match_operand:QI 1 "general_operand" "dami"))
-   (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (const_int 2)))]
-  "! reg_mentioned_p (stack_pointer_rtx, operands[1])"
-{
-  rtx xoperands[4];
-
-  if (GET_CODE (operands[1]) == REG)
-    return "move%.l %1,%-";
+;; Optimize a series of strict_low_part assignments
 
-  xoperands[1] = operands[1];
-  xoperands[2]
-    = gen_rtx_MEM (QImode, plus_constant (stack_pointer_rtx, 3));
-  xoperands[3] = stack_pointer_rtx;
-  if (!TARGET_COLDFIRE)
-    output_asm_insn ("subq%.w #4,%3\;move%.b %1,%2", xoperands);
-  else
-    output_asm_insn ("subq%.l #4,%3\;move%.b %1,%2", xoperands);
-  return "";
-})
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(const_int 0))
+   (set (strict_low_part (match_operand:HI 1 "register_operand" ""))
+	(match_operand:HI 2 "general_operand" ""))]
+  "REGNO (operands[0]) == REGNO (operands[1])
+   && strict_low_part_peephole_ok (HImode, insn, operands[0])"
+  [(set (strict_low_part (match_dup 1)) (match_dup 2))]
+  "")
 
-(define_peephole
-  [(set (match_operand:SI 0 "register_operand" "=d")
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
 	(const_int 0))
-   (set (strict_low_part (subreg:HI (match_dup 0) 2))
-	(match_operand:HI 1 "general_operand" "rmn"))]
-  "strict_low_part_peephole_ok (HImode, prev_nonnote_insn (insn), operands[0])"
-{
-  if (GET_CODE (operands[1]) == CONST_INT)
-    {
-      if (operands[1] == const0_rtx
-	  && (DATA_REG_P (operands[0])
-	      || GET_CODE (operands[0]) == MEM)
-	  /* clr insns on 68000 read before writing.  */
-	  && ((TARGET_68010 || TARGET_COLDFIRE)
-	      || !(GET_CODE (operands[0]) == MEM
-		   && MEM_VOLATILE_P (operands[0]))))
-	return "clr%.w %0";
-    }
-  return "move%.w %1,%0";
-})
+   (set (strict_low_part (match_operand:QI 1 "register_operand" ""))
+	(match_operand:QI 2 "general_operand" ""))]
+  "REGNO (operands[0]) == REGNO (operands[1])
+   && strict_low_part_peephole_ok (QImode, insn, operands[0])"
+  [(set (strict_low_part (match_dup 1)) (match_dup 2))]
+  "")
 
 ;; dbCC peepholes
 ;;
Index: gcc/gcc/config/m68k/m68k.c
===================================================================
--- gcc.orig/gcc/config/m68k/m68k.c
+++ gcc/gcc/config/m68k/m68k.c
@@ -3959,14 +3959,18 @@ bool
 strict_low_part_peephole_ok (enum machine_mode mode, rtx first_insn,
                              rtx target)
 {
-  rtx p;
+  rtx p = first_insn;
 
-  p = prev_nonnote_insn (first_insn);
-
-  while (p)
+  while ((p = PREV_INSN (p)))
     {
+      if (NOTE_INSN_BASIC_BLOCK_P (p))
+	return false;
+
+      if (NOTE_P (p))
+	continue;
+
       /* If it isn't an insn, then give up.  */
-      if (GET_CODE (p) != INSN)
+      if (!INSN_P (p))
 	return false;
 
       if (reg_set_p (target, p))
@@ -3996,8 +4000,6 @@ strict_low_part_peephole_ok (enum machin
 	  else
 	    return false;
 	}
-
-      p = prev_nonnote_insn (p);
     }
 
   return false;



More information about the Gcc-patches mailing list