https://gcc.gnu.org/g:b3b2da1389be9f54f72d8933c4eaee972c39de16
commit r16-5461-gb3b2da1389be9f54f72d8933c4eaee972c39de16 Author: Andrew MacLeod <[email protected]> Date: Thu Nov 20 12:10:25 2025 -0500 Improve PHI analyzer performance Only do iterative analysis if it might be worthwhile. PR tree-optimization/121345 gcc/ * gimple-range-phi.cc (phi_group::calculate_using_modifier): Restore performance loss by being more selective when iterating. Diff: --- gcc/gimple-range-phi.cc | 48 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/gcc/gimple-range-phi.cc b/gcc/gimple-range-phi.cc index 85d0f2795923..656d749d48d0 100644 --- a/gcc/gimple-range-phi.cc +++ b/gcc/gimple-range-phi.cc @@ -127,29 +127,59 @@ phi_group::calculate_using_modifier (range_query *q) else return false; - // Examine modifier and run 10 iterations to see if it convergences. + // If we can resolve the range using relations, use that range. + if (refine_using_relation (k)) + return true; + + // Examine modifier and run iteration evaluations to see if it convergences. // The constructor initilaized m_vr to the initial value already. - const unsigned num_iter = 10; int_range_max nv; int_range_max iter_value = m_vr; int_range_max iter_reach; - // Determie the maximum range of ITER reaching here. Often a loop - // bound restricts the range reaching here. Default to VARYING. + + // Determine the maximum range of the var reaching here. The back edge + // usually has a guard restircting the range. Default to VARYING. if (!m_modifier_name || !q->range_of_expr (iter_reach, m_modifier_name, m_modifier)) iter_reach.set_varying (m_vr.type ()); + + // Iterative evaluation can be expensive, so heuristically : + // - PLUS and MINUS are 98% of the cases, and usually handled well enough + // by loop analysis, The exception is if the reaching range has multiple + // subranges, those are often worth examining. + // - All other operations (2%) are worth checking. + bool do_iterative = false; + if (gimple_code (m_modifier) == GIMPLE_ASSIGN) + switch (gimple_assign_rhs_code (m_modifier)) + { + case PLUS_EXPR: + case MINUS_EXPR: + if (iter_reach.num_pairs () > 1) + do_iterative = true; + break; + default: + do_iterative = true; + } + + // Limit iterations to 1 more than the number of bits. + unsigned num_iter; + if (do_iterative) + num_iter = TYPE_PRECISION (m_vr.type ()) + 1; + else + num_iter = 0; + for (unsigned x = 0; x < num_iter; x++) { if (!fold_range (nv, m_modifier, iter_value, q)) break; - // Ensure nothing calculate is outside outside the reaching range. + // Ensure nothing calculated is outside outside the reaching range. nv.intersect (iter_reach); // If union does nothing, then we have convergence. if (!iter_value.union_ (nv)) { if (iter_value.varying_p ()) break; - // The last iteration Will reach the PHI node. + // The last iteration Will also reach the PHI node, add it in. fold_range (nv, m_modifier, iter_value, q); iter_value.union_ (nv); m_vr = iter_value; @@ -157,17 +187,13 @@ phi_group::calculate_using_modifier (range_query *q) } } - // If we can resolve the range using relations, use that range. - if (refine_using_relation (k)) - return true; - // Never converged, so bail for now. we could examine the pattern // from m_initial to m_vr as an extension Especially if we had a way // to project the actual number of iterations (SCEV?) // // We can also try to identify "parallel" phis to get loop counts and // determine the number of iterations of these parallel PHIs. - // + return false; }
