Skip to content

Commit 5915309

Browse files
authored
Rollup merge of #107971 - saethlin:mir-opt-ub, r=cjgillot
Clearly document intentional UB in mir-opt tests All of the changed mir-opt test input files did not pass Miri. Now they do. r? `@cjgillot` because there's a CopyProp test in here that I do not fully understand
2 parents 7efb884 + 614df3f commit 5915309

File tree

5 files changed

+49
-27
lines changed

5 files changed

+49
-27
lines changed

tests/mir-opt/copy-prop/mutate_through_pointer.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
// This attempts to mutate `a` via a pointer derived from `addr_of!(a)`. That is UB
2+
// according to Miri. However, the decision to make this UB - and to allow
3+
// rustc to rely on that fact for the purpose of optimizations - has not been
4+
// finalized.
5+
//
6+
// As such, we include this test to ensure that copy prop does not rely on that
7+
// fact. Specifically, if `addr_of!(a)` could not be used to modify a, it would
8+
// be correct for CopyProp to replace all occurrences of `a` with `c` - but that
9+
// would cause `f(true)` to output `false` instead of `true`.
10+
111
#![feature(custom_mir, core_intrinsics)]
212
#![allow(unused_assignments)]
313
extern crate core;

tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
_5 = _3; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
3333
_4 = ptr::mut_ptr::<impl *mut u8>::add(move _5, const 1_usize) -> bb1; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
3434
// mir::Constant
35-
// + span: $DIR/sibling_ptr.rs:8:12: 8:15
35+
// + span: $DIR/sibling_ptr.rs:15:12: 15:15
3636
// + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::<impl *mut u8>::add}, val: Value(<ZST>) }
3737
}
3838

tests/mir-opt/dataflow-const-prop/sibling_ptr.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
// This attempts to modify `x.1` via a pointer derived from `addr_of_mut!(x.0)`.
2+
// According to Miri, that is UB. However, T-opsem has not finalized that
3+
// decision and as such we cannot rely on it in optimizations. Consequently,
4+
// DataflowConstProp must treat the `addr_of_mut!(x.0)` as potentially being
5+
// used to modify `x.1` - if it did not, then it might incorrectly assume that it
6+
// can infer the value of `x.1` at the end of this function.
7+
18
// unit-test: DataflowConstProp
29

310
// EMIT_MIR sibling_ptr.main.DataflowConstProp.diff
@@ -7,5 +14,5 @@ fn main() {
714
let p = std::ptr::addr_of_mut!(x.0);
815
*p.add(1) = 1;
916
}
10-
let x1 = x.1; // should not be propagated
17+
let x1 = x.1; // should not be propagated
1118
}

tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff

+24-24
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,42 @@
33

44
fn escaping() -> () {
55
let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19
6-
let _1: (); // in scope 0 at $DIR/sroa.rs:+2:5: +2:42
7-
let mut _2: *const u32; // in scope 0 at $DIR/sroa.rs:+2:7: +2:41
8-
let _3: &u32; // in scope 0 at $DIR/sroa.rs:+2:7: +2:41
9-
let _4: Escaping; // in scope 0 at $DIR/sroa.rs:+2:8: +2:39
10-
let mut _5: u32; // in scope 0 at $DIR/sroa.rs:+2:34: +2:37
6+
let _1: (); // in scope 0 at $DIR/sroa.rs:+1:5: +1:42
7+
let mut _2: *const u32; // in scope 0 at $DIR/sroa.rs:+1:7: +1:41
8+
let _3: &u32; // in scope 0 at $DIR/sroa.rs:+1:7: +1:41
9+
let _4: Escaping; // in scope 0 at $DIR/sroa.rs:+1:8: +1:39
10+
let mut _5: u32; // in scope 0 at $DIR/sroa.rs:+1:34: +1:37
1111

1212
bb0: {
13-
StorageLive(_1); // scope 0 at $DIR/sroa.rs:+2:5: +2:42
14-
StorageLive(_2); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
15-
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
16-
StorageLive(_4); // scope 0 at $DIR/sroa.rs:+2:8: +2:39
17-
StorageLive(_5); // scope 0 at $DIR/sroa.rs:+2:34: +2:37
18-
_5 = g() -> bb1; // scope 0 at $DIR/sroa.rs:+2:34: +2:37
13+
StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:5: +1:42
14+
StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
15+
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
16+
StorageLive(_4); // scope 0 at $DIR/sroa.rs:+1:8: +1:39
17+
StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:34: +1:37
18+
_5 = g() -> bb1; // scope 0 at $DIR/sroa.rs:+1:34: +1:37
1919
// mir::Constant
20-
// + span: $DIR/sroa.rs:73:34: 73:35
20+
// + span: $DIR/sroa.rs:78:34: 78:35
2121
// + literal: Const { ty: fn() -> u32 {g}, val: Value(<ZST>) }
2222
}
2323

2424
bb1: {
25-
_4 = Escaping { a: const 1_u32, b: const 2_u32, c: move _5 }; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
26-
StorageDead(_5); // scope 0 at $DIR/sroa.rs:+2:38: +2:39
27-
_3 = &(_4.0: u32); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
28-
_2 = &raw const (*_3); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
29-
_1 = f(move _2) -> bb2; // scope 0 at $DIR/sroa.rs:+2:5: +2:42
25+
_4 = Escaping { a: const 1_u32, b: const 2_u32, c: move _5 }; // scope 0 at $DIR/sroa.rs:+1:8: +1:39
26+
StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:38: +1:39
27+
_3 = &(_4.0: u32); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
28+
_2 = &raw const (*_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
29+
_1 = f(move _2) -> bb2; // scope 0 at $DIR/sroa.rs:+1:5: +1:42
3030
// mir::Constant
31-
// + span: $DIR/sroa.rs:73:5: 73:6
31+
// + span: $DIR/sroa.rs:78:5: 78:6
3232
// + literal: Const { ty: fn(*const u32) {f}, val: Value(<ZST>) }
3333
}
3434

3535
bb2: {
36-
StorageDead(_2); // scope 0 at $DIR/sroa.rs:+2:41: +2:42
37-
StorageDead(_4); // scope 0 at $DIR/sroa.rs:+2:42: +2:43
38-
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+2:42: +2:43
39-
StorageDead(_1); // scope 0 at $DIR/sroa.rs:+2:42: +2:43
40-
_0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +3:2
41-
return; // scope 0 at $DIR/sroa.rs:+3:2: +3:2
36+
StorageDead(_2); // scope 0 at $DIR/sroa.rs:+1:41: +1:42
37+
StorageDead(_4); // scope 0 at $DIR/sroa.rs:+1:42: +1:43
38+
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+1:42: +1:43
39+
StorageDead(_1); // scope 0 at $DIR/sroa.rs:+1:42: +1:43
40+
_0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +2:2
41+
return; // scope 0 at $DIR/sroa.rs:+2:2: +2:2
4242
}
4343
}
4444

tests/mir-opt/sroa.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,13 @@ fn f(a: *const u32) {
6868
println!("{}", unsafe { *a.add(2) });
6969
}
7070

71+
// `f` uses the `&e.a` to access `e.c`. This is UB according to Miri today; however,
72+
// T-opsem has not finalized that decision and as such rustc should not rely on
73+
// it. If SROA were to rely on it, it would be (almost) correct to turn `e` into
74+
// three distinct locals - one for each field - and pass a reference to only one
75+
// of them to `f`. However, this would lead to a miscompilation because `b` and `c`
76+
// might no longer appear right after `a` in memory.
7177
pub fn escaping() {
72-
// Verify this struct is not flattened.
7378
f(&Escaping { a: 1, b: 2, c: g() }.a);
7479
}
7580

0 commit comments

Comments
 (0)