Skip to content

Commit dc4aa90

Browse files
committed
Auto merge of #143333 - cjgillot:local-value-numbering, r=<try>
[TOY] Extend GVN to perform local value numbering. This PR is more a toy than anything else, but I still think the implementation is sound. Current GVN MIR opt can be easily extended to track values that change inside a basic block. This PR attempts that. r? `@ghost` for perf
2 parents febb10d + e521268 commit dc4aa90

File tree

55 files changed

+1512
-1373
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1512
-1373
lines changed

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,11 @@ impl<'tcx> PlaceTy<'tcx> {
160160
/// Convenience wrapper around `projection_ty_core` for `PlaceElem`,
161161
/// where we can just use the `Ty` that is already stored inline on
162162
/// field projection elems.
163-
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
163+
pub fn projection_ty<V: ::std::fmt::Debug>(
164+
self,
165+
tcx: TyCtxt<'tcx>,
166+
elem: ProjectionElem<V, Ty<'tcx>>,
167+
) -> PlaceTy<'tcx> {
164168
self.projection_ty_core(tcx, &elem, |ty| ty, |_, _, _, ty| ty, |ty| ty)
165169
}
166170

@@ -290,6 +294,30 @@ impl<V, T> ProjectionElem<V, T> {
290294
Self::UnwrapUnsafeBinder(..) => false,
291295
}
292296
}
297+
298+
pub fn try_map<V2, T2>(
299+
self,
300+
v: impl FnOnce(V) -> Option<V2>,
301+
t: impl FnOnce(T) -> T2,
302+
) -> Option<ProjectionElem<V2, T2>> {
303+
Some(match self {
304+
ProjectionElem::Deref => ProjectionElem::Deref,
305+
ProjectionElem::Downcast(name, read_variant) => {
306+
ProjectionElem::Downcast(name, read_variant)
307+
}
308+
ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, t(ty)),
309+
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
310+
ProjectionElem::ConstantIndex { offset, min_length, from_end }
311+
}
312+
ProjectionElem::Subslice { from, to, from_end } => {
313+
ProjectionElem::Subslice { from, to, from_end }
314+
}
315+
ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(t(ty)),
316+
ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(t(ty)),
317+
ProjectionElem::UnwrapUnsafeBinder(ty) => ProjectionElem::UnwrapUnsafeBinder(t(ty)),
318+
ProjectionElem::Index(val) => ProjectionElem::Index(v(val)?),
319+
})
320+
}
293321
}
294322

295323
/// Alias for projections as they appear in `UserTypeProjection`, where we

compiler/rustc_middle/src/mir/visit.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,6 +1402,23 @@ impl PlaceContext {
14021402
)
14031403
}
14041404

1405+
/// Returns `true` if this place context may be used to know the address of the given place.
1406+
pub fn may_observe_address(self) -> bool {
1407+
matches!(
1408+
self,
1409+
PlaceContext::NonMutatingUse(
1410+
NonMutatingUseContext::SharedBorrow
1411+
| NonMutatingUseContext::RawBorrow
1412+
| NonMutatingUseContext::FakeBorrow
1413+
) | PlaceContext::MutatingUse(
1414+
MutatingUseContext::Drop
1415+
| MutatingUseContext::Borrow
1416+
| MutatingUseContext::RawBorrow
1417+
| MutatingUseContext::AsmOutput
1418+
)
1419+
)
1420+
}
1421+
14051422
/// Returns `true` if this place context represents a storage live or storage dead marker.
14061423
#[inline]
14071424
pub fn is_storage_marker(self) -> bool {

compiler/rustc_mir_dataflow/src/value_analysis.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet, StdEntry};
66
use rustc_data_structures::stack::ensure_sufficient_stack;
77
use rustc_index::IndexVec;
88
use rustc_index::bit_set::DenseBitSet;
9-
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
9+
use rustc_middle::mir::visit::{PlaceContext, Visitor};
1010
use rustc_middle::mir::*;
1111
use rustc_middle::ty::{self, Ty, TyCtxt};
1212
use tracing::debug;
@@ -917,12 +917,7 @@ pub fn excluded_locals(body: &Body<'_>) -> DenseBitSet<Local> {
917917

918918
impl<'tcx> Visitor<'tcx> for Collector {
919919
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
920-
if (context.is_borrow()
921-
|| context.is_address_of()
922-
|| context.is_drop()
923-
|| context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput))
924-
&& !place.is_indirect()
925-
{
920+
if context.may_observe_address() && !place.is_indirect() {
926921
// A pointer to a place could be used to access other places with the same local,
927922
// hence we have to exclude the local completely.
928923
self.result.insert(place.local);

0 commit comments

Comments
 (0)