rustc_codegen_ssa: only create backend BasicBlock
s as-needed.
This commit is contained in:
parent
7dc9ff5c62
commit
402e9efc56
7 changed files with 50 additions and 51 deletions
|
@ -68,7 +68,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
target: mir::BasicBlock,
|
||||
) -> (Bx::BasicBlock, bool) {
|
||||
let span = self.terminator.source_info.span;
|
||||
let lltarget = fx.blocks[target];
|
||||
let lltarget = fx.llbb(target);
|
||||
let target_funclet = fx.cleanup_kinds[target].funclet_bb(target);
|
||||
match (self.funclet_bb, target_funclet) {
|
||||
(None, None) => (lltarget, false),
|
||||
|
@ -133,13 +133,13 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
// If there is a cleanup block and the function we're calling can unwind, then
|
||||
// do an invoke, otherwise do a call.
|
||||
if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
|
||||
let ret_bx = if let Some((_, target)) = destination {
|
||||
fx.blocks[target]
|
||||
let ret_llbb = if let Some((_, target)) = destination {
|
||||
fx.llbb(target)
|
||||
} else {
|
||||
fx.unreachable_block()
|
||||
};
|
||||
let invokeret =
|
||||
bx.invoke(fn_ptr, &llargs, ret_bx, self.llblock(fx, cleanup), self.funclet(fx));
|
||||
bx.invoke(fn_ptr, &llargs, ret_llbb, self.llblock(fx, cleanup), self.funclet(fx));
|
||||
bx.apply_attrs_callsite(&fn_abi, invokeret);
|
||||
|
||||
if let Some((ret_dest, target)) = destination {
|
||||
|
@ -1205,7 +1205,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
// FIXME(eddyb) rename this to `eh_pad_for_uncached`.
|
||||
fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
|
||||
let llbb = self.blocks[bb];
|
||||
let llbb = self.llbb(bb);
|
||||
if base::wants_msvc_seh(self.cx.sess()) {
|
||||
let funclet;
|
||||
let ret_llbb;
|
||||
|
@ -1293,9 +1293,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
Bx::new_block(self.cx, self.llfn, name)
|
||||
}
|
||||
|
||||
pub fn build_block(&self, bb: mir::BasicBlock) -> Bx {
|
||||
/// Get the backend `BasicBlock` for a MIR `BasicBlock`, either already
|
||||
/// cached in `self.cached_llbbs`, or created on demand (and cached).
|
||||
// FIXME(eddyb) rename `llbb` and other `ll`-prefixed things to use a
|
||||
// more backend-agnostic prefix such as `cg` (i.e. this would be `cgbb`).
|
||||
pub fn llbb(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
|
||||
self.cached_llbbs[bb].unwrap_or_else(|| {
|
||||
// FIXME(eddyb) only name the block if `fewer_names` is `false`.
|
||||
// FIXME(eddyb) create the block directly, without a builder.
|
||||
let llbb = self.new_block(&format!("{:?}", bb)).llbb();
|
||||
self.cached_llbbs[bb] = Some(llbb);
|
||||
llbb
|
||||
})
|
||||
}
|
||||
|
||||
pub fn build_block(&mut self, bb: mir::BasicBlock) -> Bx {
|
||||
let mut bx = Bx::with_cx(self.cx);
|
||||
bx.position_at_end(self.blocks[bb]);
|
||||
bx.position_at_end(self.llbb(bb));
|
||||
bx
|
||||
}
|
||||
|
||||
|
|
|
@ -40,8 +40,11 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
|||
/// then later loaded when generating the DIVERGE_BLOCK.
|
||||
personality_slot: Option<PlaceRef<'tcx, Bx::Value>>,
|
||||
|
||||
/// A `Block` for each MIR `BasicBlock`
|
||||
blocks: IndexVec<mir::BasicBlock, Bx::BasicBlock>,
|
||||
/// A backend `BasicBlock` for each MIR `BasicBlock`, created lazily
|
||||
/// as-needed (e.g. RPO reaching it or another block branching to it).
|
||||
// FIXME(eddyb) rename `llbbs` and other `ll`-prefixed things to use a
|
||||
// more backend-agnostic prefix such as `cg` (i.e. this would be `cgbbs`).
|
||||
cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>,
|
||||
|
||||
/// The funclet status of each basic block
|
||||
cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>,
|
||||
|
@ -151,17 +154,17 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
// Allocate a `Block` for every basic block, except
|
||||
// the start block, if nothing loops back to it.
|
||||
let reentrant_start_block = !mir.predecessors()[mir::START_BLOCK].is_empty();
|
||||
let block_bxs: IndexVec<mir::BasicBlock, Bx::BasicBlock> = mir
|
||||
.basic_blocks()
|
||||
.indices()
|
||||
.map(|bb| {
|
||||
if bb == mir::START_BLOCK && !reentrant_start_block {
|
||||
bx.llbb()
|
||||
} else {
|
||||
bx.build_sibling_block(&format!("{:?}", bb)).llbb()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> =
|
||||
mir.basic_blocks()
|
||||
.indices()
|
||||
.map(|bb| {
|
||||
if bb == mir::START_BLOCK && !reentrant_start_block {
|
||||
Some(bx.llbb())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut fx = FunctionCx {
|
||||
instance,
|
||||
|
@ -170,7 +173,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
fn_abi,
|
||||
cx,
|
||||
personality_slot: None,
|
||||
blocks: block_bxs,
|
||||
cached_llbbs,
|
||||
unreachable_block: None,
|
||||
cleanup_kinds,
|
||||
landing_pads: IndexVec::from_elem(None, mir.basic_blocks()),
|
||||
|
@ -245,29 +248,14 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
// Branch to the START block, if it's not the entry block.
|
||||
if reentrant_start_block {
|
||||
bx.br(fx.blocks[mir::START_BLOCK]);
|
||||
bx.br(fx.llbb(mir::START_BLOCK));
|
||||
}
|
||||
|
||||
let rpo = traversal::reverse_postorder(&mir);
|
||||
let mut visited = BitSet::new_empty(mir.basic_blocks().len());
|
||||
|
||||
// Codegen the body of each block using reverse postorder
|
||||
for (bb, _) in rpo {
|
||||
visited.insert(bb.index());
|
||||
// FIXME(eddyb) reuse RPO iterator between `analysis` and this.
|
||||
for (bb, _) in traversal::reverse_postorder(&mir) {
|
||||
fx.codegen_block(bb);
|
||||
}
|
||||
|
||||
// Remove blocks that haven't been visited, or have no
|
||||
// predecessors.
|
||||
for bb in mir.basic_blocks().indices() {
|
||||
// Unreachable block
|
||||
if !visited.contains(bb.index()) {
|
||||
debug!("codegen_mir: block {:?} was not visited", bb);
|
||||
unsafe {
|
||||
bx.delete_basic_block(fx.blocks[bb]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Produces, for each argument, a `Value` pointing at the
|
||||
|
|
|
@ -291,6 +291,5 @@ pub trait BuilderMethods<'a, 'tcx>:
|
|||
) -> Self::Value;
|
||||
fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
|
||||
|
||||
unsafe fn delete_basic_block(&mut self, bb: Self::BasicBlock);
|
||||
fn do_not_inline(&mut self, llret: Self::Value);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue