Changes the TARGET_POLY_INT_INDETERMINATE_BOUND to be a macro instead
of a target hook. This is to lower the cost of this operation in
poly_int comparisons which can happen very often.

Additionally, adds maybe_upper_bound and maybe_lower_bound functions for
poly_ints, which try to calculate an upper or lower bound.

Then, adds optional flags to poly_int comparisons to
allow for the bounds of the polyint to be taken into account when
comparing poly_int values.

Note, that we cannot use the boounds unconditionally, as the comparison
functions are used for two slightly different purposes in the code base:

1. To check if the eventual runtime values the poly_ints represent can
   statically be known to be gt or lt eachother.
2. To check if all the coefficients of one poly_int are strictly greater
   or less than another. For instance, to check if one unsigned poly_int
   could be subtracted from another, without underflow.

Therefore, this is made an opt-in behaviour with a flag.

This also imposes some type requirements on maybe_lt and related
to make the types all work.

gcc/ChangeLog:

        * config/aarch64/aarch64-modes.def (POLY_INT_INDETERMINATE_BOUND):
        New macro definition.
        * config/aarch64/aarch64.cc (aarch64_poly_int_indeterminate_bound):
        Remove.
        (TARGET_POLY_INT_INDETERMINATE_BOUND): Remove.
        * doc/tm.texi (TARGET_POLY_INT_INDETERMINATE_BOUND): Remove.
        * doc/tm.texi.in (TARGET_POLY_INT_INDETERMINATE_BOUND): Remove.
        * genmodes.cc (POLY_INT_INDETERMINATE_BOUND): Add default value
        of POLY_INT_INDETERMINATE_BOUND macro.
        * poly-int.h (maybe_upper_bound): New function.
        (maybe_lower_bound): Likewise.
        (maybe_le): Update to have extra flag to optionally use bound
        information for comparison.
        (maybe_lt): Likewise.
        (maybe_ge): Likewise.
        (maybe_gt): Likewise.
        (known_le): Likewise.
        (known_lt): Likewise.
        (known_gt): Likewise.
        (known_ge): Likewise.
        (ordered_p): Likewise.
        (ordered_min): Likewise.
        (ordered_max): Likewise.
        * target.def (poly_int_indeterminate_bound): Remove.
        * gimple-fold.cc (gimple_fold_builtin_memory_op): Change types
        of poly_int comparison arguments to be compatible.
        * emit-rtl.cc (widen_memory_access):  Likewise.
        * alias.cc (ao_ref_from_mem): Likewise.
        * ipa-modref-tree.cc (modref_access_node::contains): Likewise.
        * tree-ssa-alias.cc (indirect_ref_may_alias_decl_p):  Likewise.
        (indirect_refs_may_alias_p): Likewise.
        * tree-ssa-sccvn.cc (vn_reference_lookup_3): Likewise.
        * tree-vect-data-refs.cc (vect_compile_time_alias): Likewise.
        * value-query.cc (range_query::get_tree_range): Likewise.
---
 gcc/alias.cc                         |   3 +-
 gcc/config/aarch64/aarch64-modes.def |   4 +
 gcc/config/aarch64/aarch64.cc        |  12 --
 gcc/doc/tm.texi                      |   8 -
 gcc/doc/tm.texi.in                   |   2 -
 gcc/emit-rtl.cc                      |   5 +-
 gcc/genmodes.cc                      |  22 +++
 gcc/gimple-fold.cc                   |   8 +-
 gcc/ipa-modref-tree.cc               |   5 +-
 gcc/poly-int.h                       | 285 ++++++++++++++++++++++-----
 gcc/target.def                       |  10 -
 gcc/tree-ssa-alias.cc                |  16 +-
 gcc/tree-ssa-sccvn.cc                |   8 +-
 gcc/tree-vect-data-refs.cc           |  11 +-
 gcc/value-query.cc                   |  85 ++------
 15 files changed, 319 insertions(+), 165 deletions(-)

diff --git a/gcc/alias.cc b/gcc/alias.cc
index cee61b551d0..1513d2ef9fc 100644
--- a/gcc/alias.cc
+++ b/gcc/alias.cc
@@ -331,7 +331,8 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
              && (DECL_SIZE (ref->base) == NULL_TREE
                  || !poly_int_tree_p (DECL_SIZE (ref->base))
                  || maybe_lt (wi::to_poly_offset (DECL_SIZE (ref->base)),
-                              ref->offset + ref->size)))))
+                              poly_offset_int::from (ref->offset + ref->size,
+                                                     SIGNED))))))
     return false;
 
   return true;
diff --git a/gcc/config/aarch64/aarch64-modes.def 
b/gcc/config/aarch64/aarch64-modes.def
index fc005542866..06bb0254374 100644
--- a/gcc/config/aarch64/aarch64-modes.def
+++ b/gcc/config/aarch64/aarch64-modes.def
@@ -271,3 +271,7 @@ FLOAT_MODE (TF, 16, ieee_quad_format);
 /* Coefficient 1 is multiplied by the number of 128-bit chunks in an
    SVE vector (referred to as "VQ") minus one.  */
 #define NUM_POLY_INT_COEFFS 2
+
+#ifndef POLY_INT_INDETERMINATE_BOUND
+#define POLY_INT_INDETERMINATE_BOUND {0, 15}
+#endif
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 263c0afd4ab..b961833de02 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -31838,15 +31838,6 @@ aarch64_estimated_poly_value (poly_int64 val,
   return val.coeffs[0] + val.coeffs[1] * over_128 / 128;
 }
 
-/* Implement TARGET_POLY_INT_INDETERMINATE_BOUND.  */
-
-static poly_uint64
-aarch64_poly_int_indeterminate_bound ()
-{
-  return poly_uint64 (0, 15);
-}
-
-
 /* Return true for types that could be supported as SIMD return or
    argument types.  */
 
@@ -35246,9 +35237,6 @@ aarch64_libgcc_floating_mode_supported_p
 #undef TARGET_ESTIMATED_POLY_VALUE
 #define TARGET_ESTIMATED_POLY_VALUE aarch64_estimated_poly_value
 
-#undef TARGET_POLY_INT_INDETERMINATE_BOUND
-#define TARGET_POLY_INT_INDETERMINATE_BOUND 
aarch64_poly_int_indeterminate_bound
-
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE aarch64_attribute_table
 
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 65cf4c640e7..b92443e3d61 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -7529,14 +7529,6 @@ the @code{POLY_VALUE_MIN}, @code{POLY_VALUE_MAX} and
 implementation returns the lowest possible value of @var{val}.
 @end deftypefn
 
-@deftypefn {Target Hook} poly_uint64 TARGET_POLY_INT_INDETERMINATE_BOUND (void)
-Return a @code{poly_uint64} whose coefficients give conservative
-inclusive upper bounds for the corresponding @code{poly_int}
-indeterminates.  The constant coefficient is ignored and should be zero.
-This hook is used for correctness rather than for costing, so the returned
-bounds must be safe for all architecturally-valid runtime values.
-@end deftypefn
-
 @deftypefn {Target Hook} bool TARGET_AVOID_STORE_FORWARDING_P 
(vec<store_fwd_info>, @var{rtx}, @var{int}, @var{bool})
 Given a list of stores and a load instruction that reads from the location
 of the stores, this hook decides if it's profitable to emit additional code
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 6b8203c5bed..4ea2bb8e1d8 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -4806,8 +4806,6 @@ Define this macro if a non-short-circuit operation 
produced by
 
 @hook TARGET_ESTIMATED_POLY_VALUE
 
-@hook TARGET_POLY_INT_INDETERMINATE_BOUND
-
 @hook TARGET_AVOID_STORE_FORWARDING_P
 
 @node Scheduling
diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
index e76e0bbb264..21098da825b 100644
--- a/gcc/emit-rtl.cc
+++ b/gcc/emit-rtl.cc
@@ -2801,7 +2801,8 @@ widen_memory_access (rtx memref, machine_mode mode, 
poly_int64 offset)
          /* Is the field at least as large as the access?  If so, ok,
             otherwise strip back to the containing structure.  */
          if (poly_int_tree_p (DECL_SIZE_UNIT (field))
-             && known_ge (wi::to_poly_offset (DECL_SIZE_UNIT (field)), size)
+             && known_ge (wi::to_poly_offset (DECL_SIZE_UNIT (field)),
+                          poly_offset_int::from (size, UNSIGNED))
              && known_ge (attrs.offset, 0))
            break;
 
@@ -2822,7 +2823,7 @@ widen_memory_access (rtx memref, machine_mode mode, 
poly_int64 offset)
               && DECL_SIZE_UNIT (attrs.expr)
               && poly_int_tree_p (DECL_SIZE_UNIT (attrs.expr))
               && known_ge (wi::to_poly_offset (DECL_SIZE_UNIT (attrs.expr)),
-                          size)
+                          poly_offset_int::from (size, UNSIGNED))
               && known_ge (attrs.offset, 0))
        break;
       else
diff --git a/gcc/genmodes.cc b/gcc/genmodes.cc
index 7e5e061c2f3..64302be9b5f 100644
--- a/gcc/genmodes.cc
+++ b/gcc/genmodes.cc
@@ -859,6 +859,14 @@ create_modes (void)
 #define NUM_POLY_INT_COEFFS 1
 #endif
 
+#ifndef POLY_INT_INDETERMINATE_BOUND
+#if NUM_POLY_INT_COEFFS == 2
+#define POLY_INT_INDETERMINATE_BOUND {0, (unsigned int) -1}
+#else
+#define POLY_INT_INDETERMINATE_BOUND {0}
+#endif
+#endif
+
 /* Processing.  */
 
 /* Sort a list of modes into the order needed for the WIDER field:
@@ -1399,6 +1407,20 @@ enum machine_mode\n{");
 
   printf ("#define NUM_POLY_INT_COEFFS %d\n", NUM_POLY_INT_COEFFS);
 
+  unsigned int indeterminate_bound[NUM_POLY_INT_COEFFS]
+    = POLY_INT_INDETERMINATE_BOUND;
+    printf ("#ifndef POLY_INT_INDETERMINATE_BOUND\n");
+  if (NUM_POLY_INT_COEFFS == 1)
+    printf ("#define POLY_INT_INDETERMINATE_BOUND {%u}\n",
+           indeterminate_bound[0]);
+  else if (NUM_POLY_INT_COEFFS == 2)
+    printf ("#define POLY_INT_INDETERMINATE_BOUND {%u, %u}\n",
+           indeterminate_bound[0], indeterminate_bound[1]);
+  else
+    internal_error ("Unsupported NUM_POLY_INT_COEFFS value '%d'",
+                   NUM_POLY_INT_COEFFS);
+  printf ("#endif\n");
+
   puts ("\
 \n\
 #endif /* insn-modes.h */");
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 9bc88da352b..4fb3d0a38be 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -1127,8 +1127,12 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
                    = mem_ref_offset (src_base) + src_offset;
                  poly_offset_int full_dest_offset
                    = mem_ref_offset (dest_base) + dest_offset;
-                 if (ranges_maybe_overlap_p (full_src_offset, maxsize,
-                                             full_dest_offset, maxsize))
+                 if (ranges_maybe_overlap_p (full_src_offset,
+                                             poly_offset_int::from (maxsize,
+                                                                    UNSIGNED),
+                                             full_dest_offset,
+                                             poly_offset_int::from (maxsize,
+                                                                    UNSIGNED)))
                    return false;
                }
              else
diff --git a/gcc/ipa-modref-tree.cc b/gcc/ipa-modref-tree.cc
index 73faa919b6c..75b50c62ae9 100644
--- a/gcc/ipa-modref-tree.cc
+++ b/gcc/ipa-modref-tree.cc
@@ -98,9 +98,10 @@ modref_access_node::contains (const modref_access_node &a) 
const
        return false;
       if (known_size_p (max_size))
        return known_subrange_p (poly_offset_int::from (a.offset, SIGNED)
-                                + aoffset_adj, a.max_size,
+                                + aoffset_adj,
+                                poly_offset_int::from (a.max_size, SIGNED),
                                 poly_offset_int::from (offset, SIGNED),
-                                max_size);
+                                poly_offset_int::from (max_size, SIGNED));
       else
        return known_le (poly_offset_int::from (offset, SIGNED),
                         poly_offset_int::from (a.offset, SIGNED)
diff --git a/gcc/poly-int.h b/gcc/poly-int.h
index 01bc5cc5c17..2c93776c3bf 100644
--- a/gcc/poly-int.h
+++ b/gcc/poly-int.h
@@ -1121,6 +1121,90 @@ sext_hwi (const poly_int<N, C> &a, unsigned int 
precision)
   return r;
 }
 
+template <unsigned int N, typename Ca>
+inline bool
+maybe_upper_bound (const poly_int<N, Ca> &a,
+                  WI_BINARY_RESULT (Ca, WI_BINARY_RESULT (Ca, unsigned int))
+                    * res,
+                  signop sgn)
+{
+  typedef WI_BINARY_RESULT (Ca, unsigned int) C1;
+  typedef WI_BINARY_RESULT (Ca, C1) Cr;
+
+  if (N > 2)
+    return false;
+
+  wi::overflow_type ovf = wi::OVF_NONE;
+  if (N < 2 || wi::neg_p (a.coeffs[1], sgn)
+      || wi::eq_p (a.coeffs[1], wi::ints_for<Ca>::zero (a.coeffs[1])))
+    {
+      Cr temp2 = wi::add (a.coeffs[0], wi::ints_for<C1>::zero (a.coeffs[0]),
+                         sgn, &ovf);
+      gcc_assert (ovf == wi::OVF_NONE);
+      *res = temp2;
+      return true;
+    }
+
+  if (N != NUM_POLY_INT_COEFFS)
+    return false;
+  const unsigned int indeterminate_bound[NUM_POLY_INT_COEFFS]
+    = POLY_INT_INDETERMINATE_BOUND;
+
+  if (indeterminate_bound[1] == (unsigned int) -1)
+    return false;
+
+  C1 temp1 = wi::mul (a.coeffs[1], indeterminate_bound[1], sgn, &ovf);
+  if (ovf != wi::OVF_NONE)
+    return false;
+  Cr temp2 = wi::add (a.coeffs[0], temp1, sgn, &ovf);
+  if (ovf != wi::OVF_NONE)
+    return false;
+
+  *res = temp2;
+  return true;
+}
+
+template <unsigned int N, typename Ca>
+inline bool
+maybe_lower_bound (const poly_int<N, Ca> &a,
+                  WI_BINARY_RESULT (Ca, WI_BINARY_RESULT (Ca, unsigned int))
+                    * res,
+                  signop sgn)
+{
+  typedef WI_BINARY_RESULT (Ca, unsigned int) C1;
+  typedef WI_BINARY_RESULT (Ca, C1) Cr;
+
+  if (N > 2)
+    return false;
+
+  wi::overflow_type ovf = wi::OVF_NONE;
+  if (N < 2 || !wi::neg_p (a.coeffs[1], sgn))
+    {
+      Cr temp2 = wi::add (a.coeffs[0], wi::ints_for<C1>::zero (a.coeffs[0]),
+                         sgn, &ovf);
+      gcc_assert (ovf == wi::OVF_NONE);
+      *res = temp2;
+      return true;
+    }
+
+  if (N != NUM_POLY_INT_COEFFS)
+    return false;
+  const unsigned int indeterminate_bound[NUM_POLY_INT_COEFFS]
+    = POLY_INT_INDETERMINATE_BOUND;
+
+  if (indeterminate_bound[1] == (unsigned int) -1)
+    return false;
+
+  C1 temp1 = wi::mul (a.coeffs[1], indeterminate_bound[1], sgn, &ovf);
+  if (ovf != wi::OVF_NONE)
+    return false;
+  Cr temp2 = wi::add (a.coeffs[0], temp1, sgn, &ovf);
+  if (ovf != wi::OVF_NONE)
+    return false;
+
+  *res = temp2;
+  return true;
+}
 
 /* Return true if a0 + a1 * x might equal b0 + b1 * x for some nonnegative
    integer x.  */
@@ -1253,10 +1337,27 @@ maybe_ne (const Ca &a, const Cb &b)
 /* Return true if A might be less than or equal to B for some
    indeterminate values.  */
 
-template<unsigned int N, typename Ca, typename Cb>
+template <unsigned int N, typename Ca, typename Cb>
 inline bool
-maybe_le (const poly_int<N, Ca> &a, const poly_int<N, Cb> &b)
-{
+maybe_le (const poly_int<N, Ca> &a, const poly_int<N, Cb> &b,
+         bool strict = true)
+{
+  typedef WI_BINARY_RESULT (Ca, unsigned int) type_a;
+  typedef WI_BINARY_RESULT (Cb, unsigned int) type_b;
+
+  signop sgn = (poly_coeff_traits<type_a>::signedness == 1
+                   || poly_coeff_traits<type_b>::signedness == 1
+                 ? SIGNED
+                 : UNSIGNED);
+
+  type_a a_lower_bound = 0;
+  type_b b_upper_bound = 0;
+  if (!strict
+      && maybe_lower_bound (a, &a_lower_bound, sgn)
+      && maybe_upper_bound (b, &b_upper_bound, sgn)
+      && wi::gt_p (a_lower_bound, b_upper_bound, sgn))
+    return false;
+
   if (N >= 2)
     for (unsigned int i = 1; i < N; i++)
       if (a.coeffs[i] < b.coeffs[i])
@@ -1264,10 +1365,20 @@ maybe_le (const poly_int<N, Ca> &a, const poly_int<N, 
Cb> &b)
   return a.coeffs[0] <= b.coeffs[0];
 }
 
-template<unsigned int N, typename Ca, typename Cb>
+template <unsigned int N, typename Ca, typename Cb>
 inline typename if_nonpoly<Cb, bool>::type
-maybe_le (const poly_int<N, Ca> &a, const Cb &b)
+maybe_le (const poly_int<N, Ca> &a, const Cb &b,
+         bool strict = true)
 {
+  typedef WI_BINARY_RESULT (Ca, unsigned int) type_a;
+  signop sgn = (poly_coeff_traits<type_a>::signedness == 1 ? SIGNED : 
UNSIGNED);
+
+  type_a a_lower_bound = 0;
+  if (!strict
+      && maybe_lower_bound (a, &a_lower_bound, sgn)
+      && wi::gt_p (a_lower_bound, b, sgn))
+    return false;
+
   if (N >= 2)
     for (unsigned int i = 1; i < N; i++)
       if (a.coeffs[i] < 0)
@@ -1275,10 +1386,20 @@ maybe_le (const poly_int<N, Ca> &a, const Cb &b)
   return a.coeffs[0] <= b;
 }
 
-template<unsigned int N, typename Ca, typename Cb>
+template <unsigned int N, typename Ca, typename Cb>
 inline typename if_nonpoly<Ca, bool>::type
-maybe_le (const Ca &a, const poly_int<N, Cb> &b)
+maybe_le (const Ca &a, const poly_int<N, Cb> &b,
+         bool strict = true)
 {
+  typedef WI_BINARY_RESULT (Cb, unsigned int) type_b;
+  signop sgn = (poly_coeff_traits<type_b>::signedness == 1 ? SIGNED : 
UNSIGNED);
+
+  type_b b_upper_bound = 0;
+  if (!strict
+      && maybe_upper_bound (b, &b_upper_bound, sgn)
+      && wi::gt_p (a, b_upper_bound, sgn))
+    return false;
+
   if (N >= 2)
     for (unsigned int i = 1; i < N; i++)
       if (b.coeffs[i] > 0)
@@ -1286,19 +1407,36 @@ maybe_le (const Ca &a, const poly_int<N, Cb> &b)
   return a <= b.coeffs[0];
 }
 
-template<typename Ca, typename Cb>
+template <typename Ca, typename Cb>
 inline typename if_nonpoly2<Ca, Cb, bool>::type
-maybe_le (const Ca &a, const Cb &b)
+maybe_le (const Ca &a, const Cb &b, bool = true)
 {
   return a <= b;
 }
 
-/* Return true if A might be less than B for some indeterminate values.  */
+/* Return true if all the coefficients of a A are less than the respective
+   coefficient in B.  */
 
-template<unsigned int N, typename Ca, typename Cb>
+template <unsigned int N, typename Ca, typename Cb>
 inline bool
-maybe_lt (const poly_int<N, Ca> &a, const poly_int<N, Cb> &b)
-{
+maybe_lt (const poly_int<N, Ca> &a, const poly_int<N, Cb> &b,
+         bool strict = true)
+{
+  typedef WI_BINARY_RESULT (Ca, unsigned int) type_a;
+  typedef WI_BINARY_RESULT (Cb, unsigned int) type_b;
+  signop sgn = (poly_coeff_traits<type_a>::signedness == 1
+                   || poly_coeff_traits<type_b>::signedness == 1
+                 ? SIGNED
+                 : UNSIGNED);
+
+  type_a a_lower_bound = 0;
+  type_b b_upper_bound = 0;
+  if (!strict
+      && maybe_lower_bound (a, &a_lower_bound, sgn)
+      && maybe_upper_bound (b, &b_upper_bound, sgn)
+      && wi::ge_p (a_lower_bound, b_upper_bound, sgn))
+    return false;
+
   if (N >= 2)
     for (unsigned int i = 1; i < N; i++)
       if (a.coeffs[i] < b.coeffs[i])
@@ -1306,10 +1444,20 @@ maybe_lt (const poly_int<N, Ca> &a, const poly_int<N, 
Cb> &b)
   return a.coeffs[0] < b.coeffs[0];
 }
 
-template<unsigned int N, typename Ca, typename Cb>
+template <unsigned int N, typename Ca, typename Cb>
 inline typename if_nonpoly<Cb, bool>::type
-maybe_lt (const poly_int<N, Ca> &a, const Cb &b)
+maybe_lt (const poly_int<N, Ca> &a, const Cb &b,
+         bool strict = true)
 {
+  typedef WI_BINARY_RESULT (Ca, unsigned int) type_a;
+  signop sgn = (poly_coeff_traits<type_a>::signedness == 1 ? SIGNED : 
UNSIGNED);
+
+  type_a a_lower_bound = 0;
+  if (!strict
+      && maybe_lower_bound (a, &a_lower_bound, sgn)
+      && wi::ge_p (a_lower_bound, b, sgn))
+    return false;
+
   if (N >= 2)
     for (unsigned int i = 1; i < N; i++)
       if (a.coeffs[i] < 0)
@@ -1317,10 +1465,20 @@ maybe_lt (const poly_int<N, Ca> &a, const Cb &b)
   return a.coeffs[0] < b;
 }
 
-template<unsigned int N, typename Ca, typename Cb>
+template <unsigned int N, typename Ca, typename Cb>
 inline typename if_nonpoly<Ca, bool>::type
-maybe_lt (const Ca &a, const poly_int<N, Cb> &b)
+maybe_lt (const Ca &a, const poly_int<N, Cb> &b,
+         bool strict = true)
 {
+  typedef WI_BINARY_RESULT (Cb, unsigned int) type_b;
+  signop sgn = (poly_coeff_traits<type_b>::signedness == 1 ? SIGNED : 
UNSIGNED);
+
+  type_b b_upper_bound = 0;
+  if (!strict
+      && maybe_upper_bound (b, &b_upper_bound, sgn)
+      && wi::ge_p (a, b_upper_bound, sgn))
+    return false;
+
   if (N >= 2)
     for (unsigned int i = 1; i < N; i++)
       if (b.coeffs[i] > 0)
@@ -1330,39 +1488,70 @@ maybe_lt (const Ca &a, const poly_int<N, Cb> &b)
 
 template<typename Ca, typename Cb>
 inline typename if_nonpoly2<Ca, Cb, bool>::type
-maybe_lt (const Ca &a, const Cb &b)
+maybe_lt (const Ca &a, const Cb &b,
+         bool = true)
 {
   return a < b;
 }
 
 /* Return true if A may be greater than or equal to B.  */
-#define maybe_ge(A, B) maybe_le (B, A)
+template <typename Ca, typename Cb>
+inline bool
+maybe_ge (const Ca &a, const Cb &b, bool strict = true)
+{
+  return maybe_le (b, a, strict);
+}
 
 /* Return true if A may be greater than B.  */
-#define maybe_gt(A, B) maybe_lt (B, A)
+template <typename Ca, typename Cb>
+inline bool
+maybe_gt (const Ca &a, const Cb &b, bool strict = true)
+{
+  return maybe_lt (b, a, strict);
+}
 
 /* Return true if A is known to be less than or equal to B.  */
-#define known_le(A, B) (!maybe_gt (A, B))
+template <typename Ca, typename Cb>
+inline bool
+known_le (const Ca &a, const Cb &b, bool strict = true)
+{
+  return !maybe_gt (a, b, strict);
+}
 
 /* Return true if A is known to be less than B.  */
-#define known_lt(A, B) (!maybe_ge (A, B))
+template <typename Ca, typename Cb>
+inline bool
+known_lt (const Ca &a, const Cb &b, bool strict = true)
+{
+  return !maybe_ge (a, b, strict);
+}
 
 /* Return true if A is known to be greater than B.  */
-#define known_gt(A, B) (!maybe_le (A, B))
+template <typename Ca, typename Cb>
+inline bool
+known_gt (const Ca &a, const Cb &b, bool strict = true)
+{
+  return !maybe_le (a, b, strict);
+}
 
 /* Return true if A is known to be greater than or equal to B.  */
-#define known_ge(A, B) (!maybe_lt (A, B))
+template <typename Ca, typename Cb>
+inline bool
+known_ge (const Ca &a, const Cb &b, bool strict = true)
+{
+  return !maybe_lt (a, b, strict);
+}
 
 /* Return true if A and B are ordered by the partial ordering known_le.  */
 
-template<typename T1, typename T2>
+template <typename T1, typename T2>
 inline bool
-ordered_p (const T1 &a, const T2 &b)
+ordered_p (const T1 &a, const T2 &b, bool strict = true)
 {
   return ((poly_int_traits<T1>::num_coeffs == 1
           && poly_int_traits<T2>::num_coeffs == 1)
-         || known_le (a, b)
-         || known_le (b, a));
+         || known_le (a, b, strict)
+         || known_le (b, a, strict));
 }
 
 /* Assert that A and B are known to be ordered and return the minimum
@@ -1371,44 +1560,45 @@ ordered_p (const T1 &a, const T2 &b)
    NOTE: When using this function, please add a comment above the call
    explaining why we know the values are ordered in that context.  */
 
-template<unsigned int N, typename Ca, typename Cb>
+template <unsigned int N, typename Ca, typename Cb>
 inline POLY_POLY_RESULT (N, Ca, Cb)
-ordered_min (const poly_int<N, Ca> &a, const poly_int<N, Cb> &b)
+ordered_min (const poly_int<N, Ca> &a, const poly_int<N, Cb> &b,
+            bool strict = true)
 {
-  if (known_le (a, b))
+  if (known_le (a, b, strict))
     return a;
   else
     {
       if (N > 1)
-       gcc_checking_assert (known_le (b, a));
+       gcc_checking_assert (known_le (b, a, strict));
       return b;
     }
 }
 
 template<unsigned int N, typename Ca, typename Cb>
 inline CONST_POLY_RESULT (N, Ca, Cb)
-ordered_min (const Ca &a, const poly_int<N, Cb> &b)
+ordered_min (const Ca &a, const poly_int<N, Cb> &b, bool strict = true)
 {
-  if (known_le (a, b))
+  if (known_le (a, b, strict))
     return a;
   else
     {
       if (N > 1)
-       gcc_checking_assert (known_le (b, a));
+       gcc_checking_assert (known_le (b, a, strict));
       return b;
     }
 }
 
 template<unsigned int N, typename Ca, typename Cb>
 inline POLY_CONST_RESULT (N, Ca, Cb)
-ordered_min (const poly_int<N, Ca> &a, const Cb &b)
+ordered_min (const poly_int<N, Ca> &a, const Cb &b, bool strict = true)
 {
-  if (known_le (a, b))
+  if (known_le (a, b, strict))
     return a;
   else
     {
       if (N > 1)
-       gcc_checking_assert (known_le (b, a));
+       gcc_checking_assert (known_le (b, a, strict));
       return b;
     }
 }
@@ -1421,42 +1611,43 @@ ordered_min (const poly_int<N, Ca> &a, const Cb &b)
 
 template<unsigned int N, typename Ca, typename Cb>
 inline POLY_POLY_RESULT (N, Ca, Cb)
-ordered_max (const poly_int<N, Ca> &a, const poly_int<N, Cb> &b)
+ordered_max (const poly_int<N, Ca> &a, const poly_int<N, Cb> &b,
+            bool strict = true)
 {
-  if (known_le (a, b))
+  if (known_le (a, b, strict))
     return b;
   else
     {
       if (N > 1)
-       gcc_checking_assert (known_le (b, a));
+       gcc_checking_assert (known_le (b, a, strict));
       return a;
     }
 }
 
 template<unsigned int N, typename Ca, typename Cb>
 inline CONST_POLY_RESULT (N, Ca, Cb)
-ordered_max (const Ca &a, const poly_int<N, Cb> &b)
+ordered_max (const Ca &a, const poly_int<N, Cb> &b, bool strict = true)
 {
-  if (known_le (a, b))
+  if (known_le (a, b, strict))
     return b;
   else
     {
       if (N > 1)
-       gcc_checking_assert (known_le (b, a));
+       gcc_checking_assert (known_le (b, a, strict));
       return a;
     }
 }
 
 template<unsigned int N, typename Ca, typename Cb>
 inline POLY_CONST_RESULT (N, Ca, Cb)
-ordered_max (const poly_int<N, Ca> &a, const Cb &b)
+ordered_max (const poly_int<N, Ca> &a, const Cb &b, bool strict = true)
 {
-  if (known_le (a, b))
+  if (known_le (a, b, strict))
     return b;
   else
     {
       if (N > 1)
-       gcc_checking_assert (known_le (b, a));
+       gcc_checking_assert (known_le (b, a, strict));
       return a;
     }
 }
diff --git a/gcc/target.def b/gcc/target.def
index 877bd166b23..b12204a669f 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -4294,16 +4294,6 @@ implementation returns the lowest possible value of 
@var{val}.",
  HOST_WIDE_INT, (poly_int64 val, poly_value_estimate_kind kind),
  default_estimated_poly_value)
 
-DEFHOOK
-(poly_int_indeterminate_bound,
- "Return a @code{poly_uint64} whose coefficients give conservative\n\
-inclusive upper bounds for the corresponding @code{poly_int}\n\
-indeterminates.  The constant coefficient is ignored and should be zero.\n\
-This hook is used for correctness rather than for costing, so the returned\n\
-bounds must be safe for all architecturally-valid runtime values.",
- poly_uint64, (void),
- NULL)
-
 /* Permit speculative instructions in delay slots during delayed-branch
    scheduling.  */
 DEFHOOK
diff --git a/gcc/tree-ssa-alias.cc b/gcc/tree-ssa-alias.cc
index 41072b4d5d9..f87803dd1cd 100644
--- a/gcc/tree-ssa-alias.cc
+++ b/gcc/tree-ssa-alias.cc
@@ -2148,7 +2148,9 @@ indirect_ref_may_alias_decl_p (tree ref1 
ATTRIBUTE_UNUSED, tree base1,
      ???  IVOPTs creates bases that do not honor this restriction,
      so do not apply this optimization for TARGET_MEM_REFs.  */
   if (TREE_CODE (base1) != TARGET_MEM_REF
-      && !ranges_maybe_overlap_p (offset1 + moff, -1, offset2, max_size2))
+      && !ranges_maybe_overlap_p (offset1 + moff, poly_offset_int (-1),
+                                 poly_offset_int::from (offset2, SIGNED),
+                                 poly_offset_int::from (max_size2, SIGNED)))
     return false;
 
   /* If the pointer based access is bigger than the variable they cannot
@@ -2249,7 +2251,11 @@ indirect_ref_may_alias_decl_p (tree ref1 
ATTRIBUTE_UNUSED, tree base1,
                              && TREE_CODE (TYPE_SIZE (TREE_TYPE (base1)))
                                 != INTEGER_CST));
       if (!partial_overlap
-         && !ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2))
+         && !ranges_maybe_overlap_p (poly_offset_int::from (doffset1, SIGNED),
+                                     poly_offset_int::from (max_size1, SIGNED),
+                                     doffset2,
+                                     poly_offset_int::from (max_size2,
+                                                            SIGNED)))
        return false;
       if (!ref1 || !ref2
          /* If there is must alias, there is no use disambiguating further.  */
@@ -2333,8 +2339,10 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, 
tree base1,
     {
       poly_offset_int moff1 = mem_ref_offset (base1) << LOG2_BITS_PER_UNIT;
       poly_offset_int moff2 = mem_ref_offset (base2) << LOG2_BITS_PER_UNIT;
-      if (!ranges_maybe_overlap_p (offset1 + moff1, max_size1,
-                                  offset2 + moff2, max_size2))
+      if (!ranges_maybe_overlap_p (offset1 + moff1,
+                                  poly_offset_int::from (max_size1, SIGNED),
+                                  offset2 + moff2,
+                                  poly_offset_int::from (max_size2, SIGNED)))
        return false;
       /* If there is must alias, there is no use disambiguating further.  */
       if (known_eq (size1, max_size1) && known_eq (size2, max_size2))
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index f8a68d4e4fd..758c3404bfa 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -3094,12 +3094,16 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void 
*data_,
        len = SSA_VAL (len);
       /* Sometimes the above trickery is smarter than alias analysis.  Take
          advantage of that.  */
-      if (!ranges_maybe_overlap_p (offset, maxsize, offset2,
+      if (!ranges_maybe_overlap_p (poly_offset_int::from (offset, SIGNED),
+                                  poly_offset_int::from (maxsize, SIGNED),
+                                  poly_offset_int::from (offset2, SIGNED),
                                   (wi::to_poly_offset (len)
                                    << LOG2_BITS_PER_UNIT)))
        return NULL;
       if (data->partial_defs.is_empty ()
-         && known_subrange_p (offset, maxsize, offset2,
+         && known_subrange_p (poly_offset_int::from (offset, SIGNED),
+                              poly_offset_int::from (maxsize, SIGNED),
+                              poly_offset_int::from (offset2, SIGNED),
                               wi::to_poly_offset (len) << LOG2_BITS_PER_UNIT))
        {
          tree val;
diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index 08b94149e7c..e213869af57 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -3924,12 +3924,15 @@ vect_compile_time_alias (dr_vec_info *a, dr_vec_info *b,
   const_length_a += access_size_a;
   const_length_b += access_size_b;
 
-  if (ranges_known_overlap_p (offset_a, const_length_a,
-                             offset_b, const_length_b))
+  if (ranges_known_overlap_p (offset_a,
+                             poly_offset_int::from (const_length_a, UNSIGNED),
+                             offset_b,
+                             poly_offset_int::from (const_length_b, UNSIGNED)))
     return 1;
 
-  if (!ranges_maybe_overlap_p (offset_a, const_length_a,
-                              offset_b, const_length_b))
+  if (!ranges_maybe_overlap_p (
+       offset_a, poly_offset_int::from (const_length_a, UNSIGNED), offset_b,
+       poly_offset_int::from (const_length_b, UNSIGNED)))
     return 0;
 
   return -1;
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index 0a6de62d763..8b3d607f0e0 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -442,86 +442,33 @@ range_query::get_tree_range (vrange &r, tree expr, gimple 
*stmt,
        {
          unsigned int precision = TYPE_PRECISION (type);
          signop sign = TYPE_SIGN (type);
-         bool have_poly_bound = targetm.poly_int_indeterminate_bound;
-         poly_uint64 indeterminate_bound;
-
-         if (have_poly_bound)
-           indeterminate_bound = targetm.poly_int_indeterminate_bound ();
 
          auto val = wi::to_poly_wide (expr);
          auto type_min = wi::to_wide (TYPE_MIN_VALUE (type));
          auto type_max = wi::to_wide (TYPE_MAX_VALUE (type));
 
-         /* Start with the invariant part of the poly-int, then account
-            for each coefficient below.
-
-            The target hook gives a per-coefficient upper bound for the
-            indeterminate.  Since those indeterminates are unsigned and
-            nonnegative, a positive coefficient can only increase the upper
-            bound and a negative coefficient can only decrease the lower
-            bound.  The opposite bound is unaffected by that coefficient:
-
-               [A, +C] with C >= 0  => max += C * bound
-               [A, -C] with C >= 0  => min -= C * bound.  */
-         wide_int bounds[2] = { val.coeffs[0], val.coeffs[0] };
-         bool ovf[2] = { false, false };
+         wide_int lower_bound = type_min;
+         wide_int upper_bound = type_max;
 
-         for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
+         if (!maybe_lower_bound (val, &lower_bound, sign)
+             || wi::lt_p (lower_bound, type_min, sign)
+             || wi::gt_p (lower_bound, type_max, sign)
+             || !maybe_upper_bound (val, &upper_bound, sign)
+             || wi::lt_p (upper_bound, type_min, sign)
+             || wi::gt_p (upper_bound, type_max, sign))
            {
-             const auto &coeff = val.coeffs[i];
-             if (wi::eq_p (coeff, 0))
-               continue;
-
-             /* Select the only bound affected by this coefficient.  A
-                negative coefficient contributes to the minimum and a positive
-                coefficient contributes to the maximum.  */
-             bool coeff_neg = wi::neg_p (coeff, sign);
-             wide_int &bound = bounds[coeff_neg ? 0 : 1];
-             bool &bound_ovf = ovf[coeff_neg ? 0 : 1];
-
-             if (bound_ovf)
-               continue;
-
-             /* A missing hook, or a -1 bound for this coefficient, means the
-                indeterminate has no finite target-specific limit.  Treat that
-                like an overflow of the affected bound.  */
-             if (!have_poly_bound
-                 || indeterminate_bound.coeffs[i] == HOST_WIDE_INT_M1U)
-               bound_ovf = true;
-             else
-               {
-                 auto indeterminate
-                   = wi::uhwi (indeterminate_bound.coeffs[i], precision);
-                 wi::overflow_type mul_ovf = wi::OVF_NONE;
-                 auto term = wi::mul (coeff, indeterminate, sign, &mul_ovf);
-                 wi::overflow_type add_ovf = wi::OVF_NONE;
-                 bound = wi::add (bound, term, sign, &add_ovf);
-                 bound_ovf = (mul_ovf != wi::OVF_NONE
-                              || add_ovf != wi::OVF_NONE);
-               }
-
-             if (TYPE_OVERFLOW_WRAPS (type) && bound_ovf)
-               {
-                 r.set_varying (type);
-                 r.update_bitmask (irange_bitmask (wi::zero (precision),
-                                                   get_nonzero_bits (expr)));
-                 return true;
-               }
-
-             if (bound_ovf)
-               {
-                 if (coeff_neg)
-                   bounds[0] = type_min;
-                 else
-                   bounds[1] = type_max;
-               }
+             /* Overflow risk, so no known bounds.  */
+             r.set_varying (type);
+             r.update_bitmask (
+               irange_bitmask (wi::zero (precision), get_nonzero_bits (expr)));
+             return true;
            }
 
          /* Check that the target filled in sensible bounds information.  */
-         gcc_assert (wi::le_p (bounds[0], bounds[1], sign));
+         gcc_assert (wi::le_p (lower_bound, upper_bound, sign));
 
-         irange &ir = as_a <irange> (r);
-         ir.set (type, bounds[0], bounds[1]);
+         irange &ir = as_a<irange> (r);
+         ir.set (type, lower_bound, upper_bound);
 
          /* Preserve alignment/step information that is not visible in the
             intervals.  For example, a poly-int like [8, 8] can
-- 
2.56.0

Reply via email to