From fb202f594edf5197aa1c51758830678f51827c90 Mon Sep 17 00:00:00 2001 From: Sven van Haastregt Date: Mon, 28 Oct 2024 09:50:57 +0100 Subject: [PATCH] [Backport to 14] SPIRVReader: Add OpCopyMemory support (#2779) Add support for translating `OpCopyMemory` into `llvm.memcpy`. Fixes https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/2769 (cherry picked from commit 8dc0349c0860172c52d600f2a7422502f11bde2e) --- lib/SPIRV/SPIRVReader.cpp | 28 ++++++++++++++++---- test/OpCopyMemory.spvasm | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 test/OpCopyMemory.spvasm diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp index e75c14117..f53621620 100644 --- a/lib/SPIRV/SPIRVReader.cpp +++ b/lib/SPIRV/SPIRVReader.cpp @@ -1812,9 +1812,28 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F, return mapValue(BV, LI); } + case OpCopyMemory: { + auto *BC = static_cast(BV); + llvm::Value *Dst = transValue(BC->getTarget(), F, BB); + MaybeAlign Align(BC->getAlignment()); + MaybeAlign SrcAlign = + BC->getSrcAlignment() ? MaybeAlign(BC->getSrcAlignment()) : Align; + Type *EltTy = + transType(BC->getSource()->getType()->getPointerElementType()); + uint64_t Size = M->getDataLayout().getTypeStoreSize(EltTy).getFixedValue(); + bool IsVolatile = BC->SPIRVMemoryAccess::isVolatile(); + IRBuilder<> Builder(BB); + + llvm::Value *Src = transValue(BC->getSource(), F, BB); + CallInst *CI = + Builder.CreateMemCpy(Dst, Align, Src, SrcAlign, Size, IsVolatile); + if (isFuncNoUnwind()) + CI->getFunction()->addFnAttr(Attribute::NoUnwind); + return mapValue(BV, CI); + } + case OpCopyMemorySized: { SPIRVCopyMemorySized *BC = static_cast(BV); - CallInst *CI = nullptr; llvm::Value *Dst = transValue(BC->getTarget(), F, BB); MaybeAlign Align(BC->getAlignment()); MaybeAlign SrcAlign = @@ -1823,10 +1842,9 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F, bool IsVolatile = BC->SPIRVMemoryAccess::isVolatile(); IRBuilder<> Builder(BB); - if (!CI) { - llvm::Value *Src = transValue(BC->getSource(), F, BB); - CI = Builder.CreateMemCpy(Dst, Align, Src, SrcAlign, Size, IsVolatile); - } + llvm::Value *Src = transValue(BC->getSource(), F, BB); + CallInst *CI = + Builder.CreateMemCpy(Dst, Align, Src, SrcAlign, Size, IsVolatile); if (isFuncNoUnwind()) CI->getFunction()->addFnAttr(Attribute::NoUnwind); return mapValue(BV, CI); diff --git a/test/OpCopyMemory.spvasm b/test/OpCopyMemory.spvasm new file mode 100644 index 000000000..199420acd --- /dev/null +++ b/test/OpCopyMemory.spvasm @@ -0,0 +1,54 @@ +; Check SPIRVReader support for OpCopyMemory. + +; REQUIRES: spirv-as +; RUN: spirv-as --target-env spv1.0 -o %t.spv %s +; RUN: spirv-val %t.spv +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s + + OpCapability Addresses + OpCapability Int16 + OpCapability Kernel + OpMemoryModel Physical64 OpenCL + OpEntryPoint Kernel %kernel "copymemory" + OpName %pStruct "pStruct" + OpName %dstStruct "dstStruct" + OpName %pShort "pShort" + OpName %dstShort "dstShort" + OpName %pInt "pInt" + OpName %dstInt "dstInt" + %ushort = OpTypeInt 16 0 + %uint = OpTypeInt 32 0 + %struct = OpTypeStruct %ushort %uint %ushort + %void = OpTypeVoid +%gptr_struct = OpTypePointer CrossWorkgroup %struct +%pptr_struct = OpTypePointer Function %struct + %gptr_short = OpTypePointer CrossWorkgroup %ushort + %pptr_short = OpTypePointer Function %ushort + %gptr_int = OpTypePointer CrossWorkgroup %uint + %pptr_int = OpTypePointer Function %uint + %kernel_sig = OpTypeFunction %void %gptr_short %gptr_int %gptr_struct + %ushort_42 = OpConstant %ushort 42 + %uint_4242 = OpConstant %uint 4242 +%struct_init = OpConstantComposite %struct %ushort_42 %uint_4242 %ushort_42 + %kernel = OpFunction %void None %kernel_sig + %dstShort = OpFunctionParameter %gptr_short + %dstInt = OpFunctionParameter %gptr_int + %dstStruct = OpFunctionParameter %gptr_struct + %entry = OpLabel + %pShort = OpVariable %pptr_short Function %ushort_42 + %pInt = OpVariable %pptr_int Function %uint_4242 + %pStruct = OpVariable %pptr_struct Function %struct_init + OpCopyMemory %dstShort %pShort + OpCopyMemory %dstInt %pInt + OpCopyMemory %dstStruct %pStruct + OpReturn + OpFunctionEnd + +; CHECK-LABEL: define spir_kernel void @copymemory(i16 addrspace(1)* %dstShort, i32 addrspace(1)* %dstInt, %structtype addrspace(1)* %dstStruct) +; CHECK: %1 = bitcast i16 addrspace(1)* %dstShort to i8 addrspace(1)* +; CHECK: call void @llvm.memcpy.p1i8.p0i8.i64(i8 addrspace(1)* %1, i8* bitcast (i16* @pShort to i8*), i64 2, i1 false) +; CHECK: %2 = bitcast i32 addrspace(1)* %dstInt to i8 addrspace(1)* +; CHECK: call void @llvm.memcpy.p1i8.p0i8.i64(i8 addrspace(1)* %2, i8* bitcast (i32* @pInt to i8*), i64 4, i1 false) +; CHECK: %3 = bitcast %structtype addrspace(1)* %dstStruct to i8 addrspace(1)* +; CHECK: call void @llvm.memcpy.p1i8.p0i8.i64(i8 addrspace(1)* %3, i8* bitcast (%structtype* @pStruct to i8*), i64 12, i1 false)