Skip to content

Commit 64434e3

Browse files
committed
Implement optimize(none)
1 parent ab1527f commit 64434e3

File tree

15 files changed

+87
-23
lines changed

15 files changed

+87
-23
lines changed

compiler/rustc_attr/src/builtin.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,22 @@ pub enum InstructionSetAttr {
5353
ArmT32,
5454
}
5555

56-
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
56+
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic, PartialEq, Eq)]
5757
pub enum OptimizeAttr {
58+
/// `#[optimize(none)]`
5859
None,
60+
/// `#[optimize(speed)]`
5961
Speed,
62+
/// `#[optimize(size)]`
6063
Size,
6164
}
6265

66+
impl OptimizeAttr {
67+
pub fn is_none(&self) -> bool {
68+
matches!(*self, OptimizeAttr::None)
69+
}
70+
}
71+
6372
/// Represents the following attributes:
6473
///
6574
/// - `#[stable]`

compiler/rustc_codegen_llvm/src/attributes.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -336,22 +336,27 @@ pub fn from_fn_attrs<'ll, 'tcx>(
336336
let mut to_add = SmallVec::<[_; 16]>::new();
337337

338338
match codegen_fn_attrs.optimize {
339-
OptimizeAttr::None => {
339+
None => {
340340
to_add.extend(default_optimisation_attrs(cx));
341341
}
342-
OptimizeAttr::Size => {
342+
Some(OptimizeAttr::None) => {
343+
to_add.push(llvm::AttributeKind::OptimizeNone.create_attr(cx.llcx));
344+
}
345+
Some(OptimizeAttr::Size) => {
343346
to_add.push(llvm::AttributeKind::MinSize.create_attr(cx.llcx));
344347
to_add.push(llvm::AttributeKind::OptimizeForSize.create_attr(cx.llcx));
345348
}
346-
OptimizeAttr::Speed => {}
349+
Some(OptimizeAttr::Speed) => {}
347350
}
348351

349-
let inline =
350-
if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) {
351-
InlineAttr::Hint
352-
} else {
353-
codegen_fn_attrs.inline
354-
};
352+
// `optnone` requires `noinline`
353+
let inline = if codegen_fn_attrs.optimize == Some(OptimizeAttr::None) {
354+
InlineAttr::Never
355+
} else if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) {
356+
InlineAttr::Hint
357+
} else {
358+
codegen_fn_attrs.inline
359+
};
355360
to_add.extend(inline_attr(cx, inline));
356361

357362
// The `uwtable` attribute according to LLVM is:

compiler/rustc_codegen_ssa/src/base.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1024,8 +1024,8 @@ pub fn provide(providers: &mut Providers) {
10241024
let any_for_speed = defids.items().any(|id| {
10251025
let CodegenFnAttrs { optimize, .. } = tcx.codegen_fn_attrs(*id);
10261026
match optimize {
1027-
attr::OptimizeAttr::None | attr::OptimizeAttr::Size => false,
1028-
attr::OptimizeAttr::Speed => true,
1027+
None | Some(attr::OptimizeAttr::None | attr::OptimizeAttr::Size) => false,
1028+
Some(attr::OptimizeAttr::Speed) => true,
10291029
}
10301030
});
10311031

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
559559
}
560560
});
561561

562-
codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
562+
codegen_fn_attrs.optimize = attrs.iter().fold(None, |ia, attr| {
563563
if !attr.has_name(sym::optimize) {
564564
return ia;
565565
}
@@ -573,14 +573,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
573573
inline_span = Some(attr.span);
574574
if items.len() != 1 {
575575
err(attr.span, "expected one argument");
576-
OptimizeAttr::None
576+
None
577577
} else if list_contains_name(items, sym::size) {
578-
OptimizeAttr::Size
578+
Some(OptimizeAttr::Size)
579579
} else if list_contains_name(items, sym::speed) {
580-
OptimizeAttr::Speed
580+
Some(OptimizeAttr::Speed)
581+
} else if list_contains_name(items, sym::none) {
582+
Some(OptimizeAttr::None)
581583
} else {
582584
err(items[0].span(), "invalid argument");
583-
OptimizeAttr::None
585+
None
584586
}
585587
}
586588
Some(MetaItemKind::NameValue(_)) => ia,

compiler/rustc_feature/src/builtin_attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
532532
),
533533
// RFC 2412
534534
gated!(
535-
optimize, Normal, template!(List: "size|speed"), ErrorPreceding,
535+
optimize, Normal, template!(List: "none|size|speed"), ErrorPreceding,
536536
EncodeCrossCrate::No, optimize_attribute, experimental!(optimize)
537537
),
538538

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ pub struct CodegenFnAttrs {
1111
pub flags: CodegenFnAttrFlags,
1212
/// Parsed representation of the `#[inline]` attribute
1313
pub inline: InlineAttr,
14-
/// Parsed representation of the `#[optimize]` attribute
15-
pub optimize: OptimizeAttr,
14+
/// Parsed representation of the `#[optimize]` attribute if present
15+
pub optimize: Option<OptimizeAttr>,
1616
/// The `#[export_name = "..."]` attribute, indicating a custom symbol a
1717
/// function should be exported under
1818
pub export_name: Option<Symbol>,
@@ -137,7 +137,7 @@ impl CodegenFnAttrs {
137137
CodegenFnAttrs {
138138
flags: CodegenFnAttrFlags::empty(),
139139
inline: InlineAttr::None,
140-
optimize: OptimizeAttr::None,
140+
optimize: None,
141141
export_name: None,
142142
link_name: None,
143143
link_ordinal: None,

compiler/rustc_middle/src/mir/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@ pub struct Body<'tcx> {
443443
/// If `-Cinstrument-coverage` is not active, or if an individual function
444444
/// is not eligible for coverage, then this should always be `None`.
445445
pub function_coverage_info: Option<Box<coverage::FunctionCoverageInfo>>,
446+
447+
/// Whether optimization is disabled by `#[optimize(none)]`
448+
pub optimization_disabled: bool,
446449
}
447450

448451
impl<'tcx> Body<'tcx> {
@@ -457,6 +460,7 @@ impl<'tcx> Body<'tcx> {
457460
span: Span,
458461
coroutine: Option<Box<CoroutineInfo<'tcx>>>,
459462
tainted_by_errors: Option<ErrorGuaranteed>,
463+
optimization_disabled: bool,
460464
) -> Self {
461465
// We need `arg_count` locals, and one for the return place.
462466
assert!(
@@ -486,6 +490,7 @@ impl<'tcx> Body<'tcx> {
486490
tainted_by_errors,
487491
coverage_info_hi: None,
488492
function_coverage_info: None,
493+
optimization_disabled,
489494
};
490495
body.is_polymorphic = body.has_non_region_param();
491496
body
@@ -517,6 +522,7 @@ impl<'tcx> Body<'tcx> {
517522
tainted_by_errors: None,
518523
coverage_info_hi: None,
519524
function_coverage_info: None,
525+
optimization_disabled: false,
520526
};
521527
body.is_polymorphic = body.has_non_region_param();
522528
body

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

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ 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,
6566
};
6667

6768
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,6 +718,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
718718
span,
719719
coroutine,
720720
Some(guar),
721+
false,
721722
)
722723
}
723724

@@ -794,6 +795,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
794795
}
795796
}
796797

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+
797805
let mut body = Body::new(
798806
MirSource::item(self.def_id.to_def_id()),
799807
self.cfg.basic_blocks,
@@ -805,6 +813,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
805813
self.fn_span,
806814
self.coroutine,
807815
None,
816+
optimization_disabled,
808817
);
809818
body.coverage_info_hi = self.coverage_info.map(|b| b.into_done());
810819
body

compiler/rustc_mir_transform/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,10 @@ 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+
557561
fn o1<T>(x: T) -> WithMinOptLevel<T> {
558562
WithMinOptLevel(1, x)
559563
}

compiler/rustc_mir_transform/src/promote_consts.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,7 @@ fn promote_candidates<'tcx>(
10061006
body.span,
10071007
None,
10081008
body.tainted_by_errors,
1009+
body.optimization_disabled,
10091010
);
10101011
promoted.phase = MirPhase::Analysis(AnalysisPhase::Initial);
10111012

compiler/rustc_mir_transform/src/shim.rs

+1
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ fn new_body<'tcx>(
326326
None,
327327
// FIXME(compiler-errors): is this correct?
328328
None,
329+
false,
329330
);
330331
// Shims do not directly mention any consts.
331332
body.set_required_consts(Vec::new());

tests/codegen/optimize-attr-1.rs

+13
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ pub fn nothing() -> i32 {
1515
2 + 2
1616
}
1717

18+
// CHECK-LABEL: define{{.*}}i32 @none
19+
// CHECK-SAME: [[NONE_ATTRS:#[0-9]+]]
20+
// SIZE-OPT: alloca
21+
// SPEED-OPT: alloca
22+
#[no_mangle]
23+
#[optimize(none)]
24+
pub fn none() -> i32 {
25+
let arr = [0, 1, 2, 3, 4];
26+
arr[4]
27+
}
28+
1829
// CHECK-LABEL: define{{.*}}i32 @size
1930
// CHECK-SAME: [[SIZE_ATTRS:#[0-9]+]]
2031
// SIZE-OPT: ret i32 6
@@ -39,8 +50,10 @@ pub fn speed() -> i32 {
3950

4051
// NO-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}}
4152
// SPEED-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}}
53+
// SPEED-OPT-DAG: attributes [[NONE_ATTRS]] = {{.*}}optnone{{.*}}
4254
// SIZE-OPT-DAG: attributes [[NOTHING_ATTRS]] = {{.*}}optsize{{.*}}
4355
// SIZE-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}}
56+
// SIZE-OPT-DAG: attributes [[NONE_ATTRS]] = {{.*}}noinline{{.*}}optnone{{.*}}
4457

4558
// SIZE-OPT: attributes [[SPEED_ATTRS]]
4659
// SIZE-OPT-NOT: minsize

tests/ui/feature-gates/feature-gate-optimize_attribute.rs

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ fn size() {}
1010
#[optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature
1111
fn speed() {}
1212

13+
#[optimize(none)] //~ ERROR the `#[optimize]` attribute is an experimental feature
14+
fn none() {}
15+
1316
#[optimize(banana)]
1417
//~^ ERROR the `#[optimize]` attribute is an experimental feature
1518
//~| ERROR E0722

tests/ui/feature-gates/feature-gate-optimize_attribute.stderr

+12-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ LL | #[optimize(speed)]
4141
error[E0658]: the `#[optimize]` attribute is an experimental feature
4242
--> $DIR/feature-gate-optimize_attribute.rs:13:1
4343
|
44+
LL | #[optimize(none)]
45+
| ^^^^^^^^^^^^^^^^^
46+
|
47+
= note: see issue #54882 <https://github.com/rust-lang/rust/issues/54882> for more information
48+
= help: add `#![feature(optimize_attribute)]` to the crate attributes to enable
49+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
50+
51+
error[E0658]: the `#[optimize]` attribute is an experimental feature
52+
--> $DIR/feature-gate-optimize_attribute.rs:16:1
53+
|
4454
LL | #[optimize(banana)]
4555
| ^^^^^^^^^^^^^^^^^^^
4656
|
@@ -49,12 +59,12 @@ LL | #[optimize(banana)]
4959
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
5060

5161
error[E0722]: invalid argument
52-
--> $DIR/feature-gate-optimize_attribute.rs:13:12
62+
--> $DIR/feature-gate-optimize_attribute.rs:16:12
5363
|
5464
LL | #[optimize(banana)]
5565
| ^^^^^^
5666

57-
error: aborting due to 6 previous errors
67+
error: aborting due to 7 previous errors
5868

5969
Some errors have detailed explanations: E0658, E0722.
6070
For more information about an error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)