about summary refs log tree commit diff
path: root/tests/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'tests/codegen')
-rw-r--r--tests/codegen/const-vector.rs107
-rw-r--r--tests/codegen/intrinsics/nontemporal.rs30
2 files changed, 134 insertions, 3 deletions
diff --git a/tests/codegen/const-vector.rs b/tests/codegen/const-vector.rs
new file mode 100644
index 00000000000..d368838201e
--- /dev/null
+++ b/tests/codegen/const-vector.rs
@@ -0,0 +1,107 @@
+//@ compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+// This test checks that constants of SIMD type are passed as immediate vectors.
+// We ensure that both vector representations (struct with fields and struct wrapping array) work.
+#![crate_type = "lib"]
+#![feature(abi_unadjusted)]
+#![feature(const_trait_impl)]
+#![feature(repr_simd)]
+#![feature(rustc_attrs)]
+#![feature(simd_ffi)]
+#![allow(non_camel_case_types)]
+
+// Setting up structs that can be used as const vectors
+#[repr(simd)]
+#[derive(Clone)]
+pub struct i8x2(i8, i8);
+
+#[repr(simd)]
+#[derive(Clone)]
+pub struct i8x2_arr([i8; 2]);
+
+#[repr(simd)]
+#[derive(Clone)]
+pub struct f32x2(f32, f32);
+
+#[repr(simd)]
+#[derive(Clone)]
+pub struct f32x2_arr([f32; 2]);
+
+#[repr(simd, packed)]
+#[derive(Copy, Clone)]
+pub struct Simd<T, const N: usize>([T; N]);
+
+// The following functions are required for the tests to ensure
+// that they are called with a const vector
+
+extern "unadjusted" {
+    #[no_mangle]
+    fn test_i8x2(a: i8x2);
+}
+
+extern "unadjusted" {
+    #[no_mangle]
+    fn test_i8x2_two_args(a: i8x2, b: i8x2);
+}
+
+extern "unadjusted" {
+    #[no_mangle]
+    fn test_i8x2_mixed_args(a: i8x2, c: i32, b: i8x2);
+}
+
+extern "unadjusted" {
+    #[no_mangle]
+    fn test_i8x2_arr(a: i8x2_arr);
+}
+
+extern "unadjusted" {
+    #[no_mangle]
+    fn test_f32x2(a: f32x2);
+}
+
+extern "unadjusted" {
+    #[no_mangle]
+    fn test_f32x2_arr(a: f32x2_arr);
+}
+
+extern "unadjusted" {
+    #[no_mangle]
+    fn test_simd(a: Simd<i32, 4>);
+}
+
+extern "unadjusted" {
+    #[no_mangle]
+    fn test_simd_unaligned(a: Simd<i32, 3>);
+}
+
+// Ensure the packed variant of the simd struct does not become a const vector
+// if the size is not a power of 2
+// CHECK: %"Simd<i32, 3>" = type { [3 x i32] }
+
+pub fn do_call() {
+    unsafe {
+        // CHECK: call void @test_i8x2(<2 x i8> <i8 32, i8 64>
+        test_i8x2(const { i8x2(32, 64) });
+
+        // CHECK: call void @test_i8x2_two_args(<2 x i8> <i8 32, i8 64>, <2 x i8> <i8 8, i8 16>
+        test_i8x2_two_args(const { i8x2(32, 64) }, const { i8x2(8, 16) });
+
+        // CHECK: call void @test_i8x2_mixed_args(<2 x i8> <i8 32, i8 64>, i32 43, <2 x i8> <i8 8, i8 16>
+        test_i8x2_mixed_args(const { i8x2(32, 64) }, 43, const { i8x2(8, 16) });
+
+        // CHECK: call void @test_i8x2_arr(<2 x i8> <i8 32, i8 64>
+        test_i8x2_arr(const { i8x2_arr([32, 64]) });
+
+        // CHECK: call void @test_f32x2(<2 x float> <float 0x3FD47AE140000000, float 0x3FE47AE140000000>
+        test_f32x2(const { f32x2(0.32, 0.64) });
+
+        // CHECK: void @test_f32x2_arr(<2 x float> <float 0x3FD47AE140000000, float 0x3FE47AE140000000>
+        test_f32x2_arr(const { f32x2_arr([0.32, 0.64]) });
+
+        // CHECK: call void @test_simd(<4 x i32> <i32 2, i32 4, i32 6, i32 8>
+        test_simd(const { Simd::<i32, 4>([2, 4, 6, 8]) });
+
+        // CHECK: call void @test_simd_unaligned(%"Simd<i32, 3>" %1
+        test_simd_unaligned(const { Simd::<i32, 3>([2, 4, 6]) });
+    }
+}
diff --git a/tests/codegen/intrinsics/nontemporal.rs b/tests/codegen/intrinsics/nontemporal.rs
index 076d6d6d9da..ff2d6296066 100644
--- a/tests/codegen/intrinsics/nontemporal.rs
+++ b/tests/codegen/intrinsics/nontemporal.rs
@@ -1,13 +1,37 @@
 //@ compile-flags: -O
+//@revisions: with_nontemporal without_nontemporal
+//@[with_nontemporal] compile-flags: --target aarch64-unknown-linux-gnu
+//@[with_nontemporal] needs-llvm-components: aarch64
+//@[without_nontemporal] compile-flags: --target x86_64-unknown-linux-gnu
+//@[without_nontemporal] needs-llvm-components: x86
 
-#![feature(core_intrinsics)]
+// Ensure that we *do* emit the `!nontemporal` flag on architectures where it
+// is well-behaved, but do *not* emit it on architectures where it is ill-behaved.
+// For more context, see <https://github.com/rust-lang/rust/issues/114582> and
+// <https://github.com/llvm/llvm-project/issues/64521>.
+
+#![feature(no_core, lang_items, intrinsics)]
+#![no_core]
 #![crate_type = "lib"]
 
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+
+impl Copy for u32 {}
+impl<T> Copy for *mut T {}
+
+extern "rust-intrinsic" {
+    pub fn nontemporal_store<T>(ptr: *mut T, val: T);
+}
+
 #[no_mangle]
 pub fn a(a: &mut u32, b: u32) {
     // CHECK-LABEL: define{{.*}}void @a
-    // CHECK: store i32 %b, ptr %a, align 4, !nontemporal
+    // with_nontemporal: store i32 %b, ptr %a, align 4, !nontemporal
+    // without_nontemporal-NOT: nontemporal
     unsafe {
-        std::intrinsics::nontemporal_store(a, b);
+        nontemporal_store(a, b);
     }
 }