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.
Pushed.
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.
---
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 54c8a04b486..aa60db65f4f 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 90691ea9612..490393357c7 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,6 +165,7 @@ 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);
m_visited_bbs = sbitmap_alloc (last_basic_block_for_fn (fun));
bitmap_clear (m_visited_bbs);
}
@@ -170,6 +173,7 @@ back_threader::back_threader (function *fun, unsigned
flags, bool first)
back_threader::~back_threader ()
{
sbitmap_free (m_visited_bbs);
+ delete m_solver;
delete m_ranger;
loop_optimizer_finalize ();
}
@@ -303,9 +307,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 ())
@@ -331,8 +334,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;
@@ -355,10 +358,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 ();
--
2.53.0