Merge basic blocks where possible when generating LLVM IR.
In `codegen_assert_terminator` we decide if a BB's successor is a candidate for merging, which requires that it be the only successor, and that it only have one predecessor. That result then gets passed down, and if it reaches `funclet_br` with the appropriate BB characteristics, then no `br` instruction is issued, a `MergingSucc::True` result is passed back, and the merging proceeds in `codegen_block`. The commit also adds `CachedLlbb`, a new type to help keep track of each BB that has been merged into its predecessor.
This commit is contained in:
parent
68194aa8d5
commit
54082dd216
4 changed files with 261 additions and 144 deletions
|
@ -16,6 +16,18 @@ use rustc_middle::mir::traversal;
|
|||
|
||||
use self::operand::{OperandRef, OperandValue};
|
||||
|
||||
// Used for tracking the state of generated basic blocks.
|
||||
enum CachedLlbb<T> {
|
||||
/// Nothing created yet.
|
||||
None,
|
||||
|
||||
/// Has been created.
|
||||
Some(T),
|
||||
|
||||
/// Nothing created yet, and nothing should be.
|
||||
Skip,
|
||||
}
|
||||
|
||||
/// Master context for codegenning from MIR.
|
||||
pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
||||
instance: Instance<'tcx>,
|
||||
|
@ -43,7 +55,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
|||
/// 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>>,
|
||||
cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>>,
|
||||
|
||||
/// The funclet status of each basic block
|
||||
cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>,
|
||||
|
@ -155,11 +167,13 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
}
|
||||
|
||||
let cleanup_kinds = analyze::cleanup_kinds(&mir);
|
||||
let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> = mir
|
||||
.basic_blocks
|
||||
.indices()
|
||||
.map(|bb| if bb == mir::START_BLOCK { Some(start_llbb) } else { None })
|
||||
.collect();
|
||||
let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> =
|
||||
mir.basic_blocks
|
||||
.indices()
|
||||
.map(|bb| {
|
||||
if bb == mir::START_BLOCK { CachedLlbb::Some(start_llbb) } else { CachedLlbb::None }
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut fx = FunctionCx {
|
||||
instance,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue