about summary refs log tree commit diff
path: root/tests/codegen
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2024-03-15 22:09:05 -0700
committerScott McMurray <scottmcm@users.noreply.github.com>2024-03-17 11:59:18 -0700
commit7d537106a192d6a06ccbbb809583e4a52b1ee353 (patch)
tree1f0b783a0a919d10eaa61257a0844d98743b8384 /tests/codegen
parentfd27e8745f0f04dc7c289893ef54a618c7c9e1da (diff)
downloadrust-7d537106a192d6a06ccbbb809583e4a52b1ee353.tar.gz
rust-7d537106a192d6a06ccbbb809583e4a52b1ee353.zip
Let codegen decide when to `mem::swap` with immediates
Making `libcore` decide this is silly; the backend has so much better information about when it's a good idea.

So introduce a new `typed_swap` intrinsic with a fallback body, but replace that implementation for immediates and scalar pairs.
Diffstat (limited to 'tests/codegen')
-rw-r--r--tests/codegen/intrinsics/typed_swap.rs77
-rw-r--r--tests/codegen/swap-small-types.rs5
2 files changed, 78 insertions, 4 deletions
diff --git a/tests/codegen/intrinsics/typed_swap.rs b/tests/codegen/intrinsics/typed_swap.rs
new file mode 100644
index 00000000000..da4c082bab5
--- /dev/null
+++ b/tests/codegen/intrinsics/typed_swap.rs
@@ -0,0 +1,77 @@
+//@ revisions: OPT0 OPT3
+//@ [OPT0] compile-flags: -Copt-level=0
+//@ [OPT3] compile-flags: -Copt-level=3
+//@ compile-flags: -C no-prepopulate-passes
+//@ only-64bit (so I don't need to worry about usize)
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::typed_swap;
+
+// CHECK-LABEL: @swap_unit(
+#[no_mangle]
+pub unsafe fn swap_unit(x: &mut (), y: &mut ()) {
+    // CHECK: start
+    // CHECK-NEXT: ret void
+    typed_swap(x, y)
+}
+
+// CHECK-LABEL: @swap_i32(
+#[no_mangle]
+pub unsafe fn swap_i32(x: &mut i32, y: &mut i32) {
+    // CHECK-NOT: alloca
+
+    // CHECK: %[[TEMP:.+]] = load i32, ptr %x, align 4
+    // CHECK-SAME: !noundef
+    // OPT0: %[[TEMP2:.+]] = load i32, ptr %y, align 4
+    // OPT0-SAME: !noundef
+    // OPT0: store i32 %[[TEMP2]], ptr %x, align 4
+    // OPT0-NOT: memcpy
+    // OPT3-NOT: load
+    // OPT3: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x, ptr align 4 %y, i64 4, i1 false)
+    // CHECK: store i32 %[[TEMP]], ptr %y, align 4
+    // CHECK: ret void
+    typed_swap(x, y)
+}
+
+// CHECK-LABEL: @swap_pair(
+#[no_mangle]
+pub unsafe fn swap_pair(x: &mut (i32, u32), y: &mut (i32, u32)) {
+    // CHECK-NOT: alloca
+
+    // CHECK: load i32
+    // CHECK-SAME: !noundef
+    // CHECK: load i32
+    // CHECK-SAME: !noundef
+    // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x, ptr align 4 %y, i64 8, i1 false)
+    // CHECK: store i32
+    // CHECK: store i32
+    typed_swap(x, y)
+}
+
+// CHECK-LABEL: @swap_str(
+#[no_mangle]
+pub unsafe fn swap_str<'a>(x: &mut &'a str, y: &mut &'a str) {
+    // CHECK-NOT: alloca
+
+    // CHECK: load ptr
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: load i64
+    // CHECK-SAME: !noundef
+    // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 %y, i64 16, i1 false)
+    // CHECK: store ptr
+    // CHECK: store i64
+    typed_swap(x, y)
+}
+
+// OPT0-LABEL: @swap_string(
+#[no_mangle]
+pub unsafe fn swap_string(x: &mut String, y: &mut String) {
+    // OPT0: %[[TEMP:.+]] = alloca {{.+}}, align 8
+    // OPT0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TEMP]], ptr align 8 %x, i64 24, i1 false)
+    // OPT0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 %y, i64 24, i1 false)
+    // OPT0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %y, ptr align 8 %[[TEMP]], i64 24, i1 false)
+    typed_swap(x, y)
+}
diff --git a/tests/codegen/swap-small-types.rs b/tests/codegen/swap-small-types.rs
index 5fdf4a5804a..4dcfed2a53a 100644
--- a/tests/codegen/swap-small-types.rs
+++ b/tests/codegen/swap-small-types.rs
@@ -70,10 +70,7 @@ pub fn swap_slices<'a>(x: &mut &'a [u32], y: &mut &'a [u32]) {
     // CHECK-NOT: alloca
     // CHECK: load ptr
     // CHECK: load i64
-    // CHECK: load ptr
-    // CHECK: load i64
-    // CHECK: store ptr
-    // CHECK: store i64
+    // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 16, i1 false)
     // CHECK: store ptr
     // CHECK: store i64
     swap(x, y)