From dfc3377954f9e03172fed57ca890141006a0d82e Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 15 Mar 2023 00:57:08 -0700 Subject: [PATCH] Split the mem-replace codegen test Apparently in CI it's getting generated in the opposite order, one function per file will make the test pass either way. --- tests/codegen/mem-replace-big-type.rs | 36 ++++++++++++++++++++++ tests/codegen/mem-replace-direct-memcpy.rs | 22 ------------- 2 files changed, 36 insertions(+), 22 deletions(-) create mode 100644 tests/codegen/mem-replace-big-type.rs diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs new file mode 100644 index 0000000000000..f6898e2f75814 --- /dev/null +++ b/tests/codegen/mem-replace-big-type.rs @@ -0,0 +1,36 @@ +// This test ensures that `mem::replace::` only ever calls `@llvm.memcpy` +// with `size_of::()` as the size, and never goes through any wrapper that +// may e.g. multiply `size_of::()` with a variable "count" (which is only +// known to be `1` after inlining). + +// compile-flags: -C no-prepopulate-passes -Zinline-mir=no +// ignore-debug: the debug assertions get in the way + +#![crate_type = "lib"] + +#[repr(C, align(8))] +pub struct Big([u64; 7]); +pub fn replace_big(dst: &mut Big, src: Big) -> Big { + // Before the `read_via_copy` intrinsic, this emitted six `memcpy`s. + std::mem::replace(dst, src) +} + +// NOTE(eddyb) the `CHECK-NOT`s ensure that the only calls of `@llvm.memcpy` in +// the entire output, are the direct calls we want, from `ptr::replace`. + +// CHECK-NOT: call void @llvm.memcpy + +// For a large type, we expect exactly three `memcpy`s +// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big) + // CHECK-NOT: alloca + // CHECK: alloca %Big + // CHECK-NOT: alloca + // CHECK-NOT: call void @llvm.memcpy + // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false) + // CHECK-NOT: call void @llvm.memcpy + // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false) + // CHECK-NOT: call void @llvm.memcpy + // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false) + // CHECK-NOT: call void @llvm.memcpy + +// CHECK-NOT: call void @llvm.memcpy diff --git a/tests/codegen/mem-replace-direct-memcpy.rs b/tests/codegen/mem-replace-direct-memcpy.rs index 3b01a621b5680..83babab4f847b 100644 --- a/tests/codegen/mem-replace-direct-memcpy.rs +++ b/tests/codegen/mem-replace-direct-memcpy.rs @@ -12,33 +12,11 @@ pub fn replace_byte(dst: &mut u8, src: u8) -> u8 { std::mem::replace(dst, src) } -#[repr(C, align(8))] -pub struct Big([u64; 7]); -pub fn replace_big(dst: &mut Big, src: Big) -> Big { - // Before the `read_via_copy` intrinsic, this emitted six `memcpy`s. - std::mem::replace(dst, src) -} - // NOTE(eddyb) the `CHECK-NOT`s ensure that the only calls of `@llvm.memcpy` in // the entire output, are the direct calls we want, from `ptr::replace`. // CHECK-NOT: call void @llvm.memcpy -// For a large type, we expect exactly three `memcpy`s -// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big) - // CHECK-NOT: alloca - // CHECK: alloca %Big - // CHECK-NOT: alloca - // CHECK-NOT: call void @llvm.memcpy - // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false) - // CHECK-NOT: call void @llvm.memcpy - // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false) - // CHECK-NOT: call void @llvm.memcpy - // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false) - // CHECK-NOT: call void @llvm.memcpy - -// CHECK-NOT: call void @llvm.memcpy - // For a small type, we expect one each of `load`/`store`/`memcpy` instead // CHECK-LABEL: define internal noundef i8 @{{.+}}mem{{.+}}replace // CHECK-NOT: alloca