Dietmar Ebner
2007-Oct-20 11:22 UTC
[LLVMdev] troubles with llvm-gcc 4.0 and APFloat on X86_64
hi, Dale Johannesen wrote:> On Oct 19, 2007, at 7:23 AM, Dietmar Ebner wrote: >> i'm trying to make some experiments with the ARM backend (llvm 2.1) >> and >> therefore built an arm-softfloat-linux-gnu toolchain on x86_64 linux. >> >> however, the llvm-gcc frontend seems to cause troubles with single >> precision floating point values, i.e., they are not converted >> correctly >> to the particular target format (double precision works as expected). > > I haven't seen this problem. You say the frontend; to check, > > llvm-gcc -O0 -S -emit-llvm file.c -o file.ll > > produces an invalid constant in the .ll file? Can you give an example?here's what i get for the following example: #include <stdio.h> int main(int argc, char *argv[]) { float f = 0.6; printf("hello world: %f / %f\n", f, 0.6); } ------------------------------------------ ; ModuleID = 'test.c' target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:12 8:128-a0:0:64-s0:0:64" target triple = "arm-softfloat-linux-gnu" @.str = internal constant [22 x i8] c"hello world: %f / %f\0A\00" ; <[22 x i8]*> [#uses=1] define i32 @main(i32 %argc, i8** %argv) { entry: %argc_addr = alloca i32 ; <i32*> [#uses=1] %argv_addr = alloca i8** ; <i8***> [#uses=1] %retval = alloca i32, align 4 ; <i32*> [#uses=1] %f = alloca float, align 4 ; <float*> [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] store i32 %argc, i32* %argc_addr store i8** %argv, i8*** %argv_addr store float 0x4000000040000000, float* %f, align 4 %tmp = load float* %f, align 4 ; <float> [#uses=1] %tmp1 = fpext float %tmp to double ; <double> [#uses=1] %tmp2 = getelementptr [22 x i8]* @.str, i32 0, i32 0 ; <i8*> [#uses=1] %tmp3 = call i32 (i8* noalias , ...)* @printf( i8* %tmp2 noalias , double %tmp1, double 0x333333333FE33333 ) ; <i32> [#uses=0] br label %return return: ; preds = %entry %retval4 = load i32* %retval ; <i32> [#uses=1] ret i32 %retval4 } declare i32 @printf(i8* noalias , ...) ------------------------------------------ which gives me the following when compiled and executed: hello world: 2.000000 / 0.600000 i've configured llvm-gcc (RELEASE_21) as follows: $ llvm-arm-gcc -v Using built-in specs. Target: arm-softfloat-linux-gnu Configured with: /nfs/a5/ebner/dev/official/llvm-gcc/configure --prefix=/nfstmp/util/arm-softfloat-linux-gnu/ --program-prefix=llvm-arm- --enable-llvm=/nfs/a5/ebner/dev/cross/arm-softfloat-linux/llvm --enable-checking --target=arm-softfloat-linux-gnu --disable-shared --disable-nls --disable-threads --with-float=soft --enable-languages=c Thread model: single i've applied a small patch (see below) to link the ieee754 softfloat library into libgcc.>> it seems the problem is related to the following piece of code taken >> from APFloat.cpp:1836 (called from ConvertREAL_CST) >> APFloat::APFloat(float f) { >> APInt api = APInt(32, 0); >> initFromAPInt(api.floatToBits(f)); >> } >> >> i guess the floatToBits call will return the wrong half word since >> ints >> are 4, but float and double are both 8 byte on x86_64 (but i'm not yet >> sure). > > I'm pretty sure float is 4 everywhere; that wouldn't be it.sure! sorry for the noise - dietmar Index: gcc/config/arm/linux-elf.h ==================================================================--- gcc/config/arm/linux-elf.h (revision 42922) +++ gcc/config/arm/linux-elf.h (working copy) @@ -56,7 +56,7 @@ %{shared:-lc} \ %{!shared:%{profile:-lc_p}%{!profile:-lc}}" -#define LIBGCC_SPEC "%{msoft-float:-lfloat} %{mfloat-abi=soft*:-lfloat} -lgcc" +/* #define LIBGCC_SPEC "%{msoft-float:-lfloat} %{mfloat-abi=soft*:-lfloat} -lgcc" */ /* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add the GNU/Linux magical crtbegin.o file (see crtstuff.c) which Index: gcc/config/arm/t-linux ==================================================================--- gcc/config/arm/t-linux (revision 42922) +++ gcc/config/arm/t-linux (working copy) @@ -4,7 +4,10 @@ LIBGCC2_DEBUG_CFLAGS = -g0 LIB1ASMSRC = arm/lib1funcs.asm -LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx +LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx \ + _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \ + _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \ + _fixsfsi _fixunssfsi # MULTILIB_OPTIONS = mhard-float/msoft-float # MULTILIB_DIRNAMES = hard-float soft-float
Dietmar Ebner
2007-Oct-22 09:08 UTC
[LLVMdev] troubles with llvm-gcc 4.0 and APFloat on X86_64
hi, i've got some more things to note. first, the issue is not related to x86_64 being the host machine - it also happens on i686/linux. next, i think (one of) the problem(s) is the use of [HOST_]WORDS_BIG_ENDIAN instead of [HOST_]FLOAT_WORDS_BIG_ENDIAN in llvm-convert.cpp (see patch below). this fixes single precision floating point but breaks double precision. for arm-softfloat-linux-gnu, FLOAT_WORDS_BIG_ENDIAN is true while WORDS_BIG_ENDIAN is false. as far as i've seen, there's only a single flag for endianess in the llvm target description string, so i don't really understand how this is supposed to work. i wonder how other people are cross compiling for arm-linux-gnu? any help would be highly appreciated! cheers, - dietmar --- llvm-convert.cpp (revision 42922) +++ llvm-convert.cpp (working copy) @@ -5581,15 +5581,15 @@ // getting the byte ordering correct and make sure you don't print any // more than 32 bits per integer on platforms with ints > 32 bits. // - bool HostBigEndian = false; -#ifdef HOST_WORDS_BIG_ENDIAN - HostBigEndian = true; + bool HostFloatBigEndian = false; +#ifdef HOST_FLOAT_WORDS_BIG_ENDIAN + HostFloatBigEndian = true; #endif UArr[0] = RealArr[0]; // Long -> int convert UArr[1] = RealArr[1]; - if (WORDS_BIG_ENDIAN != HostBigEndian) + if (FLOAT_WORDS_BIG_ENDIAN != HostFloatBigEndian) std::swap(UArr[0], UArr[1]); return ConstantFP::get(Ty, Ty==Type::FloatTy ? APFloat((float)V) Dietmar Ebner wrote:> hi, > > Dale Johannesen wrote: >> On Oct 19, 2007, at 7:23 AM, Dietmar Ebner wrote: >>> i'm trying to make some experiments with the ARM backend (llvm 2.1) >>> and >>> therefore built an arm-softfloat-linux-gnu toolchain on x86_64 linux. >>> >>> however, the llvm-gcc frontend seems to cause troubles with single >>> precision floating point values, i.e., they are not converted >>> correctly >>> to the particular target format (double precision works as expected). >> I haven't seen this problem. You say the frontend; to check, >> >> llvm-gcc -O0 -S -emit-llvm file.c -o file.ll >> >> produces an invalid constant in the .ll file? Can you give an example? > here's what i get for the following example: > > #include <stdio.h> > int main(int argc, char *argv[]) > { > float f = 0.6; > printf("hello world: %f / %f\n", f, 0.6); > } > > ------------------------------------------ > ; ModuleID = 'test.c' > target datalayout = > "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:12 > 8:128-a0:0:64-s0:0:64" > target triple = "arm-softfloat-linux-gnu" > @.str = internal constant [22 x i8] c"hello world: %f / %f\0A\00" > ; <[22 x i8]*> [#uses=1] > > define i32 @main(i32 %argc, i8** %argv) { > entry: > %argc_addr = alloca i32 ; <i32*> [#uses=1] > %argv_addr = alloca i8** ; <i8***> [#uses=1] > %retval = alloca i32, align 4 ; <i32*> [#uses=1] > %f = alloca float, align 4 ; <float*> [#uses=2] > %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] > store i32 %argc, i32* %argc_addr > store i8** %argv, i8*** %argv_addr > store float 0x4000000040000000, float* %f, align 4 > %tmp = load float* %f, align 4 ; <float> [#uses=1] > %tmp1 = fpext float %tmp to double ; <double> > [#uses=1] > %tmp2 = getelementptr [22 x i8]* @.str, i32 0, i32 0 > ; <i8*> [#uses=1] > %tmp3 = call i32 (i8* noalias , ...)* @printf( i8* %tmp2 > noalias , double %tmp1, double 0x333333333FE33333 > ) ; <i32> [#uses=0] > br label %return > > return: ; preds = %entry > %retval4 = load i32* %retval ; <i32> [#uses=1] > ret i32 %retval4 > } > > declare i32 @printf(i8* noalias , ...) > ------------------------------------------ > > which gives me the following when compiled and executed: > hello world: 2.000000 / 0.600000 > > > i've configured llvm-gcc (RELEASE_21) as follows: > $ llvm-arm-gcc -v > Using built-in specs. > Target: arm-softfloat-linux-gnu > Configured with: /nfs/a5/ebner/dev/official/llvm-gcc/configure > --prefix=/nfstmp/util/arm-softfloat-linux-gnu/ > --program-prefix=llvm-arm- > --enable-llvm=/nfs/a5/ebner/dev/cross/arm-softfloat-linux/llvm > --enable-checking --target=arm-softfloat-linux-gnu --disable-shared > --disable-nls --disable-threads --with-float=soft --enable-languages=c > Thread model: single > > i've applied a small patch (see below) to link the ieee754 softfloat > library into libgcc. > >>> it seems the problem is related to the following piece of code taken >>> from APFloat.cpp:1836 (called from ConvertREAL_CST) >>> APFloat::APFloat(float f) { >>> APInt api = APInt(32, 0); >>> initFromAPInt(api.floatToBits(f)); >>> } >>> >>> i guess the floatToBits call will return the wrong half word since >>> ints >>> are 4, but float and double are both 8 byte on x86_64 (but i'm not yet >>> sure). >> I'm pretty sure float is 4 everywhere; that wouldn't be it. > sure! sorry for the noise > > - > dietmar > > > > Index: gcc/config/arm/linux-elf.h > ==================================================================> --- gcc/config/arm/linux-elf.h (revision 42922) > +++ gcc/config/arm/linux-elf.h (working copy) > @@ -56,7 +56,7 @@ > %{shared:-lc} \ > %{!shared:%{profile:-lc_p}%{!profile:-lc}}" > > -#define LIBGCC_SPEC "%{msoft-float:-lfloat} %{mfloat-abi=soft*:-lfloat} > -lgcc" > +/* #define LIBGCC_SPEC "%{msoft-float:-lfloat} > %{mfloat-abi=soft*:-lfloat} -lgcc" */ > > /* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add > the GNU/Linux magical crtbegin.o file (see crtstuff.c) which > Index: gcc/config/arm/t-linux > ==================================================================> --- gcc/config/arm/t-linux (revision 42922) > +++ gcc/config/arm/t-linux (working copy) > @@ -4,7 +4,10 @@ > LIBGCC2_DEBUG_CFLAGS = -g0 > > LIB1ASMSRC = arm/lib1funcs.asm > -LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx > +LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx \ > + _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi > _fixunsdfsi \ > + _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \ > + _fixsfsi _fixunssfsi > > # MULTILIB_OPTIONS = mhard-float/msoft-float > # MULTILIB_DIRNAMES = hard-float soft-float > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev-- Dietmar Ebner CD Laboratory - Compilation Techniques for Embedded Processors Institut fuer Computersprachen E: ebner at complang.tuwien.ac.at Technische Universitaet Wien T: (+431) 58801-18598 Argentinierstrasse 8 / E1851 F: (+431) 58801-58521 1040 Wien, Austria W: www.complang.tuwien.ac.at/cd/ebner
Dale Johannesen
2007-Oct-22 17:03 UTC
[LLVMdev] troubles with llvm-gcc 4.0 and APFloat on X86_64
On Oct 22, 2007, at 2:08 AM, Dietmar Ebner wrote:> hi, > > i've got some more things to note. first, the issue is not related to > x86_64 being the host machine - it also happens on i686/linux. > > next, i think (one of) the problem(s) is the use of > [HOST_]WORDS_BIG_ENDIAN instead of [HOST_]FLOAT_WORDS_BIG_ENDIAN in > llvm-convert.cpp (see patch below). > > this fixes single precision floating point but breaks double > precision. > for arm-softfloat-linux-gnu, FLOAT_WORDS_BIG_ENDIAN is true while > WORDS_BIG_ENDIAN is false. as far as i've seen, there's only a single > flag for endianess in the llvm target description string, so i don't > really understand how this is supposed to work.Agree. I think those two match on all the targets I've tried. I think the right approach is to use REAL_VALUE_TO_TARGET_SINGLE for float and REAL_VALUE_TO_TARGET_DOUBLE for double, then the two endiannesses can be handled separately.> i wonder how other people are cross compiling for arm-linux-gnu? > any help would be highly appreciated!
Apparently Analagous Threads
- [LLVMdev] cross compiling for arm-softfloat-linux-gnu (was troubles with llvm-gcc 4.0 and APFloat on X86_64)
- [LLVMdev] troubles with llvm-gcc 4.0 and APFloat on X86_64
- [LLVMdev] troubles with llvm-gcc 4.0 and APFloat on X86_64
- [LLVMdev] cross compiling for arm-softfloat-linux-gnu (was troubles with llvm-gcc 4.0 and APFloat on X86_64)
- [LLVMdev] troubles with llvm-gcc 4.0 and APFloat on X86_64