[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