-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Constant folding for 'frem' is flaky #3688
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
Comments
I believe that frem is implemented in terms of the fmod libm function. Does your libm produce this result? |
Nope, fmodf() and fmod() both behave normally (gcc 4.0.1 under Mac OS 10.5.5), and frem works fine when it's not constant folded. (In the example I included, the second function returns the correct value.)
|
This may be a ConstantFP bug. We constant fold frem (which is the same as libm fmod) with:
|
It's in APFloat::convertToSignExtendedInteger, which is converting 0.1 to 1 at rounding mode NearestTiesToEven. Looks like it's been there since the beginning. Surprising this hasn't shown up before; is mod really the only thing that uses this? |
While what I said above is true, a more direct cause is that the conversion in APFloat::mod should be using RoundToZero. |
I see, currently the FP-to-integer conversions are always called with TowardsZero, except this one place. So the bug calling it with NearestTiesToEven would never show up anywhere else. This fixes both bugs. |
Nice, thanks Dale! |
OK, looking at this further, I've (re)discovered that IEEE remainder does use round-to-nearest, and is therefore not equivalent to C fmod. To confuse matters further, llvm docs refer to the C fmod operation as "remainder" (hence llvm frem is equivalent to C fmod) and the IEEE remainder operation as "modulo". It appears the intent of APFloat::mod was to implement IEEE remainder (although I don't see that stated anywhere) and I have just broken it (further). |
I'm seeing a similar problem, though for different constant values, in LLVM 3.9.1: $ cat frem.ll Compiled without optimisations gives the correct answer: $ llc frem.ll && ./frem However applying a constprop pass gives an incorrect answer: $ opt -S -constprop frem.ll define double @test1() { downstream issue: JuliaLang/julia#14089 |
Ignore that llc line, but the rest remains correct. Another error, though presumably from a different code path (0x43E0000000000000 is 0x1p63) $ cat frem2.ll $ opt -S -constprop frem2.ll define double @test1() { (answer should be 0 here) |
32177 is most likely a duplicate of this bug. If 32177 fixes itself after D29346 goes in, I'll mark it as DUPLICATE. |
D29346 was committed at rL299256 Added remaining test from this ticket at rL300757 |
Extended Description
Constant folding for 'frem' seems flaky for certain values. For example, "frem float 0.1, 1.0" returns -0.9 when constant folded:
define float @test1() {
entry:
%y = frem float 0x3FB99999A0000000, 1.0
ret float %y
}
@x = global float 0x3FB99999A0000000 ; float 0.1
define float @test2() {
%x = load float* @x
%y = frem float %x, 1.0
ret float %y
}
The text was updated successfully, but these errors were encountered: