aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/alias.c140
-rw-r--r--gcc/tracer.c2
3 files changed, 89 insertions, 63 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f67c4ac..527f822a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2012-08-22 Steven Bosscher <steven@gcc.gnu.org>
+
+ * tracer.c (mark_bb_seen): Use SBITMAP_SIZE.
+
+ * alias.c (MAX_ALIAS_LOOP_PASSES): Update comment with rationale,
+ or rather a lack thereof.
+ (init_alias_analysis): Propagate the latest information across
+ the CFG in topological order to propagate as far as possible in
+ each iteration. Ignore debug insns.
+
2012-08-22 H.J. Lu <hongjiu.lu@intel.com>
* doc/invoke.texi: Document -mlong-double-64/-mlong-double-80.
diff --git a/gcc/alias.c b/gcc/alias.c
index de7640f..a26c299 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -168,7 +168,10 @@ static void memory_modified_1 (rtx, const_rtx, void *);
#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.
@@ -2764,6 +2767,8 @@ init_alias_analysis (void)
int i;
unsigned int ui;
rtx insn, val;
+ int rpo_cnt;
+ int *rpo;
timevar_push (TV_ALIAS_ANALYSIS);
@@ -2786,6 +2791,9 @@ init_alias_analysis (void)
"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.
@@ -2801,6 +2809,9 @@ init_alias_analysis (void)
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
{
@@ -2833,80 +2844,84 @@ init_alias_analysis (void)
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. */
@@ -2925,6 +2940,7 @@ init_alias_analysis (void)
}
}
while (changed && ++pass < MAX_ALIAS_LOOP_PASSES);
+ XDELETEVEC (rpo);
/* Fill in the remaining entries. */
FOR_EACH_VEC_ELT (rtx, reg_known_value, i, val)
diff --git a/gcc/tracer.c b/gcc/tracer.c
index f60f348..9b1d724 100644
--- a/gcc/tracer.c
+++ b/gcc/tracer.c
@@ -69,7 +69,7 @@ sbitmap bb_seen;
static inline void
mark_bb_seen (basic_block bb)
{
- unsigned int size = SBITMAP_SIZE_BYTES (bb_seen) * 8;
+ unsigned int size = SBITMAP_SIZE (bb_seen);
if ((unsigned int)bb->index >= size)
bb_seen = sbitmap_resize (bb_seen, size * 2, 0);