#include <cmath> bool foo(double x) { return std::copysign(1., x) < 0.; } bool bar(double x) { return std::signbit(x); } https://godbolt.org/z/xPMzj9
I'm not sure those are equivalent if x is nan.
Err nevermind I guess they would be.
Not sure if Alive2 understands copysign (the LLVM instance seems to be dead currently). As IR, we have: define i1 @PR49179(double %x) { %s = tail call double @llvm.copysign.f64(double 1.0, double %x) %r = fcmp olt double %s, 0.0 ret i1 %r } And we want to turn it into: %2 = bitcast double %0 to i64 %3 = icmp slt i64 %2, 0 So to generalize (this pattern was found in source code in the wild?): "1.0" can be any non-zero number and "0.0" could also be "-0.0"?
> this pattern was found in source code in the wild? https://gitlab.gnome.org/GNOME/glib/-/blob/2.64.1/glib/gnulib/signbitd.c#L46 https://github.com/boostorg/core/blob/ddbaa242a99f62eda6aa9db1e3abc0c4bc36134f/include/boost/core/cmath.hpp#L70 https://stackoverflow.com/a/1905142
(In reply to Nikita Kniazev from comment #4) > > this pattern was found in source code in the wild? > > https://gitlab.gnome.org/GNOME/glib/-/blob/2.64.1/glib/gnulib/signbitd.c#L46 > https://github.com/boostorg/core/blob/ > ddbaa242a99f62eda6aa9db1e3abc0c4bc36134f/include/boost/core/cmath.hpp#L70 > https://stackoverflow.com/a/1905142 Thanks for the links! So the "1.0" and "0.0" are the important special-cases to handle. We probably don't need to fully generalize (it would get complicated if we try to handle zeros/NaN as the copysign argument, arbitrary compare predicates, and arbitrary compare constants).
Should be fixed in IR with: https://reviews.llvm.org/rG85294703a74a We have seen complications with these kinds of transforms because LLVM supports non-IEEE754-compliant targets, but I think this is always ok. If not, we'll have to move the transform to the backend. As noted in the comments, if variations of the specified pattern are found, please file other bugs. And finally (it's not clear from the description if we care about a particular target), if the performance is still not optimal, we may need to adjust codegen too. For x86, I'm seeing something like this currently: movmskpd %xmm0, %eax andl $1, %eax