Index: gcc/dbgcnt.def =================================================================== --- gcc/dbgcnt.def (revision 119428) +++ gcc/dbgcnt.def (working copy) @@ -74,3 +74,10 @@ DEBUG_COUNTER (sched2_func) DEBUG_COUNTER (local_alloc_for_sched) DEBUG_COUNTER (split_for_sched2) DEBUG_COUNTER (ia64_sched2) +DEBUG_COUNTER (pre_insn) +DEBUG_COUNTER (sched_block) +DEBUG_COUNTER (sched_insn) +DEBUG_COUNTER (gcse2_delete) +DEBUG_COUNTER (cse2_move2add) +DEBUG_COUNTER (delete_trivial_dead) +DEBUG_COUNTER (postreload_cse) Index: gcc/postreload-gcse.c =================================================================== --- gcc/postreload-gcse.c (revision 119428) +++ gcc/postreload-gcse.c (working copy) @@ -46,6 +46,7 @@ Software Foundation, 51 Franklin Street, #include "target.h" #include "timevar.h" #include "tree-pass.h" +#include "dbgcnt.h" /* The following code implements gcse after reload, the purpose of this pass is to cleanup redundant loads generated by reload and other @@ -1290,7 +1291,7 @@ delete_redundant_insns_1 (void **slot, v for (occr = expr->avail_occr; occr != NULL; occr = occr->next) { - if (occr->deleted_p) + if (occr->deleted_p && dbg_cnt (gcse2_delete)) { delete_insn (occr->insn); stats.insns_deleted++; Index: gcc/postreload.c =================================================================== --- gcc/postreload.c (revision 119428) +++ gcc/postreload.c (working copy) @@ -47,6 +47,7 @@ Software Foundation, 51 Franklin Street, #include "timevar.h" #include "tree-pass.h" #include "df.h" +#include "dbgcnt.h" static int reload_cse_noop_set_p (rtx); static void reload_cse_simplify (rtx, rtx); @@ -1227,7 +1228,8 @@ reload_cse_move2add (rtx first) /* Check if we have valid information on the contents of this register in the mode of REG. */ if (reg_set_luid[regno] > move2add_last_label_luid - && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno])) + && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno]) + && dbg_cnt (cse2_move2add)) { /* Try to transform (set (REGX) (CONST_INT A)) ... @@ -1574,6 +1576,9 @@ gate_handle_postreload (void) static unsigned int rest_of_handle_postreload (void) { + if (!dbg_cnt (postreload_cse)) + return 0; + /* Do a very simple CSE pass over just the hard registers. */ reload_cse_regs (get_insns ()); /* Reload_cse_regs can eliminate potentially-trapping MEMs. Index: gcc/auto-inc-dec.c =================================================================== --- gcc/auto-inc-dec.c (revision 119428) +++ gcc/auto-inc-dec.c (working copy) @@ -452,39 +452,34 @@ static rtx * reg_next_def = NULL; static struct df *df = NULL; -/* Move notes that match PATTERN to TO_INSN from FROM_INSN. If - PATTERN is NULL, move all notes. */ +/* Move dead note that match PATTERN to TO_INSN from FROM_INSN. We do + not really care about moving any other notes from the inc or add + insn. Moving the REG_EQUAL and REG_EQUIV is clearly wrong and it + does not appear that there are any other kinds of relavant notes. */ static void -move_notes (rtx to_insn, rtx from_insn, rtx pattern) +move_dead_notes (rtx to_insn, rtx from_insn, rtx pattern) { rtx note; rtx next_note; rtx prev_note = NULL; - if (pattern) - for (note = REG_NOTES (from_insn); note; note = next_note) - { - next_note = XEXP (note, 1); - - if (pattern == XEXP (note, 0)) - { - XEXP (note, 1) = REG_NOTES (to_insn); - REG_NOTES (to_insn) = note; - if (prev_note) - XEXP (prev_note, 1) = next_note; - else - REG_NOTES (from_insn) = next_note; - } - else prev_note = note; - } - else - for (note = REG_NOTES (from_insn); note; note = next_note) - { - next_note = XEXP (note, 1); - XEXP (note, 1) = REG_NOTES (to_insn); - REG_NOTES (to_insn) = note; - } + for (note = REG_NOTES (from_insn); note; note = next_note) + { + next_note = XEXP (note, 1); + + if ((REG_NOTE_KIND(note) == REG_DEAD) + && pattern == XEXP (note, 0)) + { + XEXP (note, 1) = REG_NOTES (to_insn); + REG_NOTES (to_insn) = note; + if (prev_note) + XEXP (prev_note, 1) = next_note; + else + REG_NOTES (from_insn) = next_note; + } + else prev_note = note; + } } @@ -565,9 +560,9 @@ attempt_change (rtx new_addr_pat, rtx in switch (inc_insn.form) { case FORM_PRE_ADD: - move_notes (mem_insn.insn, inc_insn.insn, NULL); mov_insn = insert_move_insn_before (mem_insn.insn, inc_insn.reg_res, inc_insn.reg0); + move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0); regno = REGNO (inc_insn.reg_res); reg_next_def [regno] = mov_insn; @@ -583,7 +578,6 @@ attempt_change (rtx new_addr_pat, rtx in /* Fallthru. */ case FORM_PRE_INC: - move_notes (mem_insn.insn, inc_insn.insn, NULL); regno = REGNO (inc_insn.reg_res); reg_next_def [regno] = mem_insn.insn; reg_next_use [regno] = NULL; @@ -593,9 +587,7 @@ attempt_change (rtx new_addr_pat, rtx in case FORM_POST_ADD: mov_insn = insert_move_insn_before (mem_insn.insn, inc_insn.reg_res, inc_insn.reg0); - move_notes (mov_insn, inc_insn.insn, inc_insn.reg0); - move_notes (mem_insn.insn, inc_insn.insn, inc_insn.reg1); - move_notes (mem_insn.insn, inc_insn.insn, inc_insn.reg_res); + move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0); /* Do not move anything to the mov insn because the instruction pointer for the main iteration has not yet hit that. It is @@ -1096,7 +1088,20 @@ find_inc (bool first_try) { if (dump_file) fprintf (dump_file, - "result of inc is assigned to between mem and inc insns.\n"); + "result of add is assigned to between mem and inc insns.\n"); + return false; + } + + other_insn = get_next_ref (REGNO (inc_insn.reg_res), + BASIC_BLOCK (BLOCK_NUM (mem_insn.insn)), + reg_next_use); + if (other_insn + && (other_insn != inc_insn.insn) + && (DF_INSN_LUID (df, inc_insn.insn) > DF_INSN_LUID (df, other_insn))) + { + if (dump_file) + fprintf (dump_file, + "result of add is used between mem and inc insns.\n"); return false; } Index: gcc/haifa-sched.c =================================================================== --- gcc/haifa-sched.c (revision 119428) +++ gcc/haifa-sched.c (working copy) @@ -144,6 +144,7 @@ Software Foundation, 51 Franklin Street, #include "target.h" #include "output.h" #include "params.h" +#include "dbgcnt.h" #ifdef INSN_SCHEDULING @@ -2294,8 +2295,6 @@ schedule_block (basic_block *target_bb, there's nothing better to do (ready list is empty) but there are still vacant dispatch slots in the current cycle. */ if (sched_verbose >= 6) - fprintf(sched_dump,";;\t\tSecond chance\n"); - memcpy (temp_state, curr_state, dfa_state_size); if (early_queue_to_ready (temp_state, &ready)) ready_sort (&ready); } @@ -2305,6 +2304,23 @@ schedule_block (basic_block *target_bb, || !(*current_sched_info->schedule_more_p) ()) break; + if (dbg_cnt (sched_insn) == false) + { + insn = NEXT_INSN (last_scheduled_insn); + while ((*current_sched_info->schedule_more_p) ()) + { + (*current_sched_info->begin_schedule_ready) (insn, + last_scheduled_insn); + if (QUEUE_INDEX (insn) >= 0) + queue_remove (insn); + last_scheduled_insn = insn; + insn = NEXT_INSN (insn); + } + while (ready.n_ready) + ready_remove_first (&ready); + goto bail_out; + } + /* Select and remove the insn from the ready list. */ if (sort_p) { @@ -2462,6 +2478,7 @@ schedule_block (basic_block *target_bb, } } +bail_out: /* Debug info. */ if (sched_verbose) { Index: gcc/cse.c =================================================================== --- gcc/cse.c (revision 119428) +++ gcc/cse.c (working copy) @@ -44,6 +44,7 @@ Software Foundation, 51 Franklin Street, #include "params.h" #include "rtlhooks-def.h" #include "tree-pass.h" +#include "dbgcnt.h" /* The basic idea of common subexpression elimination is to go through the code, keeping a record of expressions that would @@ -6541,7 +6542,7 @@ delete_trivially_dead_insns (rtx insns, /* If this is a dead insn, delete it and show registers in it aren't being used. */ - if (! live_insn) + if (! live_insn && dbg_cnt (delete_trivial_dead)) { count_reg_usage (insn, counts, NULL_RTX, -1); delete_insn_and_edges (insn); Index: gcc/gcse.c =================================================================== --- gcc/gcse.c (revision 119428) +++ gcc/gcse.c (working copy) @@ -171,6 +171,7 @@ Software Foundation, 51 Franklin Street, #include "timevar.h" #include "tree-pass.h" #include "hashtab.h" +#include "dbgcnt.h" /* Propagate flow information through back edges and thus enable PRE's moving loop invariant calculations out of loops. @@ -4437,7 +4438,8 @@ pre_delete (void) /* We only delete insns that have a single_set. */ if (TEST_BIT (pre_delete_map[bb->index], indx) - && (set = single_set (insn)) != 0) + && (set = single_set (insn)) != 0 + && dbg_cnt (pre_insn)) { /* Create a pseudo-reg to store the result of reaching expressions into. Get the mode for the new pseudo from Index: gcc/Makefile.in =================================================================== --- gcc/Makefile.in (revision 119428) +++ gcc/Makefile.in (working copy) @@ -2342,7 +2342,8 @@ cselib.o : cselib.c $(CONFIG_H) $(SYSTEM cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \ hard-reg-set.h $(FLAGS_H) insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \ output.h $(FUNCTION_H) $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H) \ - except.h $(TARGET_H) $(PARAMS_H) rtlhooks-def.h tree-pass.h $(REAL_H) + except.h $(TARGET_H) $(PARAMS_H) rtlhooks-def.h tree-pass.h $(REAL_H) \ + $(DBGCNT_H) dce.o : dce.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) $(DF_H) cselib.h \ $(DBGCNT_H) dce.h timevar.h tree-pass.h @@ -2359,7 +2360,7 @@ gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(GGC_H) \ $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \ $(TM_P_H) $(PARAMS_H) except.h gt-gcse.h $(TREE_H) cselib.h $(TIMEVAR_H) \ - intl.h $(OBSTACK_H) tree-pass.h + intl.h $(OBSTACK_H) tree-pass.h $(DBGCNT_H) resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) \ coretypes.h $(TM_H) $(REGS_H) $(FLAGS_H) output.h $(RESOURCE_H) $(DF_H) \ $(FUNCTION_H) toplev.h $(INSN_ATTR_H) except.h $(PARAMS_H) $(TM_P_H) @@ -2536,7 +2537,7 @@ postreload-gcse.o : postreload-gcse.c $( $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \ $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \ $(TM_P_H) except.h $(TREE_H) $(TARGET_H) $(HASHTAB_H) intl.h $(OBSTACK_H) \ - $(PARAMS_H) $(TIMEVAR_H) tree-pass.h $(REAL_H) + $(PARAMS_H) $(TIMEVAR_H) tree-pass.h $(REAL_H) $(DBGCNT_H) caller-save.o : caller-save.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(FUNCTION_H) \ addresses.h $(RECOG_H) reload.h $(EXPR_H) toplev.h $(TM_P_H) @@ -2577,7 +2578,7 @@ modulo-sched.o : modulo-sched.c $(DDG_H) haifa-sched.o : haifa-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(FUNCTION_H) \ $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) $(TARGET_H) output.h \ - $(PARAMS_H) + $(PARAMS_H) $(DBGCNT_H) sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \ $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h cselib.h \ Index: gcc/sched-rgn.c =================================================================== --- gcc/sched-rgn.c (revision 119428) +++ gcc/sched-rgn.c (working copy) @@ -2800,9 +2800,16 @@ schedule_region (int rgn) current_sched_info->queue_must_finish_empty = current_nr_blocks == 1; curr_bb = first_bb; - schedule_block (&curr_bb, rgn_n_insns); - gcc_assert (EBB_FIRST_BB (bb) == first_bb); - sched_rgn_n_insns += sched_n_insns; + if (dbg_cnt (sched_block)) + { + schedule_block (&curr_bb, rgn_n_insns); + gcc_assert (EBB_FIRST_BB (bb) == first_bb); + sched_rgn_n_insns += sched_n_insns; + } + else + { + sched_rgn_n_insns += rgn_n_insns; + } /* Clean up. */ if (current_nr_blocks > 1) Index: gcc/dce.c =================================================================== --- gcc/dce.c (revision 119428) +++ gcc/dce.c (working copy) @@ -213,6 +213,46 @@ init_dce (bool fast) } +/* Delete all REG_EQUAL notes of the registers INSN writes, + to prevent bad dangling REG_EQUAL notes. */ + +static void +delete_corresponding_reg_equal_notes (rtx insn) +{ + struct df_ref *def; + for (def = DF_INSN_DEFS (dce_df, insn); def; def = DF_REF_NEXT_REF (def)) + { + struct df_ref *eq_use = DF_REG_EQ_USE_CHAIN (dce_df, DF_REF_REGNO (def)); + + if (eq_use) + { + rtx *insns = alloca (sizeof(rtx) + * DF_REG_EQ_USE_COUNT (dce_df, DF_REF_REGNO (def))); + rtx *p_insn = insns; + do + { + rtx note; + if (DF_REF_INSN (eq_use) != insn + && (note = find_reg_note (DF_REF_INSN (eq_use), + REG_EQUAL, NULL_RTX)) != NULL) + { + remove_note (DF_REF_INSN (eq_use), note); + /* We can't rescan while iterating over EQ_USE chain, + because rescanning invalidates EQ_USE chain. + Instead, we just keep the record of the insns. */ + *p_insn++ = DF_REF_INSN (eq_use); + } + } + while ((eq_use = DF_REF_NEXT_REG (eq_use)) != NULL); + + /* Now rescan insns that have REG_EQUAL note removed. */ + while (--p_insn >= insns) + df_insn_rescan (*p_insn); + } + } +} + + /* Delete every instruction that hasn't been marked. Clear the insn from DCE_DF if DF_DELETE is true. */ @@ -232,6 +272,11 @@ delete_unmarked_insns (void) if (dump_file) fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn)); /* XXX: This may need to be changed to delete_insn_and_edges */ + + /* Before we delete the insn, we have to delete + REG_EQUAL of the destination regs of the deleted insn + to prevent dangling REG_EQUAL. */ + delete_corresponding_reg_equal_notes (insn); delete_insn (insn); something_changed = true; }