[PATCH] alpha: round to odd before narrowing TFmode to SFmode

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 (trunctfsf2): Adjust sequence to avoid
	conversion step landing at a halfway value.

gcc/testsuite/

	* gcc.target/alpha/trunctfsf2-1.c: New test.
2 files changed