Hi Aldy, The proposed frange implementation looks cool. The one technical tweak is that if x is not NaN and not +Inf/-Inf, then x*0.0 is [-0.0,0.0]. It's because this result is a range and not a constant that it can’t normally be constant folded, unless it appears in a context where the sign of zero isn't important (such as a comparison).
I suspect that frange needs pos_zero_p, neg_zero_p and any_zero_p instead of just zero_p (and variants r.set_zero) to capture the subtleties. Cheers, Roger -- > -----Original Message----- > From: Aldy Hernandez <al...@redhat.com> > Sent: 21 March 2022 05:56 > To: Jeff Law <jeffreya...@gmail.com> > Cc: Andrew MacLeod <amacl...@redhat.com>; Roger Sayle > <ro...@nextmovesoftware.com>; Richard Biener > <richard.guent...@gmail.com>; GCC Patches <gcc-patches@gcc.gnu.org> > Subject: Re: [PATCH] Ignore (possible) signed zeros in operands of FP > comparisons. > > On Fri, Mar 18, 2022 at 7:33 PM Aldy Hernandez <al...@redhat.com> wrote: > > > > >>>>> Consider the following interesting example: > > > >>>>> > > > >>>>> int foo(int x, double y) { > > > >>>>> return (x * 0.0) < y; > > > >>>>> } > > > >>>>> > > > >>>>> Although we know that x (when converted to double) can't be > > > >>>>> NaN or Inf, we still worry that for negative values of x that > > > >>>>> (x * 0.0) may be -0.0 and so perform the multiplication at > > > >>>>> run-time. But in this case, the result of the comparison (-0.0 > > > >>>>> < y) will be exactly the same as (+0.0 < y) for any y, hence > > > >>>>> the above may be safely constant folded to "0.0 < > > > >>>> y" > > > >>>>> avoiding the multiplication at run-time. > > Ok, once the "frange" infrastructure is in place, it's actually trivial. See > attached > patch and tests. We can do everything with small range-op entries and evrp / > ranger will handle everything else. > > Roger, I believe this is what you described: > > +// { dg-do compile } > +// { dg-options "-O2 -fno-tree-forwprop -fno-thread-jumps > -fdump-tree-evrp -fdump-tree-optimized" } > + > +extern void link_error (); > + > +int foo(int x, double y) > +{ > + return (x * 0.0) < y; > +} > + > +// The multiply should be gone by *vrp time. > +// { dg-final { scan-tree-dump-not " \\* " "evrp" } } > + > +// Ultimately, there sound be no references to "x". > +// { dg-final { scan-tree-dump-not "x_" "optimized" } } > > With the attached patch (and pending patches), we keep track that a cast from > int to float is guaranteed to not be NaN, which allows us to fold x*0.0 into > 0.0, > and DCE to remove x altogether. Also, as the other tests show, we are able to > resolve __builtin_isnan's for the operations implemented. It should be > straightforward for someone with floating point foo to extend this to all > operations. > > Aldy