8686
8787use std:: borrow:: Cow ;
8888use std:: hash:: { Hash , Hasher } ;
89+ use std:: ops:: Range ;
8990
9091use either:: Either ;
9192use hashbrown:: hash_table:: { Entry , HashTable } ;
@@ -108,6 +109,8 @@ use rustc_middle::mir::visit::*;
108109use rustc_middle:: mir:: * ;
109110use rustc_middle:: ty:: layout:: HasTypingEnv ;
110111use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
112+ use rustc_mir_dataflow:: impls:: MaybeLiveLocals ;
113+ use rustc_mir_dataflow:: { Analysis as _, ResultsCursor } ;
111114use rustc_span:: DUMMY_SP ;
112115use smallvec:: SmallVec ;
113116use tracing:: { debug, instrument, trace} ;
@@ -130,8 +133,37 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
130133 // Clone dominators because we need them while mutating the body.
131134 let dominators = body. basic_blocks . dominators ( ) . clone ( ) ;
132135
136+ let mut borrow_liveness: IndexVec <
137+ Local ,
138+ Option < IndexVec < BasicBlock , Option < Range < usize > > > > ,
139+ > = IndexVec :: from_elem ( None , body. local_decls ( ) ) ;
140+
133141 let immutable_borrows = ImmutableBorrows :: new ( tcx, body, typing_env, & ssa) ;
134142
143+ for ( local, _) in body. local_decls . iter_enumerated ( ) {
144+ if !immutable_borrows. locals . contains ( local) {
145+ continue ;
146+ }
147+ if immutable_borrows. always_live . contains ( local) {
148+ continue ;
149+ }
150+ borrow_liveness[ local] = Some ( IndexVec :: from_elem ( None , & body. basic_blocks ) ) ;
151+ }
152+
153+ let mut liveness = MaybeLiveLocals
154+ . iterate_to_fixpoint ( tcx, body, Some ( "MaybeLiveLocals-GVN" ) )
155+ . into_results_cursor ( body) ;
156+
157+ for ( bb, bb_data) in traversal:: preorder ( body) {
158+ liveness. seek_to_block_end ( bb) ;
159+ let live_locals = liveness. get ( ) ;
160+ for local in live_locals. iter ( ) {
161+ if let Some ( ref mut liveness) = borrow_liveness[ local] {
162+ liveness[ bb] = Some ( 0 ..bb_data. statements . len ( ) ) ;
163+ }
164+ }
165+ }
166+
135167 let arena = DroplessArena :: default ( ) ;
136168 let mut state = VnState :: new (
137169 tcx,
@@ -141,7 +173,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
141173 dominators,
142174 & body. local_decls ,
143175 & arena,
144- immutable_borrows ,
176+ borrow_liveness ,
145177 ) ;
146178
147179 for local in body. args_iter ( ) . filter ( |& local| ssa. is_ssa ( local) ) {
@@ -382,7 +414,7 @@ struct VnState<'body, 'a, 'tcx> {
382414 dominators : Dominators < BasicBlock > ,
383415 reused_locals : DenseBitSet < Local > ,
384416 arena : & ' a DroplessArena ,
385- immutable_borrows : ImmutableBorrows ,
417+ borrow_liveness : IndexVec < Local , Option < IndexVec < BasicBlock , Option < Range < usize > > > > > ,
386418}
387419
388420impl < ' body , ' a , ' tcx > VnState < ' body , ' a , ' tcx > {
@@ -394,7 +426,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
394426 dominators : Dominators < BasicBlock > ,
395427 local_decls : & ' body LocalDecls < ' tcx > ,
396428 arena : & ' a DroplessArena ,
397- immutable_borrows : ImmutableBorrows ,
429+ borrow_liveness : IndexVec < Local , Option < IndexVec < BasicBlock , Option < Range < usize > > > > > ,
398430 ) -> Self {
399431 // Compute a rough estimate of the number of values in the body from the number of
400432 // statements. This is meant to reduce the number of allocations, but it's all right if
@@ -416,7 +448,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
416448 dominators,
417449 reused_locals : DenseBitSet :: new_empty ( local_decls. len ( ) ) ,
418450 arena,
419- immutable_borrows ,
451+ borrow_liveness ,
420452 }
421453 }
422454
@@ -1870,10 +1902,11 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
18701902 if !self . ssa . assignment_dominates ( & self . dominators , other, loc) {
18711903 return false ;
18721904 }
1873- if self . immutable_borrows . locals . contains ( other)
1874- && !self . immutable_borrows . always_live . contains ( other)
1875- {
1876- return false ;
1905+ if let Some ( ref liveness) = self . borrow_liveness [ other] {
1906+ return liveness[ loc. block ]
1907+ . as_ref ( )
1908+ . map ( |range| range. contains ( & loc. statement_index ) )
1909+ . unwrap_or ( false ) ;
18771910 }
18781911 return true ;
18791912 } )
0 commit comments