On Wed, Nov 11, 2026 at 8:56 PM Andrea Pinski
<[email protected]> wrote:
>
> On Wed, Nov 11, 2026 at 9:08 AM Alfie Richards <[email protected]> wrote:
> >
> > 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.
>
> NAK. We should moving towards target hooks from target macros.
And you didn't add documentation for the new target macro
POLY_INT_INDETERMINATE_BOUND either.
Maybe you could still make a target variable as part of the target
hook like unwind_emit_before_insn is done. Then it is just a load
instead. Would that be ok for performance?
Thanks,
Andrea
>
> >
> > 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
> >