https://gcc.gnu.org/g:4ca3c04a0181c37eaef23f2d50300151b428aa6f
commit 4ca3c04a0181c37eaef23f2d50300151b428aa6f Author: Ondřej Machota <ondrejmach...@gmail.com> Date: Fri May 9 10:54:19 2025 +0200 rtl-ssa-dce: use offset_bitmap Diff: --- gcc/dce.cc | 207 +++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 168 insertions(+), 39 deletions(-) diff --git a/gcc/dce.cc b/gcc/dce.cc index 67c9ad577e67..e077485c93c3 100644 --- a/gcc/dce.cc +++ b/gcc/dce.cc @@ -1318,13 +1318,55 @@ public: } // namespace +// TODO: naalokovat prazdnou a pak resize +// -flto_partition=none +// -ftime_report a v build adresari zkusit insn*.cc (emit, match, recog) +struct offset_bitmap +{ +private: + int m_offset; + sbitmap m_bitmap; + +public: + offset_bitmap () + : m_offset{0}, m_bitmap{sbitmap_alloc(0)} + {} + + offset_bitmap (size_t size, int offset) + : m_offset{offset}, m_bitmap{sbitmap_alloc (size)} + {} + + offset_bitmap (int min_index, int max_index) + : offset_bitmap (size_t (max_index - min_index + 1), -min_index) + {} + + void resize(size_t size, int offset) + { + sbitmap_resize(m_bitmap, size, 0); + m_offset = offset; + } + + void resize(int min_index, int max_index) + { + resize(size_t (max_index - min_index + 1), -min_index); + } + + void clear_bit (int index) { bitmap_clear_bit (m_bitmap, index + m_offset); } + + void set_bit (int index) { bitmap_set_bit (m_bitmap, index + m_offset); } + + bool get_bit (int index) { return bitmap_bit_p (m_bitmap, index + m_offset); } + + ~offset_bitmap () { sbitmap_free (m_bitmap); } +}; + class rtl_ssa_dce { public: unsigned int execute (function *); private: - bool is_rtx_body_prelive (const_rtx); + bool is_rtx_pattern_prelive (const_rtx); bool can_delete_call (const_rtx); bool is_rtx_prelive (const_rtx); bool is_prelive (insn_info *); @@ -1336,14 +1378,15 @@ private: void reset_dead_debug (); void sweep (); - int offset; - - sbitmap mm_marked; + void debuggize_insn (insn_info *); + void debbugize_insns (const std::unordered_set<insn_info *> &); + + offset_bitmap m_marked; sbitmap mm_marked_phis; }; bool -rtl_ssa_dce::is_rtx_body_prelive (const_rtx insn) +rtl_ssa_dce::is_rtx_pattern_prelive (const_rtx insn) { switch (GET_CODE (insn)) { @@ -1357,9 +1400,28 @@ rtl_ssa_dce::is_rtx_body_prelive (const_rtx insn) } } +// odebrat auto + bool rtl_ssa_dce::can_delete_call (const_rtx insn) { + gcc_checking_assert (CALL_P (insn)); + + // We cannot delete pure or const sibling calls because it is + // hard to see the result. + // if (!SIBLING_CALL_P (insn)) + // // We can delete dead const or pure calls as long as they do not + // // infinite loop. + // && (RTL_CONST_OR_PURE_CALL_P (insn) + // && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn) + + // && cfun->can_delete_dead_exceptions + // ) + // return true; + // Don't delete calls that may throw if we cannot do so. + + // pridat assert na const nebo pure + // pouzivat gcc_checking_assert(); if (cfun->can_delete_dead_exceptions) return true; // if (!insn_nothrow_p (insn)) @@ -1408,8 +1470,7 @@ rtl_ssa_dce::is_rtx_prelive (const_rtx insn) gcc_assert (GET_CODE (insn) == INSN); // Don't delete insns that may throw if we cannot do so. - if (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn) - && can_alter_cfg) + if (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn)) return true; // Callee-save restores are needed. @@ -1417,8 +1478,8 @@ rtl_ssa_dce::is_rtx_prelive (const_rtx insn) && find_reg_note (insn, REG_CFA_RESTORE, NULL)) return true; - rtx body = PATTERN (insn); - switch (GET_CODE (body)) + rtx pat = PATTERN (insn); + switch (GET_CODE (pat)) { case CLOBBER: case USE: @@ -1426,13 +1487,13 @@ rtl_ssa_dce::is_rtx_prelive (const_rtx insn) return true; case PARALLEL: - for (int i = XVECLEN (body, 0) - 1; i >= 0; i--) - if (is_rtx_body_prelive (XVECEXP (body, 0, i))) + for (int i = XVECLEN (pat, 0) - 1; i >= 0; i--) + if (is_rtx_pattern_prelive (XVECEXP (pat, 0, i))) return true; return false; default: - return is_rtx_body_prelive (body); + return is_rtx_pattern_prelive (pat); } } @@ -1472,6 +1533,7 @@ rtl_ssa_dce::is_prelive (insn_info *insn) if (HARD_REGISTER_NUM_P (def->regno ()) && global_regs[def->regno ()]) return true; + // what about reload? check cse.cc unsigned int picreg = PIC_OFFSET_TABLE_REGNUM; if (picreg != INVALID_REGNUM && fixed_regs[picreg] && def->regno () == picreg) @@ -1487,7 +1549,7 @@ rtl_ssa_dce::mark_prelive_insn (insn_info *insn, auto_vec<set_info *> &worklist) if (dump_file) fprintf (dump_file, "Insn %d marked as prelive\n", insn->uid ()); - bitmap_set_bit (mm_marked, insn->uid () + offset); + m_marked.set_bit(insn->uid ()); // debug instruction are not added to worklist not to wake up possibly dead // instructions if (insn->is_debug_insn ()) @@ -1517,6 +1579,7 @@ rtl_ssa_dce::mark_prelive () return worklist; } +// kometare + PARAMETRY kapitalkami void rtl_ssa_dce::mark () { @@ -1532,11 +1595,12 @@ rtl_ssa_dce::mark () continue; // Skip already visited visited instructions. - auto uid = insn->uid () + offset; - if (bitmap_bit_p (mm_marked, uid) && !insn->is_phi ()) + auto uid = insn->uid (); + if (m_marked.get_bit(uid) && !insn->is_phi ()) continue; - bitmap_set_bit (mm_marked, uid); + m_marked.set_bit (uid); + use_array uses = insn->uses (); if (insn->is_phi ()) @@ -1604,12 +1668,24 @@ rtl_ssa_dce::reset_dead_debug () if (parent_insn == nullptr) continue; // If we depend on a dead instruction, clear current instruction uses. - sbitmap marked = parent_insn->is_phi () ? mm_marked_phis : mm_marked; - int uid = parent_insn->is_phi () ? static_cast<phi_info *> (def)->uid () : parent_insn->uid () + offset; - if (!bitmap_bit_p (marked, uid)) { + bool shouldReset = false; + if (parent_insn->is_phi ()) { + shouldReset = bitmap_bit_p(mm_marked_phis, static_cast<phi_info *> (def)->uid ()); + } else { + shouldReset = m_marked.get_bit(parent_insn->uid ()); + } + + if (shouldReset) { reset_dead_debug_insn (insn); break; } + + // sbitmap marked = parent_insn->is_phi () ? mm_marked_phis : mm_marked; + // int uid = parent_insn->is_phi () ? static_cast<phi_info *> (def)->uid () : parent_insn->uid () + offset; + // if (!bitmap_bit_p (marked, uid)) { + // reset_dead_debug_insn (insn); + // break; + // } } } } @@ -1625,7 +1701,7 @@ rtl_ssa_dce::sweep () for (insn_info *insn : crtl->ssa->nondebug_insns ()) { // Artificial or marked insns should not be deleted. - if (insn->is_artificial () || bitmap_bit_p (mm_marked, insn->uid () + offset)) + if (insn->is_artificial () || m_marked.get_bit (insn->uid ())) continue; if (dump_file) @@ -1668,11 +1744,10 @@ rtl_ssa_dce::execute (function *fn) count++; } - offset = -artificial_min; + m_marked.resize(artificial_min, real_max); // std::cout << "real_max: " << real_max << '\n'; // std::cout << "artificial_min: " << artificial_min << '\n'; // std::cout << "total: " << real_max - artificial_min + 3 << '\n'; - // std::cout << "Offset: " << offset << '\n'; // std::cout << "count: " << count << '\n'; unsigned int phi_node_max = 0; @@ -1681,8 +1756,6 @@ rtl_ssa_dce::execute (function *fn) phi_node_max = std::max (phi_node_max, phi->uid ()); // std::cout << "phi_node_max: " << phi_node_max << '\n'; - mm_marked = sbitmap_alloc(real_max - artificial_min + 3); - bitmap_clear(mm_marked); mm_marked_phis = sbitmap_alloc(phi_node_max + 1); bitmap_clear(mm_marked_phis); @@ -1715,7 +1788,6 @@ rtl_ssa_dce::execute (function *fn) if (crtl->ssa->perform_pending_updates ()) cleanup_cfg (0); - sbitmap_free(mm_marked); sbitmap_free(mm_marked_phis); delete crtl->ssa; crtl->ssa = nullptr; @@ -1754,7 +1826,8 @@ rtl_ssa_dce::propagate_dead_phis () if (dump_file) fprintf (dump_file, "Debug insns %d depends on dead phi.\n", insn->uid ()); - bitmap_clear_bit (mm_marked, insn->uid ()); + + m_marked.clear_bit (insn->uid ()); // debug instructions dont have chains continue; } @@ -1762,12 +1835,12 @@ rtl_ssa_dce::propagate_dead_phis () // mark if (insn->is_phi ()) { - gcc_assert (!bitmap_bit_p(mm_marked_phis, static_cast<phi_info *> (set)->uid ())); + gcc_checking_assert (!bitmap_bit_p(mm_marked_phis, static_cast<phi_info *> (set)->uid ())); visited_dead_phis.emplace (static_cast<phi_info *> (set)); } else { - gcc_assert (!bitmap_bit_p (mm_marked, insn->uid () + offset)); + gcc_checking_assert (!m_marked.get_bit (insn->uid ())); depends_on_dead_phi.emplace (insn); } @@ -1797,20 +1870,72 @@ rtl_ssa_dce::propagate_dead_phis () return depends_on_dead_phi; } -static void -rtl_ssa_dce_debuggize (insn_info *insn) +void +rtl_ssa_dce::debuggize_insn (insn_info *insn) { - if (insn->is_phi ()) - { - return; - } + +} - if (insn->is_debug_insn ()) - { - // we need to fix dependencies of this instruction because they might have - // changed - return; +void +rtl_ssa_dce::debbugize_insns (const std::unordered_set<insn_info *> &depends_on_dead_phi) +{ + 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; } + + gcc_checking_assert(insn->is_real ()); + + rtx_insn *rtl = insn->rtl (); + def_array defs = insn->defs (); + // def_info* s = nullptr; + // s->kind() == access_kind::SET + rtx set; + // debbugize_insns should be called only if MAY_HAVE_DEBUG_BIND_INSNS + if (MAY_HAVE_DEBUG_BIND_INSNS + && (set = single_set (rtl)) != NULL_RTX + && !(*defs.begin ())->has_nondebug_insn_uses() + // && is_dead_reg (SET_DEST (set), counts) + // Proc tam byla tato podminka? + // - debug statementy se sypou za kazdou definici ve zdrojaku, tedy + // proto se chci ptat na to, kdyz existuje debug pouziti, tak je to + // zajimava promenna + /* Used at least once in some DEBUG_INSN. */ + // && counts[REGNO (SET_DEST (set)) + nreg] > 0 + // Tohle je ten bind nebo cast debug instrukce? + /* And set exactly once. */ + // && counts[REGNO (SET_DEST (set)) + nreg * 2] == 1 + && !side_effects_p (SET_SRC (set)) + && asm_noperands (PATTERN (rtl)) < 0) + { + // TODO: musime predratovat zavisle debug insn - vsechny uses na nove + // vytvorenou debug insn + /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL). */ + rtx dval = make_debug_expr_from_rtl (SET_DEST (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 (set)), + DEBUG_EXPR_TREE_DECL (dval), + SET_SRC (set), + VAR_INIT_STATUS_INITIALIZED); + // count_reg_usage (bind_var_loc, counts + nreg, NULL_RTX, 1); + + rtx_insn *bind = emit_debug_insn_before (bind_var_loc, rtl); + + // if (replacements == NULL) + // replacements = XCNEWVEC (rtx, nreg); + // replacements[REGNO (SET_DEST (set))] = dval; + } + } } static void @@ -1828,6 +1953,10 @@ test (insn_info *insn) DEBUG_EXPR_TREE_DECL (dval), SET_SRC (set), VAR_INIT_STATUS_INITIALIZED); + obstack_watermark watermark = crtl->ssa->new_change_attempt(); + // Radeji bych zde videl pridani dval do rtl ssa + // crtl->ssa->create_insn(watermark, DEBUG_INSN, rtx pat); + // TODO : change ssa form - we have to keep uses in the first debug insn and // delete other instructions // make dval available in the following iteration