From patchwork Fri May 5 08:00:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 90327 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp225680vqo; Fri, 5 May 2023 01:01:41 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5MMb8g2HykPPRKCd9lRZkP4EkLJvtHdVPvKL7XYk6Qpwc7e5Crx7kEo2w5tjv1u/bhBdrf X-Received: by 2002:a17:907:d9f:b0:94e:cd9f:1db8 with SMTP id go31-20020a1709070d9f00b0094ecd9f1db8mr549056ejc.11.1683273701199; Fri, 05 May 2023 01:01:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683273701; cv=none; d=google.com; s=arc-20160816; b=yqomcgPZoN3uYzZvpurVGUUNLK2G4quMYf69vFAeYxT2LiTKMr50tG1o72c6eyfpXK ouCjzq/QjEmkUl86Ms0bIPbYblHbgzpxAKsvoSz1ZhtkV7zf9PHjH1TnrjGekP0Papr8 jBheN8x1xKhrvXsvkFS3K3homoMZ8m7stQtZekjLZSByXXn1OKWCyxi7BGPSuopaxG2Z r3I+Ny7svX1pcwheCQJMENnUWFdqDzoz/ceYuLup5rNGnCHiFH0tOaO23OrP+EEmNNET ReBskPxTaoXjJDPpyxk60DgscUZYLo+UjSVFukZ5nESVMvE9nZ2oyJBt/ECYdbrIBOVO kxZA== 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:mime-version:message-id:subject:cc:to:date :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=ribIc4EmOsmNguBNwI2/MD4hu4306y6IyVxUy07XtdY=; b=A9h7kFmG9U6QL+z7moLRlRyGNPJ4Kh5MfsvYgiqXqZx3HbFn6eL9C2J/T5BHViBFz7 tMJsQHHYhA9siGrMKsv4Z4IlmkIoL4W2zhWGpRanxoesL8S/b9LM/+xaKZHFzeM5WO3+ OCeKnXlkLZwNXnko3DyiQtT7clmIcjCwc87ebQSjUsMwW0fGsYSqquuTlyURwq7x1sS9 9ZDvt7HM77eUaf5ZLnl1JPbAjDObF5jIHliEilIC6JygkxJGjUQniwoW93yFTsE4jJpG ePDVXzgPKMFAeJeOKUkIryKvLoLuWnwKAS1rP7ongR+Z/VXdNTcU2pYXfp7OJyrozv3R 4UMg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b="tQ6cWS/h"; 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 fv30-20020a170907509e00b0094f0b10661esi895792ejc.503.2023.05.05.01.01.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 May 2023 01:01:41 -0700 (PDT) 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="tQ6cWS/h"; 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 982763857701 for ; Fri, 5 May 2023 08:01:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 982763857701 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1683273699; bh=ribIc4EmOsmNguBNwI2/MD4hu4306y6IyVxUy07XtdY=; h=Date:To:Cc:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=tQ6cWS/hgFJE346soRxwfFI2yXkA2Na/fsV6mf2sx7Dn7xlRlf5QH7KMxmsIVuGpP pNdOqz1+7TwjKHrYl/5PURY43gJCWlJKI54xHtbocF9UqSjZqQZ9rJqwZ+tgoT1/UH yOgO94wTnsGDmDZUNsa0M5Wd7kC01JZxb1viO+Hg= 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 8C13F3858D20 for ; Fri, 5 May 2023 08:00:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8C13F3858D20 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-664-d7AUbKa_OQak0JEjgXHm2Q-1; Fri, 05 May 2023 04:00:47 -0400 X-MC-Unique: d7AUbKa_OQak0JEjgXHm2Q-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C7F5518E52C6 for ; Fri, 5 May 2023 08:00:46 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.194.156]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8B3AB492C13; Fri, 5 May 2023 08:00:46 +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 34580i3J1358025 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 5 May 2023 10:00:44 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 34580hiW1358024; Fri, 5 May 2023 10:00:43 +0200 Date: Fri, 5 May 2023 10:00:43 +0200 To: Aldy Hernandez Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] gimple-range-op: Improve handling of sqrt ranges Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.4 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, 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 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?1765040404514501762?= X-GMAIL-MSGID: =?utf-8?q?1765040404514501762?= Hi! The previous patch just added basic intrinsic ranges for sqrt ([-0.0, +Inf] +-NAN being the general result range of the function and [-0.0, +Inf] the general operand range if result isn't NAN etc.), the following patch intersects those ranges with particular range computed from argument or result's exact range with the expected error in ulps taken into account and adds a function (frange_arithmetic variant) which can be used by other functions as well as helper. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2023-05-05 Jakub Jelinek * value-range.h (frange_arithmetic): Declare. * range-op-float.cc (frange_arithmetic): No longer static. * gimple-range-op.cc (frange_mpfr_arg1): New function. (cfn_sqrt::fold_range): Intersect the generic boundaries range with range computed from sqrt of the particular bounds. (cfn_sqrt::op1_range): Intersect the generic boundaries range with range computed from squared particular bounds. * gcc.dg/tree-ssa/range-sqrt-2.c: New test. Jakub --- gcc/value-range.h.jj 2023-05-04 13:34:45.140336099 +0200 +++ gcc/value-range.h 2023-05-04 16:28:18.286108178 +0200 @@ -1294,5 +1294,8 @@ frange::nan_signbit_p (bool &signbit) co void frange_nextafter (enum machine_mode, REAL_VALUE_TYPE &, const REAL_VALUE_TYPE &); +void frange_arithmetic (enum tree_code, tree, REAL_VALUE_TYPE &, + const REAL_VALUE_TYPE &, const REAL_VALUE_TYPE &, + const REAL_VALUE_TYPE &); #endif // GCC_VALUE_RANGE_H --- gcc/range-op-float.cc.jj 2023-05-04 13:34:45.139336114 +0200 +++ gcc/range-op-float.cc 2023-05-04 16:28:18.285108192 +0200 @@ -305,7 +305,7 @@ frange_nextafter (enum machine_mode mode // SF/DFmode (when storing into memory from the 387 stack). Maybe // this is ok as well though it is just occasionally more precise. ?? -static void +void frange_arithmetic (enum tree_code code, tree type, REAL_VALUE_TYPE &result, const REAL_VALUE_TYPE &op1, --- gcc/gimple-range-op.cc.jj 2023-05-04 13:34:45.139336114 +0200 +++ gcc/gimple-range-op.cc 2023-05-04 19:58:44.842606865 +0200 @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. #include "value-query.h" #include "gimple-range.h" #include "attr-fnspec.h" +#include "realmpfr.h" // Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names // on the statement. For efficiency, it is an error to not pass in enough @@ -403,6 +404,66 @@ public: } } op_cfn_copysign; +/* Compute FUNC (ARG) where FUNC is a mpfr function. If RES_LOW is non-NULL, + set it to low bound of possible range if the function is expected to have + ULPS precision and similarly if RES_HIGH is non-NULL, set it to high bound. + If the function returns false, the results weren't set. */ + +static bool +frange_mpfr_arg1 (REAL_VALUE_TYPE *res_low, REAL_VALUE_TYPE *res_high, + int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t), + const REAL_VALUE_TYPE &arg, tree type, unsigned ulps) +{ + if (ulps == ~0U || !real_isfinite (&arg)) + return false; + machine_mode mode = TYPE_MODE (type); + const real_format *format = REAL_MODE_FORMAT (mode); + auto_mpfr m (format->p); + mpfr_from_real (m, &arg, MPFR_RNDN); + mpfr_clear_flags (); + bool inexact = func (m, m, MPFR_RNDN); + if (!mpfr_number_p (m) || mpfr_overflow_p () || mpfr_underflow_p ()) + return false; + + REAL_VALUE_TYPE value, result; + real_from_mpfr (&value, m, format, MPFR_RNDN); + if (!real_isfinite (&value)) + return false; + if ((value.cl == rvc_zero) != (mpfr_zero_p (m) != 0)) + inexact = true; + + real_convert (&result, format, &value); + if (!real_isfinite (&result)) + return false; + bool round_low = false; + bool round_high = false; + if (!ulps && flag_rounding_math) + ++ulps; + if (inexact || !real_identical (&result, &value)) + { + if (MODE_COMPOSITE_P (mode)) + round_low = round_high = true; + else + { + round_low = !real_less (&result, &value); + round_high = !real_less (&value, &result); + } + } + if (res_low) + { + *res_low = result; + for (unsigned int i = 0; i < ulps + round_low; ++i) + frange_nextafter (mode, *res_low, dconstninf); + } + if (res_high) + { + *res_high = result; + for (unsigned int i = 0; i < ulps + round_high; ++i) + frange_nextafter (mode, *res_high, dconstinf); + } + return true; +} + class cfn_sqrt : public range_operator_float { public: @@ -434,6 +495,20 @@ public: } if (!lh.maybe_isnan () && !real_less (&lh.lower_bound (), &dconst0)) r.clear_nan (); + + unsigned ulps + = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), false); + if (ulps == ~0U) + return true; + REAL_VALUE_TYPE lb = lh.lower_bound (); + REAL_VALUE_TYPE ub = lh.upper_bound (); + if (!frange_mpfr_arg1 (&lb, NULL, mpfr_sqrt, lb, type, ulps)) + lb = dconstninf; + if (!frange_mpfr_arg1 (NULL, &ub, mpfr_sqrt, ub, type, ulps)) + ub = dconstinf; + frange r2; + r2.set (type, lb, ub); + r.intersect (r2); return true; } virtual bool op1_range (frange &r, tree type, @@ -455,27 +530,70 @@ public: } // Results outside of [-0.0, +Inf] are impossible. - const REAL_VALUE_TYPE &ub = lhs.upper_bound (); - if (real_less (&ub, &dconstm0)) + unsigned bulps + = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), true); + if (bulps != ~0U) { - 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. - goto known_nan; - return true; + const REAL_VALUE_TYPE &ub = lhs.upper_bound (); + REAL_VALUE_TYPE m0 = dconstm0; + while (bulps--) + frange_nextafter (TYPE_MODE (type), m0, dconstninf); + if (real_less (&ub, &m0)) + { + 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. + goto known_nan; + return true; + } } if (!lhs.maybe_isnan ()) + // If NAN is not valid result, the input cannot include either + // a NAN nor values smaller than -0. + r.set (type, dconstm0, dconstinf, nan_state (false, false)); + else + r.set_varying (type); + + unsigned ulps + = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), false); + if (ulps == ~0U) + return true; + REAL_VALUE_TYPE lb = lhs.lower_bound (); + REAL_VALUE_TYPE ub = lhs.upper_bound (); + if (real_less (&dconst0, &lb)) + { + for (unsigned i = 0; i < ulps; ++i) + frange_nextafter (TYPE_MODE (type), lb, dconstninf); + if (real_less (&dconst0, &lb)) + { + REAL_VALUE_TYPE op = lb; + frange_arithmetic (MULT_EXPR, type, lb, op, op, dconstninf); + } + else + lb = dconstninf; + } + else + lb = dconstninf; + if (real_isfinite (&ub) && real_less (&dconst0, &ub)) { - // If NAN is not valid result, the input cannot include either - // a NAN nor values smaller than -0. - r.set (type, dconstm0, dconstinf, nan_state (false, false)); - return true; + for (unsigned i = 0; i < ulps; ++i) + frange_nextafter (TYPE_MODE (type), ub, dconstinf); + if (real_isfinite (&ub)) + { + REAL_VALUE_TYPE op = ub; + frange_arithmetic (MULT_EXPR, type, ub, op, op, dconstinf); + } + else + ub = dconstinf; } - - r.set_varying (type); + else + ub = dconstinf; + frange r2; + r2.set (type, lb, ub); + r.intersect (r2); return true; } } op_cfn_sqrt; --- gcc/testsuite/gcc.dg/tree-ssa/range-sqrt-2.c.jj 2023-05-04 20:05:26.780872035 +0200 +++ gcc/testsuite/gcc.dg/tree-ssa/range-sqrt-2.c 2023-05-04 19:50:28.624689220 +0200 @@ -0,0 +1,44 @@ +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-evrp -fno-thread-jumps" } + +#include + +void use (double); +void link_error (); + +void +foo (double x) +{ + if (x < 1.0 || x > 9.0) + __builtin_unreachable (); + x = sqrt (x); + if (x < 0.875 || x > 3.125) + link_error (); + use (x); +} + +void +bar (double x) +{ + if (sqrt (x) >= 2.0 && sqrt (x) <= 4.0) + { + if (__builtin_isnan (x)) + link_error (); + if (x < 3.875 || x > 16.125) + link_error (); + } +} + +void +stool (double x) +{ + if (x >= 64.0) + { + double res1 = sqrt (x); + double res2 = __builtin_sqrt (x); + if (res1 < 7.875 || res2 < 7.875) + link_error (); + } +} + +// { dg-final { scan-tree-dump-not "link_error" "evrp" { target { { *-*-linux* } && { glibc } } } } }