Skip to content

Put noundef on all scalars that don't allow uninit #106294

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 17, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
@@ -501,7 +501,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
layout: TyAndLayout<'tcx>,
offset: Size,
) {
if !scalar.is_always_valid(bx) {
if !scalar.is_uninit_valid() {
bx.noundef_metadata(load);
}

8 changes: 1 addition & 7 deletions compiler/rustc_ty_utils/src/abi.rs
Original file line number Diff line number Diff line change
@@ -219,8 +219,7 @@ fn adjust_for_rust_scalar<'tcx>(
return;
}

// Scalars which have invalid values cannot be undef.
if !scalar.is_always_valid(&cx) {
if !scalar.is_uninit_valid() {
attrs.set(ArgAttribute::NoUndef);
}

@@ -246,11 +245,6 @@ fn adjust_for_rust_scalar<'tcx>(
PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
};

// `Box`, `&T`, and `&mut T` cannot be undef.
// Note that this only applies to the value of the pointer itself;
// this attribute doesn't make it UB for the pointed-to data to be undef.
attrs.set(ArgAttribute::NoUndef);

// The aliasing rules for `Box<T>` are still not decided, but currently we emit
// `noalias` for it. This can be turned off using an unstable flag.
// See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
2 changes: 1 addition & 1 deletion tests/codegen/abi-sysv64.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
// of the sysv64 abi.
//
// needs-llvm-components: x86
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu -Copt-level=0

#![crate_type = "lib"]
#![no_core]
2 changes: 1 addition & 1 deletion tests/codegen/abi-x86-interrupt.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
// of the x86-interrupt abi.

// needs-llvm-components: x86
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu -Copt-level=0

#![crate_type = "lib"]
#![no_core]
2 changes: 1 addition & 1 deletion tests/codegen/adjustments.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0

#![crate_type = "lib"]

2 changes: 1 addition & 1 deletion tests/codegen/box-maybe-uninit-llvm14.rs
Original file line number Diff line number Diff line change
@@ -31,4 +31,4 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
// Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc
// from the CHECK-NOT above. We don't check the attributes here because we can't rely
// on all of them being set until LLVM 15.
// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}}, i{{[0-9]+.*}})
// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)
2 changes: 1 addition & 1 deletion tests/codegen/box-maybe-uninit.rs
Original file line number Diff line number Diff line change
@@ -28,6 +28,6 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {

// Hide the `allocalign` attribute in the declaration of __rust_alloc
// from the CHECK-NOT above, and also verify the attributes got set reasonably.
// CHECK: declare noalias ptr @__rust_alloc(i{{[0-9]+}}, i{{[0-9]+}} allocalign) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
// CHECK: declare noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]

// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }
2 changes: 1 addition & 1 deletion tests/codegen/c-variadic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ignore-wasm32-bare compiled with panic=abort by default
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0
//

#![crate_type = "lib"]
2 changes: 1 addition & 1 deletion tests/codegen/call-llvm-intrinsics.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0

// ignore-riscv64

8 changes: 4 additions & 4 deletions tests/codegen/comparison-operators-newtype.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ use std::cmp::Ordering;
pub struct Foo(u16);

// CHECK-LABEL: @check_lt
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
#[no_mangle]
pub fn check_lt(a: Foo, b: Foo) -> bool {
// CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]]
@@ -22,7 +22,7 @@ pub fn check_lt(a: Foo, b: Foo) -> bool {
}

// CHECK-LABEL: @check_le
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
#[no_mangle]
pub fn check_le(a: Foo, b: Foo) -> bool {
// CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]]
@@ -31,7 +31,7 @@ pub fn check_le(a: Foo, b: Foo) -> bool {
}

// CHECK-LABEL: @check_gt
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
#[no_mangle]
pub fn check_gt(a: Foo, b: Foo) -> bool {
// CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]]
@@ -40,7 +40,7 @@ pub fn check_gt(a: Foo, b: Foo) -> bool {
}

// CHECK-LABEL: @check_ge
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
#[no_mangle]
pub fn check_ge(a: Foo, b: Foo) -> bool {
// CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]]
10 changes: 5 additions & 5 deletions tests/codegen/dllimports/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This test is for *-windows-msvc only.
// This test is for *-windows-msvc only.
// only-windows
// ignore-gnu

@@ -15,10 +15,10 @@ extern crate wrapper;
// CHECK: @static_global1 = external local_unnamed_addr global i32
// CHECK: @static_global2 = external local_unnamed_addr global i32

// CHECK: declare dllimport i32 @dylib_func1(i32)
// CHECK: declare dllimport i32 @dylib_func2(i32)
// CHECK: declare i32 @static_func1(i32)
// CHECK: declare i32 @static_func2(i32)
// CHECK: declare dllimport noundef i32 @dylib_func1(i32 noundef)
// CHECK: declare dllimport noundef i32 @dylib_func2(i32 noundef)
// CHECK: declare noundef i32 @static_func1(i32 noundef)
// CHECK: declare noundef i32 @static_func2(i32 noundef)

#[link(name = "dummy", kind="dylib")]
extern "C" {
6 changes: 3 additions & 3 deletions tests/codegen/enum-match.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ pub enum Enum0 {
B,
}

// CHECK: define i8 @match0{{.*}}
// CHECK: define noundef i8 @match0{{.*}}
// CHECK-NEXT: start:
// CHECK-NEXT: %1 = icmp eq i8 %0, 2
// CHECK-NEXT: %2 = and i8 %0, 1
@@ -32,7 +32,7 @@ pub enum Enum1 {
C,
}

// CHECK: define i8 @match1{{.*}}
// CHECK: define noundef i8 @match1{{.*}}
// CHECK-NEXT: start:
// CHECK-NEXT: [[DISCR:%.*]] = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1)
// CHECK-NEXT: switch i8 [[DISCR]], label {{.*}} [
@@ -88,7 +88,7 @@ pub enum Enum2 {
E,
}

// CHECK: define i8 @match2{{.*}}
// CHECK: define noundef i8 @match2{{.*}}
// CHECK-NEXT: start:
// CHECK-NEXT: %1 = add i8 %0, 2
// CHECK-NEXT: %2 = zext i8 %1 to i64
12 changes: 6 additions & 6 deletions tests/codegen/fastcall-inreg.rs
Original file line number Diff line number Diff line change
@@ -15,27 +15,27 @@ trait Sized {}
trait Copy {}

pub mod tests {
// CHECK: @f1(i32 inreg %_1, i32 inreg %_2, i32 %_3)
// CHECK: @f1(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 noundef %_3)
#[no_mangle]
pub extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}

// CHECK: @f2({{i32\*|ptr}} inreg %_1, {{i32\*|ptr}} inreg %_2, {{i32\*|ptr}} %_3)
// CHECK: @f2({{i32\*|ptr}} inreg noundef %_1, {{i32\*|ptr}} inreg noundef %_2, {{i32\*|ptr}} noundef %_3)
#[no_mangle]
pub extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}

// CHECK: @f3(float %_1, i32 inreg %_2, i32 inreg %_3, i32 %_4)
// CHECK: @f3(float noundef %_1, i32 inreg noundef %_2, i32 inreg noundef %_3, i32 noundef %_4)
#[no_mangle]
pub extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {}

// CHECK: @f4(i32 inreg %_1, float %_2, i32 inreg %_3, i32 %_4)
// CHECK: @f4(i32 inreg noundef %_1, float noundef %_2, i32 inreg noundef %_3, i32 noundef %_4)
#[no_mangle]
pub extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {}

// CHECK: @f5(i64 %_1, i32 %_2)
// CHECK: @f5(i64 noundef %_1, i32 noundef %_2)
#[no_mangle]
pub extern "fastcall" fn f5(_: i64, _: i32) {}

// CHECK: @f6(i1 inreg noundef zeroext %_1, i32 inreg %_2, i32 %_3)
// CHECK: @f6(i1 inreg noundef zeroext %_1, i32 inreg noundef %_2, i32 noundef %_3)
#[no_mangle]
pub extern "fastcall" fn f6(_: bool, _: i32, _: i32) {}
}
4 changes: 2 additions & 2 deletions tests/codegen/fewer-names.rs
Original file line number Diff line number Diff line change
@@ -7,11 +7,11 @@

#[no_mangle]
pub fn sum(x: u32, y: u32) -> u32 {
// YES-LABEL: define{{.*}}i32 @sum(i32 %0, i32 %1)
// YES-LABEL: define{{.*}}i32 @sum(i32 noundef %0, i32 noundef %1)
// YES-NEXT: %3 = add i32 %1, %0
// YES-NEXT: ret i32 %3

// NO-LABEL: define{{.*}}i32 @sum(i32 %x, i32 %y)
// NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
// NO-NEXT: start:
// NO-NEXT: %z = add i32 %y, %x
// NO-NEXT: ret i32 %z
2 changes: 1 addition & 1 deletion tests/codegen/frame-pointer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: --crate-type=rlib
// compile-flags: --crate-type=rlib -Copt-level=0
// revisions: aarch64-apple aarch64-linux force x64-apple x64-linux
// [aarch64-apple] needs-llvm-components: aarch64
// [aarch64-apple] compile-flags: --target=aarch64-apple-darwin
58 changes: 42 additions & 16 deletions tests/codegen/function-arguments.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// compile-flags: -O -C no-prepopulate-passes

#![crate_type = "lib"]
#![feature(rustc_attrs)]

use std::mem::MaybeUninit;
use std::num::NonZeroU64;
use std::marker::PhantomPinned;
use std::ptr::NonNull;

pub struct S {
_field: [i32; 8],
@@ -61,7 +61,7 @@ pub fn maybeuninit_char(x: MaybeUninit<char>) -> MaybeUninit<char> {
x
}

// CHECK: i64 @int(i64 %x)
// CHECK: noundef i64 @int(i64 noundef %x)
#[no_mangle]
pub fn int(x: u64) -> u64 {
x
@@ -73,7 +73,7 @@ pub fn nonzero_int(x: NonZeroU64) -> NonZeroU64 {
x
}

// CHECK: i64 @option_nonzero_int(i64 %x)
// CHECK: noundef i64 @option_nonzero_int(i64 noundef %x)
#[no_mangle]
pub fn option_nonzero_int(x: Option<NonZeroU64>) -> Option<NonZeroU64> {
x
@@ -138,11 +138,27 @@ pub fn indirect_struct(_: S) {
pub fn borrowed_struct(_: &S) {
}

// CHECK: @raw_struct({{%S\*|ptr}} %_1)
// CHECK: @option_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable_or_null(4) %x)
#[no_mangle]
pub fn option_borrow(x: Option<&i32>) {
}

// CHECK: @option_borrow_mut({{i32\*|ptr}} noalias noundef align 4 dereferenceable_or_null(4) %x)
#[no_mangle]
pub fn option_borrow_mut(x: Option<&mut i32>) {
}

// CHECK: @raw_struct({{%S\*|ptr}} noundef %_1)
#[no_mangle]
pub fn raw_struct(_: *const S) {
}

// CHECK: @raw_option_nonnull_struct({{i32\*|ptr}} noundef %_1)
#[no_mangle]
pub fn raw_option_nonnull_struct(_: Option<NonNull<S>>) {
}


// `Box` can get deallocated during execution of the function, so it should
// not get `dereferenceable`.
// CHECK: noundef nonnull align 4 {{i32\*|ptr}} @_box({{i32\*|ptr}} noalias noundef nonnull align 4 %x)
@@ -160,35 +176,35 @@ pub fn struct_return() -> S {
}

// Hack to get the correct size for the length part in slices
// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
// CHECK: @helper([[USIZE:i[0-9]+]] noundef %_1)
#[no_mangle]
pub fn helper(_: usize) {
}

// CHECK: @slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] %_1.1)
// CHECK: @slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn slice(_: &[u8]) {
}

// CHECK: @mutable_slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull align 1 %_1.0, [[USIZE]] %_1.1)
// CHECK: @mutable_slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull align 1 %_1.0, [[USIZE]] noundef %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn mutable_slice(_: &mut [u8]) {
}

// CHECK: @unsafe_slice({{\[0 x i16\]\*|ptr}} noundef nonnull align 2 %_1.0, [[USIZE]] %_1.1)
// CHECK: @unsafe_slice({{\[0 x i16\]\*|ptr}} noundef nonnull align 2 %_1.0, [[USIZE]] noundef %_1.1)
// unsafe interior means this isn't actually readonly and there may be aliases ...
#[no_mangle]
pub fn unsafe_slice(_: &[UnsafeInner]) {
}

// CHECK: @raw_slice({{\[0 x i8\]\*|ptr}} %_1.0, [[USIZE]] %_1.1)
// CHECK: @raw_slice({{\[0 x i8\]\*|ptr}} noundef %_1.0, [[USIZE]] noundef %_1.1)
#[no_mangle]
pub fn raw_slice(_: *const [u8]) {
}

// CHECK: @str({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] %_1.1)
// CHECK: @str({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn str(_: &[u8]) {
@@ -197,26 +213,36 @@ pub fn str(_: &[u8]) {
// CHECK: @trait_borrow({{\{\}\*|ptr}} noundef nonnull align 1 %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn trait_borrow(_: &Drop) {
pub fn trait_borrow(_: &dyn Drop) {
}

// CHECK: @option_trait_borrow({{i8\*|ptr}} noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
#[no_mangle]
pub fn option_trait_borrow(x: Option<&dyn Drop>) {
}

// CHECK: @option_trait_borrow_mut({{i8\*|ptr}} noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
#[no_mangle]
pub fn option_trait_borrow_mut(x: Option<&mut dyn Drop>) {
}

// CHECK: @trait_raw({{\{\}\*|ptr}} %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
// CHECK: @trait_raw({{\{\}\*|ptr}} noundef %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
#[no_mangle]
pub fn trait_raw(_: *const Drop) {
pub fn trait_raw(_: *const dyn Drop) {
}

// CHECK: @trait_box({{\{\}\*|ptr}} noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
#[no_mangle]
pub fn trait_box(_: Box<Drop>) {
pub fn trait_box(_: Box<dyn Drop>) {
}

// CHECK: { {{i8\*|ptr}}, {{i8\*|ptr}} } @trait_option({{i8\*|ptr}} noalias noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
#[no_mangle]
pub fn trait_option(x: Option<Box<Drop>>) -> Option<Box<Drop>> {
pub fn trait_option(x: Option<Box<dyn Drop>>) -> Option<Box<dyn Drop>> {
x
}

// CHECK: { {{\[0 x i16\]\*|ptr}}, [[USIZE]] } @return_slice({{\[0 x i16\]\*|ptr}} noalias noundef nonnull readonly align 2 %x.0, [[USIZE]] %x.1)
// CHECK: { {{\[0 x i16\]\*|ptr}}, [[USIZE]] } @return_slice({{\[0 x i16\]\*|ptr}} noalias noundef nonnull readonly align 2 %x.0, [[USIZE]] noundef %x.1)
#[no_mangle]
pub fn return_slice(x: &[u16]) -> &[u16] {
x
2 changes: 1 addition & 1 deletion tests/codegen/intrinsics/const_eval_select.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0

#![crate_type = "lib"]
#![feature(const_eval_select)]
3 changes: 2 additions & 1 deletion tests/codegen/intrinsics/mask.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// compile-flags: -Copt-level=0
#![crate_type = "lib"]
#![feature(core_intrinsics)]

@@ -6,6 +7,6 @@
#[no_mangle]
pub fn mask_ptr(ptr: *const u16, mask: usize) -> *const u16 {
// CHECK: call
// CHECK-SAME: @llvm.ptrmask.{{p0|p0i8}}.[[WORD]]({{ptr|i8\*}} {{%ptr|%0}}, [[WORD]] %mask)
// CHECK-SAME: @llvm.ptrmask.{{p0|p0i8}}.[[WORD]]({{ptr|i8\*}} {{%ptr|%1}}, [[WORD]] %mask)
core::intrinsics::ptr_mask(ptr, mask)
}
2 changes: 1 addition & 1 deletion tests/codegen/issue-32031.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0

#![crate_type = "lib"]

2 changes: 1 addition & 1 deletion tests/codegen/issue-58881.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0
//
// only-x86_64
// ignore-windows
2 changes: 1 addition & 1 deletion tests/codegen/iter-repeat-n-trivial-drop.rs
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCop
#[no_mangle]
// CHECK-LABEL: @vec_extend_via_iter_repeat_n
pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
// CHECK: %[[ADDR:.+]] = tail call dereferenceable_or_null(1234) ptr @__rust_alloc(i64 1234, i64 1)
// CHECK: %[[ADDR:.+]] = tail call noundef dereferenceable_or_null(1234) ptr @__rust_alloc(i64 noundef 1234, i64 noundef 1)
// CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234,

let n = 1234_usize;
8 changes: 4 additions & 4 deletions tests/codegen/loads.rs
Original file line number Diff line number Diff line change
@@ -50,8 +50,8 @@ pub fn load_scalar_pair<'a>(x: &(&'a i32, &'a Align16)) -> (&'a i32, &'a Align16
// CHECK-LABEL: @load_raw_pointer
#[no_mangle]
pub fn load_raw_pointer<'a>(x: &*const i32) -> *const i32 {
// loaded raw pointer should not have !nonnull, !align, or !noundef metadata
// CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x, align [[PTR_ALIGNMENT]]{{$}}
// loaded raw pointer should not have !nonnull or !align metadata
// CHECK: load {{i32\*|ptr}}, {{i32\*\*|ptr}} %x, align [[PTR_ALIGNMENT]], !noundef ![[NOUNDEF:[0-9]+]]{{$}}
*x
}

@@ -93,7 +93,7 @@ pub fn load_maybeuninit_enum_bool(x: &MaybeUninit<MyBool>) -> MaybeUninit<MyBool
// CHECK-LABEL: @load_int
#[no_mangle]
pub fn load_int(x: &u16) -> u16 {
// CHECK: load i16, {{i16\*|ptr}} %x, align 2{{$}}
// CHECK: load i16, {{i16\*|ptr}} %x, align 2, !noundef ![[NOUNDEF]]{{$}}
*x
}

@@ -107,7 +107,7 @@ pub fn load_nonzero_int(x: &NonZeroU16) -> NonZeroU16 {
// CHECK-LABEL: @load_option_nonzero_int
#[no_mangle]
pub fn load_option_nonzero_int(x: &Option<NonZeroU16>) -> Option<NonZeroU16> {
// CHECK: load i16, {{i16\*|ptr}} %x, align 2{{$}}
// CHECK: load i16, {{i16\*|ptr}} %x, align 2, !noundef ![[NOUNDEF]]{{$}}
*x
}

2 changes: 1 addition & 1 deletion tests/codegen/naked-functions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0
// needs-asm-support
// only-x86_64

2 changes: 1 addition & 1 deletion tests/codegen/pic-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C relocation-model=pic
// compile-flags: -C relocation-model=pic -Copt-level=0

#![crate_type = "rlib"]

2 changes: 1 addition & 1 deletion tests/codegen/pie-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C relocation-model=pie
// compile-flags: -C relocation-model=pie -Copt-level=0
// only-x86_64-unknown-linux-gnu

#![crate_type = "rlib"]
2 changes: 1 addition & 1 deletion tests/codegen/refs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0
// compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 -Copt-level=0

#![crate_type = "lib"]

28 changes: 14 additions & 14 deletions tests/codegen/repr-transparent.rs
Original file line number Diff line number Diff line change
@@ -18,36 +18,36 @@ pub struct Zst2(());
#[repr(transparent)]
pub struct F32(f32);

// CHECK: define{{.*}}float @test_F32(float %_1)
// CHECK: define{{.*}}float @test_F32(float noundef %_1)
#[no_mangle]
pub extern "C" fn test_F32(_: F32) -> F32 { loop {} }

#[repr(transparent)]
pub struct Ptr(*mut u8);

// CHECK: define{{.*}}{{i8\*|ptr}} @test_Ptr({{i8\*|ptr}} %_1)
// CHECK: define{{.*}}{{i8\*|ptr}} @test_Ptr({{i8\*|ptr}} noundef %_1)
#[no_mangle]
pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} }

#[repr(transparent)]
pub struct WithZst(u64, Zst1);

// CHECK: define{{.*}}i64 @test_WithZst(i64 %_1)
// CHECK: define{{.*}}i64 @test_WithZst(i64 noundef %_1)
#[no_mangle]
pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} }

#[repr(transparent)]
pub struct WithZeroSizedArray(*const f32, [i8; 0]);

// Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever.
// CHECK: define{{.*}}{{i32\*|ptr}} @test_WithZeroSizedArray({{i32\*|ptr}} %_1)
// CHECK: define{{.*}}{{i32\*|ptr}} @test_WithZeroSizedArray({{i32\*|ptr}} noundef %_1)
#[no_mangle]
pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }

#[repr(transparent)]
pub struct Generic<T>(T);

// CHECK: define{{.*}}double @test_Generic(double %_1)
// CHECK: define{{.*}}double @test_Generic(double noundef %_1)
#[no_mangle]
pub extern "C" fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }

@@ -64,7 +64,7 @@ pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { lo
#[repr(transparent)]
pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);

// CHECK: define{{.*}}{{i16\*|ptr}} @test_LifetimePhantom({{i16\*|ptr}} %_1)
// CHECK: define{{.*}}{{i16\*|ptr}} @test_LifetimePhantom({{i16\*|ptr}} noundef %_1)
#[no_mangle]
pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }

@@ -74,28 +74,28 @@ pub struct UnitPhantom<T, U> { val: T, unit: PhantomData<U> }

pub struct Px;

// CHECK: define{{.*}}float @test_UnitPhantom(float %_1)
// CHECK: define{{.*}}float @test_UnitPhantom(float noundef %_1)
#[no_mangle]
pub extern "C" fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }

#[repr(transparent)]
pub struct TwoZsts(Zst1, i8, Zst2);

// CHECK: define{{( dso_local)?}}{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1)
// CHECK: define{{( dso_local)?}} noundef{{( signext)?}} i8 @test_TwoZsts(i8 noundef{{( signext)?}} %_1)
#[no_mangle]
pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }

#[repr(transparent)]
pub struct Nested1(Zst2, Generic<f64>);

// CHECK: define{{.*}}double @test_Nested1(double %_1)
// CHECK: define{{.*}}double @test_Nested1(double noundef %_1)
#[no_mangle]
pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { loop {} }

#[repr(transparent)]
pub struct Nested2(Nested1, Zst1);

// CHECK: define{{.*}}double @test_Nested2(double %_1)
// CHECK: define{{.*}}double @test_Nested2(double noundef %_1)
#[no_mangle]
pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { loop {} }

@@ -115,7 +115,7 @@ impl<T: ?Sized> Mirror for T { type It = Self; }
#[repr(transparent)]
pub struct StructWithProjection(<f32 as Mirror>::It);

// CHECK: define{{.*}}float @test_Projection(float %_1)
// CHECK: define{{.*}}float @test_Projection(float noundef %_1)
#[no_mangle]
pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }

@@ -124,7 +124,7 @@ pub enum EnumF32 {
Variant(F32)
}

// CHECK: define{{.*}}float @test_EnumF32(float %_1)
// CHECK: define{{.*}}float @test_EnumF32(float noundef %_1)
#[no_mangle]
pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} }

@@ -133,7 +133,7 @@ pub enum EnumF32WithZsts {
Variant(Zst1, F32, Zst2)
}

// CHECK: define{{.*}}float @test_EnumF32WithZsts(float %_1)
// CHECK: define{{.*}}float @test_EnumF32WithZsts(float noundef %_1)
#[no_mangle]
pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} }

@@ -142,7 +142,7 @@ pub union UnionF32 {
field: F32,
}

// CHECK: define{{.*}}float @test_UnionF32(float %_1)
// CHECK: define{{.*}} float @test_UnionF32(float %_1)
#[no_mangle]
pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }

18 changes: 9 additions & 9 deletions tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs
Original file line number Diff line number Diff line change
@@ -29,25 +29,25 @@ pub extern "C" fn f_scalar_0(a: bool) -> bool {
a
}

// CHECK: define signext i8 @f_scalar_1(i8 signext %x)
// CHECK: define noundef signext i8 @f_scalar_1(i8 noundef signext %x)
#[no_mangle]
pub extern "C" fn f_scalar_1(x: i8) -> i8 {
x
}

// CHECK: define zeroext i8 @f_scalar_2(i8 zeroext %x)
// CHECK: define noundef zeroext i8 @f_scalar_2(i8 noundef zeroext %x)
#[no_mangle]
pub extern "C" fn f_scalar_2(x: u8) -> u8 {
x
}

// CHECK: define signext i32 @f_scalar_3(i32 signext %x)
// CHECK: define noundef signext i32 @f_scalar_3(i32 noundef signext %x)
#[no_mangle]
pub extern "C" fn f_scalar_3(x: i32) -> u32 {
x as u32
}

// CHECK: define i64 @f_scalar_4(i64 %x)
// CHECK: define noundef i64 @f_scalar_4(i64 noundef %x)
#[no_mangle]
pub extern "C" fn f_scalar_4(x: i64) -> i64 {
x
@@ -132,13 +132,13 @@ pub struct Large {
pub extern "C" fn f_agg_large(mut x: Large) {
}

// CHECK: define void @f_agg_large_ret({{%Large\*|ptr}} {{.*}}sret{{.*}}, i32 signext %i, i8 signext %j)
// CHECK: define void @f_agg_large_ret({{%Large\*|ptr}} {{.*}}sret{{.*}}, i32 noundef signext %i, i8 noundef signext %j)
#[no_mangle]
pub extern "C" fn f_agg_large_ret(i: i32, j: i8) -> Large {
Large { a: 1, b: 2, c: 3, d: 4 }
}

// CHECK: define void @f_scalar_stack_1(i64 %0, [2 x i64] %1, i128 %2, {{%Large\*|ptr}} {{.*}}%d, i8 zeroext %e, i8 signext %f, i8 %g, i8 %h)
// CHECK: define void @f_scalar_stack_1(i64 %0, [2 x i64] %1, i128 %2, {{%Large\*|ptr}} {{.*}}%d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef %g, i8 noundef %h)
#[no_mangle]
pub extern "C" fn f_scalar_stack_1(
a: Tiny,
@@ -152,7 +152,7 @@ pub extern "C" fn f_scalar_stack_1(
) {
}

// CHECK: define void @f_scalar_stack_2({{%Large\*|ptr}} {{.*}}sret{{.*}} %0, i64 %a, i128 %1, i128 %2, i64 %d, i8 zeroext %e, i8 %f, i8 %g)
// CHECK: define void @f_scalar_stack_2({{%Large\*|ptr}} {{.*}}sret{{.*}} %0, i64 noundef %a, i128 %1, i128 %2, i64 noundef %d, i8 noundef zeroext %e, i8 noundef %f, i8 noundef %g)
#[no_mangle]
pub extern "C" fn f_scalar_stack_2(
a: u64,
@@ -172,7 +172,7 @@ extern "C" {

#[no_mangle]
pub unsafe extern "C" fn f_va_caller() {
// CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i64 3, double {{.*}}, double {{.*}}, i64 {{.*}}, [2 x i64] {{.*}}, i128 {{.*}}, {{%Large\*|ptr}} {{.*}})
// CHECK: call noundef signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i64 noundef 3, double {{.*}}, double {{.*}}, i64 {{.*}}, [2 x i64] {{.*}}, i128 {{.*}}, {{%Large\*|ptr}} {{.*}})
f_va_callee(
1,
2i32,
@@ -184,6 +184,6 @@ pub unsafe extern "C" fn f_va_caller() {
SmallAligned { a: 11 },
Large { a: 12, b: 13, c: 14, d: 15 },
);
// CHECK: call signext i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i128 {{.*}}, i32 signext 6, i32 signext 7, i32 8, i32 9)
// CHECK: call noundef signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i32 noundef signext 3, i32 noundef signext 4, i128 {{.*}}, i32 noundef signext 6, i32 noundef signext 7, i32 noundef 8, i32 noundef 9)
f_va_callee(1, 2i32, 3i32, 4i32, SmallAligned { a: 5 }, 6i32, 7i32, 8i32, 9i32);
}
2 changes: 1 addition & 1 deletion tests/codegen/sanitizer-cfi-emit-type-checks.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Verifies that pointer type membership tests for indirect calls are emitted.
//
// needs-sanitizer-cfi
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0

#![crate_type="lib"]

Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
// [aarch64] needs-llvm-components: aarch64
// [x86_64] compile-flags: --target x86_64-unknown-none
// [x86_64] needs-llvm-components:
// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi
// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0

#![crate_type="lib"]
#![feature(no_core, lang_items)]
10 changes: 5 additions & 5 deletions tests/codegen/sanitizer-recover.rs
Original file line number Diff line number Diff line change
@@ -6,8 +6,8 @@
// revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER MSAN-RECOVER-LTO
// no-prefer-dynamic
//
//[ASAN] compile-flags: -Zsanitizer=address
//[ASAN-RECOVER] compile-flags: -Zsanitizer=address -Zsanitizer-recover=address
//[ASAN] compile-flags: -Zsanitizer=address -Copt-level=0
//[ASAN-RECOVER] compile-flags: -Zsanitizer=address -Zsanitizer-recover=address -Copt-level=0
//[MSAN] compile-flags: -Zsanitizer=memory
//[MSAN-RECOVER] compile-flags: -Zsanitizer=memory -Zsanitizer-recover=memory
//[MSAN-RECOVER-LTO] compile-flags: -Zsanitizer=memory -Zsanitizer-recover=memory -C lto=fat
@@ -26,17 +26,17 @@
// ASAN-RECOVER-NOT: unreachable
// ASAN: }
//
// MSAN-LABEL: define dso_local i32 @penguin(
// MSAN-LABEL: define dso_local noundef i32 @penguin(
// MSAN: call void @__msan_warning{{(_with_origin_noreturn\(i32 0\)|_noreturn\(\))}}
// MSAN: unreachable
// MSAN: }
//
// MSAN-RECOVER-LABEL: define dso_local i32 @penguin(
// MSAN-RECOVER-LABEL: define dso_local noundef i32 @penguin(
// MSAN-RECOVER: call void @__msan_warning{{(_with_origin\(i32 0\)|\(\))}}
// MSAN-RECOVER-NOT: unreachable
// MSAN-RECOVER: }
//
// MSAN-RECOVER-LTO-LABEL: define dso_local i32 @penguin(
// MSAN-RECOVER-LTO-LABEL: define dso_local noundef i32 @penguin(
// MSAN-RECOVER-LTO: call void @__msan_warning{{(_with_origin\(i32 0\)|\(\))}}
// MSAN-RECOVER-LTO-NOT: unreachable
// MSAN-RECOVER-LTO: }
4 changes: 2 additions & 2 deletions tests/codegen/scalar-pair-bool.rs
Original file line number Diff line number Diff line change
@@ -8,13 +8,13 @@ pub fn pair_bool_bool(pair: (bool, bool)) -> (bool, bool) {
pair
}

// CHECK: define{{.*}}{ i8, i32 } @pair_bool_i32(i1 noundef zeroext %pair.0, i32 %pair.1)
// CHECK: define{{.*}}{ i8, i32 } @pair_bool_i32(i1 noundef zeroext %pair.0, i32 noundef %pair.1)
#[no_mangle]
pub fn pair_bool_i32(pair: (bool, i32)) -> (bool, i32) {
pair
}

// CHECK: define{{.*}}{ i32, i8 } @pair_i32_bool(i32 %pair.0, i1 noundef zeroext %pair.1)
// CHECK: define{{.*}}{ i32, i8 } @pair_i32_bool(i32 noundef %pair.0, i1 noundef zeroext %pair.1)
#[no_mangle]
pub fn pair_i32_bool(pair: (i32, bool)) -> (i32, bool) {
pair
2 changes: 1 addition & 1 deletion tests/codegen/some-abis-do-extend-params-to-32-bits.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -Cno-prepopulate-passes
// compile-flags: -Cno-prepopulate-passes -Copt-level=0

// revisions:x86_64 i686 aarch64-apple aarch64-windows aarch64-linux arm riscv

4 changes: 2 additions & 2 deletions tests/codegen/static-relocation-model-msvc.rs
Original file line number Diff line number Diff line change
@@ -15,8 +15,8 @@ extern crate extern_decl;
// it to be marked `dso_local` as well, given the static relocation model.
//
// CHECK: @extern_static = external dso_local local_unnamed_addr global i8
// CHECK: define dso_local i8 @access_extern() {{.*}}
// CHECK: declare dso_local i8 @extern_fn() {{.*}}
// CHECK: define dso_local noundef i8 @access_extern() {{.*}}
// CHECK: declare dso_local noundef i8 @extern_fn() {{.*}}

#[no_mangle]
pub fn access_extern() -> u8 {
10 changes: 5 additions & 5 deletions tests/codegen/transmute-scalar.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
// FIXME(eddyb) all of these tests show memory stores and loads, even after a
// scalar `bitcast`, more special-casing is required to remove `alloca` usage.

// CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float %x)
// CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float noundef %x)
// CHECK: store i32 %{{.*}}, {{.*}} %0
// CHECK-NEXT: %[[RES:.*]] = load i32, {{.*}} %0
// CHECK: ret i32 %[[RES]]
@@ -24,7 +24,7 @@ pub fn bool_to_byte(b: bool) -> u8 {
unsafe { std::mem::transmute(b) }
}

// CHECK-LABEL: define{{.*}}noundef zeroext i1 @byte_to_bool(i8 %byte)
// CHECK-LABEL: define{{.*}}noundef zeroext i1 @byte_to_bool(i8 noundef %byte)
// CHECK: %1 = trunc i8 %byte to i1
// CHECK-NEXT: %2 = zext i1 %1 to i8
// CHECK-NEXT: store i8 %2, {{.*}} %0
@@ -36,7 +36,7 @@ pub unsafe fn byte_to_bool(byte: u8) -> bool {
std::mem::transmute(byte)
}

// CHECK-LABEL: define{{.*}}{{i8\*|ptr}} @ptr_to_ptr({{i16\*|ptr}} %p)
// CHECK-LABEL: define{{.*}}{{i8\*|ptr}} @ptr_to_ptr({{i16\*|ptr}} noundef %p)
// CHECK: store {{i8\*|ptr}} %{{.*}}, {{.*}} %0
// CHECK-NEXT: %[[RES:.*]] = load {{i8\*|ptr}}, {{.*}} %0
// CHECK: ret {{i8\*|ptr}} %[[RES]]
@@ -52,7 +52,7 @@ pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 {
// Tests below show the non-special-cased behavior (with the possible
// future special-cased instructions in the "NOTE(eddyb)" comments).

// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int({{i16\*|ptr}} %p)
// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int({{i16\*|ptr}} noundef %p)

// NOTE(eddyb) see above, the following two CHECK lines should ideally be this:
// %2 = ptrtoint i16* %p to [[USIZE]]
@@ -66,7 +66,7 @@ pub fn ptr_to_int(p: *mut u16) -> usize {
unsafe { std::mem::transmute(p) }
}

// CHECK: define{{.*}}{{i16\*|ptr}} @int_to_ptr([[USIZE]] %i)
// CHECK: define{{.*}}{{i16\*|ptr}} @int_to_ptr([[USIZE]] noundef %i)

// NOTE(eddyb) see above, the following two CHECK lines should ideally be this:
// %2 = inttoptr [[USIZE]] %i to i16*
2 changes: 1 addition & 1 deletion tests/codegen/tuple-layout-opt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ignore-emscripten
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0

// Test that tuples get optimized layout, in particular with a ZST in the last field (#63244)

2 changes: 1 addition & 1 deletion tests/codegen/var-names.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

#![crate_type = "lib"]

// CHECK-LABEL: define{{.*}}i32 @test(i32 %a, i32 %b)
// CHECK-LABEL: define{{.*}}i32 @test(i32 noundef %a, i32 noundef %b)
#[no_mangle]
pub fn test(a: u32, b: u32) -> u32 {
let c = a + b;
2 changes: 1 addition & 1 deletion tests/codegen/vec-calloc.rs
Original file line number Diff line number Diff line change
@@ -162,6 +162,6 @@ pub fn vec_option_bool(n: usize) -> Vec<Option<bool>> {
}

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

// CHECK-DAG: attributes [[RUST_ALLOC_ZEROED_ATTRS]] = { {{.*}} allockind("alloc,zeroed,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }
2 changes: 1 addition & 1 deletion tests/codegen/zst-offset.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0

#![crate_type = "lib"]
#![feature(repr_simd)]