OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / unroll.c
index 7f3658e..3197053 100644 (file)
@@ -1,5 +1,6 @@
 /* Try to unroll loops, and split induction variables.
-   Copyright (C) 1992, 93-95, 97-99, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998,
+   1999, 2000 Free Software Foundation, Inc.
    Contributed by James E. Wilson, Cygnus Support/UC Berkeley.
 
 This file is part of GNU CC.
@@ -159,6 +160,8 @@ enum unroll_types { UNROLL_COMPLETELY, UNROLL_MODULO, UNROLL_NAIVE };
 #include "expr.h"
 #include "loop.h"
 #include "toplev.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
 
 /* This controls which loops are unrolled, and by how much we unroll
    them.  */
@@ -195,7 +198,7 @@ static int *splittable_regs_updates;
 /* Forward declarations.  */
 
 static void init_reg_map PARAMS ((struct inline_remap *, int));
-static rtx calculate_giv_inc PARAMS ((rtx, rtx, int));
+static rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int));
 static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *));
 static void final_reg_note_copy PARAMS ((rtx, struct inline_remap *));
 static void copy_loop_body PARAMS ((rtx, rtx, struct inline_remap *, rtx, int,
@@ -233,6 +236,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
      int strength_reduce_p;
 {
   int i, j;
+  unsigned int r;
   unsigned HOST_WIDE_INT temp;
   int unroll_number = 1;
   rtx copy_start, copy_end;
@@ -242,13 +246,13 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
   struct inline_remap *map;
   char *local_label = NULL;
   char *local_regno;
-  int max_local_regnum;
-  int maxregnum;
+  unsigned int max_local_regnum;
+  unsigned int maxregnum;
   rtx exit_label = 0;
   rtx start_label;
   struct iv_class *bl;
   int splitting_not_safe = 0;
-  enum unroll_types unroll_type;
+  enum unroll_types unroll_type = UNROLL_NAIVE;
   int loop_preconditioned = 0;
   rtx safety_label;
   /* This points to the last real insn in the loop, which should be either
@@ -383,6 +387,8 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
       return;
     }
   else if (loop_info->n_iterations > 0
+          /* Avoid overflow in the next expression.  */
+          && loop_info->n_iterations < MAX_UNROLLED_INSNS
           && loop_info->n_iterations * insn_count < MAX_UNROLLED_INSNS)
     {
       unroll_number = loop_info->n_iterations;
@@ -437,7 +443,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
 
   /* Default case, calculate number of times to unroll loop based on its
      size.  */
-  if (unroll_number == 1)
+  if (unroll_type == UNROLL_NAIVE)
     {
       if (8 * insn_count < MAX_UNROLLED_INSNS)
        unroll_number = 8;
@@ -445,8 +451,6 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
        unroll_number = 4;
       else
        unroll_number = 2;
-
-      unroll_type = UNROLL_NAIVE;
     }
 
   /* Now we know how many times to unroll the loop.  */
@@ -830,11 +834,11 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
         results in better code.  */
       /* We must limit the generic test to max_reg_before_loop, because only
         these pseudo registers have valid regno_first_uid info.  */
-      for (j = FIRST_PSEUDO_REGISTER; j < max_reg_before_loop; ++j)
-       if (REGNO_FIRST_UID (j) > 0 && REGNO_FIRST_UID (j) <= max_uid_for_loop
-           && uid_luid[REGNO_FIRST_UID (j)] >= copy_start_luid
-           && REGNO_LAST_UID (j) > 0 && REGNO_LAST_UID (j) <= max_uid_for_loop
-           && uid_luid[REGNO_LAST_UID (j)] <= copy_end_luid)
+      for (r = FIRST_PSEUDO_REGISTER; r < max_reg_before_loop; ++r)
+       if (REGNO_FIRST_UID (r) > 0 && REGNO_FIRST_UID (r) <= max_uid_for_loop
+           && uid_luid[REGNO_FIRST_UID (r)] >= copy_start_luid
+           && REGNO_LAST_UID (r) > 0 && REGNO_LAST_UID (r) <= max_uid_for_loop
+           && uid_luid[REGNO_LAST_UID (r)] <= copy_end_luid)
          {
            /* However, we must also check for loop-carried dependencies.
               If the value the pseudo has at the end of iteration X is
@@ -845,26 +849,26 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
               regno_last_uid.  */
            /* ??? This check is simplistic.  We would get better code if
               this check was more sophisticated.  */
-           if (set_dominates_use (j, REGNO_FIRST_UID (j), REGNO_LAST_UID (j),
+           if (set_dominates_use (r, REGNO_FIRST_UID (r), REGNO_LAST_UID (r),
                                   copy_start, copy_end))
-             local_regno[j] = 1;
+             local_regno[r] = 1;
 
            if (loop_dump_stream)
              {
-               if (local_regno[j])
-                 fprintf (loop_dump_stream, "Marked reg %d as local\n", j);
+               if (local_regno[r])
+                 fprintf (loop_dump_stream, "Marked reg %d as local\n", r);
                else
                  fprintf (loop_dump_stream, "Did not mark reg %d as local\n",
-                          j);
+                          r);
              }
          }
       /* Givs that have been created from multiple biv increments always have
         local registers.  */
-      for (j = first_increment_giv; j <= last_increment_giv; j++)
+      for (r = first_increment_giv; r <= last_increment_giv; r++)
        {
-         local_regno[j] = 1;
+         local_regno[r] = 1;
          if (loop_dump_stream)
-           fprintf (loop_dump_stream, "Marked reg %d as local\n", j);
+           fprintf (loop_dump_stream, "Marked reg %d as local\n", r);
        }
     }
 
@@ -906,7 +910,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
          map->reg_map = (rtx *) xmalloc (maxregnum * sizeof (rtx));
 
          VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray, maxregnum,
-                                  "unroll_loop");
+                                  "unroll_loop_precondition");
          global_const_equiv_varray = map->const_equiv_varray;
 
          init_reg_map (map, maxregnum);
@@ -1081,12 +1085,13 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
                if (local_label[j])
                  set_label_in_map (map, j, gen_label_rtx ());
 
-             for (j = FIRST_PSEUDO_REGISTER; j < max_local_regnum; j++)
-               if (local_regno[j])
+             for (r = FIRST_PSEUDO_REGISTER; r < max_local_regnum; r++)
+               if (local_regno[r])
                  {
-                   map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j]));
-                   record_base_value (REGNO (map->reg_map[j]),
-                                      regno_reg_rtx[j], 0);
+                   map->reg_map[r]
+                     = gen_reg_rtx (GET_MODE (regno_reg_rtx[r]));
+                   record_base_value (REGNO (map->reg_map[r]),
+                                      regno_reg_rtx[r], 0);
                  }
              /* The last copy needs the compare/branch insns at the end,
                 so reset copy_end here if the loop ends with a conditional
@@ -1224,12 +1229,12 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
        if (local_label[j])
          set_label_in_map (map, j, gen_label_rtx ());
 
-      for (j = FIRST_PSEUDO_REGISTER; j < max_local_regnum; j++)
-       if (local_regno[j])
+      for (r = FIRST_PSEUDO_REGISTER; r < max_local_regnum; r++)
+       if (local_regno[r])
          {
-           map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j]));
-           record_base_value (REGNO (map->reg_map[j]),
-                              regno_reg_rtx[j], 0);
+           map->reg_map[r] = gen_reg_rtx (GET_MODE (regno_reg_rtx[r]));
+           record_base_value (REGNO (map->reg_map[r]),
+                              regno_reg_rtx[r], 0);
          }
 
       /* If loop starts with a branch to the test, then fix it so that
@@ -1533,7 +1538,7 @@ init_reg_map (map, maxregnum)
 static rtx
 calculate_giv_inc (pattern, src_insn, regno)
      rtx pattern, src_insn;
-     int regno;
+     unsigned int regno;
 {
   rtx increment;
   rtx increment_total = 0;
@@ -1764,7 +1769,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
            {
              struct iv_class *bl;
              struct induction *v, *tv;
-             int regno = REGNO (SET_DEST (set));
+             unsigned int regno = REGNO (SET_DEST (set));
 
              v = addr_combined_regs[REGNO (SET_DEST (set))];
              bl = reg_biv_class[REGNO (v->src_reg)];
@@ -1857,8 +1862,8 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
              && GET_CODE (SET_DEST (set)) == REG
              && splittable_regs[REGNO (SET_DEST (set))])
            {
-             int regno = REGNO (SET_DEST (set));
-             int src_regno;
+             unsigned int regno = REGNO (SET_DEST (set));
+             unsigned int src_regno;
 
              dest_reg_was_split = 1;
 
@@ -1935,8 +1940,9 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
 #endif
 
                  splittable_regs[regno]
-                   = GEN_INT (INTVAL (giv_inc)
-                              + INTVAL (splittable_regs[src_regno]));
+                   = simplify_gen_binary (PLUS, GET_MODE (giv_src_reg),
+                                          giv_inc,
+                                          splittable_regs[src_regno]);
                  giv_inc = splittable_regs[regno];
 
                  /* Now split the induction variable by changing the dest
@@ -2032,22 +2038,17 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
          if (JUMP_LABEL (insn) == start_label && insn == copy_end
              && ! last_iteration)
            {
+             /* Update JUMP_LABEL correctly to make invert_jump working.  */
+             JUMP_LABEL (copy) = get_label_from_map (map,
+                                                     CODE_LABEL_NUMBER
+                                                     (JUMP_LABEL (insn)));
              /* This is a branch to the beginning of the loop; this is the
                 last insn being copied; and this is not the last iteration.
                 In this case, we want to change the original fall through
                 case to be a branch past the end of the loop, and the
                 original jump label case to fall_through.  */
 
-             if (invert_exp (pattern, copy))
-               {
-                 if (! redirect_exp (&pattern,
-                                     get_label_from_map (map,
-                                                         CODE_LABEL_NUMBER
-                                                         (JUMP_LABEL (insn))),
-                                     exit_label, copy))
-                   abort ();
-               }
-             else
+             if (!invert_jump (copy, exit_label, 0))
                {
                  rtx jmp;
                  rtx lab = gen_label_rtx ();
@@ -2059,12 +2060,8 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
                  jmp = emit_barrier_after (jmp);
                  emit_label_after (lab, jmp);
                  LABEL_NUSES (lab) = 0;
-                 if (! redirect_exp (&pattern,
-                                     get_label_from_map (map,
-                                                         CODE_LABEL_NUMBER
-                                                         (JUMP_LABEL (insn))),
-                                     lab, copy))
-                   abort ();
+                 if (!redirect_jump (copy, lab, 0))
+                   abort();
                }
            }
 
@@ -2128,7 +2125,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
 
          /* If this used to be a conditional jump insn but whose branch
             direction is now known, we must do something special.  */
-         if (condjump_p (insn) && !simplejump_p (insn) && map->last_pc_value)
+         if (any_condjump_p (insn) && onlyjump_p (insn) && map->last_pc_value)
            {
 #ifdef HAVE_cc0
              /* If the previous insn set cc0 for us, delete it.  */
@@ -2204,6 +2201,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
             this new block.  */
 
          if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
+             && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL
              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
              && ((NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
                   && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_CONT)
@@ -2429,7 +2427,7 @@ biv_total_increment (bl)
 
 static void
 iteration_info (loop, iteration_var, initial_value, increment)
-     const struct loop *loop;
+     const struct loop *loop ATTRIBUTE_UNUSED;
      rtx iteration_var, *initial_value, *increment;
 {
   struct iv_class *bl;
@@ -3284,7 +3282,7 @@ reg_dead_after_loop (loop, reg)
            {
              if (GET_CODE (PATTERN (insn)) == RETURN)
                break;
-             else if (! simplejump_p (insn)
+             else if (!any_uncondjump_p (insn)
                       /* Prevent infinite loop following infinite loops.  */
                       || jump_count++ > 20)
                return 0;