OSDN Git Service

2009-07-07 Manuel López-Ibáñez <manu@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / loop-iv.c
index 123e37c..44ded9d 100644 (file)
@@ -1336,25 +1336,29 @@ simple_rhs_p (rtx rhs)
     {
     case PLUS:
     case MINUS:
+    case AND:
       op0 = XEXP (rhs, 0);
       op1 = XEXP (rhs, 1);
-      /* Allow reg + const and reg + reg.  */
+      /* Allow reg OP const and reg OP reg.  */
       if (!(REG_P (op0) && !HARD_REGISTER_P (op0))
-         && !CONSTANT_P (op0))
+         && !function_invariant_p (op0))
        return false;
       if (!(REG_P (op1) && !HARD_REGISTER_P (op1))
-         && !CONSTANT_P (op1))
+         && !function_invariant_p (op1))
        return false;
 
       return true;
 
     case ASHIFT:
+    case ASHIFTRT:
+    case LSHIFTRT:
+    case MULT:
       op0 = XEXP (rhs, 0);
       op1 = XEXP (rhs, 1);
-      /* Allow reg << const.  */
+      /* Allow reg OP const.  */
       if (!(REG_P (op0) && !HARD_REGISTER_P (op0)))
        return false;
-      if (!CONSTANT_P (op1))
+      if (!function_invariant_p (op1))
        return false;
 
       return true;
@@ -1364,6 +1368,57 @@ simple_rhs_p (rtx rhs)
     }
 }
 
+/* If REG has a single definition, replace it with its known value in EXPR.
+   Callback for for_each_rtx.  */
+
+static int
+replace_single_def_regs (rtx *reg, void *expr1)
+{
+  unsigned regno;
+  df_ref adef;
+  rtx set, src;
+  rtx *expr = (rtx *)expr1;
+
+  if (!REG_P (*reg))
+    return 0;
+
+  regno = REGNO (*reg);
+  for (;;)
+    {
+      rtx note;
+      adef = DF_REG_DEF_CHAIN (regno);
+      if (adef == NULL || DF_REF_NEXT_REG (adef) != NULL
+           || DF_REF_IS_ARTIFICIAL (adef))
+       return -1;
+
+      set = single_set (DF_REF_INSN (adef));
+      if (set == NULL || !REG_P (SET_DEST (set))
+         || REGNO (SET_DEST (set)) != regno)
+       return -1;
+
+      note = find_reg_equal_equiv_note (DF_REF_INSN (adef));
+
+      if (note && function_invariant_p (XEXP (note, 0)))
+       {
+         src = XEXP (note, 0);
+         break;
+       }
+      src = SET_SRC (set);
+
+      if (REG_P (src))
+       {
+         regno = REGNO (src);
+         continue;
+       }
+      break;
+    }
+  if (!function_invariant_p (src))
+    return -1;
+
+  *expr = simplify_replace_rtx (*expr, *reg, src);
+  return 1;
+}
+
 /* A subroutine of simplify_using_initial_values, this function examines INSN
    to see if it contains a suitable set that we can use to make a replacement.
    If it is suitable, return true and set DEST and SRC to the lhs and rhs of
@@ -1396,6 +1451,20 @@ suitable_set_for_replacement (rtx insn, rtx *dest, rtx *src)
   return true;
 }
 
+/* Using the data returned by suitable_set_for_replacement, replace DEST
+   with SRC in *EXPR and return the new expression.  Also call
+   replace_single_def_regs if the replacement changed something.  */
+static void
+replace_in_expr (rtx *expr, rtx dest, rtx src)
+{
+  rtx old = *expr;
+  *expr = simplify_replace_rtx (*expr, dest, src);
+  if (old == *expr)
+    return;
+  while (for_each_rtx (expr, replace_single_def_regs, expr) != 0)
+    continue;
+}
+
 /* Checks whether A implies B.  */
 
 static bool
@@ -1498,11 +1567,11 @@ implies_p (rtx a, rtx b)
 
   /* A != N is equivalent to A - (N + 1) <u -1.  */
   if (GET_CODE (a) == NE
-      && GET_CODE (op1) == CONST_INT
+      && CONST_INT_P (op1)
       && GET_CODE (b) == LTU
       && opb1 == constm1_rtx
       && GET_CODE (opb0) == PLUS
-      && GET_CODE (XEXP (opb0, 1)) == CONST_INT
+      && CONST_INT_P (XEXP (opb0, 1))
       /* Avoid overflows.  */
       && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (opb0, 1))
          != ((unsigned HOST_WIDE_INT)1
@@ -1512,12 +1581,12 @@ implies_p (rtx a, rtx b)
 
   /* Likewise, A != N implies A - N > 0.  */
   if (GET_CODE (a) == NE
-      && GET_CODE (op1) == CONST_INT)
+      && CONST_INT_P (op1))
     {
       if (GET_CODE (b) == GTU
          && GET_CODE (opb0) == PLUS
          && opb1 == const0_rtx
-         && GET_CODE (XEXP (opb0, 1)) == CONST_INT
+         && CONST_INT_P (XEXP (opb0, 1))
          /* Avoid overflows.  */
          && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (opb0, 1))
              != ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)))
@@ -1526,7 +1595,7 @@ implies_p (rtx a, rtx b)
       if (GET_CODE (b) == GEU
          && GET_CODE (opb0) == PLUS
          && opb1 == const1_rtx
-         && GET_CODE (XEXP (opb0, 1)) == CONST_INT
+         && CONST_INT_P (XEXP (opb0, 1))
          /* Avoid overflows.  */
          && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (opb0, 1))
              != ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)))
@@ -1536,11 +1605,11 @@ implies_p (rtx a, rtx b)
 
   /* A >s X, where X is positive, implies A <u Y, if Y is negative.  */
   if ((GET_CODE (a) == GT || GET_CODE (a) == GE)
-      && GET_CODE (op1) == CONST_INT
+      && CONST_INT_P (op1)
       && ((GET_CODE (a) == GT && op1 == constm1_rtx)
          || INTVAL (op1) >= 0)
       && GET_CODE (b) == LTU
-      && GET_CODE (opb1) == CONST_INT
+      && CONST_INT_P (opb1)
       && rtx_equal_p (op0, opb0))
     return INTVAL (opb1) < 0;
 
@@ -1579,7 +1648,7 @@ canon_condition (rtx cond)
     mode = GET_MODE (op1);
   gcc_assert (mode != VOIDmode);
 
-  if (GET_CODE (op1) == CONST_INT
+  if (CONST_INT_P (op1)
       && GET_MODE_CLASS (mode) != MODE_CC
       && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
     {
@@ -1814,6 +1883,12 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
 
   gcc_assert (op == UNKNOWN);
 
+  for (;;)
+    if (for_each_rtx (expr, replace_single_def_regs, expr) == 0)
+      break;
+  if (CONSTANT_P (*expr))
+    return;
+
   e = loop_preheader_edge (loop);
   if (e->src == ENTRY_BLOCK_PTR)
     return;
@@ -1877,7 +1952,7 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
            {
              rtx *pnote, *pnote_next;
 
-             *expr = simplify_replace_rtx (*expr, dest, src);
+             replace_in_expr (expr, dest, src);
              if (CONSTANT_P (*expr))
                goto out;
 
@@ -1887,8 +1962,8 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
                  rtx old_cond = XEXP (note, 0);
 
                  pnote_next = &XEXP (note, 1);
-                 XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), dest,
-                                                        src);
+                 replace_in_expr (&XEXP (note, 0), dest, src);
+
                  /* We can no longer use a condition that has been simplified
                     to a constant, and simplify_using_condition will abort if
                     we try.  */
@@ -2114,17 +2189,20 @@ canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1,
   return true;
 }
 
-/* Tries to estimate the maximum number of iterations.  */
+/* Tries to estimate the maximum number of iterations in LOOP, and store the
+   result in DESC.  This function is called from iv_number_of_iterations with
+   a number of fields in DESC already filled in.  OLD_NITER is the original
+   expression for the number of iterations, before we tried to simplify it.  */
 
 static unsigned HOST_WIDEST_INT
-determine_max_iter (struct loop *loop, struct niter_desc *desc)
+determine_max_iter (struct loop *loop, struct niter_desc *desc, rtx old_niter)
 {
   rtx niter = desc->niter_expr;
   rtx mmin, mmax, cmp;
   unsigned HOST_WIDEST_INT nmax, inc;
 
   if (GET_CODE (niter) == AND
-      && GET_CODE (XEXP (niter, 0)) == CONST_INT)
+      && CONST_INT_P (XEXP (niter, 0)))
     {
       nmax = INTVAL (XEXP (niter, 0));
       if (!(nmax & (nmax + 1)))
@@ -2139,7 +2217,7 @@ determine_max_iter (struct loop *loop, struct niter_desc *desc)
 
   if (GET_CODE (niter) == UDIV)
     {
-      if (GET_CODE (XEXP (niter, 1)) != CONST_INT)
+      if (!CONST_INT_P (XEXP (niter, 1)))
        {
          desc->niter_max = nmax;
          return nmax;
@@ -2152,7 +2230,8 @@ determine_max_iter (struct loop *loop, struct niter_desc *desc)
 
   /* We could use a binary search here, but for now improving the upper
      bound by just one eliminates one important corner case.  */
-  cmp = gen_rtx_fmt_ee (desc->signed_p ? LT : LTU, VOIDmode, niter, mmax);
+  cmp = simplify_gen_relational (desc->signed_p ? LT : LTU, VOIDmode,
+                                desc->mode, old_niter, mmax);
   simplify_using_initial_values (loop, UNKNOWN, &cmp);
   if (cmp == const_true_rtx)
     {
@@ -2266,7 +2345,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
   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)
+  if (!CONST_INT_P (iv0.step) || !CONST_INT_P (iv1.step))
     goto fail;
 
   /* We can take care of the case of two induction variables chasing each other
@@ -2397,7 +2476,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
       may_xform = const0_rtx;
       may_not_xform = const_true_rtx;
 
-      if (GET_CODE (delta) == CONST_INT)
+      if (CONST_INT_P (delta))
        {
          if (was_sharp && INTVAL (delta) == INTVAL (step) - 1)
            {
@@ -2460,11 +2539,11 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
             number of iterations in this step, so record the information
             here.  */
          inc = INTVAL (iv0.step) - INTVAL (iv1.step);
-         if (GET_CODE (iv1.base) == CONST_INT)
+         if (CONST_INT_P (iv1.base))
            up = INTVAL (iv1.base);
          else
            up = INTVAL (mode_mmax) - inc;
-         down = INTVAL (GET_CODE (iv0.base) == CONST_INT
+         down = INTVAL (CONST_INT_P (iv0.base)
                         ? iv0.base
                         : mode_mmin);
          desc->niter_max = (up - down) / inc + 1;
@@ -2673,7 +2752,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
       && XEXP (desc->noloop_assumptions, 0) == const_true_rtx)
     goto zero_iter;
 
-  if (GET_CODE (desc->niter_expr) == CONST_INT)
+  if (CONST_INT_P (desc->niter_expr))
     {
       unsigned HOST_WIDEST_INT val = INTVAL (desc->niter_expr);
 
@@ -2683,7 +2762,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
   else
     {
       if (!desc->niter_max)
-       desc->niter_max = determine_max_iter (loop, desc);
+       desc->niter_max = determine_max_iter (loop, desc, old_niter);
 
       /* simplify_using_initial_values does a copy propagation on the registers
         in the expression for the number of iterations.  This prolongs life