From patchwork Fri Mar 31 10:45:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 77719 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp466666vqo; Fri, 31 Mar 2023 03:46:01 -0700 (PDT) X-Google-Smtp-Source: AKy350YpcZ8CygZJ3YZaV3yYhpmrmpV3CVfsPHWSa0tCawZ7PnFuYVuGLP4zQvroPYKiA8Gq/9AK X-Received: by 2002:aa7:c90d:0:b0:4fb:2060:4c20 with SMTP id b13-20020aa7c90d000000b004fb20604c20mr24788947edt.31.1680259561628; Fri, 31 Mar 2023 03:46:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680259561; cv=none; d=google.com; s=arc-20160816; b=bmKfQ34rsmsURlUl0haH+z1YdBOP9/zQ5Bq2umhKRw2aje6jlYcY6sxgWdFbBk+rAo HpykmMuku18Cb+mImsuHTnnEp7QWzA7Pt3zQw3TY+IMEQTU6vSinhRXGo1TgSGByciV4 xq/j9TKygPMx04myDWa5hLbGXy9avX0P8xUX+HqkMeB+vLz7hAZlDCzycZE0ptL3p2X/ ZR5oV1EFMEzzKmmsXOACrdtF1u0ImDDnfYKminbqpMSpf8dVGJ8qIDa75jbKVBXbIYEl wQ/cbXC9myJ0KxRztV7D83TLhDtLcUQ7JgBvJJ3IT0F8tTUBd9zJtPHtWes/IWHNHY7e LuFw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-disposition:in-reply-to:mime-version:references:message-id :subject:cc:to:date:dmarc-filter:delivered-to:dkim-signature :dkim-filter; bh=W9eYpQhQ3JHVWXetNBJbVFROIigHxHUloiSs9TCYPaY=; b=RNL0+1PWYT5ff5Nz1KI9anQyeIV+yGahLDXVvyv/fmSmQ1uwb0SVlxhlttcwfvCBdb Pnzu4ZhERzZ2vhTGf6G4v3xq2WlKHMivfPmoZJg3zE2DVwz8Qd1kMlZj5NNx/lqE8kEB 3hf6WwpluqBZUVL2oHI1kizcvAbJgwClVQSKY1trBPde1X5P/5vcN6Nn38A8sysbZ04W wFPQqhtVi2tzMJtWLUw9Dp97hacOWtUNvCNVnIVkChpnm4ManZ0GSlKYUEpyYsilaqOT vnfoLIPMK2o0AmDCSLXOTl0F6X9+m+bfZ8JwbTW6lTqf4/i+USvvYm3sEYSYGWhAEC1i amvg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=iXh+GdLI; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id k14-20020aa7d8ce000000b00501daae80cfsi1699665eds.546.2023.03.31.03.46.01 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 31 Mar 2023 03:46:01 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=iXh+GdLI; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7D66A3857C44 for ; Fri, 31 Mar 2023 10:46:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7D66A3857C44 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1680259560; bh=W9eYpQhQ3JHVWXetNBJbVFROIigHxHUloiSs9TCYPaY=; h=Date:To:Cc:Subject:References:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=iXh+GdLI9ySOa39u5LGDQHuR8kmjXHEXUqqkYqLr8fkhqcLAT/p8hnYp6ew+A+tOx sYla78bWlYRw7oJpTNbvQIO/OWMAOnWx9J1zuemNh0jW2CEJoaWXgvnVMOu0jx02QI M7Z5LZbjENkxy22dkFknJxxa48p5swe6FI0rQ6fY= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id DDDA83858D33 for ; Fri, 31 Mar 2023 10:45:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DDDA83858D33 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-454-FzjEX7UzNAya7fGZxndG4A-1; Fri, 31 Mar 2023 06:45:14 -0400 X-MC-Unique: FzjEX7UzNAya7fGZxndG4A-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DBBE285A5B1 for ; Fri, 31 Mar 2023 10:45:13 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.16]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9A003C15BA0; Fri, 31 Mar 2023 10:45:13 +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 32VAjBdC3973929 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 31 Mar 2023 12:45:11 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 32VAjAnb3973928; Fri, 31 Mar 2023 12:45:10 +0200 Date: Fri, 31 Mar 2023 12:45:10 +0200 To: Aldy Hernandez , Andrew MacLeod Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] range-op-float: Further comparison fixes Message-ID: References: MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.3 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1761879850127325041?= X-GMAIL-MSGID: =?utf-8?q?1761879850127325041?= On Fri, Mar 31, 2023 at 09:57:54AM +0200, Jakub Jelinek via Gcc-patches wrote: > and so if maybe_isnan, they always return [0, 1]. Now, thinking about it, > this is unnecessary pessimization, for the case where the ... block > returns range_false (type) we actually could do it also if maybe_isnan (op1, > op2), because if one or both operands are NAN, the comparison will be false, > and if neither is NAN, the comparison will be also false. Will fix > incrementally today. Here it is. 1) the foperator_{,not_}equal::fold_range cases - we have correctly first a case handling known_isnan on either operand, return there range_false (type) - EQ, resp. range_true (type) - NE - next we handle the singleton cases, maybe_isnan + singleton isn't singleton, so these are ok - there is a missing case (not handled in this patch) where both operands are known to be zeros, but not singleton zeros - there is some !maybe_isnan (op1, op2) handling which tries to prove when the operands are certainly not equal and results in range_false (type) - EQ, resp. range_true (type) - NE - otherwise range_true_and_false (type) Now, I think (and this patch implements it) that the !maybe_isnan (op1, op2) check is unnecessary. If we prove that when ignoring maybe NANs, the ranges don't intersect and so the comparison is always false for EQ or always true for NE, if NANs can appear, it doesn't change anything on that either, for EQ if NAN appears, the result is false like what we proved for the finite ranges, for NE if NAN appears, the result is true like what we proved for the finite ranges 2) foperator_{lt,le,gt,ge}::fold_range cases - these have correctly known_isnan on either operand first and return there range_false (type) - then !maybe_isnan (op1, op2) condition guarded checks - finally range_true_and_false (type) - so do that for maybe_isnan (op1, op2) Here in the !maybe_isnan (op1, op2) guarded code we have some condition which results in range_true (type), another condition which results in range_false (type) and otherwise range_true_and_false (type). Now, the condition which results in range_false (type) can be IMHO done also for the maybe_isnan (op1, op2) cases, because it is [0, 0] if both operands are finite or [0, 0] if either operand is NAN. 3) finally, LTGT_EXPR wasn't handled at all. LTGT_EXPR is the inverse comparision to UNEQ_EXPR, I believe both raise exceptions only if either operand is sNaN, UNEQ_EXPR is true if both operands are either equal or either of the operands is NAN, while LTGT_EXPR is true if the operands compare either smaller or larger and is false if either of the operands is NAN. Ok for trunk if this passes bootstrap/regtest? 2023-03-31 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. Jakub --- 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);