On Thu, Nov 27, 2025 at 02:32:42PM +0100, Richard Biener wrote:
> > +#if GIMPLE
> > +/* (y << x) {<,<=} x -> false and (y << x) {>,>=} x -> true when y != 0
> > + and (y << x) >> x == y and for signed comparison (y << x) >= 0. */
> > +(for cmp (gt ge lt le)
> > + (simplify
> > + (cmp:c (nop_convert1?@3 (lshift@2 @0 @1)) (convert2? @1))
> > + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
> > + (with { bool ok = false;
> > + int_range_max vr0, vr1;
> > + if (gimple_match_range_of_expr (vr0, @0, @2)
> > + && !vr0.varying_p ()
> > + && !vr0.undefined_p ()
>
> I guess the varying and undefined checks could be put into
> gimple_match_range_of_expr as well?
Agreed about the undefined_p stuff, for varying_p I'd defer to the callers,
sometimes they are ok even with VARYING, depends on what exactly they use it
for. Checking !vrN.varying_p () here isn't really necessary, just that
if it is varying, testing the rest is a waste of compile time, it will
vr0 surely contain zero in that case and lz will be 0, and for the shift
count it will not be smaller than lz + uns.
Jakub