From: J"orn Rennecke Date: Wed, 24 Feb 1999 11:50:54 +0000 (+0000) Subject: loop.h (loop_insn_first_p): Declare. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c99f8c2a3e3a5a81f3bec3c1fd3a080343bd57d1;p=gcc.git loop.h (loop_insn_first_p): Declare. * loop.h (loop_insn_first_p): Declare. * loop.c (loop_insn_first_p): No longer static. * unroll.c (iteration_info) Fix comparison to reg_iv_type->num_elements. Before accessing reg_biv_class, check index against max_reg_before_loop. Fix and enable code for giv iterators. (loop_iterations): Compare with reg_iv_type->num_elements instead of with max_reg_before_loop. From-SVN: r25401 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 08591cca4b6..ff439fdc4c7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +Wed Feb 24 19:47:56 1999 J"orn Rennecke + + * loop.h (loop_insn_first_p): Declare. + * loop.c (loop_insn_first_p): No longer static. + * unroll.c (iteration_info) Fix comparison to + reg_iv_type->num_elements. + Before accessing reg_biv_class, check index against + max_reg_before_loop. + Fix and enable code for giv iterators. + (loop_iterations): Compare with reg_iv_type->num_elements instead + of with max_reg_before_loop. + Wed Feb 24 19:17:11 1999 J"orn Rennecke * unroll.c (unroll_loop): Avoid out-of-bounds index for local_regno. diff --git a/gcc/loop.c b/gcc/loop.c index cd77cddee5c..f65893360a3 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -376,8 +376,6 @@ static int indirect_jump_in_function_p PROTO((rtx)); static int compute_luids PROTO((rtx, rtx, int)); -static int loop_insn_first_p PROTO((rtx, rtx)); - static int biv_elimination_giv_has_0_offset PROTO((struct induction *, struct induction *, rtx)); @@ -8112,7 +8110,7 @@ maybe_eliminate_biv (bl, loop_start, end, eliminate_p, threshold, insn_count) This is like insn_first_p, except that we use the luid information if available. */ -static int +int loop_insn_first_p (insn, reference) rtx insn, reference; { diff --git a/gcc/loop.h b/gcc/loop.h index 50279bb09ec..e164428d861 100644 --- a/gcc/loop.h +++ b/gcc/loop.h @@ -228,10 +228,6 @@ rtx get_condition_for_loop PROTO((rtx)); void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx)); rtx express_from PROTO((struct induction *, struct induction *)); -/* Forward declarations for non-static functions declared in stmt.c. */ -void find_loop_tree_blocks PROTO((void)); -void unroll_block_trees PROTO((void)); - 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, struct loop_info *)); @@ -244,7 +240,10 @@ 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)); +int loop_insn_first_p PROTO((rtx, rtx)); extern int *loop_unroll_number; - +/* Forward declarations for non-static functions declared in stmt.c. */ +void find_loop_tree_blocks PROTO((void)); +void unroll_block_trees PROTO((void)); diff --git a/gcc/unroll.c b/gcc/unroll.c index bf0375761a7..7953416a3d5 100644 --- a/gcc/unroll.c +++ b/gcc/unroll.c @@ -1404,10 +1404,9 @@ precondition_loop_p (loop_start, loop_info, return 0; } - /* ??? Note that if iteration_info is modifed to allow GIV iterators - such as "while (i-- > 0)", the initial value will be one too small. - In this case, loop_iteration_var could be used to determine - the correct initial value, provided the loop has not been reversed. + /* Note that iteration_info biases the initial value for GIV iterators + such as "while (i-- > 0)" so that we can calculate the number of + iterations just like for BIV iterators. Also note that the absolute values of initial_value and final_value are unimportant as only their difference is used for @@ -2364,7 +2363,7 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end) /* If this is a new register, can't handle it since we don't have any reg_iv_type entry for it. */ - if ((unsigned) REGNO (iteration_var) > reg_iv_type->num_elements) + if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements) { if (loop_dump_stream) fprintf (loop_dump_stream, @@ -2392,6 +2391,12 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end) } else if (REG_IV_TYPE (REGNO (iteration_var)) == BASIC_INDUCT) { + /* When reg_iv_type / reg_iv_info is resized for biv increments + that are turned into givs, reg_biv_class is not resized. + So check here that we don't make an out-of-bounds access. */ + if (REGNO (iteration_var) >= max_reg_before_loop) + abort (); + /* Grab initial value, only useful if it is a constant. */ bl = reg_biv_class[REGNO (iteration_var)]; *initial_value = bl->initial_value; @@ -2400,34 +2405,46 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end) } else if (REG_IV_TYPE (REGNO (iteration_var)) == GENERAL_INDUCT) { -#if 1 - /* ??? The code below does not work because the incorrect number of - iterations is calculated when the biv is incremented after the giv - is set (which is the usual case). This can probably be accounted - for by biasing the initial_value by subtracting the amount of the - increment that occurs between the giv set and the giv test. However, - a giv as an iterator is very rare, so it does not seem worthwhile - to handle this. */ - /* ??? An example failure is: i = 6; do {;} while (i++ < 9). */ - if (loop_dump_stream) - fprintf (loop_dump_stream, - "Loop unrolling: Giv iterators are not handled.\n"); - return; -#else - /* Initial value is mult_val times the biv's initial value plus - add_val. Only useful if it is a constant. */ - v = REG_IV_INFO (REGNO (iteration_var)); + HOST_WIDE_INT offset = 0; + struct induction *v = REG_IV_INFO (REGNO (iteration_var)); + + if (REGNO (v->src_reg) >= max_reg_before_loop) + abort (); + bl = reg_biv_class[REGNO (v->src_reg)]; - *initial_value = fold_rtx_mult_add (v->mult_val, bl->initial_value, - v->add_val, v->mode); /* Increment value is mult_val times the increment value of the biv. */ *increment = biv_total_increment (bl, loop_start, loop_end); if (*increment) - *increment = fold_rtx_mult_add (v->mult_val, *increment, const0_rtx, - v->mode); -#endif + { + struct induction *biv_inc; + + *increment + = fold_rtx_mult_add (v->mult_val, *increment, const0_rtx, v->mode); + /* The caller assumes that one full increment has occured at the + first loop test. But that's not true when the biv is incremented + after the giv is set (which is the usual case), e.g.: + i = 6; do {;} while (i++ < 9) . + Therefore, we bias the initial value by subtracting the amount of + the increment that occurs between the giv set and the giv test. */ + for (biv_inc = bl->biv; biv_inc; biv_inc = biv_inc->next_iv) + { + if (loop_insn_first_p (v->insn, biv_inc->insn)) + offset -= INTVAL (biv_inc->add_val); + } + offset *= INTVAL (v->mult_val); + } + if (loop_dump_stream) + fprintf (loop_dump_stream, + "Loop unrolling: Giv iterator, initial value bias %ld.\n", + (long) offset); + /* Initial value is mult_val times the biv's initial value plus + add_val. Only useful if it is a constant. */ + *initial_value + = fold_rtx_mult_add (v->mult_val, + plus_constant (bl->initial_value, offset), + v->add_val, v->mode); } else { @@ -3626,10 +3643,10 @@ loop_iterations (loop_start, loop_end, loop_info) return 0; } - /* Loop iterations is always called before any new registers are created - now, so this should never occur. */ + /* The only new registers that care created before loop iterations are + givs made from biv increments, so this should never occur. */ - if (REGNO (iteration_var) >= max_reg_before_loop) + if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements) abort (); iteration_info (iteration_var, &initial_value, &increment,