[LLVMdev] Stange behavior in fp arithmetics on x86 (bug possibly)

Dmitry Borisenkov d.borisenkov at samsung.com
Tue Oct 7 10:50:37 PDT 2014


Hello everyone.

I'm not an expert neither in llvm nor in x86 nor in IEEE standard for
floating point numbers, thus any of my following assumptions maybe wrong. If
so, I will be grateful if you clarify me what's goes wrong. But if my
guesses are correct we possibly have a bug in fp arithmetics on x86.

I have the following ir:

  @g = constant i64 1

define i32 @main() {

  %gval = load i64* @g

  %gvalfp = bitcast i64 %gval to double

  %fmul = fmul double %gvalfp, -5.000000e-01

  %fcmp = fcmp ueq double %fmul, -0.000000e+00

  %ret = select i1 %fcmp, i32 1, i32 0

  ret i32 %ret

}

And I expected that minimal positive denormalized double times -0.5 is equal
to -0.0, so correct exit code is 1.

llvm-3.4.2 on x86 linux target produced the following assembly:

      .file "fpfail.ll"

      .section    .rodata.cst8,"aM", at progbits,8

      .align      8

.LCPI0_0:

      .quad -4620693217682128896    # double -0.5

.LCPI0_1:

      .quad -9223372036854775808    # double -0

      .text

      .globl      main

      .align      16, 0x90

      .type main, at function

main:                                   # @main

      .cfi_startproc

# BB#0:

      vmovsd      g, %xmm0

      vmulsd      .LCPI0_0, %xmm0, %xmm0

      vucomisd    .LCPI0_1, %xmm0

      sete  %al

      movzbl      %al, %eax

      ret

.Ltmp0:

      .size main, .Ltmp0-main

      .cfi_endproc

 

      .type g, at object               # @g

      .section    .rodata,"a", at progbits

      .globl      g

      .align      8

g:

      .quad 1                       # 0x1

      .size g, 8

 

      .section    ".note.GNU-stack","", at progbits

 

./llc -march=x86 fpfail.ll; g++ fpfail.s; ./a.out; echo $?

returns 1 as expected.

 

But llvm-3.5 (on the same target) lowers the previous ir using floating
point instructions in the following way.

      .text

      .file "fpfail.ll"

      .section    .rodata.cst4,"aM", at progbits,4

      .align      4

.LCPI0_0:

      .long 3204448256              # float -0.5

      .text

      .globl      main

      .align      16, 0x90

      .type main, at function

main:                                   # @main

      .cfi_startproc

# BB#0:

      fldl  g

      fmuls .LCPI0_0

      fldz

      fchs

      fxch  %st(1)

      fucompp

      fnstsw      %ax

                                        # kill: AX<def> AX<kill> EAX<def>

                                        # kill: AH<def> AH<kill> EAX<kill>

      sahf

      sete  %al

      movzbl      %al, %eax

      retl

.Ltmp0:

      .size main, .Ltmp0-main

      .cfi_endproc

 

      .type g, at object               # @g

      .section    .rodata,"a", at progbits

      .globl      g

      .align      8

g:

      .quad 1                       # 0x1

      .size g, 8

 

 

      .section    ".note.GNU-stack","", at progbits

 

First, it doesn't assemble with g++ (4.8):

fpfail.s:26: Error: invalid instruction suffix for `ret'

I downloaded Intel manual and haven't found any mention of retl instruction,
so I manually exchanged it with ret and reassemble:

g++ fpfail.s; ./a.out; echo $?

The exit code is 0. This is correct for Intel 80-bit floats but wrong for
doubles. What am I do wrong or this is actually a bug or even worse -
correct behavior?

 

--

Kind regards, Dmitry Borisenkov

 

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141007/8d518e8b/attachment.html>


More information about the llvm-dev mailing list