@@ -138,7 +138,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
138138 let value = state. simplify_rvalue ( rvalue, location) ;
139139 // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark `local` as
140140 // reusable if we have an exact type match.
141- if state. local_decls [ local] . ty != rvalue. ty ( state. local_decls , tcx) {
141+ if state. local_decls [ local] . ty != rvalue. ty ( state. local_decls , state . tcx ) {
142142 return ;
143143 }
144144 value
@@ -382,7 +382,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
382382 let ty = match kind {
383383 AggregateTy :: Array => {
384384 assert ! ( fields. len( ) > 0 ) ;
385- Ty :: new_array ( self . tcx , fields[ 0 ] . layout . ty , fields. len ( ) as u64 )
385+ let field_ty = fields[ 0 ] . layout . ty ;
386+ Ty :: new_array ( self . tcx , field_ty, fields. len ( ) as u64 )
386387 }
387388 AggregateTy :: Tuple => {
388389 Ty :: new_tup_from_iter ( self . tcx , fields. iter ( ) . map ( |f| f. layout . ty ) )
@@ -406,7 +407,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
406407 } ;
407408 let ptr_imm = Immediate :: new_pointer_with_meta ( data, meta, & self . ecx ) ;
408409 ImmTy :: from_immediate ( ptr_imm, ty) . into ( )
409- } else if matches ! ( ty. abi, Abi :: Scalar ( ..) | Abi :: ScalarPair ( ..) ) {
410+ } else if matches ! ( kind, AggregateTy :: Array )
411+ || matches ! ( ty. abi, Abi :: Scalar ( ..) | Abi :: ScalarPair ( ..) )
412+ {
410413 let dest = self . ecx . allocate ( ty, MemoryKind :: Stack ) . ok ( ) ?;
411414 let variant_dest = if let Some ( variant) = variant {
412415 self . ecx . project_downcast ( & dest, variant) . ok ( ) ?
@@ -418,9 +421,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
418421 self . ecx . copy_op ( op, & field_dest) . ok ( ) ?;
419422 }
420423 self . ecx . write_discriminant ( variant. unwrap_or ( FIRST_VARIANT ) , & dest) . ok ( ) ?;
421- self . ecx
422- . alloc_mark_immutable ( dest. ptr ( ) . provenance . unwrap ( ) . alloc_id ( ) )
423- . ok ( ) ?;
424+ let dest = dest. map_provenance ( |prov| prov. as_immutable ( ) ) ;
424425 dest. into ( )
425426 } else {
426427 return None ;
@@ -704,7 +705,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
704705 place. projection = self . tcx . mk_place_elems ( & projection) ;
705706 }
706707
707- trace ! ( ?place) ;
708+ trace ! ( after_place = ?place) ;
708709 }
709710
710711 /// Represent the *value* which would be read from `place`, and point `place` to a preexisting
@@ -884,7 +885,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
884885 }
885886
886887 let ( mut ty, variant_index) = match * kind {
887- AggregateKind :: Array ( .. ) => {
888+ AggregateKind :: Array ( _ ) => {
888889 assert ! ( !field_ops. is_empty( ) ) ;
889890 ( AggregateTy :: Array , FIRST_VARIANT )
890891 }
@@ -1347,6 +1348,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13471348 }
13481349}
13491350
1351+ #[ instrument( level = "trace" , skip( ecx) , ret) ]
13501352fn op_to_prop_const < ' tcx > (
13511353 ecx : & mut InterpCx < ' tcx , DummyMachine > ,
13521354 op : & OpTy < ' tcx > ,
@@ -1361,8 +1363,11 @@ fn op_to_prop_const<'tcx>(
13611363 return Some ( ConstValue :: ZeroSized ) ;
13621364 }
13631365
1364- // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to avoid.
1365- if !matches ! ( op. layout. abi, Abi :: Scalar ( ..) | Abi :: ScalarPair ( ..) ) {
1366+ // Do not synthesize too large constants, except constant arrays.
1367+ // For arrays, codegen will just memcpy them, but LLVM will optimize out those unneeded memcpy.
1368+ // For others, we'd prefer in-place initialization over memcpy them.
1369+ if !( op. layout . ty . is_array ( ) || matches ! ( op. layout. abi, Abi :: Scalar ( ..) | Abi :: ScalarPair ( ..) ) )
1370+ {
13661371 return None ;
13671372 }
13681373
@@ -1433,6 +1438,7 @@ impl<'tcx> VnState<'_, 'tcx> {
14331438 }
14341439
14351440 /// If `index` is a `Value::Constant`, return the `Constant` to be put in the MIR.
1441+ #[ instrument( level = "trace" , skip( self , index) , ret) ]
14361442 fn try_as_constant ( & mut self , index : VnIndex ) -> Option < ConstOperand < ' tcx > > {
14371443 // This was already constant in MIR, do not change it.
14381444 if let Value :: Constant { value, disambiguator : _ } = * self . get ( index)
@@ -1444,8 +1450,13 @@ impl<'tcx> VnState<'_, 'tcx> {
14441450 }
14451451
14461452 let op = self . evaluated [ index] . as_ref ( ) ?;
1447- if op. layout . is_unsized ( ) {
1448- // Do not attempt to propagate unsized locals.
1453+
1454+ // Ignore promoted arrays. Promoted arrays are already placed in `.rodata`.
1455+ // Which is what we try to archive for running gvn on constant local arrays.
1456+ if let Either :: Left ( mplace) = op. as_mplace_or_imm ( )
1457+ && mplace. layout . ty . is_array ( )
1458+ && let Value :: Projection ( _index, ProjectionElem :: Deref ) = self . get ( index)
1459+ {
14491460 return None ;
14501461 }
14511462
@@ -1484,6 +1495,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
14841495 self . simplify_operand ( operand, location) ;
14851496 }
14861497
1498+ #[ instrument( level = "trace" , skip( self , stmt) ) ]
14871499 fn visit_statement ( & mut self , stmt : & mut Statement < ' tcx > , location : Location ) {
14881500 if let StatementKind :: Assign ( box ( ref mut lhs, ref mut rvalue) ) = stmt. kind {
14891501 self . simplify_place_projection ( lhs, location) ;
0 commit comments