OSDN Git Service

PR c++/44703
[pf3gnuchains/gcc-fork.git] / gcc / tree-vrp.c
index 3b22948..74b3a7a 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);
@@ -961,7 +987,7 @@ vrp_stmt_computes_nonzero (gimple stmt, bool *strict_overflow_p)
       tree base = get_base_address (TREE_OPERAND (expr, 0));
 
       if (base != NULL_TREE
-         && TREE_CODE (base) == INDIRECT_REF
+         && TREE_CODE (base) == MEM_REF
          && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
        {
          value_range_t *vr = get_value_range (TREE_OPERAND (base, 0));
@@ -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;
 
@@ -1481,10 +1511,10 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
       /* Make sure to not set TREE_OVERFLOW on the final type
         conversion.  We are willingly interpreting large positive
         unsigned values as negative singed values here.  */
-      min = force_fit_type_double (TREE_TYPE (var), TREE_INT_CST_LOW (min),
-                                  TREE_INT_CST_HIGH (min), 0, false);
-      max = force_fit_type_double (TREE_TYPE (var), TREE_INT_CST_LOW (max),
-                                  TREE_INT_CST_HIGH (max), 0, false);
+      min = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (min),
+                                  0, false);
+      max = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (max),
+                                  0, false);
 
       /* We can transform a max, min range to an anti-range or
          vice-versa.  Use set_and_canonicalize_value_range which does
@@ -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
@@ -2156,15 +2188,30 @@ extract_range_from_binary_expr (value_range_t *vr,
 
          return;
        }
-      gcc_assert (code == POINTER_PLUS_EXPR);
-      /* For pointer types, we are really only interested in asserting
-        whether the expression evaluates to non-NULL.  */
-      if (range_is_nonnull (&vr0) || range_is_nonnull (&vr1))
-       set_value_range_to_nonnull (vr, expr_type);
-      else if (range_is_null (&vr0) && range_is_null (&vr1))
-       set_value_range_to_null (vr, expr_type);
+      if (code == POINTER_PLUS_EXPR)
+       {
+         /* For pointer types, we are really only interested in asserting
+            whether the expression evaluates to non-NULL.  */
+         if (range_is_nonnull (&vr0) || range_is_nonnull (&vr1))
+           set_value_range_to_nonnull (vr, expr_type);
+         else if (range_is_null (&vr0) && range_is_null (&vr1))
+           set_value_range_to_null (vr, expr_type);
+         else
+           set_value_range_to_varying (vr);
+       }
+      else if (code == BIT_AND_EXPR)
+       {
+         /* For pointer types, we are really only interested in asserting
+            whether the expression evaluates to non-NULL.  */
+         if (range_is_nonnull (&vr0) && range_is_nonnull (&vr1))
+           set_value_range_to_nonnull (vr, expr_type);
+         else if (range_is_null (&vr0) || range_is_null (&vr1))
+           set_value_range_to_null (vr, expr_type);
+         else
+           set_value_range_to_varying (vr);
+       }
       else
-       set_value_range_to_varying (vr);
+       gcc_unreachable ();
 
       return;
     }
@@ -2476,6 +2523,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 +2570,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 +2598,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)
        {
@@ -2733,11 +2802,11 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
        {
          tree new_min, new_max;
          new_min = force_fit_type_double (outer_type,
-                                          TREE_INT_CST_LOW (vr0.min),
-                                          TREE_INT_CST_HIGH (vr0.min), 0, 0);
+                                          tree_to_double_int (vr0.min),
+                                          0, false);
          new_max = force_fit_type_double (outer_type,
-                                          TREE_INT_CST_LOW (vr0.max),
-                                          TREE_INT_CST_HIGH (vr0.max), 0, 0);
+                                          tree_to_double_int (vr0.max),
+                                          0, false);
          if (is_overflow_infinity (vr0.min))
            new_min = negative_overflow_infinity (outer_type);
          if (is_overflow_infinity (vr0.max))
@@ -3153,7 +3222,7 @@ static void
 adjust_range_with_scev (value_range_t *vr, struct loop *loop,
                        gimple stmt, tree var)
 {
-  tree init, step, chrec, tmin, tmax, min, max, type;
+  tree init, step, chrec, tmin, tmax, min, max, type, tem;
   enum ev_direction dir;
 
   /* TODO.  Don't adjust anti-ranges.  An anti-range may provide
@@ -3174,7 +3243,13 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
     return;
 
   init = initial_condition_in_loop_num (chrec, loop->num);
+  tem = op_with_constant_singleton_value_range (init);
+  if (tem)
+    init = tem;
   step = evolution_part_in_loop_num (chrec, loop->num);
+  tem = op_with_constant_singleton_value_range (step);
+  if (tem)
+    step = tem;
 
   /* If STEP is symbolic, we can't know whether INIT will be the
      minimum or maximum value in the range.  Also, unless INIT is
@@ -3690,7 +3765,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);
@@ -3722,7 +3797,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);
@@ -3878,7 +3953,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);
@@ -3902,7 +3977,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);
@@ -5015,8 +5090,7 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
   /* Accesses to trailing arrays via pointers may access storage
      beyond the types array bounds.  */
   base = get_base_address (ref);
-  if (base
-      && INDIRECT_REF_P (base))
+  if (base && TREE_CODE (base) == MEM_REF)
     {
       tree cref, next = NULL_TREE;
 
@@ -5115,6 +5189,51 @@ search_for_addr_array (tree t, location_t location)
       t = TREE_OPERAND (t, 0);
     }
   while (handled_component_p (t));
+
+  if (TREE_CODE (t) == MEM_REF
+      && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+      && !TREE_NO_WARNING (t))
+    {
+      tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+      tree low_bound, up_bound, el_sz;
+      double_int idx;
+      if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
+         || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
+         || !TYPE_DOMAIN (TREE_TYPE (tem)))
+       return;
+
+      low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
+      up_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
+      el_sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (tem)));
+      if (!low_bound
+         || TREE_CODE (low_bound) != INTEGER_CST
+         || !up_bound
+         || TREE_CODE (up_bound) != INTEGER_CST
+         || !el_sz
+         || TREE_CODE (el_sz) != INTEGER_CST)
+       return;
+
+      idx = mem_ref_offset (t);
+      idx = double_int_sdiv (idx, tree_to_double_int (el_sz), TRUNC_DIV_EXPR);
+      if (double_int_scmp (idx, double_int_zero) < 0)
+       {
+         warning_at (location, OPT_Warray_bounds,
+                     "array subscript is below array bounds");
+         TREE_NO_WARNING (t) = 1;
+       }
+      else if (double_int_scmp (idx,
+                               double_int_add
+                                 (double_int_add
+                                   (tree_to_double_int (up_bound),
+                                    double_int_neg
+                                      (tree_to_double_int (low_bound))),
+                                   double_int_one)) > 0)
+       {
+         warning_at (location, OPT_Warray_bounds,
+                     "array subscript is above array bounds");
+         TREE_NO_WARNING (t) = 1;
+       }
+    }
 }
 
 /* walk_tree() callback that checks if *TP is
@@ -5143,7 +5262,7 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
   if (TREE_CODE (t) == ARRAY_REF)
     check_array_ref (location, t, false /*ignore_off_by_one*/);
 
-  if (TREE_CODE (t) == INDIRECT_REF
+  if (TREE_CODE (t) == MEM_REF
       || (TREE_CODE (t) == RETURN_EXPR && TREE_OPERAND (t, 0)))
     search_for_addr_array (TREE_OPERAND (t, 0), location);
 
@@ -6432,7 +6551,18 @@ vrp_visit_phi_node (gimple phi)
   /* If the new range is different than the previous value, keep
      iterating.  */
   if (update_value_range (lhs, &vr_result))
-    return SSA_PROP_INTERESTING;
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Found new range for ");
+         print_generic_expr (dump_file, lhs, 0);
+         fprintf (dump_file, ": ");
+         dump_value_range (dump_file, &vr_result);
+         fprintf (dump_file, "\n\n");
+       }
+
+      return SSA_PROP_INTERESTING;
+    }
 
   /* Nothing changed, don't add outgoing edges.  */
   return SSA_PROP_NOT_INTERESTING;
@@ -7244,6 +7374,7 @@ vrp_finalize (void)
   size_t i;
   prop_value_t *single_val_range;
   bool do_value_subst_p;
+  unsigned num = num_ssa_names;
 
   if (dump_file)
     {
@@ -7255,10 +7386,10 @@ vrp_finalize (void)
   /* We may have ended with ranges that have exactly one value.  Those
      values can be substituted as any other const propagated
      value using substitute_and_fold.  */
-  single_val_range = XCNEWVEC (prop_value_t, num_ssa_names);
+  single_val_range = XCNEWVEC (prop_value_t, num);
 
   do_value_subst_p = false;
-  for (i = 0; i < num_ssa_names; i++)
+  for (i = 0; i < num; i++)
     if (vr_value[i]
        && vr_value[i]->type == VR_RANGE
        && vr_value[i]->min == vr_value[i]->max
@@ -7276,7 +7407,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 ();
@@ -7286,7 +7417,7 @@ vrp_finalize (void)
   identify_jump_threads ();
 
   /* Free allocated memory.  */
-  for (i = 0; i < num_ssa_names; i++)
+  for (i = 0; i < num; i++)
     if (vr_value[i])
       {
        BITMAP_FREE (vr_value[i]->equiv);