]> git.lizzy.rs Git - rust.git/commitdiff
Exclude locals completely, instead of individual places
authorJannis Christopher Köhl <mail@koehl.dev>
Sat, 12 Nov 2022 13:57:14 +0000 (14:57 +0100)
committerJannis Christopher Köhl <mail@koehl.dev>
Sat, 12 Nov 2022 13:57:14 +0000 (14:57 +0100)
compiler/rustc_mir_dataflow/src/value_analysis.rs
src/test/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff [new file with mode: 0644]
src/test/mir-opt/dataflow-const-prop/sibling_ptr.rs [new file with mode: 0644]

index 0f3b952ceec84dda2ed58383b9ee55316b31e890..85a35c13fd93a841d64bf5c738270da827ee38f0 100644 (file)
@@ -34,7 +34,7 @@
 
 use std::fmt::{Debug, Formatter};
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
@@ -587,7 +587,8 @@ pub fn from_filter<'tcx>(
         filter: impl FnMut(Ty<'tcx>) -> bool,
     ) -> Self {
         let mut map = Self::new();
-        map.register_with_filter(tcx, body, filter, &escaped_places(body));
+        let exclude = excluded_locals(body);
+        map.register_with_filter(tcx, body, filter, &exclude);
         debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
         map
     }
@@ -598,19 +599,14 @@ fn register_with_filter<'tcx>(
         tcx: TyCtxt<'tcx>,
         body: &Body<'tcx>,
         mut filter: impl FnMut(Ty<'tcx>) -> bool,
-        exclude: &FxHashSet<Place<'tcx>>,
+        exclude: &IndexVec<Local, bool>,
     ) {
         // We use this vector as stack, pushing and popping projections.
         let mut projection = Vec::new();
         for (local, decl) in body.local_decls.iter_enumerated() {
-            self.register_with_filter_rec(
-                tcx,
-                local,
-                &mut projection,
-                decl.ty,
-                &mut filter,
-                exclude,
-            );
+            if !exclude[local] {
+                self.register_with_filter_rec(tcx, local, &mut projection, decl.ty, &mut filter);
+            }
         }
     }
 
@@ -624,17 +620,10 @@ fn register_with_filter_rec<'tcx>(
         projection: &mut Vec<PlaceElem<'tcx>>,
         ty: Ty<'tcx>,
         filter: &mut impl FnMut(Ty<'tcx>) -> bool,
-        exclude: &FxHashSet<Place<'tcx>>,
     ) {
-        let place = Place { local, projection: tcx.intern_place_elems(projection) };
-        if exclude.contains(&place) {
-            // This will also exclude all projections of the excluded place.
-            return;
-        }
-
         // Note: The framework supports only scalars for now.
         if filter(ty) && ty.is_scalar() {
-            trace!("registering place: {:?}", place);
+            // trace!("registering place {:?}", PlaceRef { local, projection: &*projection });
 
             // We know that the projection only contains trackable elements.
             let place = self.make_place(local, projection).unwrap();
@@ -653,7 +642,7 @@ fn register_with_filter_rec<'tcx>(
                 return;
             }
             projection.push(PlaceElem::Field(field, ty));
-            self.register_with_filter_rec(tcx, local, projection, ty, filter, exclude);
+            self.register_with_filter_rec(tcx, local, projection, ty, filter);
             projection.pop();
         });
     }
@@ -835,27 +824,27 @@ fn iter_fields<'tcx>(
     }
 }
 
-/// Returns all places, that have their reference or address taken.
-///
-/// This includes shared references, and also drops and `InlineAsm` out parameters.
-fn escaped_places<'tcx>(body: &Body<'tcx>) -> FxHashSet<Place<'tcx>> {
-    struct Collector<'tcx> {
-        result: FxHashSet<Place<'tcx>>,
+/// Returns all locals with projections that have their reference or address taken.
+fn excluded_locals<'tcx>(body: &Body<'tcx>) -> IndexVec<Local, bool> {
+    struct Collector {
+        result: IndexVec<Local, bool>,
     }
 
-    impl<'tcx> Visitor<'tcx> for Collector<'tcx> {
+    impl<'tcx> Visitor<'tcx> for Collector {
         fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
             if context.is_borrow()
                 || context.is_address_of()
                 || context.is_drop()
                 || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput)
             {
-                self.result.insert(*place);
+                // A pointer to a place could be used to access other places with the same local,
+                // hence we have to exclude the local completely.
+                self.result[place.local] = true;
             }
         }
     }
 
-    let mut collector = Collector { result: FxHashSet::default() };
+    let mut collector = Collector { result: IndexVec::from_elem(false, &body.local_decls) };
     collector.visit_body(body);
     collector.result
 }
diff --git a/src/test/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff
new file mode 100644 (file)
index 0000000..8126d4b
--- /dev/null
@@ -0,0 +1,56 @@
+- // MIR for `main` before DataflowConstProp
++ // MIR for `main` after DataflowConstProp
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/sibling_ptr.rs:+0:11: +0:11
+      let mut _1: (u8, u8);                // in scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14
+      let _2: ();                          // in scope 0 at $DIR/sibling_ptr.rs:+2:5: +5:6
+      let mut _4: *mut u8;                 // in scope 0 at $DIR/sibling_ptr.rs:+4:10: +4:18
+      let mut _5: *mut u8;                 // in scope 0 at $DIR/sibling_ptr.rs:+4:10: +4:11
+      scope 1 {
+          debug x => _1;                   // in scope 1 at $DIR/sibling_ptr.rs:+1:9: +1:14
+          let _6: u8;                      // in scope 1 at $DIR/sibling_ptr.rs:+6:9: +6:11
+          scope 2 {
+              let _3: *mut u8;             // in scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14
+              scope 3 {
+                  debug p => _3;           // in scope 3 at $DIR/sibling_ptr.rs:+3:13: +3:14
+              }
+          }
+          scope 4 {
+              debug x1 => _6;              // in scope 4 at $DIR/sibling_ptr.rs:+6:9: +6:11
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14
+          Deinit(_1);                      // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
+          (_1.0: u8) = const 0_u8;         // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
+          (_1.1: u8) = const 0_u8;         // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
+          StorageLive(_2);                 // scope 1 at $DIR/sibling_ptr.rs:+2:5: +5:6
+          StorageLive(_3);                 // scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14
+          _3 = &raw mut (_1.0: u8);        // scope 2 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+          StorageLive(_4);                 // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
+          StorageLive(_5);                 // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
+          _5 = _3;                         // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
+          _4 = ptr::mut_ptr::<impl *mut u8>::add(move _5, const 1_usize) -> bb1; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
+                                           // mir::Constant
+                                           // + span: $DIR/sibling_ptr.rs:8:12: 8:15
+                                           // + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::<impl *mut u8>::add}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          StorageDead(_5);                 // scope 3 at $DIR/sibling_ptr.rs:+4:17: +4:18
+          (*_4) = const 1_u8;              // scope 3 at $DIR/sibling_ptr.rs:+4:9: +4:22
+          StorageDead(_4);                 // scope 3 at $DIR/sibling_ptr.rs:+4:22: +4:23
+          _2 = const ();                   // scope 2 at $DIR/sibling_ptr.rs:+2:5: +5:6
+          StorageDead(_3);                 // scope 2 at $DIR/sibling_ptr.rs:+5:5: +5:6
+          StorageDead(_2);                 // scope 1 at $DIR/sibling_ptr.rs:+5:5: +5:6
+          StorageLive(_6);                 // scope 1 at $DIR/sibling_ptr.rs:+6:9: +6:11
+          _6 = (_1.1: u8);                 // scope 1 at $DIR/sibling_ptr.rs:+6:14: +6:17
+          _0 = const ();                   // scope 0 at $DIR/sibling_ptr.rs:+0:11: +7:2
+          StorageDead(_6);                 // scope 1 at $DIR/sibling_ptr.rs:+7:1: +7:2
+          StorageDead(_1);                 // scope 0 at $DIR/sibling_ptr.rs:+7:1: +7:2
+          return;                          // scope 0 at $DIR/sibling_ptr.rs:+7:2: +7:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/dataflow-const-prop/sibling_ptr.rs b/src/test/mir-opt/dataflow-const-prop/sibling_ptr.rs
new file mode 100644 (file)
index 0000000..87ef00d
--- /dev/null
@@ -0,0 +1,11 @@
+// unit-test: DataflowConstProp
+
+// EMIT_MIR sibling_ptr.main.DataflowConstProp.diff
+fn main() {
+    let mut x: (u8, u8) = (0, 0);
+    unsafe {
+        let p = std::ptr::addr_of_mut!(x.0);
+        *p.add(1) = 1;
+    }
+    let x1 = x.1;  // should not be propagated
+}