#define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X)))
/* Cap the number of passes we make over the insns propagating alias
- information through set chains. 10 is a completely arbitrary choice. */
+ information through set chains.
+ ??? 10 is a completely arbitrary choice. This should be based on the
+ maximum loop depth in the CFG, but we do not have this information
+ available (even if current_loops _is_ available). */
#define MAX_ALIAS_LOOP_PASSES 10
/* reg_base_value[N] gives an address to which register N is related.
int i;
unsigned int ui;
rtx insn, val;
+ int rpo_cnt;
+ int *rpo;
timevar_push (TV_ALIAS_ANALYSIS);
"constant" information from the previous pass to propagate alias
information through another level of assignments.
+ The propagation is done on the CFG in reverse post-order, to propagate
+ things forward as far as possible in each iteration.
+
This could get expensive if the assignment chains are long. Maybe
we should throttle the number of iterations, possibly based on
the optimization level or flag_expensive_optimizations.
The state of the arrays for the set chain in question does not matter
since the program has undefined behavior. */
+ rpo = XNEWVEC (int, n_basic_blocks);
+ rpo_cnt = pre_and_rev_post_order_compute (NULL, rpo, false);
+
pass = 0;
do
{
FIRST_PSEUDO_REGISTER * sizeof (rtx));
/* Walk the insns adding values to the new_reg_base_value array. */
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ for (i = 0; i < rpo_cnt; i++)
{
- if (INSN_P (insn))
+ basic_block bb = BASIC_BLOCK (rpo[i]);
+ FOR_BB_INSNS (bb, insn)
{
- rtx note, set;
+ if (NONDEBUG_INSN_P (insn))
+ {
+ rtx note, set;
#if defined (HAVE_prologue) || defined (HAVE_epilogue)
- /* The prologue/epilogue insns are not threaded onto the
- insn chain until after reload has completed. Thus,
- there is no sense wasting time checking if INSN is in
- the prologue/epilogue until after reload has completed. */
- if (reload_completed
- && prologue_epilogue_contains (insn))
- continue;
+ /* The prologue/epilogue insns are not threaded onto the
+ insn chain until after reload has completed. Thus,
+ there is no sense wasting time checking if INSN is in
+ the prologue/epilogue until after reload has completed. */
+ if (reload_completed
+ && prologue_epilogue_contains (insn))
+ continue;
#endif
- /* If this insn has a noalias note, process it, Otherwise,
- scan for sets. A simple set will have no side effects
- which could change the base value of any other register. */
+ /* If this insn has a noalias note, process it, Otherwise,
+ scan for sets. A simple set will have no side effects
+ which could change the base value of any other register. */
- if (GET_CODE (PATTERN (insn)) == SET
- && REG_NOTES (insn) != 0
- && find_reg_note (insn, REG_NOALIAS, NULL_RTX))
- record_set (SET_DEST (PATTERN (insn)), NULL_RTX, NULL);
- else
- note_stores (PATTERN (insn), record_set, NULL);
+ if (GET_CODE (PATTERN (insn)) == SET
+ && REG_NOTES (insn) != 0
+ && find_reg_note (insn, REG_NOALIAS, NULL_RTX))
+ record_set (SET_DEST (PATTERN (insn)), NULL_RTX, NULL);
+ else
+ note_stores (PATTERN (insn), record_set, NULL);
- set = single_set (insn);
+ set = single_set (insn);
- if (set != 0
- && REG_P (SET_DEST (set))
- && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
- {
- unsigned int regno = REGNO (SET_DEST (set));
- rtx src = SET_SRC (set);
- rtx t;
-
- note = find_reg_equal_equiv_note (insn);
- if (note && REG_NOTE_KIND (note) == REG_EQUAL
- && DF_REG_DEF_COUNT (regno) != 1)
- note = NULL_RTX;
-
- if (note != NULL_RTX
- && GET_CODE (XEXP (note, 0)) != EXPR_LIST
- && ! rtx_varies_p (XEXP (note, 0), 1)
- && ! reg_overlap_mentioned_p (SET_DEST (set),
- XEXP (note, 0)))
- {
- set_reg_known_value (regno, XEXP (note, 0));
- set_reg_known_equiv_p (regno,
- REG_NOTE_KIND (note) == REG_EQUIV);
- }
- else if (DF_REG_DEF_COUNT (regno) == 1
- && GET_CODE (src) == PLUS
- && REG_P (XEXP (src, 0))
- && (t = get_reg_known_value (REGNO (XEXP (src, 0))))
- && CONST_INT_P (XEXP (src, 1)))
- {
- t = plus_constant (GET_MODE (src), t,
- INTVAL (XEXP (src, 1)));
- set_reg_known_value (regno, t);
- set_reg_known_equiv_p (regno, false);
- }
- else if (DF_REG_DEF_COUNT (regno) == 1
- && ! rtx_varies_p (src, 1))
+ if (set != 0
+ && REG_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
{
- set_reg_known_value (regno, src);
- set_reg_known_equiv_p (regno, false);
+ unsigned int regno = REGNO (SET_DEST (set));
+ rtx src = SET_SRC (set);
+ rtx t;
+
+ note = find_reg_equal_equiv_note (insn);
+ if (note && REG_NOTE_KIND (note) == REG_EQUAL
+ && DF_REG_DEF_COUNT (regno) != 1)
+ note = NULL_RTX;
+
+ if (note != NULL_RTX
+ && GET_CODE (XEXP (note, 0)) != EXPR_LIST
+ && ! rtx_varies_p (XEXP (note, 0), 1)
+ && ! reg_overlap_mentioned_p (SET_DEST (set),
+ XEXP (note, 0)))
+ {
+ set_reg_known_value (regno, XEXP (note, 0));
+ set_reg_known_equiv_p (regno,
+ REG_NOTE_KIND (note) == REG_EQUIV);
+ }
+ else if (DF_REG_DEF_COUNT (regno) == 1
+ && GET_CODE (src) == PLUS
+ && REG_P (XEXP (src, 0))
+ && (t = get_reg_known_value (REGNO (XEXP (src, 0))))
+ && CONST_INT_P (XEXP (src, 1)))
+ {
+ t = plus_constant (GET_MODE (src), t,
+ INTVAL (XEXP (src, 1)));
+ set_reg_known_value (regno, t);
+ set_reg_known_equiv_p (regno, false);
+ }
+ else if (DF_REG_DEF_COUNT (regno) == 1
+ && ! rtx_varies_p (src, 1))
+ {
+ set_reg_known_value (regno, src);
+ set_reg_known_equiv_p (regno, false);
+ }
}
}
+ else if (NOTE_P (insn)
+ && NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)
+ copying_arguments = false;
}
- else if (NOTE_P (insn)
- && NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)
- copying_arguments = false;
}
/* Now propagate values from new_reg_base_value to reg_base_value. */
}
}
while (changed && ++pass < MAX_ALIAS_LOOP_PASSES);
+ XDELETEVEC (rpo);
/* Fill in the remaining entries. */
FOR_EACH_VEC_ELT (rtx, reg_known_value, i, val)