https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66986

            Bug ID: 66986
           Summary: poor performance of __builtin_isinf on x64
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: neleai at seznam dot cz
  Target Milestone: ---

Created attachment 36046
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36046&action=edit
benchmark.

Hi,

On x64 floating builtins are considerably slower than equivalent integer code.
For easier tracking I split this in per-function basis.

Currently libc uses separate inlines to get better performance than buildins so
fixing these would be appreciated.

As for isinf main problem is how to measure it. Depending on use case parts of
it will be optimized away.


It tests 12 cases which combination of surrounding expression
1:
 if (isinf2 (x))
   *d+=42;
2:
  if (isinf2 (x))
    abort();
3:
 *d += isinf2 (x);

where in cases 1 and 3 gcc tries to generate branchless code which does more
harm than good, case 2 is common usage to represent if (isinf(x) foo() else
bar()

Then its tried by placing this expression in function and selectively inlining
we measure effect of constructing needed integer constants. 

Attached benchmark clearly shows that its better to use following inline
instead.

#define EXTRACT_WORDS64(i, d)                                                 \
  do {                                                                        \
    int64_t i_;                                                               \
    asm ("movq %1, %0" : "=rm" (i_) : "x" ((double) (d)));                   \
    (i) = i_;                                                                 \
  } while (0)


int I2
isinf2 (double dx)
{
  unsigned long x;
  EXTRACT_WORDS64(dx, x);
  if (2 * x == 0xffe0000000000000)
    return 0;
  else
    return (int) (x >> 32);
}

Reply via email to