Skip to content

Commit d679086

Browse files
committed
Simplify align_of_val::<[T]>(…)align_of::<T>()
1 parent 7c0f451 commit d679086

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

compiler/rustc_mir_transform/src/instsimplify.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
5555

5656
let terminator = block.terminator.as_mut().unwrap();
5757
ctx.simplify_primitive_clone(terminator, &mut block.statements);
58+
ctx.simplify_align_of_slice_val(terminator, &mut block.statements);
5859
ctx.simplify_intrinsic_assert(terminator);
5960
ctx.simplify_nounwind_call(terminator);
6061
simplify_duplicate_switch_targets(terminator);
@@ -252,6 +253,36 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
252253
terminator.kind = TerminatorKind::Goto { target: *destination_block };
253254
}
254255

256+
// Convert `align_of_val::<[T]>(ptr)` to `align_of::<T>()`, since the
257+
// alignment of a slice doesn't actually depend on metadata at all
258+
// and the element type is always `Sized`.
259+
//
260+
// This is here so it can run after inlining, where it's more useful.
261+
// (LowerIntrinsics is done in cleanup, before the optimization passes.)
262+
fn simplify_align_of_slice_val(
263+
&self,
264+
terminator: &mut Terminator<'tcx>,
265+
statements: &mut Vec<Statement<'tcx>>,
266+
) {
267+
if let TerminatorKind::Call {
268+
func, args, destination, target: Some(destination_block), ..
269+
} = &terminator.kind
270+
&& args.len() == 1
271+
&& let Some((fn_def_id, generics)) = func.const_fn_def()
272+
&& self.tcx.is_intrinsic(fn_def_id, sym::align_of_val)
273+
&& let ty::Slice(elem_ty) = *generics.type_at(0).kind()
274+
{
275+
statements.push(Statement::new(
276+
terminator.source_info,
277+
StatementKind::Assign(Box::new((
278+
*destination,
279+
Rvalue::NullaryOp(NullOp::AlignOf, elem_ty),
280+
))),
281+
));
282+
terminator.kind = TerminatorKind::Goto { target: *destination_block };
283+
}
284+
}
285+
255286
fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) {
256287
let TerminatorKind::Call { ref func, ref mut unwind, .. } = terminator.kind else {
257288
return;

tests/mir-opt/instsimplify/align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
bb0: {
1010
StorageLive(_2);
1111
_2 = &raw const (*_1);
12-
_0 = std::intrinsics::align_of_val::<[T]>(move _2) -> [return: bb1, unwind unreachable];
12+
- _0 = std::intrinsics::align_of_val::<[T]>(move _2) -> [return: bb1, unwind unreachable];
13+
+ _0 = AlignOf(T);
14+
+ goto -> bb1;
1315
}
1416

1517
bb1: {

tests/mir-opt/instsimplify/align_of_slice.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
// EMIT_MIR align_of_slice.of_val_slice.InstSimplify-after-simplifycfg.diff
88
pub fn of_val_slice<T>(slice: &[T]) -> usize {
99
// CHECK-LABEL: fn of_val_slice(_1: &[T])
10-
// CHECK: _2 = &raw const (*_1);
11-
// CHECK: _0 = std::intrinsics::align_of_val::<[T]>(move _2)
10+
// CHECK: _0 = AlignOf(T);
1211
unsafe { core::intrinsics::align_of_val(slice) }
1312
}

0 commit comments

Comments
 (0)