mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 07:22:42 +00:00
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.
This commit is contained in:
commit
1c44af9b79
@ -501,7 +501,22 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||
});
|
||||
|
||||
// #73631: closures inherit `#[target_feature]` annotations
|
||||
if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
|
||||
//
|
||||
// If this closure is marked `#[inline(always)]`, simply skip adding `#[target_feature]`.
|
||||
//
|
||||
// At this point, `unsafe` has already been checked and `#[target_feature]` only affects codegen.
|
||||
// Emitting both `#[inline(always)]` and `#[target_feature]` can potentially result in an
|
||||
// ICE, because LLVM errors when the function fails to be inlined due to a target feature
|
||||
// mismatch.
|
||||
//
|
||||
// Using `#[inline(always)]` implies that this closure will most likely be inlined into
|
||||
// its parent function, which effectively inherits the features anyway. Boxing this closure
|
||||
// would result in this closure being compiled without the inherited target features, but this
|
||||
// is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
|
||||
if tcx.features().target_feature_11
|
||||
&& tcx.is_closure(did.to_def_id())
|
||||
&& codegen_fn_attrs.inline != InlineAttr::Always
|
||||
{
|
||||
let owner_id = tcx.parent(did.to_def_id());
|
||||
if tcx.def_kind(owner_id).has_codegen_attrs() {
|
||||
codegen_fn_attrs
|
||||
|
33
tests/codegen/target-feature-inline-closure.rs
Normal file
33
tests/codegen/target-feature-inline-closure.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// only-x86_64
|
||||
// compile-flags: -Copt-level=3
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(target_feature_11)]
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
// CHECK-LABEL: @with_avx
|
||||
#[no_mangle]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "avx")]
|
||||
fn with_avx(x: __m256) -> __m256 {
|
||||
// CHECK: fadd
|
||||
let add = {
|
||||
#[inline(always)]
|
||||
|x, y| unsafe { _mm256_add_ps(x, y) }
|
||||
};
|
||||
add(x, x)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @without_avx
|
||||
#[no_mangle]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe fn without_avx(x: __m256) -> __m256 {
|
||||
// CHECK-NOT: fadd
|
||||
let add = {
|
||||
#[inline(always)]
|
||||
|x, y| unsafe { _mm256_add_ps(x, y) }
|
||||
};
|
||||
add(x, x)
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
// Tests #108655: closures in `#[target_feature]` functions can still be marked #[inline(always)]
|
||||
|
||||
// check-pass
|
||||
// revisions: mir thir
|
||||
// [thir]compile-flags: -Z thir-unsafeck
|
||||
// only-x86_64
|
||||
|
||||
#![feature(target_feature_11)]
|
||||
|
||||
#[target_feature(enable = "avx")]
|
||||
pub unsafe fn test() {
|
||||
({
|
||||
#[inline(always)]
|
||||
move || {}
|
||||
})();
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user