Skip to content

Commit 2e034dc

Browse files
committed
Exclude locals completely, instead of individual places
1 parent b3f6489 commit 2e034dc

File tree

3 files changed

+85
-29
lines changed

3 files changed

+85
-29
lines changed

compiler/rustc_mir_dataflow/src/value_analysis.rs

+18-29
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
3535
use std::fmt::{Debug, Formatter};
3636

37-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
37+
use rustc_data_structures::fx::FxHashMap;
3838
use rustc_index::vec::IndexVec;
3939
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
4040
use rustc_middle::mir::*;
@@ -587,7 +587,8 @@ impl Map {
587587
filter: impl FnMut(Ty<'tcx>) -> bool,
588588
) -> Self {
589589
let mut map = Self::new();
590-
map.register_with_filter(tcx, body, filter, &escaped_places(body));
590+
let exclude = excluded_locals(body);
591+
map.register_with_filter(tcx, body, filter, &exclude);
591592
debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
592593
map
593594
}
@@ -598,19 +599,14 @@ impl Map {
598599
tcx: TyCtxt<'tcx>,
599600
body: &Body<'tcx>,
600601
mut filter: impl FnMut(Ty<'tcx>) -> bool,
601-
exclude: &FxHashSet<Place<'tcx>>,
602+
exclude: &IndexVec<Local, bool>,
602603
) {
603604
// We use this vector as stack, pushing and popping projections.
604605
let mut projection = Vec::new();
605606
for (local, decl) in body.local_decls.iter_enumerated() {
606-
self.register_with_filter_rec(
607-
tcx,
608-
local,
609-
&mut projection,
610-
decl.ty,
611-
&mut filter,
612-
exclude,
613-
);
607+
if !exclude[local] {
608+
self.register_with_filter_rec(tcx, local, &mut projection, decl.ty, &mut filter);
609+
}
614610
}
615611
}
616612

@@ -624,17 +620,10 @@ impl Map {
624620
projection: &mut Vec<PlaceElem<'tcx>>,
625621
ty: Ty<'tcx>,
626622
filter: &mut impl FnMut(Ty<'tcx>) -> bool,
627-
exclude: &FxHashSet<Place<'tcx>>,
628623
) {
629-
let place = Place { local, projection: tcx.intern_place_elems(projection) };
630-
if exclude.contains(&place) {
631-
// This will also exclude all projections of the excluded place.
632-
return;
633-
}
634-
635624
// Note: The framework supports only scalars for now.
636625
if filter(ty) && ty.is_scalar() {
637-
trace!("registering place: {:?}", place);
626+
// trace!("registering place {:?}", PlaceRef { local, projection: &*projection });
638627

639628
// We know that the projection only contains trackable elements.
640629
let place = self.make_place(local, projection).unwrap();
@@ -653,7 +642,7 @@ impl Map {
653642
return;
654643
}
655644
projection.push(PlaceElem::Field(field, ty));
656-
self.register_with_filter_rec(tcx, local, projection, ty, filter, exclude);
645+
self.register_with_filter_rec(tcx, local, projection, ty, filter);
657646
projection.pop();
658647
});
659648
}
@@ -835,27 +824,27 @@ fn iter_fields<'tcx>(
835824
}
836825
}
837826

838-
/// Returns all places, that have their reference or address taken.
839-
///
840-
/// This includes shared references, and also drops and `InlineAsm` out parameters.
841-
fn escaped_places<'tcx>(body: &Body<'tcx>) -> FxHashSet<Place<'tcx>> {
842-
struct Collector<'tcx> {
843-
result: FxHashSet<Place<'tcx>>,
827+
/// Returns all locals with projections that have their reference or address taken.
828+
fn excluded_locals<'tcx>(body: &Body<'tcx>) -> IndexVec<Local, bool> {
829+
struct Collector {
830+
result: IndexVec<Local, bool>,
844831
}
845832

846-
impl<'tcx> Visitor<'tcx> for Collector<'tcx> {
833+
impl<'tcx> Visitor<'tcx> for Collector {
847834
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
848835
if context.is_borrow()
849836
|| context.is_address_of()
850837
|| context.is_drop()
851838
|| context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput)
852839
{
853-
self.result.insert(*place);
840+
// A pointer to a place could be used to access other places with the same local,
841+
// hence we have to exclude the local completely.
842+
self.result[place.local] = true;
854843
}
855844
}
856845
}
857846

858-
let mut collector = Collector { result: FxHashSet::default() };
847+
let mut collector = Collector { result: IndexVec::from_elem(false, &body.local_decls) };
859848
collector.visit_body(body);
860849
collector.result
861850
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
- // MIR for `main` before DataflowConstProp
2+
+ // MIR for `main` after DataflowConstProp
3+
4+
fn main() -> () {
5+
let mut _0: (); // return place in scope 0 at $DIR/sibling_ptr.rs:+0:11: +0:11
6+
let mut _1: (u8, u8); // in scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14
7+
let _2: (); // in scope 0 at $DIR/sibling_ptr.rs:+2:5: +5:6
8+
let mut _4: *mut u8; // in scope 0 at $DIR/sibling_ptr.rs:+4:10: +4:18
9+
let mut _5: *mut u8; // in scope 0 at $DIR/sibling_ptr.rs:+4:10: +4:11
10+
scope 1 {
11+
debug x => _1; // in scope 1 at $DIR/sibling_ptr.rs:+1:9: +1:14
12+
let _6: u8; // in scope 1 at $DIR/sibling_ptr.rs:+6:9: +6:11
13+
scope 2 {
14+
let _3: *mut u8; // in scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14
15+
scope 3 {
16+
debug p => _3; // in scope 3 at $DIR/sibling_ptr.rs:+3:13: +3:14
17+
}
18+
}
19+
scope 4 {
20+
debug x1 => _6; // in scope 4 at $DIR/sibling_ptr.rs:+6:9: +6:11
21+
}
22+
}
23+
24+
bb0: {
25+
StorageLive(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14
26+
Deinit(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
27+
(_1.0: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
28+
(_1.1: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
29+
StorageLive(_2); // scope 1 at $DIR/sibling_ptr.rs:+2:5: +5:6
30+
StorageLive(_3); // scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14
31+
_3 = &raw mut (_1.0: u8); // scope 2 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
32+
StorageLive(_4); // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
33+
StorageLive(_5); // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
34+
_5 = _3; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
35+
_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
36+
// mir::Constant
37+
// + span: $DIR/sibling_ptr.rs:8:12: 8:15
38+
// + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::<impl *mut u8>::add}, val: Value(<ZST>) }
39+
}
40+
41+
bb1: {
42+
StorageDead(_5); // scope 3 at $DIR/sibling_ptr.rs:+4:17: +4:18
43+
(*_4) = const 1_u8; // scope 3 at $DIR/sibling_ptr.rs:+4:9: +4:22
44+
StorageDead(_4); // scope 3 at $DIR/sibling_ptr.rs:+4:22: +4:23
45+
_2 = const (); // scope 2 at $DIR/sibling_ptr.rs:+2:5: +5:6
46+
StorageDead(_3); // scope 2 at $DIR/sibling_ptr.rs:+5:5: +5:6
47+
StorageDead(_2); // scope 1 at $DIR/sibling_ptr.rs:+5:5: +5:6
48+
StorageLive(_6); // scope 1 at $DIR/sibling_ptr.rs:+6:9: +6:11
49+
_6 = (_1.1: u8); // scope 1 at $DIR/sibling_ptr.rs:+6:14: +6:17
50+
_0 = const (); // scope 0 at $DIR/sibling_ptr.rs:+0:11: +7:2
51+
StorageDead(_6); // scope 1 at $DIR/sibling_ptr.rs:+7:1: +7:2
52+
StorageDead(_1); // scope 0 at $DIR/sibling_ptr.rs:+7:1: +7:2
53+
return; // scope 0 at $DIR/sibling_ptr.rs:+7:2: +7:2
54+
}
55+
}
56+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// unit-test: DataflowConstProp
2+
3+
// EMIT_MIR sibling_ptr.main.DataflowConstProp.diff
4+
fn main() {
5+
let mut x: (u8, u8) = (0, 0);
6+
unsafe {
7+
let p = std::ptr::addr_of_mut!(x.0);
8+
*p.add(1) = 1;
9+
}
10+
let x1 = x.1; // should not be propagated
11+
}

0 commit comments

Comments
 (0)