https://gcc.gnu.org/g:175c246015a7c0f4d23c79b883467edfd4680855

commit 175c246015a7c0f4d23c79b883467edfd4680855
Author: Ondřej Machota <ondrejmach...@gmail.com>
Date:   Tue Feb 18 07:04:16 2025 +0100

    rtl-ssa: dce add prelive conditions

Diff:
---
 gcc/dce.cc | 160 ++++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 112 insertions(+), 48 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 929cb259e6d6..c3fdb32688bf 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -17,6 +17,7 @@ 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 <cassert>
 #define INCLUDE_ALGORITHM
 #define INCLUDE_FUNCTIONAL
 #include "config.h"
@@ -39,6 +40,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "dbgcnt.h"
 #include "rtl-iter.h"
+#include <unordered_set>
 
 using namespace rtl_ssa;
 
@@ -1237,30 +1239,81 @@ namespace
 
 } // namespace
 
-bool is_inherently_live(insn_info *insn)
+bool sets_global_register(rtx_insn* insn) {
+  rtx set = single_set(insn);
+  if (!set)
+    return false;
+
+  rtx dest = SET_DEST(set);
+  if (REG_P(dest) && HARD_REGISTER_NUM_P(REGNO(dest)) && 
global_regs[REGNO(dest)]) {
+    return true;
+  }
+
+  return false;
+}
+
+bool is_prelive(insn_info *insn)
 {
-  return insn->num_uses() > 0;
+  if (insn->is_artificial()) // phis are never prelive
+    return false;
+
+  /*
+   * There are a few functions we can use to detect if an instruction is
+   * inherently live:
+   * rtlanal.cc:
+   *  bool side_effects_p (const_rtx x);
+   *  bool volatile_insn_p (const_rtx x);
+   *
+   * rtlanal.h
+   *  bool has_side_effects (); inside class rtx_properties
+   *
+   * dce.cc:
+   *  static bool deletable_insn_p_1(rtx body); uses bool volatile_insn_p 
(const_rtx x);
+   *  static bool deletable_insn_p(rtx_insn *insn, bool fast, bitmap 
arg_stores);
+   * 
+   * Possibly the most accurate way would be to rewrite `static bool
+   * deletable_insn_p(rtx_insn *insn, bool fast, bitmap arg_stores);`
+   * 
+  */
+
+  // Now, we only have to handle rtx insns
+  assert(insn->is_real());
+  auto rtl = insn->rtl();
+
+  if (!INSN_P(rtl)) // This might be useless
+    return false;
+
+  rtx pat = PATTERN(rtl); // if we use this instead of rtl, then rtl notes 
wont be checked
+  
+  // TODO : join if statements
+
+  if (JUMP_P(rtl))
+    return true;
+
+  // We need to describe all possible prelive instructions, a list of all the 
instructions is inside `rtl.def`
+
+  // Mark set of a global register
+  if (sets_global_register(rtl))
+    return true;
+
+  // Call is inside side_effects_p
+  if (side_effects_p(rtl) || volatile_refs_p(rtl) || can_throw_internal(rtl))
+    return true;
+
+  return false;
 }
 
 static void
-rtl_ssa_dce_init(sbitmap &marked_rtx)
+rtl_ssa_dce_init()
 {
   calculate_dominance_info(CDI_DOMINATORS);
+  // here we create ssa form for function
   crtl->ssa = new rtl_ssa::function_info(cfun);
-
-  marked_rtx = sbitmap_alloc(get_max_uid() + 1);
-  bitmap_clear(marked_rtx);
-  if (dump_file)
-    fprintf(dump_file, "Allocated `marked_rtx` with size: %d\n", get_max_uid() 
+ 1);
 }
 
 static void
-rtl_ssa_dce_done(sbitmap marked_rtx)
+rtl_ssa_dce_done()
 {
-  sbitmap_free(marked_rtx);
-  if (dump_file)
-    fprintf(dump_file, "Freed `marked_rtx`\n");
-
   free_dominance_info(CDI_DOMINATORS);
   if (crtl->ssa->perform_pending_updates())
     cleanup_cfg(0);
@@ -1273,24 +1326,20 @@ rtl_ssa_dce_done(sbitmap marked_rtx)
 }
 
 static void
-rtl_ssa_dce_mark_live(insn_info *info, vec<insn_info *> &worklist, sbitmap 
marked_rtx)
+rtl_ssa_dce_mark_live(insn_info *info, vec<insn_info *> &worklist, 
std::unordered_set<insn_info *> marked)
 {
   int info_uid = info->uid();
   if (dump_file)
   {
     fprintf(dump_file, "  Adding insn %d to worklist\n", info_uid);
   }
-  if (info_uid < 0)
-  {
-      return;
-  }
-  bitmap_set_bit(marked_rtx, info_uid);
 
+  marked.emplace(info);
   worklist.safe_push(info);
 }
 
-static void
-rtl_ssa_dce_mark(sbitmap marked_rtx)
+static auto_vec<insn_info *>
+rtl_ssa_dce_prelive(std::unordered_set<insn_info *> marked)
 {
   insn_info *next;
   auto_vec<insn_info *> worklist;
@@ -1316,9 +1365,9 @@ rtl_ssa_dce_mark(sbitmap marked_rtx)
     * Is seems, that insn->uid() is uniq enough
     */
 
-    if (is_inherently_live(insn))
+    if (is_prelive(insn))
     {
-      rtl_ssa_dce_mark_live(insn, worklist, marked_rtx);
+      rtl_ssa_dce_mark_live(insn, worklist, marked);
     }
 
     // if (insn->can_be_optimized () || insn->is_debug_insn ())
@@ -1326,12 +1375,18 @@ rtl_ssa_dce_mark(sbitmap marked_rtx)
     //  worklist.safe_push (insn);
   }
 
+  return worklist;
+}
+
+static void
+rtl_ssa_dce_mark(std::unordered_set<insn_info *> marked)
+{
+  auto worklist = rtl_ssa_dce_prelive(marked);
+
   if (dump_file)
     fprintf(dump_file, "Finished inherently live, marking parents\n");
   while (!worklist.is_empty())
   {
-    if (dump_file)
-      fprintf(dump_file, "Brruuh; ");
     insn_info *insn = worklist.pop();
     def_array defs = insn->defs(); // array - because of phi?
     if (dump_file)
@@ -1340,29 +1395,34 @@ rtl_ssa_dce_mark(sbitmap marked_rtx)
     {
       insn_info *parent_insn = defs[i]->insn();
       int parent_insn_uid = parent_insn->uid();
-      if (parent_insn_uid < 0)
-      {
-        continue;
-      }
+      // propage that some instruction in chain is live from bottom to top
       if (dump_file)
         fprintf(dump_file, "Trying to add: %d\n", parent_insn_uid);
-      if (!bitmap_bit_p(marked_rtx, parent_insn_uid))
+      // not yet marked
+      if (!(marked.count(parent_insn) > 0))
       {
         if (dump_file)
           fprintf(dump_file, "  Adding insn %d to worklist - mark\n", 
parent_insn_uid);
         worklist.safe_push(parent_insn);
-        if (parent_insn_uid >= 0)
-          bitmap_set_bit(marked_rtx, parent_insn_uid);
+        marked.emplace(parent_insn);
       }
     }
+
+    auto bb = insn->bb();
   }
+
+  // TODO : control dependence
 }
 
 static void
-rtl_ssa_dce_sweep(sbitmap marked_rtx)
+rtl_ssa_dce_sweep(std::unordered_set<insn_info *> marked)
 {
   insn_info *next;
-  auto_vec<insn_change const*> to_delete;
+  auto_vec<insn_change> to_delete;
+  // try to rewrite it with iterator?
+  // it might be better to iterate over `marked`
+  // we can get the number of items in the set and create an array of changes
+  // which will hopefully have constructor for array_slice<insn_info *>
   for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
   {
     if (dump_file)
@@ -1370,14 +1430,12 @@ rtl_ssa_dce_sweep(sbitmap marked_rtx)
       fprintf(dump_file, "Insn: %d\n", insn->uid());
     }
     next = insn->next_any_insn();
-    if (dump_file)
-    {
-      fprintf(dump_file, "  Sweeping insn %d\n", insn->uid());
-    }
-    if (insn->uid() < 0)
-      continue;
-    if (!bitmap_bit_p(marked_rtx, insn->uid()))
+    if (!(marked.count(insn) > 0))
     {
+      if (dump_file)
+      {
+        fprintf(dump_file, "  Sweeping insn %d\n", insn->uid());
+      }
       // rtx_insn* rtl = insn->rtl();
       // How to delete phis?
       // if (rtl != nullptr) {
@@ -1393,21 +1451,27 @@ rtl_ssa_dce_sweep(sbitmap marked_rtx)
       // insn->rtl()->set_deleted();
     }
   }
-  // array_slice<insn_change&> d(to_delete);
+  
+  auto_vec<insn_change*> changes{to_delete.length()};
+  for (auto i = 0; i != to_delete.length(); ++i) {
+    changes[i] = &to_delete[i];
+  }
 
-  // crtl->ssa->change_insns();
+  // if (verify_insn_changes())
+  crtl->ssa->change_insns(changes);
 }
 
 static unsigned int
 rtl_ssa_dce()
 {
   // I can do something like invert phi uid and shift it
-  sbitmap marked_rtx;
-  rtl_ssa_dce_init(marked_rtx);
-  rtl_ssa_dce_mark(marked_rtx);
-  rtl_ssa_dce_sweep(marked_rtx);
+  // unordered_set seems to be the easiest option
+  std::unordered_set<insn_info *> marked;
+  rtl_ssa_dce_init();
+  rtl_ssa_dce_mark(marked);
+  rtl_ssa_dce_sweep(marked);
+  rtl_ssa_dce_done();
 
-  rtl_ssa_dce_done(marked_rtx);
   return 0;
 }

Reply via email to