From patchwork Thu Feb 5 21:52:05 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 4931 Received: (qmail 5025 invoked by alias); 5 Feb 2015 21:52:13 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 5007 invoked by uid 89); 5 Feb 2015 21:52:13 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com Date: Thu, 5 Feb 2015 21:52:05 +0000 From: Joseph Myers To: Subject: soft-fp: Refine FP_EX_DENORM handling for comparisons Message-ID: User-Agent: Alpine 2.10 (DEB 1266 2009-07-14) MIME-Version: 1.0 In , I noted that comparisons in soft-fp did not set FP_EX_DENORM unless denormal operands were flushed to zero. This patch fixes soft-fp to check for denormal operands for comparisons and set that exception whenever FP_EX_DENORM is not zero. In particular, for the one architecture for which the Linux kernel defines FP_EX_DENORM (alpha), this corresponds to the existing logic for comparisons and so allows that logic to be replaced by a simple call to FP_CMP_D when soft-fp is updated in the kernel. Tested for powerpc (e500) that installed stripped shared libraries are unchanged by this patch. Will commit once master reopens for 2.22 development. 2015-02-05 Joseph Myers * soft-fp/op-common.h (_FP_CMP_CHECK_DENORM): New macro. (_FP_CMP_CHECK_FLUSH_ZERO): Likewise. (_FP_CMP): Use_FP_CMP_CHECK_DENORM and _FP_CMP_CHECK_FLUSH_ZERO. (_FP_CMP_EQ): Likewise. (_FP_CMP_UNORD): Use _FP_CMP_CHECK_DENORM. diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h index 6b8b52f..a39baa9 100644 --- a/soft-fp/op-common.h +++ b/soft-fp/op-common.h @@ -1251,6 +1251,46 @@ } \ while (0) +/* Helper for comparisons. If denormal operands would raise an + exception, check for them, and flush to zero as appropriate + (otherwise, we need only check and flush to zero if it might affect + the result, which is done later with _FP_CMP_CHECK_FLUSH_ZERO). */ +#define _FP_CMP_CHECK_DENORM(fs, wc, X, Y) \ + do \ + { \ + if (FP_EX_DENORM != 0) \ + { \ + /* We must ensure the correct exceptions are raised for \ + denormal operands, even though this may not affect the \ + result of the comparison. */ \ + if (FP_DENORM_ZERO) \ + { \ + _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ + _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ + } \ + else \ + { \ + if ((X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X)) \ + || (Y##_e == 0 && !_FP_FRAC_ZEROP_##wc (Y))) \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + } \ + } \ + } \ + while (0) + +/* Helper for comparisons. Check for flushing denormals for zero if + we didn't need to check earlier for any denormal operands. */ +#define _FP_CMP_CHECK_FLUSH_ZERO(fs, wc, X, Y) \ + do \ + { \ + if (FP_EX_DENORM == 0) \ + { \ + _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ + _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ + } \ + } \ + while (0) + /* Main differential comparison routine. The inputs should be raw not cooked. The return is -1, 0, 1 for normal values, UN otherwise. */ @@ -1258,6 +1298,7 @@ #define _FP_CMP(fs, wc, ret, X, Y, un, ex) \ do \ { \ + _FP_CMP_CHECK_DENORM (fs, wc, X, Y); \ /* NANs are unordered. */ \ if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \ @@ -1270,8 +1311,7 @@ int _FP_CMP_is_zero_x; \ int _FP_CMP_is_zero_y; \ \ - _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ - _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ + _FP_CMP_CHECK_FLUSH_ZERO (fs, wc, X, Y); \ \ _FP_CMP_is_zero_x \ = (!X##_e && _FP_FRAC_ZEROP_##wc (X)) ? 1 : 0; \ @@ -1306,6 +1346,7 @@ #define _FP_CMP_EQ(fs, wc, ret, X, Y, ex) \ do \ { \ + _FP_CMP_CHECK_DENORM (fs, wc, X, Y); \ /* NANs are unordered. */ \ if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \ @@ -1315,8 +1356,7 @@ } \ else \ { \ - _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ - _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ + _FP_CMP_CHECK_FLUSH_ZERO (fs, wc, X, Y); \ \ (ret) = !(X##_e == Y##_e \ && _FP_FRAC_EQ_##wc (X, Y) \ @@ -1331,6 +1371,7 @@ #define _FP_CMP_UNORD(fs, wc, ret, X, Y, ex) \ do \ { \ + _FP_CMP_CHECK_DENORM (fs, wc, X, Y); \ (ret) = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))); \ if (ret) \