loop.h (loop_insn_first_p): Declare.
authorJ"orn Rennecke <amylaar@cygnus.co.uk>
Wed, 24 Feb 1999 11:50:54 +0000 (11:50 +0000)
committerJoern Rennecke <amylaar@gcc.gnu.org>
Wed, 24 Feb 1999 11:50:54 +0000 (11:50 +0000)
* 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

gcc/ChangeLog
gcc/loop.c
gcc/loop.h
gcc/unroll.c

index 08591cc..ff439fd 100644 (file)
@@ -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.
index cd77cdd..f658933 100644 (file)
@@ -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));
 \f
@@ -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;
 {
index 50279bb..e164428 100644 (file)
@@ -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));
index bf03757..7953416 100644 (file)
@@ -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,