From 6e19e8f63a7bbea20f711f935d2cf467bafcc14b Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Sun, 20 Sep 2020 20:32:12 +0200 Subject: [PATCH 1/5] add test that does not currently optimize --- .../eq_not.opt_has_later_use.InstCombine.diff | 81 +++++++++++++++++++ .../eq_not.opt_has_storage.InstCombine.diff | 67 +++++++++++++++ .../eq_not.opt_simple.InstCombine.diff | 48 +++++++++++ src/test/mir-opt/eq_not.rs | 21 +++++ 4 files changed, 217 insertions(+) create mode 100644 src/test/mir-opt/eq_not.opt_has_later_use.InstCombine.diff create mode 100644 src/test/mir-opt/eq_not.opt_has_storage.InstCombine.diff create mode 100644 src/test/mir-opt/eq_not.opt_simple.InstCombine.diff create mode 100644 src/test/mir-opt/eq_not.rs diff --git a/src/test/mir-opt/eq_not.opt_has_later_use.InstCombine.diff b/src/test/mir-opt/eq_not.opt_has_later_use.InstCombine.diff new file mode 100644 index 0000000000000..5127dd257f862 --- /dev/null +++ b/src/test/mir-opt/eq_not.opt_has_later_use.InstCombine.diff @@ -0,0 +1,81 @@ +- // MIR for `opt_has_later_use` before InstCombine ++ // MIR for `opt_has_later_use` after InstCombine + + fn opt_has_later_use(_1: Vec) -> u8 { + debug x => _1; // in scope 0 at $DIR/eq_not.rs:12:22: 12:23 + let mut _0: u8; // return place in scope 0 at $DIR/eq_not.rs:12:37: 12:39 + let _2: (); // in scope 0 at $DIR/eq_not.rs:13:5: 13:27 + let mut _3: bool; // in scope 0 at $DIR/eq_not.rs:13:5: 13:27 + let mut _4: bool; // in scope 0 at $DIR/eq_not.rs:13:13: 13:25 + let mut _5: usize; // in scope 0 at $DIR/eq_not.rs:13:13: 13:20 + let mut _6: &std::vec::Vec; // in scope 0 at $DIR/eq_not.rs:13:13: 13:14 + let mut _7: !; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _8: &u8; // in scope 0 at $DIR/eq_not.rs:14:5: 14:9 + let mut _9: &std::vec::Vec; // in scope 0 at $DIR/eq_not.rs:14:5: 14:6 + scope 1 { + debug self => _6; // in scope 1 at $SRC_DIR/alloc/src/vec.rs:LL:COL + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/eq_not.rs:13:5: 13:27 + StorageLive(_3); // scope 0 at $DIR/eq_not.rs:13:5: 13:27 + StorageLive(_4); // scope 0 at $DIR/eq_not.rs:13:13: 13:25 + StorageLive(_5); // scope 0 at $DIR/eq_not.rs:13:13: 13:20 + StorageLive(_6); // scope 0 at $DIR/eq_not.rs:13:13: 13:14 + _6 = &_1; // scope 0 at $DIR/eq_not.rs:13:13: 13:14 + _5 = ((*_6).1: usize); // scope 1 at $SRC_DIR/alloc/src/vec.rs:LL:COL + StorageDead(_6); // scope 0 at $DIR/eq_not.rs:13:19: 13:20 + _4 = Eq(move _5, const 2_usize); // scope 0 at $DIR/eq_not.rs:13:13: 13:25 + StorageDead(_5); // scope 0 at $DIR/eq_not.rs:13:24: 13:25 + _3 = Not(move _4); // scope 0 at $DIR/eq_not.rs:13:5: 13:27 + StorageDead(_4); // scope 0 at $DIR/eq_not.rs:13:26: 13:27 + switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/eq_not.rs:13:5: 13:27 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/eq_not.rs:12:1: 15:2 + } + + bb2 (cleanup): { + drop(_1) -> bb1; // scope 0 at $DIR/eq_not.rs:15:1: 15:2 + } + + bb3: { + _2 = const (); // scope 0 at $DIR/eq_not.rs:13:5: 13:27 + StorageDead(_3); // scope 0 at $DIR/eq_not.rs:13:26: 13:27 + StorageDead(_2); // scope 0 at $DIR/eq_not.rs:13:26: 13:27 + StorageLive(_8); // scope 0 at $DIR/eq_not.rs:14:5: 14:9 + StorageLive(_9); // scope 0 at $DIR/eq_not.rs:14:5: 14:6 + _9 = &_1; // scope 0 at $DIR/eq_not.rs:14:5: 14:6 + _8 = as Index>::index(move _9, const 0_usize) -> [return: bb5, unwind: bb2]; // scope 0 at $DIR/eq_not.rs:14:5: 14:9 + // mir::Constant + // + span: $DIR/eq_not.rs:14:5: 14:9 + // + literal: Const { ty: for<'r> fn(&'r std::vec::Vec, usize) -> &'r as std::ops::Index>::Output { as std::ops::Index>::index}, val: Value(Scalar()) } + } + + bb4: { + StorageLive(_7); // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + begin_panic::<&str>(const "assertion failed: x.len() == 2") -> bb2; // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/std/src/macros.rs:LL:COL + // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar()) } + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 120, 46, 108, 101, 110, 40, 41, 32, 61, 61, 32, 50], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1073741823], len: Size { raw: 30 } }, size: Size { raw: 30 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 30 }) + // mir::Constant + // + span: $DIR/eq_not.rs:1:1: 1:1 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 120, 46, 108, 101, 110, 40, 41, 32, 61, 61, 32, 50], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1073741823], len: Size { raw: 30 } }, size: Size { raw: 30 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 30 }) } + } + + bb5: { + _0 = (*_8); // scope 0 at $DIR/eq_not.rs:14:5: 14:9 + StorageDead(_9); // scope 0 at $DIR/eq_not.rs:14:8: 14:9 + StorageDead(_8); // scope 0 at $DIR/eq_not.rs:15:1: 15:2 + drop(_1) -> [return: bb6, unwind: bb1]; // scope 0 at $DIR/eq_not.rs:15:1: 15:2 + } + + bb6: { + return; // scope 0 at $DIR/eq_not.rs:15:2: 15:2 + } + } + diff --git a/src/test/mir-opt/eq_not.opt_has_storage.InstCombine.diff b/src/test/mir-opt/eq_not.opt_has_storage.InstCombine.diff new file mode 100644 index 0000000000000..84b6cc2893aaa --- /dev/null +++ b/src/test/mir-opt/eq_not.opt_has_storage.InstCombine.diff @@ -0,0 +1,67 @@ +- // MIR for `opt_has_storage` before InstCombine ++ // MIR for `opt_has_storage` after InstCombine + + fn opt_has_storage(_1: Vec) -> () { + debug x => _1; // in scope 0 at $DIR/eq_not.rs:7:20: 7:21 + let mut _0: (); // return place in scope 0 at $DIR/eq_not.rs:7:32: 7:32 + let _2: (); // in scope 0 at $DIR/eq_not.rs:8:5: 8:27 + let mut _3: bool; // in scope 0 at $DIR/eq_not.rs:8:5: 8:27 + let mut _4: bool; // in scope 0 at $DIR/eq_not.rs:8:13: 8:25 + let mut _5: usize; // in scope 0 at $DIR/eq_not.rs:8:13: 8:20 + let mut _6: &std::vec::Vec; // in scope 0 at $DIR/eq_not.rs:8:13: 8:14 + let mut _7: !; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + scope 1 { + debug self => _6; // in scope 1 at $SRC_DIR/alloc/src/vec.rs:LL:COL + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/eq_not.rs:8:5: 8:27 + StorageLive(_3); // scope 0 at $DIR/eq_not.rs:8:5: 8:27 + StorageLive(_4); // scope 0 at $DIR/eq_not.rs:8:13: 8:25 + StorageLive(_5); // scope 0 at $DIR/eq_not.rs:8:13: 8:20 + StorageLive(_6); // scope 0 at $DIR/eq_not.rs:8:13: 8:14 + _6 = &_1; // scope 0 at $DIR/eq_not.rs:8:13: 8:14 + _5 = ((*_6).1: usize); // scope 1 at $SRC_DIR/alloc/src/vec.rs:LL:COL + StorageDead(_6); // scope 0 at $DIR/eq_not.rs:8:19: 8:20 + _4 = Eq(move _5, const 2_usize); // scope 0 at $DIR/eq_not.rs:8:13: 8:25 + StorageDead(_5); // scope 0 at $DIR/eq_not.rs:8:24: 8:25 + _3 = Not(move _4); // scope 0 at $DIR/eq_not.rs:8:5: 8:27 + StorageDead(_4); // scope 0 at $DIR/eq_not.rs:8:26: 8:27 + switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/eq_not.rs:8:5: 8:27 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/eq_not.rs:7:1: 9:2 + } + + bb2 (cleanup): { + drop(_1) -> bb1; // scope 0 at $DIR/eq_not.rs:9:1: 9:2 + } + + bb3: { + _2 = const (); // scope 0 at $DIR/eq_not.rs:8:5: 8:27 + StorageDead(_3); // scope 0 at $DIR/eq_not.rs:8:26: 8:27 + StorageDead(_2); // scope 0 at $DIR/eq_not.rs:8:26: 8:27 + _0 = const (); // scope 0 at $DIR/eq_not.rs:7:32: 9:2 + drop(_1) -> [return: bb5, unwind: bb1]; // scope 0 at $DIR/eq_not.rs:9:1: 9:2 + } + + bb4: { + StorageLive(_7); // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + begin_panic::<&str>(const "assertion failed: x.len() == 2") -> bb2; // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/std/src/macros.rs:LL:COL + // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar()) } + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 120, 46, 108, 101, 110, 40, 41, 32, 61, 61, 32, 50], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1073741823], len: Size { raw: 30 } }, size: Size { raw: 30 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 30 }) + // mir::Constant + // + span: $DIR/eq_not.rs:1:1: 1:1 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 120, 46, 108, 101, 110, 40, 41, 32, 61, 61, 32, 50], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1073741823], len: Size { raw: 30 } }, size: Size { raw: 30 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 30 }) } + } + + bb5: { + return; // scope 0 at $DIR/eq_not.rs:9:2: 9:2 + } + } + diff --git a/src/test/mir-opt/eq_not.opt_simple.InstCombine.diff b/src/test/mir-opt/eq_not.opt_simple.InstCombine.diff new file mode 100644 index 0000000000000..7fa151fa89c77 --- /dev/null +++ b/src/test/mir-opt/eq_not.opt_simple.InstCombine.diff @@ -0,0 +1,48 @@ +- // MIR for `opt_simple` before InstCombine ++ // MIR for `opt_simple` after InstCombine + + fn opt_simple(_1: u8) -> () { + debug x => _1; // in scope 0 at $DIR/eq_not.rs:2:15: 2:16 + let mut _0: (); // return place in scope 0 at $DIR/eq_not.rs:2:22: 2:22 + let _2: (); // in scope 0 at $DIR/eq_not.rs:3:5: 3:21 + let mut _3: bool; // in scope 0 at $DIR/eq_not.rs:3:5: 3:21 + let mut _4: bool; // in scope 0 at $DIR/eq_not.rs:3:13: 3:19 + let mut _5: u8; // in scope 0 at $DIR/eq_not.rs:3:13: 3:14 + let mut _6: !; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + + bb0: { + StorageLive(_2); // scope 0 at $DIR/eq_not.rs:3:5: 3:21 + StorageLive(_3); // scope 0 at $DIR/eq_not.rs:3:5: 3:21 + StorageLive(_4); // scope 0 at $DIR/eq_not.rs:3:13: 3:19 + StorageLive(_5); // scope 0 at $DIR/eq_not.rs:3:13: 3:14 + _5 = _1; // scope 0 at $DIR/eq_not.rs:3:13: 3:14 + _4 = Eq(move _5, const 2_u8); // scope 0 at $DIR/eq_not.rs:3:13: 3:19 + StorageDead(_5); // scope 0 at $DIR/eq_not.rs:3:18: 3:19 + _3 = Not(move _4); // scope 0 at $DIR/eq_not.rs:3:5: 3:21 + StorageDead(_4); // scope 0 at $DIR/eq_not.rs:3:20: 3:21 + switchInt(_3) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/eq_not.rs:3:5: 3:21 + } + + bb1: { + _2 = const (); // scope 0 at $DIR/eq_not.rs:3:5: 3:21 + StorageDead(_3); // scope 0 at $DIR/eq_not.rs:3:20: 3:21 + StorageDead(_2); // scope 0 at $DIR/eq_not.rs:3:20: 3:21 + _0 = const (); // scope 0 at $DIR/eq_not.rs:2:22: 4:2 + return; // scope 0 at $DIR/eq_not.rs:4:2: 4:2 + } + + bb2: { + StorageLive(_6); // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + begin_panic::<&str>(const "assertion failed: x == 2"); // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/std/src/macros.rs:LL:COL + // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar()) } + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 120, 32, 61, 61, 32, 50], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16777215], len: Size { raw: 24 } }, size: Size { raw: 24 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 24 }) + // mir::Constant + // + span: $DIR/eq_not.rs:1:1: 1:1 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 120, 32, 61, 61, 32, 50], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16777215], len: Size { raw: 24 } }, size: Size { raw: 24 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 24 }) } + } + } + diff --git a/src/test/mir-opt/eq_not.rs b/src/test/mir-opt/eq_not.rs new file mode 100644 index 0000000000000..ec6873a3234b7 --- /dev/null +++ b/src/test/mir-opt/eq_not.rs @@ -0,0 +1,21 @@ +// EMIT_MIR eq_not.opt_simple.InstCombine.diff +fn opt_simple(x: u8) { + assert!(x == 2); +} + +// EMIT_MIR eq_not.opt_has_storage.InstCombine.diff +fn opt_has_storage(x: Vec) { + assert!(x.len() == 2); +} + +// EMIT_MIR eq_not.opt_has_later_use.InstCombine.diff +fn opt_has_later_use(x: Vec) -> u8 { + assert!(x.len() == 2); + x[0] +} + +fn main() { + opt_simple(0); + opt_has_storage(vec![]); + opt_has_later_use(vec![]); +} From 04bb5619190771ab3cca1f1806a419cc62082c7b Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Mon, 21 Sep 2020 21:58:17 +0200 Subject: [PATCH 2/5] Implement optimization that turns Eq-Not pair into Ne --- .../rustc_mir/src/transform/instcombine.rs | 117 +++++++++++++++ .../eq_not.opt_both_moved.InstCombine.diff | 55 ++++++++ .../eq_not.opt_has_later_use.InstCombine.diff | 85 +++++------ .../eq_not.opt_has_storage.InstCombine.diff | 6 +- .../eq_not.opt_simple.InstCombine.diff | 6 +- src/test/mir-opt/eq_not.rs | 10 +- ...e_deref.do_not_miscompile.InstCombine.diff | 6 +- .../issue_73223.main.PreCodegen.64bit.diff | 133 +++++++++--------- ..._73223.main.SimplifyArmIdentity.64bit.diff | 10 +- 9 files changed, 294 insertions(+), 134 deletions(-) create mode 100644 src/test/mir-opt/eq_not.opt_both_moved.InstCombine.diff diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index 3ed0aea1404d4..b1c2560f1ec8a 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -4,6 +4,7 @@ use crate::transform::{MirPass, MirSource}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::Mutability; use rustc_index::vec::Idx; +use rustc_middle::mir::UnOp; use rustc_middle::mir::{ visit::PlaceContext, visit::{MutVisitor, Visitor}, @@ -14,6 +15,7 @@ use rustc_middle::mir::{ Rvalue, }; use rustc_middle::ty::{self, TyCtxt}; +use smallvec::SmallVec; use std::mem; pub struct InstCombine; @@ -29,8 +31,28 @@ impl<'tcx> MirPass<'tcx> for InstCombine { optimization_finder.optimizations }; + // Since eq_not has elements removed in the visitor, we clone it here, + // such that we can still do the post visitor cleanup. + let clone_eq_not = optimizations.eq_not.clone(); // Then carry out those optimizations. MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body); + eq_not_post_visitor_mutations(body, clone_eq_not); + } +} + +fn eq_not_post_visitor_mutations<'tcx>( + body: &mut Body<'tcx>, + eq_not_opts: FxHashMap>, +) { + for (location, eq_not_opt_info) in eq_not_opts.iter() { + let statements = &mut body.basic_blocks_mut()[location.block].statements; + // We have to make sure that Ne is before any StorageDead as the operand being killed is used in the Ne + if let Some(storage_dead_idx_to_swap_with) = eq_not_opt_info.storage_dead_to_swap_with_ne { + statements.swap(location.statement_index, storage_dead_idx_to_swap_with); + } + if let Some(eq_stmt_idx) = eq_not_opt_info.can_remove_eq { + statements[eq_stmt_idx].make_nop(); + } } } @@ -81,6 +103,11 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> { *rvalue = Rvalue::Use(Operand::Copy(place)); } + if let Some(eq_not_opt_info) = self.optimizations.eq_not.remove(&location) { + *rvalue = Rvalue::BinaryOp(BinOp::Ne, eq_not_opt_info.op1, eq_not_opt_info.op2); + debug!("replacing Eq and Not with {:?}", rvalue); + } + self.super_rvalue(rvalue, location) } } @@ -221,6 +248,85 @@ impl OptimizationFinder<'b, 'tcx> { } } + fn find_eq_not(&mut self, rvalue: &Rvalue<'tcx>, location: Location) -> Option<()> { + // Optimize the sequence + // _4 = Eq(move _5, const 2_u8); + // StorageDead(_5); + // _3 = Not(move _4); + // + // into _3 = Ne(move _5, const 2_u8) + if let Rvalue::UnaryOp(UnOp::Not, op) = rvalue { + let place = op.place()?; + // See if we can find a Eq that assigns `place`. + // We limit the search to 3 statements lookback. + // Usually the first 2 statements are `StorageDead`s for operands for Eq. + // We record what is marked dead so that we can reorder StorageDead so it comes after Ne + + // We will maximum see 2 StorageDeads + let mut seen_storage_deads: SmallVec<[_; 2]> = SmallVec::new(); + let lower_index = location.statement_index.saturating_sub(3); + for (stmt_idx, stmt) in self.body.basic_blocks()[location.block].statements + [lower_index..location.statement_index] + .iter() + .enumerate() + .rev() + { + match &stmt.kind { + rustc_middle::mir::StatementKind::Assign(box (l, r)) => { + if *l == place { + match r { + Rvalue::BinaryOp(BinOp::Eq, op1, op2) => { + // We need to make sure that the StorageDeads we saw are for + // either `op1`or `op2` of Eq. Else we bail the optimization. + for (dead_local, _) in seen_storage_deads.iter() { + let dead_local_matches = [op1, op2].iter().any(|x| { + Some(*dead_local) == x.place().map(|x| x.local) + }); + if !dead_local_matches { + return None; + } + } + + // We need to make sure that the Ne we are going to insert comes before the + // StorageDeads so we want to swap the StorageDead closest to Eq with Ne. + let storage_dead_to_swap = + seen_storage_deads.last().map(|(_, idx)| *idx); + + // If the operand of Not is moved into it, + // and that same operand is the lhs of the Eq assignment, + // then we can safely remove the Eq + let can_remove_eq = if op.is_move() { + Some(stmt_idx + lower_index) + } else { + None + }; + + self.optimizations.eq_not.insert( + location, + EqNotOptInfo { + op1: op1.clone(), + op2: op2.clone(), + storage_dead_to_swap_with_ne: storage_dead_to_swap, + can_remove_eq, + }, + ); + return Some(()); + } + _ => {} + } + } + } + rustc_middle::mir::StatementKind::StorageDead(dead) => { + seen_storage_deads.push((*dead, stmt_idx + lower_index)); + } + // If we see a pattern other than (0..=2) StorageDeads and then an Eq assignment, we conservatively bail + _ => return None, + } + } + } + Some(()) + } + fn find_operand_in_equality_comparison_pattern( &self, l: &Operand<'tcx>, @@ -265,16 +371,27 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { let _ = self.find_deref_of_address(rvalue, location); + let _ = self.find_eq_not(rvalue, location); + self.find_unneeded_equality_comparison(rvalue, location); self.super_rvalue(rvalue, location) } } +#[derive(Clone)] +struct EqNotOptInfo<'tcx> { + op1: Operand<'tcx>, + op2: Operand<'tcx>, + storage_dead_to_swap_with_ne: Option, + can_remove_eq: Option, +} + #[derive(Default)] struct OptimizationList<'tcx> { and_stars: FxHashSet, arrays_lengths: FxHashMap>, unneeded_equality_comparison: FxHashMap>, unneeded_deref: FxHashMap>, + eq_not: FxHashMap>, } diff --git a/src/test/mir-opt/eq_not.opt_both_moved.InstCombine.diff b/src/test/mir-opt/eq_not.opt_both_moved.InstCombine.diff new file mode 100644 index 0000000000000..a0c3f474a8ce0 --- /dev/null +++ b/src/test/mir-opt/eq_not.opt_both_moved.InstCombine.diff @@ -0,0 +1,55 @@ +- // MIR for `opt_both_moved` before InstCombine ++ // MIR for `opt_both_moved` after InstCombine + + fn opt_both_moved(_1: u8) -> () { + debug x => _1; // in scope 0 at $DIR/eq_not.rs:18:19: 18:20 + let mut _0: (); // return place in scope 0 at $DIR/eq_not.rs:18:26: 18:26 + let _2: (); // in scope 0 at $DIR/eq_not.rs:19:5: 19:21 + let mut _3: bool; // in scope 0 at $DIR/eq_not.rs:19:5: 19:21 + let mut _4: bool; // in scope 0 at $DIR/eq_not.rs:19:13: 19:19 + let mut _5: u8; // in scope 0 at $DIR/eq_not.rs:19:13: 19:14 + let mut _6: u8; // in scope 0 at $DIR/eq_not.rs:19:18: 19:19 + let mut _7: !; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + + bb0: { + StorageLive(_2); // scope 0 at $DIR/eq_not.rs:19:5: 19:21 + StorageLive(_3); // scope 0 at $DIR/eq_not.rs:19:5: 19:21 + StorageLive(_4); // scope 0 at $DIR/eq_not.rs:19:13: 19:19 + StorageLive(_5); // scope 0 at $DIR/eq_not.rs:19:13: 19:14 + _5 = _1; // scope 0 at $DIR/eq_not.rs:19:13: 19:14 + StorageLive(_6); // scope 0 at $DIR/eq_not.rs:19:18: 19:19 + _6 = _1; // scope 0 at $DIR/eq_not.rs:19:18: 19:19 +- _4 = Eq(move _5, move _6); // scope 0 at $DIR/eq_not.rs:19:13: 19:19 +- StorageDead(_6); // scope 0 at $DIR/eq_not.rs:19:18: 19:19 ++ nop; // scope 0 at $DIR/eq_not.rs:19:13: 19:19 ++ _3 = Ne(move _5, move _6); // scope 0 at $DIR/eq_not.rs:19:5: 19:21 + StorageDead(_5); // scope 0 at $DIR/eq_not.rs:19:18: 19:19 +- _3 = Not(move _4); // scope 0 at $DIR/eq_not.rs:19:5: 19:21 ++ StorageDead(_6); // scope 0 at $DIR/eq_not.rs:19:18: 19:19 + StorageDead(_4); // scope 0 at $DIR/eq_not.rs:19:20: 19:21 + switchInt(_3) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/eq_not.rs:19:5: 19:21 + } + + bb1: { + _2 = const (); // scope 0 at $DIR/eq_not.rs:19:5: 19:21 + StorageDead(_3); // scope 0 at $DIR/eq_not.rs:19:20: 19:21 + StorageDead(_2); // scope 0 at $DIR/eq_not.rs:19:20: 19:21 + _0 = const (); // scope 0 at $DIR/eq_not.rs:18:26: 20:2 + return; // scope 0 at $DIR/eq_not.rs:20:2: 20:2 + } + + bb2: { + StorageLive(_7); // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + begin_panic::<&str>(const "assertion failed: x == x"); // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/std/src/macros.rs:LL:COL + // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar()) } + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 120, 32, 61, 61, 32, 120], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16777215], len: Size { raw: 24 } }, size: Size { raw: 24 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 24 }) + // mir::Constant + // + span: $DIR/eq_not.rs:1:1: 1:1 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 120, 32, 61, 61, 32, 120], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16777215], len: Size { raw: 24 } }, size: Size { raw: 24 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 24 }) } + } + } + diff --git a/src/test/mir-opt/eq_not.opt_has_later_use.InstCombine.diff b/src/test/mir-opt/eq_not.opt_has_later_use.InstCombine.diff index 5127dd257f862..cfc13c8108e63 100644 --- a/src/test/mir-opt/eq_not.opt_has_later_use.InstCombine.diff +++ b/src/test/mir-opt/eq_not.opt_has_later_use.InstCombine.diff @@ -4,77 +4,58 @@ fn opt_has_later_use(_1: Vec) -> u8 { debug x => _1; // in scope 0 at $DIR/eq_not.rs:12:22: 12:23 let mut _0: u8; // return place in scope 0 at $DIR/eq_not.rs:12:37: 12:39 - let _2: (); // in scope 0 at $DIR/eq_not.rs:13:5: 13:27 - let mut _3: bool; // in scope 0 at $DIR/eq_not.rs:13:5: 13:27 - let mut _4: bool; // in scope 0 at $DIR/eq_not.rs:13:13: 13:25 - let mut _5: usize; // in scope 0 at $DIR/eq_not.rs:13:13: 13:20 - let mut _6: &std::vec::Vec; // in scope 0 at $DIR/eq_not.rs:13:13: 13:14 - let mut _7: !; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _8: &u8; // in scope 0 at $DIR/eq_not.rs:14:5: 14:9 - let mut _9: &std::vec::Vec; // in scope 0 at $DIR/eq_not.rs:14:5: 14:6 + let _2: bool; // in scope 0 at $DIR/eq_not.rs:13:9: 13:10 + let mut _3: bool; // in scope 0 at $DIR/eq_not.rs:13:14: 13:28 + let mut _4: usize; // in scope 0 at $DIR/eq_not.rs:13:15: 13:22 + let mut _5: &std::vec::Vec; // in scope 0 at $DIR/eq_not.rs:13:15: 13:16 + let mut _6: bool; // in scope 0 at $DIR/eq_not.rs:14:8: 14:9 scope 1 { - debug self => _6; // in scope 1 at $SRC_DIR/alloc/src/vec.rs:LL:COL + debug x => _2; // in scope 1 at $DIR/eq_not.rs:13:9: 13:10 + } + scope 2 { + debug self => _5; // in scope 2 at $SRC_DIR/alloc/src/vec.rs:LL:COL } bb0: { - StorageLive(_2); // scope 0 at $DIR/eq_not.rs:13:5: 13:27 - StorageLive(_3); // scope 0 at $DIR/eq_not.rs:13:5: 13:27 - StorageLive(_4); // scope 0 at $DIR/eq_not.rs:13:13: 13:25 - StorageLive(_5); // scope 0 at $DIR/eq_not.rs:13:13: 13:20 - StorageLive(_6); // scope 0 at $DIR/eq_not.rs:13:13: 13:14 - _6 = &_1; // scope 0 at $DIR/eq_not.rs:13:13: 13:14 - _5 = ((*_6).1: usize); // scope 1 at $SRC_DIR/alloc/src/vec.rs:LL:COL - StorageDead(_6); // scope 0 at $DIR/eq_not.rs:13:19: 13:20 - _4 = Eq(move _5, const 2_usize); // scope 0 at $DIR/eq_not.rs:13:13: 13:25 - StorageDead(_5); // scope 0 at $DIR/eq_not.rs:13:24: 13:25 - _3 = Not(move _4); // scope 0 at $DIR/eq_not.rs:13:5: 13:27 - StorageDead(_4); // scope 0 at $DIR/eq_not.rs:13:26: 13:27 - switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/eq_not.rs:13:5: 13:27 + StorageLive(_2); // scope 0 at $DIR/eq_not.rs:13:9: 13:10 + StorageLive(_3); // scope 0 at $DIR/eq_not.rs:13:14: 13:28 + StorageLive(_4); // scope 0 at $DIR/eq_not.rs:13:15: 13:22 + StorageLive(_5); // scope 0 at $DIR/eq_not.rs:13:15: 13:16 + _5 = &_1; // scope 0 at $DIR/eq_not.rs:13:15: 13:16 + _4 = ((*_5).1: usize); // scope 2 at $SRC_DIR/alloc/src/vec.rs:LL:COL + StorageDead(_5); // scope 0 at $DIR/eq_not.rs:13:21: 13:22 +- _3 = Eq(move _4, const 2_usize); // scope 0 at $DIR/eq_not.rs:13:14: 13:28 ++ nop; // scope 0 at $DIR/eq_not.rs:13:14: 13:28 ++ _2 = Ne(move _4, const 2_usize); // scope 0 at $DIR/eq_not.rs:13:13: 13:28 + StorageDead(_4); // scope 0 at $DIR/eq_not.rs:13:27: 13:28 +- _2 = Not(move _3); // scope 0 at $DIR/eq_not.rs:13:13: 13:28 + StorageDead(_3); // scope 0 at $DIR/eq_not.rs:13:27: 13:28 + StorageLive(_6); // scope 1 at $DIR/eq_not.rs:14:8: 14:9 + _6 = _2; // scope 1 at $DIR/eq_not.rs:14:8: 14:9 + switchInt(_6) -> [false: bb2, otherwise: bb3]; // scope 1 at $DIR/eq_not.rs:14:5: 14:26 } bb1 (cleanup): { resume; // scope 0 at $DIR/eq_not.rs:12:1: 15:2 } - bb2 (cleanup): { - drop(_1) -> bb1; // scope 0 at $DIR/eq_not.rs:15:1: 15:2 + bb2: { + _0 = const 1_u8; // scope 1 at $DIR/eq_not.rs:14:23: 14:24 + goto -> bb4; // scope 1 at $DIR/eq_not.rs:14:5: 14:26 } bb3: { - _2 = const (); // scope 0 at $DIR/eq_not.rs:13:5: 13:27 - StorageDead(_3); // scope 0 at $DIR/eq_not.rs:13:26: 13:27 - StorageDead(_2); // scope 0 at $DIR/eq_not.rs:13:26: 13:27 - StorageLive(_8); // scope 0 at $DIR/eq_not.rs:14:5: 14:9 - StorageLive(_9); // scope 0 at $DIR/eq_not.rs:14:5: 14:6 - _9 = &_1; // scope 0 at $DIR/eq_not.rs:14:5: 14:6 - _8 = as Index>::index(move _9, const 0_usize) -> [return: bb5, unwind: bb2]; // scope 0 at $DIR/eq_not.rs:14:5: 14:9 - // mir::Constant - // + span: $DIR/eq_not.rs:14:5: 14:9 - // + literal: Const { ty: for<'r> fn(&'r std::vec::Vec, usize) -> &'r as std::ops::Index>::Output { as std::ops::Index>::index}, val: Value(Scalar()) } + _0 = const 0_u8; // scope 1 at $DIR/eq_not.rs:14:12: 14:13 + goto -> bb4; // scope 1 at $DIR/eq_not.rs:14:5: 14:26 } bb4: { - StorageLive(_7); // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - begin_panic::<&str>(const "assertion failed: x.len() == 2") -> bb2; // scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/std/src/macros.rs:LL:COL - // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar()) } - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 120, 46, 108, 101, 110, 40, 41, 32, 61, 61, 32, 50], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1073741823], len: Size { raw: 30 } }, size: Size { raw: 30 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 30 }) - // mir::Constant - // + span: $DIR/eq_not.rs:1:1: 1:1 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [97, 115, 115, 101, 114, 116, 105, 111, 110, 32, 102, 97, 105, 108, 101, 100, 58, 32, 120, 46, 108, 101, 110, 40, 41, 32, 61, 61, 32, 50], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1073741823], len: Size { raw: 30 } }, size: Size { raw: 30 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 30 }) } + StorageDead(_2); // scope 0 at $DIR/eq_not.rs:15:1: 15:2 + StorageDead(_6); // scope 0 at $DIR/eq_not.rs:15:1: 15:2 + drop(_1) -> [return: bb5, unwind: bb1]; // scope 0 at $DIR/eq_not.rs:15:1: 15:2 } bb5: { - _0 = (*_8); // scope 0 at $DIR/eq_not.rs:14:5: 14:9 - StorageDead(_9); // scope 0 at $DIR/eq_not.rs:14:8: 14:9 - StorageDead(_8); // scope 0 at $DIR/eq_not.rs:15:1: 15:2 - drop(_1) -> [return: bb6, unwind: bb1]; // scope 0 at $DIR/eq_not.rs:15:1: 15:2 - } - - bb6: { return; // scope 0 at $DIR/eq_not.rs:15:2: 15:2 } } diff --git a/src/test/mir-opt/eq_not.opt_has_storage.InstCombine.diff b/src/test/mir-opt/eq_not.opt_has_storage.InstCombine.diff index 84b6cc2893aaa..a03147a8fe124 100644 --- a/src/test/mir-opt/eq_not.opt_has_storage.InstCombine.diff +++ b/src/test/mir-opt/eq_not.opt_has_storage.InstCombine.diff @@ -23,9 +23,11 @@ _6 = &_1; // scope 0 at $DIR/eq_not.rs:8:13: 8:14 _5 = ((*_6).1: usize); // scope 1 at $SRC_DIR/alloc/src/vec.rs:LL:COL StorageDead(_6); // scope 0 at $DIR/eq_not.rs:8:19: 8:20 - _4 = Eq(move _5, const 2_usize); // scope 0 at $DIR/eq_not.rs:8:13: 8:25 +- _4 = Eq(move _5, const 2_usize); // scope 0 at $DIR/eq_not.rs:8:13: 8:25 ++ nop; // scope 0 at $DIR/eq_not.rs:8:13: 8:25 ++ _3 = Ne(move _5, const 2_usize); // scope 0 at $DIR/eq_not.rs:8:5: 8:27 StorageDead(_5); // scope 0 at $DIR/eq_not.rs:8:24: 8:25 - _3 = Not(move _4); // scope 0 at $DIR/eq_not.rs:8:5: 8:27 +- _3 = Not(move _4); // scope 0 at $DIR/eq_not.rs:8:5: 8:27 StorageDead(_4); // scope 0 at $DIR/eq_not.rs:8:26: 8:27 switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/eq_not.rs:8:5: 8:27 } diff --git a/src/test/mir-opt/eq_not.opt_simple.InstCombine.diff b/src/test/mir-opt/eq_not.opt_simple.InstCombine.diff index 7fa151fa89c77..b8ba46f97c35c 100644 --- a/src/test/mir-opt/eq_not.opt_simple.InstCombine.diff +++ b/src/test/mir-opt/eq_not.opt_simple.InstCombine.diff @@ -16,9 +16,11 @@ StorageLive(_4); // scope 0 at $DIR/eq_not.rs:3:13: 3:19 StorageLive(_5); // scope 0 at $DIR/eq_not.rs:3:13: 3:14 _5 = _1; // scope 0 at $DIR/eq_not.rs:3:13: 3:14 - _4 = Eq(move _5, const 2_u8); // scope 0 at $DIR/eq_not.rs:3:13: 3:19 +- _4 = Eq(move _5, const 2_u8); // scope 0 at $DIR/eq_not.rs:3:13: 3:19 ++ nop; // scope 0 at $DIR/eq_not.rs:3:13: 3:19 ++ _3 = Ne(move _5, const 2_u8); // scope 0 at $DIR/eq_not.rs:3:5: 3:21 StorageDead(_5); // scope 0 at $DIR/eq_not.rs:3:18: 3:19 - _3 = Not(move _4); // scope 0 at $DIR/eq_not.rs:3:5: 3:21 +- _3 = Not(move _4); // scope 0 at $DIR/eq_not.rs:3:5: 3:21 StorageDead(_4); // scope 0 at $DIR/eq_not.rs:3:20: 3:21 switchInt(_3) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/eq_not.rs:3:5: 3:21 } diff --git a/src/test/mir-opt/eq_not.rs b/src/test/mir-opt/eq_not.rs index ec6873a3234b7..7584289ff42e1 100644 --- a/src/test/mir-opt/eq_not.rs +++ b/src/test/mir-opt/eq_not.rs @@ -10,12 +10,18 @@ fn opt_has_storage(x: Vec) { // EMIT_MIR eq_not.opt_has_later_use.InstCombine.diff fn opt_has_later_use(x: Vec) -> u8 { - assert!(x.len() == 2); - x[0] + let x = !(x.len() == 2); + if x { 0 } else { 1 } +} + +// EMIT_MIR eq_not.opt_both_moved.InstCombine.diff +fn opt_both_moved(x: u8) { + assert!(x == x); } fn main() { opt_simple(0); opt_has_storage(vec![]); opt_has_later_use(vec![]); + opt_both_moved(0); } diff --git a/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff index 23c18bde2262b..7716243fdd746 100644 --- a/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff +++ b/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff @@ -49,9 +49,11 @@ StorageLive(_9); // scope 4 at $DIR/inst_combine_deref.rs:60:13: 60:21 StorageLive(_10); // scope 4 at $DIR/inst_combine_deref.rs:60:13: 60:15 _10 = (*_3); // scope 4 at $DIR/inst_combine_deref.rs:60:13: 60:15 - _9 = Eq(move _10, const 99_i32); // scope 4 at $DIR/inst_combine_deref.rs:60:13: 60:21 +- _9 = Eq(move _10, const 99_i32); // scope 4 at $DIR/inst_combine_deref.rs:60:13: 60:21 ++ nop; // scope 4 at $DIR/inst_combine_deref.rs:60:13: 60:21 ++ _8 = Ne(move _10, const 99_i32); // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23 StorageDead(_10); // scope 4 at $DIR/inst_combine_deref.rs:60:20: 60:21 - _8 = Not(move _9); // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23 +- _8 = Not(move _9); // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23 StorageDead(_9); // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23 switchInt(_8) -> [false: bb1, otherwise: bb2]; // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23 } diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff index a8662b96566cc..46d484b4cc7a5 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff @@ -6,50 +6,48 @@ let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14 let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30 let mut _4: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _5: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _6: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _7: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _8: &std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let _9: std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _10: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let _11: [std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _12: (&&i32, &&i32); // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _5: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _6: &std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _7: std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _8: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _9: [std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _10: (&&i32, &&i32); // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _11: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _12: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _13: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _14: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _16: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _17: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _14: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _15: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL scope 1 { debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 let _3: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 scope 3 { debug _prev => _3; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14 scope 4 { - debug left_val => _13; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - debug right_val => _15; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug left_val => _11; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug right_val => _13; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 5 { - debug arg0 => _20; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - debug arg1 => _23; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug arg0 => _18; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug arg1 => _21; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 6 { - debug x => _20; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - debug f => _19; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - let mut _18: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _19: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _20: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL + debug x => _18; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + debug f => _17; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + let mut _16: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _17: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _18: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL } scope 8 { - debug x => _23; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - debug f => _22; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - let mut _21: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _22: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _23: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL + debug x => _21; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + debug f => _20; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + let mut _19: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _20: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _21: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL } } scope 10 { - debug pieces => (_9.0: &[&str]); // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - debug args => _25; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - let mut _24: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _25: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL + debug pieces => (_7.0: &[&str]); // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + debug args => _23; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + let mut _22: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _23: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL } } } @@ -78,17 +76,11 @@ // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1])) } - _13 = (_4.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = (_4.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _11 = (_4.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _13 = (_4.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_5); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_6); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_7); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _7 = (*_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _6 = Eq(move _7, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_7); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _5 = Not(move _6); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_6); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - switchInt(_5) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _5 = (*_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + switchInt(move _5) -> [1_i32: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } bb1: { @@ -98,73 +90,74 @@ } bb2: { - (_9.0: &[&str]) = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_5); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_7.0: &[&str]) = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &[&str; 3] // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) } - StorageLive(_11); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - (_12.0: &&i32) = &_13; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _14 = &_15; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_12.1: &&i32) = move _14; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageDead(_14); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - _20 = (_12.0: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _23 = (_12.1: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _19 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_9); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + (_10.0: &&i32) = &_11; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _12 = &_13; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_10.1: &&i32) = move _12; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_12); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _18 = (_10.0: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _21 = (_10.1: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _17 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar()) } - StorageLive(_18); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _18 = transmute:: fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _19) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_16); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _16 = transmute:: fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _17) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar()) } } bb3: { - (_16.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _20) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_14.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _18) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar()) } } bb4: { - (_16.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _18; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_18); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _22 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_14.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _16; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_16); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _20 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar()) } - StorageLive(_21); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _21 = transmute:: fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _22) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_19); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _19 = transmute:: fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _20) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar()) } } bb5: { - (_17.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_15.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _21) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar()) } } bb6: { - (_17.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _21; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_21); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _11 = [move _16, move _17]; // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL - _10 = &_11; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - _25 = move _10 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageLive(_24); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - discriminant(_24) = 0; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_9.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _24; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_9.2: &[std::fmt::ArgumentV1]) = move _25; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_24); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_15.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _19; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_19); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _9 = [move _14, move _15]; // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL _8 = &_9; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - begin_panic_fmt(move _8); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _23 = move _8 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_22); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + discriminant(_22) = 0; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_7.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _22; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_7.2: &[std::fmt::ArgumentV1]) = move _23; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_22); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _6 = &_7; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + begin_panic_fmt(move _6); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL // mir::Constant // + span: $SRC_DIR/std/src/macros.rs:LL:COL // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar()) } diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff index 302612f5a0a28..bffce2c8f931a 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff @@ -148,12 +148,12 @@ _17 = (*_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = Eq(move _17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + nop; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _15 = Ne(_17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + nop; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = Not(move _16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - switchInt(_15) -> [false: bb4, otherwise: bb5]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + switchInt(move _17) -> [1_i32: bb4, otherwise: bb5]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } bb3: { @@ -161,6 +161,7 @@ } bb4: { + StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _8 = const (); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_14); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -174,6 +175,7 @@ } bb5: { + StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_19); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageLive(_20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageLive(_21); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL From df05775dfafd570a96173dd5016375dd2cad255b Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Wed, 23 Sep 2020 18:40:00 +0200 Subject: [PATCH 3/5] Add fixme for future work on Ne-Not pair --- compiler/rustc_mir/src/transform/instcombine.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index b1c2560f1ec8a..af9c6b2cae9d1 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -275,6 +275,7 @@ impl OptimizationFinder<'b, 'tcx> { rustc_middle::mir::StatementKind::Assign(box (l, r)) => { if *l == place { match r { + // FIXME(simonvandel): extend for Ne-Not pair Rvalue::BinaryOp(BinOp::Eq, op1, op2) => { // We need to make sure that the StorageDeads we saw are for // either `op1`or `op2` of Eq. Else we bail the optimization. From 65389df43edf5132498d5dc89d253bbee4d96ca3 Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Wed, 23 Sep 2020 18:47:07 +0200 Subject: [PATCH 4/5] Expand on why we swap StorageDead --- compiler/rustc_mir/src/transform/instcombine.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index af9c6b2cae9d1..a7bd19c45c9e9 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -288,8 +288,21 @@ impl OptimizationFinder<'b, 'tcx> { } } - // We need to make sure that the Ne we are going to insert comes before the - // StorageDeads so we want to swap the StorageDead closest to Eq with Ne. + // Recall that we are optimizing a sequence that looks like + // this: + // _4 = Eq(move _5, move _6); + // StorageDead(_5); + // StorageDead(_6); + // _3 = Not(move _4); + // + // If we do a naive replace of Not -> Ne, we up with this: + // StorageDead(_5); + // StorageDead(_6); + // _3 = Ne(move _5, move _6); + // + // Notice that `_5` and `_6` are marked dead before being used. + // To combat this we want to swap Ne with the StorageDead + // closest to Eq, i.e `StorageDead(_5)` in this example. let storage_dead_to_swap = seen_storage_deads.last().map(|(_, idx)| *idx); From 0e0e767542b8831efeb50b1be0ca821cc33373de Mon Sep 17 00:00:00 2001 From: Simon Vandel Sillesen Date: Wed, 23 Sep 2020 18:52:01 +0200 Subject: [PATCH 5/5] Document EqNotOptInfo fields --- compiler/rustc_mir/src/transform/instcombine.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index a7bd19c45c9e9..b69bef18c5fea 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -47,7 +47,9 @@ fn eq_not_post_visitor_mutations<'tcx>( for (location, eq_not_opt_info) in eq_not_opts.iter() { let statements = &mut body.basic_blocks_mut()[location.block].statements; // We have to make sure that Ne is before any StorageDead as the operand being killed is used in the Ne - if let Some(storage_dead_idx_to_swap_with) = eq_not_opt_info.storage_dead_to_swap_with_ne { + if let Some(storage_dead_idx_to_swap_with) = + eq_not_opt_info.storage_dead_idx_to_swap_with_ne + { statements.swap(location.statement_index, storage_dead_idx_to_swap_with); } if let Some(eq_stmt_idx) = eq_not_opt_info.can_remove_eq { @@ -320,7 +322,7 @@ impl OptimizationFinder<'b, 'tcx> { EqNotOptInfo { op1: op1.clone(), op2: op2.clone(), - storage_dead_to_swap_with_ne: storage_dead_to_swap, + storage_dead_idx_to_swap_with_ne: storage_dead_to_swap, can_remove_eq, }, ); @@ -395,9 +397,14 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { #[derive(Clone)] struct EqNotOptInfo<'tcx> { + /// First operand of the Eq in the Eq-Not pair op1: Operand<'tcx>, + /// Second operand of the Eq in the Eq-Not pair op2: Operand<'tcx>, - storage_dead_to_swap_with_ne: Option, + /// Statement index of the `StorageDead` we want to swap with Ne. + /// None if no `StorageDead` exists between Eq and Not pair) + storage_dead_idx_to_swap_with_ne: Option, + // Statement index of the Eq. None if it can not be removed can_remove_eq: Option, }