diff options
Diffstat (limited to 'tests/codegen')
| -rw-r--r-- | tests/codegen/aarch64-struct-align-128.rs | 150 | ||||
| -rw-r--r-- | tests/codegen/addr-of-mutate.rs | 6 | ||||
| -rw-r--r-- | tests/codegen/align-byval-vector.rs | 58 | ||||
| -rw-r--r-- | tests/codegen/align-byval.rs | 342 | ||||
| -rw-r--r-- | tests/codegen/array-map.rs | 1 | ||||
| -rw-r--r-- | tests/codegen/function-arguments-noopt.rs | 4 | ||||
| -rw-r--r-- | tests/codegen/function-arguments.rs | 4 | ||||
| -rw-r--r-- | tests/codegen/iter-repeat-n-trivial-drop.rs | 2 | ||||
| -rw-r--r-- | tests/codegen/simd-wide-sum.rs | 12 | ||||
| -rw-r--r-- | tests/codegen/slice-init.rs | 16 | ||||
| -rw-r--r-- | tests/codegen/slice-ref-equality.rs | 32 |
11 files changed, 592 insertions, 35 deletions
diff --git a/tests/codegen/aarch64-struct-align-128.rs b/tests/codegen/aarch64-struct-align-128.rs new file mode 100644 index 00000000000..bf34717786d --- /dev/null +++ b/tests/codegen/aarch64-struct-align-128.rs @@ -0,0 +1,150 @@ +// Test that structs aligned to 128 bits are passed with the correct ABI on aarch64. + +// revisions:linux darwin windows +//[linux] compile-flags: --target aarch64-unknown-linux-gnu +//[darwin] compile-flags: --target aarch64-apple-darwin +//[windows] compile-flags: --target aarch64-pc-windows-msvc +//[linux] needs-llvm-components: aarch64 +//[darwin] needs-llvm-components: aarch64 +//[windows] needs-llvm-components: aarch64 + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + + + +// Passed as `[i64 x 2]`, since it's an aggregate with size <= 128 bits, align < 128 bits. +#[repr(C)] +pub struct Align8 { + pub a: u64, + pub b: u64, +} + +// repr(transparent), so same as above. +#[repr(transparent)] +pub struct Transparent8 { + a: Align8 +} + +// Passed as `[i64 x 2]`, since it's an aggregate with size <= 128 bits, align < 128 bits. +#[repr(C)] +pub struct Wrapped8 { + a: Align8, +} + +extern "C" { + // linux: declare void @test_8([2 x i64], [2 x i64], [2 x i64]) + // darwin: declare void @test_8([2 x i64], [2 x i64], [2 x i64]) + // windows: declare void @test_8([2 x i64], [2 x i64], [2 x i64]) + fn test_8(a: Align8, b: Transparent8, c: Wrapped8); +} + + + +// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. +// EXCEPT on Linux, where there's a special case to use its unadjusted alignment, +// making it the same as `Align8`, so it's be passed as `[i64 x 2]`. +#[repr(C)] +#[repr(align(16))] +pub struct Align16 { + pub a: u64, + pub b: u64, +} + +// repr(transparent), so same as above. +#[repr(transparent)] +pub struct Transparent16 { + a: Align16 +} + +// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. +// On Linux, the "unadjustedness" doesn't recurse into fields, so this is passed as `i128`. +#[repr(C)] +pub struct Wrapped16 { + pub a: Align16, +} + +extern "C" { + // linux: declare void @test_16([2 x i64], [2 x i64], i128) + // darwin: declare void @test_16(i128, i128, i128) + // windows: declare void @test_16(i128, i128, i128) + fn test_16(a: Align16, b: Transparent16, c: Wrapped16); +} + + + +// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. +#[repr(C)] +pub struct I128 { + pub a: i128, +} + +// repr(transparent), so same as above. +#[repr(transparent)] +pub struct TransparentI128 { + a: I128 +} + +// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. +#[repr(C)] +pub struct WrappedI128 { + pub a: I128 +} + +extern "C" { + // linux: declare void @test_i128(i128, i128, i128) + // darwin: declare void @test_i128(i128, i128, i128) + // windows: declare void @test_i128(i128, i128, i128) + fn test_i128(a: I128, b: TransparentI128, c: WrappedI128); +} + + + +// Passed as `[2 x i64]`, since it's an aggregate with size <= 128 bits, align < 128 bits. +// Note that the Linux special case does not apply, because packing is not considered "adjustment". +#[repr(C)] +#[repr(packed)] +pub struct Packed { + pub a: i128, +} + +// repr(transparent), so same as above. +#[repr(transparent)] +pub struct TransparentPacked { + a: Packed +} + +// Passed as `[2 x i64]`, since it's an aggregate with size <= 128 bits, align < 128 bits. +#[repr(C)] +pub struct WrappedPacked { + pub a: Packed +} + +extern "C" { + // linux: declare void @test_packed([2 x i64], [2 x i64], [2 x i64]) + // darwin: declare void @test_packed([2 x i64], [2 x i64], [2 x i64]) + // windows: declare void @test_packed([2 x i64], [2 x i64], [2 x i64]) + fn test_packed(a: Packed, b: TransparentPacked, c: WrappedPacked); +} + + + +pub unsafe fn main( + a1: Align8, a2: Transparent8, a3: Wrapped8, + b1: Align16, b2: Transparent16, b3: Wrapped16, + c1: I128, c2: TransparentI128, c3: WrappedI128, + d1: Packed, d2: TransparentPacked, d3: WrappedPacked, +) { + test_8(a1, a2, a3); + test_16(b1, b2, b3); + test_i128(c1, c2, c3); + test_packed(d1, d2, d3); +} diff --git a/tests/codegen/addr-of-mutate.rs b/tests/codegen/addr-of-mutate.rs index bea1aad2352..6dfc1825015 100644 --- a/tests/codegen/addr-of-mutate.rs +++ b/tests/codegen/addr-of-mutate.rs @@ -6,7 +6,7 @@ // Test for the absence of `readonly` on the argument when it is mutated via `&raw const`. // See <https://github.com/rust-lang/rust/issues/111502>. -// CHECK: i8 @foo(ptr noalias nocapture noundef dereferenceable(128) %x) +// CHECK: i8 @foo(ptr noalias nocapture noundef align 1 dereferenceable(128) %x) #[no_mangle] pub fn foo(x: [u8; 128]) -> u8 { let ptr = core::ptr::addr_of!(x).cast_mut(); @@ -16,7 +16,7 @@ pub fn foo(x: [u8; 128]) -> u8 { x[0] } -// CHECK: i1 @second(ptr noalias nocapture noundef dereferenceable({{[0-9]+}}) %a_ptr_and_b) +// CHECK: i1 @second(ptr noalias nocapture noundef align {{[0-9]+}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) #[no_mangle] pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut(); @@ -25,7 +25,7 @@ pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { } // If going through a deref (and there are no other mutating accesses), then `readonly` is fine. -// CHECK: i1 @third(ptr noalias nocapture noundef readonly dereferenceable({{[0-9]+}}) %a_ptr_and_b) +// CHECK: i1 @third(ptr noalias nocapture noundef readonly align {{[0-9]+}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) #[no_mangle] pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut(); diff --git a/tests/codegen/align-byval-vector.rs b/tests/codegen/align-byval-vector.rs new file mode 100644 index 00000000000..3c8be659671 --- /dev/null +++ b/tests/codegen/align-byval-vector.rs @@ -0,0 +1,58 @@ +// revisions:x86-linux x86-darwin + +//[x86-linux] compile-flags: --target i686-unknown-linux-gnu +//[x86-linux] needs-llvm-components: x86 +//[x86-darwin] compile-flags: --target i686-apple-darwin +//[x86-darwin] needs-llvm-components: x86 + +// Tests that aggregates containing vector types get their alignment increased to 16 on Darwin. + +#![feature(no_core, lang_items, repr_simd, simd_ffi)] +#![crate_type = "lib"] +#![no_std] +#![no_core] +#![allow(non_camel_case_types)] + +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct i32x4(i32, i32, i32, i32); + +#[repr(C)] +pub struct Foo { + a: i32x4, + b: i8, +} + +// This tests that we recursively check for vector types, not just at the top level. +#[repr(C)] +pub struct DoubleFoo { + one: Foo, + two: Foo, +} + +extern "C" { + // x86-linux: declare void @f({{.*}}byval(%Foo) align 4{{.*}}) + // x86-darwin: declare void @f({{.*}}byval(%Foo) align 16{{.*}}) + fn f(foo: Foo); + + // x86-linux: declare void @g({{.*}}byval(%DoubleFoo) align 4{{.*}}) + // x86-darwin: declare void @g({{.*}}byval(%DoubleFoo) align 16{{.*}}) + fn g(foo: DoubleFoo); +} + +pub fn main() { + unsafe { f(Foo { a: i32x4(1, 2, 3, 4), b: 0 }) } + + unsafe { + g(DoubleFoo { + one: Foo { a: i32x4(1, 2, 3, 4), b: 0 }, + two: Foo { a: i32x4(1, 2, 3, 4), b: 0 }, + }) + } +} diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs new file mode 100644 index 00000000000..e2446e02ef4 --- /dev/null +++ b/tests/codegen/align-byval.rs @@ -0,0 +1,342 @@ +// ignore-tidy-linelength +// revisions:m68k wasm x86_64-linux x86_64-windows i686-linux i686-windows + +//[m68k] compile-flags: --target m68k-unknown-linux-gnu +//[m68k] needs-llvm-components: m68k +//[wasm] compile-flags: --target wasm32-unknown-emscripten +//[wasm] needs-llvm-components: webassembly +//[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu +//[x86_64-linux] needs-llvm-components: x86 +//[x86_64-windows] compile-flags: --target x86_64-pc-windows-msvc +//[x86_64-windows] needs-llvm-components: x86 +//[i686-linux] compile-flags: --target i686-unknown-linux-gnu +//[i686-linux] needs-llvm-components: x86 +//[i686-windows] compile-flags: --target i686-pc-windows-msvc +//[i686-windows] needs-llvm-components: x86 + +// Tests that `byval` alignment is properly specified (#80127). +// The only targets that use `byval` are m68k, wasm, x86-64, and x86. +// Note also that Windows mandates a by-ref ABI here, so it does not use byval. + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_std] +#![no_core] + +#[lang="sized"] trait Sized { } +#[lang="freeze"] trait Freeze { } +#[lang="copy"] trait Copy { } + +impl Copy for i32 {} +impl Copy for i64 {} + +// This struct can be represented as a pair, so it exercises the OperandValue::Pair +// codepath in `codegen_argument`. +#[repr(C)] +pub struct NaturalAlign1 { + a: i8, + b: i8, +} + +// This struct cannot be represented as an immediate, so it exercises the OperandValue::Ref +// codepath in `codegen_argument`. +#[repr(C)] +pub struct NaturalAlign2 { + a: [i16; 16], + b: i16, +} + +#[repr(C)] +#[repr(align(4))] +pub struct ForceAlign4 { + a: [i8; 16], + b: i8, +} + +// On i686-windows, this is passed on stack using `byval` +#[repr(C)] +pub struct NaturalAlign8 { + a: i64, + b: i64, + c: i64 +} + +// On i686-windows, this is passed by reference (because alignment is >4 and requested/forced), +// even though it has the exact same layout as `NaturalAlign8`! +#[repr(C)] +#[repr(align(8))] +pub struct ForceAlign8 { + a: i64, + b: i64, + c: i64 +} + +// On i686-windows, this is passed on stack, because requested alignment is <=4. +#[repr(C)] +#[repr(align(4))] +pub struct LowerFA8 { + a: i64, + b: i64, + c: i64 +} + +// On i686-windows, this is passed by reference, because it contains a field with +// requested/forced alignment. +#[repr(C)] +pub struct WrappedFA8 { + a: ForceAlign8 +} + +// On i686-windows, this has the same ABI as ForceAlign8, i.e. passed by reference. +#[repr(transparent)] +pub struct TransparentFA8 { + _0: (), + a: ForceAlign8 +} + +#[repr(C)] +#[repr(align(16))] +pub struct ForceAlign16 { + a: [i32; 16], + b: i8 +} + +// CHECK-LABEL: @call_na1 +#[no_mangle] +pub unsafe fn call_na1(x: NaturalAlign1) { + // CHECK: start: + + // m68k: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 1 + // m68k: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}} [[ALLOCA]]) + + // wasm: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 1 + // wasm: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}} [[ALLOCA]]) + + // x86_64-linux: call void @natural_align_1(i16 + + // x86_64-windows: call void @natural_align_1(i16 + + // i686-linux: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 4 + // i686-linux: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}} [[ALLOCA]]) + + // i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 4 + // i686-windows: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}} [[ALLOCA]]) + natural_align_1(x); +} + +// CHECK-LABEL: @call_na2 +#[no_mangle] +pub unsafe fn call_na2(x: NaturalAlign2) { + // CHECK: start: + + // m68k-NEXT: call void @natural_align_2 + // wasm-NEXT: call void @natural_align_2 + // x86_64-linux-NEXT: call void @natural_align_2 + // x86_64-windows-NEXT: call void @natural_align_2 + + // i686-linux: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4 + // i686-linux: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]]) + + // i686-windows: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4 + // i686-windows: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]]) + natural_align_2(x); +} + +// CHECK-LABEL: @call_fa4 +#[no_mangle] +pub unsafe fn call_fa4(x: ForceAlign4) { + // CHECK: start: + // CHECK-NEXT: call void @force_align_4 + force_align_4(x); +} + +// CHECK-LABEL: @call_na8 +#[no_mangle] +pub unsafe fn call_na8(x: NaturalAlign8) { + // CHECK: start: + // CHECK-NEXT: call void @natural_align_8 + natural_align_8(x); +} + +// CHECK-LABEL: @call_fa8 +#[no_mangle] +pub unsafe fn call_fa8(x: ForceAlign8) { + // CHECK: start: + // CHECK-NEXT: call void @force_align_8 + force_align_8(x); +} + +// CHECK-LABEL: @call_lfa8 +#[no_mangle] +pub unsafe fn call_lfa8(x: LowerFA8) { + // CHECK: start: + // CHECK-NEXT: call void @lower_fa8 + lower_fa8(x); +} + +// CHECK-LABEL: @call_wfa8 +#[no_mangle] +pub unsafe fn call_wfa8(x: WrappedFA8) { + // CHECK: start: + // CHECK-NEXT: call void @wrapped_fa8 + wrapped_fa8(x); +} + +// CHECK-LABEL: @call_tfa8 +#[no_mangle] +pub unsafe fn call_tfa8(x: TransparentFA8) { + // CHECK: start: + // CHECK-NEXT: call void @transparent_fa8 + transparent_fa8(x); +} + +// CHECK-LABEL: @call_fa16 +#[no_mangle] +pub unsafe fn call_fa16(x: ForceAlign16) { + // CHECK: start: + // CHECK-NEXT: call void @force_align_16 + force_align_16(x); +} + +extern "C" { + // m68k: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}}) + + // wasm: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}}) + + // x86_64-linux: declare void @natural_align_1(i16) + + // x86_64-windows: declare void @natural_align_1(i16) + + // i686-linux: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}}) + + // i686-windows: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}}) + fn natural_align_1(x: NaturalAlign1); + + // m68k: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}}) + + // wasm: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}}) + + // x86_64-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}}) + + // x86_64-windows: declare void @natural_align_2( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 2{{.*}}) + + // i686-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}}) + + // i686-windows: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}}) + fn natural_align_2(x: NaturalAlign2); + + // m68k: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) + + // wasm: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) + + // x86_64-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) + + // x86_64-windows: declare void @force_align_4( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 4{{.*}}) + + // i686-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) + + // i686-windows: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) + fn force_align_4(x: ForceAlign4); + + // m68k: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}}) + + // wasm: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}}) + + // x86_64-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}}) + + // x86_64-windows: declare void @natural_align_8( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 8{{.*}}) + + // i686-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}}) + + // i686-windows: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}}) + fn natural_align_8(x: NaturalAlign8); + + // m68k: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}}) + + // wasm: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}}) + + // x86_64-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}}) + + // x86_64-windows: declare void @force_align_8( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 8{{.*}}) + + // i686-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 4{{.*}}) + + // i686-windows: declare void @force_align_8( + // i686-windows-NOT: byval + // i686-windows-SAME: align 8{{.*}}) + fn force_align_8(x: ForceAlign8); + + // m68k: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}}) + + // wasm: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}}) + + // x86_64-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}}) + + // x86_64-windows: declare void @lower_fa8( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 8{{.*}}) + + // i686-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}}) + + // i686-windows: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}}) + fn lower_fa8(x: LowerFA8); + + // m68k: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}}) + + // wasm: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}}) + + // x86_64-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}}) + + // x86_64-windows: declare void @wrapped_fa8( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 8{{.*}}) + + // i686-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 4{{.*}}) + + // i686-windows: declare void @wrapped_fa8( + // i686-windows-NOT: byval + // i686-windows-SAME: align 8{{.*}}) + fn wrapped_fa8(x: WrappedFA8); + + // m68k: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}}) + + // wasm: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}}) + + // x86_64-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}}) + + // x86_64-windows: declare void @transparent_fa8( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 8{{.*}}) + + // i686-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 4{{.*}}) + + // i686-windows: declare void @transparent_fa8( + // i686-windows-NOT: byval + // i686-windows-SAME: align 8{{.*}}) + fn transparent_fa8(x: TransparentFA8); + + // m68k: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}}) + + // wasm: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}}) + + // x86_64-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}}) + + // x86_64-windows: declare void @force_align_16( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 16{{.*}}) + + // i686-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 4{{.*}}) + + // i686-windows: declare void @force_align_16( + // i686-windows-NOT: byval + // i686-windows-SAME: align 16{{.*}}) + fn force_align_16(x: ForceAlign16); +} diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs index 24f3f43d078..4d218e6a951 100644 --- a/tests/codegen/array-map.rs +++ b/tests/codegen/array-map.rs @@ -30,7 +30,6 @@ pub fn short_integer_map(x: [u32; 8]) -> [u32; 8] { pub fn long_integer_map(x: [u32; 512]) -> [u32; 512] { // CHECK: start: // CHECK-NEXT: alloca [512 x i32] - // CHECK-NEXT: alloca %"core::mem::manually_drop::ManuallyDrop<[u32; 512]>" // CHECK-NOT: alloca // CHECK: mul <{{[0-9]+}} x i32> // CHECK: add <{{[0-9]+}} x i32> diff --git a/tests/codegen/function-arguments-noopt.rs b/tests/codegen/function-arguments-noopt.rs index 35f31eba3b1..f99cc8fb415 100644 --- a/tests/codegen/function-arguments-noopt.rs +++ b/tests/codegen/function-arguments-noopt.rs @@ -42,7 +42,7 @@ pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 { f(x) } -// CHECK: void @struct_({{%S\*|ptr}} sret(%S){{( %_0)?}}, {{%S\*|ptr}} %x) +// CHECK: void @struct_({{%S\*|ptr}} sret(%S) align 4{{( %_0)?}}, {{%S\*|ptr}} align 4 %x) #[no_mangle] pub fn struct_(x: S) -> S { x @@ -51,7 +51,7 @@ pub fn struct_(x: S) -> S { // CHECK-LABEL: @struct_call #[no_mangle] pub fn struct_call(x: S, f: fn(S) -> S) -> S { - // CHECK: call void %f({{%S\*|ptr}} sret(%S){{( %_0)?}}, {{%S\*|ptr}} %{{.+}}) + // CHECK: call void %f({{%S\*|ptr}} sret(%S) align 4{{( %_0)?}}, {{%S\*|ptr}} align 4 %{{.+}}) f(x) } diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index ccf4a5de327..2f047f10311 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -142,7 +142,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) { pub fn notunpin_borrow(_: &NotUnpin) { } -// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef readonly dereferenceable(32) %_1) +// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef readonly align 4 dereferenceable(32) %_1) #[no_mangle] pub fn indirect_struct(_: S) { } @@ -188,7 +188,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> { x } -// CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) dereferenceable(32){{( %_0)?}}) +// CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) align 4 dereferenceable(32){{( %_0)?}}) #[no_mangle] pub fn struct_return() -> S { S { diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs index 24059f190ac..65a0f7e7ffb 100644 --- a/tests/codegen/iter-repeat-n-trivial-drop.rs +++ b/tests/codegen/iter-repeat-n-trivial-drop.rs @@ -33,7 +33,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCop // CHECK: [[EMPTY]]: // CHECK-NOT: br - // CHECK: phi i16 [ undef, %start ], [ %[[VAL]], %[[NOT_EMPTY]] ] + // CHECK: phi i16 [ %[[VAL]], %[[NOT_EMPTY]] ], [ undef, %start ] // CHECK-NOT: br // CHECK: ret diff --git a/tests/codegen/simd-wide-sum.rs b/tests/codegen/simd-wide-sum.rs index db2aa20bde7..3116f9597bc 100644 --- a/tests/codegen/simd-wide-sum.rs +++ b/tests/codegen/simd-wide-sum.rs @@ -1,6 +1,11 @@ +// revisions: llvm mir-opt3 // compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021 // only-x86_64 // ignore-debug: the debug assertions get in the way +// [mir-opt3]compile-flags: -Zmir-opt-level=3 +// [mir-opt3]build-pass + +// mir-opt3 is a regression test for https://github.com/rust-lang/rust/issues/98016 #![crate_type = "lib"] #![feature(portable_simd)] @@ -47,9 +52,8 @@ pub fn wider_reduce_iter(x: Simd<u8, N>) -> u16 { #[no_mangle] // CHECK-LABEL: @wider_reduce_into_iter pub fn wider_reduce_into_iter(x: Simd<u8, N>) -> u16 { - // FIXME MIR inlining messes up LLVM optimizations. - // WOULD-CHECK: zext <8 x i8> - // WOULD-CHECK-SAME: to <8 x i16> - // WOULD-CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> + // CHECK: zext <8 x i8> + // CHECK-SAME: to <8 x i16> + // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> x.to_array().into_iter().map(u16::from).sum() } diff --git a/tests/codegen/slice-init.rs b/tests/codegen/slice-init.rs index 794b773a776..d80628cb1d4 100644 --- a/tests/codegen/slice-init.rs +++ b/tests/codegen/slice-init.rs @@ -8,7 +8,7 @@ pub fn zero_sized_elem() { // CHECK-NOT: br label %repeat_loop_header{{.*}} // CHECK-NOT: call void @llvm.memset.p0 let x = [(); 4]; - drop(&x); + opaque(&x); } // CHECK-LABEL: @zero_len_array @@ -17,7 +17,7 @@ pub fn zero_len_array() { // CHECK-NOT: br label %repeat_loop_header{{.*}} // CHECK-NOT: call void @llvm.memset.p0 let x = [4; 0]; - drop(&x); + opaque(&x); } // CHECK-LABEL: @byte_array @@ -26,7 +26,7 @@ pub fn byte_array() { // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 7, i{{[0-9]+}} 4 // CHECK-NOT: br label %repeat_loop_header{{.*}} let x = [7u8; 4]; - drop(&x); + opaque(&x); } #[allow(dead_code)] @@ -42,7 +42,7 @@ pub fn byte_enum_array() { // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 {{.*}}, i{{[0-9]+}} 4 // CHECK-NOT: br label %repeat_loop_header{{.*}} let x = [Init::Memset; 4]; - drop(&x); + opaque(&x); } // CHECK-LABEL: @zeroed_integer_array @@ -51,7 +51,7 @@ pub fn zeroed_integer_array() { // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 0, i{{[0-9]+}} 16 // CHECK-NOT: br label %repeat_loop_header{{.*}} let x = [0u32; 4]; - drop(&x); + opaque(&x); } // CHECK-LABEL: @nonzero_integer_array @@ -60,5 +60,9 @@ pub fn nonzero_integer_array() { // CHECK: br label %repeat_loop_header{{.*}} // CHECK-NOT: call void @llvm.memset.p0 let x = [0x1a_2b_3c_4d_u32; 4]; - drop(&x); + opaque(&x); } + +// Use an opaque function to prevent rustc from removing useless drops. +#[inline(never)] +pub fn opaque(_: impl Sized) {} diff --git a/tests/codegen/slice-ref-equality.rs b/tests/codegen/slice-ref-equality.rs index 8f0adab35e7..c91e5bc3cd0 100644 --- a/tests/codegen/slice-ref-equality.rs +++ b/tests/codegen/slice-ref-equality.rs @@ -44,48 +44,48 @@ pub fn is_zero_array(data: &[u8; 4]) -> bool { // equality for non-byte types also just emit a `bcmp`, not a loop. // CHECK-LABEL: @eq_slice_of_nested_u8( -// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1 -// CHECK-SAME: [[USIZE]] noundef %3 +// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1 +// CHECK-SAME: [[USIZE]] noundef %y.1 #[no_mangle] fn eq_slice_of_nested_u8(x: &[[u8; 3]], y: &[[u8; 3]]) -> bool { - // CHECK: icmp eq [[USIZE]] %1, %3 - // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %1, 3 + // CHECK: icmp eq [[USIZE]] %x.1, %y.1 + // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %x.1, 3 // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i8\*|ptr}} // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]]) x == y } // CHECK-LABEL: @eq_slice_of_i32( -// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1 -// CHECK-SAME: [[USIZE]] noundef %3 +// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1 +// CHECK-SAME: [[USIZE]] noundef %y.1 #[no_mangle] fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool { - // CHECK: icmp eq [[USIZE]] %1, %3 - // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2 + // CHECK: icmp eq [[USIZE]] %x.1, %y.1 + // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2 // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}} // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]]) x == y } // CHECK-LABEL: @eq_slice_of_nonzero( -// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1 -// CHECK-SAME: [[USIZE]] noundef %3 +// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1 +// CHECK-SAME: [[USIZE]] noundef %y.1 #[no_mangle] fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool { - // CHECK: icmp eq [[USIZE]] %1, %3 - // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2 + // CHECK: icmp eq [[USIZE]] %x.1, %y.1 + // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2 // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}} // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]]) x == y } // CHECK-LABEL: @eq_slice_of_option_of_nonzero( -// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1 -// CHECK-SAME: [[USIZE]] noundef %3 +// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1 +// CHECK-SAME: [[USIZE]] noundef %y.1 #[no_mangle] fn eq_slice_of_option_of_nonzero(x: &[Option<NonZeroI16>], y: &[Option<NonZeroI16>]) -> bool { - // CHECK: icmp eq [[USIZE]] %1, %3 - // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 1 + // CHECK: icmp eq [[USIZE]] %x.1, %y.1 + // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 1 // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i16\*|ptr}} // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]]) x == y |
