Simplify Candidate
. · rust-lang/rust@1be2204 (original) (raw)
`@@ -164,8 +164,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
`
164
164
``
165
165
`fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
`
166
166
`let def_id = body.source.def_id();
`
167
``
`-
let mut candidates = FxIndexMap::default();
`
168
``
`-
let mut candidates_reverse = FxIndexMap::default();
`
``
167
`+
let mut candidates = Candidates::default();
`
169
168
`let mut write_info = WriteInfo::default();
`
170
169
`trace!(func = ?tcx.def_path_str(def_id));
`
171
170
``
`@@ -194,12 +193,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
`
194
193
`loop {
`
195
194
`// PERF: Can we do something smarter than recalculating the candidates and liveness
`
196
195
`// results?
`
197
``
`-
let mut candidates = find_candidates(
`
198
``
`-
body,
`
199
``
`-
&borrowed,
`
200
``
`-
&mut candidates,
`
201
``
`-
&mut candidates_reverse,
`
202
``
`-
);
`
``
196
`+
candidates.reset_and_find(body, &borrowed);
`
203
197
`trace!(?candidates);
`
204
198
`dest_prop_mir_dump(tcx, body, &points, &live, round_count);
`
205
199
``
`@@ -256,8 +250,8 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
`
256
250
`}
`
257
251
`}
`
258
252
``
259
``
`-
#[derive(Debug)]
`
260
``
`-
struct Candidates<'alloc> {
`
``
253
`+
#[derive(Debug, Default)]
`
``
254
`+
struct Candidates {
`
261
255
`/// The set of candidates we are considering in this optimization.
`
262
256
`///
`
263
257
`/// We will always merge the key into at most one of its values.
`
`@@ -272,11 +266,12 @@ struct Candidates<'alloc> {
`
272
266
`///
`
273
267
`` /// We will still report that we would like to merge _1
and _2
in an attempt to allow us to
``
274
268
`/// remove that assignment.
`
275
``
`-
c: &'alloc mut FxIndexMap<Local, Vec>,
`
``
269
`+
c: FxIndexMap<Local, Vec>,
`
``
270
+
276
271
`` /// A reverse index of the c
set; if the c
set contains a => Place { local: b, proj }
,
``
277
272
`` /// then this contains b => a
.
``
278
273
`` // PERF: Possibly these should be SmallVec
s?
``
279
``
`-
reverse: &'alloc mut FxIndexMap<Local, Vec>,
`
``
274
`+
reverse: FxIndexMap<Local, Vec>,
`
280
275
`}
`
281
276
``
282
277
`//////////////////////////////////////////////////////////
`
`@@ -349,19 +344,40 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> {
`
349
344
`//
`
350
345
`// This section enforces bullet point 2
`
351
346
``
352
``
`-
struct FilterInformation<'a, 'alloc, 'tcx> {
`
``
347
`+
struct FilterInformation<'a, 'tcx> {
`
353
348
`body: &'a Body<'tcx>,
`
354
349
`points: &'a DenseLocationMap,
`
355
350
`live: &'a SparseIntervalMatrix<Local, PointIndex>,
`
356
``
`-
candidates: &'a mut Candidates<'alloc>,
`
``
351
`+
candidates: &'a mut Candidates,
`
357
352
`write_info: &'a mut WriteInfo,
`
358
353
`at: Location,
`
359
354
`}
`
360
355
``
361
356
`// We first implement some utility functions which we will expose removing candidates according to
`
362
357
`` // different needs. Throughout the liveness filtering, the candidates
are only ever accessed
``
363
358
`// through these methods, and not directly.
`
364
``
`-
impl<'alloc> Candidates<'alloc> {
`
``
359
`+
impl Candidates {
`
``
360
`+
/// Collects the candidates for merging.
`
``
361
`+
///
`
``
362
`+
/// This is responsible for enforcing the first and third bullet point.
`
``
363
`+
fn reset_and_find<'tcx>(&mut self, body: &Body<'tcx>, borrowed: &BitSet) {
`
``
364
`+
self.c.clear();
`
``
365
`+
self.reverse.clear();
`
``
366
`+
let mut visitor = FindAssignments { body, candidates: &mut self.c, borrowed };
`
``
367
`+
visitor.visit_body(body);
`
``
368
`+
// Deduplicate candidates.
`
``
369
`+
for (_, cands) in self.c.iter_mut() {
`
``
370
`+
cands.sort();
`
``
371
`+
cands.dedup();
`
``
372
`+
}
`
``
373
`+
// Generate the reverse map.
`
``
374
`+
for (src, cands) in self.c.iter() {
`
``
375
`+
for dest in cands.iter().copied() {
`
``
376
`+
self.reverse.entry(dest).or_default().push(*src);
`
``
377
`+
}
`
``
378
`+
}
`
``
379
`+
}
`
``
380
+
365
381
`` /// Just Vec::retain
, but the condition is inverted and we add debugging output
``
366
382
`fn vec_filter_candidates(
`
367
383
`src: Local,
`
`@@ -436,7 +452,7 @@ enum CandidateFilter {
`
436
452
`Remove,
`
437
453
`}
`
438
454
``
439
``
`-
impl<'a, 'alloc, 'tcx> FilterInformation<'a, 'alloc, 'tcx> {
`
``
455
`+
impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
`
440
456
`/// Filters the set of candidates to remove those that conflict.
`
441
457
`///
`
442
458
`/// The steps we take are exactly those that are outlined at the top of the file. For each
`
`@@ -455,7 +471,7 @@ impl<'a, 'alloc, 'tcx> FilterInformation<'a, 'alloc, 'tcx> {
`
455
471
`/// statement/terminator to be live. We are additionally conservative by treating all written to
`
456
472
`/// locals as also being read from.
`
457
473
`fn filter_liveness(
`
458
``
`-
candidates: &mut Candidates<'alloc>,
`
``
474
`+
candidates: &mut Candidates,
`
459
475
`points: &DenseLocationMap,
`
460
476
`live: &SparseIntervalMatrix<Local, PointIndex>,
`
461
477
`write_info: &mut WriteInfo,
`
`@@ -725,40 +741,13 @@ fn places_to_candidate_pair<'tcx>(
`
725
741
`Some((a, b))
`
726
742
`}
`
727
743
``
728
``
`-
/// Collects the candidates for merging
`
729
``
`-
///
`
730
``
`-
/// This is responsible for enforcing the first and third bullet point.
`
731
``
`-
fn find_candidates<'alloc, 'tcx>(
`
732
``
`-
body: &Body<'tcx>,
`
733
``
`-
borrowed: &BitSet,
`
734
``
`-
candidates: &'alloc mut FxIndexMap<Local, Vec>,
`
735
``
`-
candidates_reverse: &'alloc mut FxIndexMap<Local, Vec>,
`
736
``
`-
) -> Candidates<'alloc> {
`
737
``
`-
candidates.clear();
`
738
``
`-
candidates_reverse.clear();
`
739
``
`-
let mut visitor = FindAssignments { body, candidates, borrowed };
`
740
``
`-
visitor.visit_body(body);
`
741
``
`-
// Deduplicate candidates
`
742
``
`-
for (_, cands) in candidates.iter_mut() {
`
743
``
`-
cands.sort();
`
744
``
`-
cands.dedup();
`
745
``
`-
}
`
746
``
`-
// Generate the reverse map
`
747
``
`-
for (src, cands) in candidates.iter() {
`
748
``
`-
for dest in cands.iter().copied() {
`
749
``
`-
candidates_reverse.entry(dest).or_default().push(*src);
`
750
``
`-
}
`
751
``
`-
}
`
752
``
`-
Candidates { c: candidates, reverse: candidates_reverse }
`
753
``
`-
}
`
754
``
-
755
``
`-
struct FindAssignments<'a, 'alloc, 'tcx> {
`
``
744
`+
struct FindAssignments<'a, 'tcx> {
`
756
745
`body: &'a Body<'tcx>,
`
757
``
`-
candidates: &'alloc mut FxIndexMap<Local, Vec>,
`
``
746
`+
candidates: &'a mut FxIndexMap<Local, Vec>,
`
758
747
`borrowed: &'a BitSet,
`
759
748
`}
`
760
749
``
761
``
`-
impl<'tcx> Visitor<'tcx> for FindAssignments<'_, '_, 'tcx> {
`
``
750
`+
impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
`
762
751
`fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
`
763
752
`if let StatementKind::Assign(box (
`
764
753
` lhs,
`