Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing copysign(1., x) < 0. to std::signbit(x) fold #48523

Closed
Kojoley opened this issue Feb 14, 2021 · 6 comments
Closed

Missing copysign(1., x) < 0. to std::signbit(x) fold #48523

Kojoley opened this issue Feb 14, 2021 · 6 comments
Labels
bugzilla Issues migrated from bugzilla

Comments

@Kojoley
Copy link
Contributor

Kojoley commented Feb 14, 2021

Bugzilla Link 49179
Resolution FIXED
Resolved on Apr 05, 2021 07:17
Version trunk
OS All
CC @topperc,@RKSimon,@rotateright
Fixed by commit(s) 8529470

Extended Description

#include

bool foo(double x)
{
return std::copysign(1., x) < 0.;
}

bool bar(double x)
{
return std::signbit(x);
}

https://godbolt.org/z/xPMzj9

@topperc
Copy link
Collaborator

topperc commented Feb 14, 2021

I'm not sure those are equivalent if x is nan.

@topperc
Copy link
Collaborator

topperc commented Feb 14, 2021

Err nevermind I guess they would be.

@rotateright
Copy link
Contributor

Not sure if Alive2 understands copysign (the LLVM instance seems to be dead currently).

As IR, we have:

define i1 @​#49179 (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"?

@rotateright
Copy link
Contributor

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).

@rotateright
Copy link
Contributor

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

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 11, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla
Projects
None yet
Development

No branches or pull requests

3 participants