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/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..388f69f717add 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -920,6 +920,12 @@ 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); + 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); } } @@ -1976,6 +1982,38 @@ static void handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, buildOpDecorate(DstReg, I, TII, SPIRV::Decoration::FPFastMathMode, {FMFlags}); } +static void handleFunctionDecoration(MachineInstr &MI, const SPIRVSubtarget &ST, + const SPIRVInstrInfo &TII, + SPIRV::ModuleAnalysisInfo &MAI, + llvm::Module::const_iterator F) { + Register FuncReg = MI.getOperand(0).getReg(); + llvm::SmallVector> MetaDataList; + + // 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)) { + llvm::SmallVector MetaDataVector; + MetaDataVector.push_back(MetaData.second); + 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, MI, 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, @@ -1984,9 +2022,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); + 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 cc32200a0a261..e0eec581434f3 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/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 new file mode 100644 index 0000000000000..27309b6161888 --- /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 }