Skip to content

Commit 4408092

Browse files
committed
Disable some MIR opts with #[optimize(none)]
1 parent 64434e3 commit 4408092

28 files changed

+172
-89
lines changed

compiler/rustc_attr/src/builtin.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub enum InstructionSetAttr {
5555

5656
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic, PartialEq, Eq)]
5757
pub enum OptimizeAttr {
58-
/// `#[optimize(none)]`
58+
/// `#[optimize(none)]`. This implies `#[inline(never)]`, required by LLVM
5959
None,
6060
/// `#[optimize(speed)]`
6161
Speed,
@@ -64,7 +64,7 @@ pub enum OptimizeAttr {
6464
}
6565

6666
impl OptimizeAttr {
67-
pub fn is_none(&self) -> bool {
67+
pub fn do_not_optimize(&self) -> bool {
6868
matches!(*self, OptimizeAttr::None)
6969
}
7070
}

compiler/rustc_middle/src/mir/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ pub trait MirPass<'tcx> {
153153
to_profiler_name(self.name())
154154
}
155155

156+
fn min_mir_opt_level(&self) -> usize {
157+
0
158+
}
159+
156160
/// Returns `true` if this pass is enabled with the current combination of compiler flags.
157161
fn is_enabled(&self, _sess: &Session) -> bool {
158162
true
@@ -443,9 +447,8 @@ pub struct Body<'tcx> {
443447
/// If `-Cinstrument-coverage` is not active, or if an individual function
444448
/// is not eligible for coverage, then this should always be `None`.
445449
pub function_coverage_info: Option<Box<coverage::FunctionCoverageInfo>>,
446-
447-
/// Whether optimization is disabled by `#[optimize(none)]`
448-
pub optimization_disabled: bool,
450+
// /// Whether optimization is disabled by `#[optimize(none)]`
451+
// pub optimization_disabled: bool,
449452
}
450453

451454
impl<'tcx> Body<'tcx> {
@@ -460,7 +463,6 @@ impl<'tcx> Body<'tcx> {
460463
span: Span,
461464
coroutine: Option<Box<CoroutineInfo<'tcx>>>,
462465
tainted_by_errors: Option<ErrorGuaranteed>,
463-
optimization_disabled: bool,
464466
) -> Self {
465467
// We need `arg_count` locals, and one for the return place.
466468
assert!(
@@ -490,7 +492,6 @@ impl<'tcx> Body<'tcx> {
490492
tainted_by_errors,
491493
coverage_info_hi: None,
492494
function_coverage_info: None,
493-
optimization_disabled,
494495
};
495496
body.is_polymorphic = body.has_non_region_param();
496497
body
@@ -522,7 +523,6 @@ impl<'tcx> Body<'tcx> {
522523
tainted_by_errors: None,
523524
coverage_info_hi: None,
524525
function_coverage_info: None,
525-
optimization_disabled: false,
526526
};
527527
body.is_polymorphic = body.has_non_region_param();
528528
body

compiler/rustc_mir_build/src/build/custom/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ pub(super) fn build_custom_mir<'tcx>(
6262
pass_count: 0,
6363
coverage_info_hi: None,
6464
function_coverage_info: None,
65-
optimization_disabled: false,
6665
};
6766

6867
body.local_decls.push(LocalDecl::new(return_ty, return_ty_span));

compiler/rustc_mir_build/src/build/mod.rs

-9
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,6 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
718718
span,
719719
coroutine,
720720
Some(guar),
721-
false,
722721
)
723722
}
724723

@@ -795,13 +794,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
795794
}
796795
}
797796

798-
let def_id = self.def_id.to_def_id();
799-
let optimization_disabled = if self.tcx.def_kind(def_id).has_codegen_attrs() {
800-
self.tcx.codegen_fn_attrs(def_id).optimize.as_ref().is_some_and(|o| o.is_none())
801-
} else {
802-
false
803-
};
804-
805797
let mut body = Body::new(
806798
MirSource::item(self.def_id.to_def_id()),
807799
self.cfg.basic_blocks,
@@ -813,7 +805,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
813805
self.fn_span,
814806
self.coroutine,
815807
None,
816-
optimization_disabled,
817808
);
818809
body.coverage_info_hi = self.coverage_info.map(|b| b.into_done());
819810
body

compiler/rustc_mir_transform/src/copy_prop.rs

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ use crate::ssa::SsaLocals;
1919
pub struct CopyProp;
2020

2121
impl<'tcx> MirPass<'tcx> for CopyProp {
22+
fn min_mir_opt_level(&self) -> usize {
23+
1
24+
}
25+
2226
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
2327
sess.mir_opt_level() >= 1
2428
}

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ const PLACE_LIMIT: usize = 100;
2828
pub struct DataflowConstProp;
2929

3030
impl<'tcx> MirPass<'tcx> for DataflowConstProp {
31+
fn min_mir_opt_level(&self) -> usize {
32+
3
33+
}
34+
3135
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
3236
sess.mir_opt_level() >= 3
3337
}

compiler/rustc_mir_transform/src/dead_store_elimination.rs

+4
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ impl<'tcx> MirPass<'tcx> for DeadStoreElimination {
140140
}
141141
}
142142

143+
fn min_mir_opt_level(&self) -> usize {
144+
2
145+
}
146+
143147
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
144148
sess.mir_opt_level() >= 2
145149
}

compiler/rustc_mir_transform/src/deduplicate_blocks.rs

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ use super::simplify::simplify_cfg;
1515
pub struct DeduplicateBlocks;
1616

1717
impl<'tcx> MirPass<'tcx> for DeduplicateBlocks {
18+
fn min_mir_opt_level(&self) -> usize {
19+
4
20+
}
21+
1822
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
1923
sess.mir_opt_level() >= 4
2024
}

compiler/rustc_mir_transform/src/dest_prop.rs

+4
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ use crate::MirPass;
150150
pub struct DestinationPropagation;
151151

152152
impl<'tcx> MirPass<'tcx> for DestinationPropagation {
153+
fn min_mir_opt_level(&self) -> usize {
154+
3
155+
}
156+
153157
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
154158
// For now, only run at MIR opt level 3. Two things need to be changed before this can be
155159
// turned on by default:

compiler/rustc_mir_transform/src/early_otherwise_branch.rs

+4
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ use super::simplify::simplify_cfg;
9292
pub struct EarlyOtherwiseBranch;
9393

9494
impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
95+
fn min_mir_opt_level(&self) -> usize {
96+
2
97+
}
98+
9599
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
96100
sess.mir_opt_level() >= 2
97101
}

compiler/rustc_mir_transform/src/gvn.rs

+4
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ use crate::ssa::{AssignedValue, SsaLocals};
111111
pub struct GVN;
112112

113113
impl<'tcx> MirPass<'tcx> for GVN {
114+
fn min_mir_opt_level(&self) -> usize {
115+
2
116+
}
117+
114118
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
115119
sess.mir_opt_level() >= 2
116120
}

compiler/rustc_mir_transform/src/instsimplify.rs

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ impl<'tcx> MirPass<'tcx> for InstSimplify {
3232
self.name()
3333
}
3434

35+
fn min_mir_opt_level(&self) -> usize {
36+
1
37+
}
38+
3539
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
3640
sess.mir_opt_level() > 0
3741
}

compiler/rustc_mir_transform/src/jump_threading.rs

+4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ const MAX_COST: usize = 100;
6161
const MAX_PLACES: usize = 100;
6262

6363
impl<'tcx> MirPass<'tcx> for JumpThreading {
64+
fn min_mir_opt_level(&self) -> usize {
65+
2
66+
}
67+
6468
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
6569
sess.mir_opt_level() >= 2
6670
}

compiler/rustc_mir_transform/src/lib.rs

+71-69
Original file line numberDiff line numberDiff line change
@@ -554,80 +554,82 @@ fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
554554
}
555555

556556
fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
557-
if body.optimization_disabled {
558-
return;
559-
}
560-
561557
fn o1<T>(x: T) -> WithMinOptLevel<T> {
562558
WithMinOptLevel(1, x)
563559
}
564560

561+
let passes: [&dyn MirPass<'tcx>; 40] = [
562+
// Add some UB checks before any UB gets optimized away.
563+
&check_alignment::CheckAlignment as &dyn MirPass<'_>,
564+
// Before inlining: trim down MIR with passes to reduce inlining work.
565+
566+
// Has to be done before inlining, otherwise actual call will be almost always inlined.
567+
// Also simple, so can just do first
568+
&lower_slice_len::LowerSliceLenCalls,
569+
// Perform instsimplify before inline to eliminate some trivial calls (like clone shims).
570+
&instsimplify::InstSimplify::BeforeInline,
571+
// Perform inlining, which may add a lot of code.
572+
&inline::Inline,
573+
// Code from other crates may have storage markers, so this needs to happen after inlining.
574+
&remove_storage_markers::RemoveStorageMarkers,
575+
// Inlining and instantiation may introduce ZST and useless drops.
576+
&remove_zsts::RemoveZsts,
577+
&remove_unneeded_drops::RemoveUnneededDrops,
578+
// Type instantiation may create uninhabited enums.
579+
// Also eliminates some unreachable branches based on variants of enums.
580+
&unreachable_enum_branching::UnreachableEnumBranching,
581+
&unreachable_prop::UnreachablePropagation,
582+
&o1(simplify::SimplifyCfg::AfterUnreachableEnumBranching),
583+
// Inlining may have introduced a lot of redundant code and a large move pattern.
584+
// Now, we need to shrink the generated MIR.
585+
&ref_prop::ReferencePropagation,
586+
&sroa::ScalarReplacementOfAggregates,
587+
&match_branches::MatchBranchSimplification,
588+
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
589+
&multiple_return_terminators::MultipleReturnTerminators,
590+
// After simplifycfg, it allows us to discover new opportunities for peephole optimizations.
591+
&instsimplify::InstSimplify::AfterSimplifyCfg,
592+
&simplify::SimplifyLocals::BeforeConstProp,
593+
&dead_store_elimination::DeadStoreElimination::Initial,
594+
&gvn::GVN,
595+
&simplify::SimplifyLocals::AfterGVN,
596+
&dataflow_const_prop::DataflowConstProp,
597+
&single_use_consts::SingleUseConsts,
598+
&o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
599+
&jump_threading::JumpThreading,
600+
&early_otherwise_branch::EarlyOtherwiseBranch,
601+
&simplify_comparison_integral::SimplifyComparisonIntegral,
602+
&dest_prop::DestinationPropagation,
603+
&o1(simplify_branches::SimplifyConstCondition::Final),
604+
&o1(remove_noop_landing_pads::RemoveNoopLandingPads),
605+
&o1(simplify::SimplifyCfg::Final),
606+
&copy_prop::CopyProp,
607+
&dead_store_elimination::DeadStoreElimination::Final,
608+
&nrvo::RenameReturnPlace,
609+
&simplify::SimplifyLocals::Final,
610+
&multiple_return_terminators::MultipleReturnTerminators,
611+
&deduplicate_blocks::DeduplicateBlocks,
612+
&large_enums::EnumSizeOpt { discrepancy: 128 },
613+
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
614+
&add_call_guards::CriticalCallEdges,
615+
// Cleanup for human readability, off by default.
616+
&prettify::ReorderBasicBlocks,
617+
&prettify::ReorderLocals,
618+
// Dump the end result for testing and debugging purposes.
619+
&dump_mir::Marker("PreCodegen"),
620+
];
621+
622+
let mut passes = passes.to_vec();
623+
let def_id = body.source.def_id();
624+
if tcx.def_kind(def_id).has_codegen_attrs()
625+
&& let Some(ref attrs) = tcx.codegen_fn_attrs(def_id).optimize
626+
&& attrs.do_not_optimize()
627+
{
628+
passes.retain(|pass| pass.min_mir_opt_level() <= 1);
629+
}
630+
565631
// The main optimizations that we do on MIR.
566-
pm::run_passes(
567-
tcx,
568-
body,
569-
&[
570-
// Add some UB checks before any UB gets optimized away.
571-
&check_alignment::CheckAlignment,
572-
// Before inlining: trim down MIR with passes to reduce inlining work.
573-
574-
// Has to be done before inlining, otherwise actual call will be almost always inlined.
575-
// Also simple, so can just do first
576-
&lower_slice_len::LowerSliceLenCalls,
577-
// Perform instsimplify before inline to eliminate some trivial calls (like clone shims).
578-
&instsimplify::InstSimplify::BeforeInline,
579-
// Perform inlining, which may add a lot of code.
580-
&inline::Inline,
581-
// Code from other crates may have storage markers, so this needs to happen after inlining.
582-
&remove_storage_markers::RemoveStorageMarkers,
583-
// Inlining and instantiation may introduce ZST and useless drops.
584-
&remove_zsts::RemoveZsts,
585-
&remove_unneeded_drops::RemoveUnneededDrops,
586-
// Type instantiation may create uninhabited enums.
587-
// Also eliminates some unreachable branches based on variants of enums.
588-
&unreachable_enum_branching::UnreachableEnumBranching,
589-
&unreachable_prop::UnreachablePropagation,
590-
&o1(simplify::SimplifyCfg::AfterUnreachableEnumBranching),
591-
// Inlining may have introduced a lot of redundant code and a large move pattern.
592-
// Now, we need to shrink the generated MIR.
593-
&ref_prop::ReferencePropagation,
594-
&sroa::ScalarReplacementOfAggregates,
595-
&match_branches::MatchBranchSimplification,
596-
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
597-
&multiple_return_terminators::MultipleReturnTerminators,
598-
// After simplifycfg, it allows us to discover new opportunities for peephole optimizations.
599-
&instsimplify::InstSimplify::AfterSimplifyCfg,
600-
&simplify::SimplifyLocals::BeforeConstProp,
601-
&dead_store_elimination::DeadStoreElimination::Initial,
602-
&gvn::GVN,
603-
&simplify::SimplifyLocals::AfterGVN,
604-
&dataflow_const_prop::DataflowConstProp,
605-
&single_use_consts::SingleUseConsts,
606-
&o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
607-
&jump_threading::JumpThreading,
608-
&early_otherwise_branch::EarlyOtherwiseBranch,
609-
&simplify_comparison_integral::SimplifyComparisonIntegral,
610-
&dest_prop::DestinationPropagation,
611-
&o1(simplify_branches::SimplifyConstCondition::Final),
612-
&o1(remove_noop_landing_pads::RemoveNoopLandingPads),
613-
&o1(simplify::SimplifyCfg::Final),
614-
&copy_prop::CopyProp,
615-
&dead_store_elimination::DeadStoreElimination::Final,
616-
&nrvo::RenameReturnPlace,
617-
&simplify::SimplifyLocals::Final,
618-
&multiple_return_terminators::MultipleReturnTerminators,
619-
&deduplicate_blocks::DeduplicateBlocks,
620-
&large_enums::EnumSizeOpt { discrepancy: 128 },
621-
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
622-
&add_call_guards::CriticalCallEdges,
623-
// Cleanup for human readability, off by default.
624-
&prettify::ReorderBasicBlocks,
625-
&prettify::ReorderLocals,
626-
// Dump the end result for testing and debugging purposes.
627-
&dump_mir::Marker("PreCodegen"),
628-
],
629-
Some(MirPhase::Runtime(RuntimePhase::Optimized)),
630-
);
632+
pm::run_passes(tcx, body, &passes, Some(MirPhase::Runtime(RuntimePhase::Optimized)));
631633
}
632634

633635
/// Optimize the MIR and prepare it for codegen.

compiler/rustc_mir_transform/src/lower_slice_len.rs

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ use rustc_middle::ty::TyCtxt;
88
pub struct LowerSliceLenCalls;
99

1010
impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls {
11+
fn min_mir_opt_level(&self) -> usize {
12+
1
13+
}
14+
1115
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
1216
sess.mir_opt_level() > 0
1317
}

compiler/rustc_mir_transform/src/match_branches.rs

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ use super::simplify::simplify_cfg;
1313
pub struct MatchBranchSimplification;
1414

1515
impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
16+
fn min_mir_opt_level(&self) -> usize {
17+
1
18+
}
19+
1620
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
1721
sess.mir_opt_level() >= 1
1822
}

compiler/rustc_mir_transform/src/multiple_return_terminators.rs

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ use crate::simplify;
1010
pub struct MultipleReturnTerminators;
1111

1212
impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators {
13+
fn min_mir_opt_level(&self) -> usize {
14+
4
15+
}
16+
1317
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
1418
sess.mir_opt_level() >= 4
1519
}

0 commit comments

Comments
 (0)