about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-02-09 18:57:22 +0000
committerMichael Goulet <michael@errs.io>2025-02-09 18:58:14 +0000
commita6dcfe3af43dce6762d0569e0effe1a9d8719d07 (patch)
treedf4c67915220b752d897287a05f384c8d1c58c5a
parenta26e97be8826d408309fffbd8168362365719f50 (diff)
downloadrust-a6dcfe3af43dce6762d0569e0effe1a9d8719d07.tar.gz
rust-a6dcfe3af43dce6762d0569e0effe1a9d8719d07.zip
Remove the deduplicate_blocks pass
-rw-r--r--compiler/rustc_mir_transform/src/deduplicate_blocks.rs195
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff100
-rw-r--r--tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff100
-rw-r--r--tests/mir-opt/deduplicate_blocks.rs17
5 files changed, 0 insertions, 414 deletions
diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
deleted file mode 100644
index 63257df66fb..00000000000
--- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
+++ /dev/null
@@ -1,195 +0,0 @@
-//! This pass finds basic blocks that are completely equal,
-//! and replaces all uses with just one of them.
-
-use std::collections::hash_map::Entry;
-use std::hash::{Hash, Hasher};
-use std::iter;
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_middle::mir::visit::MutVisitor;
-use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
-use tracing::debug;
-
-use super::simplify::simplify_cfg;
-
-pub(super) struct DeduplicateBlocks;
-
-impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks {
-    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.mir_opt_level() >= 4
-    }
-
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        debug!("Running DeduplicateBlocks on `{:?}`", body.source);
-        let duplicates = find_duplicates(body);
-        let has_opts_to_apply = !duplicates.is_empty();
-
-        if has_opts_to_apply {
-            let mut opt_applier = OptApplier { tcx, duplicates };
-            opt_applier.visit_body(body);
-            simplify_cfg(body);
-        }
-    }
-
-    fn is_required(&self) -> bool {
-        false
-    }
-}
-
-struct OptApplier<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    duplicates: FxHashMap<BasicBlock, BasicBlock>,
-}
-
-impl<'tcx> MutVisitor<'tcx> for OptApplier<'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
-        for target in terminator.successors_mut() {
-            if let Some(replacement) = self.duplicates.get(target) {
-                debug!("SUCCESS: Replacing: `{:?}` with `{:?}`", target, replacement);
-                *target = *replacement;
-            }
-        }
-
-        self.super_terminator(terminator, location);
-    }
-}
-
-fn find_duplicates(body: &Body<'_>) -> FxHashMap<BasicBlock, BasicBlock> {
-    let mut duplicates = FxHashMap::default();
-
-    let bbs_to_go_through =
-        body.basic_blocks.iter_enumerated().filter(|(_, bbd)| !bbd.is_cleanup).count();
-
-    let mut same_hashes =
-        FxHashMap::with_capacity_and_hasher(bbs_to_go_through, Default::default());
-
-    // Go through the basic blocks backwards. This means that in case of duplicates,
-    // we can use the basic block with the highest index as the replacement for all lower ones.
-    // For example, if bb1, bb2 and bb3 are duplicates, we will first insert bb3 in same_hashes.
-    // Then we will see that bb2 is a duplicate of bb3,
-    // and insert bb2 with the replacement bb3 in the duplicates list.
-    // When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the
-    // duplicates list with replacement bb3.
-    // When the duplicates are removed, we will end up with only bb3.
-    for (bb, bbd) in body.basic_blocks.iter_enumerated().rev().filter(|(_, bbd)| !bbd.is_cleanup) {
-        // Basic blocks can get really big, so to avoid checking for duplicates in basic blocks
-        // that are unlikely to have duplicates, we stop early. The early bail number has been
-        // found experimentally by eprintln while compiling the crates in the rustc-perf suite.
-        if bbd.statements.len() > 10 {
-            continue;
-        }
-
-        let to_hash = BasicBlockHashable { basic_block_data: bbd };
-        let entry = same_hashes.entry(to_hash);
-        match entry {
-            Entry::Occupied(occupied) => {
-                // The basic block was already in the hashmap, which means we have a duplicate
-                let value = *occupied.get();
-                debug!("Inserting {:?} -> {:?}", bb, value);
-                duplicates.try_insert(bb, value).expect("key was already inserted");
-            }
-            Entry::Vacant(vacant) => {
-                vacant.insert(bb);
-            }
-        }
-    }
-
-    duplicates
-}
-
-struct BasicBlockHashable<'a, 'tcx> {
-    basic_block_data: &'a BasicBlockData<'tcx>,
-}
-
-impl Hash for BasicBlockHashable<'_, '_> {
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        hash_statements(state, self.basic_block_data.statements.iter());
-        // Note that since we only hash the kind, we lose span information if we deduplicate the
-        // blocks.
-        self.basic_block_data.terminator().kind.hash(state);
-    }
-}
-
-impl Eq for BasicBlockHashable<'_, '_> {}
-
-impl PartialEq for BasicBlockHashable<'_, '_> {
-    fn eq(&self, other: &Self) -> bool {
-        self.basic_block_data.statements.len() == other.basic_block_data.statements.len()
-            && &self.basic_block_data.terminator().kind == &other.basic_block_data.terminator().kind
-            && iter::zip(&self.basic_block_data.statements, &other.basic_block_data.statements)
-                .all(|(x, y)| statement_eq(&x.kind, &y.kind))
-    }
-}
-
-fn hash_statements<'a, 'tcx, H: Hasher>(
-    hasher: &mut H,
-    iter: impl Iterator<Item = &'a Statement<'tcx>>,
-) where
-    'tcx: 'a,
-{
-    for stmt in iter {
-        statement_hash(hasher, &stmt.kind);
-    }
-}
-
-fn statement_hash<H: Hasher>(hasher: &mut H, stmt: &StatementKind<'_>) {
-    match stmt {
-        StatementKind::Assign(box (place, rvalue)) => {
-            place.hash(hasher);
-            rvalue_hash(hasher, rvalue)
-        }
-        x => x.hash(hasher),
-    };
-}
-
-fn rvalue_hash<H: Hasher>(hasher: &mut H, rvalue: &Rvalue<'_>) {
-    match rvalue {
-        Rvalue::Use(op) => operand_hash(hasher, op),
-        x => x.hash(hasher),
-    };
-}
-
-fn operand_hash<H: Hasher>(hasher: &mut H, operand: &Operand<'_>) {
-    match operand {
-        Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }) => const_.hash(hasher),
-        x => x.hash(hasher),
-    };
-}
-
-fn statement_eq<'tcx>(lhs: &StatementKind<'tcx>, rhs: &StatementKind<'tcx>) -> bool {
-    let res = match (lhs, rhs) {
-        (
-            StatementKind::Assign(box (place, rvalue)),
-            StatementKind::Assign(box (place2, rvalue2)),
-        ) => place == place2 && rvalue_eq(rvalue, rvalue2),
-        (x, y) => x == y,
-    };
-    debug!("statement_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res);
-    res
-}
-
-fn rvalue_eq<'tcx>(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool {
-    let res = match (lhs, rhs) {
-        (Rvalue::Use(op1), Rvalue::Use(op2)) => operand_eq(op1, op2),
-        (x, y) => x == y,
-    };
-    debug!("rvalue_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res);
-    res
-}
-
-fn operand_eq<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool {
-    let res = match (lhs, rhs) {
-        (
-            Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }),
-            Operand::Constant(box ConstOperand { user_ty: _, const_: const2, span: _ }),
-        ) => const_ == const2,
-        (x, y) => x == y,
-    };
-    debug!("operand_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res);
-    res
-}
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index b572f6ca0b3..397d21a857f 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -135,7 +135,6 @@ declare_passes! {
         Initial,
         Final
     };
-    mod deduplicate_blocks : DeduplicateBlocks;
     mod deref_separator : Derefer;
     mod dest_prop : DestinationPropagation;
     pub mod dump_mir : Marker;
@@ -700,7 +699,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &nrvo::RenameReturnPlace,
             &simplify::SimplifyLocals::Final,
             &multiple_return_terminators::MultipleReturnTerminators,
-            &deduplicate_blocks::DeduplicateBlocks,
             &large_enums::EnumSizeOpt { discrepancy: 128 },
             // Some cleanup necessary at least for LLVM and potentially other codegen backends.
             &add_call_guards::CriticalCallEdges,
diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff
deleted file mode 100644
index 60742ef0e9a..00000000000
--- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff
+++ /dev/null
@@ -1,100 +0,0 @@
-- // MIR for `is_line_doc_comment_2` before DeduplicateBlocks
-+ // MIR for `is_line_doc_comment_2` after DeduplicateBlocks
-  
-  fn is_line_doc_comment_2(_1: &str) -> bool {
-      debug s => _1;
-      let mut _0: bool;
-      let mut _2: &[u8];
-      let mut _3: &str;
-      let mut _4: usize;
-      let mut _5: usize;
-      let mut _6: bool;
-      let mut _7: usize;
-      let mut _8: usize;
-      let mut _9: bool;
-  
-      bb0: {
-          StorageLive(_2);
-          StorageLive(_3);
-          _3 = &(*_1);
-          _2 = core::str::<impl str>::as_bytes(move _3) -> [return: bb1, unwind unreachable];
-      }
-  
-      bb1: {
-          StorageDead(_3);
-          _4 = Len((*_2));
-          _5 = const 4_usize;
-          _6 = Ge(move _4, move _5);
-          switchInt(move _6) -> [0: bb2, otherwise: bb3];
-      }
-  
-      bb2: {
-          _7 = Len((*_2));
-          _8 = const 3_usize;
-          _9 = Ge(move _7, move _8);
--         switchInt(move _9) -> [0: bb7, otherwise: bb8];
-+         switchInt(move _9) -> [0: bb11, otherwise: bb7];
-      }
-  
-      bb3: {
-          switchInt(copy (*_2)[0 of 4]) -> [47: bb4, otherwise: bb2];
-      }
-  
-      bb4: {
-          switchInt(copy (*_2)[1 of 4]) -> [47: bb5, otherwise: bb2];
-      }
-  
-      bb5: {
-          switchInt(copy (*_2)[2 of 4]) -> [47: bb6, otherwise: bb2];
-      }
-  
-      bb6: {
--         switchInt(copy (*_2)[3 of 4]) -> [47: bb13, otherwise: bb2];
-+         switchInt(copy (*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
-      }
-  
-      bb7: {
--         _0 = const false;
--         goto -> bb14;
-+         switchInt(copy (*_2)[0 of 3]) -> [47: bb8, otherwise: bb11];
-      }
-  
-      bb8: {
--         switchInt(copy (*_2)[0 of 3]) -> [47: bb9, otherwise: bb7];
-+         switchInt(copy (*_2)[1 of 3]) -> [47: bb9, otherwise: bb11];
-      }
-  
-      bb9: {
--         switchInt(copy (*_2)[1 of 3]) -> [47: bb10, otherwise: bb7];
-+         switchInt(copy (*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11];
-      }
-  
-      bb10: {
--         switchInt(copy (*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7];
--     }
-- 
--     bb11: {
-          _0 = const true;
--         goto -> bb14;
-+         goto -> bb12;
-      }
-  
--     bb12: {
--         _0 = const true;
--         goto -> bb14;
--     }
-- 
--     bb13: {
-+     bb11: {
-          _0 = const false;
--         goto -> bb14;
-+         goto -> bb12;
-      }
-  
--     bb14: {
-+     bb12: {
-          StorageDead(_2);
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff
deleted file mode 100644
index 7337a32f525..00000000000
--- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff
+++ /dev/null
@@ -1,100 +0,0 @@
-- // MIR for `is_line_doc_comment_2` before DeduplicateBlocks
-+ // MIR for `is_line_doc_comment_2` after DeduplicateBlocks
-  
-  fn is_line_doc_comment_2(_1: &str) -> bool {
-      debug s => _1;
-      let mut _0: bool;
-      let mut _2: &[u8];
-      let mut _3: &str;
-      let mut _4: usize;
-      let mut _5: usize;
-      let mut _6: bool;
-      let mut _7: usize;
-      let mut _8: usize;
-      let mut _9: bool;
-  
-      bb0: {
-          StorageLive(_2);
-          StorageLive(_3);
-          _3 = &(*_1);
-          _2 = core::str::<impl str>::as_bytes(move _3) -> [return: bb1, unwind continue];
-      }
-  
-      bb1: {
-          StorageDead(_3);
-          _4 = Len((*_2));
-          _5 = const 4_usize;
-          _6 = Ge(move _4, move _5);
-          switchInt(move _6) -> [0: bb2, otherwise: bb3];
-      }
-  
-      bb2: {
-          _7 = Len((*_2));
-          _8 = const 3_usize;
-          _9 = Ge(move _7, move _8);
--         switchInt(move _9) -> [0: bb7, otherwise: bb8];
-+         switchInt(move _9) -> [0: bb11, otherwise: bb7];
-      }
-  
-      bb3: {
-          switchInt(copy (*_2)[0 of 4]) -> [47: bb4, otherwise: bb2];
-      }
-  
-      bb4: {
-          switchInt(copy (*_2)[1 of 4]) -> [47: bb5, otherwise: bb2];
-      }
-  
-      bb5: {
-          switchInt(copy (*_2)[2 of 4]) -> [47: bb6, otherwise: bb2];
-      }
-  
-      bb6: {
--         switchInt(copy (*_2)[3 of 4]) -> [47: bb13, otherwise: bb2];
-+         switchInt(copy (*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
-      }
-  
-      bb7: {
--         _0 = const false;
--         goto -> bb14;
-+         switchInt(copy (*_2)[0 of 3]) -> [47: bb8, otherwise: bb11];
-      }
-  
-      bb8: {
--         switchInt(copy (*_2)[0 of 3]) -> [47: bb9, otherwise: bb7];
-+         switchInt(copy (*_2)[1 of 3]) -> [47: bb9, otherwise: bb11];
-      }
-  
-      bb9: {
--         switchInt(copy (*_2)[1 of 3]) -> [47: bb10, otherwise: bb7];
-+         switchInt(copy (*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11];
-      }
-  
-      bb10: {
--         switchInt(copy (*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7];
--     }
-- 
--     bb11: {
-          _0 = const true;
--         goto -> bb14;
-+         goto -> bb12;
-      }
-  
--     bb12: {
--         _0 = const true;
--         goto -> bb14;
--     }
-- 
--     bb13: {
-+     bb11: {
-          _0 = const false;
--         goto -> bb14;
-+         goto -> bb12;
-      }
-  
--     bb14: {
-+     bb12: {
-          StorageDead(_2);
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/deduplicate_blocks.rs b/tests/mir-opt/deduplicate_blocks.rs
deleted file mode 100644
index 3a164cb09a0..00000000000
--- a/tests/mir-opt/deduplicate_blocks.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// skip-filecheck
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-//@ test-mir-pass: DeduplicateBlocks
-
-// EMIT_MIR deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
-pub const fn is_line_doc_comment_2(s: &str) -> bool {
-    match s.as_bytes() {
-        [b'/', b'/', b'/', b'/', ..] => false,
-        [b'/', b'/', b'/', ..] => true,
-        [b'/', b'/', b'!', ..] => true,
-        _ => false,
-    }
-}
-
-fn main() {
-    is_line_doc_comment_2("asd");
-}