https://gcc.gnu.org/g:39fe620963b29e7bdc8dcfa2037490df26b4edf2
commit r15-81-g39fe620963b29e7bdc8dcfa2037490df26b4edf2 Author: Andrew MacLeod <amacl...@redhat.com> Date: Wed Mar 13 14:18:48 2024 -0400 Add range_on_entry/exit to value_query API. Add range_on_entry and range_on_exit to the value_query API. These will also work with generic trees like range_of_expr does. * gimple-range.cc (gimple_ranger::range_on_entry): Adjust for new API and support non-SSA expressions. (gimple_ranger::range_on_exit): Ditto. * gimple-range.h (range_on_entry, range_on_exit): Adjust API. * value-query.cc (range_query::range_on_entry): New. (range_query::range_on_exit): New. (range_query::value_on_entry): New. (range_query::value_on_exit): New. (range_query::invoke_range_of_expr): New. (range_query::get_tree_range): Allow stmt, on_entry or on_exit range queries. SSA_NAMES should invoke range_of_expr if possible. * value-query.h (class range_query): Adjust prototypes. Diff: --- gcc/gimple-range.cc | 14 +++++--- gcc/gimple-range.h | 4 +-- gcc/value-query.cc | 100 ++++++++++++++++++++++++++++++++++++++++++++++++---- gcc/value-query.h | 9 ++++- 4 files changed, 112 insertions(+), 15 deletions(-) diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 3966cfbd14c..e75e2e17dc3 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -152,11 +152,13 @@ gimple_ranger::range_of_expr (vrange &r, tree expr, gimple *stmt) // Return the range of NAME on entry to block BB in R. -void +bool gimple_ranger::range_on_entry (vrange &r, basic_block bb, tree name) { + if (!gimple_range_ssa_p (name)) + return get_tree_range (r, name, NULL, bb, NULL); + Value_Range entry_range (TREE_TYPE (name)); - gcc_checking_assert (gimple_range_ssa_p (name)); unsigned idx; if ((idx = tracer.header ("range_on_entry ("))) @@ -174,16 +176,17 @@ gimple_ranger::range_on_entry (vrange &r, basic_block bb, tree name) if (idx) tracer.trailer (idx, "range_on_entry", true, name, r); + return true; } // Calculate the range for NAME at the end of block BB and return it in R. // Return false if no range can be calculated. -void +bool gimple_ranger::range_on_exit (vrange &r, basic_block bb, tree name) { - // on-exit from the exit block? - gcc_checking_assert (gimple_range_ssa_p (name)); + if (!gimple_range_ssa_p (name)) + return get_tree_range (r, name, NULL, NULL, bb); unsigned idx; if ((idx = tracer.header ("range_on_exit ("))) @@ -208,6 +211,7 @@ gimple_ranger::range_on_exit (vrange &r, basic_block bb, tree name) if (idx) tracer.trailer (idx, "range_on_exit", true, name, r); + return true; } // Calculate a range for NAME on edge E and return it in R. diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h index 8739ab6a2ef..167b54b2a37 100644 --- a/gcc/gimple-range.h +++ b/gcc/gimple-range.h @@ -52,8 +52,8 @@ public: virtual bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override; virtual bool range_of_expr (vrange &r, tree name, gimple * = NULL) override; virtual bool range_on_edge (vrange &r, edge e, tree name) override; - void range_on_entry (vrange &r, basic_block bb, tree name); - void range_on_exit (vrange &r, basic_block bb, tree name); + 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; void export_global_ranges (); inline gori_compute &gori () { return m_cache.m_gori; } virtual void dump (FILE *f) override; diff --git a/gcc/value-query.cc b/gcc/value-query.cc index e88c8e25789..c2ab745a466 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -41,6 +41,18 @@ range_query::range_on_edge (vrange &r, edge, tree expr) return range_of_expr (r, expr); } +bool +range_query::range_on_entry (vrange &r, basic_block, tree expr) +{ + return range_of_expr (r, expr); +} + +bool +range_query::range_on_exit (vrange &r, basic_block, tree expr) +{ + return range_of_expr (r, expr); +} + bool range_query::range_of_stmt (vrange &r, gimple *stmt, tree name) { @@ -54,6 +66,9 @@ range_query::range_of_stmt (vrange &r, gimple *stmt, tree name) return false; } +// If the range of expr EXPR at STMT is a single value, return it. +// Otherwise return NULL_TREE. + tree range_query::value_of_expr (tree expr, gimple *stmt) { @@ -76,6 +91,9 @@ range_query::value_of_expr (tree expr, gimple *stmt) return NULL_TREE; } +// If the range on edge E for EXPR is a single value, return it. +// Otherwise return NULL_TREE. + tree range_query::value_on_edge (edge e, tree expr) { @@ -94,9 +112,11 @@ range_query::value_on_edge (edge e, tree expr) return t; } return NULL_TREE; - } +// If the range of STMT for NAME is a single value, return it. +// Otherwise return NULL_TREE. + tree range_query::value_of_stmt (gimple *stmt, tree name) { @@ -113,7 +133,44 @@ range_query::value_of_stmt (gimple *stmt, tree name) if (range_of_stmt (r, stmt, name) && r.singleton_p (&t)) return t; return NULL_TREE; +} + +// If the range on entry to BB for EXPR is a single value, return it. +// Otherwise return NULL_TREE. + +tree +range_query::value_on_entry (basic_block bb, tree expr) +{ + tree t; + gcc_checking_assert (bb); + if (!Value_Range::supports_type_p (TREE_TYPE (expr))) + return NULL_TREE; + + Value_Range r (TREE_TYPE (expr)); + + if (range_on_entry (r, bb, expr) && r.singleton_p (&t)) + return t; + return NULL_TREE; +} + +// If the range on exit to BB for EXPR is a single value, return it. +// Otherwise return NULL_TREE. + +tree +range_query::value_on_exit (basic_block bb, tree expr) +{ + tree t; + + gcc_checking_assert (bb); + if (!Value_Range::supports_type_p (TREE_TYPE (expr))) + return NULL_TREE; + + Value_Range r (TREE_TYPE (expr)); + + if (range_on_exit (r, bb, expr) && r.singleton_p (&t)) + return t; + return NULL_TREE; } void @@ -130,11 +187,36 @@ range_query::~range_query () { } -// Return a range in R for the tree EXPR. Return true if a range is -// representable, and UNDEFINED/false if not. +// This routine will invoke the equivalent of range_of_expr on +// either a gimple statement STMT, on entry to block BBENTRY, or on +// exit from block BBEXIT. Only one of these 3 fields may be set. +// It is valid for none of them to be set, in wqhich case there is no context. + +bool +range_query::invoke_range_of_expr (vrange &r, tree expr, gimple *stmt, + basic_block bbentry, basic_block bbexit) +{ + if (bbentry) + { + gcc_checking_assert (!stmt && !bbexit); + return range_on_entry (r, bbentry, expr); + } + if (bbexit) + { + gcc_checking_assert (!stmt); + return range_on_exit (r, bbexit, expr); + } + + return range_of_expr (r, expr, stmt); +} + +// Return a range in R for the tree EXPR. The context can be either a STMT, +// or on entry to block BBENTRY or exit from block BBEXIT. +// Return true if a range is representable, and UNDEFINED/false if not. bool -range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) +range_query::get_tree_range (vrange &r, tree expr, gimple *stmt, + basic_block bbentry, basic_block bbexit) { tree type; if (TYPE_P (expr)) @@ -180,6 +262,9 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) } case SSA_NAME: + // If this is not an abnormal or virtual ssa, invoke range_of_expr. + if (gimple_range_ssa_p (expr)) + return invoke_range_of_expr (r, expr, stmt, bbentry, bbexit); gimple_range_global (r, expr); return true; @@ -210,8 +295,8 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) { Value_Range r0 (TREE_TYPE (op0)); Value_Range r1 (TREE_TYPE (op1)); - range_of_expr (r0, op0, stmt); - range_of_expr (r1, op1, stmt); + invoke_range_of_expr (r0, op0, stmt, bbentry, bbexit); + invoke_range_of_expr (r1, op1, stmt, bbentry, bbexit); if (!op.fold_range (r, type, r0, r1)) r.set_varying (type); } @@ -228,7 +313,8 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) Value_Range r0 (TREE_TYPE (TREE_OPERAND (expr, 0))); Value_Range r1 (type); r1.set_varying (type); - range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); + invoke_range_of_expr (r0, TREE_OPERAND (expr, 0), stmt, bbentry, + bbexit); if (!op.fold_range (r, type, r0, r1)) r.set_varying (type); } diff --git a/gcc/value-query.h b/gcc/value-query.h index a1306e2bd25..4d2a7bce485 100644 --- a/gcc/value-query.h +++ b/gcc/value-query.h @@ -60,6 +60,8 @@ public: virtual tree value_of_expr (tree expr, gimple * = NULL); virtual tree value_on_edge (edge, tree expr); virtual tree value_of_stmt (gimple *, tree name = NULL); + virtual tree value_on_entry (basic_block, tree expr); + virtual tree value_on_exit (basic_block, tree expr); // These are the range equivalents of the value_* methods. Instead // of returning a singleton, they calculate a range and return it in @@ -70,6 +72,8 @@ public: virtual bool range_of_expr (vrange &r, tree expr, gimple * = NULL) = 0; virtual bool range_on_edge (vrange &r, edge, tree expr); virtual bool range_of_stmt (vrange &r, gimple *, tree name = NULL); + virtual bool range_on_entry (vrange &r, basic_block bb, tree expr); + virtual bool range_on_exit (vrange &r, basic_block bb, tree expr); // Query if there is any relation between SSA1 and SSA2. relation_kind query_relation (gimple *s, tree ssa1, tree ssa2, @@ -82,7 +86,10 @@ public: virtual void dump (FILE *); protected: - bool get_tree_range (vrange &v, tree expr, gimple *stmt); + bool get_tree_range (vrange &v, tree expr, gimple *stmt, + basic_block bbentry = NULL, basic_block bbexit = NULL); + bool invoke_range_of_expr (vrange &v, tree expr, gimple *stmt, + basic_block bbentry, basic_block bbexit); bool get_arith_expr_range (vrange &r, tree expr, gimple *stmt); relation_oracle *m_oracle; };