diff options
Diffstat (limited to 'contrib/gcc/doloop.c')
-rw-r--r-- | contrib/gcc/doloop.c | 882 |
1 files changed, 0 insertions, 882 deletions
diff --git a/contrib/gcc/doloop.c b/contrib/gcc/doloop.c deleted file mode 100644 index a82fb16..0000000 --- a/contrib/gcc/doloop.c +++ /dev/null @@ -1,882 +0,0 @@ -/* Perform doloop optimizations - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. - Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "rtl.h" -#include "flags.h" -#include "expr.h" -#include "loop.h" -#include "hard-reg-set.h" -#include "basic-block.h" -#include "toplev.h" -#include "tm_p.h" -#include "cfgloop.h" - - -/* This module is used to modify loops with a determinable number of - iterations to use special low-overhead looping instructions. - - It first validates whether the loop is well behaved and has a - determinable number of iterations (either at compile or run-time). - It then modifies the loop to use a low-overhead looping pattern as - follows: - - 1. A pseudo register is allocated as the loop iteration counter. - - 2. The number of loop iterations is calculated and is stored - in the loop counter. - - 3. At the end of the loop, the jump insn is replaced by the - doloop_end pattern. The compare must remain because it might be - used elsewhere. If the loop-variable or condition register are - used elsewhere, they will be eliminated by flow. - - 4. An optional doloop_begin pattern is inserted at the top of the - loop. -*/ - - -#ifdef HAVE_doloop_end - -static unsigned HOST_WIDE_INT doloop_iterations_max (const struct loop_info *, - enum machine_mode, int); -static int doloop_valid_p (const struct loop *, rtx); -static int doloop_modify (const struct loop *, rtx, rtx, rtx, rtx, rtx); -static int doloop_modify_runtime (const struct loop *, rtx, rtx, rtx, - enum machine_mode, rtx); - - -/* Return the loop termination condition for PATTERN or zero - if it is not a decrement and branch jump insn. */ -rtx -doloop_condition_get (rtx pattern) -{ - rtx cmp; - rtx inc; - rtx reg; - rtx condition; - - /* The canonical doloop pattern we expect is: - - (parallel [(set (pc) (if_then_else (condition) - (label_ref (label)) - (pc))) - (set (reg) (plus (reg) (const_int -1))) - (additional clobbers and uses)]) - - Some machines (IA-64) make the decrement conditional on - the condition as well, so we don't bother verifying the - actual decrement. In summary, the branch must be the - first entry of the parallel (also required by jump.c), - and the second entry of the parallel must be a set of - the loop counter register. */ - - if (GET_CODE (pattern) != PARALLEL) - return 0; - - cmp = XVECEXP (pattern, 0, 0); - inc = XVECEXP (pattern, 0, 1); - - /* Check for (set (reg) (something)). */ - if (GET_CODE (inc) != SET || ! REG_P (SET_DEST (inc))) - return 0; - - /* Extract loop counter register. */ - reg = SET_DEST (inc); - - /* Check for (set (pc) (if_then_else (condition) - (label_ref (label)) - (pc))). */ - if (GET_CODE (cmp) != SET - || SET_DEST (cmp) != pc_rtx - || GET_CODE (SET_SRC (cmp)) != IF_THEN_ELSE - || GET_CODE (XEXP (SET_SRC (cmp), 1)) != LABEL_REF - || XEXP (SET_SRC (cmp), 2) != pc_rtx) - return 0; - - /* Extract loop termination condition. */ - condition = XEXP (SET_SRC (cmp), 0); - - if ((GET_CODE (condition) != GE && GET_CODE (condition) != NE) - || GET_CODE (XEXP (condition, 1)) != CONST_INT) - return 0; - - if (XEXP (condition, 0) == reg) - return condition; - - if (GET_CODE (XEXP (condition, 0)) == PLUS - && XEXP (XEXP (condition, 0), 0) == reg) - return condition; - - /* ??? If a machine uses a funny comparison, we could return a - canonicalised form here. */ - - return 0; -} - - -/* Return an estimate of the maximum number of loop iterations for the - loop specified by LOOP or zero if the loop is not normal. - MODE is the mode of the iteration count and NONNEG is nonzero if - the iteration count has been proved to be non-negative. */ -static unsigned HOST_WIDE_INT -doloop_iterations_max (const struct loop_info *loop_info, - enum machine_mode mode, int nonneg) -{ - unsigned HOST_WIDE_INT n_iterations_max; - enum rtx_code code; - rtx min_value; - rtx max_value; - HOST_WIDE_INT abs_inc; - int neg_inc; - - neg_inc = 0; - abs_inc = INTVAL (loop_info->increment); - if (abs_inc < 0) - { - abs_inc = -abs_inc; - neg_inc = 1; - } - - if (neg_inc) - { - code = swap_condition (loop_info->comparison_code); - min_value = loop_info->final_equiv_value; - max_value = loop_info->initial_equiv_value; - } - else - { - code = loop_info->comparison_code; - min_value = loop_info->initial_equiv_value; - max_value = loop_info->final_equiv_value; - } - - /* Since the loop has a VTOP, we know that the initial test will be - true and thus the value of max_value should be greater than the - value of min_value. Thus the difference should always be positive - and the code must be LT, LE, LTU, LEU, or NE. Otherwise the loop is - not normal, e.g., `for (i = 0; i < 10; i--)'. */ - switch (code) - { - case LTU: - case LEU: - { - unsigned HOST_WIDE_INT umax; - unsigned HOST_WIDE_INT umin; - - if (GET_CODE (min_value) == CONST_INT) - umin = INTVAL (min_value); - else - umin = 0; - - if (GET_CODE (max_value) == CONST_INT) - umax = INTVAL (max_value); - else - umax = ((unsigned) 2 << (GET_MODE_BITSIZE (mode) - 1)) - 1; - - n_iterations_max = umax - umin; - break; - } - - case LT: - case LE: - { - HOST_WIDE_INT smax; - HOST_WIDE_INT smin; - - if (GET_CODE (min_value) == CONST_INT) - smin = INTVAL (min_value); - else - smin = -((unsigned) 1 << (GET_MODE_BITSIZE (mode) - 1)); - - if (GET_CODE (max_value) == CONST_INT) - smax = INTVAL (max_value); - else - smax = ((unsigned) 1 << (GET_MODE_BITSIZE (mode) - 1)) - 1; - - n_iterations_max = smax - smin; - break; - } - - case NE: - if (GET_CODE (min_value) == CONST_INT - && GET_CODE (max_value) == CONST_INT) - n_iterations_max = INTVAL (max_value) - INTVAL (min_value); - else - /* We need to conservatively assume that we might have the maximum - number of iterations without any additional knowledge. */ - n_iterations_max = ((unsigned) 2 << (GET_MODE_BITSIZE (mode) - 1)) - 1; - break; - - default: - return 0; - } - - n_iterations_max /= abs_inc; - - /* If we know that the iteration count is non-negative then adjust - n_iterations_max if it is so large that it appears negative. */ - if (nonneg - && n_iterations_max > ((unsigned) 1 << (GET_MODE_BITSIZE (mode) - 1))) - n_iterations_max = ((unsigned) 1 << (GET_MODE_BITSIZE (mode) - 1)) - 1; - - return n_iterations_max; -} - - -/* Return nonzero if the loop specified by LOOP is suitable for - the use of special low-overhead looping instructions. */ -static int -doloop_valid_p (const struct loop *loop, rtx jump_insn) -{ - const struct loop_info *loop_info = LOOP_INFO (loop); - - /* The loop must have a conditional jump at the end. */ - if (! any_condjump_p (jump_insn) - || ! onlyjump_p (jump_insn)) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Invalid jump at loop end.\n"); - return 0; - } - - /* Give up if a loop has been completely unrolled. */ - if (loop_info->n_iterations == loop_info->unroll_number) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Loop completely unrolled.\n"); - return 0; - } - - /* The loop must have a single exit target. A break or return - statement within a loop will generate multiple loop exits. - Another example of a loop that currently generates multiple exit - targets is for (i = 0; i < (foo ? 8 : 4); i++) { }. */ - if (loop_info->has_multiple_exit_targets || loop->exit_count) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Loop has multiple exit targets.\n"); - return 0; - } - - /* An indirect jump may jump out of the loop. */ - if (loop_info->has_indirect_jump) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Indirect jump in function.\n"); - return 0; - } - - /* A called function may clobber any special registers required for - low-overhead looping. */ - if (loop_info->has_call) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Function call in loop.\n"); - return 0; - } - - /* Some targets (eg, PPC) use the count register for branch on table - instructions. ??? This should be a target specific check. */ - if (loop_info->has_tablejump) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Computed branch in the loop.\n"); - return 0; - } - - if (! loop_info->increment) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Could not determine iteration info.\n"); - return 0; - } - - if (GET_CODE (loop_info->increment) != CONST_INT) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Increment not an integer constant.\n"); - return 0; - } - - /* There is no guarantee that a NE loop will terminate if the - absolute increment is not unity. ??? We could compute this - condition at run-time and have an additional jump around the loop - to ensure an infinite loop. */ - if (loop_info->comparison_code == NE - && !loop_info->preconditioned - && INTVAL (loop_info->increment) != -1 - && INTVAL (loop_info->increment) != 1) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: NE loop with non-unity increment.\n"); - return 0; - } - - /* Check for loops that may not terminate under special conditions. */ - if (! loop_info->n_iterations - && ((loop_info->comparison_code == LEU - && INTVAL (loop_info->increment) > 0) - || (loop_info->comparison_code == GEU - && INTVAL (loop_info->increment) < 0) - || (loop_info->comparison_code == LTU - && INTVAL (loop_info->increment) > 1) - || (loop_info->comparison_code == GTU - && INTVAL (loop_info->increment) < -1))) - { - /* If the comparison is LEU and the comparison value is UINT_MAX - then the loop will not terminate. Similarly, if the - comparison code is GEU and the comparison value is 0, the - loop will not terminate. - - If the absolute increment is not 1, the loop can be infinite - even with LTU/GTU, e.g. for (i = 3; i > 0; i -= 2) - - Note that with LE and GE, the loop behavior is undefined - (C++ standard section 5 clause 5) if an overflow occurs, say - between INT_MAX and INT_MAX + 1. We thus don't have to worry - about these two cases. - - ??? We could compute these conditions at run-time and have a - additional jump around the loop to ensure an infinite loop. - However, it is very unlikely that this is the intended - behavior of the loop and checking for these rare boundary - conditions would pessimize all other code. - - If the loop is executed only a few times an extra check to - restart the loop could use up most of the benefits of using a - count register loop. Note however, that normally, this - restart branch would never execute, so it could be predicted - well by the CPU. We should generate the pessimistic code by - default, and have an option, e.g. -funsafe-loops that would - enable count-register loops in this case. */ - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Possible infinite iteration case ignored.\n"); - } - - return 1; -} - - -/* Modify the loop to use the low-overhead looping insn where LOOP - describes the loop, ITERATIONS is an RTX containing the desired - number of loop iterations, ITERATIONS_MAX is a CONST_INT specifying - the maximum number of loop iterations, and DOLOOP_INSN is the - low-overhead looping insn to emit at the end of the loop. This - returns nonzero if it was successful. */ -static int -doloop_modify (const struct loop *loop, rtx iterations, rtx iterations_max, - rtx doloop_seq, rtx start_label, rtx condition) -{ - rtx counter_reg; - rtx count; - rtx sequence; - rtx jump_insn; - int nonneg = 0; - int decrement_count; - - jump_insn = prev_nonnote_insn (loop->end); - - if (loop_dump_stream) - { - fprintf (loop_dump_stream, "Doloop: Inserting doloop pattern ("); - if (GET_CODE (iterations) == CONST_INT) - fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, - INTVAL (iterations)); - else - fputs ("runtime", loop_dump_stream); - fputs (" iterations).", loop_dump_stream); - } - - /* Emit the label that will delimit the top of the loop. - This has to be done before the delete_insn call below, to prevent - delete_insn from deleting too much. */ - emit_label_after (start_label, loop->top ? loop->top : loop->start); - LABEL_NUSES (start_label)++; - - /* Discard original jump to continue loop. The original compare - result may still be live, so it cannot be discarded explicitly. */ - delete_related_insns (jump_insn); - - counter_reg = XEXP (condition, 0); - if (GET_CODE (counter_reg) == PLUS) - counter_reg = XEXP (counter_reg, 0); - - start_sequence (); - - count = iterations; - decrement_count = 0; - switch (GET_CODE (condition)) - { - case NE: - /* Currently only NE tests against zero and one are supported. */ - if (XEXP (condition, 1) == const0_rtx) - decrement_count = 1; - else if (XEXP (condition, 1) != const1_rtx) - abort (); - break; - - case GE: - /* Currently only GE tests against zero are supported. */ - if (XEXP (condition, 1) != const0_rtx) - abort (); - - /* The iteration count needs decrementing for a GE test. */ - decrement_count = 1; - - /* Determine if the iteration counter will be non-negative. - Note that the maximum value loaded is iterations_max - 1. */ - if ((unsigned HOST_WIDE_INT) INTVAL (iterations_max) - <= ((unsigned) 1 << (GET_MODE_BITSIZE (GET_MODE (counter_reg)) - 1))) - nonneg = 1; - break; - - /* Abort if an invalid doloop pattern has been generated. */ - default: - abort (); - } - - if (decrement_count) - { - if (GET_CODE (count) == CONST_INT) - count = GEN_INT (INTVAL (count) - 1); - else - count = expand_simple_binop (GET_MODE (counter_reg), MINUS, - count, const1_rtx, - 0, 0, OPTAB_LIB_WIDEN); - } - - /* Insert initialization of the count register into the loop header. */ - convert_move (counter_reg, count, 1); - sequence = get_insns (); - end_sequence (); - emit_insn_before (sequence, loop->start); - - /* Some targets (eg, C4x) need to initialize special looping - registers. */ -#ifdef HAVE_doloop_begin - { - rtx init; - - init = gen_doloop_begin (counter_reg, - GET_CODE (iterations) == CONST_INT - ? iterations : const0_rtx, iterations_max, - GEN_INT (loop->level)); - if (init) - { - start_sequence (); - emit_insn (init); - sequence = get_insns (); - end_sequence (); - emit_insn_after (sequence, loop->start); - } - } -#endif - - /* Insert the new low-overhead looping insn. */ - emit_jump_insn_before (doloop_seq, loop->end); - jump_insn = prev_nonnote_insn (loop->end); - JUMP_LABEL (jump_insn) = start_label; - - /* Add a REG_NONNEG note if the actual or estimated maximum number - of iterations is non-negative. */ - if (nonneg) - { - REG_NOTES (jump_insn) - = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX, REG_NOTES (jump_insn)); - } - return 1; -} - - -/* Handle the more complex case, where the bounds are not known at - compile time. In this case we generate a run_time calculation of - the number of iterations. We rely on the existence of a run-time - guard to ensure that the loop executes at least once, i.e., - initial_value obeys the loop comparison condition. If a guard is - not present, we emit one. The loop to modify is described by LOOP. - ITERATIONS_MAX is a CONST_INT specifying the estimated maximum - number of loop iterations. DOLOOP_INSN is the low-overhead looping - insn to insert. Returns nonzero if loop successfully modified. */ -static int -doloop_modify_runtime (const struct loop *loop, rtx iterations_max, - rtx doloop_seq, rtx start_label, - enum machine_mode mode, rtx condition) -{ - const struct loop_info *loop_info = LOOP_INFO (loop); - HOST_WIDE_INT abs_inc; - HOST_WIDE_INT abs_loop_inc; - int neg_inc; - rtx diff; - rtx sequence; - rtx iterations; - rtx initial_value; - rtx final_value; - rtx increment; - int unsigned_p; - enum rtx_code comparison_code; - - increment = loop_info->increment; - initial_value = loop_info->initial_value; - final_value = loop_info->final_value; - - neg_inc = 0; - abs_inc = INTVAL (increment); - if (abs_inc < 0) - { - abs_inc = -abs_inc; - neg_inc = 1; - } - - comparison_code = loop_info->comparison_code; - unsigned_p = (comparison_code == LTU - || comparison_code == LEU - || comparison_code == GTU - || comparison_code == GEU - || comparison_code == NE); - - /* The number of iterations (prior to any loop unrolling) is given by: - - n = (abs (final - initial) + abs_inc - 1) / abs_inc. - - However, it is possible for the summation to overflow, and a - safer method is: - - n = abs (final - initial) / abs_inc; - n += (abs (final - initial) % abs_inc) != 0; - - But when abs_inc is a power of two, the summation won't overflow - except in cases where the loop never terminates. So we don't - need to use this more costly calculation. - - If the loop has been unrolled, the full calculation is - - t1 = abs_inc * unroll_number; increment per loop - n = (abs (final - initial) + abs_inc - 1) / t1; full loops - n += (abs (final - initial) + abs_inc - 1) % t1) >= abs_inc; - partial loop - which works out to be equivalent to - - n = (abs (final - initial) + t1 - 1) / t1; - - In the case where the loop was preconditioned, a few iterations - may have been executed earlier; but 'initial' was adjusted as they - were executed, so we don't need anything special for that case here. - As above, when t1 is a power of two we don't need to worry about - overflow. - - The division and modulo operations can be avoided by requiring - that the increment is a power of 2 (precondition_loop_p enforces - this requirement). Nevertheless, the RTX_COSTS should be checked - to see if a fast divmod is available. */ - - start_sequence (); - /* abs (final - initial) */ - diff = expand_simple_binop (mode, MINUS, - copy_rtx (neg_inc ? initial_value : final_value), - copy_rtx (neg_inc ? final_value : initial_value), - NULL_RTX, unsigned_p, OPTAB_LIB_WIDEN); - - /* Some code transformations can result in code akin to - - tmp = i + 1; - ... - goto scan_start; - top: - tmp = tmp + 1; - scan_start: - i = tmp; - if (i < n) goto top; - - We'll have already detected this form of loop in scan_loop, - and set loop->top and loop->scan_start appropriately. - - In this situation, we skip the increment the first time through - the loop, which results in an incorrect estimate of the number - of iterations. Adjust the difference to compensate. */ - /* ??? Logically, it would seem this belongs in loop_iterations. - However, this causes regressions e.g. on x86 execute/20011008-3.c, - so I do not believe we've properly characterized the exact nature - of the problem. In the meantime, this fixes execute/20011126-2.c - on ia64 and some Ada front end miscompilation on ppc. */ - - if (loop->scan_start) - { - rtx iteration_var = loop_info->iteration_var; - struct loop_ivs *ivs = LOOP_IVS (loop); - struct iv_class *bl; - - if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT) - bl = REG_IV_CLASS (ivs, REGNO (iteration_var)); - else if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == GENERAL_INDUCT) - { - struct induction *v = REG_IV_INFO (ivs, REGNO (iteration_var)); - bl = REG_IV_CLASS (ivs, REGNO (v->src_reg)); - } - else - /* Iteration var must be an induction variable to get here. */ - abort (); - - if (INSN_UID (bl->biv->insn) < max_uid_for_loop - && INSN_LUID (bl->biv->insn) < INSN_LUID (loop->scan_start)) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Basic induction var skips initial incr.\n"); - - diff = expand_simple_binop (mode, PLUS, diff, GEN_INT (abs_inc), - diff, unsigned_p, OPTAB_LIB_WIDEN); - } - } - - abs_loop_inc = abs_inc * loop_info->unroll_number; - if (abs_loop_inc != 1) - { - int shift_count; - - shift_count = exact_log2 (abs_loop_inc); - if (shift_count < 0) - abort (); - - /* (abs (final - initial) + abs_inc * unroll_number - 1) */ - diff = expand_simple_binop (GET_MODE (diff), PLUS, - diff, GEN_INT (abs_loop_inc - 1), - diff, 1, OPTAB_LIB_WIDEN); - - /* (abs (final - initial) + abs_inc * unroll_number - 1) - / (abs_inc * unroll_number) */ - diff = expand_simple_binop (GET_MODE (diff), LSHIFTRT, - diff, GEN_INT (shift_count), - diff, 1, OPTAB_LIB_WIDEN); - } - iterations = diff; - - /* If there is a NOTE_INSN_LOOP_VTOP, we have a `for' or `while' - style loop, with a loop exit test at the start. Thus, we can - assume that the loop condition was true when the loop was - entered. - - `do-while' loops require special treatment since the exit test is - not executed before the start of the loop. We need to determine - if the loop will terminate after the first pass and to limit the - iteration count to one if necessary. */ - if (! loop->vtop) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, "Doloop: Do-while loop.\n"); - - /* A `do-while' loop must iterate at least once. For code like - i = initial; do { ... } while (++i < final); - we will calculate a bogus iteration count if initial > final. - So detect this and set the iteration count to 1. - Note that if the loop has been unrolled, then the loop body - is guaranteed to execute at least once. Also, when the - comparison is NE, our calculated count will be OK. */ - if (loop_info->unroll_number == 1 && comparison_code != NE) - { - rtx label; - - /* Emit insns to test if the loop will immediately - terminate and to set the iteration count to 1 if true. */ - label = gen_label_rtx(); - emit_cmp_and_jump_insns (copy_rtx (initial_value), - copy_rtx (loop_info->comparison_value), - comparison_code, NULL_RTX, mode, 0, - label); - JUMP_LABEL (get_last_insn ()) = label; - LABEL_NUSES (label)++; - emit_move_insn (iterations, const1_rtx); - emit_label (label); - } - } - - sequence = get_insns (); - end_sequence (); - emit_insn_before (sequence, loop->start); - - return doloop_modify (loop, iterations, iterations_max, doloop_seq, - start_label, condition); -} - - -/* This is the main entry point. Process loop described by LOOP - validating that the loop is suitable for conversion to use a low - overhead looping instruction, replacing the jump insn where - suitable. We distinguish between loops with compile-time bounds - and those with run-time bounds. Information from LOOP is used to - compute the number of iterations and to determine whether the loop - is a candidate for this optimization. Returns nonzero if loop - successfully modified. */ -int -doloop_optimize (const struct loop *loop) -{ - struct loop_info *loop_info = LOOP_INFO (loop); - rtx initial_value; - rtx final_value; - rtx increment; - rtx jump_insn; - enum machine_mode mode; - unsigned HOST_WIDE_INT n_iterations; - unsigned HOST_WIDE_INT n_iterations_max; - rtx doloop_seq, doloop_pat, doloop_reg; - rtx iterations; - rtx iterations_max; - rtx start_label; - rtx condition; - - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Processing loop %d, enclosed levels %d.\n", - loop->num, loop->level); - - jump_insn = prev_nonnote_insn (loop->end); - - /* Check that loop is a candidate for a low-overhead looping insn. */ - if (! doloop_valid_p (loop, jump_insn)) - return 0; - - /* Determine if the loop can be safely, and profitably, - preconditioned. While we don't precondition the loop in a loop - unrolling sense, this test ensures that the loop is well behaved - and that the increment is a constant integer. */ - if (! precondition_loop_p (loop, &initial_value, &final_value, - &increment, &mode)) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Cannot precondition loop.\n"); - return 0; - } - - /* Determine or estimate the maximum number of loop iterations. */ - n_iterations = loop_info->n_iterations; - if (n_iterations) - { - /* This is the simple case where the initial and final loop - values are constants. */ - n_iterations_max = n_iterations; - } - else - { - int nonneg = find_reg_note (jump_insn, REG_NONNEG, 0) != 0; - - /* This is the harder case where the initial and final loop - values may not be constants. */ - n_iterations_max = doloop_iterations_max (loop_info, mode, nonneg); - - if (! n_iterations_max) - { - /* We have something like `for (i = 0; i < 10; i--)'. */ - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Not normal loop.\n"); - return 0; - } - } - - /* Account for loop unrolling in the iteration count. This will - have no effect if loop_iterations could not determine the number - of iterations. */ - n_iterations /= loop_info->unroll_number; - n_iterations_max /= loop_info->unroll_number; - - if (n_iterations && n_iterations < 3) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Too few iterations (%ld) to be profitable.\n", - (long int) n_iterations); - return 0; - } - - iterations = GEN_INT (n_iterations); - iterations_max = GEN_INT (n_iterations_max); - - /* Generate looping insn. If the pattern FAILs then give up trying - to modify the loop since there is some aspect the back-end does - not like. */ - start_label = gen_label_rtx (); - doloop_reg = gen_reg_rtx (mode); - doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max, - GEN_INT (loop->level), start_label); - if (! doloop_seq && mode != word_mode) - { - PUT_MODE (doloop_reg, word_mode); - doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max, - GEN_INT (loop->level), start_label); - } - if (! doloop_seq) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Target unwilling to use doloop pattern!\n"); - return 0; - } - - /* If multiple instructions were created, the last must be the - jump instruction. Also, a raw define_insn may yield a plain - pattern. */ - doloop_pat = doloop_seq; - if (INSN_P (doloop_pat)) - { - while (NEXT_INSN (doloop_pat) != NULL_RTX) - doloop_pat = NEXT_INSN (doloop_pat); - if (GET_CODE (doloop_pat) == JUMP_INSN) - doloop_pat = PATTERN (doloop_pat); - else - doloop_pat = NULL_RTX; - } - - if (! doloop_pat - || ! (condition = doloop_condition_get (doloop_pat))) - { - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Doloop: Unrecognizable doloop pattern!\n"); - return 0; - } - - if (n_iterations != 0) - /* Handle the simpler case, where we know the iteration count at - compile time. */ - return doloop_modify (loop, iterations, iterations_max, doloop_seq, - start_label, condition); - else - /* Handle the harder case, where we must add additional runtime tests. */ - return doloop_modify_runtime (loop, iterations_max, doloop_seq, - start_label, mode, condition); -} - -#endif /* HAVE_doloop_end */ |