https://gcc.gnu.org/g:59e5e863c7dc5e8a4164d36273c4c2b5f6cd602c
commit r15-9865-g59e5e863c7dc5e8a4164d36273c4c2b5f6cd602c Author: Richard Biener <rguent...@suse.de> Date: Fri Jun 20 15:07:20 2025 +0200 tree-optimization/120729 - limit compile time in uninit_analysis::prune_phi_opnds The testcase in this PR shows, on the GCC 14 branch, that in some degenerate cases we can spend exponential time pruning always initialized paths through a web of PHIs. The following adds --param uninit-max-prune-work, defaulted to 100000, to limit that to effectively O(1). PR tree-optimization/120729 * gimple-predicate-analysis.h (uninit_analysis::prune_phi_opnds): Add argument of work budget remaining. * gimple-predicate-analysis.cc (uninit_analysis::prune_phi_opnds): Likewise. Maintain and honor it throughout the recursion. * params.opt (uninit-max-prune-work): New. * doc/invoke.texi (uninit-max-prune-work): Document. (cherry picked from commit 97044a47de533f2a9b3fc864e5ea318e53979079) Diff: --- gcc/doc/invoke.texi | 3 +++ gcc/gimple-predicate-analysis.cc | 12 +++++++++--- gcc/gimple-predicate-analysis.h | 2 +- gcc/params.opt | 4 ++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index baaa0c1aed5e..14750aed64db 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -17308,6 +17308,9 @@ predicate chain. @item uninit-max-num-chains Maximum number of predicates ored in the normalized predicate chain. +@item uninit-max-prune-work +Maximum amount of work done to prune paths where the variable is always initialized. + @item sched-autopref-queue-depth Hardware autoprefetcher scheduler model control flag. Number of lookahead cycles the model looks into; at ' diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc index 76f6ab613107..b056b42a17ec 100644 --- a/gcc/gimple-predicate-analysis.cc +++ b/gcc/gimple-predicate-analysis.cc @@ -385,7 +385,8 @@ bool uninit_analysis::prune_phi_opnds (gphi *phi, unsigned opnds, gphi *flag_def, tree boundary_cst, tree_code cmp_code, hash_set<gphi *> *visited_phis, - bitmap *visited_flag_phis) + bitmap *visited_flag_phis, + unsigned &max_attempts) { /* The Boolean predicate guarding the PHI definition. Initialized lazily from PHI in the first call to is_use_guarded() and cached @@ -398,6 +399,10 @@ uninit_analysis::prune_phi_opnds (gphi *phi, unsigned opnds, gphi *flag_def, if (!MASK_TEST_BIT (opnds, i)) continue; + if (max_attempts == 0) + return false; + --max_attempts; + tree flag_arg = gimple_phi_arg_def (flag_def, i); if (!is_gimple_constant (flag_arg)) { @@ -432,7 +437,7 @@ uninit_analysis::prune_phi_opnds (gphi *phi, unsigned opnds, gphi *flag_def, unsigned opnds_arg_phi = m_eval.phi_arg_set (phi_arg_def); if (!prune_phi_opnds (phi_arg_def, opnds_arg_phi, flag_arg_def, boundary_cst, cmp_code, visited_phis, - visited_flag_phis)) + visited_flag_phis, max_attempts)) return false; bitmap_clear_bit (*visited_flag_phis, SSA_NAME_VERSION (phi_result)); @@ -634,9 +639,10 @@ uninit_analysis::overlap (gphi *phi, unsigned opnds, hash_set<gphi *> *visited, value that is in conflict with the use guard/predicate. */ bitmap visited_flag_phis = NULL; gphi *phi_def = as_a<gphi *> (flag_def); + unsigned max_attempts = param_uninit_max_prune_work; bool all_pruned = prune_phi_opnds (phi, opnds, phi_def, boundary_cst, cmp_code, visited, - &visited_flag_phis); + &visited_flag_phis, max_attempts); if (visited_flag_phis) BITMAP_FREE (visited_flag_phis); if (all_pruned) diff --git a/gcc/gimple-predicate-analysis.h b/gcc/gimple-predicate-analysis.h index f71061ec2836..67a19aa09052 100644 --- a/gcc/gimple-predicate-analysis.h +++ b/gcc/gimple-predicate-analysis.h @@ -152,7 +152,7 @@ private: bool is_use_guarded (gimple *, basic_block, gphi *, unsigned, hash_set<gphi *> *); bool prune_phi_opnds (gphi *, unsigned, gphi *, tree, tree_code, - hash_set<gphi *> *, bitmap *); + hash_set<gphi *> *, bitmap *, unsigned &); bool overlap (gphi *, unsigned, hash_set<gphi *> *, const predicate &); void collect_phi_def_edges (gphi *, basic_block, vec<edge> *, diff --git a/gcc/params.opt b/gcc/params.opt index a2b606fb9178..412b6701fadc 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -1189,6 +1189,10 @@ predicate chain. Common Joined UInteger Var(param_uninit_max_num_chains) Init(8) IntegerRange(1, 128) Param Optimization Maximum number of predicates ored in the normalized predicate chain. +-param=uninit-max-prune-work= +Common Joined UInteger Var(param_uninit_max_prune_work) Init(100000) Param Optimization +Maximum amount of work done to prune paths where the variable is always initialized. + -param=uninlined-function-insns= Common Joined UInteger Var(param_uninlined_function_insns) Init(2) Optimization IntegerRange(0, 1000000) Param Instruction accounted for function prologue, epilogue and other overhead.