diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst index 6ff8034cac00c..8e8966e0fb63f 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_maximum_registers`` + - This extension adds an execution mode to specify the maximum number of registers a SPIR-V consumer should use when compiling an entry point. 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: @@ -489,6 +491,11 @@ SPIR-V backend, along with their descriptions and argument details. - `[spirv.Image Image, 32-bit Integer coordinate, vec4 data]` - Stores the data to the image buffer at the given coordinate. The \ data must be a 4-element vector. + * - `int_spv_max_reg_constant` + - void + - `[32-bit Integer Maximum registers allowed]` + - 32-bit integer indicating the maximum number of registers allowed. \ + Used as an operand to the OpExecutionModeId MaximumRegistersIdINTEL. .. _spirv-builtin-functions: diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 404467781b4d0..cac99105b74df 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -148,6 +148,9 @@ let TargetPrefix = "spv" in { // FPMaxErrorDecorationINTEL def int_spv_assign_fpmaxerror_decoration: Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>; + + // ExecutionModeMaxRedId + def int_spv_max_reg_constant : Intrinsic<[], [llvm_i32_ty], [ImmArg>]>; // Convert between the generic storage class and a concrete one. def int_spv_generic_cast_to_ptr_explicit diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h index d009244a92259..3ea39506c38c6 100644 --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h @@ -217,6 +217,11 @@ namespace CooperativeMatrixOperands { #include "SPIRVGenTables.inc" } // namespace CooperativeMatrixOperands +namespace NamedMaximumNumberOfRegisters { +#define GET_NamedMaximumNumberOfRegisters_DECL +#include "SPIRVGenTables.inc" +} // namespace NamedMaximumNumberOfRegisters + struct ExtendedBuiltin { StringRef Name; InstructionSet::InstructionSet Set; diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp index b486132077e3b..c51ae48b3310a 100644 --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::SPIRV; @@ -147,7 +148,22 @@ void SPIRVInstPrinter::printInst(const MCInst *MI, uint64_t Address, case SPIRV::OpMemberDecorate: printRemainingVariableOps(MI, NumFixedOps, OS); break; - case SPIRV::OpExecutionMode: + case SPIRV::OpExecutionMode: { + unsigned NumOperands = MI->getNumOperands(); + if (NumOperands != NumFixedOps) { + const unsigned MaxRegVal = + MI->getOperand(FirstVariableIndex).getImm(); + if (MaxRegVal == 0) { + + OS << ' '; + printSymbolicOperand< + OperandCategory::NamedMaximumNumberOfRegistersOperand>( + MI, FirstVariableIndex, OS); + break; + } + } + printRemainingVariableOps(MI, NumFixedOps, OS); + } break; case SPIRV::OpExecutionModeId: case SPIRV::OpLoopMerge: { // Print any literals after the OPERAND_UNKNOWN argument normally. diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp index f17c8a8fac14b..eff41bd1f0c7e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp @@ -76,6 +76,9 @@ class SPIRVAsmPrinter : public AsmPrinter { void outputExecutionModeFromNumthreadsAttribute( const MCRegister &Reg, const Attribute &Attr, SPIRV::ExecutionMode::ExecutionMode EM); + void outputExecutionModeFromRegisterAllocMode(const MCRegister &Reg, + const MDNode *Node, + MachineFunction *MF); void outputExecutionMode(const Module &M); void outputAnnotations(const Module &M); void outputModuleSections(); @@ -492,6 +495,45 @@ void SPIRVAsmPrinter::outputExecutionModeFromNumthreadsAttribute( outputMCInst(Inst); } +// outputs the execution mode for the extension SPV_INTEL_maximum_registers +void SPIRVAsmPrinter::outputExecutionModeFromRegisterAllocMode( + const MCRegister &Reg, const MDNode *Node, MachineFunction *MF) { + MCInst Inst; + auto *RegisterAllocMode = Node->getOperand(0).get(); + Inst.setOpcode(SPIRV::OpExecutionMode); + Inst.addOperand(MCOperand::createReg(Reg)); + + if (auto *MDS = dyn_cast(RegisterAllocMode)) { + StringRef Str = MDS->getString(); + if (Str.equals_insensitive("AutoINTEL")) { + Inst.addOperand(MCOperand::createImm(static_cast( + SPIRV::ExecutionMode::NamedMaximumRegistersINTEL))); + Inst.addOperand(MCOperand::createImm(static_cast( + SPIRV::NamedMaximumNumberOfRegisters::AutoINTEL))); + } + } else if (MDNode *NestedNode = dyn_cast(RegisterAllocMode)) { + if (auto *CMD = dyn_cast(NestedNode->getOperand(0))) { + if (ConstantInt *CI = dyn_cast(CMD->getValue())) { + Inst.setOpcode(SPIRV::OpExecutionModeId); + Inst.addOperand(MCOperand::createImm( + SPIRV::ExecutionMode::MaximumRegistersIdINTEL)); + auto *GR = ST->getSPIRVGlobalRegistry(); + Register MaxOpConstantReg = GR->getMaxRegConstantExtMap(MF); + MCRegister MaxRegister = MAI->getRegisterAlias(MF, MaxOpConstantReg); + Inst.addOperand(MCOperand::createReg(MaxRegister)); + } + } + } else { + + int64_t RegisterAllocVal = + mdconst::dyn_extract(RegisterAllocMode)->getZExtValue(); + Inst.addOperand( + MCOperand::createImm(SPIRV::ExecutionMode::MaximumRegistersINTEL)); + Inst.addOperand(MCOperand::createImm(RegisterAllocVal)); + } + outputMCInst(Inst); +} + void SPIRVAsmPrinter::outputExecutionMode(const Module &M) { NamedMDNode *Node = M.getNamedMetadata("spirv.ExecutionMode"); if (Node) { @@ -532,6 +574,10 @@ void SPIRVAsmPrinter::outputExecutionMode(const Module &M) { Inst.addOperand(MCOperand::createImm(TypeCode)); outputMCInst(Inst); } + if (MDNode *Node = F.getMetadata("RegisterAllocMode")) { + MachineFunction *MF = MMI->getMachineFunction(F); + outputExecutionModeFromRegisterAllocMode(FReg, Node, MF); + } if (ST->isOpenCLEnv() && !M.getNamedMetadata("spirv.ExecutionMode") && !M.getNamedMetadata("opencl.enable.FP_CONTRACT")) { MCInst Inst; diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index 56cbd9414c9ee..bf9058886aa98 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_maximum_registers", + SPIRV::Extension::SPV_INTEL_maximum_registers}}; bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName, StringRef ArgValue, diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 4325023406c7c..47d8bcb57c5b0 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -149,6 +149,7 @@ class SPIRVEmitIntrinsics unsigned OperandToReplace, IRBuilder<> &B); void insertPtrCastOrAssignTypeInstr(Instruction *I, IRBuilder<> &B); + void insertMaxRegIdExecModeIntrs(Function *F, IRBuilder<> &B); bool shouldTryToAddMemAliasingDecoration(Instruction *Inst); void insertSpirvDecorations(Instruction *I, IRBuilder<> &B); void processGlobalValue(GlobalVariable &GV, IRBuilder<> &B); @@ -2210,6 +2211,30 @@ void SPIRVEmitIntrinsics::processParamTypesByFunHeader(Function *F, } } +void SPIRVEmitIntrinsics::insertMaxRegIdExecModeIntrs(Function *F, + IRBuilder<> &B) { + MDNode *Node = F->getMetadata("RegisterAllocMode"); + + if (Node) { + Metadata *RegisterAllocMode = Node->getOperand(0).get(); + // spv_max_reg_constant is added to add the OpConstant instruction which + // will be then used as operand for OpExecutionMode MaximumRegistersIdINTEL + if (MDNode *NestedNode = dyn_cast(RegisterAllocMode)) { + if (auto *CMD = dyn_cast(NestedNode->getOperand(0))) { + auto *CI = dyn_cast(CMD->getValue()); + if (!CI) + return; + int32_t MaxRegNumExt = CI->getSExtValue(); + B.SetInsertPointPastAllocas(F); + Value *MaxRegNumExtVal = + ConstantInt::get(Type::getInt32Ty(B.getContext()), MaxRegNumExt); + B.CreateIntrinsic(Intrinsic::spv_max_reg_constant, {}, + {MaxRegNumExtVal}); + } + } + } +} + void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) { B.SetInsertPointPastAllocas(F); for (unsigned OpIdx = 0; OpIdx < F->arg_size(); ++OpIdx) { @@ -2385,7 +2410,6 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { } processParamTypesByFunHeader(CurrF, B); - // StoreInst's operand type can be changed during the next transformations, // so we need to store it in the set. Also store already transformed types. for (auto &I : instructions(Func)) { @@ -2419,6 +2443,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { insertAssignTypeIntrs(I, B); insertPtrCastOrAssignTypeInstr(I, B); insertSpirvDecorations(I, B); + insertMaxRegIdExecModeIntrs(CurrF, B); // if instruction requires a pointee type set, let's check if we know it // already, and force it to be i8 if not if (Postpone && !GR->findAssignPtrTypeInstr(I)) diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h index b05896fb7174c..5e811edcdef0c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h @@ -68,6 +68,11 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping { // Number of bits pointers and size_t integers require. const unsigned PointerSize; + // Maps each MachineFunction to its associated OpConstant register for the + // SPV_INTEL_maximum_registers extension with ExecutionModeId + // MaximumRegistersIdINTEL. + DenseMap MaxRegConstantExtMap; + // Holds the maximum ID we have in the module. unsigned Bound; @@ -114,6 +119,15 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping { void setBound(unsigned V) { Bound = V; } unsigned getBound() { return Bound; } + void addMaxRegConstantRegisterExt(const MachineFunction *MF, Register Reg) { + MaxRegConstantExtMap[MF] = Reg; + } + + Register getMaxRegConstantExtMap(const MachineFunction *MF) { + assert(MaxRegConstantExtMap.count(MF) && + "MachineFunction not found in MaxRegConstantExtMap"); + return MaxRegConstantExtMap[MF]; + } void addGlobalObject(const Value *V, const MachineFunction *MF, Register R) { Reg2GO[std::make_pair(MF, R)] = V; } diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 0db60c068bdff..10b6f824120da 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -3191,6 +3191,13 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, case Intrinsic::spv_discard: { return selectDiscard(ResVReg, ResType, I); } + case Intrinsic::spv_max_reg_constant: { + int32_t MaxRegNum = I.getOperand(1).getImm(); + auto ConstMaxRegId = buildI32Constant(MaxRegNum, I); + Register MaxIdRegister = ConstMaxRegId.first; + GR.addMaxRegConstantRegisterExt(MF, MaxIdRegister); + return ConstMaxRegId.second; + } break; default: { std::string DiagMsg; raw_string_ostream OS(DiagMsg); diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 6d2ecd563d200..0e72c6f60ad81 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1176,6 +1176,50 @@ static bool isImageTypeWithUnknownFormat(SPIRVType *TypeInst) { return TypeInst->getOperand(7).getImm() == 0; } +static void setExtMaxRegId(const MachineFunction *MF, + SPIRV::ModuleAnalysisInfo &MAI, + SPIRVGlobalRegistry *GR) { + Register VirtualReg = GR->getMaxRegConstantExtMap(MF); + MCRegister MaxOpConstantReg = MAI.getNextIDRegister(); + MAI.setRegisterAlias(MF, VirtualReg, MaxOpConstantReg); +} + +static void transFunctionMetadataAsExecutionMode(const Function &F, + const SPIRVSubtarget &ST, + SPIRV::ModuleAnalysisInfo &MAI, + MachineFunction *MF) { + SmallVector RegisterAllocModeMDs; + F.getMetadata("RegisterAllocMode", RegisterAllocModeMDs); + if (!RegisterAllocModeMDs.empty()) { + MAI.Reqs.addExtension(SPIRV::Extension::SPV_INTEL_maximum_registers); + MAI.Reqs.addCapability(SPIRV::Capability::RegisterLimitsINTEL); + } + for (unsigned I = 0; I < RegisterAllocModeMDs.size(); I++) { + + auto *RegisterAllocMode = RegisterAllocModeMDs[I]->getOperand(0).get(); + if (auto *MDS = dyn_cast(RegisterAllocMode)) { + MAI.Reqs.getAndAddRequirements( + SPIRV::OperandCategory::ExecutionModeOperand, + SPIRV::ExecutionMode::NamedMaximumRegistersINTEL, ST); + } else if (isa(RegisterAllocMode)) { + MDNode *NestedNode = dyn_cast(RegisterAllocMode); + if (auto *CMD = dyn_cast(NestedNode->getOperand(0))) { + auto *CI = dyn_cast(CMD->getValue()); + if (!CI) + break; + MAI.Reqs.getAndAddRequirements( + SPIRV::OperandCategory::ExecutionModeOperand, + SPIRV::ExecutionMode::MaximumRegistersIdINTEL, ST); + setExtMaxRegId(MF, MAI, ST.getSPIRVGlobalRegistry()); + } + } else { + MAI.Reqs.getAndAddRequirements( + SPIRV::OperandCategory::ExecutionModeOperand, + SPIRV::ExecutionMode::MaximumRegistersINTEL, ST); + } + } +} + static void AddDotProductRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST) { @@ -1921,7 +1965,10 @@ static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, MAI.Reqs.getAndAddRequirements( SPIRV::OperandCategory::ExecutionModeOperand, SPIRV::ExecutionMode::VecTypeHint, ST); - + if (F.getMetadata("RegisterAllocMode")) { + MachineFunction *MF = MMI->getMachineFunction(F); + transFunctionMetadataAsExecutionMode(F, ST, MAI, MF); + } if (F.hasOptNone()) { if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) { MAI.Reqs.addExtension(SPIRV::Extension::SPV_INTEL_optnone); @@ -2059,7 +2106,6 @@ bool SPIRVModuleAnalysis::runOnModule(Module &M) { // Process type/const/global var/func decl instructions, number their // destination registers from 0 to N, collect Extensions and Capabilities. - collectReqs(M, MAI, MMI, *ST); collectDeclarations(M); // Number rest of registers from N+1 onwards. diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index cc32200a0a261..a8a75a19d3a23 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -172,6 +172,8 @@ def KernelProfilingInfoOperand : OperandCategory; def OpcodeOperand : OperandCategory; def CooperativeMatrixLayoutOperand : OperandCategory; def CooperativeMatrixOperandsOperand : OperandCategory; +def NamedMaximumNumberOfRegistersOperand: OperandCategory; + //===----------------------------------------------------------------------===// // Multiclass used to define Extesions enum values and at the same time @@ -315,6 +317,7 @@ defm SPV_INTEL_memory_access_aliasing : ExtensionOperand<118>; defm SPV_INTEL_fp_max_error : ExtensionOperand<119>; defm SPV_INTEL_ternary_bitwise_function : ExtensionOperand<120>; defm SPV_INTEL_subgroup_matrix_multiply_accumulate : ExtensionOperand<121>; +defm SPV_INTEL_maximum_registers : ExtensionOperand<122>; //===----------------------------------------------------------------------===// // Multiclass used to define Capabilities enum values and at the same time @@ -517,6 +520,7 @@ 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 RegisterLimitsINTEL : CapabilityOperand<6460 , 0, 0, [SPV_INTEL_maximum_registers], []>; //===----------------------------------------------------------------------===// // Multiclass used to define SourceLanguage enum values and at the same time @@ -714,6 +718,9 @@ defm RoundingModeRTPINTEL : ExecutionModeOperand<5620, [RoundToInfinityINTEL]>; defm RoundingModeRTNINTEL : ExecutionModeOperand<5621, [RoundToInfinityINTEL]>; defm FloatingPointModeALTINTEL : ExecutionModeOperand<5622, [FloatingPointModeINTEL]>; defm FloatingPointModeIEEEINTEL : ExecutionModeOperand<5623, [FloatingPointModeINTEL]>; +defm MaximumRegistersINTEL : ExecutionModeOperand<6461, [RegisterLimitsINTEL]>; +defm MaximumRegistersIdINTEL : ExecutionModeOperand<6462, [RegisterLimitsINTEL]>; +defm NamedMaximumRegistersINTEL : ExecutionModeOperand<6463, [RegisterLimitsINTEL]>; //===----------------------------------------------------------------------===// // Multiclass used to define StorageClass enum values and at the same time @@ -1746,3 +1753,28 @@ defm MatrixAAndBTF32ComponentsINTEL : CooperativeMatrixOperandsOperand<0x20, [SP defm MatrixAAndBBFloat16ComponentsINTEL : CooperativeMatrixOperandsOperand<0x40, [SPV_INTEL_joint_matrix], [CooperativeMatrixBFloat16ComponentTypeINTEL]>; defm MatrixCBFloat16ComponentsINTEL : CooperativeMatrixOperandsOperand<0x80, [SPV_INTEL_joint_matrix], [CooperativeMatrixBFloat16ComponentTypeINTEL]>; defm MatrixResultBFloat16ComponentsINTEL : CooperativeMatrixOperandsOperand<0x100, [SPV_INTEL_joint_matrix], [CooperativeMatrixBFloat16ComponentTypeINTEL]>; + +//===----------------------------------------------------------------------===// +// Multiclass used to define Named Max Number of Reg Operands enum values and at the +// same time SymbolicOperand entries with string mnemonics, extensions and +// capabilities. +//===----------------------------------------------------------------------===// + +def NamedMaximumNumberOfRegisters : GenericEnum, Operand { + let FilterClass = "NamedMaximumNumberOfRegisters"; + let NameField = "Name"; + let ValueField = "Value"; + let PrintMethod = !strconcat("printSymbolicOperand"); +} + +class NamedMaximumNumberOfRegisters value> { + string Name = name; + bits<32> Value = value; +} + +multiclass NamedMaximumNumberOfRegistersOperand value, list reqExtensions, list reqCapabilities> { + def : NamedMaximumNumberOfRegisters; + defm : SymbolicOperandWithRequirements; +} + +defm AutoINTEL : NamedMaximumNumberOfRegistersOperand<0x0, [SPV_INTEL_maximum_registers], [RegisterLimitsINTEL]>; diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_maximum_registers/registerallocmode_maxreg_extension.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_maximum_registers/registerallocmode_maxreg_extension.ll new file mode 100644 index 0000000000000..b30abf65aaaa1 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_maximum_registers/registerallocmode_maxreg_extension.ll @@ -0,0 +1,77 @@ +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_INTEL_maximum_registers -o - | FileCheck %s +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_INTEL_maximum_registers -o - -filetype=obj | spirv-val %} + +; CHECK: OpCapability RegisterLimitsINTEL +; CHECK: OpExtension "SPV_INTEL_maximum_registers" + +; CHECK: OpMemoryModel Physical64 OpenCL +; CHECK: OpExecutionMode %[[#f1:]] MaximumRegistersINTEL 2 +; CHECK: OpExecutionMode %[[#f2:]] MaximumRegistersINTEL 1 +; CHECK: OpExecutionMode %[[#f3:]] NamedMaximumRegistersINTEL AutoINTEL +; CHECK: OpExecutionModeId %[[#f4:]] MaximumRegistersIdINTEL %[[#const_3:]] + +; CHECK: %[[#void_type:]] = OpTypeVoid +; CHECK: %[[#func_type:]] = OpTypeFunction %[[#void_type]] + +; CHECK: %[[#int_type:]] = OpTypeInt 32 0 +; CHECK: %[[#const_3]] = OpConstant %[[#int_type]] 3 + +; CHECK: %[[#f1]] = OpFunction %[[#void_type]] DontInline %[[#]] +; Function Attrs: noinline nounwind optnone +define weak dso_local spir_kernel void @main_l3() #0 !RegisterAllocMode !10 { +newFuncRoot: + ret void +} + +; CHECK: %[[#f2]] = OpFunction %[[#void_type]] DontInline %[[#]] +; Function Attrs: noinline nounwind optnone +define weak dso_local spir_kernel void @main_l6() #0 !RegisterAllocMode !11 { +newFuncRoot: + ret void +} + +; CHECK: %[[#f3]] = OpFunction %[[#void_type]] DontInline %[[#]] +; Function Attrs: noinline nounwind optnone +define weak dso_local spir_kernel void @main_l9() #0 !RegisterAllocMode !12 { +newFuncRoot: + ret void +} + +; CHECK: %[[#f4]] = OpFunction %[[#void_type]] DontInline %[[#]] +; Function Attrs: noinline nounwind optnone +define weak dso_local spir_kernel void @main_l13() #0 !RegisterAllocMode !13 { +newFuncRoot: + ret void +} + +; CHECK: %[[#f5:]] = OpFunction %[[#void_type]] DontInline %[[#]] +; Function Attrs: noinline nounwind optnone +define weak dso_local spir_kernel void @main_l19() #0 { +newFuncRoot: + ret void +} + +attributes #0 = { noinline nounwind optnone } + + +!opencl.compiler.options = !{!0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0} +!spirv.Source = !{!2, !3, !3, !3, !3, !3, !2, !3, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2} +!llvm.module.flags = !{!4, !5, !6, !7, !8} +!spirv.MemoryModel = !{!9, !9, !9, !9, !9, !9} +!spirv.ExecutionMode = !{} + +!0 = !{} +!2 = !{i32 4, i32 200000} +!3 = !{i32 3, i32 200000} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 7, !"openmp", i32 50} +!6 = !{i32 7, !"openmp-device", i32 50} +!7 = !{i32 8, !"PIC Level", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 2} +!9 = !{i32 2, i32 2} +!10 = !{i32 2} +!11 = !{i32 1} +!12 = !{!"AutoINTEL"} +!13 = !{!14} +!14 = !{i32 3} +