From b8d08bbe77752d442983c13921c7e09ec23314ba Mon Sep 17 00:00:00 2001 From: dianqk Date: Sat, 18 Oct 2025 21:42:08 +0800 Subject: [PATCH 1/3] Add miscompiled test cases for GVN --- .../gvn_copy_aggregate.deref_nonssa.GVN.diff | 50 ++++++++++++ ...gvn_copy_aggregate.deref_nonssa_2.GVN.diff | 77 +++++++++++++++++++ tests/mir-opt/gvn_copy_aggregate.rs | 25 ++++++ .../gvn_overlapping.copy_overlapping.GVN.diff | 19 +++++ tests/mir-opt/gvn_overlapping.rs | 17 ++++ 5 files changed, 188 insertions(+) create mode 100644 tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff create mode 100644 tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff create mode 100644 tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff diff --git a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff new file mode 100644 index 0000000000000..d17213993282a --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff @@ -0,0 +1,50 @@ +- // MIR for `deref_nonssa` before GVN ++ // MIR for `deref_nonssa` after GVN + + fn deref_nonssa() -> Single { + let mut _0: Single; + let mut _1: Single; + let mut _4: Single; + let mut _5: u8; + scope 1 { + debug a => _1; + let _2: &Single; + scope 2 { + debug b => _2; + let _3: u8; + scope 3 { + debug c => _3; + } + } + } + + bb0: { + StorageLive(_1); +- _1 = Single(const 0_u8); +- StorageLive(_2); ++ _1 = const Single(0_u8); ++ nop; + _2 = &_1; +- StorageLive(_3); ++ nop; + _3 = copy ((*_2).0: u8); + StorageLive(_4); +- _4 = Single(const 1_u8); +- _1 = move _4; ++ _4 = const Single(1_u8); ++ _1 = const Single(1_u8); + StorageDead(_4); + StorageLive(_5); + _5 = copy _3; +- _0 = Single(move _5); ++ _0 = copy (*_2); + StorageDead(_5); +- StorageDead(_3); +- StorageDead(_2); ++ nop; ++ nop; + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff new file mode 100644 index 0000000000000..64d137bfc26bd --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff @@ -0,0 +1,77 @@ +- // MIR for `deref_nonssa_2` before GVN ++ // MIR for `deref_nonssa_2` after GVN + + fn deref_nonssa_2() -> Single { + let mut _0: Single; + let mut _1: Single; + let mut _3: &Single; + let _4: &Single; + let mut _7: Single; + let mut _9: u8; + scope 1 { + debug a => _1; + let _2: SingleRef<'_>; + scope 2 { + debug r => _2; + let _5: &Single; + scope 3 { + debug b => _5; + let _6: u8; + scope 4 { + debug c => _6; + let _8: Single; + scope 5 { + debug d => _8; + } + } + } + } + } + + bb0: { + StorageLive(_1); +- _1 = Single(const 0_u8); ++ _1 = const Single(0_u8); + StorageLive(_2); +- StorageLive(_3); +- StorageLive(_4); ++ nop; ++ nop; + _4 = &_1; + _3 = &(*_4); +- _2 = SingleRef::<'_>(move _3); +- StorageDead(_3); +- StorageDead(_4); ++ _2 = SingleRef::<'_>(copy _3); ++ nop; ++ nop; + StorageLive(_5); +- _5 = copy (_2.0: &Single); +- StorageLive(_6); +- _6 = copy ((*_5).0: u8); ++ _5 = copy _3; ++ nop; ++ _6 = copy ((*_4).0: u8); + StorageLive(_7); +- _7 = Single(const 1_u8); +- _1 = move _7; ++ _7 = const Single(1_u8); ++ _1 = const Single(1_u8); + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _9 = copy _6; +- _8 = Single(move _9); ++ _8 = copy (*_4); + StorageDead(_9); + _0 = move _8; + StorageDead(_8); +- StorageDead(_6); ++ nop; + StorageDead(_5); + StorageDead(_2); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.rs b/tests/mir-opt/gvn_copy_aggregate.rs index c9473025a15f2..af1839fd3efc1 100644 --- a/tests/mir-opt/gvn_copy_aggregate.rs +++ b/tests/mir-opt/gvn_copy_aggregate.rs @@ -259,3 +259,28 @@ fn remove_storage_dead_from_index(f: fn() -> usize, v: [SameType; 5]) -> SameTyp } } } + +pub struct Single(u8); + +// EMIT_MIR gvn_copy_aggregate.deref_nonssa.GVN.diff +fn deref_nonssa() -> Single { + let mut a = Single(0); + let b = &a; + let c = (*b).0; + a = Single(1); + // GVN shouldn't replace `Single(c)` with `*b`. + Single(c) +} + +pub struct SingleRef<'a>(&'a Single); + +// EMIT_MIR gvn_copy_aggregate.deref_nonssa_2.GVN.diff +pub fn deref_nonssa_2() -> Single { + let mut a = Single(0); + let r = SingleRef(&a); + let b = r.0; + let c = (*b).0; + a = Single(1); + let d = Single(c); + d +} diff --git a/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff b/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff new file mode 100644 index 0000000000000..f13c92e4fd012 --- /dev/null +++ b/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff @@ -0,0 +1,19 @@ +- // MIR for `copy_overlapping` before GVN ++ // MIR for `copy_overlapping` after GVN + + fn copy_overlapping() -> () { + let mut _0: (); + let mut _1: Adt; + let mut _2: u32; + let mut _3: &Adt; + + bb0: { + ((_1 as variant#1).0: u32) = const 0_u32; + _3 = &_1; + _2 = copy (((*_3) as variant#1).0: u32); +- _1 = Adt::Some(copy _2); ++ _1 = copy (*_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_overlapping.rs b/tests/mir-opt/gvn_overlapping.rs index f148a84356125..a41f8ad5fd607 100644 --- a/tests/mir-opt/gvn_overlapping.rs +++ b/tests/mir-opt/gvn_overlapping.rs @@ -64,6 +64,23 @@ fn fields(_1: (Adt, Adt)) { } } +// EMIT_MIR gvn_overlapping.copy_overlapping.GVN.diff +#[custom_mir(dialect = "runtime")] +fn copy_overlapping() { + mir! { + let _1; + let _2; + let _3; + { + place!(Field(Variant(_1, 1), 0)) = 0u32; + _3 = &_1; + _2 = Field(Variant(*_3, 1), 0); + _1 = Adt::Some(_2); + Return() + } + } +} + fn main() { overlapping(Adt::Some(0)); } From e312df787dedd75d7de0962fc072ab7ed5e2343d Mon Sep 17 00:00:00 2001 From: dianqk Date: Tue, 21 Oct 2025 20:06:44 +0800 Subject: [PATCH 2/3] GVN: Remove invalidate_derefs --- compiler/rustc_middle/src/mir/terminator.rs | 22 ------------ compiler/rustc_mir_transform/src/gvn.rs | 38 +-------------------- 2 files changed, 1 insertion(+), 59 deletions(-) diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index cd447d4ed992b..cd9db451ac536 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -695,28 +695,6 @@ impl<'tcx> TerminatorKind<'tcx> { _ => None, } } - - /// Returns true if the terminator can write to memory. - pub fn can_write_to_memory(&self) -> bool { - match self { - TerminatorKind::Goto { .. } - | TerminatorKind::SwitchInt { .. } - | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Return - | TerminatorKind::Assert { .. } - | TerminatorKind::CoroutineDrop - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::Unreachable => false, - TerminatorKind::Call { .. } - | TerminatorKind::Drop { .. } - | TerminatorKind::TailCall { .. } - // Yield writes to the resume_arg place. - | TerminatorKind::Yield { .. } - | TerminatorKind::InlineAsm { .. } => true, - } - } } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 820998eed1005..164ddd40466af 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -129,7 +129,6 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let ssa = SsaLocals::new(tcx, body, typing_env); // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let maybe_loop_headers = loops::maybe_loop_headers(body); let arena = DroplessArena::default(); let mut state = @@ -142,11 +141,6 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); for bb in reverse_postorder { - // N.B. With loops, reverse postorder cannot produce a valid topological order. - // A statement or terminator from inside the loop, that is not processed yet, may have performed an indirect write. - if maybe_loop_headers.contains(bb) { - state.invalidate_derefs(); - } let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb]; state.visit_basic_block_data(bb, data); } @@ -350,12 +344,6 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> { fn ty(&self, index: VnIndex) -> Ty<'tcx> { self.types[index] } - - /// Replace the value associated with `index` with an opaque value. - #[inline] - fn forget(&mut self, index: VnIndex) { - self.values[index] = Value::Opaque(VnOpaque); - } } struct VnState<'body, 'a, 'tcx> { @@ -374,8 +362,6 @@ struct VnState<'body, 'a, 'tcx> { /// - `Some(None)` are values for which computation has failed; /// - `Some(Some(op))` are successful computations. evaluated: IndexVec>>>, - /// Cache the deref values. - derefs: Vec, ssa: &'body SsaLocals, dominators: Dominators, reused_locals: DenseBitSet, @@ -408,7 +394,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { rev_locals: IndexVec::with_capacity(num_values), values: ValueSet::new(num_values), evaluated: IndexVec::with_capacity(num_values), - derefs: Vec::new(), ssa, dominators, reused_locals: DenseBitSet::new_empty(local_decls.len()), @@ -542,15 +527,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex { - let value = self.insert(ty, Value::Projection(value, ProjectionElem::Deref)); - self.derefs.push(value); - value - } - - fn invalidate_derefs(&mut self) { - for deref in std::mem::take(&mut self.derefs) { - self.values.forget(deref); - } + self.insert(ty, Value::Projection(value, ProjectionElem::Deref)) } #[instrument(level = "trace", skip(self), ret)] @@ -1873,10 +1850,6 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { self.simplify_place_projection(place, location); - if context.is_mutating_use() && place.is_indirect() { - // Non-local mutation maybe invalidate deref. - self.invalidate_derefs(); - } self.super_place(place, context, location); } @@ -1906,11 +1879,6 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { } } - if lhs.is_indirect() { - // Non-local mutation maybe invalidate deref. - self.invalidate_derefs(); - } - if let Some(local) = lhs.as_local() && self.ssa.is_ssa(local) && let rvalue_ty = rvalue.ty(self.local_decls, self.tcx) @@ -1933,10 +1901,6 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { self.assign(local, opaque); } } - // Terminators that can write to memory may invalidate (nested) derefs. - if terminator.kind.can_write_to_memory() { - self.invalidate_derefs(); - } self.super_terminator(terminator, location); } } From c6dd1f73234595a1ad0ab52aa7b0d5eeec974a97 Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 29 Dec 2025 21:30:37 +0800 Subject: [PATCH 3/3] GVN: Do not introduce new dereferences or unify dereferences if they borrow from non-SSA locals --- compiler/rustc_mir_transform/src/gvn.rs | 107 ++++++++++--- ....dereference_reborrow.GVN.panic-abort.diff | 37 +++++ ...dereference_reborrow.GVN.panic-unwind.diff | 37 +++++ .../gvn.dereferences.GVN.panic-abort.diff | 30 ++-- .../gvn.dereferences.GVN.panic-unwind.diff | 30 ++-- .../gvn.fn_pointers.GVN.panic-abort.diff | 18 +-- .../gvn.fn_pointers.GVN.panic-unwind.diff | 18 +-- .../gvn.references.GVN.panic-abort.diff | 31 ++-- .../gvn.references.GVN.panic-unwind.diff | 31 ++-- tests/mir-opt/gvn.rs | 72 +++++---- ...xpression_elimination.GVN.panic-abort.diff | 50 +++--- ...pression_elimination.GVN.panic-unwind.diff | 50 +++--- .../gvn_copy_aggregate.all_copy_2.GVN.diff | 16 +- .../gvn_copy_aggregate.all_copy_mut.GVN.diff | 61 +++++++ .../gvn_copy_aggregate.deref_nonssa.GVN.diff | 8 +- ...gvn_copy_aggregate.deref_nonssa_2.GVN.diff | 15 +- tests/mir-opt/gvn_copy_aggregate.rs | 25 ++- .../mir-opt/gvn_loop.loop_deref_mut.GVN.diff | 24 +-- tests/mir-opt/gvn_loop.rs | 2 +- .../gvn_overlapping.copy_overlapping.GVN.diff | 3 +- .../gvn_overlapping.overlapping.GVN.diff | 4 +- tests/mir-opt/gvn_overlapping.rs | 29 ++-- ...gvn_overlapping.stable_projection.GVN.diff | 12 +- ...implifyComparisonIntegral.panic-abort.diff | 34 ++-- ...mplifyComparisonIntegral.panic-unwind.diff | 34 ++-- .../pre-codegen/deref_nested_borrows.rs | 8 + ...variant_a-{closure#0}.PreCodegen.after.mir | 150 +++++++++--------- ...variant_b-{closure#0}.PreCodegen.after.mir | 54 ++++--- ...ted_loop.PreCodegen.after.panic-unwind.mir | 5 +- 29 files changed, 639 insertions(+), 356 deletions(-) create mode 100644 tests/mir-opt/gvn.dereference_reborrow.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.dereference_reborrow.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn_copy_aggregate.all_copy_mut.GVN.diff diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 164ddd40466af..1a2c03e0f0cc4 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -135,7 +135,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls, &arena); for local in body.args_iter().filter(|&local| ssa.is_ssa(local)) { - let opaque = state.new_opaque(body.local_decls[local].ty); + let opaque = state.new_argument(body.local_decls[local].ty); state.assign(local, opaque); } @@ -198,8 +198,9 @@ enum AddressBase { enum Value<'a, 'tcx> { // Root values. /// Used to represent values we know nothing about. - /// The `usize` is a counter incremented by `new_opaque`. Opaque(VnOpaque), + /// The value is a argument. + Argument(VnOpaque), /// Evaluated or unevaluated constant value. Constant { value: Const<'tcx>, @@ -284,7 +285,7 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> { let value = value(VnOpaque); debug_assert!(match value { - Value::Opaque(_) | Value::Address { .. } => true, + Value::Opaque(_) | Value::Argument(_) | Value::Address { .. } => true, Value::Constant { disambiguator, .. } => disambiguator.is_some(), _ => false, }); @@ -440,6 +441,13 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { index } + #[instrument(level = "trace", skip(self), ret)] + fn new_argument(&mut self, ty: Ty<'tcx>) -> VnIndex { + let index = self.insert_unique(ty, Value::Argument); + self.evaluated[index] = Some(None); + index + } + /// Create a new `Value::Address` distinct from all the others. #[instrument(level = "trace", skip(self), ret)] fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind) -> Option { @@ -458,6 +466,10 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { projection.next(); AddressBase::Deref(base) } else { + // Only propagate the pointer of the SSA local. + if !self.ssa.is_ssa(place.local) { + return None; + } AddressBase::Local(place.local) }; // Do not try evaluating inside `Index`, this has been done by `simplify_place_projection`. @@ -526,10 +538,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { self.insert(ty, Value::Aggregate(VariantIdx::ZERO, self.arena.alloc_slice(values))) } - fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex { - self.insert(ty, Value::Projection(value, ProjectionElem::Deref)) - } - #[instrument(level = "trace", skip(self), ret)] fn eval_to_const_inner(&mut self, value: VnIndex) -> Option> { use Value::*; @@ -543,7 +551,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { let op = match self.get(value) { _ if ty.is_zst() => ImmTy::uninit(ty).into(), - Opaque(_) => return None, + Opaque(_) | Argument(_) => return None, // Keep runtime check constants as symbolic. RuntimeChecks(..) => return None, @@ -795,7 +803,13 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { // An immutable borrow `_x` always points to the same value for the // lifetime of the borrow, so we can merge all instances of `*_x`. - return Some((projection_ty, self.insert_deref(projection_ty.ty, value))); + return Some(( + projection_ty, + self.insert( + projection_ty.ty, + Value::Projection(value, ProjectionElem::Deref), + ), + )); } else { return None; } @@ -1014,7 +1028,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { let op = self.simplify_operand(op, location)?; Value::Repeat(op, amount) } - Rvalue::Aggregate(..) => return self.simplify_aggregate(lhs, rvalue, location), + Rvalue::Aggregate(..) => return self.simplify_aggregate(rvalue, location), Rvalue::Ref(_, borrow_kind, ref mut place) => { self.simplify_place_projection(place, location); return self.new_pointer(*place, AddressKind::Ref(borrow_kind)); @@ -1119,13 +1133,48 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } } + // We can introduce a new dereference if the source value cannot be changed in the body. + let mut copy_root = copy_from_local_value; + loop { + match self.get(copy_root) { + Value::Projection(base, _) => { + copy_root = base; + } + Value::Address { + base, + projection, + kind: AddressKind::Ref(BorrowKind::Shared), + .. + } if projection.iter().all(ProjectionElem::is_stable_offset) => match base { + AddressBase::Local(_) => { + break; + } + AddressBase::Deref(index) => { + copy_root = index; + } + }, + Value::Argument(_) if !self.ty(copy_root).is_mutable_ptr() => { + break; + } + Value::Opaque(_) => { + let ty = self.ty(copy_root); + if ty.is_fn() || !ty.is_any_ptr() { + break; + } + return None; + } + _ => { + return None; + } + } + } + // Both must be variants of the same type. if self.ty(copy_from_local_value) == ty { Some(copy_from_local_value) } else { None } } fn simplify_aggregate( &mut self, - lhs: &Place<'tcx>, rvalue: &mut Rvalue<'tcx>, location: Location, ) -> Option { @@ -1208,12 +1257,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } if let Some(value) = self.simplify_aggregate_to_copy(ty, variant_index, &fields) { - // Allow introducing places with non-constant offsets, as those are still better than - // reconstructing an aggregate. But avoid creating `*a = copy (*b)`, as they might be - // aliases resulting in overlapping assignments. - let allow_complex_projection = - lhs.projection[..].iter().all(PlaceElem::is_stable_offset); - if let Some(place) = self.try_as_place(value, location, allow_complex_projection) { + if let Some(place) = self.try_as_place(value, location, true) { self.reused_locals.insert(place.local); *rvalue = Rvalue::Use(Operand::Copy(place)); } @@ -1866,7 +1910,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { ) { self.simplify_place_projection(lhs, location); - let value = self.simplify_rvalue(lhs, rvalue, location); + let mut value = self.simplify_rvalue(lhs, rvalue, location); if let Some(value) = value { if let Some(const_) = self.try_as_constant(value) { *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); @@ -1879,9 +1923,34 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { } } + let rvalue_ty = rvalue.ty(self.local_decls, self.tcx); + // DO NOT reason the pointer value if it may point to a non-SSA local. + // For instance, we cannot unify two pointers that dereference same local, because they may + // have different lifetimes. + if rvalue_ty.is_ref() + && let Some(index) = value + { + match self.get(index) { + Value::Opaque(_) | Value::Projection(..) => { + value = None; + } + Value::Constant { .. } + | Value::Address { .. } + | Value::Argument(_) + | Value::RawPtr { .. } + | Value::BinaryOp(..) + | Value::Cast { .. } => {} + Value::Aggregate(..) + | Value::Union(..) + | Value::Repeat(..) + | Value::Discriminant(..) + | Value::RuntimeChecks(..) + | Value::UnaryOp(..) => unreachable!(), + } + } + if let Some(local) = lhs.as_local() && self.ssa.is_ssa(local) - && let rvalue_ty = rvalue.ty(self.local_decls, self.tcx) // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark // `local` as reusable if we have an exact type match. && self.local_decls[local].ty == rvalue_ty diff --git a/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-abort.diff new file mode 100644 index 0000000000000..1b2e6c681b926 --- /dev/null +++ b/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-abort.diff @@ -0,0 +1,37 @@ +- // MIR for `dereference_reborrow` before GVN ++ // MIR for `dereference_reborrow` after GVN + + fn dereference_reborrow(_1: &mut u8) -> () { + debug mut_a => _1; + let mut _0: (); + let _2: &u8; + scope 1 { + debug a => _2; + let _3: u8; + scope 2 { + debug b => _3; + let _4: u8; + scope 3 { + debug c => _4; + } + } + } + + bb0: { + StorageLive(_2); + _2 = &(*_1); +- StorageLive(_3); ++ nop; + _3 = copy (*_2); + StorageLive(_4); +- _4 = copy (*_2); ++ _4 = copy _3; + _0 = const (); + StorageDead(_4); +- StorageDead(_3); ++ nop; + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-unwind.diff new file mode 100644 index 0000000000000..1b2e6c681b926 --- /dev/null +++ b/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-unwind.diff @@ -0,0 +1,37 @@ +- // MIR for `dereference_reborrow` before GVN ++ // MIR for `dereference_reborrow` after GVN + + fn dereference_reborrow(_1: &mut u8) -> () { + debug mut_a => _1; + let mut _0: (); + let _2: &u8; + scope 1 { + debug a => _2; + let _3: u8; + scope 2 { + debug b => _3; + let _4: u8; + scope 3 { + debug c => _4; + } + } + } + + bb0: { + StorageLive(_2); + _2 = &(*_1); +- StorageLive(_3); ++ nop; + _3 = copy (*_2); + StorageLive(_4); +- _4 = copy (*_2); ++ _4 = copy _3; + _0 = const (); + StorageDead(_4); +- StorageDead(_3); ++ nop; + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff index ecd7bdc433cd9..a763614dc644b 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff @@ -107,18 +107,23 @@ StorageLive(_18); _18 = &(*_1); StorageLive(_19); - StorageLive(_20); +- StorageLive(_20); ++ nop; _20 = copy (*_18); - _19 = opaque::(move _20) -> [return: bb7, unwind unreachable]; +- _19 = opaque::(move _20) -> [return: bb7, unwind unreachable]; ++ _19 = opaque::(copy _20) -> [return: bb7, unwind unreachable]; } bb7: { - StorageDead(_20); +- StorageDead(_20); ++ nop; StorageDead(_19); StorageLive(_21); StorageLive(_22); - _22 = copy (*_18); - _21 = opaque::(move _22) -> [return: bb8, unwind unreachable]; +- _22 = copy (*_18); +- _21 = opaque::(move _22) -> [return: bb8, unwind unreachable]; ++ _22 = copy _20; ++ _21 = opaque::(copy _20) -> [return: bb8, unwind unreachable]; } bb8: { @@ -152,18 +157,23 @@ StorageDead(_28); StorageDead(_27); StorageLive(_29); - StorageLive(_30); +- StorageLive(_30); ++ nop; _30 = copy ((*_3).0: u32); - _29 = opaque::(move _30) -> [return: bb12, unwind unreachable]; +- _29 = opaque::(move _30) -> [return: bb12, unwind unreachable]; ++ _29 = opaque::(copy _30) -> [return: bb12, unwind unreachable]; } bb12: { - StorageDead(_30); +- StorageDead(_30); ++ nop; StorageDead(_29); StorageLive(_31); StorageLive(_32); - _32 = copy ((*_3).0: u32); - _31 = opaque::(move _32) -> [return: bb13, unwind unreachable]; +- _32 = copy ((*_3).0: u32); +- _31 = opaque::(move _32) -> [return: bb13, unwind unreachable]; ++ _32 = copy _30; ++ _31 = opaque::(copy _30) -> [return: bb13, unwind unreachable]; } bb13: { diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff index bbca6bc3c754d..ca6fda483642c 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff @@ -107,18 +107,23 @@ StorageLive(_18); _18 = &(*_1); StorageLive(_19); - StorageLive(_20); +- StorageLive(_20); ++ nop; _20 = copy (*_18); - _19 = opaque::(move _20) -> [return: bb7, unwind continue]; +- _19 = opaque::(move _20) -> [return: bb7, unwind continue]; ++ _19 = opaque::(copy _20) -> [return: bb7, unwind continue]; } bb7: { - StorageDead(_20); +- StorageDead(_20); ++ nop; StorageDead(_19); StorageLive(_21); StorageLive(_22); - _22 = copy (*_18); - _21 = opaque::(move _22) -> [return: bb8, unwind continue]; +- _22 = copy (*_18); +- _21 = opaque::(move _22) -> [return: bb8, unwind continue]; ++ _22 = copy _20; ++ _21 = opaque::(copy _20) -> [return: bb8, unwind continue]; } bb8: { @@ -152,18 +157,23 @@ StorageDead(_28); StorageDead(_27); StorageLive(_29); - StorageLive(_30); +- StorageLive(_30); ++ nop; _30 = copy ((*_3).0: u32); - _29 = opaque::(move _30) -> [return: bb12, unwind continue]; +- _29 = opaque::(move _30) -> [return: bb12, unwind continue]; ++ _29 = opaque::(copy _30) -> [return: bb12, unwind continue]; } bb12: { - StorageDead(_30); +- StorageDead(_30); ++ nop; StorageDead(_29); StorageLive(_31); StorageLive(_32); - _32 = copy ((*_3).0: u32); - _31 = opaque::(move _32) -> [return: bb13, unwind continue]; +- _32 = copy ((*_3).0: u32); +- _31 = opaque::(move _32) -> [return: bb13, unwind continue]; ++ _32 = copy _30; ++ _31 = opaque::(copy _30) -> [return: bb13, unwind continue]; } bb13: { diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index 90920dd0be8fd..cb5041880ca63 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:617:19: 617:21}; + let mut _9: {closure@$DIR/gvn.rs:628:19: 628:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:617:19: 617:21}; + let mut _13: {closure@$DIR/gvn.rs:628:19: 628:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:617:19: 617:21}; + let _7: {closure@$DIR/gvn.rs:628:19: 628:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:617:19: 617:21}; +- _7 = {closure@$DIR/gvn.rs:628:19: 628:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:628:19: 628:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:628:19: 628:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:628:19: 628:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:628:19: 628:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:628:19: 628:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index 0aca8e508f5c3..e404b0a124858 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:617:19: 617:21}; + let mut _9: {closure@$DIR/gvn.rs:628:19: 628:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:617:19: 617:21}; + let mut _13: {closure@$DIR/gvn.rs:628:19: 628:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:617:19: 617:21}; + let _7: {closure@$DIR/gvn.rs:628:19: 628:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:617:19: 617:21}; +- _7 = {closure@$DIR/gvn.rs:628:19: 628:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:628:19: 628:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:628:19: 628:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:628:19: 628:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:628:19: 628:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:628:19: 628:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.references.GVN.panic-abort.diff b/tests/mir-opt/gvn.references.GVN.panic-abort.diff index 62a487dee8215..ec79e98134f4e 100644 --- a/tests/mir-opt/gvn.references.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.references.GVN.panic-abort.diff @@ -112,24 +112,23 @@ bb8: { StorageDead(_17); StorageDead(_16); -- StorageLive(_18); -+ nop; + StorageLive(_18); _18 = &mut _1; StorageLive(_19); StorageLive(_20); - StorageLive(_21); -- _21 = move _18; +- StorageLive(_21); ++ nop; + _21 = move _18; - _20 = S::<&mut impl Sized>(move _21); -+ _21 = copy _18; -+ _20 = S::<&mut impl Sized>(copy _18); - StorageDead(_21); +- StorageDead(_21); - _19 = move (_20.0: &mut impl Sized); -+ _19 = copy _18; ++ _20 = S::<&mut impl Sized>(copy _21); ++ nop; ++ _19 = copy _21; StorageDead(_20); StorageLive(_22); StorageLive(_23); -- _23 = &(*_19); -+ _23 = &(*_18); + _23 = &(*_19); _22 = opaque::<&impl Sized>(move _23) -> [return: bb9, unwind unreachable]; } @@ -138,8 +137,7 @@ StorageDead(_22); StorageLive(_24); StorageLive(_25); -- _25 = &mut (*_19); -+ _25 = &mut (*_18); + _25 = &mut (*_19); _24 = opaque::<&mut impl Sized>(move _25) -> [return: bb10, unwind unreachable]; } @@ -148,8 +146,7 @@ StorageDead(_24); StorageLive(_26); StorageLive(_27); -- _27 = &raw const (*_19); -+ _27 = &raw const (*_18); + _27 = &raw const (*_19); _26 = opaque::<*const impl Sized>(move _27) -> [return: bb11, unwind unreachable]; } @@ -158,8 +155,7 @@ StorageDead(_26); StorageLive(_28); StorageLive(_29); -- _29 = &raw mut (*_19); -+ _29 = &raw mut (*_18); + _29 = &raw mut (*_19); _28 = opaque::<*mut impl Sized>(move _29) -> [return: bb12, unwind unreachable]; } @@ -168,8 +164,7 @@ StorageDead(_28); _0 = const (); StorageDead(_19); -- StorageDead(_18); -+ nop; + StorageDead(_18); drop(_1) -> [return: bb13, unwind unreachable]; } diff --git a/tests/mir-opt/gvn.references.GVN.panic-unwind.diff b/tests/mir-opt/gvn.references.GVN.panic-unwind.diff index 6dd986907fcc6..0116a454c0cd2 100644 --- a/tests/mir-opt/gvn.references.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.references.GVN.panic-unwind.diff @@ -112,24 +112,23 @@ bb8: { StorageDead(_17); StorageDead(_16); -- StorageLive(_18); -+ nop; + StorageLive(_18); _18 = &mut _1; StorageLive(_19); StorageLive(_20); - StorageLive(_21); -- _21 = move _18; +- StorageLive(_21); ++ nop; + _21 = move _18; - _20 = S::<&mut impl Sized>(move _21); -+ _21 = copy _18; -+ _20 = S::<&mut impl Sized>(copy _18); - StorageDead(_21); +- StorageDead(_21); - _19 = move (_20.0: &mut impl Sized); -+ _19 = copy _18; ++ _20 = S::<&mut impl Sized>(copy _21); ++ nop; ++ _19 = copy _21; StorageDead(_20); StorageLive(_22); StorageLive(_23); -- _23 = &(*_19); -+ _23 = &(*_18); + _23 = &(*_19); _22 = opaque::<&impl Sized>(move _23) -> [return: bb9, unwind: bb14]; } @@ -138,8 +137,7 @@ StorageDead(_22); StorageLive(_24); StorageLive(_25); -- _25 = &mut (*_19); -+ _25 = &mut (*_18); + _25 = &mut (*_19); _24 = opaque::<&mut impl Sized>(move _25) -> [return: bb10, unwind: bb14]; } @@ -148,8 +146,7 @@ StorageDead(_24); StorageLive(_26); StorageLive(_27); -- _27 = &raw const (*_19); -+ _27 = &raw const (*_18); + _27 = &raw const (*_19); _26 = opaque::<*const impl Sized>(move _27) -> [return: bb11, unwind: bb14]; } @@ -158,8 +155,7 @@ StorageDead(_26); StorageLive(_28); StorageLive(_29); -- _29 = &raw mut (*_19); -+ _29 = &raw mut (*_18); + _29 = &raw mut (*_19); _28 = opaque::<*mut impl Sized>(move _29) -> [return: bb12, unwind: bb14]; } @@ -168,8 +164,7 @@ StorageDead(_28); _0 = const (); StorageDead(_19); -- StorageDead(_18); -+ nop; + StorageDead(_18); drop(_1) -> [return: bb13, unwind: bb15]; } diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 3c3241fefe22e..d744a170d400a 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -102,11 +102,11 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { // We cannot substitute through an immutable reference. // CHECK: [[ref:_.*]] = &_3; // CHECK: [[deref:_.*]] = copy (*[[ref]]); - // CHECK: [[addref:_.*]] = Add(move [[deref]], copy _1); - // CHECK: opaque::(move [[addref]]) - // CHECK: [[deref2:_.*]] = copy (*[[ref]]); - // CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); - // CHECK: opaque::(move [[addref2]]) + // CHECK: [[addref:_.*]] = Add(copy [[deref]], copy _1); + // CHECK: opaque::(copy [[addref]]) + // CHECK: [[deref2:_.*]] = copy [[deref]]; + // CHECK: [[addref2:_.*]] = copy [[addref]]; + // CHECK: opaque::(copy [[addref]]) let a = &z; opaque(*a + x); opaque(*a + x); @@ -139,15 +139,14 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { opaque(*d + x); } - // We still cannot substitute again, and never with the earlier computations. // Important: `e` is not `a`! // CHECK: [[ref2:_.*]] = &_3; // CHECK: [[deref2:_.*]] = copy (*[[ref2]]); - // CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); - // CHECK: opaque::(move [[addref2]]) - // CHECK: [[deref3:_.*]] = copy (*[[ref2]]); - // CHECK: [[addref3:_.*]] = Add(move [[deref3]], copy _1); - // CHECK: opaque::(move [[addref3]]) + // CHECK: [[addref2:_.*]] = Add(copy [[deref2]], copy _1); + // CHECK: opaque::(copy [[addref2]]) + // CHECK: [[deref3:_.*]] = copy [[deref2]]; + // CHECK: [[addref3:_.*]] = copy [[addref2]]; + // CHECK: opaque::(copy [[addref2]]) let e = &z; opaque(*e + x); opaque(*e + x); @@ -451,20 +450,21 @@ fn references(mut x: impl Sized) { // CHECK: opaque::<*mut impl Sized>(move [[ref8]]) opaque(&raw mut x); + // FIXME: ReferencePropagation transform this pattern. let r = &mut x; let s = S(r).0; // Obfuscate `r`. Following lines should still reborrow `r`. // CHECK: [[ref9:_.*]] = &mut _1; - // CHECK: [[ref10:_.*]] = &(*[[ref9]]); - // CHECK: opaque::<&impl Sized>(move [[ref10]]) + // COM: CHECK: [[ref10:_.*]] = &(*[[ref9]]); + // COM: CHECK: opaque::<&impl Sized>(move [[ref10]]) opaque(&*s); - // CHECK: [[ref11:_.*]] = &mut (*[[ref9]]); - // CHECK: opaque::<&mut impl Sized>(move [[ref11]]) + // COM: CHECK: [[ref11:_.*]] = &mut (*[[ref9]]); + // COM: CHECK: opaque::<&mut impl Sized>(move [[ref11]]) opaque(&mut *s); - // CHECK: [[ref12:_.*]] = &raw const (*[[ref9]]); - // CHECK: opaque::<*const impl Sized>(move [[ref12]]) + // COM: CHECK: [[ref12:_.*]] = &raw const (*[[ref9]]); + // COM: CHECK: opaque::<*const impl Sized>(move [[ref12]]) opaque(&raw const *s); - // CHECK: [[ref12:_.*]] = &raw mut (*[[ref9]]); - // CHECK: opaque::<*mut impl Sized>(move [[ref12]]) + // COM: CHECK: [[ref12:_.*]] = &raw mut (*[[ref9]]); + // COM: CHECK: opaque::<*mut impl Sized>(move [[ref12]]) opaque(&raw mut *s); } @@ -472,17 +472,21 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { // CHECK-LABEL: fn dereferences( // Do not reuse dereferences of `&mut`. + // CHECK: bb0: // CHECK: [[st1:_.*]] = copy (*_1); // CHECK: opaque::(move [[st1]]) + // CHECK: bb1: // CHECK: [[st2:_.*]] = copy (*_1); // CHECK: opaque::(move [[st2]]) opaque(*t); opaque(*t); // Do not reuse dereferences of `*const`. + // CHECK: bb2: // CHECK: [[raw:_.*]] = &raw const (*_1); // CHECK: [[st3:_.*]] = copy (*[[raw]]); // CHECK: opaque::(move [[st3]]) + // CHECK: bb3: // CHECK: [[st4:_.*]] = copy (*[[raw]]); // CHECK: opaque::(move [[st4]]) let z = &raw const *t; @@ -490,42 +494,49 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { unsafe { opaque(*z) }; // Do not reuse dereferences of `*mut`. + // CHECK: bb4: // CHECK: [[ptr:_.*]] = &raw mut (*_1); // CHECK: [[st5:_.*]] = copy (*[[ptr]]); // CHECK: opaque::(move [[st5]]) + // CHECK: bb5: // CHECK: [[st6:_.*]] = copy (*[[ptr]]); // CHECK: opaque::(move [[st6]]) let z = &raw mut *t; unsafe { opaque(*z) }; unsafe { opaque(*z) }; - // Do not reuse dereferences of `&Freeze`. + // CHECK: bb6: // CHECK: [[ref:_.*]] = &(*_1); // CHECK: [[st7:_.*]] = copy (*[[ref]]); - // CHECK: opaque::(move [[st7]]) - // CHECK: [[st8:_.*]] = copy (*[[ref]]); - // CHECK: opaque::(move [[st8]]) + // CHECK: opaque::(copy [[st7]]) + // CHECK: bb7: + // CHECK: [[st8:_.*]] = copy [[st7]]; + // CHECK: opaque::(copy [[st7]]) let z = &*t; opaque(*z); opaque(*z); // Not in reborrows either. + // CHECK: bb8: // CHECK: [[reborrow:_.*]] = &(*[[ref]]); // CHECK: opaque::<&u32>(move [[reborrow]]) opaque(&*z); // `*u` is not Freeze, so we cannot reuse. + // CHECK: bb9: // CHECK: [[st8:_.*]] = copy (*_2); // CHECK: opaque::(move [[st8]]) + // CHECK: bb10: // CHECK: [[st9:_.*]] = copy (*_2); // CHECK: opaque::(move [[st9]]) opaque(*u); opaque(*u); - // `*s` is not Copy, but `(*s).0` is, but we still cannot reuse. + // CHECK: bb11: // CHECK: [[st10:_.*]] = copy ((*_3).0: u32); - // CHECK: opaque::(move [[st10]]) - // CHECK: [[st11:_.*]] = copy ((*_3).0: u32); - // CHECK: opaque::(move [[st11]]) + // CHECK: opaque::(copy [[st10]]) + // CHECK: bb12: + // CHECK: [[st11:_.*]] = copy [[st10]]; + // CHECK: opaque::(copy [[st10]]) opaque(s.0); opaque(s.0); } @@ -1071,6 +1082,13 @@ fn dereference_indexing(array: [u8; 2], index: usize) { opaque(*a); } +// EMIT_MIR gvn.dereference_reborrow.GVN.diff +fn dereference_reborrow(mut_a: &mut u8) { + let a = &*mut_a; + let b = *a; + let c = *a; +} + // CHECK-LABEL: fn main( fn main() { subexpression_elimination(2, 4, 5); diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff index e872e011542b3..7a479bc55da75 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff @@ -758,32 +758,39 @@ StorageLive(_126); _126 = &_3; StorageLive(_127); - StorageLive(_128); - StorageLive(_129); +- StorageLive(_128); +- StorageLive(_129); ++ nop; ++ nop; _129 = copy (*_126); StorageLive(_130); _130 = copy _1; - _128 = Add(move _129, move _130); -+ _128 = Add(move _129, copy _1); ++ _128 = Add(copy _129, copy _1); StorageDead(_130); - StorageDead(_129); - _127 = opaque::(move _128) -> [return: bb35, unwind unreachable]; +- StorageDead(_129); +- _127 = opaque::(move _128) -> [return: bb35, unwind unreachable]; ++ nop; ++ _127 = opaque::(copy _128) -> [return: bb35, unwind unreachable]; } bb35: { - StorageDead(_128); +- StorageDead(_128); ++ nop; StorageDead(_127); StorageLive(_131); StorageLive(_132); StorageLive(_133); - _133 = copy (*_126); +- _133 = copy (*_126); ++ _133 = copy _129; StorageLive(_134); _134 = copy _1; - _132 = Add(move _133, move _134); -+ _132 = Add(move _133, copy _1); ++ _132 = copy _128; StorageDead(_134); StorageDead(_133); - _131 = opaque::(move _132) -> [return: bb36, unwind unreachable]; +- _131 = opaque::(move _132) -> [return: bb36, unwind unreachable]; ++ _131 = opaque::(copy _128) -> [return: bb36, unwind unreachable]; } bb36: { @@ -899,32 +906,39 @@ StorageLive(_163); _163 = &_3; StorageLive(_164); - StorageLive(_165); - StorageLive(_166); +- StorageLive(_165); +- StorageLive(_166); ++ nop; ++ nop; _166 = copy (*_163); StorageLive(_167); _167 = copy _1; - _165 = Add(move _166, move _167); -+ _165 = Add(move _166, copy _1); ++ _165 = Add(copy _166, copy _1); StorageDead(_167); - StorageDead(_166); - _164 = opaque::(move _165) -> [return: bb43, unwind unreachable]; +- StorageDead(_166); +- _164 = opaque::(move _165) -> [return: bb43, unwind unreachable]; ++ nop; ++ _164 = opaque::(copy _165) -> [return: bb43, unwind unreachable]; } bb43: { - StorageDead(_165); +- StorageDead(_165); ++ nop; StorageDead(_164); StorageLive(_168); StorageLive(_169); StorageLive(_170); - _170 = copy (*_163); +- _170 = copy (*_163); ++ _170 = copy _166; StorageLive(_171); _171 = copy _1; - _169 = Add(move _170, move _171); -+ _169 = Add(move _170, copy _1); ++ _169 = copy _165; StorageDead(_171); StorageDead(_170); - _168 = opaque::(move _169) -> [return: bb44, unwind unreachable]; +- _168 = opaque::(move _169) -> [return: bb44, unwind unreachable]; ++ _168 = opaque::(copy _165) -> [return: bb44, unwind unreachable]; } bb44: { diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff index 3996dab27a343..3ca5238663c28 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff @@ -758,32 +758,39 @@ StorageLive(_126); _126 = &_3; StorageLive(_127); - StorageLive(_128); - StorageLive(_129); +- StorageLive(_128); +- StorageLive(_129); ++ nop; ++ nop; _129 = copy (*_126); StorageLive(_130); _130 = copy _1; - _128 = Add(move _129, move _130); -+ _128 = Add(move _129, copy _1); ++ _128 = Add(copy _129, copy _1); StorageDead(_130); - StorageDead(_129); - _127 = opaque::(move _128) -> [return: bb35, unwind continue]; +- StorageDead(_129); +- _127 = opaque::(move _128) -> [return: bb35, unwind continue]; ++ nop; ++ _127 = opaque::(copy _128) -> [return: bb35, unwind continue]; } bb35: { - StorageDead(_128); +- StorageDead(_128); ++ nop; StorageDead(_127); StorageLive(_131); StorageLive(_132); StorageLive(_133); - _133 = copy (*_126); +- _133 = copy (*_126); ++ _133 = copy _129; StorageLive(_134); _134 = copy _1; - _132 = Add(move _133, move _134); -+ _132 = Add(move _133, copy _1); ++ _132 = copy _128; StorageDead(_134); StorageDead(_133); - _131 = opaque::(move _132) -> [return: bb36, unwind continue]; +- _131 = opaque::(move _132) -> [return: bb36, unwind continue]; ++ _131 = opaque::(copy _128) -> [return: bb36, unwind continue]; } bb36: { @@ -899,32 +906,39 @@ StorageLive(_163); _163 = &_3; StorageLive(_164); - StorageLive(_165); - StorageLive(_166); +- StorageLive(_165); +- StorageLive(_166); ++ nop; ++ nop; _166 = copy (*_163); StorageLive(_167); _167 = copy _1; - _165 = Add(move _166, move _167); -+ _165 = Add(move _166, copy _1); ++ _165 = Add(copy _166, copy _1); StorageDead(_167); - StorageDead(_166); - _164 = opaque::(move _165) -> [return: bb43, unwind continue]; +- StorageDead(_166); +- _164 = opaque::(move _165) -> [return: bb43, unwind continue]; ++ nop; ++ _164 = opaque::(copy _165) -> [return: bb43, unwind continue]; } bb43: { - StorageDead(_165); +- StorageDead(_165); ++ nop; StorageDead(_164); StorageLive(_168); StorageLive(_169); StorageLive(_170); - _170 = copy (*_163); +- _170 = copy (*_163); ++ _170 = copy _166; StorageLive(_171); _171 = copy _1; - _169 = Add(move _170, move _171); -+ _169 = Add(move _170, copy _1); ++ _169 = copy _165; StorageDead(_171); StorageDead(_170); - _168 = opaque::(move _169) -> [return: bb44, unwind continue]; +- _168 = opaque::(move _169) -> [return: bb44, unwind continue]; ++ _168 = opaque::(copy _165) -> [return: bb44, unwind continue]; } bb44: { diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff index eed8cb7d62e70..2eeeff56cc778 100644 --- a/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff @@ -29,17 +29,13 @@ _8 = copy (*_1); _2 = copy ((*_8).0: i32); - StorageLive(_3); -- _9 = copy (*_1); -- _3 = copy ((*_9).1: u64); -- StorageLive(_4); -- _10 = copy (*_1); -- _4 = copy ((*_10).2: [i8; 3]); + nop; -+ _9 = copy _8; -+ _3 = copy ((*_8).1: u64); + _9 = copy (*_1); + _3 = copy ((*_9).1: u64); +- StorageLive(_4); + nop; -+ _10 = copy _8; -+ _4 = copy ((*_8).2: [i8; 3]); + _10 = copy (*_1); + _4 = copy ((*_10).2: [i8; 3]); StorageLive(_5); _5 = copy _2; StorageLive(_6); @@ -47,7 +43,7 @@ StorageLive(_7); _7 = copy _4; - _0 = AllCopy { a: move _5, b: move _6, c: move _7 }; -+ _0 = copy (*_8); ++ _0 = AllCopy { a: copy _2, b: copy _3, c: copy _4 }; StorageDead(_7); StorageDead(_6); StorageDead(_5); diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_mut.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_mut.GVN.diff new file mode 100644 index 0000000000000..92c9db1b3d79a --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_mut.GVN.diff @@ -0,0 +1,61 @@ +- // MIR for `all_copy_mut` before GVN ++ // MIR for `all_copy_mut` after GVN + + fn all_copy_mut(_1: &mut AllCopy) -> AllCopy { + debug mut_v => _1; + let mut _0: AllCopy; + let _2: &AllCopy; + let mut _6: i32; + let mut _7: u64; + let mut _8: [i8; 3]; + scope 1 { + debug v => _2; + let _3: i32; + scope 2 { + debug a => _3; + let _4: u64; + scope 3 { + debug b => _4; + let _5: [i8; 3]; + scope 4 { + debug c => _5; + } + } + } + } + + bb0: { + StorageLive(_2); + _2 = &(*_1); +- StorageLive(_3); ++ nop; + _3 = copy ((*_2).0: i32); +- StorageLive(_4); ++ nop; + _4 = copy ((*_2).1: u64); +- StorageLive(_5); ++ nop; + _5 = copy ((*_2).2: [i8; 3]); + ((*_1).0: i32) = const 0_i32; + StorageLive(_6); + _6 = copy _3; + StorageLive(_7); + _7 = copy _4; + StorageLive(_8); + _8 = copy _5; +- _0 = AllCopy { a: move _6, b: move _7, c: move _8 }; ++ _0 = AllCopy { a: copy _3, b: copy _4, c: copy _5 }; + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); +- StorageDead(_5); +- StorageDead(_4); +- StorageDead(_3); ++ nop; ++ nop; ++ nop; + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff index d17213993282a..d9707e40c0bda 100644 --- a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff +++ b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff @@ -21,9 +21,8 @@ bb0: { StorageLive(_1); - _1 = Single(const 0_u8); -- StorageLive(_2); + _1 = const Single(0_u8); -+ nop; + StorageLive(_2); _2 = &_1; - StorageLive(_3); + nop; @@ -37,12 +36,11 @@ StorageLive(_5); _5 = copy _3; - _0 = Single(move _5); -+ _0 = copy (*_2); ++ _0 = Single(copy _3); StorageDead(_5); - StorageDead(_3); -- StorageDead(_2); -+ nop; + nop; + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff index 64d137bfc26bd..2aa8d23aae944 100644 --- a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff +++ b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff @@ -7,7 +7,7 @@ let mut _3: &Single; let _4: &Single; let mut _7: Single; - let mut _9: u8; + let mut _8: u8; scope 1 { debug a => _1; let _2: SingleRef<'_>; @@ -19,10 +19,6 @@ let _6: u8; scope 4 { debug c => _6; - let _8: Single; - scope 5 { - debug d => _8; - } } } } @@ -59,12 +55,9 @@ + _1 = const Single(1_u8); StorageDead(_7); StorageLive(_8); - StorageLive(_9); - _9 = copy _6; -- _8 = Single(move _9); -+ _8 = copy (*_4); - StorageDead(_9); - _0 = move _8; + _8 = copy _6; +- _0 = Single(move _8); ++ _0 = Single(copy _6); StorageDead(_8); - StorageDead(_6); + nop; diff --git a/tests/mir-opt/gvn_copy_aggregate.rs b/tests/mir-opt/gvn_copy_aggregate.rs index af1839fd3efc1..f7974c761d77e 100644 --- a/tests/mir-opt/gvn_copy_aggregate.rs +++ b/tests/mir-opt/gvn_copy_aggregate.rs @@ -24,13 +24,25 @@ fn all_copy(v: &AllCopy) -> AllCopy { AllCopy { a, b, c } } +// EMIT_MIR gvn_copy_aggregate.all_copy_mut.GVN.diff +fn all_copy_mut(mut_v: &mut AllCopy) -> AllCopy { + // CHECK-LABEL: fn all_copy_mut( + // CHECK: = AllCopy { {{.*}} }; + // CHECK-NOT: _0 = copy ({{.*}}); + let v = &*mut_v; + let a = v.a; + let b = v.b; + let c = v.c; + mut_v.a = 0; + AllCopy { a, b, c } +} + +// FIXME: For nested references, we need knowing each borrows can be merged. // EMIT_MIR gvn_copy_aggregate.all_copy_2.GVN.diff fn all_copy_2(v: &&AllCopy) -> AllCopy { // CHECK-LABEL: fn all_copy_2( // CHECK: bb0: { - // CHECK-NOT: = AllCopy { {{.*}} }; - // CHECK: [[V1:_.*]] = copy (*_1); - // CHECK: _0 = copy (*[[V1]]); + // CHECK: _0 = AllCopy { {{.*}} }; let a = v.a; let b = v.b; let c = v.c; @@ -264,6 +276,8 @@ pub struct Single(u8); // EMIT_MIR gvn_copy_aggregate.deref_nonssa.GVN.diff fn deref_nonssa() -> Single { + // CHECK-LABEL: fn deref_nonssa( + // CHECK: _0 = Single(copy {{.*}}); let mut a = Single(0); let b = &a; let c = (*b).0; @@ -276,11 +290,12 @@ pub struct SingleRef<'a>(&'a Single); // EMIT_MIR gvn_copy_aggregate.deref_nonssa_2.GVN.diff pub fn deref_nonssa_2() -> Single { + // CHECK-LABEL: fn deref_nonssa_2( + // CHECK: _0 = Single(copy {{.*}}); let mut a = Single(0); let r = SingleRef(&a); let b = r.0; let c = (*b).0; a = Single(1); - let d = Single(c); - d + Single(c) } diff --git a/tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff b/tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff index e5d719cf3ca99..589cfd2a3cf12 100644 --- a/tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff +++ b/tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff @@ -17,7 +17,7 @@ let mut _15: !; let mut _16: Value; scope 1 { - debug val_alias => _2; + debug val_alias => _3; let mut _5: bool; scope 2 { debug stop => _5; @@ -33,23 +33,16 @@ } bb0: { - StorageLive(_2); -- StorageLive(_3); -+ nop; StorageLive(_4); _4 = &(*_1); - _3 = get::(move _4) -> [return: bb1, unwind unreachable]; + _3 = get::(copy _4) -> [return: bb1, unwind unreachable]; } bb1: { - _2 = &(*_3); StorageDead(_4); -- StorageDead(_3); -+ nop; StorageLive(_5); _5 = const false; -- _8 = discriminant((*_2)); -+ _8 = discriminant((*_3)); + _8 = discriminant((*_3)); switchInt(move _8) -> [0: bb3, otherwise: bb2]; } @@ -59,10 +52,8 @@ bb3: { - StorageLive(_7); -- _7 = copy (((*_2) as V0).0: i32); + nop; -+ _7 = copy (((*_3) as V0).0: i32); - StorageLive(_9); + _7 = copy (((*_3) as V0).0: i32); goto -> bb4; } @@ -73,7 +64,6 @@ - _11 = Value::V0(move _12); + _11 = Value::V0(copy _7); StorageDead(_12); - StorageLive(_13); StorageLive(_14); _14 = copy _5; switchInt(move _14) -> [0: bb6, otherwise: bb5]; @@ -82,20 +72,15 @@ bb5: { _0 = move _11; StorageDead(_14); - StorageDead(_13); StorageDead(_11); - StorageDead(_9); - StorageDead(_7); + nop; StorageDead(_5); - StorageDead(_2); return; } bb6: { - _13 = const (); StorageDead(_14); - StorageDead(_13); _5 = const true; StorageLive(_16); - _16 = Value::V1; @@ -103,7 +88,6 @@ + _16 = const Value::V1; + (*_1) = const Value::V1; StorageDead(_16); - _10 = const (); StorageDead(_11); goto -> bb4; } diff --git a/tests/mir-opt/gvn_loop.rs b/tests/mir-opt/gvn_loop.rs index ce23f7930f1b1..d51baf46302f6 100644 --- a/tests/mir-opt/gvn_loop.rs +++ b/tests/mir-opt/gvn_loop.rs @@ -1,5 +1,5 @@ //@ test-mir-pass: GVN -//@ compile-flags: -Zdump-mir-exclude-alloc-bytes +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes -Zmir-enable-passes=+ReferencePropagation #![crate_type = "lib"] #![feature(core_intrinsics, rustc_attrs)] diff --git a/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff b/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff index f13c92e4fd012..7b7537bc9b40e 100644 --- a/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff +++ b/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff @@ -11,8 +11,7 @@ ((_1 as variant#1).0: u32) = const 0_u32; _3 = &_1; _2 = copy (((*_3) as variant#1).0: u32); -- _1 = Adt::Some(copy _2); -+ _1 = copy (*_3); + _1 = Adt::Some(copy _2); return; } } diff --git a/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff b/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff index fcabcdbcfef2c..efebdf53c292a 100644 --- a/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff +++ b/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff @@ -3,12 +3,12 @@ fn overlapping(_1: Adt) -> () { let mut _0: (); - let mut _2: *mut Adt; + let mut _2: &mut Adt; let mut _3: u32; let mut _4: &Adt; bb0: { - _2 = &raw mut _1; + _2 = &mut _1; _4 = &(*_2); _3 = copy (((*_4) as variant#1).0: u32); (*_2) = Adt::Some(copy _3); diff --git a/tests/mir-opt/gvn_overlapping.rs b/tests/mir-opt/gvn_overlapping.rs index a41f8ad5fd607..bd93787cb483f 100644 --- a/tests/mir-opt/gvn_overlapping.rs +++ b/tests/mir-opt/gvn_overlapping.rs @@ -7,19 +7,19 @@ use std::intrinsics::mir::*; // EMIT_MIR gvn_overlapping.overlapping.GVN.diff /// Check that we do not create overlapping assignments. #[custom_mir(dialect = "runtime")] -fn overlapping(_17: Adt) { +fn overlapping(_1: Adt) { // CHECK-LABEL: fn overlapping( - // CHECK: let mut [[PTR:.*]]: *mut Adt; + // CHECK: let mut [[PTR:.*]]: &mut Adt; // CHECK: (*[[PTR]]) = Adt::Some(copy {{.*}}); mir! { - let _33: *mut Adt; - let _48: u32; - let _73: &Adt; + let _2: &mut Adt; + let _3: u32; + let _4: &Adt; { - _33 = core::ptr::addr_of_mut!(_17); - _73 = &(*_33); - _48 = Field(Variant((*_73), 1), 0); - (*_33) = Adt::Some(_48); + _2 = &mut _1; + _4 = &(*_2); + _3 = Field(Variant((*_4), 1), 0); + (*_2) = Adt::Some(_3); Return() } } @@ -30,18 +30,19 @@ fn overlapping(_17: Adt) { #[custom_mir(dialect = "runtime")] fn stable_projection(_1: (Adt,)) { // CHECK-LABEL: fn stable_projection( - // CHECK: let mut _2: *mut Adt; + // CHECK: let mut _2: &Adt; // CHECK: let mut _4: &Adt; - // CHECK: (_1.0: Adt) = copy (*_4); + // CHECK: (_5.0: Adt) = copy (_1.0: Adt); mir! { - let _2: *mut Adt; + let _2: &Adt; let _3: u32; let _4: &Adt; + let _5: (Adt,); { - _2 = core::ptr::addr_of_mut!(_1.0); + _2 = &_1.0; _4 = &(*_2); _3 = Field(Variant((*_4), 1), 0); - _1.0 = Adt::Some(_3); + _5.0 = Adt::Some(_3); Return() } } diff --git a/tests/mir-opt/gvn_overlapping.stable_projection.GVN.diff b/tests/mir-opt/gvn_overlapping.stable_projection.GVN.diff index 0883545659113..b5353b7abde78 100644 --- a/tests/mir-opt/gvn_overlapping.stable_projection.GVN.diff +++ b/tests/mir-opt/gvn_overlapping.stable_projection.GVN.diff @@ -3,16 +3,18 @@ fn stable_projection(_1: (Adt,)) -> () { let mut _0: (); - let mut _2: *mut Adt; + let mut _2: &Adt; let mut _3: u32; let mut _4: &Adt; + let mut _5: (Adt,); bb0: { - _2 = &raw mut (_1.0: Adt); + _2 = &(_1.0: Adt); _4 = &(*_2); - _3 = copy (((*_4) as variant#1).0: u32); -- (_1.0: Adt) = Adt::Some(copy _3); -+ (_1.0: Adt) = copy (*_4); +- _3 = copy (((*_4) as variant#1).0: u32); +- (_5.0: Adt) = Adt::Some(copy _3); ++ _3 = copy (((_1.0: Adt) as variant#1).0: u32); ++ (_5.0: Adt) = copy (_1.0: Adt); return; } } diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff index 614d9ad440d20..a91bdd85d899e 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff @@ -5,38 +5,44 @@ debug x => _1; let mut _0: (); let _2: &[T]; - let _3: &[T; 3]; - let _4: [T; 3]; - let mut _8: !; + let mut _3: &[T; 3]; + let _4: &[T; 3]; + let _5: [T; 3]; + let mut _9: !; scope 1 { debug v => _2; - let _5: &T; let _6: &T; let _7: &T; + let _8: &T; scope 2 { - debug v1 => _5; - debug v2 => _6; - debug v3 => _7; + debug v1 => _6; + debug v2 => _7; + debug v3 => _8; } } bb0: { + StorageLive(_3); StorageLive(_4); - _4 = [copy _1, copy _1, copy _1]; - _3 = &_4; + StorageLive(_5); + _5 = [copy _1, copy _1, copy _1]; + _4 = &_5; + _3 = copy _4; _2 = copy _3 as &[T] (PointerCoercion(Unsize, Implicit)); + StorageDead(_3); + StorageDead(_4); goto -> bb2; } bb1: { - _8 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable; + _9 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable; } bb2: { - // DBG: _5 = &(*_2)[0 of 3]; - // DBG: _6 = &(*_2)[1 of 3]; - // DBG: _7 = &(*_2)[2 of 3]; - StorageDead(_4); + // DBG: _6 = &(*_2)[0 of 3]; + // DBG: _7 = &(*_2)[1 of 3]; + // DBG: _8 = &(*_2)[2 of 3]; + StorageDead(_5); return; } } diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff index 57a88cf898412..aef3712d463a7 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff @@ -5,38 +5,44 @@ debug x => _1; let mut _0: (); let _2: &[T]; - let _3: &[T; 3]; - let _4: [T; 3]; - let mut _8: !; + let mut _3: &[T; 3]; + let _4: &[T; 3]; + let _5: [T; 3]; + let mut _9: !; scope 1 { debug v => _2; - let _5: &T; let _6: &T; let _7: &T; + let _8: &T; scope 2 { - debug v1 => _5; - debug v2 => _6; - debug v3 => _7; + debug v1 => _6; + debug v2 => _7; + debug v3 => _8; } } bb0: { + StorageLive(_3); StorageLive(_4); - _4 = [copy _1, copy _1, copy _1]; - _3 = &_4; + StorageLive(_5); + _5 = [copy _1, copy _1, copy _1]; + _4 = &_5; + _3 = copy _4; _2 = copy _3 as &[T] (PointerCoercion(Unsize, Implicit)); + StorageDead(_3); + StorageDead(_4); goto -> bb2; } bb1: { - _8 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue; + _9 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue; } bb2: { - // DBG: _5 = &(*_2)[0 of 3]; - // DBG: _6 = &(*_2)[1 of 3]; - // DBG: _7 = &(*_2)[2 of 3]; - StorageDead(_4); + // DBG: _6 = &(*_2)[0 of 3]; + // DBG: _7 = &(*_2)[1 of 3]; + // DBG: _8 = &(*_2)[2 of 3]; + StorageDead(_5); return; } } diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs index 738cd981ae674..23ad0189a66de 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs @@ -2,6 +2,14 @@ fn src(x: &&u8) -> bool { // CHECK-LABEL: fn src( + // CHECK: debug y => [[Y:_.*]]; + // CHECK: bb0: + // CHECK: [[BORROW_u8:_.*]] = copy (*_1); + // CHECK: [[Y]] = copy (*[[BORROW_u8]]); + // CHECK: bb1: + // BORROW_u8 outside its lifetime in bb1. + // CHECK-NOT: copy (*[[BORROW_u8]]); + // CHECK: copy (*_1); // CHECK-NOT: _0 = const true; // CHECK: _0 = Eq({{.*}}, {{.*}}); // CHECK-NOT: _0 = const true; diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index 2cab88182962f..afac0d23115e6 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -3,101 +3,107 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2: &&(usize, usize, usize, usize)) -> bool { let mut _0: bool; let mut _3: &(usize, usize, usize, usize); - let mut _6: bool; + let mut _4: &(usize, usize, usize, usize); + let mut _5: &(usize, usize, usize, usize); + let mut _6: &(usize, usize, usize, usize); let mut _9: bool; - let mut _10: bool; - let _13: &usize; - let _14: &usize; - let _15: &usize; + let mut _12: bool; + let mut _13: bool; let _16: &usize; - let mut _17: &&usize; - let mut _18: &&usize; - let mut _19: &&usize; + let _17: &usize; + let _18: &usize; + let _19: &usize; let mut _20: &&usize; let mut _21: &&usize; let mut _22: &&usize; let mut _23: &&usize; let mut _24: &&usize; + let mut _25: &&usize; + let mut _26: &&usize; + let mut _27: &&usize; scope 1 { - debug a => _13; - debug b => _14; - debug c => _15; - debug d => _16; + debug a => _16; + debug b => _17; + debug c => _18; + debug d => _19; scope 2 (inlined std::cmp::impls::::le) { - debug self => _17; - debug other => _18; + debug self => _20; + debug other => _21; scope 3 (inlined std::cmp::impls::::le) { - debug self => _13; - debug other => _15; - let mut _4: usize; - let mut _5: usize; + debug self => _16; + debug other => _18; + let mut _7: usize; + let mut _8: usize; } } scope 4 (inlined std::cmp::impls::::le) { - debug self => _19; - debug other => _20; + debug self => _22; + debug other => _23; scope 5 (inlined std::cmp::impls::::le) { - debug self => _16; - debug other => _14; - let mut _7: usize; - let mut _8: usize; + debug self => _19; + debug other => _17; + let mut _10: usize; + let mut _11: usize; } } scope 6 (inlined std::cmp::impls::::le) { - debug self => _21; - debug other => _22; + debug self => _24; + debug other => _25; scope 7 (inlined std::cmp::impls::::le) { - debug self => _15; - debug other => _13; + debug self => _18; + debug other => _16; } } scope 8 (inlined std::cmp::impls::::le) { - debug self => _23; - debug other => _24; + debug self => _26; + debug other => _27; scope 9 (inlined std::cmp::impls::::le) { - debug self => _14; - debug other => _16; - let mut _11: usize; - let mut _12: usize; + debug self => _17; + debug other => _19; + let mut _14: usize; + let mut _15: usize; } } } bb0: { _3 = copy (*_2); - // DBG: _13 = &((*_3).0: usize); - // DBG: _14 = &((*_3).1: usize); - // DBG: _15 = &((*_3).2: usize); - // DBG: _16 = &((*_3).3: usize); - StorageLive(_6); - // DBG: _17 = &_13; - // DBG: _18 = &?; - _4 = copy ((*_3).0: usize); - _5 = copy ((*_3).2: usize); - _6 = Le(copy _4, copy _5); - switchInt(move _6) -> [0: bb2, otherwise: bb1]; + // DBG: _16 = &((*_3).0: usize); + _4 = copy (*_2); + // DBG: _17 = &((*_4).1: usize); + _5 = copy (*_2); + // DBG: _18 = &((*_5).2: usize); + _6 = copy (*_2); + // DBG: _19 = &((*_6).3: usize); + StorageLive(_9); + // DBG: _20 = &_16; + // DBG: _21 = &?; + _7 = copy ((*_3).0: usize); + _8 = copy ((*_5).2: usize); + _9 = Le(copy _7, copy _8); + switchInt(move _9) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageLive(_9); - // DBG: _19 = &_16; - // DBG: _20 = &?; - StorageLive(_7); - _7 = copy ((*_3).3: usize); - StorageLive(_8); - _8 = copy ((*_3).1: usize); - _9 = Le(move _7, move _8); - StorageDead(_8); - StorageDead(_7); - switchInt(move _9) -> [0: bb2, otherwise: bb6]; + StorageLive(_12); + // DBG: _22 = &_19; + // DBG: _23 = &?; + StorageLive(_10); + _10 = copy ((*_6).3: usize); + StorageLive(_11); + _11 = copy ((*_4).1: usize); + _12 = Le(move _10, move _11); + StorageDead(_11); + StorageDead(_10); + switchInt(move _12) -> [0: bb2, otherwise: bb6]; } bb2: { - StorageLive(_10); - // DBG: _21 = &_15; - // DBG: _22 = &?; - _10 = Le(copy _5, copy _4); - switchInt(move _10) -> [0: bb3, otherwise: bb4]; + StorageLive(_13); + // DBG: _24 = &_18; + // DBG: _25 = &?; + _13 = Le(copy _8, copy _7); + switchInt(move _13) -> [0: bb3, otherwise: bb4]; } bb3: { @@ -106,20 +112,20 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 } bb4: { - // DBG: _23 = &_14; - // DBG: _24 = &?; - StorageLive(_11); - _11 = copy ((*_3).1: usize); - StorageLive(_12); - _12 = copy ((*_3).3: usize); - _0 = Le(move _11, move _12); - StorageDead(_12); - StorageDead(_11); + // DBG: _26 = &_17; + // DBG: _27 = &?; + StorageLive(_14); + _14 = copy ((*_4).1: usize); + StorageLive(_15); + _15 = copy ((*_6).3: usize); + _0 = Le(move _14, move _15); + StorageDead(_15); + StorageDead(_14); goto -> bb5; } bb5: { - StorageDead(_10); + StorageDead(_13); goto -> bb7; } @@ -129,8 +135,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 } bb7: { + StorageDead(_12); StorageDead(_9); - StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir index bc7a31d52199b..f93f7264dec20 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir @@ -4,40 +4,46 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: usize; - let _5: usize; + let mut _5: &(usize, usize, usize, usize); let _6: usize; - let _7: usize; - let mut _8: bool; - let mut _9: bool; - let mut _10: bool; + let mut _7: &(usize, usize, usize, usize); + let _8: usize; + let mut _9: &(usize, usize, usize, usize); + let _10: usize; + let mut _11: bool; + let mut _12: bool; + let mut _13: bool; scope 1 { debug a => _4; - debug b => _5; - debug c => _6; - debug d => _7; + debug b => _6; + debug c => _8; + debug d => _10; } bb0: { _3 = copy (*_2); _4 = copy ((*_3).0: usize); - _5 = copy ((*_3).1: usize); - _6 = copy ((*_3).2: usize); - _7 = copy ((*_3).3: usize); - StorageLive(_8); - _8 = Le(copy _4, copy _6); - switchInt(move _8) -> [0: bb2, otherwise: bb1]; + _5 = copy (*_2); + _6 = copy ((*_5).1: usize); + _7 = copy (*_2); + _8 = copy ((*_7).2: usize); + _9 = copy (*_2); + _10 = copy ((*_9).3: usize); + StorageLive(_11); + _11 = Le(copy _4, copy _8); + switchInt(move _11) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageLive(_9); - _9 = Le(copy _7, copy _5); - switchInt(move _9) -> [0: bb2, otherwise: bb6]; + StorageLive(_12); + _12 = Le(copy _10, copy _6); + switchInt(move _12) -> [0: bb2, otherwise: bb6]; } bb2: { - StorageLive(_10); - _10 = Le(copy _6, copy _4); - switchInt(move _10) -> [0: bb3, otherwise: bb4]; + StorageLive(_13); + _13 = Le(copy _8, copy _4); + switchInt(move _13) -> [0: bb3, otherwise: bb4]; } bb3: { @@ -46,12 +52,12 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb4: { - _0 = Le(copy _5, copy _7); + _0 = Le(copy _6, copy _10); goto -> bb5; } bb5: { - StorageDead(_10); + StorageDead(_13); goto -> bb7; } @@ -61,8 +67,8 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb7: { - StorageDead(_9); - StorageDead(_8); + StorageDead(_12); + StorageDead(_11); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 28b12cdf36755..ef27e0df6866b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -105,6 +105,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb4: { + StorageLive(_14); _13 = &mut _12; _14 = > as Iterator>::next(move _13) -> [return: bb5, unwind: bb11]; } @@ -115,6 +116,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb6: { + StorageDead(_14); StorageDead(_12); drop(_2) -> [return: bb7, unwind continue]; } @@ -129,13 +131,14 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageLive(_18); _18 = &_2; StorageLive(_19); - _19 = copy ((_14 as Some).0: (usize, &T)); + _19 = (copy _16, copy _17); _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; } bb9: { StorageDead(_19); StorageDead(_18); + StorageDead(_14); goto -> bb4; }