https://gcc.gnu.org/g:8b34a015640d9ffbd4a32525c5fcc3617a238688
commit r17-4005-g8b34a015640d9ffbd4a32525c5fcc3617a238688 Author: Aldy Hernandez <[email protected]> Date: Mon Sep 7 17:28:22 2026 +0000 backthreader: reuse one path_range_query across candidate paths find_taken_edge_* built a fresh path_range_query for every candidate path, which means a path_oracle allocation, an ssa_lazy_cache setup and a heap vec for the path per candidate. path_range_query already has a reset_path method for exactly this, which we're already using in DOM's hybrid threader. Do the same here. Measured in perf instructions retired over our stage1 .ii corpus, this drops back_threader::thread_blocks() by a further 6.7% (pass_thread_jumps 7.9%, pass_thread_jumps_full 5.0%, pass_early_thread_jumps 5.1%) and the whole compile by a further 0.08% over 806 TUs, for 8.8% and 0.10% over the two patches. Tested on ppc64le Linux. The assembly is identical over the .ii files, so this is a NFC. gcc/ChangeLog: * gimple-range-path.cc (path_range_query::reset_path): Splice into the existing path vector. (path_range_query::compute_ranges): Reset the path oracle unconditionally. * tree-ssa-threadbackward.cc (back_threader::m_solver): New. (back_threader::back_threader): Allocate it. (back_threader::~back_threader): Free it. (back_threader::find_taken_edge_goto): Use it. (back_threader::find_taken_edge_switch): Same. (back_threader::find_taken_edge_cond): Same. Diff: --- gcc/gimple-range-path.cc | 15 +++++++++------ gcc/tree-ssa-threadbackward.cc | 19 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc index 54c8a04b486f..aa60db65f4ff 100644 --- a/gcc/gimple-range-path.cc +++ b/gcc/gimple-range-path.cc @@ -205,7 +205,11 @@ path_range_query::reset_path (const vec<basic_block> &path, const bitmap_head *dependencies) { gcc_checking_assert (path.length () > 1); - m_path = path.copy (); + + // Use truncate/safe_splice instead of copy() to avoid repeated mallocs here. + m_path.truncate (0); + m_path.safe_splice (path); + m_pos = m_path.length () - 1; m_undefined_path = false; m_cache.clear (); @@ -576,11 +580,10 @@ path_range_query::compute_ranges (const bitmap_head *dependencies) else compute_exit_dependencies (m_exit_dependencies); - if (m_resolve) - { - path_oracle *p = get_path_oracle (); - p->reset_path (&(m_ranger.relation ())); - } + // The oracle carries state from any previously solved path, so it has + // to be reset even in non-resolving mode. + path_oracle *p = get_path_oracle (); + p->reset_path (&(m_ranger.relation ())); if (DEBUG_SOLVER) { diff --git a/gcc/tree-ssa-threadbackward.cc b/gcc/tree-ssa-threadbackward.cc index 20bb74c507fd..4173f9c9e8c3 100644 --- a/gcc/tree-ssa-threadbackward.cc +++ b/gcc/tree-ssa-threadbackward.cc @@ -135,6 +135,8 @@ private: function *m_fun; // Ranger for the path solver. gimple_ranger *m_ranger; + // Path solver, reused across all candidate paths. + path_range_query *m_solver; unsigned m_flags; // Set to TRUE for the first of each thread[12] pass or the first of // each threadfull[12] pass. This is used to differentiate between @@ -163,10 +165,12 @@ back_threader::back_threader (function *fun, unsigned flags, bool first) mark_dfs_back_edges (); m_ranger = new gimple_ranger; + m_solver = new path_range_query (*m_ranger, flags & BT_RESOLVE); } back_threader::~back_threader () { + delete m_solver; delete m_ranger; loop_optimizer_finalize (); } @@ -300,9 +304,8 @@ back_threader::find_taken_edge_goto (const vec<basic_block> &path, if (TREE_CODE (dest) == SSA_NAME) { prange r; - path_range_query solver (*m_ranger, path, m_imports, - m_flags & BT_RESOLVE); - if (!solver.range_of_expr (r, dest, stmt)) + m_solver->reset_path (path, m_imports); + if (!m_solver->range_of_expr (r, dest, stmt)) return NULL; if (r.undefined_p ()) @@ -328,8 +331,8 @@ back_threader::find_taken_edge_switch (const vec<basic_block> &path, tree name = gimple_switch_index (sw); int_range_max r; - path_range_query solver (*m_ranger, path, m_imports, m_flags & BT_RESOLVE); - solver.range_of_expr (r, name, sw); + m_solver->reset_path (path, m_imports); + m_solver->range_of_expr (r, name, sw); if (r.undefined_p ()) return UNREACHABLE_EDGE; @@ -352,10 +355,10 @@ back_threader::find_taken_edge_cond (const vec<basic_block> &path, { int_range_max r; - path_range_query solver (*m_ranger, path, m_imports, m_flags & BT_RESOLVE); - solver.range_of_stmt (r, cond); + m_solver->reset_path (path, m_imports); + m_solver->range_of_stmt (r, cond); - if (solver.unreachable_path_p ()) + if (m_solver->unreachable_path_p ()) return UNREACHABLE_EDGE; int_range<2> true_range = range_true ();
