Skip to content

Commit 2414698

Browse files
committed
Add a noinline attribute at the callsite when we bail on adding alwaysinline
1 parent b269cc3 commit 2414698

2 files changed

Lines changed: 48 additions & 9 deletions

File tree

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,20 +1434,31 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14341434

14351435
// Only propagate `#[inline(always)]` to the callsite when there is
14361436
// an attribute and the caller and callee are compatible for
1437-
// inlining here.
1437+
// inlining here. Otherwise we explicitly emit a `noinline` to
1438+
// ensure that the function will not get inlined through an LLVM
1439+
// pass.
14381440
if attributes::has_inline_always_callsite_attribute(
14391441
self.cx.tcx,
14401442
callee_attrs,
14411443
callee_instance,
1442-
) && self.tcx.is_call_inline_able_at_callsite(
1443-
&callee_attrs.target_features,
1444-
&caller_attrs.target_features,
14451444
) {
1446-
attributes::apply_to_callsite(
1447-
call,
1448-
llvm::AttributePlace::Function,
1449-
&[AttributeKind::AlwaysInline.create_attr(self.cx.llcx)],
1450-
);
1445+
if self.tcx.is_call_inline_able_at_callsite(
1446+
&callee_attrs.target_features,
1447+
&caller_attrs.target_features,
1448+
) {
1449+
attributes::apply_to_callsite(
1450+
call,
1451+
llvm::AttributePlace::Function,
1452+
&[AttributeKind::AlwaysInline.create_attr(self.cx.llcx)],
1453+
);
1454+
} else {
1455+
// Ensure the function call will not be inlined.
1456+
attributes::apply_to_callsite(
1457+
call,
1458+
llvm::AttributePlace::Function,
1459+
&[AttributeKind::NoInline.create_attr(self.cx.llcx)],
1460+
);
1461+
}
14511462
}
14521463
}
14531464

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//@ compile-flags: --crate-type=lib --target x86_64-unknown-linux-gnu -O -Zinline-mir=no -C no-prepopulate-passes
2+
//@ needs-llvm-components: x86
3+
//@ only-x86_64
4+
//@ ignore-backends: gcc
5+
6+
#![feature(core_intrinsics, target_feature_inline_always)]
7+
#![allow(incomplete_features)]
8+
9+
use std::intrinsics::{AtomicOrdering, atomic_load};
10+
11+
#[inline(always)]
12+
#[target_feature(enable = "cmpxchg16b")]
13+
#[unsafe(no_mangle)]
14+
pub fn load(x: *const u128) -> u128 {
15+
unsafe { atomic_load::<u128, { AtomicOrdering::Relaxed }>(x) }
16+
}
17+
18+
#[unsafe(no_mangle)]
19+
// CHECK-LABEL: define{{.*}} @load_core(
20+
pub fn load_core(x: *const u128) -> u128 {
21+
// `cmpxchg16b` is not enabled on the caller, so the ineligible
22+
// `#[inline(always)]` callee must be marked `noinline` at the callsite.
23+
//
24+
// CHECK: %_0 = {{(tail )?}}call{{.*}} @load(ptr{{.*}} %x) [[CALL_ATTRS:#[0-9]+]]
25+
unsafe { load(x) }
26+
}
27+
28+
// CHECK: attributes [[CALL_ATTRS]] = { {{.*}}noinline{{.*}} }

0 commit comments

Comments
 (0)