re PR target/65697 (__atomic memory barriers not strong enough for __sync builtins)
[gcc.git] / gcc / tree-vrp.c
index ef1c21db973438a02f27956c401d710b315cd280..ec6d2c3e139ee9ddf2c0e3041a6be4a4fc4eb2d4 100644 (file)
@@ -23,15 +23,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "flags.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "vec.h"
-#include "double-int.h"
-#include "input.h"
 #include "alias.h"
 #include "symtab.h"
-#include "wide-int.h"
-#include "inchash.h"
 #include "tree.h"
 #include "fold-const.h"
 #include "stor-layout.h"
@@ -48,7 +41,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-fold.h"
 #include "tree-eh.h"
 #include "gimple-expr.h"
-#include "is-a.h"
 #include "gimple.h"
 #include "gimple-iterator.h"
 #include "gimple-walk.h"
@@ -73,11 +65,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-propagate.h"
 #include "tree-chrec.h"
 #include "tree-ssa-threadupdate.h"
-#include "hashtab.h"
 #include "rtl.h"
-#include "statistics.h"
-#include "real.h"
-#include "fixed-value.h"
 #include "insn-config.h"
 #include "expmed.h"
 #include "dojump.h"
@@ -88,6 +76,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "insn-codes.h"
 #include "optabs.h"
+#include "tree-ssa-scopedtables.h"
 #include "tree-ssa-threadedge.h"
 
 
@@ -393,6 +382,17 @@ nonnull_arg_p (const_tree arg)
   if (arg == cfun->static_chain_decl)
     return true;
 
+  /* THIS argument of method is always non-NULL.  */
+  if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE
+      && arg == DECL_ARGUMENTS (current_function_decl)
+      && flag_delete_null_pointer_checks)
+    return true;
+
+  /* Values passed by reference are always non-NULL.  */
+  if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE
+      && flag_delete_null_pointer_checks)
+    return true;
+
   fntype = TREE_TYPE (current_function_decl);
   for (attrs = TYPE_ATTRIBUTES (fntype); attrs; attrs = TREE_CHAIN (attrs))
     {
@@ -874,13 +874,18 @@ update_value_range (const_tree var, value_range_t *new_vr)
   if (is_new)
     {
       /* Do not allow transitions up the lattice.  The following
-         is slightly more awkward than just new_vr->type < old_vr->type
+        is slightly more awkward than just new_vr->type < old_vr->type
         because VR_RANGE and VR_ANTI_RANGE need to be considered
         the same.  We may not have is_new when transitioning to
-        UNDEFINED or from VARYING.  */
-      if (new_vr->type == VR_UNDEFINED
-         || old_vr->type == VR_VARYING)
-       set_value_range_to_varying (old_vr);
+        UNDEFINED.  If old_vr->type is VARYING, we shouldn't be
+        called.  */
+      if (new_vr->type == VR_UNDEFINED)
+       {
+         BITMAP_FREE (new_vr->equiv);
+         set_value_range_to_varying (old_vr);
+         set_value_range_to_varying (new_vr);
+         return true;
+       }
       else
        set_value_range (old_vr, new_vr->type, new_vr->min, new_vr->max,
                         new_vr->equiv);
@@ -1216,6 +1221,10 @@ gimple_stmt_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
            && DECL_IS_OPERATOR_NEW (fndecl)
            && !TREE_NOTHROW (fndecl))
          return true;
+       /* References are always non-NULL.  */
+       if (flag_delete_null_pointer_checks
+           && TREE_CODE (TREE_TYPE (fndecl)) == REFERENCE_TYPE)
+         return true;
        if (flag_delete_null_pointer_checks && 
            lookup_attribute ("returns_nonnull",
                              TYPE_ATTRIBUTES (gimple_call_fntype (stmt))))
@@ -2905,33 +2914,17 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
             prod3.  */
          /* min0min1 > max0max1 */
          if (wi::gts_p (prod0, prod3))
-           {
-             vrp_int tmp = prod3;
-             prod3 = prod0;
-             prod0 = tmp;
-           }
+           std::swap (prod0, prod3);
 
          /* min0max1 > max0min1 */
          if (wi::gts_p (prod1, prod2))
-           {
-             vrp_int tmp = prod2;
-             prod2 = prod1;
-             prod1 = tmp;
-           }
+           std::swap (prod1, prod2);
 
          if (wi::gts_p (prod0, prod1))
-           {
-             vrp_int tmp = prod1;
-             prod1 = prod0;
-             prod0 = tmp;
-           }
+           std::swap (prod0, prod1);
 
          if (wi::gts_p (prod2, prod3))
-           {
-             vrp_int tmp = prod3;
-             prod3 = prod2;
-             prod2 = tmp;
-           }
+           std::swap (prod2, prod3);
 
          /* diff = max - min.  */
          prod2 = prod3 - prod0;
@@ -3140,14 +3133,33 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
                 and all numbers from min to 0 for negative min.  */
              cmp = compare_values (vr0.max, zero);
              if (cmp == -1)
-               max = zero;
+               {
+                 /* When vr0.max < 0, vr1.min != 0 and value
+                    ranges for dividend and divisor are available.  */
+                 if (vr1.type == VR_RANGE
+                     && !symbolic_range_p (&vr0)
+                     && !symbolic_range_p (&vr1)
+                     && !compare_values (vr1.min, zero))
+                   max = int_const_binop (code, vr0.max, vr1.min);
+                 else
+                   max = zero;
+               }
              else if (cmp == 0 || cmp == 1)
                max = vr0.max;
              else
                type = VR_VARYING;
              cmp = compare_values (vr0.min, zero);
              if (cmp == 1)
-               min = zero;
+               {
+                 /* For unsigned division when value ranges for dividend
+                    and divisor are available.  */
+                 if (vr1.type == VR_RANGE
+                     && !symbolic_range_p (&vr0)
+                     && !symbolic_range_p (&vr1))
+                   min = int_const_binop (code, vr0.min, vr1.max);
+                 else
+                   min = zero;
+               }
              else if (cmp == 0 || cmp == -1)
                min = vr0.min;
              else
@@ -3175,26 +3187,60 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
     }
   else if (code == TRUNC_MOD_EXPR)
     {
-      if (vr1.type != VR_RANGE
-         || range_includes_zero_p (vr1.min, vr1.max) != 0
-         || vrp_val_is_min (vr1.min))
+      if (range_is_null (&vr1))
        {
-         set_value_range_to_varying (vr);
+         set_value_range_to_undefined (vr);
          return;
        }
+      /* ABS (A % B) < ABS (B) and either
+        0 <= A % B <= A or A <= A % B <= 0.  */
       type = VR_RANGE;
-      /* Compute MAX <|vr1.min|, |vr1.max|> - 1.  */
-      max = fold_unary_to_constant (ABS_EXPR, expr_type, vr1.min);
-      if (tree_int_cst_lt (max, vr1.max))
-       max = vr1.max;
-      max = int_const_binop (MINUS_EXPR, max, build_int_cst (TREE_TYPE (max), 1));
-      /* If the dividend is non-negative the modulus will be
-        non-negative as well.  */
-      if (TYPE_UNSIGNED (expr_type)
-         || value_range_nonnegative_p (&vr0))
-       min = build_int_cst (TREE_TYPE (max), 0);
+      signop sgn = TYPE_SIGN (expr_type);
+      unsigned int prec = TYPE_PRECISION (expr_type);
+      wide_int wmin, wmax, tmp;
+      wide_int zero = wi::zero (prec);
+      wide_int one = wi::one (prec);
+      if (vr1.type == VR_RANGE && !symbolic_range_p (&vr1))
+       {
+         wmax = wi::sub (vr1.max, one);
+         if (sgn == SIGNED)
+           {
+             tmp = wi::sub (wi::minus_one (prec), vr1.min);
+             wmax = wi::smax (wmax, tmp);
+           }
+       }
+      else
+       {
+         wmax = wi::max_value (prec, sgn);
+         /* X % INT_MIN may be INT_MAX.  */
+         if (sgn == UNSIGNED)
+           wmax = wmax - one;
+       }
+
+      if (sgn == UNSIGNED)
+       wmin = zero;
       else
-       min = fold_unary_to_constant (NEGATE_EXPR, expr_type, max);
+       {
+         wmin = -wmax;
+         if (vr0.type == VR_RANGE && TREE_CODE (vr0.min) == INTEGER_CST)
+           {
+             tmp = vr0.min;
+             if (wi::gts_p (tmp, zero))
+               tmp = zero;
+             wmin = wi::smax (wmin, tmp);
+           }
+       }
+
+      if (vr0.type == VR_RANGE && TREE_CODE (vr0.max) == INTEGER_CST)
+       {
+         tmp = vr0.max;
+         if (sgn == SIGNED && wi::neg_p (tmp))
+           tmp = zero;
+         wmax = wi::min (wmax, tmp, sgn);
+       }
+
+      min = wide_int_to_tree (expr_type, wmin);
+      max = wide_int_to_tree (expr_type, wmax);
     }
   else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR)
     {
@@ -3680,11 +3726,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
        {
           /* If the range was reversed, swap MIN and MAX.  */
          if (cmp == 1)
-           {
-             tree t = min;
-             min = max;
-             max = t;
-           }
+           std::swap (min, max);
        }
 
       cmp = compare_values (min, max);
@@ -4501,11 +4543,8 @@ compare_ranges (enum tree_code comp, value_range_t *vr0, value_range_t *vr1,
      operands around and change the comparison code.  */
   if (comp == GT_EXPR || comp == GE_EXPR)
     {
-      value_range_t *tmp;
       comp = (comp == GT_EXPR) ? LT_EXPR : LE_EXPR;
-      tmp = vr0;
-      vr0 = vr1;
-      vr1 = tmp;
+      std::swap (vr0, vr1);
     }
 
   if (comp == EQ_EXPR)
@@ -6550,6 +6589,14 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
   up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
                                 build_int_cst (TREE_TYPE (up_bound), 1));
 
+  /* Empty array.  */
+  if (tree_int_cst_equal (low_bound, up_bound_p1))
+    {
+      warning_at (location, OPT_Warray_bounds,
+                 "array subscript is above array bounds");
+      TREE_NO_WARNING (ref) = 1;
+    }
+
   if (TREE_CODE (low_sub) == SSA_NAME)
     {
       vr = get_value_range (low_sub);
@@ -6563,9 +6610,11 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
   if (vr && vr->type == VR_ANTI_RANGE)
     {
       if (TREE_CODE (up_sub) == INTEGER_CST
-          && tree_int_cst_lt (up_bound, up_sub)
+          && (ignore_off_by_one
+             ? tree_int_cst_lt (up_bound, up_sub)
+             : tree_int_cst_le (up_bound, up_sub))
           && TREE_CODE (low_sub) == INTEGER_CST
-          && tree_int_cst_lt (low_sub, low_bound))
+          && tree_int_cst_le (low_sub, low_bound))
         {
           warning_at (location, OPT_Warray_bounds,
                      "array subscript is outside array bounds");
@@ -6574,10 +6623,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
     }
   else if (TREE_CODE (up_sub) == INTEGER_CST
           && (ignore_off_by_one
-              ? (tree_int_cst_lt (up_bound, up_sub)
-                 && !tree_int_cst_equal (up_bound_p1, up_sub))
-              : (tree_int_cst_lt (up_bound, up_sub)
-                 || tree_int_cst_equal (up_bound_p1, up_sub))))
+              ? !tree_int_cst_le (up_sub, up_bound_p1)
+              : !tree_int_cst_le (up_sub, up_bound)))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
@@ -6610,25 +6657,6 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
 static void
 search_for_addr_array (tree t, location_t location)
 {
-  while (TREE_CODE (t) == SSA_NAME)
-    {
-      gimple g = SSA_NAME_DEF_STMT (t);
-
-      if (gimple_code (g) != GIMPLE_ASSIGN)
-       return;
-
-      if (get_gimple_rhs_class (gimple_assign_rhs_code (g))
-         != GIMPLE_SINGLE_RHS)
-       return;
-
-      t = gimple_assign_rhs1 (g);
-    }
-
-
-  /* We are only interested in addresses of ARRAY_REF's.  */
-  if (TREE_CODE (t) != ADDR_EXPR)
-    return;
-
   /* Check each ARRAY_REFs in the reference chain. */
   do
     {
@@ -6718,12 +6746,11 @@ 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) == MEM_REF
-      || (TREE_CODE (t) == RETURN_EXPR && TREE_OPERAND (t, 0)))
-    search_for_addr_array (TREE_OPERAND (t, 0), location);
-
-  if (TREE_CODE (t) == ADDR_EXPR)
-    *walk_subtree = FALSE;
+  else if (TREE_CODE (t) == ADDR_EXPR)
+    {
+      search_for_addr_array (t, location);
+      *walk_subtree = FALSE;
+    }
 
   return NULL_TREE;
 }
@@ -6753,29 +6780,17 @@ check_all_array_refs (void)
        {
          gimple stmt = gsi_stmt (si);
          struct walk_stmt_info wi;
-         if (!gimple_has_location (stmt))
+         if (!gimple_has_location (stmt)
+             || is_gimple_debug (stmt))
            continue;
 
-         if (is_gimple_call (stmt))
-           {
-             size_t i;
-             size_t n = gimple_call_num_args (stmt);
-             for (i = 0; i < n; i++)
-               {
-                 tree arg = gimple_call_arg (stmt, i);
-                 search_for_addr_array (arg, gimple_location (stmt));
-               }
-           }
-         else
-           {
-             memset (&wi, 0, sizeof (wi));
-             wi.info = CONST_CAST (void *, (const void *)
-                                   gimple_location_ptr (stmt));
+         memset (&wi, 0, sizeof (wi));
+         wi.info = CONST_CAST (void *, (const void *)
+                               gimple_location_ptr (stmt));
 
-             walk_gimple_op (gsi_stmt (si),
-                             check_array_bounds,
-                             &wi);
-           }
+         walk_gimple_op (gsi_stmt (si),
+                         check_array_bounds,
+                         &wi);
        }
     }
 }
@@ -7096,7 +7111,8 @@ vrp_valueize_1 (tree name)
          this SSA edge as the SSA propagator does not necessarily
         re-visit the use.  */
       gimple def_stmt = SSA_NAME_DEF_STMT (name);
-      if (prop_simulate_again_p (def_stmt))
+      if (!gimple_nop_p (def_stmt)
+         && prop_simulate_again_p (def_stmt))
        return NULL_TREE;
       value_range_t *vr = get_value_range (name);
       if (range_int_cst_singleton_p (vr))
@@ -8948,6 +8964,9 @@ update_range:
          fprintf (dump_file, "\n");
        }
 
+      if (vr_result.type == VR_VARYING)
+       return SSA_PROP_VARYING;
+
       return SSA_PROP_INTERESTING;
     }
 
@@ -10062,12 +10081,8 @@ vrp_fold_stmt (gimple_stmt_iterator *si)
   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.
-
-   A NULL entry is used to mark the end of pairs which need to be
-   restored.  */
-static vec<tree> equiv_stack;
+/* Unwindable const/copy equivalences.  */
+const_and_copies *equiv_stack;
 
 /* A trivial wrapper so that we can present the generic jump threading
    code with a simple API for simplifying statements.  STMT is the
@@ -10148,7 +10163,7 @@ identify_jump_threads (void)
 
   /* Allocate our unwinder stack to unwind any temporary equivalences
      that might be recorded.  */
-  equiv_stack.create (20);
+  equiv_stack = new const_and_copies (dump_file, dump_flags);
 
   /* To avoid lots of silly node creation, we create a single
      conditional and just modify it in-place when attempting to
@@ -10172,16 +10187,20 @@ identify_jump_threads (void)
       if (! potentially_threadable_block (bb))
        continue;
 
-      /* We only care about blocks ending in a COND_EXPR.  While there
-        may be some value in handling SWITCH_EXPR here, I doubt it's
-        terribly important.  */
-      last = gsi_stmt (gsi_last_bb (bb));
+      last = last_stmt (bb);
 
       /* We're basically looking for a switch or any kind of conditional with
         integral or pointer type arguments.  Note the type of the second
         argument will be the same as the first argument, so no need to
-        check it explicitly.  */
-      if (gimple_code (last) == GIMPLE_SWITCH
+        check it explicitly. 
+
+        We also handle the case where there are no statements in the
+        block.  This come up with forwarder blocks that are not
+        optimized away because they lead to a loop header.  But we do
+        want to thread through them as we can sometimes thread to the
+        loop exit which is obviously profitable.  */
+      if (!last
+         || gimple_code (last) == GIMPLE_SWITCH
          || (gimple_code (last) == GIMPLE_COND
              && TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME
              && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last)))
@@ -10202,7 +10221,7 @@ identify_jump_threads (void)
              if (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
                continue;
 
-             thread_across_edge (dummy, e, true, &equiv_stack,
+             thread_across_edge (dummy, e, true, equiv_stack,
                                  simplify_stmt_for_jump_threading);
            }
        }
@@ -10223,7 +10242,7 @@ static void
 finalize_jump_threads (void)
 {
   thread_through_all_blocks (false);
-  equiv_stack.release ();
+  delete equiv_stack;
 }
 
 
@@ -10265,12 +10284,12 @@ vrp_finalize (void)
          || (vr_value[i]->type == VR_UNDEFINED))
        continue;
 
-       if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
-           && (TREE_CODE (vr_value[i]->max) == INTEGER_CST)
-           && (vr_value[i]->type == VR_RANGE
-               || vr_value[i]->type == VR_ANTI_RANGE))
-         set_range_info (name, vr_value[i]->type, vr_value[i]->min,
-                         vr_value[i]->max);
+      if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
+         && (TREE_CODE (vr_value[i]->max) == INTEGER_CST)
+         && (vr_value[i]->type == VR_RANGE
+             || vr_value[i]->type == VR_ANTI_RANGE))
+       set_range_info (name, vr_value[i]->type, vr_value[i]->min,
+                       vr_value[i]->max);
       }
 
   /* Free allocated memory.  */