Skip to content

Commit

Permalink
Auto merge of #123425 - jieyouxu:array-imm-noundef-param, r=<try>
Browse files Browse the repository at this point in the history
Add `noundef` metadata for fits-in-target-pointer-size array immediate arguments

`noundef` is only added if the small array immediate fits in the target pointer size and if optimizations are enabled.

Closes #123183.
  • Loading branch information
bors committed Apr 3, 2024
2 parents 98efd80 + 31abdb2 commit 6be5114
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 2 deletions.
27 changes: 25 additions & 2 deletions compiler/rustc_ty_utils/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt};
use rustc_session::config::OptLevel;
use rustc_span::def_id::DefId;
use rustc_target::abi::call::{
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
RiscvInterruptKind,
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, Conv, FnAbi, PassMode, Reg,
RegKind, RiscvInterruptKind,
};
use rustc_target::abi::*;
use rustc_target::spec::abi::Abi as SpecAbi;
Expand Down Expand Up @@ -784,6 +784,29 @@ fn fn_abi_adjust_for_abi<'tcx>(
// an LLVM aggregate type for this leads to bad optimizations,
// so we pick an appropriately sized integer type instead.
arg.cast_to(Reg { kind: RegKind::Integer, size });

// Let's see if we can add a `noundef`. This is only legal for arrays, definitely
// not for unions. This is also legal for `#[repr(transparent)] struct` or
// `#[repr(transparent)] enum` containing array.
let is_transparent_array =
if arg.layout.is_transparent::<LayoutCx<'tcx, TyCtxt<'tcx>>>()
&& let Some((_, layout)) = arg.layout.non_1zst_field(cx)
&& layout.ty.is_array()
{
true
} else {
false
};

if arg.layout.ty.is_array() || is_transparent_array {
// Fixup arg attribute with `noundef`.
let PassMode::Cast { ref mut cast, .. } = &mut arg.mode else {
bug!("this cannot fail because of the previous cast_to `Reg`");
};

let box CastTarget { ref mut attrs, .. } = cast;
attrs.set(ArgAttribute::NoUndef);
}
}

// If we deduced that this parameter was read-only, add that to the attribute list now.
Expand Down
95 changes: 95 additions & 0 deletions tests/codegen/array-immediate-param-noundef.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Check that small array immediates that fits in target pointer size in argument position have
// `noundef` parameter metadata. Note that the `noundef` parameter metadata is only applied if:
// - `!arg.layout.is_unsized() && size <= Pointer(AddressSpace::DATA).size(cx)`
// - optimizations are turned on.
//
// ignore-tidy-linelength
//@ only-64bit (presence of noundef depends on pointer width)
//@ compile-flags: -C no-prepopulate-passes -O
#![crate_type = "lib"]

// CHECK: define noundef i64 @replace_short_array_u64x1(ptr noalias noundef align 8 dereferenceable(8) %r, i64 noundef %0)
#[no_mangle]
pub fn replace_short_array_u64x1(r: &mut [u64; 1], v: [u64; 1]) -> [u64; 1] {
std::mem::replace(r, v)
}

// CHECK: define noundef i32 @replace_short_array_u32x1(ptr noalias noundef align 4 dereferenceable(4) %r, i32 noundef %0)
#[no_mangle]
pub fn replace_short_array_u32x1(r: &mut [u32; 1], v: [u32; 1]) -> [u32; 1] {
std::mem::replace(r, v)
}

// CHECK: define noundef i64 @replace_short_array_u32x2(ptr noalias noundef align 4 dereferenceable(8) %r, i64 noundef %0)
#[no_mangle]
pub fn replace_short_array_u32x2(r: &mut [u32; 2], v: [u32; 2]) -> [u32; 2] {
std::mem::replace(r, v)
}

// CHECK: define noundef i16 @replace_short_array_u16x1(ptr noalias noundef align 2 dereferenceable(2) %r, i16 noundef %0)
#[no_mangle]
pub fn replace_short_array_u16x1(r: &mut [u16; 1], v: [u16; 1]) -> [u16; 1] {
std::mem::replace(r, v)
}

// CHECK: define noundef i32 @replace_short_array_u16x2(ptr noalias noundef align 2 dereferenceable(4) %r, i32 noundef %0)
#[no_mangle]
pub fn replace_short_array_u16x2(r: &mut [u16; 2], v: [u16; 2]) -> [u16; 2] {
std::mem::replace(r, v)
}

// CHECK: define noundef i48 @replace_short_array_u16x3(ptr noalias noundef align 2 dereferenceable(6) %r, i48 noundef %0)
#[no_mangle]
pub fn replace_short_array_u16x3(r: &mut [u16; 3], v: [u16; 3]) -> [u16; 3] {
std::mem::replace(r, v)
}

// CHECK: define noundef i64 @replace_short_array_u16x4(ptr noalias noundef align 2 dereferenceable(8) %r, i64 noundef %0)
#[no_mangle]
pub fn replace_short_array_u16x4(r: &mut [u16; 4], v: [u16; 4]) -> [u16; 4] {
std::mem::replace(r, v)
}

// CHECK: define noundef i8 @replace_short_array_u8x1(ptr noalias noundef align 1 dereferenceable(1) %r, i8 noundef %0)
#[no_mangle]
pub fn replace_short_array_u8x1(r: &mut [u8; 1], v: [u8; 1]) -> [u8; 1] {
std::mem::replace(r, v)
}

// CHECK: define noundef i16 @replace_short_array_u8x2(ptr noalias noundef align 1 dereferenceable(2) %r, i16 noundef %0)
#[no_mangle]
pub fn replace_short_array_u8x2(r: &mut [u8; 2], v: [u8; 2]) -> [u8; 2] {
std::mem::replace(r, v)
}

// CHECK: define noundef i24 @replace_short_array_u8x3(ptr noalias noundef align 1 dereferenceable(3) %r, i24 noundef %0)
#[no_mangle]
pub fn replace_short_array_u8x3(r: &mut [u8; 3], v: [u8; 3]) -> [u8; 3] {
std::mem::replace(r, v)
}

// CHECK: define noundef i64 @replace_short_array_u8x8(ptr noalias noundef align 1 dereferenceable(8) %r, i64 noundef %0)
#[no_mangle]
pub fn replace_short_array_u8x8(r: &mut [u8; 8], v: [u8; 8]) -> [u8; 8] {
std::mem::replace(r, v)
}

#[repr(transparent)]
pub struct Foo([u8; 4]);

// CHECK: define noundef i32 @replace_repr_transparent_struct_short_array(ptr noalias noundef align 1 dereferenceable(4) %r, i32 noundef %0)
#[no_mangle]
pub fn replace_repr_transparent_struct_short_array(r: &mut Foo, v: Foo) -> Foo {
std::mem::replace(r, v)
}

#[repr(transparent)]
pub enum Bar {
Default([u8; 4])
}

// CHECK: define noundef i32 @replace_repr_transparent_enum_short_array(ptr noalias noundef align 1 dereferenceable(4) %r, i32 noundef %0)
#[no_mangle]
pub fn replace_repr_transparent_enum_short_array(r: &mut Bar, v: Bar) -> Bar {
std::mem::replace(r, v)
}

0 comments on commit 6be5114

Please sign in to comment.