[PATCH] PR23392, regrename and REG_FRAME_RELATED_EXPR notes

Alan Modra amodra@bigpond.net.au
Tue Nov 8 11:26:00 GMT 2005


: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



More information about the Gcc-patches mailing list