[gcc(refs/users/omachota/heads/rtl-ssa-dce)] rtl-ssa-dce: fix index out of range when debugizing
Ondrej Machota
omachota@gcc.gnu.org
Wed May 28 08:13:52 GMT 2025
https://gcc.gnu.org/g:a26cccc0eca59789d4dc2d064205d7ca0f2e544a
commit a26cccc0eca59789d4dc2d064205d7ca0f2e544a
Author: Ondřej Machota <ondrejmachota@gmail.com>
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<insn_info *> &);
void debugize_insns (const sbitmap);
@@ -1701,6 +1701,8 @@ rtl_ssa_dce::sweep ()
fprintf (dump_file, "DCE: Sweep phase\n");
auto_vec<insn_change> 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<insn_info *> 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<set_info *>(def);
+ auto *set = static_cast<set_info *>(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<insn_info *> &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<insn_info *> &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, debugizable);
+ std::cerr << "FAILED TO CREATE DEBUG\n";
continue;
}
def_info *def = *defs.begin ();
- if (def->kind () != access_kind::SET)
+ if (def->kind () != access_kind::SET) // Skip clobbers
continue;
set_info *set = static_cast<set_info *> (def);
- // this is a problem a bit
- // TODO: check instruction dependencies and their debugizability
// if some dependent is a debugizable
bool has_debug_uses = false;
for (use_info *use : set->all_uses())
{
- if (!use->is_in_any_insn ())
+ // skip phi nodes
+ if (use->is_in_phi ())
continue;
insn_info *use_insn = use->insn();
- gcc_assert(use_insn->is_real());
+ if (use_insn->is_artificial ())
+ continue;
if (bitmap_bit_p(debugizable, use_insn->uid ())) {
has_debug_uses = true;
@@ -2028,12 +2047,15 @@ rtl_ssa_dce::find_debugizable(const std::unordered_set<insn_info *> &depends_on_
return debugizable;
}
+// create new debug instructions according to the DEBUGIZABLE sbitmap
void
rtl_ssa_dce::debugize_insns (const sbitmap debugizable)
{
for (insn_info *insn : crtl->ssa->reverse_all_insns ())
{
- if (insn->is_artificial () || !bitmap_bit_p(debugizable, insn->uid ()))
+ if (insn->is_artificial () ||
+ insn->is_debug_insn() ||
+ !bitmap_bit_p(debugizable, insn->uid ()))
continue;
rtx_insn *rtl = insn->rtl ();
@@ -2060,6 +2082,7 @@ rtl_ssa_dce::debugize_insns (const sbitmap debugizable)
insn_change change(debug_insn);
change.new_uses = insn->uses();
change.move_range = insn_range_info(insn);
+ debug (change);
if (!rtl_ssa::restrict_movement (change))
std::cerr << "change move range location does not exists\n";
@@ -2069,12 +2092,27 @@ rtl_ssa_dce::debugize_insns (const sbitmap debugizable)
register_replacement replacement;
for (use_info *u : set->all_uses ()) {
// TODO: transform dependent insns
+ if (u->is_artificial())
+ continue;
+
replacement.regno = u->regno();
replacement.expr = dval;
+ // if debugizable -> replace
+
simplify_replace_fn_rtx(INSN_VAR_LOCATION_LOC(rtl), NULL_RTX, replace_dead_reg, &replacement);
}
+ // pr113089.c
+ if (insn->uses().size() > 0) {
+ // std::cerr << "Insn has uses...\n";
+ }
+
+ // debug (bind_var_loc);
+ // debug (insn);
+ // debug (change.insn ());
+ // debug (crtl->ssa);
+
// 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
More information about the Gcc-cvs
mailing list