From f87e8bd1254b4f60153c06a6d12971869f95af50 Mon Sep 17 00:00:00 2001 From: EbinJose2002 Date: Mon, 17 Mar 2025 13:16:01 +0530 Subject: [PATCH 1/3] - Support for SPV_INTEL_cluster_attributes extension - Added decorations for StallEnableINTEL and StallFreeINTEL --- llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp | 4 +- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 68 +++++++++++++++++++ .../lib/Target/SPIRV/SPIRVSymbolicOperands.td | 4 ++ .../cluster_attributes.ll | 22 ++++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cluster_attributes/cluster_attributes.ll diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index 56cbd9414c9ee..528dd4d1dbdce 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -97,7 +97,9 @@ static const std::map> SPIRV::Extension::Extension:: SPV_INTEL_subgroup_matrix_multiply_accumulate}, {"SPV_INTEL_ternary_bitwise_function", - SPIRV::Extension::Extension::SPV_INTEL_ternary_bitwise_function}}; + SPIRV::Extension::Extension::SPV_INTEL_ternary_bitwise_function}, + {"SPV_INTEL_fpga_cluster_attributes", + SPIRV::Extension::Extension::SPV_INTEL_fpga_cluster_attributes}}; bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName, StringRef ArgValue, diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 6d2ecd563d200..cc697eccec60c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -920,6 +920,10 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, } else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) { Reqs.addRequirements(SPIRV::Capability::FPMaxErrorINTEL); Reqs.addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error); + } else if (Dec == SPIRV::Decoration::StallEnableINTEL) { + Reqs.addRequirements(SPIRV::Capability::FPGAClusterAttributesINTEL); + } else if (Dec == SPIRV::Decoration::StallFreeINTEL) { + Reqs.addRequirements(SPIRV::Capability::FPGAClusterAttributesV2INTEL); } } @@ -1976,6 +1980,68 @@ static void handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, buildOpDecorate(DstReg, I, TII, SPIRV::Decoration::FPFastMathMode, {FMFlags}); } +static std::vector +getMetaDataValues(std::vector &MetaDataList) { + std::vector res; + for (auto metaDataNode : MetaDataList) { + if (metaDataNode->getNumOperands() > 0) { + if (auto *CMD = llvm::dyn_cast( + metaDataNode->getOperand(0))) { + if (auto *CI = llvm::dyn_cast(CMD->getValue())) { + APInt val = CI->getValue(); + int64_t decVal = val.getZExtValue(); + res.push_back(decVal); + } + } + } + } + return res; +} + +static void handleFunctionDecoration(llvm::Module::const_iterator F, + const SPIRVInstrInfo &TII, + MachineModuleInfo *MMI, + const SPIRVSubtarget &ST) { + MachineFunction *MF = MMI->getMachineFunction(*F); + Register FuncReg; + MachineInstr *FirstInstr = nullptr; + llvm::SmallVector> MetaDataList; + // Find function register and first instruction + for (auto &MBB : *MF) { + for (auto &MI : MBB) { + if (MI.getOpcode() == SPIRV::OpFunction) { + FirstInstr = &MI; + FuncReg = MI.getOperand(0).getReg(); + break; + } + } + if (FuncReg.isValid() && FirstInstr) + break; + } + // Add function-level decorations based on metadata + F->getAllMetadata(MetaDataList); + for (auto &MetaData : MetaDataList) { + if (MetaData.second == F->getMetadata("stall_enable") || + MetaData.second == F->getMetadata("stall_free")) { + if (ST.canUseExtension( + SPIRV::Extension::SPV_INTEL_fpga_cluster_attributes)) { + std::vector MetaDataVector; + MetaDataVector.push_back(MetaData.second); + std::vector params = getMetaDataValues(MetaDataVector); + if (params.at(0) == 1) { + if (MetaData.second == F->getMetadata("stall_enable")) { + buildOpDecorate(FuncReg, *FirstInstr, TII, + SPIRV::Decoration::StallEnableINTEL, {}); + } else { + buildOpDecorate(FuncReg, *FirstInstr, TII, + SPIRV::Decoration::StallFreeINTEL, {}); + } + } + } + } + } +} + // Walk all functions and add decorations related to MI flags. static void addDecorations(const Module &M, const SPIRVInstrInfo &TII, MachineModuleInfo *MMI, const SPIRVSubtarget &ST, @@ -1987,6 +2053,8 @@ static void addDecorations(const Module &M, const SPIRVInstrInfo &TII, for (auto &MBB : *MF) for (auto &MI : MBB) handleMIFlagDecoration(MI, ST, TII, MAI.Reqs); + + handleFunctionDecoration(F, TII, MMI, ST); } } diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index cc32200a0a261..cd534385be80b 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -517,6 +517,8 @@ defm MemoryAccessAliasingINTEL : CapabilityOperand<5910, 0, 0, [SPV_INTEL_memory defm FPMaxErrorINTEL : CapabilityOperand<6169, 0, 0, [SPV_INTEL_fp_max_error], []>; defm TernaryBitwiseFunctionINTEL : CapabilityOperand<6241, 0, 0, [SPV_INTEL_ternary_bitwise_function], []>; defm SubgroupMatrixMultiplyAccumulateINTEL : CapabilityOperand<6236, 0, 0, [SPV_INTEL_subgroup_matrix_multiply_accumulate], []>; +defm FPGAClusterAttributesINTEL : CapabilityOperand<5904, 0, 0, [SPV_INTEL_fpga_cluster_attributes], []>; +defm FPGAClusterAttributesV2INTEL : CapabilityOperand<6150, 0, 0, [SPV_INTEL_fpga_cluster_attributes], []>; //===----------------------------------------------------------------------===// // Multiclass used to define SourceLanguage enum values and at the same time @@ -1268,6 +1270,8 @@ defm FunctionFloatingPointModeINTEL : DecorationOperand<6080, 0, 0, [], [Functio defm AliasScopeINTEL : DecorationOperand<5914, 0, 0, [], [MemoryAccessAliasingINTEL]>; defm NoAliasINTEL : DecorationOperand<5915, 0, 0, [], [MemoryAccessAliasingINTEL]>; defm FPMaxErrorDecorationINTEL : DecorationOperand<6170, 0, 0, [], [FPMaxErrorINTEL]>; +defm StallEnableINTEL : DecorationOperand<5905, 0, 0, [SPV_INTEL_fpga_cluster_attributes], [FPGAClusterAttributesINTEL]>; +defm StallFreeINTEL : DecorationOperand<6151, 0, 0, [SPV_INTEL_fpga_cluster_attributes], [FPGAClusterAttributesV2INTEL]>; //===----------------------------------------------------------------------===// // Multiclass used to define BuiltIn enum values and at the same time diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cluster_attributes/cluster_attributes.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cluster_attributes/cluster_attributes.ll new file mode 100644 index 0000000000000..bbc1949766118 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cluster_attributes/cluster_attributes.ll @@ -0,0 +1,22 @@ +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_fpga_cluster_attributes %s -o - | FileCheck %s + +; CHECK-DAG: OpCapability FPGAClusterAttributesINTEL +; CHECK-DAG: OpCapability FPGAClusterAttributesV2INTEL +; CHECK-DAG: OpExtension "SPV_INTEL_fpga_cluster_attributes" +; CHECK-DAG: OpDecorate %[[#STALLENABLE_DEC:]] StallEnableINTEL +; CHECK-DAG: OpDecorate %[[#STALLFREE_DEC:]] StallFreeINTEL +; CHECK: %[[#STALLENABLE_DEC]] = OpFunction %[[#]] None %[[#]] +; CHECK: %[[#STALLFREE_DEC]] = OpFunction %[[#]] None %[[#]] + +define spir_func void @test_fpga_stallenable_attr() !stall_enable !0 { + entry: + ret void +} + +define spir_func void @test_fpga_stallfree_attr() !stall_free !1 { + entry: + ret void +} + +!0 = !{ i32 1 } +!1 = !{ i32 1 } \ No newline at end of file From 7935c3d70922700adfbbe55a7b561350bd450dc8 Mon Sep 17 00:00:00 2001 From: EbinJose2002 Date: Tue, 6 May 2025 10:49:06 +0530 Subject: [PATCH 2/3] - Moved the function to SPIRVUtils.cpp - Added Documentation --- llvm/docs/SPIRVUsage.rst | 2 + llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 70 ++++++------------- .../lib/Target/SPIRV/SPIRVSymbolicOperands.td | 4 +- llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 18 +++++ llvm/lib/Target/SPIRV/SPIRVUtils.h | 4 ++ .../cluster_attributes.ll | 22 +++--- 6 files changed, 58 insertions(+), 62 deletions(-) diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst index 6ff8034cac00c..114faaf36f941 100644 --- a/llvm/docs/SPIRVUsage.rst +++ b/llvm/docs/SPIRVUsage.rst @@ -213,6 +213,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na - Adds a bitwise instruction on three operands and a look-up table index for specifying the bitwise operation to perform. * - ``SPV_INTEL_subgroup_matrix_multiply_accumulate`` - Adds an instruction to compute the matrix product of an M x K matrix with a K x N matrix and then add an M x N matrix. + * - ``SPV_INTEL_cluster_attributes`` + - Adds decorations to indicate the cluster attributes of a function. To enable multiple extensions, list them separated by comma. For example, to enable support for atomic operations on floating-point numbers and arbitrary precision integers, use: diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index cc697eccec60c..67b1abca33961 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1980,44 +1980,13 @@ static void handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, buildOpDecorate(DstReg, I, TII, SPIRV::Decoration::FPFastMathMode, {FMFlags}); } -static std::vector -getMetaDataValues(std::vector &MetaDataList) { - std::vector res; - for (auto metaDataNode : MetaDataList) { - if (metaDataNode->getNumOperands() > 0) { - if (auto *CMD = llvm::dyn_cast( - metaDataNode->getOperand(0))) { - if (auto *CI = llvm::dyn_cast(CMD->getValue())) { - APInt val = CI->getValue(); - int64_t decVal = val.getZExtValue(); - res.push_back(decVal); - } - } - } - } - return res; -} - -static void handleFunctionDecoration(llvm::Module::const_iterator F, +static void handleFunctionDecoration(MachineInstr &MI, const SPIRVSubtarget &ST, const SPIRVInstrInfo &TII, - MachineModuleInfo *MMI, - const SPIRVSubtarget &ST) { - MachineFunction *MF = MMI->getMachineFunction(*F); - Register FuncReg; - MachineInstr *FirstInstr = nullptr; + SPIRV::ModuleAnalysisInfo &MAI, + llvm::Module::const_iterator F) { + Register FuncReg = MI.getOperand(0).getReg(); llvm::SmallVector> MetaDataList; - // Find function register and first instruction - for (auto &MBB : *MF) { - for (auto &MI : MBB) { - if (MI.getOpcode() == SPIRV::OpFunction) { - FirstInstr = &MI; - FuncReg = MI.getOperand(0).getReg(); - break; - } - } - if (FuncReg.isValid() && FirstInstr) - break; - } + // Add function-level decorations based on metadata F->getAllMetadata(MetaDataList); for (auto &MetaData : MetaDataList) { @@ -2025,17 +1994,18 @@ static void handleFunctionDecoration(llvm::Module::const_iterator F, MetaData.second == F->getMetadata("stall_free")) { if (ST.canUseExtension( SPIRV::Extension::SPV_INTEL_fpga_cluster_attributes)) { - std::vector MetaDataVector; + llvm::SmallVector MetaDataVector; MetaDataVector.push_back(MetaData.second); - std::vector params = getMetaDataValues(MetaDataVector); - if (params.at(0) == 1) { - if (MetaData.second == F->getMetadata("stall_enable")) { - buildOpDecorate(FuncReg, *FirstInstr, TII, + llvm::SmallVector params = + getConstantFromMetadata(MetaDataVector); + + if (params[0] == 1) { + if (MetaData.second == F->getMetadata("stall_enable")) + buildOpDecorate(FuncReg, MI, TII, SPIRV::Decoration::StallEnableINTEL, {}); - } else { - buildOpDecorate(FuncReg, *FirstInstr, TII, - SPIRV::Decoration::StallFreeINTEL, {}); - } + else + buildOpDecorate(FuncReg, MI, TII, SPIRV::Decoration::StallFreeINTEL, + {}); } } } @@ -2050,11 +2020,13 @@ static void addDecorations(const Module &M, const SPIRVInstrInfo &TII, MachineFunction *MF = MMI->getMachineFunction(*F); if (!MF) continue; - for (auto &MBB : *MF) - for (auto &MI : MBB) + for (auto &MBB : *MF) { + for (auto &MI : MBB) { handleMIFlagDecoration(MI, ST, TII, MAI.Reqs); - - handleFunctionDecoration(F, TII, MMI, ST); + if (MI.getOpcode() == SPIRV::OpFunction) + handleFunctionDecoration(MI, ST, TII, MAI, F); + } + } } } diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index cd534385be80b..e0eec581434f3 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -518,7 +518,7 @@ defm FPMaxErrorINTEL : CapabilityOperand<6169, 0, 0, [SPV_INTEL_fp_max_error], [ defm TernaryBitwiseFunctionINTEL : CapabilityOperand<6241, 0, 0, [SPV_INTEL_ternary_bitwise_function], []>; defm SubgroupMatrixMultiplyAccumulateINTEL : CapabilityOperand<6236, 0, 0, [SPV_INTEL_subgroup_matrix_multiply_accumulate], []>; defm FPGAClusterAttributesINTEL : CapabilityOperand<5904, 0, 0, [SPV_INTEL_fpga_cluster_attributes], []>; -defm FPGAClusterAttributesV2INTEL : CapabilityOperand<6150, 0, 0, [SPV_INTEL_fpga_cluster_attributes], []>; +defm FPGAClusterAttributesV2INTEL : CapabilityOperand<6150, 0, 0, [SPV_INTEL_fpga_cluster_attributes], []>; //===----------------------------------------------------------------------===// // Multiclass used to define SourceLanguage enum values and at the same time @@ -1271,7 +1271,7 @@ defm AliasScopeINTEL : DecorationOperand<5914, 0, 0, [], [MemoryAccessAliasingIN defm NoAliasINTEL : DecorationOperand<5915, 0, 0, [], [MemoryAccessAliasingINTEL]>; defm FPMaxErrorDecorationINTEL : DecorationOperand<6170, 0, 0, [], [FPMaxErrorINTEL]>; defm StallEnableINTEL : DecorationOperand<5905, 0, 0, [SPV_INTEL_fpga_cluster_attributes], [FPGAClusterAttributesINTEL]>; -defm StallFreeINTEL : DecorationOperand<6151, 0, 0, [SPV_INTEL_fpga_cluster_attributes], [FPGAClusterAttributesV2INTEL]>; +defm StallFreeINTEL : DecorationOperand<6151, 0, 0, [SPV_INTEL_fpga_cluster_attributes], [FPGAClusterAttributesV2INTEL]>; //===----------------------------------------------------------------------===// // Multiclass used to define BuiltIn enum values and at the same time diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp index f38794afab436..2a4c5f3f9289e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -370,6 +370,24 @@ Type *getMDOperandAsType(const MDNode *N, unsigned I) { return toTypedPointer(ElementTy); } +llvm::SmallVector +getConstantFromMetadata(llvm::SmallVector &MetaDataList) { + llvm::SmallVector res; + for (auto metaDataNode : MetaDataList) { + if (metaDataNode->getNumOperands() > 0) { + if (auto *CMD = llvm::dyn_cast( + metaDataNode->getOperand(0))) { + if (auto *CI = llvm::dyn_cast(CMD->getValue())) { + APInt val = CI->getValue(); + int64_t decVal = val.getZExtValue(); + res.push_back(decVal); + } + } + } + } + return res; +} + // The set of names is borrowed from the SPIR-V translator. // TODO: may be implemented in SPIRVBuiltins.td. static bool isPipeOrAddressSpaceCastBI(const StringRef MangledName) { diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h index ccf394de45c89..a836bebd19995 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.h +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h @@ -243,6 +243,10 @@ bool isSpvIntrinsic(const Value *Arg); // Get type of i-th operand of the metadata node. Type *getMDOperandAsType(const MDNode *N, unsigned I); +// Extract the constant value from the metadata node. +llvm::SmallVector +getConstantFromMetadata(llvm::SmallVector &MetaDataList); + // If OpenCL or SPIR-V builtin function name is recognized, return a demangled // name, otherwise return an empty string. std::string getOclOrSpirvBuiltinDemangledName(StringRef Name); diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cluster_attributes/cluster_attributes.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cluster_attributes/cluster_attributes.ll index bbc1949766118..27309b6161888 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cluster_attributes/cluster_attributes.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_cluster_attributes/cluster_attributes.ll @@ -1,22 +1,22 @@ ; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_fpga_cluster_attributes %s -o - | FileCheck %s -; CHECK-DAG: OpCapability FPGAClusterAttributesINTEL -; CHECK-DAG: OpCapability FPGAClusterAttributesV2INTEL -; CHECK-DAG: OpExtension "SPV_INTEL_fpga_cluster_attributes" -; CHECK-DAG: OpDecorate %[[#STALLENABLE_DEC:]] StallEnableINTEL -; CHECK-DAG: OpDecorate %[[#STALLFREE_DEC:]] StallFreeINTEL -; CHECK: %[[#STALLENABLE_DEC]] = OpFunction %[[#]] None %[[#]] -; CHECK: %[[#STALLFREE_DEC]] = OpFunction %[[#]] None %[[#]] +; CHECK-DAG: OpCapability FPGAClusterAttributesINTEL +; CHECK-DAG: OpCapability FPGAClusterAttributesV2INTEL +; CHECK-DAG: OpExtension "SPV_INTEL_fpga_cluster_attributes" +; CHECK-DAG: OpDecorate %[[#STALLENABLE_DEC:]] StallEnableINTEL +; CHECK-DAG: OpDecorate %[[#STALLFREE_DEC:]] StallFreeINTEL +; CHECK: %[[#STALLENABLE_DEC]] = OpFunction %[[#]] None %[[#]] +; CHECK: %[[#STALLFREE_DEC]] = OpFunction %[[#]] None %[[#]] define spir_func void @test_fpga_stallenable_attr() !stall_enable !0 { entry: ret void -} +} define spir_func void @test_fpga_stallfree_attr() !stall_free !1 { entry: ret void -} +} -!0 = !{ i32 1 } -!1 = !{ i32 1 } \ No newline at end of file +!0 = !{ i32 1 } +!1 = !{ i32 1 } From 02fedad620440710c153bb4463317b856d82315a Mon Sep 17 00:00:00 2001 From: Ebin-McW Date: Fri, 16 May 2025 16:36:54 +0530 Subject: [PATCH 3/3] Update llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp Co-authored-by: Dmitry Sidorov --- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 67b1abca33961..388f69f717add 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -922,8 +922,10 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, Reqs.addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error); } else if (Dec == SPIRV::Decoration::StallEnableINTEL) { Reqs.addRequirements(SPIRV::Capability::FPGAClusterAttributesINTEL); + Reqs.addExtension(SPIRV::Extension::SPV_INTEL_fpga_cluster_attributes); } else if (Dec == SPIRV::Decoration::StallFreeINTEL) { Reqs.addRequirements(SPIRV::Capability::FPGAClusterAttributesV2INTEL); + Reqs.addExtension(SPIRV::Extension::SPV_INTEL_fpga_cluster_attributes); } }