diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 1a65affe8121a..dea4137a11927 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -48,6 +48,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { ctx.simplify_ref_deref(rvalue); ctx.simplify_ptr_aggregate(rvalue); ctx.simplify_cast(rvalue); + ctx.simplify_repeated_aggregate(rvalue); } _ => {} } @@ -68,6 +69,32 @@ struct InstSimplifyContext<'a, 'tcx> { } impl<'tcx> InstSimplifyContext<'_, 'tcx> { + fn simplify_repeated_aggregate(&self, rvalue: &mut Rvalue<'tcx>) { + let Rvalue::Aggregate(box AggregateKind::Array(_), fields) = rvalue else { + return; + }; + if fields.len() < 5 { + return; + } + let first = &fields[rustc_abi::FieldIdx::ZERO]; + let Operand::Constant(first) = first else { + return; + }; + let Ok(first_val) = first.const_.eval(self.tcx, self.typing_env, first.span) else { + return; + }; + if fields.iter().all(|v| { + let Operand::Constant(v) = v else { + return false; + }; + let v = v.const_.eval(self.tcx, self.typing_env, v.span); + v == Ok(first_val) + }) { + let len = ty::Const::from_target_usize(self.tcx, fields.len().try_into().unwrap()); + *rvalue = Rvalue::Repeat(Operand::Constant(first.clone()), len); + } + } + /// Transform boolean comparisons into logical operations. fn simplify_bool_cmp(&self, rvalue: &mut Rvalue<'tcx>) { match rvalue {