@@ -1409,7 +1409,9 @@ fn op_to_prop_const<'tcx>(
1409
1409
return Some ( ConstValue :: ZeroSized ) ;
1410
1410
}
1411
1411
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.
1413
1415
if !( op. layout . ty . is_array ( ) || matches ! ( op. layout. abi, Abi :: Scalar ( ..) | Abi :: ScalarPair ( ..) ) )
1414
1416
{
1415
1417
return None ;
@@ -1487,17 +1489,18 @@ impl<'tcx> VnState<'_, 'tcx> {
1487
1489
// This was already constant in MIR, do not change it.
1488
1490
let value = self . get ( index) ;
1489
1491
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.
1493
1495
&& value. is_deterministic ( )
1494
1496
{
1495
- return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : * value } ) ;
1497
+ return Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ : value } ) ;
1496
1498
}
1497
1499
1498
1500
let op = self . evaluated [ index] . as_ref ( ) ?;
1499
1501
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.
1501
1504
if let Either :: Left ( mplace) = op. as_mplace_or_imm ( )
1502
1505
&& mplace. layout . ty . is_array ( )
1503
1506
&& let Value :: Projection ( _index, ProjectionElem :: Deref ) = value
@@ -1558,10 +1561,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1558
1561
let Some ( value) = value else { return } ;
1559
1562
1560
1563
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 ( )
1565
1566
&& let Some ( locals) = self . rev_locals . get ( value) . as_deref ( )
1566
1567
&& let [ first, ..] = locals[ ..]
1567
1568
{
@@ -1570,7 +1571,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1570
1571
false
1571
1572
} ;
1572
1573
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) {
1574
1575
* rvalue = Rvalue :: Use ( Operand :: Constant ( Box :: new ( const_) ) ) ;
1575
1576
} else if let Some ( local) = self . try_as_local ( value, location)
1576
1577
&& * rvalue != Rvalue :: Use ( Operand :: Move ( local. into ( ) ) )
0 commit comments