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!
Reasonably Related 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