aboutsummaryrefslogtreecommitdiff
path: root/gcc/loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/loop.c')
-rw-r--r--gcc/loop.c101
1 files changed, 73 insertions, 28 deletions
diff --git a/gcc/loop.c b/gcc/loop.c
index 5d458cbabc8..0ac3717bebf 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -154,12 +154,25 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define PREFETCH_CONDITIONAL 1
#endif
+/* APPLE LOCAL begin avoid out-of-bounds refs */
+/* If the first or last uid lies outside the loop, assume the
+ lifetime extends to that end of the loop. */
#define LOOP_REG_LIFETIME(LOOP, REGNO) \
-((REGNO_LAST_LUID (REGNO) - REGNO_FIRST_LUID (REGNO)))
-
+(((REGNO_LAST_UID (REGNO) > max_uid_for_loop) \
+ ? (INSN_LUID ((LOOP)->end)) \
+ : (REGNO_LAST_LUID (REGNO))) \
+ - ((REGNO_FIRST_UID (REGNO) > max_uid_for_loop) \
+ ? (INSN_LUID ((LOOP)->start)) \
+ : (REGNO_FIRST_LUID (REGNO))))
+
+/* uid's that are too big are derived from nested loops and are
+ not referenced outside this loop, hence they are not global. */
#define LOOP_REG_GLOBAL_P(LOOP, REGNO) \
-((REGNO_LAST_LUID (REGNO) > INSN_LUID ((LOOP)->end) \
- || REGNO_FIRST_LUID (REGNO) < INSN_LUID ((LOOP)->start)))
+((REGNO_LAST_UID (REGNO) > max_uid_for_loop) ? 0 : \
+(((REGNO_FIRST_UID (REGNO) > max_uid_for_loop) ? 0 : \
+((((REGNO_LAST_LUID (REGNO) > INSN_LUID ((LOOP)->end) \
+ || REGNO_FIRST_LUID (REGNO) < INSN_LUID ((LOOP)->start))))))))
+/* APPLE LOCAL end avoid out-of-bounds refs */
#define LOOP_REGNO_NREGS(REGNO, SET_DEST) \
((REGNO) < FIRST_PSEUDO_REGISTER \
@@ -1541,6 +1554,8 @@ combine_movables (struct loop_movables *movables, struct loop_regs *regs)
&& GET_MODE_CLASS (GET_MODE (m1->set_dest)) == MODE_INT
&& (GET_MODE_BITSIZE (GET_MODE (m->set_dest))
>= GET_MODE_BITSIZE (GET_MODE (m1->set_dest)))))
+ /* APPLE LOCAL combine hoisted consts */
+ && m1->regno >= FIRST_PSEUDO_REGISTER
/* See if the source of M1 says it matches M. */
&& ((GET_CODE (m1->set_src) == REG
&& matched_regs[REGNO (m1->set_src)])
@@ -3323,7 +3338,7 @@ loop_invariant_p (const struct loop *loop, rtx x)
We don't know the loop bounds here though, so just fail for all
labels. */
- if (flag_old_unroll_loops)
+ if (flag_unroll_loops)
return 0;
else
return 1;
@@ -4699,13 +4714,26 @@ loop_givs_reduce (struct loop *loop, struct iv_class *bl)
this is an address giv, then try to put the increment
immediately after its use, so that flow can create an
auto-increment addressing mode. */
+ /* APPLE LOCAL begin check loop->top */
+ /* Don't do this for loops entered at the bottom, to avoid
+ this invalid transformation:
+ jmp L; -> jmp L;
+ TOP: TOP:
+ use giv use giv
+ L: inc giv
+ inc biv L:
+ test biv test giv
+ cbr TOP cbr TOP
+ */
if (v->giv_type == DEST_ADDR && bl->biv_count == 1
&& bl->biv->always_executed && ! bl->biv->maybe_multiple
/* We don't handle reversed biv's because bl->biv->insn
does not have a valid INSN_LUID. */
&& ! bl->reversed
&& v->always_executed && ! v->maybe_multiple
- && INSN_UID (v->insn) < max_uid_for_loop)
+ && INSN_UID (v->insn) < max_uid_for_loop
+ && !loop->top)
+ /* APPLE LOCAL end check loop->top */
{
/* If other giv's have been combined with this one, then
this will work only if all uses of the other giv's occur
@@ -4986,6 +5014,24 @@ loop_giv_reduce_benefit (struct loop *loop ATTRIBUTE_UNUSED,
determining code size than run-time benefits. */
benefit -= add_cost * bl->biv_count;
+ /* APPLE LOCAL better induction variable selection */
+#ifdef TARGET_POWERPC
+ /* Adjust this computation to allow for the likelihood that the
+ original increment of the biv will be deleted. This permits
+ induction variables to be selected correctly in simple
+ cases like for(i){a[i]=42;} Without this, choice of induction
+ variables is sensitive to whether the relative stack offset of
+ a is 0 or not(!) On x86 it is probably superior to be more
+ conservative, as there aren't enough registers. */
+ if ( v->replaceable && bl->eliminable )
+ {
+ int orig_add_cost = iv_add_mult_cost (bl->biv->add_val,
+ bl->biv->mult_val, test_reg, test_reg);
+ benefit += orig_add_cost * bl->biv_count;
+ }
+#endif
+ /* APPLE LOCAL end better induction variable selection */
+
/* Decide whether to strength-reduce this giv or to leave the code
unchanged (recompute it from the biv each time it is used). This
decision can be made independently for each giv. */
@@ -4998,7 +5044,8 @@ loop_giv_reduce_benefit (struct loop *loop ATTRIBUTE_UNUSED,
/* Increasing the benefit is risky, since this is only a guess.
Avoid increasing register pressure in cases where there would
be no other benefit from reducing this giv. */
- && benefit > 0
+ /* APPLE LOCAL compare >= 0, not > 0. */
+ && benefit >= 0
&& GET_CODE (v->mult_val) == CONST_INT)
{
int size = GET_MODE_SIZE (GET_MODE (v->mem));
@@ -5288,10 +5335,25 @@ strength_reduce (struct loop *loop, int flags)
value, so we don't need another one. We can't calculate the
proper final value for such a biv here anyways. */
if (bl->final_value && ! bl->reversed)
- loop_insn_sink_or_swim (loop,
- gen_load_of_final_value (bl->biv->dest_reg,
- bl->final_value));
-
+ /* APPLE LOCAL begin put this insn after the loop in all cases */
+ /* Putting it before the loop can cause problems in an
+ obscure case. "a" is the variable we're currently
+ looking at:
+ b <- a
+ loop beginning
+ b++; and references
+ a++; no references
+ if we put the final value for a before the loop, then
+ eliminate b in favor of c later on, we'll get this
+ before the loop:
+ b <- a
+ a <- final value
+ c <- a
+ which is no good. */
+ loop_insn_sink (loop, gen_load_of_final_value (bl->biv->dest_reg,
+ bl->final_value));
+ /* APPLE LOCAL end put this insn after the loop in all cases */
+
if (loop_dump_stream)
fprintf (loop_dump_stream, "Reg %d: biv eliminated\n",
bl->regno);
@@ -5352,23 +5414,6 @@ strength_reduce (struct loop *loop, int flags)
&& unrolled_insn_copies <= insn_count))
unroll_loop (loop, insn_count, 1);
-#ifdef HAVE_doloop_end
- if (HAVE_doloop_end && (flags & LOOP_BCT) && flag_branch_on_count_reg)
- doloop_optimize (loop);
-#endif /* HAVE_doloop_end */
-
- /* In case number of iterations is known, drop branch prediction note
- in the branch. Do that only in second loop pass, as loop unrolling
- may change the number of iterations performed. */
- if (flags & LOOP_BCT)
- {
- unsigned HOST_WIDE_INT n
- = loop_info->n_iterations / loop_info->unroll_number;
- if (n > 1)
- predict_insn (prev_nonnote_insn (loop->end), PRED_LOOP_ITERATIONS,
- REG_BR_PROB_BASE - REG_BR_PROB_BASE / n);
- }
-
if (loop_dump_stream)
fprintf (loop_dump_stream, "\n");