@@ -980,27 +980,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
980
980
}
981
981
}
982
982
983
- let tcx = self . tcx ;
984
- let mut projection = SmallVec :: < [ PlaceElem < ' tcx > ; 1 ] > :: new ( ) ;
985
- loop {
986
- if let Some ( local) = self . try_as_local ( copy_from_local_value, location) {
987
- projection. reverse ( ) ;
988
- let place = Place { local, projection : tcx. mk_place_elems ( projection. as_slice ( ) ) } ;
989
- if rvalue. ty ( self . local_decls , tcx) == place. ty ( self . local_decls , tcx) . ty {
990
- self . reused_locals . insert ( local) ;
991
- * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
992
- return Some ( copy_from_value) ;
993
- }
994
- return None ;
995
- } else if let Value :: Projection ( pointer, proj) = * self . get ( copy_from_local_value)
996
- && let Some ( proj) = self . try_as_place_elem ( proj, location)
997
- {
998
- projection. push ( proj) ;
999
- copy_from_local_value = pointer;
1000
- } else {
1001
- return None ;
983
+ if let Some ( place) = self . try_as_place ( copy_from_local_value, location) {
984
+ if rvalue. ty ( self . local_decls , self . tcx ) == place. ty ( self . local_decls , self . tcx ) . ty {
985
+ self . reused_locals . insert ( place. local ) ;
986
+ * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
987
+ return Some ( copy_from_local_value) ;
1002
988
}
1003
989
}
990
+
991
+ None
1004
992
}
1005
993
1006
994
fn simplify_aggregate (
@@ -1672,14 +1660,14 @@ fn op_to_prop_const<'tcx>(
1672
1660
}
1673
1661
1674
1662
impl < ' tcx > VnState < ' _ , ' tcx > {
1675
- /// If either [`Self::try_as_constant`] as [`Self::try_as_local `] succeeds,
1663
+ /// If either [`Self::try_as_constant`] as [`Self::try_as_place `] succeeds,
1676
1664
/// returns that result as an [`Operand`].
1677
1665
fn try_as_operand ( & mut self , index : VnIndex , location : Location ) -> Option < Operand < ' tcx > > {
1678
1666
if let Some ( const_) = self . try_as_constant ( index) {
1679
1667
Some ( Operand :: Constant ( Box :: new ( const_) ) )
1680
- } else if let Some ( local ) = self . try_as_local ( index, location) {
1681
- self . reused_locals . insert ( local) ;
1682
- Some ( Operand :: Copy ( local . into ( ) ) )
1668
+ } else if let Some ( place ) = self . try_as_place ( index, location) {
1669
+ self . reused_locals . insert ( place . local ) ;
1670
+ Some ( Operand :: Copy ( place ) )
1683
1671
} else {
1684
1672
None
1685
1673
}
@@ -1712,6 +1700,29 @@ impl<'tcx> VnState<'_, 'tcx> {
1712
1700
Some ( ConstOperand { span : DUMMY_SP , user_ty : None , const_ } )
1713
1701
}
1714
1702
1703
+ /// Construct a place which holds the same value as `index` and for which all locals strictly
1704
+ /// dominate `loc`. If you used this place, add its base local to `reused_locals` to remove
1705
+ /// storage statements.
1706
+ #[ instrument( level = "trace" , skip( self ) , ret) ]
1707
+ fn try_as_place ( & mut self , mut index : VnIndex , loc : Location ) -> Option < Place < ' tcx > > {
1708
+ let mut projection = SmallVec :: < [ PlaceElem < ' tcx > ; 1 ] > :: new ( ) ;
1709
+ loop {
1710
+ if let Some ( local) = self . try_as_local ( index, loc) {
1711
+ projection. reverse ( ) ;
1712
+ let place =
1713
+ Place { local, projection : self . tcx . mk_place_elems ( projection. as_slice ( ) ) } ;
1714
+ return Some ( place) ;
1715
+ } else if let Value :: Projection ( pointer, proj) = * self . get ( index)
1716
+ && let Some ( proj) = self . try_as_place_elem ( proj, loc)
1717
+ {
1718
+ projection. push ( proj) ;
1719
+ index = pointer;
1720
+ } else {
1721
+ return None ;
1722
+ }
1723
+ }
1724
+ }
1725
+
1715
1726
/// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`,
1716
1727
/// return it. If you used this local, add it to `reused_locals` to remove storage statements.
1717
1728
fn try_as_local ( & mut self , index : VnIndex , loc : Location ) -> Option < Local > {
@@ -1762,11 +1773,12 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1762
1773
if let Some ( value) = value {
1763
1774
if let Some ( const_) = self . try_as_constant ( value) {
1764
1775
* rvalue = Rvalue :: Use ( Operand :: Constant ( Box :: new ( const_) ) ) ;
1765
- } else if let Some ( local) = self . try_as_local ( value, location)
1766
- && * rvalue != Rvalue :: Use ( Operand :: Move ( local. into ( ) ) )
1776
+ } else if let Some ( place) = self . try_as_place ( value, location)
1777
+ && * rvalue != Rvalue :: Use ( Operand :: Move ( place) )
1778
+ && * rvalue != Rvalue :: Use ( Operand :: Copy ( place) )
1767
1779
{
1768
- * rvalue = Rvalue :: Use ( Operand :: Copy ( local . into ( ) ) ) ;
1769
- self . reused_locals . insert ( local) ;
1780
+ * rvalue = Rvalue :: Use ( Operand :: Copy ( place ) ) ;
1781
+ self . reused_locals . insert ( place . local ) ;
1770
1782
}
1771
1783
}
1772
1784
}
0 commit comments