Never MIR inline functions with a different instruction set
This commit is contained in:
parent
9e5d58fb42
commit
eb5e2d08c7
5 changed files with 152 additions and 1 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
54
src/test/mir-opt/inline/inline-instruction-set.rs
Normal file
54
src/test/mir-opt/inline/inline-instruction-set.rs
Normal 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();
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue