diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 5fe7b0f647dcd..e4751bd7c77d7 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1485,6 +1485,13 @@ pub enum StatementKind<'tcx> { } impl<'tcx> StatementKind<'tcx> { + pub fn as_assign(&self) -> Option<&(Place<'tcx>, Rvalue<'tcx>)> { + match self { + StatementKind::Assign(x) => Some(x), + _ => None, + } + } + pub fn as_assign_mut(&mut self) -> Option<&mut Box<(Place<'tcx>, Rvalue<'tcx>)>> { match self { StatementKind::Assign(x) => Some(x), @@ -1736,6 +1743,7 @@ impl<'tcx> Place<'tcx> { self.as_ref().as_local() } + #[inline] pub fn as_ref(&self) -> PlaceRef<'tcx> { PlaceRef { local: self.local, projection: &self.projection } } @@ -2395,7 +2403,7 @@ impl<'tcx> UserTypeProjections { /// Encodes the effect of a user-supplied type annotation on the /// subcomponents of a pattern. The effect is determined by applying the -/// given list of proejctions to some underlying base type. Often, +/// given list of projections to some underlying base type. Often, /// the projection element list `projs` is empty, in which case this /// directly encodes a type in `base`. But in the case of complex patterns with /// subpatterns and bindings, we want to apply only a *part* of the type to a variable, diff --git a/compiler/rustc_mir/src/dataflow/framework/mod.rs b/compiler/rustc_mir/src/dataflow/framework/mod.rs index 524ad0af1a7b4..fe5aa9ae04b3b 100644 --- a/compiler/rustc_mir/src/dataflow/framework/mod.rs +++ b/compiler/rustc_mir/src/dataflow/framework/mod.rs @@ -412,6 +412,9 @@ pub trait GenKill { self.kill(elem); } } + + /// Returns whether `elem` is alive + fn is_alive(&self, elem: T) -> bool; } /// Stores a transfer function for a gen/kill problem. @@ -450,6 +453,10 @@ impl GenKill for GenKillSet { self.kill.insert(elem); self.gen.remove(elem); } + + fn is_alive(&self, elem: T) -> bool { + self.gen.contains(elem) && !self.kill.contains(elem) + } } impl GenKill for BitSet { @@ -460,6 +467,10 @@ impl GenKill for BitSet { fn kill(&mut self, elem: T) { self.remove(elem); } + + fn is_alive(&self, elem: T) -> bool { + self.contains(elem) + } } impl GenKill for lattice::Dual> { @@ -470,6 +481,10 @@ impl GenKill for lattice::Dual> { fn kill(&mut self, elem: T) { self.0.remove(elem); } + + fn is_alive(&self, elem: T) -> bool { + self.0.contains(elem) + } } // NOTE: DO NOT CHANGE VARIANT ORDER. The derived `Ord` impls rely on the current order. diff --git a/compiler/rustc_mir/src/dataflow/impls/available_locals.rs b/compiler/rustc_mir/src/dataflow/impls/available_locals.rs new file mode 100644 index 0000000000000..3daa41fbd5ba7 --- /dev/null +++ b/compiler/rustc_mir/src/dataflow/impls/available_locals.rs @@ -0,0 +1,326 @@ +use std::{fmt, hash::BuildHasherDefault}; + +use crate::dataflow::{ + fmt::DebugWithAdapter, fmt::DebugWithContext, lattice, lattice::Dual, AnalysisDomain, Forward, + GenKill, GenKillAnalysis, +}; +use rustc_data_structures::fx::FxIndexMap; +use rustc_index::{bit_set::BitSet, vec::Idx}; + +use rustc_middle::{ + mir::{self, Body, Local, Location}, + mir::{visit::Visitor, BorrowKind, Operand, Rvalue, Statement, StatementKind}, +}; +use smallvec::SmallVec; + +/// Dataflow analysis for availability of locals. A local is available at a given program point, +/// if the value of the local can freely be used at the given program point. +/// Consider the following example: +/// ``` +/// _1 = 4; +/// _2 = &_1; +/// _3 = *_2 +/// ``` +/// In the above example, `_2` is available at the third statement, so the statement can be +/// simplified to `_3 = _1`. +/// In general, an available local can be used freely on any path from the definition of `_2` to +/// statement `s`, if `_2` and its value is guaranteed to not be changed on all paths. +/// +/// In the following example `_2` is not available in `bb2`, +/// since we do not know if `_2 = &5` is executed. +/// ``` +/// bb0 { +/// _2 = &_1; +/// switchInt(_1) -> [4: bb1, otherwise: bb2] +/// } +/// +/// bb1 { +/// _2 = &5; +/// } +/// +/// bb2 { +/// _3 = *_2 +/// } +/// ``` +pub struct AvailableLocals { + local_with_location_map: LocalWithLocationMap, +} + +type State = Dual>; + +impl<'a, 'tcx> AvailableLocals { + pub fn new(body: &'a Body<'tcx>) -> Self { + let local_with_location_map = LocalWithLocationMap::new(body); + debug!("Constructed {:?}", local_with_location_map); + Self { local_with_location_map } + } + + /// Returns the state with context attached, making debug easier + pub fn debug_state(&'a self, state: &'a State) -> impl fmt::Debug + 'a { + DebugWithAdapter { this: state, ctxt: &self.local_with_location_map } + } + + pub fn get_local_with_location_index( + &self, + local: Local, + location: Location, + ) -> Option { + self.local_with_location_map.local_with_specific_location(local, Some(location)) + } + + /// Returns whether the given local is available at the given state + pub fn is_available(&self, local: Local, state: &'a State) -> Option { + self.local_with_location_map.local_with_locations(local)?.find(|idx| state.0.contains(*idx)) + } + + fn transfer_function(&'a self, available: &'a mut T) -> TransferFunction<'a, T> + where + T: GenKill, + { + TransferFunction { available, local_with_location_map: &self.local_with_location_map } + } +} +impl AnalysisDomain<'tcx> for AvailableLocals { + /// We want a *forward must* analysis. + /// At each join point, we only keep locals that were available in both basic blocks. + /// For this, we use the Dual of a semi-lattice, such that intersection is the join operator + type Domain = State; + type Direction = Forward; + + const NAME: &'static str = "available_locals"; + + fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain { + // If we were not using the dual, we would have nothing available, but since we are using + // the dual, we also "reverse" the bottom to be filled + // bottom = nothing is available + let bottom = BitSet::new_filled(self.local_with_location_map.len()); + lattice::Dual(bottom) + } + + fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain) { + // In the start block, nothing is available at first + state.0.clear(); + + // only the function parameters are available + for arg in body.args_iter() { + if let Some(l) = self.local_with_location_map.local_with_specific_location(arg, None) { + state.0.insert(l); + } + } + } +} + +impl GenKillAnalysis<'tcx> for AvailableLocals { + type Idx = LocalWithLocationIndex; + + fn statement_effect( + &self, + trans: &mut impl GenKill, + statement: &mir::Statement<'tcx>, + location: Location, + ) { + self.transfer_function(trans).visit_statement(statement, location); + } + + fn terminator_effect( + &self, + trans: &mut impl GenKill, + terminator: &mir::Terminator<'tcx>, + location: Location, + ) { + self.transfer_function(trans).visit_terminator(terminator, location); + } + + fn call_return_effect( + &self, + _trans: &mut impl GenKill, + _block: mir::BasicBlock, + _func: &mir::Operand<'tcx>, + _args: &[mir::Operand<'tcx>], + _dest_place: mir::Place<'tcx>, + ) { + // Conservatively do not try to reason about calls + } +} + +// Compiling rustc stage2 reveals that 95% of locals are only used at 2 locations +const LOCAL_WITH_LOCATION_SMALLVEC_CAP: usize = 2; + +#[derive(Debug)] +struct LocalWithLocationMap( + FxIndexMap< + Local, + SmallVec<[(LocalWithLocationIndex, Option); LOCAL_WITH_LOCATION_SMALLVEC_CAP]>, + >, +); + +impl LocalWithLocationMap { + fn new(body: &Body<'tcx>) -> Self { + let mut map = FxIndexMap::with_capacity_and_hasher( + 1 + body.arg_count + body.vars_and_temps_iter().len(), + BuildHasherDefault::default(), + ); + + let mut idx = LocalWithLocationIndex::from(0usize); + + // return pointer + map.entry(body.local_decls.indices().next().unwrap()) + .or_insert(SmallVec::with_capacity(LOCAL_WITH_LOCATION_SMALLVEC_CAP)) + .push((idx, None)); + idx.increment_by(1); + + for arg in body.args_iter() { + map.entry(arg) + .or_insert(SmallVec::with_capacity(LOCAL_WITH_LOCATION_SMALLVEC_CAP)) + .push((idx, None)); + idx.increment_by(1); + } + + // visit all assignments which are all different "versions" of the locals + for (bb, bbd) in body.basic_blocks().iter_enumerated() { + for (stmt_idx, stmt) in bbd.statements.iter().enumerate() { + if let Some((lhs, _)) = stmt.kind.as_assign() { + // We don't handle projections for locals, so let's only add a local with no projections + if lhs.as_local().is_some() { + let location = Location { block: bb, statement_index: stmt_idx }; + map.entry(lhs.local) + .or_insert(SmallVec::with_capacity(2)) + .push((idx, Some(location))); + idx.increment_by(1); + } + } + } + } + + Self(map) + } + + fn local_with_specific_location( + &self, + local: Local, + location: Option, + ) -> Option { + debug!("Looking for {:?} in {:?}", (local, location), self.0); + let locations = self.0.get(&local)?; + locations.iter().find(|(_, l)| *l == location).map(|(location_idx, _)| *location_idx) + } + + fn local_with_locations( + &self, + local: Local, + ) -> Option + '_> { + debug!("Looking for {:?} in {:?}", local, self.0); + let locations = self.0.get(&local)?; + return Some(locations.iter().map(move |(location_idx, _)| *location_idx)); + } + + fn len(&self) -> usize { + let mut count = 0; + for v in self.0.values() { + count += v.len(); + } + count + } +} + +rustc_index::newtype_index! { + pub struct LocalWithLocationIndex { + DEBUG_FORMAT = "ll_{}" + } +} + +impl DebugWithContext for LocalWithLocationIndex { + fn fmt_with(&self, ctx: &AvailableLocals, f: &mut fmt::Formatter<'_>) -> fmt::Result { + DebugWithContext::fmt_with(self, &ctx.local_with_location_map, f) + } +} + +impl DebugWithContext for LocalWithLocationIndex { + fn fmt_with(&self, ctx: &LocalWithLocationMap, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // find local and location + for (local, value) in ctx.0.iter() { + if let Some((idx, location)) = value.iter().find(|(idx, _)| idx == self) { + return write!(f, "{:?}: {:?}", idx, (local, location)); + } + } + unreachable!() + } +} + +struct TransferFunction<'a, T> +where + T: GenKill, +{ + available: &'a mut T, + local_with_location_map: &'a LocalWithLocationMap, +} + +impl<'a, 'tcx, T> TransferFunction<'a, T> +where + T: GenKill, +{ + fn invalidate_local(&mut self, local_invalidated: Local, _location: Location) { + if let Some(locations) = + self.local_with_location_map.local_with_locations(local_invalidated) + { + for x in locations { + debug!("Invalidating {:?} which corresponds to {:?}", x, local_invalidated); + self.available.kill(x); + } + } + } + + fn add_available(&mut self, local: Local, rvalue: &Rvalue<'tcx>, location: Location) { + self.invalidate_local(local, location); + + // If rvalue is a move into the assigned local, then the local being moved should be invalidated + match rvalue { + Rvalue::Use(Operand::Move(moved)) => self.invalidate_local(moved.local, location), + _ => {} + } + + if let Some(index) = + self.local_with_location_map.local_with_specific_location(local, Some(location)) + { + debug!("Inserting {:?} which corresponds to {:?}", index, (local, Some(location))); + self.available.gen(index); + }; + } +} + +impl<'a, 'tcx, T> Visitor<'tcx> for TransferFunction<'a, T> +where + T: GenKill, +{ + fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { + match &statement.kind { + StatementKind::StorageDead(dead) => { + self.invalidate_local(*dead, location); + } + StatementKind::Assign(box (assigned_place, rvalue)) => { + if let Some(assigned_local) = assigned_place.as_local() { + let disallowed_place_opt = match rvalue { + Rvalue::Ref(_, BorrowKind::Mut { .. } | BorrowKind::Shallow, ref_of) => { + Some(ref_of) + } + Rvalue::AddressOf(_, ref_of) => Some(ref_of), + _ => None, + }; + + if let Some(disallowed_place) = disallowed_place_opt { + // It is difficult to reason about availability of mutable places or raw pointers, so throw out any + // availability information about the local taken a reference of. + debug!( + "Found disallowed reference of `{:?}`. Invalidating {:?} and {:?}", + disallowed_place, disallowed_place.local, assigned_local + ); + self.invalidate_local(disallowed_place.local, location); + } else { + self.add_available(assigned_local, rvalue, location); + } + } + } + _ => {} + } + } +} diff --git a/compiler/rustc_mir/src/dataflow/impls/mod.rs b/compiler/rustc_mir/src/dataflow/impls/mod.rs index 185f0edfeb6bc..d4c13dc932334 100644 --- a/compiler/rustc_mir/src/dataflow/impls/mod.rs +++ b/compiler/rustc_mir/src/dataflow/impls/mod.rs @@ -20,12 +20,14 @@ use super::on_lookup_result_bits; use crate::dataflow::drop_flag_effects; use crate::dataflow::framework::SwitchIntEdgeEffects; +mod available_locals; mod borrowed_locals; pub(super) mod borrows; mod init_locals; mod liveness; mod storage_liveness; +pub use self::available_locals::{AvailableLocals, LocalWithLocationIndex}; pub use self::borrowed_locals::{MaybeBorrowedLocals, MaybeMutBorrowedLocals}; pub use self::borrows::Borrows; pub use self::init_locals::MaybeInitializedLocals; diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index 59b7db2431900..4b198cfd0f78b 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -4,14 +4,10 @@ use crate::transform::MirPass; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::Mutability; use rustc_index::vec::Idx; +use rustc_middle::mir::visit::{MutVisitor, Visitor}; + use rustc_middle::mir::{ - visit::PlaceContext, - visit::{MutVisitor, Visitor}, - Statement, -}; -use rustc_middle::mir::{ - BinOp, Body, BorrowKind, Constant, Local, Location, Operand, Place, PlaceRef, ProjectionElem, - Rvalue, + BinOp, Body, Constant, Local, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, }; use rustc_middle::ty::{self, TyCtxt}; use std::mem; @@ -76,36 +72,10 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> { *rvalue = Rvalue::Use(operand); } - if let Some(place) = self.optimizations.unneeded_deref.remove(&location) { - debug!("unneeded_deref: replacing {:?} with {:?}", rvalue, place); - *rvalue = Rvalue::Use(Operand::Copy(place)); - } - self.super_rvalue(rvalue, location) } } -struct MutatingUseVisitor { - has_mutating_use: bool, - local_to_look_for: Local, -} - -impl MutatingUseVisitor { - fn has_mutating_use_in_stmt(local: Local, stmt: &Statement<'tcx>, location: Location) -> bool { - let mut _self = Self { has_mutating_use: false, local_to_look_for: local }; - _self.visit_statement(stmt, location); - _self.has_mutating_use - } -} - -impl<'tcx> Visitor<'tcx> for MutatingUseVisitor { - fn visit_local(&mut self, local: &Local, context: PlaceContext, _: Location) { - if *local == self.local_to_look_for { - self.has_mutating_use |= context.is_mutating_use(); - } - } -} - /// Finds optimization opportunities on the MIR. struct OptimizationFinder<'b, 'tcx> { body: &'b Body<'tcx>, @@ -118,103 +88,6 @@ impl OptimizationFinder<'b, 'tcx> { OptimizationFinder { body, tcx, optimizations: OptimizationList::default() } } - fn find_deref_of_address(&mut self, rvalue: &Rvalue<'tcx>, location: Location) -> Option<()> { - // FIXME(#78192): This optimization can result in unsoundness. - if !self.tcx.sess.opts.debugging_opts.unsound_mir_opts { - return None; - } - - // Look for the sequence - // - // _2 = &_1; - // ... - // _5 = (*_2); - // - // which we can replace the last statement with `_5 = _1;` to avoid the load of `_2`. - if let Rvalue::Use(op) = rvalue { - let local_being_derefed = match op.place()?.as_ref() { - PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local), - _ => None, - }?; - - let mut dead_locals_seen = vec![]; - - let stmt_index = location.statement_index; - // Look behind for statement that assigns the local from a address of operator. - // 6 is chosen as a heuristic determined by seeing the number of times - // the optimization kicked in compiling rust std. - let lower_index = stmt_index.saturating_sub(6); - let statements_to_look_in = self.body.basic_blocks()[location.block].statements - [lower_index..stmt_index] - .iter() - .rev(); - for stmt in statements_to_look_in { - match &stmt.kind { - // Exhaustive match on statements to detect conditions that warrant we bail out of the optimization. - rustc_middle::mir::StatementKind::Assign(box (l, r)) - if l.local == local_being_derefed => - { - match r { - // Looking for immutable reference e.g _local_being_deref = &_1; - Rvalue::Ref( - _, - // Only apply the optimization if it is an immutable borrow. - BorrowKind::Shared, - place_taken_address_of, - ) => { - // Make sure that the place has not been marked dead - if dead_locals_seen.contains(&place_taken_address_of.local) { - return None; - } - - self.optimizations - .unneeded_deref - .insert(location, *place_taken_address_of); - return Some(()); - } - - // We found an assignment of `local_being_deref` that is not an immutable ref, e.g the following sequence - // _2 = &_1; - // _3 = &5 - // _2 = _3; <-- this means it is no longer valid to replace the last statement with `_5 = _1;` - // _5 = (*_2); - _ => return None, - } - } - - // Inline asm can do anything, so bail out of the optimization. - rustc_middle::mir::StatementKind::LlvmInlineAsm(_) => return None, - - // Remember `StorageDead`s, as the local being marked dead could be the - // place RHS we are looking for, in which case we need to abort to avoid UB - // using an uninitialized place - rustc_middle::mir::StatementKind::StorageDead(dead) => { - dead_locals_seen.push(*dead) - } - - // Check that `local_being_deref` is not being used in a mutating way which can cause misoptimization. - rustc_middle::mir::StatementKind::Assign(box (_, _)) - | rustc_middle::mir::StatementKind::Coverage(_) - | rustc_middle::mir::StatementKind::Nop - | rustc_middle::mir::StatementKind::FakeRead(_, _) - | rustc_middle::mir::StatementKind::StorageLive(_) - | rustc_middle::mir::StatementKind::Retag(_, _) - | rustc_middle::mir::StatementKind::AscribeUserType(_, _) - | rustc_middle::mir::StatementKind::SetDiscriminant { .. } => { - if MutatingUseVisitor::has_mutating_use_in_stmt( - local_being_derefed, - stmt, - location, - ) { - return None; - } - } - } - } - } - Some(()) - } - fn find_unneeded_equality_comparison(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { // find Ne(_place, false) or Ne(false, _place) // or Eq(_place, true) or Eq(true, _place) @@ -281,8 +154,6 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { } } - let _ = self.find_deref_of_address(rvalue, location); - self.find_unneeded_equality_comparison(rvalue, location); self.super_rvalue(rvalue, location) @@ -294,5 +165,4 @@ struct OptimizationList<'tcx> { and_stars: FxHashSet, arrays_lengths: FxHashMap>, unneeded_equality_comparison: FxHashMap>, - unneeded_deref: FxHashMap>, } diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index e3fea2d2701e5..7f09b6d8bfa5d 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -46,6 +46,7 @@ pub mod simplify_branches; pub mod simplify_comparison_integral; pub mod simplify_try; pub mod uninhabited_enum_branching; +pub mod unneeded_deref; pub mod unreachable_prop; pub mod validate; @@ -395,6 +396,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) &multiple_return_terminators::MultipleReturnTerminators, &instcombine::InstCombine, + &unneeded_deref::UnneededDeref, &const_prop::ConstProp, &simplify_branches::SimplifyBranches::new("after-const-prop"), &early_otherwise_branch::EarlyOtherwiseBranch, diff --git a/compiler/rustc_mir/src/transform/unneeded_deref.rs b/compiler/rustc_mir/src/transform/unneeded_deref.rs new file mode 100644 index 0000000000000..f1b00a5eb36b4 --- /dev/null +++ b/compiler/rustc_mir/src/transform/unneeded_deref.rs @@ -0,0 +1,187 @@ +use rustc_data_structures::fx::FxHashMap; +use rustc_index::bit_set::BitSet; +use rustc_middle::{ + mir::visit::Visitor, + mir::{ + visit::{MutVisitor, PlaceContext}, + Body, BorrowKind, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, Statement, + StatementKind, + }, + ty::TyCtxt, +}; + +use super::MirPass; +use crate::dataflow::Analysis; +use crate::dataflow::{ + impls::{AvailableLocals, LocalWithLocationIndex}, + lattice::Dual, + Results, ResultsVisitor, +}; + +/// Pass to find cases where a dereference of a reference can be avoided by +/// using the referenced value directly. +/// +/// Consider the following example: +/// ``` +/// _1 = 4; +/// _2 = &_1; +/// _3 = *_2 +/// ``` +/// +/// This is optimized into: +/// ``` +/// _1 = 4; +/// _2 = &_1; +/// _3 = _1 +/// ``` +/// +/// Later passes can then potentially remove `_2` as it is now unused. +pub struct UnneededDeref; + +impl<'tcx> MirPass<'tcx> for UnneededDeref { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let optimizations = UnneededDerefVisitor::go(body, tcx); + if !optimizations.is_empty() { + MutVisitor::visit_body(&mut ApplyOpts { optimizations, tcx }, body); + } + } +} + +struct UnneededDerefVisitor<'a, 'tcx> { + refs: &'a mut FxHashMap, (LocalWithLocationIndex, LocalWithLocationIndex))>, + optimizations: &'a mut FxHashMap<(Location, Place<'tcx>), Place<'tcx>>, + results: &'a Results<'tcx, AvailableLocals>, +} + +struct FindOptVisitor<'a, 'tcx> { + refs: &'a mut FxHashMap, (LocalWithLocationIndex, LocalWithLocationIndex))>, + optimizations: &'a mut FxHashMap<(Location, Place<'tcx>), Place<'tcx>>, + state: &'a Dual>, +} + +impl<'a, 'tcx> Visitor<'tcx> for FindOptVisitor<'a, 'tcx> { + fn visit_place(&mut self, place: &Place<'tcx>, _context: PlaceContext, location: Location) { + let _: Option<_> = try { + debug!("Visiting place {:?}", place); + let state = self.state; + + match place.as_ref() { + PlaceRef { projection: [ProjectionElem::Deref], .. } => { + let place_derefed = place; + debug!("Refs {:?}", self.refs); + // See if we have recorded an earlier assignment where we took the reference of the place we are now dereferencing + let (place_taken_ref_of, (lhs_idx, place_taken_ref_of_location)) = + self.refs.get(&place_derefed.local)?; + + // We found a reference. Let's check if it is still valid + let place_taken_ref_of_available = + state.0.contains(*place_taken_ref_of_location); + + debug!( + "{:?} has availability {:?}", + place_taken_ref_of.local, place_taken_ref_of_available + ); + if place_taken_ref_of_available { + // And then check if the place we are dereferencing is still valid + let place_available = state.0.contains(*lhs_idx); + debug!("{:?} has availability {:?}", place.local, place_available); + if place_available { + self.optimizations + .insert((location, place.clone()), place_taken_ref_of.clone()); + } + } + } + + _ => {} + } + }; + // We explicitly do not call super_place as we don't need to explore the graph deeper + } +} + +impl<'a, 'tcx> UnneededDerefVisitor<'a, 'tcx> { + fn go( + body: &'a Body<'tcx>, + tcx: TyCtxt<'tcx>, + ) -> FxHashMap<(Location, Place<'tcx>), Place<'tcx>> { + let analysis = AvailableLocals::new(body); + let results = analysis.into_engine(tcx, body).iterate_to_fixpoint(); + let mut refs = FxHashMap::default(); + let mut optimizations = FxHashMap::default(); + + let mut _self = UnneededDerefVisitor { + refs: &mut refs, + optimizations: &mut optimizations, + results: &results, + }; + + results.visit_reachable_with(body, &mut _self); + + optimizations + } +} + +impl<'a, 'tcx> ResultsVisitor<'a, 'tcx> for UnneededDerefVisitor<'a, 'tcx> { + type FlowState = Dual>; + fn visit_statement_before_primary_effect( + &mut self, + state: &Self::FlowState, + stmt: &'mir Statement<'tcx>, + location: Location, + ) { + let analysis = &self.results.analysis; + debug!("state: {:?} before statement {:?}", analysis.debug_state(state), stmt); + let _: Option<_> = try { + match &stmt.kind { + StatementKind::Assign(box ( + lhs, + Rvalue::Ref(_, BorrowKind::Shared, place_taken_ref_of), + )) => { + let analysis = &self.results.analysis; + // Only insert if the place that is referenced is available + if let Some(place_taken_ref_of_idx) = + analysis.is_available(place_taken_ref_of.local, state) + { + if let Some(lhs_idx) = + analysis.get_local_with_location_index(lhs.local, location) + { + self.refs.insert( + lhs.local, + (place_taken_ref_of.clone(), (lhs_idx, place_taken_ref_of_idx)), + ); + }; + } + } + StatementKind::Assign(box (_, rvalue)) => match rvalue { + rvalue => { + let mut _self = FindOptVisitor { + refs: self.refs, + optimizations: &mut self.optimizations, + state: state, + }; + _self.visit_rvalue(rvalue, location); + } + }, + _ => {} + } + }; + } +} + +struct ApplyOpts<'tcx> { + optimizations: FxHashMap<(Location, Place<'tcx>), Place<'tcx>>, + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> MutVisitor<'tcx> for ApplyOpts<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_place(&mut self, place: &mut Place<'tcx>, _context: PlaceContext, location: Location) { + if let Some(found_place) = self.optimizations.remove(&(location, *place)) { + debug!("unneeded_deref: replacing {:?} with {:?}", place, found_place); + *place = found_place; + } + } +} diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff index 812c7c9771801..7ec0751263fb1 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff @@ -19,7 +19,7 @@ // + span: $DIR/ref_deref_project.rs:5:6: 5:17 // + literal: Const { ty: &(i32, i32), val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) } _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 - _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17 + _1 = ((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17 StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18 StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18 _0 = const (); // scope 0 at $DIR/ref_deref_project.rs:4:11: 6:2 diff --git a/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir index db504b416fe1d..4bda9ae383c22 100644 --- a/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir @@ -40,7 +40,7 @@ fn foo(_1: T, _2: &i32) -> i32 { _9 = move (_5.1: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 StorageLive(_10); // scope 2 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 _10 = _8; // scope 2 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 - _0 = (*_8); // scope 3 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 + _0 = (*_10); // scope 3 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 StorageDead(_10); // scope 2 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 StorageDead(_9); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 StorageDead(_8); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 diff --git a/src/test/mir-opt/inst_combine_deref.deep_opt.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.deep_opt.InstCombine.diff deleted file mode 100644 index 1d20e17a8499b..0000000000000 --- a/src/test/mir-opt/inst_combine_deref.deep_opt.InstCombine.diff +++ /dev/null @@ -1,92 +0,0 @@ -- // MIR for `deep_opt` before InstCombine -+ // MIR for `deep_opt` after InstCombine - - fn deep_opt() -> (u64, u64, u64) { - let mut _0: (u64, u64, u64); // return place in scope 0 at $DIR/inst_combine_deref.rs:11:18: 11:33 - let _1: u64; // in scope 0 at $DIR/inst_combine_deref.rs:12:9: 12:11 - let mut _10: u64; // in scope 0 at $DIR/inst_combine_deref.rs:21:6: 21:8 - let mut _11: u64; // in scope 0 at $DIR/inst_combine_deref.rs:21:10: 21:12 - let mut _12: u64; // in scope 0 at $DIR/inst_combine_deref.rs:21:14: 21:16 - scope 1 { - debug x1 => _1; // in scope 1 at $DIR/inst_combine_deref.rs:12:9: 12:11 - let _2: u64; // in scope 1 at $DIR/inst_combine_deref.rs:13:9: 13:11 - scope 2 { - debug x2 => _2; // in scope 2 at $DIR/inst_combine_deref.rs:13:9: 13:11 - let _3: u64; // in scope 2 at $DIR/inst_combine_deref.rs:14:9: 14:11 - scope 3 { - debug x3 => _3; // in scope 3 at $DIR/inst_combine_deref.rs:14:9: 14:11 - let _4: &u64; // in scope 3 at $DIR/inst_combine_deref.rs:15:9: 15:11 - scope 4 { - debug y1 => _4; // in scope 4 at $DIR/inst_combine_deref.rs:15:9: 15:11 - let _5: &u64; // in scope 4 at $DIR/inst_combine_deref.rs:16:9: 16:11 - scope 5 { - debug y2 => _5; // in scope 5 at $DIR/inst_combine_deref.rs:16:9: 16:11 - let _6: &u64; // in scope 5 at $DIR/inst_combine_deref.rs:17:9: 17:11 - scope 6 { - debug y3 => _6; // in scope 6 at $DIR/inst_combine_deref.rs:17:9: 17:11 - let _7: u64; // in scope 6 at $DIR/inst_combine_deref.rs:18:9: 18:11 - scope 7 { - debug z1 => _7; // in scope 7 at $DIR/inst_combine_deref.rs:18:9: 18:11 - let _8: u64; // in scope 7 at $DIR/inst_combine_deref.rs:19:9: 19:11 - scope 8 { - debug z2 => _8; // in scope 8 at $DIR/inst_combine_deref.rs:19:9: 19:11 - let _9: u64; // in scope 8 at $DIR/inst_combine_deref.rs:20:9: 20:11 - scope 9 { - debug z3 => _9; // in scope 9 at $DIR/inst_combine_deref.rs:20:9: 20:11 - } - } - } - } - } - } - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/inst_combine_deref.rs:12:9: 12:11 - _1 = const 1_u64; // scope 0 at $DIR/inst_combine_deref.rs:12:14: 12:15 - StorageLive(_2); // scope 1 at $DIR/inst_combine_deref.rs:13:9: 13:11 - _2 = const 2_u64; // scope 1 at $DIR/inst_combine_deref.rs:13:14: 13:15 - StorageLive(_3); // scope 2 at $DIR/inst_combine_deref.rs:14:9: 14:11 - _3 = const 3_u64; // scope 2 at $DIR/inst_combine_deref.rs:14:14: 14:15 - StorageLive(_4); // scope 3 at $DIR/inst_combine_deref.rs:15:9: 15:11 - _4 = &_1; // scope 3 at $DIR/inst_combine_deref.rs:15:14: 15:17 - StorageLive(_5); // scope 4 at $DIR/inst_combine_deref.rs:16:9: 16:11 - _5 = &_2; // scope 4 at $DIR/inst_combine_deref.rs:16:14: 16:17 - StorageLive(_6); // scope 5 at $DIR/inst_combine_deref.rs:17:9: 17:11 - _6 = &_3; // scope 5 at $DIR/inst_combine_deref.rs:17:14: 17:17 - StorageLive(_7); // scope 6 at $DIR/inst_combine_deref.rs:18:9: 18:11 -- _7 = (*_4); // scope 6 at $DIR/inst_combine_deref.rs:18:14: 18:17 -+ _7 = _1; // scope 6 at $DIR/inst_combine_deref.rs:18:14: 18:17 - StorageLive(_8); // scope 7 at $DIR/inst_combine_deref.rs:19:9: 19:11 -- _8 = (*_5); // scope 7 at $DIR/inst_combine_deref.rs:19:14: 19:17 -+ _8 = _2; // scope 7 at $DIR/inst_combine_deref.rs:19:14: 19:17 - StorageLive(_9); // scope 8 at $DIR/inst_combine_deref.rs:20:9: 20:11 -- _9 = (*_6); // scope 8 at $DIR/inst_combine_deref.rs:20:14: 20:17 -+ _9 = _3; // scope 8 at $DIR/inst_combine_deref.rs:20:14: 20:17 - StorageLive(_10); // scope 9 at $DIR/inst_combine_deref.rs:21:6: 21:8 - _10 = _7; // scope 9 at $DIR/inst_combine_deref.rs:21:6: 21:8 - StorageLive(_11); // scope 9 at $DIR/inst_combine_deref.rs:21:10: 21:12 - _11 = _8; // scope 9 at $DIR/inst_combine_deref.rs:21:10: 21:12 - StorageLive(_12); // scope 9 at $DIR/inst_combine_deref.rs:21:14: 21:16 - _12 = _9; // scope 9 at $DIR/inst_combine_deref.rs:21:14: 21:16 - (_0.0: u64) = move _10; // scope 9 at $DIR/inst_combine_deref.rs:21:5: 21:17 - (_0.1: u64) = move _11; // scope 9 at $DIR/inst_combine_deref.rs:21:5: 21:17 - (_0.2: u64) = move _12; // scope 9 at $DIR/inst_combine_deref.rs:21:5: 21:17 - StorageDead(_12); // scope 9 at $DIR/inst_combine_deref.rs:21:16: 21:17 - StorageDead(_11); // scope 9 at $DIR/inst_combine_deref.rs:21:16: 21:17 - StorageDead(_10); // scope 9 at $DIR/inst_combine_deref.rs:21:16: 21:17 - StorageDead(_9); // scope 8 at $DIR/inst_combine_deref.rs:22:1: 22:2 - StorageDead(_8); // scope 7 at $DIR/inst_combine_deref.rs:22:1: 22:2 - StorageDead(_7); // scope 6 at $DIR/inst_combine_deref.rs:22:1: 22:2 - StorageDead(_6); // scope 5 at $DIR/inst_combine_deref.rs:22:1: 22:2 - StorageDead(_5); // scope 4 at $DIR/inst_combine_deref.rs:22:1: 22:2 - StorageDead(_4); // scope 3 at $DIR/inst_combine_deref.rs:22:1: 22:2 - StorageDead(_3); // scope 2 at $DIR/inst_combine_deref.rs:22:1: 22:2 - StorageDead(_2); // scope 1 at $DIR/inst_combine_deref.rs:22:1: 22:2 - StorageDead(_1); // scope 0 at $DIR/inst_combine_deref.rs:22:1: 22:2 - return; // scope 0 at $DIR/inst_combine_deref.rs:22:2: 22:2 - } - } - 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 deleted file mode 100644 index 23c18bde2262b..0000000000000 --- a/src/test/mir-opt/inst_combine_deref.do_not_miscompile.InstCombine.diff +++ /dev/null @@ -1,85 +0,0 @@ -- // MIR for `do_not_miscompile` before InstCombine -+ // MIR for `do_not_miscompile` after InstCombine - - fn do_not_miscompile() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inst_combine_deref.rs:54:24: 54:24 - let _1: i32; // in scope 0 at $DIR/inst_combine_deref.rs:55:9: 55:10 - let mut _5: &i32; // in scope 0 at $DIR/inst_combine_deref.rs:59:10: 59:12 - let _6: &i32; // in scope 0 at $DIR/inst_combine_deref.rs:59:10: 59:12 - let _7: (); // in scope 0 at $DIR/inst_combine_deref.rs:60:5: 60:23 - let mut _8: bool; // in scope 0 at $DIR/inst_combine_deref.rs:60:5: 60:23 - let mut _9: bool; // in scope 0 at $DIR/inst_combine_deref.rs:60:13: 60:21 - let mut _10: i32; // in scope 0 at $DIR/inst_combine_deref.rs:60:13: 60:15 - let mut _11: !; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - scope 1 { - debug x => _1; // in scope 1 at $DIR/inst_combine_deref.rs:55:9: 55:10 - let _2: i32; // in scope 1 at $DIR/inst_combine_deref.rs:56:9: 56:10 - scope 2 { - debug a => _2; // in scope 2 at $DIR/inst_combine_deref.rs:56:9: 56:10 - let mut _3: &i32; // in scope 2 at $DIR/inst_combine_deref.rs:57:9: 57:14 - scope 3 { - debug y => _3; // in scope 3 at $DIR/inst_combine_deref.rs:57:9: 57:14 - let _4: &mut &i32; // in scope 3 at $DIR/inst_combine_deref.rs:58:9: 58:10 - scope 4 { - debug z => _4; // in scope 4 at $DIR/inst_combine_deref.rs:58:9: 58:10 - } - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/inst_combine_deref.rs:55:9: 55:10 - _1 = const 42_i32; // scope 0 at $DIR/inst_combine_deref.rs:55:13: 55:15 - StorageLive(_2); // scope 1 at $DIR/inst_combine_deref.rs:56:9: 56:10 - _2 = const 99_i32; // scope 1 at $DIR/inst_combine_deref.rs:56:13: 56:15 - StorageLive(_3); // scope 2 at $DIR/inst_combine_deref.rs:57:9: 57:14 - _3 = &_1; // scope 2 at $DIR/inst_combine_deref.rs:57:17: 57:19 - StorageLive(_4); // scope 3 at $DIR/inst_combine_deref.rs:58:9: 58:10 - _4 = &mut _3; // scope 3 at $DIR/inst_combine_deref.rs:58:13: 58:19 - StorageLive(_5); // scope 4 at $DIR/inst_combine_deref.rs:59:10: 59:12 - StorageLive(_6); // scope 4 at $DIR/inst_combine_deref.rs:59:10: 59:12 - _6 = &_2; // scope 4 at $DIR/inst_combine_deref.rs:59:10: 59:12 -- _5 = &(*_6); // scope 4 at $DIR/inst_combine_deref.rs:59:10: 59:12 -+ _5 = _6; // scope 4 at $DIR/inst_combine_deref.rs:59:10: 59:12 - (*_4) = move _5; // scope 4 at $DIR/inst_combine_deref.rs:59:5: 59:12 - StorageDead(_5); // scope 4 at $DIR/inst_combine_deref.rs:59:11: 59:12 - StorageDead(_6); // scope 4 at $DIR/inst_combine_deref.rs:59:12: 59:13 - StorageLive(_7); // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23 - StorageLive(_8); // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23 - 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 - 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 - 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 - } - - bb1: { - _7 = const (); // scope 4 at $DIR/inst_combine_deref.rs:60:5: 60:23 - StorageDead(_8); // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23 - StorageDead(_7); // scope 4 at $DIR/inst_combine_deref.rs:60:22: 60:23 - _0 = const (); // scope 0 at $DIR/inst_combine_deref.rs:54:24: 61:2 - StorageDead(_4); // scope 3 at $DIR/inst_combine_deref.rs:61:1: 61:2 - StorageDead(_3); // scope 2 at $DIR/inst_combine_deref.rs:61:1: 61:2 - StorageDead(_2); // scope 1 at $DIR/inst_combine_deref.rs:61:1: 61:2 - StorageDead(_1); // scope 0 at $DIR/inst_combine_deref.rs:61:1: 61:2 - return; // scope 0 at $DIR/inst_combine_deref.rs:61:2: 61:2 - } - - bb2: { - StorageLive(_11); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - begin_panic::<&str>(const "assertion failed: *y == 99"); // 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: 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, 42, 121, 32, 61, 61, 32, 57, 57], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [67108863], len: Size { raw: 26 } }, size: Size { raw: 26 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 26 }) - // mir::Constant - // + span: $DIR/inst_combine_deref.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, 42, 121, 32, 61, 61, 32, 57, 57], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [67108863], len: Size { raw: 26 } }, size: Size { raw: 26 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 26 }) } - } - } - diff --git a/src/test/mir-opt/inst_combine_deref.dont_opt.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.dont_opt.InstCombine.diff deleted file mode 100644 index 69036491a10b7..0000000000000 --- a/src/test/mir-opt/inst_combine_deref.dont_opt.InstCombine.diff +++ /dev/null @@ -1,53 +0,0 @@ -- // MIR for `dont_opt` before InstCombine -+ // MIR for `dont_opt` after InstCombine - - fn dont_opt() -> u64 { - let mut _0: u64; // return place in scope 0 at $DIR/inst_combine_deref.rs:43:18: 43:21 - let _1: i32; // in scope 0 at $DIR/inst_combine_deref.rs:44:9: 44:10 - let mut _5: &i32; // in scope 0 at $DIR/inst_combine_deref.rs:48:10: 48:14 - scope 1 { - debug y => _1; // in scope 1 at $DIR/inst_combine_deref.rs:44:9: 44:10 - let _2: &i32; // in scope 1 at $DIR/inst_combine_deref.rs:45:9: 45:13 - scope 2 { - debug _ref => _2; // in scope 2 at $DIR/inst_combine_deref.rs:45:9: 45:13 - let _3: i32; // in scope 2 at $DIR/inst_combine_deref.rs:46:9: 46:10 - scope 3 { - debug x => _3; // in scope 3 at $DIR/inst_combine_deref.rs:46:9: 46:10 - let mut _4: &i32; // in scope 3 at $DIR/inst_combine_deref.rs:47:9: 47:15 - scope 4 { - debug _1 => _4; // in scope 4 at $DIR/inst_combine_deref.rs:47:9: 47:15 - let _6: i32; // in scope 4 at $DIR/inst_combine_deref.rs:49:9: 49:11 - scope 5 { - debug _4 => _6; // in scope 5 at $DIR/inst_combine_deref.rs:49:9: 49:11 - } - } - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/inst_combine_deref.rs:44:9: 44:10 - _1 = const 5_i32; // scope 0 at $DIR/inst_combine_deref.rs:44:13: 44:14 - StorageLive(_2); // scope 1 at $DIR/inst_combine_deref.rs:45:9: 45:13 - _2 = &_1; // scope 1 at $DIR/inst_combine_deref.rs:45:16: 45:18 - StorageLive(_3); // scope 2 at $DIR/inst_combine_deref.rs:46:9: 46:10 - _3 = const 5_i32; // scope 2 at $DIR/inst_combine_deref.rs:46:13: 46:14 - StorageLive(_4); // scope 3 at $DIR/inst_combine_deref.rs:47:9: 47:15 - _4 = &_3; // scope 3 at $DIR/inst_combine_deref.rs:47:18: 47:20 - StorageLive(_5); // scope 4 at $DIR/inst_combine_deref.rs:48:10: 48:14 -- _5 = &(*_2); // scope 4 at $DIR/inst_combine_deref.rs:48:10: 48:14 -+ _5 = _2; // scope 4 at $DIR/inst_combine_deref.rs:48:10: 48:14 - _4 = move _5; // scope 4 at $DIR/inst_combine_deref.rs:48:5: 48:14 - StorageDead(_5); // scope 4 at $DIR/inst_combine_deref.rs:48:13: 48:14 - StorageLive(_6); // scope 4 at $DIR/inst_combine_deref.rs:49:9: 49:11 - _6 = (*_4); // scope 4 at $DIR/inst_combine_deref.rs:49:14: 49:17 - _0 = const 0_u64; // scope 5 at $DIR/inst_combine_deref.rs:50:5: 50:6 - StorageDead(_6); // scope 4 at $DIR/inst_combine_deref.rs:51:1: 51:2 - StorageDead(_4); // scope 3 at $DIR/inst_combine_deref.rs:51:1: 51:2 - StorageDead(_3); // scope 2 at $DIR/inst_combine_deref.rs:51:1: 51:2 - StorageDead(_2); // scope 1 at $DIR/inst_combine_deref.rs:51:1: 51:2 - StorageDead(_1); // scope 0 at $DIR/inst_combine_deref.rs:51:1: 51:2 - return; // scope 0 at $DIR/inst_combine_deref.rs:51:2: 51:2 - } - } - diff --git a/src/test/mir-opt/inst_combine_deref.opt_struct.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.opt_struct.InstCombine.diff deleted file mode 100644 index c867543d05ea3..0000000000000 --- a/src/test/mir-opt/inst_combine_deref.opt_struct.InstCombine.diff +++ /dev/null @@ -1,44 +0,0 @@ -- // MIR for `opt_struct` before InstCombine -+ // MIR for `opt_struct` after InstCombine - - fn opt_struct(_1: S) -> u64 { - debug s => _1; // in scope 0 at $DIR/inst_combine_deref.rs:30:15: 30:16 - let mut _0: u64; // return place in scope 0 at $DIR/inst_combine_deref.rs:30:24: 30:27 - let _2: &u64; // in scope 0 at $DIR/inst_combine_deref.rs:31:9: 31:10 - let mut _5: u64; // in scope 0 at $DIR/inst_combine_deref.rs:34:5: 34:7 - let mut _6: u64; // in scope 0 at $DIR/inst_combine_deref.rs:34:10: 34:11 - scope 1 { - debug a => _2; // in scope 1 at $DIR/inst_combine_deref.rs:31:9: 31:10 - let _3: &u64; // in scope 1 at $DIR/inst_combine_deref.rs:32:9: 32:10 - scope 2 { - debug b => _3; // in scope 2 at $DIR/inst_combine_deref.rs:32:9: 32:10 - let _4: u64; // in scope 2 at $DIR/inst_combine_deref.rs:33:9: 33:10 - scope 3 { - debug x => _4; // in scope 3 at $DIR/inst_combine_deref.rs:33:9: 33:10 - } - } - } - - bb0: { - StorageLive(_2); // scope 0 at $DIR/inst_combine_deref.rs:31:9: 31:10 - _2 = &(_1.0: u64); // scope 0 at $DIR/inst_combine_deref.rs:31:13: 31:17 - StorageLive(_3); // scope 1 at $DIR/inst_combine_deref.rs:32:9: 32:10 - _3 = &(_1.1: u64); // scope 1 at $DIR/inst_combine_deref.rs:32:13: 32:17 - StorageLive(_4); // scope 2 at $DIR/inst_combine_deref.rs:33:9: 33:10 -- _4 = (*_2); // scope 2 at $DIR/inst_combine_deref.rs:33:13: 33:15 -+ _4 = (_1.0: u64); // scope 2 at $DIR/inst_combine_deref.rs:33:13: 33:15 - StorageLive(_5); // scope 3 at $DIR/inst_combine_deref.rs:34:5: 34:7 -- _5 = (*_3); // scope 3 at $DIR/inst_combine_deref.rs:34:5: 34:7 -+ _5 = (_1.1: u64); // scope 3 at $DIR/inst_combine_deref.rs:34:5: 34:7 - StorageLive(_6); // scope 3 at $DIR/inst_combine_deref.rs:34:10: 34:11 - _6 = _4; // scope 3 at $DIR/inst_combine_deref.rs:34:10: 34:11 - _0 = Add(move _5, move _6); // scope 3 at $DIR/inst_combine_deref.rs:34:5: 34:11 - StorageDead(_6); // scope 3 at $DIR/inst_combine_deref.rs:34:10: 34:11 - StorageDead(_5); // scope 3 at $DIR/inst_combine_deref.rs:34:10: 34:11 - StorageDead(_4); // scope 2 at $DIR/inst_combine_deref.rs:35:1: 35:2 - StorageDead(_3); // scope 1 at $DIR/inst_combine_deref.rs:35:1: 35:2 - StorageDead(_2); // scope 0 at $DIR/inst_combine_deref.rs:35:1: 35:2 - return; // scope 0 at $DIR/inst_combine_deref.rs:35:2: 35:2 - } - } - diff --git a/src/test/mir-opt/inst_combine_deref.rs b/src/test/mir-opt/inst_combine_deref.rs deleted file mode 100644 index 78361c336607c..0000000000000 --- a/src/test/mir-opt/inst_combine_deref.rs +++ /dev/null @@ -1,69 +0,0 @@ -// compile-flags: -O -Zunsound-mir-opts -// EMIT_MIR inst_combine_deref.simple_opt.InstCombine.diff -fn simple_opt() -> u64 { - let x = 5; - let y = &x; - let z = *y; - z -} - -// EMIT_MIR inst_combine_deref.deep_opt.InstCombine.diff -fn deep_opt() -> (u64, u64, u64) { - let x1 = 1; - let x2 = 2; - let x3 = 3; - let y1 = &x1; - let y2 = &x2; - let y3 = &x3; - let z1 = *y1; - let z2 = *y2; - let z3 = *y3; - (z1, z2, z3) -} - -struct S { - a: u64, - b: u64, -} - -// EMIT_MIR inst_combine_deref.opt_struct.InstCombine.diff -fn opt_struct(s: S) -> u64 { - let a = &s.a; - let b = &s.b; - let x = *a; - *b + x -} - -// EMIT_MIR inst_combine_deref.dont_opt.InstCombine.diff -// do not optimize a sequence looking like this: -// _1 = &_2; -// _1 = _3; -// _4 = *_1; -// as the _1 = _3 assignment makes it not legal to replace the last statement with _4 = _2 -fn dont_opt() -> u64 { - let y = 5; - let _ref = &y; - let x = 5; - let mut _1 = &x; - _1 = _ref; - let _4 = *_1; - 0 -} - -// EMIT_MIR inst_combine_deref.do_not_miscompile.InstCombine.diff -fn do_not_miscompile() { - let x = 42; - let a = 99; - let mut y = &x; - let z = &mut y; - *z = &a; - assert!(*y == 99); -} - -fn main() { - simple_opt(); - deep_opt(); - opt_struct(S { a: 0, b: 1 }); - dont_opt(); - do_not_miscompile(); -} diff --git a/src/test/mir-opt/inst_combine_deref.simple_opt.InstCombine.diff b/src/test/mir-opt/inst_combine_deref.simple_opt.InstCombine.diff deleted file mode 100644 index f52dfe379ca30..0000000000000 --- a/src/test/mir-opt/inst_combine_deref.simple_opt.InstCombine.diff +++ /dev/null @@ -1,34 +0,0 @@ -- // MIR for `simple_opt` before InstCombine -+ // MIR for `simple_opt` after InstCombine - - fn simple_opt() -> u64 { - let mut _0: u64; // return place in scope 0 at $DIR/inst_combine_deref.rs:3:20: 3:23 - let _1: u64; // in scope 0 at $DIR/inst_combine_deref.rs:4:9: 4:10 - scope 1 { - debug x => _1; // in scope 1 at $DIR/inst_combine_deref.rs:4:9: 4:10 - let _2: &u64; // in scope 1 at $DIR/inst_combine_deref.rs:5:9: 5:10 - scope 2 { - debug y => _2; // in scope 2 at $DIR/inst_combine_deref.rs:5:9: 5:10 - let _3: u64; // in scope 2 at $DIR/inst_combine_deref.rs:6:9: 6:10 - scope 3 { - debug z => _3; // in scope 3 at $DIR/inst_combine_deref.rs:6:9: 6:10 - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/inst_combine_deref.rs:4:9: 4:10 - _1 = const 5_u64; // scope 0 at $DIR/inst_combine_deref.rs:4:13: 4:14 - StorageLive(_2); // scope 1 at $DIR/inst_combine_deref.rs:5:9: 5:10 - _2 = &_1; // scope 1 at $DIR/inst_combine_deref.rs:5:13: 5:15 - StorageLive(_3); // scope 2 at $DIR/inst_combine_deref.rs:6:9: 6:10 -- _3 = (*_2); // scope 2 at $DIR/inst_combine_deref.rs:6:13: 6:15 -+ _3 = _1; // scope 2 at $DIR/inst_combine_deref.rs:6:13: 6:15 - _0 = _3; // scope 3 at $DIR/inst_combine_deref.rs:7:5: 7:6 - StorageDead(_3); // scope 2 at $DIR/inst_combine_deref.rs:8:1: 8:2 - StorageDead(_2); // scope 1 at $DIR/inst_combine_deref.rs:8:1: 8:2 - StorageDead(_1); // scope 0 at $DIR/inst_combine_deref.rs:8:1: 8:2 - return; // scope 0 at $DIR/inst_combine_deref.rs:8:2: 8:2 - } - } - diff --git a/src/test/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff deleted file mode 100644 index 5048359e5c654..0000000000000 --- a/src/test/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff +++ /dev/null @@ -1,13 +0,0 @@ -- // MIR for `bar` before InstrumentCoverage -+ // MIR for `bar` after InstrumentCoverage - - fn bar() -> bool { - let mut _0: bool; // return place in scope 0 at /the/src/instrument_coverage.rs:19:13: 19:17 - - bb0: { - _0 = const true; // scope 0 at /the/src/instrument_coverage.rs:20:5: 20:9 -+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:20:5 - 21:2; // scope 0 at /the/src/instrument_coverage.rs:21:2: 21:2 - return; // scope 0 at /the/src/instrument_coverage.rs:21:2: 21:2 - } - } - diff --git a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff deleted file mode 100644 index c67d0e2ffe656..0000000000000 --- a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ /dev/null @@ -1,51 +0,0 @@ -- // MIR for `main` before InstrumentCoverage -+ // MIR for `main` after InstrumentCoverage - - fn main() -> () { - let mut _0: (); // return place in scope 0 at /the/src/instrument_coverage.rs:10:11: 10:11 - let mut _1: (); // in scope 0 at /the/src/instrument_coverage.rs:10:1: 16:2 - let mut _2: bool; // in scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 - let mut _3: !; // in scope 0 at /the/src/instrument_coverage.rs:12:18: 14:10 - - bb0: { - falseUnwind -> [real: bb1, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 - } - - bb1: { - StorageLive(_2); // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 - _2 = bar() -> [return: bb2, unwind: bb6]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 - // mir::Constant - // + span: /the/src/instrument_coverage.rs:12:12: 12:15 - // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar()) } - } - - bb2: { - FakeRead(ForMatchedPlace, _2); // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 -+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:12:12 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10 - switchInt(_2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10 - } - - bb3: { - falseEdge -> [real: bb5, imaginary: bb4]; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10 - } - - bb4: { - _1 = const (); // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10 - StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:15:5: 15:6 -+ Coverage::Expression(4294967295) = 1 - 2 for /the/src/instrument_coverage.rs:15:6 - 15:7; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 - goto -> bb0; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 - } - - bb5: { - _0 = const (); // scope 0 at /the/src/instrument_coverage.rs:13:13: 13:18 - StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:15:5: 15:6 -+ Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 -+ Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 - return; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 - } - - bb6 (cleanup): { - resume; // scope 0 at /the/src/instrument_coverage.rs:10:1: 16:2 - } - } - diff --git a/src/test/mir-opt/issue-78192.rs b/src/test/mir-opt/issue-78192.rs index 906d094f72b4a..b5a24ad54b7e1 100644 --- a/src/test/mir-opt/issue-78192.rs +++ b/src/test/mir-opt/issue-78192.rs @@ -1,4 +1,4 @@ -// EMIT_MIR issue_78192.f.InstCombine.diff +// EMIT_MIR issue_78192.f.UnneededDeref.diff pub fn f(a: &T) -> *const T { let b: &*const T = &(a as *const T); *b diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff index 499134b69919f..1175ced49eba4 100644 --- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff @@ -86,15 +86,15 @@ _15 = &(*_2)[2 of 3]; // scope 1 at $DIR/issue_76432.rs:9:26: 9:32 StorageLive(_16); // scope 2 at $DIR/issue_76432.rs:9:38: 9:52 StorageLive(_17); // scope 2 at $DIR/issue_76432.rs:9:38: 9:52 - _17 = &raw const (*_13); // scope 2 at $DIR/issue_76432.rs:9:38: 9:40 + _17 = &raw const (*_2)[0 of 3]; // scope 2 at $DIR/issue_76432.rs:9:38: 9:40 _16 = _17; // scope 2 at $DIR/issue_76432.rs:9:38: 9:52 StorageLive(_18); // scope 2 at $DIR/issue_76432.rs:9:54: 9:68 StorageLive(_19); // scope 2 at $DIR/issue_76432.rs:9:54: 9:68 - _19 = &raw const (*_14); // scope 2 at $DIR/issue_76432.rs:9:54: 9:56 + _19 = &raw const (*_2)[1 of 3]; // scope 2 at $DIR/issue_76432.rs:9:54: 9:56 _18 = _19; // scope 2 at $DIR/issue_76432.rs:9:54: 9:68 StorageLive(_20); // scope 2 at $DIR/issue_76432.rs:9:70: 9:84 StorageLive(_21); // scope 2 at $DIR/issue_76432.rs:9:70: 9:84 - _21 = &raw const (*_15); // scope 2 at $DIR/issue_76432.rs:9:70: 9:72 + _21 = &raw const (*_2)[2 of 3]; // scope 2 at $DIR/issue_76432.rs:9:70: 9:72 _20 = _21; // scope 2 at $DIR/issue_76432.rs:9:70: 9:84 _9 = [move _16, move _18, move _20]; // scope 2 at $DIR/issue_76432.rs:9:37: 9:85 StorageDead(_21); // scope 2 at $DIR/issue_76432.rs:9:84: 9:85 diff --git a/src/test/mir-opt/issue_78192.f.InstCombine.diff b/src/test/mir-opt/issue_78192.f.UnneededDeref.diff similarity index 87% rename from src/test/mir-opt/issue_78192.f.InstCombine.diff rename to src/test/mir-opt/issue_78192.f.UnneededDeref.diff index ec3be78525802..0c1795f91290d 100644 --- a/src/test/mir-opt/issue_78192.f.InstCombine.diff +++ b/src/test/mir-opt/issue_78192.f.UnneededDeref.diff @@ -1,5 +1,5 @@ -- // MIR for `f` before InstCombine -+ // MIR for `f` after InstCombine +- // MIR for `f` before UnneededDeref ++ // MIR for `f` after UnneededDeref fn f(_1: &T) -> *const T { debug a => _1; // in scope 0 at $DIR/issue-78192.rs:2:13: 2:14 @@ -17,8 +17,7 @@ StorageLive(_4); // scope 0 at $DIR/issue-78192.rs:3:25: 3:40 _4 = &raw const (*_1); // scope 0 at $DIR/issue-78192.rs:3:26: 3:27 _3 = &_4; // scope 0 at $DIR/issue-78192.rs:3:24: 3:40 -- _2 = &(*_3); // scope 0 at $DIR/issue-78192.rs:3:24: 3:40 -+ _2 = _3; // scope 0 at $DIR/issue-78192.rs:3:24: 3:40 + _2 = _3; // scope 0 at $DIR/issue-78192.rs:3:24: 3:40 StorageDead(_3); // scope 0 at $DIR/issue-78192.rs:3:40: 3:41 _0 = (*_2); // scope 1 at $DIR/issue-78192.rs:4:5: 4:7 StorageDead(_4); // scope 0 at $DIR/issue-78192.rs:5:1: 5:2 diff --git a/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff b/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff deleted file mode 100644 index c3e503bf2c686..0000000000000 --- a/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff +++ /dev/null @@ -1,72 +0,0 @@ -- // MIR for `try_identity` before DestinationPropagation -+ // MIR for `try_identity` after DestinationPropagation - - fn try_identity(_1: std::result::Result) -> std::result::Result { - debug x => _1; // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18 - let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57 - let _2: u32; // in scope 0 at $DIR/simplify_try.rs:7:9: 7:10 - let mut _3: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15 - let mut _4: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:14 - let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15 - let _6: i32; // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15 - let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15 - let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15 - let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15 - let _10: u32; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15 - let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:8:8: 8:9 - scope 1 { - debug y => _2; // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10 - } - scope 2 { - debug err => _6; // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15 - scope 3 { - scope 7 { - debug t => _9; // in scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL - } - scope 8 { - debug v => _8; // in scope 8 at $SRC_DIR/libcore/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:7:14: 7:15 - } - } - } - scope 4 { - debug val => _10; // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15 - scope 5 { - } - } - scope 6 { -- debug self => _4; // in scope 6 at $SRC_DIR/libcore/result.rs:LL:COL -+ debug self => _0; // in scope 6 at $SRC_DIR/libcore/result.rs:LL:COL - } - - bb0: { - StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:7:9: 7:10 -- StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:7:13: 7:15 -- StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:7:13: 7:14 -- _4 = _1; // scope 0 at $DIR/simplify_try.rs:7:13: 7:14 -- _3 = move _4; // scope 6 at $SRC_DIR/libcore/result.rs:LL:COL -- StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:7:14: 7:15 -- _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:7:14: 7:15 -+ nop; // scope 0 at $DIR/simplify_try.rs:7:13: 7:15 -+ nop; // scope 0 at $DIR/simplify_try.rs:7:13: 7:14 -+ _0 = _1; // scope 0 at $DIR/simplify_try.rs:7:13: 7:14 -+ nop; // scope 6 at $SRC_DIR/libcore/result.rs:LL:COL -+ nop; // scope 0 at $DIR/simplify_try.rs:7:14: 7:15 -+ _5 = discriminant(_0); // scope 0 at $DIR/simplify_try.rs:7:14: 7:15 - goto -> bb1; // scope 0 at $DIR/simplify_try.rs:7:14: 7:15 - } - - bb1: { -- _0 = move _3; // scope 1 at $DIR/simplify_try.rs:8:5: 8:10 -- StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:7:15: 7:16 -+ nop; // scope 1 at $DIR/simplify_try.rs:8:5: 8:10 -+ nop; // scope 0 at $DIR/simplify_try.rs:7:15: 7:16 - StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:9:1: 9:2 - goto -> bb2; // scope 0 at $DIR/simplify_try.rs:9:2: 9:2 - } - - bb2: { - return; // scope 0 at $DIR/simplify_try.rs:9:2: 9:2 - } - } - diff --git a/src/test/mir-opt/simplify_try_if_let.{impl#0}-append.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try_if_let.{impl#0}-append.SimplifyArmIdentity.diff deleted file mode 100644 index 11f6b5337414a..0000000000000 --- a/src/test/mir-opt/simplify_try_if_let.{impl#0}-append.SimplifyArmIdentity.diff +++ /dev/null @@ -1,104 +0,0 @@ -- // MIR for `::append` before SimplifyArmIdentity -+ // MIR for `::append` after SimplifyArmIdentity - - fn ::append(_1: &mut LinkedList, _2: &mut LinkedList) -> () { - debug self => _1; // in scope 0 at $DIR/simplify_try_if_let.rs:20:19: 20:28 - debug other => _2; // in scope 0 at $DIR/simplify_try_if_let.rs:20:30: 20:35 - let mut _0: (); // return place in scope 0 at $DIR/simplify_try_if_let.rs:20:48: 20:48 - let mut _3: isize; // in scope 0 at $DIR/simplify_try_if_let.rs:22:13: 22:17 - let mut _4: std::ptr::NonNull; // in scope 0 at $DIR/simplify_try_if_let.rs:23:18: 23:26 - let mut _5: std::option::Option>; // in scope 0 at $DIR/simplify_try_if_let.rs:26:43: 26:60 - let mut _6: &mut std::option::Option>; // in scope 0 at $DIR/simplify_try_if_let.rs:26:43: 26:53 - let mut _7: isize; // in scope 0 at $DIR/simplify_try_if_let.rs:26:24: 26:40 - let mut _9: std::option::Option>; // in scope 0 at $DIR/simplify_try_if_let.rs:28:46: 28:62 - let mut _10: std::ptr::NonNull; // in scope 0 at $DIR/simplify_try_if_let.rs:28:51: 28:61 - let mut _11: &mut Node; // in scope 0 at $DIR/simplify_try_if_let.rs:28:25: 28:38 - let mut _12: &mut std::ptr::NonNull; // in scope 0 at $DIR/simplify_try_if_let.rs:28:25: 28:29 - scope 1 { - debug tail => _4; // in scope 1 at $DIR/simplify_try_if_let.rs:23:18: 23:26 - let _8: std::ptr::NonNull; // in scope 1 at $DIR/simplify_try_if_let.rs:26:29: 26:39 - scope 2 { -- debug other_head => _8; // in scope 2 at $DIR/simplify_try_if_let.rs:26:29: 26:39 -+ debug other_head => ((_9 as Some).0: std::ptr::NonNull); // in scope 2 at $DIR/simplify_try_if_let.rs:26:29: 26:39 - scope 3 { - } - } - } - - bb0: { - _3 = discriminant(((*_1).1: std::option::Option>)); // scope 0 at $DIR/simplify_try_if_let.rs:22:13: 22:17 - switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try_if_let.rs:22:13: 22:17 - } - - bb1: { - StorageLive(_4); // scope 0 at $DIR/simplify_try_if_let.rs:23:18: 23:26 - _4 = ((((*_1).1: std::option::Option>) as Some).0: std::ptr::NonNull); // scope 0 at $DIR/simplify_try_if_let.rs:23:18: 23:26 - StorageLive(_5); // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:60 - StorageLive(_6); // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:53 - _6 = &mut ((*_2).0: std::option::Option>); // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:53 - _5 = Option::>::take(move _6) -> bb4; // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:60 - // mir::Constant - // + span: $DIR/simplify_try_if_let.rs:26:54: 26:58 - // + literal: Const { ty: for<'r> fn(&'r mut std::option::Option>) -> std::option::Option> {std::option::Option::>::take}, val: Value(Scalar()) } - } - - bb2: { - unreachable; // scope 0 at $DIR/simplify_try_if_let.rs:21:15: 21:24 - } - - bb3: { - _0 = const (); // scope 0 at $DIR/simplify_try_if_let.rs:22:21: 22:24 - goto -> bb9; // scope 0 at $DIR/simplify_try_if_let.rs:21:9: 32:10 - } - - bb4: { - StorageDead(_6); // scope 1 at $DIR/simplify_try_if_let.rs:26:59: 26:60 - _7 = discriminant(_5); // scope 1 at $DIR/simplify_try_if_let.rs:26:24: 26:40 - switchInt(move _7) -> [1_isize: bb6, otherwise: bb5]; // scope 1 at $DIR/simplify_try_if_let.rs:26:24: 26:40 - } - - bb5: { - _0 = const (); // scope 1 at $DIR/simplify_try_if_let.rs:26:17: 30:18 - goto -> bb8; // scope 1 at $DIR/simplify_try_if_let.rs:26:17: 30:18 - } - - bb6: { - StorageLive(_8); // scope 1 at $DIR/simplify_try_if_let.rs:26:29: 26:39 - _8 = ((_5 as Some).0: std::ptr::NonNull); // scope 1 at $DIR/simplify_try_if_let.rs:26:29: 26:39 - StorageLive(_9); // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62 -- StorageLive(_10); // scope 3 at $DIR/simplify_try_if_let.rs:28:51: 28:61 -- _10 = _8; // scope 3 at $DIR/simplify_try_if_let.rs:28:51: 28:61 -- ((_9 as Some).0: std::ptr::NonNull) = move _10; // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62 -- discriminant(_9) = 1; // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62 -- StorageDead(_10); // scope 3 at $DIR/simplify_try_if_let.rs:28:61: 28:62 -+ _9 = move _5; // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62 - StorageLive(_11); // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:38 - StorageLive(_12); // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:29 - _12 = &mut _4; // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:29 - _11 = NonNull::::as_mut(move _12) -> bb7; // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:38 - // mir::Constant - // + span: $DIR/simplify_try_if_let.rs:28:30: 28:36 - // + literal: Const { ty: for<'r> unsafe fn(&'r mut std::ptr::NonNull) -> &'r mut Node {std::ptr::NonNull::::as_mut}, val: Value(Scalar()) } - } - - bb7: { - StorageDead(_12); // scope 3 at $DIR/simplify_try_if_let.rs:28:37: 28:38 - ((*_11).0: std::option::Option>) = move _9; // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:62 - StorageDead(_9); // scope 3 at $DIR/simplify_try_if_let.rs:28:61: 28:62 - StorageDead(_11); // scope 3 at $DIR/simplify_try_if_let.rs:28:62: 28:63 - _0 = const (); // scope 3 at $DIR/simplify_try_if_let.rs:27:21: 29:22 - StorageDead(_8); // scope 1 at $DIR/simplify_try_if_let.rs:30:17: 30:18 - goto -> bb8; // scope 1 at $DIR/simplify_try_if_let.rs:26:17: 30:18 - } - - bb8: { - StorageDead(_5); // scope 1 at $DIR/simplify_try_if_let.rs:31:13: 31:14 - StorageDead(_4); // scope 0 at $DIR/simplify_try_if_let.rs:31:13: 31:14 - goto -> bb9; // scope 0 at $DIR/simplify_try_if_let.rs:21:9: 32:10 - } - - bb9: { - return; // scope 0 at $DIR/simplify_try_if_let.rs:33:6: 33:6 - } - } - diff --git a/src/test/mir-opt/unneeded_deref.deep_opt.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref.deep_opt.UnneededDeref.diff new file mode 100644 index 0000000000000..c4f8298795751 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref.deep_opt.UnneededDeref.diff @@ -0,0 +1,92 @@ +- // MIR for `deep_opt` before UnneededDeref ++ // MIR for `deep_opt` after UnneededDeref + + fn deep_opt() -> (u64, u64, u64) { + let mut _0: (u64, u64, u64); // return place in scope 0 at $DIR/unneeded_deref.rs:11:18: 11:33 + let _1: u64; // in scope 0 at $DIR/unneeded_deref.rs:12:9: 12:11 + let mut _10: u64; // in scope 0 at $DIR/unneeded_deref.rs:21:6: 21:8 + let mut _11: u64; // in scope 0 at $DIR/unneeded_deref.rs:21:10: 21:12 + let mut _12: u64; // in scope 0 at $DIR/unneeded_deref.rs:21:14: 21:16 + scope 1 { + debug x1 => _1; // in scope 1 at $DIR/unneeded_deref.rs:12:9: 12:11 + let _2: u64; // in scope 1 at $DIR/unneeded_deref.rs:13:9: 13:11 + scope 2 { + debug x2 => _2; // in scope 2 at $DIR/unneeded_deref.rs:13:9: 13:11 + let _3: u64; // in scope 2 at $DIR/unneeded_deref.rs:14:9: 14:11 + scope 3 { + debug x3 => _3; // in scope 3 at $DIR/unneeded_deref.rs:14:9: 14:11 + let _4: &u64; // in scope 3 at $DIR/unneeded_deref.rs:15:9: 15:11 + scope 4 { + debug y1 => _4; // in scope 4 at $DIR/unneeded_deref.rs:15:9: 15:11 + let _5: &u64; // in scope 4 at $DIR/unneeded_deref.rs:16:9: 16:11 + scope 5 { + debug y2 => _5; // in scope 5 at $DIR/unneeded_deref.rs:16:9: 16:11 + let _6: &u64; // in scope 5 at $DIR/unneeded_deref.rs:17:9: 17:11 + scope 6 { + debug y3 => _6; // in scope 6 at $DIR/unneeded_deref.rs:17:9: 17:11 + let _7: u64; // in scope 6 at $DIR/unneeded_deref.rs:18:9: 18:11 + scope 7 { + debug z1 => _7; // in scope 7 at $DIR/unneeded_deref.rs:18:9: 18:11 + let _8: u64; // in scope 7 at $DIR/unneeded_deref.rs:19:9: 19:11 + scope 8 { + debug z2 => _8; // in scope 8 at $DIR/unneeded_deref.rs:19:9: 19:11 + let _9: u64; // in scope 8 at $DIR/unneeded_deref.rs:20:9: 20:11 + scope 9 { + debug z3 => _9; // in scope 9 at $DIR/unneeded_deref.rs:20:9: 20:11 + } + } + } + } + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/unneeded_deref.rs:12:9: 12:11 + _1 = const 1_u64; // scope 0 at $DIR/unneeded_deref.rs:12:14: 12:15 + StorageLive(_2); // scope 1 at $DIR/unneeded_deref.rs:13:9: 13:11 + _2 = const 2_u64; // scope 1 at $DIR/unneeded_deref.rs:13:14: 13:15 + StorageLive(_3); // scope 2 at $DIR/unneeded_deref.rs:14:9: 14:11 + _3 = const 3_u64; // scope 2 at $DIR/unneeded_deref.rs:14:14: 14:15 + StorageLive(_4); // scope 3 at $DIR/unneeded_deref.rs:15:9: 15:11 + _4 = &_1; // scope 3 at $DIR/unneeded_deref.rs:15:14: 15:17 + StorageLive(_5); // scope 4 at $DIR/unneeded_deref.rs:16:9: 16:11 + _5 = &_2; // scope 4 at $DIR/unneeded_deref.rs:16:14: 16:17 + StorageLive(_6); // scope 5 at $DIR/unneeded_deref.rs:17:9: 17:11 + _6 = &_3; // scope 5 at $DIR/unneeded_deref.rs:17:14: 17:17 + StorageLive(_7); // scope 6 at $DIR/unneeded_deref.rs:18:9: 18:11 +- _7 = (*_4); // scope 6 at $DIR/unneeded_deref.rs:18:14: 18:17 ++ _7 = _1; // scope 6 at $DIR/unneeded_deref.rs:18:14: 18:17 + StorageLive(_8); // scope 7 at $DIR/unneeded_deref.rs:19:9: 19:11 +- _8 = (*_5); // scope 7 at $DIR/unneeded_deref.rs:19:14: 19:17 ++ _8 = _2; // scope 7 at $DIR/unneeded_deref.rs:19:14: 19:17 + StorageLive(_9); // scope 8 at $DIR/unneeded_deref.rs:20:9: 20:11 +- _9 = (*_6); // scope 8 at $DIR/unneeded_deref.rs:20:14: 20:17 ++ _9 = _3; // scope 8 at $DIR/unneeded_deref.rs:20:14: 20:17 + StorageLive(_10); // scope 9 at $DIR/unneeded_deref.rs:21:6: 21:8 + _10 = _7; // scope 9 at $DIR/unneeded_deref.rs:21:6: 21:8 + StorageLive(_11); // scope 9 at $DIR/unneeded_deref.rs:21:10: 21:12 + _11 = _8; // scope 9 at $DIR/unneeded_deref.rs:21:10: 21:12 + StorageLive(_12); // scope 9 at $DIR/unneeded_deref.rs:21:14: 21:16 + _12 = _9; // scope 9 at $DIR/unneeded_deref.rs:21:14: 21:16 + (_0.0: u64) = move _10; // scope 9 at $DIR/unneeded_deref.rs:21:5: 21:17 + (_0.1: u64) = move _11; // scope 9 at $DIR/unneeded_deref.rs:21:5: 21:17 + (_0.2: u64) = move _12; // scope 9 at $DIR/unneeded_deref.rs:21:5: 21:17 + StorageDead(_12); // scope 9 at $DIR/unneeded_deref.rs:21:16: 21:17 + StorageDead(_11); // scope 9 at $DIR/unneeded_deref.rs:21:16: 21:17 + StorageDead(_10); // scope 9 at $DIR/unneeded_deref.rs:21:16: 21:17 + StorageDead(_9); // scope 8 at $DIR/unneeded_deref.rs:22:1: 22:2 + StorageDead(_8); // scope 7 at $DIR/unneeded_deref.rs:22:1: 22:2 + StorageDead(_7); // scope 6 at $DIR/unneeded_deref.rs:22:1: 22:2 + StorageDead(_6); // scope 5 at $DIR/unneeded_deref.rs:22:1: 22:2 + StorageDead(_5); // scope 4 at $DIR/unneeded_deref.rs:22:1: 22:2 + StorageDead(_4); // scope 3 at $DIR/unneeded_deref.rs:22:1: 22:2 + StorageDead(_3); // scope 2 at $DIR/unneeded_deref.rs:22:1: 22:2 + StorageDead(_2); // scope 1 at $DIR/unneeded_deref.rs:22:1: 22:2 + StorageDead(_1); // scope 0 at $DIR/unneeded_deref.rs:22:1: 22:2 + return; // scope 0 at $DIR/unneeded_deref.rs:22:2: 22:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref.operand_opt.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref.operand_opt.UnneededDeref.diff new file mode 100644 index 0000000000000..7cc342ded6593 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref.operand_opt.UnneededDeref.diff @@ -0,0 +1,71 @@ +- // MIR for `operand_opt` before UnneededDeref ++ // MIR for `operand_opt` after UnneededDeref + + fn operand_opt(_1: Option) -> bool { + debug input => _1; // in scope 0 at $DIR/unneeded_deref.rs:87:25: 87:30 + let mut _0: bool; // return place in scope 0 at $DIR/unneeded_deref.rs:87:46: 87:50 + let _2: bool; // in scope 0 at $DIR/unneeded_deref.rs:88:9: 88:10 + let mut _3: &std::option::Option; // in scope 0 at $DIR/unneeded_deref.rs:88:13: 88:18 + let mut _5: &std::option::Option; // in scope 0 at $DIR/unneeded_deref.rs:89:13: 89:18 + let mut _6: bool; // in scope 0 at $DIR/unneeded_deref.rs:90:5: 90:6 + let mut _7: bool; // in scope 0 at $DIR/unneeded_deref.rs:90:10: 90:11 + let mut _10: isize; // in scope 0 at $DIR/unneeded_deref.rs:88:13: 88:28 + let mut _11: isize; // in scope 0 at $DIR/unneeded_deref.rs:89:13: 89:28 + scope 1 { + debug x => _2; // in scope 1 at $DIR/unneeded_deref.rs:88:9: 88:10 + let _4: bool; // in scope 1 at $DIR/unneeded_deref.rs:89:9: 89:10 + scope 2 { + debug y => _4; // in scope 2 at $DIR/unneeded_deref.rs:89:9: 89:10 + } + scope 4 (inlined Option::::is_some) { // at $DIR/unneeded_deref.rs:89:13: 89:28 + debug self => _5; // in scope 4 at $DIR/unneeded_deref.rs:89:13: 89:28 + let mut _9: isize; // in scope 4 at $DIR/unneeded_deref.rs:89:13: 89:28 + } + } + scope 3 (inlined Option::::is_some) { // at $DIR/unneeded_deref.rs:88:13: 88:28 + debug self => _3; // in scope 3 at $DIR/unneeded_deref.rs:88:13: 88:28 + let mut _8: isize; // in scope 3 at $DIR/unneeded_deref.rs:88:13: 88:28 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/unneeded_deref.rs:88:9: 88:10 + StorageLive(_3); // scope 0 at $DIR/unneeded_deref.rs:88:13: 88:18 + _3 = &_1; // scope 0 at $DIR/unneeded_deref.rs:88:13: 88:18 +- _8 = discriminant((*_3)); // scope 3 at $DIR/unneeded_deref.rs:88:13: 88:28 ++ _8 = discriminant(_1); // scope 3 at $DIR/unneeded_deref.rs:88:13: 88:28 + StorageLive(_10); // scope 3 at $DIR/unneeded_deref.rs:88:13: 88:28 + _10 = move _8; // scope 3 at $DIR/unneeded_deref.rs:88:13: 88:28 + _2 = Eq(_10, const 1_isize); // scope 3 at $DIR/unneeded_deref.rs:88:13: 88:28 + StorageDead(_10); // scope 3 at $DIR/unneeded_deref.rs:88:13: 88:28 + goto -> bb1; // scope 3 at $DIR/unneeded_deref.rs:88:13: 88:28 + } + + bb1: { + StorageDead(_3); // scope 0 at $DIR/unneeded_deref.rs:88:27: 88:28 + StorageLive(_4); // scope 1 at $DIR/unneeded_deref.rs:89:9: 89:10 + StorageLive(_5); // scope 1 at $DIR/unneeded_deref.rs:89:13: 89:18 + _5 = &_1; // scope 1 at $DIR/unneeded_deref.rs:89:13: 89:18 +- _9 = discriminant((*_5)); // scope 4 at $DIR/unneeded_deref.rs:89:13: 89:28 ++ _9 = discriminant(_1); // scope 4 at $DIR/unneeded_deref.rs:89:13: 89:28 + StorageLive(_11); // scope 4 at $DIR/unneeded_deref.rs:89:13: 89:28 + _11 = move _9; // scope 4 at $DIR/unneeded_deref.rs:89:13: 89:28 + _4 = Eq(_11, const 1_isize); // scope 4 at $DIR/unneeded_deref.rs:89:13: 89:28 + StorageDead(_11); // scope 4 at $DIR/unneeded_deref.rs:89:13: 89:28 + goto -> bb2; // scope 4 at $DIR/unneeded_deref.rs:89:13: 89:28 + } + + bb2: { + StorageDead(_5); // scope 1 at $DIR/unneeded_deref.rs:89:27: 89:28 + StorageLive(_6); // scope 2 at $DIR/unneeded_deref.rs:90:5: 90:6 + _6 = _2; // scope 2 at $DIR/unneeded_deref.rs:90:5: 90:6 + StorageLive(_7); // scope 2 at $DIR/unneeded_deref.rs:90:10: 90:11 + _7 = _4; // scope 2 at $DIR/unneeded_deref.rs:90:10: 90:11 + _0 = Eq(move _6, move _7); // scope 2 at $DIR/unneeded_deref.rs:90:5: 90:11 + StorageDead(_7); // scope 2 at $DIR/unneeded_deref.rs:90:10: 90:11 + StorageDead(_6); // scope 2 at $DIR/unneeded_deref.rs:90:10: 90:11 + StorageDead(_4); // scope 1 at $DIR/unneeded_deref.rs:91:1: 91:2 + StorageDead(_2); // scope 0 at $DIR/unneeded_deref.rs:91:1: 91:2 + return; // scope 0 at $DIR/unneeded_deref.rs:91:2: 91:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref.opt_different_bbs.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref.opt_different_bbs.UnneededDeref.diff new file mode 100644 index 0000000000000..6ed3cd3dc5762 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref.opt_different_bbs.UnneededDeref.diff @@ -0,0 +1,58 @@ +- // MIR for `opt_different_bbs` before UnneededDeref ++ // MIR for `opt_different_bbs` after UnneededDeref + + fn opt_different_bbs(_1: bool) -> u64 { + debug input => _1; // in scope 0 at $DIR/unneeded_deref.rs:70:22: 70:27 + let mut _0: u64; // return place in scope 0 at $DIR/unneeded_deref.rs:70:38: 70:41 + let _2: u64; // in scope 0 at $DIR/unneeded_deref.rs:71:9: 71:10 + let mut _4: i32; // in scope 0 at $DIR/unneeded_deref.rs:73:13: 73:38 + let mut _5: bool; // in scope 0 at $DIR/unneeded_deref.rs:73:16: 73:21 + scope 1 { + debug x => _2; // in scope 1 at $DIR/unneeded_deref.rs:71:9: 71:10 + let _3: &u64; // in scope 1 at $DIR/unneeded_deref.rs:72:9: 72:10 + scope 2 { + debug y => _3; // in scope 2 at $DIR/unneeded_deref.rs:72:9: 72:10 + scope 3 { + let _6: u64; // in scope 3 at $DIR/unneeded_deref.rs:74:9: 74:10 + scope 4 { + debug z => _6; // in scope 4 at $DIR/unneeded_deref.rs:74:9: 74:10 + } + } + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/unneeded_deref.rs:71:9: 71:10 + _2 = const 5_u64; // scope 0 at $DIR/unneeded_deref.rs:71:13: 71:14 + StorageLive(_3); // scope 1 at $DIR/unneeded_deref.rs:72:9: 72:10 + _3 = &_2; // scope 1 at $DIR/unneeded_deref.rs:72:13: 72:15 + StorageLive(_4); // scope 2 at $DIR/unneeded_deref.rs:73:13: 73:38 + StorageLive(_5); // scope 2 at $DIR/unneeded_deref.rs:73:16: 73:21 + _5 = _1; // scope 2 at $DIR/unneeded_deref.rs:73:16: 73:21 + switchInt(_5) -> [false: bb1, otherwise: bb2]; // scope 2 at $DIR/unneeded_deref.rs:73:13: 73:38 + } + + bb1: { + _4 = const 3_i32; // scope 2 at $DIR/unneeded_deref.rs:73:35: 73:36 + goto -> bb3; // scope 2 at $DIR/unneeded_deref.rs:73:13: 73:38 + } + + bb2: { + _4 = const 2_i32; // scope 2 at $DIR/unneeded_deref.rs:73:24: 73:25 + goto -> bb3; // scope 2 at $DIR/unneeded_deref.rs:73:13: 73:38 + } + + bb3: { + StorageDead(_5); // scope 2 at $DIR/unneeded_deref.rs:73:38: 73:39 + StorageDead(_4); // scope 2 at $DIR/unneeded_deref.rs:73:38: 73:39 + StorageLive(_6); // scope 3 at $DIR/unneeded_deref.rs:74:9: 74:10 +- _6 = (*_3); // scope 3 at $DIR/unneeded_deref.rs:74:13: 74:15 ++ _6 = _2; // scope 3 at $DIR/unneeded_deref.rs:74:13: 74:15 + _0 = _6; // scope 4 at $DIR/unneeded_deref.rs:75:5: 75:6 + StorageDead(_6); // scope 3 at $DIR/unneeded_deref.rs:76:1: 76:2 + StorageDead(_3); // scope 1 at $DIR/unneeded_deref.rs:76:1: 76:2 + StorageDead(_2); // scope 0 at $DIR/unneeded_deref.rs:76:1: 76:2 + return; // scope 0 at $DIR/unneeded_deref.rs:76:2: 76:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref.opt_different_bbs2.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref.opt_different_bbs2.UnneededDeref.diff new file mode 100644 index 0000000000000..3ef7925a95f96 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref.opt_different_bbs2.UnneededDeref.diff @@ -0,0 +1,52 @@ +- // MIR for `opt_different_bbs2` before UnneededDeref ++ // MIR for `opt_different_bbs2` after UnneededDeref + + fn opt_different_bbs2(_1: bool) -> u64 { + debug input => _1; // in scope 0 at $DIR/unneeded_deref.rs:79:23: 79:28 + let mut _0: u64; // return place in scope 0 at $DIR/unneeded_deref.rs:79:39: 79:42 + let _2: u64; // in scope 0 at $DIR/unneeded_deref.rs:80:9: 80:10 + let mut _5: bool; // in scope 0 at $DIR/unneeded_deref.rs:82:16: 82:21 + scope 1 { + debug x => _2; // in scope 1 at $DIR/unneeded_deref.rs:80:9: 80:10 + let _3: &u64; // in scope 1 at $DIR/unneeded_deref.rs:81:9: 81:10 + scope 2 { + debug y => _3; // in scope 2 at $DIR/unneeded_deref.rs:81:9: 81:10 + let _4: u64; // in scope 2 at $DIR/unneeded_deref.rs:82:9: 82:10 + scope 3 { + debug z => _4; // in scope 3 at $DIR/unneeded_deref.rs:82:9: 82:10 + } + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/unneeded_deref.rs:80:9: 80:10 + _2 = const 5_u64; // scope 0 at $DIR/unneeded_deref.rs:80:13: 80:14 + StorageLive(_3); // scope 1 at $DIR/unneeded_deref.rs:81:9: 81:10 + _3 = &_2; // scope 1 at $DIR/unneeded_deref.rs:81:13: 81:15 + StorageLive(_4); // scope 2 at $DIR/unneeded_deref.rs:82:9: 82:10 + StorageLive(_5); // scope 2 at $DIR/unneeded_deref.rs:82:16: 82:21 + _5 = _1; // scope 2 at $DIR/unneeded_deref.rs:82:16: 82:21 + switchInt(_5) -> [false: bb1, otherwise: bb2]; // scope 2 at $DIR/unneeded_deref.rs:82:13: 82:39 + } + + bb1: { + _4 = const 3_u64; // scope 2 at $DIR/unneeded_deref.rs:82:36: 82:37 + goto -> bb3; // scope 2 at $DIR/unneeded_deref.rs:82:13: 82:39 + } + + bb2: { +- _4 = (*_3); // scope 2 at $DIR/unneeded_deref.rs:82:24: 82:26 ++ _4 = _2; // scope 2 at $DIR/unneeded_deref.rs:82:24: 82:26 + goto -> bb3; // scope 2 at $DIR/unneeded_deref.rs:82:13: 82:39 + } + + bb3: { + StorageDead(_5); // scope 2 at $DIR/unneeded_deref.rs:82:39: 82:40 + _0 = _4; // scope 3 at $DIR/unneeded_deref.rs:83:5: 83:6 + StorageDead(_4); // scope 2 at $DIR/unneeded_deref.rs:84:1: 84:2 + StorageDead(_3); // scope 1 at $DIR/unneeded_deref.rs:84:1: 84:2 + StorageDead(_2); // scope 0 at $DIR/unneeded_deref.rs:84:1: 84:2 + return; // scope 0 at $DIR/unneeded_deref.rs:84:2: 84:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref.opt_struct.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref.opt_struct.UnneededDeref.diff new file mode 100644 index 0000000000000..078ac8e0ab268 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref.opt_struct.UnneededDeref.diff @@ -0,0 +1,44 @@ +- // MIR for `opt_struct` before UnneededDeref ++ // MIR for `opt_struct` after UnneededDeref + + fn opt_struct(_1: S) -> u64 { + debug s => _1; // in scope 0 at $DIR/unneeded_deref.rs:30:15: 30:16 + let mut _0: u64; // return place in scope 0 at $DIR/unneeded_deref.rs:30:24: 30:27 + let _2: &u64; // in scope 0 at $DIR/unneeded_deref.rs:31:9: 31:10 + let mut _5: u64; // in scope 0 at $DIR/unneeded_deref.rs:34:5: 34:7 + let mut _6: u64; // in scope 0 at $DIR/unneeded_deref.rs:34:10: 34:11 + scope 1 { + debug a => _2; // in scope 1 at $DIR/unneeded_deref.rs:31:9: 31:10 + let _3: &u64; // in scope 1 at $DIR/unneeded_deref.rs:32:9: 32:10 + scope 2 { + debug b => _3; // in scope 2 at $DIR/unneeded_deref.rs:32:9: 32:10 + let _4: u64; // in scope 2 at $DIR/unneeded_deref.rs:33:9: 33:10 + scope 3 { + debug x => _4; // in scope 3 at $DIR/unneeded_deref.rs:33:9: 33:10 + } + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/unneeded_deref.rs:31:9: 31:10 + _2 = &(_1.0: u64); // scope 0 at $DIR/unneeded_deref.rs:31:13: 31:17 + StorageLive(_3); // scope 1 at $DIR/unneeded_deref.rs:32:9: 32:10 + _3 = &(_1.1: u64); // scope 1 at $DIR/unneeded_deref.rs:32:13: 32:17 + StorageLive(_4); // scope 2 at $DIR/unneeded_deref.rs:33:9: 33:10 +- _4 = (*_2); // scope 2 at $DIR/unneeded_deref.rs:33:13: 33:15 ++ _4 = (_1.0: u64); // scope 2 at $DIR/unneeded_deref.rs:33:13: 33:15 + StorageLive(_5); // scope 3 at $DIR/unneeded_deref.rs:34:5: 34:7 +- _5 = (*_3); // scope 3 at $DIR/unneeded_deref.rs:34:5: 34:7 ++ _5 = (_1.1: u64); // scope 3 at $DIR/unneeded_deref.rs:34:5: 34:7 + StorageLive(_6); // scope 3 at $DIR/unneeded_deref.rs:34:10: 34:11 + _6 = _4; // scope 3 at $DIR/unneeded_deref.rs:34:10: 34:11 + _0 = Add(move _5, move _6); // scope 3 at $DIR/unneeded_deref.rs:34:5: 34:11 + StorageDead(_6); // scope 3 at $DIR/unneeded_deref.rs:34:10: 34:11 + StorageDead(_5); // scope 3 at $DIR/unneeded_deref.rs:34:10: 34:11 + StorageDead(_4); // scope 2 at $DIR/unneeded_deref.rs:35:1: 35:2 + StorageDead(_3); // scope 1 at $DIR/unneeded_deref.rs:35:1: 35:2 + StorageDead(_2); // scope 0 at $DIR/unneeded_deref.rs:35:1: 35:2 + return; // scope 0 at $DIR/unneeded_deref.rs:35:2: 35:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref.rs b/src/test/mir-opt/unneeded_deref.rs new file mode 100644 index 0000000000000..a49aec44d2ace --- /dev/null +++ b/src/test/mir-opt/unneeded_deref.rs @@ -0,0 +1,101 @@ +// compile-flags: -O -Zunsound-mir-opts +// EMIT_MIR unneeded_deref.simple_opt.UnneededDeref.diff +fn simple_opt() -> u64 { + let x = 5; + let y = &x; + let z = *y; + z +} + +// EMIT_MIR unneeded_deref.deep_opt.UnneededDeref.diff +fn deep_opt() -> (u64, u64, u64) { + let x1 = 1; + let x2 = 2; + let x3 = 3; + let y1 = &x1; + let y2 = &x2; + let y3 = &x3; + let z1 = *y1; + let z2 = *y2; + let z3 = *y3; + (z1, z2, z3) +} + +struct S { + a: u64, + b: u64, +} + +// EMIT_MIR unneeded_deref.opt_struct.UnneededDeref.diff +fn opt_struct(s: S) -> u64 { + let a = &s.a; + let b = &s.b; + let x = *a; + *b + x +} + +// EMIT_MIR unneeded_deref.very_deep_opt.UnneededDeref.diff +fn very_deep_opt() -> (u64, u64, u64, u64, u64, u64, u64, u64, u64) { + let x1 = 1; + let x2 = 2; + let x3 = 3; + let x4 = 4; + let x5 = 5; + let x6 = 6; + let x7 = 7; + let x8 = 8; + let x9 = 9; + let y1 = &x1; + let y2 = &x2; + let y3 = &x3; + let y4 = &x4; + let y5 = &x5; + let y6 = &x6; + let y7 = &x7; + let y8 = &x8; + let y9 = &x9; + let z1 = *y1; + let z2 = *y2; + let z3 = *y3; + let z4 = *y4; + let z5 = *y5; + let z6 = *y6; + let z7 = *y7; + let z8 = *y8; + let z9 = *y9; + (z1, z2, z3, z4, z5, z6, z7, z8, z9) +} + +// EMIT_MIR unneeded_deref.opt_different_bbs.UnneededDeref.diff +fn opt_different_bbs(input: bool) -> u64 { + let x = 5; + let y = &x; + let _ = if input { 2 } else { 3 }; + let z = *y; + z +} + +// EMIT_MIR unneeded_deref.opt_different_bbs2.UnneededDeref.diff +fn opt_different_bbs2(input: bool) -> u64 { + let x = 5; + let y = &x; + let z = if input { *y } else { 3 }; + z +} + +// EMIT_MIR unneeded_deref.operand_opt.UnneededDeref.diff +fn operand_opt(input: Option) -> bool { + let x = input.is_some(); + let y = input.is_some(); + x == y +} + +fn main() { + simple_opt(); + deep_opt(); + opt_struct(S { a: 0, b: 1 }); + very_deep_opt(); + opt_different_bbs(false); + opt_different_bbs2(false); + operand_opt(Some(true)); +} diff --git a/src/test/mir-opt/unneeded_deref.simple_opt.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref.simple_opt.UnneededDeref.diff new file mode 100644 index 0000000000000..eb91889dde87f --- /dev/null +++ b/src/test/mir-opt/unneeded_deref.simple_opt.UnneededDeref.diff @@ -0,0 +1,34 @@ +- // MIR for `simple_opt` before UnneededDeref ++ // MIR for `simple_opt` after UnneededDeref + + fn simple_opt() -> u64 { + let mut _0: u64; // return place in scope 0 at $DIR/unneeded_deref.rs:3:20: 3:23 + let _1: u64; // in scope 0 at $DIR/unneeded_deref.rs:4:9: 4:10 + scope 1 { + debug x => _1; // in scope 1 at $DIR/unneeded_deref.rs:4:9: 4:10 + let _2: &u64; // in scope 1 at $DIR/unneeded_deref.rs:5:9: 5:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/unneeded_deref.rs:5:9: 5:10 + let _3: u64; // in scope 2 at $DIR/unneeded_deref.rs:6:9: 6:10 + scope 3 { + debug z => _3; // in scope 3 at $DIR/unneeded_deref.rs:6:9: 6:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/unneeded_deref.rs:4:9: 4:10 + _1 = const 5_u64; // scope 0 at $DIR/unneeded_deref.rs:4:13: 4:14 + StorageLive(_2); // scope 1 at $DIR/unneeded_deref.rs:5:9: 5:10 + _2 = &_1; // scope 1 at $DIR/unneeded_deref.rs:5:13: 5:15 + StorageLive(_3); // scope 2 at $DIR/unneeded_deref.rs:6:9: 6:10 +- _3 = (*_2); // scope 2 at $DIR/unneeded_deref.rs:6:13: 6:15 ++ _3 = _1; // scope 2 at $DIR/unneeded_deref.rs:6:13: 6:15 + _0 = _3; // scope 3 at $DIR/unneeded_deref.rs:7:5: 7:6 + StorageDead(_3); // scope 2 at $DIR/unneeded_deref.rs:8:1: 8:2 + StorageDead(_2); // scope 1 at $DIR/unneeded_deref.rs:8:1: 8:2 + StorageDead(_1); // scope 0 at $DIR/unneeded_deref.rs:8:1: 8:2 + return; // scope 0 at $DIR/unneeded_deref.rs:8:2: 8:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref.very_deep_opt.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref.very_deep_opt.UnneededDeref.diff new file mode 100644 index 0000000000000..9c516385a5851 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref.very_deep_opt.UnneededDeref.diff @@ -0,0 +1,254 @@ +- // MIR for `very_deep_opt` before UnneededDeref ++ // MIR for `very_deep_opt` after UnneededDeref + + fn very_deep_opt() -> (u64, u64, u64, u64, u64, u64, u64, u64, u64) { + let mut _0: (u64, u64, u64, u64, u64, u64, u64, u64, u64); // return place in scope 0 at $DIR/unneeded_deref.rs:38:23: 38:68 + let _1: u64; // in scope 0 at $DIR/unneeded_deref.rs:39:9: 39:11 + let mut _28: u64; // in scope 0 at $DIR/unneeded_deref.rs:66:6: 66:8 + let mut _29: u64; // in scope 0 at $DIR/unneeded_deref.rs:66:10: 66:12 + let mut _30: u64; // in scope 0 at $DIR/unneeded_deref.rs:66:14: 66:16 + let mut _31: u64; // in scope 0 at $DIR/unneeded_deref.rs:66:18: 66:20 + let mut _32: u64; // in scope 0 at $DIR/unneeded_deref.rs:66:22: 66:24 + let mut _33: u64; // in scope 0 at $DIR/unneeded_deref.rs:66:26: 66:28 + let mut _34: u64; // in scope 0 at $DIR/unneeded_deref.rs:66:30: 66:32 + let mut _35: u64; // in scope 0 at $DIR/unneeded_deref.rs:66:34: 66:36 + let mut _36: u64; // in scope 0 at $DIR/unneeded_deref.rs:66:38: 66:40 + scope 1 { + debug x1 => _1; // in scope 1 at $DIR/unneeded_deref.rs:39:9: 39:11 + let _2: u64; // in scope 1 at $DIR/unneeded_deref.rs:40:9: 40:11 + scope 2 { + debug x2 => _2; // in scope 2 at $DIR/unneeded_deref.rs:40:9: 40:11 + let _3: u64; // in scope 2 at $DIR/unneeded_deref.rs:41:9: 41:11 + scope 3 { + debug x3 => _3; // in scope 3 at $DIR/unneeded_deref.rs:41:9: 41:11 + let _4: u64; // in scope 3 at $DIR/unneeded_deref.rs:42:9: 42:11 + scope 4 { + debug x4 => _4; // in scope 4 at $DIR/unneeded_deref.rs:42:9: 42:11 + let _5: u64; // in scope 4 at $DIR/unneeded_deref.rs:43:9: 43:11 + scope 5 { + debug x5 => _5; // in scope 5 at $DIR/unneeded_deref.rs:43:9: 43:11 + let _6: u64; // in scope 5 at $DIR/unneeded_deref.rs:44:9: 44:11 + scope 6 { + debug x6 => _6; // in scope 6 at $DIR/unneeded_deref.rs:44:9: 44:11 + let _7: u64; // in scope 6 at $DIR/unneeded_deref.rs:45:9: 45:11 + scope 7 { + debug x7 => _7; // in scope 7 at $DIR/unneeded_deref.rs:45:9: 45:11 + let _8: u64; // in scope 7 at $DIR/unneeded_deref.rs:46:9: 46:11 + scope 8 { + debug x8 => _8; // in scope 8 at $DIR/unneeded_deref.rs:46:9: 46:11 + let _9: u64; // in scope 8 at $DIR/unneeded_deref.rs:47:9: 47:11 + scope 9 { + debug x9 => _9; // in scope 9 at $DIR/unneeded_deref.rs:47:9: 47:11 + let _10: &u64; // in scope 9 at $DIR/unneeded_deref.rs:48:9: 48:11 + scope 10 { + debug y1 => _10; // in scope 10 at $DIR/unneeded_deref.rs:48:9: 48:11 + let _11: &u64; // in scope 10 at $DIR/unneeded_deref.rs:49:9: 49:11 + scope 11 { + debug y2 => _11; // in scope 11 at $DIR/unneeded_deref.rs:49:9: 49:11 + let _12: &u64; // in scope 11 at $DIR/unneeded_deref.rs:50:9: 50:11 + scope 12 { + debug y3 => _12; // in scope 12 at $DIR/unneeded_deref.rs:50:9: 50:11 + let _13: &u64; // in scope 12 at $DIR/unneeded_deref.rs:51:9: 51:11 + scope 13 { + debug y4 => _13; // in scope 13 at $DIR/unneeded_deref.rs:51:9: 51:11 + let _14: &u64; // in scope 13 at $DIR/unneeded_deref.rs:52:9: 52:11 + scope 14 { + debug y5 => _14; // in scope 14 at $DIR/unneeded_deref.rs:52:9: 52:11 + let _15: &u64; // in scope 14 at $DIR/unneeded_deref.rs:53:9: 53:11 + scope 15 { + debug y6 => _15; // in scope 15 at $DIR/unneeded_deref.rs:53:9: 53:11 + let _16: &u64; // in scope 15 at $DIR/unneeded_deref.rs:54:9: 54:11 + scope 16 { + debug y7 => _16; // in scope 16 at $DIR/unneeded_deref.rs:54:9: 54:11 + let _17: &u64; // in scope 16 at $DIR/unneeded_deref.rs:55:9: 55:11 + scope 17 { + debug y8 => _17; // in scope 17 at $DIR/unneeded_deref.rs:55:9: 55:11 + let _18: &u64; // in scope 17 at $DIR/unneeded_deref.rs:56:9: 56:11 + scope 18 { + debug y9 => _18; // in scope 18 at $DIR/unneeded_deref.rs:56:9: 56:11 + let _19: u64; // in scope 18 at $DIR/unneeded_deref.rs:57:9: 57:11 + scope 19 { + debug z1 => _19; // in scope 19 at $DIR/unneeded_deref.rs:57:9: 57:11 + let _20: u64; // in scope 19 at $DIR/unneeded_deref.rs:58:9: 58:11 + scope 20 { + debug z2 => _20; // in scope 20 at $DIR/unneeded_deref.rs:58:9: 58:11 + let _21: u64; // in scope 20 at $DIR/unneeded_deref.rs:59:9: 59:11 + scope 21 { + debug z3 => _21; // in scope 21 at $DIR/unneeded_deref.rs:59:9: 59:11 + let _22: u64; // in scope 21 at $DIR/unneeded_deref.rs:60:9: 60:11 + scope 22 { + debug z4 => _22; // in scope 22 at $DIR/unneeded_deref.rs:60:9: 60:11 + let _23: u64; // in scope 22 at $DIR/unneeded_deref.rs:61:9: 61:11 + scope 23 { + debug z5 => _23; // in scope 23 at $DIR/unneeded_deref.rs:61:9: 61:11 + let _24: u64; // in scope 23 at $DIR/unneeded_deref.rs:62:9: 62:11 + scope 24 { + debug z6 => _24; // in scope 24 at $DIR/unneeded_deref.rs:62:9: 62:11 + let _25: u64; // in scope 24 at $DIR/unneeded_deref.rs:63:9: 63:11 + scope 25 { + debug z7 => _25; // in scope 25 at $DIR/unneeded_deref.rs:63:9: 63:11 + let _26: u64; // in scope 25 at $DIR/unneeded_deref.rs:64:9: 64:11 + scope 26 { + debug z8 => _26; // in scope 26 at $DIR/unneeded_deref.rs:64:9: 64:11 + let _27: u64; // in scope 26 at $DIR/unneeded_deref.rs:65:9: 65:11 + scope 27 { + debug z9 => _27; // in scope 27 at $DIR/unneeded_deref.rs:65:9: 65:11 + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/unneeded_deref.rs:39:9: 39:11 + _1 = const 1_u64; // scope 0 at $DIR/unneeded_deref.rs:39:14: 39:15 + StorageLive(_2); // scope 1 at $DIR/unneeded_deref.rs:40:9: 40:11 + _2 = const 2_u64; // scope 1 at $DIR/unneeded_deref.rs:40:14: 40:15 + StorageLive(_3); // scope 2 at $DIR/unneeded_deref.rs:41:9: 41:11 + _3 = const 3_u64; // scope 2 at $DIR/unneeded_deref.rs:41:14: 41:15 + StorageLive(_4); // scope 3 at $DIR/unneeded_deref.rs:42:9: 42:11 + _4 = const 4_u64; // scope 3 at $DIR/unneeded_deref.rs:42:14: 42:15 + StorageLive(_5); // scope 4 at $DIR/unneeded_deref.rs:43:9: 43:11 + _5 = const 5_u64; // scope 4 at $DIR/unneeded_deref.rs:43:14: 43:15 + StorageLive(_6); // scope 5 at $DIR/unneeded_deref.rs:44:9: 44:11 + _6 = const 6_u64; // scope 5 at $DIR/unneeded_deref.rs:44:14: 44:15 + StorageLive(_7); // scope 6 at $DIR/unneeded_deref.rs:45:9: 45:11 + _7 = const 7_u64; // scope 6 at $DIR/unneeded_deref.rs:45:14: 45:15 + StorageLive(_8); // scope 7 at $DIR/unneeded_deref.rs:46:9: 46:11 + _8 = const 8_u64; // scope 7 at $DIR/unneeded_deref.rs:46:14: 46:15 + StorageLive(_9); // scope 8 at $DIR/unneeded_deref.rs:47:9: 47:11 + _9 = const 9_u64; // scope 8 at $DIR/unneeded_deref.rs:47:14: 47:15 + StorageLive(_10); // scope 9 at $DIR/unneeded_deref.rs:48:9: 48:11 + _10 = &_1; // scope 9 at $DIR/unneeded_deref.rs:48:14: 48:17 + StorageLive(_11); // scope 10 at $DIR/unneeded_deref.rs:49:9: 49:11 + _11 = &_2; // scope 10 at $DIR/unneeded_deref.rs:49:14: 49:17 + StorageLive(_12); // scope 11 at $DIR/unneeded_deref.rs:50:9: 50:11 + _12 = &_3; // scope 11 at $DIR/unneeded_deref.rs:50:14: 50:17 + StorageLive(_13); // scope 12 at $DIR/unneeded_deref.rs:51:9: 51:11 + _13 = &_4; // scope 12 at $DIR/unneeded_deref.rs:51:14: 51:17 + StorageLive(_14); // scope 13 at $DIR/unneeded_deref.rs:52:9: 52:11 + _14 = &_5; // scope 13 at $DIR/unneeded_deref.rs:52:14: 52:17 + StorageLive(_15); // scope 14 at $DIR/unneeded_deref.rs:53:9: 53:11 + _15 = &_6; // scope 14 at $DIR/unneeded_deref.rs:53:14: 53:17 + StorageLive(_16); // scope 15 at $DIR/unneeded_deref.rs:54:9: 54:11 + _16 = &_7; // scope 15 at $DIR/unneeded_deref.rs:54:14: 54:17 + StorageLive(_17); // scope 16 at $DIR/unneeded_deref.rs:55:9: 55:11 + _17 = &_8; // scope 16 at $DIR/unneeded_deref.rs:55:14: 55:17 + StorageLive(_18); // scope 17 at $DIR/unneeded_deref.rs:56:9: 56:11 + _18 = &_9; // scope 17 at $DIR/unneeded_deref.rs:56:14: 56:17 + StorageLive(_19); // scope 18 at $DIR/unneeded_deref.rs:57:9: 57:11 +- _19 = (*_10); // scope 18 at $DIR/unneeded_deref.rs:57:14: 57:17 ++ _19 = _1; // scope 18 at $DIR/unneeded_deref.rs:57:14: 57:17 + StorageLive(_20); // scope 19 at $DIR/unneeded_deref.rs:58:9: 58:11 +- _20 = (*_11); // scope 19 at $DIR/unneeded_deref.rs:58:14: 58:17 ++ _20 = _2; // scope 19 at $DIR/unneeded_deref.rs:58:14: 58:17 + StorageLive(_21); // scope 20 at $DIR/unneeded_deref.rs:59:9: 59:11 +- _21 = (*_12); // scope 20 at $DIR/unneeded_deref.rs:59:14: 59:17 ++ _21 = _3; // scope 20 at $DIR/unneeded_deref.rs:59:14: 59:17 + StorageLive(_22); // scope 21 at $DIR/unneeded_deref.rs:60:9: 60:11 +- _22 = (*_13); // scope 21 at $DIR/unneeded_deref.rs:60:14: 60:17 ++ _22 = _4; // scope 21 at $DIR/unneeded_deref.rs:60:14: 60:17 + StorageLive(_23); // scope 22 at $DIR/unneeded_deref.rs:61:9: 61:11 +- _23 = (*_14); // scope 22 at $DIR/unneeded_deref.rs:61:14: 61:17 ++ _23 = _5; // scope 22 at $DIR/unneeded_deref.rs:61:14: 61:17 + StorageLive(_24); // scope 23 at $DIR/unneeded_deref.rs:62:9: 62:11 +- _24 = (*_15); // scope 23 at $DIR/unneeded_deref.rs:62:14: 62:17 ++ _24 = _6; // scope 23 at $DIR/unneeded_deref.rs:62:14: 62:17 + StorageLive(_25); // scope 24 at $DIR/unneeded_deref.rs:63:9: 63:11 +- _25 = (*_16); // scope 24 at $DIR/unneeded_deref.rs:63:14: 63:17 ++ _25 = _7; // scope 24 at $DIR/unneeded_deref.rs:63:14: 63:17 + StorageLive(_26); // scope 25 at $DIR/unneeded_deref.rs:64:9: 64:11 +- _26 = (*_17); // scope 25 at $DIR/unneeded_deref.rs:64:14: 64:17 ++ _26 = _8; // scope 25 at $DIR/unneeded_deref.rs:64:14: 64:17 + StorageLive(_27); // scope 26 at $DIR/unneeded_deref.rs:65:9: 65:11 +- _27 = (*_18); // scope 26 at $DIR/unneeded_deref.rs:65:14: 65:17 ++ _27 = _9; // scope 26 at $DIR/unneeded_deref.rs:65:14: 65:17 + StorageLive(_28); // scope 27 at $DIR/unneeded_deref.rs:66:6: 66:8 + _28 = _19; // scope 27 at $DIR/unneeded_deref.rs:66:6: 66:8 + StorageLive(_29); // scope 27 at $DIR/unneeded_deref.rs:66:10: 66:12 + _29 = _20; // scope 27 at $DIR/unneeded_deref.rs:66:10: 66:12 + StorageLive(_30); // scope 27 at $DIR/unneeded_deref.rs:66:14: 66:16 + _30 = _21; // scope 27 at $DIR/unneeded_deref.rs:66:14: 66:16 + StorageLive(_31); // scope 27 at $DIR/unneeded_deref.rs:66:18: 66:20 + _31 = _22; // scope 27 at $DIR/unneeded_deref.rs:66:18: 66:20 + StorageLive(_32); // scope 27 at $DIR/unneeded_deref.rs:66:22: 66:24 + _32 = _23; // scope 27 at $DIR/unneeded_deref.rs:66:22: 66:24 + StorageLive(_33); // scope 27 at $DIR/unneeded_deref.rs:66:26: 66:28 + _33 = _24; // scope 27 at $DIR/unneeded_deref.rs:66:26: 66:28 + StorageLive(_34); // scope 27 at $DIR/unneeded_deref.rs:66:30: 66:32 + _34 = _25; // scope 27 at $DIR/unneeded_deref.rs:66:30: 66:32 + StorageLive(_35); // scope 27 at $DIR/unneeded_deref.rs:66:34: 66:36 + _35 = _26; // scope 27 at $DIR/unneeded_deref.rs:66:34: 66:36 + StorageLive(_36); // scope 27 at $DIR/unneeded_deref.rs:66:38: 66:40 + _36 = _27; // scope 27 at $DIR/unneeded_deref.rs:66:38: 66:40 + (_0.0: u64) = move _28; // scope 27 at $DIR/unneeded_deref.rs:66:5: 66:41 + (_0.1: u64) = move _29; // scope 27 at $DIR/unneeded_deref.rs:66:5: 66:41 + (_0.2: u64) = move _30; // scope 27 at $DIR/unneeded_deref.rs:66:5: 66:41 + (_0.3: u64) = move _31; // scope 27 at $DIR/unneeded_deref.rs:66:5: 66:41 + (_0.4: u64) = move _32; // scope 27 at $DIR/unneeded_deref.rs:66:5: 66:41 + (_0.5: u64) = move _33; // scope 27 at $DIR/unneeded_deref.rs:66:5: 66:41 + (_0.6: u64) = move _34; // scope 27 at $DIR/unneeded_deref.rs:66:5: 66:41 + (_0.7: u64) = move _35; // scope 27 at $DIR/unneeded_deref.rs:66:5: 66:41 + (_0.8: u64) = move _36; // scope 27 at $DIR/unneeded_deref.rs:66:5: 66:41 + StorageDead(_36); // scope 27 at $DIR/unneeded_deref.rs:66:40: 66:41 + StorageDead(_35); // scope 27 at $DIR/unneeded_deref.rs:66:40: 66:41 + StorageDead(_34); // scope 27 at $DIR/unneeded_deref.rs:66:40: 66:41 + StorageDead(_33); // scope 27 at $DIR/unneeded_deref.rs:66:40: 66:41 + StorageDead(_32); // scope 27 at $DIR/unneeded_deref.rs:66:40: 66:41 + StorageDead(_31); // scope 27 at $DIR/unneeded_deref.rs:66:40: 66:41 + StorageDead(_30); // scope 27 at $DIR/unneeded_deref.rs:66:40: 66:41 + StorageDead(_29); // scope 27 at $DIR/unneeded_deref.rs:66:40: 66:41 + StorageDead(_28); // scope 27 at $DIR/unneeded_deref.rs:66:40: 66:41 + StorageDead(_27); // scope 26 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_26); // scope 25 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_25); // scope 24 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_24); // scope 23 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_23); // scope 22 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_22); // scope 21 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_21); // scope 20 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_20); // scope 19 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_19); // scope 18 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_18); // scope 17 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_17); // scope 16 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_16); // scope 15 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_15); // scope 14 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_14); // scope 13 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_13); // scope 12 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_12); // scope 11 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_11); // scope 10 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_10); // scope 9 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_9); // scope 8 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_8); // scope 7 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_7); // scope 6 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_6); // scope 5 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_5); // scope 4 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_4); // scope 3 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_3); // scope 2 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_2); // scope 1 at $DIR/unneeded_deref.rs:67:1: 67:2 + StorageDead(_1); // scope 0 at $DIR/unneeded_deref.rs:67:1: 67:2 + return; // scope 0 at $DIR/unneeded_deref.rs:67:2: 67:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_miscompile.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_miscompile.UnneededDeref.diff new file mode 100644 index 0000000000000..0a43a9b0164f0 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_miscompile.UnneededDeref.diff @@ -0,0 +1,84 @@ +- // MIR for `do_not_miscompile` before UnneededDeref ++ // MIR for `do_not_miscompile` after UnneededDeref + + fn do_not_miscompile() -> () { + let mut _0: (); // return place in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:20:24: 20:24 + let _1: i32; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:21:9: 21:10 + let mut _5: &i32; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:25:10: 25:12 + let _6: &i32; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:25:10: 25:12 + let _7: (); // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:26:5: 26:23 + let mut _8: bool; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:26:5: 26:23 + let mut _9: bool; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:26:13: 26:21 + let mut _10: i32; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:26:13: 26:15 + let mut _11: !; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + scope 1 { + debug x => _1; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:21:9: 21:10 + let _2: i32; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:22:9: 22:10 + scope 2 { + debug a => _2; // in scope 2 at $DIR/unneeded_deref_do_not_opt.rs:22:9: 22:10 + let mut _3: &i32; // in scope 2 at $DIR/unneeded_deref_do_not_opt.rs:23:9: 23:14 + scope 3 { + debug y => _3; // in scope 3 at $DIR/unneeded_deref_do_not_opt.rs:23:9: 23:14 + let _4: &mut &i32; // in scope 3 at $DIR/unneeded_deref_do_not_opt.rs:24:9: 24:10 + scope 4 { + debug z => _4; // in scope 4 at $DIR/unneeded_deref_do_not_opt.rs:24:9: 24:10 + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:21:9: 21:10 + _1 = const 42_i32; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:21:13: 21:15 + StorageLive(_2); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:22:9: 22:10 + _2 = const 99_i32; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:22:13: 22:15 + StorageLive(_3); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:23:9: 23:14 + _3 = &_1; // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:23:17: 23:19 + StorageLive(_4); // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:24:9: 24:10 + _4 = &mut _3; // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:24:13: 24:19 + StorageLive(_5); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:25:10: 25:12 + StorageLive(_6); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:25:10: 25:12 + _6 = &_2; // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:25:10: 25:12 + _5 = _6; // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:25:10: 25:12 + (*_4) = move _5; // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:25:5: 25:12 + StorageDead(_5); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:25:11: 25:12 + StorageDead(_6); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:25:12: 25:13 + StorageLive(_7); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:5: 26:23 + StorageLive(_8); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:5: 26:23 + StorageLive(_9); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:13: 26:21 + StorageLive(_10); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:13: 26:15 + _10 = (*_3); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:13: 26:15 + _9 = Eq(move _10, const 99_i32); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:13: 26:21 + StorageDead(_10); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:20: 26:21 + _8 = Not(move _9); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:5: 26:23 + StorageDead(_9); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:22: 26:23 + switchInt(_8) -> [false: bb1, otherwise: bb2]; // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:5: 26:23 + } + + bb1: { + _7 = const (); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:5: 26:23 + StorageDead(_8); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:22: 26:23 + StorageDead(_7); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:26:22: 26:23 + _0 = const (); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:20:24: 27:2 + StorageDead(_4); // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:27:1: 27:2 + StorageDead(_3); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:27:1: 27:2 + StorageDead(_2); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:27:1: 27:2 + StorageDead(_1); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:27:1: 27:2 + return; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:27:2: 27:2 + } + + bb2: { + StorageLive(_11); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + begin_panic::<&str>(const "assertion failed: *y == 99"); // 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: 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, 42, 121, 32, 61, 61, 32, 57, 57], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [67108863], len: Size { raw: 26 } }, size: Size { raw: 26 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 26 }) + // mir::Constant + // + span: $DIR/unneeded_deref_do_not_opt.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, 42, 121, 32, 61, 61, 32, 57, 57], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [67108863], len: Size { raw: 26 } }, size: Size { raw: 26 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 26 }) } + } + } + diff --git a/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_miscompile_mut_ref.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_miscompile_mut_ref.UnneededDeref.diff new file mode 100644 index 0000000000000..beddd2fe3010e --- /dev/null +++ b/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_miscompile_mut_ref.UnneededDeref.diff @@ -0,0 +1,70 @@ +- // MIR for `do_not_miscompile_mut_ref` before UnneededDeref ++ // MIR for `do_not_miscompile_mut_ref` after UnneededDeref + + fn do_not_miscompile_mut_ref() -> () { + let mut _0: (); // return place in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:31:32: 31:32 + let _1: u32; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:32:9: 32:10 + let _4: &u32; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:35:29: 35:31 + let _6: &u32; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:36:19: 36:21 + let mut _8: *const u32; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:39:9: 39:10 + scope 1 { + debug a => _1; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:32:9: 32:10 + let _2: u32; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:33:9: 33:10 + scope 2 { + debug b => _2; // in scope 2 at $DIR/unneeded_deref_do_not_opt.rs:33:9: 33:10 + let mut _3: *const u32; // in scope 2 at $DIR/unneeded_deref_do_not_opt.rs:35:9: 35:14 + scope 3 { + debug c => _3; // in scope 3 at $DIR/unneeded_deref_do_not_opt.rs:35:9: 35:14 + let _5: &u32; // in scope 3 at $DIR/unneeded_deref_do_not_opt.rs:36:9: 36:10 + scope 4 { + debug d => _5; // in scope 4 at $DIR/unneeded_deref_do_not_opt.rs:36:9: 36:10 + let _7: &u32; // in scope 4 at $DIR/unneeded_deref_do_not_opt.rs:38:9: 38:10 + scope 5 { + debug x => _7; // in scope 5 at $DIR/unneeded_deref_do_not_opt.rs:38:9: 38:10 + let _9: u32; // in scope 5 at $DIR/unneeded_deref_do_not_opt.rs:40:9: 40:10 + scope 7 { + debug z => _9; // in scope 7 at $DIR/unneeded_deref_do_not_opt.rs:40:9: 40:10 + } + } + scope 6 { + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:32:9: 32:10 + _1 = const 1_u32; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:32:13: 32:17 + StorageLive(_2); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:33:9: 33:10 + _2 = const 2_u32; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:33:13: 33:17 + StorageLive(_3); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:35:9: 35:14 + StorageLive(_4); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:35:29: 35:31 + _4 = &_1; // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:35:29: 35:31 +- _3 = &raw const (*_4); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:35:29: 35:31 ++ _3 = &raw const _1; // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:35:29: 35:31 + StorageDead(_4); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:35:31: 35:32 + StorageLive(_5); // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:36:9: 36:10 + StorageLive(_6); // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:36:19: 36:21 + _6 = &_2; // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:36:19: 36:21 + _5 = _6; // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:36:19: 36:21 + StorageDead(_6); // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:36:21: 36:22 + StorageLive(_7); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:38:9: 38:10 + _7 = &(*_3); // scope 6 at $DIR/unneeded_deref_do_not_opt.rs:38:22: 38:25 + StorageLive(_8); // scope 5 at $DIR/unneeded_deref_do_not_opt.rs:39:9: 39:10 + _8 = &raw const (*_5); // scope 5 at $DIR/unneeded_deref_do_not_opt.rs:39:9: 39:10 + _3 = move _8; // scope 5 at $DIR/unneeded_deref_do_not_opt.rs:39:5: 39:10 + StorageDead(_8); // scope 5 at $DIR/unneeded_deref_do_not_opt.rs:39:9: 39:10 + StorageLive(_9); // scope 5 at $DIR/unneeded_deref_do_not_opt.rs:40:9: 40:10 + _9 = (*_7); // scope 5 at $DIR/unneeded_deref_do_not_opt.rs:40:13: 40:15 + _0 = const (); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:31:32: 41:2 + StorageDead(_9); // scope 5 at $DIR/unneeded_deref_do_not_opt.rs:41:1: 41:2 + StorageDead(_7); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:41:1: 41:2 + StorageDead(_5); // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:41:1: 41:2 + StorageDead(_3); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:41:1: 41:2 + StorageDead(_2); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:41:1: 41:2 + StorageDead(_1); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:41:1: 41:2 + return; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:41:2: 41:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_opt_different_bbs.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_opt_different_bbs.UnneededDeref.diff new file mode 100644 index 0000000000000..39175f537d7a6 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_opt_different_bbs.UnneededDeref.diff @@ -0,0 +1,64 @@ +- // MIR for `do_not_opt_different_bbs` before UnneededDeref ++ // MIR for `do_not_opt_different_bbs` after UnneededDeref + + fn do_not_opt_different_bbs(_1: bool) -> u64 { + debug input => _1; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:51:29: 51:34 + let mut _0: u64; // return place in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:51:45: 51:48 + let _2: u64; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:52:9: 52:10 + let mut _4: bool; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:53:16: 53:21 + let _5: &u64; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:53:36: 53:39 + let _6: u64; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:53:37: 53:39 + scope 1 { + debug x => _2; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:52:9: 52:10 + let _3: &u64; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:9: 53:10 + let mut _8: &u64; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:36: 53:39 + scope 2 { + debug y => _3; // in scope 2 at $DIR/unneeded_deref_do_not_opt.rs:53:9: 53:10 + let _7: u64; // in scope 2 at $DIR/unneeded_deref_do_not_opt.rs:54:9: 54:10 + scope 3 { + debug z => _7; // in scope 3 at $DIR/unneeded_deref_do_not_opt.rs:54:9: 54:10 + } + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:52:9: 52:10 + _2 = const 5_u64; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:52:13: 52:14 + StorageLive(_3); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:9: 53:10 + StorageLive(_4); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:16: 53:21 + _4 = _1; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:16: 53:21 + switchInt(_4) -> [false: bb1, otherwise: bb2]; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:13: 53:41 + } + + bb1: { + StorageLive(_5); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:36: 53:39 + _8 = const do_not_opt_different_bbs::promoted[0]; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:36: 53:39 + // ty::Const + // + ty: &u64 + // + val: Unevaluated(WithOptConstParam { did: DefId(0:8 ~ unneeded_deref_do_not_opt[317d]::do_not_opt_different_bbs), const_param_did: None }, [], Some(promoted[0])) + // mir::Constant + // + span: $DIR/unneeded_deref_do_not_opt.rs:53:36: 53:39 + // + literal: Const { ty: &u64, val: Unevaluated(WithOptConstParam { did: DefId(0:8 ~ unneeded_deref_do_not_opt[317d]::do_not_opt_different_bbs), const_param_did: None }, [], Some(promoted[0])) } + _5 = _8; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:36: 53:39 + _3 = _5; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:36: 53:39 + StorageDead(_5); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:40: 53:41 + goto -> bb3; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:13: 53:41 + } + + bb2: { + _3 = &_2; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:24: 53:26 + goto -> bb3; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:13: 53:41 + } + + bb3: { + StorageDead(_4); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:53:41: 53:42 + StorageLive(_7); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:54:9: 54:10 + _7 = (*_3); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:54:13: 54:15 + _0 = _7; // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:55:5: 55:6 + StorageDead(_7); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:56:1: 56:2 + StorageDead(_3); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:56:1: 56:2 + StorageDead(_2); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:56:1: 56:2 + return; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:56:2: 56:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_use_moved.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_use_moved.UnneededDeref.diff new file mode 100644 index 0000000000000..7d880e6040fe0 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref_do_not_opt.do_not_use_moved.UnneededDeref.diff @@ -0,0 +1,35 @@ +- // MIR for `do_not_use_moved` before UnneededDeref ++ // MIR for `do_not_use_moved` after UnneededDeref + + fn do_not_use_moved(_1: T) -> () { + debug x => _1; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:44:24: 44:25 + let mut _0: (); // return place in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:44:30: 44:30 + let _2: T; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:45:9: 45:10 + scope 1 { + debug b => _2; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:45:9: 45:10 + let _3: &T; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:46:9: 46:10 + scope 2 { + debug z => _3; // in scope 2 at $DIR/unneeded_deref_do_not_opt.rs:46:9: 46:10 + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:45:9: 45:10 + _2 = move _1; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:45:13: 45:14 + StorageLive(_3); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:46:9: 46:10 + _3 = &_2; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:46:13: 46:15 + _0 = const (); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:44:30: 47:2 + StorageDead(_3); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:47:1: 47:2 + drop(_2) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:47:1: 47:2 + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:47:1: 47:2 + return; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:47:2: 47:2 + } + + bb2 (cleanup): { + resume; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:44:1: 47:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref_do_not_opt.dont_opt.UnneededDeref.diff b/src/test/mir-opt/unneeded_deref_do_not_opt.dont_opt.UnneededDeref.diff new file mode 100644 index 0000000000000..fb3083e5f2ce7 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref_do_not_opt.dont_opt.UnneededDeref.diff @@ -0,0 +1,52 @@ +- // MIR for `dont_opt` before UnneededDeref ++ // MIR for `dont_opt` after UnneededDeref + + fn dont_opt() -> u64 { + let mut _0: u64; // return place in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:9:18: 9:21 + let _1: i32; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:10:9: 10:10 + let mut _5: &i32; // in scope 0 at $DIR/unneeded_deref_do_not_opt.rs:14:10: 14:14 + scope 1 { + debug y => _1; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:10:9: 10:10 + let _2: &i32; // in scope 1 at $DIR/unneeded_deref_do_not_opt.rs:11:9: 11:13 + scope 2 { + debug _ref => _2; // in scope 2 at $DIR/unneeded_deref_do_not_opt.rs:11:9: 11:13 + let _3: i32; // in scope 2 at $DIR/unneeded_deref_do_not_opt.rs:12:9: 12:10 + scope 3 { + debug x => _3; // in scope 3 at $DIR/unneeded_deref_do_not_opt.rs:12:9: 12:10 + let mut _4: &i32; // in scope 3 at $DIR/unneeded_deref_do_not_opt.rs:13:9: 13:15 + scope 4 { + debug _1 => _4; // in scope 4 at $DIR/unneeded_deref_do_not_opt.rs:13:9: 13:15 + let _6: i32; // in scope 4 at $DIR/unneeded_deref_do_not_opt.rs:15:9: 15:11 + scope 5 { + debug _4 => _6; // in scope 5 at $DIR/unneeded_deref_do_not_opt.rs:15:9: 15:11 + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:10:9: 10:10 + _1 = const 5_i32; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:10:13: 10:14 + StorageLive(_2); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:11:9: 11:13 + _2 = &_1; // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:11:16: 11:18 + StorageLive(_3); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:12:9: 12:10 + _3 = const 5_i32; // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:12:13: 12:14 + StorageLive(_4); // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:13:9: 13:15 + _4 = &_3; // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:13:18: 13:20 + StorageLive(_5); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:14:10: 14:14 + _5 = _2; // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:14:10: 14:14 + _4 = move _5; // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:14:5: 14:14 + StorageDead(_5); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:14:13: 14:14 + StorageLive(_6); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:15:9: 15:11 + _6 = (*_4); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:15:14: 15:17 + _0 = const 0_u64; // scope 5 at $DIR/unneeded_deref_do_not_opt.rs:16:5: 16:6 + StorageDead(_6); // scope 4 at $DIR/unneeded_deref_do_not_opt.rs:17:1: 17:2 + StorageDead(_4); // scope 3 at $DIR/unneeded_deref_do_not_opt.rs:17:1: 17:2 + StorageDead(_3); // scope 2 at $DIR/unneeded_deref_do_not_opt.rs:17:1: 17:2 + StorageDead(_2); // scope 1 at $DIR/unneeded_deref_do_not_opt.rs:17:1: 17:2 + StorageDead(_1); // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:17:1: 17:2 + return; // scope 0 at $DIR/unneeded_deref_do_not_opt.rs:17:2: 17:2 + } + } + diff --git a/src/test/mir-opt/unneeded_deref_do_not_opt.rs b/src/test/mir-opt/unneeded_deref_do_not_opt.rs new file mode 100644 index 0000000000000..76d1b03e0c9a4 --- /dev/null +++ b/src/test/mir-opt/unneeded_deref_do_not_opt.rs @@ -0,0 +1,64 @@ +// compile-flags: -O -Zunsound-mir-opts + +// EMIT_MIR unneeded_deref_do_not_opt.dont_opt.UnneededDeref.diff +// do not optimize a sequence looking like this: +// _1 = &_2; +// _1 = _3; +// _4 = *_1; +// as the _1 = _3 assignment makes it not legal to replace the last statement with _4 = _2 +fn dont_opt() -> u64 { + let y = 5; + let _ref = &y; + let x = 5; + let mut _1 = &x; + _1 = _ref; + let _4 = *_1; + 0 +} + +// EMIT_MIR unneeded_deref_do_not_opt.do_not_miscompile.UnneededDeref.diff +fn do_not_miscompile() { + let x = 42; + let a = 99; + let mut y = &x; + let z = &mut y; + *z = &a; + assert!(*y == 99); +} + +// EMIT_MIR unneeded_deref_do_not_opt.do_not_miscompile_mut_ref.UnneededDeref.diff +// See #78192 +fn do_not_miscompile_mut_ref() { + let a = 1u32; + let b = 2u32; + + let mut c: *const u32 = &a; + let d: &u32 = &b; + + let x = unsafe { &*c }; + c = d; + let z = *x; +} + +// EMIT_MIR unneeded_deref_do_not_opt.do_not_use_moved.UnneededDeref.diff +fn do_not_use_moved(x: T) { + let b = x; + let z = &b; +} + +// EMIT_MIR unneeded_deref_do_not_opt.do_not_opt_different_bbs.UnneededDeref.diff +// We cannot know whether z should be 5 or 33 +fn do_not_opt_different_bbs(input: bool) -> u64 { + let x = 5; + let y = if input { &x } else { &33 }; + let z = *y; + z +} + +fn main() { + dont_opt(); + do_not_miscompile(); + do_not_miscompile_mut_ref(); + do_not_use_moved(String::new()); + do_not_opt_different_bbs(false); +}