Auto merge of #111836 - calebzulawski:target-feature-closure, r=worki… · rust-lang/rust@1c44af9 (original) (raw)

File tree

3 files changed

lines changed

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -501,7 +501,22 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
501 501 });
502 502
503 503 // #73631: closures inherit `#[target_feature]` annotations
504 -if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
504 +//
505 +// If this closure is marked `#[inline(always)]`, simply skip adding `#[target_feature]`.
506 +//
507 +// At this point, `unsafe` has already been checked and `#[target_feature]` only affects codegen.
508 +// Emitting both `#[inline(always)]` and `#[target_feature]` can potentially result in an
509 +// ICE, because LLVM errors when the function fails to be inlined due to a target feature
510 +// mismatch.
511 +//
512 +// Using `#[inline(always)]` implies that this closure will most likely be inlined into
513 +// its parent function, which effectively inherits the features anyway. Boxing this closure
514 +// would result in this closure being compiled without the inherited target features, but this
515 +// is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
516 +if tcx.features().target_feature_11
517 + && tcx.is_closure(did.to_def_id())
518 + && codegen_fn_attrs.inline != InlineAttr::Always
519 +{
505 520 let owner_id = tcx.parent(did.to_def_id());
506 521 if tcx.def_kind(owner_id).has_codegen_attrs() {
507 522 codegen_fn_attrs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
1 +// only-x86_64
2 +// compile-flags: -Copt-level=3
3 +
4 +#![crate_type = "lib"]
5 +#![feature(target_feature_11)]
6 +
7 +#[cfg(target_arch = "x86_64")]
8 +use std::arch::x86_64::*;
9 +
10 +// CHECK-LABEL: @with_avx
11 +#[no_mangle]
12 +#[cfg(target_arch = "x86_64")]
13 +#[target_feature(enable = "avx")]
14 +fn with_avx(x: __m256) -> __m256 {
15 +// CHECK: fadd
16 +let add = {
17 +#[inline(always)]
18 + |x, y
19 +};
20 +add(x, x)
21 +}
22 +
23 +// CHECK-LABEL: @without_avx
24 +#[no_mangle]
25 +#[cfg(target_arch = "x86_64")]
26 +unsafe fn without_avx(x: __m256) -> __m256 {
27 +// CHECK-NOT: fadd
28 +let add = {
29 +#[inline(always)]
30 + |x, y
31 +};
32 +add(x, x)
33 +}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
1 +// Tests #108655: closures in `#[target_feature]` functions can still be marked #[inline(always)]
2 +
3 +// check-pass
4 +// revisions: mir thir
5 +// [thir]compile-flags: -Z thir-unsafeck
6 +// only-x86_64
7 +
8 +#![feature(target_feature_11)]
9 +
10 +#[target_feature(enable = "avx")]
11 +pub unsafe fn test() {
12 +({
13 +#[inline(always)]
14 +move |
15 +})();
16 +}
17 +
18 +fn main() {}