@@ -89,6 +89,7 @@ use std::borrow::Cow;
8989use either:: Either ;
9090use itertools:: Itertools as _;
9191use rustc_abi:: { self as abi, BackendRepr , FIRST_VARIANT , FieldIdx , Primitive , Size , VariantIdx } ;
92+ use rustc_arena:: DroplessArena ;
9293use rustc_const_eval:: const_eval:: DummyMachine ;
9394use rustc_const_eval:: interpret:: {
9495 ImmTy , Immediate , InterpCx , MemPlaceMeta , MemoryKind , OpTy , Projectable , Scalar ,
@@ -127,7 +128,9 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
127128 // Clone dominators because we need them while mutating the body.
128129 let dominators = body. basic_blocks . dominators ( ) . clone ( ) ;
129130
130- let mut state = VnState :: new ( tcx, body, typing_env, & ssa, dominators, & body. local_decls ) ;
131+ let arena = DroplessArena :: default ( ) ;
132+ let mut state =
133+ VnState :: new ( tcx, body, typing_env, & ssa, dominators, & body. local_decls , & arena) ;
131134
132135 for local in body. args_iter ( ) . filter ( |& local| ssa. is_ssa ( local) ) {
133136 let opaque = state. new_opaque ( body. local_decls [ local] . ty ) ;
@@ -161,8 +164,8 @@ enum AddressKind {
161164 Address ( RawPtrKind ) ,
162165}
163166
164- #[ derive( Debug , PartialEq , Eq , Hash ) ]
165- enum Value < ' tcx > {
167+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
168+ enum Value < ' a , ' tcx > {
166169 // Root values.
167170 /// Used to represent values we know nothing about.
168171 /// The `usize` is a counter incremented by `new_opaque`.
@@ -177,7 +180,7 @@ enum Value<'tcx> {
177180 } ,
178181 /// An aggregate value, either tuple/closure/struct/enum.
179182 /// This does not contain unions, as we cannot reason with the value.
180- Aggregate ( VariantIdx , Vec < VnIndex > ) ,
183+ Aggregate ( VariantIdx , & ' a [ VnIndex ] ) ,
181184 /// A raw pointer aggregate built from a thin pointer and metadata.
182185 RawPtr {
183186 /// Thin pointer component. This is field 0 in MIR.
@@ -211,7 +214,7 @@ enum Value<'tcx> {
211214 } ,
212215}
213216
214- struct VnState < ' body , ' tcx > {
217+ struct VnState < ' body , ' a , ' tcx > {
215218 tcx : TyCtxt < ' tcx > ,
216219 ecx : InterpCx < ' tcx , DummyMachine > ,
217220 local_decls : & ' body LocalDecls < ' tcx > ,
@@ -221,7 +224,7 @@ struct VnState<'body, 'tcx> {
221224 /// Locals that are assigned that value.
222225 // This vector does not hold all the values of `VnIndex` that we create.
223226 rev_locals : IndexVec < VnIndex , SmallVec < [ Local ; 1 ] > > ,
224- values : FxIndexSet < ( Value < ' tcx > , Ty < ' tcx > ) > ,
227+ values : FxIndexSet < ( Value < ' a , ' tcx > , Ty < ' tcx > ) > ,
225228 /// Values evaluated as constants if possible.
226229 evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
227230 /// Counter to generate different values.
@@ -231,16 +234,18 @@ struct VnState<'body, 'tcx> {
231234 ssa : & ' body SsaLocals ,
232235 dominators : Dominators < BasicBlock > ,
233236 reused_locals : DenseBitSet < Local > ,
237+ arena : & ' a DroplessArena ,
234238}
235239
236- impl < ' body , ' tcx > VnState < ' body , ' tcx > {
240+ impl < ' body , ' a , ' tcx > VnState < ' body , ' a , ' tcx > {
237241 fn new (
238242 tcx : TyCtxt < ' tcx > ,
239243 body : & Body < ' tcx > ,
240244 typing_env : ty:: TypingEnv < ' tcx > ,
241245 ssa : & ' body SsaLocals ,
242246 dominators : Dominators < BasicBlock > ,
243247 local_decls : & ' body LocalDecls < ' tcx > ,
248+ arena : & ' a DroplessArena ,
244249 ) -> Self {
245250 // Compute a rough estimate of the number of values in the body from the number of
246251 // statements. This is meant to reduce the number of allocations, but it's all right if
@@ -263,6 +268,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
263268 ssa,
264269 dominators,
265270 reused_locals : DenseBitSet :: new_empty ( local_decls. len ( ) ) ,
271+ arena,
266272 }
267273 }
268274
@@ -271,7 +277,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
271277 }
272278
273279 #[ instrument( level = "trace" , skip( self ) , ret) ]
274- fn insert ( & mut self , ty : Ty < ' tcx > , value : Value < ' tcx > ) -> VnIndex {
280+ fn insert ( & mut self , ty : Ty < ' tcx > , value : Value < ' a , ' tcx > ) -> VnIndex {
275281 let ( index, new) = self . values . insert_full ( ( value, ty) ) ;
276282 let index = VnIndex :: from_usize ( index) ;
277283 if new {
@@ -314,8 +320,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
314320 }
315321
316322 #[ inline]
317- fn get ( & self , index : VnIndex ) -> & Value < ' tcx > {
318- & self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 0
323+ fn get ( & self , index : VnIndex ) -> Value < ' a , ' tcx > {
324+ self . values . get_index ( index. as_usize ( ) ) . unwrap ( ) . 0
319325 }
320326
321327 #[ inline]
@@ -360,8 +366,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
360366 self . insert ( ty, Value :: Constant { value, disambiguator : 0 } )
361367 }
362368
363- fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : Vec < VnIndex > ) -> VnIndex {
364- self . insert ( ty, Value :: Aggregate ( VariantIdx :: ZERO , values) )
369+ fn insert_tuple ( & mut self , ty : Ty < ' tcx > , values : & [ VnIndex ] ) -> VnIndex {
370+ self . insert ( ty, Value :: Aggregate ( VariantIdx :: ZERO , self . arena . alloc_slice ( values) ) )
365371 }
366372
367373 fn insert_deref ( & mut self , ty : Ty < ' tcx > , value : VnIndex ) -> VnIndex {
@@ -387,7 +393,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
387393 } else {
388394 return None ;
389395 } ;
390- let op = match * self . get ( value) {
396+ let op = match self . get ( value) {
391397 _ if ty. is_zst ( ) => ImmTy :: uninit ( ty) . into ( ) ,
392398
393399 Opaque ( _) => return None ,
@@ -602,7 +608,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
602608 if let Value :: Aggregate ( _, fields) = self . get ( value) {
603609 return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
604610 } else if let Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) ) = self . get ( value)
605- && let Value :: Aggregate ( written_variant, fields) = self . get ( * outer_value)
611+ && let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
606612 // This pass is not aware of control-flow, so we do not know whether the
607613 // replacement we are doing is actually reachable. We could be in any arm of
608614 // ```
@@ -627,15 +633,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
627633 ProjectionElem :: Index ( idx) => {
628634 if let Value :: Repeat ( inner, _) = self . get ( value) {
629635 * from_non_ssa_index |= self . locals [ idx] . is_none ( ) ;
630- return Some ( ( projection_ty, * inner) ) ;
636+ return Some ( ( projection_ty, inner) ) ;
631637 }
632638 let idx = self . locals [ idx] ?;
633639 ProjectionElem :: Index ( idx)
634640 }
635641 ProjectionElem :: ConstantIndex { offset, min_length, from_end } => {
636642 match self . get ( value) {
637643 Value :: Repeat ( inner, _) => {
638- return Some ( ( projection_ty, * inner) ) ;
644+ return Some ( ( projection_ty, inner) ) ;
639645 }
640646 Value :: Aggregate ( _, operands) => {
641647 let offset = if from_end {
@@ -725,8 +731,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
725731 let mut place_ty = PlaceTy :: from_ty ( self . local_decls [ place. local ] . ty ) ;
726732 let mut from_non_ssa_index = false ;
727733 for ( index, proj) in place. projection . iter ( ) . enumerate ( ) {
728- if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = * self . get ( value)
729- && let Value :: Address { place : mut pointee, kind, .. } = * self . get ( pointer)
734+ if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = self . get ( value)
735+ && let Value :: Address { place : mut pointee, kind, .. } = self . get ( pointer)
730736 && let AddressKind :: Ref ( BorrowKind :: Shared ) = kind
731737 && let Some ( v) = self . simplify_place_value ( & mut pointee, location)
732738 {
@@ -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 {
@@ -861,7 +867,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
861867 fn simplify_discriminant ( & mut self , place : VnIndex ) -> Option < VnIndex > {
862868 let enum_ty = self . ty ( place) ;
863869 if enum_ty. is_enum ( )
864- && let Value :: Aggregate ( variant, _) = * self . get ( place)
870+ && let Value :: Aggregate ( variant, _) = self . get ( place)
865871 {
866872 let discr = self . ecx . discriminant_for_variant ( enum_ty, variant) . discard_err ( ) ?;
867873 return Some ( self . insert_scalar ( discr. layout . ty , discr. to_scalar ( ) ) ) ;
@@ -893,11 +899,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
893899 fields : & [ VnIndex ] ,
894900 ) -> Option < VnIndex > {
895901 let Some ( & first_field) = fields. first ( ) else { return None } ;
896- let Value :: Projection ( copy_from_value, _) = * self . get ( first_field) else { return None } ;
902+ let Value :: Projection ( copy_from_value, _) = self . get ( first_field) else { return None } ;
897903
898904 // All fields must correspond one-to-one and come from the same aggregate value.
899905 if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
900- if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = * self . get ( v)
906+ if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = self . get ( v)
901907 && copy_from_value == pointer
902908 && from_index. index ( ) == index
903909 {
@@ -909,7 +915,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
909915 }
910916
911917 let mut copy_from_local_value = copy_from_value;
912- if let Value :: Projection ( pointer, proj) = * self . get ( copy_from_value)
918+ if let Value :: Projection ( pointer, proj) = self . get ( copy_from_value)
913919 && let ProjectionElem :: Downcast ( _, read_variant) = proj
914920 {
915921 if variant_index == read_variant {
@@ -954,13 +960,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
954960 }
955961 }
956962
957- let fields: Vec < _ > = field_ops
958- . iter_mut ( )
959- . map ( |op| {
960- self . simplify_operand ( op, location)
961- . unwrap_or_else ( || self . new_opaque ( op. ty ( self . local_decls , self . tcx ) ) )
962- } )
963- . collect ( ) ;
963+ let fields = self . arena . alloc_from_iter ( field_ops. iter_mut ( ) . map ( |op| {
964+ self . simplify_operand ( op, location)
965+ . unwrap_or_else ( || self . new_opaque ( op. ty ( self . local_decls , self . tcx ) ) )
966+ } ) ) ;
964967
965968 let variant_index = match * kind {
966969 AggregateKind :: Array ( ..) | AggregateKind :: Tuple => {
@@ -981,12 +984,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
981984 let mut was_updated = false ;
982985 while let Value :: Cast { kind : CastKind :: PtrToPtr , value : cast_value } =
983986 self . get ( pointer)
984- && let ty:: RawPtr ( from_pointee_ty, from_mtbl) = self . ty ( * cast_value) . kind ( )
987+ && let ty:: RawPtr ( from_pointee_ty, from_mtbl) = self . ty ( cast_value) . kind ( )
985988 && let ty:: RawPtr ( _, output_mtbl) = ty. kind ( )
986989 && from_mtbl == output_mtbl
987990 && from_pointee_ty. is_sized ( self . tcx , self . typing_env ( ) )
988991 {
989- pointer = * cast_value;
992+ pointer = cast_value;
990993 was_updated = true ;
991994 }
992995
@@ -1051,16 +1054,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10511054 // To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`,
10521055 // it's fine to get a projection as the type.
10531056 Value :: Cast { kind : CastKind :: PtrToPtr , value : inner }
1054- if self . pointers_have_same_metadata ( self . ty ( * inner) , arg_ty) =>
1057+ if self . pointers_have_same_metadata ( self . ty ( inner) , arg_ty) =>
10551058 {
1056- * inner
1059+ inner
10571060 }
10581061
10591062 // We have an unsizing cast, which assigns the length to wide pointer metadata.
10601063 Value :: Cast {
10611064 kind : CastKind :: PointerCoercion ( ty:: adjustment:: PointerCoercion :: Unsize , _) ,
10621065 value : from,
1063- } if let Some ( from) = self . ty ( * from) . builtin_deref ( true )
1066+ } if let Some ( from) = self . ty ( from) . builtin_deref ( true )
10641067 && let ty:: Array ( _, len) = from. kind ( )
10651068 && let Some ( to) = self . ty ( arg_index) . builtin_deref ( true )
10661069 && let ty:: Slice ( ..) = to. kind ( ) =>
@@ -1088,15 +1091,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10881091 }
10891092
10901093 let value = match ( op, self . get ( arg_index) ) {
1091- ( UnOp :: Not , Value :: UnaryOp ( UnOp :: Not , inner) ) => return Some ( * inner) ,
1092- ( UnOp :: Neg , Value :: UnaryOp ( UnOp :: Neg , inner) ) => return Some ( * inner) ,
1094+ ( UnOp :: Not , Value :: UnaryOp ( UnOp :: Not , inner) ) => return Some ( inner) ,
1095+ ( UnOp :: Neg , Value :: UnaryOp ( UnOp :: Neg , inner) ) => return Some ( inner) ,
10931096 ( UnOp :: Not , Value :: BinaryOp ( BinOp :: Eq , lhs, rhs) ) => {
1094- Value :: BinaryOp ( BinOp :: Ne , * lhs, * rhs)
1097+ Value :: BinaryOp ( BinOp :: Ne , lhs, rhs)
10951098 }
10961099 ( UnOp :: Not , Value :: BinaryOp ( BinOp :: Ne , lhs, rhs) ) => {
1097- Value :: BinaryOp ( BinOp :: Eq , * lhs, * rhs)
1100+ Value :: BinaryOp ( BinOp :: Eq , lhs, rhs)
10981101 }
1099- ( UnOp :: PtrMetadata , Value :: RawPtr { metadata, .. } ) => return Some ( * metadata) ,
1102+ ( UnOp :: PtrMetadata , Value :: RawPtr { metadata, .. } ) => return Some ( metadata) ,
11001103 // We have an unsizing cast, which assigns the length to wide pointer metadata.
11011104 (
11021105 UnOp :: PtrMetadata ,
@@ -1105,7 +1108,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11051108 value : inner,
11061109 } ,
11071110 ) if let ty:: Slice ( ..) = arg_ty. builtin_deref ( true ) . unwrap ( ) . kind ( )
1108- && let ty:: Array ( _, len) = self . ty ( * inner) . builtin_deref ( true ) . unwrap ( ) . kind ( ) =>
1111+ && let ty:: Array ( _, len) = self . ty ( inner) . builtin_deref ( true ) . unwrap ( ) . kind ( ) =>
11091112 {
11101113 return Some ( self . insert_constant ( Const :: Ty ( self . tcx . types . usize , * len) ) ) ;
11111114 }
@@ -1138,12 +1141,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11381141 && lhs_ty. is_any_ptr ( )
11391142 && let Value :: Cast { kind : CastKind :: PtrToPtr , value : lhs_value } = self . get ( lhs)
11401143 && let Value :: Cast { kind : CastKind :: PtrToPtr , value : rhs_value } = self . get ( rhs)
1141- && let lhs_from = self . ty ( * lhs_value)
1142- && lhs_from == self . ty ( * rhs_value)
1144+ && let lhs_from = self . ty ( lhs_value)
1145+ && lhs_from == self . ty ( rhs_value)
11431146 && self . pointers_have_same_metadata ( lhs_from, lhs_ty)
11441147 {
1145- lhs = * lhs_value;
1146- rhs = * rhs_value;
1148+ lhs = lhs_value;
1149+ rhs = rhs_value;
11471150 if let Some ( lhs_op) = self . try_as_operand ( lhs, location)
11481151 && let Some ( rhs_op) = self . try_as_operand ( rhs, location)
11491152 {
@@ -1277,7 +1280,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
12771280 if op. is_overflowing ( ) {
12781281 let ty = Ty :: new_tup ( self . tcx , & [ self . ty ( result) , self . tcx . types . bool ] ) ;
12791282 let false_val = self . insert_bool ( false ) ;
1280- Some ( self . insert_tuple ( ty, vec ! [ result, false_val] ) )
1283+ Some ( self . insert_tuple ( ty, & [ result, false_val] ) )
12811284 } else {
12821285 Some ( result)
12831286 }
@@ -1330,11 +1333,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13301333 && let ty:: RawPtr ( to_pointee, _) = to. kind ( )
13311334 && to_pointee. is_sized ( self . tcx , self . typing_env ( ) )
13321335 {
1333- from = self . ty ( * pointer) ;
1334- value = * pointer;
1336+ from = self . ty ( pointer) ;
1337+ value = pointer;
13351338 was_updated_this_iteration = true ;
13361339 if from == to {
1337- return Some ( * pointer) ;
1340+ return Some ( pointer) ;
13381341 }
13391342 }
13401343
@@ -1343,7 +1346,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13431346 if let Transmute = kind
13441347 && let Value :: Aggregate ( variant_idx, field_values) = self . get ( value)
13451348 && let Some ( ( field_idx, field_ty) ) =
1346- self . value_is_all_in_one_field ( from, * variant_idx)
1349+ self . value_is_all_in_one_field ( from, variant_idx)
13471350 {
13481351 from = field_ty;
13491352 value = field_values[ field_idx. as_usize ( ) ] ;
@@ -1354,7 +1357,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13541357 }
13551358
13561359 // Various cast-then-cast cases can be simplified.
1357- if let Value :: Cast { kind : inner_kind, value : inner_value } = * self . get ( value) {
1360+ if let Value :: Cast { kind : inner_kind, value : inner_value } = self . get ( value) {
13581361 let inner_from = self . ty ( inner_value) ;
13591362 let new_kind = match ( inner_kind, kind) {
13601363 // Even if there's a narrowing cast in here that's fine, because
@@ -1553,7 +1556,7 @@ fn op_to_prop_const<'tcx>(
15531556 None
15541557}
15551558
1556- impl < ' tcx > VnState < ' _ , ' tcx > {
1559+ impl < ' tcx > VnState < ' _ , ' _ , ' tcx > {
15571560 /// If either [`Self::try_as_constant`] as [`Self::try_as_place`] succeeds,
15581561 /// returns that result as an [`Operand`].
15591562 fn try_as_operand ( & mut self , index : VnIndex , location : Location ) -> Option < Operand < ' tcx > > {
@@ -1572,7 +1575,7 @@ impl<'tcx> VnState<'_, 'tcx> {
15721575 // This was already constant in MIR, do not change it. If the constant is not
15731576 // deterministic, adding an additional mention of it in MIR will not give the same value as
15741577 // the former mention.
1575- if let Value :: Constant { value, disambiguator : 0 } = * self . get ( index) {
1578+ if let Value :: Constant { value, disambiguator : 0 } = self . get ( index) {
15761579 debug_assert ! ( value. is_deterministic( ) ) ;
15771580 return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : value } ) ;
15781581 }
@@ -1616,7 +1619,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16161619 // If we are here, we failed to find a local, and we already have a `Deref`.
16171620 // Trying to add projections will only result in an ill-formed place.
16181621 return None ;
1619- } else if let Value :: Projection ( pointer, proj) = * self . get ( index)
1622+ } else if let Value :: Projection ( pointer, proj) = self . get ( index)
16201623 && ( allow_complex_projection || proj. is_stable_offset ( ) )
16211624 && let Some ( proj) = self . try_as_place_elem ( self . ty ( index) , proj, loc)
16221625 {
@@ -1639,7 +1642,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16391642 }
16401643}
16411644
1642- impl < ' tcx > MutVisitor < ' tcx > for VnState < ' _ , ' tcx > {
1645+ impl < ' tcx > MutVisitor < ' tcx > for VnState < ' _ , ' _ , ' tcx > {
16431646 fn tcx ( & self ) -> TyCtxt < ' tcx > {
16441647 self . tcx
16451648 }
0 commit comments