Disentangle range_fold_*ary_expr() into various independent pieces.
authorAldy Hernandez <aldyh@redhat.com>
Mon, 7 Oct 2019 11:43:13 +0000 (11:43 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Mon, 7 Oct 2019 11:43:13 +0000 (11:43 +0000)
From-SVN: r276654

gcc/ChangeLog
gcc/ipa-prop.c
gcc/ipa-prop.h
gcc/tree-vrp.c
gcc/tree-vrp.h

index fbb1634cbae8b79b6f6ebdffc357fa2537791ddd..83ad0017b5aefd3ea0e5f7792ebf2e9ce6d28c86 100644 (file)
@@ -1,3 +1,23 @@
+2019-10-07  Aldy Hernandez  <aldyh@redhat.com>
+
+       * ipa-prop.c (ipa_vr::nonzero_p): New.
+       (ipcp_update_vr): Use nonzero_p instead of open-coding check for
+       non-zero range.
+       * ipa-prop.h (class ipa_vr): Add nonzero_p.
+       * tree-vrp.c (range_has_numeric_bounds_p): New.
+       (range_int_cst_p): Use range_has_numeric_bounds_p.
+       (get_range_op_handler): New.
+       (supported_types_p): New.
+       (defined_ranges_p): New.
+       (drop_undefines_to_varying): New.
+       (range_fold_binary_symbolics_p): New.
+       (range_fold_unary_symbolics_p): New.
+       (range_fold_unary_expr): Extract out into above functions.
+       (range_fold_binary_expr): Same.
+       (value_range_base::normalize_addresses): New.
+       (value_range_base::normalize_symbolics): Normalize addresses.
+       * tree-vrp.h (class value_range_base): Add normalize_addresses.
+
 2019-10-07  Aldy Hernandez  <aldyh@redhat.com>
 
        * tree-vrp.c (value_range_base::singleton_p): Use
index e79add12b1e5ffbc30a2caa0ba53bac7b041d3bd..20a0bddcbab9c21d562cb51f2fb1f8afd99869e3 100644 (file)
@@ -5109,6 +5109,18 @@ ipcp_update_bits (struct cgraph_node *node)
     }
 }
 
+bool
+ipa_vr::nonzero_p (tree expr_type) const
+{
+  if (type == VR_ANTI_RANGE && wi::eq_p (min, 0) && wi::eq_p (max, 0))
+    return true;
+
+  unsigned prec = TYPE_PRECISION (expr_type);
+  return (type == VR_RANGE
+         && wi::eq_p (min, wi::one (prec))
+         && wi::eq_p (max, wi::max_value (prec, TYPE_SIGN (expr_type))));
+}
+
 /* Update value range of formal parameters as described in
    ipcp_transformation.  */
 
@@ -5181,9 +5193,7 @@ ipcp_update_vr (struct cgraph_node *node)
                                                      TYPE_SIGN (type)));
            }
          else if (POINTER_TYPE_P (TREE_TYPE (ddef))
-                  && vr[i].type == VR_ANTI_RANGE
-                  && wi::eq_p (vr[i].min, 0)
-                  && wi::eq_p (vr[i].max, 0))
+                  && vr[i].nonzero_p (TREE_TYPE (ddef)))
            {
              if (dump_file)
                fprintf (dump_file, "Setting nonnull for %u\n", i);
index 0ff80854284520004a7eec5331c5466c0ea32679..eb3397a6d81a37c4ff51ca95e484f74562364414 100644 (file)
@@ -165,6 +165,7 @@ public:
   enum value_range_kind type;
   wide_int min;
   wide_int max;
+  bool nonzero_p (tree) const;
 };
 
 /* A jump function for a callsite represents the values passed as actual
index 86e4dace0739c0128f109adafb0a7464afc89efe..d69cfb107cbe79058a8f1d96385491a571053d11 100644 (file)
@@ -910,15 +910,21 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2)
              && bitmap_equal_p (b1, b2)));
 }
 
+static bool
+range_has_numeric_bounds_p (const value_range_base *vr)
+{
+  return (vr->min ()
+         && TREE_CODE (vr->min ()) == INTEGER_CST
+         && TREE_CODE (vr->max ()) == INTEGER_CST);
+}
+
 /* Return true if max and min of VR are INTEGER_CST.  It's not necessary
    a singleton.  */
 
 bool
 range_int_cst_p (const value_range_base *vr)
 {
-  return (vr->kind () == VR_RANGE
-         && TREE_CODE (vr->min ()) == INTEGER_CST
-         && TREE_CODE (vr->max ()) == INTEGER_CST);
+  return (vr->kind () == VR_RANGE && range_has_numeric_bounds_p (vr));
 }
 
 /* Return true if VR is a INTEGER_CST singleton.  */
@@ -1760,119 +1766,102 @@ extract_range_from_plus_minus_expr (value_range_base *vr,
     vr->set (kind, min, max);
 }
 
-/* Normalize a value_range for use in range_ops and return it.  */
+/* Return the range-ops handler for CODE and EXPR_TYPE.  If no
+   suitable operator is found, return NULL and set VR to VARYING.  */
 
-static value_range_base
-normalize_for_range_ops (const value_range_base &vr)
+static const range_operator *
+get_range_op_handler (value_range_base *vr,
+                     enum tree_code code,
+                     tree expr_type)
 {
-  tree type = vr.type ();
+  const range_operator *op = range_op_handler (code, expr_type);
+  if (!op)
+    vr->set_varying (expr_type);
+  return op;
+}
+
+/* If the types passed are supported, return TRUE, otherwise set VR to
+   VARYING and return FALSE.  */
 
-  /* This will return ~[0,0] for [&var, &var].  */
-  if (POINTER_TYPE_P (type) && !range_includes_zero_p (&vr))
+static bool
+supported_types_p (value_range_base *vr,
+                  tree type0,
+                  tree type1 = NULL)
+{
+  if (!value_range_base::supports_type_p (type0)
+      || (type1 && !value_range_base::supports_type_p (type1)))
     {
-      value_range_base temp;
-      temp.set_nonzero (type);
-      return temp;
+      vr->set_varying (type0);
+      return false;
     }
-  if (vr.symbolic_p ())
-    return normalize_for_range_ops (vr.normalize_symbolics ());
-  if (TREE_CODE (vr.min ()) == INTEGER_CST
-      && TREE_CODE (vr.max ()) == INTEGER_CST)
-    return vr;
-  /* Anything not strictly numeric at this point becomes varying.  */
-  return value_range_base (vr.type ());
+  return true;
 }
 
-/* Fold a binary expression of two value_range's with range-ops.  */
+/* If any of the ranges passed are defined, return TRUE, otherwise set
+   VR to UNDEFINED and return FALSE.  */
 
-void
-range_fold_binary_expr (value_range_base *vr,
-                       enum tree_code code,
-                       tree expr_type,
-                       const value_range_base *vr0_,
-                       const value_range_base *vr1_)
+static bool
+defined_ranges_p (value_range_base *vr,
+                 const value_range_base *vr0,
+                 const value_range_base *vr1 = NULL)
 {
-  if (!value_range_base::supports_type_p (expr_type)
-      || (!vr0_->undefined_p ()
-         && !value_range_base::supports_type_p (vr0_->type ()))
-      || (!vr1_->undefined_p ()
-         && !value_range_base::supports_type_p (vr1_->type ())))
-    {
-      vr->set_varying (expr_type);
-      return;
-    }
-  if (vr0_->undefined_p () && vr1_->undefined_p ())
+  if (vr0->undefined_p () && (!vr1 || vr1->undefined_p ()))
     {
       vr->set_undefined ();
-      return;
-    }
-  range_operator *op = range_op_handler (code, expr_type);
-  if (!op)
-    {
-      vr->set_varying (expr_type);
-      return;
+      return false;
     }
+  return true;
+}
 
-  /* Mimic any behavior users of extract_range_from_binary_expr may
-     expect.  */
-  value_range_base vr0 = *vr0_, vr1 = *vr1_;
-  if (vr0.undefined_p ())
-    vr0.set_varying (expr_type);
-  else if (vr1.undefined_p ())
-    vr1.set_varying (expr_type);
+static value_range_base
+drop_undefines_to_varying (const value_range_base *vr, tree expr_type)
+{
+  if (vr->undefined_p ())
+    return value_range_base (expr_type);
+  else
+    return *vr;
+}
+
+/* If any operand is symbolic, perform a binary operation on them and
+   return TRUE, otherwise return FALSE.  */
 
-  /* Handle symbolics.  */
-  if (vr0.symbolic_p () || vr1.symbolic_p ())
+static bool
+range_fold_binary_symbolics_p (value_range_base *vr,
+                              tree_code code,
+                              tree expr_type,
+                              const value_range_base *vr0,
+                              const value_range_base *vr1)
+{
+  if (vr0->symbolic_p () || vr1->symbolic_p ())
     {
       if ((code == PLUS_EXPR || code == MINUS_EXPR))
        {
-         extract_range_from_plus_minus_expr (vr, code, expr_type,
-                                             &vr0, &vr1);
-         return;
+         extract_range_from_plus_minus_expr (vr, code, expr_type, vr0, vr1);
+         return true;
        }
       if (POINTER_TYPE_P (expr_type) && code == POINTER_PLUS_EXPR)
        {
-         extract_range_from_pointer_plus_expr (vr, code, expr_type,
-                                               &vr0, &vr1);
-         return;
+         extract_range_from_pointer_plus_expr (vr, code, expr_type, vr0, vr1);
+         return true;
        }
+      const range_operator *op = get_range_op_handler (vr, code, expr_type);
+      *vr = op->fold_range (expr_type,
+                           vr0->normalize_symbolics (),
+                           vr1->normalize_symbolics ());
+      return true;
     }
-
-  /* Do the range-ops dance.  */
-  value_range_base n0 = normalize_for_range_ops (vr0);
-  value_range_base n1 = normalize_for_range_ops (vr1);
-  *vr = op->fold_range (expr_type, n0, n1);
+  return false;
 }
 
-/* Fold a unary expression of a value_range with range-ops.  */
+/* If operand is symbolic, perform a unary operation on it and return
+   TRUE, otherwise return FALSE.  */
 
-void
-range_fold_unary_expr (value_range_base *vr,
-                      enum tree_code code, tree expr_type,
-                      const value_range_base *vr0,
-                      tree vr0_type)
+static bool
+range_fold_unary_symbolics_p (value_range_base *vr,
+                             tree_code code,
+                             tree expr_type,
+                             const value_range_base *vr0)
 {
-  /* Mimic any behavior users of extract_range_from_unary_expr may
-     expect.  */
-  if (!value_range_base::supports_type_p (expr_type)
-      || !value_range_base::supports_type_p (vr0_type))
-    {
-      vr->set_varying (expr_type);
-      return;
-    }
-  if (vr0->undefined_p ())
-    {
-      vr->set_undefined ();
-      return;
-    }
-  range_operator *op = range_op_handler (code, expr_type);
-  if (!op)
-    {
-      vr->set_varying (expr_type);
-      return;
-    }
-
-  /* Handle symbolics.  */
   if (vr0->symbolic_p ())
     {
       if (code == NEGATE_EXPR)
@@ -1881,7 +1870,7 @@ range_fold_unary_expr (value_range_base *vr,
          value_range_base zero;
          zero.set_zero (vr0->type ());
          range_fold_binary_expr (vr, MINUS_EXPR, expr_type, &zero, vr0);
-         return;
+         return true;
        }
       if (code == BIT_NOT_EXPR)
        {
@@ -1889,30 +1878,64 @@ range_fold_unary_expr (value_range_base *vr,
          value_range_base minusone;
          minusone.set (build_int_cst (vr0->type (), -1));
          range_fold_binary_expr (vr, MINUS_EXPR, expr_type, &minusone, vr0);
-         return;
+         return true;
        }
+      const range_operator *op = get_range_op_handler (vr, code, expr_type);
       *vr = op->fold_range (expr_type,
-                           normalize_for_range_ops (*vr0),
+                           vr0->normalize_symbolics (),
                            value_range_base (expr_type));
-      return;
-    }
-  if (CONVERT_EXPR_CODE_P (code) && (POINTER_TYPE_P (expr_type)
-                                    || POINTER_TYPE_P (vr0->type ())))
-    {
-      /* This handles symbolic conversions such such as [25, x_4].  */
-      if (!range_includes_zero_p (vr0))
-       vr->set_nonzero (expr_type);
-      else if (vr0->zero_p ())
-       vr->set_zero (expr_type);
-      else
-       vr->set_varying (expr_type);
-      return;
+      return true;
     }
+  return false;
+}
 
-  /* Do the range-ops dance.  */
-  value_range_base n0 = normalize_for_range_ops (*vr0);
-  value_range_base n1 (expr_type);
-  *vr = op->fold_range (expr_type, n0, n1);
+/* Perform a binary operation on a pair of ranges.  */
+
+void
+range_fold_binary_expr (value_range_base *vr,
+                       enum tree_code code,
+                       tree expr_type,
+                       const value_range_base *vr0_,
+                       const value_range_base *vr1_)
+{
+  if (!supported_types_p (vr, expr_type)
+      || !defined_ranges_p (vr, vr0_, vr1_))
+    return;
+  const range_operator *op = get_range_op_handler (vr, code, expr_type);
+  if (!op)
+    return;
+
+  value_range_base vr0 = drop_undefines_to_varying (vr0_, expr_type);
+  value_range_base vr1 = drop_undefines_to_varying (vr1_, expr_type);
+  if (range_fold_binary_symbolics_p (vr, code, expr_type, &vr0, &vr1))
+    return;
+
+  *vr = op->fold_range (expr_type,
+                       vr0.normalize_addresses (),
+                       vr1.normalize_addresses ());
+}
+
+/* Perform a unary operation on a range.  */
+
+void
+range_fold_unary_expr (value_range_base *vr,
+                      enum tree_code code, tree expr_type,
+                      const value_range_base *vr0,
+                      tree vr0_type)
+{
+  if (!supported_types_p (vr, expr_type, vr0_type)
+      || !defined_ranges_p (vr, vr0))
+    return;
+  const range_operator *op = get_range_op_handler (vr, code, expr_type);
+  if (!op)
+    return;
+
+  if (range_fold_unary_symbolics_p (vr, code, expr_type, vr0))
+    return;
+
+  *vr = op->fold_range (expr_type,
+                       vr0->normalize_addresses (),
+                       value_range_base (expr_type));
 }
 
 /* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
@@ -5997,7 +6020,24 @@ value_range::union_ (const value_range *other)
     }
 }
 
-/* Normalize symbolics into constants.  */
+/* Normalize addresses into constants.  */
+
+value_range_base
+value_range_base::normalize_addresses () const
+{
+  if (!POINTER_TYPE_P (type ()) || range_has_numeric_bounds_p (this))
+    return *this;
+
+  if (!range_includes_zero_p (this))
+    {
+      gcc_checking_assert (TREE_CODE (m_min) == ADDR_EXPR
+                          || TREE_CODE (m_max) == ADDR_EXPR);
+      return range_nonzero (type ());
+    }
+  return value_range_base (type ());
+}
+
+/* Normalize symbolics and addresses into constants.  */
 
 value_range_base
 value_range_base::normalize_symbolics () const
@@ -6008,7 +6048,7 @@ value_range_base::normalize_symbolics () const
   bool min_symbolic = !is_gimple_min_invariant (min ());
   bool max_symbolic = !is_gimple_min_invariant (max ());
   if (!min_symbolic && !max_symbolic)
-    return *this;
+    return normalize_addresses ();
 
   // [SYM, SYM] -> VARYING
   if (min_symbolic && max_symbolic)
index d20d0043ba3b01026afda2df7a064822ed6bcd13..a3f9e90699d3d49fe080be1713c5b52fdf71904b 100644 (file)
@@ -86,6 +86,7 @@ public:
 
   static bool supports_type_p (tree);
   value_range_base normalize_symbolics () const;
+  value_range_base normalize_addresses () const;
 
   static const unsigned int m_max_pairs = 2;
   bool contains_p (tree) const;