@@ -48,6 +48,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
4848 ctx. simplify_ref_deref ( rvalue) ;
4949 ctx. simplify_ptr_aggregate ( rvalue) ;
5050 ctx. simplify_cast ( rvalue) ;
51+ ctx. simplify_repeated_aggregate ( rvalue) ;
5152 }
5253 _ => { }
5354 }
@@ -68,6 +69,35 @@ struct InstSimplifyContext<'a, 'tcx> {
6869}
6970
7071impl < ' tcx > InstSimplifyContext < ' _ , ' tcx > {
72+ /// Transform aggregates like [0, 0, 0, 0, 0] into [0; 5].
73+ /// GVN can also do this optimization, but GVN is only run at mir-opt-level 2 so having this in
74+ /// InstSimplify helps unoptimized builds.
75+ fn simplify_repeated_aggregate ( & self , rvalue : & mut Rvalue < ' tcx > ) {
76+ let Rvalue :: Aggregate ( box AggregateKind :: Array ( _) , fields) = rvalue else {
77+ return ;
78+ } ;
79+ if fields. len ( ) < 5 {
80+ return ;
81+ }
82+ let first = & fields[ rustc_abi:: FieldIdx :: ZERO ] ;
83+ let Operand :: Constant ( first) = first else {
84+ return ;
85+ } ;
86+ let Ok ( first_val) = first. const_ . eval ( self . tcx , self . typing_env , first. span ) else {
87+ return ;
88+ } ;
89+ if fields. iter ( ) . all ( |field| {
90+ let Operand :: Constant ( field) = field else {
91+ return false ;
92+ } ;
93+ let field = field. const_ . eval ( self . tcx , self . typing_env , field. span ) ;
94+ field == Ok ( first_val)
95+ } ) {
96+ let len = ty:: Const :: from_target_usize ( self . tcx , fields. len ( ) . try_into ( ) . unwrap ( ) ) ;
97+ * rvalue = Rvalue :: Repeat ( Operand :: Constant ( first. clone ( ) ) , len) ;
98+ }
99+ }
100+
71101 /// Transform boolean comparisons into logical operations.
72102 fn simplify_bool_cmp ( & self , rvalue : & mut Rvalue < ' tcx > ) {
73103 match rvalue {
0 commit comments