*** empty log message ***
authorRichard Kenner <kenner@gcc.gnu.org>
Sat, 28 Mar 1992 12:27:04 +0000 (07:27 -0500)
committerRichard Kenner <kenner@gcc.gnu.org>
Sat, 28 Mar 1992 12:27:04 +0000 (07:27 -0500)
From-SVN: r611

gcc/loop.c

index 5165851..842ab12 100644 (file)
@@ -1467,7 +1467,7 @@ add_label_notes (x, insns)
      rtx insns;
 {
   enum rtx_code code = GET_CODE (x);
-  int i;
+  int i, j;
   char *fmt;
   rtx insn;
 
@@ -1482,8 +1482,13 @@ add_label_notes (x, insns)
 
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    if (fmt[i] == 'e')
-      add_label_notes (XEXP (x, i), insns);
+    {
+      if (fmt[i] == 'e')
+       add_label_notes (XEXP (x, i), insns);
+      else if (fmt[i] == 'E')
+       for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+         add_label_notes (XVECEXP (x, i, j), insns);
+    }
 }
 \f
 /* Scan MOVABLES, and move the insns that deserve to be moved.
@@ -3067,6 +3072,9 @@ strength_reduce (scan_start, end, loop_top, insn_count,
   /* This is 1 if current insn is not executed at least once for every loop
      iteration.  */
   int not_every_iteration = 0;
+  /* This is 1 if current insn may be executed more than once for every
+     loop iteration.  */
+  int maybe_multiple = 0;
   /* Temporary list pointers for traversing loop_iv_list.  */
   struct iv_class *bl, **backbl;
   /* Ratio of extra register life span we can justify
@@ -3141,7 +3149,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
                    = (struct induction *) alloca (sizeof (struct induction));
 
                  record_biv (v, p, dest_reg, inc_val, mult_val,
-                             not_every_iteration);
+                             not_every_iteration, maybe_multiple);
                  reg_iv_type[REGNO (dest_reg)] = BASIC_INDUCT;
                }
              else if (REGNO (dest_reg) < max_reg_before_loop)
@@ -3149,6 +3157,46 @@ strength_reduce (scan_start, end, loop_top, insn_count,
            }
        }
 
+      /* Past CODE_LABEL, we get to insns that may be executed multiple
+        times.  The only way we can be sure that they can't is if every
+        every jump insn between here and the end of the loop either
+        returns, exits the loop, or is a forward jump.  */
+
+      if (GET_CODE (p) == CODE_LABEL)
+       {
+         rtx insn = p;
+
+         maybe_multiple = 0;
+
+         while (1)
+           {
+             insn = NEXT_INSN (insn);
+             if (insn == scan_start)
+               break;
+             if (insn == end)
+               {
+                 if (loop_top != 0)
+                   insn = NEXT_INSN (loop_top);
+                 else
+                   break;
+                 if (insn == scan_start)
+                   break;
+               }
+
+             if (GET_CODE (insn) == JUMP_INSN
+                 && GET_CODE (PATTERN (insn)) != RETURN
+                 && (! condjump_p (insn)
+                     || (JUMP_LABEL (insn) != 0
+                         && (INSN_UID (JUMP_LABEL (insn)) > max_uid_for_loop
+                             || (INSN_LUID (JUMP_LABEL (insn))
+                                 < INSN_LUID (insn))))))
+             {
+               maybe_multiple = 1;
+               break;
+             }
+           }
+       }
+
       /* Past a label or a jump, we get to insns for which we can't count
         on whether or how many times they will be executed during each
         iteration.  */
@@ -3415,7 +3463,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
 
       /* Update the status of whether giv can derive other givs.  This can
         change when we pass a label or an insn that updates a biv.  */
-      if (GET_CODE (p) == INSN || GET_CODE (p) == CODE_LABEL)
+      if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
+       || GET_CODE (p) == CODE_LABEL)
        update_giv_derive (p);
 
       /* Past a label or a jump, we get to insns for which we can't count
@@ -4000,16 +4049,24 @@ find_mem_givs (x, insn, not_every_iteration, loop_start, loop_end)
 
    MULT_VAL is const1_rtx if the biv is being incremented here, in which case
    INC_VAL is the increment.  Otherwise, MULT_VAL is const0_rtx and the biv is
-   being set to INC_VAL.  */
+   being set to INC_VAL.
+
+   NOT_EVERY_ITERATION is nonzero if this biv update is not know to be
+   executed every iteration; MAYBE_MULTIPLE is nonzero if this biv update
+   can be executed more than once per iteration.  If MAYBE_MULTIPLE
+   and NOT_EVERY_ITERATION are both zero, we know that the biv update is
+   executed exactly once per iteration.  */
 
 static void
-record_biv (v, insn, dest_reg, inc_val, mult_val, not_every_iteration)
+record_biv (v, insn, dest_reg, inc_val, mult_val,
+           not_every_iteration, maybe_multiple)
      struct induction *v;
      rtx insn;
      rtx dest_reg;
      rtx inc_val;
      rtx mult_val;
      int not_every_iteration;
+     int maybe_multiple;
 {
   struct iv_class *bl;
 
@@ -4020,6 +4077,7 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, not_every_iteration)
   v->add_val = inc_val;
   v->mode = GET_MODE (dest_reg);
   v->always_computable = ! not_every_iteration;
+  v->maybe_multiple = maybe_multiple;
 
   /* Add this to the reg's iv_class, creating a class
      if this is the first incrementation of the reg.  */
@@ -4122,6 +4180,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
   v->location = location;
   v->cant_derive = 0;
   v->combined_with = 0;
+  v->maybe_multiple = 0;
   v->maybe_dead = 0;
   v->derive_adjustment = 0;
   v->same = 0;
@@ -4485,7 +4544,7 @@ update_giv_derive (p)
 
   /* Search all IV classes, then all bivs, and finally all givs.
 
-     There are two cases we are concerned with.  First we have the situation
+     There are three cases we are concerned with.  First we have the situation
      of a giv that is only updated conditionally.  In that case, it may not
      derive any givs after a label is passed.
 
@@ -4501,13 +4560,19 @@ update_giv_derive (p)
      a branch here (actually, we need to pass both a jump and a label, but
      this extra tracking doesn't seem worth it).
 
-     If this is a giv update, we must adjust the giv status to show that a
+     If this is a jump, we are concerned about any biv update that may be
+     executed multiple times.  We are actually only concerned about
+     backward jumps, but it is probably not worth performing the test
+     on the jump again here.
+
+     If this is a biv update, we must adjust the giv status to show that a
      subsequent biv update was performed.  If this adjustment cannot be done,
      the giv cannot derive further givs.  */
 
   for (bl = loop_iv_list; bl; bl = bl->next)
     for (biv = bl->biv; biv; biv = biv->next_iv)
-      if (GET_CODE (p) == CODE_LABEL || biv->insn == p)
+      if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN
+         || biv->insn == p)
        {
          for (giv = bl->giv; giv; giv = giv->next_iv)
            {
@@ -4551,7 +4616,8 @@ update_giv_derive (p)
                  else
                    giv->cant_derive = 1;
                }
-             else if (GET_CODE (p) == CODE_LABEL && ! biv->always_computable)
+             else if ((GET_CODE (p) == CODE_LABEL && ! biv->always_computable)
+                      || (GET_CODE (p) == JUMP_INSN && biv->maybe_multiple))
                giv->cant_derive = 1;
            }
        }