mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-19 11:12:43 +00:00
Rollup merge of #117141 - tmiasko:inline-target-features, r=oli-obk
Require target features to match exactly during inlining In general it is not correct to inline a callee with a target features that are subset of the callee. Require target features to match exactly during inlining. The exact match could be potentially relaxed, but this would require identifying specific feature that are allowed to differ, those that need to match, and those that can be present in caller but not in callee. This resolves MIR part of #116573. For other concerns with respect to the previous implementation also see areInlineCompatible in LLVM.
This commit is contained in:
commit
a1ab16792b
@ -438,10 +438,8 @@ impl<'tcx> Inliner<'tcx> {
|
||||
return Err("incompatible instruction set");
|
||||
}
|
||||
|
||||
for feature in &callee_attrs.target_features {
|
||||
if !self.codegen_fn_attrs.target_features.contains(feature) {
|
||||
return Err("incompatible target feature");
|
||||
}
|
||||
if callee_attrs.target_features != self.codegen_fn_attrs.target_features {
|
||||
return Err("incompatible target features");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1,21 +0,0 @@
|
||||
- // MIR for `inlined_no_sanitize` before Inline
|
||||
+ // MIR for `inlined_no_sanitize` after Inline
|
||||
|
||||
fn inlined_no_sanitize() -> () {
|
||||
let mut _0: ();
|
||||
let _1: ();
|
||||
+ scope 1 (inlined no_sanitize) {
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _1 = no_sanitize() -> [return: bb1, unwind unreachable];
|
||||
- }
|
||||
-
|
||||
- bb1: {
|
||||
StorageDead(_1);
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
- // MIR for `inlined_no_sanitize` before Inline
|
||||
+ // MIR for `inlined_no_sanitize` after Inline
|
||||
|
||||
fn inlined_no_sanitize() -> () {
|
||||
let mut _0: ();
|
||||
let _1: ();
|
||||
+ scope 1 (inlined no_sanitize) {
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _1 = no_sanitize() -> [return: bb1, unwind continue];
|
||||
- }
|
||||
-
|
||||
- bb1: {
|
||||
StorageDead(_1);
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
- // MIR for `inlined_target_feature` before Inline
|
||||
+ // MIR for `inlined_target_feature` after Inline
|
||||
|
||||
fn inlined_target_feature() -> () {
|
||||
let mut _0: ();
|
||||
let _1: ();
|
||||
+ scope 1 (inlined target_feature) {
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _1 = target_feature() -> [return: bb1, unwind unreachable];
|
||||
- }
|
||||
-
|
||||
- bb1: {
|
||||
StorageDead(_1);
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
- // MIR for `inlined_target_feature` before Inline
|
||||
+ // MIR for `inlined_target_feature` after Inline
|
||||
|
||||
fn inlined_target_feature() -> () {
|
||||
let mut _0: ();
|
||||
let _1: ();
|
||||
+ scope 1 (inlined target_feature) {
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _1 = target_feature() -> [return: bb1, unwind continue];
|
||||
- }
|
||||
-
|
||||
- bb1: {
|
||||
StorageDead(_1);
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
- // MIR for `not_inlined_c_variadic` before Inline
|
||||
+ // MIR for `not_inlined_c_variadic` after Inline
|
||||
|
||||
fn not_inlined_c_variadic() -> () {
|
||||
let mut _0: ();
|
||||
let _1: u32;
|
||||
scope 1 {
|
||||
debug s => _1;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = sum(const 4_u32, const 4_u32, const 30_u32, const 200_u32, const 1000_u32) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = const ();
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
- // MIR for `not_inlined_c_variadic` before Inline
|
||||
+ // MIR for `not_inlined_c_variadic` after Inline
|
||||
|
||||
fn not_inlined_c_variadic() -> () {
|
||||
let mut _0: ();
|
||||
let _1: u32;
|
||||
scope 1 {
|
||||
debug s => _1;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = sum(const 4_u32, const 4_u32, const 30_u32, const 200_u32, const 1000_u32) -> [return: bb1, unwind continue];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = const ();
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
- // MIR for `not_inlined_no_sanitize` before Inline
|
||||
+ // MIR for `not_inlined_no_sanitize` after Inline
|
||||
|
||||
fn not_inlined_no_sanitize() -> () {
|
||||
let mut _0: ();
|
||||
let _1: ();
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = no_sanitize() -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_1);
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
- // MIR for `not_inlined_no_sanitize` before Inline
|
||||
+ // MIR for `not_inlined_no_sanitize` after Inline
|
||||
|
||||
fn not_inlined_no_sanitize() -> () {
|
||||
let mut _0: ();
|
||||
let _1: ();
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = no_sanitize() -> [return: bb1, unwind continue];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_1);
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
- // MIR for `not_inlined_target_feature` before Inline
|
||||
+ // MIR for `not_inlined_target_feature` after Inline
|
||||
|
||||
fn not_inlined_target_feature() -> () {
|
||||
let mut _0: ();
|
||||
let _1: ();
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = target_feature() -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_1);
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
- // MIR for `not_inlined_target_feature` before Inline
|
||||
+ // MIR for `not_inlined_target_feature` after Inline
|
||||
|
||||
fn not_inlined_target_feature() -> () {
|
||||
let mut _0: ();
|
||||
let _1: ();
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = target_feature() -> [return: bb1, unwind continue];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_1);
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,51 +1,71 @@
|
||||
// skip-filecheck
|
||||
// Checks that only functions with compatible attributes are inlined.
|
||||
//
|
||||
// only-x86_64
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
// compile-flags: -Cpanic=abort
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(no_sanitize)]
|
||||
#![feature(target_feature_11)]
|
||||
#![feature(c_variadic)]
|
||||
|
||||
// EMIT_MIR inline_compatibility.inlined_target_feature.Inline.diff
|
||||
#[target_feature(enable = "sse2")]
|
||||
pub unsafe fn inlined_target_feature() {
|
||||
target_feature();
|
||||
}
|
||||
|
||||
// EMIT_MIR inline_compatibility.not_inlined_target_feature.Inline.diff
|
||||
pub unsafe fn not_inlined_target_feature() {
|
||||
target_feature();
|
||||
}
|
||||
|
||||
// EMIT_MIR inline_compatibility.inlined_no_sanitize.Inline.diff
|
||||
#[no_sanitize(address)]
|
||||
pub unsafe fn inlined_no_sanitize() {
|
||||
no_sanitize();
|
||||
}
|
||||
|
||||
// EMIT_MIR inline_compatibility.not_inlined_no_sanitize.Inline.diff
|
||||
pub unsafe fn not_inlined_no_sanitize() {
|
||||
no_sanitize();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[target_feature(enable = "sse2")]
|
||||
pub unsafe fn target_feature() {}
|
||||
unsafe fn sse2() {}
|
||||
|
||||
#[inline]
|
||||
fn nop() {}
|
||||
|
||||
// CHECK-LABEL: fn f0()
|
||||
// CHECK: bb0: {
|
||||
// CHECK-NEXT: return;
|
||||
#[target_feature(enable = "sse2")]
|
||||
pub unsafe fn f0() {
|
||||
sse2();
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn f1()
|
||||
// CHECK: bb0: {
|
||||
// CHECK-NEXT: sse2()
|
||||
pub unsafe fn f1() {
|
||||
sse2();
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn f2()
|
||||
// CHECK: bb0: {
|
||||
// CHECK-NEXT: nop()
|
||||
#[target_feature(enable = "avx")]
|
||||
pub unsafe fn f2() {
|
||||
nop();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[no_sanitize(address)]
|
||||
pub unsafe fn no_sanitize() {}
|
||||
|
||||
// EMIT_MIR inline_compatibility.not_inlined_c_variadic.Inline.diff
|
||||
pub unsafe fn not_inlined_c_variadic() {
|
||||
let s = sum(4u32, 4u32, 30u32, 200u32, 1000u32);
|
||||
// CHECK-LABEL: fn inlined_no_sanitize()
|
||||
// CHECK: bb0: {
|
||||
// CHECK-NEXT: return;
|
||||
#[no_sanitize(address)]
|
||||
pub unsafe fn inlined_no_sanitize() {
|
||||
no_sanitize();
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn not_inlined_no_sanitize()
|
||||
// CHECK: bb0: {
|
||||
// CHECK-NEXT: no_sanitize()
|
||||
pub unsafe fn not_inlined_no_sanitize() {
|
||||
no_sanitize();
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn not_inlined_c_variadic()
|
||||
// CHECK: bb0: {
|
||||
// CHECK-NEXT: StorageLive(_1)
|
||||
// CHECK-NEXT: _1 = sum
|
||||
pub unsafe fn not_inlined_c_variadic() {
|
||||
let _ = sum(4u32, 4u32, 30u32, 200u32, 1000u32);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn sum(n: u32, mut vs: ...) -> u32 {
|
||||
let mut s = 0;
|
||||
let mut i = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user