On Fri, Mar 18, 2022 at 7:33 PM Aldy Hernandez 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