Skip to content

Commit d2d24e3

Browse files
committed
Auto merge of #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

+14-27
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

+17-1
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

+2-1
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

+2-1
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

+43-12
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

+3-3
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

+11-11
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

-40
This file was deleted.

0 commit comments

Comments
 (0)