OSDN Git Service

* ja.po: Update.
[pf3gnuchains/gcc-fork.git] / gcc / tree-chrec.c
index 9711e20..c721d43 100644 (file)
@@ -1,5 +1,5 @@
 /* Chains of recurrences.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Sebastian Pop <pop@cri.ensmp.fr>
 
@@ -27,21 +27,14 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "ggc.h"
-#include "tree.h"
-#include "real.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
 #include "cfgloop.h"
 #include "tree-flow.h"
 #include "tree-chrec.h"
 #include "tree-pass.h"
 #include "params.h"
-#include "flags.h"
 #include "tree-scalar-evolution.h"
 
-\f
-
 /* Extended folder for chrecs.  */
 
 /* Determines whether CST is not a constant evolution.  */
@@ -283,6 +276,10 @@ chrec_fold_plus_1 (enum tree_code code, tree type,
        case POLYNOMIAL_CHREC:
          return chrec_fold_plus_poly_poly (code, type, op0, op1);
 
+       CASE_CONVERT:
+         if (tree_contains_chrecs (op1, NULL))
+           return chrec_dont_know;
+
        default:
          if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
            return build_polynomial_chrec
@@ -296,6 +293,10 @@ chrec_fold_plus_1 (enum tree_code code, tree type,
               CHREC_RIGHT (op0));
        }
 
+    CASE_CONVERT:
+      if (tree_contains_chrecs (op0, NULL))
+       return chrec_dont_know;
+
     default:
       switch (TREE_CODE (op1))
        {
@@ -314,6 +315,10 @@ chrec_fold_plus_1 (enum tree_code code, tree type,
                                    ? build_real (type, dconstm1)
                                    : build_int_cst_type (type, -1)));
 
+       CASE_CONVERT:
+         if (tree_contains_chrecs (op1, NULL))
+           return chrec_dont_know;
+
        default:
          {
            int size = 0;
@@ -393,6 +398,10 @@ chrec_fold_multiply (tree type,
        case POLYNOMIAL_CHREC:
          return chrec_fold_multiply_poly_poly (type, op0, op1);
 
+       CASE_CONVERT:
+         if (tree_contains_chrecs (op1, NULL))
+           return chrec_dont_know;
+
        default:
          if (integer_onep (op1))
            return op0;
@@ -405,6 +414,10 @@ chrec_fold_multiply (tree type,
             chrec_fold_multiply (type, CHREC_RIGHT (op0), op1));
        }
 
+    CASE_CONVERT:
+      if (tree_contains_chrecs (op0, NULL))
+       return chrec_dont_know;
+
     default:
       if (integer_onep (op0))
        return op1;
@@ -420,6 +433,10 @@ chrec_fold_multiply (tree type,
             chrec_fold_multiply (type, CHREC_LEFT (op1), op0),
             chrec_fold_multiply (type, CHREC_RIGHT (op1), op0));
 
+       CASE_CONVERT:
+         if (tree_contains_chrecs (op1, NULL))
+           return chrec_dont_know;
+
        default:
          if (integer_onep (op1))
            return op0;
@@ -576,23 +593,40 @@ chrec_apply (unsigned var,
   if (TREE_CODE (x) == INTEGER_CST && SCALAR_FLOAT_TYPE_P (type))
     x = build_real_from_int_cst (type, x);
 
-  if (evolution_function_is_affine_p (chrec))
+  switch (TREE_CODE (chrec))
     {
-      /* "{a, +, b} (x)"  ->  "a + b*x".  */
-      x = chrec_convert_rhs (type, x, NULL);
-      res = chrec_fold_multiply (TREE_TYPE (x), CHREC_RIGHT (chrec), x);
-      res = chrec_fold_plus (type, CHREC_LEFT (chrec), res);
-    }
+    case POLYNOMIAL_CHREC:
+      if (evolution_function_is_affine_p (chrec))
+       {
+         if (CHREC_VARIABLE (chrec) != var)
+           return build_polynomial_chrec
+             (CHREC_VARIABLE (chrec),
+              chrec_apply (var, CHREC_LEFT (chrec), x),
+              chrec_apply (var, CHREC_RIGHT (chrec), x));
+
+         /* "{a, +, b} (x)"  ->  "a + b*x".  */
+         x = chrec_convert_rhs (type, x, NULL);
+         res = chrec_fold_multiply (TREE_TYPE (x), CHREC_RIGHT (chrec), x);
+         res = chrec_fold_plus (type, CHREC_LEFT (chrec), res);
+       }
+      else if (TREE_CODE (x) == INTEGER_CST
+              && tree_int_cst_sgn (x) == 1)
+       /* testsuite/.../ssa-chrec-38.c.  */
+       res = chrec_evaluate (var, chrec, x, 0);
+      else
+       res = chrec_dont_know;
+      break;
 
-  else if (TREE_CODE (chrec) != POLYNOMIAL_CHREC)
-    res = chrec;
+    CASE_CONVERT:
+      res = chrec_convert (TREE_TYPE (chrec),
+                          chrec_apply (var, TREE_OPERAND (chrec, 0), x),
+                          NULL);
+      break;
 
-  else if (TREE_CODE (x) == INTEGER_CST
-          && tree_int_cst_sgn (x) == 1)
-    /* testsuite/.../ssa-chrec-38.c.  */
-    res = chrec_evaluate (var, chrec, x, 0);
-  else
-    res = chrec_dont_know;
+    default:
+      res = chrec;
+      break;
+    }
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -609,6 +643,23 @@ chrec_apply (unsigned var,
   return res;
 }
 
+/* For a given CHREC and an induction variable map IV_MAP that maps
+   (loop->num, expr) for every loop number of the current_loops an
+   expression, calls chrec_apply when the expression is not NULL.  */
+
+tree
+chrec_apply_map (tree chrec, VEC (tree, heap) *iv_map)
+{
+  int i;
+  tree expr;
+
+  FOR_EACH_VEC_ELT (tree, iv_map, i, expr)
+    if (expr)
+      chrec = chrec_apply (i, chrec, expr);
+
+  return chrec;
+}
+
 /* Replaces the initial condition in CHREC with INIT_COND.  */
 
 tree
@@ -1207,13 +1258,15 @@ convert_affine_scev (struct loop *loop, tree type,
 }
 \f
 
-/* Convert CHREC for the right hand side of a CREC.
+/* Convert CHREC for the right hand side of a CHREC.
    The increment for a pointer type is always sizetype.  */
+
 tree
 chrec_convert_rhs (tree type, tree chrec, gimple at_stmt)
 {
   if (POINTER_TYPE_P (type))
-   type = sizetype;
+    type = sizetype;
+
   return chrec_convert (type, chrec, at_stmt);
 }
 
@@ -1293,6 +1346,8 @@ keep_cast:
   if (use_overflow_semantics
       && (TREE_CODE (chrec) == PLUS_EXPR
          || TREE_CODE (chrec) == MINUS_EXPR)
+      && TREE_CODE (type) == INTEGER_TYPE
+      && TREE_CODE (ct) == INTEGER_TYPE
       && TYPE_PRECISION (type) > TYPE_PRECISION (ct)
       && TYPE_OVERFLOW_UNDEFINED (ct))
     res = fold_build2 (TREE_CODE (chrec), type,
@@ -1372,6 +1427,16 @@ eq_evolutions_p (const_tree chrec0, const_tree chrec1)
       return (CHREC_VARIABLE (chrec0) == CHREC_VARIABLE (chrec1)
              && eq_evolutions_p (CHREC_LEFT (chrec0), CHREC_LEFT (chrec1))
              && eq_evolutions_p (CHREC_RIGHT (chrec0), CHREC_RIGHT (chrec1)));
+
+    case PLUS_EXPR:
+    case MULT_EXPR:
+    case MINUS_EXPR:
+    case POINTER_PLUS_EXPR:
+      return eq_evolutions_p (TREE_OPERAND (chrec0, 0),
+                             TREE_OPERAND (chrec1, 0))
+         && eq_evolutions_p (TREE_OPERAND (chrec0, 1),
+                             TREE_OPERAND (chrec1, 1));
+
     default:
       return false;
     }
@@ -1503,14 +1568,12 @@ evolution_function_right_is_integer_cst (const_tree chrec)
       return true;
 
     case POLYNOMIAL_CHREC:
-      if (!evolution_function_right_is_integer_cst (CHREC_RIGHT (chrec)))
-       return false;
-
-      if (TREE_CODE (CHREC_LEFT (chrec)) == POLYNOMIAL_CHREC
-       && !evolution_function_right_is_integer_cst (CHREC_LEFT (chrec)))
-       return false;
+      return TREE_CODE (CHREC_RIGHT (chrec)) == INTEGER_CST
+       && (TREE_CODE (CHREC_LEFT (chrec)) != POLYNOMIAL_CHREC
+           || evolution_function_right_is_integer_cst (CHREC_LEFT (chrec)));
 
-      return true;
+    CASE_CONVERT:
+      return evolution_function_right_is_integer_cst (TREE_OPERAND (chrec, 0));
 
     default:
       return false;