@@ -88,6 +88,7 @@ use std::borrow::Cow;
8888
8989use either:: Either ;
9090use rustc_abi:: { self as abi, BackendRepr , FIRST_VARIANT , FieldIdx , Primitive , Size , VariantIdx } ;
91+ use rustc_arena:: DroplessArena ;
9192use rustc_const_eval:: const_eval:: DummyMachine ;
9293use rustc_const_eval:: interpret:: {
9394 ImmTy , Immediate , InterpCx , MemPlaceMeta , MemoryKind , OpTy , Projectable , Scalar ,
@@ -126,7 +127,9 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
126127 // Clone dominators because we need them while mutating the body.
127128 let dominators = body. basic_blocks . dominators ( ) . clone ( ) ;
128129
129- let mut state = VnState :: new ( tcx, body, typing_env, & ssa, dominators, & body. local_decls ) ;
130+ let arena = DroplessArena :: default ( ) ;
131+ let mut state =
132+ VnState :: new ( tcx, body, typing_env, & ssa, dominators, & body. local_decls , & arena) ;
130133
131134 for local in body. args_iter ( ) . filter ( |& local| ssa. is_ssa ( local) ) {
132135 let opaque = state. new_opaque ( body. local_decls [ local] . ty ) ;
@@ -160,8 +163,8 @@ enum AddressKind {
160163 Address ( RawPtrKind ) ,
161164}
162165
163- #[ derive( Debug , PartialEq , Eq , Hash ) ]
164- enum Value < ' tcx > {
166+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
167+ enum Value < ' a , ' tcx > {
165168 // Root values.
166169 /// Used to represent values we know nothing about.
167170 /// The `usize` is a counter incremented by `new_opaque`.
@@ -176,7 +179,7 @@ enum Value<'tcx> {
176179 } ,
177180 /// An aggregate value, either tuple/closure/struct/enum.
178181 /// This does not contain unions, as we cannot reason with the value.
179- Aggregate ( VariantIdx , Vec < VnIndex > ) ,
182+ Aggregate ( VariantIdx , & ' a [ VnIndex ] ) ,
180183 /// A raw pointer aggregate built from a thin pointer and metadata.
181184 RawPtr {
182185 /// Thin pointer component. This is field 0 in MIR.
@@ -212,7 +215,7 @@ enum Value<'tcx> {
212215 } ,
213216}
214217
215- struct VnState < ' body , ' tcx > {
218+ struct VnState < ' body , ' a , ' tcx > {
216219 tcx : TyCtxt < ' tcx > ,
217220 ecx : InterpCx < ' tcx , DummyMachine > ,
218221 local_decls : & ' body LocalDecls < ' tcx > ,
@@ -222,7 +225,7 @@ struct VnState<'body, 'tcx> {
222225 /// Locals that are assigned that value.
223226 // This vector does not hold all the values of `VnIndex` that we create.
224227 rev_locals : IndexVec < VnIndex , SmallVec < [ Local ; 1 ] > > ,
225- values : FxIndexSet < ( Value < ' tcx > , Ty < ' tcx > ) > ,
228+ values : FxIndexSet < ( Value < ' a , ' tcx > , Ty < ' tcx > ) > ,
226229 /// Values evaluated as constants if possible.
227230 evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
228231 /// Counter to generate different values.
@@ -232,16 +235,18 @@ struct VnState<'body, 'tcx> {
232235 ssa : & ' body SsaLocals ,
233236 dominators : Dominators < BasicBlock > ,
234237 reused_locals : DenseBitSet < Local > ,
238+ arena : & ' a DroplessArena ,
235239}
236240
237- impl < ' body , ' tcx > VnState < ' body , ' tcx > {
241+ impl < ' body , ' a , ' tcx > VnState < ' body , ' a , ' tcx > {
238242 fn new (
239243 tcx : TyCtxt < ' tcx > ,
240244 body : & Body < ' tcx > ,
241245 typing_env : ty:: TypingEnv < ' tcx > ,
242246 ssa : & ' body SsaLocals ,
243247 dominators : Dominators < BasicBlock > ,
244248 local_decls : & ' body LocalDecls < ' tcx > ,
249+ arena : & ' a DroplessArena ,
245250 ) -> Self {
246251 // Compute a rough estimate of the number of values in the body from the number of
247252 // statements. This is meant to reduce the number of allocations, but it's all right if
@@ -264,6 +269,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
264269 ssa,
265270 dominators,
266271 reused_locals : DenseBitSet :: new_empty ( local_decls. len ( ) ) ,
272+ arena,
267273 }
268274 }
269275
@@ -272,7 +278,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
272278 }
273279
274280 #[ instrument( level = "trace" , skip( self ) , ret) ]
275- fn insert ( & mut self , ty : Ty < ' tcx > , value : Value < ' tcx > ) -> VnIndex {
281+ fn insert ( & mut self , ty : Ty < ' tcx > , value : Value < ' a , ' tcx > ) -> VnIndex {
276282 let ( index, new) = self . values . insert_full ( ( value, ty) ) ;
277283 let index = VnIndex :: from_usize ( index) ;
278284 if new {
@@ -315,8 +321,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
315321 }
316322
317323 #[ inline]
318- fn get ( & self , index : VnIndex ) -> & Value < ' tcx > {
319- & self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 0
324+ fn get ( & self , index : VnIndex ) -> Value < ' a , ' tcx > {
325+ self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 0
320326 }
321327
322328 #[ inline]
@@ -361,8 +367,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
361367 self . insert ( ty, Value :: Constant { value, disambiguator : 0 } )
362368 }
363369
364- fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : Vec < VnIndex > ) -> VnIndex {
365- self . insert ( ty, Value :: Aggregate ( VariantIdx :: ZERO , values) )
370+ fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : & [ VnIndex ] ) -> VnIndex {
371+ self . insert ( ty, Value :: Aggregate ( VariantIdx :: ZERO , self . arena . alloc_slice ( values) ) )
366372 }
367373
368374 fn insert_deref ( & mut self , ty : Ty < ' tcx > , value : VnIndex ) -> VnIndex {
@@ -388,7 +394,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
388394 } else {
389395 return None ;
390396 } ;
391- let op = match * self . get ( value) {
397+ let op = match self . get ( value) {
392398 _ if ty. is_zst ( ) => ImmTy :: uninit ( ty) . into ( ) ,
393399
394400 Opaque ( _) => return None ,
@@ -608,7 +614,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
608614 if let Value :: Aggregate ( _, fields) = self . get ( value) {
609615 return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
610616 } else if let Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) ) = self . get ( value)
611- && let Value :: Aggregate ( written_variant, fields) = self . get ( * outer_value)
617+ && let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
612618 // This pass is not aware of control-flow, so we do not know whether the
613619 // replacement we are doing is actually reachable. We could be in any arm of
614620 // ```
@@ -633,15 +639,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
633639 ProjectionElem :: Index ( idx) => {
634640 if let Value :: Repeat ( inner, _) = self . get ( value) {
635641 * from_non_ssa_index |= self . locals [ idx] . is_none ( ) ;
636- return Some ( ( projection_ty, * inner) ) ;
642+ return Some ( ( projection_ty, inner) ) ;
637643 }
638644 let idx = self . locals [ idx] ?;
639645 ProjectionElem :: Index ( idx)
640646 }
641647 ProjectionElem :: ConstantIndex { offset, min_length, from_end } => {
642648 match self . get ( value) {
643649 Value :: Repeat ( inner, _) => {
644- return Some ( ( projection_ty, * inner) ) ;
650+ return Some ( ( projection_ty, inner) ) ;
645651 }
646652 Value :: Aggregate ( _, operands) => {
647653 let offset = if from_end {
@@ -731,8 +737,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
731737 let mut place_ty = PlaceTy :: from_ty ( self . local_decls [ place. local ] . ty ) ;
732738 let mut from_non_ssa_index = false ;
733739 for ( index, proj) in place. projection . iter ( ) . enumerate ( ) {
734- if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = * self . get ( value)
735- && let Value :: Address { place : mut pointee, kind, .. } = * self . get ( pointer)
740+ if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = self . get ( value)
741+ && let Value :: Address { place : mut pointee, kind, .. } = self . get ( pointer)
736742 && let AddressKind :: Ref ( BorrowKind :: Shared ) = kind
737743 && let Some ( v) = self . simplify_place_value ( & mut pointee, location)
738744 {
@@ -749,8 +755,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
749755 ( place_ty, value) = self . project ( place_ty, value, proj, & mut from_non_ssa_index) ?;
750756 }
751757
752- if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = * self . get ( value)
753- && let Value :: Address { place : mut pointee, kind, .. } = * self . get ( pointer)
758+ if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = self . get ( value)
759+ && let Value :: Address { place : mut pointee, kind, .. } = self . get ( pointer)
754760 && let AddressKind :: Ref ( BorrowKind :: Shared ) = kind
755761 && let Some ( v) = self . simplify_place_value ( & mut pointee, location)
756762 {
@@ -857,7 +863,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
857863 fn simplify_discriminant ( & mut self , place : VnIndex ) -> Option < VnIndex > {
858864 let enum_ty = self . ty ( place) ;
859865 if enum_ty. is_enum ( )
860- && let Value :: Aggregate ( variant, _) = * self . get ( place)
866+ && let Value :: Aggregate ( variant, _) = self . get ( place)
861867 {
862868 let discr = self . ecx . discriminant_for_variant ( enum_ty, variant) . discard_err ( ) ?;
863869 return Some ( self . insert_scalar ( discr. layout . ty , discr. to_scalar ( ) ) ) ;
@@ -893,12 +899,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
893899 let Some ( & first_field) = fields. first ( ) else {
894900 return None ;
895901 } ;
896- let Value :: Projection ( copy_from_value, _) = * self . get ( first_field) else {
902+ let Value :: Projection ( copy_from_value, _) = self . get ( first_field) else {
897903 return None ;
898904 } ;
899905 // All fields must correspond one-to-one and come from the same aggregate value.
900906 if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
901- if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = * self . get ( v)
907+ if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = self . get ( v)
902908 && copy_from_value == pointer
903909 && from_index. index ( ) == index
904910 {
@@ -910,7 +916,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
910916 }
911917
912918 let mut copy_from_local_value = copy_from_value;
913- if let Value :: Projection ( pointer, proj) = * self . get ( copy_from_value)
919+ if let Value :: Projection ( pointer, proj) = self . get ( copy_from_value)
914920 && let ProjectionElem :: Downcast ( _, read_variant) = proj
915921 {
916922 if variant_index == read_variant {
@@ -968,13 +974,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
968974 }
969975 }
970976
971- let fields: Vec < _ > = field_ops
972- . iter_mut ( )
973- . map ( |op| {
974- self . simplify_operand ( op, location)
975- . unwrap_or_else ( || self . new_opaque ( op. ty ( self . local_decls , self . tcx ) ) )
976- } )
977- . collect ( ) ;
977+ let fields = self . arena . alloc_from_iter ( field_ops. iter_mut ( ) . map ( |op| {
978+ self . simplify_operand ( op, location)
979+ . unwrap_or_else ( || self . new_opaque ( op. ty ( self . local_decls , self . tcx ) ) )
980+ } ) ) ;
978981
979982 let variant_index = match * kind {
980983 AggregateKind :: Array ( ..) | AggregateKind :: Tuple => {
@@ -995,12 +998,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
995998 let mut was_updated = false ;
996999 while let Value :: Cast { kind : CastKind :: PtrToPtr , value : cast_value } =
9971000 self . get ( pointer)
998- && let ty:: RawPtr ( from_pointee_ty, from_mtbl) = self . ty ( * cast_value) . kind ( )
1001+ && let ty:: RawPtr ( from_pointee_ty, from_mtbl) = self . ty ( cast_value) . kind ( )
9991002 && let ty:: RawPtr ( _, output_mtbl) = ty. kind ( )
10001003 && from_mtbl == output_mtbl
10011004 && from_pointee_ty. is_sized ( self . tcx , self . typing_env ( ) )
10021005 {
1003- pointer = * cast_value;
1006+ pointer = cast_value;
10041007 was_updated = true ;
10051008 }
10061009
@@ -1058,9 +1061,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10581061 // To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`,
10591062 // it's fine to get a projection as the type.
10601063 Value :: Cast { kind : CastKind :: PtrToPtr , value : inner }
1061- if self . pointers_have_same_metadata ( self . ty ( * inner) , arg_ty) =>
1064+ if self . pointers_have_same_metadata ( self . ty ( inner) , arg_ty) =>
10621065 {
1063- arg_index = * inner;
1066+ arg_index = inner;
10641067 was_updated = true ;
10651068 continue ;
10661069 }
@@ -1087,15 +1090,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10871090 }
10881091
10891092 let value = match ( op, self . get ( arg_index) ) {
1090- ( UnOp :: Not , Value :: UnaryOp ( UnOp :: Not , inner) ) => return Some ( * inner) ,
1091- ( UnOp :: Neg , Value :: UnaryOp ( UnOp :: Neg , inner) ) => return Some ( * inner) ,
1093+ ( UnOp :: Not , Value :: UnaryOp ( UnOp :: Not , inner) ) => return Some ( inner) ,
1094+ ( UnOp :: Neg , Value :: UnaryOp ( UnOp :: Neg , inner) ) => return Some ( inner) ,
10921095 ( UnOp :: Not , Value :: BinaryOp ( BinOp :: Eq , lhs, rhs) ) => {
1093- Value :: BinaryOp ( BinOp :: Ne , * lhs, * rhs)
1096+ Value :: BinaryOp ( BinOp :: Ne , lhs, rhs)
10941097 }
10951098 ( UnOp :: Not , Value :: BinaryOp ( BinOp :: Ne , lhs, rhs) ) => {
1096- Value :: BinaryOp ( BinOp :: Eq , * lhs, * rhs)
1099+ Value :: BinaryOp ( BinOp :: Eq , lhs, rhs)
10971100 }
1098- ( UnOp :: PtrMetadata , Value :: RawPtr { metadata, .. } ) => return Some ( * metadata) ,
1101+ ( UnOp :: PtrMetadata , Value :: RawPtr { metadata, .. } ) => return Some ( metadata) ,
10991102 // We have an unsizing cast, which assigns the length to wide pointer metadata.
11001103 (
11011104 UnOp :: PtrMetadata ,
@@ -1104,7 +1107,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11041107 value : inner,
11051108 } ,
11061109 ) if let ty:: Slice ( ..) = arg_ty. builtin_deref ( true ) . unwrap ( ) . kind ( )
1107- && let ty:: Array ( _, len) = self . ty ( * inner) . builtin_deref ( true ) . unwrap ( ) . kind ( ) =>
1110+ && let ty:: Array ( _, len) = self . ty ( inner) . builtin_deref ( true ) . unwrap ( ) . kind ( ) =>
11081111 {
11091112 return Some ( self . insert_constant ( Const :: Ty ( self . tcx . types . usize , * len) ) ) ;
11101113 }
@@ -1137,12 +1140,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11371140 && lhs_ty. is_any_ptr ( )
11381141 && let Value :: Cast { kind : CastKind :: PtrToPtr , value : lhs_value } = self . get ( lhs)
11391142 && let Value :: Cast { kind : CastKind :: PtrToPtr , value : rhs_value } = self . get ( rhs)
1140- && let lhs_from = self . ty ( * lhs_value)
1141- && lhs_from == self . ty ( * rhs_value)
1143+ && let lhs_from = self . ty ( lhs_value)
1144+ && lhs_from == self . ty ( rhs_value)
11421145 && self . pointers_have_same_metadata ( lhs_from, lhs_ty)
11431146 {
1144- lhs = * lhs_value;
1145- rhs = * rhs_value;
1147+ lhs = lhs_value;
1148+ rhs = rhs_value;
11461149 if let Some ( lhs_op) = self . try_as_operand ( lhs, location)
11471150 && let Some ( rhs_op) = self . try_as_operand ( rhs, location)
11481151 {
@@ -1276,7 +1279,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
12761279 if op. is_overflowing ( ) {
12771280 let ty = Ty :: new_tup ( self . tcx , & [ self . ty ( result) , self . tcx . types . bool ] ) ;
12781281 let false_val = self . insert_bool ( false ) ;
1279- Some ( self . insert_tuple ( ty, vec ! [ result, false_val] ) )
1282+ Some ( self . insert_tuple ( ty, & [ result, false_val] ) )
12801283 } else {
12811284 Some ( result)
12821285 }
@@ -1329,11 +1332,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13291332 && let ty:: RawPtr ( to_pointee, _) = to. kind ( )
13301333 && to_pointee. is_sized ( self . tcx , self . typing_env ( ) )
13311334 {
1332- from = self . ty ( * pointer) ;
1333- value = * pointer;
1335+ from = self . ty ( pointer) ;
1336+ value = pointer;
13341337 was_updated_this_iteration = true ;
13351338 if from == to {
1336- return Some ( * pointer) ;
1339+ return Some ( pointer) ;
13371340 }
13381341 }
13391342
@@ -1342,7 +1345,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13421345 if let Transmute = kind
13431346 && let Value :: Aggregate ( variant_idx, field_values) = self . get ( value)
13441347 && let Some ( ( field_idx, field_ty) ) =
1345- self . value_is_all_in_one_field ( from, * variant_idx)
1348+ self . value_is_all_in_one_field ( from, variant_idx)
13461349 {
13471350 from = field_ty;
13481351 value = field_values[ field_idx. as_usize ( ) ] ;
@@ -1353,7 +1356,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13531356 }
13541357
13551358 // Various cast-then-cast cases can be simplified.
1356- if let Value :: Cast { kind : inner_kind, value : inner_value } = * self . get ( value) {
1359+ if let Value :: Cast { kind : inner_kind, value : inner_value } = self . get ( value) {
13571360 let inner_from = self . ty ( inner_value) ;
13581361 let new_kind = match ( inner_kind, kind) {
13591362 // Even if there's a narrowing cast in here that's fine, because
@@ -1427,7 +1430,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
14271430 // We have an unsizing cast, which assigns the length to wide pointer metadata.
14281431 if let Value :: Cast { kind, value : from } = self . get ( inner)
14291432 && let CastKind :: PointerCoercion ( ty:: adjustment:: PointerCoercion :: Unsize , _) = kind
1430- && let Some ( from) = self . ty ( * from) . builtin_deref ( true )
1433+ && let Some ( from) = self . ty ( from) . builtin_deref ( true )
14311434 && let ty:: Array ( _, len) = from. kind ( )
14321435 && let Some ( to) = self . ty ( inner) . builtin_deref ( true )
14331436 && let ty:: Slice ( ..) = to. kind ( )
@@ -1585,7 +1588,7 @@ fn op_to_prop_const<'tcx>(
15851588 None
15861589}
15871590
1588- impl < ' tcx > VnState < ' _ , ' tcx > {
1591+ impl < ' tcx > VnState < ' _ , ' _ , ' tcx > {
15891592 /// If either [`Self::try_as_constant`] as [`Self::try_as_place`] succeeds,
15901593 /// returns that result as an [`Operand`].
15911594 fn try_as_operand ( & mut self , index : VnIndex , location : Location ) -> Option < Operand < ' tcx > > {
@@ -1604,7 +1607,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16041607 // This was already constant in MIR, do not change it. If the constant is not
16051608 // deterministic, adding an additional mention of it in MIR will not give the same value as
16061609 // the former mention.
1607- if let Value :: Constant { value, disambiguator : 0 } = * self . get ( index) {
1610+ if let Value :: Constant { value, disambiguator : 0 } = self . get ( index) {
16081611 debug_assert ! ( value. is_deterministic( ) ) ;
16091612 return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : value } ) ;
16101613 }
@@ -1643,7 +1646,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16431646 let place =
16441647 Place { local, projection : self . tcx . mk_place_elems ( projection. as_slice ( ) ) } ;
16451648 return Some ( place) ;
1646- } else if let Value :: Projection ( pointer, proj) = * self . get ( index)
1649+ } else if let Value :: Projection ( pointer, proj) = self . get ( index)
16471650 && ( allow_complex_projection || proj. is_stable_offset ( ) )
16481651 && let Some ( proj) = self . try_as_place_elem ( self . ty ( index) , proj, loc)
16491652 {
@@ -1666,7 +1669,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16661669 }
16671670}
16681671
1669- impl < ' tcx > MutVisitor < ' tcx > for VnState < ' _ , ' tcx > {
1672+ impl < ' tcx > MutVisitor < ' tcx > for VnState < ' _ , ' _ , ' tcx > {
16701673 fn tcx ( & self ) -> TyCtxt < ' tcx > {
16711674 self . tcx
16721675 }
0 commit comments