diff --git a/src/test/mir-opt/dest-prop/branch.rs b/src/test/mir-opt/dest-prop/branch.rs new file mode 100644 index 0000000000000..b49ecf07daa39 --- /dev/null +++ b/src/test/mir-opt/dest-prop/branch.rs @@ -0,0 +1,21 @@ +//! Tests that assignment in both branches of an `if` are eliminated. + +fn val() -> i32 { + 1 +} + +fn cond() -> bool { + true +} + +// EMIT_MIR rustc.main.DestinationPropagation.diff +fn main() { + let x = val(); + + let y = if cond() { + x + } else { + val(); + x + }; +} diff --git a/src/test/mir-opt/dest-prop/branch/rustc.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/branch/rustc.main.DestinationPropagation.diff new file mode 100644 index 0000000000000..b8387ae449387 --- /dev/null +++ b/src/test/mir-opt/dest-prop/branch/rustc.main.DestinationPropagation.diff @@ -0,0 +1,88 @@ +- // MIR for `main` before DestinationPropagation ++ // MIR for `main` after DestinationPropagation + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/branch.rs:12:11: 12:11 + let _1: i32; // in scope 0 at $DIR/branch.rs:13:9: 13:10 + let mut _3: bool; // in scope 0 at $DIR/branch.rs:15:16: 15:22 + let _4: i32; // in scope 0 at $DIR/branch.rs:18:9: 18:14 + scope 1 { +- debug x => _1; // in scope 1 at $DIR/branch.rs:13:9: 13:10 ++ debug x => _2; // in scope 1 at $DIR/branch.rs:13:9: 13:10 + let _2: i32; // in scope 1 at $DIR/branch.rs:15:9: 15:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/branch.rs:15:9: 15:10 + } + } + + bb0: { +- StorageLive(_1); // scope 0 at $DIR/branch.rs:13:9: 13:10 +- _1 = const val() -> bb1; // scope 0 at $DIR/branch.rs:13:13: 13:18 ++ nop; // scope 0 at $DIR/branch.rs:13:9: 13:10 ++ _2 = const val() -> bb1; // scope 0 at $DIR/branch.rs:13:13: 13:18 + // ty::Const + // + ty: fn() -> i32 {val} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/branch.rs:13:13: 13:16 + // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar()) } + } + + bb1: { +- StorageLive(_2); // scope 1 at $DIR/branch.rs:15:9: 15:10 ++ nop; // scope 1 at $DIR/branch.rs:15:9: 15:10 + StorageLive(_3); // scope 1 at $DIR/branch.rs:15:16: 15:22 + _3 = const cond() -> bb2; // scope 1 at $DIR/branch.rs:15:16: 15:22 + // ty::Const + // + ty: fn() -> bool {cond} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/branch.rs:15:16: 15:20 + // + literal: Const { ty: fn() -> bool {cond}, val: Value(Scalar()) } + } + + bb2: { + switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 1 at $DIR/branch.rs:15:13: 20:6 + } + + bb3: { + StorageLive(_4); // scope 1 at $DIR/branch.rs:18:9: 18:14 + _4 = const val() -> bb5; // scope 1 at $DIR/branch.rs:18:9: 18:14 + // ty::Const + // + ty: fn() -> i32 {val} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/branch.rs:18:9: 18:12 + // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar()) } + } + + bb4: { +- _2 = _1; // scope 1 at $DIR/branch.rs:16:9: 16:10 ++ nop; // scope 1 at $DIR/branch.rs:16:9: 16:10 + goto -> bb6; // scope 1 at $DIR/branch.rs:15:13: 20:6 + } + + bb5: { + StorageDead(_4); // scope 1 at $DIR/branch.rs:18:14: 18:15 +- _2 = _1; // scope 1 at $DIR/branch.rs:19:9: 19:10 ++ nop; // scope 1 at $DIR/branch.rs:19:9: 19:10 + goto -> bb6; // scope 1 at $DIR/branch.rs:15:13: 20:6 + } + + bb6: { + StorageDead(_3); // scope 1 at $DIR/branch.rs:20:6: 20:7 + _0 = const (); // scope 0 at $DIR/branch.rs:12:11: 21:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/branch.rs:12:11: 21:2 + // + literal: Const { ty: (), val: Value(Scalar()) } +- StorageDead(_2); // scope 1 at $DIR/branch.rs:21:1: 21:2 +- StorageDead(_1); // scope 0 at $DIR/branch.rs:21:1: 21:2 ++ nop; // scope 1 at $DIR/branch.rs:21:1: 21:2 ++ nop; // scope 0 at $DIR/branch.rs:21:1: 21:2 + return; // scope 0 at $DIR/branch.rs:21:2: 21:2 + } + } + diff --git a/src/test/mir-opt/dest-prop/cycle.rs b/src/test/mir-opt/dest-prop/cycle.rs new file mode 100644 index 0000000000000..d55d527bc65f6 --- /dev/null +++ b/src/test/mir-opt/dest-prop/cycle.rs @@ -0,0 +1,15 @@ +//! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code. + +fn val() -> i32 { + 1 +} + +// EMIT_MIR rustc.main.DestinationPropagation.diff +fn main() { + let mut x = val(); + let y = x; + let z = y; + x = z; + + drop(x); +} diff --git a/src/test/mir-opt/dest-prop/cycle/rustc.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/cycle/rustc.main.DestinationPropagation.diff new file mode 100644 index 0000000000000..5189b665acff1 --- /dev/null +++ b/src/test/mir-opt/dest-prop/cycle/rustc.main.DestinationPropagation.diff @@ -0,0 +1,91 @@ +- // MIR for `main` before DestinationPropagation ++ // MIR for `main` after DestinationPropagation + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/cycle.rs:8:11: 8:11 + let mut _1: i32; // in scope 0 at $DIR/cycle.rs:9:9: 9:14 + let mut _4: i32; // in scope 0 at $DIR/cycle.rs:12:9: 12:10 + let _5: (); // in scope 0 at $DIR/cycle.rs:14:5: 14:12 + let mut _6: i32; // in scope 0 at $DIR/cycle.rs:14:10: 14:11 + scope 1 { +- debug x => _1; // in scope 1 at $DIR/cycle.rs:9:9: 9:14 ++ debug x => _4; // in scope 1 at $DIR/cycle.rs:9:9: 9:14 + let _2: i32; // in scope 1 at $DIR/cycle.rs:10:9: 10:10 + scope 2 { +- debug y => _2; // in scope 2 at $DIR/cycle.rs:10:9: 10:10 ++ debug y => _4; // in scope 2 at $DIR/cycle.rs:10:9: 10:10 + let _3: i32; // in scope 2 at $DIR/cycle.rs:11:9: 11:10 + scope 3 { +- debug z => _3; // in scope 3 at $DIR/cycle.rs:11:9: 11:10 ++ debug z => _4; // in scope 3 at $DIR/cycle.rs:11:9: 11:10 + scope 4 { + debug _x => _6; // in scope 4 at $SRC_DIR/libcore/mem/mod.rs:LL:COL + } + } + } + } + + bb0: { +- StorageLive(_1); // scope 0 at $DIR/cycle.rs:9:9: 9:14 +- _1 = const val() -> bb1; // scope 0 at $DIR/cycle.rs:9:17: 9:22 ++ nop; // scope 0 at $DIR/cycle.rs:9:9: 9:14 ++ _4 = const val() -> bb1; // scope 0 at $DIR/cycle.rs:9:17: 9:22 + // ty::Const + // + ty: fn() -> i32 {val} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/cycle.rs:9:17: 9:20 + // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar()) } + } + + bb1: { +- StorageLive(_2); // scope 1 at $DIR/cycle.rs:10:9: 10:10 +- _2 = _1; // scope 1 at $DIR/cycle.rs:10:13: 10:14 +- StorageLive(_3); // scope 2 at $DIR/cycle.rs:11:9: 11:10 +- _3 = _2; // scope 2 at $DIR/cycle.rs:11:13: 11:14 +- StorageLive(_4); // scope 3 at $DIR/cycle.rs:12:9: 12:10 +- _4 = _3; // scope 3 at $DIR/cycle.rs:12:9: 12:10 +- _1 = move _4; // scope 3 at $DIR/cycle.rs:12:5: 12:10 +- StorageDead(_4); // scope 3 at $DIR/cycle.rs:12:9: 12:10 ++ nop; // scope 1 at $DIR/cycle.rs:10:9: 10:10 ++ nop; // scope 1 at $DIR/cycle.rs:10:13: 10:14 ++ nop; // scope 2 at $DIR/cycle.rs:11:9: 11:10 ++ nop; // scope 2 at $DIR/cycle.rs:11:13: 11:14 ++ nop; // scope 3 at $DIR/cycle.rs:12:9: 12:10 ++ nop; // scope 3 at $DIR/cycle.rs:12:9: 12:10 ++ nop; // scope 3 at $DIR/cycle.rs:12:5: 12:10 ++ nop; // scope 3 at $DIR/cycle.rs:12:9: 12:10 + StorageLive(_5); // scope 3 at $DIR/cycle.rs:14:5: 14:12 + StorageLive(_6); // scope 3 at $DIR/cycle.rs:14:10: 14:11 +- _6 = _1; // scope 3 at $DIR/cycle.rs:14:10: 14:11 ++ _6 = _4; // scope 3 at $DIR/cycle.rs:14:10: 14:11 + _5 = const (); // scope 4 at $SRC_DIR/libcore/mem/mod.rs:LL:COL + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $SRC_DIR/libcore/mem/mod.rs:LL:COL + // + literal: Const { ty: (), val: Value(Scalar()) } + drop(_6) -> bb2; // scope 4 at $SRC_DIR/libcore/mem/mod.rs:LL:COL + } + + bb2: { + StorageDead(_6); // scope 3 at $DIR/cycle.rs:14:11: 14:12 + StorageDead(_5); // scope 3 at $DIR/cycle.rs:14:12: 14:13 + _0 = const (); // scope 0 at $DIR/cycle.rs:8:11: 15:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/cycle.rs:8:11: 15:2 + // + literal: Const { ty: (), val: Value(Scalar()) } +- StorageDead(_3); // scope 2 at $DIR/cycle.rs:15:1: 15:2 +- StorageDead(_2); // scope 1 at $DIR/cycle.rs:15:1: 15:2 +- StorageDead(_1); // scope 0 at $DIR/cycle.rs:15:1: 15:2 ++ nop; // scope 2 at $DIR/cycle.rs:15:1: 15:2 ++ nop; // scope 1 at $DIR/cycle.rs:15:1: 15:2 ++ nop; // scope 0 at $DIR/cycle.rs:15:1: 15:2 + return; // scope 0 at $DIR/cycle.rs:15:2: 15:2 + } + } + diff --git a/src/test/mir-opt/dest-prop/simple.rs b/src/test/mir-opt/dest-prop/simple.rs new file mode 100644 index 0000000000000..add821eafe0b0 --- /dev/null +++ b/src/test/mir-opt/dest-prop/simple.rs @@ -0,0 +1,14 @@ +//! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too. + +// EMIT_MIR rustc.nrvo.DestinationPropagation.diff +fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { + let mut buf = [0; 1024]; + init(&mut buf); + buf +} + +fn main() { + let _ = nrvo(|buf| { + buf[4] = 4; + }); +} diff --git a/src/test/mir-opt/dest-prop/simple/rustc.nrvo.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/simple/rustc.nrvo.DestinationPropagation.diff new file mode 100644 index 0000000000000..d59e1f3c0c938 --- /dev/null +++ b/src/test/mir-opt/dest-prop/simple/rustc.nrvo.DestinationPropagation.diff @@ -0,0 +1,56 @@ +- // MIR for `nrvo` before DestinationPropagation ++ // MIR for `nrvo` after DestinationPropagation + + fn nrvo(_1: for<'r> fn(&'r mut [u8; 1024])) -> [u8; 1024] { + debug init => _1; // in scope 0 at $DIR/simple.rs:4:9: 4:13 + let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/simple.rs:4:39: 4:49 + let mut _2: [u8; 1024]; // in scope 0 at $DIR/simple.rs:5:9: 5:16 + let _3: (); // in scope 0 at $DIR/simple.rs:6:5: 6:19 + let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/simple.rs:6:5: 6:9 + let mut _5: &mut [u8; 1024]; // in scope 0 at $DIR/simple.rs:6:10: 6:18 + let mut _6: &mut [u8; 1024]; // in scope 0 at $DIR/simple.rs:6:10: 6:18 + scope 1 { +- debug buf => _2; // in scope 1 at $DIR/simple.rs:5:9: 5:16 ++ debug buf => _0; // in scope 1 at $DIR/simple.rs:5:9: 5:16 + } + + bb0: { +- StorageLive(_2); // scope 0 at $DIR/simple.rs:5:9: 5:16 +- _2 = [const 0u8; 1024]; // scope 0 at $DIR/simple.rs:5:19: 5:28 ++ nop; // scope 0 at $DIR/simple.rs:5:9: 5:16 ++ _0 = [const 0u8; 1024]; // scope 0 at $DIR/simple.rs:5:19: 5:28 + // ty::Const + // + ty: u8 + // + val: Value(Scalar(0x00)) + // mir::Constant + // + span: $DIR/simple.rs:5:20: 5:21 + // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } + StorageLive(_3); // scope 1 at $DIR/simple.rs:6:5: 6:19 + StorageLive(_4); // scope 1 at $DIR/simple.rs:6:5: 6:9 + _4 = _1; // scope 1 at $DIR/simple.rs:6:5: 6:9 +- StorageLive(_5); // scope 1 at $DIR/simple.rs:6:10: 6:18 +- StorageLive(_6); // scope 1 at $DIR/simple.rs:6:10: 6:18 +- _6 = &mut _2; // scope 1 at $DIR/simple.rs:6:10: 6:18 +- _5 = move _6; // scope 1 at $DIR/simple.rs:6:10: 6:18 ++ nop; // scope 1 at $DIR/simple.rs:6:10: 6:18 ++ nop; // scope 1 at $DIR/simple.rs:6:10: 6:18 ++ _5 = &mut _0; // scope 1 at $DIR/simple.rs:6:10: 6:18 ++ nop; // scope 1 at $DIR/simple.rs:6:10: 6:18 + _3 = move _4(move _5) -> bb1; // scope 1 at $DIR/simple.rs:6:5: 6:19 + } + + bb1: { +- StorageDead(_5); // scope 1 at $DIR/simple.rs:6:18: 6:19 ++ nop; // scope 1 at $DIR/simple.rs:6:18: 6:19 + StorageDead(_4); // scope 1 at $DIR/simple.rs:6:18: 6:19 +- StorageDead(_6); // scope 1 at $DIR/simple.rs:6:19: 6:20 ++ nop; // scope 1 at $DIR/simple.rs:6:19: 6:20 + StorageDead(_3); // scope 1 at $DIR/simple.rs:6:19: 6:20 +- _0 = _2; // scope 1 at $DIR/simple.rs:7:5: 7:8 +- StorageDead(_2); // scope 0 at $DIR/simple.rs:8:1: 8:2 ++ nop; // scope 1 at $DIR/simple.rs:7:5: 7:8 ++ nop; // scope 0 at $DIR/simple.rs:8:1: 8:2 + return; // scope 0 at $DIR/simple.rs:8:2: 8:2 + } + } + diff --git a/src/test/mir-opt/dest-prop/union.rs b/src/test/mir-opt/dest-prop/union.rs new file mode 100644 index 0000000000000..ea8364124043e --- /dev/null +++ b/src/test/mir-opt/dest-prop/union.rs @@ -0,0 +1,16 @@ +//! Tests that projections through unions cancel `DestinationPropagation`. + +fn val() -> u32 { + 1 +} + +// EMIT_MIR rustc.main.DestinationPropagation.diff +fn main() { + union Un { + us: u32, + } + + let un = Un { us: val() }; + + drop(unsafe { un.us }); +} diff --git a/src/test/mir-opt/dest-prop/union/rustc.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/union/rustc.main.DestinationPropagation.diff new file mode 100644 index 0000000000000..f6ebb6cb9403d --- /dev/null +++ b/src/test/mir-opt/dest-prop/union/rustc.main.DestinationPropagation.diff @@ -0,0 +1,61 @@ +- // MIR for `main` before DestinationPropagation ++ // MIR for `main` after DestinationPropagation + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/union.rs:8:11: 8:11 + let _1: main::Un; // in scope 0 at $DIR/union.rs:13:9: 13:11 + let mut _2: u32; // in scope 0 at $DIR/union.rs:13:23: 13:28 + let _3: (); // in scope 0 at $DIR/union.rs:15:5: 15:27 + let mut _4: u32; // in scope 0 at $DIR/union.rs:15:10: 15:26 + scope 1 { + debug un => _1; // in scope 1 at $DIR/union.rs:13:9: 13:11 + scope 2 { + } + scope 3 { + debug _x => _4; // in scope 3 at $SRC_DIR/libcore/mem/mod.rs:LL:COL + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/union.rs:13:9: 13:11 + StorageLive(_2); // scope 0 at $DIR/union.rs:13:23: 13:28 + _2 = const val() -> bb1; // scope 0 at $DIR/union.rs:13:23: 13:28 + // ty::Const + // + ty: fn() -> u32 {val} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/union.rs:13:23: 13:26 + // + literal: Const { ty: fn() -> u32 {val}, val: Value(Scalar()) } + } + + bb1: { + (_1.0: u32) = move _2; // scope 0 at $DIR/union.rs:13:14: 13:30 + StorageDead(_2); // scope 0 at $DIR/union.rs:13:29: 13:30 + StorageLive(_3); // scope 1 at $DIR/union.rs:15:5: 15:27 + StorageLive(_4); // scope 1 at $DIR/union.rs:15:10: 15:26 + _4 = (_1.0: u32); // scope 2 at $DIR/union.rs:15:19: 15:24 + _3 = const (); // scope 3 at $SRC_DIR/libcore/mem/mod.rs:LL:COL + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $SRC_DIR/libcore/mem/mod.rs:LL:COL + // + literal: Const { ty: (), val: Value(Scalar()) } + drop(_4) -> bb2; // scope 3 at $SRC_DIR/libcore/mem/mod.rs:LL:COL + } + + bb2: { + StorageDead(_4); // scope 1 at $DIR/union.rs:15:26: 15:27 + StorageDead(_3); // scope 1 at $DIR/union.rs:15:27: 15:28 + _0 = const (); // scope 0 at $DIR/union.rs:8:11: 16:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/union.rs:8:11: 16:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_1); // scope 0 at $DIR/union.rs:16:1: 16:2 + return; // scope 0 at $DIR/union.rs:16:2: 16:2 + } + } +