llvm: NewFloat does not generate the expected output
Hello all,
I would first like to say thanks for an amazing library and I appreciate the hard work and dedication to support LLVM through Go.
However, using the library in a project of my own to generate LLVM instructions for different variables, I ran into a problem where using NewFloat
did not produce the expected results. I will demonstrate using a C program as a comparison.
Using clang -S -emit-llvm main.c
on the following program:
Input C Program:
int main() {
float j = 1.1;
return 0;
}
Produces the following store instruction for the float variable:
store float 0x3FF19999A0000000, float* %2, align 4
This is a 64 bit float with the last 28 bits dropped and converted to hex. (According to: http://lists.llvm.org/pipermail/llvm-dev/2011-April/039811.html)
However, attempting to generate the same instruction using this library:
mainBlock.NewStore(constant.NewFloat(value, types.Float), mainBlock.NewAlloca(types.Float))
where value
is the float literal 1.1
.
I obtained the following instruction:
store float 1.1, float* %1
Putting this into LLVM to generate assembly using:
llc -march=x86 -o main.expr.assembly main.expr.ll
Generates an error of:
llc: main.expr.ll:6:14: error: floating point constant invalid for type
store float 1.1, float* %1
I can provide more information if needed, but a few questions:
- Is this expected behavior?
- Should this be expected behavior?
- If yes, why does this produce code that doesn’t work?
I can get it to work using types.Double
, and if that is the solution then so be it for now, but I’d like to investigate if this is actually the expected output.
Again, Thanks for the work and dedication
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 42 (36 by maintainers)
Commits related to this issue
- (#31) IEEE 754 128bit float from string (#119) * (#31) support IEEE754 128 bit format * (#31) upgrade mewmew/float for IEEE754 128bit float to big.Float support * go mod tidy — committed to llir/llvm by dannypsnl 5 years ago
- (#31) WIP, based on IEEE754 implementation — committed to llir/llvm by dannypsnl 5 years ago
- (#31) update mewmew/float to get ppc_fp128 support — committed to llir/llvm by dannypsnl 5 years ago
- (#31) powerpc 128-bits float (#123) * (#31) WIP, based on IEEE754 implementation * (#31) update mewmew/float to get ppc_fp128 support * (#31) use TrimPrefix * (#31) add test for new float fr... — committed to llir/llvm by dannypsnl 5 years ago
Normally, yes - these are 64-bit floats and the precision does not cover that resolution. However, with double-double arithmetic, these values do not correspond to the same bits as just adding two floats together. According to Wikipedia (4), it should be possible to represent something like e-1074.
Just my thoughts after looking into it, I come across a few different things:
Taking a look at double-double precision on Wikipedia (4) and a Go double-double lib (2), it does not appear that the floats are simply just added together, they need to be dissected as each one does not contain symmetric significand and mantissa values. This is consistent with examples shown in (1) and (3) as well. Also, looking at Go’s
math.big
, it implements arbitrary precision arithmetic, not double-double so I don’t think we can be sure if that example is supposed to be correct.I have also referenced the Julia DoubleDouble lib as I think that can provide an example for use cases and implementations.
I am not sure how much this helps, but just some thoughts and links for direction.
I agree with @dannypsnl, I don’t think this is important for the release. PPC is already very obscure and I would be surprised if anyone actually uses 128-bit floats in combination.
No, I don’t think it would be a blocker, postponing fixing is ok.
I think these cases seem like just formatting problems.
Yes, this definitely seems to the what
ppc_fp128
corresponds to. Thanks for doing the research on this issue 😃From lib/Support/APFloat.cpp:
Updated, didn’t know it required that number www
Sure, I would take a look later. 😃
On Sat, Dec 7, 2019 at 10:38 AM Robin Eklind notifications@github.com wrote:
Hi Scott,
Thanks for the detailed report!
The representation of floating-point numbers is not yet up to pair with LLVM; so in that sense it is expected behaviour. It definitely should not be expected, and leading up to a 1.0 release of llir/llvm this has to be resolved. So, good that we now have an issue to refer to, for the implementation of floating-point values.
Any help implementing support for this would be greatly appreciated. We’ve given it a few attempts, but so far only cover a subset of the valid representations.
The most relevant code is currently located in https://github.com/llir/llvm/tree/master/internal/floats It could be expanded, more thoroughly tested and eventually made complete, for float80, float128, float16, etc.
The current implementation of floating-point constants is riddled with
TODO
notes, see for instance https://github.com/llir/llvm/blob/master/ir/constant/float.go#L50For your specific use case of
float
values, see https://github.com/llir/llvm/blob/master/ir/constant/float.go#L121I wish we were in a better state handling floating-point values, but the work has just not yet been done. So, for this we warmly invite you to help take a stab at it 😃
I’d be glad to help you get acquainted with the code base if you’d like.
The end goal is to support encoding and decoding of these floating-point types (including their hexadecimal representations):
half
: 16-bit floating point typefloat
: 32-bit floating point typedouble
: 64-bit floating point typefp128
: 128-bit floating point type (112-bit mantissa)x86_fp80
: 80-bit floating point type (x87)ppc_fp128
: 128-bit floating point type (two 64-bits, PowerPC)Cheerful regards from a sunny Sweden, Robin
P.S. as a small side note, and as outlined in issue #29 for the upcoming release, we’ve been working recently to have a grammar that covers the entire LLVM IR language. As outlined, the repo https://github.com/mewmew/l has been used during the experimental phase and its grammar will be merged back into the llir/llvm repo once the code base matures. Some more work on float80 has been done at https://github.com/mewmew/l/tree/master/internal/float80 but I don’t think it’s complete. So you can simply take a look, and then use the resources that you find to come up with a more complete implementation.