1
Fork 0

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:
Nicholas Nethercote 2022-10-17 08:29:40 +11:00
parent 68194aa8d5
commit 54082dd216
4 changed files with 261 additions and 144 deletions

View file

@ -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,