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 AE6E23858D20 for ; Fri, 21 Apr 2023 19:30:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AE6E23858D20 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=1682105412; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type:resent-to:resent-from:resent-message-id: in-reply-to:in-reply-to:references:references; bh=KPP/uYRE9hpA3dkkb17yCYuT2poFRQGXdUzUtj6lsG0=; b=TCcTTss9jd8+QCbbbLG/5SBicGCbQUrrkpeyvrvcM7Ao83zWvQVwqhXeeOslT1WVV2TdNt U8P1LnyxP2HVNV/4KuJbl89jknxthY7mvHbAasy8gUvQTejPSjYu0z5CCftPBUpbKxz7vC 7/1Vb1ytyvCeU/LVx30Xr2R3EU2AtlI= 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-649-VTF2BBMlMr6QG1sKngIxwQ-1; Fri, 21 Apr 2023 15:30:08 -0400 X-MC-Unique: VTF2BBMlMr6QG1sKngIxwQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 7D9E12999B51; Fri, 21 Apr 2023 19:30:08 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.194.25]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0E83C40C83B6; Fri, 21 Apr 2023 19:30:07 +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 33LJU5Wv009195 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 21 Apr 2023 21:30:05 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 33LJU4EI009194; Fri, 21 Apr 2023 21:30:04 +0200 Resent-From: Jakub Jelinek Resent-Date: Fri, 21 Apr 2023 21:30:04 +0200 Resent-Message-ID: Resent-To: Aldy Hernandez , "Joseph S. Myers" , GCC patches , Andrew MacLeod Date: Fri, 21 Apr 2023 18:40:40 +0200 From: Jakub Jelinek To: Aldy Hernandez , "Joseph S. Myers" , GCC patches , Andrew MacLeod Subject: Re: [PATCH] Implement range-op entry for sin/cos. Message-ID: Reply-To: Jakub Jelinek References: <20230418131250.310916-1-aldyh@redhat.com> MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 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,KAM_SHORT,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE 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 Thu, Apr 20, 2023 at 02:59:35PM +0200, Jakub Jelinek via Gcc-patches wrote: > Thanks for working on this. Though expectedly here we are running > again into the discussions we had in November about math properties of the > functions vs. numeric properties in their implementations, how big maximum > error shall we expect for the functions (and whether we should hardcode > it for all implementations, or have some more fine-grained list of expected > ulp errors for each implementation), whether the implementations at least > guarantee the basic mathematical properties of the functions even if they > have some errors (say for sin/cos, if they really never return > 1.0 or < > -1.0) and the same questions repeated for -frounding-math, what kind of > extra errors to expect when using non-default rounding and whether say sin > could ever return nextafter (1.0, 2.0) or even larger value say when > using non-default rounding mode. > https://gcc.gnu.org/pipermail/gcc-patches/2022-November/606466.html > was my attempt to get at least some numbers on some targets, I'm afraid > for most implementations we aren't going to get any numerical proofs of > maximum errors and the like. For sin/cos to check whether the implementation > really never returns > 1.0 or < -1.0 perhaps instead of using randomized > testing we could exhaustively check some range around 0, M_PI, 3*M_PI, > -M_PI, -3*M_PI, and say some much larger multiples of M_PI, say 50 ulps > in each direction about those points, and similarly for sin around M_PI/2 > etc., in all arounding modes. Appart from the ulps ranges which I plan to introduce a target hook next week... > > + if (!lh.maybe_isnan ()) > > This condition isn't sufficient, even if lh can't be NAN, but just > may be +Inf or -Inf, the result needs to include maybe NAN. I've incorporated my other comments into a patch form. I also found missing undefined_p () checks in two spots, the r.set_undefined (); stuff being misplaced (it was done in the lhs.maybe_isnan () case, which is incorrect, if the lhs may be nan, then even if the finite range is say [-30., -10.] or [1.5., 42.], result shouldn't be invalid, because the result still could be NAN and in that case operand of say +-Inf or NAN would be valid. Actually thinking about it some more, perhaps we should do that check before the maybe_isnan () check and if we find the impossible finite, either use r.set_undefined (); of !maybe_isnan () or handle it like known_isnan () otherwise. Also, I think we should remember if it is SIN or COS, we'll need it both for the ulps case and if we improve it for (ub-lb) < 2*PI ranges. Now, talking about that, I'd very much like to avoid finding if some multiple of PI/2 occurs inside of such ranges, the precision of real.cc is clearly not sufficient for that, but perhaps we could use derivative of sin (cos) or of cos (sin) to see if the function on the boundary is increasing or decreasing and from that on both boundaries and their approximate distance find out if the range needs to be extended to +1 or -1. So, just incremental WIP so far... --- gcc/gimple-range-op.cc.jj 2023-04-21 17:09:48.250367999 +0200 +++ gcc/gimple-range-op.cc 2023-04-21 18:37:26.048325391 +0200 @@ -405,17 +405,20 @@ class cfn_sincos : public range_operator public: using range_operator_float::fold_range; using range_operator_float::op1_range; + cfn_sincos (combined_fn cfn) { m_cfn = cfn; } virtual bool fold_range (frange &r, tree type, const frange &lh, const frange &, relation_trio) const final override { + if (lh.undefined_p ()) + return false; if (lh.known_isnan () || lh.known_isinf ()) { r.set_nan (type); return true; } r.set (type, dconstm1, dconst1); - if (!lh.maybe_isnan ()) + if (!lh.maybe_isnan () && !lh.maybe_isinf ()) r.clear_nan (); return true; } @@ -423,15 +426,9 @@ public: const frange &lhs, const frange &, relation_trio) const final override { - if (!lhs.maybe_isnan ()) - { - // If NAN is not valid result, the input cannot include either - // a NAN nor a +-INF. - REAL_VALUE_TYPE lb = real_min_representable (type); - REAL_VALUE_TYPE ub = real_max_representable (type); - r.set (type, lb, ub, nan_state (false, false)); - return true; - } + if (lhs.undefined_p ()) + return false; + // A known NAN means the input is [-INF,-INF][+INF,+INF] U +-NAN, // which we can't currently represent. if (lhs.known_isnan ()) @@ -439,20 +436,38 @@ public: r.set_varying (type); return true; } + // Results outside of [-1.0, +1.0] are impossible. REAL_VALUE_TYPE lb = lhs.lower_bound (); REAL_VALUE_TYPE ub = lhs.upper_bound (); - if (real_less (&lb, &dconstm1) - || real_less (&dconst1, &ub)) + if (real_less (&lb, &dconstm1) || real_less (&dconst1, &ub)) { - r.set_undefined (); + if (!lhs.maybe_isnan ()) + r.set_undefined (); + else + /* If lhs could be NAN and finite result is impossible, + the range is like lhs.known_isnan () above, + [-INF,-INF][+INF,+INF] U +-NAN. */ + r.set_varying (type); + return true; + } + + if (!lhs.maybe_isnan ()) + { + // If NAN is not valid result, the input cannot include either + // a NAN nor a +-INF. + lb = real_min_representable (type); + ub = real_max_representable (type); + r.set (type, lb, ub, nan_state (false, false)); return true; } r.set_varying (type); return true; } -} op_cfn_sincos; +private: + combined_fn m_cfn; +} op_cfn_sin (CFN_SIN), op_cfn_cos (CFN_COS); // Implement range operator for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER. class cfn_toupper_tolower : public range_operator @@ -934,10 +949,15 @@ gimple_range_op_handler::maybe_builtin_c CASE_CFN_SIN: CASE_CFN_SIN_FN: + m_op1 = gimple_call_arg (call, 0); + m_float = &op_cfn_sin; + m_valid = true; + break; + CASE_CFN_COS: CASE_CFN_COS_FN: m_op1 = gimple_call_arg (call, 0); - m_float = &op_cfn_sincos; + m_float = &op_cfn_cos; m_valid = true; break; Jakub