OSDN Git Service

2009-11-04 Kenneth Zadeck <zadeck@naturalbridge.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-vrp.c
index 237245e..5adc0da 100644 (file)
@@ -4651,6 +4651,9 @@ find_assert_locations_1 (basic_block bb, sbitmap live)
 
       stmt = gsi_stmt (si);
 
+      if (is_gimple_debug (stmt))
+       continue;
+
       /* See if we can derive an assertion for any of STMT's operands.  */
       FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
        {
@@ -5675,7 +5678,7 @@ vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0,
    based on undefined signed overflow, issue a warning if
    appropriate.  */
 
-tree
+static tree
 vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, gimple stmt)
 {
   bool sop;
@@ -6745,13 +6748,9 @@ test_for_singularity (enum tree_code cond_code, tree op0,
      value range information we have for op0.  */
   if (min && max)
     {
-      if (compare_values (vr->min, min) == -1)
-       min = min;
-      else
+      if (compare_values (vr->min, min) == 1)
        min = vr->min;
-      if (compare_values (vr->max, max) == 1)
-       max = max;
-      else
+      if (compare_values (vr->max, max) == -1)
        max = vr->max;
 
       /* If the new min/max values have converged to a single value,
@@ -6942,7 +6941,7 @@ simplify_switch_using_ranges (gimple stmt)
 
 /* Simplify STMT using ranges if possible.  */
 
-bool
+static bool
 simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
 {
   gimple stmt = gsi_stmt (*gsi);
@@ -6995,6 +6994,78 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
   return false;
 }
 
+/* If the statement pointed by SI has a predicate whose value can be
+   computed using the value range information computed by VRP, compute
+   its value and return true.  Otherwise, return false.  */
+
+static bool
+fold_predicate_in (gimple_stmt_iterator *si)
+{
+  bool assignment_p = false;
+  tree val;
+  gimple stmt = gsi_stmt (*si);
+
+  if (is_gimple_assign (stmt)
+      && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison)
+    {
+      assignment_p = true;
+      val = vrp_evaluate_conditional (gimple_assign_rhs_code (stmt),
+                                     gimple_assign_rhs1 (stmt),
+                                     gimple_assign_rhs2 (stmt),
+                                     stmt);
+    }
+  else if (gimple_code (stmt) == GIMPLE_COND)
+    val = vrp_evaluate_conditional (gimple_cond_code (stmt),
+                                   gimple_cond_lhs (stmt),
+                                   gimple_cond_rhs (stmt),
+                                   stmt);
+  else
+    return false;
+
+  if (val)
+    {
+      if (assignment_p)
+        val = fold_convert (gimple_expr_type (stmt), val);
+      
+      if (dump_file)
+       {
+         fprintf (dump_file, "Folding predicate ");
+         print_gimple_expr (dump_file, stmt, 0, 0);
+         fprintf (dump_file, " to ");
+         print_generic_expr (dump_file, val, 0);
+         fprintf (dump_file, "\n");
+       }
+
+      if (is_gimple_assign (stmt))
+       gimple_assign_set_rhs_from_tree (si, val);
+      else
+       {
+         gcc_assert (gimple_code (stmt) == GIMPLE_COND);
+         if (integer_zerop (val))
+           gimple_cond_make_false (stmt);
+         else if (integer_onep (val))
+           gimple_cond_make_true (stmt);
+         else
+           gcc_unreachable ();
+       }
+
+      return true;
+    }
+
+  return false;
+}
+
+/* Callback for substitute_and_fold folding the stmt at *SI.  */
+
+static bool
+vrp_fold_stmt (gimple_stmt_iterator *si)
+{
+  if (fold_predicate_in (si))
+    return true;
+
+  return simplify_stmt_using_ranges (si);
+}
+
 /* Stack of dest,src equivalency pairs that need to be restored after
    each attempt to thread a block's incoming edge to an outgoing edge. 
 
@@ -7162,7 +7233,7 @@ vrp_finalize (void)
     }
 
   /* We may have ended with ranges that have exactly one value.  Those
-     values can be substituted as any other copy/const propagated
+     values can be substituted as any other const propagated
      value using substitute_and_fold.  */
   single_val_range = XCNEWVEC (prop_value_t, num_ssa_names);
 
@@ -7170,7 +7241,8 @@ vrp_finalize (void)
   for (i = 0; i < num_ssa_names; i++)
     if (vr_value[i]
        && vr_value[i]->type == VR_RANGE
-       && vr_value[i]->min == vr_value[i]->max)
+       && vr_value[i]->min == vr_value[i]->max
+       && is_gimple_min_invariant (vr_value[i]->min))
       {
        single_val_range[i].value = vr_value[i]->min;
        do_value_subst_p = true;
@@ -7184,7 +7256,7 @@ vrp_finalize (void)
       single_val_range = NULL;
     }
 
-  substitute_and_fold (single_val_range, true);
+  substitute_and_fold (single_val_range, vrp_fold_stmt);
 
   if (warn_array_bounds)
       check_all_array_refs ();