summaryrefslogtreecommitdiffstats
path: root/tests/codegen/intrinsics
diff options
context:
space:
mode:
Diffstat (limited to 'tests/codegen/intrinsics')
-rw-r--r--tests/codegen/intrinsics/const_eval_select.rs18
-rw-r--r--tests/codegen/intrinsics/exact_div.rs20
-rw-r--r--tests/codegen/intrinsics/likely.rs30
-rw-r--r--tests/codegen/intrinsics/mask.rs12
-rw-r--r--tests/codegen/intrinsics/nearby.rs18
-rw-r--r--tests/codegen/intrinsics/nontemporal.rs13
-rw-r--r--tests/codegen/intrinsics/offset_from.rs36
-rw-r--r--tests/codegen/intrinsics/prefetch.rs63
-rw-r--r--tests/codegen/intrinsics/unchecked_math.rs46
-rw-r--r--tests/codegen/intrinsics/volatile.rs55
-rw-r--r--tests/codegen/intrinsics/volatile_order.rs18
11 files changed, 329 insertions, 0 deletions
diff --git a/tests/codegen/intrinsics/const_eval_select.rs b/tests/codegen/intrinsics/const_eval_select.rs
new file mode 100644
index 000000000..f3877dc6b
--- /dev/null
+++ b/tests/codegen/intrinsics/const_eval_select.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+#![crate_type = "lib"]
+#![feature(const_eval_select)]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::const_eval_select;
+
+const fn foo(_: i32) -> i32 { 1 }
+
+#[no_mangle]
+pub fn hi(n: i32) -> i32 { n }
+
+#[no_mangle]
+pub unsafe fn hey() {
+ // CHECK: call i32 @hi(i32
+ const_eval_select((42,), foo, hi);
+}
diff --git a/tests/codegen/intrinsics/exact_div.rs b/tests/codegen/intrinsics/exact_div.rs
new file mode 100644
index 000000000..68eaa3999
--- /dev/null
+++ b/tests/codegen/intrinsics/exact_div.rs
@@ -0,0 +1,20 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::exact_div;
+
+// CHECK-LABEL: @exact_sdiv
+#[no_mangle]
+pub unsafe fn exact_sdiv(x: i32, y: i32) -> i32 {
+ // CHECK: sdiv exact
+ exact_div(x, y)
+}
+
+// CHECK-LABEL: @exact_udiv
+#[no_mangle]
+pub unsafe fn exact_udiv(x: u32, y: u32) -> u32 {
+ // CHECK: udiv exact
+ exact_div(x, y)
+}
diff --git a/tests/codegen/intrinsics/likely.rs b/tests/codegen/intrinsics/likely.rs
new file mode 100644
index 000000000..c5a0185bd
--- /dev/null
+++ b/tests/codegen/intrinsics/likely.rs
@@ -0,0 +1,30 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::{likely,unlikely};
+
+#[no_mangle]
+pub fn check_likely(x: i32, y: i32) -> Option<i32> {
+ unsafe {
+ // CHECK: call i1 @llvm.expect.i1(i1 %{{.*}}, i1 true)
+ if likely(x == y) {
+ None
+ } else {
+ Some(x + y)
+ }
+ }
+}
+
+#[no_mangle]
+pub fn check_unlikely(x: i32, y: i32) -> Option<i32> {
+ unsafe {
+ // CHECK: call i1 @llvm.expect.i1(i1 %{{.*}}, i1 false)
+ if unlikely(x == y) {
+ None
+ } else {
+ Some(x + y)
+ }
+ }
+}
diff --git a/tests/codegen/intrinsics/mask.rs b/tests/codegen/intrinsics/mask.rs
new file mode 100644
index 000000000..8f93da2e5
--- /dev/null
+++ b/tests/codegen/intrinsics/mask.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Copt-level=0
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+// CHECK-LABEL: @mask_ptr
+// CHECK-SAME: [[WORD:i[0-9]+]] %mask
+#[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|%1}}, [[WORD]] %mask)
+ core::intrinsics::ptr_mask(ptr, mask)
+}
diff --git a/tests/codegen/intrinsics/nearby.rs b/tests/codegen/intrinsics/nearby.rs
new file mode 100644
index 000000000..520fe2f18
--- /dev/null
+++ b/tests/codegen/intrinsics/nearby.rs
@@ -0,0 +1,18 @@
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics;
+
+// CHECK-LABEL: @nearbyintf32
+#[no_mangle]
+pub unsafe fn nearbyintf32(a: f32) -> f32 {
+ // CHECK: llvm.nearbyint.f32
+ intrinsics::nearbyintf32(a)
+}
+
+// CHECK-LABEL: @nearbyintf64
+#[no_mangle]
+pub unsafe fn nearbyintf64(a: f64) -> f64 {
+ // CHECK: llvm.nearbyint.f64
+ intrinsics::nearbyintf64(a)
+}
diff --git a/tests/codegen/intrinsics/nontemporal.rs b/tests/codegen/intrinsics/nontemporal.rs
new file mode 100644
index 000000000..d8ee29452
--- /dev/null
+++ b/tests/codegen/intrinsics/nontemporal.rs
@@ -0,0 +1,13 @@
+// compile-flags: -O
+
+#![feature(core_intrinsics)]
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn a(a: &mut u32, b: u32) {
+ // CHECK-LABEL: define{{.*}}void @a
+ // CHECK: store i32 %b, {{i32\*|ptr}} %a, align 4, !nontemporal
+ unsafe {
+ std::intrinsics::nontemporal_store(a, b);
+ }
+}
diff --git a/tests/codegen/intrinsics/offset_from.rs b/tests/codegen/intrinsics/offset_from.rs
new file mode 100644
index 000000000..d0de4c835
--- /dev/null
+++ b/tests/codegen/intrinsics/offset_from.rs
@@ -0,0 +1,36 @@
+// compile-flags: -C opt-level=1
+// only-64bit (because we're using [ui]size)
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+//! Basic optimizations are enabled because otherwise `x86_64-gnu-nopt` had an alloca.
+//! Uses a type with non-power-of-two size to avoid normalizations to shifts.
+
+use std::intrinsics::*;
+
+type RGB = [u8; 3];
+
+// CHECK-LABEL: @offset_from_odd_size
+#[no_mangle]
+pub unsafe fn offset_from_odd_size(a: *const RGB, b: *const RGB) -> isize {
+ // CHECK: start
+ // CHECK-NEXT: ptrtoint
+ // CHECK-NEXT: ptrtoint
+ // CHECK-NEXT: sub i64
+ // CHECK-NEXT: sdiv exact i64 %{{[0-9]+}}, 3
+ // CHECK-NEXT: ret i64
+ ptr_offset_from(a, b)
+}
+
+// CHECK-LABEL: @offset_from_unsigned_odd_size
+#[no_mangle]
+pub unsafe fn offset_from_unsigned_odd_size(a: *const RGB, b: *const RGB) -> usize {
+ // CHECK: start
+ // CHECK-NEXT: ptrtoint
+ // CHECK-NEXT: ptrtoint
+ // CHECK-NEXT: sub nuw i64
+ // CHECK-NEXT: udiv exact i64 %{{[0-9]+}}, 3
+ // CHECK-NEXT: ret i64
+ ptr_offset_from_unsigned(a, b)
+}
diff --git a/tests/codegen/intrinsics/prefetch.rs b/tests/codegen/intrinsics/prefetch.rs
new file mode 100644
index 000000000..59d7fa638
--- /dev/null
+++ b/tests/codegen/intrinsics/prefetch.rs
@@ -0,0 +1,63 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::{prefetch_read_data, prefetch_write_data,
+ prefetch_read_instruction, prefetch_write_instruction};
+
+#[no_mangle]
+pub fn check_prefetch_read_data(data: &[i8]) {
+ unsafe {
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 0, i32 1)
+ prefetch_read_data(data.as_ptr(), 0);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 1, i32 1)
+ prefetch_read_data(data.as_ptr(), 1);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 2, i32 1)
+ prefetch_read_data(data.as_ptr(), 2);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 3, i32 1)
+ prefetch_read_data(data.as_ptr(), 3);
+ }
+}
+
+#[no_mangle]
+pub fn check_prefetch_write_data(data: &[i8]) {
+ unsafe {
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 0, i32 1)
+ prefetch_write_data(data.as_ptr(), 0);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 1, i32 1)
+ prefetch_write_data(data.as_ptr(), 1);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 2, i32 1)
+ prefetch_write_data(data.as_ptr(), 2);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 3, i32 1)
+ prefetch_write_data(data.as_ptr(), 3);
+ }
+}
+
+#[no_mangle]
+pub fn check_prefetch_read_instruction(data: &[i8]) {
+ unsafe {
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 0, i32 0)
+ prefetch_read_instruction(data.as_ptr(), 0);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 1, i32 0)
+ prefetch_read_instruction(data.as_ptr(), 1);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 2, i32 0)
+ prefetch_read_instruction(data.as_ptr(), 2);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 0, i32 3, i32 0)
+ prefetch_read_instruction(data.as_ptr(), 3);
+ }
+}
+
+#[no_mangle]
+pub fn check_prefetch_write_instruction(data: &[i8]) {
+ unsafe {
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 0, i32 0)
+ prefetch_write_instruction(data.as_ptr(), 0);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 1, i32 0)
+ prefetch_write_instruction(data.as_ptr(), 1);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 2, i32 0)
+ prefetch_write_instruction(data.as_ptr(), 2);
+ // CHECK: call void @llvm.prefetch{{.*}}({{.*}}, i32 1, i32 3, i32 0)
+ prefetch_write_instruction(data.as_ptr(), 3);
+ }
+}
diff --git a/tests/codegen/intrinsics/unchecked_math.rs b/tests/codegen/intrinsics/unchecked_math.rs
new file mode 100644
index 000000000..419c120ed
--- /dev/null
+++ b/tests/codegen/intrinsics/unchecked_math.rs
@@ -0,0 +1,46 @@
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::*;
+
+// CHECK-LABEL: @unchecked_add_signed
+#[no_mangle]
+pub unsafe fn unchecked_add_signed(a: i32, b: i32) -> i32 {
+ // CHECK: add nsw
+ unchecked_add(a, b)
+}
+
+// CHECK-LABEL: @unchecked_add_unsigned
+#[no_mangle]
+pub unsafe fn unchecked_add_unsigned(a: u32, b: u32) -> u32 {
+ // CHECK: add nuw
+ unchecked_add(a, b)
+}
+
+// CHECK-LABEL: @unchecked_sub_signed
+#[no_mangle]
+pub unsafe fn unchecked_sub_signed(a: i32, b: i32) -> i32 {
+ // CHECK: sub nsw
+ unchecked_sub(a, b)
+}
+
+// CHECK-LABEL: @unchecked_sub_unsigned
+#[no_mangle]
+pub unsafe fn unchecked_sub_unsigned(a: u32, b: u32) -> u32 {
+ // CHECK: sub nuw
+ unchecked_sub(a, b)
+}
+
+// CHECK-LABEL: @unchecked_mul_signed
+#[no_mangle]
+pub unsafe fn unchecked_mul_signed(a: i32, b: i32) -> i32 {
+ // CHECK: mul nsw
+ unchecked_mul(a, b)
+}
+
+// CHECK-LABEL: @unchecked_mul_unsigned
+#[no_mangle]
+pub unsafe fn unchecked_mul_unsigned(a: u32, b: u32) -> u32 {
+ // CHECK: mul nuw
+ unchecked_mul(a, b)
+}
diff --git a/tests/codegen/intrinsics/volatile.rs b/tests/codegen/intrinsics/volatile.rs
new file mode 100644
index 000000000..7980c00e7
--- /dev/null
+++ b/tests/codegen/intrinsics/volatile.rs
@@ -0,0 +1,55 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics;
+
+// CHECK-LABEL: @volatile_copy_memory
+#[no_mangle]
+pub unsafe fn volatile_copy_memory(a: *mut u8, b: *const u8) {
+ // CHECK: llvm.memmove.{{\w*(.*true)}}
+ intrinsics::volatile_copy_memory(a, b, 1)
+}
+
+// CHECK-LABEL: @volatile_copy_nonoverlapping_memory
+#[no_mangle]
+pub unsafe fn volatile_copy_nonoverlapping_memory(a: *mut u8, b: *const u8) {
+ // CHECK: llvm.memcpy.{{\w*(.*true)}}
+ intrinsics::volatile_copy_nonoverlapping_memory(a, b, 1)
+}
+
+// CHECK-LABEL: @volatile_set_memory
+#[no_mangle]
+pub unsafe fn volatile_set_memory(a: *mut u8, b: u8) {
+ // CHECK: llvm.memset.{{\w*(.*true)}}
+ intrinsics::volatile_set_memory(a, b, 1)
+}
+
+// CHECK-LABEL: @volatile_load
+#[no_mangle]
+pub unsafe fn volatile_load(a: *const u8) -> u8 {
+ // CHECK: load volatile
+ intrinsics::volatile_load(a)
+}
+
+// CHECK-LABEL: @volatile_store
+#[no_mangle]
+pub unsafe fn volatile_store(a: *mut u8, b: u8) {
+ // CHECK: store volatile
+ intrinsics::volatile_store(a, b)
+}
+
+// CHECK-LABEL: @unaligned_volatile_load
+#[no_mangle]
+pub unsafe fn unaligned_volatile_load(a: *const u8) -> u8 {
+ // CHECK: load volatile
+ intrinsics::unaligned_volatile_load(a)
+}
+
+// CHECK-LABEL: @unaligned_volatile_store
+#[no_mangle]
+pub unsafe fn unaligned_volatile_store(a: *mut u8, b: u8) {
+ // CHECK: store volatile
+ intrinsics::unaligned_volatile_store(a, b)
+}
diff --git a/tests/codegen/intrinsics/volatile_order.rs b/tests/codegen/intrinsics/volatile_order.rs
new file mode 100644
index 000000000..99469831a
--- /dev/null
+++ b/tests/codegen/intrinsics/volatile_order.rs
@@ -0,0 +1,18 @@
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::*;
+
+pub unsafe fn test_volatile_order() {
+ let mut a: Box<u8> = Box::new(0);
+ // CHECK: load volatile
+ let x = volatile_load(&*a);
+ // CHECK: load volatile
+ let x = volatile_load(&*a);
+ // CHECK: store volatile
+ volatile_store(&mut *a, 12);
+ // CHECK: store volatile
+ unaligned_volatile_store(&mut *a, 12);
+ // CHECK: llvm.memset.p0
+ volatile_set_memory(&mut *a, 12, 1)
+}