diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 08da90d535da1..2bd3cb9442d7b 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -17,7 +17,7 @@ use rustc_codegen_ssa::traits::*; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::bug; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature, TargetFeatureKind}; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers, TyAndLayout, @@ -1428,14 +1428,18 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // Attributes on the function definition being called let fn_defn_attrs = self.cx.tcx.codegen_fn_attrs(instance.def_id()); if let Some(fn_call_attrs) = fn_call_attrs - && !fn_call_attrs.target_features.is_empty() // If there is an inline attribute and a target feature that matches // we will add the attribute to the callsite otherwise we'll omit // this and not add the attribute to prevent soundness issues. && let Some(inlining_rule) = attributes::inline_attr(&self.cx, self.cx.tcx, instance) && self.cx.tcx.is_target_feature_call_safe( - &fn_call_attrs.target_features, &fn_defn_attrs.target_features, + &fn_call_attrs.target_features.iter().cloned().chain( + self.cx.tcx.sess.target_features.iter().map(|feat| TargetFeature { + name: *feat, + kind: TargetFeatureKind::Implied, + }) + ).collect::>(), ) { attributes::apply_to_callsite( diff --git a/tests/codegen-llvm/inline-always-callsite.rs b/tests/codegen-llvm/inline-always-callsite.rs new file mode 100644 index 0000000000000..c47113e3bf3ab --- /dev/null +++ b/tests/codegen-llvm/inline-always-callsite.rs @@ -0,0 +1,37 @@ +//@ add-core-stubs +//@ compile-flags: --target aarch64-unknown-linux-gnu -Zinline-mir=no -C no-prepopulate-passes +//@ needs-llvm-components: aarch64 + +#![crate_type = "lib"] +#![feature(no_core, lang_items, target_feature_inline_always)] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[inline(always)] +#[target_feature(enable = "neon")] +#[no_mangle] +pub fn single_target_feature() -> i32 { + 42 +} + +#[inline(always)] +#[target_feature(enable = "neon,i8mm")] +#[no_mangle] +// CHECK: define noundef i32 @multiple_target_features() unnamed_addr #1 { +pub fn multiple_target_features() -> i32 { + // CHECK: %_0 = call noundef i32 @single_target_feature() #3 + single_target_feature() +} + +#[no_mangle] +// CHECK: define noundef i32 @inherits_from_global() unnamed_addr #2 { +pub fn inherits_from_global() -> i32 { + unsafe { + // CHECK: %_0 = call noundef i32 @single_target_feature() #3 + single_target_feature() + } +} + +// CHECK: attributes #3 = { alwaysinline nounwind }