diff mbox

Fix regression caused by my var-tracking.c note fix (PR bootstrap/55615, PR middle-end/43631)

Message ID 20121207160159.GZ2315@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Dec. 7, 2012, 4:01 p.m. UTC
Hi!

The barriers pass wants to put a BARRIER from after a noreturn call in
between the call and NOTE_INSN_CALL_ARG_LOCATION, but as the note no longer
is BB_END (the call is), it happens to extend BB_END to the BARRIER which
later breaks the md reorg pass.

dwarf2out.c seems to handle a BARRIER in between the call and related
NOTE_INSN_CALL_ARG_LOCATION resp. NOTE_INSN_VAR_LOCATION/c just fine,
only NOTE_INSN_CALL_ARG_LOCATION needs to go first.

My first fix was to the barriers pass to allow NOTE_INSN_CALL_ARG_LOCATION
in between the CALL_INSN and BARRIER, but I think I prefer to put the
BARRIER first from the beginning.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2012-12-07  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/43631
	PR bootstrap/55615
	* var-tracking.c (emit_note_insn_var_location): If insn is followed
	by BARRIER, put note after the BARRIER.
	(next_non_note_insn_var_location): Skip over BARRIERs.
	(emit_notes_in_bb): If call is followed by BARRIER, put note after
	the BARRIER.

	* g++.dg/other/pr43631.C: New test.


	Jakub
diff mbox

Patch

--- gcc/var-tracking.c.jj	2012-12-06 15:37:30.000000000 +0100
+++ gcc/var-tracking.c	2012-12-07 13:00:32.713116052 +0100
@@ -8538,7 +8538,10 @@  emit_note_insn_var_location (void **varp
 
   if (where != EMIT_NOTE_BEFORE_INSN)
     {
-      note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
+      rtx after = insn;
+      while (NEXT_INSN (after) && BARRIER_P (NEXT_INSN (after)))
+	after = NEXT_INSN (after);
+      note = emit_note_after (NOTE_INSN_VAR_LOCATION, after);
       if (where == EMIT_NOTE_AFTER_CALL_INSN)
 	NOTE_DURING_CALL_P (note) = true;
     }
@@ -8892,9 +8895,11 @@  next_non_note_insn_var_location (rtx ins
   while (insn)
     {
       insn = NEXT_INSN (insn);
-      if (insn == 0
-	  || !NOTE_P (insn)
-	  || NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION)
+      if (insn == 0)
+	break;
+      if (BARRIER_P (insn))
+	continue;
+      if (!NOTE_P (insn) || NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION)
 	break;
     }
 
@@ -8923,7 +8928,7 @@  emit_notes_in_bb (basic_block bb, datafl
 	    dataflow_set_clear_at_call (set);
 	    emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars);
 	    {
-	      rtx arguments = mo->u.loc, *p = &arguments, note;
+	      rtx arguments = mo->u.loc, *p = &arguments, note, after;
 	      while (*p)
 		{
 		  XEXP (XEXP (*p, 0), 1)
@@ -8947,7 +8952,10 @@  emit_notes_in_bb (basic_block bb, datafl
 		  else
 		    *p = XEXP (*p, 1);
 		}
-	      note = emit_note_after (NOTE_INSN_CALL_ARG_LOCATION, insn);
+	      after = insn;
+	      while (NEXT_INSN (after) && BARRIER_P (NEXT_INSN (after)))
+		after = NEXT_INSN (after);
+	      note = emit_note_after (NOTE_INSN_CALL_ARG_LOCATION, after);
 	      NOTE_VAR_LOCATION (note) = arguments;
 	      /* If insn is BB_END of some bb, make sure the note
 		 doesn't have BLOCK_FOR_INSN set.  The notes don't
--- gcc/testsuite/g++.dg/other/pr43631.C.jj	2012-12-07 12:12:35.557226106 +0100
+++ gcc/testsuite/g++.dg/other/pr43631.C	2012-12-07 12:13:48.170822223 +0100
@@ -0,0 +1,15 @@ 
+// PR middle-end/43631
+// { dg-do compile }
+// { dg-options "-g -O2" }
+// { dg-additional-options "-mtune=atom" { target i?86-*-* x86_64-*-* } }
+
+typedef void (*T) ();
+struct S { T t; };
+void bar (T) __attribute__ ((__noreturn__));
+S *p;
+
+void
+foo ()
+{
+  try { bar (p->t); } catch (...) { throw 1; }
+}