From 6397d6f2097572838eed592ff3313f2aebc84735 Mon Sep 17 00:00:00 2001 From: "Sidorov, Dmitry" Date: Tue, 18 Feb 2025 19:14:31 -0800 Subject: [PATCH 1/3] [SPIR-V] SPV_INTEL_bindless_images Adds instructions to convert convert unsigned integer handles to images, samplers and sampled images. Spec: https://github.com/intel/llvm/blob/sycl/sycl/doc/design/spirv-extensions/SPV_INTEL_bindless_images.asciidoc Signed-off-by: Sidorov, Dmitry --- llvm/docs/SPIRVUsage.rst | 2 + llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp | 44 +++++++++++++++++++ llvm/lib/Target/SPIRV/SPIRVBuiltins.td | 6 +++ llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp | 2 + llvm/lib/Target/SPIRV/SPIRVInstrInfo.td | 8 ++++ llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 9 ++++ .../lib/Target/SPIRV/SPIRVSymbolicOperands.td | 2 + .../bindless_images_generic.ll | 33 ++++++++++++++ 8 files changed, 106 insertions(+) create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bindless_images/bindless_images_generic.ll diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst index b7601b26beb89..93c53a04bc447 100644 --- a/llvm/docs/SPIRVUsage.rst +++ b/llvm/docs/SPIRVUsage.rst @@ -155,6 +155,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na - Adds atomic min and max instruction on floating-point numbers. * - ``SPV_INTEL_arbitrary_precision_integers`` - Allows generating arbitrary width integer types. + * - ``SPV_INTEL_bindless_images`` + - Adds instructions to convert convert unsigned integer handles to images, samplers and sampled images. * - ``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`` diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp index 7b897f7e34c6f..df549f9fff2f9 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -1043,6 +1043,37 @@ static bool buildExtendedBitOpsInst(const SPIRV::IncomingCall *Call, return true; } +/// Helper function for building Intel's bindless image instructions. +static bool buildBindlessImageINTELInst(const SPIRV::IncomingCall *Call, + unsigned Opcode, + MachineIRBuilder &MIRBuilder, + SPIRVGlobalRegistry *GR) { + const SPIRV::DemangledBuiltin *Builtin = Call->Builtin; + const auto *ST = + static_cast(&MIRBuilder.getMF().getSubtarget()); + if ((Opcode == SPIRV::OpConvertHandleToImageINTEL || + Opcode == SPIRV::OpConvertHandleToSamplerINTEL || + Opcode == SPIRV::OpConvertHandleToSampledImageINTEL) && + !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images)) { + std::string DiagMsg = std::string(Builtin->Name) + + ": the builtin requires the following SPIR-V " + "extension: SPV_INTEL_bindless_images"; + report_fatal_error(DiagMsg.c_str(), false); + } + + // Generate SPIRV instruction accordingly. + if (Call->isSpirvOp()) + return buildOpFromWrapper(MIRBuilder, Opcode, Call, + GR->getSPIRVTypeID(Call->ReturnType)); + + auto MIB = MIRBuilder.buildInstr(Opcode) + .addDef(Call->ReturnRegister) + .addUse(GR->getSPIRVTypeID(Call->ReturnType)); + MIB.addUse(Call->Arguments[0]); + + return true; +} + static unsigned getNumComponentsForDim(SPIRV::Dim::Dim dim) { switch (dim) { case SPIRV::Dim::DIM_1D: @@ -2232,6 +2263,17 @@ static bool generateExtendedBitOpsInst(const SPIRV::IncomingCall *Call, return buildExtendedBitOpsInst(Call, Opcode, MIRBuilder, GR); } +static bool generateBindlessImageINTELInst(const SPIRV::IncomingCall *Call, + MachineIRBuilder &MIRBuilder, + SPIRVGlobalRegistry *GR) { + // Lookup the instruction opcode in the TableGen records. + const SPIRV::DemangledBuiltin *Builtin = Call->Builtin; + unsigned Opcode = + SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode; + + return buildBindlessImageINTELInst(Call, Opcode, MIRBuilder, GR); +} + static bool buildNDRange(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { @@ -2809,6 +2851,8 @@ std::optional lowerBuiltin(const StringRef DemangledCall, return generateCoopMatrInst(Call.get(), MIRBuilder, GR); case SPIRV::ExtendedBitOps: return generateExtendedBitOpsInst(Call.get(), MIRBuilder, GR); + case SPIRV::BindlessINTEL: + return generateBindlessImageINTELInst(Call.get(), MIRBuilder, GR); } return false; } diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td index 85f42fc08a4e0..c9a5c92ee3a66 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td @@ -66,6 +66,7 @@ def Construct : BuiltinGroup; def CoopMatr : BuiltinGroup; def ICarryBorrow : BuiltinGroup; def ExtendedBitOps : BuiltinGroup; +def BindlessINTEL : BuiltinGroup; //===----------------------------------------------------------------------===// // Class defining a demangled builtin record. The information in the record @@ -708,6 +709,11 @@ defm : DemangledNativeBuiltin<"__spirv_CooperativeMatrixStoreCheckedINTEL", Open defm : DemangledNativeBuiltin<"__spirv_CooperativeMatrixConstructCheckedINTEL", OpenCL_std, CoopMatr, 5, 5, OpCooperativeMatrixConstructCheckedINTEL>; defm : DemangledNativeBuiltin<"__spirv_CooperativeMatrixGetElementCoordINTEL", OpenCL_std, CoopMatr, 2, 2, OpCooperativeMatrixGetElementCoordINTEL>; +// SPV_INTEL_bindless_images builtin records: +defm : DemangledNativeBuiltin<"__spirv_ConvertHandleToImageINTEL", OpenCL_std, BindlessINTEL, 1, 1, OpConvertHandleToImageINTEL>; +defm : DemangledNativeBuiltin<"__spirv_ConvertHandleToSamplerINTEL", OpenCL_std, BindlessINTEL, 1, 1, OpConvertHandleToSamplerINTEL>; +defm : DemangledNativeBuiltin<"__spirv_ConvertHandleToSampledImageINTEL", OpenCL_std, BindlessINTEL, 1, 1, OpConvertHandleToSampledImageINTEL>; + //===----------------------------------------------------------------------===// // Class defining a work/sub group builtin that should be translated into a // SPIR-V instruction using the defined properties. diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index 13683fd9a266d..2472e92b360be 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -71,6 +71,8 @@ static const std::map> SPIRV::Extension::Extension::SPV_KHR_linkonce_odr}, {"SPV_INTEL_inline_assembly", SPIRV::Extension::Extension::SPV_INTEL_inline_assembly}, + {"SPV_INTEL_bindless_images", + SPIRV::Extension::Extension::SPV_INTEL_bindless_images}, {"SPV_INTEL_bfloat16_conversion", SPIRV::Extension::Extension::SPV_INTEL_bfloat16_conversion}, {"SPV_KHR_subgroup_rotate", diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td index 981e224a66399..65cf14fc93864 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td +++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td @@ -931,3 +931,11 @@ def OpCooperativeMatrixPrefetchINTEL: Op<6449, (outs), // SPV_EXT_arithmetic_fence def OpArithmeticFenceEXT: Op<6145, (outs ID:$res), (ins TYPE:$type, ID:$target), "$res = OpArithmeticFenceEXT $type $target">; + +// SPV_INTEL_bindless_images +def OpConvertHandleToImageINTEL: Op<6529, (outs ID:$res), (ins TYPE:$type, ID:$operand), + "$res = OpConvertHandleToImageINTEL $type $operand">; +def OpConvertHandleToSamplerINTEL: Op<6530, (outs ID:$res), (ins TYPE:$type, ID:$operand), + "$res = OpConvertHandleToSamplerINTEL $type $operand">; +def OpConvertHandleToSampledImageINTEL: Op<6531, (outs ID:$res), (ins TYPE:$type, ID:$operand), + "$res = OpConvertHandleToSampledImageINTEL $type $operand">; diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index a7a5ecead6f5f..0db046ebed963 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1677,6 +1677,15 @@ void addInstrRequirements(const MachineInstr &MI, Reqs.addCapability( SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL); break; + case SPIRV::OpConvertHandleToImageINTEL: + case SPIRV::OpConvertHandleToSamplerINTEL: + case SPIRV::OpConvertHandleToSampledImageINTEL: + if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images)) + report_fatal_error("Intel bindless images handles require the following " + "SPIR-V extension: SPV_INTEL_bindless_images", false); + Reqs.addExtension(SPIRV::Extension::SPV_INTEL_bindless_images); + Reqs.addCapability(SPIRV::Capability::BindlessImagesINTEL); + break; case SPIRV::OpKill: { Reqs.addCapability(SPIRV::Capability::Shader); } break; diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index fec3cb0091bf5..ada19a40c42f1 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -309,6 +309,7 @@ defm SPV_EXT_arithmetic_fence : ExtensionOperand<112>; defm SPV_EXT_optnone : ExtensionOperand<113>; defm SPV_INTEL_joint_matrix : ExtensionOperand<114>; defm SPV_INTEL_float_controls2 : ExtensionOperand<115>; +defm SPV_INTEL_bindless_images : ExtensionOperand<116>; //===----------------------------------------------------------------------===// // Multiclass used to define Capabilities enum values and at the same time @@ -505,6 +506,7 @@ defm CooperativeMatrixBFloat16ComponentTypeINTEL : CapabilityOperand<6437, 0, 0, defm RoundToInfinityINTEL : CapabilityOperand<5582, 0, 0, [SPV_INTEL_float_controls2], []>; defm FloatingPointModeINTEL : CapabilityOperand<5583, 0, 0, [SPV_INTEL_float_controls2], []>; defm FunctionFloatControlINTEL : CapabilityOperand<5821, 0, 0, [SPV_INTEL_float_controls2], []>; +defm BindlessImagesINTEL : CapabilityOperand<6528, 0, 0, [SPV_INTEL_bindless_images], []>; //===----------------------------------------------------------------------===// // Multiclass used to define SourceLanguage enum values and at the same time diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bindless_images/bindless_images_generic.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bindless_images/bindless_images_generic.ll new file mode 100644 index 0000000000000..a24340529eaea --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bindless_images/bindless_images_generic.ll @@ -0,0 +1,33 @@ +; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_bindless_images %s -o - | FileCheck %s + +; CHECK-ERROR: LLVM ERROR: __spirv_ConvertHandleToImageINTEL: the builtin requires the following SPIR-V extension: SPV_INTEL_bindless_images + +; CHECK: OpCapability BindlessImagesINTEL +; CHECK: OpExtension "SPV_INTEL_bindless_images" + +; CHECK-DAG: %[[#VoidTy:]] = OpTypeVoid +; CHECK-DAG: %[[#Int64Ty:]] = OpTypeInt 64 +; CHECK-DAG: %[[#Const42:]] = OpConstant %[[#Int64Ty]] 42 +; CHECK-DAG: %[[#Const43:]] = OpConstant %[[#Int64Ty]] 43 +; CHECK-DAG: %[[#IntImgTy:]] = OpTypeImage %[[#Int64Ty]] +; CHECK-DAG: %[[#SamplerTy:]] = OpTypeSampler +; CHECK-DAG: %[[#IntSmpImgTy:]] = OpTypeImage %[[#Int64Ty]] +; CHECK-DAG: %[[#SampImageTy:]] = OpTypeSampledImage %[[#IntSmpImgTy]] +; CHECK: %[[#Input:]] = OpFunctionParameter %[[#Int64Ty]] +; CHECK: %[[#]] = OpConvertHandleToImageINTEL %[[#IntImgTy]] %[[#Input]] +; CHECK: %[[#]] = OpConvertHandleToSamplerINTEL %[[#SamplerTy]] %[[#Const42]] +; CHECK: %[[#]] = OpConvertHandleToSampledImageINTEL %[[#SampImageTy]] %[[#Const43]] + +define spir_func void @foo(i64 %in) { + %img = call spir_func target("spirv.Image", i64, 2, 0, 0, 0, 0, 0, 0) @_Z33__spirv_ConvertHandleToImageINTELl(i64 %in) + %samp = call spir_func target("spirv.Sampler") @_Z35__spirv_ConvertHandleToSamplerINTELl(i64 42) + %sampImage = call spir_func target("spirv.SampledImage", i64, 1, 0, 0, 0, 0, 0, 0) @_Z40__spirv_ConvertHandleToSampledImageINTELl(i64 43) + ret void +} + +declare spir_func target("spirv.Image", i64, 2, 0, 0, 0, 0, 0, 0) @_Z33__spirv_ConvertHandleToImageINTELl(i64) + +declare spir_func target("spirv.Sampler") @_Z35__spirv_ConvertHandleToSamplerINTELl(i64) + +declare spir_func target("spirv.SampledImage", i64, 1, 0, 0, 0, 0, 0, 0) @_Z40__spirv_ConvertHandleToSampledImageINTELl(i64) From b1d74e04d06b0cba9e624cfde9e033a33f50dbdb Mon Sep 17 00:00:00 2001 From: "Sidorov, Dmitry" Date: Wed, 19 Feb 2025 04:55:53 -0800 Subject: [PATCH 2/3] format Signed-off-by: Sidorov, Dmitry --- llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp | 4 ++-- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp index df549f9fff2f9..1397b4c9d7d35 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -1068,8 +1068,8 @@ static bool buildBindlessImageINTELInst(const SPIRV::IncomingCall *Call, auto MIB = MIRBuilder.buildInstr(Opcode) .addDef(Call->ReturnRegister) - .addUse(GR->getSPIRVTypeID(Call->ReturnType)); - MIB.addUse(Call->Arguments[0]); + .addUse(GR->getSPIRVTypeID(Call->ReturnType)) + .addUse(Call->Arguments[0]); return true; } diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 0db046ebed963..636d467cdab74 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1682,7 +1682,8 @@ void addInstrRequirements(const MachineInstr &MI, case SPIRV::OpConvertHandleToSampledImageINTEL: if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images)) report_fatal_error("Intel bindless images handles require the following " - "SPIR-V extension: SPV_INTEL_bindless_images", false); + "SPIR-V extension: SPV_INTEL_bindless_images", + false); Reqs.addExtension(SPIRV::Extension::SPV_INTEL_bindless_images); Reqs.addCapability(SPIRV::Capability::BindlessImagesINTEL); break; From 58f0e994cc8ee54b63ce27330a3f395172b84f2f Mon Sep 17 00:00:00 2001 From: "Sidorov, Dmitry" Date: Wed, 19 Feb 2025 05:44:53 -0800 Subject: [PATCH 3/3] move error Signed-off-by: Sidorov, Dmitry --- llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp | 13 ------------- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 5 +++-- .../bindless_images_generic.ll | 3 ++- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp index 1397b4c9d7d35..473fcec8c4dea 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -1048,19 +1048,6 @@ static bool buildBindlessImageINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { - const SPIRV::DemangledBuiltin *Builtin = Call->Builtin; - const auto *ST = - static_cast(&MIRBuilder.getMF().getSubtarget()); - if ((Opcode == SPIRV::OpConvertHandleToImageINTEL || - Opcode == SPIRV::OpConvertHandleToSamplerINTEL || - Opcode == SPIRV::OpConvertHandleToSampledImageINTEL) && - !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images)) { - std::string DiagMsg = std::string(Builtin->Name) + - ": the builtin requires the following SPIR-V " - "extension: SPV_INTEL_bindless_images"; - report_fatal_error(DiagMsg.c_str(), false); - } - // Generate SPIRV instruction accordingly. if (Call->isSpirvOp()) return buildOpFromWrapper(MIRBuilder, Opcode, Call, diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 636d467cdab74..407034702426c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1681,8 +1681,9 @@ void addInstrRequirements(const MachineInstr &MI, case SPIRV::OpConvertHandleToSamplerINTEL: case SPIRV::OpConvertHandleToSampledImageINTEL: if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images)) - report_fatal_error("Intel bindless images handles require the following " - "SPIR-V extension: SPV_INTEL_bindless_images", + report_fatal_error("OpConvertHandleTo[Image/Sampler/SampledImage]INTEL " + "instructions require the following SPIR-V extension: " + "SPV_INTEL_bindless_images", false); Reqs.addExtension(SPIRV::Extension::SPV_INTEL_bindless_images); Reqs.addCapability(SPIRV::Capability::BindlessImagesINTEL); diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bindless_images/bindless_images_generic.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bindless_images/bindless_images_generic.ll index a24340529eaea..3963180e51172 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bindless_images/bindless_images_generic.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bindless_images/bindless_images_generic.ll @@ -1,7 +1,8 @@ ; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_bindless_images %s -o - | FileCheck %s -; CHECK-ERROR: LLVM ERROR: __spirv_ConvertHandleToImageINTEL: the builtin requires the following SPIR-V extension: SPV_INTEL_bindless_images +; CHECK-ERROR: LLVM ERROR: OpConvertHandleTo[Image/Sampler/SampledImage]INTEL instruction +; CHECK-ERROR-SAME: require the following SPIR-V extension: SPV_INTEL_bindless_images ; CHECK: OpCapability BindlessImagesINTEL ; CHECK: OpExtension "SPV_INTEL_bindless_images"