From patchwork Fri Nov 11 11:50:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 18700 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp692732wru; Fri, 11 Nov 2022 03:50:54 -0800 (PST) X-Google-Smtp-Source: AA0mqf5+ZqJK5gawlCmT83iVYrfLZpbL2dkiH23BOvnD2e9eGBYaIZF1cSaLgUlI5CeMPjI4882F X-Received: by 2002:a17:906:37c4:b0:7ae:9c7b:4d5c with SMTP id o4-20020a17090637c400b007ae9c7b4d5cmr1443061ejc.598.1668167454104; Fri, 11 Nov 2022 03:50:54 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668167454; cv=none; d=google.com; s=arc-20160816; b=emUrqiK3U5Mj9G7pVFeKFF7uwsVKVoZ/CHSt9Q/bfUA5Hb7SIqDfR8J0sqk2S8zHmN jOc7aTWteZpxgpGfH9YfiXejBc6weXYUny3SQPP/mBGp/1uNDMh46U9L1Vc8KaEVvbsa q5JbfEyMuAnILrvsxLQZ3lHLpMYqN8vJ8/KD31a1PdEyXRn/pIHStSiHdGQesUhQ7o8T 4mK97a+ewpq76kkjC9F+8gr7HldPllssqJSeHzLZQuCON7OesczK/IcYYDT386CUKZvP lxgFvUddccEW2O+8nAWggwsIPapagHwSAAGOpUH+ZGEGtc/xlklI0pGQ7rueZ/3lMjU5 C3rA== 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=EWxbEtXMaghPsWQmVE6aBqmYkVNkMn1HJb4SPq054iM=; b=M+O0KTH58/0uyqEvsP/e/gyVTVI8zrtzuY7tbXb1FA5ZgB3vZKdNXS20l6Izc0MWru lbGGfZco3pw8vGSlnG4yF2HMeIwF5jD5mkFUb6a72X3NEPwXfNJzA///22j456CHOrLi C5pKJnrO1r5RnlXqlgMZnKUVK/CbDgC3a+SosMBH4M8ZgVuIlbA8FObWDaM7Hk+ISAse AoJ/rcMmfhdjEGv8VF62sK3DznH5DNtOt3w2V5QUzrk5L33dSqJZxvP6ZrN9a2ST7rI6 8eCuXEuoVx54b0xBe/7xLH9XbDbMy+zfp8HLpC14DGUViiRIkf2BBt4cF9FxeHsbWQWa vjwA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=q9JfC7i0; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c 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 (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id h25-20020aa7de19000000b004616acd9cbcsi1791038edv.360.2022.11.11.03.50.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Nov 2022 03:50:54 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=q9JfC7i0; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c 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 E31773858D3C for ; Fri, 11 Nov 2022 11:50:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E31773858D3C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1668167452; bh=EWxbEtXMaghPsWQmVE6aBqmYkVNkMn1HJb4SPq054iM=; 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=q9JfC7i0IMIgWkS38sPhacKo/coSfKLbXqb/AMK4wjeFB9SfBmg4zTNrlMMQTGnfZ N5nE46hmewMg3mNcShqdlnCQOzJoySNL07yKnAex8E93AzwSCto8k8vaBkRV1WtPc5 DgfYNfAPlkzv37rSqm9L5hUySlDzoBX+hgnJaVaM= 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.129.124]) by sourceware.org (Postfix) with ESMTPS id 0C41F3858D35 for ; Fri, 11 Nov 2022 11:50:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0C41F3858D35 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-TIUBb7i6NIKT0TIcdrrYYw-1; Fri, 11 Nov 2022 06:50:06 -0500 X-MC-Unique: TIUBb7i6NIKT0TIcdrrYYw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 174551C087A7 for ; Fri, 11 Nov 2022 11:50:06 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.38]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C3826112131B; Fri, 11 Nov 2022 11:50:05 +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 2ABBo34N3254004 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Nov 2022 12:50:03 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 2ABBo24Z3254003; Fri, 11 Nov 2022 12:50:02 +0100 Date: Fri, 11 Nov 2022 12:50:02 +0100 To: Aldy Hernandez Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] range-op: Implement op[12]_range operators for {PLUS,MINUS,MULT,RDIV}_EXPR Message-ID: References: <20221109090246.1036213-1-aldyh@redhat.com> MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.9 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?1749200356172989895?= X-GMAIL-MSGID: =?utf-8?q?1749200356172989895?= On Wed, Nov 09, 2022 at 04:43:56PM +0100, Aldy Hernandez wrote: > On Wed, Nov 9, 2022 at 3:58 PM Jakub Jelinek wrote: > > > > On Wed, Nov 09, 2022 at 10:02:46AM +0100, Aldy Hernandez wrote: > > > We can implement the op[12]_range entries for plus and minus in terms > > > of each other. These are adapted from the integer versions. > > > > I think for NANs the op[12]_range shouldn't act this way. > > For the forward binary operations, we have the (maybe/known) NAN handling > > of one or both NAN operands resulting in VARYING sign (maybe/known) NAN > > result, that is the somehow the case for the reverse binary operations too, > > if result is (maybe/known) NAN and the other op is not NAN, op is > > VARYING sign (maybe/known) NAN, if other op is (maybe/known) NAN, > > then op is VARYING sign maybe NAN (always maybe, never known). > > But then for + we have the -INF + INF or vice versa into NAN, and that > > is something that shouldn't be considered. If result isn't NAN, then > > neither operand can be NAN, regardless of whether result can be > > +/- INF and the other op -/+ INF. > > Heh. I just ran into this while debugging the problem reported by Xi. > > We are solving NAN = op1 - VARYING, and trying to do it with op1 = NAN > + VARYING, which returns op1 = NAN (incorrectly). > > I suppose in the above case op1 should ideally be > [-INF,-INF][+INF,+INF]+-NAN, but since we can't represent that then > [-INF,+INF] +-NAN, which is actually VARYING. Do you agree? > > I'm reverting this patch as attached, while I sort this out. Here is my (so far only on the testcase tested) patch which reinstalls your change, add the fixups I've talked about and also hooks up reverse operators for MULT_EXPR/RDIV_EXPR. 2022-11-11 Aldy Hernandez Jakub Jelinek * range-op-float.cc (float_binary_op_range_finish): New function. (foperator_plus::op1_range): New. (foperator_plus::op2_range): New. (foperator_minus::op1_range): New. (foperator_minus::op2_range): New. (foperator_mult::op1_range): New. (foperator_mult::op2_range): New. (foperator_div::op1_range): New. (foperator_div::op2_range): New. * gcc.c-torture/execute/ieee/inf-4.c: New test. Jakub --- gcc/range-op-float.cc.jj 2022-11-11 10:55:57.602617289 +0100 +++ gcc/range-op-float.cc 2022-11-11 12:32:19.378633983 +0100 @@ -1861,8 +1861,64 @@ foperator_unordered_equal::op1_range (fr return true; } +// Final tweaks for float binary op op1_range/op2_range. + +static bool +float_binary_op_range_finish (bool ret, frange &r, tree type, + const frange &lhs) +{ + if (!ret) + return ret; + + // If we get a known NAN from reverse op, it means either that + // the other operand was known NAN (in that case we know nothing), + // or the reverse operation introduced a known NAN. + // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too, + // 0 / 0 is known NAN. Just punt in that case. + // Or if lhs is a known NAN, we also don't know anything. + if (r.known_isnan () || lhs.known_isnan ()) + { + r.set_varying (type); + return false; + } + + // If lhs isn't NAN, then neither operand could be NAN, + // even if the reverse operation does introduce a maybe_nan. + if (!lhs.maybe_isnan ()) + r.clear_nan (); + // If lhs is a maybe or known NAN, the operand could be + // NAN. + else + r.update_nan (); + return true; +} + class foperator_plus : public range_operator_float { + using range_operator_float::op1_range; + using range_operator_float::op2_range; +public: + virtual bool op1_range (frange &r, tree type, + const frange &lhs, + const frange &op2, + relation_trio = TRIO_VARYING) const final override + { + if (lhs.undefined_p ()) + return false; + range_op_handler minus (MINUS_EXPR, type); + if (!minus) + return false; + return float_binary_op_range_finish (minus.fold_range (r, type, lhs, op2), + r, type, lhs); + } + virtual bool op2_range (frange &r, tree type, + const frange &lhs, + const frange &op1, + relation_trio = TRIO_VARYING) const final override + { + return op1_range (r, type, lhs, op1); + } +private: void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan, tree type, const REAL_VALUE_TYPE &lh_lb, @@ -1888,6 +1944,31 @@ class foperator_plus : public range_oper class foperator_minus : public range_operator_float { + using range_operator_float::op1_range; + using range_operator_float::op2_range; +public: + virtual bool op1_range (frange &r, tree type, + const frange &lhs, + const frange &op2, + relation_trio = TRIO_VARYING) const final override + { + if (lhs.undefined_p ()) + return false; + return float_binary_op_range_finish (fop_plus.fold_range (r, type, lhs, + op2), + r, type, lhs); + } + virtual bool op2_range (frange &r, tree type, + const frange &lhs, + const frange &op1, + relation_trio = TRIO_VARYING) const final override + { + if (lhs.undefined_p ()) + return false; + return float_binary_op_range_finish (fold_range (r, type, op1, lhs), + r, type, lhs); + } +private: void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan, tree type, const REAL_VALUE_TYPE &lh_lb, @@ -2031,6 +2112,30 @@ protected: class foperator_mult : public foperator_mult_div_base { + using range_operator_float::op1_range; + using range_operator_float::op2_range; +public: + virtual bool op1_range (frange &r, tree type, + const frange &lhs, + const frange &op2, + relation_trio = TRIO_VARYING) const final override + { + if (lhs.undefined_p ()) + return false; + range_op_handler rdiv (RDIV_EXPR, type); + if (!rdiv) + return false; + return float_binary_op_range_finish (rdiv.fold_range (r, type, lhs, op2), + r, type, lhs); + } + virtual bool op2_range (frange &r, tree type, + const frange &lhs, + const frange &op1, + relation_trio = TRIO_VARYING) const final override + { + return op1_range (r, type, lhs, op1); + } +private: void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan, tree type, const REAL_VALUE_TYPE &lh_lb, @@ -2138,6 +2243,31 @@ class foperator_mult : public foperator_ class foperator_div : public foperator_mult_div_base { + using range_operator_float::op1_range; + using range_operator_float::op2_range; +public: + virtual bool op1_range (frange &r, tree type, + const frange &lhs, + const frange &op2, + relation_trio = TRIO_VARYING) const final override + { + if (lhs.undefined_p ()) + return false; + return float_binary_op_range_finish (fop_mult.fold_range (r, type, lhs, + op2), + r, type, lhs); + } + virtual bool op2_range (frange &r, tree type, + const frange &lhs, + const frange &op1, + relation_trio = TRIO_VARYING) const final override + { + if (lhs.undefined_p ()) + return false; + return float_binary_op_range_finish (fold_range (r, type, op1, lhs), + r, type, lhs); + } +private: void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan, tree type, const REAL_VALUE_TYPE &lh_lb, --- gcc/testsuite/gcc.c-torture/execute/ieee/inf-4.c.jj 2022-11-11 12:44:57.615274471 +0100 +++ gcc/testsuite/gcc.c-torture/execute/ieee/inf-4.c 2022-11-11 12:44:13.351879222 +0100 @@ -0,0 +1,26 @@ +__attribute__((noipa)) int +foo (double a, double b) +{ + double c = a - b; + if (!__builtin_isfinite (c)) + { + if (__builtin_isnan (c)) + { + if (!__builtin_isnan (a) && !__builtin_isnan (b)) + return 1; + } + else if (__builtin_isfinite (a) && __builtin_isfinite (b)) + return 2; + } + else if (c == 0 && a != b) + return 3; + return 4; +} + +int +main () +{ + double a = __builtin_inf (); + if (foo (a, a) != 1) + __builtin_abort (); +}