Hi!

Steven has been complaining for some years that var-tracking inserts
NOTE_INSN_VAR_LOCATION (and NOTE_INSN_CALL_ARG_LOCATION) notes sometimes
in between basic blocks, but with BLOCK_FOR_INSN set (or sometimes extends
a bb ending originally with a noreturn or throwing call by a note or more
after it).  Fixed thusly, bootstrapped/regtested on x86_64-linux and
i686-linux, ok for trunk?

2012-11-14  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/43631
        * var-tracking.c (emit_note_insn_var_location, emit_notes_in_bb):
        Clear BLOCK_FOR_INSN on notes emitted in between basic blocks,
        don't adjust BB_END when inserting note after BB_END of some bb.

--- gcc/var-tracking.c.jj       2012-11-13 10:54:06.000000000 +0100
+++ gcc/var-tracking.c  2012-11-13 11:35:31.668284140 +0100
@@ -8566,9 +8566,30 @@ emit_note_insn_var_location (void **varp
              || NOTE_KIND (insn) == NOTE_INSN_CALL_ARG_LOCATION))
        note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
       else
-       note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
+       {
+         note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
+         /* If insn is BB_HEAD of some bb, make sure the note
+            doesn't have BLOCK_FOR_INSN set.  The notes don't
+            extend the extents of a basic block, and e.g. notes emitted
+            for differences in between basic blocks should live in between
+            the basic blocks.  */
+         if (BLOCK_FOR_INSN (note)
+             && BB_HEAD (BLOCK_FOR_INSN (note)) == insn)
+           set_block_for_insn (note, NULL);
+       }
     }
   NOTE_VAR_LOCATION (note) = note_vl;
+  /* If insn is BB_END of some bb, make sure the note
+     doesn't have BLOCK_FOR_INSN set.  The notes don't
+     extend the extents of a basic block, and e.g. a noreturn
+     call can still be followed by NOTE_INSN_CALL_ARG_LOCATION.  */
+  if (BLOCK_FOR_INSN (note)
+      && BB_END (BLOCK_FOR_INSN (note)) == note
+      && PREV_INSN (note) == insn)
+    {
+      BB_END (BLOCK_FOR_INSN (note)) = insn;
+      set_block_for_insn (note, NULL);
+    }
 
   set_dv_changed (var->dv, false);
   gcc_assert (var->in_changed_variables);
@@ -8936,6 +8957,16 @@ emit_notes_in_bb (basic_block bb, datafl
                }
              note = emit_note_after (NOTE_INSN_CALL_ARG_LOCATION, insn);
              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
+                extend the extents of a basic block, and e.g. a noreturn
+                call can still be followed by NOTE_INSN_CALL_ARG_LOCATION.  */
+             if (BLOCK_FOR_INSN (note)
+                 && BB_END (BLOCK_FOR_INSN (note)) == note)
+               {
+                 BB_END (BLOCK_FOR_INSN (note)) = insn;
+                 set_block_for_insn (note, NULL);
+               }
            }
            break;
 

        Jakub

Reply via email to