Hi,
the following snippet is from the nextafter() function of
<http://www.netlib.no/netlib/toms/722>
--- repro.c ---
#define Zero 0.0
double nextafter(double argx, double argy)
{
double z = argx;
if (isnan(argx) || isnan(argy)) return argx + argy;
if (argx == argy) return argx;
if (argx != Zero)
if (((argx < Zero) && (argx < argy))
|| ((argx > Zero) && (argx > argy)))
z += 1.0;
else
z -= 1.0;
return z;
}
--- EOF ---
I expect that GCC knows DeMorgan's rules and is able to
simplify/optimize the last if-statement to
if ((argx < Zero) == (argx < argy))
Unfortunately GCC fails to do so: see the lines from
label .L20: to label L7
$ gcc -m64 -O3 -o- -S
...
nextafter:
ucomisd %xmm1, %xmm0
jp .L19
pxor %xmm2, %xmm2
movl $1, %edx
ucomisd %xmm2, %xmm0
setp %al
cmovne %edx, %eax
testb %al, %al
je .L3
ucomisd %xmm1, %xmm0
setp %al
cmove %eax, %edx
testb %dl, %dl
jne .L20
.L3:
ret
.L20:
comisd %xmm0, %xmm2
ja .L21
.L4:
comisd %xmm2, %xmm0
jbe .L7
comisd %xmm1, %xmm0
jbe .L7
.L6:
addsd .LC1(%rip), %xmm0
ret
.L21:
comisd %xmm0, %xmm1
ja .L6
jmp .L4
.L7:
subsd .LC1(%rip), %xmm0
ret
.L19:
addsd %xmm1, %xmm0
ret
.LC1:
.long 0
.long 1072693248
Stefan