OSDN Git Service

* config/rs6000/rs6000.md: Document why a pattern is not
[pf3gnuchains/gcc-fork.git] / gcc / unroll.c
index 955136e..88e4423 100644 (file)
@@ -1,6 +1,6 @@
 /* Try to unroll loops, and split induction variables.
    Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003
+   2002, 2003, 2004
    Free Software Foundation, Inc.
    Contributed by James E. Wilson, Cygnus Support/UC Berkeley.
 
@@ -671,14 +671,14 @@ unroll_loop (struct loop *loop, int insn_count, int strength_reduce_p)
      without initializing fields within the map structure.
 
      To be safe, we use xcalloc to zero the memory.  */
-  map = (struct inline_remap *) xcalloc (1, sizeof (struct inline_remap));
+  map = xcalloc (1, sizeof (struct inline_remap));
 
   /* Allocate the label map.  */
 
   if (max_labelno > 0)
     {
-      map->label_map = (rtx *) xcalloc (max_labelno, sizeof (rtx));
-      local_label = (char *) xcalloc (max_labelno, sizeof (char));
+      map->label_map = xcalloc (max_labelno, sizeof (rtx));
+      local_label = xcalloc (max_labelno, sizeof (char));
     }
 
   /* Search the loop and mark all local labels, i.e. the ones which have to
@@ -722,7 +722,7 @@ unroll_loop (struct loop *loop, int insn_count, int strength_reduce_p)
 
   /* Allocate space for the insn map.  */
 
-  map->insn_map = (rtx *) xmalloc (max_insnno * sizeof (rtx));
+  map->insn_map = xmalloc (max_insnno * sizeof (rtx));
 
   /* Set this to zero, to indicate that we are doing loop unrolling,
      not function inlining.  */
@@ -748,11 +748,10 @@ unroll_loop (struct loop *loop, int insn_count, int strength_reduce_p)
      preconditioning code and find_splittable_regs will never be used
      to access the splittable_regs[] and addr_combined_regs[] arrays.  */
 
-  splittable_regs = (rtx *) xcalloc (maxregnum, sizeof (rtx));
-  splittable_regs_updates = (int *) xcalloc (maxregnum, sizeof (int));
-  addr_combined_regs
-    = (struct induction **) xcalloc (maxregnum, sizeof (struct induction *));
-  local_regno = (char *) xcalloc (maxregnum, sizeof (char));
+  splittable_regs = xcalloc (maxregnum, sizeof (rtx));
+  splittable_regs_updates = xcalloc (maxregnum, sizeof (int));
+  addr_combined_regs = xcalloc (maxregnum, sizeof (struct induction *));
+  local_regno = xcalloc (maxregnum, sizeof (char));
 
   /* Mark all local registers, i.e. the ones which are referenced only
      inside the loop.  */
@@ -854,7 +853,7 @@ unroll_loop (struct loop *loop, int insn_count, int strength_reduce_p)
          int less_p     = (cc == LE  || cc == LEU || cc == LT  || cc == LTU);
          int unsigned_p = (cc == LEU || cc == GEU || cc == LTU || cc == GTU);
 
-         map->reg_map = (rtx *) xmalloc (maxregnum * sizeof (rtx));
+         map->reg_map = xmalloc (maxregnum * sizeof (rtx));
 
          VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray, maxregnum,
                                   "unroll_loop_precondition");
@@ -921,7 +920,7 @@ unroll_loop (struct loop *loop, int insn_count, int strength_reduce_p)
          /* Now emit a sequence of branches to jump to the proper precond
             loop entry point.  */
 
-         labels = (rtx *) xmalloc (sizeof (rtx) * unroll_number);
+         labels = xmalloc (sizeof (rtx) * unroll_number);
          for (i = 0; i < unroll_number; i++)
            labels[i] = gen_label_rtx ();
 
@@ -1054,8 +1053,8 @@ unroll_loop (struct loop *loop, int insn_count, int strength_reduce_p)
              emit_label_after (labels[unroll_number - i],
                                PREV_INSN (loop_start));
 
-             memset ((char *) map->insn_map, 0, max_insnno * sizeof (rtx));
-             memset ((char *) &VARRAY_CONST_EQUIV (map->const_equiv_varray, 0),
+             memset (map->insn_map, 0, max_insnno * sizeof (rtx));
+             memset (&VARRAY_CONST_EQUIV (map->const_equiv_varray, 0),
                      0, (VARRAY_SIZE (map->const_equiv_varray)
                          * sizeof (struct const_equiv_data)));
              map->const_age = 0;
@@ -1158,7 +1157,7 @@ unroll_loop (struct loop *loop, int insn_count, int strength_reduce_p)
      the constant maps also.  */
 
   maxregnum = max_reg_num ();
-  map->reg_map = (rtx *) xmalloc (maxregnum * sizeof (rtx));
+  map->reg_map = xmalloc (maxregnum * sizeof (rtx));
 
   init_reg_map (map, maxregnum);
 
@@ -1206,8 +1205,8 @@ unroll_loop (struct loop *loop, int insn_count, int strength_reduce_p)
 
   for (i = 0; i < unroll_number; i++)
     {
-      memset ((char *) map->insn_map, 0, max_insnno * sizeof (rtx));
-      memset ((char *) &VARRAY_CONST_EQUIV (map->const_equiv_varray, 0), 0,
+      memset (map->insn_map, 0, max_insnno * sizeof (rtx));
+      memset (&VARRAY_CONST_EQUIV (map->const_equiv_varray, 0), 0,
              VARRAY_SIZE (map->const_equiv_varray) * sizeof (struct const_equiv_data));
       map->const_age = 0;
 
@@ -1339,7 +1338,7 @@ simplify_cmp_and_jump_insns (enum rtx_code code, enum machine_mode mode,
 {
   rtx t, insn;
 
-  t = simplify_relational_operation (code, mode, op0, op1);
+  t = simplify_const_relational_operation (code, mode, op0, op1);
   if (!t)
     {
       enum rtx_code scode = signed_condition (code);
@@ -2437,7 +2436,13 @@ biv_total_increment (const struct iv_class *bl)
       if (v->always_computable && v->mult_val == const1_rtx
          && ! v->maybe_multiple
          && SCALAR_INT_MODE_P (v->mode))
-       result = fold_rtx_mult_add (result, const1_rtx, v->add_val, v->mode);
+       {
+         /* If we have already counted it, skip it.  */
+         if (v->same)
+           continue;
+
+         result = fold_rtx_mult_add (result, const1_rtx, v->add_val, v->mode);
+       }
       else
        return 0;
     }
@@ -2792,8 +2797,9 @@ find_splittable_givs (const struct loop *loop, struct iv_class *bl,
                {
                  rtx tem = gen_reg_rtx (v->mode);
                  record_base_value (REGNO (tem), v->add_val, 0);
-                 loop_iv_add_mult_hoist (loop, bl->initial_value, v->mult_val,
-                                         v->add_val, tem);
+                 loop_iv_add_mult_hoist (loop, 
+                               extend_value_for_giv (v, bl->initial_value), 
+                               v->mult_val, v->add_val, tem);
                  value = tem;
                }
 
@@ -2866,7 +2872,6 @@ static int
 reg_dead_after_loop (const struct loop *loop, rtx reg)
 {
   rtx insn, label;
-  enum rtx_code code;
   int jump_count = 0;
   int label_count = 0;
 
@@ -2896,29 +2901,32 @@ reg_dead_after_loop (const struct loop *loop, rtx reg)
       insn = NEXT_INSN (XEXP (label, 0));
       while (insn)
        {
-         code = GET_CODE (insn);
-         if (GET_RTX_CLASS (code) == 'i')
+         if (INSN_P (insn))
            {
-             rtx set;
+             rtx set, note;
 
              if (reg_referenced_p (reg, PATTERN (insn)))
                return 0;
 
+             note = find_reg_equal_equiv_note (insn);
+             if (note && reg_overlap_mentioned_p (reg, XEXP (note, 0)))
+               return 0;
+
              set = single_set (insn);
              if (set && rtx_equal_p (SET_DEST (set), reg))
                break;
-           }
 
-         if (code == JUMP_INSN)
-           {
-             if (GET_CODE (PATTERN (insn)) == RETURN)
-               break;
-             else if (!any_uncondjump_p (insn)
-                      /* Prevent infinite loop following infinite loops.  */
-                      || jump_count++ > 20)
-               return 0;
-             else
-               insn = JUMP_LABEL (insn);
+             if (GET_CODE (insn) == JUMP_INSN)
+               {
+                 if (GET_CODE (PATTERN (insn)) == RETURN)
+                   break;
+                 else if (!any_uncondjump_p (insn)
+                          /* Prevent infinite loop following infinite loops.  */
+                          || jump_count++ > 20)
+                   return 0;
+                 else
+                   insn = JUMP_LABEL (insn);
+               }
            }
 
          insn = NEXT_INSN (insn);
@@ -3412,7 +3420,20 @@ loop_iterations (struct loop *loop)
                 "Loop iterations: Iteration var not an integer.\n");
       return 0;
     }
-  else if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT)
+
+  /* Try swapping the comparison to identify a suitable iv.  */
+  if (REG_IV_TYPE (ivs, REGNO (iteration_var)) != BASIC_INDUCT
+      && REG_IV_TYPE (ivs, REGNO (iteration_var)) != GENERAL_INDUCT
+      && GET_CODE (comparison_value) == REG
+      && REGNO (comparison_value) < ivs->n_regs)
+    {
+      rtx temp = comparison_value;
+      comparison_code = swap_condition (comparison_code);
+      comparison_value = iteration_var;
+      iteration_var = temp;
+    }
+
+  if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT)
     {
       if (REGNO (iteration_var) >= ivs->n_regs)
        abort ();
@@ -3478,6 +3499,10 @@ loop_iterations (struct loop *loop)
                        return 0;
                    }
 
+                 /* If we have already counted it, skip it.  */
+                 if (biv_inc->same)
+                   continue;
+
                  offset -= INTVAL (biv_inc->add_val);
                }
            }
@@ -3535,6 +3560,7 @@ loop_iterations (struct loop *loop)
       unsigned_p = 1;
     case GT:
       compare_dir = -1;
+      break;
     case NE:
       compare_dir = 0;
       break;
@@ -3615,7 +3641,7 @@ loop_iterations (struct loop *loop)
 
          if (find_common_reg_term (temp, reg2))
            initial_value = temp;
-         else
+         else if (loop_invariant_p (loop, reg2))
            {
              /* Find what reg2 is equivalent to.  Hopefully it will
                 either be reg1 or reg1 plus a constant.  Let's ignore