diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 35a21a2a83429..6421ba6d7c866 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -6,6 +6,8 @@ use rustc_middle::ty::{self, TyCtxt, layout}; use rustc_span::sym; use rustc_target::spec::PanicStrategy; +use crate::PassPolicy; + /// A pass that runs which is targeted at ensuring that codegen guarantees about /// unwinding are upheld for compilations of panic=abort programs. /// @@ -138,7 +140,9 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { super::simplify::remove_dead_blocks(body); } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Implements part of MIR semantics, turning effectively implicit aborts into explicit + // ones. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index 831ce81b1d0ee..55d8493d55c3c 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -21,6 +21,8 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use tracing::debug; +use crate::PassPolicy; + #[derive(PartialEq)] pub(super) enum AddCallGuards { AllCallEdges, @@ -127,8 +129,10 @@ impl<'tcx> crate::MirPass<'tcx> for AddCallGuards { basic_blocks.extend(new_blocks); } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Breaks critical edges so codegen can place edge-specific actions without affecting + // other control-flow edges. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index dd3f381c0af5a..378a5618f0faa 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::{self, TyCtxt}; use tracing::debug; use crate::patch::MirPatch; -use crate::util; +use crate::{PassPolicy, util}; /// This pass moves values being dropped that are within a packed /// struct to a separate local before dropping them, to ensure that @@ -70,8 +70,9 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { patch.apply(body); } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Implements part of MIR semantics by making implicit packed-drop handling explicit. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index fc31d502087fd..08c4b0a0dc5e9 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -2,6 +2,7 @@ use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use crate::PassPolicy; use crate::patch::MirPatch; pub(super) struct Subtyper; @@ -65,7 +66,8 @@ impl<'tcx> crate::MirPass<'tcx> for Subtyper { checker.patcher.apply(body); } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Later MIR phases expect all subtyping to be explicit. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index f481a73bfbe5c..ee4fe5b2005c7 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -7,13 +7,15 @@ use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_session::Session; +use crate::PassPolicy; use crate::check_pointers::{BorrowedFieldProjectionMode, PointerCheck, check_pointers}; pub(super) struct CheckAlignment; impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { - fn is_enabled(&self, sess: &Session) -> bool { - sess.ub_checks() + fn policy(&self, sess: &Session) -> PassPolicy { + // When UB checks are enabled this is part of their semantics, not an optimization. + PassPolicy::optional_non_optimization(sess.ub_checks()) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -31,10 +33,6 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { BorrowedFieldProjectionMode::FollowProjections, ); } - - fn is_required(&self) -> bool { - true - } } /// Inserts the actual alignment check's logic. Returns a diff --git a/compiler/rustc_mir_transform/src/check_enums.rs b/compiler/rustc_mir_transform/src/check_enums.rs index ea545317e980d..438463d199c66 100644 --- a/compiler/rustc_mir_transform/src/check_enums.rs +++ b/compiler/rustc_mir_transform/src/check_enums.rs @@ -10,14 +10,17 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypingEnv}; use rustc_session::Session; use tracing::debug; +use crate::PassPolicy; + /// This pass inserts checks for a valid enum discriminant where they are most /// likely to find UB, because checking everywhere like Miri would generate too /// much MIR. pub(super) struct CheckEnums; impl<'tcx> crate::MirPass<'tcx> for CheckEnums { - fn is_enabled(&self, sess: &Session) -> bool { - sess.ub_checks() + fn policy(&self, sess: &Session) -> PassPolicy { + // When UB checks are enabled this is part of their semantics, not an optimization. + PassPolicy::optional_non_optimization(sess.ub_checks()) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -109,10 +112,6 @@ impl<'tcx> crate::MirPass<'tcx> for CheckEnums { } } } - - fn is_required(&self) -> bool { - true - } } /// Represent the different kind of enum checks we can insert. diff --git a/compiler/rustc_mir_transform/src/check_null.rs b/compiler/rustc_mir_transform/src/check_null.rs index beb26a20cd3f8..03208458f2907 100644 --- a/compiler/rustc_mir_transform/src/check_null.rs +++ b/compiler/rustc_mir_transform/src/check_null.rs @@ -5,13 +5,15 @@ use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_session::Session; +use crate::PassPolicy; use crate::check_pointers::{BorrowedFieldProjectionMode, PointerCheck, check_pointers}; pub(super) struct CheckNull; impl<'tcx> crate::MirPass<'tcx> for CheckNull { - fn is_enabled(&self, sess: &Session) -> bool { - sess.ub_checks() + fn policy(&self, sess: &Session) -> PassPolicy { + // When UB checks are enabled this is part of their semantics, not an optimization. + PassPolicy::optional_non_optimization(sess.ub_checks()) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -23,10 +25,6 @@ impl<'tcx> crate::MirPass<'tcx> for CheckNull { BorrowedFieldProjectionMode::NoFollowProjections, ); } - - fn is_required(&self) -> bool { - true - } } fn insert_null_check<'tcx>( diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index 1f2ce9e5dc10d..fa034119fb57c 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -21,6 +21,8 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::adjustment::PointerCoercion; +use crate::PassPolicy; + pub(super) struct CleanupPostBorrowck; impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { @@ -85,7 +87,8 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { } } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Removes administrative MIR instructions that later passes must never see. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 77ec352d5c73d..6ba520f0431a2 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::{Analysis, ResultsCursor}; use tracing::{debug, instrument}; +use crate::PassPolicy; use crate::ssa::{MaybeUninitializedLocals, SsaLocals}; /// Unify locals that copy each other. @@ -21,8 +22,8 @@ use crate::ssa::{MaybeUninitializedLocals, SsaLocals}; pub(super) struct CopyProp; impl<'tcx> crate::MirPass<'tcx> for CopyProp { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 1 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() >= 1) } #[instrument(level = "trace", skip(self, tcx, body))] @@ -95,10 +96,6 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp { crate::simplify::remove_unused_definitions(body); } - - fn is_required(&self) -> bool { - false - } } /// Utility to help performing substitution: for all key-value pairs in `copy_classes`, diff --git a/compiler/rustc_mir_transform/src/coroutine/mod.rs b/compiler/rustc_mir_transform/src/coroutine/mod.rs index a64d23b0b939f..6d9d0d35d3ed6 100644 --- a/compiler/rustc_mir_transform/src/coroutine/mod.rs +++ b/compiler/rustc_mir_transform/src/coroutine/mod.rs @@ -80,7 +80,7 @@ use tracing::{debug, instrument}; use crate::deref_separator::deref_finder; use crate::patch::MirPatch; -use crate::{abort_unwinding_calls, pass_manager as pm, simplify}; +use crate::{PassPolicy, abort_unwinding_calls, pass_manager as pm, simplify}; pub(super) struct StateTransform; @@ -1219,8 +1219,9 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { create_coroutine_resume_function(tcx, transform, body, can_return, can_unwind); } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Implements coroutine semantics by lowering the coroutine body to a state machine. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index c3b7cc45c88ec..a9d9a593a0f26 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -3,6 +3,7 @@ use rustc_middle::mir::{self, BasicBlock, Statement, StatementKind, TerminatorKi use rustc_middle::ty::TyCtxt; use tracing::{debug, debug_span, trace}; +use crate::PassPolicy; use crate::coverage::counters::BcbCountersData; use crate::coverage::graph::CoverageGraph; use crate::coverage::mappings::ExtractedMappings; @@ -24,8 +25,8 @@ mod tests; pub(super) struct InstrumentCoverage; impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.instrument_coverage() + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optional_non_optimization(sess.instrument_coverage()) } fn run_pass(&self, tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) { @@ -54,10 +55,6 @@ impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage { instrument_function_for_coverage(tcx, mir_body); } - - fn is_required(&self) -> bool { - true - } } fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index e2f518bb4ee81..f9334590c1e42 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -8,6 +8,8 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use tracing::instrument; +use crate::PassPolicy; + pub(super) struct CtfeLimit; impl<'tcx> crate::MirPass<'tcx> for CtfeLimit { @@ -37,8 +39,9 @@ impl<'tcx> crate::MirPass<'tcx> for CtfeLimit { } } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // This is part of CTFE diagnostics rather than an optimization. + PassPolicy::optional_non_optimization(true) } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 98153da199d19..7f2e5c05eb5d3 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -26,6 +26,8 @@ use rustc_mir_dataflow::{Analysis, ResultsVisitor, visit_reachable_results}; use rustc_span::DUMMY_SP; use tracing::{debug, debug_span, instrument}; +use crate::PassPolicy; + // 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; @@ -34,8 +36,8 @@ const PLACE_LIMIT: usize = 100; pub(super) struct DataflowConstProp; impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 3 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() >= 3) } #[instrument(skip_all level = "debug")] @@ -74,10 +76,6 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp { let mut patch = visitor.patch; debug_span!("patch").in_scope(|| patch.visit_body_preserves_cfg(body)); } - - fn is_required(&self) -> bool { - false - } } // Note: Currently, places that have their reference taken cannot be tracked. Although this would diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index e968ed640ecf1..879335d15dd98 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -22,6 +22,7 @@ use rustc_mir_dataflow::impls::{ LivenessTransferFunction, MaybeTransitiveLiveLocals, borrowed_locals, }; +use crate::PassPolicy; use crate::simplify::UsedInStmtLocals; use crate::util::most_packed_projection; @@ -140,8 +141,8 @@ impl<'tcx> crate::MirPass<'tcx> for DeadStoreElimination { } } - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 2 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() >= 2) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -152,8 +153,4 @@ impl<'tcx> crate::MirPass<'tcx> for DeadStoreElimination { } } } - - fn is_required(&self) -> bool { - false - } } diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index 4631c8ff680ca..ef5f8931ac600 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -3,6 +3,7 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use crate::PassPolicy; use crate::patch::MirPatch; pub(super) struct Derefer; @@ -101,7 +102,8 @@ impl<'tcx> crate::MirPass<'tcx> for Derefer { deref_finder(tcx, body, true); } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Later MIR stages expect derefs to only appear as the first place projection. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index f6c5ae1e43f60..e392f856696be 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -149,11 +149,13 @@ use rustc_mir_dataflow::points::DenseLocationMap; use rustc_mir_dataflow::{Analysis, EntryStates, GenKill}; use tracing::{debug, trace}; +use crate::PassPolicy; + pub(super) struct DestinationPropagation; impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 2 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() >= 2) } #[tracing::instrument(level = "trace", skip(self, tcx, body))] @@ -232,10 +234,6 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { apply_merges(body, tcx, relevant, merged_locals); } - - fn is_required(&self) -> bool { - false - } } ////////////////////////////////////////////////////////// diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 7adeebd235384..28c7e7facc578 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::{Ty, TyCtxt}; use tracing::trace; use super::simplify::simplify_cfg; +use crate::PassPolicy; use crate::patch::MirPatch; /// This pass optimizes something like @@ -94,8 +95,8 @@ use crate::patch::MirPatch; pub(super) struct EarlyOtherwiseBranch; impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 2 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() >= 2) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -198,10 +199,6 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { simplify_cfg(tcx, body); } } - - fn is_required(&self) -> bool { - false - } } #[derive(Debug)] diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index b2c1314ec08b1..717c1cb39cb61 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -8,6 +8,7 @@ use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::{self, PatternKind, Ty, TyCtxt}; +use crate::PassPolicy; use crate::patch::MirPatch; /// Constructs the types used when accessing a Box's pointer @@ -161,7 +162,8 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { } } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Implements Box dereference semantics so backends and Miri do not have to handle them. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 1fc3f55f8e145..83dd9db5f1367 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -14,6 +14,7 @@ use rustc_mir_dataflow::{ use rustc_span::Span; use tracing::{debug, instrument}; +use crate::PassPolicy; use crate::elaborate_drop::{DropElaborator, DropFlagMode, DropStyle, Unwind, elaborate_drop}; use crate::patch::MirPatch; @@ -87,8 +88,9 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { elaborate_patch.apply(body); } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Implements MIR drop semantics. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/erase_deref_temps.rs b/compiler/rustc_mir_transform/src/erase_deref_temps.rs index 445c567bcb661..a0c3dd930ccf6 100644 --- a/compiler/rustc_mir_transform/src/erase_deref_temps.rs +++ b/compiler/rustc_mir_transform/src/erase_deref_temps.rs @@ -5,6 +5,8 @@ use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use crate::PassPolicy; + struct EraseDerefTempsVisitor<'tcx> { tcx: TyCtxt<'tcx>, } @@ -37,7 +39,8 @@ impl<'tcx> crate::MirPass<'tcx> for EraseDerefTemps { EraseDerefTempsVisitor { tcx }.visit_body_preserves_cfg(body); } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Later MIR stages assume that CopyForDeref is gone. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index f00dd3fde5aac..9d751a7cc5bd0 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -122,13 +122,14 @@ use rustc_span::DUMMY_SP; use smallvec::SmallVec; use tracing::{debug, instrument, trace}; +use crate::PassPolicy; use crate::ssa::{MaybeUninitializedLocals, SsaLocals}; pub(super) struct GVN; impl<'tcx> crate::MirPass<'tcx> for GVN { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 2 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() >= 2) } #[instrument(level = "trace", skip(self, tcx, body))] @@ -185,10 +186,6 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { StorageRemover { tcx, reused_locals: &state.reused_locals, storage_to_remove } .visit_body_preserves_cfg(body); } - - fn is_required(&self) -> bool { - false - } } newtype_index! { diff --git a/compiler/rustc_mir_transform/src/impossible_clauses.rs b/compiler/rustc_mir_transform/src/impossible_clauses.rs index dbe4c9caf5036..39f864d8a8219 100644 --- a/compiler/rustc_mir_transform/src/impossible_clauses.rs +++ b/compiler/rustc_mir_transform/src/impossible_clauses.rs @@ -32,6 +32,7 @@ use rustc_span::def_id::DefId; use rustc_trait_selection::traits; use tracing::trace; +use crate::PassPolicy; use crate::pass_manager::MirPass; fn is_structurally_unsized<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { @@ -113,7 +114,8 @@ impl<'tcx> MirPass<'tcx> for ImpossibleClauses { } } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // This can only replace code proven unreachable with immediate UB, so it cannot remove UB. + PassPolicy::optional_non_optimization(true) } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 0e6aaf3ccf220..765fd8984b446 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -24,7 +24,7 @@ use tracing::{debug, instrument, trace, trace_span}; use crate::cost_checker::{CostChecker, is_call_like}; use crate::simplify::{UsedInStmtLocals, simplify_cfg}; use crate::validate::validate_types; -use crate::{check_inline, util}; +use crate::{PassPolicy, check_inline, util}; pub(crate) mod cycle; @@ -44,19 +44,18 @@ struct CallSite<'tcx> { pub struct Inline; impl<'tcx> crate::MirPass<'tcx> for Inline { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - if let Some(enabled) = sess.opts.unstable_opts.inline_mir { - return enabled; - } - - match sess.mir_opt_level() { - 0 | 1 => false, - 2 => { - (sess.opts.optimize == OptLevel::More || sess.opts.optimize == OptLevel::Aggressive) - && sess.opts.incremental == None - } - _ => true, - } + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + let enabled_by_default = + sess.opts.unstable_opts.inline_mir.unwrap_or_else(|| match sess.mir_opt_level() { + 0 | 1 => false, + 2 => { + (sess.opts.optimize == OptLevel::More + || sess.opts.optimize == OptLevel::Aggressive) + && sess.opts.incremental == None + } + _ => true, + }); + PassPolicy::optimization(enabled_by_default) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -67,10 +66,6 @@ impl<'tcx> crate::MirPass<'tcx> for Inline { simplify_cfg(tcx, body); } } - - fn is_required(&self) -> bool { - false - } } pub struct ForceInline; @@ -82,16 +77,9 @@ impl ForceInline { } impl<'tcx> crate::MirPass<'tcx> for ForceInline { - fn is_enabled(&self, _: &rustc_session::Session) -> bool { - true - } - - fn can_be_overridden(&self) -> bool { - false - } - - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Forced inlining is part of MIR semantics. + PassPolicy::Required } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index c5a54d596b4e5..9d92ac29870b5 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::layout::{IntegerExt, ValidityRequirement}; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, layout}; use rustc_span::{Symbol, sym}; +use crate::PassPolicy; use crate::simplify::simplify_duplicate_switch_targets; pub(super) enum InstSimplify { @@ -25,8 +26,8 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { } } - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 0 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() > 0) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -62,10 +63,6 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { simplify_duplicate_switch_targets(terminator); } } - - fn is_required(&self) -> bool { - false - } } struct InstSimplifyContext<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 6c93472245d2f..e4c74e2dfa23b 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -68,6 +68,7 @@ use rustc_mir_dataflow::value_analysis::{ use rustc_span::DUMMY_SP; use tracing::{debug, instrument, trace}; +use crate::PassPolicy; use crate::cost_checker::CostChecker; pub(super) struct JumpThreading; @@ -75,16 +76,18 @@ pub(super) struct JumpThreading; const MAX_COST: u8 = 100; impl<'tcx> crate::MirPass<'tcx> for JumpThreading { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - if sess.target.is_like_gpu { + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + let enabled_by_default = if sess.target.is_like_gpu { // Jump threading can duplicate calls in control-flow. // This leads to incorrect code when done for so called "convergent" operations on GPU // targets, similar to how inline assembly cannot be duplicated on all targets. // Conservatively prevent this by disabling the pass. // See also issue #137086. - return false; - } - sess.mir_opt_level() >= 2 + false + } else { + sess.mir_opt_level() >= 2 + }; + PassPolicy::optimization(enabled_by_default) } #[instrument(skip_all level = "debug")] @@ -148,10 +151,6 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { opportunities.apply(); } } - - fn is_required(&self) -> bool { - false - } } struct TOFinder<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 2043de792ebab..43cd4198b2621 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -7,6 +7,7 @@ use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_session::Session; +use crate::PassPolicy; use crate::patch::MirPatch; /// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large @@ -31,11 +32,13 @@ pub(super) struct EnumSizeOpt { } impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { - fn is_enabled(&self, sess: &Session) -> bool { + fn policy(&self, sess: &Session) -> PassPolicy { // There are some differences in behavior on wasm and ARM that are not properly // understood, so we conservatively treat this optimization as unsound: // https://github.com/rust-lang/rust/issues/154413 - sess.opts.unstable_opts.unsound_mir_opts && sess.mir_opt_level() >= 3 + PassPolicy::optimization( + sess.opts.unstable_opts.unsound_mir_opts && sess.mir_opt_level() >= 3, + ) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -165,10 +168,6 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { patch.apply(body); } - - fn is_required(&self) -> bool { - false - } } impl EnumSizeOpt { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 30c35ced95498..505881349769d 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -35,7 +35,7 @@ mod pass_manager; use std::sync::LazyLock; -use pass_manager::{self as pm, Lint, MirLint, MirPass, WithMinOptLevel}; +use pass_manager::{self as pm, Lint, MirLint, MirPass, PassPolicy, WithMinOptLevel}; mod check_pointers; mod cost_checker; diff --git a/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs b/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs index 7d902c0149c95..a69b69ef94d59 100644 --- a/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs +++ b/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs @@ -3,6 +3,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNREACHABLE_CODE; +use crate::PassPolicy; use crate::diagnostics::UnreachableDueToUninhabited; /// Lint unreachable code due to uninhabited values from function calls, @@ -82,8 +83,10 @@ impl<'tcx> crate::MirPass<'tcx> for LintAndRemoveUninhabited { } } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Removing visibly uninhabited return edges determines the control flow seen by MIR checks. + // Cannot remove UB: removing the return edge would *introduce* UB if the call actually returned. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index ba294038d702f..6126560949c79 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::sym; -use crate::take_array; +use crate::{PassPolicy, take_array}; pub(super) struct LowerIntrinsics; @@ -339,7 +339,8 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { } } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Implements intrinsic semantics by lowering intrinsic calls to ordinary MIR operations. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 79a9017de3ee1..b157cf3d53d40 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -5,11 +5,13 @@ use rustc_hir::def_id::DefId; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use crate::PassPolicy; + pub(super) struct LowerSliceLenCalls; impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 0 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() > 0) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -26,10 +28,6 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { lower_slice_len_call(block, slice_len_fn_item_def_id); } } - - fn is_required(&self) -> bool { - false - } } fn lower_slice_len_call<'tcx>(block: &mut BasicBlockData<'tcx>, slice_len_fn_item_def_id: DefId) { diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 05f4f6c520978..36eed06fcadda 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::util::Discr; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use super::simplify::simplify_cfg; +use crate::PassPolicy; use crate::patch::MirPatch; use crate::unreachable_prop::remove_successors_from_switch; @@ -13,9 +14,9 @@ use crate::unreachable_prop::remove_successors_from_switch; pub(super) struct MatchBranchSimplification; impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { // Enable only under -Zmir-opt-level=2 as this can make programs less debuggable. - sess.mir_opt_level() >= 2 + PassPolicy::optimization(sess.mir_opt_level() >= 2) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -32,10 +33,6 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { simplify_cfg(tcx, body); } } - - fn is_required(&self) -> bool { - false - } } struct SimplifyMatch<'tcx, 'a> { diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index c98ca2f4da52d..89146f5ce8548 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -5,6 +5,8 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::Session; use rustc_span::Spanned; +use crate::PassPolicy; + pub(super) struct MentionedItems; struct MentionedItemsVisitor<'a, 'tcx> { @@ -14,12 +16,12 @@ struct MentionedItemsVisitor<'a, 'tcx> { } impl<'tcx> crate::MirPass<'tcx> for MentionedItems { - fn is_enabled(&self, _sess: &Session) -> bool { + fn policy(&self, _sess: &Session) -> PassPolicy { // If this pass is skipped the collector assume that nothing got mentioned! We could // potentially skip it in opt-level 0 if we are sure that opt-level will never *remove* uses // of anything, but that still seems fragile. Furthermore, even debug builds use level 1, so // special-casing level 0 is just not worth it. - true + PassPolicy::Required } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { @@ -27,10 +29,6 @@ impl<'tcx> crate::MirPass<'tcx> for MentionedItems { visitor.visit_body(body); body.set_mentioned_items(visitor.mentioned_items); } - - fn is_required(&self) -> bool { - true - } } // This visitor is carefully in sync with the one in `rustc_monomorphize::collector`. We are diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index f59b849e85c62..8f2709e71dfcf 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -5,13 +5,13 @@ use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use crate::simplify; +use crate::{PassPolicy, simplify}; pub(super) struct MultipleReturnTerminators; impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 4 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() >= 4) } fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -34,8 +34,4 @@ impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators { simplify::remove_dead_blocks(body) } - - fn is_required(&self) -> bool { - false - } } diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index ef4f64cb6c87d..798f69d3cc883 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -79,6 +79,52 @@ const fn simplify_pass_type_name(name: &'static str) -> &'static str { } } +/// Rules outlining when this pass may be overridden or suppressed. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub(crate) enum PassPolicy { + /// This pass implements a mandatory lowering step, either to implement parts of the MIR semantics + /// or to bring MIR into a shape that is easier to deal with for later passes/codegen. + /// Passes using this cannot be disabled via any means. They must not remove any UB, as they will + /// run in Miri. They must also come with a comment justifying why they must always run. + Required, + /// An optional pass that may be configured by `-Zmir-enable-passes`. + Optional { + /// Whether this pass should be enabled by default in this session in the absence of + /// an explicit `-Zmir-enable-passes` or `#[optimize(none)]`. + generally_enabled: bool, + /// Whether this is an optimization pass. `#[optimize(none)]` only disables optimization + /// passes. + /// A pass may be optional without being an optimization pass, + /// e.g. if it just adds extra debug checks that one can turn off. + optimization: bool, + }, +} + +impl PassPolicy { + fn and_enabled(self, enabled: bool) -> Self { + match self { + PassPolicy::Required => PassPolicy::Required, + PassPolicy::Optional { generally_enabled: enabled_by_default, optimization } => { + PassPolicy::Optional { + generally_enabled: enabled_by_default && enabled, + optimization, + } + } + } + } + + /// Create a [`PassPolicy::Optional`] that is not an optimization, + /// enabled by default under the given condition. + pub(crate) fn optional_non_optimization(condition: bool) -> Self { + Self::Optional { generally_enabled: condition, optimization: false } + } + + /// Create a [`PassPolicy::Optional`] optimization, enabled by default under the given condition. + pub(crate) fn optimization(condition: bool) -> Self { + Self::Optional { generally_enabled: condition, optimization: true } + } +} + /// 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`. @@ -91,27 +137,14 @@ pub(super) trait MirPass<'tcx> { to_profiler_name(self.name()) } - /// Returns `true` if this pass is enabled with the current combination of compiler flags. - fn is_enabled(&self, _sess: &Session) -> bool { - true - } - - /// Returns `true` if this pass can be overridden by `-Zenable-mir-passes`. This should be - /// true for basically every pass other than those that are necessary for correctness. - fn can_be_overridden(&self) -> bool { - true - } + /// Describes how this pass is enabled and which mechanisms may disable it. + fn policy(&self, sess: &Session) -> PassPolicy; fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); fn is_mir_dump_enabled(&self) -> bool { true } - - /// Returns `true` if this pass must be run (i.e. it is required for soundness). - /// For passes which are strictly optimizations, this should return `false`. - /// If this is `false`, `#[optimize(none)]` will disable the pass. - fn is_required(&self) -> bool; } /// Just like `MirPass`, except it cannot mutate `Body`, and MIR dumping is @@ -121,10 +154,6 @@ pub(super) trait MirLint<'tcx> { const { simplify_pass_type_name(std::any::type_name::()) } } - fn is_enabled(&self, _sess: &Session) -> bool { - true - } - fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>); } @@ -140,10 +169,6 @@ where self.0.name() } - fn is_enabled(&self, sess: &Session) -> bool { - self.0.is_enabled(sess) - } - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { self.0.run_lint(tcx, body) } @@ -152,8 +177,8 @@ where false } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &Session) -> PassPolicy { + PassPolicy::optional_non_optimization(true) } } @@ -167,22 +192,18 @@ where self.1.name() } - fn is_enabled(&self, sess: &Session) -> bool { - sess.mir_opt_level() >= self.0 as usize - } - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { self.1.run_pass(tcx, body) } - fn is_required(&self) -> bool { - self.1.is_required() + fn policy(&self, sess: &Session) -> PassPolicy { + self.1.policy(sess).and_enabled(sess.mir_opt_level() >= self.0 as usize) } } -/// Whether to allow non-[required] optimizations +/// Whether to allow [optimization passes]. /// -/// [required]: MirPass::is_required +/// [optimization passes]: PassPolicy::Optional::optimization #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub(crate) enum Optimizations { /// The current function has `#[optimize(none)]`. @@ -221,23 +242,34 @@ where P: MirPass<'tcx> + ?Sized, { let name = pass.name(); + let pass_override = || { + tcx.sess + .opts + .unstable_opts + .mir_enable_passes + .iter() + .rev() + .find_map(|(name_, polarity)| if name == name_ { Some(*polarity) } else { None }) + }; - if !pass.can_be_overridden() { - return pass.is_enabled(tcx.sess); + match pass.policy(tcx.sess) { + PassPolicy::Required => true, + PassPolicy::Optional { generally_enabled: enabled_by_default, optimization } => { + if let Some(o) = pass_override() { + trace!( + pass = %name, + "{} as requested by flag", + if o { "Running" } else { "Not running" } + ); + o + } else if optimization && optimizations == Optimizations::Suppressed { + trace!(pass = %name, "Not running as requested by `#[optimize(none)]`"); + false + } else { + enabled_by_default + } + } } - - let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; - let overridden = - overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| { - trace!( - pass = %name, - "{} as requested by flag", - if *polarity { "Running" } else { "Not running" }, - ); - *polarity - }); - let suppressed = !pass.is_required() && matches!(optimizations, Optimizations::Suppressed); - overridden.unwrap_or_else(|| !suppressed && pass.is_enabled(tcx.sess)) } fn run_passes_inner<'tcx>( diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs index 135cd5324e65d..532e1097b5546 100644 --- a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs +++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs @@ -6,6 +6,8 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; +use crate::PassPolicy; + pub(super) struct PostAnalysisNormalize; impl<'tcx> crate::MirPass<'tcx> for PostAnalysisNormalize { @@ -16,8 +18,9 @@ impl<'tcx> crate::MirPass<'tcx> for PostAnalysisNormalize { PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body); } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Reveals opaque types and normalizes MIR while transitioning to the runtime dialect. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs index 8217feff24eca..ea1988c0b5c5a 100644 --- a/compiler/rustc_mir_transform/src/prettify.rs +++ b/compiler/rustc_mir_transform/src/prettify.rs @@ -11,6 +11,8 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use rustc_session::Session; +use crate::PassPolicy; + /// Rearranges the basic blocks into a *reverse post-order*. /// /// Thus after this pass, all the successors of a block are later than it in the @@ -18,8 +20,8 @@ use rustc_session::Session; pub(super) struct ReorderBasicBlocks; impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks { - fn is_enabled(&self, _session: &Session) -> bool { - false + fn policy(&self, _session: &Session) -> PassPolicy { + PassPolicy::optional_non_optimization(false) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -35,10 +37,6 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks { permute(body.basic_blocks.as_mut(), &updater.map); } - - fn is_required(&self) -> bool { - false - } } /// Rearranges the locals into *use* order. @@ -50,8 +48,8 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks { pub(super) struct ReorderLocals; impl<'tcx> crate::MirPass<'tcx> for ReorderLocals { - fn is_enabled(&self, _session: &Session) -> bool { - false + fn policy(&self, _session: &Session) -> PassPolicy { + PassPolicy::optional_non_optimization(false) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -89,10 +87,6 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals { permute(&mut body.local_decls, &updater.map); } - - fn is_required(&self) -> bool { - false - } } fn permute(data: &mut IndexVec, map: &IndexSlice) { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 72f15d3c35b2a..1e2c7a5188706 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -27,6 +27,8 @@ use rustc_middle::{bug, mir, span_bug}; use rustc_span::{Span, Spanned}; use tracing::{debug, instrument}; +use crate::PassPolicy; + /// A `MirPass` for promotion. /// /// Promotion is the extraction of promotable temps into separate MIR bodies so they can have @@ -62,8 +64,9 @@ impl<'tcx> crate::MirPass<'tcx> for PromoteTemps<'tcx> { self.promoted_fragments.set(promoted); } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Implements promotion by extracting eligible values into separate constant MIR bodies. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 2643c53eac1ac..1db9c36bee184 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -11,6 +11,7 @@ use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::impls::{MaybeStorageDead, always_storage_live_locals}; use tracing::{debug, instrument}; +use crate::PassPolicy; use crate::ssa::{SsaLocals, StorageLiveLocals}; /// Propagate references using SSA analysis. @@ -72,8 +73,8 @@ use crate::ssa::{SsaLocals, StorageLiveLocals}; pub(super) struct ReferencePropagation; impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 2 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() >= 2) } #[instrument(level = "trace", skip(self, tcx, body))] @@ -82,10 +83,6 @@ impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation { move_to_copy_pointers(tcx, body); while propagate_ssa(tcx, body) {} } - - fn is_required(&self) -> bool { - false - } } /// The SSA analysis done by [`SsaLocals`] treats [`Operand::Move`] as a read, even though in diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index e7c2fb54b2909..7d55756a9a694 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -3,6 +3,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, Instance, TyCtxt}; use tracing::{debug, instrument}; +use crate::PassPolicy; use crate::patch::MirPatch; /// A pass that removes noop landing pads and replaces jumps to them with @@ -11,8 +12,10 @@ use crate::patch::MirPatch; pub(super) struct RemoveNoopLandingPads; impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.panic_strategy().unwinds() + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + // FIXME: isn't this an optimization? Or is the LLVM code so terrible we want this even with + // "no" optimizations? + PassPolicy::optional_non_optimization(sess.panic_strategy().unwinds()) } #[instrument(level = "debug", skip(self, _tcx, body))] @@ -66,10 +69,6 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { }); } } - - fn is_required(&self) -> bool { - true - } } impl RemoveNoopLandingPads { diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs index d56b51bb496e4..bec46896a8d55 100644 --- a/compiler/rustc_mir_transform/src/remove_place_mention.rs +++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs @@ -4,11 +4,13 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use tracing::trace; +use crate::PassPolicy; + pub(super) struct RemovePlaceMention; impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - !sess.opts.unstable_opts.mir_preserve_ub + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optional_non_optimization(!sess.opts.unstable_opts.mir_preserve_ub) } fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -20,8 +22,4 @@ impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention { }) } } - - fn is_required(&self) -> bool { - true - } } diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs index cb97d2c865ac9..47fcbf2420164 100644 --- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -4,11 +4,15 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use tracing::trace; +use crate::PassPolicy; + pub(super) struct RemoveStorageMarkers; impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 0 && !sess.emit_lifetime_markers() + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optional_non_optimization( + sess.mir_opt_level() > 0 && !sess.emit_lifetime_markers(), + ) } fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -22,8 +26,4 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers { }) } } - - fn is_required(&self) -> bool { - true - } } diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 049c407f8f993..19ac267b62836 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -6,6 +6,8 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::{Analysis, MaybeReachable, move_path_children_matching}; +use crate::PassPolicy; + /// Removes `Drop` terminators whose target is known to be uninitialized at /// that point. /// @@ -64,8 +66,9 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { } } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + // Const checking relies on uninitialized drops being removed before drop elaboration. + PassPolicy::Required } } diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 132dc85c68ff3..f36423a8c8e73 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::TyCtxt; use tracing::{debug, trace}; use super::simplify::simplify_cfg; +use crate::PassPolicy; pub(super) struct RemoveUnneededDrops; @@ -39,7 +40,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops { } } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optional_non_optimization(true) } } diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index a82f80a9118b7..6dddf4838a6c3 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -4,11 +4,13 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; +use crate::PassPolicy; + pub(super) struct RemoveZsts; impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 0 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optional_non_optimization(sess.mir_opt_level() > 0) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -27,10 +29,6 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { replacer.visit_basic_block_data(bb, data); } } - - fn is_required(&self) -> bool { - true - } } struct Replacer<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 14ab4fb0e74eb..47d31f4e0d04b 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -45,6 +45,8 @@ use rustc_span::DUMMY_SP; use smallvec::SmallVec; use tracing::{debug, trace}; +use crate::PassPolicy; + pub(super) enum SimplifyCfg { Initial, PromoteConsts, @@ -93,14 +95,14 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg { self.name() } + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(true) + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source); simplify_cfg(tcx, body); } - - fn is_required(&self) -> bool { - false - } } struct CfgSimplifier<'a, 'tcx> { @@ -427,8 +429,8 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals { } } - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 0 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() > 0) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -457,10 +459,6 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals { body.local_decls.shrink_to_fit(); } } - - fn is_required(&self) -> bool { - false - } } pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index 6d854dfcc6445..ceea038444e4d 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -2,6 +2,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use tracing::trace; +use crate::PassPolicy; use crate::patch::MirPatch; pub(super) enum SimplifyConstCondition { @@ -22,6 +23,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { } } + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(true) + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running SimplifyConstCondition on {:?}", body.source); let typing_env = body.typing_env(tcx); @@ -91,8 +96,4 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { } patch.apply(body); } - - fn is_required(&self) -> bool { - false - } } diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 9f5b8ce690be2..a0ce3932a0952 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -8,6 +8,7 @@ use rustc_middle::mir::{ use rustc_middle::ty::{Ty, TyCtxt}; use tracing::trace; +use crate::PassPolicy; use crate::ssa::SsaLocals; /// Pass to convert `if` conditions on integrals into switches on the integral. @@ -26,8 +27,8 @@ use crate::ssa::SsaLocals; pub(super) struct SimplifyComparisonIntegral; impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 1 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() > 1) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -104,10 +105,6 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { TerminatorKind::SwitchInt { discr: Operand::Copy(opt.to_switch_on), targets }; } } - - fn is_required(&self) -> bool { - false - } } struct OptimizationFinder<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 18ec9c4d85181..21ba434acc6ad 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -5,6 +5,7 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use crate::PassPolicy; use crate::strip_debuginfo::drop_invalid_debuginfos; /// Various parts of MIR building introduce temporaries that are commonly not needed. @@ -24,8 +25,8 @@ use crate::strip_debuginfo::drop_invalid_debuginfos; pub(super) struct SingleUseConsts; impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 0 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() > 0) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -87,10 +88,6 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { drop_invalid_debuginfos(body); } - - fn is_required(&self) -> bool { - false - } } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index b18aaa829afd3..b16336fb9150c 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -10,13 +10,14 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields}; use tracing::{debug, instrument}; +use crate::PassPolicy; use crate::patch::MirPatch; pub(super) struct ScalarReplacementOfAggregates; impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 2 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() >= 2) } #[instrument(level = "debug", skip(self, tcx, body))] @@ -49,10 +50,6 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates { } } } - - fn is_required(&self) -> bool { - false - } } /// Identify all locals that are not eligible for SROA. diff --git a/compiler/rustc_mir_transform/src/ssa_range_prop.rs b/compiler/rustc_mir_transform/src/ssa_range_prop.rs index 348c3bc2c9119..0492398fd7bcb 100644 --- a/compiler/rustc_mir_transform/src/ssa_range_prop.rs +++ b/compiler/rustc_mir_transform/src/ssa_range_prop.rs @@ -19,13 +19,14 @@ use rustc_middle::mir::{BasicBlock, Body, Location, Operand, Place, TerminatorKi use rustc_middle::ty::{TyCtxt, TypingEnv}; use rustc_span::DUMMY_SP; +use crate::PassPolicy; use crate::ssa::SsaLocals; pub(super) struct SsaRangePropagation; impl<'tcx> crate::MirPass<'tcx> for SsaRangePropagation { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 1 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() > 1) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -42,10 +43,6 @@ impl<'tcx> crate::MirPass<'tcx> for SsaRangePropagation { range_set.visit_basic_block_data(bb, data); } } - - fn is_required(&self) -> bool { - false - } } struct RangeSet<'tcx, 'body, 'a> { diff --git a/compiler/rustc_mir_transform/src/strip_debuginfo.rs b/compiler/rustc_mir_transform/src/strip_debuginfo.rs index 5931a46660241..7535ab166c757 100644 --- a/compiler/rustc_mir_transform/src/strip_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/strip_debuginfo.rs @@ -3,6 +3,8 @@ use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::debuginfo::debuginfo_locals; use rustc_session::config::MirStripDebugInfo; +use crate::PassPolicy; + /// Conditionally remove some of the VarDebugInfo in MIR. /// /// In particular, stripping non-parameter debug info for tiny, primitive-like @@ -10,8 +12,10 @@ use rustc_session::config::MirStripDebugInfo; pub(super) struct StripDebugInfo; impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.opts.unstable_opts.mir_strip_debuginfo != MirStripDebugInfo::None + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optional_non_optimization( + sess.opts.unstable_opts.mir_strip_debuginfo != MirStripDebugInfo::None, + ) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -34,10 +38,6 @@ impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo { drop_invalid_debuginfos(body); } - - fn is_required(&self) -> bool { - true - } } // Drop invalid debuginfos when strip locals in `var_debug_info`. diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index e40df5b91aca5..0bb6d87379caa 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{Ty, TyCtxt}; use tracing::trace; +use crate::PassPolicy; use crate::patch::MirPatch; pub(super) struct UnreachableEnumBranching; @@ -77,8 +78,8 @@ fn variant_discriminants<'tcx>( } impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 0 + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optimization(sess.mir_opt_level() > 0) } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -169,8 +170,4 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching { patch.apply(body); } - - fn is_required(&self) -> bool { - false - } } diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index ddc33eafc9138..3c9ae691c885c 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -9,14 +9,15 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; +use crate::PassPolicy; use crate::patch::MirPatch; pub(super) struct UnreachablePropagation; impl crate::MirPass<'_> for UnreachablePropagation { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + fn policy(&self, sess: &rustc_session::Session) -> PassPolicy { // Enable only under -Zmir-opt-level=2 as this can make programs less debuggable. - sess.mir_opt_level() >= 2 + PassPolicy::optimization(sess.mir_opt_level() >= 2) } fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -55,10 +56,6 @@ impl crate::MirPass<'_> for UnreachablePropagation { body.basic_blocks_mut()[bb].statements.clear(); } } - - fn is_required(&self) -> bool { - false - } } /// Return whether the current terminator is fully unreachable. diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 5ec2cd81c9c4e..56a9a179c8fcb 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -20,6 +20,7 @@ use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::debuginfo::debuginfo_locals; use rustc_trait_selection::traits::ObligationCtxt; +use crate::PassPolicy; use crate::util::{self, most_packed_projection}; #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -97,8 +98,8 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { } } - fn is_required(&self) -> bool { - true + fn policy(&self, _sess: &rustc_session::Session) -> PassPolicy { + PassPolicy::optional_non_optimization(true) } }