Patchwork PR middle-end/43631

login
register
mail settings
Submitter Steven Bosscher
Date April 14, 2013, 10 p.m.
Message ID <CABu31nOEO8+hAWQTwK2CQ116L68LsbzzjtFN7QYaQKHEChEDZg@mail.gmail.com>
Download mbox | patch
Permalink /patch/236482/
State New
Headers show

Comments

Steven Bosscher - April 14, 2013, 10 p.m.
On Fri, Apr 12, 2013 at 6:46 PM, Steven Bosscher wrote:
>> Can we reorganize insn-notes.def so that the 3 classes are clearly separated
>> (and optionally define a NOTE_INSN_CLASS macro so that we don't need to
>> enumerate the notes each time)?
>
> That's probably a good idea, yes.

This didn't really help make things look prettier. The notes are
enumerated in many other places, for various purposes. I didn't like
special-casing this one INSN_NOTE oddity when there are so many others
already. So I created a note_outside_basic_block_p instead, I hope you
agree with this approach.

While there, I noticed that we could use a make_note_raw.


>> Reading your patch, it apppears that NOTE_INSN_SWITCH_TEXT_SECTIONS is the
>> only member of the 1st class and that almost all notes are in the 2nd class
>> except for the 2 LOCATION and the 2 EH_REGION recently added notes.
>
> I think DELETED_LABEL and DELETED_DEBUG_LABEL also can only live
> outside basic blocks (i.e. like SWITCH_TEXT_SECTIONS), but I'm not
> sure.

It turns out that DELETED_LABEL cannot be emitted, it can only be
created by patching out a label. Likewise for DELETED_DEBUG_LABEL, so
I've included that one also in the gcc_assert for this.

>>  - Remove the
>>
>>     This and the next should be the only functions called to insert an insn
>>     once delay slots have been filled since only they know how to update a
>>     SEQUENCE.
>>
>> from the head comment of functions that are now private to emit-rtl.c.
>
> OK.

Done.

Updated patch attached, similarly tested. OK for trunk?

Ciao!
Steven
PR middle-end/43631
	* emit-rtl.c (make_note_raw): New function.
	(link_insn_into_chain): New static inline function.
	(add_insn): Use it.
	(add_insn_before, add_insn_after): Factor insn chain linking code...
	(add_insn_before_nobb, add_insn_after_nobb): ...here, new functions
	using link_insn_into_chain.
	(note_outside_basic_block_p): New helper function for emit_note_after
	and emit_note_before.
	(emit_note_after): Use nobb variant of add_insn_after if the note
	should not be contained in a basic block.
	(emit_note_before): Use nobb variant of add_insn_before if the note
	should not be contained in a basic block.
	(emit_note_copy): Use make_note_raw.
	(emit_note): Likewise.
	* bb-reorder.c (insert_section_boundary_note): Remove hack to set
	BLOCK_FOR_INSN to NULL manually for NOTE_INSN_SWITCH_TEXT_SECTIONS.
	* jump.c (cleanup_barriers): Use reorder_insns_nobb to avoid making
	the moved barrier the tail of the basic block it follows.
	* var-tracking.c (pass_variable_tracking): Add TODO_verify_flow.
Eric Botcazou - April 15, 2013, 9:20 a.m.
> This didn't really help make things look prettier. The notes are
> enumerated in many other places, for various purposes. I didn't like
> special-casing this one INSN_NOTE oddity when there are so many others
> already. So I created a note_outside_basic_block_p instead, I hope you
> agree with this approach.

Sure, thanks for investigating the proposal in any case.

> Updated patch attached, similarly tested. OK for trunk?

Yes, modulo a few nits:

+/* Like add_insn_after, but try to set BLOCK_FOR_INSN.
+   If BB is NULL, an attempt is made to infer the bb from before.
+
+   This and the next function should be the only functions called
+   to insert an insn once delay slots have been filled since only
+   they know how to update a SEQUENCE. */
+
+void
+add_insn_after (rtx insn, rtx after, basic_block bb)

Like add_insn_after_nobb, ...


-/* Add INSN into the doubly-linked list before insn BEFORE.  This and
-   the previous should be the only functions called to insert an insn
-   once delay slots have been filled since only they know how to
-   update a SEQUENCE.  If BB is NULL, an attempt is made to infer the
-   bb from before.  */
+/* Like add_insn_before_nobb, but try to set BLOCK_FOR_INSN.
+   If BB is NULL, an attempt is made to infer the bb from before.  */
 
 void
 add_insn_before (rtx insn, rtx before, basic_block bb)

Keep the blurb about SEQUENCEs: "This and the previous function should..."


+/* Return true iff a note of kind SUBTYPE should be emitted with via
+   routines that never set BLOCK_FOR_INSN on NOTE.  BB_BOUNDARY is true
+   if the caller is asked to emit a note before BB_HEAD, or after BB_END.  */

Superfluous "with" or "via".


+static bool
+note_outside_basic_block_p (enum insn_note subtype, bool on_bb_boundary_p)
+{

This should be implemented with a switch statement.

Patch

Index: emit-rtl.c
===================================================================
--- emit-rtl.c	(revision 197942)
+++ emit-rtl.c	(working copy)
@@ -3751,62 +3751,135 @@  make_call_insn_raw (rtx pattern)
 
   return insn;
 }
+
+/* Like `make_insn_raw' but make a NOTE instead of an insn.  */
+
+static rtx
+make_note_raw (enum insn_note subtype)
+{
+  /* Some notes are never created this way at all.  These notes are
+     only created by patching out insns.  */
+  gcc_assert (subtype != NOTE_INSN_DELETED_LABEL
+	      && subtype != NOTE_INSN_DELETED_DEBUG_LABEL);
+
+  rtx note = rtx_alloc (NOTE);
+  INSN_UID (note) = cur_insn_uid++;
+  NOTE_KIND (note) = subtype;
+  BLOCK_FOR_INSN (note) = NULL;
+  memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
+  return note;
+}
 
+/* Add INSN to the end of the doubly-linked list, between PREV and NEXT.
+   INSN may be any object that can appear in the chain: INSN_P and NOTE_P objects,
+   but also BARRIERs and JUMP_TABLE_DATAs.  PREV and NEXT may be NULL.  */
+
+static inline void
+link_insn_into_chain (rtx insn, rtx prev, rtx next)
+{
+  PREV_INSN (insn) = prev;
+  NEXT_INSN (insn) = next;
+  if (prev != NULL)
+    {
+      NEXT_INSN (prev) = insn;
+      if (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
+	{
+	  rtx sequence = PATTERN (prev);
+	  NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
+	}
+    }
+  if (next != NULL)
+    {
+      PREV_INSN (next) = insn;
+      if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
+	PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = insn;
+    }
+}
+
 /* Add INSN to the end of the doubly-linked list.
    INSN may be an INSN, JUMP_INSN, CALL_INSN, CODE_LABEL, BARRIER or NOTE.  */
 
 void
 add_insn (rtx insn)
 {
-  PREV_INSN (insn) = get_last_insn();
-  NEXT_INSN (insn) = 0;
-
-  if (NULL != get_last_insn())
-    NEXT_INSN (get_last_insn ()) = insn;
-
+  rtx prev = get_last_insn ();
+  link_insn_into_chain (insn, prev, NULL);
   if (NULL == get_insns ())
     set_first_insn (insn);
-
   set_last_insn (insn);
 }
 
-/* Add INSN into the doubly-linked list after insn AFTER.  This and
-   the next should be the only functions called to insert an insn once
-   delay slots have been filled since only they know how to update a
-   SEQUENCE.  */
+/* Add INSN into the doubly-linked list after insn AFTER.  */
 
-void
-add_insn_after (rtx insn, rtx after, basic_block bb)
+static void
+add_insn_after_nobb (rtx insn, rtx after)
 {
   rtx next = NEXT_INSN (after);
 
   gcc_assert (!optimize || !INSN_DELETED_P (after));
 
-  NEXT_INSN (insn) = next;
-  PREV_INSN (insn) = after;
+  link_insn_into_chain (insn, after, next);
 
-  if (next)
+  if (next == NULL)
     {
-      PREV_INSN (next) = insn;
-      if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
-	PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = insn;
+      if (get_last_insn () == after)
+	set_last_insn (insn);
+      else
+	{
+	  struct sequence_stack *stack = seq_stack;
+	  /* Scan all pending sequences too.  */
+	  for (; stack; stack = stack->next)
+	    if (after == stack->last)
+	      {
+		stack->last = insn;
+		break;
+	      }
+	}
     }
-  else if (get_last_insn () == after)
-    set_last_insn (insn);
-  else
+}
+
+/* Add INSN into the doubly-linked list before insn BEFORE.  */
+
+static void
+add_insn_before_nobb (rtx insn, rtx before)
+{
+  rtx prev = PREV_INSN (before);
+
+  gcc_assert (!optimize || !INSN_DELETED_P (before));
+
+  link_insn_into_chain (insn, prev, before);
+
+  if (prev == NULL)
     {
-      struct sequence_stack *stack = seq_stack;
-      /* Scan all pending sequences too.  */
-      for (; stack; stack = stack->next)
-	if (after == stack->last)
-	  {
-	    stack->last = insn;
-	    break;
-	  }
+      if (get_insns () == before)
+	set_first_insn (insn);
+      else
+	{
+	  struct sequence_stack *stack = seq_stack;
+	  /* Scan all pending sequences too.  */
+	  for (; stack; stack = stack->next)
+	    if (before == stack->first)
+	      {
+		stack->first = insn;
+		break;
+	      }
 
-      gcc_assert (stack);
+	  gcc_assert (stack);
+	}
     }
+}
 
+/* Like add_insn_after, but try to set BLOCK_FOR_INSN.
+   If BB is NULL, an attempt is made to infer the bb from before.
+
+   This and the next function should be the only functions called
+   to insert an insn once delay slots have been filled since only
+   they know how to update a SEQUENCE. */
+
+void
+add_insn_after (rtx insn, rtx after, basic_block bb)
+{
+  add_insn_after_nobb (insn, after);
   if (!BARRIER_P (after)
       && !BARRIER_P (insn)
       && (bb = BLOCK_FOR_INSN (after)))
@@ -3822,55 +3895,15 @@  add_insn_after (rtx insn, rtx after, bas
 	  && !NOTE_INSN_BASIC_BLOCK_P (insn))
 	BB_END (bb) = insn;
     }
-
-  NEXT_INSN (after) = insn;
-  if (NONJUMP_INSN_P (after) && GET_CODE (PATTERN (after)) == SEQUENCE)
-    {
-      rtx sequence = PATTERN (after);
-      NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
-    }
 }
 
-/* Add INSN into the doubly-linked list before insn BEFORE.  This and
-   the previous should be the only functions called to insert an insn
-   once delay slots have been filled since only they know how to
-   update a SEQUENCE.  If BB is NULL, an attempt is made to infer the
-   bb from before.  */
+/* Like add_insn_before_nobb, but try to set BLOCK_FOR_INSN.
+   If BB is NULL, an attempt is made to infer the bb from before.  */
 
 void
 add_insn_before (rtx insn, rtx before, basic_block bb)
 {
-  rtx prev = PREV_INSN (before);
-
-  gcc_assert (!optimize || !INSN_DELETED_P (before));
-
-  PREV_INSN (insn) = prev;
-  NEXT_INSN (insn) = before;
-
-  if (prev)
-    {
-      NEXT_INSN (prev) = insn;
-      if (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
-	{
-	  rtx sequence = PATTERN (prev);
-	  NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
-	}
-    }
-  else if (get_insns () == before)
-    set_first_insn (insn);
-  else
-    {
-      struct sequence_stack *stack = seq_stack;
-      /* Scan all pending sequences too.  */
-      for (; stack; stack = stack->next)
-	if (before == stack->first)
-	  {
-	    stack->first = insn;
-	    break;
-	  }
-
-      gcc_assert (stack);
-    }
+  add_insn_before_nobb (insn, before);
 
   if (!bb
       && !BARRIER_P (before)
@@ -3889,13 +3922,8 @@  add_insn_before (rtx insn, rtx before, b
 		  || BARRIER_P (insn)
 		  || NOTE_INSN_BASIC_BLOCK_P (insn));
     }
-
-  PREV_INSN (before) = insn;
-  if (NONJUMP_INSN_P (before) && GET_CODE (PATTERN (before)) == SEQUENCE)
-    PREV_INSN (XVECEXP (PATTERN (before), 0, 0)) = insn;
 }
 
-
 /* Replace insn with an deleted instruction note.  */
 
 void
@@ -4239,21 +4267,6 @@  emit_label_before (rtx label, rtx before
   add_insn_before (label, before, NULL);
   return label;
 }
-
-/* Emit a note of subtype SUBTYPE before the insn BEFORE.  */
-
-rtx
-emit_note_before (enum insn_note subtype, rtx before)
-{
-  rtx note = rtx_alloc (NOTE);
-  INSN_UID (note) = cur_insn_uid++;
-  NOTE_KIND (note) = subtype;
-  BLOCK_FOR_INSN (note) = NULL;
-  memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
-
-  add_insn_before (note, before, NULL);
-  return note;
-}
 
 /* Helper for emit_insn_after, handles lists of instructions
    efficiently.  */
@@ -4400,18 +4413,66 @@  emit_label_after (rtx label, rtx after)
   add_insn_after (label, after, NULL);
   return label;
 }
+
+/* Notes require a bit of special handling: Some notes need to have their
+   BLOCK_FOR_INSN set, others should never have it set, and some should have
+   it set or clear depending on the context.   */
+
+/* Return true iff a note of kind SUBTYPE should be emitted with via
+   routines that never set BLOCK_FOR_INSN on NOTE.  BB_BOUNDARY is true
+   if the caller is asked to emit a note before BB_HEAD, or after BB_END.  */
+
+static bool
+note_outside_basic_block_p (enum insn_note subtype, bool on_bb_boundary_p)
+{
+
+  /* NOTE_INSN_SWITCH_TEXT_SECTIONS only appears between basic blocks.  */
+  if (subtype == NOTE_INSN_SWITCH_TEXT_SECTIONS)
+    return true;
+
+  /* Notes for var tracking and EH region markers can appear between or
+     inside basic blocks.  If the caller is emitting on the basic block
+     boundary, do not set BLOCK_FOR_INSN on the new note.  */
+  if ((subtype == NOTE_INSN_VAR_LOCATION
+       || subtype == NOTE_INSN_CALL_ARG_LOCATION
+       || subtype == NOTE_INSN_EH_REGION_BEG
+       || subtype == NOTE_INSN_EH_REGION_END)
+      && on_bb_boundary_p)
+    return true;
+
+  /* Otherwise, BLOCK_FOR_INSN must be set.  */
+  return false;
+}
 
 /* Emit a note of subtype SUBTYPE after the insn AFTER.  */
 
 rtx
 emit_note_after (enum insn_note subtype, rtx after)
 {
-  rtx note = rtx_alloc (NOTE);
-  INSN_UID (note) = cur_insn_uid++;
-  NOTE_KIND (note) = subtype;
-  BLOCK_FOR_INSN (note) = NULL;
-  memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
-  add_insn_after (note, after, NULL);
+  rtx note = make_note_raw (subtype);
+  basic_block bb = BARRIER_P (after) ? NULL : BLOCK_FOR_INSN (after);
+  bool on_bb_boundary_p = (bb != NULL && BB_END (bb) == after);
+
+  if (note_outside_basic_block_p (subtype, on_bb_boundary_p))
+    add_insn_after_nobb (note, after);
+  else
+    add_insn_after (note, after, bb);
+  return note;
+}
+
+/* Emit a note of subtype SUBTYPE before the insn BEFORE.  */
+
+rtx
+emit_note_before (enum insn_note subtype, rtx before)
+{
+  rtx note = make_note_raw (subtype);
+  basic_block bb = BARRIER_P (before) ? NULL : BLOCK_FOR_INSN (before);
+  bool on_bb_boundary_p = (bb != NULL && BB_HEAD (bb) == before);
+
+  if (note_outside_basic_block_p (subtype, on_bb_boundary_p))
+    add_insn_before_nobb (note, before);
+  else
+    add_insn_before (note, before, bb);
   return note;
 }
 
@@ -4854,16 +4915,10 @@  emit_barrier (void)
 rtx
 emit_note_copy (rtx orig)
 {
-  rtx note;
-
-  note = rtx_alloc (NOTE);
-
-  INSN_UID (note) = cur_insn_uid++;
+  enum insn_note kind = (enum insn_note) NOTE_KIND (orig);
+  rtx note = make_note_raw (kind);
   NOTE_DATA (note) = NOTE_DATA (orig);
-  NOTE_KIND (note) = NOTE_KIND (orig);
-  BLOCK_FOR_INSN (note) = NULL;
   add_insn (note);
-
   return note;
 }
 
@@ -4873,13 +4928,7 @@  emit_note_copy (rtx orig)
 rtx
 emit_note (enum insn_note kind)
 {
-  rtx note;
-
-  note = rtx_alloc (NOTE);
-  INSN_UID (note) = cur_insn_uid++;
-  NOTE_KIND (note) = kind;
-  memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
-  BLOCK_FOR_INSN (note) = NULL;
+  rtx note = make_note_raw (kind);
   add_insn (note);
   return note;
 }
Index: bb-reorder.c
===================================================================
--- bb-reorder.c	(revision 197941)
+++ bb-reorder.c	(working copy)
@@ -2173,7 +2173,6 @@  static void
 insert_section_boundary_note (void)
 {
   basic_block bb;
-  rtx new_note;
   int first_partition = 0;
 
   if (!flag_reorder_blocks_and_partition)
@@ -2185,11 +2184,7 @@  insert_section_boundary_note (void)
 	first_partition = BB_PARTITION (bb);
       if (BB_PARTITION (bb) != first_partition)
 	{
-	  new_note = emit_note_before (NOTE_INSN_SWITCH_TEXT_SECTIONS,
-				       BB_HEAD (bb));
-	  /* ??? This kind of note always lives between basic blocks,
-	     but add_insn_before will set BLOCK_FOR_INSN anyway.  */
-	  BLOCK_FOR_INSN (new_note) = NULL;
+	  emit_note_before (NOTE_INSN_SWITCH_TEXT_SECTIONS, BB_HEAD (bb));
 	  break;
 	}
     }
Index: jump.c
===================================================================
--- jump.c	(revision 197941)
+++ jump.c	(working copy)
@@ -133,7 +133,7 @@  cleanup_barriers (void)
 	  if (BARRIER_P (prev))
 	    delete_insn (insn);
 	  else if (prev != PREV_INSN (insn))
-	    reorder_insns (insn, insn, prev);
+	    reorder_insns_nobb (insn, insn, prev);
 	}
     }
   return 0;
Index: var-tracking.c
===================================================================
--- var-tracking.c	(revision 197941)
+++ var-tracking.c	(working copy)
@@ -10238,6 +10238,7 @@  struct rtl_opt_pass pass_variable_tracki
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_verify_rtl_sharing               /* todo_flags_finish */
+  TODO_verify_rtl_sharing
+   | TODO_verify_flow                   /* todo_flags_finish */
  }
 };