mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Preserve unused pointer to address casts
This commit is contained in:
parent
7fe2c4b00d
commit
6277c3a944
@ -2605,9 +2605,34 @@ pub enum Rvalue<'tcx> {
|
|||||||
static_assert_size!(Rvalue<'_>, 40);
|
static_assert_size!(Rvalue<'_>, 40);
|
||||||
|
|
||||||
impl<'tcx> Rvalue<'tcx> {
|
impl<'tcx> Rvalue<'tcx> {
|
||||||
|
/// Returns true if rvalue can be safely removed when the result is unused.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_pointer_int_cast(&self) -> bool {
|
pub fn is_safe_to_remove(&self) -> bool {
|
||||||
matches!(self, Rvalue::Cast(CastKind::PointerExposeAddress, _, _))
|
match self {
|
||||||
|
// Pointer to int casts may be side-effects due to exposing the provenance.
|
||||||
|
// While the model is undecided, we should be conservative. See
|
||||||
|
// <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
|
||||||
|
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false,
|
||||||
|
|
||||||
|
Rvalue::Use(_)
|
||||||
|
| Rvalue::Repeat(_, _)
|
||||||
|
| Rvalue::Ref(_, _, _)
|
||||||
|
| Rvalue::ThreadLocalRef(_)
|
||||||
|
| Rvalue::AddressOf(_, _)
|
||||||
|
| Rvalue::Len(_)
|
||||||
|
| Rvalue::Cast(
|
||||||
|
CastKind::Misc | CastKind::Pointer(_) | CastKind::PointerFromExposedAddress,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
)
|
||||||
|
| Rvalue::BinaryOp(_, _)
|
||||||
|
| Rvalue::CheckedBinaryOp(_, _)
|
||||||
|
| Rvalue::NullaryOp(_, _)
|
||||||
|
| Rvalue::UnaryOp(_, _)
|
||||||
|
| Rvalue::Discriminant(_)
|
||||||
|
| Rvalue::Aggregate(_, _)
|
||||||
|
| Rvalue::ShallowInitBox(_, _) => true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,13 +244,10 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
|
|||||||
// Compute the place that we are storing to, if any
|
// Compute the place that we are storing to, if any
|
||||||
let destination = match &statement.kind {
|
let destination = match &statement.kind {
|
||||||
StatementKind::Assign(assign) => {
|
StatementKind::Assign(assign) => {
|
||||||
if assign.1.is_pointer_int_cast() {
|
if assign.1.is_safe_to_remove() {
|
||||||
// Pointer to int casts may be side-effects due to exposing the provenance.
|
|
||||||
// While the model is undecided, we should be conservative. See
|
|
||||||
// <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(assign.0)
|
Some(assign.0)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => {
|
StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => {
|
||||||
|
@ -34,7 +34,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
|
|||||||
for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
|
for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
|
||||||
let loc = Location { block: bb, statement_index };
|
let loc = Location { block: bb, statement_index };
|
||||||
if let StatementKind::Assign(assign) = &statement.kind {
|
if let StatementKind::Assign(assign) = &statement.kind {
|
||||||
if assign.1.is_pointer_int_cast() {
|
if !assign.1.is_safe_to_remove() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -494,8 +494,12 @@ impl<'tcx> Visitor<'tcx> for UsedLocals {
|
|||||||
StatementKind::StorageLive(_local) | StatementKind::StorageDead(_local) => {}
|
StatementKind::StorageLive(_local) | StatementKind::StorageDead(_local) => {}
|
||||||
|
|
||||||
StatementKind::Assign(box (ref place, ref rvalue)) => {
|
StatementKind::Assign(box (ref place, ref rvalue)) => {
|
||||||
|
if rvalue.is_safe_to_remove() {
|
||||||
self.visit_lhs(place, location);
|
self.visit_lhs(place, location);
|
||||||
self.visit_rvalue(rvalue, location);
|
self.visit_rvalue(rvalue, location);
|
||||||
|
} else {
|
||||||
|
self.super_statement(statement, location);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StatementKind::SetDiscriminant { ref place, variant_index: _ }
|
StatementKind::SetDiscriminant { ref place, variant_index: _ }
|
||||||
|
@ -62,6 +62,12 @@ fn t4() -> u32 {
|
|||||||
unsafe { X + 1 }
|
unsafe { X + 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR simplify_locals.expose_addr.SimplifyLocals.diff
|
||||||
|
fn expose_addr(p: *const usize) {
|
||||||
|
// Used pointer to address cast. Has a side effect of exposing the provenance.
|
||||||
|
p as usize;
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
c();
|
c();
|
||||||
d1();
|
d1();
|
||||||
@ -71,4 +77,5 @@ fn main() {
|
|||||||
t2();
|
t2();
|
||||||
t3();
|
t3();
|
||||||
t4();
|
t4();
|
||||||
|
expose_addr(&0);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
- // MIR for `expose_addr` before SimplifyLocals
|
||||||
|
+ // MIR for `expose_addr` after SimplifyLocals
|
||||||
|
|
||||||
|
fn expose_addr(_1: *const usize) -> () {
|
||||||
|
debug p => _1; // in scope 0 at $DIR/simplify-locals.rs:66:16: 66:17
|
||||||
|
let mut _0: (); // return place in scope 0 at $DIR/simplify-locals.rs:66:33: 66:33
|
||||||
|
let _2: usize; // in scope 0 at $DIR/simplify-locals.rs:68:5: 68:15
|
||||||
|
let mut _3: *const usize; // in scope 0 at $DIR/simplify-locals.rs:68:5: 68:6
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_2); // scope 0 at $DIR/simplify-locals.rs:68:5: 68:15
|
||||||
|
StorageLive(_3); // scope 0 at $DIR/simplify-locals.rs:68:5: 68:6
|
||||||
|
_3 = _1; // scope 0 at $DIR/simplify-locals.rs:68:5: 68:6
|
||||||
|
_2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/simplify-locals.rs:68:5: 68:15
|
||||||
|
StorageDead(_3); // scope 0 at $DIR/simplify-locals.rs:68:14: 68:15
|
||||||
|
StorageDead(_2); // scope 0 at $DIR/simplify-locals.rs:68:15: 68:16
|
||||||
|
_0 = const (); // scope 0 at $DIR/simplify-locals.rs:66:33: 69:2
|
||||||
|
return; // scope 0 at $DIR/simplify-locals.rs:69:2: 69:2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user