Attached is a pre-approved patch which adds a range_query to the inferred range mechanism.

The only change you will need to make is to replace "get_range_query (cfun)->"  with "q->" which is passed in.

This regstraps on x86 without your patch, and I got as far as a bootstrap with your patches..

Andfrew

On 11/15/24 04:36, Jakub Jelinek wrote:
On Thu, Nov 14, 2024 at 06:25:49PM +0100, Jakub Jelinek wrote:
On Thu, Nov 14, 2024 at 10:05:05AM -0500, Andrew MacLeod wrote:
The inferred range mechanism is also initialized using cfun, so again
introducing a use of cfun shouldnt be an issue.

Something like this ought to work I think?
2024-11-14  Jakub Jelinek  <ja...@redhat.com>
            Andrew MacLeod  <amacl...@redhat.com>

        PR c/117023
        * gimple-range-infer.cc (gimple_infer_range::gimple_infer_range):
        Handle also nonnull_if_nonzero attributes.

        * gcc.dg/tree-ssa/pr78154-2.c: New test.
Unfortunately that broke bootstrap.
https://gcc.gnu.org/pipermail/gcc-patches/2024-November/668554.html
https://gcc.gnu.org/pipermail/gcc-patches/2024-November/668699.html
https://gcc.gnu.org/pipermail/gcc-patches/2024-November/668700.html
https://gcc.gnu.org/pipermail/gcc-patches/2024-November/668711.html
bootstrap/regtest fine, but if
https://gcc.gnu.org/pipermail/gcc-patches/2024-November/668700.html
in there is replaced with
https://gcc.gnu.org/pipermail/gcc-patches/2024-November/668818.html
I get ICE on e.g. opts-common.cc.

Reduced testcase:

void foo (int *, __SIZE_TYPE__);
char *a, b[64], c;

void
bar (void)
{
   for (int i = 0; i < 42; ++i)
     {
       char *d = &a[i];
       int e;
       if (c)
        foo (&e, 1);
       __SIZE_TYPE__ f = __builtin_strlen (d);
       if (f)
        __builtin_memcpy (b, d, f);
     }
}

/home/jakub/src/gcc/obj72x/prev-gcc/cc1 -quiet -O2 fbc-ice.c
during GIMPLE pass: wrestrict
fbc-ice.c: In function ‘bar’:
fbc-ice.c:5:1: internal compiler error: in fill_block_cache, at 
gimple-range-cache.cc:1565
     5 | bar (void)
       | ^~~
0x44ebf97 internal_error(char const*, ...)
        ../../gcc/diagnostic-global-context.cc:518
0x44bc0ef fancy_abort(char const*, int, char const*)
        ../../gcc/diagnostic.cc:1696
0x41d186f ranger_cache::fill_block_cache(tree_node*, basic_block_def*, 
basic_block_def*)
        ../../gcc/gimple-range-cache.cc:1565
0x41d07be ranger_cache::block_range(vrange&, basic_block_def*, tree_node*, bool)
        ../../gcc/gimple-range-cache.cc:1304
0x41c95f4 gimple_ranger::range_on_entry(vrange&, basic_block_def*, tree_node*)
        ../../gcc/gimple-range.cc:175
0x41c93f3 gimple_ranger::range_of_expr(vrange&, tree_node*, gimple*)
        ../../gcc/gimple-range.cc:147
0x41e2c8c gimple_infer_range::gimple_infer_range(gimple*, bool)
        ../../gcc/gimple-range-infer.cc:205
0x41e3f52 infer_range_manager::register_all_uses(tree_node*)
        ../../gcc/gimple-range-infer.cc:476
0x41e35ec infer_range_manager::has_range_p(basic_block_def*, tree_node*)
        ../../gcc/gimple-range-infer.cc:356
0x41d1a64 ranger_cache::fill_block_cache(tree_node*, basic_block_def*, 
basic_block_def*)
        ../../gcc/gimple-range-cache.cc:1604
0x41d07be ranger_cache::block_range(vrange&, basic_block_def*, tree_node*, bool)
        ../../gcc/gimple-range-cache.cc:1304
0x41c95f4 gimple_ranger::range_on_entry(vrange&, basic_block_def*, tree_node*)
        ../../gcc/gimple-range.cc:175
0x41c93f3 gimple_ranger::range_of_expr(vrange&, tree_node*, gimple*)
        ../../gcc/gimple-range.cc:147
0x41d5d5b fur_stmt::get_operand(vrange&, tree_node*)
        ../../gcc/gimple-range-fold.cc:143
0x41d7cb5 fold_using_range::range_of_range_op(vrange&, gimple_range_op_handler&, 
fur_source&)
        ../../gcc/gimple-range-fold.cc:718
0x41d770e fold_using_range::fold_stmt(vrange&, gimple*, fur_source&, tree_node*)
        ../../gcc/gimple-range-fold.cc:649
0x41c9d03 gimple_ranger::fold_range_internal(vrange&, gimple*, tree_node*)
        ../../gcc/gimple-range.cc:278
0x41ca03c gimple_ranger::range_of_stmt(vrange&, gimple*, tree_node*)
        ../../gcc/gimple-range.cc:339
0x41c95b5 gimple_ranger::range_on_entry(vrange&, basic_block_def*, tree_node*)
        ../../gcc/gimple-range.cc:172
0x41c93f3 gimple_ranger::range_of_expr(vrange&, tree_node*, gimple*)
        ../../gcc/gimple-range.cc:147
Please submit a full bug report, with preprocessed source (by using 
-freport-bug).
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.

        Jakub
From 3c6fdbb17f012e9a022fd74356aa35d6fb2309ed Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Sat, 16 Nov 2024 08:29:30 -0500
Subject: [PATCH] Add a range query to inferred ranges.

Provide a range_query for any inferred range processing which wants to
examine the range of an argument to make decisions.  Add some comments.

	* gimple-range-cache.cc (ranger_cache::ranger_cache): Create the
	infer oracle using THIS as the range_query.
	* gimple_range_infer.cc (gimple_infer_range::gimple_infer_range):
	Add a range_query to the constructor and use it.
	(infer_range_manager::infer_range_manager): Add a range_query.
	* gimple-range-infer.h (gimple_infer_range): Adjust prototype.
	(infer_range_manager): Add a range_query.
	* value-query.cc (range_query::create_infer_oracle): Add a range_query.
---
 gcc/gimple-range-cache.cc |  5 +++-
 gcc/gimple-range-infer.cc | 24 +++++++++++++------
 gcc/gimple-range-infer.h  | 50 ++++++++++++++++++++++++++++++++++-----
 gcc/value-query.cc        | 10 ++++++--
 gcc/value-query.h         |  2 +-
 5 files changed, 74 insertions(+), 17 deletions(-)

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 1788a935429..1814431f1e9 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -1003,7 +1003,10 @@ ranger_cache::ranger_cache (int not_executable_flag, bool use_imm_uses)
 
   // If DOM info is available, spawn an oracle as well.
   create_relation_oracle ();
-  create_infer_oracle (use_imm_uses);
+  // Create an infer oracle using this cache as the range query.  The cache
+  // version acts as a read-only query, and will spawn no additional lookups.
+  // It just ues what is already known.
+  create_infer_oracle (this, use_imm_uses);
   create_gori (not_executable_flag, param_vrp_switch_limit);
 
   unsigned x, lim = last_basic_block_for_fn (cfun);
diff --git a/gcc/gimple-range-infer.cc b/gcc/gimple-range-infer.cc
index dd748248eaa..e9ee4d13530 100644
--- a/gcc/gimple-range-infer.cc
+++ b/gcc/gimple-range-infer.cc
@@ -152,19 +152,24 @@ gimple_infer_range::add_nonzero (tree name)
 }
 
 // Process S for range inference and fill in the summary list.
-// This is the routine where new inferred ranges should be added.
+// This is the routine where any new inferred ranges should be added.
 // If USE_RANGEOPS is true, invoke range-ops on stmts with a single
-// ssa-name aa constant to reflect an inferred range. ie
+// ssa-name a constant to reflect an inferred range. ie
 // x_2 = y_3 + 1 will provide an inferred range for y_3 of [-INF, +INF - 1].
 // This defaults to FALSE as it can be expensive.,
 
-gimple_infer_range::gimple_infer_range (gimple *s, bool use_rangeops)
+gimple_infer_range::gimple_infer_range (gimple *s, range_query *q,
+					bool use_rangeops)
 {
   num_args = 0;
 
   if (is_a<gphi *> (s))
     return;
 
+  // Default to the global query if none provided.
+  if (!q)
+    q = get_global_range_query ();
+
   if (is_a<gcall *> (s) && flag_delete_null_pointer_checks)
     {
       tree fntype = gimple_call_fntype (s);
@@ -220,14 +225,14 @@ gimple_infer_range::gimple_infer_range (gimple *s, bool use_rangeops)
   if (ssa1)
     {
       value_range op1 (TREE_TYPE (ssa1));
-      if (op1_range (op1, s, get_global_range_query ()) && !op1.varying_p ())
+      if (op1_range (op1, s, q) && !op1.varying_p ())
 	add_range (ssa1, op1);
     }
   else
     {
       gcc_checking_assert (ssa2);
       value_range op2 (TREE_TYPE (ssa2));
-      if (op2_range (op2, s, get_global_range_query ()) && !op2.varying_p ())
+      if (op2_range (op2, s, q) && !op2.varying_p ())
 	add_range (ssa2, op2);
     }
 }
@@ -274,9 +279,14 @@ infer_range_manager::exit_range_head::find_ptr (tree ssa)
 // Construct a range infer manager.  DO_SEARCH indicates whether an immediate
 // use scan should be made the first time a name is processed.  This is for
 // on-demand clients who may not visit every statement and may miss uses.
+// Q is the range_query to use for any lookups.  Default is NULL which maps
+// to the global_range_query.
 
-infer_range_manager::infer_range_manager (bool do_search)
+infer_range_manager::infer_range_manager (bool do_search, range_query *q)
 {
+  // Set the range query to use.
+  m_query = q ? q : get_global_range_query ();
+
   bitmap_obstack_initialize (&m_bitmaps);
   m_on_exit.create (0);
   m_on_exit.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1);
@@ -450,7 +460,7 @@ infer_range_manager::register_all_uses (tree name)
   FOR_EACH_IMM_USE_FAST (use_p, iter, name)
     {
       gimple *s = USE_STMT (use_p);
-      gimple_infer_range infer (s);
+      gimple_infer_range infer (s, m_query);
       for (unsigned x = 0; x < infer.num (); x++)
 	{
 	  if (name == infer.name (x))
diff --git a/gcc/gimple-range-infer.h b/gcc/gimple-range-infer.h
index b11d28352ad..049ce78cab2 100644
--- a/gcc/gimple-range-infer.h
+++ b/gcc/gimple-range-infer.h
@@ -27,11 +27,39 @@ along with GCC; see the file COPYING3.  If not see
 // This class manages an on-demand summary of inferred ranges for a statement.
 // It can be instantiated as required and provides a list of inferred ranges.
 // New inferred ranges should be added in the constructor of this class.
+//
+// There are 2 main instantiations.
+// gimple_range_infer (gimple *s, range_query *q, bool use_range_ops)
+//   S is the statement being queried.
+//   Q is a range-query object which is used to resolve any ranges that
+//      might be required.  This defaults to NULL which maps to the
+//      global_range_query, which is what most passes will want.
+//      Ranger internally will pass the cache's range-query which is a
+//      read-only query and prevents any additional lookup.
+//   USE_RANGEOPS is a boolean flag which defaults to false.  if TRUE,
+//      range-ops is invoked to see if any additional side effects are seen
+//      based on the stmt.  ie .x = y * 2 will reigster a side effect for Y
+//      which is [-INF/2 , +INF/2].  It is not on by default because it
+//      is a relatively expensive operation to do on every statement, and
+//      ranger will already incorporate that range for Y via GORI most of the
+//      time that it matters.  Individual passes may have use for it however.
+//      PR 113879 is an example where this can be of use.
+//
+// gimple_range_infer (tree name, vrange &r)
+// This instantiation simply create an inferred range record directly.
+//   NAME is the SSA_NAME to create the record for
+//   R is the range for NAME.
+//
+// Once a gimple_infer_range record has been created, the API is simple:
+//   num ()    - The number of inferred ranges in this record.
+//   name (i)  - The i'th SSA_NAME in this record.
+//   range (i) - The range of the i'th SSA_NAME.
 
 class gimple_infer_range
 {
 public:
-  gimple_infer_range (gimple *s, bool use_rangeops = false);
+  gimple_infer_range (gimple *s, range_query *q = NULL,
+		      bool use_rangeops = false);
   gimple_infer_range (tree name, vrange &r);
   inline unsigned num () const { return num_args; }
   inline tree name (unsigned index) const
@@ -65,14 +93,24 @@ public:
 
 // This class manages a list of inferred ranges for each basic block.
 // As inferences are made, they can be registered to a block and later
-// queried.  When constructed with a TRUE flag, immediate uses chains are
-// followed the first time a name is referenced and block populated if
-// there are any inferred ranges.
+// queried via a DOM search.
+// When DO_SEARCH is TRUE,  immediate uses chains are followed the first time
+// a name is referenced and block populated if there are any inferred ranges.
+// range_query Q is the range_query to use for any range lookups. It defaults
+// to NULL which maps to the global_range_query.  This is what most passes
+// will want to use. Ranger invokes it with the cache's internal query which
+// can provide better ranges during a DOM walk.
+//
+// add_ranges is used to add inferred range IR assocaited with stmt S.
+// has_range_p is used to check if NAME has an inferred range in block BB.
+// maybe_adjust_range will adjust the range R to incorporate any inferred
+//   range NAME may have in block BB.  If there are on inferred ranges in
+//   block BB, then R will be unchanged, otherwise the ranges are intersected.
 
 class infer_range_manager : public infer_range_oracle
 {
 public:
-  infer_range_manager (bool do_search);
+  infer_range_manager (bool do_search, range_query *q = NULL);
   virtual ~infer_range_manager ();
   virtual void add_ranges (gimple *s, gimple_infer_range &ir);
   virtual bool has_range_p (basic_block bb, tree name = NULL_TREE);
@@ -96,6 +134,6 @@ private:
   bitmap_obstack m_bitmaps;
   struct obstack m_list_obstack;
   class vrange_allocator *m_range_allocator;
+  range_query *m_query;
 };
-
 #endif // GCC_GIMPLE_RANGE_SIDE_H
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index d68ac5d4896..7edc4c76e45 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -207,11 +207,17 @@ range_query::destroy_gori ()
   m_gori= &default_gori;
 }
 
+// Create an infer oracle using Q as the default range query if needed.
+// if DO_SEARCH is true, use immediate uses to scan alluses of a NAME the first
+// time it is queried.  This is primarily for passes which operate in the
+// on-demand model where earlier uses may not have been seen.
+// VRP and DOM walk passes set this to FALSE as they will walk all statements
+// in order.
 void
-range_query::create_infer_oracle (bool do_search)
+range_query::create_infer_oracle (range_query *q, bool do_search)
 {
   gcc_checking_assert (m_infer == &default_infer_oracle);
-  m_infer = new infer_range_manager (do_search);
+  m_infer = new infer_range_manager (do_search, q);
   gcc_checking_assert (m_infer);
 }
 
diff --git a/gcc/value-query.h b/gcc/value-query.h
index 78840fd7a78..07e63b8ac94 100644
--- a/gcc/value-query.h
+++ b/gcc/value-query.h
@@ -80,7 +80,7 @@ public:
   void destroy_relation_oracle ();
 
   inline class infer_range_oracle &infer_oracle () const { return *m_infer; }
-  void create_infer_oracle (bool do_search = TRUE);
+  void create_infer_oracle (range_query *q = NULL, bool do_search = true);
   void destroy_infer_oracle ();
 
   inline class gimple_outgoing_range &gori () const { return *m_gori; }
-- 
2.45.0

Reply via email to