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

Rounding issues on ARM #10127

Closed
ViralBShah opened this issue Feb 8, 2015 · 15 comments
Closed

Rounding issues on ARM #10127

ViralBShah opened this issue Feb 8, 2015 · 15 comments
Labels
system:arm ARMv7 and AArch64

Comments

@ViralBShah
Copy link
Member

This evaluates to true on x86, but to false on ARM (from rounding.jl)

 with_rounding(Float64, RoundToZero) do 
       prevfloat(0.5)+0.5 === prevfloat(1.)
end
@ViralBShah ViralBShah added the system:arm ARMv7 and AArch64 label Feb 8, 2015
@ViralBShah
Copy link
Member Author

On ARM:

julia> with_rounding(Float64, RoundToZero) do 
                       prevfloat(0.5)+0.5
                   end
1.0

but on x86,


julia> with_rounding(Float64, RoundToZero) do 
                              prevfloat(0.5)+0.5
                          end
0.9999999999999999

@simonbyrne
Copy link
Contributor

It looks like a problem with fesetround. You might be able to access the control register directly via the llvm @llvm.arm.get.fpscr intrinsic to see if it has actually changed.

@ViralBShah
Copy link
Member Author

Would we be using fesetround from openlibm, or does this come directly from llvm? I will try out your suggestion.

@ViralBShah
Copy link
Member Author

How do I use @llvm.arm.get.fpscr from the julia prompt?

@simonbyrne
Copy link
Contributor

I don't have an ARM machine, so I can't try it, but maybe something like:

function getfpscr()
    Base.llvmcall("""%0 = call i32 @llvm.arm.get.fpscr()
        ret i32 %0""", UInt32, ())
end

It might throw "Failed to parse LLVM Assembly" the first time you run it: if so just run it again (this is due to #8740).

See also my code for playing around with the SSE register on x86:
https://gist.github.com/simonbyrne/9c1e4704be46b66b1485

@simonbyrne
Copy link
Contributor

Would we be using fesetround from openlibm, or does this come directly from llvm? I will try out your suggestion.

I assume that this line means that we use the system fesetround?

@ViralBShah
Copy link
Member Author

That is what we did back then. Are we better off going through LLVM?

@simonbyrne
Copy link
Contributor

I don't think LLVM offers fesetround/fegetround intrinsics. We could implement our own via the appropriate control register intrinsics, but LLVM doesn't model floating point side-effects and so might reorder them incorrectly (LLVM #6393).

@ViralBShah
Copy link
Member Author

That LLVM issue has been open for almost 5 years now!

@simonbyrne
Copy link
Contributor

Yeah: it would be useful if we ever want floating-point exceptions to work correctly, but it doesn't seem like it is going to get fixed any time soon. It could be an interesting GSOC project, if you could find someone able to supervise it?

@ViralBShah
Copy link
Member Author

The linux system manpage for fegetround/fesetround says:

BUGS
       C99 specifies that the value of FLT_ROUNDS should reflect changes to the current rounding mode, as set by fes‐
       etround().  Currently, this does not occur: FLT_ROUNDS always has the value 1.

I also found the following in OpenBSD sources:

 * The ARM FPA codes the rounding mode into the actual FP instructions
 * so there is no such thing as a global rounding mode.
 * The default is round to nearest if rounding is not explicitly specified.
 * FP instructions generated by GCC will not explicitly specify a rounding
 * mode.
 *
 * So the best we can do it to return the rounding mode FP instructions
 * use if rounding is not specified which is round to nearest.
 *
 * This could change in the future with new floating point emulators or
 * soft float FP libraries.

It appears that we are not going to have all the rounding modes anytime soon on ARM. The thing to do here would be to avoid running these tests on ARM, at least for now.

@nalimilan
Copy link
Member

Good catch. Trying to set rounding mode to anything other than round-to-nearest should probably result in an error or at least a warning on ARM then.

@simonbyrne
Copy link
Contributor

To be fair, instruction specific rounding is much more useful.

We could emulate a global mode, similar to how we do BigFloats, but I imagine it would be infeasible in terms of performance.

@ViralBShah
Copy link
Member Author

Probably we need to disable rounding for arm and just give an appropriate error message. This would be sufficient to close this for now.

@yuyichao
Copy link
Contributor

This is actually caused by the build not picking up the right constant for fesetround.

AFAICT what ARM and AArch64 have are

  1. FPSCR register

    This controls the rounding mode of most (all?) vfp instructions and should be IEEE754 complaint.

  2. There are some conversion instructions that ignores FPSCR or use a specific rounding mode

  3. NEON (therefore all SIMD instructions) ignores rounding mode

We don't require NEON on ARM (so no simd =( ) so the ARM generic binary should support rounding mode. Native arch ARM binaries may not but only in a vectorized loop or with fast math set in which case the rounding mode probably doesn't matter....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
system:arm ARMv7 and AArch64
Projects
None yet
Development

No branches or pull requests

4 participants