OSDN Git Service

* loop.c (strength_reduce): Check for intervening jumps when
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 19 Feb 1999 11:59:01 +0000 (11:59 +0000)
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 19 Feb 1999 11:59:01 +0000 (11:59 +0000)
converting biv increment to giv.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@25310 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/loop.c

index d670b01..f356a24 100644 (file)
@@ -1,3 +1,8 @@
+Fri Feb 19 19:55:06 1999  J"orn Rennecke <amylaar@cygnus.co.uk>
+
+       * loop.c (strength_reduce): Check for intervening jumps when
+       converting biv increment to giv.
+
 Thu Feb 18 16:36:58 1999  Per Bothner  <bothner@cygnus.com>
 
        * tree.def (TRY_FINALLY_EXPR, GOTO_SUBROUTINE_EXPR):  New tree nodes,
index a5ea970..43db725 100644 (file)
@@ -4136,7 +4136,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
       for (bl = loop_iv_list; bl; bl = bl->next)
        {
          struct induction **vp, *v, *next;
-    
+         int biv_dead_after_loop = 0;
+
          /* The biv increments lists are in reverse order.  Fix this first.  */
          for (v = bl->biv, bl->biv = 0; v; v = next)
            {
@@ -4144,19 +4145,46 @@ strength_reduce (scan_start, end, loop_top, insn_count,
              v->next_iv = bl->biv;
              bl->biv = v;
            }
-    
+
+         /* We must guard against the case that an early exit between v->insn
+            and next->insn leaves the biv live after the loop, since that
+            would mean that we'd be missing an increment for the final
+            value.  The following test to set biv_dead_after_loop is like
+            the first part of the test to set bl->eliminable.
+            We don't check here if we can calculate the final value, since
+            this can't succeed if we already know that there is a jump
+            between v->insn and next->insn, yet next->always_executed is
+            set and next->maybe_multiple is cleared.  Such a combination
+            implies that the jump destination is outseide the loop.
+            If we want to make this check more sophisticated, we should
+            check each branch between v->insn and next->insn individually
+            to see if it the biv is dead at its destination.  */
+
+         if (uid_luid[REGNO_LAST_UID (bl->regno)] < INSN_LUID (loop_end)
+             && bl->init_insn
+             && INSN_UID (bl->init_insn) < max_uid_for_loop
+             && (uid_luid[REGNO_FIRST_UID (bl->regno)]
+                 >= INSN_LUID (bl->init_insn))
+#ifdef HAVE_decrement_and_branch_until_zero
+             && ! bl->nonneg
+#endif
+             && ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
+           biv_dead_after_loop = 1;
+
          for (vp = &bl->biv, next = *vp; v = next, next = v->next_iv;)
            {
              HOST_WIDE_INT offset;
              rtx set, add_val, old_reg, dest_reg, last_use_insn;
              int old_regno, new_regno;
-    
+
              if (! v->always_executed
                  || v->maybe_multiple
                  || GET_CODE (v->add_val) != CONST_INT
                  || ! next->always_executed
                  || next->maybe_multiple
-                 || ! CONSTANT_P (next->add_val))
+                 || ! CONSTANT_P (next->add_val)
+                 || ! (biv_dead_after_loop
+                       || no_jumps_between_p (v->insn, next->insn)))
                {
                  vp = &v->next_iv;
                  continue;