https://gcc.gnu.org/g:2e2274102964364a1b5fcd0a70d92c5f6f3c5e08

commit 2e2274102964364a1b5fcd0a70d92c5f6f3c5e08
Author: Ondřej Machota <ondrejmach...@gmail.com>
Date:   Tue May 13 06:28:48 2025 +0200

    rtl-ssa-dce: create debug instruction

Diff:
---
 gcc/dce.cc              | 219 +++++++++++++++---------------------------------
 gcc/emit-rtl.cc         |   2 +-
 gcc/rtl-ssa/changes.cc  |   8 +-
 gcc/rtl-ssa/functions.h |   2 +-
 gcc/rtl.h               |   1 +
 5 files changed, 74 insertions(+), 158 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 5b8648be5859..305bb0e63db6 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -17,7 +17,6 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
-#include "bitmap.h"
 #include "sbitmap.h"
 #include <iostream>
 #include <ostream>
@@ -1381,7 +1380,10 @@ private:
   void sweep ();
 
   void debuggize_insn (insn_info *);
-  void debugize_insns (const std::unordered_set<insn_info *> &);
+
+  void unmark_debugizable(insn_info &, sbitmap &);
+  sbitmap find_debugizable(const std::unordered_set<insn_info *> &);
+  void debugize_insns (const sbitmap);
 
   offset_bitmap m_marked;
   sbitmap mm_marked_phis;
@@ -1640,7 +1642,7 @@ rtl_ssa_dce::reset_dead_debug_insn (insn_info *insn)
   if (dump_file)
     fprintf (dump_file, "Resetting debug insn: %d\n", insn->uid ());
 
-  // bitmap_clear_bit (mm_marked, insn->uid () + offset);
+  m_marked.clear_bit (insn->uid ());
   insn_change change (insn);
   change.new_uses = {};
   INSN_VAR_LOCATION_LOC (insn->rtl ()) = gen_rtx_UNKNOWN_VAR_LOC ();
@@ -1899,14 +1901,14 @@ replace_dead_reg(rtx x, const_rtx old_rtx 
ATTRIBUTE_UNUSED, void *data)
 }
 
 // visit every marked instruction in INSN dependency tree and unmark it
-static void
-unmark_debugizable(const insn_info& insn, auto_sbitmap &debugizable) 
+void
+rtl_ssa_dce::unmark_debugizable(insn_info &insn, sbitmap &debugizable) 
 {
   auto_vec<insn_info *> worklist;
   bitmap_set_bit (debugizable, insn.uid ());
   worklist.safe_push (&insn);
 
-  while (!worklist.empty ()) {
+  while (!worklist.is_empty ()) {
     insn_info *current = worklist.pop ();
     int current_uid = current->uid ();
 
@@ -1916,7 +1918,7 @@ unmark_debugizable(const insn_info& insn, auto_sbitmap 
&debugizable)
 
     bitmap_clear_bit(debugizable, current_uid);
     // add all marked dependencies to the worklist
-    for (def_info *def : current.defs())
+    for (def_info *def : current->defs())
     {
       if (def->kind() != access_kind::SET)
         continue;
@@ -1932,14 +1934,20 @@ unmark_debugizable(const insn_info& insn, auto_sbitmap 
&debugizable)
   }
 }
 
-static auto_sbitmap
-find_debugizable(const std::unordered_set<insn_info *> &depends_on_dead_phi) 
+sbitmap
+rtl_ssa_dce::find_debugizable(const std::unordered_set<insn_info *> 
&depends_on_dead_phi) 
 {
   // only real instructions
-  auto_sbitmap debugizable(get_max_uid () + 1);
+  sbitmap debugizable = sbitmap_alloc (get_max_uid () + 1);
   bitmap_clear(debugizable);
 
   for (insn_info *insn : crtl->ssa->reverse_all_insns ()) {
+    if (insn->is_artificial ())
+      continue;
+
+      // TODO: mark debug instructions that do not depend on a
+      // dead phi
+
     if (insn->is_artificial () || 
       (m_marked.get_bit (insn->uid ()) && !insn->is_debug_insn()))
       continue;
@@ -1966,7 +1974,7 @@ find_debugizable(const std::unordered_set<insn_info *> 
&depends_on_dead_phi)
       asm_noperands (PATTERN (rtl)) >= 0)
       {
         unmark_debugizable(*insn, debugizable);
-        continue; // TODO: call unmark_debugizable
+        continue;
       }
 
     // some of the checks might be duplicate:
@@ -1974,7 +1982,7 @@ find_debugizable(const std::unordered_set<insn_info *> 
&depends_on_dead_phi)
     {
       if (insn->num_defs() > 1)
         unmark_debugizable(*insn, debugizable);
-      continue; // TODO: call unmark_debugizable if num_defs>1
+      continue;
     }
 
     def_info *def = *defs.begin ();
@@ -1984,7 +1992,24 @@ find_debugizable(const std::unordered_set<insn_info *> 
&depends_on_dead_phi)
     set_info *set = static_cast<set_info *> (def);
     // this is a problem a bit
     // TODO: check instruction dependencies and their debugizability
-    if (!set->has_nondebug_insn_uses ())
+
+    // if some dependent is a debugizable
+    bool has_debug_uses = false;
+    for (use_info *use : set->all_uses()) 
+    {
+      if (!use->is_in_any_insn ())
+        continue;
+
+      insn_info *use_insn = use->insn();
+      gcc_assert(use_insn->is_real());
+
+      if (bitmap_bit_p(debugizable, use_insn->uid ())) {
+        has_debug_uses = true;
+        break;
+      }
+    }
+    // if (!set->has_nondebug_insn_uses ())
+    if (!has_debug_uses)
       continue;
 
     bitmap_set_bit (debugizable, insn->uid ());
@@ -1993,8 +2018,8 @@ find_debugizable(const std::unordered_set<insn_info *> 
&depends_on_dead_phi)
   return debugizable;
 }
 
-static void 
-bruh(const auto_sbitmap& debugizable)
+void
+rtl_ssa_dce::debugize_insns (const sbitmap debugizable)
 {
   for (insn_info *insn : crtl->ssa->reverse_all_insns ())
   {
@@ -2026,76 +2051,10 @@ bruh(const auto_sbitmap& debugizable)
     change.new_uses = insn->uses();
     change.move_range = insn_range_info(insn);
 
-    rtx_insn *bind = emit_debug_insn_before (bind_var_loc, rtl);
-
-    register_replacement replacement;
-    for (use_info *u : set->all_uses ()) {
-      // TODO: transform dependent insns
-      replacement.regno = u->regno();
-      replacement.expr = dval;
-
-      simplify_replace_fn_rtx(INSN_VAR_LOCATION_LOC(rtl), NULL_RTX, 
replace_dead_reg, &replacement);
-    }
-  }
-}
-
-void
-rtl_ssa_dce::debugize_insns (const std::unordered_set<insn_info *> 
&depends_on_dead_phi)
-{
-  for (insn_info *insn : crtl->ssa->reverse_all_insns ()) {
-    if (insn->is_artificial () || 
-      (m_marked.get_bit (insn->uid ()) && !insn->is_debug_insn()))
-      continue;
-
-    // TODO: reset dead debug instructions - those that are dependend on a 
dead phi
-    if (depends_on_dead_phi.count (insn) > 0) {
-      if (insn->is_debug_insn ())
-        reset_dead_debug_insn (insn);
-      continue;
-    }
-
-    gcc_checking_assert(insn->is_real ());
-
-    rtx_insn *rtl = insn->rtl ();
-    def_array defs = insn->defs ();
-    rtx rtx_set;
-
-    // If insn has debug uses and will be deleted, signalize it
-    if (!MAY_HAVE_DEBUG_BIND_INSNS ||
-      (rtx_set = single_set (rtl)) == NULL_RTX ||
-      side_effects_p (SET_SRC (rtx_set)) ||
-      asm_noperands (PATTERN (rtl)) >= 0)
-      continue;
-
-    // some of the checks might be duplicate:
-    if (insn->num_defs () != 1)
-      continue;
-
-    def_info *def = *defs.begin ();
-    if (def->kind () != access_kind::SET)
-      continue;
-
-    set_info *set = static_cast<set_info *> (def);
-    if (!set->has_nondebug_insn_uses ())
-      continue;
-
-    rtx dval = make_debug_expr_from_rtl (SET_DEST (rtx_set));
-
-    /* Emit a debug bind insn before the insn in which
-        reg dies.  */
-    rtx bind_var_loc =
-      gen_rtx_VAR_LOCATION (GET_MODE (SET_DEST (rtx_set)),
-          DEBUG_EXPR_TREE_DECL (dval),
-          SET_SRC (rtx_set),
-          VAR_INIT_STATUS_INITIALIZED);
-
-    obstack_watermark watermark = crtl->ssa->new_change_attempt();
-    insn_info *debug_insn = crtl->ssa->create_insn(watermark, DEBUG_INSN, 
bind_var_loc);
-    insn_change change(debug_insn);
-    change.new_uses = insn->uses();
-    change.move_range = insn_range_info(insn);
-
-    rtx_insn *bind = emit_debug_insn_before (bind_var_loc, rtl);
+    if (!rtl_ssa::restrict_movement (change))
+      std::cerr << "change move range location does not exists\n";
+    crtl->ssa->change_insn(change);
+    // rtx_insn *bind = emit_debug_insn_before (bind_var_loc, rtl);
 
     register_replacement replacement;
     for (use_info *u : set->all_uses ()) {
@@ -2111,82 +2070,38 @@ rtl_ssa_dce::debugize_insns (const 
std::unordered_set<insn_info *> &depends_on_d
     //    debugized, update a bitmap. If the instruction is dead, walk over
     //    its dependencies with worklist and reset the bitmap for visited 
     //    instructions.
-    // 2. Do the actual debugizing. 
-
-    rtx set;
-    // debugize_insns should be called only if MAY_HAVE_DEBUG_BIND_INSNS
-    if (MAY_HAVE_DEBUG_BIND_INSNS
-                 && (set = single_set (rtl)) != NULL_RTX
-      && !(*defs.begin ())->has_nondebug_insn_uses()
-                 // && is_dead_reg (SET_DEST (set), counts)
-      // Proc tam byla tato podminka?
-      // - debug statementy se sypou za kazdou definici ve zdrojaku, tedy 
-      // proto se chci ptat na to, kdyz existuje debug pouziti, tak je to 
-      // zajimava promenna
-                 /* Used at least once in some DEBUG_INSN.  */ 
-                 // && counts[REGNO (SET_DEST (set)) + nreg] > 0
-      // Tohle je ten bind nebo cast debug instrukce?
-                 /* And set exactly once.  */
-                 // && counts[REGNO (SET_DEST (set)) + nreg * 2] == 1
-                 && !side_effects_p (SET_SRC (set))
-                 && asm_noperands (PATTERN (rtl)) < 0)
-               {
-      // TODO: musime predratovat zavisle debug insn - vsechny uses na nove
-      //       vytvorenou debug insn
-                 /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL).  */
-                 rtx dval = make_debug_expr_from_rtl (SET_DEST (set));
-
-                 /* Emit a debug bind insn before the insn in which
-                    reg dies.  */
-                 rtx bind_var_loc =
-                   gen_rtx_VAR_LOCATION (GET_MODE (SET_DEST (set)),
-                                         DEBUG_EXPR_TREE_DECL (dval),
-                                         SET_SRC (set),
-                                         VAR_INIT_STATUS_INITIALIZED);
-                 // count_reg_usage (bind_var_loc, counts + nreg, NULL_RTX, 1);
-
-      rtl_ssa::obstack_watermark watermark = crtl->ssa->new_change_attempt();
-      insn_info *debug_insn = crtl->ssa->create_insn(watermark, DEBUG_INSN, 
rtx bind_var_loc);
-      insn_change change(debug_insn);
-      change.move_range = insn_range_info(insn)
-      // TODO: chains and defs
-
-      def_info *d = *defs.begin ();
-      if (d->kind() == access_kind::SET) {
-        set_info *s = static_cast<set_info *>(d);
-        for (use_info *u : s->all_uses()) {
-          // TODO: transform dependent insns
-        }
-      }
+    // 2. Do the actual debugizing.
+
+    // rtx set;
+    // // debugize_insns should be called only if MAY_HAVE_DEBUG_BIND_INSNS
+    // if (MAY_HAVE_DEBUG_BIND_INSNS
+               //   && (set = single_set (rtl)) != NULL_RTX
+    //   && !(*defs.begin ())->has_nondebug_insn_uses()
+               //   // && is_dead_reg (SET_DEST (set), counts)
+    //   // Proc tam byla tato podminka?
+    //   // - debug statementy se sypou za kazdou definici ve zdrojaku, tedy 
+    //   // proto se chci ptat na to, kdyz existuje debug pouziti, tak je to 
+    //   // zajimava promenna
+               //   /* Used at least once in some DEBUG_INSN.  */ 
+               //   // && counts[REGNO (SET_DEST (set)) + nreg] > 0
+    //   // Tohle je ten bind nebo cast debug instrukce?
+               //   /* And set exactly once.  */
+               //   // && counts[REGNO (SET_DEST (set)) + nreg * 2] == 1
+               //   && !side_effects_p (SET_SRC (set))
+               //   && asm_noperands (PATTERN (rtl)) < 0)
+               // {
 
-                 rtx_insn *bind = emit_debug_insn_before (bind_var_loc, rtl);
-
-                 // if (replacements == NULL)
-                   // replacements = XCNEWVEC (rtx, nreg);
-                 // replacements[REGNO (SET_DEST (set))] = dval;
-    }   
+    // }
   }
 
+  sbitmap_free (debugizable);
   // TODO: check that all of the debug insn uses are live,
-  // othervise reset the instruction
+  // otherwise reset the instruction
 }
 
 static void
 test (insn_info *insn)
 {
-  rtx_insn *rtl = insn->rtl ();
-  rtx set = single_set (rtl);
-  if (set == NULL_RTX || side_effects_p (SET_SRC (set))
-      || asm_noperands (PATTERN (rtl)) >= 0)
-    return;
-
-  rtx dval = make_debug_expr_from_rtl (SET_DEST (set));
-  rtx bind_var_loc
-    = gen_rtx_VAR_LOCATION (GET_MODE (SET_DEST (set)),
-                           DEBUG_EXPR_TREE_DECL (dval), SET_SRC (set),
-                           VAR_INIT_STATUS_INITIALIZED);
-
-  obstack_watermark watermark = crtl->ssa->new_change_attempt();
   // Radeji bych zde videl pridani dval do rtl ssa
   // crtl->ssa->create_insn(watermark, DEBUG_INSN, rtx pat);
 
diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
index 3e2c4309dee6..3e1e9a633c24 100644
--- a/gcc/emit-rtl.cc
+++ b/gcc/emit-rtl.cc
@@ -4153,7 +4153,7 @@ make_insn_raw (rtx pattern)
 
 /* Like `make_insn_raw' but make a DEBUG_INSN instead of an insn.  */
 
-static rtx_insn *
+rtx_insn *
 make_debug_insn_raw (rtx pattern)
 {
   rtx_debug_insn *insn;
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index 4657aec47cd8..62518c515c92 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -256,7 +256,7 @@ rtl_ssa::changes_are_worthwhile (array_slice<insn_change 
*const> changes,
 // 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, auto_sbitmap& 
visited_phis)
+function_info::process_uses_of_deleted_def (set_info *set, auto_sbitmap 
&visited_phis)
 {
   if (!set->has_any_uses ())
     return;
@@ -268,7 +268,7 @@ function_info::process_uses_of_deleted_def (set_info *set, 
auto_sbitmap& visited
       if (use->is_in_phi ())
        {
          // This call will not recurse.
-         process_uses_of_deleted_def (use->phi ());
+         process_uses_of_deleted_def (use->phi (), visited_phis);
          delete_phi (use->phi ());
        }
       else
@@ -861,8 +861,8 @@ function_info::change_insns (array_slice<insn_change *> 
changes)
          auto *set = dyn_cast<set_info *> (def);
          if (set && set->has_any_uses ())
            {
-                       auto_sbitmap phis(m_next_phi_uid);
-                       process_uses_of_deleted_def (set);
+                       auto_sbitmap visited_phis(m_next_phi_uid);
+                       process_uses_of_deleted_def (set, visited_phis);
                }
          remove_def (def);
        }
diff --git a/gcc/rtl-ssa/functions.h b/gcc/rtl-ssa/functions.h
index 2e20f5e47d72..033154dfa586 100644
--- a/gcc/rtl-ssa/functions.h
+++ b/gcc/rtl-ssa/functions.h
@@ -306,7 +306,7 @@ private:
   bb_info *create_bb_info (basic_block);
   void append_bb (bb_info *);
 
-  void process_uses_of_deleted_def (set_info *);
+  void process_uses_of_deleted_def (set_info *set, auto_sbitmap &);
   insn_info *add_placeholder_after (insn_info *);
   void possibly_queue_changes (insn_change &);
   void finalize_new_accesses (insn_change &, insn_info *,
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 3b676c468805..15045376e2bc 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3375,6 +3375,7 @@ extern rtx_insn *emit_clobber (rtx);
 extern rtx_insn *gen_use (rtx);
 extern rtx_insn *emit_use (rtx);
 extern rtx_insn *make_insn_raw (rtx);
+extern rtx_insn *make_debug_insn_raw (rtx);
 extern void add_function_usage_to (rtx, rtx);
 extern rtx_call_insn *last_call_insn (void);
 extern rtx_insn *previous_insn (rtx_insn *);

Reply via email to