loop.h (struct induction): Add multi_insn_incr.
authorRichard Henderson <rth@cygnus.com>
Wed, 8 Dec 1999 03:22:33 +0000 (19:22 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 8 Dec 1999 03:22:33 +0000 (19:22 -0800)
        * loop.h (struct induction): Add multi_insn_incr.
        * loop.c (basic_induction_var): New multi_insn_incr argument.
        Set it if we search back through previous insns for the biv.
        (record_biv): New multi_insn_incr argument; fill in struct induction.
        (strength_reduce): Discard an iv with multiple bivs, any of
        which require multiple insns to increment.

From-SVN: r30820

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

index 14ce3bbe27040edfd841e9640032e7a46e9ad5a2..9861e064c1ead52c80be4d7d7a05ccfc2ff053fe 100644 (file)
@@ -1,3 +1,12 @@
+Tue Dec  7 19:22:06 1999  Richard Henderson  <rth@cygnus.com>
+
+       * loop.h (struct induction): Add multi_insn_incr.
+       * loop.c (basic_induction_var): New multi_insn_incr argument.
+       Set it if we search back through previous insns for the biv.
+       (record_biv): New multi_insn_incr argument; fill in struct induction.
+       (strength_reduce): Discard an iv with multiple bivs, any of
+       which require multiple insns to increment.
+
 1999-12-07  Martin v. Löwis  <loewis@informatik.hu-berlin.de>
 
        * invoke.texi (C Dialect Options): Remove -flang-c9x, add -std
index 5921e5ef70d4cd73a0839cefe3bd2ff483ccf29a..90e6c44f5ea827c4be01f6609745c788151858d8 100644 (file)
@@ -310,12 +310,12 @@ static void strength_reduce PROTO((rtx, rtx, rtx, int, rtx, rtx,
 static void find_single_use_in_loop PROTO((rtx, rtx, varray_type));
 static int valid_initial_value_p PROTO((rtx, rtx, int, rtx));
 static void find_mem_givs PROTO((rtx, rtx, int, int, rtx, rtx));
-static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx *, int, int));
+static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx *, int, int, int));
 static void check_final_value PROTO((struct induction *, rtx, rtx, 
                                     unsigned HOST_WIDE_INT));
 static void record_giv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx, int, enum g_types, int, int, rtx *, rtx, rtx));
 static void update_giv_derive PROTO((rtx));
-static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, rtx *, rtx *, rtx **));
+static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, rtx *, rtx *, rtx **, int *));
 static rtx simplify_giv_expr PROTO((rtx, int *));
 static int general_induction_var PROTO((rtx, rtx *, rtx *, rtx *, int, int *));
 static int consec_sets_giv PROTO((int, rtx, rtx, rtx, rtx *, rtx *, rtx *));
@@ -3837,9 +3837,11 @@ strength_reduce (scan_start, end, loop_top, insn_count,
              && REGNO (dest_reg) >= FIRST_PSEUDO_REGISTER
              && REG_IV_TYPE (REGNO (dest_reg)) != NOT_BASIC_INDUCT)
            {
+             int multi_insn_incr = 0;
+
              if (basic_induction_var (SET_SRC (set), GET_MODE (SET_SRC (set)),
                                       dest_reg, p, &inc_val, &mult_val,
-                                      &location))
+                                      &location, &multi_insn_incr))
                {
                  /* It is a possible basic induction variable.
                     Create and initialize an induction structure for it.  */
@@ -3848,7 +3850,8 @@ 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, location,
-                             not_every_iteration, maybe_multiple);
+                             not_every_iteration, maybe_multiple, 
+                             multi_insn_incr);
                  REG_IV_TYPE (REGNO (dest_reg)) = BASIC_INDUCT;
                }
              else if (REGNO (dest_reg) < max_reg_before_loop)
@@ -3976,6 +3979,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
      Make a sanity check against n_times_set.  */
   for (backbl = &loop_iv_list, bl = *backbl; bl; bl = bl->next)
     {
+      int fail = 0;
+
       if (REG_IV_TYPE (bl->regno) != BASIC_INDUCT
          /* Above happens if register modified by subreg, etc.  */
          /* Make sure it is not recognized as a basic induction var: */
@@ -3983,6 +3988,21 @@ strength_reduce (scan_start, end, loop_top, insn_count,
          /* If never incremented, it is invariant that we decided not to
             move.  So leave it alone.  */
          || ! bl->incremented)
+       fail = 1;
+      else if (bl->biv_count > 1)
+       {
+         /* ??? If we have multiple increments for this BIV, and any of
+            them take multiple insns to perform the increment, drop the
+            BIV, since the bit below that converts the extra increments
+            into GIVs can't handle the multiple insn increment.  */
+         
+         struct induction *v;
+         for (v = bl->biv; v ; v = v->next_iv)
+           if (v->multi_insn_incr)
+             fail = 1;
+       }
+
+      if (fail)
        {
          if (loop_dump_stream)
            fprintf (loop_dump_stream, "Reg %d: biv discarded, %s\n",
@@ -4453,7 +4473,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
 
              if (loop_dump_stream)
                fprintf (loop_dump_stream,
-                        "Increment %d of biv %d converted to giv %d.\n\n",
+                        "Increment %d of biv %d converted to giv %d.\n",
                         INSN_UID (v->insn), old_regno, new_regno);
            }
        }
@@ -5460,7 +5480,7 @@ find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start,
 
 static void
 record_biv (v, insn, dest_reg, inc_val, mult_val, location,
-           not_every_iteration, maybe_multiple)
+           not_every_iteration, maybe_multiple, multi_insn_incr)
      struct induction *v;
      rtx insn;
      rtx dest_reg;
@@ -5482,6 +5502,7 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
   v->always_computable = ! not_every_iteration;
   v->always_executed = ! not_every_iteration;
   v->maybe_multiple = maybe_multiple;
+  v->multi_insn_incr = multi_insn_incr;
 
   /* Add this to the reg's iv_class, creating a class
      if this is the first incrementation of the reg.  */
@@ -5589,6 +5610,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
   v->cant_derive = 0;
   v->combined_with = 0;
   v->maybe_multiple = maybe_multiple;
+  v->multi_insn_incr = 0;
   v->maybe_dead = 0;
   v->derive_adjustment = 0;
   v->same = 0;
@@ -6077,7 +6099,8 @@ update_giv_derive (p)
    If we cannot find a biv, we return 0.  */
 
 static int
-basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
+basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location,
+                    multi_insn_incr)
      register rtx x;
      enum machine_mode mode;
      rtx p;
@@ -6085,6 +6108,7 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
      rtx *inc_val;
      rtx *mult_val;
      rtx **location;
+     int *multi_insn_incr;
 {
   register enum rtx_code code;
   rtx *argp, arg;
@@ -6126,7 +6150,8 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
         value.  */
       if (SUBREG_PROMOTED_VAR_P (x))
        return basic_induction_var (SUBREG_REG (x), GET_MODE (SUBREG_REG (x)),
-                                   dest_reg, p, inc_val, mult_val, location);
+                                   dest_reg, p, inc_val, mult_val, location,
+                                   multi_insn_incr);
       return 0;
 
     case REG:
@@ -6159,8 +6184,12 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
                                       ? GET_MODE (x)
                                       : GET_MODE (SET_SRC (set))),
                                      dest_reg, insn,
-                                     inc_val, mult_val, location))
-           return 1;
+                                     inc_val, mult_val, location,
+                                     multi_insn_incr))
+           {
+             *multi_insn_incr = 1;
+             return 1;
+           }
        }
       /* ... fall through ...  */
 
@@ -6191,7 +6220,8 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
 
     case SIGN_EXTEND:
       return basic_induction_var (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
-                                 dest_reg, p, inc_val, mult_val, location);
+                                 dest_reg, p, inc_val, mult_val, location,
+                                 multi_insn_incr);
 
     case ASHIFTRT:
       /* Similar, since this can be a sign extension.  */
@@ -6208,11 +6238,15 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
          && GET_CODE (XEXP (x, 1)) == CONST_INT
          && INTVAL (XEXP (x, 1)) >= 0
          && GET_CODE (SET_SRC (set)) == ASHIFT
-         && XEXP (x, 1) == XEXP (SET_SRC (set), 1))
-       return basic_induction_var (XEXP (SET_SRC (set), 0),
-                                   GET_MODE (XEXP (x, 0)),
-                                   dest_reg, insn, inc_val, mult_val,
-                                   location);
+         && XEXP (x, 1) == XEXP (SET_SRC (set), 1)
+         && basic_induction_var (XEXP (SET_SRC (set), 0),
+                                 GET_MODE (XEXP (x, 0)),
+                                 dest_reg, insn, inc_val, mult_val,
+                                 location, multi_insn_incr))
+       {
+         *multi_insn_incr = 1;
+         return 1;
+       }
       return 0;
 
     default:
index 2578956bd9532ff7a3be33854783344de5e6bbbf..14735810fd52e4e1fff5a7defbcc00dc5a6893ae 100644 (file)
@@ -101,6 +101,7 @@ struct induction
                                   initialized in unrolled loop.  */
   unsigned shared : 1;
   unsigned no_const_addval : 1; /* 1 if add_val does not contain a const. */
+  unsigned multi_insn_incr : 1;        /* 1 if multiple insns updated the biv.  */
   int lifetime;                        /* Length of life of this giv */
   rtx derive_adjustment;       /* If nonzero, is an adjustment to be
                                   subtracted from add_val when this giv