@@ -7,10 +7,10 @@ use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Loc
7
7
use rustc_middle:: traits:: query:: DropckOutlivesResult ;
8
8
use rustc_middle:: ty:: relate:: Relate ;
9
9
use rustc_middle:: ty:: { Ty , TyCtxt , TypeVisitable , TypeVisitableExt } ;
10
- use rustc_mir_dataflow:: impls:: MaybeInitializedPlaces ;
10
+ use rustc_mir_dataflow:: impls:: { FilteringMovePathIndexMapper , MaybeInitializedPlaces2 } ;
11
11
use rustc_mir_dataflow:: move_paths:: { HasMoveData , MoveData , MovePathIndex } ;
12
12
use rustc_mir_dataflow:: points:: { DenseLocationMap , PointIndex } ;
13
- use rustc_mir_dataflow:: { Analysis , ResultsCursor } ;
13
+ use rustc_mir_dataflow:: { Analysis , ResultsCursor , on_all_children_bits } ;
14
14
use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span } ;
15
15
use rustc_trait_selection:: error_reporting:: InferCtxtErrorExt ;
16
16
use rustc_trait_selection:: traits:: ObligationCtxt ;
@@ -45,13 +45,29 @@ pub(super) fn trace<'tcx>(
45
45
boring_locals : Vec < Local > ,
46
46
) {
47
47
let local_use_map = & LocalUseMap :: build ( & relevant_live_locals, location_map, typeck. body ) ;
48
+
49
+ let mut dense_mpis = smallvec:: SmallVec :: new ( ) ;
50
+ for & local in relevant_live_locals. iter ( ) {
51
+ let Some ( mpi) = move_data. rev_lookup . find_local ( local) else { unreachable ! ( ) } ;
52
+
53
+ // We only compute initializedness in drop-liveness on locals with drop points.
54
+ if local_use_map. drops ( local) . next ( ) . is_none ( ) {
55
+ continue ;
56
+ }
57
+
58
+ on_all_children_bits ( move_data, mpi, |child| {
59
+ dense_mpis. push ( child) ;
60
+ } ) ;
61
+ }
62
+
48
63
let cx = LivenessContext {
49
64
typeck,
50
65
flow_inits : None ,
51
66
location_map,
52
67
local_use_map,
53
68
move_data,
54
69
drop_data : FxIndexMap :: default ( ) ,
70
+ dense_mpis,
55
71
} ;
56
72
57
73
let mut results = LivenessResults :: new ( cx) ;
@@ -81,11 +97,15 @@ struct LivenessContext<'a, 'typeck, 'tcx> {
81
97
82
98
/// Results of dataflow tracking which variables (and paths) have been
83
99
/// initialized. Computed lazily when needed by drop-liveness.
84
- flow_inits : Option < ResultsCursor < ' a , ' tcx , MaybeInitializedPlaces < ' a , ' tcx > > > ,
100
+ flow_inits : Option <
101
+ ResultsCursor < ' a , ' tcx , MaybeInitializedPlaces2 < ' a , ' tcx , FilteringMovePathIndexMapper > > ,
102
+ > ,
85
103
86
104
/// Index indicating where each variable is assigned, used, or
87
105
/// dropped.
88
106
local_use_map : & ' a LocalUseMap ,
107
+
108
+ dense_mpis : smallvec:: SmallVec < [ MovePathIndex ; 1 ] > ,
89
109
}
90
110
91
111
struct DropData < ' tcx > {
@@ -468,7 +488,10 @@ impl<'a, 'typeck, 'tcx> LivenessContext<'a, 'typeck, 'tcx> {
468
488
///
469
489
/// This happens as part of the drop-liveness computation: it's the only place checking for
470
490
/// maybe-initializedness of `MovePathIndex`es.
471
- fn flow_inits ( & mut self ) -> & mut ResultsCursor < ' a , ' tcx , MaybeInitializedPlaces < ' a , ' tcx > > {
491
+ fn flow_inits (
492
+ & mut self ,
493
+ ) -> & mut ResultsCursor < ' a , ' tcx , MaybeInitializedPlaces2 < ' a , ' tcx , FilteringMovePathIndexMapper > >
494
+ {
472
495
self . flow_inits . get_or_insert_with ( || {
473
496
let tcx = self . typeck . tcx ( ) ;
474
497
let body = self . typeck . body ;
@@ -484,9 +507,85 @@ impl<'a, 'typeck, 'tcx> LivenessContext<'a, 'typeck, 'tcx> {
484
507
// a much, much smaller domain: in our benchmarks, when it's not zero (the most likely
485
508
// case), there are a few dozens compared to e.g. thousands or tens of thousands of
486
509
// locals and move paths.
487
- let flow_inits = MaybeInitializedPlaces :: new ( tcx, body, self . move_data )
510
+ // eprintln!(
511
+ // "computing flow_inits: {} MPIs total, {} relevant MPIs",
512
+ // self.move_data.move_paths.len(),
513
+ // self.dense_mpis.len()
514
+ // );
515
+
516
+ // FIXME: use the sparse vec + bitset metadata trick instead of a map!
517
+
518
+ // let map_timer = std::time::Instant::now();
519
+ // let mut sparse_map = FxIndexMap::default();
520
+ // for (idx, &dense_idx) in self.dense_mpis.iter().enumerate() {
521
+ // let sparse_idx = SparseMovePathIndex::from_usize(idx);
522
+ // sparse_map.insert(dense_idx, sparse_idx);
523
+ // }
524
+ // // for local in body.args_iter() {
525
+ // // let Some(mpi) = self.move_data.rev_lookup.find_local(local) else { unreachable!() };
526
+ // // self.dense_mpis.push(mpi);
527
+ // // map.insert(mpi, self.dense_mpis.len());
528
+ // // }
529
+
530
+ // let map_len = sparse_map.len();
531
+ // let mapper = FilteringMovePathIndexMapper { sparse_map };
532
+ // let map_elapsed = map_timer.elapsed();
533
+
534
+ // // let mapper = rustc_mir_dataflow::impls::NoOpMapper;
535
+
536
+ // let sparse_bitset_timer = std::time::Instant::now();
537
+
538
+ // // let mut sparse_bitset = Sparse32::new(self.dense_mpis.len());
539
+ // // // FIXME: do this in asc order to keep idxes stable and not shuffle the vec inside
540
+ // // for &dense_idx in self.dense_mpis.iter() {
541
+ // // sparse_bitset.insert(dense_idx);
542
+ // // }
543
+
544
+ // let sparse_bitset = Sparse32::new(&self.dense_mpis);
545
+
546
+ // // let sparse_bitset_elapsed = sparse_bitset_timer.elapsed();
547
+ // // let sparse_bitset_len = sparse_bitset.dense.len();
548
+
549
+ // // let sparse_bitset_timer = std::time::Instant::now();
550
+
551
+ // let mut sparse_bitset = Sparse::new(
552
+ // 1 + self.dense_mpis.iter().max().unwrap().as_usize(),
553
+ // self.dense_mpis.len(),
554
+ // );
555
+ // // FIXME: do this in asc order to keep idxes stable and not shuffle the vec inside
556
+ // for &dense_idx in self.dense_mpis.iter() {
557
+ // sparse_bitset.insert(dense_idx);
558
+ // }
559
+ // // also: move this into the sparse ctor, so that prefixes can be computed there after inserting stuff
560
+
561
+ // sparse_bitset.compute_prefixes();
562
+
563
+ // // let sparse_bitset_elapsed = sparse_bitset_timer.elapsed();
564
+ // // let sparse_bitset_len = sparse_bitset.sparse.len();
565
+
566
+ // let mapper = sparse_bitset;
567
+
568
+ // let timer = std::time::Instant::now();
569
+ let flow_inits = MaybeInitializedPlaces2 :: new ( tcx, body, self . move_data )
570
+ . filter_move_paths ( & self . dense_mpis )
571
+ // .with_mapper(mapper)
488
572
. iterate_to_fixpoint ( tcx, body, Some ( "borrowck" ) )
489
573
. into_results_cursor ( body) ;
574
+ // let elapsed = timer.elapsed();
575
+
576
+ // use std::sync::OnceLock;
577
+ // static PROFILE: OnceLock<bool> = OnceLock::new();
578
+ // if *PROFILE.get_or_init(|| std::env::var("LETSGO1").is_ok()) {
579
+ // eprintln!(
580
+ // "flow_inits took {:?} ns, map of {} took: {} ns, sparse bitset of {} took {} ns, {:?}",
581
+ // elapsed.as_nanos(),
582
+ // map_len,
583
+ // map_elapsed.as_nanos(),
584
+ // sparse_bitset_len,
585
+ // sparse_bitset_elapsed.as_nanos(),
586
+ // body.span,
587
+ // );
588
+ // }
490
589
flow_inits
491
590
} )
492
591
}
@@ -502,13 +601,24 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
502
601
/// the cursor to the desired location.
503
602
fn initialized_at_curr_loc ( & mut self , mpi : MovePathIndex ) -> bool {
504
603
let flow_inits = self . flow_inits ( ) ;
604
+ let analysis = flow_inits. analysis ( ) ;
605
+ let idx = analysis
606
+ . map_index ( mpi)
607
+ . unwrap_or_else ( || unreachable ! ( "dataflow is somehow missing MPI {mpi:?}" ) ) ;
505
608
let state = flow_inits. get ( ) ;
506
- if state. contains ( mpi ) {
609
+ if state. contains ( idx ) {
507
610
return true ;
508
611
}
509
612
510
- let move_paths = & flow_inits. analysis ( ) . move_data ( ) . move_paths ;
511
- move_paths[ mpi] . find_descendant ( move_paths, |mpi| state. contains ( mpi) ) . is_some ( )
613
+ let move_paths = & analysis. move_data ( ) . move_paths ;
614
+ move_paths[ mpi]
615
+ . find_descendant ( move_paths, |mpi| {
616
+ let idx = analysis
617
+ . map_index ( mpi)
618
+ . unwrap_or_else ( || unreachable ! ( "dataflow is somehow missing MPI {mpi:?}" ) ) ;
619
+ state. contains ( idx)
620
+ } )
621
+ . is_some ( )
512
622
}
513
623
514
624
/// Returns `true` if the local variable (or some part of it) is initialized in
0 commit comments