diff options
author | Vyacheslav Levytskyy <vyacheslav.levytskyy@intel.com> | 2024-05-29 12:53:08 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-29 12:53:08 +0200 |
commit | f63adf3b51008970cc7c3794c68c7a6e33e8d5dd (patch) | |
tree | 499b4f458fac1e9ee8978436db83f474e192fa06 | |
parent | 7fa45afa938e0feb0030b14a8633de7dd8e529cb (diff) | |
download | llvm-f63adf3b51008970cc7c3794c68c7a6e33e8d5dd.zip llvm-f63adf3b51008970cc7c3794c68c7a6e33e8d5dd.tar.gz llvm-f63adf3b51008970cc7c3794c68c7a6e33e8d5dd.tar.bz2 |
[SPIR-V] Introduce support of llvm.ptr.annotation to SPIR-V Backend and implement extensions which make use of spirv.Decorations (#93561)
This PR introduces support of llvm.ptr.annotation to SPIR-V Backend, and
implement several extensions which make use of spirv.Decorations and
llvm.ptr.annotation to annotate global variables and pointers:
- SPV_INTEL_cache_controls
- SPV_INTEL_global_variable_host_access
- SPV_INTEL_global_variable_fpga_decorations
11 files changed, 379 insertions, 0 deletions
diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst index 657b0fb..de27f6b 100644 --- a/llvm/docs/SPIRVUsage.rst +++ b/llvm/docs/SPIRVUsage.rst @@ -141,10 +141,16 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na - Allows generating arbitrary width integer types. * - ``SPV_INTEL_bfloat16_conversion`` - Adds instructions to convert between single-precision 32-bit floating-point values and 16-bit bfloat16 values. + * - ``SPV_INTEL_cache_controls`` + - Allows cache control information to be applied to memory access instructions. * - ``SPV_INTEL_function_pointers`` - Allows translation of function pointers. * - ``SPV_INTEL_inline_assembly`` - Allows to use inline assembly. + * - ``SPV_INTEL_global_variable_host_access`` + - Adds decorations that can be applied to global (module scope) variables. + * - ``SPV_INTEL_global_variable_fpga_decorations`` + - Adds decorations that can be applied to global (module scope) variables to help code generation for FPGA devices. * - ``SPV_INTEL_optnone`` - Adds OptNoneINTEL value for Function Control mask that indicates a request to not optimize the function. * - ``SPV_INTEL_subgroups`` diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp index 5c286ac..ff87597 100644 --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp @@ -272,6 +272,13 @@ void SPIRVInstPrinter::printOpDecorate(const MCInst *MI, raw_ostream &O) { case Decoration::UserSemantic: printStringImm(MI, NumFixedOps, O); break; + case Decoration::HostAccessINTEL: + printOperand(MI, NumFixedOps, O); + if (NumFixedOps + 1 < MI->getNumOperands()) { + O << ' '; + printStringImm(MI, NumFixedOps + 1, O); + } + break; default: printRemainingVariableOps(MI, NumFixedOps, O, true); break; diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index 7f53154..75aa182 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -30,6 +30,13 @@ static const std::map<std::string, SPIRV::Extension::Extension> SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_min_max}, {"SPV_INTEL_arbitrary_precision_integers", SPIRV::Extension::Extension::SPV_INTEL_arbitrary_precision_integers}, + {"SPV_INTEL_cache_controls", + SPIRV::Extension::Extension::SPV_INTEL_cache_controls}, + {"SPV_INTEL_global_variable_fpga_decorations", + SPIRV::Extension::Extension:: + SPV_INTEL_global_variable_fpga_decorations}, + {"SPV_INTEL_global_variable_host_access", + SPIRV::Extension::Extension::SPV_INTEL_global_variable_host_access}, {"SPV_INTEL_optnone", SPIRV::Extension::Extension::SPV_INTEL_optnone}, {"SPV_INTEL_usm_storage_classes", SPIRV::Extension::Extension::SPV_INTEL_usm_storage_classes}, diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index c86ab28..61f99f8 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -703,6 +703,15 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, static_cast<SPIRV::LinkageType::LinkageType>(LinkageOp); if (LnkType == SPIRV::LinkageType::LinkOnceODR) Reqs.addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr); + } else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL || + Dec == SPIRV::Decoration::CacheControlStoreINTEL) { + Reqs.addExtension(SPIRV::Extension::SPV_INTEL_cache_controls); + } else if (Dec == SPIRV::Decoration::HostAccessINTEL) { + Reqs.addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access); + } else if (Dec == SPIRV::Decoration::InitModeINTEL || + Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) { + Reqs.addExtension( + SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations); } } diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp index a8a0577..7bee87d 100644 --- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp @@ -22,6 +22,7 @@ #include "SPIRVSubtarget.h" #include "SPIRVTargetMachine.h" #include "SPIRVUtils.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/IntrinsicLowering.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" @@ -29,6 +30,8 @@ #include "llvm/IR/IntrinsicsSPIRV.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/LowerMemIntrinsics.h" +#include <charconv> +#include <regex> using namespace llvm; @@ -152,6 +155,132 @@ static bool lowerIntrinsicToFunction(IntrinsicInst *Intrinsic) { return true; } +static std::string getAnnotation(Value *AnnoVal, Value *OptAnnoVal) { + if (auto *Ref = dyn_cast_or_null<GetElementPtrInst>(AnnoVal)) + AnnoVal = Ref->getOperand(0); + if (auto *Ref = dyn_cast_or_null<BitCastInst>(OptAnnoVal)) + OptAnnoVal = Ref->getOperand(0); + + std::string Anno; + if (auto *C = dyn_cast_or_null<Constant>(AnnoVal)) { + StringRef Str; + if (getConstantStringInfo(C, Str)) + Anno = Str; + } + // handle optional annotation parameter in a way that Khronos Translator do + // (collect integers wrapped in a struct) + if (auto *C = dyn_cast_or_null<Constant>(OptAnnoVal); + C && C->getNumOperands()) { + Value *MaybeStruct = C->getOperand(0); + if (auto *Struct = dyn_cast<ConstantStruct>(MaybeStruct)) { + for (unsigned I = 0, E = Struct->getNumOperands(); I != E; ++I) { + if (auto *CInt = dyn_cast<ConstantInt>(Struct->getOperand(I))) + Anno += (I == 0 ? ": " : ", ") + + std::to_string(CInt->getType()->getIntegerBitWidth() == 1 + ? CInt->getZExtValue() + : CInt->getSExtValue()); + } + } else if (auto *Struct = dyn_cast<ConstantAggregateZero>(MaybeStruct)) { + // { i32 i32 ... } zeroinitializer + for (unsigned I = 0, E = Struct->getType()->getStructNumElements(); + I != E; ++I) + Anno += I == 0 ? ": 0" : ", 0"; + } + } + return Anno; +} + +static SmallVector<Metadata *> parseAnnotation(Value *I, + const std::string &Anno, + LLVMContext &Ctx, + Type *Int32Ty) { + // Try to parse the annotation string according to the following rules: + // annotation := ({kind} | {kind:value,value,...})+ + // kind := number + // value := number | string + static const std::regex R( + "\\{(\\d+)(?:[:,](\\d+|\"[^\"]*\")(?:,(\\d+|\"[^\"]*\"))*)?\\}"); + SmallVector<Metadata *> MDs; + int Pos = 0; + for (std::sregex_iterator + It = std::sregex_iterator(Anno.begin(), Anno.end(), R), + ItEnd = std::sregex_iterator(); + It != ItEnd; ++It) { + if (It->position() != Pos) + return SmallVector<Metadata *>{}; + Pos = It->position() + It->length(); + std::smatch Match = *It; + SmallVector<Metadata *> MDsItem; + for (std::size_t i = 1; i < Match.size(); ++i) { + std::ssub_match SMatch = Match[i]; + std::string Item = SMatch.str(); + if (Item.length() == 0) + break; + if (Item[0] == '"') { + Item = Item.substr(1, Item.length() - 2); + // Acceptable format of the string snippet is: + static const std::regex RStr("^(\\d+)(?:,(\\d+))*$"); + if (std::smatch MatchStr; std::regex_match(Item, MatchStr, RStr)) { + for (std::size_t SubIdx = 1; SubIdx < MatchStr.size(); ++SubIdx) + if (std::string SubStr = MatchStr[SubIdx].str(); SubStr.length()) + MDsItem.push_back(ConstantAsMetadata::get( + ConstantInt::get(Int32Ty, std::stoi(SubStr)))); + } else { + MDsItem.push_back(MDString::get(Ctx, Item)); + } + } else if (int32_t Num; + std::from_chars(Item.data(), Item.data() + Item.size(), Num) + .ec == std::errc{}) { + MDsItem.push_back( + ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Num))); + } else { + MDsItem.push_back(MDString::get(Ctx, Item)); + } + } + if (MDsItem.size() == 0) + return SmallVector<Metadata *>{}; + MDs.push_back(MDNode::get(Ctx, MDsItem)); + } + return Pos == static_cast<int>(Anno.length()) ? MDs + : SmallVector<Metadata *>{}; +} + +static void lowerPtrAnnotation(IntrinsicInst *II) { + LLVMContext &Ctx = II->getContext(); + Type *Int32Ty = Type::getInt32Ty(Ctx); + + // Retrieve an annotation string from arguments. + Value *PtrArg = nullptr; + if (auto *BI = dyn_cast<BitCastInst>(II->getArgOperand(0))) + PtrArg = BI->getOperand(0); + else + PtrArg = II->getOperand(0); + std::string Anno = + getAnnotation(II->getArgOperand(1), + 4 < II->arg_size() ? II->getArgOperand(4) : nullptr); + + // Parse the annotation. + SmallVector<Metadata *> MDs = parseAnnotation(II, Anno, Ctx, Int32Ty); + + // If the annotation string is not parsed successfully we don't know the + // format used and output it as a general UserSemantic decoration. + // Otherwise MDs is a Metadata tuple (a decoration list) in the format + // expected by `spirv.Decorations`. + if (MDs.size() == 0) { + auto UserSemantic = ConstantAsMetadata::get(ConstantInt::get( + Int32Ty, static_cast<uint32_t>(SPIRV::Decoration::UserSemantic))); + MDs.push_back(MDNode::get(Ctx, {UserSemantic, MDString::get(Ctx, Anno)})); + } + + // Build the internal intrinsic function. + IRBuilder<> IRB(II->getParent()); + IRB.SetInsertPoint(II); + IRB.CreateIntrinsic( + Intrinsic::spv_assign_decoration, {PtrArg->getType()}, + {PtrArg, MetadataAsValue::get(Ctx, MDNode::get(Ctx, MDs))}); + II->replaceAllUsesWith(II->getOperand(0)); +} + static void lowerFunnelShifts(IntrinsicInst *FSHIntrinsic) { // Get a separate function - otherwise, we'd have to rework the CFG of the // current one. Then simply replace the intrinsic uses with a call to the new @@ -334,6 +463,10 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) { Changed |= toSpvOverloadedIntrinsic( II, Intrinsic::SPVIntrinsics::spv_lifetime_end, {1}); break; + case Intrinsic::ptr_annotation: + lowerPtrAnnotation(II); + Changed = true; + break; } } } diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index 98cbd9d..65b48c8 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -299,6 +299,9 @@ defm SPV_INTEL_function_pointers : ExtensionOperand<104>; defm SPV_INTEL_variable_length_array : ExtensionOperand<105>; defm SPV_INTEL_bfloat16_conversion : ExtensionOperand<106>; defm SPV_INTEL_inline_assembly : ExtensionOperand<107>; +defm SPV_INTEL_cache_controls : ExtensionOperand<108>; +defm SPV_INTEL_global_variable_host_access : ExtensionOperand<109>; +defm SPV_INTEL_global_variable_fpga_decorations : ExtensionOperand<110>; //===----------------------------------------------------------------------===// // Multiclass used to define Capabilities enum values and at the same time @@ -471,6 +474,10 @@ defm VariableLengthArrayINTEL : CapabilityOperand<5817, 0, 0, [SPV_INTEL_variabl defm GroupUniformArithmeticKHR : CapabilityOperand<6400, 0, 0, [SPV_KHR_uniform_group_instructions], []>; defm USMStorageClassesINTEL : CapabilityOperand<5935, 0, 0, [SPV_INTEL_usm_storage_classes], [Kernel]>; defm BFloat16ConversionINTEL : CapabilityOperand<6115, 0, 0, [SPV_INTEL_bfloat16_conversion], []>; +defm GlobalVariableHostAccessINTEL : CapabilityOperand<6187, 0, 0, [SPV_INTEL_global_variable_host_access], []>; +defm HostAccessINTEL : CapabilityOperand<6188, 0, 0, [SPV_INTEL_global_variable_host_access], []>; +defm GlobalVariableFPGADecorationsINTEL : CapabilityOperand<6189, 0, 0, [SPV_INTEL_global_variable_fpga_decorations], []>; +defm CacheControlsINTEL : CapabilityOperand<6441, 0, 0, [SPV_INTEL_cache_controls], []>; //===----------------------------------------------------------------------===// // Multiclass used to define SourceLanguage enum values and at the same time @@ -1206,6 +1213,11 @@ defm ReferencedIndirectlyINTEL : DecorationOperand<5602, 0, 0, [], [IndirectRefe defm ClobberINTEL : DecorationOperand<5607, 0, 0, [SPV_INTEL_inline_assembly], [AsmINTEL]>; defm SideEffectsINTEL : DecorationOperand<5608, 0, 0, [SPV_INTEL_inline_assembly], [AsmINTEL]>; defm ArgumentAttributeINTEL : DecorationOperand<6409, 0, 0, [], [FunctionPointersINTEL]>; +defm CacheControlLoadINTEL : DecorationOperand<6442, 0, 0, [], [CacheControlsINTEL]>; +defm CacheControlStoreINTEL : DecorationOperand<6443, 0, 0, [], [CacheControlsINTEL]>; +defm HostAccessINTEL : DecorationOperand<6188, 0, 0, [], [GlobalVariableHostAccessINTEL]>; +defm InitModeINTEL : DecorationOperand<6190, 0, 0, [], [GlobalVariableFPGADecorationsINTEL]>; +defm ImplementInRegisterMapINTEL : DecorationOperand<6191, 0, 0, [], [GlobalVariableFPGADecorationsINTEL]>; //===----------------------------------------------------------------------===// // Multiclass used to define BuiltIn enum values and at the same time diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cache_controls/basic-load-store.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cache_controls/basic-load-store.ll new file mode 100644 index 0000000..359f6d1 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cache_controls/basic-load-store.ll @@ -0,0 +1,53 @@ +; Adapted from https://github.com/KhronosGroup/SPIRV-LLVM-Translator/tree/main/test/extensions/INTEL/SPV_INTEL_cache_controls + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_cache_controls %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_cache_controls %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV: Capability CacheControlsINTEL +; CHECK-SPIRV: Extension "SPV_INTEL_cache_controls" +; CHECK-SPIRV-DAG: OpName %[[#GVar:]] "G" +; CHECK-SPIRV-DAG: OpName %[[#Arg:]] "buffer" +; CHECK-SPIRV-DAG: OpDecorate %[[#GVar]] CacheControlStoreINTEL 0 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#GVar]] CacheControlStoreINTEL 1 3 +; CHECK-SPIRV-DAG: OpDecorate %[[#Arg]] CacheControlLoadINTEL 0 0 +; CHECK-SPIRV-DAG: OpDecorate %[[#Arg]] CacheControlStoreINTEL 0 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#LoadPtr:]] CacheControlLoadINTEL 0 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#LoadPtr]] CacheControlLoadINTEL 1 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#StorePtr:]] CacheControlStoreINTEL 0 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#StorePtr]] CacheControlStoreINTEL 1 2 +; CHECK-SPIRV: OpLoad %[[#]] %[[#LoadPtr]] +; CHECK-SPIRV: OpStore %[[#StorePtr]] %[[#]] + +@G = common addrspace(1) global i32 0, align 4, !spirv.Decorations !9 + +define spir_kernel void @test(ptr addrspace(1) %dummy, ptr addrspace(1) %buffer) !spirv.ParameterDecorations !12 { +entry: + %arrayidx = getelementptr inbounds i32, ptr addrspace(1) %buffer, i64 1, !spirv.Decorations !3 + %0 = load i32, ptr addrspace(1) %arrayidx, align 4 + %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %buffer, i64 0, !spirv.Decorations !6 + store i32 %0, ptr addrspace(1) %arrayidx1, align 4 + ret void +} + +!spirv.MemoryModel = !{!0} +!spirv.Source = !{!1} +!opencl.spir.version = !{!2} +!opencl.ocl.version = !{!2} + +!0 = !{i32 2, i32 2} +!1 = !{i32 3, i32 102000} +!2 = !{i32 1, i32 2} +!3 = !{!4, !5} +!4 = !{i32 6442, i32 0, i32 1} ; {CacheControlLoadINTEL, CacheLevel=0, Cached} +!5 = !{i32 6442, i32 1, i32 1} ; {CacheControlLoadINTEL, CacheLevel=1, Cached} +!6 = !{!7, !8} +!7 = !{i32 6443, i32 0, i32 1} ; {CacheControlStoreINTEL, CacheLevel=0, WriteThrough} +!8 = !{i32 6443, i32 1, i32 2} ; {CacheControlStoreINTEL, CacheLevel=1, WriteBack} +!9 = !{!10, !11} +!10 = !{i32 6443, i32 0, i32 1} ; {CacheControlStoreINTEL, CacheLevel=0, WriteThrough} +!11 = !{i32 6443, i32 1, i32 3} ; {CacheControlStoreINTEL, CacheLevel=1, Streaming} +!12 = !{!13, !14} +!13 = !{} +!14 = !{!15, !16} +!15 = !{i32 6442, i32 0, i32 0} ; {CacheControlLoadINTEL, CacheLevel=0, Uncached} +!16 = !{i32 6443, i32 0, i32 1} ; {CacheControlStoreINTEL, CacheLevel=0, WriteThrough} diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cache_controls/decorate-prefetch-w-cache-controls.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cache_controls/decorate-prefetch-w-cache-controls.ll new file mode 100644 index 0000000..9a13b72 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cache_controls/decorate-prefetch-w-cache-controls.ll @@ -0,0 +1,44 @@ +; Adapted from https://github.com/KhronosGroup/SPIRV-LLVM-Translator/tree/main/test/extensions/INTEL/SPV_INTEL_cache_controls + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_cache_controls %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_cache_controls %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV: Capability CacheControlsINTEL +; CHECK-SPIRV: Extension "SPV_INTEL_cache_controls" + +; CHECK-SPIRV-DAG: OpName %[[#Ptr1:]] "ptr1" +; CHECK-SPIRV-DAG: OpName %[[#Ptr2:]] "ptr2" +; CHECK-SPIRV-DAG: OpName %[[#Ptr3:]] "ptr3" +; CHECK-SPIRV-DAG: OpDecorate %[[#Ptr1]] CacheControlLoadINTEL 0 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#Ptr2]] CacheControlLoadINTEL 1 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#Ptr3]] CacheControlStoreINTEL 2 3 +; CHECK-SPIRV: OpExtInst %[[#]] %[[#]] prefetch %[[#Ptr1]] %[[#]] +; CHECK-SPIRV: OpExtInst %[[#]] %[[#]] prefetch %[[#Ptr2]] %[[#]] +; CHECK-SPIRV: OpExtInst %[[#]] %[[#]] prefetch %[[#Ptr3]] %[[#]] + +; 6442 stands for CacheControlLoadINTEL token +@.str.1 = private unnamed_addr addrspace(1) constant [16 x i8] c"../prefetch.hpp\00", section "llvm.metadata" +@.str.9 = private unnamed_addr addrspace(1) constant [13 x i8] c"{6442:\220,1\22}\00", section "llvm.metadata" +@.str.10 = private unnamed_addr addrspace(1) constant [13 x i8] c"{6442:\221,1\22}\00", section "llvm.metadata" +@.str.11 = private unnamed_addr addrspace(1) constant [13 x i8] c"{6443:\222,3\22}\00", section "llvm.metadata" + +define weak_odr dso_local spir_kernel void @foo(ptr addrspace(1) noundef align 1 %_arg_dataPtr) { +entry: + %r0 = addrspacecast ptr addrspace(1) %_arg_dataPtr to ptr addrspace(4) + %ptr1 = tail call spir_func noundef ptr addrspace(1) @_Z41__spirv_GenericCastToPtrExplicit_ToGlobalPvi(ptr addrspace(4) noundef %r0, i32 noundef 5) + %r1 = tail call ptr addrspace(1) @llvm.ptr.annotation.p1.p1(ptr addrspace(1) %ptr1, ptr addrspace(1) @.str.9, ptr addrspace(1) @.str.1, i32 76, ptr addrspace(1) null) + tail call spir_func void @_Z20__spirv_ocl_prefetchPU3AS1Kcm(ptr addrspace(1) noundef %r1, i64 noundef 1) + %arrayidx3.i = getelementptr inbounds i8, ptr addrspace(4) %r0, i64 1 + %ptr2 = tail call spir_func noundef ptr addrspace(1) @_Z41__spirv_GenericCastToPtrExplicit_ToGlobalPvi(ptr addrspace(4) noundef %arrayidx3.i, i32 noundef 5) + %r2 = tail call ptr addrspace(1) @llvm.ptr.annotation.p1.p1(ptr addrspace(1) %ptr2, ptr addrspace(1) @.str.10, ptr addrspace(1) @.str.1, i32 80, ptr addrspace(1) null) + tail call spir_func void @_Z20__spirv_ocl_prefetchPU3AS1Kcm(ptr addrspace(1) noundef %r2, i64 noundef 1) + %arrayidx7.i = getelementptr inbounds i8, ptr addrspace(4) %r0, i64 2 + %ptr3 = tail call spir_func noundef ptr addrspace(1) @_Z41__spirv_GenericCastToPtrExplicit_ToGlobalPvi(ptr addrspace(4) noundef %arrayidx7.i, i32 noundef 5) + %r3 = tail call ptr addrspace(1) @llvm.ptr.annotation.p1.p1(ptr addrspace(1) %ptr3, ptr addrspace(1) @.str.11, ptr addrspace(1) @.str.1, i32 80, ptr addrspace(1) null) + tail call spir_func void @_Z20__spirv_ocl_prefetchPU3AS1Kcm(ptr addrspace(1) noundef %r3, i64 noundef 2) + ret void +} + +declare ptr addrspace(1) @llvm.ptr.annotation.p1.p1(ptr addrspace(1), ptr addrspace(1), ptr addrspace(1), i32, ptr addrspace(1)) +declare dso_local spir_func void @_Z20__spirv_ocl_prefetchPU3AS1Kcm(ptr addrspace(1) noundef, i64 noundef) +declare dso_local spir_func noundef ptr addrspace(1) @_Z41__spirv_GenericCastToPtrExplicit_ToGlobalPvi(ptr addrspace(4) noundef, i32 noundef) diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_global_variable_fpga_decorations/global-var-decorations.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_global_variable_fpga_decorations/global-var-decorations.ll new file mode 100644 index 0000000..4000887 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_global_variable_fpga_decorations/global-var-decorations.ll @@ -0,0 +1,33 @@ +; Adapted from https://github.com/KhronosGroup/SPIRV-LLVM-Translator/tree/main/test/extensions/INTEL/SPV_INTEL_global_variable_fpga_decorations + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_global_variable_fpga_decorations %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_global_variable_fpga_decorations %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV: Capability GlobalVariableFPGADecorationsINTEL +; CHECK-SPIRV: Extension "SPV_INTEL_global_variable_fpga_decorations" +; CHECK-SPIRV-DAG: OpName %[[#G1:]] "int_var" +; CHECK-SPIRV-DAG: OpName %[[#G2:]] "float_var" +; CHECK-SPIRV-DAG: OpName %[[#G3:]] "bool_var" +; CHECK-SPIRV-DAG: OpDecorate %[[#G1]] ImplementInRegisterMapINTEL 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#G1]] InitModeINTEL 0 +; CHECK-SPIRV-DAG: OpDecorate %[[#G2]] ImplementInRegisterMapINTEL 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#G2]] InitModeINTEL 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#G3]] ImplementInRegisterMapINTEL 0 +; CHECK-SPIRV-DAG: OpDecorate %[[#G3]] InitModeINTEL 0 + +@int_var = addrspace(1) global i32 42, !spirv.Decorations !1 +@float_var = addrspace(1) global float 1.0, !spirv.Decorations !5 +@bool_var = addrspace(1) global i1 0, !spirv.Decorations !7 + +define spir_kernel void @test() { +entry: + ret void +} + +!1 = !{!2, !3} +!2 = !{i32 6191, i1 true} ; ImplementInRegisterMapINTEL = true +!3 = !{i32 6190, i32 0} ; InitModeINTEL = 0 +!4 = !{i32 6190, i32 1} ; InitModeINTEL = 1 +!5 = !{!2, !4} +!6 = !{i32 6191, i1 false} ; ImplementInRegisterMapINTEL = false +!7 = !{!6, !3} diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_global_variable_host_access/global-var-host-access.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_global_variable_host_access/global-var-host-access.ll new file mode 100644 index 0000000..1397435 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_global_variable_host_access/global-var-host-access.ll @@ -0,0 +1,34 @@ +; Adapted from https://github.com/KhronosGroup/SPIRV-LLVM-Translator/tree/main/test/extensions/INTEL/SPV_INTEL_global_variable_host_access + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_global_variable_host_access,+SPV_INTEL_global_variable_fpga_decorations %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_global_variable_host_access,+SPV_INTEL_global_variable_fpga_decorations %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: Capability GlobalVariableHostAccessINTEL +; CHECK-SPIRV-DAG: Capability GlobalVariableFPGADecorationsINTEL +; CHECK-SPIRV-DAG: Extension "SPV_INTEL_global_variable_host_access" +; CHECK-SPIRV-DAG: Extension "SPV_INTEL_global_variable_fpga_decorations" + +; CHECK-SPIRV-DAG: OpName %[[#G1:]] "int_var" +; CHECK-SPIRV-DAG: OpName %[[#G2:]] "bool_var" +; CHECK-SPIRV-DAG: OpName %[[#G3:]] "float_var" +; CHECK-SPIRV-DAG: OpDecorate %[[#G1]] HostAccessINTEL 1 "IntVarName" +; CHECK-SPIRV-DAG: OpDecorate %[[#G2]] HostAccessINTEL 3 "BoolVarName" +; CHECK-SPIRV-DAG: OpDecorate %[[#G3]] ImplementInRegisterMapINTEL 1 +; CHECK-SPIRV-DAG: OpDecorate %[[#G3]] InitModeINTEL 1 + +@int_var = addrspace(1) global i32 42, !spirv.Decorations !1 +@bool_var = addrspace(1) global i1 0, !spirv.Decorations !4 +@float_var = addrspace(1) global float 1.0, !spirv.Decorations !5 + +define spir_kernel void @test() { +entry: + ret void +} + +!1 = !{!2} +!2 = !{i32 6188, i32 1, !"IntVarName"} ; HostAccessINTEL 1 "IntVarName" +!3 = !{i32 6188, i32 3, !"BoolVarName"} ; HostAccessINTEL 3 "BoolVarName" +!4 = !{!3} +!5 = !{!6, !7} +!6 = !{i32 6191, i1 true} ; ImplementInRegisterMapINTEL = true +!7 = !{i32 6190, i32 1} ; InitModeINTEL = 1 diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/ptr-annotation.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/ptr-annotation.ll new file mode 100644 index 0000000..06f1d0b --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/ptr-annotation.ll @@ -0,0 +1,41 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: OpName %[[#Foo:]] "foo" +; CHECK-DAG: OpName %[[#Ptr1:]] "_arg1" +; CHECK-DAG: OpName %[[#Ptr2:]] "_arg2" +; CHECK-DAG: OpName %[[#Ptr3:]] "_arg3" +; CHECK-DAG: OpName %[[#Ptr4:]] "_arg4" +; CHECK-DAG: OpName %[[#Ptr5:]] "_arg5" +; CHECK-DAG: OpDecorate %[[#Ptr1]] NonReadable +; CHECK-DAG: OpDecorate %[[#Ptr2]] Alignment 128 +; CHECK-DAG: OpDecorate %[[#Ptr2]] NonReadable +; CHECK-DAG: OpDecorate %[[#Ptr3]] Alignment 128 +; CHECK-DAG: OpDecorate %[[#Ptr3]] NonReadable +; CHECK-DAG: OpDecorate %[[#Ptr4]] Alignment 128 +; CHECK-DAG: OpDecorate %[[#Ptr4]] NonReadable +; CHECK-DAG: OpDecorate %[[#Ptr5]] UserSemantic "Unknown format" +; CHECK: %[[#Foo]] = OpFunction +; CHECK-NEXT: %[[#Ptr1]] = OpFunctionParameter +; CHECK-NEXT: %[[#Ptr2]] = OpFunctionParameter +; CHECK-NEXT: %[[#Ptr3]] = OpFunctionParameter +; CHECK-NEXT: %[[#Ptr4]] = OpFunctionParameter +; CHECK-NEXT: %[[#Ptr5]] = OpFunctionParameter +; CHECK: OpFunctionEnd + +@.str.0 = private unnamed_addr addrspace(1) constant [16 x i8] c"../prefetch.hpp\00", section "llvm.metadata" +@.str.1 = private unnamed_addr addrspace(1) constant [5 x i8] c"{25}\00", section "llvm.metadata" +@.str.2 = private unnamed_addr addrspace(1) constant [13 x i8] c"{44:128}{25}\00", section "llvm.metadata" +@.str.3 = private unnamed_addr addrspace(1) constant [15 x i8] c"{44:\22128\22}{25}\00", section "llvm.metadata" +@.str.4 = private unnamed_addr addrspace(1) constant [13 x i8] c"{44,128}{25}\00", section "llvm.metadata" +@.str.5 = private unnamed_addr addrspace(1) constant [15 x i8] c"Unknown format\00", section "llvm.metadata" + +define spir_kernel void @foo(ptr addrspace(1) %_arg1, ptr addrspace(1) %_arg2, ptr addrspace(1) %_arg3, ptr addrspace(1) %_arg4, ptr addrspace(1) %_arg5) { +entry: + %r1 = tail call ptr addrspace(1) @llvm.ptr.annotation.p1.p1(ptr addrspace(1) %_arg1, ptr addrspace(1) @.str.1, ptr addrspace(1) @.str.0, i32 80, ptr addrspace(1) null) + %r2 = tail call ptr addrspace(1) @llvm.ptr.annotation.p1.p1(ptr addrspace(1) %_arg2, ptr addrspace(1) @.str.2, ptr addrspace(1) @.str.0, i32 80, ptr addrspace(1) null) + %r3 = tail call ptr addrspace(1) @llvm.ptr.annotation.p1.p1(ptr addrspace(1) %_arg3, ptr addrspace(1) @.str.3, ptr addrspace(1) @.str.0, i32 80, ptr addrspace(1) null) + %r4 = tail call ptr addrspace(1) @llvm.ptr.annotation.p1.p1(ptr addrspace(1) %_arg4, ptr addrspace(1) @.str.4, ptr addrspace(1) @.str.0, i32 80, ptr addrspace(1) null) + %r5 = tail call ptr addrspace(1) @llvm.ptr.annotation.p1.p1(ptr addrspace(1) %_arg5, ptr addrspace(1) @.str.5, ptr addrspace(1) @.str.0, i32 80, ptr addrspace(1) null) + ret void +} |