aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJ"orn Rennecke <amylaar@cygnus.co.uk>1999-02-24 11:50:54 +0000
committerJoern Rennecke <amylaar@gcc.gnu.org>1999-02-24 11:50:54 +0000
commitc99f8c2a3e3a5a81f3bec3c1fd3a080343bd57d1 (patch)
treed564513348fedddafc05c01c247a96bf31e2b04b /gcc
parentddce352881f2a8fcea7e43d6e0354b5d03e1874e (diff)
downloadgcc-c99f8c2a3e3a5a81f3bec3c1fd3a080343bd57d1.zip
gcc-c99f8c2a3e3a5a81f3bec3c1fd3a080343bd57d1.tar.gz
gcc-c99f8c2a3e3a5a81f3bec3c1fd3a080343bd57d1.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/loop.c4
-rw-r--r--gcc/loop.h9
-rw-r--r--gcc/unroll.c77
4 files changed, 64 insertions, 38 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 08591cc..ff439fd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+Wed Feb 24 19:47:56 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * 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 <amylaar@cygnus.co.uk>
* unroll.c (unroll_loop): Avoid out-of-bounds index for local_regno.
diff --git a/gcc/loop.c b/gcc/loop.c
index cd77cdd..f658933 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 50279bb..e164428 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 bf03757..7953416 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,