This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[dataflow] Don't rescan everything after CSE
- From: Paolo Bonzini <paolo dot bonzini at lu dot unisi dot ch>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Kenneth Zadeck <zadeck at naturalbridge dot com>
- Date: Tue, 06 Mar 2007 15:22:38 +0100
- Subject: [dataflow] Don't rescan everything after CSE
- Reply-to: bonzini at gnu dot org
This saves ~1% of compilation time.
More ideas that I have, but did not implement are:
1) delay computation of LR/UR until where we did it in the trunk. fwprop and GCSE do not need it, for example.
2) don't update REG_DEAD/REG_UNUSED notes for patches that don't need it. Updating them could/should be a changeable flag.
Bootstrapped/regtested i686-pc-linux-gnu.
Paolo
2007-03-06 Paolo Bonzini <bonzini@gnu.org>
* cse.c (validate_canon_reg): Don't do anything if *XLOC is NULL. Assert
it is only called with insn != 0 and it never resets something non-NULL to
NULL. Always use validate_change.
(cse_insn): Always call canon_reg with an INSN except when it is used on
a REG. When processing notes, first canonicalize, then fold, and call
df_notes_rescan.
(cse_process_notes): Rename to cse_process_notes_1, add CHANGED parameter.
(cse_process_notes_1): Wrapper around cse_process_notes to set the CHANGED
parameter.
(cse_extended_basic_block): Adjust call to cse_process_notes and use result
to call df_notes_rescan.
(cse_main): Set deferred insn rescanning flag, don't rescan on exit.
(pass_cse2): Add TODO_df_finish.
* gcse.c (pass_gcse): Likewise.
Index: cse.c
===================================================================
--- cse.c (revision 122403)
+++ cse.c (working copy)
@@ -585,7 +585,7 @@ static void record_jump_cond (enum rtx_c
static void cse_insn (rtx, rtx);
static void cse_prescan_path (struct cse_basic_block_data *);
static void invalidate_from_clobbers (rtx);
-static rtx cse_process_notes (rtx, rtx);
+static rtx cse_process_notes (rtx, rtx, bool *);
static void cse_extended_basic_block (struct cse_basic_block_data *);
static void count_reg_usage (rtx, int *, rtx, int);
static int check_for_label_ref (rtx *, void *);
@@ -2642,14 +2642,15 @@ cse_rtx_varies_p (rtx x, int from_alias)
static void
validate_canon_reg (rtx *xloc, rtx insn)
{
- rtx new = canon_reg (*xloc, insn);
+ if (*xloc)
+ {
+ rtx new = canon_reg (*xloc, insn);
- /* If replacing pseudo with hard reg or vice versa, ensure the
- insn remains valid. Likewise if the insn has MATCH_DUPs. */
- if (insn != 0 && new != 0)
- validate_change (insn, xloc, new, 1);
- else
- *xloc = new;
+ /* If replacing pseudo with hard reg or vice versa, ensure the
+ insn remains valid. Likewise if the insn has MATCH_DUPs. */
+ gcc_assert (insn && new);
+ validate_change (insn, xloc, new, 1);
+ }
}
/* Canonicalize an expression:
@@ -4119,12 +4120,12 @@ cse_insn (rtx insn, rtx libcall_insn)
This does nothing when a register is clobbered
because we have already invalidated the reg. */
if (MEM_P (XEXP (y, 0)))
- canon_reg (XEXP (y, 0), NULL_RTX);
+ canon_reg (XEXP (y, 0), insn);
}
else if (GET_CODE (y) == USE
&& ! (REG_P (XEXP (y, 0))
&& REGNO (XEXP (y, 0)) < FIRST_PSEUDO_REGISTER))
- canon_reg (y, NULL_RTX);
+ canon_reg (y, insn);
else if (GET_CODE (y) == CALL)
{
/* The result of apply_change_group can be ignored; see
@@ -4138,14 +4139,14 @@ cse_insn (rtx insn, rtx libcall_insn)
else if (GET_CODE (x) == CLOBBER)
{
if (MEM_P (XEXP (x, 0)))
- canon_reg (XEXP (x, 0), NULL_RTX);
+ canon_reg (XEXP (x, 0), insn);
}
/* Canonicalize a USE of a pseudo register or memory location. */
else if (GET_CODE (x) == USE
&& ! (REG_P (XEXP (x, 0))
&& REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER))
- canon_reg (XEXP (x, 0), NULL_RTX);
+ canon_reg (XEXP (x, 0), insn);
else if (GET_CODE (x) == CALL)
{
/* The result of apply_change_group can be ignored; see canon_reg. */
@@ -4163,8 +4164,12 @@ cse_insn (rtx insn, rtx libcall_insn)
&& (! rtx_equal_p (XEXP (tem, 0), SET_SRC (sets[0].rtl))
|| GET_CODE (SET_DEST (sets[0].rtl)) == STRICT_LOW_PART))
{
- src_eqv = fold_rtx (canon_reg (XEXP (tem, 0), NULL_RTX), insn);
+ /* The result of apply_change_group can be ignored; see canon_reg. */
+ canon_reg (XEXP (tem, 0), insn);
+ apply_change_group ();
+ src_eqv = fold_rtx (XEXP (tem, 0), insn);
XEXP (tem, 0) = src_eqv;
+ df_notes_rescan (insn);
}
/* Canonicalize sources and addresses of destinations.
@@ -4829,6 +4834,7 @@ cse_insn (rtx insn, rtx libcall_insn)
XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0),
sets[i].orig_src,
copy_rtx (new));
+ df_notes_rescan (libcall_insn);
}
/* The result of apply_change_group can be ignored; see
@@ -4947,6 +4953,7 @@ cse_insn (rtx insn, rtx libcall_insn)
/* Record the actual constant value in a REG_EQUAL note,
making a new one if one does not already exist. */
set_unique_reg_note (insn, REG_EQUAL, src_const);
+ df_notes_rescan (insn);
}
}
@@ -5683,7 +5690,7 @@ invalidate_from_clobbers (rtx x)
Return the replacement for X. */
static rtx
-cse_process_notes (rtx x, rtx object)
+cse_process_notes_1 (rtx x, rtx object, bool *changed)
{
enum rtx_code code = GET_CODE (x);
const char *fmt = GET_RTX_FORMAT (code);
@@ -5704,22 +5711,22 @@ cse_process_notes (rtx x, rtx object)
case MEM:
validate_change (x, &XEXP (x, 0),
- cse_process_notes (XEXP (x, 0), x), 0);
+ cse_process_notes (XEXP (x, 0), x, changed), 0);
return x;
case EXPR_LIST:
case INSN_LIST:
if (REG_NOTE_KIND (x) == REG_EQUAL)
- XEXP (x, 0) = cse_process_notes (XEXP (x, 0), NULL_RTX);
+ XEXP (x, 0) = cse_process_notes (XEXP (x, 0), NULL_RTX, changed);
if (XEXP (x, 1))
- XEXP (x, 1) = cse_process_notes (XEXP (x, 1), NULL_RTX);
+ XEXP (x, 1) = cse_process_notes (XEXP (x, 1), NULL_RTX, changed);
return x;
case SIGN_EXTEND:
case ZERO_EXTEND:
case SUBREG:
{
- rtx new = cse_process_notes (XEXP (x, 0), object);
+ rtx new = cse_process_notes (XEXP (x, 0), object, changed);
/* We don't substitute VOIDmode constants into these rtx,
since they would impede folding. */
if (GET_MODE (new) != VOIDmode)
@@ -5755,10 +5762,20 @@ cse_process_notes (rtx x, rtx object)
for (i = 0; i < GET_RTX_LENGTH (code); i++)
if (fmt[i] == 'e')
validate_change (object, &XEXP (x, i),
- cse_process_notes (XEXP (x, i), object), 0);
+ cse_process_notes (XEXP (x, i), object, changed), 0);
return x;
}
+
+static rtx
+cse_process_notes (rtx x, rtx object, bool *changed)
+{
+ rtx new = cse_process_notes_1 (x, object, changed);
+ if (new != x)
+ *changed = true;
+ return new;
+}
+
/* Find a path in the CFG, starting with FIRST_BB to perform CSE on.
@@ -6006,8 +6023,13 @@ cse_extended_basic_block (struct cse_bas
/* Process notes first so we have all notes in canonical forms
when looking for duplicate operations. */
if (REG_NOTES (insn))
- REG_NOTES (insn) = cse_process_notes (REG_NOTES (insn),
- NULL_RTX);
+ {
+ bool changed = false;
+ REG_NOTES (insn) = cse_process_notes (REG_NOTES (insn),
+ NULL_RTX, &changed);
+ if (changed)
+ df_notes_rescan (insn);
+ }
/* Track when we are inside in LIBCALL block. Inside such
a block we do not want to record destinations. The last
@@ -6181,7 +6203,10 @@ cse_main (rtx f ATTRIBUTE_UNUSED, int nr
int i, n_blocks;
if (df)
- df_set_flags (DF_NO_INSN_RESCAN);
+ {
+ df_analyze ();
+ df_set_flags (DF_DEFER_INSN_RESCAN);
+ }
init_cse_reg_info (nregs);
@@ -6264,11 +6289,6 @@ cse_main (rtx f ATTRIBUTE_UNUSED, int nr
sbitmap_free (reg_used_in_multiple_bb);
free (rc_order);
rtl_hooks = general_rtl_hooks;
- if (df)
- {
- df_clear_flags (DF_NO_INSN_RESCAN);
- df_insn_rescan_all ();
- }
return cse_jumps_altered || recorded_label_ref;
}
@@ -7080,6 +7100,7 @@ struct tree_opt_pass pass_cse2 =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
+ TODO_df_finish |
TODO_dump_func |
TODO_ggc_collect |
TODO_verify_flow, /* todo_flags_finish */
Index: gcse.c
===================================================================
--- gcse.c (revision 122403)
+++ gcse.c (working copy)
@@ -6731,6 +6731,7 @@ struct tree_opt_pass pass_gcse =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
+ TODO_df_finish |
TODO_dump_func |
TODO_verify_flow | TODO_ggc_collect, /* todo_flags_finish */
'G' /* letter */