@@ -163,7 +163,8 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
163
163
164
164
fn run_pass ( & self , tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
165
165
let def_id = body. source . def_id ( ) ;
166
- let mut allocations = Allocations :: default ( ) ;
166
+ let mut candidates = Candidates :: default ( ) ;
167
+ let mut write_info = WriteInfo :: default ( ) ;
167
168
trace ! ( func = ?tcx. def_path_str( def_id) ) ;
168
169
169
170
let borrowed = rustc_mir_dataflow:: impls:: borrowed_locals ( body) ;
@@ -191,20 +192,15 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
191
192
loop {
192
193
// PERF: Can we do something smarter than recalculating the candidates and liveness
193
194
// results?
194
- let mut candidates = find_candidates (
195
- body,
196
- & borrowed,
197
- & mut allocations. candidates ,
198
- & mut allocations. candidates_reverse ,
199
- ) ;
195
+ candidates. reset_and_find ( body, & borrowed) ;
200
196
trace ! ( ?candidates) ;
201
197
dest_prop_mir_dump ( tcx, body, & points, & live, round_count) ;
202
198
203
199
FilterInformation :: filter_liveness (
204
200
& mut candidates,
205
201
& points,
206
202
& live,
207
- & mut allocations . write_info ,
203
+ & mut write_info,
208
204
body,
209
205
) ;
210
206
@@ -253,20 +249,8 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
253
249
}
254
250
}
255
251
256
- /// Container for the various allocations that we need.
257
- ///
258
- /// We store these here and hand out `&mut` access to them, instead of dropping and recreating them
259
- /// frequently. Everything with a `&'alloc` lifetime points into here.
260
- #[ derive( Default ) ]
261
- struct Allocations {
262
- candidates : FxIndexMap < Local , Vec < Local > > ,
263
- candidates_reverse : FxIndexMap < Local , Vec < Local > > ,
264
- write_info : WriteInfo ,
265
- // PERF: Do this for `MaybeLiveLocals` allocations too.
266
- }
267
-
268
- #[ derive( Debug ) ]
269
- struct Candidates < ' alloc > {
252
+ #[ derive( Debug , Default ) ]
253
+ struct Candidates {
270
254
/// The set of candidates we are considering in this optimization.
271
255
///
272
256
/// We will always merge the key into at most one of its values.
@@ -281,11 +265,12 @@ struct Candidates<'alloc> {
281
265
///
282
266
/// We will still report that we would like to merge `_1` and `_2` in an attempt to allow us to
283
267
/// remove that assignment.
284
- c : & ' alloc mut FxIndexMap < Local , Vec < Local > > ,
268
+ c : FxIndexMap < Local , Vec < Local > > ,
269
+
285
270
/// A reverse index of the `c` set; if the `c` set contains `a => Place { local: b, proj }`,
286
271
/// then this contains `b => a`.
287
272
// PERF: Possibly these should be `SmallVec`s?
288
- reverse : & ' alloc mut FxIndexMap < Local , Vec < Local > > ,
273
+ reverse : FxIndexMap < Local , Vec < Local > > ,
289
274
}
290
275
291
276
//////////////////////////////////////////////////////////
@@ -358,19 +343,40 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> {
358
343
//
359
344
// This section enforces bullet point 2
360
345
361
- struct FilterInformation < ' a , ' body , ' alloc , ' tcx > {
362
- body : & ' body Body < ' tcx > ,
346
+ struct FilterInformation < ' a , ' tcx > {
347
+ body : & ' a Body < ' tcx > ,
363
348
points : & ' a DenseLocationMap ,
364
349
live : & ' a SparseIntervalMatrix < Local , PointIndex > ,
365
- candidates : & ' a mut Candidates < ' alloc > ,
366
- write_info : & ' alloc mut WriteInfo ,
350
+ candidates : & ' a mut Candidates ,
351
+ write_info : & ' a mut WriteInfo ,
367
352
at : Location ,
368
353
}
369
354
370
355
// We first implement some utility functions which we will expose removing candidates according to
371
356
// different needs. Throughout the liveness filtering, the `candidates` are only ever accessed
372
357
// through these methods, and not directly.
373
- impl < ' alloc > Candidates < ' alloc > {
358
+ impl Candidates {
359
+ /// Collects the candidates for merging.
360
+ ///
361
+ /// This is responsible for enforcing the first and third bullet point.
362
+ fn reset_and_find < ' tcx > ( & mut self , body : & Body < ' tcx > , borrowed : & BitSet < Local > ) {
363
+ self . c . clear ( ) ;
364
+ self . reverse . clear ( ) ;
365
+ let mut visitor = FindAssignments { body, candidates : & mut self . c , borrowed } ;
366
+ visitor. visit_body ( body) ;
367
+ // Deduplicate candidates.
368
+ for ( _, cands) in self . c . iter_mut ( ) {
369
+ cands. sort ( ) ;
370
+ cands. dedup ( ) ;
371
+ }
372
+ // Generate the reverse map.
373
+ for ( src, cands) in self . c . iter ( ) {
374
+ for dest in cands. iter ( ) . copied ( ) {
375
+ self . reverse . entry ( dest) . or_default ( ) . push ( * src) ;
376
+ }
377
+ }
378
+ }
379
+
374
380
/// Just `Vec::retain`, but the condition is inverted and we add debugging output
375
381
fn vec_filter_candidates (
376
382
src : Local ,
@@ -445,7 +451,7 @@ enum CandidateFilter {
445
451
Remove ,
446
452
}
447
453
448
- impl < ' a , ' body , ' alloc , ' tcx > FilterInformation < ' a , ' body , ' alloc , ' tcx > {
454
+ impl < ' a , ' tcx > FilterInformation < ' a , ' tcx > {
449
455
/// Filters the set of candidates to remove those that conflict.
450
456
///
451
457
/// The steps we take are exactly those that are outlined at the top of the file. For each
@@ -463,12 +469,12 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
463
469
/// before the statement/terminator will correctly report locals that are read in the
464
470
/// statement/terminator to be live. We are additionally conservative by treating all written to
465
471
/// locals as also being read from.
466
- fn filter_liveness < ' b > (
467
- candidates : & mut Candidates < ' alloc > ,
472
+ fn filter_liveness (
473
+ candidates : & mut Candidates ,
468
474
points : & DenseLocationMap ,
469
475
live : & SparseIntervalMatrix < Local , PointIndex > ,
470
- write_info_alloc : & ' alloc mut WriteInfo ,
471
- body : & ' b Body < ' tcx > ,
476
+ write_info : & mut WriteInfo ,
477
+ body : & Body < ' tcx > ,
472
478
) {
473
479
let mut this = FilterInformation {
474
480
body,
@@ -477,7 +483,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
477
483
candidates,
478
484
// We don't actually store anything at this scope, we just keep things here to be able
479
485
// to reuse the allocation.
480
- write_info : write_info_alloc ,
486
+ write_info,
481
487
// Doesn't matter what we put here, will be overwritten before being used
482
488
at : Location :: START ,
483
489
} ;
@@ -734,40 +740,13 @@ fn places_to_candidate_pair<'tcx>(
734
740
Some ( ( a, b) )
735
741
}
736
742
737
- /// Collects the candidates for merging
738
- ///
739
- /// This is responsible for enforcing the first and third bullet point.
740
- fn find_candidates < ' alloc , ' tcx > (
741
- body : & Body < ' tcx > ,
742
- borrowed : & BitSet < Local > ,
743
- candidates : & ' alloc mut FxIndexMap < Local , Vec < Local > > ,
744
- candidates_reverse : & ' alloc mut FxIndexMap < Local , Vec < Local > > ,
745
- ) -> Candidates < ' alloc > {
746
- candidates. clear ( ) ;
747
- candidates_reverse. clear ( ) ;
748
- let mut visitor = FindAssignments { body, candidates, borrowed } ;
749
- visitor. visit_body ( body) ;
750
- // Deduplicate candidates
751
- for ( _, cands) in candidates. iter_mut ( ) {
752
- cands. sort ( ) ;
753
- cands. dedup ( ) ;
754
- }
755
- // Generate the reverse map
756
- for ( src, cands) in candidates. iter ( ) {
757
- for dest in cands. iter ( ) . copied ( ) {
758
- candidates_reverse. entry ( dest) . or_default ( ) . push ( * src) ;
759
- }
760
- }
761
- Candidates { c : candidates, reverse : candidates_reverse }
762
- }
763
-
764
- struct FindAssignments < ' a , ' alloc , ' tcx > {
743
+ struct FindAssignments < ' a , ' tcx > {
765
744
body : & ' a Body < ' tcx > ,
766
- candidates : & ' alloc mut FxIndexMap < Local , Vec < Local > > ,
745
+ candidates : & ' a mut FxIndexMap < Local , Vec < Local > > ,
767
746
borrowed : & ' a BitSet < Local > ,
768
747
}
769
748
770
- impl < ' tcx > Visitor < ' tcx > for FindAssignments < ' _ , ' _ , ' tcx > {
749
+ impl < ' tcx > Visitor < ' tcx > for FindAssignments < ' _ , ' tcx > {
771
750
fn visit_statement ( & mut self , statement : & Statement < ' tcx > , _: Location ) {
772
751
if let StatementKind :: Assign ( box (
773
752
lhs,
@@ -819,9 +798,9 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool {
819
798
/////////////////////////////////////////////////////////
820
799
// MIR Dump
821
800
822
- fn dest_prop_mir_dump < ' body , ' tcx > (
801
+ fn dest_prop_mir_dump < ' tcx > (
823
802
tcx : TyCtxt < ' tcx > ,
824
- body : & ' body Body < ' tcx > ,
803
+ body : & Body < ' tcx > ,
825
804
points : & DenseLocationMap ,
826
805
live : & SparseIntervalMatrix < Local , PointIndex > ,
827
806
round : usize ,
0 commit comments