@@ -382,7 +382,7 @@ struct VnState<'body, 'a, 'tcx> {
382382 dominators : Dominators < BasicBlock > ,
383383 reused_locals : DenseBitSet < Local > ,
384384 arena : & ' a DroplessArena ,
385- immutable_borrows : ImmutableBorrows ,
385+ immutable_borrows : ImmutableBorrows < ' a > ,
386386}
387387
388388impl < ' body , ' a , ' tcx > VnState < ' body , ' a , ' tcx > {
@@ -394,7 +394,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
394394 dominators : Dominators < BasicBlock > ,
395395 local_decls : & ' body LocalDecls < ' tcx > ,
396396 arena : & ' a DroplessArena ,
397- immutable_borrows : ImmutableBorrows ,
397+ immutable_borrows : ImmutableBorrows < ' a > ,
398398 ) -> Self {
399399 // Compute a rough estimate of the number of values in the body from the number of
400400 // statements. This is meant to reduce the number of allocations, but it's all right if
@@ -1254,8 +1254,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
12541254 // Allow introducing places with non-constant offsets, as those are still better than
12551255 // reconstructing an aggregate. But avoid creating `*a = copy (*b)`, as they might be
12561256 // aliases resulting in overlapping assignments.
1257- let allow_complex_projection =
1258- lhs. projection [ ..] . iter ( ) . all ( PlaceElem :: is_stable_offset) ;
1257+ let allow_complex_projection = lhs. is_stable_offset ( ) ;
12591258 if let Some ( place) = self . try_as_place ( value, location, allow_complex_projection) {
12601259 self . reused_locals . insert ( place. local ) ;
12611260 * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
@@ -1990,18 +1989,19 @@ impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> {
19901989 }
19911990}
19921991
1993- struct ImmutableBorrows {
1992+ struct ImmutableBorrows < ' a > {
19941993 locals : DenseBitSet < Local > ,
19951994 always_live : DenseBitSet < Local > ,
1995+ ssa : & ' a SsaLocals ,
19961996}
19971997
1998- impl ImmutableBorrows {
1998+ impl < ' a > ImmutableBorrows < ' a > {
19991999 fn new < ' tcx > (
20002000 tcx : TyCtxt < ' tcx > ,
20012001 body : & Body < ' tcx > ,
20022002 typing_env : ty:: TypingEnv < ' tcx > ,
2003- ssa : & SsaLocals ,
2004- ) -> ImmutableBorrows {
2003+ ssa : & ' a SsaLocals ,
2004+ ) -> ImmutableBorrows < ' a > {
20052005 let mut locals: DenseBitSet < Local > = DenseBitSet :: new_empty ( body. local_decls ( ) . len ( ) ) ;
20062006 for ( local, decl) in body. local_decls . iter_enumerated ( ) {
20072007 if let Some ( Mutability :: Not ) = decl. ty . ref_mutability ( )
@@ -2017,21 +2017,27 @@ impl ImmutableBorrows {
20172017 always_live. insert ( local) ;
20182018 }
20192019 }
2020- let mut always_live_immutable_borrows = ImmutableBorrows { locals, always_live } ;
2020+ let mut always_live_immutable_borrows = ImmutableBorrows { locals, always_live, ssa } ;
20212021 for ( bb, bb_data) in body. basic_blocks . iter_enumerated ( ) {
20222022 always_live_immutable_borrows. visit_basic_block_data ( bb, bb_data) ;
20232023 }
20242024 always_live_immutable_borrows
20252025 }
20262026}
20272027
2028- impl < ' tcx > Visitor < ' tcx > for ImmutableBorrows {
2028+ impl < ' tcx , ' a > Visitor < ' tcx > for ImmutableBorrows < ' a > {
20292029 fn visit_assign ( & mut self , place : & Place < ' tcx > , rvalue : & Rvalue < ' tcx > , _: Location ) {
20302030 if let Some ( local) = place. as_local ( )
20312031 && self . locals . contains ( local)
2032- && let Rvalue :: Use ( Operand :: Constant ( _) ) = rvalue
20332032 {
2034- self . always_live . insert ( local) ;
2033+ if let Rvalue :: Use ( Operand :: Constant ( _) ) = rvalue {
2034+ self . always_live . insert ( local) ;
2035+ } else if let Rvalue :: Ref ( _, _, place) = rvalue
2036+ && place. is_stable_offset ( )
2037+ && self . ssa . is_ssa ( place. local )
2038+ {
2039+ self . always_live . insert ( local) ;
2040+ }
20352041 } ;
20362042 }
20372043}
0 commit comments