Skip to content

Commit 2a0e52c

Browse files
committed
Auto merge of #162896 - Jamesbarford:feat/inline-always+target-feature-#2_no-callsite, r=<try>
Feat/inline always+target feature #2 no callsite
2 parents c999cef + 27e7311 commit 2a0e52c

8 files changed

Lines changed: 89 additions & 70 deletions

File tree

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ pub(crate) fn inline_attr<'tcx, 'll>(
6767

6868
match inline {
6969
InlineAttr::Hint => Some(AttributeKind::InlineHint.create_attr(cx.llcx)),
70+
// LLVM 22 and older may inline a target-featured function into a caller
71+
// that lacks those features. Keep the function inlineable, but do not force it.
72+
InlineAttr::Always
73+
if !codegen_fn_attrs.target_features.is_empty()
74+
&& llvm_util::get_version() < (23, 0, 0) =>
75+
{
76+
Some(AttributeKind::InlineHint.create_attr(cx.llcx))
77+
}
7078
InlineAttr::Always | InlineAttr::Force { .. } => {
7179
Some(AttributeKind::AlwaysInline.create_attr(cx.llcx))
7280
}

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,21 +1523,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
15231523
)
15241524
};
15251525

1526-
if let Some(callee_instance) = callee_instance {
1527-
// Attributes on the function definition being called
1528-
let callee_attrs = self.cx.tcx.codegen_fn_attrs(callee_instance.def_id());
1529-
1530-
if let Some(inlining_rule) =
1531-
attributes::inline_attr(&self.cx, self.cx.tcx, callee_instance, callee_attrs)
1532-
{
1533-
attributes::apply_to_callsite(
1534-
call,
1535-
llvm::AttributePlace::Function,
1536-
&[inlining_rule],
1537-
);
1538-
}
1539-
}
1540-
15411526
if let Some(fn_abi) = fn_abi {
15421527
fn_abi.apply_attrs_callsite(self, call);
15431528
}

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -415,33 +415,6 @@ fn check_result(
415415
interesting_spans: InterestingAttributeDiagnosticSpans,
416416
codegen_fn_attrs: &CodegenFnAttrs,
417417
) {
418-
// If a function uses `#[target_feature]` it can't be inlined into general
419-
// purpose functions as they wouldn't have the right target features
420-
// enabled. For that reason we also forbid `#[inline(always)]` as it can't be
421-
// respected.
422-
//
423-
// `#[rustc_force_inline]` doesn't need to be prohibited here, only
424-
// `#[inline(always)]`, as forced inlining is implemented entirely within
425-
// rustc (and so the MIR inliner can do any necessary checks for compatible target
426-
// features).
427-
//
428-
// This sidesteps the LLVM blockers in enabling `target_features` +
429-
// `inline(always)` to be used together (see rust-lang/rust#116573 and
430-
// llvm/llvm-project#70563).
431-
if !codegen_fn_attrs.target_features.is_empty()
432-
&& matches!(codegen_fn_attrs.inline, InlineAttr::Always)
433-
&& let Some(span) = interesting_spans.inline
434-
{
435-
let mut diag = tcx
436-
.dcx()
437-
.struct_span_err(span, "cannot use `#[inline(always)]` with `#[target_feature]`");
438-
diag.note(
439-
"See this issue for full discussion: \
440-
https://github.com/rust-lang/rust/issues/145574",
441-
);
442-
diag.emit();
443-
}
444-
445418
// warn that inline has no effect when no_sanitize is present
446419
if codegen_fn_attrs.sanitizers != SanitizerFnAttrs::default()
447420
&& codegen_fn_attrs.inline.always()

compiler/rustc_lint/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,9 @@ fn register_builtins(store: &mut LintStore) {
697697
store.register_removed("soft_unstable", "the general soft-unstable mechanism has been removed");
698698
store.register_removed(
699699
"inline_always_mismatching_target_features",
700-
"replaced by a hard error for `#[inline(always)]` with `#[target_feature]`",
700+
"replaced by a hard error for `#[inline(always)]` with `#[target_feature]`. \
701+
This was prior to LLVM23 where combining these could be unsound. See \
702+
<https://github.com/rust-lang/rust/issues/145574> for more information",
701703
);
702704
store.register_removed(
703705
"repr_transparent_external_private_fields",
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ only-x86_64
2+
//@ min-llvm-version: 23
3+
//@ compile-flags: -Copt-level=3
4+
5+
#![crate_type = "lib"]
6+
#![feature(test)]
7+
#![allow(unused_unsafe)]
8+
9+
use std::arch::x86_64::_bzhi_u64;
10+
11+
extern crate test;
12+
use test::black_box as b;
13+
14+
#[inline(always)]
15+
#[target_feature(enable = "bmi2")]
16+
#[unsafe(no_mangle)]
17+
pub unsafe fn callee_requires_bmi2() -> u64 {
18+
// black box this as `_bzhi_u64(1, 2)` can evaluate to `1` at compile time and LLVM is smart
19+
// enough to see that it then can ignore `bmi2` as this returns a constant. Which is safe to
20+
// do.
21+
b(_bzhi_u64(1, 2))
22+
}
23+
24+
#[unsafe(no_mangle)]
25+
// CHECK-LABEL: define{{.*}} @caller_only()
26+
// CHECK: [[TMP:%.+]] = tail call noundef i64 @callee_requires_bmi2()
27+
pub unsafe fn caller_only() {
28+
let _x = callee_requires_bmi2();
29+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//@ add-minicore
2+
//@ compile-flags: --target aarch64-unknown-linux-gnu -Zinline-mir=no -C no-prepopulate-passes -Copt-level=3
3+
//@ needs-llvm-components: aarch64
4+
//@ min-llvm-version: 23
5+
6+
#![crate_type = "lib"]
7+
#![feature(no_core, lang_items)]
8+
#![no_core]
9+
10+
extern crate minicore;
11+
use minicore::*;
12+
13+
#[inline(always)]
14+
#[target_feature(enable = "neon")]
15+
#[no_mangle]
16+
pub fn single_target_feature() -> i32 {
17+
42
18+
}
19+
20+
#[inline(always)]
21+
#[target_feature(enable = "neon,i8mm")]
22+
#[no_mangle]
23+
// CHECK: define{{( noundef)?}} i32 @multiple_target_features() unnamed_addr #1{{( !guid ![0-9]+)?}} {
24+
pub fn multiple_target_features() -> i32 {
25+
// CHECK: %_0 = call{{( noundef)?}} i32 @single_target_feature() #3
26+
single_target_feature()
27+
}
28+
29+
#[no_mangle]
30+
// CHECK: define{{( noundef)?}} i32 @inherits_from_global() unnamed_addr #2{{( !guid ![0-9]+)?}} {
31+
pub fn inherits_from_global() -> i32 {
32+
unsafe {
33+
// CHECK: %_0 = call{{( noundef)?}} i32 @single_target_feature() #3
34+
single_target_feature()
35+
}
36+
}

tests/ui/target-feature/invalid-attribute.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,6 @@ type Uwu = ();
6666
//~^ ERROR attribute cannot be used on
6767
trait Baz {}
6868

69-
#[inline(always)]
70-
//~^ ERROR: cannot use `#[inline(always)]`
71-
//~| NOTE: See this issue for full discussion: https://github.com/rust-lang/rust/issues/145574
72-
#[target_feature(enable = "sse2")]
73-
unsafe fn test() {}
74-
7569
#[target_feature(enable = "sse2")]
7670
//~^ ERROR attribute cannot be used on
7771
static A: () = ();

tests/ui/target-feature/invalid-attribute.stderr

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -121,53 +121,45 @@ LL | #[target_feature(enable = "sse2")]
121121
= help: the `target_feature` attribute can only be applied to functions
122122

123123
error: the `target_feature` attribute cannot be used on statics
124-
--> $DIR/invalid-attribute.rs:75:3
124+
--> $DIR/invalid-attribute.rs:69:3
125125
|
126126
LL | #[target_feature(enable = "sse2")]
127127
| ^^^^^^^^^^^^^^
128128
|
129129
= help: the `target_feature` attribute can only be applied to functions
130130

131131
error: the `target_feature` attribute cannot be used on trait impl blocks
132-
--> $DIR/invalid-attribute.rs:79:3
132+
--> $DIR/invalid-attribute.rs:73:3
133133
|
134134
LL | #[target_feature(enable = "sse2")]
135135
| ^^^^^^^^^^^^^^
136136
|
137137
= help: the `target_feature` attribute can only be applied to functions
138138

139139
error: the `target_feature` attribute cannot be used on inherent impl blocks
140-
--> $DIR/invalid-attribute.rs:85:3
140+
--> $DIR/invalid-attribute.rs:79:3
141141
|
142142
LL | #[target_feature(enable = "sse2")]
143143
| ^^^^^^^^^^^^^^
144144
|
145145
= help: the `target_feature` attribute can only be applied to functions
146146

147147
error: the `target_feature` attribute cannot be used on expressions
148-
--> $DIR/invalid-attribute.rs:106:7
148+
--> $DIR/invalid-attribute.rs:100:7
149149
|
150150
LL | #[target_feature(enable = "sse2")]
151151
| ^^^^^^^^^^^^^^
152152
|
153153
= help: the `target_feature` attribute can only be applied to functions
154154

155155
error: the `target_feature` attribute cannot be used on closures
156-
--> $DIR/invalid-attribute.rs:112:7
156+
--> $DIR/invalid-attribute.rs:106:7
157157
|
158158
LL | #[target_feature(enable = "sse2")]
159159
| ^^^^^^^^^^^^^^
160160
|
161161
= help: the `target_feature` attribute can be applied to functions and methods
162162

163-
error: cannot use `#[inline(always)]` with `#[target_feature]`
164-
--> $DIR/invalid-attribute.rs:69:1
165-
|
166-
LL | #[inline(always)]
167-
| ^^^^^^^^^^^^^^^^^
168-
|
169-
= note: See this issue for full discussion: https://github.com/rust-lang/rust/issues/145574
170-
171163
error: the feature named `foo` is not valid for this target
172164
--> $DIR/invalid-attribute.rs:27:18
173165
|
@@ -177,7 +169,7 @@ LL | #[target_feature(enable = "foo")]
177169
= help: valid names are: `fma`, `xop`, `adx`, `aes`, and `avx` and X more
178170

179171
error[E0046]: not all trait items implemented, missing: `foo`
180-
--> $DIR/invalid-attribute.rs:81:1
172+
--> $DIR/invalid-attribute.rs:75:1
181173
|
182174
LL | impl Quux for u8 {}
183175
| ^^^^^^^^^^^^^^^^ missing `foo` in implementation
@@ -186,7 +178,7 @@ LL | fn foo();
186178
| --------- `foo` from trait
187179

188180
error: `#[target_feature(..)]` cannot be applied to safe trait method
189-
--> $DIR/invalid-attribute.rs:95:5
181+
--> $DIR/invalid-attribute.rs:89:5
190182
|
191183
LL | #[target_feature(enable = "sse2")]
192184
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
@@ -195,21 +187,21 @@ LL | fn foo() {}
195187
| -------- not an `unsafe` function
196188

197189
error[E0053]: method `foo` has an incompatible type for trait
198-
--> $DIR/invalid-attribute.rs:98:5
190+
--> $DIR/invalid-attribute.rs:92:5
199191
|
200192
LL | fn foo() {}
201193
| ^^^^^^^^ expected safe fn, found unsafe fn
202194
|
203195
note: type in trait
204-
--> $DIR/invalid-attribute.rs:90:5
196+
--> $DIR/invalid-attribute.rs:84:5
205197
|
206198
LL | fn foo();
207199
| ^^^^^^^^^
208200
= note: expected signature `fn()`
209201
found signature `#[target_feature(..)] fn()`
210202

211203
error: the feature named `+sse2` is not valid for this target
212-
--> $DIR/invalid-attribute.rs:117:18
204+
--> $DIR/invalid-attribute.rs:111:18
213205
|
214206
LL | #[target_feature(enable = "+sse2")]
215207
| ^^^^^^^^^^^^^^^^ `+sse2` is not valid for this target
@@ -221,22 +213,22 @@ LL + #[target_feature(enable = "sse2")]
221213
|
222214

223215
error: the feature named `sse5` is not valid for this target
224-
--> $DIR/invalid-attribute.rs:122:18
216+
--> $DIR/invalid-attribute.rs:116:18
225217
|
226218
LL | #[target_feature(enable = "sse5")]
227219
| ^^^^^^^^^^^^^^^ `sse5` is not valid for this target
228220
|
229221
= help: valid names are: `sse`, `sse2`, `sse3`, `sse4a`, and `ssse3` and X more
230222

231223
error: the feature named `avx512` is not valid for this target
232-
--> $DIR/invalid-attribute.rs:127:18
224+
--> $DIR/invalid-attribute.rs:121:18
233225
|
234226
LL | #[target_feature(enable = "avx512")]
235227
| ^^^^^^^^^^^^^^^^^ `avx512` is not valid for this target
236228
|
237229
= help: valid names are: `avx512f`, `avx2`, `avx512bw`, `avx512cd`, and `avx512dq` and X more
238230

239-
error: aborting due to 26 previous errors
231+
error: aborting due to 25 previous errors
240232

241233
Some errors have detailed explanations: E0046, E0053, E0539.
242234
For more information about an error, try `rustc --explain E0046`.

0 commit comments

Comments
 (0)