about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src
diff options
context:
space:
mode:
authorDianQK <dianqk@dianqk.net>2024-02-28 22:54:37 +0800
committerDianQK <dianqk@dianqk.net>2024-03-08 08:15:18 +0800
commit2884230df2bdf6ff23d51808f5e2f270dfbe0d3a (patch)
tree768e92d484e1d7e4ff04b593d9aebf0a09f53be8 /compiler/rustc_mir_transform/src
parentb5bd98d5403c1376dadbc635ae426888320f3f9a (diff)
downloadrust-2884230df2bdf6ff23d51808f5e2f270dfbe0d3a.tar.gz
rust-2884230df2bdf6ff23d51808f5e2f270dfbe0d3a.zip
Add a workaround for the `TailDuplicator` compile time overhead
Diffstat (limited to 'compiler/rustc_mir_transform/src')
-rw-r--r--compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs29
1 files changed, 24 insertions, 5 deletions
diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
index 840a7eda27b..57fe46ad75a 100644
--- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
@@ -4,7 +4,8 @@ use crate::MirPass;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::{
-    BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind,
+    BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind,
+    TerminatorKind,
 };
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{Ty, TyCtxt};
@@ -118,9 +119,28 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
                     unreachable_targets.push(index);
                 }
             }
-
-            let replace_otherwise_to_unreachable = allowed_variants.len() <= 1
-                && !body.basic_blocks[targets.otherwise()].is_empty_unreachable();
+            let otherwise_is_empty_unreachable =
+                body.basic_blocks[targets.otherwise()].is_empty_unreachable();
+            // After resolving https://github.com/llvm/llvm-project/issues/78578,
+            // we can remove the limit on the number of successors.
+            fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool {
+                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
+            }
+            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();
 
             if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable {
                 continue;
@@ -129,7 +149,6 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
             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.is_empty();
                 if otherwise_is_last_variant {
                     #[allow(rustc::potential_query_instability)]
                     let last_variant = *allowed_variants.iter().next().unwrap();