From f5f4cc54d7916608f8010449472cce695ef2b30f Mon Sep 17 00:00:00 2001 From: "Maksimova, Viktoria" Date: Thu, 4 Jul 2024 08:13:39 -0700 Subject: [PATCH] Translate function attributes (incl. parameter attrs) for entry point kernels Original commit: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/commit/aded5af --- llvm-spirv/lib/SPIRV/SPIRVReader.cpp | 98 +++++++++++-------- llvm-spirv/lib/SPIRV/SPIRVReader.h | 1 + .../sycl-kernel-arg-annotation.ll | 1 + .../SPV_INTEL_function_pointers/alias.ll | 4 +- llvm-spirv/test/image.ll | 2 - .../test/transcoding/kernel_arg_type_qual.ll | 2 +- .../test/transcoding/registerallocmode.ll | 5 +- 7 files changed, 63 insertions(+), 50 deletions(-) diff --git a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp index e0e8c345ffa73..961649ede51a6 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp @@ -2970,12 +2970,65 @@ bool SPIRVToLLVM::foreachFuncCtlMask(SourceTy Source, FuncTy Func) { return true; } +void SPIRVToLLVM::transFunctionAttrs(SPIRVFunction *BF, Function *F) { + if (BF->hasDecorate(DecorationReferencedIndirectlyINTEL)) + F->addFnAttr("referenced-indirectly"); + if (isFuncNoUnwind()) + F->addFnAttr(Attribute::NoUnwind); + foreachFuncCtlMask(BF, [&](Attribute::AttrKind Attr) { F->addFnAttr(Attr); }); + + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; + ++I) { + auto *BA = BF->getArgument(I->getArgNo()); + mapValue(BA, &(*I)); + setName(&(*I), BA); + AttributeMask IllegalAttrs = AttributeFuncs::typeIncompatible(I->getType()); + BA->foreachAttr([&](SPIRVFuncParamAttrKind Kind) { + // Skip this function parameter attribute as it will translated among + // OpenCL metadata + if (Kind == FunctionParameterAttributeRuntimeAlignedINTEL) + return; + Attribute::AttrKind LLVMKind = SPIRSPIRVFuncParamAttrMap::rmap(Kind); + if (IllegalAttrs.contains(LLVMKind)) + return; + Type *AttrTy = nullptr; + switch (LLVMKind) { + case Attribute::AttrKind::ByVal: + case Attribute::AttrKind::StructRet: + AttrTy = transType(BA->getType()->getPointerElementType()); + break; + default: + break; // do nothing + } + // Make sure to use a correct constructor for a typed/typeless attribute + auto A = AttrTy ? Attribute::get(*Context, LLVMKind, AttrTy) + : Attribute::get(*Context, LLVMKind); + I->addAttr(A); + }); + + AttrBuilder Builder(*Context); + SPIRVWord MaxOffset = 0; + if (BA->hasDecorate(DecorationMaxByteOffset, 0, &MaxOffset)) + Builder.addDereferenceableAttr(MaxOffset); + SPIRVWord AlignmentBytes = 0; + if (BA->hasDecorate(DecorationAlignment, 0, &AlignmentBytes)) + Builder.addAlignmentAttr(AlignmentBytes); + I->addAttrs(Builder); + } + BF->foreachReturnValueAttr([&](SPIRVFuncParamAttrKind Kind) { + if (Kind == FunctionParameterAttributeNoWrite) + return; + F->addRetAttr(SPIRSPIRVFuncParamAttrMap::rmap(Kind)); + }); +} + Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF) { auto Loc = FuncMap.find(BF); if (Loc != FuncMap.end()) return Loc->second; auto IsKernel = isKernel(BF); + if (IsKernel) { // search for a previous function with the same name // upgrade it to a kernel and drop this if it's found @@ -2988,6 +3041,7 @@ Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF) { F->setDSOLocal(false); F = cast(mapValue(BF, F)); mapFunction(BF, F); + transFunctionAttrs(BF, F); return F; } } @@ -3036,49 +3090,7 @@ Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF) { F->setCallingConv(IsKernel ? CallingConv::SPIR_KERNEL : CallingConv::SPIR_FUNC); - if (BF->hasDecorate(DecorationReferencedIndirectlyINTEL)) - F->addFnAttr("referenced-indirectly"); - if (isFuncNoUnwind()) - F->addFnAttr(Attribute::NoUnwind); - foreachFuncCtlMask(BF, [&](Attribute::AttrKind Attr) { F->addFnAttr(Attr); }); - - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; - ++I) { - auto BA = BF->getArgument(I->getArgNo()); - mapValue(BA, &(*I)); - setName(&(*I), BA); - BA->foreachAttr([&](SPIRVFuncParamAttrKind Kind) { - Attribute::AttrKind LLVMKind = SPIRSPIRVFuncParamAttrMap::rmap(Kind); - Type *AttrTy = nullptr; - switch (LLVMKind) { - case Attribute::AttrKind::ByVal: - case Attribute::AttrKind::StructRet: - AttrTy = transType(BA->getType()->getPointerElementType()); - break; - default: - break; // do nothing - } - // Make sure to use a correct constructor for a typed/typeless attribute - auto A = AttrTy ? Attribute::get(*Context, LLVMKind, AttrTy) - : Attribute::get(*Context, LLVMKind); - I->addAttr(A); - }); - - AttrBuilder Builder(*Context); - SPIRVWord MaxOffset = 0; - if (BA->hasDecorate(DecorationMaxByteOffset, 0, &MaxOffset)) - Builder.addDereferenceableAttr(MaxOffset); - SPIRVWord AlignmentBytes = 0; - if (BA->hasDecorate(DecorationAlignment, 0, &AlignmentBytes)) - Builder.addAlignmentAttr(AlignmentBytes); - I->addAttrs(Builder); - } - BF->foreachReturnValueAttr([&](SPIRVFuncParamAttrKind Kind) { - if (Kind == FunctionParameterAttributeNoWrite) - return; - F->addRetAttr(SPIRSPIRVFuncParamAttrMap::rmap(Kind)); - }); - + transFunctionAttrs(BF, F); // Creating all basic blocks before creating instructions. for (size_t I = 0, E = BF->getNumBasicBlock(); I != E; ++I) { transValue(BF->getBasicBlock(I), F, nullptr); diff --git a/llvm-spirv/lib/SPIRV/SPIRVReader.h b/llvm-spirv/lib/SPIRV/SPIRVReader.h index 58c8f53bdc9c9..71725eb59cbc2 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVReader.h +++ b/llvm-spirv/lib/SPIRV/SPIRVReader.h @@ -104,6 +104,7 @@ class SPIRVToLLVM : private BuiltinCallHelper { std::vector transValue(const std::vector &, Function *F, BasicBlock *); Function *transFunction(SPIRVFunction *F); + void transFunctionAttrs(SPIRVFunction *BF, Function *F); Value *transBlockInvoke(SPIRVValue *Invoke, BasicBlock *BB); Instruction *transWGSizeQueryBI(SPIRVInstruction *BI, BasicBlock *BB); Instruction *transSGSizeQueryBI(SPIRVInstruction *BI, BasicBlock *BB); diff --git a/llvm-spirv/test/extensions/INTEL/SPV_INTEL_fpga_argument_interfaces/sycl-kernel-arg-annotation.ll b/llvm-spirv/test/extensions/INTEL/SPV_INTEL_fpga_argument_interfaces/sycl-kernel-arg-annotation.ll index 4001bd8ebff70..992862a3b3aa7 100644 --- a/llvm-spirv/test/extensions/INTEL/SPV_INTEL_fpga_argument_interfaces/sycl-kernel-arg-annotation.ll +++ b/llvm-spirv/test/extensions/INTEL/SPV_INTEL_fpga_argument_interfaces/sycl-kernel-arg-annotation.ll @@ -53,6 +53,7 @@ entry: ; CHECK-SPIRV: Capability FPGAArgumentInterfacesINTEL ; CHECK-SPIRV: Extension "SPV_INTEL_fpga_argument_interfaces" ; CHECK-SPIRV: Extension "SPV_INTEL_fpga_buffer_location" +; CHECK-SPIRV-DAG: Name [[IDS:[0-9]+]] "_arg_p" ; CHECK-SPIRV-DAG: Name [[ID:[0-9]+]] "_arg_p" ; CHECK-SPIRV: Decorate [[ID]] Alignment 4 ; CHECK-SPIRV: Decorate [[ID]] MMHostInterfaceAddressWidthINTEL 32 diff --git a/llvm-spirv/test/extensions/INTEL/SPV_INTEL_function_pointers/alias.ll b/llvm-spirv/test/extensions/INTEL/SPV_INTEL_function_pointers/alias.ll index a59d341a36699..49344084a8f7a 100644 --- a/llvm-spirv/test/extensions/INTEL/SPV_INTEL_function_pointers/alias.ll +++ b/llvm-spirv/test/extensions/INTEL/SPV_INTEL_function_pointers/alias.ll @@ -1,5 +1,3 @@ -; XFAIL: * - ; RUN: llvm-as %s -o %t.bc ; RUN: llvm-spirv -spirv-ext=+SPV_INTEL_function_pointers -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-SPIRV ; RUN: llvm-spirv -spirv-ext=+SPV_INTEL_function_pointers %t.bc -o %t.spv @@ -34,7 +32,7 @@ target triple = "spir64-unknown-unknown" ; CHECK-LLVM: define spir_func i32 @foo(i32 %x) -; CHECK-LLVM: define spir_func void @bar(ptr %y) +; CHECK-LLVM: define spir_kernel void @bar(ptr %y) ; CHECK-LLVM: [[PTRTOINT:%.*]] = ptrtoint ptr @foo to i64 ; CHECK-LLVM: store i64 [[PTRTOINT]], ptr %y, align 8 diff --git a/llvm-spirv/test/image.ll b/llvm-spirv/test/image.ll index 1696af69f3404..5faa055b42fcb 100644 --- a/llvm-spirv/test/image.ll +++ b/llvm-spirv/test/image.ll @@ -1,5 +1,3 @@ -; XFAIL: * - ; RUN: llvm-as %s -o %t.bc ; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV ; RUN: llvm-spirv %t.bc -o %t.spv diff --git a/llvm-spirv/test/transcoding/kernel_arg_type_qual.ll b/llvm-spirv/test/transcoding/kernel_arg_type_qual.ll index 0a2d486c4263f..0824b49e559d8 100644 --- a/llvm-spirv/test/transcoding/kernel_arg_type_qual.ll +++ b/llvm-spirv/test/transcoding/kernel_arg_type_qual.ll @@ -14,7 +14,7 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16 target triple = "spir64-unknown-unknown." ; CHECK-SPIRV: String [[#]] "kernel_arg_type_qual.test.volatile,const,," -; CHECK-SPIRV: Name [[ARG:[0-9]+]] "g" +; CHECK-SPIRV: Name [[ARG:1[0-9]+]] "g" ; CHECK-SPIRV: Decorate [[ARG]] Volatile ; CHECK-SPIRV-NEGATIVE-NOT: String [[#]] "kernel_arg_type_qual.test.volatile,const,," diff --git a/llvm-spirv/test/transcoding/registerallocmode.ll b/llvm-spirv/test/transcoding/registerallocmode.ll index af0836cf3fc75..8c59d6be69e1e 100644 --- a/llvm-spirv/test/transcoding/registerallocmode.ll +++ b/llvm-spirv/test/transcoding/registerallocmode.ll @@ -19,8 +19,11 @@ ; CHECK-LLVM: @[[FLAG0:[0-9]+]] = private unnamed_addr constant [20 x i8] c"num-thread-per-eu 4\00", section "llvm.metadata" ; CHECK-LLVM: @[[FLAG1:[0-9]+]] = private unnamed_addr constant [20 x i8] c"num-thread-per-eu 8\00", section "llvm.metadata" ; CHECK-LLVM: @[[FLAG2:[0-9]+]] = private unnamed_addr constant [20 x i8] c"num-thread-per-eu 0\00", section "llvm.metadata" +; CHECK-LLVM: @[[FLAG3:[0-9]+]] = private unnamed_addr constant [20 x i8] c"num-thread-per-eu 4\00", section "llvm.metadata" +; CHECK-LLVM: @[[FLAG4:[0-9]+]] = private unnamed_addr constant [20 x i8] c"num-thread-per-eu 8\00", section "llvm.metadata" +; CHECK-LLVM: @[[FLAG5:[0-9]+]] = private unnamed_addr constant [20 x i8] c"num-thread-per-eu 0\00", section "llvm.metadata" -; CHECK-LLVM: @llvm.global.annotations = appending global [3 x { ptr, ptr, ptr, i32, ptr }] [{ ptr, ptr, ptr, i32, ptr } { ptr @main_l3, ptr @[[FLAG0]], ptr undef, i32 undef, ptr undef }, { ptr, ptr, ptr, i32, ptr } { ptr @main_l6, ptr @[[FLAG1]], ptr undef, i32 undef, ptr undef }, { ptr, ptr, ptr, i32, ptr } { ptr @main_l9, ptr @[[FLAG2]], ptr undef, i32 undef, ptr undef }], section "llvm.metadata" +; CHECK-LLVM: @llvm.global.annotations = appending global [6 x { ptr, ptr, ptr, i32, ptr }] [{ ptr, ptr, ptr, i32, ptr } { ptr @main_l3, ptr @[[FLAG0]], ptr undef, i32 undef, ptr undef }, { ptr, ptr, ptr, i32, ptr } { ptr @main_l6, ptr @[[FLAG1]], ptr undef, i32 undef, ptr undef }, { ptr, ptr, ptr, i32, ptr } { ptr @main_l9, ptr @[[FLAG2]], ptr undef, i32 undef, ptr undef }, { ptr, ptr, ptr, i32, ptr } { ptr @main_l3, ptr @[[FLAG3]], ptr undef, i32 undef, ptr undef }, { ptr, ptr, ptr, i32, ptr } { ptr @main_l6, ptr @[[FLAG4]], ptr undef, i32 undef, ptr undef }, { ptr, ptr, ptr, i32, ptr } { ptr @main_l9, ptr @[[FLAG5]], ptr undef, i32 undef, ptr undef }], section "llvm.metadata" target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" target triple = "spir64"