[LLVMdev] troubles with llvm-gcc 4.0 and APFloat on X86_64

Dietmar Ebner ebner at complang.tuwien.ac.at
Sat Oct 20 04:22:56 PDT 2007


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




More information about the llvm-dev mailing list