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

Reply via email to