Auto merge of #106959 - tmiasko:opt-funclets, r=davidtwco
Omit needless funclet partitioning
This commit is contained in:
commit
db137ba7d4
@ -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
|
||||||
|
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user