Message ID | 20220906072901.3472801-1-aldyh@redhat.com |
---|---|
State | New, archived |
Headers |
Return-Path: <gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5044:0:0:0:0:0 with SMTP id h4csp508261wrt; Tue, 6 Sep 2022 00:34:21 -0700 (PDT) X-Google-Smtp-Source: AA6agR6f3Tr2TPf9sF+d0BPLNq4fcWIqMELtyh3o9GNkJZ+z7Sj5D41AgkfknuaRAZFYN8CDARlW X-Received: by 2002:a17:907:3d8b:b0:741:9f51:ac16 with SMTP id he11-20020a1709073d8b00b007419f51ac16mr27247431ejc.39.1662449661433; Tue, 06 Sep 2022 00:34:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1662449661; cv=none; d=google.com; s=arc-20160816; b=wL/xSUwN/MUywQvuU5aTC4af4jU39/74E7W+MdCyv6+wMXie3KmhCVvEyPElKPq5fW aOPedur/9jIGX7v9PKF6h7zZL81vvDhuOuSQXE8W7B5krS19o5RbraVxoE6+tca9EcvK FaEHs+2U/fcPyXpKmNkJq4wPctB7qmTkn8NDM114m6qd63VXjBA0Urz0kcOnbSgQx/wd OYtaQQ85k23wIyRAR36ey9DonSVgGisNI5KsoJ+HNQgmJHFyH4JPKQJLOUY2lJ10/3sc uhiH1ZOkPWv5jelXME13t8wigXYBX3yr+lXUC0p61+zAzS/3xXskdDJ/gshPMHY/d5Mm le7g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:reply-to:from:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:message-id:date:subject:to :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=bWD0quz3Hrx2YQ7y4QUAwOReCy5myqk3JFogInQl13I=; b=vqrGAC8qHYfLq/7q7vZGjQpiW3TtQpkZAAv34Y4oe9MIpmKFXoeNb69TjwBNA8vUbQ +3BJdmKhj2j9uEp+VALbdee9EC0yuo3sMkRabaVSRgga03C1StHXumwNbzxZ11VeSzNz /ca6TSqZd9ACzHr/LCrI6ZO13BvB6jiaJR4YIcgay7wpNZkwK0zBhjupEwR6xOSobyiW rXq+yHKUfkNfVG1/P5b9sZuZhR2pc5Haba1G6wnx0fobVTun0p3fYW8mGhWvmhvT4iEZ LB7XXDAmLGDsrYsVg5D1LgW6ryGQfdbYVhsGAn8r+t+cMzVzT14gOxHor9mjOOEBo1zq GDcw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=bqcfSUtM; 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 (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id o21-20020a170906975500b0073d6e0416f9si10193449ejy.671.2022.09.06.00.34.21 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Sep 2022 00:34:21 -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=bqcfSUtM; 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 BA2B1388451B for <ouuuleilei@gmail.com>; Tue, 6 Sep 2022 07:29:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BA2B1388451B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1662449398; bh=bWD0quz3Hrx2YQ7y4QUAwOReCy5myqk3JFogInQl13I=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=bqcfSUtMVJAeYNSXGOC1IHKiZG7PEq1fEds6FJoAVsymN4aOHWdSa67JIyJVbcYAl FeczzrKELDp2X+FWVmbyomY/Q48HRplCryei3UcO2XXL1wynRbG8ylukY7yqAqPRA+ AY02EAO3NEdhZrUhcdMQexpLDSgnnrqM1xp8Q9Z8= 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 3F1A33851400 for <gcc-patches@gcc.gnu.org>; Tue, 6 Sep 2022 07:29:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3F1A33851400 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-502-Y6_gqk-bMnC5xlyUYyVndw-1; Tue, 06 Sep 2022 03:29:11 -0400 X-MC-Unique: Y6_gqk-bMnC5xlyUYyVndw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 73A4980A0AE; Tue, 6 Sep 2022 07:29:11 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.194.11]) by smtp.corp.redhat.com (Postfix) with ESMTPS id D8D741415137; Tue, 6 Sep 2022 07:29:10 +0000 (UTC) Received: from abulafia.quesejoda.com (localhost [127.0.0.1]) by abulafia.quesejoda.com (8.17.1/8.17.1) with ESMTPS id 2867T6P83472849 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Tue, 6 Sep 2022 09:29:06 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.17.1/8.17.1/Submit) id 2867T6193472848; Tue, 6 Sep 2022 09:29:06 +0200 To: GCC patches <gcc-patches@gcc.gnu.org> Subject: [PATCH] Handle > INF and < INF correctly in range-op-float.cc Date: Tue, 6 Sep 2022 09:29:01 +0200 Message-Id: <20220906072901.3472801-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.85 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, 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 <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> From: Aldy Hernandez via Gcc-patches <gcc-patches@gcc.gnu.org> Reply-To: Aldy Hernandez <aldyh@redhat.com> Cc: Jakub Jelinek <jakub@redhat.com> Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" <gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org> X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1743204815921888326?= X-GMAIL-MSGID: =?utf-8?q?1743204815921888326?= |
Series |
Handle > INF and < INF correctly in range-op-float.cc
|
|
Commit Message
Aldy Hernandez
Sept. 6, 2022, 7:29 a.m. UTC
The gfortran.dg/minlocval*.f90 tests are generating conditionals past the infinities. For example: if (x <= +Inf) foo (x); else bar (x); It seems to me that the only possible value for x on the false side is either NAN or undefined (for !HONOR_NANS). Is this correct, or is there some other FP nuance I'm unaware of? gcc/ChangeLog: * range-op-float.cc (build_lt): Handle < -INF. (build_gt): Handle > +INF. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/vrp-float-inf-1.c: New test. --- gcc/range-op-float.cc | 18 ++++++++++++++++++ .../gcc.dg/tree-ssa/vrp-float-inf-1.c | 15 +++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-float-inf-1.c
Comments
On Tue, Sep 06, 2022 at 09:29:01AM +0200, Aldy Hernandez wrote: > The gfortran.dg/minlocval*.f90 tests are generating conditionals past > the infinities. For example: > > if (x <= +Inf) > foo (x); > else > bar (x); > > It seems to me that the only possible value for x on the false side is > either NAN or undefined (for !HONOR_NANS). No, none of the ==, <, <=, >, >= comparisons are ever true if one or both operands are NaN (only != will be true in those cases from the standard comparisons, when not counting UNORDERED_EXPR and the likes). So, x < -Inf or x > +Inf are always false, we just can't optimize those away without -ffast-math because they could raise an exception on sNaN. But I think not optimizing such operations away if we care about exceptions is the duty of DCE etc. Jakub
On Tue, Sep 6, 2022 at 9:35 AM Jakub Jelinek <jakub@redhat.com> wrote: > > On Tue, Sep 06, 2022 at 09:29:01AM +0200, Aldy Hernandez wrote: > > The gfortran.dg/minlocval*.f90 tests are generating conditionals past > > the infinities. For example: > > > > if (x <= +Inf) > > foo (x); > > else > > bar (x); > > > > It seems to me that the only possible value for x on the false side is > > either NAN or undefined (for !HONOR_NANS). > > No, none of the ==, <, <=, >, >= comparisons are ever true if one > or both operands are NaN (only != will be true in those cases from the > standard comparisons, when not counting UNORDERED_EXPR and the likes). > So, x < -Inf or x > +Inf are always false, we just can't optimize those > away without -ffast-math because they could raise an exception on sNaN. > But I think not optimizing such operations away if we care about exceptions > is the duty of DCE etc. No, no. I'm not talking about optimizing them away. I'm talking about representing what is going on in the IL. For example, for: if (x > 5.0) foo (x); // {5.0, +Inf] !NAN else bar (x); // [-Inf, 5.0] ?NAN So on the true side we know x is in the {5.0, +Inf] range, plus we know it can't be a NAN. On the false side we know x is either [-Inf, 5.0] or a NAN. What I'm trying to do is represent the possible ranges for the false side of: if (x <= Inf) ... Aldy
On Tue, Sep 06, 2022 at 09:40:59AM +0200, Aldy Hernandez wrote: > if (x <= Inf) This will be [-Inf, Inf] !NAN on the true side and NAN (either sign) on the false side indeed. > if (x < -Inf) will be NAN (either sign) on the true side and [-Inf, Inf] !NAN on the false side. Jakub
On Tue, Sep 6, 2022 at 9:44 AM Jakub Jelinek <jakub@redhat.com> wrote: > > On Tue, Sep 06, 2022 at 09:40:59AM +0200, Aldy Hernandez wrote: > > if (x <= Inf) > > This will be [-Inf, Inf] !NAN on the true side and > NAN (either sign) on the false side indeed. > > > if (x < -Inf) > > will be NAN (either sign) on the true side and > [-Inf, Inf] !NAN on the false side. Sweet, that's exactly what I thought, thus the patch. Furthermore, for !HONOR_NANS I would expect the NAN sides above to be UNDEFINED/unreachable. That is, the false side of x <= Inf when !HONOR_NANS is unreachable. Agreed? Aldy
On Tue, Sep 06, 2022 at 09:49:55AM +0200, Aldy Hernandez wrote: > On Tue, Sep 6, 2022 at 9:44 AM Jakub Jelinek <jakub@redhat.com> wrote: > > > > On Tue, Sep 06, 2022 at 09:40:59AM +0200, Aldy Hernandez wrote: > > > if (x <= Inf) > > > > This will be [-Inf, Inf] !NAN on the true side and > > NAN (either sign) on the false side indeed. > > > > > if (x < -Inf) > > > > will be NAN (either sign) on the true side and > > [-Inf, Inf] !NAN on the false side. > > Sweet, that's exactly what I thought, thus the patch. > > Furthermore, for !HONOR_NANS I would expect the NAN sides above to be > UNDEFINED/unreachable. That is, the false side of x <= Inf when > !HONOR_NANS is unreachable. In practice, there is no real format that has NaNs and doesn't have Infs or vice versa and similarly we have just one switch to cover both Infinities and NaNs, so either both are supported, or neither of them, or both are supported but neither of them should appear in a valid program (-ffinite-math-only on most floating point formats). So the answer in that case is a little bit fuzzy because one shouldn't compare against infinity in that case (or for !MODE_HAS_INFINITIES even can't). But sure, if NaNs aren't possible or can't appear and you compare x <= Largest_possible_float, then it is always true and so UNDEFINED on the false edge. Jakub
On Tue, Sep 6, 2022 at 9:59 AM Jakub Jelinek <jakub@redhat.com> wrote: > > On Tue, Sep 06, 2022 at 09:49:55AM +0200, Aldy Hernandez wrote: > > On Tue, Sep 6, 2022 at 9:44 AM Jakub Jelinek <jakub@redhat.com> wrote: > > > > > > On Tue, Sep 06, 2022 at 09:40:59AM +0200, Aldy Hernandez wrote: > > > > if (x <= Inf) > > > > > > This will be [-Inf, Inf] !NAN on the true side and > > > NAN (either sign) on the false side indeed. > > > > > > > if (x < -Inf) > > > > > > will be NAN (either sign) on the true side and > > > [-Inf, Inf] !NAN on the false side. > > > > Sweet, that's exactly what I thought, thus the patch. > > > > Furthermore, for !HONOR_NANS I would expect the NAN sides above to be > > UNDEFINED/unreachable. That is, the false side of x <= Inf when > > !HONOR_NANS is unreachable. > > In practice, there is no real format that has NaNs and doesn't have Infs > or vice versa and similarly we have just one switch to cover both Infinities > and NaNs, so either both are supported, or neither of them, or both > are supported but neither of them should appear in a valid program > (-ffinite-math-only on most floating point formats). > So the answer in that case is a little bit fuzzy because one shouldn't > compare against infinity in that case (or for !MODE_HAS_INFINITIES even > can't). But sure, if NaNs aren't possible or can't appear and you compare > x <= Largest_possible_float, then it is always true and so UNDEFINED on the > false edge. OK, let's leave it as undefined to be consistent. Come to think of it, perhaps we could represent the endpoints (varying, [x, +INF], etc) as the min/max representable values for the type (for !HONOR_NANS). I don't think it would make a big difference, but we might get better results for some corner cases. Question...for !HONOR_NANS or !HONOR_INFINITIES or whatever, say the range for the domain is [-MIN, +MAX] for the min and max representable numbers. What happens for MAX+1? Is that undefined? I wonder what real.cc does for that. Attached is the final version of the patch I'm pushing. Tested (+mpfr tests) on x86-64 Linux. Aldy
On Tue, Sep 06, 2022 at 01:47:43PM +0200, Aldy Hernandez wrote: > Question...for !HONOR_NANS or !HONOR_INFINITIES or whatever, say the > range for the domain is [-MIN, +MAX] for the min and max representable > numbers. What happens for MAX+1? Is that undefined? I wonder what > real.cc does for that. I'm afraid I have no idea. The formats without Inf/NaN are: spu_single_format vax_{f,d,g}_format arm_half_format Never had the "pleasure" to work with any of these. Looking at encode_vax_*, it seems both GCC internal inf and nan are most likely are encoded as maximum or minimum representable numbers (depending on sign), and encode_ieee_half for !fmt->has_inf does too (for !fmt->has_nans it seems to "encode" the nan mantissa bits into highest possible exponent). encode_ieee_single (for spu) uses maximum or minimum representable numbers for any infinities or nans. What they actually do at runtime is something I can't really check, but one would hope it is saturating... Jakub
On Tue, Sep 6, 2022 at 2:06 PM Jakub Jelinek <jakub@redhat.com> wrote: > > On Tue, Sep 06, 2022 at 01:47:43PM +0200, Aldy Hernandez wrote: > > Question...for !HONOR_NANS or !HONOR_INFINITIES or whatever, say the > > range for the domain is [-MIN, +MAX] for the min and max representable > > numbers. What happens for MAX+1? Is that undefined? I wonder what > > real.cc does for that. > > I'm afraid I have no idea. > > The formats without Inf/NaN are: > spu_single_format > vax_{f,d,g}_format > arm_half_format > > Never had the "pleasure" to work with any of these. > Looking at encode_vax_*, it seems both GCC internal inf and nan are > most likely are encoded as maximum or minimum representable numbers > (depending on sign), and encode_ieee_half for !fmt->has_inf does too > (for !fmt->has_nans it seems to "encode" the nan mantissa bits into > highest possible exponent). encode_ieee_single (for spu) uses > maximum or minimum representable numbers for any infinities or nans. > What they actually do at runtime is something I can't really check, > but one would hope it is saturating... I'd simply do what we do for -ffinite-math-only - just pretend you don't cross the maximum/minmum value and effectively saturate the range. Richard. > Jakub >
On Tue, Sep 6, 2022 at 2:17 PM Richard Biener <richard.guenther@gmail.com> wrote: > > On Tue, Sep 6, 2022 at 2:06 PM Jakub Jelinek <jakub@redhat.com> wrote: > > > > On Tue, Sep 06, 2022 at 01:47:43PM +0200, Aldy Hernandez wrote: > > > Question...for !HONOR_NANS or !HONOR_INFINITIES or whatever, say the > > > range for the domain is [-MIN, +MAX] for the min and max representable > > > numbers. What happens for MAX+1? Is that undefined? I wonder what > > > real.cc does for that. > > > > I'm afraid I have no idea. > > > > The formats without Inf/NaN are: > > spu_single_format > > vax_{f,d,g}_format > > arm_half_format > > > > Never had the "pleasure" to work with any of these. > > Looking at encode_vax_*, it seems both GCC internal inf and nan are > > most likely are encoded as maximum or minimum representable numbers > > (depending on sign), and encode_ieee_half for !fmt->has_inf does too > > (for !fmt->has_nans it seems to "encode" the nan mantissa bits into > > highest possible exponent). encode_ieee_single (for spu) uses > > maximum or minimum representable numbers for any infinities or nans. > > What they actually do at runtime is something I can't really check, > > but one would hope it is saturating... > > I'd simply do what we do for -ffinite-math-only - just pretend you don't > cross the maximum/minmum value and effectively saturate the range. Yeah, that sounds reasonable. I take it I can assume that MAX+1 is undefined for -ffinite-math-only? So I'm free to saturate, etc? Ok, crazy hypothetical talk... if (x > y) For -ffinite-math-only, on the true side, can I assume: x: MIN + 1 ULP y: MAX - 1 ULP range-op for integers did all sorts of stuff like that, and we ended up optimizing some interesting cases...as well as driving the middle end warnings crazy :-P. Aldy
> On Sep 6, 2022, at 8:06 AM, Jakub Jelinek via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > On Tue, Sep 06, 2022 at 01:47:43PM +0200, Aldy Hernandez wrote: >> Question...for !HONOR_NANS or !HONOR_INFINITIES or whatever, say the >> range for the domain is [-MIN, +MAX] for the min and max representable >> numbers. What happens for MAX+1? Is that undefined? I wonder what >> real.cc does for that. > > I'm afraid I have no idea. > > The formats without Inf/NaN are: > spu_single_format > vax_{f,d,g}_format > arm_half_format Actually, DEC (VAX and PDP-11) float does have NaN; signaling NaN to be precise. paul
diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index 050f07a9867..4515bbf0b7e 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -235,6 +235,15 @@ build_le (frange &r, tree type, const REAL_VALUE_TYPE &val) static void build_lt (frange &r, tree type, const REAL_VALUE_TYPE &val) { + if (real_isinf (&val, 1)) + { + if (HONOR_NANS (type)) + frange_set_nan (r, type); + else + r.set_undefined (); + return; + } + // Hijack LE because we only support closed intervals. build_le (r, type, val); } @@ -252,6 +261,15 @@ build_ge (frange &r, tree type, const REAL_VALUE_TYPE &val) static void build_gt (frange &r, tree type, const REAL_VALUE_TYPE &val) { + if (real_isinf (&val, 0)) + { + if (HONOR_NANS (type)) + frange_set_nan (r, type); + else + r.set_undefined (); + return; + } + // Hijack GE because we only support closed intervals. build_ge (r, type, val); } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-inf-1.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-inf-1.c new file mode 100644 index 00000000000..1d21cce41e6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-inf-1.c @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-evrp-details" } + +void foo (); +void bar (double); + +void funky(double f, double g) +{ + if (f <= __builtin_inf ()) + foo (); + else + bar (f); +} + +// { dg-final { scan-tree-dump-not " Inf, Inf" "evrp" } }