public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Aldy Hernandez <aldyh@redhat.com>
To: Richard Biener <richard.guenther@gmail.com>
Cc: GCC patches <gcc-patches@gcc.gnu.org>,
	Andrew MacLeod <amacleod@redhat.com>,
	richard.sandiford@arm.com
Subject: Re: [PATCH] [PR68097] Try to avoid recursing for floats in tree_*_nonnegative_warnv_p.
Date: Tue, 15 Nov 2022 11:46:10 +0100	[thread overview]
Message-ID: <503f89de-8e88-2e20-5b14-5493191b19f5@redhat.com> (raw)
In-Reply-To: <CAFiYyc3=0GWNHQE4YO7FS49Msf0RAZMA9pLdKm1SU+T9CeKFiw@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 5892 bytes --]



On 11/15/22 08:15, Richard Biener wrote:
> On Mon, Nov 14, 2022 at 8:05 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>>
>>
>>
>> On 11/14/22 10:12, Richard Biener wrote:
>>> On Sat, Nov 12, 2022 at 7:30 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>>>>
>>>> It irks me that a PR named "we should track ranges for floating-point
>>>> hasn't been closed in this release.  This is an attempt to do just
>>>> that.
>>>>
>>>> As mentioned in the PR, even though we track ranges for floats, it has
>>>> been suggested that avoiding recursing through SSA defs in
>>>> gimple_assign_nonnegative_warnv_p is also a goal.  We can do this with
>>>> various ranger components without the need for a heavy handed approach
>>>> (i.e. a full ranger).
>>>>
>>>> I have implemented two versions of known_float_sign_p() that answer
>>>> the question whether we definitely know the sign for an operation or a
>>>> tree expression.
>>>>
>>>> Both versions use get_global_range_query, which is a wrapper to query
>>>> global ranges.  This means, that no caching or propagation is done.
>>>> In the case of an SSA, we just return the global range for it (think
>>>> SSA_NAME_RANGE_INFO).  In the case of a tree code with operands, we
>>>> also use get_global_range_query to resolve the operands, and then call
>>>> into range-ops, which is our lowest level component.  There is no
>>>> ranger or gori involved.  All we're doing is resolving the operation
>>>> with the ranges passed.
>>>>
>>>> This is enough to avoid recursing in the case where we definitely know
>>>> the sign of a range.  Otherwise, we still recurse.
>>>>
>>>> Note that instead of get_global_range_query(), we could use
>>>> get_range_query() which uses a ranger (if active in a pass), or
>>>> get_global_range_query if not.  This would allow passes that have an
>>>> active ranger (with enable_ranger) to use a full ranger.  These passes
>>>> are currently, VRP, loop unswitching, DOM, loop versioning, etc.  If
>>>> no ranger is active, get_range_query defaults to global ranges, so
>>>> there's no additional penalty.
>>>>
>>>> Would this be acceptable, at least enough to close (or rename the PR ;-))?
>>>
>>> I think the checks would belong to the gimple_stmt_nonnegative_warnv_p function
>>> only (that's the SSA name entry from the fold-const.cc ones)?
>>
>> That was my first approach, but I thought I'd cover the unary and binary
>> operators as well, since they had other callers.  But I'm happy with
>> just the top-level tweak.  It's a lot less code :).
> 
> @@ -9234,6 +9235,15 @@ bool
>   gimple_stmt_nonnegative_warnv_p (gimple *stmt, bool *strict_overflow_p,
>                                   int depth)
>   {
> +  tree type = gimple_range_type (stmt);
> +  if (type && frange::supports_p (type))
> +    {
> +      frange r;
> +      bool sign;
> +      return (get_global_range_query ()->range_of_stmt (r, stmt)
> +             && r.signbit_p (sign)
> +             && sign == false);
> +    }
> 
> the above means we never fall through to the switch below if
> frange::supports_p (type) - that's eventually good enough, I
> don't think we ever call this very function directly but it gets
> invoked via recursion through operands only.  But of course

Woah, sorry.  That was not intended.  For that matter, the patch as 
posted caused:

FAIL: gcc.dg/builtins-10.c (test for excess errors)
FAIL: gcc.dg/builtins-57.c (test for excess errors)
FAIL: gcc.dg/torture/builtin-nonneg-1.c   -O1  (test for excess errors)
FAIL: gcc.dg/torture/builtin-nonneg-1.c   -O2  (test for excess errors)
FAIL: gcc.dg/torture/builtin-nonneg-1.c   -O2 -flto 
-fno-use-linker-plugin -flto-partition=none  (test for excess errors)
FAIL: gcc.dg/torture/builtin-nonneg-1.c   -O3 -g  (test for excess errors)
FAIL: gcc.dg/torture/builtin-nonneg-1.c   -Os  (test for excess errors)
FAIL: gcc.dg/torture/builtin-power-1.c   -O1  (test for excess errors)
FAIL: gcc.dg/torture/builtin-power-1.c   -O2  (test for excess errors)
FAIL: gcc.dg/torture/builtin-power-1.c   -O2 -flto 
-fno-use-linker-plugin -flto-partition=none  (test for excess errors)
FAIL: gcc.dg/torture/builtin-power-1.c   -O3 -g  (test for excess errors)
FAIL: gcc.dg/torture/builtin-power-1.c   -Os  (test for excess errors)

Note that ranger folding calls this function, though it won't run the 
risk of endless recursion because range_of_stmt uses the LHS, and only 
use global ranges to solve the LHS.

Also, frange::supports_p() does not support all floats:

   static bool supports_p (const_tree type)
   {
     // ?? Decimal floats can have multiple representations for the
     // same number.  Supporting them may be as simple as just
     // disabling them in singleton_p.  No clue.
     return SCALAR_FLOAT_TYPE_P (type) && !DECIMAL_FLOAT_TYPE_P (type);
   }

Finally, my patch is more conservative than what the *nonnegative_warn* 
friends do.  We only return true when we're sure about the sign bit and 
it's FALSE.  As I mentioned elsewhere, tree_call_nonnegative_warn_p() 
always returns true for:

     CASE_CFN_ACOS:
     CASE_CFN_ACOS_FN:
     CASE_CFN_ACOSH:
     CASE_CFN_ACOSH_FN:
     CASE_CFN_CABS:
     CASE_CFN_CABS_FN:
...
...
       /* Always true.  */
       return true;

This means that we'll return true for a NAN, but we're incorrectly 
assuming the NAN will be +NAN.  In my proposed patch, we don't make such 
assumptions.  We only return true if the range is non-negative, 
including the NAN.

> I wonder what types are not supported by frange and whether
> the manual processing we fall through to does anything meaningful
> for those?
> 
> I won't ask you to thoroughly answer this now but please put in
> a comment reflecting the above before the switch stmt.
> 
>     switch (gimple_code (stmt))
> 
> 
> Otherwise OK, in case you tree gets back to bootstrapping ;)

Updated patch that passes test.

OK?  And if so, can I close the PR?

Thanks.
Aldy

[-- Attachment #2: 0001-PR68097-Try-to-avoid-recursing-for-floats-in-gimple_.patch --]
[-- Type: text/x-patch, Size: 1776 bytes --]

From 8f589cff22e80eda7cc3837080dbc9ae8280da8c Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <aldyh@redhat.com>
Date: Sat, 12 Nov 2022 11:58:07 +0100
Subject: [PATCH] [PR68097] Try to avoid recursing for floats in
 gimple_stmt_nonnegative_warnv_p.

It irks me that a PR named "we should track ranges for floating-point
hasn't been closed in this release.  This is an attempt to do just
that.

As mentioned in the PR, even though we track ranges for floats, it has
been suggested that avoiding recursing through SSA defs in
gimple_assign_nonnegative_warnv_p is also a goal.  This patch uses a
global range query (no on-demand lookups, just global ranges and
minimal folding) to determine if the range of a statement is known to
be non-negative.

	PR tree-optimization/68097

gcc/ChangeLog:

	* gimple-fold.cc (gimple_stmt_nonnegative_warnv_p): Call
	range_of_stmt for floats.
---
 gcc/gimple-fold.cc | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 0a212e6d0d4..c4ebe9a3b52 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -68,6 +68,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-strlen.h"
 #include "varasm.h"
 #include "internal-fn.h"
+#include "gimple-range.h"
 
 enum strlen_range_kind {
   /* Compute the exact constant string length.  */
@@ -9234,6 +9235,15 @@ bool
 gimple_stmt_nonnegative_warnv_p (gimple *stmt, bool *strict_overflow_p,
 				 int depth)
 {
+  tree type = gimple_range_type (stmt);
+  if (type && frange::supports_p (type))
+    {
+      frange r;
+      bool sign;
+      if (get_global_range_query ()->range_of_stmt (r, stmt)
+	  && r.signbit_p (sign))
+	return !sign;
+    }
   switch (gimple_code (stmt))
     {
     case GIMPLE_ASSIGN:
-- 
2.38.1


  reply	other threads:[~2022-11-15 10:46 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-12 18:30 Aldy Hernandez
2022-11-14  9:12 ` Richard Biener
2022-11-14 19:05   ` Aldy Hernandez
2022-11-15  7:15     ` Richard Biener
2022-11-15 10:46       ` Aldy Hernandez [this message]
2022-11-16 16:04         ` Richard Biener
2022-11-16 17:38           ` Aldy Hernandez
2022-11-17  8:01             ` Richard Biener
2022-11-15 13:52   ` Aldy Hernandez
2022-11-16 15:59     ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=503f89de-8e88-2e20-5b14-5493191b19f5@redhat.com \
    --to=aldyh@redhat.com \
    --cc=amacleod@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=richard.guenther@gmail.com \
    --cc=richard.sandiford@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).