[LLVMdev] troubles with llvm-gcc 4.0 and APFloat on X86_64
Dietmar Ebner
ebner at complang.tuwien.ac.at
Mon Oct 22 02:08:16 PDT 2007
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
More information about the llvm-dev
mailing list