Re: [PATCH] alpha: round to odd before narrowing TFmode to SFmode
Matt Turner <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <CAEdQ38Esyv=7Yadv=f5DFoON8=Zg-L2NfZ+0GDXm7z93MvBnxA@mail.gmail.com> |
On Sun, Aug 9, 2026 at 6:12 PM Jeffrey Law <[email protected]> wrote: > > > > 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. Thanks a bunch, Jeff! (Sorry for forgetting the ChangeLog entry. Will make sure to include those in the future) > 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. Interesting, thanks. I'll investsigate.