there is an entry point in a range_query object to update an ssa-name to
a specific range outside of ranger. :
virtual void update_range_info (tree name, const vrange &r);
This Patch provides another entry point which indicates that a global
range may be out of date, and should be recalculated next time it is
encountered. It will mark the SSA name as "stale", and if it is used
again, it will trigger a recalculation by ranger and it will check if
the new value is different or not.
This is then hooked into gimple_set_modified() so that if a statement is
rewritten by any other component, ranger will now be aware. If the LHS
of the statement is subsequently used, ranger will re-evaluate the new
statement which was created.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
From 9237613db491e8f47a22d6f07e00c3e534d52a1f Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Wed, 3 Dec 2025 13:24:11 -0500
Subject: [PATCH 3/6] update_range_info can mark a statement for recalculation.
Add an alternative update_range_info method which marks the SSA_NAME as
"to be recalcualted" the next time it is used.
* gimple-range-cache.cc (ranger_cache::ranger_cache): Allocate bitmap.
ranger_cache::~ranger_cache): Free bitmap.
(ranger_cache::mark_stale): New.
(ranger_cache::get_global_range): Check if NAME is marked stale.
* gimple-range-cache.h (ranger_cache::mark_stale): New.
* gimple-range.cc (gimple_ranger::update_range_info): New variant.
* gimple-range.h (update_range_info): New prototype.
* gimple.h (gimple_set_modified): Call update_range_info.
* value-query.cc (range_query::update_range_info): New variant.
* value-query.h (range_query::update_range_info): New prototype.
---
gcc/gimple-range-cache.cc | 20 ++++++++++++++++++++
gcc/gimple-range-cache.h | 2 ++
gcc/gimple-range.cc | 13 ++++++++++++-
gcc/gimple-range.h | 1 +
gcc/gimple.h | 14 +++++++++++++-
gcc/value-query.cc | 6 ++++++
gcc/value-query.h | 3 +++
7 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 380590b6dca..02af482838d 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -1019,10 +1019,12 @@ ranger_cache::ranger_cache (int not_executable_flag, bool use_imm_uses)
gori_ssa ()->exports (bb);
}
m_update = new update_list ();
+ m_stale = BITMAP_ALLOC (NULL);
}
ranger_cache::~ranger_cache ()
{
+ BITMAP_FREE (m_stale);
delete m_update;
destroy_infer_oracle ();
destroy_relation_oracle ();
@@ -1064,6 +1066,17 @@ ranger_cache::get_global_range (vrange &r, tree name) const
return false;
}
+// Mark NAME as stale. The next query of NAME forces a recalculation.
+
+void
+ranger_cache::mark_stale (tree name)
+{
+ // Only mark it as stale if it has been processed. If it has no range
+ // it will be calculated at the next request anyway.
+ if (m_globals.has_range (name))
+ bitmap_set_bit (m_stale, SSA_NAME_VERSION (name));
+}
+
// Get the global range for NAME, and return in R. Return false if the
// global range is not set, and R will contain the legacy global value.
// CURRENT_P is set to true if the value was in cache and not stale.
@@ -1102,6 +1115,13 @@ ranger_cache::get_global_range (vrange &r, tree name, bool ¤t_p)
m_globals.set_range (name, r);
}
+ // If NAME is out of date, clear the bit and mark as not current.
+ if (bitmap_bit_p (m_stale, SSA_NAME_VERSION (name)))
+ {
+ bitmap_clear_bit (m_stale, SSA_NAME_VERSION (name));
+ current_p = false;
+ }
+
// If the existing value was not current, mark it as always current.
if (!current_p)
m_temporal->set_always_current (name, true);
diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h
index 9e01005016e..e01f35a548d 100644
--- a/gcc/gimple-range-cache.h
+++ b/gcc/gimple-range-cache.h
@@ -111,6 +111,7 @@ public:
bool get_global_range (vrange &r, tree name) const;
bool get_global_range (vrange &r, tree name, bool ¤t_p);
void set_global_range (tree name, const vrange &r, bool changed = true);
+ void mark_stale (tree name);
void update_consumers (tree name);
range_query &const_query () { return m_globals; }
@@ -143,6 +144,7 @@ private:
vec<basic_block> m_workback;
class update_list *m_update;
+ bitmap m_stale;
};
#endif // GCC_SSA_RANGE_CACHE_H
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 4c768ed3a07..a65d626b43c 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -556,6 +556,14 @@ gimple_ranger::register_transitive_inferred_ranges (basic_block bb)
}
}
+// Indicate NAME should have its range recalculated next time it is used.
+
+void
+gimple_ranger::update_range_info (tree name)
+{
+ m_cache.mark_stale (name);
+}
+
// This is called to update ranger's concept of a global value for NAME
// with range R by an outside entity.
@@ -565,7 +573,10 @@ gimple_ranger::update_range_info (tree name, const vrange &r)
value_range current (TREE_TYPE (name));
m_cache.get_global_range (current, name);
if (current.intersect (r))
- m_cache.set_global_range (name, current, true);
+ {
+ m_cache.set_global_range (name, current, true);
+ m_cache.mark_stale (name);
+ }
}
// This routine will export whatever global ranges are known to GCC
diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h
index 77e1bb9efd8..b7df438e369 100644
--- a/gcc/gimple-range.h
+++ b/gcc/gimple-range.h
@@ -54,6 +54,7 @@ public:
virtual bool range_on_edge (vrange &r, edge e, tree name) override;
virtual bool range_on_entry (vrange &r, basic_block bb, tree name) override;
virtual bool range_on_exit (vrange &r, basic_block bb, tree name) override;
+ virtual void update_range_info (tree) override;
virtual void update_range_info (tree, const vrange &) override;
void export_global_ranges ();
virtual void dump (FILE *f) override;
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 2484a33f476..83722100849 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -24,6 +24,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-alias.h"
#include "gimple-expr.h"
+#include "bitmap.h"
+#include "value-range.h"
+#include "value-query.h"
typedef gimple *gimple_seq_node;
@@ -2309,7 +2312,16 @@ inline void
gimple_set_modified (gimple *s, bool modifiedp)
{
if (gimple_has_ops (s))
- s->modified = (unsigned) modifiedp;
+ {
+ s->modified = (unsigned) modifiedp;
+ // Mark the LHS as out of date with the current range query.
+ if (modifiedp)
+ {
+ tree def = gimple_get_lhs (s);
+ if (def && TREE_CODE (def) == SSA_NAME)
+ get_range_query (cfun)->update_range_info (def);
+ }
+ }
}
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index 5fbe8f932a6..3f50e31a9f4 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -66,6 +66,12 @@ range_query::range_of_stmt (vrange &r, gimple *stmt, tree name)
return false;
}
+// Default for updating range info is to do nothing.
+void
+range_query::update_range_info (tree)
+{
+}
+
// Default for updating range info is to do nothing.
void
range_query::update_range_info (tree, const vrange &)
diff --git a/gcc/value-query.h b/gcc/value-query.h
index 3cbe0314cef..7756e431155 100644
--- a/gcc/value-query.h
+++ b/gcc/value-query.h
@@ -75,6 +75,9 @@ public:
virtual bool range_on_entry (vrange &r, basic_block bb, tree expr);
virtual bool range_on_exit (vrange &r, basic_block bb, tree expr);
+ // Indicate that NAME should be considered for a range update.
+ virtual void update_range_info (tree name);
+ // Provide a specific range update to NAME.
virtual void update_range_info (tree name, const vrange &r);
inline class relation_oracle &relation () const { return *m_relation; }
--
2.45.0