mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Revert "Add a workaround for the TailDuplicator compile time overhead"
This reverts commit 2884230df2.
This commit is contained in:
@@ -4,8 +4,7 @@
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::{
|
||||
BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind,
|
||||
TerminatorKind,
|
||||
BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
@@ -125,43 +124,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
unreachable_targets.push(index);
|
||||
}
|
||||
}
|
||||
let otherwise_is_empty_unreachable =
|
||||
body.basic_blocks[targets.otherwise()].is_empty_unreachable();
|
||||
fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool {
|
||||
// After resolving https://github.com/llvm/llvm-project/issues/78578,
|
||||
// We can remove this check.
|
||||
// The main issue here is that `early-tailduplication` causes compile time overhead
|
||||
// and potential performance problems.
|
||||
// Simply put, when encounter a switch (indirect branch) statement,
|
||||
// `early-tailduplication` tries to duplicate the switch branch statement with BB
|
||||
// into (each) predecessors. This makes CFG very complex.
|
||||
// We can understand it as it transforms the following code
|
||||
// ```rust
|
||||
// match a { ... many cases };
|
||||
// match b { ... many cases };
|
||||
// ```
|
||||
// into
|
||||
// ```rust
|
||||
// match a { ... many match b { goto BB cases } }
|
||||
// ... BB cases
|
||||
// ```
|
||||
// Abandon this transformation when it is possible (the best effort)
|
||||
// to encounter the problem.
|
||||
let mut successors = basic_blocks[bb].terminator().successors();
|
||||
let Some(first_successor) = successors.next() else { return true };
|
||||
if successors.next().is_some() {
|
||||
return true;
|
||||
}
|
||||
if let TerminatorKind::SwitchInt { .. } =
|
||||
&basic_blocks[first_successor].terminator().kind
|
||||
{
|
||||
return false;
|
||||
};
|
||||
true
|
||||
}
|
||||
|
||||
// If and only if there is a variant that does not have a branch set, change the
|
||||
// current of otherwise as the variant branch and set otherwise to unreachable. It
|
||||
// transforms following code
|
||||
// transforms the following code
|
||||
// ```rust
|
||||
// match c {
|
||||
// Ordering::Less => 1,
|
||||
@@ -177,12 +143,8 @@ fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool {
|
||||
// Ordering::Greater => 3,
|
||||
// }
|
||||
// ```
|
||||
let otherwise_is_last_variant = !otherwise_is_empty_unreachable
|
||||
&& allowed_variants.len() == 1
|
||||
&& check_successors(&body.basic_blocks, targets.otherwise());
|
||||
let replace_otherwise_to_unreachable = otherwise_is_last_variant
|
||||
|| (!otherwise_is_empty_unreachable && allowed_variants.is_empty());
|
||||
|
||||
let replace_otherwise_to_unreachable = allowed_variants.len() <= 1
|
||||
&& !body.basic_blocks[targets.otherwise()].is_empty_unreachable();
|
||||
if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable {
|
||||
continue;
|
||||
}
|
||||
@@ -190,6 +152,7 @@ fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool {
|
||||
let unreachable_block = patch.unreachable_no_cleanup_block();
|
||||
let mut targets = targets.clone();
|
||||
if replace_otherwise_to_unreachable {
|
||||
let otherwise_is_last_variant = allowed_variants.len() == 1;
|
||||
if otherwise_is_last_variant {
|
||||
// We have checked that `allowed_variants` has only one element.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
|
||||
Reference in New Issue
Block a user