Don't drop Rvalue::WrapUnsafeBinder during GVN

This commit is contained in:
Michael Goulet 2025-03-11 16:05:34 +00:00
parent 4d30011f6c
commit 13134dd096
4 changed files with 102 additions and 2 deletions

View file

@ -872,8 +872,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
self.simplify_place_projection(place, location);
return self.new_pointer(*place, AddressKind::Address(mutbl));
}
Rvalue::WrapUnsafeBinder(ref mut op, _) => {
return self.simplify_operand(op, location);
Rvalue::WrapUnsafeBinder(ref mut op, ty) => {
let value = self.simplify_operand(op, location)?;
Value::Cast {
kind: CastKind::Transmute,
value,
from: op.ty(self.local_decls, self.tcx),
to: ty,
}
}
// Operations.

View file

@ -0,0 +1,35 @@
- // MIR for `propagate` before GVN
+ // MIR for `propagate` after GVN
fn propagate() -> unsafe<> i32 {
let mut _0: unsafe<> i32;
let _1: i32;
let mut _3: i32;
scope 1 {
debug x => _1;
let _2: unsafe<> i32;
scope 2 {
debug binder => _2;
}
}
bb0: {
- StorageLive(_1);
+ nop;
_1 = const 1_i32;
StorageLive(_2);
StorageLive(_3);
- _3 = copy _1;
- _2 = wrap_binder!(move _3; unsafe<> i32);
+ _3 = const 1_i32;
+ _2 = const {transmute(0x00000001): unsafe<> i32};
StorageDead(_3);
- _0 = move _2;
+ _0 = const {transmute(0x00000001): unsafe<> i32};
StorageDead(_2);
- StorageDead(_1);
+ nop;
return;
}
}

View file

@ -0,0 +1,29 @@
// skip-filecheck
//@ test-mir-pass: GVN
// EMIT_MIR gvn_on_unsafe_binder.test.GVN.diff
// EMIT_MIR gvn_on_unsafe_binder.propagate.GVN.diff
#![feature(unsafe_binders)]
use std::unsafe_binder::wrap_binder;
// Test for ICE <https://github.com/rust-lang/rust/issues/137846>.
fn test() {
unsafe {
let x = 1;
let binder: unsafe<'a> &'a i32 = wrap_binder!(&x);
}
}
// Test that GVN propagates const values through unsafe binders.
//
// The lifetime `'a` is redundant (and doesn't print when we print out the type).
// However, we need it so that rustfmt doesn't rip out the `unsafe<>` part for now.
fn propagate() -> unsafe<'a> i32 {
unsafe {
let x = 1;
let binder: unsafe<'a> i32 = wrap_binder!(x);
binder
}
}

View file

@ -0,0 +1,30 @@
- // MIR for `test` before GVN
+ // MIR for `test` after GVN
fn test() -> () {
let mut _0: ();
let _1: i32;
let mut _3: &i32;
scope 1 {
debug x => _1;
let _2: unsafe<'a> &'a i32;
scope 2 {
debug binder => _2;
}
}
bb0: {
StorageLive(_1);
_1 = const 1_i32;
StorageLive(_2);
StorageLive(_3);
_3 = &_1;
_2 = wrap_binder!(move _3; unsafe<'a> &'a i32);
StorageDead(_3);
_0 = const ();
StorageDead(_2);
StorageDead(_1);
return;
}
}