diff options
Diffstat (limited to 'contrib/gcc/loop.c')
-rw-r--r-- | contrib/gcc/loop.c | 118 |
1 files changed, 77 insertions, 41 deletions
diff --git a/contrib/gcc/loop.c b/contrib/gcc/loop.c index a65595f..d653b5c 100644 --- a/contrib/gcc/loop.c +++ b/contrib/gcc/loop.c @@ -235,6 +235,7 @@ FILE *loop_dump_stream; /* Forward declarations. */ +static void invalidate_loops_containing_label PARAMS ((rtx)); static void find_and_verify_loops PARAMS ((rtx, struct loops *)); static void mark_loop_jump PARAMS ((rtx, struct loop *)); static void prescan_loop PARAMS ((struct loop *)); @@ -1102,7 +1103,25 @@ scan_loop (loop, flags) optimizing for code size. */ if (! optimize_size) - move_movables (loop, movables, threshold, insn_count); + { + move_movables (loop, movables, threshold, insn_count); + + /* Recalculate regs->array if move_movables has created new + registers. */ + if (max_reg_num () > regs->num) + { + loop_regs_scan (loop, 0); + for (update_start = loop_start; + PREV_INSN (update_start) + && GET_CODE (PREV_INSN (update_start)) != CODE_LABEL; + update_start = PREV_INSN (update_start)) + ; + update_end = NEXT_INSN (loop_end); + + reg_scan_update (update_start, update_end, loop_max_reg); + loop_max_reg = max_reg_num (); + } + } /* Now candidates that still are negative are those not moved. Change regs->array[I].set_in_loop to indicate that those are not actually @@ -2474,6 +2493,8 @@ prescan_loop (loop) loop_info->unknown_address_altered = 1; loop_info->has_nonconst_call = 1; } + else if (pure_call_p (insn)) + loop_info->has_nonconst_call = 1; loop_info->has_call = 1; if (can_throw_internal (insn)) loop_info->has_multiple_exit_targets = 1; @@ -2486,16 +2507,17 @@ prescan_loop (loop) if (set) { + rtx src = SET_SRC (set); rtx label1, label2; - if (GET_CODE (SET_SRC (set)) == IF_THEN_ELSE) + if (GET_CODE (src) == IF_THEN_ELSE) { - label1 = XEXP (SET_SRC (set), 1); - label2 = XEXP (SET_SRC (set), 2); + label1 = XEXP (src, 1); + label2 = XEXP (src, 2); } else { - label1 = SET_SRC (PATTERN (insn)); + label1 = src; label2 = NULL_RTX; } @@ -2589,6 +2611,17 @@ prescan_loop (loop) } } +/* Invalidate all loops containing LABEL. */ + +static void +invalidate_loops_containing_label (label) + rtx label; +{ + struct loop *loop; + for (loop = uid_loop[INSN_UID (label)]; loop; loop = loop->outer) + loop->invalid = 1; +} + /* Scan the function looking for loops. Record the start and end of each loop. Also mark as invalid loops any loops that contain a setjmp or are branched to from outside the loop. */ @@ -2675,23 +2708,12 @@ find_and_verify_loops (f, loops) /* Any loop containing a label used in an initializer must be invalidated, because it can be jumped into from anywhere. */ - for (label = forced_labels; label; label = XEXP (label, 1)) - { - for (loop = uid_loop[INSN_UID (XEXP (label, 0))]; - loop; loop = loop->outer) - loop->invalid = 1; - } + invalidate_loops_containing_label (XEXP (label, 0)); /* Any loop containing a label used for an exception handler must be invalidated, because it can be jumped into from anywhere. */ - - for (label = exception_handler_labels; label; label = XEXP (label, 1)) - { - for (loop = uid_loop[INSN_UID (XEXP (label, 0))]; - loop; loop = loop->outer) - loop->invalid = 1; - } + for_each_eh_label (invalidate_loops_containing_label); /* Now scan all insn's in the function. If any JUMP_INSN branches into a loop that it is not contained within, that loop is marked invalid. @@ -2715,11 +2737,7 @@ find_and_verify_loops (f, loops) { rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX); if (note) - { - for (loop = uid_loop[INSN_UID (XEXP (note, 0))]; - loop; loop = loop->outer) - loop->invalid = 1; - } + invalidate_loops_containing_label (XEXP (note, 0)); } if (GET_CODE (insn) != JUMP_INSN) @@ -3683,8 +3701,19 @@ remove_constant_addition (x) HOST_WIDE_INT addval = 0; rtx exp = *x; + /* Avoid clobbering a shared CONST expression. */ if (GET_CODE (exp) == CONST) - exp = XEXP (exp, 0); + { + if (GET_CODE (XEXP (exp, 0)) == PLUS + && GET_CODE (XEXP (XEXP (exp, 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (exp, 0), 1)) == CONST_INT) + { + *x = XEXP (XEXP (exp, 0), 0); + return INTVAL (XEXP (XEXP (exp, 0), 1)); + } + return 0; + } + if (GET_CODE (exp) == CONST_INT) { addval = INTVAL (exp); @@ -5132,6 +5161,11 @@ strength_reduce (loop, flags) fprintf (loop_dump_stream, "Reg %d: biv eliminated\n", bl->regno); } + /* See above note wrt final_value. But since we couldn't eliminate + the biv, we must set the value after the loop instead of before. */ + else if (bl->final_value && ! bl->reversed) + loop_insn_sink (loop, gen_move_insn (bl->biv->dest_reg, + bl->final_value)); } /* Go through all the instructions in the loop, making all the @@ -5178,7 +5212,8 @@ strength_reduce (loop, flags) collected. Always unroll loops that would be as small or smaller unrolled than when rolled. */ if ((flags & LOOP_UNROLL) - || (loop_info->n_iterations > 0 + || (!(flags & LOOP_FIRST_PASS) + && loop_info->n_iterations > 0 && unrolled_insn_copies <= insn_count)) unroll_loop (loop, insn_count, 1); @@ -6111,13 +6146,13 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location) return 1; case SUBREG: - /* If this is a SUBREG for a promoted variable, check the inner - value. */ - if (SUBREG_PROMOTED_VAR_P (x)) - return basic_induction_var (loop, SUBREG_REG (x), - GET_MODE (SUBREG_REG (x)), - dest_reg, p, inc_val, mult_val, location); - return 0; + /* If what's inside the SUBREG is a BIV, then the SUBREG. This will + handle addition of promoted variables. + ??? The comment at the start of this function is wrong: promoted + variable increments don't look like it says they do. */ + return basic_induction_var (loop, SUBREG_REG (x), + GET_MODE (SUBREG_REG (x)), + dest_reg, p, inc_val, mult_val, location); case REG: /* If this register is assigned in a previous insn, look at its @@ -6179,10 +6214,11 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location) case CONST: /* convert_modes aborts if we try to convert to or from CCmode, so just exclude that case. It is very unlikely that a condition code value - would be a useful iterator anyways. */ + would be a useful iterator anyways. convert_modes aborts if we try to + convert a float mode to non-float or vice versa too. */ if (loop->level == 1 - && GET_MODE_CLASS (mode) != MODE_CC - && GET_MODE_CLASS (GET_MODE (dest_reg)) != MODE_CC) + && GET_MODE_CLASS (mode) == GET_MODE_CLASS (GET_MODE (dest_reg)) + && GET_MODE_CLASS (mode) != MODE_CC) { /* Possible bug here? Perhaps we don't know the mode of X. */ *inc_val = convert_modes (GET_MODE (dest_reg), mode, x, 0); @@ -7626,9 +7662,9 @@ loop_regs_update (loop, seq) } else { - rtx set = single_set (seq); - if (set && GET_CODE (SET_DEST (set)) == REG) - record_base_value (REGNO (SET_DEST (set)), SET_SRC (set), 0); + if (GET_CODE (seq) == SET + && GET_CODE (SET_DEST (seq)) == REG) + record_base_value (REGNO (SET_DEST (seq)), SET_SRC (seq), 0); } } @@ -7654,7 +7690,7 @@ loop_iv_add_mult_emit_before (loop, b, m, a, reg, before_bb, before_insn) } /* Use copy_rtx to prevent unexpected sharing of these rtx. */ - seq = gen_add_mult (copy_rtx (b), m, copy_rtx (a), reg); + seq = gen_add_mult (copy_rtx (b), copy_rtx (m), copy_rtx (a), reg); /* Increase the lifetime of any invariants moved further in code. */ update_reg_last_use (a, before_insn); @@ -7682,7 +7718,7 @@ loop_iv_add_mult_sink (loop, b, m, a, reg) rtx seq; /* Use copy_rtx to prevent unexpected sharing of these rtx. */ - seq = gen_add_mult (copy_rtx (b), m, copy_rtx (a), reg); + seq = gen_add_mult (copy_rtx (b), copy_rtx (m), copy_rtx (a), reg); /* Increase the lifetime of any invariants moved further in code. ???? Is this really necessary? */ @@ -7711,7 +7747,7 @@ loop_iv_add_mult_hoist (loop, b, m, a, reg) rtx seq; /* Use copy_rtx to prevent unexpected sharing of these rtx. */ - seq = gen_add_mult (copy_rtx (b), m, copy_rtx (a), reg); + seq = gen_add_mult (copy_rtx (b), copy_rtx (m), copy_rtx (a), reg); loop_insn_hoist (loop, seq); |