Skip to content

Commit 1c44af9

Browse files
committed
Auto merge of #111836 - calebzulawski:target-feature-closure, r=workingjubilee
Fix #[inline(always)] on closures with target feature 1.1 Fixes #108655. I think this is the most obvious solution that isn't overly complicated. The comment includes more justification, but I think this is likely better than demoting the `#[inline(always)]` to `#[inline]`, since existing code is unaffected.
2 parents 98179ad + cdb9de7 commit 1c44af9

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,22 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
501501
});
502502

503503
// #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+
{
505520
let owner_id = tcx.parent(did.to_def_id());
506521
if tcx.def_kind(owner_id).has_codegen_attrs() {
507522
codegen_fn_attrs
Original file line numberDiff line numberDiff 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| unsafe { _mm256_add_ps(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| unsafe { _mm256_add_ps(x, y) }
31+
};
32+
add(x, x)
33+
}
Original file line numberDiff line numberDiff 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() {}

0 commit comments

Comments
 (0)