Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d2d24e3

Browse files
committedMay 3, 2024
Auto merge of rust-lang#123602 - cjgillot:gvn-borrowed, r=oli-obk
Account for immutably borrowed locals in MIR copy-prop and GVN For the most part, we consider that immutably borrowed `Freeze` locals still fulfill SSA conditions. As the borrow is immutable, any use of the local will have the value given by the single assignment, and there can be no surprise. This allows copy-prop to merge a non-borrowed local with a borrowed local. We chose to keep copy-classes heads unborrowed, as those may be easier to optimize in later passes. This also allows to GVN the value behind an immutable borrow. If a SSA local is borrowed, dereferencing that borrow is equivalent to copying the local's value: re-executing the assignment between the borrow and the dereference would be UB. r? `@ghost` for perf
2 parents befabbc + c19866f commit d2d24e3

30 files changed

+591
-302
lines changed
 

‎compiler/rustc_mir_transform/src/copy_prop.rs

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use rustc_index::IndexSlice;
33
use rustc_middle::mir::visit::*;
44
use rustc_middle::mir::*;
55
use rustc_middle::ty::TyCtxt;
6-
use rustc_mir_dataflow::impls::borrowed_locals;
76

87
use crate::ssa::SsaLocals;
98

@@ -32,8 +31,8 @@ impl<'tcx> MirPass<'tcx> for CopyProp {
3231
}
3332

3433
fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
35-
let borrowed_locals = borrowed_locals(body);
36-
let ssa = SsaLocals::new(body);
34+
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
35+
let ssa = SsaLocals::new(tcx, body, param_env);
3736

3837
let fully_moved = fully_moved_locals(&ssa, body);
3938
debug!(?fully_moved);
@@ -51,7 +50,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
5150
tcx,
5251
copy_classes: ssa.copy_classes(),
5352
fully_moved,
54-
borrowed_locals,
53+
borrowed_locals: ssa.borrowed_locals(),
5554
storage_to_remove,
5655
}
5756
.visit_body_preserves_cfg(body);
@@ -101,7 +100,7 @@ struct Replacer<'a, 'tcx> {
101100
tcx: TyCtxt<'tcx>,
102101
fully_moved: BitSet<Local>,
103102
storage_to_remove: BitSet<Local>,
104-
borrowed_locals: BitSet<Local>,
103+
borrowed_locals: &'a BitSet<Local>,
105104
copy_classes: &'a IndexSlice<Local, Local>,
106105
}
107106

@@ -112,6 +111,12 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
112111

113112
fn visit_local(&mut self, local: &mut Local, ctxt: PlaceContext, _: Location) {
114113
let new_local = self.copy_classes[*local];
114+
// We must not unify two locals that are borrowed. But this is fine if one is borrowed and
115+
// the other is not. We chose to check the original local, and not the target. That way, if
116+
// the original local is borrowed and the target is not, we do not pessimize the whole class.
117+
if self.borrowed_locals.contains(*local) {
118+
return;
119+
}
115120
match ctxt {
116121
// Do not modify the local in storage statements.
117122
PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) => {}
@@ -122,32 +127,14 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
122127
}
123128
}
124129

125-
fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
130+
fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, loc: Location) {
126131
if let Some(new_projection) = self.process_projection(place.projection, loc) {
127132
place.projection = self.tcx().mk_place_elems(&new_projection);
128133
}
129134

130-
let observes_address = match ctxt {
131-
PlaceContext::NonMutatingUse(
132-
NonMutatingUseContext::SharedBorrow
133-
| NonMutatingUseContext::FakeBorrow
134-
| NonMutatingUseContext::AddressOf,
135-
) => true,
136-
// For debuginfo, merging locals is ok.
137-
PlaceContext::NonUse(NonUseContext::VarDebugInfo) => {
138-
self.borrowed_locals.contains(place.local)
139-
}
140-
_ => false,
141-
};
142-
if observes_address && !place.is_indirect() {
143-
// We observe the address of `place.local`. Do not replace it.
144-
} else {
145-
self.visit_local(
146-
&mut place.local,
147-
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
148-
loc,
149-
)
150-
}
135+
// Any non-mutating use context is ok.
136+
let ctxt = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
137+
self.visit_local(&mut place.local, ctxt, loc)
151138
}
152139

153140
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {

‎compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ impl<'tcx> MirPass<'tcx> for GVN {
121121

122122
fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
123123
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
124-
let ssa = SsaLocals::new(body);
124+
let ssa = SsaLocals::new(tcx, body, param_env);
125125
// Clone dominators as we need them while mutating the body.
126126
let dominators = body.basic_blocks.dominators().clone();
127127

@@ -724,6 +724,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
724724
// Invariant: `value` holds the value up-to the `index`th projection excluded.
725725
let mut value = self.locals[place.local]?;
726726
for (index, proj) in place.projection.iter().enumerate() {
727+
if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
728+
&& let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
729+
&& let AddressKind::Ref(BorrowKind::Shared) = kind
730+
&& let Some(v) = self.simplify_place_value(&mut pointee, location)
731+
{
732+
value = v;
733+
place_ref = pointee.project_deeper(&place.projection[index..], self.tcx).as_ref();
734+
}
727735
if let Some(local) = self.try_as_local(value, location) {
728736
// Both `local` and `Place { local: place.local, projection: projection[..index] }`
729737
// hold the same value. Therefore, following place holds the value in the original
@@ -735,6 +743,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
735743
value = self.project(base, value, proj)?;
736744
}
737745

746+
if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
747+
&& let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
748+
&& let AddressKind::Ref(BorrowKind::Shared) = kind
749+
&& let Some(v) = self.simplify_place_value(&mut pointee, location)
750+
{
751+
value = v;
752+
place_ref = pointee.project_deeper(&[], self.tcx).as_ref();
753+
}
738754
if let Some(new_local) = self.try_as_local(value, location) {
739755
place_ref = PlaceRef { local: new_local, projection: &[] };
740756
}

‎compiler/rustc_mir_transform/src/normalize_array_len.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ impl<'tcx> MirPass<'tcx> for NormalizeArrayLen {
2222
}
2323

2424
fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
25-
let ssa = SsaLocals::new(body);
25+
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
26+
let ssa = SsaLocals::new(tcx, body, param_env);
2627

2728
let slice_lengths = compute_slice_length(tcx, &ssa, body);
2829
debug!(?slice_lengths);

‎compiler/rustc_mir_transform/src/ref_prop.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ impl<'tcx> MirPass<'tcx> for ReferencePropagation {
8282
}
8383

8484
fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
85-
let ssa = SsaLocals::new(body);
85+
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
86+
let ssa = SsaLocals::new(tcx, body, param_env);
8687

8788
let mut replacer = compute_replacement(tcx, body, &ssa);
8889
debug!(?replacer.targets);

‎compiler/rustc_mir_transform/src/ssa.rs

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
//! 1/ They are only assigned-to once, either as a function parameter, or in an assign statement;
33
//! 2/ This single assignment dominates all uses;
44
//!
5-
//! As a consequence of rule 2, we consider that borrowed locals are not SSA, even if they are
6-
//! `Freeze`, as we do not track that the assignment dominates all uses of the borrow.
5+
//! As we do not track indirect assignments, a local that has its address taken (either by
6+
//! AddressOf or by borrowing) is considered non-SSA. However, it is UB to modify through an
7+
//! immutable borrow of a `Freeze` local. Those can still be considered to be SSA.
78
89
use rustc_data_structures::graph::dominators::Dominators;
910
use rustc_index::bit_set::BitSet;
1011
use rustc_index::{IndexSlice, IndexVec};
1112
use rustc_middle::middle::resolve_bound_vars::Set1;
1213
use rustc_middle::mir::visit::*;
1314
use rustc_middle::mir::*;
15+
use rustc_middle::ty::{ParamEnv, TyCtxt};
1416

1517
pub struct SsaLocals {
1618
/// Assignments to each local. This defines whether the local is SSA.
@@ -24,6 +26,8 @@ pub struct SsaLocals {
2426
/// Number of "direct" uses of each local, ie. uses that are not dereferences.
2527
/// We ignore non-uses (Storage statements, debuginfo).
2628
direct_uses: IndexVec<Local, u32>,
29+
/// Set of SSA locals that are immutably borrowed.
30+
borrowed_locals: BitSet<Local>,
2731
}
2832

2933
pub enum AssignedValue<'a, 'tcx> {
@@ -33,15 +37,22 @@ pub enum AssignedValue<'a, 'tcx> {
3337
}
3438

3539
impl SsaLocals {
36-
pub fn new<'tcx>(body: &Body<'tcx>) -> SsaLocals {
40+
pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ParamEnv<'tcx>) -> SsaLocals {
3741
let assignment_order = Vec::with_capacity(body.local_decls.len());
3842

3943
let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls);
4044
let dominators = body.basic_blocks.dominators();
4145

4246
let direct_uses = IndexVec::from_elem(0, &body.local_decls);
43-
let mut visitor =
44-
SsaVisitor { body, assignments, assignment_order, dominators, direct_uses };
47+
let borrowed_locals = BitSet::new_empty(body.local_decls.len());
48+
let mut visitor = SsaVisitor {
49+
body,
50+
assignments,
51+
assignment_order,
52+
dominators,
53+
direct_uses,
54+
borrowed_locals,
55+
};
4556

4657
for local in body.args_iter() {
4758
visitor.assignments[local] = Set1::One(DefLocation::Argument);
@@ -58,6 +69,16 @@ impl SsaLocals {
5869
visitor.visit_var_debug_info(var_debug_info);
5970
}
6071

72+
// The immutability of shared borrows only works on `Freeze` locals. If the visitor found
73+
// borrows, we need to check the types. For raw pointers and mutable borrows, the locals
74+
// have already been marked as non-SSA.
75+
debug!(?visitor.borrowed_locals);
76+
for local in visitor.borrowed_locals.iter() {
77+
if !body.local_decls[local].ty.is_freeze(tcx, param_env) {
78+
visitor.assignments[local] = Set1::Many;
79+
}
80+
}
81+
6182
debug!(?visitor.assignments);
6283
debug!(?visitor.direct_uses);
6384

@@ -70,6 +91,7 @@ impl SsaLocals {
7091
assignments: visitor.assignments,
7192
assignment_order: visitor.assignment_order,
7293
direct_uses: visitor.direct_uses,
94+
borrowed_locals: visitor.borrowed_locals,
7395
// This is filled by `compute_copy_classes`.
7496
copy_classes: IndexVec::default(),
7597
};
@@ -174,6 +196,11 @@ impl SsaLocals {
174196
&self.copy_classes
175197
}
176198

199+
/// Set of SSA locals that are immutably borrowed.
200+
pub fn borrowed_locals(&self) -> &BitSet<Local> {
201+
&self.borrowed_locals
202+
}
203+
177204
/// Make a property uniform on a copy equivalence class by removing elements.
178205
pub fn meet_copy_equivalence(&self, property: &mut BitSet<Local>) {
179206
// Consolidate to have a local iff all its copies are.
@@ -208,6 +235,8 @@ struct SsaVisitor<'tcx, 'a> {
208235
assignments: IndexVec<Local, Set1<DefLocation>>,
209236
assignment_order: Vec<Local>,
210237
direct_uses: IndexVec<Local, u32>,
238+
// Track locals that are immutably borrowed, so we can check their type is `Freeze` later.
239+
borrowed_locals: BitSet<Local>,
211240
}
212241

213242
impl SsaVisitor<'_, '_> {
@@ -232,16 +261,18 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'tcx, '_> {
232261
PlaceContext::MutatingUse(MutatingUseContext::Projection)
233262
| PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => bug!(),
234263
// Anything can happen with raw pointers, so remove them.
235-
// We do not verify that all uses of the borrow dominate the assignment to `local`,
236-
// so we have to remove them too.
237-
PlaceContext::NonMutatingUse(
238-
NonMutatingUseContext::SharedBorrow
239-
| NonMutatingUseContext::FakeBorrow
240-
| NonMutatingUseContext::AddressOf,
241-
)
264+
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
242265
| PlaceContext::MutatingUse(_) => {
243266
self.assignments[local] = Set1::Many;
244267
}
268+
// Immutable borrows are ok, but we need to delay a check that the type is `Freeze`.
269+
PlaceContext::NonMutatingUse(
270+
NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::FakeBorrow,
271+
) => {
272+
self.borrowed_locals.insert(local);
273+
self.check_dominates(local, loc);
274+
self.direct_uses[local] += 1;
275+
}
245276
PlaceContext::NonMutatingUse(_) => {
246277
self.check_dominates(local, loc);
247278
self.direct_uses[local] += 1;

‎tests/coverage/issue-83601.cov-map

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
Function name: issue_83601::main
2-
Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02]
2+
Raw bytes (21): 0x[01, 01, 01, 05, 00, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02]
33
Number of files: 1
44
- file 0 => global file 1
55
Number of expressions: 1
6-
- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
6+
- expression 0 operands: lhs = Counter(1), rhs = Zero
77
Number of file 0 mappings: 3
88
- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28)
99
- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28)
1010
- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2)
11-
= (c1 - c2)
11+
= (c1 - Zero)
1212

‎tests/coverage/issue-84561.cov-map

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,22 @@ Number of file 0 mappings: 1
7777
- Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10)
7878

7979
Function name: issue_84561::test3
80-
Raw bytes (436): 0x[01, 01, 41, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 41, 2e, 45, 3d, 41, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 92, 01, 55, 51, 00, 8f, 01, 5d, 92, 01, 55, 51, 00, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 00, fe, 01, 82, 02, 00, 69, 6d, 69, 6d, 82, 02, 00, 69, 6d, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, ee, 01, 00, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02]
80+
Raw bytes (436): 0x[01, 01, 41, 05, 00, 0d, 00, 15, 00, 12, 00, 15, 00, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 00, 2e, 45, 3d, 00, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 92, 01, 55, 51, 00, 8f, 01, 5d, 92, 01, 55, 51, 00, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 00, fe, 01, 82, 02, 00, 69, 6d, 69, 6d, 82, 02, 00, 69, 6d, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, ee, 01, 00, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02]
8181
Number of files: 1
8282
- file 0 => global file 1
8383
Number of expressions: 65
84-
- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
84+
- expression 0 operands: lhs = Counter(1), rhs = Zero
8585
- expression 1 operands: lhs = Counter(3), rhs = Zero
86-
- expression 2 operands: lhs = Counter(5), rhs = Counter(6)
86+
- expression 2 operands: lhs = Counter(5), rhs = Zero
8787
- expression 3 operands: lhs = Expression(4, Sub), rhs = Zero
88-
- expression 4 operands: lhs = Counter(5), rhs = Counter(6)
88+
- expression 4 operands: lhs = Counter(5), rhs = Zero
8989
- expression 5 operands: lhs = Counter(8), rhs = Zero
9090
- expression 6 operands: lhs = Expression(7, Sub), rhs = Zero
9191
- expression 7 operands: lhs = Counter(8), rhs = Zero
9292
- expression 8 operands: lhs = Counter(12), rhs = Zero
93-
- expression 9 operands: lhs = Counter(15), rhs = Counter(16)
93+
- expression 9 operands: lhs = Counter(15), rhs = Zero
9494
- expression 10 operands: lhs = Expression(11, Sub), rhs = Counter(17)
95-
- expression 11 operands: lhs = Counter(15), rhs = Counter(16)
95+
- expression 11 operands: lhs = Counter(15), rhs = Zero
9696
- expression 12 operands: lhs = Expression(16, Sub), rhs = Counter(18)
9797
- expression 13 operands: lhs = Counter(17), rhs = Zero
9898
- expression 14 operands: lhs = Expression(15, Add), rhs = Counter(20)
@@ -150,15 +150,15 @@ Number of file 0 mappings: 51
150150
- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
151151
- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28)
152152
- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 4, 31)
153-
= (c1 - c2)
153+
= (c1 - Zero)
154154
- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31)
155155
- Code(Expression(1, Sub)) at (prev + 1, 5) to (start + 0, 31)
156156
= (c3 - Zero)
157157
- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28)
158158
- Code(Expression(4, Sub)) at (prev + 2, 5) to (start + 0, 31)
159-
= (c5 - c6)
159+
= (c5 - Zero)
160160
- Code(Expression(3, Sub)) at (prev + 1, 5) to (start + 0, 15)
161-
= ((c5 - c6) - Zero)
161+
= ((c5 - Zero) - Zero)
162162
- Code(Zero) at (prev + 0, 32) to (start + 0, 48)
163163
- Code(Counter(8)) at (prev + 1, 5) to (start + 3, 15)
164164
- Code(Zero) at (prev + 3, 32) to (start + 0, 48)
@@ -176,10 +176,10 @@ Number of file 0 mappings: 51
176176
= (c12 - Zero)
177177
- Code(Counter(15)) at (prev + 4, 9) to (start + 4, 6)
178178
- Code(Expression(11, Sub)) at (prev + 5, 8) to (start + 0, 15)
179-
= (c15 - c16)
179+
= (c15 - Zero)
180180
- Code(Counter(17)) at (prev + 1, 9) to (start + 3, 10)
181181
- Code(Expression(10, Sub)) at (prev + 5, 9) to (start + 3, 10)
182-
= ((c15 - c16) - c17)
182+
= ((c15 - Zero) - c17)
183183
- Code(Expression(15, Add)) at (prev + 5, 8) to (start + 0, 15)
184184
= ((c17 - Zero) + c18)
185185
- Code(Counter(20)) at (prev + 1, 9) to (start + 0, 19)

‎tests/crashes/111883.rs

Lines changed: 0 additions & 40 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
- // MIR for `borrowed` before CopyProp
2+
+ // MIR for `borrowed` after CopyProp
3+
4+
fn borrowed(_1: T) -> bool {
5+
let mut _0: bool;
6+
let mut _2: T;
7+
let mut _3: &T;
8+
9+
bb0: {
10+
- _2 = _1;
11+
_3 = &_1;
12+
_0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable];
13+
}
14+
15+
bb1: {
16+
- _0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable];
17+
+ _0 = opaque::<T>(_1) -> [return: bb2, unwind unreachable];
18+
}
19+
20+
bb2: {
21+
return;
22+
}
23+
}
24+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
- // MIR for `borrowed` before CopyProp
2+
+ // MIR for `borrowed` after CopyProp
3+
4+
fn borrowed(_1: T) -> bool {
5+
let mut _0: bool;
6+
let mut _2: T;
7+
let mut _3: &T;
8+
9+
bb0: {
10+
- _2 = _1;
11+
_3 = &_1;
12+
_0 = opaque::<&T>(_3) -> [return: bb1, unwind continue];
13+
}
14+
15+
bb1: {
16+
- _0 = opaque::<T>(_2) -> [return: bb2, unwind continue];
17+
+ _0 = opaque::<T>(_1) -> [return: bb2, unwind continue];
18+
}
19+
20+
bb2: {
21+
return;
22+
}
23+
}
24+

‎tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-abort.diff renamed to ‎tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-abort.diff

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
- // MIR for `f` before CopyProp
2-
+ // MIR for `f` after CopyProp
1+
- // MIR for `compare_address` before CopyProp
2+
+ // MIR for `compare_address` after CopyProp
33

4-
fn f() -> bool {
4+
fn compare_address() -> bool {
55
let mut _0: bool;
66
let mut _1: u8;
77
let mut _2: &u8;

‎tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-unwind.diff renamed to ‎tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-unwind.diff

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
- // MIR for `f` before CopyProp
2-
+ // MIR for `f` after CopyProp
1+
- // MIR for `compare_address` before CopyProp
2+
+ // MIR for `compare_address` after CopyProp
33

4-
fn f() -> bool {
4+
fn compare_address() -> bool {
55
let mut _0: bool;
66
let mut _1: u8;
77
let mut _2: &u8;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
- // MIR for `non_freeze` before CopyProp
2+
+ // MIR for `non_freeze` after CopyProp
3+
4+
fn non_freeze(_1: T) -> bool {
5+
let mut _0: bool;
6+
let mut _2: T;
7+
let mut _3: &T;
8+
9+
bb0: {
10+
_2 = _1;
11+
_3 = &_1;
12+
_0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable];
13+
}
14+
15+
bb1: {
16+
_0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable];
17+
}
18+
19+
bb2: {
20+
return;
21+
}
22+
}
23+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
- // MIR for `non_freeze` before CopyProp
2+
+ // MIR for `non_freeze` after CopyProp
3+
4+
fn non_freeze(_1: T) -> bool {
5+
let mut _0: bool;
6+
let mut _2: T;
7+
let mut _3: &T;
8+
9+
bb0: {
10+
_2 = _1;
11+
_3 = &_1;
12+
_0 = opaque::<&T>(_3) -> [return: bb1, unwind continue];
13+
}
14+
15+
bb1: {
16+
_0 = opaque::<T>(_2) -> [return: bb2, unwind continue];
17+
}
18+
19+
bb2: {
20+
return;
21+
}
22+
}
23+

‎tests/mir-opt/copy-prop/borrowed_local.rs

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
// skip-filecheck
21
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
32
//@ test-mir-pass: CopyProp
43

5-
#![feature(custom_mir, core_intrinsics)]
4+
#![feature(custom_mir, core_intrinsics, freeze)]
65
#![allow(unused_assignments)]
76
extern crate core;
7+
use core::marker::Freeze;
88
use core::intrinsics::mir::*;
99

1010
fn opaque(_: impl Sized) -> bool { true }
@@ -14,7 +14,16 @@ fn cmp_ref(a: &u8, b: &u8) -> bool {
1414
}
1515

1616
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
17-
fn f() -> bool {
17+
fn compare_address() -> bool {
18+
// CHECK-LABEL: fn compare_address(
19+
// CHECK: bb0: {
20+
// CHECK-NEXT: _1 = const 5_u8;
21+
// CHECK-NEXT: _2 = &_1;
22+
// CHECK-NEXT: _3 = _1;
23+
// CHECK-NEXT: _4 = &_3;
24+
// CHECK-NEXT: _0 = cmp_ref(_2, _4)
25+
// CHECK: bb1: {
26+
// CHECK-NEXT: _0 = opaque::<u8>(_3)
1827
mir!(
1928
{
2029
let a = 5_u8;
@@ -34,8 +43,60 @@ fn f() -> bool {
3443
)
3544
}
3645

46+
/// Generic type `T` is `Freeze`, so shared borrows are immutable.
47+
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
48+
fn borrowed<T: Copy + Freeze>(x: T) -> bool {
49+
// CHECK-LABEL: fn borrowed(
50+
// CHECK: bb0: {
51+
// CHECK-NEXT: _3 = &_1;
52+
// CHECK-NEXT: _0 = opaque::<&T>(_3)
53+
// CHECK: bb1: {
54+
// CHECK-NEXT: _0 = opaque::<T>(_1)
55+
mir!(
56+
{
57+
let a = x;
58+
let r1 = &x;
59+
Call(RET = opaque(r1), ReturnTo(next), UnwindContinue())
60+
}
61+
next = {
62+
Call(RET = opaque(a), ReturnTo(ret), UnwindContinue())
63+
}
64+
ret = {
65+
Return()
66+
}
67+
)
68+
}
69+
70+
/// Generic type `T` is not known to be `Freeze`, so shared borrows may be mutable.
71+
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
72+
fn non_freeze<T: Copy>(x: T) -> bool {
73+
// CHECK-LABEL: fn non_freeze(
74+
// CHECK: bb0: {
75+
// CHECK-NEXT: _2 = _1;
76+
// CHECK-NEXT: _3 = &_1;
77+
// CHECK-NEXT: _0 = opaque::<&T>(_3)
78+
// CHECK: bb1: {
79+
// CHECK-NEXT: _0 = opaque::<T>(_2)
80+
mir!(
81+
{
82+
let a = x;
83+
let r1 = &x;
84+
Call(RET = opaque(r1), ReturnTo(next), UnwindContinue())
85+
}
86+
next = {
87+
Call(RET = opaque(a), ReturnTo(ret), UnwindContinue())
88+
}
89+
ret = {
90+
Return()
91+
}
92+
)
93+
}
94+
3795
fn main() {
38-
assert!(!f());
96+
assert!(!compare_address());
97+
non_freeze(5);
3998
}
4099

41-
// EMIT_MIR borrowed_local.f.CopyProp.diff
100+
// EMIT_MIR borrowed_local.compare_address.CopyProp.diff
101+
// EMIT_MIR borrowed_local.borrowed.CopyProp.diff
102+
// EMIT_MIR borrowed_local.non_freeze.CopyProp.diff
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
- // MIR for `borrowed` before GVN
2+
+ // MIR for `borrowed` after GVN
3+
4+
fn borrowed(_1: T) -> () {
5+
let mut _0: ();
6+
let mut _2: T;
7+
let mut _3: &T;
8+
9+
bb0: {
10+
_2 = _1;
11+
_3 = &_1;
12+
_0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable];
13+
}
14+
15+
bb1: {
16+
- _0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable];
17+
+ _0 = opaque::<T>(_1) -> [return: bb2, unwind unreachable];
18+
}
19+
20+
bb2: {
21+
- _0 = opaque::<T>((*_3)) -> [return: bb3, unwind unreachable];
22+
+ _0 = opaque::<T>(_1) -> [return: bb3, unwind unreachable];
23+
}
24+
25+
bb3: {
26+
return;
27+
}
28+
}
29+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
- // MIR for `borrowed` before GVN
2+
+ // MIR for `borrowed` after GVN
3+
4+
fn borrowed(_1: T) -> () {
5+
let mut _0: ();
6+
let mut _2: T;
7+
let mut _3: &T;
8+
9+
bb0: {
10+
_2 = _1;
11+
_3 = &_1;
12+
_0 = opaque::<&T>(_3) -> [return: bb1, unwind continue];
13+
}
14+
15+
bb1: {
16+
- _0 = opaque::<T>(_2) -> [return: bb2, unwind continue];
17+
+ _0 = opaque::<T>(_1) -> [return: bb2, unwind continue];
18+
}
19+
20+
bb2: {
21+
- _0 = opaque::<T>((*_3)) -> [return: bb3, unwind continue];
22+
+ _0 = opaque::<T>(_1) -> [return: bb3, unwind continue];
23+
}
24+
25+
bb3: {
26+
return;
27+
}
28+
}
29+

‎tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
let mut _3: fn(u8) -> u8;
99
let _5: ();
1010
let mut _6: fn(u8) -> u8;
11-
let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21};
11+
let mut _9: {closure@$DIR/gvn.rs:612:19: 612:21};
1212
let _10: ();
1313
let mut _11: fn();
14-
let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21};
14+
let mut _13: {closure@$DIR/gvn.rs:612:19: 612:21};
1515
let _14: ();
1616
let mut _15: fn();
1717
scope 1 {
1818
debug f => _1;
1919
let _4: fn(u8) -> u8;
2020
scope 2 {
2121
debug g => _4;
22-
let _7: {closure@$DIR/gvn.rs:610:19: 610:21};
22+
let _7: {closure@$DIR/gvn.rs:612:19: 612:21};
2323
scope 3 {
2424
debug closure => _7;
2525
let _8: fn();
@@ -62,16 +62,16 @@
6262
StorageDead(_6);
6363
StorageDead(_5);
6464
- StorageLive(_7);
65-
- _7 = {closure@$DIR/gvn.rs:610:19: 610:21};
65+
- _7 = {closure@$DIR/gvn.rs:612:19: 612:21};
6666
- StorageLive(_8);
6767
+ nop;
68-
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
68+
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
6969
+ nop;
7070
StorageLive(_9);
7171
- _9 = _7;
7272
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
73-
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
74-
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
73+
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
74+
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
7575
StorageDead(_9);
7676
StorageLive(_10);
7777
StorageLive(_11);
@@ -88,8 +88,8 @@
8888
StorageLive(_13);
8989
- _13 = _7;
9090
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
91-
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
92-
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
91+
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
92+
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
9393
StorageDead(_13);
9494
StorageLive(_14);
9595
StorageLive(_15);

‎tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
let mut _3: fn(u8) -> u8;
99
let _5: ();
1010
let mut _6: fn(u8) -> u8;
11-
let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21};
11+
let mut _9: {closure@$DIR/gvn.rs:612:19: 612:21};
1212
let _10: ();
1313
let mut _11: fn();
14-
let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21};
14+
let mut _13: {closure@$DIR/gvn.rs:612:19: 612:21};
1515
let _14: ();
1616
let mut _15: fn();
1717
scope 1 {
1818
debug f => _1;
1919
let _4: fn(u8) -> u8;
2020
scope 2 {
2121
debug g => _4;
22-
let _7: {closure@$DIR/gvn.rs:610:19: 610:21};
22+
let _7: {closure@$DIR/gvn.rs:612:19: 612:21};
2323
scope 3 {
2424
debug closure => _7;
2525
let _8: fn();
@@ -62,16 +62,16 @@
6262
StorageDead(_6);
6363
StorageDead(_5);
6464
- StorageLive(_7);
65-
- _7 = {closure@$DIR/gvn.rs:610:19: 610:21};
65+
- _7 = {closure@$DIR/gvn.rs:612:19: 612:21};
6666
- StorageLive(_8);
6767
+ nop;
68-
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
68+
+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
6969
+ nop;
7070
StorageLive(_9);
7171
- _9 = _7;
7272
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
73-
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
74-
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
73+
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
74+
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
7575
StorageDead(_9);
7676
StorageLive(_10);
7777
StorageLive(_11);
@@ -88,8 +88,8 @@
8888
StorageLive(_13);
8989
- _13 = _7;
9090
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
91-
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
92-
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
91+
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
92+
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
9393
StorageDead(_13);
9494
StorageLive(_14);
9595
StorageLive(_15);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
- // MIR for `non_freeze` before GVN
2+
+ // MIR for `non_freeze` after GVN
3+
4+
fn non_freeze(_1: T) -> () {
5+
let mut _0: ();
6+
let mut _2: T;
7+
let mut _3: &T;
8+
9+
bb0: {
10+
_2 = _1;
11+
_3 = &_1;
12+
_0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable];
13+
}
14+
15+
bb1: {
16+
_0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable];
17+
}
18+
19+
bb2: {
20+
_0 = opaque::<T>((*_3)) -> [return: bb3, unwind unreachable];
21+
}
22+
23+
bb3: {
24+
return;
25+
}
26+
}
27+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
- // MIR for `non_freeze` before GVN
2+
+ // MIR for `non_freeze` after GVN
3+
4+
fn non_freeze(_1: T) -> () {
5+
let mut _0: ();
6+
let mut _2: T;
7+
let mut _3: &T;
8+
9+
bb0: {
10+
_2 = _1;
11+
_3 = &_1;
12+
_0 = opaque::<&T>(_3) -> [return: bb1, unwind continue];
13+
}
14+
15+
bb1: {
16+
_0 = opaque::<T>(_2) -> [return: bb2, unwind continue];
17+
}
18+
19+
bb2: {
20+
_0 = opaque::<T>((*_3)) -> [return: bb3, unwind continue];
21+
}
22+
23+
bb3: {
24+
return;
25+
}
26+
}
27+

‎tests/mir-opt/gvn.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
#![feature(rustc_attrs)]
77
#![feature(custom_mir)]
88
#![feature(core_intrinsics)]
9+
#![feature(freeze)]
910
#![allow(unconditional_panic)]
1011

1112
use std::intrinsics::mir::*;
13+
use std::marker::Freeze;
1214
use std::mem::transmute;
1315

1416
struct S<T>(T);
@@ -720,6 +722,65 @@ fn wide_ptr_integer() {
720722
opaque(a >= b);
721723
}
722724

725+
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
726+
fn borrowed<T: Copy + Freeze>(x: T) {
727+
// CHECK-LABEL: fn borrowed(
728+
// CHECK: bb0: {
729+
// CHECK-NEXT: _2 = _1;
730+
// CHECK-NEXT: _3 = &_1;
731+
// CHECK-NEXT: _0 = opaque::<&T>(_3)
732+
// CHECK: bb1: {
733+
// CHECK-NEXT: _0 = opaque::<T>(_1)
734+
// CHECK: bb2: {
735+
// CHECK-NEXT: _0 = opaque::<T>(_1)
736+
mir!(
737+
{
738+
let a = x;
739+
let r1 = &x;
740+
Call(RET = opaque(r1), ReturnTo(next), UnwindContinue())
741+
}
742+
next = {
743+
Call(RET = opaque(a), ReturnTo(deref), UnwindContinue())
744+
}
745+
deref = {
746+
Call(RET = opaque(*r1), ReturnTo(ret), UnwindContinue())
747+
}
748+
ret = {
749+
Return()
750+
}
751+
)
752+
}
753+
754+
/// Generic type `T` is not known to be `Freeze`, so shared borrows may be mutable.
755+
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
756+
fn non_freeze<T: Copy>(x: T) {
757+
// CHECK-LABEL: fn non_freeze(
758+
// CHECK: bb0: {
759+
// CHECK-NEXT: _2 = _1;
760+
// CHECK-NEXT: _3 = &_1;
761+
// CHECK-NEXT: _0 = opaque::<&T>(_3)
762+
// CHECK: bb1: {
763+
// CHECK-NEXT: _0 = opaque::<T>(_2)
764+
// CHECK: bb2: {
765+
// CHECK-NEXT: _0 = opaque::<T>((*_3))
766+
mir!(
767+
{
768+
let a = x;
769+
let r1 = &x;
770+
Call(RET = opaque(r1), ReturnTo(next), UnwindContinue())
771+
}
772+
next = {
773+
Call(RET = opaque(a), ReturnTo(deref), UnwindContinue())
774+
}
775+
deref = {
776+
Call(RET = opaque(*r1), ReturnTo(ret), UnwindContinue())
777+
}
778+
ret = {
779+
Return()
780+
}
781+
)
782+
}
783+
723784
fn main() {
724785
subexpression_elimination(2, 4, 5);
725786
wrap_unwrap(5);
@@ -742,6 +803,8 @@ fn main() {
742803
constant_index_overflow(&[5, 3]);
743804
wide_ptr_provenance();
744805
wide_ptr_integer();
806+
borrowed(5);
807+
non_freeze(5);
745808
}
746809

747810
#[inline(never)]
@@ -773,3 +836,5 @@ fn identity<T>(x: T) -> T {
773836
// EMIT_MIR gvn.wide_ptr_provenance.GVN.diff
774837
// EMIT_MIR gvn.wide_ptr_same_provenance.GVN.diff
775838
// EMIT_MIR gvn.wide_ptr_integer.GVN.diff
839+
// EMIT_MIR gvn.borrowed.GVN.diff
840+
// EMIT_MIR gvn.non_freeze.GVN.diff

‎tests/mir-opt/gvn.slices.GVN.panic-abort.diff

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,9 @@
111111
StorageLive(_7);
112112
StorageLive(_8);
113113
- StorageLive(_9);
114+
- StorageLive(_10);
115+
+ nop;
114116
+ nop;
115-
StorageLive(_10);
116117
StorageLive(_11);
117118
_11 = &(*_1);
118119
_10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind unreachable];
@@ -122,8 +123,9 @@
122123
StorageDead(_11);
123124
_9 = &_10;
124125
- StorageLive(_12);
126+
- StorageLive(_13);
127+
+ nop;
125128
+ nop;
126-
StorageLive(_13);
127129
StorageLive(_14);
128130
- _14 = &(*_4);
129131
+ _14 = &(*_1);
@@ -148,11 +150,12 @@
148150
StorageLive(_17);
149151
StorageLive(_18);
150152
- _18 = (*_15);
151-
+ _18 = (*_9);
153+
+ _18 = _10;
152154
StorageLive(_19);
153155
- _19 = (*_16);
154-
+ _19 = (*_12);
155-
_17 = Eq(move _18, move _19);
156+
- _17 = Eq(move _18, move _19);
157+
+ _19 = _13;
158+
+ _17 = Eq(_10, _13);
156159
switchInt(move _17) -> [0: bb6, otherwise: bb5];
157160
}
158161

@@ -163,8 +166,10 @@
163166
StorageDead(_17);
164167
StorageDead(_16);
165168
StorageDead(_15);
166-
StorageDead(_13);
167-
StorageDead(_10);
169+
- StorageDead(_13);
170+
- StorageDead(_10);
171+
+ nop;
172+
+ nop;
168173
StorageDead(_8);
169174
StorageDead(_7);
170175
- StorageLive(_29);
@@ -213,8 +218,9 @@
213218
StorageLive(_33);
214219
StorageLive(_34);
215220
- StorageLive(_35);
221+
- StorageLive(_36);
222+
+ nop;
216223
+ nop;
217-
StorageLive(_36);
218224
StorageLive(_37);
219225
_37 = &(*_1);
220226
_36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind unreachable];
@@ -224,8 +230,9 @@
224230
StorageDead(_37);
225231
_35 = &_36;
226232
- StorageLive(_38);
233+
- StorageLive(_39);
234+
+ nop;
227235
+ nop;
228-
StorageLive(_39);
229236
StorageLive(_40);
230237
_40 = &(*_29);
231238
_39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind unreachable];
@@ -249,11 +256,12 @@
249256
StorageLive(_43);
250257
StorageLive(_44);
251258
- _44 = (*_41);
252-
+ _44 = (*_35);
259+
+ _44 = _36;
253260
StorageLive(_45);
254261
- _45 = (*_42);
255-
+ _45 = (*_38);
256-
_43 = Eq(move _44, move _45);
262+
- _43 = Eq(move _44, move _45);
263+
+ _45 = _39;
264+
+ _43 = Eq(_36, _39);
257265
switchInt(move _43) -> [0: bb11, otherwise: bb10];
258266
}
259267

@@ -264,8 +272,10 @@
264272
StorageDead(_43);
265273
StorageDead(_42);
266274
StorageDead(_41);
267-
StorageDead(_39);
268-
StorageDead(_36);
275+
- StorageDead(_39);
276+
- StorageDead(_36);
277+
+ nop;
278+
+ nop;
269279
StorageDead(_34);
270280
StorageDead(_33);
271281
_0 = const ();

‎tests/mir-opt/gvn.slices.GVN.panic-unwind.diff

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,9 @@
111111
StorageLive(_7);
112112
StorageLive(_8);
113113
- StorageLive(_9);
114+
- StorageLive(_10);
115+
+ nop;
114116
+ nop;
115-
StorageLive(_10);
116117
StorageLive(_11);
117118
_11 = &(*_1);
118119
_10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind continue];
@@ -122,8 +123,9 @@
122123
StorageDead(_11);
123124
_9 = &_10;
124125
- StorageLive(_12);
126+
- StorageLive(_13);
127+
+ nop;
125128
+ nop;
126-
StorageLive(_13);
127129
StorageLive(_14);
128130
- _14 = &(*_4);
129131
+ _14 = &(*_1);
@@ -148,11 +150,12 @@
148150
StorageLive(_17);
149151
StorageLive(_18);
150152
- _18 = (*_15);
151-
+ _18 = (*_9);
153+
+ _18 = _10;
152154
StorageLive(_19);
153155
- _19 = (*_16);
154-
+ _19 = (*_12);
155-
_17 = Eq(move _18, move _19);
156+
- _17 = Eq(move _18, move _19);
157+
+ _19 = _13;
158+
+ _17 = Eq(_10, _13);
156159
switchInt(move _17) -> [0: bb6, otherwise: bb5];
157160
}
158161

@@ -163,8 +166,10 @@
163166
StorageDead(_17);
164167
StorageDead(_16);
165168
StorageDead(_15);
166-
StorageDead(_13);
167-
StorageDead(_10);
169+
- StorageDead(_13);
170+
- StorageDead(_10);
171+
+ nop;
172+
+ nop;
168173
StorageDead(_8);
169174
StorageDead(_7);
170175
- StorageLive(_29);
@@ -213,8 +218,9 @@
213218
StorageLive(_33);
214219
StorageLive(_34);
215220
- StorageLive(_35);
221+
- StorageLive(_36);
222+
+ nop;
216223
+ nop;
217-
StorageLive(_36);
218224
StorageLive(_37);
219225
_37 = &(*_1);
220226
_36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind continue];
@@ -224,8 +230,9 @@
224230
StorageDead(_37);
225231
_35 = &_36;
226232
- StorageLive(_38);
233+
- StorageLive(_39);
234+
+ nop;
227235
+ nop;
228-
StorageLive(_39);
229236
StorageLive(_40);
230237
_40 = &(*_29);
231238
_39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind continue];
@@ -249,11 +256,12 @@
249256
StorageLive(_43);
250257
StorageLive(_44);
251258
- _44 = (*_41);
252-
+ _44 = (*_35);
259+
+ _44 = _36;
253260
StorageLive(_45);
254261
- _45 = (*_42);
255-
+ _45 = (*_38);
256-
_43 = Eq(move _44, move _45);
262+
- _43 = Eq(move _44, move _45);
263+
+ _45 = _39;
264+
+ _43 = Eq(_36, _39);
257265
switchInt(move _43) -> [0: bb11, otherwise: bb10];
258266
}
259267

@@ -264,8 +272,10 @@
264272
StorageDead(_43);
265273
StorageDead(_42);
266274
StorageDead(_41);
267-
StorageDead(_39);
268-
StorageDead(_36);
275+
- StorageDead(_39);
276+
- StorageDead(_36);
277+
+ nop;
278+
+ nop;
269279
StorageDead(_34);
270280
StorageDead(_33);
271281
_0 = const ();

‎tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
StorageLive(_3);
1818
_5 = const f::promoted[0];
1919
_3 = &(*_5);
20-
_2 = ((*_3).1: E);
20+
- _2 = ((*_3).1: E);
21+
+ _2 = ((*_5).1: E);
2122
StorageLive(_1);
2223
- _1 = ((_2 as A).1: u32);
2324
+ _1 = const 0_u32;

‎tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
StorageLive(_3);
1818
_5 = const f::promoted[0];
1919
_3 = &(*_5);
20-
_2 = ((*_3).1: E);
20+
- _2 = ((*_3).1: E);
21+
+ _2 = ((*_5).1: E);
2122
StorageLive(_1);
2223
- _1 = ((_2 as A).1: u32);
2324
+ _1 = const 0_u32;

‎tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir

Lines changed: 74 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
1010
let mut _8: &&usize;
1111
let _9: &usize;
1212
let mut _10: &&usize;
13-
let mut _15: bool;
13+
let mut _13: bool;
14+
let mut _14: &&usize;
15+
let _15: &usize;
1416
let mut _16: &&usize;
15-
let _17: &usize;
16-
let mut _18: &&usize;
17+
let mut _19: bool;
18+
let mut _20: &&usize;
19+
let _21: &usize;
20+
let mut _22: &&usize;
1721
let mut _23: bool;
1822
let mut _24: &&usize;
1923
let _25: &usize;
2024
let mut _26: &&usize;
21-
let mut _31: bool;
22-
let mut _32: &&usize;
23-
let _33: &usize;
24-
let mut _34: &&usize;
2525
scope 1 {
2626
debug a => _4;
2727
debug b => _5;
@@ -30,208 +30,145 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
3030
scope 2 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) {
3131
debug self => _8;
3232
debug other => _10;
33-
let mut _11: &usize;
34-
let mut _12: &usize;
3533
scope 3 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
36-
debug self => _11;
37-
debug other => _12;
38-
let mut _13: usize;
39-
let mut _14: usize;
34+
debug self => _4;
35+
debug other => _9;
36+
let mut _11: usize;
37+
let mut _12: usize;
4038
}
4139
}
4240
scope 4 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) {
43-
debug self => _16;
44-
debug other => _18;
45-
let mut _19: &usize;
46-
let mut _20: &usize;
41+
debug self => _14;
42+
debug other => _16;
4743
scope 5 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
48-
debug self => _19;
49-
debug other => _20;
50-
let mut _21: usize;
51-
let mut _22: usize;
44+
debug self => _7;
45+
debug other => _15;
46+
let mut _17: usize;
47+
let mut _18: usize;
5248
}
5349
}
5450
scope 6 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) {
55-
debug self => _24;
56-
debug other => _26;
57-
let mut _27: &usize;
58-
let mut _28: &usize;
51+
debug self => _20;
52+
debug other => _22;
5953
scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
60-
debug self => _27;
61-
debug other => _28;
62-
let mut _29: usize;
63-
let mut _30: usize;
54+
debug self => _6;
55+
debug other => _21;
6456
}
6557
}
6658
scope 8 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) {
67-
debug self => _32;
68-
debug other => _34;
69-
let mut _35: &usize;
70-
let mut _36: &usize;
59+
debug self => _24;
60+
debug other => _26;
7161
scope 9 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
72-
debug self => _35;
73-
debug other => _36;
74-
let mut _37: usize;
75-
let mut _38: usize;
62+
debug self => _5;
63+
debug other => _25;
64+
let mut _27: usize;
65+
let mut _28: usize;
7666
}
7767
}
7868
}
7969

8070
bb0: {
81-
StorageLive(_4);
8271
_3 = (*_2);
8372
_4 = &((*_3).0: usize);
84-
StorageLive(_5);
8573
_5 = &((*_3).1: usize);
86-
StorageLive(_6);
8774
_6 = &((*_3).2: usize);
88-
StorageLive(_7);
8975
_7 = &((*_3).3: usize);
90-
StorageLive(_15);
76+
StorageLive(_13);
9177
StorageLive(_8);
9278
_8 = &_4;
9379
StorageLive(_10);
94-
StorageLive(_9);
95-
_9 = _6;
80+
_9 = &((*_3).2: usize);
9681
_10 = &_9;
97-
StorageLive(_11);
98-
StorageLive(_12);
99-
_11 = _4;
100-
_12 = _9;
101-
StorageLive(_13);
102-
_13 = (*_11);
103-
StorageLive(_14);
104-
_14 = (*_12);
105-
_15 = Le(move _13, move _14);
106-
StorageDead(_14);
107-
StorageDead(_13);
108-
StorageDead(_12);
109-
StorageDead(_11);
110-
switchInt(move _15) -> [0: bb1, otherwise: bb2];
82+
_11 = ((*_3).0: usize);
83+
_12 = ((*_3).2: usize);
84+
_13 = Le(_11, _12);
85+
switchInt(move _13) -> [0: bb1, otherwise: bb2];
11186
}
11287

11388
bb1: {
114-
StorageDead(_9);
11589
StorageDead(_10);
11690
StorageDead(_8);
11791
goto -> bb4;
11892
}
11993

12094
bb2: {
121-
StorageDead(_9);
12295
StorageDead(_10);
12396
StorageDead(_8);
124-
StorageLive(_23);
97+
StorageLive(_19);
98+
StorageLive(_14);
99+
_14 = &_7;
125100
StorageLive(_16);
126-
_16 = &_7;
127-
StorageLive(_18);
101+
_15 = &((*_3).1: usize);
102+
_16 = &_15;
128103
StorageLive(_17);
129-
_17 = _5;
130-
_18 = &_17;
131-
StorageLive(_19);
132-
StorageLive(_20);
133-
_19 = _7;
134-
_20 = _17;
135-
StorageLive(_21);
136-
_21 = (*_19);
137-
StorageLive(_22);
138-
_22 = (*_20);
139-
_23 = Le(move _21, move _22);
140-
StorageDead(_22);
141-
StorageDead(_21);
142-
StorageDead(_20);
143-
StorageDead(_19);
144-
switchInt(move _23) -> [0: bb3, otherwise: bb8];
104+
_17 = ((*_3).3: usize);
105+
StorageLive(_18);
106+
_18 = ((*_3).1: usize);
107+
_19 = Le(move _17, move _18);
108+
StorageDead(_18);
109+
StorageDead(_17);
110+
switchInt(move _19) -> [0: bb3, otherwise: bb8];
145111
}
146112

147113
bb3: {
148-
StorageDead(_17);
149-
StorageDead(_18);
150114
StorageDead(_16);
115+
StorageDead(_14);
151116
goto -> bb4;
152117
}
153118

154119
bb4: {
155-
StorageLive(_31);
156-
StorageLive(_24);
157-
_24 = &_6;
158-
StorageLive(_26);
159-
StorageLive(_25);
160-
_25 = _4;
161-
_26 = &_25;
162-
StorageLive(_27);
163-
StorageLive(_28);
164-
_27 = _6;
165-
_28 = _25;
166-
StorageLive(_29);
167-
_29 = (*_27);
168-
StorageLive(_30);
169-
_30 = (*_28);
170-
_31 = Le(move _29, move _30);
171-
StorageDead(_30);
172-
StorageDead(_29);
173-
StorageDead(_28);
174-
StorageDead(_27);
175-
switchInt(move _31) -> [0: bb5, otherwise: bb6];
120+
StorageLive(_23);
121+
StorageLive(_20);
122+
_20 = &_6;
123+
StorageLive(_22);
124+
_21 = &((*_3).0: usize);
125+
_22 = &_21;
126+
_23 = Le(_12, _11);
127+
switchInt(move _23) -> [0: bb5, otherwise: bb6];
176128
}
177129

178130
bb5: {
179-
StorageDead(_25);
180-
StorageDead(_26);
181-
StorageDead(_24);
131+
StorageDead(_22);
132+
StorageDead(_20);
182133
_0 = const false;
183134
goto -> bb7;
184135
}
185136

186137
bb6: {
187-
StorageDead(_25);
138+
StorageDead(_22);
139+
StorageDead(_20);
140+
StorageLive(_24);
141+
_24 = &_5;
142+
StorageLive(_26);
143+
_25 = &((*_3).3: usize);
144+
_26 = &_25;
145+
StorageLive(_27);
146+
_27 = ((*_3).1: usize);
147+
StorageLive(_28);
148+
_28 = ((*_3).3: usize);
149+
_0 = Le(move _27, move _28);
150+
StorageDead(_28);
151+
StorageDead(_27);
188152
StorageDead(_26);
189153
StorageDead(_24);
190-
StorageLive(_32);
191-
_32 = &_5;
192-
StorageLive(_34);
193-
StorageLive(_33);
194-
_33 = _7;
195-
_34 = &_33;
196-
StorageLive(_35);
197-
StorageLive(_36);
198-
_35 = _5;
199-
_36 = _33;
200-
StorageLive(_37);
201-
_37 = (*_35);
202-
StorageLive(_38);
203-
_38 = (*_36);
204-
_0 = Le(move _37, move _38);
205-
StorageDead(_38);
206-
StorageDead(_37);
207-
StorageDead(_36);
208-
StorageDead(_35);
209-
StorageDead(_33);
210-
StorageDead(_34);
211-
StorageDead(_32);
212154
goto -> bb7;
213155
}
214156

215157
bb7: {
216-
StorageDead(_31);
158+
StorageDead(_23);
217159
goto -> bb9;
218160
}
219161

220162
bb8: {
221-
StorageDead(_17);
222-
StorageDead(_18);
223163
StorageDead(_16);
164+
StorageDead(_14);
224165
_0 = const true;
225166
goto -> bb9;
226167
}
227168

228169
bb9: {
229-
StorageDead(_23);
230-
StorageDead(_15);
231-
StorageDead(_7);
232-
StorageDead(_6);
233-
StorageDead(_5);
234-
StorageDead(_4);
170+
StorageDead(_19);
171+
StorageDead(_13);
235172
return;
236173
}
237174
}

‎tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,8 @@
247247
StorageLive(_21);
248248
_21 = &_20;
249249
StorageLive(_22);
250-
_22 = (*_20);
250+
- _22 = (*_20);
251+
+ _22 = _19;
251252
StorageLive(_23);
252253
StorageLive(_24);
253254
_24 = _21;
@@ -394,7 +395,8 @@
394395
StorageLive(_62);
395396
_62 = &_61;
396397
StorageLive(_63);
397-
_63 = (*_61);
398+
- _63 = (*_61);
399+
+ _63 = _60;
398400
StorageLive(_64);
399401
StorageLive(_65);
400402
_65 = ();

‎tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@
260260
StorageLive(_20);
261261
_20 = &_19;
262262
StorageLive(_21);
263-
_21 = (*_19);
263+
- _21 = (*_19);
264+
+ _21 = _18;
264265
StorageLive(_22);
265266
StorageLive(_23);
266267
_23 = _20;
@@ -429,7 +430,8 @@
429430
StorageLive(_67);
430431
_67 = &_66;
431432
StorageLive(_68);
432-
_68 = (*_66);
433+
- _68 = (*_66);
434+
+ _68 = _65;
433435
StorageLive(_69);
434436
StorageLive(_70);
435437
_70 = ();

‎tests/mir-opt/reference_prop.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) {
4949
// CHECK: [[a:_.*]] = const 5_usize;
5050
// CHECK: [[b:_.*]] = &[[a]];
5151
// CHECK: [[d:_.*]] = &[[b]];
52-
// CHECK: [[c:_.*]] = (*[[b]]);
52+
// CHECK: [[c:_.*]] = [[a]];
5353

5454
let a = 5_usize;
5555
let b = &a;
@@ -138,8 +138,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) {
138138
// CHECK: [[a:_.*]] = const 5_usize;
139139
// CHECK: [[b:_.*]] = &[[a]];
140140
// CHECK: [[d:_.*]] = &[[b]];
141-
// FIXME this could be [[a]]
142-
// CHECK: [[c:_.*]] = (*[[b]]);
141+
// CHECK: [[c:_.*]] = [[a]];
143142

144143
let a = 5_usize;
145144
let b = &a;
@@ -363,7 +362,7 @@ fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *con
363362
// CHECK: [[a:_.*]] = const 5_usize;
364363
// CHECK: [[b:_.*]] = &raw const [[a]];
365364
// CHECK: [[d:_.*]] = &[[b]];
366-
// CHECK: [[c:_.*]] = (*[[b]]);
365+
// CHECK: [[c:_.*]] = [[a]];
367366

368367
let a = 5_usize;
369368
let b = &raw const a;
@@ -467,8 +466,7 @@ fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *con
467466
// CHECK: [[a:_.*]] = const 5_usize;
468467
// CHECK: [[b:_.*]] = &raw const [[a]];
469468
// CHECK: [[d:_.*]] = &[[b]];
470-
// FIXME this could be [[a]]
471-
// CHECK: [[c:_.*]] = (*[[b]]);
469+
// CHECK: [[c:_.*]] = [[a]];
472470

473471
let a = 5_usize;
474472
let b = &raw const a;

0 commit comments

Comments
 (0)
This repository has been archived.