diff options
Diffstat (limited to 'gcc/loop.c')
-rw-r--r-- | gcc/loop.c | 101 |
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"); |