[gcc r17-3204] Provide a DCE no-delete option.
Andrew Macleod
amacleod@gcc.gnu.org
Tue Aug 11 17:39:48 GMT 2026
https://gcc.gnu.org/g:e02ce3b8c4574c81a943eb1084b0e0bf6a9955d5
commit r17-3204-ge02ce3b8c4574c81a943eb1084b0e0bf6a9955d5
Author: Andrew MacLeod <amacleod@redhat.com>
Date: Tue Aug 4 12:13:15 2026 -0400
Provide a DCE no-delete option.
Add a flag which replaces statement with assignment to zero instead of
removing them.
PR tree-optimization/126329
gcc/
* tree-ssa-dce.cc (simple_dce_from_worklist): Add no-delete option.
* tree-ssa-dce.h (simple_dce_from_worklist): Add no delete param.
* tree-vrp.cc (remove_unreachable::handle_early): Use no delete option.
gcc/testsuite/
* gcc.dg/pr126329.c: New.
Diff:
---
gcc/testsuite/gcc.dg/pr126329.c | 28 +++++++++++++++++++++
gcc/tree-ssa-dce.cc | 54 +++++++++++++++++++++++++++++++++--------
gcc/tree-ssa-dce.h | 2 +-
gcc/tree-vrp.cc | 2 +-
4 files changed, 74 insertions(+), 12 deletions(-)
diff --git a/gcc/testsuite/gcc.dg/pr126329.c b/gcc/testsuite/gcc.dg/pr126329.c
new file mode 100644
index 000000000000..50165c574e5d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr126329.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+#include <stdint.h>
+int32_t g30;
+void f25(int32_t a1)
+{
+ int a2;
+ _Bool c6, c14;
+ int8_t v8;
+ int64_t v15;
+ int8_t v16;
+ if (a1 == 8098) goto lbl_sw11;
+ a2 = __builtin_ffs(a1);
+lbl_b8:
+ v8 = a2;
+ c6 = v8 >= v16;
+ goto lbl_br26;
+lbl_sw11:
+lbl_br17:
+ goto lbl_b8;
+lbl_br26:
+ g30 = v8;
+ if (c6) __builtin_unreachable();
+ c6 = c14 = a1;
+ a1 = v8;
+ if (v15) goto lbl_br26;
+ if (c14) goto lbl_br17;
+}
diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc
index 548d5d4bd661..bf818ad2c919 100644
--- a/gcc/tree-ssa-dce.cc
+++ b/gcc/tree-ssa-dce.cc
@@ -2170,10 +2170,16 @@ make_pass_cd_dce (gcc::context *ctxt)
/* A cheap DCE interface. WORKLIST is a list of possibly dead stmts and
is consumed by this function. The function has linear complexity in
the number of dead stmts with a constant factor like the average SSA
- use operands number. */
+ use operands number.
+ If no_delete is true (defaults to false) then rather than deleting the
+ statement, it is replaced with an assignment to 0. This allows the
+ same elimination of statement dependencies, but delays the actual statement
+ removal from the IL until the next time DCE is run and they are detected
+ as dead statements with no uses. */
void
-simple_dce_from_worklist (bitmap worklist, bitmap need_eh_cleanup)
+simple_dce_from_worklist (bitmap worklist, bitmap need_eh_cleanup,
+ bool no_delete)
{
int phiremoved = 0;
int stmtremoved = 0;
@@ -2217,11 +2223,20 @@ simple_dce_from_worklist (bitmap worklist, bitmap need_eh_cleanup)
gimple *t = SSA_NAME_DEF_STMT (def);
if (gimple_has_side_effects (t))
{
- if (gcall *call = dyn_cast <gcall *> (t))
+ gcall *call = dyn_cast <gcall *> (t);
+ if (call)
{
gimple_call_set_lhs (call, NULL_TREE);
update_stmt (call);
- release_ssa_name (def);
+ if (no_delete)
+ {
+ tree zero = build_zero_cst (TREE_TYPE (def));
+ gassign *new_stmt = gimple_build_assign (def, zero);
+ gimple_stmt_iterator gsi = gsi_for_stmt (t);
+ gsi_insert_after (&gsi, new_stmt, GSI_SAME_STMT);
+ }
+ else
+ release_ssa_name (def);
}
continue;
}
@@ -2263,19 +2278,38 @@ simple_dce_from_worklist (bitmap worklist, bitmap need_eh_cleanup)
gimple_stmt_iterator gsi = gsi_for_stmt (t);
if (gimple_code (t) == GIMPLE_PHI)
{
- remove_phi_node (&gsi, true);
+ if (no_delete)
+ {
+ gphi *phi = as_a<gphi *> (t);
+ tree zero = build_zero_cst (TREE_TYPE (def));
+ for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
+ SET_PHI_ARG_DEF (phi, i, zero);
+ update_stmt (phi);
+ }
+ else
+ remove_phi_node (&gsi, true);
+
phiremoved++;
}
else
{
unlink_stmt_vdef (t);
- gsi_remove (&gsi, true);
- release_defs (t);
+ if (no_delete)
+ {
+ tree zero = build_zero_cst (TREE_TYPE (def));
+ gassign *new_stmt = gimple_build_assign (def, zero);
+ gsi_replace (&gsi, new_stmt, true);
+ }
+ else
+ {
+ gsi_remove (&gsi, true);
+ release_defs (t);
+ }
stmtremoved++;
}
}
- statistics_counter_event (cfun, "PHIs removed",
+ statistics_counter_event (cfun, no_delete ? "PHIs rewritten" : "PHIs removed",
phiremoved);
- statistics_counter_event (cfun, "Statements removed",
- stmtremoved);
+ statistics_counter_event (cfun, no_delete ? "Statements rewritten"
+ : "Statements removed", stmtremoved);
}
diff --git a/gcc/tree-ssa-dce.h b/gcc/tree-ssa-dce.h
index dd874479fb56..d97e5e7c3b1e 100644
--- a/gcc/tree-ssa-dce.h
+++ b/gcc/tree-ssa-dce.h
@@ -18,5 +18,5 @@ along with GCC; see the file COPYING3. If not see
#ifndef TREE_SSA_DCE_H
#define TREE_SSA_DCE_H
-extern void simple_dce_from_worklist (bitmap, bitmap = nullptr);
+extern void simple_dce_from_worklist (bitmap, bitmap = nullptr, bool no_delete = false);
#endif
diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
index da65d67b4052..6f1e3eb90352 100644
--- a/gcc/tree-vrp.cc
+++ b/gcc/tree-vrp.cc
@@ -248,7 +248,7 @@ remove_unreachable::handle_early (gimple *s, edge e)
{
auto_bitmap dce;
bitmap_set_bit (dce, SSA_NAME_VERSION (ssa));
- simple_dce_from_worklist (dce);
+ simple_dce_from_worklist (dce, nullptr, true);
}
}
More information about the Gcc-cvs
mailing list