This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[dataflow] speed up by 2%, patch 2/4 - combine changes
- 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: Mon, 19 Feb 2007 13:21:08 +0100
- Subject: [dataflow] speed up by 2%, patch 2/4 - combine changes
This patch removes CUIDs from combine, and puts log links in a side
vector indexed by insn UID.
CUIDs are consecutive IDs that are unique in the entire function, but we
actually need them to be unique only for each basic block. This is what
df's LUIDs are.
The computation of LUIDs in auto-inc-dec is extracted into a separate
pass so that we can run it even if auto-inc-dec is disabled.
Bootstrapped/regtested i686-pc-linux-gnu together with the others.
Since it affects auto-inc-dec too, I've also built a powerpc-darwin
cross and done an assembly language comparison on cc1 .i files, with no
change.
Ok?
Paolo
2007-01-18 Paolo Bonzini <bonzini@gnu.org>
* combine.c (uid_cuid, max_uid_cuid): Remove.
(INSN_CUID): Replace throughout with DF_INSN_LUID.
(last_call_cuid): Rename to last_call_luid.
(subst_low_cuid): Rename to subst_low_luid.
(last_insn_cost): Rename to max_uid_known.
(uid_log_links): New.
(INSN_COST, LOG_LINKS): New.
(combine_validate_cost): Use INSN_COST instead of accessing
uid_insn_cost.
(create_log_links, clear_log_links): Move before combine_instructions.
(combine_instructions): Don't compute cuids. Allocate uid_log_links.
Call create_log_links and clear_log_links here. Only initialize
data structures for insns within a basic block. Use INSN_COST
instead of accessing uid_insn_cost. Reset last_call_luid and
mem_last_set once for every basic block.
(can_combine_p, try_combine, reg_nonzero_bits_for_combine,
reg_num_sign_bit_copies_for_combine, record_value_for_reg,
record_dead_and_set_regs_1, record_dead_and_set_regs,
get_last_value_validate, get_last_value, use_crosses_set_p,
move_deaths, distribute_notes, distribute_links): Rename stuff
as indicated above.
(rest_of_handle_combine): Don't create/clear loglinks here.
(pass_combine): Require and destroy PROP_luid.
* auto-inc-dec.c (pass_auto_inc_dec): Require PROP_luid.
(merge_in_block): Don't recompute luids here.
* df-scan.c (df_recompute_all_luids): New.
(pass_compute_luid): New.
* tree-pass.h (pass_compute_luid): New.
* passes.c (init_optimization_passes): Move pass_initialize_regs before
pass_auto_inc_dec. Add pass_compute_luid before pass_auto_inc_dec.
Index: combine.c
===================================================================
--- combine.c (revision 122099)
+++ combine.c (working copy)
@@ -142,20 +142,6 @@ static rtx i2mod_old_rhs;
static rtx i2mod_new_rhs;
-/* Vector mapping INSN_UIDs to cuids.
- The cuids are like uids but increase monotonically always.
- Combine always uses cuids so that it can compare them.
- But actually renumbering the uids, which we used to do,
- proves to be a bad idea because it makes it hard to compare
- the dumps produced by earlier passes with those from later passes. */
-
-static int *uid_cuid;
-static int max_uid_cuid;
-
-/* Get the cuid of an insn. */
-
-#define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)])
-
/* Maximum register number, which is the size of the tables below. */
static unsigned int combine_max_regno;
@@ -271,15 +257,15 @@ struct reg_stat {
static struct reg_stat *reg_stat;
-/* Record the cuid of the last insn that invalidated memory
+/* Record the luid of the last insn that invalidated memory
(anything that writes memory, and subroutine calls, but not pushes). */
static int mem_last_set;
-/* Record the cuid of the last CALL_INSN
+/* Record the luid of the last CALL_INSN
so we can tell whether a potential combination crosses any calls. */
-static int last_call_cuid;
+static int last_call_luid;
/* When `subst' is called, this is the insn that is being modified
(by combining in a previous insn). The PATTERN of this insn
@@ -289,14 +275,14 @@ static int last_call_cuid;
static rtx subst_insn;
-/* This is the lowest CUID that `subst' is currently dealing with.
+/* This is the lowest LUID that `subst' is currently dealing with.
get_last_value will not return a value if the register was set at or
- after this CUID. If not for this mechanism, we could get confused if
+ after this LUID. If not for this mechanism, we could get confused if
I2 or I1 in try_combine were an insn that used the old value of a register
to obtain a new value. In that case, we might erroneously get the
new value of the register when we wanted the old one. */
-static int subst_low_cuid;
+static int subst_low_luid;
/* This contains any hard registers that are used in newpat; reg_dead_at_p
must consider all these registers to be always live. */
@@ -313,14 +299,22 @@ static rtx added_links_insn;
static basic_block this_basic_block;
+/* Length of the currently allocated uid_insn_cost array. */
+
+static int max_uid_known;
+
/* The following array records the insn_rtx_cost for every insn
in the instruction stream. */
static int *uid_insn_cost;
-/* Length of the currently allocated uid_insn_cost array. */
+/* The following array records the LOG_LINKS for every insn in the
+ instruction stream as an INSN_LIST rtx. */
-static int last_insn_cost;
+static rtx *uid_log_links;
+
+#define INSN_COST(INSN) (uid_insn_cost[INSN_UID (INSN)])
+#define LOG_LINKS(INSN) (uid_log_links[INSN_UID (INSN)])
/* Incremented for each label. */
@@ -760,15 +754,12 @@ combine_validate_cost (rtx i1, rtx i2, r
int old_cost, new_cost;
/* Lookup the original insn_rtx_costs. */
- i2_cost = INSN_UID (i2) <= last_insn_cost
- ? uid_insn_cost[INSN_UID (i2)] : 0;
- i3_cost = INSN_UID (i3) <= last_insn_cost
- ? uid_insn_cost[INSN_UID (i3)] : 0;
+ i2_cost = INSN_COST (i2);
+ i3_cost = INSN_COST (i3);
if (i1)
{
- i1_cost = INSN_UID (i1) <= last_insn_cost
- ? uid_insn_cost[INSN_UID (i1)] : 0;
+ i1_cost = INSN_COST (i1);
old_cost = (i1_cost > 0 && i2_cost > 0 && i3_cost > 0)
? i1_cost + i2_cost + i3_cost : 0;
}
@@ -796,8 +787,7 @@ combine_validate_cost (rtx i1, rtx i2, r
{
int old_other_cost, new_other_cost;
- old_other_cost = (INSN_UID (undobuf.other_insn) <= last_insn_cost
- ? uid_insn_cost[INSN_UID (undobuf.other_insn)] : 0);
+ old_other_cost = INSN_COST (undobuf.other_insn);
new_other_cost = insn_rtx_cost (PATTERN (undobuf.other_insn));
if (old_other_cost > 0 && new_other_cost > 0)
{
@@ -845,10 +835,10 @@ combine_validate_cost (rtx i1, rtx i2, r
}
/* Update the uid_insn_cost array with the replacement costs. */
- uid_insn_cost[INSN_UID (i2)] = new_i2_cost;
- uid_insn_cost[INSN_UID (i3)] = new_i3_cost;
+ INSN_COST (i2) = new_i2_cost;
+ INSN_COST (i3) = new_i3_cost;
if (i1)
- uid_insn_cost[INSN_UID (i1)] = 0;
+ INSN_COST (i1) = 0;
return true;
}
@@ -901,6 +891,113 @@ continue;
}
+/* Fill in log links field for all insns. */
+
+static void
+create_log_links (void)
+{
+ basic_block bb;
+ rtx *next_use, insn;
+ struct df_ref **def_vec, **use_vec;
+
+ next_use = XCNEWVEC (rtx, max_reg_num ());
+
+ /* Pass through each block from the end, recording the uses of each
+ register and establishing log links when def is encountered.
+ Note that we do not clear next_use array in order to save time,
+ so we have to test whether the use is in the same basic block as def.
+
+ There are a few cases below when we do not consider the definition or
+ usage -- these are taken from original flow.c did. Don't ask me why it is
+ done this way; I don't know and if it works, I don't want to know. */
+
+ FOR_EACH_BB (bb)
+ {
+ FOR_BB_INSNS_REVERSE (bb, insn)
+ {
+ if (!INSN_P (insn))
+ continue;
+
+ /* Log links are created only once. */
+ gcc_assert (!LOG_LINKS (insn));
+
+ for (def_vec = DF_INSN_DEFS (insn); *def_vec; def_vec++)
+ {
+ struct df_ref *def = *def_vec;
+ int regno = DF_REF_REGNO (def);
+ rtx use_insn;
+
+ if (!next_use[regno])
+ continue;
+
+ /* Do not consider if it is pre/post modification in MEM. */
+ if (DF_REF_FLAGS (def) & DF_REF_PRE_POST_MODIFY)
+ continue;
+
+ /* Do not make the log link for frame pointer. */
+ if ((regno == FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
+#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ || (regno == HARD_FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
+#endif
+#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ || (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
+#endif
+ )
+ continue;
+
+ use_insn = next_use[regno];
+ if (BLOCK_FOR_INSN (use_insn) == bb)
+ {
+ /* flow.c claimed:
+
+ We don't build a LOG_LINK for hard registers contained
+ in ASM_OPERANDs. If these registers get replaced,
+ we might wind up changing the semantics of the insn,
+ even if reload can make what appear to be valid
+ assignments later. */
+ if (regno >= FIRST_PSEUDO_REGISTER
+ || asm_noperands (PATTERN (use_insn)) < 0)
+ LOG_LINKS (use_insn) =
+ alloc_INSN_LIST (insn, LOG_LINKS (use_insn));
+ }
+ next_use[regno] = NULL_RTX;
+ }
+
+ for (use_vec = DF_INSN_USES (insn); *use_vec; use_vec++)
+ {
+ struct df_ref *use = *use_vec;
+ int regno = DF_REF_REGNO (use);
+
+ /* Do not consider the usage of the stack pointer
+ by function call. */
+ if (DF_REF_FLAGS (use) & DF_REF_CALL_STACK_USAGE)
+ continue;
+
+ next_use[regno] = insn;
+ }
+ }
+ }
+
+ free (next_use);
+}
+
+/* Clear LOG_LINKS fields of insns. */
+
+static void
+clear_log_links (void)
+{
+ rtx insn;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ free_INSN_LIST_list (&LOG_LINKS (insn));
+}
+
+
+
+
/* Main entry point for combiner. F is the first insn of the function.
NREGS is the first unused pseudo-reg number.
@@ -913,7 +1010,6 @@ combine_instructions (rtx f, unsigned in
#ifdef HAVE_cc0
rtx prev;
#endif
- int i;
rtx links, nextlinks;
int new_direct_jump_p = 0;
@@ -931,14 +1027,10 @@ combine_instructions (rtx f, unsigned in
init_recog_no_volatile ();
- /* Compute maximum uid value so uid_cuid can be allocated. */
-
- for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
- if (INSN_UID (insn) > i)
- i = INSN_UID (insn);
-
- uid_cuid = XNEWVEC (int, i + 1);
- max_uid_cuid = i;
+ /* Allocate array for insn info. */
+ max_uid_known = get_max_uid ();
+ uid_log_links = XCNEWVEC (rtx, max_uid_known + 1);
+ uid_insn_cost = XCNEWVEC (int, max_uid_known + 1);
nonzero_bits_mode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
@@ -947,11 +1039,7 @@ combine_instructions (rtx f, unsigned in
nonzero_sign_valid = 0;
- /* Compute the mapping from uids to cuids.
- Cuids are numbers assigned to insns, like uids,
- except that cuids increase monotonically through the code.
-
- Scan all SETs and see if we can deduce anything about what
+ /* Scan all SETs and see if we can deduce anything about what
bits are known to be zero for some registers and how many copies
of the sign bit are known to exist for those registers.
@@ -962,19 +1050,14 @@ combine_instructions (rtx f, unsigned in
setup_incoming_promotions ();
-
- /* Allocate array of current insn_rtx_costs. */
- uid_insn_cost = XCNEWVEC (int, max_uid_cuid + 1);
- last_insn_cost = max_uid_cuid;
-
- for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
+ create_log_links ();
+ for (insn = f; insn; insn = NEXT_INSN (insn))
{
- uid_cuid[INSN_UID (insn)] = ++i;
- subst_low_cuid = i;
- subst_insn = insn;
-
- if (INSN_P (insn))
+ if (INSN_P (insn) && BLOCK_FOR_INSN (insn))
{
+ subst_low_luid = DF_INSN_LUID (insn);
+ subst_insn = insn;
+
note_stores (PATTERN (insn), set_nonzero_bits_and_sign_copies,
insn);
record_dead_and_set_regs (insn);
@@ -988,10 +1071,10 @@ combine_instructions (rtx f, unsigned in
/* Record the current insn_rtx_cost of this instruction. */
if (NONJUMP_INSN_P (insn))
- uid_insn_cost[INSN_UID (insn)] = insn_rtx_cost (PATTERN (insn));
+ INSN_COST (insn) = insn_rtx_cost (PATTERN (insn));
if (dump_file)
fprintf(dump_file, "insn_cost %d: %d\n",
- INSN_UID (insn), uid_insn_cost[INSN_UID (insn)]);
+ INSN_UID (insn), INSN_COST (insn));
}
if (LABEL_P (insn))
@@ -1003,13 +1086,13 @@ combine_instructions (rtx f, unsigned in
/* Now scan all the insns in forward order. */
label_tick = 1;
- last_call_cuid = 0;
- mem_last_set = 0;
init_reg_last ();
setup_incoming_promotions ();
FOR_EACH_BB (this_basic_block)
{
+ last_call_luid = 0;
+ mem_last_set = 0;
for (insn = BB_HEAD (this_basic_block);
insn != NEXT_INSN (BB_END (this_basic_block));
insn = next ? next : NEXT_INSN (insn))
@@ -1163,14 +1246,15 @@ combine_instructions (rtx f, unsigned in
}
}
+ clear_log_links ();
clear_bb_flags ();
new_direct_jump_p |= purge_all_dead_edges ();
delete_noop_moves ();
/* Clean up. */
+ free (uid_log_links);
free (uid_insn_cost);
free (reg_stat);
- free (uid_cuid);
{
struct undo *undo, *next;
@@ -1528,7 +1612,7 @@ can_combine_p (rtx insn, rtx i3, rtx pre
|| (! all_adjacent
&& (((!MEM_P (src)
|| ! find_reg_note (insn, REG_EQUIV, src))
- && use_crosses_set_p (src, INSN_CUID (insn)))
+ && use_crosses_set_p (src, DF_INSN_LUID (insn)))
|| (GET_CODE (src) == ASM_OPERANDS && MEM_VOLATILE_P (src))
|| GET_CODE (src) == UNSPEC_VOLATILE))
/* If there is a REG_NO_CONFLICT note for DEST in I3 or SUCC, we get
@@ -1540,7 +1624,7 @@ can_combine_p (rtx insn, rtx i3, rtx pre
and it is a pain to update that information.
Exception: if source is a constant, moving it later can't hurt.
Accept that special case, because it helps -fforce-addr a lot. */
- || (INSN_CUID (insn) < last_call_cuid && ! CONSTANT_P (src)))
+ || (DF_INSN_LUID (insn) < last_call_luid && ! CONSTANT_P (src)))
return 0;
/* DEST must either be a REG or CC0. */
@@ -2100,7 +2184,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
/* If I1 and I2 both feed I3, they can be in any order. To simplify the
code below, set I1 to be the earlier of the two insns. */
- if (i1 && INSN_CUID (i1) > INSN_CUID (i2))
+ if (i1 && DF_INSN_LUID (i1) > DF_INSN_LUID (i2))
temp = i1, i1 = i2, i2 = temp;
added_links_insn = 0;
@@ -2165,7 +2249,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
combine_merges++;
subst_insn = i3;
- subst_low_cuid = INSN_CUID (i2);
+ subst_low_luid = DF_INSN_LUID (i2);
added_sets_2 = added_sets_1 = 0;
i2dest = SET_SRC (PATTERN (i3));
@@ -2306,7 +2390,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
combine_merges++;
subst_insn = i3;
- subst_low_cuid = INSN_CUID (i2);
+ subst_low_luid = DF_INSN_LUID (i2);
added_sets_2 = added_sets_1 = 0;
i2dest = SET_DEST (temp);
i2dest_killed = dead_or_set_p (i2, i2dest);
@@ -2352,14 +2436,13 @@ try_combine (rtx i3, rtx i2, rtx i1, int
if (i == 1)
{
/* We make I1 with the same INSN_UID as I2. This gives it
- the same INSN_CUID for value tracking. Our fake I1 will
+ the same DF_INSN_LUID for value tracking. Our fake I1 will
never appear in the insn stream so giving it the same INSN_UID
as I2 will not cause a problem. */
i1 = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
BLOCK_FOR_INSN (i2), INSN_LOCATOR (i2),
- XVECEXP (PATTERN (i2), 0, 1), -1, NULL_RTX,
- NULL_RTX);
+ XVECEXP (PATTERN (i2), 0, 1), -1, NULL_RTX);
SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
@@ -2573,12 +2656,12 @@ try_combine (rtx i3, rtx i2, rtx i1, int
simplifications. */
if (i1)
{
- subst_low_cuid = INSN_CUID (i1);
+ subst_low_luid = DF_INSN_LUID (i1);
i1src = subst (i1src, pc_rtx, pc_rtx, 0, 0);
}
else
{
- subst_low_cuid = INSN_CUID (i2);
+ subst_low_luid = DF_INSN_LUID (i2);
i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0);
}
}
@@ -2589,7 +2672,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
need to make a unique copy of I2SRC each time we substitute it
to avoid self-referential rtl. */
- subst_low_cuid = INSN_CUID (i2);
+ subst_low_luid = DF_INSN_LUID (i2);
newpat = subst (PATTERN (i3), i2dest, i2src, 0,
! i1_feeds_i3 && i1dest_in_i1src);
substed_i2 = 1;
@@ -2615,7 +2698,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
}
n_occurrences = 0;
- subst_low_cuid = INSN_CUID (i1);
+ subst_low_luid = DF_INSN_LUID (i1);
newpat = subst (newpat, i1dest, i1src, 0, 0);
substed_i1 = 1;
}
@@ -2862,7 +2945,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
}
else if (m_split && NEXT_INSN (NEXT_INSN (m_split)) == NULL_RTX
&& (next_real_insn (i2) == i3
- || ! use_crosses_set_p (PATTERN (m_split), INSN_CUID (i2))))
+ || ! use_crosses_set_p (PATTERN (m_split), DF_INSN_LUID (i2))))
{
rtx i2set, i3set;
rtx newi3pat = PATTERN (NEXT_INSN (m_split));
@@ -2926,7 +3009,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
|| can_change_dest_mode (i2dest, added_sets_2,
GET_MODE (*split)))
&& (next_real_insn (i2) == i3
- || ! use_crosses_set_p (*split, INSN_CUID (i2)))
+ || ! use_crosses_set_p (*split, DF_INSN_LUID (i2)))
/* We can't overwrite I2DEST if its value is still used by
NEWPAT. */
&& ! reg_referenced_p (i2dest, newpat))
@@ -3096,7 +3179,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
&& rtx_equal_p (SET_SRC (XVECEXP (newpat, 0, 1)),
XEXP (SET_SRC (XVECEXP (newpat, 0, 0)), 0))
&& ! use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)),
- INSN_CUID (i2))
+ DF_INSN_LUID (i2))
&& GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != ZERO_EXTRACT
&& GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != STRICT_LOW_PART
&& ! (temp = SET_DEST (XVECEXP (newpat, 0, 1)),
@@ -3150,7 +3233,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
&& GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != ZERO_EXTRACT
&& GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != STRICT_LOW_PART
&& ! use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)),
- INSN_CUID (i2))
+ DF_INSN_LUID (i2))
&& ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 1)),
XVECEXP (newpat, 0, 0))
&& ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 0)),
@@ -3441,11 +3524,11 @@ try_combine (rtx i3, rtx i2, rtx i1, int
if (newi2pat)
{
- move_deaths (newi2pat, NULL_RTX, INSN_CUID (i1), i2, &midnotes);
- move_deaths (newpat, newi2pat, INSN_CUID (i1), i3, &midnotes);
+ move_deaths (newi2pat, NULL_RTX, DF_INSN_LUID (i1), i2, &midnotes);
+ move_deaths (newpat, newi2pat, DF_INSN_LUID (i1), i3, &midnotes);
}
else
- move_deaths (newpat, NULL_RTX, i1 ? INSN_CUID (i1) : INSN_CUID (i2),
+ move_deaths (newpat, NULL_RTX, i1 ? DF_INSN_LUID (i1) : DF_INSN_LUID (i2),
i3, &midnotes);
/* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3. */
@@ -3676,8 +3759,8 @@ try_combine (rtx i3, rtx i2, rtx i1, int
undo_commit ();
if (added_links_insn
- && (newi2pat == 0 || INSN_CUID (added_links_insn) < INSN_CUID (i2))
- && INSN_CUID (added_links_insn) < INSN_CUID (i3))
+ && (newi2pat == 0 || DF_INSN_LUID (added_links_insn) < DF_INSN_LUID (i2))
+ && DF_INSN_LUID (added_links_insn) < DF_INSN_LUID (i3))
return added_links_insn;
else
return newi2pat ? i2 : i3;
@@ -8553,7 +8636,7 @@ reg_nonzero_bits_for_combine (rtx x, enu
&& REG_N_SETS (REGNO (x)) == 1
&& REGNO_REG_SET_P
(DF_UR_IN (ENTRY_BLOCK_PTR->next_bb), REGNO (x))))
- && INSN_CUID (reg_stat[REGNO (x)].last_set) < subst_low_cuid)
+ && DF_INSN_LUID (reg_stat[REGNO (x)].last_set) < subst_low_luid)
{
*nonzero &= reg_stat[REGNO (x)].last_set_nonzero_bits;
return NULL;
@@ -8620,7 +8703,7 @@ reg_num_sign_bit_copies_for_combine (rtx
&& REG_N_SETS (REGNO (x)) == 1
&& REGNO_REG_SET_P
(DF_UR_IN (ENTRY_BLOCK_PTR->next_bb), REGNO (x))))
- && INSN_CUID (reg_stat[REGNO (x)].last_set) < subst_low_cuid)
+ && DF_INSN_LUID (reg_stat[REGNO (x)].last_set) < subst_low_luid)
{
*result = reg_stat[REGNO (x)].last_set_sign_bit_copies;
return NULL;
@@ -11140,7 +11223,7 @@ record_value_for_reg (rtx reg, rtx insn,
/* Set things up so get_last_value is allowed to see anything set up to
our insn. */
- subst_low_cuid = INSN_CUID (insn);
+ subst_low_luid = DF_INSN_LUID (insn);
tem = get_last_value (reg);
/* If TEM is simply a binary operation with two CLOBBERs as operands,
@@ -11222,7 +11305,7 @@ record_value_for_reg (rtx reg, rtx insn,
if (value)
{
enum machine_mode mode = GET_MODE (reg);
- subst_low_cuid = INSN_CUID (insn);
+ subst_low_luid = DF_INSN_LUID (insn);
reg_stat[regno].last_set_mode = mode;
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
@@ -11273,7 +11356,7 @@ record_dead_and_set_regs_1 (rtx dest, rt
else if (MEM_P (dest)
/* Ignore pushes, they clobber nothing. */
&& ! push_operand (dest, GET_MODE (dest)))
- mem_last_set = INSN_CUID (record_dead_insn);
+ mem_last_set = DF_INSN_LUID (record_dead_insn);
}
/* Update the records of when each REG was most recently set or killed
@@ -11283,7 +11366,7 @@ record_dead_and_set_regs_1 (rtx dest, rt
We update reg_stat[], in particular fields last_set, last_set_value,
last_set_mode, last_set_nonzero_bits, last_set_sign_bit_copies,
last_death, and also the similar information mem_last_set (which insn
- most recently modified memory) and last_call_cuid (which insn was the
+ most recently modified memory) and last_call_luid (which insn was the
most recent subroutine call). */
static void
@@ -11323,10 +11406,10 @@ record_dead_and_set_regs (rtx insn)
reg_stat[i].truncated_to_mode = 0;
}
- last_call_cuid = mem_last_set = INSN_CUID (insn);
+ last_call_luid = mem_last_set = DF_INSN_LUID (insn);
/* We can't combine into a call pattern. Remember, though, that
- the return value register is set at this CUID. We could
+ the return value register is set at this LUID. We could
still replace a register with the return value from the
wrong subroutine call! */
note_stores (PATTERN (insn), record_dead_and_set_regs_1, NULL_RTX);
@@ -11526,7 +11609,7 @@ get_last_value_validate (rtx *loc, rtx i
no stores after it that might have clobbered the value. We don't
have alias info, so we assume any store invalidates it. */
else if (MEM_P (x) && !MEM_READONLY_P (x)
- && INSN_CUID (insn) <= mem_last_set)
+ && DF_INSN_LUID (insn) <= mem_last_set)
{
if (replace)
*loc = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
@@ -11627,7 +11710,7 @@ get_last_value (rtx x)
/* If the value was set in a later insn than the ones we are processing,
we can't use it even if the register was only set once. */
- if (INSN_CUID (reg_stat[regno].last_set) >= subst_low_cuid)
+ if (DF_INSN_LUID (reg_stat[regno].last_set) >= subst_low_luid)
return 0;
/* If the value has all its registers valid, return it. */
@@ -11647,10 +11730,10 @@ get_last_value (rtx x)
}
/* Return nonzero if expression X refers to a REG or to memory
- that is set in an instruction more recent than FROM_CUID. */
+ that is set in an instruction more recent than FROM_LUID. */
static int
-use_crosses_set_p (rtx x, int from_cuid)
+use_crosses_set_p (rtx x, int from_luid)
{
const char *fmt;
int i;
@@ -11670,12 +11753,12 @@ use_crosses_set_p (rtx x, int from_cuid)
#endif
for (; regno < endreg; regno++)
if (reg_stat[regno].last_set
- && INSN_CUID (reg_stat[regno].last_set) > from_cuid)
+ && DF_INSN_LUID (reg_stat[regno].last_set) > from_luid)
return 1;
return 0;
}
- if (code == MEM && mem_last_set > from_cuid)
+ if (code == MEM && mem_last_set > from_luid)
return 1;
fmt = GET_RTX_FORMAT (code);
@@ -11686,11 +11769,11 @@ use_crosses_set_p (rtx x, int from_cuid)
{
int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (use_crosses_set_p (XVECEXP (x, i, j), from_cuid))
+ if (use_crosses_set_p (XVECEXP (x, i, j), from_luid))
return 1;
}
else if (fmt[i] == 'e'
- && use_crosses_set_p (XEXP (x, i), from_cuid))
+ && use_crosses_set_p (XEXP (x, i), from_luid))
return 1;
}
return 0;
@@ -11910,7 +11993,7 @@ remove_death (unsigned int regno, rtx in
}
/* For each register (hardware or pseudo) used within expression X, if its
- death is in an instruction with cuid between FROM_CUID (inclusive) and
+ death is in an instruction with luid between FROM_LUID (inclusive) and
TO_INSN (exclusive), put a REG_DEAD note for that register in the
list headed by PNOTES.
@@ -11920,7 +12003,7 @@ remove_death (unsigned int regno, rtx in
notes will then be distributed as needed. */
static void
-move_deaths (rtx x, rtx maybe_kill_insn, int from_cuid, rtx to_insn,
+move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx to_insn,
rtx *pnotes)
{
const char *fmt;
@@ -11938,8 +12021,8 @@ move_deaths (rtx x, rtx maybe_kill_insn,
return;
if (where_dead
- && INSN_CUID (where_dead) >= from_cuid
- && INSN_CUID (where_dead) < INSN_CUID (to_insn))
+ && DF_INSN_LUID (where_dead) >= from_luid
+ && DF_INSN_LUID (where_dead) < DF_INSN_LUID (to_insn))
{
rtx note = remove_death (regno, where_dead);
@@ -11996,7 +12079,7 @@ move_deaths (rtx x, rtx maybe_kill_insn,
for (i = regno + offset; i < ourend; i++)
move_deaths (regno_reg_rtx[i],
- maybe_kill_insn, from_cuid, to_insn, &oldnotes);
+ maybe_kill_insn, from_luid, to_insn, &oldnotes);
}
if (note != 0 && GET_MODE (XEXP (note, 0)) == GET_MODE (x))
@@ -12017,7 +12100,7 @@ move_deaths (rtx x, rtx maybe_kill_insn,
{
rtx dest = SET_DEST (x);
- move_deaths (SET_SRC (x), maybe_kill_insn, from_cuid, to_insn, pnotes);
+ move_deaths (SET_SRC (x), maybe_kill_insn, from_luid, to_insn, pnotes);
/* In the case of a ZERO_EXTRACT, a STRICT_LOW_PART, or a SUBREG
that accesses one word of a multi-word item, some
@@ -12033,7 +12116,7 @@ move_deaths (rtx x, rtx maybe_kill_insn,
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD))))
{
- move_deaths (dest, maybe_kill_insn, from_cuid, to_insn, pnotes);
+ move_deaths (dest, maybe_kill_insn, from_luid, to_insn, pnotes);
return;
}
@@ -12047,7 +12130,7 @@ move_deaths (rtx x, rtx maybe_kill_insn,
being replaced so the old value is not used in this insn. */
if (MEM_P (dest))
- move_deaths (XEXP (dest, 0), maybe_kill_insn, from_cuid,
+ move_deaths (XEXP (dest, 0), maybe_kill_insn, from_luid,
to_insn, pnotes);
return;
}
@@ -12064,11 +12147,11 @@ move_deaths (rtx x, rtx maybe_kill_insn,
{
int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- move_deaths (XVECEXP (x, i, j), maybe_kill_insn, from_cuid,
+ move_deaths (XVECEXP (x, i, j), maybe_kill_insn, from_luid,
to_insn, pnotes);
}
else if (fmt[i] == 'e')
- move_deaths (XEXP (x, i), maybe_kill_insn, from_cuid, to_insn, pnotes);
+ move_deaths (XEXP (x, i), maybe_kill_insn, from_luid, to_insn, pnotes);
}
}
@@ -12545,9 +12628,9 @@ distribute_notes (rtx notes, rtx from_in
i2 but does not die in i2, and place is between i2
and i3, then we may need to move a link from place to
i2. */
- if (i2 && INSN_CUID (place) > INSN_CUID (i2)
+ if (i2 && DF_INSN_LUID (place) > DF_INSN_LUID (i2)
&& from_insn
- && INSN_CUID (from_insn) > INSN_CUID (i2)
+ && DF_INSN_LUID (from_insn) > DF_INSN_LUID (i2)
&& reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
{
rtx links = LOG_LINKS (place);
@@ -12778,7 +12861,7 @@ distribute_links (rtx links)
/* Set added_links_insn to the earliest insn we added a
link to. */
if (added_links_insn == 0
- || INSN_CUID (added_links_insn) > INSN_CUID (place))
+ || DF_INSN_LUID (added_links_insn) > DF_INSN_LUID (place))
added_links_insn = place;
}
}
@@ -12830,112 +12913,6 @@ dump_combine_total_stats (FILE *file)
total_attempts, total_merges, total_extras, total_successes);
}
-
-/* Fill in log links field for all insns. */
-
-static void
-create_log_links (void)
-{
- basic_block bb;
- rtx *next_use, insn;
- struct df_ref **def_vec, **use_vec;
-
- next_use = XCNEWVEC (rtx, max_reg_num ());
-
- /* Pass through each block from the end, recording the uses of each
- register and establishing log links when def is encountered.
- Note that we do not clear next_use array in order to save time,
- so we have to test whether the use is in the same basic block as def.
-
- There are a few cases below when we do not consider the definition or
- usage -- these are taken from original flow.c did. Don't ask me why it is
- done this way; I don't know and if it works, I don't want to know. */
-
- FOR_EACH_BB (bb)
- {
- FOR_BB_INSNS_REVERSE (bb, insn)
- {
- if (!INSN_P (insn))
- continue;
-
- /* Log links are created only once. */
- gcc_assert (!LOG_LINKS (insn));
-
- for (def_vec = DF_INSN_DEFS (insn); *def_vec; def_vec++)
- {
- struct df_ref *def = *def_vec;
- int regno = DF_REF_REGNO (def);
- rtx use_insn;
-
- if (!next_use[regno])
- continue;
-
- /* Do not consider if it is pre/post modification in MEM. */
- if (DF_REF_FLAGS (def) & DF_REF_PRE_POST_MODIFY)
- continue;
-
- /* Do not make the log link for frame pointer. */
- if ((regno == FRAME_POINTER_REGNUM
- && (! reload_completed || frame_pointer_needed))
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || (regno == HARD_FRAME_POINTER_REGNUM
- && (! reload_completed || frame_pointer_needed))
-#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
-#endif
- )
- continue;
-
- use_insn = next_use[regno];
- if (BLOCK_FOR_INSN (use_insn) == bb)
- {
- /* flow.c claimed:
-
- We don't build a LOG_LINK for hard registers contained
- in ASM_OPERANDs. If these registers get replaced,
- we might wind up changing the semantics of the insn,
- even if reload can make what appear to be valid
- assignments later. */
- if (regno >= FIRST_PSEUDO_REGISTER
- || asm_noperands (PATTERN (use_insn)) < 0)
- LOG_LINKS (use_insn) =
- alloc_INSN_LIST (insn, LOG_LINKS (use_insn));
- }
- next_use[regno] = NULL_RTX;
- }
-
- for (use_vec = DF_INSN_USES (insn); *use_vec; use_vec++)
- {
- struct df_ref *use = *use_vec;
- int regno = DF_REF_REGNO (use);
-
- /* Do not consider the usage of the stack pointer
- by function call. */
- if (DF_REF_FLAGS (use) & DF_REF_CALL_STACK_USAGE)
- continue;
-
- next_use[regno] = insn;
- }
- }
- }
-
- free (next_use);
-}
-
-/* Clear LOG_LINKS fields of insns. */
-
-static void
-clear_log_links (void)
-{
- rtx insn;
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (INSN_P (insn))
- free_INSN_LIST_list (&LOG_LINKS (insn));
-}
-
-
static bool
gate_handle_combine (void)
{
@@ -12952,7 +12929,6 @@ rest_of_handle_combine (void)
df_ri_add_problem (DF_RI_LIFE);
df_analyze ();
- create_log_links ();
rebuild_jump_labels_after_combine
= combine_instructions (get_insns (), max_reg_num ());
@@ -12968,7 +12944,6 @@ rest_of_handle_combine (void)
delete_dead_jumptables ();
cleanup_cfg (CLEANUP_EXPENSIVE);
}
- clear_log_links ();
return 0;
}
@@ -12982,9 +12958,9 @@ struct tree_opt_pass pass_combine =
NULL, /* next */
0, /* static_pass_number */
TV_COMBINE, /* tv_id */
- 0, /* properties_required */
+ PROP_luid, /* properties_required */
0, /* properties_provided */
- 0, /* properties_destroyed */
+ PROP_luid, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func |
TODO_df_finish |
Index: tree-pass.h
===================================================================
--- tree-pass.h (revision 122099)
+++ tree-pass.h (working copy)
@@ -372,6 +373,7 @@ extern struct tree_opt_pass pass_subregs
extern struct tree_opt_pass pass_inc_dec;
extern struct tree_opt_pass pass_no_new_pseudos;
extern struct tree_opt_pass pass_stack_ptr_mod;
+extern struct tree_opt_pass pass_compute_luid;
extern struct tree_opt_pass pass_initialize_regs;
extern struct tree_opt_pass pass_combine;
extern struct tree_opt_pass pass_if_after_combine;
Index: passes.c
===================================================================
--- passes.c (revision 122099)
+++ passes.c (working copy)
@@ -714,9 +714,10 @@ init_optimization_passes (void)
NEXT_PASS (pass_rtl_fwprop_addr);
NEXT_PASS (pass_regclass_init);
NEXT_PASS (pass_subregs_of_mode_init);
+ NEXT_PASS (pass_initialize_regs);
+ NEXT_PASS (pass_compute_luid);
NEXT_PASS (pass_inc_dec);
NEXT_PASS (pass_stack_ptr_mod);
- NEXT_PASS (pass_initialize_regs);
NEXT_PASS (pass_no_new_pseudos);
NEXT_PASS (pass_combine);
NEXT_PASS (pass_rtl_dse2);
Index: auto-inc-dec.c
===================================================================
--- auto-inc-dec.c (revision 122099)
+++ auto-inc-dec.c (working copy)
@@ -1379,8 +1379,6 @@ merge_in_block (int max_reg, basic_block
if (dump_file)
fprintf (dump_file, "\n\nstarting bb %d\n", bb->index);
- df_recompute_luids (bb);
-
FOR_BB_INSNS_REVERSE_SAFE (bb, insn, curr)
{
unsigned int uid = INSN_UID (insn);
@@ -1555,8 +1553,8 @@ struct tree_opt_pass pass_inc_dec =
NULL, /* next */
0, /* static_pass_number */
TV_AUTO_INC_DEC, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
+ PROP_luid, /* properties_required */
+ 0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func |
Index: df-scan.c
===================================================================
--- df-scan.c (revision 122099)
+++ df-scan.c (working copy)
@@ -3009,7 +3009,33 @@ df_recompute_luids (basic_block bb)
}
}
-
+static unsigned int
+df_recompute_all_luids (void)
+{
+ basic_block bb;
+ FOR_EACH_BB (bb)
+ df_recompute_luids (bb);
+ return 0;
+}
+
+struct tree_opt_pass pass_compute_luid =
+{
+ "luids", /* name */
+ 0, /* gate */
+ df_recompute_all_luids, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ 0, /* properties_required */
+ PROP_luid, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func |
+ TODO_df_finish, /* todo_flags_finish */
+ 0 /* letter */
+};
+
/* Returns true if the function entry needs to
define the static chain register. */