@@ -48,6 +48,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
48
48
ctx. simplify_ref_deref ( rvalue) ;
49
49
ctx. simplify_ptr_aggregate ( rvalue) ;
50
50
ctx. simplify_cast ( rvalue) ;
51
+ ctx. simplify_repeated_aggregate ( rvalue) ;
51
52
}
52
53
_ => { }
53
54
}
@@ -68,6 +69,35 @@ struct InstSimplifyContext<'a, 'tcx> {
68
69
}
69
70
70
71
impl < ' 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
+
71
101
/// Transform boolean comparisons into logical operations.
72
102
fn simplify_bool_cmp ( & self , rvalue : & mut Rvalue < ' tcx > ) {
73
103
match rvalue {
0 commit comments