From: Kyrylo Tkachov <[email protected]>
The three RTL if-conversion passes were three near-identical rtl_opt_pass
subclasses, and if_convert took a bool after_combine that was stored in the
ifcvt_after_combine file-scope global purely so cheap_bb_rtx_cost_p could
tell the pre-combine run apart from the later ones.
Introduce an ifcvt_phase enum (BEFORE_COMBINE, AFTER_COMBINE, AFTER_RELOAD)
and give if_convert that instead of the bool. Collapse the three pass
classes into one pass_rtl_ifcvt parameterised on the phase: the phase
selects the gate condition and whether execute cleans up the CFG (ce1) or
just reruns if-conversion (ce2/ce3). The three pass_data blocks and the
three make_pass_* entry points stay, so the pipeline is unchanged. No
functional change.
gcc/ChangeLog:
* ifcvt.cc (enum ifcvt_phase): New.
(ifcvt_pass_phase): New, replacing...
(ifcvt_after_combine): ...this.
(cheap_bb_rtx_cost_p): Test ifcvt_pass_phase.
(if_convert): Take an ifcvt_phase instead of a bool.
(rest_of_handle_if_conversion): Adjust caller.
(pass_if_after_combine, pass_if_after_reload): Remove, folding both
into...
(pass_rtl_ifcvt): ...this, now parameterised on the phase.
(make_pass_rtl_ifcvt, make_pass_if_after_combine,
make_pass_if_after_reload): Construct it with the matching phase.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/ifcvt.cc | 151 ++++++++++++++++++++++-----------------------------
1 file changed, 66 insertions(+), 85 deletions(-)
diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 9528f5f9a55..6d4ebb70656 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -57,8 +57,18 @@
#define NULL_BLOCK ((basic_block) NULL)
-/* True if after combine pass. */
-static bool ifcvt_after_combine;
+/* Which of the three RTL if-conversion passes is running. ce1 runs before
+ combine, ce2 after combine and ce3 after reload. The cost model treats the
+ pre-combine run specially, so the phase is recorded here. */
+enum ifcvt_phase
+{
+ IFCVT_BEFORE_COMBINE, /* ce1. */
+ IFCVT_AFTER_COMBINE, /* ce2. */
+ IFCVT_AFTER_RELOAD /* ce3. */
+};
+
+/* The if-conversion pass currently running. */
+static ifcvt_phase ifcvt_pass_phase;
/* True if the target has the cbranchcc4 optab. */
static bool have_cbranchcc4;
@@ -153,7 +163,8 @@ cheap_bb_rtx_cost_p (const_basic_block bb,
Use optimize_function_for_speed_p instead of the pre-defined
variable speed to make sure it is set to same value for all
basic blocks in one if-conversion transformation. */
- if (!optimize_function_for_speed_p (cfun) && ifcvt_after_combine)
+ if (!optimize_function_for_speed_p (cfun)
+ && ifcvt_pass_phase != IFCVT_BEFORE_COMBINE)
scale = REG_BR_PROB_BASE;
/* Our branch probability/scaling factors are just estimates and don't
account for cases where we can get speculation for free and other
@@ -6887,11 +6898,11 @@ dead_or_predicable (basic_block test_bb, basic_block
merge_bb,
return false;
}
-/* Main entry point for all if-conversion. AFTER_COMBINE is true if
- we are after combine pass. */
+/* Main entry point for all if-conversion. PHASE selects the ce1, ce2 or ce3
+ run: before combine, after combine, or after reload. */
static void
-if_convert (bool after_combine)
+if_convert (ifcvt_phase phase)
{
basic_block bb;
int pass;
@@ -6902,8 +6913,8 @@ if_convert (bool after_combine)
df_live_set_all_dirty ();
}
- /* Record whether we are after combine pass. */
- ifcvt_after_combine = after_combine;
+ /* Record which pass is running for the cost model. */
+ ifcvt_pass_phase = phase;
have_cbranchcc4 = (direct_optab_handler (cbranch_optab, CCmode)
!= CODE_FOR_nothing);
num_possible_if_blocks = 0;
@@ -7006,7 +7017,7 @@ rest_of_handle_if_conversion (void)
dump_flow_info (dump_file, dump_flags);
}
cleanup_cfg (CLEANUP_EXPENSIVE);
- if_convert (false);
+ if_convert (IFCVT_BEFORE_COMBINE);
if (num_updated_if_blocks)
/* Get rid of any dead CC-related instructions. */
flags |= CLEANUP_FORCE_FAST_DCE;
@@ -7030,41 +7041,8 @@ const pass_data pass_data_rtl_ifcvt =
TODO_df_finish, /* todo_flags_finish */
};
-class pass_rtl_ifcvt : public rtl_opt_pass
-{
-public:
- pass_rtl_ifcvt (gcc::context *ctxt)
- : rtl_opt_pass (pass_data_rtl_ifcvt, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate (function *) final override
- {
- return (optimize > 0) && dbg_cnt (if_conversion);
- }
-
- unsigned int execute (function *) final override
- {
- rest_of_handle_if_conversion ();
- return 0;
- }
-
-}; // class pass_rtl_ifcvt
-
-} // anon namespace
-
-rtl_opt_pass *
-make_pass_rtl_ifcvt (gcc::context *ctxt)
-{
- return new pass_rtl_ifcvt (ctxt);
-}
-
-
-/* Rerun if-conversion, as combine may have simplified things enough
- to now meet sequence length restrictions. */
-
-namespace {
-
+/* ce2 reruns if-conversion after combine has simplified things enough to
+ meet the sequence-length restrictions. */
const pass_data pass_data_if_after_combine =
{
RTL_PASS, /* type */
@@ -7078,39 +7056,7 @@ const pass_data pass_data_if_after_combine =
TODO_df_finish, /* todo_flags_finish */
};
-class pass_if_after_combine : public rtl_opt_pass
-{
-public:
- pass_if_after_combine (gcc::context *ctxt)
- : rtl_opt_pass (pass_data_if_after_combine, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate (function *) final override
- {
- return optimize > 0 && flag_if_conversion
- && dbg_cnt (if_after_combine);
- }
-
- unsigned int execute (function *) final override
- {
- if_convert (true);
- return 0;
- }
-
-}; // class pass_if_after_combine
-
-} // anon namespace
-
-rtl_opt_pass *
-make_pass_if_after_combine (gcc::context *ctxt)
-{
- return new pass_if_after_combine (ctxt);
-}
-
-
-namespace {
-
+/* ce3 reruns if-conversion after reload. */
const pass_data pass_data_if_after_reload =
{
RTL_PASS, /* type */
@@ -7124,32 +7070,67 @@ const pass_data pass_data_if_after_reload =
TODO_df_finish, /* todo_flags_finish */
};
-class pass_if_after_reload : public rtl_opt_pass
+/* The three if-conversion passes (ce1/ce2/ce3) share this class. M_PHASE
+ selects the gate condition and the work: ce1 (before combine) also cleans
+ up the CFG and is gated only on optimize, while ce2 and ce3 rerun once
+ combine and reload have simplified the RTL. */
+
+class pass_rtl_ifcvt : public rtl_opt_pass
{
public:
- pass_if_after_reload (gcc::context *ctxt)
- : rtl_opt_pass (pass_data_if_after_reload, ctxt)
+ pass_rtl_ifcvt (gcc::context *ctxt, const pass_data &data, ifcvt_phase phase)
+ : rtl_opt_pass (data, ctxt), m_phase (phase)
{}
/* opt_pass methods: */
bool gate (function *) final override
{
- return optimize > 0 && flag_if_conversion2
- && dbg_cnt (if_after_reload);
+ if (optimize == 0)
+ return false;
+ switch (m_phase)
+ {
+ case IFCVT_BEFORE_COMBINE:
+ return dbg_cnt (if_conversion);
+ case IFCVT_AFTER_COMBINE:
+ return flag_if_conversion && dbg_cnt (if_after_combine);
+ case IFCVT_AFTER_RELOAD:
+ return flag_if_conversion2 && dbg_cnt (if_after_reload);
+ }
+ gcc_unreachable ();
}
unsigned int execute (function *) final override
{
- if_convert (true);
+ if (m_phase == IFCVT_BEFORE_COMBINE)
+ rest_of_handle_if_conversion ();
+ else
+ if_convert (m_phase);
return 0;
}
-}; // class pass_if_after_reload
+private:
+ ifcvt_phase m_phase;
+
+}; // class pass_rtl_ifcvt
} // anon namespace
+rtl_opt_pass *
+make_pass_rtl_ifcvt (gcc::context *ctxt)
+{
+ return new pass_rtl_ifcvt (ctxt, pass_data_rtl_ifcvt, IFCVT_BEFORE_COMBINE);
+}
+
+rtl_opt_pass *
+make_pass_if_after_combine (gcc::context *ctxt)
+{
+ return new pass_rtl_ifcvt (ctxt, pass_data_if_after_combine,
+ IFCVT_AFTER_COMBINE);
+}
+
rtl_opt_pass *
make_pass_if_after_reload (gcc::context *ctxt)
{
- return new pass_if_after_reload (ctxt);
+ return new pass_rtl_ifcvt (ctxt, pass_data_if_after_reload,
+ IFCVT_AFTER_RELOAD);
}
--
2.50.1 (Apple Git-155)