From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id B0BF93858D28 for ; Sat, 1 Apr 2023 07:39:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B0BF93858D28 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1680334764; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references; bh=e4DxY0uI4wqnBQjkcKEUYG1XO498t8Zfbudj15JtZzM=; b=fI5cV9Gim0neipvCNQYY7YDiiSnlbEHToS6kASenfpaiFex97yHfsYEpMCsWD6aQMSVTfq JpeE9R2cAV/ybajWJ4K6oLPtA0PY0s1+/gI3wh2ttQSg3B1KgUURR4CyN9pNKc7oucHyxE 4k+qNmWaceP8KadSetzWEa8ukcZorAw= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-639-jTGHC4qDNWSr8Qq9At5LhA-1; Sat, 01 Apr 2023 03:39:23 -0400 X-MC-Unique: jTGHC4qDNWSr8Qq9At5LhA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 053681C05AED for ; Sat, 1 Apr 2023 07:39:22 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.16]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 90B3D40C6E67; Sat, 1 Apr 2023 07:39:21 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 3317dBJk1977118 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Sat, 1 Apr 2023 09:39:11 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 3317dA8P1977117; Sat, 1 Apr 2023 09:39:10 +0200 Date: Sat, 1 Apr 2023 09:39:10 +0200 From: Jakub Jelinek To: Aldy Hernandez Cc: Andrew MacLeod , gcc-patches@gcc.gnu.org Subject: Re: [PATCH] range-op-float: Further comparison fixes Message-ID: Reply-To: Jakub Jelinek References: MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Fri, Mar 31, 2023 at 01:28:35PM +0200, Aldy Hernandez wrote: > > Ok for trunk if this passes bootstrap/regtest? > > LGTM Unfortunately I ran into 4 tests where we run into the known bug where if ranger finds out a range of some floating point operation it folds it and throws away the trapping side-effects with it. In particular, e.g. VARYING > __builtin_inf () is now folded to false because no finite or infinite value is larger than +inf, and if NAN is compared against it, the result is false as well. Given that it is a known problem we need to find some solution for in GCC 14, I've just changed those testcases to disable dom and vrp passes which were optimizing it. Another workaround would be to hide the infinity from the optimizers, but given that the test was added exactly to verify match.pd doesn't optimize this for -ftrapping-math, I think disabling dom/vrp is better. So, here is what I've committed (the other patch committed unchanged): 2023-04-01 Jakub Jelinek * range-op-float.cc (foperator_equal::fold_range): Perform the non-singleton handling regardless of maybe_isnan (op1, op2). (foperator_not_equal::fold_range): Likewise. (foperator_lt::fold_range, foperator_le::fold_range, foperator_gt::fold_range, foperator_ge::fold_range): Perform the real_* comparison check which results in range_false (type) even if maybe_isnan (op1, op2). Simplify. (foperator_ltgt): New class. (fop_ltgt): New variable. (floating_op_table::floating_op_table): Handle LTGT_EXPR using fop_ltgt. * gcc.dg/torture/inf-compare-1.c: Add dg-additional-options -fno-tree-dominator-opts -fno-tree-vrp. * gcc.dg/torture/inf-compare-1-float.c: Likewise. * gcc.dg/torture/inf-compare-2.c: Likewise. * gcc.dg/torture/inf-compare-2-float.c: Likewise. --- gcc/range-op-float.cc.jj 2023-03-31 09:30:11.245296618 +0200 +++ gcc/range-op-float.cc 2023-03-31 11:23:04.817876083 +0200 @@ -616,7 +616,7 @@ foperator_equal::fold_range (irange &r, else r = range_false (type); } - else if (!maybe_isnan (op1, op2)) + else { // If ranges do not intersect, we know the range is not equal, // otherwise we don't know anything for sure. @@ -638,8 +638,6 @@ foperator_equal::fold_range (irange &r, else r = range_true_and_false (type); } - else - r = range_true_and_false (type); return true; } @@ -734,7 +732,7 @@ foperator_not_equal::fold_range (irange else r = range_true (type); } - else if (!maybe_isnan (op1, op2)) + else { // If ranges do not intersect, we know the range is not equal, // otherwise we don't know anything for sure. @@ -756,8 +754,6 @@ foperator_not_equal::fold_range (irange else r = range_true_and_false (type); } - else - r = range_true_and_false (type); return true; } @@ -839,17 +835,13 @@ foperator_lt::fold_range (irange &r, tre if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT)) return true; - if (op1.known_isnan () || op2.known_isnan ()) + if (op1.known_isnan () + || op2.known_isnan () + || !real_less (&op1.lower_bound (), &op2.upper_bound ())) r = range_false (type); - else if (!maybe_isnan (op1, op2)) - { - if (real_less (&op1.upper_bound (), &op2.lower_bound ())) - r = range_true (type); - else if (!real_less (&op1.lower_bound (), &op2.upper_bound ())) - r = range_false (type); - else - r = range_true_and_false (type); - } + else if (!maybe_isnan (op1, op2) + && real_less (&op1.upper_bound (), &op2.lower_bound ())) + r = range_true (type); else r = range_true_and_false (type); return true; @@ -959,17 +951,13 @@ foperator_le::fold_range (irange &r, tre if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE)) return true; - if (op1.known_isnan () || op2.known_isnan ()) + if (op1.known_isnan () + || op2.known_isnan () + || !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ())) r = range_false (type); - else if (!maybe_isnan (op1, op2)) - { - if (real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ())) - r = range_true (type); - else if (!real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ())) - r = range_false (type); - else - r = range_true_and_false (type); - } + else if (!maybe_isnan (op1, op2) + && real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ())) + r = range_true (type); else r = range_true_and_false (type); return true; @@ -1073,17 +1061,13 @@ foperator_gt::fold_range (irange &r, tre if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT)) return true; - if (op1.known_isnan () || op2.known_isnan ()) + if (op1.known_isnan () + || op2.known_isnan () + || !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ())) r = range_false (type); - else if (!maybe_isnan (op1, op2)) - { - if (real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ())) - r = range_true (type); - else if (!real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ())) - r = range_false (type); - else - r = range_true_and_false (type); - } + else if (!maybe_isnan (op1, op2) + && real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ())) + r = range_true (type); else r = range_true_and_false (type); return true; @@ -1197,17 +1181,13 @@ foperator_ge::fold_range (irange &r, tre if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE)) return true; - if (op1.known_isnan () || op2.known_isnan ()) + if (op1.known_isnan () + || op2.known_isnan () + || !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ())) r = range_false (type); - else if (!maybe_isnan (op1, op2)) - { - if (real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ())) - r = range_true (type); - else if (!real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ())) - r = range_false (type); - else - r = range_true_and_false (type); - } + else if (!maybe_isnan (op1, op2) + && real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ())) + r = range_true (type); else r = range_true_and_false (type); return true; @@ -2092,6 +2072,87 @@ foperator_unordered_equal::op1_range (fr return true; } +class foperator_ltgt : public range_operator_float +{ + using range_operator_float::fold_range; + using range_operator_float::op1_range; + using range_operator_float::op2_range; +public: + bool fold_range (irange &r, tree type, + const frange &op1, const frange &op2, + relation_trio rel = TRIO_VARYING) const final override + { + if (op1.known_isnan () || op2.known_isnan ()) + { + r = range_false (type); + return true; + } + frange op1_no_nan = op1; + frange op2_no_nan = op2; + if (op1.maybe_isnan ()) + op1_no_nan.clear_nan (); + if (op2.maybe_isnan ()) + op2_no_nan.clear_nan (); + if (!fop_not_equal.fold_range (r, type, op1_no_nan, op2_no_nan, rel)) + return false; + // The result is the same as the ordered version when the + // comparison is true or when the operands cannot be NANs. + if (!maybe_isnan (op1, op2) || r == range_false (type)) + return true; + else + { + r = range_true_and_false (type); + return true; + } + } + bool op1_range (frange &r, tree type, + const irange &lhs, const frange &op2, + relation_trio = TRIO_VARYING) const final override; + bool op2_range (frange &r, tree type, + const irange &lhs, const frange &op1, + relation_trio rel = TRIO_VARYING) const final override + { + return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ()); + } +} fop_ltgt; + +bool +foperator_ltgt::op1_range (frange &r, tree type, + const irange &lhs, + const frange &op2, + relation_trio) const +{ + switch (get_bool_state (r, lhs, type)) + { + case BRS_TRUE: + // A true LTGT means both operands are !NAN, so it's + // impossible for op2 to be a NAN. + if (op2.known_isnan ()) + r.set_undefined (); + else + { + // The true side indicates !NAN and not equal. We can at least + // represent !NAN. + r.set_varying (type); + r.clear_nan (); + } + break; + + case BRS_FALSE: + // If it's false, the result is the same as OP2 plus a NAN. + r = op2; + // Add both zeros if there's the possibility of zero equality. + frange_add_zeros (r, type); + // Add the possibility of a NAN. + r.update_nan (); + break; + + default: + break; + } + return true; +} + // Final tweaks for float binary op op1_range/op2_range. // Return TRUE if the operation is performed and a valid range is available. @@ -2767,6 +2828,7 @@ floating_op_table::floating_op_table () set (UNEQ_EXPR, fop_unordered_equal); set (ORDERED_EXPR, fop_ordered); set (UNORDERED_EXPR, fop_unordered); + set (LTGT_EXPR, fop_ltgt); set (ABS_EXPR, fop_abs); set (NEGATE_EXPR, fop_negate); --- gcc/testsuite/gcc.dg/torture/inf-compare-1.c.jj 2022-10-21 08:56:19.330180242 +0200 +++ gcc/testsuite/gcc.dg/torture/inf-compare-1.c 2023-04-01 09:26:24.385274181 +0200 @@ -3,6 +3,7 @@ /* { dg-add-options ieee } */ /* { dg-require-effective-target fenv_exceptions_double } */ /* { dg-skip-if "fenv" { powerpc-ibm-aix* } } */ +/* { dg-additional-options "-fno-tree-dominator-opts -fno-tree-vrp" } */ #include --- gcc/testsuite/gcc.dg/torture/inf-compare-1-float.c.jj 2022-10-21 08:56:19.330180242 +0200 +++ gcc/testsuite/gcc.dg/torture/inf-compare-1-float.c 2023-04-01 09:26:15.380403321 +0200 @@ -3,6 +3,7 @@ /* { dg-add-options ieee } */ /* { dg-require-effective-target fenv_exceptions } */ /* { dg-skip-if "fenv" { powerpc-ibm-aix* } } */ +/* { dg-additional-options "-fno-tree-dominator-opts -fno-tree-vrp" } */ #include --- gcc/testsuite/gcc.dg/torture/inf-compare-2.c.jj 2022-10-21 08:56:19.330180242 +0200 +++ gcc/testsuite/gcc.dg/torture/inf-compare-2.c 2023-04-01 09:26:43.555999258 +0200 @@ -3,6 +3,7 @@ /* { dg-add-options ieee } */ /* { dg-require-effective-target fenv_exceptions_double } */ /* { dg-skip-if "fenv" { powerpc-ibm-aix* } } */ +/* { dg-additional-options "-fno-tree-dominator-opts -fno-tree-vrp" } */ #include --- gcc/testsuite/gcc.dg/torture/inf-compare-2-float.c.jj 2022-10-21 08:56:19.330180242 +0200 +++ gcc/testsuite/gcc.dg/torture/inf-compare-2-float.c 2023-04-01 09:26:32.682155200 +0200 @@ -3,6 +3,7 @@ /* { dg-add-options ieee } */ /* { dg-require-effective-target fenv_exceptions } */ /* { dg-skip-if "fenv" { powerpc-ibm-aix* } } */ +/* { dg-additional-options "-fno-tree-dominator-opts -fno-tree-vrp" } */ #include Jakub