-
Notifications
You must be signed in to change notification settings - Fork 17.9k
[SPIRV] Add support for SPV_KHR_abort extension #193037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
eab1954
31414b8
d0da520
4936a11
5ac1874
6bacaf1
f4c0835
dd33160
f65c7f7
57c64dd
b5c48c4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -348,6 +348,8 @@ class SPIRVInstructionSelector : public InstructionSelector { | |
|
|
||
| bool diagnoseUnsupported(const MachineInstr &I, const Twine &Msg) const; | ||
|
|
||
| bool selectAbort(MachineInstr &I) const; | ||
| bool selectTrap(MachineInstr &I) const; | ||
| bool selectFrameIndex(Register ResVReg, SPIRVTypeInst ResType, | ||
| MachineInstr &I) const; | ||
| bool selectAllocaArray(Register ResVReg, SPIRVTypeInst ResType, | ||
|
|
@@ -1375,11 +1377,13 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg, | |
| case TargetOpcode::G_UNMERGE_VALUES: | ||
| return selectUnmergeValues(I); | ||
|
|
||
| case TargetOpcode::G_TRAP: | ||
| case TargetOpcode::G_UBSANTRAP: | ||
| return selectTrap(I); | ||
|
|
||
| // Discard gen opcodes for intrinsics which we do not expect to actually | ||
| // represent code after lowering or intrinsics which are not implemented but | ||
| // should not crash when found in a customer's LLVM IR input. | ||
| case TargetOpcode::G_TRAP: | ||
| case TargetOpcode::G_UBSANTRAP: | ||
| case TargetOpcode::DBG_LABEL: | ||
| return true; | ||
| case TargetOpcode::G_DEBUGTRAP: | ||
|
|
@@ -1739,9 +1743,9 @@ bool SPIRVInstructionSelector::selectPopCount(Register ResVReg, | |
| SPIRVTypeInst ResType, | ||
| MachineInstr &I, | ||
| unsigned Opcode) const { | ||
| // Vulkan restricts OpBitCount to 32-bit integers or vectors of 32-bit | ||
| // integers unless VK_KHR_maintenance9 is enabled. Until VK_KHR_maintaince9 | ||
| // is core we will not generate OpBitCount with any other types when | ||
| // Vulkan restricts OpBitCount to 32-bit integers or vectors of 32-bit | ||
| // integers unless VK_KHR_maintenance9 is enabled. Until VK_KHR_maintenance9 | ||
| // is core we will not generate OpBitCount with any other types when | ||
| // targeting Vulkan. | ||
| if (!STI.getTargetTriple().isVulkanOS()) | ||
| return selectUnOp(ResVReg, ResType, I, Opcode); | ||
|
|
@@ -4760,6 +4764,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, | |
| BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpUnreachable)) | ||
| .constrainAllUses(TII, TRI, RBI); | ||
| return true; | ||
| case Intrinsic::spv_abort: | ||
| return selectAbort(I); | ||
| case Intrinsic::spv_alloca: | ||
| return selectFrameIndex(ResVReg, ResType, I); | ||
| case Intrinsic::spv_alloca_array: | ||
|
|
@@ -6326,6 +6332,86 @@ bool SPIRVInstructionSelector::selectAllocaArray(Register ResVReg, | |
| return true; | ||
| } | ||
|
|
||
| // Returns true iff `Ty` is a concrete SPIR-V type per the SPV_KHR_abort | ||
| // definition: a numerical scalar (int/float), a (physical) pointer, a vector, | ||
| // matrix or any aggregate (array/struct) recursively containing only such | ||
| // types. OpTypeBool, OpTypeVoid, opaque handles and similar abstract | ||
| // non-concrete types are rejected. | ||
| static bool isConcreteSPIRVType(SPIRVTypeInst Ty, | ||
| const SPIRVGlobalRegistry &GR) { | ||
| SmallVector<SPIRVTypeInst, 4> Worklist{Ty}; | ||
| while (!Worklist.empty()) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this deserves its own function. |
||
| SPIRVTypeInst T = Worklist.pop_back_val(); | ||
| switch (T->getOpcode()) { | ||
| case SPIRV::OpTypeInt: | ||
| case SPIRV::OpTypeFloat: | ||
| case SPIRV::OpTypePointer: | ||
| break; | ||
| case SPIRV::OpTypeVector: | ||
| case SPIRV::OpTypeMatrix: | ||
| case SPIRV::OpTypeArray: { | ||
| Register OperandReg = T->getOperand(1).getReg(); | ||
| SPIRVTypeInst ElementT = GR.getSPIRVTypeForVReg(OperandReg); | ||
| Worklist.push_back(ElementT); | ||
| } break; | ||
| case SPIRV::OpTypeStruct: | ||
| for (unsigned Idx = 1, E = T->getNumOperands(); Idx < E; ++Idx) { | ||
| Register OperandReg = T->getOperand(Idx).getReg(); | ||
| SPIRVTypeInst ElementT = GR.getSPIRVTypeForVReg(OperandReg); | ||
| Worklist.push_back(ElementT); | ||
| } | ||
| break; | ||
| default: | ||
|
Comment on lines
+6343
to
+6364
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this also be a physical pointer (since it can be any concrete type)?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implemented: d0da520 |
||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| bool SPIRVInstructionSelector::selectAbort(MachineInstr &I) const { | ||
| assert(I.getNumExplicitOperands() == 2); | ||
|
|
||
| Register MsgReg = I.getOperand(1).getReg(); | ||
| SPIRVTypeInst MsgType = GR.getSPIRVTypeForVReg(MsgReg); | ||
| assert(MsgType && "Message argument of llvm.spv.abort has no SPIR-V type"); | ||
|
|
||
| if (!isConcreteSPIRVType(MsgType, GR)) | ||
| return diagnoseUnsupported( | ||
| I, | ||
| "llvm.spv.abort message type must be a concrete SPIR-V type (numerical " | ||
| "scalar, pointer, vector, matrix, or aggregate of such types)"); | ||
|
|
||
| MachineBasicBlock &BB = *I.getParent(); | ||
| BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpAbortKHR)) | ||
| .addUse(GR.getSPIRVTypeID(MsgType)) | ||
| .addUse(MsgReg) | ||
| .constrainAllUses(TII, TRI, RBI); | ||
| return true; | ||
| } | ||
|
|
||
| bool SPIRVInstructionSelector::selectTrap(MachineInstr &I) const { | ||
| // When the SPV_KHR_abort extension is disabled, drop the G_TRAP and | ||
| // G_UBSANTRAP silently. | ||
| if (!STI.canUseExtension(SPIRV::Extension::SPV_KHR_abort)) | ||
| return true; | ||
|
|
||
| // Use the 32-bit integer constant for the abort "message" argument: | ||
| // - G_UBSANTRAP operand is zero-extended to 32 bits. | ||
| // - "All ones" constant is used for G_TRAP. | ||
| uint32_t MsgVal = ~0u; | ||
| if (I.getOpcode() == TargetOpcode::G_UBSANTRAP) | ||
| MsgVal = static_cast<uint32_t>(I.getOperand(0).getImm()); | ||
|
|
||
| SPIRVTypeInst MsgType = GR.getOrCreateSPIRVIntegerType(32, I, TII); | ||
| Register MsgReg = buildI32Constant(MsgVal, I, MsgType); | ||
| MachineBasicBlock &BB = *I.getParent(); | ||
| BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpAbortKHR)) | ||
| .addUse(GR.getSPIRVTypeID(MsgType)) | ||
| .addUse(MsgReg) | ||
| .constrainAllUses(TII, TRI, RBI); | ||
| return true; | ||
| } | ||
|
|
||
| bool SPIRVInstructionSelector::selectFrameIndex(Register ResVReg, | ||
| SPIRVTypeInst ResType, | ||
| MachineInstr &I) const { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.