[PATCH] Fix -fcompare-debug differences caused by caller-save (PR debug/42918)

Jakub Jelinek jakub@redhat.com
Tue Feb 16 16:53:00 GMT 2010


Hi!

As discussed in the PR, we have before IRA a CALL_INSN, followed
by DELETED_LABEL note, followed by some DEBUG_INSNs (those were initially
in a different bb whose label was that deleted label).
save_call_clobbered_regs wants to restore all pending regs at the end
of bb and does so after the last reload_insn_chain item in that bb.
With -g0 such last insn is the CALL (and thus the reg restores inherit
locus of the call), but with -g that is the last debug insn and the restores
are inserted after the last debug insn (thus also after the deleted label
note).  While locus inheritance in emit_insn_after ignores debug_insns,
it doesn't ignore notes and thus the restores with -g get no location.
We really need to restore after the DEBUG_INSNs, otherwise debug info
could be incorrect, so the following patch fixes it by moving any notes
in between the last real insn and the last debug insn in that case after
the last debug insn.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2010-02-16  Jakub Jelinek  <jakub@redhat.com>

	PR debug/42918
	* caller-save.c (save_call_clobbered_regs): If BB ends with
	a DEBUG_INSN, move any notes in between last real insn and the last
	DEBUG_INSN after the last DEBUG_INSN.

	* gcc.dg/pr42918.c: New test.

--- gcc/caller-save.c.jj	2010-02-15 10:36:00.000000000 +0100
+++ gcc/caller-save.c	2010-02-15 19:11:27.000000000 +0100
@@ -754,7 +754,7 @@ setup_save_areas (void)
 void
 save_call_clobbered_regs (void)
 {
-  struct insn_chain *chain, *next;
+  struct insn_chain *chain, *next, *last = NULL;
   enum machine_mode save_mode [FIRST_PSEUDO_REGISTER];
 
   /* Computed in mark_set_regs, holds all registers set by the current
@@ -861,6 +861,7 @@ save_call_clobbered_regs (void)
 		if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
 		  n_regs_saved++;
 	    }
+          last = chain;
 	}
       else if (DEBUG_INSN_P (insn) && n_regs_saved)
 	mark_referenced_regs (&PATTERN (insn),
@@ -874,6 +875,36 @@ save_call_clobbered_regs (void)
 	     remain saved.  If the last insn in the block is a JUMP_INSN, put
 	     the restore before the insn, otherwise, put it after the insn.  */
 
+	  if (DEBUG_INSN_P (insn) && last && last->block == chain->block)
+	    {
+	      rtx ins, prev;
+	      basic_block bb = BLOCK_FOR_INSN (insn);
+
+	      /* When adding hard reg restores after a DEBUG_INSN, move
+		 all notes between last real insn and this DEBUG_INSN after
+		 the DEBUG_INSN, otherwise we could get code
+		 -g/-g0 differences.  */
+	      for (ins = PREV_INSN (insn); ins != last->insn; ins = prev)
+		{
+		  prev = PREV_INSN (ins);
+		  if (NOTE_P (ins))
+		    {
+		      NEXT_INSN (prev) = NEXT_INSN (ins);
+		      PREV_INSN (NEXT_INSN (ins)) = prev;
+		      PREV_INSN (ins) = insn;
+		      NEXT_INSN (ins) = NEXT_INSN (insn);
+		      NEXT_INSN (insn) = ins;
+		      if (NEXT_INSN (ins))
+			PREV_INSN (NEXT_INSN (ins)) = ins;
+                      if (BB_END (bb) == insn)
+			BB_END (bb) = ins;
+		    }
+		  else
+		    gcc_assert (DEBUG_INSN_P (ins));
+		}
+	    }
+	  last = NULL;
+
 	  if (n_regs_saved)
 	    for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
 	      if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
--- gcc/testsuite/gcc.dg/pr42918.c.jj	2010-02-15 21:54:13.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr42918.c	2010-02-15 21:53:47.000000000 +0100
@@ -0,0 +1,21 @@
+/* PR debug/42918 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcompare-debug -ftracer" } */
+
+extern int fi (void);
+extern void fv (void);
+
+int
+f (int i, int j)
+{
+  if (!j)
+    {
+      fv ();
+      goto lab;
+    }
+  i = fi ();
+  if (i == j)
+    fv ();
+lab:
+  return i;
+}

	Jakub



More information about the Gcc-patches mailing list