1
Fork 0

Disable non-required MIR opts with optimize(none)

Co-authored-by: Waffle Lapkin <waffle.lapkin@gmail.com>
This commit is contained in:
clubby789 2024-12-09 19:34:51 +00:00
parent cd848c9f3e
commit 7a9661d768
57 changed files with 319 additions and 10 deletions

View file

@ -46,6 +46,12 @@ pub enum OptimizeAttr {
Size, Size,
} }
impl OptimizeAttr {
pub fn do_not_optimize(&self) -> bool {
matches!(self, Self::DoNotOptimize)
}
}
#[derive(Clone, Debug, Encodable, Decodable)] #[derive(Clone, Debug, Encodable, Decodable)]
pub enum DiagnosticAttribute { pub enum DiagnosticAttribute {
// tidy-alphabetical-start // tidy-alphabetical-start

View file

@ -116,4 +116,8 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
// We may have invalidated some `cleanup` blocks so clean those up now. // We may have invalidated some `cleanup` blocks so clean those up now.
super::simplify::remove_dead_blocks(body); super::simplify::remove_dead_blocks(body);
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -75,4 +75,8 @@ impl<'tcx> crate::MirPass<'tcx> for AddCallGuards {
body.basic_blocks_mut().extend(new_blocks); body.basic_blocks_mut().extend(new_blocks);
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -68,6 +68,10 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
patch.apply(body); patch.apply(body);
} }
fn is_required(&self) -> bool {
true
}
} }
fn add_move_for_packed_drop<'tcx>( fn add_move_for_packed_drop<'tcx>(

View file

@ -176,4 +176,8 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag {
} }
} }
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -61,4 +61,8 @@ impl<'tcx> crate::MirPass<'tcx> for Subtyper {
} }
checker.patcher.apply(body); checker.patcher.apply(body);
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -60,6 +60,10 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
} }
} }
} }
fn is_required(&self) -> bool {
true
}
} }
struct PointerFinder<'a, 'tcx> { struct PointerFinder<'a, 'tcx> {

View file

@ -72,4 +72,8 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck {
decl.user_ty = None; decl.user_ty = None;
} }
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -56,6 +56,10 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp {
crate::simplify::remove_unused_definitions(body); crate::simplify::remove_unused_definitions(body);
} }
} }
fn is_required(&self) -> bool {
false
}
} }
/// `SsaLocals` computed equivalence classes between locals considering copy/move assignments. /// `SsaLocals` computed equivalence classes between locals considering copy/move assignments.

View file

@ -1688,6 +1688,10 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
// Run derefer to fix Derefs that are not in the first place // Run derefer to fix Derefs that are not in the first place
deref_finder(tcx, body); deref_finder(tcx, body);
} }
fn is_required(&self) -> bool {
true
}
} }
/// Looks for any assignments between locals (e.g., `_4 = _5`) that will both be converted to fields /// Looks for any assignments between locals (e.g., `_4 = _5`) that will both be converted to fields

View file

@ -61,6 +61,10 @@ impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage {
instrument_function_for_coverage(tcx, mir_body); instrument_function_for_coverage(tcx, mir_body);
} }
fn is_required(&self) -> bool {
false
}
} }
fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) { fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) {

View file

@ -69,7 +69,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
// Don't do any inference if codegen optimizations are disabled and also MIR inlining is not // Don't do any inference if codegen optimizations are disabled and also MIR inlining is not
// enabled. This ensures that we do inference even if someone only passes -Zinline-mir, // enabled. This ensures that we do inference even if someone only passes -Zinline-mir,
// which is less confusing than having to also enable -Copt-level=1. // which is less confusing than having to also enable -Copt-level=1.
let inliner_will_run = pm::should_run_pass(tcx, &inline::Inline) let inliner_will_run = pm::should_run_pass(tcx, &inline::Inline, pm::Optimizations::Allowed)
|| inline::ForceInline::should_run_pass_for_callee(tcx, def_id.to_def_id()); || inline::ForceInline::should_run_pass_for_callee(tcx, def_id.to_def_id());
if matches!(tcx.sess.opts.optimize, OptLevel::No) && !inliner_will_run { if matches!(tcx.sess.opts.optimize, OptLevel::No) && !inliner_will_run {
return false; return false;

View file

@ -36,6 +36,10 @@ impl<'tcx> crate::MirPass<'tcx> for CtfeLimit {
); );
} }
} }
fn is_required(&self) -> bool {
true
}
} }
fn has_back_edge( fn has_back_edge(

View file

@ -71,6 +71,10 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
let mut patch = visitor.patch; let mut patch = visitor.patch;
debug_span!("patch").in_scope(|| patch.visit_body_preserves_cfg(body)); 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 // Note: Currently, places that have their reference taken cannot be tracked. Although this would

View file

@ -147,4 +147,8 @@ impl<'tcx> crate::MirPass<'tcx> for DeadStoreElimination {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
eliminate(tcx, body); eliminate(tcx, body);
} }
fn is_required(&self) -> bool {
false
}
} }

View file

@ -31,6 +31,10 @@ impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks {
simplify_cfg(body); simplify_cfg(body);
} }
} }
fn is_required(&self) -> bool {
false
}
} }
struct OptApplier<'tcx> { struct OptApplier<'tcx> {

View file

@ -81,4 +81,8 @@ impl<'tcx> crate::MirPass<'tcx> for Derefer {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
deref_finder(tcx, body); deref_finder(tcx, body);
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -240,6 +240,10 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
trace!(round_count); trace!(round_count);
} }
fn is_required(&self) -> bool {
false
}
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]

View file

@ -15,6 +15,10 @@ impl<'tcx> crate::MirPass<'tcx> for Marker {
} }
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {} fn run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {}
fn is_required(&self) -> bool {
false
}
} }
pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> { pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> {

View file

@ -227,6 +227,10 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
simplify_cfg(body); simplify_cfg(body);
} }
} }
fn is_required(&self) -> bool {
false
}
} }
#[derive(Debug)] #[derive(Debug)]

View file

@ -150,4 +150,8 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
} }
} }
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -88,6 +88,10 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
elaborate_patch.apply(body); elaborate_patch.apply(body);
deref_finder(tcx, body); deref_finder(tcx, body);
} }
fn is_required(&self) -> bool {
true
}
} }
/// Records unwind edges which are known to be unreachable, because they are in `drop` terminators /// Records unwind edges which are known to be unreachable, because they are in `drop` terminators

View file

@ -163,6 +163,10 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
// statements. // statements.
StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body); StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body);
} }
fn is_required(&self) -> bool {
false
}
} }
newtype_index! { newtype_index! {

View file

@ -53,4 +53,8 @@ impl<'tcx> MirPass<'tcx> for ImpossiblePredicates {
body.local_decls.raw.truncate(body.arg_count + 1); body.local_decls.raw.truncate(body.arg_count + 1);
} }
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -66,6 +66,10 @@ impl<'tcx> crate::MirPass<'tcx> for Inline {
deref_finder(tcx, body); deref_finder(tcx, body);
} }
} }
fn is_required(&self) -> bool {
false
}
} }
pub struct ForceInline; pub struct ForceInline;
@ -85,6 +89,10 @@ impl<'tcx> crate::MirPass<'tcx> for ForceInline {
false false
} }
fn is_required(&self) -> bool {
true
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let span = trace_span!("force_inline", body = %tcx.def_path_str(body.source.def_id())); let span = trace_span!("force_inline", body = %tcx.def_path_str(body.source.def_id()));
let _guard = span.enter(); let _guard = span.enter();

View file

@ -62,6 +62,10 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap());
} }
} }
fn is_required(&self) -> bool {
false
}
} }
struct InstSimplifyContext<'a, 'tcx> { struct InstSimplifyContext<'a, 'tcx> {

View file

@ -105,6 +105,10 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
} }
OpportunitySet::new(body, opportunities).apply(body); OpportunitySet::new(body, opportunities).apply(body);
} }
fn is_required(&self) -> bool {
false
}
} }
#[derive(Debug)] #[derive(Debug)]

View file

@ -200,6 +200,10 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
}); });
} }
} }
fn is_required(&self) -> bool {
false
}
} }
impl EnumSizeOpt { impl EnumSizeOpt {

View file

@ -388,6 +388,7 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
&Lint(sanity_check::SanityCheck), &Lint(sanity_check::SanityCheck),
], ],
None, None,
pm::Optimizations::Allowed,
); );
tcx.alloc_steal_mir(body) tcx.alloc_steal_mir(body)
} }
@ -440,6 +441,7 @@ fn mir_promoted(
&mut body, &mut body,
&[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage], &[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage],
Some(MirPhase::Analysis(AnalysisPhase::Initial)), Some(MirPhase::Analysis(AnalysisPhase::Initial)),
pm::Optimizations::Allowed,
); );
lint_tail_expr_drop_order::run_lint(tcx, def, &body); lint_tail_expr_drop_order::run_lint(tcx, def, &body);
@ -473,7 +475,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
}; };
let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::Const); let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::Const);
pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None); pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None, pm::Optimizations::Allowed);
body body
} }
@ -493,7 +495,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
let is_fn_like = tcx.def_kind(def).is_fn_like(); let is_fn_like = tcx.def_kind(def).is_fn_like();
if is_fn_like { if is_fn_like {
// Do not compute the mir call graph without said call graph actually being used. // Do not compute the mir call graph without said call graph actually being used.
if pm::should_run_pass(tcx, &inline::Inline) if pm::should_run_pass(tcx, &inline::Inline, pm::Optimizations::Allowed)
|| inline::ForceInline::should_run_pass_for_callee(tcx, def.to_def_id()) || inline::ForceInline::should_run_pass_for_callee(tcx, def.to_def_id())
{ {
tcx.ensure_with_value().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id())); tcx.ensure_with_value().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id()));
@ -533,6 +535,7 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
&Lint(post_drop_elaboration::CheckLiveDrops), &Lint(post_drop_elaboration::CheckLiveDrops),
], ],
None, None,
pm::Optimizations::Allowed,
); );
} }
@ -557,7 +560,13 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&deref_separator::Derefer, &deref_separator::Derefer,
]; ];
pm::run_passes(tcx, body, passes, Some(MirPhase::Analysis(AnalysisPhase::PostCleanup))); pm::run_passes(
tcx,
body,
passes,
Some(MirPhase::Analysis(AnalysisPhase::PostCleanup)),
pm::Optimizations::Allowed,
);
} }
/// Returns the sequence of passes that lowers analysis to runtime MIR. /// Returns the sequence of passes that lowers analysis to runtime MIR.
@ -597,7 +606,13 @@ fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&simplify::SimplifyCfg::PreOptimizations, &simplify::SimplifyCfg::PreOptimizations,
]; ];
pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup))); pm::run_passes(
tcx,
body,
passes,
Some(MirPhase::Runtime(RuntimePhase::PostCleanup)),
pm::Optimizations::Allowed,
);
// Clear this by anticipation. Optimizations and runtime MIR have no reason to look // Clear this by anticipation. Optimizations and runtime MIR have no reason to look
// into this information, which is meant for borrowck diagnostics. // into this information, which is meant for borrowck diagnostics.
@ -611,6 +626,15 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
WithMinOptLevel(1, x) WithMinOptLevel(1, x)
} }
let def_id = body.source.def_id();
let optimizations = if tcx.def_kind(def_id).has_codegen_attrs()
&& tcx.codegen_fn_attrs(def_id).optimize.do_not_optimize()
{
pm::Optimizations::Suppressed
} else {
pm::Optimizations::Allowed
};
// The main optimizations that we do on MIR. // The main optimizations that we do on MIR.
pm::run_passes( pm::run_passes(
tcx, tcx,
@ -683,6 +707,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&dump_mir::Marker("PreCodegen"), &dump_mir::Marker("PreCodegen"),
], ],
Some(MirPhase::Runtime(RuntimePhase::Optimized)), Some(MirPhase::Runtime(RuntimePhase::Optimized)),
optimizations,
); );
} }

View file

@ -325,4 +325,8 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
} }
} }
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -26,6 +26,10 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls {
lower_slice_len_call(block, slice_len_fn_item_def_id); 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) { fn lower_slice_len_call<'tcx>(block: &mut BasicBlockData<'tcx>, slice_len_fn_item_def_id: DefId) {

View file

@ -49,6 +49,10 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
simplify_cfg(body); simplify_cfg(body);
} }
} }
fn is_required(&self) -> bool {
false
}
} }
trait SimplifyMatch<'tcx> { trait SimplifyMatch<'tcx> {

View file

@ -27,6 +27,10 @@ impl<'tcx> crate::MirPass<'tcx> for MentionedItems {
visitor.visit_body(body); visitor.visit_body(body);
body.set_mentioned_items(visitor.mentioned_items); 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 // This visitor is carefully in sync with the one in `rustc_monomorphize::collector`. We are

View file

@ -36,4 +36,8 @@ impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators {
simplify::remove_dead_blocks(body) simplify::remove_dead_blocks(body)
} }
fn is_required(&self) -> bool {
false
}
} }

View file

@ -71,6 +71,10 @@ impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace {
// The return place is always mutable. // The return place is always mutable.
ret_decl.mutability = Mutability::Mut; ret_decl.mutability = Mutability::Mut;
} }
fn is_required(&self) -> bool {
false
}
} }
/// MIR that is eligible for the NRVO must fulfill two conditions: /// MIR that is eligible for the NRVO must fulfill two conditions:

View file

@ -90,6 +90,11 @@ pub(super) trait MirPass<'tcx> {
fn is_mir_dump_enabled(&self) -> bool { fn is_mir_dump_enabled(&self) -> bool {
true 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 /// Just like `MirPass`, except it cannot mutate `Body`, and MIR dumping is
@ -134,6 +139,10 @@ where
fn is_mir_dump_enabled(&self) -> bool { fn is_mir_dump_enabled(&self) -> bool {
false false
} }
fn is_required(&self) -> bool {
true
}
} }
pub(super) struct WithMinOptLevel<T>(pub u32, pub T); pub(super) struct WithMinOptLevel<T>(pub u32, pub T);
@ -153,6 +162,19 @@ where
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
self.1.run_pass(tcx, body) self.1.run_pass(tcx, body)
} }
fn is_required(&self) -> bool {
self.1.is_required()
}
}
/// Whether to allow non-[required] optimizations
///
/// [required]: MirPass::is_required
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum Optimizations {
Suppressed,
Allowed,
} }
/// Run the sequence of passes without validating the MIR after each pass. The MIR is still /// Run the sequence of passes without validating the MIR after each pass. The MIR is still
@ -163,7 +185,7 @@ pub(super) fn run_passes_no_validate<'tcx>(
passes: &[&dyn MirPass<'tcx>], passes: &[&dyn MirPass<'tcx>],
phase_change: Option<MirPhase>, phase_change: Option<MirPhase>,
) { ) {
run_passes_inner(tcx, body, passes, phase_change, false); run_passes_inner(tcx, body, passes, phase_change, false, Optimizations::Allowed);
} }
/// The optional `phase_change` is applied after executing all the passes, if present /// The optional `phase_change` is applied after executing all the passes, if present
@ -172,11 +194,16 @@ pub(super) fn run_passes<'tcx>(
body: &mut Body<'tcx>, body: &mut Body<'tcx>,
passes: &[&dyn MirPass<'tcx>], passes: &[&dyn MirPass<'tcx>],
phase_change: Option<MirPhase>, phase_change: Option<MirPhase>,
optimizations: Optimizations,
) { ) {
run_passes_inner(tcx, body, passes, phase_change, true); run_passes_inner(tcx, body, passes, phase_change, true, optimizations);
} }
pub(super) fn should_run_pass<'tcx, P>(tcx: TyCtxt<'tcx>, pass: &P) -> bool pub(super) fn should_run_pass<'tcx, P>(
tcx: TyCtxt<'tcx>,
pass: &P,
optimizations: Optimizations,
) -> bool
where where
P: MirPass<'tcx> + ?Sized, P: MirPass<'tcx> + ?Sized,
{ {
@ -196,7 +223,8 @@ where
); );
*polarity *polarity
}); });
overridden.unwrap_or_else(|| pass.is_enabled(tcx.sess)) let suppressed = !pass.is_required() && matches!(optimizations, Optimizations::Suppressed);
overridden.unwrap_or_else(|| !suppressed && pass.is_enabled(tcx.sess))
} }
fn run_passes_inner<'tcx>( fn run_passes_inner<'tcx>(
@ -205,6 +233,7 @@ fn run_passes_inner<'tcx>(
passes: &[&dyn MirPass<'tcx>], passes: &[&dyn MirPass<'tcx>],
phase_change: Option<MirPhase>, phase_change: Option<MirPhase>,
validate_each: bool, validate_each: bool,
optimizations: Optimizations,
) { ) {
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
trace!(?overridden_passes); trace!(?overridden_passes);
@ -243,7 +272,7 @@ fn run_passes_inner<'tcx>(
for pass in passes { for pass in passes {
let name = pass.name(); let name = pass.name();
if !should_run_pass(tcx, *pass) { if !should_run_pass(tcx, *pass, optimizations) {
continue; continue;
}; };

View file

@ -15,6 +15,10 @@ impl<'tcx> crate::MirPass<'tcx> for PostAnalysisNormalize {
let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body); PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body);
} }
fn is_required(&self) -> bool {
true
}
} }
struct PostAnalysisNormalizeVisitor<'tcx> { struct PostAnalysisNormalizeVisitor<'tcx> {

View file

@ -35,6 +35,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks {
permute(body.basic_blocks.as_mut(), &updater.map); permute(body.basic_blocks.as_mut(), &updater.map);
} }
fn is_required(&self) -> bool {
false
}
} }
/// Rearranges the locals into *use* order. /// Rearranges the locals into *use* order.
@ -85,6 +89,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals {
permute(&mut body.local_decls, &updater.map); permute(&mut body.local_decls, &updater.map);
} }
fn is_required(&self) -> bool {
false
}
} }
fn permute<I: rustc_index::Idx + Ord, T>(data: &mut IndexVec<I, T>, map: &IndexSlice<I, I>) { fn permute<I: rustc_index::Idx + Ord, T>(data: &mut IndexVec<I, T>, map: &IndexSlice<I, I>) {

View file

@ -61,6 +61,10 @@ impl<'tcx> crate::MirPass<'tcx> for PromoteTemps<'tcx> {
let promoted = promote_candidates(body, tcx, temps, promotable_candidates); let promoted = promote_candidates(body, tcx, temps, promotable_candidates);
self.promoted_fragments.set(promoted); self.promoted_fragments.set(promoted);
} }
fn is_required(&self) -> bool {
true
}
} }
/// State of a temporary during collection and promotion. /// State of a temporary during collection and promotion.

View file

@ -81,6 +81,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation {
debug!(def_id = ?body.source.def_id()); debug!(def_id = ?body.source.def_id());
while propagate_ssa(tcx, body) {} while propagate_ssa(tcx, body) {}
} }
fn is_required(&self) -> bool {
false
}
} }
fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {

View file

@ -74,6 +74,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed); debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed);
} }
fn is_required(&self) -> bool {
true
}
} }
impl RemoveNoopLandingPads { impl RemoveNoopLandingPads {

View file

@ -20,4 +20,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention {
}) })
} }
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -22,4 +22,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers {
}) })
} }
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -62,6 +62,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
block.terminator_mut().kind = TerminatorKind::Goto { target: *target }; block.terminator_mut().kind = TerminatorKind::Goto { target: *target };
} }
} }
fn is_required(&self) -> bool {
true
}
} }
fn is_needs_drop_and_init<'tcx>( fn is_needs_drop_and_init<'tcx>(

View file

@ -38,4 +38,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
simplify_cfg(body); simplify_cfg(body);
} }
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -27,6 +27,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts {
replacer.visit_basic_block_data(bb, data); replacer.visit_basic_block_data(bb, data);
} }
} }
fn is_required(&self) -> bool {
true
}
} }
struct Replacer<'a, 'tcx> { struct Replacer<'a, 'tcx> {

View file

@ -119,6 +119,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
&add_call_guards::CriticalCallEdges, &add_call_guards::CriticalCallEdges,
], ],
Some(MirPhase::Runtime(RuntimePhase::Optimized)), Some(MirPhase::Runtime(RuntimePhase::Optimized)),
pm::Optimizations::Allowed,
); );
return body; return body;

View file

@ -83,6 +83,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg {
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source); debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source);
simplify_cfg(body); simplify_cfg(body);
} }
fn is_required(&self) -> bool {
false
}
} }
struct CfgSimplifier<'a, 'tcx> { struct CfgSimplifier<'a, 'tcx> {
@ -405,6 +409,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
body.local_decls.shrink_to_fit(); body.local_decls.shrink_to_fit();
} }
} }
fn is_required(&self) -> bool {
false
}
} }
pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) { pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {

View file

@ -60,4 +60,8 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
}; };
} }
} }
fn is_required(&self) -> bool {
false
}
} }

View file

@ -140,6 +140,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
body.basic_blocks_mut()[idx].statements.insert(0, stmt); body.basic_blocks_mut()[idx].statements.insert(0, stmt);
} }
} }
fn is_required(&self) -> bool {
false
}
} }
struct OptimizationFinder<'a, 'tcx> { struct OptimizationFinder<'a, 'tcx> {

View file

@ -81,6 +81,10 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts {
} }
} }
} }
fn is_required(&self) -> bool {
true
}
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]

View file

@ -48,6 +48,10 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
} }
} }
} }
fn is_required(&self) -> bool {
false
}
} }
/// Identify all locals that are not eligible for SROA. /// Identify all locals that are not eligible for SROA.

View file

@ -31,4 +31,8 @@ impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo {
) )
}); });
} }
fn is_required(&self) -> bool {
true
}
} }

View file

@ -208,4 +208,8 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching {
patch.apply(body); patch.apply(body);
} }
fn is_required(&self) -> bool {
false
}
} }

View file

@ -52,6 +52,10 @@ impl crate::MirPass<'_> for UnreachablePropagation {
body.basic_blocks_mut()[bb].statements.clear(); body.basic_blocks_mut()[bb].statements.clear();
} }
} }
fn is_required(&self) -> bool {
false
}
} }
/// Return whether the current terminator is fully unreachable. /// Return whether the current terminator is fully unreachable.

View file

@ -91,6 +91,10 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
} }
} }
} }
fn is_required(&self) -> bool {
true
}
} }
struct CfgChecker<'a, 'tcx> { struct CfgChecker<'a, 'tcx> {

View file

@ -0,0 +1,32 @@
//@ revisions: NO-OPT SPEED-OPT
//@[NO-OPT] compile-flags: -Copt-level=0
//@[SPEED-OPT] compile-flags: -Copt-level=3 -Coverflow-checks=y
#![feature(optimize_attribute)]
#[optimize(none)]
pub fn add_noopt() -> i32 {
// CHECK-LABEL: fn add_noopt(
// CHECK: AddWithOverflow(const 1_i32, const 2_i32);
// CHECK-NEXT: assert
1 + 2
}
#[optimize(none)]
pub fn const_branch() -> i32 {
// CHECK-LABEL: fn const_branch(
// CHECK: switchInt(const true) -> [0: [[FALSE:bb[0-9]+]], otherwise: [[TRUE:bb[0-9]+]]];
// CHECK-NEXT: }
// CHECK: [[FALSE]]: {
// CHECK-NEXT: _0 = const 0
// CHECK-NEXT: goto
// CHECK-NEXT: }
// CHECK: [[TRUE]]: {
// CHECK-NEXT: _0 = const 1
// CHECK-NEXT: goto
// CHECK-NEXT: }
if true { 1 } else { 0 }
}
fn main() {}