diff options
Diffstat (limited to 'gcc/loop.c')
-rw-r--r-- | gcc/loop.c | 633 |
1 files changed, 343 insertions, 290 deletions
diff --git a/gcc/loop.c b/gcc/loop.c index 2bd19445ae0..149e7d1b97b 100644 --- a/gcc/loop.c +++ b/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 *)); @@ -639,6 +640,7 @@ scan_loop (loop, flags) int threshold; /* Nonzero if we are scanning instructions in a sub-loop. */ int loop_depth = 0; + int in_libcall; loop->top = 0; @@ -755,290 +757,311 @@ scan_loop (loop, flags) When MAYBE_NEVER is 0, all insns will be executed at least once so that is not a problem. */ - for (p = next_insn_in_loop (loop, loop->scan_start); + for (in_libcall = 0, p = next_insn_in_loop (loop, loop->scan_start); p != NULL_RTX; p = next_insn_in_loop (loop, p)) { - if (GET_CODE (p) == INSN - && (set = single_set (p)) - && GET_CODE (SET_DEST (set)) == REG -#ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED - && SET_DEST (set) != pic_offset_table_rtx -#endif - && ! regs->array[REGNO (SET_DEST (set))].may_not_optimize) + if (in_libcall && INSN_P (p) && find_reg_note (p, REG_RETVAL, NULL_RTX)) + in_libcall--; + if (GET_CODE (p) == INSN) { - int tem1 = 0; - int tem2 = 0; - int move_insn = 0; - rtx src = SET_SRC (set); - rtx dependencies = 0; - - /* Figure out what to use as a source of this insn. If a REG_EQUIV - note is given or if a REG_EQUAL note with a constant operand is - specified, use it as the source and mark that we should move - this insn by calling emit_move_insn rather that duplicating the - insn. - - Otherwise, only use the REG_EQUAL contents if a REG_RETVAL note - is present. */ - temp = find_reg_note (p, REG_EQUIV, NULL_RTX); + temp = find_reg_note (p, REG_LIBCALL, NULL_RTX); if (temp) - src = XEXP (temp, 0), move_insn = 1; - else + in_libcall++; + if (! in_libcall + && (set = single_set (p)) + && GET_CODE (SET_DEST (set)) == REG +#ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED + && SET_DEST (set) != pic_offset_table_rtx +#endif + && ! regs->array[REGNO (SET_DEST (set))].may_not_optimize) { - temp = find_reg_note (p, REG_EQUAL, NULL_RTX); - if (temp && CONSTANT_P (XEXP (temp, 0))) + int tem1 = 0; + int tem2 = 0; + int move_insn = 0; + rtx src = SET_SRC (set); + rtx dependencies = 0; + + /* Figure out what to use as a source of this insn. If a + REG_EQUIV note is given or if a REG_EQUAL note with a + constant operand is specified, use it as the source and + mark that we should move this insn by calling + emit_move_insn rather that duplicating the insn. + + Otherwise, only use the REG_EQUAL contents if a REG_RETVAL + note is present. */ + temp = find_reg_note (p, REG_EQUIV, NULL_RTX); + if (temp) src = XEXP (temp, 0), move_insn = 1; - if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX)) + else { - src = XEXP (temp, 0); - /* A libcall block can use regs that don't appear in - the equivalent expression. To move the libcall, - we must move those regs too. */ - dependencies = libcall_other_reg (p, src); + temp = find_reg_note (p, REG_EQUAL, NULL_RTX); + if (temp && CONSTANT_P (XEXP (temp, 0))) + src = XEXP (temp, 0), move_insn = 1; + if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX)) + { + src = XEXP (temp, 0); + /* A libcall block can use regs that don't appear in + the equivalent expression. To move the libcall, + we must move those regs too. */ + dependencies = libcall_other_reg (p, src); + } } - } - /* For parallels, add any possible uses to the depencies, as we can't move - the insn without resolving them first. */ - if (GET_CODE (PATTERN (p)) == PARALLEL) - { - for (i = 0; i < XVECLEN (PATTERN (p), 0); i++) + /* For parallels, add any possible uses to the depencies, as + we can't move the insn without resolving them first. */ + if (GET_CODE (PATTERN (p)) == PARALLEL) { - rtx x = XVECEXP (PATTERN (p), 0, i); - if (GET_CODE (x) == USE) - dependencies = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0), dependencies); - } - } - - /* Don't try to optimize a register that was made - by loop-optimization for an inner loop. - We don't know its life-span, so we can't compute the benefit. */ - if (REGNO (SET_DEST (set)) >= max_reg_before_loop) - ; - else if (/* The register is used in basic blocks other - than the one where it is set (meaning that - something after this point in the loop might - depend on its value before the set). */ - ! reg_in_basic_block_p (p, SET_DEST (set)) - /* And the set is not guaranteed to be executed once - the loop starts, or the value before the set is - needed before the set occurs... - - ??? Note we have quadratic behaviour here, mitigated - by the fact that the previous test will often fail for - large loops. Rather than re-scanning the entire loop - each time for register usage, we should build tables - of the register usage and use them here instead. */ - && (maybe_never - || loop_reg_used_before_p (loop, set, p))) - /* It is unsafe to move the set. - - This code used to consider it OK to move a set of a variable - which was not created by the user and not used in an exit test. - That behavior is incorrect and was removed. */ - ; - else if ((tem = loop_invariant_p (loop, src)) - && (dependencies == 0 - || (tem2 = loop_invariant_p (loop, dependencies)) != 0) - && (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1 - || (tem1 - = consec_sets_invariant_p - (loop, SET_DEST (set), - regs->array[REGNO (SET_DEST (set))].set_in_loop, - p))) - /* If the insn can cause a trap (such as divide by zero), - can't move it unless it's guaranteed to be executed - once loop is entered. Even a function call might - prevent the trap insn from being reached - (since it might exit!) */ - && ! ((maybe_never || call_passed) - && may_trap_p (src))) - { - struct movable *m; - int regno = REGNO (SET_DEST (set)); - - /* A potential lossage is where we have a case where two insns - can be combined as long as they are both in the loop, but - we move one of them outside the loop. For large loops, - this can lose. The most common case of this is the address - of a function being called. - - Therefore, if this register is marked as being used exactly - once if we are in a loop with calls (a "large loop"), see if - we can replace the usage of this register with the source - of this SET. If we can, delete this insn. - - Don't do this if P has a REG_RETVAL note or if we have - SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */ - - if (loop_info->has_call - && regs->array[regno].single_usage != 0 - && regs->array[regno].single_usage != const0_rtx - && REGNO_FIRST_UID (regno) == INSN_UID (p) - && (REGNO_LAST_UID (regno) - == INSN_UID (regs->array[regno].single_usage)) - && regs->array[regno].set_in_loop == 1 - && GET_CODE (SET_SRC (set)) != ASM_OPERANDS - && ! side_effects_p (SET_SRC (set)) - && ! find_reg_note (p, REG_RETVAL, NULL_RTX) - && (! SMALL_REGISTER_CLASSES - || (! (GET_CODE (SET_SRC (set)) == REG - && REGNO (SET_SRC (set)) < FIRST_PSEUDO_REGISTER))) - /* This test is not redundant; SET_SRC (set) might be - a call-clobbered register and the life of REGNO - might span a call. */ - && ! modified_between_p (SET_SRC (set), p, - regs->array[regno].single_usage) - && no_labels_between_p (p, regs->array[regno].single_usage) - && validate_replace_rtx (SET_DEST (set), SET_SRC (set), - regs->array[regno].single_usage)) - { - /* Replace any usage in a REG_EQUAL note. Must copy the - new source, so that we don't get rtx sharing between the - SET_SOURCE and REG_NOTES of insn p. */ - REG_NOTES (regs->array[regno].single_usage) - = replace_rtx (REG_NOTES (regs->array[regno].single_usage), - SET_DEST (set), copy_rtx (SET_SRC (set))); - - delete_insn (p); - for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++) - regs->array[regno+i].set_in_loop = 0; - continue; + for (i = 0; i < XVECLEN (PATTERN (p), 0); i++) + { + rtx x = XVECEXP (PATTERN (p), 0, i); + if (GET_CODE (x) == USE) + dependencies + = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0), + dependencies); + } } - m = (struct movable *) xmalloc (sizeof (struct movable)); - m->next = 0; - m->insn = p; - m->set_src = src; - m->dependencies = dependencies; - m->set_dest = SET_DEST (set); - m->force = 0; - m->consec = regs->array[REGNO (SET_DEST (set))].set_in_loop - 1; - m->done = 0; - m->forces = 0; - m->partial = 0; - m->move_insn = move_insn; - m->move_insn_first = 0; - m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0); - m->savemode = VOIDmode; - m->regno = regno; - /* Set M->cond if either loop_invariant_p - or consec_sets_invariant_p returned 2 - (only conditionally invariant). */ - m->cond = ((tem | tem1 | tem2) > 1); - m->global = LOOP_REG_GLOBAL_P (loop, regno); - m->match = 0; - m->lifetime = LOOP_REG_LIFETIME (loop, regno); - m->savings = regs->array[regno].n_times_set; - if (find_reg_note (p, REG_RETVAL, NULL_RTX)) - m->savings += libcall_benefit (p); - for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++) - regs->array[regno+i].set_in_loop = move_insn ? -2 : -1; - /* Add M to the end of the chain MOVABLES. */ - loop_movables_add (movables, m); - - if (m->consec > 0) + /* Don't try to optimize a register that was made + by loop-optimization for an inner loop. + We don't know its life-span, so we can't compute + the benefit. */ + if (REGNO (SET_DEST (set)) >= max_reg_before_loop) + ; + else if (/* The register is used in basic blocks other + than the one where it is set (meaning that + something after this point in the loop might + depend on its value before the set). */ + ! reg_in_basic_block_p (p, SET_DEST (set)) + /* And the set is not guaranteed to be executed once + the loop starts, or the value before the set is + needed before the set occurs... + + ??? Note we have quadratic behaviour here, mitigated + by the fact that the previous test will often fail for + large loops. Rather than re-scanning the entire loop + each time for register usage, we should build tables + of the register usage and use them here instead. */ + && (maybe_never + || loop_reg_used_before_p (loop, set, p))) + /* It is unsafe to move the set. + + This code used to consider it OK to move a set of a variable + which was not created by the user and not used in an exit + test. + That behavior is incorrect and was removed. */ + ; + else if ((tem = loop_invariant_p (loop, src)) + && (dependencies == 0 + || (tem2 + = loop_invariant_p (loop, dependencies)) != 0) + && (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1 + || (tem1 + = consec_sets_invariant_p + (loop, SET_DEST (set), + regs->array[REGNO (SET_DEST (set))].set_in_loop, + p))) + /* If the insn can cause a trap (such as divide by zero), + can't move it unless it's guaranteed to be executed + once loop is entered. Even a function call might + prevent the trap insn from being reached + (since it might exit!) */ + && ! ((maybe_never || call_passed) + && may_trap_p (src))) { - /* It is possible for the first instruction to have a - REG_EQUAL note but a non-invariant SET_SRC, so we must - remember the status of the first instruction in case - the last instruction doesn't have a REG_EQUAL note. */ - m->move_insn_first = m->move_insn; - - /* Skip this insn, not checking REG_LIBCALL notes. */ - p = next_nonnote_insn (p); - /* Skip the consecutive insns, if there are any. */ - p = skip_consec_insns (p, m->consec); - /* Back up to the last insn of the consecutive group. */ - p = prev_nonnote_insn (p); - - /* We must now reset m->move_insn, m->is_equiv, and possibly - m->set_src to correspond to the effects of all the - insns. */ - temp = find_reg_note (p, REG_EQUIV, NULL_RTX); - if (temp) - m->set_src = XEXP (temp, 0), m->move_insn = 1; - else + struct movable *m; + int regno = REGNO (SET_DEST (set)); + + /* A potential lossage is where we have a case where two insns + can be combined as long as they are both in the loop, but + we move one of them outside the loop. For large loops, + this can lose. The most common case of this is the address + of a function being called. + + Therefore, if this register is marked as being used + exactly once if we are in a loop with calls + (a "large loop"), see if we can replace the usage of + this register with the source of this SET. If we can, + delete this insn. + + Don't do this if P has a REG_RETVAL note or if we have + SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */ + + if (loop_info->has_call + && regs->array[regno].single_usage != 0 + && regs->array[regno].single_usage != const0_rtx + && REGNO_FIRST_UID (regno) == INSN_UID (p) + && (REGNO_LAST_UID (regno) + == INSN_UID (regs->array[regno].single_usage)) + && regs->array[regno].set_in_loop == 1 + && GET_CODE (SET_SRC (set)) != ASM_OPERANDS + && ! side_effects_p (SET_SRC (set)) + && ! find_reg_note (p, REG_RETVAL, NULL_RTX) + && (! SMALL_REGISTER_CLASSES + || (! (GET_CODE (SET_SRC (set)) == REG + && (REGNO (SET_SRC (set)) + < FIRST_PSEUDO_REGISTER)))) + /* This test is not redundant; SET_SRC (set) might be + a call-clobbered register and the life of REGNO + might span a call. */ + && ! modified_between_p (SET_SRC (set), p, + regs->array[regno].single_usage) + && no_labels_between_p (p, + regs->array[regno].single_usage) + && validate_replace_rtx (SET_DEST (set), SET_SRC (set), + regs->array[regno].single_usage)) { - temp = find_reg_note (p, REG_EQUAL, NULL_RTX); - if (temp && CONSTANT_P (XEXP (temp, 0))) - m->set_src = XEXP (temp, 0), m->move_insn = 1; - else - m->move_insn = 0; + /* Replace any usage in a REG_EQUAL note. Must copy + the new source, so that we don't get rtx sharing + between the SET_SOURCE and REG_NOTES of insn p. */ + REG_NOTES (regs->array[regno].single_usage) + = (replace_rtx + (REG_NOTES (regs->array[regno].single_usage), + SET_DEST (set), copy_rtx (SET_SRC (set)))); + delete_insn (p); + for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); + i++) + regs->array[regno+i].set_in_loop = 0; + continue; } - m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0); - } - } - /* If this register is always set within a STRICT_LOW_PART - or set to zero, then its high bytes are constant. - So clear them outside the loop and within the loop - just load the low bytes. - We must check that the machine has an instruction to do so. - Also, if the value loaded into the register - depends on the same register, this cannot be done. */ - else if (SET_SRC (set) == const0_rtx - && GET_CODE (NEXT_INSN (p)) == INSN - && (set1 = single_set (NEXT_INSN (p))) - && GET_CODE (set1) == SET - && (GET_CODE (SET_DEST (set1)) == STRICT_LOW_PART) - && (GET_CODE (XEXP (SET_DEST (set1), 0)) == SUBREG) - && (SUBREG_REG (XEXP (SET_DEST (set1), 0)) - == SET_DEST (set)) - && !reg_mentioned_p (SET_DEST (set), SET_SRC (set1))) - { - int regno = REGNO (SET_DEST (set)); - if (regs->array[regno].set_in_loop == 2) - { - struct movable *m; + m = (struct movable *) xmalloc (sizeof (struct movable)); m->next = 0; m->insn = p; + m->set_src = src; + m->dependencies = dependencies; m->set_dest = SET_DEST (set); - m->dependencies = 0; m->force = 0; - m->consec = 0; + m->consec + = regs->array[REGNO (SET_DEST (set))].set_in_loop - 1; m->done = 0; m->forces = 0; - m->move_insn = 0; + m->partial = 0; + m->move_insn = move_insn; m->move_insn_first = 0; - m->partial = 1; - /* If the insn may not be executed on some cycles, - we can't clear the whole reg; clear just high part. - Not even if the reg is used only within this loop. - Consider this: - while (1) - while (s != t) { - if (foo ()) x = *s; - use (x); - } - Clearing x before the inner loop could clobber a value - being saved from the last time around the outer loop. - However, if the reg is not used outside this loop - and all uses of the register are in the same - basic block as the store, there is no problem. - - If this insn was made by loop, we don't know its - INSN_LUID and hence must make a conservative - assumption. */ - m->global = (INSN_UID (p) >= max_uid_for_loop - || LOOP_REG_GLOBAL_P (loop, regno) - || (labels_in_range_p - (p, REGNO_FIRST_LUID (regno)))); - if (maybe_never && m->global) - m->savemode = GET_MODE (SET_SRC (set1)); - else - m->savemode = VOIDmode; + m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0); + m->savemode = VOIDmode; m->regno = regno; - m->cond = 0; + /* Set M->cond if either loop_invariant_p + or consec_sets_invariant_p returned 2 + (only conditionally invariant). */ + m->cond = ((tem | tem1 | tem2) > 1); + m->global = LOOP_REG_GLOBAL_P (loop, regno); m->match = 0; m->lifetime = LOOP_REG_LIFETIME (loop, regno); - m->savings = 1; + m->savings = regs->array[regno].n_times_set; + if (find_reg_note (p, REG_RETVAL, NULL_RTX)) + m->savings += libcall_benefit (p); for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++) - regs->array[regno+i].set_in_loop = -1; + regs->array[regno+i].set_in_loop = move_insn ? -2 : -1; /* Add M to the end of the chain MOVABLES. */ loop_movables_add (movables, m); + + if (m->consec > 0) + { + /* It is possible for the first instruction to have a + REG_EQUAL note but a non-invariant SET_SRC, so we must + remember the status of the first instruction in case + the last instruction doesn't have a REG_EQUAL note. */ + m->move_insn_first = m->move_insn; + + /* Skip this insn, not checking REG_LIBCALL notes. */ + p = next_nonnote_insn (p); + /* Skip the consecutive insns, if there are any. */ + p = skip_consec_insns (p, m->consec); + /* Back up to the last insn of the consecutive group. */ + p = prev_nonnote_insn (p); + + /* We must now reset m->move_insn, m->is_equiv, and + possibly m->set_src to correspond to the effects of + all the insns. */ + temp = find_reg_note (p, REG_EQUIV, NULL_RTX); + if (temp) + m->set_src = XEXP (temp, 0), m->move_insn = 1; + else + { + temp = find_reg_note (p, REG_EQUAL, NULL_RTX); + if (temp && CONSTANT_P (XEXP (temp, 0))) + m->set_src = XEXP (temp, 0), m->move_insn = 1; + else + m->move_insn = 0; + + } + m->is_equiv + = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0); + } + } + /* If this register is always set within a STRICT_LOW_PART + or set to zero, then its high bytes are constant. + So clear them outside the loop and within the loop + just load the low bytes. + We must check that the machine has an instruction to do so. + Also, if the value loaded into the register + depends on the same register, this cannot be done. */ + else if (SET_SRC (set) == const0_rtx + && GET_CODE (NEXT_INSN (p)) == INSN + && (set1 = single_set (NEXT_INSN (p))) + && GET_CODE (set1) == SET + && (GET_CODE (SET_DEST (set1)) == STRICT_LOW_PART) + && (GET_CODE (XEXP (SET_DEST (set1), 0)) == SUBREG) + && (SUBREG_REG (XEXP (SET_DEST (set1), 0)) + == SET_DEST (set)) + && !reg_mentioned_p (SET_DEST (set), SET_SRC (set1))) + { + int regno = REGNO (SET_DEST (set)); + if (regs->array[regno].set_in_loop == 2) + { + struct movable *m; + m = (struct movable *) xmalloc (sizeof (struct movable)); + m->next = 0; + m->insn = p; + m->set_dest = SET_DEST (set); + m->dependencies = 0; + m->force = 0; + m->consec = 0; + m->done = 0; + m->forces = 0; + m->move_insn = 0; + m->move_insn_first = 0; + m->partial = 1; + /* If the insn may not be executed on some cycles, + we can't clear the whole reg; clear just high part. + Not even if the reg is used only within this loop. + Consider this: + while (1) + while (s != t) { + if (foo ()) x = *s; + use (x); + } + Clearing x before the inner loop could clobber a value + being saved from the last time around the outer loop. + However, if the reg is not used outside this loop + and all uses of the register are in the same + basic block as the store, there is no problem. + + If this insn was made by loop, we don't know its + INSN_LUID and hence must make a conservative + assumption. */ + m->global = (INSN_UID (p) >= max_uid_for_loop + || LOOP_REG_GLOBAL_P (loop, regno) + || (labels_in_range_p + (p, REGNO_FIRST_LUID (regno)))); + if (maybe_never && m->global) + m->savemode = GET_MODE (SET_SRC (set1)); + else + m->savemode = VOIDmode; + m->regno = regno; + m->cond = 0; + m->match = 0; + m->lifetime = LOOP_REG_LIFETIME (loop, regno); + m->savings = 1; + for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); + i++) + regs->array[regno+i].set_in_loop = -1; + /* Add M to the end of the chain MOVABLES. */ + loop_movables_add (movables, m); + } } } } @@ -1910,10 +1933,10 @@ move_movables (loop, movables, threshold, insn_count) for (count = m->consec; count >= 0; count--) { /* If this is the first insn of a library call sequence, - skip to the end. */ + something is very wrong. */ if (GET_CODE (p) != NOTE && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX))) - p = XEXP (temp, 0); + abort (); /* If this is the last insn of a libcall sequence, then delete every insn in the sequence except the last. @@ -2492,6 +2515,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; @@ -2504,16 +2529,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; } @@ -2607,6 +2633,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. */ @@ -2693,23 +2730,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. @@ -2733,11 +2759,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) @@ -4039,6 +4061,7 @@ emit_prefetch_instructions (loop) int bytes_ahead = PREFETCH_BLOCK * (ahead + y); rtx before_insn = info[i].giv->insn; rtx prev_insn = PREV_INSN (info[i].giv->insn); + rtx seq; /* We can save some effort by offsetting the address on architectures with offsettable memory references. */ @@ -4053,14 +4076,17 @@ emit_prefetch_instructions (loop) loc = reg; } + start_sequence (); /* Make sure the address operand is valid for prefetch. */ if (! (*insn_data[(int)CODE_FOR_prefetch].operand[0].predicate) (loc, insn_data[(int)CODE_FOR_prefetch].operand[0].mode)) loc = force_reg (Pmode, loc); - emit_insn_before (gen_prefetch (loc, GEN_INT (info[i].write), - GEN_INT (3)), - before_insn); + emit_insn (gen_prefetch (loc, GEN_INT (info[i].write), + GEN_INT (3))); + seq = gen_sequence (); + end_sequence (); + emit_insn_before (seq, before_insn); /* Check all insns emitted and record the new GIV information. */ @@ -4086,11 +4112,17 @@ emit_prefetch_instructions (loop) { rtx reg = gen_reg_rtx (Pmode); rtx loop_start = loop->start; + rtx init_val = info[i].class->initial_value; rtx add_val = simplify_gen_binary (PLUS, Pmode, info[i].giv->add_val, GEN_INT (y * PREFETCH_BLOCK)); - loop_iv_add_mult_emit_before (loop, info[i].class->initial_value, + /* Functions called by LOOP_IV_ADD_EMIT_BEFORE expect a + non-constant INIT_VAL to have the same mode as REG, which + in this case we know to be Pmode. */ + if (GET_MODE (init_val) != Pmode && !CONSTANT_P (init_val)) + init_val = convert_to_mode (Pmode, init_val, 0); + loop_iv_add_mult_emit_before (loop, init_val, info[i].giv->mult_val, add_val, reg, 0, loop_start); emit_insn_before (gen_prefetch (reg, GEN_INT (info[i].write), @@ -5212,7 +5244,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); @@ -5846,7 +5879,7 @@ check_final_value (loop, v) #endif if ((final_value = final_giv_value (loop, v)) - && (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn))) + && (v->always_executed || last_use_this_basic_block (v->dest_reg, v->insn))) { int biv_increment_seen = 0, before_giv_insn = 0; rtx p = v->insn; @@ -6213,10 +6246,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); @@ -9258,7 +9292,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg) { case LE: if ((unsigned HOST_WIDE_INT) const_val != max_val >> 1) - code = LT, op1 = GEN_INT (const_val + 1); + code = LT, op1 = gen_int_mode (const_val + 1, GET_MODE (op0)); break; /* When cross-compiling, const_val might be sign-extended from @@ -9267,17 +9301,17 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg) if ((HOST_WIDE_INT) (const_val & max_val) != (((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1)))) - code = GT, op1 = GEN_INT (const_val - 1); + code = GT, op1 = gen_int_mode (const_val - 1, GET_MODE (op0)); break; case LEU: if (uconst_val < max_val) - code = LTU, op1 = GEN_INT (uconst_val + 1); + code = LTU, op1 = gen_int_mode (uconst_val + 1, GET_MODE (op0)); break; case GEU: if (uconst_val != 0) - code = GTU, op1 = GEN_INT (uconst_val - 1); + code = GTU, op1 = gen_int_mode (uconst_val - 1, GET_MODE (op0)); break; default: @@ -9526,6 +9560,25 @@ loop_regs_scan (loop, extra_size) if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN) memset (last_set, 0, regs->num * sizeof (rtx)); + + /* Invalidate all registers used for function argument passing. + We check rtx_varies_p for the same reason as below, to allow + optimizing PIC calculations. */ + if (GET_CODE (insn) == CALL_INSN) + { + rtx link; + for (link = CALL_INSN_FUNCTION_USAGE (insn); + link; + link = XEXP (link, 1)) + { + rtx op, reg; + + if (GET_CODE (op = XEXP (link, 0)) == USE + && GET_CODE (reg = XEXP (op, 0)) == REG + && rtx_varies_p (reg, 1)) + regs->array[REGNO (reg)].may_not_optimize = 1; + } + } } /* Invalidate all hard registers clobbered by calls. With one exception: |