Never MIR inline functions with a different instruction set

This commit is contained in:
Tomasz Miąsko 2021-02-05 00:00:00 +00:00
parent 9e5d58fb42
commit eb5e2d08c7
5 changed files with 152 additions and 1 deletions

View File

@ -74,7 +74,7 @@ pub enum InlineAttr {
Never,
}
#[derive(Clone, Encodable, Decodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum InstructionSetAttr {
ArmA32,
ArmT32,

View File

@ -281,6 +281,11 @@ impl Inliner<'tcx> {
return false;
}
if self.codegen_fn_attrs.instruction_set != codegen_fn_attrs.instruction_set {
debug!("`callee has incompatible instruction set - not inlining");
return false;
}
let hinted = match codegen_fn_attrs.inline {
// Just treat inline(always) as a hint for now,
// there are cases that prevent inlining that we

View File

@ -0,0 +1,54 @@
// Checks that only functions with the compatible instruction_set attributes are inlined.
//
// compile-flags: --target thumbv4t-none-eabi
// needs-llvm-components: arm
#![crate_type = "lib"]
#![feature(rustc_attrs)]
#![feature(no_core, lang_items)]
#![feature(isa_attribute)]
#![no_core]
#[rustc_builtin_macro]
#[macro_export]
macro_rules! asm {
("assembly template",
$(operands,)*
$(options($(option),*))?
) => {
/* compiler built-in */
};
}
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
#[instruction_set(arm::a32)]
#[inline]
fn instruction_set_a32() {}
#[instruction_set(arm::t32)]
#[inline]
fn instruction_set_t32() {}
#[inline]
fn instruction_set_default() {}
// 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();
}
// EMIT_MIR inline_instruction_set.default.Inline.diff
pub fn default() {
instruction_set_a32();
instruction_set_t32();
instruction_set_default();
}

View File

@ -0,0 +1,45 @@
- // MIR for `default` before Inline
+ // MIR for `default` after Inline
fn default() -> () {
let mut _0: (); // return place in scope 0 at $DIR/inline-instruction-set.rs:50:18: 50:18
let _1: (); // in scope 0 at $DIR/inline-instruction-set.rs:51:5: 51:26
let _2: (); // in scope 0 at $DIR/inline-instruction-set.rs:52:5: 52:26
let _3: (); // in scope 0 at $DIR/inline-instruction-set.rs:53:5: 53:30
+ scope 1 (inlined instruction_set_default) { // at $DIR/inline-instruction-set.rs:53:5: 53:30
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/inline-instruction-set.rs:51:5: 51:26
_1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline-instruction-set.rs:51:5: 51:26
// mir::Constant
// + span: $DIR/inline-instruction-set.rs:51:5: 51:24
// + literal: Const { ty: fn() {instruction_set_a32}, val: Value(Scalar(<ZST>)) }
}
bb1: {
StorageDead(_1); // scope 0 at $DIR/inline-instruction-set.rs:51:26: 51:27
StorageLive(_2); // scope 0 at $DIR/inline-instruction-set.rs:52:5: 52:26
_2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline-instruction-set.rs:52:5: 52:26
// mir::Constant
// + span: $DIR/inline-instruction-set.rs:52:5: 52:24
// + literal: Const { ty: fn() {instruction_set_t32}, val: Value(Scalar(<ZST>)) }
}
bb2: {
StorageDead(_2); // scope 0 at $DIR/inline-instruction-set.rs:52:26: 52:27
StorageLive(_3); // scope 0 at $DIR/inline-instruction-set.rs:53:5: 53:30
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline-instruction-set.rs:53:5: 53:30
- // mir::Constant
- // + span: $DIR/inline-instruction-set.rs:53:5: 53:28
- // + literal: Const { ty: fn() {instruction_set_default}, val: Value(Scalar(<ZST>)) }
- }
-
- bb3: {
+ _3 = const (); // scope 1 at $DIR/inline-instruction-set.rs:53:5: 53:30
StorageDead(_3); // scope 0 at $DIR/inline-instruction-set.rs:53:30: 53:31
_0 = const (); // scope 0 at $DIR/inline-instruction-set.rs:50:18: 54:2
return; // scope 0 at $DIR/inline-instruction-set.rs:54:2: 54:2
}
}

View File

@ -0,0 +1,47 @@
- // MIR for `t32` before Inline
+ // MIR for `t32` after Inline
fn t32() -> () {
let mut _0: (); // return place in scope 0 at $DIR/inline-instruction-set.rs:41:14: 41:14
let _1: (); // in scope 0 at $DIR/inline-instruction-set.rs:42:5: 42:26
let _2: (); // in scope 0 at $DIR/inline-instruction-set.rs:43:5: 43:26
let _3: (); // in scope 0 at $DIR/inline-instruction-set.rs:46:5: 46:30
+ scope 1 (inlined instruction_set_t32) { // at $DIR/inline-instruction-set.rs:43:5: 43:26
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/inline-instruction-set.rs:42:5: 42:26
_1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline-instruction-set.rs:42:5: 42:26
// mir::Constant
// + span: $DIR/inline-instruction-set.rs:42:5: 42:24
// + literal: Const { ty: fn() {instruction_set_a32}, val: Value(Scalar(<ZST>)) }
}
bb1: {
StorageDead(_1); // scope 0 at $DIR/inline-instruction-set.rs:42:26: 42:27
StorageLive(_2); // scope 0 at $DIR/inline-instruction-set.rs:43:5: 43:26
- _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline-instruction-set.rs:43:5: 43:26
- // mir::Constant
- // + span: $DIR/inline-instruction-set.rs:43:5: 43:24
- // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(Scalar(<ZST>)) }
- }
-
- bb2: {
+ _2 = const (); // scope 1 at $DIR/inline-instruction-set.rs:43:5: 43:26
StorageDead(_2); // scope 0 at $DIR/inline-instruction-set.rs:43:26: 43:27
StorageLive(_3); // scope 0 at $DIR/inline-instruction-set.rs:46:5: 46:30
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline-instruction-set.rs:46:5: 46:30
+ _3 = instruction_set_default() -> bb2; // scope 0 at $DIR/inline-instruction-set.rs:46:5: 46:30
// mir::Constant
// + span: $DIR/inline-instruction-set.rs:46:5: 46:28
// + literal: Const { ty: fn() {instruction_set_default}, val: Value(Scalar(<ZST>)) }
}
- bb3: {
+ bb2: {
StorageDead(_3); // scope 0 at $DIR/inline-instruction-set.rs:46:30: 46:31
_0 = const (); // scope 0 at $DIR/inline-instruction-set.rs:41:14: 47:2
return; // scope 0 at $DIR/inline-instruction-set.rs:47:2: 47:2
}
}