This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [m68k 09/13] Convert some text peepholes
Hi,
On Tue, 6 Feb 2007, Richard Sandiford wrote:
> Yes. The 'R' constraint is an extra constraint that is allowed to be
> the source of a memory move. It applies over and above what earlier
> ColdFire targets allowed there. In other words, the 'R' stuff allows
> _more_ alternatives, while the use of 'K' in the 680x0 insns is
> specifically there to allow _fewer_ alternatives.
>
> (mov3q is like a memory version of moveq, and lets you move constants
> directly to offset addresses, which ColdFire's move.foo doesn't.)
ColdFire addressing modes are confusing. :)
> >> >> One thing the patch I posted did was use adjust_address* family
> >> >> of functions to create the new MEM. Hard-coding the MEM in the
> >> >> output pattern will lose the alias information on the original MEM
> >> >> (including that set up by get_frame_mem). The same comment applies
> >> >> to the other peepholes.
> >> >
> >> > Below is new version of the patch which does this, I also added the CF
> >> > variant for a single byte push. (Ligthly tested.)
> >>
> >> It still contains hard-coded MEMs. E.g.:
> >
> > That one looks pretty much like in your version. :)
>
> Oops ;) Serves me right for going off memory.
>
> So have you incorporated all the address-changing stuff that was
> in the patch I posted? Did you do it the same way, or differently?
It's pretty much the same way, I'm avoiding generating a new pre_dec if
possible:
addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
operands[2] = adjust_automodify_address (operands[0], SImode, addr, -3);
and just do:
operands[0] = adjust_automodify_address (operands[0], SImode,
XEXP (operands[0], 0), -2);
(If I read the source correctly using NULL there does the same.)
Below is hopefully the final patch, it tries now to avoid changing "pea
X.w" into "move.l" (it can still happen, but only if it's a clear win) and
also tries to use moveq if a scratch register is available.
bye, Roman
---
gcc/config/m68k/m68k.c | 18 +--
gcc/config/m68k/m68k.h | 6 -
gcc/config/m68k/m68k.md | 285 +++++++++++++++++++++++++-----------------------
3 files changed, 163 insertions(+), 146 deletions(-)
Index: egcs/gcc/config/m68k/m68k.h
===================================================================
--- egcs.orig/gcc/config/m68k/m68k.h
+++ egcs/gcc/config/m68k/m68k.h
@@ -773,10 +773,6 @@ __transfer_from_trampoline () \
(DATA_REGNO_P (REGNO) \
|| DATA_REGNO_P (reg_renumber[REGNO]))
-#define REGNO_OK_FOR_FP_P(REGNO) \
- (FP_REGNO_P (REGNO) \
- || FP_REGNO_P (reg_renumber[REGNO]))
-
/* Now macros that check whether X is a register and also,
strictly, whether it is in a specified class.
@@ -788,7 +784,7 @@ __transfer_from_trampoline () \
#define DATA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_DATA_P (REGNO (X)))
/* 1 if X is an fp register. */
-#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X)))
+#define FP_REG_P(X) (REG_P (X) && FP_REGNO_P (REGNO (X)))
/* 1 if X is an address register */
#define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X)))
Index: egcs/gcc/config/m68k/m68k.md
===================================================================
--- egcs.orig/gcc/config/m68k/m68k.md
+++ egcs/gcc/config/m68k/m68k.md
@@ -653,13 +653,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.
+;; General case of fullword move.
(define_insn ""
;; 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" "daymSnT,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 ""
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<")
(match_operand:SI 1 "general_src_operand" "daymSKT,n,i"))]
"!TARGET_COLDFIRE"
@@ -6634,153 +6643,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: egcs/gcc/config/m68k/m68k.c
===================================================================
--- egcs.orig/gcc/config/m68k/m68k.c
+++ egcs/gcc/config/m68k/m68k.c
@@ -2485,7 +2485,7 @@ force_mode (enum machine_mode mode, rtx
static int
fp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
- return reg_renumber && FP_REG_P (op);
+ return FP_REG_P (op);
}
/* Emit insns to move operands[1] into operands[0].
@@ -3439,14 +3439,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))
@@ -3476,8 +3480,6 @@ strict_low_part_peephole_ok (enum machin
else
return false;
}
-
- p = prev_nonnote_insn (p);
}
return false;