diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2023-02-17 17:36:43 +0000 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2023-02-27 20:02:18 +0000 |
| commit | 2a32a2b64faf52b65080ea84b5bc110627294954 (patch) | |
| tree | 348b02aededbc14d33b0a67c4c1e68c6b3a7bd86 /compiler/rustc_mir_transform/src | |
| parent | 43ee4d15bf201f72c36abd7f02961df87dead441 (diff) | |
| download | rust-2a32a2b64faf52b65080ea84b5bc110627294954.tar.gz rust-2a32a2b64faf52b65080ea84b5bc110627294954.zip | |
Special case deref projections in SsaVisitor.
Diffstat (limited to 'compiler/rustc_mir_transform/src')
| -rw-r--r-- | compiler/rustc_mir_transform/src/ssa.rs | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index c1e7f62dea5..0bb97c4fc09 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -179,6 +179,25 @@ struct SsaVisitor { assignment_order: Vec<Local>, } +impl SsaVisitor { + fn check_assignment_dominates(&mut self, local: Local, loc: Location) { + let set = &mut self.assignments[local]; + let assign_dominates = match *set { + Set1::Empty | Set1::Many => false, + Set1::One(LocationExtended::Arg) => true, + Set1::One(LocationExtended::Plain(assign)) => { + assign.successor_within_block().dominates(loc, &self.dominators) + } + }; + // We are visiting a use that is not dominated by an assignment. + // Either there is a cycle involved, or we are reading for uninitialized local. + // Bail out. + if !assign_dominates { + *set = Set1::Many; + } + } +} + impl<'tcx> Visitor<'tcx> for SsaVisitor { fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) { match ctxt { @@ -192,24 +211,26 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor { // Immutable borrows are taken into account in `SsaLocals::new` by // removing non-freeze locals. PlaceContext::NonMutatingUse(_) => { - let set = &mut self.assignments[local]; - let assign_dominates = match *set { - Set1::Empty | Set1::Many => false, - Set1::One(LocationExtended::Arg) => true, - Set1::One(LocationExtended::Plain(assign)) => { - assign.successor_within_block().dominates(loc, &self.dominators) - } - }; - // We are visiting a use that is not dominated by an assignment. - // Either there is a cycle involved, or we are reading for uninitialized local. - // Bail out. - if !assign_dominates { - *set = Set1::Many; - } + self.check_assignment_dominates(local, loc); } PlaceContext::NonUse(_) => {} } } + + fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, loc: Location) { + if place.projection.first() == Some(&PlaceElem::Deref) { + // Do not do anything for storage statements and debuginfo. + if ctxt.is_use() { + // A use through a `deref` only reads from the local, and cannot write to it. + let new_ctxt = PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection); + + self.visit_projection(place.as_ref(), new_ctxt, loc); + self.check_assignment_dominates(place.local, loc); + } + return; + } + self.super_place(place, ctxt, loc); + } } #[instrument(level = "trace", skip(ssa, body))] |
