https://gcc.gnu.org/g:d1b901b1b3a2335abacdf4a3b69df3c5d8b9fdbc

commit d1b901b1b3a2335abacdf4a3b69df3c5d8b9fdbc
Author: Ondřej Machota <ondrejmach...@gmail.com>
Date:   Fri Jun 27 13:24:06 2025 +0200

    rtl-ssa-dce: improve code, do not mark uses inside notes

Diff:
---
 gcc/dce.cc             | 108 +++++++++++++++++++++++++++++++++----------------
 gcc/rtl-ssa/changes.cc |   4 +-
 2 files changed, 76 insertions(+), 36 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 1aa5c6539664..3654a5101106 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1374,6 +1374,8 @@ private:
   bool can_delete_call (const_rtx);
   bool is_rtx_prelive (const_rtx);
   bool is_prelive (insn_info *);
+  bool mark_if_not_visited (const set_info *);
+  void append_not_visited_sets (auto_vec<set_info *> &, use_array &);
   void mark_prelive_insn (insn_info *, auto_vec<set_info *> &);
   auto_vec<set_info *> mark_prelive ();
   void mark ();
@@ -1507,25 +1509,84 @@ rtl_ssa_dce::is_prelive (insn_info *insn)
   return is_rtx_prelive (insn->rtl ());
 }
 
-// Marks INSN and adds its uses to worklist if INSN is not a debug instruction
+
+// Mark SET as visited and return true if SET->insn() is not nullptr and SET
+// has not been visited. Otherwise return false.
+bool
+rtl_ssa_dce::mark_if_not_visited (const set_info *set)
+{
+  insn_info *insn = set->insn ();
+  if (!insn)
+    return false;
+
+  if (insn->is_phi ())
+  {
+    const phi_info *phi = static_cast<const phi_info *> (set);
+         auto uid = phi->uid ();
+
+    if (bitmap_bit_p (m_marked_phis, uid))
+           return false;
+
+    bitmap_set_bit (m_marked_phis, uid);
+    if (dump_file)
+      fprintf (dump_file, "Phi node %d:%d marked as live\n", set->regno () 
,insn->uid ());
+  } else
+  {
+    auto uid = insn->uid ();
+    if (m_marked.get_bit (uid))
+      return false;
+
+    m_marked.set_bit (uid);
+    if (dump_file)
+      fprintf (dump_file, "Insn %d marked as live\n", insn->uid ());
+  }
+
+  return true;
+}
+
+// For each use in USES, if use->def () is non-null and has not been visited,
+// mark it as visited and append it to WORKLIST.
+void
+rtl_ssa_dce::append_not_visited_sets (auto_vec<set_info *>& worklist, 
use_array& uses) {
+  for (use_info *use : uses)
+  {
+    // This seems to be a good idea, however there is a problem is 
process_uses_of_deleted_def
+    if (use->only_occurs_in_notes())
+      continue;
+
+    set_info *parent_set = use->def ();
+         if (!parent_set)
+           continue;
+
+    if (!mark_if_not_visited (parent_set))
+      continue;
+
+    // mark_if_not_visited will return false if insn is nullptr
+    // insn_info *insn = parent_set->insn ();
+    // gcc_checking_assert (insn);
+
+    // if (dump_file)
+         //   fprintf (dump_file, "Adding insn %d to worklist\n", insn->uid 
());
+    worklist.safe_push (parent_set);
+  }
+}
+
+// Mark INSN and add its uses to WORKLIST if INSN is not a debug instruction
 void
 rtl_ssa_dce::mark_prelive_insn (insn_info *insn, auto_vec<set_info *> 
&worklist)
 {
   if (dump_file)
     fprintf (dump_file, "Insn %d marked as prelive\n", insn->uid ());
 
+  // A phi node will never be prelive.
   m_marked.set_bit(insn->uid ());
   // Debug instruction are not added to worklist. They would wake up possibly 
dead
   // instructions
   if (insn->is_debug_insn ())
     return;
 
-  for (use_info *use : insn->uses ())
-    {
-      set_info *set = use->def ();
-      if (set)
-       worklist.safe_push (set);
-    }
+  use_array uses = insn->uses ();
+  append_not_visited_sets (worklist, uses);
 }
 
 // Scans all instructions and marks all which are prelive
@@ -1556,41 +1617,18 @@ rtl_ssa_dce::mark ()
     {
       set_info *set = worklist.pop ();
       insn_info *insn = set->insn ();
-      if (!insn)
-       continue;
-
-      // Skip already visited visited instructions.
-      auto uid = insn->uid ();
-      if (m_marked.get_bit(uid) && !insn->is_phi ())
-       continue;
-
-      m_marked.set_bit (uid);
 
+      // a set without an insn will not be added to the worklist
+      gcc_checking_assert (insn);
 
       use_array uses = insn->uses ();
       if (insn->is_phi ())
        {
          phi_info *phi = static_cast<phi_info *> (set);
-         auto phi_uid = phi->uid ();
-         // Skip already visited phi node.
-         if (bitmap_bit_p(m_marked_phis, phi_uid))
-           continue;
-
-    bitmap_set_bit (m_marked_phis, phi_uid);
          uses = phi->inputs ();
        }
 
-      if (dump_file)
-       fprintf (dump_file, "Adding insn %d to worklist\n", insn->uid ());
-
-      for (use_info *use : uses)
-       {
-         set_info *parent_set = use->def ();
-         if (!parent_set)
-           continue;
-
-         worklist.safe_push (parent_set);
-       }
+      append_not_visited_sets(worklist, uses);
     }
 }
 
@@ -1630,9 +1668,9 @@ rtl_ssa_dce::reset_dead_debug ()
     bool is_parent_marked = false;
     if (parent_insn->is_phi ()) {
       auto phi = static_cast<phi_info *> (def);
-      is_parent_marked = bitmap_bit_p(m_marked_phis, phi->uid ());
+      is_parent_marked = bitmap_bit_p (m_marked_phis, phi->uid ());
     } else {
-      is_parent_marked = m_marked.get_bit(parent_insn->uid ());
+      is_parent_marked = m_marked.get_bit (parent_insn->uid ());
     }
 
     if (!is_parent_marked) {
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index 3c0fb51cc866..6598ebc1df13 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -285,7 +285,9 @@ function_info::process_uses_of_deleted_def (set_info *set)
        }
       else
        {
-         gcc_assert (use->is_live_out_use ());
+         // following assert causes crash when running rtl_ssa_dce with
+         // deleting eq_notes on testsuite
+         // gcc_assert (use->is_live_out_use ());
          remove_use (use);
        }
       // The phi handling above might have removed multiple uses of this_set.

Reply via email to