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

            Bug ID: 127298
           Summary: [alpha] classification built-ins expand to FP
                    comparisons, which trap or misclassify a subnormal
                    operand
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mattst88 at gmail dot com
  Target Milestone: ---
              Host: alpha-*-*

On Alpha, __builtin_fpclassify, __builtin_isnan, __builtin_isinf,
__builtin_isinf_sign, __builtin_isfinite and __builtin_isnormal expand to
floating-point comparison instructions, which in the default trap mode carry
no software-completion suffix:

  $ cat cls.c
  #include <stdio.h>
  int
  main (void)
  {
    volatile double x = 0x1p-1050;
    printf ("%d\n", __builtin_fpclassify (0, 1, 4, 3, 2, x));
    return 0;
  }
  $ alpha-unknown-linux-gnu-gcc -O2 -o cls cls.c
  $ ./cls
  Floating point exception (core dumped)

A comparison raises a denormal-operand exception for a subnormal operand, and
what follows depends on the FPCR denormal-operand-disable bit:

  - with denormal traps enabled, the default on Linux, the trap is delivered
    with no completion information and the program dies as above;

  - with them disabled, the operand is flushed to zero, so a subnormal is
    indistinguishable from a zero. __builtin_fpclassify then returns FP_ZERO
    for a subnormal, and __builtin_isnormal is no more trustworthy.

The fpclassify expansion above ends in "cmpteq $f16,$f31,$f10" -- a comparison
against zero, which a flushed subnormal passes.

-mieee gives the right answer, and the program above prints 3, because the
compiler then maintains trap shadows and emits cmptun/su for the kernel to
complete. But -mieee is not the default, and emitting /su ad hoc without it
is not a fix: software completion also needs the trap-shadow rules, which the
compiler only observes at -mfp-trap-mode=su and above.

Classifying by examining the encoding in an integer register needs no
comparison and raises nothing. __builtin_issignaling already does that and is
unaffected.

This also blocks glibc, whose fpclassify, isnan, isinf, isfinite and isnormal
macros are defined in terms of these built-ins and have to call the
out-of-line implementations on Alpha instead. A different failure mode from
PR 66462 -- wrong for signalling NaNs there, wrong for subnormals here -- but
the same consequence.

Patch to follow: the isfinite<mode>2, isinf<mode>2, isnan<mode>2 and
isnormal<mode>2 optabs in the Alpha back end for alpha_fptm < ALPHA_FPTM_SU,
plus a fold_builtin_fpclassify change to build on those built-ins where their
optabs exist rather than always folding to comparisons.

Reply via email to