@@ -1409,7 +1409,9 @@ fn op_to_prop_const<'tcx>(
14091409 return Some ( ConstValue :: ZeroSized ) ;
14101410 }
14111411
1412- // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to avoid.
1412+ // Do not synthesize too large constants, except constant arrays.
1413+ // For arrays, codegen will just memcpy them, but LLVM will optimize out those unneeded memcpy.
1414+ // For others, we'd prefer in-place initialization over memcpy them.
14131415 if !( op. layout . ty . is_array ( ) || matches ! ( op. layout. abi, Abi :: Scalar ( ..) | Abi :: ScalarPair ( ..) ) )
14141416 {
14151417 return None ;
@@ -1487,17 +1489,18 @@ impl<'tcx> VnState<'_, 'tcx> {
14871489 // This was already constant in MIR, do not change it.
14881490 let value = self . get ( index) ;
14891491 debug ! ( ?index, ?value) ;
1490- // If the constant is not deterministic, adding an additional mention of it in MIR will
1491- // not give the same value as the former mention.
1492- if let Value :: Constant { value , disambiguator : _ } = value
1492+ if let Value :: Constant { value , disambiguator : _ } = * value
1493+ // If the constant is not deterministic, adding an additional mention of it in MIR will
1494+ // not give the same value as the former mention.
14931495 && value. is_deterministic ( )
14941496 {
1495- return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : * value } ) ;
1497+ return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : value } ) ;
14961498 }
14971499
14981500 let op = self . evaluated [ index] . as_ref ( ) ?;
14991501
1500- // Ignore promoted arrays.
1502+ // Ignore promoted arrays. Promoted arrays are already placed in `.rodata`.
1503+ // Which is what we try to archive for running gvn on constant local arrays.
15011504 if let Either :: Left ( mplace) = op. as_mplace_or_imm ( )
15021505 && mplace. layout . ty . is_array ( )
15031506 && let Value :: Projection ( _index, ProjectionElem :: Deref ) = value
@@ -1558,10 +1561,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
15581561 let Some ( value) = value else { return } ;
15591562
15601563 debug ! ( before_rvalue = ?rvalue) ;
1561- // Ignore arrays in operands.
1562- // Prevent code bloat that makes
1563- // `_2 = _1` now resolved to `_2 = <evaluated array>`.
1564- let disallow_dup_array = if rvalue. ty ( self . local_decls , self . tcx ) . is_array ( )
1564+ // De-duplicate locals has the same arrays assigned to prevent code bloat.
1565+ let disallowed_duplicated_array = if rvalue. ty ( self . local_decls , self . tcx ) . is_array ( )
15651566 && let Some ( locals) = self . rev_locals . get ( value) . as_deref ( )
15661567 && let [ first, ..] = locals[ ..]
15671568 {
@@ -1570,7 +1571,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
15701571 false
15711572 } ;
15721573
1573- if !disallow_dup_array && let Some ( const_) = self . try_as_constant ( value) {
1574+ if !disallowed_duplicated_array && let Some ( const_) = self . try_as_constant ( value) {
15741575 * rvalue = Rvalue :: Use ( Operand :: Constant ( Box :: new ( const_) ) ) ;
15751576 } else if let Some ( local) = self . try_as_local ( value, location)
15761577 && * rvalue != Rvalue :: Use ( Operand :: Move ( local. into ( ) ) )
0 commit comments