Skip to content

Commit 5eec5e3

Browse files
TKanXscottmcm
andcommitted
perf(codegen): Eliminate size_of_val == 0 for non-ZST DSTs via nuw+assume
Co-authored-by: Scott McMurray <scottmcm@users.noreply.github.com>
1 parent 5fb2ff8 commit 5eec5e3

3 files changed

Lines changed: 52 additions & 4 deletions

File tree

‎compiler/rustc_codegen_ssa/src/size_of_val.rs‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
159159
// Furthermore, `align >= unsized_align`, and therefore we only need to do:
160160
// let full_size = (unsized_offset_unadjusted + unsized_size).align_to(full_align);
161161

162-
let full_size = bx.add(unsized_offset_unadjusted, unsized_size);
162+
// total <= isize::MAX, so nuw+nsw.
163+
let unrounded_size = bx.unchecked_suadd(unsized_offset_unadjusted, unsized_size);
163164

164165
// Issue #27023: must add any necessary padding to `size`
165166
// (to make it a multiple of `align`) before returning it.
@@ -173,10 +174,15 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
173174
// `(size + (align-1)) & -align`
174175
let one = bx.const_usize(1);
175176
let addend = bx.sub(full_align, one);
176-
let add = bx.add(full_size, addend);
177+
let add = bx.add(unrounded_size, addend);
177178
let neg = bx.neg(full_align);
178179
let full_size = bx.and(add, neg);
179180

181+
// round_up(x, a) >= x for pow2 a; with nuw above LLVM deduces
182+
// full_size >= unrounded_size >= offset > 0 (#152788).
183+
let size_ge = bx.icmp(IntPredicate::IntUGE, full_size, unrounded_size);
184+
bx.assume(size_ge);
185+
180186
(full_size, full_align)
181187
}
182188
_ => bug!("size_and_align_of_dst: {t} not supported"),
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled
2+
//@ min-llvm-version: 21
3+
//@ needs-deterministic-layouts
4+
5+
#![crate_type = "lib"]
6+
7+
// Regression test for #152788: `size_of_val(p) == 0` folds to `false` for
8+
// DSTs with a non-zero prefix (nuw+nsw on offset+tail, assume on rounding).
9+
10+
pub struct Foo<T: ?Sized>(pub [u32; 3], pub T);
11+
12+
// CHECK-LABEL: @size_of_val_dyn_not_zero
13+
#[no_mangle]
14+
pub fn size_of_val_dyn_not_zero(p: &Foo<dyn std::fmt::Debug>) -> bool {
15+
// CHECK: ret i1 false
16+
std::mem::size_of_val(p) == 0
17+
}
18+
19+
// CHECK-LABEL: @size_of_val_slice_u8_not_zero
20+
#[no_mangle]
21+
pub fn size_of_val_slice_u8_not_zero(p: &Foo<[u8]>) -> bool {
22+
// CHECK: ret i1 false
23+
std::mem::size_of_val(p) == 0
24+
}
25+
26+
// CHECK-LABEL: @size_of_val_slice_i32_not_zero
27+
#[no_mangle]
28+
pub fn size_of_val_slice_i32_not_zero(p: &Foo<[i32]>) -> bool {
29+
// CHECK: ret i1 false
30+
std::mem::size_of_val(p) == 0
31+
}

‎tests/codegen-llvm/dst-vtable-align-nonzero.rs‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled
2+
//@ revisions: LLVM20 CURRENT
3+
//@ [LLVM20] max-llvm-major-version: 20
4+
//@ [CURRENT] min-llvm-version: 21
25

36
#![crate_type = "lib"]
47
#![feature(core_intrinsics)]
@@ -30,10 +33,18 @@ pub struct Struct<W: ?Sized> {
3033
pub fn eliminates_runtime_check_when_align_1(
3134
x: &Struct<WrapperWithAlign1<dyn Trait>>,
3235
) -> &WrapperWithAlign1<dyn Trait> {
33-
// CHECK: load [[USIZE:i[0-9]+]], {{.+}} !range [[RANGE_META:![0-9]+]]
36+
// LLVM20: load [[USIZE:i[0-9]+]], {{.+}} !range {{![0-9]+}}
37+
// LLVM20: load [[USIZE]], {{.+}} !range [[RANGE_META:![0-9]+]]
38+
// CURRENT: load [[USIZE:i[0-9]+]], {{.+}} !range [[RANGE_META:![0-9]+]]
3439
// CHECK-NOT: llvm.umax
35-
// CHECK-NOT: icmp
3640
// CHECK-NOT: select
41+
// CURRENT-NOT: icmp
42+
// LLVM20-NOT: icmp
43+
// LLVM20: [[DOES_NOT_SHRINK:%.+]] = icmp ug{{[et]}}
44+
// LLVM20-NEXT: call void @llvm.assume(i1 [[DOES_NOT_SHRINK]])
45+
// LLVM20-NOT: llvm.umax
46+
// LLVM20-NOT: icmp
47+
// LLVM20-NOT: select
3748
// CHECK: ret
3849
&x.dst
3950
}

0 commit comments

Comments
 (0)