diff options
| author | Ben Kimock <kimockb@gmail.com> | 2025-01-08 20:49:48 -0500 |
|---|---|---|
| committer | Ben Kimock <kimockb@gmail.com> | 2025-01-09 20:00:32 -0500 |
| commit | a285d202cf2ea695751e127ac0b2e0664bbd98f3 (patch) | |
| tree | f104bf325b537a4e8fa642f2ff7eb71e4ecc6ab6 /compiler/rustc_mir_transform/src | |
| parent | fb546ee09b226bc4dd4b712d35a372d923c4fa54 (diff) | |
| download | rust-a285d202cf2ea695751e127ac0b2e0664bbd98f3.tar.gz rust-a285d202cf2ea695751e127ac0b2e0664bbd98f3.zip | |
Add an InstSimplify for repetitive array expressions
Diffstat (limited to 'compiler/rustc_mir_transform/src')
| -rw-r--r-- | compiler/rustc_mir_transform/src/instsimplify.rs | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 1a65affe812..927345a7dbb 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,35 @@ struct InstSimplifyContext<'a, 'tcx> { } impl<'tcx> InstSimplifyContext<'_, 'tcx> { + /// Transform aggregates like [0, 0, 0, 0, 0] into [0; 5]. + /// GVN can also do this optimization, but GVN is only run at mir-opt-level 2 so having this in + /// InstSimplify helps unoptimized builds. + 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(|field| { + let Operand::Constant(field) = field else { + return false; + }; + let field = field.const_.eval(self.tcx, self.typing_env, field.span); + field == 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 { |
