diff options
Diffstat (limited to 'gcc/loop.c')
-rw-r--r-- | gcc/loop.c | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/gcc/loop.c b/gcc/loop.c index 2b765c821d8..08aabfa37ec 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -502,12 +502,25 @@ struct loop_info #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 \ @@ -1893,6 +1906,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. */ && ((REG_P (m1->set_src) && matched_regs[REGNO (m1->set_src)]) @@ -4655,12 +4670,18 @@ for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall) int not_every_iteration = 0; int maybe_multiple = 0; int past_loop_latch = 0; + bool exit_test_is_entry = false; rtx p; - /* If loop_scan_start points to the loop exit test, we have to be wary of - subversive use of gotos inside expression statements. */ + /* If loop_scan_start points to the loop exit test, the loop body + cannot be counted on running on every iteration, and we have to + be wary of subversive use of gotos inside expression + statements. */ if (prev_nonnote_insn (loop->scan_start) != prev_nonnote_insn (loop->start)) - maybe_multiple = back_branch_in_range_p (loop, loop->scan_start); + { + exit_test_is_entry = true; + maybe_multiple = back_branch_in_range_p (loop, loop->scan_start); + } /* Scan through loop and update NOT_EVERY_ITERATION and MAYBE_MULTIPLE. */ for (p = next_insn_in_loop (loop, loop->scan_start); @@ -4718,10 +4739,12 @@ for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall) beginning, don't set not_every_iteration for that. This can be any kind of jump, since we want to know if insns will be executed if the loop is executed. */ - && !(JUMP_LABEL (p) == loop->top - && ((NEXT_INSN (NEXT_INSN (p)) == loop->end - && any_uncondjump_p (p)) - || (NEXT_INSN (p) == loop->end && any_condjump_p (p))))) + && (exit_test_is_entry + || !(JUMP_LABEL (p) == loop->top + && ((NEXT_INSN (NEXT_INSN (p)) == loop->end + && any_uncondjump_p (p)) + || (NEXT_INSN (p) == loop->end + && any_condjump_p (p)))))) { rtx label = 0; @@ -5571,7 +5594,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)); @@ -6504,10 +6528,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); |