This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFA] m68k output_move_double : use POST_INC instead of INDEX
- From: Philippe De Muyter <phdm at macqel dot be>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 18 Apr 2007 23:14:59 +0200
- Subject: [RFA] m68k output_move_double : use POST_INC instead of INDEX
Hi all,
the following replaces a reg+index addressing into a post_inc one in
output_move_double, when possible. This is especially useful with the
pic modes, e.g. -msep-data, where the adresses of the variables are never
constant, but always in an address-register. `output_move-double''s signature
needed to be changed, to get the `insn'.
OK to apply ?
example:
without patch with the patch
link.w %fp,#0 link.w %fp,#0
move.l %a5,-(%sp) move.l %a5,-(%sp)
move.l b@GOT(%a5),%a1 move.l b@GOT(%a5),%a1
move.l a@GOT(%a5),%a0 move.l a@GOT(%a5),%a0
move.l (%a1),%d0 | move.l (%a1)+,%d0
move.l 4(%a1),%d1 | move.l (%a1)+,%d1
move.l %d0,(%a0) | move.l %d0,(%a0)+
move.l %d1,4(%a0) | move.l %d1,(%a0)+
move.l (%sp)+,%a5 move.l (%sp)+,%a5
unlk %fp unlk %fp
rts rts
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c (revision 123959)
+++ gcc/config/m68k/m68k.c (working copy)
@@ -2440,7 +2440,7 @@
with operands OPERANDS. */
const char *
-output_move_double (rtx *operands)
+output_move_double (rtx insn, rtx *operands)
{
enum
{
@@ -2526,6 +2526,35 @@
optype1 = OFFSOP;
}
+ /* If an operand is a simple register indirect, and that the register
+ is dead afterwards, POST_INC is cheaper than register + offset. */
+
+ if (optype0 == OFFSOP && optype1 != PUSHOP)
+ {
+ rtx op0 = XEXP (operands[0], 0);
+
+ if (REG_P (op0) && find_reg_note (insn, REG_DEAD, op0)
+ && ! reg_overlap_mentioned_p (op0, operands[1]))
+ {
+ operands[0] = gen_rtx_MEM (GET_MODE (operands[0]),
+ gen_rtx_POST_INC (SImode, op0));
+ optype0 = POPOP;
+ }
+ }
+
+ if (optype1 == OFFSOP && optype0 != PUSHOP)
+ {
+ rtx op0 = XEXP (operands[1], 0);
+
+ if (REG_P (op0) && find_reg_note (insn, REG_DEAD, op0)
+ && ! reg_overlap_mentioned_p (op0, operands[0]))
+ {
+ operands[1] = gen_rtx_MEM (GET_MODE (operands[1]),
+ gen_rtx_POST_INC (SImode, op0));
+ optype1 = POPOP;
+ }
+ }
+
/* If an operand is an unoffsettable memory ref, find a register
we can increment temporarily to make it refer to the second word. */
Index: gcc/config/m68k/m68k.md
===================================================================
--- gcc/config/m68k/m68k.md (revision 123959)
+++ gcc/config/m68k/m68k.md (working copy)
@@ -157,7 +157,7 @@
{
if (FP_REG_P (operands[1]))
return "fmove%.d %f1,%0";
- return output_move_double (operands);
+ return output_move_double (insn, operands);
})
(define_insn "pushdi"
@@ -165,7 +165,7 @@
(match_operand:DI 1 "general_operand" "ro<>Fi"))]
""
{
- return output_move_double (operands);
+ return output_move_double (insn, operands);
})
;; We don't want to allow a constant operand for test insns because
@@ -193,7 +193,7 @@
xoperands[0] = operands[2];
xoperands[1] = operands[0];
- output_move_double (xoperands);
+ output_move_double (insn, xoperands);
cc_status.flags |= CC_REVERSED;
return "neg%.l %R2\;negx%.l %2";
}
@@ -1000,7 +1000,7 @@
else
return "fmove%.d %f1,%0";
}
- return output_move_double (operands);
+ return output_move_double (insn, operands);
})
(define_insn "movdf_cf_soft"
@@ -1008,7 +1008,7 @@
(match_operand:DF 1 "general_operand" "g,r"))]
"TARGET_COLDFIRE && !TARGET_COLDFIRE_FPU"
{
- return output_move_double (operands);
+ return output_move_double (insn, operands);
})
(define_insn "movdf_cf_hard"
@@ -1031,7 +1031,7 @@
case 3:
return "move%.l %R1,%-;move%.l %1,%-;fdmove%.d %+,%0";
case 4: case 5: case 6:
- return output_move_double (operands);
+ return output_move_double (insn, operands);
case 7:
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
REAL_VALUE_TO_TARGET_DOUBLE (r, l);
@@ -1119,7 +1119,7 @@
/* Must be memory destination. */
return "fmove%.x %f1,%0";
}
- return output_move_double (operands);
+ return output_move_double (insn, operands);
})
(define_insn ""
@@ -1158,14 +1158,14 @@
else
return "fmove%.x %f1,%0";
}
- return output_move_double (operands);
+ return output_move_double (insn, operands);
})
(define_insn ""
[(set (match_operand:XF 0 "nonimmediate_operand" "=r,g")
(match_operand:XF 1 "nonimmediate_operand" "g,r"))]
"! TARGET_68881 && TARGET_COLDFIRE"
- "* return output_move_double (operands);")
+ "* return output_move_double (insn, operands);")
(define_expand "movdi"
;; Let's see if it really still needs to handle fp regs, and, if so, why.
@@ -1212,14 +1212,14 @@
else
return "fmove%.d %f1,%0";
}
- return output_move_double (operands);
+ return output_move_double (insn, operands);
})
(define_insn ""
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,g")
(match_operand:DI 1 "general_operand" "g,r"))]
"TARGET_COLDFIRE"
- "* return output_move_double (operands);")
+ "* return output_move_double (insn, operands);")
;; Thus goes after the move instructions
;; because the move instructions are better (require no spilling)
Index: gcc/config/m68k/m68k-protos.h
===================================================================
--- gcc/config/m68k/m68k-protos.h (revision 123959)
+++ gcc/config/m68k/m68k-protos.h (working copy)
@@ -32,7 +32,7 @@
extern const char *output_move_qimode (rtx *);
extern const char *output_move_stricthi (rtx *);
extern const char *output_move_strictqi (rtx *);
-extern const char *output_move_double (rtx *);
+extern const char *output_move_double (rtx, rtx *);
extern const char *output_move_const_single (rtx *);
extern const char *output_move_const_double (rtx *);
extern const char *output_btst (rtx *, rtx, rtx, rtx, int);
--
Philippe De Muyter phdm at macqel dot be Tel +32 27029044
Macq Electronique SA rue de l'Aeronef 2 B-1140 Bruxelles Fax +32 27029077