diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2025-07-29 23:50:35 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-29 23:50:35 +1000 |
| commit | 826c462c32642c8cc17d708a1bb9a7022fd5bdd5 (patch) | |
| tree | 11a4ba4c50e698b28abd6fb0e1a7df77d121d925 /compiler/rustc_mir_transform/src | |
| parent | f8370285cf81e8af24c7f95b77cbb83c3d6db1cf (diff) | |
| parent | 8ef9233339c09d80e12b31c523082b94d9e09b44 (diff) | |
| download | rust-826c462c32642c8cc17d708a1bb9a7022fd5bdd5.tar.gz rust-826c462c32642c8cc17d708a1bb9a7022fd5bdd5.zip | |
Rollup merge of #144566 - scottmcm:align-of-slice, r=oli-obk
Simplify `align_of_val::<[T]>(…)` → `align_of::<T>()` I spotted this while working on the inliner (rust-lang/rust#144561). In particular, if [`Layout::for_value`](https://doc.rust-lang.org/std/alloc/struct.Layout.html#method.for_value) inlines, then it can be pretty easy to end up with an `align_of_val::<[T]>` today (demo: <https://rust.godbolt.org/z/Tesnscj4a>) where we can save at least a block, if not more, by using the version that's an rvalue and not a call.
Diffstat (limited to 'compiler/rustc_mir_transform/src')
| -rw-r--r-- | compiler/rustc_mir_transform/src/instsimplify.rs | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index dbcaed20953..c83bd25c663 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -55,6 +55,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { let terminator = block.terminator.as_mut().unwrap(); ctx.simplify_primitive_clone(terminator, &mut block.statements); + ctx.simplify_align_of_slice_val(terminator, &mut block.statements); ctx.simplify_intrinsic_assert(terminator); ctx.simplify_nounwind_call(terminator); simplify_duplicate_switch_targets(terminator); @@ -252,6 +253,36 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { terminator.kind = TerminatorKind::Goto { target: *destination_block }; } + // Convert `align_of_val::<[T]>(ptr)` to `align_of::<T>()`, since the + // alignment of a slice doesn't actually depend on metadata at all + // and the element type is always `Sized`. + // + // This is here so it can run after inlining, where it's more useful. + // (LowerIntrinsics is done in cleanup, before the optimization passes.) + fn simplify_align_of_slice_val( + &self, + terminator: &mut Terminator<'tcx>, + statements: &mut Vec<Statement<'tcx>>, + ) { + if let TerminatorKind::Call { + func, args, destination, target: Some(destination_block), .. + } = &terminator.kind + && args.len() == 1 + && let Some((fn_def_id, generics)) = func.const_fn_def() + && self.tcx.is_intrinsic(fn_def_id, sym::align_of_val) + && let ty::Slice(elem_ty) = *generics.type_at(0).kind() + { + statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( + *destination, + Rvalue::NullaryOp(NullOp::AlignOf, elem_ty), + ))), + )); + terminator.kind = TerminatorKind::Goto { target: *destination_block }; + } + } + fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) { let TerminatorKind::Call { ref func, ref mut unwind, .. } = terminator.kind else { return; |
