This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [dataflow]: PATCH: fix regressions on IA64/PPC, add more debug points.
- From: Kenneth Zadeck <zadeck at naturalbridge dot com>
- To: Seongbae Park <seongbae dot park at gmail dot com>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>, Daniel Berlin <dberlin at dberlin dot org>
- Date: Fri, 01 Dec 2006 21:18:24 -0500
- Subject: Re: [dataflow]: PATCH: fix regressions on IA64/PPC, add more debug points.
- References: <ab3a61990612011609p5be2f7tfff3e0be3efdc744@mail.gmail.com>
Ok to check in.
kenny.
Seongbae Park wrote:
> Bootstrapped and regression tested on x86, x86-64, PPC and ia64.
> This patch clears up all dataflow branch regressions on above platforms,
> except a few extra regressions on x86 (32bit) due to a latent bug
> which Ken Zadeck is already working on.
>
>
> 2006-12-01 Seongbae Park <seongbae.park@gmail.com>
>
> * dbgcnt.def: New counters
> * postreload-gcse.c (delete_redundant_insns_1): New
> debug counter point.
> * postreload.c (reload_cse_move2add, gate_handle_postreload):
> New debug counter point.
> * auto-inc-dec.c (move_notes): Removed.
> (move_dead_notes): New function.
> (attempt_change): Call move_dead_notes(). Add missing
> dependency check.
> * haifa-sched.c (schedule_block): New debug counter point.
> * cse.c (delete_trivially_dead_insns): New debug counter point.
> * gcse.c (pre_delete): New debug counter point.
> * Makefile.in: Adding dependency on DBGCNT_H.
> * sched-rgn.c (schedule_region): New debug counter point.
> * dce.c (delete_corresponding_reg_equal_notes): New function
> (delete_unmarked_insns): Call
> delete_corresponding_reg_equal_notes.
>
> ------------------------------------------------------------------------
>
> 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;
> }
>