diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 46bb1182c298c..f4365db077127 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,7 +1,7 @@ use rustc_abi::{Align, ExternAbi}; use rustc_hir::attrs::{ AttributeKind, EiiImplResolution, InlineAttr, InstrumentFnAttr as HirInstrumentFnAttr, Linkage, - RtsanSetting, UsedBy, + OptimizeAttr, RtsanSetting, UsedBy, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; @@ -354,6 +354,17 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code } } + // Closures inherit `#[optimize]` annotations. + if tcx.is_closure_like(did.to_def_id()) { + let owner_id = tcx.parent(did.to_def_id()); + if tcx.def_kind(owner_id).has_codegen_attrs() { + let owner_attrs = tcx.codegen_fn_attrs(owner_id); + if codegen_fn_attrs.optimize == OptimizeAttr::Default { + codegen_fn_attrs.optimize = owner_attrs.optimize; + } + } + } + // When `no_builtins` is applied at the crate level, we should add the // `no-builtins` attribute to each function to ensure it takes effect in LTO. let no_builtins = find_attr!(tcx, crate, NoBuiltins); diff --git a/tests/codegen-llvm/optimize-closures-inheritance.rs b/tests/codegen-llvm/optimize-closures-inheritance.rs new file mode 100644 index 0000000000000..e9695d56a377d --- /dev/null +++ b/tests/codegen-llvm/optimize-closures-inheritance.rs @@ -0,0 +1,33 @@ +//! Ensure that `#[optimize]` applied to an outer function is inherited by closures +//! and their coercion shims. + +//@ compile-flags: -Copt-level=3 + +#![feature(optimize_attribute)] +#![crate_type = "lib"] + +// CHECK-DAG: define{{.*}}void {{.*}}test_none{{.*}}call_once{{.*}}#[[ATTR_NONE:[0-9]+]] +// CHECK-DAG: define{{.*}}void {{.*}}test_none{{.*}}B{{[0-9]+}}_() {{.*}}#[[ATTR_NONE]] +// CHECK-DAG: define{{.*}}void {{.*}}test_size{{.*}}call_once{{.*}}#[[ATTR_SIZE:[0-9]+]] + +// CHECK-DAG: attributes #[[ATTR_NONE]] = { {{.*}}noinline{{.*}}optnone{{.*}} } +// CHECK-DAG: attributes #[[ATTR_SIZE]] = { {{.*}}optsize{{.*}} } + +extern "C" { + fn side_effect_1(); + fn side_effect_2(); +} + +#[optimize(none)] +#[no_mangle] +pub fn test_none() -> fn() { + let closure = || unsafe { side_effect_1() }; + closure +} + +#[optimize(size)] +#[no_mangle] +pub fn test_size() -> fn() { + let closure = || unsafe { side_effect_2() }; + closure +}