]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rtl-ssa: Handle artifical uses of deleted defs
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 25 Oct 2023 09:39:51 +0000 (10:39 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Wed, 25 Oct 2023 09:39:51 +0000 (10:39 +0100)
If an optimisation removes the last real use of a definition,
there can still be artificial uses left.  This patch removes
those uses too.

These artificial uses exist because RTL-SSA is only an SSA-like
view of the existing RTL IL, rather than a native SSA representation.
It effectively treats RTL registers like gimple vops, but with the
addition of an RPO view of the register's lifetime(s).  Things are
structured to allow most operations to update this RPO view in
amortised sublinear time.

gcc/
* rtl-ssa/functions.h (function_info::process_uses_of_deleted_def):
New member function.
* rtl-ssa/changes.cc (function_info::process_uses_of_deleted_def):
Likewise.
(function_info::change_insns): Use it.

gcc/rtl-ssa/changes.cc
gcc/rtl-ssa/functions.h

index 5800f9dba976cd9d304e6d4c77f8f01d255c9dfa..3e14069421c8edbf187098f206a0431a8f7ce73f 100644 (file)
@@ -209,6 +209,35 @@ rtl_ssa::changes_are_worthwhile (array_slice<insn_change *const> changes,
   return true;
 }
 
+// SET has been deleted.  Clean up all remaining uses.  Such uses are
+// either dead phis or now-redundant live-out uses.
+void
+function_info::process_uses_of_deleted_def (set_info *set)
+{
+  if (!set->has_any_uses ())
+    return;
+
+  auto *use = *set->all_uses ().begin ();
+  do
+    {
+      auto *next_use = use->next_use ();
+      if (use->is_in_phi ())
+       {
+         // This call will not recurse.
+         process_uses_of_deleted_def (use->phi ());
+         delete_phi (use->phi ());
+       }
+      else
+       {
+         gcc_assert (use->is_live_out_use ());
+         remove_use (use);
+       }
+      use = next_use;
+    }
+  while (use);
+  gcc_assert (!set->has_any_uses ());
+}
+
 // Update the REG_NOTES of INSN, whose pattern has just been changed.
 static void
 update_notes (rtx_insn *insn)
@@ -695,7 +724,8 @@ function_info::change_insns (array_slice<insn_change *> changes)
     }
 
   // Remove all definitions that are no longer needed.  After the above,
-  // such definitions should no longer have any registered users.
+  // the only uses of such definitions should be dead phis and now-redundant
+  // live-out uses.
   //
   // In particular, this means that consumers must handle debug
   // instructions before removing a set.
@@ -704,7 +734,8 @@ function_info::change_insns (array_slice<insn_change *> changes)
       if (def->m_has_been_superceded)
        {
          auto *set = dyn_cast<set_info *> (def);
-         gcc_assert (!set || !set->has_any_uses ());
+         if (set && set->has_any_uses ())
+           process_uses_of_deleted_def (set);
          remove_def (def);
        }
 
index 73690a0e63b4d30c3c61b96eff9d812aad60062e..cd90b6aa9df49cd5bcfe2cde9d0cb6b26546b31f 100644 (file)
@@ -263,6 +263,7 @@ private:
   bb_info *create_bb_info (basic_block);
   void append_bb (bb_info *);
 
+  void process_uses_of_deleted_def (set_info *);
   insn_info *add_placeholder_after (insn_info *);
   void possibly_queue_changes (insn_change &);
   void finalize_new_accesses (insn_change &, insn_info *);