[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rlt-ssa: dce init and done functions

2024-05-05 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:8f4b6a6dadd92a06849b78af5630a2ca5dd70212

commit 8f4b6a6dadd92a06849b78af5630a2ca5dd70212
Author: Ondřej Machota 
Date:   Sun May 5 21:19:18 2024 +0200

rlt-ssa: dce init and done functions

Diff:
---
 gcc/dce.cc | 42 +++---
 1 file changed, 35 insertions(+), 7 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 9ded9256c3b..591a750e456 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -17,6 +17,8 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -25,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "predict.h"
 #include "df.h"
+#include "rtl-ssa.h"
 #include "memmodel.h"
 #include "tm_p.h"
 #include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
@@ -1292,7 +1295,37 @@ public:
 
 }; // class pass_fast_rtl_dce
 
-} // anon namespace
+} // namespace
+
+static void
+rtl_ssa_dce_init ()
+{
+calculate_dominance_info (CDI_DOMINATORS);
+crtl->ssa = new rtl_ssa::function_info (cfun);
+}
+
+static void
+rtl_ssa_dce_done ()
+{
+free_dominance_info (CDI_DOMINATORS);
+if (crtl->ssa->perform_pending_updates ())
+  cleanup_cfg (0);
+
+delete crtl->ssa;
+crtl->ssa = nullptr;
+
+if (dump_file)
+  fprintf (dump_file, "\nFinished running rtl_ssa_dce\n\n");
+}
+
+static unsigned int
+rtl_ssa_dce ()
+{
+rtl_ssa_dce_init ();
+
+rtl_ssa_dce_done ();
+return 0;
+}
 
 rtl_opt_pass *
 make_pass_fast_rtl_dce (gcc::context *ctxt)
@@ -1324,12 +1357,7 @@ public:
   /* opt_pass methods: */
   bool gate (function *) final override { return flag_dce; }
 
-  unsigned int execute (function *) final override
-  {
-if (dump_file)
-  fprintf (dump_file, "pass_rtl_ssa_dce called\n");
-return 0;
-  }
+  unsigned int execute (function *) final override { return rtl_ssa_dce (); }
 
 }; // class pass_fast_rtl_dce


[gcc] Created branch 'omachota/heads/rtl-ssa-dce' in namespace 'refs/users'

2024-04-20 Thread Ondrej Machota via Gcc-cvs
The branch 'omachota/heads/rtl-ssa-dce' was created in namespace 'refs/users' 
pointing to:

 f5447eae72f... Revert "RISC-V: Support highest overlap for wv instructions


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: Create new dce pass

2024-04-29 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:bf1ef45735e94247fe632602ee4dda091a5fd2bf

commit bf1ef45735e94247fe632602ee4dda091a5fd2bf
Author: Ondřej Machota 
Date:   Mon Apr 29 21:38:47 2024 +0200

rtl-ssa: Create new dce pass

Diff:
---
 gcc/dce.cc  | 41 +
 gcc/dce.h   |  1 +
 gcc/passes.def  |  2 +-
 gcc/tree-pass.h |  1 +
 4 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index be1a2a87732..9ded9256c3b 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1299,3 +1299,44 @@ make_pass_fast_rtl_dce (gcc::context *ctxt)
 {
   return new pass_fast_rtl_dce (ctxt);
 }
+
+namespace {
+
+const pass_data pass_data_rtl_ssa_dce = {
+  RTL_PASS,  /* type */
+  "rtl_ssa_dce",  /* name */
+  OPTGROUP_NONE,  /* optinfo_flags */
+  TV_DCE,/* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_df_finish, /* todo_flags_finish */
+};
+
+class pass_rtl_ssa_dce : public rtl_opt_pass
+{
+public:
+  pass_rtl_ssa_dce (gcc::context *ctxt)
+: rtl_opt_pass (pass_data_rtl_ssa_dce, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate (function *) final override { return flag_dce; }
+
+  unsigned int execute (function *) final override
+  {
+if (dump_file)
+  fprintf (dump_file, "pass_rtl_ssa_dce called\n");
+return 0;
+  }
+
+}; // class pass_fast_rtl_dce
+
+} // namespace
+
+rtl_opt_pass *
+make_pass_rtl_ssa_dce (gcc::context *ctxt)
+{
+  return new pass_rtl_ssa_dce (ctxt);
+}
diff --git a/gcc/dce.h b/gcc/dce.h
index 346fb28d80e..806aa6a18bc 100644
--- a/gcc/dce.h
+++ b/gcc/dce.h
@@ -23,5 +23,6 @@ along with GCC; see the file COPYING3.  If not see
 extern void run_word_dce (void);
 extern void run_fast_dce (void);
 extern void run_fast_df_dce (void);
+extern void run_rtl_ssa_dce (void);
 
 #endif /* GCC_DCE_H */
diff --git a/gcc/passes.def b/gcc/passes.def
index 1cbbd413097..f55a2ee5e82 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -526,7 +526,7 @@ along with GCC; see the file COPYING3.  If not see
  NEXT_PASS (pass_regrename);
  NEXT_PASS (pass_fold_mem_offsets);
  NEXT_PASS (pass_cprop_hardreg);
- NEXT_PASS (pass_fast_rtl_dce);
+ NEXT_PASS (pass_rtl_ssa_dce);
  NEXT_PASS (pass_reorder_blocks);
  NEXT_PASS (pass_leaf_regs);
  NEXT_PASS (pass_split_before_sched2);
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 29267589eeb..fbdd95a1e04 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -562,6 +562,7 @@ extern rtl_opt_pass *make_pass_jump2 (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_lower_subreg (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_cse (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_fast_rtl_dce (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_ssa_dce (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_ud_rtl_dce (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_rtl_dce (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_rtl_dse1 (gcc::context *ctxt);


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce fix mark compile and sweep sketch

2024-09-29 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:96c7ea34796ff0c661209c4fa4caebb78ec3428f

commit 96c7ea34796ff0c661209c4fa4caebb78ec3428f
Author: Ondřej Machota 
Date:   Sun Sep 29 22:17:46 2024 +0200

rtl-ssa: dce fix mark compile and sweep sketch

Diff:
---
 gcc/dce.cc | 1658 +---
 1 file changed, 807 insertions(+), 851 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index f59bc6c6ffa2..cde7d7f3c83d 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -30,7 +30,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "rtl-ssa.h"
 #include "memmodel.h"
 #include "tm_p.h"
-#include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
+#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h.  */
 #include "cfgrtl.h"
 #include "cfgbuild.h"
 #include "cfgcleanup.h"
@@ -42,7 +42,6 @@ along with GCC; see the file COPYING3.  If not see
 
 using namespace rtl_ssa;
 
-
 /* -
Core mark/delete routines
- */
@@ -65,57 +64,57 @@ static sbitmap marked;
 static bitmap_obstack dce_blocks_bitmap_obstack;
 static bitmap_obstack dce_tmp_bitmap_obstack;
 
-static bool find_call_stack_args (rtx_call_insn *, bool, bool, bitmap);
+static bool find_call_stack_args(rtx_call_insn *, bool, bool, bitmap);
 
 /* A subroutine for which BODY is part of the instruction being tested;
either the top-level pattern, or an element of a PARALLEL.  The
instruction is known not to be a bare USE or CLOBBER.  */
 
 static bool
-deletable_insn_p_1 (rtx body)
+deletable_insn_p_1(rtx body)
 {
-  switch (GET_CODE (body))
-{
-case PREFETCH:
-case TRAP_IF:
-  /* The UNSPEC case was added here because the ia-64 claims that
-USEs do not work after reload and generates UNSPECS rather
-than USEs.  Since dce is run after reload we need to avoid
-deleting these even if they are dead.  If it turns out that
-USEs really do work after reload, the ia-64 should be
-changed, and the UNSPEC case can be removed.  */
-case UNSPEC:
-  return false;
+  switch (GET_CODE(body))
+  {
+  case PREFETCH:
+  case TRAP_IF:
+/* The UNSPEC case was added here because the ia-64 claims that
+ USEs do not work after reload and generates UNSPECS rather
+ than USEs.  Since dce is run after reload we need to avoid
+ deleting these even if they are dead.  If it turns out that
+ USEs really do work after reload, the ia-64 should be
+ changed, and the UNSPEC case can be removed.  */
+  case UNSPEC:
+return false;
 
-default:
-  return !volatile_refs_p (body);
-}
+  default:
+return !volatile_refs_p(body);
+  }
 }
 
 /* Don't delete calls that may throw if we cannot do so.  */
 
 static bool
-can_delete_call (rtx_insn *insn)
+can_delete_call(rtx_insn *insn)
 {
   if (cfun->can_delete_dead_exceptions && can_alter_cfg)
 return true;
-  if (!insn_nothrow_p (insn))
+  if (!insn_nothrow_p(insn))
 return false;
   if (can_alter_cfg)
 return true;
   /* If we can't alter cfg, even when the call can't throw exceptions, it
  might have EDGE_ABNORMAL_CALL edges and so we shouldn't delete such
  calls.  */
-  gcc_assert (CALL_P (insn));
-  if (BLOCK_FOR_INSN (insn) && BB_END (BLOCK_FOR_INSN (insn)) == insn)
-{
-  edge e;
-  edge_iterator ei;
-
-  FOR_EACH_EDGE (e, ei, BLOCK_FOR_INSN (insn)->succs)
-   if ((e->flags & EDGE_ABNORMAL_CALL) != 0)
- return false;
-}
+  gcc_assert(CALL_P(insn));
+  if (BLOCK_FOR_INSN(insn) && BB_END(BLOCK_FOR_INSN(insn)) == insn)
+  {
+edge e;
+edge_iterator ei;
+
+FOR_EACH_EDGE(e, ei, BLOCK_FOR_INSN(insn)->succs)
+if ((e->flags & EDGE_ABNORMAL_CALL) != 0)
+  return false;
+  }
   return true;
 }
 
@@ -123,175 +122,156 @@ can_delete_call (rtx_insn *insn)
the DCE pass.  */
 
 static bool
-deletable_insn_p (rtx_insn *insn, bool fast, bitmap arg_stores)
+deletable_insn_p(rtx_insn *insn, bool fast, bitmap arg_stores)
 {
   rtx body, x;
   int i;
   df_ref def;
 
-  if (CALL_P (insn)
+  if (CALL_P(insn)
   /* We cannot delete calls inside of the recursive dce because
-this may cause basic blocks to be deleted and this messes up
-the rest of the stack of optimization passes.  */
+   this may cause basic blocks to be deleted and this messes up
+   the rest of the stack of optimization passes.  */
   && (!df_in_progress)
   /* We cannot delete pure or const sibling calls because it is
-hard to see the result.  */
-  && (!SIBLING_CALL_P (insn))
+   hard to see the result.  */
+  && (!SIBLING_CALL_P(insn))
   /* We can delete dead const or pure calls as long as they do not
  infinite loop.  */
-  && (RTL_CONST_OR_PURE_CALL_P (insn)
- && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))
+  && (RTL_CONST_OR_PURE_CALL_P(insn) && 
!RTL_L

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce fix uid

2024-10-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:cde5332b496943e584748870e65265549102077f

commit cde5332b496943e584748870e65265549102077f
Author: Ondřej Machota 
Date:   Mon Oct 21 16:54:52 2024 +0200

rtl-ssa: dce fix uid

Diff:
---
 gcc/dce.cc | 44 +++-
 1 file changed, 35 insertions(+), 9 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index cde7d7f3c83d..716236d79c1b 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1239,6 +1239,7 @@ namespace
 
 bool is_inherently_live(insn_info *insn)
 {
+  return insn->num_uses() > 0;
 }
 
 static void
@@ -1262,6 +1263,17 @@ rtl_ssa_dce_done()
 fprintf(dump_file, "\nFinished running rtl_ssa_dce\n\n");
 }
 
+static void
+rtl_ssa_dce_mark_live(insn_info *info, auto_vec worklist, sbitmap 
marked) {
+  int info_uid = info->uid();
+  bitmap_set_bit(marked, info_uid);
+  if (dump_file) {
+fprintf(dump_file, "  Adding insn %d to worklist\n", info_uid);
+  }
+
+  worklist.safe_push(info);
+}
+
 static void
 rtl_ssa_dce_mark(sbitmap marked)
 {
@@ -1279,12 +1291,19 @@ rtl_ssa_dce_mark(sbitmap marked)
 */
 // insn.defs() // UD chain - this is what I want - reach the ancestors\
  // insn.uses() // DU chain
+
+/*
+* For marking phi nodes, which don't have uid (insn->rtl() is null) by 
definition, use a dictionary and store their addresses
+* Is seems, that insn->uid() is uniq enough
+*/
+
 if (is_inherently_live(insn))
 {
   if (dump_file)
-fprintf(dump_file, "  Adding insn %d to worklist\n", 
INSN_UID(insn->rtl()));
+fprintf(dump_file, "  Adding insn %d to worklist\n", insn->uid());
+  rtl_ssa_dce_mark_live(insn, marked);
   worklist.safe_push(insn);
-  bitmap_set_bit(marked, INSN_UID(insn->rtl()));
+  bitmap_set_bit(marked, insn->uid());
 }
 
 // if (insn->can_be_optimized () || insn->is_debug_insn ())
@@ -1301,12 +1320,13 @@ rtl_ssa_dce_mark(sbitmap marked)
 
   insn_info *parent_insn = defs[i]->insn();
 
-  if (!bitmap_bit_p(marked, INSN_UID(parent_insn->rtl(
+  int parent_insn_uid = parent_insn->uid();
+  if (!bitmap_bit_p(marked, parent_insn_uid))
   {
 if (dump_file)
-  fprintf(dump_file, "  Adding insn %d to worklist\n", 
INSN_UID(parent_insn->rtl()));
+  fprintf(dump_file, "  Adding insn %d to worklist\n", 
parent_insn_uid);
 worklist.safe_push(parent_insn);
-bitmap_set_bit(marked, INSN_UID(parent_insn->rtl()));
+bitmap_set_bit(marked, parent_insn_uid);
   }
 }
   }
@@ -1318,10 +1338,16 @@ rtl_ssa_dce_sweep(sbitmap marked)
   insn_info *next;
   for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
   {
-  if (!bitmap_bit_p(marked, INSN_UID(insn->rtl( {
-insn->rtl()->set_deleted();
-// delete
-  }
+if (!bitmap_bit_p(marked, insn->uid())) {
+  // rtx_insn* rtl = insn->rtl();
+  // How to delete phis?
+  // if (rtl != nullptr) {
+  //   delete_insn(rtl);
+  // }
+  // insn_change::delete_insn(insn);
+  crtl->ssa->possibly_queue_changes(insn_change::delete_insn(insn))
+  // insn->rtl()->set_deleted();
+}
   }
 }


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce fix working with sbitmap

2024-10-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:d0095cfa468ae39a6b0c2e44951b2772f734a33a

commit d0095cfa468ae39a6b0c2e44951b2772f734a33a
Author: Ondřej Machota 
Date:   Tue Oct 22 08:40:34 2024 +0200

rtl-ssa: dce fix working with sbitmap

Diff:
---
 gcc/dce.cc | 107 -
 1 file changed, 77 insertions(+), 30 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 716236d79c1b..929cb259e6d6 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1243,15 +1243,24 @@ bool is_inherently_live(insn_info *insn)
 }
 
 static void
-rtl_ssa_dce_init()
+rtl_ssa_dce_init(sbitmap &marked_rtx)
 {
   calculate_dominance_info(CDI_DOMINATORS);
   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()
+rtl_ssa_dce_done(sbitmap marked_rtx)
 {
+  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);
@@ -1264,23 +1273,33 @@ rtl_ssa_dce_done()
 }
 
 static void
-rtl_ssa_dce_mark_live(insn_info *info, auto_vec worklist, sbitmap 
marked) {
+rtl_ssa_dce_mark_live(insn_info *info, vec &worklist, sbitmap 
marked_rtx)
+{
   int info_uid = info->uid();
-  bitmap_set_bit(marked, info_uid);
-  if (dump_file) {
+  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);
 
   worklist.safe_push(info);
 }
 
 static void
-rtl_ssa_dce_mark(sbitmap marked)
+rtl_ssa_dce_mark(sbitmap marked_rtx)
 {
   insn_info *next;
   auto_vec worklist;
   for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
   {
+if (dump_file)
+{
+  fprintf(dump_file, "Insn: %d\n", insn->uid());
+}
 next = insn->next_any_insn();
 /*
 I would like to mark visited instruction with something like plf (Pass 
local flags) as in gimple
@@ -1288,22 +1307,18 @@ rtl_ssa_dce_mark(sbitmap marked)
 This file contains some useful functions: e.g. marked_insn_p, mark_insn
 mark_insn does much more than I want now...
 It does quite a useful job. If rtl_insn is a call and it is obsolete, it 
will find call arguments.
-*/
-// insn.defs() // UD chain - this is what I want - reach the ancestors\
- // insn.uses() // DU chain
 
-/*
+insn.defs() // UD chain - this is what I want - reach the ancestors\
+insn.uses() // DU chain
+
+
 * For marking phi nodes, which don't have uid (insn->rtl() is null) by 
definition, use a dictionary and store their addresses
 * Is seems, that insn->uid() is uniq enough
 */
 
 if (is_inherently_live(insn))
 {
-  if (dump_file)
-fprintf(dump_file, "  Adding insn %d to worklist\n", insn->uid());
-  rtl_ssa_dce_mark_live(insn, marked);
-  worklist.safe_push(insn);
-  bitmap_set_bit(marked, insn->uid());
+  rtl_ssa_dce_mark_live(insn, worklist, marked_rtx);
 }
 
 // if (insn->can_be_optimized () || insn->is_debug_insn ())
@@ -1311,56 +1326,88 @@ rtl_ssa_dce_mark(sbitmap marked)
 //  worklist.safe_push (insn);
   }
 
+  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)
+  fprintf(dump_file, "Looking at: %d, defs: %d\n", insn->uid(), 
defs.size());
 for (size_t i = 0; i < defs.size(); i++)
 {
-
   insn_info *parent_insn = defs[i]->insn();
-
   int parent_insn_uid = parent_insn->uid();
-  if (!bitmap_bit_p(marked, parent_insn_uid))
+  if (parent_insn_uid < 0)
+  {
+continue;
+  }
+  if (dump_file)
+fprintf(dump_file, "Trying to add: %d\n", parent_insn_uid);
+  if (!bitmap_bit_p(marked_rtx, parent_insn_uid))
   {
 if (dump_file)
-  fprintf(dump_file, "  Adding insn %d to worklist\n", 
parent_insn_uid);
+  fprintf(dump_file, "  Adding insn %d to worklist - mark\n", 
parent_insn_uid);
 worklist.safe_push(parent_insn);
-bitmap_set_bit(marked, parent_insn_uid);
+if (parent_insn_uid >= 0)
+  bitmap_set_bit(marked_rtx, parent_insn_uid);
   }
 }
   }
 }
 
 static void
-rtl_ssa_dce_sweep(sbitmap marked)
+rtl_ssa_dce_sweep(sbitmap marked_rtx)
 {
   insn_info *next;
+  auto_vec to_delete;
   for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
   {
-if (!bitmap_bit_p(marked, insn->uid())) {
+if (dump_file)
+{
+  fprintf(dump_file, "Insn: %d\n", insn->uid());
+}
+next = insn->next_any_insn();
+if (dump_file)
+{
+  fprintf

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce mark sketch

2024-09-29 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:18c34785c85295f2366c0a0a110f33f4da260ba4

commit 18c34785c85295f2366c0a0a110f33f4da260ba4
Author: Ondřej Machota 
Date:   Sun Sep 29 20:20:11 2024 +0200

rtl-ssa: dce mark sketch

Diff:
---
 gcc/dce.cc | 57 +
 1 file changed, 57 insertions(+)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 591a750e4566..f59bc6c6ffa2 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -40,6 +40,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "dbgcnt.h"
 #include "rtl-iter.h"
 
+using namespace rtl_ssa;
+
 
 /* -
Core mark/delete routines
@@ -1297,6 +1299,15 @@ public:
 
 } // namespace
 
+
+bool is_inherently_live(insn_info *insn) {
+
+}
+
+static void rti_ssa_dce_() {
+  
+}
+
 static void
 rtl_ssa_dce_init ()
 {
@@ -1323,6 +1334,52 @@ rtl_ssa_dce ()
 {
 rtl_ssa_dce_init ();
 
+insn_info *next;
+sbitmap marked;
+auto_vec worklist;
+for (insn_info *insn = crtl->ssa->first_insn (); insn; insn = next)
+{
+  next = insn->next_any_insn ();
+  auto *rtl = insn->rtl();
+  /*
+  I would like to mark visited instruction with something like plf (Pass 
local flags) as in gimple
+
+  This file contains some useful functions: e.g. marked_insn_p, mark_insn
+  mark_insn does much more than I want now...
+  It does quite a useful job. If rtl_insn is a call and it is obsolete, it 
will find call arguments.
+  */
+ // insn.defs() // UD chain - this is what I want - reach the ancestors\
+ // insn.uses() // DU chain
+  if (is_inherently_live(insn)) {
+if (dump_file)
+ fprintf (dump_file, "  Adding insn %d to worklist\n", 
INSN_UID (insn));
+worklist.safe_push (insn);
+bitmap_set_bit(marked, INSN_UID (insn)); 
+  }
+
+  //if (insn->can_be_optimized () || insn->is_debug_insn ())
+   // if (fwprop_insn (insn, fwprop_addr_p))
+   // worklist.safe_push (insn);
+}
+
+while (!worklist.is_empty())
+{
+  insn_info *insn = worklist.pop();
+  def_array defs = insn->defs(); // array - because of phi?
+  for (size_t i = 0; i < defs.size(); i++)
+  {
+
+insn_info* parent_insn = defs[i]->insn();
+
+if (!bitmap_bit_p(INSN_UID (parent_insn))) {
+  if (dump_file)
+ fprintf (dump_file, "  Adding insn %d to worklist\n", 
INSN_UID (parent_insn));
+  worklist.safe_push(parent_insn);
+  bitmap_set_bit(marked, INSN_UID (parent_insn)); 
+}
+  }
+}
+
 rtl_ssa_dce_done ();
 return 0;
 }


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce access phi node inputs

2025-03-15 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:742f2489b1d676ff0b98ac2de9ef52fe1dbf854d

commit 742f2489b1d676ff0b98ac2de9ef52fe1dbf854d
Author: Ondřej Machota 
Date:   Tue Mar 11 00:31:04 2025 +0100

rtl-ssa: dce access phi node inputs

Diff:
---
 gcc/dce.cc | 46 +-
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 3e6e47f19208..14d7e1fa9120 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1430,8 +1430,8 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   // According to the docs, rtl ssa does not contain noteS and barrierS 
   if (!NONJUMP_INSN_P (insn))
   {
-std::cerr << "found jump instruction\n";
-debug(insn);
+//std::cerr << "found jump instruction\n";
+//debug(insn);
 return true;
   }
 
@@ -1510,7 +1510,7 @@ bool is_prelive(insn_info *insn)
 return false;
 
   auto res = is_rtx_insn_prelive(rtl);
-  std::cerr << "Trying to mark insn: " << insn->uid() << " as prelive: " << 
res << '\n';
+  //std::cerr << "Trying to mark insn: " << insn->uid() << " as prelive: " << 
res << '\n';
 
   return is_rtx_insn_prelive(rtl);
 }
@@ -1589,11 +1589,25 @@ rtl_ssa_dce_mark()
   {
 insn_info *insn = worklist.pop();
 use_array uses = insn->uses();
+if (insn->is_phi()) {
+  std::cerr << "Phi : "<< insn->uid() << " - uses: " << insn->num_uses() 
<< ", defs:" << insn->num_defs() << '\n';
+  for (auto&& use : uses) {
+debug(use);
+std::cerr << '\n';
+  }
+} else if (insn->is_artificial()) {
+  std::cerr << "Artificial " << insn->uid() << " - uses: " << 
insn->num_uses() << ", defs:" << insn->num_defs() << '\n';
+  for (auto&& use : uses) {
+debug(use);
+std::cerr << '\n';
+  }
+}
 
 if (dump_file)
   fprintf(dump_file, "Looking at: %d, uses: %d\n", insn->uid(), 
uses.size());
 
-std::cerr << "Insn: " << insn->uid() << ", uses: " << uses.size() << '\n';
+//std::cerr << "Insn: " << insn->uid() << ", uses: " << uses.size() << 
'\n';
+  std::cerr << "Current: " << insn->uid() << '\n';
 for (size_t i = 0; i < uses.size(); i++)
 {
   // debug(uses[i]);
@@ -1605,7 +1619,18 @@ rtl_ssa_dce_mark()
   // std::cerr << '\n';
   // debug(use);
   // std::cerr << '\n';
+  
+  
   insn_info *parent_insn = use->def()->insn();
+  if (parent_insn->is_phi()) { // this is weird...
+// debug(use->def());
+phi_info * pi = as_a (use->def());
+// std::cerr << "phi inputs: " << pi->num_inputs() << '\n';
+for (auto&& input: pi->inputs()) {
+  use_info* phi_use = input;
+  std::cerr << "Via phi insn: " << phi_use->def()->insn()->uid() << 
'\n';
+}
+  }
   int parent_insn_uid = parent_insn->uid();
   // propage that some instruction in chain is live from bottom to top
   if (dump_file)
@@ -1613,9 +1638,11 @@ rtl_ssa_dce_mark()
   // not yet marked
   if (!(marked.count(parent_insn) > 0))
   {
-std::cerr << "Adding: " << parent_insn_uid << " to worklist";
+//std::cerr << "Adding: " << parent_insn_uid << " to worklist";
 if (dump_file)
   fprintf(dump_file, "  Adding insn %d to worklist - mark\n", 
parent_insn_uid);
+
+
 worklist.safe_push(parent_insn);
 marked.emplace(parent_insn);
   }
@@ -1625,7 +1652,8 @@ rtl_ssa_dce_mark()
   }
 
   for (auto&& insn : marked) {
-std::cerr << "Marked insn: " << insn->uid() << '\n';
+if (dump_file)
+  fprintf(dump_file, "  Marked insn: %d\n", insn->uid());
   }
 
   // TODO : control dependence
@@ -1672,7 +1700,7 @@ rtl_ssa_dce_sweep(std::unordered_set marked)
   }
 
   if (crtl->ssa->verify_insn_changes(changes)) {
-std::cerr << "Changes are correct\n";
+//std::cerr << "Changes are correct\n";
 crtl->ssa->change_insns(changes);
   } else {
 std::cerr << "Changes are not correct\n";
@@ -1685,7 +1713,7 @@ rtl_ssa_dce()
   rtl_ssa_dce_init();
   debug(crtl->ssa);
 
-  std::cerr << "Next phase: prelive + mark: \n";
+  //std::cerr << "Next phase: prelive + mark: \n";
   std::unordered_set marked = rtl_ssa_dce_mark();
   rtl_ssa_dce_sweep(marked);
   rtl_ssa_dce_done();
@@ -1723,7 +1751,7 @@ namespace
 }
 
 /* opt_pass methods: */
-bool gate(function *) final override { return flag_dce; }
+bool gate(function *) final override { return optimize > 0 && flag_dce; }
 
 unsigned int execute(function *) final override { return rtl_ssa_dce(); }


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: add may_trap_or_fault_p as another prelive condition

2025-03-16 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:ea280c3ed885befd456eb1b9a54601a93ebaf8af

commit ea280c3ed885befd456eb1b9a54601a93ebaf8af
Author: Ondřej Machota 
Date:   Sun Mar 16 12:41:31 2025 +0100

rtl-ssa-dce: add may_trap_or_fault_p as another prelive condition

Diff:
---
 gcc/dce.cc | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index c8c8be2293a1..55aeb64269ca 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1473,7 +1473,12 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (GET_CODE(body) == CLOBBER) // 
gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 return true;
 
-  if (side_effects_with_mem(body) || can_throw_internal(body))
+  // may_trap_or_fault_p helps a lot to pass some tests from 
RUNTESTSFLAGS=execute.exp
+  // e. g. this one: testsuite/gcc.c-torture/execute/20020418-1.c
+  // TODO : debug the testcase
+  // It seems that the issue was due to trap_if rtl insn and fixed with 
may_trap_or_fault_p
+  // What about can_throw_internal?
+  if (side_effects_with_mem(body) || can_throw_internal(body) || 
may_trap_or_fault_p(body))
 return true;
 
   // TODO : parallel, {pre,post}_{int,dec}, {pre,post}_modify, 
may_trap_or_fault_p
@@ -1523,6 +1528,8 @@ bool is_prelive(insn_info *insn)
 static void
 rtl_ssa_dce_init()
 {
+  // internal compiler error: gcc.c-torture/execute/20040811-1.c - 
rtl_ssa::function_info::add_phi_nodes
+
   calculate_dominance_info(CDI_DOMINATORS);
   // here we create ssa form for function
   crtl->ssa = new rtl_ssa::function_info(cfun);


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: improve prelive conditions (USE, TRAP_IF)

2025-03-18 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:a9bdb2c0c422b9d8d054c8dfe33892b85d01bcd3

commit a9bdb2c0c422b9d8d054c8dfe33892b85d01bcd3
Author: Ondřej Machota 
Date:   Tue Mar 18 20:40:21 2025 +0100

rtl-ssa-dce: improve prelive conditions (USE, TRAP_IF)

Diff:
---
 gcc/dce.cc | 31 +--
 1 file changed, 9 insertions(+), 22 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 74c1a6f8a879..6152b985ca31 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1314,6 +1314,8 @@ bool sets_global_register(const_rtx rtx) {
 
 // We should mark stack registers
 // use HARD_FRAME_POINTER_REGNUM, REGNO_PTR_FRAME_P
+// muzeme mit parallel, ktery ma napr. dva single sety, nebo asm statement
+// pouzit note_pattern_stores nebo note_stores
 bool sets_global_register(rtx_insn* insn) {
   rtx set = single_set(insn);
   if (!set)
@@ -1334,25 +1336,6 @@ bool sets_global_register(rtx_insn* insn) {
   return false;
 }
 
-bool is_control_flow(rtx_code code) {
-  // What about BARRIERs?
-  switch (code) {
-case JUMP_INSN:
-case JUMP_TABLE_DATA: // Be careful with Table jump addresses - ADDR_VEC, 
ADDR_DIFF_VEC, PREFETCH 
-case TRAP_IF:
-case IF_THEN_ELSE: // Also COMPARE?
-case COND_EXEC: // We might want to check the operation that is under this?
-case RETURN:
-case SIMPLE_RETURN:
-case EH_RETURN:
-case LABEL_REF:
-  return true;
-
-default:
-  return false;
-  }
-}
-
 bool side_effects_with_mem (const_rtx x)
 {
   const RTX_CODE code = GET_CODE (x);
@@ -1393,8 +1376,8 @@ bool side_effects_with_mem (const_rtx x)
return true;
 
 // This should rather by RTX_BODY in is_rtx_insn_prelive - like global 
clobber
-case USE:
-  return true;
+// case USE:
+  // return true;
 
 default:
   break;
@@ -1475,6 +1458,9 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (GET_CODE(body) == PREFETCH)
 return true;
 
+  if (GET_CODE(body) == USE || GET_CODE(body) == TRAP_IF || GET_CODE(body) == 
UNSPEC)
+return true;
+
   // See deletable_insn_p_1 for UNSPEC. TRAP_IF is caught by 
may_trap_or_fault_p
 
   // may_trap_or_fault_p helps a lot to pass some tests from 
RUNTESTSFLAGS=execute.exp
@@ -1482,7 +1468,8 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   // TODO : debug the testcase
   // It seems that the issue was due to trap_if rtl insn and fixed with 
may_trap_or_fault_p
   // What about can_throw_internal?
-  if (side_effects_with_mem(body) || can_throw_internal(body) || 
may_trap_or_fault_p(body))
+  // || can_throw_internal(body) - testy na ntb prochazi
+  if (side_effects_with_mem(body)) // || may_trap_or_fault_p(body))
 return true;
 
   return false;


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: mark global regs as prelive with ssa

2025-03-18 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:675ceb0fa20e7a1a3800e54dde2686d7ad8c5997

commit 675ceb0fa20e7a1a3800e54dde2686d7ad8c5997
Author: Ondřej Machota 
Date:   Tue Mar 18 22:55:02 2025 +0100

rtl-ssa-dce: mark global regs as prelive with ssa

Diff:
---
 gcc/dce.cc | 100 -
 1 file changed, 45 insertions(+), 55 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 6152b985ca31..5cc9f3129067 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1303,15 +1303,6 @@ public:
 
 } // namespace
 
-
-bool sets_global_register(const_rtx rtx) {
-  auto code = GET_CODE(rtx);
-  if (GET_RTX_CLASS(code) != RTX_INSN)
-return false;
-
-  return sets_global_register(static_cast(rtx));
-}
-
 // We should mark stack registers
 // use HARD_FRAME_POINTER_REGNUM, REGNO_PTR_FRAME_P
 // muzeme mit parallel, ktery ma napr. dva single sety, nebo asm statement
@@ -1324,12 +1315,12 @@ bool sets_global_register(rtx_insn* insn) {
   rtx dest = SET_DEST(set);
 
   // TODO : rewrite to simple return
-  //std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
+  std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
   //std::cerr << "register: " << REGNO(dest) << "\n";
   //debug(insn);
   // If I understand correctly, global_regs[i] is 1 iff reg i is used
   if (REG_P(dest) && HARD_REGISTER_NUM_P(REGNO(dest))) { // && 
global_regs[REGNO(dest)]
-//std::cerr << "sets_global_register: true\n";
+std::cerr << "sets_global_register: true\n";
 return true;
   }
 
@@ -1375,10 +1366,6 @@ bool side_effects_with_mem (const_rtx x)
 case ASM_OPERANDS:
return true;
 
-// This should rather by RTX_BODY in is_rtx_insn_prelive - like global 
clobber
-// case USE:
-  // return true;
-
 default:
   break;
 }
@@ -1448,8 +1435,8 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 return true;
 
   // Mark set of a global register
-  if (sets_global_register(insn)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
-return true;
+  // if (sets_global_register(insn)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
+  //   return true;
 
   rtx body = PATTERN(insn);
   if (GET_CODE(body) == CLOBBER) // 
gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
@@ -1469,7 +1456,7 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   // It seems that the issue was due to trap_if rtl insn and fixed with 
may_trap_or_fault_p
   // What about can_throw_internal?
   // || can_throw_internal(body) - testy na ntb prochazi
-  if (side_effects_with_mem(body)) // || may_trap_or_fault_p(body))
+  if (side_effects_with_mem(body)) // || may_trap_or_fault_p(body)) // 
replaced by TRAP_IF
 return true;
 
   return false;
@@ -1503,39 +1490,28 @@ bool is_prelive(insn_info *insn)
   gcc_assert (insn->is_real());
   auto rtl = insn->rtl();
 
-  if (!INSN_P(rtl)) // This might be useless
-return false;
+  for (auto&& __def : insn->defs()) {
+def_info * def = __def;
+if (!def->is_reg()) {
+  continue;
+}
+
+// this ignore clobbers, which is probably fine
+if (def->kind() == access_kind::SET && HARD_REGISTER_NUM_P(def->regno())) {
+  // We might try to write something like def->regno() == REGNO 
(pic_offset_table_rtx) ...
+  // TODO : else if (DF_REF_REG (def) == pic_offset_table_rtx && REGNO 
(pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
+  // std::cerr << "hello, dear hard register! regno: " << def->regno() << 
"\n";
+  // debug(rtl);
+  return true;
+}
+  }
 
-  auto res = is_rtx_insn_prelive(rtl);
+  // auto res = is_rtx_insn_prelive(rtl);
   //std::cerr << "Trying to mark insn: " << insn->uid() << " as prelive: " << 
res << '\n';
 
   return is_rtx_insn_prelive(rtl);
 }
 
-static void
-rtl_ssa_dce_init()
-{
-  // internal compiler error: gcc.c-torture/execute/20040811-1.c - 
rtl_ssa::function_info::add_phi_nodes
-
-  calculate_dominance_info(CDI_DOMINATORS);
-  // here we create ssa form for function
-  crtl->ssa = new rtl_ssa::function_info(cfun);
-}
-
-static void
-rtl_ssa_dce_done()
-{
-  free_dominance_info(CDI_DOMINATORS);
-  if (crtl->ssa->perform_pending_updates())
-cleanup_cfg(0);
-
-  delete crtl->ssa;
-  crtl->ssa = nullptr;
-
-  if (dump_file)
-fprintf(dump_file, "\nFinished running rtl_ssa_dce\n\n");
-}
-
 static void
 rtl_ssa_dce_mark_live(insn_info *info, vec &worklist, 
std::unordered_set &marked)
 {
@@ -1555,18 +1531,8 @@ rtl_ssa_dce_prelive(std::unordered_set 
&marked)
   for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
   {
 next = insn->next_any_insn();
-/*
-I would like to mark visited instruction with something like plf (Pass 
local flags) as in gimple
-
-This file contains some useful functions: e.g. marked_insn_p, mark_insn
-mark_insn does much more than I want now...
-It does quite a useful job. If rtl_insn is a call and it is obsolete, it 
will find call arguments.
-*/
-
 if (is_prelive

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce another prelive conditions

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:0a294fa7512b77426e8a5106f9679439a7729f74

commit 0a294fa7512b77426e8a5106f9679439a7729f74
Author: Ondřej Machota 
Date:   Tue Feb 25 08:44:25 2025 +0100

rtl-ssa: dce another prelive conditions

Diff:
---
 gcc/dce.cc | 125 -
 1 file changed, 100 insertions(+), 25 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 49bc4c3c6780..f51f27dbd143 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -17,6 +17,8 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+#include 
+#include 
 #define INCLUDE_ALGORITHM
 #define INCLUDE_FUNCTIONAL
 #define INCLUDE_ARRAY
@@ -1305,13 +1307,29 @@ public:
 } // namespace
 
 
+bool sets_global_register(const_rtx rtx) {
+  auto code = GET_CODE(rtx);
+  if (GET_RTX_CLASS(code) != RTX_INSN)
+return false;
+
+  return sets_global_register(static_cast(rtx));
+}
+
+// We should mark stack registers
 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)]) {
+
+  // TODO : rewrite to simple return
+  std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
+  std::cerr << "register: " << REGNO(dest) << "\n";
+  debug(insn);
+  // If I understand correctly, global_regs[i] is 1 iff reg i is used
+  if (REG_P(dest) && HARD_REGISTER_NUM_P(REGNO(dest))) { // && 
global_regs[REGNO(dest)]
+std::cerr << "sets_global_register: true\n";
 return true;
   }
 
@@ -1329,6 +1347,7 @@ bool is_control_flow(rtx_code code) {
 case RETURN:
 case SIMPLE_RETURN:
 case EH_RETURN:
+case LABEL_REF:
   return true;
 
 default:
@@ -1336,13 +1355,66 @@ bool is_control_flow(rtx_code code) {
   }
 }
 
-bool handle_rtl_previle(rtx_insn *insn) {
-  // TODO : handle everything except parallel
+bool is_unary_mem_modification(rtx_code code) {
+  switch (code) {
+case PRE_DEC:
+case PRE_INC:
+case POST_DEC:
+case POST_INC:
+case PRE_MODIFY:
+case POST_MODIFY:
+  return true;
+
+default:
+  return false;
+  }
+}
+
+bool is_rtx_insn_prelive(const_rtx rtx) {
+  if (rtx == nullptr) {
+return false;
+  }
+
+  auto code = GET_CODE(rtx);
+  if (is_control_flow(code))
+return true;
+
+  // Mark set of a global register
+  if (sets_global_register(rtx)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
+return true;
+
+  // Call is inside side_effects_p - how to mark parameter registers?
+  if (volatile_refs_p(rtx) || can_throw_internal(rtx) || BARRIER_P(rtx) || 
code == PREFETCH)
+return true;
+
+  if (is_unary_mem_modification(code))
+return true;
+
+  // TODO : parallel, {pre,post}_{int,dec}, {pre,post}_modify, 
may_trap_or_fault_p
+  // Parallel is handled by volatile_refs_p
+
+  switch (code) {
+
+  }
+
+  const char *const fmt = GET_RTX_FORMAT (code);
+  for (size_t i = 0; i < GET_RTX_LENGTH(code); ++i) {
+if (fmt[i] == 'e' && is_rtx_insn_prelive(XEXP(rtx, i))) {
+  return true;
+} else if (fmt[i] == 'E') {
+  for (size_t j = 0; j < XVECLEN(rtx, i); ++j) {
+if (is_rtx_insn_prelive(XVECEXP(rtx, i, j)))
+  return true;
+  }
+}
+  }
+
+  return false;
 }
 
 bool is_prelive(insn_info *insn)
 {
-  if (insn->is_artificial()) // phis are never prelive
+  if (insn->is_artificial()) // phis are never prelive, bb head + end are 
artificial
 return false;
 
   /*
@@ -1377,8 +1449,8 @@ bool is_prelive(insn_info *insn)
   // We need to describe all possible prelive instructions, a list of all the 
instructions is inside `rtl.def`
 
   // Control flow
-  auto rtl_code = GET_CODE(rtl);
-  if (is_control_flow(rtl_code))
+  auto code = GET_CODE(rtl);
+  if (is_control_flow(code))
 return true;
 
   // Mark set of a global register
@@ -1386,9 +1458,16 @@ bool is_prelive(insn_info *insn)
 return true;
 
   // Call is inside side_effects_p
-  if (volatile_refs_p(rtl) || can_throw_internal(rtl) || BARRIER_P(rtl) || 
rtl_code == PREFETCH)
+  std::cerr << "Prelive: " << GET_RTX_NAME(code) << '\n';
+  // debug(insn);
+  debug(rtl);
+  if (volatile_refs_p(rtl) || can_throw_internal(rtl) || BARRIER_P(rtl) || 
code == PREFETCH)
 return true;
 
+  if (code == PARALLEL) {
+
+  }
+
   // TODO : handle parallel, {pre,post}_{int,dec}, {pre,post}_modify
 
   return false;
@@ -1421,9 +1500,7 @@ rtl_ssa_dce_mark_live(insn_info *info, vec 
&worklist, std::unordere
 {
   int info_uid = info->uid();
   if (dump_file)
-  {
 fprintf(dump_file, "  Adding insn %d to worklist\n", info_uid);
-  }
 
   marked.emplace(info);
   worklist.safe_push(info);
@@ -1436,10 +1513,6 @@ rtl_ssa_dce_prelive(std::unordered_set 
marked)
   auto_vec worklist;
   for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
   {
-if (dump_fil

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: add may_trap_or_fault_p as another prelive condition

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:703df50da1f6c45a756c7c265e0326bbb1582cde

commit 703df50da1f6c45a756c7c265e0326bbb1582cde
Author: Ondřej Machota 
Date:   Sun Mar 16 12:41:31 2025 +0100

rtl-ssa-dce: add may_trap_or_fault_p as another prelive condition

Diff:
---
 gcc/dce.cc | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 58d763314778..091e5c620f5b 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1476,7 +1476,12 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (GET_CODE(body) == CLOBBER) // 
gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 return true;
 
-  if (side_effects_with_mem(body) || can_throw_internal(body))
+  // may_trap_or_fault_p helps a lot to pass some tests from 
RUNTESTSFLAGS=execute.exp
+  // e. g. this one: testsuite/gcc.c-torture/execute/20020418-1.c
+  // TODO : debug the testcase
+  // It seems that the issue was due to trap_if rtl insn and fixed with 
may_trap_or_fault_p
+  // What about can_throw_internal?
+  if (side_effects_with_mem(body) || can_throw_internal(body) || 
may_trap_or_fault_p(body))
 return true;
 
   // TODO : parallel, {pre,post}_{int,dec}, {pre,post}_modify, 
may_trap_or_fault_p
@@ -1526,6 +1531,8 @@ bool is_prelive(insn_info *insn)
 static void
 rtl_ssa_dce_init()
 {
+  // internal compiler error: gcc.c-torture/execute/20040811-1.c - 
rtl_ssa::function_info::add_phi_nodes
+
   calculate_dominance_info(CDI_DOMINATORS);
   // here we create ssa form for function
   crtl->ssa = new rtl_ssa::function_info(cfun);


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: mark global regs as prelive with ssa

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:44402e206e07ebeb817ac8587a87fe8438cb0b0e

commit 44402e206e07ebeb817ac8587a87fe8438cb0b0e
Author: Ondřej Machota 
Date:   Tue Mar 18 22:55:02 2025 +0100

rtl-ssa-dce: mark global regs as prelive with ssa

Diff:
---
 gcc/dce.cc | 100 -
 1 file changed, 45 insertions(+), 55 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 42b63cbcfb81..62ab115455c0 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1306,15 +1306,6 @@ public:
 
 } // namespace
 
-
-bool sets_global_register(const_rtx rtx) {
-  auto code = GET_CODE(rtx);
-  if (GET_RTX_CLASS(code) != RTX_INSN)
-return false;
-
-  return sets_global_register(static_cast(rtx));
-}
-
 // We should mark stack registers
 // use HARD_FRAME_POINTER_REGNUM, REGNO_PTR_FRAME_P
 // muzeme mit parallel, ktery ma napr. dva single sety, nebo asm statement
@@ -1327,12 +1318,12 @@ bool sets_global_register(rtx_insn* insn) {
   rtx dest = SET_DEST(set);
 
   // TODO : rewrite to simple return
-  //std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
+  std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
   //std::cerr << "register: " << REGNO(dest) << "\n";
   //debug(insn);
   // If I understand correctly, global_regs[i] is 1 iff reg i is used
   if (REG_P(dest) && HARD_REGISTER_NUM_P(REGNO(dest))) { // && 
global_regs[REGNO(dest)]
-//std::cerr << "sets_global_register: true\n";
+std::cerr << "sets_global_register: true\n";
 return true;
   }
 
@@ -1378,10 +1369,6 @@ bool side_effects_with_mem (const_rtx x)
 case ASM_OPERANDS:
return true;
 
-// This should rather by RTX_BODY in is_rtx_insn_prelive - like global 
clobber
-// case USE:
-  // return true;
-
 default:
   break;
 }
@@ -1451,8 +1438,8 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 return true;
 
   // Mark set of a global register
-  if (sets_global_register(insn)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
-return true;
+  // if (sets_global_register(insn)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
+  //   return true;
 
   rtx body = PATTERN(insn);
   if (GET_CODE(body) == CLOBBER) // 
gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
@@ -1472,7 +1459,7 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   // It seems that the issue was due to trap_if rtl insn and fixed with 
may_trap_or_fault_p
   // What about can_throw_internal?
   // || can_throw_internal(body) - testy na ntb prochazi
-  if (side_effects_with_mem(body)) // || may_trap_or_fault_p(body))
+  if (side_effects_with_mem(body)) // || may_trap_or_fault_p(body)) // 
replaced by TRAP_IF
 return true;
 
   return false;
@@ -1506,39 +1493,28 @@ bool is_prelive(insn_info *insn)
   gcc_assert (insn->is_real());
   auto rtl = insn->rtl();
 
-  if (!INSN_P(rtl)) // This might be useless
-return false;
+  for (auto&& __def : insn->defs()) {
+def_info * def = __def;
+if (!def->is_reg()) {
+  continue;
+}
+
+// this ignore clobbers, which is probably fine
+if (def->kind() == access_kind::SET && HARD_REGISTER_NUM_P(def->regno())) {
+  // We might try to write something like def->regno() == REGNO 
(pic_offset_table_rtx) ...
+  // TODO : else if (DF_REF_REG (def) == pic_offset_table_rtx && REGNO 
(pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
+  // std::cerr << "hello, dear hard register! regno: " << def->regno() << 
"\n";
+  // debug(rtl);
+  return true;
+}
+  }
 
-  auto res = is_rtx_insn_prelive(rtl);
+  // auto res = is_rtx_insn_prelive(rtl);
   //std::cerr << "Trying to mark insn: " << insn->uid() << " as prelive: " << 
res << '\n';
 
   return is_rtx_insn_prelive(rtl);
 }
 
-static void
-rtl_ssa_dce_init()
-{
-  // internal compiler error: gcc.c-torture/execute/20040811-1.c - 
rtl_ssa::function_info::add_phi_nodes
-
-  calculate_dominance_info(CDI_DOMINATORS);
-  // here we create ssa form for function
-  crtl->ssa = new rtl_ssa::function_info(cfun);
-}
-
-static void
-rtl_ssa_dce_done()
-{
-  free_dominance_info(CDI_DOMINATORS);
-  if (crtl->ssa->perform_pending_updates())
-cleanup_cfg(0);
-
-  delete crtl->ssa;
-  crtl->ssa = nullptr;
-
-  if (dump_file)
-fprintf(dump_file, "\nFinished running rtl_ssa_dce\n\n");
-}
-
 static void
 rtl_ssa_dce_mark_live(insn_info *info, vec &worklist, 
std::unordered_set &marked)
 {
@@ -1558,18 +1534,8 @@ rtl_ssa_dce_prelive(std::unordered_set 
&marked)
   for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
   {
 next = insn->next_any_insn();
-/*
-I would like to mark visited instruction with something like plf (Pass 
local flags) as in gimple
-
-This file contains some useful functions: e.g. marked_insn_p, mark_insn
-mark_insn does much more than I want now...
-It does quite a useful job. If rtl_insn is a call and it is obsolete, it 
will find call arguments.
-*/
-
 if (is_prelive

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: Create new dce pass

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:a4eff4f9b65f6adb0730a8a7b1945c649b157908

commit a4eff4f9b65f6adb0730a8a7b1945c649b157908
Author: Ondřej Machota 
Date:   Mon Apr 29 21:38:47 2024 +0200

rtl-ssa: Create new dce pass

Diff:
---
 gcc/dce.cc  | 41 +
 gcc/dce.h   |  1 +
 gcc/passes.def  |  2 +-
 gcc/tree-pass.h |  1 +
 4 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 6a6a845f2343..514b9fc809cf 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1302,3 +1302,44 @@ make_pass_fast_rtl_dce (gcc::context *ctxt)
 {
   return new pass_fast_rtl_dce (ctxt);
 }
+
+namespace {
+
+const pass_data pass_data_rtl_ssa_dce = {
+  RTL_PASS,  /* type */
+  "rtl_ssa_dce",  /* name */
+  OPTGROUP_NONE,  /* optinfo_flags */
+  TV_DCE,/* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_df_finish, /* todo_flags_finish */
+};
+
+class pass_rtl_ssa_dce : public rtl_opt_pass
+{
+public:
+  pass_rtl_ssa_dce (gcc::context *ctxt)
+: rtl_opt_pass (pass_data_rtl_ssa_dce, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate (function *) final override { return flag_dce; }
+
+  unsigned int execute (function *) final override
+  {
+if (dump_file)
+  fprintf (dump_file, "pass_rtl_ssa_dce called\n");
+return 0;
+  }
+
+}; // class pass_fast_rtl_dce
+
+} // namespace
+
+rtl_opt_pass *
+make_pass_rtl_ssa_dce (gcc::context *ctxt)
+{
+  return new pass_rtl_ssa_dce (ctxt);
+}
diff --git a/gcc/dce.h b/gcc/dce.h
index fc92be3f51b2..167d3065369c 100644
--- a/gcc/dce.h
+++ b/gcc/dce.h
@@ -23,5 +23,6 @@ along with GCC; see the file COPYING3.  If not see
 extern void run_word_dce (void);
 extern void run_fast_dce (void);
 extern void run_fast_df_dce (void);
+extern void run_rtl_ssa_dce (void);
 
 #endif /* GCC_DCE_H */
diff --git a/gcc/passes.def b/gcc/passes.def
index 9fd85a35a63d..51ce7276da28 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -531,7 +531,7 @@ along with GCC; see the file COPYING3.  If not see
  NEXT_PASS (pass_regrename);
  NEXT_PASS (pass_fold_mem_offsets);
  NEXT_PASS (pass_cprop_hardreg);
- NEXT_PASS (pass_fast_rtl_dce);
+ NEXT_PASS (pass_rtl_ssa_dce);
  NEXT_PASS (pass_reorder_blocks);
  NEXT_PASS (pass_leaf_regs);
  NEXT_PASS (pass_split_before_sched2);
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 217c31fbb09b..65639302875c 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -566,6 +566,7 @@ extern rtl_opt_pass *make_pass_jump2 (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_lower_subreg (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_cse (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_fast_rtl_dce (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_ssa_dce (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_ud_rtl_dce (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_rtl_dce (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_rtl_dse1 (gcc::context *ctxt);


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce some prelive conditions

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:a7cb3a2146967afb3ea16590347e7197090cd18a

commit a7cb3a2146967afb3ea16590347e7197090cd18a
Author: Ondřej Machota 
Date:   Fri Feb 21 14:11:36 2025 +0100

rtl-ssa: dce some prelive conditions

Diff:
---
 gcc/dce.cc | 321 +
 1 file changed, 239 insertions(+), 82 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index ed3231d91404..909e47b99195 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -17,8 +17,10 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+#include 
 #define INCLUDE_ALGORITHM
 #define INCLUDE_FUNCTIONAL
+#define INCLUDE_ARRAY
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -30,7 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "rtl-ssa.h"
 #include "memmodel.h"
 #include "tm_p.h"
-#include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
+#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h.  */
 #include "cfgrtl.h"
 #include "cfgbuild.h"
 #include "cfgcleanup.h"
@@ -39,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "dbgcnt.h"
 #include "rtl-iter.h"
+#include 
 
 using namespace rtl_ssa;
 
@@ -1303,128 +1306,282 @@ public:
 } // 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;
 }
 
-static void rti_ssa_dce_() {
+bool is_prelive(insn_info *insn)
+{
+  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 ()
+rtl_ssa_dce_init()
 {
-calculate_dominance_info (CDI_DOMINATORS);
-crtl->ssa = new rtl_ssa::function_info (cfun);
+  calculate_dominance_info(CDI_DOMINATORS);
+  // here we create ssa form for function
+  crtl->ssa = new rtl_ssa::function_info(cfun);
 }
 
 static void
-rtl_ssa_dce_done ()
+rtl_ssa_dce_done()
 {
-free_dominance_info (CDI_DOMINATORS);
-if (crtl->ssa->perform_pending_updates ())
-  cleanup_cfg (0);
+  free_dominance_info(CDI_DOMINATORS);
+  if (crtl->ssa->perform_pending_updates())
+cleanup_cfg(0);
 
-delete crtl->ssa;
-crtl->ssa = nullptr;
+  delete crtl->ssa;
+  crtl->ssa = nullptr;
 
-if (dump_file)
-  fprintf (dump_file, "\nFinished running rtl_ssa_dce\n\n");
+  if (dump_file)
+fprintf(dump_file, "\nFinished running rtl_ssa_dce\n\n");
 }
 
-static unsigned int
-rtl_ssa_dce ()
+static void
+rtl_ssa_dce_mark_live(insn_info *info, vec &worklist, 
std::unordered_set marked)
 {
-rtl_ssa_dce_init ();
+  int info_uid = info->uid();
+  if (dump_file)
+  {
+fprintf(dump_file, "  Adding insn %d to worklist\n", info_uid);
+  }
 
-insn_info *next;
-sbitmap marked;
-auto_vec worklist;
-for (insn_info *insn = crtl->ssa->first_insn (); insn; insn = next)
+  marked.emplace(info);
+  worklist.safe_push(info);
+}
+
+static auto_vec
+rtl_ssa_dce_prelive(std::unordered_set marked)
+{
+  insn_info *next;
+  auto_vec worklist;
+  for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
+  {
+if (dump_file)
 {
-  next = insn->next_any_insn ();
-  auto *rtl = insn->rtl();
-  /*
-  I would like to mark visited instruction with something like plf (Pass 
local flags) as in gimple
-
-  This file contains some useful functions: e.g. mark

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce fix marking

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:5e62c115654300d61bb880a9c054eac4eedba147

commit 5e62c115654300d61bb880a9c054eac4eedba147
Author: Ondřej Machota 
Date:   Tue Mar 11 11:03:56 2025 +0100

rtl-ssa: dce fix marking

Diff:
---
 gcc/dce.cc | 77 ++
 1 file changed, 67 insertions(+), 10 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 21a7f23507af..d1558f2a9798 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1585,6 +1585,57 @@ rtl_ssa_dce_mark()
 {
   std::unordered_set marked{};
   auto worklist = rtl_ssa_dce_prelive(marked);
+  auto_vec worklist_new{};
+  for (auto && item : worklist) {
+insn_info * insn = item;
+for (auto&& use : insn->uses()) {
+  set_info* set = use->def();
+  if (set) {
+worklist_new.safe_push(set);
+  }
+}
+  }
+
+  while (!worklist_new.is_empty()) {
+set_info* set = worklist_new.pop();
+insn_info* insn = set->insn();
+if (!insn) {
+  continue;
+}
+
+if (!(marked.count(insn) > 0))
+{
+  marked.emplace(insn);
+}
+
+// use_array uses = insn->uses();
+if (insn->is_phi()) {
+  phi_info* pi = as_a (set);
+  
+  for (auto && input : pi->inputs()) {
+use_info* use = input;
+set_info* parent_set = use->def();
+if (!parent_set) { // Clobber...
+  continue;
+}
+
+worklist_new.safe_push(parent_set);
+  }
+} else {
+  if (dump_file)
+fprintf(dump_file, "  Adding insn %d to worklist - mark\n", 
insn->uid());
+  
+  for (auto && use__ : insn->uses()) {
+use_info * use = use__;
+set_info* parent_set = use->def();
+if (!parent_set) {
+  continue;
+}
+
+worklist_new.safe_push(parent_set);
+  }
+}
+  }
 
   if (dump_file)
 fprintf(dump_file, "Finished inherently live, marking parents\n");
@@ -1623,17 +1674,23 @@ rtl_ssa_dce_mark()
   // debug(use);
   // std::cerr << '\n';
   
-  
-  insn_info *parent_insn = use->def()->insn();
-  if (parent_insn->is_phi()) { // this is weird...
-// debug(use->def());
-phi_info * pi = as_a (use->def());
-// std::cerr << "phi inputs: " << pi->num_inputs() << '\n';
-for (auto&& input: pi->inputs()) {
-  use_info* phi_use = input;
-  std::cerr << "Via phi insn: " << phi_use->def()->insn()->uid() << 
'\n';
-}
+  set_info* set = use->def();
+  if (!set) {
+continue;
+  }
+  insn_info *parent_insn = set->insn();
+  if (!parent_insn) {
+continue;
   }
+  // if (parent_insn->is_phi()) { // this is weird...
+  //   // debug(use->def());
+  //   phi_info * pi = as_a (use->def());
+  //   // std::cerr << "phi inputs: " << pi->num_inputs() << '\n';
+  //   for (auto&& input: pi->inputs()) {
+  // use_info* phi_use = input;
+  // std::cerr << "Via phi insn: " << phi_use->def()->insn()->uid() << 
'\n';
+  //   }
+  // }
   int parent_insn_uid = parent_insn->uid();
   // propage that some instruction in chain is live from bottom to top
   if (dump_file)


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: improve marking, but still not correct

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:622c367a5fc67ebbda55c02aba391d86738dc6ad

commit 622c367a5fc67ebbda55c02aba391d86738dc6ad
Author: Ondřej Machota 
Date:   Wed Mar 12 13:12:43 2025 +0100

rtl-ssa-dce: improve marking, but still not correct

Diff:
---
 gcc/dce.cc | 211 +
 1 file changed, 113 insertions(+), 98 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index d1558f2a9798..cfa58f21dc03 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1390,10 +1390,12 @@ bool side_effects_with_mem (const_rtx x)
   return true;
 
 case MEM: // We might want tu return true iff volatile or mem is a 
destination
+  // write or possible null read
 case ASM_INPUT:
 case ASM_OPERANDS:
return true;
 
+// This should rather by RTX_BODY in is_rtx_insn_prelive - like global 
clobber
 case USE:
   return true;
 
@@ -1471,6 +1473,9 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 return true;
 
   rtx body = PATTERN(insn);
+  if (GET_CODE(body) == CLOBBER) // 
~/Documents/gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
+return true;
+
   if (side_effects_with_mem(body) || can_throw_internal(body))
 return true;
 
@@ -1588,6 +1593,7 @@ rtl_ssa_dce_mark()
   auto_vec worklist_new{};
   for (auto && item : worklist) {
 insn_info * insn = item;
+std::cerr << "cp Current: " << insn->uid() << '\n';
 for (auto&& use : insn->uses()) {
   set_info* set = use->def();
   if (set) {
@@ -1603,118 +1609,119 @@ rtl_ssa_dce_mark()
   continue;
 }
 
-if (!(marked.count(insn) > 0))
-{
-  marked.emplace(insn);
-}
+/*
+ * TODO : a phi insn might be visited more times due to having more phi 
nodes
+ * Either we have to mark phi nodes or do not mark phi insn
+*/
+std::cerr << "Current: " << insn->uid() << '\n';
+// if (insn->uid() == -21) {
+  // std::cerr << "Insn -21 phi? " << insn->is_phi() << '\n';
+// }
 
-// use_array uses = insn->uses();
-if (insn->is_phi()) {
-  phi_info* pi = as_a (set);
-  
-  for (auto && input : pi->inputs()) {
-use_info* use = input;
-set_info* parent_set = use->def();
-if (!parent_set) { // Clobber...
-  continue;
-}
-
-worklist_new.safe_push(parent_set);
-  }
-} else {
-  if (dump_file)
-fprintf(dump_file, "  Adding insn %d to worklist - mark\n", 
insn->uid());
-  
-  for (auto && use__ : insn->uses()) {
-use_info * use = use__;
-set_info* parent_set = use->def();
-if (!parent_set) {
-  continue;
-}
-
-worklist_new.safe_push(parent_set);
-  }
+if ((marked.count(insn) > 0)) {
+  continue;
 }
-  }
 
-  if (dump_file)
-fprintf(dump_file, "Finished inherently live, marking parents\n");
-  while (!worklist.is_empty())
-  {
-insn_info *insn = worklist.pop();
+marked.emplace(insn);
+
 use_array uses = insn->uses();
 if (insn->is_phi()) {
-  std::cerr << "Phi : "<< insn->uid() << " - uses: " << insn->num_uses() 
<< ", defs:" << insn->num_defs() << '\n';
-  for (auto&& use : uses) {
-debug(use);
-std::cerr << '\n';
-  }
-} else if (insn->is_artificial()) {
-  std::cerr << "Artificial " << insn->uid() << " - uses: " << 
insn->num_uses() << ", defs:" << insn->num_defs() << '\n';
-  for (auto&& use : uses) {
-debug(use);
-std::cerr << '\n';
-  }
+  phi_info* pi = as_a (set);
+  uses = pi->inputs();
 }
 
 if (dump_file)
-  fprintf(dump_file, "Looking at: %d, uses: %d\n", insn->uid(), 
uses.size());
-
-//std::cerr << "Insn: " << insn->uid() << ", uses: " << uses.size() << 
'\n';
-  std::cerr << "Current: " << insn->uid() << '\n';
-for (size_t i = 0; i < uses.size(); i++)
-{
-  // debug(uses[i]);
-  use_info* use = uses[i];
-  // debug(use->def());
-  // if (use->def() != nullptr) {
-  //   std::cerr << use->def()->insn()->uid() << '\n';
-  // }
-  // std::cerr << '\n';
-  // debug(use);
-  // std::cerr << '\n';
-  
-  set_info* set = use->def();
-  if (!set) {
+  fprintf(dump_file, "  Adding insn %d to worklist - mark\n", insn->uid());
+
+for (auto && use__ : uses) {
+  use_info * use = use__;
+  set_info* parent_set = use->def();
+  if (!parent_set) {
 continue;
   }
-  insn_info *parent_insn = set->insn();
-  if (!parent_insn) {
-continue;
-  }
-  // if (parent_insn->is_phi()) { // this is weird...
-  //   // debug(use->def());
-  //   phi_info * pi = as_a (use->def());
-  //   // std::cerr << "phi inputs: " << pi->num_inputs() << '\n';
-  //   for (auto&& input: pi->inputs()) {
-  // use_info* phi_use = input;
-  // std::cerr << "Via phi insn: " << phi_use->def()->insn()->uid() << 
'\n';
-  //   }
-  // }
-  int parent_insn_uid = par

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: phis are marked correctly

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:8dd2f1ee16fb9ec05ef5c5370e33b0acb946e94d

commit 8dd2f1ee16fb9ec05ef5c5370e33b0acb946e94d
Author: Ondřej Machota 
Date:   Fri Mar 14 14:04:39 2025 +0100

rtl-ssa-dce: phis are marked correctly

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

diff --git a/gcc/dce.cc b/gcc/dce.cc
index cfa58f21dc03..58d763314778 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1473,7 +1473,7 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 return true;
 
   rtx body = PATTERN(insn);
-  if (GET_CODE(body) == CLOBBER) // 
~/Documents/gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
+  if (GET_CODE(body) == CLOBBER) // 
gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 return true;
 
   if (side_effects_with_mem(body) || can_throw_internal(body))
@@ -1588,12 +1588,18 @@ rtl_ssa_dce_prelive(std::unordered_set 
&marked)
 static std::unordered_set
 rtl_ssa_dce_mark()
 {
+  std::unordered_set marked_sets{};
+
+
   std::unordered_set marked{};
+  // phi insn might have more that one phi node: 
gcc/gcc/testsuite/gcc.c-torture/execute/2224-1.c
+  std::unordered_set marked_phi_nodes{};
+  // Phi will not be prelive
   auto worklist = rtl_ssa_dce_prelive(marked);
   auto_vec worklist_new{};
   for (auto && item : worklist) {
 insn_info * insn = item;
-std::cerr << "cp Current: " << insn->uid() << '\n';
+// std::cerr << "cp Current: " << insn->uid() << '\n';
 for (auto&& use : insn->uses()) {
   set_info* set = use->def();
   if (set) {
@@ -1613,20 +1619,26 @@ rtl_ssa_dce_mark()
  * TODO : a phi insn might be visited more times due to having more phi 
nodes
  * Either we have to mark phi nodes or do not mark phi insn
 */
-std::cerr << "Current: " << insn->uid() << '\n';
+// std::cerr << "Current: " << insn->uid() << '\n';
 // if (insn->uid() == -21) {
   // std::cerr << "Insn -21 phi? " << insn->is_phi() << '\n';
 // }
 
-if ((marked.count(insn) > 0)) {
+if ((marked.count(insn) > 0) && !insn->is_phi()) {
   continue;
 }
 
+// std::cout << insn->uid() << " not skipped\n";
+
 marked.emplace(insn);
 
 use_array uses = insn->uses();
 if (insn->is_phi()) {
   phi_info* pi = as_a (set);
+  if (marked_phi_nodes.count(pi) > 0) {
+continue;
+  }
+  marked_phi_nodes.emplace(pi);
   uses = pi->inputs();
 }
 
@@ -1644,80 +1656,6 @@ rtl_ssa_dce_mark()
 }
   }
 
-  // if (dump_file)
-  //   fprintf(dump_file, "Finished inherently live, marking parents\n");
-  // while (!worklist.is_empty())
-  // {
-  //   insn_info *insn = worklist.pop();
-  //   use_array uses = insn->uses();
-  //   if (insn->is_phi()) {
-  // std::cerr << "Phi : "<< insn->uid() << " - uses: " << 
insn->num_uses() << ", defs:" << insn->num_defs() << '\n';
-  // for (auto&& use : uses) {
-  //   debug(use);
-  //   std::cerr << '\n';
-  // }
-  //   } else if (insn->is_artificial()) {
-  // std::cerr << "Artificial " << insn->uid() << " - uses: " << 
insn->num_uses() << ", defs:" << insn->num_defs() << '\n';
-  // for (auto&& use : uses) {
-  //   debug(use);
-  //   std::cerr << '\n';
-  // }
-  //   }
-
-  //   if (dump_file)
-  // fprintf(dump_file, "Looking at: %d, uses: %d\n", insn->uid(), 
uses.size());
-
-  //   //std::cerr << "Insn: " << insn->uid() << ", uses: " << uses.size() << 
'\n';
-  // std::cerr << "Current: " << insn->uid() << '\n';
-  //   for (size_t i = 0; i < uses.size(); i++)
-  //   {
-  // // debug(uses[i]);
-  // use_info* use = uses[i];
-  // // debug(use->def());
-  // // if (use->def() != nullptr) {
-  // //   std::cerr << use->def()->insn()->uid() << '\n';
-  // // }
-  // // std::cerr << '\n';
-  // // debug(use);
-  // // std::cerr << '\n';
-  
-  // set_info* set = use->def();
-  // if (!set) {
-  //   continue;
-  // }
-  // insn_info *parent_insn = set->insn();
-  // if (!parent_insn) {
-  //   continue;
-  // }
-  // // if (parent_insn->is_phi()) { // this is weird...
-  // //   // debug(use->def());
-  // //   phi_info * pi = as_a (use->def());
-  // //   // std::cerr << "phi inputs: " << pi->num_inputs() << '\n';
-  // //   for (auto&& input: pi->inputs()) {
-  // // use_info* phi_use = input;
-  // // std::cerr << "Via phi insn: " << phi_use->def()->insn()->uid() 
<< '\n';
-  // //   }
-  // // }
-  // int parent_insn_uid = parent_insn->uid();
-  // // 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);
-  // // not yet marked
-  // if (!(marked.count(parent_insn) > 0))
-  // {
-  //   //std::cerr << "Adding: " << parent_insn_uid << " to worklist";
-  //   if (dump_file)
-  // fprintf(du

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce access phi node inputs

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:f8e0cfeb4ede5c0202bf6e4f0df1c74b74140cc3

commit f8e0cfeb4ede5c0202bf6e4f0df1c74b74140cc3
Author: Ondřej Machota 
Date:   Tue Mar 11 00:31:04 2025 +0100

rtl-ssa: dce access phi node inputs

Diff:
---
 gcc/dce.cc | 46 +-
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index d3b569a74ca0..21a7f23507af 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1433,8 +1433,8 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   // According to the docs, rtl ssa does not contain noteS and barrierS 
   if (!NONJUMP_INSN_P (insn))
   {
-std::cerr << "found jump instruction\n";
-debug(insn);
+//std::cerr << "found jump instruction\n";
+//debug(insn);
 return true;
   }
 
@@ -1513,7 +1513,7 @@ bool is_prelive(insn_info *insn)
 return false;
 
   auto res = is_rtx_insn_prelive(rtl);
-  std::cerr << "Trying to mark insn: " << insn->uid() << " as prelive: " << 
res << '\n';
+  //std::cerr << "Trying to mark insn: " << insn->uid() << " as prelive: " << 
res << '\n';
 
   return is_rtx_insn_prelive(rtl);
 }
@@ -1592,11 +1592,25 @@ rtl_ssa_dce_mark()
   {
 insn_info *insn = worklist.pop();
 use_array uses = insn->uses();
+if (insn->is_phi()) {
+  std::cerr << "Phi : "<< insn->uid() << " - uses: " << insn->num_uses() 
<< ", defs:" << insn->num_defs() << '\n';
+  for (auto&& use : uses) {
+debug(use);
+std::cerr << '\n';
+  }
+} else if (insn->is_artificial()) {
+  std::cerr << "Artificial " << insn->uid() << " - uses: " << 
insn->num_uses() << ", defs:" << insn->num_defs() << '\n';
+  for (auto&& use : uses) {
+debug(use);
+std::cerr << '\n';
+  }
+}
 
 if (dump_file)
   fprintf(dump_file, "Looking at: %d, uses: %d\n", insn->uid(), 
uses.size());
 
-std::cerr << "Insn: " << insn->uid() << ", uses: " << uses.size() << '\n';
+//std::cerr << "Insn: " << insn->uid() << ", uses: " << uses.size() << 
'\n';
+  std::cerr << "Current: " << insn->uid() << '\n';
 for (size_t i = 0; i < uses.size(); i++)
 {
   // debug(uses[i]);
@@ -1608,7 +1622,18 @@ rtl_ssa_dce_mark()
   // std::cerr << '\n';
   // debug(use);
   // std::cerr << '\n';
+  
+  
   insn_info *parent_insn = use->def()->insn();
+  if (parent_insn->is_phi()) { // this is weird...
+// debug(use->def());
+phi_info * pi = as_a (use->def());
+// std::cerr << "phi inputs: " << pi->num_inputs() << '\n';
+for (auto&& input: pi->inputs()) {
+  use_info* phi_use = input;
+  std::cerr << "Via phi insn: " << phi_use->def()->insn()->uid() << 
'\n';
+}
+  }
   int parent_insn_uid = parent_insn->uid();
   // propage that some instruction in chain is live from bottom to top
   if (dump_file)
@@ -1616,9 +1641,11 @@ rtl_ssa_dce_mark()
   // not yet marked
   if (!(marked.count(parent_insn) > 0))
   {
-std::cerr << "Adding: " << parent_insn_uid << " to worklist";
+//std::cerr << "Adding: " << parent_insn_uid << " to worklist";
 if (dump_file)
   fprintf(dump_file, "  Adding insn %d to worklist - mark\n", 
parent_insn_uid);
+
+
 worklist.safe_push(parent_insn);
 marked.emplace(parent_insn);
   }
@@ -1628,7 +1655,8 @@ rtl_ssa_dce_mark()
   }
 
   for (auto&& insn : marked) {
-std::cerr << "Marked insn: " << insn->uid() << '\n';
+if (dump_file)
+  fprintf(dump_file, "  Marked insn: %d\n", insn->uid());
   }
 
   // TODO : control dependence
@@ -1675,7 +1703,7 @@ rtl_ssa_dce_sweep(std::unordered_set marked)
   }
 
   if (crtl->ssa->verify_insn_changes(changes)) {
-std::cerr << "Changes are correct\n";
+//std::cerr << "Changes are correct\n";
 crtl->ssa->change_insns(changes);
   } else {
 std::cerr << "Changes are not correct\n";
@@ -1688,7 +1716,7 @@ rtl_ssa_dce()
   rtl_ssa_dce_init();
   debug(crtl->ssa);
 
-  std::cerr << "Next phase: prelive + mark: \n";
+  //std::cerr << "Next phase: prelive + mark: \n";
   std::unordered_set marked = rtl_ssa_dce_mark();
   rtl_ssa_dce_sweep(marked);
   rtl_ssa_dce_done();
@@ -1726,7 +1754,7 @@ namespace
 }
 
 /* opt_pass methods: */
-bool gate(function *) final override { return flag_dce; }
+bool gate(function *) final override { return optimize > 0 && flag_dce; }
 
 unsigned int execute(function *) final override { return rtl_ssa_dce(); }


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce pass simple testcase

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:28c1702afc0b1a99333d1e5bef6c302348141ab5

commit 28c1702afc0b1a99333d1e5bef6c302348141ab5
Author: Ondřej Machota 
Date:   Sun Mar 9 23:02:03 2025 +0100

rtl-ssa: dce pass simple testcase

Diff:
---
 gcc/cse.cc |   2 +-
 gcc/dce.cc | 233 +
 gcc/passes.def |   3 +-
 3 files changed, 104 insertions(+), 134 deletions(-)

diff --git a/gcc/cse.cc b/gcc/cse.cc
index 70d5caac4cac..9c0924d73e1d 100644
--- a/gcc/cse.cc
+++ b/gcc/cse.cc
@@ -7639,7 +7639,7 @@ rest_of_handle_cse2 (void)
  bypassed safely.  */
   cse_condition_code_reg ();
 
-  delete_trivially_dead_insns (get_insns (), max_reg_num ());
+  // delete_trivially_dead_insns (get_insns (), max_reg_num ());
 
   if (tem == 2)
 {
diff --git a/gcc/dce.cc b/gcc/dce.cc
index 9a217a795b76..d3b569a74ca0 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1325,12 +1325,12 @@ bool sets_global_register(rtx_insn* insn) {
   rtx dest = SET_DEST(set);
 
   // TODO : rewrite to simple return
-  std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
-  std::cerr << "register: " << REGNO(dest) << "\n";
-  debug(insn);
+  //std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
+  //std::cerr << "register: " << REGNO(dest) << "\n";
+  //debug(insn);
   // If I understand correctly, global_regs[i] is 1 iff reg i is used
   if (REG_P(dest) && HARD_REGISTER_NUM_P(REGNO(dest))) { // && 
global_regs[REGNO(dest)]
-std::cerr << "sets_global_register: true\n";
+//std::cerr << "sets_global_register: true\n";
 return true;
   }
 
@@ -1356,24 +1356,88 @@ bool is_control_flow(rtx_code code) {
   }
 }
 
-bool is_unary_mem_modification(rtx_code code) {
-  switch (code) {
-case PRE_DEC:
+bool side_effects_with_mem (const_rtx x)
+{
+  const RTX_CODE code = GET_CODE (x);
+  switch (code)
+{
+case LABEL_REF:
+case SYMBOL_REF:
+case CONST:
+CASE_CONST_ANY:
+case PC:
+case REG:
+case SCRATCH:
+case ADDR_VEC:
+case ADDR_DIFF_VEC:
+case VAR_LOCATION:
+  return false;
+
+case CLOBBER:
+  /* Reject CLOBBER with a non-VOID mode.  These are made by combine.cc
+when some combination can't be done.  If we see one, don't think
+that we can simplify the expression.  */
+  return (GET_MODE (x) != VOIDmode);
+
 case PRE_INC:
-case POST_DEC:
+case PRE_DEC:
 case POST_INC:
+case POST_DEC:
 case PRE_MODIFY:
 case POST_MODIFY:
+case CALL:
+case UNSPEC_VOLATILE:
+  return true;
+
+case MEM: // We might want tu return true iff volatile or mem is a 
destination
+case ASM_INPUT:
+case ASM_OPERANDS:
+   return true;
+
+case USE:
   return true;
 
 default:
-  return false;
+  break;
+}
+
+  /* Recursively scan the operands of this expression.  */
+
+  {
+const char *fmt = GET_RTX_FORMAT (code);
+int i;
+
+for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+  {
+   if (fmt[i] == 'e')
+ {
+   if (side_effects_with_mem (XEXP (x, i)))
+ return true;
+ }
+   else if (fmt[i] == 'E')
+ {
+   int j;
+   for (j = 0; j < XVECLEN (x, i); j++)
+ if (side_effects_with_mem (XVECEXP (x, i, j)))
+   return true;
+ }
+  }
   }
+  return false;
 }
 
 bool is_rtx_insn_prelive(rtx_insn *insn) {
   gcc_assert(insn != nullptr);
 
+  // Jumps, notes, barriers should not be deleted
+  // According to the docs, rtl ssa does not contain noteS and barrierS 
+  if (!NONJUMP_INSN_P (insn))
+  {
+std::cerr << "found jump instruction\n";
+debug(insn);
+return true;
+  }
+
   // TODO : handle calls correctly
   if (CALL_P (insn)
   /* We cannot delete pure or const sibling calls because it is
@@ -1387,15 +1451,6 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 return true;
 // return !find_call_stack_args (as_a  (insn), false, 
fast, arg_stores);
 
-  // Jumps, notes, barriers should not be deleted
-// According to the docs, rtl ssa does not contain noteS and barrierS 
-  if (!NONJUMP_INSN_P (insn))
-  {
-std::cerr << "found jump instruction\n";
-debug(insn);
-return true;
-  }
-
   // Only rtx_insn should be handled here
   auto code = GET_CODE(insn);
   gcc_assert(code == INSN);
@@ -1411,51 +1466,17 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate && 
find_reg_note (insn, REG_CFA_RESTORE, NULL))
 return true;
 
-  // if (is_control_flow(code))
-  //   return true;
-
   // Mark set of a global register
   if (sets_global_register(insn)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
 return true;
 
   rtx body = PATTERN(insn);
-  if (side_effects_p(body) || can_throw_internal(body))
-return true;
-
-  if (is_unary_mem_modification(code))
+  if (side_effects_with_mem(body) || can_throw_internal(body))
 return 

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: mark REGNO (pic_offset_table_rtx) as prelive

2025-03-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:be7d7f41e118a4e11a352bfa0c011aaae54d75e9

commit be7d7f41e118a4e11a352bfa0c011aaae54d75e9
Author: Ondřej Machota 
Date:   Thu Mar 20 10:03:09 2025 +0100

rtl-ssa-dce: mark REGNO (pic_offset_table_rtx) as prelive

Diff:
---
 gcc/dce.cc | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 62ab115455c0..bd70c9588497 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1500,7 +1500,11 @@ bool is_prelive(insn_info *insn)
 }
 
 // this ignore clobbers, which is probably fine
-if (def->kind() == access_kind::SET && HARD_REGISTER_NUM_P(def->regno())) {
+if (def->kind() == access_kind::SET 
+&& (HARD_REGISTER_NUM_P(def->regno())
+|| (def->regno() == REGNO (pic_offset_table_rtx)
+&& REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER))
+  ) {
   // We might try to write something like def->regno() == REGNO 
(pic_offset_table_rtx) ...
   // TODO : else if (DF_REF_REG (def) == pic_offset_table_rtx && REGNO 
(pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
   // std::cerr << "hello, dear hard register! regno: " << def->regno() << 
"\n";


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: improve prelive conditions

2025-03-24 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:914f83868c9d3641463aecf5d597512ee9b820be

commit 914f83868c9d3641463aecf5d597512ee9b820be
Author: Ondřej Machota 
Date:   Mon Mar 24 23:04:15 2025 +0100

rtl-ssa-dce: improve prelive conditions

Diff:
---
 gcc/dce.cc | 41 -
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index a769c1387346..f227fc214e99 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1394,6 +1394,18 @@ bool side_effects_with_mem (const_rtx x)
   return false;
 }
 
+bool is_ssa_prelive(const_rtx insn) {
+  switch (GET_CODE(insn)) {
+case PREFETCH:
+case UNSPEC:
+case TRAP_IF:
+  return true;
+
+default:
+  return side_effects_p(insn);
+  }
+}
+
 bool is_rtx_insn_prelive(rtx_insn *insn) {
   gcc_assert(insn != nullptr);
 
@@ -1401,6 +1413,7 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   // According to the docs, rtl ssa does not contain noteS and barrierS 
   if (!NONJUMP_INSN_P (insn))
   {
+// This handles jumps, debug_insns, call_insn, ...
 //std::cerr << "found jump instruction\n";
 //debug(insn);
 return true;
@@ -1437,6 +1450,8 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   // if (sets_global_register(insn)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
   //   return true;
 
+  // TODO : asm_noperands???
+
   rtx body = PATTERN(insn);
   switch (GET_CODE(body)) {
 case CLOBBER: // gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
@@ -1449,12 +1464,12 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 
 case PARALLEL:
   for (int i = XVECLEN (body, 0) - 1; i >= 0; i--)
-if (!deletable_insn_p_1 (XVECEXP (body, 0, i)))
+if (is_ssa_prelive (XVECEXP (body, 0, i)))
   return true;
-return false;
+  return false;
 
 default:
-  return !deletable_insn_p_1 (body);
+  return is_ssa_prelive (body);
   }
 
   // See deletable_insn_p_1 for UNSPEC. TRAP_IF is caught by 
may_trap_or_fault_p
@@ -1514,6 +1529,8 @@ bool is_prelive(insn_info *insn)
   && def->regno() == REGNO (pic_offset_table_rtx)
   && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER))
   ) {
+// TODO : set_noop_p?
+
   // std::cerr << "hard reg marked: " << def->regno() << "in " << 
insn->uid() << "\n";
   // debug(rtl);
   return true;
@@ -1722,17 +1739,31 @@ rtl_ssa_dce()
 {
   rtl_ssa_dce_init();
   // debug(crtl->ssa);
+  // std::cout << "\033[31m" << "Before rtl ssa dce pass" << "\033[0m" << "\n";
+
   // for (rtx_insn * insn = get_insns (); insn != nullptr; insn = 
next_insn(insn)) {
-  //   debug(insn);
-  // }l
+// debug(insn);
+  // }
+
+  // std::cout << "\033[31m" << "Before rtl ssa dce pass end" << "\033[0m" << 
"\n";
+
 
   std::unordered_set marked = rtl_ssa_dce_mark();
   rtl_ssa_dce_sweep(marked);
   rtl_ssa_dce_done();
+  // std::cout << "\033[32m" << "After rtl ssa dce" << "\033[0m" << "\n";
+  // for (rtx_insn * insn = get_insns (); insn != nullptr; insn = 
next_insn(insn)) {
+// debug(insn);
+  // }
   if (delete_trivially_dead_insns(get_insns (), max_reg_num ())) {
+// std::cout << "\033[31m" << "Some insns deleted by 
delete_trivially_dead_insns" << "\033[0m" << "\n";
+// for (rtx_insn * insn = get_insns (); insn != nullptr; insn = 
next_insn(insn)) {
+  // debug(insn);
+// }
 std::cerr << "\033[31m" << "rtl_ssa_dce did not delete everything :(" << 
"\033[0m" << "\n";
   }
 
+  // std::cout << "rtl ssa dce FINISH\n";
   return 0;
 }


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: phis are marked correctly

2025-03-14 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:5d97053d63fb4f6380a56eaaf3a3488be5ef0454

commit 5d97053d63fb4f6380a56eaaf3a3488be5ef0454
Author: Ondřej Machota 
Date:   Fri Mar 14 14:04:39 2025 +0100

rtl-ssa-dce: phis are marked correctly

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

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 959677663855..c8c8be2293a1 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1470,7 +1470,7 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 return true;
 
   rtx body = PATTERN(insn);
-  if (GET_CODE(body) == CLOBBER) // 
~/Documents/gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
+  if (GET_CODE(body) == CLOBBER) // 
gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 return true;
 
   if (side_effects_with_mem(body) || can_throw_internal(body))
@@ -1585,12 +1585,18 @@ rtl_ssa_dce_prelive(std::unordered_set 
&marked)
 static std::unordered_set
 rtl_ssa_dce_mark()
 {
+  std::unordered_set marked_sets{};
+
+
   std::unordered_set marked{};
+  // phi insn might have more that one phi node: 
gcc/gcc/testsuite/gcc.c-torture/execute/2224-1.c
+  std::unordered_set marked_phi_nodes{};
+  // Phi will not be prelive
   auto worklist = rtl_ssa_dce_prelive(marked);
   auto_vec worklist_new{};
   for (auto && item : worklist) {
 insn_info * insn = item;
-std::cerr << "cp Current: " << insn->uid() << '\n';
+// std::cerr << "cp Current: " << insn->uid() << '\n';
 for (auto&& use : insn->uses()) {
   set_info* set = use->def();
   if (set) {
@@ -1610,20 +1616,26 @@ rtl_ssa_dce_mark()
  * TODO : a phi insn might be visited more times due to having more phi 
nodes
  * Either we have to mark phi nodes or do not mark phi insn
 */
-std::cerr << "Current: " << insn->uid() << '\n';
+// std::cerr << "Current: " << insn->uid() << '\n';
 // if (insn->uid() == -21) {
   // std::cerr << "Insn -21 phi? " << insn->is_phi() << '\n';
 // }
 
-if ((marked.count(insn) > 0)) {
+if ((marked.count(insn) > 0) && !insn->is_phi()) {
   continue;
 }
 
+// std::cout << insn->uid() << " not skipped\n";
+
 marked.emplace(insn);
 
 use_array uses = insn->uses();
 if (insn->is_phi()) {
   phi_info* pi = as_a (set);
+  if (marked_phi_nodes.count(pi) > 0) {
+continue;
+  }
+  marked_phi_nodes.emplace(pi);
   uses = pi->inputs();
 }
 
@@ -1641,80 +1653,6 @@ rtl_ssa_dce_mark()
 }
   }
 
-  // if (dump_file)
-  //   fprintf(dump_file, "Finished inherently live, marking parents\n");
-  // while (!worklist.is_empty())
-  // {
-  //   insn_info *insn = worklist.pop();
-  //   use_array uses = insn->uses();
-  //   if (insn->is_phi()) {
-  // std::cerr << "Phi : "<< insn->uid() << " - uses: " << 
insn->num_uses() << ", defs:" << insn->num_defs() << '\n';
-  // for (auto&& use : uses) {
-  //   debug(use);
-  //   std::cerr << '\n';
-  // }
-  //   } else if (insn->is_artificial()) {
-  // std::cerr << "Artificial " << insn->uid() << " - uses: " << 
insn->num_uses() << ", defs:" << insn->num_defs() << '\n';
-  // for (auto&& use : uses) {
-  //   debug(use);
-  //   std::cerr << '\n';
-  // }
-  //   }
-
-  //   if (dump_file)
-  // fprintf(dump_file, "Looking at: %d, uses: %d\n", insn->uid(), 
uses.size());
-
-  //   //std::cerr << "Insn: " << insn->uid() << ", uses: " << uses.size() << 
'\n';
-  // std::cerr << "Current: " << insn->uid() << '\n';
-  //   for (size_t i = 0; i < uses.size(); i++)
-  //   {
-  // // debug(uses[i]);
-  // use_info* use = uses[i];
-  // // debug(use->def());
-  // // if (use->def() != nullptr) {
-  // //   std::cerr << use->def()->insn()->uid() << '\n';
-  // // }
-  // // std::cerr << '\n';
-  // // debug(use);
-  // // std::cerr << '\n';
-  
-  // set_info* set = use->def();
-  // if (!set) {
-  //   continue;
-  // }
-  // insn_info *parent_insn = set->insn();
-  // if (!parent_insn) {
-  //   continue;
-  // }
-  // // if (parent_insn->is_phi()) { // this is weird...
-  // //   // debug(use->def());
-  // //   phi_info * pi = as_a (use->def());
-  // //   // std::cerr << "phi inputs: " << pi->num_inputs() << '\n';
-  // //   for (auto&& input: pi->inputs()) {
-  // // use_info* phi_use = input;
-  // // std::cerr << "Via phi insn: " << phi_use->def()->insn()->uid() 
<< '\n';
-  // //   }
-  // // }
-  // int parent_insn_uid = parent_insn->uid();
-  // // 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);
-  // // not yet marked
-  // if (!(marked.count(parent_insn) > 0))
-  // {
-  //   //std::cerr << "Adding: " << parent_insn_uid << " to worklist";
-  //   if (dump_file)
-  // fprintf(du

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: add prefetch as prelive + clone on pass

2025-03-17 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:7ca7bf12324598cdfef53ed377082f1a8ee829e4

commit 7ca7bf12324598cdfef53ed377082f1a8ee829e4
Author: Ondřej Machota 
Date:   Mon Mar 17 23:30:08 2025 +0100

rtl-ssa-dce: add prefetch as prelive + clone on pass

Diff:
---
 gcc/dce.cc | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 55aeb64269ca..74c1a6f8a879 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1451,8 +1451,7 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 // return !find_call_stack_args (as_a  (insn), false, 
fast, arg_stores);
 
   // Only rtx_insn should be handled here
-  auto code = GET_CODE(insn);
-  gcc_assert(code == INSN);
+  gcc_assert(GET_CODE(insn) == INSN);
 
   /* Don't delete insns that may throw if we cannot do so.  */
   if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) && !insn_nothrow_p 
(insn))
@@ -1473,6 +1472,11 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (GET_CODE(body) == CLOBBER) // 
gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 return true;
 
+  if (GET_CODE(body) == PREFETCH)
+return true;
+
+  // See deletable_insn_p_1 for UNSPEC. TRAP_IF is caught by 
may_trap_or_fault_p
+
   // may_trap_or_fault_p helps a lot to pass some tests from 
RUNTESTSFLAGS=execute.exp
   // e. g. this one: testsuite/gcc.c-torture/execute/20020418-1.c
   // TODO : debug the testcase
@@ -1481,10 +1485,6 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (side_effects_with_mem(body) || can_throw_internal(body) || 
may_trap_or_fault_p(body))
 return true;
 
-  // TODO : parallel, {pre,post}_{int,dec}, {pre,post}_modify, 
may_trap_or_fault_p
-  // Parallel is handled by volatile_refs_p
-
-
   return false;
 }
 
@@ -1764,8 +1764,9 @@ namespace
   public:
 pass_rtl_ssa_dce(gcc::context *ctxt)
 : rtl_opt_pass(pass_data_rtl_ssa_dce, ctxt)
-{
-}
+{}
+
+opt_pass * clone () final override { return new pass_rtl_ssa_dce (m_ctxt); 
}
 
 /* opt_pass methods: */
 bool gate(function *) final override { return optimize > 0 && flag_dce; }


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce mark sketch

2025-04-05 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:3136c46e7d16842d921aa15b268e72e04f9c5af5

commit 3136c46e7d16842d921aa15b268e72e04f9c5af5
Author: Ondřej Machota 
Date:   Sun Sep 29 20:20:11 2024 +0200

rtl-ssa: dce mark sketch

Diff:
---
 gcc/dce.cc | 57 +
 1 file changed, 57 insertions(+)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 640040dbf3d3..ed3231d91404 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -40,6 +40,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "dbgcnt.h"
 #include "rtl-iter.h"
 
+using namespace rtl_ssa;
+
 
 /* -
Core mark/delete routines
@@ -1300,6 +1302,15 @@ public:
 
 } // namespace
 
+
+bool is_inherently_live(insn_info *insn) {
+
+}
+
+static void rti_ssa_dce_() {
+  
+}
+
 static void
 rtl_ssa_dce_init ()
 {
@@ -1326,6 +1337,52 @@ rtl_ssa_dce ()
 {
 rtl_ssa_dce_init ();
 
+insn_info *next;
+sbitmap marked;
+auto_vec worklist;
+for (insn_info *insn = crtl->ssa->first_insn (); insn; insn = next)
+{
+  next = insn->next_any_insn ();
+  auto *rtl = insn->rtl();
+  /*
+  I would like to mark visited instruction with something like plf (Pass 
local flags) as in gimple
+
+  This file contains some useful functions: e.g. marked_insn_p, mark_insn
+  mark_insn does much more than I want now...
+  It does quite a useful job. If rtl_insn is a call and it is obsolete, it 
will find call arguments.
+  */
+ // insn.defs() // UD chain - this is what I want - reach the ancestors\
+ // insn.uses() // DU chain
+  if (is_inherently_live(insn)) {
+if (dump_file)
+ fprintf (dump_file, "  Adding insn %d to worklist\n", 
INSN_UID (insn));
+worklist.safe_push (insn);
+bitmap_set_bit(marked, INSN_UID (insn)); 
+  }
+
+  //if (insn->can_be_optimized () || insn->is_debug_insn ())
+   // if (fwprop_insn (insn, fwprop_addr_p))
+   // worklist.safe_push (insn);
+}
+
+while (!worklist.is_empty())
+{
+  insn_info *insn = worklist.pop();
+  def_array defs = insn->defs(); // array - because of phi?
+  for (size_t i = 0; i < defs.size(); i++)
+  {
+
+insn_info* parent_insn = defs[i]->insn();
+
+if (!bitmap_bit_p(INSN_UID (parent_insn))) {
+  if (dump_file)
+ fprintf (dump_file, "  Adding insn %d to worklist\n", 
INSN_UID (parent_insn));
+  worklist.safe_push(parent_insn);
+  bitmap_set_bit(marked, INSN_UID (parent_insn)); 
+}
+  }
+}
+
 rtl_ssa_dce_done ();
 return 0;
 }


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: add prefetch as prelive + clone on pass

2025-04-05 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:cbfcd3865f6b87df53891ab62edde5cbdb3a0cbd

commit cbfcd3865f6b87df53891ab62edde5cbdb3a0cbd
Author: Ondřej Machota 
Date:   Mon Mar 17 23:30:08 2025 +0100

rtl-ssa-dce: add prefetch as prelive + clone on pass

Diff:
---
 gcc/dce.cc | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 091e5c620f5b..b11ced743d74 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1454,8 +1454,7 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 // return !find_call_stack_args (as_a  (insn), false, 
fast, arg_stores);
 
   // Only rtx_insn should be handled here
-  auto code = GET_CODE(insn);
-  gcc_assert(code == INSN);
+  gcc_assert(GET_CODE(insn) == INSN);
 
   /* Don't delete insns that may throw if we cannot do so.  */
   if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) && !insn_nothrow_p 
(insn))
@@ -1476,6 +1475,11 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (GET_CODE(body) == CLOBBER) // 
gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 return true;
 
+  if (GET_CODE(body) == PREFETCH)
+return true;
+
+  // See deletable_insn_p_1 for UNSPEC. TRAP_IF is caught by 
may_trap_or_fault_p
+
   // may_trap_or_fault_p helps a lot to pass some tests from 
RUNTESTSFLAGS=execute.exp
   // e. g. this one: testsuite/gcc.c-torture/execute/20020418-1.c
   // TODO : debug the testcase
@@ -1484,10 +1488,6 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (side_effects_with_mem(body) || can_throw_internal(body) || 
may_trap_or_fault_p(body))
 return true;
 
-  // TODO : parallel, {pre,post}_{int,dec}, {pre,post}_modify, 
may_trap_or_fault_p
-  // Parallel is handled by volatile_refs_p
-
-
   return false;
 }
 
@@ -1767,8 +1767,9 @@ namespace
   public:
 pass_rtl_ssa_dce(gcc::context *ctxt)
 : rtl_opt_pass(pass_data_rtl_ssa_dce, ctxt)
-{
-}
+{}
+
+opt_pass * clone () final override { return new pass_rtl_ssa_dce (m_ctxt); 
}
 
 /* opt_pass methods: */
 bool gate(function *) final override { return optimize > 0 && flag_dce; }


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: improve prelive conditions (USE, TRAP_IF)

2025-04-04 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:037d91e03673f29447d783a54bcf9c2b015e8e2b

commit 037d91e03673f29447d783a54bcf9c2b015e8e2b
Author: Ondřej Machota 
Date:   Tue Mar 18 20:40:21 2025 +0100

rtl-ssa-dce: improve prelive conditions (USE, TRAP_IF)

Diff:
---
 gcc/dce.cc | 31 +--
 1 file changed, 9 insertions(+), 22 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index b11ced743d74..42b63cbcfb81 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1317,6 +1317,8 @@ bool sets_global_register(const_rtx rtx) {
 
 // We should mark stack registers
 // use HARD_FRAME_POINTER_REGNUM, REGNO_PTR_FRAME_P
+// muzeme mit parallel, ktery ma napr. dva single sety, nebo asm statement
+// pouzit note_pattern_stores nebo note_stores
 bool sets_global_register(rtx_insn* insn) {
   rtx set = single_set(insn);
   if (!set)
@@ -1337,25 +1339,6 @@ bool sets_global_register(rtx_insn* insn) {
   return false;
 }
 
-bool is_control_flow(rtx_code code) {
-  // What about BARRIERs?
-  switch (code) {
-case JUMP_INSN:
-case JUMP_TABLE_DATA: // Be careful with Table jump addresses - ADDR_VEC, 
ADDR_DIFF_VEC, PREFETCH 
-case TRAP_IF:
-case IF_THEN_ELSE: // Also COMPARE?
-case COND_EXEC: // We might want to check the operation that is under this?
-case RETURN:
-case SIMPLE_RETURN:
-case EH_RETURN:
-case LABEL_REF:
-  return true;
-
-default:
-  return false;
-  }
-}
-
 bool side_effects_with_mem (const_rtx x)
 {
   const RTX_CODE code = GET_CODE (x);
@@ -1396,8 +1379,8 @@ bool side_effects_with_mem (const_rtx x)
return true;
 
 // This should rather by RTX_BODY in is_rtx_insn_prelive - like global 
clobber
-case USE:
-  return true;
+// case USE:
+  // return true;
 
 default:
   break;
@@ -1478,6 +1461,9 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (GET_CODE(body) == PREFETCH)
 return true;
 
+  if (GET_CODE(body) == USE || GET_CODE(body) == TRAP_IF || GET_CODE(body) == 
UNSPEC)
+return true;
+
   // See deletable_insn_p_1 for UNSPEC. TRAP_IF is caught by 
may_trap_or_fault_p
 
   // may_trap_or_fault_p helps a lot to pass some tests from 
RUNTESTSFLAGS=execute.exp
@@ -1485,7 +1471,8 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   // TODO : debug the testcase
   // It seems that the issue was due to trap_if rtl insn and fixed with 
may_trap_or_fault_p
   // What about can_throw_internal?
-  if (side_effects_with_mem(body) || can_throw_internal(body) || 
may_trap_or_fault_p(body))
+  // || can_throw_internal(body) - testy na ntb prochazi
+  if (side_effects_with_mem(body)) // || may_trap_or_fault_p(body))
 return true;
 
   return false;


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce fix bad marked insn map passing

2025-03-27 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:aecd918163914a09df0f619a9f3163dcadfaf425

commit aecd918163914a09df0f619a9f3163dcadfaf425
Author: Ondřej Machota 
Date:   Sun Mar 9 20:59:45 2025 +0100

rtl-ssa: dce fix bad marked insn map passing

Diff:
---
 gcc/dce.cc | 146 -
 1 file changed, 116 insertions(+), 30 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index f51f27dbd143..9a217a795b76 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1316,6 +1316,7 @@ bool sets_global_register(const_rtx rtx) {
 }
 
 // We should mark stack registers
+// use HARD_FRAME_POINTER_REGNUM, REGNO_PTR_FRAME_P
 bool sets_global_register(rtx_insn* insn) {
   rtx set = single_set(insn);
   if (!set)
@@ -1370,21 +1371,55 @@ bool is_unary_mem_modification(rtx_code code) {
   }
 }
 
-bool is_rtx_insn_prelive(const_rtx rtx) {
-  if (rtx == nullptr) {
-return false;
+bool is_rtx_insn_prelive(rtx_insn *insn) {
+  gcc_assert(insn != nullptr);
+
+  // TODO : handle calls correctly
+  if (CALL_P (insn)
+  /* We cannot delete pure or const sibling calls because it is
+hard to see the result.  */
+  && (!SIBLING_CALL_P (insn))
+  /* We can delete dead const or pure calls as long as they do not
+ infinite loop.  */
+  && (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P 
(insn))
+  /* Don't delete calls that may throw if we cannot do so.  */
+  && can_delete_call (insn))
+return true;
+// return !find_call_stack_args (as_a  (insn), false, 
fast, arg_stores);
+
+  // Jumps, notes, barriers should not be deleted
+// According to the docs, rtl ssa does not contain noteS and barrierS 
+  if (!NONJUMP_INSN_P (insn))
+  {
+std::cerr << "found jump instruction\n";
+debug(insn);
+return true;
   }
 
-  auto code = GET_CODE(rtx);
-  if (is_control_flow(code))
+  // Only rtx_insn should be handled here
+  auto code = GET_CODE(insn);
+  gcc_assert(code == INSN);
+
+  /* Don't delete insns that may throw if we cannot do so.  */
+  if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) && !insn_nothrow_p 
(insn))
 return true;
 
+  /* TODO : What about call argumets? Accoring to the docs, for function 
prologue the RTX_FRAME_RELATED_P
+ should return true.
+  */  
+  /* Callee-save restores are needed.  */
+  if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate && 
find_reg_note (insn, REG_CFA_RESTORE, NULL))
+return true;
+
+  // if (is_control_flow(code))
+  //   return true;
+
   // Mark set of a global register
-  if (sets_global_register(rtx)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
+  if (sets_global_register(insn)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
 return true;
 
-  // Call is inside side_effects_p - how to mark parameter registers?
-  if (volatile_refs_p(rtx) || can_throw_internal(rtx) || BARRIER_P(rtx) || 
code == PREFETCH)
+  rtx body = PATTERN(insn);
+  if (side_effects_p(body) || can_throw_internal(body))
 return true;
 
   if (is_unary_mem_modification(code))
@@ -1394,21 +1429,34 @@ bool is_rtx_insn_prelive(const_rtx rtx) {
   // Parallel is handled by volatile_refs_p
 
   switch (code) {
-
-  }
-
-  const char *const fmt = GET_RTX_FORMAT (code);
-  for (size_t i = 0; i < GET_RTX_LENGTH(code); ++i) {
-if (fmt[i] == 'e' && is_rtx_insn_prelive(XEXP(rtx, i))) {
+case MEM:
+case ASM_INPUT:
+case ASM_OPERANDS:
   return true;
-} else if (fmt[i] == 'E') {
-  for (size_t j = 0; j < XVECLEN(rtx, i); ++j) {
-if (is_rtx_insn_prelive(XVECEXP(rtx, i, j)))
-  return true;
-  }
-}
+
+case PARALLEL:
+  for (int i = XVECLEN (body, 0) - 1; i >= 0; i--)
+ if (!deletable_insn_p_1 (XVECEXP (body, 0, i)))
+   return true;
+  return false;
+  break;
+
+default:
+  break;
   }
 
+  // const char *const fmt = GET_RTX_FORMAT (code);
+  // for (size_t i = 0; i < GET_RTX_LENGTH(code); ++i) {
+  //   if (fmt[i] == 'e' && is_rtx_insn_prelive(XEXP(rtx, i))) {
+  // return true;
+  //   } else if (fmt[i] == 'E') {
+  // for (size_t j = 0; j < XVECLEN(rtx, i); ++j) {
+  //   if (is_rtx_insn_prelive(XVECEXP(rtx, i, j)))
+  // return true;
+  // }
+  //   }
+  // }
+
   return false;
 }
 
@@ -1443,7 +1491,7 @@ bool is_prelive(insn_info *insn)
   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
+  return is_rtx_insn_prelive(rtl);
   
   // TODO : join if statements
   // We need to describe all possible prelive instructions, a list of all the 
instructions is inside `rtl.def`
@@ -1461,7 +1509,7 @@ bool is_prelive(insn_info *insn)
   std::cerr << "Prelive: " << GET_RTX_NAME(code) << '\n';
   // debug(insn);
   debug(rtl);
-  if (volatile_refs_p(rtl) || can_throw_internal(rtl) || BARRIER_P(rtl) || 
code == PREFETCH)

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce improve prelive conditions

2025-03-27 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:829a7f63e2616652a81a6ee432cf72ae4232235f

commit 829a7f63e2616652a81a6ee432cf72ae4232235f
Author: Ondřej Machota 
Date:   Fri Feb 21 23:06:19 2025 +0100

rtl-ssa: dce improve prelive conditions

Diff:
---
 gcc/dce.cc | 38 +++---
 1 file changed, 31 insertions(+), 7 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 909e47b99195..49bc4c3c6780 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
 .  */
 
-#include 
 #define INCLUDE_ALGORITHM
 #define INCLUDE_FUNCTIONAL
 #define INCLUDE_ARRAY
@@ -1319,6 +1318,28 @@ bool sets_global_register(rtx_insn* insn) {
   return false;
 }
 
+bool is_control_flow(rtx_code code) {
+  // What about BARRIERs?
+  switch (code) {
+case JUMP_INSN:
+case JUMP_TABLE_DATA: // Be careful with Table jump addresses - ADDR_VEC, 
ADDR_DIFF_VEC, PREFETCH 
+case TRAP_IF:
+case IF_THEN_ELSE: // Also COMPARE?
+case COND_EXEC: // We might want to check the operation that is under this?
+case RETURN:
+case SIMPLE_RETURN:
+case EH_RETURN:
+  return true;
+
+default:
+  return false;
+  }
+}
+
+bool handle_rtl_previle(rtx_insn *insn) {
+  // TODO : handle everything except parallel
+}
+
 bool is_prelive(insn_info *insn)
 {
   if (insn->is_artificial()) // phis are never prelive
@@ -1344,7 +1365,7 @@ bool is_prelive(insn_info *insn)
   */
 
   // Now, we only have to handle rtx insns
-  assert(insn->is_real());
+  gcc_assert (insn->is_real());
   auto rtl = insn->rtl();
 
   if (!INSN_P(rtl)) // This might be useless
@@ -1353,20 +1374,23 @@ bool is_prelive(insn_info *insn)
   rtx pat = PATTERN(rtl); // if we use this instead of rtl, then rtl notes 
wont be checked
   
   // TODO : join if statements
+  // We need to describe all possible prelive instructions, a list of all the 
instructions is inside `rtl.def`
 
-  if (JUMP_P(rtl))
+  // Control flow
+  auto rtl_code = GET_CODE(rtl);
+  if (is_control_flow(rtl_code))
 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))
+  if (volatile_refs_p(rtl) || can_throw_internal(rtl) || BARRIER_P(rtl) || 
rtl_code == PREFETCH)
 return true;
 
+  // TODO : handle parallel, {pre,post}_{int,dec}, {pre,post}_modify
+
   return false;
 }
 
@@ -1524,8 +1548,8 @@ rtl_ssa_dce_sweep(std::unordered_set marked)
 changes[i] = &to_delete[i];
   }
 
-  // if (verify_insn_changes())
   crtl->ssa->change_insns(changes);
+  // if (verify_insn_changes())
 }
 
 static unsigned int


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: mark REGNO (pic_offset_table_rtx) as prelive

2025-03-26 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:4932c4eef80d9488dda9ea1d8cb90a417244a9b7

commit 4932c4eef80d9488dda9ea1d8cb90a417244a9b7
Author: Ondřej Machota 
Date:   Thu Mar 20 10:03:09 2025 +0100

rtl-ssa-dce: mark REGNO (pic_offset_table_rtx) as prelive

Diff:
---
 gcc/dce.cc | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 5cc9f3129067..8573e50a66de 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1497,7 +1497,11 @@ bool is_prelive(insn_info *insn)
 }
 
 // this ignore clobbers, which is probably fine
-if (def->kind() == access_kind::SET && HARD_REGISTER_NUM_P(def->regno())) {
+if (def->kind() == access_kind::SET 
+&& (HARD_REGISTER_NUM_P(def->regno())
+|| (def->regno() == REGNO (pic_offset_table_rtx)
+&& REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER))
+  ) {
   // We might try to write something like def->regno() == REGNO 
(pic_offset_table_rtx) ...
   // TODO : else if (DF_REF_REG (def) == pic_offset_table_rtx && REGNO 
(pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
   // std::cerr << "hello, dear hard register! regno: " << def->regno() << 
"\n";


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: change prelive conditions for mem

2025-03-27 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:90bbab8cdb9d7ecf9be135ee8c23289789700e70

commit 90bbab8cdb9d7ecf9be135ee8c23289789700e70
Author: Ondřej Machota 
Date:   Fri Mar 21 13:42:25 2025 +0100

rtl-ssa-dce: change prelive conditions for mem

Diff:
---
 gcc/dce.cc | 92 --
 1 file changed, 53 insertions(+), 39 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index bd70c9588497..a769c1387346 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1306,10 +1306,6 @@ public:
 
 } // namespace
 
-// We should mark stack registers
-// use HARD_FRAME_POINTER_REGNUM, REGNO_PTR_FRAME_P
-// muzeme mit parallel, ktery ma napr. dva single sety, nebo asm statement
-// pouzit note_pattern_stores nebo note_stores
 bool sets_global_register(rtx_insn* insn) {
   rtx set = single_set(insn);
   if (!set)
@@ -1442,14 +1438,24 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   //   return true;
 
   rtx body = PATTERN(insn);
-  if (GET_CODE(body) == CLOBBER) // 
gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
-return true;
+  switch (GET_CODE(body)) {
+case CLOBBER: // gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
+case USE:
+case VAR_LOCATION:
+case PREFETCH: // This and following case might be removed since they are 
part of deletable_insn_p_1
+case TRAP_IF:
+case UNSPEC:
+  return true;
 
-  if (GET_CODE(body) == PREFETCH)
-return true;
+case PARALLEL:
+  for (int i = XVECLEN (body, 0) - 1; i >= 0; i--)
+if (!deletable_insn_p_1 (XVECEXP (body, 0, i)))
+  return true;
+return false;
 
-  if (GET_CODE(body) == USE || GET_CODE(body) == TRAP_IF || GET_CODE(body) == 
UNSPEC)
-return true;
+default:
+  return !deletable_insn_p_1 (body);
+  }
 
   // See deletable_insn_p_1 for UNSPEC. TRAP_IF is caught by 
may_trap_or_fault_p
 
@@ -1495,27 +1501,25 @@ bool is_prelive(insn_info *insn)
 
   for (auto&& __def : insn->defs()) {
 def_info * def = __def;
-if (!def->is_reg()) {
-  continue;
+// The purpose of this pass is not to eliminate stores to memory...
+if (def->is_mem()) { // TODO : clobbered memory?
+  return true;
 }
 
-// this ignore clobbers, which is probably fine
+gcc_assert(def->is_reg());
+// this ignores clobbers, which is probably fine
 if (def->kind() == access_kind::SET 
 && (HARD_REGISTER_NUM_P(def->regno())
-|| (def->regno() == REGNO (pic_offset_table_rtx)
-&& REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER))
+|| ( pic_offset_table_rtx != nullptr 
+  && def->regno() == REGNO (pic_offset_table_rtx)
+  && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER))
   ) {
-  // We might try to write something like def->regno() == REGNO 
(pic_offset_table_rtx) ...
-  // TODO : else if (DF_REF_REG (def) == pic_offset_table_rtx && REGNO 
(pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
-  // std::cerr << "hello, dear hard register! regno: " << def->regno() << 
"\n";
+  // std::cerr << "hard reg marked: " << def->regno() << "in " << 
insn->uid() << "\n";
   // debug(rtl);
   return true;
 }
   }
 
-  // auto res = is_rtx_insn_prelive(rtl);
-  //std::cerr << "Trying to mark insn: " << insn->uid() << " as prelive: " << 
res << '\n';
-
   return is_rtx_insn_prelive(rtl);
 }
 
@@ -1539,7 +1543,9 @@ rtl_ssa_dce_prelive(std::unordered_set 
&marked)
   {
 next = insn->next_any_insn();
 if (is_prelive(insn))
-  rtl_ssa_dce_mark_live(insn, worklist, marked);
+  {
+// std::cout << "insn is prelive: " << insn->uid() << '\n';
+rtl_ssa_dce_mark_live(insn, worklist, marked);}
 
 // if (insn->can_be_optimized () || insn->is_debug_insn ())
 //  if (fwprop_insn (insn, fwprop_addr_p))
@@ -1639,6 +1645,9 @@ rtl_ssa_dce_sweep(std::unordered_set marked)
   // which will hopefully have constructor for array_slice
   auto attempt = crtl->ssa->new_change_attempt ();
   // std::cerr << "Change attempt created successfully" << std::endl;
+  for (auto && insn : crtl->ssa->all_insns()) {
+
+  }
   for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
   {
 if (dump_file)
@@ -1646,22 +1655,24 @@ rtl_ssa_dce_sweep(std::unordered_set 
marked)
   fprintf(dump_file, "Insn: %d\n", insn->uid());
 }
 next = insn->next_any_insn();
-if (!(marked.count(insn) > 0))
+if (marked.count(insn) > 0)
 {
-  if (dump_file)
-  {
-fprintf(dump_file, "  Sweeping insn %d\n", insn->uid());
-  }
+  continue;
+}
+
+if (dump_file)
+{
+  fprintf(dump_file, "  Sweeping insn %d\n", insn->uid());
+}
 
-  // Skip artificial insns (or uid() < 0)
-  if (insn->is_real())
-  {
-// std::cerr << "Insn: " << insn->uid() << " will be deleted\n";
-auto change = insn_change::delete_insn(insn);
-// crtl->ssa->possibly_queue_changes(change);
-to_delete.safe_push(change);
-   

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: partial cleanup, prepare transform to debug insns

2025-03-28 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:122b4dfca4b1a3e8e6e838ff068f0a016406b699

commit 122b4dfca4b1a3e8e6e838ff068f0a016406b699
Author: Ondřej Machota 
Date:   Fri Mar 28 20:13:27 2025 +0100

rtl-ssa-dce: partial cleanup, prepare transform to debug insns

Diff:
---
 gcc/dce.cc | 86 +-
 1 file changed, 69 insertions(+), 17 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index f227fc214e99..bb7040ae653d 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1306,6 +1306,32 @@ public:
 
 } // namespace
 
+struct offset_bitmap {
+  private:
+const int m_offset;
+sbitmap m_bitmap;
+  
+  public:
+offset_bitmap(size_t size, int offset) : m_bitmap{sbitmap_alloc(size)} {}
+offset_bitmap(int min_index, int max_index) : offset_bitmap(max_index - 
min_index, 0) {}
+
+void clear_bit(int index) {
+  bitmap_clear_bit(m_bitmap, index + m_offset);
+}
+
+void set_bit(int index) {
+  bitmap_set_bit(m_bitmap, index + m_offset);
+}
+
+bool get_bit(int index) {
+  return bitmap_bit_p(m_bitmap, index + m_offset);
+}
+
+~offset_bitmap() {
+  sbitmap_free(m_bitmap);
+}
+};
+
 bool sets_global_register(rtx_insn* insn) {
   rtx set = single_set(insn);
   if (!set)
@@ -1409,13 +1435,9 @@ bool is_ssa_prelive(const_rtx insn) {
 bool is_rtx_insn_prelive(rtx_insn *insn) {
   gcc_assert(insn != nullptr);
 
-  // Jumps, notes, barriers should not be deleted
-  // According to the docs, rtl ssa does not contain noteS and barrierS 
   if (!NONJUMP_INSN_P (insn))
   {
 // This handles jumps, debug_insns, call_insn, ...
-//std::cerr << "found jump instruction\n";
-//debug(insn);
 return true;
   }
 
@@ -1446,10 +1468,6 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate && 
find_reg_note (insn, REG_CFA_RESTORE, NULL))
 return true;
 
-  // Mark set of a global register
-  // if (sets_global_register(insn)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
-  //   return true;
-
   // TODO : asm_noperands???
 
   rtx body = PATTERN(insn);
@@ -1561,8 +1579,8 @@ rtl_ssa_dce_prelive(std::unordered_set 
&marked)
 next = insn->next_any_insn();
 if (is_prelive(insn))
   {
-// std::cout << "insn is prelive: " << insn->uid() << '\n';
-rtl_ssa_dce_mark_live(insn, worklist, marked);}
+rtl_ssa_dce_mark_live(insn, worklist, marked);
+  }
 
 // if (insn->can_be_optimized () || insn->is_debug_insn ())
 //  if (fwprop_insn (insn, fwprop_addr_p))
@@ -1575,9 +1593,6 @@ rtl_ssa_dce_prelive(std::unordered_set 
&marked)
 static std::unordered_set
 rtl_ssa_dce_mark()
 {
-  std::unordered_set marked_sets{};
-
-
   std::unordered_set marked{};
   // phi insn might have more that one phi node: 
gcc/gcc/testsuite/gcc.c-torture/execute/2224-1.c
   std::unordered_set marked_phi_nodes{};
@@ -1586,7 +1601,6 @@ rtl_ssa_dce_mark()
   auto_vec worklist_new{};
   for (auto && item : worklist) {
 insn_info * insn = item;
-// std::cerr << "cp Current: " << insn->uid() << '\n';
 for (auto&& use : insn->uses()) {
   set_info* set = use->def();
   if (set) {
@@ -1621,6 +1635,8 @@ rtl_ssa_dce_mark()
 
 use_array uses = insn->uses();
 if (insn->is_phi()) {
+  // Each phi node has a unique uid, yeeey
+  // So, only one bitmap (with shift) in needed.
   phi_info* pi = as_a (set);
   if (marked_phi_nodes.count(pi) > 0) {
 continue;
@@ -1710,6 +1726,41 @@ rtl_ssa_dce_sweep(std::unordered_set marked)
   }
 }
 
+static void
+rtl_ssa_dce_transform_insns_to_debug() {
+  // TODO : bude nejspise zase treba rozdelit phi a ostatni insns
+  std::unordered_set is_debug;
+
+  // chceme prochazet v post orderu, abychom nejdrive zpracovali zavislosti a 
pak az definici
+  // nelze jen menit instrukce, protoze musime informaci propagovat pres phi 
node
+  for (insn_info * insn : crtl->ssa->reverse_all_insns()) {
+if (insn->is_debug_insn()) { // phi is never debug
+// TODO : store info about this insn
+
+is_debug.emplace(insn->uid());
+continue;
+}
+
+if (insn->is_phi()) {
+  // TODO : special handling for phi_node required
+}
+
+bool is_debug = true;
+for (def_info *def : insn->defs()) {
+  // TODO : how to cast this correctly? - clobber_info
+  if (def->mode() == access_kind::CLOBBER)
+continue;
+  set_info* set = as_a(def);
+  for (use_info * use : set->all_uses()) {
+auto iii = use->insn()->uid();
+  }
+}
+
+// TODO : projit vsechny set_infa a podivat se, zda jsou zavisloti jen 
debug
+// Musime si dat pozor na phi - tam je treba se podivat na kontretni phi 
node
+  }
+}
+
 static void
 rtl_ssa_dce_init()
 {
@@ -1738,8 +1789,9 @@ static unsigned int
 rtl_ssa_dce()
 {
   rtl_ssa_dce_init();
-  // debug(crtl->ssa);
-  // std::cout << "\033[31m" << "Before rtl ssa dce pass" << "\033[0m" << "\n";

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: improve code

2025-04-01 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:f75018f0b959b76e0ba0b7bf2dbbe47e80d8cbe6

commit f75018f0b959b76e0ba0b7bf2dbbe47e80d8cbe6
Author: Ondřej Machota 
Date:   Mon Mar 31 08:50:34 2025 +0200

rtl-ssa-dce: improve code

Diff:
---
 gcc/dce.cc | 24 
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 53934d19c0ac..a90a8d9ccf53 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1538,6 +1538,14 @@ bool is_prelive(insn_info *insn)
 if (def->kind() != access_kind::SET)
   continue;
 
+// We need to perform some kind of reset_unmarked_insns_debug_uses
+// to be able to reproduce ud_dce - now only 4 tests are falling
+// because of debug_insn being dependent on parallel with set flags 
+// gcc.c-torture/execute/20051215-1.c
+// gcc.c-torture/execute/20100805-1.c
+// gcc.c-torture/execute/pr39339.c
+// gcc.c-torture/execute/pr47925.c
+
 // This might be messed up a bit
 if (def->regno() == FRAME_POINTER_REGNUM
 || def->regno() == STACK_POINTER_REGNUM)
@@ -1813,14 +1821,14 @@ rtl_ssa_dce()
   rtl_ssa_dce_init();
   std::unordered_set marked = rtl_ssa_dce_mark();
   rtl_ssa_dce_sweep(marked);
-  // std::cerr << "\033[31m" << "SSA debug start" << "\033[0m" << "\n";
-  // debug (crtl->ssa);
-  // for (insn_info * insn : crtl->ssa->all_insns()) {
-  //   if (insn->is_artificial())
-  // continue;
-  //   debug(insn->rtl());
-  // }
-  // std::cerr << "\033[31m" << "SSA debug end" << "\033[0m" << "\n";
+  std::cerr << "\033[31m" << "SSA debug start" << "\033[0m" << "\n";
+  debug (crtl->ssa);
+  for (insn_info * insn : crtl->ssa->all_insns()) {
+if (insn->is_artificial())
+  continue;
+debug(insn->rtl());
+  }
+  std::cerr << "\033[31m" << "SSA debug end" << "\033[0m" << "\n";
   rtl_ssa_dce_done();
   // if (delete_trivially_dead_insns(get_insns (), max_reg_num ())) {
   //   std::cerr << "\033[31m" << "rtl_ssa_dce did not delete everything :(" 
<< "\033[0m" << "\n";


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: delete dead debug insns

2025-04-09 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:668fb8231327b7385492464ab879fe06f9859ca1

commit 668fb8231327b7385492464ab879fe06f9859ca1
Author: Ondřej Machota 
Date:   Tue Apr 8 23:27:00 2025 +0200

rtl-ssa-dce: delete dead debug insns

Diff:
---
 gcc/dce.cc | 138 -
 1 file changed, 35 insertions(+), 103 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index c0ca89980254..40b4cd991151 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1421,42 +1421,24 @@ bool is_prelive(insn_info *insn)
   gcc_assert (insn->is_real());
   auto rtl = insn->rtl();
 
-  /* I guess that a lot of conditions bellow are captured by artificial uses
- of bb head and end insns. */
   for (def_info * def : insn->defs()) {
 /* The purpose of this pass is not to eliminate stores to memory... */
 if (def->is_mem())
-  // TODO : clobbered memory?
   return true;
 
 gcc_assert(def->is_reg());
-/* this ignores clobbers, which is probably fine */
 
 /* gcc.c-torture/execute/2503-1.c - flags register is unused. Not all
hard registers should be marked... */
+   
+/* this ignores clobbers, which is probably fine */
 if (def->kind() != access_kind::SET)
   continue;
 
-/* This might be messed up a bit */
-// if (def->regno() == FRAME_POINTER_REGNUM
-// || def->regno() == STACK_POINTER_REGNUM)
-//   return true;
-
 /* needed by gcc.c-torture/execute/pr51447.c */
 if (HARD_REGISTER_NUM_P (def->regno())
 && global_regs[def->regno()])
-// { std::cout << "marked global reg: " << def->regno() << " in " << 
insn->uid() << '\n';
-  return true;
-// }
-
-// if (!HARD_FRAME_POINTER_IS_FRAME_POINTER
-// && def->regno() == HARD_FRAME_POINTER_REGNUM)
-//   return true;
-
-// if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-// && fixed_regs[ARG_POINTER_REGNUM]
-// && def->regno() == ARG_POINTER_REGNUM)
-//   return true;
+return true;
 
 unsigned int picreg = PIC_OFFSET_TABLE_REGNUM;
 if (picreg != INVALID_REGNUM
@@ -1469,20 +1451,24 @@ bool is_prelive(insn_info *insn)
 }
 
 static void
-rtl_ssa_dce_mark_prelive_insn(insn_info *info, vec &worklist, 
+rtl_ssa_dce_mark_prelive_insn(insn_info *insn, auto_vec &worklist, 
   std::unordered_set &marked)
 {
   if (dump_file)
-fprintf(dump_file, "Insn %d is prelive\n", info->uid());
+fprintf(dump_file, "Insn %d marked as prelive\n", insn->uid());
 
-  marked.emplace(info);
-  worklist.safe_push(info);
+  marked.emplace(insn);
+  for (use_info *use : insn->uses()) {
+set_info* set = use->def();
+if (set)
+  worklist.safe_push(set);
+  }
 }
 
-static auto_vec
+static auto_vec
 rtl_ssa_dce_mark_prelive(std::unordered_set &marked)
 {
-  auto_vec worklist;
+  auto_vec worklist;
   for (insn_info * insn : crtl->ssa->all_insns()) {
 if (is_prelive(insn))
   rtl_ssa_dce_mark_prelive_insn(insn, worklist, marked);
@@ -1497,16 +1483,7 @@ rtl_ssa_dce_mark()
   std::unordered_set marked{};
   /* Phi insn might have more that one phi node: 
gcc/gcc/testsuite/gcc.c-torture/execute/2224-1.c */
   std::unordered_set marked_phi_nodes{};
-  auto prelive_insns = rtl_ssa_dce_mark_prelive(marked);
-  /* Extract uses from prelive insns to worklist */
-  auto_vec worklist{};
-  for (insn_info * insn : prelive_insns) {
-for (auto&& use : insn->uses()) {
-  set_info* set = use->def();
-  if (set)
-worklist.safe_push(set);
-}
-  }
+  auto worklist = rtl_ssa_dce_mark_prelive(marked);
 
   while (!worklist.is_empty()) {
 set_info* set = worklist.pop();
@@ -1581,78 +1558,31 @@ rtl_ssa_dce_sweep(std::unordered_set 
marked)
   crtl->ssa->change_insns(changes);
 }
 
-// WIP
-static void
-rtl_ssa_dce_transform_insns_to_debug() {
-  std::unordered_set is_debug;
-  // Should we use ssa when modifing insns? if yes, we want in-place replace
-
-  /* chceme prochazet v post orderu, abychom nejdrive zpracovali zavislosti
- a pak az definici nelze jen menit instrukce, protoze musime informaci
- propagovat pres phi node */
-  /* We check, whether all insns that use a definition from the current insn
- are only debug insns */
-  for (insn_info * insn : crtl->ssa->reverse_all_insns()) {
-if (insn->is_debug_insn()) { // phi is never debug
-// TODO : store info about this insn
-is_debug.emplace(insn->uid());
-continue;
-}
+static void reset_debug_insn_uses(insn_info * insn) {
+  gcc_assert(insn->is_debug_insn());
 
-if (insn->is_phi()) {
-  // for each phi_info
-  for (def_info *def : insn->defs()) {
-phi_info *pi = as_a (def);
-
-  }
-}
+  if (dump_file)
+fprintf(dump_file, "Resetting debug insn: %d\n", insn->uid());
 
-rtx_insn * rtl = insn->rtl();
-rtx set;
-if (!(MAY_HAVE_DEBUG_BIND_INSNS 
-  && (set = single_set (rtl)) != NULL_RTX 
-  && (!side_effects_p (SET_SRC (set))
-  && asm_n

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: propagate dead phis

2025-04-18 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:66297a27965b6bd6c04a85491e7270d33181a5c9

commit 66297a27965b6bd6c04a85491e7270d33181a5c9
Author: Ondřej Machota 
Date:   Fri Apr 18 15:55:39 2025 +0200

rtl-ssa-dce: propagate dead phis

Diff:
---
 gcc/dce.cc | 41 -
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 630906fb1ec6..c626d19f0747 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1511,7 +1511,7 @@ rtl_ssa_dce_mark(std::unordered_set 
&marked_phis)
   if (marked_phis.count(pi) > 0)
 continue;
 
-marked_phis.emplace(pi);
+  marked_phis.emplace(pi);
   uses = pi->inputs();
 }
 
@@ -1566,6 +1566,45 @@ rtl_ssa_dce_sweep(std::unordered_set marked)
 fprintf(dump_file, "DCE: finish sweep phase\n");
 }
 
+static void propagate_dead_phis(std::unordered_set &marked, 
std::unordered_set &marked_phis) {
+  auto_vec worklist;
+  // TODO : add visited to speedup following section
+  for (ebb_info *ebb : crtl->ssa->ebbs()) {
+for (phi_info *phi : ebb->phis()) {
+  if (marked_phis.count(phi) > 0) 
+continue;
+
+  worklist.safe_push(phi);
+}
+  }
+
+  // suppose that debug insns are marked - non marked will be removed later
+  while (!worklist.is_empty ()) {
+set_info *set = worklist.pop ();
+insn_info *insn = set->insn ();
+
+if (insn->is_debug_insn ()) {
+  marked.erase (insn);
+  // debug instructions dont have chains
+  continue;
+}
+
+for (use_info *use : set->all_uses()) {
+  if (use->is_in_phi()) {
+worklist.emplace (use->phi ());
+  } else {
+gcc_assert(use->is_in_any_insn ());
+for (def_info *def : use->insn()->defs()) {
+  if (def->kind() != access_kind::SET)
+continue;
+
+  worklist.emplace(static_cast(def));
+}
+  }
+}
+  }
+}
+
 // Clear debug_insn uses and set gen_rtx_UNKNOWN_VAR_LOC
 static void reset_debug_insn_uses(insn_info * insn) {
   gcc_assert(insn->is_debug_insn());


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: fix offset_bitmap size

2025-04-22 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:240fe8013efed4b33ba62582fdf9ae531bcd27a0

commit 240fe8013efed4b33ba62582fdf9ae531bcd27a0
Author: Ondřej Machota 
Date:   Tue Apr 22 12:20:36 2025 +0200

rtl-ssa-dce: fix offset_bitmap size

Diff:
---
 gcc/dce.cc | 18 --
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 0a210b008e41..c83324d3aa15 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1327,8 +1327,9 @@ struct offset_bitmap {
   public:
 offset_bitmap(size_t size, int offset) : m_offset{offset},
   m_bitmap{sbitmap_alloc(size)} {}
+
 offset_bitmap(int min_index, int max_index) : 
-  offset_bitmap(size_t(max_index - min_index), min_index) {}
+  offset_bitmap(size_t(max_index - min_index + 1), -min_index) {}
 
 void clear_bit(int index) {
   bitmap_clear_bit(m_bitmap, index + m_offset);
@@ -1731,7 +1732,7 @@ is_rtx_insn_prelive(rtx_insn *insn) {
 
   rtx body = PATTERN(insn);
   switch (GET_CODE(body)) {
-// Clobbers are handled inside is_prelive
+// Clobbers are handled inside is_prelive - what about parallel?
 // case CLOBBER: // gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 case USE:
 case VAR_LOCATION:
@@ -1973,6 +1974,19 @@ propagate_dead_phis(std::unordered_set 
&marked, std::unordered_set<
   return depends_on_dead_phi;
 }
 
+static void
+rtl_ssa_dce_debuggize(insn_info *insn) {
+  if (insn->is_phi()) {
+return;
+  }
+
+  if (insn->is_debug_insn()) {
+// we need to fix dependencies of this instruction because they might have
+// changed
+return;
+  }
+}
+
 static void
 test(insn_info *insn) {
   rtx_insn *rtl = insn->rtl();


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: apply clang format

2025-04-27 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:71827344a150eaa480e87c78faf71e49c04be9c5

commit 71827344a150eaa480e87c78faf71e49c04be9c5
Author: Ondřej Machota 
Date:   Mon Apr 28 08:45:07 2025 +0200

rtl-ssa-dce: apply clang format

Diff:
---
 gcc/dce.cc | 680 -
 1 file changed, 361 insertions(+), 319 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 70c9faf27c59..e21f8bff8898 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1318,33 +1318,28 @@ public:
 
 } // namespace
 
-struct offset_bitmap {
-  private:
-const int m_offset;
-sbitmap m_bitmap;
-  
-  public:
-offset_bitmap(size_t size, int offset) : m_offset{offset},
-  m_bitmap{sbitmap_alloc(size)} {}
-
-offset_bitmap(int min_index, int max_index) : 
-  offset_bitmap(size_t(max_index - min_index + 1), -min_index) {}
-
-void clear_bit(int index) {
-  bitmap_clear_bit(m_bitmap, index + m_offset);
-}
+struct offset_bitmap
+{
+private:
+  const int m_offset;
+  sbitmap m_bitmap;
 
-void set_bit(int index) {
-  bitmap_set_bit(m_bitmap, index + m_offset);
-}
+public:
+  offset_bitmap (size_t size, int offset)
+: m_offset{offset}, m_bitmap{sbitmap_alloc (size)}
+  {}
 
-bool get_bit(int index) {
-  return bitmap_bit_p(m_bitmap, index + m_offset);
-}
+  offset_bitmap (int min_index, int max_index)
+: offset_bitmap (size_t (max_index - min_index + 1), -min_index)
+  {}
 
-~offset_bitmap() {
-  sbitmap_free(m_bitmap);
-}
+  void clear_bit (int index) { bitmap_clear_bit (m_bitmap, index + m_offset); }
+
+  void set_bit (int index) { bitmap_set_bit (m_bitmap, index + m_offset); }
+
+  bool get_bit (int index) { return bitmap_bit_p (m_bitmap, index + m_offset); 
}
+
+  ~offset_bitmap () { sbitmap_free (m_bitmap); }
 };
 
 class rtl_ssa_dce
@@ -1353,33 +1348,37 @@ public:
   unsigned int execute (function *);
 
 private:
-  bool is_rtx_body_prelive(const_rtx);
-  bool can_delete_call(const_rtx);
-  bool is_rtx_prelive(const_rtx);
-  bool is_prelive(insn_info *);
-  void mark_prelive_insn(insn_info *, auto_vec&);
-  auto_vec mark_prelive();
-  void mark();
-  std::unordered_set propagate_dead_phis();
-  void reset_dead_debug_insn(insn_info *);
-  void reset_dead_debug();
-  void sweep();
-
+  bool is_rtx_body_prelive (const_rtx);
+  bool can_delete_call (const_rtx);
+  bool is_rtx_prelive (const_rtx);
+  bool is_prelive (insn_info *);
+  void mark_prelive_insn (insn_info *, auto_vec &);
+  auto_vec mark_prelive ();
+  void mark ();
+  std::unordered_set propagate_dead_phis ();
+  void reset_dead_debug_insn (insn_info *);
+  void reset_dead_debug ();
+  void sweep ();
+
+  offset_bitmap mm_marked;
+  offset_bitmap mm_marked_phis;
   std::unordered_set m_marked;
   std::unordered_set m_marked_phis;
 };
 
 bool
-rtl_ssa_dce::is_rtx_body_prelive(const_rtx insn) {
-  switch (GET_CODE(insn)) {
+rtl_ssa_dce::is_rtx_body_prelive (const_rtx insn)
+{
+  switch (GET_CODE (insn))
+{
 case PREFETCH:
 case UNSPEC:
 case TRAP_IF: /* testsuite/gcc.c-torture/execute/20020418-1.c */
   return true;
 
 default:
-  return side_effects_p(insn);
-  }
+  return side_effects_p (insn);
+}
 }
 
 bool
@@ -1387,10 +1386,9 @@ rtl_ssa_dce::can_delete_call (const_rtx insn)
 {
   if (cfun->can_delete_dead_exceptions)
 return true;
-  if (!insn_nothrow_p (insn))
-return false;
-  // if (can_alter_cfg)
-  return true;
+  // if (!insn_nothrow_p (insn))
+// return false;
+  return insn_nothrow_p (insn);
 
   // UD_DCE ignores this and works...
   /* If we can't alter cfg, even when the call can't throw exceptions, it
@@ -1403,45 +1401,49 @@ rtl_ssa_dce::can_delete_call (const_rtx insn)
   // edge_iterator ei;
 
   // FOR_EACH_EDGE (e, ei, BLOCK_FOR_INSN (insn)->succs)
-   // if ((e->flags & EDGE_ABNORMAL_CALL) != 0)
-   //   return false;
+  // if ((e->flags & EDGE_ABNORMAL_CALL) != 0)
+  //   return false;
   //   }
   // return true;
 }
 
 bool
-rtl_ssa_dce::is_rtx_prelive(const_rtx insn) {
-  gcc_assert(insn != nullptr);
+rtl_ssa_dce::is_rtx_prelive (const_rtx insn)
+{
+  gcc_assert (insn != nullptr);
 
   if (CALL_P (insn)
-// We cannot delete pure or const sibling calls because it is
-// hard to see the result.
-&& (!SIBLING_CALL_P (insn))
-// We can delete dead const or pure calls as long as they do not
-// infinite loop.
-&& (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P 
(insn))
-// Don't delete calls that may throw if we cannot do so.
-&& can_delete_call (insn))
-  return false;
+  // We cannot delete pure or const sibling calls because it is
+  // hard to see the result.
+  && (!SIBLING_CALL_P (insn))
+  // We can delete dead const or pure calls as long as they do not
+  // infinite loop.
+  && (RTL_CONST_OR_PURE_CALL_P (insn)
+ && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))
+  // Don't delete calls that may throw if we c

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: fix missing set bp

2025-04-24 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:ddda72f4a2053ebae4301980db947ab1a5fa33d0

commit ddda72f4a2053ebae4301980db947ab1a5fa33d0
Author: Ondřej Machota 
Date:   Thu Apr 24 17:50:37 2025 +0200

rtl-ssa-dce: fix missing set bp

Diff:
---
 gcc/dce.cc | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index c83324d3aa15..02da64c7669a 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1733,7 +1733,7 @@ is_rtx_insn_prelive(rtx_insn *insn) {
   rtx body = PATTERN(insn);
   switch (GET_CODE(body)) {
 // Clobbers are handled inside is_prelive - what about parallel?
-// case CLOBBER: // gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
+case CLOBBER: // gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 case USE:
 case VAR_LOCATION:
   return true;
@@ -1767,13 +1767,20 @@ is_prelive(insn_info *insn)
   return true;
 
 gcc_assert(def->is_reg());
+// if (def->regno() == HARD_FRAME_POINTER_REGNUM)
+  // std::cout << "set frame pointer (bp): " << def->regno() << " in: " << 
def->insn()->uid() << '\n';
+
+if (frame_pointer_needed && def->regno() == HARD_FRAME_POINTER_REGNUM) {
+  // std::cerr << "bp marked as prelive\n";
+  return true;
+}
 
 /* gcc.c-torture/execute/2503-1.c - flags register is unused. Not all
hard registers should be marked... */
 
 /* this ignores clobbers, which is probably fine */
 if (def->kind() == access_kind::CLOBBER)
-  return true;
+  continue;
 
 gcc_assert (def->kind() == access_kind::SET);
 
@@ -2092,6 +2099,16 @@ rtl_ssa_dce_fn()
   // debug(crtl->ssa);
   if (dump_file)
 dump(dump_file, crtl->ssa);
+  // std::cout << '\n' << function_name(cfun) << '\n';
+  // std::cout << "HARD_FRAME_POINTER_IS_ARG_POINTER: " << 
HARD_FRAME_POINTER_IS_ARG_POINTER << '\n';
+  // std::cout << "HARD_FRAME_POINTER_IS_FRAME_POINTER: " << 
HARD_FRAME_POINTER_IS_FRAME_POINTER << '\n';
+  // std::cout << "HARD_FRAME_POINTER_REGNUM: " << HARD_FRAME_POINTER_REGNUM 
<< '\n';
+  // std::cout << "FRAME_POINTER_REGNUM: " << FRAME_POINTER_REGNUM << '\n';
+  // std::cout << "fixed_regs[HARD_FRAME_POINTER_REGNUM]: " << 
(fixed_regs[HARD_FRAME_POINTER_REGNUM] == 1) << '\n';
+  // std::cout << "fixed_regs[FRAME_POINTER_REGNUM]: " << 
(fixed_regs[FRAME_POINTER_REGNUM] == 1) << '\n';
+  // std::cout << "global_regs[HARD_FRAME_POINTER_REGNUM]: " << 
(global_regs[HARD_FRAME_POINTER_REGNUM] == 1) << '\n';
+  // std::cout << "global_regs[FRAME_POINTER_REGNUM]: " << 
(global_regs[FRAME_POINTER_REGNUM] == 1) << '\n';
+  // std::cout << "frame_pointer_needed: " << frame_pointer_needed << '\n';
   std::unordered_set marked;
   std::unordered_set marked_phis;
   rtl_ssa_dce_mark(marked, marked_phis);


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: fix eh

2025-04-10 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:a8b182971c47e3793df08c7fbab6cde116bfcc4b

commit a8b182971c47e3793df08c7fbab6cde116bfcc4b
Author: Ondřej Machota 
Date:   Tue Apr 8 18:00:34 2025 +0200

rtl-ssa-dce: fix eh

Diff:
---
 gcc/dce.cc | 67 +-
 1 file changed, 27 insertions(+), 40 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 6221e3b39910..c0ca89980254 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1351,7 +1351,7 @@ bool is_rtx_prelive(const_rtx insn) {
   switch (GET_CODE(insn)) {
 case PREFETCH:
 case UNSPEC:
-case TRAP_IF:
+case TRAP_IF: /* testsuite/gcc.c-torture/execute/20020418-1.c */
   return true;
 
 default:
@@ -1372,7 +1372,6 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 /* Don't delete calls that may throw if we cannot do so.  */
 && can_delete_call (insn))
   return false;
-  // return !find_call_stack_args (as_a  (insn), false, fast, 
arg_stores);
 
   if (!NONJUMP_INSN_P (insn))
 /* This handles jumps, notes, call_insns, debug_insns, ... */
@@ -1396,10 +1395,6 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 case CLOBBER: // gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 case USE:
 case VAR_LOCATION:
-/* Following cases might be removed since they are part of is_rtx_prelive 
*/
-case PREFETCH:
-case TRAP_IF: /* testsuite/gcc.c-torture/execute/20020418-1.c */
-case UNSPEC:
   return true;
 
 case PARALLEL:
@@ -1415,13 +1410,19 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 
 bool is_prelive(insn_info *insn)
 {
-  /* Phi insns are never prelive, bb head + end also are artificial */
+  /* Phi insns are never prelive, bb head and end contain artificial uses that
+ we need to mark as prelive */
+  if (insn->is_bb_head() || insn->is_bb_end())
+return true;
+
   if (insn->is_artificial() || insn->is_debug_insn())
 return false;
 
   gcc_assert (insn->is_real());
   auto rtl = insn->rtl();
 
+  /* I guess that a lot of conditions bellow are captured by artificial uses
+ of bb head and end insns. */
   for (def_info * def : insn->defs()) {
 /* The purpose of this pass is not to eliminate stores to memory... */
 if (def->is_mem())
@@ -1431,59 +1432,44 @@ bool is_prelive(insn_info *insn)
 gcc_assert(def->is_reg());
 /* this ignores clobbers, which is probably fine */
 
-/* TODO : find something similar to mark_artificial_uses to mark only
-   artificially-used registers.
-   - df_get_regular_block_artificial_uses
-   That should fix following test as assume
-   gcc.c-torture/execute/2503-1.c - flags register is unused. Not all
+/* gcc.c-torture/execute/2503-1.c - flags register is unused. Not all
hard registers should be marked... */
 if (def->kind() != access_kind::SET)
   continue;
 
 /* This might be messed up a bit */
-if (def->regno() == FRAME_POINTER_REGNUM
-|| def->regno() == STACK_POINTER_REGNUM)
-  return true;
+// if (def->regno() == FRAME_POINTER_REGNUM
+// || def->regno() == STACK_POINTER_REGNUM)
+//   return true;
 
 /* needed by gcc.c-torture/execute/pr51447.c */
 if (HARD_REGISTER_NUM_P (def->regno())
 && global_regs[def->regno()])
-return true;
+// { std::cout << "marked global reg: " << def->regno() << " in " << 
insn->uid() << '\n';
+  return true;
+// }
 
-if (!HARD_FRAME_POINTER_IS_FRAME_POINTER
-&& def->regno() == HARD_FRAME_POINTER_REGNUM)
-  return true;
+// if (!HARD_FRAME_POINTER_IS_FRAME_POINTER
+// && def->regno() == HARD_FRAME_POINTER_REGNUM)
+//   return true;
 
-if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-&& fixed_regs[ARG_POINTER_REGNUM]
-&& def->regno() == ARG_POINTER_REGNUM)
-  return true;
+// if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+// && fixed_regs[ARG_POINTER_REGNUM]
+// && def->regno() == ARG_POINTER_REGNUM)
+//   return true;
 
 unsigned int picreg = PIC_OFFSET_TABLE_REGNUM;
 if (picreg != INVALID_REGNUM
 && fixed_regs[picreg]
 && def->regno() == picreg)
 return true;
-
-// TODO : eh?
-
-/*
-if (def->kind() == access_kind::SET 
-&& (HARD_REGISTER_NUM_P(def->regno())
-|| (pic_offset_table_rtx != nullptr 
-  && def->regno() == REGNO (pic_offset_table_rtx)
-  && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER))
-  ) {
-  // find_reg_note(insn->rtl(), REG_UNUSED, def->regno())
-  return true;
-} */
   }
 
   return is_rtx_insn_prelive(rtl);
 }
 
 static void
-rtl_ssa_dce_mark_prelive(insn_info *info, vec &worklist, 
+rtl_ssa_dce_mark_prelive_insn(insn_info *info, vec &worklist, 
   std::unordered_set &marked)
 {
   if (dump_file)
@@ -1494,12 +1480,12 @@ rtl_ssa_dce_mark_prelive(insn_info *info, vec &worklist,
 }
 
 static auto_vec
-rtl_ssa_dce_prelive(std::unordered_set &marked)
+rtl_ssa_dce

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: remove c style code

2025-04-25 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:f166c9141b6dc2094bef42d5b632da8b608f7a34

commit f166c9141b6dc2094bef42d5b632da8b608f7a34
Author: Ondřej Machota 
Date:   Fri Apr 25 21:57:46 2025 +0200

rtl-ssa-dce: remove c style code

Diff:
---
 gcc/dce.cc | 453 +
 1 file changed, 61 insertions(+), 392 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 02da64c7669a..70c9faf27c59 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1318,7 +1318,6 @@ public:
 
 } // namespace
 
-// This struct could help to remove unordered_set for rtl ssa dce
 struct offset_bitmap {
   private:
 const int m_offset;
@@ -1361,7 +1360,7 @@ private:
   void mark_prelive_insn(insn_info *, auto_vec&);
   auto_vec mark_prelive();
   void mark();
-  // void propagate_dead_phis();
+  std::unordered_set propagate_dead_phis();
   void reset_dead_debug_insn(insn_info *);
   void reset_dead_debug();
   void sweep();
@@ -1415,36 +1414,35 @@ rtl_ssa_dce::is_rtx_prelive(const_rtx insn) {
   gcc_assert(insn != nullptr);
 
   if (CALL_P (insn)
-/* We cannot delete pure or const sibling calls because it is
-  hard to see the result.  */
+// We cannot delete pure or const sibling calls because it is
+// hard to see the result.
 && (!SIBLING_CALL_P (insn))
-/* We can delete dead const or pure calls as long as they do not
-  infinite loop.  */
+// We can delete dead const or pure calls as long as they do not
+// infinite loop.
 && (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P 
(insn))
-/* Don't delete calls that may throw if we cannot do so.  */
+// Don't delete calls that may throw if we cannot do so.
 && can_delete_call (insn))
   return false;
 
   if (!NONJUMP_INSN_P (insn))
-/* This handles jumps, notes, call_insns, debug_insns, ... */
+// This handles jumps, notes, call_insns, debug_insns, ...
 return true;
 
-  /* Only rtx_insn should be handled here */
+  // Only rtx_insn should be handled here
   gcc_assert(GET_CODE(insn) == INSN);
 
-  /* Don't delete insns that may throw if we cannot do so.  */
+  // Don't delete insns that may throw if we cannot do so.
   if (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn)  && 
can_alter_cfg)
 return true;
  
-  /* Callee-save restores are needed.  */
+  // Callee-save restores are needed.
   if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate 
   && find_reg_note (insn, REG_CFA_RESTORE, NULL))
 return true;
 
   rtx body = PATTERN(insn);
   switch (GET_CODE(body)) {
-// Clobbers are handled inside is_prelive
-case CLOBBER: // gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
+case CLOBBER:
 case USE:
 case VAR_LOCATION:
   return true;
@@ -1462,12 +1460,14 @@ rtl_ssa_dce::is_rtx_prelive(const_rtx insn) {
 
 bool
 rtl_ssa_dce::is_prelive(insn_info *insn) {
-  // Phi insns and debug insns are never prelive, bb head and end contain 
-  // artificial uses that we need to mark as prelive
-  if (insn->is_bb_head() || insn->is_bb_end())
+  // bb head and end contain artificial uses that we need to mark as prelive
+  // debug instructions are also prelive, however, they are not added to the
+  // worklist
+  if (insn->is_bb_head() || insn->is_bb_end() || insn->is_debug_insn())
 return true;
 
-  if (insn->is_artificial() || insn->is_debug_insn())
+  // Phi instructions are never prelive
+  if (insn->is_artificial())
 return false;
 
   gcc_assert (insn->is_real());
@@ -1478,18 +1478,18 @@ rtl_ssa_dce::is_prelive(insn_info *insn) {
 
 gcc_assert(def->is_reg());
 
-/* gcc.c-torture/execute/2503-1.c - flags register is unused. Not all
-   hard registers should be marked... */
+// we should not delete the frame pointer because of the dward2frame pass
+if (frame_pointer_needed && def->regno() == HARD_FRAME_POINTER_REGNUM)
+  return true;
  
-/* this ignores clobbers, which is probably fine */
+// skip clobbers, they are handled inside is_rtx_prelive
 if (def->kind() == access_kind::CLOBBER)
-  return true;
+  continue;
 
 gcc_assert (def->kind() == access_kind::SET);
 
-/* needed by gcc.c-torture/execute/pr51447.c */
-if (HARD_REGISTER_NUM_P (def->regno())
-&& global_regs[def->regno()])
+// needed by gcc.c-torture/execute/pr51447.c
+if (HARD_REGISTER_NUM_P (def->regno()) && global_regs[def->regno()])
   return true;
 
 unsigned int picreg = PIC_OFFSET_TABLE_REGNUM;
@@ -1508,6 +1508,11 @@ rtl_ssa_dce::mark_prelive_insn(insn_info *insn, 
auto_vec &worklist)
 fprintf(dump_file, "Insn %d marked as prelive\n", insn->uid());
 
   m_marked.emplace(insn);
+  // debug instruction are not added to worklist not to wake up possibly dead
+  // instructions 
+  if (insn->is_debug_insn())
+return;
+
   for (use_info *use : insn->uses()) {
 set_info* set = use->def();
 if (set)
@@ -1538,11 +1543,10 @@ rtl_ssa_dce::mark() {
   while (

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: remove useless conditions and fix dead debug insns

2025-04-15 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:f495eae10735f687366a59884a25561de823daff

commit f495eae10735f687366a59884a25561de823daff
Author: Ondřej Machota 
Date:   Tue Apr 15 09:21:56 2025 +0200

rtl-ssa-dce: remove useless conditions and fix dead debug insns

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

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 40b4cd991151..630906fb1ec6 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -123,6 +123,8 @@ can_delete_call (rtx_insn *insn)
   return true;
 }
 
+static bool inside_ud = false;
+
 /* Return true if INSN is a normal instruction that can be deleted by
the DCE pass.  */
 
@@ -578,8 +580,6 @@ reset_unmarked_insns_debug_uses (void)
 }
 
 /* Delete every instruction that hasn't been marked.  */
-static bool inside_ud = false;
-
 static void
 delete_unmarked_insns (void)
 {
@@ -819,7 +819,6 @@ fini_dce (bool fast)
 static unsigned int
 rest_of_handle_ud_dce (void)
 {
-  inside_ud = true;
   rtx_insn *insn;
 
   init_dce (false);
@@ -833,6 +832,7 @@ rest_of_handle_ud_dce (void)
 }
   worklist.release ();
 
+  inside_ud = true;
   if (MAY_HAVE_DEBUG_BIND_INSNS)
 reset_unmarked_insns_debug_uses ();
 
@@ -1381,9 +1381,8 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   gcc_assert(GET_CODE(insn) == INSN);
 
   /* Don't delete insns that may throw if we cannot do so.  */
-  if (!(cfun->can_delete_dead_exceptions && can_alter_cfg)
-  && !insn_nothrow_p (insn))
-return true;
+  if (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn))
+  return true;
  
   /* Callee-save restores are needed.  */
   if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate 
@@ -1410,8 +1409,8 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 
 bool is_prelive(insn_info *insn)
 {
-  /* Phi insns are never prelive, bb head and end contain artificial uses that
- we need to mark as prelive */
+  /* Phi insns and debug insns are never prelive, bb head and end contain 
+ artificial uses that we need to mark as prelive */
   if (insn->is_bb_head() || insn->is_bb_end())
 return true;
 
@@ -1468,6 +1467,9 @@ rtl_ssa_dce_mark_prelive_insn(insn_info *insn, 
auto_vec &worklist,
 static auto_vec
 rtl_ssa_dce_mark_prelive(std::unordered_set &marked)
 {
+  if (dump_file)
+fprintf(dump_file, "DCE: prelive phase\n");
+
   auto_vec worklist;
   for (insn_info * insn : crtl->ssa->all_insns()) {
 if (is_prelive(insn))
@@ -1478,12 +1480,13 @@ rtl_ssa_dce_mark_prelive(std::unordered_set &marked)
 }
 
 static std::unordered_set
-rtl_ssa_dce_mark()
+rtl_ssa_dce_mark(std::unordered_set &marked_phis)
 {
-  std::unordered_set marked{};
   /* Phi insn might have more that one phi node: 
gcc/gcc/testsuite/gcc.c-torture/execute/2224-1.c */
-  std::unordered_set marked_phi_nodes{};
+  std::unordered_set marked{};
   auto worklist = rtl_ssa_dce_mark_prelive(marked);
+  if (dump_file)
+fprintf(dump_file, "DCE: marking phase\n");
 
   while (!worklist.is_empty()) {
 set_info* set = worklist.pop();
@@ -1505,10 +1508,10 @@ rtl_ssa_dce_mark()
  might be used. */
   phi_info* pi = as_a (set);
   auto pi_uid = pi->uid();
-  if (marked_phi_nodes.count(pi) > 0)
+  if (marked_phis.count(pi) > 0)
 continue;
 
-  marked_phi_nodes.emplace(pi);
+marked_phis.emplace(pi);
   uses = pi->inputs();
 }
 
@@ -1527,37 +1530,43 @@ rtl_ssa_dce_mark()
   return marked;
 }
 
+// Iterate over non-debug instructions in RPO and remove all aren't marked.
 static void
 rtl_ssa_dce_sweep(std::unordered_set marked)
 {
-  /* We can get the number of items in the `marked` set and create an array
- of changes with appropriate size */
+  if (dump_file)
+fprintf(dump_file, "DCE: Sweep phase\n");
+
   auto_vec to_delete;
-  for (insn_info * insn : crtl->ssa->all_insns()) {
-/* Artificial and marked insns cannot be deleted.
-   There is a slight problem with phis, because we might want to delete
-   some phi nodes from phi insn. */
-if (insn->is_artificial() || insn->is_debug_insn() || marked.count(insn) > 
0)
+  for (insn_info * insn : crtl->ssa->nondebug_insns()) {
+// Artificial or marked insns cannot be deleted.
+if (insn->is_artificial() || marked.count(insn) > 0)
   continue;
 
-auto change = insn_change::delete_insn(insn);
-to_delete.safe_push(change);
 if (dump_file)
-  fprintf(dump_file, "Sweeping insn %d\n", insn->uid());
-/* crtl->ssa->change_insn(change); */
+  fprintf(dump_file, "Sweeping insn: %d\n", insn->uid());
+
+auto change = insn_change::delete_insn(insn);
+to_delete.safe_push(std::move(change));
+
+// If we use following way with reverse_nondebug_insns, not all insns seem
+// to be deleted...
+// crtl->ssa->change_insn(change);
   }
 
-  auto attempt = crtl->ssa->new_change_attempt ();
   auto_vec changes(to_delete.length());
   for (size_t i = 0; i != to_delete.length(); ++i)

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: use sbitmap completed

2025-04-29 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:e18885b07e47e933aa12ee5bbbaa29b0628ec609

commit e18885b07e47e933aa12ee5bbbaa29b0628ec609
Author: Ondřej Machota 
Date:   Tue Apr 29 14:31:10 2025 +0200

rtl-ssa-dce: use sbitmap completed

Diff:
---
 gcc/dce.cc | 113 ++---
 1 file changed, 63 insertions(+), 50 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 3bc5bdb4d56c..67c9ad577e67 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1336,11 +1336,10 @@ private:
   void reset_dead_debug ();
   void sweep ();
 
-  int phi_min, real_max, artificial_min;
+  int offset;
+  
   sbitmap mm_marked;
   sbitmap mm_marked_phis;
-  std::unordered_set m_marked;
-  std::unordered_set m_marked_phis;
 };
 
 bool
@@ -1488,7 +1487,7 @@ rtl_ssa_dce::mark_prelive_insn (insn_info *insn, 
auto_vec &worklist)
   if (dump_file)
 fprintf (dump_file, "Insn %d marked as prelive\n", insn->uid ());
 
-  bitmap_set_bit (mm_marked, insn->uid ());
+  bitmap_set_bit (mm_marked, insn->uid () + offset);
   // debug instruction are not added to worklist not to wake up possibly dead
   // instructions
   if (insn->is_debug_insn ())
@@ -1533,7 +1532,7 @@ rtl_ssa_dce::mark ()
continue;
 
   // Skip already visited visited instructions.
-  auto uid = insn->uid ();
+  auto uid = insn->uid () + offset;
   if (bitmap_bit_p (mm_marked, uid) && !insn->is_phi ())
continue;
 
@@ -1543,12 +1542,12 @@ rtl_ssa_dce::mark ()
   if (insn->is_phi ())
{
  phi_info *phi = static_cast (set);
- auto phi_uid = pi->uid ();
+ auto phi_uid = phi->uid ();
  // Skip already visited phi node.
  if (bitmap_bit_p(mm_marked_phis, phi_uid))
continue;
 
-mm_marked_phis.set_bit(phi_uid);
+bitmap_set_bit (mm_marked_phis, phi_uid);
  uses = phi->inputs ();
}
 
@@ -1575,7 +1574,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 ());
+  // bitmap_clear_bit (mm_marked, insn->uid () + offset);
   insn_change change (insn);
   change.new_uses = {};
   INSN_VAR_LOCATION_LOC (insn->rtl ()) = gen_rtx_UNKNOWN_VAR_LOC ();
@@ -1599,19 +1598,18 @@ rtl_ssa_dce::reset_dead_debug ()
   // TODO : use iterate_safely?
   for (use_info *use : insn->uses ())
{
- insn_info *parent_insn = use->def ()->insn (); // TODO : check for 
nullptr
+def_info *def = use->def ();
+ insn_info *parent_insn = def->insn ();
+// Is this check needed?
+if (parent_insn == nullptr)
+  continue;
+// If we depend on a dead instruction, clear current instruction uses.
 sbitmap marked = parent_insn->is_phi () ? mm_marked_phis : mm_marked;
-int uid = parent_insn->is_phi () ? as_a (use->def ())->uid () 
? parent_insn->uid ();
+int uid = parent_insn->is_phi () ? static_cast (def)->uid () : 
parent_insn->uid () + offset;
 if (!bitmap_bit_p (marked, uid)) {
-  // ...
+  reset_dead_debug_insn (insn);
+   break;
 }
- if ((parent_insn->is_phi ()
-  && m_marked_phis.count (as_a (use->def ())) == 0)
- || (!parent_insn->is_phi () && m_marked.count (parent_insn) == 0))
-   {
- reset_dead_debug_insn (insn);
- break;
-   }
}
 }
 }
@@ -1627,7 +1625,7 @@ rtl_ssa_dce::sweep ()
   for (insn_info *insn : crtl->ssa->nondebug_insns ())
 {
   // Artificial or marked insns should not be deleted.
-  if (insn->is_artificial () || m_marked.count (insn) > 0)
+  if (insn->is_artificial () || bitmap_bit_p (mm_marked, insn->uid () + 
offset))
continue;
 
   if (dump_file)
@@ -1652,6 +1650,8 @@ rtl_ssa_dce::sweep ()
 fprintf (dump_file, "DCE: finish sweep phase\n");
 }
 
+#include 
+
 unsigned int
 rtl_ssa_dce::execute (function *fn)
 {
@@ -1659,18 +1659,32 @@ rtl_ssa_dce::execute (function *fn)
   // internal compiler error: gcc.c-torture/execute/20040811-1.c -
   // rtl_ssa::function_info::add_phi_nodes
   crtl->ssa = new rtl_ssa::function_info (fn);
+  int real_max = 0, artificial_min = 0;
+  std::size_t count = 0;
   for (insn_info *insn : crtl->ssa->all_insns ()) 
   {
 artificial_min = std::min (artificial_min, insn->uid ());
-real_max = std::min (real_max, insn->uid ());
+real_max = std::max (real_max, insn->uid ());
+count++;
   }
 
+  offset = -artificial_min;
+  // std::cout << "real_max: " << real_max << '\n';
+  // std::cout << "artificial_min: " << artificial_min << '\n';
+  // std::cout << "total: " << real_max - artificial_min + 3 << '\n';
+  // std::cout << "Offset: " << offset << '\n';
+  // std::cout << "count: " << count << '\n';
+
+  unsigned int phi_node_max = 0;
   for (ebb_info *ebb : crtl->ssa->ebbs ())
 for (phi_info *phi : ebb->phis ())
-  phi_min = std::min (phi_min, phi->uid ());
+phi_node_max = std::max 

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: use sbitmap

2025-04-29 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:0b830664e62baeb3ff35bf79dbeaf0211251bd9b

commit 0b830664e62baeb3ff35bf79dbeaf0211251bd9b
Author: Ondřej Machota 
Date:   Tue Apr 29 09:44:32 2025 +0200

rtl-ssa-dce: use sbitmap

Diff:
---
 gcc/dce.cc | 70 --
 1 file changed, 32 insertions(+), 38 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 4f35875988cf..3bc5bdb4d56c 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1318,30 +1318,6 @@ public:
 
 } // namespace
 
-struct offset_bitmap
-{
-private:
-  const int m_offset;
-  sbitmap m_bitmap;
-
-public:
-  offset_bitmap (size_t size, int offset)
-: m_offset{offset}, m_bitmap{sbitmap_alloc (size)}
-  {}
-
-  offset_bitmap (int min_index, int max_index)
-: offset_bitmap (size_t (max_index - min_index + 1), -min_index)
-  {}
-
-  void clear_bit (int index) { bitmap_clear_bit (m_bitmap, index + m_offset); }
-
-  void set_bit (int index) { bitmap_set_bit (m_bitmap, index + m_offset); }
-
-  bool get_bit (int index) { return bitmap_bit_p (m_bitmap, index + m_offset); 
}
-
-  ~offset_bitmap () { sbitmap_free (m_bitmap); }
-};
-
 class rtl_ssa_dce
 {
 public:
@@ -1360,8 +1336,9 @@ private:
   void reset_dead_debug ();
   void sweep ();
 
-  offset_bitmap mm_marked;
-  offset_bitmap mm_marked_phis;
+  int phi_min, real_max, artificial_min;
+  sbitmap mm_marked;
+  sbitmap mm_marked_phis;
   std::unordered_set m_marked;
   std::unordered_set m_marked_phis;
 };
@@ -1511,8 +1488,7 @@ rtl_ssa_dce::mark_prelive_insn (insn_info *insn, 
auto_vec &worklist)
   if (dump_file)
 fprintf (dump_file, "Insn %d marked as prelive\n", insn->uid ());
 
-  mm_marked.set_bit(insn->uid());
-  m_marked.emplace (insn);
+  bitmap_set_bit (mm_marked, insn->uid ());
   // debug instruction are not added to worklist not to wake up possibly dead
   // instructions
   if (insn->is_debug_insn ())
@@ -1558,24 +1534,22 @@ rtl_ssa_dce::mark ()
 
   // Skip already visited visited instructions.
   auto uid = insn->uid ();
-  if ((m_marked.count (insn) > 0) && !insn->is_phi ())
+  if (bitmap_bit_p (mm_marked, uid) && !insn->is_phi ())
continue;
 
-  m_marked.emplace (insn);
-  mm_marked.set_bit(uid);
+  bitmap_set_bit (mm_marked, uid);
 
   use_array uses = insn->uses ();
   if (insn->is_phi ())
{
- phi_info *pi = static_cast (set);
- auto pi_uid = pi->uid ();
+ phi_info *phi = static_cast (set);
+ auto phi_uid = pi->uid ();
  // Skip already visited phi node.
- if (m_marked_phis.count (pi) > 0)
+ if (bitmap_bit_p(mm_marked_phis, phi_uid))
continue;
 
-mm_marked_phis.set_bit(pi_uid);
- m_marked_phis.emplace (pi);
- uses = pi->inputs ();
+mm_marked_phis.set_bit(phi_uid);
+ uses = phi->inputs ();
}
 
   if (dump_file)
@@ -1601,6 +1575,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 ());
   insn_change change (insn);
   change.new_uses = {};
   INSN_VAR_LOCATION_LOC (insn->rtl ()) = gen_rtx_UNKNOWN_VAR_LOC ();
@@ -1624,7 +1599,12 @@ rtl_ssa_dce::reset_dead_debug ()
   // TODO : use iterate_safely?
   for (use_info *use : insn->uses ())
{
- insn_info *parent_insn = use->def ()->insn ();
+ insn_info *parent_insn = use->def ()->insn (); // TODO : check for 
nullptr
+sbitmap marked = parent_insn->is_phi () ? mm_marked_phis : mm_marked;
+int uid = parent_insn->is_phi () ? as_a (use->def ())->uid () 
? parent_insn->uid ();
+if (!bitmap_bit_p (marked, uid)) {
+  // ...
+}
  if ((parent_insn->is_phi ()
   && m_marked_phis.count (as_a (use->def ())) == 0)
  || (!parent_insn->is_phi () && m_marked.count (parent_insn) == 0))
@@ -1679,6 +1659,18 @@ rtl_ssa_dce::execute (function *fn)
   // internal compiler error: gcc.c-torture/execute/20040811-1.c -
   // rtl_ssa::function_info::add_phi_nodes
   crtl->ssa = new rtl_ssa::function_info (fn);
+  for (insn_info *insn : crtl->ssa->all_insns ()) 
+  {
+artificial_min = std::min (artificial_min, insn->uid ());
+real_max = std::min (real_max, insn->uid ());
+  }
+
+  for (ebb_info *ebb : crtl->ssa->ebbs ())
+for (phi_info *phi : ebb->phis ())
+  phi_min = std::min (phi_min, phi->uid ());
+
+  mm_marked = sbitmap_alloc(real_max - artificial_min + 1);
+  mm_marked_phis = sbitmap_alloc(-phi_min);
 
   if (dump_file)
 dump (dump_file, crtl->ssa);
@@ -1709,6 +1701,8 @@ rtl_ssa_dce::execute (function *fn)
   if (crtl->ssa->perform_pending_updates ())
 cleanup_cfg (0);
 
+  sbitmap_free(mm_marked);
+  sbitmap_free(mm_marked_phis);
   delete crtl->ssa;
   crtl->ssa = nullptr;
 }


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: prepare sbitmaps

2025-04-28 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:7c51ab8bcf7707ef1f752a3fbd30f1f9edc9a2a3

commit 7c51ab8bcf7707ef1f752a3fbd30f1f9edc9a2a3
Author: Ondřej Machota 
Date:   Mon Apr 28 20:41:18 2025 +0200

rtl-ssa-dce: prepare sbitmaps

Diff:
---
 gcc/dce.cc | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index e21f8bff8898..4f35875988cf 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1511,6 +1511,7 @@ rtl_ssa_dce::mark_prelive_insn (insn_info *insn, 
auto_vec &worklist)
   if (dump_file)
 fprintf (dump_file, "Insn %d marked as prelive\n", insn->uid ());
 
+  mm_marked.set_bit(insn->uid());
   m_marked.emplace (insn);
   // debug instruction are not added to worklist not to wake up possibly dead
   // instructions
@@ -1561,6 +1562,7 @@ rtl_ssa_dce::mark ()
continue;
 
   m_marked.emplace (insn);
+  mm_marked.set_bit(uid);
 
   use_array uses = insn->uses ();
   if (insn->is_phi ())
@@ -1571,6 +1573,7 @@ rtl_ssa_dce::mark ()
  if (m_marked_phis.count (pi) > 0)
continue;
 
+mm_marked_phis.set_bit(pi_uid);
  m_marked_phis.emplace (pi);
  uses = pi->inputs ();
}
@@ -1742,7 +1745,8 @@ rtl_ssa_dce::propagate_dead_phis ()
  if (dump_file)
fprintf (dump_file, "Debug insns %d depends on dead phi.\n",
 insn->uid ());
- marked.erase (insn);
+ m_marked.erase (insn);
+mm_marked.clear_bit(insn->uid());
  // debug instructions dont have chains
  continue;
}
@@ -1750,12 +1754,12 @@ rtl_ssa_dce::propagate_dead_phis ()
   // mark
   if (insn->is_phi ())
{
- gcc_assert (marked_phis.count (static_cast (set)) == 0);
+ gcc_assert (m_marked_phis.count (static_cast (set)) == 0);
  visited_dead_phis.emplace (static_cast (set));
}
   else
{
- gcc_assert (marked.count (insn) == 0);
+ gcc_assert (m_marked.count (insn) == 0);
  depends_on_dead_phi.emplace (insn);
}


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: c++ version, propagate dead phis

2025-04-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:65a8a2615bb6057578feb2f8760b7841ffebd787

commit 65a8a2615bb6057578feb2f8760b7841ffebd787
Author: Ondřej Machota 
Date:   Mon Apr 21 22:47:07 2025 +0200

rtl-ssa-dce: c++ version, propagate dead phis

Diff:
---
 gcc/dce.cc | 482 -
 1 file changed, 449 insertions(+), 33 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index c626d19f0747..0a210b008e41 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1347,7 +1347,30 @@ struct offset_bitmap {
 }
 };
 
-bool is_rtx_prelive(const_rtx insn) {
+class rtl_ssa_dce
+{
+public:
+  unsigned int execute (function *);
+
+private:
+  bool is_rtx_body_prelive(const_rtx);
+  bool can_delete_call(const_rtx);
+  bool is_rtx_prelive(const_rtx);
+  bool is_prelive(insn_info *);
+  void mark_prelive_insn(insn_info *, auto_vec&);
+  auto_vec mark_prelive();
+  void mark();
+  // void propagate_dead_phis();
+  void reset_dead_debug_insn(insn_info *);
+  void reset_dead_debug();
+  void sweep();
+
+  std::unordered_set m_marked;
+  std::unordered_set m_marked_phis;
+};
+
+bool
+rtl_ssa_dce::is_rtx_body_prelive(const_rtx insn) {
   switch (GET_CODE(insn)) {
 case PREFETCH:
 case UNSPEC:
@@ -1359,7 +1382,35 @@ bool is_rtx_prelive(const_rtx insn) {
   }
 }
 
-bool is_rtx_insn_prelive(rtx_insn *insn) {
+bool
+rtl_ssa_dce::can_delete_call (const_rtx insn)
+{
+  if (cfun->can_delete_dead_exceptions)
+return true;
+  if (!insn_nothrow_p (insn))
+return false;
+  // if (can_alter_cfg)
+  return true;
+
+  // UD_DCE ignores this and works...
+  /* If we can't alter cfg, even when the call can't throw exceptions, it
+ might have EDGE_ABNORMAL_CALL edges and so we shouldn't delete such
+ calls.  */
+  // gcc_assert (CALL_P (insn));
+  // if (BLOCK_FOR_INSN (insn) && BB_END (BLOCK_FOR_INSN (insn)) == insn)
+  //   {
+  // edge e;
+  // edge_iterator ei;
+
+  // FOR_EACH_EDGE (e, ei, BLOCK_FOR_INSN (insn)->succs)
+   // if ((e->flags & EDGE_ABNORMAL_CALL) != 0)
+   //   return false;
+  //   }
+  // return true;
+}
+
+bool
+rtl_ssa_dce::is_rtx_prelive(const_rtx insn) {
   gcc_assert(insn != nullptr);
 
   if (CALL_P (insn)
@@ -1381,8 +1432,8 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   gcc_assert(GET_CODE(insn) == INSN);
 
   /* Don't delete insns that may throw if we cannot do so.  */
-  if (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn))
-  return true;
+  if (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn)  && 
can_alter_cfg)
+return true;
  
   /* Callee-save restores are needed.  */
   if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate 
@@ -1391,11 +1442,301 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 
   rtx body = PATTERN(insn);
   switch (GET_CODE(body)) {
+// Clobbers are handled inside is_prelive
 case CLOBBER: // gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 case USE:
 case VAR_LOCATION:
   return true;
 
+case PARALLEL:
+  for (int i = XVECLEN (body, 0) - 1; i >= 0; i--)
+if (is_rtx_body_prelive (XVECEXP (body, 0, i)))
+  return true;
+  return false;
+
+default:
+  return is_rtx_body_prelive (body);
+  }
+}
+
+bool
+rtl_ssa_dce::is_prelive(insn_info *insn) {
+  // Phi insns and debug insns are never prelive, bb head and end contain 
+  // artificial uses that we need to mark as prelive
+  if (insn->is_bb_head() || insn->is_bb_end())
+return true;
+
+  if (insn->is_artificial() || insn->is_debug_insn())
+return false;
+
+  gcc_assert (insn->is_real());
+  for (def_info *def : insn->defs()) {
+// The purpose of this pass is not to eliminate memory stores...
+if (def->is_mem())
+  return true;
+
+gcc_assert(def->is_reg());
+
+/* gcc.c-torture/execute/2503-1.c - flags register is unused. Not all
+   hard registers should be marked... */
+ 
+/* this ignores clobbers, which is probably fine */
+if (def->kind() == access_kind::CLOBBER)
+  return true;
+
+gcc_assert (def->kind() == access_kind::SET);
+
+/* needed by gcc.c-torture/execute/pr51447.c */
+if (HARD_REGISTER_NUM_P (def->regno())
+&& global_regs[def->regno()])
+  return true;
+
+unsigned int picreg = PIC_OFFSET_TABLE_REGNUM;
+if (picreg != INVALID_REGNUM
+&& fixed_regs[picreg]
+&& def->regno() == picreg)
+  return true;
+  }
+
+  return is_rtx_prelive(insn->rtl());
+}
+
+void
+rtl_ssa_dce::mark_prelive_insn(insn_info *insn, auto_vec 
&worklist) {
+  if (dump_file)
+fprintf(dump_file, "Insn %d marked as prelive\n", insn->uid());
+
+  m_marked.emplace(insn);
+  for (use_info *use : insn->uses()) {
+set_info* set = use->def();
+if (set)
+  worklist.safe_push(set);
+  }
+}
+
+auto_vec
+rtl_ssa_dce::mark_prelive() {
+  if (dump_file)
+fprintf(dump_file, "DCE: prelive phase\n");
+
+  auto_vec worklist;
+  for (insn_info *insn : crtl->ssa->all_insns()) {
+if (is_prelive(

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce add prelive conditions

2025-02-17 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:175c246015a7c0f4d23c79b883467edfd4680855

commit 175c246015a7c0f4d23c79b883467edfd4680855
Author: Ondřej Machota 
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
 .  */
 
+#include 
 #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 
 
 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 &worklist, sbitmap 
marked_rtx)
+rtl_ssa_dce_mark_live(insn_info *info, vec &worklist, 
std::unordered_set 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
+rtl_ssa_dce_prelive(std::unordered_set marked)
 {
   insn_info *next;
   auto_vec 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 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-

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce fix bad marked insn map passing

2025-03-09 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:5759cb1c0b15d7c83f3aa5701d883508004a1b83

commit 5759cb1c0b15d7c83f3aa5701d883508004a1b83
Author: Ondřej Machota 
Date:   Sun Mar 9 20:59:45 2025 +0100

rtl-ssa: dce fix bad marked insn map passing

Diff:
---
 gcc/dce.cc | 146 -
 1 file changed, 116 insertions(+), 30 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index a04c5702d8a3..fa3d7721a6d0 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1313,6 +1313,7 @@ bool sets_global_register(const_rtx rtx) {
 }
 
 // We should mark stack registers
+// use HARD_FRAME_POINTER_REGNUM, REGNO_PTR_FRAME_P
 bool sets_global_register(rtx_insn* insn) {
   rtx set = single_set(insn);
   if (!set)
@@ -1367,21 +1368,55 @@ bool is_unary_mem_modification(rtx_code code) {
   }
 }
 
-bool is_rtx_insn_prelive(const_rtx rtx) {
-  if (rtx == nullptr) {
-return false;
+bool is_rtx_insn_prelive(rtx_insn *insn) {
+  gcc_assert(insn != nullptr);
+
+  // TODO : handle calls correctly
+  if (CALL_P (insn)
+  /* We cannot delete pure or const sibling calls because it is
+hard to see the result.  */
+  && (!SIBLING_CALL_P (insn))
+  /* We can delete dead const or pure calls as long as they do not
+ infinite loop.  */
+  && (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P 
(insn))
+  /* Don't delete calls that may throw if we cannot do so.  */
+  && can_delete_call (insn))
+return true;
+// return !find_call_stack_args (as_a  (insn), false, 
fast, arg_stores);
+
+  // Jumps, notes, barriers should not be deleted
+// According to the docs, rtl ssa does not contain noteS and barrierS 
+  if (!NONJUMP_INSN_P (insn))
+  {
+std::cerr << "found jump instruction\n";
+debug(insn);
+return true;
   }
 
-  auto code = GET_CODE(rtx);
-  if (is_control_flow(code))
+  // Only rtx_insn should be handled here
+  auto code = GET_CODE(insn);
+  gcc_assert(code == INSN);
+
+  /* Don't delete insns that may throw if we cannot do so.  */
+  if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) && !insn_nothrow_p 
(insn))
 return true;
 
+  /* TODO : What about call argumets? Accoring to the docs, for function 
prologue the RTX_FRAME_RELATED_P
+ should return true.
+  */  
+  /* Callee-save restores are needed.  */
+  if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate && 
find_reg_note (insn, REG_CFA_RESTORE, NULL))
+return true;
+
+  // if (is_control_flow(code))
+  //   return true;
+
   // Mark set of a global register
-  if (sets_global_register(rtx)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
+  if (sets_global_register(insn)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
 return true;
 
-  // Call is inside side_effects_p - how to mark parameter registers?
-  if (volatile_refs_p(rtx) || can_throw_internal(rtx) || BARRIER_P(rtx) || 
code == PREFETCH)
+  rtx body = PATTERN(insn);
+  if (side_effects_p(body) || can_throw_internal(body))
 return true;
 
   if (is_unary_mem_modification(code))
@@ -1391,21 +1426,34 @@ bool is_rtx_insn_prelive(const_rtx rtx) {
   // Parallel is handled by volatile_refs_p
 
   switch (code) {
-
-  }
-
-  const char *const fmt = GET_RTX_FORMAT (code);
-  for (size_t i = 0; i < GET_RTX_LENGTH(code); ++i) {
-if (fmt[i] == 'e' && is_rtx_insn_prelive(XEXP(rtx, i))) {
+case MEM:
+case ASM_INPUT:
+case ASM_OPERANDS:
   return true;
-} else if (fmt[i] == 'E') {
-  for (size_t j = 0; j < XVECLEN(rtx, i); ++j) {
-if (is_rtx_insn_prelive(XVECEXP(rtx, i, j)))
-  return true;
-  }
-}
+
+case PARALLEL:
+  for (int i = XVECLEN (body, 0) - 1; i >= 0; i--)
+ if (!deletable_insn_p_1 (XVECEXP (body, 0, i)))
+   return true;
+  return false;
+  break;
+
+default:
+  break;
   }
 
+  // const char *const fmt = GET_RTX_FORMAT (code);
+  // for (size_t i = 0; i < GET_RTX_LENGTH(code); ++i) {
+  //   if (fmt[i] == 'e' && is_rtx_insn_prelive(XEXP(rtx, i))) {
+  // return true;
+  //   } else if (fmt[i] == 'E') {
+  // for (size_t j = 0; j < XVECLEN(rtx, i); ++j) {
+  //   if (is_rtx_insn_prelive(XVECEXP(rtx, i, j)))
+  // return true;
+  // }
+  //   }
+  // }
+
   return false;
 }
 
@@ -1440,7 +1488,7 @@ bool is_prelive(insn_info *insn)
   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
+  return is_rtx_insn_prelive(rtl);
   
   // TODO : join if statements
   // We need to describe all possible prelive instructions, a list of all the 
instructions is inside `rtl.def`
@@ -1458,7 +1506,7 @@ bool is_prelive(insn_info *insn)
   std::cerr << "Prelive: " << GET_RTX_NAME(code) << '\n';
   // debug(insn);
   debug(rtl);
-  if (volatile_refs_p(rtl) || can_throw_internal(rtl) || BARRIER_P(rtl) || 
code == PREFETCH)

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce pass simple testcase

2025-03-09 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:a6de52696da5e080e9694b0a85f4f463801a4f52

commit a6de52696da5e080e9694b0a85f4f463801a4f52
Author: Ondřej Machota 
Date:   Sun Mar 9 23:02:03 2025 +0100

rtl-ssa: dce pass simple testcase

Diff:
---
 gcc/cse.cc |   2 +-
 gcc/dce.cc | 233 +
 gcc/passes.def |   3 +-
 3 files changed, 104 insertions(+), 134 deletions(-)

diff --git a/gcc/cse.cc b/gcc/cse.cc
index c53deecbe547..4dc1d3d57849 100644
--- a/gcc/cse.cc
+++ b/gcc/cse.cc
@@ -7622,7 +7622,7 @@ rest_of_handle_cse2 (void)
  bypassed safely.  */
   cse_condition_code_reg ();
 
-  delete_trivially_dead_insns (get_insns (), max_reg_num ());
+  // delete_trivially_dead_insns (get_insns (), max_reg_num ());
 
   if (tem == 2)
 {
diff --git a/gcc/dce.cc b/gcc/dce.cc
index fa3d7721a6d0..3e6e47f19208 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1322,12 +1322,12 @@ bool sets_global_register(rtx_insn* insn) {
   rtx dest = SET_DEST(set);
 
   // TODO : rewrite to simple return
-  std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
-  std::cerr << "register: " << REGNO(dest) << "\n";
-  debug(insn);
+  //std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
+  //std::cerr << "register: " << REGNO(dest) << "\n";
+  //debug(insn);
   // If I understand correctly, global_regs[i] is 1 iff reg i is used
   if (REG_P(dest) && HARD_REGISTER_NUM_P(REGNO(dest))) { // && 
global_regs[REGNO(dest)]
-std::cerr << "sets_global_register: true\n";
+//std::cerr << "sets_global_register: true\n";
 return true;
   }
 
@@ -1353,24 +1353,88 @@ bool is_control_flow(rtx_code code) {
   }
 }
 
-bool is_unary_mem_modification(rtx_code code) {
-  switch (code) {
-case PRE_DEC:
+bool side_effects_with_mem (const_rtx x)
+{
+  const RTX_CODE code = GET_CODE (x);
+  switch (code)
+{
+case LABEL_REF:
+case SYMBOL_REF:
+case CONST:
+CASE_CONST_ANY:
+case PC:
+case REG:
+case SCRATCH:
+case ADDR_VEC:
+case ADDR_DIFF_VEC:
+case VAR_LOCATION:
+  return false;
+
+case CLOBBER:
+  /* Reject CLOBBER with a non-VOID mode.  These are made by combine.cc
+when some combination can't be done.  If we see one, don't think
+that we can simplify the expression.  */
+  return (GET_MODE (x) != VOIDmode);
+
 case PRE_INC:
-case POST_DEC:
+case PRE_DEC:
 case POST_INC:
+case POST_DEC:
 case PRE_MODIFY:
 case POST_MODIFY:
+case CALL:
+case UNSPEC_VOLATILE:
+  return true;
+
+case MEM: // We might want tu return true iff volatile or mem is a 
destination
+case ASM_INPUT:
+case ASM_OPERANDS:
+   return true;
+
+case USE:
   return true;
 
 default:
-  return false;
+  break;
+}
+
+  /* Recursively scan the operands of this expression.  */
+
+  {
+const char *fmt = GET_RTX_FORMAT (code);
+int i;
+
+for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+  {
+   if (fmt[i] == 'e')
+ {
+   if (side_effects_with_mem (XEXP (x, i)))
+ return true;
+ }
+   else if (fmt[i] == 'E')
+ {
+   int j;
+   for (j = 0; j < XVECLEN (x, i); j++)
+ if (side_effects_with_mem (XVECEXP (x, i, j)))
+   return true;
+ }
+  }
   }
+  return false;
 }
 
 bool is_rtx_insn_prelive(rtx_insn *insn) {
   gcc_assert(insn != nullptr);
 
+  // Jumps, notes, barriers should not be deleted
+  // According to the docs, rtl ssa does not contain noteS and barrierS 
+  if (!NONJUMP_INSN_P (insn))
+  {
+std::cerr << "found jump instruction\n";
+debug(insn);
+return true;
+  }
+
   // TODO : handle calls correctly
   if (CALL_P (insn)
   /* We cannot delete pure or const sibling calls because it is
@@ -1384,15 +1448,6 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 return true;
 // return !find_call_stack_args (as_a  (insn), false, 
fast, arg_stores);
 
-  // Jumps, notes, barriers should not be deleted
-// According to the docs, rtl ssa does not contain noteS and barrierS 
-  if (!NONJUMP_INSN_P (insn))
-  {
-std::cerr << "found jump instruction\n";
-debug(insn);
-return true;
-  }
-
   // Only rtx_insn should be handled here
   auto code = GET_CODE(insn);
   gcc_assert(code == INSN);
@@ -1408,51 +1463,17 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate && 
find_reg_note (insn, REG_CFA_RESTORE, NULL))
 return true;
 
-  // if (is_control_flow(code))
-  //   return true;
-
   // Mark set of a global register
   if (sets_global_register(insn)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
 return true;
 
   rtx body = PATTERN(insn);
-  if (side_effects_p(body) || can_throw_internal(body))
-return true;
-
-  if (is_unary_mem_modification(code))
+  if (side_effects_with_mem(body) || can_throw_internal(body))
 return 

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce fix marking

2025-03-12 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:775add98a313f182c3f45e6a0931f2ed612dab24

commit 775add98a313f182c3f45e6a0931f2ed612dab24
Author: Ondřej Machota 
Date:   Tue Mar 11 11:03:56 2025 +0100

rtl-ssa: dce fix marking

Diff:
---
 gcc/dce.cc | 77 ++
 1 file changed, 67 insertions(+), 10 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 14d7e1fa9120..e612243c01be 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1582,6 +1582,57 @@ rtl_ssa_dce_mark()
 {
   std::unordered_set marked{};
   auto worklist = rtl_ssa_dce_prelive(marked);
+  auto_vec worklist_new{};
+  for (auto && item : worklist) {
+insn_info * insn = item;
+for (auto&& use : insn->uses()) {
+  set_info* set = use->def();
+  if (set) {
+worklist_new.safe_push(set);
+  }
+}
+  }
+
+  while (!worklist_new.is_empty()) {
+set_info* set = worklist_new.pop();
+insn_info* insn = set->insn();
+if (!insn) {
+  continue;
+}
+
+if (!(marked.count(insn) > 0))
+{
+  marked.emplace(insn);
+}
+
+// use_array uses = insn->uses();
+if (insn->is_phi()) {
+  phi_info* pi = as_a (set);
+  
+  for (auto && input : pi->inputs()) {
+use_info* use = input;
+set_info* parent_set = use->def();
+if (!parent_set) { // Clobber...
+  continue;
+}
+
+worklist_new.safe_push(parent_set);
+  }
+} else {
+  if (dump_file)
+fprintf(dump_file, "  Adding insn %d to worklist - mark\n", 
insn->uid());
+  
+  for (auto && use__ : insn->uses()) {
+use_info * use = use__;
+set_info* parent_set = use->def();
+if (!parent_set) {
+  continue;
+}
+
+worklist_new.safe_push(parent_set);
+  }
+}
+  }
 
   if (dump_file)
 fprintf(dump_file, "Finished inherently live, marking parents\n");
@@ -1620,17 +1671,23 @@ rtl_ssa_dce_mark()
   // debug(use);
   // std::cerr << '\n';
   
-  
-  insn_info *parent_insn = use->def()->insn();
-  if (parent_insn->is_phi()) { // this is weird...
-// debug(use->def());
-phi_info * pi = as_a (use->def());
-// std::cerr << "phi inputs: " << pi->num_inputs() << '\n';
-for (auto&& input: pi->inputs()) {
-  use_info* phi_use = input;
-  std::cerr << "Via phi insn: " << phi_use->def()->insn()->uid() << 
'\n';
-}
+  set_info* set = use->def();
+  if (!set) {
+continue;
+  }
+  insn_info *parent_insn = set->insn();
+  if (!parent_insn) {
+continue;
   }
+  // if (parent_insn->is_phi()) { // this is weird...
+  //   // debug(use->def());
+  //   phi_info * pi = as_a (use->def());
+  //   // std::cerr << "phi inputs: " << pi->num_inputs() << '\n';
+  //   for (auto&& input: pi->inputs()) {
+  // use_info* phi_use = input;
+  // std::cerr << "Via phi insn: " << phi_use->def()->insn()->uid() << 
'\n';
+  //   }
+  // }
   int parent_insn_uid = parent_insn->uid();
   // propage that some instruction in chain is live from bottom to top
   if (dump_file)


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: improve marking, but still not correct

2025-03-12 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:0950f89fdd8a433f2dcccf45dcb088d3be16130c

commit 0950f89fdd8a433f2dcccf45dcb088d3be16130c
Author: Ondřej Machota 
Date:   Wed Mar 12 13:12:43 2025 +0100

rtl-ssa-dce: improve marking, but still not correct

Diff:
---
 gcc/dce.cc | 211 +
 1 file changed, 113 insertions(+), 98 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index e612243c01be..959677663855 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1387,10 +1387,12 @@ bool side_effects_with_mem (const_rtx x)
   return true;
 
 case MEM: // We might want tu return true iff volatile or mem is a 
destination
+  // write or possible null read
 case ASM_INPUT:
 case ASM_OPERANDS:
return true;
 
+// This should rather by RTX_BODY in is_rtx_insn_prelive - like global 
clobber
 case USE:
   return true;
 
@@ -1468,6 +1470,9 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 return true;
 
   rtx body = PATTERN(insn);
+  if (GET_CODE(body) == CLOBBER) // 
~/Documents/gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
+return true;
+
   if (side_effects_with_mem(body) || can_throw_internal(body))
 return true;
 
@@ -1585,6 +1590,7 @@ rtl_ssa_dce_mark()
   auto_vec worklist_new{};
   for (auto && item : worklist) {
 insn_info * insn = item;
+std::cerr << "cp Current: " << insn->uid() << '\n';
 for (auto&& use : insn->uses()) {
   set_info* set = use->def();
   if (set) {
@@ -1600,118 +1606,119 @@ rtl_ssa_dce_mark()
   continue;
 }
 
-if (!(marked.count(insn) > 0))
-{
-  marked.emplace(insn);
-}
+/*
+ * TODO : a phi insn might be visited more times due to having more phi 
nodes
+ * Either we have to mark phi nodes or do not mark phi insn
+*/
+std::cerr << "Current: " << insn->uid() << '\n';
+// if (insn->uid() == -21) {
+  // std::cerr << "Insn -21 phi? " << insn->is_phi() << '\n';
+// }
 
-// use_array uses = insn->uses();
-if (insn->is_phi()) {
-  phi_info* pi = as_a (set);
-  
-  for (auto && input : pi->inputs()) {
-use_info* use = input;
-set_info* parent_set = use->def();
-if (!parent_set) { // Clobber...
-  continue;
-}
-
-worklist_new.safe_push(parent_set);
-  }
-} else {
-  if (dump_file)
-fprintf(dump_file, "  Adding insn %d to worklist - mark\n", 
insn->uid());
-  
-  for (auto && use__ : insn->uses()) {
-use_info * use = use__;
-set_info* parent_set = use->def();
-if (!parent_set) {
-  continue;
-}
-
-worklist_new.safe_push(parent_set);
-  }
+if ((marked.count(insn) > 0)) {
+  continue;
 }
-  }
 
-  if (dump_file)
-fprintf(dump_file, "Finished inherently live, marking parents\n");
-  while (!worklist.is_empty())
-  {
-insn_info *insn = worklist.pop();
+marked.emplace(insn);
+
 use_array uses = insn->uses();
 if (insn->is_phi()) {
-  std::cerr << "Phi : "<< insn->uid() << " - uses: " << insn->num_uses() 
<< ", defs:" << insn->num_defs() << '\n';
-  for (auto&& use : uses) {
-debug(use);
-std::cerr << '\n';
-  }
-} else if (insn->is_artificial()) {
-  std::cerr << "Artificial " << insn->uid() << " - uses: " << 
insn->num_uses() << ", defs:" << insn->num_defs() << '\n';
-  for (auto&& use : uses) {
-debug(use);
-std::cerr << '\n';
-  }
+  phi_info* pi = as_a (set);
+  uses = pi->inputs();
 }
 
 if (dump_file)
-  fprintf(dump_file, "Looking at: %d, uses: %d\n", insn->uid(), 
uses.size());
-
-//std::cerr << "Insn: " << insn->uid() << ", uses: " << uses.size() << 
'\n';
-  std::cerr << "Current: " << insn->uid() << '\n';
-for (size_t i = 0; i < uses.size(); i++)
-{
-  // debug(uses[i]);
-  use_info* use = uses[i];
-  // debug(use->def());
-  // if (use->def() != nullptr) {
-  //   std::cerr << use->def()->insn()->uid() << '\n';
-  // }
-  // std::cerr << '\n';
-  // debug(use);
-  // std::cerr << '\n';
-  
-  set_info* set = use->def();
-  if (!set) {
+  fprintf(dump_file, "  Adding insn %d to worklist - mark\n", insn->uid());
+
+for (auto && use__ : uses) {
+  use_info * use = use__;
+  set_info* parent_set = use->def();
+  if (!parent_set) {
 continue;
   }
-  insn_info *parent_insn = set->insn();
-  if (!parent_insn) {
-continue;
-  }
-  // if (parent_insn->is_phi()) { // this is weird...
-  //   // debug(use->def());
-  //   phi_info * pi = as_a (use->def());
-  //   // std::cerr << "phi inputs: " << pi->num_inputs() << '\n';
-  //   for (auto&& input: pi->inputs()) {
-  // use_info* phi_use = input;
-  // std::cerr << "Via phi insn: " << phi_use->def()->insn()->uid() << 
'\n';
-  //   }
-  // }
-  int parent_insn_uid = par

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce improve prelive conditions

2025-02-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:b948b7907c28284ac9e14f5316b15d5deec4382d

commit b948b7907c28284ac9e14f5316b15d5deec4382d
Author: Ondřej Machota 
Date:   Fri Feb 21 23:06:19 2025 +0100

rtl-ssa: dce improve prelive conditions

Diff:
---
 gcc/dce.cc | 38 +++---
 1 file changed, 31 insertions(+), 7 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 6b95f89c5b2c..7fb24d1d975b 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
 .  */
 
-#include 
 #define INCLUDE_ALGORITHM
 #define INCLUDE_FUNCTIONAL
 #define INCLUDE_ARRAY
@@ -1316,6 +1315,28 @@ bool sets_global_register(rtx_insn* insn) {
   return false;
 }
 
+bool is_control_flow(rtx_code code) {
+  // What about BARRIERs?
+  switch (code) {
+case JUMP_INSN:
+case JUMP_TABLE_DATA: // Be careful with Table jump addresses - ADDR_VEC, 
ADDR_DIFF_VEC, PREFETCH 
+case TRAP_IF:
+case IF_THEN_ELSE: // Also COMPARE?
+case COND_EXEC: // We might want to check the operation that is under this?
+case RETURN:
+case SIMPLE_RETURN:
+case EH_RETURN:
+  return true;
+
+default:
+  return false;
+  }
+}
+
+bool handle_rtl_previle(rtx_insn *insn) {
+  // TODO : handle everything except parallel
+}
+
 bool is_prelive(insn_info *insn)
 {
   if (insn->is_artificial()) // phis are never prelive
@@ -1341,7 +1362,7 @@ bool is_prelive(insn_info *insn)
   */
 
   // Now, we only have to handle rtx insns
-  assert(insn->is_real());
+  gcc_assert (insn->is_real());
   auto rtl = insn->rtl();
 
   if (!INSN_P(rtl)) // This might be useless
@@ -1350,20 +1371,23 @@ bool is_prelive(insn_info *insn)
   rtx pat = PATTERN(rtl); // if we use this instead of rtl, then rtl notes 
wont be checked
   
   // TODO : join if statements
+  // We need to describe all possible prelive instructions, a list of all the 
instructions is inside `rtl.def`
 
-  if (JUMP_P(rtl))
+  // Control flow
+  auto rtl_code = GET_CODE(rtl);
+  if (is_control_flow(rtl_code))
 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))
+  if (volatile_refs_p(rtl) || can_throw_internal(rtl) || BARRIER_P(rtl) || 
rtl_code == PREFETCH)
 return true;
 
+  // TODO : handle parallel, {pre,post}_{int,dec}, {pre,post}_modify
+
   return false;
 }
 
@@ -1521,8 +1545,8 @@ rtl_ssa_dce_sweep(std::unordered_set marked)
 changes[i] = &to_delete[i];
   }
 
-  // if (verify_insn_changes())
   crtl->ssa->change_insns(changes);
+  // if (verify_insn_changes())
 }
 
 static unsigned int


[gcc/omachota/heads/rtl-ssa-dce] rtl-ssa: dce some prelive conditions

2025-02-21 Thread Ondrej Machota via Gcc-cvs
The branch 'omachota/heads/rtl-ssa-dce' was updated to point to:

 7b02cedb2aa8... rtl-ssa: dce some prelive conditions

It previously pointed to:

 175c246015a7... rtl-ssa: dce add prelive conditions

Diff:

!!! WARNING: THE FOLLOWING COMMITS ARE NO LONGER ACCESSIBLE (LOST):
---

  175c246... rtl-ssa: dce add prelive conditions
  d0095cf... rtl-ssa: dce fix working with sbitmap
  cde5332... rtl-ssa: dce fix uid
  96c7ea3... rtl-ssa: dce fix mark compile and sweep sketch


Summary of changes (added commits):
---

  7b02ced... rtl-ssa: dce some prelive conditions


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce some prelive conditions

2025-02-21 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:7b02cedb2aa83d5d5cbca668661bf96e58376092

commit 7b02cedb2aa83d5d5cbca668661bf96e58376092
Author: Ondřej Machota 
Date:   Fri Feb 21 14:11:36 2025 +0100

rtl-ssa: dce some prelive conditions

Diff:
---
 gcc/dce.cc | 321 +
 1 file changed, 239 insertions(+), 82 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index f59bc6c6ffa2..6b95f89c5b2c 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -17,8 +17,10 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+#include 
 #define INCLUDE_ALGORITHM
 #define INCLUDE_FUNCTIONAL
+#define INCLUDE_ARRAY
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -30,7 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "rtl-ssa.h"
 #include "memmodel.h"
 #include "tm_p.h"
-#include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
+#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h.  */
 #include "cfgrtl.h"
 #include "cfgbuild.h"
 #include "cfgcleanup.h"
@@ -39,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "dbgcnt.h"
 #include "rtl-iter.h"
+#include 
 
 using namespace rtl_ssa;
 
@@ -1300,128 +1303,282 @@ public:
 } // 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;
 }
 
-static void rti_ssa_dce_() {
+bool is_prelive(insn_info *insn)
+{
+  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 ()
+rtl_ssa_dce_init()
 {
-calculate_dominance_info (CDI_DOMINATORS);
-crtl->ssa = new rtl_ssa::function_info (cfun);
+  calculate_dominance_info(CDI_DOMINATORS);
+  // here we create ssa form for function
+  crtl->ssa = new rtl_ssa::function_info(cfun);
 }
 
 static void
-rtl_ssa_dce_done ()
+rtl_ssa_dce_done()
 {
-free_dominance_info (CDI_DOMINATORS);
-if (crtl->ssa->perform_pending_updates ())
-  cleanup_cfg (0);
+  free_dominance_info(CDI_DOMINATORS);
+  if (crtl->ssa->perform_pending_updates())
+cleanup_cfg(0);
 
-delete crtl->ssa;
-crtl->ssa = nullptr;
+  delete crtl->ssa;
+  crtl->ssa = nullptr;
 
-if (dump_file)
-  fprintf (dump_file, "\nFinished running rtl_ssa_dce\n\n");
+  if (dump_file)
+fprintf(dump_file, "\nFinished running rtl_ssa_dce\n\n");
 }
 
-static unsigned int
-rtl_ssa_dce ()
+static void
+rtl_ssa_dce_mark_live(insn_info *info, vec &worklist, 
std::unordered_set marked)
 {
-rtl_ssa_dce_init ();
+  int info_uid = info->uid();
+  if (dump_file)
+  {
+fprintf(dump_file, "  Adding insn %d to worklist\n", info_uid);
+  }
 
-insn_info *next;
-sbitmap marked;
-auto_vec worklist;
-for (insn_info *insn = crtl->ssa->first_insn (); insn; insn = next)
+  marked.emplace(info);
+  worklist.safe_push(info);
+}
+
+static auto_vec
+rtl_ssa_dce_prelive(std::unordered_set marked)
+{
+  insn_info *next;
+  auto_vec worklist;
+  for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
+  {
+if (dump_file)
 {
-  next = insn->next_any_insn ();
-  auto *rtl = insn->rtl();
-  /*
-  I would like to mark visited instruction with something like plf (Pass 
local flags) as in gimple
-
-  This file contains some useful functions: e.g. mark

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa: dce another prelive conditions

2025-02-24 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:bd2f26a74f4c38b068974262957fb4306b0b15e6

commit bd2f26a74f4c38b068974262957fb4306b0b15e6
Author: Ondřej Machota 
Date:   Tue Feb 25 08:44:25 2025 +0100

rtl-ssa: dce another prelive conditions

Diff:
---
 gcc/dce.cc | 125 -
 1 file changed, 100 insertions(+), 25 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 7fb24d1d975b..a04c5702d8a3 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -17,6 +17,8 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+#include 
+#include 
 #define INCLUDE_ALGORITHM
 #define INCLUDE_FUNCTIONAL
 #define INCLUDE_ARRAY
@@ -1302,13 +1304,29 @@ public:
 } // namespace
 
 
+bool sets_global_register(const_rtx rtx) {
+  auto code = GET_CODE(rtx);
+  if (GET_RTX_CLASS(code) != RTX_INSN)
+return false;
+
+  return sets_global_register(static_cast(rtx));
+}
+
+// We should mark stack registers
 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)]) {
+
+  // TODO : rewrite to simple return
+  std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
+  std::cerr << "register: " << REGNO(dest) << "\n";
+  debug(insn);
+  // If I understand correctly, global_regs[i] is 1 iff reg i is used
+  if (REG_P(dest) && HARD_REGISTER_NUM_P(REGNO(dest))) { // && 
global_regs[REGNO(dest)]
+std::cerr << "sets_global_register: true\n";
 return true;
   }
 
@@ -1326,6 +1344,7 @@ bool is_control_flow(rtx_code code) {
 case RETURN:
 case SIMPLE_RETURN:
 case EH_RETURN:
+case LABEL_REF:
   return true;
 
 default:
@@ -1333,13 +1352,66 @@ bool is_control_flow(rtx_code code) {
   }
 }
 
-bool handle_rtl_previle(rtx_insn *insn) {
-  // TODO : handle everything except parallel
+bool is_unary_mem_modification(rtx_code code) {
+  switch (code) {
+case PRE_DEC:
+case PRE_INC:
+case POST_DEC:
+case POST_INC:
+case PRE_MODIFY:
+case POST_MODIFY:
+  return true;
+
+default:
+  return false;
+  }
+}
+
+bool is_rtx_insn_prelive(const_rtx rtx) {
+  if (rtx == nullptr) {
+return false;
+  }
+
+  auto code = GET_CODE(rtx);
+  if (is_control_flow(code))
+return true;
+
+  // Mark set of a global register
+  if (sets_global_register(rtx)) // check rtx_class with GET_RTX_CLASS if 
RTX_ISNS and convert if needed
+return true;
+
+  // Call is inside side_effects_p - how to mark parameter registers?
+  if (volatile_refs_p(rtx) || can_throw_internal(rtx) || BARRIER_P(rtx) || 
code == PREFETCH)
+return true;
+
+  if (is_unary_mem_modification(code))
+return true;
+
+  // TODO : parallel, {pre,post}_{int,dec}, {pre,post}_modify, 
may_trap_or_fault_p
+  // Parallel is handled by volatile_refs_p
+
+  switch (code) {
+
+  }
+
+  const char *const fmt = GET_RTX_FORMAT (code);
+  for (size_t i = 0; i < GET_RTX_LENGTH(code); ++i) {
+if (fmt[i] == 'e' && is_rtx_insn_prelive(XEXP(rtx, i))) {
+  return true;
+} else if (fmt[i] == 'E') {
+  for (size_t j = 0; j < XVECLEN(rtx, i); ++j) {
+if (is_rtx_insn_prelive(XVECEXP(rtx, i, j)))
+  return true;
+  }
+}
+  }
+
+  return false;
 }
 
 bool is_prelive(insn_info *insn)
 {
-  if (insn->is_artificial()) // phis are never prelive
+  if (insn->is_artificial()) // phis are never prelive, bb head + end are 
artificial
 return false;
 
   /*
@@ -1374,8 +1446,8 @@ bool is_prelive(insn_info *insn)
   // We need to describe all possible prelive instructions, a list of all the 
instructions is inside `rtl.def`
 
   // Control flow
-  auto rtl_code = GET_CODE(rtl);
-  if (is_control_flow(rtl_code))
+  auto code = GET_CODE(rtl);
+  if (is_control_flow(code))
 return true;
 
   // Mark set of a global register
@@ -1383,9 +1455,16 @@ bool is_prelive(insn_info *insn)
 return true;
 
   // Call is inside side_effects_p
-  if (volatile_refs_p(rtl) || can_throw_internal(rtl) || BARRIER_P(rtl) || 
rtl_code == PREFETCH)
+  std::cerr << "Prelive: " << GET_RTX_NAME(code) << '\n';
+  // debug(insn);
+  debug(rtl);
+  if (volatile_refs_p(rtl) || can_throw_internal(rtl) || BARRIER_P(rtl) || 
code == PREFETCH)
 return true;
 
+  if (code == PARALLEL) {
+
+  }
+
   // TODO : handle parallel, {pre,post}_{int,dec}, {pre,post}_modify
 
   return false;
@@ -1418,9 +1497,7 @@ rtl_ssa_dce_mark_live(insn_info *info, vec 
&worklist, std::unordere
 {
   int info_uid = info->uid();
   if (dump_file)
-  {
 fprintf(dump_file, "  Adding insn %d to worklist\n", info_uid);
-  }
 
   marked.emplace(info);
   worklist.safe_push(info);
@@ -1433,10 +1510,6 @@ rtl_ssa_dce_prelive(std::unordered_set 
marked)
   auto_vec worklist;
   for (insn_info *insn = crtl->ssa->first_insn(); insn; insn = next)
   {
-if (dump_fil

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: cleanup and comparsion with ud_dce

2025-03-30 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:b065e82ac0a5b02167043e7ef1bb7f512e81543f

commit b065e82ac0a5b02167043e7ef1bb7f512e81543f
Author: Ondřej Machota 
Date:   Sun Mar 30 22:53:17 2025 +0200

rtl-ssa-dce: cleanup and comparsion with ud_dce

Diff:
---
 gcc/dce.cc | 292 +
 gcc/passes.def |   3 +-
 2 files changed, 153 insertions(+), 142 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index bb7040ae653d..53934d19c0ac 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -578,6 +578,7 @@ reset_unmarked_insns_debug_uses (void)
 }
 
 /* Delete every instruction that hasn't been marked.  */
+static bool inside_ud = false;
 
 static void
 delete_unmarked_insns (void)
@@ -585,6 +586,7 @@ delete_unmarked_insns (void)
   basic_block bb;
   rtx_insn *insn, *next;
   bool must_clean = false;
+  bool any = false;
 
   FOR_EACH_BB_REVERSE_FN (bb, cfun)
 FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next)
@@ -653,9 +655,17 @@ delete_unmarked_insns (void)
}
  else
/* Now delete the insn.  */
+  if (inside_ud) {
+debug(insn);
+  }
+  any = true;
must_clean |= delete_insn_and_edges (insn);
}
 
+  if (any && inside_ud) {
+std::cerr << "\033[31m" << "ud was able to delete more insns..." << 
"\033[0m \n";
+  }
+
   /* Deleted a pure or const call.  */
   if (must_clean)
 {
@@ -809,6 +819,7 @@ fini_dce (bool fast)
 static unsigned int
 rest_of_handle_ud_dce (void)
 {
+  inside_ud = true;
   rtx_insn *insn;
 
   init_dce (false);
@@ -829,6 +840,7 @@ rest_of_handle_ud_dce (void)
  they are not bidirectional.  */
   df_remove_problem (df_chain);
   delete_unmarked_insns ();
+  inside_ud = false;
 
   fini_dce (false);
   return 0;
@@ -1306,14 +1318,15 @@ public:
 
 } // namespace
 
+// This struct could help to remove unordered_set for rtl ssa dce
 struct offset_bitmap {
   private:
 const int m_offset;
 sbitmap m_bitmap;
   
   public:
-offset_bitmap(size_t size, int offset) : m_bitmap{sbitmap_alloc(size)} {}
-offset_bitmap(int min_index, int max_index) : offset_bitmap(max_index - 
min_index, 0) {}
+offset_bitmap(size_t size, int offset) : m_offset{offset}, 
m_bitmap{sbitmap_alloc(size)} {}
+offset_bitmap(int min_index, int max_index) : 
offset_bitmap(size_t(max_index - min_index), min_index) {}
 
 void clear_bit(int index) {
   bitmap_clear_bit(m_bitmap, index + m_offset);
@@ -1332,26 +1345,6 @@ struct offset_bitmap {
 }
 };
 
-bool sets_global_register(rtx_insn* insn) {
-  rtx set = single_set(insn);
-  if (!set)
-return false;
-
-  rtx dest = SET_DEST(set);
-
-  // TODO : rewrite to simple return
-  std::cerr << "first pseudo: " << FIRST_PSEUDO_REGISTER << '\n';
-  //std::cerr << "register: " << REGNO(dest) << "\n";
-  //debug(insn);
-  // If I understand correctly, global_regs[i] is 1 iff reg i is used
-  if (REG_P(dest) && HARD_REGISTER_NUM_P(REGNO(dest))) { // && 
global_regs[REGNO(dest)]
-std::cerr << "sets_global_register: true\n";
-return true;
-  }
-
-  return false;
-}
-
 bool side_effects_with_mem (const_rtx x)
 {
   const RTX_CODE code = GET_CODE (x);
@@ -1460,10 +1453,7 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   /* Don't delete insns that may throw if we cannot do so.  */
   if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) && !insn_nothrow_p 
(insn))
 return true;
-
-  /* TODO : What about call argumets? Accoring to the docs, for function 
prologue the RTX_FRAME_RELATED_P
- should return true.
-  */  
+ 
   /* Callee-save restores are needed.  */
   if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate && 
find_reg_note (insn, REG_CFA_RESTORE, NULL))
 return true;
@@ -1496,9 +1486,7 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   // e. g. this one: testsuite/gcc.c-torture/execute/20020418-1.c
   // TODO : debug the testcase
   // It seems that the issue was due to trap_if rtl insn and fixed with 
may_trap_or_fault_p
-  // What about can_throw_internal?
-  // || can_throw_internal(body) - testy na ntb prochazi
-  if (side_effects_with_mem(body)) // || may_trap_or_fault_p(body)) // 
replaced by TRAP_IF
+  if (side_effects_with_mem(body)) // may_trap_or_fault_p(body) replaced by 
TRAP_IF
 return true;
 
   return false;
@@ -1532,8 +1520,7 @@ bool is_prelive(insn_info *insn)
   gcc_assert (insn->is_real());
   auto rtl = insn->rtl();
 
-  for (auto&& __def : insn->defs()) {
-def_info * def = __def;
+  for (def_info * def : insn->defs()) {
 // The purpose of this pass is not to eliminate stores to memory...
 if (def->is_mem()) { // TODO : clobbered memory?
   return true;
@@ -1541,18 +1528,52 @@ bool is_prelive(insn_info *insn)
 
 gcc_assert(def->is_reg());
 // this ignores clobbers, which is probably fine
-if (def->kind() == access_kind::SET 
-&& (HARD_REGISTER_NUM_P(def->regno())
-|| ( pic_offset_table_rtx != nullptr 
-  && def->regno() == REGNO (pic_offset_table_

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: format code

2025-03-31 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:7cbb0ce1fbec2adad90bd7c14342243ea9505ff9

commit 7cbb0ce1fbec2adad90bd7c14342243ea9505ff9
Author: Ondřej Machota 
Date:   Mon Mar 31 11:19:18 2025 +0200

rtl-ssa-dce: format code

Diff:
---
 gcc/dce.cc | 306 +++--
 1 file changed, 94 insertions(+), 212 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index a90a8d9ccf53..d16cec35eb16 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1325,8 +1325,10 @@ struct offset_bitmap {
 sbitmap m_bitmap;
   
   public:
-offset_bitmap(size_t size, int offset) : m_offset{offset}, 
m_bitmap{sbitmap_alloc(size)} {}
-offset_bitmap(int min_index, int max_index) : 
offset_bitmap(size_t(max_index - min_index), min_index) {}
+offset_bitmap(size_t size, int offset) : m_offset{offset},
+  m_bitmap{sbitmap_alloc(size)} {}
+offset_bitmap(int min_index, int max_index) : 
+  offset_bitmap(size_t(max_index - min_index), min_index) {}
 
 void clear_bit(int index) {
   bitmap_clear_bit(m_bitmap, index + m_offset);
@@ -1345,75 +1347,7 @@ struct offset_bitmap {
 }
 };
 
-bool side_effects_with_mem (const_rtx x)
-{
-  const RTX_CODE code = GET_CODE (x);
-  switch (code)
-{
-case LABEL_REF:
-case SYMBOL_REF:
-case CONST:
-CASE_CONST_ANY:
-case PC:
-case REG:
-case SCRATCH:
-case ADDR_VEC:
-case ADDR_DIFF_VEC:
-case VAR_LOCATION:
-  return false;
-
-case CLOBBER:
-  /* Reject CLOBBER with a non-VOID mode.  These are made by combine.cc
-when some combination can't be done.  If we see one, don't think
-that we can simplify the expression.  */
-  return (GET_MODE (x) != VOIDmode);
-
-case PRE_INC:
-case PRE_DEC:
-case POST_INC:
-case POST_DEC:
-case PRE_MODIFY:
-case POST_MODIFY:
-case CALL:
-case UNSPEC_VOLATILE:
-  return true;
-
-case MEM: // We might want tu return true iff volatile or mem is a 
destination
-  // write or possible null read
-case ASM_INPUT:
-case ASM_OPERANDS:
-   return true;
-
-default:
-  break;
-}
-
-  /* Recursively scan the operands of this expression.  */
-
-  {
-const char *fmt = GET_RTX_FORMAT (code);
-int i;
-
-for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-  {
-   if (fmt[i] == 'e')
- {
-   if (side_effects_with_mem (XEXP (x, i)))
- return true;
- }
-   else if (fmt[i] == 'E')
- {
-   int j;
-   for (j = 0; j < XVECLEN (x, i); j++)
- if (side_effects_with_mem (XVECEXP (x, i, j)))
-   return true;
- }
-  }
-  }
-  return false;
-}
-
-bool is_ssa_prelive(const_rtx insn) {
+bool is_rtx_prelive(const_rtx insn) {
   switch (GET_CODE(insn)) {
 case PREFETCH:
 case UNSPEC:
@@ -1429,15 +1363,12 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
   gcc_assert(insn != nullptr);
 
   if (!NONJUMP_INSN_P (insn))
-  {
-// This handles jumps, debug_insns, call_insn, ...
+/* This handles jumps, debug_insns, call_insn, ... */
 return true;
-  }
 
-  // TODO : handle calls correctly
   if (CALL_P (insn)
   /* We cannot delete pure or const sibling calls because it is
-hard to see the result.  */
+  hard to see the result.  */
   && (!SIBLING_CALL_P (insn))
   /* We can delete dead const or pure calls as long as they do not
  infinite loop.  */
@@ -1447,111 +1378,74 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 return true;
 // return !find_call_stack_args (as_a  (insn), false, 
fast, arg_stores);
 
-  // Only rtx_insn should be handled here
+  /* Only rtx_insn should be handled here */
   gcc_assert(GET_CODE(insn) == INSN);
 
   /* Don't delete insns that may throw if we cannot do so.  */
-  if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) && !insn_nothrow_p 
(insn))
+  if (!(cfun->can_delete_dead_exceptions && can_alter_cfg)
+  && !insn_nothrow_p (insn))
 return true;
  
   /* Callee-save restores are needed.  */
-  if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate && 
find_reg_note (insn, REG_CFA_RESTORE, NULL))
+  if (RTX_FRAME_RELATED_P (insn) && crtl->shrink_wrapped_separate 
+  && find_reg_note (insn, REG_CFA_RESTORE, NULL))
 return true;
 
-  // TODO : asm_noperands???
-
   rtx body = PATTERN(insn);
   switch (GET_CODE(body)) {
 case CLOBBER: // gcc/gcc/testsuite/gcc.c-torture/compile/2605-1.c
 case USE:
 case VAR_LOCATION:
-case PREFETCH: // This and following case might be removed since they are 
part of deletable_insn_p_1
-case TRAP_IF:
+/* Following cases might be removed since they are part of is_rtx_prelive 
*/
+case PREFETCH:
+case TRAP_IF: /* testsuite/gcc.c-torture/execute/20020418-1.c */
 case UNSPEC:
   return true;
 
 case PARALLEL:
   for (int i = XVECLEN (body, 0) - 1; i >= 0; i--)
-if (is_ssa_prelive (XVECEXP (body, 

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: fix calls that should not be prelive

2025-03-31 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:a5ce39df8ae350e2239f7b3bd5aded8a94f5fb54

commit a5ce39df8ae350e2239f7b3bd5aded8a94f5fb54
Author: Ondřej Machota 
Date:   Mon Mar 31 19:27:28 2025 +0200

rtl-ssa-dce: fix calls that should not be prelive

Diff:
---
 gcc/dce.cc | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index d16cec35eb16..b4ea199c6d76 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1362,21 +1362,21 @@ bool is_rtx_prelive(const_rtx insn) {
 bool is_rtx_insn_prelive(rtx_insn *insn) {
   gcc_assert(insn != nullptr);
 
-  if (!NONJUMP_INSN_P (insn))
-/* This handles jumps, debug_insns, call_insn, ... */
-return true;
-
   if (CALL_P (insn)
-  /* We cannot delete pure or const sibling calls because it is
-  hard to see the result.  */
-  && (!SIBLING_CALL_P (insn))
-  /* We can delete dead const or pure calls as long as they do not
- infinite loop.  */
-  && (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P 
(insn))
-  /* Don't delete calls that may throw if we cannot do so.  */
-  && can_delete_call (insn))
+/* We cannot delete pure or const sibling calls because it is
+  hard to see the result.  */
+&& (!SIBLING_CALL_P (insn))
+/* We can delete dead const or pure calls as long as they do not
+  infinite loop.  */
+&& (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P 
(insn))
+/* Don't delete calls that may throw if we cannot do so.  */
+&& can_delete_call (insn))
+  return false;
+  // return !find_call_stack_args (as_a  (insn), false, fast, 
arg_stores);
+
+  if (!NONJUMP_INSN_P (insn))
+/* This handles jumps, notes, call_insns, debug_insns, ... */
 return true;
-// return !find_call_stack_args (as_a  (insn), false, 
fast, arg_stores);
 
   /* Only rtx_insn should be handled here */
   gcc_assert(GET_CODE(insn) == INSN);
@@ -1571,7 +1571,9 @@ rtl_ssa_dce_sweep(std::unordered_set marked)
  of changes with appropriate size */
   auto_vec to_delete;
   for (insn_info * insn : crtl->ssa->all_insns()) {
-/* artificial and marked insns cannot be deleted */
+/* Artificial and marked insns cannot be deleted.
+   There is a slight problem with phis, because we might want to delete
+   some phi nodes from phi insn. */
 if (insn->is_artificial() || marked.count(insn) > 0)
   continue;


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rlt-ssa: dce init and done functions

2025-03-24 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:71dd3ab9a9ac7e0d196f016d4f44a16bf01a6050

commit 71dd3ab9a9ac7e0d196f016d4f44a16bf01a6050
Author: Ondřej Machota 
Date:   Sun May 5 21:19:18 2024 +0200

rlt-ssa: dce init and done functions

Diff:
---
 gcc/dce.cc | 42 +++---
 1 file changed, 35 insertions(+), 7 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 514b9fc809cf..640040dbf3d3 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -17,6 +17,8 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+#define INCLUDE_ALGORITHM
+#define INCLUDE_FUNCTIONAL
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -25,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "predict.h"
 #include "df.h"
+#include "rtl-ssa.h"
 #include "memmodel.h"
 #include "tm_p.h"
 #include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
@@ -1295,7 +1298,37 @@ public:
 
 }; // class pass_fast_rtl_dce
 
-} // anon namespace
+} // namespace
+
+static void
+rtl_ssa_dce_init ()
+{
+calculate_dominance_info (CDI_DOMINATORS);
+crtl->ssa = new rtl_ssa::function_info (cfun);
+}
+
+static void
+rtl_ssa_dce_done ()
+{
+free_dominance_info (CDI_DOMINATORS);
+if (crtl->ssa->perform_pending_updates ())
+  cleanup_cfg (0);
+
+delete crtl->ssa;
+crtl->ssa = nullptr;
+
+if (dump_file)
+  fprintf (dump_file, "\nFinished running rtl_ssa_dce\n\n");
+}
+
+static unsigned int
+rtl_ssa_dce ()
+{
+rtl_ssa_dce_init ();
+
+rtl_ssa_dce_done ();
+return 0;
+}
 
 rtl_opt_pass *
 make_pass_fast_rtl_dce (gcc::context *ctxt)
@@ -1327,12 +1360,7 @@ public:
   /* opt_pass methods: */
   bool gate (function *) final override { return flag_dce; }
 
-  unsigned int execute (function *) final override
-  {
-if (dump_file)
-  fprintf (dump_file, "pass_rtl_ssa_dce called\n");
-return 0;
-  }
+  unsigned int execute (function *) final override { return rtl_ssa_dce (); }
 
 }; // class pass_fast_rtl_dce


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: pass execute tests

2025-04-02 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:753dc2e51076204b3da0728a4525f3a0e954309f

commit 753dc2e51076204b3da0728a4525f3a0e954309f
Author: Ondřej Machota 
Date:   Wed Apr 2 20:41:24 2025 +0200

rtl-ssa-dce: pass execute tests

Diff:
---
 gcc/dce.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index b4ea199c6d76..6221e3b39910 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1416,7 +1416,7 @@ bool is_rtx_insn_prelive(rtx_insn *insn) {
 bool is_prelive(insn_info *insn)
 {
   /* Phi insns are never prelive, bb head + end also are artificial */
-  if (insn->is_artificial())
+  if (insn->is_artificial() || insn->is_debug_insn())
 return false;
 
   gcc_assert (insn->is_real());
@@ -1574,7 +1574,7 @@ rtl_ssa_dce_sweep(std::unordered_set marked)
 /* Artificial and marked insns cannot be deleted.
There is a slight problem with phis, because we might want to delete
some phi nodes from phi insn. */
-if (insn->is_artificial() || marked.count(insn) > 0)
+if (insn->is_artificial() || insn->is_debug_insn() || marked.count(insn) > 
0)
   continue;
 
 auto change = insn_change::delete_insn(insn);


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: sketch debugize_insns

2025-05-09 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:cd276ae9d29e1d0d0c2d25292d5c7a8e7272f707

commit cd276ae9d29e1d0d0c2d25292d5c7a8e7272f707
Author: Ondřej Machota 
Date:   Fri May 9 13:32:14 2025 +0200

rtl-ssa-dce: sketch debugize_insns

Diff:
---
 gcc/dce.cc | 20 +---
 gcc/rtl-ssa/changes.cc |  3 +++
 gcc/timevar.def|  1 +
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index e077485c93c3..fdf5a35d6765 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1379,7 +1379,7 @@ private:
   void sweep ();
 
   void debuggize_insn (insn_info *);
-  void debbugize_insns (const std::unordered_set &);
+  void debugize_insns (const std::unordered_set &);
 
   offset_bitmap m_marked;
   sbitmap mm_marked_phis;
@@ -1877,7 +1877,7 @@ rtl_ssa_dce::debuggize_insn (insn_info *insn)
 }
 
 void
-rtl_ssa_dce::debbugize_insns (const std::unordered_set 
&depends_on_dead_phi)
+rtl_ssa_dce::debugize_insns (const std::unordered_set 
&depends_on_dead_phi)
 {
   for (insn_info *insn : crtl->ssa->reverse_all_insns ()) {
 if (insn->is_artificial () || 
@@ -1898,7 +1898,7 @@ rtl_ssa_dce::debbugize_insns (const 
std::unordered_set &depends_on_
 // def_info* s = nullptr;
 // s->kind() == access_kind::SET
 rtx set;
-// debbugize_insns should be called only if MAY_HAVE_DEBUG_BIND_INSNS
+// 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()
@@ -1929,6 +1929,20 @@ rtl_ssa_dce::debbugize_insns (const 
std::unordered_set &depends_on_
  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
+
+  def_info *d = *defs.begin ();
+  if (d->kind() == access_kind::SET) {
+set_info *s = static_cast(d);
+for (use_info *u : s->all_uses()) {
+  // TODO: transform dependent insns
+}
+  }
+
  rtx_insn *bind = emit_debug_insn_before (bind_var_loc, rtl);
 
  // if (replacements == NULL)
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index eb579ad3ad7e..b9861d24d380 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -1281,6 +1281,9 @@ function_info::create_insn (obstack_watermark &watermark,
 case INSN:
   rti = make_insn_raw (pat);
   break;
+   case DEBUG_INSN:
+ rti = make_debug_insn_raw(pat);
+ break;
 default:
   gcc_unreachable ();
 }
diff --git a/gcc/timevar.def b/gcc/timevar.def
index c1029d9dcf36..608451277d34 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -243,6 +243,7 @@ DEFTIMEVAR (TV_JUMP  , "jump")
 DEFTIMEVAR (TV_FWPROP, "forward prop")
 DEFTIMEVAR (TV_CSE   , "CSE")
 DEFTIMEVAR (TV_DCE   , "dead code elimination")
+DEFTIMEVAR (TV_RTL_SSA_DCE   , "rtl ssa dead code elimination")
 DEFTIMEVAR (TV_DSE1  , "dead store elim1")
 DEFTIMEVAR (TV_DSE2  , "dead store elim2")
 DEFTIMEVAR (TV_LOOP  , "loop analysis")


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: create debug instruction

2025-05-12 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:2e2274102964364a1b5fcd0a70d92c5f6f3c5e08

commit 2e2274102964364a1b5fcd0a70d92c5f6f3c5e08
Author: Ondřej Machota 
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
 .  */
 
-#include "bitmap.h"
 #include "sbitmap.h"
 #include 
 #include 
@@ -1381,7 +1380,10 @@ private:
   void sweep ();
 
   void debuggize_insn (insn_info *);
-  void debugize_insns (const std::unordered_set &);
+
+  void unmark_debugizable(insn_info &, sbitmap &);
+  sbitmap find_debugizable(const std::unordered_set &);
+  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 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 &depends_on_dead_phi) 
+sbitmap
+rtl_ssa_dce::find_debugizable(const std::unordered_set 
&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 
&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 
&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 
&depends_on_dead_phi)
 set_info *set = static_cast (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 
&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->

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: use offset_bitmap

2025-05-09 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:4ca3c04a0181c37eaef23f2d50300151b428aa6f

commit 4ca3c04a0181c37eaef23f2d50300151b428aa6f
Author: Ondřej Machota 
Date:   Fri May 9 10:54:19 2025 +0200

rtl-ssa-dce: use offset_bitmap

Diff:
---
 gcc/dce.cc | 207 +
 1 file changed, 168 insertions(+), 39 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 67c9ad577e67..e077485c93c3 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1318,13 +1318,55 @@ public:
 
 } // namespace
 
+// TODO: naalokovat prazdnou a pak resize
+// -flto_partition=none
+// -ftime_report a v build adresari zkusit insn*.cc (emit, match, recog)
+struct offset_bitmap
+{
+private:
+  int m_offset;
+  sbitmap m_bitmap;
+
+public:
+  offset_bitmap ()
+: m_offset{0}, m_bitmap{sbitmap_alloc(0)}
+  {}
+
+  offset_bitmap (size_t size, int offset)
+: m_offset{offset}, m_bitmap{sbitmap_alloc (size)}
+  {}
+
+  offset_bitmap (int min_index, int max_index)
+: offset_bitmap (size_t (max_index - min_index + 1), -min_index)
+  {}
+
+  void resize(size_t size, int offset)
+  {
+sbitmap_resize(m_bitmap, size, 0); 
+m_offset = offset; 
+  }
+
+  void resize(int min_index, int max_index)
+  {
+resize(size_t (max_index - min_index + 1), -min_index);
+  }
+
+  void clear_bit (int index) { bitmap_clear_bit (m_bitmap, index + m_offset); }
+
+  void set_bit (int index) { bitmap_set_bit (m_bitmap, index + m_offset); }
+
+  bool get_bit (int index) { return bitmap_bit_p (m_bitmap, index + m_offset); 
}
+
+  ~offset_bitmap () { sbitmap_free (m_bitmap); }
+};
+
 class rtl_ssa_dce
 {
 public:
   unsigned int execute (function *);
 
 private:
-  bool is_rtx_body_prelive (const_rtx);
+  bool is_rtx_pattern_prelive (const_rtx);
   bool can_delete_call (const_rtx);
   bool is_rtx_prelive (const_rtx);
   bool is_prelive (insn_info *);
@@ -1336,14 +1378,15 @@ private:
   void reset_dead_debug ();
   void sweep ();
 
-  int offset;
-  
-  sbitmap mm_marked;
+  void debuggize_insn (insn_info *);
+  void debbugize_insns (const std::unordered_set &);
+
+  offset_bitmap m_marked;
   sbitmap mm_marked_phis;
 };
 
 bool
-rtl_ssa_dce::is_rtx_body_prelive (const_rtx insn)
+rtl_ssa_dce::is_rtx_pattern_prelive (const_rtx insn)
 {
   switch (GET_CODE (insn))
 {
@@ -1357,9 +1400,28 @@ rtl_ssa_dce::is_rtx_body_prelive (const_rtx insn)
 }
 }
 
+// odebrat auto
+
 bool
 rtl_ssa_dce::can_delete_call (const_rtx insn)
 {
+  gcc_checking_assert (CALL_P (insn));
+
+  // We cannot delete pure or const sibling calls because it is
+  // hard to see the result.
+  // if (!SIBLING_CALL_P (insn))
+  // // We can delete dead const or pure calls as long as they do not
+  // // infinite loop.
+  // && (RTL_CONST_OR_PURE_CALL_P (insn)
+   //   && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)
+
+  //   && cfun->can_delete_dead_exceptions
+  // )
+  //   return true;
+  // Don't delete calls that may throw if we cannot do so.
+
+  // pridat assert na const nebo pure
+  //  pouzivat gcc_checking_assert();
   if (cfun->can_delete_dead_exceptions)
 return true;
   // if (!insn_nothrow_p (insn))
@@ -1408,8 +1470,7 @@ rtl_ssa_dce::is_rtx_prelive (const_rtx insn)
   gcc_assert (GET_CODE (insn) == INSN);
 
   // Don't delete insns that may throw if we cannot do so.
-  if (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn)
-  && can_alter_cfg)
+  if (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn))
 return true;
 
   // Callee-save restores are needed.
@@ -1417,8 +1478,8 @@ rtl_ssa_dce::is_rtx_prelive (const_rtx insn)
   && find_reg_note (insn, REG_CFA_RESTORE, NULL))
 return true;
 
-  rtx body = PATTERN (insn);
-  switch (GET_CODE (body))
+  rtx pat = PATTERN (insn);
+  switch (GET_CODE (pat))
 {
 case CLOBBER:
 case USE:
@@ -1426,13 +1487,13 @@ rtl_ssa_dce::is_rtx_prelive (const_rtx insn)
   return true;
 
 case PARALLEL:
-  for (int i = XVECLEN (body, 0) - 1; i >= 0; i--)
-   if (is_rtx_body_prelive (XVECEXP (body, 0, i)))
+  for (int i = XVECLEN (pat, 0) - 1; i >= 0; i--)
+   if (is_rtx_pattern_prelive (XVECEXP (pat, 0, i)))
  return true;
   return false;
 
 default:
-  return is_rtx_body_prelive (body);
+  return is_rtx_pattern_prelive (pat);
 }
 }
 
@@ -1472,6 +1533,7 @@ rtl_ssa_dce::is_prelive (insn_info *insn)
   if (HARD_REGISTER_NUM_P (def->regno ()) && global_regs[def->regno ()])
return true;
 
+  // what about reload? check cse.cc
   unsigned int picreg = PIC_OFFSET_TABLE_REGNUM;
   if (picreg != INVALID_REGNUM && fixed_regs[picreg]
  && def->regno () == picreg)
@@ -1487,7 +1549,7 @@ rtl_ssa_dce::mark_prelive_insn (insn_info *insn, 
auto_vec &worklist)
   if (dump_file)
 fprintf (dump_file, "Insn %d marked as prelive\n", insn->uid ());
 
-  bitmap_set_bit (mm_marked, insn->uid () + offset);
+  m_marked.set_bit(insn->uid ());
   // debug instruction are not added to worklist not to

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: debugize insns

2025-05-11 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:92e2b2fd496403a8d82b20b1fcefb265d1bf9e68

commit 92e2b2fd496403a8d82b20b1fcefb265d1bf9e68
Author: Ondřej Machota 
Date:   Sun May 11 19:08:12 2025 +0200

rtl-ssa-dce: debugize insns

Diff:
---
 gcc/dce.cc | 143 +
 1 file changed, 143 insertions(+)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index f12269f5dc97..5b8648be5859 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -17,6 +17,8 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+#include "bitmap.h"
+#include "sbitmap.h"
 #include 
 #include 
 #define INCLUDE_ALGORITHM
@@ -1896,6 +1898,147 @@ replace_dead_reg(rtx x, const_rtx old_rtx 
ATTRIBUTE_UNUSED, void *data)
  return NULL_RTX;
 }
 
+// visit every marked instruction in INSN dependency tree and unmark it
+static void
+unmark_debugizable(const insn_info& insn, auto_sbitmap &debugizable) 
+{
+  auto_vec worklist;
+  bitmap_set_bit (debugizable, insn.uid ());
+  worklist.safe_push (&insn);
+
+  while (!worklist.empty ()) {
+insn_info *current = worklist.pop ();
+int current_uid = current->uid ();
+
+// skip instruction that are not marked
+if (!bitmap_bit_p(debugizable, current_uid))
+  continue;
+
+bitmap_clear_bit(debugizable, current_uid);
+// add all marked dependencies to the worklist
+for (def_info *def : current.defs())
+{
+  if (def->kind() != access_kind::SET)
+continue;
+  
+  set_info *set = static_cast(def);
+  for (use_info *use : set->all_uses()) 
+  {
+insn_info *use_insn = use->insn();
+if (bitmap_bit_p(debugizable, use_insn->uid()))
+  worklist.safe_push (use_insn);
+  }
+}
+  }
+}
+
+static auto_sbitmap
+find_debugizable(const std::unordered_set &depends_on_dead_phi) 
+{
+  // only real instructions
+  auto_sbitmap debugizable(get_max_uid () + 1);
+  bitmap_clear(debugizable);
+
+  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;
+}
+
+// this insn might have some debugizable dependencies and if we find that
+// current insn is not debugizable, we have to reset those dependencies
+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)
+  {
+unmark_debugizable(*insn, debugizable);
+continue; // TODO: call unmark_debugizable
+  }
+
+// some of the checks might be duplicate:
+if (insn->num_defs () != 1)
+{
+  if (insn->num_defs() > 1)
+unmark_debugizable(*insn, debugizable);
+  continue; // TODO: call unmark_debugizable if num_defs>1
+}
+
+def_info *def = *defs.begin ();
+if (def->kind () != access_kind::SET)
+  continue;
+
+set_info *set = static_cast (def);
+// this is a problem a bit
+// TODO: check instruction dependencies and their debugizability
+if (!set->has_nondebug_insn_uses ())
+  continue;
+
+bitmap_set_bit (debugizable, insn->uid ());
+  }
+
+  return debugizable;
+}
+
+static void 
+bruh(const auto_sbitmap& debugizable)
+{
+  for (insn_info *insn : crtl->ssa->reverse_all_insns ())
+  {
+if (insn->is_artificial () || !bitmap_bit_p(debugizable, insn->uid ()))
+  continue;
+
+rtx_insn *rtl = insn->rtl ();
+def_array defs = insn->defs ();
+rtx rtx_set = single_set (rtl);
+def_info *def = *defs.begin ();
+gcc_checking_assert (def->kind () != access_kind::SET);
+
+set_info *set = static_cast (def);
+
+// turn instruction into debug
+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);
+
+register_replacement replacement;
+for (use_info *u : set->all_uses ()) {
+  

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: debugize_insns

2025-05-11 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:5a59807bef7e70e8216ce41c212b8ddb2d8caf22

commit 5a59807bef7e70e8216ce41c212b8ddb2d8caf22
Author: Ondřej Machota 
Date:   Sat May 10 15:38:28 2025 +0200

rtl-ssa-dce: debugize_insns

Diff:
---
 gcc/dce.cc | 82 --
 gcc/rtl-ssa/changes.cc |  7 +++--
 2 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index fdf5a35d6765..f12269f5dc97 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1876,6 +1876,26 @@ rtl_ssa_dce::debuggize_insn (insn_info *insn)
   
 }
 
+struct register_replacement {
+  unsigned int regno;
+  rtx expr;
+};
+
+static rtx
+replace_dead_reg(rtx x, const_rtx old_rtx ATTRIBUTE_UNUSED, void *data)
+{
+  auto replacement = static_cast(data);
+  
+ if (REG_P (x) && REGNO (x) >= FIRST_VIRTUAL_REGISTER && replacement->regno == 
REGNO (x))
+ {
+  if (GET_MODE (x) == GET_MODE (replacement->expr))
+ return replacement->expr;
+  return lowpart_subreg (GET_MODE (x), replacement->expr, GET_MODE 
(replacement->expr));
+ }
+
+ return NULL_RTX;
+}
+
 void
 rtl_ssa_dce::debugize_insns (const std::unordered_set 
&depends_on_dead_phi)
 {
@@ -1895,8 +1915,61 @@ rtl_ssa_dce::debugize_insns (const 
std::unordered_set &depends_on_d
 
 rtx_insn *rtl = insn->rtl ();
 def_array defs = insn->defs ();
-// def_info* s = nullptr;
-// s->kind() == access_kind::SET
+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 (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);
+
+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);
+}
+
+// note:
+// 1. Walk over all insns from last to first. If an insntruction can be
+//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
@@ -1933,7 +2006,7 @@ rtl_ssa_dce::debugize_insns (const 
std::unordered_set &depends_on_d
   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
+  // TODO: chains and defs
 
   def_info *d = *defs.begin ();
   if (d->kind() == access_kind::SET) {
@@ -1950,6 +2023,9 @@ rtl_ssa_dce::debugize_insns (const 
std::unordered_set &depends_on_d
  // replacements[REGNO (SET_DEST (set))] = dval;
 }   
   }
+
+  // TODO: check that all of the debug insn uses are live,
+  // othervise reset the instruction
 }
 
 static void
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index b9861d24d380..4657aec47cd8 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -256,7 +256,7 @@ rtl_ssa::changes_are_worthwhile (array_slice 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)
+function_info::process_uses_of_deleted_def (set_info *set, auto_sbitmap& 
visited_phis)
 {
   if (!set->has_any_uses ())
 return;
@@ -860,7 +860,10 @@ function_info::change_insns (array_slice 
changes)
{
  auto *set = dyn_cast (def);
  if (set && set->has_any_uses ())
-   process_uses_of_deleted_def (set);
+   {
+   auto_sbitmap phis(m_next_phi_uid);
+   proces

[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: explain debugizing

2025-05-13 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:62514a92baecb702abddf5ab7fcfb8520344e835

commit 62514a92baecb702abddf5ab7fcfb8520344e835
Author: Ondřej Machota 
Date:   Tue May 13 22:14:54 2025 +0200

rtl-ssa-dce: explain debugizing

Diff:
---
 gcc/dce.cc | 24 +---
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 305bb0e63db6..520202f0462e 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1379,7 +1379,7 @@ private:
   void reset_dead_debug ();
   void sweep ();
 
-  void debuggize_insn (insn_info *);
+  void debugize_insn (insn_info *);
 
   void unmark_debugizable(insn_info &, sbitmap &);
   sbitmap find_debugizable(const std::unordered_set &);
@@ -1875,7 +1875,7 @@ rtl_ssa_dce::propagate_dead_phis ()
 }
 
 void
-rtl_ssa_dce::debuggize_insn (insn_info *insn)
+rtl_ssa_dce::debugize_insn (insn_info *insn)
 {
   
 }
@@ -1908,6 +1908,7 @@ rtl_ssa_dce::unmark_debugizable(insn_info &insn, sbitmap 
&debugizable)
   bitmap_set_bit (debugizable, insn.uid ());
   worklist.safe_push (&insn);
 
+  // process all marked dependencies and unmark them
   while (!worklist.is_empty ()) {
 insn_info *current = worklist.pop ();
 int current_uid = current->uid ();
@@ -1917,6 +1918,7 @@ rtl_ssa_dce::unmark_debugizable(insn_info &insn, sbitmap 
&debugizable)
   continue;
 
 bitmap_clear_bit(debugizable, current_uid);
+
 // add all marked dependencies to the worklist
 for (def_info *def : current->defs())
 {
@@ -1934,6 +1936,8 @@ rtl_ssa_dce::unmark_debugizable(insn_info &insn, sbitmap 
&debugizable)
   }
 }
 
+// return a bitmap which describes whether an instruction can be debugized
+// - that means replaced with a debug instruction
 sbitmap
 rtl_ssa_dce::find_debugizable(const std::unordered_set 
&depends_on_dead_phi) 
 {
@@ -1942,26 +1946,24 @@ rtl_ssa_dce::find_debugizable(const 
std::unordered_set &depends_on_
   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
-
+// Skip live nondebug instrunctions. Debug instructions are by default 
live 
+// and we cannot skip them here
 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);
+
+  // we don't have to call unmark_debugizable, because dead nondebug
+  // instructions that depend on a dead phi won't be turned into a 
+  // debug instrunction
   continue;
 }
 
-// this insn might have some debugizable dependencies and if we find that
+// this insn may have some debugizable dependencies and if we find that
 // current insn is not debugizable, we have to reset those dependencies
-gcc_checking_assert(insn->is_real ());
 
 rtx_insn *rtl = insn->rtl ();
 def_array defs = insn->defs ();


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: detect phi loop when deleting, enable debugizing

2025-05-19 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:9728f377ae6a1092aba53166a8e67e6eff641412

commit 9728f377ae6a1092aba53166a8e67e6eff641412
Author: Ondřej Machota 
Date:   Tue May 20 08:37:19 2025 +0200

rtl-ssa-dce: detect phi loop when deleting, enable debugizing

Diff:
---
 gcc/dce.cc | 20 ++--
 gcc/rtl-ssa/changes.cc | 19 +++
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 520202f0462e..46806f18db80 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
 .  */
 
-#include "sbitmap.h"
 #include 
 #include 
 #define INCLUDE_ALGORITHM
@@ -1343,7 +1342,7 @@ public:
 
   void resize(size_t size, int offset)
   {
-sbitmap_resize(m_bitmap, size, 0); 
+m_bitmap = sbitmap_resize(m_bitmap, (unsigned int)size, 0); 
 m_offset = offset; 
   }
 
@@ -1381,7 +1380,7 @@ private:
 
   void debugize_insn (insn_info *);
 
-  void unmark_debugizable(insn_info &, sbitmap &);
+  void unmark_debugizable(insn_info &, sbitmap);
   sbitmap find_debugizable(const std::unordered_set &);
   void debugize_insns (const sbitmap);
 
@@ -1748,7 +1747,7 @@ rtl_ssa_dce::execute (function *fn)
 count++;
   }
 
-  m_marked.resize(artificial_min, real_max);
+  m_marked.resize(artificial_min, real_max + 1);
   // std::cout << "real_max: " << real_max << '\n';
   // std::cout << "artificial_min: " << artificial_min << '\n';
   // std::cout << "total: " << real_max - artificial_min + 3 << '\n';
@@ -1783,9 +1782,14 @@ rtl_ssa_dce::execute (function *fn)
   // frame_pointer_needed << '\n';
 
   mark ();
-  // propagate_dead_phis();
   if (MAY_HAVE_DEBUG_BIND_INSNS)
+   {
+auto dead_phis = propagate_dead_phis();
+auto debugizable = find_debugizable(dead_phis);
+debugize_insns(debugizable);
+
 reset_dead_debug ();
+   }
   sweep ();
 
   free_dominance_info (CDI_DOMINATORS);
@@ -1902,9 +1906,13 @@ replace_dead_reg(rtx x, const_rtx old_rtx 
ATTRIBUTE_UNUSED, void *data)
 
 // visit every marked instruction in INSN dependency tree and unmark it
 void
-rtl_ssa_dce::unmark_debugizable(insn_info &insn, sbitmap &debugizable) 
+rtl_ssa_dce::unmark_debugizable(insn_info &insn, sbitmap debugizable) 
 {
   auto_vec worklist;
+  gcc_assert(!insn.is_artificial());
+  if (insn.uid () < 0)
+std::cerr << "WTF" << insn.uid() << '\n';
+  std::cout << insn.uid () << '\n';
   bitmap_set_bit (debugizable, insn.uid ());
   worklist.safe_push (&insn);
 
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index 62518c515c92..aab6251d2bb1 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -256,20 +256,30 @@ rtl_ssa::changes_are_worthwhile (array_slice 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_phi_nodes)
 {
   if (!set->has_any_uses ())
 return;
 
+  insn_info *set_insn = set->insn ();
+  if (set_insn && set_insn->is_phi()) {
+   auto *phi = static_cast (set);
+   bitmap_set_bit (visited_phi_nodes, phi->uid ());
+  } 
+
   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 (), visited_phis);
- delete_phi (use->phi ());
+ phi_info *phi = use->phi ();
+ if (bitmap_bit_p(visited_phi_nodes, phi->uid ())) {
+   remove_use (use);
+ } else {
+   process_uses_of_deleted_def (phi, visited_phi_nodes);
+   delete_phi (phi);
+ }
}
   else
{
@@ -862,6 +872,7 @@ function_info::change_insns (array_slice 
changes)
  if (set && set->has_any_uses ())
{
auto_sbitmap visited_phis(m_next_phi_uid);
+   bitmap_clear(visited_phis);
process_uses_of_deleted_def (set, visited_phis);
}
  remove_def (def);


[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: fix index out of range when debugizing

2025-05-28 Thread Ondrej Machota via Gcc-cvs
https://gcc.gnu.org/g:a260eca59789d4dc2d064205d7ca0f2e544a

commit a260eca59789d4dc2d064205d7ca0f2e544a
Author: Ondřej Machota 
Date:   Wed May 28 10:13:14 2025 +0200

rtl-ssa-dce: fix index out of range when debugizing

Diff:
---
 gcc/dce.cc | 84 +-
 1 file changed, 61 insertions(+), 23 deletions(-)

diff --git a/gcc/dce.cc b/gcc/dce.cc
index 46806f18db80..2a203b673f32 100644
--- a/gcc/dce.cc
+++ b/gcc/dce.cc
@@ -1380,7 +1380,7 @@ private:
 
   void debugize_insn (insn_info *);
 
-  void unmark_debugizable(insn_info &, sbitmap);
+  void unmark_debugizable(insn_info *, sbitmap);
   sbitmap find_debugizable(const std::unordered_set &);
   void debugize_insns (const sbitmap);
 
@@ -1701,6 +1701,8 @@ rtl_ssa_dce::sweep ()
 fprintf (dump_file, "DCE: Sweep phase\n");
 
   auto_vec to_delete;
+
+  // Previously created debug instructions won't be visited here
   for (insn_info *insn : crtl->ssa->nondebug_insns ())
 {
   // Artificial or marked insns should not be deleted.
@@ -1906,15 +1908,13 @@ replace_dead_reg(rtx x, const_rtx old_rtx 
ATTRIBUTE_UNUSED, void *data)
 
 // visit every marked instruction in INSN dependency tree and unmark it
 void
-rtl_ssa_dce::unmark_debugizable(insn_info &insn, sbitmap debugizable) 
+rtl_ssa_dce::unmark_debugizable (insn_info *insn, sbitmap debugizable) 
 {
   auto_vec worklist;
-  gcc_assert(!insn.is_artificial());
-  if (insn.uid () < 0)
-std::cerr << "WTF" << insn.uid() << '\n';
-  std::cout << insn.uid () << '\n';
-  bitmap_set_bit (debugizable, insn.uid ());
-  worklist.safe_push (&insn);
+  gcc_checking_assert (!insn->is_artificial ());
+
+  bitmap_set_bit (debugizable, insn->uid ());
+  worklist.safe_push (insn);
 
   // process all marked dependencies and unmark them
   while (!worklist.is_empty ()) {
@@ -1930,13 +1930,22 @@ rtl_ssa_dce::unmark_debugizable(insn_info &insn, 
sbitmap debugizable)
 // add all marked dependencies to the worklist
 for (def_info *def : current->defs())
 {
-  if (def->kind() != access_kind::SET)
+  if (def->kind() != access_kind::SET) // skip clobbers
 continue;
   
-  set_info *set = static_cast(def);
+  auto *set = static_cast(def);
   for (use_info *use : set->all_uses()) 
   {
+// this phi node might not be dead
+if (use->is_in_phi ())
+  continue;
+
 insn_info *use_insn = use->insn();
+
+// artificial instruction will never be debugizable
+if (use_insn->is_artificial ())
+  continue;
+
 if (bitmap_bit_p(debugizable, use_insn->uid()))
   worklist.safe_push (use_insn);
   }
@@ -1949,27 +1958,34 @@ rtl_ssa_dce::unmark_debugizable(insn_info &insn, 
sbitmap debugizable)
 sbitmap
 rtl_ssa_dce::find_debugizable(const std::unordered_set 
&depends_on_dead_phi) 
 {
-  // only real instructions
+  // only real instructions can be turned to debug instructions
   sbitmap debugizable = sbitmap_alloc (get_max_uid () + 1);
   bitmap_clear(debugizable);
 
   for (insn_info *insn : crtl->ssa->reverse_all_insns ()) {
 // Skip live nondebug instrunctions. Debug instructions are by default 
live 
-// and we cannot skip them here
+// and we cannot skip them here - they have to be marked as debugizable
 if (insn->is_artificial () || 
   (m_marked.get_bit (insn->uid ()) && !insn->is_debug_insn()))
   continue;
 
+// instructions that depend on a dead phi node cannot be debugized
 if (depends_on_dead_phi.count (insn) > 0) {
   if (insn->is_debug_insn ())
 reset_dead_debug_insn (insn);
 
-  // we don't have to call unmark_debugizable, because dead nondebug
-  // instructions that depend on a dead phi won't be turned into a 
+  // we don't have to call unmark_debugizable, because a dead nondebug
+  // instructions that depends on a dead phi won't be turned into a 
   // debug instrunction
   continue;
 }
 
+// handle debug instrunctions - mark them and skip
+if (insn->is_debug_insn ()) {
+  bitmap_set_bit (debugizable, insn->uid ());
+  continue;
+}
+
 // this insn may have some debugizable dependencies and if we find that
 // current insn is not debugizable, we have to reset those dependencies
 
@@ -1983,35 +1999,38 @@ rtl_ssa_dce::find_debugizable(const 
std::unordered_set &depends_on_
   side_effects_p (SET_SRC (rtx_set)) ||
   asm_noperands (PATTERN (rtl)) >= 0)
   {
-unmark_debugizable(*insn, debugizable);
+std::cerr << "FAILED TO CREATE DEBUG\n";
+unmark_debugizable(insn, debugizable);
 continue;
   }
 
-// some of the checks might be duplicate:
+// insn is definitely a single_set, following if statement is useless:
 if (insn->num_defs () != 1)
 {
+  gcc_assert (false);
   if (insn->num_defs() > 1)
-unmark_debugizable(*insn, debugizable);
+unmark_debugizable(insn, debugi