OSDN Git Service

* c-tree.h (enum c_storage_class): New.
[pf3gnuchains/gcc-fork.git] / gcc / loop-iv.c
index efdcc73..a7c43e3 100644 (file)
@@ -34,14 +34,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    interesting reg, it is now easy to find a reaching definition (there may be
    only one).
 
-   Induction variable is then simply analysed by walking the use-def
+   Induction variable is then simply analyzed by walking the use-def
    chains.
    
    Usage:
 
    iv_analysis_loop_init (loop);
    insn = iv_get_reaching_def (where, reg);
-   if (iv_analyse (insn, reg, &iv))
+   if (iv_analyze (insn, reg, &iv))
      {
        ...
      }
@@ -104,17 +104,17 @@ dump_iv_info (FILE *file, struct rtx_iv *iv)
       return;
     }
 
-  if (iv->step == const0_rtx)
-    {
-      fprintf (file, "invariant ");
-      print_rtl (file, iv->base);
-      return;
-    }
+  if (iv->step == const0_rtx
+      && !iv->first_special)
+    fprintf (file, "invariant ");
 
   print_rtl (file, iv->base);
-  fprintf (file, " + ");
-  print_rtl (file, iv->step);
-  fprintf (file, " * iteration");
+  if (iv->step != const0_rtx)
+    {
+      fprintf (file, " + ");
+      print_rtl (file, iv->step);
+      fprintf (file, " * iteration");
+    }
   fprintf (file, " (in %s)", GET_MODE_NAME (iv->mode));
 
   if (iv->mode != iv->extend_mode)
@@ -222,6 +222,7 @@ simple_set_p (rtx lhs, rtx rhs)
     case PLUS:
     case MINUS:
     case MULT:
+    case ASHIFT:
       op0 = XEXP (rhs, 0);
       op1 = XEXP (rhs, 1);
 
@@ -238,6 +239,10 @@ simple_set_p (rtx lhs, rtx rhs)
          && !CONSTANT_P (op1))
        return false;
 
+      if (GET_CODE (rhs) == ASHIFT
+         && CONSTANT_P (op0))
+       return false;
+
       return true;
 
     default:
@@ -254,7 +259,9 @@ mark_single_set (rtx insn, rtx set)
   unsigned regno, uid;
 
   src = find_reg_equal_equiv_note (insn);
-  if (!src)
+  if (src)
+    src = XEXP (src, 0);
+  else
     src = SET_SRC (set);
 
   if (!simple_set_p (SET_DEST (set), src))
@@ -420,7 +427,7 @@ iv_constant (struct rtx_iv *iv, rtx cst, enum machine_mode mode)
   iv->base = cst;
   iv->step = const0_rtx;
   iv->first_special = false;
-  iv->extend = NIL;
+  iv->extend = UNKNOWN;
   iv->extend_mode = iv->mode;
   iv->delta = const0_rtx;
   iv->mult = const1_rtx;
@@ -433,13 +440,28 @@ iv_constant (struct rtx_iv *iv, rtx cst, enum machine_mode mode)
 static bool
 iv_subreg (struct rtx_iv *iv, enum machine_mode mode)
 {
+  /* If iv is invariant, just calculate the new value.  */
+  if (iv->step == const0_rtx
+      && !iv->first_special)
+    {
+      rtx val = get_iv_value (iv, const0_rtx);
+      val = lowpart_subreg (mode, val, iv->extend_mode);
+
+      iv->base = val;
+      iv->extend = UNKNOWN;
+      iv->mode = iv->extend_mode = mode;
+      iv->delta = const0_rtx;
+      iv->mult = const1_rtx;
+      return true;
+    }
+
   if (iv->extend_mode == mode)
     return true;
 
   if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (iv->mode))
     return false;
 
-  iv->extend = NIL;
+  iv->extend = UNKNOWN;
   iv->mode = mode;
 
   iv->base = simplify_gen_binary (PLUS, iv->extend_mode, iv->delta,
@@ -458,10 +480,25 @@ iv_subreg (struct rtx_iv *iv, enum machine_mode mode)
 static bool
 iv_extend (struct rtx_iv *iv, enum rtx_code extend, enum machine_mode mode)
 {
+  /* If iv is invariant, just calculate the new value.  */
+  if (iv->step == const0_rtx
+      && !iv->first_special)
+    {
+      rtx val = get_iv_value (iv, const0_rtx);
+      val = simplify_gen_unary (extend, mode, val, iv->extend_mode);
+
+      iv->base = val;
+      iv->extend = UNKNOWN;
+      iv->mode = iv->extend_mode = mode;
+      iv->delta = const0_rtx;
+      iv->mult = const1_rtx;
+      return true;
+    }
+
   if (mode != iv->extend_mode)
     return false;
 
-  if (iv->extend != NIL
+  if (iv->extend != UNKNOWN
       && iv->extend != extend)
     return false;
 
@@ -475,7 +512,7 @@ iv_extend (struct rtx_iv *iv, enum rtx_code extend, enum machine_mode mode)
 static bool
 iv_neg (struct rtx_iv *iv)
 {
-  if (iv->extend == NIL)
+  if (iv->extend == UNKNOWN)
     {
       iv->base = simplify_gen_unary (NEG, iv->extend_mode,
                                     iv->base, iv->extend_mode);
@@ -501,8 +538,8 @@ iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op)
   enum machine_mode mode;
   rtx arg;
 
-  /* Extend the constant to extend_mode of the other operand if neccesary.  */
-  if (iv0->extend == NIL
+  /* Extend the constant to extend_mode of the other operand if necessary.  */
+  if (iv0->extend == UNKNOWN
       && iv0->mode == iv0->extend_mode
       && iv0->step == const0_rtx
       && GET_MODE_SIZE (iv0->extend_mode) < GET_MODE_SIZE (iv1->extend_mode))
@@ -511,7 +548,7 @@ iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op)
       iv0->base = simplify_gen_unary (ZERO_EXTEND, iv0->extend_mode,
                                      iv0->base, iv0->mode);
     }
-  if (iv1->extend == NIL
+  if (iv1->extend == UNKNOWN
       && iv1->mode == iv1->extend_mode
       && iv1->step == const0_rtx
       && GET_MODE_SIZE (iv1->extend_mode) < GET_MODE_SIZE (iv0->extend_mode))
@@ -525,7 +562,7 @@ iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op)
   if (mode != iv1->extend_mode)
     return false;
 
-  if (iv0->extend == NIL && iv1->extend == NIL)
+  if (iv0->extend == UNKNOWN && iv1->extend == UNKNOWN)
     {
       if (iv0->mode != iv1->mode)
        return false;
@@ -537,7 +574,7 @@ iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op)
     }
 
   /* Handle addition of constant.  */
-  if (iv1->extend == NIL
+  if (iv1->extend == UNKNOWN
       && iv1->mode == mode
       && iv1->step == const0_rtx)
     {
@@ -545,7 +582,7 @@ iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op)
       return true;
     }
 
-  if (iv0->extend == NIL
+  if (iv0->extend == UNKNOWN
       && iv0->mode == mode
       && iv0->step == const0_rtx)
     {
@@ -573,7 +610,7 @@ iv_mult (struct rtx_iv *iv, rtx mby)
       && GET_MODE (mby) != mode)
     return false;
 
-  if (iv->extend == NIL)
+  if (iv->extend == UNKNOWN)
     {
       iv->base = simplify_gen_binary (MULT, mode, iv->base, mby);
       iv->step = simplify_gen_binary (MULT, mode, iv->step, mby);
@@ -587,6 +624,31 @@ iv_mult (struct rtx_iv *iv, rtx mby)
   return true;
 }
 
+/* Evaluates shift of IV by constant CST.  */
+
+static bool
+iv_shift (struct rtx_iv *iv, rtx mby)
+{
+  enum machine_mode mode = iv->extend_mode;
+
+  if (GET_MODE (mby) != VOIDmode
+      && GET_MODE (mby) != mode)
+    return false;
+
+  if (iv->extend == UNKNOWN)
+    {
+      iv->base = simplify_gen_binary (ASHIFT, mode, iv->base, mby);
+      iv->step = simplify_gen_binary (ASHIFT, mode, iv->step, mby);
+    }
+  else
+    {
+      iv->delta = simplify_gen_binary (ASHIFT, mode, iv->delta, mby);
+      iv->mult = simplify_gen_binary (ASHIFT, mode, iv->mult, mby);
+    }
+
+  return true;
+}
+
 /* The recursive part of get_biv_step.  Gets the value of the single value
    defined in INSN wrto initial value of REG inside loop, in shape described
    at get_biv_step.  */
@@ -603,7 +665,9 @@ get_biv_step_1 (rtx insn, rtx reg,
 
   set = single_set (insn);
   rhs = find_reg_equal_equiv_note (insn);
-  if (!rhs)
+  if (rhs)
+    rhs = XEXP (rhs, 0);
+  else
     rhs = SET_SRC (set);
   lhs = SET_DEST (set);
 
@@ -686,7 +750,7 @@ get_biv_step_1 (rtx insn, rtx reg,
        return false;
 
       *inner_step = const0_rtx;
-      *extend = NIL;
+      *extend = UNKNOWN;
       *inner_mode = outer_mode;
       *outer_step = const0_rtx;
     }
@@ -706,7 +770,7 @@ get_biv_step_1 (rtx insn, rtx reg,
       *inner_step = simplify_gen_binary (PLUS, outer_mode,
                                         *inner_step, *outer_step);
       *outer_step = const0_rtx;
-      *extend = NIL;
+      *extend = UNKNOWN;
     }
 
   switch (code)
@@ -730,7 +794,7 @@ get_biv_step_1 (rtx insn, rtx reg,
     case SIGN_EXTEND:
     case ZERO_EXTEND:
       if (GET_MODE (op0) != *inner_mode
-         || *extend != NIL
+         || *extend != UNKNOWN
          || *outer_step != const0_rtx)
        abort ();
 
@@ -763,11 +827,11 @@ get_biv_step (rtx reg, rtx *inner_step, enum machine_mode *inner_mode,
     return false;
 
   if (*inner_mode != *outer_mode
-      && *extend == NIL)
+      && *extend == UNKNOWN)
     abort ();
 
   if (*inner_mode == *outer_mode
-      && *extend != NIL)
+      && *extend != UNKNOWN)
     abort ();
 
   if (*inner_mode == *outer_mode
@@ -781,18 +845,18 @@ get_biv_step (rtx reg, rtx *inner_step, enum machine_mode *inner_mode,
    to *IV.  */
 
 static bool
-iv_analyse_biv (rtx def, struct rtx_iv *iv)
+iv_analyze_biv (rtx def, struct rtx_iv *iv)
 {
   unsigned regno;
   rtx inner_step, outer_step;
   enum machine_mode inner_mode, outer_mode;
   enum rtx_code extend;
 
-  if (rtl_dump_file)
+  if (dump_file)
     {
-      fprintf (rtl_dump_file, "Analysing ");
-      print_rtl (rtl_dump_file, def);
-      fprintf (rtl_dump_file, " for bivness.\n");
+      fprintf (dump_file, "Analysing ");
+      print_rtl (dump_file, def);
+      fprintf (dump_file, " for bivness.\n");
     }
     
   if (!REG_P (def))
@@ -806,15 +870,15 @@ iv_analyse_biv (rtx def, struct rtx_iv *iv)
   regno = REGNO (def);
   if (last_def[regno] == const0_rtx)
     {
-      if (rtl_dump_file)
-       fprintf (rtl_dump_file, "  not simple.\n");
+      if (dump_file)
+       fprintf (dump_file, "  not simple.\n");
       return false;
     }
 
   if (last_def[regno] && bivs[regno].analysed)
     {
-      if (rtl_dump_file)
-       fprintf (rtl_dump_file, "  already analysed.\n");
+      if (dump_file)
+       fprintf (dump_file, "  already analysed.\n");
 
       *iv = bivs[regno];
       return iv->base != NULL_RTX;
@@ -849,12 +913,12 @@ iv_analyse_biv (rtx def, struct rtx_iv *iv)
   iv->delta = outer_step;
   iv->first_special = inner_mode != outer_mode;
 
-end:
-  if (rtl_dump_file)
+ end:
+  if (dump_file)
     {
-      fprintf (rtl_dump_file, "  ");
-      dump_iv_info (rtl_dump_file, iv);
-      fprintf (rtl_dump_file, "\n");
+      fprintf (dump_file, "  ");
+      dump_iv_info (dump_file, iv);
+      fprintf (dump_file, "\n");
     }
 
   bivs[regno] = *iv;
@@ -862,21 +926,21 @@ end:
   return iv->base != NULL_RTX;
 }
 
-/* Analyses operand OP of INSN and stores the result to *IV.  */
+/* Analyzes operand OP of INSN and stores the result to *IV.  */
 
 static bool
-iv_analyse_op (rtx insn, rtx op, struct rtx_iv *iv)
+iv_analyze_op (rtx insn, rtx op, struct rtx_iv *iv)
 {
   rtx def_insn;
   unsigned regno;
   bool inv = CONSTANT_P (op);
 
-  if (rtl_dump_file)
+  if (dump_file)
     {
-      fprintf (rtl_dump_file, "Analysing operand ");
-      print_rtl (rtl_dump_file, op);
-      fprintf (rtl_dump_file, " of insn ");
-      print_rtl_single (rtl_dump_file, insn);
+      fprintf (dump_file, "Analysing operand ");
+      print_rtl (dump_file, op);
+      fprintf (dump_file, " of insn ");
+      print_rtl_single (dump_file, insn);
     }
 
   if (GET_CODE (op) == SUBREG)
@@ -884,7 +948,7 @@ iv_analyse_op (rtx insn, rtx op, struct rtx_iv *iv)
       if (!subreg_lowpart_p (op))
        return false;
 
-      if (!iv_analyse_op (insn, SUBREG_REG (op), iv))
+      if (!iv_analyze_op (insn, SUBREG_REG (op), iv))
        return false;
 
       return iv_subreg (iv, GET_MODE (op));
@@ -897,8 +961,8 @@ iv_analyse_op (rtx insn, rtx op, struct rtx_iv *iv)
        inv = true;
       else if (last_def[regno] == const0_rtx)
        {
-         if (rtl_dump_file)
-           fprintf (rtl_dump_file, "  not simple.\n");
+         if (dump_file)
+           fprintf (dump_file, "  not simple.\n");
          return false;
        }
     }
@@ -907,11 +971,11 @@ iv_analyse_op (rtx insn, rtx op, struct rtx_iv *iv)
     {
       iv_constant (iv, op, VOIDmode);
 
-      if (rtl_dump_file)
+      if (dump_file)
        {
-         fprintf (rtl_dump_file, "  ");
-         dump_iv_info (rtl_dump_file, iv);
-         fprintf (rtl_dump_file, "\n");
+         fprintf (dump_file, "  ");
+         dump_iv_info (dump_file, iv);
+         fprintf (dump_file, "\n");
        }
       return true;
     }
@@ -919,18 +983,18 @@ iv_analyse_op (rtx insn, rtx op, struct rtx_iv *iv)
   def_insn = iv_get_reaching_def (insn, op);
   if (def_insn == const0_rtx)
     {
-      if (rtl_dump_file)
-       fprintf (rtl_dump_file, "  not simple.\n");
+      if (dump_file)
+       fprintf (dump_file, "  not simple.\n");
       return false;
     }
 
-  return iv_analyse (def_insn, op, iv);
+  return iv_analyze (def_insn, op, iv);
 }
 
-/* Analyses iv DEF defined in INSN and stores the result to *IV.  */
+/* Analyzes iv DEF defined in INSN and stores the result to *IV.  */
 
 bool
-iv_analyse (rtx insn, rtx def, struct rtx_iv *iv)
+iv_analyze (rtx insn, rtx def, struct rtx_iv *iv)
 {
   unsigned uid;
   rtx set, rhs, mby = NULL_RTX, tmp;
@@ -947,28 +1011,28 @@ iv_analyse (rtx insn, rtx def, struct rtx_iv *iv)
       if (!subreg_lowpart_p (def))
        return false;
 
-      if (!iv_analyse (insn, SUBREG_REG (def), iv))
+      if (!iv_analyze (insn, SUBREG_REG (def), iv))
        return false;
 
       return iv_subreg (iv, GET_MODE (def));
     }
 
   if (!insn)
-    return iv_analyse_biv (def, iv);
+    return iv_analyze_biv (def, iv);
 
-  if (rtl_dump_file)
+  if (dump_file)
     {
-      fprintf (rtl_dump_file, "Analysing def of ");
-      print_rtl (rtl_dump_file, def);
-      fprintf (rtl_dump_file, " in insn ");
-      print_rtl_single (rtl_dump_file, insn);
+      fprintf (dump_file, "Analysing def of ");
+      print_rtl (dump_file, def);
+      fprintf (dump_file, " in insn ");
+      print_rtl_single (dump_file, insn);
     }
 
   uid = INSN_UID (insn);
   if (insn_info[uid].iv.analysed)
     {
-      if (rtl_dump_file)
-       fprintf (rtl_dump_file, "  already analysed.\n");
+      if (dump_file)
+       fprintf (dump_file, "  already analysed.\n");
       *iv = insn_info[uid].iv;
       return iv->base != NULL_RTX;
     }
@@ -979,7 +1043,9 @@ iv_analyse (rtx insn, rtx def, struct rtx_iv *iv)
 
   set = single_set (insn);
   rhs = find_reg_equal_equiv_note (insn);
-  if (!rhs)
+  if (rhs)
+    rhs = XEXP (rhs, 0);
+  else
     rhs = SET_SRC (set);
   code = GET_CODE (rhs);
 
@@ -1026,7 +1092,14 @@ iv_analyse (rtx insn, rtx def, struct rtx_iv *iv)
              mby = tmp;
            }
          break;
-           
+
+       case ASHIFT:
+         if (CONSTANT_P (XEXP (rhs, 0)))
+           abort ();
+         op0 = XEXP (rhs, 0);
+         mby = XEXP (rhs, 1);
+         break;
+
        default:
          abort ();
        }
@@ -1036,7 +1109,7 @@ iv_analyse (rtx insn, rtx def, struct rtx_iv *iv)
 
   if (op0)
     {
-      if (!iv_analyse_op (insn, op0, &iv0))
+      if (!iv_analyze_op (insn, op0, &iv0))
        goto end;
        
       if (iv0.mode == VOIDmode)
@@ -1048,7 +1121,7 @@ iv_analyse (rtx insn, rtx def, struct rtx_iv *iv)
 
   if (op1)
     {
-      if (!iv_analyse_op (insn, op1, &iv1))
+      if (!iv_analyze_op (insn, op1, &iv1))
        goto end;
 
       if (iv1.mode == VOIDmode)
@@ -1082,24 +1155,29 @@ iv_analyse (rtx insn, rtx def, struct rtx_iv *iv)
        goto end;
       break;
 
+    case ASHIFT:
+      if (!iv_shift (&iv0, mby))
+       goto end;
+      break;
+
     default:
       break;
     }
 
   *iv = iv0;
 
-end:
+ end:
   iv->analysed = true;
   insn_info[uid].iv = *iv;
 
-  if (rtl_dump_file)
+  if (dump_file)
     {
-      print_rtl (rtl_dump_file, def);
-      fprintf (rtl_dump_file, " in insn ");
-      print_rtl_single (rtl_dump_file, insn);
-      fprintf (rtl_dump_file, "  is ");
-      dump_iv_info (rtl_dump_file, iv);
-      fprintf (rtl_dump_file, "\n");
+      print_rtl (dump_file, def);
+      fprintf (dump_file, " in insn ");
+      print_rtl_single (dump_file, insn);
+      fprintf (dump_file, "  is ");
+      dump_iv_info (dump_file, iv);
+      fprintf (dump_file, "\n");
     }
 
   return iv->base != NULL_RTX;
@@ -1129,7 +1207,7 @@ get_iv_value (struct rtx_iv *iv, rtx iteration)
 
   val = lowpart_subreg (iv->mode, val, iv->extend_mode);
 
-  if (iv->extend == NIL)
+  if (iv->extend == UNKNOWN)
     return val;
 
   val = simplify_gen_unary (iv->extend, iv->extend_mode, val, iv->mode);
@@ -1203,7 +1281,7 @@ determine_max_iter (struct niter_desc *desc)
        }
     }
 
-  get_mode_bounds (desc->mode, desc->signed_p, &mmin, &mmax);
+  get_mode_bounds (desc->mode, desc->signed_p, desc->mode, &mmin, &mmax);
   nmax = INTVAL (mmax) - INTVAL (mmin);
 
   if (GET_CODE (niter) == UDIV)
@@ -1309,13 +1387,13 @@ static void
 simplify_using_assignment (rtx insn, rtx *expr, regset altered)
 {
   rtx set = single_set (insn);
-  rtx lhs, rhs;
+  rtx lhs = NULL_RTX, rhs;
   bool ret = false;
 
   if (set)
     {
       lhs = SET_DEST (set);
-      if (GET_CODE (lhs) != REG
+      if (!REG_P (lhs)
          || altered_reg_used (&lhs, altered))
        ret = true;
     }
@@ -1323,7 +1401,7 @@ simplify_using_assignment (rtx insn, rtx *expr, regset altered)
     ret = true;
 
   note_stores (PATTERN (insn), mark_altered, altered);
-  if (GET_CODE (insn) == CALL_INSN)
+  if (CALL_P (insn))
     {
       int i;
 
@@ -1337,7 +1415,9 @@ simplify_using_assignment (rtx insn, rtx *expr, regset altered)
     return;
 
   rhs = find_reg_equal_equiv_note (insn);
-  if (!rhs)
+  if (rhs)
+    rhs = XEXP (rhs, 0);
+  else
     rhs = SET_SRC (set);
 
   if (!simple_rhs_p (rhs))
@@ -1354,7 +1434,8 @@ simplify_using_assignment (rtx insn, rtx *expr, regset altered)
 static bool
 implies_p (rtx a, rtx b)
 {
-  rtx op0, op1, r;
+  rtx op0, op1, opb0, opb1, r;
+  enum machine_mode mode;
 
   if (GET_CODE (a) == EQ)
     {
@@ -1376,6 +1457,45 @@ implies_p (rtx a, rtx b)
        }
     }
 
+  /* A < B implies A + 1 <= B.  */
+  if ((GET_CODE (a) == GT || GET_CODE (a) == LT)
+      && (GET_CODE (b) == GE || GET_CODE (b) == LE))
+    {
+      op0 = XEXP (a, 0);
+      op1 = XEXP (a, 1);
+      opb0 = XEXP (b, 0);
+      opb1 = XEXP (b, 1);
+
+      if (GET_CODE (a) == GT)
+       {
+         r = op0;
+         op0 = op1;
+         op1 = r;
+       }
+
+      if (GET_CODE (b) == GE)
+       {
+         r = opb0;
+         opb0 = opb1;
+         opb1 = r;
+       }
+
+      mode = GET_MODE (op0);
+      if (mode != GET_MODE (opb0))
+       mode = VOIDmode;
+      else if (mode == VOIDmode)
+       {
+         mode = GET_MODE (op1);
+         if (mode != GET_MODE (opb1))
+           mode = VOIDmode;
+       }
+
+      if (mode != VOIDmode
+         && rtx_equal_p (op1, opb1)
+         && simplify_gen_binary (MINUS, mode, opb0, op0) == const1_rtx)
+       return true;
+    }
+
   return false;
 }
 
@@ -1469,7 +1589,7 @@ simplify_using_condition (rtx cond, rtx *expr, regset altered)
 {
   rtx rev, reve, exp = *expr;
 
-  if (GET_RTX_CLASS (GET_CODE (*expr)) != '<')
+  if (!COMPARISON_P (exp))
     return;
 
   /* If some register gets altered later, we do not really speak about its
@@ -1607,7 +1727,7 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
       else
        abort ();
 
-      simplify_using_initial_values (loop, NIL, &head);
+      simplify_using_initial_values (loop, UNKNOWN, &head);
       if (head == aggr)
        {
          XEXP (*expr, 0) = aggr;
@@ -1633,7 +1753,7 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
       return;
     }
 
-  if (op != NIL)
+  if (op != UNKNOWN)
     abort ();
 
   e = loop_preheader_edge (loop);
@@ -1647,9 +1767,7 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
       insn = BB_END (e->src);
       if (any_condjump_p (insn))
        {
-         /* FIXME -- slightly wrong -- what if compared register
-            gets altered between start of the condition and insn?  */
-         rtx cond = get_condition (BB_END (e->src), NULL, false);
+         rtx cond = get_condition (BB_END (e->src), NULL, false, true);
       
          if (cond && (e->flags & EDGE_FALLTHRU))
            cond = reversed_condition (cond);
@@ -1696,7 +1814,7 @@ shorten_into_mode (struct rtx_iv *iv, enum machine_mode mode,
 {
   rtx mmin, mmax, cond_over, cond_under;
 
-  get_mode_bounds (mode, signed_p, &mmin, &mmax);
+  get_mode_bounds (mode, signed_p, iv->extend_mode, &mmin, &mmax);
   cond_under = simplify_gen_relational (LT, SImode, iv->extend_mode,
                                        iv->base, mmin);
   cond_over = simplify_gen_relational (GT, SImode, iv->extend_mode,
@@ -1746,7 +1864,7 @@ shorten_into_mode (struct rtx_iv *iv, enum machine_mode mode,
 }
 
 /* Transforms IV0 and IV1 compared by COND so that they are both compared as
-   subregs of the same mode if possible (sometimes it is neccesary to add
+   subregs of the same mode if possible (sometimes it is necessary to add
    some assumptions to DESC).  */
 
 static bool
@@ -1783,15 +1901,15 @@ canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1,
        break;
 
       case NE:
-       if (iv0->extend != NIL
-           && iv1->extend != NIL
+       if (iv0->extend != UNKNOWN
+           && iv1->extend != UNKNOWN
            && iv0->extend != iv1->extend)
          return false;
 
        signed_p = false;
-       if (iv0->extend != NIL)
+       if (iv0->extend != UNKNOWN)
          signed_p = iv0->extend == SIGN_EXTEND;
-       if (iv1->extend != NIL)
+       if (iv1->extend != UNKNOWN)
          signed_p = iv1->extend == SIGN_EXTEND;
        break;
 
@@ -1870,13 +1988,14 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
 {
   rtx op0, op1, delta, step, bound, may_xform, def_insn, tmp, tmp0, tmp1;
   struct rtx_iv iv0, iv1, tmp_iv;
-  rtx assumption;
+  rtx assumption, may_not_xform;
   enum rtx_code cond;
   enum machine_mode mode, comp_mode;
-  rtx mmin, mmax;
-  unsigned HOST_WIDEST_INT s, size, d;
+  rtx mmin, mmax, mode_mmin, mode_mmax;
+  unsigned HOST_WIDEST_INT s, size, d, inv;
   HOST_WIDEST_INT up, down, inc;
   int was_sharp = false;
+  rtx old_niter;
 
   /* The meaning of these assumptions is this:
      if !assumptions
@@ -1894,7 +2013,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
   desc->niter_max = 0;
 
   cond = GET_CODE (condition);
-  if (GET_RTX_CLASS (cond) != '<')
+  if (!COMPARISON_P (condition))
     abort ();
 
   mode = GET_MODE (XEXP (condition, 0));
@@ -1911,14 +2030,14 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
 
   op0 = XEXP (condition, 0);
   def_insn = iv_get_reaching_def (insn, op0);
-  if (!iv_analyse (def_insn, op0, &iv0))
+  if (!iv_analyze (def_insn, op0, &iv0))
     goto fail;
   if (iv0.extend_mode == VOIDmode)
     iv0.mode = iv0.extend_mode = mode;
   
   op1 = XEXP (condition, 1);
   def_insn = iv_get_reaching_def (insn, op1);
-  if (!iv_analyse (def_insn, op1, &iv1))
+  if (!iv_analyze (def_insn, op1, &iv1))
     goto fail;
   if (iv1.extend_mode == VOIDmode)
     iv1.mode = iv1.extend_mode = mode;
@@ -1959,7 +2078,9 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
   comp_mode = iv0.extend_mode;
   mode = iv0.mode;
   size = GET_MODE_BITSIZE (mode);
-  get_mode_bounds (mode, (cond == LE || cond == LT), &mmin, &mmax);
+  get_mode_bounds (mode, (cond == LE || cond == LT), comp_mode, &mmin, &mmax);
+  mode_mmin = lowpart_subreg (mode, mmin, comp_mode);
+  mode_mmax = lowpart_subreg (mode, mmax, comp_mode);
 
   if (GET_CODE (iv0.step) != CONST_INT || GET_CODE (iv1.step) != CONST_INT)
     goto fail;
@@ -2001,7 +2122,8 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
        if (iv0.step == const0_rtx)
          {
            tmp = lowpart_subreg (mode, iv0.base, comp_mode);
-           assumption = simplify_gen_relational (EQ, SImode, mode, tmp, mmax);
+           assumption = simplify_gen_relational (EQ, SImode, mode, tmp,
+                                                 mode_mmax);
            if (assumption == const_true_rtx)
              goto zero_iter;
            iv0.base = simplify_gen_binary (PLUS, comp_mode,
@@ -2010,7 +2132,8 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
        else
          {
            tmp = lowpart_subreg (mode, iv1.base, comp_mode);
-           assumption = simplify_gen_relational (EQ, SImode, mode, tmp, mmin);
+           assumption = simplify_gen_relational (EQ, SImode, mode, tmp,
+                                                 mode_mmin);
            if (assumption == const_true_rtx)
              goto zero_iter;
            iv1.base = simplify_gen_binary (PLUS, comp_mode,
@@ -2035,7 +2158,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
       if (iv0.step == const0_rtx)
        {
          tmp = lowpart_subreg (mode, iv0.base, comp_mode);
-         if (rtx_equal_p (tmp, mmin))
+         if (rtx_equal_p (tmp, mode_mmin))
            {
              desc->infinite =
                      alloc_EXPR_LIST (0, const_true_rtx, NULL_RTX);
@@ -2045,7 +2168,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
       else
        {
          tmp = lowpart_subreg (mode, iv1.base, comp_mode);
-         if (rtx_equal_p (tmp, mmax))
+         if (rtx_equal_p (tmp, mode_mmax))
            {
              desc->infinite =
                      alloc_EXPR_LIST (0, const_true_rtx, NULL_RTX);
@@ -2070,6 +2193,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
       delta = lowpart_subreg (mode, delta, comp_mode);
       delta = simplify_gen_binary (UMOD, mode, delta, step);
       may_xform = const0_rtx;
+      may_not_xform = const_true_rtx;
 
       if (GET_CODE (delta) == CONST_INT)
        {
@@ -2082,7 +2206,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
                 obviously if the test for overflow during that transformation
                 passed, we cannot overflow here.  Most importantly any
                 loop with sharp end condition and step 1 falls into this
-                cathegory, so handling this case specially is definitely
+                category, so handling this case specially is definitely
                 worth the troubles.  */
              may_xform = const_true_rtx;
            }
@@ -2094,6 +2218,9 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
              tmp = lowpart_subreg (mode, iv0.base, comp_mode);
              may_xform = simplify_gen_relational (cond, SImode, mode,
                                                   bound, tmp);
+             may_not_xform = simplify_gen_relational (reverse_condition (cond),
+                                                      SImode, mode,
+                                                      bound, tmp);
            }
          else
            {
@@ -2103,6 +2230,9 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
              tmp = lowpart_subreg (mode, iv1.base, comp_mode);
              may_xform = simplify_gen_relational (cond, SImode, mode,
                                                   tmp, bound);
+             may_not_xform = simplify_gen_relational (reverse_condition (cond),
+                                                      SImode, mode,
+                                                      tmp, bound);
            }
        }
 
@@ -2112,8 +2242,18 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
             completely senseless.  This is OK, as we would need this assumption
             to determine the number of iterations anyway.  */
          if (may_xform != const_true_rtx)
-           desc->assumptions = alloc_EXPR_LIST (0, may_xform,
-                                                desc->assumptions);
+           {
+             /* If the step is a power of two and the final value we have
+                computed overflows, the cycle is infinite.  Otherwise it
+                is nontrivial to compute the number of iterations.  */
+             s = INTVAL (step);
+             if ((s & (s - 1)) == 0)
+               desc->infinite = alloc_EXPR_LIST (0, may_not_xform,
+                                                 desc->infinite);
+             else
+               desc->assumptions = alloc_EXPR_LIST (0, may_xform,
+                                                    desc->assumptions);
+           }
 
          /* We are going to lose some information about upper bound on
             number of iterations in this step, so record the information
@@ -2122,8 +2262,10 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
          if (GET_CODE (iv1.base) == CONST_INT)
            up = INTVAL (iv1.base);
          else
-           up = INTVAL (mmax) - inc;
-         down = INTVAL (GET_CODE (iv0.base) == CONST_INT ? iv0.base : mmin);
+           up = INTVAL (mode_mmax) - inc;
+         down = INTVAL (GET_CODE (iv0.base) == CONST_INT
+                        ? iv0.base
+                        : mode_mmin);
          desc->niter_max = (up - down) / inc + 1;
 
          if (iv0.step == const0_rtx)
@@ -2186,8 +2328,9 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
       desc->infinite = alloc_EXPR_LIST (0, assumption, desc->infinite);
 
       tmp = simplify_gen_binary (UDIV, mode, tmp1, GEN_INT (d));
-      tmp = simplify_gen_binary (MULT, mode,
-                                tmp, GEN_INT (inverse (s, size)));
+      inv = inverse (s, size);
+      inv = trunc_int_for_mode (inv, mode);
+      tmp = simplify_gen_binary (MULT, mode, tmp, GEN_INT (inv));
       desc->niter_expr = simplify_gen_binary (AND, mode, tmp, bound);
     }
   else
@@ -2204,7 +2347,8 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
          tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
          tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
 
-         bound = simplify_gen_binary (MINUS, mode, mmax, step);
+         bound = simplify_gen_binary (MINUS, mode, mode_mmax,
+                                      lowpart_subreg (mode, step, comp_mode));
          assumption = simplify_gen_relational (cond, SImode, mode,
                                                tmp1, bound);
          desc->assumptions =
@@ -2227,7 +2371,8 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
          tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
          tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
 
-         bound = simplify_gen_binary (MINUS, mode, mmin, step);
+         bound = simplify_gen_binary (MINUS, mode, mode_mmin,
+                                      lowpart_subreg (mode, step, comp_mode));
          assumption = simplify_gen_relational (cond, SImode, mode,
                                                bound, tmp0);
          desc->assumptions =
@@ -2250,13 +2395,15 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
       desc->niter_expr = delta;
     }
 
+  old_niter = desc->niter_expr;
+
   simplify_using_initial_values (loop, AND, &desc->assumptions);
   if (desc->assumptions
       && XEXP (desc->assumptions, 0) == const0_rtx)
     goto fail;
   simplify_using_initial_values (loop, IOR, &desc->noloop_assumptions);
   simplify_using_initial_values (loop, IOR, &desc->infinite);
-  simplify_using_initial_values (loop, NIL, &desc->niter_expr);
+  simplify_using_initial_values (loop, UNKNOWN, &desc->niter_expr);
 
   /* Rerun the simplification.  Consider code (created by copying loop headers)
 
@@ -2279,7 +2426,11 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
     goto fail;
   simplify_using_initial_values (loop, IOR, &desc->noloop_assumptions);
   simplify_using_initial_values (loop, IOR, &desc->infinite);
-  simplify_using_initial_values (loop, NIL, &desc->niter_expr);
+  simplify_using_initial_values (loop, UNKNOWN, &desc->niter_expr);
+
+  if (desc->noloop_assumptions
+      && XEXP (desc->noloop_assumptions, 0) == const_true_rtx)
+    goto zero_iter;
 
   if (GET_CODE (desc->niter_expr) == CONST_INT)
     {
@@ -2288,8 +2439,19 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
       desc->const_iter = true;
       desc->niter_max = desc->niter = val & GET_MODE_MASK (desc->mode);
     }
-  else if (!desc->niter_max)
-    desc->niter_max = determine_max_iter (desc);
+  else
+    {
+      if (!desc->niter_max)
+       desc->niter_max = determine_max_iter (desc);
+
+      /* simplify_using_initial_values does a copy propagation on the registers
+        in the expression for the number of iterations.  This prolongs life
+        ranges of registers and increases register pressure, and usually
+        brings no gain (and if it happens to do, the cse pass will take care
+        of it anyway).  So prevent this behavior, unless it enabled us to
+        derive that the number of iterations is a constant.  */
+      desc->niter_expr = old_niter;
+    }
 
   return;
 
@@ -2306,7 +2468,7 @@ zero_iter:
 }
 
 /* Checks whether E is a simple exit from LOOP and stores its description
-   into DESC.  TODO Should replace cfgloopanal.c:simple_loop_exit_p.  */
+   into DESC.  */
 
 static void
 check_simple_exit (struct loop *loop, edge e, struct niter_desc *desc)
@@ -2338,7 +2500,7 @@ check_simple_exit (struct loop *loop, edge e, struct niter_desc *desc)
   desc->in_edge = ei;
 
   /* Test whether the condition is suitable.  */
-  if (!(condition = get_condition (BB_END (ei->src), &at, false)))
+  if (!(condition = get_condition (BB_END (ei->src), &at, false, false)))
     return;
 
   if (ei->flags & EDGE_FALLTHRU)
@@ -2353,8 +2515,7 @@ check_simple_exit (struct loop *loop, edge e, struct niter_desc *desc)
   iv_number_of_iterations (loop, at, condition, desc);
 }
 
-/* Finds a simple exit of LOOP and stores its description into DESC.
-   TODO Should replace cfgloopanal.c:simple_loop_p.  */
+/* Finds a simple exit of LOOP and stores its description into DESC.  */
 
 void
 find_simple_exit (struct loop *loop, struct niter_desc *desc)
@@ -2389,43 +2550,43 @@ find_simple_exit (struct loop *loop, struct niter_desc *desc)
        }
     }
 
-  if (rtl_dump_file)
+  if (dump_file)
     {
       if (desc->simple_p)
        {
-         fprintf (rtl_dump_file, "Loop %d is simple:\n", loop->num);
-         fprintf (rtl_dump_file, "  simple exit %d -> %d\n",
+         fprintf (dump_file, "Loop %d is simple:\n", loop->num);
+         fprintf (dump_file, "  simple exit %d -> %d\n",
                   desc->out_edge->src->index,
                   desc->out_edge->dest->index);
          if (desc->assumptions)
            {
-             fprintf (rtl_dump_file, "  assumptions: ");
-             print_rtl (rtl_dump_file, desc->assumptions);
-             fprintf (rtl_dump_file, "\n");
+             fprintf (dump_file, "  assumptions: ");
+             print_rtl (dump_file, desc->assumptions);
+             fprintf (dump_file, "\n");
            }
          if (desc->noloop_assumptions)
            {
-             fprintf (rtl_dump_file, "  does not roll if: ");
-             print_rtl (rtl_dump_file, desc->noloop_assumptions);
-             fprintf (rtl_dump_file, "\n");
+             fprintf (dump_file, "  does not roll if: ");
+             print_rtl (dump_file, desc->noloop_assumptions);
+             fprintf (dump_file, "\n");
            }
          if (desc->infinite)
            {
-             fprintf (rtl_dump_file, "  infinite if: ");
-             print_rtl (rtl_dump_file, desc->infinite);
-             fprintf (rtl_dump_file, "\n");
+             fprintf (dump_file, "  infinite if: ");
+             print_rtl (dump_file, desc->infinite);
+             fprintf (dump_file, "\n");
            }
 
-         fprintf (rtl_dump_file, "  number of iterations: ");
-         print_rtl (rtl_dump_file, desc->niter_expr);
-         fprintf (rtl_dump_file, "\n");
+         fprintf (dump_file, "  number of iterations: ");
+         print_rtl (dump_file, desc->niter_expr);
+         fprintf (dump_file, "\n");
 
-         fprintf (rtl_dump_file, "  upper bound: ");
-         fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC, desc->niter_max);
-         fprintf (rtl_dump_file, "\n");
+         fprintf (dump_file, "  upper bound: ");
+         fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, desc->niter_max);
+         fprintf (dump_file, "\n");
        }
       else
-       fprintf (rtl_dump_file, "Loop %d is not simple.\n", loop->num);
+       fprintf (dump_file, "Loop %d is not simple.\n", loop->num);
     }
 
   free (body);