diff options
author | Vyacheslav Levytskyy <89994100+VyacheslavLevytskyy@users.noreply.github.com> | 2024-02-27 10:58:45 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-27 10:58:45 +0100 |
commit | ada70f50a5591839d0c81a167ca64ce98ab2d088 (patch) | |
tree | 6a5191bdfb777f3ac04c0645ef8b03b78e4e4df7 /llvm/lib | |
parent | 9796b0e9f91bc8ff00d2616fa3656e1ca848c05c (diff) | |
download | llvm-ada70f50a5591839d0c81a167ca64ce98ab2d088.zip llvm-ada70f50a5591839d0c81a167ca64ce98ab2d088.tar.gz llvm-ada70f50a5591839d0c81a167ca64ce98ab2d088.tar.bz2 |
[SPIR-V]: add SPIR-V extension: SPV_INTEL_variable_length_array (#83002)
This PR adds SPIR-V extension SPV_INTEL_variable_length_array that
allows to allocate local arrays whose number of elements is unknown at
compile time:
* add a new SPIR-V internal intrinsic:int_spv_alloca_array
* legalize G_STACKSAVE and G_STACKRESTORE
* implement allocation of arrays (previously getArraySize() of
AllocaInst was not used)
* add tests
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 18 | ||||
-rw-r--r-- | llvm/lib/Target/SPIRV/SPIRVInstrInfo.td | 9 | ||||
-rw-r--r-- | llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 56 | ||||
-rw-r--r-- | llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td | 2 |
7 files changed, 98 insertions, 1 deletions
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index e32cd50..afb24bf 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -500,9 +500,25 @@ Instruction *SPIRVEmitIntrinsics::visitStoreInst(StoreInst &I) { } Instruction *SPIRVEmitIntrinsics::visitAllocaInst(AllocaInst &I) { + Value *ArraySize = nullptr; + if (I.isArrayAllocation()) { + const SPIRVSubtarget *STI = TM->getSubtargetImpl(*I.getFunction()); + if (!STI->canUseExtension( + SPIRV::Extension::SPV_INTEL_variable_length_array)) + report_fatal_error( + "array allocation: this instruction requires the following " + "SPIR-V extension: SPV_INTEL_variable_length_array", + false); + ArraySize = I.getArraySize(); + } + TrackConstants = false; Type *PtrTy = I.getType(); - auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_alloca, {PtrTy}, {}); + auto *NewI = + ArraySize + ? IRB->CreateIntrinsic(Intrinsic::spv_alloca_array, + {PtrTy, ArraySize->getType()}, {ArraySize}) + : IRB->CreateIntrinsic(Intrinsic::spv_alloca, {PtrTy}, {}); std::string InstName = I.hasName() ? I.getName().str() : ""; I.replaceAllUsesWith(NewI); I.eraseFromParent(); diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td index 7c5252e..fe8c909 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td +++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td @@ -287,6 +287,15 @@ def OpPtrNotEqual: Op<402, (outs ID:$res), (ins TYPE:$resType, ID:$a, ID:$b), def OpPtrDiff: Op<403, (outs ID:$res), (ins TYPE:$resType, ID:$a, ID:$b), "$res = OpPtrDiff $resType $a $b">; +// - SPV_INTEL_variable_length_array + +def OpVariableLengthArrayINTEL: Op<5818, (outs ID:$res), (ins TYPE:$type, ID:$length), + "$res = OpVariableLengthArrayINTEL $type $length">; +def OpSaveMemoryINTEL: Op<5819, (outs ID:$res), (ins TYPE:$type), + "$res = OpSaveMemoryINTEL $type">; +def OpRestoreMemoryINTEL: Op<5820, (outs), (ins ID:$ptr), + "OpRestoreMemoryINTEL $ptr">; + // 3.42.9 Function Instructions def OpFunction: Op<54, (outs ID:$func), diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index f1e18f0..9b38073 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -99,6 +99,10 @@ private: MachineInstr &I) const; bool selectStore(MachineInstr &I) const; + bool selectStackSave(Register ResVReg, const SPIRVType *ResType, + MachineInstr &I) const; + bool selectStackRestore(MachineInstr &I) const; + bool selectMemOperation(Register ResVReg, MachineInstr &I) const; bool selectAtomicRMW(Register ResVReg, const SPIRVType *ResType, @@ -167,6 +171,8 @@ private: bool selectFrameIndex(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const; + bool selectAllocaArray(Register ResVReg, const SPIRVType *ResType, + MachineInstr &I) const; bool selectBranch(MachineInstr &I) const; bool selectBranchCond(MachineInstr &I) const; @@ -508,6 +514,11 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg, case TargetOpcode::G_FENCE: return selectFence(I); + case TargetOpcode::G_STACKSAVE: + return selectStackSave(ResVReg, ResType, I); + case TargetOpcode::G_STACKRESTORE: + return selectStackRestore(I); + default: return false; } @@ -653,6 +664,35 @@ bool SPIRVInstructionSelector::selectStore(MachineInstr &I) const { return MIB.constrainAllUses(TII, TRI, RBI); } +bool SPIRVInstructionSelector::selectStackSave(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + if (!STI.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) + report_fatal_error( + "llvm.stacksave intrinsic: this instruction requires the following " + "SPIR-V extension: SPV_INTEL_variable_length_array", + false); + MachineBasicBlock &BB = *I.getParent(); + return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSaveMemoryINTEL)) + .addDef(ResVReg) + .addUse(GR.getSPIRVTypeID(ResType)) + .constrainAllUses(TII, TRI, RBI); +} + +bool SPIRVInstructionSelector::selectStackRestore(MachineInstr &I) const { + if (!STI.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) + report_fatal_error( + "llvm.stackrestore intrinsic: this instruction requires the following " + "SPIR-V extension: SPV_INTEL_variable_length_array", + false); + if (!I.getOperand(0).isReg()) + return false; + MachineBasicBlock &BB = *I.getParent(); + return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpRestoreMemoryINTEL)) + .addUse(I.getOperand(0).getReg()) + .constrainAllUses(TII, TRI, RBI); +} + bool SPIRVInstructionSelector::selectMemOperation(Register ResVReg, MachineInstr &I) const { MachineBasicBlock &BB = *I.getParent(); @@ -1505,6 +1545,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, break; case Intrinsic::spv_alloca: return selectFrameIndex(ResVReg, ResType, I); + case Intrinsic::spv_alloca_array: + return selectAllocaArray(ResVReg, ResType, I); case Intrinsic::spv_assume: if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpAssumeTrueKHR)) @@ -1524,6 +1566,20 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, return true; } +bool SPIRVInstructionSelector::selectAllocaArray(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + // there was an allocation size parameter to the allocation instruction + // that is not 1 + MachineBasicBlock &BB = *I.getParent(); + return BuildMI(BB, I, I.getDebugLoc(), + TII.get(SPIRV::OpVariableLengthArrayINTEL)) + .addDef(ResVReg) + .addUse(GR.getSPIRVTypeID(ResType)) + .addUse(I.getOperand(2).getReg()) + .constrainAllUses(TII, TRI, RBI); +} + bool SPIRVInstructionSelector::selectFrameIndex(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const { diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp index aedca79..049ca4a 100644 --- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp @@ -186,6 +186,8 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) { getActionDefinitionsBuilder({G_IMPLICIT_DEF, G_FREEZE}).alwaysLegal(); + getActionDefinitionsBuilder({G_STACKSAVE, G_STACKRESTORE}).alwaysLegal(); + getActionDefinitionsBuilder(G_INTTOPTR) .legalForCartesianProduct(allPtrs, allIntScalars); getActionDefinitionsBuilder(G_PTRTOINT) diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 3be28c9..ac3d6b3 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1110,6 +1110,14 @@ void addInstrRequirements(const MachineInstr &MI, case SPIRV::OpAtomicFMaxEXT: AddAtomicFloatRequirements(MI, Reqs, ST); break; + case SPIRV::OpVariableLengthArrayINTEL: + case SPIRV::OpSaveMemoryINTEL: + case SPIRV::OpRestoreMemoryINTEL: + if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) { + Reqs.addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array); + Reqs.addCapability(SPIRV::Capability::VariableLengthArrayINTEL); + } + break; default: break; } diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp index 79f1614..0e8952d 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp @@ -85,6 +85,10 @@ cl::list<SPIRV::Extension::Extension> Extensions( "SPV_KHR_subgroup_rotate", "Adds a new instruction that enables rotating values across " "invocations within a subgroup."), + clEnumValN(SPIRV::Extension::SPV_INTEL_variable_length_array, + "SPV_INTEL_variable_length_array", + "Allows to allocate local arrays whose number of elements " + "is unknown at compile time."), clEnumValN(SPIRV::Extension::SPV_INTEL_function_pointers, "SPV_INTEL_function_pointers", "Allows translation of function pointers."))); diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index b022b97..211c223 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -296,6 +296,7 @@ defm SPV_INTEL_fpga_latency_control : ExtensionOperand<101>; defm SPV_INTEL_fpga_argument_interfaces : ExtensionOperand<102>; defm SPV_INTEL_optnone : ExtensionOperand<103>; defm SPV_INTEL_function_pointers : ExtensionOperand<104>; +defm SPV_INTEL_variable_length_array : ExtensionOperand<105>; //===----------------------------------------------------------------------===// // Multiclass used to define Capabilities enum values and at the same time @@ -462,6 +463,7 @@ defm AtomicFloat16AddEXT : CapabilityOperand<6095, 0, 0, [SPV_EXT_shader_atomic_ defm AtomicFloat16MinMaxEXT : CapabilityOperand<5616, 0, 0, [SPV_EXT_shader_atomic_float_min_max], []>; defm AtomicFloat32MinMaxEXT : CapabilityOperand<5612, 0, 0, [SPV_EXT_shader_atomic_float_min_max], []>; defm AtomicFloat64MinMaxEXT : CapabilityOperand<5613, 0, 0, [SPV_EXT_shader_atomic_float_min_max], []>; +defm VariableLengthArrayINTEL : CapabilityOperand<5817, 0, 0, [SPV_INTEL_variable_length_array], []>; defm GroupUniformArithmeticKHR : CapabilityOperand<6400, 0, 0, [SPV_KHR_uniform_group_instructions], []>; defm USMStorageClassesINTEL : CapabilityOperand<5935, 0, 0, [SPV_INTEL_usm_storage_classes], [Kernel]>; |