Mercurial > hg > CbC > CbC_gcc
diff gcc/dce.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
line wrap: on
line diff
--- a/gcc/dce.c Sun Aug 21 07:07:55 2011 +0900 +++ b/gcc/dce.c Fri Oct 27 22:46:09 2017 +0900 @@ -1,6 +1,5 @@ /* RTL dead code elimination. - Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2005-2017 Free Software Foundation, Inc. This file is part of GCC. @@ -21,22 +20,21 @@ #include "config.h" #include "system.h" #include "coretypes.h" -#include "hashtab.h" -#include "tm.h" +#include "backend.h" #include "rtl.h" #include "tree.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "flags.h" -#include "except.h" +#include "predict.h" #include "df.h" -#include "cselib.h" +#include "memmodel.h" +#include "tm_p.h" +#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */ +#include "cfgrtl.h" +#include "cfgbuild.h" +#include "cfgcleanup.h" #include "dce.h" -#include "timevar.h" +#include "valtrack.h" #include "tree-pass.h" #include "dbgcnt.h" -#include "tm_p.h" -#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */ /* ------------------------------------------------------------------------- @@ -47,9 +45,12 @@ we don't want to reenter it. */ static bool df_in_progress = false; +/* True if we are allowed to alter the CFG in this pass. */ +static bool can_alter_cfg = false; + /* Instructions that have been marked but whose dependencies have not yet been processed. */ -static VEC(rtx,heap) *worklist; +static vec<rtx_insn *> worklist; /* Bitmap of instructions marked as needed indexed by INSN_UID. */ static sbitmap marked; @@ -58,7 +59,7 @@ static bitmap_obstack dce_blocks_bitmap_obstack; static bitmap_obstack dce_tmp_bitmap_obstack; -static bool find_call_stack_args (rtx, bool, bool, bitmap); +static bool find_call_stack_args (rtx_call_insn *, bool, bool, bitmap); /* A subroutine for which BODY is part of the instruction being tested; either the top-level pattern, or an element of a PARALLEL. The @@ -90,10 +91,11 @@ the DCE pass. */ static bool -deletable_insn_p (rtx insn, bool fast, bitmap arg_stores) +deletable_insn_p (rtx_insn *insn, bool fast, bitmap arg_stores) { rtx body, x; int i; + df_ref def; if (CALL_P (insn) /* We cannot delete calls inside of the recursive dce because @@ -107,16 +109,28 @@ infinite loop. */ && (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) - return find_call_stack_args (insn, false, fast, arg_stores); + return find_call_stack_args (as_a <rtx_call_insn *> (insn), false, + fast, arg_stores); /* Don't delete jumps, notes and the like. */ if (!NONJUMP_INSN_P (insn)) return false; - /* Don't delete insns that can throw. */ - if (!insn_nothrow_p (insn)) + /* Don't delete insns that may throw if we cannot do so. */ + if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) + && !insn_nothrow_p (insn)) return false; + /* If INSN sets a global_reg, leave it untouched. */ + FOR_EACH_INSN_DEF (def, insn) + if (HARD_REGISTER_NUM_P (DF_REF_REGNO (def)) + && global_regs[DF_REF_REGNO (def)]) + return false; + /* Initialization of pseudo PIC register should never be removed. */ + else if (DF_REF_REG (def) == pic_offset_table_rtx + && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER) + return false; + body = PATTERN (insn); switch (GET_CODE (body)) { @@ -154,12 +168,12 @@ /* Return true if INSN has been marked as needed. */ static inline int -marked_insn_p (rtx insn) +marked_insn_p (rtx_insn *insn) { /* Artificial defs are always needed and they do not have an insn. We should never see them here. */ gcc_assert (insn); - return TEST_BIT (marked, INSN_UID (insn)); + return bitmap_bit_p (marked, INSN_UID (insn)); } @@ -167,13 +181,13 @@ the worklist. */ static void -mark_insn (rtx insn, bool fast) +mark_insn (rtx_insn *insn, bool fast) { if (!marked_insn_p (insn)) { if (!fast) - VEC_safe_push (rtx, heap, worklist, insn); - SET_BIT (marked, INSN_UID (insn)); + worklist.safe_push (insn); + bitmap_set_bit (marked, INSN_UID (insn)); if (dump_file) fprintf (dump_file, " Adding insn %d to worklist\n", INSN_UID (insn)); if (CALL_P (insn) @@ -181,7 +195,7 @@ && !SIBLING_CALL_P (insn) && (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) - find_call_stack_args (insn, true, fast, NULL); + find_call_stack_args (as_a <rtx_call_insn *> (insn), true, fast, NULL); } } @@ -193,7 +207,7 @@ mark_nonreg_stores_1 (rtx dest, const_rtx pattern, void *data) { if (GET_CODE (pattern) != CLOBBER && !REG_P (dest)) - mark_insn ((rtx) data, true); + mark_insn ((rtx_insn *) data, true); } @@ -204,14 +218,14 @@ mark_nonreg_stores_2 (rtx dest, const_rtx pattern, void *data) { if (GET_CODE (pattern) != CLOBBER && !REG_P (dest)) - mark_insn ((rtx) data, false); + mark_insn ((rtx_insn *) data, false); } /* Mark INSN if BODY stores to a non-register destination. */ static void -mark_nonreg_stores (rtx body, rtx insn, bool fast) +mark_nonreg_stores (rtx body, rtx_insn *insn, bool fast) { if (fast) note_stores (body, mark_nonreg_stores_1, insn); @@ -220,16 +234,17 @@ } -/* Return true if store to MEM, starting OFF bytes from stack pointer, +/* Return true if a store to SIZE bytes, starting OFF bytes from stack pointer, is a call argument store, and clear corresponding bits from SP_BYTES bitmap if it is. */ static bool -check_argument_store (rtx mem, HOST_WIDE_INT off, HOST_WIDE_INT min_sp_off, - HOST_WIDE_INT max_sp_off, bitmap sp_bytes) +check_argument_store (HOST_WIDE_INT size, HOST_WIDE_INT off, + HOST_WIDE_INT min_sp_off, HOST_WIDE_INT max_sp_off, + bitmap sp_bytes) { HOST_WIDE_INT byte; - for (byte = off; byte < off + GET_MODE_SIZE (GET_MODE (mem)); byte++) + for (byte = off; byte < off + size; byte++) { if (byte < min_sp_off || byte >= max_sp_off @@ -248,10 +263,11 @@ going to be marked called again with DO_MARK true. */ static bool -find_call_stack_args (rtx call_insn, bool do_mark, bool fast, +find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, bitmap arg_stores) { - rtx p, insn, prev_insn; + rtx p; + rtx_insn *insn, *prev_insn; bool ret; HOST_WIDE_INT min_sp_off, max_sp_off; bitmap sp_bytes; @@ -275,11 +291,11 @@ if (GET_CODE (XEXP (p, 0)) == USE && MEM_P (XEXP (XEXP (p, 0), 0))) { - rtx mem = XEXP (XEXP (p, 0), 0), addr, size; - HOST_WIDE_INT off = 0; + rtx mem = XEXP (XEXP (p, 0), 0), addr; + HOST_WIDE_INT off = 0, size; + if (!MEM_SIZE_KNOWN_P (mem)) + return false; size = MEM_SIZE (mem); - if (size == NULL_RTX) - return false; addr = XEXP (mem, 0); if (GET_CODE (addr) == PLUS && REG_P (XEXP (addr, 0)) @@ -296,18 +312,18 @@ sp + offset. */ if (!fast) { - df_ref *use_rec; + df_ref use; struct df_link *defs; rtx set; - for (use_rec = DF_INSN_USES (call_insn); *use_rec; use_rec++) - if (rtx_equal_p (addr, DF_REF_REG (*use_rec))) + FOR_EACH_INSN_USE (use, call_insn) + if (rtx_equal_p (addr, DF_REF_REG (use))) break; - if (*use_rec == NULL) + if (use == NULL) return false; - for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next) + for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) if (! DF_REF_IS_ARTIFICIAL (defs->ref)) break; @@ -329,7 +345,7 @@ return false; } min_sp_off = MIN (min_sp_off, off); - max_sp_off = MAX (max_sp_off, off + INTVAL (size)); + max_sp_off = MAX (max_sp_off, off + size); } if (min_sp_off >= max_sp_off) @@ -355,22 +371,22 @@ } if (addr != stack_pointer_rtx) { - df_ref *use_rec; + df_ref use; struct df_link *defs; rtx set; - for (use_rec = DF_INSN_USES (call_insn); *use_rec; use_rec++) - if (rtx_equal_p (addr, DF_REF_REG (*use_rec))) + FOR_EACH_INSN_USE (use, call_insn) + if (rtx_equal_p (addr, DF_REF_REG (use))) break; - for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next) + for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) if (! DF_REF_IS_ARTIFICIAL (defs->ref)) break; set = single_set (DF_REF_INSN (defs->ref)); off += INTVAL (XEXP (SET_SRC (set), 1)); } - for (byte = off; byte < off + INTVAL (MEM_SIZE (mem)); byte++) + for (byte = off; byte < off + MEM_SIZE (mem); byte++) { if (!bitmap_set_bit (sp_bytes, byte - min_sp_off)) gcc_unreachable (); @@ -387,7 +403,7 @@ HOST_WIDE_INT off; if (insn == BB_HEAD (BLOCK_FOR_INSN (call_insn))) - prev_insn = NULL_RTX; + prev_insn = NULL; else prev_insn = PREV_INSN (insn); @@ -420,18 +436,18 @@ break; if (!fast) { - df_ref *use_rec; + df_ref use; struct df_link *defs; rtx set; - for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) - if (rtx_equal_p (addr, DF_REF_REG (*use_rec))) + FOR_EACH_INSN_USE (use, insn) + if (rtx_equal_p (addr, DF_REF_REG (use))) break; - if (*use_rec == NULL) + if (use == NULL) break; - for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next) + for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) if (! DF_REF_IS_ARTIFICIAL (defs->ref)) break; @@ -453,8 +469,8 @@ break; } - if (GET_MODE_SIZE (GET_MODE (mem)) == 0 - || !check_argument_store (mem, off, min_sp_off, + if (!MEM_SIZE_KNOWN_P (mem) + || !check_argument_store (MEM_SIZE (mem), off, min_sp_off, max_sp_off, sp_bytes)) break; @@ -485,14 +501,51 @@ writes to. */ static void -remove_reg_equal_equiv_notes_for_defs (rtx insn) +remove_reg_equal_equiv_notes_for_defs (rtx_insn *insn) { - df_ref *def_rec; + df_ref def; - for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) - remove_reg_equal_equiv_notes_for_regno (DF_REF_REGNO (*def_rec)); + FOR_EACH_INSN_DEF (def, insn) + remove_reg_equal_equiv_notes_for_regno (DF_REF_REGNO (def)); } +/* Scan all BBs for debug insns and reset those that reference values + defined in unmarked insns. */ + +static void +reset_unmarked_insns_debug_uses (void) +{ + basic_block bb; + rtx_insn *insn, *next; + + FOR_EACH_BB_REVERSE_FN (bb, cfun) + FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next) + if (DEBUG_INSN_P (insn)) + { + df_ref use; + + FOR_EACH_INSN_USE (use, insn) + { + struct df_link *defs; + for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) + { + rtx_insn *ref_insn; + if (DF_REF_IS_ARTIFICIAL (defs->ref)) + continue; + ref_insn = DF_REF_INSN (defs->ref); + if (!marked_insn_p (ref_insn)) + break; + } + if (!defs) + continue; + /* ??? FIXME could we propagate the values assigned to + each of the DEFs? */ + INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC (); + df_insn_rescan_debug_internal (insn); + break; + } + } +} /* Delete every instruction that hasn't been marked. */ @@ -500,12 +553,12 @@ delete_unmarked_insns (void) { basic_block bb; - rtx insn, next; + rtx_insn *insn, *next; bool must_clean = false; - FOR_EACH_BB_REVERSE (bb) + FOR_EACH_BB_REVERSE_FN (bb, cfun) FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next) - if (INSN_P (insn)) + if (NONDEBUG_INSN_P (insn)) { /* Always delete no-op moves. */ if (noop_move_p (insn)) @@ -536,6 +589,15 @@ if (!dbg_cnt (dce)) continue; + if (crtl->shrink_wrapped_separate + && find_reg_note (insn, REG_CFA_RESTORE, NULL)) + { + if (dump_file) + fprintf (dump_file, "DCE: NOT deleting insn %d, it's a " + "callee-save restore\n", INSN_UID (insn)); + continue; + } + if (dump_file) fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn)); @@ -567,7 +629,7 @@ prescan_insns_for_dce (bool fast) { basic_block bb; - rtx insn, prev; + rtx_insn *insn, *prev; bitmap arg_stores = NULL; if (dump_file) @@ -576,10 +638,10 @@ if (!df_in_progress && ACCUMULATE_OUTGOING_ARGS) arg_stores = BITMAP_ALLOC (NULL); - FOR_EACH_BB (bb) + FOR_EACH_BB_FN (bb, cfun) { FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev) - if (INSN_P (insn)) + if (NONDEBUG_INSN_P (insn)) { /* Don't mark argument stores now. They will be marked if needed when the associated CALL is marked. */ @@ -614,33 +676,29 @@ { basic_block bb; struct df_link *defs; - df_ref *use_rec; + df_ref use; - FOR_ALL_BB (bb) - { - for (use_rec = df_get_artificial_uses (bb->index); - *use_rec; use_rec++) - for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next) - if (! DF_REF_IS_ARTIFICIAL (defs->ref)) - mark_insn (DF_REF_INSN (defs->ref), false); - } + FOR_ALL_BB_FN (bb, cfun) + FOR_EACH_ARTIFICIAL_USE (use, bb->index) + for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) + if (!DF_REF_IS_ARTIFICIAL (defs->ref)) + mark_insn (DF_REF_INSN (defs->ref), false); } /* Mark every instruction that defines a register value that INSN uses. */ static void -mark_reg_dependencies (rtx insn) +mark_reg_dependencies (rtx_insn *insn) { struct df_link *defs; - df_ref *use_rec; + df_ref use; if (DEBUG_INSN_P (insn)) return; - for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) + FOR_EACH_INSN_USE (use, insn) { - df_ref use = *use_rec; if (dump_file) { fprintf (dump_file, "Processing use of "); @@ -662,7 +720,10 @@ if (!df_in_progress) { if (!fast) - df_chain_add_problem (DF_UD_CHAIN); + { + df_set_flags (DF_RD_PRUNE_DEAD_DEFS); + df_chain_add_problem (DF_UD_CHAIN); + } df_analyze (); } @@ -673,10 +734,13 @@ { bitmap_obstack_initialize (&dce_blocks_bitmap_obstack); bitmap_obstack_initialize (&dce_tmp_bitmap_obstack); + can_alter_cfg = false; } + else + can_alter_cfg = true; marked = sbitmap_alloc (get_max_uid () + 1); - sbitmap_zero (marked); + bitmap_clear (marked); } @@ -700,18 +764,21 @@ static unsigned int rest_of_handle_ud_dce (void) { - rtx insn; + rtx_insn *insn; init_dce (false); prescan_insns_for_dce (false); mark_artificial_uses (); - while (VEC_length (rtx, worklist) > 0) + while (worklist.length () > 0) { - insn = VEC_pop (rtx, worklist); + insn = worklist.pop (); mark_reg_dependencies (insn); } - VEC_free (rtx, heap, worklist); + worklist.release (); + + if (MAY_HAVE_DEBUG_INSNS) + reset_unmarked_insns_debug_uses (); /* Before any insns are deleted, we must remove the chains since they are not bidirectional. */ @@ -723,33 +790,48 @@ } -static bool -gate_ud_dce (void) +namespace { + +const pass_data pass_data_ud_rtl_dce = { - return optimize > 1 && flag_dce - && dbg_cnt (dce_ud); -} + RTL_PASS, /* type */ + "ud_dce", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_DCE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_df_finish, /* todo_flags_finish */ +}; -struct rtl_opt_pass pass_ud_rtl_dce = +class pass_ud_rtl_dce : public rtl_opt_pass { - { - RTL_PASS, - "ud dce", /* name */ - gate_ud_dce, /* gate */ - rest_of_handle_ud_dce, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_DCE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_dump_func | - TODO_df_finish | TODO_verify_rtl_sharing | - TODO_ggc_collect /* todo_flags_finish */ - } -}; +public: + pass_ud_rtl_dce (gcc::context *ctxt) + : rtl_opt_pass (pass_data_ud_rtl_dce, ctxt) + {} + + /* opt_pass methods: */ + virtual bool gate (function *) + { + return optimize > 1 && flag_dce && dbg_cnt (dce_ud); + } + + virtual unsigned int execute (function *) + { + return rest_of_handle_ud_dce (); + } + +}; // class pass_ud_rtl_dce + +} // anon namespace + +rtl_opt_pass * +make_pass_ud_rtl_dce (gcc::context *ctxt) +{ + return new pass_ud_rtl_dce (ctxt); +} /* ------------------------------------------------------------------------- @@ -759,14 +841,17 @@ /* Process basic block BB. Return true if the live_in set has changed. REDO_OUT is true if the info at the bottom of the block needs to be recalculated before starting. AU is the proper set of - artificial uses. */ + artificial uses. Track global substitution of uses of dead pseudos + in debug insns using GLOBAL_DEBUG. */ static bool -word_dce_process_block (basic_block bb, bool redo_out) +word_dce_process_block (basic_block bb, bool redo_out, + struct dead_debug_global *global_debug) { bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); - rtx insn; + rtx_insn *insn; bool block_changed; + struct dead_debug_local debug; if (redo_out) { @@ -788,11 +873,24 @@ } bitmap_copy (local_live, DF_WORD_LR_OUT (bb)); + dead_debug_local_init (&debug, NULL, global_debug); FOR_BB_INSNS_REVERSE (bb, insn) - if (NONDEBUG_INSN_P (insn)) + if (DEBUG_INSN_P (insn)) + { + df_ref use; + FOR_EACH_INSN_USE (use, insn) + if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER + && (GET_MODE_SIZE (GET_MODE (DF_REF_REAL_REG (use))) + == 2 * UNITS_PER_WORD) + && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (use)) + && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (use) + 1)) + dead_debug_add (&debug, use, DF_REF_REGNO (use)); + } + else if (INSN_P (insn)) { bool any_changed; + /* No matter if the instruction is needed or not, we remove any regno in the defs from the live set. */ any_changed = df_word_lr_simulate_defs (insn, local_live); @@ -804,6 +902,22 @@ if (marked_insn_p (insn)) df_word_lr_simulate_uses (insn, local_live); + /* Insert debug temps for dead REGs used in subsequent debug + insns. We may have to emit a debug temp even if the insn + was marked, in case the debug use was after the point of + death. */ + if (debug.used && !bitmap_empty_p (debug.used)) + { + df_ref def; + + FOR_EACH_INSN_DEF (def, insn) + dead_debug_insert_temp (&debug, DF_REF_REGNO (def), insn, + marked_insn_p (insn) + && !control_flow_insn_p (insn) + ? DEBUG_TEMP_AFTER_WITH_REG_FORCE + : DEBUG_TEMP_BEFORE_WITH_VALUE); + } + if (dump_file) { fprintf (dump_file, "finished processing insn %d live out = ", @@ -816,6 +930,7 @@ if (block_changed) bitmap_copy (DF_WORD_LR_IN (bb), local_live); + dead_debug_local_finish (&debug, NULL); BITMAP_FREE (local_live); return block_changed; } @@ -824,15 +939,18 @@ /* Process basic block BB. Return true if the live_in set has changed. REDO_OUT is true if the info at the bottom of the block needs to be recalculated before starting. AU is the proper set of - artificial uses. */ + artificial uses. Track global substitution of uses of dead pseudos + in debug insns using GLOBAL_DEBUG. */ static bool -dce_process_block (basic_block bb, bool redo_out, bitmap au) +dce_process_block (basic_block bb, bool redo_out, bitmap au, + struct dead_debug_global *global_debug) { bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); - rtx insn; + rtx_insn *insn; bool block_changed; - df_ref *def_rec; + df_ref def; + struct dead_debug_local debug; if (redo_out) { @@ -856,17 +974,26 @@ bitmap_copy (local_live, DF_LR_OUT (bb)); df_simulate_initialize_backwards (bb, local_live); + dead_debug_local_init (&debug, NULL, global_debug); FOR_BB_INSNS_REVERSE (bb, insn) - if (INSN_P (insn)) + if (DEBUG_INSN_P (insn)) + { + df_ref use; + FOR_EACH_INSN_USE (use, insn) + if (!bitmap_bit_p (local_live, DF_REF_REGNO (use)) + && !bitmap_bit_p (au, DF_REF_REGNO (use))) + dead_debug_add (&debug, use, DF_REF_REGNO (use)); + } + else if (INSN_P (insn)) { bool needed = marked_insn_p (insn); /* The insn is needed if there is someone who uses the output. */ if (!needed) - for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) - if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec)) - || bitmap_bit_p (au, DF_REF_REGNO (*def_rec))) + FOR_EACH_INSN_DEF (def, insn) + if (bitmap_bit_p (local_live, DF_REF_REGNO (def)) + || bitmap_bit_p (au, DF_REF_REGNO (def))) { needed = true; mark_insn (insn, true); @@ -881,8 +1008,20 @@ anything in local_live. */ if (needed) df_simulate_uses (insn, local_live); + + /* Insert debug temps for dead REGs used in subsequent debug + insns. We may have to emit a debug temp even if the insn + was marked, in case the debug use was after the point of + death. */ + if (debug.used && !bitmap_empty_p (debug.used)) + FOR_EACH_INSN_DEF (def, insn) + dead_debug_insert_temp (&debug, DF_REF_REGNO (def), insn, + needed && !control_flow_insn_p (insn) + ? DEBUG_TEMP_AFTER_WITH_REG_FORCE + : DEBUG_TEMP_BEFORE_WITH_VALUE); } + dead_debug_local_finish (&debug, NULL); df_simulate_finalize_backwards (bb, local_live); block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb)); @@ -919,12 +1058,15 @@ bitmap au = &df->regular_block_artificial_uses; bitmap au_eh = &df->eh_block_artificial_uses; int i; + struct dead_debug_global global_debug; prescan_insns_for_dce (true); for (i = 0; i < n_blocks; i++) bitmap_set_bit (all_blocks, postorder[i]); + dead_debug_global_init (&global_debug, NULL); + while (global_changed) { global_changed = false; @@ -932,7 +1074,7 @@ for (i = 0; i < n_blocks; i++) { int index = postorder[i]; - basic_block bb = BASIC_BLOCK (index); + basic_block bb = BASIC_BLOCK_FOR_FN (cfun, index); bool local_changed; if (index < NUM_FIXED_BLOCKS) @@ -943,11 +1085,13 @@ if (word_level) local_changed - = word_dce_process_block (bb, bitmap_bit_p (redo_out, index)); + = word_dce_process_block (bb, bitmap_bit_p (redo_out, index), + &global_debug); else local_changed = dce_process_block (bb, bitmap_bit_p (redo_out, index), - bb_has_eh_pred (bb) ? au_eh : au); + bb_has_eh_pred (bb) ? au_eh : au, + &global_debug); bitmap_set_bit (processed, index); if (local_changed) @@ -975,7 +1119,7 @@ /* So something was deleted that requires a redo. Do it on the cheap. */ delete_unmarked_insns (); - sbitmap_zero (marked); + bitmap_clear (marked); bitmap_clear (processed); bitmap_clear (redo_out); @@ -995,6 +1139,8 @@ } } + dead_debug_global_finish (&global_debug, NULL); + delete_unmarked_insns (); BITMAP_FREE (processed); @@ -1075,30 +1221,45 @@ } -static bool -gate_fast_dce (void) +namespace { + +const pass_data pass_data_fast_rtl_dce = { - return optimize > 0 && flag_dce - && dbg_cnt (dce_fast); -} + RTL_PASS, /* type */ + "rtl_dce", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_DCE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_df_finish, /* todo_flags_finish */ +}; -struct rtl_opt_pass pass_fast_rtl_dce = +class pass_fast_rtl_dce : public rtl_opt_pass { - { - RTL_PASS, - "rtl dce", /* name */ - gate_fast_dce, /* gate */ - rest_of_handle_fast_dce, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_DCE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_dump_func | - TODO_df_finish | TODO_verify_rtl_sharing | - TODO_ggc_collect /* todo_flags_finish */ - } -}; +public: + pass_fast_rtl_dce (gcc::context *ctxt) + : rtl_opt_pass (pass_data_fast_rtl_dce, ctxt) + {} + + /* opt_pass methods: */ + virtual bool gate (function *) + { + return optimize > 0 && flag_dce && dbg_cnt (dce_fast); + } + + virtual unsigned int execute (function *) + { + return rest_of_handle_fast_dce (); + } + +}; // class pass_fast_rtl_dce + +} // anon namespace + +rtl_opt_pass * +make_pass_fast_rtl_dce (gcc::context *ctxt) +{ + return new pass_fast_rtl_dce (ctxt); +}