Rollup merge of #135099 - Shunpoco:116971-mir-opt-copy-prop, r=davidtwco
Add FileCheck annotations to mir-opt/copy-prop This resolves a part of https://github.com/rust-lang/rust/issues/116971 . This PR adds FileCheck annotations to test files under mir-opt/copy-prop.
This commit is contained in:
commit
c97bde7df7
16 changed files with 110 additions and 89 deletions
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
//! Tests that we bail out when there are multiple assignments to the same local.
|
||||
//@ test-mir-pass: CopyProp
|
||||
|
|
@ -12,6 +11,14 @@ fn cond() -> bool {
|
|||
|
||||
// EMIT_MIR branch.foo.CopyProp.diff
|
||||
fn foo() -> i32 {
|
||||
// CHECK-LABEL: fn foo(
|
||||
// CHECK: debug x => [[x:_.*]];
|
||||
// CHECK: debug y => [[y:_.*]];
|
||||
// CHECK: bb3: {
|
||||
// CHECK: [[y]] = copy [[x]];
|
||||
// CHECK: bb5: {
|
||||
// CHECK: [[y]] = copy [[x]];
|
||||
// CHECK: _0 = copy [[y]];
|
||||
let x = val();
|
||||
|
||||
let y = if cond() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
// Check that CopyProp does propagate return values of call terminators.
|
||||
//@ test-mir-pass: CopyProp
|
||||
//@ needs-unwind
|
||||
|
|
@ -13,6 +12,13 @@ fn dummy(x: u8) -> u8 {
|
|||
|
||||
// EMIT_MIR calls.nrvo.CopyProp.diff
|
||||
fn nrvo() -> u8 {
|
||||
// CHECK-LABEL: fn nrvo(
|
||||
// CHECK: debug y => _0;
|
||||
// CHECK-NOT: StorageLive(_1);
|
||||
// CHECK-NOT: _1 = dummy(const 5_u8)
|
||||
// CHECK: _0 = dummy(const 5_u8)
|
||||
// CHECK-NOT: _0 = copy _1;
|
||||
// CHECK-NOT: StorageDead(_1);
|
||||
let y = dummy(5); // this should get NRVO
|
||||
y
|
||||
}
|
||||
|
|
@ -20,6 +26,11 @@ fn nrvo() -> u8 {
|
|||
// EMIT_MIR calls.multiple_edges.CopyProp.diff
|
||||
#[custom_mir(dialect = "runtime", phase = "initial")]
|
||||
fn multiple_edges(t: bool) -> u8 {
|
||||
// CHECK-LABEL: fn multiple_edges(
|
||||
// CHECK: bb1: {
|
||||
// CHECK: _2 = dummy(const 13_u8)
|
||||
// CHECK: bb2: {
|
||||
// CHECK: _0 = copy _2;
|
||||
mir! {
|
||||
let x: u8;
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
// Check that CopyProp does not propagate an assignment to a function argument
|
||||
// (doing so can break usages of the original argument value)
|
||||
|
|
@ -9,25 +8,46 @@ fn dummy(x: u8) -> u8 {
|
|||
|
||||
// EMIT_MIR copy_propagation_arg.foo.CopyProp.diff
|
||||
fn foo(mut x: u8) {
|
||||
// CHECK-LABEL: fn foo(
|
||||
// CHECK: debug x => [[x:_.*]];
|
||||
// CHECK: [[three:_.*]] = copy [[x]];
|
||||
// CHECK: [[two:_.*]] = dummy(move [[three]])
|
||||
// CHECK: [[x]] = move [[two]];
|
||||
// calling `dummy` to make a use of `x` that copyprop cannot eliminate
|
||||
x = dummy(x); // this will assign a local to `x`
|
||||
}
|
||||
|
||||
// EMIT_MIR copy_propagation_arg.bar.CopyProp.diff
|
||||
fn bar(mut x: u8) {
|
||||
// CHECK-LABEL: fn bar(
|
||||
// CHECK: debug x => [[x:_.*]];
|
||||
// CHECK: [[three:_.*]] = copy [[x]];
|
||||
// CHECK: dummy(move [[three]])
|
||||
// CHECK: [[x]] = const 5_u8;
|
||||
dummy(x);
|
||||
x = 5;
|
||||
}
|
||||
|
||||
// EMIT_MIR copy_propagation_arg.baz.CopyProp.diff
|
||||
fn baz(mut x: i32) -> i32 {
|
||||
// self-assignment to a function argument should be eliminated
|
||||
// CHECK-LABEL: fn baz(
|
||||
// CHECK: debug x => [[x:_.*]];
|
||||
// CHECK: [[x2:_.*]] = copy [[x]];
|
||||
// CHECK: [[x]] = move [[x2]];
|
||||
// CHECK: _0 = copy [[x]];
|
||||
// In the original case for DestProp, the self-assignment to a function argument is eliminated,
|
||||
// but in CopyProp it is not eliminated.
|
||||
x = x;
|
||||
x
|
||||
}
|
||||
|
||||
// EMIT_MIR copy_propagation_arg.arg_src.CopyProp.diff
|
||||
fn arg_src(mut x: i32) -> i32 {
|
||||
// CHECK-LABEL: fn arg_src(
|
||||
// CHECK: debug x => [[x:_.*]];
|
||||
// CHECK: debug y => [[y:_.*]];
|
||||
// CHECK: [[y]] = copy [[x]];
|
||||
// CHECK: [[x]] = const 123_i32;
|
||||
let y = x;
|
||||
x = 123; // Don't propagate this assignment to `y`
|
||||
y
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
//@ test-mir-pass: CopyProp
|
||||
|
||||
|
|
@ -12,6 +11,13 @@ struct NotCopy(bool);
|
|||
// EMIT_MIR custom_move_arg.f.CopyProp.diff
|
||||
#[custom_mir(dialect = "runtime")]
|
||||
fn f(_1: NotCopy) {
|
||||
// CHECK-LABEL: fn f(
|
||||
// CHECK: bb0: {
|
||||
// CHECK-NOT: _2 = copy _1;
|
||||
// CHECK: _0 = opaque::<NotCopy>(copy _1)
|
||||
// CHECK: bb1: {
|
||||
// CHECK-NOT: _3 = move _2;
|
||||
// CHECK: _0 = opaque::<NotCopy>(copy _1)
|
||||
mir! {
|
||||
{
|
||||
let _2 = _1;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
//! Tests that cyclic assignments don't hang CopyProp, and result in reasonable code.
|
||||
//@ test-mir-pass: CopyProp
|
||||
|
|
@ -8,6 +7,18 @@ fn val() -> i32 {
|
|||
|
||||
// EMIT_MIR cycle.main.CopyProp.diff
|
||||
fn main() {
|
||||
// CHECK-LABEL: fn main(
|
||||
// CHECK: debug x => [[x:_.*]];
|
||||
// CHECK: debug y => [[y:_.*]];
|
||||
// CHECK: debug z => [[y]];
|
||||
// CHECK-NOT: StorageLive([[y]]);
|
||||
// CHECK: [[y]] = copy [[x]];
|
||||
// CHECK-NOT: StorageLive(_3);
|
||||
// CHECK-NOT: _3 = copy [[y]];
|
||||
// CHECK-NOT: StorageLive(_4);
|
||||
// CHECK-NOT: _4 = copy _3;
|
||||
// CHECK-NOT: _1 = move _4;
|
||||
// CHECK: [[x]] = copy [[y]];
|
||||
let mut x = val();
|
||||
let y = x;
|
||||
let z = y;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
//@ test-mir-pass: CopyProp
|
||||
|
||||
|
|
@ -8,6 +7,14 @@ fn id<T>(x: T) -> T {
|
|||
|
||||
// EMIT_MIR dead_stores_79191.f.CopyProp.after.mir
|
||||
fn f(mut a: usize) -> usize {
|
||||
// CHECK-LABEL: fn f(
|
||||
// CHECK: debug a => [[a:_.*]];
|
||||
// CHECK: debug b => [[b:_.*]];
|
||||
// CHECK: [[b]] = copy [[a]];
|
||||
// CHECK: [[a]] = const 5_usize;
|
||||
// CHECK: [[a]] = copy [[b]];
|
||||
// CHECK: [[c:_.*]] = copy [[a]]
|
||||
// CHECK: id::<usize>(move [[c]])
|
||||
let b = a;
|
||||
a = 5;
|
||||
a = b;
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
// MIR for `f` after CopyProp
|
||||
|
||||
fn f(_1: usize) -> usize {
|
||||
debug a => _1;
|
||||
let mut _0: usize;
|
||||
let _2: usize;
|
||||
let mut _3: usize;
|
||||
let mut _4: usize;
|
||||
scope 1 {
|
||||
debug b => _2;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_2 = copy _1;
|
||||
_1 = const 5_usize;
|
||||
_1 = copy _2;
|
||||
StorageLive(_4);
|
||||
_4 = copy _1;
|
||||
_0 = id::<usize>(move _4) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// MIR for `f` after CopyProp
|
||||
|
||||
fn f(_1: usize) -> usize {
|
||||
debug a => _1;
|
||||
let mut _0: usize;
|
||||
let _2: usize;
|
||||
let mut _3: usize;
|
||||
let mut _4: usize;
|
||||
scope 1 {
|
||||
debug b => _2;
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_2 = copy _1;
|
||||
_1 = const 5_usize;
|
||||
_1 = copy _2;
|
||||
StorageLive(_4);
|
||||
_4 = copy _1;
|
||||
_0 = id::<usize>(move _4) -> [return: bb1, unwind continue];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
// This is a copy of the `dead_stores_79191` test, except that we turn on DSE. This demonstrates
|
||||
// that that pass enables this one to do more optimizations.
|
||||
|
||||
//@ test-mir-pass: CopyProp
|
||||
//@ compile-flags: -Zmir-enable-passes=+DeadStoreElimination
|
||||
|
||||
fn id<T>(x: T) -> T {
|
||||
x
|
||||
}
|
||||
|
||||
// EMIT_MIR dead_stores_better.f.CopyProp.after.mir
|
||||
pub fn f(mut a: usize) -> usize {
|
||||
let b = a;
|
||||
a = 5;
|
||||
a = b;
|
||||
id(a)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
f(0);
|
||||
}
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
//@ test-mir-pass: CopyProp
|
||||
|
||||
// EMIT_MIR issue_107511.main.CopyProp.diff
|
||||
fn main() {
|
||||
// CHECK-LABEL: fn main(
|
||||
// CHECK: debug i => [[i:_.*]];
|
||||
// CHECK-NOT: StorageLive([[i]]);
|
||||
// CHECK-NOT: StorageDead([[i]]);
|
||||
let mut sum = 0;
|
||||
let a = [0, 10, 20, 30];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
// Test that we do not move multiple times from the same local.
|
||||
//@ test-mir-pass: CopyProp
|
||||
|
||||
// EMIT_MIR move_arg.f.CopyProp.diff
|
||||
pub fn f<T: Copy>(a: T) {
|
||||
// CHECK-LABEL: fn f(
|
||||
// CHECK: debug a => [[a:_.*]];
|
||||
// CHECK: debug b => [[a]];
|
||||
// CHECK: g::<T>(copy [[a]], copy [[a]])
|
||||
let b = a;
|
||||
g(a, b);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
//@ test-mir-pass: CopyProp
|
||||
|
||||
|
|
@ -15,6 +14,15 @@ struct Foo(u8);
|
|||
|
||||
#[custom_mir(dialect = "runtime")]
|
||||
fn f(a: Foo) -> bool {
|
||||
// CHECK-LABEL: fn f(
|
||||
// CHECK-SAME: [[a:_.*]]: Foo)
|
||||
// CHECK: bb0: {
|
||||
// CHECK-NOT: _2 = copy [[a]];
|
||||
// CHECK-NOT: _3 = move (_2.0: u8);
|
||||
// CHECK: [[c:_.*]] = copy ([[a]].0: u8);
|
||||
// CHECK: _0 = opaque::<Foo>(copy [[a]])
|
||||
// CHECK: bb1: {
|
||||
// CHECK: _0 = opaque::<u8>(move [[c]])
|
||||
mir! {
|
||||
{
|
||||
let b = a;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
//@ test-mir-pass: CopyProp
|
||||
//
|
||||
// This attempts to mutate `a` via a pointer derived from `addr_of!(a)`. That is UB
|
||||
|
|
@ -18,6 +17,10 @@ use core::intrinsics::mir::*;
|
|||
|
||||
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
|
||||
fn f(c: bool) -> bool {
|
||||
// CHECK-LABEL: fn f(
|
||||
// CHECK: _2 = copy _1;
|
||||
// CHECK-NOT: _3 = &raw const _1;
|
||||
// CHECK: _3 = &raw const _2;
|
||||
mir! {
|
||||
{
|
||||
let a = c;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
//@ test-mir-pass: CopyProp
|
||||
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
|
@ -8,6 +7,11 @@ use core::intrinsics::mir::*;
|
|||
|
||||
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
|
||||
fn f(c: bool) -> bool {
|
||||
// CHECK-LABEL: fn f(
|
||||
// CHECK: bb2: {
|
||||
// CHECK: _2 = copy _3;
|
||||
// CHECK: bb3: {
|
||||
// CHECK: _0 = copy _2;
|
||||
mir! {
|
||||
let a: bool;
|
||||
let b: bool;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
//@ test-mir-pass: CopyProp
|
||||
// Verify that we do not ICE on partial initializations.
|
||||
|
||||
|
|
@ -9,6 +8,9 @@ use core::intrinsics::mir::*;
|
|||
// EMIT_MIR partial_init.main.CopyProp.diff
|
||||
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
|
||||
pub fn main() {
|
||||
// CHECK-LABEL: fn main(
|
||||
// CHECK: let mut [[x:_.*]]: (isize,);
|
||||
// CHECK: ([[x]].0: isize) = const 1_isize;
|
||||
mir! (
|
||||
let x: (isize, );
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
// Check that CopyProp considers reborrows as not mutating the pointer.
|
||||
//@ test-mir-pass: CopyProp
|
||||
|
|
@ -8,6 +7,9 @@ fn opaque(_: impl Sized) {}
|
|||
|
||||
// EMIT_MIR reborrow.remut.CopyProp.diff
|
||||
fn remut(mut x: u8) {
|
||||
// CHECK-LABEL: fn remut(
|
||||
// CHECK: debug a => [[a:_.*]];
|
||||
// CHECK: debug c => [[a]];
|
||||
let a = &mut x;
|
||||
let b = &mut *a; //< this cannot mutate a.
|
||||
let c = a; //< so `c` and `a` can be merged.
|
||||
|
|
@ -16,6 +18,9 @@ fn remut(mut x: u8) {
|
|||
|
||||
// EMIT_MIR reborrow.reraw.CopyProp.diff
|
||||
fn reraw(mut x: u8) {
|
||||
// CHECK-LABEL: fn reraw(
|
||||
// CHECK: debug a => [[a:_.*]];
|
||||
// CHECK: debug c => [[a]];
|
||||
let a = &mut x;
|
||||
let b = &raw mut *a; //< this cannot mutate a.
|
||||
let c = a; //< so `c` and `a` can be merged.
|
||||
|
|
@ -24,6 +29,9 @@ fn reraw(mut x: u8) {
|
|||
|
||||
// EMIT_MIR reborrow.miraw.CopyProp.diff
|
||||
fn miraw(mut x: u8) {
|
||||
// CHECK-LABEL: fn miraw(
|
||||
// CHECK: debug a => [[a:_.*]];
|
||||
// CHECK: debug c => [[a]];
|
||||
let a = &raw mut x;
|
||||
let b = unsafe { &raw mut *a }; //< this cannot mutate a.
|
||||
let c = a; //< so `c` and `a` can be merged.
|
||||
|
|
@ -32,6 +40,9 @@ fn miraw(mut x: u8) {
|
|||
|
||||
// EMIT_MIR reborrow.demiraw.CopyProp.diff
|
||||
fn demiraw(mut x: u8) {
|
||||
// CHECK-LABEL: fn demiraw(
|
||||
// CHECK: debug a => [[a:_.*]];
|
||||
// CHECK: debug c => [[a]];
|
||||
let a = &raw mut x;
|
||||
let b = unsafe { &mut *a }; //< this cannot mutate a.
|
||||
let c = a; //< so `c` and `a` can be merged.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue