This patch fixes the bug reported in PR67624 where a single-precision infinity value was being incorrectly converted to a half-precision NaN value. Since we need to preserve the semantics of converting signaling NaNs to quiet NaNs, we test explicitly for this case.
Built and tested on an arm-eabi cross. Applied to trunk. libgcc: PR libgcc/67624 * config/arm/fp16.c (__gnu_f2h_internal): Handle infinity correctly. gcc/testsuite: PR libgcc/67624 * gcc.target/arm/fp16-inf.c: New test.
diff --git a/gcc/testsuite/gcc.target/arm/fp16-inf.c b/gcc/testsuite/gcc.target/arm/fp16-inf.c new file mode 100644 index 0000000..ce5c197 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/fp16-inf.c @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-options "-O -mfp16-format=ieee" } */ + +/* Conversion of infinity to __fp16 and back again should preserve the + value. */ +volatile float f = __builtin_inf (); + +int main () +{ + __fp16 h = f; + if (h != __builtin_inf ()) + __builtin_abort (); + return 0; +} diff --git a/libgcc/config/arm/fp16.c b/libgcc/config/arm/fp16.c index 86a6348..8eaae2b 100644 --- a/libgcc/config/arm/fp16.c +++ b/libgcc/config/arm/fp16.c @@ -35,9 +35,12 @@ __gnu_f2h_internal(unsigned int a, int ieee) { if (!ieee) return sign; + if (mantissa == 0) + return sign | 0x7c00; /* Infinity. */ + /* Remaining cases are NaNs. Convert SNaN to QNaN. */ return sign | 0x7e00 | (mantissa >> 13); } - + if (aexp == 0 && mantissa == 0) return sign; @@ -49,7 +52,7 @@ __gnu_f2h_internal(unsigned int a, int ieee) { mask = 0x00ffffff; if (aexp >= -25) - mask >>= 25 + aexp; + mask >>= 25 + aexp; } else mask = 0x00001fff;