From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794065194; b=EPCzmLvzxAWio7+BeFMTMCWCpXS5ldqviuNw2pih/5vV86nW5l9AvKSOW+ks9X42y/A2 F8xWcYoYmoTgMWfwRuw7YjEm89UrwNLK9Pptule8K/khdT5nwFaIqCNPS59T3f9vlaxLZ fGXIlHCwo+Q0Qg5VxNvHkPSojpv0PfgDAUxl3BEzGNT9TlMcH2fAeOy1EwepjrTGCBTb9 b5y+4u3ZKVR8f/9Wio9pb5HsfBB+NiuEnDnbYz72trZcFPlW+AHEecsqKszz/PjDjVB74 nLsOpwvQ8doEE3xLEgA88Rx21P37KUzs+Dd7no+K8OYyQR0hL5nzrSIYUXiwesqOeTA== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794065194; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=iMrdZxBmf22Z3hYRmgrKpiQm5i9w/rx68pqSRY9SIhc=; b=KMpoO8mSHVG9HzB5A6peEMui00ssqxLbdLab6jS/QJi0CQGrbrX5W1O7nxSgIjTlm6C4 AzNdxqk0bFlj0MSra5AQxUA87LlYh9nJky41dZt60TTymhFdpPLkjxhvyx1ThaxFyShcI I81EetrHW/od5InBlQN3jyOB3oqQdrNG61kIwdfuNBYa9c1FuwuKjpn1f1eTFYXNiRkrt iH1WyKuUwD55DxozY11yChKR4Ddhz8M5vLeM6s9HvZSj/JJFuPFDWO3geNbSxyLhrLA7q zI0uaKJAKkzs+p6BiXcC0/dFzb/KVrVNbRRvWeCk0zmXwB8rOx7B5nrJ1ShqULB29WA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=dIRd4gdV; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9A35606A339; Sat, 7 Nov 2026 15:26:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=dIRd4gdV Received: by smtp.kernel.org (Postfix) with ESMTPSA id 944591F0089F; Sat, 7 Nov 2026 15:26:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1794065193; bh=iMrdZxBmf22Z3hYRmgrKpiQm5i9w/rx68pqSRY9SIhc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=dIRd4gdVxKzd/FEQoZkAE7wUa4h0QCRnthPOtsfNwzDWjdFOPTx4lt258k2f9kyJ4 QPmS4YjjDAVkTiOanS8n1bqfvdmtl2lMC/cKVZBPhHOs0epC9xSrhOzc4Rw/Vkfwrh TuyHycUt5M2MBFoilYWOpnOVC9qTFlxyqQLpXqYs= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Magnus Lindholm , Matt Turner , Sasha Levin Subject: [PATCH 7.3 0994/1257] alpha: determine tininess after rounding in the FP emulation Date: Sat, 7 Nov 2026 08:54:50 -0500 Message-ID: <20261107135006.816523078@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261107134939.434104957@linuxfoundation.org> References: <20261107134939.434104957@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: stable@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 7.3-stable review patch. If anyone has any objections, please let me know. ------------------ From: Matt Turner [ Upstream commit b74843b38da8f1186fd7d447646c835b47096a15 ] IEEE 754 lets an architecture determine tininess of a floating-point result either before or after rounding, but requires the same choice for every operation. Alpha determines it after rounding, and stdlib's tst-tininess confirms the hardware does so for the results it produces itself. The soft-fp emulation has no notion of the distinction and always determines tininess before rounding, so a result that the hardware would not consider tiny is reported as underflowing whenever the instruction happens to trap for software completion. The two paths then disagree on the same machine. A multiply of the largest subnormal double by 1 + 2^-52 rounds up to the smallest normal and raises no underflow when the operands are normal, but raises it when an operand is subnormal and the instruction traps: glibc math testsuite, test-float32x-float64-mul: Failure: mul_double (0x3.ffffffffffffcp-1024, 0x1.0000000000001p+0): Exception "Underflow" set Add _FP_TININESS_AFTER_ROUNDING, as glibc's copy of soft-fp has, and set it for alpha. It determines tininess by rounding a copy of the result as if the exponent range were unbounded, which is what the definition asks for. A plain check of whether the rounded result came out normal is not equivalent: it differs for values that are still tiny once rounded with an unbounded exponent range but reach the smallest normal on the coarser subnormal grid. That plain check is what the hardware itself does (it decides tininess from the delivered result), and it is why a divide such as -0x4p-128 / 0x1.000002p+0 in FE_DOWNWARD delivers -0x1p-126 and raises nothing although the result is tiny after rounding. Such cases do not trap, so the emulation never sees them; where it does get control, it follows the definition rather than reproducing that deviation, which is what glibc's soft-fp does as well. The macro defaults to zero, so powerpc, sh and sparc keep determining tininess before rounding as they do now. Cc: stable@vger.kernel.org # 5.15+ Reviewed-by: Magnus Lindholm Tested-by: Magnus Lindholm Link: https://lore.kernel.org/r/20260803-alpha-fp-exceptions-v1-3-c99d75608e60@gmail.com Signed-off-by: Matt Turner Signed-off-by: Sasha Levin --- arch/alpha/include/asm/sfp-machine.h | 4 ++++ include/math-emu/op-common.h | 23 +++++++++++++++++++++-- include/math-emu/soft-fp.h | 8 ++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/arch/alpha/include/asm/sfp-machine.h b/arch/alpha/include/asm/sfp-machine.h index 5fe63afbd474f..bff1ad963c689 100644 --- a/arch/alpha/include/asm/sfp-machine.h +++ b/arch/alpha/include/asm/sfp-machine.h @@ -59,6 +59,10 @@ R##_c = FP_CLS_NAN; \ } while (0) +/* Alpha determines tininess after rounding, so the emulation must do the + same as the hardware does for the results it produces itself. */ +#define _FP_TININESS_AFTER_ROUNDING 1 + /* Obtain the current rounding mode. */ #define FP_ROUNDMODE mode #define FP_RND_NEAREST (FPCR_DYN_NORMAL >> FPCR_DYN_SHIFT) diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h index 8ce066c035cfa..1d1ce5c08efcf 100644 --- a/include/math-emu/op-common.h +++ b/include/math-emu/op-common.h @@ -135,6 +135,24 @@ do { \ else \ { \ /* we've got a denormalized number */ \ + int _FP_PACK_CANONICAL_is_tiny = 1; \ + if (_FP_TININESS_AFTER_ROUNDING && X##_e == 0) \ + { \ + /* Architectures that detect tininess after rounding \ + only signal underflow if the result is still \ + subnormal once rounded as if the exponent range \ + were unbounded. Round a copy to find out. */ \ + FP_DECL_##fs(_FP_PACK_CANONICAL_T); \ + /* The class field is not used by the rounding below, \ + and is unused entirely where this block is dead. */ \ + (void)_FP_PACK_CANONICAL_T##_c; \ + _FP_FRAC_COPY_##wc(_FP_PACK_CANONICAL_T, X); \ + _FP_PACK_CANONICAL_T##_s = X##_s; \ + _FP_PACK_CANONICAL_T##_e = X##_e; \ + _FP_ROUND(wc, _FP_PACK_CANONICAL_T); \ + if (_FP_FRAC_OVERP_##wc(fs, _FP_PACK_CANONICAL_T)) \ + _FP_PACK_CANONICAL_is_tiny = 0; \ + } \ X##_e = -X##_e + 1; \ if (X##_e <= _FP_WFRACBITS_##fs) \ { \ @@ -161,8 +179,9 @@ do { \ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ } \ } \ - if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \ - (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \ + if (_FP_PACK_CANONICAL_is_tiny \ + && ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \ + (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))) \ FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ } \ else \ diff --git a/include/math-emu/soft-fp.h b/include/math-emu/soft-fp.h index 5650c16283830..02ada0a9fca16 100644 --- a/include/math-emu/soft-fp.h +++ b/include/math-emu/soft-fp.h @@ -31,6 +31,14 @@ #include #endif +/* Whether the architecture determines tininess of a floating-point + result after rounding rather than before it. IEEE 754 permits either + but requires the same choice for every operation, so this has to agree + with what the hardware does for the results it produces itself. */ +#ifndef _FP_TININESS_AFTER_ROUNDING +#define _FP_TININESS_AFTER_ROUNDING 0 +#endif + #define _FP_WORKBITS 3 #define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3) #define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2) -- 2.53.0