[1/2] rtl-ssa: Add replace_nondebug_insn [PR115785]

Message ID mpt5xte60vs.fsf@arm.com
State New
Headers
Series [1/2] rtl-ssa: Add replace_nondebug_insn [PR115785] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

Richard Sandiford July 9, 2024, 3:28 p.m. UTC
  change_insns is used to change multiple instructions at once, so that
the IR on return is valid & self-consistent.  These changes can involve
moving instructions, and the new position for one instruction might
be expressed in terms of the old position of another instruction
that is changing at the same time.

change_insns therefore adds placeholder instructions to mark each
new instruction position, then replaces each placeholder with the
corresponding real instruction.  This replacement was done in two
steps: removing the old placeholder instruction and inserting the new
real instruction.  But it's more convenient for the upcoming fix for
PR115785 if we do the operation as a single step.  That should also
be slightly more efficient, since e.g. no splay tree operations are
needed.

This operation happens purely on the rtl-ssa instruction chain.
The placeholders are never represented in rtl.

Bootstrapped & regression-tested on aarch64-linux-gnu and
x86_64-linux-gnu.  OK to install?

Richard


gcc/
	PR rtl-optimization/115785
	* rtl-ssa/functions.h (function_info::replace_nondebug_insn): Declare.
	* rtl-ssa/insns.h (insn_info::order_node::set_uid): New function.
	(insn_info::remove_note): Declare.
	* rtl-ssa/insns.cc (insn_info::remove_note): New function.
	(function_info::replace_nondebug_insn): Likewise.
	* rtl-ssa/changes.cc (function_info::change_insns): Use
	replace_nondebug_insn instead of remove_insn + add_insn.
---
 gcc/rtl-ssa/changes.cc  |  5 +----
 gcc/rtl-ssa/functions.h |  1 +
 gcc/rtl-ssa/insns.cc    | 42 +++++++++++++++++++++++++++++++++++++++++
 gcc/rtl-ssa/insns.h     |  4 ++++
 4 files changed, 48 insertions(+), 4 deletions(-)
  

Comments

Jeff Law July 9, 2024, 3:32 p.m. UTC | #1
On 7/9/24 9:28 AM, Richard Sandiford wrote:
> change_insns is used to change multiple instructions at once, so that
> the IR on return is valid & self-consistent.  These changes can involve
> moving instructions, and the new position for one instruction might
> be expressed in terms of the old position of another instruction
> that is changing at the same time.
> 
> change_insns therefore adds placeholder instructions to mark each
> new instruction position, then replaces each placeholder with the
> corresponding real instruction.  This replacement was done in two
> steps: removing the old placeholder instruction and inserting the new
> real instruction.  But it's more convenient for the upcoming fix for
> PR115785 if we do the operation as a single step.  That should also
> be slightly more efficient, since e.g. no splay tree operations are
> needed.
> 
> This operation happens purely on the rtl-ssa instruction chain.
> The placeholders are never represented in rtl.
> 
> Bootstrapped & regression-tested on aarch64-linux-gnu and
> x86_64-linux-gnu.  OK to install?
> 
> Richard
> 
> 
> gcc/
> 	PR rtl-optimization/115785
> 	* rtl-ssa/functions.h (function_info::replace_nondebug_insn): Declare.
> 	* rtl-ssa/insns.h (insn_info::order_node::set_uid): New function.
> 	(insn_info::remove_note): Declare.
> 	* rtl-ssa/insns.cc (insn_info::remove_note): New function.
> 	(function_info::replace_nondebug_insn): Likewise.
> 	* rtl-ssa/changes.cc (function_info::change_insns): Use
> 	replace_nondebug_insn instead of remove_insn + add_insn.
OK
jeff
  

Patch

diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index bc80d7da829..6b6f7cd5d3a 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -874,14 +874,11 @@  function_info::change_insns (array_slice<insn_change *> changes)
 	    }
 	  else
 	    {
-	      // Remove the placeholder first so that we have a wider range of
-	      // program points when inserting INSN.
 	      insn_info *after = placeholder->prev_any_insn ();
 	      if (!insn->is_temporary ())
 		remove_insn (insn);
-	      remove_insn (placeholder);
+	      replace_nondebug_insn (placeholder, insn);
 	      insn->set_bb (after->bb ());
-	      add_insn_after (insn, after);
 	    }
 	}
     }
diff --git a/gcc/rtl-ssa/functions.h b/gcc/rtl-ssa/functions.h
index e2134621723..8be04f1aa96 100644
--- a/gcc/rtl-ssa/functions.h
+++ b/gcc/rtl-ssa/functions.h
@@ -274,6 +274,7 @@  private:
   insn_info::order_node *need_order_node (insn_info *);
 
   void add_insn_after (insn_info *, insn_info *);
+  void replace_nondebug_insn (insn_info *, insn_info *);
   void append_insn (insn_info *);
   void remove_insn (insn_info *);
 
diff --git a/gcc/rtl-ssa/insns.cc b/gcc/rtl-ssa/insns.cc
index 68365e323ec..7e26bfd978f 100644
--- a/gcc/rtl-ssa/insns.cc
+++ b/gcc/rtl-ssa/insns.cc
@@ -70,6 +70,16 @@  insn_info::add_note (insn_note *note)
   *ptr = note;
 }
 
+// Remove NOTE from the instruction's notes.
+void
+insn_info::remove_note (insn_note *note)
+{
+  insn_note **ptr = &m_first_note;
+  while (*ptr != note)
+    ptr = &(*ptr)->m_next_note;
+  *ptr = note->m_next_note;
+}
+
 // Implement compare_with for the case in which this insn and OTHER
 // have the same program point.
 int
@@ -346,6 +356,38 @@  function_info::add_insn_after (insn_info *insn, insn_info *after)
     }
 }
 
+// Replace non-debug instruction OLD_INSN with non-debug instruction NEW_INSN.
+// NEW_INSN is not currently linked.
+void
+function_info::replace_nondebug_insn (insn_info *old_insn, insn_info *new_insn)
+{
+  gcc_assert (!old_insn->is_debug_insn ()
+	      && !new_insn->is_debug_insn ()
+	      && !new_insn->has_insn_links ());
+
+  insn_info *prev = old_insn->prev_any_insn ();
+  insn_info *next_nondebug = old_insn->next_nondebug_insn ();
+
+  // We should never remove the entry or exit block's instructions.
+  gcc_checking_assert (prev && next_nondebug);
+
+  new_insn->copy_prev_from (old_insn);
+  new_insn->copy_next_from (old_insn);
+
+  prev->set_next_any_insn (new_insn);
+  next_nondebug->set_prev_sametype_insn (new_insn);
+
+  new_insn->set_point (old_insn->point ());
+  if (insn_info::order_node *order = old_insn->get_order_node ())
+    {
+      order->set_uid (new_insn->uid ());
+      old_insn->remove_note (order);
+      new_insn->add_note (order);
+    }
+
+  old_insn->clear_insn_links ();
+}
+
 // Remove INSN from the function's list of instructions.
 void
 function_info::remove_insn (insn_info *insn)
diff --git a/gcc/rtl-ssa/insns.h b/gcc/rtl-ssa/insns.h
index 1ba56abc2ca..80eae5eaa1e 100644
--- a/gcc/rtl-ssa/insns.h
+++ b/gcc/rtl-ssa/insns.h
@@ -330,6 +330,9 @@  private:
     // Return the uid of the instruction that this node describes.
     int uid () const { return m_data32; }
 
+    // Change the uid of the instruction that this node describes.
+    void set_uid (int uid) { m_data32 = uid; }
+
     // The splay tree pointers.
     order_node *m_children[2];
     order_node *m_parent;
@@ -374,6 +377,7 @@  private:
   void set_bb (bb_info *bb) { m_bb = bb; }
 
   void add_note (insn_note *note);
+  void remove_note (insn_note *note);
 
   order_node *get_order_node () const;
   order_node *get_known_order_node () const;