diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index def6b16ee8ae3..b4027a096c532 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -35,13 +35,25 @@ pub enum InstructionSetAttr { ArmT32, } -#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic, Default)] pub enum OptimizeAttr { - None, + /// No `#[optimize(..)]` attribute + #[default] + Default, + /// `#[optimize(none)]` + DoNotOptimize, + /// `#[optimize(speed)]` Speed, + /// `#[optimize(size)]` Size, } +impl OptimizeAttr { + pub fn do_not_optimize(&self) -> bool { + matches!(self, Self::DoNotOptimize) + } +} + #[derive(Clone, Debug, Encodable, Decodable)] pub enum DiagnosticAttribute { // tidy-alphabetical-start diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 95e0481b035e2..3d7afa17bdf3d 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -333,9 +333,12 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( let mut to_add = SmallVec::<[_; 16]>::new(); match codegen_fn_attrs.optimize { - OptimizeAttr::None => { + OptimizeAttr::Default => { to_add.extend(default_optimisation_attrs(cx)); } + OptimizeAttr::DoNotOptimize => { + to_add.push(llvm::AttributeKind::OptimizeNone.create_attr(cx.llcx)); + } OptimizeAttr::Size => { to_add.push(llvm::AttributeKind::MinSize.create_attr(cx.llcx)); to_add.push(llvm::AttributeKind::OptimizeForSize.create_attr(cx.llcx)); @@ -343,12 +346,12 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( OptimizeAttr::Speed => {} } - let inline = - if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) { - InlineAttr::Hint - } else { - codegen_fn_attrs.inline - }; + // `optnone` requires `noinline` + let inline = match (codegen_fn_attrs.inline, &codegen_fn_attrs.optimize) { + (_, OptimizeAttr::DoNotOptimize) => InlineAttr::Never, + (InlineAttr::None, _) if instance.def.requires_inline(cx.tcx) => InlineAttr::Hint, + (inline, _) => inline, + }; to_add.extend(inline_attr(cx, inline)); // The `uwtable` attribute according to LLVM is: diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 83724af604d14..6099dec2bb2ac 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -1053,10 +1053,7 @@ pub(crate) fn provide(providers: &mut Providers) { let any_for_speed = defids.items().any(|id| { let CodegenFnAttrs { optimize, .. } = tcx.codegen_fn_attrs(*id); - match optimize { - attr::OptimizeAttr::None | attr::OptimizeAttr::Size => false, - attr::OptimizeAttr::Speed => true, - } + matches!(optimize, attr::OptimizeAttr::Speed) }); if any_for_speed { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 1daa17fbaf347..a0bc2d4ea48f1 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -575,7 +575,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.inline = InlineAttr::Never; } - codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| { + codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::Default, |ia, attr| { if !attr.has_name(sym::optimize) { return ia; } @@ -587,17 +587,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { inline_span = Some(attr.span); if items.len() != 1 { err(attr.span, "expected one argument"); - OptimizeAttr::None + OptimizeAttr::Default } else if list_contains_name(items, sym::size) { OptimizeAttr::Size } else if list_contains_name(items, sym::speed) { OptimizeAttr::Speed + } else if list_contains_name(items, sym::none) { + OptimizeAttr::DoNotOptimize } else { err(items[0].span(), "invalid argument"); - OptimizeAttr::None + OptimizeAttr::Default } } else { - OptimizeAttr::None + OptimizeAttr::Default } }); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 68e0191f45e7b..966f7730918de 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -532,7 +532,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // RFC 2412 gated!( - optimize, Normal, template!(List: "size|speed"), ErrorPreceding, + optimize, Normal, template!(List: "none|size|speed"), ErrorPreceding, EncodeCrossCrate::No, optimize_attribute, experimental!(optimize) ), diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index e05f42af6fd24..cc980f6e62aee 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -147,7 +147,7 @@ impl CodegenFnAttrs { CodegenFnAttrs { flags: CodegenFnAttrFlags::empty(), inline: InlineAttr::None, - optimize: OptimizeAttr::None, + optimize: OptimizeAttr::Default, export_name: None, link_name: None, link_ordinal: None, diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 03f11885d58ae..5bd6fdcf48577 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -116,4 +116,8 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { // We may have invalidated some `cleanup` blocks so clean those up now. super::simplify::remove_dead_blocks(body); } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index 24c955c0c78c6..55694cacd92e0 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -75,4 +75,8 @@ impl<'tcx> crate::MirPass<'tcx> for AddCallGuards { body.basic_blocks_mut().extend(new_blocks); } + + fn is_required(&self) -> bool { + true + } } 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 12a2fe23b149e..87ae2b7165434 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 @@ -68,6 +68,10 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { patch.apply(body); } + + fn is_required(&self) -> bool { + true + } } fn add_move_for_packed_drop<'tcx>( diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 53176eec9bcb9..1fc788a2dadeb 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -176,4 +176,8 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag { } } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index e585e338613d8..e41f47db545b8 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -61,4 +61,8 @@ impl<'tcx> crate::MirPass<'tcx> for Subtyper { } checker.patcher.apply(body); } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 1b7c89fd25183..d7e22c123942c 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -60,6 +60,10 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { } } } + + fn is_required(&self) -> bool { + true + } } struct PointerFinder<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index 6a22a58470c95..cb84401985735 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -72,4 +72,8 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { decl.user_ty = None; } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index f149bf97cde65..27af5818982d0 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -56,6 +56,10 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp { crate::simplify::remove_unused_definitions(body); } } + + fn is_required(&self) -> bool { + false + } } /// `SsaLocals` computed equivalence classes between locals considering copy/move assignments. diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index a3715b5d48556..3b75be58e437f 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1688,6 +1688,10 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { // Run derefer to fix Derefs that are not in the first place 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 diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index b8aa76a7dbe5d..15487d05a301d 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -61,6 +61,10 @@ impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage { 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>) { diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 8fce856687cb8..4f45d9588a890 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -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 // 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. - 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()); if matches!(tcx.sess.opts.optimize, OptLevel::No) && !inliner_will_run { return false; diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index bd58b1b668997..d0b313e149aca 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -36,6 +36,10 @@ impl<'tcx> crate::MirPass<'tcx> for CtfeLimit { ); } } + + fn is_required(&self) -> bool { + true + } } fn has_back_edge( diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 51af77778af82..8879e029346da 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -71,6 +71,10 @@ 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 434e921d43929..eea2b0990d730 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -147,4 +147,8 @@ impl<'tcx> crate::MirPass<'tcx> for DeadStoreElimination { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { eliminate(tcx, body); } + + fn is_required(&self) -> bool { + false + } } diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index 26b28c8c4870e..63257df66fb9b 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -31,6 +31,10 @@ impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks { simplify_cfg(body); } } + + fn is_required(&self) -> bool { + false + } } struct OptApplier<'tcx> { diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index ad7ccef4976aa..a54bdaa407593 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -81,4 +81,8 @@ impl<'tcx> crate::MirPass<'tcx> for Derefer { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { deref_finder(tcx, body); } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index b4f9f1f08ef82..41de1b58b91bb 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -240,6 +240,10 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { trace!(round_count); } + + fn is_required(&self) -> bool { + false + } } #[derive(Debug, Default)] diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index 5dd84975b88ed..e4fcbaa483d04 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -15,6 +15,10 @@ impl<'tcx> crate::MirPass<'tcx> for Marker { } 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<()> { diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 91e1395e76415..eb335a1e4a707 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -227,6 +227,10 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { simplify_cfg(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 d6ecadbfe29c1..6d3b5d9851b33 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -150,4 +150,8 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { } } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 988f1a25561e9..cb869160c8054 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -88,6 +88,10 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { elaborate_patch.apply(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 diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index cb03b422d9e38..dfeb83a0887d3 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -163,6 +163,10 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { // statements. StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body); } + + fn is_required(&self) -> bool { + false + } } newtype_index! { diff --git a/compiler/rustc_mir_transform/src/impossible_predicates.rs b/compiler/rustc_mir_transform/src/impossible_predicates.rs index ba8389bbe2ffb..86e2bf6cb3c60 100644 --- a/compiler/rustc_mir_transform/src/impossible_predicates.rs +++ b/compiler/rustc_mir_transform/src/impossible_predicates.rs @@ -53,4 +53,8 @@ impl<'tcx> MirPass<'tcx> for ImpossiblePredicates { body.local_decls.raw.truncate(body.arg_count + 1); } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 2052e28325c90..95aeccfdda66b 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -66,6 +66,10 @@ impl<'tcx> crate::MirPass<'tcx> for Inline { deref_finder(tcx, body); } } + + fn is_required(&self) -> bool { + false + } } pub struct ForceInline; @@ -85,6 +89,10 @@ impl<'tcx> crate::MirPass<'tcx> for ForceInline { false } + fn is_required(&self) -> bool { + true + } + 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 _guard = span.enter(); diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 5a36519e6a3bb..090dcee426141 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -62,6 +62,10 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); } } + + 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 c73a03489c57f..17084eca6e388 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -105,6 +105,10 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { } OpportunitySet::new(body, opportunities).apply(body); } + + fn is_required(&self) -> bool { + false + } } #[derive(Debug)] diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 490e7dd8f7e07..e201763468b31 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -200,6 +200,10 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { }); } } + + 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 d1bacf1f5985a..2dc55e3614e6c 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -388,6 +388,7 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { &Lint(sanity_check::SanityCheck), ], None, + pm::Optimizations::Allowed, ); tcx.alloc_steal_mir(body) } @@ -440,6 +441,7 @@ fn mir_promoted( &mut body, &[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage], Some(MirPhase::Analysis(AnalysisPhase::Initial)), + pm::Optimizations::Allowed, ); 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); - pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None); + pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None, pm::Optimizations::Allowed); 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(); if is_fn_like { // 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()) { 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), ], None, + pm::Optimizations::Allowed, ); } @@ -557,7 +560,13 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &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. @@ -597,7 +606,13 @@ fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &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 // 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) } + 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. pm::run_passes( tcx, @@ -683,6 +707,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &dump_mir::Marker("PreCodegen"), ], Some(MirPhase::Runtime(RuntimePhase::Optimized)), + optimizations, ); } diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 942c6144ea69c..9a9f66ed4fd7a 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -325,4 +325,8 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { } } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 420661f29c8cf..aca80e36e339d 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -26,6 +26,10 @@ 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 534ba99178017..500116580d5d7 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -49,6 +49,10 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { simplify_cfg(body); } } + + fn is_required(&self) -> bool { + false + } } trait SimplifyMatch<'tcx> { diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index cf5c5f85a9ff6..f5c57418467a1 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -27,6 +27,10 @@ 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 6dfa14d6b527d..c63bfdcee8559 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -36,4 +36,8 @@ 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/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index 35872de385245..965002aae04c7 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -71,6 +71,10 @@ impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace { // The return place is always mutable. ret_decl.mutability = Mutability::Mut; } + + fn is_required(&self) -> bool { + false + } } /// MIR that is eligible for the NRVO must fulfill two conditions: diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index c3f0a989ce105..7a8d3ba1ff1fa 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -90,6 +90,11 @@ pub(super) trait MirPass<'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 @@ -134,6 +139,10 @@ where fn is_mir_dump_enabled(&self) -> bool { false } + + fn is_required(&self) -> bool { + true + } } pub(super) struct WithMinOptLevel(pub u32, pub T); @@ -153,6 +162,19 @@ where 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() + } +} + +/// 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 @@ -163,7 +185,7 @@ pub(super) fn run_passes_no_validate<'tcx>( passes: &[&dyn MirPass<'tcx>], phase_change: Option, ) { - 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 @@ -172,11 +194,16 @@ pub(super) fn run_passes<'tcx>( body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>], phase_change: Option, + 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 P: MirPass<'tcx> + ?Sized, { @@ -196,7 +223,8 @@ where ); *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>( @@ -205,6 +233,7 @@ fn run_passes_inner<'tcx>( passes: &[&dyn MirPass<'tcx>], phase_change: Option, validate_each: bool, + optimizations: Optimizations, ) { let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); @@ -243,7 +272,7 @@ fn run_passes_inner<'tcx>( for pass in passes { let name = pass.name(); - if !should_run_pass(tcx, *pass) { + if !should_run_pass(tcx, *pass, optimizations) { continue; }; diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs index 3eecf79a7eae7..76c2f082c0bfc 100644 --- a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs +++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs @@ -15,6 +15,10 @@ impl<'tcx> crate::MirPass<'tcx> for PostAnalysisNormalize { let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body); } + + fn is_required(&self) -> bool { + true + } } struct PostAnalysisNormalizeVisitor<'tcx> { diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs index 51abd4da86eb1..8ccfbe2f194b4 100644 --- a/compiler/rustc_mir_transform/src/prettify.rs +++ b/compiler/rustc_mir_transform/src/prettify.rs @@ -35,6 +35,10 @@ 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. @@ -85,6 +89,10 @@ 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 6be95b1f0f1e6..6aa3343bb6e3b 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -61,6 +61,10 @@ impl<'tcx> crate::MirPass<'tcx> for PromoteTemps<'tcx> { let promoted = promote_candidates(body, tcx, temps, promotable_candidates); self.promoted_fragments.set(promoted); } + + fn is_required(&self) -> bool { + true + } } /// State of a temporary during collection and promotion. diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 95b05f94270a8..368d5340ac34f 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -81,6 +81,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation { debug!(def_id = ?body.source.def_id()); while propagate_ssa(tcx, body) {} } + + fn is_required(&self) -> bool { + false + } } fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { 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 76a3edfe0be4e..9cdd52bec7bb9 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -74,6 +74,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed); } + + 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 71399eb72f004..15fe77d53195a 100644 --- a/compiler/rustc_mir_transform/src/remove_place_mention.rs +++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs @@ -20,4 +20,8 @@ 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 3ecb4a8994f5f..1ae33c0096875 100644 --- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -22,4 +22,8 @@ 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 e955d8277a458..9044a88295cc4 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -62,6 +62,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { block.terminator_mut().kind = TerminatorKind::Goto { target: *target }; } } + + fn is_required(&self) -> bool { + true + } } fn is_needs_drop_and_init<'tcx>( diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index e335051d65644..8a8cdafc69070 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -38,4 +38,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops { simplify_cfg(body); } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 55e5701bd0af3..78d94a038671d 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -27,6 +27,10 @@ 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/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 4648ec33c9345..f7ec0f740d300 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -119,6 +119,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< &add_call_guards::CriticalCallEdges, ], Some(MirPhase::Runtime(RuntimePhase::Optimized)), + pm::Optimizations::Allowed, ); return body; diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 4f312ed2aaabc..67070f03dedbd 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -83,6 +83,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source); simplify_cfg(body); } + + fn is_required(&self) -> bool { + false + } } struct CfgSimplifier<'a, 'tcx> { @@ -405,6 +409,10 @@ 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 bea3d0d8557a7..12c3503879fb9 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -60,4 +60,8 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { }; } } + + 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 b6d8017308662..c0f25c7ecfebc 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -140,6 +140,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { body.basic_blocks_mut()[idx].statements.insert(0, stmt); } } + + 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 10b3c0ae94f24..c5e951eb8b2c2 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -81,6 +81,10 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { } } } + + fn is_required(&self) -> bool { + true + } } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index d54ea3feab6ee..92e5c8a9ca428 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -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. diff --git a/compiler/rustc_mir_transform/src/strip_debuginfo.rs b/compiler/rustc_mir_transform/src/strip_debuginfo.rs index 438c75726bb90..9ede8aa79c44a 100644 --- a/compiler/rustc_mir_transform/src/strip_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/strip_debuginfo.rs @@ -31,4 +31,8 @@ impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo { ) }); } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 55dcad0680a96..1ff7043ed14d9 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -208,4 +208,8 @@ 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 734703ec78b55..1e5d9469c033e 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -52,6 +52,10 @@ 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 b62e34ac08d09..026923ad786bb 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -91,6 +91,10 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { } } } + + fn is_required(&self) -> bool { + true + } } struct CfgChecker<'a, 'tcx> { diff --git a/tests/codegen/optimize-attr-1.rs b/tests/codegen/optimize-attr-1.rs index 3aee44791e0e6..db6bdcf9a8b90 100644 --- a/tests/codegen/optimize-attr-1.rs +++ b/tests/codegen/optimize-attr-1.rs @@ -37,11 +37,23 @@ pub fn speed() -> i32 { 4 + 4 } +// CHECK-LABEL: define{{.*}}i32 @none +// CHECK-SAME: [[NONE_ATTRS:#[0-9]+]] +// SIZE-OPT: alloca +// SPEED-OPT: alloca +#[no_mangle] +#[optimize(none)] +pub fn none() -> i32 { + let arr = [0, 1, 2, 3, 4]; + arr[4] +} + // NO-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}} // SPEED-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}} // SIZE-OPT-DAG: attributes [[NOTHING_ATTRS]] = {{.*}}optsize{{.*}} // SIZE-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}} +// CHECK-DAG: attributes [[NONE_ATTRS]] = {{.*}}noinline{{.*}}optnone{{.*}} -// SIZE-OPT: attributes [[SPEED_ATTRS]] +// SIZE-OPT-DAG: attributes [[SPEED_ATTRS]] // SIZE-OPT-NOT: minsize // SIZE-OPT-NOT: optsize diff --git a/tests/mir-opt/optimize_none.rs b/tests/mir-opt/optimize_none.rs new file mode 100644 index 0000000000000..a5b541bd2b628 --- /dev/null +++ b/tests/mir-opt/optimize_none.rs @@ -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() {} diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.rs b/tests/ui/feature-gates/feature-gate-optimize_attribute.rs index 7f9cada6a47d5..77cc307c9f453 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.rs +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.rs @@ -6,6 +6,9 @@ fn size() {} #[optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature fn speed() {} +#[optimize(none)] //~ ERROR the `#[optimize]` attribute is an experimental feature +fn none() {} + #[optimize(banana)] //~^ ERROR the `#[optimize]` attribute is an experimental feature //~| ERROR E0722 diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr index ca8f4a078f09e..4e6e4ac2703a8 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr @@ -21,6 +21,16 @@ LL | #[optimize(speed)] error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:9:1 | +LL | #[optimize(none)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the `#[optimize]` attribute is an experimental feature + --> $DIR/feature-gate-optimize_attribute.rs:12:1 + | LL | #[optimize(banana)] | ^^^^^^^^^^^^^^^^^^^ | @@ -29,12 +39,12 @@ LL | #[optimize(banana)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0722]: invalid argument - --> $DIR/feature-gate-optimize_attribute.rs:9:12 + --> $DIR/feature-gate-optimize_attribute.rs:12:12 | LL | #[optimize(banana)] | ^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0658, E0722. For more information about an error, try `rustc --explain E0658`.