diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d066040d2eb..e295f1ca316 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +Thu Nov 26 18:05:04 1998 Michael Hayes + + * loop.h (struct loop_info): Define new structure. + (precondition_loop_p): Added prototype. + (unroll_loop): Added new argument loop_info to prototype. + (final_biv_value, final_giv_value): Added new argument n_iterations + to prototype. + * loop.c (strength_reduce): Declare new structure loop_iteration_info + and new pointer loop_info. + (loop_n_iterations): Replace global variable by element in + loop_info structure. + (check_final_value): New argument n_iterations. + (insert_bct): New argument loop_info. + (loop_unroll_factor): Replace global array by element in + loop_info structure. + (loop_optimize): Remove code to allocate and initialise + loop_unroll_factor_array. + * unroll.c (precondition_loop_p): No longer static since + used by branch on count optimization. + (precondition_loop_p, unroll_loop): New argument loop_info. + (final_biv_value, final_giv_value, find_splittable_regs): New + argument n_iterations. + (loop_iteration_var, loop_initial_value, loop_increment, + loop_final_value, loop_comparison_code, loop_unroll_factor): + Replaced global variables by loop_info structure. + (loop_unroll_factor): Replace global array by element in + loop_info structure. + + Thu Nov 26 17:49:29 1998 Michael Hayes * loop.c (check_dbra_loop): Update JUMP_LABEL field of jump insn diff --git a/gcc/loop.c b/gcc/loop.c index 4fb51988fbf..1d0e08d59f5 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -88,14 +88,6 @@ int *loop_outer_loop; int *loop_used_count_register; #endif /* HAVE_decrement_and_branch_on_count */ -/* For each loop, keep track of its unrolling factor. - Potential values: - 0: unrolled - 1: not unrolled. - -1: completely unrolled - >0: holds the unroll exact factor. */ -int *loop_unroll_factor; - /* Indexed by loop number, contains a nonzero value if the "loop" isn't really a loop (an insn outside the loop branches into it). */ @@ -118,14 +110,6 @@ rtx *loop_number_exit_labels; int *loop_number_exit_count; -/* Holds the number of loop iterations. It is zero if the number could not be - calculated. Must be unsigned since the number of iterations can - be as high as 2^wordsize-1. For loops with a wider iterator, this number - will be zero if the number of loop iterations is too large for an - unsigned integer to hold. */ - -unsigned HOST_WIDE_INT loop_n_iterations; - /* Nonzero if there is a subroutine call in the current loop. */ static int loop_has_call; @@ -320,7 +304,8 @@ static void find_single_use_in_loop PROTO((rtx, rtx, varray_type)); static int valid_initial_value_p PROTO((rtx, rtx, int, rtx)); static void find_mem_givs PROTO((rtx, rtx, int, rtx, rtx)); static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, int, int)); -static void check_final_value PROTO((struct induction *, rtx, rtx)); +static void check_final_value PROTO((struct induction *, rtx, rtx, + unsigned HOST_WIDE_INT)); static void record_giv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx, int, enum g_types, int, rtx *, rtx, rtx)); static void update_giv_derive PROTO((rtx)); static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, rtx *, rtx *)); @@ -365,7 +350,7 @@ typedef struct rtx_pair { #ifdef HAVE_decrement_and_branch_on_count /* Test whether BCT applicable and safe. */ -static void insert_bct PROTO((rtx, rtx)); +static void insert_bct PROTO((rtx, rtx, struct loop_info *)); /* Auxiliary function that inserts the BCT pattern into the loop. */ static void instrument_loop_bct PROTO((rtx, rtx, rtx)); @@ -478,12 +463,6 @@ loop_optimize (f, dumpfile, unroll_p, bct_p) loop_number_exit_labels = (rtx *) alloca (max_loop_num * sizeof (rtx)); loop_number_exit_count = (int *) alloca (max_loop_num * sizeof (int)); - /* This is initialized by the unrolling code, so we go ahead - and clear them just in case we are not performing loop - unrolling. */ - loop_unroll_factor = (int *) alloca (max_loop_num *sizeof (int)); - bzero ((char *) loop_unroll_factor, max_loop_num * sizeof (int)); - #ifdef HAVE_decrement_and_branch_on_count /* Allocate for BCT optimization */ loop_used_count_register = (int *) alloca (max_loop_num * sizeof (int)); @@ -3573,6 +3552,8 @@ strength_reduce (scan_start, end, loop_top, insn_count, rtx test; rtx end_insert_before; int loop_depth = 0; + struct loop_info loop_iteration_info; + struct loop_info *loop_info = &loop_iteration_info; reg_iv_type = (enum iv_mode *) alloca (max_reg_before_loop * sizeof (enum iv_mode)); @@ -3771,7 +3752,8 @@ strength_reduce (scan_start, end, loop_top, insn_count, /* Can still unroll the loop anyways, but indicate that there is no strength reduction info available. */ if (unroll_p) - unroll_loop (loop_end, insn_count, loop_start, end_insert_before, 0); + unroll_loop (loop_end, insn_count, loop_start, end_insert_before, + loop_info, 0); return; } @@ -4040,7 +4022,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, be called after all giv's have been identified, since otherwise it may fail if the iteration variable is a giv. */ - loop_n_iterations = loop_iterations (loop_start, loop_end); + loop_iterations (loop_start, loop_end, loop_info); /* Now for each giv for which we still don't know whether or not it is replaceable, check to see if it is replaceable because its final value @@ -4053,7 +4035,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, for (v = bl->giv; v; v = v->next_iv) if (! v->replaceable && ! v->not_replaceable) - check_final_value (v, loop_start, loop_end); + check_final_value (v, loop_start, loop_end, loop_info->n_iterations); } /* Try to prove that the loop counter variable (if any) is always @@ -4099,7 +4081,8 @@ strength_reduce (scan_start, end, loop_top, insn_count, && ! bl->nonneg #endif && ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set))) - || ((final_value = final_biv_value (bl, loop_start, loop_end)) + || ((final_value = final_biv_value (bl, loop_start, loop_end, + loop_info->n_iterations)) #ifdef HAVE_decrement_and_branch_until_zero && ! bl->nonneg #endif @@ -4562,13 +4545,14 @@ strength_reduce (scan_start, end, loop_top, insn_count, collected. */ if (unroll_p) - unroll_loop (loop_end, insn_count, loop_start, end_insert_before, 1); + unroll_loop (loop_end, insn_count, loop_start, end_insert_before, + loop_info, 1); #ifdef HAVE_decrement_and_branch_on_count /* Instrument the loop with BCT insn. */ if (HAVE_decrement_and_branch_on_count && bct_p && flag_branch_on_count_reg) - insert_bct (loop_start, loop_end); + insert_bct (loop_start, loop_end, loop_info); #endif /* HAVE_decrement_and_branch_on_count */ if (loop_dump_stream) @@ -5058,9 +5042,10 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit, have been identified. */ static void -check_final_value (v, loop_start, loop_end) +check_final_value (v, loop_start, loop_end, n_iterations) struct induction *v; rtx loop_start, loop_end; + unsigned HOST_WIDE_INT n_iterations; { struct iv_class *bl; rtx final_value = 0; @@ -5087,7 +5072,7 @@ check_final_value (v, loop_start, loop_end) v->replaceable = 0; #endif - if ((final_value = final_giv_value (v, loop_start, loop_end)) + if ((final_value = final_giv_value (v, loop_start, loop_end, n_iterations)) && (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn))) { int biv_increment_seen = 0; @@ -7965,8 +7950,9 @@ get_condition_for_loop (x) */ static void -insert_bct (loop_start, loop_end) +insert_bct (loop_start, loop_end, loop_info) rtx loop_start, loop_end; + struct loop_info *loop_info; { int i; unsigned HOST_WIDE_INT n_iterations; @@ -7982,7 +7968,7 @@ insert_bct (loop_start, loop_end) int loop_num = uid_loop_num [INSN_UID (loop_start)]; /* It's impossible to instrument a competely unrolled loop. */ - if (loop_unroll_factor [loop_num] == -1) + if (loop_info->unroll_number == -1) return; /* Make sure that the count register is not in use. */ @@ -8040,10 +8026,10 @@ insert_bct (loop_start, loop_end) } /* Account for loop unrolling in instrumented iteration count. */ - if (loop_unroll_factor [loop_num] > 1) - n_iterations = loop_n_iterations / loop_unroll_factor [loop_num]; + if (loop_info->unroll_number > 1) + n_iterations = loop_info->n_iterations / loop_info->unroll_number; else - n_iterations = loop_n_iterations; + n_iterations = loop_info->n_iterations; if (n_iterations != 0 && n_iterations < 3) { @@ -8071,7 +8057,7 @@ insert_bct (loop_start, loop_end) at compile time. In this case we generate run_time calculation of the number of iterations. */ - if (loop_iteration_var == 0) + if (loop_info->iteration_var == 0) { if (loop_dump_stream) fprintf (loop_dump_stream, @@ -8080,8 +8066,8 @@ insert_bct (loop_start, loop_end) return; } - if (GET_MODE_CLASS (GET_MODE (loop_iteration_var)) != MODE_INT - || GET_MODE_SIZE (GET_MODE (loop_iteration_var)) != UNITS_PER_WORD) + if (GET_MODE_CLASS (GET_MODE (loop_info->iteration_var)) != MODE_INT + || GET_MODE_SIZE (GET_MODE (loop_info->iteration_var)) != UNITS_PER_WORD) { if (loop_dump_stream) fprintf (loop_dump_stream, @@ -8091,7 +8077,7 @@ insert_bct (loop_start, loop_end) } /* With runtime bounds, if the compare is of the form '!=' we give up */ - if (loop_comparison_code == NE) + if (loop_info->comparison_code == NE) { if (loop_dump_stream) fprintf (loop_dump_stream, diff --git a/gcc/loop.h b/gcc/loop.h index d0ae25f4d45..f747e46612e 100644 --- a/gcc/loop.h +++ b/gcc/loop.h @@ -143,6 +143,43 @@ struct iv_class { biv controls. */ }; +/* Information required to calculate the number of loop iterations. + This is set by loop_iterations. */ + +struct loop_info +{ + /* Register or constant initial loop value. */ + rtx initial_value; + /* Register or constant value used for comparison test. */ + rtx comparison_value; + /* Register or constant approximate final value. */ + rtx final_value; + /* Register or constant initial loop value with term common to + final_value removed. */ + rtx initial_equiv_value; + /* Register or constant final loop value with term common to + initial_value removed. */ + rtx final_equiv_value; + /* Register corresponding to iteration variable. */ + rtx iteration_var; + /* Constant loop increment. */ + rtx increment; + enum rtx_code comparison_code; + /* Holds the number of loop iterations. It is zero if the number + could not be calculated. Must be unsigned since the number of + iterations can be as high as 2^wordsize - 1. For loops with a + wider iterator, this number will be zero if the number of loop + iterations is too large for an unsigned integer to hold. */ + unsigned HOST_WIDE_INT n_iterations; + /* The loop unrolling factor. + Potential values: + 0: unrolled + 1: not unrolled. + -1: completely unrolled + >0: holds the unroll exact factor. */ + int unroll_number; +}; + /* Definitions used by the basic induction variable discovery code. */ enum iv_mode { UNKNOWN_INDUCT, BASIC_INDUCT, NOT_BASIC_INDUCT, GENERAL_INDUCT }; @@ -155,7 +192,6 @@ extern int *uid_loop_num; extern int *loop_outer_loop; extern rtx *loop_number_exit_labels; extern int *loop_number_exit_count; -extern unsigned HOST_WIDE_INT loop_n_iterations; extern int max_reg_before_loop; extern FILE *loop_dump_stream; @@ -175,21 +211,18 @@ void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx)); void find_loop_tree_blocks PROTO((void)); void unroll_block_trees PROTO((void)); -void unroll_loop PROTO((rtx, int, rtx, rtx, int)); +void unroll_loop PROTO((rtx, int, rtx, rtx, struct loop_info *, int)); rtx biv_total_increment PROTO((struct iv_class *, rtx, rtx)); -unsigned HOST_WIDE_INT loop_iterations PROTO((rtx, rtx)); -rtx final_biv_value PROTO((struct iv_class *, rtx, rtx)); -rtx final_giv_value PROTO((struct induction *, rtx, rtx)); +unsigned HOST_WIDE_INT loop_iterations PROTO((rtx, rtx, struct loop_info *)); +int precondition_loop_p PROTO((rtx, struct loop_info *, + rtx *, rtx *, rtx *)); +rtx final_biv_value PROTO((struct iv_class *, rtx, rtx, + unsigned HOST_WIDE_INT)); +rtx final_giv_value PROTO((struct induction *, rtx, rtx, + unsigned HOST_WIDE_INT)); void emit_unrolled_add PROTO((rtx, rtx, rtx)); int back_branch_in_range_p PROTO((rtx, rtx, rtx)); -extern int *loop_unroll_factor; +extern int *loop_unroll_number; -#ifdef HAVE_decrement_and_branch_on_count -extern rtx loop_iteration_var; -extern rtx loop_initial_value; -extern rtx loop_increment; -extern rtx loop_final_value; -extern enum rtx_code loop_comparison_code; -#endif /* HAVE_decrement_and_branch_on_count */ diff --git a/gcc/unroll.c b/gcc/unroll.c index 9bf6a514c2a..5f9f2c7addc 100644 --- a/gcc/unroll.c +++ b/gcc/unroll.c @@ -186,19 +186,9 @@ static rtx *splittable_regs; static int *splittable_regs_updates; -/* Values describing the current loop's iteration variable. These are set up - by loop_iterations, and used by precondition_loop_p. */ - -rtx loop_iteration_var; -rtx loop_initial_value; -rtx loop_increment; -rtx loop_final_value; -enum rtx_code loop_comparison_code; - /* Forward declarations. */ static void init_reg_map PROTO((struct inline_remap *, int)); -static int precondition_loop_p PROTO((rtx *, rtx *, rtx *, rtx)); static rtx calculate_giv_inc PROTO((rtx, rtx, int)); static rtx initial_reg_note_copy PROTO((rtx, struct inline_remap *)); static void final_reg_note_copy PROTO((rtx, struct inline_remap *)); @@ -206,8 +196,9 @@ static void copy_loop_body PROTO((rtx, rtx, struct inline_remap *, rtx, int, enum unroll_types, rtx, rtx, rtx, rtx)); void iteration_info PROTO((rtx, rtx *, rtx *, rtx, rtx)); static rtx approx_final_value PROTO((enum rtx_code, rtx, int *, int *)); -static int find_splittable_regs PROTO((enum unroll_types, rtx, rtx, rtx, int)); -static int find_splittable_givs PROTO((struct iv_class *,enum unroll_types, +static int find_splittable_regs PROTO((enum unroll_types, rtx, rtx, rtx, int, + unsigned HOST_WIDE_INT)); +static int find_splittable_givs PROTO((struct iv_class *, enum unroll_types, rtx, rtx, rtx, int)); static int reg_dead_after_loop PROTO((rtx, rtx, rtx)); static rtx fold_rtx_mult_add PROTO((rtx, rtx, rtx, enum machine_mode)); @@ -227,11 +218,12 @@ static rtx remap_split_bivs PROTO((rtx)); void unroll_loop (loop_end, insn_count, loop_start, end_insert_before, - strength_reduce_p) + loop_info, strength_reduce_p) rtx loop_end; int insn_count; rtx loop_start; rtx end_insert_before; + struct loop_info *loop_info; int strength_reduce_p; { int i, j, temp; @@ -304,18 +296,19 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, /* Determine type of unroll to perform. Depends on the number of iterations and the size of the loop. */ - /* If there is no strength reduce info, then set loop_n_iterations to zero. - This can happen if strength_reduce can't find any bivs in the loop. - A value of zero indicates that the number of iterations could not be - calculated. */ + /* If there is no strength reduce info, then set + loop_info->n_iterations to zero. This can happen if + strength_reduce can't find any bivs in the loop. A value of zero + indicates that the number of iterations could not be calculated. */ if (! strength_reduce_p) - loop_n_iterations = 0; + loop_info->n_iterations = 0; - if (loop_dump_stream && loop_n_iterations > 0) + if (loop_dump_stream && loop_info->n_iterations > 0) { fputs ("Loop unrolling: ", loop_dump_stream); - fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, loop_n_iterations); + fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, + loop_info->n_iterations); fputs (" iterations.\n", loop_dump_stream); } @@ -326,7 +319,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, /* Calculate how many times to unroll the loop. Indicate whether or not the loop is being completely unrolled. */ - if (loop_n_iterations == 1) + if (loop_info->n_iterations == 1) { /* If number of iterations is exactly 1, then eliminate the compare and branch at the end of the loop since they will never be taken. @@ -355,13 +348,13 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, } return; } - else if (loop_n_iterations > 0 - && loop_n_iterations * insn_count < MAX_UNROLLED_INSNS) + else if (loop_info->n_iterations > 0 + && loop_info->n_iterations * insn_count < MAX_UNROLLED_INSNS) { - unroll_number = loop_n_iterations; + unroll_number = loop_info->n_iterations; unroll_type = UNROLL_COMPLETELY; } - else if (loop_n_iterations > 0) + else if (loop_info->n_iterations > 0) { /* Try to factor the number of iterations. Don't bother with the general case, only using 2, 3, 5, and 7 will get 75% of all @@ -370,7 +363,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, for (i = 0; i < NUM_FACTORS; i++) factors[i].count = 0; - temp = loop_n_iterations; + temp = loop_info->n_iterations; for (i = NUM_FACTORS - 1; i >= 0; i--) while (temp % factors[i].factor == 0) { @@ -857,8 +850,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, { rtx initial_value, final_value, increment; - if (precondition_loop_p (&initial_value, &final_value, &increment, - loop_start)) + if (precondition_loop_p (loop_start, loop_info, + &initial_value, &final_value, &increment)) { register rtx diff ; enum machine_mode mode; @@ -939,7 +932,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, case. This check does not apply if the loop has a NE comparison at the end. */ - if (loop_comparison_code != NE) + if (loop_info->comparison_code != NE) { emit_cmp_insn (initial_value, final_value, neg_inc ? LE : GE, NULL_RTX, mode, 0, 0); @@ -1141,11 +1134,11 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, /* At this point, we are guaranteed to unroll the loop. */ - /* Keep track of the unroll factor for each loop. */ + /* Keep track of the unroll factor for the loop. */ if (unroll_type == UNROLL_COMPLETELY) - loop_unroll_factor [uid_loop_num [INSN_UID (loop_start)]] = -1; + loop_info->unroll_number = -1; else - loop_unroll_factor [uid_loop_num [INSN_UID (loop_start)]] = unroll_number; + loop_info->unroll_number = unroll_number; /* For each biv and giv, determine whether it can be safely split into @@ -1160,7 +1153,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, temp = 0; else temp = find_splittable_regs (unroll_type, loop_start, loop_end, - end_insert_before, unroll_number); + end_insert_before, unroll_number, + loop_info->n_iterations); /* find_splittable_regs may have created some new registers, so must reallocate the reg_map with the new larger size, and must realloc @@ -1318,52 +1312,54 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, when the increment is not a power of 2. Use RTX_COST to compute whether divide is cheap. */ -static int -precondition_loop_p (initial_value, final_value, increment, loop_start) - rtx *initial_value, *final_value, *increment; +int +precondition_loop_p (loop_start, loop_info, + initial_value, final_value, increment) rtx loop_start; + struct loop_info *loop_info; + rtx *initial_value, *final_value, *increment; { - if (loop_n_iterations > 0) + if (loop_info->n_iterations > 0) { *initial_value = const0_rtx; *increment = const1_rtx; - *final_value = GEN_INT (loop_n_iterations); + *final_value = GEN_INT (loop_info->n_iterations); if (loop_dump_stream) { fputs ("Preconditioning: Success, number of iterations known, ", loop_dump_stream); fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, - loop_n_iterations); + loop_info->n_iterations); fputs (".\n", loop_dump_stream); } return 1; } - if (loop_initial_value == 0) + if (loop_info->initial_value == 0) { if (loop_dump_stream) fprintf (loop_dump_stream, "Preconditioning: Could not find initial value.\n"); return 0; } - else if (loop_increment == 0) + else if (loop_info->increment == 0) { if (loop_dump_stream) fprintf (loop_dump_stream, "Preconditioning: Could not find increment value.\n"); return 0; } - else if (GET_CODE (loop_increment) != CONST_INT) + else if (GET_CODE (loop_info->increment) != CONST_INT) { if (loop_dump_stream) fprintf (loop_dump_stream, "Preconditioning: Increment not a constant.\n"); return 0; } - else if ((exact_log2 (INTVAL (loop_increment)) < 0) - && (exact_log2 (- INTVAL (loop_increment)) < 0)) + else if ((exact_log2 (INTVAL (loop_info->increment)) < 0) + && (exact_log2 (- INTVAL (loop_info->increment)) < 0)) { if (loop_dump_stream) fprintf (loop_dump_stream, @@ -1374,7 +1370,7 @@ precondition_loop_p (initial_value, final_value, increment, loop_start) /* Unsigned_compare and compare_dir can be ignored here, since they do not matter for preconditioning. */ - if (loop_final_value == 0) + if (loop_info->final_value == 0) { if (loop_dump_stream) fprintf (loop_dump_stream, @@ -1387,11 +1383,11 @@ precondition_loop_p (initial_value, final_value, increment, loop_start) to make sure that the register is in the range covered by invariant_p. If it isn't, then it is most likely a biv/giv which by definition are not invariant. */ - if ((GET_CODE (loop_final_value) == REG - && REGNO (loop_final_value) >= max_reg_before_loop) - || (GET_CODE (loop_final_value) == PLUS - && REGNO (XEXP (loop_final_value, 0)) >= max_reg_before_loop) - || ! invariant_p (loop_final_value)) + if ((GET_CODE (loop_info->final_value) == REG + && REGNO (loop_info->final_value) >= max_reg_before_loop) + || (GET_CODE (loop_info->final_value) == PLUS + && REGNO (XEXP (loop_info->final_value, 0)) >= max_reg_before_loop) + || ! invariant_p (loop_info->final_value)) { if (loop_dump_stream) fprintf (loop_dump_stream, @@ -1401,8 +1397,8 @@ precondition_loop_p (initial_value, final_value, increment, loop_start) /* Fail for floating point values, since the caller of this function does not have code to deal with them. */ - if (GET_MODE_CLASS (GET_MODE (loop_final_value)) == MODE_FLOAT - || GET_MODE_CLASS (GET_MODE (loop_initial_value)) == MODE_FLOAT) + if (GET_MODE_CLASS (GET_MODE (loop_info->final_value)) == MODE_FLOAT + || GET_MODE_CLASS (GET_MODE (loop_info->initial_value)) == MODE_FLOAT) { if (loop_dump_stream) fprintf (loop_dump_stream, @@ -1410,10 +1406,10 @@ precondition_loop_p (initial_value, final_value, increment, loop_start) return 0; } - /* Fail if loop_iteration_var is not live before loop_start, since we need - to test its value in the preconditioning code. */ + /* Fail if loop_info->iteration_var is not live before loop_start, + since we need to test its value in the preconditioning code. */ - if (uid_luid[REGNO_FIRST_UID (REGNO (loop_iteration_var))] + if (uid_luid[REGNO_FIRST_UID (REGNO (loop_info->iteration_var))] > INSN_LUID (loop_start)) { if (loop_dump_stream) @@ -1430,9 +1426,9 @@ precondition_loop_p (initial_value, final_value, increment, loop_start) Also note that the absolute values of initial_value and final_value are unimportant as only their difference is used for calculating the number of loop iterations. */ - *initial_value = loop_initial_value; - *increment = loop_increment; - *final_value = loop_final_value; + *initial_value = loop_info->initial_value; + *increment = loop_info->increment; + *final_value = loop_info->final_value; /* Success! */ if (loop_dump_stream) @@ -2361,7 +2357,7 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end) /* Reject iteration variables larger than the host wide int size, since they could result in a number of iterations greater than the range of our - `unsigned HOST_WIDE_INT' variable loop_n_iterations. */ + `unsigned HOST_WIDE_INT' variable loop_info->n_iterations. */ else if ((GET_MODE_BITSIZE (GET_MODE (iteration_var)) > HOST_BITS_PER_WIDE_INT)) { @@ -2506,11 +2502,12 @@ approx_final_value (comparison_code, comparison_value, unsigned_p, compare_dir) static int find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, - unroll_number) + unroll_number, n_iterations) enum unroll_types unroll_type; rtx loop_start, loop_end; rtx end_insert_before; int unroll_number; + unsigned HOST_WIDE_INT n_iterations; { struct iv_class *bl; struct induction *v; @@ -2548,7 +2545,8 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, || (uid_luid[REGNO_FIRST_UID (bl->regno)] < INSN_LUID (bl->init_insn)) || reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set))) - && ! (biv_final_value = final_biv_value (bl, loop_start, loop_end))) + && ! (biv_final_value = final_biv_value (bl, loop_start, loop_end, + n_iterations))) biv_splittable = 0; /* If any of the insns setting the BIV don't do so with a simple @@ -3201,9 +3199,10 @@ reg_dead_after_loop (reg, loop_start, loop_end) the end of the loop. If we can do it, return that value. */ rtx -final_biv_value (bl, loop_start, loop_end) +final_biv_value (bl, loop_start, loop_end, n_iterations) struct iv_class *bl; rtx loop_start, loop_end; + unsigned HOST_WIDE_INT n_iterations; { rtx increment, tem; @@ -3231,7 +3230,7 @@ final_biv_value (bl, loop_start, loop_end) it may not have its final value when the loop exits), and the initial value of the biv must be invariant. */ - if (loop_n_iterations != 0 + if (n_iterations != 0 && ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]] && invariant_p (bl->initial_value)) { @@ -3248,7 +3247,7 @@ final_biv_value (bl, loop_start, loop_end) /* Make sure loop_end is not the last insn. */ if (NEXT_INSN (loop_end) == 0) emit_note_after (NOTE_INSN_DELETED, loop_end); - emit_iv_add_mult (increment, GEN_INT (loop_n_iterations), + emit_iv_add_mult (increment, GEN_INT (n_iterations), bl->initial_value, tem, NEXT_INSN (loop_end)); if (loop_dump_stream) @@ -3277,9 +3276,10 @@ final_biv_value (bl, loop_start, loop_end) the end of the loop. If we can do it, return that value. */ rtx -final_giv_value (v, loop_start, loop_end) +final_giv_value (v, loop_start, loop_end, n_iterations) struct induction *v; rtx loop_start, loop_end; + unsigned HOST_WIDE_INT n_iterations; { struct iv_class *bl; rtx insn; @@ -3310,7 +3310,7 @@ final_giv_value (v, loop_start, loop_end) only one exit for this to work, but the loop iterations does not need to be known. */ - if (loop_n_iterations != 0 + if (n_iterations != 0 && ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]) { /* ?? It is tempting to use the biv's value here since these insns will @@ -3330,7 +3330,7 @@ final_giv_value (v, loop_start, loop_end) && invariant_p (bl->initial_value)) { /* Can calculate the loop exit value of its biv as - (loop_n_iterations * increment) + initial_value */ + (n_iterations * increment) + initial_value */ /* The loop exit value of the giv is then (final_biv_value - extra increments) * mult_val + add_val. @@ -3344,7 +3344,7 @@ final_giv_value (v, loop_start, loop_end) /* Put the final biv value in tem. */ tem = gen_reg_rtx (bl->biv->mode); record_base_value (REGNO (tem), bl->biv->add_val, 0); - emit_iv_add_mult (increment, GEN_INT (loop_n_iterations), + emit_iv_add_mult (increment, GEN_INT (n_iterations), bl->initial_value, tem, insert_before); /* Subtract off extra increments as we find them. */ @@ -3402,8 +3402,9 @@ final_giv_value (v, loop_start, loop_end) iterations if it can be calculated, otherwise returns zero. */ unsigned HOST_WIDE_INT -loop_iterations (loop_start, loop_end) +loop_iterations (loop_start, loop_end, loop_info) rtx loop_start, loop_end; + struct loop_info *loop_info; { rtx comparison, comparison_value; rtx iteration_var, initial_value, increment, final_value; @@ -3418,10 +3419,11 @@ loop_iterations (loop_start, loop_end) branch, and the insn before tests a register value, make that the iteration variable. */ - loop_initial_value = 0; - loop_increment = 0; - loop_final_value = 0; - loop_iteration_var = 0; + loop_info->initial_value = 0; + loop_info->increment = 0; + loop_info->final_value = 0; + loop_info->iteration_var = 0; + loop_info->unroll_number = 2; /* We used to use pren_nonnote_insn here, but that fails because it might accidentally get the branch for a contained loop if the branch for this @@ -3508,11 +3510,11 @@ loop_iterations (loop_start, loop_end) recalculated inside precondition_loop_p because strength reduction optimizations may obscure the loop's structure. */ - loop_iteration_var = iteration_var; - loop_initial_value = initial_value; - loop_increment = increment; - loop_final_value = final_value; - loop_comparison_code = comparison_code; + loop_info->iteration_var = iteration_var; + loop_info->initial_value = initial_value; + loop_info->increment = increment; + loop_info->final_value = final_value; + loop_info->comparison_code = comparison_code; if (increment == 0) { @@ -3617,7 +3619,7 @@ loop_iterations (loop_start, loop_end) } /* Calculate the number of iterations, final_value is only an approximation, - so correct for that. Note that tempu and loop_n_iterations are + so correct for that. Note that tempu and loop_info->n_iterations are unsigned, because they can be as large as 2^n - 1. */ i = INTVAL (increment);