https://gcc.gnu.org/g:e6b162ba3f9c3b26f57e7f00dbfa8d2dc8656cf8
commit e6b162ba3f9c3b26f57e7f00dbfa8d2dc8656cf8 Author: Ondřej Machota <ondrejmach...@gmail.com> Date: Fri Jun 20 00:01:49 2025 +0200 rtl-ssa-dce: bug report Diff: --- gcc/cse.cc | 2 +- gcc/dce.cc | 517 +++--------------------------------------------- gcc/fwprop.cc | 2 +- gcc/passes.def | 5 +- gcc/rtl-ssa/changes.cc | 24 +-- gcc/rtl-ssa/functions.h | 2 +- 6 files changed, 34 insertions(+), 518 deletions(-) diff --git a/gcc/cse.cc b/gcc/cse.cc index 9c0924d73e1d..70d5caac4cac 100644 --- a/gcc/cse.cc +++ b/gcc/cse.cc @@ -7639,7 +7639,7 @@ rest_of_handle_cse2 (void) bypassed safely. */ cse_condition_code_reg (); - // delete_trivially_dead_insns (get_insns (), max_reg_num ()); + delete_trivially_dead_insns (get_insns (), max_reg_num ()); if (tem == 2) { diff --git a/gcc/dce.cc b/gcc/dce.cc index 2a203b673f32..77ff0a4d2791 100644 --- a/gcc/dce.cc +++ b/gcc/dce.cc @@ -42,7 +42,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-pass.h" #include "dbgcnt.h" #include "rtl-iter.h" -#include <unordered_set> using namespace rtl_ssa; @@ -1318,9 +1317,13 @@ public: } // namespace -// TODO: naalokovat prazdnou a pak resize -// -flto_partition=none -// -ftime_report a v build adresari zkusit insn*.cc (emit, match, recog) +rtl_opt_pass * +make_pass_fast_rtl_dce (gcc::context *ctxt) +{ + return new pass_fast_rtl_dce (ctxt); +} + +// offset_bitmap is a wrapper around sbitmap which takes care of negative indices struct offset_bitmap { private: @@ -1373,17 +1376,10 @@ private: void mark_prelive_insn (insn_info *, auto_vec<set_info *> &); auto_vec<set_info *> mark_prelive (); void mark (); - std::unordered_set<insn_info *> propagate_dead_phis (); void reset_dead_debug_insn (insn_info *); void reset_dead_debug (); void sweep (); - void debugize_insn (insn_info *); - - void unmark_debugizable(insn_info *, sbitmap); - sbitmap find_debugizable(const std::unordered_set<insn_info *> &); - void debugize_insns (const sbitmap); - offset_bitmap m_marked; sbitmap mm_marked_phis; }; @@ -1403,49 +1399,14 @@ rtl_ssa_dce::is_rtx_pattern_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)) - // return false; return insn_nothrow_p (insn); - - // UD_DCE ignores this and works... - /* If we can't alter cfg, even when the call can't throw exceptions, it - might have EDGE_ABNORMAL_CALL edges and so we shouldn't delete such - calls. */ - // gcc_assert (CALL_P (insn)); - // if (BLOCK_FOR_INSN (insn) && BB_END (BLOCK_FOR_INSN (insn)) == insn) - // { - // edge e; - // edge_iterator ei; - - // FOR_EACH_EDGE (e, ei, BLOCK_FOR_INSN (insn)->succs) - // if ((e->flags & EDGE_ABNORMAL_CALL) != 0) - // return false; - // } - // return true; } bool @@ -1503,8 +1464,8 @@ rtl_ssa_dce::is_rtx_prelive (const_rtx insn) bool rtl_ssa_dce::is_prelive (insn_info *insn) { - // bb head and end contain artificial uses that we need to mark as prelive - // debug instructions are also prelive, however, they are not added to the + // Bb head and end contain artificial uses that we need to mark as prelive. + // Debug instructions are also prelive, however, they are not added to the // worklist if (insn->is_bb_head () || insn->is_bb_end () || insn->is_debug_insn ()) return true; @@ -1522,21 +1483,20 @@ rtl_ssa_dce::is_prelive (insn_info *insn) gcc_assert (def->is_reg ()); - // we should not delete the frame pointer because of the dward2frame pass + // We should not delete the frame pointer because of the dward2frame pass if (frame_pointer_needed && def->regno () == HARD_FRAME_POINTER_REGNUM) return true; - // skip clobbers, they are handled inside is_rtx_prelive + // Skip clobbers, they are handled inside is_rtx_prelive if (def->kind () == access_kind::CLOBBER) continue; gcc_assert (def->kind () == access_kind::SET); - // needed by gcc.c-torture/execute/pr51447.c + // Needed by gcc.c-torture/execute/pr51447.c 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) @@ -1546,6 +1506,7 @@ rtl_ssa_dce::is_prelive (insn_info *insn) return is_rtx_prelive (insn->rtl ()); } +// Marks INSN and adds its uses to worklist if INSN is not a debug instruction void rtl_ssa_dce::mark_prelive_insn (insn_info *insn, auto_vec<set_info *> &worklist) { @@ -1553,7 +1514,7 @@ 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 ()); m_marked.set_bit(insn->uid ()); - // debug instruction are not added to worklist not to wake up possibly dead + // Debug instruction are not added to worklist. They would wake up possibly dead // instructions if (insn->is_debug_insn ()) return; @@ -1566,6 +1527,7 @@ rtl_ssa_dce::mark_prelive_insn (insn_info *insn, auto_vec<set_info *> &worklist) } } +// Scans all instructions and marks all which are prelive auto_vec<set_info *> rtl_ssa_dce::mark_prelive () { @@ -1582,7 +1544,6 @@ rtl_ssa_dce::mark_prelive () return worklist; } -// kometare + PARAMETRY kapitalkami void rtl_ssa_dce::mark () { @@ -1594,7 +1555,7 @@ rtl_ssa_dce::mark () { set_info *set = worklist.pop (); insn_info *insn = set->insn (); - if (!insn) // TODO: is this possible? + if (!insn) continue; // Skip already visited visited instructions. @@ -1636,15 +1597,15 @@ rtl_ssa_dce::mark () void rtl_ssa_dce::reset_dead_debug_insn (insn_info *insn) { - gcc_assert (insn->is_debug_insn ()); + gcc_checking_assert (insn->is_debug_insn ()); if (dump_file) fprintf (dump_file, "Resetting debug insn: %d\n", insn->uid ()); m_marked.clear_bit (insn->uid ()); + INSN_VAR_LOCATION_LOC (insn->rtl ()) = gen_rtx_UNKNOWN_VAR_LOC (); insn_change change (insn); change.new_uses = {}; - INSN_VAR_LOCATION_LOC (insn->rtl ()) = gen_rtx_UNKNOWN_VAR_LOC (); crtl->ssa->change_insn (change); } @@ -1658,37 +1619,25 @@ rtl_ssa_dce::reset_dead_debug () if (!insn->is_debug_insn ()) continue; - // When propagate_dead_phis is ready, check if insn is in marked. If true, - // then try to create debug instructions RTL SSA does not contain debug - // insntructions... we have to make sure that uses are correct - - // TODO : use iterate_safely? for (use_info *use : insn->uses ()) { def_info *def = use->def (); insn_info *parent_insn = def->insn (); - // Is this check needed? if (parent_insn == nullptr) continue; // If we depend on a dead instruction, clear current instruction uses. - bool shouldReset = false; + bool is_parent_marked = false; if (parent_insn->is_phi ()) { - shouldReset = bitmap_bit_p(mm_marked_phis, static_cast<phi_info *> (def)->uid ()); + auto phi = static_cast<phi_info *> (def); + is_parent_marked = bitmap_bit_p(mm_marked_phis, phi->uid ()); } else { - shouldReset = m_marked.get_bit(parent_insn->uid ()); + is_parent_marked = m_marked.get_bit(parent_insn->uid ()); } - if (shouldReset) { + if (!is_parent_marked) { 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; - // } } } } @@ -1714,10 +1663,6 @@ rtl_ssa_dce::sweep () auto change = insn_change::delete_insn (insn); to_delete.safe_push (std::move (change)); - - // If we use following way with reverse_nondebug_insns, not all insns seem - // to be deleted... - // crtl->ssa->change_insn(change); } auto_vec<insn_change *> changes (to_delete.length ()); @@ -1731,14 +1676,10 @@ rtl_ssa_dce::sweep () fprintf (dump_file, "DCE: finish sweep phase\n"); } -#include <iostream> - unsigned int rtl_ssa_dce::execute (function *fn) { calculate_dominance_info (CDI_DOMINATORS); - // internal compiler error: gcc.c-torture/execute/20040811-1.c - - // rtl_ssa::function_info::add_phi_nodes crtl->ssa = new rtl_ssa::function_info (fn); int real_max = 0, artificial_min = 0; std::size_t count = 0; @@ -1750,48 +1691,18 @@ rtl_ssa_dce::execute (function *fn) } m_marked.resize(artificial_min, real_max + 1); - // 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 << "count: " << count << '\n'; 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 ()); - // std::cout << "phi_node_max: " << phi_node_max << '\n'; mm_marked_phis = sbitmap_alloc(phi_node_max + 1); bitmap_clear(mm_marked_phis); - if (dump_file) - dump (dump_file, crtl->ssa); - - // std::cout << '\n' << function_name(cfun) << '\n'; - // std::cout << "HARD_FRAME_POINTER_IS_ARG_POINTER: " << - // HARD_FRAME_POINTER_IS_ARG_POINTER << '\n'; std::cout << - // "HARD_FRAME_POINTER_IS_FRAME_POINTER: " << - // HARD_FRAME_POINTER_IS_FRAME_POINTER << '\n'; std::cout << - // "HARD_FRAME_POINTER_REGNUM: " << HARD_FRAME_POINTER_REGNUM << '\n'; - // std::cout << "FRAME_POINTER_REGNUM: " << FRAME_POINTER_REGNUM << '\n'; - // std::cout << "fixed_regs[HARD_FRAME_POINTER_REGNUM]: " << - // (fixed_regs[HARD_FRAME_POINTER_REGNUM] == 1) << '\n'; std::cout << - // "fixed_regs[FRAME_POINTER_REGNUM]: " << (fixed_regs[FRAME_POINTER_REGNUM] - // == 1) << '\n'; std::cout << "global_regs[HARD_FRAME_POINTER_REGNUM]: " << - // (global_regs[HARD_FRAME_POINTER_REGNUM] == 1) << '\n'; std::cout << - // "global_regs[FRAME_POINTER_REGNUM]: " << (global_regs[FRAME_POINTER_REGNUM] - // == 1) << '\n'; std::cout << "frame_pointer_needed: " << - // frame_pointer_needed << '\n'; - mark (); if (MAY_HAVE_DEBUG_BIND_INSNS) - { - auto dead_phis = propagate_dead_phis(); - auto debugizable = find_debugizable(dead_phis); - debugize_insns(debugizable); - reset_dead_debug (); - } sweep (); free_dominance_info (CDI_DOMINATORS); @@ -1804,388 +1715,6 @@ rtl_ssa_dce::execute (function *fn) return 0; } -// mark instructions that depend on a dead phi -std::unordered_set<insn_info *> -rtl_ssa_dce::propagate_dead_phis () -{ - std::unordered_set<phi_info *> visited_dead_phis; - std::unordered_set<insn_info *> depends_on_dead_phi; - auto_vec<set_info *> worklist; - - // add dead phis to worklist - for (ebb_info *ebb : crtl->ssa->ebbs ()) - { - for (phi_info *phi : ebb->phis ()) - { - if (bitmap_bit_p (mm_marked_phis, phi->uid ())) - continue; - - worklist.safe_push (phi); - } - } - - // suppose that debug insns are marked - non marked will be removed later - // propagate dead phis via du chains and unmark reachable debug instructions - while (!worklist.is_empty ()) - { - set_info *set = worklist.pop (); - insn_info *insn = set->insn (); - - if (insn->is_debug_insn ()) - { - if (dump_file) - fprintf (dump_file, "Debug insns %d depends on dead phi.\n", - insn->uid ()); - - m_marked.clear_bit (insn->uid ()); - // debug instructions dont have chains - continue; - } - - // mark - if (insn->is_phi ()) - { - 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_checking_assert (!m_marked.get_bit (insn->uid ())); - depends_on_dead_phi.emplace (insn); - } - - for (use_info *use : set->all_uses ()) - { - if (use->is_in_phi ()) - { - // do not add already visited dead phis - if (visited_dead_phis.count (use->phi ()) == 0) - worklist.safe_push (use->phi ()); - } - else - { - gcc_assert (use->is_in_any_insn ()); - // add all defs from insn to worklist - for (def_info *def : use->insn ()->defs ()) - { - if (def->kind () != access_kind::SET) - continue; - - worklist.safe_push (static_cast<set_info *> (def)); - } - } - } - } - - return depends_on_dead_phi; -} - -void -rtl_ssa_dce::debugize_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; -} - -// visit every marked instruction in INSN dependency tree and unmark it -void -rtl_ssa_dce::unmark_debugizable (insn_info *insn, sbitmap debugizable) -{ - auto_vec<insn_info *> worklist; - 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 ()) { - 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) // skip clobbers - continue; - - 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); - } - } - } -} - -// return a bitmap which describes whether an instruction can be debugized -// - that means replaced with a debug instruction -sbitmap -rtl_ssa_dce::find_debugizable(const std::unordered_set<insn_info *> &depends_on_dead_phi) -{ - // 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 - 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 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 - - 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) - { - std::cerr << "FAILED TO CREATE DEBUG\n"; - unmark_debugizable(insn, debugizable); - continue; - } - - // 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); - std::cerr << "FAILED TO CREATE DEBUG\n"; - continue; - } - - def_info *def = *defs.begin (); - if (def->kind () != access_kind::SET) // Skip clobbers - continue; - - set_info *set = static_cast<set_info *> (def); - - // if some dependent is a debugizable - bool has_debug_uses = false; - for (use_info *use : set->all_uses()) - { - // skip phi nodes - if (use->is_in_phi ()) - continue; - - insn_info *use_insn = use->insn(); - if (use_insn->is_artificial ()) - continue; - - if (bitmap_bit_p(debugizable, use_insn->uid ())) { - has_debug_uses = true; - break; - } - } - // if (!set->has_nondebug_insn_uses ()) - if (!has_debug_uses) - continue; - - bitmap_set_bit (debugizable, insn->uid ()); - } - - 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 () || - insn->is_debug_insn() || - !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); - debug (change); - - if (!rtl_ssa::restrict_movement (change)) - std::cerr << "change move range location does not exists\n"; - crtl->ssa->change_insn(change); - // 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 - 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 - // 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 - // && (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) - // { - - // } - } - - sbitmap_free (debugizable); - // TODO: check that all of the debug insn uses are live, - // otherwise reset the instruction -} - -static void -test (insn_info *insn) -{ - // 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 -} - -// static auto_vec<insn_change> -// wip (std::unordered_set<insn_info *> &marked, -// std::unordered_set<phi_info *> &marked_phis) -// { -// std::unordered_set<insn_info *> depends_on_dead_phi = propagate_dead_phis (); -// for (insn_info *insn : crtl->ssa->all_insns ()) -// { -// if (insn->is_phi ()) // insn->is_artificial() ?? -// continue; - -// // skip marked instructions -// if (marked.count (insn) > 0) // debug instruction are still alive -// continue; - -// // we cannot create debug instruction if we depend on a dead phi -// if (depends_on_dead_phi.count (insn) > 0) -// continue; - -// // insn is nondebug and dead -// } -// } - -rtl_opt_pass * -make_pass_fast_rtl_dce (gcc::context *ctxt) -{ - return new pass_fast_rtl_dce (ctxt); -} - namespace { const pass_data pass_data_rtl_ssa_dce = { diff --git a/gcc/fwprop.cc b/gcc/fwprop.cc index 4ee44adcde29..ff7caaa8074c 100644 --- a/gcc/fwprop.cc +++ b/gcc/fwprop.cc @@ -905,7 +905,7 @@ fwprop_done (void) delete crtl->ssa; crtl->ssa = nullptr; - delete_trivially_dead_insns (get_insns (), max_reg_num ()); + // delete_trivially_dead_insns (get_insns (), max_reg_num ()); if (dump_file) fprintf (dump_file, diff --git a/gcc/passes.def b/gcc/passes.def index 2509f44bc5c7..a4cd1eb741b2 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -489,7 +489,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_inc_dec); NEXT_PASS (pass_initialize_regs); NEXT_PASS (pass_rtl_ssa_dce); - NEXT_PASS (pass_ud_rtl_dce); + // __NEXT_PAS (pass_ud_rtl_dce); NEXT_PASS (pass_ext_dce); NEXT_PASS (pass_combine); NEXT_PASS (pass_late_combine); @@ -532,7 +532,8 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_regrename); NEXT_PASS (pass_fold_mem_offsets); NEXT_PASS (pass_cprop_hardreg); - // NEXT_PASS (pass_rtl_ssa_dce); + NEXT_PASS (pass_rtl_ssa_dce); + NEXT_PASS (pass_ud_rtl_dce); // NEXT_PASS (pass_fast_rtl_dce); NEXT_PASS (pass_reorder_blocks); NEXT_PASS (pass_leaf_regs); diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc index aab6251d2bb1..eb89eb664de0 100644 --- a/gcc/rtl-ssa/changes.cc +++ b/gcc/rtl-ssa/changes.cc @@ -256,30 +256,20 @@ 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, auto_sbitmap &visited_phi_nodes) +function_info::process_uses_of_deleted_def (set_info *set) { if (!set->has_any_uses ()) return; - insn_info *set_insn = set->insn (); - if (set_insn && set_insn->is_phi()) { - auto *phi = static_cast<phi_info *> (set); - bitmap_set_bit (visited_phi_nodes, phi->uid ()); - } - auto *use = *set->all_uses ().begin (); do { auto *next_use = use->next_use (); if (use->is_in_phi ()) { - phi_info *phi = use->phi (); - if (bitmap_bit_p(visited_phi_nodes, phi->uid ())) { - remove_use (use); - } else { - process_uses_of_deleted_def (phi, visited_phi_nodes); - delete_phi (phi); - } + // This call will not recurse. + process_uses_of_deleted_def (use->phi ()); + delete_phi (use->phi ()); } else { @@ -870,11 +860,7 @@ function_info::change_insns (array_slice<insn_change *> changes) { auto *set = dyn_cast<set_info *> (def); if (set && set->has_any_uses ()) - { - auto_sbitmap visited_phis(m_next_phi_uid); - bitmap_clear(visited_phis); - process_uses_of_deleted_def (set, visited_phis); - } + process_uses_of_deleted_def (set); remove_def (def); } diff --git a/gcc/rtl-ssa/functions.h b/gcc/rtl-ssa/functions.h index 033154dfa586..2e20f5e47d72 100644 --- a/gcc/rtl-ssa/functions.h +++ b/gcc/rtl-ssa/functions.h @@ -306,7 +306,7 @@ private: bb_info *create_bb_info (basic_block); void append_bb (bb_info *); - void process_uses_of_deleted_def (set_info *set, auto_sbitmap &); + void process_uses_of_deleted_def (set_info *); insn_info *add_placeholder_after (insn_info *); void possibly_queue_changes (insn_change &); void finalize_new_accesses (insn_change &, insn_info *,