This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[vta] regstack fixes for var-tracking-assignments


Most of the changes I'd made to regstack.c to avoid code changes with
debug insns were obsoleted by other changes elsewhere.  However,
references to floating point stack registers in debug insns weren't
being updated at all.  This patch fixes this.

It also fixes a codegen change caused by debug insns in the beginning
of a BB.  reg-stack uses the reg-stack requirements of the first insn
in the BB that has reg-stack requirements to determine how the
reg-stack should look like at the entry point of the BB.  If there was
a debug insns that referenced stack registers before, its requirements
(none) would be taken into account *instead of* those of the first
active insn.  Oops.

This patch processes the initial debug insns after determining the
entry point stack layout.  I guess I could try to come up with some
clever means to link the debug insns such that I wouldn't have to
count them and potentially iterate over the entire sequence, but I
don't think it's worth it.

I'm going to check this in the vta branch soon.

for  gcc/ChangeLog.vta
from  Alexandre Oliva  <aoliva@redhat.com>

	* reg-stack.c (subst_stack_regs_in_debug_insn): New.
	(subst_stack_regs_pat): Revert.
	(convert_regs_1): Replace regs in debug insns.  Deal with
	debug insns before first active insn.

Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c.orig	2007-11-05 05:06:18.000000000 -0200
+++ gcc/reg-stack.c	2007-11-05 05:31:55.000000000 -0200
@@ -310,7 +310,7 @@ stack_regs_mentioned (const_rtx insn)
   unsigned int uid, max;
   int test;
 
-  if (! INSN_P (insn) /* || DEBUG_INSN_P (insn) */ || !stack_regs_mentioned_data)
+  if (! INSN_P (insn) || !stack_regs_mentioned_data)
     return 0;
 
   uid = INSN_UID (insn);
@@ -1328,6 +1328,30 @@ compare_for_stack_reg (rtx insn, stack r
     }
 }
 
+/* Substitute new registers in LOC, which is part of a debug insn.
+   REGSTACK is the current register layout.  */
+
+static int
+subst_stack_regs_in_debug_insn (rtx *loc, void *data)
+{
+  rtx *tloc = get_true_reg (loc);
+  stack regstack = (stack)data;
+  int hard_regno;
+
+  if (!STACK_REG_P (*tloc))
+    return 0;
+
+  if (tloc != loc)
+    return 0;
+
+  hard_regno = get_hard_regnum (regstack, *loc);
+  gcc_assert (hard_regno >= FIRST_STACK_REG);
+
+  replace_reg (loc, hard_regno);
+
+  return -1;
+}
+
 /* Substitute new registers in PAT, which is part of INSN.  REGSTACK
    is the current register layout.  Return whether a control flow insn
    was deleted in the process.  */
@@ -1362,14 +1386,7 @@ subst_stack_regs_pat (rtx insn, stack re
       break;
 
     case VAR_LOCATION:
-      for (dest = &REG_NOTES (insn); *dest; dest = &XEXP (*dest, 1))
-	if (REG_NOTE_KIND (*dest) == REG_DEAD
-	    && STACK_REG_P (*(src = &XEXP (*dest, 0)))
-	    && TEST_HARD_REG_BIT (regstack->reg_set, REGNO (*src)))
-	  /* ??? This is not right.  We want to *avoid* emitting the
-	     pop and the corresponding push.  */
-	  emit_pop_insn (insn, regstack, *src, EMIT_AFTER);
-      break;
+      gcc_unreachable ();
 
     case CLOBBER:
       {
@@ -2865,6 +2882,7 @@ convert_regs_1 (basic_block block)
   int reg;
   rtx insn, next;
   bool control_flow_insn_deleted = false;
+  int debug_insns_with_starting_stack = 0;
 
   any_malformed_asm = false;
 
@@ -2917,8 +2935,25 @@ convert_regs_1 (basic_block block)
 
       /* Don't bother processing unless there is a stack reg
 	 mentioned or if it's a CALL_INSN.  */
-      if (stack_regs_mentioned (insn)
-	  || CALL_P (insn))
+      if (DEBUG_INSN_P (insn))
+	{
+	  if (starting_stack_p)
+	    debug_insns_with_starting_stack++;
+	  else
+	    {
+	      for_each_rtx (&PATTERN (insn), subst_stack_regs_in_debug_insn,
+			    &regstack);
+
+	      /* Nothing must ever die at a debug insn.  If something
+		 is referenced in it that becomes dead, it should have
+		 died before and the reference in the debug insn
+		 should have been removed so as to avoid changing code
+		 generation.  */
+	      gcc_assert (!REG_NOTES (insn));
+	    }
+	}
+      else if (stack_regs_mentioned (insn)
+	       || CALL_P (insn))
 	{
 	  if (dump_file)
 	    {
@@ -2932,6 +2967,24 @@ convert_regs_1 (basic_block block)
     }
   while (next);
 
+  if (debug_insns_with_starting_stack)
+    {
+      /* Since it's the first non-debug instruction that determines
+	 the stack requirements of the current basic block, we refrain
+	 from updating debug insns before it in the loop above, and
+	 fix them up here.  */
+      for (insn = BB_HEAD (block); debug_insns_with_starting_stack;
+	   insn = NEXT_INSN (insn))
+	{
+	  if (!DEBUG_INSN_P (insn))
+	    continue;
+
+	  debug_insns_with_starting_stack--;
+	  for_each_rtx (&PATTERN (insn), subst_stack_regs_in_debug_insn,
+			&bi->stack_in);
+	}
+    }
+
   if (dump_file)
     {
       fprintf (dump_file, "Expected live registers [");
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
FSF Latin America Board Member         http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]