diff options
| author | dianqk <dianqk@dianqk.net> | 2025-05-19 21:07:34 +0800 |
|---|---|---|
| committer | dianqk <dianqk@dianqk.net> | 2025-05-19 21:35:49 +0800 |
| commit | be5d6c5425e8dfdf1662225fb23d6deb0e124dd4 (patch) | |
| tree | efe8f23e53d92fe332ddbed5be9602c46d459796 /compiler/rustc_mir_transform/src | |
| parent | 7068c8bd81c73db264c544f75a43158555567848 (diff) | |
| download | rust-be5d6c5425e8dfdf1662225fb23d6deb0e124dd4.tar.gz rust-be5d6c5425e8dfdf1662225fb23d6deb0e124dd4.zip | |
gvn: bail out unavoidable non-ssa locals in repeat
We cannot transform `*elem` to `array[idx1]` in the following code,
as `idx1` has already been modified.
```rust
mir! {
let array;
let elem;
{
array = [*val; 5];
elem = &array[idx1];
idx1 = idx2;
RET = *elem;
Return()
}
}
```
Diffstat (limited to 'compiler/rustc_mir_transform/src')
| -rw-r--r-- | compiler/rustc_mir_transform/src/gvn.rs | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 209e818e9e3..a91d46ec406 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -638,6 +638,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { place: PlaceRef<'tcx>, value: VnIndex, proj: PlaceElem<'tcx>, + from_non_ssa_index: &mut bool, ) -> Option<VnIndex> { let proj = match proj { ProjectionElem::Deref => { @@ -682,6 +683,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } ProjectionElem::Index(idx) => { if let Value::Repeat(inner, _) = self.get(value) { + *from_non_ssa_index |= self.locals[idx].is_none(); return Some(*inner); } let idx = self.locals[idx]?; @@ -774,6 +776,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Invariant: `value` holds the value up-to the `index`th projection excluded. let mut value = self.locals[place.local]?; + let mut from_non_ssa_index = false; for (index, proj) in place.projection.iter().enumerate() { if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value) && let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer) @@ -791,7 +794,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } let base = PlaceRef { local: place.local, projection: &place.projection[..index] }; - value = self.project(base, value, proj)?; + value = self.project(base, value, proj, &mut from_non_ssa_index)?; } if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value) @@ -804,6 +807,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } if let Some(new_local) = self.try_as_local(value, location) { place_ref = PlaceRef { local: new_local, projection: &[] }; + } else if from_non_ssa_index { + // If access to non-SSA locals is unavoidable, bail out. + return None; } if place_ref.local != place.local || place_ref.projection.len() < place.projection.len() { |
