diff options
| author | Eduard-Mihai Burtescu <eddyb@lyken.rs> | 2021-05-06 17:37:19 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <eddyb@lyken.rs> | 2021-05-17 00:04:09 +0300 |
| commit | 402e9efc56fb21464a0cddf9aeab57c7512cf71d (patch) | |
| tree | 3a5b0eb4df206123dcfdbd1564cda65a2cda014d /compiler/rustc_codegen_ssa/src/mir | |
| parent | 7dc9ff5c629753b6930ecfe9a0446538b8e25fb7 (diff) | |
| download | rust-402e9efc56fb21464a0cddf9aeab57c7512cf71d.tar.gz rust-402e9efc56fb21464a0cddf9aeab57c7512cf71d.zip | |
rustc_codegen_ssa: only create backend `BasicBlock`s as-needed.
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/mir')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/block.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/mod.rs | 52 |
2 files changed, 41 insertions, 39 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 8f92d3e6b80..b26c7c9d51a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -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 } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index a14ae16517d..73d08b84cb8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -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 |
