aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorVyacheslav Levytskyy <89994100+VyacheslavLevytskyy@users.noreply.github.com>2024-02-27 10:58:45 +0100
committerGitHub <noreply@github.com>2024-02-27 10:58:45 +0100
commitada70f50a5591839d0c81a167ca64ce98ab2d088 (patch)
tree6a5191bdfb777f3ac04c0645ef8b03b78e4e4df7 /llvm/lib
parent9796b0e9f91bc8ff00d2616fa3656e1ca848c05c (diff)
downloadllvm-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.cpp18
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVInstrInfo.td9
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp56
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp2
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp8
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp4
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td2
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]>;