From 4f9c30fb676482a5148f28c0728b5280246a9886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Thu, 25 Aug 2022 16:43:46 +0000 Subject: [PATCH 01/76] Add initial version of value analysis and dataflow constant propagation --- compiler/rustc_graphviz/src/lib.rs | 6 +- .../src/framework/graphviz.rs | 5 +- compiler/rustc_mir_dataflow/src/lib.rs | 1 + .../rustc_mir_dataflow/src/value_analysis.rs | 677 ++++++++++++++++++ .../src/dataflow_const_prop.rs | 490 +++++++++++++ compiler/rustc_mir_transform/src/lib.rs | 2 + .../cast.main.DataflowConstProp.diff | 41 ++ src/test/mir-opt/dataflow-const-prop/cast.rs | 7 + .../cell.main.DataflowConstProp.diff | 12 + src/test/mir-opt/dataflow-const-prop/cell.rs | 6 + .../checked.main.DataflowConstProp.diff | 81 +++ .../mir-opt/dataflow-const-prop/checked.rs | 13 + .../if.main.DataflowConstProp.diff | 118 +++ src/test/mir-opt/dataflow-const-prop/if.rs | 12 + .../promoted.main.DataflowConstProp.diff | 29 + .../mir-opt/dataflow-const-prop/promoted.rs | 7 + .../recursive.main.DataflowConstProp.diff | 133 ++++ .../mir-opt/dataflow-const-prop/recursive.rs | 23 + .../ref.main.DataflowConstProp.diff | 89 +++ src/test/mir-opt/dataflow-const-prop/ref.rs | 9 + .../ref_mut.main.DataflowConstProp.diff | 77 ++ .../mir-opt/dataflow-const-prop/ref_mut.rs | 15 + .../terminator.main.DataflowConstProp.diff | 40 ++ .../mir-opt/dataflow-const-prop/terminator.rs | 9 + .../unnamed.main.DataflowConstProp.diff | 38 + .../mir-opt/dataflow-const-prop/unnamed.rs | 10 + 26 files changed, 1948 insertions(+), 2 deletions(-) create mode 100644 compiler/rustc_mir_dataflow/src/value_analysis.rs create mode 100644 compiler/rustc_mir_transform/src/dataflow_const_prop.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/cast.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/cell.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/cell.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/checked.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/if.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/promoted.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/recursive.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/ref.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/ref_mut.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/terminator.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/unnamed.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/unnamed.rs diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index 3c1bb5532661a..401d3f6689c99 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -471,7 +471,11 @@ pub trait Labeller<'a> { /// Escape tags in such a way that it is suitable for inclusion in a /// Graphviz HTML label. pub fn escape_html(s: &str) -> String { - s.replace('&', "&").replace('\"', """).replace('<', "<").replace('>', ">") + s.replace('&', "&") + .replace('\"', """) + .replace('<', "<") + .replace('>', ">") + .replace('\n', "
") } impl<'a> LabelText<'a> { diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 579fe68a14935..c9d5601f2074c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -475,7 +475,10 @@ where r#"{state}"#, colspan = this.style.num_state_columns(), fmt = fmt, - state = format!("{:?}", DebugWithAdapter { this: state, ctxt: analysis }), + state = dot::escape_html(&format!( + "{:?}", + DebugWithAdapter { this: state, ctxt: analysis } + )), ) }) } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index b471d04fd606f..7f40cfca32fff 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -41,6 +41,7 @@ pub mod move_paths; pub mod rustc_peek; pub mod storage; pub mod un_derefer; +pub mod value_analysis; pub(crate) mod indexes { pub(crate) use super::move_paths::MovePathIndex; diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs new file mode 100644 index 0000000000000..1dcea430a0f67 --- /dev/null +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -0,0 +1,677 @@ +//! This module provides a framework on top of the normal MIR dataflow framework to simplify the +//! implementation of analyses that track the values stored in places of interest. +//! +//! The default methods of [`ValueAnalysis`] (prefixed with `super_` instead of `handle_`) +//! provide some behavior that should be valid for all abstract domains that are based only on the +//! value stored in a certain place. On top of these default rules, an implementation should +//! override some of the `handle_` methods. For an example, see `ConstAnalysis`. +//! +//! An implementation must also provide a [`Map`]. Before the anaylsis begins, all places that +//! should be tracked during the analysis must be registered. The set of tracked places cannot be +//! changed during the analysis. + +use std::fmt::{Debug, Formatter}; + +use rustc_data_structures::fx::FxHashMap; +use rustc_index::vec::IndexVec; +use rustc_middle::mir::*; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_target::abi::VariantIdx; + +use crate::{ + fmt::DebugWithContext, lattice::FlatSet, Analysis, AnalysisDomain, CallReturnPlaces, + JoinSemiLattice, SwitchIntEdgeEffects, +}; + +pub trait ValueAnalysis<'tcx> { + /// For each place of interest, the analysis tracks a value of the given type. + type Value: Clone + JoinSemiLattice + HasBottom + HasTop; + + const NAME: &'static str; + + fn map(&self) -> ⤅ + + fn handle_statement(&self, statement: &Statement<'tcx>, state: &mut State) { + self.super_statement(statement, state) + } + + fn super_statement(&self, statement: &Statement<'tcx>, state: &mut State) { + match &statement.kind { + StatementKind::Assign(box (place, rvalue)) => { + self.handle_assign(*place, rvalue, state); + } + StatementKind::SetDiscriminant { .. } => { + // Could tread this as writing a constant to a pseudo-place. + } + StatementKind::CopyNonOverlapping(..) => { + // FIXME: What to do here? + } + StatementKind::StorageLive(..) + | StatementKind::StorageDead(..) + | StatementKind::Deinit(_) => { + // Could perhaps use these. + } + StatementKind::Nop + | StatementKind::Retag(..) + | StatementKind::FakeRead(..) + | StatementKind::Coverage(..) + | StatementKind::AscribeUserType(..) => (), + } + } + + fn handle_assign( + &self, + target: Place<'tcx>, + rvalue: &Rvalue<'tcx>, + state: &mut State, + ) { + self.super_assign(target, rvalue, state) + } + + fn super_assign( + &self, + target: Place<'tcx>, + rvalue: &Rvalue<'tcx>, + state: &mut State, + ) { + match rvalue { + Rvalue::Ref(_, BorrowKind::Shared, place) => { + let target_deref = self + .map() + .find(target.as_ref()) + .and_then(|target| self.map().apply_elem(target, ProjElem::Deref)); + let place = self.map().find(place.as_ref()); + match (target_deref, place) { + (Some(target_deref), Some(place)) => { + state.assign_idx(target_deref, ValueOrPlace::Place(place), self.map()) + } + _ => (), + } + } + Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + state.flood(place.as_ref(), self.map(), Self::Value::top()); + } + _ => { + let result = self.handle_rvalue(rvalue, state); + state.assign(target.as_ref(), result, self.map()); + } + } + } + + fn handle_rvalue( + &self, + rvalue: &Rvalue<'tcx>, + state: &mut State, + ) -> ValueOrPlace { + self.super_rvalue(rvalue, state) + } + + fn super_rvalue( + &self, + rvalue: &Rvalue<'tcx>, + state: &mut State, + ) -> ValueOrPlace { + match rvalue { + Rvalue::Use(operand) => self.handle_operand(operand, state), + Rvalue::CopyForDeref(place) => self.handle_operand(&Operand::Copy(*place), state), + Rvalue::Ref(..) | Rvalue::AddressOf(..) => { + bug!("this rvalue must be handled by handle_assign() or super_assign()") + } + _ => { + // FIXME: Check that other Rvalues really have no side-effect. + ValueOrPlace::Unknown + } + } + } + + fn handle_operand( + &self, + operand: &Operand<'tcx>, + state: &mut State, + ) -> ValueOrPlace { + self.super_operand(operand, state) + } + + fn super_operand( + &self, + operand: &Operand<'tcx>, + state: &mut State, + ) -> ValueOrPlace { + match operand { + Operand::Constant(box constant) => { + ValueOrPlace::Value(self.handle_constant(constant, state)) + } + Operand::Copy(place) | Operand::Move(place) => { + // Do want want to handle moves different? Could flood place with bottom. + self.map() + .find(place.as_ref()) + .map(ValueOrPlace::Place) + .unwrap_or(ValueOrPlace::Unknown) + } + } + } + + fn handle_constant( + &self, + constant: &Constant<'tcx>, + state: &mut State, + ) -> Self::Value { + self.super_constant(constant, state) + } + + fn super_constant( + &self, + _constant: &Constant<'tcx>, + _state: &mut State, + ) -> Self::Value { + Self::Value::top() + } + + fn handle_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State) { + self.super_terminator(terminator, state) + } + + fn super_terminator(&self, _terminator: &Terminator<'tcx>, _state: &mut State) {} + + fn handle_call_return( + &self, + return_places: CallReturnPlaces<'_, 'tcx>, + state: &mut State, + ) { + self.super_call_return(return_places, state) + } + + fn super_call_return( + &self, + return_places: CallReturnPlaces<'_, 'tcx>, + state: &mut State, + ) { + return_places.for_each(|place| { + state.flood(place.as_ref(), self.map(), Self::Value::top()); + }) + } + + fn handle_switch_int( + &self, + discr: &Operand<'tcx>, + apply_edge_effects: &mut impl SwitchIntEdgeEffects>, + ) { + self.super_switch_int(discr, apply_edge_effects) + } + + fn super_switch_int( + &self, + _discr: &Operand<'tcx>, + _apply_edge_effects: &mut impl SwitchIntEdgeEffects>, + ) { + } + + fn wrap(self) -> ValueAnalysisWrapper + where + Self: Sized, + { + ValueAnalysisWrapper(self) + } +} + +pub struct ValueAnalysisWrapper(pub T); + +impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper { + type Domain = State; + + type Direction = crate::Forward; + + const NAME: &'static str = T::NAME; + + fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain { + State(IndexVec::from_elem_n(T::Value::bottom(), self.0.map().value_count)) + } + + fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) { + for arg in body.args_iter() { + state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map(), T::Value::top()); + } + } +} + +impl<'tcx, T> Analysis<'tcx> for ValueAnalysisWrapper +where + T: ValueAnalysis<'tcx>, +{ + fn apply_statement_effect( + &self, + state: &mut Self::Domain, + statement: &Statement<'tcx>, + _location: Location, + ) { + self.0.handle_statement(statement, state); + } + + fn apply_terminator_effect( + &self, + state: &mut Self::Domain, + terminator: &Terminator<'tcx>, + _location: Location, + ) { + self.0.handle_terminator(terminator, state); + } + + fn apply_call_return_effect( + &self, + state: &mut Self::Domain, + _block: BasicBlock, + return_places: crate::CallReturnPlaces<'_, 'tcx>, + ) { + self.0.handle_call_return(return_places, state) + } + + fn apply_switch_int_edge_effects( + &self, + _block: BasicBlock, + discr: &Operand<'tcx>, + apply_edge_effects: &mut impl SwitchIntEdgeEffects, + ) { + self.0.handle_switch_int(discr, apply_edge_effects) + } +} + +rustc_index::newtype_index!( + pub struct PlaceIndex {} +); + +rustc_index::newtype_index!( + struct ValueIndex {} +); + +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct State(IndexVec); + +impl State { + pub fn flood_all(&mut self, value: V) { + self.0.raw.fill(value); + } + + pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { + if let Some(root) = map.find(place) { + self.flood_idx(root, map, value); + } + } + + pub fn flood_idx(&mut self, place: PlaceIndex, map: &Map, value: V) { + map.preorder_invoke(place, &mut |place| { + if let Some(vi) = map.places[place].value_index { + self.0[vi] = value.clone(); + } + }); + } + + pub fn assign_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map) { + if let Some(target_value) = map.places[target].value_index { + if let Some(source_value) = map.places[source].value_index { + self.0[target_value] = self.0[source_value].clone(); + } else { + self.0[target_value] = V::top(); + } + } + for target_child in map.children(target) { + // Try to find corresponding child in source. + let projection = map.places[target_child].proj_elem.unwrap(); + if let Some(source_child) = map.projections.get(&(source, projection)) { + self.assign_place_idx(target_child, *source_child, map); + } else { + self.flood_idx(target_child, map, V::top()); + } + } + } + + pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlace, map: &Map) { + if let Some(target) = map.find(target) { + self.assign_idx(target, result, map); + } + } + + pub fn assign_idx(&mut self, target: PlaceIndex, result: ValueOrPlace, map: &Map) { + match result { + ValueOrPlace::Value(value) => { + // FIXME: What if not all tracked projections are overwritten? Can this happen? + if let Some(value_index) = map.places[target].value_index { + self.0[value_index] = value; + } + } + ValueOrPlace::Place(source) => self.assign_place_idx(target, source, map), + ValueOrPlace::Unknown => { + self.flood_idx(target, map, V::top()); + } + } + } + + pub fn get(&self, place: PlaceRef<'_>, map: &Map) -> V { + map.find(place).map(|place| self.get_idx(place, map)).unwrap_or(V::top()) + } + + pub fn get_idx(&self, place: PlaceIndex, map: &Map) -> V { + map.places[place].value_index.map(|v| self.0[v].clone()).unwrap_or(V::top()) + } +} + +impl JoinSemiLattice for State { + fn join(&mut self, other: &Self) -> bool { + self.0.join(&other.0) + } +} + +#[derive(Debug)] +pub struct Map { + locals: IndexVec>, + projections: FxHashMap<(PlaceIndex, ProjElem), PlaceIndex>, + places: IndexVec, + value_count: usize, +} + +impl Map { + pub fn new() -> Self { + Self { + locals: IndexVec::new(), + projections: FxHashMap::default(), + places: IndexVec::new(), + value_count: 0, + } + } + + /// Register all places with suitable types up to a certain derefence depth (to prevent cycles). + pub fn register_with_filter<'tcx>( + &mut self, + tcx: TyCtxt<'tcx>, + source: &impl HasLocalDecls<'tcx>, + max_derefs: u32, + mut filter: impl FnMut(Ty<'tcx>) -> bool, + ) { + let mut projection = Vec::new(); + for (local, decl) in source.local_decls().iter_enumerated() { + self.register_with_filter_rec( + tcx, + max_derefs, + local, + &mut projection, + decl.ty, + &mut filter, + ); + } + } + + fn register_with_filter_rec<'tcx>( + &mut self, + tcx: TyCtxt<'tcx>, + max_derefs: u32, + local: Local, + projection: &mut Vec>, + ty: Ty<'tcx>, + filter: &mut impl FnMut(Ty<'tcx>) -> bool, + ) { + if filter(ty) { + self.register(local, projection) + .expect("projection should only contain convertible elements"); + } + if max_derefs > 0 { + if let Some(ty::TypeAndMut { ty, .. }) = ty.builtin_deref(false) { + projection.push(PlaceElem::Deref); + self.register_with_filter_rec(tcx, max_derefs - 1, local, projection, ty, filter); + projection.pop(); + } + } + iter_fields(ty, tcx, |variant, field, ty| { + if let Some(variant) = variant { + projection.push(PlaceElem::Downcast(None, variant)); + } + projection.push(PlaceElem::Field(field, ty)); + self.register_with_filter_rec(tcx, max_derefs, local, projection, ty, filter); + projection.pop(); + if variant.is_some() { + projection.pop(); + } + }); + } + + pub fn register<'tcx>( + &mut self, + local: Local, + projection: &[PlaceElem<'tcx>], + ) -> Result<(), ()> { + // Get the base index of the local. + let mut index = + *self.locals.get_or_insert_with(local, || self.places.push(PlaceInfo::new(None))); + + // Apply the projection. + for &elem in projection { + let elem = elem.try_into()?; + index = *self.projections.entry((index, elem)).or_insert_with(|| { + // Prepend new child to the linked list. + let next = self.places.push(PlaceInfo::new(Some(elem))); + self.places[next].next_sibling = self.places[index].first_child; + self.places[index].first_child = Some(next); + next + }); + } + + // Allocate a value slot if it doesn't have one. + if self.places[index].value_index.is_none() { + self.places[index].value_index = Some(self.value_count.into()); + self.value_count += 1; + } + + Ok(()) + } + + pub fn apply_elem(&self, place: PlaceIndex, elem: ProjElem) -> Option { + self.projections.get(&(place, elem)).copied() + } + + pub fn find(&self, place: PlaceRef<'_>) -> Option { + let mut index = *self.locals.get(place.local)?.as_ref()?; + + for &elem in place.projection { + index = self.apply_elem(index, elem.try_into().ok()?)?; + } + + Some(index) + } + + pub fn children(&self, parent: PlaceIndex) -> impl Iterator + '_ { + Children::new(self, parent) + } + + pub fn preorder_invoke(&self, root: PlaceIndex, f: &mut impl FnMut(PlaceIndex)) { + f(root); + for child in self.children(root) { + self.preorder_invoke(child, f); + } + } +} + +#[derive(Debug)] +struct PlaceInfo { + next_sibling: Option, + first_child: Option, + /// The projection used to go from parent to this node (only None for root). + proj_elem: Option, + value_index: Option, +} + +impl PlaceInfo { + fn new(proj_elem: Option) -> Self { + Self { next_sibling: None, first_child: None, proj_elem, value_index: None } + } +} + +struct Children<'a> { + map: &'a Map, + next: Option, +} + +impl<'a> Children<'a> { + fn new(map: &'a Map, parent: PlaceIndex) -> Self { + Self { map, next: map.places[parent].first_child } + } +} + +impl<'a> Iterator for Children<'a> { + type Item = PlaceIndex; + + fn next(&mut self) -> Option { + match self.next { + Some(child) => { + self.next = self.map.places[child].next_sibling; + Some(child) + } + None => None, + } + } +} + +// FIXME: See if we can get rid of `Unknown`. +pub enum ValueOrPlace { + Value(V), + Place(PlaceIndex), + Unknown, +} + +pub trait HasBottom { + fn bottom() -> Self; +} + +pub trait HasTop { + fn top() -> Self; +} + +impl HasBottom for FlatSet { + fn bottom() -> Self { + Self::Bottom + } +} + +impl HasTop for FlatSet { + fn top() -> Self { + Self::Top + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum ProjElem { + Deref, + Field(Field), + Downcast(VariantIdx), +} + +impl TryFrom> for ProjElem { + type Error = (); + + fn try_from(value: ProjectionElem) -> Result { + match value { + ProjectionElem::Deref => Ok(ProjElem::Deref), + ProjectionElem::Field(field, _) => Ok(ProjElem::Field(field)), + ProjectionElem::Downcast(_, variant) => Ok(ProjElem::Downcast(variant)), + _ => Err(()), + } + } +} + +fn iter_fields<'tcx>( + ty: Ty<'tcx>, + tcx: TyCtxt<'tcx>, + mut f: impl FnMut(Option, Field, Ty<'tcx>), +) { + match ty.kind() { + ty::Tuple(list) => { + for (field, ty) in list.iter().enumerate() { + f(None, field.into(), ty); + } + } + ty::Adt(def, substs) => { + for (v_index, v_def) in def.variants().iter_enumerated() { + for (f_index, f_def) in v_def.fields.iter().enumerate() { + let field_ty = tcx.normalize_erasing_regions( + ty::ParamEnv::reveal_all(), + f_def.ty(tcx, substs), + ); + f(Some(v_index), f_index.into(), field_ty); + } + } + } + ty::Closure(_, substs) => { + iter_fields(substs.as_closure().tupled_upvars_ty(), tcx, f); + } + _ => (), + } +} + +fn debug_with_context_rec( + place: PlaceIndex, + place_str: &str, + new: &State, + old: Option<&State>, + map: &Map, + f: &mut Formatter<'_>, +) -> std::fmt::Result { + if let Some(value) = map.places[place].value_index { + match old { + None => writeln!(f, "{}: {:?}", place_str, new.0[value])?, + Some(old) => { + if new.0[value] != old.0[value] { + writeln!(f, "\u{001f}-{}: {:?}", place_str, old.0[value])?; + writeln!(f, "\u{001f}+{}: {:?}", place_str, new.0[value])?; + } + } + } + } + + for child in map.children(place) { + let info_elem = map.places[child].proj_elem.unwrap(); + let child_place_str = match info_elem { + ProjElem::Deref => format!("*{}", place_str), + ProjElem::Field(field) => { + if place_str.starts_with("*") { + format!("({}).{}", place_str, field.index()) + } else { + format!("{}.{}", place_str, field.index()) + } + } + ProjElem::Downcast(variant) => format!("({} as #{})", place_str, variant.index()), + }; + debug_with_context_rec(child, &child_place_str, new, old, map, f)?; + } + + Ok(()) +} + +fn debug_with_context( + new: &State, + old: Option<&State>, + map: &Map, + f: &mut Formatter<'_>, +) -> std::fmt::Result { + for (local, place) in map.locals.iter_enumerated() { + if let Some(place) = place { + debug_with_context_rec(*place, &format!("{:?}", local), new, old, map, f)?; + } + } + Ok(()) +} + +impl<'tcx, T> DebugWithContext> for State +where + T: ValueAnalysis<'tcx>, + T::Value: Debug, +{ + fn fmt_with(&self, ctxt: &ValueAnalysisWrapper, f: &mut Formatter<'_>) -> std::fmt::Result { + debug_with_context(self, None, ctxt.0.map(), f) + } + + fn fmt_diff_with( + &self, + old: &Self, + ctxt: &ValueAnalysisWrapper, + f: &mut Formatter<'_>, + ) -> std::fmt::Result { + debug_with_context(self, Some(old), ctxt.0.map(), f) + } +} diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs new file mode 100644 index 0000000000000..f1220f634acf2 --- /dev/null +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -0,0 +1,490 @@ +use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar}; +use rustc_data_structures::fx::FxHashMap; +use rustc_middle::mir::visit::{MutVisitor, Visitor}; +use rustc_middle::mir::*; +use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; +use rustc_mir_dataflow::value_analysis::{Map, ProjElem, State, ValueAnalysis, ValueOrPlace}; +use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects}; +use rustc_span::DUMMY_SP; + +use crate::MirPass; + +pub struct DataflowConstProp; + +impl<'tcx> MirPass<'tcx> for DataflowConstProp { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + // Choose different minimum level? + sess.mir_opt_level() >= 4 + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + // Decide which places to track during the analysis. + let mut map = Map::new(); + map.register_with_filter(tcx, body, 3, |ty| ty.is_scalar() && !ty.is_unsafe_ptr()); + + // Perform the actual dataflow analysis. + let analysis = ConstAnalysis::new(tcx, body, map); + let results = analysis.wrap().into_engine(tcx, body).iterate_to_fixpoint(); + + // Collect results and patch the body afterwards. + let mut visitor = CollectAndPatch::new(tcx, &results.analysis.0.map); + results.visit_reachable_with(body, &mut visitor); + visitor.visit_body(body); + } +} + +// FIXME: Consider support for discriminants, mutable references, arrays and slices. +struct ConstAnalysis<'tcx> { + map: Map, + tcx: TyCtxt<'tcx>, + ecx: InterpCx<'tcx, 'tcx, DummyMachine>, + param_env: ty::ParamEnv<'tcx>, +} + +impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { + type Value = FlatSet>; + + const NAME: &'static str = "ConstAnalysis"; + + fn map(&self) -> &Map { + &self.map + } + + fn handle_assign( + &self, + target: Place<'tcx>, + rvalue: &Rvalue<'tcx>, + state: &mut State, + ) { + match rvalue { + Rvalue::CheckedBinaryOp(op, box (left, right)) => { + let target = self.map().find(target.as_ref()); + let value_target = target.and_then(|target| { + self.map().apply_elem(target, ProjElem::Field(0_u32.into())) + }); + let overflow_target = target.and_then(|target| { + self.map().apply_elem(target, ProjElem::Field(1_u32.into())) + }); + + if value_target.is_some() || overflow_target.is_some() { + let (val, overflow) = self.binary_op(state, *op, left, right); + + if let Some(value_target) = value_target { + state.assign_idx(value_target, ValueOrPlace::Value(val), self.map()); + } + if let Some(overflow_target) = overflow_target { + state.assign_idx( + overflow_target, + ValueOrPlace::Value(overflow), + self.map(), + ); + } + } + } + _ => self.super_assign(target, rvalue, state), + } + } + + fn handle_rvalue( + &self, + rvalue: &Rvalue<'tcx>, + state: &mut State, + ) -> ValueOrPlace { + match rvalue { + Rvalue::Cast(CastKind::Misc, operand, ty) => { + let operand = self.eval_operand(operand, state); + match operand { + FlatSet::Elem(operand) => self + .ecx + .misc_cast(&operand, *ty) + .map(|result| ValueOrPlace::Value(self.wrap_immediate(result, *ty))) + .unwrap_or(ValueOrPlace::Unknown), + _ => ValueOrPlace::Unknown, + } + } + Rvalue::BinaryOp(op, box (left, right)) => { + let (val, _overflow) = self.binary_op(state, *op, left, right); + // FIXME: Just ignore overflow here? + ValueOrPlace::Value(val) + } + Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) { + FlatSet::Elem(value) => self + .ecx + .unary_op(*op, &value) + .map(|val| ValueOrPlace::Value(self.wrap_immty(val))) + .unwrap_or(ValueOrPlace::Value(FlatSet::Top)), + FlatSet::Bottom => ValueOrPlace::Value(FlatSet::Bottom), + FlatSet::Top => ValueOrPlace::Value(FlatSet::Top), + }, + _ => self.super_rvalue(rvalue, state), + } + } + + fn handle_constant( + &self, + constant: &Constant<'tcx>, + _state: &mut State, + ) -> Self::Value { + constant + .literal + .eval(self.tcx, self.param_env) + .try_to_scalar() + .and_then(|scalar| scalar.try_to_int().ok()) + .map(|value| FlatSet::Elem(Const::Scalar(value, constant.ty()))) + .unwrap_or(FlatSet::Top) + } + + fn handle_switch_int( + &self, + discr: &Operand<'tcx>, + apply_edge_effects: &mut impl SwitchIntEdgeEffects>, + ) { + // FIXME: The dataflow framework only provides the state if we call `apply()`, which makes + // this more inefficient than it has to be. + // FIXME: Perhaps we rather need a proper unreachability flag for every block. + let mut discr_value = None; + let mut handled = false; + apply_edge_effects.apply(|state, target| { + let discr_value = match discr_value { + Some(value) => value, + None => { + let value = match self.handle_operand(discr, state) { + ValueOrPlace::Value(value) => value, + ValueOrPlace::Place(place) => state.get_idx(place, self.map()), + ValueOrPlace::Unknown => FlatSet::Top, + }; + let result = match value { + FlatSet::Top => FlatSet::Top, + FlatSet::Elem(Const::Scalar(scalar, _)) => { + FlatSet::Elem(scalar.assert_bits(scalar.size())) + } + FlatSet::Bottom => FlatSet::Bottom, + }; + discr_value = Some(result); + result + } + }; + + let FlatSet::Elem(choice) = discr_value else { + // Do nothing if we don't know which branch will be taken. + return + }; + + if target.value.map(|n| n == choice).unwrap_or(!handled) { + // Branch is taken. Has no effect on state. + handled = true; + } else { + // Branch is not taken, we can flood everything. + state.flood_all(FlatSet::Bottom); + } + }) + } +} + +#[derive(Clone, PartialEq, Eq)] +enum Const<'tcx> { + // FIXME: If there won't be any other cases, make it a struct. + Scalar(ScalarInt, Ty<'tcx>), +} + +impl<'tcx> std::fmt::Debug for Const<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + Self::Scalar(scalar, ty) => { + std::fmt::Display::fmt(&ConstantKind::Val(ConstValue::Scalar(scalar.into()), ty), f) + } + } + } +} + +impl<'tcx> ConstAnalysis<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, map: Map) -> Self { + Self { + map, + tcx, + ecx: InterpCx::new(tcx, DUMMY_SP, ty::ParamEnv::empty(), DummyMachine), + param_env: tcx.param_env(body.source.def_id()), + } + } + + fn binary_op( + &self, + state: &mut State>>, + op: BinOp, + left: &Operand<'tcx>, + right: &Operand<'tcx>, + ) -> (FlatSet>, FlatSet>) { + let left = self.eval_operand(left, state); + let right = self.eval_operand(right, state); + match (left, right) { + (FlatSet::Elem(left), FlatSet::Elem(right)) => { + match self.ecx.overflowing_binary_op(op, &left, &right) { + Ok((val, overflow, ty)) => { + let val = val + .try_to_int() + .ok() + .map(|val| self.wrap_scalar(val, ty)) + .unwrap_or(FlatSet::Top); + let overflow = self.wrap_scalar(overflow.into(), self.tcx.types.bool); + (val, overflow) + } + _ => (FlatSet::Top, FlatSet::Top), + } + } + (FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom), + (_, _) => { + // Could attempt some algebraic simplifcations here. + (FlatSet::Top, FlatSet::Top) + } + } + } + + fn eval_operand( + &self, + op: &Operand<'tcx>, + state: &mut State>>, + ) -> FlatSet> { + let value = match self.handle_operand(op, state) { + ValueOrPlace::Value(value) => value, + ValueOrPlace::Place(place) => state.get_idx(place, &self.map), + ValueOrPlace::Unknown => FlatSet::Top, + }; + match value { + FlatSet::Top => FlatSet::Top, + FlatSet::Elem(Const::Scalar(value, ty)) => { + let layout = self + .tcx + .layout_of(ty::ParamEnv::empty().and(ty)) + .expect("this should not happen"); // FIXME + FlatSet::Elem(ImmTy::from_scalar(value.into(), layout)) + } + FlatSet::Bottom => FlatSet::Bottom, + } + } + + fn wrap_scalar(&self, scalar: ScalarInt, ty: Ty<'tcx>) -> FlatSet> { + FlatSet::Elem(Const::Scalar(scalar, ty)) + } + + fn wrap_immediate(&self, imm: Immediate, ty: Ty<'tcx>) -> FlatSet> { + match imm { + Immediate::Scalar(Scalar::Int(scalar)) => self.wrap_scalar(scalar, ty), + _ => FlatSet::Top, + } + } + + fn wrap_immty(&self, val: ImmTy<'tcx>) -> FlatSet> { + self.wrap_immediate(*val, val.layout.ty) + } +} + +struct CollectAndPatch<'tcx, 'map> { + tcx: TyCtxt<'tcx>, + map: &'map Map, + before_effect: FxHashMap<(Location, Place<'tcx>), Const<'tcx>>, + assignments: FxHashMap>, +} + +impl<'tcx, 'map> CollectAndPatch<'tcx, 'map> { + fn new(tcx: TyCtxt<'tcx>, map: &'map Map) -> Self { + Self { tcx, map, before_effect: FxHashMap::default(), assignments: FxHashMap::default() } + } + + fn make_operand(&self, constant: Const<'tcx>) -> Operand<'tcx> { + let Const::Scalar(scalar, ty) = constant; + Operand::Constant(Box::new(Constant { + span: DUMMY_SP, + user_ty: None, + literal: ConstantKind::Val(ConstValue::Scalar(scalar.into()), ty), + })) + } +} + +impl<'mir, 'tcx, 'map> ResultsVisitor<'mir, 'tcx> for CollectAndPatch<'tcx, 'map> { + type FlowState = State>>; + + fn visit_statement_before_primary_effect( + &mut self, + state: &Self::FlowState, + statement: &'mir Statement<'tcx>, + location: Location, + ) { + match &statement.kind { + StatementKind::Assign(box (_, rvalue)) => { + OperandCollector { state, visitor: self }.visit_rvalue(rvalue, location); + } + _ => (), + } + } + + fn visit_statement_after_primary_effect( + &mut self, + state: &Self::FlowState, + statement: &'mir Statement<'tcx>, + location: Location, + ) { + match statement.kind { + StatementKind::Assign(box (place, _)) => match state.get(place.as_ref(), self.map) { + FlatSet::Top => (), + FlatSet::Elem(value) => { + self.assignments.insert(location, value); + } + FlatSet::Bottom => { + // This statement is not reachable. Do nothing, it will (hopefully) be removed. + } + }, + _ => (), + } + } + + fn visit_terminator_before_primary_effect( + &mut self, + state: &Self::FlowState, + terminator: &'mir Terminator<'tcx>, + location: Location, + ) { + OperandCollector { state, visitor: self }.visit_terminator(terminator, location); + } +} + +impl<'tcx, 'map> MutVisitor<'tcx> for CollectAndPatch<'tcx, 'map> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) { + if let Some(value) = self.assignments.get(&location) { + match &mut statement.kind { + StatementKind::Assign(box (_, rvalue)) => { + *rvalue = Rvalue::Use(self.make_operand(value.clone())); + } + _ => bug!("found assignment info for non-assign statement"), + } + } else { + self.super_statement(statement, location); + } + } + + fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { + match operand { + Operand::Copy(place) | Operand::Move(place) => { + if let Some(value) = self.before_effect.get(&(location, *place)) { + *operand = self.make_operand(value.clone()); + } + } + _ => (), + } + } +} + +struct OperandCollector<'tcx, 'map, 'a> { + state: &'a State>>, + visitor: &'a mut CollectAndPatch<'tcx, 'map>, +} + +impl<'tcx, 'map, 'a> Visitor<'tcx> for OperandCollector<'tcx, 'map, 'a> { + fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { + match operand { + Operand::Copy(place) | Operand::Move(place) => { + match self.state.get(place.as_ref(), self.visitor.map) { + FlatSet::Top => (), + FlatSet::Elem(value) => { + self.visitor.before_effect.insert((location, *place), value); + } + FlatSet::Bottom => { + // This only happens if this location is unreachable. + } + } + } + _ => (), + } + } +} + +struct DummyMachine; + +impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachine { + rustc_const_eval::interpret::compile_time_machine!(<'mir, 'tcx>); + type MemoryKind = !; + const PANIC_ON_ALLOC_FAIL: bool = true; + + fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { + unimplemented!() + } + + fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { + unimplemented!() + } + + fn find_mir_or_eval_fn( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _instance: ty::Instance<'tcx>, + _abi: rustc_target::spec::abi::Abi, + _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>], + _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>, + _target: Option, + _unwind: rustc_const_eval::interpret::StackPopUnwind, + ) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> { + unimplemented!() + } + + fn call_intrinsic( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _instance: ty::Instance<'tcx>, + _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>], + _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>, + _target: Option, + _unwind: rustc_const_eval::interpret::StackPopUnwind, + ) -> interpret::InterpResult<'tcx> { + unimplemented!() + } + + fn assert_panic( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _msg: &rustc_middle::mir::AssertMessage<'tcx>, + _unwind: Option, + ) -> interpret::InterpResult<'tcx> { + unimplemented!() + } + + fn binary_ptr_op( + _ecx: &InterpCx<'mir, 'tcx, Self>, + _bin_op: BinOp, + _left: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>, + _right: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>, + ) -> interpret::InterpResult<'tcx, (interpret::Scalar, bool, Ty<'tcx>)> { + unimplemented!() + } + + fn expose_ptr( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _ptr: interpret::Pointer, + ) -> interpret::InterpResult<'tcx> { + unimplemented!() + } + + fn init_frame_extra( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _frame: rustc_const_eval::interpret::Frame<'mir, 'tcx, Self::Provenance>, + ) -> interpret::InterpResult< + 'tcx, + rustc_const_eval::interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>, + > { + unimplemented!() + } + + fn stack<'a>( + _ecx: &'a InterpCx<'mir, 'tcx, Self>, + ) -> &'a [rustc_const_eval::interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] + { + unimplemented!() + } + + fn stack_mut<'a>( + _ecx: &'a mut InterpCx<'mir, 'tcx, Self>, + ) -> &'a mut Vec< + rustc_const_eval::interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>, + > { + unimplemented!() + } +} diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 4791be1306c1b..692eeddfb9857 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -54,6 +54,7 @@ mod const_goto; mod const_prop; mod const_prop_lint; mod coverage; +mod dataflow_const_prop; mod dead_store_elimination; mod deaggregator; mod deduce_param_attrs; @@ -569,6 +570,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // // FIXME(#70073): This pass is responsible for both optimization as well as some lints. &const_prop::ConstProp, + &dataflow_const_prop::DataflowConstProp, // // Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0. &const_debuginfo::ConstDebugInfo, diff --git a/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..950b0518e0bb2 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff @@ -0,0 +1,41 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/cast.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/cast.rs:+1:9: +1:10 + let mut _3: u8; // in scope 0 at $DIR/cast.rs:+2:13: +2:22 + let mut _4: i32; // in scope 0 at $DIR/cast.rs:+2:13: +2:16 + let mut _5: &i32; // in scope 0 at $DIR/cast.rs:+2:14: +2:16 + scope 1 { + debug a => _1; // in scope 1 at $DIR/cast.rs:+1:9: +1:10 + let _2: u8; // in scope 1 at $DIR/cast.rs:+2:9: +2:10 + scope 2 { + debug b => _2; // in scope 2 at $DIR/cast.rs:+2:9: +2:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/cast.rs:+1:9: +1:10 + _1 = const 257_i32; // scope 0 at $DIR/cast.rs:+1:13: +1:16 + StorageLive(_2); // scope 1 at $DIR/cast.rs:+2:9: +2:10 + StorageLive(_3); // scope 1 at $DIR/cast.rs:+2:13: +2:22 + StorageLive(_4); // scope 1 at $DIR/cast.rs:+2:13: +2:16 + StorageLive(_5); // scope 1 at $DIR/cast.rs:+2:14: +2:16 + _5 = &_1; // scope 1 at $DIR/cast.rs:+2:14: +2:16 +- _4 = (*_5); // scope 1 at $DIR/cast.rs:+2:13: +2:16 +- _3 = move _4 as u8 (Misc); // scope 1 at $DIR/cast.rs:+2:13: +2:22 ++ _4 = const 257_i32; // scope 1 at $DIR/cast.rs:+2:13: +2:16 ++ _3 = const 1_u8; // scope 1 at $DIR/cast.rs:+2:13: +2:22 + StorageDead(_4); // scope 1 at $DIR/cast.rs:+2:21: +2:22 +- _2 = Add(move _3, const 1_u8); // scope 1 at $DIR/cast.rs:+2:13: +2:26 ++ _2 = const 2_u8; // scope 1 at $DIR/cast.rs:+2:13: +2:26 + StorageDead(_3); // scope 1 at $DIR/cast.rs:+2:25: +2:26 + StorageDead(_5); // scope 1 at $DIR/cast.rs:+2:26: +2:27 + _0 = const (); // scope 0 at $DIR/cast.rs:+0:11: +3:2 + StorageDead(_2); // scope 1 at $DIR/cast.rs:+3:1: +3:2 + StorageDead(_1); // scope 0 at $DIR/cast.rs:+3:1: +3:2 + return; // scope 0 at $DIR/cast.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/cast.rs b/src/test/mir-opt/dataflow-const-prop/cast.rs new file mode 100644 index 0000000000000..bf5838cb89dd1 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/cast.rs @@ -0,0 +1,7 @@ +// unit-test: DataflowConstProp + +// EMIT_MIR cast.main.DataflowConstProp.diff +fn main() { + let a = 257; + let b = *&a as u8 + 1; +} diff --git a/src/test/mir-opt/dataflow-const-prop/cell.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/cell.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..e947f08497068 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/cell.main.DataflowConstProp.diff @@ -0,0 +1,12 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/cell.rs:+0:11: +0:11 + + bb0: { + _0 = const (); // scope 0 at $DIR/cell.rs:+0:11: +2:2 + return; // scope 0 at $DIR/cell.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/cell.rs b/src/test/mir-opt/dataflow-const-prop/cell.rs new file mode 100644 index 0000000000000..82a4c3465959b --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/cell.rs @@ -0,0 +1,6 @@ +// unit-test: DataflowConstProp + +// EMIT_MIR cell.main.DataflowConstProp.diff +fn main() { + // FIXME: Is it possible to build something with UnsafeCell? +} diff --git a/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..39bc506adacea --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff @@ -0,0 +1,81 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/checked.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/checked.rs:+1:9: +1:10 + let mut _4: i32; // in scope 0 at $DIR/checked.rs:+3:13: +3:14 + let mut _5: i32; // in scope 0 at $DIR/checked.rs:+3:17: +3:18 + let mut _6: (i32, bool); // in scope 0 at $DIR/checked.rs:+3:13: +3:18 + let mut _9: i32; // in scope 0 at $DIR/checked.rs:+6:13: +6:14 + let mut _10: (i32, bool); // in scope 0 at $DIR/checked.rs:+6:13: +6:18 + scope 1 { + debug a => _1; // in scope 1 at $DIR/checked.rs:+1:9: +1:10 + let _2: i32; // in scope 1 at $DIR/checked.rs:+2:9: +2:10 + scope 2 { + debug b => _2; // in scope 2 at $DIR/checked.rs:+2:9: +2:10 + let _3: i32; // in scope 2 at $DIR/checked.rs:+3:9: +3:10 + scope 3 { + debug c => _3; // in scope 3 at $DIR/checked.rs:+3:9: +3:10 + let _7: i32; // in scope 3 at $DIR/checked.rs:+5:9: +5:10 + scope 4 { + debug d => _7; // in scope 4 at $DIR/checked.rs:+5:9: +5:10 + let _8: i32; // in scope 4 at $DIR/checked.rs:+6:9: +6:10 + scope 5 { + debug e => _8; // in scope 5 at $DIR/checked.rs:+6:9: +6:10 + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/checked.rs:+1:9: +1:10 + _1 = const 1_i32; // scope 0 at $DIR/checked.rs:+1:13: +1:14 + StorageLive(_2); // scope 1 at $DIR/checked.rs:+2:9: +2:10 + _2 = const 2_i32; // scope 1 at $DIR/checked.rs:+2:13: +2:14 + StorageLive(_3); // scope 2 at $DIR/checked.rs:+3:9: +3:10 + StorageLive(_4); // scope 2 at $DIR/checked.rs:+3:13: +3:14 +- _4 = _1; // scope 2 at $DIR/checked.rs:+3:13: +3:14 ++ _4 = const 1_i32; // scope 2 at $DIR/checked.rs:+3:13: +3:14 + StorageLive(_5); // scope 2 at $DIR/checked.rs:+3:17: +3:18 +- _5 = _2; // scope 2 at $DIR/checked.rs:+3:17: +3:18 +- _6 = CheckedAdd(_4, _5); // scope 2 at $DIR/checked.rs:+3:13: +3:18 +- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> bb1; // scope 2 at $DIR/checked.rs:+3:13: +3:18 ++ _5 = const 2_i32; // scope 2 at $DIR/checked.rs:+3:17: +3:18 ++ _6 = CheckedAdd(const 1_i32, const 2_i32); // scope 2 at $DIR/checked.rs:+3:13: +3:18 ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> bb1; // scope 2 at $DIR/checked.rs:+3:13: +3:18 + } + + bb1: { +- _3 = move (_6.0: i32); // scope 2 at $DIR/checked.rs:+3:13: +3:18 ++ _3 = const 3_i32; // scope 2 at $DIR/checked.rs:+3:13: +3:18 + StorageDead(_5); // scope 2 at $DIR/checked.rs:+3:17: +3:18 + StorageDead(_4); // scope 2 at $DIR/checked.rs:+3:17: +3:18 + StorageLive(_7); // scope 3 at $DIR/checked.rs:+5:9: +5:10 +- _7 = const core::num::::MAX; // scope 3 at $DIR/checked.rs:+5:13: +5:21 ++ _7 = const i32::MAX; // scope 3 at $DIR/checked.rs:+5:13: +5:21 + StorageLive(_8); // scope 4 at $DIR/checked.rs:+6:9: +6:10 + StorageLive(_9); // scope 4 at $DIR/checked.rs:+6:13: +6:14 +- _9 = _7; // scope 4 at $DIR/checked.rs:+6:13: +6:14 +- _10 = CheckedAdd(_9, const 1_i32); // scope 4 at $DIR/checked.rs:+6:13: +6:18 +- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> bb2; // scope 4 at $DIR/checked.rs:+6:13: +6:18 ++ _9 = const i32::MAX; // scope 4 at $DIR/checked.rs:+6:13: +6:14 ++ _10 = CheckedAdd(const i32::MAX, const 1_i32); // scope 4 at $DIR/checked.rs:+6:13: +6:18 ++ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> bb2; // scope 4 at $DIR/checked.rs:+6:13: +6:18 + } + + bb2: { +- _8 = move (_10.0: i32); // scope 4 at $DIR/checked.rs:+6:13: +6:18 ++ _8 = const i32::MIN; // scope 4 at $DIR/checked.rs:+6:13: +6:18 + StorageDead(_9); // scope 4 at $DIR/checked.rs:+6:17: +6:18 + _0 = const (); // scope 0 at $DIR/checked.rs:+0:11: +7:2 + StorageDead(_8); // scope 4 at $DIR/checked.rs:+7:1: +7:2 + StorageDead(_7); // scope 3 at $DIR/checked.rs:+7:1: +7:2 + StorageDead(_3); // scope 2 at $DIR/checked.rs:+7:1: +7:2 + StorageDead(_2); // scope 1 at $DIR/checked.rs:+7:1: +7:2 + StorageDead(_1); // scope 0 at $DIR/checked.rs:+7:1: +7:2 + return; // scope 0 at $DIR/checked.rs:+7:2: +7:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/checked.rs b/src/test/mir-opt/dataflow-const-prop/checked.rs new file mode 100644 index 0000000000000..ae457af72c066 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/checked.rs @@ -0,0 +1,13 @@ +// unit-test: DataflowConstProp +// compile-flags: -C overflow-checks=on + +// EMIT_MIR checked.main.DataflowConstProp.diff +#[allow(arithmetic_overflow)] +fn main() { + let a = 1; + let b = 2; + let c = a + b; + + let d = i32::MAX; + let e = d + 1; +} diff --git a/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..951e5c5b9ad4e --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff @@ -0,0 +1,118 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/if.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/if.rs:+2:9: +2:10 + let mut _3: bool; // in scope 0 at $DIR/if.rs:+3:16: +3:24 + let mut _4: i32; // in scope 0 at $DIR/if.rs:+3:16: +3:19 + let mut _5: &i32; // in scope 0 at $DIR/if.rs:+3:17: +3:19 + let mut _7: i32; // in scope 0 at $DIR/if.rs:+4:13: +4:14 + let mut _9: bool; // in scope 0 at $DIR/if.rs:+6:16: +6:24 + let mut _10: i32; // in scope 0 at $DIR/if.rs:+6:16: +6:19 + let mut _11: &i32; // in scope 0 at $DIR/if.rs:+6:17: +6:19 + let mut _12: i32; // in scope 0 at $DIR/if.rs:+6:38: +6:39 + let mut _14: i32; // in scope 0 at $DIR/if.rs:+7:13: +7:14 + scope 1 { + debug a => _1; // in scope 1 at $DIR/if.rs:+2:9: +2:10 + let _2: i32; // in scope 1 at $DIR/if.rs:+3:9: +3:10 + scope 2 { + debug b => _2; // in scope 2 at $DIR/if.rs:+3:9: +3:10 + let _6: i32; // in scope 2 at $DIR/if.rs:+4:9: +4:10 + scope 3 { + debug c => _6; // in scope 3 at $DIR/if.rs:+4:9: +4:10 + let _8: i32; // in scope 3 at $DIR/if.rs:+6:9: +6:10 + scope 4 { + debug d => _8; // in scope 4 at $DIR/if.rs:+6:9: +6:10 + let _13: i32; // in scope 4 at $DIR/if.rs:+7:9: +7:10 + scope 5 { + debug e => _13; // in scope 5 at $DIR/if.rs:+7:9: +7:10 + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/if.rs:+2:9: +2:10 + _1 = const 1_i32; // scope 0 at $DIR/if.rs:+2:13: +2:14 + StorageLive(_2); // scope 1 at $DIR/if.rs:+3:9: +3:10 + StorageLive(_3); // scope 1 at $DIR/if.rs:+3:16: +3:24 + StorageLive(_4); // scope 1 at $DIR/if.rs:+3:16: +3:19 + StorageLive(_5); // scope 1 at $DIR/if.rs:+3:17: +3:19 + _5 = &_1; // scope 1 at $DIR/if.rs:+3:17: +3:19 +- _4 = (*_5); // scope 1 at $DIR/if.rs:+3:16: +3:19 +- _3 = Eq(move _4, const 1_i32); // scope 1 at $DIR/if.rs:+3:16: +3:24 ++ _4 = const 1_i32; // scope 1 at $DIR/if.rs:+3:16: +3:19 ++ _3 = const true; // scope 1 at $DIR/if.rs:+3:16: +3:24 + StorageDead(_5); // scope 1 at $DIR/if.rs:+3:23: +3:24 + StorageDead(_4); // scope 1 at $DIR/if.rs:+3:23: +3:24 +- switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+3:16: +3:24 ++ switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+3:16: +3:24 + } + + bb1: { + _2 = const 2_i32; // scope 1 at $DIR/if.rs:+3:27: +3:28 + goto -> bb3; // scope 1 at $DIR/if.rs:+3:13: +3:41 + } + + bb2: { + _2 = const 3_i32; // scope 1 at $DIR/if.rs:+3:38: +3:39 + goto -> bb3; // scope 1 at $DIR/if.rs:+3:13: +3:41 + } + + bb3: { + StorageDead(_3); // scope 1 at $DIR/if.rs:+3:40: +3:41 + StorageLive(_6); // scope 2 at $DIR/if.rs:+4:9: +4:10 + StorageLive(_7); // scope 2 at $DIR/if.rs:+4:13: +4:14 + _7 = _2; // scope 2 at $DIR/if.rs:+4:13: +4:14 + _6 = Add(move _7, const 1_i32); // scope 2 at $DIR/if.rs:+4:13: +4:18 + StorageDead(_7); // scope 2 at $DIR/if.rs:+4:17: +4:18 + StorageLive(_8); // scope 3 at $DIR/if.rs:+6:9: +6:10 + StorageLive(_9); // scope 3 at $DIR/if.rs:+6:16: +6:24 + StorageLive(_10); // scope 3 at $DIR/if.rs:+6:16: +6:19 + StorageLive(_11); // scope 3 at $DIR/if.rs:+6:17: +6:19 + _11 = &_1; // scope 3 at $DIR/if.rs:+6:17: +6:19 +- _10 = (*_11); // scope 3 at $DIR/if.rs:+6:16: +6:19 +- _9 = Eq(move _10, const 1_i32); // scope 3 at $DIR/if.rs:+6:16: +6:24 ++ _10 = const 1_i32; // scope 3 at $DIR/if.rs:+6:16: +6:19 ++ _9 = const true; // scope 3 at $DIR/if.rs:+6:16: +6:24 + StorageDead(_11); // scope 3 at $DIR/if.rs:+6:23: +6:24 + StorageDead(_10); // scope 3 at $DIR/if.rs:+6:23: +6:24 +- switchInt(move _9) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+6:16: +6:24 ++ switchInt(const true) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+6:16: +6:24 + } + + bb4: { +- _8 = _1; // scope 3 at $DIR/if.rs:+6:27: +6:28 ++ _8 = const 1_i32; // scope 3 at $DIR/if.rs:+6:27: +6:28 + goto -> bb6; // scope 3 at $DIR/if.rs:+6:13: +6:45 + } + + bb5: { + StorageLive(_12); // scope 3 at $DIR/if.rs:+6:38: +6:39 + _12 = _1; // scope 3 at $DIR/if.rs:+6:38: +6:39 + _8 = Add(move _12, const 1_i32); // scope 3 at $DIR/if.rs:+6:38: +6:43 + StorageDead(_12); // scope 3 at $DIR/if.rs:+6:42: +6:43 + goto -> bb6; // scope 3 at $DIR/if.rs:+6:13: +6:45 + } + + bb6: { + StorageDead(_9); // scope 3 at $DIR/if.rs:+6:44: +6:45 + StorageLive(_13); // scope 4 at $DIR/if.rs:+7:9: +7:10 + StorageLive(_14); // scope 4 at $DIR/if.rs:+7:13: +7:14 +- _14 = _8; // scope 4 at $DIR/if.rs:+7:13: +7:14 +- _13 = Add(move _14, const 1_i32); // scope 4 at $DIR/if.rs:+7:13: +7:18 ++ _14 = const 1_i32; // scope 4 at $DIR/if.rs:+7:13: +7:14 ++ _13 = const 2_i32; // scope 4 at $DIR/if.rs:+7:13: +7:18 + StorageDead(_14); // scope 4 at $DIR/if.rs:+7:17: +7:18 + _0 = const (); // scope 0 at $DIR/if.rs:+0:11: +8:2 + StorageDead(_13); // scope 4 at $DIR/if.rs:+8:1: +8:2 + StorageDead(_8); // scope 3 at $DIR/if.rs:+8:1: +8:2 + StorageDead(_6); // scope 2 at $DIR/if.rs:+8:1: +8:2 + StorageDead(_2); // scope 1 at $DIR/if.rs:+8:1: +8:2 + StorageDead(_1); // scope 0 at $DIR/if.rs:+8:1: +8:2 + return; // scope 0 at $DIR/if.rs:+8:2: +8:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/if.rs b/src/test/mir-opt/dataflow-const-prop/if.rs new file mode 100644 index 0000000000000..8df8908047797 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/if.rs @@ -0,0 +1,12 @@ +// unit-test: DataflowConstProp + +// EMIT_MIR if.main.DataflowConstProp.diff +fn main() { + // This does not work (yet). Needs perhaps additional state to track unreachability. + let a = 1; + let b = if *&a == 1 { 2 } else { 3 }; + let c = b + 1; + + let d = if *&a == 1 { a } else { a + 1 }; + let e = d + 1; +} diff --git a/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..d5a17d0835616 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff @@ -0,0 +1,29 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/promoted.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/promoted.rs:+2:9: +2:10 + let mut _2: &i32; // in scope 0 at $DIR/promoted.rs:+2:14: +2:17 + let _3: i32; // in scope 0 at $DIR/promoted.rs:+2:15: +2:17 + let mut _4: &i32; // in scope 0 at $DIR/promoted.rs:+2:14: +2:17 + scope 1 { + debug a => _1; // in scope 1 at $DIR/promoted.rs:+2:9: +2:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/promoted.rs:+2:9: +2:10 + StorageLive(_2); // scope 0 at $DIR/promoted.rs:+2:14: +2:17 + _4 = const main::promoted[0]; // scope 0 at $DIR/promoted.rs:+2:14: +2:17 + // mir::Constant + // + span: $DIR/promoted.rs:6:14: 6:17 + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } + _2 = &(*_4); // scope 0 at $DIR/promoted.rs:+2:14: +2:17 + _1 = (*_2); // scope 0 at $DIR/promoted.rs:+2:13: +2:17 + StorageDead(_2); // scope 0 at $DIR/promoted.rs:+2:17: +2:18 + _0 = const (); // scope 0 at $DIR/promoted.rs:+0:11: +3:2 + StorageDead(_1); // scope 0 at $DIR/promoted.rs:+3:1: +3:2 + return; // scope 0 at $DIR/promoted.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/promoted.rs b/src/test/mir-opt/dataflow-const-prop/promoted.rs new file mode 100644 index 0000000000000..1653cf3334408 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/promoted.rs @@ -0,0 +1,7 @@ +// unit-test: DataflowConstProp + +// EMIT_MIR promoted.main.DataflowConstProp.diff +fn main() { + // This does not work because `&42` gets promoted. + let a = *&42; +} diff --git a/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..953628cff06f9 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff @@ -0,0 +1,133 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/recursive.rs:+0:11: +0:11 + let _1: S; // in scope 0 at $DIR/recursive.rs:+1:9: +1:10 + let mut _3: &S; // in scope 0 at $DIR/recursive.rs:+2:20: +2:22 + let _4: &S; // in scope 0 at $DIR/recursive.rs:+2:20: +2:22 + let mut _6: &S; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 + let _7: &S; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 + let mut _9: isize; // in scope 0 at $DIR/recursive.rs:+5:9: +5:18 + let mut _11: isize; // in scope 0 at $DIR/recursive.rs:+6:13: +6:22 + let mut _13: isize; // in scope 0 at $DIR/recursive.rs:+7:17: +7:28 + let mut _15: !; // in scope 0 at $DIR/recursive.rs:+8:22: +8:43 + let mut _16: !; // in scope 0 at $DIR/recursive.rs:+10:18: +10:39 + let mut _17: !; // in scope 0 at $DIR/recursive.rs:+12:14: +12:35 + let mut _18: &S; // in scope 0 at $DIR/recursive.rs:+6:20: +6:21 + let mut _19: &S; // in scope 0 at $DIR/recursive.rs:+6:20: +6:21 + scope 1 { + debug a => _1; // in scope 1 at $DIR/recursive.rs:+1:9: +1:10 + let _2: S; // in scope 1 at $DIR/recursive.rs:+2:9: +2:10 + scope 2 { + debug b => _2; // in scope 2 at $DIR/recursive.rs:+2:9: +2:10 + let _5: S; // in scope 2 at $DIR/recursive.rs:+3:9: +3:10 + scope 3 { + debug c => _5; // in scope 3 at $DIR/recursive.rs:+3:9: +3:10 + let _8: u32; // in scope 3 at $DIR/recursive.rs:+4:9: +4:10 + let _10: &S; // in scope 3 at $DIR/recursive.rs:+5:16: +5:17 + scope 4 { + debug d => _8; // in scope 4 at $DIR/recursive.rs:+4:9: +4:10 + } + scope 5 { + debug b => _10; // in scope 5 at $DIR/recursive.rs:+5:16: +5:17 + let _12: &&S; // in scope 5 at $DIR/recursive.rs:+6:20: +6:21 + scope 6 { + debug a => _12; // in scope 6 at $DIR/recursive.rs:+6:20: +6:21 + let _14: &u32; // in scope 6 at $DIR/recursive.rs:+7:24: +7:27 + scope 7 { + debug num => _14; // in scope 7 at $DIR/recursive.rs:+7:24: +7:27 + } + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/recursive.rs:+1:9: +1:10 + Deinit(_1); // scope 0 at $DIR/recursive.rs:+1:13: +1:22 + ((_1 as Num).0: u32) = const 0_u32; // scope 0 at $DIR/recursive.rs:+1:13: +1:22 + discriminant(_1) = 1; // scope 0 at $DIR/recursive.rs:+1:13: +1:22 + StorageLive(_2); // scope 1 at $DIR/recursive.rs:+2:9: +2:10 + StorageLive(_3); // scope 1 at $DIR/recursive.rs:+2:20: +2:22 + StorageLive(_4); // scope 1 at $DIR/recursive.rs:+2:20: +2:22 + _4 = &_1; // scope 1 at $DIR/recursive.rs:+2:20: +2:22 + _3 = &(*_4); // scope 1 at $DIR/recursive.rs:+2:20: +2:22 + Deinit(_2); // scope 1 at $DIR/recursive.rs:+2:13: +2:23 + ((_2 as Rec).0: &S) = move _3; // scope 1 at $DIR/recursive.rs:+2:13: +2:23 + discriminant(_2) = 0; // scope 1 at $DIR/recursive.rs:+2:13: +2:23 + StorageDead(_3); // scope 1 at $DIR/recursive.rs:+2:22: +2:23 + StorageDead(_4); // scope 1 at $DIR/recursive.rs:+2:23: +2:24 + StorageLive(_5); // scope 2 at $DIR/recursive.rs:+3:9: +3:10 + StorageLive(_6); // scope 2 at $DIR/recursive.rs:+3:20: +3:22 + StorageLive(_7); // scope 2 at $DIR/recursive.rs:+3:20: +3:22 + _7 = &_2; // scope 2 at $DIR/recursive.rs:+3:20: +3:22 + _6 = &(*_7); // scope 2 at $DIR/recursive.rs:+3:20: +3:22 + Deinit(_5); // scope 2 at $DIR/recursive.rs:+3:13: +3:23 + ((_5 as Rec).0: &S) = move _6; // scope 2 at $DIR/recursive.rs:+3:13: +3:23 + discriminant(_5) = 0; // scope 2 at $DIR/recursive.rs:+3:13: +3:23 + StorageDead(_6); // scope 2 at $DIR/recursive.rs:+3:22: +3:23 + StorageDead(_7); // scope 2 at $DIR/recursive.rs:+3:23: +3:24 + StorageLive(_8); // scope 3 at $DIR/recursive.rs:+4:9: +4:10 + _9 = discriminant(_5); // scope 3 at $DIR/recursive.rs:+4:19: +4:20 + switchInt(move _9) -> [0_isize: bb2, otherwise: bb1]; // scope 3 at $DIR/recursive.rs:+4:13: +4:20 + } + + bb1: { + StorageLive(_17); // scope 3 at $DIR/recursive.rs:+12:14: +12:35 + _17 = exit(const 0_i32); // scope 3 at $DIR/recursive.rs:+12:14: +12:35 + // mir::Constant + // + span: $DIR/recursive.rs:21:14: 21:32 + // + literal: Const { ty: fn(i32) -> ! {exit}, val: Value() } + } + + bb2: { + StorageLive(_10); // scope 3 at $DIR/recursive.rs:+5:16: +5:17 + _10 = ((_5 as Rec).0: &S); // scope 3 at $DIR/recursive.rs:+5:16: +5:17 + _11 = discriminant((*_10)); // scope 5 at $DIR/recursive.rs:+5:28: +5:29 + switchInt(move _11) -> [0_isize: bb4, otherwise: bb3]; // scope 5 at $DIR/recursive.rs:+5:22: +5:29 + } + + bb3: { + StorageLive(_16); // scope 5 at $DIR/recursive.rs:+10:18: +10:39 + _16 = exit(const 0_i32); // scope 5 at $DIR/recursive.rs:+10:18: +10:39 + // mir::Constant + // + span: $DIR/recursive.rs:19:18: 19:36 + // + literal: Const { ty: fn(i32) -> ! {exit}, val: Value() } + } + + bb4: { + StorageLive(_12); // scope 5 at $DIR/recursive.rs:+6:20: +6:21 + _12 = &(((*_10) as Rec).0: &S); // scope 5 at $DIR/recursive.rs:+6:20: +6:21 + _18 = deref_copy (*_12); // scope 6 at $DIR/recursive.rs:+6:32: +6:33 + _13 = discriminant((*_18)); // scope 6 at $DIR/recursive.rs:+6:32: +6:33 + switchInt(move _13) -> [1_isize: bb6, otherwise: bb5]; // scope 6 at $DIR/recursive.rs:+6:26: +6:33 + } + + bb5: { + StorageLive(_15); // scope 6 at $DIR/recursive.rs:+8:22: +8:43 + _15 = exit(const 0_i32); // scope 6 at $DIR/recursive.rs:+8:22: +8:43 + // mir::Constant + // + span: $DIR/recursive.rs:17:22: 17:40 + // + literal: Const { ty: fn(i32) -> ! {exit}, val: Value() } + } + + bb6: { + StorageLive(_14); // scope 6 at $DIR/recursive.rs:+7:24: +7:27 + _19 = deref_copy (*_12); // scope 6 at $DIR/recursive.rs:+7:24: +7:27 + _14 = &(((*_19) as Num).0: u32); // scope 6 at $DIR/recursive.rs:+7:24: +7:27 +- _8 = (*_14); // scope 7 at $DIR/recursive.rs:+7:32: +7:36 ++ _8 = const 0_u32; // scope 7 at $DIR/recursive.rs:+7:32: +7:36 + StorageDead(_14); // scope 6 at $DIR/recursive.rs:+7:35: +7:36 + StorageDead(_12); // scope 5 at $DIR/recursive.rs:+9:13: +9:14 + StorageDead(_10); // scope 3 at $DIR/recursive.rs:+11:9: +11:10 + _0 = const (); // scope 0 at $DIR/recursive.rs:+0:11: +14:2 + StorageDead(_8); // scope 3 at $DIR/recursive.rs:+14:1: +14:2 + StorageDead(_5); // scope 2 at $DIR/recursive.rs:+14:1: +14:2 + StorageDead(_2); // scope 1 at $DIR/recursive.rs:+14:1: +14:2 + StorageDead(_1); // scope 0 at $DIR/recursive.rs:+14:1: +14:2 + return; // scope 0 at $DIR/recursive.rs:+14:2: +14:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/recursive.rs b/src/test/mir-opt/dataflow-const-prop/recursive.rs new file mode 100644 index 0000000000000..0eda1239ecd05 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/recursive.rs @@ -0,0 +1,23 @@ +// unit-test: DataflowConstProp + +enum S<'a> { + Rec(&'a S<'a>), + Num(u32), +} + +// EMIT_MIR recursive.main.DataflowConstProp.diff +fn main() { + let a = S::Num(0); + let b = S::Rec(&a); + let c = S::Rec(&b); + let d = match c { + S::Rec(b) => match b { + S::Rec(a) => match a { + S::Num(num) => *num, + _ => std::process::exit(0), + }, + _ => std::process::exit(0), + }, + _ => std::process::exit(0), + }; +} diff --git a/src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..6af381617f9ac --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff @@ -0,0 +1,89 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/ref.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/ref.rs:+1:9: +1:10 + let mut _4: bool; // in scope 0 at $DIR/ref.rs:+3:16: +3:43 + let mut _5: u32; // in scope 0 at $DIR/ref.rs:+3:16: +3:38 + let mut _6: u32; // in scope 0 at $DIR/ref.rs:+3:16: +3:34 + let mut _7: bool; // in scope 0 at $DIR/ref.rs:+3:16: +3:38 + let _8: &i32; // in scope 0 at $DIR/ref.rs:+3:58: +3:60 + let mut _10: i32; // in scope 0 at $DIR/ref.rs:+4:13: +4:15 + scope 1 { + debug a => _1; // in scope 1 at $DIR/ref.rs:+1:9: +1:10 + let _2: i32; // in scope 1 at $DIR/ref.rs:+2:9: +2:10 + scope 2 { + debug b => _2; // in scope 2 at $DIR/ref.rs:+2:9: +2:10 + let _3: &i32; // in scope 2 at $DIR/ref.rs:+3:9: +3:10 + scope 3 { + debug c => _3; // in scope 3 at $DIR/ref.rs:+3:9: +3:10 + let _9: i32; // in scope 3 at $DIR/ref.rs:+4:9: +4:10 + scope 4 { + debug d => _9; // in scope 4 at $DIR/ref.rs:+4:9: +4:10 + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/ref.rs:+1:9: +1:10 + _1 = const 0_i32; // scope 0 at $DIR/ref.rs:+1:13: +1:14 + StorageLive(_2); // scope 1 at $DIR/ref.rs:+2:9: +2:10 + _2 = const 0_i32; // scope 1 at $DIR/ref.rs:+2:13: +2:14 + StorageLive(_3); // scope 2 at $DIR/ref.rs:+3:9: +3:10 + StorageLive(_4); // scope 2 at $DIR/ref.rs:+3:16: +3:43 + StorageLive(_5); // scope 2 at $DIR/ref.rs:+3:16: +3:38 + StorageLive(_6); // scope 2 at $DIR/ref.rs:+3:16: +3:34 + _6 = id() -> bb1; // scope 2 at $DIR/ref.rs:+3:16: +3:34 + // mir::Constant + // + span: $DIR/ref.rs:7:16: 7:32 + // + literal: Const { ty: fn() -> u32 {id}, val: Value() } + } + + bb1: { +- _7 = Eq(const 2_u32, const 0_u32); // scope 2 at $DIR/ref.rs:+3:16: +3:38 +- assert(!move _7, "attempt to calculate the remainder of `{}` with a divisor of zero", _6) -> bb2; // scope 2 at $DIR/ref.rs:+3:16: +3:38 ++ _7 = const false; // scope 2 at $DIR/ref.rs:+3:16: +3:38 ++ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _6) -> bb2; // scope 2 at $DIR/ref.rs:+3:16: +3:38 + } + + bb2: { + _5 = Rem(move _6, const 2_u32); // scope 2 at $DIR/ref.rs:+3:16: +3:38 + StorageDead(_6); // scope 2 at $DIR/ref.rs:+3:37: +3:38 + _4 = Eq(move _5, const 0_u32); // scope 2 at $DIR/ref.rs:+3:16: +3:43 + StorageDead(_5); // scope 2 at $DIR/ref.rs:+3:42: +3:43 + switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/ref.rs:+3:16: +3:43 + } + + bb3: { + _3 = &_1; // scope 2 at $DIR/ref.rs:+3:46: +3:48 + goto -> bb5; // scope 2 at $DIR/ref.rs:+3:13: +3:62 + } + + bb4: { + StorageLive(_8); // scope 2 at $DIR/ref.rs:+3:58: +3:60 + _8 = &_2; // scope 2 at $DIR/ref.rs:+3:58: +3:60 + _3 = &(*_8); // scope 2 at $DIR/ref.rs:+3:58: +3:60 + StorageDead(_8); // scope 2 at $DIR/ref.rs:+3:61: +3:62 + goto -> bb5; // scope 2 at $DIR/ref.rs:+3:13: +3:62 + } + + bb5: { + StorageDead(_4); // scope 2 at $DIR/ref.rs:+3:61: +3:62 + StorageLive(_9); // scope 3 at $DIR/ref.rs:+4:9: +4:10 + StorageLive(_10); // scope 3 at $DIR/ref.rs:+4:13: +4:15 +- _10 = (*_3); // scope 3 at $DIR/ref.rs:+4:13: +4:15 +- _9 = Add(move _10, const 1_i32); // scope 3 at $DIR/ref.rs:+4:13: +4:19 ++ _10 = const 0_i32; // scope 3 at $DIR/ref.rs:+4:13: +4:15 ++ _9 = const 1_i32; // scope 3 at $DIR/ref.rs:+4:13: +4:19 + StorageDead(_10); // scope 3 at $DIR/ref.rs:+4:18: +4:19 + _0 = const (); // scope 0 at $DIR/ref.rs:+0:11: +5:2 + StorageDead(_9); // scope 3 at $DIR/ref.rs:+5:1: +5:2 + StorageDead(_3); // scope 2 at $DIR/ref.rs:+5:1: +5:2 + StorageDead(_2); // scope 1 at $DIR/ref.rs:+5:1: +5:2 + StorageDead(_1); // scope 0 at $DIR/ref.rs:+5:1: +5:2 + return; // scope 0 at $DIR/ref.rs:+5:2: +5:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/ref.rs b/src/test/mir-opt/dataflow-const-prop/ref.rs new file mode 100644 index 0000000000000..6da613fc51632 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/ref.rs @@ -0,0 +1,9 @@ +// unit-test: DataflowConstProp + +// EMIT_MIR ref.main.DataflowConstProp.diff +fn main() { + let a = 0; + let b = 0; + let c = if std::process::id() % 2 == 0 { &a } else { &b }; + let d = *c + 1; +} diff --git a/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..fe5bdd07d4a02 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff @@ -0,0 +1,77 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/ref_mut.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/ref_mut.rs:+1:9: +1:14 + let mut _7: &i32; // in scope 0 at $DIR/ref_mut.rs:+9:10: +9:12 + let _8: &i32; // in scope 0 at $DIR/ref_mut.rs:+9:10: +9:12 + let _9: i32; // in scope 0 at $DIR/ref_mut.rs:+9:11: +9:12 + scope 1 { + debug a => _1; // in scope 1 at $DIR/ref_mut.rs:+1:9: +1:14 + let _2: &mut i32; // in scope 1 at $DIR/ref_mut.rs:+2:9: +2:10 + scope 2 { + debug b => _2; // in scope 2 at $DIR/ref_mut.rs:+2:9: +2:10 + let _3: i32; // in scope 2 at $DIR/ref_mut.rs:+4:9: +4:10 + scope 3 { + debug c => _3; // in scope 3 at $DIR/ref_mut.rs:+4:9: +4:10 + let _4: i32; // in scope 3 at $DIR/ref_mut.rs:+6:9: +6:10 + scope 4 { + debug d => _4; // in scope 4 at $DIR/ref_mut.rs:+6:9: +6:10 + let mut _5: &i32; // in scope 4 at $DIR/ref_mut.rs:+7:9: +7:14 + scope 5 { + debug e => _5; // in scope 5 at $DIR/ref_mut.rs:+7:9: +7:14 + let _6: &mut &i32; // in scope 5 at $DIR/ref_mut.rs:+8:9: +8:10 + scope 6 { + debug f => _6; // in scope 6 at $DIR/ref_mut.rs:+8:9: +8:10 + let _10: i32; // in scope 6 at $DIR/ref_mut.rs:+10:9: +10:10 + let mut _11: &i32; // in scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 + scope 7 { + debug g => _10; // in scope 7 at $DIR/ref_mut.rs:+10:9: +10:10 + } + } + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/ref_mut.rs:+1:9: +1:14 + _1 = const 0_i32; // scope 0 at $DIR/ref_mut.rs:+1:17: +1:18 + StorageLive(_2); // scope 1 at $DIR/ref_mut.rs:+2:9: +2:10 + _2 = &mut _1; // scope 1 at $DIR/ref_mut.rs:+2:13: +2:19 + (*_2) = const 1_i32; // scope 2 at $DIR/ref_mut.rs:+3:5: +3:11 + StorageLive(_3); // scope 2 at $DIR/ref_mut.rs:+4:9: +4:10 + _3 = _1; // scope 2 at $DIR/ref_mut.rs:+4:13: +4:14 + StorageLive(_4); // scope 3 at $DIR/ref_mut.rs:+6:9: +6:10 + _4 = const 0_i32; // scope 3 at $DIR/ref_mut.rs:+6:13: +6:14 + StorageLive(_5); // scope 4 at $DIR/ref_mut.rs:+7:9: +7:14 + _5 = &_4; // scope 4 at $DIR/ref_mut.rs:+7:17: +7:19 + StorageLive(_6); // scope 5 at $DIR/ref_mut.rs:+8:9: +8:10 + _6 = &mut _5; // scope 5 at $DIR/ref_mut.rs:+8:13: +8:19 + StorageLive(_7); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 + StorageLive(_8); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 + _11 = const main::promoted[0]; // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 + // mir::Constant + // + span: $DIR/ref_mut.rs:13:10: 13:12 + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } + _8 = &(*_11); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 + _7 = &(*_8); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 + (*_6) = move _7; // scope 6 at $DIR/ref_mut.rs:+9:5: +9:12 + StorageDead(_7); // scope 6 at $DIR/ref_mut.rs:+9:11: +9:12 + StorageDead(_8); // scope 6 at $DIR/ref_mut.rs:+9:12: +9:13 + StorageLive(_10); // scope 6 at $DIR/ref_mut.rs:+10:9: +10:10 + _10 = (*_5); // scope 6 at $DIR/ref_mut.rs:+10:13: +10:15 + _0 = const (); // scope 0 at $DIR/ref_mut.rs:+0:11: +11:2 + StorageDead(_10); // scope 6 at $DIR/ref_mut.rs:+11:1: +11:2 + StorageDead(_6); // scope 5 at $DIR/ref_mut.rs:+11:1: +11:2 + StorageDead(_5); // scope 4 at $DIR/ref_mut.rs:+11:1: +11:2 + StorageDead(_4); // scope 3 at $DIR/ref_mut.rs:+11:1: +11:2 + StorageDead(_3); // scope 2 at $DIR/ref_mut.rs:+11:1: +11:2 + StorageDead(_2); // scope 1 at $DIR/ref_mut.rs:+11:1: +11:2 + StorageDead(_1); // scope 0 at $DIR/ref_mut.rs:+11:1: +11:2 + return; // scope 0 at $DIR/ref_mut.rs:+11:2: +11:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/ref_mut.rs b/src/test/mir-opt/dataflow-const-prop/ref_mut.rs new file mode 100644 index 0000000000000..8b2baf7676df9 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/ref_mut.rs @@ -0,0 +1,15 @@ +// unit-test: DataflowConstProp + +// EMIT_MIR ref_mut.main.DataflowConstProp.diff +fn main() { + let mut a = 0; + let b = &mut a; + *b = 1; + let c = a; + + let d = 0; + let mut e = &d; + let f = &mut e; + *f = &1; + let g = *e; +} diff --git a/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..1d01d4fd2e775 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff @@ -0,0 +1,40 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/terminator.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/terminator.rs:+1:9: +1:10 + let _2: (); // in scope 0 at $DIR/terminator.rs:+2:5: +2:15 + let mut _3: i32; // in scope 0 at $DIR/terminator.rs:+2:9: +2:14 + let mut _4: i32; // in scope 0 at $DIR/terminator.rs:+2:9: +2:10 + scope 1 { + debug a => _1; // in scope 1 at $DIR/terminator.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/terminator.rs:+1:9: +1:10 + _1 = const 1_i32; // scope 0 at $DIR/terminator.rs:+1:13: +1:14 + StorageLive(_2); // scope 1 at $DIR/terminator.rs:+2:5: +2:15 + StorageLive(_3); // scope 1 at $DIR/terminator.rs:+2:9: +2:14 + StorageLive(_4); // scope 1 at $DIR/terminator.rs:+2:9: +2:10 +- _4 = _1; // scope 1 at $DIR/terminator.rs:+2:9: +2:10 +- _3 = Add(move _4, const 1_i32); // scope 1 at $DIR/terminator.rs:+2:9: +2:14 ++ _4 = const 1_i32; // scope 1 at $DIR/terminator.rs:+2:9: +2:10 ++ _3 = const 2_i32; // scope 1 at $DIR/terminator.rs:+2:9: +2:14 + StorageDead(_4); // scope 1 at $DIR/terminator.rs:+2:13: +2:14 +- _2 = foo(move _3) -> bb1; // scope 1 at $DIR/terminator.rs:+2:5: +2:15 ++ _2 = foo(const 2_i32) -> bb1; // scope 1 at $DIR/terminator.rs:+2:5: +2:15 + // mir::Constant + // + span: $DIR/terminator.rs:8:5: 8:8 + // + literal: Const { ty: fn(i32) {foo}, val: Value() } + } + + bb1: { + StorageDead(_3); // scope 1 at $DIR/terminator.rs:+2:14: +2:15 + StorageDead(_2); // scope 1 at $DIR/terminator.rs:+2:15: +2:16 + _0 = const (); // scope 0 at $DIR/terminator.rs:+0:11: +3:2 + StorageDead(_1); // scope 0 at $DIR/terminator.rs:+3:1: +3:2 + return; // scope 0 at $DIR/terminator.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/terminator.rs b/src/test/mir-opt/dataflow-const-prop/terminator.rs new file mode 100644 index 0000000000000..e96b25de63ccc --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/terminator.rs @@ -0,0 +1,9 @@ +// unit-test: DataflowConstProp + +fn foo(n: i32) {} + +// EMIT_MIR terminator.main.DataflowConstProp.diff +fn main() { + let a = 1; + foo(a + 1); +} diff --git a/src/test/mir-opt/dataflow-const-prop/unnamed.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/unnamed.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..684c661fc1185 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/unnamed.main.DataflowConstProp.diff @@ -0,0 +1,38 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/unnamed.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/unnamed.rs:+1:9: +1:14 + let mut _2: i32; // in scope 0 at $DIR/unnamed.rs:+3:10: +3:11 + let mut _3: &i32; // in scope 0 at $DIR/unnamed.rs:+3:10: +3:11 + scope 1 { + debug a => _1; // in scope 1 at $DIR/unnamed.rs:+1:9: +1:14 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/unnamed.rs:+1:9: +1:14 + _1 = const 0_i32; // scope 0 at $DIR/unnamed.rs:+1:17: +1:18 +- _1 = Add(_1, const 1_i32); // scope 1 at $DIR/unnamed.rs:+2:5: +2:11 ++ _1 = const 1_i32; // scope 1 at $DIR/unnamed.rs:+2:5: +2:11 + StorageLive(_2); // scope 1 at $DIR/unnamed.rs:+3:10: +3:11 + StorageLive(_3); // scope 1 at $DIR/unnamed.rs:+3:10: +3:11 + _3 = const {alloc1: &i32}; // scope 1 at $DIR/unnamed.rs:+3:10: +3:11 + // mir::Constant + // + span: $DIR/unnamed.rs:9:10: 9:11 + // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } + _2 = (*_3); // scope 1 at $DIR/unnamed.rs:+3:10: +3:11 +- _1 = Add(_1, move _2); // scope 1 at $DIR/unnamed.rs:+3:5: +3:11 ++ _1 = Add(const 1_i32, move _2); // scope 1 at $DIR/unnamed.rs:+3:5: +3:11 + StorageDead(_2); // scope 1 at $DIR/unnamed.rs:+3:10: +3:11 + StorageDead(_3); // scope 1 at $DIR/unnamed.rs:+3:11: +3:12 + _0 = const (); // scope 0 at $DIR/unnamed.rs:+0:11: +4:2 + StorageDead(_1); // scope 0 at $DIR/unnamed.rs:+4:1: +4:2 + return; // scope 0 at $DIR/unnamed.rs:+4:2: +4:2 + } + } + + alloc1 (static: g, size: 4, align: 4) { + 02 00 00 00 │ .... + } + diff --git a/src/test/mir-opt/dataflow-const-prop/unnamed.rs b/src/test/mir-opt/dataflow-const-prop/unnamed.rs new file mode 100644 index 0000000000000..91f5a9e1c12d1 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/unnamed.rs @@ -0,0 +1,10 @@ +// unit-test: DataflowConstProp + +static g: i32 = 2; + +// EMIT_MIR unnamed.main.DataflowConstProp.diff +fn main() { + let mut a = 0; + a += 1; + a += g; +} From d0afe6833d3c81f4b37dc58d1a102068f6f80019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Mon, 29 Aug 2022 22:29:46 +0200 Subject: [PATCH 02/76] Try field type normalization instead of forcing it --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 1dcea430a0f67..71e430acaa4ec 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -589,10 +589,10 @@ fn iter_fields<'tcx>( ty::Adt(def, substs) => { for (v_index, v_def) in def.variants().iter_enumerated() { for (f_index, f_def) in v_def.fields.iter().enumerate() { - let field_ty = tcx.normalize_erasing_regions( - ty::ParamEnv::reveal_all(), - f_def.ty(tcx, substs), - ); + let field_ty = f_def.ty(tcx, substs); + let field_ty = tcx + .try_normalize_erasing_regions(ty::ParamEnv::reveal_all(), field_ty) + .unwrap_or(field_ty); f(Some(v_index), f_index.into(), field_ty); } } From 601fcc41d3671462cbc4db32cc45bc6965a89332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Mon, 29 Aug 2022 23:02:12 +0200 Subject: [PATCH 03/76] Update test results --- .../issue_73223.main.SimplifyArmIdentity.diff | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff index c9a9511586d78..f854d93125a22 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff @@ -1,6 +1,6 @@ - // MIR for `main` before SimplifyArmIdentity + // MIR for `main` after SimplifyArmIdentity - + fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue_73223.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/issue_73223.rs:+1:9: +1:14 @@ -47,7 +47,7 @@ scope 2 { debug v => _4; // in scope 2 at $DIR/issue_73223.rs:+2:14: +2:15 } - + bb0: { StorageLive(_1); // scope 0 at $DIR/issue_73223.rs:+1:9: +1:14 StorageLive(_2); // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 @@ -57,18 +57,18 @@ _3 = const 1_isize; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 goto -> bb3; // scope 0 at $DIR/issue_73223.rs:+1:17: +1:30 } - + bb1: { nop; // scope 0 at $DIR/issue_73223.rs:+3:17: +3:23 StorageDead(_2); // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7 StorageDead(_1); // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2 return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 } - + bb2: { unreachable; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 } - + bb3: { StorageLive(_4); // scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 _4 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 @@ -104,17 +104,21 @@ StorageLive(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _17 = (*_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- _17 = (*_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ _17 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = Eq(move _17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- _16 = Eq(move _17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ _16 = const true; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = Not(move _16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- _15 = Not(move _16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ _15 = const false; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - switchInt(move _15) -> [false: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- switchInt(move _15) -> [false: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ goto -> bb5; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } - + bb4: { StorageLive(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Deinit(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -144,7 +148,7 @@ // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } } - + bb5: { nop; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -158,4 +162,4 @@ return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 } } - + From 56ff16d19f2a34eaf54bf30a2d71e6924ca1bff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Mon, 29 Aug 2022 23:03:30 +0200 Subject: [PATCH 04/76] Fix spelling --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 71e430acaa4ec..15aa605021c81 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -41,7 +41,7 @@ pub trait ValueAnalysis<'tcx> { self.handle_assign(*place, rvalue, state); } StatementKind::SetDiscriminant { .. } => { - // Could tread this as writing a constant to a pseudo-place. + // Could treat this as writing a constant to a pseudo-place. } StatementKind::CopyNonOverlapping(..) => { // FIXME: What to do here? From 93ee80623366622cc4ce019caa7b90ce55eb14e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 30 Aug 2022 00:57:49 +0200 Subject: [PATCH 05/76] Update test results --- .../issue_81605.f.DataflowConstProp.diff | 34 +++++++++++++++++++ .../dataflow-const-prop/issue_81605.rs | 10 ++++++ .../issue_73223.main.SimplifyArmIdentity.diff | 28 +++++++-------- 3 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/issue_81605.rs diff --git a/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff new file mode 100644 index 0000000000000..075cf35a54548 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff @@ -0,0 +1,34 @@ +- // MIR for `f` before DataflowConstProp ++ // MIR for `f` after DataflowConstProp + + fn f() -> usize { + let mut _0: usize; // return place in scope 0 at $DIR/issue_81605.rs:+0:11: +0:16 + let mut _1: usize; // in scope 0 at $DIR/issue_81605.rs:+1:9: +1:33 + let mut _2: bool; // in scope 0 at $DIR/issue_81605.rs:+1:12: +1:16 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/issue_81605.rs:+1:9: +1:33 + StorageLive(_2); // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16 + _2 = const true; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16 +- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16 ++ switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16 + } + + bb1: { + _1 = const 1_usize; // scope 0 at $DIR/issue_81605.rs:+1:19: +1:20 + goto -> bb3; // scope 0 at $DIR/issue_81605.rs:+1:9: +1:33 + } + + bb2: { + _1 = const 2_usize; // scope 0 at $DIR/issue_81605.rs:+1:30: +1:31 + goto -> bb3; // scope 0 at $DIR/issue_81605.rs:+1:9: +1:33 + } + + bb3: { + StorageDead(_2); // scope 0 at $DIR/issue_81605.rs:+1:32: +1:33 + _0 = Add(const 1_usize, move _1); // scope 0 at $DIR/issue_81605.rs:+1:5: +1:33 + StorageDead(_1); // scope 0 at $DIR/issue_81605.rs:+1:32: +1:33 + return; // scope 0 at $DIR/issue_81605.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/issue_81605.rs b/src/test/mir-opt/dataflow-const-prop/issue_81605.rs new file mode 100644 index 0000000000000..d75e2a28bef6b --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/issue_81605.rs @@ -0,0 +1,10 @@ +// unit-test: DataflowConstProp + +// EMIT_MIR issue_81605.f.DataflowConstProp.diff +fn f() -> usize { + 1 + if true { 1 } else { 2 } +} + +fn main() { + f(); +} diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff index f854d93125a22..b305fa16d1b49 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff @@ -1,6 +1,6 @@ - // MIR for `main` before SimplifyArmIdentity + // MIR for `main` after SimplifyArmIdentity - + fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue_73223.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/issue_73223.rs:+1:9: +1:14 @@ -47,7 +47,7 @@ scope 2 { debug v => _4; // in scope 2 at $DIR/issue_73223.rs:+2:14: +2:15 } - + bb0: { StorageLive(_1); // scope 0 at $DIR/issue_73223.rs:+1:9: +1:14 StorageLive(_2); // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 @@ -57,18 +57,18 @@ _3 = const 1_isize; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 goto -> bb3; // scope 0 at $DIR/issue_73223.rs:+1:17: +1:30 } - + bb1: { nop; // scope 0 at $DIR/issue_73223.rs:+3:17: +3:23 StorageDead(_2); // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7 StorageDead(_1); // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2 return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 } - + bb2: { unreachable; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 } - + bb3: { StorageLive(_4); // scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 _4 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 @@ -104,21 +104,17 @@ StorageLive(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- _17 = (*_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ _17 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _17 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- _16 = Eq(move _17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ _16 = const true; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _16 = const true; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- _15 = Not(move _16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ _15 = const false; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _15 = const false; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- switchInt(move _15) -> [false: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ goto -> bb5; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + goto -> bb5; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } - + bb4: { StorageLive(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Deinit(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -148,7 +144,7 @@ // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } } - + bb5: { nop; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -162,4 +158,4 @@ return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 } } - + From c83489c64bac7c99624d8a13a6fa503330f6b9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 31 Aug 2022 00:15:21 +0200 Subject: [PATCH 06/76] Remove empty test --- .../cell.main.DataflowConstProp.diff | 12 ------------ src/test/mir-opt/dataflow-const-prop/cell.rs | 6 ------ 2 files changed, 18 deletions(-) delete mode 100644 src/test/mir-opt/dataflow-const-prop/cell.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/cell.rs diff --git a/src/test/mir-opt/dataflow-const-prop/cell.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/cell.main.DataflowConstProp.diff deleted file mode 100644 index e947f08497068..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/cell.main.DataflowConstProp.diff +++ /dev/null @@ -1,12 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/cell.rs:+0:11: +0:11 - - bb0: { - _0 = const (); // scope 0 at $DIR/cell.rs:+0:11: +2:2 - return; // scope 0 at $DIR/cell.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/cell.rs b/src/test/mir-opt/dataflow-const-prop/cell.rs deleted file mode 100644 index 82a4c3465959b..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/cell.rs +++ /dev/null @@ -1,6 +0,0 @@ -// unit-test: DataflowConstProp - -// EMIT_MIR cell.main.DataflowConstProp.diff -fn main() { - // FIXME: Is it possible to build something with UnsafeCell? -} From bb1639769ec2ef5ff297986f63b2954091c9c95c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 31 Aug 2022 00:56:39 +0200 Subject: [PATCH 07/76] Clarify registration and tracking of references --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 15aa605021c81..662ab0bdfa526 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -7,8 +7,14 @@ //! override some of the `handle_` methods. For an example, see `ConstAnalysis`. //! //! An implementation must also provide a [`Map`]. Before the anaylsis begins, all places that -//! should be tracked during the analysis must be registered. The set of tracked places cannot be -//! changed during the analysis. +//! should be tracked during the analysis must be registered. Currently, the projections of these +//! places may only contain derefs, fields and downcasts (otherwise registration fails). During the +//! analysis, no new places can be registered. +//! +//! Note that if you want to track values behind references, you have to register the dereferenced +//! place. For example: Assume `let x = (0, 0)` and that we want to propagate values from `x.0` and +//! `x.1` also through the assignment `let y = &x`. In this case, we should register `x.0`, `x.1`, +//! `(*y).0` and `(*y).1`. use std::fmt::{Debug, Formatter}; From 292869493ce64e4aa4305eae4f1f2a246d50d0b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 31 Aug 2022 16:01:37 +0200 Subject: [PATCH 08/76] Add additional flooding when assigning a value and corresponding test --- .../rustc_mir_dataflow/src/value_analysis.rs | 4 +- .../static_ref.main.DataflowConstProp.diff | 53 +++++++++++++++++++ .../mir-opt/dataflow-const-prop/static_ref.rs | 10 ++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/static_ref.rs diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 662ab0bdfa526..a4ade54604e02 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -339,7 +339,9 @@ impl State { pub fn assign_idx(&mut self, target: PlaceIndex, result: ValueOrPlace, map: &Map) { match result { ValueOrPlace::Value(value) => { - // FIXME: What if not all tracked projections are overwritten? Can this happen? + // First flood the target place in case we also track any projections (although + // this scenario is currently not well-supported with the ValueOrPlace interface). + self.flood_idx(target, map, V::top()); if let Some(value_index) = map.places[target].value_index { self.0[value_index] = value; } diff --git a/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..4c6c0bd8f3e24 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff @@ -0,0 +1,53 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/static_ref.rs:+0:11: +0:11 + let _1: usize; // in scope 0 at $DIR/static_ref.rs:+2:9: +2:10 + let mut _3: &usize; // in scope 0 at $DIR/static_ref.rs:+4:9: +4:11 + let _4: &usize; // in scope 0 at $DIR/static_ref.rs:+4:9: +4:11 + let _5: &usize; // in scope 0 at $DIR/static_ref.rs:+4:10: +4:11 + scope 1 { + debug x => _1; // in scope 1 at $DIR/static_ref.rs:+2:9: +2:10 + let mut _2: &usize; // in scope 1 at $DIR/static_ref.rs:+3:9: +3:14 + scope 2 { + debug r => _2; // in scope 2 at $DIR/static_ref.rs:+3:9: +3:14 + let _6: usize; // in scope 2 at $DIR/static_ref.rs:+5:9: +5:10 + scope 3 { + debug y => _6; // in scope 3 at $DIR/static_ref.rs:+5:9: +5:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/static_ref.rs:+2:9: +2:10 + _1 = const 0_usize; // scope 0 at $DIR/static_ref.rs:+2:13: +2:14 + StorageLive(_2); // scope 1 at $DIR/static_ref.rs:+3:9: +3:14 + _2 = &_1; // scope 1 at $DIR/static_ref.rs:+3:17: +3:19 + StorageLive(_3); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 + StorageLive(_4); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 + StorageLive(_5); // scope 2 at $DIR/static_ref.rs:+4:10: +4:11 + _5 = const {alloc1: &usize}; // scope 2 at $DIR/static_ref.rs:+4:10: +4:11 + // mir::Constant + // + span: $DIR/static_ref.rs:8:10: 8:11 + // + literal: Const { ty: &usize, val: Value(Scalar(alloc1)) } + _4 = &(*_5); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 + _3 = &(*_4); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 + _2 = move _3; // scope 2 at $DIR/static_ref.rs:+4:5: +4:11 + StorageDead(_3); // scope 2 at $DIR/static_ref.rs:+4:10: +4:11 + StorageDead(_5); // scope 2 at $DIR/static_ref.rs:+4:11: +4:12 + StorageDead(_4); // scope 2 at $DIR/static_ref.rs:+4:11: +4:12 + StorageLive(_6); // scope 2 at $DIR/static_ref.rs:+5:9: +5:10 + _6 = (*_2); // scope 2 at $DIR/static_ref.rs:+5:13: +5:15 + _0 = const (); // scope 0 at $DIR/static_ref.rs:+0:11: +6:2 + StorageDead(_6); // scope 2 at $DIR/static_ref.rs:+6:1: +6:2 + StorageDead(_2); // scope 1 at $DIR/static_ref.rs:+6:1: +6:2 + StorageDead(_1); // scope 0 at $DIR/static_ref.rs:+6:1: +6:2 + return; // scope 0 at $DIR/static_ref.rs:+6:2: +6:2 + } + } + + alloc1 (static: P, size: 8, align: 8) { + 05 00 00 00 00 00 00 00 │ ........ + } + diff --git a/src/test/mir-opt/dataflow-const-prop/static_ref.rs b/src/test/mir-opt/dataflow-const-prop/static_ref.rs new file mode 100644 index 0000000000000..d5e8063cf018c --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/static_ref.rs @@ -0,0 +1,10 @@ +// unit-test: DataflowConstProp + +// EMIT_MIR static_ref.main.DataflowConstProp.diff +fn main() { + static P: usize = 5; + let x = 0; + let mut r = &x; + r = &P; + let y = *r; +} From e75ad93d958c0c3d4dceaa07cceccc253674a4f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 31 Aug 2022 17:43:53 +0200 Subject: [PATCH 09/76] Begin a semi-formal argument for correctness --- .../rustc_mir_dataflow/src/value_analysis.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index a4ade54604e02..8b913d708001b 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -15,6 +15,34 @@ //! place. For example: Assume `let x = (0, 0)` and that we want to propagate values from `x.0` and //! `x.1` also through the assignment `let y = &x`. In this case, we should register `x.0`, `x.1`, //! `(*y).0` and `(*y).1`. +//! +//! +//! # Correctness +//! +//! Warning: This is a semi-formal attempt to argue for the correctness of this analysis. If you +//! find any weak spots, let me know! Recommended reading: Abstract Interpretation. +//! +//! In the following, we will assume a constant propagation analysis. Our analysis is correct if +//! every transfer function is correct. This is the case if for every pair (f, f#) and abstract +//! state s, we have f(y(s)) <= y(f#(s)), where s is a mapping from tracked place to top, bottom or +//! a constant. Since pointers (and mutable references) are not tracked, but can be used to change +//! values in the concrete domain, f# must assume that all places that can be affected in this way +//! for a given program point are marked with top (otherwise many assignments and function calls +//! would have no choice but to mark all tracked places with top). This leads us to an invariant: +//! For all possible program points where there could possibly exist a mutable reference or pointer +//! to a tracked place (in the concrete domain), this place must be assigned to top (in the +//! abstract domain). The concretization function y can be defined as expected for the constant +//! propagation analysis, although the concrete state of course contains all kinds of non-tracked +//! data. However, by the invariant above, no mutable references or pointers to tracked places that +//! are not marked with top may be introduced. +//! +//! Note that we (at least currently) do not differentiate between "this place may assume different +//! values" and "a pointer to this place escaped the analysis". However, we still want to handle +//! assignments to constants as usual for f#. This adds an assumption: Whenever we have an +//! assignment, all mutable access to the underlying place (which is not observed by the analysis) +//! must be invalidated. This is (hopefully) covered by Stacked Borrows. +//! +//! To be continued... use std::fmt::{Debug, Formatter}; From 1da30333406f0de9df70159d423d0196f164d8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 31 Aug 2022 18:28:25 +0200 Subject: [PATCH 10/76] Change test from usize to i32 to prevent target issues --- .../static_ref.main.DataflowConstProp.diff | 22 +++++++++---------- .../mir-opt/dataflow-const-prop/static_ref.rs | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff index 4c6c0bd8f3e24..46386ca34d559 100644 --- a/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff @@ -3,16 +3,16 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/static_ref.rs:+0:11: +0:11 - let _1: usize; // in scope 0 at $DIR/static_ref.rs:+2:9: +2:10 - let mut _3: &usize; // in scope 0 at $DIR/static_ref.rs:+4:9: +4:11 - let _4: &usize; // in scope 0 at $DIR/static_ref.rs:+4:9: +4:11 - let _5: &usize; // in scope 0 at $DIR/static_ref.rs:+4:10: +4:11 + let _1: i32; // in scope 0 at $DIR/static_ref.rs:+2:9: +2:10 + let mut _3: &i32; // in scope 0 at $DIR/static_ref.rs:+4:9: +4:11 + let _4: &i32; // in scope 0 at $DIR/static_ref.rs:+4:9: +4:11 + let _5: &i32; // in scope 0 at $DIR/static_ref.rs:+4:10: +4:11 scope 1 { debug x => _1; // in scope 1 at $DIR/static_ref.rs:+2:9: +2:10 - let mut _2: &usize; // in scope 1 at $DIR/static_ref.rs:+3:9: +3:14 + let mut _2: &i32; // in scope 1 at $DIR/static_ref.rs:+3:9: +3:14 scope 2 { debug r => _2; // in scope 2 at $DIR/static_ref.rs:+3:9: +3:14 - let _6: usize; // in scope 2 at $DIR/static_ref.rs:+5:9: +5:10 + let _6: i32; // in scope 2 at $DIR/static_ref.rs:+5:9: +5:10 scope 3 { debug y => _6; // in scope 3 at $DIR/static_ref.rs:+5:9: +5:10 } @@ -21,16 +21,16 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/static_ref.rs:+2:9: +2:10 - _1 = const 0_usize; // scope 0 at $DIR/static_ref.rs:+2:13: +2:14 + _1 = const 0_i32; // scope 0 at $DIR/static_ref.rs:+2:13: +2:14 StorageLive(_2); // scope 1 at $DIR/static_ref.rs:+3:9: +3:14 _2 = &_1; // scope 1 at $DIR/static_ref.rs:+3:17: +3:19 StorageLive(_3); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 StorageLive(_4); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 StorageLive(_5); // scope 2 at $DIR/static_ref.rs:+4:10: +4:11 - _5 = const {alloc1: &usize}; // scope 2 at $DIR/static_ref.rs:+4:10: +4:11 + _5 = const {alloc1: &i32}; // scope 2 at $DIR/static_ref.rs:+4:10: +4:11 // mir::Constant // + span: $DIR/static_ref.rs:8:10: 8:11 - // + literal: Const { ty: &usize, val: Value(Scalar(alloc1)) } + // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } _4 = &(*_5); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 _3 = &(*_4); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 _2 = move _3; // scope 2 at $DIR/static_ref.rs:+4:5: +4:11 @@ -47,7 +47,7 @@ } } - alloc1 (static: P, size: 8, align: 8) { - 05 00 00 00 00 00 00 00 │ ........ + alloc1 (static: P, size: 4, align: 4) { + 05 00 00 00 │ .... } diff --git a/src/test/mir-opt/dataflow-const-prop/static_ref.rs b/src/test/mir-opt/dataflow-const-prop/static_ref.rs index d5e8063cf018c..5e60ab1805ba6 100644 --- a/src/test/mir-opt/dataflow-const-prop/static_ref.rs +++ b/src/test/mir-opt/dataflow-const-prop/static_ref.rs @@ -2,7 +2,7 @@ // EMIT_MIR static_ref.main.DataflowConstProp.diff fn main() { - static P: usize = 5; + static P: i32 = 5; let x = 0; let mut r = &x; r = &P; From 3f98dc78380a60ffea0e5849393a718a10f495b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Thu, 1 Sep 2022 13:50:31 +0200 Subject: [PATCH 11/76] Clarify place expressions vs place objects --- .../rustc_mir_dataflow/src/value_analysis.rs | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 8b913d708001b..bc367de4baa5f 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -20,27 +20,34 @@ //! # Correctness //! //! Warning: This is a semi-formal attempt to argue for the correctness of this analysis. If you -//! find any weak spots, let me know! Recommended reading: Abstract Interpretation. +//! find any weak spots, let me know! Recommended reading: Abstract Interpretation. We will use the +//! term "place" to refer to a place expression (like `mir::Place`), and we will call the +//! underlying entity "object". For instance, `*_1` and `*_2` are not the same place, but depending +//! on the value of `_1` and `_2`, they could refer to the same object. Also, the same place can +//! refer to different objects during execution. If `_1` is reassigned, then `*_1` may refer to +//! different objects before and after assignment. Additionally, when saying "access to a place", +//! what we really mean is "access to an object denoted by arbitrary projections of that place". //! //! In the following, we will assume a constant propagation analysis. Our analysis is correct if //! every transfer function is correct. This is the case if for every pair (f, f#) and abstract //! state s, we have f(y(s)) <= y(f#(s)), where s is a mapping from tracked place to top, bottom or //! a constant. Since pointers (and mutable references) are not tracked, but can be used to change //! values in the concrete domain, f# must assume that all places that can be affected in this way -//! for a given program point are marked with top (otherwise many assignments and function calls -//! would have no choice but to mark all tracked places with top). This leads us to an invariant: -//! For all possible program points where there could possibly exist a mutable reference or pointer -//! to a tracked place (in the concrete domain), this place must be assigned to top (in the +//! for a given program point are already marked with top in s (otherwise many assignments and +//! function calls would have no choice but to mark all tracked places with top). This leads us to +//! an invariant: For all possible program points where there could possibly exist means of mutable +//! access to a tracked place (in the concrete domain), this place must be assigned to top (in the //! abstract domain). The concretization function y can be defined as expected for the constant //! propagation analysis, although the concrete state of course contains all kinds of non-tracked -//! data. However, by the invariant above, no mutable references or pointers to tracked places that -//! are not marked with top may be introduced. +//! data. However, by the invariant above, no mutable access to tracked places that are not marked +//! with top may be introduced. //! //! Note that we (at least currently) do not differentiate between "this place may assume different //! values" and "a pointer to this place escaped the analysis". However, we still want to handle //! assignments to constants as usual for f#. This adds an assumption: Whenever we have an -//! assignment, all mutable access to the underlying place (which is not observed by the analysis) -//! must be invalidated. This is (hopefully) covered by Stacked Borrows. +//! assignment that is captured by the analysis, all mutable access to the underlying place (which +//! is not observable by the analysis) must be invalidated. This is (hopefully) covered by Stacked +//! Borrows. //! //! To be continued... From ad99d2e15dd9f36a1b84359f8b9bb9ffbaa5ac60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Thu, 1 Sep 2022 14:17:15 +0200 Subject: [PATCH 12/76] Move handling of references and simplify flooding --- .../rustc_mir_dataflow/src/value_analysis.rs | 115 +++++++++++------- .../src/dataflow_const_prop.rs | 34 ++++-- 2 files changed, 92 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index bc367de4baa5f..4d4a1ea553e40 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -115,35 +115,15 @@ pub trait ValueAnalysis<'tcx> { rvalue: &Rvalue<'tcx>, state: &mut State, ) { - match rvalue { - Rvalue::Ref(_, BorrowKind::Shared, place) => { - let target_deref = self - .map() - .find(target.as_ref()) - .and_then(|target| self.map().apply_elem(target, ProjElem::Deref)); - let place = self.map().find(place.as_ref()); - match (target_deref, place) { - (Some(target_deref), Some(place)) => { - state.assign_idx(target_deref, ValueOrPlace::Place(place), self.map()) - } - _ => (), - } - } - Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { - state.flood(place.as_ref(), self.map(), Self::Value::top()); - } - _ => { - let result = self.handle_rvalue(rvalue, state); - state.assign(target.as_ref(), result, self.map()); - } - } + let result = self.handle_rvalue(rvalue, state); + state.assign(target.as_ref(), result, self.map()); } fn handle_rvalue( &self, rvalue: &Rvalue<'tcx>, state: &mut State, - ) -> ValueOrPlace { + ) -> ValueOrPlaceOrRef { self.super_rvalue(rvalue, state) } @@ -151,16 +131,24 @@ pub trait ValueAnalysis<'tcx> { &self, rvalue: &Rvalue<'tcx>, state: &mut State, - ) -> ValueOrPlace { + ) -> ValueOrPlaceOrRef { match rvalue { - Rvalue::Use(operand) => self.handle_operand(operand, state), - Rvalue::CopyForDeref(place) => self.handle_operand(&Operand::Copy(*place), state), - Rvalue::Ref(..) | Rvalue::AddressOf(..) => { - bug!("this rvalue must be handled by handle_assign() or super_assign()") + Rvalue::Use(operand) => self.handle_operand(operand, state).into(), + Rvalue::Ref(_, BorrowKind::Shared, place) => self + .map() + .find(place.as_ref()) + .map(ValueOrPlaceOrRef::Ref) + .unwrap_or(ValueOrPlaceOrRef::Unknown), + Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + state.flood(place.as_ref(), self.map()); + ValueOrPlaceOrRef::Unknown + } + Rvalue::CopyForDeref(place) => { + self.handle_operand(&Operand::Copy(*place), state).into() } _ => { // FIXME: Check that other Rvalues really have no side-effect. - ValueOrPlace::Unknown + ValueOrPlaceOrRef::Unknown } } } @@ -228,7 +216,7 @@ pub trait ValueAnalysis<'tcx> { state: &mut State, ) { return_places.for_each(|place| { - state.flood(place.as_ref(), self.map(), Self::Value::top()); + state.flood(place.as_ref(), self.map()); }) } @@ -270,7 +258,7 @@ impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) { for arg in body.args_iter() { - state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map(), T::Value::top()); + state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map()); } } } @@ -328,17 +316,25 @@ rustc_index::newtype_index!( pub struct State(IndexVec); impl State { - pub fn flood_all(&mut self, value: V) { + pub fn flood_all(&mut self) { + self.flood_all_with(V::top()) + } + + pub fn flood_all_with(&mut self, value: V) { self.0.raw.fill(value); } - pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { + pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { if let Some(root) = map.find(place) { - self.flood_idx(root, map, value); + self.flood_idx_with(root, map, value); } } - pub fn flood_idx(&mut self, place: PlaceIndex, map: &Map, value: V) { + pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map) { + self.flood_with(place, map, V::top()) + } + + pub fn flood_idx_with(&mut self, place: PlaceIndex, map: &Map, value: V) { map.preorder_invoke(place, &mut |place| { if let Some(vi) = map.places[place].value_index { self.0[vi] = value.clone(); @@ -346,6 +342,10 @@ impl State { }); } + pub fn flood_idx(&mut self, place: PlaceIndex, map: &Map) { + self.flood_idx_with(place, map, V::top()) + } + pub fn assign_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map) { if let Some(target_value) = map.places[target].value_index { if let Some(source_value) = map.places[source].value_index { @@ -360,30 +360,40 @@ impl State { if let Some(source_child) = map.projections.get(&(source, projection)) { self.assign_place_idx(target_child, *source_child, map); } else { - self.flood_idx(target_child, map, V::top()); + self.flood_idx(target_child, map); } } } - pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlace, map: &Map) { + pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlaceOrRef, map: &Map) { if let Some(target) = map.find(target) { self.assign_idx(target, result, map); + } else { + // We don't track this place nor any projections, assignment can be ignored. } } - pub fn assign_idx(&mut self, target: PlaceIndex, result: ValueOrPlace, map: &Map) { + pub fn assign_idx(&mut self, target: PlaceIndex, result: ValueOrPlaceOrRef, map: &Map) { match result { - ValueOrPlace::Value(value) => { + ValueOrPlaceOrRef::Value(value) => { // First flood the target place in case we also track any projections (although - // this scenario is currently not well-supported with the ValueOrPlace interface). - self.flood_idx(target, map, V::top()); + // this scenario is currently not well-supported by the API). + self.flood_idx(target, map); if let Some(value_index) = map.places[target].value_index { self.0[value_index] = value; } } - ValueOrPlace::Place(source) => self.assign_place_idx(target, source, map), - ValueOrPlace::Unknown => { - self.flood_idx(target, map, V::top()); + ValueOrPlaceOrRef::Place(source) => self.assign_place_idx(target, source, map), + ValueOrPlaceOrRef::Ref(source) => { + if let Some(value_index) = map.places[target].value_index { + self.0[value_index] = V::top(); + } + if let Some(target_deref) = map.apply_elem(target, ProjElem::Deref) { + self.assign_place_idx(target_deref, source, map); + } + } + ValueOrPlaceOrRef::Unknown => { + self.flood_idx(target, map); } } } @@ -578,6 +588,23 @@ pub enum ValueOrPlace { Unknown, } +pub enum ValueOrPlaceOrRef { + Value(V), + Place(PlaceIndex), + Ref(PlaceIndex), + Unknown, +} + +impl From> for ValueOrPlaceOrRef { + fn from(x: ValueOrPlace) -> Self { + match x { + ValueOrPlace::Value(value) => ValueOrPlaceOrRef::Value(value), + ValueOrPlace::Place(place) => ValueOrPlaceOrRef::Place(place), + ValueOrPlace::Unknown => ValueOrPlaceOrRef::Unknown, + } + } +} + pub trait HasBottom { fn bottom() -> Self; } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index f1220f634acf2..b05b0fdfd43ec 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -3,7 +3,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::visit::{MutVisitor, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; -use rustc_mir_dataflow::value_analysis::{Map, ProjElem, State, ValueAnalysis, ValueOrPlace}; +use rustc_mir_dataflow::value_analysis::{ + Map, ProjElem, State, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef, +}; use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects}; use rustc_span::DUMMY_SP; @@ -59,6 +61,12 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { match rvalue { Rvalue::CheckedBinaryOp(op, box (left, right)) => { let target = self.map().find(target.as_ref()); + if let Some(target) = target { + // We should not track any projections other than + // what is overwritten below, but just in case... + state.flood_idx(target, self.map()); + } + let value_target = target.and_then(|target| { self.map().apply_elem(target, ProjElem::Field(0_u32.into())) }); @@ -70,12 +78,12 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { let (val, overflow) = self.binary_op(state, *op, left, right); if let Some(value_target) = value_target { - state.assign_idx(value_target, ValueOrPlace::Value(val), self.map()); + state.assign_idx(value_target, ValueOrPlaceOrRef::Value(val), self.map()); } if let Some(overflow_target) = overflow_target { state.assign_idx( overflow_target, - ValueOrPlace::Value(overflow), + ValueOrPlaceOrRef::Value(overflow), self.map(), ); } @@ -89,7 +97,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { &self, rvalue: &Rvalue<'tcx>, state: &mut State, - ) -> ValueOrPlace { + ) -> ValueOrPlaceOrRef { match rvalue { Rvalue::Cast(CastKind::Misc, operand, ty) => { let operand = self.eval_operand(operand, state); @@ -97,24 +105,24 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { FlatSet::Elem(operand) => self .ecx .misc_cast(&operand, *ty) - .map(|result| ValueOrPlace::Value(self.wrap_immediate(result, *ty))) - .unwrap_or(ValueOrPlace::Unknown), - _ => ValueOrPlace::Unknown, + .map(|result| ValueOrPlaceOrRef::Value(self.wrap_immediate(result, *ty))) + .unwrap_or(ValueOrPlaceOrRef::Unknown), + _ => ValueOrPlaceOrRef::Unknown, } } Rvalue::BinaryOp(op, box (left, right)) => { let (val, _overflow) = self.binary_op(state, *op, left, right); // FIXME: Just ignore overflow here? - ValueOrPlace::Value(val) + ValueOrPlaceOrRef::Value(val) } Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) { FlatSet::Elem(value) => self .ecx .unary_op(*op, &value) - .map(|val| ValueOrPlace::Value(self.wrap_immty(val))) - .unwrap_or(ValueOrPlace::Value(FlatSet::Top)), - FlatSet::Bottom => ValueOrPlace::Value(FlatSet::Bottom), - FlatSet::Top => ValueOrPlace::Value(FlatSet::Top), + .map(|val| ValueOrPlaceOrRef::Value(self.wrap_immty(val))) + .unwrap_or(ValueOrPlaceOrRef::Value(FlatSet::Top)), + FlatSet::Bottom => ValueOrPlaceOrRef::Value(FlatSet::Bottom), + FlatSet::Top => ValueOrPlaceOrRef::Value(FlatSet::Top), }, _ => self.super_rvalue(rvalue, state), } @@ -175,7 +183,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { handled = true; } else { // Branch is not taken, we can flood everything. - state.flood_all(FlatSet::Bottom); + state.flood_all(); } }) } From 47a00d53379da5f226ec1c69d742f1bde3f29523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Thu, 1 Sep 2022 14:22:37 +0200 Subject: [PATCH 13/76] Flood with bottom instead of top for unreachable branches --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index b05b0fdfd43ec..f461514716e60 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -182,8 +182,8 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { // Branch is taken. Has no effect on state. handled = true; } else { - // Branch is not taken, we can flood everything. - state.flood_all(); + // Branch is not taken, we can flood everything with bottom. + state.flood_all_with(FlatSet::Bottom); } }) } From 8a789ce0090a5e959ef45f0ac962b165a9b1ab28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Thu, 1 Sep 2022 15:05:53 +0200 Subject: [PATCH 14/76] Reject registration of downcasts for now --- .../rustc_mir_dataflow/src/value_analysis.rs | 9 +- .../recursive.main.DataflowConstProp.diff | 169 +++++++++--------- .../mir-opt/dataflow-const-prop/recursive.rs | 1 + 3 files changed, 92 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 4d4a1ea553e40..64e45083fc07b 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -462,8 +462,8 @@ impl Map { filter: &mut impl FnMut(Ty<'tcx>) -> bool, ) { if filter(ty) { - self.register(local, projection) - .expect("projection should only contain convertible elements"); + // Since downcasts are currently not allowed, this might fail. + let _ = self.register(local, projection); } if max_derefs > 0 { if let Some(ty::TypeAndMut { ty, .. }) = ty.builtin_deref(false) { @@ -496,6 +496,11 @@ impl Map { // Apply the projection. for &elem in projection { + // For now, downcast is not allowed (see #101168). + match elem { + PlaceElem::Downcast(..) => return Err(()), + _ => (), + } let elem = elem.try_into()?; index = *self.projections.entry((index, elem)).or_insert_with(|| { // Prepend new child to the linked list. diff --git a/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff index 953628cff06f9..f7c557c3edf3f 100644 --- a/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff @@ -3,40 +3,40 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/recursive.rs:+0:11: +0:11 - let _1: S; // in scope 0 at $DIR/recursive.rs:+1:9: +1:10 - let mut _3: &S; // in scope 0 at $DIR/recursive.rs:+2:20: +2:22 - let _4: &S; // in scope 0 at $DIR/recursive.rs:+2:20: +2:22 - let mut _6: &S; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 - let _7: &S; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 - let mut _9: isize; // in scope 0 at $DIR/recursive.rs:+5:9: +5:18 - let mut _11: isize; // in scope 0 at $DIR/recursive.rs:+6:13: +6:22 - let mut _13: isize; // in scope 0 at $DIR/recursive.rs:+7:17: +7:28 - let mut _15: !; // in scope 0 at $DIR/recursive.rs:+8:22: +8:43 - let mut _16: !; // in scope 0 at $DIR/recursive.rs:+10:18: +10:39 - let mut _17: !; // in scope 0 at $DIR/recursive.rs:+12:14: +12:35 - let mut _18: &S; // in scope 0 at $DIR/recursive.rs:+6:20: +6:21 - let mut _19: &S; // in scope 0 at $DIR/recursive.rs:+6:20: +6:21 + let _1: S; // in scope 0 at $DIR/recursive.rs:+2:9: +2:10 + let mut _3: &S; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 + let _4: &S; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 + let mut _6: &S; // in scope 0 at $DIR/recursive.rs:+4:20: +4:22 + let _7: &S; // in scope 0 at $DIR/recursive.rs:+4:20: +4:22 + let mut _9: isize; // in scope 0 at $DIR/recursive.rs:+6:9: +6:18 + let mut _11: isize; // in scope 0 at $DIR/recursive.rs:+7:13: +7:22 + let mut _13: isize; // in scope 0 at $DIR/recursive.rs:+8:17: +8:28 + let mut _15: !; // in scope 0 at $DIR/recursive.rs:+9:22: +9:43 + let mut _16: !; // in scope 0 at $DIR/recursive.rs:+11:18: +11:39 + let mut _17: !; // in scope 0 at $DIR/recursive.rs:+13:14: +13:35 + let mut _18: &S; // in scope 0 at $DIR/recursive.rs:+7:20: +7:21 + let mut _19: &S; // in scope 0 at $DIR/recursive.rs:+7:20: +7:21 scope 1 { - debug a => _1; // in scope 1 at $DIR/recursive.rs:+1:9: +1:10 - let _2: S; // in scope 1 at $DIR/recursive.rs:+2:9: +2:10 + debug a => _1; // in scope 1 at $DIR/recursive.rs:+2:9: +2:10 + let _2: S; // in scope 1 at $DIR/recursive.rs:+3:9: +3:10 scope 2 { - debug b => _2; // in scope 2 at $DIR/recursive.rs:+2:9: +2:10 - let _5: S; // in scope 2 at $DIR/recursive.rs:+3:9: +3:10 + debug b => _2; // in scope 2 at $DIR/recursive.rs:+3:9: +3:10 + let _5: S; // in scope 2 at $DIR/recursive.rs:+4:9: +4:10 scope 3 { - debug c => _5; // in scope 3 at $DIR/recursive.rs:+3:9: +3:10 - let _8: u32; // in scope 3 at $DIR/recursive.rs:+4:9: +4:10 - let _10: &S; // in scope 3 at $DIR/recursive.rs:+5:16: +5:17 + debug c => _5; // in scope 3 at $DIR/recursive.rs:+4:9: +4:10 + let _8: u32; // in scope 3 at $DIR/recursive.rs:+5:9: +5:10 + let _10: &S; // in scope 3 at $DIR/recursive.rs:+6:16: +6:17 scope 4 { - debug d => _8; // in scope 4 at $DIR/recursive.rs:+4:9: +4:10 + debug d => _8; // in scope 4 at $DIR/recursive.rs:+5:9: +5:10 } scope 5 { - debug b => _10; // in scope 5 at $DIR/recursive.rs:+5:16: +5:17 - let _12: &&S; // in scope 5 at $DIR/recursive.rs:+6:20: +6:21 + debug b => _10; // in scope 5 at $DIR/recursive.rs:+6:16: +6:17 + let _12: &&S; // in scope 5 at $DIR/recursive.rs:+7:20: +7:21 scope 6 { - debug a => _12; // in scope 6 at $DIR/recursive.rs:+6:20: +6:21 - let _14: &u32; // in scope 6 at $DIR/recursive.rs:+7:24: +7:27 + debug a => _12; // in scope 6 at $DIR/recursive.rs:+7:20: +7:21 + let _14: &u32; // in scope 6 at $DIR/recursive.rs:+8:24: +8:27 scope 7 { - debug num => _14; // in scope 7 at $DIR/recursive.rs:+7:24: +7:27 + debug num => _14; // in scope 7 at $DIR/recursive.rs:+8:24: +8:27 } } } @@ -45,89 +45,88 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/recursive.rs:+1:9: +1:10 - Deinit(_1); // scope 0 at $DIR/recursive.rs:+1:13: +1:22 - ((_1 as Num).0: u32) = const 0_u32; // scope 0 at $DIR/recursive.rs:+1:13: +1:22 - discriminant(_1) = 1; // scope 0 at $DIR/recursive.rs:+1:13: +1:22 - StorageLive(_2); // scope 1 at $DIR/recursive.rs:+2:9: +2:10 - StorageLive(_3); // scope 1 at $DIR/recursive.rs:+2:20: +2:22 - StorageLive(_4); // scope 1 at $DIR/recursive.rs:+2:20: +2:22 - _4 = &_1; // scope 1 at $DIR/recursive.rs:+2:20: +2:22 - _3 = &(*_4); // scope 1 at $DIR/recursive.rs:+2:20: +2:22 - Deinit(_2); // scope 1 at $DIR/recursive.rs:+2:13: +2:23 - ((_2 as Rec).0: &S) = move _3; // scope 1 at $DIR/recursive.rs:+2:13: +2:23 - discriminant(_2) = 0; // scope 1 at $DIR/recursive.rs:+2:13: +2:23 - StorageDead(_3); // scope 1 at $DIR/recursive.rs:+2:22: +2:23 - StorageDead(_4); // scope 1 at $DIR/recursive.rs:+2:23: +2:24 - StorageLive(_5); // scope 2 at $DIR/recursive.rs:+3:9: +3:10 - StorageLive(_6); // scope 2 at $DIR/recursive.rs:+3:20: +3:22 - StorageLive(_7); // scope 2 at $DIR/recursive.rs:+3:20: +3:22 - _7 = &_2; // scope 2 at $DIR/recursive.rs:+3:20: +3:22 - _6 = &(*_7); // scope 2 at $DIR/recursive.rs:+3:20: +3:22 - Deinit(_5); // scope 2 at $DIR/recursive.rs:+3:13: +3:23 - ((_5 as Rec).0: &S) = move _6; // scope 2 at $DIR/recursive.rs:+3:13: +3:23 - discriminant(_5) = 0; // scope 2 at $DIR/recursive.rs:+3:13: +3:23 - StorageDead(_6); // scope 2 at $DIR/recursive.rs:+3:22: +3:23 - StorageDead(_7); // scope 2 at $DIR/recursive.rs:+3:23: +3:24 - StorageLive(_8); // scope 3 at $DIR/recursive.rs:+4:9: +4:10 - _9 = discriminant(_5); // scope 3 at $DIR/recursive.rs:+4:19: +4:20 - switchInt(move _9) -> [0_isize: bb2, otherwise: bb1]; // scope 3 at $DIR/recursive.rs:+4:13: +4:20 + StorageLive(_1); // scope 0 at $DIR/recursive.rs:+2:9: +2:10 + Deinit(_1); // scope 0 at $DIR/recursive.rs:+2:13: +2:22 + ((_1 as Num).0: u32) = const 0_u32; // scope 0 at $DIR/recursive.rs:+2:13: +2:22 + discriminant(_1) = 1; // scope 0 at $DIR/recursive.rs:+2:13: +2:22 + StorageLive(_2); // scope 1 at $DIR/recursive.rs:+3:9: +3:10 + StorageLive(_3); // scope 1 at $DIR/recursive.rs:+3:20: +3:22 + StorageLive(_4); // scope 1 at $DIR/recursive.rs:+3:20: +3:22 + _4 = &_1; // scope 1 at $DIR/recursive.rs:+3:20: +3:22 + _3 = &(*_4); // scope 1 at $DIR/recursive.rs:+3:20: +3:22 + Deinit(_2); // scope 1 at $DIR/recursive.rs:+3:13: +3:23 + ((_2 as Rec).0: &S) = move _3; // scope 1 at $DIR/recursive.rs:+3:13: +3:23 + discriminant(_2) = 0; // scope 1 at $DIR/recursive.rs:+3:13: +3:23 + StorageDead(_3); // scope 1 at $DIR/recursive.rs:+3:22: +3:23 + StorageDead(_4); // scope 1 at $DIR/recursive.rs:+3:23: +3:24 + StorageLive(_5); // scope 2 at $DIR/recursive.rs:+4:9: +4:10 + StorageLive(_6); // scope 2 at $DIR/recursive.rs:+4:20: +4:22 + StorageLive(_7); // scope 2 at $DIR/recursive.rs:+4:20: +4:22 + _7 = &_2; // scope 2 at $DIR/recursive.rs:+4:20: +4:22 + _6 = &(*_7); // scope 2 at $DIR/recursive.rs:+4:20: +4:22 + Deinit(_5); // scope 2 at $DIR/recursive.rs:+4:13: +4:23 + ((_5 as Rec).0: &S) = move _6; // scope 2 at $DIR/recursive.rs:+4:13: +4:23 + discriminant(_5) = 0; // scope 2 at $DIR/recursive.rs:+4:13: +4:23 + StorageDead(_6); // scope 2 at $DIR/recursive.rs:+4:22: +4:23 + StorageDead(_7); // scope 2 at $DIR/recursive.rs:+4:23: +4:24 + StorageLive(_8); // scope 3 at $DIR/recursive.rs:+5:9: +5:10 + _9 = discriminant(_5); // scope 3 at $DIR/recursive.rs:+5:19: +5:20 + switchInt(move _9) -> [0_isize: bb2, otherwise: bb1]; // scope 3 at $DIR/recursive.rs:+5:13: +5:20 } bb1: { - StorageLive(_17); // scope 3 at $DIR/recursive.rs:+12:14: +12:35 - _17 = exit(const 0_i32); // scope 3 at $DIR/recursive.rs:+12:14: +12:35 + StorageLive(_17); // scope 3 at $DIR/recursive.rs:+13:14: +13:35 + _17 = exit(const 0_i32); // scope 3 at $DIR/recursive.rs:+13:14: +13:35 // mir::Constant - // + span: $DIR/recursive.rs:21:14: 21:32 + // + span: $DIR/recursive.rs:22:14: 22:32 // + literal: Const { ty: fn(i32) -> ! {exit}, val: Value() } } bb2: { - StorageLive(_10); // scope 3 at $DIR/recursive.rs:+5:16: +5:17 - _10 = ((_5 as Rec).0: &S); // scope 3 at $DIR/recursive.rs:+5:16: +5:17 - _11 = discriminant((*_10)); // scope 5 at $DIR/recursive.rs:+5:28: +5:29 - switchInt(move _11) -> [0_isize: bb4, otherwise: bb3]; // scope 5 at $DIR/recursive.rs:+5:22: +5:29 + StorageLive(_10); // scope 3 at $DIR/recursive.rs:+6:16: +6:17 + _10 = ((_5 as Rec).0: &S); // scope 3 at $DIR/recursive.rs:+6:16: +6:17 + _11 = discriminant((*_10)); // scope 5 at $DIR/recursive.rs:+6:28: +6:29 + switchInt(move _11) -> [0_isize: bb4, otherwise: bb3]; // scope 5 at $DIR/recursive.rs:+6:22: +6:29 } bb3: { - StorageLive(_16); // scope 5 at $DIR/recursive.rs:+10:18: +10:39 - _16 = exit(const 0_i32); // scope 5 at $DIR/recursive.rs:+10:18: +10:39 + StorageLive(_16); // scope 5 at $DIR/recursive.rs:+11:18: +11:39 + _16 = exit(const 0_i32); // scope 5 at $DIR/recursive.rs:+11:18: +11:39 // mir::Constant - // + span: $DIR/recursive.rs:19:18: 19:36 + // + span: $DIR/recursive.rs:20:18: 20:36 // + literal: Const { ty: fn(i32) -> ! {exit}, val: Value() } } bb4: { - StorageLive(_12); // scope 5 at $DIR/recursive.rs:+6:20: +6:21 - _12 = &(((*_10) as Rec).0: &S); // scope 5 at $DIR/recursive.rs:+6:20: +6:21 - _18 = deref_copy (*_12); // scope 6 at $DIR/recursive.rs:+6:32: +6:33 - _13 = discriminant((*_18)); // scope 6 at $DIR/recursive.rs:+6:32: +6:33 - switchInt(move _13) -> [1_isize: bb6, otherwise: bb5]; // scope 6 at $DIR/recursive.rs:+6:26: +6:33 + StorageLive(_12); // scope 5 at $DIR/recursive.rs:+7:20: +7:21 + _12 = &(((*_10) as Rec).0: &S); // scope 5 at $DIR/recursive.rs:+7:20: +7:21 + _18 = deref_copy (*_12); // scope 6 at $DIR/recursive.rs:+7:32: +7:33 + _13 = discriminant((*_18)); // scope 6 at $DIR/recursive.rs:+7:32: +7:33 + switchInt(move _13) -> [1_isize: bb6, otherwise: bb5]; // scope 6 at $DIR/recursive.rs:+7:26: +7:33 } bb5: { - StorageLive(_15); // scope 6 at $DIR/recursive.rs:+8:22: +8:43 - _15 = exit(const 0_i32); // scope 6 at $DIR/recursive.rs:+8:22: +8:43 + StorageLive(_15); // scope 6 at $DIR/recursive.rs:+9:22: +9:43 + _15 = exit(const 0_i32); // scope 6 at $DIR/recursive.rs:+9:22: +9:43 // mir::Constant - // + span: $DIR/recursive.rs:17:22: 17:40 + // + span: $DIR/recursive.rs:18:22: 18:40 // + literal: Const { ty: fn(i32) -> ! {exit}, val: Value() } } bb6: { - StorageLive(_14); // scope 6 at $DIR/recursive.rs:+7:24: +7:27 - _19 = deref_copy (*_12); // scope 6 at $DIR/recursive.rs:+7:24: +7:27 - _14 = &(((*_19) as Num).0: u32); // scope 6 at $DIR/recursive.rs:+7:24: +7:27 -- _8 = (*_14); // scope 7 at $DIR/recursive.rs:+7:32: +7:36 -+ _8 = const 0_u32; // scope 7 at $DIR/recursive.rs:+7:32: +7:36 - StorageDead(_14); // scope 6 at $DIR/recursive.rs:+7:35: +7:36 - StorageDead(_12); // scope 5 at $DIR/recursive.rs:+9:13: +9:14 - StorageDead(_10); // scope 3 at $DIR/recursive.rs:+11:9: +11:10 - _0 = const (); // scope 0 at $DIR/recursive.rs:+0:11: +14:2 - StorageDead(_8); // scope 3 at $DIR/recursive.rs:+14:1: +14:2 - StorageDead(_5); // scope 2 at $DIR/recursive.rs:+14:1: +14:2 - StorageDead(_2); // scope 1 at $DIR/recursive.rs:+14:1: +14:2 - StorageDead(_1); // scope 0 at $DIR/recursive.rs:+14:1: +14:2 - return; // scope 0 at $DIR/recursive.rs:+14:2: +14:2 + StorageLive(_14); // scope 6 at $DIR/recursive.rs:+8:24: +8:27 + _19 = deref_copy (*_12); // scope 6 at $DIR/recursive.rs:+8:24: +8:27 + _14 = &(((*_19) as Num).0: u32); // scope 6 at $DIR/recursive.rs:+8:24: +8:27 + _8 = (*_14); // scope 7 at $DIR/recursive.rs:+8:32: +8:36 + StorageDead(_14); // scope 6 at $DIR/recursive.rs:+8:35: +8:36 + StorageDead(_12); // scope 5 at $DIR/recursive.rs:+10:13: +10:14 + StorageDead(_10); // scope 3 at $DIR/recursive.rs:+12:9: +12:10 + _0 = const (); // scope 0 at $DIR/recursive.rs:+0:11: +15:2 + StorageDead(_8); // scope 3 at $DIR/recursive.rs:+15:1: +15:2 + StorageDead(_5); // scope 2 at $DIR/recursive.rs:+15:1: +15:2 + StorageDead(_2); // scope 1 at $DIR/recursive.rs:+15:1: +15:2 + StorageDead(_1); // scope 0 at $DIR/recursive.rs:+15:1: +15:2 + return; // scope 0 at $DIR/recursive.rs:+15:2: +15:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/recursive.rs b/src/test/mir-opt/dataflow-const-prop/recursive.rs index 0eda1239ecd05..d7ca182b9fcfa 100644 --- a/src/test/mir-opt/dataflow-const-prop/recursive.rs +++ b/src/test/mir-opt/dataflow-const-prop/recursive.rs @@ -7,6 +7,7 @@ enum S<'a> { // EMIT_MIR recursive.main.DataflowConstProp.diff fn main() { + // FIXME: This currently does not work, because downcasts are rejected. let a = S::Num(0); let b = S::Rec(&a); let c = S::Rec(&b); From 469fb197d06de9c6b06cb5b74eb8aff6ad85a332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Thu, 1 Sep 2022 15:25:24 +0200 Subject: [PATCH 15/76] Update other test results --- .../issue_73223.main.PreCodegen.32bit.diff | 117 ++++++++++++++++++ .../issue_73223.main.PreCodegen.64bit.diff | 117 ++++++++++++++++++ .../issue_73223.main.SimplifyArmIdentity.diff | 8 +- 3 files changed, 238 insertions(+), 4 deletions(-) create mode 100644 src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff create mode 100644 src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff new file mode 100644 index 0000000000000..be8e86a832cb6 --- /dev/null +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff @@ -0,0 +1,117 @@ +- // MIR for `main` before PreCodegen ++ // MIR for `main` after PreCodegen + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 + let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + let _3: i32; // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 + let mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _6: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _12: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _14: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _19: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + scope 1 { + debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14 + let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 + scope 3 { + debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14 + let _8: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + scope 4 { + debug left_val => _8; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug right_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _13: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + scope 5 { + debug kind => _13; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + } + } + } + } + scope 2 { + debug v => _3; // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 + StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + Deinit(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 + _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 + _1 = _3; // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21 + StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21 + StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7 + StorageLive(_4); // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 + StorageLive(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _6 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } + _7 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Deinit(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_5.0: &i32) = move _6; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_5.1: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _8 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _9 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _12 = (*_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _11 = Eq(move _12, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _10 = Not(move _11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + switchInt(move _10) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + } + + bb1: { + StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _16 = _8; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _18 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Deinit(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _14 = core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } + } + + bb2: { + StorageDead(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2 + StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2 + return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2 + } + } + diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff new file mode 100644 index 0000000000000..be8e86a832cb6 --- /dev/null +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff @@ -0,0 +1,117 @@ +- // MIR for `main` before PreCodegen ++ // MIR for `main` after PreCodegen + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 + let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + let _3: i32; // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 + let mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _6: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _12: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _14: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _19: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + scope 1 { + debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14 + let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 + scope 3 { + debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14 + let _8: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + scope 4 { + debug left_val => _8; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug right_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _13: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + scope 5 { + debug kind => _13; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + } + } + } + } + scope 2 { + debug v => _3; // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 + StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + Deinit(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 + StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 + _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 + _1 = _3; // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21 + StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21 + StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7 + StorageLive(_4); // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 + StorageLive(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _6 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } + _7 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Deinit(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_5.0: &i32) = move _6; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_5.1: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _8 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _9 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _12 = (*_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _11 = Eq(move _12, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _10 = Not(move _11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + switchInt(move _10) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + } + + bb1: { + StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _16 = _8; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _18 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Deinit(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _14 = core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } + } + + bb2: { + StorageDead(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2 + StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2 + return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2 + } + } + diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff index b305fa16d1b49..c9a9511586d78 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff @@ -104,15 +104,15 @@ StorageLive(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _17 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _17 = (*_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = const true; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _16 = Eq(move _17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = const false; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _15 = Not(move _16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - goto -> bb5; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + switchInt(move _15) -> [false: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } bb4: { From 16dedba1c80e96e7b0481191d4ae16e2d8cb0016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 2 Sep 2022 00:37:38 +0200 Subject: [PATCH 16/76] Ignore terminators explicitly --- .../rustc_mir_dataflow/src/value_analysis.rs | 20 ++++++++++++++----- .../src/dataflow_const_prop.rs | 1 - 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 64e45083fc07b..5fe768f83106a 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -146,10 +146,7 @@ pub trait ValueAnalysis<'tcx> { Rvalue::CopyForDeref(place) => { self.handle_operand(&Operand::Copy(*place), state).into() } - _ => { - // FIXME: Check that other Rvalues really have no side-effect. - ValueOrPlaceOrRef::Unknown - } + _ => ValueOrPlaceOrRef::Unknown, } } @@ -200,7 +197,20 @@ pub trait ValueAnalysis<'tcx> { self.super_terminator(terminator, state) } - fn super_terminator(&self, _terminator: &Terminator<'tcx>, _state: &mut State) {} + fn super_terminator(&self, terminator: &Terminator<'tcx>, _state: &mut State) { + match &terminator.kind { + TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => { + // Effect is applied by `handle_call_return`. + } + TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } => { + // They would have an effect, but are not allowed in this phase. + bug!("encountered disallowed terminator"); + } + _ => { + // The other terminators can be ignored. + } + } + } fn handle_call_return( &self, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index f461514716e60..c80ff3dd3ec72 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -35,7 +35,6 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp { } } -// FIXME: Consider support for discriminants, mutable references, arrays and slices. struct ConstAnalysis<'tcx> { map: Map, tcx: TyCtxt<'tcx>, From fe84bbf844cec89db7726f835517151e08ff2597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 2 Sep 2022 14:41:27 +0200 Subject: [PATCH 17/76] Add tracking of unreachability --- .../rustc_mir_dataflow/src/value_analysis.rs | 98 ++++++++++++++----- .../src/dataflow_const_prop.rs | 5 +- .../if.main.DataflowConstProp.diff | 6 +- .../issue_81605.f.DataflowConstProp.diff | 3 +- 4 files changed, 82 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 5fe768f83106a..40d8aaea94dc9 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -263,10 +263,13 @@ impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper const NAME: &'static str = T::NAME; fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain { - State(IndexVec::from_elem_n(T::Value::bottom(), self.0.map().value_count)) + State(StateData::Unreachable) } fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) { + assert!(matches!(state.0, StateData::Unreachable)); + let values = IndexVec::from_elem_n(T::Value::bottom(), self.0.map().value_count); + *state = State(StateData::Reachable(values)); for arg in body.args_iter() { state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map()); } @@ -283,7 +286,9 @@ where statement: &Statement<'tcx>, _location: Location, ) { - self.0.handle_statement(statement, state); + if state.is_reachable() { + self.0.handle_statement(statement, state); + } } fn apply_terminator_effect( @@ -292,7 +297,9 @@ where terminator: &Terminator<'tcx>, _location: Location, ) { - self.0.handle_terminator(terminator, state); + if state.is_reachable() { + self.0.handle_terminator(terminator, state); + } } fn apply_call_return_effect( @@ -301,7 +308,9 @@ where _block: BasicBlock, return_places: crate::CallReturnPlaces<'_, 'tcx>, ) { - self.0.handle_call_return(return_places, state) + if state.is_reachable() { + self.0.handle_call_return(return_places, state) + } } fn apply_switch_int_edge_effects( @@ -310,6 +319,7 @@ where discr: &Operand<'tcx>, apply_edge_effects: &mut impl SwitchIntEdgeEffects, ) { + // FIXME: Dataflow framework provides no access to current state here. self.0.handle_switch_int(discr, apply_edge_effects) } } @@ -323,15 +333,31 @@ rustc_index::newtype_index!( ); #[derive(PartialEq, Eq, Clone, Debug)] -pub struct State(IndexVec); +enum StateData { + Reachable(IndexVec), + Unreachable, +} + +/// All operations on unreachable states are ignored. +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct State(StateData); impl State { + pub fn is_reachable(&self) -> bool { + matches!(&self.0, StateData::Reachable(_)) + } + + pub fn mark_unreachable(&mut self) { + self.0 = StateData::Unreachable; + } + pub fn flood_all(&mut self) { self.flood_all_with(V::top()) } pub fn flood_all_with(&mut self, value: V) { - self.0.raw.fill(value); + let StateData::Reachable(values) = &mut self.0 else { return }; + values.raw.fill(value); } pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { @@ -345,9 +371,10 @@ impl State { } pub fn flood_idx_with(&mut self, place: PlaceIndex, map: &Map, value: V) { + let StateData::Reachable(values) = &mut self.0 else { return }; map.preorder_invoke(place, &mut |place| { if let Some(vi) = map.places[place].value_index { - self.0[vi] = value.clone(); + values[vi] = value.clone(); } }); } @@ -357,11 +384,12 @@ impl State { } pub fn assign_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map) { + let StateData::Reachable(values) = &mut self.0 else { return }; if let Some(target_value) = map.places[target].value_index { if let Some(source_value) = map.places[source].value_index { - self.0[target_value] = self.0[source_value].clone(); + values[target_value] = values[source_value].clone(); } else { - self.0[target_value] = V::top(); + values[target_value] = V::top(); } } for target_child in map.children(target) { @@ -389,14 +417,16 @@ impl State { // First flood the target place in case we also track any projections (although // this scenario is currently not well-supported by the API). self.flood_idx(target, map); + let StateData::Reachable(values) = &mut self.0 else { return }; if let Some(value_index) = map.places[target].value_index { - self.0[value_index] = value; + values[value_index] = value; } } ValueOrPlaceOrRef::Place(source) => self.assign_place_idx(target, source, map), ValueOrPlaceOrRef::Ref(source) => { + let StateData::Reachable(values) = &mut self.0 else { return }; if let Some(value_index) = map.places[target].value_index { - self.0[value_index] = V::top(); + values[value_index] = V::top(); } if let Some(target_deref) = map.apply_elem(target, ProjElem::Deref) { self.assign_place_idx(target_deref, source, map); @@ -413,13 +443,25 @@ impl State { } pub fn get_idx(&self, place: PlaceIndex, map: &Map) -> V { - map.places[place].value_index.map(|v| self.0[v].clone()).unwrap_or(V::top()) + match &self.0 { + StateData::Reachable(values) => { + map.places[place].value_index.map(|v| values[v].clone()).unwrap_or(V::top()) + } + StateData::Unreachable => V::top(), + } } } -impl JoinSemiLattice for State { +impl JoinSemiLattice for State { fn join(&mut self, other: &Self) -> bool { - self.0.join(&other.0) + match (&mut self.0, &other.0) { + (_, StateData::Unreachable) => false, + (StateData::Unreachable, _) => { + *self = other.clone(); + true + } + (StateData::Reachable(this), StateData::Reachable(other)) => this.join(other), + } } } @@ -692,18 +734,18 @@ fn iter_fields<'tcx>( fn debug_with_context_rec( place: PlaceIndex, place_str: &str, - new: &State, - old: Option<&State>, + new: &IndexVec, + old: Option<&IndexVec>, map: &Map, f: &mut Formatter<'_>, ) -> std::fmt::Result { if let Some(value) = map.places[place].value_index { match old { - None => writeln!(f, "{}: {:?}", place_str, new.0[value])?, + None => writeln!(f, "{}: {:?}", place_str, new[value])?, Some(old) => { - if new.0[value] != old.0[value] { - writeln!(f, "\u{001f}-{}: {:?}", place_str, old.0[value])?; - writeln!(f, "\u{001f}+{}: {:?}", place_str, new.0[value])?; + if new[value] != old[value] { + writeln!(f, "\u{001f}-{}: {:?}", place_str, old[value])?; + writeln!(f, "\u{001f}+{}: {:?}", place_str, new[value])?; } } } @@ -729,8 +771,8 @@ fn debug_with_context_rec( } fn debug_with_context( - new: &State, - old: Option<&State>, + new: &IndexVec, + old: Option<&IndexVec>, map: &Map, f: &mut Formatter<'_>, ) -> std::fmt::Result { @@ -748,7 +790,10 @@ where T::Value: Debug, { fn fmt_with(&self, ctxt: &ValueAnalysisWrapper, f: &mut Formatter<'_>) -> std::fmt::Result { - debug_with_context(self, None, ctxt.0.map(), f) + match &self.0 { + StateData::Reachable(values) => debug_with_context(values, None, ctxt.0.map(), f), + StateData::Unreachable => write!(f, "unreachable"), + } } fn fmt_diff_with( @@ -757,6 +802,11 @@ where ctxt: &ValueAnalysisWrapper, f: &mut Formatter<'_>, ) -> std::fmt::Result { - debug_with_context(self, Some(old), ctxt.0.map(), f) + match (&self.0, &old.0) { + (StateData::Reachable(this), StateData::Reachable(old)) => { + debug_with_context(this, Some(old), ctxt.0.map(), f) + } + _ => Ok(()), // Consider printing something here. + } } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index c80ff3dd3ec72..1cc4201a94982 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -148,7 +148,6 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { ) { // FIXME: The dataflow framework only provides the state if we call `apply()`, which makes // this more inefficient than it has to be. - // FIXME: Perhaps we rather need a proper unreachability flag for every block. let mut discr_value = None; let mut handled = false; apply_edge_effects.apply(|state, target| { @@ -181,8 +180,8 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { // Branch is taken. Has no effect on state. handled = true; } else { - // Branch is not taken, we can flood everything with bottom. - state.flood_all_with(FlatSet::Bottom); + // Branch is not taken. + state.mark_unreachable(); } }) } diff --git a/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff index 951e5c5b9ad4e..b2c2ba6fa5c63 100644 --- a/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff @@ -65,8 +65,10 @@ StorageDead(_3); // scope 1 at $DIR/if.rs:+3:40: +3:41 StorageLive(_6); // scope 2 at $DIR/if.rs:+4:9: +4:10 StorageLive(_7); // scope 2 at $DIR/if.rs:+4:13: +4:14 - _7 = _2; // scope 2 at $DIR/if.rs:+4:13: +4:14 - _6 = Add(move _7, const 1_i32); // scope 2 at $DIR/if.rs:+4:13: +4:18 +- _7 = _2; // scope 2 at $DIR/if.rs:+4:13: +4:14 +- _6 = Add(move _7, const 1_i32); // scope 2 at $DIR/if.rs:+4:13: +4:18 ++ _7 = const 2_i32; // scope 2 at $DIR/if.rs:+4:13: +4:14 ++ _6 = const 3_i32; // scope 2 at $DIR/if.rs:+4:13: +4:18 StorageDead(_7); // scope 2 at $DIR/if.rs:+4:17: +4:18 StorageLive(_8); // scope 3 at $DIR/if.rs:+6:9: +6:10 StorageLive(_9); // scope 3 at $DIR/if.rs:+6:16: +6:24 diff --git a/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff index 075cf35a54548..881d80f7c0326 100644 --- a/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff @@ -26,7 +26,8 @@ bb3: { StorageDead(_2); // scope 0 at $DIR/issue_81605.rs:+1:32: +1:33 - _0 = Add(const 1_usize, move _1); // scope 0 at $DIR/issue_81605.rs:+1:5: +1:33 +- _0 = Add(const 1_usize, move _1); // scope 0 at $DIR/issue_81605.rs:+1:5: +1:33 ++ _0 = const 2_usize; // scope 0 at $DIR/issue_81605.rs:+1:5: +1:33 StorageDead(_1); // scope 0 at $DIR/issue_81605.rs:+1:32: +1:33 return; // scope 0 at $DIR/issue_81605.rs:+2:2: +2:2 } From f234419a15de5d14f7b014e928d77026409b4f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 2 Sep 2022 17:57:05 +0200 Subject: [PATCH 18/76] Rebase onto master --- .../lower_intrinsics_e2e.f_u64.PreCodegen.after.mir | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/test/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir b/src/test/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir index 8e185323e1a84..f6d8bdd742289 100644 --- a/src/test/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir +++ b/src/test/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir @@ -6,25 +6,20 @@ fn f_u64() -> () { scope 1 (inlined f_dispatch::) { // at $DIR/lower_intrinsics_e2e.rs:15:5: 15:21 debug t => _1; // in scope 1 at $DIR/lower_intrinsics_e2e.rs:19:22: 19:23 let _2: (); // in scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21 - let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20 scope 2 (inlined std::mem::size_of::) { // at $DIR/lower_intrinsics_e2e.rs:20:8: 20:32 } } bb0: { StorageLive(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21 - _1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21 StorageLive(_2); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21 - StorageLive(_3); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20 - _3 = move _1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20 - _2 = f_non_zst::(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21 + _2 = f_non_zst::(const 0_u64) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21 // mir::Constant // + span: $DIR/lower_intrinsics_e2e.rs:23:9: 23:18 // + literal: Const { ty: fn(u64) {f_non_zst::}, val: Value() } } bb1: { - StorageDead(_3); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:20: 23:21 StorageDead(_2); // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:21: 23:22 StorageDead(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21 return; // scope 0 at $DIR/lower_intrinsics_e2e.rs:+2:2: +2:2 From 895181b962cf39b7674023dc329c5c6d387a435f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 2 Sep 2022 18:06:22 +0200 Subject: [PATCH 19/76] Remove leftover test files --- .../issue_73223.main.PreCodegen.32bit.diff | 117 ------------------ .../issue_73223.main.PreCodegen.64bit.diff | 117 ------------------ 2 files changed, 234 deletions(-) delete mode 100644 src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff delete mode 100644 src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff deleted file mode 100644 index be8e86a832cb6..0000000000000 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff +++ /dev/null @@ -1,117 +0,0 @@ -- // MIR for `main` before PreCodegen -+ // MIR for `main` after PreCodegen - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - let _3: i32; // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - let mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _6: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _12: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _14: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _19: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 1 { - debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14 - let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - scope 3 { - debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14 - let _8: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 4 { - debug left_val => _8; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - debug right_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _13: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 5 { - debug kind => _13; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - } - } - } - scope 2 { - debug v => _3; // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - Deinit(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _1 = _3; // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7 - StorageLive(_4); // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - StorageLive(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _6 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } - _7 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_5.0: &i32) = move _6; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_5.1: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _8 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _9 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _12 = (*_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _11 = Eq(move _12, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _10 = Not(move _11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - switchInt(move _10) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb1: { - StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = _8; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _14 = core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } - } - - bb2: { - StorageDead(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2 - return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2 - } - } - diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff deleted file mode 100644 index be8e86a832cb6..0000000000000 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff +++ /dev/null @@ -1,117 +0,0 @@ -- // MIR for `main` before PreCodegen -+ // MIR for `main` after PreCodegen - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - let _3: i32; // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - let mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _6: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _12: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _14: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _19: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 1 { - debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14 - let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - scope 3 { - debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14 - let _8: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 4 { - debug left_val => _8; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - debug right_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _13: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 5 { - debug kind => _13; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - } - } - } - scope 2 { - debug v => _3; // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14 - StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - Deinit(_2); // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30 - StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15 - _1 = _3; // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7 - StorageLive(_4); // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 - StorageLive(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _6 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } - _7 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_5.0: &i32) = move _6; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_5.1: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _8 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _9 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _12 = (*_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _11 = Eq(move _12, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _10 = Not(move _11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - switchInt(move _10) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - } - - bb1: { - StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = _8; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _14 = core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } - // mir::Constant - // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } - } - - bb2: { - StorageDead(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2 - return; // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2 - } - } - From 2e4d0820d2f36d97f5db22496c1f71087d0e5323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 3 Sep 2022 00:26:15 +0200 Subject: [PATCH 20/76] Add more documentation --- .../rustc_mir_dataflow/src/value_analysis.rs | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 40d8aaea94dc9..355b7728e0cb6 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -193,6 +193,8 @@ pub trait ValueAnalysis<'tcx> { Self::Value::top() } + /// The effect of a successful function call return should not be + /// applied here, see [`Analysis::apply_terminator_effect`]. fn handle_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State) { self.super_terminator(terminator, state) } @@ -267,6 +269,8 @@ impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper } fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) { + // The initial state maps all tracked places of argument projections to ⊤ and the rest to ⊥. + // This utilizes that reading from an uninitialized place is UB. assert!(matches!(state.0, StateData::Unreachable)); let values = IndexVec::from_elem_n(T::Value::bottom(), self.0.map().value_count); *state = State(StateData::Reachable(values)); @@ -325,20 +329,38 @@ where } rustc_index::newtype_index!( + /// This index uniquely identifies a place. + /// + /// Not every place has a `PlaceIndex`, and not every `PlaceIndex` correspondends to a tracked + /// place. However, every tracked place and all places along its projection have a `PlaceIndex`. pub struct PlaceIndex {} ); rustc_index::newtype_index!( + /// This index uniquely identifies a tracked place and therefore a slot in [`State`]. + /// + /// It is an implementation detail of this module. struct ValueIndex {} ); +/// See [`State`]. #[derive(PartialEq, Eq, Clone, Debug)] enum StateData { Reachable(IndexVec), Unreachable, } -/// All operations on unreachable states are ignored. +/// The dataflow state for an instance of [`ValueAnalysis`]. +/// +/// Every instance specifies a lattice that represents the possible values of a single tracked +/// place. If we call this lattice `V` and set set of tracked places `P`, then a [`State`] is an +/// element of `{unreachable} ∪ (P -> V)`. This again forms a lattice, where the bottom element is +/// `unreachable` and the top element is the mapping `p ↦ ⊤`. Note that the mapping `p ↦ ⊥` is not +/// the bottom element (because joining an unreachable and any other reachable state yields a +/// reachable state). All operations on unreachable states are ignored. +/// +/// Flooding means assigning a value (by default `⊤`) to all tracked projections of a given place. +/// Assigning a place (or reference thereof) to another place assumes that #[derive(PartialEq, Eq, Clone, Debug)] pub struct State(StateData); @@ -383,8 +405,13 @@ impl State { self.flood_idx_with(place, map, V::top()) } + /// This method assumes that the given places are not overlapping, and that we can therefore + /// copy all entries one after another. pub fn assign_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map) { let StateData::Reachable(values) = &mut self.0 else { return }; + // If both places are tracked, we copy the value to the target. If the target is tracked, + // but the source is not, we have to invalidate the value in target. If the target is not + // tracked, then we don't have to do anything. if let Some(target_value) = map.places[target].value_index { if let Some(source_value) = map.places[source].value_index { values[target_value] = values[source_value].clone(); @@ -393,7 +420,7 @@ impl State { } } for target_child in map.children(target) { - // Try to find corresponding child in source. + // Try to find corresponding child and recurse. Reasoning is similar as above. let projection = map.places[target_child].proj_elem.unwrap(); if let Some(source_child) = map.projections.get(&(source, projection)) { self.assign_place_idx(target_child, *source_child, map); From 2113e45488190030451f9ea89bdbc42d3e958bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 3 Sep 2022 00:30:22 +0200 Subject: [PATCH 21/76] Remove superfluous line --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 355b7728e0cb6..2f22ccc41e83d 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -360,7 +360,6 @@ enum StateData { /// reachable state). All operations on unreachable states are ignored. /// /// Flooding means assigning a value (by default `⊤`) to all tracked projections of a given place. -/// Assigning a place (or reference thereof) to another place assumes that #[derive(PartialEq, Eq, Clone, Debug)] pub struct State(StateData); From 904adcac0f93db6970fb1ee5164328b08cc926dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sun, 4 Sep 2022 12:02:38 +0200 Subject: [PATCH 22/76] Flood place on drop --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 2f22ccc41e83d..763ccff25a92e 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -199,11 +199,15 @@ pub trait ValueAnalysis<'tcx> { self.super_terminator(terminator, state) } - fn super_terminator(&self, terminator: &Terminator<'tcx>, _state: &mut State) { + fn super_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State) { match &terminator.kind { TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => { // Effect is applied by `handle_call_return`. } + TerminatorKind::Drop { place, .. } => { + // Place can still be accessed after drop, and drop has mutable access to it. + state.flood(place.as_ref(), self.map()); + } TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } => { // They would have an effect, but are not allowed in this phase. bug!("encountered disallowed terminator"); From 1e5ca5701496a73d822b8dff220c7a8e8463724b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sun, 4 Sep 2022 12:29:19 +0200 Subject: [PATCH 23/76] Use StorageDead and Deinit to flood place --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 763ccff25a92e..f625f71ccda48 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -87,12 +87,16 @@ pub trait ValueAnalysis<'tcx> { StatementKind::CopyNonOverlapping(..) => { // FIXME: What to do here? } - StatementKind::StorageLive(..) - | StatementKind::StorageDead(..) - | StatementKind::Deinit(_) => { - // Could perhaps use these. + StatementKind::StorageDead(local) => { + // It is UB to access an unallocated local. + state.flood(Place::from(*local).as_ref(), self.map()); + } + StatementKind::Deinit(box place) => { + // It is UB to access `uninit` bytes. + state.flood(place.as_ref(), self.map()); } StatementKind::Nop + | StatementKind::StorageLive(..) | StatementKind::Retag(..) | StatementKind::FakeRead(..) | StatementKind::Coverage(..) From e2ddf8a6e579ca1d92fdddd8bead46277c3261eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sun, 4 Sep 2022 12:29:49 +0200 Subject: [PATCH 24/76] Add comment about downcast projection element --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index f625f71ccda48..80d343e2b537d 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -582,7 +582,10 @@ impl Map { // Apply the projection. for &elem in projection { - // For now, downcast is not allowed (see #101168). + // For now, downcast is not allowed due to aliasing between variants (see #101168). + // Also, according to the documentation of [`Place`], a single-variant type can be + // projected with and without a [`ProjectionElem::Downcast`]. This creates an ambiguity + // that needs to be resolved. match elem { PlaceElem::Downcast(..) => return Err(()), _ => (), From 817c27744ddd6627dcc05fc35f92534b6be6435b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 9 Sep 2022 11:56:10 +0200 Subject: [PATCH 25/76] Handle StorageLive --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 80d343e2b537d..bdcb18f93b9e9 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -83,20 +83,21 @@ pub trait ValueAnalysis<'tcx> { } StatementKind::SetDiscriminant { .. } => { // Could treat this as writing a constant to a pseudo-place. + // But discriminants are currently not tracked, so we do nothing. + // Related: https://github.com/rust-lang/unsafe-code-guidelines/issues/84 } StatementKind::CopyNonOverlapping(..) => { // FIXME: What to do here? } - StatementKind::StorageDead(local) => { - // It is UB to access an unallocated local. + StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { + // It is UB to read from an unitialized or unallocated local. state.flood(Place::from(*local).as_ref(), self.map()); } StatementKind::Deinit(box place) => { - // It is UB to access `uninit` bytes. + // It is UB to read `uninit` bytes. state.flood(place.as_ref(), self.map()); } StatementKind::Nop - | StatementKind::StorageLive(..) | StatementKind::Retag(..) | StatementKind::FakeRead(..) | StatementKind::Coverage(..) From bc82c13e973bddd59a55f2fbff6286b398eb68eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 23 Sep 2022 15:15:14 +0200 Subject: [PATCH 26/76] Track Scalar instead of ScalarInt for const prop --- .../src/dataflow_const_prop.rs | 71 ++++++++----------- 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 1cc4201a94982..334af0c6e8e6b 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -2,7 +2,7 @@ use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::visit::{MutVisitor, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{ Map, ProjElem, State, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef, }; @@ -43,7 +43,7 @@ struct ConstAnalysis<'tcx> { } impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { - type Value = FlatSet>; + type Value = FlatSet>; const NAME: &'static str = "ConstAnalysis"; @@ -136,8 +136,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { .literal .eval(self.tcx, self.param_env) .try_to_scalar() - .and_then(|scalar| scalar.try_to_int().ok()) - .map(|value| FlatSet::Elem(Const::Scalar(value, constant.ty()))) + .map(|value| FlatSet::Elem(ScalarTy(value, constant.ty()))) .unwrap_or(FlatSet::Top) } @@ -161,8 +160,9 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { }; let result = match value { FlatSet::Top => FlatSet::Top, - FlatSet::Elem(Const::Scalar(scalar, _)) => { - FlatSet::Elem(scalar.assert_bits(scalar.size())) + FlatSet::Elem(ScalarTy(scalar, _)) => { + let int = scalar.assert_int(); + FlatSet::Elem(int.assert_bits(int.size())) } FlatSet::Bottom => FlatSet::Bottom, }; @@ -188,18 +188,11 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { } #[derive(Clone, PartialEq, Eq)] -enum Const<'tcx> { - // FIXME: If there won't be any other cases, make it a struct. - Scalar(ScalarInt, Ty<'tcx>), -} +struct ScalarTy<'tcx>(Scalar, Ty<'tcx>); -impl<'tcx> std::fmt::Debug for Const<'tcx> { +impl<'tcx> std::fmt::Debug for ScalarTy<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match *self { - Self::Scalar(scalar, ty) => { - std::fmt::Display::fmt(&ConstantKind::Val(ConstValue::Scalar(scalar.into()), ty), f) - } - } + std::fmt::Display::fmt(&ConstantKind::Val(ConstValue::Scalar(self.0), self.1), f) } } @@ -215,25 +208,20 @@ impl<'tcx> ConstAnalysis<'tcx> { fn binary_op( &self, - state: &mut State>>, + state: &mut State>>, op: BinOp, left: &Operand<'tcx>, right: &Operand<'tcx>, - ) -> (FlatSet>, FlatSet>) { + ) -> (FlatSet>, FlatSet>) { let left = self.eval_operand(left, state); let right = self.eval_operand(right, state); match (left, right) { (FlatSet::Elem(left), FlatSet::Elem(right)) => { match self.ecx.overflowing_binary_op(op, &left, &right) { - Ok((val, overflow, ty)) => { - let val = val - .try_to_int() - .ok() - .map(|val| self.wrap_scalar(val, ty)) - .unwrap_or(FlatSet::Top); - let overflow = self.wrap_scalar(overflow.into(), self.tcx.types.bool); - (val, overflow) - } + Ok((val, overflow, ty)) => ( + self.wrap_scalar(val, ty), + self.wrap_scalar(Scalar::from_bool(overflow), self.tcx.types.bool), + ), _ => (FlatSet::Top, FlatSet::Top), } } @@ -248,7 +236,7 @@ impl<'tcx> ConstAnalysis<'tcx> { fn eval_operand( &self, op: &Operand<'tcx>, - state: &mut State>>, + state: &mut State>>, ) -> FlatSet> { let value = match self.handle_operand(op, state) { ValueOrPlace::Value(value) => value, @@ -257,29 +245,29 @@ impl<'tcx> ConstAnalysis<'tcx> { }; match value { FlatSet::Top => FlatSet::Top, - FlatSet::Elem(Const::Scalar(value, ty)) => { + FlatSet::Elem(ScalarTy(scalar, ty)) => { let layout = self .tcx .layout_of(ty::ParamEnv::empty().and(ty)) .expect("this should not happen"); // FIXME - FlatSet::Elem(ImmTy::from_scalar(value.into(), layout)) + FlatSet::Elem(ImmTy::from_scalar(scalar, layout)) } FlatSet::Bottom => FlatSet::Bottom, } } - fn wrap_scalar(&self, scalar: ScalarInt, ty: Ty<'tcx>) -> FlatSet> { - FlatSet::Elem(Const::Scalar(scalar, ty)) + fn wrap_scalar(&self, scalar: Scalar, ty: Ty<'tcx>) -> FlatSet> { + FlatSet::Elem(ScalarTy(scalar, ty)) } - fn wrap_immediate(&self, imm: Immediate, ty: Ty<'tcx>) -> FlatSet> { + fn wrap_immediate(&self, imm: Immediate, ty: Ty<'tcx>) -> FlatSet> { match imm { - Immediate::Scalar(Scalar::Int(scalar)) => self.wrap_scalar(scalar, ty), + Immediate::Scalar(scalar) => self.wrap_scalar(scalar, ty), _ => FlatSet::Top, } } - fn wrap_immty(&self, val: ImmTy<'tcx>) -> FlatSet> { + fn wrap_immty(&self, val: ImmTy<'tcx>) -> FlatSet> { self.wrap_immediate(*val, val.layout.ty) } } @@ -287,8 +275,8 @@ impl<'tcx> ConstAnalysis<'tcx> { struct CollectAndPatch<'tcx, 'map> { tcx: TyCtxt<'tcx>, map: &'map Map, - before_effect: FxHashMap<(Location, Place<'tcx>), Const<'tcx>>, - assignments: FxHashMap>, + before_effect: FxHashMap<(Location, Place<'tcx>), ScalarTy<'tcx>>, + assignments: FxHashMap>, } impl<'tcx, 'map> CollectAndPatch<'tcx, 'map> { @@ -296,18 +284,17 @@ impl<'tcx, 'map> CollectAndPatch<'tcx, 'map> { Self { tcx, map, before_effect: FxHashMap::default(), assignments: FxHashMap::default() } } - fn make_operand(&self, constant: Const<'tcx>) -> Operand<'tcx> { - let Const::Scalar(scalar, ty) = constant; + fn make_operand(&self, scalar: ScalarTy<'tcx>) -> Operand<'tcx> { Operand::Constant(Box::new(Constant { span: DUMMY_SP, user_ty: None, - literal: ConstantKind::Val(ConstValue::Scalar(scalar.into()), ty), + literal: ConstantKind::Val(ConstValue::Scalar(scalar.0), scalar.1), })) } } impl<'mir, 'tcx, 'map> ResultsVisitor<'mir, 'tcx> for CollectAndPatch<'tcx, 'map> { - type FlowState = State>>; + type FlowState = State>>; fn visit_statement_before_primary_effect( &mut self, @@ -384,7 +371,7 @@ impl<'tcx, 'map> MutVisitor<'tcx> for CollectAndPatch<'tcx, 'map> { } struct OperandCollector<'tcx, 'map, 'a> { - state: &'a State>>, + state: &'a State>>, visitor: &'a mut CollectAndPatch<'tcx, 'map>, } From 13b70599c1fbf15ced793b862ee9732156dd7bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 27 Sep 2022 16:16:09 +0200 Subject: [PATCH 27/76] Only allow registration of scalars for now --- .../rustc_mir_dataflow/src/value_analysis.rs | 68 ++++++++++++++----- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index bdcb18f93b9e9..05285e460eb17 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -55,6 +55,7 @@ use std::fmt::{Debug, Formatter}; use rustc_data_structures::fx::FxHashMap; use rustc_index::vec::IndexVec; +use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_target::abi::VariantIdx; @@ -549,8 +550,8 @@ impl Map { filter: &mut impl FnMut(Ty<'tcx>) -> bool, ) { if filter(ty) { - // Since downcasts are currently not allowed, this might fail. - let _ = self.register(local, projection); + // This might fail if `ty` is not scalar. + let _ = self.register_with_ty(local, projection, ty); } if max_derefs > 0 { if let Some(ty::TypeAndMut { ty, .. }) = ty.builtin_deref(false) { @@ -560,33 +561,27 @@ impl Map { } } iter_fields(ty, tcx, |variant, field, ty| { - if let Some(variant) = variant { - projection.push(PlaceElem::Downcast(None, variant)); + if variant.is_some() { + // Downcasts are currently not supported. + return; } projection.push(PlaceElem::Field(field, ty)); self.register_with_filter_rec(tcx, max_derefs, local, projection, ty, filter); projection.pop(); - if variant.is_some() { - projection.pop(); - } }); } - pub fn register<'tcx>( + fn make_place<'tcx>( &mut self, local: Local, projection: &[PlaceElem<'tcx>], - ) -> Result<(), ()> { + ) -> Result { // Get the base index of the local. let mut index = *self.locals.get_or_insert_with(local, || self.places.push(PlaceInfo::new(None))); // Apply the projection. for &elem in projection { - // For now, downcast is not allowed due to aliasing between variants (see #101168). - // Also, according to the documentation of [`Place`], a single-variant type can be - // projected with and without a [`ProjectionElem::Downcast`]. This creates an ambiguity - // that needs to be resolved. match elem { PlaceElem::Downcast(..) => return Err(()), _ => (), @@ -601,9 +596,46 @@ impl Map { }); } + Ok(index) + } + + pub fn register<'tcx>( + &mut self, + local: Local, + projection: &[PlaceElem<'tcx>], + decls: &impl HasLocalDecls<'tcx>, + tcx: TyCtxt<'tcx>, + ) -> Result<(), ()> { + projection + .iter() + .fold(PlaceTy::from_ty(decls.local_decls()[local].ty), |place_ty, &elem| { + place_ty.projection_ty(tcx, elem) + }); + + let place_ty = Place::ty_from(local, projection, decls, tcx); + if place_ty.variant_index.is_some() { + return Err(()); + } + self.register_with_ty(local, projection, place_ty.ty) + } + + fn register_with_ty<'tcx>( + &mut self, + local: Local, + projection: &[PlaceElem<'tcx>], + ty: Ty<'tcx>, + ) -> Result<(), ()> { + if !ty.is_scalar() { + // Currently, only scalar types are allowed, because they are atomic + // and therefore do not require invalidation of parent places. + return Err(()); + } + + let place = self.make_place(local, projection)?; + // Allocate a value slot if it doesn't have one. - if self.places[index].value_index.is_none() { - self.places[index].value_index = Some(self.value_count.into()); + if self.places[place].value_index.is_none() { + self.places[place].value_index = Some(self.value_count.into()); self.value_count += 1; } @@ -720,11 +752,13 @@ impl HasTop for FlatSet { } } +/// Currently, we only track places through deref and field projections. +/// +/// For now, downcast is not allowed due to aliasing between variants (see #101168). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum ProjElem { Deref, Field(Field), - Downcast(VariantIdx), } impl TryFrom> for ProjElem { @@ -734,7 +768,6 @@ impl TryFrom> for ProjElem { match value { ProjectionElem::Deref => Ok(ProjElem::Deref), ProjectionElem::Field(field, _) => Ok(ProjElem::Field(field)), - ProjectionElem::Downcast(_, variant) => Ok(ProjElem::Downcast(variant)), _ => Err(()), } } @@ -800,7 +833,6 @@ fn debug_with_context_rec( format!("{}.{}", place_str, field.index()) } } - ProjElem::Downcast(variant) => format!("({} as #{})", place_str, variant.index()), }; debug_with_context_rec(child, &child_place_str, new, old, map, f)?; } From 686861711df9e2a70df709c92577a95881baca76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 27 Sep 2022 16:18:40 +0200 Subject: [PATCH 28/76] Add tests from current const prop --- .../aggregate.main.DataflowConstProp.diff | 32 ++++++++ .../dataflow-const-prop/previous/aggregate.rs | 7 ++ ...ay_index.main.DataflowConstProp.32bit.diff | 39 ++++++++++ ...ay_index.main.DataflowConstProp.64bit.diff | 39 ++++++++++ .../previous/array_index.rs | 7 ++ ...op_div_by_zero.main.DataflowConstProp.diff | 52 +++++++++++++ .../previous/bad_op_div_by_zero.rs | 7 ++ ...op_mod_by_zero.main.DataflowConstProp.diff | 54 +++++++++++++ .../previous/bad_op_mod_by_zero.rs | 6 ++ ...r_slices.main.DataflowConstProp.32bit.diff | 56 ++++++++++++++ ...r_slices.main.DataflowConstProp.64bit.diff | 56 ++++++++++++++ .../previous/bad_op_unsafe_oob_for_slices.rs | 9 +++ .../previous/boolean_identities.rs | 11 +++ ...ean_identities.test.DataflowConstProp.diff | 33 ++++++++ .../boxes.main.DataflowConstProp.diff | 60 +++++++++++++++ .../dataflow-const-prop/previous/boxes.rs | 14 ++++ .../previous/cast.main.DataflowConstProp.diff | 28 +++++++ .../dataflow-const-prop/previous/cast.rs | 8 ++ .../checked_add.main.DataflowConstProp.diff | 28 +++++++ .../previous/checked_add.rs | 7 ++ ...ils_gracefully.main.DataflowConstProp.diff | 44 +++++++++++ .../previous/const_prop_fails_gracefully.rs | 10 +++ .../previous/control-flow-simplification.rs | 21 +++++ ...implification.hello.DataflowConstProp.diff | 34 ++++++++ ...simplification.hello.PreCodegen.before.mir | 9 +++ ...riminant.main.DataflowConstProp.32bit.diff | 52 +++++++++++++ ...riminant.main.DataflowConstProp.64bit.diff | 52 +++++++++++++ .../previous/discriminant.rs | 13 ++++ .../indirect.main.DataflowConstProp.diff | 33 ++++++++ .../dataflow-const-prop/previous/indirect.rs | 7 ++ ...valid_constant.main.DataflowConstProp.diff | 77 +++++++++++++++++++ .../previous/invalid_constant.rs | 44 +++++++++++ .../previous/issue-66971.rs | 18 +++++ .../previous/issue-67019.rs | 13 ++++ .../issue_66971.main.DataflowConstProp.diff | 33 ++++++++ .../issue_67019.main.DataflowConstProp.diff | 34 ++++++++ ...ay_index.main.DataflowConstProp.32bit.diff | 37 +++++++++ ...ay_index.main.DataflowConstProp.64bit.diff | 37 +++++++++ .../previous/large_array_index.rs | 7 ++ .../previous/mult_by_zero.rs | 11 +++ .../mult_by_zero.test.DataflowConstProp.diff | 18 +++++ ...table_variable.main.DataflowConstProp.diff | 28 +++++++ .../previous/mutable_variable.rs | 9 +++ ...able_aggregate.main.DataflowConstProp.diff | 30 ++++++++ .../previous/mutable_variable_aggregate.rs | 9 +++ ...regate_mut_ref.main.DataflowConstProp.diff | 36 +++++++++ .../mutable_variable_aggregate_mut_ref.rs | 10 +++ ...e_partial_read.main.DataflowConstProp.diff | 35 +++++++++ ...mutable_variable_aggregate_partial_read.rs | 15 ++++ ...riable_no_prop.main.DataflowConstProp.diff | 48 ++++++++++++ .../previous/mutable_variable_no_prop.rs | 13 ++++ ..._unprop_assign.main.DataflowConstProp.diff | 54 +++++++++++++ .../mutable_variable_unprop_assign.rs | 16 ++++ ...variable.main.DataflowConstProp.32bit.diff | 68 ++++++++++++++++ ...variable.main.DataflowConstProp.64bit.diff | 68 ++++++++++++++++ ...riable.main.SimplifyLocals.after.32bit.mir | 27 +++++++ ...riable.main.SimplifyLocals.after.64bit.mir | 27 +++++++ .../previous/optimizes_into_variable.rs | 16 ++++ ...mutable_static.main.DataflowConstProp.diff | 48 ++++++++++++ .../previous/read_immutable_static.rs | 9 +++ .../ref_deref.main.DataflowConstProp.diff | 27 +++++++ .../previous/ref_deref.main.PromoteTemps.diff | 30 ++++++++ .../dataflow-const-prop/previous/ref_deref.rs | 6 ++ ..._deref_project.main.DataflowConstProp.diff | 26 +++++++ .../ref_deref_project.main.PromoteTemps.diff | 30 ++++++++ .../previous/ref_deref_project.rs | 7 ++ .../reify_fn_ptr.main.DataflowConstProp.diff | 29 +++++++ .../previous/reify_fn_ptr.rs | 5 ++ .../repeat.main.DataflowConstProp.32bit.diff | 43 +++++++++++ .../repeat.main.DataflowConstProp.64bit.diff | 43 +++++++++++ .../dataflow-const-prop/previous/repeat.rs | 7 ++ .../return_place.add.DataflowConstProp.diff | 21 +++++ .../return_place.add.PreCodegen.before.mir | 10 +++ .../previous/return_place.rs | 11 +++ ...al_propagation.main.DataflowConstProp.diff | 35 +++++++++ .../previous/scalar_literal_propagation.rs | 8 ++ ...lice_len.main.DataflowConstProp.32bit.diff | 53 +++++++++++++ ...lice_len.main.DataflowConstProp.64bit.diff | 53 +++++++++++++ .../dataflow-const-prop/previous/slice_len.rs | 6 ++ .../switch_int.main.DataflowConstProp.diff | 34 ++++++++ ...mplifyConstCondition-after-const-prop.diff | 34 ++++++++ .../previous/switch_int.rs | 11 +++ ...al_propagation.main.DataflowConstProp.diff | 36 +++++++++ .../previous/tuple_literal_propagation.rs | 9 +++ 84 files changed, 2297 insertions(+) create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/aggregate.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/aggregate.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/array_index.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/boxes.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/cast.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/checked_add.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/control-flow-simplification.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/discriminant.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/indirect.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/issue-66971.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/issue-67019.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/issue_66971.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/large_array_index.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/repeat.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/return_place.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.SimplifyConstCondition-after-const-prop.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/switch_int.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs diff --git a/src/test/mir-opt/dataflow-const-prop/previous/aggregate.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/aggregate.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..8c35b5ca4203a --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/aggregate.main.DataflowConstProp.diff @@ -0,0 +1,32 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10 + let mut _2: i32; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24 + let mut _3: (i32, i32, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + scope 1 { + debug x => _1; // in scope 1 at $DIR/aggregate.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 + StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + Deinit(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 + (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 +- _2 = (_3.1: i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 +- _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 ++ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 ++ _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 + StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28 + StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29 + _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2 + return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/aggregate.rs b/src/test/mir-opt/dataflow-const-prop/previous/aggregate.rs new file mode 100644 index 0000000000000..bdfa922cf5caf --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/aggregate.rs @@ -0,0 +1,7 @@ +// unit-test: DataflowConstProp +// compile-flags: -O + +// EMIT_MIR aggregate.main.DataflowConstProp.diff +fn main() { + let x = (0, 1, 2).1 + 0; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff new file mode 100644 index 0000000000000..8cbc4a72e800f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff @@ -0,0 +1,39 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/array_index.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/array_index.rs:+1:9: +1:10 + let mut _2: [u32; 4]; // in scope 0 at $DIR/array_index.rs:+1:18: +1:30 + let _3: usize; // in scope 0 at $DIR/array_index.rs:+1:31: +1:32 + let mut _4: usize; // in scope 0 at $DIR/array_index.rs:+1:18: +1:33 + let mut _5: bool; // in scope 0 at $DIR/array_index.rs:+1:18: +1:33 + scope 1 { + debug x => _1; // in scope 1 at $DIR/array_index.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/array_index.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:30 + _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30 + StorageLive(_3); // scope 0 at $DIR/array_index.rs:+1:31: +1:32 + _3 = const 2_usize; // scope 0 at $DIR/array_index.rs:+1:31: +1:32 +- _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 +- _5 = Lt(_3, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ _4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ _5 = const true; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 + } + + bb1: { +- _1 = _2[_3]; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ _1 = const 2_u32; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 + StorageDead(_3); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 + StorageDead(_2); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 + _0 = const (); // scope 0 at $DIR/array_index.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/array_index.rs:+2:1: +2:2 + return; // scope 0 at $DIR/array_index.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff new file mode 100644 index 0000000000000..8cbc4a72e800f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff @@ -0,0 +1,39 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/array_index.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/array_index.rs:+1:9: +1:10 + let mut _2: [u32; 4]; // in scope 0 at $DIR/array_index.rs:+1:18: +1:30 + let _3: usize; // in scope 0 at $DIR/array_index.rs:+1:31: +1:32 + let mut _4: usize; // in scope 0 at $DIR/array_index.rs:+1:18: +1:33 + let mut _5: bool; // in scope 0 at $DIR/array_index.rs:+1:18: +1:33 + scope 1 { + debug x => _1; // in scope 1 at $DIR/array_index.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/array_index.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:30 + _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30 + StorageLive(_3); // scope 0 at $DIR/array_index.rs:+1:31: +1:32 + _3 = const 2_usize; // scope 0 at $DIR/array_index.rs:+1:31: +1:32 +- _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 +- _5 = Lt(_3, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ _4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ _5 = const true; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 + } + + bb1: { +- _1 = _2[_3]; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ _1 = const 2_u32; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 + StorageDead(_3); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 + StorageDead(_2); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 + _0 = const (); // scope 0 at $DIR/array_index.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/array_index.rs:+2:1: +2:2 + return; // scope 0 at $DIR/array_index.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/array_index.rs b/src/test/mir-opt/dataflow-const-prop/previous/array_index.rs new file mode 100644 index 0000000000000..3cd7ddf20a7da --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/array_index.rs @@ -0,0 +1,7 @@ +// unit-test: DataflowConstProp +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +// EMIT_MIR array_index.main.DataflowConstProp.diff +fn main() { + let x: u32 = [0, 1, 2, 3][2]; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..47af40988ddd3 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff @@ -0,0 +1,52 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+1:9: +1:10 + let mut _3: i32; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 + let mut _4: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + let mut _5: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + let mut _6: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + let mut _7: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + scope 1 { + debug y => _1; // in scope 1 at $DIR/bad_op_div_by_zero.rs:+1:9: +1:10 + let _2: i32; // in scope 1 at $DIR/bad_op_div_by_zero.rs:+2:9: +2:11 + scope 2 { + debug _z => _2; // in scope 2 at $DIR/bad_op_div_by_zero.rs:+2:9: +2:11 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/bad_op_div_by_zero.rs:+1:9: +1:10 + _1 = const 0_i32; // scope 0 at $DIR/bad_op_div_by_zero.rs:+1:13: +1:14 + StorageLive(_2); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:9: +2:11 + StorageLive(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 +- _3 = _1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 +- _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 ++ _3 = const 0_i32; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 ++ _4 = const true; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + } + + bb1: { +- _5 = Eq(_3, const -1_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 +- _6 = Eq(const 1_i32, const i32::MIN); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 +- _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 +- assert(!move _7, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 ++ _5 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 ++ _6 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 ++ _7 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 ++ assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + } + + bb2: { + _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + StorageDead(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 + _0 = const (); // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2 + StorageDead(_2); // scope 1 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2 + StorageDead(_1); // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2 + return; // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.rs b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.rs new file mode 100644 index 0000000000000..ddf195b2c8a9f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.rs @@ -0,0 +1,7 @@ +// unit-test: DataflowConstProp +// EMIT_MIR bad_op_div_by_zero.main.DataflowConstProp.diff +#[allow(unconditional_panic)] +fn main() { + let y = 0; + let _z = 1 / y; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..0069d3ce53443 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff @@ -0,0 +1,54 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/bad_op_mod_by_zero.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:9: +1:10 + let mut _3: i32; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 + let mut _4: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + let mut _5: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + let mut _6: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + let mut _7: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + scope 1 { + debug y => _1; // in scope 1 at $DIR/bad_op_mod_by_zero.rs:+1:9: +1:10 + let _2: i32; // in scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11 + scope 2 { + debug _z => _2; // in scope 2 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:9: +1:10 + _1 = const 0_i32; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:13: +1:14 + StorageLive(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11 + StorageLive(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 +- _3 = _1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 +- _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- assert(!move _4, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ _3 = const 0_i32; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 ++ _4 = const true; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + } + + bb1: { +- _5 = Eq(_3, const -1_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- _6 = Eq(const 1_i32, const i32::MIN); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ _5 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ _6 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ _7 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + } + + bb2: { +- _2 = Rem(const 1_i32, move _3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + StorageDead(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 + nop; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+0:11: +3:2 + StorageDead(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2 + StorageDead(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2 + return; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs new file mode 100644 index 0000000000000..6a7a82e5034b0 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs @@ -0,0 +1,6 @@ +// EMIT_MIR bad_op_mod_by_zero.main.DataflowConstProp.diff +#[allow(unconditional_panic)] +fn main() { + let y = 0; + let _z = 1 % y; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff new file mode 100644 index 0000000000000..f04715e3b335f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff @@ -0,0 +1,56 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+0:11: +0:11 + let _1: *const [i32]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 + let mut _2: *const [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + let _3: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + let _4: [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:26: +1:35 + let _6: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + let mut _7: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + let mut _8: bool; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + let mut _9: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + scope 1 { + debug a => _1; // in scope 1 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 + scope 2 { + let _5: i32; // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + scope 3 { + debug _b => _5; // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + // mir::Constant + // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 + // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } + _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35 + StorageDead(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:35: +1:36 + StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + } + + bb1: { + _5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 + nop; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 + StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 + StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2 + return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff new file mode 100644 index 0000000000000..f04715e3b335f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff @@ -0,0 +1,56 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+0:11: +0:11 + let _1: *const [i32]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 + let mut _2: *const [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + let _3: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + let _4: [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:26: +1:35 + let _6: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + let mut _7: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + let mut _8: bool; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + let mut _9: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + scope 1 { + debug a => _1; // in scope 1 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 + scope 2 { + let _5: i32; // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + scope 3 { + debug _b => _5; // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + // mir::Constant + // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 + // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } + _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35 + StorageDead(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:35: +1:36 + StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + } + + bb1: { + _5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 + nop; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 + StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 + StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2 + return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs new file mode 100644 index 0000000000000..e4cc9cb917ede --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs @@ -0,0 +1,9 @@ +// EMIT_MIR_FOR_EACH_BIT_WIDTH +// EMIT_MIR bad_op_unsafe_oob_for_slices.main.DataflowConstProp.diff +#[allow(unconditional_panic)] +fn main() { + let a: *const [_] = &[1, 2, 3]; + unsafe { + let _b = (*a)[3]; + } +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.rs b/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.rs new file mode 100644 index 0000000000000..578f9830cf221 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.rs @@ -0,0 +1,11 @@ +// unit-test: DataflowConstProp +// compile-flags: -O -Zmir-opt-level=4 + +// EMIT_MIR boolean_identities.test.DataflowConstProp.diff +pub fn test(x: bool, y: bool) -> bool { + (y | true) & (x & false) +} + +fn main() { + test(true, false); +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff new file mode 100644 index 0000000000000..90236fcf0a935 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff @@ -0,0 +1,33 @@ +- // MIR for `test` before DataflowConstProp ++ // MIR for `test` after DataflowConstProp + + fn test(_1: bool, _2: bool) -> bool { + debug x => _1; // in scope 0 at $DIR/boolean_identities.rs:+0:13: +0:14 + debug y => _2; // in scope 0 at $DIR/boolean_identities.rs:+0:22: +0:23 + let mut _0: bool; // return place in scope 0 at $DIR/boolean_identities.rs:+0:34: +0:38 + let mut _3: bool; // in scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 + let mut _4: bool; // in scope 0 at $DIR/boolean_identities.rs:+1:6: +1:7 + let mut _5: bool; // in scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 + let mut _6: bool; // in scope 0 at $DIR/boolean_identities.rs:+1:19: +1:20 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 + StorageLive(_4); // scope 0 at $DIR/boolean_identities.rs:+1:6: +1:7 + _4 = _2; // scope 0 at $DIR/boolean_identities.rs:+1:6: +1:7 +- _3 = BitOr(move _4, const true); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 ++ _3 = const true; // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 + StorageDead(_4); // scope 0 at $DIR/boolean_identities.rs:+1:14: +1:15 + StorageLive(_5); // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 + StorageLive(_6); // scope 0 at $DIR/boolean_identities.rs:+1:19: +1:20 + _6 = _1; // scope 0 at $DIR/boolean_identities.rs:+1:19: +1:20 +- _5 = BitAnd(move _6, const false); // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 ++ _5 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 + StorageDead(_6); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29 +- _0 = BitAnd(move _3, move _5); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:29 ++ _0 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:29 + StorageDead(_5); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29 + StorageDead(_3); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29 + return; // scope 0 at $DIR/boolean_identities.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..2d8604440deb3 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff @@ -0,0 +1,60 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/boxes.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/boxes.rs:+1:9: +1:10 + let mut _2: i32; // in scope 0 at $DIR/boxes.rs:+1:13: +1:22 + let mut _3: std::boxed::Box; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 + let mut _4: usize; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 + let mut _5: usize; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 + let mut _6: *mut u8; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 + let mut _7: std::boxed::Box; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 + let mut _8: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 + let mut _9: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 + scope 1 { + debug x => _1; // in scope 1 at $DIR/boxes.rs:+1:9: +1:10 + } + scope 2 { + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/boxes.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/boxes.rs:+1:13: +1:22 + StorageLive(_3); // scope 0 at $DIR/boxes.rs:+1:14: +1:22 +- _4 = SizeOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22 +- _5 = AlignOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22 ++ _4 = const 4_usize; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 ++ _5 = const 4_usize; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 + _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 + // mir::Constant + // + span: $DIR/boxes.rs:13:14: 13:22 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value() } + } + + bb1: { + StorageLive(_7); // scope 0 at $DIR/boxes.rs:+1:14: +1:22 + _7 = ShallowInitBox(move _6, i32); // scope 0 at $DIR/boxes.rs:+1:14: +1:22 + _8 = (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); // scope 0 at $DIR/boxes.rs:+1:19: +1:21 + (*_8) = const 42_i32; // scope 0 at $DIR/boxes.rs:+1:19: +1:21 + _3 = move _7; // scope 0 at $DIR/boxes.rs:+1:14: +1:22 + StorageDead(_7); // scope 0 at $DIR/boxes.rs:+1:21: +1:22 + _9 = (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); // scope 0 at $DIR/boxes.rs:+1:13: +1:22 + _2 = (*_9); // scope 0 at $DIR/boxes.rs:+1:13: +1:22 + _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/boxes.rs:+1:13: +1:26 + StorageDead(_2); // scope 0 at $DIR/boxes.rs:+1:25: +1:26 + drop(_3) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/boxes.rs:+1:26: +1:27 + } + + bb2: { + StorageDead(_3); // scope 0 at $DIR/boxes.rs:+1:26: +1:27 + _0 = const (); // scope 0 at $DIR/boxes.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/boxes.rs:+2:1: +2:2 + return; // scope 0 at $DIR/boxes.rs:+2:2: +2:2 + } + + bb3 (cleanup): { + resume; // scope 0 at $DIR/boxes.rs:+0:1: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/boxes.rs b/src/test/mir-opt/dataflow-const-prop/previous/boxes.rs new file mode 100644 index 0000000000000..8b0c13c2eb6f5 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/boxes.rs @@ -0,0 +1,14 @@ +// unit-test: DataflowConstProp +// compile-flags: -O +// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32 +// ignore-wasm64 + +#![feature(box_syntax)] + +// Note: this test verifies that we, in fact, do not const prop `box` + +// EMIT_MIR boxes.main.DataflowConstProp.diff +fn main() { + let x = *(box 42) + 0; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..fb346993d6133 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff @@ -0,0 +1,28 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/cast.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/cast.rs:+1:9: +1:10 + scope 1 { + debug x => _1; // in scope 1 at $DIR/cast.rs:+1:9: +1:10 + let _2: u8; // in scope 1 at $DIR/cast.rs:+3:9: +3:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/cast.rs:+3:9: +3:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/cast.rs:+1:9: +1:10 +- _1 = const 42_u8 as u32 (Misc); // scope 0 at $DIR/cast.rs:+1:13: +1:24 ++ _1 = const 42_u32; // scope 0 at $DIR/cast.rs:+1:13: +1:24 + StorageLive(_2); // scope 1 at $DIR/cast.rs:+3:9: +3:10 +- _2 = const 42_u32 as u8 (Misc); // scope 1 at $DIR/cast.rs:+3:13: +3:24 ++ _2 = const 42_u8; // scope 1 at $DIR/cast.rs:+3:13: +3:24 + _0 = const (); // scope 0 at $DIR/cast.rs:+0:11: +4:2 + StorageDead(_2); // scope 1 at $DIR/cast.rs:+4:1: +4:2 + StorageDead(_1); // scope 0 at $DIR/cast.rs:+4:1: +4:2 + return; // scope 0 at $DIR/cast.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/cast.rs b/src/test/mir-opt/dataflow-const-prop/previous/cast.rs new file mode 100644 index 0000000000000..25cc1839ff019 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/cast.rs @@ -0,0 +1,8 @@ +// unit-test: DataflowConstProp +// EMIT_MIR cast.main.DataflowConstProp.diff + +fn main() { + let x = 42u8 as u32; + + let y = 42u32 as u8; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..4a40fd27497c4 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff @@ -0,0 +1,28 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/checked_add.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/checked_add.rs:+1:9: +1:10 + let mut _2: (u32, bool); // in scope 0 at $DIR/checked_add.rs:+1:18: +1:23 + scope 1 { + debug x => _1; // in scope 1 at $DIR/checked_add.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/checked_add.rs:+1:9: +1:10 +- _2 = CheckedAdd(const 1_u32, const 1_u32); // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 +- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 ++ _2 = const (2_u32, false); // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 + } + + bb1: { +- _1 = move (_2.0: u32); // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 ++ _1 = const 2_u32; // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 + _0 = const (); // scope 0 at $DIR/checked_add.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/checked_add.rs:+2:1: +2:2 + return; // scope 0 at $DIR/checked_add.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/checked_add.rs b/src/test/mir-opt/dataflow-const-prop/previous/checked_add.rs new file mode 100644 index 0000000000000..e7cb047098989 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/checked_add.rs @@ -0,0 +1,7 @@ +// unit-test: DataflowConstProp +// compile-flags: -C overflow-checks=on + +// EMIT_MIR checked_add.main.DataflowConstProp.diff +fn main() { + let x: u32 = 1 + 1; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..17b63065df020 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff @@ -0,0 +1,44 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +0:11 + let _1: usize; // in scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:9: +2:10 + let mut _2: *const i32; // in scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:30 + let _3: &i32; // in scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 + let _4: (); // in scope 0 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12 + let mut _5: usize; // in scope 0 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11 + scope 1 { + debug x => _1; // in scope 1 at $DIR/const_prop_fails_gracefully.rs:+2:9: +2:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:9: +2:10 + StorageLive(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:30 + StorageLive(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 + _3 = const FOO; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 + // mir::Constant + // + span: $DIR/const_prop_fails_gracefully.rs:8:13: 8:16 + // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) } + _2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 + _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:39 + StorageDead(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:38: +2:39 + StorageDead(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:39: +2:40 + StorageLive(_4); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12 + StorageLive(_5); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11 + _5 = _1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11 + _4 = read(move _5) -> bb1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12 + // mir::Constant + // + span: $DIR/const_prop_fails_gracefully.rs:9:5: 9:9 + // + literal: Const { ty: fn(usize) {read}, val: Value() } + } + + bb1: { + StorageDead(_5); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:11: +3:12 + StorageDead(_4); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:12: +3:13 + _0 = const (); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +4:2 + StorageDead(_1); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:1: +4:2 + return; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.rs b/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.rs new file mode 100644 index 0000000000000..59b2f9caf2eaf --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.rs @@ -0,0 +1,10 @@ +// unit-test: DataflowConstProp +#[inline(never)] +fn read(_: usize) {} + +// EMIT_MIR const_prop_fails_gracefully.main.DataflowConstProp.diff +fn main() { + const FOO: &i32 = &1; + let x = FOO as *const i32 as usize; + read(x); +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/control-flow-simplification.rs b/src/test/mir-opt/dataflow-const-prop/previous/control-flow-simplification.rs new file mode 100644 index 0000000000000..e1269628d2f1a --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/control-flow-simplification.rs @@ -0,0 +1,21 @@ +// unit-test: DataflowConstProp +// compile-flags: -Zmir-opt-level=1 + +trait NeedsDrop: Sized { + const NEEDS: bool = std::mem::needs_drop::(); +} + +impl NeedsDrop for This {} + +// EMIT_MIR control_flow_simplification.hello.DataflowConstProp.diff +// EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir +fn hello() { + if ::NEEDS { + panic!() + } +} + +pub fn main() { + hello::<()>(); + hello::>(); +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff new file mode 100644 index 0000000000000..2faa8422e5ea9 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff @@ -0,0 +1,34 @@ +- // MIR for `hello` before DataflowConstProp ++ // MIR for `hello` after DataflowConstProp + + fn hello() -> () { + let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:+0:14: +0:14 + let mut _1: bool; // in scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 + let mut _2: !; // in scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL + + bb0: { + StorageLive(_1); // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 +- _1 = const ::NEEDS; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 +- switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 ++ _1 = const false; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 ++ switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 + } + + bb1: { + StorageLive(_2); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL + _2 = begin_panic::<&str>(const "explicit panic"); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/std/src/panic.rs:LL:COL + // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value() } + // mir::Constant + // + span: $SRC_DIR/std/src/panic.rs:LL:COL + // + literal: Const { ty: &str, val: Value(Slice(..)) } + } + + bb2: { + nop; // scope 0 at $DIR/control-flow-simplification.rs:+3:6: +3:6 + StorageDead(_1); // scope 0 at $DIR/control-flow-simplification.rs:+3:5: +3:6 + return; // scope 0 at $DIR/control-flow-simplification.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir new file mode 100644 index 0000000000000..70f9797751131 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir @@ -0,0 +1,9 @@ +// MIR for `hello` before PreCodegen + +fn hello() -> () { + let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:+0:14: +0:14 + + bb0: { + return; // scope 0 at $DIR/control-flow-simplification.rs:+4:2: +4:2 + } +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff new file mode 100644 index 0000000000000..e527e2e1a5451 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff @@ -0,0 +1,52 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/discriminant.rs:+1:9: +1:10 + let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:+1:13: +1:64 + let mut _3: std::option::Option; // in scope 0 at $DIR/discriminant.rs:+1:34: +1:44 + let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:+1:21: +1:31 + scope 1 { + debug x => _1; // in scope 1 at $DIR/discriminant.rs:+1:9: +1:10 + } + scope 2 { + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 + StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 + Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 + ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 + discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 +- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 +- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 ++ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 ++ switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 + } + + bb1: { + switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 + } + + bb2: { + _2 = const 42_i32; // scope 2 at $DIR/discriminant.rs:+1:47: +1:49 + goto -> bb4; // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 + } + + bb3: { + _2 = const 10_i32; // scope 0 at $DIR/discriminant.rs:+1:59: +1:61 + goto -> bb4; // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 + } + + bb4: { + _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/discriminant.rs:+1:13: +1:68 + StorageDead(_2); // scope 0 at $DIR/discriminant.rs:+1:67: +1:68 + StorageDead(_3); // scope 0 at $DIR/discriminant.rs:+1:68: +1:69 + _0 = const (); // scope 0 at $DIR/discriminant.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/discriminant.rs:+2:1: +2:2 + return; // scope 0 at $DIR/discriminant.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff new file mode 100644 index 0000000000000..e527e2e1a5451 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff @@ -0,0 +1,52 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/discriminant.rs:+1:9: +1:10 + let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:+1:13: +1:64 + let mut _3: std::option::Option; // in scope 0 at $DIR/discriminant.rs:+1:34: +1:44 + let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:+1:21: +1:31 + scope 1 { + debug x => _1; // in scope 1 at $DIR/discriminant.rs:+1:9: +1:10 + } + scope 2 { + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 + StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 + Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 + ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 + discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 +- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 +- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 ++ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 ++ switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 + } + + bb1: { + switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 + } + + bb2: { + _2 = const 42_i32; // scope 2 at $DIR/discriminant.rs:+1:47: +1:49 + goto -> bb4; // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 + } + + bb3: { + _2 = const 10_i32; // scope 0 at $DIR/discriminant.rs:+1:59: +1:61 + goto -> bb4; // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 + } + + bb4: { + _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/discriminant.rs:+1:13: +1:68 + StorageDead(_2); // scope 0 at $DIR/discriminant.rs:+1:67: +1:68 + StorageDead(_3); // scope 0 at $DIR/discriminant.rs:+1:68: +1:69 + _0 = const (); // scope 0 at $DIR/discriminant.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/discriminant.rs:+2:1: +2:2 + return; // scope 0 at $DIR/discriminant.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.rs b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.rs new file mode 100644 index 0000000000000..5399bc2599778 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.rs @@ -0,0 +1,13 @@ +// unit-test: DataflowConstProp +// compile-flags: -O + +// FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with +// `let x = 42` but that doesn't work because const-prop doesn't support `Operand::Indirect` +// and `InterpCx::eval_place()` always forces an allocation which creates the `Indirect`. +// Fixing either of those will allow us to const-prop this away. + +// EMIT_MIR_FOR_EACH_BIT_WIDTH +// EMIT_MIR discriminant.main.DataflowConstProp.diff +fn main() { + let x = (if let Some(true) = Some(true) { 42 } else { 10 }) + 0; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..f5b23abfb3bcb --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff @@ -0,0 +1,33 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/indirect.rs:+0:11: +0:11 + let _1: u8; // in scope 0 at $DIR/indirect.rs:+1:9: +1:10 + let mut _2: u8; // in scope 0 at $DIR/indirect.rs:+1:13: +1:25 + let mut _3: (u8, bool); // in scope 0 at $DIR/indirect.rs:+1:13: +1:29 + scope 1 { + debug x => _1; // in scope 1 at $DIR/indirect.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/indirect.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/indirect.rs:+1:13: +1:25 +- _2 = const 2_u32 as u8 (Misc); // scope 0 at $DIR/indirect.rs:+1:13: +1:25 +- _3 = CheckedAdd(_2, const 1_u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 +- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 ++ _2 = const 2_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:25 ++ _3 = const (3_u8, false); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 + } + + bb1: { +- _1 = move (_3.0: u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 ++ _1 = const 3_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 + StorageDead(_2); // scope 0 at $DIR/indirect.rs:+1:28: +1:29 + _0 = const (); // scope 0 at $DIR/indirect.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/indirect.rs:+2:1: +2:2 + return; // scope 0 at $DIR/indirect.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/indirect.rs b/src/test/mir-opt/dataflow-const-prop/previous/indirect.rs new file mode 100644 index 0000000000000..d8d79d29b8a41 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/indirect.rs @@ -0,0 +1,7 @@ +// unit-test: DataflowConstProp +// compile-flags: -C overflow-checks=on + +// EMIT_MIR indirect.main.DataflowConstProp.diff +fn main() { + let x = (2u32 as u8) + 1; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..b8713d31ad742 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff @@ -0,0 +1,77 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:+0:11: +0:11 + let _1: char; // in scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22 + let mut _2: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:+6:34: +6:63 + let mut _4: E; // in scope 0 at $DIR/invalid_constant.rs:+13:25: +13:59 + let mut _5: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:+13:34: +13:55 + let mut _7: Empty; // in scope 0 at $DIR/invalid_constant.rs:+20:35: +20:73 + let mut _8: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:+20:44: +20:65 + scope 1 { + debug _invalid_char => _1; // in scope 1 at $DIR/invalid_constant.rs:+6:9: +6:22 + let _3: [E; 1]; // in scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21 + scope 3 { + debug _invalid_tag => _3; // in scope 3 at $DIR/invalid_constant.rs:+13:9: +13:21 + let _6: [Empty; 1]; // in scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31 + scope 5 { + debug _enum_without_variants => _6; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31 + let _9: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22 + scope 7 { + debug _non_utf8_str => _9; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22 + } + } + scope 6 { + } + } + scope 4 { + } + } + scope 2 { + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22 + StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 + Deinit(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 + (_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 +- _1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67 ++ _1 = const {transmute(0x00110001): char}; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67 + StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:+6:69: +6:70 + StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21 + StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:+13:25: +13:59 + StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 + Deinit(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 + (_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 +- _4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57 +- _3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60 ++ _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57 ++ // mir::Constant ++ // + span: $DIR/invalid_constant.rs:28:34: 28:57 ++ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } ++ _3 = [const Scalar(0x00000004): E]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60 ++ // mir::Constant ++ // + span: $DIR/invalid_constant.rs:28:24: 28:60 ++ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } + StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60 + StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61 + StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31 + StorageLive(_7); // scope 3 at $DIR/invalid_constant.rs:+20:35: +20:73 + StorageLive(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65 + Deinit(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65 + (_8.0: u32) = const 0_u32; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65 + nop; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71 + nop; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74 + StorageDead(_7); // scope 3 at $DIR/invalid_constant.rs:+20:73: +20:74 + StorageDead(_8); // scope 3 at $DIR/invalid_constant.rs:+20:74: +20:75 + StorageLive(_9); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22 + nop; // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2 + StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2 + StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2 + StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2 + StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2 + return; // scope 0 at $DIR/invalid_constant.rs:+27:2: +27:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.rs b/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.rs new file mode 100644 index 0000000000000..296fdcf0bc43c --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.rs @@ -0,0 +1,44 @@ +// Verify that we can pretty print invalid constants. + +#![feature(adt_const_params)] +#![feature(inline_const)] +#![allow(incomplete_features)] + +#[derive(Copy, Clone)] +#[repr(u32)] +enum E { + A, + B, + C, +} + +#[derive(Copy, Clone)] +enum Empty {} + +// EMIT_MIR invalid_constant.main.DataflowConstProp.diff +fn main() { + // An invalid char. + union InvalidChar { + int: u32, + chr: char, + } + let _invalid_char = unsafe { InvalidChar { int: 0x110001 }.chr }; + + // An enum with an invalid tag. Regression test for #93688. + union InvalidTag { + int: u32, + e: E, + } + let _invalid_tag = [unsafe { InvalidTag { int: 4 }.e }]; + + // An enum without variants. Regression test for #94073. + union NoVariants { + int: u32, + empty: Empty, + } + let _enum_without_variants = [unsafe { NoVariants { int: 0 }.empty }]; + + // A non-UTF-8 string slice. Regression test for #75763 and #78520. + struct Str; + let _non_utf8_str: Str<{ unsafe { std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5]) } }>; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/issue-66971.rs b/src/test/mir-opt/dataflow-const-prop/previous/issue-66971.rs new file mode 100644 index 0000000000000..39f0ace71347e --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/issue-66971.rs @@ -0,0 +1,18 @@ +// unit-test: DataflowConstProp +// compile-flags: -Z mir-opt-level=3 + +// Due to a bug in propagating scalar pairs the assertion below used to fail. In the expected +// outputs below, after DataflowConstProp this is how _2 would look like with the bug: +// +// _2 = (const Scalar(0x00) : (), const 0u8); +// +// Which has the wrong type. + +fn encode(this: ((), u8, u8)) { + assert!(this.2 == 0); +} + +// EMIT_MIR issue_66971.main.DataflowConstProp.diff +fn main() { + encode(((), 0, 0)); +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/issue-67019.rs b/src/test/mir-opt/dataflow-const-prop/previous/issue-67019.rs new file mode 100644 index 0000000000000..6d8b482a543ef --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/issue-67019.rs @@ -0,0 +1,13 @@ +// unit-test: DataflowConstProp +// compile-flags: -Z mir-opt-level=3 + +// This used to ICE in const-prop + +fn test(this: ((u8, u8),)) { + assert!((this.0).0 == 1); +} + +// EMIT_MIR issue_67019.main.DataflowConstProp.diff +fn main() { + test(((1, 2),)); +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/issue_66971.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/issue_66971.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..62e94755f1283 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/issue_66971.main.DataflowConstProp.diff @@ -0,0 +1,33 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/issue-66971.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/issue-66971.rs:+1:5: +1:23 + let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 + let mut _3: (); // in scope 0 at $DIR/issue-66971.rs:+1:13: +1:15 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/issue-66971.rs:+1:5: +1:23 + StorageLive(_2); // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 + StorageLive(_3); // scope 0 at $DIR/issue-66971.rs:+1:13: +1:15 + nop; // scope 0 at $DIR/issue-66971.rs:+1:13: +1:15 + Deinit(_2); // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 + nop; // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 + (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 + (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 + StorageDead(_3); // scope 0 at $DIR/issue-66971.rs:+1:21: +1:22 + _1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue-66971.rs:+1:5: +1:23 + // mir::Constant + // + span: $DIR/issue-66971.rs:17:5: 17:11 + // + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value() } + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/issue-66971.rs:+1:22: +1:23 + StorageDead(_1); // scope 0 at $DIR/issue-66971.rs:+1:23: +1:24 + nop; // scope 0 at $DIR/issue-66971.rs:+0:11: +2:2 + return; // scope 0 at $DIR/issue-66971.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..acd6b977d269a --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff @@ -0,0 +1,34 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/issue-67019.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 + let mut _2: ((u8, u8),); // in scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 + let mut _3: (u8, u8); // in scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 + StorageLive(_2); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 + StorageLive(_3); // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 + Deinit(_3); // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 + (_3.0: u8) = const 1_u8; // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 + (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 + Deinit(_2); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 +- (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 ++ (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 + StorageDead(_3); // scope 0 at $DIR/issue-67019.rs:+1:18: +1:19 + _1 = test(move _2) -> bb1; // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 + // mir::Constant + // + span: $DIR/issue-67019.rs:12:5: 12:9 + // + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value() } + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/issue-67019.rs:+1:19: +1:20 + StorageDead(_1); // scope 0 at $DIR/issue-67019.rs:+1:20: +1:21 + nop; // scope 0 at $DIR/issue-67019.rs:+0:11: +2:2 + return; // scope 0 at $DIR/issue-67019.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff new file mode 100644 index 0000000000000..eabe4ec6d0fb6 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff @@ -0,0 +1,37 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/large_array_index.rs:+0:11: +0:11 + let _1: u8; // in scope 0 at $DIR/large_array_index.rs:+2:9: +2:10 + let mut _2: [u8; 5000]; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 + let _3: usize; // in scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 + let mut _4: usize; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + let mut _5: bool; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + scope 1 { + debug x => _1; // in scope 1 at $DIR/large_array_index.rs:+2:9: +2:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/large_array_index.rs:+2:9: +2:10 + StorageLive(_2); // scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 + _2 = [const 0_u8; 5000]; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 + StorageLive(_3); // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 + _3 = const 2_usize; // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 + _4 = const 5000_usize; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 +- _5 = Lt(_3, _4); // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 ++ _5 = const true; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + } + + bb1: { + _1 = _2[_3]; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + StorageDead(_3); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 + StorageDead(_2); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 + nop; // scope 0 at $DIR/large_array_index.rs:+0:11: +3:2 + StorageDead(_1); // scope 0 at $DIR/large_array_index.rs:+3:1: +3:2 + return; // scope 0 at $DIR/large_array_index.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff new file mode 100644 index 0000000000000..eabe4ec6d0fb6 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff @@ -0,0 +1,37 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/large_array_index.rs:+0:11: +0:11 + let _1: u8; // in scope 0 at $DIR/large_array_index.rs:+2:9: +2:10 + let mut _2: [u8; 5000]; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 + let _3: usize; // in scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 + let mut _4: usize; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + let mut _5: bool; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + scope 1 { + debug x => _1; // in scope 1 at $DIR/large_array_index.rs:+2:9: +2:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/large_array_index.rs:+2:9: +2:10 + StorageLive(_2); // scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 + _2 = [const 0_u8; 5000]; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 + StorageLive(_3); // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 + _3 = const 2_usize; // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 + _4 = const 5000_usize; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 +- _5 = Lt(_3, _4); // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 ++ _5 = const true; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + } + + bb1: { + _1 = _2[_3]; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + StorageDead(_3); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 + StorageDead(_2); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 + nop; // scope 0 at $DIR/large_array_index.rs:+0:11: +3:2 + StorageDead(_1); // scope 0 at $DIR/large_array_index.rs:+3:1: +3:2 + return; // scope 0 at $DIR/large_array_index.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.rs b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.rs new file mode 100644 index 0000000000000..a1002401f57b6 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.rs @@ -0,0 +1,7 @@ +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +// EMIT_MIR large_array_index.main.DataflowConstProp.diff +fn main() { + // check that we don't propagate this, because it's too large + let x: u8 = [0_u8; 5000][2]; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs new file mode 100644 index 0000000000000..e169135e0acde --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs @@ -0,0 +1,11 @@ +// unit-test +// compile-flags: -O -Zmir-opt-level=4 + +// EMIT_MIR mult_by_zero.test.DataflowConstProp.diff +fn test(x: i32) -> i32 { + x * 0 +} + +fn main() { + test(10); +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff new file mode 100644 index 0000000000000..0f1d49e3888b1 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff @@ -0,0 +1,18 @@ +- // MIR for `test` before DataflowConstProp ++ // MIR for `test` after DataflowConstProp + + fn test(_1: i32) -> i32 { + debug x => _1; // in scope 0 at $DIR/mult_by_zero.rs:+0:9: +0:10 + let mut _0: i32; // return place in scope 0 at $DIR/mult_by_zero.rs:+0:21: +0:24 + let mut _2: i32; // in scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:4 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:4 + _2 = _1; // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:4 +- _0 = Mul(move _2, const 0_i32); // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:8 ++ _0 = const 0_i32; // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:8 + StorageDead(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:7: +1:8 + return; // scope 0 at $DIR/mult_by_zero.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..94724a676c490 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff @@ -0,0 +1,28 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/mutable_variable.rs:+1:9: +1:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/mutable_variable.rs:+1:9: +1:14 + let _2: i32; // in scope 1 at $DIR/mutable_variable.rs:+3:9: +3:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/mutable_variable.rs:+3:9: +3:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable.rs:+1:9: +1:14 + _1 = const 42_i32; // scope 0 at $DIR/mutable_variable.rs:+1:17: +1:19 + _1 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+2:5: +2:11 + StorageLive(_2); // scope 1 at $DIR/mutable_variable.rs:+3:9: +3:10 +- _2 = _1; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 ++ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 + nop; // scope 0 at $DIR/mutable_variable.rs:+0:11: +4:2 + StorageDead(_2); // scope 1 at $DIR/mutable_variable.rs:+4:1: +4:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable.rs:+4:1: +4:2 + return; // scope 0 at $DIR/mutable_variable.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs new file mode 100644 index 0000000000000..055b7f158da09 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs @@ -0,0 +1,9 @@ +// unit-test +// compile-flags: -O + +// EMIT_MIR mutable_variable.main.DataflowConstProp.diff +fn main() { + let mut x = 42; + x = 99; + let y = x; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..adff27af3b347 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff @@ -0,0 +1,30 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +0:11 + let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 + let _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 + Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 + (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 + (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 + (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13 + StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 +- _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 ++ _2 = const (42_i32, 99_i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 + nop; // scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +4:2 + StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 + return; // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs new file mode 100644 index 0000000000000..854c2d3b8a800 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs @@ -0,0 +1,9 @@ +// unit-test +// compile-flags: -O + +// EMIT_MIR mutable_variable_aggregate.main.DataflowConstProp.diff +fn main() { + let mut x = (42, 43); + x.1 = 99; + let y = x; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..8c3f4b9261804 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff @@ -0,0 +1,36 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+0:11: +0:11 + let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:9: +1:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:9: +1:14 + let _2: &mut (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10 + scope 2 { + debug z => _2; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10 + let _3: (i32, i32); // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 + scope 3 { + debug y => _3; // in scope 3 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:9: +1:14 + Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25 + (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25 + (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25 + StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10 + _2 = &mut _1; // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:13: +2:19 + ((*_2).1: i32) = const 99_i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+3:5: +3:13 + StorageLive(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 + _3 = _1; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14 + nop; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+0:11: +5:2 + StorageDead(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 + StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 + return; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:2: +5:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs new file mode 100644 index 0000000000000..18df3596cff18 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs @@ -0,0 +1,10 @@ +// unit-test +// compile-flags: -O + +// EMIT_MIR mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff +fn main() { + let mut x = (42, 43); + let z = &mut x; + z.1 = 99; + let y = x; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..e7d64c4f451a9 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff @@ -0,0 +1,35 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+0:11: +0:11 + let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14 + let _2: i32; // in scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:9: +4:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:9: +4:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14 + _1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:29: +1:34 + // mir::Constant + // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:29: 6:32 + // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value() } + } + + bb1: { + (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+2:5: +2:13 + (_1.0: i32) = const 42_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+3:5: +3:13 + StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:9: +4:10 +- _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 ++ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 + nop; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+0:11: +5:2 + StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2 + return; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:2: +5:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs new file mode 100644 index 0000000000000..39a77ba178946 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs @@ -0,0 +1,15 @@ +// unit-test +// compile-flags: -O + +// EMIT_MIR mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff +fn main() { + let mut x: (i32, i32) = foo(); + x.1 = 99; + x.0 = 42; + let y = x.1; +} + +#[inline(never)] +fn foo() -> (i32, i32) { + unimplemented!() +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..783aaacca3c04 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff @@ -0,0 +1,48 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +0:11 + let mut _1: u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14 + let _2: (); // in scope 0 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 + let mut _3: u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 + let mut _4: *mut u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 + scope 1 { + debug x => _1; // in scope 1 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14 + let _5: u32; // in scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 + scope 2 { + } + scope 3 { + debug y => _5; // in scope 3 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14 + _1 = const 42_u32; // scope 0 at $DIR/mutable_variable_no_prop.rs:+1:17: +1:19 + StorageLive(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 + StorageLive(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 + StorageLive(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 + _4 = const {alloc1: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 + // mir::Constant + // + span: $DIR/mutable_variable_no_prop.rs:10:13: 10:19 + // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) } + _3 = (*_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 + _1 = move _3; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19 + StorageDead(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:18: +3:19 + StorageDead(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:19: +3:20 + nop; // scope 2 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 + StorageDead(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:+4:5: +4:6 + StorageLive(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 + _5 = _1; // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:13: +5:14 + nop; // scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +6:2 + StorageDead(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 + return; // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:2: +6:2 + } + } + + alloc1 (static: STATIC, size: 4, align: 4) { + 2a 00 00 00 │ *... + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs new file mode 100644 index 0000000000000..26f9cab5cd44f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs @@ -0,0 +1,13 @@ +// unit-test +// compile-flags: -O + +static mut STATIC: u32 = 42; + +// EMIT_MIR mutable_variable_no_prop.main.DataflowConstProp.diff +fn main() { + let mut x = 42; + unsafe { + x = STATIC; + } + let y = x; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..e9b5236581390 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff @@ -0,0 +1,54 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 + let mut _3: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + scope 1 { + debug a => _1; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 + let mut _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + scope 2 { + debug x => _2; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + let _4: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + scope 3 { + debug y => _4; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + let _5: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 + scope 4 { + debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 + _1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:13: +1:18 + // mir::Constant + // + span: $DIR/mutable_variable_unprop_assign.rs:6:13: 6:16 + // + literal: Const { ty: fn() -> i32 {foo}, val: Value() } + } + + bb1: { + StorageLive(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + Deinit(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 + (_2.0: i32) = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 + (_2.1: i32) = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 + StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + _3 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + (_2.1: i32) = move _3; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12 + StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + StorageLive(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + _4 = (_2.1: i32); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 + StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 +- _5 = (_2.0: i32); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 ++ _5 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 + nop; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +6:2 + StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageDead(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:2: +6:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs new file mode 100644 index 0000000000000..92da91682d160 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs @@ -0,0 +1,16 @@ +// unit-test +// compile-flags: -O + +// EMIT_MIR mutable_variable_unprop_assign.main.DataflowConstProp.diff +fn main() { + let a = foo(); + let mut x: (i32, i32) = (1, 2); + x.1 = a; + let y = x.1; + let z = x.0; // this could theoretically be allowed, but we can't handle it right now +} + +#[inline(never)] +fn foo() -> i32 { + unimplemented!() +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff new file mode 100644 index 0000000000000..43afabda7f631 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff @@ -0,0 +1,68 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + let mut _2: (i32, bool); // in scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + let mut _4: [i32; 6]; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 + let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 + let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + scope 1 { + debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + scope 2 { + debug y => _3; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + let _8: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + scope 3 { + debug z => _8; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 +- _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 +- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 ++ _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + } + + bb1: { +- _1 = move (_2.0: i32); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 ++ _1 = const 4_i32; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + StorageLive(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + StorageLive(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 + _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 + StorageLive(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 + _5 = const 3_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 + _6 = const 6_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 +- _7 = Lt(_5, _6); // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 +- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 ++ _7 = const true; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + } + + bb2: { +- _3 = _4[_5]; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 ++ _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 + StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 + StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 +- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 ++ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 + nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 + StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff new file mode 100644 index 0000000000000..43afabda7f631 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff @@ -0,0 +1,68 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + let mut _2: (i32, bool); // in scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + let mut _4: [i32; 6]; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 + let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 + let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + scope 1 { + debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + scope 2 { + debug y => _3; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + let _8: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + scope 3 { + debug z => _8; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 +- _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 +- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 ++ _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + } + + bb1: { +- _1 = move (_2.0: i32); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 ++ _1 = const 4_i32; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + StorageLive(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + StorageLive(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 + _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 + StorageLive(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 + _5 = const 3_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 + _6 = const 6_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 +- _7 = Lt(_5, _6); // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 +- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 ++ _7 = const true; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + } + + bb2: { +- _3 = _4[_5]; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 ++ _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 + StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 + StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 +- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 ++ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 + nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 + StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir new file mode 100644 index 0000000000000..75cea8ad2cebf --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir @@ -0,0 +1,27 @@ +// MIR for `main` after SimplifyLocals + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + scope 1 { + debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + scope 3 { + debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 + } +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir new file mode 100644 index 0000000000000..75cea8ad2cebf --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir @@ -0,0 +1,27 @@ +// MIR for `main` after SimplifyLocals + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + scope 1 { + debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + scope 3 { + debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 + StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 + StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 + StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 + return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 + } +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.rs b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.rs new file mode 100644 index 0000000000000..189a080dbef78 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.rs @@ -0,0 +1,16 @@ +// unit-test +// compile-flags: -C overflow-checks=on + +struct Point { + x: u32, + y: u32, +} + +// EMIT_MIR_FOR_EACH_BIT_WIDTH +// EMIT_MIR optimizes_into_variable.main.DataflowConstProp.diff +// EMIT_MIR optimizes_into_variable.main.SimplifyLocals.after.mir +fn main() { + let x = 2 + 2; + let y = [0, 1, 2, 3, 4, 5][3]; + let z = (Point { x: 12, y: 42 }).y; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..2aeb0bb9e0e26 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff @@ -0,0 +1,48 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/read_immutable_static.rs:+0:11: +0:11 + let _1: u8; // in scope 0 at $DIR/read_immutable_static.rs:+1:9: +1:10 + let mut _2: u8; // in scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 + let mut _3: &u8; // in scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 + let mut _4: u8; // in scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 + let mut _5: &u8; // in scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 + scope 1 { + debug x => _1; // in scope 1 at $DIR/read_immutable_static.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/read_immutable_static.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 + StorageLive(_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 + _3 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 + // mir::Constant + // + span: $DIR/read_immutable_static.rs:8:13: 8:16 + // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } +- _2 = (*_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 ++ _2 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 + StorageLive(_4); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 + StorageLive(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 + _5 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 + // mir::Constant + // + span: $DIR/read_immutable_static.rs:8:19: 8:22 + // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } +- _4 = (*_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 +- _1 = Add(move _2, move _4); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22 ++ _4 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 ++ _1 = const 4_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22 + StorageDead(_4); // scope 0 at $DIR/read_immutable_static.rs:+1:21: +1:22 + StorageDead(_2); // scope 0 at $DIR/read_immutable_static.rs:+1:21: +1:22 + StorageDead(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23 + StorageDead(_3); // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23 + nop; // scope 0 at $DIR/read_immutable_static.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/read_immutable_static.rs:+2:1: +2:2 + return; // scope 0 at $DIR/read_immutable_static.rs:+2:2: +2:2 + } + } + + alloc1 (static: FOO, size: 1, align: 1) { + 02 │ . + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs new file mode 100644 index 0000000000000..0ca5668fb8629 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs @@ -0,0 +1,9 @@ +// unit-test +// compile-flags: -O + +static FOO: u8 = 2; + +// EMIT_MIR read_immutable_static.main.DataflowConstProp.diff +fn main() { + let x = FOO + FOO; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..eb55ab0f1b261 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff @@ -0,0 +1,27 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/ref_deref.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 + let mut _2: &i32; // in scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + let _3: i32; // in scope 0 at $DIR/ref_deref.rs:+1:8: +1:9 + let mut _4: &i32; // in scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 + StorageLive(_2); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + // mir::Constant + // + span: $DIR/ref_deref.rs:5:6: 5:10 + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } + _2 = _4; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 +- _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 ++ _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 + StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 + StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 + nop; // scope 0 at $DIR/ref_deref.rs:+0:11: +2:2 + return; // scope 0 at $DIR/ref_deref.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff new file mode 100644 index 0000000000000..d141d2cf87bb7 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff @@ -0,0 +1,30 @@ +- // MIR for `main` before PromoteTemps ++ // MIR for `main` after PromoteTemps + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/ref_deref.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 + let mut _2: &i32; // in scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + let _3: i32; // in scope 0 at $DIR/ref_deref.rs:+1:8: +1:9 ++ let mut _4: &i32; // in scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 + StorageLive(_2); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 +- StorageLive(_3); // scope 0 at $DIR/ref_deref.rs:+1:8: +1:9 +- _3 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:+1:8: +1:9 +- _2 = &_3; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 ++ _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 ++ // mir::Constant ++ // + span: $DIR/ref_deref.rs:5:6: 5:10 ++ // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } ++ _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 +- StorageDead(_3); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 + StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 + StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 + _0 = const (); // scope 0 at $DIR/ref_deref.rs:+0:11: +2:2 + return; // scope 0 at $DIR/ref_deref.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs new file mode 100644 index 0000000000000..ee9426dd906ea --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs @@ -0,0 +1,6 @@ +// EMIT_MIR ref_deref.main.PromoteTemps.diff +// EMIT_MIR ref_deref.main.DataflowConstProp.diff + +fn main() { + *(&4); +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..66828e5013c9f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff @@ -0,0 +1,26 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/ref_deref_project.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 + let mut _2: &i32; // in scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + let _3: (i32, i32); // in scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14 + let mut _4: &(i32, i32); // in scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 + StorageLive(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + // mir::Constant + // + span: $DIR/ref_deref_project.rs:6:6: 6:17 + // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } + _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 + StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 + StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 + nop; // scope 0 at $DIR/ref_deref_project.rs:+0:11: +2:2 + return; // scope 0 at $DIR/ref_deref_project.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff new file mode 100644 index 0000000000000..6f3a060a1260a --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff @@ -0,0 +1,30 @@ +- // MIR for `main` before PromoteTemps ++ // MIR for `main` after PromoteTemps + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/ref_deref_project.rs:+0:11: +0:11 + let _1: i32; // in scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 + let mut _2: &i32; // in scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + let _3: (i32, i32); // in scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14 ++ let mut _4: &(i32, i32); // in scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 + StorageLive(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 +- StorageLive(_3); // scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14 +- _3 = (const 4_i32, const 5_i32); // scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14 +- _2 = &(_3.1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 ++ _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 ++ // mir::Constant ++ // + span: $DIR/ref_deref_project.rs:6:6: 6:17 ++ // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } ++ _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 +- StorageDead(_3); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 + StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 + StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 + _0 = const (); // scope 0 at $DIR/ref_deref_project.rs:+0:11: +2:2 + return; // scope 0 at $DIR/ref_deref_project.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs new file mode 100644 index 0000000000000..b28fb320d33e4 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs @@ -0,0 +1,7 @@ +// unit-test +// EMIT_MIR ref_deref_project.main.PromoteTemps.diff +// EMIT_MIR ref_deref_project.main.DataflowConstProp.diff + +fn main() { + *(&(4, 5).1); // This does not currently propagate (#67862) +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..7581b852a89b0 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff @@ -0,0 +1,29 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +0:11 + let mut _1: *const fn(); // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41 + let mut _2: usize; // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 + let mut _3: fn(); // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 + scope 1 { + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41 + StorageLive(_2); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 + StorageLive(_3); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 + _3 = main as fn() (Pointer(ReifyFnPointer)); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 + // mir::Constant + // + span: $DIR/reify_fn_ptr.rs:4:13: 4:17 + // + literal: Const { ty: fn() {main}, val: Value() } + _2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 + StorageDead(_3); // scope 0 at $DIR/reify_fn_ptr.rs:+1:25: +1:26 + _1 = move _2 as *const fn() (PointerFromExposedAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41 + StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:+1:40: +1:41 + StorageDead(_1); // scope 0 at $DIR/reify_fn_ptr.rs:+1:41: +1:42 + nop; // scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +2:2 + return; // scope 0 at $DIR/reify_fn_ptr.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs b/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs new file mode 100644 index 0000000000000..00205a2963080 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs @@ -0,0 +1,5 @@ +// EMIT_MIR reify_fn_ptr.main.DataflowConstProp.diff + +fn main() { + let _ = main as usize as *const fn(); +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff new file mode 100644 index 0000000000000..8534710bf369f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff @@ -0,0 +1,43 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/repeat.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/repeat.rs:+1:9: +1:10 + let mut _2: u32; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 + let mut _3: [u32; 8]; // in scope 0 at $DIR/repeat.rs:+1:18: +1:25 + let _4: usize; // in scope 0 at $DIR/repeat.rs:+1:26: +1:27 + let mut _5: usize; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 + let mut _6: bool; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 + scope 1 { + debug x => _1; // in scope 1 at $DIR/repeat.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/repeat.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + StorageLive(_3); // scope 0 at $DIR/repeat.rs:+1:18: +1:25 + _3 = [const 42_u32; 8]; // scope 0 at $DIR/repeat.rs:+1:18: +1:25 + StorageLive(_4); // scope 0 at $DIR/repeat.rs:+1:26: +1:27 + _4 = const 2_usize; // scope 0 at $DIR/repeat.rs:+1:26: +1:27 + _5 = const 8_usize; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 +- _6 = Lt(_4, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 ++ _6 = const true; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + } + + bb1: { +- _2 = _3[_4]; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 +- _1 = Add(move _2, const 0_u32); // scope 0 at $DIR/repeat.rs:+1:18: +1:32 ++ _2 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 ++ _1 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:32 + StorageDead(_2); // scope 0 at $DIR/repeat.rs:+1:31: +1:32 + StorageDead(_4); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 + StorageDead(_3); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 + nop; // scope 0 at $DIR/repeat.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/repeat.rs:+2:1: +2:2 + return; // scope 0 at $DIR/repeat.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff new file mode 100644 index 0000000000000..8534710bf369f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff @@ -0,0 +1,43 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/repeat.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/repeat.rs:+1:9: +1:10 + let mut _2: u32; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 + let mut _3: [u32; 8]; // in scope 0 at $DIR/repeat.rs:+1:18: +1:25 + let _4: usize; // in scope 0 at $DIR/repeat.rs:+1:26: +1:27 + let mut _5: usize; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 + let mut _6: bool; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 + scope 1 { + debug x => _1; // in scope 1 at $DIR/repeat.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/repeat.rs:+1:9: +1:10 + StorageLive(_2); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + StorageLive(_3); // scope 0 at $DIR/repeat.rs:+1:18: +1:25 + _3 = [const 42_u32; 8]; // scope 0 at $DIR/repeat.rs:+1:18: +1:25 + StorageLive(_4); // scope 0 at $DIR/repeat.rs:+1:26: +1:27 + _4 = const 2_usize; // scope 0 at $DIR/repeat.rs:+1:26: +1:27 + _5 = const 8_usize; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 +- _6 = Lt(_4, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 ++ _6 = const true; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + } + + bb1: { +- _2 = _3[_4]; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 +- _1 = Add(move _2, const 0_u32); // scope 0 at $DIR/repeat.rs:+1:18: +1:32 ++ _2 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 ++ _1 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:32 + StorageDead(_2); // scope 0 at $DIR/repeat.rs:+1:31: +1:32 + StorageDead(_4); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 + StorageDead(_3); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 + nop; // scope 0 at $DIR/repeat.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/repeat.rs:+2:1: +2:2 + return; // scope 0 at $DIR/repeat.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.rs b/src/test/mir-opt/dataflow-const-prop/previous/repeat.rs new file mode 100644 index 0000000000000..ade87676869ee --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/repeat.rs @@ -0,0 +1,7 @@ +// compile-flags: -O + +// EMIT_MIR_FOR_EACH_BIT_WIDTH +// EMIT_MIR repeat.main.DataflowConstProp.diff +fn main() { + let x: u32 = [42; 8][2] + 0; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff new file mode 100644 index 0000000000000..97966e86a2dc8 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff @@ -0,0 +1,21 @@ +- // MIR for `add` before DataflowConstProp ++ // MIR for `add` after DataflowConstProp + + fn add() -> u32 { + let mut _0: u32; // return place in scope 0 at $DIR/return_place.rs:+0:13: +0:16 + let mut _1: (u32, bool); // in scope 0 at $DIR/return_place.rs:+1:5: +1:10 + + bb0: { +- _1 = CheckedAdd(const 2_u32, const 2_u32); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 +- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 ++ _1 = const (4_u32, false); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 + } + + bb1: { +- _0 = move (_1.0: u32); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 ++ _0 = const 4_u32; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 + return; // scope 0 at $DIR/return_place.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir new file mode 100644 index 0000000000000..ececd9942838d --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir @@ -0,0 +1,10 @@ +// MIR for `add` before PreCodegen + +fn add() -> u32 { + let mut _0: u32; // return place in scope 0 at $DIR/return_place.rs:+0:13: +0:16 + + bb0: { + _0 = const 4_u32; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 + return; // scope 0 at $DIR/return_place.rs:+2:2: +2:2 + } +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/return_place.rs b/src/test/mir-opt/dataflow-const-prop/previous/return_place.rs new file mode 100644 index 0000000000000..d4cac2c76ddcd --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/return_place.rs @@ -0,0 +1,11 @@ +// compile-flags: -C overflow-checks=on + +// EMIT_MIR return_place.add.DataflowConstProp.diff +// EMIT_MIR return_place.add.PreCodegen.before.mir +fn add() -> u32 { + 2 + 2 +} + +fn main() { + add(); +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..955c3e956c8e7 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff @@ -0,0 +1,35 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/scalar_literal_propagation.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10 + let _2: (); // in scope 0 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 + let mut _3: u32; // in scope 0 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10 + _1 = const 1_u32; // scope 0 at $DIR/scalar_literal_propagation.rs:+1:13: +1:14 + StorageLive(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 + StorageLive(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 +- _3 = _1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 +- _2 = consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 ++ _3 = const 1_u32; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 ++ _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 + // mir::Constant + // + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12 + // + literal: Const { ty: fn(u32) {consume}, val: Value() } + } + + bb1: { + StorageDead(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:14: +2:15 + StorageDead(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:15: +2:16 + nop; // scope 0 at $DIR/scalar_literal_propagation.rs:+0:11: +3:2 + StorageDead(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+3:1: +3:2 + return; // scope 0 at $DIR/scalar_literal_propagation.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs new file mode 100644 index 0000000000000..00726b6f13de9 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs @@ -0,0 +1,8 @@ +// EMIT_MIR scalar_literal_propagation.main.DataflowConstProp.diff +fn main() { + let x = 1; + consume(x); +} + +#[inline(never)] +fn consume(_: u32) {} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff new file mode 100644 index 0000000000000..d8718409b4b77 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff @@ -0,0 +1,53 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/slice_len.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + let mut _2: &[u32]; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:30 + let mut _3: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + let _4: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + let _5: [u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:7: +1:19 + let _6: usize; // in scope 0 at $DIR/slice_len.rs:+1:31: +1:32 + let mut _7: usize; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + let mut _8: bool; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + let mut _9: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + let mut _10: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + StorageLive(_2); // scope 0 at $DIR/slice_len.rs:+1:5: +1:30 + StorageLive(_3); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + // mir::Constant + // + span: $DIR/slice_len.rs:5:6: 5:19 + // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } + _4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + StorageLive(_10); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _10 = _3; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + StorageDead(_3); // scope 0 at $DIR/slice_len.rs:+1:18: +1:19 + StorageLive(_6); // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 + _6 = const 1_usize; // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 + _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + StorageDead(_10); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 +- _8 = Lt(_6, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 ++ _8 = const true; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + } + + bb1: { +- _1 = (*_2)[_6]; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 ++ _1 = const 2_u32; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + StorageDead(_6); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 + StorageDead(_4); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 + StorageDead(_2); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 + StorageDead(_1); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 + nop; // scope 0 at $DIR/slice_len.rs:+0:11: +2:2 + return; // scope 0 at $DIR/slice_len.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff new file mode 100644 index 0000000000000..d8718409b4b77 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff @@ -0,0 +1,53 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/slice_len.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + let mut _2: &[u32]; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:30 + let mut _3: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + let _4: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + let _5: [u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:7: +1:19 + let _6: usize; // in scope 0 at $DIR/slice_len.rs:+1:31: +1:32 + let mut _7: usize; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + let mut _8: bool; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + let mut _9: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + let mut _10: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + StorageLive(_2); // scope 0 at $DIR/slice_len.rs:+1:5: +1:30 + StorageLive(_3); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + // mir::Constant + // + span: $DIR/slice_len.rs:5:6: 5:19 + // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } + _4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + StorageLive(_10); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _10 = _3; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + StorageDead(_3); // scope 0 at $DIR/slice_len.rs:+1:18: +1:19 + StorageLive(_6); // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 + _6 = const 1_usize; // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 + _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + StorageDead(_10); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 +- _8 = Lt(_6, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 ++ _8 = const true; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + } + + bb1: { +- _1 = (*_2)[_6]; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 ++ _1 = const 2_u32; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + StorageDead(_6); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 + StorageDead(_4); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 + StorageDead(_2); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 + StorageDead(_1); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 + nop; // scope 0 at $DIR/slice_len.rs:+0:11: +2:2 + return; // scope 0 at $DIR/slice_len.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs new file mode 100644 index 0000000000000..224ccb70f8b46 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs @@ -0,0 +1,6 @@ +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +// EMIT_MIR slice_len.main.DataflowConstProp.diff +fn main() { + (&[1u32, 2, 3] as &[u32])[1]; +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..27223fcb2dbbb --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff @@ -0,0 +1,34 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/switch_int.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/switch_int.rs:+1:11: +1:12 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/switch_int.rs:+1:11: +1:12 + _1 = const 1_i32; // scope 0 at $DIR/switch_int.rs:+1:11: +1:12 +- switchInt(_1) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12 ++ switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12 + } + + bb1: { + _0 = foo(const -1_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+3:14: +3:21 + // mir::Constant + // + span: $DIR/switch_int.rs:9:14: 9:17 + // + literal: Const { ty: fn(i32) {foo}, val: Value() } + } + + bb2: { + _0 = foo(const 0_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+2:14: +2:20 + // mir::Constant + // + span: $DIR/switch_int.rs:8:14: 8:17 + // + literal: Const { ty: fn(i32) {foo}, val: Value() } + } + + bb3: { + StorageDead(_1); // scope 0 at $DIR/switch_int.rs:+5:1: +5:2 + return; // scope 0 at $DIR/switch_int.rs:+5:2: +5:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.SimplifyConstCondition-after-const-prop.diff b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.SimplifyConstCondition-after-const-prop.diff new file mode 100644 index 0000000000000..74f9eafe42061 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.SimplifyConstCondition-after-const-prop.diff @@ -0,0 +1,34 @@ +- // MIR for `main` before SimplifyConstCondition-after-const-prop ++ // MIR for `main` after SimplifyConstCondition-after-const-prop + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/switch_int.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/switch_int.rs:+1:11: +1:12 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/switch_int.rs:+1:11: +1:12 + _1 = const 1_i32; // scope 0 at $DIR/switch_int.rs:+1:11: +1:12 +- switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12 ++ goto -> bb2; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12 + } + + bb1: { + _0 = foo(const -1_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+3:14: +3:21 + // mir::Constant + // + span: $DIR/switch_int.rs:9:14: 9:17 + // + literal: Const { ty: fn(i32) {foo}, val: Value() } + } + + bb2: { + _0 = foo(const 0_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+2:14: +2:20 + // mir::Constant + // + span: $DIR/switch_int.rs:8:14: 8:17 + // + literal: Const { ty: fn(i32) {foo}, val: Value() } + } + + bb3: { + StorageDead(_1); // scope 0 at $DIR/switch_int.rs:+5:1: +5:2 + return; // scope 0 at $DIR/switch_int.rs:+5:2: +5:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.rs b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.rs new file mode 100644 index 0000000000000..eec51c5c48c25 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.rs @@ -0,0 +1,11 @@ +#[inline(never)] +fn foo(_: i32) {} + +// EMIT_MIR switch_int.main.DataflowConstProp.diff +// EMIT_MIR switch_int.main.SimplifyConstCondition-after-const-prop.diff +fn main() { + match 1 { + 1 => foo(0), + _ => foo(-1), + } +} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..176fd70fbef31 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff @@ -0,0 +1,36 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/tuple_literal_propagation.rs:+0:11: +0:11 + let _1: (u32, u32); // in scope 0 at $DIR/tuple_literal_propagation.rs:+1:9: +1:10 + let _2: (); // in scope 0 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 + let mut _3: (u32, u32); // in scope 0 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/tuple_literal_propagation.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:9: +1:10 + Deinit(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 + (_1.0: u32) = const 1_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 + (_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 + StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 + StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 +- _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 ++ _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 + _2 = consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 + // mir::Constant + // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12 + // + literal: Const { ty: fn((u32, u32)) {consume}, val: Value() } + } + + bb1: { + StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15 + StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16 + nop; // scope 0 at $DIR/tuple_literal_propagation.rs:+0:11: +4:2 + StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2 + return; // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs new file mode 100644 index 0000000000000..41085838127f6 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs @@ -0,0 +1,9 @@ +// EMIT_MIR tuple_literal_propagation.main.DataflowConstProp.diff +fn main() { + let x = (1, 2); + + consume(x); +} + +#[inline(never)] +fn consume(_: (u32, u32)) {} From 4cda6e5401980f749db0b847e1521ad1e1e78bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 27 Sep 2022 16:42:51 +0200 Subject: [PATCH 29/76] Update test results --- ...ay_index.main.DataflowConstProp.32bit.diff | 10 +++--- ...ay_index.main.DataflowConstProp.64bit.diff | 10 +++--- ...op_div_by_zero.main.DataflowConstProp.diff | 8 +++-- ...op_mod_by_zero.main.DataflowConstProp.diff | 24 +++++--------- ...r_slices.main.DataflowConstProp.32bit.diff | 6 ++-- ...r_slices.main.DataflowConstProp.64bit.diff | 6 ++-- ...ean_identities.test.DataflowConstProp.diff | 9 ++--- .../boxes.main.DataflowConstProp.diff | 6 ++-- .../checked_add.main.DataflowConstProp.diff | 3 +- ...implification.hello.DataflowConstProp.diff | 8 ++--- ...simplification.hello.PreCodegen.before.mir | 2 +- ...riminant.main.DataflowConstProp.32bit.diff | 6 ++-- ...riminant.main.DataflowConstProp.64bit.diff | 6 ++-- .../indirect.main.DataflowConstProp.diff | 4 +-- ...valid_constant.main.DataflowConstProp.diff | 33 +++++++++---------- .../issue_67019.main.DataflowConstProp.diff | 3 +- ...ay_index.main.DataflowConstProp.32bit.diff | 6 ++-- ...ay_index.main.DataflowConstProp.64bit.diff | 6 ++-- .../mult_by_zero.test.DataflowConstProp.diff | 13 ++++---- ...table_variable.main.DataflowConstProp.diff | 3 +- ...able_aggregate.main.DataflowConstProp.diff | 3 +- ...e_partial_read.main.DataflowConstProp.diff | 3 +- ..._unprop_assign.main.DataflowConstProp.diff | 3 +- ...variable.main.DataflowConstProp.32bit.diff | 33 ++++++++----------- ...variable.main.DataflowConstProp.64bit.diff | 33 ++++++++----------- ...mutable_static.main.DataflowConstProp.diff | 9 ++--- .../ref_deref.main.DataflowConstProp.diff | 3 +- .../repeat.main.DataflowConstProp.32bit.diff | 12 +++---- .../repeat.main.DataflowConstProp.64bit.diff | 12 +++---- .../return_place.add.DataflowConstProp.diff | 9 ++--- ...al_propagation.main.DataflowConstProp.diff | 6 ++-- ...lice_len.main.DataflowConstProp.32bit.diff | 9 ++--- ...lice_len.main.DataflowConstProp.64bit.diff | 9 ++--- .../switch_int.main.DataflowConstProp.diff | 3 +- ...al_propagation.main.DataflowConstProp.diff | 3 +- 35 files changed, 122 insertions(+), 200 deletions(-) diff --git a/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff index 8cbc4a72e800f..00eb9d0e2006a 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff @@ -18,17 +18,15 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30 StorageLive(_3); // scope 0 at $DIR/array_index.rs:+1:31: +1:32 _3 = const 2_usize; // scope 0 at $DIR/array_index.rs:+1:31: +1:32 -- _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 + _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - _5 = Lt(_3, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ _4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ _5 = const true; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ _5 = Lt(const 2_usize, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 } bb1: { -- _1 = _2[_3]; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ _1 = const 2_u32; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 + _1 = _2[_3]; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 StorageDead(_3); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 StorageDead(_2); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 _0 = const (); // scope 0 at $DIR/array_index.rs:+0:11: +2:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff index 8cbc4a72e800f..00eb9d0e2006a 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff @@ -18,17 +18,15 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30 StorageLive(_3); // scope 0 at $DIR/array_index.rs:+1:31: +1:32 _3 = const 2_usize; // scope 0 at $DIR/array_index.rs:+1:31: +1:32 -- _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 + _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - _5 = Lt(_3, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ _4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ _5 = const true; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ _5 = Lt(const 2_usize, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 } bb1: { -- _1 = _2[_3]; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ _1 = const 2_u32; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 + _1 = _2[_3]; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 StorageDead(_3); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 StorageDead(_2); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 _0 = const (); // scope 0 at $DIR/array_index.rs:+0:11: +2:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff index 47af40988ddd3..1744b7b976afd 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff @@ -24,9 +24,10 @@ StorageLive(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 - _3 = _1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 - _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 +- assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + _3 = const 0_i32; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 + _4 = const true; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 - assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 ++ assert(!const true, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 } bb1: { @@ -37,11 +38,12 @@ + _5 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + _6 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + _7 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 ++ assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 } bb2: { - _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 +- _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 ++ _2 = Div(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 StorageDead(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 _0 = const (); // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2 StorageDead(_2); // scope 1 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff index 0069d3ce53443..59bd12670155d 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff @@ -22,28 +22,20 @@ _1 = const 0_i32; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:13: +1:14 StorageLive(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11 StorageLive(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 -- _3 = _1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 -- _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -- assert(!move _4, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ _3 = const 0_i32; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 -+ _4 = const true; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + _3 = const 0_i32; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 + _4 = const true; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 } bb1: { -- _5 = Eq(_3, const -1_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -- _6 = Eq(const 1_i32, const i32::MIN); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -- _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ _5 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ _6 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ _7 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + _5 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + _6 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + _7 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 } bb2: { -- _2 = Rem(const 1_i32, move _3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 StorageDead(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 nop; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+0:11: +3:2 StorageDead(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff index f04715e3b335f..65cd794636766 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff @@ -38,10 +38,8 @@ StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 } bb1: { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff index f04715e3b335f..65cd794636766 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff @@ -38,10 +38,8 @@ StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 } bb1: { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff index 90236fcf0a935..307324d5768d8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff @@ -14,17 +14,14 @@ StorageLive(_3); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 StorageLive(_4); // scope 0 at $DIR/boolean_identities.rs:+1:6: +1:7 _4 = _2; // scope 0 at $DIR/boolean_identities.rs:+1:6: +1:7 -- _3 = BitOr(move _4, const true); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 -+ _3 = const true; // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 + _3 = const true; // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 StorageDead(_4); // scope 0 at $DIR/boolean_identities.rs:+1:14: +1:15 StorageLive(_5); // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 StorageLive(_6); // scope 0 at $DIR/boolean_identities.rs:+1:19: +1:20 _6 = _1; // scope 0 at $DIR/boolean_identities.rs:+1:19: +1:20 -- _5 = BitAnd(move _6, const false); // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 -+ _5 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 + _5 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 StorageDead(_6); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29 -- _0 = BitAnd(move _3, move _5); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:29 -+ _0 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:29 + _0 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:29 StorageDead(_5); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29 StorageDead(_3); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29 return; // scope 0 at $DIR/boolean_identities.rs:+2:2: +2:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff index 2d8604440deb3..501108a7abcf8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff @@ -22,10 +22,8 @@ StorageLive(_1); // scope 0 at $DIR/boxes.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/boxes.rs:+1:13: +1:22 StorageLive(_3); // scope 0 at $DIR/boxes.rs:+1:14: +1:22 -- _4 = SizeOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22 -- _5 = AlignOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22 -+ _4 = const 4_usize; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 -+ _5 = const 4_usize; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 + _4 = SizeOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22 + _5 = AlignOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22 _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 // mir::Constant // + span: $DIR/boxes.rs:13:14: 13:22 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff index 4a40fd27497c4..5371e049664c3 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff @@ -11,9 +11,8 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/checked_add.rs:+1:9: +1:10 -- _2 = CheckedAdd(const 1_u32, const 1_u32); // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 + _2 = CheckedAdd(const 1_u32, const 1_u32); // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 - assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 -+ _2 = const (2_u32, false); // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff index 2faa8422e5ea9..e2e42e72c281d 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff @@ -2,16 +2,14 @@ + // MIR for `hello` after DataflowConstProp fn hello() -> () { - let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:+0:14: +0:14 + let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:+0:15: +0:15 let mut _1: bool; // in scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 let mut _2: !; // in scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL bb0: { StorageLive(_1); // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 -- _1 = const ::NEEDS; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 -- switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 -+ _1 = const false; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 -+ switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 + _1 = const false; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 + switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 } bb1: { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir index 70f9797751131..442ae80776172 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir +++ b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir @@ -1,7 +1,7 @@ // MIR for `hello` before PreCodegen fn hello() -> () { - let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:+0:14: +0:14 + let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:+0:15: +0:15 bb0: { return; // scope 0 at $DIR/control-flow-simplification.rs:+4:2: +4:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff index e527e2e1a5451..f98270b3ff04d 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff @@ -20,10 +20,8 @@ Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 -- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 -- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 -+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 -+ switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 + _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 + switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 } bb1: { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff index e527e2e1a5451..f98270b3ff04d 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff @@ -20,10 +20,8 @@ Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 -- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 -- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 -+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 -+ switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 + _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 + switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 } bb1: { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff index f5b23abfb3bcb..461ed4d8922b8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff @@ -17,8 +17,8 @@ - _3 = CheckedAdd(_2, const 1_u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 - assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 + _2 = const 2_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:25 -+ _3 = const (3_u8, false); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 ++ _3 = CheckedAdd(const 2_u8, const 1_u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 } bb1: { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff index b8713d31ad742..9cf6c1f989cd8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff @@ -36,24 +36,21 @@ StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 Deinit(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 (_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 -- _1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67 -+ _1 = const {transmute(0x00110001): char}; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67 + _1 = const {transmute(0x00110001): char}; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67 StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:+6:69: +6:70 StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21 StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:+13:25: +13:59 StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 Deinit(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 (_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 -- _4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57 -- _3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60 -+ _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57 -+ // mir::Constant -+ // + span: $DIR/invalid_constant.rs:28:34: 28:57 -+ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } -+ _3 = [const Scalar(0x00000004): E]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60 -+ // mir::Constant -+ // + span: $DIR/invalid_constant.rs:28:24: 28:60 -+ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } + _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57 + // mir::Constant + // + span: $DIR/invalid_constant.rs:32:34: 32:57 + // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } + _3 = [const Scalar(0x00000004): E]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60 + // mir::Constant + // + span: $DIR/invalid_constant.rs:32:24: 32:60 + // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60 StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61 StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31 @@ -66,12 +63,12 @@ StorageDead(_7); // scope 3 at $DIR/invalid_constant.rs:+20:73: +20:74 StorageDead(_8); // scope 3 at $DIR/invalid_constant.rs:+20:74: +20:75 StorageLive(_9); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22 - nop; // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2 - StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2 - StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2 - StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2 - StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2 - return; // scope 0 at $DIR/invalid_constant.rs:+27:2: +27:2 + nop; // scope 0 at $DIR/invalid_constant.rs:+0:11: +25:2 + StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:+25:1: +25:2 + StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+25:1: +25:2 + StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+25:1: +25:2 + StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+25:1: +25:2 + return; // scope 0 at $DIR/invalid_constant.rs:+25:2: +25:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff index acd6b977d269a..ddbbb11397229 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff @@ -15,8 +15,7 @@ (_3.0: u8) = const 1_u8; // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 Deinit(_2); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 -- (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 -+ (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 + (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 StorageDead(_3); // scope 0 at $DIR/issue-67019.rs:+1:18: +1:19 _1 = test(move _2) -> bb1; // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 // mir::Constant diff --git a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff index eabe4ec6d0fb6..487b2b74371d8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff @@ -19,10 +19,8 @@ StorageLive(_3); // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 _3 = const 2_usize; // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 _4 = const 5000_usize; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 -- _5 = Lt(_3, _4); // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 -+ _5 = const true; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + _5 = const true; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 } bb1: { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff index eabe4ec6d0fb6..487b2b74371d8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff @@ -19,10 +19,8 @@ StorageLive(_3); // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 _3 = const 2_usize; // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 _4 = const 5000_usize; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 -- _5 = Lt(_3, _4); // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 -+ _5 = const true; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + _5 = const true; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 } bb1: { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff index 0f1d49e3888b1..540cccb3b375f 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff @@ -3,15 +3,14 @@ fn test(_1: i32) -> i32 { debug x => _1; // in scope 0 at $DIR/mult_by_zero.rs:+0:9: +0:10 - let mut _0: i32; // return place in scope 0 at $DIR/mult_by_zero.rs:+0:21: +0:24 - let mut _2: i32; // in scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:4 + let mut _0: i32; // return place in scope 0 at $DIR/mult_by_zero.rs:+0:20: +0:23 + let mut _2: i32; // in scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:6 bb0: { - StorageLive(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:4 - _2 = _1; // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:4 -- _0 = Mul(move _2, const 0_i32); // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:8 -+ _0 = const 0_i32; // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:8 - StorageDead(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:7: +1:8 + StorageLive(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:6 + _2 = _1; // scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:6 + _0 = const 0_i32; // scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:10 + StorageDead(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:9: +1:10 return; // scope 0 at $DIR/mult_by_zero.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff index 94724a676c490..03556e85088e8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff @@ -17,8 +17,7 @@ _1 = const 42_i32; // scope 0 at $DIR/mutable_variable.rs:+1:17: +1:19 _1 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+2:5: +2:11 StorageLive(_2); // scope 1 at $DIR/mutable_variable.rs:+3:9: +3:10 -- _2 = _1; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 -+ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 + _2 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 nop; // scope 0 at $DIR/mutable_variable.rs:+0:11: +4:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable.rs:+4:1: +4:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff index adff27af3b347..7b5be873ee821 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff @@ -19,8 +19,7 @@ (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13 StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 -- _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 -+ _2 = const (42_i32, 99_i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 + _2 = const (42_i32, 99_i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 nop; // scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +4:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff index e7d64c4f451a9..fb396e7a121ad 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff @@ -24,8 +24,7 @@ (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+2:5: +2:13 (_1.0: i32) = const 42_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+3:5: +3:13 StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:9: +4:10 -- _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 -+ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 + _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 nop; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+0:11: +5:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff index e9b5236581390..2f6aeca20763e 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff @@ -41,8 +41,7 @@ StorageLive(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 _4 = (_2.1: i32); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 -- _5 = (_2.0: i32); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 -+ _5 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 + _5 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 nop; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +6:2 StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff index 43afabda7f631..3b77cb6e543c2 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff @@ -9,7 +9,7 @@ let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -24,40 +24,33 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 -- _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 -- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 -+ _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 } bb1: { -- _1 = move (_2.0: i32); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 -+ _1 = const 4_i32; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + _1 = const 4_i32; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 StorageLive(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 StorageLive(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 StorageLive(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 _5 = const 3_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 _6 = const 6_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 -- _7 = Lt(_5, _6); // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 -+ _7 = const true; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + _7 = const true; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 } bb2: { -- _3 = _4[_5]; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 -+ _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 -+ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 - StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 + StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 + Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 + (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 + (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 + _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:39 + StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:39: +3:40 nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff index 43afabda7f631..3b77cb6e543c2 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff @@ -9,7 +9,7 @@ let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -24,40 +24,33 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 -- _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 -- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 -+ _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 } bb1: { -- _1 = move (_2.0: i32); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 -+ _1 = const 4_i32; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 + _1 = const 4_i32; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 StorageLive(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 StorageLive(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 StorageLive(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 _5 = const 3_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 _6 = const 6_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 -- _7 = Lt(_5, _6); // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 -+ _7 = const true; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + _7 = const true; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 } bb2: { -- _3 = _4[_5]; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 -+ _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 + _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 -+ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 - StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 + StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 + Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 + (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 + (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 + _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:39 + StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:39: +3:40 nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff index 2aeb0bb9e0e26..dd3dc9b9e4dbd 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff @@ -20,18 +20,15 @@ // mir::Constant // + span: $DIR/read_immutable_static.rs:8:13: 8:16 // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } -- _2 = (*_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 -+ _2 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 + _2 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 StorageLive(_4); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 StorageLive(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 _5 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 // mir::Constant // + span: $DIR/read_immutable_static.rs:8:19: 8:22 // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } -- _4 = (*_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 -- _1 = Add(move _2, move _4); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22 -+ _4 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 -+ _1 = const 4_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22 + _4 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 + _1 = const 4_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22 StorageDead(_4); // scope 0 at $DIR/read_immutable_static.rs:+1:21: +1:22 StorageDead(_2); // scope 0 at $DIR/read_immutable_static.rs:+1:21: +1:22 StorageDead(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff index eb55ab0f1b261..74c53808e1596 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff @@ -16,8 +16,7 @@ // + span: $DIR/ref_deref.rs:5:6: 5:10 // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } _2 = _4; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 -- _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 -+ _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 + _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 nop; // scope 0 at $DIR/ref_deref.rs:+0:11: +2:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff index 8534710bf369f..f7e60a5a351d8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff @@ -21,17 +21,13 @@ StorageLive(_4); // scope 0 at $DIR/repeat.rs:+1:26: +1:27 _4 = const 2_usize; // scope 0 at $DIR/repeat.rs:+1:26: +1:27 _5 = const 8_usize; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -- _6 = Lt(_4, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -+ _6 = const true; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + _6 = const true; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 } bb1: { -- _2 = _3[_4]; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -- _1 = Add(move _2, const 0_u32); // scope 0 at $DIR/repeat.rs:+1:18: +1:32 -+ _2 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -+ _1 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:32 + _2 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + _1 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:32 StorageDead(_2); // scope 0 at $DIR/repeat.rs:+1:31: +1:32 StorageDead(_4); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 StorageDead(_3); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff index 8534710bf369f..f7e60a5a351d8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff @@ -21,17 +21,13 @@ StorageLive(_4); // scope 0 at $DIR/repeat.rs:+1:26: +1:27 _4 = const 2_usize; // scope 0 at $DIR/repeat.rs:+1:26: +1:27 _5 = const 8_usize; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -- _6 = Lt(_4, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -+ _6 = const true; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + _6 = const true; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 } bb1: { -- _2 = _3[_4]; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -- _1 = Add(move _2, const 0_u32); // scope 0 at $DIR/repeat.rs:+1:18: +1:32 -+ _2 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -+ _1 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:32 + _2 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + _1 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:32 StorageDead(_2); // scope 0 at $DIR/repeat.rs:+1:31: +1:32 StorageDead(_4); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 StorageDead(_3); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff index 97966e86a2dc8..f7a3227f39de8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff @@ -6,15 +6,12 @@ let mut _1: (u32, bool); // in scope 0 at $DIR/return_place.rs:+1:5: +1:10 bb0: { -- _1 = CheckedAdd(const 2_u32, const 2_u32); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 -- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 -+ _1 = const (4_u32, false); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 + _1 = const (4_u32, false); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 } bb1: { -- _0 = move (_1.0: u32); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 -+ _0 = const 4_u32; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 + _0 = const 4_u32; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 return; // scope 0 at $DIR/return_place.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff index 955c3e956c8e7..97609293c9a56 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff @@ -15,10 +15,8 @@ _1 = const 1_u32; // scope 0 at $DIR/scalar_literal_propagation.rs:+1:13: +1:14 StorageLive(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 StorageLive(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 -- _3 = _1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 -- _2 = consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 -+ _3 = const 1_u32; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 -+ _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 + _3 = const 1_u32; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 + _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 // mir::Constant // + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12 // + literal: Const { ty: fn(u32) {consume}, val: Value() } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff index d8718409b4b77..7af3a3881df2c 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff @@ -33,15 +33,12 @@ _6 = const 1_usize; // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 StorageDead(_10); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -- _8 = Lt(_6, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -+ _8 = const true; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + _8 = const true; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 } bb1: { -- _1 = (*_2)[_6]; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -+ _1 = const 2_u32; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + _1 = const 2_u32; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 StorageDead(_6); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 StorageDead(_4); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 StorageDead(_2); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff index d8718409b4b77..7af3a3881df2c 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff @@ -33,15 +33,12 @@ _6 = const 1_usize; // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 StorageDead(_10); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -- _8 = Lt(_6, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -+ _8 = const true; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + _8 = const true; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 } bb1: { -- _1 = (*_2)[_6]; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -+ _1 = const 2_u32; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + _1 = const 2_u32; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 StorageDead(_6); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 StorageDead(_4); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 StorageDead(_2); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff index 27223fcb2dbbb..b2f98061d2294 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff @@ -8,8 +8,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/switch_int.rs:+1:11: +1:12 _1 = const 1_i32; // scope 0 at $DIR/switch_int.rs:+1:11: +1:12 -- switchInt(_1) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12 -+ switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12 + switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12 } bb1: { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff index 176fd70fbef31..7fcde2be17149 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff @@ -17,8 +17,7 @@ (_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 -- _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 -+ _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 + _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 _2 = consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 // mir::Constant // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12 From 97a69a76705e76ac59d054ebfde5ddc954237a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 27 Sep 2022 17:28:32 +0200 Subject: [PATCH 30/76] Add some more unit-test directives --- ...op_mod_by_zero.main.DataflowConstProp.diff | 26 ++++++++++++------- .../previous/bad_op_mod_by_zero.rs | 1 + ...r_slices.main.DataflowConstProp.32bit.diff | 12 +++++---- ...r_slices.main.DataflowConstProp.64bit.diff | 12 +++++---- .../previous/bad_op_unsafe_oob_for_slices.rs | 1 + .../previous/mult_by_zero.rs | 3 +-- .../mult_by_zero.test.DataflowConstProp.diff | 2 +- ...table_variable.main.DataflowConstProp.diff | 5 ++-- .../previous/mutable_variable.rs | 3 +-- ...able_aggregate.main.DataflowConstProp.diff | 4 +-- .../previous/mutable_variable_aggregate.rs | 3 +-- ...regate_mut_ref.main.DataflowConstProp.diff | 2 +- .../mutable_variable_aggregate_mut_ref.rs | 3 +-- ...e_partial_read.main.DataflowConstProp.diff | 7 ++--- ...mutable_variable_aggregate_partial_read.rs | 3 +-- ...riable_no_prop.main.DataflowConstProp.diff | 6 ++--- .../previous/mutable_variable_no_prop.rs | 3 +-- ..._unprop_assign.main.DataflowConstProp.diff | 7 ++--- .../mutable_variable_unprop_assign.rs | 3 +-- ...mutable_static.main.DataflowConstProp.diff | 12 ++++----- .../previous/read_immutable_static.rs | 3 +-- .../ref_deref.main.DataflowConstProp.diff | 8 +++--- .../previous/ref_deref.main.PromoteTemps.diff | 2 +- .../dataflow-const-prop/previous/ref_deref.rs | 1 + ..._deref_project.main.DataflowConstProp.diff | 2 +- .../previous/ref_deref_project.rs | 2 +- .../reify_fn_ptr.main.DataflowConstProp.diff | 4 +-- .../previous/reify_fn_ptr.rs | 1 + .../repeat.main.DataflowConstProp.32bit.diff | 14 +++++----- .../repeat.main.DataflowConstProp.64bit.diff | 14 +++++----- .../dataflow-const-prop/previous/repeat.rs | 2 +- .../return_place.add.DataflowConstProp.diff | 8 +++--- .../return_place.add.PreCodegen.before.mir | 6 +++++ .../previous/return_place.rs | 1 + ...al_propagation.main.DataflowConstProp.diff | 10 ++++--- .../previous/scalar_literal_propagation.rs | 1 + ...lice_len.main.DataflowConstProp.32bit.diff | 22 +++++++--------- ...lice_len.main.DataflowConstProp.64bit.diff | 22 +++++++--------- .../dataflow-const-prop/previous/slice_len.rs | 1 + ...al_propagation.main.DataflowConstProp.diff | 6 ++--- .../previous/tuple_literal_propagation.rs | 1 + 41 files changed, 137 insertions(+), 112 deletions(-) diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff index 59bd12670155d..cc8dea75c9cb9 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff @@ -22,22 +22,30 @@ _1 = const 0_i32; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:13: +1:14 StorageLive(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11 StorageLive(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 - _3 = const 0_i32; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 - _4 = const true; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- _3 = _1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 +- _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- assert(!move _4, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ _3 = const 0_i32; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 ++ _4 = const true; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 } bb1: { - _5 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - _6 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - _7 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- _5 = Eq(_3, const -1_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- _6 = Eq(const 1_i32, const i32::MIN); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ _5 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ _6 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ _7 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 } bb2: { - _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 +- _2 = Rem(const 1_i32, move _3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 ++ _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 StorageDead(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 - nop; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+0:11: +3:2 + _0 = const (); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+0:11: +3:2 StorageDead(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2 StorageDead(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2 return; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:2: +3:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs index 6a7a82e5034b0..ad30a5b6242ed 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs @@ -1,3 +1,4 @@ +// unit-test: DataflowConstProp // EMIT_MIR bad_op_mod_by_zero.main.DataflowConstProp.diff #[allow(unconditional_panic)] fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff index 65cd794636766..86ed32a1f9dc5 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff @@ -27,9 +27,9 @@ StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 // mir::Constant - // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 + // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35 // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } - _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _3 = &(*_9); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35 @@ -38,14 +38,16 @@ StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 } bb1: { _5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 - nop; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 + _0 = const (); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2 return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff index 65cd794636766..86ed32a1f9dc5 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff @@ -27,9 +27,9 @@ StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 // mir::Constant - // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 + // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35 // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } - _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _3 = &(*_9); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35 @@ -38,14 +38,16 @@ StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 } bb1: { _5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 - nop; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 + _0 = const (); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2 return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs index e4cc9cb917ede..c97257e6d8fa2 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs @@ -1,3 +1,4 @@ +// unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR bad_op_unsafe_oob_for_slices.main.DataflowConstProp.diff #[allow(unconditional_panic)] diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs index e169135e0acde..a6f156fe052ee 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs @@ -1,5 +1,4 @@ -// unit-test -// compile-flags: -O -Zmir-opt-level=4 +// unit-test: DataflowConstProp // EMIT_MIR mult_by_zero.test.DataflowConstProp.diff fn test(x: i32) -> i32 { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff index 540cccb3b375f..c225b35e19239 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:6 _2 = _1; // scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:6 - _0 = const 0_i32; // scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:10 + _0 = Mul(move _2, const 0_i32); // scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:10 StorageDead(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:9: +1:10 return; // scope 0 at $DIR/mult_by_zero.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff index 03556e85088e8..098440dbe2f1e 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff @@ -17,8 +17,9 @@ _1 = const 42_i32; // scope 0 at $DIR/mutable_variable.rs:+1:17: +1:19 _1 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+2:5: +2:11 StorageLive(_2); // scope 1 at $DIR/mutable_variable.rs:+3:9: +3:10 - _2 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 - nop; // scope 0 at $DIR/mutable_variable.rs:+0:11: +4:2 +- _2 = _1; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 ++ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 + _0 = const (); // scope 0 at $DIR/mutable_variable.rs:+0:11: +4:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable.rs:+4:1: +4:2 return; // scope 0 at $DIR/mutable_variable.rs:+4:2: +4:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs index 055b7f158da09..680bcd7fc703b 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs @@ -1,5 +1,4 @@ -// unit-test -// compile-flags: -O +// unit-test: DataflowConstProp // EMIT_MIR mutable_variable.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff index 7b5be873ee821..1180dffdbadbf 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff @@ -19,8 +19,8 @@ (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13 StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 - _2 = const (42_i32, 99_i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 - nop; // scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +4:2 + _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 + _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +4:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 return; // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:2: +4:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs index 854c2d3b8a800..255236049f988 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs @@ -1,5 +1,4 @@ -// unit-test -// compile-flags: -O +// unit-test: DataflowConstProp // EMIT_MIR mutable_variable_aggregate.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff index 8c3f4b9261804..f278854780073 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff @@ -26,7 +26,7 @@ ((*_2).1: i32) = const 99_i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+3:5: +3:13 StorageLive(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 _3 = _1; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14 - nop; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+0:11: +5:2 + _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+0:11: +5:2 StorageDead(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs index 18df3596cff18..54b898b4ee5c5 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs @@ -1,5 +1,4 @@ -// unit-test -// compile-flags: -O +// unit-test: DataflowConstProp // EMIT_MIR mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff index fb396e7a121ad..1f8e283f33a56 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff @@ -16,7 +16,7 @@ StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14 _1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:29: +1:34 // mir::Constant - // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:29: 6:32 + // + span: $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:32 // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value() } } @@ -24,8 +24,9 @@ (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+2:5: +2:13 (_1.0: i32) = const 42_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+3:5: +3:13 StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:9: +4:10 - _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 - nop; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+0:11: +5:2 +- _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 ++ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 + _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+0:11: +5:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2 return; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:2: +5:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs index 39a77ba178946..0439a52081998 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs @@ -1,5 +1,4 @@ -// unit-test -// compile-flags: -O +// unit-test: DataflowConstProp // EMIT_MIR mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff index 783aaacca3c04..9363e6b9aa1ce 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff @@ -25,17 +25,17 @@ StorageLive(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 _4 = const {alloc1: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 // mir::Constant - // + span: $DIR/mutable_variable_no_prop.rs:10:13: 10:19 + // + span: $DIR/mutable_variable_no_prop.rs:9:13: 9:19 // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) } _3 = (*_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 _1 = move _3; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19 StorageDead(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:18: +3:19 StorageDead(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:19: +3:20 - nop; // scope 2 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 + _2 = const (); // scope 2 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 StorageDead(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:+4:5: +4:6 StorageLive(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 _5 = _1; // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:13: +5:14 - nop; // scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +6:2 + _0 = const (); // scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +6:2 StorageDead(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 return; // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:2: +6:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs index 26f9cab5cd44f..e4edf1475f2bf 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs @@ -1,5 +1,4 @@ -// unit-test -// compile-flags: -O +// unit-test: DataflowConstProp static mut STATIC: u32 = 42; diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff index 2f6aeca20763e..8d31d5533da2a 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff @@ -25,7 +25,7 @@ StorageLive(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 _1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:13: +1:18 // mir::Constant - // + span: $DIR/mutable_variable_unprop_assign.rs:6:13: 6:16 + // + span: $DIR/mutable_variable_unprop_assign.rs:5:13: 5:16 // + literal: Const { ty: fn() -> i32 {foo}, val: Value() } } @@ -41,8 +41,9 @@ StorageLive(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 _4 = (_2.1: i32); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 - _5 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 - nop; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +6:2 +- _5 = (_2.0: i32); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 ++ _5 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 + _0 = const (); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +6:2 StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs index 92da91682d160..942e96fee4442 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs @@ -1,5 +1,4 @@ -// unit-test -// compile-flags: -O +// unit-test: DataflowConstProp // EMIT_MIR mutable_variable_unprop_assign.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff index dd3dc9b9e4dbd..a48ba5bf2e1bb 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff @@ -18,22 +18,22 @@ StorageLive(_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 _3 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 // mir::Constant - // + span: $DIR/read_immutable_static.rs:8:13: 8:16 + // + span: $DIR/read_immutable_static.rs:7:13: 7:16 // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } - _2 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 + _2 = (*_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 StorageLive(_4); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 StorageLive(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 _5 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 // mir::Constant - // + span: $DIR/read_immutable_static.rs:8:19: 8:22 + // + span: $DIR/read_immutable_static.rs:7:19: 7:22 // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } - _4 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 - _1 = const 4_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22 + _4 = (*_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 + _1 = Add(move _2, move _4); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22 StorageDead(_4); // scope 0 at $DIR/read_immutable_static.rs:+1:21: +1:22 StorageDead(_2); // scope 0 at $DIR/read_immutable_static.rs:+1:21: +1:22 StorageDead(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23 StorageDead(_3); // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23 - nop; // scope 0 at $DIR/read_immutable_static.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/read_immutable_static.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/read_immutable_static.rs:+2:1: +2:2 return; // scope 0 at $DIR/read_immutable_static.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs index 0ca5668fb8629..6324b4a9c545b 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs @@ -1,5 +1,4 @@ -// unit-test -// compile-flags: -O +// unit-test: DataflowConstProp static FOO: u8 = 2; diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff index 74c53808e1596..045836b6373de 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff @@ -13,13 +13,13 @@ StorageLive(_2); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 // mir::Constant - // + span: $DIR/ref_deref.rs:5:6: 5:10 + // + span: $DIR/ref_deref.rs:6:6: 6:10 // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } - _2 = _4; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 + _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 - nop; // scope 0 at $DIR/ref_deref.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/ref_deref.rs:+0:11: +2:2 return; // scope 0 at $DIR/ref_deref.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff index d141d2cf87bb7..37eb403fd4113 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff @@ -16,7 +16,7 @@ - _2 = &_3; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + // mir::Constant -+ // + span: $DIR/ref_deref.rs:5:6: 5:10 ++ // + span: $DIR/ref_deref.rs:6:6: 6:10 + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } + _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs index ee9426dd906ea..b3ec2383b913c 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs @@ -1,3 +1,4 @@ +// unit-test: DataflowConstProp // EMIT_MIR ref_deref.main.PromoteTemps.diff // EMIT_MIR ref_deref.main.DataflowConstProp.diff diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff index 66828e5013c9f..1a3761f15aa9e 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff @@ -19,7 +19,7 @@ _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 - nop; // scope 0 at $DIR/ref_deref_project.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/ref_deref_project.rs:+0:11: +2:2 return; // scope 0 at $DIR/ref_deref_project.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs index b28fb320d33e4..65175917e13b8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs @@ -1,4 +1,4 @@ -// unit-test +// unit-test: DataflowConstProp // EMIT_MIR ref_deref_project.main.PromoteTemps.diff // EMIT_MIR ref_deref_project.main.DataflowConstProp.diff diff --git a/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff index 7581b852a89b0..6822f353b05bd 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff @@ -15,14 +15,14 @@ StorageLive(_3); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 _3 = main as fn() (Pointer(ReifyFnPointer)); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 // mir::Constant - // + span: $DIR/reify_fn_ptr.rs:4:13: 4:17 + // + span: $DIR/reify_fn_ptr.rs:5:13: 5:17 // + literal: Const { ty: fn() {main}, val: Value() } _2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 StorageDead(_3); // scope 0 at $DIR/reify_fn_ptr.rs:+1:25: +1:26 _1 = move _2 as *const fn() (PointerFromExposedAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41 StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:+1:40: +1:41 StorageDead(_1); // scope 0 at $DIR/reify_fn_ptr.rs:+1:41: +1:42 - nop; // scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +2:2 return; // scope 0 at $DIR/reify_fn_ptr.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs b/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs index 00205a2963080..c69680d36e2b5 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs @@ -1,3 +1,4 @@ +// unit-test: DataflowConstProp // EMIT_MIR reify_fn_ptr.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff index f7e60a5a351d8..4e3de9df468e0 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff @@ -20,18 +20,20 @@ _3 = [const 42_u32; 8]; // scope 0 at $DIR/repeat.rs:+1:18: +1:25 StorageLive(_4); // scope 0 at $DIR/repeat.rs:+1:26: +1:27 _4 = const 2_usize; // scope 0 at $DIR/repeat.rs:+1:26: +1:27 - _5 = const 8_usize; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - _6 = const true; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + _5 = Len(_3); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 +- _6 = Lt(_4, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 ++ _6 = Lt(const 2_usize, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 ++ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 } bb1: { - _2 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - _1 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:32 + _2 = _3[_4]; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + _1 = Add(move _2, const 0_u32); // scope 0 at $DIR/repeat.rs:+1:18: +1:32 StorageDead(_2); // scope 0 at $DIR/repeat.rs:+1:31: +1:32 StorageDead(_4); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 StorageDead(_3); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 - nop; // scope 0 at $DIR/repeat.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/repeat.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/repeat.rs:+2:1: +2:2 return; // scope 0 at $DIR/repeat.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff index f7e60a5a351d8..4e3de9df468e0 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff @@ -20,18 +20,20 @@ _3 = [const 42_u32; 8]; // scope 0 at $DIR/repeat.rs:+1:18: +1:25 StorageLive(_4); // scope 0 at $DIR/repeat.rs:+1:26: +1:27 _4 = const 2_usize; // scope 0 at $DIR/repeat.rs:+1:26: +1:27 - _5 = const 8_usize; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - _6 = const true; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + _5 = Len(_3); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 +- _6 = Lt(_4, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 +- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 ++ _6 = Lt(const 2_usize, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 ++ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 } bb1: { - _2 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - _1 = const 42_u32; // scope 0 at $DIR/repeat.rs:+1:18: +1:32 + _2 = _3[_4]; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 + _1 = Add(move _2, const 0_u32); // scope 0 at $DIR/repeat.rs:+1:18: +1:32 StorageDead(_2); // scope 0 at $DIR/repeat.rs:+1:31: +1:32 StorageDead(_4); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 StorageDead(_3); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 - nop; // scope 0 at $DIR/repeat.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/repeat.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/repeat.rs:+2:1: +2:2 return; // scope 0 at $DIR/repeat.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.rs b/src/test/mir-opt/dataflow-const-prop/previous/repeat.rs index ade87676869ee..df5284d11dadf 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/repeat.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/repeat.rs @@ -1,4 +1,4 @@ -// compile-flags: -O +// unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR repeat.main.DataflowConstProp.diff diff --git a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff index f7a3227f39de8..07cdba28e042f 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff @@ -6,12 +6,14 @@ let mut _1: (u32, bool); // in scope 0 at $DIR/return_place.rs:+1:5: +1:10 bb0: { - _1 = const (4_u32, false); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 - assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 + _1 = CheckedAdd(const 2_u32, const 2_u32); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 +- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 } bb1: { - _0 = const 4_u32; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 +- _0 = move (_1.0: u32); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 ++ _0 = const 4_u32; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 return; // scope 0 at $DIR/return_place.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir index ececd9942838d..4f5ea6320f16a 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir +++ b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir @@ -2,8 +2,14 @@ fn add() -> u32 { let mut _0: u32; // return place in scope 0 at $DIR/return_place.rs:+0:13: +0:16 + let mut _1: (u32, bool); // in scope 0 at $DIR/return_place.rs:+1:5: +1:10 bb0: { + _1 = CheckedAdd(const 2_u32, const 2_u32); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 + } + + bb1: { _0 = const 4_u32; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 return; // scope 0 at $DIR/return_place.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/return_place.rs b/src/test/mir-opt/dataflow-const-prop/previous/return_place.rs index d4cac2c76ddcd..26365cc5db2dc 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/return_place.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/return_place.rs @@ -1,3 +1,4 @@ +// unit-test: DataflowConstProp // compile-flags: -C overflow-checks=on // EMIT_MIR return_place.add.DataflowConstProp.diff diff --git a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff index 97609293c9a56..a0212aea5dd8a 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff @@ -15,17 +15,19 @@ _1 = const 1_u32; // scope 0 at $DIR/scalar_literal_propagation.rs:+1:13: +1:14 StorageLive(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 StorageLive(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 - _3 = const 1_u32; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 - _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 +- _3 = _1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 +- _2 = consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 ++ _3 = const 1_u32; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 ++ _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 // mir::Constant - // + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12 + // + span: $DIR/scalar_literal_propagation.rs:5:5: 5:12 // + literal: Const { ty: fn(u32) {consume}, val: Value() } } bb1: { StorageDead(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:14: +2:15 StorageDead(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:15: +2:16 - nop; // scope 0 at $DIR/scalar_literal_propagation.rs:+0:11: +3:2 + _0 = const (); // scope 0 at $DIR/scalar_literal_propagation.rs:+0:11: +3:2 StorageDead(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+3:1: +3:2 return; // scope 0 at $DIR/scalar_literal_propagation.rs:+3:2: +3:2 } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs index 00726b6f13de9..d26cb30c07645 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs @@ -1,3 +1,4 @@ +// unit-test: DataflowConstProp // EMIT_MIR scalar_literal_propagation.main.DataflowConstProp.diff fn main() { let x = 1; diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff index 7af3a3881df2c..39955097a28c4 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff @@ -12,7 +12,6 @@ let mut _7: usize; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 let mut _8: bool; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 let mut _9: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - let mut _10: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 bb0: { StorageLive(_1); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 @@ -21,29 +20,28 @@ StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 // mir::Constant - // + span: $DIR/slice_len.rs:5:6: 5:19 + // + span: $DIR/slice_len.rs:6:6: 6:19 // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } - _4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - StorageLive(_10); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _10 = _3; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _4 = &(*_9); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _3 = &(*_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 StorageDead(_3); // scope 0 at $DIR/slice_len.rs:+1:18: +1:19 StorageLive(_6); // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 _6 = const 1_usize; // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 - _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - StorageDead(_10); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - _8 = const true; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + _7 = Len((*_2)); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 +- _8 = Lt(_6, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 ++ _8 = Lt(const 1_usize, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 } bb1: { - _1 = const 2_u32; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + _1 = (*_2)[_6]; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 StorageDead(_6); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 StorageDead(_4); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 StorageDead(_2); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 StorageDead(_1); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 - nop; // scope 0 at $DIR/slice_len.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/slice_len.rs:+0:11: +2:2 return; // scope 0 at $DIR/slice_len.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff index 7af3a3881df2c..39955097a28c4 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff @@ -12,7 +12,6 @@ let mut _7: usize; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 let mut _8: bool; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 let mut _9: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - let mut _10: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 bb0: { StorageLive(_1); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 @@ -21,29 +20,28 @@ StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 // mir::Constant - // + span: $DIR/slice_len.rs:5:6: 5:19 + // + span: $DIR/slice_len.rs:6:6: 6:19 // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } - _4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - StorageLive(_10); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _10 = _3; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _4 = &(*_9); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _3 = &(*_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 StorageDead(_3); // scope 0 at $DIR/slice_len.rs:+1:18: +1:19 StorageLive(_6); // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 _6 = const 1_usize; // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 - _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - StorageDead(_10); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - _8 = const true; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + _7 = Len((*_2)); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 +- _8 = Lt(_6, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 ++ _8 = Lt(const 1_usize, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 } bb1: { - _1 = const 2_u32; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 + _1 = (*_2)[_6]; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 StorageDead(_6); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 StorageDead(_4); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 StorageDead(_2); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 StorageDead(_1); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 - nop; // scope 0 at $DIR/slice_len.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/slice_len.rs:+0:11: +2:2 return; // scope 0 at $DIR/slice_len.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs index 224ccb70f8b46..b22d33795ef10 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs @@ -1,3 +1,4 @@ +// unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR slice_len.main.DataflowConstProp.diff diff --git a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff index 7fcde2be17149..3a1b5f374f0ff 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff @@ -17,17 +17,17 @@ (_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 - _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 + _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 _2 = consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 // mir::Constant - // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12 + // + span: $DIR/tuple_literal_propagation.rs:6:5: 6:12 // + literal: Const { ty: fn((u32, u32)) {consume}, val: Value() } } bb1: { StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15 StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16 - nop; // scope 0 at $DIR/tuple_literal_propagation.rs:+0:11: +4:2 + _0 = const (); // scope 0 at $DIR/tuple_literal_propagation.rs:+0:11: +4:2 StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2 return; // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2 } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs index 41085838127f6..737f39673a3c8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs +++ b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs @@ -1,3 +1,4 @@ +// unit-test: DataflowConstProp // EMIT_MIR tuple_literal_propagation.main.DataflowConstProp.diff fn main() { let x = (1, 2); From c56e99cdba2dc969902005fc495c12f13b9eb2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 27 Sep 2022 17:30:50 +0200 Subject: [PATCH 31/76] Fix typo --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 05285e460eb17..55b1185acd39f 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -174,7 +174,7 @@ pub trait ValueAnalysis<'tcx> { ValueOrPlace::Value(self.handle_constant(constant, state)) } Operand::Copy(place) | Operand::Move(place) => { - // Do want want to handle moves different? Could flood place with bottom. + // Do we want to handle moves differently? Could flood place with bottom. self.map() .find(place.as_ref()) .map(ValueOrPlace::Place) From f99950f6aeb78bd271af3f99cbad03613f7b93f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 5 Oct 2022 01:24:33 +0200 Subject: [PATCH 32/76] Update test results after rebase --- .../rustc_mir_dataflow/src/value_analysis.rs | 20 +++++++++++-- .../checked.main.DataflowConstProp.diff | 2 +- ...r_slices.main.DataflowConstProp.32bit.diff | 2 +- ...r_slices.main.DataflowConstProp.64bit.diff | 2 +- ...ils_gracefully.main.DataflowConstProp.diff | 2 +- ...implification.hello.DataflowConstProp.diff | 3 +- .../ref_deref.main.DataflowConstProp.diff | 2 +- .../previous/ref_deref.main.PromoteTemps.diff | 2 +- ..._deref_project.main.DataflowConstProp.diff | 2 +- .../ref_deref_project.main.PromoteTemps.diff | 2 +- ...lice_len.main.DataflowConstProp.32bit.diff | 2 +- ...lice_len.main.DataflowConstProp.64bit.diff | 2 +- .../promoted.main.DataflowConstProp.diff | 2 +- .../recursive.main.DataflowConstProp.diff | 30 +++++++++---------- .../ref_mut.main.DataflowConstProp.diff | 2 +- 15 files changed, 47 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 55b1185acd39f..66e2a445fbcdf 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -87,8 +87,8 @@ pub trait ValueAnalysis<'tcx> { // But discriminants are currently not tracked, so we do nothing. // Related: https://github.com/rust-lang/unsafe-code-guidelines/issues/84 } - StatementKind::CopyNonOverlapping(..) => { - // FIXME: What to do here? + StatementKind::Intrinsic(box intrinsic) => { + self.handle_intrinsic(intrinsic, state); } StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { // It is UB to read from an unitialized or unallocated local. @@ -106,6 +106,22 @@ pub trait ValueAnalysis<'tcx> { } } + fn handle_intrinsic( + &self, + intrinsic: &NonDivergingIntrinsic<'tcx>, + state: &mut State, + ) { + self.super_intrinsic(intrinsic, state); + } + + fn super_intrinsic( + &self, + _intrinsic: &NonDivergingIntrinsic<'tcx>, + _state: &mut State, + ) { + todo!(); + } + fn handle_assign( &self, target: Place<'tcx>, diff --git a/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff index 39bc506adacea..fbc95cea7cd95 100644 --- a/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff @@ -53,7 +53,7 @@ StorageDead(_5); // scope 2 at $DIR/checked.rs:+3:17: +3:18 StorageDead(_4); // scope 2 at $DIR/checked.rs:+3:17: +3:18 StorageLive(_7); // scope 3 at $DIR/checked.rs:+5:9: +5:10 -- _7 = const core::num::::MAX; // scope 3 at $DIR/checked.rs:+5:13: +5:21 +- _7 = const _; // scope 3 at $DIR/checked.rs:+5:13: +5:21 + _7 = const i32::MAX; // scope 3 at $DIR/checked.rs:+5:13: +5:21 StorageLive(_8); // scope 4 at $DIR/checked.rs:+6:9: +6:10 StorageLive(_9); // scope 4 at $DIR/checked.rs:+6:13: +6:14 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff index 86ed32a1f9dc5..ce1524af76531 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff @@ -25,7 +25,7 @@ StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _9 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35 // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff index 86ed32a1f9dc5..ce1524af76531 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff @@ -25,7 +25,7 @@ StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _9 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35 // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff index 17b63065df020..38a5eecb8e8f0 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff @@ -16,7 +16,7 @@ StorageLive(_1); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:9: +2:10 StorageLive(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:30 StorageLive(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 - _3 = const FOO; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 + _3 = const _; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 // mir::Constant // + span: $DIR/const_prop_fails_gracefully.rs:8:13: 8:16 // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff index e2e42e72c281d..f13ca4b62e6fb 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff @@ -8,7 +8,8 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 - _1 = const false; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 +- _1 = const _; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 ++ _1 = const false; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff index 045836b6373de..018178ab624e3 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 StorageLive(_2); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + _4 = const _; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 // mir::Constant // + span: $DIR/ref_deref.rs:6:6: 6:10 // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff index 37eb403fd4113..015ec4d078c10 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff @@ -14,7 +14,7 @@ - StorageLive(_3); // scope 0 at $DIR/ref_deref.rs:+1:8: +1:9 - _3 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:+1:8: +1:9 - _2 = &_3; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 -+ _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 ++ _4 = const _; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + // mir::Constant + // + span: $DIR/ref_deref.rs:6:6: 6:10 + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff index 1a3761f15aa9e..f16d2fcafb8fa 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 StorageLive(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 - _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + _4 = const _; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 // mir::Constant // + span: $DIR/ref_deref_project.rs:6:6: 6:17 // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff index 6f3a060a1260a..cd0616e65baf8 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff @@ -14,7 +14,7 @@ - StorageLive(_3); // scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14 - _3 = (const 4_i32, const 5_i32); // scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14 - _2 = &(_3.1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 -+ _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 ++ _4 = const _; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + // mir::Constant + // + span: $DIR/ref_deref_project.rs:6:6: 6:17 + // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff index 39955097a28c4..e39afae5aa626 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff @@ -18,7 +18,7 @@ StorageLive(_2); // scope 0 at $DIR/slice_len.rs:+1:5: +1:30 StorageLive(_3); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 // mir::Constant // + span: $DIR/slice_len.rs:6:6: 6:19 // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff index 39955097a28c4..e39afae5aa626 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff @@ -18,7 +18,7 @@ StorageLive(_2); // scope 0 at $DIR/slice_len.rs:+1:5: +1:30 StorageLive(_3); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 + _9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 // mir::Constant // + span: $DIR/slice_len.rs:6:6: 6:19 // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } diff --git a/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff index d5a17d0835616..1dabb0ae3eea9 100644 --- a/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff @@ -14,7 +14,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/promoted.rs:+2:9: +2:10 StorageLive(_2); // scope 0 at $DIR/promoted.rs:+2:14: +2:17 - _4 = const main::promoted[0]; // scope 0 at $DIR/promoted.rs:+2:14: +2:17 + _4 = const _; // scope 0 at $DIR/promoted.rs:+2:14: +2:17 // mir::Constant // + span: $DIR/promoted.rs:6:14: 6:17 // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } diff --git a/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff index f7c557c3edf3f..c344de76b6a32 100644 --- a/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff @@ -3,35 +3,35 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/recursive.rs:+0:11: +0:11 - let _1: S; // in scope 0 at $DIR/recursive.rs:+2:9: +2:10 - let mut _3: &S; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 - let _4: &S; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 - let mut _6: &S; // in scope 0 at $DIR/recursive.rs:+4:20: +4:22 - let _7: &S; // in scope 0 at $DIR/recursive.rs:+4:20: +4:22 + let _1: S<'_>; // in scope 0 at $DIR/recursive.rs:+2:9: +2:10 + let mut _3: &S<'_>; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 + let _4: &S<'_>; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 + let mut _6: &S<'_>; // in scope 0 at $DIR/recursive.rs:+4:20: +4:22 + let _7: &S<'_>; // in scope 0 at $DIR/recursive.rs:+4:20: +4:22 let mut _9: isize; // in scope 0 at $DIR/recursive.rs:+6:9: +6:18 let mut _11: isize; // in scope 0 at $DIR/recursive.rs:+7:13: +7:22 let mut _13: isize; // in scope 0 at $DIR/recursive.rs:+8:17: +8:28 let mut _15: !; // in scope 0 at $DIR/recursive.rs:+9:22: +9:43 let mut _16: !; // in scope 0 at $DIR/recursive.rs:+11:18: +11:39 let mut _17: !; // in scope 0 at $DIR/recursive.rs:+13:14: +13:35 - let mut _18: &S; // in scope 0 at $DIR/recursive.rs:+7:20: +7:21 - let mut _19: &S; // in scope 0 at $DIR/recursive.rs:+7:20: +7:21 + let mut _18: &S<'_>; // in scope 0 at $DIR/recursive.rs:+7:20: +7:21 + let mut _19: &S<'_>; // in scope 0 at $DIR/recursive.rs:+7:20: +7:21 scope 1 { debug a => _1; // in scope 1 at $DIR/recursive.rs:+2:9: +2:10 - let _2: S; // in scope 1 at $DIR/recursive.rs:+3:9: +3:10 + let _2: S<'_>; // in scope 1 at $DIR/recursive.rs:+3:9: +3:10 scope 2 { debug b => _2; // in scope 2 at $DIR/recursive.rs:+3:9: +3:10 - let _5: S; // in scope 2 at $DIR/recursive.rs:+4:9: +4:10 + let _5: S<'_>; // in scope 2 at $DIR/recursive.rs:+4:9: +4:10 scope 3 { debug c => _5; // in scope 3 at $DIR/recursive.rs:+4:9: +4:10 let _8: u32; // in scope 3 at $DIR/recursive.rs:+5:9: +5:10 - let _10: &S; // in scope 3 at $DIR/recursive.rs:+6:16: +6:17 + let _10: &S<'_>; // in scope 3 at $DIR/recursive.rs:+6:16: +6:17 scope 4 { debug d => _8; // in scope 4 at $DIR/recursive.rs:+5:9: +5:10 } scope 5 { debug b => _10; // in scope 5 at $DIR/recursive.rs:+6:16: +6:17 - let _12: &&S; // in scope 5 at $DIR/recursive.rs:+7:20: +7:21 + let _12: &&S<'_>; // in scope 5 at $DIR/recursive.rs:+7:20: +7:21 scope 6 { debug a => _12; // in scope 6 at $DIR/recursive.rs:+7:20: +7:21 let _14: &u32; // in scope 6 at $DIR/recursive.rs:+8:24: +8:27 @@ -55,7 +55,7 @@ _4 = &_1; // scope 1 at $DIR/recursive.rs:+3:20: +3:22 _3 = &(*_4); // scope 1 at $DIR/recursive.rs:+3:20: +3:22 Deinit(_2); // scope 1 at $DIR/recursive.rs:+3:13: +3:23 - ((_2 as Rec).0: &S) = move _3; // scope 1 at $DIR/recursive.rs:+3:13: +3:23 + ((_2 as Rec).0: &S<'_>) = move _3; // scope 1 at $DIR/recursive.rs:+3:13: +3:23 discriminant(_2) = 0; // scope 1 at $DIR/recursive.rs:+3:13: +3:23 StorageDead(_3); // scope 1 at $DIR/recursive.rs:+3:22: +3:23 StorageDead(_4); // scope 1 at $DIR/recursive.rs:+3:23: +3:24 @@ -65,7 +65,7 @@ _7 = &_2; // scope 2 at $DIR/recursive.rs:+4:20: +4:22 _6 = &(*_7); // scope 2 at $DIR/recursive.rs:+4:20: +4:22 Deinit(_5); // scope 2 at $DIR/recursive.rs:+4:13: +4:23 - ((_5 as Rec).0: &S) = move _6; // scope 2 at $DIR/recursive.rs:+4:13: +4:23 + ((_5 as Rec).0: &S<'_>) = move _6; // scope 2 at $DIR/recursive.rs:+4:13: +4:23 discriminant(_5) = 0; // scope 2 at $DIR/recursive.rs:+4:13: +4:23 StorageDead(_6); // scope 2 at $DIR/recursive.rs:+4:22: +4:23 StorageDead(_7); // scope 2 at $DIR/recursive.rs:+4:23: +4:24 @@ -84,7 +84,7 @@ bb2: { StorageLive(_10); // scope 3 at $DIR/recursive.rs:+6:16: +6:17 - _10 = ((_5 as Rec).0: &S); // scope 3 at $DIR/recursive.rs:+6:16: +6:17 + _10 = ((_5 as Rec).0: &S<'_>); // scope 3 at $DIR/recursive.rs:+6:16: +6:17 _11 = discriminant((*_10)); // scope 5 at $DIR/recursive.rs:+6:28: +6:29 switchInt(move _11) -> [0_isize: bb4, otherwise: bb3]; // scope 5 at $DIR/recursive.rs:+6:22: +6:29 } @@ -99,7 +99,7 @@ bb4: { StorageLive(_12); // scope 5 at $DIR/recursive.rs:+7:20: +7:21 - _12 = &(((*_10) as Rec).0: &S); // scope 5 at $DIR/recursive.rs:+7:20: +7:21 + _12 = &(((*_10) as Rec).0: &S<'_>); // scope 5 at $DIR/recursive.rs:+7:20: +7:21 _18 = deref_copy (*_12); // scope 6 at $DIR/recursive.rs:+7:32: +7:33 _13 = discriminant((*_18)); // scope 6 at $DIR/recursive.rs:+7:32: +7:33 switchInt(move _13) -> [1_isize: bb6, otherwise: bb5]; // scope 6 at $DIR/recursive.rs:+7:26: +7:33 diff --git a/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff index fe5bdd07d4a02..6d55092747a5a 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff @@ -52,7 +52,7 @@ _6 = &mut _5; // scope 5 at $DIR/ref_mut.rs:+8:13: +8:19 StorageLive(_7); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 StorageLive(_8); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 - _11 = const main::promoted[0]; // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 + _11 = const _; // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 // mir::Constant // + span: $DIR/ref_mut.rs:13:10: 13:12 // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } From eab77320e6cad8a42b05989c17bdc8a9609d83ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 5 Oct 2022 20:19:11 +0200 Subject: [PATCH 33/76] Handle NonDivergingIntrinsic and CopyNonOverlapping --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 66e2a445fbcdf..02b92ed7a6206 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -116,10 +116,19 @@ pub trait ValueAnalysis<'tcx> { fn super_intrinsic( &self, - _intrinsic: &NonDivergingIntrinsic<'tcx>, - _state: &mut State, + intrinsic: &NonDivergingIntrinsic<'tcx>, + state: &mut State, ) { - todo!(); + match intrinsic { + NonDivergingIntrinsic::Assume(..) => { + // Could use this, but ignoring it is sound. + } + NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { dst, .. }) => { + if let Some(place) = dst.place() { + state.flood(place.as_ref(), self.map()); + } + } + } } fn handle_assign( From 2f66e9417f51d4350274854287c52a106599f31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 5 Oct 2022 20:46:39 +0200 Subject: [PATCH 34/76] Flood with bottom for Deinit, StorageLive and StorageDead --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 02b92ed7a6206..1abfcacb0c099 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -91,12 +91,13 @@ pub trait ValueAnalysis<'tcx> { self.handle_intrinsic(intrinsic, state); } StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { - // It is UB to read from an unitialized or unallocated local. - state.flood(Place::from(*local).as_ref(), self.map()); + // We can flood with bottom here, because `StorageLive` makes the local + // uninitialized, and `StorageDead` makes it UB to access. + state.flood_with(Place::from(*local).as_ref(), self.map(), Self::Value::bottom()); } StatementKind::Deinit(box place) => { - // It is UB to read `uninit` bytes. - state.flood(place.as_ref(), self.map()); + // The bottom states denotes uninitialized values. + state.flood_with(place.as_ref(), self.map(), Self::Value::bottom()); } StatementKind::Nop | StatementKind::Retag(..) From b5063ab0e543174e416e34fc130c8b8daba34b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 5 Oct 2022 21:30:43 +0200 Subject: [PATCH 35/76] Make more assumptions explicit --- .../rustc_mir_dataflow/src/value_analysis.rs | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 1abfcacb0c099..510856da92fb5 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -50,6 +50,20 @@ //! Borrows. //! //! To be continued... +//! +//! The bottom state denotes uninitalized memory. +//! +//! +//! # Assumptions +//! +//! - (A1) Assignment to any tracked place invalidates all pointers that could be used to change +//! the underlying value. +//! - (A2) `StorageLive`, `StorageDead` and `Deinit` make the underlying memory at least +//! uninitialized (at least in the sense that declaring access UB is also fine). +//! - (A3) An assignment with `State::assign_place_idx` either involves non-overlapping places, or +//! the places are the same. +//! - (A4) If the value behind a reference to a `Freeze` place is changed, dereferencing the +//! reference is UB. use std::fmt::{Debug, Formatter}; @@ -91,12 +105,11 @@ pub trait ValueAnalysis<'tcx> { self.handle_intrinsic(intrinsic, state); } StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { - // We can flood with bottom here, because `StorageLive` makes the local - // uninitialized, and `StorageDead` makes it UB to access. + // (A2) state.flood_with(Place::from(*local).as_ref(), self.map(), Self::Value::bottom()); } StatementKind::Deinit(box place) => { - // The bottom states denotes uninitialized values. + // (A2) state.flood_with(place.as_ref(), self.map(), Self::Value::bottom()); } StatementKind::Nop @@ -200,7 +213,8 @@ pub trait ValueAnalysis<'tcx> { ValueOrPlace::Value(self.handle_constant(constant, state)) } Operand::Copy(place) | Operand::Move(place) => { - // Do we want to handle moves differently? Could flood place with bottom. + // On move, we would ideally flood the place with bottom. But with the current + // framework this is not possible (similar to `InterpCx::eval_operand`). self.map() .find(place.as_ref()) .map(ValueOrPlace::Place) @@ -306,7 +320,6 @@ impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) { // The initial state maps all tracked places of argument projections to ⊤ and the rest to ⊥. - // This utilizes that reading from an uninitialized place is UB. assert!(matches!(state.0, StateData::Unreachable)); let values = IndexVec::from_elem_n(T::Value::bottom(), self.0.map().value_count); *state = State(StateData::Reachable(values)); @@ -440,10 +453,10 @@ impl State { self.flood_idx_with(place, map, V::top()) } - /// This method assumes that the given places are not overlapping, and that we can therefore - /// copy all entries one after another. pub fn assign_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map) { + // We use (A3) and copy all entries one after another. let StateData::Reachable(values) = &mut self.0 else { return }; + // If both places are tracked, we copy the value to the target. If the target is tracked, // but the source is not, we have to invalidate the value in target. If the target is not // tracked, then we don't have to do anything. @@ -490,6 +503,10 @@ impl State { if let Some(value_index) = map.places[target].value_index { values[value_index] = V::top(); } + // Instead of tracking of *where* a reference points to (as in, which place), we + // track *what* it points to (as in, what do we know about the target). For an + // assignment `x = &y`, we thus copy the info we have for `y` to `*x`. This is + // sound because we only track places that are `Freeze`, and (A4). if let Some(target_deref) = map.apply_elem(target, ProjElem::Deref) { self.assign_place_idx(target_deref, source, map); } @@ -657,6 +674,8 @@ impl Map { return Err(()); } + // FIXME: Check that the place is `Freeze`. + let place = self.make_place(local, projection)?; // Allocate a value slot if it doesn't have one. From 1765587846ac9bee95f4f293862b0aae9b8ff4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 5 Oct 2022 21:42:16 +0200 Subject: [PATCH 36/76] Only track (trivially) freeze types --- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_mir_dataflow/src/value_analysis.rs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index f72e236eda133..6cbdac2a8cbc6 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -849,7 +849,7 @@ impl<'tcx> Ty<'tcx> { /// /// Returning true means the type is known to be `Freeze`. Returning /// `false` means nothing -- could be `Freeze`, might not be. - fn is_trivially_freeze(self) -> bool { + pub fn is_trivially_freeze(self) -> bool { match self.kind() { ty::Int(_) | ty::Uint(_) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 510856da92fb5..766a659adca58 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -674,7 +674,11 @@ impl Map { return Err(()); } - // FIXME: Check that the place is `Freeze`. + if !ty.is_trivially_freeze() { + // Due to the way we deal with shared references, only `Freeze` types may be tracked. + // We are a little bit to restrictive here by only allowing trivially `Freeze` types. + return Err(()); + } let place = self.make_place(local, projection)?; From 7ab1ba95debdacdd4fc205510a0bb402b4428e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 5 Oct 2022 22:01:33 +0200 Subject: [PATCH 37/76] Remove `Unknown` state in favor of `Value(Top)` --- .../rustc_mir_dataflow/src/value_analysis.rs | 31 +++++++++++-------- .../src/dataflow_const_prop.rs | 10 ++---- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 766a659adca58..924d3d72a524b 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -183,15 +183,15 @@ pub trait ValueAnalysis<'tcx> { .map() .find(place.as_ref()) .map(ValueOrPlaceOrRef::Ref) - .unwrap_or(ValueOrPlaceOrRef::Unknown), + .unwrap_or(ValueOrPlaceOrRef::top()), Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { state.flood(place.as_ref(), self.map()); - ValueOrPlaceOrRef::Unknown + ValueOrPlaceOrRef::top() } Rvalue::CopyForDeref(place) => { self.handle_operand(&Operand::Copy(*place), state).into() } - _ => ValueOrPlaceOrRef::Unknown, + _ => ValueOrPlaceOrRef::top(), } } @@ -218,7 +218,7 @@ pub trait ValueAnalysis<'tcx> { self.map() .find(place.as_ref()) .map(ValueOrPlace::Place) - .unwrap_or(ValueOrPlace::Unknown) + .unwrap_or(ValueOrPlace::top()) } } } @@ -511,9 +511,6 @@ impl State { self.assign_place_idx(target_deref, source, map); } } - ValueOrPlaceOrRef::Unknown => { - self.flood_idx(target, map); - } } } @@ -756,27 +753,35 @@ impl<'a> Iterator for Children<'a> { } } } - -// FIXME: See if we can get rid of `Unknown`. pub enum ValueOrPlace { Value(V), Place(PlaceIndex), - Unknown, +} + +impl ValueOrPlace { + pub fn top() -> Self { + ValueOrPlace::Value(V::top()) + } } pub enum ValueOrPlaceOrRef { Value(V), Place(PlaceIndex), - Ref(PlaceIndex), - Unknown, + Ref(PlaceIndex) } +impl ValueOrPlaceOrRef { + pub fn top() -> Self { + ValueOrPlaceOrRef::Value(V::top()) + } +} + + impl From> for ValueOrPlaceOrRef { fn from(x: ValueOrPlace) -> Self { match x { ValueOrPlace::Value(value) => ValueOrPlaceOrRef::Value(value), ValueOrPlace::Place(place) => ValueOrPlaceOrRef::Place(place), - ValueOrPlace::Unknown => ValueOrPlaceOrRef::Unknown, } } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 334af0c6e8e6b..a6f5f71d09193 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -105,8 +105,8 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { .ecx .misc_cast(&operand, *ty) .map(|result| ValueOrPlaceOrRef::Value(self.wrap_immediate(result, *ty))) - .unwrap_or(ValueOrPlaceOrRef::Unknown), - _ => ValueOrPlaceOrRef::Unknown, + .unwrap_or(ValueOrPlaceOrRef::top()), + _ => ValueOrPlaceOrRef::top(), } } Rvalue::BinaryOp(op, box (left, right)) => { @@ -156,7 +156,6 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { let value = match self.handle_operand(discr, state) { ValueOrPlace::Value(value) => value, ValueOrPlace::Place(place) => state.get_idx(place, self.map()), - ValueOrPlace::Unknown => FlatSet::Top, }; let result = match value { FlatSet::Top => FlatSet::Top, @@ -241,7 +240,6 @@ impl<'tcx> ConstAnalysis<'tcx> { let value = match self.handle_operand(op, state) { ValueOrPlace::Value(value) => value, ValueOrPlace::Place(place) => state.get_idx(place, &self.map), - ValueOrPlace::Unknown => FlatSet::Top, }; match value { FlatSet::Top => FlatSet::Top, @@ -384,9 +382,7 @@ impl<'tcx, 'map, 'a> Visitor<'tcx> for OperandCollector<'tcx, 'map, 'a> { FlatSet::Elem(value) => { self.visitor.before_effect.insert((location, *place), value); } - FlatSet::Bottom => { - // This only happens if this location is unreachable. - } + FlatSet::Bottom => (), } } _ => (), From 4478a87018d59a1945b0c462d0584fc03edc6e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 5 Oct 2022 22:23:57 +0200 Subject: [PATCH 38/76] Fix formatting --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 924d3d72a524b..d3ae97fd0b6ff 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -767,7 +767,7 @@ impl ValueOrPlace { pub enum ValueOrPlaceOrRef { Value(V), Place(PlaceIndex), - Ref(PlaceIndex) + Ref(PlaceIndex), } impl ValueOrPlaceOrRef { @@ -776,7 +776,6 @@ impl ValueOrPlaceOrRef { } } - impl From> for ValueOrPlaceOrRef { fn from(x: ValueOrPlace) -> Self { match x { From 111324e17cd5d6c1181ea592051583a88bbe0f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 7 Oct 2022 00:09:36 +0200 Subject: [PATCH 39/76] Prevent registration inside references if target is !Freeze --- compiler/rustc_middle/src/ty/util.rs | 2 +- .../rustc_mir_dataflow/src/value_analysis.rs | 56 +++++++++++++------ .../src/dataflow_const_prop.rs | 3 +- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6cbdac2a8cbc6..f72e236eda133 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -849,7 +849,7 @@ impl<'tcx> Ty<'tcx> { /// /// Returning true means the type is known to be `Freeze`. Returning /// `false` means nothing -- could be `Freeze`, might not be. - pub fn is_trivially_freeze(self) -> bool { + fn is_trivially_freeze(self) -> bool { match self.kind() { ty::Int(_) | ty::Uint(_) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index d3ae97fd0b6ff..fbaaee48148d0 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -72,6 +72,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::DUMMY_SP; use rustc_target::abi::VariantIdx; use crate::{ @@ -550,7 +551,7 @@ pub struct Map { } impl Map { - pub fn new() -> Self { + fn new() -> Self { Self { locals: IndexVec::new(), projections: FxHashMap::default(), @@ -559,16 +560,27 @@ impl Map { } } - /// Register all places with suitable types up to a certain derefence depth (to prevent cycles). - pub fn register_with_filter<'tcx>( + /// Register all suitable places with matching types (up to a certain depth). + pub fn from_filter<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + filter: impl FnMut(Ty<'tcx>) -> bool, + ) -> Self { + let mut map = Self::new(); + map.register_with_filter(tcx, body, 3, filter); + map + } + + fn register_with_filter<'tcx>( &mut self, tcx: TyCtxt<'tcx>, - source: &impl HasLocalDecls<'tcx>, + body: &Body<'tcx>, max_derefs: u32, mut filter: impl FnMut(Ty<'tcx>) -> bool, ) { + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let mut projection = Vec::new(); - for (local, decl) in source.local_decls().iter_enumerated() { + for (local, decl) in body.local_decls.iter_enumerated() { self.register_with_filter_rec( tcx, max_derefs, @@ -576,6 +588,7 @@ impl Map { &mut projection, decl.ty, &mut filter, + param_env, ); } } @@ -588,16 +601,28 @@ impl Map { projection: &mut Vec>, ty: Ty<'tcx>, filter: &mut impl FnMut(Ty<'tcx>) -> bool, + param_env: ty::ParamEnv<'tcx>, ) { if filter(ty) { // This might fail if `ty` is not scalar. let _ = self.register_with_ty(local, projection, ty); } if max_derefs > 0 { - if let Some(ty::TypeAndMut { ty, .. }) = ty.builtin_deref(false) { - projection.push(PlaceElem::Deref); - self.register_with_filter_rec(tcx, max_derefs - 1, local, projection, ty, filter); - projection.pop(); + if let Some(ty::TypeAndMut { ty: deref_ty, .. }) = ty.builtin_deref(false) { + // References can only be tracked if the target is `!Freeze`. + if deref_ty.is_freeze(tcx.at(DUMMY_SP), param_env) { + projection.push(PlaceElem::Deref); + self.register_with_filter_rec( + tcx, + max_derefs - 1, + local, + projection, + deref_ty, + filter, + param_env, + ); + projection.pop(); + } } } iter_fields(ty, tcx, |variant, field, ty| { @@ -606,7 +631,9 @@ impl Map { return; } projection.push(PlaceElem::Field(field, ty)); - self.register_with_filter_rec(tcx, max_derefs, local, projection, ty, filter); + self.register_with_filter_rec( + tcx, max_derefs, local, projection, ty, filter, param_env, + ); projection.pop(); }); } @@ -639,7 +666,8 @@ impl Map { Ok(index) } - pub fn register<'tcx>( + #[allow(unused)] + fn register<'tcx>( &mut self, local: Local, projection: &[PlaceElem<'tcx>], @@ -671,12 +699,6 @@ impl Map { return Err(()); } - if !ty.is_trivially_freeze() { - // Due to the way we deal with shared references, only `Freeze` types may be tracked. - // We are a little bit to restrictive here by only allowing trivially `Freeze` types. - return Err(()); - } - let place = self.make_place(local, projection)?; // Allocate a value slot if it doesn't have one. diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index a6f5f71d09193..8f77b2b0081a8 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -21,8 +21,7 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Decide which places to track during the analysis. - let mut map = Map::new(); - map.register_with_filter(tcx, body, 3, |ty| ty.is_scalar() && !ty.is_unsafe_ptr()); + let map = Map::from_filter(tcx, body, |ty| ty.is_scalar() && !ty.is_unsafe_ptr()); // Perform the actual dataflow analysis. let analysis = ConstAnalysis::new(tcx, body, map); From 3c0f3b04b52134b870baf2ca8cedc5067cc5cb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 7 Oct 2022 01:10:10 +0200 Subject: [PATCH 40/76] Only assume Stacked Borrows if -Zunsound-mir-opts is given --- compiler/rustc_middle/src/mir/visit.rs | 9 + .../rustc_mir_dataflow/src/value_analysis.rs | 44 ++++- src/test/mir-opt/dataflow-const-prop/cast.rs | 1 + .../if.main.DataflowConstProp.diff | 164 +++++++++--------- src/test/mir-opt/dataflow-const-prop/if.rs | 2 +- .../ref.main.DataflowConstProp.diff | 2 +- src/test/mir-opt/dataflow-const-prop/ref.rs | 1 + 7 files changed, 137 insertions(+), 86 deletions(-) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index ddcf3711bfc95..d87eb28970e41 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1320,6 +1320,15 @@ impl PlaceContext { ) } + /// Returns `true` if this place context represents an address-of. + pub fn is_address_of(&self) -> bool { + matches!( + self, + PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) + | PlaceContext::MutatingUse(MutatingUseContext::AddressOf) + ) + } + /// Returns `true` if this place context represents a storage live or storage dead marker. #[inline] pub fn is_storage_marker(&self) -> bool { diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index fbaaee48148d0..9ae87418bc8b9 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -70,6 +70,7 @@ use std::fmt::{Debug, Formatter}; use rustc_data_structures::fx::FxHashMap; use rustc_index::vec::IndexVec; use rustc_middle::mir::tcx::PlaceTy; +use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::DUMMY_SP; @@ -567,7 +568,17 @@ impl Map { filter: impl FnMut(Ty<'tcx>) -> bool, ) -> Self { let mut map = Self::new(); - map.register_with_filter(tcx, body, 3, filter); + + // If `-Zunsound-mir-opts` is given, tracking through references, and tracking of places + // that have their reference taken is allowed. This would be "unsound" in the sense that + // the correctness relies on an aliasing model similar to Stacked Borrows (which is + // not yet guaranteed). + if tcx.sess.opts.unstable_opts.unsound_mir_opts { + map.register_with_filter(tcx, body, 3, filter, &[]); + } else { + map.register_with_filter(tcx, body, 0, filter, &escaped_places(body)); + } + map } @@ -577,6 +588,7 @@ impl Map { body: &Body<'tcx>, max_derefs: u32, mut filter: impl FnMut(Ty<'tcx>) -> bool, + exclude: &[Place<'tcx>], ) { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let mut projection = Vec::new(); @@ -589,6 +601,7 @@ impl Map { decl.ty, &mut filter, param_env, + exclude, ); } } @@ -602,11 +615,18 @@ impl Map { ty: Ty<'tcx>, filter: &mut impl FnMut(Ty<'tcx>) -> bool, param_env: ty::ParamEnv<'tcx>, + exclude: &[Place<'tcx>], ) { + // This check could be improved. + if exclude.contains(&Place { local, projection: tcx.intern_place_elems(projection) }) { + return; + } + if filter(ty) { // This might fail if `ty` is not scalar. let _ = self.register_with_ty(local, projection, ty); } + if max_derefs > 0 { if let Some(ty::TypeAndMut { ty: deref_ty, .. }) = ty.builtin_deref(false) { // References can only be tracked if the target is `!Freeze`. @@ -620,6 +640,7 @@ impl Map { deref_ty, filter, param_env, + exclude, ); projection.pop(); } @@ -632,7 +653,7 @@ impl Map { } projection.push(PlaceElem::Field(field, ty)); self.register_with_filter_rec( - tcx, max_derefs, local, projection, ty, filter, param_env, + tcx, max_derefs, local, projection, ty, filter, param_env, exclude, ); projection.pop(); }); @@ -751,6 +772,25 @@ impl PlaceInfo { } } +/// Returns all places, that have their reference or address taken. +fn escaped_places<'tcx>(body: &Body<'tcx>) -> Vec> { + struct Collector<'tcx> { + result: Vec>, + } + + impl<'tcx> Visitor<'tcx> for Collector<'tcx> { + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { + if context.is_borrow() || context.is_address_of() { + self.result.push(*place); + } + } + } + + let mut collector = Collector { result: Vec::new() }; + collector.visit_body(body); + collector.result +} + struct Children<'a> { map: &'a Map, next: Option, diff --git a/src/test/mir-opt/dataflow-const-prop/cast.rs b/src/test/mir-opt/dataflow-const-prop/cast.rs index bf5838cb89dd1..23c360ed87489 100644 --- a/src/test/mir-opt/dataflow-const-prop/cast.rs +++ b/src/test/mir-opt/dataflow-const-prop/cast.rs @@ -1,4 +1,5 @@ // unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts // EMIT_MIR cast.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff index b2c2ba6fa5c63..1a5ded8cc0df6 100644 --- a/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff @@ -3,30 +3,30 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/if.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/if.rs:+2:9: +2:10 - let mut _3: bool; // in scope 0 at $DIR/if.rs:+3:16: +3:24 - let mut _4: i32; // in scope 0 at $DIR/if.rs:+3:16: +3:19 - let mut _5: &i32; // in scope 0 at $DIR/if.rs:+3:17: +3:19 - let mut _7: i32; // in scope 0 at $DIR/if.rs:+4:13: +4:14 - let mut _9: bool; // in scope 0 at $DIR/if.rs:+6:16: +6:24 - let mut _10: i32; // in scope 0 at $DIR/if.rs:+6:16: +6:19 - let mut _11: &i32; // in scope 0 at $DIR/if.rs:+6:17: +6:19 - let mut _12: i32; // in scope 0 at $DIR/if.rs:+6:38: +6:39 - let mut _14: i32; // in scope 0 at $DIR/if.rs:+7:13: +7:14 + let _1: i32; // in scope 0 at $DIR/if.rs:+1:9: +1:10 + let mut _3: bool; // in scope 0 at $DIR/if.rs:+2:16: +2:24 + let mut _4: i32; // in scope 0 at $DIR/if.rs:+2:16: +2:19 + let mut _5: &i32; // in scope 0 at $DIR/if.rs:+2:17: +2:19 + let mut _7: i32; // in scope 0 at $DIR/if.rs:+3:13: +3:14 + let mut _9: bool; // in scope 0 at $DIR/if.rs:+5:16: +5:24 + let mut _10: i32; // in scope 0 at $DIR/if.rs:+5:16: +5:19 + let mut _11: &i32; // in scope 0 at $DIR/if.rs:+5:17: +5:19 + let mut _12: i32; // in scope 0 at $DIR/if.rs:+5:38: +5:39 + let mut _14: i32; // in scope 0 at $DIR/if.rs:+6:13: +6:14 scope 1 { - debug a => _1; // in scope 1 at $DIR/if.rs:+2:9: +2:10 - let _2: i32; // in scope 1 at $DIR/if.rs:+3:9: +3:10 + debug a => _1; // in scope 1 at $DIR/if.rs:+1:9: +1:10 + let _2: i32; // in scope 1 at $DIR/if.rs:+2:9: +2:10 scope 2 { - debug b => _2; // in scope 2 at $DIR/if.rs:+3:9: +3:10 - let _6: i32; // in scope 2 at $DIR/if.rs:+4:9: +4:10 + debug b => _2; // in scope 2 at $DIR/if.rs:+2:9: +2:10 + let _6: i32; // in scope 2 at $DIR/if.rs:+3:9: +3:10 scope 3 { - debug c => _6; // in scope 3 at $DIR/if.rs:+4:9: +4:10 - let _8: i32; // in scope 3 at $DIR/if.rs:+6:9: +6:10 + debug c => _6; // in scope 3 at $DIR/if.rs:+3:9: +3:10 + let _8: i32; // in scope 3 at $DIR/if.rs:+5:9: +5:10 scope 4 { - debug d => _8; // in scope 4 at $DIR/if.rs:+6:9: +6:10 - let _13: i32; // in scope 4 at $DIR/if.rs:+7:9: +7:10 + debug d => _8; // in scope 4 at $DIR/if.rs:+5:9: +5:10 + let _13: i32; // in scope 4 at $DIR/if.rs:+6:9: +6:10 scope 5 { - debug e => _13; // in scope 5 at $DIR/if.rs:+7:9: +7:10 + debug e => _13; // in scope 5 at $DIR/if.rs:+6:9: +6:10 } } } @@ -34,87 +34,87 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/if.rs:+2:9: +2:10 - _1 = const 1_i32; // scope 0 at $DIR/if.rs:+2:13: +2:14 - StorageLive(_2); // scope 1 at $DIR/if.rs:+3:9: +3:10 - StorageLive(_3); // scope 1 at $DIR/if.rs:+3:16: +3:24 - StorageLive(_4); // scope 1 at $DIR/if.rs:+3:16: +3:19 - StorageLive(_5); // scope 1 at $DIR/if.rs:+3:17: +3:19 - _5 = &_1; // scope 1 at $DIR/if.rs:+3:17: +3:19 -- _4 = (*_5); // scope 1 at $DIR/if.rs:+3:16: +3:19 -- _3 = Eq(move _4, const 1_i32); // scope 1 at $DIR/if.rs:+3:16: +3:24 -+ _4 = const 1_i32; // scope 1 at $DIR/if.rs:+3:16: +3:19 -+ _3 = const true; // scope 1 at $DIR/if.rs:+3:16: +3:24 - StorageDead(_5); // scope 1 at $DIR/if.rs:+3:23: +3:24 - StorageDead(_4); // scope 1 at $DIR/if.rs:+3:23: +3:24 -- switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+3:16: +3:24 -+ switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+3:16: +3:24 + StorageLive(_1); // scope 0 at $DIR/if.rs:+1:9: +1:10 + _1 = const 1_i32; // scope 0 at $DIR/if.rs:+1:13: +1:14 + StorageLive(_2); // scope 1 at $DIR/if.rs:+2:9: +2:10 + StorageLive(_3); // scope 1 at $DIR/if.rs:+2:16: +2:24 + StorageLive(_4); // scope 1 at $DIR/if.rs:+2:16: +2:19 + StorageLive(_5); // scope 1 at $DIR/if.rs:+2:17: +2:19 + _5 = &_1; // scope 1 at $DIR/if.rs:+2:17: +2:19 +- _4 = (*_5); // scope 1 at $DIR/if.rs:+2:16: +2:19 +- _3 = Eq(move _4, const 1_i32); // scope 1 at $DIR/if.rs:+2:16: +2:24 ++ _4 = const 1_i32; // scope 1 at $DIR/if.rs:+2:16: +2:19 ++ _3 = const true; // scope 1 at $DIR/if.rs:+2:16: +2:24 + StorageDead(_5); // scope 1 at $DIR/if.rs:+2:23: +2:24 + StorageDead(_4); // scope 1 at $DIR/if.rs:+2:23: +2:24 +- switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:24 ++ switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:24 } bb1: { - _2 = const 2_i32; // scope 1 at $DIR/if.rs:+3:27: +3:28 - goto -> bb3; // scope 1 at $DIR/if.rs:+3:13: +3:41 + _2 = const 2_i32; // scope 1 at $DIR/if.rs:+2:27: +2:28 + goto -> bb3; // scope 1 at $DIR/if.rs:+2:13: +2:41 } bb2: { - _2 = const 3_i32; // scope 1 at $DIR/if.rs:+3:38: +3:39 - goto -> bb3; // scope 1 at $DIR/if.rs:+3:13: +3:41 + _2 = const 3_i32; // scope 1 at $DIR/if.rs:+2:38: +2:39 + goto -> bb3; // scope 1 at $DIR/if.rs:+2:13: +2:41 } bb3: { - StorageDead(_3); // scope 1 at $DIR/if.rs:+3:40: +3:41 - StorageLive(_6); // scope 2 at $DIR/if.rs:+4:9: +4:10 - StorageLive(_7); // scope 2 at $DIR/if.rs:+4:13: +4:14 -- _7 = _2; // scope 2 at $DIR/if.rs:+4:13: +4:14 -- _6 = Add(move _7, const 1_i32); // scope 2 at $DIR/if.rs:+4:13: +4:18 -+ _7 = const 2_i32; // scope 2 at $DIR/if.rs:+4:13: +4:14 -+ _6 = const 3_i32; // scope 2 at $DIR/if.rs:+4:13: +4:18 - StorageDead(_7); // scope 2 at $DIR/if.rs:+4:17: +4:18 - StorageLive(_8); // scope 3 at $DIR/if.rs:+6:9: +6:10 - StorageLive(_9); // scope 3 at $DIR/if.rs:+6:16: +6:24 - StorageLive(_10); // scope 3 at $DIR/if.rs:+6:16: +6:19 - StorageLive(_11); // scope 3 at $DIR/if.rs:+6:17: +6:19 - _11 = &_1; // scope 3 at $DIR/if.rs:+6:17: +6:19 -- _10 = (*_11); // scope 3 at $DIR/if.rs:+6:16: +6:19 -- _9 = Eq(move _10, const 1_i32); // scope 3 at $DIR/if.rs:+6:16: +6:24 -+ _10 = const 1_i32; // scope 3 at $DIR/if.rs:+6:16: +6:19 -+ _9 = const true; // scope 3 at $DIR/if.rs:+6:16: +6:24 - StorageDead(_11); // scope 3 at $DIR/if.rs:+6:23: +6:24 - StorageDead(_10); // scope 3 at $DIR/if.rs:+6:23: +6:24 -- switchInt(move _9) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+6:16: +6:24 -+ switchInt(const true) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+6:16: +6:24 + StorageDead(_3); // scope 1 at $DIR/if.rs:+2:40: +2:41 + StorageLive(_6); // scope 2 at $DIR/if.rs:+3:9: +3:10 + StorageLive(_7); // scope 2 at $DIR/if.rs:+3:13: +3:14 +- _7 = _2; // scope 2 at $DIR/if.rs:+3:13: +3:14 +- _6 = Add(move _7, const 1_i32); // scope 2 at $DIR/if.rs:+3:13: +3:18 ++ _7 = const 2_i32; // scope 2 at $DIR/if.rs:+3:13: +3:14 ++ _6 = const 3_i32; // scope 2 at $DIR/if.rs:+3:13: +3:18 + StorageDead(_7); // scope 2 at $DIR/if.rs:+3:17: +3:18 + StorageLive(_8); // scope 3 at $DIR/if.rs:+5:9: +5:10 + StorageLive(_9); // scope 3 at $DIR/if.rs:+5:16: +5:24 + StorageLive(_10); // scope 3 at $DIR/if.rs:+5:16: +5:19 + StorageLive(_11); // scope 3 at $DIR/if.rs:+5:17: +5:19 + _11 = &_1; // scope 3 at $DIR/if.rs:+5:17: +5:19 +- _10 = (*_11); // scope 3 at $DIR/if.rs:+5:16: +5:19 +- _9 = Eq(move _10, const 1_i32); // scope 3 at $DIR/if.rs:+5:16: +5:24 ++ _10 = const 1_i32; // scope 3 at $DIR/if.rs:+5:16: +5:19 ++ _9 = const true; // scope 3 at $DIR/if.rs:+5:16: +5:24 + StorageDead(_11); // scope 3 at $DIR/if.rs:+5:23: +5:24 + StorageDead(_10); // scope 3 at $DIR/if.rs:+5:23: +5:24 +- switchInt(move _9) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:24 ++ switchInt(const true) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:24 } bb4: { -- _8 = _1; // scope 3 at $DIR/if.rs:+6:27: +6:28 -+ _8 = const 1_i32; // scope 3 at $DIR/if.rs:+6:27: +6:28 - goto -> bb6; // scope 3 at $DIR/if.rs:+6:13: +6:45 +- _8 = _1; // scope 3 at $DIR/if.rs:+5:27: +5:28 ++ _8 = const 1_i32; // scope 3 at $DIR/if.rs:+5:27: +5:28 + goto -> bb6; // scope 3 at $DIR/if.rs:+5:13: +5:45 } bb5: { - StorageLive(_12); // scope 3 at $DIR/if.rs:+6:38: +6:39 - _12 = _1; // scope 3 at $DIR/if.rs:+6:38: +6:39 - _8 = Add(move _12, const 1_i32); // scope 3 at $DIR/if.rs:+6:38: +6:43 - StorageDead(_12); // scope 3 at $DIR/if.rs:+6:42: +6:43 - goto -> bb6; // scope 3 at $DIR/if.rs:+6:13: +6:45 + StorageLive(_12); // scope 3 at $DIR/if.rs:+5:38: +5:39 + _12 = _1; // scope 3 at $DIR/if.rs:+5:38: +5:39 + _8 = Add(move _12, const 1_i32); // scope 3 at $DIR/if.rs:+5:38: +5:43 + StorageDead(_12); // scope 3 at $DIR/if.rs:+5:42: +5:43 + goto -> bb6; // scope 3 at $DIR/if.rs:+5:13: +5:45 } bb6: { - StorageDead(_9); // scope 3 at $DIR/if.rs:+6:44: +6:45 - StorageLive(_13); // scope 4 at $DIR/if.rs:+7:9: +7:10 - StorageLive(_14); // scope 4 at $DIR/if.rs:+7:13: +7:14 -- _14 = _8; // scope 4 at $DIR/if.rs:+7:13: +7:14 -- _13 = Add(move _14, const 1_i32); // scope 4 at $DIR/if.rs:+7:13: +7:18 -+ _14 = const 1_i32; // scope 4 at $DIR/if.rs:+7:13: +7:14 -+ _13 = const 2_i32; // scope 4 at $DIR/if.rs:+7:13: +7:18 - StorageDead(_14); // scope 4 at $DIR/if.rs:+7:17: +7:18 - _0 = const (); // scope 0 at $DIR/if.rs:+0:11: +8:2 - StorageDead(_13); // scope 4 at $DIR/if.rs:+8:1: +8:2 - StorageDead(_8); // scope 3 at $DIR/if.rs:+8:1: +8:2 - StorageDead(_6); // scope 2 at $DIR/if.rs:+8:1: +8:2 - StorageDead(_2); // scope 1 at $DIR/if.rs:+8:1: +8:2 - StorageDead(_1); // scope 0 at $DIR/if.rs:+8:1: +8:2 - return; // scope 0 at $DIR/if.rs:+8:2: +8:2 + StorageDead(_9); // scope 3 at $DIR/if.rs:+5:44: +5:45 + StorageLive(_13); // scope 4 at $DIR/if.rs:+6:9: +6:10 + StorageLive(_14); // scope 4 at $DIR/if.rs:+6:13: +6:14 +- _14 = _8; // scope 4 at $DIR/if.rs:+6:13: +6:14 +- _13 = Add(move _14, const 1_i32); // scope 4 at $DIR/if.rs:+6:13: +6:18 ++ _14 = const 1_i32; // scope 4 at $DIR/if.rs:+6:13: +6:14 ++ _13 = const 2_i32; // scope 4 at $DIR/if.rs:+6:13: +6:18 + StorageDead(_14); // scope 4 at $DIR/if.rs:+6:17: +6:18 + _0 = const (); // scope 0 at $DIR/if.rs:+0:11: +7:2 + StorageDead(_13); // scope 4 at $DIR/if.rs:+7:1: +7:2 + StorageDead(_8); // scope 3 at $DIR/if.rs:+7:1: +7:2 + StorageDead(_6); // scope 2 at $DIR/if.rs:+7:1: +7:2 + StorageDead(_2); // scope 1 at $DIR/if.rs:+7:1: +7:2 + StorageDead(_1); // scope 0 at $DIR/if.rs:+7:1: +7:2 + return; // scope 0 at $DIR/if.rs:+7:2: +7:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/if.rs b/src/test/mir-opt/dataflow-const-prop/if.rs index 8df8908047797..cc41da2dc9a2c 100644 --- a/src/test/mir-opt/dataflow-const-prop/if.rs +++ b/src/test/mir-opt/dataflow-const-prop/if.rs @@ -1,8 +1,8 @@ // unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts // EMIT_MIR if.main.DataflowConstProp.diff fn main() { - // This does not work (yet). Needs perhaps additional state to track unreachability. let a = 1; let b = if *&a == 1 { 2 } else { 3 }; let c = b + 1; diff --git a/src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff index 6af381617f9ac..f500c827786f8 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff @@ -37,7 +37,7 @@ StorageLive(_6); // scope 2 at $DIR/ref.rs:+3:16: +3:34 _6 = id() -> bb1; // scope 2 at $DIR/ref.rs:+3:16: +3:34 // mir::Constant - // + span: $DIR/ref.rs:7:16: 7:32 + // + span: $DIR/ref.rs:8:16: 8:32 // + literal: Const { ty: fn() -> u32 {id}, val: Value() } } diff --git a/src/test/mir-opt/dataflow-const-prop/ref.rs b/src/test/mir-opt/dataflow-const-prop/ref.rs index 6da613fc51632..6c0e3063b0ab6 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref.rs +++ b/src/test/mir-opt/dataflow-const-prop/ref.rs @@ -1,4 +1,5 @@ // unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts // EMIT_MIR ref.main.DataflowConstProp.diff fn main() { From 7a52e7350e3772ea9c04610f4d5ccd2b5b72403f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 7 Oct 2022 01:11:06 +0200 Subject: [PATCH 41/76] Add tests for Stacked Borrows behavior --- .../ref_with_sb.main.DataflowConstProp.diff | 46 +++++++++++++++++++ .../dataflow-const-prop/ref_with_sb.rs | 15 ++++++ ...ref_without_sb.main.DataflowConstProp.diff | 45 ++++++++++++++++++ .../dataflow-const-prop/ref_without_sb.rs | 14 ++++++ 4 files changed, 120 insertions(+) create mode 100644 src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs diff --git a/src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..6a9de6af8c59b --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff @@ -0,0 +1,46 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/ref_with_sb.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/ref_with_sb.rs:+1:9: +1:14 + let _2: (); // in scope 0 at $DIR/ref_with_sb.rs:+2:5: +2:15 + let mut _3: &i32; // in scope 0 at $DIR/ref_with_sb.rs:+2:12: +2:14 + let _4: &i32; // in scope 0 at $DIR/ref_with_sb.rs:+2:12: +2:14 + scope 1 { + debug a => _1; // in scope 1 at $DIR/ref_with_sb.rs:+1:9: +1:14 + let _5: i32; // in scope 1 at $DIR/ref_with_sb.rs:+6:9: +6:10 + scope 2 { + debug b => _5; // in scope 2 at $DIR/ref_with_sb.rs:+6:9: +6:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/ref_with_sb.rs:+1:9: +1:14 + _1 = const 0_i32; // scope 0 at $DIR/ref_with_sb.rs:+1:17: +1:18 + StorageLive(_2); // scope 1 at $DIR/ref_with_sb.rs:+2:5: +2:15 + StorageLive(_3); // scope 1 at $DIR/ref_with_sb.rs:+2:12: +2:14 + StorageLive(_4); // scope 1 at $DIR/ref_with_sb.rs:+2:12: +2:14 + _4 = &_1; // scope 1 at $DIR/ref_with_sb.rs:+2:12: +2:14 + _3 = &(*_4); // scope 1 at $DIR/ref_with_sb.rs:+2:12: +2:14 + _2 = escape::(move _3) -> bb1; // scope 1 at $DIR/ref_with_sb.rs:+2:5: +2:15 + // mir::Constant + // + span: $DIR/ref_with_sb.rs:10:5: 10:11 + // + literal: Const { ty: for<'a> fn(&'a i32) {escape::}, val: Value() } + } + + bb1: { + StorageDead(_3); // scope 1 at $DIR/ref_with_sb.rs:+2:14: +2:15 + StorageDead(_4); // scope 1 at $DIR/ref_with_sb.rs:+2:15: +2:16 + StorageDead(_2); // scope 1 at $DIR/ref_with_sb.rs:+2:15: +2:16 + _1 = const 1_i32; // scope 1 at $DIR/ref_with_sb.rs:+3:5: +3:10 + StorageLive(_5); // scope 1 at $DIR/ref_with_sb.rs:+6:9: +6:10 +- _5 = _1; // scope 1 at $DIR/ref_with_sb.rs:+6:13: +6:14 ++ _5 = const 1_i32; // scope 1 at $DIR/ref_with_sb.rs:+6:13: +6:14 + _0 = const (); // scope 0 at $DIR/ref_with_sb.rs:+0:11: +7:2 + StorageDead(_5); // scope 1 at $DIR/ref_with_sb.rs:+7:1: +7:2 + StorageDead(_1); // scope 0 at $DIR/ref_with_sb.rs:+7:1: +7:2 + return; // scope 0 at $DIR/ref_with_sb.rs:+7:2: +7:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs b/src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs new file mode 100644 index 0000000000000..05f18dab4cd62 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs @@ -0,0 +1,15 @@ +// unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts + +#[inline(never)] +fn escape(x: &T) {} + +// EMIT_MIR ref_with_sb.main.DataflowConstProp.diff +fn main() { + let mut a = 0; + escape(&a); + a = 1; + // With `-Zunsound-mir-opt`, this should be propagated + // (because we assume Stacked Borrows). + let b = a; +} diff --git a/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..66b05cdb7c107 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff @@ -0,0 +1,45 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/ref_without_sb.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/ref_without_sb.rs:+1:9: +1:14 + let _2: (); // in scope 0 at $DIR/ref_without_sb.rs:+2:5: +2:15 + let mut _3: &i32; // in scope 0 at $DIR/ref_without_sb.rs:+2:12: +2:14 + let _4: &i32; // in scope 0 at $DIR/ref_without_sb.rs:+2:12: +2:14 + scope 1 { + debug a => _1; // in scope 1 at $DIR/ref_without_sb.rs:+1:9: +1:14 + let _5: i32; // in scope 1 at $DIR/ref_without_sb.rs:+6:9: +6:10 + scope 2 { + debug b => _5; // in scope 2 at $DIR/ref_without_sb.rs:+6:9: +6:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/ref_without_sb.rs:+1:9: +1:14 + _1 = const 0_i32; // scope 0 at $DIR/ref_without_sb.rs:+1:17: +1:18 + StorageLive(_2); // scope 1 at $DIR/ref_without_sb.rs:+2:5: +2:15 + StorageLive(_3); // scope 1 at $DIR/ref_without_sb.rs:+2:12: +2:14 + StorageLive(_4); // scope 1 at $DIR/ref_without_sb.rs:+2:12: +2:14 + _4 = &_1; // scope 1 at $DIR/ref_without_sb.rs:+2:12: +2:14 + _3 = &(*_4); // scope 1 at $DIR/ref_without_sb.rs:+2:12: +2:14 + _2 = escape::(move _3) -> bb1; // scope 1 at $DIR/ref_without_sb.rs:+2:5: +2:15 + // mir::Constant + // + span: $DIR/ref_without_sb.rs:9:5: 9:11 + // + literal: Const { ty: for<'a> fn(&'a i32) {escape::}, val: Value() } + } + + bb1: { + StorageDead(_3); // scope 1 at $DIR/ref_without_sb.rs:+2:14: +2:15 + StorageDead(_4); // scope 1 at $DIR/ref_without_sb.rs:+2:15: +2:16 + StorageDead(_2); // scope 1 at $DIR/ref_without_sb.rs:+2:15: +2:16 + _1 = const 1_i32; // scope 1 at $DIR/ref_without_sb.rs:+3:5: +3:10 + StorageLive(_5); // scope 1 at $DIR/ref_without_sb.rs:+6:9: +6:10 + _5 = _1; // scope 1 at $DIR/ref_without_sb.rs:+6:13: +6:14 + _0 = const (); // scope 0 at $DIR/ref_without_sb.rs:+0:11: +7:2 + StorageDead(_5); // scope 1 at $DIR/ref_without_sb.rs:+7:1: +7:2 + StorageDead(_1); // scope 0 at $DIR/ref_without_sb.rs:+7:1: +7:2 + return; // scope 0 at $DIR/ref_without_sb.rs:+7:2: +7:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs new file mode 100644 index 0000000000000..4ef027a9b4d4f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs @@ -0,0 +1,14 @@ +// unit-test: DataflowConstProp + +#[inline(never)] +fn escape(x: &T) {} + +// EMIT_MIR ref_without_sb.main.DataflowConstProp.diff +fn main() { + let mut a = 0; + escape(&a); + a = 1; + // Without `-Zunsound-mir-opt`, this should not be propagated + // (because we do not assume Stacked Borrows). + let b = a; +} From b9dbb81b5e4f62be117fd196723a85e45b84341d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 7 Oct 2022 01:17:43 +0200 Subject: [PATCH 42/76] Improve example used for SB tests --- .../ref_with_sb.main.DataflowConstProp.diff | 30 ++++++++++++------- .../dataflow-const-prop/ref_with_sb.rs | 4 +++ ...ref_without_sb.main.DataflowConstProp.diff | 28 +++++++++++------ .../dataflow-const-prop/ref_without_sb.rs | 4 +++ 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff index 6a9de6af8c59b..81aa0a1a93d66 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff @@ -7,11 +7,12 @@ let _2: (); // in scope 0 at $DIR/ref_with_sb.rs:+2:5: +2:15 let mut _3: &i32; // in scope 0 at $DIR/ref_with_sb.rs:+2:12: +2:14 let _4: &i32; // in scope 0 at $DIR/ref_with_sb.rs:+2:12: +2:14 + let _5: (); // in scope 0 at $DIR/ref_with_sb.rs:+4:5: +4:20 scope 1 { debug a => _1; // in scope 1 at $DIR/ref_with_sb.rs:+1:9: +1:14 - let _5: i32; // in scope 1 at $DIR/ref_with_sb.rs:+6:9: +6:10 + let _6: i32; // in scope 1 at $DIR/ref_with_sb.rs:+7:9: +7:10 scope 2 { - debug b => _5; // in scope 2 at $DIR/ref_with_sb.rs:+6:9: +6:10 + debug b => _6; // in scope 2 at $DIR/ref_with_sb.rs:+7:9: +7:10 } } @@ -25,7 +26,7 @@ _3 = &(*_4); // scope 1 at $DIR/ref_with_sb.rs:+2:12: +2:14 _2 = escape::(move _3) -> bb1; // scope 1 at $DIR/ref_with_sb.rs:+2:5: +2:15 // mir::Constant - // + span: $DIR/ref_with_sb.rs:10:5: 10:11 + // + span: $DIR/ref_with_sb.rs:13:5: 13:11 // + literal: Const { ty: for<'a> fn(&'a i32) {escape::}, val: Value() } } @@ -34,13 +35,22 @@ StorageDead(_4); // scope 1 at $DIR/ref_with_sb.rs:+2:15: +2:16 StorageDead(_2); // scope 1 at $DIR/ref_with_sb.rs:+2:15: +2:16 _1 = const 1_i32; // scope 1 at $DIR/ref_with_sb.rs:+3:5: +3:10 - StorageLive(_5); // scope 1 at $DIR/ref_with_sb.rs:+6:9: +6:10 -- _5 = _1; // scope 1 at $DIR/ref_with_sb.rs:+6:13: +6:14 -+ _5 = const 1_i32; // scope 1 at $DIR/ref_with_sb.rs:+6:13: +6:14 - _0 = const (); // scope 0 at $DIR/ref_with_sb.rs:+0:11: +7:2 - StorageDead(_5); // scope 1 at $DIR/ref_with_sb.rs:+7:1: +7:2 - StorageDead(_1); // scope 0 at $DIR/ref_with_sb.rs:+7:1: +7:2 - return; // scope 0 at $DIR/ref_with_sb.rs:+7:2: +7:2 + StorageLive(_5); // scope 1 at $DIR/ref_with_sb.rs:+4:5: +4:20 + _5 = some_function() -> bb2; // scope 1 at $DIR/ref_with_sb.rs:+4:5: +4:20 + // mir::Constant + // + span: $DIR/ref_with_sb.rs:15:5: 15:18 + // + literal: Const { ty: fn() {some_function}, val: Value() } + } + + bb2: { + StorageDead(_5); // scope 1 at $DIR/ref_with_sb.rs:+4:20: +4:21 + StorageLive(_6); // scope 1 at $DIR/ref_with_sb.rs:+7:9: +7:10 +- _6 = _1; // scope 1 at $DIR/ref_with_sb.rs:+7:13: +7:14 ++ _6 = const 1_i32; // scope 1 at $DIR/ref_with_sb.rs:+7:13: +7:14 + _0 = const (); // scope 0 at $DIR/ref_with_sb.rs:+0:11: +8:2 + StorageDead(_6); // scope 1 at $DIR/ref_with_sb.rs:+8:1: +8:2 + StorageDead(_1); // scope 0 at $DIR/ref_with_sb.rs:+8:1: +8:2 + return; // scope 0 at $DIR/ref_with_sb.rs:+8:2: +8:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs b/src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs index 05f18dab4cd62..060aa6ab79472 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs +++ b/src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs @@ -4,11 +4,15 @@ #[inline(never)] fn escape(x: &T) {} +#[inline(never)] +fn some_function() {} + // EMIT_MIR ref_with_sb.main.DataflowConstProp.diff fn main() { let mut a = 0; escape(&a); a = 1; + some_function(); // With `-Zunsound-mir-opt`, this should be propagated // (because we assume Stacked Borrows). let b = a; diff --git a/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff index 66b05cdb7c107..dc6a6a8a7595d 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff @@ -7,11 +7,12 @@ let _2: (); // in scope 0 at $DIR/ref_without_sb.rs:+2:5: +2:15 let mut _3: &i32; // in scope 0 at $DIR/ref_without_sb.rs:+2:12: +2:14 let _4: &i32; // in scope 0 at $DIR/ref_without_sb.rs:+2:12: +2:14 + let _5: (); // in scope 0 at $DIR/ref_without_sb.rs:+4:5: +4:20 scope 1 { debug a => _1; // in scope 1 at $DIR/ref_without_sb.rs:+1:9: +1:14 - let _5: i32; // in scope 1 at $DIR/ref_without_sb.rs:+6:9: +6:10 + let _6: i32; // in scope 1 at $DIR/ref_without_sb.rs:+7:9: +7:10 scope 2 { - debug b => _5; // in scope 2 at $DIR/ref_without_sb.rs:+6:9: +6:10 + debug b => _6; // in scope 2 at $DIR/ref_without_sb.rs:+7:9: +7:10 } } @@ -25,7 +26,7 @@ _3 = &(*_4); // scope 1 at $DIR/ref_without_sb.rs:+2:12: +2:14 _2 = escape::(move _3) -> bb1; // scope 1 at $DIR/ref_without_sb.rs:+2:5: +2:15 // mir::Constant - // + span: $DIR/ref_without_sb.rs:9:5: 9:11 + // + span: $DIR/ref_without_sb.rs:12:5: 12:11 // + literal: Const { ty: for<'a> fn(&'a i32) {escape::}, val: Value() } } @@ -34,12 +35,21 @@ StorageDead(_4); // scope 1 at $DIR/ref_without_sb.rs:+2:15: +2:16 StorageDead(_2); // scope 1 at $DIR/ref_without_sb.rs:+2:15: +2:16 _1 = const 1_i32; // scope 1 at $DIR/ref_without_sb.rs:+3:5: +3:10 - StorageLive(_5); // scope 1 at $DIR/ref_without_sb.rs:+6:9: +6:10 - _5 = _1; // scope 1 at $DIR/ref_without_sb.rs:+6:13: +6:14 - _0 = const (); // scope 0 at $DIR/ref_without_sb.rs:+0:11: +7:2 - StorageDead(_5); // scope 1 at $DIR/ref_without_sb.rs:+7:1: +7:2 - StorageDead(_1); // scope 0 at $DIR/ref_without_sb.rs:+7:1: +7:2 - return; // scope 0 at $DIR/ref_without_sb.rs:+7:2: +7:2 + StorageLive(_5); // scope 1 at $DIR/ref_without_sb.rs:+4:5: +4:20 + _5 = some_function() -> bb2; // scope 1 at $DIR/ref_without_sb.rs:+4:5: +4:20 + // mir::Constant + // + span: $DIR/ref_without_sb.rs:14:5: 14:18 + // + literal: Const { ty: fn() {some_function}, val: Value() } + } + + bb2: { + StorageDead(_5); // scope 1 at $DIR/ref_without_sb.rs:+4:20: +4:21 + StorageLive(_6); // scope 1 at $DIR/ref_without_sb.rs:+7:9: +7:10 + _6 = _1; // scope 1 at $DIR/ref_without_sb.rs:+7:13: +7:14 + _0 = const (); // scope 0 at $DIR/ref_without_sb.rs:+0:11: +8:2 + StorageDead(_6); // scope 1 at $DIR/ref_without_sb.rs:+8:1: +8:2 + StorageDead(_1); // scope 0 at $DIR/ref_without_sb.rs:+8:1: +8:2 + return; // scope 0 at $DIR/ref_without_sb.rs:+8:2: +8:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs index 4ef027a9b4d4f..4789eb69cda60 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs +++ b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs @@ -3,11 +3,15 @@ #[inline(never)] fn escape(x: &T) {} +#[inline(never)] +fn some_function() {} + // EMIT_MIR ref_without_sb.main.DataflowConstProp.diff fn main() { let mut a = 0; escape(&a); a = 1; + some_function(); // Without `-Zunsound-mir-opt`, this should not be propagated // (because we do not assume Stacked Borrows). let b = a; From 5696d06e2282b5570bfe75c16eceacd8b34ddf99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 7 Oct 2022 01:24:24 +0200 Subject: [PATCH 43/76] Use the same is_enabled as the current const prop --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 8f77b2b0081a8..c73402705063d 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -15,8 +15,7 @@ pub struct DataflowConstProp; impl<'tcx> MirPass<'tcx> for DataflowConstProp { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - // Choose different minimum level? - sess.mir_opt_level() >= 4 + sess.mir_opt_level() >= 1 } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { From aaa35b3e48b768315a5f53b8523435f27b708d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 12 Oct 2022 23:46:31 +0200 Subject: [PATCH 44/76] Add comment for the current retag situation --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 9ae87418bc8b9..116a8b7bd4081 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -114,8 +114,13 @@ pub trait ValueAnalysis<'tcx> { // (A2) state.flood_with(place.as_ref(), self.map(), Self::Value::bottom()); } + StatementKind::Retag(..) => { + // A retag modifies the provenance of references. Currently references are only + // tracked if `-Zunsound-mir-opts` is given, but this might change in the future. + // However, it is still unclear how retags should be handled: + // https://github.com/rust-lang/rust/pull/101168#discussion_r985304895 + } StatementKind::Nop - | StatementKind::Retag(..) | StatementKind::FakeRead(..) | StatementKind::Coverage(..) | StatementKind::AscribeUserType(..) => (), From 890fae9c60debadd0ce80e67ac1b4d6d8bf5c81e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Thu, 13 Oct 2022 01:02:18 +0200 Subject: [PATCH 45/76] Fix rebased CastKind --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index c73402705063d..f30dc741abbb1 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -96,7 +96,14 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { state: &mut State, ) -> ValueOrPlaceOrRef { match rvalue { - Rvalue::Cast(CastKind::Misc, operand, ty) => { + Rvalue::Cast( + CastKind::IntToInt + | CastKind::FloatToInt + | CastKind::FloatToFloat + | CastKind::IntToFloat, + operand, + ty, + ) => { let operand = self.eval_operand(operand, state); match operand { FlatSet::Elem(operand) => self From 8bed0b5936179179a84fb7347fc2db57f84b4472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 15 Oct 2022 17:26:11 +0200 Subject: [PATCH 46/76] Update issue-50814.rs test result --- src/test/ui/consts/const-eval/issue-50814.rs | 10 +++++---- .../ui/consts/const-eval/issue-50814.stderr | 22 ++++++++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs index 5a587701f787a..e3f0fb90c8f0a 100644 --- a/src/test/ui/consts/const-eval/issue-50814.rs +++ b/src/test/ui/consts/const-eval/issue-50814.rs @@ -9,16 +9,18 @@ impl Unsigned for U8 { const MAX: u8 = 0xff; } -struct Sum(A,B); +struct Sum(A, B); -impl Unsigned for Sum { +impl Unsigned for Sum { const MAX: u8 = A::MAX + B::MAX; //~^ ERROR evaluation of ` as Unsigned>::MAX` failed + //~| ERROR evaluation of ` as Unsigned>::MAX` failed } fn foo(_: T) -> &'static u8 { - &Sum::::MAX - //~^ ERROR E0080 + &Sum::::MAX + //~^ ERROR evaluation of `foo::` failed [E0080] + //~| ERROR evaluation of `foo::` failed [E0080] } fn main() { diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr index 46dd2b89fa2ac..07f3033c44fee 100644 --- a/src/test/ui/consts/const-eval/issue-50814.stderr +++ b/src/test/ui/consts/const-eval/issue-50814.stderr @@ -4,18 +4,30 @@ error[E0080]: evaluation of ` as Unsigned>::MAX` failed LL | const MAX: u8 = A::MAX + B::MAX; | ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow +error[E0080]: evaluation of `foo::` failed + --> $DIR/issue-50814.rs:21:6 + | +LL | &Sum::::MAX + | ^^^^^^^^^^^^^^^^^^ referenced constant has errors + +error[E0080]: evaluation of ` as Unsigned>::MAX` failed + --> $DIR/issue-50814.rs:15:21 + | +LL | const MAX: u8 = A::MAX + B::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow + error[E0080]: evaluation of `foo::` failed - --> $DIR/issue-50814.rs:20:6 + --> $DIR/issue-50814.rs:21:6 | -LL | &Sum::::MAX - | ^^^^^^^^^^^^^^^^^ referenced constant has errors +LL | &Sum::::MAX + | ^^^^^^^^^^^^^^^^^^ referenced constant has errors note: the above error was encountered while instantiating `fn foo::` - --> $DIR/issue-50814.rs:25:5 + --> $DIR/issue-50814.rs:27:5 | LL | foo(0); | ^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0080`. From 1dde908fae0c5c1f33d4a19bee1c58fd36c42cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 15 Oct 2022 17:38:40 +0200 Subject: [PATCH 47/76] Update test results --- .../dataflow-const-prop/cast.main.DataflowConstProp.diff | 2 +- .../previous/cast.main.DataflowConstProp.diff | 4 ++-- .../previous/indirect.main.DataflowConstProp.diff | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff index 950b0518e0bb2..a8f04c9fc7f43 100644 --- a/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff @@ -24,7 +24,7 @@ StorageLive(_5); // scope 1 at $DIR/cast.rs:+2:14: +2:16 _5 = &_1; // scope 1 at $DIR/cast.rs:+2:14: +2:16 - _4 = (*_5); // scope 1 at $DIR/cast.rs:+2:13: +2:16 -- _3 = move _4 as u8 (Misc); // scope 1 at $DIR/cast.rs:+2:13: +2:22 +- _3 = move _4 as u8 (IntToInt); // scope 1 at $DIR/cast.rs:+2:13: +2:22 + _4 = const 257_i32; // scope 1 at $DIR/cast.rs:+2:13: +2:16 + _3 = const 1_u8; // scope 1 at $DIR/cast.rs:+2:13: +2:22 StorageDead(_4); // scope 1 at $DIR/cast.rs:+2:21: +2:22 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff index fb346993d6133..3fd9fb5331b07 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff @@ -14,10 +14,10 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/cast.rs:+1:9: +1:10 -- _1 = const 42_u8 as u32 (Misc); // scope 0 at $DIR/cast.rs:+1:13: +1:24 +- _1 = const 42_u8 as u32 (IntToInt); // scope 0 at $DIR/cast.rs:+1:13: +1:24 + _1 = const 42_u32; // scope 0 at $DIR/cast.rs:+1:13: +1:24 StorageLive(_2); // scope 1 at $DIR/cast.rs:+3:9: +3:10 -- _2 = const 42_u32 as u8 (Misc); // scope 1 at $DIR/cast.rs:+3:13: +3:24 +- _2 = const 42_u32 as u8 (IntToInt); // scope 1 at $DIR/cast.rs:+3:13: +3:24 + _2 = const 42_u8; // scope 1 at $DIR/cast.rs:+3:13: +3:24 _0 = const (); // scope 0 at $DIR/cast.rs:+0:11: +4:2 StorageDead(_2); // scope 1 at $DIR/cast.rs:+4:1: +4:2 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff index 461ed4d8922b8..80deb02c77f56 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff @@ -13,7 +13,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/indirect.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/indirect.rs:+1:13: +1:25 -- _2 = const 2_u32 as u8 (Misc); // scope 0 at $DIR/indirect.rs:+1:13: +1:25 +- _2 = const 2_u32 as u8 (IntToInt); // scope 0 at $DIR/indirect.rs:+1:13: +1:25 - _3 = CheckedAdd(_2, const 1_u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 - assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 + _2 = const 2_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:25 From be9013f02b629ec7b6d40a5a4ff7966e2df751f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 15 Oct 2022 19:24:02 +0200 Subject: [PATCH 48/76] Make overflow flag propagation conditional --- .../src/dataflow_const_prop.rs | 18 +++++++- ...low_checks_use.main.DataflowConstProp.diff | 45 +++++++++++++++++++ .../inherit_overflow_checks_use.rs | 8 ++++ 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.rs diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index f30dc741abbb1..2d7768105eb6c 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -7,7 +7,7 @@ use rustc_mir_dataflow::value_analysis::{ Map, ProjElem, State, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef, }; use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects}; -use rustc_span::DUMMY_SP; +use rustc_span::{sym, DUMMY_SP}; use crate::MirPass; @@ -38,6 +38,7 @@ struct ConstAnalysis<'tcx> { tcx: TyCtxt<'tcx>, ecx: InterpCx<'tcx, 'tcx, DummyMachine>, param_env: ty::ParamEnv<'tcx>, + propagate_overflow: bool, } impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { @@ -72,7 +73,11 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { }); if value_target.is_some() || overflow_target.is_some() { - let (val, overflow) = self.binary_op(state, *op, left, right); + let (val, mut overflow) = self.binary_op(state, *op, left, right); + + if !self.propagate_overflow { + overflow = FlatSet::Top; + } if let Some(value_target) = value_target { state.assign_idx(value_target, ValueOrPlaceOrRef::Value(val), self.map()); @@ -202,11 +207,20 @@ impl<'tcx> std::fmt::Debug for ScalarTy<'tcx> { impl<'tcx> ConstAnalysis<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, map: Map) -> Self { + // It can happen that overflow will be detected even though overflow checks are disabled. + // This is caused by inlining functions that have #[rustc_inherit_overflow_checks]. Such + // overflows must not be propagated if `-C overflow-checks=off`. Also, if the function we + // are optimizing here has #[rustc_inherit_overflow_checks], the overflow checks may + // actually not be triggered by the consuming crate, so we have to ignore them too. + // Related to https://github.com/rust-lang/rust/issues/35310. + let propagate_overflow = tcx.sess.overflow_checks() + && !tcx.has_attr(body.source.def_id(), sym::rustc_inherit_overflow_checks); Self { map, tcx, ecx: InterpCx::new(tcx, DUMMY_SP, ty::ParamEnv::empty(), DummyMachine), param_env: tcx.param_env(body.source.def_id()), + propagate_overflow, } } diff --git a/src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..53c7ec4168047 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.main.DataflowConstProp.diff @@ -0,0 +1,45 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inherit_overflow_checks_use.rs:+0:11: +0:11 + let mut _1: u8; // in scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + let mut _2: u8; // in scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + let mut _3: u8; // in scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + scope 1 { + } + scope 2 (inlined ::add) { // at $DIR/inherit_overflow_checks_use.rs:7:13: 7:47 + debug self => _2; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + debug other => _3; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + let mut _4: u8; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + let mut _5: u8; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + let mut _6: (u8, bool); // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + StorageLive(_2); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + _2 = const u8::MAX; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + StorageLive(_3); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + _3 = const 1_u8; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + StorageLive(_4); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + _4 = const u8::MAX; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + StorageLive(_5); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + _5 = const 1_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + _6 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + } + + bb1: { +- _1 = move (_6.0: u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL ++ _1 = const 0_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + StorageDead(_5); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + StorageDead(_4); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + StorageDead(_3); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + StorageDead(_2); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + StorageDead(_1); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:47: +3:48 + nop; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+0:11: +4:2 + return; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.rs b/src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.rs new file mode 100644 index 0000000000000..d4fcb1d77052b --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.rs @@ -0,0 +1,8 @@ +// compile-flags: -C overflow-checks=off + +// EMIT_MIR inherit_overflow_checks_use.main.DataflowConstProp.diff +fn main() { + // After inlining, this will contain a `CheckedBinaryOp`. The overflow + // must be ignored by the constant propagation to avoid triggering a panic. + let _ = ::add(255, 1); +} From 931d99f61f93e244a60fb0a65198382ef9d66a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 15 Oct 2022 23:40:03 +0200 Subject: [PATCH 49/76] Make overflow handling more precise --- .../src/dataflow_const_prop.rs | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 2d7768105eb6c..d4111fa313aa0 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -73,16 +73,26 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { }); if value_target.is_some() || overflow_target.is_some() { - let (val, mut overflow) = self.binary_op(state, *op, left, right); - - if !self.propagate_overflow { - overflow = FlatSet::Top; - } + let (val, overflow) = self.binary_op(state, *op, left, right); if let Some(value_target) = value_target { state.assign_idx(value_target, ValueOrPlaceOrRef::Value(val), self.map()); } if let Some(overflow_target) = overflow_target { + let overflow = match overflow { + FlatSet::Top => FlatSet::Top, + FlatSet::Elem(overflow) => { + if overflow && !self.propagate_overflow { + FlatSet::Top + } else { + self.wrap_scalar( + Scalar::from_bool(overflow), + self.tcx.types.bool, + ) + } + } + FlatSet::Bottom => FlatSet::Bottom, + }; state.assign_idx( overflow_target, ValueOrPlaceOrRef::Value(overflow), @@ -120,8 +130,8 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { } } Rvalue::BinaryOp(op, box (left, right)) => { + // Overflows must be ignored here. let (val, _overflow) = self.binary_op(state, *op, left, right); - // FIXME: Just ignore overflow here? ValueOrPlaceOrRef::Value(val) } Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) { @@ -230,16 +240,13 @@ impl<'tcx> ConstAnalysis<'tcx> { op: BinOp, left: &Operand<'tcx>, right: &Operand<'tcx>, - ) -> (FlatSet>, FlatSet>) { + ) -> (FlatSet>, FlatSet) { let left = self.eval_operand(left, state); let right = self.eval_operand(right, state); match (left, right) { (FlatSet::Elem(left), FlatSet::Elem(right)) => { match self.ecx.overflowing_binary_op(op, &left, &right) { - Ok((val, overflow, ty)) => ( - self.wrap_scalar(val, ty), - self.wrap_scalar(Scalar::from_bool(overflow), self.tcx.types.bool), - ), + Ok((val, overflow, ty)) => (self.wrap_scalar(val, ty), FlatSet::Elem(overflow)), _ => (FlatSet::Top, FlatSet::Top), } } From 274a49132b7728fa7254fa4b5bd0575bdffa8b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 19 Oct 2022 15:56:58 +0200 Subject: [PATCH 50/76] Improve documentation, plus some small changes --- .../rustc_mir_dataflow/src/value_analysis.rs | 202 +++++++++++------- .../src/dataflow_const_prop.rs | 24 ++- .../checked.main.DataflowConstProp.diff | 3 +- ...implification.hello.DataflowConstProp.diff | 3 +- 4 files changed, 143 insertions(+), 89 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 116a8b7bd4081..4f092d36103fb 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -192,13 +192,27 @@ pub trait ValueAnalysis<'tcx> { .map(ValueOrPlaceOrRef::Ref) .unwrap_or(ValueOrPlaceOrRef::top()), Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + // This is not a `&x` reference and could be used for modification. state.flood(place.as_ref(), self.map()); ValueOrPlaceOrRef::top() } Rvalue::CopyForDeref(place) => { self.handle_operand(&Operand::Copy(*place), state).into() } - _ => ValueOrPlaceOrRef::top(), + Rvalue::Repeat(..) + | Rvalue::ThreadLocalRef(..) + | Rvalue::Len(..) + | Rvalue::Cast(..) + | Rvalue::BinaryOp(..) + | Rvalue::CheckedBinaryOp(..) + | Rvalue::NullaryOp(..) + | Rvalue::UnaryOp(..) + | Rvalue::Discriminant(..) + | Rvalue::Aggregate(..) + | Rvalue::ShallowInitBox(..) => { + // No modification is possible through these r-values. + ValueOrPlaceOrRef::top() + } } } @@ -419,7 +433,7 @@ enum StateData { #[derive(PartialEq, Eq, Clone, Debug)] pub struct State(StateData); -impl State { +impl State { pub fn is_reachable(&self) -> bool { matches!(&self.0, StateData::Reachable(_)) } @@ -460,6 +474,10 @@ impl State { self.flood_idx_with(place, map, V::top()) } + /// Copies `source` to `target`, including all tracked places beneath. + /// + /// If `target` contains a place that is not contained in `source`, it will be overwritten with + /// Top. Also, because this will copy all entries one after another, it may only be pub fn assign_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map) { // We use (A3) and copy all entries one after another. let StateData::Reachable(values) = &mut self.0 else { return }; @@ -514,7 +532,7 @@ impl State { // track *what* it points to (as in, what do we know about the target). For an // assignment `x = &y`, we thus copy the info we have for `y` to `*x`. This is // sound because we only track places that are `Freeze`, and (A4). - if let Some(target_deref) = map.apply_elem(target, ProjElem::Deref) { + if let Some(target_deref) = map.apply(target, TrackElem::Deref) { self.assign_place_idx(target_deref, source, map); } } @@ -530,7 +548,10 @@ impl State { StateData::Reachable(values) => { map.places[place].value_index.map(|v| values[v].clone()).unwrap_or(V::top()) } - StateData::Unreachable => V::top(), + StateData::Unreachable => { + // Because this is unreachable, we can return any value we want. + V::bottom() + } } } } @@ -548,10 +569,15 @@ impl JoinSemiLattice for State { } } +/// A partial mapping from `Place` to `PlaceIndex`. +/// +/// Some additioanl bookkeeping is done to speed up traversal: +/// - For iteration, every [`PlaceInfo`] contains an intrusive linked list of its children. +/// - To directly get the child for a specific projection, there is `projections` map. #[derive(Debug)] pub struct Map { locals: IndexVec>, - projections: FxHashMap<(PlaceIndex, ProjElem), PlaceIndex>, + projections: FxHashMap<(PlaceIndex, TrackElem), PlaceIndex>, places: IndexVec, value_count: usize, } @@ -566,7 +592,10 @@ impl Map { } } - /// Register all suitable places with matching types (up to a certain depth). + /// Returns a map that only tracks places whose type passes the filter. + /// + /// This is currently the only way to create a [`Map`]. The way in which the tracked places are + /// chosen is an implementation detail an may not be relied upon. pub fn from_filter<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -579,7 +608,9 @@ impl Map { // the correctness relies on an aliasing model similar to Stacked Borrows (which is // not yet guaranteed). if tcx.sess.opts.unstable_opts.unsound_mir_opts { - map.register_with_filter(tcx, body, 3, filter, &[]); + // We might want to add additional limitations. If a struct has 10 boxed fields of + // itself, will currently be `10.pow(max_derefs)` tracked places. + map.register_with_filter(tcx, body, 2, filter, &[]); } else { map.register_with_filter(tcx, body, 0, filter, &escaped_places(body)); } @@ -587,6 +618,7 @@ impl Map { map } + /// Register all non-excluded places that pass the filter, up to a certain dereference depth. fn register_with_filter<'tcx>( &mut self, tcx: TyCtxt<'tcx>, @@ -595,7 +627,9 @@ impl Map { mut filter: impl FnMut(Ty<'tcx>) -> bool, exclude: &[Place<'tcx>], ) { + // This is used to tell whether a type is `!Freeze`. let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let mut projection = Vec::new(); for (local, decl) in body.local_decls.iter_enumerated() { self.register_with_filter_rec( @@ -622,7 +656,7 @@ impl Map { param_env: ty::ParamEnv<'tcx>, exclude: &[Place<'tcx>], ) { - // This check could be improved. + // This currently does a linear scan, could be improved. if exclude.contains(&Place { local, projection: tcx.intern_place_elems(projection) }) { return; } @@ -664,6 +698,9 @@ impl Map { }); } + /// Tries to add the place to the map, without allocating a value slot. + /// + /// Can fail if the projection contains non-trackable elements. fn make_place<'tcx>( &mut self, local: Local, @@ -675,10 +712,6 @@ impl Map { // Apply the projection. for &elem in projection { - match elem { - PlaceElem::Downcast(..) => return Err(()), - _ => (), - } let elem = elem.try_into()?; index = *self.projections.entry((index, elem)).or_insert_with(|| { // Prepend new child to the linked list. @@ -713,6 +746,7 @@ impl Map { self.register_with_ty(local, projection, place_ty.ty) } + /// Tries to track the given place. Fails if type is non-scalar or projection is not trackable. fn register_with_ty<'tcx>( &mut self, local: Local, @@ -736,7 +770,7 @@ impl Map { Ok(()) } - pub fn apply_elem(&self, place: PlaceIndex, elem: ProjElem) -> Option { + pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option { self.projections.get(&(place, elem)).copied() } @@ -744,12 +778,13 @@ impl Map { let mut index = *self.locals.get(place.local)?.as_ref()?; for &elem in place.projection { - index = self.apply_elem(index, elem.try_into().ok()?)?; + index = self.apply(index, elem.try_into().ok()?)?; } Some(index) } + /// Iterate over all direct children. pub fn children(&self, parent: PlaceIndex) -> impl Iterator + '_ { Children::new(self, parent) } @@ -762,40 +797,31 @@ impl Map { } } +/// This is the information tracked for every [`PlaceIndex`] and is stored by [`Map`]. +/// +/// Together, `first_child` and `next_sibling` form an intrusive linked list, which is used to +/// model a tree structure (a replacement for a member like `children: Vec`). #[derive(Debug)] struct PlaceInfo { - next_sibling: Option, - first_child: Option, - /// The projection used to go from parent to this node (only None for root). - proj_elem: Option, + /// We store a [`ValueIndex`] if and only if the placed is tracked by the analysis. value_index: Option, + + /// The projection used to go from parent to this node (only None for root). + proj_elem: Option, + + /// The left-most child. + first_child: Option, + + /// Index of the sibling to the right of this node. + next_sibling: Option, } impl PlaceInfo { - fn new(proj_elem: Option) -> Self { + fn new(proj_elem: Option) -> Self { Self { next_sibling: None, first_child: None, proj_elem, value_index: None } } } -/// Returns all places, that have their reference or address taken. -fn escaped_places<'tcx>(body: &Body<'tcx>) -> Vec> { - struct Collector<'tcx> { - result: Vec>, - } - - impl<'tcx> Visitor<'tcx> for Collector<'tcx> { - fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - if context.is_borrow() || context.is_address_of() { - self.result.push(*place); - } - } - } - - let mut collector = Collector { result: Vec::new() }; - collector.visit_body(body); - collector.result -} - struct Children<'a> { map: &'a Map, next: Option, @@ -820,25 +846,28 @@ impl<'a> Iterator for Children<'a> { } } } + +/// Used as the result of an operand. pub enum ValueOrPlace { Value(V), Place(PlaceIndex), } -impl ValueOrPlace { - pub fn top() -> Self { +impl HasTop for ValueOrPlace { + fn top() -> Self { ValueOrPlace::Value(V::top()) } } +/// Used as the result of an r-value. pub enum ValueOrPlaceOrRef { Value(V), Place(PlaceIndex), Ref(PlaceIndex), } -impl ValueOrPlaceOrRef { - pub fn top() -> Self { +impl HasTop for ValueOrPlaceOrRef { + fn top() -> Self { ValueOrPlaceOrRef::Value(V::top()) } } @@ -872,27 +901,28 @@ impl HasTop for FlatSet { } } -/// Currently, we only track places through deref and field projections. +/// The set of projection elements that can be used by a tracked place. /// /// For now, downcast is not allowed due to aliasing between variants (see #101168). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum ProjElem { +pub enum TrackElem { Deref, Field(Field), } -impl TryFrom> for ProjElem { +impl TryFrom> for TrackElem { type Error = (); fn try_from(value: ProjectionElem) -> Result { match value { - ProjectionElem::Deref => Ok(ProjElem::Deref), - ProjectionElem::Field(field, _) => Ok(ProjElem::Field(field)), + ProjectionElem::Deref => Ok(TrackElem::Deref), + ProjectionElem::Field(field, _) => Ok(TrackElem::Field(field)), _ => Err(()), } } } +/// Invokes `f` on all direct fields of `ty`. fn iter_fields<'tcx>( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, @@ -922,6 +952,53 @@ fn iter_fields<'tcx>( } } +/// Returns all places, that have their reference or address taken. +fn escaped_places<'tcx>(body: &Body<'tcx>) -> Vec> { + struct Collector<'tcx> { + result: Vec>, + } + + impl<'tcx> Visitor<'tcx> for Collector<'tcx> { + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { + if context.is_borrow() || context.is_address_of() { + self.result.push(*place); + } + } + } + + let mut collector = Collector { result: Vec::new() }; + collector.visit_body(body); + collector.result +} + +/// This is used to visualize the dataflow analysis. +impl<'tcx, T> DebugWithContext> for State +where + T: ValueAnalysis<'tcx>, + T::Value: Debug, +{ + fn fmt_with(&self, ctxt: &ValueAnalysisWrapper, f: &mut Formatter<'_>) -> std::fmt::Result { + match &self.0 { + StateData::Reachable(values) => debug_with_context(values, None, ctxt.0.map(), f), + StateData::Unreachable => write!(f, "unreachable"), + } + } + + fn fmt_diff_with( + &self, + old: &Self, + ctxt: &ValueAnalysisWrapper, + f: &mut Formatter<'_>, + ) -> std::fmt::Result { + match (&self.0, &old.0) { + (StateData::Reachable(this), StateData::Reachable(old)) => { + debug_with_context(this, Some(old), ctxt.0.map(), f) + } + _ => Ok(()), // Consider printing something here. + } + } +} + fn debug_with_context_rec( place: PlaceIndex, place_str: &str, @@ -945,8 +1022,8 @@ fn debug_with_context_rec( for child in map.children(place) { let info_elem = map.places[child].proj_elem.unwrap(); let child_place_str = match info_elem { - ProjElem::Deref => format!("*{}", place_str), - ProjElem::Field(field) => { + TrackElem::Deref => format!("*{}", place_str), + TrackElem::Field(field) => { if place_str.starts_with("*") { format!("({}).{}", place_str, field.index()) } else { @@ -973,30 +1050,3 @@ fn debug_with_context( } Ok(()) } - -impl<'tcx, T> DebugWithContext> for State -where - T: ValueAnalysis<'tcx>, - T::Value: Debug, -{ - fn fmt_with(&self, ctxt: &ValueAnalysisWrapper, f: &mut Formatter<'_>) -> std::fmt::Result { - match &self.0 { - StateData::Reachable(values) => debug_with_context(values, None, ctxt.0.map(), f), - StateData::Unreachable => write!(f, "unreachable"), - } - } - - fn fmt_diff_with( - &self, - old: &Self, - ctxt: &ValueAnalysisWrapper, - f: &mut Formatter<'_>, - ) -> std::fmt::Result { - match (&self.0, &old.0) { - (StateData::Reachable(this), StateData::Reachable(old)) => { - debug_with_context(this, Some(old), ctxt.0.map(), f) - } - _ => Ok(()), // Consider printing something here. - } - } -} diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index d4111fa313aa0..75d9ea16bd60c 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -1,10 +1,14 @@ +//! A constant propagation optimization pass based on dataflow analysis. +//! +//! Tracks places that have a scalar type. + use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::visit::{MutVisitor, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{ - Map, ProjElem, State, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef, + HasTop, Map, State, TrackElem, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef, }; use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects}; use rustc_span::{sym, DUMMY_SP}; @@ -20,7 +24,7 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Decide which places to track during the analysis. - let map = Map::from_filter(tcx, body, |ty| ty.is_scalar() && !ty.is_unsafe_ptr()); + let map = Map::from_filter(tcx, body, Ty::is_scalar); // Perform the actual dataflow analysis. let analysis = ConstAnalysis::new(tcx, body, map); @@ -65,12 +69,10 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { state.flood_idx(target, self.map()); } - let value_target = target.and_then(|target| { - self.map().apply_elem(target, ProjElem::Field(0_u32.into())) - }); - let overflow_target = target.and_then(|target| { - self.map().apply_elem(target, ProjElem::Field(1_u32.into())) - }); + let value_target = target + .and_then(|target| self.map().apply(target, TrackElem::Field(0_u32.into()))); + let overflow_target = target + .and_then(|target| self.map().apply(target, TrackElem::Field(1_u32.into()))); if value_target.is_some() || overflow_target.is_some() { let (val, overflow) = self.binary_op(state, *op, left, right); @@ -211,6 +213,7 @@ struct ScalarTy<'tcx>(Scalar, Ty<'tcx>); impl<'tcx> std::fmt::Debug for ScalarTy<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // This is used for dataflow visualization, so we return something more concise. std::fmt::Display::fmt(&ConstantKind::Val(ConstValue::Scalar(self.0), self.1), f) } } @@ -341,13 +344,16 @@ impl<'mir, 'tcx, 'map> ResultsVisitor<'mir, 'tcx> for CollectAndPatch<'tcx, 'map location: Location, ) { match statement.kind { + StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(_)))) => { + // Don't overwrite the assignment if it already uses a constant (to keep the span). + } StatementKind::Assign(box (place, _)) => match state.get(place.as_ref(), self.map) { FlatSet::Top => (), FlatSet::Elem(value) => { self.assignments.insert(location, value); } FlatSet::Bottom => { - // This statement is not reachable. Do nothing, it will (hopefully) be removed. + // This assignment is either unreachable, or an uninitialized value is assigned. } }, _ => (), diff --git a/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff index fbc95cea7cd95..944afed8f465a 100644 --- a/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff @@ -53,8 +53,7 @@ StorageDead(_5); // scope 2 at $DIR/checked.rs:+3:17: +3:18 StorageDead(_4); // scope 2 at $DIR/checked.rs:+3:17: +3:18 StorageLive(_7); // scope 3 at $DIR/checked.rs:+5:9: +5:10 -- _7 = const _; // scope 3 at $DIR/checked.rs:+5:13: +5:21 -+ _7 = const i32::MAX; // scope 3 at $DIR/checked.rs:+5:13: +5:21 + _7 = const _; // scope 3 at $DIR/checked.rs:+5:13: +5:21 StorageLive(_8); // scope 4 at $DIR/checked.rs:+6:9: +6:10 StorageLive(_9); // scope 4 at $DIR/checked.rs:+6:13: +6:14 - _9 = _7; // scope 4 at $DIR/checked.rs:+6:13: +6:14 diff --git a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff index f13ca4b62e6fb..d990c3b07e518 100644 --- a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff @@ -8,8 +8,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 -- _1 = const _; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 -+ _1 = const false; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 + _1 = const _; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 } From 062053ba7950076ce25600896302cb3a363d7862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 19 Oct 2022 16:29:01 +0200 Subject: [PATCH 51/76] Fix unimplemented binary_ptr_op --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 75d9ea16bd60c..b4078625d83d8 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -474,7 +474,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi _left: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>, _right: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>, ) -> interpret::InterpResult<'tcx, (interpret::Scalar, bool, Ty<'tcx>)> { - unimplemented!() + throw_unsup!(Unsupported("".into())) } fn expose_ptr( From 5b7b309c60465ec948b42332673ac3860f2d2482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 21 Oct 2022 17:02:03 +0200 Subject: [PATCH 52/76] Improve documentation of assumptions --- .../rustc_mir_dataflow/src/value_analysis.rs | 116 ++++++++---------- 1 file changed, 51 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 4f092d36103fb..8169c41d99557 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -1,69 +1,49 @@ //! This module provides a framework on top of the normal MIR dataflow framework to simplify the -//! implementation of analyses that track the values stored in places of interest. +//! implementation of analyses that track information about the values stored in certain places. +//! We are using the term "place" here to refer to a `mir::Place` (a place expression) instead of +//! an `interpret::Place` (a memory location). //! //! The default methods of [`ValueAnalysis`] (prefixed with `super_` instead of `handle_`) //! provide some behavior that should be valid for all abstract domains that are based only on the //! value stored in a certain place. On top of these default rules, an implementation should //! override some of the `handle_` methods. For an example, see `ConstAnalysis`. //! -//! An implementation must also provide a [`Map`]. Before the anaylsis begins, all places that -//! should be tracked during the analysis must be registered. Currently, the projections of these -//! places may only contain derefs, fields and downcasts (otherwise registration fails). During the -//! analysis, no new places can be registered. +//! An implementation must also provide a [`Map`]. Before the analysis begins, all places that +//! should be tracked during the analysis must be registered. During the analysis, no new places +//! can be registered. The [`State`] can be queried to retrieve the abstract value stored for a +//! certain place by passing the map. //! -//! Note that if you want to track values behind references, you have to register the dereferenced -//! place. For example: Assume `let x = (0, 0)` and that we want to propagate values from `x.0` and -//! `x.1` also through the assignment `let y = &x`. In this case, we should register `x.0`, `x.1`, -//! `(*y).0` and `(*y).1`. +//! This framework is currently experimental. In particular, the features related to references are +//! currently guarded behind `-Zunsound-mir-opts`, because their correctness relies on Stacked +//! Borrows. Also, only places with scalar types can be tracked currently. This is because scalar +//! types are indivisible, which simplifies the current implementation. But this limitation could be +//! lifted in the future. //! //! -//! # Correctness +//! # Notes //! -//! Warning: This is a semi-formal attempt to argue for the correctness of this analysis. If you -//! find any weak spots, let me know! Recommended reading: Abstract Interpretation. We will use the -//! term "place" to refer to a place expression (like `mir::Place`), and we will call the -//! underlying entity "object". For instance, `*_1` and `*_2` are not the same place, but depending -//! on the value of `_1` and `_2`, they could refer to the same object. Also, the same place can -//! refer to different objects during execution. If `_1` is reassigned, then `*_1` may refer to -//! different objects before and after assignment. Additionally, when saying "access to a place", -//! what we really mean is "access to an object denoted by arbitrary projections of that place". +//! - The bottom state denotes uninitialized memory. Because we are only doing a sound approximation +//! of the actual execution, we can also use this state for places where access would be UB. //! -//! In the following, we will assume a constant propagation analysis. Our analysis is correct if -//! every transfer function is correct. This is the case if for every pair (f, f#) and abstract -//! state s, we have f(y(s)) <= y(f#(s)), where s is a mapping from tracked place to top, bottom or -//! a constant. Since pointers (and mutable references) are not tracked, but can be used to change -//! values in the concrete domain, f# must assume that all places that can be affected in this way -//! for a given program point are already marked with top in s (otherwise many assignments and -//! function calls would have no choice but to mark all tracked places with top). This leads us to -//! an invariant: For all possible program points where there could possibly exist means of mutable -//! access to a tracked place (in the concrete domain), this place must be assigned to top (in the -//! abstract domain). The concretization function y can be defined as expected for the constant -//! propagation analysis, although the concrete state of course contains all kinds of non-tracked -//! data. However, by the invariant above, no mutable access to tracked places that are not marked -//! with top may be introduced. +//! - The assignment logic in `State::assign_place_idx` assumes that the places are non-overlapping, +//! or identical. Note that this refers to place expressions, not memory locations. //! -//! Note that we (at least currently) do not differentiate between "this place may assume different -//! values" and "a pointer to this place escaped the analysis". However, we still want to handle -//! assignments to constants as usual for f#. This adds an assumption: Whenever we have an -//! assignment that is captured by the analysis, all mutable access to the underlying place (which -//! is not observable by the analysis) must be invalidated. This is (hopefully) covered by Stacked -//! Borrows. +//! - Since pointers (and mutable references) are not tracked, but can be used to change the +//! underlying values, we are conservative and immediately flood the referenced place upon creation +//! of the pointer. Also, we have to uphold the invariant that the place must stay that way as long +//! as this mutable access could exist. However... //! -//! To be continued... +//! - Without an aliasing model like Stacked Borrows (i.e., `-Zunsound-mir-opts` is not given), +//! such mutable access is never revoked. And even shared references could be used to obtain the +//! address of a value an modify it. When not assuming Stacked Borrows, we prevent such places from +//! being tracked at all. This means that the analysis itself can assume that writes to a *tracked* +//! place always invalidate all other means of mutable access, regardless of the aliasing model. //! -//! The bottom state denotes uninitalized memory. -//! -//! -//! # Assumptions -//! -//! - (A1) Assignment to any tracked place invalidates all pointers that could be used to change -//! the underlying value. -//! - (A2) `StorageLive`, `StorageDead` and `Deinit` make the underlying memory at least -//! uninitialized (at least in the sense that declaring access UB is also fine). -//! - (A3) An assignment with `State::assign_place_idx` either involves non-overlapping places, or -//! the places are the same. -//! - (A4) If the value behind a reference to a `Freeze` place is changed, dereferencing the -//! reference is UB. +//! - Likewise, the analysis itself assumes that if the value of a *tracked* place behind a shared +//! reference is changed, the reference may not be used to access that value anymore. This is true +//! for all places if the referenced type is `Freeze` and we assume Stacked Borrows. If we are not +//! assuming Stacking Borrows (or if the referenced type could be `!Freeze`), we again prevent such +//! places from being tracked at all, making this assertion trivially true. use std::fmt::{Debug, Formatter}; @@ -107,11 +87,12 @@ pub trait ValueAnalysis<'tcx> { self.handle_intrinsic(intrinsic, state); } StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { - // (A2) + // StorageLive leaves the local in an uninitialized state. + // StorageDead makes it UB to access the local afterwards. state.flood_with(Place::from(*local).as_ref(), self.map(), Self::Value::bottom()); } StatementKind::Deinit(box place) => { - // (A2) + // Deinit makes the place uninitialized. state.flood_with(place.as_ref(), self.map(), Self::Value::bottom()); } StatementKind::Retag(..) => { @@ -477,9 +458,9 @@ impl State { /// Copies `source` to `target`, including all tracked places beneath. /// /// If `target` contains a place that is not contained in `source`, it will be overwritten with - /// Top. Also, because this will copy all entries one after another, it may only be + /// Top. Also, because this will copy all entries one after another, it may only be used for + /// places that are non-overlapping or identical. pub fn assign_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map) { - // We use (A3) and copy all entries one after another. let StateData::Reachable(values) = &mut self.0 else { return }; // If both places are tracked, we copy the value to the target. If the target is tracked, @@ -528,21 +509,24 @@ impl State { if let Some(value_index) = map.places[target].value_index { values[value_index] = V::top(); } - // Instead of tracking of *where* a reference points to (as in, which place), we - // track *what* it points to (as in, what do we know about the target). For an - // assignment `x = &y`, we thus copy the info we have for `y` to `*x`. This is - // sound because we only track places that are `Freeze`, and (A4). + // Instead of tracking of *where* a reference points to (as in, which memory + // location), we track *what* it points to (as in, what do we know about the + // target). For an assignment `x = &y`, we thus copy the info of `y` to `*x`. if let Some(target_deref) = map.apply(target, TrackElem::Deref) { + // We know here that `*x` is `Freeze`, because we only track through + // dereferences if the target type is `Freeze`. self.assign_place_idx(target_deref, source, map); } } } } + /// Retrieve the value stored for a place, or ⊥ if it is not tracked. pub fn get(&self, place: PlaceRef<'_>, map: &Map) -> V { map.find(place).map(|place| self.get_idx(place, map)).unwrap_or(V::top()) } + /// Retrieve the value stored for a place index, or ⊥ if it is not tracked. pub fn get_idx(&self, place: PlaceIndex, map: &Map) -> V { match &self.0 { StateData::Reachable(values) => { @@ -569,11 +553,11 @@ impl JoinSemiLattice for State { } } -/// A partial mapping from `Place` to `PlaceIndex`. +/// A partial mapping from `Place` to `PlaceIndex`, where some place indices have value indices. /// -/// Some additioanl bookkeeping is done to speed up traversal: +/// Some additional bookkeeping is done to speed up traversal: /// - For iteration, every [`PlaceInfo`] contains an intrusive linked list of its children. -/// - To directly get the child for a specific projection, there is `projections` map. +/// - To directly get the child for a specific projection, there is a `projections` map. #[derive(Debug)] pub struct Map { locals: IndexVec>, @@ -595,7 +579,7 @@ impl Map { /// Returns a map that only tracks places whose type passes the filter. /// /// This is currently the only way to create a [`Map`]. The way in which the tracked places are - /// chosen is an implementation detail an may not be relied upon. + /// chosen is an implementation detail and may not be relied upon. pub fn from_filter<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -609,7 +593,7 @@ impl Map { // not yet guaranteed). if tcx.sess.opts.unstable_opts.unsound_mir_opts { // We might want to add additional limitations. If a struct has 10 boxed fields of - // itself, will currently be `10.pow(max_derefs)` tracked places. + // itself, there will currently be `10.pow(max_derefs)` tracked places. map.register_with_filter(tcx, body, 2, filter, &[]); } else { map.register_with_filter(tcx, body, 0, filter, &escaped_places(body)); @@ -668,7 +652,7 @@ impl Map { if max_derefs > 0 { if let Some(ty::TypeAndMut { ty: deref_ty, .. }) = ty.builtin_deref(false) { - // References can only be tracked if the target is `!Freeze`. + // Values behind references can only be tracked if the target is `Freeze`. if deref_ty.is_freeze(tcx.at(DUMMY_SP), param_env) { projection.push(PlaceElem::Deref); self.register_with_filter_rec( @@ -953,6 +937,8 @@ fn iter_fields<'tcx>( } /// Returns all places, that have their reference or address taken. +/// +/// This includes shared references. fn escaped_places<'tcx>(body: &Body<'tcx>) -> Vec> { struct Collector<'tcx> { result: Vec>, From d86acdd72a823fa496b3501c9d656beedf9f124f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sun, 23 Oct 2022 14:49:38 +0200 Subject: [PATCH 53/76] Prevent propagation of overflow if overflow occured --- .../src/dataflow_const_prop.rs | 20 ++++--------------- .../checked.main.DataflowConstProp.diff | 2 +- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index b4078625d83d8..8cb1a9dc4a1df 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -11,7 +11,7 @@ use rustc_mir_dataflow::value_analysis::{ HasTop, Map, State, TrackElem, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef, }; use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects}; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::DUMMY_SP; use crate::MirPass; @@ -42,7 +42,6 @@ struct ConstAnalysis<'tcx> { tcx: TyCtxt<'tcx>, ecx: InterpCx<'tcx, 'tcx, DummyMachine>, param_env: ty::ParamEnv<'tcx>, - propagate_overflow: bool, } impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { @@ -84,13 +83,11 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { let overflow = match overflow { FlatSet::Top => FlatSet::Top, FlatSet::Elem(overflow) => { - if overflow && !self.propagate_overflow { + if overflow { + // Overflow cannot be reliable propagated. See: https://github.com/rust-lang/rust/pull/101168#issuecomment-1288091446 FlatSet::Top } else { - self.wrap_scalar( - Scalar::from_bool(overflow), - self.tcx.types.bool, - ) + self.wrap_scalar(Scalar::from_bool(false), self.tcx.types.bool) } } FlatSet::Bottom => FlatSet::Bottom, @@ -220,20 +217,11 @@ impl<'tcx> std::fmt::Debug for ScalarTy<'tcx> { impl<'tcx> ConstAnalysis<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, map: Map) -> Self { - // It can happen that overflow will be detected even though overflow checks are disabled. - // This is caused by inlining functions that have #[rustc_inherit_overflow_checks]. Such - // overflows must not be propagated if `-C overflow-checks=off`. Also, if the function we - // are optimizing here has #[rustc_inherit_overflow_checks], the overflow checks may - // actually not be triggered by the consuming crate, so we have to ignore them too. - // Related to https://github.com/rust-lang/rust/issues/35310. - let propagate_overflow = tcx.sess.overflow_checks() - && !tcx.has_attr(body.source.def_id(), sym::rustc_inherit_overflow_checks); Self { map, tcx, ecx: InterpCx::new(tcx, DUMMY_SP, ty::ParamEnv::empty(), DummyMachine), param_env: tcx.param_env(body.source.def_id()), - propagate_overflow, } } diff --git a/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff index 944afed8f465a..a4ebd0c8c18f0 100644 --- a/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff @@ -61,7 +61,7 @@ - assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> bb2; // scope 4 at $DIR/checked.rs:+6:13: +6:18 + _9 = const i32::MAX; // scope 4 at $DIR/checked.rs:+6:13: +6:14 + _10 = CheckedAdd(const i32::MAX, const 1_i32); // scope 4 at $DIR/checked.rs:+6:13: +6:18 -+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> bb2; // scope 4 at $DIR/checked.rs:+6:13: +6:18 ++ assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> bb2; // scope 4 at $DIR/checked.rs:+6:13: +6:18 } bb2: { From de69d088a46e8f9a70e2ac4b3477211fbaa01580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sun, 23 Oct 2022 15:05:03 +0200 Subject: [PATCH 54/76] Explicitly match all terminators --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 8169c41d99557..bfe714342e206 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -260,8 +260,17 @@ pub trait ValueAnalysis<'tcx> { // They would have an effect, but are not allowed in this phase. bug!("encountered disallowed terminator"); } - _ => { - // The other terminators can be ignored. + TerminatorKind::Goto { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::Assert { .. } + | TerminatorKind::GeneratorDrop + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::FalseUnwind { .. } => { + // These terminators have no effect on the analysis. } } } From efc7ca8c7d7db6a14b04e9931c75ee3e61ca718f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sun, 23 Oct 2022 15:31:46 +0200 Subject: [PATCH 55/76] Use ParamEnv consistently --- .../src/dataflow_const_prop.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 8cb1a9dc4a1df..aae7fefd1121c 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -217,11 +217,12 @@ impl<'tcx> std::fmt::Debug for ScalarTy<'tcx> { impl<'tcx> ConstAnalysis<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, map: Map) -> Self { + let param_env = tcx.param_env(body.source.def_id()); Self { map, tcx, - ecx: InterpCx::new(tcx, DUMMY_SP, ty::ParamEnv::empty(), DummyMachine), - param_env: tcx.param_env(body.source.def_id()), + ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), + param_env: param_env, } } @@ -260,13 +261,11 @@ impl<'tcx> ConstAnalysis<'tcx> { }; match value { FlatSet::Top => FlatSet::Top, - FlatSet::Elem(ScalarTy(scalar, ty)) => { - let layout = self - .tcx - .layout_of(ty::ParamEnv::empty().and(ty)) - .expect("this should not happen"); // FIXME - FlatSet::Elem(ImmTy::from_scalar(scalar, layout)) - } + FlatSet::Elem(ScalarTy(scalar, ty)) => self + .tcx + .layout_of(self.param_env.and(ty)) + .map(|layout| FlatSet::Elem(ImmTy::from_scalar(scalar, layout))) + .unwrap_or(FlatSet::Top), FlatSet::Bottom => FlatSet::Bottom, } } From f29533b4e031771dae471bff534e3cc03ab48cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 25 Oct 2022 00:28:41 +0200 Subject: [PATCH 56/76] Small documentation changes --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index aae7fefd1121c..62b0902e60af5 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -1,6 +1,6 @@ //! A constant propagation optimization pass based on dataflow analysis. //! -//! Tracks places that have a scalar type. +//! Currently, this pass only propagates scalar values. use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar}; use rustc_data_structures::fx::FxHashMap; @@ -289,7 +289,13 @@ impl<'tcx> ConstAnalysis<'tcx> { struct CollectAndPatch<'tcx, 'map> { tcx: TyCtxt<'tcx>, map: &'map Map, + + /// For a given MIR location, this stores the values of the operands used by that location. In + /// particular, this is before the effect, such that the operands of `_1 = _1 + _2` are + /// properly captured. before_effect: FxHashMap<(Location, Place<'tcx>), ScalarTy<'tcx>>, + + /// Stores the assigned values for assignments where the Rvalue is constant. assignments: FxHashMap>, } From 1f82a9f89e3c0388442835df632b56ccea08a971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 25 Oct 2022 00:56:51 +0200 Subject: [PATCH 57/76] Move HasTop and HasBottom into lattice.rs --- .../src/framework/lattice.rs | 34 +++++++++++++++++++ .../rustc_mir_dataflow/src/value_analysis.rs | 33 ++++-------------- .../src/dataflow_const_prop.rs | 2 +- 3 files changed, 42 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index d6b89eb82275e..f0e75c53ea15c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -73,6 +73,16 @@ pub trait MeetSemiLattice: Eq { fn meet(&mut self, other: &Self) -> bool; } +/// A set that has a "bottom" element, which is less than or equal to any other element. +pub trait HasBottom { + fn bottom() -> Self; +} + +/// A set that has a "top" element, which is greater than or equal to any other element. +pub trait HasTop { + fn top() -> Self; +} + /// A `bool` is a "two-point" lattice with `true` as the top element and `false` as the bottom: /// /// ```text @@ -102,6 +112,18 @@ impl MeetSemiLattice for bool { } } +impl HasBottom for bool { + fn bottom() -> Self { + false + } +} + +impl HasTop for bool { + fn top() -> Self { + true + } +} + /// A tuple (or list) of lattices is itself a lattice whose least upper bound is the concatenation /// of the least upper bounds of each element of the tuple (or list). /// @@ -250,3 +272,15 @@ impl MeetSemiLattice for FlatSet { true } } + +impl HasBottom for FlatSet { + fn bottom() -> Self { + Self::Bottom + } +} + +impl HasTop for FlatSet { + fn top() -> Self { + Self::Top + } +} diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index bfe714342e206..a3194ebc30cfc 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -56,9 +56,10 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::DUMMY_SP; use rustc_target::abi::VariantIdx; +use crate::lattice::{HasBottom, HasTop}; use crate::{ - fmt::DebugWithContext, lattice::FlatSet, Analysis, AnalysisDomain, CallReturnPlaces, - JoinSemiLattice, SwitchIntEdgeEffects, + fmt::DebugWithContext, Analysis, AnalysisDomain, CallReturnPlaces, JoinSemiLattice, + SwitchIntEdgeEffects, }; pub trait ValueAnalysis<'tcx> { @@ -846,8 +847,8 @@ pub enum ValueOrPlace { Place(PlaceIndex), } -impl HasTop for ValueOrPlace { - fn top() -> Self { +impl ValueOrPlace { + pub fn top() -> Self { ValueOrPlace::Value(V::top()) } } @@ -859,8 +860,8 @@ pub enum ValueOrPlaceOrRef { Ref(PlaceIndex), } -impl HasTop for ValueOrPlaceOrRef { - fn top() -> Self { +impl ValueOrPlaceOrRef { + pub fn top() -> Self { ValueOrPlaceOrRef::Value(V::top()) } } @@ -874,26 +875,6 @@ impl From> for ValueOrPlaceOrRef { } } -pub trait HasBottom { - fn bottom() -> Self; -} - -pub trait HasTop { - fn top() -> Self; -} - -impl HasBottom for FlatSet { - fn bottom() -> Self { - Self::Bottom - } -} - -impl HasTop for FlatSet { - fn top() -> Self { - Self::Top - } -} - /// The set of projection elements that can be used by a tracked place. /// /// For now, downcast is not allowed due to aliasing between variants (see #101168). diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 62b0902e60af5..93f7ddbee798e 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::visit::{MutVisitor, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{ - HasTop, Map, State, TrackElem, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef, + Map, State, TrackElem, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef, }; use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects}; use rustc_span::DUMMY_SP; From da4a40f81650222d86fa070aad87b5d20f8596e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 25 Oct 2022 02:27:27 +0200 Subject: [PATCH 58/76] Remove copy of current const prop tests and add a few new tests --- .../mir-opt/dataflow-const-prop/checked.rs | 2 +- ...erit_overflow.main.DataflowConstProp.diff} | 30 ++-- ...flow_checks_use.rs => inherit_overflow.rs} | 4 +- .../dataflow-const-prop/issue_81605.rs | 1 + .../aggregate.main.DataflowConstProp.diff | 32 ----- .../dataflow-const-prop/previous/aggregate.rs | 7 - ...ay_index.main.DataflowConstProp.32bit.diff | 37 ----- ...ay_index.main.DataflowConstProp.64bit.diff | 37 ----- .../previous/array_index.rs | 7 - ...op_div_by_zero.main.DataflowConstProp.diff | 54 ------- .../previous/bad_op_div_by_zero.rs | 7 - ...op_mod_by_zero.main.DataflowConstProp.diff | 54 ------- .../previous/bad_op_mod_by_zero.rs | 7 - ...r_slices.main.DataflowConstProp.32bit.diff | 56 -------- ...r_slices.main.DataflowConstProp.64bit.diff | 56 -------- .../previous/bad_op_unsafe_oob_for_slices.rs | 10 -- .../previous/boolean_identities.rs | 11 -- ...ean_identities.test.DataflowConstProp.diff | 30 ---- .../boxes.main.DataflowConstProp.diff | 58 -------- .../dataflow-const-prop/previous/boxes.rs | 14 -- .../previous/cast.main.DataflowConstProp.diff | 28 ---- .../dataflow-const-prop/previous/cast.rs | 8 -- .../checked_add.main.DataflowConstProp.diff | 27 ---- .../previous/checked_add.rs | 7 - ...ils_gracefully.main.DataflowConstProp.diff | 44 ------ .../previous/const_prop_fails_gracefully.rs | 10 -- .../previous/control-flow-simplification.rs | 21 --- ...implification.hello.DataflowConstProp.diff | 32 ----- ...simplification.hello.PreCodegen.before.mir | 9 -- ...riminant.main.DataflowConstProp.32bit.diff | 50 ------- ...riminant.main.DataflowConstProp.64bit.diff | 50 ------- .../previous/discriminant.rs | 13 -- .../indirect.main.DataflowConstProp.diff | 33 ----- .../dataflow-const-prop/previous/indirect.rs | 7 - ...valid_constant.main.DataflowConstProp.diff | 74 ---------- .../previous/invalid_constant.rs | 44 ------ .../previous/issue-66971.rs | 18 --- .../previous/issue-67019.rs | 13 -- .../issue_66971.main.DataflowConstProp.diff | 33 ----- .../issue_67019.main.DataflowConstProp.diff | 33 ----- ...ay_index.main.DataflowConstProp.32bit.diff | 35 ----- ...ay_index.main.DataflowConstProp.64bit.diff | 35 ----- .../previous/large_array_index.rs | 7 - .../previous/mult_by_zero.rs | 10 -- .../mult_by_zero.test.DataflowConstProp.diff | 17 --- ...table_variable.main.DataflowConstProp.diff | 28 ---- .../previous/mutable_variable.rs | 8 -- ...able_aggregate.main.DataflowConstProp.diff | 29 ---- .../previous/mutable_variable_aggregate.rs | 8 -- ...regate_mut_ref.main.DataflowConstProp.diff | 36 ----- .../mutable_variable_aggregate_mut_ref.rs | 9 -- ...e_partial_read.main.DataflowConstProp.diff | 35 ----- ...mutable_variable_aggregate_partial_read.rs | 14 -- ...riable_no_prop.main.DataflowConstProp.diff | 48 ------- .../previous/mutable_variable_no_prop.rs | 12 -- ..._unprop_assign.main.DataflowConstProp.diff | 54 ------- .../mutable_variable_unprop_assign.rs | 15 -- ...variable.main.DataflowConstProp.32bit.diff | 61 -------- ...variable.main.DataflowConstProp.64bit.diff | 61 -------- ...riable.main.SimplifyLocals.after.32bit.mir | 27 ---- ...riable.main.SimplifyLocals.after.64bit.mir | 27 ---- .../previous/optimizes_into_variable.rs | 16 --- ...mutable_static.main.DataflowConstProp.diff | 45 ------ .../previous/read_immutable_static.rs | 8 -- .../ref_deref.main.DataflowConstProp.diff | 26 ---- .../previous/ref_deref.main.PromoteTemps.diff | 30 ---- .../dataflow-const-prop/previous/ref_deref.rs | 7 - ..._deref_project.main.DataflowConstProp.diff | 26 ---- .../ref_deref_project.main.PromoteTemps.diff | 30 ---- .../previous/ref_deref_project.rs | 7 - .../reify_fn_ptr.main.DataflowConstProp.diff | 29 ---- .../previous/reify_fn_ptr.rs | 6 - .../repeat.main.DataflowConstProp.32bit.diff | 41 ------ .../repeat.main.DataflowConstProp.64bit.diff | 41 ------ .../dataflow-const-prop/previous/repeat.rs | 7 - .../return_place.add.DataflowConstProp.diff | 20 --- .../return_place.add.PreCodegen.before.mir | 16 --- .../previous/return_place.rs | 12 -- ...al_propagation.main.DataflowConstProp.diff | 35 ----- .../previous/scalar_literal_propagation.rs | 9 -- ...lice_len.main.DataflowConstProp.32bit.diff | 48 ------- ...lice_len.main.DataflowConstProp.64bit.diff | 48 ------- .../dataflow-const-prop/previous/slice_len.rs | 7 - .../switch_int.main.DataflowConstProp.diff | 33 ----- ...mplifyConstCondition-after-const-prop.diff | 34 ----- .../previous/switch_int.rs | 11 -- ...al_propagation.main.DataflowConstProp.diff | 35 ----- .../previous/tuple_literal_propagation.rs | 10 -- .../promoted.main.DataflowConstProp.diff | 2 +- .../mir-opt/dataflow-const-prop/promoted.rs | 1 + .../recursive.main.DataflowConstProp.diff | 132 ------------------ .../mir-opt/dataflow-const-prop/recursive.rs | 24 ---- .../ref_mut.main.DataflowConstProp.diff | 2 +- .../mir-opt/dataflow-const-prop/ref_mut.rs | 1 + .../self_assign.main.DataflowConstProp.diff | 52 +++++++ .../dataflow-const-prop/self_assign.rs | 13 ++ ...elf_assign_add.main.DataflowConstProp.diff | 23 +++ .../dataflow-const-prop/self_assign_add.rs | 9 ++ .../static_ref.main.DataflowConstProp.diff | 62 ++++---- .../mir-opt/dataflow-const-prop/static_ref.rs | 2 + .../terminator.main.DataflowConstProp.diff | 2 +- .../mir-opt/dataflow-const-prop/terminator.rs | 1 + .../tuple.main.DataflowConstProp.diff | 86 ++++++++++++ src/test/mir-opt/dataflow-const-prop/tuple.rs | 12 ++ .../unnamed.main.DataflowConstProp.diff | 38 ----- .../mir-opt/dataflow-const-prop/unnamed.rs | 10 -- 106 files changed, 253 insertions(+), 2500 deletions(-) rename src/test/mir-opt/dataflow-const-prop/{inherit_overflow_checks_use.main.DataflowConstProp.diff => inherit_overflow.main.DataflowConstProp.diff} (80%) rename src/test/mir-opt/dataflow-const-prop/{inherit_overflow_checks_use.rs => inherit_overflow.rs} (65%) delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/aggregate.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/aggregate.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/array_index.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/boxes.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/cast.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/checked_add.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/control-flow-simplification.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/discriminant.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/indirect.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/issue-66971.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/issue-67019.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/issue_66971.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/large_array_index.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/repeat.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/return_place.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.SimplifyConstCondition-after-const-prop.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/switch_int.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/recursive.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/self_assign.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/self_assign_add.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/self_assign_add.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/tuple.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/unnamed.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/unnamed.rs diff --git a/src/test/mir-opt/dataflow-const-prop/checked.rs b/src/test/mir-opt/dataflow-const-prop/checked.rs index ae457af72c066..8c99fc95eb1d8 100644 --- a/src/test/mir-opt/dataflow-const-prop/checked.rs +++ b/src/test/mir-opt/dataflow-const-prop/checked.rs @@ -1,5 +1,5 @@ // unit-test: DataflowConstProp -// compile-flags: -C overflow-checks=on +// compile-flags: -Zunsound-mir-opts -Coverflow-checks=on // EMIT_MIR checked.main.DataflowConstProp.diff #[allow(arithmetic_overflow)] diff --git a/src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff similarity index 80% rename from src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.main.DataflowConstProp.diff rename to src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff index 53c7ec4168047..bf4557ed3d92c 100644 --- a/src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff @@ -2,13 +2,13 @@ + // MIR for `main` after DataflowConstProp fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/inherit_overflow_checks_use.rs:+0:11: +0:11 - let mut _1: u8; // in scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 - let mut _2: u8; // in scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 - let mut _3: u8; // in scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + let mut _0: (); // return place in scope 0 at $DIR/inherit_overflow.rs:+0:11: +0:11 + let mut _1: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + let mut _2: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + let mut _3: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 scope 1 { } - scope 2 (inlined ::add) { // at $DIR/inherit_overflow_checks_use.rs:7:13: 7:47 + scope 2 (inlined ::add) { // at $DIR/inherit_overflow.rs:7:13: 7:47 debug self => _2; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL debug other => _3; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL let mut _4: u8; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL @@ -17,11 +17,11 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 - StorageLive(_2); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 - _2 = const u8::MAX; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 - StorageLive(_3); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 - _3 = const 1_u8; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 + StorageLive(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + StorageLive(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + _2 = const u8::MAX; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + StorageLive(_3); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + _3 = const 1_u8; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 StorageLive(_4); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL _4 = const u8::MAX; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL StorageLive(_5); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL @@ -35,11 +35,11 @@ + _1 = const 0_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL StorageDead(_5); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL StorageDead(_4); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - StorageDead(_3); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 - StorageDead(_2); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:13: +3:47 - StorageDead(_1); // scope 0 at $DIR/inherit_overflow_checks_use.rs:+3:47: +3:48 - nop; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+0:11: +4:2 - return; // scope 0 at $DIR/inherit_overflow_checks_use.rs:+4:2: +4:2 + StorageDead(_3); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + StorageDead(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + StorageDead(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:47: +3:48 + nop; // scope 0 at $DIR/inherit_overflow.rs:+0:11: +4:2 + return; // scope 0 at $DIR/inherit_overflow.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.rs b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.rs similarity index 65% rename from src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.rs rename to src/test/mir-opt/dataflow-const-prop/inherit_overflow.rs index d4fcb1d77052b..3f6329dfd1d16 100644 --- a/src/test/mir-opt/dataflow-const-prop/inherit_overflow_checks_use.rs +++ b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.rs @@ -1,6 +1,6 @@ -// compile-flags: -C overflow-checks=off +// compile-flags: -Coverflow-checks=off -Zunsound-mir-opts -// EMIT_MIR inherit_overflow_checks_use.main.DataflowConstProp.diff +// EMIT_MIR inherit_overflow.main.DataflowConstProp.diff fn main() { // After inlining, this will contain a `CheckedBinaryOp`. The overflow // must be ignored by the constant propagation to avoid triggering a panic. diff --git a/src/test/mir-opt/dataflow-const-prop/issue_81605.rs b/src/test/mir-opt/dataflow-const-prop/issue_81605.rs index d75e2a28bef6b..2829d32c905c8 100644 --- a/src/test/mir-opt/dataflow-const-prop/issue_81605.rs +++ b/src/test/mir-opt/dataflow-const-prop/issue_81605.rs @@ -1,4 +1,5 @@ // unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts // EMIT_MIR issue_81605.f.DataflowConstProp.diff fn f() -> usize { diff --git a/src/test/mir-opt/dataflow-const-prop/previous/aggregate.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/aggregate.main.DataflowConstProp.diff deleted file mode 100644 index 8c35b5ca4203a..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/aggregate.main.DataflowConstProp.diff +++ /dev/null @@ -1,32 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10 - let mut _2: i32; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24 - let mut _3: (i32, i32, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - scope 1 { - debug x => _1; // in scope 1 at $DIR/aggregate.rs:+1:9: +1:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 - StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - Deinit(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 - (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22 -- _2 = (_3.1: i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 -- _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 -+ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24 -+ _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 - StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28 - StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29 - _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2 - return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/aggregate.rs b/src/test/mir-opt/dataflow-const-prop/previous/aggregate.rs deleted file mode 100644 index bdfa922cf5caf..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/aggregate.rs +++ /dev/null @@ -1,7 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -O - -// EMIT_MIR aggregate.main.DataflowConstProp.diff -fn main() { - let x = (0, 1, 2).1 + 0; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff deleted file mode 100644 index 00eb9d0e2006a..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.32bit.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/array_index.rs:+0:11: +0:11 - let _1: u32; // in scope 0 at $DIR/array_index.rs:+1:9: +1:10 - let mut _2: [u32; 4]; // in scope 0 at $DIR/array_index.rs:+1:18: +1:30 - let _3: usize; // in scope 0 at $DIR/array_index.rs:+1:31: +1:32 - let mut _4: usize; // in scope 0 at $DIR/array_index.rs:+1:18: +1:33 - let mut _5: bool; // in scope 0 at $DIR/array_index.rs:+1:18: +1:33 - scope 1 { - debug x => _1; // in scope 1 at $DIR/array_index.rs:+1:9: +1:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/array_index.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:30 - _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30 - StorageLive(_3); // scope 0 at $DIR/array_index.rs:+1:31: +1:32 - _3 = const 2_usize; // scope 0 at $DIR/array_index.rs:+1:31: +1:32 - _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -- _5 = Lt(_3, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ _5 = Lt(const 2_usize, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - } - - bb1: { - _1 = _2[_3]; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - StorageDead(_3); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 - StorageDead(_2); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 - _0 = const (); // scope 0 at $DIR/array_index.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/array_index.rs:+2:1: +2:2 - return; // scope 0 at $DIR/array_index.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff deleted file mode 100644 index 00eb9d0e2006a..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/array_index.main.DataflowConstProp.64bit.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/array_index.rs:+0:11: +0:11 - let _1: u32; // in scope 0 at $DIR/array_index.rs:+1:9: +1:10 - let mut _2: [u32; 4]; // in scope 0 at $DIR/array_index.rs:+1:18: +1:30 - let _3: usize; // in scope 0 at $DIR/array_index.rs:+1:31: +1:32 - let mut _4: usize; // in scope 0 at $DIR/array_index.rs:+1:18: +1:33 - let mut _5: bool; // in scope 0 at $DIR/array_index.rs:+1:18: +1:33 - scope 1 { - debug x => _1; // in scope 1 at $DIR/array_index.rs:+1:9: +1:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/array_index.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:30 - _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30 - StorageLive(_3); // scope 0 at $DIR/array_index.rs:+1:31: +1:32 - _3 = const 2_usize; // scope 0 at $DIR/array_index.rs:+1:31: +1:32 - _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -- _5 = Lt(_3, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ _5 = Lt(const 2_usize, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - } - - bb1: { - _1 = _2[_3]; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - StorageDead(_3); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 - StorageDead(_2); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 - _0 = const (); // scope 0 at $DIR/array_index.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/array_index.rs:+2:1: +2:2 - return; // scope 0 at $DIR/array_index.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/array_index.rs b/src/test/mir-opt/dataflow-const-prop/previous/array_index.rs deleted file mode 100644 index 3cd7ddf20a7da..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/array_index.rs +++ /dev/null @@ -1,7 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR_FOR_EACH_BIT_WIDTH - -// EMIT_MIR array_index.main.DataflowConstProp.diff -fn main() { - let x: u32 = [0, 1, 2, 3][2]; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff deleted file mode 100644 index 1744b7b976afd..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.main.DataflowConstProp.diff +++ /dev/null @@ -1,54 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+1:9: +1:10 - let mut _3: i32; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 - let mut _4: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 - let mut _5: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 - let mut _6: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 - let mut _7: bool; // in scope 0 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 - scope 1 { - debug y => _1; // in scope 1 at $DIR/bad_op_div_by_zero.rs:+1:9: +1:10 - let _2: i32; // in scope 1 at $DIR/bad_op_div_by_zero.rs:+2:9: +2:11 - scope 2 { - debug _z => _2; // in scope 2 at $DIR/bad_op_div_by_zero.rs:+2:9: +2:11 - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/bad_op_div_by_zero.rs:+1:9: +1:10 - _1 = const 0_i32; // scope 0 at $DIR/bad_op_div_by_zero.rs:+1:13: +1:14 - StorageLive(_2); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:9: +2:11 - StorageLive(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 -- _3 = _1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 -- _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -- assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ _3 = const 0_i32; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 -+ _4 = const true; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ assert(!const true, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 - } - - bb1: { -- _5 = Eq(_3, const -1_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -- _6 = Eq(const 1_i32, const i32::MIN); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -- _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -- assert(!move _7, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ _5 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ _6 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ _7 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 - } - - bb2: { -- _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ _2 = Div(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 - StorageDead(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 - _0 = const (); // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2 - StorageDead(_2); // scope 1 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2 - StorageDead(_1); // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2 - return; // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:2: +3:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.rs b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.rs deleted file mode 100644 index ddf195b2c8a9f..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_div_by_zero.rs +++ /dev/null @@ -1,7 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR bad_op_div_by_zero.main.DataflowConstProp.diff -#[allow(unconditional_panic)] -fn main() { - let y = 0; - let _z = 1 / y; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff deleted file mode 100644 index cc8dea75c9cb9..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.main.DataflowConstProp.diff +++ /dev/null @@ -1,54 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/bad_op_mod_by_zero.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:9: +1:10 - let mut _3: i32; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 - let mut _4: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - let mut _5: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - let mut _6: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - let mut _7: bool; // in scope 0 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - scope 1 { - debug y => _1; // in scope 1 at $DIR/bad_op_mod_by_zero.rs:+1:9: +1:10 - let _2: i32; // in scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11 - scope 2 { - debug _z => _2; // in scope 2 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11 - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:9: +1:10 - _1 = const 0_i32; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:13: +1:14 - StorageLive(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11 - StorageLive(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 -- _3 = _1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 -- _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -- assert(!move _4, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ _3 = const 0_i32; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 -+ _4 = const true; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - } - - bb1: { -- _5 = Eq(_3, const -1_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -- _6 = Eq(const 1_i32, const i32::MIN); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -- _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ _5 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ _6 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ _7 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - } - - bb2: { -- _2 = Rem(const 1_i32, move _3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 -+ _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 - StorageDead(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 - _0 = const (); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+0:11: +3:2 - StorageDead(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2 - StorageDead(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2 - return; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:2: +3:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs deleted file mode 100644 index ad30a5b6242ed..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_mod_by_zero.rs +++ /dev/null @@ -1,7 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR bad_op_mod_by_zero.main.DataflowConstProp.diff -#[allow(unconditional_panic)] -fn main() { - let y = 0; - let _z = 1 % y; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff deleted file mode 100644 index ce1524af76531..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.32bit.diff +++ /dev/null @@ -1,56 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+0:11: +0:11 - let _1: *const [i32]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 - let mut _2: *const [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - let _3: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - let _4: [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:26: +1:35 - let _6: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - let mut _7: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - let mut _8: bool; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - let mut _9: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - scope 1 { - debug a => _1; // in scope 1 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 - scope 2 { - let _5: i32; // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 - scope 3 { - debug _b => _5; // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - _9 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - // mir::Constant - // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35 - // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } - _3 = &(*_9); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35 - StorageDead(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:35: +1:36 - StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 - StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - } - - bb1: { - _5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 - _0 = const (); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 - StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 - StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2 - return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff deleted file mode 100644 index ce1524af76531..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.main.DataflowConstProp.64bit.diff +++ /dev/null @@ -1,56 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+0:11: +0:11 - let _1: *const [i32]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 - let mut _2: *const [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - let _3: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - let _4: [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:26: +1:35 - let _6: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - let mut _7: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - let mut _8: bool; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - let mut _9: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - scope 1 { - debug a => _1; // in scope 1 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 - scope 2 { - let _5: i32; // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 - scope 3 { - debug _b => _5; // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - _9 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - // mir::Constant - // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35 - // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } - _3 = &(*_9); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35 - StorageDead(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:35: +1:36 - StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 - StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - } - - bb1: { - _5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 - _0 = const (); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 - StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 - StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2 - return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs b/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs deleted file mode 100644 index c97257e6d8fa2..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/bad_op_unsafe_oob_for_slices.rs +++ /dev/null @@ -1,10 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR bad_op_unsafe_oob_for_slices.main.DataflowConstProp.diff -#[allow(unconditional_panic)] -fn main() { - let a: *const [_] = &[1, 2, 3]; - unsafe { - let _b = (*a)[3]; - } -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.rs b/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.rs deleted file mode 100644 index 578f9830cf221..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.rs +++ /dev/null @@ -1,11 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -O -Zmir-opt-level=4 - -// EMIT_MIR boolean_identities.test.DataflowConstProp.diff -pub fn test(x: bool, y: bool) -> bool { - (y | true) & (x & false) -} - -fn main() { - test(true, false); -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff deleted file mode 100644 index 307324d5768d8..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/boolean_identities.test.DataflowConstProp.diff +++ /dev/null @@ -1,30 +0,0 @@ -- // MIR for `test` before DataflowConstProp -+ // MIR for `test` after DataflowConstProp - - fn test(_1: bool, _2: bool) -> bool { - debug x => _1; // in scope 0 at $DIR/boolean_identities.rs:+0:13: +0:14 - debug y => _2; // in scope 0 at $DIR/boolean_identities.rs:+0:22: +0:23 - let mut _0: bool; // return place in scope 0 at $DIR/boolean_identities.rs:+0:34: +0:38 - let mut _3: bool; // in scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 - let mut _4: bool; // in scope 0 at $DIR/boolean_identities.rs:+1:6: +1:7 - let mut _5: bool; // in scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 - let mut _6: bool; // in scope 0 at $DIR/boolean_identities.rs:+1:19: +1:20 - - bb0: { - StorageLive(_3); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 - StorageLive(_4); // scope 0 at $DIR/boolean_identities.rs:+1:6: +1:7 - _4 = _2; // scope 0 at $DIR/boolean_identities.rs:+1:6: +1:7 - _3 = const true; // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15 - StorageDead(_4); // scope 0 at $DIR/boolean_identities.rs:+1:14: +1:15 - StorageLive(_5); // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 - StorageLive(_6); // scope 0 at $DIR/boolean_identities.rs:+1:19: +1:20 - _6 = _1; // scope 0 at $DIR/boolean_identities.rs:+1:19: +1:20 - _5 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29 - StorageDead(_6); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29 - _0 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:29 - StorageDead(_5); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29 - StorageDead(_3); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29 - return; // scope 0 at $DIR/boolean_identities.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff deleted file mode 100644 index 501108a7abcf8..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/boxes.main.DataflowConstProp.diff +++ /dev/null @@ -1,58 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/boxes.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/boxes.rs:+1:9: +1:10 - let mut _2: i32; // in scope 0 at $DIR/boxes.rs:+1:13: +1:22 - let mut _3: std::boxed::Box; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 - let mut _4: usize; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 - let mut _5: usize; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 - let mut _6: *mut u8; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 - let mut _7: std::boxed::Box; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 - let mut _8: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 - let mut _9: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22 - scope 1 { - debug x => _1; // in scope 1 at $DIR/boxes.rs:+1:9: +1:10 - } - scope 2 { - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/boxes.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/boxes.rs:+1:13: +1:22 - StorageLive(_3); // scope 0 at $DIR/boxes.rs:+1:14: +1:22 - _4 = SizeOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22 - _5 = AlignOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22 - _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 - // mir::Constant - // + span: $DIR/boxes.rs:13:14: 13:22 - // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value() } - } - - bb1: { - StorageLive(_7); // scope 0 at $DIR/boxes.rs:+1:14: +1:22 - _7 = ShallowInitBox(move _6, i32); // scope 0 at $DIR/boxes.rs:+1:14: +1:22 - _8 = (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); // scope 0 at $DIR/boxes.rs:+1:19: +1:21 - (*_8) = const 42_i32; // scope 0 at $DIR/boxes.rs:+1:19: +1:21 - _3 = move _7; // scope 0 at $DIR/boxes.rs:+1:14: +1:22 - StorageDead(_7); // scope 0 at $DIR/boxes.rs:+1:21: +1:22 - _9 = (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); // scope 0 at $DIR/boxes.rs:+1:13: +1:22 - _2 = (*_9); // scope 0 at $DIR/boxes.rs:+1:13: +1:22 - _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/boxes.rs:+1:13: +1:26 - StorageDead(_2); // scope 0 at $DIR/boxes.rs:+1:25: +1:26 - drop(_3) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/boxes.rs:+1:26: +1:27 - } - - bb2: { - StorageDead(_3); // scope 0 at $DIR/boxes.rs:+1:26: +1:27 - _0 = const (); // scope 0 at $DIR/boxes.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/boxes.rs:+2:1: +2:2 - return; // scope 0 at $DIR/boxes.rs:+2:2: +2:2 - } - - bb3 (cleanup): { - resume; // scope 0 at $DIR/boxes.rs:+0:1: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/boxes.rs b/src/test/mir-opt/dataflow-const-prop/previous/boxes.rs deleted file mode 100644 index 8b0c13c2eb6f5..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/boxes.rs +++ /dev/null @@ -1,14 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -O -// ignore-emscripten compiled with panic=abort by default -// ignore-wasm32 -// ignore-wasm64 - -#![feature(box_syntax)] - -// Note: this test verifies that we, in fact, do not const prop `box` - -// EMIT_MIR boxes.main.DataflowConstProp.diff -fn main() { - let x = *(box 42) + 0; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff deleted file mode 100644 index 3fd9fb5331b07..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/cast.main.DataflowConstProp.diff +++ /dev/null @@ -1,28 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/cast.rs:+0:11: +0:11 - let _1: u32; // in scope 0 at $DIR/cast.rs:+1:9: +1:10 - scope 1 { - debug x => _1; // in scope 1 at $DIR/cast.rs:+1:9: +1:10 - let _2: u8; // in scope 1 at $DIR/cast.rs:+3:9: +3:10 - scope 2 { - debug y => _2; // in scope 2 at $DIR/cast.rs:+3:9: +3:10 - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/cast.rs:+1:9: +1:10 -- _1 = const 42_u8 as u32 (IntToInt); // scope 0 at $DIR/cast.rs:+1:13: +1:24 -+ _1 = const 42_u32; // scope 0 at $DIR/cast.rs:+1:13: +1:24 - StorageLive(_2); // scope 1 at $DIR/cast.rs:+3:9: +3:10 -- _2 = const 42_u32 as u8 (IntToInt); // scope 1 at $DIR/cast.rs:+3:13: +3:24 -+ _2 = const 42_u8; // scope 1 at $DIR/cast.rs:+3:13: +3:24 - _0 = const (); // scope 0 at $DIR/cast.rs:+0:11: +4:2 - StorageDead(_2); // scope 1 at $DIR/cast.rs:+4:1: +4:2 - StorageDead(_1); // scope 0 at $DIR/cast.rs:+4:1: +4:2 - return; // scope 0 at $DIR/cast.rs:+4:2: +4:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/cast.rs b/src/test/mir-opt/dataflow-const-prop/previous/cast.rs deleted file mode 100644 index 25cc1839ff019..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/cast.rs +++ /dev/null @@ -1,8 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR cast.main.DataflowConstProp.diff - -fn main() { - let x = 42u8 as u32; - - let y = 42u32 as u8; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff deleted file mode 100644 index 5371e049664c3..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/checked_add.main.DataflowConstProp.diff +++ /dev/null @@ -1,27 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/checked_add.rs:+0:11: +0:11 - let _1: u32; // in scope 0 at $DIR/checked_add.rs:+1:9: +1:10 - let mut _2: (u32, bool); // in scope 0 at $DIR/checked_add.rs:+1:18: +1:23 - scope 1 { - debug x => _1; // in scope 1 at $DIR/checked_add.rs:+1:9: +1:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/checked_add.rs:+1:9: +1:10 - _2 = CheckedAdd(const 1_u32, const 1_u32); // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 -- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 - } - - bb1: { -- _1 = move (_2.0: u32); // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 -+ _1 = const 2_u32; // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 - _0 = const (); // scope 0 at $DIR/checked_add.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/checked_add.rs:+2:1: +2:2 - return; // scope 0 at $DIR/checked_add.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/checked_add.rs b/src/test/mir-opt/dataflow-const-prop/previous/checked_add.rs deleted file mode 100644 index e7cb047098989..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/checked_add.rs +++ /dev/null @@ -1,7 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -C overflow-checks=on - -// EMIT_MIR checked_add.main.DataflowConstProp.diff -fn main() { - let x: u32 = 1 + 1; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff deleted file mode 100644 index 38a5eecb8e8f0..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.main.DataflowConstProp.diff +++ /dev/null @@ -1,44 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +0:11 - let _1: usize; // in scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:9: +2:10 - let mut _2: *const i32; // in scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:30 - let _3: &i32; // in scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 - let _4: (); // in scope 0 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12 - let mut _5: usize; // in scope 0 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11 - scope 1 { - debug x => _1; // in scope 1 at $DIR/const_prop_fails_gracefully.rs:+2:9: +2:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:9: +2:10 - StorageLive(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:30 - StorageLive(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 - _3 = const _; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 - // mir::Constant - // + span: $DIR/const_prop_fails_gracefully.rs:8:13: 8:16 - // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) } - _2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 - _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:39 - StorageDead(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:38: +2:39 - StorageDead(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:39: +2:40 - StorageLive(_4); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12 - StorageLive(_5); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11 - _5 = _1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11 - _4 = read(move _5) -> bb1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12 - // mir::Constant - // + span: $DIR/const_prop_fails_gracefully.rs:9:5: 9:9 - // + literal: Const { ty: fn(usize) {read}, val: Value() } - } - - bb1: { - StorageDead(_5); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:11: +3:12 - StorageDead(_4); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:12: +3:13 - _0 = const (); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +4:2 - StorageDead(_1); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:1: +4:2 - return; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:2: +4:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.rs b/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.rs deleted file mode 100644 index 59b2f9caf2eaf..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/const_prop_fails_gracefully.rs +++ /dev/null @@ -1,10 +0,0 @@ -// unit-test: DataflowConstProp -#[inline(never)] -fn read(_: usize) {} - -// EMIT_MIR const_prop_fails_gracefully.main.DataflowConstProp.diff -fn main() { - const FOO: &i32 = &1; - let x = FOO as *const i32 as usize; - read(x); -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/control-flow-simplification.rs b/src/test/mir-opt/dataflow-const-prop/previous/control-flow-simplification.rs deleted file mode 100644 index e1269628d2f1a..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/control-flow-simplification.rs +++ /dev/null @@ -1,21 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -Zmir-opt-level=1 - -trait NeedsDrop: Sized { - const NEEDS: bool = std::mem::needs_drop::(); -} - -impl NeedsDrop for This {} - -// EMIT_MIR control_flow_simplification.hello.DataflowConstProp.diff -// EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir -fn hello() { - if ::NEEDS { - panic!() - } -} - -pub fn main() { - hello::<()>(); - hello::>(); -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff deleted file mode 100644 index d990c3b07e518..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.DataflowConstProp.diff +++ /dev/null @@ -1,32 +0,0 @@ -- // MIR for `hello` before DataflowConstProp -+ // MIR for `hello` after DataflowConstProp - - fn hello() -> () { - let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:+0:15: +0:15 - let mut _1: bool; // in scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 - let mut _2: !; // in scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL - - bb0: { - StorageLive(_1); // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 - _1 = const _; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 - switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:+1:8: +1:21 - } - - bb1: { - StorageLive(_2); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL - _2 = begin_panic::<&str>(const "explicit panic"); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/std/src/panic.rs:LL:COL - // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value() } - // mir::Constant - // + span: $SRC_DIR/std/src/panic.rs:LL:COL - // + literal: Const { ty: &str, val: Value(Slice(..)) } - } - - bb2: { - nop; // scope 0 at $DIR/control-flow-simplification.rs:+3:6: +3:6 - StorageDead(_1); // scope 0 at $DIR/control-flow-simplification.rs:+3:5: +3:6 - return; // scope 0 at $DIR/control-flow-simplification.rs:+4:2: +4:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir b/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir deleted file mode 100644 index 442ae80776172..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/control_flow_simplification.hello.PreCodegen.before.mir +++ /dev/null @@ -1,9 +0,0 @@ -// MIR for `hello` before PreCodegen - -fn hello() -> () { - let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:+0:15: +0:15 - - bb0: { - return; // scope 0 at $DIR/control-flow-simplification.rs:+4:2: +4:2 - } -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff deleted file mode 100644 index f98270b3ff04d..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.32bit.diff +++ /dev/null @@ -1,50 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/discriminant.rs:+1:9: +1:10 - let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:+1:13: +1:64 - let mut _3: std::option::Option; // in scope 0 at $DIR/discriminant.rs:+1:34: +1:44 - let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:+1:21: +1:31 - scope 1 { - debug x => _1; // in scope 1 at $DIR/discriminant.rs:+1:9: +1:10 - } - scope 2 { - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 - StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 - switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 - } - - bb1: { - switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 - } - - bb2: { - _2 = const 42_i32; // scope 2 at $DIR/discriminant.rs:+1:47: +1:49 - goto -> bb4; // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 - } - - bb3: { - _2 = const 10_i32; // scope 0 at $DIR/discriminant.rs:+1:59: +1:61 - goto -> bb4; // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 - } - - bb4: { - _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/discriminant.rs:+1:13: +1:68 - StorageDead(_2); // scope 0 at $DIR/discriminant.rs:+1:67: +1:68 - StorageDead(_3); // scope 0 at $DIR/discriminant.rs:+1:68: +1:69 - _0 = const (); // scope 0 at $DIR/discriminant.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/discriminant.rs:+2:1: +2:2 - return; // scope 0 at $DIR/discriminant.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff deleted file mode 100644 index f98270b3ff04d..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.main.DataflowConstProp.64bit.diff +++ /dev/null @@ -1,50 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/discriminant.rs:+1:9: +1:10 - let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:+1:13: +1:64 - let mut _3: std::option::Option; // in scope 0 at $DIR/discriminant.rs:+1:34: +1:44 - let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:+1:21: +1:31 - scope 1 { - debug x => _1; // in scope 1 at $DIR/discriminant.rs:+1:9: +1:10 - } - scope 2 { - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 - StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44 - _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 - switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 - } - - bb1: { - switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31 - } - - bb2: { - _2 = const 42_i32; // scope 2 at $DIR/discriminant.rs:+1:47: +1:49 - goto -> bb4; // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 - } - - bb3: { - _2 = const 10_i32; // scope 0 at $DIR/discriminant.rs:+1:59: +1:61 - goto -> bb4; // scope 0 at $DIR/discriminant.rs:+1:13: +1:64 - } - - bb4: { - _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/discriminant.rs:+1:13: +1:68 - StorageDead(_2); // scope 0 at $DIR/discriminant.rs:+1:67: +1:68 - StorageDead(_3); // scope 0 at $DIR/discriminant.rs:+1:68: +1:69 - _0 = const (); // scope 0 at $DIR/discriminant.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/discriminant.rs:+2:1: +2:2 - return; // scope 0 at $DIR/discriminant.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.rs b/src/test/mir-opt/dataflow-const-prop/previous/discriminant.rs deleted file mode 100644 index 5399bc2599778..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/discriminant.rs +++ /dev/null @@ -1,13 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -O - -// FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with -// `let x = 42` but that doesn't work because const-prop doesn't support `Operand::Indirect` -// and `InterpCx::eval_place()` always forces an allocation which creates the `Indirect`. -// Fixing either of those will allow us to const-prop this away. - -// EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR discriminant.main.DataflowConstProp.diff -fn main() { - let x = (if let Some(true) = Some(true) { 42 } else { 10 }) + 0; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff deleted file mode 100644 index 80deb02c77f56..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/indirect.main.DataflowConstProp.diff +++ /dev/null @@ -1,33 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/indirect.rs:+0:11: +0:11 - let _1: u8; // in scope 0 at $DIR/indirect.rs:+1:9: +1:10 - let mut _2: u8; // in scope 0 at $DIR/indirect.rs:+1:13: +1:25 - let mut _3: (u8, bool); // in scope 0 at $DIR/indirect.rs:+1:13: +1:29 - scope 1 { - debug x => _1; // in scope 1 at $DIR/indirect.rs:+1:9: +1:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/indirect.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/indirect.rs:+1:13: +1:25 -- _2 = const 2_u32 as u8 (IntToInt); // scope 0 at $DIR/indirect.rs:+1:13: +1:25 -- _3 = CheckedAdd(_2, const 1_u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 -- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 -+ _2 = const 2_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:25 -+ _3 = CheckedAdd(const 2_u8, const 1_u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 - } - - bb1: { -- _1 = move (_3.0: u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 -+ _1 = const 3_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 - StorageDead(_2); // scope 0 at $DIR/indirect.rs:+1:28: +1:29 - _0 = const (); // scope 0 at $DIR/indirect.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/indirect.rs:+2:1: +2:2 - return; // scope 0 at $DIR/indirect.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/indirect.rs b/src/test/mir-opt/dataflow-const-prop/previous/indirect.rs deleted file mode 100644 index d8d79d29b8a41..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/indirect.rs +++ /dev/null @@ -1,7 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -C overflow-checks=on - -// EMIT_MIR indirect.main.DataflowConstProp.diff -fn main() { - let x = (2u32 as u8) + 1; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff deleted file mode 100644 index 9cf6c1f989cd8..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.main.DataflowConstProp.diff +++ /dev/null @@ -1,74 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:+0:11: +0:11 - let _1: char; // in scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22 - let mut _2: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:+6:34: +6:63 - let mut _4: E; // in scope 0 at $DIR/invalid_constant.rs:+13:25: +13:59 - let mut _5: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:+13:34: +13:55 - let mut _7: Empty; // in scope 0 at $DIR/invalid_constant.rs:+20:35: +20:73 - let mut _8: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:+20:44: +20:65 - scope 1 { - debug _invalid_char => _1; // in scope 1 at $DIR/invalid_constant.rs:+6:9: +6:22 - let _3: [E; 1]; // in scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21 - scope 3 { - debug _invalid_tag => _3; // in scope 3 at $DIR/invalid_constant.rs:+13:9: +13:21 - let _6: [Empty; 1]; // in scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31 - scope 5 { - debug _enum_without_variants => _6; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31 - let _9: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22 - scope 7 { - debug _non_utf8_str => _9; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22 - } - } - scope 6 { - } - } - scope 4 { - } - } - scope 2 { - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22 - StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 - Deinit(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 - (_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63 - _1 = const {transmute(0x00110001): char}; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67 - StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:+6:69: +6:70 - StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21 - StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:+13:25: +13:59 - StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 - Deinit(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 - (_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55 - _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57 - // mir::Constant - // + span: $DIR/invalid_constant.rs:32:34: 32:57 - // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } - _3 = [const Scalar(0x00000004): E]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60 - // mir::Constant - // + span: $DIR/invalid_constant.rs:32:24: 32:60 - // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } - StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60 - StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61 - StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31 - StorageLive(_7); // scope 3 at $DIR/invalid_constant.rs:+20:35: +20:73 - StorageLive(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65 - Deinit(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65 - (_8.0: u32) = const 0_u32; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65 - nop; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71 - nop; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74 - StorageDead(_7); // scope 3 at $DIR/invalid_constant.rs:+20:73: +20:74 - StorageDead(_8); // scope 3 at $DIR/invalid_constant.rs:+20:74: +20:75 - StorageLive(_9); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22 - nop; // scope 0 at $DIR/invalid_constant.rs:+0:11: +25:2 - StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:+25:1: +25:2 - StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+25:1: +25:2 - StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+25:1: +25:2 - StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+25:1: +25:2 - return; // scope 0 at $DIR/invalid_constant.rs:+25:2: +25:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.rs b/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.rs deleted file mode 100644 index 296fdcf0bc43c..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/invalid_constant.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Verify that we can pretty print invalid constants. - -#![feature(adt_const_params)] -#![feature(inline_const)] -#![allow(incomplete_features)] - -#[derive(Copy, Clone)] -#[repr(u32)] -enum E { - A, - B, - C, -} - -#[derive(Copy, Clone)] -enum Empty {} - -// EMIT_MIR invalid_constant.main.DataflowConstProp.diff -fn main() { - // An invalid char. - union InvalidChar { - int: u32, - chr: char, - } - let _invalid_char = unsafe { InvalidChar { int: 0x110001 }.chr }; - - // An enum with an invalid tag. Regression test for #93688. - union InvalidTag { - int: u32, - e: E, - } - let _invalid_tag = [unsafe { InvalidTag { int: 4 }.e }]; - - // An enum without variants. Regression test for #94073. - union NoVariants { - int: u32, - empty: Empty, - } - let _enum_without_variants = [unsafe { NoVariants { int: 0 }.empty }]; - - // A non-UTF-8 string slice. Regression test for #75763 and #78520. - struct Str; - let _non_utf8_str: Str<{ unsafe { std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5]) } }>; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/issue-66971.rs b/src/test/mir-opt/dataflow-const-prop/previous/issue-66971.rs deleted file mode 100644 index 39f0ace71347e..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/issue-66971.rs +++ /dev/null @@ -1,18 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -Z mir-opt-level=3 - -// Due to a bug in propagating scalar pairs the assertion below used to fail. In the expected -// outputs below, after DataflowConstProp this is how _2 would look like with the bug: -// -// _2 = (const Scalar(0x00) : (), const 0u8); -// -// Which has the wrong type. - -fn encode(this: ((), u8, u8)) { - assert!(this.2 == 0); -} - -// EMIT_MIR issue_66971.main.DataflowConstProp.diff -fn main() { - encode(((), 0, 0)); -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/issue-67019.rs b/src/test/mir-opt/dataflow-const-prop/previous/issue-67019.rs deleted file mode 100644 index 6d8b482a543ef..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/issue-67019.rs +++ /dev/null @@ -1,13 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -Z mir-opt-level=3 - -// This used to ICE in const-prop - -fn test(this: ((u8, u8),)) { - assert!((this.0).0 == 1); -} - -// EMIT_MIR issue_67019.main.DataflowConstProp.diff -fn main() { - test(((1, 2),)); -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/issue_66971.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/issue_66971.main.DataflowConstProp.diff deleted file mode 100644 index 62e94755f1283..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/issue_66971.main.DataflowConstProp.diff +++ /dev/null @@ -1,33 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-66971.rs:+0:11: +0:11 - let _1: (); // in scope 0 at $DIR/issue-66971.rs:+1:5: +1:23 - let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - let mut _3: (); // in scope 0 at $DIR/issue-66971.rs:+1:13: +1:15 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-66971.rs:+1:5: +1:23 - StorageLive(_2); // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - StorageLive(_3); // scope 0 at $DIR/issue-66971.rs:+1:13: +1:15 - nop; // scope 0 at $DIR/issue-66971.rs:+1:13: +1:15 - Deinit(_2); // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - nop; // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue-66971.rs:+1:12: +1:22 - StorageDead(_3); // scope 0 at $DIR/issue-66971.rs:+1:21: +1:22 - _1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue-66971.rs:+1:5: +1:23 - // mir::Constant - // + span: $DIR/issue-66971.rs:17:5: 17:11 - // + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value() } - } - - bb1: { - StorageDead(_2); // scope 0 at $DIR/issue-66971.rs:+1:22: +1:23 - StorageDead(_1); // scope 0 at $DIR/issue-66971.rs:+1:23: +1:24 - nop; // scope 0 at $DIR/issue-66971.rs:+0:11: +2:2 - return; // scope 0 at $DIR/issue-66971.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff deleted file mode 100644 index ddbbb11397229..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/issue_67019.main.DataflowConstProp.diff +++ /dev/null @@ -1,33 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-67019.rs:+0:11: +0:11 - let _1: (); // in scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 - let mut _2: ((u8, u8),); // in scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 - let mut _3: (u8, u8); // in scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 - StorageLive(_2); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 - StorageLive(_3); // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 - Deinit(_3); // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 - (_3.0: u8) = const 1_u8; // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 - (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue-67019.rs:+1:11: +1:17 - Deinit(_2); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 - (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue-67019.rs:+1:10: +1:19 - StorageDead(_3); // scope 0 at $DIR/issue-67019.rs:+1:18: +1:19 - _1 = test(move _2) -> bb1; // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 - // mir::Constant - // + span: $DIR/issue-67019.rs:12:5: 12:9 - // + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value() } - } - - bb1: { - StorageDead(_2); // scope 0 at $DIR/issue-67019.rs:+1:19: +1:20 - StorageDead(_1); // scope 0 at $DIR/issue-67019.rs:+1:20: +1:21 - nop; // scope 0 at $DIR/issue-67019.rs:+0:11: +2:2 - return; // scope 0 at $DIR/issue-67019.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff deleted file mode 100644 index 487b2b74371d8..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.32bit.diff +++ /dev/null @@ -1,35 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/large_array_index.rs:+0:11: +0:11 - let _1: u8; // in scope 0 at $DIR/large_array_index.rs:+2:9: +2:10 - let mut _2: [u8; 5000]; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 - let _3: usize; // in scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 - let mut _4: usize; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - let mut _5: bool; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - scope 1 { - debug x => _1; // in scope 1 at $DIR/large_array_index.rs:+2:9: +2:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/large_array_index.rs:+2:9: +2:10 - StorageLive(_2); // scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 - _2 = [const 0_u8; 5000]; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 - StorageLive(_3); // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 - _3 = const 2_usize; // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 - _4 = const 5000_usize; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - _5 = const true; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - } - - bb1: { - _1 = _2[_3]; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - StorageDead(_3); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 - StorageDead(_2); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 - nop; // scope 0 at $DIR/large_array_index.rs:+0:11: +3:2 - StorageDead(_1); // scope 0 at $DIR/large_array_index.rs:+3:1: +3:2 - return; // scope 0 at $DIR/large_array_index.rs:+3:2: +3:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff deleted file mode 100644 index 487b2b74371d8..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.main.DataflowConstProp.64bit.diff +++ /dev/null @@ -1,35 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/large_array_index.rs:+0:11: +0:11 - let _1: u8; // in scope 0 at $DIR/large_array_index.rs:+2:9: +2:10 - let mut _2: [u8; 5000]; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 - let _3: usize; // in scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 - let mut _4: usize; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - let mut _5: bool; // in scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - scope 1 { - debug x => _1; // in scope 1 at $DIR/large_array_index.rs:+2:9: +2:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/large_array_index.rs:+2:9: +2:10 - StorageLive(_2); // scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 - _2 = [const 0_u8; 5000]; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:29 - StorageLive(_3); // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 - _3 = const 2_usize; // scope 0 at $DIR/large_array_index.rs:+2:30: +2:31 - _4 = const 5000_usize; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - _5 = const true; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - } - - bb1: { - _1 = _2[_3]; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 - StorageDead(_3); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 - StorageDead(_2); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 - nop; // scope 0 at $DIR/large_array_index.rs:+0:11: +3:2 - StorageDead(_1); // scope 0 at $DIR/large_array_index.rs:+3:1: +3:2 - return; // scope 0 at $DIR/large_array_index.rs:+3:2: +3:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.rs b/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.rs deleted file mode 100644 index a1002401f57b6..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/large_array_index.rs +++ /dev/null @@ -1,7 +0,0 @@ -// EMIT_MIR_FOR_EACH_BIT_WIDTH - -// EMIT_MIR large_array_index.main.DataflowConstProp.diff -fn main() { - // check that we don't propagate this, because it's too large - let x: u8 = [0_u8; 5000][2]; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs deleted file mode 100644 index a6f156fe052ee..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.rs +++ /dev/null @@ -1,10 +0,0 @@ -// unit-test: DataflowConstProp - -// EMIT_MIR mult_by_zero.test.DataflowConstProp.diff -fn test(x: i32) -> i32 { - x * 0 -} - -fn main() { - test(10); -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff deleted file mode 100644 index c225b35e19239..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mult_by_zero.test.DataflowConstProp.diff +++ /dev/null @@ -1,17 +0,0 @@ -- // MIR for `test` before DataflowConstProp -+ // MIR for `test` after DataflowConstProp - - fn test(_1: i32) -> i32 { - debug x => _1; // in scope 0 at $DIR/mult_by_zero.rs:+0:9: +0:10 - let mut _0: i32; // return place in scope 0 at $DIR/mult_by_zero.rs:+0:20: +0:23 - let mut _2: i32; // in scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:6 - - bb0: { - StorageLive(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:6 - _2 = _1; // scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:6 - _0 = Mul(move _2, const 0_i32); // scope 0 at $DIR/mult_by_zero.rs:+1:5: +1:10 - StorageDead(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:9: +1:10 - return; // scope 0 at $DIR/mult_by_zero.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff deleted file mode 100644 index 098440dbe2f1e..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.main.DataflowConstProp.diff +++ /dev/null @@ -1,28 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/mutable_variable.rs:+0:11: +0:11 - let mut _1: i32; // in scope 0 at $DIR/mutable_variable.rs:+1:9: +1:14 - scope 1 { - debug x => _1; // in scope 1 at $DIR/mutable_variable.rs:+1:9: +1:14 - let _2: i32; // in scope 1 at $DIR/mutable_variable.rs:+3:9: +3:10 - scope 2 { - debug y => _2; // in scope 2 at $DIR/mutable_variable.rs:+3:9: +3:10 - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/mutable_variable.rs:+1:9: +1:14 - _1 = const 42_i32; // scope 0 at $DIR/mutable_variable.rs:+1:17: +1:19 - _1 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+2:5: +2:11 - StorageLive(_2); // scope 1 at $DIR/mutable_variable.rs:+3:9: +3:10 -- _2 = _1; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 -+ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 - _0 = const (); // scope 0 at $DIR/mutable_variable.rs:+0:11: +4:2 - StorageDead(_2); // scope 1 at $DIR/mutable_variable.rs:+4:1: +4:2 - StorageDead(_1); // scope 0 at $DIR/mutable_variable.rs:+4:1: +4:2 - return; // scope 0 at $DIR/mutable_variable.rs:+4:2: +4:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs deleted file mode 100644 index 680bcd7fc703b..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable.rs +++ /dev/null @@ -1,8 +0,0 @@ -// unit-test: DataflowConstProp - -// EMIT_MIR mutable_variable.main.DataflowConstProp.diff -fn main() { - let mut x = 42; - x = 99; - let y = x; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff deleted file mode 100644 index 1180dffdbadbf..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.main.DataflowConstProp.diff +++ /dev/null @@ -1,29 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +0:11 - let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 - scope 1 { - debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 - let _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 - scope 2 { - debug y => _2; // in scope 2 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14 - Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 - (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 - (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25 - (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13 - StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 - _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 - _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +4:2 - StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 - StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 - return; // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:2: +4:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs deleted file mode 100644 index 255236049f988..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate.rs +++ /dev/null @@ -1,8 +0,0 @@ -// unit-test: DataflowConstProp - -// EMIT_MIR mutable_variable_aggregate.main.DataflowConstProp.diff -fn main() { - let mut x = (42, 43); - x.1 = 99; - let y = x; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff deleted file mode 100644 index f278854780073..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff +++ /dev/null @@ -1,36 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+0:11: +0:11 - let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:9: +1:14 - scope 1 { - debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:9: +1:14 - let _2: &mut (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10 - scope 2 { - debug z => _2; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10 - let _3: (i32, i32); // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 - scope 3 { - debug y => _3; // in scope 3 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:9: +1:14 - Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25 - (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25 - (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25 - StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10 - _2 = &mut _1; // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:13: +2:19 - ((*_2).1: i32) = const 99_i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+3:5: +3:13 - StorageLive(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 - _3 = _1; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14 - _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+0:11: +5:2 - StorageDead(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 - StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 - StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 - return; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs deleted file mode 100644 index 54b898b4ee5c5..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_mut_ref.rs +++ /dev/null @@ -1,9 +0,0 @@ -// unit-test: DataflowConstProp - -// EMIT_MIR mutable_variable_aggregate_mut_ref.main.DataflowConstProp.diff -fn main() { - let mut x = (42, 43); - let z = &mut x; - z.1 = 99; - let y = x; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff deleted file mode 100644 index 1f8e283f33a56..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff +++ /dev/null @@ -1,35 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+0:11: +0:11 - let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14 - scope 1 { - debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14 - let _2: i32; // in scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:9: +4:10 - scope 2 { - debug y => _2; // in scope 2 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:9: +4:10 - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14 - _1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:29: +1:34 - // mir::Constant - // + span: $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:32 - // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value() } - } - - bb1: { - (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+2:5: +2:13 - (_1.0: i32) = const 42_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+3:5: +3:13 - StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:9: +4:10 -- _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 -+ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 - _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+0:11: +5:2 - StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2 - StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2 - return; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs deleted file mode 100644 index 0439a52081998..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_aggregate_partial_read.rs +++ /dev/null @@ -1,14 +0,0 @@ -// unit-test: DataflowConstProp - -// EMIT_MIR mutable_variable_aggregate_partial_read.main.DataflowConstProp.diff -fn main() { - let mut x: (i32, i32) = foo(); - x.1 = 99; - x.0 = 42; - let y = x.1; -} - -#[inline(never)] -fn foo() -> (i32, i32) { - unimplemented!() -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff deleted file mode 100644 index 9363e6b9aa1ce..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.main.DataflowConstProp.diff +++ /dev/null @@ -1,48 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +0:11 - let mut _1: u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14 - let _2: (); // in scope 0 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 - let mut _3: u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 - let mut _4: *mut u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 - scope 1 { - debug x => _1; // in scope 1 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14 - let _5: u32; // in scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 - scope 2 { - } - scope 3 { - debug y => _5; // in scope 3 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14 - _1 = const 42_u32; // scope 0 at $DIR/mutable_variable_no_prop.rs:+1:17: +1:19 - StorageLive(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 - StorageLive(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 - StorageLive(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 - _4 = const {alloc1: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 - // mir::Constant - // + span: $DIR/mutable_variable_no_prop.rs:9:13: 9:19 - // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) } - _3 = (*_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 - _1 = move _3; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19 - StorageDead(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:18: +3:19 - StorageDead(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:19: +3:20 - _2 = const (); // scope 2 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 - StorageDead(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:+4:5: +4:6 - StorageLive(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 - _5 = _1; // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:13: +5:14 - _0 = const (); // scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +6:2 - StorageDead(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 - StorageDead(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 - return; // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:2: +6:2 - } - } - - alloc1 (static: STATIC, size: 4, align: 4) { - 2a 00 00 00 │ *... - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs deleted file mode 100644 index e4edf1475f2bf..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_no_prop.rs +++ /dev/null @@ -1,12 +0,0 @@ -// unit-test: DataflowConstProp - -static mut STATIC: u32 = 42; - -// EMIT_MIR mutable_variable_no_prop.main.DataflowConstProp.diff -fn main() { - let mut x = 42; - unsafe { - x = STATIC; - } - let y = x; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff deleted file mode 100644 index 8d31d5533da2a..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.main.DataflowConstProp.diff +++ /dev/null @@ -1,54 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 - let mut _3: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - scope 1 { - debug a => _1; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 - let mut _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - scope 2 { - debug x => _2; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - let _4: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 - scope 3 { - debug y => _4; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 - let _5: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 - scope 4 { - debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 - } - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 - _1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:13: +1:18 - // mir::Constant - // + span: $DIR/mutable_variable_unprop_assign.rs:5:13: 5:16 - // + literal: Const { ty: fn() -> i32 {foo}, val: Value() } - } - - bb1: { - StorageLive(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - Deinit(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - (_2.0: i32) = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - (_2.1: i32) = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - _3 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - (_2.1: i32) = move _3; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12 - StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - StorageLive(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 - _4 = (_2.1: i32); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 - StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 -- _5 = (_2.0: i32); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 -+ _5 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 - _0 = const (); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +6:2 - StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:2: +6:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs b/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs deleted file mode 100644 index 942e96fee4442..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/mutable_variable_unprop_assign.rs +++ /dev/null @@ -1,15 +0,0 @@ -// unit-test: DataflowConstProp - -// EMIT_MIR mutable_variable_unprop_assign.main.DataflowConstProp.diff -fn main() { - let a = foo(); - let mut x: (i32, i32) = (1, 2); - x.1 = a; - let y = x.1; - let z = x.0; // this could theoretically be allowed, but we can't handle it right now -} - -#[inline(never)] -fn foo() -> i32 { - unimplemented!() -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff deleted file mode 100644 index 3b77cb6e543c2..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.32bit.diff +++ /dev/null @@ -1,61 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - let mut _2: (i32, bool); // in scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 - let mut _4: [i32; 6]; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 - let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 - let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 - scope 1 { - debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - scope 2 { - debug y => _3; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - let _8: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - scope 3 { - debug z => _8; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 - assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 - } - - bb1: { - _1 = const 4_i32; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 - StorageLive(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - StorageLive(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 - _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 - StorageLive(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 - _5 = const 3_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 - _6 = const 6_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - _7 = const true; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - } - - bb2: { - _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 - StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 - StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 - Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 - (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 - (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 - _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:39 - StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:39: +3:40 - nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 - StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff deleted file mode 100644 index 3b77cb6e543c2..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.DataflowConstProp.64bit.diff +++ /dev/null @@ -1,61 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - let mut _2: (i32, bool); // in scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 - let mut _4: [i32; 6]; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 - let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 - let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 - scope 1 { - debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - scope 2 { - debug y => _3; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - let _8: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - scope 3 { - debug z => _8; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 - assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 - } - - bb1: { - _1 = const 4_i32; // scope 0 at $DIR/optimizes_into_variable.rs:+1:13: +1:18 - StorageLive(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - StorageLive(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 - _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:31 - StorageLive(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 - _5 = const 3_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 - _6 = const 6_usize; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - _7 = const true; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - } - - bb2: { - _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 - StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 - StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 - Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 - (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 - (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:37 - _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:39 - StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:39: +3:40 - nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 - StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir deleted file mode 100644 index 75cea8ad2cebf..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir +++ /dev/null @@ -1,27 +0,0 @@ -// MIR for `main` after SimplifyLocals - -fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - scope 1 { - debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - scope 2 { - debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - scope 3 { - debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 - } -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir deleted file mode 100644 index 75cea8ad2cebf..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir +++ /dev/null @@ -1,27 +0,0 @@ -// MIR for `main` after SimplifyLocals - -fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - scope 1 { - debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - scope 2 { - debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - scope 3 { - debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 - StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 - StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 - return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2 - } -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.rs b/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.rs deleted file mode 100644 index 189a080dbef78..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/optimizes_into_variable.rs +++ /dev/null @@ -1,16 +0,0 @@ -// unit-test -// compile-flags: -C overflow-checks=on - -struct Point { - x: u32, - y: u32, -} - -// EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR optimizes_into_variable.main.DataflowConstProp.diff -// EMIT_MIR optimizes_into_variable.main.SimplifyLocals.after.mir -fn main() { - let x = 2 + 2; - let y = [0, 1, 2, 3, 4, 5][3]; - let z = (Point { x: 12, y: 42 }).y; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff deleted file mode 100644 index a48ba5bf2e1bb..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.main.DataflowConstProp.diff +++ /dev/null @@ -1,45 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/read_immutable_static.rs:+0:11: +0:11 - let _1: u8; // in scope 0 at $DIR/read_immutable_static.rs:+1:9: +1:10 - let mut _2: u8; // in scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 - let mut _3: &u8; // in scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 - let mut _4: u8; // in scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 - let mut _5: &u8; // in scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 - scope 1 { - debug x => _1; // in scope 1 at $DIR/read_immutable_static.rs:+1:9: +1:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/read_immutable_static.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 - StorageLive(_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 - _3 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 - // mir::Constant - // + span: $DIR/read_immutable_static.rs:7:13: 7:16 - // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } - _2 = (*_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 - StorageLive(_4); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 - StorageLive(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 - _5 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 - // mir::Constant - // + span: $DIR/read_immutable_static.rs:7:19: 7:22 - // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } - _4 = (*_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 - _1 = Add(move _2, move _4); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22 - StorageDead(_4); // scope 0 at $DIR/read_immutable_static.rs:+1:21: +1:22 - StorageDead(_2); // scope 0 at $DIR/read_immutable_static.rs:+1:21: +1:22 - StorageDead(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23 - StorageDead(_3); // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23 - _0 = const (); // scope 0 at $DIR/read_immutable_static.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/read_immutable_static.rs:+2:1: +2:2 - return; // scope 0 at $DIR/read_immutable_static.rs:+2:2: +2:2 - } - } - - alloc1 (static: FOO, size: 1, align: 1) { - 02 │ . - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs b/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs deleted file mode 100644 index 6324b4a9c545b..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/read_immutable_static.rs +++ /dev/null @@ -1,8 +0,0 @@ -// unit-test: DataflowConstProp - -static FOO: u8 = 2; - -// EMIT_MIR read_immutable_static.main.DataflowConstProp.diff -fn main() { - let x = FOO + FOO; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff deleted file mode 100644 index 018178ab624e3..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.DataflowConstProp.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/ref_deref.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 - let mut _2: &i32; // in scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - let _3: i32; // in scope 0 at $DIR/ref_deref.rs:+1:8: +1:9 - let mut _4: &i32; // in scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 - StorageLive(_2); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - _4 = const _; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - // mir::Constant - // + span: $DIR/ref_deref.rs:6:6: 6:10 - // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } - _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 - StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 - StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 - _0 = const (); // scope 0 at $DIR/ref_deref.rs:+0:11: +2:2 - return; // scope 0 at $DIR/ref_deref.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff deleted file mode 100644 index 015ec4d078c10..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.main.PromoteTemps.diff +++ /dev/null @@ -1,30 +0,0 @@ -- // MIR for `main` before PromoteTemps -+ // MIR for `main` after PromoteTemps - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/ref_deref.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 - let mut _2: &i32; // in scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - let _3: i32; // in scope 0 at $DIR/ref_deref.rs:+1:8: +1:9 -+ let mut _4: &i32; // in scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 - StorageLive(_2); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 -- StorageLive(_3); // scope 0 at $DIR/ref_deref.rs:+1:8: +1:9 -- _3 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:+1:8: +1:9 -- _2 = &_3; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 -+ _4 = const _; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 -+ // mir::Constant -+ // + span: $DIR/ref_deref.rs:6:6: 6:10 -+ // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } -+ _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 -- StorageDead(_3); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 - StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 - StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 - _0 = const (); // scope 0 at $DIR/ref_deref.rs:+0:11: +2:2 - return; // scope 0 at $DIR/ref_deref.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs deleted file mode 100644 index b3ec2383b913c..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref.rs +++ /dev/null @@ -1,7 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR ref_deref.main.PromoteTemps.diff -// EMIT_MIR ref_deref.main.DataflowConstProp.diff - -fn main() { - *(&4); -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff deleted file mode 100644 index f16d2fcafb8fa..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.DataflowConstProp.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/ref_deref_project.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 - let mut _2: &i32; // in scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 - let _3: (i32, i32); // in scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14 - let mut _4: &(i32, i32); // in scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 - StorageLive(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 - _4 = const _; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 - // mir::Constant - // + span: $DIR/ref_deref_project.rs:6:6: 6:17 - // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } - _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 - _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 - StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 - StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 - _0 = const (); // scope 0 at $DIR/ref_deref_project.rs:+0:11: +2:2 - return; // scope 0 at $DIR/ref_deref_project.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff deleted file mode 100644 index cd0616e65baf8..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.main.PromoteTemps.diff +++ /dev/null @@ -1,30 +0,0 @@ -- // MIR for `main` before PromoteTemps -+ // MIR for `main` after PromoteTemps - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/ref_deref_project.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 - let mut _2: &i32; // in scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 - let _3: (i32, i32); // in scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14 -+ let mut _4: &(i32, i32); // in scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 - StorageLive(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 -- StorageLive(_3); // scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14 -- _3 = (const 4_i32, const 5_i32); // scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14 -- _2 = &(_3.1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 -+ _4 = const _; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 -+ // mir::Constant -+ // + span: $DIR/ref_deref_project.rs:6:6: 6:17 -+ // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } -+ _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 - _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 -- StorageDead(_3); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 - StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 - StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 - _0 = const (); // scope 0 at $DIR/ref_deref_project.rs:+0:11: +2:2 - return; // scope 0 at $DIR/ref_deref_project.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs b/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs deleted file mode 100644 index 65175917e13b8..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/ref_deref_project.rs +++ /dev/null @@ -1,7 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR ref_deref_project.main.PromoteTemps.diff -// EMIT_MIR ref_deref_project.main.DataflowConstProp.diff - -fn main() { - *(&(4, 5).1); // This does not currently propagate (#67862) -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff deleted file mode 100644 index 6822f353b05bd..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.main.DataflowConstProp.diff +++ /dev/null @@ -1,29 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +0:11 - let mut _1: *const fn(); // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41 - let mut _2: usize; // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 - let mut _3: fn(); // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 - scope 1 { - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41 - StorageLive(_2); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 - StorageLive(_3); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 - _3 = main as fn() (Pointer(ReifyFnPointer)); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 - // mir::Constant - // + span: $DIR/reify_fn_ptr.rs:5:13: 5:17 - // + literal: Const { ty: fn() {main}, val: Value() } - _2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 - StorageDead(_3); // scope 0 at $DIR/reify_fn_ptr.rs:+1:25: +1:26 - _1 = move _2 as *const fn() (PointerFromExposedAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41 - StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:+1:40: +1:41 - StorageDead(_1); // scope 0 at $DIR/reify_fn_ptr.rs:+1:41: +1:42 - _0 = const (); // scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +2:2 - return; // scope 0 at $DIR/reify_fn_ptr.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs b/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs deleted file mode 100644 index c69680d36e2b5..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/reify_fn_ptr.rs +++ /dev/null @@ -1,6 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR reify_fn_ptr.main.DataflowConstProp.diff - -fn main() { - let _ = main as usize as *const fn(); -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff deleted file mode 100644 index 4e3de9df468e0..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.32bit.diff +++ /dev/null @@ -1,41 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/repeat.rs:+0:11: +0:11 - let _1: u32; // in scope 0 at $DIR/repeat.rs:+1:9: +1:10 - let mut _2: u32; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 - let mut _3: [u32; 8]; // in scope 0 at $DIR/repeat.rs:+1:18: +1:25 - let _4: usize; // in scope 0 at $DIR/repeat.rs:+1:26: +1:27 - let mut _5: usize; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 - let mut _6: bool; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 - scope 1 { - debug x => _1; // in scope 1 at $DIR/repeat.rs:+1:9: +1:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/repeat.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - StorageLive(_3); // scope 0 at $DIR/repeat.rs:+1:18: +1:25 - _3 = [const 42_u32; 8]; // scope 0 at $DIR/repeat.rs:+1:18: +1:25 - StorageLive(_4); // scope 0 at $DIR/repeat.rs:+1:26: +1:27 - _4 = const 2_usize; // scope 0 at $DIR/repeat.rs:+1:26: +1:27 - _5 = Len(_3); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -- _6 = Lt(_4, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -+ _6 = Lt(const 2_usize, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - } - - bb1: { - _2 = _3[_4]; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - _1 = Add(move _2, const 0_u32); // scope 0 at $DIR/repeat.rs:+1:18: +1:32 - StorageDead(_2); // scope 0 at $DIR/repeat.rs:+1:31: +1:32 - StorageDead(_4); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 - StorageDead(_3); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 - _0 = const (); // scope 0 at $DIR/repeat.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/repeat.rs:+2:1: +2:2 - return; // scope 0 at $DIR/repeat.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff deleted file mode 100644 index 4e3de9df468e0..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/repeat.main.DataflowConstProp.64bit.diff +++ /dev/null @@ -1,41 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/repeat.rs:+0:11: +0:11 - let _1: u32; // in scope 0 at $DIR/repeat.rs:+1:9: +1:10 - let mut _2: u32; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 - let mut _3: [u32; 8]; // in scope 0 at $DIR/repeat.rs:+1:18: +1:25 - let _4: usize; // in scope 0 at $DIR/repeat.rs:+1:26: +1:27 - let mut _5: usize; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 - let mut _6: bool; // in scope 0 at $DIR/repeat.rs:+1:18: +1:28 - scope 1 { - debug x => _1; // in scope 1 at $DIR/repeat.rs:+1:9: +1:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/repeat.rs:+1:9: +1:10 - StorageLive(_2); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - StorageLive(_3); // scope 0 at $DIR/repeat.rs:+1:18: +1:25 - _3 = [const 42_u32; 8]; // scope 0 at $DIR/repeat.rs:+1:18: +1:25 - StorageLive(_4); // scope 0 at $DIR/repeat.rs:+1:26: +1:27 - _4 = const 2_usize; // scope 0 at $DIR/repeat.rs:+1:26: +1:27 - _5 = Len(_3); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -- _6 = Lt(_4, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -+ _6 = Lt(const 2_usize, _5); // scope 0 at $DIR/repeat.rs:+1:18: +1:28 -+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - } - - bb1: { - _2 = _3[_4]; // scope 0 at $DIR/repeat.rs:+1:18: +1:28 - _1 = Add(move _2, const 0_u32); // scope 0 at $DIR/repeat.rs:+1:18: +1:32 - StorageDead(_2); // scope 0 at $DIR/repeat.rs:+1:31: +1:32 - StorageDead(_4); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 - StorageDead(_3); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 - _0 = const (); // scope 0 at $DIR/repeat.rs:+0:11: +2:2 - StorageDead(_1); // scope 0 at $DIR/repeat.rs:+2:1: +2:2 - return; // scope 0 at $DIR/repeat.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/repeat.rs b/src/test/mir-opt/dataflow-const-prop/previous/repeat.rs deleted file mode 100644 index df5284d11dadf..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/repeat.rs +++ /dev/null @@ -1,7 +0,0 @@ -// unit-test: DataflowConstProp - -// EMIT_MIR_FOR_EACH_BIT_WIDTH -// EMIT_MIR repeat.main.DataflowConstProp.diff -fn main() { - let x: u32 = [42; 8][2] + 0; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff deleted file mode 100644 index 07cdba28e042f..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.DataflowConstProp.diff +++ /dev/null @@ -1,20 +0,0 @@ -- // MIR for `add` before DataflowConstProp -+ // MIR for `add` after DataflowConstProp - - fn add() -> u32 { - let mut _0: u32; // return place in scope 0 at $DIR/return_place.rs:+0:13: +0:16 - let mut _1: (u32, bool); // in scope 0 at $DIR/return_place.rs:+1:5: +1:10 - - bb0: { - _1 = CheckedAdd(const 2_u32, const 2_u32); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 -- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 - } - - bb1: { -- _0 = move (_1.0: u32); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 -+ _0 = const 4_u32; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 - return; // scope 0 at $DIR/return_place.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir b/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir deleted file mode 100644 index 4f5ea6320f16a..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/return_place.add.PreCodegen.before.mir +++ /dev/null @@ -1,16 +0,0 @@ -// MIR for `add` before PreCodegen - -fn add() -> u32 { - let mut _0: u32; // return place in scope 0 at $DIR/return_place.rs:+0:13: +0:16 - let mut _1: (u32, bool); // in scope 0 at $DIR/return_place.rs:+1:5: +1:10 - - bb0: { - _1 = CheckedAdd(const 2_u32, const 2_u32); // scope 0 at $DIR/return_place.rs:+1:5: +1:10 - assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 - } - - bb1: { - _0 = const 4_u32; // scope 0 at $DIR/return_place.rs:+1:5: +1:10 - return; // scope 0 at $DIR/return_place.rs:+2:2: +2:2 - } -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/return_place.rs b/src/test/mir-opt/dataflow-const-prop/previous/return_place.rs deleted file mode 100644 index 26365cc5db2dc..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/return_place.rs +++ /dev/null @@ -1,12 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -C overflow-checks=on - -// EMIT_MIR return_place.add.DataflowConstProp.diff -// EMIT_MIR return_place.add.PreCodegen.before.mir -fn add() -> u32 { - 2 + 2 -} - -fn main() { - add(); -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff deleted file mode 100644 index a0212aea5dd8a..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.main.DataflowConstProp.diff +++ /dev/null @@ -1,35 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/scalar_literal_propagation.rs:+0:11: +0:11 - let _1: u32; // in scope 0 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10 - let _2: (); // in scope 0 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 - let mut _3: u32; // in scope 0 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 - scope 1 { - debug x => _1; // in scope 1 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10 - _1 = const 1_u32; // scope 0 at $DIR/scalar_literal_propagation.rs:+1:13: +1:14 - StorageLive(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 - StorageLive(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 -- _3 = _1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 -- _2 = consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 -+ _3 = const 1_u32; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14 -+ _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 - // mir::Constant - // + span: $DIR/scalar_literal_propagation.rs:5:5: 5:12 - // + literal: Const { ty: fn(u32) {consume}, val: Value() } - } - - bb1: { - StorageDead(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:14: +2:15 - StorageDead(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:15: +2:16 - _0 = const (); // scope 0 at $DIR/scalar_literal_propagation.rs:+0:11: +3:2 - StorageDead(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+3:1: +3:2 - return; // scope 0 at $DIR/scalar_literal_propagation.rs:+3:2: +3:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs b/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs deleted file mode 100644 index d26cb30c07645..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/scalar_literal_propagation.rs +++ /dev/null @@ -1,9 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR scalar_literal_propagation.main.DataflowConstProp.diff -fn main() { - let x = 1; - consume(x); -} - -#[inline(never)] -fn consume(_: u32) {} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff deleted file mode 100644 index e39afae5aa626..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.32bit.diff +++ /dev/null @@ -1,48 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/slice_len.rs:+0:11: +0:11 - let _1: u32; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - let mut _2: &[u32]; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:30 - let mut _3: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - let _4: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - let _5: [u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:7: +1:19 - let _6: usize; // in scope 0 at $DIR/slice_len.rs:+1:31: +1:32 - let mut _7: usize; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - let mut _8: bool; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - let mut _9: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - StorageLive(_2); // scope 0 at $DIR/slice_len.rs:+1:5: +1:30 - StorageLive(_3); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - // mir::Constant - // + span: $DIR/slice_len.rs:6:6: 6:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } - _4 = &(*_9); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _3 = &(*_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - StorageDead(_3); // scope 0 at $DIR/slice_len.rs:+1:18: +1:19 - StorageLive(_6); // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 - _6 = const 1_usize; // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 - _7 = Len((*_2)); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -- _8 = Lt(_6, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -+ _8 = Lt(const 1_usize, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - } - - bb1: { - _1 = (*_2)[_6]; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - StorageDead(_6); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 - StorageDead(_4); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 - StorageDead(_2); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 - StorageDead(_1); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 - _0 = const (); // scope 0 at $DIR/slice_len.rs:+0:11: +2:2 - return; // scope 0 at $DIR/slice_len.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff deleted file mode 100644 index e39afae5aa626..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.main.DataflowConstProp.64bit.diff +++ /dev/null @@ -1,48 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/slice_len.rs:+0:11: +0:11 - let _1: u32; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - let mut _2: &[u32]; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:30 - let mut _3: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - let _4: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - let _5: [u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:7: +1:19 - let _6: usize; // in scope 0 at $DIR/slice_len.rs:+1:31: +1:32 - let mut _7: usize; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - let mut _8: bool; // in scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - let mut _9: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - StorageLive(_2); // scope 0 at $DIR/slice_len.rs:+1:5: +1:30 - StorageLive(_3); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - // mir::Constant - // + span: $DIR/slice_len.rs:6:6: 6:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } - _4 = &(*_9); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _3 = &(*_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 - StorageDead(_3); // scope 0 at $DIR/slice_len.rs:+1:18: +1:19 - StorageLive(_6); // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 - _6 = const 1_usize; // scope 0 at $DIR/slice_len.rs:+1:31: +1:32 - _7 = Len((*_2)); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -- _8 = Lt(_6, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -+ _8 = Lt(const 1_usize, _7); // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - } - - bb1: { - _1 = (*_2)[_6]; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33 - StorageDead(_6); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 - StorageDead(_4); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 - StorageDead(_2); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 - StorageDead(_1); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34 - _0 = const (); // scope 0 at $DIR/slice_len.rs:+0:11: +2:2 - return; // scope 0 at $DIR/slice_len.rs:+2:2: +2:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs b/src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs deleted file mode 100644 index b22d33795ef10..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/slice_len.rs +++ /dev/null @@ -1,7 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR_FOR_EACH_BIT_WIDTH - -// EMIT_MIR slice_len.main.DataflowConstProp.diff -fn main() { - (&[1u32, 2, 3] as &[u32])[1]; -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff deleted file mode 100644 index b2f98061d2294..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.DataflowConstProp.diff +++ /dev/null @@ -1,33 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/switch_int.rs:+0:11: +0:11 - let mut _1: i32; // in scope 0 at $DIR/switch_int.rs:+1:11: +1:12 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/switch_int.rs:+1:11: +1:12 - _1 = const 1_i32; // scope 0 at $DIR/switch_int.rs:+1:11: +1:12 - switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12 - } - - bb1: { - _0 = foo(const -1_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+3:14: +3:21 - // mir::Constant - // + span: $DIR/switch_int.rs:9:14: 9:17 - // + literal: Const { ty: fn(i32) {foo}, val: Value() } - } - - bb2: { - _0 = foo(const 0_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+2:14: +2:20 - // mir::Constant - // + span: $DIR/switch_int.rs:8:14: 8:17 - // + literal: Const { ty: fn(i32) {foo}, val: Value() } - } - - bb3: { - StorageDead(_1); // scope 0 at $DIR/switch_int.rs:+5:1: +5:2 - return; // scope 0 at $DIR/switch_int.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.SimplifyConstCondition-after-const-prop.diff b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.SimplifyConstCondition-after-const-prop.diff deleted file mode 100644 index 74f9eafe42061..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.main.SimplifyConstCondition-after-const-prop.diff +++ /dev/null @@ -1,34 +0,0 @@ -- // MIR for `main` before SimplifyConstCondition-after-const-prop -+ // MIR for `main` after SimplifyConstCondition-after-const-prop - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/switch_int.rs:+0:11: +0:11 - let mut _1: i32; // in scope 0 at $DIR/switch_int.rs:+1:11: +1:12 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/switch_int.rs:+1:11: +1:12 - _1 = const 1_i32; // scope 0 at $DIR/switch_int.rs:+1:11: +1:12 -- switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12 -+ goto -> bb2; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12 - } - - bb1: { - _0 = foo(const -1_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+3:14: +3:21 - // mir::Constant - // + span: $DIR/switch_int.rs:9:14: 9:17 - // + literal: Const { ty: fn(i32) {foo}, val: Value() } - } - - bb2: { - _0 = foo(const 0_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+2:14: +2:20 - // mir::Constant - // + span: $DIR/switch_int.rs:8:14: 8:17 - // + literal: Const { ty: fn(i32) {foo}, val: Value() } - } - - bb3: { - StorageDead(_1); // scope 0 at $DIR/switch_int.rs:+5:1: +5:2 - return; // scope 0 at $DIR/switch_int.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.rs b/src/test/mir-opt/dataflow-const-prop/previous/switch_int.rs deleted file mode 100644 index eec51c5c48c25..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/switch_int.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[inline(never)] -fn foo(_: i32) {} - -// EMIT_MIR switch_int.main.DataflowConstProp.diff -// EMIT_MIR switch_int.main.SimplifyConstCondition-after-const-prop.diff -fn main() { - match 1 { - 1 => foo(0), - _ => foo(-1), - } -} diff --git a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff deleted file mode 100644 index 3a1b5f374f0ff..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.main.DataflowConstProp.diff +++ /dev/null @@ -1,35 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/tuple_literal_propagation.rs:+0:11: +0:11 - let _1: (u32, u32); // in scope 0 at $DIR/tuple_literal_propagation.rs:+1:9: +1:10 - let _2: (); // in scope 0 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 - let mut _3: (u32, u32); // in scope 0 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 - scope 1 { - debug x => _1; // in scope 1 at $DIR/tuple_literal_propagation.rs:+1:9: +1:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:9: +1:10 - Deinit(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 - (_1.0: u32) = const 1_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 - (_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 - StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 - StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 - _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14 - _2 = consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 - // mir::Constant - // + span: $DIR/tuple_literal_propagation.rs:6:5: 6:12 - // + literal: Const { ty: fn((u32, u32)) {consume}, val: Value() } - } - - bb1: { - StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15 - StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16 - _0 = const (); // scope 0 at $DIR/tuple_literal_propagation.rs:+0:11: +4:2 - StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2 - return; // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs b/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs deleted file mode 100644 index 737f39673a3c8..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/previous/tuple_literal_propagation.rs +++ /dev/null @@ -1,10 +0,0 @@ -// unit-test: DataflowConstProp -// EMIT_MIR tuple_literal_propagation.main.DataflowConstProp.diff -fn main() { - let x = (1, 2); - - consume(x); -} - -#[inline(never)] -fn consume(_: (u32, u32)) {} diff --git a/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff index 1dabb0ae3eea9..177736d62cd90 100644 --- a/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff @@ -16,7 +16,7 @@ StorageLive(_2); // scope 0 at $DIR/promoted.rs:+2:14: +2:17 _4 = const _; // scope 0 at $DIR/promoted.rs:+2:14: +2:17 // mir::Constant - // + span: $DIR/promoted.rs:6:14: 6:17 + // + span: $DIR/promoted.rs:7:14: 7:17 // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } _2 = &(*_4); // scope 0 at $DIR/promoted.rs:+2:14: +2:17 _1 = (*_2); // scope 0 at $DIR/promoted.rs:+2:13: +2:17 diff --git a/src/test/mir-opt/dataflow-const-prop/promoted.rs b/src/test/mir-opt/dataflow-const-prop/promoted.rs index 1653cf3334408..e5ca2f5b6072f 100644 --- a/src/test/mir-opt/dataflow-const-prop/promoted.rs +++ b/src/test/mir-opt/dataflow-const-prop/promoted.rs @@ -1,4 +1,5 @@ // unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts // EMIT_MIR promoted.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff deleted file mode 100644 index c344de76b6a32..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/recursive.main.DataflowConstProp.diff +++ /dev/null @@ -1,132 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/recursive.rs:+0:11: +0:11 - let _1: S<'_>; // in scope 0 at $DIR/recursive.rs:+2:9: +2:10 - let mut _3: &S<'_>; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 - let _4: &S<'_>; // in scope 0 at $DIR/recursive.rs:+3:20: +3:22 - let mut _6: &S<'_>; // in scope 0 at $DIR/recursive.rs:+4:20: +4:22 - let _7: &S<'_>; // in scope 0 at $DIR/recursive.rs:+4:20: +4:22 - let mut _9: isize; // in scope 0 at $DIR/recursive.rs:+6:9: +6:18 - let mut _11: isize; // in scope 0 at $DIR/recursive.rs:+7:13: +7:22 - let mut _13: isize; // in scope 0 at $DIR/recursive.rs:+8:17: +8:28 - let mut _15: !; // in scope 0 at $DIR/recursive.rs:+9:22: +9:43 - let mut _16: !; // in scope 0 at $DIR/recursive.rs:+11:18: +11:39 - let mut _17: !; // in scope 0 at $DIR/recursive.rs:+13:14: +13:35 - let mut _18: &S<'_>; // in scope 0 at $DIR/recursive.rs:+7:20: +7:21 - let mut _19: &S<'_>; // in scope 0 at $DIR/recursive.rs:+7:20: +7:21 - scope 1 { - debug a => _1; // in scope 1 at $DIR/recursive.rs:+2:9: +2:10 - let _2: S<'_>; // in scope 1 at $DIR/recursive.rs:+3:9: +3:10 - scope 2 { - debug b => _2; // in scope 2 at $DIR/recursive.rs:+3:9: +3:10 - let _5: S<'_>; // in scope 2 at $DIR/recursive.rs:+4:9: +4:10 - scope 3 { - debug c => _5; // in scope 3 at $DIR/recursive.rs:+4:9: +4:10 - let _8: u32; // in scope 3 at $DIR/recursive.rs:+5:9: +5:10 - let _10: &S<'_>; // in scope 3 at $DIR/recursive.rs:+6:16: +6:17 - scope 4 { - debug d => _8; // in scope 4 at $DIR/recursive.rs:+5:9: +5:10 - } - scope 5 { - debug b => _10; // in scope 5 at $DIR/recursive.rs:+6:16: +6:17 - let _12: &&S<'_>; // in scope 5 at $DIR/recursive.rs:+7:20: +7:21 - scope 6 { - debug a => _12; // in scope 6 at $DIR/recursive.rs:+7:20: +7:21 - let _14: &u32; // in scope 6 at $DIR/recursive.rs:+8:24: +8:27 - scope 7 { - debug num => _14; // in scope 7 at $DIR/recursive.rs:+8:24: +8:27 - } - } - } - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/recursive.rs:+2:9: +2:10 - Deinit(_1); // scope 0 at $DIR/recursive.rs:+2:13: +2:22 - ((_1 as Num).0: u32) = const 0_u32; // scope 0 at $DIR/recursive.rs:+2:13: +2:22 - discriminant(_1) = 1; // scope 0 at $DIR/recursive.rs:+2:13: +2:22 - StorageLive(_2); // scope 1 at $DIR/recursive.rs:+3:9: +3:10 - StorageLive(_3); // scope 1 at $DIR/recursive.rs:+3:20: +3:22 - StorageLive(_4); // scope 1 at $DIR/recursive.rs:+3:20: +3:22 - _4 = &_1; // scope 1 at $DIR/recursive.rs:+3:20: +3:22 - _3 = &(*_4); // scope 1 at $DIR/recursive.rs:+3:20: +3:22 - Deinit(_2); // scope 1 at $DIR/recursive.rs:+3:13: +3:23 - ((_2 as Rec).0: &S<'_>) = move _3; // scope 1 at $DIR/recursive.rs:+3:13: +3:23 - discriminant(_2) = 0; // scope 1 at $DIR/recursive.rs:+3:13: +3:23 - StorageDead(_3); // scope 1 at $DIR/recursive.rs:+3:22: +3:23 - StorageDead(_4); // scope 1 at $DIR/recursive.rs:+3:23: +3:24 - StorageLive(_5); // scope 2 at $DIR/recursive.rs:+4:9: +4:10 - StorageLive(_6); // scope 2 at $DIR/recursive.rs:+4:20: +4:22 - StorageLive(_7); // scope 2 at $DIR/recursive.rs:+4:20: +4:22 - _7 = &_2; // scope 2 at $DIR/recursive.rs:+4:20: +4:22 - _6 = &(*_7); // scope 2 at $DIR/recursive.rs:+4:20: +4:22 - Deinit(_5); // scope 2 at $DIR/recursive.rs:+4:13: +4:23 - ((_5 as Rec).0: &S<'_>) = move _6; // scope 2 at $DIR/recursive.rs:+4:13: +4:23 - discriminant(_5) = 0; // scope 2 at $DIR/recursive.rs:+4:13: +4:23 - StorageDead(_6); // scope 2 at $DIR/recursive.rs:+4:22: +4:23 - StorageDead(_7); // scope 2 at $DIR/recursive.rs:+4:23: +4:24 - StorageLive(_8); // scope 3 at $DIR/recursive.rs:+5:9: +5:10 - _9 = discriminant(_5); // scope 3 at $DIR/recursive.rs:+5:19: +5:20 - switchInt(move _9) -> [0_isize: bb2, otherwise: bb1]; // scope 3 at $DIR/recursive.rs:+5:13: +5:20 - } - - bb1: { - StorageLive(_17); // scope 3 at $DIR/recursive.rs:+13:14: +13:35 - _17 = exit(const 0_i32); // scope 3 at $DIR/recursive.rs:+13:14: +13:35 - // mir::Constant - // + span: $DIR/recursive.rs:22:14: 22:32 - // + literal: Const { ty: fn(i32) -> ! {exit}, val: Value() } - } - - bb2: { - StorageLive(_10); // scope 3 at $DIR/recursive.rs:+6:16: +6:17 - _10 = ((_5 as Rec).0: &S<'_>); // scope 3 at $DIR/recursive.rs:+6:16: +6:17 - _11 = discriminant((*_10)); // scope 5 at $DIR/recursive.rs:+6:28: +6:29 - switchInt(move _11) -> [0_isize: bb4, otherwise: bb3]; // scope 5 at $DIR/recursive.rs:+6:22: +6:29 - } - - bb3: { - StorageLive(_16); // scope 5 at $DIR/recursive.rs:+11:18: +11:39 - _16 = exit(const 0_i32); // scope 5 at $DIR/recursive.rs:+11:18: +11:39 - // mir::Constant - // + span: $DIR/recursive.rs:20:18: 20:36 - // + literal: Const { ty: fn(i32) -> ! {exit}, val: Value() } - } - - bb4: { - StorageLive(_12); // scope 5 at $DIR/recursive.rs:+7:20: +7:21 - _12 = &(((*_10) as Rec).0: &S<'_>); // scope 5 at $DIR/recursive.rs:+7:20: +7:21 - _18 = deref_copy (*_12); // scope 6 at $DIR/recursive.rs:+7:32: +7:33 - _13 = discriminant((*_18)); // scope 6 at $DIR/recursive.rs:+7:32: +7:33 - switchInt(move _13) -> [1_isize: bb6, otherwise: bb5]; // scope 6 at $DIR/recursive.rs:+7:26: +7:33 - } - - bb5: { - StorageLive(_15); // scope 6 at $DIR/recursive.rs:+9:22: +9:43 - _15 = exit(const 0_i32); // scope 6 at $DIR/recursive.rs:+9:22: +9:43 - // mir::Constant - // + span: $DIR/recursive.rs:18:22: 18:40 - // + literal: Const { ty: fn(i32) -> ! {exit}, val: Value() } - } - - bb6: { - StorageLive(_14); // scope 6 at $DIR/recursive.rs:+8:24: +8:27 - _19 = deref_copy (*_12); // scope 6 at $DIR/recursive.rs:+8:24: +8:27 - _14 = &(((*_19) as Num).0: u32); // scope 6 at $DIR/recursive.rs:+8:24: +8:27 - _8 = (*_14); // scope 7 at $DIR/recursive.rs:+8:32: +8:36 - StorageDead(_14); // scope 6 at $DIR/recursive.rs:+8:35: +8:36 - StorageDead(_12); // scope 5 at $DIR/recursive.rs:+10:13: +10:14 - StorageDead(_10); // scope 3 at $DIR/recursive.rs:+12:9: +12:10 - _0 = const (); // scope 0 at $DIR/recursive.rs:+0:11: +15:2 - StorageDead(_8); // scope 3 at $DIR/recursive.rs:+15:1: +15:2 - StorageDead(_5); // scope 2 at $DIR/recursive.rs:+15:1: +15:2 - StorageDead(_2); // scope 1 at $DIR/recursive.rs:+15:1: +15:2 - StorageDead(_1); // scope 0 at $DIR/recursive.rs:+15:1: +15:2 - return; // scope 0 at $DIR/recursive.rs:+15:2: +15:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/recursive.rs b/src/test/mir-opt/dataflow-const-prop/recursive.rs deleted file mode 100644 index d7ca182b9fcfa..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/recursive.rs +++ /dev/null @@ -1,24 +0,0 @@ -// unit-test: DataflowConstProp - -enum S<'a> { - Rec(&'a S<'a>), - Num(u32), -} - -// EMIT_MIR recursive.main.DataflowConstProp.diff -fn main() { - // FIXME: This currently does not work, because downcasts are rejected. - let a = S::Num(0); - let b = S::Rec(&a); - let c = S::Rec(&b); - let d = match c { - S::Rec(b) => match b { - S::Rec(a) => match a { - S::Num(num) => *num, - _ => std::process::exit(0), - }, - _ => std::process::exit(0), - }, - _ => std::process::exit(0), - }; -} diff --git a/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff index 6d55092747a5a..746082eee531a 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff @@ -54,7 +54,7 @@ StorageLive(_8); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 _11 = const _; // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 // mir::Constant - // + span: $DIR/ref_mut.rs:13:10: 13:12 + // + span: $DIR/ref_mut.rs:14:10: 14:12 // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } _8 = &(*_11); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 _7 = &(*_8); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 diff --git a/src/test/mir-opt/dataflow-const-prop/ref_mut.rs b/src/test/mir-opt/dataflow-const-prop/ref_mut.rs index 8b2baf7676df9..5728343951690 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref_mut.rs +++ b/src/test/mir-opt/dataflow-const-prop/ref_mut.rs @@ -1,4 +1,5 @@ // unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts // EMIT_MIR ref_mut.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..dd1242d7cac02 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff @@ -0,0 +1,52 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/self_assign.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/self_assign.rs:+1:9: +1:14 + let mut _2: i32; // in scope 0 at $DIR/self_assign.rs:+2:9: +2:10 + let mut _3: i32; // in scope 0 at $DIR/self_assign.rs:+3:9: +3:10 + let mut _5: &i32; // in scope 0 at $DIR/self_assign.rs:+6:9: +6:10 + let mut _6: i32; // in scope 0 at $DIR/self_assign.rs:+7:9: +7:11 + scope 1 { + debug a => _1; // in scope 1 at $DIR/self_assign.rs:+1:9: +1:14 + let mut _4: &i32; // in scope 1 at $DIR/self_assign.rs:+5:9: +5:14 + scope 2 { + debug b => _4; // in scope 2 at $DIR/self_assign.rs:+5:9: +5:14 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/self_assign.rs:+1:9: +1:14 + _1 = const 0_i32; // scope 0 at $DIR/self_assign.rs:+1:17: +1:18 + StorageLive(_2); // scope 1 at $DIR/self_assign.rs:+2:9: +2:10 +- _2 = _1; // scope 1 at $DIR/self_assign.rs:+2:9: +2:10 +- _1 = Add(move _2, const 1_i32); // scope 1 at $DIR/self_assign.rs:+2:5: +2:14 ++ _2 = const 0_i32; // scope 1 at $DIR/self_assign.rs:+2:9: +2:10 ++ _1 = const 1_i32; // scope 1 at $DIR/self_assign.rs:+2:5: +2:14 + StorageDead(_2); // scope 1 at $DIR/self_assign.rs:+2:13: +2:14 + StorageLive(_3); // scope 1 at $DIR/self_assign.rs:+3:9: +3:10 +- _3 = _1; // scope 1 at $DIR/self_assign.rs:+3:9: +3:10 +- _1 = move _3; // scope 1 at $DIR/self_assign.rs:+3:5: +3:10 ++ _3 = const 1_i32; // scope 1 at $DIR/self_assign.rs:+3:9: +3:10 ++ _1 = const 1_i32; // scope 1 at $DIR/self_assign.rs:+3:5: +3:10 + StorageDead(_3); // scope 1 at $DIR/self_assign.rs:+3:9: +3:10 + StorageLive(_4); // scope 1 at $DIR/self_assign.rs:+5:9: +5:14 + _4 = &_1; // scope 1 at $DIR/self_assign.rs:+5:17: +5:19 + StorageLive(_5); // scope 2 at $DIR/self_assign.rs:+6:9: +6:10 + _5 = _4; // scope 2 at $DIR/self_assign.rs:+6:9: +6:10 + _4 = move _5; // scope 2 at $DIR/self_assign.rs:+6:5: +6:10 + StorageDead(_5); // scope 2 at $DIR/self_assign.rs:+6:9: +6:10 + StorageLive(_6); // scope 2 at $DIR/self_assign.rs:+7:9: +7:11 +- _6 = (*_4); // scope 2 at $DIR/self_assign.rs:+7:9: +7:11 +- _1 = move _6; // scope 2 at $DIR/self_assign.rs:+7:5: +7:11 ++ _6 = const 1_i32; // scope 2 at $DIR/self_assign.rs:+7:9: +7:11 ++ _1 = const 1_i32; // scope 2 at $DIR/self_assign.rs:+7:5: +7:11 + StorageDead(_6); // scope 2 at $DIR/self_assign.rs:+7:10: +7:11 + _0 = const (); // scope 0 at $DIR/self_assign.rs:+0:11: +8:2 + StorageDead(_4); // scope 1 at $DIR/self_assign.rs:+8:1: +8:2 + StorageDead(_1); // scope 0 at $DIR/self_assign.rs:+8:1: +8:2 + return; // scope 0 at $DIR/self_assign.rs:+8:2: +8:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/self_assign.rs b/src/test/mir-opt/dataflow-const-prop/self_assign.rs new file mode 100644 index 0000000000000..e8a62a8396043 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/self_assign.rs @@ -0,0 +1,13 @@ +// unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts + +// EMIT_MIR self_assign.main.DataflowConstProp.diff +fn main() { + let mut a = 0; + a = a + 1; + a = a; + + let mut b = &a; + b = b; + a = *b; +} diff --git a/src/test/mir-opt/dataflow-const-prop/self_assign_add.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/self_assign_add.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..c09e4061ededf --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/self_assign_add.main.DataflowConstProp.diff @@ -0,0 +1,23 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/self_assign_add.rs:+0:11: +0:11 + let mut _1: i32; // in scope 0 at $DIR/self_assign_add.rs:+1:9: +1:14 + scope 1 { + debug a => _1; // in scope 1 at $DIR/self_assign_add.rs:+1:9: +1:14 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/self_assign_add.rs:+1:9: +1:14 + _1 = const 0_i32; // scope 0 at $DIR/self_assign_add.rs:+1:17: +1:18 +- _1 = Add(_1, const 1_i32); // scope 1 at $DIR/self_assign_add.rs:+2:5: +2:11 +- _1 = Add(_1, const 1_i32); // scope 1 at $DIR/self_assign_add.rs:+3:5: +3:11 ++ _1 = const 1_i32; // scope 1 at $DIR/self_assign_add.rs:+2:5: +2:11 ++ _1 = const 2_i32; // scope 1 at $DIR/self_assign_add.rs:+3:5: +3:11 + _0 = const (); // scope 0 at $DIR/self_assign_add.rs:+0:11: +4:2 + StorageDead(_1); // scope 0 at $DIR/self_assign_add.rs:+4:1: +4:2 + return; // scope 0 at $DIR/self_assign_add.rs:+4:2: +4:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/self_assign_add.rs b/src/test/mir-opt/dataflow-const-prop/self_assign_add.rs new file mode 100644 index 0000000000000..be2a4f04f6288 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/self_assign_add.rs @@ -0,0 +1,9 @@ +// unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts + +// EMIT_MIR self_assign_add.main.DataflowConstProp.diff +fn main() { + let mut a = 0; + a += 1; + a += 1; +} diff --git a/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff index 46386ca34d559..2d0d70b6a7428 100644 --- a/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff @@ -3,47 +3,47 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/static_ref.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/static_ref.rs:+2:9: +2:10 - let mut _3: &i32; // in scope 0 at $DIR/static_ref.rs:+4:9: +4:11 - let _4: &i32; // in scope 0 at $DIR/static_ref.rs:+4:9: +4:11 - let _5: &i32; // in scope 0 at $DIR/static_ref.rs:+4:10: +4:11 + let _1: i32; // in scope 0 at $DIR/static_ref.rs:+3:9: +3:10 + let mut _3: &i32; // in scope 0 at $DIR/static_ref.rs:+5:9: +5:11 + let _4: &i32; // in scope 0 at $DIR/static_ref.rs:+5:9: +5:11 + let _5: &i32; // in scope 0 at $DIR/static_ref.rs:+5:10: +5:11 scope 1 { - debug x => _1; // in scope 1 at $DIR/static_ref.rs:+2:9: +2:10 - let mut _2: &i32; // in scope 1 at $DIR/static_ref.rs:+3:9: +3:14 + debug x => _1; // in scope 1 at $DIR/static_ref.rs:+3:9: +3:10 + let mut _2: &i32; // in scope 1 at $DIR/static_ref.rs:+4:9: +4:14 scope 2 { - debug r => _2; // in scope 2 at $DIR/static_ref.rs:+3:9: +3:14 - let _6: i32; // in scope 2 at $DIR/static_ref.rs:+5:9: +5:10 + debug r => _2; // in scope 2 at $DIR/static_ref.rs:+4:9: +4:14 + let _6: i32; // in scope 2 at $DIR/static_ref.rs:+6:9: +6:10 scope 3 { - debug y => _6; // in scope 3 at $DIR/static_ref.rs:+5:9: +5:10 + debug y => _6; // in scope 3 at $DIR/static_ref.rs:+6:9: +6:10 } } } bb0: { - StorageLive(_1); // scope 0 at $DIR/static_ref.rs:+2:9: +2:10 - _1 = const 0_i32; // scope 0 at $DIR/static_ref.rs:+2:13: +2:14 - StorageLive(_2); // scope 1 at $DIR/static_ref.rs:+3:9: +3:14 - _2 = &_1; // scope 1 at $DIR/static_ref.rs:+3:17: +3:19 - StorageLive(_3); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 - StorageLive(_4); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 - StorageLive(_5); // scope 2 at $DIR/static_ref.rs:+4:10: +4:11 - _5 = const {alloc1: &i32}; // scope 2 at $DIR/static_ref.rs:+4:10: +4:11 + StorageLive(_1); // scope 0 at $DIR/static_ref.rs:+3:9: +3:10 + _1 = const 0_i32; // scope 0 at $DIR/static_ref.rs:+3:13: +3:14 + StorageLive(_2); // scope 1 at $DIR/static_ref.rs:+4:9: +4:14 + _2 = &_1; // scope 1 at $DIR/static_ref.rs:+4:17: +4:19 + StorageLive(_3); // scope 2 at $DIR/static_ref.rs:+5:9: +5:11 + StorageLive(_4); // scope 2 at $DIR/static_ref.rs:+5:9: +5:11 + StorageLive(_5); // scope 2 at $DIR/static_ref.rs:+5:10: +5:11 + _5 = const {alloc1: &i32}; // scope 2 at $DIR/static_ref.rs:+5:10: +5:11 // mir::Constant - // + span: $DIR/static_ref.rs:8:10: 8:11 + // + span: $DIR/static_ref.rs:10:10: 10:11 // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } - _4 = &(*_5); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 - _3 = &(*_4); // scope 2 at $DIR/static_ref.rs:+4:9: +4:11 - _2 = move _3; // scope 2 at $DIR/static_ref.rs:+4:5: +4:11 - StorageDead(_3); // scope 2 at $DIR/static_ref.rs:+4:10: +4:11 - StorageDead(_5); // scope 2 at $DIR/static_ref.rs:+4:11: +4:12 - StorageDead(_4); // scope 2 at $DIR/static_ref.rs:+4:11: +4:12 - StorageLive(_6); // scope 2 at $DIR/static_ref.rs:+5:9: +5:10 - _6 = (*_2); // scope 2 at $DIR/static_ref.rs:+5:13: +5:15 - _0 = const (); // scope 0 at $DIR/static_ref.rs:+0:11: +6:2 - StorageDead(_6); // scope 2 at $DIR/static_ref.rs:+6:1: +6:2 - StorageDead(_2); // scope 1 at $DIR/static_ref.rs:+6:1: +6:2 - StorageDead(_1); // scope 0 at $DIR/static_ref.rs:+6:1: +6:2 - return; // scope 0 at $DIR/static_ref.rs:+6:2: +6:2 + _4 = &(*_5); // scope 2 at $DIR/static_ref.rs:+5:9: +5:11 + _3 = &(*_4); // scope 2 at $DIR/static_ref.rs:+5:9: +5:11 + _2 = move _3; // scope 2 at $DIR/static_ref.rs:+5:5: +5:11 + StorageDead(_3); // scope 2 at $DIR/static_ref.rs:+5:10: +5:11 + StorageDead(_5); // scope 2 at $DIR/static_ref.rs:+5:11: +5:12 + StorageDead(_4); // scope 2 at $DIR/static_ref.rs:+5:11: +5:12 + StorageLive(_6); // scope 2 at $DIR/static_ref.rs:+6:9: +6:10 + _6 = (*_2); // scope 2 at $DIR/static_ref.rs:+6:13: +6:15 + _0 = const (); // scope 0 at $DIR/static_ref.rs:+0:11: +7:2 + StorageDead(_6); // scope 2 at $DIR/static_ref.rs:+7:1: +7:2 + StorageDead(_2); // scope 1 at $DIR/static_ref.rs:+7:1: +7:2 + StorageDead(_1); // scope 0 at $DIR/static_ref.rs:+7:1: +7:2 + return; // scope 0 at $DIR/static_ref.rs:+7:2: +7:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/static_ref.rs b/src/test/mir-opt/dataflow-const-prop/static_ref.rs index 5e60ab1805ba6..90f20ae51ceb9 100644 --- a/src/test/mir-opt/dataflow-const-prop/static_ref.rs +++ b/src/test/mir-opt/dataflow-const-prop/static_ref.rs @@ -1,7 +1,9 @@ // unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts // EMIT_MIR static_ref.main.DataflowConstProp.diff fn main() { + // Currently, this will not propagate. static P: i32 = 5; let x = 0; let mut r = &x; diff --git a/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff index 1d01d4fd2e775..d1b8895901eaa 100644 --- a/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff @@ -25,7 +25,7 @@ - _2 = foo(move _3) -> bb1; // scope 1 at $DIR/terminator.rs:+2:5: +2:15 + _2 = foo(const 2_i32) -> bb1; // scope 1 at $DIR/terminator.rs:+2:5: +2:15 // mir::Constant - // + span: $DIR/terminator.rs:8:5: 8:8 + // + span: $DIR/terminator.rs:9:5: 9:8 // + literal: Const { ty: fn(i32) {foo}, val: Value() } } diff --git a/src/test/mir-opt/dataflow-const-prop/terminator.rs b/src/test/mir-opt/dataflow-const-prop/terminator.rs index e96b25de63ccc..7d8bb58f684eb 100644 --- a/src/test/mir-opt/dataflow-const-prop/terminator.rs +++ b/src/test/mir-opt/dataflow-const-prop/terminator.rs @@ -1,4 +1,5 @@ // unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts fn foo(n: i32) {} diff --git a/src/test/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..7fb1c8b7cafb6 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff @@ -0,0 +1,86 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/tuple.rs:+0:11: +0:11 + let mut _1: (i32, i32); // in scope 0 at $DIR/tuple.rs:+1:9: +1:14 + let mut _4: i32; // in scope 0 at $DIR/tuple.rs:+3:13: +3:22 + let mut _5: i32; // in scope 0 at $DIR/tuple.rs:+3:13: +3:16 + let mut _6: i32; // in scope 0 at $DIR/tuple.rs:+3:19: +3:22 + let mut _7: &(i32, i32); // in scope 0 at $DIR/tuple.rs:+5:9: +5:11 + let _8: &(i32, i32); // in scope 0 at $DIR/tuple.rs:+5:9: +5:11 + let mut _10: i32; // in scope 0 at $DIR/tuple.rs:+6:13: +6:22 + let mut _11: i32; // in scope 0 at $DIR/tuple.rs:+6:13: +6:16 + let mut _12: i32; // in scope 0 at $DIR/tuple.rs:+6:19: +6:22 + scope 1 { + debug a => _1; // in scope 1 at $DIR/tuple.rs:+1:9: +1:14 + let mut _2: &(i32, i32); // in scope 1 at $DIR/tuple.rs:+2:9: +2:14 + scope 2 { + debug b => _2; // in scope 2 at $DIR/tuple.rs:+2:9: +2:14 + let _3: i32; // in scope 2 at $DIR/tuple.rs:+3:9: +3:10 + scope 3 { + debug c => _3; // in scope 3 at $DIR/tuple.rs:+3:9: +3:10 + let _9: i32; // in scope 3 at $DIR/tuple.rs:+6:9: +6:10 + scope 4 { + debug d => _9; // in scope 4 at $DIR/tuple.rs:+6:9: +6:10 + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/tuple.rs:+1:9: +1:14 + Deinit(_1); // scope 0 at $DIR/tuple.rs:+1:17: +1:23 + (_1.0: i32) = const 1_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23 + (_1.1: i32) = const 2_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23 + StorageLive(_2); // scope 1 at $DIR/tuple.rs:+2:9: +2:14 + _2 = &_1; // scope 1 at $DIR/tuple.rs:+2:17: +2:19 + StorageLive(_3); // scope 2 at $DIR/tuple.rs:+3:9: +3:10 + StorageLive(_4); // scope 2 at $DIR/tuple.rs:+3:13: +3:22 + StorageLive(_5); // scope 2 at $DIR/tuple.rs:+3:13: +3:16 +- _5 = (_1.0: i32); // scope 2 at $DIR/tuple.rs:+3:13: +3:16 ++ _5 = const 1_i32; // scope 2 at $DIR/tuple.rs:+3:13: +3:16 + StorageLive(_6); // scope 2 at $DIR/tuple.rs:+3:19: +3:22 +- _6 = ((*_2).1: i32); // scope 2 at $DIR/tuple.rs:+3:19: +3:22 +- _4 = Add(move _5, move _6); // scope 2 at $DIR/tuple.rs:+3:13: +3:22 ++ _6 = const 2_i32; // scope 2 at $DIR/tuple.rs:+3:19: +3:22 ++ _4 = const 3_i32; // scope 2 at $DIR/tuple.rs:+3:13: +3:22 + StorageDead(_6); // scope 2 at $DIR/tuple.rs:+3:21: +3:22 + StorageDead(_5); // scope 2 at $DIR/tuple.rs:+3:21: +3:22 +- _3 = Add(move _4, const 3_i32); // scope 2 at $DIR/tuple.rs:+3:13: +3:26 ++ _3 = const 6_i32; // scope 2 at $DIR/tuple.rs:+3:13: +3:26 + StorageDead(_4); // scope 2 at $DIR/tuple.rs:+3:25: +3:26 + Deinit(_1); // scope 3 at $DIR/tuple.rs:+4:5: +4:15 + (_1.0: i32) = const 2_i32; // scope 3 at $DIR/tuple.rs:+4:5: +4:15 + (_1.1: i32) = const 3_i32; // scope 3 at $DIR/tuple.rs:+4:5: +4:15 + StorageLive(_7); // scope 3 at $DIR/tuple.rs:+5:9: +5:11 + StorageLive(_8); // scope 3 at $DIR/tuple.rs:+5:9: +5:11 + _8 = &_1; // scope 3 at $DIR/tuple.rs:+5:9: +5:11 + _7 = &(*_8); // scope 3 at $DIR/tuple.rs:+5:9: +5:11 + _2 = move _7; // scope 3 at $DIR/tuple.rs:+5:5: +5:11 + StorageDead(_7); // scope 3 at $DIR/tuple.rs:+5:10: +5:11 + StorageDead(_8); // scope 3 at $DIR/tuple.rs:+5:11: +5:12 + StorageLive(_9); // scope 3 at $DIR/tuple.rs:+6:9: +6:10 + StorageLive(_10); // scope 3 at $DIR/tuple.rs:+6:13: +6:22 + StorageLive(_11); // scope 3 at $DIR/tuple.rs:+6:13: +6:16 +- _11 = (_1.0: i32); // scope 3 at $DIR/tuple.rs:+6:13: +6:16 ++ _11 = const 2_i32; // scope 3 at $DIR/tuple.rs:+6:13: +6:16 + StorageLive(_12); // scope 3 at $DIR/tuple.rs:+6:19: +6:22 +- _12 = ((*_2).1: i32); // scope 3 at $DIR/tuple.rs:+6:19: +6:22 +- _10 = Add(move _11, move _12); // scope 3 at $DIR/tuple.rs:+6:13: +6:22 ++ _12 = const 3_i32; // scope 3 at $DIR/tuple.rs:+6:19: +6:22 ++ _10 = const 5_i32; // scope 3 at $DIR/tuple.rs:+6:13: +6:22 + StorageDead(_12); // scope 3 at $DIR/tuple.rs:+6:21: +6:22 + StorageDead(_11); // scope 3 at $DIR/tuple.rs:+6:21: +6:22 +- _9 = Add(move _10, const 4_i32); // scope 3 at $DIR/tuple.rs:+6:13: +6:26 ++ _9 = const 9_i32; // scope 3 at $DIR/tuple.rs:+6:13: +6:26 + StorageDead(_10); // scope 3 at $DIR/tuple.rs:+6:25: +6:26 + _0 = const (); // scope 0 at $DIR/tuple.rs:+0:11: +7:2 + StorageDead(_9); // scope 3 at $DIR/tuple.rs:+7:1: +7:2 + StorageDead(_3); // scope 2 at $DIR/tuple.rs:+7:1: +7:2 + StorageDead(_2); // scope 1 at $DIR/tuple.rs:+7:1: +7:2 + StorageDead(_1); // scope 0 at $DIR/tuple.rs:+7:1: +7:2 + return; // scope 0 at $DIR/tuple.rs:+7:2: +7:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/tuple.rs b/src/test/mir-opt/dataflow-const-prop/tuple.rs new file mode 100644 index 0000000000000..dfc49fe857ab0 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/tuple.rs @@ -0,0 +1,12 @@ +// unit-test: DataflowConstProp +// compile-flags: -Zunsound-mir-opts + +// EMIT_MIR tuple.main.DataflowConstProp.diff +fn main() { + let mut a = (1, 2); + let mut b = &a; + let c = a.0 + b.1 + 3; + a = (2, 3); + b = &a; + let d = a.0 + b.1 + 4; +} diff --git a/src/test/mir-opt/dataflow-const-prop/unnamed.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/unnamed.main.DataflowConstProp.diff deleted file mode 100644 index 684c661fc1185..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/unnamed.main.DataflowConstProp.diff +++ /dev/null @@ -1,38 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/unnamed.rs:+0:11: +0:11 - let mut _1: i32; // in scope 0 at $DIR/unnamed.rs:+1:9: +1:14 - let mut _2: i32; // in scope 0 at $DIR/unnamed.rs:+3:10: +3:11 - let mut _3: &i32; // in scope 0 at $DIR/unnamed.rs:+3:10: +3:11 - scope 1 { - debug a => _1; // in scope 1 at $DIR/unnamed.rs:+1:9: +1:14 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/unnamed.rs:+1:9: +1:14 - _1 = const 0_i32; // scope 0 at $DIR/unnamed.rs:+1:17: +1:18 -- _1 = Add(_1, const 1_i32); // scope 1 at $DIR/unnamed.rs:+2:5: +2:11 -+ _1 = const 1_i32; // scope 1 at $DIR/unnamed.rs:+2:5: +2:11 - StorageLive(_2); // scope 1 at $DIR/unnamed.rs:+3:10: +3:11 - StorageLive(_3); // scope 1 at $DIR/unnamed.rs:+3:10: +3:11 - _3 = const {alloc1: &i32}; // scope 1 at $DIR/unnamed.rs:+3:10: +3:11 - // mir::Constant - // + span: $DIR/unnamed.rs:9:10: 9:11 - // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } - _2 = (*_3); // scope 1 at $DIR/unnamed.rs:+3:10: +3:11 -- _1 = Add(_1, move _2); // scope 1 at $DIR/unnamed.rs:+3:5: +3:11 -+ _1 = Add(const 1_i32, move _2); // scope 1 at $DIR/unnamed.rs:+3:5: +3:11 - StorageDead(_2); // scope 1 at $DIR/unnamed.rs:+3:10: +3:11 - StorageDead(_3); // scope 1 at $DIR/unnamed.rs:+3:11: +3:12 - _0 = const (); // scope 0 at $DIR/unnamed.rs:+0:11: +4:2 - StorageDead(_1); // scope 0 at $DIR/unnamed.rs:+4:1: +4:2 - return; // scope 0 at $DIR/unnamed.rs:+4:2: +4:2 - } - } - - alloc1 (static: g, size: 4, align: 4) { - 02 00 00 00 │ .... - } - diff --git a/src/test/mir-opt/dataflow-const-prop/unnamed.rs b/src/test/mir-opt/dataflow-const-prop/unnamed.rs deleted file mode 100644 index 91f5a9e1c12d1..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/unnamed.rs +++ /dev/null @@ -1,10 +0,0 @@ -// unit-test: DataflowConstProp - -static g: i32 = 2; - -// EMIT_MIR unnamed.main.DataflowConstProp.diff -fn main() { - let mut a = 0; - a += 1; - a += g; -} From 630e17d3e41dbe338b209effb6091471314798c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Tue, 25 Oct 2022 21:54:39 +0200 Subject: [PATCH 59/76] Limit number of tracked places, and some other perf improvements --- .../rustc_mir_dataflow/src/value_analysis.rs | 57 +++++++++++++++---- .../src/dataflow_const_prop.rs | 23 +++++++- 2 files changed, 66 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index a3194ebc30cfc..8e0fc77ec9990 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -47,7 +47,7 @@ use std::fmt::{Debug, Formatter}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::vec::IndexVec; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{PlaceContext, Visitor}; @@ -405,12 +405,31 @@ rustc_index::newtype_index!( ); /// See [`State`]. -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(PartialEq, Eq, Debug)] enum StateData { Reachable(IndexVec), Unreachable, } +impl Clone for StateData { + fn clone(&self) -> Self { + match self { + Self::Reachable(x) => Self::Reachable(x.clone()), + Self::Unreachable => Self::Unreachable, + } + } + + fn clone_from(&mut self, source: &Self) { + match (&mut *self, source) { + (Self::Reachable(x), Self::Reachable(y)) => { + // We go through `raw` here, because `IndexVec` currently has a naive `clone_from`. + x.raw.clone_from(&y.raw); + } + _ => *self = source.clone(), + } + } +} + /// The dataflow state for an instance of [`ValueAnalysis`]. /// /// Every instance specifies a lattice that represents the possible values of a single tracked @@ -421,9 +440,19 @@ enum StateData { /// reachable state). All operations on unreachable states are ignored. /// /// Flooding means assigning a value (by default `⊤`) to all tracked projections of a given place. -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(PartialEq, Eq, Debug)] pub struct State(StateData); +impl Clone for State { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + + fn clone_from(&mut self, source: &Self) { + self.0.clone_from(&source.0); + } +} + impl State { pub fn is_reachable(&self) -> bool { matches!(&self.0, StateData::Reachable(_)) @@ -590,6 +619,7 @@ impl Map { /// /// This is currently the only way to create a [`Map`]. The way in which the tracked places are /// chosen is an implementation detail and may not be relied upon. + #[instrument(skip_all, level = "debug")] pub fn from_filter<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -604,11 +634,12 @@ impl Map { if tcx.sess.opts.unstable_opts.unsound_mir_opts { // We might want to add additional limitations. If a struct has 10 boxed fields of // itself, there will currently be `10.pow(max_derefs)` tracked places. - map.register_with_filter(tcx, body, 2, filter, &[]); + map.register_with_filter(tcx, body, 2, filter, &FxHashSet::default()); } else { map.register_with_filter(tcx, body, 0, filter, &escaped_places(body)); } + debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len()); map } @@ -619,7 +650,7 @@ impl Map { body: &Body<'tcx>, max_derefs: u32, mut filter: impl FnMut(Ty<'tcx>) -> bool, - exclude: &[Place<'tcx>], + exclude: &FxHashSet>, ) { // This is used to tell whether a type is `!Freeze`. let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); @@ -648,10 +679,10 @@ impl Map { ty: Ty<'tcx>, filter: &mut impl FnMut(Ty<'tcx>) -> bool, param_env: ty::ParamEnv<'tcx>, - exclude: &[Place<'tcx>], + exclude: &FxHashSet>, ) { - // This currently does a linear scan, could be improved. if exclude.contains(&Place { local, projection: tcx.intern_place_elems(projection) }) { + // This will also exclude all projections of the excluded place. return; } @@ -764,6 +795,10 @@ impl Map { Ok(()) } + pub fn tracked_places(&self) -> usize { + self.value_count + } + pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option { self.projections.get(&(place, elem)).copied() } @@ -929,20 +964,20 @@ fn iter_fields<'tcx>( /// Returns all places, that have their reference or address taken. /// /// This includes shared references. -fn escaped_places<'tcx>(body: &Body<'tcx>) -> Vec> { +fn escaped_places<'tcx>(body: &Body<'tcx>) -> FxHashSet> { struct Collector<'tcx> { - result: Vec>, + result: FxHashSet>, } impl<'tcx> Visitor<'tcx> for Collector<'tcx> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { if context.is_borrow() || context.is_address_of() { - self.result.push(*place); + self.result.insert(*place); } } } - let mut collector = Collector { result: Vec::new() }; + let mut collector = Collector { result: FxHashSet::default() }; collector.visit_body(body); collector.result } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 93f7ddbee798e..1eeebfabba7c7 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -15,6 +15,8 @@ use rustc_span::DUMMY_SP; use crate::MirPass; +const TRACKING_LIMIT: usize = 1000; + pub struct DataflowConstProp; impl<'tcx> MirPass<'tcx> for DataflowConstProp { @@ -22,18 +24,33 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp { sess.mir_opt_level() >= 1 } + #[instrument(skip_all level = "debug")] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Decide which places to track during the analysis. let map = Map::from_filter(tcx, body, Ty::is_scalar); + // We want to have a somewhat linear runtime w.r.t. the number of statements/terminators. + // Let's call this number `n`. Dataflow analysis has `O(h*n)` transfer function + // applications, where `h` is the height of the lattice. Because the height of our lattice + // is linear w.r.t. the number of tracked places, this is `O(tracked_places * n)`. However, + // because every transfer function application could traverse the whole map, this becomes + // `O(num_nodes * tracked_places * n)` in terms of time complexity. Since the number of + // map nodes is strongly correlated to the number of tracked places, this becomes more or + // less `O(n)` if we place a constant limit on the number of tracked places. + if map.tracked_places() > TRACKING_LIMIT { + debug!("aborted dataflow const prop due to too many tracked places"); + return; + } + // Perform the actual dataflow analysis. let analysis = ConstAnalysis::new(tcx, body, map); - let results = analysis.wrap().into_engine(tcx, body).iterate_to_fixpoint(); + let results = debug_span!("analyze") + .in_scope(|| analysis.wrap().into_engine(tcx, body).iterate_to_fixpoint()); // Collect results and patch the body afterwards. let mut visitor = CollectAndPatch::new(tcx, &results.analysis.0.map); - results.visit_reachable_with(body, &mut visitor); - visitor.visit_body(body); + debug_span!("collect").in_scope(|| results.visit_reachable_with(body, &mut visitor)); + debug_span!("patch").in_scope(|| visitor.visit_body(body)); } } From b478fcf2705dee1ee0a03461c0dd3856760c42eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 26 Oct 2022 14:46:27 +0200 Subject: [PATCH 60/76] Use new cast methods --- .../src/dataflow_const_prop.rs | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 1eeebfabba7c7..acb0f7b95abc8 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -128,23 +128,26 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { ) -> ValueOrPlaceOrRef { match rvalue { Rvalue::Cast( - CastKind::IntToInt + kind @ (CastKind::IntToInt | CastKind::FloatToInt | CastKind::FloatToFloat - | CastKind::IntToFloat, + | CastKind::IntToFloat), operand, ty, - ) => { - let operand = self.eval_operand(operand, state); - match operand { - FlatSet::Elem(operand) => self - .ecx - .misc_cast(&operand, *ty) - .map(|result| ValueOrPlaceOrRef::Value(self.wrap_immediate(result, *ty))) - .unwrap_or(ValueOrPlaceOrRef::top()), - _ => ValueOrPlaceOrRef::top(), + ) => match self.eval_operand(operand, state) { + FlatSet::Elem(op) => match kind { + CastKind::IntToInt | CastKind::IntToFloat => { + self.ecx.int_to_int_or_float(&op, *ty) + } + CastKind::FloatToInt | CastKind::FloatToFloat => { + self.ecx.float_to_float_or_int(&op, *ty) + } + _ => unreachable!(), } - } + .map(|result| ValueOrPlaceOrRef::Value(self.wrap_immediate(result, *ty))) + .unwrap_or(ValueOrPlaceOrRef::top()), + _ => ValueOrPlaceOrRef::top(), + }, Rvalue::BinaryOp(op, box (left, right)) => { // Overflows must be ignored here. let (val, _overflow) = self.binary_op(state, *op, left, right); From 72196ee6661a38cb640d66c2a8d9941f9d6c6bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Thu, 27 Oct 2022 16:50:39 +0200 Subject: [PATCH 61/76] Limit number of basic blocks and tracked places to 100 for now --- .../rustc_mir_transform/src/dataflow_const_prop.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index acb0f7b95abc8..001b83ccda236 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -15,7 +15,8 @@ use rustc_span::DUMMY_SP; use crate::MirPass; -const TRACKING_LIMIT: usize = 1000; +const BLOCK_LIMIT: usize = 100; +const PLACE_LIMIT: usize = 100; pub struct DataflowConstProp; @@ -26,6 +27,11 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp { #[instrument(skip_all level = "debug")] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + if body.basic_blocks.len() > BLOCK_LIMIT { + debug!("aborted dataflow const prop due too many basic blocks"); + return; + } + // Decide which places to track during the analysis. let map = Map::from_filter(tcx, body, Ty::is_scalar); @@ -37,7 +43,7 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp { // `O(num_nodes * tracked_places * n)` in terms of time complexity. Since the number of // map nodes is strongly correlated to the number of tracked places, this becomes more or // less `O(n)` if we place a constant limit on the number of tracked places. - if map.tracked_places() > TRACKING_LIMIT { + if map.tracked_places() > PLACE_LIMIT { debug!("aborted dataflow const prop due to too many tracked places"); return; } From 89f934917da364d1b9e32dc57a085014a6465bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Mon, 7 Nov 2022 10:33:28 +0100 Subject: [PATCH 62/76] Small corrections of documentation --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 8e0fc77ec9990..2c631a937b622 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -560,12 +560,12 @@ impl State { } } - /// Retrieve the value stored for a place, or ⊥ if it is not tracked. + /// Retrieve the value stored for a place, or ⊤ if it is not tracked. pub fn get(&self, place: PlaceRef<'_>, map: &Map) -> V { map.find(place).map(|place| self.get_idx(place, map)).unwrap_or(V::top()) } - /// Retrieve the value stored for a place index, or ⊥ if it is not tracked. + /// Retrieve the value stored for a place index, or ⊤ if it is not tracked. pub fn get_idx(&self, place: PlaceIndex, map: &Map) -> V { match &self.0 { StateData::Reachable(values) => { @@ -652,7 +652,7 @@ impl Map { mut filter: impl FnMut(Ty<'tcx>) -> bool, exclude: &FxHashSet>, ) { - // This is used to tell whether a type is `!Freeze`. + // This is used to tell whether a type is `Freeze`. let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let mut projection = Vec::new(); From 3997893ccb56dde4671cf7213faf9581714da402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Mon, 7 Nov 2022 11:01:44 +0100 Subject: [PATCH 63/76] Fix rebase --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 3 +-- src/test/mir-opt/issue_101973.inner.ConstProp.diff | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 2c631a937b622..3472f2a51d235 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -53,7 +53,6 @@ use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::DUMMY_SP; use rustc_target::abi::VariantIdx; use crate::lattice::{HasBottom, HasTop}; @@ -694,7 +693,7 @@ impl Map { if max_derefs > 0 { if let Some(ty::TypeAndMut { ty: deref_ty, .. }) = ty.builtin_deref(false) { // Values behind references can only be tracked if the target is `Freeze`. - if deref_ty.is_freeze(tcx.at(DUMMY_SP), param_env) { + if deref_ty.is_freeze(tcx, param_env) { projection.push(PlaceElem::Deref); self.register_with_filter_rec( tcx, diff --git a/src/test/mir-opt/issue_101973.inner.ConstProp.diff b/src/test/mir-opt/issue_101973.inner.ConstProp.diff index c24abedae927f..bce40f277d23b 100644 --- a/src/test/mir-opt/issue_101973.inner.ConstProp.diff +++ b/src/test/mir-opt/issue_101973.inner.ConstProp.diff @@ -37,7 +37,6 @@ StorageLive(_4); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:17 StorageLive(_5); // scope 0 at $DIR/issue_101973.rs:+1:10: +1:16 _5 = _1; // scope 0 at $DIR/issue_101973.rs:+1:10: +1:16 - _4 = const 0_u32; // scope 1 at $DIR/issue_101973.rs:6:19: 6:23 StorageLive(_12); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27 StorageLive(_13); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20 StorageLive(_14); // scope 2 at $DIR/issue_101973.rs:7:13: 7:14 @@ -73,7 +72,7 @@ StorageDead(_14); // scope 2 at $DIR/issue_101973.rs:7:19: 7:20 _12 = BitAnd(move _13, const 255_u32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27 StorageDead(_13); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27 - _4 = BitOr(_4, move _12); // scope 2 at $DIR/issue_101973.rs:7:5: 7:27 + _4 = BitOr(const 0_u32, move _12); // scope 2 at $DIR/issue_101973.rs:7:5: 7:27 StorageDead(_12); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27 StorageDead(_5); // scope 0 at $DIR/issue_101973.rs:+1:16: +1:17 StorageLive(_6); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 From bfbca6c75c1502b14ffda12afa2b688fe42288fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 9 Nov 2022 18:03:30 +0100 Subject: [PATCH 64/76] Completely remove tracking of references for now --- .../rustc_mir_dataflow/src/value_analysis.rs | 172 ++++-------------- .../src/dataflow_const_prop.rs | 24 +-- .../cast.main.DataflowConstProp.diff | 28 ++- src/test/mir-opt/dataflow-const-prop/cast.rs | 3 +- .../mir-opt/dataflow-const-prop/checked.rs | 2 +- .../if.main.DataflowConstProp.diff | 134 +++++++------- src/test/mir-opt/dataflow-const-prop/if.rs | 5 +- .../dataflow-const-prop/inherit_overflow.rs | 2 +- .../dataflow-const-prop/issue_81605.rs | 1 - .../promoted.main.DataflowConstProp.diff | 29 --- .../mir-opt/dataflow-const-prop/promoted.rs | 8 - .../ref.main.DataflowConstProp.diff | 89 --------- src/test/mir-opt/dataflow-const-prop/ref.rs | 10 - .../ref_mut.main.DataflowConstProp.diff | 77 -------- .../mir-opt/dataflow-const-prop/ref_mut.rs | 16 -- .../ref_with_sb.main.DataflowConstProp.diff | 56 ------ .../dataflow-const-prop/ref_with_sb.rs | 19 -- ...ref_without_sb.main.DataflowConstProp.diff | 16 +- .../dataflow-const-prop/ref_without_sb.rs | 3 +- .../self_assign.main.DataflowConstProp.diff | 18 +- .../dataflow-const-prop/self_assign.rs | 1 - .../dataflow-const-prop/self_assign_add.rs | 1 - .../static_ref.main.DataflowConstProp.diff | 53 ------ .../mir-opt/dataflow-const-prop/static_ref.rs | 12 -- .../terminator.main.DataflowConstProp.diff | 36 ++-- .../mir-opt/dataflow-const-prop/terminator.rs | 2 +- .../tuple.main.DataflowConstProp.diff | 117 ++++++------ src/test/mir-opt/dataflow-const-prop/tuple.rs | 7 +- 28 files changed, 218 insertions(+), 723 deletions(-) delete mode 100644 src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/promoted.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/ref.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/ref_mut.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs delete mode 100644 src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff delete mode 100644 src/test/mir-opt/dataflow-const-prop/static_ref.rs diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 3472f2a51d235..f428cd5ee8223 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -13,11 +13,10 @@ //! can be registered. The [`State`] can be queried to retrieve the abstract value stored for a //! certain place by passing the map. //! -//! This framework is currently experimental. In particular, the features related to references are -//! currently guarded behind `-Zunsound-mir-opts`, because their correctness relies on Stacked -//! Borrows. Also, only places with scalar types can be tracked currently. This is because scalar -//! types are indivisible, which simplifies the current implementation. But this limitation could be -//! lifted in the future. +//! This framework is currently experimental. Originally, it supported shared references and enum +//! variants. However, it was discovered that both of these were unsound, and especially references +//! had subtle but serious issues. In the future, they could be added back in, but we should clarify +//! the rules for optimizations that rely on the aliasing model first. //! //! //! # Notes @@ -28,29 +27,17 @@ //! - The assignment logic in `State::assign_place_idx` assumes that the places are non-overlapping, //! or identical. Note that this refers to place expressions, not memory locations. //! -//! - Since pointers (and mutable references) are not tracked, but can be used to change the -//! underlying values, we are conservative and immediately flood the referenced place upon creation -//! of the pointer. Also, we have to uphold the invariant that the place must stay that way as long -//! as this mutable access could exist. However... -//! -//! - Without an aliasing model like Stacked Borrows (i.e., `-Zunsound-mir-opts` is not given), -//! such mutable access is never revoked. And even shared references could be used to obtain the -//! address of a value an modify it. When not assuming Stacked Borrows, we prevent such places from -//! being tracked at all. This means that the analysis itself can assume that writes to a *tracked* -//! place always invalidate all other means of mutable access, regardless of the aliasing model. -//! -//! - Likewise, the analysis itself assumes that if the value of a *tracked* place behind a shared -//! reference is changed, the reference may not be used to access that value anymore. This is true -//! for all places if the referenced type is `Freeze` and we assume Stacked Borrows. If we are not -//! assuming Stacking Borrows (or if the referenced type could be `!Freeze`), we again prevent such -//! places from being tracked at all, making this assertion trivially true. +//! - Currently, places that have their reference taken cannot be tracked. Although this would be +//! possible, it has to rely on some aliasing model, which we are not ready to commit to yet. +//! Because of that, we can assume that the only way to change the value behind a tracked place is +//! by direct assignment. use std::fmt::{Debug, Formatter}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::vec::IndexVec; use rustc_middle::mir::tcx::PlaceTy; -use rustc_middle::mir::visit::{PlaceContext, Visitor}; +use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_target::abi::VariantIdx; @@ -96,10 +83,7 @@ pub trait ValueAnalysis<'tcx> { state.flood_with(place.as_ref(), self.map(), Self::Value::bottom()); } StatementKind::Retag(..) => { - // A retag modifies the provenance of references. Currently references are only - // tracked if `-Zunsound-mir-opts` is given, but this might change in the future. - // However, it is still unclear how retags should be handled: - // https://github.com/rust-lang/rust/pull/101168#discussion_r985304895 + // We don't track references. } StatementKind::Nop | StatementKind::FakeRead(..) @@ -156,7 +140,7 @@ pub trait ValueAnalysis<'tcx> { &self, rvalue: &Rvalue<'tcx>, state: &mut State, - ) -> ValueOrPlaceOrRef { + ) -> ValueOrPlace { self.super_rvalue(rvalue, state) } @@ -164,21 +148,15 @@ pub trait ValueAnalysis<'tcx> { &self, rvalue: &Rvalue<'tcx>, state: &mut State, - ) -> ValueOrPlaceOrRef { + ) -> ValueOrPlace { match rvalue { - Rvalue::Use(operand) => self.handle_operand(operand, state).into(), - Rvalue::Ref(_, BorrowKind::Shared, place) => self - .map() - .find(place.as_ref()) - .map(ValueOrPlaceOrRef::Ref) - .unwrap_or(ValueOrPlaceOrRef::top()), - Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { - // This is not a `&x` reference and could be used for modification. - state.flood(place.as_ref(), self.map()); - ValueOrPlaceOrRef::top() - } + Rvalue::Use(operand) => self.handle_operand(operand, state), Rvalue::CopyForDeref(place) => { - self.handle_operand(&Operand::Copy(*place), state).into() + self.handle_operand(&Operand::Copy(*place), state) + } + Rvalue::Ref(..) | Rvalue::AddressOf(..) => { + // We don't track such places. + ValueOrPlace::top() } Rvalue::Repeat(..) | Rvalue::ThreadLocalRef(..) @@ -192,7 +170,7 @@ pub trait ValueAnalysis<'tcx> { | Rvalue::Aggregate(..) | Rvalue::ShallowInitBox(..) => { // No modification is possible through these r-values. - ValueOrPlaceOrRef::top() + ValueOrPlace::top() } } } @@ -247,14 +225,13 @@ pub trait ValueAnalysis<'tcx> { self.super_terminator(terminator, state) } - fn super_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State) { + fn super_terminator(&self, terminator: &Terminator<'tcx>, _state: &mut State) { match &terminator.kind { TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => { // Effect is applied by `handle_call_return`. } - TerminatorKind::Drop { place, .. } => { - // Place can still be accessed after drop, and drop has mutable access to it. - state.flood(place.as_ref(), self.map()); + TerminatorKind::Drop { .. } => { + // We don't track dropped places. } TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } => { // They would have an effect, but are not allowed in this phase. @@ -522,7 +499,7 @@ impl State { } } - pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlaceOrRef, map: &Map) { + pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlace, map: &Map) { if let Some(target) = map.find(target) { self.assign_idx(target, result, map); } else { @@ -530,9 +507,9 @@ impl State { } } - pub fn assign_idx(&mut self, target: PlaceIndex, result: ValueOrPlaceOrRef, map: &Map) { + pub fn assign_idx(&mut self, target: PlaceIndex, result: ValueOrPlace, map: &Map) { match result { - ValueOrPlaceOrRef::Value(value) => { + ValueOrPlace::Value(value) => { // First flood the target place in case we also track any projections (although // this scenario is currently not well-supported by the API). self.flood_idx(target, map); @@ -541,21 +518,7 @@ impl State { values[value_index] = value; } } - ValueOrPlaceOrRef::Place(source) => self.assign_place_idx(target, source, map), - ValueOrPlaceOrRef::Ref(source) => { - let StateData::Reachable(values) = &mut self.0 else { return }; - if let Some(value_index) = map.places[target].value_index { - values[value_index] = V::top(); - } - // Instead of tracking of *where* a reference points to (as in, which memory - // location), we track *what* it points to (as in, what do we know about the - // target). For an assignment `x = &y`, we thus copy the info of `y` to `*x`. - if let Some(target_deref) = map.apply(target, TrackElem::Deref) { - // We know here that `*x` is `Freeze`, because we only track through - // dereferences if the target type is `Freeze`. - self.assign_place_idx(target_deref, source, map); - } - } + ValueOrPlace::Place(source) => self.assign_place_idx(target, source, map), } } @@ -625,45 +588,27 @@ impl Map { filter: impl FnMut(Ty<'tcx>) -> bool, ) -> Self { let mut map = Self::new(); - - // If `-Zunsound-mir-opts` is given, tracking through references, and tracking of places - // that have their reference taken is allowed. This would be "unsound" in the sense that - // the correctness relies on an aliasing model similar to Stacked Borrows (which is - // not yet guaranteed). - if tcx.sess.opts.unstable_opts.unsound_mir_opts { - // We might want to add additional limitations. If a struct has 10 boxed fields of - // itself, there will currently be `10.pow(max_derefs)` tracked places. - map.register_with_filter(tcx, body, 2, filter, &FxHashSet::default()); - } else { - map.register_with_filter(tcx, body, 0, filter, &escaped_places(body)); - } - + map.register_with_filter(tcx, body, filter, &escaped_places(body)); debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len()); map } - /// Register all non-excluded places that pass the filter, up to a certain dereference depth. + /// Register all non-excluded places that pass the filter. fn register_with_filter<'tcx>( &mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - max_derefs: u32, mut filter: impl FnMut(Ty<'tcx>) -> bool, exclude: &FxHashSet>, ) { - // This is used to tell whether a type is `Freeze`. - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let mut projection = Vec::new(); for (local, decl) in body.local_decls.iter_enumerated() { self.register_with_filter_rec( tcx, - max_derefs, local, &mut projection, decl.ty, &mut filter, - param_env, exclude, ); } @@ -672,12 +617,10 @@ impl Map { fn register_with_filter_rec<'tcx>( &mut self, tcx: TyCtxt<'tcx>, - max_derefs: u32, local: Local, projection: &mut Vec>, ty: Ty<'tcx>, filter: &mut impl FnMut(Ty<'tcx>) -> bool, - param_env: ty::ParamEnv<'tcx>, exclude: &FxHashSet>, ) { if exclude.contains(&Place { local, projection: tcx.intern_place_elems(projection) }) { @@ -689,26 +632,6 @@ impl Map { // This might fail if `ty` is not scalar. let _ = self.register_with_ty(local, projection, ty); } - - if max_derefs > 0 { - if let Some(ty::TypeAndMut { ty: deref_ty, .. }) = ty.builtin_deref(false) { - // Values behind references can only be tracked if the target is `Freeze`. - if deref_ty.is_freeze(tcx, param_env) { - projection.push(PlaceElem::Deref); - self.register_with_filter_rec( - tcx, - max_derefs - 1, - local, - projection, - deref_ty, - filter, - param_env, - exclude, - ); - projection.pop(); - } - } - } iter_fields(ty, tcx, |variant, field, ty| { if variant.is_some() { // Downcasts are currently not supported. @@ -716,7 +639,7 @@ impl Map { } projection.push(PlaceElem::Field(field, ty)); self.register_with_filter_rec( - tcx, max_derefs, local, projection, ty, filter, param_env, exclude, + tcx, local, projection, ty, filter, exclude, ); projection.pop(); }); @@ -875,7 +798,7 @@ impl<'a> Iterator for Children<'a> { } } -/// Used as the result of an operand. +/// Used as the result of an operand or r-value. pub enum ValueOrPlace { Value(V), Place(PlaceIndex), @@ -887,34 +810,11 @@ impl ValueOrPlace { } } -/// Used as the result of an r-value. -pub enum ValueOrPlaceOrRef { - Value(V), - Place(PlaceIndex), - Ref(PlaceIndex), -} - -impl ValueOrPlaceOrRef { - pub fn top() -> Self { - ValueOrPlaceOrRef::Value(V::top()) - } -} - -impl From> for ValueOrPlaceOrRef { - fn from(x: ValueOrPlace) -> Self { - match x { - ValueOrPlace::Value(value) => ValueOrPlaceOrRef::Value(value), - ValueOrPlace::Place(place) => ValueOrPlaceOrRef::Place(place), - } - } -} - /// The set of projection elements that can be used by a tracked place. /// -/// For now, downcast is not allowed due to aliasing between variants (see #101168). +/// Although only field projections are currently allowed, this could change in the future. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum TrackElem { - Deref, Field(Field), } @@ -923,7 +823,6 @@ impl TryFrom> for TrackElem { fn try_from(value: ProjectionElem) -> Result { match value { - ProjectionElem::Deref => Ok(TrackElem::Deref), ProjectionElem::Field(field, _) => Ok(TrackElem::Field(field)), _ => Err(()), } @@ -962,7 +861,7 @@ fn iter_fields<'tcx>( /// Returns all places, that have their reference or address taken. /// -/// This includes shared references. +/// This includes shared references, and also drops and `InlineAsm` out parameters. fn escaped_places<'tcx>(body: &Body<'tcx>) -> FxHashSet> { struct Collector<'tcx> { result: FxHashSet>, @@ -970,7 +869,11 @@ fn escaped_places<'tcx>(body: &Body<'tcx>) -> FxHashSet> { impl<'tcx> Visitor<'tcx> for Collector<'tcx> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - if context.is_borrow() || context.is_address_of() { + if context.is_borrow() + || context.is_address_of() + || context.is_drop() + || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) + { self.result.insert(*place); } } @@ -1032,7 +935,6 @@ fn debug_with_context_rec( for child in map.children(place) { let info_elem = map.places[child].proj_elem.unwrap(); let child_place_str = match info_elem { - TrackElem::Deref => format!("*{}", place_str), TrackElem::Field(field) => { if place_str.starts_with("*") { format!("({}).{}", place_str, field.index()) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 001b83ccda236..e88125777f142 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::visit::{MutVisitor, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{ - Map, State, TrackElem, ValueAnalysis, ValueOrPlace, ValueOrPlaceOrRef, + Map, State, TrackElem, ValueAnalysis, ValueOrPlace, }; use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects}; use rustc_span::DUMMY_SP; @@ -100,7 +100,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { let (val, overflow) = self.binary_op(state, *op, left, right); if let Some(value_target) = value_target { - state.assign_idx(value_target, ValueOrPlaceOrRef::Value(val), self.map()); + state.assign_idx(value_target, ValueOrPlace::Value(val), self.map()); } if let Some(overflow_target) = overflow_target { let overflow = match overflow { @@ -117,7 +117,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { }; state.assign_idx( overflow_target, - ValueOrPlaceOrRef::Value(overflow), + ValueOrPlace::Value(overflow), self.map(), ); } @@ -131,7 +131,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { &self, rvalue: &Rvalue<'tcx>, state: &mut State, - ) -> ValueOrPlaceOrRef { + ) -> ValueOrPlace { match rvalue { Rvalue::Cast( kind @ (CastKind::IntToInt @@ -150,23 +150,23 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { } _ => unreachable!(), } - .map(|result| ValueOrPlaceOrRef::Value(self.wrap_immediate(result, *ty))) - .unwrap_or(ValueOrPlaceOrRef::top()), - _ => ValueOrPlaceOrRef::top(), + .map(|result| ValueOrPlace::Value(self.wrap_immediate(result, *ty))) + .unwrap_or(ValueOrPlace::top()), + _ => ValueOrPlace::top(), }, Rvalue::BinaryOp(op, box (left, right)) => { // Overflows must be ignored here. let (val, _overflow) = self.binary_op(state, *op, left, right); - ValueOrPlaceOrRef::Value(val) + ValueOrPlace::Value(val) } Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) { FlatSet::Elem(value) => self .ecx .unary_op(*op, &value) - .map(|val| ValueOrPlaceOrRef::Value(self.wrap_immty(val))) - .unwrap_or(ValueOrPlaceOrRef::Value(FlatSet::Top)), - FlatSet::Bottom => ValueOrPlaceOrRef::Value(FlatSet::Bottom), - FlatSet::Top => ValueOrPlaceOrRef::Value(FlatSet::Top), + .map(|val| ValueOrPlace::Value(self.wrap_immty(val))) + .unwrap_or(ValueOrPlace::Value(FlatSet::Top)), + FlatSet::Bottom => ValueOrPlace::Value(FlatSet::Bottom), + FlatSet::Top => ValueOrPlace::Value(FlatSet::Top), }, _ => self.super_rvalue(rvalue, state), } diff --git a/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff index a8f04c9fc7f43..bf9ab8669380a 100644 --- a/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/cast.main.DataflowConstProp.diff @@ -4,9 +4,8 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/cast.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/cast.rs:+1:9: +1:10 - let mut _3: u8; // in scope 0 at $DIR/cast.rs:+2:13: +2:22 - let mut _4: i32; // in scope 0 at $DIR/cast.rs:+2:13: +2:16 - let mut _5: &i32; // in scope 0 at $DIR/cast.rs:+2:14: +2:16 + let mut _3: u8; // in scope 0 at $DIR/cast.rs:+2:13: +2:20 + let mut _4: i32; // in scope 0 at $DIR/cast.rs:+2:13: +2:14 scope 1 { debug a => _1; // in scope 1 at $DIR/cast.rs:+1:9: +1:10 let _2: u8; // in scope 1 at $DIR/cast.rs:+2:9: +2:10 @@ -19,19 +18,16 @@ StorageLive(_1); // scope 0 at $DIR/cast.rs:+1:9: +1:10 _1 = const 257_i32; // scope 0 at $DIR/cast.rs:+1:13: +1:16 StorageLive(_2); // scope 1 at $DIR/cast.rs:+2:9: +2:10 - StorageLive(_3); // scope 1 at $DIR/cast.rs:+2:13: +2:22 - StorageLive(_4); // scope 1 at $DIR/cast.rs:+2:13: +2:16 - StorageLive(_5); // scope 1 at $DIR/cast.rs:+2:14: +2:16 - _5 = &_1; // scope 1 at $DIR/cast.rs:+2:14: +2:16 -- _4 = (*_5); // scope 1 at $DIR/cast.rs:+2:13: +2:16 -- _3 = move _4 as u8 (IntToInt); // scope 1 at $DIR/cast.rs:+2:13: +2:22 -+ _4 = const 257_i32; // scope 1 at $DIR/cast.rs:+2:13: +2:16 -+ _3 = const 1_u8; // scope 1 at $DIR/cast.rs:+2:13: +2:22 - StorageDead(_4); // scope 1 at $DIR/cast.rs:+2:21: +2:22 -- _2 = Add(move _3, const 1_u8); // scope 1 at $DIR/cast.rs:+2:13: +2:26 -+ _2 = const 2_u8; // scope 1 at $DIR/cast.rs:+2:13: +2:26 - StorageDead(_3); // scope 1 at $DIR/cast.rs:+2:25: +2:26 - StorageDead(_5); // scope 1 at $DIR/cast.rs:+2:26: +2:27 + StorageLive(_3); // scope 1 at $DIR/cast.rs:+2:13: +2:20 + StorageLive(_4); // scope 1 at $DIR/cast.rs:+2:13: +2:14 +- _4 = _1; // scope 1 at $DIR/cast.rs:+2:13: +2:14 +- _3 = move _4 as u8 (IntToInt); // scope 1 at $DIR/cast.rs:+2:13: +2:20 ++ _4 = const 257_i32; // scope 1 at $DIR/cast.rs:+2:13: +2:14 ++ _3 = const 1_u8; // scope 1 at $DIR/cast.rs:+2:13: +2:20 + StorageDead(_4); // scope 1 at $DIR/cast.rs:+2:19: +2:20 +- _2 = Add(move _3, const 1_u8); // scope 1 at $DIR/cast.rs:+2:13: +2:24 ++ _2 = const 2_u8; // scope 1 at $DIR/cast.rs:+2:13: +2:24 + StorageDead(_3); // scope 1 at $DIR/cast.rs:+2:23: +2:24 _0 = const (); // scope 0 at $DIR/cast.rs:+0:11: +3:2 StorageDead(_2); // scope 1 at $DIR/cast.rs:+3:1: +3:2 StorageDead(_1); // scope 0 at $DIR/cast.rs:+3:1: +3:2 diff --git a/src/test/mir-opt/dataflow-const-prop/cast.rs b/src/test/mir-opt/dataflow-const-prop/cast.rs index 23c360ed87489..484403f7f0ec4 100644 --- a/src/test/mir-opt/dataflow-const-prop/cast.rs +++ b/src/test/mir-opt/dataflow-const-prop/cast.rs @@ -1,8 +1,7 @@ // unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts // EMIT_MIR cast.main.DataflowConstProp.diff fn main() { let a = 257; - let b = *&a as u8 + 1; + let b = a as u8 + 1; } diff --git a/src/test/mir-opt/dataflow-const-prop/checked.rs b/src/test/mir-opt/dataflow-const-prop/checked.rs index 8c99fc95eb1d8..0738a4ee53b86 100644 --- a/src/test/mir-opt/dataflow-const-prop/checked.rs +++ b/src/test/mir-opt/dataflow-const-prop/checked.rs @@ -1,5 +1,5 @@ // unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts -Coverflow-checks=on +// compile-flags: -Coverflow-checks=on // EMIT_MIR checked.main.DataflowConstProp.diff #[allow(arithmetic_overflow)] diff --git a/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff index 1a5ded8cc0df6..26808c70fbf2c 100644 --- a/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff @@ -4,29 +4,27 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/if.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/if.rs:+1:9: +1:10 - let mut _3: bool; // in scope 0 at $DIR/if.rs:+2:16: +2:24 - let mut _4: i32; // in scope 0 at $DIR/if.rs:+2:16: +2:19 - let mut _5: &i32; // in scope 0 at $DIR/if.rs:+2:17: +2:19 - let mut _7: i32; // in scope 0 at $DIR/if.rs:+3:13: +3:14 - let mut _9: bool; // in scope 0 at $DIR/if.rs:+5:16: +5:24 - let mut _10: i32; // in scope 0 at $DIR/if.rs:+5:16: +5:19 - let mut _11: &i32; // in scope 0 at $DIR/if.rs:+5:17: +5:19 - let mut _12: i32; // in scope 0 at $DIR/if.rs:+5:38: +5:39 - let mut _14: i32; // in scope 0 at $DIR/if.rs:+6:13: +6:14 + let mut _3: bool; // in scope 0 at $DIR/if.rs:+2:16: +2:22 + let mut _4: i32; // in scope 0 at $DIR/if.rs:+2:16: +2:17 + let mut _6: i32; // in scope 0 at $DIR/if.rs:+3:13: +3:14 + let mut _8: bool; // in scope 0 at $DIR/if.rs:+5:16: +5:22 + let mut _9: i32; // in scope 0 at $DIR/if.rs:+5:16: +5:17 + let mut _10: i32; // in scope 0 at $DIR/if.rs:+5:36: +5:37 + let mut _12: i32; // in scope 0 at $DIR/if.rs:+6:13: +6:14 scope 1 { debug a => _1; // in scope 1 at $DIR/if.rs:+1:9: +1:10 let _2: i32; // in scope 1 at $DIR/if.rs:+2:9: +2:10 scope 2 { debug b => _2; // in scope 2 at $DIR/if.rs:+2:9: +2:10 - let _6: i32; // in scope 2 at $DIR/if.rs:+3:9: +3:10 + let _5: i32; // in scope 2 at $DIR/if.rs:+3:9: +3:10 scope 3 { - debug c => _6; // in scope 3 at $DIR/if.rs:+3:9: +3:10 - let _8: i32; // in scope 3 at $DIR/if.rs:+5:9: +5:10 + debug c => _5; // in scope 3 at $DIR/if.rs:+3:9: +3:10 + let _7: i32; // in scope 3 at $DIR/if.rs:+5:9: +5:10 scope 4 { - debug d => _8; // in scope 4 at $DIR/if.rs:+5:9: +5:10 - let _13: i32; // in scope 4 at $DIR/if.rs:+6:9: +6:10 + debug d => _7; // in scope 4 at $DIR/if.rs:+5:9: +5:10 + let _11: i32; // in scope 4 at $DIR/if.rs:+6:9: +6:10 scope 5 { - debug e => _13; // in scope 5 at $DIR/if.rs:+6:9: +6:10 + debug e => _11; // in scope 5 at $DIR/if.rs:+6:9: +6:10 } } } @@ -37,81 +35,75 @@ StorageLive(_1); // scope 0 at $DIR/if.rs:+1:9: +1:10 _1 = const 1_i32; // scope 0 at $DIR/if.rs:+1:13: +1:14 StorageLive(_2); // scope 1 at $DIR/if.rs:+2:9: +2:10 - StorageLive(_3); // scope 1 at $DIR/if.rs:+2:16: +2:24 - StorageLive(_4); // scope 1 at $DIR/if.rs:+2:16: +2:19 - StorageLive(_5); // scope 1 at $DIR/if.rs:+2:17: +2:19 - _5 = &_1; // scope 1 at $DIR/if.rs:+2:17: +2:19 -- _4 = (*_5); // scope 1 at $DIR/if.rs:+2:16: +2:19 -- _3 = Eq(move _4, const 1_i32); // scope 1 at $DIR/if.rs:+2:16: +2:24 -+ _4 = const 1_i32; // scope 1 at $DIR/if.rs:+2:16: +2:19 -+ _3 = const true; // scope 1 at $DIR/if.rs:+2:16: +2:24 - StorageDead(_5); // scope 1 at $DIR/if.rs:+2:23: +2:24 - StorageDead(_4); // scope 1 at $DIR/if.rs:+2:23: +2:24 -- switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:24 -+ switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:24 + StorageLive(_3); // scope 1 at $DIR/if.rs:+2:16: +2:22 + StorageLive(_4); // scope 1 at $DIR/if.rs:+2:16: +2:17 +- _4 = _1; // scope 1 at $DIR/if.rs:+2:16: +2:17 +- _3 = Eq(move _4, const 1_i32); // scope 1 at $DIR/if.rs:+2:16: +2:22 ++ _4 = const 1_i32; // scope 1 at $DIR/if.rs:+2:16: +2:17 ++ _3 = const true; // scope 1 at $DIR/if.rs:+2:16: +2:22 + StorageDead(_4); // scope 1 at $DIR/if.rs:+2:21: +2:22 +- switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22 ++ switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22 } bb1: { - _2 = const 2_i32; // scope 1 at $DIR/if.rs:+2:27: +2:28 - goto -> bb3; // scope 1 at $DIR/if.rs:+2:13: +2:41 + _2 = const 2_i32; // scope 1 at $DIR/if.rs:+2:25: +2:26 + goto -> bb3; // scope 1 at $DIR/if.rs:+2:13: +2:39 } bb2: { - _2 = const 3_i32; // scope 1 at $DIR/if.rs:+2:38: +2:39 - goto -> bb3; // scope 1 at $DIR/if.rs:+2:13: +2:41 + _2 = const 3_i32; // scope 1 at $DIR/if.rs:+2:36: +2:37 + goto -> bb3; // scope 1 at $DIR/if.rs:+2:13: +2:39 } bb3: { - StorageDead(_3); // scope 1 at $DIR/if.rs:+2:40: +2:41 - StorageLive(_6); // scope 2 at $DIR/if.rs:+3:9: +3:10 - StorageLive(_7); // scope 2 at $DIR/if.rs:+3:13: +3:14 -- _7 = _2; // scope 2 at $DIR/if.rs:+3:13: +3:14 -- _6 = Add(move _7, const 1_i32); // scope 2 at $DIR/if.rs:+3:13: +3:18 -+ _7 = const 2_i32; // scope 2 at $DIR/if.rs:+3:13: +3:14 -+ _6 = const 3_i32; // scope 2 at $DIR/if.rs:+3:13: +3:18 - StorageDead(_7); // scope 2 at $DIR/if.rs:+3:17: +3:18 - StorageLive(_8); // scope 3 at $DIR/if.rs:+5:9: +5:10 - StorageLive(_9); // scope 3 at $DIR/if.rs:+5:16: +5:24 - StorageLive(_10); // scope 3 at $DIR/if.rs:+5:16: +5:19 - StorageLive(_11); // scope 3 at $DIR/if.rs:+5:17: +5:19 - _11 = &_1; // scope 3 at $DIR/if.rs:+5:17: +5:19 -- _10 = (*_11); // scope 3 at $DIR/if.rs:+5:16: +5:19 -- _9 = Eq(move _10, const 1_i32); // scope 3 at $DIR/if.rs:+5:16: +5:24 -+ _10 = const 1_i32; // scope 3 at $DIR/if.rs:+5:16: +5:19 -+ _9 = const true; // scope 3 at $DIR/if.rs:+5:16: +5:24 - StorageDead(_11); // scope 3 at $DIR/if.rs:+5:23: +5:24 - StorageDead(_10); // scope 3 at $DIR/if.rs:+5:23: +5:24 -- switchInt(move _9) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:24 -+ switchInt(const true) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:24 + StorageDead(_3); // scope 1 at $DIR/if.rs:+2:38: +2:39 + StorageLive(_5); // scope 2 at $DIR/if.rs:+3:9: +3:10 + StorageLive(_6); // scope 2 at $DIR/if.rs:+3:13: +3:14 +- _6 = _2; // scope 2 at $DIR/if.rs:+3:13: +3:14 +- _5 = Add(move _6, const 1_i32); // scope 2 at $DIR/if.rs:+3:13: +3:18 ++ _6 = const 2_i32; // scope 2 at $DIR/if.rs:+3:13: +3:14 ++ _5 = const 3_i32; // scope 2 at $DIR/if.rs:+3:13: +3:18 + StorageDead(_6); // scope 2 at $DIR/if.rs:+3:17: +3:18 + StorageLive(_7); // scope 3 at $DIR/if.rs:+5:9: +5:10 + StorageLive(_8); // scope 3 at $DIR/if.rs:+5:16: +5:22 + StorageLive(_9); // scope 3 at $DIR/if.rs:+5:16: +5:17 +- _9 = _1; // scope 3 at $DIR/if.rs:+5:16: +5:17 +- _8 = Eq(move _9, const 1_i32); // scope 3 at $DIR/if.rs:+5:16: +5:22 ++ _9 = const 1_i32; // scope 3 at $DIR/if.rs:+5:16: +5:17 ++ _8 = const true; // scope 3 at $DIR/if.rs:+5:16: +5:22 + StorageDead(_9); // scope 3 at $DIR/if.rs:+5:21: +5:22 +- switchInt(move _8) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22 ++ switchInt(const true) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22 } bb4: { -- _8 = _1; // scope 3 at $DIR/if.rs:+5:27: +5:28 -+ _8 = const 1_i32; // scope 3 at $DIR/if.rs:+5:27: +5:28 - goto -> bb6; // scope 3 at $DIR/if.rs:+5:13: +5:45 +- _7 = _1; // scope 3 at $DIR/if.rs:+5:25: +5:26 ++ _7 = const 1_i32; // scope 3 at $DIR/if.rs:+5:25: +5:26 + goto -> bb6; // scope 3 at $DIR/if.rs:+5:13: +5:43 } bb5: { - StorageLive(_12); // scope 3 at $DIR/if.rs:+5:38: +5:39 - _12 = _1; // scope 3 at $DIR/if.rs:+5:38: +5:39 - _8 = Add(move _12, const 1_i32); // scope 3 at $DIR/if.rs:+5:38: +5:43 - StorageDead(_12); // scope 3 at $DIR/if.rs:+5:42: +5:43 - goto -> bb6; // scope 3 at $DIR/if.rs:+5:13: +5:45 + StorageLive(_10); // scope 3 at $DIR/if.rs:+5:36: +5:37 + _10 = _1; // scope 3 at $DIR/if.rs:+5:36: +5:37 + _7 = Add(move _10, const 1_i32); // scope 3 at $DIR/if.rs:+5:36: +5:41 + StorageDead(_10); // scope 3 at $DIR/if.rs:+5:40: +5:41 + goto -> bb6; // scope 3 at $DIR/if.rs:+5:13: +5:43 } bb6: { - StorageDead(_9); // scope 3 at $DIR/if.rs:+5:44: +5:45 - StorageLive(_13); // scope 4 at $DIR/if.rs:+6:9: +6:10 - StorageLive(_14); // scope 4 at $DIR/if.rs:+6:13: +6:14 -- _14 = _8; // scope 4 at $DIR/if.rs:+6:13: +6:14 -- _13 = Add(move _14, const 1_i32); // scope 4 at $DIR/if.rs:+6:13: +6:18 -+ _14 = const 1_i32; // scope 4 at $DIR/if.rs:+6:13: +6:14 -+ _13 = const 2_i32; // scope 4 at $DIR/if.rs:+6:13: +6:18 - StorageDead(_14); // scope 4 at $DIR/if.rs:+6:17: +6:18 + StorageDead(_8); // scope 3 at $DIR/if.rs:+5:42: +5:43 + StorageLive(_11); // scope 4 at $DIR/if.rs:+6:9: +6:10 + StorageLive(_12); // scope 4 at $DIR/if.rs:+6:13: +6:14 +- _12 = _7; // scope 4 at $DIR/if.rs:+6:13: +6:14 +- _11 = Add(move _12, const 1_i32); // scope 4 at $DIR/if.rs:+6:13: +6:18 ++ _12 = const 1_i32; // scope 4 at $DIR/if.rs:+6:13: +6:14 ++ _11 = const 2_i32; // scope 4 at $DIR/if.rs:+6:13: +6:18 + StorageDead(_12); // scope 4 at $DIR/if.rs:+6:17: +6:18 _0 = const (); // scope 0 at $DIR/if.rs:+0:11: +7:2 - StorageDead(_13); // scope 4 at $DIR/if.rs:+7:1: +7:2 - StorageDead(_8); // scope 3 at $DIR/if.rs:+7:1: +7:2 - StorageDead(_6); // scope 2 at $DIR/if.rs:+7:1: +7:2 + StorageDead(_11); // scope 4 at $DIR/if.rs:+7:1: +7:2 + StorageDead(_7); // scope 3 at $DIR/if.rs:+7:1: +7:2 + StorageDead(_5); // scope 2 at $DIR/if.rs:+7:1: +7:2 StorageDead(_2); // scope 1 at $DIR/if.rs:+7:1: +7:2 StorageDead(_1); // scope 0 at $DIR/if.rs:+7:1: +7:2 return; // scope 0 at $DIR/if.rs:+7:2: +7:2 diff --git a/src/test/mir-opt/dataflow-const-prop/if.rs b/src/test/mir-opt/dataflow-const-prop/if.rs index cc41da2dc9a2c..34fc35790c17f 100644 --- a/src/test/mir-opt/dataflow-const-prop/if.rs +++ b/src/test/mir-opt/dataflow-const-prop/if.rs @@ -1,12 +1,11 @@ // unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts // EMIT_MIR if.main.DataflowConstProp.diff fn main() { let a = 1; - let b = if *&a == 1 { 2 } else { 3 }; + let b = if a == 1 { 2 } else { 3 }; let c = b + 1; - let d = if *&a == 1 { a } else { a + 1 }; + let d = if a == 1 { a } else { a + 1 }; let e = d + 1; } diff --git a/src/test/mir-opt/dataflow-const-prop/inherit_overflow.rs b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.rs index 3f6329dfd1d16..2f2d9d0102d12 100644 --- a/src/test/mir-opt/dataflow-const-prop/inherit_overflow.rs +++ b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.rs @@ -1,4 +1,4 @@ -// compile-flags: -Coverflow-checks=off -Zunsound-mir-opts +// compile-flags: -Zunsound-mir-opts // EMIT_MIR inherit_overflow.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/issue_81605.rs b/src/test/mir-opt/dataflow-const-prop/issue_81605.rs index 2829d32c905c8..d75e2a28bef6b 100644 --- a/src/test/mir-opt/dataflow-const-prop/issue_81605.rs +++ b/src/test/mir-opt/dataflow-const-prop/issue_81605.rs @@ -1,5 +1,4 @@ // unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts // EMIT_MIR issue_81605.f.DataflowConstProp.diff fn f() -> usize { diff --git a/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff deleted file mode 100644 index 177736d62cd90..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/promoted.main.DataflowConstProp.diff +++ /dev/null @@ -1,29 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/promoted.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/promoted.rs:+2:9: +2:10 - let mut _2: &i32; // in scope 0 at $DIR/promoted.rs:+2:14: +2:17 - let _3: i32; // in scope 0 at $DIR/promoted.rs:+2:15: +2:17 - let mut _4: &i32; // in scope 0 at $DIR/promoted.rs:+2:14: +2:17 - scope 1 { - debug a => _1; // in scope 1 at $DIR/promoted.rs:+2:9: +2:10 - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/promoted.rs:+2:9: +2:10 - StorageLive(_2); // scope 0 at $DIR/promoted.rs:+2:14: +2:17 - _4 = const _; // scope 0 at $DIR/promoted.rs:+2:14: +2:17 - // mir::Constant - // + span: $DIR/promoted.rs:7:14: 7:17 - // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } - _2 = &(*_4); // scope 0 at $DIR/promoted.rs:+2:14: +2:17 - _1 = (*_2); // scope 0 at $DIR/promoted.rs:+2:13: +2:17 - StorageDead(_2); // scope 0 at $DIR/promoted.rs:+2:17: +2:18 - _0 = const (); // scope 0 at $DIR/promoted.rs:+0:11: +3:2 - StorageDead(_1); // scope 0 at $DIR/promoted.rs:+3:1: +3:2 - return; // scope 0 at $DIR/promoted.rs:+3:2: +3:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/promoted.rs b/src/test/mir-opt/dataflow-const-prop/promoted.rs deleted file mode 100644 index e5ca2f5b6072f..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/promoted.rs +++ /dev/null @@ -1,8 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts - -// EMIT_MIR promoted.main.DataflowConstProp.diff -fn main() { - // This does not work because `&42` gets promoted. - let a = *&42; -} diff --git a/src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff deleted file mode 100644 index f500c827786f8..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/ref.main.DataflowConstProp.diff +++ /dev/null @@ -1,89 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/ref.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/ref.rs:+1:9: +1:10 - let mut _4: bool; // in scope 0 at $DIR/ref.rs:+3:16: +3:43 - let mut _5: u32; // in scope 0 at $DIR/ref.rs:+3:16: +3:38 - let mut _6: u32; // in scope 0 at $DIR/ref.rs:+3:16: +3:34 - let mut _7: bool; // in scope 0 at $DIR/ref.rs:+3:16: +3:38 - let _8: &i32; // in scope 0 at $DIR/ref.rs:+3:58: +3:60 - let mut _10: i32; // in scope 0 at $DIR/ref.rs:+4:13: +4:15 - scope 1 { - debug a => _1; // in scope 1 at $DIR/ref.rs:+1:9: +1:10 - let _2: i32; // in scope 1 at $DIR/ref.rs:+2:9: +2:10 - scope 2 { - debug b => _2; // in scope 2 at $DIR/ref.rs:+2:9: +2:10 - let _3: &i32; // in scope 2 at $DIR/ref.rs:+3:9: +3:10 - scope 3 { - debug c => _3; // in scope 3 at $DIR/ref.rs:+3:9: +3:10 - let _9: i32; // in scope 3 at $DIR/ref.rs:+4:9: +4:10 - scope 4 { - debug d => _9; // in scope 4 at $DIR/ref.rs:+4:9: +4:10 - } - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/ref.rs:+1:9: +1:10 - _1 = const 0_i32; // scope 0 at $DIR/ref.rs:+1:13: +1:14 - StorageLive(_2); // scope 1 at $DIR/ref.rs:+2:9: +2:10 - _2 = const 0_i32; // scope 1 at $DIR/ref.rs:+2:13: +2:14 - StorageLive(_3); // scope 2 at $DIR/ref.rs:+3:9: +3:10 - StorageLive(_4); // scope 2 at $DIR/ref.rs:+3:16: +3:43 - StorageLive(_5); // scope 2 at $DIR/ref.rs:+3:16: +3:38 - StorageLive(_6); // scope 2 at $DIR/ref.rs:+3:16: +3:34 - _6 = id() -> bb1; // scope 2 at $DIR/ref.rs:+3:16: +3:34 - // mir::Constant - // + span: $DIR/ref.rs:8:16: 8:32 - // + literal: Const { ty: fn() -> u32 {id}, val: Value() } - } - - bb1: { -- _7 = Eq(const 2_u32, const 0_u32); // scope 2 at $DIR/ref.rs:+3:16: +3:38 -- assert(!move _7, "attempt to calculate the remainder of `{}` with a divisor of zero", _6) -> bb2; // scope 2 at $DIR/ref.rs:+3:16: +3:38 -+ _7 = const false; // scope 2 at $DIR/ref.rs:+3:16: +3:38 -+ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _6) -> bb2; // scope 2 at $DIR/ref.rs:+3:16: +3:38 - } - - bb2: { - _5 = Rem(move _6, const 2_u32); // scope 2 at $DIR/ref.rs:+3:16: +3:38 - StorageDead(_6); // scope 2 at $DIR/ref.rs:+3:37: +3:38 - _4 = Eq(move _5, const 0_u32); // scope 2 at $DIR/ref.rs:+3:16: +3:43 - StorageDead(_5); // scope 2 at $DIR/ref.rs:+3:42: +3:43 - switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/ref.rs:+3:16: +3:43 - } - - bb3: { - _3 = &_1; // scope 2 at $DIR/ref.rs:+3:46: +3:48 - goto -> bb5; // scope 2 at $DIR/ref.rs:+3:13: +3:62 - } - - bb4: { - StorageLive(_8); // scope 2 at $DIR/ref.rs:+3:58: +3:60 - _8 = &_2; // scope 2 at $DIR/ref.rs:+3:58: +3:60 - _3 = &(*_8); // scope 2 at $DIR/ref.rs:+3:58: +3:60 - StorageDead(_8); // scope 2 at $DIR/ref.rs:+3:61: +3:62 - goto -> bb5; // scope 2 at $DIR/ref.rs:+3:13: +3:62 - } - - bb5: { - StorageDead(_4); // scope 2 at $DIR/ref.rs:+3:61: +3:62 - StorageLive(_9); // scope 3 at $DIR/ref.rs:+4:9: +4:10 - StorageLive(_10); // scope 3 at $DIR/ref.rs:+4:13: +4:15 -- _10 = (*_3); // scope 3 at $DIR/ref.rs:+4:13: +4:15 -- _9 = Add(move _10, const 1_i32); // scope 3 at $DIR/ref.rs:+4:13: +4:19 -+ _10 = const 0_i32; // scope 3 at $DIR/ref.rs:+4:13: +4:15 -+ _9 = const 1_i32; // scope 3 at $DIR/ref.rs:+4:13: +4:19 - StorageDead(_10); // scope 3 at $DIR/ref.rs:+4:18: +4:19 - _0 = const (); // scope 0 at $DIR/ref.rs:+0:11: +5:2 - StorageDead(_9); // scope 3 at $DIR/ref.rs:+5:1: +5:2 - StorageDead(_3); // scope 2 at $DIR/ref.rs:+5:1: +5:2 - StorageDead(_2); // scope 1 at $DIR/ref.rs:+5:1: +5:2 - StorageDead(_1); // scope 0 at $DIR/ref.rs:+5:1: +5:2 - return; // scope 0 at $DIR/ref.rs:+5:2: +5:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/ref.rs b/src/test/mir-opt/dataflow-const-prop/ref.rs deleted file mode 100644 index 6c0e3063b0ab6..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/ref.rs +++ /dev/null @@ -1,10 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts - -// EMIT_MIR ref.main.DataflowConstProp.diff -fn main() { - let a = 0; - let b = 0; - let c = if std::process::id() % 2 == 0 { &a } else { &b }; - let d = *c + 1; -} diff --git a/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff deleted file mode 100644 index 746082eee531a..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/ref_mut.main.DataflowConstProp.diff +++ /dev/null @@ -1,77 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/ref_mut.rs:+0:11: +0:11 - let mut _1: i32; // in scope 0 at $DIR/ref_mut.rs:+1:9: +1:14 - let mut _7: &i32; // in scope 0 at $DIR/ref_mut.rs:+9:10: +9:12 - let _8: &i32; // in scope 0 at $DIR/ref_mut.rs:+9:10: +9:12 - let _9: i32; // in scope 0 at $DIR/ref_mut.rs:+9:11: +9:12 - scope 1 { - debug a => _1; // in scope 1 at $DIR/ref_mut.rs:+1:9: +1:14 - let _2: &mut i32; // in scope 1 at $DIR/ref_mut.rs:+2:9: +2:10 - scope 2 { - debug b => _2; // in scope 2 at $DIR/ref_mut.rs:+2:9: +2:10 - let _3: i32; // in scope 2 at $DIR/ref_mut.rs:+4:9: +4:10 - scope 3 { - debug c => _3; // in scope 3 at $DIR/ref_mut.rs:+4:9: +4:10 - let _4: i32; // in scope 3 at $DIR/ref_mut.rs:+6:9: +6:10 - scope 4 { - debug d => _4; // in scope 4 at $DIR/ref_mut.rs:+6:9: +6:10 - let mut _5: &i32; // in scope 4 at $DIR/ref_mut.rs:+7:9: +7:14 - scope 5 { - debug e => _5; // in scope 5 at $DIR/ref_mut.rs:+7:9: +7:14 - let _6: &mut &i32; // in scope 5 at $DIR/ref_mut.rs:+8:9: +8:10 - scope 6 { - debug f => _6; // in scope 6 at $DIR/ref_mut.rs:+8:9: +8:10 - let _10: i32; // in scope 6 at $DIR/ref_mut.rs:+10:9: +10:10 - let mut _11: &i32; // in scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 - scope 7 { - debug g => _10; // in scope 7 at $DIR/ref_mut.rs:+10:9: +10:10 - } - } - } - } - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/ref_mut.rs:+1:9: +1:14 - _1 = const 0_i32; // scope 0 at $DIR/ref_mut.rs:+1:17: +1:18 - StorageLive(_2); // scope 1 at $DIR/ref_mut.rs:+2:9: +2:10 - _2 = &mut _1; // scope 1 at $DIR/ref_mut.rs:+2:13: +2:19 - (*_2) = const 1_i32; // scope 2 at $DIR/ref_mut.rs:+3:5: +3:11 - StorageLive(_3); // scope 2 at $DIR/ref_mut.rs:+4:9: +4:10 - _3 = _1; // scope 2 at $DIR/ref_mut.rs:+4:13: +4:14 - StorageLive(_4); // scope 3 at $DIR/ref_mut.rs:+6:9: +6:10 - _4 = const 0_i32; // scope 3 at $DIR/ref_mut.rs:+6:13: +6:14 - StorageLive(_5); // scope 4 at $DIR/ref_mut.rs:+7:9: +7:14 - _5 = &_4; // scope 4 at $DIR/ref_mut.rs:+7:17: +7:19 - StorageLive(_6); // scope 5 at $DIR/ref_mut.rs:+8:9: +8:10 - _6 = &mut _5; // scope 5 at $DIR/ref_mut.rs:+8:13: +8:19 - StorageLive(_7); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 - StorageLive(_8); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 - _11 = const _; // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 - // mir::Constant - // + span: $DIR/ref_mut.rs:14:10: 14:12 - // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } - _8 = &(*_11); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 - _7 = &(*_8); // scope 6 at $DIR/ref_mut.rs:+9:10: +9:12 - (*_6) = move _7; // scope 6 at $DIR/ref_mut.rs:+9:5: +9:12 - StorageDead(_7); // scope 6 at $DIR/ref_mut.rs:+9:11: +9:12 - StorageDead(_8); // scope 6 at $DIR/ref_mut.rs:+9:12: +9:13 - StorageLive(_10); // scope 6 at $DIR/ref_mut.rs:+10:9: +10:10 - _10 = (*_5); // scope 6 at $DIR/ref_mut.rs:+10:13: +10:15 - _0 = const (); // scope 0 at $DIR/ref_mut.rs:+0:11: +11:2 - StorageDead(_10); // scope 6 at $DIR/ref_mut.rs:+11:1: +11:2 - StorageDead(_6); // scope 5 at $DIR/ref_mut.rs:+11:1: +11:2 - StorageDead(_5); // scope 4 at $DIR/ref_mut.rs:+11:1: +11:2 - StorageDead(_4); // scope 3 at $DIR/ref_mut.rs:+11:1: +11:2 - StorageDead(_3); // scope 2 at $DIR/ref_mut.rs:+11:1: +11:2 - StorageDead(_2); // scope 1 at $DIR/ref_mut.rs:+11:1: +11:2 - StorageDead(_1); // scope 0 at $DIR/ref_mut.rs:+11:1: +11:2 - return; // scope 0 at $DIR/ref_mut.rs:+11:2: +11:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/ref_mut.rs b/src/test/mir-opt/dataflow-const-prop/ref_mut.rs deleted file mode 100644 index 5728343951690..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/ref_mut.rs +++ /dev/null @@ -1,16 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts - -// EMIT_MIR ref_mut.main.DataflowConstProp.diff -fn main() { - let mut a = 0; - let b = &mut a; - *b = 1; - let c = a; - - let d = 0; - let mut e = &d; - let f = &mut e; - *f = &1; - let g = *e; -} diff --git a/src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff deleted file mode 100644 index 81aa0a1a93d66..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/ref_with_sb.main.DataflowConstProp.diff +++ /dev/null @@ -1,56 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/ref_with_sb.rs:+0:11: +0:11 - let mut _1: i32; // in scope 0 at $DIR/ref_with_sb.rs:+1:9: +1:14 - let _2: (); // in scope 0 at $DIR/ref_with_sb.rs:+2:5: +2:15 - let mut _3: &i32; // in scope 0 at $DIR/ref_with_sb.rs:+2:12: +2:14 - let _4: &i32; // in scope 0 at $DIR/ref_with_sb.rs:+2:12: +2:14 - let _5: (); // in scope 0 at $DIR/ref_with_sb.rs:+4:5: +4:20 - scope 1 { - debug a => _1; // in scope 1 at $DIR/ref_with_sb.rs:+1:9: +1:14 - let _6: i32; // in scope 1 at $DIR/ref_with_sb.rs:+7:9: +7:10 - scope 2 { - debug b => _6; // in scope 2 at $DIR/ref_with_sb.rs:+7:9: +7:10 - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/ref_with_sb.rs:+1:9: +1:14 - _1 = const 0_i32; // scope 0 at $DIR/ref_with_sb.rs:+1:17: +1:18 - StorageLive(_2); // scope 1 at $DIR/ref_with_sb.rs:+2:5: +2:15 - StorageLive(_3); // scope 1 at $DIR/ref_with_sb.rs:+2:12: +2:14 - StorageLive(_4); // scope 1 at $DIR/ref_with_sb.rs:+2:12: +2:14 - _4 = &_1; // scope 1 at $DIR/ref_with_sb.rs:+2:12: +2:14 - _3 = &(*_4); // scope 1 at $DIR/ref_with_sb.rs:+2:12: +2:14 - _2 = escape::(move _3) -> bb1; // scope 1 at $DIR/ref_with_sb.rs:+2:5: +2:15 - // mir::Constant - // + span: $DIR/ref_with_sb.rs:13:5: 13:11 - // + literal: Const { ty: for<'a> fn(&'a i32) {escape::}, val: Value() } - } - - bb1: { - StorageDead(_3); // scope 1 at $DIR/ref_with_sb.rs:+2:14: +2:15 - StorageDead(_4); // scope 1 at $DIR/ref_with_sb.rs:+2:15: +2:16 - StorageDead(_2); // scope 1 at $DIR/ref_with_sb.rs:+2:15: +2:16 - _1 = const 1_i32; // scope 1 at $DIR/ref_with_sb.rs:+3:5: +3:10 - StorageLive(_5); // scope 1 at $DIR/ref_with_sb.rs:+4:5: +4:20 - _5 = some_function() -> bb2; // scope 1 at $DIR/ref_with_sb.rs:+4:5: +4:20 - // mir::Constant - // + span: $DIR/ref_with_sb.rs:15:5: 15:18 - // + literal: Const { ty: fn() {some_function}, val: Value() } - } - - bb2: { - StorageDead(_5); // scope 1 at $DIR/ref_with_sb.rs:+4:20: +4:21 - StorageLive(_6); // scope 1 at $DIR/ref_with_sb.rs:+7:9: +7:10 -- _6 = _1; // scope 1 at $DIR/ref_with_sb.rs:+7:13: +7:14 -+ _6 = const 1_i32; // scope 1 at $DIR/ref_with_sb.rs:+7:13: +7:14 - _0 = const (); // scope 0 at $DIR/ref_with_sb.rs:+0:11: +8:2 - StorageDead(_6); // scope 1 at $DIR/ref_with_sb.rs:+8:1: +8:2 - StorageDead(_1); // scope 0 at $DIR/ref_with_sb.rs:+8:1: +8:2 - return; // scope 0 at $DIR/ref_with_sb.rs:+8:2: +8:2 - } - } - diff --git a/src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs b/src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs deleted file mode 100644 index 060aa6ab79472..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/ref_with_sb.rs +++ /dev/null @@ -1,19 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts - -#[inline(never)] -fn escape(x: &T) {} - -#[inline(never)] -fn some_function() {} - -// EMIT_MIR ref_with_sb.main.DataflowConstProp.diff -fn main() { - let mut a = 0; - escape(&a); - a = 1; - some_function(); - // With `-Zunsound-mir-opt`, this should be propagated - // (because we assume Stacked Borrows). - let b = a; -} diff --git a/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff index dc6a6a8a7595d..158f187f15769 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff @@ -10,9 +10,9 @@ let _5: (); // in scope 0 at $DIR/ref_without_sb.rs:+4:5: +4:20 scope 1 { debug a => _1; // in scope 1 at $DIR/ref_without_sb.rs:+1:9: +1:14 - let _6: i32; // in scope 1 at $DIR/ref_without_sb.rs:+7:9: +7:10 + let _6: i32; // in scope 1 at $DIR/ref_without_sb.rs:+6:9: +6:10 scope 2 { - debug b => _6; // in scope 2 at $DIR/ref_without_sb.rs:+7:9: +7:10 + debug b => _6; // in scope 2 at $DIR/ref_without_sb.rs:+6:9: +6:10 } } @@ -44,12 +44,12 @@ bb2: { StorageDead(_5); // scope 1 at $DIR/ref_without_sb.rs:+4:20: +4:21 - StorageLive(_6); // scope 1 at $DIR/ref_without_sb.rs:+7:9: +7:10 - _6 = _1; // scope 1 at $DIR/ref_without_sb.rs:+7:13: +7:14 - _0 = const (); // scope 0 at $DIR/ref_without_sb.rs:+0:11: +8:2 - StorageDead(_6); // scope 1 at $DIR/ref_without_sb.rs:+8:1: +8:2 - StorageDead(_1); // scope 0 at $DIR/ref_without_sb.rs:+8:1: +8:2 - return; // scope 0 at $DIR/ref_without_sb.rs:+8:2: +8:2 + StorageLive(_6); // scope 1 at $DIR/ref_without_sb.rs:+6:9: +6:10 + _6 = _1; // scope 1 at $DIR/ref_without_sb.rs:+6:13: +6:14 + _0 = const (); // scope 0 at $DIR/ref_without_sb.rs:+0:11: +7:2 + StorageDead(_6); // scope 1 at $DIR/ref_without_sb.rs:+7:1: +7:2 + StorageDead(_1); // scope 0 at $DIR/ref_without_sb.rs:+7:1: +7:2 + return; // scope 0 at $DIR/ref_without_sb.rs:+7:2: +7:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs index 4789eb69cda60..2fd480b0968af 100644 --- a/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs +++ b/src/test/mir-opt/dataflow-const-prop/ref_without_sb.rs @@ -12,7 +12,6 @@ fn main() { escape(&a); a = 1; some_function(); - // Without `-Zunsound-mir-opt`, this should not be propagated - // (because we do not assume Stacked Borrows). + // This should currently not be propagated. let b = a; } diff --git a/src/test/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff index dd1242d7cac02..df08eff94cb27 100644 --- a/src/test/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/self_assign.main.DataflowConstProp.diff @@ -20,16 +20,12 @@ StorageLive(_1); // scope 0 at $DIR/self_assign.rs:+1:9: +1:14 _1 = const 0_i32; // scope 0 at $DIR/self_assign.rs:+1:17: +1:18 StorageLive(_2); // scope 1 at $DIR/self_assign.rs:+2:9: +2:10 -- _2 = _1; // scope 1 at $DIR/self_assign.rs:+2:9: +2:10 -- _1 = Add(move _2, const 1_i32); // scope 1 at $DIR/self_assign.rs:+2:5: +2:14 -+ _2 = const 0_i32; // scope 1 at $DIR/self_assign.rs:+2:9: +2:10 -+ _1 = const 1_i32; // scope 1 at $DIR/self_assign.rs:+2:5: +2:14 + _2 = _1; // scope 1 at $DIR/self_assign.rs:+2:9: +2:10 + _1 = Add(move _2, const 1_i32); // scope 1 at $DIR/self_assign.rs:+2:5: +2:14 StorageDead(_2); // scope 1 at $DIR/self_assign.rs:+2:13: +2:14 StorageLive(_3); // scope 1 at $DIR/self_assign.rs:+3:9: +3:10 -- _3 = _1; // scope 1 at $DIR/self_assign.rs:+3:9: +3:10 -- _1 = move _3; // scope 1 at $DIR/self_assign.rs:+3:5: +3:10 -+ _3 = const 1_i32; // scope 1 at $DIR/self_assign.rs:+3:9: +3:10 -+ _1 = const 1_i32; // scope 1 at $DIR/self_assign.rs:+3:5: +3:10 + _3 = _1; // scope 1 at $DIR/self_assign.rs:+3:9: +3:10 + _1 = move _3; // scope 1 at $DIR/self_assign.rs:+3:5: +3:10 StorageDead(_3); // scope 1 at $DIR/self_assign.rs:+3:9: +3:10 StorageLive(_4); // scope 1 at $DIR/self_assign.rs:+5:9: +5:14 _4 = &_1; // scope 1 at $DIR/self_assign.rs:+5:17: +5:19 @@ -38,10 +34,8 @@ _4 = move _5; // scope 2 at $DIR/self_assign.rs:+6:5: +6:10 StorageDead(_5); // scope 2 at $DIR/self_assign.rs:+6:9: +6:10 StorageLive(_6); // scope 2 at $DIR/self_assign.rs:+7:9: +7:11 -- _6 = (*_4); // scope 2 at $DIR/self_assign.rs:+7:9: +7:11 -- _1 = move _6; // scope 2 at $DIR/self_assign.rs:+7:5: +7:11 -+ _6 = const 1_i32; // scope 2 at $DIR/self_assign.rs:+7:9: +7:11 -+ _1 = const 1_i32; // scope 2 at $DIR/self_assign.rs:+7:5: +7:11 + _6 = (*_4); // scope 2 at $DIR/self_assign.rs:+7:9: +7:11 + _1 = move _6; // scope 2 at $DIR/self_assign.rs:+7:5: +7:11 StorageDead(_6); // scope 2 at $DIR/self_assign.rs:+7:10: +7:11 _0 = const (); // scope 0 at $DIR/self_assign.rs:+0:11: +8:2 StorageDead(_4); // scope 1 at $DIR/self_assign.rs:+8:1: +8:2 diff --git a/src/test/mir-opt/dataflow-const-prop/self_assign.rs b/src/test/mir-opt/dataflow-const-prop/self_assign.rs index e8a62a8396043..8de2195f93ba4 100644 --- a/src/test/mir-opt/dataflow-const-prop/self_assign.rs +++ b/src/test/mir-opt/dataflow-const-prop/self_assign.rs @@ -1,5 +1,4 @@ // unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts // EMIT_MIR self_assign.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/self_assign_add.rs b/src/test/mir-opt/dataflow-const-prop/self_assign_add.rs index be2a4f04f6288..e3282762459a0 100644 --- a/src/test/mir-opt/dataflow-const-prop/self_assign_add.rs +++ b/src/test/mir-opt/dataflow-const-prop/self_assign_add.rs @@ -1,5 +1,4 @@ // unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts // EMIT_MIR self_assign_add.main.DataflowConstProp.diff fn main() { diff --git a/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff deleted file mode 100644 index 2d0d70b6a7428..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/static_ref.main.DataflowConstProp.diff +++ /dev/null @@ -1,53 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/static_ref.rs:+0:11: +0:11 - let _1: i32; // in scope 0 at $DIR/static_ref.rs:+3:9: +3:10 - let mut _3: &i32; // in scope 0 at $DIR/static_ref.rs:+5:9: +5:11 - let _4: &i32; // in scope 0 at $DIR/static_ref.rs:+5:9: +5:11 - let _5: &i32; // in scope 0 at $DIR/static_ref.rs:+5:10: +5:11 - scope 1 { - debug x => _1; // in scope 1 at $DIR/static_ref.rs:+3:9: +3:10 - let mut _2: &i32; // in scope 1 at $DIR/static_ref.rs:+4:9: +4:14 - scope 2 { - debug r => _2; // in scope 2 at $DIR/static_ref.rs:+4:9: +4:14 - let _6: i32; // in scope 2 at $DIR/static_ref.rs:+6:9: +6:10 - scope 3 { - debug y => _6; // in scope 3 at $DIR/static_ref.rs:+6:9: +6:10 - } - } - } - - bb0: { - StorageLive(_1); // scope 0 at $DIR/static_ref.rs:+3:9: +3:10 - _1 = const 0_i32; // scope 0 at $DIR/static_ref.rs:+3:13: +3:14 - StorageLive(_2); // scope 1 at $DIR/static_ref.rs:+4:9: +4:14 - _2 = &_1; // scope 1 at $DIR/static_ref.rs:+4:17: +4:19 - StorageLive(_3); // scope 2 at $DIR/static_ref.rs:+5:9: +5:11 - StorageLive(_4); // scope 2 at $DIR/static_ref.rs:+5:9: +5:11 - StorageLive(_5); // scope 2 at $DIR/static_ref.rs:+5:10: +5:11 - _5 = const {alloc1: &i32}; // scope 2 at $DIR/static_ref.rs:+5:10: +5:11 - // mir::Constant - // + span: $DIR/static_ref.rs:10:10: 10:11 - // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } - _4 = &(*_5); // scope 2 at $DIR/static_ref.rs:+5:9: +5:11 - _3 = &(*_4); // scope 2 at $DIR/static_ref.rs:+5:9: +5:11 - _2 = move _3; // scope 2 at $DIR/static_ref.rs:+5:5: +5:11 - StorageDead(_3); // scope 2 at $DIR/static_ref.rs:+5:10: +5:11 - StorageDead(_5); // scope 2 at $DIR/static_ref.rs:+5:11: +5:12 - StorageDead(_4); // scope 2 at $DIR/static_ref.rs:+5:11: +5:12 - StorageLive(_6); // scope 2 at $DIR/static_ref.rs:+6:9: +6:10 - _6 = (*_2); // scope 2 at $DIR/static_ref.rs:+6:13: +6:15 - _0 = const (); // scope 0 at $DIR/static_ref.rs:+0:11: +7:2 - StorageDead(_6); // scope 2 at $DIR/static_ref.rs:+7:1: +7:2 - StorageDead(_2); // scope 1 at $DIR/static_ref.rs:+7:1: +7:2 - StorageDead(_1); // scope 0 at $DIR/static_ref.rs:+7:1: +7:2 - return; // scope 0 at $DIR/static_ref.rs:+7:2: +7:2 - } - } - - alloc1 (static: P, size: 4, align: 4) { - 05 00 00 00 │ .... - } - diff --git a/src/test/mir-opt/dataflow-const-prop/static_ref.rs b/src/test/mir-opt/dataflow-const-prop/static_ref.rs deleted file mode 100644 index 90f20ae51ceb9..0000000000000 --- a/src/test/mir-opt/dataflow-const-prop/static_ref.rs +++ /dev/null @@ -1,12 +0,0 @@ -// unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts - -// EMIT_MIR static_ref.main.DataflowConstProp.diff -fn main() { - // Currently, this will not propagate. - static P: i32 = 5; - let x = 0; - let mut r = &x; - r = &P; - let y = *r; -} diff --git a/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff index d1b8895901eaa..8018400e798a7 100644 --- a/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff @@ -4,9 +4,9 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/terminator.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/terminator.rs:+1:9: +1:10 - let _2: (); // in scope 0 at $DIR/terminator.rs:+2:5: +2:15 - let mut _3: i32; // in scope 0 at $DIR/terminator.rs:+2:9: +2:14 - let mut _4: i32; // in scope 0 at $DIR/terminator.rs:+2:9: +2:10 + let _2: (); // in scope 0 at $DIR/terminator.rs:+3:5: +3:15 + let mut _3: i32; // in scope 0 at $DIR/terminator.rs:+3:9: +3:14 + let mut _4: i32; // in scope 0 at $DIR/terminator.rs:+3:9: +3:10 scope 1 { debug a => _1; // in scope 1 at $DIR/terminator.rs:+1:9: +1:10 } @@ -14,27 +14,27 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/terminator.rs:+1:9: +1:10 _1 = const 1_i32; // scope 0 at $DIR/terminator.rs:+1:13: +1:14 - StorageLive(_2); // scope 1 at $DIR/terminator.rs:+2:5: +2:15 - StorageLive(_3); // scope 1 at $DIR/terminator.rs:+2:9: +2:14 - StorageLive(_4); // scope 1 at $DIR/terminator.rs:+2:9: +2:10 -- _4 = _1; // scope 1 at $DIR/terminator.rs:+2:9: +2:10 -- _3 = Add(move _4, const 1_i32); // scope 1 at $DIR/terminator.rs:+2:9: +2:14 -+ _4 = const 1_i32; // scope 1 at $DIR/terminator.rs:+2:9: +2:10 -+ _3 = const 2_i32; // scope 1 at $DIR/terminator.rs:+2:9: +2:14 - StorageDead(_4); // scope 1 at $DIR/terminator.rs:+2:13: +2:14 -- _2 = foo(move _3) -> bb1; // scope 1 at $DIR/terminator.rs:+2:5: +2:15 -+ _2 = foo(const 2_i32) -> bb1; // scope 1 at $DIR/terminator.rs:+2:5: +2:15 + StorageLive(_2); // scope 1 at $DIR/terminator.rs:+3:5: +3:15 + StorageLive(_3); // scope 1 at $DIR/terminator.rs:+3:9: +3:14 + StorageLive(_4); // scope 1 at $DIR/terminator.rs:+3:9: +3:10 +- _4 = _1; // scope 1 at $DIR/terminator.rs:+3:9: +3:10 +- _3 = Add(move _4, const 1_i32); // scope 1 at $DIR/terminator.rs:+3:9: +3:14 ++ _4 = const 1_i32; // scope 1 at $DIR/terminator.rs:+3:9: +3:10 ++ _3 = const 2_i32; // scope 1 at $DIR/terminator.rs:+3:9: +3:14 + StorageDead(_4); // scope 1 at $DIR/terminator.rs:+3:13: +3:14 +- _2 = foo(move _3) -> bb1; // scope 1 at $DIR/terminator.rs:+3:5: +3:15 ++ _2 = foo(const 2_i32) -> bb1; // scope 1 at $DIR/terminator.rs:+3:5: +3:15 // mir::Constant // + span: $DIR/terminator.rs:9:5: 9:8 // + literal: Const { ty: fn(i32) {foo}, val: Value() } } bb1: { - StorageDead(_3); // scope 1 at $DIR/terminator.rs:+2:14: +2:15 - StorageDead(_2); // scope 1 at $DIR/terminator.rs:+2:15: +2:16 - _0 = const (); // scope 0 at $DIR/terminator.rs:+0:11: +3:2 - StorageDead(_1); // scope 0 at $DIR/terminator.rs:+3:1: +3:2 - return; // scope 0 at $DIR/terminator.rs:+3:2: +3:2 + StorageDead(_3); // scope 1 at $DIR/terminator.rs:+3:14: +3:15 + StorageDead(_2); // scope 1 at $DIR/terminator.rs:+3:15: +3:16 + _0 = const (); // scope 0 at $DIR/terminator.rs:+0:11: +4:2 + StorageDead(_1); // scope 0 at $DIR/terminator.rs:+4:1: +4:2 + return; // scope 0 at $DIR/terminator.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/terminator.rs b/src/test/mir-opt/dataflow-const-prop/terminator.rs index 7d8bb58f684eb..d151f666a2dc2 100644 --- a/src/test/mir-opt/dataflow-const-prop/terminator.rs +++ b/src/test/mir-opt/dataflow-const-prop/terminator.rs @@ -1,10 +1,10 @@ // unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts fn foo(n: i32) {} // EMIT_MIR terminator.main.DataflowConstProp.diff fn main() { let a = 1; + // Checks that we propagate into terminators. foo(a + 1); } diff --git a/src/test/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff index 7fb1c8b7cafb6..e028def00a116 100644 --- a/src/test/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff @@ -4,26 +4,21 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/tuple.rs:+0:11: +0:11 let mut _1: (i32, i32); // in scope 0 at $DIR/tuple.rs:+1:9: +1:14 - let mut _4: i32; // in scope 0 at $DIR/tuple.rs:+3:13: +3:22 - let mut _5: i32; // in scope 0 at $DIR/tuple.rs:+3:13: +3:16 - let mut _6: i32; // in scope 0 at $DIR/tuple.rs:+3:19: +3:22 - let mut _7: &(i32, i32); // in scope 0 at $DIR/tuple.rs:+5:9: +5:11 - let _8: &(i32, i32); // in scope 0 at $DIR/tuple.rs:+5:9: +5:11 - let mut _10: i32; // in scope 0 at $DIR/tuple.rs:+6:13: +6:22 - let mut _11: i32; // in scope 0 at $DIR/tuple.rs:+6:13: +6:16 - let mut _12: i32; // in scope 0 at $DIR/tuple.rs:+6:19: +6:22 + let mut _3: i32; // in scope 0 at $DIR/tuple.rs:+2:13: +2:22 + let mut _4: i32; // in scope 0 at $DIR/tuple.rs:+2:13: +2:16 + let mut _5: i32; // in scope 0 at $DIR/tuple.rs:+2:19: +2:22 + let mut _7: i32; // in scope 0 at $DIR/tuple.rs:+4:13: +4:22 + let mut _8: i32; // in scope 0 at $DIR/tuple.rs:+4:13: +4:16 + let mut _9: i32; // in scope 0 at $DIR/tuple.rs:+4:19: +4:22 + let mut _10: i32; // in scope 0 at $DIR/tuple.rs:+4:25: +4:26 scope 1 { debug a => _1; // in scope 1 at $DIR/tuple.rs:+1:9: +1:14 - let mut _2: &(i32, i32); // in scope 1 at $DIR/tuple.rs:+2:9: +2:14 + let _2: i32; // in scope 1 at $DIR/tuple.rs:+2:9: +2:10 scope 2 { - debug b => _2; // in scope 2 at $DIR/tuple.rs:+2:9: +2:14 - let _3: i32; // in scope 2 at $DIR/tuple.rs:+3:9: +3:10 + debug b => _2; // in scope 2 at $DIR/tuple.rs:+2:9: +2:10 + let _6: i32; // in scope 2 at $DIR/tuple.rs:+4:9: +4:10 scope 3 { - debug c => _3; // in scope 3 at $DIR/tuple.rs:+3:9: +3:10 - let _9: i32; // in scope 3 at $DIR/tuple.rs:+6:9: +6:10 - scope 4 { - debug d => _9; // in scope 4 at $DIR/tuple.rs:+6:9: +6:10 - } + debug c => _6; // in scope 3 at $DIR/tuple.rs:+4:9: +4:10 } } } @@ -33,54 +28,48 @@ Deinit(_1); // scope 0 at $DIR/tuple.rs:+1:17: +1:23 (_1.0: i32) = const 1_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23 (_1.1: i32) = const 2_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23 - StorageLive(_2); // scope 1 at $DIR/tuple.rs:+2:9: +2:14 - _2 = &_1; // scope 1 at $DIR/tuple.rs:+2:17: +2:19 - StorageLive(_3); // scope 2 at $DIR/tuple.rs:+3:9: +3:10 - StorageLive(_4); // scope 2 at $DIR/tuple.rs:+3:13: +3:22 - StorageLive(_5); // scope 2 at $DIR/tuple.rs:+3:13: +3:16 -- _5 = (_1.0: i32); // scope 2 at $DIR/tuple.rs:+3:13: +3:16 -+ _5 = const 1_i32; // scope 2 at $DIR/tuple.rs:+3:13: +3:16 - StorageLive(_6); // scope 2 at $DIR/tuple.rs:+3:19: +3:22 -- _6 = ((*_2).1: i32); // scope 2 at $DIR/tuple.rs:+3:19: +3:22 -- _4 = Add(move _5, move _6); // scope 2 at $DIR/tuple.rs:+3:13: +3:22 -+ _6 = const 2_i32; // scope 2 at $DIR/tuple.rs:+3:19: +3:22 -+ _4 = const 3_i32; // scope 2 at $DIR/tuple.rs:+3:13: +3:22 - StorageDead(_6); // scope 2 at $DIR/tuple.rs:+3:21: +3:22 - StorageDead(_5); // scope 2 at $DIR/tuple.rs:+3:21: +3:22 -- _3 = Add(move _4, const 3_i32); // scope 2 at $DIR/tuple.rs:+3:13: +3:26 -+ _3 = const 6_i32; // scope 2 at $DIR/tuple.rs:+3:13: +3:26 - StorageDead(_4); // scope 2 at $DIR/tuple.rs:+3:25: +3:26 - Deinit(_1); // scope 3 at $DIR/tuple.rs:+4:5: +4:15 - (_1.0: i32) = const 2_i32; // scope 3 at $DIR/tuple.rs:+4:5: +4:15 - (_1.1: i32) = const 3_i32; // scope 3 at $DIR/tuple.rs:+4:5: +4:15 - StorageLive(_7); // scope 3 at $DIR/tuple.rs:+5:9: +5:11 - StorageLive(_8); // scope 3 at $DIR/tuple.rs:+5:9: +5:11 - _8 = &_1; // scope 3 at $DIR/tuple.rs:+5:9: +5:11 - _7 = &(*_8); // scope 3 at $DIR/tuple.rs:+5:9: +5:11 - _2 = move _7; // scope 3 at $DIR/tuple.rs:+5:5: +5:11 - StorageDead(_7); // scope 3 at $DIR/tuple.rs:+5:10: +5:11 - StorageDead(_8); // scope 3 at $DIR/tuple.rs:+5:11: +5:12 - StorageLive(_9); // scope 3 at $DIR/tuple.rs:+6:9: +6:10 - StorageLive(_10); // scope 3 at $DIR/tuple.rs:+6:13: +6:22 - StorageLive(_11); // scope 3 at $DIR/tuple.rs:+6:13: +6:16 -- _11 = (_1.0: i32); // scope 3 at $DIR/tuple.rs:+6:13: +6:16 -+ _11 = const 2_i32; // scope 3 at $DIR/tuple.rs:+6:13: +6:16 - StorageLive(_12); // scope 3 at $DIR/tuple.rs:+6:19: +6:22 -- _12 = ((*_2).1: i32); // scope 3 at $DIR/tuple.rs:+6:19: +6:22 -- _10 = Add(move _11, move _12); // scope 3 at $DIR/tuple.rs:+6:13: +6:22 -+ _12 = const 3_i32; // scope 3 at $DIR/tuple.rs:+6:19: +6:22 -+ _10 = const 5_i32; // scope 3 at $DIR/tuple.rs:+6:13: +6:22 - StorageDead(_12); // scope 3 at $DIR/tuple.rs:+6:21: +6:22 - StorageDead(_11); // scope 3 at $DIR/tuple.rs:+6:21: +6:22 -- _9 = Add(move _10, const 4_i32); // scope 3 at $DIR/tuple.rs:+6:13: +6:26 -+ _9 = const 9_i32; // scope 3 at $DIR/tuple.rs:+6:13: +6:26 - StorageDead(_10); // scope 3 at $DIR/tuple.rs:+6:25: +6:26 - _0 = const (); // scope 0 at $DIR/tuple.rs:+0:11: +7:2 - StorageDead(_9); // scope 3 at $DIR/tuple.rs:+7:1: +7:2 - StorageDead(_3); // scope 2 at $DIR/tuple.rs:+7:1: +7:2 - StorageDead(_2); // scope 1 at $DIR/tuple.rs:+7:1: +7:2 - StorageDead(_1); // scope 0 at $DIR/tuple.rs:+7:1: +7:2 - return; // scope 0 at $DIR/tuple.rs:+7:2: +7:2 + StorageLive(_2); // scope 1 at $DIR/tuple.rs:+2:9: +2:10 + StorageLive(_3); // scope 1 at $DIR/tuple.rs:+2:13: +2:22 + StorageLive(_4); // scope 1 at $DIR/tuple.rs:+2:13: +2:16 +- _4 = (_1.0: i32); // scope 1 at $DIR/tuple.rs:+2:13: +2:16 ++ _4 = const 1_i32; // scope 1 at $DIR/tuple.rs:+2:13: +2:16 + StorageLive(_5); // scope 1 at $DIR/tuple.rs:+2:19: +2:22 +- _5 = (_1.1: i32); // scope 1 at $DIR/tuple.rs:+2:19: +2:22 +- _3 = Add(move _4, move _5); // scope 1 at $DIR/tuple.rs:+2:13: +2:22 ++ _5 = const 2_i32; // scope 1 at $DIR/tuple.rs:+2:19: +2:22 ++ _3 = const 3_i32; // scope 1 at $DIR/tuple.rs:+2:13: +2:22 + StorageDead(_5); // scope 1 at $DIR/tuple.rs:+2:21: +2:22 + StorageDead(_4); // scope 1 at $DIR/tuple.rs:+2:21: +2:22 +- _2 = Add(move _3, const 3_i32); // scope 1 at $DIR/tuple.rs:+2:13: +2:26 ++ _2 = const 6_i32; // scope 1 at $DIR/tuple.rs:+2:13: +2:26 + StorageDead(_3); // scope 1 at $DIR/tuple.rs:+2:25: +2:26 + Deinit(_1); // scope 2 at $DIR/tuple.rs:+3:5: +3:15 + (_1.0: i32) = const 2_i32; // scope 2 at $DIR/tuple.rs:+3:5: +3:15 + (_1.1: i32) = const 3_i32; // scope 2 at $DIR/tuple.rs:+3:5: +3:15 + StorageLive(_6); // scope 2 at $DIR/tuple.rs:+4:9: +4:10 + StorageLive(_7); // scope 2 at $DIR/tuple.rs:+4:13: +4:22 + StorageLive(_8); // scope 2 at $DIR/tuple.rs:+4:13: +4:16 +- _8 = (_1.0: i32); // scope 2 at $DIR/tuple.rs:+4:13: +4:16 ++ _8 = const 2_i32; // scope 2 at $DIR/tuple.rs:+4:13: +4:16 + StorageLive(_9); // scope 2 at $DIR/tuple.rs:+4:19: +4:22 +- _9 = (_1.1: i32); // scope 2 at $DIR/tuple.rs:+4:19: +4:22 +- _7 = Add(move _8, move _9); // scope 2 at $DIR/tuple.rs:+4:13: +4:22 ++ _9 = const 3_i32; // scope 2 at $DIR/tuple.rs:+4:19: +4:22 ++ _7 = const 5_i32; // scope 2 at $DIR/tuple.rs:+4:13: +4:22 + StorageDead(_9); // scope 2 at $DIR/tuple.rs:+4:21: +4:22 + StorageDead(_8); // scope 2 at $DIR/tuple.rs:+4:21: +4:22 + StorageLive(_10); // scope 2 at $DIR/tuple.rs:+4:25: +4:26 +- _10 = _2; // scope 2 at $DIR/tuple.rs:+4:25: +4:26 +- _6 = Add(move _7, move _10); // scope 2 at $DIR/tuple.rs:+4:13: +4:26 ++ _10 = const 6_i32; // scope 2 at $DIR/tuple.rs:+4:25: +4:26 ++ _6 = const 11_i32; // scope 2 at $DIR/tuple.rs:+4:13: +4:26 + StorageDead(_10); // scope 2 at $DIR/tuple.rs:+4:25: +4:26 + StorageDead(_7); // scope 2 at $DIR/tuple.rs:+4:25: +4:26 + _0 = const (); // scope 0 at $DIR/tuple.rs:+0:11: +5:2 + StorageDead(_6); // scope 2 at $DIR/tuple.rs:+5:1: +5:2 + StorageDead(_2); // scope 1 at $DIR/tuple.rs:+5:1: +5:2 + StorageDead(_1); // scope 0 at $DIR/tuple.rs:+5:1: +5:2 + return; // scope 0 at $DIR/tuple.rs:+5:2: +5:2 } } diff --git a/src/test/mir-opt/dataflow-const-prop/tuple.rs b/src/test/mir-opt/dataflow-const-prop/tuple.rs index dfc49fe857ab0..92c70eab0ff6f 100644 --- a/src/test/mir-opt/dataflow-const-prop/tuple.rs +++ b/src/test/mir-opt/dataflow-const-prop/tuple.rs @@ -1,12 +1,9 @@ // unit-test: DataflowConstProp -// compile-flags: -Zunsound-mir-opts // EMIT_MIR tuple.main.DataflowConstProp.diff fn main() { let mut a = (1, 2); - let mut b = &a; - let c = a.0 + b.1 + 3; + let b = a.0 + a.1 + 3; a = (2, 3); - b = &a; - let d = a.0 + b.1 + 4; + let c = a.0 + a.1 + b; } From 9766ee0b2040d93c7ff4af237c3c839d54adf8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 9 Nov 2022 18:21:42 +0100 Subject: [PATCH 65/76] Fix struct field tracking and add tests for it --- .../rustc_mir_dataflow/src/value_analysis.rs | 14 ++--- .../src/dataflow_const_prop.rs | 4 +- .../enum.main.DataflowConstProp.diff | 61 +++++++++++++++++++ src/test/mir-opt/dataflow-const-prop/enum.rs | 13 ++++ .../struct.main.DataflowConstProp.diff | 52 ++++++++++++++++ .../mir-opt/dataflow-const-prop/struct.rs | 11 ++++ 6 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/enum.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/struct.rs diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index f428cd5ee8223..17d349fb52699 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -151,9 +151,7 @@ pub trait ValueAnalysis<'tcx> { ) -> ValueOrPlace { match rvalue { Rvalue::Use(operand) => self.handle_operand(operand, state), - Rvalue::CopyForDeref(place) => { - self.handle_operand(&Operand::Copy(*place), state) - } + Rvalue::CopyForDeref(place) => self.handle_operand(&Operand::Copy(*place), state), Rvalue::Ref(..) | Rvalue::AddressOf(..) => { // We don't track such places. ValueOrPlace::top() @@ -638,9 +636,7 @@ impl Map { return; } projection.push(PlaceElem::Field(field, ty)); - self.register_with_filter_rec( - tcx, local, projection, ty, filter, exclude, - ); + self.register_with_filter_rec(tcx, local, projection, ty, filter, exclude); projection.pop(); }); } @@ -842,13 +838,17 @@ fn iter_fields<'tcx>( } } ty::Adt(def, substs) => { + if def.is_union() { + return; + } for (v_index, v_def) in def.variants().iter_enumerated() { + let variant = if def.is_struct() { None } else { Some(v_index) }; for (f_index, f_def) in v_def.fields.iter().enumerate() { let field_ty = f_def.ty(tcx, substs); let field_ty = tcx .try_normalize_erasing_regions(ty::ParamEnv::reveal_all(), field_ty) .unwrap_or(field_ty); - f(Some(v_index), f_index.into(), field_ty); + f(variant, f_index.into(), field_ty); } } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index e88125777f142..e1c7b6ab1803a 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -7,9 +7,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::visit::{MutVisitor, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_mir_dataflow::value_analysis::{ - Map, State, TrackElem, ValueAnalysis, ValueOrPlace, -}; +use rustc_mir_dataflow::value_analysis::{Map, State, TrackElem, ValueAnalysis, ValueOrPlace}; use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects}; use rustc_span::DUMMY_SP; diff --git a/src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..2ced794e628f0 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff @@ -0,0 +1,61 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/enum.rs:+0:11: +0:11 + let _1: E; // in scope 0 at $DIR/enum.rs:+1:9: +1:10 + let mut _3: isize; // in scope 0 at $DIR/enum.rs:+2:23: +2:31 + scope 1 { + debug e => _1; // in scope 1 at $DIR/enum.rs:+1:9: +1:10 + let _2: i32; // in scope 1 at $DIR/enum.rs:+2:9: +2:10 + let _4: i32; // in scope 1 at $DIR/enum.rs:+2:29: +2:30 + let _5: i32; // in scope 1 at $DIR/enum.rs:+2:44: +2:45 + scope 2 { + debug x => _2; // in scope 2 at $DIR/enum.rs:+2:9: +2:10 + } + scope 3 { + debug x => _4; // in scope 3 at $DIR/enum.rs:+2:29: +2:30 + } + scope 4 { + debug x => _5; // in scope 4 at $DIR/enum.rs:+2:44: +2:45 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum.rs:+1:9: +1:10 + Deinit(_1); // scope 0 at $DIR/enum.rs:+1:13: +1:21 + ((_1 as V1).0: i32) = const 0_i32; // scope 0 at $DIR/enum.rs:+1:13: +1:21 + discriminant(_1) = 0; // scope 0 at $DIR/enum.rs:+1:13: +1:21 + StorageLive(_2); // scope 1 at $DIR/enum.rs:+2:9: +2:10 + _3 = discriminant(_1); // scope 1 at $DIR/enum.rs:+2:19: +2:20 + switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20 + } + + bb1: { + StorageLive(_5); // scope 1 at $DIR/enum.rs:+2:44: +2:45 + _5 = ((_1 as V2).0: i32); // scope 1 at $DIR/enum.rs:+2:44: +2:45 + _2 = _5; // scope 4 at $DIR/enum.rs:+2:50: +2:51 + StorageDead(_5); // scope 1 at $DIR/enum.rs:+2:50: +2:51 + goto -> bb4; // scope 1 at $DIR/enum.rs:+2:50: +2:51 + } + + bb2: { + unreachable; // scope 1 at $DIR/enum.rs:+2:19: +2:20 + } + + bb3: { + StorageLive(_4); // scope 1 at $DIR/enum.rs:+2:29: +2:30 + _4 = ((_1 as V1).0: i32); // scope 1 at $DIR/enum.rs:+2:29: +2:30 + _2 = _4; // scope 3 at $DIR/enum.rs:+2:35: +2:36 + StorageDead(_4); // scope 1 at $DIR/enum.rs:+2:35: +2:36 + goto -> bb4; // scope 1 at $DIR/enum.rs:+2:35: +2:36 + } + + bb4: { + _0 = const (); // scope 0 at $DIR/enum.rs:+0:11: +3:2 + StorageDead(_2); // scope 1 at $DIR/enum.rs:+3:1: +3:2 + StorageDead(_1); // scope 0 at $DIR/enum.rs:+3:1: +3:2 + return; // scope 0 at $DIR/enum.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/enum.rs b/src/test/mir-opt/dataflow-const-prop/enum.rs new file mode 100644 index 0000000000000..13288577dea3f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/enum.rs @@ -0,0 +1,13 @@ +// unit-test: DataflowConstProp + +// Not trackable, because variants could be aliased. +enum E { + V1(i32), + V2(i32) +} + +// EMIT_MIR enum.main.DataflowConstProp.diff +fn main() { + let e = E::V1(0); + let x = match e { E::V1(x) => x, E::V2(x) => x }; +} diff --git a/src/test/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..cfb2706c167cd --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff @@ -0,0 +1,52 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/struct.rs:+0:11: +0:11 + let mut _1: S; // in scope 0 at $DIR/struct.rs:+1:9: +1:14 + let mut _3: i32; // in scope 0 at $DIR/struct.rs:+2:13: +2:16 + let mut _5: i32; // in scope 0 at $DIR/struct.rs:+4:13: +4:14 + let mut _6: i32; // in scope 0 at $DIR/struct.rs:+4:17: +4:20 + scope 1 { + debug s => _1; // in scope 1 at $DIR/struct.rs:+1:9: +1:14 + let _2: i32; // in scope 1 at $DIR/struct.rs:+2:9: +2:10 + scope 2 { + debug a => _2; // in scope 2 at $DIR/struct.rs:+2:9: +2:10 + let _4: i32; // in scope 2 at $DIR/struct.rs:+4:9: +4:10 + scope 3 { + debug b => _4; // in scope 3 at $DIR/struct.rs:+4:9: +4:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/struct.rs:+1:9: +1:14 + Deinit(_1); // scope 0 at $DIR/struct.rs:+1:17: +1:21 + (_1.0: i32) = const 1_i32; // scope 0 at $DIR/struct.rs:+1:17: +1:21 + StorageLive(_2); // scope 1 at $DIR/struct.rs:+2:9: +2:10 + StorageLive(_3); // scope 1 at $DIR/struct.rs:+2:13: +2:16 +- _3 = (_1.0: i32); // scope 1 at $DIR/struct.rs:+2:13: +2:16 +- _2 = Add(move _3, const 2_i32); // scope 1 at $DIR/struct.rs:+2:13: +2:20 ++ _3 = const 1_i32; // scope 1 at $DIR/struct.rs:+2:13: +2:16 ++ _2 = const 3_i32; // scope 1 at $DIR/struct.rs:+2:13: +2:20 + StorageDead(_3); // scope 1 at $DIR/struct.rs:+2:19: +2:20 + (_1.0: i32) = const 3_i32; // scope 2 at $DIR/struct.rs:+3:5: +3:12 + StorageLive(_4); // scope 2 at $DIR/struct.rs:+4:9: +4:10 + StorageLive(_5); // scope 2 at $DIR/struct.rs:+4:13: +4:14 +- _5 = _2; // scope 2 at $DIR/struct.rs:+4:13: +4:14 ++ _5 = const 3_i32; // scope 2 at $DIR/struct.rs:+4:13: +4:14 + StorageLive(_6); // scope 2 at $DIR/struct.rs:+4:17: +4:20 +- _6 = (_1.0: i32); // scope 2 at $DIR/struct.rs:+4:17: +4:20 +- _4 = Add(move _5, move _6); // scope 2 at $DIR/struct.rs:+4:13: +4:20 ++ _6 = const 3_i32; // scope 2 at $DIR/struct.rs:+4:17: +4:20 ++ _4 = const 6_i32; // scope 2 at $DIR/struct.rs:+4:13: +4:20 + StorageDead(_6); // scope 2 at $DIR/struct.rs:+4:19: +4:20 + StorageDead(_5); // scope 2 at $DIR/struct.rs:+4:19: +4:20 + _0 = const (); // scope 0 at $DIR/struct.rs:+0:11: +5:2 + StorageDead(_4); // scope 2 at $DIR/struct.rs:+5:1: +5:2 + StorageDead(_2); // scope 1 at $DIR/struct.rs:+5:1: +5:2 + StorageDead(_1); // scope 0 at $DIR/struct.rs:+5:1: +5:2 + return; // scope 0 at $DIR/struct.rs:+5:2: +5:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/struct.rs b/src/test/mir-opt/dataflow-const-prop/struct.rs new file mode 100644 index 0000000000000..841b279e03eee --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/struct.rs @@ -0,0 +1,11 @@ +// unit-test: DataflowConstProp + +struct S(i32); + +// EMIT_MIR struct.main.DataflowConstProp.diff +fn main() { + let mut s = S(1); + let a = s.0 + 2; + s.0 = 3; + let b = a + s.0; +} From 8ecb276735f61ef3822b5ed6a48d1c8fd591b79b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Thu, 10 Nov 2022 19:12:10 +0100 Subject: [PATCH 66/76] Simplify creation of map --- .../rustc_mir_dataflow/src/value_analysis.rs | 77 ++++++------------- .../src/dataflow_const_prop.rs | 2 +- 2 files changed, 26 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 17d349fb52699..13072a30282c4 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -36,7 +36,6 @@ use std::fmt::{Debug, Formatter}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::vec::IndexVec; -use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -552,9 +551,10 @@ impl JoinSemiLattice for State { } } -/// A partial mapping from `Place` to `PlaceIndex`, where some place indices have value indices. +/// Partial mapping from [`Place`] to [`PlaceIndex`], where some places also have a [`ValueIndex`]. /// -/// Some additional bookkeeping is done to speed up traversal: +/// This data structure essentially maintains a tree of places and their projections. Some +/// additional bookkeeping is done, to speed up traversal over this tree: /// - For iteration, every [`PlaceInfo`] contains an intrusive linked list of its children. /// - To directly get the child for a specific projection, there is a `projections` map. #[derive(Debug)] @@ -578,7 +578,8 @@ impl Map { /// Returns a map that only tracks places whose type passes the filter. /// /// This is currently the only way to create a [`Map`]. The way in which the tracked places are - /// chosen is an implementation detail and may not be relied upon. + /// chosen is an implementation detail and may not be relied upon (other than that their type + /// passes the filter). #[instrument(skip_all, level = "debug")] pub fn from_filter<'tcx>( tcx: TyCtxt<'tcx>, @@ -599,6 +600,7 @@ impl Map { mut filter: impl FnMut(Ty<'tcx>) -> bool, exclude: &FxHashSet>, ) { + // We use this vector as stack, pushing and popping projections. let mut projection = Vec::new(); for (local, decl) in body.local_decls.iter_enumerated() { self.register_with_filter_rec( @@ -612,6 +614,9 @@ impl Map { } } + /// Register fields of the given (local, projection) place. + /// + /// Invariant: The projection must only contain fields. fn register_with_filter_rec<'tcx>( &mut self, tcx: TyCtxt<'tcx>, @@ -626,10 +631,19 @@ impl Map { return; } - if filter(ty) { - // This might fail if `ty` is not scalar. - let _ = self.register_with_ty(local, projection, ty); + // Note: The framework supports only scalars for now. + if filter(ty) && ty.is_scalar() { + // We know that the projection only contains trackable elements. + let place = self.make_place(local, projection).unwrap(); + + // Allocate a value slot if it doesn't have one. + if self.places[place].value_index.is_none() { + self.places[place].value_index = Some(self.value_count.into()); + self.value_count += 1; + } } + + // Recurse with all fields of this place. iter_fields(ty, tcx, |variant, field, ty| { if variant.is_some() { // Downcasts are currently not supported. @@ -668,59 +682,17 @@ impl Map { Ok(index) } - #[allow(unused)] - fn register<'tcx>( - &mut self, - local: Local, - projection: &[PlaceElem<'tcx>], - decls: &impl HasLocalDecls<'tcx>, - tcx: TyCtxt<'tcx>, - ) -> Result<(), ()> { - projection - .iter() - .fold(PlaceTy::from_ty(decls.local_decls()[local].ty), |place_ty, &elem| { - place_ty.projection_ty(tcx, elem) - }); - - let place_ty = Place::ty_from(local, projection, decls, tcx); - if place_ty.variant_index.is_some() { - return Err(()); - } - self.register_with_ty(local, projection, place_ty.ty) - } - - /// Tries to track the given place. Fails if type is non-scalar or projection is not trackable. - fn register_with_ty<'tcx>( - &mut self, - local: Local, - projection: &[PlaceElem<'tcx>], - ty: Ty<'tcx>, - ) -> Result<(), ()> { - if !ty.is_scalar() { - // Currently, only scalar types are allowed, because they are atomic - // and therefore do not require invalidation of parent places. - return Err(()); - } - - let place = self.make_place(local, projection)?; - - // Allocate a value slot if it doesn't have one. - if self.places[place].value_index.is_none() { - self.places[place].value_index = Some(self.value_count.into()); - self.value_count += 1; - } - - Ok(()) - } - + /// Returns the number of tracked places, i.e., those for which a value can be stored. pub fn tracked_places(&self) -> usize { self.value_count } + /// Applies a single projection element, yielding the corresponding child. pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option { self.projections.get(&(place, elem)).copied() } + /// Locates the given place, if it exists in the tree. pub fn find(&self, place: PlaceRef<'_>) -> Option { let mut index = *self.locals.get(place.local)?.as_ref()?; @@ -736,6 +708,7 @@ impl Map { Children::new(self, parent) } + /// Invoke a function on the given place and all descendants. pub fn preorder_invoke(&self, root: PlaceIndex, f: &mut impl FnMut(PlaceIndex)) { f(root); for child in self.children(root) { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index e1c7b6ab1803a..2ed8a6f161f7f 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -105,7 +105,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> { FlatSet::Top => FlatSet::Top, FlatSet::Elem(overflow) => { if overflow { - // Overflow cannot be reliable propagated. See: https://github.com/rust-lang/rust/pull/101168#issuecomment-1288091446 + // Overflow cannot be reliably propagated. See: https://github.com/rust-lang/rust/pull/101168#issuecomment-1288091446 FlatSet::Top } else { self.wrap_scalar(Scalar::from_bool(false), self.tcx.types.bool) From 3c6d1a723d2d6466d8ee34d4f442a60fdc8cfa1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Fri, 11 Nov 2022 11:24:31 +0100 Subject: [PATCH 67/76] Add test for repr(transparent) with scalar --- .../rustc_mir_dataflow/src/value_analysis.rs | 7 ++- ...pr_transparent.main.DataflowConstProp.diff | 44 +++++++++++++++++++ .../dataflow-const-prop/repr_transparent.rs | 12 +++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/test/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/repr_transparent.rs diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 13072a30282c4..0f3b952ceec84 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -614,7 +614,7 @@ impl Map { } } - /// Register fields of the given (local, projection) place. + /// Potentially register the (local, projection) place and its fields, recursively. /// /// Invariant: The projection must only contain fields. fn register_with_filter_rec<'tcx>( @@ -626,13 +626,16 @@ impl Map { filter: &mut impl FnMut(Ty<'tcx>) -> bool, exclude: &FxHashSet>, ) { - if exclude.contains(&Place { local, projection: tcx.intern_place_elems(projection) }) { + let place = Place { local, projection: tcx.intern_place_elems(projection) }; + if exclude.contains(&place) { // This will also exclude all projections of the excluded place. return; } // Note: The framework supports only scalars for now. if filter(ty) && ty.is_scalar() { + trace!("registering place: {:?}", place); + // We know that the projection only contains trackable elements. let place = self.make_place(local, projection).unwrap(); diff --git a/src/test/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..f66b00a9a224b --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff @@ -0,0 +1,44 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/repr_transparent.rs:+0:11: +0:11 + let _1: I32; // in scope 0 at $DIR/repr_transparent.rs:+1:9: +1:10 + let mut _3: i32; // in scope 0 at $DIR/repr_transparent.rs:+2:17: +2:26 + let mut _4: i32; // in scope 0 at $DIR/repr_transparent.rs:+2:17: +2:20 + let mut _5: i32; // in scope 0 at $DIR/repr_transparent.rs:+2:23: +2:26 + scope 1 { + debug x => _1; // in scope 1 at $DIR/repr_transparent.rs:+1:9: +1:10 + let _2: I32; // in scope 1 at $DIR/repr_transparent.rs:+2:9: +2:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/repr_transparent.rs:+2:9: +2:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/repr_transparent.rs:+1:9: +1:10 + Deinit(_1); // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19 + (_1.0: i32) = const 0_i32; // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19 + StorageLive(_2); // scope 1 at $DIR/repr_transparent.rs:+2:9: +2:10 + StorageLive(_3); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26 + StorageLive(_4); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:20 +- _4 = (_1.0: i32); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:20 ++ _4 = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:20 + StorageLive(_5); // scope 1 at $DIR/repr_transparent.rs:+2:23: +2:26 +- _5 = (_1.0: i32); // scope 1 at $DIR/repr_transparent.rs:+2:23: +2:26 +- _3 = Add(move _4, move _5); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26 ++ _5 = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:23: +2:26 ++ _3 = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26 + StorageDead(_5); // scope 1 at $DIR/repr_transparent.rs:+2:25: +2:26 + StorageDead(_4); // scope 1 at $DIR/repr_transparent.rs:+2:25: +2:26 + Deinit(_2); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27 +- (_2.0: i32) = move _3; // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27 ++ (_2.0: i32) = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27 + StorageDead(_3); // scope 1 at $DIR/repr_transparent.rs:+2:26: +2:27 + _0 = const (); // scope 0 at $DIR/repr_transparent.rs:+0:11: +3:2 + StorageDead(_2); // scope 1 at $DIR/repr_transparent.rs:+3:1: +3:2 + StorageDead(_1); // scope 0 at $DIR/repr_transparent.rs:+3:1: +3:2 + return; // scope 0 at $DIR/repr_transparent.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/repr_transparent.rs b/src/test/mir-opt/dataflow-const-prop/repr_transparent.rs new file mode 100644 index 0000000000000..4ce0ca4dff46f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/repr_transparent.rs @@ -0,0 +1,12 @@ +// unit-test: DataflowConstProp + +// The struct has scalar ABI, but is not a scalar type. +// Make sure that we handle this correctly. +#[repr(transparent)] +struct I32(i32); + +// EMIT_MIR repr_transparent.main.DataflowConstProp.diff +fn main() { + let x = I32(0); + let y = I32(x.0 + x.0); +} From b3f648958d4f556bcceedd8c1d9b0dedb83c7bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 12 Nov 2022 14:07:54 +0100 Subject: [PATCH 68/76] Add comment for guessed constants --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 2ed8a6f161f7f..28167988d2c3c 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -13,6 +13,7 @@ use rustc_span::DUMMY_SP; use crate::MirPass; +// These constants are somewhat random guesses and have not been optimized. const BLOCK_LIMIT: usize = 100; const PLACE_LIMIT: usize = 100; From 2e034dc68cb4d593f564f5ff8c444be5d12fc95b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 12 Nov 2022 14:57:14 +0100 Subject: [PATCH 69/76] Exclude locals completely, instead of individual places --- .../rustc_mir_dataflow/src/value_analysis.rs | 47 ++++++---------- .../sibling_ptr.main.DataflowConstProp.diff | 56 +++++++++++++++++++ .../dataflow-const-prop/sibling_ptr.rs | 11 ++++ 3 files changed, 85 insertions(+), 29 deletions(-) create mode 100644 src/test/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/sibling_ptr.rs diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 0f3b952ceec84..85a35c13fd93a 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -34,7 +34,7 @@ use std::fmt::{Debug, Formatter}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; @@ -587,7 +587,8 @@ impl Map { filter: impl FnMut(Ty<'tcx>) -> bool, ) -> Self { let mut map = Self::new(); - map.register_with_filter(tcx, body, filter, &escaped_places(body)); + let exclude = excluded_locals(body); + map.register_with_filter(tcx, body, filter, &exclude); debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len()); map } @@ -598,19 +599,14 @@ impl Map { tcx: TyCtxt<'tcx>, body: &Body<'tcx>, mut filter: impl FnMut(Ty<'tcx>) -> bool, - exclude: &FxHashSet>, + exclude: &IndexVec, ) { // We use this vector as stack, pushing and popping projections. let mut projection = Vec::new(); for (local, decl) in body.local_decls.iter_enumerated() { - self.register_with_filter_rec( - tcx, - local, - &mut projection, - decl.ty, - &mut filter, - exclude, - ); + if !exclude[local] { + self.register_with_filter_rec(tcx, local, &mut projection, decl.ty, &mut filter); + } } } @@ -624,17 +620,10 @@ impl Map { projection: &mut Vec>, ty: Ty<'tcx>, filter: &mut impl FnMut(Ty<'tcx>) -> bool, - exclude: &FxHashSet>, ) { - let place = Place { local, projection: tcx.intern_place_elems(projection) }; - if exclude.contains(&place) { - // This will also exclude all projections of the excluded place. - return; - } - // Note: The framework supports only scalars for now. if filter(ty) && ty.is_scalar() { - trace!("registering place: {:?}", place); + // trace!("registering place {:?}", PlaceRef { local, projection: &*projection }); // We know that the projection only contains trackable elements. let place = self.make_place(local, projection).unwrap(); @@ -653,7 +642,7 @@ impl Map { return; } projection.push(PlaceElem::Field(field, ty)); - self.register_with_filter_rec(tcx, local, projection, ty, filter, exclude); + self.register_with_filter_rec(tcx, local, projection, ty, filter); projection.pop(); }); } @@ -835,27 +824,27 @@ fn iter_fields<'tcx>( } } -/// Returns all places, that have their reference or address taken. -/// -/// This includes shared references, and also drops and `InlineAsm` out parameters. -fn escaped_places<'tcx>(body: &Body<'tcx>) -> FxHashSet> { - struct Collector<'tcx> { - result: FxHashSet>, +/// Returns all locals with projections that have their reference or address taken. +fn excluded_locals<'tcx>(body: &Body<'tcx>) -> IndexVec { + struct Collector { + result: IndexVec, } - impl<'tcx> Visitor<'tcx> for Collector<'tcx> { + impl<'tcx> Visitor<'tcx> for Collector { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { if context.is_borrow() || context.is_address_of() || context.is_drop() || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) { - self.result.insert(*place); + // A pointer to a place could be used to access other places with the same local, + // hence we have to exclude the local completely. + self.result[place.local] = true; } } } - let mut collector = Collector { result: FxHashSet::default() }; + let mut collector = Collector { result: IndexVec::from_elem(false, &body.local_decls) }; collector.visit_body(body); collector.result } diff --git a/src/test/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff new file mode 100644 index 0000000000000..8126d4b8585e6 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff @@ -0,0 +1,56 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/sibling_ptr.rs:+0:11: +0:11 + let mut _1: (u8, u8); // in scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14 + let _2: (); // in scope 0 at $DIR/sibling_ptr.rs:+2:5: +5:6 + let mut _4: *mut u8; // in scope 0 at $DIR/sibling_ptr.rs:+4:10: +4:18 + let mut _5: *mut u8; // in scope 0 at $DIR/sibling_ptr.rs:+4:10: +4:11 + scope 1 { + debug x => _1; // in scope 1 at $DIR/sibling_ptr.rs:+1:9: +1:14 + let _6: u8; // in scope 1 at $DIR/sibling_ptr.rs:+6:9: +6:11 + scope 2 { + let _3: *mut u8; // in scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14 + scope 3 { + debug p => _3; // in scope 3 at $DIR/sibling_ptr.rs:+3:13: +3:14 + } + } + scope 4 { + debug x1 => _6; // in scope 4 at $DIR/sibling_ptr.rs:+6:9: +6:11 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14 + Deinit(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33 + (_1.0: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33 + (_1.1: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33 + StorageLive(_2); // scope 1 at $DIR/sibling_ptr.rs:+2:5: +5:6 + StorageLive(_3); // scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14 + _3 = &raw mut (_1.0: u8); // scope 2 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + StorageLive(_4); // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18 + StorageLive(_5); // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11 + _5 = _3; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11 + _4 = ptr::mut_ptr::::add(move _5, const 1_usize) -> bb1; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18 + // mir::Constant + // + span: $DIR/sibling_ptr.rs:8:12: 8:15 + // + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::::add}, val: Value() } + } + + bb1: { + StorageDead(_5); // scope 3 at $DIR/sibling_ptr.rs:+4:17: +4:18 + (*_4) = const 1_u8; // scope 3 at $DIR/sibling_ptr.rs:+4:9: +4:22 + StorageDead(_4); // scope 3 at $DIR/sibling_ptr.rs:+4:22: +4:23 + _2 = const (); // scope 2 at $DIR/sibling_ptr.rs:+2:5: +5:6 + StorageDead(_3); // scope 2 at $DIR/sibling_ptr.rs:+5:5: +5:6 + StorageDead(_2); // scope 1 at $DIR/sibling_ptr.rs:+5:5: +5:6 + StorageLive(_6); // scope 1 at $DIR/sibling_ptr.rs:+6:9: +6:11 + _6 = (_1.1: u8); // scope 1 at $DIR/sibling_ptr.rs:+6:14: +6:17 + _0 = const (); // scope 0 at $DIR/sibling_ptr.rs:+0:11: +7:2 + StorageDead(_6); // scope 1 at $DIR/sibling_ptr.rs:+7:1: +7:2 + StorageDead(_1); // scope 0 at $DIR/sibling_ptr.rs:+7:1: +7:2 + return; // scope 0 at $DIR/sibling_ptr.rs:+7:2: +7:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/sibling_ptr.rs b/src/test/mir-opt/dataflow-const-prop/sibling_ptr.rs new file mode 100644 index 0000000000000..87ef00d18295f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/sibling_ptr.rs @@ -0,0 +1,11 @@ +// unit-test: DataflowConstProp + +// EMIT_MIR sibling_ptr.main.DataflowConstProp.diff +fn main() { + let mut x: (u8, u8) = (0, 0); + unsafe { + let p = std::ptr::addr_of_mut!(x.0); + *p.add(1) = 1; + } + let x1 = x.1; // should not be propagated +} From 74d53ab9129e33708fcaf11d560c7d4aa282ffd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 12 Nov 2022 15:24:23 +0100 Subject: [PATCH 70/76] Require -Zmir-opt-level >= 3 for now --- .../src/dataflow_const_prop.rs | 2 +- .../ui/const-ptr/forbidden_slices.64bit.stderr | 2 +- src/test/ui/consts/const-eval/issue-50814.rs | 2 -- .../ui/consts/const-eval/issue-50814.stderr | 18 +++--------------- src/test/ui/consts/offset_from_ub.stderr | 6 +++--- 5 files changed, 8 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 28167988d2c3c..085977dac8369 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -21,7 +21,7 @@ pub struct DataflowConstProp; impl<'tcx> MirPass<'tcx> for DataflowConstProp { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 1 + sess.mir_opt_level() >= 3 } #[instrument(skip_all level = "debug")] diff --git a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr index db42b7c98307d..58f97347fa2ff 100644 --- a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr +++ b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr @@ -164,7 +164,7 @@ LL | pub static R4: &[u8] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾──────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ } error[E0080]: it is undefined behavior to use this value diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs index e3f0fb90c8f0a..9c6108292b527 100644 --- a/src/test/ui/consts/const-eval/issue-50814.rs +++ b/src/test/ui/consts/const-eval/issue-50814.rs @@ -14,13 +14,11 @@ struct Sum(A, B); impl Unsigned for Sum { const MAX: u8 = A::MAX + B::MAX; //~^ ERROR evaluation of ` as Unsigned>::MAX` failed - //~| ERROR evaluation of ` as Unsigned>::MAX` failed } fn foo(_: T) -> &'static u8 { &Sum::::MAX //~^ ERROR evaluation of `foo::` failed [E0080] - //~| ERROR evaluation of `foo::` failed [E0080] } fn main() { diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr index 07f3033c44fee..38e9dc36ee98f 100644 --- a/src/test/ui/consts/const-eval/issue-50814.stderr +++ b/src/test/ui/consts/const-eval/issue-50814.stderr @@ -4,30 +4,18 @@ error[E0080]: evaluation of ` as Unsigned>::MAX` failed LL | const MAX: u8 = A::MAX + B::MAX; | ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow -error[E0080]: evaluation of `foo::` failed - --> $DIR/issue-50814.rs:21:6 - | -LL | &Sum::::MAX - | ^^^^^^^^^^^^^^^^^^ referenced constant has errors - -error[E0080]: evaluation of ` as Unsigned>::MAX` failed - --> $DIR/issue-50814.rs:15:21 - | -LL | const MAX: u8 = A::MAX + B::MAX; - | ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow - error[E0080]: evaluation of `foo::` failed - --> $DIR/issue-50814.rs:21:6 + --> $DIR/issue-50814.rs:20:6 | LL | &Sum::::MAX | ^^^^^^^^^^^^^^^^^^ referenced constant has errors note: the above error was encountered while instantiating `fn foo::` - --> $DIR/issue-50814.rs:27:5 + --> $DIR/issue-50814.rs:25:5 | LL | foo(0); | ^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index 62a087d94d356..ada0bc8ddaee7 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -40,19 +40,19 @@ error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:53:14 | LL | unsafe { ptr_offset_from(end_ptr, start_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc18 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc17 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:62:14 | LL | unsafe { ptr_offset_from(start_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc21 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc20 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:70:14 | LL | unsafe { ptr_offset_from(end_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc24 has size 4, so pointer at offset 10 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc23 has size 4, so pointer at offset 10 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:79:14 From abe31a9986db85ac8e146a5d062fc6d186c5bd9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 12 Nov 2022 17:01:56 +0100 Subject: [PATCH 71/76] Partially revert 74d53ab --- src/test/ui/const-ptr/forbidden_slices.64bit.stderr | 2 +- src/test/ui/consts/offset_from_ub.stderr | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr index 58f97347fa2ff..db42b7c98307d 100644 --- a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr +++ b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr @@ -164,7 +164,7 @@ LL | pub static R4: &[u8] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾──────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ } error[E0080]: it is undefined behavior to use this value diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index ada0bc8ddaee7..62a087d94d356 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -40,19 +40,19 @@ error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:53:14 | LL | unsafe { ptr_offset_from(end_ptr, start_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc17 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc18 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:62:14 | LL | unsafe { ptr_offset_from(start_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc20 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc21 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:70:14 | LL | unsafe { ptr_offset_from(end_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc23 has size 4, so pointer at offset 10 is out-of-bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc24 has size 4, so pointer at offset 10 is out-of-bounds error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:79:14 From d66a00a7b192f7332288e6386ac99f63f7e1d8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 12 Nov 2022 20:05:52 +0100 Subject: [PATCH 72/76] Expand upon comment regarding self-assignment --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 085977dac8369..c1293b3b7b6f5 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -317,7 +317,7 @@ struct CollectAndPatch<'tcx, 'map> { /// For a given MIR location, this stores the values of the operands used by that location. In /// particular, this is before the effect, such that the operands of `_1 = _1 + _2` are - /// properly captured. + /// properly captured. (This may become UB soon, but it is currently emitted even by safe code.) before_effect: FxHashMap<(Location, Place<'tcx>), ScalarTy<'tcx>>, /// Stores the assigned values for assignments where the Rvalue is constant. From ea23585c91a3bbe38162b967ecf6838b50ae369a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 12 Nov 2022 20:14:34 +0100 Subject: [PATCH 73/76] Disable limits if mir-opt-level >= 4 --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index c1293b3b7b6f5..e9027387413cf 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -14,6 +14,7 @@ use rustc_span::DUMMY_SP; use crate::MirPass; // These constants are somewhat random guesses and have not been optimized. +// If `tcx.sess.mir_opt_level() >= 4`, we ignore the limits (this can become very expensive). const BLOCK_LIMIT: usize = 100; const PLACE_LIMIT: usize = 100; @@ -26,7 +27,7 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp { #[instrument(skip_all level = "debug")] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if body.basic_blocks.len() > BLOCK_LIMIT { + if tcx.sess.mir_opt_level() < 4 && body.basic_blocks.len() > BLOCK_LIMIT { debug!("aborted dataflow const prop due too many basic blocks"); return; } @@ -42,7 +43,7 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp { // `O(num_nodes * tracked_places * n)` in terms of time complexity. Since the number of // map nodes is strongly correlated to the number of tracked places, this becomes more or // less `O(n)` if we place a constant limit on the number of tracked places. - if map.tracked_places() > PLACE_LIMIT { + if tcx.sess.mir_opt_level() < 4 && map.tracked_places() > PLACE_LIMIT { debug!("aborted dataflow const prop due to too many tracked places"); return; } From 108790b8dc2298a63214d28abf8354b09878e427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Sat, 12 Nov 2022 20:32:09 +0100 Subject: [PATCH 74/76] Remove log statement that was commented out --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 85a35c13fd93a..db4b0a3deda9d 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -623,8 +623,6 @@ impl Map { ) { // Note: The framework supports only scalars for now. if filter(ty) && ty.is_scalar() { - // trace!("registering place {:?}", PlaceRef { local, projection: &*projection }); - // We know that the projection only contains trackable elements. let place = self.make_place(local, projection).unwrap(); From c27ddc9a7f606e076aa1751523323f0ada2becbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Mon, 14 Nov 2022 15:11:18 +0100 Subject: [PATCH 75/76] Remove redundant graphviz escaping --- compiler/rustc_middle/src/mir/generic_graphviz.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/mir/generic_graphviz.rs b/compiler/rustc_middle/src/mir/generic_graphviz.rs index 11ac45943ac58..ccae7e159b1f1 100644 --- a/compiler/rustc_middle/src/mir/generic_graphviz.rs +++ b/compiler/rustc_middle/src/mir/generic_graphviz.rs @@ -126,7 +126,7 @@ impl< write!( w, r#"{}"#, - dot::escape_html(§ion).replace('\n', "
") + dot::escape_html(§ion) )?; } @@ -147,7 +147,7 @@ impl< let src = self.node(source); let trg = self.node(target); let escaped_edge_label = if let Some(edge_label) = edge_labels.get(index) { - dot::escape_html(edge_label).replace('\n', r#"
"#) + dot::escape_html(edge_label) } else { "".to_owned() }; @@ -162,8 +162,7 @@ impl< where W: Write, { - let lines = label.split('\n').map(|s| dot::escape_html(s)).collect::>(); - let escaped_label = lines.join(r#"
"#); + let escaped_label = dot::escape_html(label); writeln!(w, r#" label=<

{}



>;"#, escaped_label) } From 24d2e903df2f0d7d66ab50f4df6d06c84254c85b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Mon, 14 Nov 2022 15:11:30 +0100 Subject: [PATCH 76/76] Bless graphviz tests --- .../coverage_graphviz.bar.InstrumentCoverage.0.dot | 2 +- .../coverage_graphviz.main.InstrumentCoverage.0.dot | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot b/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot index c00eae96e0838..03df5c9504be2 100644 --- a/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot +++ b/src/test/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot @@ -2,5 +2,5 @@ digraph Cov_0_4 { graph [fontname="Courier, monospace"]; node [fontname="Courier, monospace"]; edge [fontname="Courier, monospace"]; - bcb0__Cov_0_4 [shape="none", label=<
bcb0
Counter(bcb0) at 18:1-20:2
19:5-19:9: @0[0]: Coverage::Counter(1) for $DIR/coverage_graphviz.rs:18:1 - 20:2
20:2-20:2: @0.Return: return
bb0: Return
>]; + bcb0__Cov_0_4 [shape="none", label=<
bcb0
Counter(bcb0) at 18:1-20:2
19:5-19:9: @0[0]: Coverage::Counter(1) for $DIR/coverage_graphviz.rs:18:1 - 20:2
20:2-20:2: @0.Return: return
bb0: Return
>]; } diff --git a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot index ca0eb7e845aad..fd21b14af25f3 100644 --- a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot +++ b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot @@ -2,10 +2,10 @@ digraph Cov_0_3 { graph [fontname="Courier, monospace"]; node [fontname="Courier, monospace"]; edge [fontname="Courier, monospace"]; - bcb3__Cov_0_3 [shape="none", label=<
bcb3
Counter(bcb3) at 13:10-13:10
13:10-13:10: @5[0]: Coverage::Counter(2) for $DIR/coverage_graphviz.rs:13:10 - 13:11
bb5: Goto
>]; - bcb2__Cov_0_3 [shape="none", label=<
bcb2
Expression(bcb1:(bcb0 + bcb3) - bcb3) at 12:13-12:18
12:13-12:18: @4[0]: Coverage::Expression(4294967293) = 4294967294 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2
Expression(bcb2:(bcb1:(bcb0 + bcb3) - bcb3) + 0) at 15:2-15:2
15:2-15:2: @4.Return: return
bb4: Return
>]; - bcb1__Cov_0_3 [shape="none", label=<
bcb1
Expression(bcb0 + bcb3) at 10:5-11:17
11:12-11:17: @2.Call: _2 = bar() -> [return: bb3, unwind: bb6]
bb1: FalseUnwind
bb2: Call
bb3: SwitchInt
>]; - bcb0__Cov_0_3 [shape="none", label=<
bcb0
Counter(bcb0) at 9:1-9:11
bb0: Goto
>]; + bcb3__Cov_0_3 [shape="none", label=<
bcb3
Counter(bcb3) at 13:10-13:10
13:10-13:10: @5[0]: Coverage::Counter(2) for $DIR/coverage_graphviz.rs:13:10 - 13:11
bb5: Goto
>]; + bcb2__Cov_0_3 [shape="none", label=<
bcb2
Expression(bcb1:(bcb0 + bcb3) - bcb3) at 12:13-12:18
12:13-12:18: @4[0]: Coverage::Expression(4294967293) = 4294967294 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2
Expression(bcb2:(bcb1:(bcb0 + bcb3) - bcb3) + 0) at 15:2-15:2
15:2-15:2: @4.Return: return
bb4: Return
>]; + bcb1__Cov_0_3 [shape="none", label=<
bcb1
Expression(bcb0 + bcb3) at 10:5-11:17
11:12-11:17: @2.Call: _2 = bar() -> [return: bb3, unwind: bb6]
bb1: FalseUnwind
bb2: Call
bb3: SwitchInt
>]; + bcb0__Cov_0_3 [shape="none", label=<
bcb0
Counter(bcb0) at 9:1-9:11
bb0: Goto
>]; bcb3__Cov_0_3 -> bcb1__Cov_0_3 [label=<>]; bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=]; bcb1__Cov_0_3 -> bcb2__Cov_0_3 [label=];