[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