Skip to content

Commit 89563b0

Browse files
committed
Added test for dead-live edge case
1 parent adae8c8 commit 89563b0

File tree

5 files changed

+121
-1
lines changed

5 files changed

+121
-1
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
164164
// Conservatively remove all storage statements for reused locals.
165165
state.reused_locals.clone()
166166
};
167-
167+
168168
debug!(?storage_to_remove);
169169

170170
StorageRemover { tcx, reused_locals: state.reused_locals, storage_to_remove }
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
- // MIR for `repeat_local` before GVN
2+
+ // MIR for `repeat_local` after GVN
3+
4+
fn repeat_local(_1: usize, _2: usize, _3: i32) -> i32 {
5+
let mut _0: i32;
6+
let mut _4: [i32; 5];
7+
let mut _5: &i32;
8+
9+
bb0: {
10+
_4 = [copy _3; 5];
11+
_5 = &_4[_1];
12+
- _0 = copy (*_5);
13+
+ _0 = copy _3;
14+
return;
15+
}
16+
}
17+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
- // MIR for `repeat_local_dead` before GVN
2+
+ // MIR for `repeat_local_dead` after GVN
3+
4+
fn repeat_local_dead(_1: usize, _2: usize, _3: i32) -> i32 {
5+
let mut _0: i32;
6+
let mut _4: [i32; 5];
7+
let mut _5: &i32;
8+
9+
bb0: {
10+
_4 = [copy _3; 5];
11+
_5 = &_4[_1];
12+
- StorageDead(_3);
13+
- _0 = copy (*_5);
14+
+ nop;
15+
+ _0 = copy _3;
16+
return;
17+
}
18+
}
19+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
- // MIR for `repeat_local_dead_live` before GVN
2+
+ // MIR for `repeat_local_dead_live` after GVN
3+
4+
fn repeat_local_dead_live(_1: usize, _2: usize, _3: i32) -> i32 {
5+
let mut _0: i32;
6+
let mut _4: [i32; 5];
7+
let mut _5: &i32;
8+
9+
bb0: {
10+
_4 = [copy _3; 5];
11+
_5 = &_4[_1];
12+
StorageDead(_3);
13+
StorageLive(_3);
14+
- _0 = copy (*_5);
15+
+ _0 = copy _3;
16+
return;
17+
}
18+
}
19+

tests/mir-opt/gvn_storage_twice.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// skip-filecheck
2+
//@ test-mir-pass: GVN
3+
//@ compile-flags: -Zlint-mir=false
4+
5+
#![feature(custom_mir, core_intrinsics)]
6+
7+
use std::intrinsics::mir::*;
8+
9+
// EMIT_MIR gvn_storage_twice.repeat_local.GVN.diff
10+
// EMIT_MIR gvn_storage_twice.repeat_local_dead.GVN.diff
11+
// EMIT_MIR gvn_storage_twice.repeat_local_dead_live.GVN.diff
12+
13+
// Check that we remove the storage statements if the local
14+
// doesn't have valid storage when it is used.
15+
//
16+
// Based on `gvn_repeat.rs::repeat_local`, were GVN should replace
17+
// `let RET = *_5;` with `let RET = _3;`.
18+
19+
#[custom_mir(dialect = "runtime")]
20+
pub fn repeat_local(_1: usize, _2: usize, _3: i32) -> i32 {
21+
mir! {
22+
{
23+
let _4 = [_3; 5];
24+
let _5 = &_4[_1];
25+
RET = *_5;
26+
Return()
27+
}
28+
}
29+
}
30+
31+
// Since _3 is dead when we access _5, GVN should remove the storage statements.
32+
33+
#[custom_mir(dialect = "runtime")]
34+
pub fn repeat_local_dead(_1: usize, _2: usize, _3: i32) -> i32 {
35+
mir! {
36+
{
37+
let _4 = [_3; 5];
38+
let _5 = &_4[_1];
39+
StorageDead(_3);
40+
RET = *_5;
41+
Return()
42+
}
43+
}
44+
}
45+
46+
// Since _3 is uninitizaled when we access _5, GVN should _not_ optimze the code.
47+
48+
#[custom_mir(dialect = "runtime")]
49+
pub fn repeat_local_dead_live(_1: usize, _2: usize, _3: i32) -> i32 {
50+
mir! {
51+
{
52+
let _4 = [_3; 5];
53+
let _5 = &_4[_1];
54+
StorageDead(_3);
55+
StorageLive(_3);
56+
RET = *_5;
57+
Return()
58+
}
59+
}
60+
}
61+
62+
#[inline(never)]
63+
fn opaque<T>(a: T) -> T {
64+
a
65+
}

0 commit comments

Comments
 (0)