From 6277c3a9441a0f2e0c89d479c1f3306567685817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 1 Jun 2022 00:00:00 +0000 Subject: [PATCH] Preserve unused pointer to address casts --- compiler/rustc_middle/src/mir/mod.rs | 29 +++++++++++++++++-- .../rustc_mir_dataflow/src/impls/liveness.rs | 9 ++---- .../src/dead_store_elimination.rs | 2 +- compiler/rustc_mir_transform/src/simplify.rs | 8 +++-- src/test/mir-opt/simplify-locals.rs | 7 +++++ ...ify_locals.expose_addr.SimplifyLocals.diff | 21 ++++++++++++++ 6 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index f3db359ec33..f382812f163 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2605,9 +2605,34 @@ pub enum Rvalue<'tcx> { static_assert_size!(Rvalue<'_>, 40); impl<'tcx> Rvalue<'tcx> { + /// Returns true if rvalue can be safely removed when the result is unused. #[inline] - pub fn is_pointer_int_cast(&self) -> bool { - matches!(self, Rvalue::Cast(CastKind::PointerExposeAddress, _, _)) + pub fn is_safe_to_remove(&self) -> bool { + 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 + // + 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, + } } } diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 7076fbe1bdb..9b62ee5473c 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -244,13 +244,10 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { // Compute the place that we are storing to, if any let destination = match &statement.kind { StatementKind::Assign(assign) => { - if assign.1.is_pointer_int_cast() { - // Pointer to int casts may be side-effects due to exposing the provenance. - // While the model is undecided, we should be conservative. See - // - None - } else { + if assign.1.is_safe_to_remove() { Some(assign.0) + } else { + None } } StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => { diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 8becac34ed7..779f3c77815 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -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() { let loc = Location { block: bb, statement_index }; if let StatementKind::Assign(assign) = &statement.kind { - if assign.1.is_pointer_int_cast() { + if !assign.1.is_safe_to_remove() { continue; } } diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 72e08343925..8a78ea5c82b 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -494,8 +494,12 @@ impl<'tcx> Visitor<'tcx> for UsedLocals { StatementKind::StorageLive(_local) | StatementKind::StorageDead(_local) => {} StatementKind::Assign(box (ref place, ref rvalue)) => { - self.visit_lhs(place, location); - self.visit_rvalue(rvalue, location); + if rvalue.is_safe_to_remove() { + self.visit_lhs(place, location); + self.visit_rvalue(rvalue, location); + } else { + self.super_statement(statement, location); + } } StatementKind::SetDiscriminant { ref place, variant_index: _ } diff --git a/src/test/mir-opt/simplify-locals.rs b/src/test/mir-opt/simplify-locals.rs index 5862cf2eb29..f6bf396cd05 100644 --- a/src/test/mir-opt/simplify-locals.rs +++ b/src/test/mir-opt/simplify-locals.rs @@ -62,6 +62,12 @@ fn t4() -> u32 { 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() { c(); d1(); @@ -71,4 +77,5 @@ fn main() { t2(); t3(); t4(); + expose_addr(&0); } diff --git a/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff new file mode 100644 index 00000000000..93d77ad40aa --- /dev/null +++ b/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff @@ -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 + } + } +