Rollup merge of #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 #127089 r? mir-opt
This commit is contained in:
commit
6938b4b640
6 changed files with 132 additions and 5 deletions
|
@ -1074,11 +1074,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
{
|
||||
lhs = *lhs_value;
|
||||
rhs = *rhs_value;
|
||||
if let Some(op) = self.try_as_operand(lhs, location) {
|
||||
*lhs_operand = op;
|
||||
}
|
||||
if let Some(op) = self.try_as_operand(rhs, location) {
|
||||
*rhs_operand = op;
|
||||
if let Some(lhs_op) = self.try_as_operand(lhs, location)
|
||||
&& let Some(rhs_op) = self.try_as_operand(rhs, location)
|
||||
{
|
||||
*lhs_operand = lhs_op;
|
||||
*rhs_operand = rhs_op;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
- // MIR for `remove_casts_must_change_both_sides` before GVN
|
||||
+ // MIR for `remove_casts_must_change_both_sides` after GVN
|
||||
|
||||
fn remove_casts_must_change_both_sides(_1: &*mut u8, _2: *mut u8) -> bool {
|
||||
let mut _0: bool;
|
||||
let mut _3: *const u8;
|
||||
let mut _4: *const u8;
|
||||
|
||||
bb0: {
|
||||
_3 = (*_1) as *const u8 (PtrToPtr);
|
||||
_4 = _2 as *const u8 (PtrToPtr);
|
||||
_0 = Eq(_3, _4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
- // MIR for `remove_casts_must_change_both_sides` before GVN
|
||||
+ // MIR for `remove_casts_must_change_both_sides` after GVN
|
||||
|
||||
fn remove_casts_must_change_both_sides(_1: &*mut u8, _2: *mut u8) -> bool {
|
||||
let mut _0: bool;
|
||||
let mut _3: *const u8;
|
||||
let mut _4: *const u8;
|
||||
|
||||
bb0: {
|
||||
_3 = (*_1) as *const u8 (PtrToPtr);
|
||||
_4 = _2 as *const u8 (PtrToPtr);
|
||||
_0 = Eq(_3, _4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -926,6 +926,25 @@ unsafe fn cast_pointer_then_transmute(thin: *mut u32, fat: *mut [u8]) {
|
|||
let fat_addr: usize = std::intrinsics::transmute(fat as *const ());
|
||||
}
|
||||
|
||||
#[custom_mir(dialect = "analysis")]
|
||||
fn remove_casts_must_change_both_sides(mut_a: &*mut u8, mut_b: *mut u8) -> bool {
|
||||
// CHECK-LABEL: fn remove_casts_must_change_both_sides(
|
||||
mir! {
|
||||
// We'd like to remove these casts, but we can't change *both* of them
|
||||
// to be locals, so make sure we don't change one without the other, as
|
||||
// that would be a type error.
|
||||
{
|
||||
// CHECK: [[A:_.+]] = (*_1) as *const u8 (PtrToPtr);
|
||||
let a = *mut_a as *const u8;
|
||||
// CHECK: [[B:_.+]] = _2 as *const u8 (PtrToPtr);
|
||||
let b = mut_b as *const u8;
|
||||
// CHECK: _0 = Eq([[A]], [[B]]);
|
||||
RET = a == b;
|
||||
Return()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
subexpression_elimination(2, 4, 5);
|
||||
wrap_unwrap(5);
|
||||
|
@ -995,3 +1014,4 @@ fn identity<T>(x: T) -> T {
|
|||
// EMIT_MIR gvn.generic_cast_metadata.GVN.diff
|
||||
// EMIT_MIR gvn.cast_pointer_eq.GVN.diff
|
||||
// EMIT_MIR gvn.cast_pointer_then_transmute.GVN.diff
|
||||
// EMIT_MIR gvn.remove_casts_must_change_both_sides.GVN.diff
|
||||
|
|
52
tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff
Normal file
52
tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff
Normal file
|
@ -0,0 +1,52 @@
|
|||
- // MIR for `main` before GVN
|
||||
+ // MIR for `main` after GVN
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: ();
|
||||
let _1: bool;
|
||||
let mut _2: *mut u8;
|
||||
scope 1 (inlined dangling_mut::<u8>) {
|
||||
let mut _3: usize;
|
||||
scope 2 (inlined align_of::<u8>) {
|
||||
}
|
||||
scope 3 (inlined without_provenance_mut::<u8>) {
|
||||
}
|
||||
}
|
||||
scope 4 (inlined Foo::<u8>::cmp_ptr) {
|
||||
let mut _4: *const u8;
|
||||
let mut _5: *mut u8;
|
||||
let mut _6: *const u8;
|
||||
scope 5 (inlined std::ptr::eq::<u8>) {
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
- _3 = AlignOf(u8);
|
||||
- _2 = _3 as *mut u8 (Transmute);
|
||||
+ _3 = const 1_usize;
|
||||
+ _2 = const {0x1 as *mut u8};
|
||||
StorageDead(_3);
|
||||
StorageLive(_4);
|
||||
StorageLive(_5);
|
||||
- _5 = _2;
|
||||
- _4 = _2 as *const u8 (PtrToPtr);
|
||||
+ _5 = const {0x1 as *mut u8};
|
||||
+ _4 = const {0x1 as *const u8};
|
||||
StorageDead(_5);
|
||||
StorageLive(_6);
|
||||
- _6 = const Foo::<u8>::SENTINEL as *const u8 (PtrToPtr);
|
||||
- _1 = Eq(_4, _6);
|
||||
+ _6 = const {0x1 as *const u8};
|
||||
+ _1 = const true;
|
||||
StorageDead(_6);
|
||||
StorageDead(_4);
|
||||
StorageDead(_2);
|
||||
StorageDead(_1);
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
23
tests/mir-opt/gvn_ptr_eq_with_constant.rs
Normal file
23
tests/mir-opt/gvn_ptr_eq_with_constant.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// skip-filecheck
|
||||
//@ test-mir-pass: GVN
|
||||
//@ only-64bit
|
||||
//@ compile-flags: -Z mir-enable-passes=+Inline
|
||||
|
||||
// Regression for <https://github.com/rust-lang/rust/issues/127089>
|
||||
|
||||
#![feature(strict_provenance)]
|
||||
|
||||
struct Foo<T>(std::marker::PhantomData<T>);
|
||||
|
||||
impl<T> Foo<T> {
|
||||
const SENTINEL: *mut T = std::ptr::dangling_mut();
|
||||
|
||||
fn cmp_ptr(a: *mut T) -> bool {
|
||||
std::ptr::eq(a, Self::SENTINEL)
|
||||
}
|
||||
}
|
||||
|
||||
// EMIT_MIR gvn_ptr_eq_with_constant.main.GVN.diff
|
||||
pub fn main() {
|
||||
Foo::<u8>::cmp_ptr(std::ptr::dangling_mut());
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue