From 8dc0349c0860172c52d600f2a7422502f11bde2e Mon Sep 17 00:00:00 2001 From: Sven van Haastregt Date: Mon, 28 Oct 2024 09:50:57 +0100 Subject: [PATCH 1/4] SPIRVReader: Add OpCopyMemory support (#2779) Add support for translating `OpCopyMemory` into `llvm.memcpy`. Fixes https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/2769 --- lib/SPIRV/SPIRVReader.cpp | 28 +++++++++++++++++---- test/OpCopyMemory.spvasm | 51 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 test/OpCopyMemory.spvasm diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp index 2542b3066..93c4a7903 100644 --- a/lib/SPIRV/SPIRVReader.cpp +++ b/lib/SPIRV/SPIRVReader.cpp @@ -1814,9 +1814,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 = @@ -1825,10 +1844,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..2d20981f3 --- /dev/null +++ b/test/OpCopyMemory.spvasm @@ -0,0 +1,51 @@ +; 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(ptr addrspace(1) %dstShort, ptr addrspace(1) %dstInt, ptr addrspace(1) %dstStruct) +; CHECK: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %dstShort, ptr @pShort, i64 2, i1 false) +; CHECK: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %dstInt, ptr @pInt, i64 4, i1 false) +; CHECK: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %dstStruct, ptr @pStruct, i64 12, i1 false) From e3b9ba37834931310f244b2cb826e9e816fda101 Mon Sep 17 00:00:00 2001 From: Viktoria Maximova Date: Wed, 30 Oct 2024 11:30:44 +0100 Subject: [PATCH 2/4] Fix llvm.frexp intrinsic translation with SPV_KHR_untyped_pointers (#2818) --- lib/SPIRV/SPIRVWriter.cpp | 18 ++++++++++++++++-- test/llvm-intrinsics/frexp.ll | 15 ++++++++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp index 489a09008..d620d5bff 100644 --- a/lib/SPIRV/SPIRVWriter.cpp +++ b/lib/SPIRV/SPIRVWriter.cpp @@ -2243,7 +2243,15 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, auto *FrexpResult = transValue(RV, BB); SPIRVValue *IntFromFrexpResult = static_cast(FrexpResult)->getArgValues()[1]; - IntFromFrexpResult = BM->addLoadInst(IntFromFrexpResult, {}, BB); + SPIRVType *LoadTy = nullptr; + + if (IntFromFrexpResult->isUntypedVariable()) { + auto *BV = + static_cast(IntFromFrexpResult); + LoadTy = BV->getDataType(); + } + IntFromFrexpResult = + BM->addLoadInst(IntFromFrexpResult, {}, BB, LoadTy); std::vector Operands = {FrexpResult->getId(), IntFromFrexpResult->getId()}; @@ -2462,7 +2470,13 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, // Idx = 1 SPIRVValue *IntFromFrexpResult = static_cast(Val)->getArgValues()[1]; - IntFromFrexpResult = BM->addLoadInst(IntFromFrexpResult, {}, BB); + SPIRVType *LoadTy = nullptr; + if (IntFromFrexpResult->isUntypedVariable()) { + auto *BV = static_cast(IntFromFrexpResult); + LoadTy = BV->getDataType(); + } + IntFromFrexpResult = + BM->addLoadInst(IntFromFrexpResult, {}, BB, LoadTy); return mapValue(V, IntFromFrexpResult); } } diff --git a/test/llvm-intrinsics/frexp.ll b/test/llvm-intrinsics/frexp.ll index 6a8229397..f340fe8d2 100644 --- a/test/llvm-intrinsics/frexp.ll +++ b/test/llvm-intrinsics/frexp.ll @@ -1,11 +1,18 @@ ; RUN: llvm-as %s -o %t.bc ; RUN: llvm-spirv %t.bc -spirv-text -; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV +; RUN: FileCheck < %t.spt %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-TYPED-PTR ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: llvm-dis %t.rev.bc ; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM +; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_KHR_untyped_pointers -spirv-text -o %t.spt +; RUN: FileCheck < %t.spt %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-UNTYPED-PTR +; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_KHR_untyped_pointers -o %t.spv +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis %t.rev.bc +; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir64-unknown-unknown" @@ -14,7 +21,8 @@ target triple = "spir64-unknown-unknown" ; CHECK-SPIRV: TypeInt [[#TypeInt:]] 32 ; CHECK-SPIRV: TypeFloat [[#TypeFloat:]] 32 ; CHECK-SPIRV: TypeStruct [[#TypeStrFloatInt:]] [[#TypeFloat]] [[#TypeInt]] -; CHECK-SPIRV: TypePointer [[#TypeIntPtr:]] 7 [[#TypeInt]] +; CHECK-SPIRV-TYPED-PTR: TypePointer [[#TypeIntPtr:]] 7 [[#TypeInt]] +; CHECK-SPIRV-UNTYPED-PTR: TypeUntypedPointerKHR [[#TypePtr:]] 7 ; CHECK-SPIRV: TypeFloat [[#TypeDouble:]] 64 ; CHECK-SPIRV: TypeStruct [[#TypeStrDoubleInt:]] [[#TypeDouble]] [[#TypeInt]] @@ -49,7 +57,8 @@ declare { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float>) declare { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double>) ; CHECK-SPIRV: Function [[#TypeStrFloatInt:]] -; CHECK-SPIRV: Variable [[#TypeIntPtr]] [[#IntVar:]] 7 +; CHECK-SPIRV-TYPED-PTR: Variable [[#TypeIntPtr]] [[#IntVar:]] 7 +; CHECK-SPIRV-UNTYPED-PTR: UntypedVariableKHR [[#TypePtr]] [[#IntVar:]] 7 [[#TypeInt]] ; CHECK-SPIRV: ExtInst [[#TypeFloat]] [[#FrexpId:]] [[#ExtInstSetId]] frexp [[#NegatedZeroConst]] [[#IntVar]] ; CHECK-SPIRV: Load [[#]] [[#LoadId:]] [[#]] ; CHECK-SPIRV: CompositeConstruct [[#TypeStrFloatInt]] [[#ComposConstr:]] [[#FrexpId]] [[#LoadId]] From cd7985fb6d2589d4eaaab631d188c817ea1e3b01 Mon Sep 17 00:00:00 2001 From: Viktoria Maximova Date: Wed, 30 Oct 2024 13:05:01 +0100 Subject: [PATCH 3/4] SPV_KHR_untyped_pointers - fix images translation (#2817) This patch ensures that we are loading image type, not untyped pointer type when the extension is used. This way we also preserve correct mangling during the reverse translation. --- lib/SPIRV/SPIRVWriter.cpp | 20 ++++++++++++------- test/transcoding/get_image_num_mip_levels.ll | 9 +++++++++ .../image_with_access_qualifiers.ll | 6 ++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp index d620d5bff..a8320c4d0 100644 --- a/lib/SPIRV/SPIRVWriter.cpp +++ b/lib/SPIRV/SPIRVWriter.cpp @@ -2218,13 +2218,19 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, MemoryAccessNoAliasINTELMaskMask); if (MemoryAccess.front() == 0) MemoryAccess.clear(); - return mapValue( - V, - BM->addLoadInst( - transValue(LD->getPointerOperand(), BB), MemoryAccess, BB, - BM->isAllowedToUseExtension(ExtensionID::SPV_KHR_untyped_pointers) - ? transType(LD->getType()) - : nullptr)); + if (BM->isAllowedToUseExtension(ExtensionID::SPV_KHR_untyped_pointers)) { + SPIRVValue *Source = transValue(LD->getPointerOperand(), BB); + SPIRVType *LoadTy = transType(LD->getType()); + // For images do not use explicit load type, but rather use the source + // type (calculated in SPIRVLoad constructor) + if (LoadTy->isTypeUntypedPointerKHR() && + (Source->getType()->getPointerElementType()->isTypeImage())) { + LoadTy = nullptr; + } + return mapValue(V, BM->addLoadInst(Source, MemoryAccess, BB, LoadTy)); + } + return mapValue(V, BM->addLoadInst(transValue(LD->getPointerOperand(), BB), + MemoryAccess, BB)); } if (BinaryOperator *B = dyn_cast(V)) { diff --git a/test/transcoding/get_image_num_mip_levels.ll b/test/transcoding/get_image_num_mip_levels.ll index cf4123630..8dc8ed94e 100644 --- a/test/transcoding/get_image_num_mip_levels.ll +++ b/test/transcoding/get_image_num_mip_levels.ll @@ -8,6 +8,15 @@ ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-SPV-IR ; RUN: llvm-spirv -spirv-text %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: llvm-spirv --spirv-ext=+SPV_KHR_untyped_pointers -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: llvm-spirv --spirv-ext=+SPV_KHR_untyped_pointers %t.bc -o %t.spv +; RUN: spirv-val %t.spv +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc --spirv-target-env=SPV-IR +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-SPV-IR +; RUN: llvm-spirv -spirv-text %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-SPIRV + ; Generated from the following OpenCL C code: ; #pragma OPENCL EXTENSION cl_khr_mipmap_image : enable ; void test(image1d_t img1, diff --git a/test/transcoding/image_with_access_qualifiers.ll b/test/transcoding/image_with_access_qualifiers.ll index 0f30bcdab..4b20be2b8 100644 --- a/test/transcoding/image_with_access_qualifiers.ll +++ b/test/transcoding/image_with_access_qualifiers.ll @@ -5,6 +5,12 @@ ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM +; RUN: llvm-spirv --spirv-ext=+SPV_KHR_untyped_pointers %t.bc -spirv-text -o %t.txt +; RUN: FileCheck < %t.txt %s --check-prefix=CHECK-SPIRV +; RUN: llvm-spirv --spirv-ext=+SPV_KHR_untyped_pointers %t.bc -o %t.spv +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + ; NOTE: access qualifier infomation is not preserved after round-trip conversion to LLVM ; CHECK-LLVM: call spir_func <4 x float> @_Z11read_imagef14ocl_image1d_rw11ocl_sampleri(ptr From cc57c3a3cd000abd3a1c23265633e80f5da891d9 Mon Sep 17 00:00:00 2001 From: LU-JOHN Date: Thu, 31 Oct 2024 21:01:40 +0800 Subject: [PATCH 4/4] Enable spirv-val testing (#2651) spirv-val allows non-constant and array of 8-bit ints for printf fmt strings after KhronosGroup/SPIRV-Tools#5677. Enable spirv-val testing of this new functionality. Signed-off-by: Lu, John