OSDN Git Service

2009-09-01 Sebastian Pop <sebastian.pop@amd.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-scalar-evolution.c
index 02a4eed..219ef5c 100644 (file)
@@ -1492,18 +1492,29 @@ analyze_evolution_in_loop (gimple loop_phi_node,
       bb = gimple_phi_arg_edge (loop_phi_node, i)->src;
       if (!flow_bb_inside_loop_p (loop, bb))
        continue;
-      
+
       if (TREE_CODE (arg) == SSA_NAME)
        {
+         bool val = false;
+
          ssa_chain = SSA_NAME_DEF_STMT (arg);
 
          /* Pass in the initial condition to the follow edge function.  */
          ev_fn = init_cond;
          res = follow_ssa_edge (loop, ssa_chain, loop_phi_node, &ev_fn, 0);
+
+         /* If ev_fn has no evolution in the inner loop, and the
+            init_cond is not equal to ev_fn, then we have an
+            ambiguity between two possible values, as we cannot know
+            the number of iterations at this point.  */
+         if (TREE_CODE (ev_fn) != POLYNOMIAL_CHREC
+             && no_evolution_in_loop_p (ev_fn, loop->num, &val) && val
+             && !operand_equal_p (init_cond, ev_fn, 0))
+           ev_fn = chrec_dont_know;
        }
       else
        res = t_false;
-             
+
       /* When it is impossible to go back on the same
         loop_phi_node by following the ssa edges, the
         evolution is represented by a peeled chrec, i.e. the
@@ -2098,6 +2109,148 @@ loop_closed_phi_def (tree var)
   return NULL_TREE;
 }
 
+static tree instantiate_scev_1 (basic_block, struct loop *, tree, bool,
+                               htab_t, int);
+
+/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
+   and EVOLUTION_LOOP, that were left under a symbolic form.
+
+   CHREC is an SSA_NAME to be instantiated.
+
+   CACHE is the cache of already instantiated values.
+
+   FOLD_CONVERSIONS should be set to true when the conversions that
+   may wrap in signed/pointer type are folded, as long as the value of
+   the chrec is preserved.
+
+   SIZE_EXPR is used for computing the size of the expression to be
+   instantiated, and to stop if it exceeds some limit.  */
+
+static tree
+instantiate_scev_name (basic_block instantiate_below,
+                      struct loop *evolution_loop, tree chrec,
+                      bool fold_conversions, htab_t cache, int size_expr)
+{
+  tree res;
+  struct loop *def_loop;
+  basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (chrec));
+
+  /* A parameter (or loop invariant and we do not want to include
+     evolutions in outer loops), nothing to do.  */
+  if (!def_bb
+      || loop_depth (def_bb->loop_father) == 0
+      || dominated_by_p (CDI_DOMINATORS, instantiate_below, def_bb))
+    return chrec;
+
+  /* We cache the value of instantiated variable to avoid exponential
+     time complexity due to reevaluations.  We also store the convenient
+     value in the cache in order to prevent infinite recursion -- we do
+     not want to instantiate the SSA_NAME if it is in a mixer
+     structure.  This is used for avoiding the instantiation of
+     recursively defined functions, such as:
+
+     | a_2 -> {0, +, 1, +, a_2}_1  */
+
+  res = get_instantiated_value (cache, instantiate_below, chrec);
+  if (res)
+    return res;
+
+  res = chrec_dont_know;
+  set_instantiated_value (cache, instantiate_below, chrec, res);
+
+  def_loop = find_common_loop (evolution_loop, def_bb->loop_father);
+
+  /* If the analysis yields a parametric chrec, instantiate the
+     result again.  */
+  res = analyze_scalar_evolution (def_loop, chrec);
+
+  /* Don't instantiate loop-closed-ssa phi nodes.  */
+  if (TREE_CODE (res) == SSA_NAME
+      && (loop_containing_stmt (SSA_NAME_DEF_STMT (res)) == NULL
+         || (loop_depth (loop_containing_stmt (SSA_NAME_DEF_STMT (res)))
+             > loop_depth (def_loop))))
+    {
+      if (res == chrec)
+       res = loop_closed_phi_def (chrec);
+      else
+       res = chrec;
+
+      if (res == NULL_TREE
+         || !dominated_by_p (CDI_DOMINATORS, instantiate_below,
+                             gimple_bb (SSA_NAME_DEF_STMT (res))))
+       res = chrec_dont_know;
+    }
+
+  else if (res != chrec_dont_know)
+    res = instantiate_scev_1 (instantiate_below, evolution_loop, res,
+                             fold_conversions, cache, size_expr);
+
+  /* Store the correct value to the cache.  */
+  set_instantiated_value (cache, instantiate_below, chrec, res);
+  return res;
+
+}
+
+/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
+   and EVOLUTION_LOOP, that were left under a symbolic form.
+
+   CHREC is a binary expression to be instantiated.
+
+   CACHE is the cache of already instantiated values.
+
+   FOLD_CONVERSIONS should be set to true when the conversions that
+   may wrap in signed/pointer type are folded, as long as the value of
+   the chrec is preserved.
+
+   SIZE_EXPR is used for computing the size of the expression to be
+   instantiated, and to stop if it exceeds some limit.  */
+
+static tree
+instantiate_scev_binary (basic_block instantiate_below,
+                        struct loop *evolution_loop, tree chrec,
+                        bool fold_conversions, htab_t cache, int size_expr)
+{
+  tree op1;
+  tree op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
+                                TREE_OPERAND (chrec, 0), fold_conversions, cache,
+                                size_expr);
+  if (op0 == chrec_dont_know)
+    return chrec_dont_know;
+
+  op1 = instantiate_scev_1 (instantiate_below, evolution_loop,
+                           TREE_OPERAND (chrec, 1), fold_conversions, cache,
+                           size_expr);
+  if (op1 == chrec_dont_know)
+    return chrec_dont_know;
+
+  if (TREE_OPERAND (chrec, 0) != op0
+      || TREE_OPERAND (chrec, 1) != op1)
+    {
+      tree type = chrec_type (chrec);
+
+      op0 = chrec_convert (type, op0, NULL);
+      op1 = chrec_convert_rhs (type, op1, NULL);
+
+      switch (TREE_CODE (chrec))
+       {
+       case POINTER_PLUS_EXPR:
+       case PLUS_EXPR:
+         return chrec_fold_plus (type, op0, op1);
+
+       case MINUS_EXPR:
+         return chrec_fold_minus (type, op0, op1);
+
+       case MULT_EXPR:
+         return chrec_fold_multiply (type, op0, op1);
+
+       default:
+         gcc_unreachable ();
+       }
+    }
+
+  return chrec;
+}
+
 /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
    and EVOLUTION_LOOP, that were left under a symbolic form.  
 
@@ -2117,9 +2270,7 @@ instantiate_scev_1 (basic_block instantiate_below,
                    struct loop *evolution_loop, tree chrec,
                    bool fold_conversions, htab_t cache, int size_expr)
 {
-  tree res, op0, op1, op2;
-  basic_block def_bb;
-  struct loop *def_loop;
+  tree op0, op1, op2;
   tree type = chrec_type (chrec);
 
   /* Give up if the expression is larger than the MAX that we allow.  */
@@ -2133,61 +2284,8 @@ instantiate_scev_1 (basic_block instantiate_below,
   switch (TREE_CODE (chrec))
     {
     case SSA_NAME:
-      def_bb = gimple_bb (SSA_NAME_DEF_STMT (chrec));
-
-      /* A parameter (or loop invariant and we do not want to include
-        evolutions in outer loops), nothing to do.  */
-      if (!def_bb
-         || loop_depth (def_bb->loop_father) == 0
-         || dominated_by_p (CDI_DOMINATORS, instantiate_below, def_bb))
-       return chrec;
-
-      /* We cache the value of instantiated variable to avoid exponential
-        time complexity due to reevaluations.  We also store the convenient
-        value in the cache in order to prevent infinite recursion -- we do
-        not want to instantiate the SSA_NAME if it is in a mixer
-        structure.  This is used for avoiding the instantiation of
-        recursively defined functions, such as: 
-
-        | a_2 -> {0, +, 1, +, a_2}_1  */
-
-      res = get_instantiated_value (cache, instantiate_below, chrec);
-      if (res)
-       return res;
-
-      res = chrec_dont_know;
-      set_instantiated_value (cache, instantiate_below, chrec, res);
-
-      def_loop = find_common_loop (evolution_loop, def_bb->loop_father);
-
-      /* If the analysis yields a parametric chrec, instantiate the
-        result again.  */
-      res = analyze_scalar_evolution (def_loop, chrec);
-
-      /* Don't instantiate loop-closed-ssa phi nodes.  */
-      if (TREE_CODE (res) == SSA_NAME
-         && (loop_containing_stmt (SSA_NAME_DEF_STMT (res)) == NULL
-             || (loop_depth (loop_containing_stmt (SSA_NAME_DEF_STMT (res)))
-                 > loop_depth (def_loop))))
-       {
-         if (res == chrec)
-           res = loop_closed_phi_def (chrec);
-         else
-           res = chrec;
-
-         if (res == NULL_TREE
-             || !dominated_by_p (CDI_DOMINATORS, instantiate_below,
-                                 gimple_bb (SSA_NAME_DEF_STMT (res))))
-           res = chrec_dont_know;
-       }
-
-      else if (res != chrec_dont_know)
-       res = instantiate_scev_1 (instantiate_below, evolution_loop, res,
-                                 fold_conversions, cache, size_expr);
-
-      /* Store the correct value to the cache.  */
-      set_instantiated_value (cache, instantiate_below, chrec, res);
-      return res;
+      return instantiate_scev_name (instantiate_below, evolution_loop, chrec,
+                                   fold_conversions, cache, size_expr);
 
     case POLYNOMIAL_CHREC:
       op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
@@ -2212,70 +2310,10 @@ instantiate_scev_1 (basic_block instantiate_below,
 
     case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
-      op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
-                               TREE_OPERAND (chrec, 0), fold_conversions, cache,
-                               size_expr);
-      if (op0 == chrec_dont_know)
-       return chrec_dont_know;
-
-      op1 = instantiate_scev_1 (instantiate_below, evolution_loop,
-                               TREE_OPERAND (chrec, 1), fold_conversions, cache,
-                               size_expr);
-      if (op1 == chrec_dont_know)
-       return chrec_dont_know;
-
-      if (TREE_OPERAND (chrec, 0) != op0
-         || TREE_OPERAND (chrec, 1) != op1)
-       {
-         op0 = chrec_convert (type, op0, NULL);
-         op1 = chrec_convert_rhs (type, op1, NULL);
-         chrec = chrec_fold_plus (type, op0, op1);
-       }
-      return chrec;
-
     case MINUS_EXPR:
-      op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
-                               TREE_OPERAND (chrec, 0), fold_conversions, cache,
-                               size_expr);
-      if (op0 == chrec_dont_know)
-       return chrec_dont_know;
-
-      op1 = instantiate_scev_1 (instantiate_below, evolution_loop,
-                               TREE_OPERAND (chrec, 1),
-                               fold_conversions, cache, size_expr);
-      if (op1 == chrec_dont_know)
-       return chrec_dont_know;
-
-      if (TREE_OPERAND (chrec, 0) != op0
-         || TREE_OPERAND (chrec, 1) != op1)
-       {
-         op0 = chrec_convert (type, op0, NULL);
-         op1 = chrec_convert (type, op1, NULL);
-         chrec = chrec_fold_minus (type, op0, op1);
-       }
-      return chrec;
-
     case MULT_EXPR:
-      op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
-                               TREE_OPERAND (chrec, 0),
-                               fold_conversions, cache, size_expr);
-      if (op0 == chrec_dont_know)
-       return chrec_dont_know;
-
-      op1 = instantiate_scev_1 (instantiate_below, evolution_loop,
-                               TREE_OPERAND (chrec, 1),
-                               fold_conversions, cache, size_expr);
-      if (op1 == chrec_dont_know)
-       return chrec_dont_know;
-
-      if (TREE_OPERAND (chrec, 0) != op0
-         || TREE_OPERAND (chrec, 1) != op1)
-       {
-         op0 = chrec_convert (type, op0, NULL);
-         op1 = chrec_convert (type, op1, NULL);
-         chrec = chrec_fold_multiply (type, op0, op1);
-       }
-      return chrec;
+      return instantiate_scev_binary (instantiate_below, evolution_loop, chrec,
+                                     fold_conversions, cache, size_expr);
 
     CASE_CONVERT:
       op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
@@ -2325,7 +2363,7 @@ instantiate_scev_1 (basic_block instantiate_below,
 
     case SCEV_KNOWN:
       return chrec_known;
-                                     
+
     default:
       break;
     }