aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/tree-pass.h1
-rw-r--r--gcc/tree-ssa-threadbackward.c178
2 files changed, 108 insertions, 71 deletions
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 84477a4..d379769 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -407,6 +407,7 @@ extern gimple_opt_pass *make_pass_cd_dce (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_call_cdce (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_merge_phi (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_thread_jumps (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_thread_jumps_full (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_early_thread_jumps (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_split_crit_edges (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_laddress (gcc::context *ctxt);
diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c
index 8cc92a4..62f936a 100644
--- a/gcc/tree-ssa-threadbackward.c
+++ b/gcc/tree-ssa-threadbackward.c
@@ -114,7 +114,7 @@ private:
static const edge UNREACHABLE_EDGE;
// Set to TRUE if unknown SSA names along a path should be resolved
// with the ranger. Otherwise, unknown SSA names are assumed to be
- // VARYING. Setting to true more precise but slower.
+ // VARYING. Setting to true is more precise but slower.
bool m_resolve;
};
@@ -925,47 +925,15 @@ back_threader_registry::register_path (const vec<basic_block> &m_path,
return true;
}
-namespace {
-
-const pass_data pass_data_thread_jumps =
-{
- GIMPLE_PASS,
- "thread",
- OPTGROUP_NONE,
- TV_TREE_SSA_THREAD_JUMPS,
- ( PROP_cfg | PROP_ssa ),
- 0,
- 0,
- 0,
- TODO_update_ssa,
-};
-
-class pass_thread_jumps : public gimple_opt_pass
-{
-public:
- pass_thread_jumps (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_thread_jumps, ctxt)
- {}
-
- opt_pass * clone (void) { return new pass_thread_jumps (m_ctxt); }
- virtual bool gate (function *);
- virtual unsigned int execute (function *);
-};
-
-bool
-pass_thread_jumps::gate (function *fun ATTRIBUTE_UNUSED)
-{
- return flag_thread_jumps && flag_expensive_optimizations;
-}
-
-// Try to thread blocks in FUN. Return TRUE if any jump thread paths were
-// registered.
+// Try to thread blocks in FUN. RESOLVE is TRUE when fully resolving
+// unknown SSAs. SPEED is TRUE when optimizing for speed.
+//
+// Return TRUE if any jump thread paths were registered.
static bool
-try_thread_blocks (function *fun)
+try_thread_blocks (function *fun, bool resolve, bool speed)
{
- /* Try to thread each block with more than one successor. */
- back_threader threader (/*speed=*/true, /*resolve=*/false);
+ back_threader threader (speed, resolve);
basic_block bb;
FOR_EACH_BB_FN (bb, fun)
{
@@ -975,24 +943,27 @@ try_thread_blocks (function *fun)
return threader.thread_through_all_blocks (/*peel_loop_headers=*/true);
}
-unsigned int
-pass_thread_jumps::execute (function *fun)
+static unsigned int
+do_early_thread_jumps (function *fun, bool resolve)
{
- loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES);
+ loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
- bool changed = try_thread_blocks (fun);
+ try_thread_blocks (fun, resolve, /*speed=*/false);
loop_optimizer_finalize ();
-
- return changed ? TODO_cleanup_cfg : 0;
-}
-
+ return 0;
}
-gimple_opt_pass *
-make_pass_thread_jumps (gcc::context *ctxt)
+static unsigned int
+do_thread_jumps (function *fun, bool resolve)
{
- return new pass_thread_jumps (ctxt);
+ loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES);
+
+ bool changed = try_thread_blocks (fun, resolve, /*speed=*/true);
+
+ loop_optimizer_finalize ();
+
+ return changed ? TODO_cleanup_cfg : 0;
}
namespace {
@@ -1010,6 +981,33 @@ const pass_data pass_data_early_thread_jumps =
( TODO_cleanup_cfg | TODO_update_ssa ),
};
+const pass_data pass_data_thread_jumps =
+{
+ GIMPLE_PASS,
+ "thread",
+ OPTGROUP_NONE,
+ TV_TREE_SSA_THREAD_JUMPS,
+ ( PROP_cfg | PROP_ssa ),
+ 0,
+ 0,
+ 0,
+ TODO_update_ssa,
+};
+
+const pass_data pass_data_thread_jumps_full =
+{
+ GIMPLE_PASS,
+ "thread-full",
+ OPTGROUP_NONE,
+ TV_TREE_SSA_THREAD_JUMPS,
+ ( PROP_cfg | PROP_ssa ),
+ 0,
+ 0,
+ 0,
+ TODO_update_ssa,
+};
+
+// Early jump threading pass optimizing for size.
class pass_early_thread_jumps : public gimple_opt_pass
{
public:
@@ -1017,36 +1015,74 @@ public:
: gimple_opt_pass (pass_data_early_thread_jumps, ctxt)
{}
- opt_pass * clone (void) { return new pass_early_thread_jumps (m_ctxt); }
- virtual bool gate (function *);
- virtual unsigned int execute (function *);
+ opt_pass * clone () override
+ {
+ return new pass_early_thread_jumps (m_ctxt);
+ }
+ bool gate (function *) override
+ {
+ return flag_thread_jumps;
+ }
+ unsigned int execute (function *fun) override
+ {
+ return do_early_thread_jumps (fun, /*resolve=*/false);
+ }
};
-bool
-pass_early_thread_jumps::gate (function *fun ATTRIBUTE_UNUSED)
+// Jump threading pass without resolving of unknown SSAs.
+class pass_thread_jumps : public gimple_opt_pass
{
- return flag_thread_jumps;
-}
+public:
+ pass_thread_jumps (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_thread_jumps, ctxt)
+ {}
+ opt_pass * clone (void) override
+ {
+ return new pass_thread_jumps (m_ctxt);
+ }
+ bool gate (function *) override
+ {
+ return flag_thread_jumps && flag_expensive_optimizations;
+ }
+ unsigned int execute (function *fun) override
+ {
+ return do_thread_jumps (fun, /*resolve=*/false);
+ }
+};
-unsigned int
-pass_early_thread_jumps::execute (function *fun)
+// Jump threading pass that fully resolves unknown SSAs.
+class pass_thread_jumps_full : public gimple_opt_pass
{
- loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+public:
+ pass_thread_jumps_full (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_thread_jumps_full, ctxt)
+ {}
+ opt_pass * clone (void) override
+ {
+ return new pass_thread_jumps (m_ctxt);
+ }
+ bool gate (function *) override
+ {
+ return flag_thread_jumps && flag_expensive_optimizations;
+ }
+ unsigned int execute (function *fun) override
+ {
+ return do_thread_jumps (fun, /*resolve=*/true);
+ }
+};
- /* Try to thread each block with more than one successor. */
- back_threader threader (/*speed_p=*/false, /*resolve=*/false);
- basic_block bb;
- FOR_EACH_BB_FN (bb, fun)
- {
- if (EDGE_COUNT (bb->succs) > 1)
- threader.maybe_thread_block (bb);
- }
- threader.thread_through_all_blocks (/*peel_loop_headers=*/true);
+} // namespace {
- loop_optimizer_finalize ();
- return 0;
+gimple_opt_pass *
+make_pass_thread_jumps (gcc::context *ctxt)
+{
+ return new pass_thread_jumps (ctxt);
}
+gimple_opt_pass *
+make_pass_thread_jumps_full (gcc::context *ctxt)
+{
+ return new pass_thread_jumps_full (ctxt);
}
gimple_opt_pass *