https://gcc.gnu.org/g:92e2b2fd496403a8d82b20b1fcefb265d1bf9e68
commit 92e2b2fd496403a8d82b20b1fcefb265d1bf9e68 Author: Ondřej Machota <ondrejmach...@gmail.com> 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 <http://www.gnu.org/licenses/>. */ +#include "bitmap.h" +#include "sbitmap.h" #include <iostream> #include <ostream> #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<insn_info *> 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<set_info *>(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<insn_info *> &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<set_info *> (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<set_info *> (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 ()) { + // 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); + } + } +} + void rtl_ssa_dce::debugize_insns (const std::unordered_set<insn_info *> &depends_on_dead_phi) {