diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 7c5d2e52360..6709c42a48f 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -11879,6 +11879,25 @@ of the if-block in the @code{struct ce_if_block} structure that is pointed to by @var{ce_info}. @end defmac +@deftypefn {Target Hook} bool TARGET_USE_LATE_PROLOGUE_EPILOGUE () +Return true if the current function's prologue and epilogue should +be emitted late in the pass pipeline, instead of at the usual point. + +Normally, the prologue and epilogue sequences are introduced soon after +register allocation is complete. The advantage of this approach is that +it allows the prologue and epilogue instructions to be optimized and +scheduled with other code in the function. However, some targets +require the prologue and epilogue to be the first and last sequences +executed by the function, with no variation allowed. This hook should +return true on such targets. + +The default implementation returns false, which is correct for most +targets. The hook should only return true if there is a specific +target limitation that cannot be described in RTL. For example, +the hook might return true if the prologue and epilogue need to switch +between instruction sets. +@end deftypefn + @deftypefn {Target Hook} void TARGET_MACHINE_DEPENDENT_REORG (void) If non-null, this hook performs a target-specific pass over the instruction stream. The compiler will run it at all optimization levels, diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index c24493add57..d1d7cfafdca 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7784,6 +7784,8 @@ of the if-block in the @code{struct ce_if_block} structure that is pointed to by @var{ce_info}. @end defmac +@hook TARGET_USE_LATE_PROLOGUE_EPILOGUE + @hook TARGET_MACHINE_DEPENDENT_REORG @hook TARGET_INIT_BUILTINS diff --git a/gcc/function.cc b/gcc/function.cc index 527ea4807b0..704930160c3 100644 --- a/gcc/function.cc +++ b/gcc/function.cc @@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see #include "function-abi.h" #include "value-range.h" #include "gimple-range.h" +#include "insn-attr.h" /* So we can assign to cfun in this file. */ #undef cfun @@ -6629,6 +6630,11 @@ public: {} /* opt_pass methods: */ + bool gate (function *) final override + { + return !targetm.use_late_prologue_epilogue (); + } + unsigned int execute (function * fun) final override { rest_of_handle_thread_prologue_and_epilogue (fun); @@ -6637,6 +6643,44 @@ public: }; // class pass_thread_prologue_and_epilogue +const pass_data pass_data_late_thread_prologue_and_epilogue = +{ + RTL_PASS, /* type */ + "late_pro_and_epilogue", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_THREAD_PROLOGUE_AND_EPILOGUE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + ( TODO_df_verify | TODO_df_finish ), /* todo_flags_finish */ +}; + +class pass_late_thread_prologue_and_epilogue : public rtl_opt_pass +{ +public: + pass_late_thread_prologue_and_epilogue (gcc::context *ctxt) + : rtl_opt_pass (pass_data_late_thread_prologue_and_epilogue, ctxt) + {} + + /* opt_pass methods: */ + bool gate (function *) final override + { + return targetm.use_late_prologue_epilogue (); + } + + unsigned int execute (function *fn) final override + { + /* It's not currently possible to have both delay slots and + late prologue/epilogue, since the latter has to run before + the former, and the former won't honor whatever restrictions + the latter is trying to enforce. */ + gcc_assert (!DELAY_SLOTS); + rest_of_handle_thread_prologue_and_epilogue (fn); + return 0; + } +}; // class pass_late_thread_prologue_and_epilogue + } // anon namespace rtl_opt_pass * @@ -6645,6 +6689,12 @@ make_pass_thread_prologue_and_epilogue (gcc::context *ctxt) return new pass_thread_prologue_and_epilogue (ctxt); } +rtl_opt_pass * +make_pass_late_thread_prologue_and_epilogue (gcc::context *ctxt) +{ + return new pass_late_thread_prologue_and_epilogue (ctxt); +} + namespace { const pass_data pass_data_zero_call_used_regs = diff --git a/gcc/passes.def b/gcc/passes.def index 1e1950bdb39..f3139415065 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -533,6 +533,9 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_stack_regs_run); POP_INSERT_PASSES () POP_INSERT_PASSES () + NEXT_PASS (pass_late_thread_prologue_and_epilogue); + /* No target-independent code motion is allowed beyond this point, + excepting the legacy delayed-branch pass. */ NEXT_PASS (pass_late_compilation); PUSH_INSERT_PASSES_WITHIN (pass_late_compilation) NEXT_PASS (pass_zero_call_used_regs); diff --git a/gcc/target.def b/gcc/target.def index c6562ed40ac..04715028460 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4153,6 +4153,27 @@ returns @code{VOIDmode}.", machine_mode, (machine_mode m1, machine_mode m2), default_cc_modes_compatible) +DEFHOOK +(use_late_prologue_epilogue, + "Return true if the current function's prologue and epilogue should\n\ +be emitted late in the pass pipeline, instead of at the usual point.\n\ +\n\ +Normally, the prologue and epilogue sequences are introduced soon after\n\ +register allocation is complete. The advantage of this approach is that\n\ +it allows the prologue and epilogue instructions to be optimized and\n\ +scheduled with other code in the function. However, some targets\n\ +require the prologue and epilogue to be the first and last sequences\n\ +executed by the function, with no variation allowed. This hook should\n\ +return true on such targets.\n\ +\n\ +The default implementation returns false, which is correct for most\n\ +targets. The hook should only return true if there is a specific\n\ +target limitation that cannot be described in RTL. For example,\n\ +the hook might return true if the prologue and epilogue need to switch\n\ +between instruction sets.", + bool, (), + hook_bool_void_false) + /* Do machine-dependent code transformations. Called just before delayed-branch scheduling. */ DEFHOOK diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 09e6ada5b2f..4e89dd1aaac 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -616,6 +616,8 @@ extern rtl_opt_pass *make_pass_gcse2 (gcc::context *ctxt); extern rtl_opt_pass *make_pass_split_after_reload (gcc::context *ctxt); extern rtl_opt_pass *make_pass_thread_prologue_and_epilogue (gcc::context *ctxt); +extern rtl_opt_pass *make_pass_late_thread_prologue_and_epilogue (gcc::context + *ctxt); extern rtl_opt_pass *make_pass_zero_call_used_regs (gcc::context *ctxt); extern rtl_opt_pass *make_pass_stack_adjustments (gcc::context *ctxt); extern rtl_opt_pass *make_pass_sched_fusion (gcc::context *ctxt);