https://gcc.gnu.org/g:a26cccc0eca59789d4dc2d064205d7ca0f2e544a
commit a26cccc0eca59789d4dc2d064205d7ca0f2e544a Author: Ondřej Machota <ondrejmach...@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