cache the terminate block with the last reason that we saw

This commit is contained in:
Ralf Jung 2023-08-22 13:57:09 +02:00
parent ddea3f981e
commit 114fde6ac7
3 changed files with 16 additions and 21 deletions

View File

@ -1581,8 +1581,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock { fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock {
if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup { if let Some((cached_bb, cached_reason)) = self.terminate_block && reason == cached_reason {
return bb; return cached_bb;
} }
let funclet; let funclet;
@ -1653,9 +1653,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.unreachable(); bx.unreachable();
if reason == UnwindTerminateReason::InCleanup { self.terminate_block = Some((llbb, reason));
self.terminate_in_cleanup_block = Some(llbb);
}
llbb llbb
} }

View File

@ -5,6 +5,7 @@ use rustc_index::IndexVec;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::mir::traversal; use rustc_middle::mir::traversal;
use rustc_middle::mir::UnwindTerminateReason;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_target::abi::call::{FnAbi, PassMode}; use rustc_target::abi::call::{FnAbi, PassMode};
@ -83,8 +84,8 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
/// Cached unreachable block /// Cached unreachable block
unreachable_block: Option<Bx::BasicBlock>, unreachable_block: Option<Bx::BasicBlock>,
/// Cached terminate upon unwinding (reason: InCleanup) block /// Cached terminate upon unwinding block and its reason
terminate_in_cleanup_block: Option<Bx::BasicBlock>, terminate_block: Option<(Bx::BasicBlock, UnwindTerminateReason)>,
/// The location where each MIR arg/var/tmp/ret is stored. This is /// The location where each MIR arg/var/tmp/ret is stored. This is
/// usually an `PlaceRef` representing an alloca, but not always: /// usually an `PlaceRef` representing an alloca, but not always:
@ -199,7 +200,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
personality_slot: None, personality_slot: None,
cached_llbbs, cached_llbbs,
unreachable_block: None, unreachable_block: None,
terminate_in_cleanup_block: None, terminate_block: None,
cleanup_kinds, cleanup_kinds,
landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), landing_pads: IndexVec::from_elem(None, &mir.basic_blocks),
funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()),

View File

@ -14,8 +14,8 @@ pub struct MirPatch<'tcx> {
resume_block: Option<BasicBlock>, resume_block: Option<BasicBlock>,
// Only for unreachable in cleanup path. // Only for unreachable in cleanup path.
unreachable_cleanup_block: Option<BasicBlock>, unreachable_cleanup_block: Option<BasicBlock>,
// Cached block for UnwindTerminate(InCleanup) // Cached block for UnwindTerminate (with reason)
terminate_in_cleanup_block: Option<BasicBlock>, terminate_block: Option<(BasicBlock, UnwindTerminateReason)>,
body_span: Span, body_span: Span,
next_local: usize, next_local: usize,
} }
@ -30,7 +30,7 @@ impl<'tcx> MirPatch<'tcx> {
next_local: body.local_decls.len(), next_local: body.local_decls.len(),
resume_block: None, resume_block: None,
unreachable_cleanup_block: None, unreachable_cleanup_block: None,
terminate_in_cleanup_block: None, terminate_block: None,
body_span: body.span, body_span: body.span,
}; };
@ -53,12 +53,10 @@ impl<'tcx> MirPatch<'tcx> {
} }
// Check if we already have a terminate block // Check if we already have a terminate block
if matches!( if let TerminatorKind::UnwindTerminate(reason) = block.terminator().kind
block.terminator().kind, && block.statements.is_empty()
TerminatorKind::UnwindTerminate(UnwindTerminateReason::InCleanup)
) && block.statements.is_empty()
{ {
result.terminate_in_cleanup_block = Some(bb); result.terminate_block = Some((bb, reason));
continue; continue;
} }
} }
@ -101,8 +99,8 @@ impl<'tcx> MirPatch<'tcx> {
} }
pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock { pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock {
if let Some(bb) = self.terminate_in_cleanup_block && reason == UnwindTerminateReason::InCleanup { if let Some((cached_bb, cached_reason)) = self.terminate_block && reason == cached_reason {
return bb; return cached_bb;
} }
let bb = self.new_block(BasicBlockData { let bb = self.new_block(BasicBlockData {
@ -113,9 +111,7 @@ impl<'tcx> MirPatch<'tcx> {
}), }),
is_cleanup: true, is_cleanup: true,
}); });
if reason == UnwindTerminateReason::InCleanup { self.terminate_block = Some((bb, reason));
self.terminate_in_cleanup_block = Some(bb);
}
bb bb
} }