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

Reply via email to