https://gcc.gnu.org/g:1bda298251f57d8942796fe141746a23db99f56f
commit 1bda298251f57d8942796fe141746a23db99f56f Author: Ondřej Machota <ondrejmach...@gmail.com> Date: Mon Jul 7 23:06:56 2025 +0200 rtl-ssa-dce: improve code Diff: --- gcc/dce.cc | 184 +++++++++++++++++++++++++----------------------- gcc/rtl-ssa/changes.cc | 49 ++++++++++--- gcc/rtl-ssa/functions.h | 1 + 3 files changed, 134 insertions(+), 100 deletions(-) diff --git a/gcc/dce.cc b/gcc/dce.cc index d564935a82f3..67fb42541d84 100644 --- a/gcc/dce.cc +++ b/gcc/dce.cc @@ -1324,7 +1324,8 @@ make_pass_fast_rtl_dce (gcc::context *ctxt) } namespace { -// offset_bitmap is a wrapper around sbitmap that also handles negative indices from RTL SSA +// offset_bitmap is a wrapper around sbitmap that also handles negative indices +// from RTL SSA struct offset_bitmap { private: @@ -1332,9 +1333,7 @@ private: sbitmap m_bitmap; public: - offset_bitmap () - : m_offset{0}, m_bitmap{sbitmap_alloc(0)} - {} + 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)} @@ -1344,15 +1343,15 @@ public: : offset_bitmap (size_t (max_index - min_index + 1), -min_index) {} - void resize(size_t size, int offset) + void resize (size_t size, int offset) { - m_bitmap = sbitmap_resize(m_bitmap, (unsigned int)size, 0); - m_offset = offset; + m_bitmap = sbitmap_resize (m_bitmap, (unsigned int) size, 0); + m_offset = offset; } - void resize(int min_index, int max_index) + void resize (int min_index, int max_index) { - resize(size_t (max_index - min_index + 1), -min_index); + resize (size_t (max_index - min_index + 1), -min_index); } void clear_bit (int index) { bitmap_clear_bit (m_bitmap, index + m_offset); } @@ -1411,13 +1410,12 @@ rtl_ssa_dce::can_delete_call (const_rtx insn) // We cannot delete pure or const sibling calls because it is // hard to see the result. return !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)) - // Don't delete calls that may throw if we cannot do so. - && cfun->can_delete_dead_exceptions - && insn_nothrow_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)) + // Don't delete calls that may throw if we cannot do so. + && cfun->can_delete_dead_exceptions && insn_nothrow_p (insn); } bool @@ -1508,7 +1506,6 @@ rtl_ssa_dce::is_prelive (insn_info *insn) return is_rtx_prelive (insn->rtl ()); } - // Mark SET as visited and return true if SET->insn() is not nullptr and SET // has not been visited. Otherwise return false. bool @@ -1519,26 +1516,28 @@ rtl_ssa_dce::mark_if_not_visited (const set_info *set) return false; if (insn->is_phi ()) - { - const phi_info *phi = static_cast<const phi_info *> (set); - auto uid = phi->uid (); + { + const phi_info *phi = static_cast<const phi_info *> (set); + auto uid = phi->uid (); - if (bitmap_bit_p (m_marked_phis, uid)) - return false; + if (bitmap_bit_p (m_marked_phis, uid)) + return false; - bitmap_set_bit (m_marked_phis, uid); - if (dump_file) - fprintf (dump_file, "Phi node %d:%d marked as live\n", set->regno () ,insn->uid ()); - } else - { - auto uid = insn->uid (); - if (m_marked.get_bit (uid)) - return false; + bitmap_set_bit (m_marked_phis, uid); + if (dump_file) + fprintf (dump_file, "Phi node %d:%d marked as live\n", set->regno (), + insn->uid ()); + } + else + { + auto uid = insn->uid (); + if (m_marked.get_bit (uid)) + return false; - m_marked.set_bit (uid); - if (dump_file) - fprintf (dump_file, "Insn %d marked as live\n", insn->uid ()); - } + m_marked.set_bit (uid); + if (dump_file) + fprintf (dump_file, "Insn %d marked as live\n", insn->uid ()); + } return true; } @@ -1546,28 +1545,31 @@ rtl_ssa_dce::mark_if_not_visited (const set_info *set) // For each use in USES, if use->def () is non-null and has not been visited, // mark it as visited and append it to WORKLIST. void -rtl_ssa_dce::append_not_visited_sets (auto_vec<set_info *>& worklist, use_array& uses) { +rtl_ssa_dce::append_not_visited_sets (auto_vec<set_info *> &worklist, + use_array &uses) +{ for (use_info *use : uses) - { - // This seems to be a good idea, however there is a problem is process_uses_of_deleted_def - if (use->only_occurs_in_notes()) - continue; + { + // This seems to be a good idea, however there is a problem is + // process_uses_of_deleted_def + if (use->only_occurs_in_notes ()) + continue; - set_info *parent_set = use->def (); - if (!parent_set) - continue; + set_info *parent_set = use->def (); + if (!parent_set) + continue; - if (!mark_if_not_visited (parent_set)) - continue; + if (!mark_if_not_visited (parent_set)) + continue; - // mark_if_not_visited will return false if insn is nullptr - // insn_info *insn = parent_set->insn (); - // gcc_checking_assert (insn); + // mark_if_not_visited will return false if insn is nullptr + // insn_info *insn = parent_set->insn (); + // gcc_checking_assert (insn); - // if (dump_file) - // fprintf (dump_file, "Adding insn %d to worklist\n", insn->uid ()); - worklist.safe_push (parent_set); - } + // if (dump_file) + // fprintf (dump_file, "Adding insn %d to worklist\n", insn->uid ()); + worklist.safe_push (parent_set); + } } // Mark INSN and add its uses to WORKLIST if INSN is not a debug instruction @@ -1578,9 +1580,9 @@ rtl_ssa_dce::mark_prelive_insn (insn_info *insn, auto_vec<set_info *> &worklist) fprintf (dump_file, "Insn %d marked as prelive\n", insn->uid ()); // A phi node will never be prelive. - m_marked.set_bit(insn->uid ()); - // Debug instruction are not added to worklist. They would wake up possibly dead - // instructions + m_marked.set_bit (insn->uid ()); + // Debug instruction are not added to worklist. They would wake up possibly + // dead instructions if (insn->is_debug_insn ()) return; @@ -1627,7 +1629,7 @@ rtl_ssa_dce::mark () uses = phi->inputs (); } - append_not_visited_sets(worklist, uses); + append_not_visited_sets (worklist, uses); } } @@ -1659,23 +1661,27 @@ rtl_ssa_dce::reset_dead_debug () for (use_info *use : insn->uses ()) { - def_info *def = use->def (); + def_info *def = use->def (); insn_info *parent_insn = def->insn (); - if (parent_insn == nullptr) - continue; - // If we depend on a dead instruction, clear current instruction uses. - bool is_parent_marked = false; - if (parent_insn->is_phi ()) { - auto phi = static_cast<phi_info *> (def); - is_parent_marked = bitmap_bit_p (m_marked_phis, phi->uid ()); - } else { - is_parent_marked = m_marked.get_bit (parent_insn->uid ()); - } + if (parent_insn == nullptr) + continue; + // If we depend on a dead instruction, clear current instruction uses. + bool is_parent_marked = false; + if (parent_insn->is_phi ()) + { + auto phi = static_cast<phi_info *> (def); + is_parent_marked = bitmap_bit_p (m_marked_phis, phi->uid ()); + } + else + { + is_parent_marked = m_marked.get_bit (parent_insn->uid ()); + } - if (!is_parent_marked) { - reset_dead_debug_insn (insn); - break; - } + if (!is_parent_marked) + { + reset_dead_debug_insn (insn); + break; + } } } } @@ -1717,27 +1723,27 @@ rtl_ssa_dce::sweep () unsigned int rtl_ssa_dce::execute (function *fn) { - auto_timevar timer(TV_RTL_SSA_DCE); + auto_timevar timer (TV_RTL_SSA_DCE); calculate_dominance_info (CDI_DOMINATORS); crtl->ssa = new rtl_ssa::function_info (fn); int real_max = 0, artificial_min = 0; std::size_t count = 0; - for (insn_info *insn : crtl->ssa->all_insns ()) - { - artificial_min = std::min (artificial_min, insn->uid ()); - real_max = std::max (real_max, insn->uid ()); - count++; - } + for (insn_info *insn : crtl->ssa->all_insns ()) + { + artificial_min = std::min (artificial_min, insn->uid ()); + real_max = std::max (real_max, insn->uid ()); + count++; + } - m_marked.resize(artificial_min, real_max + 1); + m_marked.resize (artificial_min, real_max + 1); unsigned int phi_node_max = 0; for (ebb_info *ebb : crtl->ssa->ebbs ()) for (phi_info *phi : ebb->phis ()) phi_node_max = std::max (phi_node_max, phi->uid ()); - m_marked_phis = sbitmap_alloc(phi_node_max + 1); - bitmap_clear(m_marked_phis); + m_marked_phis = sbitmap_alloc (phi_node_max + 1); + bitmap_clear (m_marked_phis); mark (); if (MAY_HAVE_DEBUG_BIND_INSNS) @@ -1748,21 +1754,21 @@ rtl_ssa_dce::execute (function *fn) if (crtl->ssa->perform_pending_updates ()) cleanup_cfg (0); - sbitmap_free(m_marked_phis); + sbitmap_free (m_marked_phis); delete crtl->ssa; crtl->ssa = nullptr; return 0; } const pass_data pass_data_rtl_ssa_dce = { - RTL_PASS, /* type */ - "rtl_ssa_dce", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - TV_RTL_SSA_DCE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ + RTL_PASS, /* type */ + "rtl_ssa_dce", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_RTL_SSA_DCE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ TODO_df_finish, /* todo_flags_finish */ }; diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc index a9b1a00475dd..f99c95a87fbf 100644 --- a/gcc/rtl-ssa/changes.cc +++ b/gcc/rtl-ssa/changes.cc @@ -36,6 +36,7 @@ #include "cfghooks.h" #include "cfgrtl.h" #include "sreal.h" +#include "rtl-iter.h" using namespace rtl_ssa; @@ -253,8 +254,42 @@ rtl_ssa::changes_are_worthwhile (array_slice<insn_change *const> changes, return true; } +// A definition is dead. Remove REG_EQUIV and REG_EQUAL notes from +// the instruction which uses the definition. +void +function_info::remove_notes_of_deleted_def (use_info *use) +{ + gcc_checking_assert (use->only_occurs_in_notes ()); + + insn_info *insn = use->insn (); + rtx_insn *rtl = insn->rtl (); + for (rtx next = REG_NOTES (rtl); next;) + { + rtx note = next; + next = XEXP (note, 1); + int kind = REG_NOTE_KIND (note); + if (kind != REG_EQUIV && kind != REG_EQUAL) + continue; + + bool reg_equals = false; + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, note, ALL) + { + if (GET_CODE (*iter) == REG && REGNO (*iter) == use->regno ()) + { + reg_equals = true; + break; + } + } + + if (reg_equals) + remove_note (rtl, note); + } +} + + // SET has been deleted. Clean up all remaining uses. Such uses are -// either dead phis or now-redundant live-out uses. +// either dead phis, now-redundant live-out uses or dead notes. void function_info::process_uses_of_deleted_def (set_info *set) { @@ -285,20 +320,12 @@ function_info::process_uses_of_deleted_def (set_info *set) } else { - // following assert causes crash when running rtl_ssa_dce with - // deleting eq_notes on testsuite if (use->only_occurs_in_notes ()) - { - insn_info *insn = use->insn (); - rtx_insn *rtl = insn->rtl (); - // TODO: remove note from rtl - } + remove_notes_of_deleted_def (use); else - { gcc_assert (use->is_live_out_use ()); - } - remove_use (use); + remove_use (use); } // The phi handling above might have removed multiple uses of this_set. if (this_set->has_any_uses ()) diff --git a/gcc/rtl-ssa/functions.h b/gcc/rtl-ssa/functions.h index 2e20f5e47d72..72b330ec8c35 100644 --- a/gcc/rtl-ssa/functions.h +++ b/gcc/rtl-ssa/functions.h @@ -306,6 +306,7 @@ private: bb_info *create_bb_info (basic_block); void append_bb (bb_info *); + void remove_notes_of_deleted_def (use_info *); void process_uses_of_deleted_def (set_info *); insn_info *add_placeholder_after (insn_info *); void possibly_queue_changes (insn_change &);