[clang] [llvm] [SPIR-V] Implement SPV_KHR_untyped_pointers extension (PR #201233)
Dmitry Sidorov via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 29 10:45:54 PDT 2026
================
@@ -4553,32 +4567,88 @@ bool SPIRVInstructionSelector::selectGEP(Register ResVReg,
SPIRVTypeInst ResType,
MachineInstr &I) const {
const bool IsGEPInBounds = I.getOperand(2).getImm();
+ // Pointers to opaque types stay typed even with the extension on, so emit the
+ // untyped variant only when the result is actually an untyped pointer.
+ const bool UseUntypedPointers =
+ ResType->getOpcode() == SPIRV::OpTypeUntypedPointerKHR;
- // OpAccessChain could be used for OpenCL, but the SPIRV-LLVM Translator only
- // relies on PtrAccessChain, so we'll try not to deviate. For Vulkan however,
- // we have to use Op[InBounds]AccessChain.
- const unsigned Opcode = STI.isLogicalSPIRV()
- ? (IsGEPInBounds ? SPIRV::OpInBoundsAccessChain
- : SPIRV::OpAccessChain)
- : (IsGEPInBounds ? SPIRV::OpInBoundsPtrAccessChain
- : SPIRV::OpPtrAccessChain);
+ // Determine the opcode based on pointer type and bounds checking.
+ // When using untyped pointers, use OpUntyped*AccessChainKHR variants.
+ unsigned Opcode;
+ if (UseUntypedPointers) {
+ if (STI.isLogicalSPIRV()) {
+ Opcode = IsGEPInBounds ? SPIRV::OpUntypedInBoundsAccessChainKHR
+ : SPIRV::OpUntypedAccessChainKHR;
+ } else {
+ Opcode = IsGEPInBounds ? SPIRV::OpUntypedInBoundsPtrAccessChainKHR
+ : SPIRV::OpUntypedPtrAccessChainKHR;
+ }
+ } else {
+ // OpAccessChain could be used for OpenCL, but the SPIRV-LLVM Translator
+ // only relies on PtrAccessChain, so we'll try not to deviate. For Vulkan
+ // however, we have to use Op[InBounds]AccessChain.
+ // FIXME: fix llvm-spirv.
+ if (STI.isLogicalSPIRV()) {
+ Opcode =
+ IsGEPInBounds ? SPIRV::OpInBoundsAccessChain : SPIRV::OpAccessChain;
+ } else {
+ Opcode = IsGEPInBounds ? SPIRV::OpInBoundsPtrAccessChain
+ : SPIRV::OpPtrAccessChain;
+ }
+ }
auto Res = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode))
.addDef(ResVReg)
- .addUse(GR.getSPIRVTypeID(ResType))
- // Object to get a pointer to.
- .addUse(I.getOperand(3).getReg());
- assert(
- (Opcode == SPIRV::OpPtrAccessChain ||
- Opcode == SPIRV::OpInBoundsPtrAccessChain ||
- (getImm(I.getOperand(4), MRI) && foldImm(I.getOperand(4), MRI) == 0)) &&
- "Cannot translate GEP to OpAccessChain. First index must be 0.");
+ .addUse(GR.getSPIRVTypeID(ResType));
+
+ // For untyped access chains, we need to add the base type operand.
+ if (UseUntypedPointers) {
+ // Get the element type from the base pointer register.
+ // For untyped pointers, this was stored when processing
+ // spv_assign_ptr_type.
+ Register BaseReg = I.getOperand(3).getReg();
+ SPIRVTypeInst BaseType = GR.getUntypedPtrElementType(BaseReg);
+ if (!BaseType) {
+ // Otherwise try the pointee type for mixed typed-pointer usage.
+ SPIRVTypeInst BasePtrType = GR.getSPIRVTypeForVReg(BaseReg);
+ BaseType = BasePtrType ? GR.getPointeeType(BasePtrType) : nullptr;
+ }
+ if (!BaseType) {
+ // The base may be a not-yet-selected global. Read its value type from
+ // the defining G_GLOBAL_VALUE, following copies.
+ Register DefReg = BaseReg;
+ MachineInstr *Def = MRI->getVRegDef(DefReg);
+ while (Def && Def->getOpcode() == TargetOpcode::COPY &&
+ Def->getOperand(1).isReg())
+ Def = MRI->getVRegDef(Def->getOperand(1).getReg());
+ if (Def && Def->getOpcode() == TargetOpcode::G_GLOBAL_VALUE)
+ if (const auto *GVar =
+ dyn_cast<GlobalVariable>(Def->getOperand(1).getGlobal()))
+ BaseType = GR.getOrCreateSPIRVType(GVar->getValueType(), I,
+ SPIRV::AccessQualifier::ReadWrite,
+ /*EmitIR=*/false);
+ }
+ if (!BaseType) {
+ BaseType = GR.getOrCreateSPIRVIntegerType(8, I, TII);
+ }
----------------
MrSidims wrote:
replaced with an error
https://github.com/llvm/llvm-project/pull/201233
More information about the cfe-commits
mailing list