OSDN Git Service

2004-06-15 Jerry Quinn <jlquinn@optonline.net>
[pf3gnuchains/gcc-fork.git] / gcc / loop-iv.c
index 9c170de..0093743 100644 (file)
@@ -254,7 +254,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))
@@ -603,7 +605,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);
 
@@ -979,7 +983,9 @@ iv_analyze (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);
 
@@ -1203,7 +1209,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)
@@ -1315,7 +1321,7 @@ simplify_using_assignment (rtx insn, rtx *expr, regset altered)
   if (set)
     {
       lhs = SET_DEST (set);
-      if (GET_CODE (lhs) != REG
+      if (!REG_P (lhs)
          || altered_reg_used (&lhs, altered))
        ret = true;
     }
@@ -1337,7 +1343,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 +1362,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 +1385,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 +1517,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
@@ -1696,7 +1744,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,
@@ -1870,11 +1918,11 @@ 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;
 
@@ -1894,7 +1942,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));
@@ -1959,7 +2007,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 +2051,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 +2061,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 +2087,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 +2097,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 +2122,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)
        {
@@ -2094,6 +2147,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 +2159,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 +2171,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 +2191,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 +2257,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 +2276,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 +2300,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 =
@@ -2281,6 +2355,10 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
   simplify_using_initial_values (loop, IOR, &desc->infinite);
   simplify_using_initial_values (loop, NIL, &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)
     {
       unsigned HOST_WIDEST_INT val = INTVAL (desc->niter_expr);
@@ -2306,7 +2384,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)
@@ -2353,8 +2431,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)