Skip to content

Commit ea47943

Browse files
committed
Refine instruction_set inline rules
Previously an exact match of the `instruction_set` attribute was required for an MIR inline to be considered. This change checks for an exact match *only* if the callee sets an `instruction_set` in the first place. When the callee does not declare an instruction set then it is considered to be platform agnostic code and it's allowed to be inline'd into the caller.
1 parent 68f7729 commit ea47943

File tree

4 files changed

+71
-22
lines changed

4 files changed

+71
-22
lines changed

compiler/rustc_mir_transform/src/inline.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,12 @@ impl<'tcx> Inliner<'tcx> {
375375
return Err("incompatible sanitizer set");
376376
}
377377

378-
if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set {
378+
// Two functions are compatible if the callee has no attribute (meaning
379+
// that it's codegen agnostic), or sets an attribute that is identical
380+
// to this function's attribute.
381+
if callee_attrs.instruction_set.is_some()
382+
&& callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
383+
{
379384
return Err("incompatible instruction set");
380385
}
381386

@@ -453,6 +458,15 @@ impl<'tcx> Inliner<'tcx> {
453458
if ty.needs_drop(tcx, self.param_env) && let Some(unwind) = unwind {
454459
work_list.push(unwind);
455460
}
461+
} else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
462+
&& matches!(term.kind, TerminatorKind::InlineAsm { .. })
463+
{
464+
// During the attribute checking stage we allow a callee with no
465+
// instruction_set assigned to count as compatible with a function that does
466+
// assign one. However, during this stage we require an exact match when any
467+
// inline-asm is detected. LLVM will still possibly do an inline later on
468+
// if the no-attribute function ends up with the same instruction set anyway.
469+
return Err("Cannot move inline-asm across instruction sets");
456470
} else {
457471
work_list.extend(term.successors())
458472
}

src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff

+22-6
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@
66
let _1: (); // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
77
let _2: (); // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
88
let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
9-
+ scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:53:5: 53:30
9+
let _4: (); // in scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
10+
+ scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:59:5: 59:30
11+
+ }
12+
+ scope 2 (inlined inline_always_and_using_inline_asm) { // at $DIR/inline_instruction_set.rs:60:5: 60:41
13+
+ scope 3 {
14+
+ }
1015
+ }
1116

1217
bb0: {
1318
StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
1419
_1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
1520
// mir::Constant
16-
// + span: $DIR/inline_instruction_set.rs:51:5: 51:24
21+
// + span: $DIR/inline_instruction_set.rs:57:5: 57:24
1722
// + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) }
1823
}
1924

@@ -22,7 +27,7 @@
2227
StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
2328
_2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
2429
// mir::Constant
25-
// + span: $DIR/inline_instruction_set.rs:52:5: 52:24
30+
// + span: $DIR/inline_instruction_set.rs:58:5: 58:24
2631
// + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) }
2732
}
2833

@@ -31,14 +36,25 @@
3136
StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
3237
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
3338
- // mir::Constant
34-
- // + span: $DIR/inline_instruction_set.rs:53:5: 53:28
39+
- // + span: $DIR/inline_instruction_set.rs:59:5: 59:28
3540
- // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
3641
- }
3742
-
3843
- bb3: {
3944
StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
40-
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +4:2
41-
return; // scope 0 at $DIR/inline_instruction_set.rs:+4:2: +4:2
45+
StorageLive(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
46+
- _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
47+
- // mir::Constant
48+
- // + span: $DIR/inline_instruction_set.rs:60:5: 60:39
49+
- // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) }
50+
+ asm!("/* do nothing */", options((empty))) -> bb3; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38
51+
}
52+
53+
- bb4: {
54+
+ bb3: {
55+
StorageDead(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:41: +4:42
56+
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +5:2
57+
return; // scope 0 at $DIR/inline_instruction_set.rs:+5:2: +5:2
4258
}
4359
}
4460

src/test/mir-opt/inline/inline_instruction_set.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// Checks that only functions with the compatible instruction_set attributes are inlined.
22
//
3+
// A function is "compatible" when the *callee* has the same attribute or no attribute.
4+
//
35
// compile-flags: --target thumbv4t-none-eabi
46
// needs-llvm-components: arm
57

@@ -36,19 +38,24 @@ fn instruction_set_t32() {}
3638
#[inline]
3739
fn instruction_set_default() {}
3840

41+
#[inline(always)]
42+
fn inline_always_and_using_inline_asm() {
43+
unsafe { asm!("/* do nothing */") };
44+
}
45+
3946
// EMIT_MIR inline_instruction_set.t32.Inline.diff
4047
#[instruction_set(arm::t32)]
4148
pub fn t32() {
4249
instruction_set_a32();
4350
instruction_set_t32();
44-
// The default instruction set is currently
45-
// conservatively assumed to be incompatible.
4651
instruction_set_default();
52+
inline_always_and_using_inline_asm();
4753
}
4854

4955
// EMIT_MIR inline_instruction_set.default.Inline.diff
5056
pub fn default() {
5157
instruction_set_a32();
5258
instruction_set_t32();
5359
instruction_set_default();
60+
inline_always_and_using_inline_asm();
5461
}

src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff

+25-13
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@
55
let mut _0: (); // return place in scope 0 at $DIR/inline_instruction_set.rs:+0:14: +0:14
66
let _1: (); // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
77
let _2: (); // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
8-
let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
9-
+ scope 1 (inlined instruction_set_t32) { // at $DIR/inline_instruction_set.rs:43:5: 43:26
8+
let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
9+
let _4: (); // in scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
10+
+ scope 1 (inlined instruction_set_t32) { // at $DIR/inline_instruction_set.rs:50:5: 50:26
11+
+ }
12+
+ scope 2 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:51:5: 51:30
1013
+ }
1114

1215
bb0: {
1316
StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
1417
_1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
1518
// mir::Constant
16-
// + span: $DIR/inline_instruction_set.rs:42:5: 42:24
19+
// + span: $DIR/inline_instruction_set.rs:49:5: 49:24
1720
// + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) }
1821
}
1922

@@ -22,25 +25,34 @@
2225
StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
2326
- _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
2427
- // mir::Constant
25-
- // + span: $DIR/inline_instruction_set.rs:43:5: 43:24
28+
- // + span: $DIR/inline_instruction_set.rs:50:5: 50:24
2629
- // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) }
2730
- }
2831
-
2932
- bb2: {
3033
StorageDead(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27
31-
StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
32-
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
33-
+ _3 = instruction_set_default() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
34+
StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
35+
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
36+
- // mir::Constant
37+
- // + span: $DIR/inline_instruction_set.rs:51:5: 51:28
38+
- // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
39+
- }
40+
-
41+
- bb3: {
42+
StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
43+
StorageLive(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
44+
- _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
45+
+ _4 = inline_always_and_using_inline_asm() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
3446
// mir::Constant
35-
// + span: $DIR/inline_instruction_set.rs:46:5: 46:28
36-
// + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
47+
// + span: $DIR/inline_instruction_set.rs:52:5: 52:39
48+
// + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) }
3749
}
3850

39-
- bb3: {
51+
- bb4: {
4052
+ bb2: {
41-
StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+5:30: +5:31
42-
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:14: +6:2
43-
return; // scope 0 at $DIR/inline_instruction_set.rs:+6:2: +6:2
53+
StorageDead(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:41: +4:42
54+
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:14: +5:2
55+
return; // scope 0 at $DIR/inline_instruction_set.rs:+5:2: +5:2
4456
}
4557
}
4658

0 commit comments

Comments
 (0)