@@ -27,49 +27,12 @@ pub struct SsaLocals {
2727 direct_uses: IndexVec<Local, u32>,
2828}
2929
30- /// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
31- /// actually compute dominators, we can just compare block indices because bb0 is always the first
32- /// block, and in any body all other blocks are always dominated by bb0.
33- struct SmallDominators<'a> {
34- inner: Option<&'a Dominators<BasicBlock>>,
35- }
36-
37- impl SmallDominators<'_> {
38- fn dominates(&self, first: Location, second: Location) -> bool {
39- if first.block == second.block {
40- first.statement_index <= second.statement_index
41- } else if let Some(inner) = &self.inner {
42- inner.dominates(first.block, second.block)
43- } else {
44- first.block < second.block
45- }
46- }
47-
48- fn check_dominates(&mut self, set: &mut Set1<LocationExtended>, loc: Location) {
49- let assign_dominates = match *set {
50- Set1::Empty | Set1::Many => false,
51- Set1::One(LocationExtended::Arg) => true,
52- Set1::One(LocationExtended::Plain(assign)) => {
53- self.dominates(assign.successor_within_block(), loc)
54- }
55- };
56- // We are visiting a use that is not dominated by an assignment.
57- // Either there is a cycle involved, or we are reading for uninitialized local.
58- // Bail out.
59- if !assign_dominates {
60- *set = Set1::Many;
61- }
62- }
63- }
64-
6530impl SsaLocals {
6631 pub fn new<'tcx>(body: &Body<'tcx>) -> SsaLocals {
6732 let assignment_order = Vec::with_capacity(body.local_decls.len());
6833
6934 let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls);
70- let dominators =
71- if body.basic_blocks.len() > 2 { Some(body.basic_blocks.dominators()) } else { None };
72- let dominators = SmallDominators { inner: dominators };
35+ let dominators = body.basic_blocks.dominators();
7336
7437 let direct_uses = IndexVec::from_elem(0, &body.local_decls);
7538 let mut visitor = SsaVisitor { assignments, assignment_order, dominators, direct_uses };
@@ -231,12 +194,31 @@ enum LocationExtended {
231194}
232195
233196struct SsaVisitor<'a> {
234- dominators: SmallDominators<'a >,
197+ dominators: &'a Dominators<BasicBlock >,
235198 assignments: IndexVec<Local, Set1<LocationExtended>>,
236199 assignment_order: Vec<Local>,
237200 direct_uses: IndexVec<Local, u32>,
238201}
239202
203+ impl SsaVisitor<'_> {
204+ fn check_dominates(&mut self, local: Local, loc: Location) {
205+ let set = &mut self.assignments[local];
206+ let assign_dominates = match *set {
207+ Set1::Empty | Set1::Many => false,
208+ Set1::One(LocationExtended::Arg) => true,
209+ Set1::One(LocationExtended::Plain(assign)) => {
210+ assign.successor_within_block().dominates(loc, self.dominators)
211+ }
212+ };
213+ // We are visiting a use that is not dominated by an assignment.
214+ // Either there is a cycle involved, or we are reading for uninitialized local.
215+ // Bail out.
216+ if !assign_dominates {
217+ *set = Set1::Many;
218+ }
219+ }
220+ }
221+
240222impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> {
241223 fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) {
242224 match ctxt {
@@ -254,7 +236,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> {
254236 self.assignments[local] = Set1::Many;
255237 }
256238 PlaceContext::NonMutatingUse(_) => {
257- self.dominators. check_dominates(&mut self.assignments[ local] , loc);
239+ self.check_dominates(local, loc);
258240 self.direct_uses[local] += 1;
259241 }
260242 PlaceContext::NonUse(_) => {}
@@ -269,7 +251,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> {
269251 let new_ctxt = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
270252
271253 self.visit_projection(place.as_ref(), new_ctxt, loc);
272- self.dominators. check_dominates(&mut self.assignments[ place.local] , loc);
254+ self.check_dominates(place.local, loc);
273255 }
274256 return;
275257 } else {
0 commit comments