On 8/9/2026 1:12 PM, Matt Turner wrote:
Alpha has no instruction converting TFmode to SFmode, so trunctfsf2 goes
through DFmode and has to avoid rounding twice.
It tried to, by setting a sticky bit at fraction bit 48 when the low word
of the TFmode value was nonzero: a DFmode value with that bit set cannot
sit exactly halfway between two SFmode values, leaving the second
rounding nothing to break a tie on. But the bit is set before the
conversion to DFmode, and the carry out of the bits that conversion
discards can propagate up through bit 48 and clear it, landing on the
halfway value it was there to avoid.
Round to odd at the last fraction bit DFmode keeps instead. The value is
then exactly representable in DFmode, so that conversion does not round
and the one to SFmode is the only rounding.
Over values constructed around SFmode halfway points the old sequence is
wrong for about a quarter of them and the new one for none. Uniformly
random values do not reach it: that needs the conversion to DFmode to
carry all the way to a halfway value.
Rounding twice also loses the underflow flag when the result is subnormal.
glibc's narrowing functions compute a round-to-odd value in the wider type
and convert it once, and that single conversion is what is meant to raise
underflow; splitting it in two can leave the intermediate DFmode value
exactly representable in SFmode, so the final step raises nothing.
Found through glibc's math testsuite, where three of the narrowing fma
tests returned a wrong result. Retested there on an EV67 with a glibc
built by a compiler carrying this patch: the wrong results are gone, every
test now reporting a maximum error of 0 ulp, and the six narrowing add and
subtract tests that had been failing on the lost underflow flag pass. The
narrowing tests that still fail there do so for an unrelated reason, Alpha
determining tininess from the delivered result rather than as IEEE 754
describes, which no change to the compiler can address.
---
gcc/config/alpha/alpha.md | 23 +++++++++++------
gcc/testsuite/gcc.target/alpha/trunctfsf2-1.c | 25 +++++++++++++++++++
2 files changed, 40 insertions(+), 8 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/alpha/trunctfsf2-1.c
THanks. I constructed a ChangeLog entry and pushed this to the trunk.
Not sure how much time you have Matt, but these tests started failing
about a month ago on alpha-linux-gnu. No idea why yet.
Tests that now fail, but worked before (28 tests):
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O0 execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O0 execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O1 execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O1 execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O2 execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O2 execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O2 -flto
-fno-use-linker-plugin -flto-partition=none execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O2 -flto
-fno-use-linker-plugin -flto-partition=none execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O2 -flto
-fuse-linker-plugin -fno-fat-lto-objects execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O2 -flto
-fuse-linker-plugin -fno-fat-lto-objects execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O3 -g execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -O3 -g execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -Os execution test
gcc: gcc.dg/torture/fp-int-convert-float32-timode.c -Os execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O0 execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O0 execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O1 execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O1 execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O2 execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O2 execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O2 -flto -fno-use-linker-plugin
-flto-partition=none execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O2 -flto -fno-use-linker-plugin
-flto-partition=none execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O2 -flto -fuse-linker-plugin
-fno-fat-lto-objects execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O2 -flto -fuse-linker-plugin
-fno-fat-lto-objects execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O3 -g execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -O3 -g execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -Os execution test
gcc: gcc.dg/torture/fp-int-convert-timode.c -Os execution test
31d967232a9331ad72571da27550b2f5d7d38523 was the last good hash.
f06e56614b948ad88dabf63020f47713b7dea0ec was the first reported bad hash if
you're going to try and chase it down.
Jeff