This fixes a lot of confusion in rs6000_frame_related call arguments.
At the time rs6000_frame_related first appeared, the prologue only
used sp_reg_rtx (r1) or frame_ptr_rtx (r12) as frame_reg_rtx to access
register save slots. If r12 was used, it was necessary to add a note
that gave the equivalent offset relative to r1.
Nowadays, r11 is used as frame_reg_rtx too, when abiv4 and saving regs
out-of-line with a large frame. When that change was made the calls
to rs6000_frame_related were not updated. So rs6000_frame_related
won't replace r11 in register save rtl. As it happens this isn't a
bug because when you look closely, out-of-line saves are disabled with
a large frame! A fix for that will come later in this patch series.
I also optimize rs6000_frame_related a little to save generating
duplicate rtl.
* config/rs6000/rs6000.c (rs6000_frame_related): Don't emit a
REG_FRAME_RELATED_EXPR note when the instruction exactly matches
the replacement.
(emit_frame_save): Delete frame_ptr param. Rename total_size to
frame_reg_to_sp.
(rs6000_emit_prologue): Add sp_off. Update rs6000_frame_related
and emit_frame_save calls. Cope with possibly missing note.
diff -urp gcc-alan1/gcc/config/rs6000/rs6000.c
gcc-alan2/gcc/config/rs6000/rs6000.c
--- gcc-alan1/gcc/config/rs6000/rs6000.c2012-04-16 11:57:37.282242636
+0930
+++ gcc-alan2/gcc/config/rs6000/rs6000.c2012-04-16 11:58:01.50108
+0930
@@ -18751,7 +18751,10 @@ output_probe_stack_range (rtx reg1, rtx
with (plus:P (reg 1) VAL), and with REG2 replaced with RREG if REG2
is not NULL. It would be nice if dwarf2out_frame_debug_expr could
deduce these equivalences by itself so it wasn't necessary to hold
- its hand so much. */
+ its hand so much. Don't be tempted to always supply d2_f_d_e with
+ the actual cfa register, ie. r31 when we are using a hard frame
+ pointer. That fails when saving regs off r1, and sched moves the
+ r31 setup past the reg saves. */
static rtx
rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
@@ -18759,6 +18762,25 @@ rs6000_frame_related (rtx insn, rtx reg,
{
rtx real, temp;
+ if (REGNO (reg) == 1 && reg2 == NULL_RTX)
+{
+ /* No need for any replacement. Just set RTX_FRAME_RELATED_P. */
+ int i;
+
+ gcc_checking_assert (val == 0);
+ real = PATTERN (insn);
+ if (GET_CODE (real) == PARALLEL)
+ for (i = 0; i < XVECLEN (real, 0); i++)
+ if (GET_CODE (XVECEXP (real, 0, i)) == SET)
+ {
+ rtx set = XVECEXP (real, 0, i);
+
+ RTX_FRAME_RELATED_P (set) = 1;
+ }
+ RTX_FRAME_RELATED_P (insn) = 1;
+ return insn;
+}
+
/* copy_rtx will not make unique copies of registers, so we need to
ensure we don't have unwanted sharing here. */
if (reg == reg2)
@@ -18772,10 +18794,13 @@ rs6000_frame_related (rtx insn, rtx reg,
if (reg2 != NULL_RTX)
real = replace_rtx (real, reg2, rreg);
- real = replace_rtx (real, reg,
- gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode,
- STACK_POINTER_REGNUM),
- GEN_INT (val)));
+ if (REGNO (reg) == 1)
+gcc_checking_assert (val == 0);
+ else
+real = replace_rtx (real, reg,
+ gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode,
+ STACK_POINTER_REGNUM),
+ GEN_INT (val)));
/* We expect that 'real' is either a SET or a PARALLEL containing
SETs (and possibly other stuff). In a PARALLEL, all the SETs
@@ -18893,8 +18918,8 @@ generate_set_vrsave (rtx reg, rs6000_sta
Save REGNO into [FRAME_REG + OFFSET] in mode MODE. */
static rtx
-emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
-unsigned int regno, int offset, HOST_WIDE_INT total_size)
+emit_frame_save (rtx frame_reg, enum machine_mode mode,
+unsigned int regno, int offset, HOST_WIDE_INT frame_reg_to_sp)
{
rtx reg, offset_rtx, insn, mem, addr, int_rtx;
rtx replacea, replaceb;
@@ -18930,7 +18955,8 @@ emit_frame_save (rtx frame_reg, rtx fram
insn = emit_move_insn (mem, reg);
- return rs6000_frame_related (insn, frame_ptr, total_size, replacea,
replaceb);
+ return rs6000_frame_related (insn, frame_reg, frame_reg_to_sp,
+ replacea, replaceb);
}
/* Emit an offset memory reference suitable for a frame store, while
@@ -19295,7 +19321,9 @@ rs6000_emit_prologue (void)
int using_static_chain_p = (cfun->static_chain_decl != NULL_TREE
&& df_regs_ever_live_p (STATIC_CHAIN_REGNUM)
&& call_used_regs[STATIC_CHAIN_REGNUM]);
+ /* Offset to top of frame for frame_reg and sp respectively. */
HOST_WIDE_INT frame_off = 0;
+ HOST_WIDE_INT sp_off = 0;
if (flag_st