Skip to content

Commit

Permalink
Auto merge of #106989 - clubby789:is-zero-num, r=scottmcm
Browse files Browse the repository at this point in the history
Implement `alloc::vec::IsZero` for `Option<$NUM>` types

Fixes #106911

Mirrors the `NonZero$NUM` implementations with an additional `assert_zero_valid`.
`None::<i32>` doesn't stricly satisfy `IsZero` but for the purpose of allocating we can produce more efficient codegen.
  • Loading branch information
bors committed Jan 19, 2023
2 parents 65d2f2a + 50e9f2e commit 705a96d
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
#![feature(const_size_of_val)]
#![feature(const_align_of_val)]
#![feature(const_ptr_read)]
#![feature(const_maybe_uninit_zeroed)]
#![feature(const_maybe_uninit_write)]
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_refs_to_cell)]
Expand Down
20 changes: 19 additions & 1 deletion library/alloc/src/vec/is_zero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::boxed::Box;

#[rustc_specialization_trait]
pub(super) unsafe trait IsZero {
/// Whether this value's representation is all zeros
/// Whether this value's representation is all zeros,
/// or can be represented with all zeroes.
fn is_zero(&self) -> bool;
}

Expand Down Expand Up @@ -147,6 +148,23 @@ impl_is_zero_option_of_nonzero!(
NonZeroIsize,
);

macro_rules! impl_is_zero_option_of_num {
($($t:ty,)+) => {$(
unsafe impl IsZero for Option<$t> {
#[inline]
fn is_zero(&self) -> bool {
const {
let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
assert!(none.is_none());
}
self.is_none()
}
}
)+};
}

impl_is_zero_option_of_num!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize,);

unsafe impl<T: IsZero> IsZero for Wrapping<T> {
#[inline]
fn is_zero(&self) -> bool {
Expand Down
17 changes: 17 additions & 0 deletions tests/codegen/vec-calloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,23 @@ pub fn vec_option_bool(n: usize) -> Vec<Option<bool>> {
vec![Some(false); n]
}

// CHECK-LABEL: @vec_option_i32
#[no_mangle]
pub fn vec_option_i32(n: usize) -> Vec<Option<i32>> {
// CHECK-NOT: call {{.*}}alloc::vec::from_elem
// CHECK-NOT: call {{.*}}reserve
// CHECK-NOT: call {{.*}}__rust_alloc(

// CHECK: call {{.*}}__rust_alloc_zeroed(

// CHECK-NOT: call {{.*}}alloc::vec::from_elem
// CHECK-NOT: call {{.*}}reserve
// CHECK-NOT: call {{.*}}__rust_alloc(

// CHECK: ret void
vec![None; n]
}

// Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away.
// CHECK: declare noalias noundef ptr @__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]]

Expand Down

0 comments on commit 705a96d

Please sign in to comment.