Hi everyone, I'm learning how to use LLVM API and JIT engine and I've come across with an issue I haven't been able to figure out. The problem I'm having is that the wrong float is being stored in a float global variable. The code snippet I use to generate the float value is as follow: llvm::Type* type = // initialize with the global variable type; std::string real_value = // initialized with the float value from std input. ... return ConstantFP::get(type,real_value); I am using the code snippet above to store a float and double value, the double value works, the float value not. This can be seen with the following LLVM IR I am generating: What the functions do is just: 1. backup current value of global variable 2. store new value 3. call a C function which returns the value of the global variable in that same module 4. Compare against the value used in step 2 5. restore the initial value 6. return true or false if the values were equal. /** float gfloat = 3.141592; */ define i32 @test_getgfloat_0() { block_test_getgfloat_0: %0 = load float* @gfloat store float 0x400921FB00000000, float* @gfloat // wrong value stored %1 = call float @getgfloat() %2 = fcmp oeq float %1, 0x400921FA00000000 // wrong value stored %3 = zext i1 %2 to i32 store float %0, float* @gfloat ret i32 %3 } /** double gdouble = 2.52340; */ define i32 @test_getdouble_0() { block_test_getdouble_0: %0 = load double* @gdouble store double 2.523400e+00, double* @gdouble // correct value stored %1 = call double @getdouble() %2 = fcmp oeq double %1, 2.523400e+00 // correct value stored %3 = zext i1 %2 to i32 store double %0, double* @gdouble ret i32 %3 } Do you have any idea of why I'm having this problem? Thank you.
On Wed, Jun 18, 2014 at 11:59 AM, Adrian Ortega <elfus0.1 at gmail.com> wrote:> /** > float gfloat = 3.141592; > */ >> store float 0x400921FB00000000, float* @gfloat // wrong value stored >Here you store .....FB..... %2 = fcmp oeq float %1, 0x400921FA00000000 // wrong value stored Here you compare with .....FA..... - is that what you intended? Jim -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140618/73b71fe0/attachment.html>
Is the problem that the store and the fcmp have different single-precision constants to eachother, or is it that neither constant is what you expected? If it's the latter, then the constants look correct to me. Hexadecimal floating point values in LLVM-IR are in double precision format for both single and double precision values. When used for a single-precision constant, the double-precision constant must be convertible to single-precision without rounding. See the paragraph starting 'The one non-intuitive notation ...' at http://llvm.org/docs/LangRef.html#simple-constants. I'm not sure why the store and fcmp constants differ though. 3.141592 isn't exactly representable in single precision but I would have expected both constants to be rounded the same way.> -----Original Message----- > From: llvmdev-bounces at cs.uiuc.edu [mailto:llvmdev-bounces at cs.uiuc.edu] > On Behalf Of Adrian Ortega > Sent: 18 June 2014 04:59 > To: llvmdev at cs.uiuc.edu > Subject: [LLVMdev] Wrong float value stored in LLVM IR code > > Hi everyone, > > I'm learning how to use LLVM API and JIT engine and I've come across with an > issue I haven't been able to figure out. > > The problem I'm having is that the wrong float is being stored in a float global > variable. > > The code snippet I use to generate the float value is as follow: > > llvm::Type* type = // initialize with the global variable type; > std::string real_value = // initialized with the float value from std input. > ... > return ConstantFP::get(type,real_value); > > I am using the code snippet above to store a float and double value, the > double value works, the float value not. This can be seen with the following > LLVM IR I am generating: > > What the functions do is just: > 1. backup current value of global variable > 2. store new value > 3. call a C function which returns the value of the global variable in that same > module > 4. Compare against the value used in step 2 > 5. restore the initial value > 6. return true or false if the values were equal. > > /** > float gfloat = 3.141592; > */ > define i32 @test_getgfloat_0() { > block_test_getgfloat_0: > %0 = load float* @gfloat > store float 0x400921FB00000000, float* @gfloat // wrong value stored > %1 = call float @getgfloat() > %2 = fcmp oeq float %1, 0x400921FA00000000 // wrong value stored > %3 = zext i1 %2 to i32 > store float %0, float* @gfloat > ret i32 %3 > } > > /** > double gdouble = 2.52340; > */ > define i32 @test_getdouble_0() { > block_test_getdouble_0: > %0 = load double* @gdouble > store double 2.523400e+00, double* @gdouble // correct value stored > %1 = call double @getdouble() > %2 = fcmp oeq double %1, 2.523400e+00 // correct value stored > %3 = zext i1 %2 to i32 > store double %0, double* @gdouble > ret i32 %3 > } > > Do you have any idea of why I'm having this problem? > > Thank you. > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Originally was the latter, but after carefully debugging it turned out the former. In summary, I was storing the floating point value in a string and using ConstantFP::get() to get a float value in two different lines in my code. The problem was that in one line for debugging reasons I was converting the string value to a C++ float type, and then again back to string thus I lost some precision there and a few digits were lost, and two different constants were generated (I know, I looked at the code and seems I needed a cup of coffee... :) ). Solution was to call ConstantFP::get() with the same string in both places with no castings to other type. However, the information you provided was really helpful as I looked over my code and detected some bugs related to floats precision I was generating related to the explanation below (aside that silly bug from above). Thanks everyone for your help. On 18/06/14 07:29, Daniel Sanders wrote:> Is the problem that the store and the fcmp have different single-precision constants to eachother, or is it that neither constant is what you expected? > > If it's the latter, then the constants look correct to me. Hexadecimal floating point values in LLVM-IR are in double precision format for both single and double precision values. When used for a single-precision constant, the double-precision constant must be convertible to single-precision without rounding. See the paragraph starting 'The one non-intuitive notation ...' at http://llvm.org/docs/LangRef.html#simple-constants. > > I'm not sure why the store and fcmp constants differ though. 3.141592 isn't exactly representable in single precision but I would have expected both constants to be rounded the same way. > >> -----Original Message----- >> From: llvmdev-bounces at cs.uiuc.edu [mailto:llvmdev-bounces at cs.uiuc.edu] >> On Behalf Of Adrian Ortega >> Sent: 18 June 2014 04:59 >> To: llvmdev at cs.uiuc.edu >> Subject: [LLVMdev] Wrong float value stored in LLVM IR code >> >> Hi everyone, >> >> I'm learning how to use LLVM API and JIT engine and I've come across with an >> issue I haven't been able to figure out. >> >> The problem I'm having is that the wrong float is being stored in a float global >> variable. >> >> The code snippet I use to generate the float value is as follow: >> >> llvm::Type* type = // initialize with the global variable type; >> std::string real_value = // initialized with the float value from std input. >> ... >> return ConstantFP::get(type,real_value); >> >> I am using the code snippet above to store a float and double value, the >> double value works, the float value not. This can be seen with the following >> LLVM IR I am generating: >> >> What the functions do is just: >> 1. backup current value of global variable >> 2. store new value >> 3. call a C function which returns the value of the global variable in that same >> module >> 4. Compare against the value used in step 2 >> 5. restore the initial value >> 6. return true or false if the values were equal. >> >> /** >> float gfloat = 3.141592; >> */ >> define i32 @test_getgfloat_0() { >> block_test_getgfloat_0: >> %0 = load float* @gfloat >> store float 0x400921FB00000000, float* @gfloat // wrong value stored >> %1 = call float @getgfloat() >> %2 = fcmp oeq float %1, 0x400921FA00000000 // wrong value stored >> %3 = zext i1 %2 to i32 >> store float %0, float* @gfloat >> ret i32 %3 >> } >> >> /** >> double gdouble = 2.52340; >> */ >> define i32 @test_getdouble_0() { >> block_test_getdouble_0: >> %0 = load double* @gdouble >> store double 2.523400e+00, double* @gdouble // correct value stored >> %1 = call double @getdouble() >> %2 = fcmp oeq double %1, 2.523400e+00 // correct value stored >> %3 = zext i1 %2 to i32 >> store double %0, double* @gdouble >> ret i32 %3 >> } >> >> Do you have any idea of why I'm having this problem? >> >> Thank you. >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140618/2cb10963/attachment.html>