Skip to content

Commit 6938b4b

Browse files
authored
Rollup merge of rust-lang#127105 - scottmcm:issue-127089, r=cjgillot
Only update `Eq` operands in GVN if it can update both sides Otherwise the types might not match Fixes rust-lang#127089 r? mir-opt
2 parents 04a3969 + f694211 commit 6938b4b

6 files changed

+132
-5
lines changed

compiler/rustc_mir_transform/src/gvn.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1074,11 +1074,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10741074
{
10751075
lhs = *lhs_value;
10761076
rhs = *rhs_value;
1077-
if let Some(op) = self.try_as_operand(lhs, location) {
1078-
*lhs_operand = op;
1079-
}
1080-
if let Some(op) = self.try_as_operand(rhs, location) {
1081-
*rhs_operand = op;
1077+
if let Some(lhs_op) = self.try_as_operand(lhs, location)
1078+
&& let Some(rhs_op) = self.try_as_operand(rhs, location)
1079+
{
1080+
*lhs_operand = lhs_op;
1081+
*rhs_operand = rhs_op;
10821082
}
10831083
}
10841084

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
- // MIR for `remove_casts_must_change_both_sides` before GVN
2+
+ // MIR for `remove_casts_must_change_both_sides` after GVN
3+
4+
fn remove_casts_must_change_both_sides(_1: &*mut u8, _2: *mut u8) -> bool {
5+
let mut _0: bool;
6+
let mut _3: *const u8;
7+
let mut _4: *const u8;
8+
9+
bb0: {
10+
_3 = (*_1) as *const u8 (PtrToPtr);
11+
_4 = _2 as *const u8 (PtrToPtr);
12+
_0 = Eq(_3, _4);
13+
return;
14+
}
15+
}
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
- // MIR for `remove_casts_must_change_both_sides` before GVN
2+
+ // MIR for `remove_casts_must_change_both_sides` after GVN
3+
4+
fn remove_casts_must_change_both_sides(_1: &*mut u8, _2: *mut u8) -> bool {
5+
let mut _0: bool;
6+
let mut _3: *const u8;
7+
let mut _4: *const u8;
8+
9+
bb0: {
10+
_3 = (*_1) as *const u8 (PtrToPtr);
11+
_4 = _2 as *const u8 (PtrToPtr);
12+
_0 = Eq(_3, _4);
13+
return;
14+
}
15+
}
16+

tests/mir-opt/gvn.rs

+20
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,25 @@ unsafe fn cast_pointer_then_transmute(thin: *mut u32, fat: *mut [u8]) {
926926
let fat_addr: usize = std::intrinsics::transmute(fat as *const ());
927927
}
928928

929+
#[custom_mir(dialect = "analysis")]
930+
fn remove_casts_must_change_both_sides(mut_a: &*mut u8, mut_b: *mut u8) -> bool {
931+
// CHECK-LABEL: fn remove_casts_must_change_both_sides(
932+
mir! {
933+
// We'd like to remove these casts, but we can't change *both* of them
934+
// to be locals, so make sure we don't change one without the other, as
935+
// that would be a type error.
936+
{
937+
// CHECK: [[A:_.+]] = (*_1) as *const u8 (PtrToPtr);
938+
let a = *mut_a as *const u8;
939+
// CHECK: [[B:_.+]] = _2 as *const u8 (PtrToPtr);
940+
let b = mut_b as *const u8;
941+
// CHECK: _0 = Eq([[A]], [[B]]);
942+
RET = a == b;
943+
Return()
944+
}
945+
}
946+
}
947+
929948
fn main() {
930949
subexpression_elimination(2, 4, 5);
931950
wrap_unwrap(5);
@@ -995,3 +1014,4 @@ fn identity<T>(x: T) -> T {
9951014
// EMIT_MIR gvn.generic_cast_metadata.GVN.diff
9961015
// EMIT_MIR gvn.cast_pointer_eq.GVN.diff
9971016
// EMIT_MIR gvn.cast_pointer_then_transmute.GVN.diff
1017+
// EMIT_MIR gvn.remove_casts_must_change_both_sides.GVN.diff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
- // MIR for `main` before GVN
2+
+ // MIR for `main` after GVN
3+
4+
fn main() -> () {
5+
let mut _0: ();
6+
let _1: bool;
7+
let mut _2: *mut u8;
8+
scope 1 (inlined dangling_mut::<u8>) {
9+
let mut _3: usize;
10+
scope 2 (inlined align_of::<u8>) {
11+
}
12+
scope 3 (inlined without_provenance_mut::<u8>) {
13+
}
14+
}
15+
scope 4 (inlined Foo::<u8>::cmp_ptr) {
16+
let mut _4: *const u8;
17+
let mut _5: *mut u8;
18+
let mut _6: *const u8;
19+
scope 5 (inlined std::ptr::eq::<u8>) {
20+
}
21+
}
22+
23+
bb0: {
24+
StorageLive(_1);
25+
StorageLive(_2);
26+
StorageLive(_3);
27+
- _3 = AlignOf(u8);
28+
- _2 = _3 as *mut u8 (Transmute);
29+
+ _3 = const 1_usize;
30+
+ _2 = const {0x1 as *mut u8};
31+
StorageDead(_3);
32+
StorageLive(_4);
33+
StorageLive(_5);
34+
- _5 = _2;
35+
- _4 = _2 as *const u8 (PtrToPtr);
36+
+ _5 = const {0x1 as *mut u8};
37+
+ _4 = const {0x1 as *const u8};
38+
StorageDead(_5);
39+
StorageLive(_6);
40+
- _6 = const Foo::<u8>::SENTINEL as *const u8 (PtrToPtr);
41+
- _1 = Eq(_4, _6);
42+
+ _6 = const {0x1 as *const u8};
43+
+ _1 = const true;
44+
StorageDead(_6);
45+
StorageDead(_4);
46+
StorageDead(_2);
47+
StorageDead(_1);
48+
_0 = const ();
49+
return;
50+
}
51+
}
52+
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// skip-filecheck
2+
//@ test-mir-pass: GVN
3+
//@ only-64bit
4+
//@ compile-flags: -Z mir-enable-passes=+Inline
5+
6+
// Regression for <https://github.com/rust-lang/rust/issues/127089>
7+
8+
#![feature(strict_provenance)]
9+
10+
struct Foo<T>(std::marker::PhantomData<T>);
11+
12+
impl<T> Foo<T> {
13+
const SENTINEL: *mut T = std::ptr::dangling_mut();
14+
15+
fn cmp_ptr(a: *mut T) -> bool {
16+
std::ptr::eq(a, Self::SENTINEL)
17+
}
18+
}
19+
20+
// EMIT_MIR gvn_ptr_eq_with_constant.main.GVN.diff
21+
pub fn main() {
22+
Foo::<u8>::cmp_ptr(std::ptr::dangling_mut());
23+
}

0 commit comments

Comments
 (0)