From da4cb6c650fe07566fbe20b6a0dde9de579e2e22 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 7 Oct 2020 11:08:51 -0700 Subject: [PATCH 1/5] Define a `PassManager` for managing MIR passes --- compiler/rustc_mir/src/lib.rs | 4 +- compiler/rustc_mir/src/shim.rs | 23 +- compiler/rustc_mir/src/transform/mod.rs | 274 +++++++---------------- compiler/rustc_mir/src/transform/pass.rs | 147 ++++++++++++ 4 files changed, 245 insertions(+), 203 deletions(-) create mode 100644 compiler/rustc_mir/src/transform/pass.rs diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs index c00c6860903c8..15ff9fff72a0f 100644 --- a/compiler/rustc_mir/src/lib.rs +++ b/compiler/rustc_mir/src/lib.rs @@ -34,13 +34,15 @@ extern crate tracing; #[macro_use] extern crate rustc_middle; +#[macro_use] +pub mod transform; + mod borrow_check; pub mod const_eval; pub mod dataflow; pub mod interpret; pub mod monomorphize; mod shim; -pub mod transform; pub mod util; use rustc_middle::ty::query::Providers; diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir/src/shim.rs index 5431d22e70320..87bf5fbf4c4cd 100644 --- a/compiler/rustc_mir/src/shim.rs +++ b/compiler/rustc_mir/src/shim.rs @@ -17,7 +17,7 @@ use std::iter; use crate::transform::{ add_call_guards, add_moves_for_packed_drops, no_landing_pads, remove_noop_landing_pads, - run_passes, simplify, + simplify, PassManager, }; use crate::util::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle}; use crate::util::expand_aggregate; @@ -75,18 +75,15 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' }; debug!("make_shim({:?}) = untransformed {:?}", instance, result); - run_passes( - tcx, - &mut result, - MirPhase::Const, - &[&[ - &add_moves_for_packed_drops::AddMovesForPackedDrops, - &no_landing_pads::NoLandingPads::new(tcx), - &remove_noop_landing_pads::RemoveNoopLandingPads, - &simplify::SimplifyCfg::new("make_shim"), - &add_call_guards::CriticalCallEdges, - ]], - ); + if result.phase < MirPhase::Const { + run_passes!(PassManager::new(tcx, &mut result, MirPhase::Const) => [ + add_moves_for_packed_drops::AddMovesForPackedDrops, + no_landing_pads::NoLandingPads::new(tcx), + remove_noop_landing_pads::RemoveNoopLandingPads, + simplify::SimplifyCfg::new("make_shim"), + add_call_guards::CriticalCallEdges, + ]); + } debug!("make_shim({:?}) = {:?}", instance, result); diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index b4f5947f5a339..622350f029c89 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -11,8 +11,13 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::steal::Steal; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::{Span, Symbol}; -use std::borrow::Cow; +#[macro_use] +mod pass; + +pub use self::pass::{MirPass, OptLevel, PassManager}; + +// Passes pub mod add_call_guards; pub mod add_moves_for_packed_drops; pub mod add_retag; @@ -134,82 +139,6 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> FxHashSet { set } -/// Generates a default name for the pass based on the name of the -/// type `T`. -pub fn default_name() -> Cow<'static, str> { - let name = ::std::any::type_name::(); - if let Some(tail) = name.rfind(':') { Cow::from(&name[tail + 1..]) } else { Cow::from(name) } -} - -/// A streamlined trait that you can implement to create a pass; the -/// pass will be named after the type, and it will consist of a main -/// loop that goes over each available MIR and applies `run_pass`. -pub trait MirPass<'tcx> { - fn name(&self) -> Cow<'_, str> { - default_name::() - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); -} - -pub fn run_passes( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - mir_phase: MirPhase, - passes: &[&[&dyn MirPass<'tcx>]], -) { - let phase_index = mir_phase.phase_index(); - let validate = tcx.sess.opts.debugging_opts.validate_mir; - - if body.phase >= mir_phase { - return; - } - - if validate { - validate::Validator { when: format!("input to phase {:?}", mir_phase), mir_phase } - .run_pass(tcx, body); - } - - let mut index = 0; - let mut run_pass = |pass: &dyn MirPass<'tcx>| { - let run_hooks = |body: &_, index, is_after| { - dump_mir::on_mir_pass( - tcx, - &format_args!("{:03}-{:03}", phase_index, index), - &pass.name(), - body, - is_after, - ); - }; - run_hooks(body, index, false); - pass.run_pass(tcx, body); - run_hooks(body, index, true); - - if validate { - validate::Validator { - when: format!("after {} in phase {:?}", pass.name(), mir_phase), - mir_phase, - } - .run_pass(tcx, body); - } - - index += 1; - }; - - for pass_group in passes { - for pass in *pass_group { - run_pass(*pass); - } - } - - body.phase = mir_phase; - - if mir_phase == MirPhase::Optimization { - validate::Validator { when: format!("end of phase {:?}", mir_phase), mir_phase } - .run_pass(tcx, body); - } -} - fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> ConstQualifs { let const_kind = tcx.hir().body_const_context(def.did); @@ -259,19 +188,15 @@ fn mir_const<'tcx>( util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); - run_passes( - tcx, - &mut body, - MirPhase::Const, - &[&[ - // MIR-level lints. - &check_packed_ref::CheckPackedRef, - &check_const_item_mutation::CheckConstItemMutation, - // What we need to do constant evaluation. - &simplify::SimplifyCfg::new("initial"), - &rustc_peek::SanityCheck, - ]], - ); + run_passes!(PassManager::new(tcx, &mut body, MirPhase::Const) => [ + // MIR-level lints. + check_packed_ref::CheckPackedRef, + check_const_item_mutation::CheckConstItemMutation, + // What we need to do constant evaluation. + simplify::SimplifyCfg::new("initial"), + rustc_peek::SanityCheck, + ]); + tcx.alloc_steal_mir(body) } @@ -301,20 +226,19 @@ fn mir_promoted( } body.required_consts = required_consts; + let mut promotion_passes = PassManager::new(tcx, &mut body, MirPhase::ConstPromotion); + let promote_pass = promote_consts::PromoteTemps::default(); - let promote: &[&dyn MirPass<'tcx>] = &[ - // What we need to run borrowck etc. - &promote_pass, - &simplify::SimplifyCfg::new("promote-consts"), - ]; - - let opt_coverage: &[&dyn MirPass<'tcx>] = if tcx.sess.opts.debugging_opts.instrument_coverage { - &[&instrument_coverage::InstrumentCoverage] - } else { - &[] - }; + run_passes!(promotion_passes => [ + promote_pass, + simplify::SimplifyCfg::new("promote-consts"), + ]); + + if tcx.sess.opts.debugging_opts.instrument_coverage { + run_passes!(promotion_passes => [instrument_coverage::InstrumentCoverage]); + } - run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]); + drop(promotion_passes); let promoted = promote_pass.promoted_fragments.into_inner(); (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) @@ -348,30 +272,28 @@ fn mir_drops_elaborated_and_const_checked<'tcx>( fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("post_borrowck_cleanup({:?})", body.source.def_id()); - let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[ + run_passes!(PassManager::new(tcx, body, MirPhase::DropLowering) => [ // Remove all things only needed by analysis - &no_landing_pads::NoLandingPads::new(tcx), - &simplify_branches::SimplifyBranches::new("initial"), - &remove_noop_landing_pads::RemoveNoopLandingPads, - &cleanup_post_borrowck::CleanupNonCodegenStatements, - &simplify::SimplifyCfg::new("early-opt"), + no_landing_pads::NoLandingPads::new(tcx), + simplify_branches::SimplifyBranches::new("initial"), + remove_noop_landing_pads::RemoveNoopLandingPads, + cleanup_post_borrowck::CleanupNonCodegenStatements, + simplify::SimplifyCfg::new("early-opt"), // These next passes must be executed together - &add_call_guards::CriticalCallEdges, - &elaborate_drops::ElaborateDrops, - &no_landing_pads::NoLandingPads::new(tcx), + add_call_guards::CriticalCallEdges, + elaborate_drops::ElaborateDrops, + no_landing_pads::NoLandingPads::new(tcx), // AddMovesForPackedDrops needs to run after drop // elaboration. - &add_moves_for_packed_drops::AddMovesForPackedDrops, + add_moves_for_packed_drops::AddMovesForPackedDrops, // `AddRetag` needs to run after `ElaborateDrops`. Otherwise it should run fairly late, // but before optimizations begin. - &add_retag::AddRetag, - &simplify::SimplifyCfg::new("elaborate-drops"), + add_retag::AddRetag, + simplify::SimplifyCfg::new("elaborate-drops"), // `Deaggregator` is conceptually part of MIR building, some backends rely on it happening // and it can help optimizations. - &deaggregator::Deaggregator, - ]; - - run_passes(tcx, body, MirPhase::DropLowering, &[post_borrowck_cleanup]); + deaggregator::Deaggregator, + ]); } fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -380,80 +302,54 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Lowering generator control-flow and variables has to happen before we do anything else // to them. We run some optimizations before that, because they may be harder to do on the state // machine than on MIR with async primitives. - let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[ - &unreachable_prop::UnreachablePropagation, - &uninhabited_enum_branching::UninhabitedEnumBranching, - &simplify::SimplifyCfg::new("after-uninhabited-enum-branching"), - &inline::Inline, - &generator::StateTransform, - ]; - - // Even if we don't do optimizations, we still have to lower generators for codegen. - let no_optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[&generator::StateTransform]; - - // The main optimizations that we do on MIR. - let optimizations: &[&dyn MirPass<'tcx>] = &[ - &remove_unneeded_drops::RemoveUnneededDrops, - &match_branches::MatchBranchSimplification, - // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) - &multiple_return_terminators::MultipleReturnTerminators, - &instcombine::InstCombine, - &const_prop::ConstProp, - &simplify_branches::SimplifyBranches::new("after-const-prop"), - &early_otherwise_branch::EarlyOtherwiseBranch, - &simplify_comparison_integral::SimplifyComparisonIntegral, - &simplify_try::SimplifyArmIdentity, - &simplify_try::SimplifyBranchSame, - &dest_prop::DestinationPropagation, - ©_prop::CopyPropagation, - &simplify_branches::SimplifyBranches::new("after-copy-prop"), - &remove_noop_landing_pads::RemoveNoopLandingPads, - &simplify::SimplifyCfg::new("final"), - &nrvo::RenameReturnPlace, - &simplify::SimplifyLocals, - &multiple_return_terminators::MultipleReturnTerminators, - ]; - - // Optimizations to run even if mir optimizations have been disabled. - let no_optimizations: &[&dyn MirPass<'tcx>] = &[ - // FIXME(#70073): This pass is responsible for both optimization as well as some lints. - &const_prop::ConstProp, - ]; + run_passes!(PassManager::new(tcx, body, MirPhase::GeneratorLowering) => [ + unreachable_prop::UnreachablePropagation, + uninhabited_enum_branching::UninhabitedEnumBranching, + simplify::SimplifyCfg::new("after-uninhabited-enum-branching"), + inline::Inline, + generator::StateTransform, + ]); + + let mut optimizations = PassManager::new(tcx, body, MirPhase::Optimization); + + // FIXME(ecstaticmorse): We shouldn't branch on `mir_opt_level` here, but instead rely on the + // `LEVEL` of each `MirPass` to determine whether it runs. However, this would run some + // "cleanup" passes as well as `RemoveNoopLandingPads` when we didn't before. + if mir_opt_level > 0 { + run_passes!(optimizations => [ + remove_unneeded_drops::RemoveUnneededDrops, + match_branches::MatchBranchSimplification, + // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) + multiple_return_terminators::MultipleReturnTerminators, + instcombine::InstCombine, + const_prop::ConstProp, + simplify_branches::SimplifyBranches::new("after-const-prop"), + early_otherwise_branch::EarlyOtherwiseBranch, + simplify_comparison_integral::SimplifyComparisonIntegral, + simplify_try::SimplifyArmIdentity, + simplify_try::SimplifyBranchSame, + dest_prop::DestinationPropagation, + copy_prop::CopyPropagation, + simplify_branches::SimplifyBranches::new("after-copy-prop"), + remove_noop_landing_pads::RemoveNoopLandingPads, + simplify::SimplifyCfg::new("final"), + nrvo::RenameReturnPlace, + simplify::SimplifyLocals, + multiple_return_terminators::MultipleReturnTerminators, + ]); + } else { + run_passes!(optimizations => [ + // FIXME(#70073): This pass is responsible for both optimization as well as some lints. + const_prop::ConstProp, + ]); + } // Some cleanup necessary at least for LLVM and potentially other codegen backends. - let pre_codegen_cleanup: &[&dyn MirPass<'tcx>] = &[ - &add_call_guards::CriticalCallEdges, + run_passes!(optimizations => [ + add_call_guards::CriticalCallEdges, // Dump the end result for testing and debugging purposes. - &dump_mir::Marker("PreCodegen"), - ]; - - // End of pass declarations, now actually run the passes. - // Generator Lowering - #[rustfmt::skip] - run_passes( - tcx, - body, - MirPhase::GeneratorLowering, - &[ - if mir_opt_level > 0 { - optimizations_with_generators - } else { - no_optimizations_with_generators - } - ], - ); - - // Main optimization passes - #[rustfmt::skip] - run_passes( - tcx, - body, - MirPhase::Optimization, - &[ - if mir_opt_level > 0 { optimizations } else { no_optimizations }, - pre_codegen_cleanup, - ], - ); + dump_mir::Marker("PreCodegen"), + ]); } fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> { diff --git a/compiler/rustc_mir/src/transform/pass.rs b/compiler/rustc_mir/src/transform/pass.rs new file mode 100644 index 0000000000000..fc10ae8a32449 --- /dev/null +++ b/compiler/rustc_mir/src/transform/pass.rs @@ -0,0 +1,147 @@ +use std::borrow::Cow; + +use rustc_middle::mir::{Body, MirPhase}; +use rustc_middle::ty::TyCtxt; + +use super::{dump_mir, validate}; + +/// A streamlined trait that you can implement to create a pass; the +/// pass will be named after the type, and it will consist of a main +/// loop that goes over each available MIR and applies `run_pass`. +pub trait MirPass<'tcx> { + const LEVEL: OptLevel; + + fn name(&self) -> Cow<'_, str> { + let name = std::any::type_name::(); + name.rsplit(':').next().unwrap().into() + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); +} + +const UNSOUND_MIR_OPT_LEVEL: u8 = 1; + +pub enum OptLevel { + /// Passes that will run at `-Zmir-opt-level=N` or higher. + N(u8), + + /// Passes that are known or suspected to cause miscompilations. + /// + /// These passes only run if `-Zunsound-mir-opts` is enabled and we are at `mir-opt-level=1` or + /// above. + Unsound, + + /// Passes that clean up the MIR after other transformations. + /// + /// A `Cleanup` pass is skipped if the pass immediately preceding it is skipped. + // + // FIXME: Maybe we want to run the cleanup unless *all* passes between it and the last cleanup + // were skipped? + Cleanup, +} + +impl OptLevel { + /// A pass that will always run, regardless of `-Zmir-opt-level` or other flags. + pub const ALWAYS: Self = OptLevel::N(0); + + /// A pass that will run if no flags are passed to `rustc` (e.g. `-Zmir-opt-level`). + pub const DEFAULT: Self = OptLevel::N(1); +} + +/// RAII-style type that runs a series of optimization passes on a `Body`. +/// +/// Upon going out of scope, this type updates the `MirPhase` of that `Body`. +pub struct PassManager<'mir, 'tcx> { + tcx: TyCtxt<'tcx>, + body: &'mir mut Body<'tcx>, + phase_change: MirPhase, + passes_run: usize, + skip_cleanup: bool, +} + +impl PassManager<'mir, 'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mut Body<'tcx>, phase_change: MirPhase) -> Self { + assert!(body.phase < phase_change); + + let ret = PassManager { tcx, phase_change, body, passes_run: 0, skip_cleanup: false }; + + if tcx.sess.opts.debugging_opts.validate_mir { + ret.validate(&format!("input to phase {:?}", phase_change)); + } + + ret + } + + fn is_pass_enabled(&self, level: OptLevel) -> bool { + let opts = &self.tcx.sess.opts.debugging_opts; + let level_required = match level { + OptLevel::Cleanup => return !self.skip_cleanup, + OptLevel::Unsound if !opts.unsound_mir_opts => return false, + + OptLevel::Unsound => UNSOUND_MIR_OPT_LEVEL, + OptLevel::N(n) => n, + }; + + opts.mir_opt_level >= level_required as usize + } + + pub fn validate(&self, when: &str) { + validate::validate_body(self.tcx, self.body, when); + } + + pub fn run_pass

(&mut self, pass: &P) + where + P: MirPass<'tcx>, + { + if !self.is_pass_enabled(pass) { + info!("Skipping {}", pass.name()); + self.skip_cleanup = true; + return; + } + + dump_mir::on_mir_pass( + self.tcx, + &format_args!("{:03}-{:03}", self.body.phase.phase_index(), self.passes_run), + &pass.name(), + self.body, + false, + ); + pass.run_pass(self.tcx, self.body); + dump_mir::on_mir_pass( + self.tcx, + &format_args!("{:03}-{:03}", self.body.phase.phase_index(), self.passes_run), + &pass.name(), + self.body, + true, + ); + + self.skip_cleanup = false; + self.passes_run += 1; + + if self.tcx.sess.opts.debugging_opts.validate_mir { + self.validate(&format!( + "after {} while transitioning to {:?}", + pass.name(), + self.phase_change + )); + } + } +} + +impl Drop for PassManager<'mir, 'tcx> { + fn drop(&mut self) { + self.body.phase = self.phase_change; + + // Do MIR validation after all optimization passes have run regardless of `-Zvalidate_mir`. + if self.phase_change == MirPhase::Optimization { + self.validate(&format!("end of phase {:?}", self.phase_change)); + } + } +} + +macro_rules! run_passes { + ($manager:expr => [$($pass:expr),* $(,)?]) => {{ + let ref mut manager: PassManager<'_, '_> = $manager; + $( manager.run_pass(&$pass); )* + }} +} From 5f985405905dbd2f224533a846a7fd1fd6b619dd Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 7 Oct 2020 11:11:08 -0700 Subject: [PATCH 2/5] Declare `opt-level` for each MIR transformation --- .../src/transform/add_call_guards.rs | 4 ++- .../transform/add_moves_for_packed_drops.rs | 4 ++- compiler/rustc_mir/src/transform/add_retag.rs | 4 ++- .../transform/check_const_item_mutation.rs | 5 +++- .../src/transform/check_packed_ref.rs | 5 +++- .../src/transform/cleanup_post_borrowck.rs | 4 ++- .../rustc_mir/src/transform/const_prop.rs | 5 +++- compiler/rustc_mir/src/transform/copy_prop.rs | 14 ++++------ .../rustc_mir/src/transform/deaggregator.rs | 4 ++- compiler/rustc_mir/src/transform/dest_prop.rs | 12 ++++---- compiler/rustc_mir/src/transform/dump_mir.rs | 4 ++- .../src/transform/early_otherwise_branch.rs | 8 +++--- .../src/transform/elaborate_drops.rs | 4 ++- compiler/rustc_mir/src/transform/generator.rs | 5 +++- compiler/rustc_mir/src/transform/inline.rs | 28 +++++++++---------- .../rustc_mir/src/transform/instcombine.rs | 4 ++- .../src/transform/instrument_coverage.rs | 4 ++- .../rustc_mir/src/transform/match_branches.rs | 4 ++- .../transform/multiple_return_terminators.rs | 8 ++---- .../src/transform/no_landing_pads.rs | 4 ++- compiler/rustc_mir/src/transform/nrvo.rs | 4 ++- .../rustc_mir/src/transform/promote_consts.rs | 4 ++- .../src/transform/remove_noop_landing_pads.rs | 4 ++- .../src/transform/remove_unneeded_drops.rs | 4 ++- .../rustc_mir/src/transform/rustc_peek.rs | 4 ++- compiler/rustc_mir/src/transform/simplify.rs | 6 +++- .../src/transform/simplify_branches.rs | 4 ++- .../transform/simplify_comparison_integral.rs | 4 ++- .../rustc_mir/src/transform/simplify_try.rs | 12 ++++---- .../transform/uninhabited_enum_branching.rs | 4 ++- .../src/transform/unreachable_prop.rs | 12 ++++---- 31 files changed, 120 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_mir/src/transform/add_call_guards.rs b/compiler/rustc_mir/src/transform/add_call_guards.rs index 1dddaeb89e684..c2c23d450a249 100644 --- a/compiler/rustc_mir/src/transform/add_call_guards.rs +++ b/compiler/rustc_mir/src/transform/add_call_guards.rs @@ -1,4 +1,4 @@ -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -31,6 +31,8 @@ pub use self::AddCallGuards::*; */ impl<'tcx> MirPass<'tcx> for AddCallGuards { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { self.add_call_guards(body); } diff --git a/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs b/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs index 417e0a51aecf0..19ac48ba24482 100644 --- a/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs @@ -1,7 +1,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use crate::util; use crate::util::patch::MirPatch; @@ -39,6 +39,8 @@ use crate::util::patch::MirPatch; pub struct AddMovesForPackedDrops; impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span); add_moves_for_packed_drops(tcx, body); diff --git a/compiler/rustc_mir/src/transform/add_retag.rs b/compiler/rustc_mir/src/transform/add_retag.rs index eec704e6cb775..a1338f7c8ca47 100644 --- a/compiler/rustc_mir/src/transform/add_retag.rs +++ b/compiler/rustc_mir/src/transform/add_retag.rs @@ -4,7 +4,7 @@ //! of MIR building, and only after this pass we think of the program has having the //! normal MIR semantics. -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -58,6 +58,8 @@ fn may_be_reference(ty: Ty<'tcx>) -> bool { } impl<'tcx> MirPass<'tcx> for AddRetag { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if !tcx.sess.opts.debugging_opts.mir_emit_retag { return; diff --git a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs b/compiler/rustc_mir/src/transform/check_const_item_mutation.rs index 26993a6b941fb..99959b1a64c17 100644 --- a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs +++ b/compiler/rustc_mir/src/transform/check_const_item_mutation.rs @@ -6,11 +6,14 @@ use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::CONST_ITEM_MUTATION; use rustc_span::def_id::DefId; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; +// FIXME: This does not mutate the MIR, and should not be MIR pass. pub struct CheckConstItemMutation; impl<'tcx> MirPass<'tcx> for CheckConstItemMutation { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut checker = ConstMutationChecker { body, tcx, target_local: None }; checker.visit_body(&body); diff --git a/compiler/rustc_mir/src/transform/check_packed_ref.rs b/compiler/rustc_mir/src/transform/check_packed_ref.rs index ee88daa83e783..bebf89b8d96de 100644 --- a/compiler/rustc_mir/src/transform/check_packed_ref.rs +++ b/compiler/rustc_mir/src/transform/check_packed_ref.rs @@ -3,12 +3,15 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::UNALIGNED_REFERENCES; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use crate::util; +// FIXME: This does not mutate the MIR, and should not be `MirPass`. pub struct CheckPackedRef; impl<'tcx> MirPass<'tcx> for CheckPackedRef { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(body.source.def_id()); let source_info = SourceInfo::outermost(body.span); diff --git a/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs b/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs index 8ff0fae768618..ff6f4ad9e8a0f 100644 --- a/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs @@ -18,7 +18,7 @@ //! [`ForMatchGuard`]: rustc_middle::mir::FakeReadCause::ForMatchGuard //! [`Nop`]: rustc_middle::mir::StatementKind::Nop -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{Body, BorrowKind, Location, Rvalue}; use rustc_middle::mir::{Statement, StatementKind}; @@ -31,6 +31,8 @@ pub struct DeleteNonCodegenStatements<'tcx> { } impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut delete = DeleteNonCodegenStatements { tcx }; delete.visit_body(body); diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 14b310cda939e..0392bc2b2964e 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -32,7 +32,7 @@ use crate::interpret::{ InterpCx, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, ScalarMaybeUninit, StackPopCleanup, }; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; /// The maximum number of bytes that we'll allocate space for a local or the return value. /// Needed for #66397, because otherwise we eval into large places and that can cause OOM or just @@ -60,6 +60,9 @@ macro_rules! throw_machine_stop_str { pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { + // FIXME(#70073): This pass is responsible for both optimization as well as some lints. + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // will be evaluated by miri and produce its errors there if body.source.promoted.is_some() { diff --git a/compiler/rustc_mir/src/transform/copy_prop.rs b/compiler/rustc_mir/src/transform/copy_prop.rs index 4f44bb7b20476..403e2f06c8762 100644 --- a/compiler/rustc_mir/src/transform/copy_prop.rs +++ b/compiler/rustc_mir/src/transform/copy_prop.rs @@ -19,7 +19,7 @@ //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the //! future. -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use crate::util::def_use::DefUseAnalysis; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{ @@ -30,15 +30,11 @@ use rustc_middle::ty::TyCtxt; pub struct CopyPropagation; impl<'tcx> MirPass<'tcx> for CopyPropagation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let opts = &tcx.sess.opts.debugging_opts; - // We only run when the MIR optimization level is > 1. - // This avoids a slow pass, and messing up debug info. - // FIXME(76740): This optimization is buggy and can cause unsoundness. - if opts.mir_opt_level <= 1 || !opts.unsound_mir_opts { - return; - } + // This pass is slow and doesn't handle debug info. It shouldn't run by default. + // FIXME(76740): This optimization is buggy and can cause unsoundness. + const LEVEL: OptLevel = OptLevel::Unsound; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut def_use_analysis = DefUseAnalysis::new(body); loop { def_use_analysis.analyze(body); diff --git a/compiler/rustc_mir/src/transform/deaggregator.rs b/compiler/rustc_mir/src/transform/deaggregator.rs index 5bd7256c666c6..4250197bcd5ae 100644 --- a/compiler/rustc_mir/src/transform/deaggregator.rs +++ b/compiler/rustc_mir/src/transform/deaggregator.rs @@ -1,4 +1,4 @@ -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use crate::util::expand_aggregate; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -6,6 +6,8 @@ use rustc_middle::ty::TyCtxt; pub struct Deaggregator; impl<'tcx> MirPass<'tcx> for Deaggregator { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); let local_decls = &*local_decls; diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs index 410f462ed469f..cfa69574c9f6e 100644 --- a/compiler/rustc_mir/src/transform/dest_prop.rs +++ b/compiler/rustc_mir/src/transform/dest_prop.rs @@ -99,7 +99,7 @@ use crate::dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals}; use crate::dataflow::Analysis; use crate::{ - transform::MirPass, + transform::{MirPass, OptLevel}, util::{dump_mir, PassWhere}, }; use itertools::Itertools; @@ -126,13 +126,11 @@ const MAX_BLOCKS: usize = 250; pub struct DestinationPropagation; impl<'tcx> MirPass<'tcx> for DestinationPropagation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // Only run at mir-opt-level=2 or higher for now (we don't fix up debuginfo and remove - // storage statements at the moment). - if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { - return; - } + // Only run at mir-opt-level=2 or higher for now (we don't fix up debuginfo and remove + // storage statements at the moment). + const LEVEL: OptLevel = OptLevel::N(2); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); let candidates = find_candidates(tcx, body); diff --git a/compiler/rustc_mir/src/transform/dump_mir.rs b/compiler/rustc_mir/src/transform/dump_mir.rs index 5b6edf17d06ab..64796719aa8cc 100644 --- a/compiler/rustc_mir/src/transform/dump_mir.rs +++ b/compiler/rustc_mir/src/transform/dump_mir.rs @@ -5,7 +5,7 @@ use std::fmt; use std::fs::File; use std::io; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use crate::util as mir_util; use rustc_middle::mir::Body; use rustc_middle::ty::TyCtxt; @@ -14,6 +14,8 @@ use rustc_session::config::{OutputFilenames, OutputType}; pub struct Marker(pub &'static str); impl<'tcx> MirPass<'tcx> for Marker { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn name(&self) -> Cow<'_, str> { Cow::Borrowed(self.0) } diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs index 237a5c7864b1f..b24abc373a44a 100644 --- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs +++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs @@ -1,4 +1,5 @@ -use crate::{transform::MirPass, util::patch::MirPatch}; +use crate::transform::{MirPass, OptLevel}; +use crate::util::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; use std::{borrow::Cow, fmt::Debug}; @@ -25,10 +26,9 @@ use super::simplify::simplify_cfg; pub struct EarlyOtherwiseBranch; impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { + const LEVEL: OptLevel = OptLevel::N(2); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level < 2 { - return; - } trace!("running EarlyOtherwiseBranch on {:?}", body.source); // we are only interested in this bb if the terminator is a switchInt let bbs_with_switch = diff --git a/compiler/rustc_mir/src/transform/elaborate_drops.rs b/compiler/rustc_mir/src/transform/elaborate_drops.rs index 3d435f6d0e75a..8807971405408 100644 --- a/compiler/rustc_mir/src/transform/elaborate_drops.rs +++ b/compiler/rustc_mir/src/transform/elaborate_drops.rs @@ -5,7 +5,7 @@ use crate::dataflow::on_lookup_result_bits; use crate::dataflow::MoveDataParamEnv; use crate::dataflow::{on_all_children_bits, on_all_drop_children_bits}; use crate::dataflow::{Analysis, ResultsCursor}; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use crate::util::elaborate_drops::{elaborate_drop, DropFlagState, Unwind}; use crate::util::elaborate_drops::{DropElaborator, DropFlagMode, DropStyle}; use crate::util::patch::MirPatch; @@ -20,6 +20,8 @@ use std::fmt; pub struct ElaborateDrops; impl<'tcx> MirPass<'tcx> for ElaborateDrops { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", body.source, body.span); diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir/src/transform/generator.rs index 924bb4996fc35..560245153df75 100644 --- a/compiler/rustc_mir/src/transform/generator.rs +++ b/compiler/rustc_mir/src/transform/generator.rs @@ -55,7 +55,7 @@ use crate::dataflow::impls::{ use crate::dataflow::{self, Analysis}; use crate::transform::no_landing_pads::no_landing_pads; use crate::transform::simplify; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use crate::util::dump_mir; use crate::util::expand_aggregate; use crate::util::storage; @@ -1235,6 +1235,9 @@ fn create_cases<'tcx>( } impl<'tcx> MirPass<'tcx> for StateTransform { + // Even if we don't do optimizations, we still have to lower generators for codegen. + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let yield_ty = if let Some(yield_ty) = body.yield_ty { yield_ty diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index bec1eb790478c..91e1afac19e8e 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyC use rustc_target::spec::abi::Abi; use super::simplify::{remove_dead_blocks, CfgSimplifier}; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use std::collections::VecDeque; use std::iter; @@ -37,21 +37,21 @@ struct CallSite<'tcx> { } impl<'tcx> MirPass<'tcx> for Inline { + const LEVEL: OptLevel = OptLevel::N(2); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { - if tcx.sess.opts.debugging_opts.instrument_coverage { - // The current implementation of source code coverage injects code region counters - // into the MIR, and assumes a 1-to-1 correspondence between MIR and source-code- - // based function. - debug!("function inlining is disabled when compiling with `instrument_coverage`"); - } else { - Inliner { - tcx, - param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()), - codegen_fn_attrs: tcx.codegen_fn_attrs(body.source.def_id()), - } - .run_pass(body); + if tcx.sess.opts.debugging_opts.instrument_coverage { + // The current implementation of source code coverage injects code region counters + // into the MIR, and assumes a 1-to-1 correspondence between MIR and source-code- + // based function. + debug!("function inlining is disabled when compiling with `instrument_coverage`"); + } else { + Inliner { + tcx, + param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()), + codegen_fn_attrs: tcx.codegen_fn_attrs(body.source.def_id()), } + .run_pass(body); } } } diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index 1a8e281d417df..cc5ad2345bcc6 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -1,6 +1,6 @@ //! Performs various peephole optimizations. -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::Mutability; use rustc_index::vec::Idx; @@ -19,6 +19,8 @@ use std::mem; pub struct InstCombine; impl<'tcx> MirPass<'tcx> for InstCombine { + const LEVEL: OptLevel = OptLevel::DEFAULT; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // First, find optimization opportunities. This is done in a pre-pass to keep the MIR // read-only so that we can do global analyses on the MIR in the process (e.g. diff --git a/compiler/rustc_mir/src/transform/instrument_coverage.rs b/compiler/rustc_mir/src/transform/instrument_coverage.rs index babe10a0f14da..1fac80278c8a1 100644 --- a/compiler/rustc_mir/src/transform/instrument_coverage.rs +++ b/compiler/rustc_mir/src/transform/instrument_coverage.rs @@ -1,4 +1,4 @@ -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use crate::util::pretty; use crate::util::spanview::{self, SpanViewable}; @@ -88,6 +88,8 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo } impl<'tcx> MirPass<'tcx> for InstrumentCoverage { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) { // If the InstrumentCoverage pass is called on promoted MIRs, skip them. // See: https://github.com/rust-lang/rust/pull/73011#discussion_r438317601 diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs index dad3812c5cd74..5ce251b249ffd 100644 --- a/compiler/rustc_mir/src/transform/match_branches.rs +++ b/compiler/rustc_mir/src/transform/match_branches.rs @@ -1,4 +1,4 @@ -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -37,6 +37,8 @@ pub struct MatchBranchSimplification; /// ``` impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { + const LEVEL: OptLevel = OptLevel::DEFAULT; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(body.source.def_id()); let bbs = body.basic_blocks_mut(); diff --git a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs index c37b54a3190f8..9be113b114d33 100644 --- a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs +++ b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs @@ -1,7 +1,7 @@ //! This pass removes jumps to basic blocks containing only a return, and replaces them with a //! return instead. -use crate::transform::{simplify, MirPass}; +use crate::transform::{simplify, MirPass, OptLevel}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -9,11 +9,9 @@ use rustc_middle::ty::TyCtxt; pub struct MultipleReturnTerminators; impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level < 3 { - return; - } + const LEVEL: OptLevel = OptLevel::N(3); + fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // find basic blocks with no statement and a return terminator let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks().len()); let bbs = body.basic_blocks_mut(); diff --git a/compiler/rustc_mir/src/transform/no_landing_pads.rs b/compiler/rustc_mir/src/transform/no_landing_pads.rs index 83954c93c04a1..00d668d49d09d 100644 --- a/compiler/rustc_mir/src/transform/no_landing_pads.rs +++ b/compiler/rustc_mir/src/transform/no_landing_pads.rs @@ -1,7 +1,7 @@ //! This pass removes the unwind branch of all the terminators when the no-landing-pads option is //! specified. -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -18,6 +18,8 @@ impl<'tcx> NoLandingPads<'tcx> { } impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { no_landing_pads(tcx, body) } diff --git a/compiler/rustc_mir/src/transform/nrvo.rs b/compiler/rustc_mir/src/transform/nrvo.rs index 7e05d66074bb1..0b440086dd83d 100644 --- a/compiler/rustc_mir/src/transform/nrvo.rs +++ b/compiler/rustc_mir/src/transform/nrvo.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor} use rustc_middle::mir::{self, BasicBlock, Local, Location}; use rustc_middle::ty::TyCtxt; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; /// This pass looks for MIR that always copies the same local into the return place and eliminates /// the copy by renaming all uses of that local to `_0`. @@ -31,6 +31,8 @@ use crate::transform::MirPass; pub struct RenameReturnPlace; impl<'tcx> MirPass<'tcx> for RenameReturnPlace { + const LEVEL: OptLevel = OptLevel::DEFAULT; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { return; diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 7abc998d3882f..21a3ca63e909e 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -32,7 +32,7 @@ use std::{cmp, iter, mem}; use crate::const_eval::{is_const_fn, is_unstable_const_fn}; use crate::transform::check_consts::{is_lang_panic_fn, qualifs, ConstCx}; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; /// A `MirPass` for promotion. /// @@ -47,6 +47,8 @@ pub struct PromoteTemps<'tcx> { } impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. // diff --git a/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs b/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs index b45c533d2c002..da66ab0696083 100644 --- a/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs @@ -1,4 +1,4 @@ -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use crate::util::patch::MirPatch; use rustc_index::bit_set::BitSet; use rustc_middle::mir::*; @@ -20,6 +20,8 @@ pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) } impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { remove_noop_landing_pads(tcx, body); } diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs index aaf3ecab4dca7..ebc112b74ab33 100644 --- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs +++ b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs @@ -1,6 +1,6 @@ //! This pass replaces a drop of a type that does not need dropping, with a goto -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::{ParamEnv, TyCtxt}; @@ -10,6 +10,8 @@ use super::simplify::simplify_cfg; pub struct RemoveUnneededDrops; impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { + const LEVEL: OptLevel = OptLevel::DEFAULT; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running RemoveUnneededDrops on {:?}", body.source); let mut opt_finder = RemoveUnneededDropsOptimizationFinder { diff --git a/compiler/rustc_mir/src/transform/rustc_peek.rs b/compiler/rustc_mir/src/transform/rustc_peek.rs index 205f718d6e446..386eef6eb3a0c 100644 --- a/compiler/rustc_mir/src/transform/rustc_peek.rs +++ b/compiler/rustc_mir/src/transform/rustc_peek.rs @@ -5,7 +5,7 @@ use rustc_span::symbol::sym; use rustc_span::Span; use rustc_target::spec::abi::Abi; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -22,6 +22,8 @@ use crate::dataflow::{Analysis, JoinSemiLattice, Results, ResultsCursor}; pub struct SanityCheck; impl<'tcx> MirPass<'tcx> for SanityCheck { + const LEVEL: OptLevel = OptLevel::ALWAYS; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { use crate::dataflow::has_rustc_mir_with; let def_id = body.source.def_id(); diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index f0c87bcf513cd..69334b9f2b0f9 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -27,7 +27,7 @@ //! naively generate still contains the `_a = ()` write in the unreachable block "after" the //! return. -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; @@ -55,6 +55,8 @@ pub fn simplify_cfg(body: &mut Body<'_>) { } impl<'tcx> MirPass<'tcx> for SimplifyCfg { + const LEVEL: OptLevel = OptLevel::Cleanup; + fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } @@ -318,6 +320,8 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { pub struct SimplifyLocals; impl<'tcx> MirPass<'tcx> for SimplifyLocals { + const LEVEL: OptLevel = OptLevel::N(1); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("running SimplifyLocals on {:?}", body.source); diff --git a/compiler/rustc_mir/src/transform/simplify_branches.rs b/compiler/rustc_mir/src/transform/simplify_branches.rs index 161856a38ee03..6f5230f305072 100644 --- a/compiler/rustc_mir/src/transform/simplify_branches.rs +++ b/compiler/rustc_mir/src/transform/simplify_branches.rs @@ -1,6 +1,6 @@ //! A pass that simplifies branches when their condition is known. -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -17,6 +17,8 @@ impl SimplifyBranches { } impl<'tcx> MirPass<'tcx> for SimplifyBranches { + const LEVEL: OptLevel = OptLevel::Cleanup; + fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } diff --git a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs index 9f837cf78a608..7aad8513403c3 100644 --- a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs +++ b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs @@ -1,4 +1,4 @@ -use super::MirPass; +use super::{MirPass, OptLevel}; use rustc_middle::{ mir::{ interpret::Scalar, BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement, @@ -24,6 +24,8 @@ use rustc_middle::{ pub struct SimplifyComparisonIntegral; impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { + const LEVEL: OptLevel = OptLevel::N(2); + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running SimplifyComparisonIntegral on {:?}", body.source); diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir/src/transform/simplify_try.rs index a4e7a5a94533d..16ec3488520cb 100644 --- a/compiler/rustc_mir/src/transform/simplify_try.rs +++ b/compiler/rustc_mir/src/transform/simplify_try.rs @@ -9,7 +9,7 @@ //! //! into just `x`. -use crate::transform::{simplify, MirPass}; +use crate::transform::{simplify, MirPass, OptLevel}; use itertools::Itertools as _; use rustc_index::{bit_set::BitSet, vec::IndexVec}; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; @@ -367,12 +367,10 @@ fn optimization_applies<'tcx>( } impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // FIXME(77359): This optimization can result in unsoundness. - if !tcx.sess.opts.debugging_opts.unsound_mir_opts { - return; - } + // FIXME(77359): This optimization can result in unsoundness. + const LEVEL: OptLevel = OptLevel::Unsound; + fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let source = body.source; trace!("running SimplifyArmIdentity on {:?}", source); @@ -530,6 +528,8 @@ fn match_variant_field_place<'tcx>(place: Place<'tcx>) -> Option<(Local, VarFiel pub struct SimplifyBranchSame; impl<'tcx> MirPass<'tcx> for SimplifyBranchSame { + const LEVEL: OptLevel = OptLevel::DEFAULT; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running SimplifyBranchSame on {:?}", body.source); let finder = SimplifyBranchSameOptimizationFinder { body, tcx }; diff --git a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs b/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs index 87906e83ed56c..bce6195ebfc76 100644 --- a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs @@ -1,6 +1,6 @@ //! A pass that eliminates branches on uninhabited enum variants. -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_data_structures::stable_set::FxHashSet; use rustc_middle::mir::{ BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind, @@ -71,6 +71,8 @@ fn variant_discriminants<'tcx>( } impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { + const LEVEL: OptLevel = OptLevel::DEFAULT; + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if body.source.promoted.is_some() { return; diff --git a/compiler/rustc_mir/src/transform/unreachable_prop.rs b/compiler/rustc_mir/src/transform/unreachable_prop.rs index c6426a06ea155..de43641453105 100644 --- a/compiler/rustc_mir/src/transform/unreachable_prop.rs +++ b/compiler/rustc_mir/src/transform/unreachable_prop.rs @@ -3,7 +3,7 @@ //! post-order traversal of the blocks. use crate::transform::simplify; -use crate::transform::MirPass; +use crate::transform::{MirPass, OptLevel}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -12,13 +12,11 @@ use std::borrow::Cow; pub struct UnreachablePropagation; impl MirPass<'_> for UnreachablePropagation { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level < 3 { - // Enable only under -Zmir-opt-level=3 as in some cases (check the deeply-nested-opt - // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code. - return; - } + // Enable only under -Zmir-opt-level=3 as in some cases (check the deeply-nested-opt + // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code. + const LEVEL: OptLevel = OptLevel::N(3); + fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut unreachable_blocks = FxHashSet::default(); let mut replacements = FxHashMap::default(); From 5b46f91e3be343d0280ecdfbd1572ca9f5925980 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 7 Oct 2020 11:11:50 -0700 Subject: [PATCH 3/5] `Validate` is not a MIR transformation In general, read-only passes should not be declared as a `MirPass`, since they always run and their MIR dump provides no additional information. --- compiler/rustc_mir/src/transform/validate.rs | 49 +++++++++----------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs index cf51e86c5bc8f..4843d3aa8dc86 100644 --- a/compiler/rustc_mir/src/transform/validate.rs +++ b/compiler/rustc_mir/src/transform/validate.rs @@ -4,7 +4,6 @@ use crate::dataflow::impls::MaybeStorageLive; use crate::dataflow::{Analysis, ResultsCursor}; use crate::util::storage::AlwaysLiveLocals; -use super::MirPass; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, Rvalue, @@ -13,38 +12,32 @@ use rustc_middle::mir::{ use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; -#[derive(Copy, Clone, Debug)] -enum EdgeKind { - Unwind, - Normal, +pub fn validate_body(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: &str) { + validate_body_during_phase(tcx, body, body.phase, when); } -pub struct Validator { - /// Describes at which point in the pipeline this validation is happening. - pub when: String, - /// The phase for which we are upholding the dialect. If the given phase forbids a specific - /// element, this validator will now emit errors if that specific element is encountered. - /// Note that phases that change the dialect cause all *following* phases to check the - /// invariants of the new dialect. A phase that changes dialects never checks the new invariants - /// itself. - pub mir_phase: MirPhase, -} +pub fn validate_body_during_phase( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + phase: MirPhase, + when: &str, +) { + let def_id = body.source.def_id(); + let param_env = tcx.param_env(def_id); -impl<'tcx> MirPass<'tcx> for Validator { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let def_id = body.source.def_id(); - let param_env = tcx.param_env(def_id); - let mir_phase = self.mir_phase; + let always_live_locals = AlwaysLiveLocals::new(body); + let storage_liveness = MaybeStorageLive::new(always_live_locals) + .into_engine(tcx, body) + .iterate_to_fixpoint() + .into_results_cursor(body); - let always_live_locals = AlwaysLiveLocals::new(body); - let storage_liveness = MaybeStorageLive::new(always_live_locals) - .into_engine(tcx, body) - .iterate_to_fixpoint() - .into_results_cursor(body); + TypeChecker { when, body, tcx, param_env, mir_phase: phase, storage_liveness }.visit_body(body); +} - TypeChecker { when: &self.when, body, tcx, param_env, mir_phase, storage_liveness } - .visit_body(body); - } +#[derive(Copy, Clone, Debug)] +enum EdgeKind { + Unwind, + Normal, } /// Returns whether the two types are equal up to lifetimes. From 51da28aeaf350969ece7938ad050c075c9e4f385 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 7 Oct 2020 11:49:31 -0700 Subject: [PATCH 4/5] Add mechanism for skipping MIR passes --- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_mir/src/transform/pass.rs | 21 ++++++++++++++++++--- compiler/rustc_session/src/options.rs | 2 ++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 07ce9d0cd9484..f1a76dd418948 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -558,6 +558,7 @@ fn test_debugging_options_tracking_hash() { tracked!(link_only, true); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); + tracked!(mir_opt_skip_pass, vec!["ConstProp".to_owned()]); tracked!(mir_opt_level, 3); tracked!(mutable_noalias, true); tracked!(new_llvm_pass_manager, true); diff --git a/compiler/rustc_mir/src/transform/pass.rs b/compiler/rustc_mir/src/transform/pass.rs index fc10ae8a32449..71832b64d40f8 100644 --- a/compiler/rustc_mir/src/transform/pass.rs +++ b/compiler/rustc_mir/src/transform/pass.rs @@ -72,9 +72,12 @@ impl PassManager<'mir, 'tcx> { ret } - fn is_pass_enabled(&self, level: OptLevel) -> bool { + fn is_pass_enabled

(&self, pass: &P) -> bool + where + P: MirPass<'tcx>, + { let opts = &self.tcx.sess.opts.debugging_opts; - let level_required = match level { + let level_required = match P::LEVEL { OptLevel::Cleanup => return !self.skip_cleanup, OptLevel::Unsound if !opts.unsound_mir_opts => return false, @@ -82,7 +85,12 @@ impl PassManager<'mir, 'tcx> { OptLevel::N(n) => n, }; - opts.mir_opt_level >= level_required as usize + // Optimization passes that are not always run can be disabled + if level_required != 0 && is_skipped(&pass.name(), &opts.mir_opt_skip_pass) { + return false; + } + + opts.mir_opt_level >= level_required.into() } pub fn validate(&self, when: &str) { @@ -145,3 +153,10 @@ macro_rules! run_passes { $( manager.run_pass(&$pass); )* }} } + +fn is_skipped(pass_name: &str, skipped_passes: &[String]) -> bool { + skipped_passes + .into_iter() + .filter(|skipped| !skipped.is_empty()) + .any(|skipped| pass_name.starts_with(skipped)) +} diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index a106007c274d3..082028d95baea 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -959,6 +959,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, mir_emit_retag: bool = (false, parse_bool, [TRACKED], "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \ (default: no)"), + mir_opt_skip_pass: Vec = (Vec::new(), parse_string_push, [TRACKED], + "MIR optimization passes that will not run (default: [])"), mir_opt_level: usize = (1, parse_uint, [TRACKED], "MIR optimization level (0-3; default: 1)"), mutable_noalias: bool = (false, parse_bool, [TRACKED], From d32556481a4f64a0afbd94bef64490e3eace9068 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 10 Oct 2020 15:07:21 -0700 Subject: [PATCH 5/5] Add missing flags for `mir-opt` tests of unsound passes These don't actually test anything since whoever implemented `-Zunsound-mir-opts` forgot to set it when unsound passes were checked. They break now that the passes are skipped entirely without `-Zunsound-mir-opts` instead of just being no-ops. --- ...opagation_arg.arg_src.CopyPropagation.diff | 20 ++--- ...y_propagation_arg.bar.CopyPropagation.diff | 28 +++---- ...y_propagation_arg.baz.CopyPropagation.diff | 18 ++--- ...y_propagation_arg.foo.CopyPropagation.diff | 28 +++---- src/test/mir-opt/copy_propagation_arg.rs | 2 + src/test/mir-opt/issue-73223.rs | 2 + .../issue_73223.main.PreCodegen.32bit.diff | 44 +++++------ .../issue_73223.main.PreCodegen.64bit.diff | 44 +++++------ ..._73223.main.SimplifyArmIdentity.32bit.diff | 74 +++++++++---------- ..._73223.main.SimplifyArmIdentity.64bit.diff | 74 +++++++++---------- src/test/mir-opt/simplify-arm-identity.rs | 2 +- 11 files changed, 170 insertions(+), 166 deletions(-) diff --git a/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff index 8aab2299d2651..dafb7ba70fd55 100644 --- a/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff +++ b/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff @@ -2,20 +2,20 @@ + // MIR for `arg_src` after CopyPropagation fn arg_src(_1: i32) -> i32 { - debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:27:12: 27:17 - let mut _0: i32; // return place in scope 0 at $DIR/copy_propagation_arg.rs:27:27: 27:30 - let _2: i32; // in scope 0 at $DIR/copy_propagation_arg.rs:28:9: 28:10 + debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:29:12: 29:17 + let mut _0: i32; // return place in scope 0 at $DIR/copy_propagation_arg.rs:29:27: 29:30 + let _2: i32; // in scope 0 at $DIR/copy_propagation_arg.rs:30:9: 30:10 scope 1 { - debug y => _0; // in scope 1 at $DIR/copy_propagation_arg.rs:28:9: 28:10 + debug y => _0; // in scope 1 at $DIR/copy_propagation_arg.rs:30:9: 30:10 } bb0: { - nop; // scope 0 at $DIR/copy_propagation_arg.rs:28:9: 28:10 - _0 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:28:13: 28:14 - _1 = const 123_i32; // scope 1 at $DIR/copy_propagation_arg.rs:29:5: 29:12 - nop; // scope 1 at $DIR/copy_propagation_arg.rs:30:5: 30:6 - nop; // scope 0 at $DIR/copy_propagation_arg.rs:31:1: 31:2 - return; // scope 0 at $DIR/copy_propagation_arg.rs:31:2: 31:2 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:30:9: 30:10 + _0 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:30:13: 30:14 + _1 = const 123_i32; // scope 1 at $DIR/copy_propagation_arg.rs:31:5: 31:12 + nop; // scope 1 at $DIR/copy_propagation_arg.rs:32:5: 32:6 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:33:1: 33:2 + return; // scope 0 at $DIR/copy_propagation_arg.rs:33:2: 33:2 } } diff --git a/src/test/mir-opt/copy_propagation_arg.bar.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.bar.CopyPropagation.diff index fb793e53ea8a7..ea0de091bd23d 100644 --- a/src/test/mir-opt/copy_propagation_arg.bar.CopyPropagation.diff +++ b/src/test/mir-opt/copy_propagation_arg.bar.CopyPropagation.diff @@ -2,27 +2,27 @@ + // MIR for `bar` after CopyPropagation fn bar(_1: u8) -> () { - debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:15:8: 15:13 - let mut _0: (); // return place in scope 0 at $DIR/copy_propagation_arg.rs:15:19: 15:19 - let _2: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:16:5: 16:13 - let mut _3: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:16:11: 16:12 + debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:17:8: 17:13 + let mut _0: (); // return place in scope 0 at $DIR/copy_propagation_arg.rs:17:19: 17:19 + let _2: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:18:5: 18:13 + let mut _3: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:18:11: 18:12 bb0: { - StorageLive(_2); // scope 0 at $DIR/copy_propagation_arg.rs:16:5: 16:13 - StorageLive(_3); // scope 0 at $DIR/copy_propagation_arg.rs:16:11: 16:12 - _3 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:16:11: 16:12 - _2 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:16:5: 16:13 + StorageLive(_2); // scope 0 at $DIR/copy_propagation_arg.rs:18:5: 18:13 + StorageLive(_3); // scope 0 at $DIR/copy_propagation_arg.rs:18:11: 18:12 + _3 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:18:11: 18:12 + _2 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:18:5: 18:13 // mir::Constant - // + span: $DIR/copy_propagation_arg.rs:16:5: 16:10 + // + span: $DIR/copy_propagation_arg.rs:18:5: 18:10 // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(Scalar()) } } bb1: { - StorageDead(_3); // scope 0 at $DIR/copy_propagation_arg.rs:16:12: 16:13 - StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:16:13: 16:14 - _1 = const 5_u8; // scope 0 at $DIR/copy_propagation_arg.rs:17:5: 17:10 - _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:15:19: 18:2 - return; // scope 0 at $DIR/copy_propagation_arg.rs:18:2: 18:2 + StorageDead(_3); // scope 0 at $DIR/copy_propagation_arg.rs:18:12: 18:13 + StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:18:13: 18:14 + _1 = const 5_u8; // scope 0 at $DIR/copy_propagation_arg.rs:19:5: 19:10 + _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:17:19: 20:2 + return; // scope 0 at $DIR/copy_propagation_arg.rs:20:2: 20:2 } } diff --git a/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff index 1ea51fec71069..ad57f5555f380 100644 --- a/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff +++ b/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff @@ -2,17 +2,17 @@ + // MIR for `baz` after CopyPropagation fn baz(_1: i32) -> () { - debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:21:8: 21:13 - let mut _0: (); // return place in scope 0 at $DIR/copy_propagation_arg.rs:21:20: 21:20 - let mut _2: i32; // in scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10 + debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:23:8: 23:13 + let mut _0: (); // return place in scope 0 at $DIR/copy_propagation_arg.rs:23:20: 23:20 + let mut _2: i32; // in scope 0 at $DIR/copy_propagation_arg.rs:25:9: 25:10 bb0: { - nop; // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10 - nop; // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10 - nop; // scope 0 at $DIR/copy_propagation_arg.rs:23:5: 23:10 - nop; // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10 - _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:21:20: 24:2 - return; // scope 0 at $DIR/copy_propagation_arg.rs:24:2: 24:2 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:25:9: 25:10 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:25:9: 25:10 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:25:5: 25:10 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:25:9: 25:10 + _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:23:20: 26:2 + return; // scope 0 at $DIR/copy_propagation_arg.rs:26:2: 26:2 } } diff --git a/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff index 48ab37a239c62..bd05f75f8ba9a 100644 --- a/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff +++ b/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff @@ -2,27 +2,27 @@ + // MIR for `foo` after CopyPropagation fn foo(_1: u8) -> () { - debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:9:8: 9:13 - let mut _0: (); // return place in scope 0 at $DIR/copy_propagation_arg.rs:9:19: 9:19 - let mut _2: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17 - let mut _3: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16 + debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:11:8: 11:13 + let mut _0: (); // return place in scope 0 at $DIR/copy_propagation_arg.rs:11:19: 11:19 + let mut _2: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:13:9: 13:17 + let mut _3: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:13:15: 13:16 bb0: { - nop; // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17 - StorageLive(_3); // scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16 - _3 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16 - _1 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:13:9: 13:17 + StorageLive(_3); // scope 0 at $DIR/copy_propagation_arg.rs:13:15: 13:16 + _3 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:13:15: 13:16 + _1 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:13:9: 13:17 // mir::Constant - // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14 + // + span: $DIR/copy_propagation_arg.rs:13:9: 13:14 // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(Scalar()) } } bb1: { - StorageDead(_3); // scope 0 at $DIR/copy_propagation_arg.rs:11:16: 11:17 - nop; // scope 0 at $DIR/copy_propagation_arg.rs:11:5: 11:17 - nop; // scope 0 at $DIR/copy_propagation_arg.rs:11:16: 11:17 - _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:9:19: 12:2 - return; // scope 0 at $DIR/copy_propagation_arg.rs:12:2: 12:2 + StorageDead(_3); // scope 0 at $DIR/copy_propagation_arg.rs:13:16: 13:17 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:13:5: 13:17 + nop; // scope 0 at $DIR/copy_propagation_arg.rs:13:16: 13:17 + _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:11:19: 14:2 + return; // scope 0 at $DIR/copy_propagation_arg.rs:14:2: 14:2 } } diff --git a/src/test/mir-opt/copy_propagation_arg.rs b/src/test/mir-opt/copy_propagation_arg.rs index 3a00fc58a4ea8..6dca1aed3e356 100644 --- a/src/test/mir-opt/copy_propagation_arg.rs +++ b/src/test/mir-opt/copy_propagation_arg.rs @@ -1,3 +1,5 @@ +// compile-flags: -Z unsound-mir-opts + // Check that CopyPropagation does not propagate an assignment to a function argument // (doing so can break usages of the original argument value) diff --git a/src/test/mir-opt/issue-73223.rs b/src/test/mir-opt/issue-73223.rs index 703b876123133..954ad4b102110 100644 --- a/src/test/mir-opt/issue-73223.rs +++ b/src/test/mir-opt/issue-73223.rs @@ -1,3 +1,5 @@ +// compile-flags: -Z unsound-mir-opts -Z mir-opt-skip-pass=CopyProp + fn main() { let split = match Some(1) { Some(v) => v, diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff index ef7c73068faf6..2971634c4ec6e 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff @@ -2,10 +2,10 @@ + // MIR for `main` after PreCodegen fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:1:11: 1:11 - let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14 - let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - let _3: i32; // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15 + let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:3:11: 3:11 + let _1: i32; // in scope 0 at $DIR/issue-73223.rs:4:9: 4:14 + let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + let _3: i32; // in scope 0 at $DIR/issue-73223.rs:5:14: 5: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 _9: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -23,10 +23,10 @@ let mut _21: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _22: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL scope 1 { - debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 - let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 + debug split => _1; // in scope 1 at $DIR/issue-73223.rs:4:9: 4:14 + let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:9:9: 9:14 scope 3 { - debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14 + debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:9:9: 9:14 let _7: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _8: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 4 { @@ -61,7 +61,7 @@ } } scope 2 { - debug v => _3; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15 + debug v => _3; // in scope 2 at $DIR/issue-73223.rs:5:14: 5:15 } scope 7 { } @@ -69,17 +69,17 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14 - StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:3:14: 3:15 - _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:3:14: 3:15 - _1 = _3; // scope 2 at $DIR/issue-73223.rs:3:20: 3:21 - StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:3:20: 3:21 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7 - ((_4 as Some).0: i32) = _1; // scope 1 at $DIR/issue-73223.rs:7:22: 7:27 - discriminant(_4) = 1; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28 + StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:4:9: 4:14 + StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:5:14: 5:15 + _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:5:14: 5:15 + _1 = _3; // scope 2 at $DIR/issue-73223.rs:5:20: 5:21 + StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:5:20: 5:21 + StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:7:6: 7:7 + ((_4 as Some).0: i32) = _1; // scope 1 at $DIR/issue-73223.rs:9:22: 9:27 + discriminant(_4) = 1; // scope 1 at $DIR/issue-73223.rs:9:17: 9:28 (_5.0: &i32) = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _6 = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const @@ -108,9 +108,9 @@ StorageDead(_9); // scope 4 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(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2 - return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 + _0 = const (); // scope 0 at $DIR/issue-73223.rs:3:11: 11:2 + StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:11:1: 11:2 + return; // scope 0 at $DIR/issue-73223.rs:11:2: 11:2 } bb2: { diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff index ef7c73068faf6..2971634c4ec6e 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff @@ -2,10 +2,10 @@ + // MIR for `main` after PreCodegen fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:1:11: 1:11 - let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14 - let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - let _3: i32; // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15 + let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:3:11: 3:11 + let _1: i32; // in scope 0 at $DIR/issue-73223.rs:4:9: 4:14 + let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + let _3: i32; // in scope 0 at $DIR/issue-73223.rs:5:14: 5: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 _9: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -23,10 +23,10 @@ let mut _21: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _22: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL scope 1 { - debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 - let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 + debug split => _1; // in scope 1 at $DIR/issue-73223.rs:4:9: 4:14 + let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:9:9: 9:14 scope 3 { - debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14 + debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:9:9: 9:14 let _7: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _8: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 4 { @@ -61,7 +61,7 @@ } } scope 2 { - debug v => _3; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15 + debug v => _3; // in scope 2 at $DIR/issue-73223.rs:5:14: 5:15 } scope 7 { } @@ -69,17 +69,17 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14 - StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:3:14: 3:15 - _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:3:14: 3:15 - _1 = _3; // scope 2 at $DIR/issue-73223.rs:3:20: 3:21 - StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:3:20: 3:21 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7 - ((_4 as Some).0: i32) = _1; // scope 1 at $DIR/issue-73223.rs:7:22: 7:27 - discriminant(_4) = 1; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28 + StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:4:9: 4:14 + StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + StorageLive(_3); // scope 0 at $DIR/issue-73223.rs:5:14: 5:15 + _3 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:5:14: 5:15 + _1 = _3; // scope 2 at $DIR/issue-73223.rs:5:20: 5:21 + StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:5:20: 5:21 + StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:7:6: 7:7 + ((_4 as Some).0: i32) = _1; // scope 1 at $DIR/issue-73223.rs:9:22: 9:27 + discriminant(_4) = 1; // scope 1 at $DIR/issue-73223.rs:9:17: 9:28 (_5.0: &i32) = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _6 = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const @@ -108,9 +108,9 @@ StorageDead(_9); // scope 4 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(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2 - return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 + _0 = const (); // scope 0 at $DIR/issue-73223.rs:3:11: 11:2 + StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:11:1: 11:2 + return; // scope 0 at $DIR/issue-73223.rs:11:2: 11:2 } bb2: { diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff index 9039735f6ba38..85115c5b3c7ec 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff @@ -2,18 +2,18 @@ + // MIR for `main` after SimplifyArmIdentity fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:1:11: 1:11 - let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14 - let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - let mut _3: isize; // in scope 0 at $DIR/issue-73223.rs:3:9: 3:16 - let _4: i32; // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15 - let mut _5: !; // in scope 0 at $DIR/issue-73223.rs:4:17: 4:23 - let mut _7: i32; // in scope 0 at $DIR/issue-73223.rs:7:22: 7:27 + let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:3:11: 3:11 + let _1: i32; // in scope 0 at $DIR/issue-73223.rs:4:9: 4:14 + let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + let mut _3: isize; // in scope 0 at $DIR/issue-73223.rs:5:9: 5:16 + let _4: i32; // in scope 0 at $DIR/issue-73223.rs:5:14: 5:15 + let mut _5: !; // in scope 0 at $DIR/issue-73223.rs:6:17: 6:23 + let mut _7: i32; // in scope 0 at $DIR/issue-73223.rs:9:22: 9:27 let _8: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _9: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _10: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _11: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _12: i32; // in scope 0 at $DIR/issue-73223.rs:8:23: 8:24 + let _12: i32; // in scope 0 at $DIR/issue-73223.rs:10:23: 10:24 let mut _15: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _16: bool; // 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 @@ -42,10 +42,10 @@ let mut _42: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _43: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // 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:2:9: 2:14 - let _6: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 + debug split => _1; // in scope 1 at $DIR/issue-73223.rs:4:9: 4:14 + let _6: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:9:9: 9:14 scope 3 { - debug _prev => _6; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14 + debug _prev => _6; // in scope 3 at $DIR/issue-73223.rs:9:9: 9:14 let _13: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _14: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _45: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -86,7 +86,7 @@ } } scope 2 { - debug v => _4; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15 + debug v => _4; // in scope 2 at $DIR/issue-73223.rs:5:14: 5:15 } scope 7 { } @@ -94,33 +94,33 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14 - StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - _3 = const 1_isize; // scope 0 at $DIR/issue-73223.rs:3:9: 3:16 - goto -> bb2; // scope 0 at $DIR/issue-73223.rs:3:9: 3:16 + StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:4:9: 4:14 + StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + _3 = const 1_isize; // scope 0 at $DIR/issue-73223.rs:5:9: 5:16 + goto -> bb2; // scope 0 at $DIR/issue-73223.rs:5:9: 5:16 } bb1: { - _0 = const (); // scope 0 at $DIR/issue-73223.rs:4:17: 4:23 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2 - return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 + _0 = const (); // scope 0 at $DIR/issue-73223.rs:6:17: 6:23 + StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:7:6: 7:7 + StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:11:1: 11:2 + return; // scope 0 at $DIR/issue-73223.rs:11:2: 11:2 } bb2: { - StorageLive(_4); // scope 0 at $DIR/issue-73223.rs:3:14: 3:15 - _4 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:3:14: 3:15 - _1 = _4; // scope 2 at $DIR/issue-73223.rs:3:20: 3:21 - StorageDead(_4); // scope 0 at $DIR/issue-73223.rs:3:20: 3:21 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7 - StorageLive(_6); // scope 1 at $DIR/issue-73223.rs:7:9: 7:14 - StorageLive(_7); // scope 1 at $DIR/issue-73223.rs:7:22: 7:27 - _7 = _1; // scope 1 at $DIR/issue-73223.rs:7:22: 7:27 - ((_6 as Some).0: i32) = move _7; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28 - discriminant(_6) = 1; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28 - StorageDead(_7); // scope 1 at $DIR/issue-73223.rs:7:27: 7:28 + StorageLive(_4); // scope 0 at $DIR/issue-73223.rs:5:14: 5:15 + _4 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:5:14: 5:15 + _1 = _4; // scope 2 at $DIR/issue-73223.rs:5:20: 5:21 + StorageDead(_4); // scope 0 at $DIR/issue-73223.rs:5:20: 5:21 + StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:7:6: 7:7 + StorageLive(_6); // scope 1 at $DIR/issue-73223.rs:9:9: 9:14 + StorageLive(_7); // scope 1 at $DIR/issue-73223.rs:9:22: 9:27 + _7 = _1; // scope 1 at $DIR/issue-73223.rs:9:22: 9:27 + ((_6 as Some).0: i32) = move _7; // scope 1 at $DIR/issue-73223.rs:9:17: 9:28 + discriminant(_6) = 1; // scope 1 at $DIR/issue-73223.rs:9:17: 9:28 + StorageDead(_7); // scope 1 at $DIR/issue-73223.rs:9:27: 9:28 StorageLive(_8); // 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 StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -163,10 +163,10 @@ StorageDead(_13); // scope 3 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 - _0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2 - StorageDead(_6); // scope 1 at $DIR/issue-73223.rs:9:1: 9:2 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2 - return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 + _0 = const (); // scope 0 at $DIR/issue-73223.rs:3:11: 11:2 + StorageDead(_6); // scope 1 at $DIR/issue-73223.rs:11:1: 11:2 + StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:11:1: 11:2 + return; // scope 0 at $DIR/issue-73223.rs:11:2: 11:2 } bb4: { diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff index 9039735f6ba38..85115c5b3c7ec 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff @@ -2,18 +2,18 @@ + // MIR for `main` after SimplifyArmIdentity fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:1:11: 1:11 - let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14 - let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - let mut _3: isize; // in scope 0 at $DIR/issue-73223.rs:3:9: 3:16 - let _4: i32; // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15 - let mut _5: !; // in scope 0 at $DIR/issue-73223.rs:4:17: 4:23 - let mut _7: i32; // in scope 0 at $DIR/issue-73223.rs:7:22: 7:27 + let mut _0: (); // return place in scope 0 at $DIR/issue-73223.rs:3:11: 3:11 + let _1: i32; // in scope 0 at $DIR/issue-73223.rs:4:9: 4:14 + let mut _2: std::option::Option; // in scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + let mut _3: isize; // in scope 0 at $DIR/issue-73223.rs:5:9: 5:16 + let _4: i32; // in scope 0 at $DIR/issue-73223.rs:5:14: 5:15 + let mut _5: !; // in scope 0 at $DIR/issue-73223.rs:6:17: 6:23 + let mut _7: i32; // in scope 0 at $DIR/issue-73223.rs:9:22: 9:27 let _8: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _9: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _10: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _11: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _12: i32; // in scope 0 at $DIR/issue-73223.rs:8:23: 8:24 + let _12: i32; // in scope 0 at $DIR/issue-73223.rs:10:23: 10:24 let mut _15: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _16: bool; // 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 @@ -42,10 +42,10 @@ let mut _42: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _43: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // 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:2:9: 2:14 - let _6: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 + debug split => _1; // in scope 1 at $DIR/issue-73223.rs:4:9: 4:14 + let _6: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:9:9: 9:14 scope 3 { - debug _prev => _6; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14 + debug _prev => _6; // in scope 3 at $DIR/issue-73223.rs:9:9: 9:14 let _13: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _14: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _45: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -86,7 +86,7 @@ } } scope 2 { - debug v => _4; // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15 + debug v => _4; // in scope 2 at $DIR/issue-73223.rs:5:14: 5:15 } scope 7 { } @@ -94,33 +94,33 @@ } bb0: { - StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:2:9: 2:14 - StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30 - _3 = const 1_isize; // scope 0 at $DIR/issue-73223.rs:3:9: 3:16 - goto -> bb2; // scope 0 at $DIR/issue-73223.rs:3:9: 3:16 + StorageLive(_1); // scope 0 at $DIR/issue-73223.rs:4:9: 4:14 + StorageLive(_2); // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + discriminant(_2) = 1; // scope 0 at $DIR/issue-73223.rs:4:23: 4:30 + _3 = const 1_isize; // scope 0 at $DIR/issue-73223.rs:5:9: 5:16 + goto -> bb2; // scope 0 at $DIR/issue-73223.rs:5:9: 5:16 } bb1: { - _0 = const (); // scope 0 at $DIR/issue-73223.rs:4:17: 4:23 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2 - return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 + _0 = const (); // scope 0 at $DIR/issue-73223.rs:6:17: 6:23 + StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:7:6: 7:7 + StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:11:1: 11:2 + return; // scope 0 at $DIR/issue-73223.rs:11:2: 11:2 } bb2: { - StorageLive(_4); // scope 0 at $DIR/issue-73223.rs:3:14: 3:15 - _4 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:3:14: 3:15 - _1 = _4; // scope 2 at $DIR/issue-73223.rs:3:20: 3:21 - StorageDead(_4); // scope 0 at $DIR/issue-73223.rs:3:20: 3:21 - StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7 - StorageLive(_6); // scope 1 at $DIR/issue-73223.rs:7:9: 7:14 - StorageLive(_7); // scope 1 at $DIR/issue-73223.rs:7:22: 7:27 - _7 = _1; // scope 1 at $DIR/issue-73223.rs:7:22: 7:27 - ((_6 as Some).0: i32) = move _7; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28 - discriminant(_6) = 1; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28 - StorageDead(_7); // scope 1 at $DIR/issue-73223.rs:7:27: 7:28 + StorageLive(_4); // scope 0 at $DIR/issue-73223.rs:5:14: 5:15 + _4 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue-73223.rs:5:14: 5:15 + _1 = _4; // scope 2 at $DIR/issue-73223.rs:5:20: 5:21 + StorageDead(_4); // scope 0 at $DIR/issue-73223.rs:5:20: 5:21 + StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:7:6: 7:7 + StorageLive(_6); // scope 1 at $DIR/issue-73223.rs:9:9: 9:14 + StorageLive(_7); // scope 1 at $DIR/issue-73223.rs:9:22: 9:27 + _7 = _1; // scope 1 at $DIR/issue-73223.rs:9:22: 9:27 + ((_6 as Some).0: i32) = move _7; // scope 1 at $DIR/issue-73223.rs:9:17: 9:28 + discriminant(_6) = 1; // scope 1 at $DIR/issue-73223.rs:9:17: 9:28 + StorageDead(_7); // scope 1 at $DIR/issue-73223.rs:9:27: 9:28 StorageLive(_8); // 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 StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -163,10 +163,10 @@ StorageDead(_13); // scope 3 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 - _0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2 - StorageDead(_6); // scope 1 at $DIR/issue-73223.rs:9:1: 9:2 - StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2 - return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 + _0 = const (); // scope 0 at $DIR/issue-73223.rs:3:11: 11:2 + StorageDead(_6); // scope 1 at $DIR/issue-73223.rs:11:1: 11:2 + StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:11:1: 11:2 + return; // scope 0 at $DIR/issue-73223.rs:11:2: 11:2 } bb4: { diff --git a/src/test/mir-opt/simplify-arm-identity.rs b/src/test/mir-opt/simplify-arm-identity.rs index 0a59032e87ba0..b9072a7dc14bd 100644 --- a/src/test/mir-opt/simplify-arm-identity.rs +++ b/src/test/mir-opt/simplify-arm-identity.rs @@ -1,7 +1,7 @@ // Checks that `SimplifyArmIdentity` is not applied if enums have incompatible layouts. // Regression test for issue #66856. // -// compile-flags: -Zmir-opt-level=2 +// compile-flags: -Zmir-opt-level=2 -Zunsound-mir-opts // EMIT_MIR_FOR_EACH_BIT_WIDTH enum Src {