diff options
| author | bors <bors@rust-lang.org> | 2023-05-14 05:31:10 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-05-14 05:31:10 +0000 |
| commit | bc888958c9e1fdde09791f15d3421bdc3b6d7d29 (patch) | |
| tree | 7c58f002e19288e067a691a56b09cb71d7b3ad29 /compiler/rustc_mir_transform/src | |
| parent | ad6ab11234ae885913229f6de2c4465bdc0d76f3 (diff) | |
| parent | 8fb888dfaa1618838a288c41a8dc8ad24d1dadd5 (diff) | |
| download | rust-bc888958c9e1fdde09791f15d3421bdc3b6d7d29.tar.gz rust-bc888958c9e1fdde09791f15d3421bdc3b6d7d29.zip | |
Auto merge of #111440 - cjgillot:refprop-debuginfo, r=oli-obk
Allow MIR debuginfo to point to a variable's address
MIR optimizations currently do not to operate on borrowed locals.
When enabling #106285, many borrows will be left as-is because they are used in debuginfo. This pass allows to replace this pattern directly in MIR debuginfo:
```rust
a => _1
_1 = &raw? mut? _2
```
becomes
```rust
a => &_2
// No statement to borrow _2.
```
This pass is implemented as a drive-by in ReferencePropagation MIR pass.
This transformation allows following following MIR opts to treat _2 as an unborrowed local, and optimize it as such, even in builds with debuginfo.
In codegen, when encountering `a => &..&_2`, we create a list of allocas:
```llvm
store ptr %_2.dbg.spill, ptr %a.ref0.dbg.spill
store ptr %a.ref0.dbg.spill, ptr %a.ref1.dbg.spill
...
call void `@llvm.dbg.declare(metadata` ptr %a.ref{n}.dbg.spill, /* ... */)
```
Caveat: this transformation looses the exact type, we do not differentiate `a` as a immutable, mutable reference or a raw pointer. Everything is declared to `*mut` to codegen. I'm not convinced this is a blocker.
Diffstat (limited to 'compiler/rustc_mir_transform/src')
| -rw-r--r-- | compiler/rustc_mir_transform/src/ref_prop.rs | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index d1bc9ee9153..bbd9f76ba5c 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -77,11 +77,11 @@ impl<'tcx> MirPass<'tcx> for ReferencePropagation { #[instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - propagate_ssa(tcx, body); + while propagate_ssa(tcx, body) {} } } -fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { let ssa = SsaLocals::new(body); let mut replacer = compute_replacement(tcx, body, &ssa); @@ -94,6 +94,8 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if replacer.any_replacement { crate::simplify::remove_unused_definitions(body); } + + replacer.any_replacement } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -263,6 +265,7 @@ fn compute_replacement<'tcx>( targets, storage_to_remove, allowed_replacements, + fully_replacable_locals, any_replacement: false, }; @@ -343,6 +346,7 @@ struct Replacer<'tcx> { storage_to_remove: BitSet<Local>, allowed_replacements: FxHashSet<(Local, Location)>, any_replacement: bool, + fully_replacable_locals: BitSet<Local>, } impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> { @@ -350,6 +354,25 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> { self.tcx } + fn visit_var_debug_info(&mut self, debuginfo: &mut VarDebugInfo<'tcx>) { + if let VarDebugInfoContents::Place(ref mut place) = debuginfo.value + && place.projection.is_empty() + && let Value::Pointer(target, _) = self.targets[place.local] + && target.projection.iter().all(|p| p.can_use_in_debuginfo()) + { + if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() { + *place = Place::from(target.local).project_deeper(rest, self.tcx); + self.any_replacement = true; + } else if self.fully_replacable_locals.contains(place.local) + && let Some(references) = debuginfo.references.checked_add(1) + { + debuginfo.references = references; + *place = target; + self.any_replacement = true; + } + } + } + fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) { if place.projection.first() != Some(&PlaceElem::Deref) { return; |
