From patchwork Thu Nov 26 08:38:55 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sujoy Saraswati X-Patchwork-Id: 57322 Delivered-To: patch@linaro.org Received: by 10.112.155.196 with SMTP id vy4csp376366lbb; Thu, 26 Nov 2015 00:40:20 -0800 (PST) X-Received: by 10.98.43.18 with SMTP id r18mr38305693pfr.2.1448527220120; Thu, 26 Nov 2015 00:40:20 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id u81si40439439pfa.147.2015.11.26.00.40.19 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 26 Nov 2015 00:40:20 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-415463-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; spf=pass (google.com: domain of gcc-patches-return-415463-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-415463-patch=linaro.org@gcc.gnu.org; dkim=pass header.i=@gcc.gnu.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:content-type :content-transfer-encoding:mime-version; q=dns; s=default; b=FRg dSA7kew8r0NX6ke2wwY2KROtQ0SkYEDEgxTQjTDVf7YATFqZc4CYJSKqtFpRashF IHxD3xoh9BjhKBKLnamsETiV7q62I1+WOd8g3fHrUcD3MEuYdZf62iv8z4qLLJRr dMlxJtCvXyqy4ehhakjzNxsVhyo5ryp5x9wJwTGo= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:content-type :content-transfer-encoding:mime-version; s=default; bh=qFpGpa3g1 4Eaqlo52DsNeuYitpc=; b=FP043tgZQB/Kc9f7/1DZosXHgfyr7emYZAQUqT67z O9G8E7A22GbXfAbuOdakiFqFBuG4E9L7vQao1fYMR+iaxzJgRRq6kNck42MhrttG r1qc3Hwk7DU9VxkeGdhnGFY36kq0Ohwgk5wsQ1YUxuvZAf7IdTS4Yt/dX0ZObFfn GY= Received: (qmail 108420 invoked by alias); 26 Nov 2015 08:40:06 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 108399 invoked by uid 89); 26 Nov 2015 08:40:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.1 required=5.0 tests=AWL, BAYES_50, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY autolearn=no version=3.3.2 X-HELO: g4t3425.houston.hp.com Received: from g4t3425.houston.hp.com (HELO g4t3425.houston.hp.com) (15.201.208.53) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 26 Nov 2015 08:40:03 +0000 Received: from G9W0364.americas.hpqcorp.net (g9w0364.houston.hp.com [16.216.193.45]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by g4t3425.houston.hp.com (Postfix) with ESMTPS id A5FC5BC; Thu, 26 Nov 2015 08:40:01 +0000 (UTC) Received: from G4W6306.americas.hpqcorp.net (16.210.26.231) by G9W0364.americas.hpqcorp.net (16.216.193.45) with Microsoft SMTP Server (TLS) id 14.3.169.1; Thu, 26 Nov 2015 08:38:56 +0000 Received: from G4W3297.americas.hpqcorp.net ([169.254.11.80]) by G4W6306.americas.hpqcorp.net ([16.210.26.231]) with mapi id 14.03.0169.001; Thu, 26 Nov 2015 08:38:56 +0000 From: "Saraswati, Sujoy (OSTL)" To: Joseph Myers , Sujoy Saraswati , GCC Patches CC: Richard Biener Subject: Fix 61441 [5/5] Disable various transformations for signaling NaN operands Date: Thu, 26 Nov 2015 08:38:55 +0000 Message-ID: <5379BA8D7E9D7E4D87BF6749A92854C248FC90F6@G4W3297.americas.hpqcorp.net> MIME-Version: 1.0 Hi, This patch avoids various transformations with signaling NaN operands when flag_signaling_nans is on, to avoid folding which would lose exceptions. A test case for this change is also added as part of this patch. Regards, Sujoy 2015-11-26 Sujoy Saraswati PR tree-optimization/61441 * fold-const.c (const_binop): Convert sNaN to qNaN when flag_signaling_nans is off. (const_unop): Avoid the operation, other than NEGATE and ABS, if flag_signaling_nans is on and the operand is an sNaN. (fold_convert_const_real_from_real): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (integer_valued_real_unary_p): Update comment stating it returns false for sNaN values. (integer_valued_real_binary_p, integer_valued_real_call_p): Same. (integer_valued_real_single_p): Same. (integer_valued_real_invalid_p, integer_valued_real_p): Same. * fold-const-call.c (fold_const_pow): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (fold_const_builtin_load_exponent) Same. (fold_const_call_sss): Same for BUILT_IN_POWI. * gimple-fold.c (gimple_assign_integer_valued_real_p): Same. (gimple_call_integer_valued_real_p): Same. (gimple_phi_integer_valued_real_p): Same. (gimple_stmt_integer_valued_real_p): Same. * simplify-rtx.c (simplify_const_unary_operation): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (simplify_const_binary_operation): Same. * tree-ssa-math-opts.c (gimple_expand_builtin_pow): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. PR tree-optimization/61441 * gcc.dg/pr61441.c: New testcase. =================================================================== diff -u -p a/gcc/fold-const.c b/gcc/fold-const.c --- a/gcc/fold-const.c 2015-11-25 15:24:49.656116740 +0530 +++ b/gcc/fold-const.c 2015-11-25 15:25:07.712117294 +0530 @@ -1166,9 +1166,21 @@ const_binop (enum tree_code code, tree a /* If either operand is a NaN, just return it. Otherwise, set up for floating-point trap; we return an overflow. */ if (REAL_VALUE_ISNAN (d1)) - return arg1; + { + /* Make resulting NaN value to be qNaN when flag_signaling_nans + is off. */ + d1.signalling = 0; + t = build_real (type, d1); + return t; + } else if (REAL_VALUE_ISNAN (d2)) - return arg2; + { + /* Make resulting NaN value to be qNaN when flag_signaling_nans + is off. */ + d2.signalling = 0; + t = build_real (type, d2); + return t; + } inexact = real_arithmetic (&value, code, &d1, &d2); real_convert (&result, mode, &value); @@ -1538,6 +1550,15 @@ const_binop (enum tree_code code, tree t tree const_unop (enum tree_code code, tree type, tree arg0) { + /* Don't perform the operation, other than NEGATE and ABS, if + flag_signaling_nans is on and the operand is a NaN. */ + if (TREE_CODE (arg0) == REAL_CST + && HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))) + && REAL_VALUE_ISSIGNALING_NAN (TREE_REAL_CST (arg0)) + && code != NEGATE_EXPR + && code != ABS_EXPR) + return NULL_TREE; + switch (code) { CASE_CONVERT: @@ -1949,6 +1970,12 @@ fold_convert_const_real_from_real (tree REAL_VALUE_TYPE value; tree t; + /* Don't perform the operation if flag_signaling_nans is on + and the operand is a NaN. */ + if (HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))) + && REAL_VALUE_ISSIGNALING_NAN (TREE_REAL_CST (arg1))) + return NULL_TREE; + real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1)); t = build_real (type, value); @@ -13420,7 +13447,7 @@ tree_single_nonzero_warnv_p (tree t, boo /* Return true if the floating point result of (CODE OP0) has an integer value. We also allow +Inf, -Inf and NaN to be considered - integer values. + integer values. Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ @@ -13453,7 +13480,7 @@ integer_valued_real_unary_p (tree_code c /* Return true if the floating point result of (CODE OP0 OP1) has an integer value. We also allow +Inf, -Inf and NaN to be considered - integer values. + integer values. Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ @@ -13477,8 +13504,8 @@ integer_valued_real_binary_p (tree_code /* Return true if the floating point result of calling FNDECL with arguments ARG0 and ARG1 has an integer value. We also allow +Inf, -Inf and NaN to be - considered integer values. If FNDECL takes fewer than 2 arguments, - the remaining ARGn are null. + considered integer values. Return false for signalling NaN. If FNDECL + takes fewer than 2 arguments, the remaining ARGn are null. DEPTH is the current nesting depth of the query. */ @@ -13507,7 +13534,7 @@ integer_valued_real_call_p (combined_fn /* Return true if the floating point expression T (a GIMPLE_SINGLE_RHS) has an integer value. We also allow +Inf, -Inf and NaN to be - considered integer values. + considered integer values. Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ @@ -13541,7 +13568,7 @@ integer_valued_real_single_p (tree t, in /* Return true if the floating point expression T (a GIMPLE_INVALID_RHS) has an integer value. We also allow +Inf, -Inf and NaN to be - considered integer values. + considered integer values. Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ @@ -13569,6 +13596,7 @@ integer_valued_real_invalid_p (tree t, i /* Return true if the floating point expression T has an integer value. We also allow +Inf, -Inf and NaN to be considered integer values. + Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ =================================================================== diff -u -p a/gcc/fold-const-call.c b/gcc/fold-const-call.c --- a/gcc/fold-const-call.c 2015-11-25 15:38:34.780142086 +0530 +++ b/gcc/fold-const-call.c 2015-11-25 15:38:05.840141197 +0530 @@ -512,7 +512,11 @@ fold_const_pow (real_value *result, cons || !real_equal (arg0, &dconst0))) { bool inexact = real_powi (result, format, arg0, n1); - if (flag_unsafe_math_optimizations || !inexact) + /* Avoid the folding if flag_signaling_nans is on. */ + if (flag_unsafe_math_optimizations + || (!inexact + && !(flag_signaling_nans + && REAL_VALUE_ISSIGNALING_NAN (*arg0)))) return true; } @@ -541,6 +545,13 @@ fold_const_builtin_load_exponent (real_v if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj)) return false; + /* Don't perform operation if we honor signaling NaNs and + operand is a NaN. */ + if (!flag_unsafe_math_optimizations + && flag_signaling_nans + && REAL_VALUE_ISSIGNALING_NAN (*arg0)) + return false; + REAL_VALUE_TYPE initial_result; real_ldexp (&initial_result, arg0, arg1.to_shwi ()); @@ -1202,6 +1213,12 @@ fold_const_call_sss (real_value *result, format)); CASE_CFN_POWI: + /* Avoid the folding if flag_signaling_nans is on. */ + if (!flag_unsafe_math_optimizations + && flag_signaling_nans + && REAL_VALUE_ISSIGNALING_NAN (*arg0)) + return false; + real_powi (result, format, arg0, arg1.to_shwi ()); return true; =================================================================== diff -u -p a/gcc/gimple-fold.c b/gcc/gimple-fold.c --- a/gcc/gimple-fold.c 2015-11-25 15:41:58.200148334 +0530 +++ b/gcc/gimple-fold.c 2015-11-25 15:41:33.100147563 +0530 @@ -6266,7 +6266,7 @@ gimple_stmt_nonnegative_warnv_p (gimple /* Return true if the floating-point value computed by assignment STMT is known to have an integer value. We also allow +Inf, -Inf and NaN - to be considered integer values. + to be considered integer values. Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ @@ -6295,7 +6295,7 @@ gimple_assign_integer_valued_real_p (gim /* Return true if the floating-point value computed by call STMT is known to have an integer value. We also allow +Inf, -Inf and NaN to be - considered integer values. + considered integer values. Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ @@ -6314,7 +6314,7 @@ gimple_call_integer_valued_real_p (gimpl /* Return true if the floating-point result of phi STMT is known to have an integer value. We also allow +Inf, -Inf and NaN to be considered - integer values. + integer values. Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ @@ -6332,7 +6332,7 @@ gimple_phi_integer_valued_real_p (gimple /* Return true if the floating-point value computed by STMT is known to have an integer value. We also allow +Inf, -Inf and NaN to be - considered integer values. + considered integer values. Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ =================================================================== diff -u -p a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c --- a/gcc/simplify-rtx.c 2015-11-25 15:49:46.740162727 +0530 +++ b/gcc/simplify-rtx.c 2015-11-25 15:49:03.200161389 +0530 @@ -1703,6 +1703,11 @@ simplify_const_unary_operation (enum rtx } real_from_integer (&d, mode, std::make_pair (op, op_mode), SIGNED); + + /* Avoid the folding if flag_signaling_nans is on. */ + if (HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d)) + return 0; + d = real_value_truncate (mode, d); return const_double_from_real_value (d, mode); } @@ -1721,6 +1726,11 @@ simplify_const_unary_operation (enum rtx } real_from_integer (&d, mode, std::make_pair (op, op_mode), UNSIGNED); + + /* Avoid the folding if flag_signaling_nans is on. */ + if (HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d)) + return 0; + d = real_value_truncate (mode, d); return const_double_from_real_value (d, mode); } @@ -1825,16 +1835,25 @@ simplify_const_unary_operation (enum rtx d = real_value_negate (&d); break; case FLOAT_TRUNCATE: - d = real_value_truncate (mode, d); + /* Don't perform the operation if flag_signaling_nans is on + and the operand is a NaN. */ + if (!(HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d))) + d = real_value_truncate (mode, d); break; case FLOAT_EXTEND: /* All this does is change the mode, unless changing mode class. */ - if (GET_MODE_CLASS (mode) != GET_MODE_CLASS (GET_MODE (op))) + /* Don't perform the operation if flag_signaling_nans is on + and the operand is a NaN. */ + if (GET_MODE_CLASS (mode) != GET_MODE_CLASS (GET_MODE (op)) + && !(HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d))) real_convert (&d, mode, &d); break; case FIX: - real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL); + /* Don't perform the operation if flag_signaling_nans is on + and the operand is a NaN. */ + if (!(HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d))) + real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL); break; case NOT: { @@ -3886,16 +3905,20 @@ simplify_const_binary_operation (enum rt else { REAL_VALUE_TYPE f0, f1, value, result; + const REAL_VALUE_TYPE *opr0, *opr1; bool inexact; - real_convert (&f0, mode, CONST_DOUBLE_REAL_VALUE (op0)); - real_convert (&f1, mode, CONST_DOUBLE_REAL_VALUE (op1)); + opr0 = CONST_DOUBLE_REAL_VALUE (op0); + opr1 = CONST_DOUBLE_REAL_VALUE (op1); if (HONOR_SNANS (mode) - && (REAL_VALUE_ISSIGNALING_NAN (f0) - || REAL_VALUE_ISSIGNALING_NAN (f1))) + && (REAL_VALUE_ISSIGNALING_NAN (*opr0) + || REAL_VALUE_ISSIGNALING_NAN (*opr1))) return 0; + real_convert (&f0, mode, opr0); + real_convert (&f1, mode, opr1); + if (code == DIV && real_equal (&f1, &dconst0) && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) =================================================================== diff -u -p a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c --- a/gcc/tree-ssa-math-opts.c 2015-11-25 15:52:00.564166838 +0530 +++ b/gcc/tree-ssa-math-opts.c 2015-11-23 16:10:39.694893171 +0530 @@ -1480,6 +1480,13 @@ gimple_expand_builtin_pow (gimple_stmt_i if (TREE_CODE (arg1) != REAL_CST) return NULL_TREE; + /* Don't perform the operation if flag_signaling_nans is on + and the operand is a NaN. */ + if (HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))) + && (REAL_VALUE_ISSIGNALING_NAN (TREE_REAL_CST (arg0)) + || REAL_VALUE_ISSIGNALING_NAN (TREE_REAL_CST (arg1)))) + return NULL_TREE; + /* If the exponent is equivalent to an integer, expand to an optimal multiplication sequence when profitable. */ c = TREE_REAL_CST (arg1); Index: gcc/testsuite/gcc.dg/pr61441.c =================================================================== --- gcc/testsuite/gcc.dg/pr61441.c (revision 0) +++ gcc/testsuite/gcc.dg/pr61441.c (working copy) @@ -0,0 +1,61 @@ +/* { dg-do run } */ +/* { dg-options "-O1 -lm" } */ + +#define _GNU_SOURCE +#include +#include + +void conversion() +{ + float sNaN = __builtin_nansf (""); + double x = (double) sNaN; + if (issignaling(x)) + { + __builtin_abort(); + } +} + +enum op {Add, Mult, Div, Abs}; + +void operation(enum op t) +{ + float x, y; + float sNaN = __builtin_nansf (""); + switch (t) + { + case Abs: + x = fabs(sNaN); + break; + case Add: + x = sNaN + 2.0; + break; + case Mult: + x = sNaN * 2.0; + break; + case Div: + default: + x = sNaN / 2.0; + break; + } + if (t == Abs) + { + if (!issignaling(x)) + { + __builtin_abort(); + } + } + else if (issignaling(x)) + { + __builtin_abort(); + } +} + +int main (void) +{ + conversion(); + operation(Add); + operation(Mult); + operation(Div); + operation(Abs); + return 0; +}