Mapping NAN to ZERO / When does gcc generate MOVcc and FCMOVcc instructions?

Uros Bizjak ubizjak@gmail.com
Fri Nov 3 07:45:00 GMT 2006


Michael James wrote:

> Conceptually, the code is:

> double sum = 0;

> for(i=0; i<n; ++i) {
>    float x = ..computed..;
>    sum += isnan(x)? 0: x;
> }


> I have tried a half dozen variants at the source level in attempt to
> get gcc to do this without branching (and without calling a helper
> function isnan). I was not really able to succeed at either of these.

You need to specify an architecture that has cmov instruction; at
least -march=i686.

> Concerning the inline evaluation of isnan, I tried using
> __builtin_unordered(x,x) which either gets optimized out of existence
> when I specificy -funsafe-math-optimizations, or causes other gcc math
> inlines (specifically log) to not use their inline definitions when I
> do not specificy -funsafe-math-optimizations. For my particular
> problem I have a work around for this which none-the-less causes the
> result of isnan to end up as a condition flag in the EFLAGS register.
> (Instead of a test for nan, I use a test for 0 in the domain of the
> log.)

This testcase (similar to yours, but it actually compiles):

double test(int n, double a)
{
  double sum = 0.0;
  int i;

  for(i=0; i<n; ++i)
    {
      float x = logf((float)i);
      sum += isnan(x) ? 0 : x;
    }

  return sum;
}

produces exactly the code you are looking for (using gcc-4.2 with -march=i686):

.L5:
        pushl   %ebx
        fildl   (%esp)
        addl    $4, %esp
        fstps   (%esp)
        fstpl   -24(%ebp)
        call    logf
        fucomi  %st(0), %st
        fldz
        fcmovnu %st(1), %st
        fstp    %st(1)
        addl    $1, %ebx
        cmpl    %esi, %ebx
        fldl    -24(%ebp)
        faddp   %st, %st(1)
        jne     .L5

logf() function will be inlined by specifying
-funsafe-math-optimizations, this flag also enables implicit
float->double extensions for x87 math. As you probably don't need math
errno from log(), -fno-math-errno should be added.

Those two flags produce IMO optimal loop:

.L5:
        pushl   %eax
        fildl   (%esp)
        addl    $4, %esp
        fldln2
        fxch    %st(1)
        fyl2x
        fucomi  %st(0), %st
        fldz
        fcmovnu %st(1), %st
        fstp    %st(1)
        addl    $1, %eax
        cmpl    %edx, %eax
        faddp   %st, %st(1)
        jne     .L5

Uros.

> Concerning the use of an unconditional add, followed by a FCMOVcc
> instead of a Jcc, I have had no success: I have tried code such as:



More information about the Gcc mailing list