OSDN Git Service

* collect2.c (main): Remove SWITCHES_NEED_SPACES conditional.
[pf3gnuchains/gcc-fork.git] / gcc / tree-vrp.c
index b23132c..efeb474 100644 (file)
@@ -31,7 +31,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "tree-dump.h"
 #include "timevar.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
+#include "gimple-pretty-print.h"
 #include "toplev.h"
 #include "intl.h"
 #include "cfgloop.h"
@@ -764,6 +765,27 @@ range_is_null (value_range_t *vr)
         && integer_zerop (vr->max);
 }
 
+/* Return true if max and min of VR are INTEGER_CST.  It's not necessary
+   a singleton.  */
+
+static inline bool
+range_int_cst_p (value_range_t *vr)
+{
+  return (vr->type == VR_RANGE
+         && TREE_CODE (vr->max) == INTEGER_CST
+         && TREE_CODE (vr->min) == INTEGER_CST
+         && !TREE_OVERFLOW (vr->max)
+         && !TREE_OVERFLOW (vr->min));
+}
+
+/* Return true if VR is a INTEGER_CST singleton.  */
+
+static inline bool
+range_int_cst_singleton_p (value_range_t *vr)
+{
+  return (range_int_cst_p (vr)
+         && tree_int_cst_equal (vr->min, vr->max));
+}
 
 /* Return true if value range VR involves at least one symbol.  */
 
@@ -843,6 +865,8 @@ gimple_assign_nonnegative_warnv_p (gimple stmt, bool *strict_overflow_p)
                                              gimple_assign_rhs1 (stmt),
                                              gimple_assign_rhs2 (stmt),
                                              strict_overflow_p);
+    case GIMPLE_TERNARY_RHS:
+      return false;
     case GIMPLE_SINGLE_RHS:
       return tree_single_nonnegative_warnv_p (gimple_assign_rhs1 (stmt),
                                              strict_overflow_p);
@@ -914,6 +938,8 @@ gimple_assign_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
                                          gimple_assign_rhs1 (stmt),
                                          gimple_assign_rhs2 (stmt),
                                          strict_overflow_p);
+    case GIMPLE_TERNARY_RHS:
+      return false;
     case GIMPLE_SINGLE_RHS:
       return tree_single_nonzero_warnv_p (gimple_assign_rhs1 (stmt),
                                          strict_overflow_p);
@@ -1343,6 +1369,10 @@ ssa_name_nonnegative_p (const_tree t)
 {
   value_range_t *vr = get_value_range (t);
 
+  if (INTEGRAL_TYPE_P (t)
+      && TYPE_UNSIGNED (t))
+    return true;
+
   if (!vr)
     return false;
 
@@ -2058,6 +2088,7 @@ extract_range_from_binary_expr (value_range_t *vr,
       && code != CEIL_DIV_EXPR
       && code != EXACT_DIV_EXPR
       && code != ROUND_DIV_EXPR
+      && code != TRUNC_MOD_EXPR
       && code != RSHIFT_EXPR
       && code != MIN_EXPR
       && code != MAX_EXPR
@@ -2126,6 +2157,7 @@ extract_range_from_binary_expr (value_range_t *vr,
       && code != CEIL_DIV_EXPR
       && code != EXACT_DIV_EXPR
       && code != ROUND_DIV_EXPR
+      && code != TRUNC_MOD_EXPR
       && (vr0.type == VR_VARYING
          || vr1.type == VR_VARYING
          || vr0.type != vr1.type
@@ -2476,6 +2508,31 @@ extract_range_from_binary_expr (value_range_t *vr,
            }
        }
     }
+  else if (code == TRUNC_MOD_EXPR)
+    {
+      bool sop = false;
+      if (vr1.type != VR_RANGE
+         || symbolic_range_p (&vr1)
+         || range_includes_zero_p (&vr1)
+         || vrp_val_is_min (vr1.min))
+       {
+         set_value_range_to_varying (vr);
+         return;
+       }
+      type = VR_RANGE;
+      /* Compute MAX <|vr1.min|, |vr1.max|> - 1.  */
+      max = fold_unary_to_constant (ABS_EXPR, TREE_TYPE (vr1.min), vr1.min);
+      if (tree_int_cst_lt (max, vr1.max))
+       max = vr1.max;
+      max = int_const_binop (MINUS_EXPR, max, integer_one_node, 0);
+      /* If the dividend is non-negative the modulus will be
+        non-negative as well.  */
+      if (TYPE_UNSIGNED (TREE_TYPE (max))
+         || (vrp_expr_computes_nonnegative (op0, &sop) && !sop))
+       min = build_int_cst (TREE_TYPE (max), 0);
+      else
+       min = fold_unary_to_constant (NEGATE_EXPR, TREE_TYPE (max), max);
+    }
   else if (code == MINUS_EXPR)
     {
       /* If we have a MINUS_EXPR with two VR_ANTI_RANGEs, drop to
@@ -2498,19 +2555,20 @@ extract_range_from_binary_expr (value_range_t *vr,
     }
   else if (code == BIT_AND_EXPR)
     {
-      if (vr0.type == VR_RANGE
-         && vr0.min == vr0.max
-         && TREE_CODE (vr0.max) == INTEGER_CST
-         && !TREE_OVERFLOW (vr0.max)
-         && tree_int_cst_sgn (vr0.max) >= 0)
+      bool vr0_int_cst_singleton_p, vr1_int_cst_singleton_p;
+
+      vr0_int_cst_singleton_p = range_int_cst_singleton_p (&vr0);
+      vr1_int_cst_singleton_p = range_int_cst_singleton_p (&vr1);
+
+      if (vr0_int_cst_singleton_p && vr1_int_cst_singleton_p)
+       min = max = int_const_binop (code, vr0.max, vr1.max, 0);
+      else if (vr0_int_cst_singleton_p
+              && tree_int_cst_sgn (vr0.max) >= 0)
        {
          min = build_int_cst (expr_type, 0);
          max = vr0.max;
        }
-      else if (vr1.type == VR_RANGE
-              && vr1.min == vr1.max
-              && TREE_CODE (vr1.max) == INTEGER_CST
-              && !TREE_OVERFLOW (vr1.max)
+      else if (vr1_int_cst_singleton_p
               && tree_int_cst_sgn (vr1.max) >= 0)
        {
          type = VR_RANGE;
@@ -2525,12 +2583,8 @@ extract_range_from_binary_expr (value_range_t *vr,
     }
   else if (code == BIT_IOR_EXPR)
     {
-      if (vr0.type == VR_RANGE
-          && vr1.type == VR_RANGE
-         && TREE_CODE (vr0.min) == INTEGER_CST
-         && TREE_CODE (vr1.min) == INTEGER_CST
-         && TREE_CODE (vr0.max) == INTEGER_CST
-         && TREE_CODE (vr1.max) == INTEGER_CST
+      if (range_int_cst_p (&vr0)
+         && range_int_cst_p (&vr1)
          && tree_int_cst_sgn (vr0.min) >= 0
          && tree_int_cst_sgn (vr1.min) >= 0)
        {
@@ -3696,7 +3750,7 @@ dump_value_range (FILE *file, value_range_t *vr)
 
 /* Dump value range VR to stderr.  */
 
-void
+DEBUG_FUNCTION void
 debug_value_range (value_range_t *vr)
 {
   dump_value_range (stderr, vr);
@@ -3728,7 +3782,7 @@ dump_all_value_ranges (FILE *file)
 
 /* Dump all value ranges to stderr.  */
 
-void
+DEBUG_FUNCTION void
 debug_all_value_ranges (void)
 {
   dump_all_value_ranges (stderr);
@@ -3884,7 +3938,7 @@ dump_asserts_for (FILE *file, tree name)
 
 /* Dump all the registered assertions for NAME to stderr.  */
 
-void
+DEBUG_FUNCTION void
 debug_asserts_for (tree name)
 {
   dump_asserts_for (stderr, name);
@@ -3908,7 +3962,7 @@ dump_all_asserts (FILE *file)
 
 /* Dump all the registered assertions for all the names to stderr.  */
 
-void
+DEBUG_FUNCTION void
 debug_all_asserts (void)
 {
   dump_all_asserts (stderr);
@@ -7293,7 +7347,7 @@ vrp_finalize (void)
       single_val_range = NULL;
     }
 
-  substitute_and_fold (single_val_range, vrp_fold_stmt);
+  substitute_and_fold (single_val_range, vrp_fold_stmt, false);
 
   if (warn_array_bounds)
     check_all_array_refs ();