https://gcc.gnu.org/g:5a59807bef7e70e8216ce41c212b8ddb2d8caf22
commit 5a59807bef7e70e8216ce41c212b8ddb2d8caf22 Author: Ondřej Machota <ondrejmach...@gmail.com> 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<register_replacement *>(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<insn_info *> &depends_on_dead_phi) { @@ -1895,8 +1915,61 @@ rtl_ssa_dce::debugize_insns (const std::unordered_set<insn_info *> &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<set_info *> (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<insn_info *> &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<insn_info *> &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<insn_change *const> 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<insn_change *> changes) { auto *set = dyn_cast<set_info *> (def); if (set && set->has_any_uses ()) - process_uses_of_deleted_def (set); + { + auto_sbitmap phis(m_next_phi_uid); + process_uses_of_deleted_def (set); + } remove_def (def); }