This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR23392, regrename and REG_FRAME_RELATED_EXPR notes
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 8 Nov 2005 21:55:55 +1030
- Subject: [PATCH] PR23392, regrename and REG_FRAME_RELATED_EXPR notes
:ADDPATCH rtl-optimization:
This patch teaches regrename to update REG_FRAME_RELATED_EXPR notes when
the associated insn has its registers renumbered. The trick is to place
the location of register rtx in such notes in the def/use chains that
regrename creates.
REG_FRAME_RELATED_EXPR notes invariably consist of a SET (or a PARALLEL
containing SETs). We mark the source regs just after marking reg reads
in the associated instruction, and importantly, before closing def/use
chains for dead regs. (If it was ever possible to have a REG_INC and
REG_DEAD note for the same reg in one insn, then this patch fixes a bug
with REG_INC notes too.) Conveniently, regrename.c:scan_rtx correctly
sets up the operand type (OP_IN or OP_OUT) for a SET, so we can use the
same scan_rtx call as for REG_INC notes. We don't need to specially
look at just the source part.
Destination regs of SETs in REG_FRAME_RELATED_EXPR notes are marked
after we have opened new chains for reg writes in the insn. We can't
treat them as a real write (using mark_write), because we don't want to
create new def/use chains for them. So I added a new action,
mark_access, that marks OP_OUT registers as being read. This puts the
destination reg of the note in the newly opened def/use chain. As for
mark_write, mark_access should not do anything in scan_rtx_address
because address registers have already been marked when looking for
REG_FRAME_RELATED_EXPR source registers.
I've verified that this patch cures the foward-1.m failure on
powerpc64-linux, and am currently bootstrapping and regression
testing this version. OK to apply assuming all goes well?
* PR rtl-optimization/23392
* regrename.c (enum scan_actions) Add mark_access.
(scan_actions_name): Ditto.
(scan_rtx_reg): Handle mark_access.
(scan_rtx_address): Do nothing for mark_access.
(build_def_use): Mark source registers in REG_FRAME_RELATED_EXPR
and regs in REG_INC notes before closing chains for dead regs.
Mark destination regs in REG_FRAME_RELATED_EXPR notes after
opening chains for new writes.
Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c (revision 106631)
+++ gcc/regrename.c (working copy)
@@ -58,7 +58,11 @@ enum scan_actions
terminate_write,
terminate_dead,
mark_read,
- mark_write
+ mark_write,
+ /* mark_access is for marking the destination regs in
+ REG_FRAME_RELATED_EXPR notes (as if they were read) so that the
+ note is updated properly. */
+ mark_access
};
static const char * const scan_actions_name[] =
@@ -68,7 +72,8 @@ static const char * const scan_actions_n
"terminate_write",
"terminate_dead",
"mark_read",
- "mark_write"
+ "mark_write",
+ "mark_access"
};
static struct obstack rename_obstack;
@@ -408,8 +413,7 @@ scan_rtx_reg (rtx insn, rtx *loc, enum r
return;
}
- if ((type == OP_OUT && action != terminate_write)
- || (type != OP_OUT && action == terminate_write))
+ if ((type == OP_OUT) != (action == terminate_write || action == mark_access))
return;
for (p = &open_chains; *p;)
@@ -438,7 +442,7 @@ scan_rtx_reg (rtx insn, rtx *loc, enum r
continue;
}
- if (action == mark_read)
+ if (action == mark_read || action == mark_access)
{
gcc_assert (exact_match);
@@ -509,7 +513,7 @@ scan_rtx_address (rtx insn, rtx *loc, en
const char *fmt;
int i, j;
- if (action == mark_write)
+ if (action == mark_write || action == mark_access)
return;
switch (code)
@@ -866,17 +870,19 @@ build_def_use (basic_block bb)
scan_rtx (insn, loc, cl, mark_read, type, 0);
}
- /* Step 4: Close chains for registers that die here.
- Also record updates for REG_INC notes. */
+ /* Step 3B: Record updates for regs in REG_INC notes, and
+ source regs in REG_FRAME_RELATED_EXPR notes. */
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- {
- if (REG_NOTE_KIND (note) == REG_DEAD)
- scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
- OP_IN, 0);
- else if (REG_NOTE_KIND (note) == REG_INC)
- scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read,
- OP_INOUT, 0);
- }
+ if (REG_NOTE_KIND (note) == REG_INC
+ || REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
+ scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read,
+ OP_INOUT, 0);
+
+ /* Step 4: Close chains for registers that die here. */
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_DEAD)
+ scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
+ OP_IN, 0);
/* Step 4B: If this is a call, any chain live at this point
requires a caller-saved reg. */
@@ -949,6 +955,13 @@ build_def_use (basic_block bb)
recog_op_alt[opn][alt].earlyclobber);
}
+ /* Step 6B: Record destination regs in REG_FRAME_RELATED_EXPR
+ notes for update. */
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
+ scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_access,
+ OP_INOUT, 0);
+
/* Step 7: Close chains for registers that were never
really used here. */
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
--
Alan Modra
IBM OzLabs - Linux Technology Centre