OSDN Git Service

PR c++/39786
[pf3gnuchains/gcc-fork.git] / gcc / tree-scalar-evolution.c
index b3990c6..70af0fd 100644 (file)
@@ -466,7 +466,7 @@ loop_phi_node_p (gimple phi)
    EVOLUTION_FN = {i_0, +, 2}_1.
 */
  
-static tree 
+tree
 compute_overall_effect_of_inner_loop (struct loop *loop, tree evolution_fn)
 {
   bool val = false;
@@ -492,7 +492,10 @@ compute_overall_effect_of_inner_loop (struct loop *loop, tree evolution_fn)
              /* evolution_fn is the evolution function in LOOP.  Get
                 its value in the nb_iter-th iteration.  */
              res = chrec_apply (inner_loop->num, evolution_fn, nb_iter);
-             
+
+             if (chrec_contains_symbols_defined_in_loop (res, loop->num))
+               res = instantiate_parameters (loop, res);
+
              /* Continue the computation until ending on a parent of LOOP.  */
              return compute_overall_effect_of_inner_loop (loop, res);
            }
@@ -1141,11 +1144,10 @@ static t_bool
 follow_ssa_edge_expr (struct loop *loop, gimple at_stmt, tree expr, 
                      gimple halting_phi, tree *evolution_of_loop, int limit)
 {
-  t_bool res = t_false;
-  tree rhs0, rhs1;
-  tree type = TREE_TYPE (expr);
-  enum tree_code code;
-  
+  enum tree_code code = TREE_CODE (expr);
+  tree type = TREE_TYPE (expr), rhs0, rhs1;
+  t_bool res;
+
   /* The EXPR is one of the following cases:
      - an SSA_NAME, 
      - an INTEGER_CST,
@@ -1154,10 +1156,10 @@ follow_ssa_edge_expr (struct loop *loop, gimple at_stmt, tree expr,
      - a MINUS_EXPR,
      - an ASSERT_EXPR,
      - other cases are not yet handled.  */
-  code = TREE_CODE (expr);
+
   switch (code)
     {
-    case NOP_EXPR:
+    CASE_CONVERT:
       /* This assignment is under the form "a_1 = (cast) rhs.  */
       res = follow_ssa_edge_expr (loop, at_stmt, TREE_OPERAND (expr, 0),
                                  halting_phi, evolution_of_loop, limit);
@@ -1168,43 +1170,42 @@ follow_ssa_edge_expr (struct loop *loop, gimple at_stmt, tree expr,
       /* This assignment is under the form "a_1 = 7".  */
       res = t_false;
       break;
-      
+
     case SSA_NAME:
       /* This assignment is under the form: "a_1 = b_2".  */
       res = follow_ssa_edge 
        (loop, SSA_NAME_DEF_STMT (expr), halting_phi, evolution_of_loop, limit);
       break;
-      
+
     case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
     case MINUS_EXPR:
       /* This case is under the form "rhs0 +- rhs1".  */
       rhs0 = TREE_OPERAND (expr, 0);
       rhs1 = TREE_OPERAND (expr, 1);
-      STRIP_TYPE_NOPS (rhs0);
-      STRIP_TYPE_NOPS (rhs1);
-      return follow_ssa_edge_binary (loop, at_stmt, type, rhs0, code, rhs1,
-                                    halting_phi, evolution_of_loop, limit);
+      type = TREE_TYPE (rhs0);
+      STRIP_USELESS_TYPE_CONVERSION (rhs0);
+      STRIP_USELESS_TYPE_CONVERSION (rhs1);
+      res = follow_ssa_edge_binary (loop, at_stmt, type, rhs0, code, rhs1,
+                                   halting_phi, evolution_of_loop, limit);
+      break;
 
     case ASSERT_EXPR:
-      {
-       /* This assignment is of the form: "a_1 = ASSERT_EXPR <a_2, ...>"
-          It must be handled as a copy assignment of the form a_1 = a_2.  */
-       tree op0 = ASSERT_EXPR_VAR (expr);
-       if (TREE_CODE (op0) == SSA_NAME)
-         res = follow_ssa_edge (loop, SSA_NAME_DEF_STMT (op0),
-                                halting_phi, evolution_of_loop, limit);
-       else
-         res = t_false;
-       break;
-      }
-
+      /* This assignment is of the form: "a_1 = ASSERT_EXPR <a_2, ...>"
+        It must be handled as a copy assignment of the form a_1 = a_2.  */
+      rhs0 = ASSERT_EXPR_VAR (expr);
+      if (TREE_CODE (rhs0) == SSA_NAME)
+       res = follow_ssa_edge (loop, SSA_NAME_DEF_STMT (rhs0),
+                              halting_phi, evolution_of_loop, limit);
+      else
+       res = t_false;
+      break;
 
     default:
       res = t_false;
       break;
     }
-  
+
   return res;
 }
 
@@ -1215,34 +1216,39 @@ static t_bool
 follow_ssa_edge_in_rhs (struct loop *loop, gimple stmt,
                        gimple halting_phi, tree *evolution_of_loop, int limit)
 {
-  tree type = TREE_TYPE (gimple_assign_lhs (stmt));
   enum tree_code code = gimple_assign_rhs_code (stmt);
+  tree type = gimple_expr_type (stmt), rhs1, rhs2;
+  t_bool res;
 
-  switch (get_gimple_rhs_class (code))
+  switch (code)
     {
-    case GIMPLE_BINARY_RHS:
-      return follow_ssa_edge_binary (loop, stmt, type,
-                                    gimple_assign_rhs1 (stmt), code,
-                                    gimple_assign_rhs2 (stmt),
-                                    halting_phi, evolution_of_loop, limit);
-    case GIMPLE_SINGLE_RHS:
-      return follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt),
-                                  halting_phi, evolution_of_loop, limit);
-    case GIMPLE_UNARY_RHS:
-      if (code == NOP_EXPR)
-       {
-         /* This assignment is under the form "a_1 = (cast) rhs.  */
-         t_bool res
-           = follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt),
+    CASE_CONVERT:
+      /* This assignment is under the form "a_1 = (cast) rhs.  */
+      res = follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt),
+                                 halting_phi, evolution_of_loop, limit);
+      *evolution_of_loop = chrec_convert (type, *evolution_of_loop, stmt);
+      break;
+
+    case POINTER_PLUS_EXPR:
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+      rhs1 = gimple_assign_rhs1 (stmt);
+      rhs2 = gimple_assign_rhs2 (stmt);
+      type = TREE_TYPE (rhs1);
+      res = follow_ssa_edge_binary (loop, stmt, type, rhs1, code, rhs2,
                                    halting_phi, evolution_of_loop, limit);
-         *evolution_of_loop = chrec_convert (type, *evolution_of_loop, stmt);
-         return res;
-       }
-      /* FALLTHRU */
+      break;
 
     default:
-      return t_false;
+      if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS)
+       res = follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt),
+                                   halting_phi, evolution_of_loop, limit);
+      else
+       res = t_false;
+      break;
     }
+
+  return res;
 }
 
 /* Checks whether the I-th argument of a PHI comes from a backedge.  */
@@ -1486,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
@@ -1887,18 +1904,16 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res)
   return res;
 }
 
-/* Entry point for the scalar evolution analyzer.
-   Analyzes and returns the scalar evolution of the ssa_name VAR.
-   LOOP_NB is the identifier number of the loop in which the variable
-   is used.
+/* Analyzes and returns the scalar evolution of the ssa_name VAR in
+   LOOP.  LOOP is the loop in which the variable is used.
    
    Example of use: having a pointer VAR to a SSA_NAME node, STMT a
    pointer to the statement that uses this variable, in order to
    determine the evolution function of the variable, use the following
    calls:
    
-   unsigned loop_nb = loop_containing_stmt (stmt)->num;
-   tree chrec_with_symbols = analyze_scalar_evolution (loop_nb, var);
+   loop_p loop = loop_containing_stmt (stmt);
+   tree chrec_with_symbols = analyze_scalar_evolution (loop, var);
    tree chrec_instantiated = instantiate_parameters (loop, chrec_with_symbols);
 */
 
@@ -2171,7 +2186,9 @@ instantiate_scev_1 (basic_block instantiate_below,
          else
            res = chrec;
 
-         if (res == NULL_TREE)
+         if (res == NULL_TREE
+             || !dominated_by_p (CDI_DOMINATORS, instantiate_below,
+                                 gimple_bb (SSA_NAME_DEF_STMT (res))))
            res = chrec_dont_know;
        }