mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 22:41:50 +00:00
Rollup merge of #104121 - Lokathor:mir-opt-when-instruction-set-missing-on-callee, r=tmiasko
Refine `instruction_set` MIR 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. cc ``@oli-obk`` [Edit] Zulip Context: https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/What.20exactly.20does.20the.20MIR.20optimizer.20do.3F
This commit is contained in:
commit
4733312e09
@ -375,7 +375,12 @@ impl<'tcx> Inliner<'tcx> {
|
||||
return Err("incompatible sanitizer set");
|
||||
}
|
||||
|
||||
if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set {
|
||||
// Two functions are compatible if the callee has no attribute (meaning
|
||||
// that it's codegen agnostic), or sets an attribute that is identical
|
||||
// to this function's attribute.
|
||||
if callee_attrs.instruction_set.is_some()
|
||||
&& callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
|
||||
{
|
||||
return Err("incompatible instruction set");
|
||||
}
|
||||
|
||||
@ -453,6 +458,15 @@ impl<'tcx> Inliner<'tcx> {
|
||||
if ty.needs_drop(tcx, self.param_env) && let Some(unwind) = unwind {
|
||||
work_list.push(unwind);
|
||||
}
|
||||
} else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
|
||||
&& matches!(term.kind, TerminatorKind::InlineAsm { .. })
|
||||
{
|
||||
// During the attribute checking stage we allow a callee with no
|
||||
// instruction_set assigned to count as compatible with a function that does
|
||||
// assign one. However, during this stage we require an exact match when any
|
||||
// inline-asm is detected. LLVM will still possibly do an inline later on
|
||||
// if the no-attribute function ends up with the same instruction set anyway.
|
||||
return Err("Cannot move inline-asm across instruction sets");
|
||||
} else {
|
||||
work_list.extend(term.successors())
|
||||
}
|
||||
|
@ -6,14 +6,19 @@
|
||||
let _1: (); // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
|
||||
let _2: (); // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
|
||||
let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
|
||||
+ scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:53:5: 53:30
|
||||
let _4: (); // in scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
|
||||
+ scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:59:5: 59:30
|
||||
+ }
|
||||
+ scope 2 (inlined inline_always_and_using_inline_asm) { // at $DIR/inline_instruction_set.rs:60:5: 60:41
|
||||
+ scope 3 {
|
||||
+ }
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
|
||||
_1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
|
||||
// mir::Constant
|
||||
// + span: $DIR/inline_instruction_set.rs:51:5: 51:24
|
||||
// + span: $DIR/inline_instruction_set.rs:57:5: 57:24
|
||||
// + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
@ -22,7 +27,7 @@
|
||||
StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
|
||||
_2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
|
||||
// mir::Constant
|
||||
// + span: $DIR/inline_instruction_set.rs:52:5: 52:24
|
||||
// + span: $DIR/inline_instruction_set.rs:58:5: 58:24
|
||||
// + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
@ -31,14 +36,25 @@
|
||||
StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
|
||||
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
|
||||
- // mir::Constant
|
||||
- // + span: $DIR/inline_instruction_set.rs:53:5: 53:28
|
||||
- // + span: $DIR/inline_instruction_set.rs:59:5: 59:28
|
||||
- // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
|
||||
- }
|
||||
-
|
||||
- bb3: {
|
||||
StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
|
||||
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +4:2
|
||||
return; // scope 0 at $DIR/inline_instruction_set.rs:+4:2: +4:2
|
||||
StorageLive(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
|
||||
- _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
|
||||
- // mir::Constant
|
||||
- // + span: $DIR/inline_instruction_set.rs:60:5: 60:39
|
||||
- // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) }
|
||||
+ asm!("/* do nothing */", options((empty))) -> bb3; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38
|
||||
}
|
||||
|
||||
- bb4: {
|
||||
+ bb3: {
|
||||
StorageDead(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:41: +4:42
|
||||
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +5:2
|
||||
return; // scope 0 at $DIR/inline_instruction_set.rs:+5:2: +5:2
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
// Checks that only functions with the compatible instruction_set attributes are inlined.
|
||||
//
|
||||
// A function is "compatible" when the *callee* has the same attribute or no attribute.
|
||||
//
|
||||
// compile-flags: --target thumbv4t-none-eabi
|
||||
// needs-llvm-components: arm
|
||||
|
||||
@ -36,14 +38,18 @@ fn instruction_set_t32() {}
|
||||
#[inline]
|
||||
fn instruction_set_default() {}
|
||||
|
||||
#[inline(always)]
|
||||
fn inline_always_and_using_inline_asm() {
|
||||
unsafe { asm!("/* do nothing */") };
|
||||
}
|
||||
|
||||
// EMIT_MIR inline_instruction_set.t32.Inline.diff
|
||||
#[instruction_set(arm::t32)]
|
||||
pub fn t32() {
|
||||
instruction_set_a32();
|
||||
instruction_set_t32();
|
||||
// The default instruction set is currently
|
||||
// conservatively assumed to be incompatible.
|
||||
instruction_set_default();
|
||||
inline_always_and_using_inline_asm();
|
||||
}
|
||||
|
||||
// EMIT_MIR inline_instruction_set.default.Inline.diff
|
||||
@ -51,4 +57,5 @@ pub fn default() {
|
||||
instruction_set_a32();
|
||||
instruction_set_t32();
|
||||
instruction_set_default();
|
||||
inline_always_and_using_inline_asm();
|
||||
}
|
||||
|
@ -5,15 +5,18 @@
|
||||
let mut _0: (); // return place in scope 0 at $DIR/inline_instruction_set.rs:+0:14: +0:14
|
||||
let _1: (); // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
|
||||
let _2: (); // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
|
||||
let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
|
||||
+ scope 1 (inlined instruction_set_t32) { // at $DIR/inline_instruction_set.rs:43:5: 43:26
|
||||
let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
|
||||
let _4: (); // in scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
|
||||
+ scope 1 (inlined instruction_set_t32) { // at $DIR/inline_instruction_set.rs:50:5: 50:26
|
||||
+ }
|
||||
+ scope 2 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:51:5: 51:30
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
|
||||
_1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
|
||||
// mir::Constant
|
||||
// + span: $DIR/inline_instruction_set.rs:42:5: 42:24
|
||||
// + span: $DIR/inline_instruction_set.rs:49:5: 49:24
|
||||
// + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
@ -22,25 +25,34 @@
|
||||
StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
|
||||
- _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
|
||||
- // mir::Constant
|
||||
- // + span: $DIR/inline_instruction_set.rs:43:5: 43:24
|
||||
- // + span: $DIR/inline_instruction_set.rs:50:5: 50:24
|
||||
- // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) }
|
||||
- }
|
||||
-
|
||||
- bb2: {
|
||||
StorageDead(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27
|
||||
StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
|
||||
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
|
||||
+ _3 = instruction_set_default() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+5:5: +5:30
|
||||
StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
|
||||
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
|
||||
- // mir::Constant
|
||||
- // + span: $DIR/inline_instruction_set.rs:51:5: 51:28
|
||||
- // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
|
||||
- }
|
||||
-
|
||||
- bb3: {
|
||||
StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
|
||||
StorageLive(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
|
||||
- _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
|
||||
+ _4 = inline_always_and_using_inline_asm() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
|
||||
// mir::Constant
|
||||
// + span: $DIR/inline_instruction_set.rs:46:5: 46:28
|
||||
// + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
|
||||
// + span: $DIR/inline_instruction_set.rs:52:5: 52:39
|
||||
// + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
- bb3: {
|
||||
- bb4: {
|
||||
+ bb2: {
|
||||
StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+5:30: +5:31
|
||||
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:14: +6:2
|
||||
return; // scope 0 at $DIR/inline_instruction_set.rs:+6:2: +6:2
|
||||
StorageDead(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:41: +4:42
|
||||
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:14: +5:2
|
||||
return; // scope 0 at $DIR/inline_instruction_set.rs:+5:2: +5:2
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user