Omit needless funclet partitioning

This commit is contained in:
Tomasz Miąsko 2023-01-17 00:00:00 +00:00
parent 4781233a77
commit cd92bca49d
2 changed files with 40 additions and 43 deletions

View File

@ -39,7 +39,6 @@ enum MergingSucc {
struct TerminatorCodegenHelper<'tcx> { struct TerminatorCodegenHelper<'tcx> {
bb: mir::BasicBlock, bb: mir::BasicBlock,
terminator: &'tcx mir::Terminator<'tcx>, terminator: &'tcx mir::Terminator<'tcx>,
funclet_bb: Option<mir::BasicBlock>,
} }
impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
@ -49,28 +48,24 @@ fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>(
&self, &self,
fx: &'b mut FunctionCx<'a, 'tcx, Bx>, fx: &'b mut FunctionCx<'a, 'tcx, Bx>,
) -> Option<&'b Bx::Funclet> { ) -> Option<&'b Bx::Funclet> {
let funclet_bb = self.funclet_bb?; let cleanup_kinds = (&fx.cleanup_kinds).as_ref()?;
if base::wants_msvc_seh(fx.cx.tcx().sess) { let funclet_bb = cleanup_kinds[self.bb].funclet_bb(self.bb)?;
// If `landing_pad_for` hasn't been called yet to create the `Funclet`, // If `landing_pad_for` hasn't been called yet to create the `Funclet`,
// it has to be now. This may not seem necessary, as RPO should lead // it has to be now. This may not seem necessary, as RPO should lead
// to all the unwind edges being visited (and so to `landing_pad_for` // to all the unwind edges being visited (and so to `landing_pad_for`
// getting called for them), before building any of the blocks inside // getting called for them), before building any of the blocks inside
// the funclet itself - however, if MIR contains edges that end up not // the funclet itself - however, if MIR contains edges that end up not
// being needed in the LLVM IR after monomorphization, the funclet may // being needed in the LLVM IR after monomorphization, the funclet may
// be unreachable, and we don't have yet a way to skip building it in // be unreachable, and we don't have yet a way to skip building it in
// such an eventuality (which may be a better solution than this). // such an eventuality (which may be a better solution than this).
if fx.funclets[funclet_bb].is_none() { if fx.funclets[funclet_bb].is_none() {
fx.landing_pad_for(funclet_bb); fx.landing_pad_for(funclet_bb);
}
Some(
fx.funclets[funclet_bb]
.as_ref()
.expect("landing_pad_for didn't also create funclets entry"),
)
} else {
None
} }
Some(
fx.funclets[funclet_bb]
.as_ref()
.expect("landing_pad_for didn't also create funclets entry"),
)
} }
/// Get a basic block (creating it if necessary), possibly with cleanup /// Get a basic block (creating it if necessary), possibly with cleanup
@ -104,23 +99,24 @@ fn llbb_characteristics<Bx: BuilderMethods<'a, 'tcx>>(
fx: &mut FunctionCx<'a, 'tcx, Bx>, fx: &mut FunctionCx<'a, 'tcx, Bx>,
target: mir::BasicBlock, target: mir::BasicBlock,
) -> (bool, bool) { ) -> (bool, bool) {
let target_funclet = fx.cleanup_kinds[target].funclet_bb(target); if let Some(ref cleanup_kinds) = fx.cleanup_kinds {
let (needs_landing_pad, is_cleanupret) = match (self.funclet_bb, target_funclet) { let funclet_bb = cleanup_kinds[self.bb].funclet_bb(self.bb);
(None, None) => (false, false), let target_funclet = cleanup_kinds[target].funclet_bb(target);
(None, Some(_)) => (true, false), let (needs_landing_pad, is_cleanupret) = match (funclet_bb, target_funclet) {
(Some(_), None) => { (None, None) => (false, false),
let span = self.terminator.source_info.span; (None, Some(_)) => (true, false),
span_bug!(span, "{:?} - jump out of cleanup?", self.terminator); (Some(f), Some(t_f)) => (f != t_f, f != t_f),
} (Some(_), None) => {
(Some(f), Some(t_f)) => { let span = self.terminator.source_info.span;
if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) { span_bug!(span, "{:?} - jump out of cleanup?", self.terminator);
(false, false)
} else {
(true, true)
} }
} };
}; (needs_landing_pad, is_cleanupret)
(needs_landing_pad, is_cleanupret) } else {
let needs_landing_pad = !fx.mir[self.bb].is_cleanup && fx.mir[target].is_cleanup;
let is_cleanupret = false;
(needs_landing_pad, is_cleanupret)
}
} }
fn funclet_br<Bx: BuilderMethods<'a, 'tcx>>( fn funclet_br<Bx: BuilderMethods<'a, 'tcx>>(
@ -1253,9 +1249,7 @@ fn codegen_terminator(
) -> MergingSucc { ) -> MergingSucc {
debug!("codegen_terminator: {:?}", terminator); debug!("codegen_terminator: {:?}", terminator);
// Create the cleanup bundle, if needed. let helper = TerminatorCodegenHelper { bb, terminator };
let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb);
let helper = TerminatorCodegenHelper { bb, terminator, funclet_bb };
let mergeable_succ = || { let mergeable_succ = || {
// Note: any call to `switch_to_block` will invalidate a `true` value // Note: any call to `switch_to_block` will invalidate a `true` value

View File

@ -1,3 +1,4 @@
use crate::base;
use crate::traits::*; use crate::traits::*;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
@ -58,7 +59,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>>, cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>>,
/// The funclet status of each basic block /// The funclet status of each basic block
cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>, cleanup_kinds: Option<IndexVec<mir::BasicBlock, analyze::CleanupKind>>,
/// When targeting MSVC, this stores the cleanup info for each funclet BB. /// When targeting MSVC, this stores the cleanup info for each funclet BB.
/// This is initialized at the same time as the `landing_pads` entry for the /// This is initialized at the same time as the `landing_pads` entry for the
@ -166,7 +167,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
start_bx.set_personality_fn(cx.eh_personality()); start_bx.set_personality_fn(cx.eh_personality());
} }
let cleanup_kinds = analyze::cleanup_kinds(&mir); let cleanup_kinds =
if base::wants_msvc_seh(cx.tcx().sess) { Some(analyze::cleanup_kinds(&mir)) } else { None };
let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> = let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> =
mir.basic_blocks mir.basic_blocks
.indices() .indices()