From: Andrew MacLeod Date: Tue, 2 Dec 2025 15:12:24 +0000 (-0500) Subject: Return true when a value_relation is added. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d597daf3a8316e3a6f39bed9cc444fe57b11e4cd;p=thirdparty%2Fgcc.git Return true when a value_relation is added. relation_oracle::record does not indicate whether a relation was added. Add a boolean return and only update timestamps when a relation is actually added. PR tree-optimization/122898 gcc/ * gimple-range-fold.cc (fur_source::register_relation): Return a bool; (fur_depend::register_relation): Ditto. (fur_relation::register_relation): Ditto. * gimple-range-fold.h (fur_source::register_relation): Adjust prototype. (fur_depend::register_relation): Ditto. * gimple-range-path.cc (jt_fur_source::register_relation): Return bool. * value-relation.cc (equiv_oracle::add_partial_equiv): Return a bool. (equiv_oracle::record): Return a bool. (relation_oracle::record): Return a bool. (dom_oracle::record): Return a bool. (dom_oracle::set_one_relation): Remove some debug output. (path_oracle::equiv_set): Return a bool. (path_oracle::register_equiv): Return a bool. (path_oracle::record): Return a bool. * value-relation.h (relation_oracle::record): Adjust prototype. (equiv_oracle::add_partial_equiv): Ditto (equiv_oracle::record): Ditto. (dom_oracle::record): Ditto. (path_oracle::equiv_set): Ditto. (path_oracle::register_equiv): Ditto. (path_oracle::record): Ditto. gcc/testsuite * gcc.dg/pr122898.c: New. --- diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index bd5e53516b7..ad11074c14b 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -89,24 +89,26 @@ fur_source::query_relation (tree op1 ATTRIBUTE_UNUSED, return VREL_VARYING; } -// Default registers nothing. +// Default registers nothing and returns false meaning nothing changed. -void +bool fur_source::register_relation (gimple *s ATTRIBUTE_UNUSED, relation_kind k ATTRIBUTE_UNUSED, tree op1 ATTRIBUTE_UNUSED, tree op2 ATTRIBUTE_UNUSED) { + return false; } -// Default registers nothing. +// Default registers nothing and returns false meaning nothing changed. -void +bool fur_source::register_relation (edge e ATTRIBUTE_UNUSED, relation_kind k ATTRIBUTE_UNUSED, tree op1 ATTRIBUTE_UNUSED, tree op2 ATTRIBUTE_UNUSED) { + return false; } // Get the value of EXPR on edge m_edge. @@ -170,12 +172,15 @@ fur_depend::fur_depend (gimple *s, range_query *q, ranger_cache *c) m_depend_p = true; } -// Register a relation on a stmt if there is an oracle. +// Register a relation on a stmt if there is an oracle. Return false if +// no new relation is registered. -void +bool fur_depend::register_relation (gimple *s, relation_kind k, tree op1, tree op2) { - m_query->relation ().record (s, k, op1, op2); + if (!m_query->relation ().record (s, k, op1, op2)) + return false; + // This new relation could cause different calculations, so mark the operands // with a new timestamp, forcing recalculations. if (m_cache) @@ -183,14 +188,18 @@ fur_depend::register_relation (gimple *s, relation_kind k, tree op1, tree op2) m_cache->update_consumers (op1); m_cache->update_consumers (op2); } + return true; } -// Register a relation on an edge if there is an oracle. +// Register a relation on an edge if there is an oracle. Return false if +// no new relation is registered. -void +bool fur_depend::register_relation (edge e, relation_kind k, tree op1, tree op2) { - m_query->relation ().record (e, k, op1, op2); + if (!m_query->relation ().record (e, k, op1, op2)) + return false; + // This new relation could cause different calculations, so mark the operands // with a new timestamp, forcing recalculations. if (m_cache) @@ -198,6 +207,7 @@ fur_depend::register_relation (edge e, relation_kind k, tree op1, tree op2) m_cache->update_consumers (op1); m_cache->update_consumers (op2); } + return true; } // This version of fur_source will pick a range up from a list of ranges @@ -400,9 +410,9 @@ class fur_relation : public fur_stmt { public: fur_relation (gimple *s, range_query *q = NULL); - virtual void register_relation (gimple *stmt, relation_kind k, tree op1, + virtual bool register_relation (gimple *stmt, relation_kind k, tree op1, tree op2); - virtual void register_relation (edge e, relation_kind k, tree op1, + virtual bool register_relation (edge e, relation_kind k, tree op1, tree op2); relation_trio trio() const; private: @@ -423,15 +433,18 @@ fur_relation::trio () const } // Don't support edges, but avoid a compiler warning by providing the routine. +// Return false indicating nothing has changed. -void +bool fur_relation::register_relation (edge, relation_kind, tree, tree) { + return false; } -// Register relation K between OP1 and OP2 on STMT. +// Register relation K between OP1 and OP2 on STMT. Return false if there +// is no relation. -void +bool fur_relation::register_relation (gimple *stmt, relation_kind k, tree op1, tree op2) { @@ -475,6 +488,8 @@ fur_relation::register_relation (gimple *stmt, relation_kind k, tree op1, else if (op2 == a1 && op1 == a2) op1_op2 = relation_swap (k); } + return def_op1 == VREL_VARYING && def_op2 == VREL_VARYING + && op1_op2 == VREL_VARYING; } // Return the relation trio for stmt S using query Q. diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h index 760a107821a..54c1d169b9b 100644 --- a/gcc/gimple-range-fold.h +++ b/gcc/gimple-range-fold.h @@ -113,9 +113,9 @@ public: virtual bool get_operand (vrange &r, tree expr); virtual bool get_phi_operand (vrange &r, tree expr, edge e); virtual relation_kind query_relation (tree op1, tree op2); - virtual void register_relation (gimple *stmt, relation_kind k, tree op1, + virtual bool register_relation (gimple *stmt, relation_kind k, tree op1, tree op2); - virtual void register_relation (edge e, relation_kind k, tree op1, + virtual bool register_relation (edge e, relation_kind k, tree op1, tree op2); void register_outgoing_edges (gcond *, irange &lhs_range, edge e0, edge e1); protected: @@ -144,9 +144,9 @@ class fur_depend : public fur_stmt { public: fur_depend (gimple *s, range_query *q = NULL, class ranger_cache *c = NULL); - virtual void register_relation (gimple *stmt, relation_kind k, tree op1, + virtual bool register_relation (gimple *stmt, relation_kind k, tree op1, tree op2) override; - virtual void register_relation (edge e, relation_kind k, tree op1, + virtual bool register_relation (edge e, relation_kind k, tree op1, tree op2) override; private: ranger_cache *m_cache; diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc index 625622d45aa..823130c35ec 100644 --- a/gcc/gimple-range-path.cc +++ b/gcc/gimple-range-path.cc @@ -615,8 +615,8 @@ class jt_fur_source : public fur_depend public: jt_fur_source (gimple *s, path_range_query *, const vec &); relation_kind query_relation (tree op1, tree op2) override; - void register_relation (gimple *, relation_kind, tree op1, tree op2) override; - void register_relation (edge, relation_kind, tree op1, tree op2) override; + bool register_relation (gimple *, relation_kind, tree op1, tree op2) override; + bool register_relation (edge, relation_kind, tree op1, tree op2) override; private: basic_block m_entry; }; @@ -631,20 +631,22 @@ jt_fur_source::jt_fur_source (gimple *s, m_entry = path[path.length () - 1]; } -// Ignore statement and register relation on entry to path. +// Ignore statement and register relation on entry to path. Return false if +// no new relation is registered. -void +bool jt_fur_source::register_relation (gimple *, relation_kind k, tree op1, tree op2) { - m_query->relation ().record (m_entry, k, op1, op2); + return m_query->relation ().record (m_entry, k, op1, op2); } -// Ignore edge and register relation on entry to path. +// Ignore edge and register relation on entry to path. Return false if no +// new relation is registered. -void +bool jt_fur_source::register_relation (edge, relation_kind k, tree op1, tree op2) { - m_query->relation ().record (m_entry, k, op1, op2); + return m_query->relation ().record (m_entry, k, op1, op2); } relation_kind diff --git a/gcc/testsuite/gcc.dg/pr122898.c b/gcc/testsuite/gcc.dg/pr122898.c new file mode 100644 index 00000000000..8b89c829d10 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr122898.c @@ -0,0 +1,56 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fno-tree-forwprop -fno-tree-fre" } */ +extern void o(); +int a, b, c, d, e, f, g, h, i, k, l, m, n; +volatile int j; +static void p() { + if (d) { + q: + if (a) { + if (k) { + if (!(d && e)) + goto r; + if (i) + goto q; + o(); + } + h || j; + } + s: + d || j; + if (a) + goto q; + r: + if (b) { + if (c) + goto t; + if (b) + goto r; + if (m) + goto q; + } + while (j) + ; + u: + if (g) { + o(); + goto s; + } + if (h) { + t: + if (n) + goto v; + o(); + goto r; + } + int w = i & 1; + v: + if (w <= l) + if (f) + goto u; + goto q; + } + if (a) + goto v; +} +int main() { p(); } diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc index 2ac7650fe5b..c96d438caf4 100644 --- a/gcc/value-relation.cc +++ b/gcc/value-relation.cc @@ -334,9 +334,10 @@ equiv_oracle::~equiv_oracle () bitmap_obstack_release (&m_bitmaps); } -// Add a partial equivalence R between OP1 and OP2. +// Add a partial equivalence R between OP1 and OP2. Return false if no +// new relation is added. -void +bool equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2) { int v1 = SSA_NAME_VERSION (op1); @@ -359,10 +360,10 @@ equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2) // being re-evaluated, or the def was used before being registered. // In either case, if PE2 has an entry, we simply do nothing. if (pe2.members) - return; + return false; // If there are no uses of op2, do not register. if (has_zero_uses (op2)) - return; + return false; // PE1 is the LHS and already has members, so everything in the set // should be a slice of PE2 rather than PE1. pe2.code = pe_min (r, pe1.code); @@ -376,13 +377,13 @@ equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2) m_partial[x].code = pe_min (m_partial[x].code, pe2.code); } bitmap_set_bit (pe1.members, v2); - return; + return true; } if (pe2.members) { // If there are no uses of op1, do not register. if (has_zero_uses (op1)) - return; + return false; pe1.ssa_base = pe2.ssa_base; // If pe2 is a 16 bit value, but only an 8 bit copy, we can't be any // more than an 8 bit equivalence here, so choose MIN value. @@ -394,11 +395,11 @@ equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2) { // If there are no uses of either operand, do not register. if (has_zero_uses (op1) || has_zero_uses (op2)) - return; + return false; // Neither name has an entry, simply create op1 as slice of op2. pe2.code = bits_to_pe (TYPE_PRECISION (TREE_TYPE (op2))); if (pe2.code == VREL_VARYING) - return; + return false; pe2.ssa_base = op2; pe2.members = BITMAP_ALLOC (&m_bitmaps); bitmap_set_bit (pe2.members, v2); @@ -407,6 +408,7 @@ equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2) pe1.members = pe2.members; bitmap_set_bit (pe1.members, v1); } + return true; } // Return the set of partial equivalences associated with NAME. The bitmap @@ -621,19 +623,18 @@ equiv_oracle::register_initial_def (tree ssa) // a query is made as to what equivalences both names have already, and // any preexisting equivalences are merged to create a single equivalence // containing all the ssa_names in this basic block. +// Return false if no new relation is added. -void +bool equiv_oracle::record (basic_block bb, relation_kind k, tree ssa1, tree ssa2) { // Process partial equivalencies. if (relation_partial_equiv_p (k)) - { - add_partial_equiv (k, ssa1, ssa2); - return; - } + return add_partial_equiv (k, ssa1, ssa2); + // Only handle equality relations. if (k != VREL_EQ) - return; + return false; unsigned v1 = SSA_NAME_VERSION (ssa1); unsigned v2 = SSA_NAME_VERSION (ssa2); @@ -650,7 +651,7 @@ equiv_oracle::record (basic_block bb, relation_kind k, tree ssa1, tree ssa2) // Check if they are the same set if (equiv_1 && equiv_1 == equiv_2) - return; + return false; bitmap equiv_set; @@ -674,9 +675,10 @@ equiv_oracle::record (basic_block bb, relation_kind k, tree ssa1, tree ssa2) // A non-null return is a bitmap that is to be added to the current // block as a new equivalence. if (!equiv_set) - return; + return false; add_equiv_to_block (bb, equiv_set); + return true; } // Add an equivalency record in block BB containing bitmap EQUIV_SET. @@ -1073,8 +1075,9 @@ dom_oracle::~dom_oracle () } // Register relation K between ssa_name OP1 and OP2 on STMT. +// Return false if no new relation is added. -void +bool relation_oracle::record (gimple *stmt, relation_kind k, tree op1, tree op2) { gcc_checking_assert (TREE_CODE (op1) == SSA_NAME); @@ -1083,16 +1086,7 @@ relation_oracle::record (gimple *stmt, relation_kind k, tree op1, tree op2) // Don't register lack of a relation. if (k == VREL_VARYING) - return; - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - value_relation vr (k, op1, op2); - fprintf (dump_file, " Registering value_relation "); - vr.dump (dump_file); - fprintf (dump_file, " (bb%d) at ", gimple_bb (stmt)->index); - print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); - } + return false; // If an equivalence is being added between a PHI and one of its arguments // make sure that that argument is not defined in the same block. @@ -1106,22 +1100,26 @@ relation_oracle::record (gimple *stmt, relation_kind k, tree op1, tree op2) if (phi_def == op2) arg = op1; if (gimple_bb (stmt) == gimple_bb (SSA_NAME_DEF_STMT (arg))) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, " Not registered due to "); - print_generic_expr (dump_file, arg, TDF_SLIM); - fprintf (dump_file, " being defined in the same block.\n"); - } - return; - } + return false; + } + + bool ret = record (gimple_bb (stmt), k, op1, op2); + + if (ret && dump_file && (dump_flags & TDF_DETAILS)) + { + value_relation vr (k, op1, op2); + fprintf (dump_file, " Registering value_relation "); + vr.dump (dump_file); + fprintf (dump_file, " (bb%d) at ", gimple_bb (stmt)->index); + print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); } - record (gimple_bb (stmt), k, op1, op2); + return ret; } // Register relation K between ssa_name OP1 and OP2 on edge E. +// Return false if no new relation is added. -void +bool relation_oracle::record (edge e, relation_kind k, tree op1, tree op2) { gcc_checking_assert (TREE_CODE (op1) == SSA_NAME); @@ -1130,34 +1128,35 @@ relation_oracle::record (edge e, relation_kind k, tree op1, tree op2) // Do not register lack of relation, or blocks which have more than // edge E for a predecessor. if (k == VREL_VARYING || !single_pred_p (e->dest)) - return; + return false; - if (dump_file && (dump_flags & TDF_DETAILS)) + bool ret = record (e->dest, k, op1, op2); + + if (ret && dump_file && (dump_flags & TDF_DETAILS)) { value_relation vr (k, op1, op2); fprintf (dump_file, " Registering value_relation "); vr.dump (dump_file); fprintf (dump_file, " on (%d->%d)\n", e->src->index, e->dest->index); } - - record (e->dest, k, op1, op2); + return ret; } // Register relation K between OP! and OP2 in block BB. // This creates the record and searches for existing records in the dominator -// tree to merge with. +// tree to merge with. Return false if no new relation is added. -void +bool dom_oracle::record (basic_block bb, relation_kind k, tree op1, tree op2) { // If the 2 ssa_names are the same, do nothing. An equivalence is implied, // and no other relation makes sense. if (op1 == op2) - return; + return false; // Equivalencies are handled by the equivalence oracle. if (relation_equiv_p (k)) - equiv_oracle::record (bb, k, op1, op2); + return equiv_oracle::record (bb, k, op1, op2); else { // if neither op1 nor op2 are in a relation before this is registered, @@ -1169,6 +1168,7 @@ dom_oracle::record (basic_block bb, relation_kind k, tree op1, tree op2) && (m_relations[bb->index].m_num_relations < param_relation_block_limit)) register_transitives (bb, *ptr); + return ptr != NULL; } } @@ -1201,33 +1201,16 @@ dom_oracle::set_one_relation (basic_block bb, relation_kind k, tree op1, // There is an existing relation in this block, just intersect with it. if (curr != VREL_VARYING) { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, " Intersecting with existing "); - ptr->dump (dump_file); - } // Check into whether we can simply replace the relation rather than // intersecting it. This may help with some optimistic iterative - // updating algorithms. - bool new_rel = ptr->intersect (vr); - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, " to produce "); - ptr->dump (dump_file); - fprintf (dump_file, " %s.\n", new_rel ? "Updated" : "No Change"); - } - // If there was no change, return no record.. - if (!new_rel) + // updating algorithms. If there was no change, return no record.. + if (!ptr->intersect (vr)) return NULL; } else { if (m_relations[bbi].m_num_relations >= param_relation_block_limit) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, " Not registered due to bb being full\n"); - return NULL; - } + return NULL; m_relations[bbi].m_num_relations++; // Check for an existing relation further up the DOM chain. // By including dominating relations, The first one found in any search @@ -1585,9 +1568,9 @@ path_oracle::equiv_set (tree ssa, basic_block bb) } // Register an equivalence between SSA1 and SSA2 resolving unknowns from -// block BB. +// block BB. Return false if no new equivalence was added. -void +bool path_oracle::register_equiv (basic_block bb, tree ssa1, tree ssa2) { const_bitmap equiv_1 = equiv_set (ssa1, bb); @@ -1595,7 +1578,7 @@ path_oracle::register_equiv (basic_block bb, tree ssa1, tree ssa2) // Check if they are the same set, if so, we're done. if (bitmap_equal_p (equiv_1, equiv_2)) - return; + return false; // Don't mess around, simply create a new record and insert it first. bitmap b = BITMAP_ALLOC (&m_bitmaps); @@ -1609,6 +1592,7 @@ path_oracle::register_equiv (basic_block bb, tree ssa1, tree ssa2) ptr->m_next = m_equiv.m_next; m_equiv.m_next = ptr; bitmap_ior_into (m_equiv.m_names, b); + return true; } // Register killing definition of an SSA_NAME. @@ -1658,41 +1642,43 @@ path_oracle::killing_def (tree ssa) } // Register relation K between SSA1 and SSA2, resolving unknowns by -// querying from BB. +// querying from BB. Return false if no new relation is registered. -void +bool path_oracle::record (basic_block bb, relation_kind k, tree ssa1, tree ssa2) { // If the 2 ssa_names are the same, do nothing. An equivalence is implied, // and no other relation makes sense. if (ssa1 == ssa2) - return; - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - value_relation vr (k, ssa1, ssa2); - fprintf (dump_file, " Registering value_relation (path_oracle) "); - vr.dump (dump_file); - fprintf (dump_file, " (root: bb%d)\n", bb->index); - } + return false; relation_kind curr = query (bb, ssa1, ssa2); if (curr != VREL_VARYING) k = relation_intersect (curr, k); + bool ret; if (k == VREL_EQ) + ret = register_equiv (bb, ssa1, ssa2); + else { - register_equiv (bb, ssa1, ssa2); - return; + bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa1)); + bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa2)); + relation_chain *ptr = (relation_chain *) obstack_alloc (&m_chain_obstack, + sizeof (relation_chain)); + ptr->set_relation (k, ssa1, ssa2); + ptr->m_next = m_relations.m_head; + m_relations.m_head = ptr; + ret = true; } - bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa1)); - bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa2)); - relation_chain *ptr = (relation_chain *) obstack_alloc (&m_chain_obstack, - sizeof (relation_chain)); - ptr->set_relation (k, ssa1, ssa2); - ptr->m_next = m_relations.m_head; - m_relations.m_head = ptr; + if (ret && dump_file && (dump_flags & TDF_DETAILS)) + { + value_relation vr (k, ssa1, ssa2); + fprintf (dump_file, " Registering value_relation (path_oracle) "); + vr.dump (dump_file); + fprintf (dump_file, " (root: bb%d)\n", bb->index); + } + return ret; } // Query for a relationship between equiv set B1 and B2, resolving unknowns diff --git a/gcc/value-relation.h b/gcc/value-relation.h index 87f0d856fab..fface9436bb 100644 --- a/gcc/value-relation.h +++ b/gcc/value-relation.h @@ -100,9 +100,9 @@ public: virtual ~relation_oracle () { } // register a relation between 2 ssa names. - void record (gimple *, relation_kind, tree, tree); - void record (edge, relation_kind, tree, tree); - virtual void record (basic_block, relation_kind, tree, tree) { } + bool record (gimple *, relation_kind, tree, tree); + bool record (edge, relation_kind, tree, tree); + virtual bool record (basic_block, relation_kind, tree, tree) { return false; } // Query if there is any relation between SSA1 and SSA2. relation_kind query (gimple *s, tree ssa1, tree ssa2); @@ -166,7 +166,7 @@ public: ~equiv_oracle (); const_bitmap equiv_set (tree ssa, basic_block bb) final override; - void record (basic_block bb, relation_kind k, tree ssa1, tree ssa2) override; + bool record (basic_block bb, relation_kind k, tree ssa1, tree ssa2) override; relation_kind partial_equiv (tree ssa1, tree ssa2, tree *base = NULL) const; relation_kind query (basic_block, tree, tree) override; @@ -175,7 +175,7 @@ public: void dump (FILE *f) const override; protected: - void add_partial_equiv (relation_kind, tree, tree); + bool add_partial_equiv (relation_kind, tree, tree); const pe_slice *partial_equiv_set (tree name) final override; inline bool has_equiv_p (unsigned v) { return bitmap_bit_p (m_equiv_set, v); } bitmap_obstack m_bitmaps; @@ -224,7 +224,7 @@ public: dom_oracle (bool do_trans_p = true); ~dom_oracle (); - void record (basic_block bb, relation_kind k, tree op1, tree op2) + bool record (basic_block bb, relation_kind k, tree op1, tree op2) final override; relation_kind query (basic_block bb, tree ssa1, tree ssa2) final override; @@ -273,7 +273,7 @@ public: path_oracle (relation_oracle *oracle = NULL); ~path_oracle (); const_bitmap equiv_set (tree, basic_block) final override; - void record (basic_block, relation_kind, tree, tree) final override; + bool record (basic_block, relation_kind, tree, tree) final override; void killing_def (tree); relation_kind query (basic_block, tree, tree) final override; relation_kind query (basic_block, const_bitmap, const_bitmap) final override; @@ -282,7 +282,7 @@ public: void dump (FILE *, basic_block) const final override; void dump (FILE *) const final override; private: - void register_equiv (basic_block bb, tree ssa1, tree ssa2); + bool register_equiv (basic_block bb, tree ssa1, tree ssa2); equiv_chain m_equiv; relation_chain_head m_relations; relation_oracle *m_root;