From patchwork Fri Sep 19 01:29:06 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 391060 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 96A0214016B for ; Fri, 19 Sep 2014 11:29:25 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:from:to:subject:in-reply-to:message-id :references:mime-version:content-type; q=dns; s=default; b=JjCqV oW7t0xyLkafMTglXZf6XYiSLC9lTMjQQUDaNPy+a633udH9ftt+M3zFI731Y9QUK Vi4kigEDGqL4Xwb/iqtm6Tt01bOzacCg4wvIUBdDOPCGqIz5ARAuMUePdgsfMzW/ SiJHMq1isUsbTqs+bYVlVvhZafQZN9KREkzqOM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:from:to:subject:in-reply-to:message-id :references:mime-version:content-type; s=default; bh=aU6j5mgl0ld bSyKx8PnhyxNYCU8=; b=aw2bA3OvVn6P1UVkSnWcp53HZQ6MAKd5fzXKeqFu4N/ HtQ/nDcANlblDbo6UrWFbT8Ex/VA4TZ4EnEY7fYousWckzb+cdwdjupzQ+hM5mvD 1gpJl4TXf6jA/VGmoK+6fYO5iRwL+K/ExA+WxMGE61xymZOAjC9g0MQhQIGG0rNE = Received: (qmail 13319 invoked by alias); 19 Sep 2014 01:29:18 -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 13291 invoked by uid 89); 19 Sep 2014 01:29:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, UPPERCASE_50_75 autolearn=no version=3.3.2 X-HELO: relay1.mentorg.com Date: Fri, 19 Sep 2014 01:29:06 +0000 From: "Joseph S. Myers" To: Subject: Re: soft-fp: Support more precise "invalid" exceptions In-Reply-To: Message-ID: References: MIME-Version: 1.0 Here is a corrected version of this patch with a bug in _FP_TO_INT's sNaN detection fixed. diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h index af859e2..833658d 100644 --- a/soft-fp/op-common.h +++ b/soft-fp/op-common.h @@ -87,7 +87,8 @@ X##_c = FP_CLS_NAN; \ /* Check for signaling NaN. */ \ if (_FP_FRAC_SNANP (fs, X)) \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_SNAN); \ } \ break; \ } \ @@ -123,14 +124,14 @@ /* Check for a semi-raw value being a signaling NaN and raise the invalid exception if so. */ -#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \ - do \ - { \ - if (X##_e == _FP_EXPMAX_##fs \ - && !_FP_FRAC_ZEROP_##wc (X) \ - && _FP_FRAC_SNANP_SEMIRAW (fs, X)) \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ - } \ +#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \ + do \ + { \ + if (X##_e == _FP_EXPMAX_##fs \ + && !_FP_FRAC_ZEROP_##wc (X) \ + && _FP_FRAC_SNANP_SEMIRAW (fs, X)) \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SNAN); \ + } \ while (0) /* Choose a NaN result from an operation on two semi-raw NaN @@ -741,7 +742,8 @@ R##_s = _FP_NANSIGN_##fs; \ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ _FP_FRAC_SLL_##wc (R, _FP_WORKBITS); \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_ISI); \ } \ else \ { \ @@ -893,7 +895,7 @@ R##_s = _FP_NANSIGN_##fs; \ R##_c = FP_CLS_NAN; \ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_IMZ); \ break; \ \ default: \ @@ -1057,7 +1059,7 @@ _FP_FMA_T##_s = _FP_NANSIGN_##fs; \ _FP_FMA_T##_c = FP_CLS_NAN; \ _FP_FRAC_SET_##wc (_FP_FMA_T, _FP_NANFRAC_##fs); \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_IMZ_FMA); \ break; \ \ default: \ @@ -1102,7 +1104,7 @@ R##_s = _FP_NANSIGN_##fs; \ R##_c = FP_CLS_NAN; \ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_ISI); \ } \ break; \ \ @@ -1176,7 +1178,10 @@ R##_s = _FP_NANSIGN_##fs; \ R##_c = FP_CLS_NAN; \ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | (X##_c == FP_CLS_INF \ + ? FP_EX_INVALID_IDI \ + : FP_EX_INVALID_ZDZ)); \ break; \ \ default: \ @@ -1190,17 +1195,25 @@ raise exceptions for signaling NaN operands, 2 to raise exceptions for all NaN operands. */ -#define _FP_CMP_CHECK_NAN(fs, wc, X, Y, ex) \ - do \ - { \ - if (ex) \ - { \ - if ((ex) == 2 \ - || _FP_ISSIGNAN (fs, wc, X) \ - || _FP_ISSIGNAN (fs, wc, Y)) \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ - } \ - } \ +#define _FP_CMP_CHECK_NAN(fs, wc, X, Y, ex) \ + do \ + { \ + if (ex) \ + { \ + if (FP_EX_INVALID_SNAN || FP_EX_INVALID_VC) \ + { \ + if ((ex) == 2) \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_VC); \ + if (_FP_ISSIGNAN (fs, wc, X) \ + || _FP_ISSIGNAN (fs, wc, Y)) \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SNAN); \ + } \ + else if ((ex) == 2 \ + || _FP_ISSIGNAN (fs, wc, X) \ + || _FP_ISSIGNAN (fs, wc, Y)) \ + FP_SET_EXCEPTION (FP_EX_INVALID); \ + } \ + } \ while (0) /* Main differential comparison routine. The inputs should be raw not @@ -1285,58 +1298,58 @@ /* Main square root routine. The input value should be cooked. */ -#define _FP_SQRT(fs, wc, R, X) \ - do \ - { \ - _FP_FRAC_DECL_##wc (_FP_SQRT_T); \ - _FP_FRAC_DECL_##wc (_FP_SQRT_S); \ - _FP_W_TYPE _FP_SQRT_q; \ - switch (X##_c) \ - { \ - case FP_CLS_NAN: \ - _FP_FRAC_COPY_##wc (R, X); \ - R##_s = X##_s; \ - R##_c = FP_CLS_NAN; \ - break; \ - case FP_CLS_INF: \ - if (X##_s) \ - { \ - R##_s = _FP_NANSIGN_##fs; \ - R##_c = FP_CLS_NAN; /* NAN */ \ - _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ - } \ - else \ - { \ - R##_s = 0; \ - R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \ - } \ - break; \ - case FP_CLS_ZERO: \ - R##_s = X##_s; \ - R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \ - break; \ - case FP_CLS_NORMAL: \ - R##_s = 0; \ - if (X##_s) \ - { \ - R##_c = FP_CLS_NAN; /* NAN */ \ - R##_s = _FP_NANSIGN_##fs; \ - _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ - break; \ - } \ - R##_c = FP_CLS_NORMAL; \ - if (X##_e & 1) \ - _FP_FRAC_SLL_##wc (X, 1); \ - R##_e = X##_e >> 1; \ - _FP_FRAC_SET_##wc (_FP_SQRT_S, _FP_ZEROFRAC_##wc); \ - _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \ - _FP_SQRT_q = _FP_OVERFLOW_##fs >> 1; \ - _FP_SQRT_MEAT_##wc (R, _FP_SQRT_S, _FP_SQRT_T, X, \ - _FP_SQRT_q); \ - } \ - } \ +#define _FP_SQRT(fs, wc, R, X) \ + do \ + { \ + _FP_FRAC_DECL_##wc (_FP_SQRT_T); \ + _FP_FRAC_DECL_##wc (_FP_SQRT_S); \ + _FP_W_TYPE _FP_SQRT_q; \ + switch (X##_c) \ + { \ + case FP_CLS_NAN: \ + _FP_FRAC_COPY_##wc (R, X); \ + R##_s = X##_s; \ + R##_c = FP_CLS_NAN; \ + break; \ + case FP_CLS_INF: \ + if (X##_s) \ + { \ + R##_s = _FP_NANSIGN_##fs; \ + R##_c = FP_CLS_NAN; /* NAN */ \ + _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SQRT); \ + } \ + else \ + { \ + R##_s = 0; \ + R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \ + } \ + break; \ + case FP_CLS_ZERO: \ + R##_s = X##_s; \ + R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \ + break; \ + case FP_CLS_NORMAL: \ + R##_s = 0; \ + if (X##_s) \ + { \ + R##_c = FP_CLS_NAN; /* NAN */ \ + R##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SQRT); \ + break; \ + } \ + R##_c = FP_CLS_NORMAL; \ + if (X##_e & 1) \ + _FP_FRAC_SLL_##wc (X, 1); \ + R##_e = X##_e >> 1; \ + _FP_FRAC_SET_##wc (_FP_SQRT_S, _FP_ZEROFRAC_##wc); \ + _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \ + _FP_SQRT_q = _FP_OVERFLOW_##fs >> 1; \ + _FP_SQRT_MEAT_##wc (R, _FP_SQRT_S, _FP_SQRT_T, X, \ + _FP_SQRT_q); \ + } \ + } \ while (0) /* Convert from FP to integer. Input is raw. */ @@ -1399,12 +1412,17 @@ }) \ : 0); \ if (!_FP_FRAC_ZEROP_##wc (X)) \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ else if (_FP_TO_INT_inexact) \ FP_SET_EXCEPTION (FP_EX_INEXACT); \ } \ else \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_CVI \ + | ((FP_EX_INVALID_SNAN \ + && _FP_ISSIGNAN (fs, wc, X)) \ + ? FP_EX_INVALID_SNAN \ + : 0)); \ } \ else \ { \ @@ -1563,7 +1581,8 @@ if (!_FP_FRAC_ZEROP_##swc (S)) \ { \ if (_FP_FRAC_SNANP (sfs, S)) \ - FP_SET_EXCEPTION (FP_EX_INVALID); \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_SNAN); \ _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs \ - _FP_FRACBITS_##sfs)); \ _FP_SETQNAN (dfs, dwc, D); \ diff --git a/soft-fp/soft-fp.h b/soft-fp/soft-fp.h index 5fb7358..3ced6ca 100644 --- a/soft-fp/soft-fp.h +++ b/soft-fp/soft-fp.h @@ -83,6 +83,44 @@ # define FP_EX_DENORM 0 #endif +/* Sub-exceptions of "invalid". */ +/* Signaling NaN operand. */ +#ifndef FP_EX_INVALID_SNAN +# define FP_EX_INVALID_SNAN 0 +#endif +/* Inf * 0. */ +#ifndef FP_EX_INVALID_IMZ +# define FP_EX_INVALID_IMZ 0 +#endif +/* fma (Inf, 0, c). */ +#ifndef FP_EX_INVALID_IMZ_FMA +# define FP_EX_INVALID_IMZ_FMA 0 +#endif +/* Inf - Inf. */ +#ifndef FP_EX_INVALID_ISI +# define FP_EX_INVALID_ISI 0 +#endif +/* 0 / 0. */ +#ifndef FP_EX_INVALID_ZDZ +# define FP_EX_INVALID_ZDZ 0 +#endif +/* Inf / Inf. */ +#ifndef FP_EX_INVALID_IDI +# define FP_EX_INVALID_IDI 0 +#endif +/* sqrt (negative). */ +#ifndef FP_EX_INVALID_SQRT +# define FP_EX_INVALID_SQRT 0 +#endif +/* Invalid conversion to integer. */ +#ifndef FP_EX_INVALID_CVI +# define FP_EX_INVALID_CVI 0 +#endif +/* Invalid comparison. */ +#ifndef FP_EX_INVALID_VC +# define FP_EX_INVALID_VC 0 +#endif + /* _FP_STRUCT_LAYOUT may be defined as an attribute to determine the struct layout variant used for structures where bit-fields are used to access specific parts of binary floating-point numbers. This is