diff options
| author | Scott McMurray <scottmcm@users.noreply.github.com> | 2025-01-09 22:53:14 -0800 |
|---|---|---|
| committer | Scott McMurray <scottmcm@users.noreply.github.com> | 2025-01-11 15:56:53 -0800 |
| commit | 6e34369ef6ec53f571565298b0d0de489f343acc (patch) | |
| tree | 57abe5c44d75de3a854b0cc71471fafe843a3de1 /compiler/rustc_mir_transform | |
| parent | eb54a50837ad4bcc9842924f27e7287ca66e294c (diff) | |
| download | rust-6e34369ef6ec53f571565298b0d0de489f343acc.tar.gz rust-6e34369ef6ec53f571565298b0d0de489f343acc.zip | |
[mir-opt] simplify `Repeat`s that don't actually repeat the operand
Diffstat (limited to 'compiler/rustc_mir_transform')
| -rw-r--r-- | compiler/rustc_mir_transform/src/instsimplify.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/remove_zsts.rs | 28 |
2 files changed, 30 insertions, 11 deletions
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index f74a577c598..20e2e3e8ba2 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -49,6 +49,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { ctx.simplify_ptr_aggregate(rvalue); ctx.simplify_cast(rvalue); ctx.simplify_repeated_aggregate(rvalue); + ctx.simplify_repeat_once(rvalue); } _ => {} } @@ -207,6 +208,18 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } } + /// Simplify `[x; 1]` to just `[x]`. + fn simplify_repeat_once(&self, rvalue: &mut Rvalue<'tcx>) { + if let Rvalue::Repeat(operand, count) = rvalue + && let Some(1) = count.try_to_target_usize(self.tcx) + { + *rvalue = Rvalue::Aggregate( + Box::new(AggregateKind::Array(operand.ty(self.local_decls, self.tcx))), + [operand.clone()].into(), + ); + } + } + fn simplify_primitive_clone( &self, terminator: &mut Terminator<'tcx>, diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 64e183bcbc0..e37ead3674b 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -36,31 +36,37 @@ struct Replacer<'a, 'tcx> { } /// A cheap, approximate check to avoid unnecessary `layout_of` calls. -fn maybe_zst(ty: Ty<'_>) -> bool { +/// +/// `Some(true)` is definitely ZST; `Some(false)` is definitely *not* ZST. +/// +/// `None` may or may not be, and must check `layout_of` to be sure. +fn trivially_zst<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<bool> { match ty.kind() { + // definitely ZST + ty::FnDef(..) | ty::Never => Some(true), + ty::Tuple(fields) if fields.is_empty() => Some(true), + ty::Array(_ty, len) if let Some(0) = len.try_to_target_usize(tcx) => Some(true), // maybe ZST (could be more precise) ty::Adt(..) | ty::Array(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Tuple(..) - | ty::Alias(ty::Opaque, ..) => true, - // definitely ZST - ty::FnDef(..) | ty::Never => true, + | ty::Alias(ty::Opaque, ..) => None, // unreachable or can't be ZST - _ => false, + _ => Some(false), } } impl<'tcx> Replacer<'_, 'tcx> { fn known_to_be_zst(&self, ty: Ty<'tcx>) -> bool { - if !maybe_zst(ty) { - return false; + if let Some(is_zst) = trivially_zst(ty, self.tcx) { + is_zst + } else { + self.tcx + .layout_of(self.typing_env.as_query_input(ty)) + .is_ok_and(|layout| layout.is_zst()) } - let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(ty)) else { - return false; - }; - layout.is_zst() } fn make_zst(&self, ty: Ty<'tcx>) -> ConstOperand<'tcx> { |
