From 06f435d587db631be745eb36c46e550939022827 Mon Sep 17 00:00:00 2001 Message-ID: <06f435d587db631be745eb36c46e550939022827.1787205028.git.sam@gentoo.org> From: Andrew MacLeod Date: Tue, 18 Aug 2026 08:58:35 -0400 Subject: [PATCH] Provide a range_info reset method. Provide a mechanism to reset range info in ranger and the oracles. PR tree-optimization/126856 gcc/ * gimple-range-cache.cc (block_range_cache::clear): New. (ranger_cache::reset_range_info): New. * gimple-range-cache.h (block_range_cache::clear): Declare. (ranger_cache::reset_range_info): Declare. * gimple-range-gori.cc (range_def_chain::clear): New. * gimple-range-gori.h (range_def_chain::clear): Declare. * gimple-range-infer.cc (infer_range_manager::clear): New. * gimple-range-infer.h (infer_oracle::clear): New virtual function. (infer_range_manager::clear): Override. * gimple-range.cc (gimple_ranger::reset_range_info): New. * gimple-range.h (gimple_ranger::reset_range_info): Declare. * tree-ssa-dce.cc (simple_dce_from_worklist): Reset flow-sensitive information when replacing a definition. * tree-ssanames.cc (reset_flow_sensitive_info): Reset information maintained by the current range query. * value-query.cc (range_query::reset_range_info): New. * value-query.h (range_query::reset_range_info): Declare. * value-relation.cc (equiv_oracle::clear): New. (relation_chain_head::clear): New. (dom_oracle::clear): New. (path_oracle::clear): New. * value-relation.h (relation_oracle::clear): New virtual function. (equiv_oracle::clear): Override. (relation_chain_head::clear): Declare. (dom_oracle::clear): Override. (path_oracle::clear): Override. gcc/testsuite/ * gcc.dg/pr126856.c: New test. --- gcc/gimple-range-cache.cc | 21 +++++++ gcc/gimple-range-cache.h | 3 + gcc/gimple-range-gori.cc | 15 +++++ gcc/gimple-range-gori.h | 1 + gcc/gimple-range-infer.cc | 31 +++++++++++ gcc/gimple-range-infer.h | 2 + gcc/gimple-range.cc | 9 +++ gcc/gimple-range.h | 1 + gcc/testsuite/gcc.dg/pr126856.c | 16 ++++++ gcc/tree-ssa-dce.cc | 2 + gcc/tree-ssanames.cc | 3 + gcc/value-query.cc | 11 ++++ gcc/value-query.h | 2 + gcc/value-relation.cc | 98 +++++++++++++++++++++++++++++++++ gcc/value-relation.h | 11 ++++ 15 files changed, 226 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/pr126856.c diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc index a540a10ce588..0386b9981178 100644 --- a/gcc/gimple-range-cache.cc +++ b/gcc/gimple-range-cache.cc @@ -381,6 +381,17 @@ block_range_cache::~block_range_cache () bitmap_obstack_release (&m_bitmaps); } +// Clear block info for NAME. + +void +block_range_cache::clear (tree name) +{ + unsigned v = SSA_NAME_VERSION (name); + if (v >= m_ssa_ranges.length ()) + return; + m_ssa_ranges[v] = NULL; +} + // Set the range for NAME on entry to block BB to R. // If it has not been accessed yet, allocate it first. @@ -1982,3 +1993,13 @@ ranger_cache::apply_inferred_ranges (gimple *s) for (unsigned x = 0; x < infer.num (); x++) register_inferred_value (infer.range (x), infer.name (x), bb); } + +// Reset range info for NAME. + +void +ranger_cache::reset_range_info (tree name) +{ + m_on_entry.clear (name); + m_globals.clear_range (name); + range_query::reset_range_info (name); +} diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h index e01f35a548db..8a4185fc3e37 100644 --- a/gcc/gimple-range-cache.h +++ b/gcc/gimple-range-cache.h @@ -38,6 +38,7 @@ public: bool set_bb_range (tree name, const_basic_block bb, const vrange &v); bool get_bb_range (vrange &v, tree name, const_basic_block bb); bool bb_range_p (tree name, const_basic_block bb); + void clear (tree name); void dump (FILE *f); void dump (FILE *f, basic_block bb, bool print_varying = true); @@ -120,6 +121,8 @@ public: void register_inferred_value (const vrange &r, tree name, basic_block bb); void apply_inferred_ranges (gimple *s); + void reset_range_info (tree name); + void dump_bb (FILE *f, basic_block bb); virtual void dump (FILE *f) override; private: diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index 3bdc5305b491..d34c2b79a7c8 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -295,6 +295,21 @@ range_def_chain::get_def_chain (tree name) return m_def_chain[v].bm; } +// Clear def chain info for NAME. + +void +range_def_chain::clear (tree name) +{ + unsigned v = SSA_NAME_VERSION (name); + if (v >= m_def_chain.length ()) + return; + + m_def_chain[v].ssa1 = 0; + m_def_chain[v].ssa2 = 0; + m_def_chain[v].bm = NULL; + get_def_chain (name); +} + // Dump what we know for basic block BB to file F. void diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h index d562c515a28e..ab83d8f3dff8 100644 --- a/gcc/gimple-range-gori.h +++ b/gcc/gimple-range-gori.h @@ -36,6 +36,7 @@ public: bool in_chain_p (tree name, tree def); bool chain_import_p (tree name, tree import); void register_dependency (tree name, tree ssa1, basic_block bb = NULL); + void clear (tree name); void dump (FILE *f, basic_block bb, const char *prefix = NULL); protected: bool has_def_chain (tree name); diff --git a/gcc/gimple-range-infer.cc b/gcc/gimple-range-infer.cc index 65c10ac1cb43..5f0f7efcc012 100644 --- a/gcc/gimple-range-infer.cc +++ b/gcc/gimple-range-infer.cc @@ -532,3 +532,34 @@ infer_range_manager::register_all_uses (tree name) } } } + +// Clear all inferred ranges for NAME. + +void +infer_range_manager::clear(tree name) +{ + if (!m_seen) + return; + + // Check if this name has any inferred ranges. + unsigned v = SSA_NAME_VERSION (name); + if (!bitmap_bit_p (m_seen, v)) + return; + + // Check each basic block for an inferred range. + basic_block bb; + FOR_EACH_BB_FN (bb, cfun) + { + unsigned bbi = bb->index; + if (bbi >= m_on_exit.length ()) + continue; + exit_range *ptr = m_on_exit[bbi].find_ptr (name); + if (ptr) + { + bitmap_clear_bit (m_on_exit[bbi].m_names, v); + ptr->name = NULL; + } + } + + bitmap_clear_bit (m_seen, v); +} diff --git a/gcc/gimple-range-infer.h b/gcc/gimple-range-infer.h index e2adeec8edf2..ca95e121633b 100644 --- a/gcc/gimple-range-infer.h +++ b/gcc/gimple-range-infer.h @@ -89,6 +89,7 @@ public: virtual bool has_range_p (basic_block, tree = NULL_TREE) { return false; } virtual bool maybe_adjust_range (vrange &, tree, basic_block) { return false; } + virtual void clear (tree) { } }; // This class manages a list of inferred ranges for each basic block. @@ -115,6 +116,7 @@ public: virtual void add_ranges (gimple *s, gimple_infer_range &ir); virtual bool has_range_p (basic_block bb, tree name = NULL_TREE); virtual bool maybe_adjust_range (vrange &r, tree name, basic_block bb); + virtual void clear (tree name); private: void add_range (tree name, gimple *s, const vrange &r); void add_nonzero (tree name, gimple *s); diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 37390c5df276..b221cfc56164 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -607,6 +607,15 @@ gimple_ranger::update_range_info (tree name, const vrange &r) } } +// Reset range information for NAME. + +void +gimple_ranger::reset_range_info (tree name) +{ + // Clearing the cache will also clear all the shared oracles. + m_cache.reset_range_info (name); +} + // This routine will export whatever global ranges are known to GCC // SSA_RANGE_NAME_INFO and SSA_NAME_PTR_INFO fields. diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h index a74b48aafe68..003fede83342 100644 --- a/gcc/gimple-range.h +++ b/gcc/gimple-range.h @@ -65,6 +65,7 @@ public: void register_inferred_ranges (gimple *s); void register_transitive_inferred_ranges (basic_block bb); range_query &const_query (); + void reset_range_info (tree name); protected: bool fold_range_internal (vrange &r, gimple *s, tree name); struct prefill_frame diff --git a/gcc/testsuite/gcc.dg/pr126856.c b/gcc/testsuite/gcc.dg/pr126856.c new file mode 100644 index 000000000000..9f1d7734705c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr126856.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +__attribute__((noipa)) static int +mpfr_scale2_bad (int exp) +{ + if (-1073 > exp || exp > 1025) + __builtin_unreachable(); + if (exp < -1021) + __builtin_abort(); + return exp; +} +int main () +{ + if (mpfr_scale2_bad(499) != 499) + __builtin_abort(); +} diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc index 18bc851b2cdd..a5391290c4dc 100644 --- a/gcc/tree-ssa-dce.cc +++ b/gcc/tree-ssa-dce.cc @@ -2278,6 +2278,7 @@ simple_dce_from_worklist (bitmap worklist, bitmap need_eh_cleanup, for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) SET_PHI_ARG_DEF (phi, i, zero); update_stmt (phi); + reset_flow_sensitive_info (def); } else remove_phi_node (&gsi, true); @@ -2292,6 +2293,7 @@ simple_dce_from_worklist (bitmap worklist, bitmap need_eh_cleanup, tree zero = build_zero_cst (TREE_TYPE (def)); gassign *new_stmt = gimple_build_assign (def, zero); gsi_replace (&gsi, new_stmt, true); + reset_flow_sensitive_info (def); } else { diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc index 9ad860df65a1..8eac57f42cba 100644 --- a/gcc/tree-ssanames.cc +++ b/gcc/tree-ssanames.cc @@ -927,6 +927,9 @@ reset_flow_sensitive_info (tree name) } else SSA_NAME_RANGE_INFO (name) = NULL; + + // Clear range info in the current range query. + get_range_query (cfun)->reset_range_info (name); } /* Clear all flow sensitive data from all statements and PHI definitions diff --git a/gcc/value-query.cc b/gcc/value-query.cc index decf4e4d0ac0..17077eef9e8b 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -78,6 +78,17 @@ range_query::update_range_info (tree, const vrange &) { } +// Default for resetting range info for NAME is to clear the oracles. + +void +range_query::reset_range_info (tree name) +{ + relation ().clear (name); + if (gori_ssa ()) + gori_ssa ()->clear (name); + infer_oracle ().clear (name); +} + // If the range of expr EXPR at STMT is a single value, return it. // Otherwise return NULL_TREE. diff --git a/gcc/value-query.h b/gcc/value-query.h index 7756e431155a..9932d7d493b2 100644 --- a/gcc/value-query.h +++ b/gcc/value-query.h @@ -79,6 +79,8 @@ public: virtual void update_range_info (tree name); // Provide a specific range update to NAME. virtual void update_range_info (tree name, const vrange &r); + // Reset range information for NAME. + virtual void reset_range_info (tree name); inline class relation_oracle &relation () const { return *m_relation; } void create_relation_oracle (bool do_trans_p = true); diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc index cc9e8e56c67b..b4b65e6cdc8b 100644 --- a/gcc/value-relation.cc +++ b/gcc/value-relation.cc @@ -621,6 +621,38 @@ equiv_oracle::register_initial_def (tree ssa) add_equiv_to_block (bb, equiv_set); } +// Clear the equivalence lists and partial equivalencs for NAME. + +void +equiv_oracle::clear (tree name) +{ + unsigned v = SSA_NAME_VERSION (name); + // Remove v from any equivalences. + if (bitmap_bit_p (m_equiv_set, v)) + { + basic_block bb; + FOR_EACH_BB_FN (bb, cfun) + { + unsigned bbi = bb->index; + if (bbi >= m_equiv.length ()) + continue; + if (!m_equiv[bbi]) + continue; + equiv_chain *ptr = m_equiv[bbi]->find (v); + if (ptr) + { + bitmap_clear_bit (ptr->m_names, v); + bitmap_clear_bit (m_equiv[bbi]->m_names, v); + } + } + bitmap_clear_bit (m_equiv_set, v); + } + // Eliminate any partial equivs. + if (v < m_partial.length ()) + m_partial[v].members = NULL; +} + + // Register an equivalence between SSA1 and SSA2 in block BB. // The equivalence oracle maintains a vector of equivalencies indexed by basic // block. When an equivalence between SSA1 and SSA2 is registered in block BB, @@ -1078,6 +1110,56 @@ dom_oracle::~dom_oracle () m_relations.release (); } +// Remove any relations with NAME from this list. + +void +relation_chain_head::clear (tree name) +{ + unsigned v = SSA_NAME_VERSION (name); + if (!m_names || !bitmap_bit_p (m_names, v)) + return; + + relation_chain *ptr, *last = NULL;; + + for (ptr = m_head; ptr; ptr = ptr->m_next) + { + tree op1 = ptr->op1 (); + tree op2 = ptr->op2 (); + // Delink any elements with NAME. + if (op1 == name || op2 == name) + { + if (!last) + m_head = ptr->m_next; + else + last->m_next = ptr->m_next; + } + else + last = ptr; + } + // And remove name from the possible relations in this block bitfield. + bitmap_clear_bit (m_names, v); +} + +// Remove any relations involving NAME from the DOM oracle + +void +dom_oracle::clear (tree name) +{ + equiv_oracle::clear (name); + unsigned v = SSA_NAME_VERSION (name); + if (bitmap_bit_p (m_relation_set, v)) + { + basic_block bb; + FOR_EACH_BB_FN (bb, cfun) + { + if (bb->index >= (int)m_relations.length()) + continue; + m_relations[bb->index].clear (name); + } + bitmap_clear_bit (m_relation_set, v); + } +} + // Register relation K between ssa_name OP1 and OP2 on STMT. // Return false if no new relation is added. @@ -1728,6 +1810,22 @@ path_oracle::~path_oracle () bitmap_obstack_release (&m_bitmaps); } +// Clear any range info and relations associated with NAME. + +void +path_oracle::clear (tree name) +{ + if (m_root) + m_root->clear (name); + + m_relations.clear (name); + + unsigned v = SSA_NAME_VERSION (name); + equiv_chain *ptr = m_equiv.find (v); + if (ptr) + bitmap_clear_bit (ptr->m_names, v); +} + // Return the equiv set for SSA, and if there isn't one, check for equivs // starting in block BB. diff --git a/gcc/value-relation.h b/gcc/value-relation.h index eed79c5e83d8..d150b0ac5b2a 100644 --- a/gcc/value-relation.h +++ b/gcc/value-relation.h @@ -110,6 +110,9 @@ public: relation_kind query (edge e, tree ssa1, tree ssa2); virtual relation_kind query (basic_block, tree, tree) { return VREL_VARYING; } + // Remove relations for an SSA_NAME + virtual void clear (tree) { } + virtual void dump (FILE *, basic_block) const { } virtual void dump (FILE *) const { } void debug () const; @@ -174,6 +177,8 @@ public: relation_kind partial_equiv (tree ssa1, tree ssa2, tree *base = NULL) const; relation_kind query (basic_block, tree, tree) override; relation_kind query (basic_block, const_bitmap, const_bitmap) override; + + virtual void clear (tree name); void dump (FILE *f, basic_block bb) const override; void dump (FILE *f) const override; @@ -209,6 +214,7 @@ public: class relation_chain *m_head; // List of relations in block. int m_num_relations; // Number of relations in block. relation_kind find_relation (const_bitmap b1, const_bitmap b2) const; + void clear (tree name); }; // A relation oracle maintains a set of relations between ssa_names using the @@ -234,6 +240,8 @@ public: relation_kind query (basic_block bb, const_bitmap b1, const_bitmap b2) final override; + virtual void clear (tree name); + void dump (FILE *f, basic_block bb) const final override; void dump (FILE *f) const final override; protected: @@ -284,6 +292,9 @@ public: relation_kind query (basic_block, const_bitmap, const_bitmap) final override; void reset_path (relation_oracle *oracle = NULL); void set_root_oracle (relation_oracle *oracle) { m_root = oracle; } + + virtual void clear (tree name); + void dump (FILE *, basic_block) const final override; void dump (FILE *) const final override; private: -- 2.55.0