[llvm] [SPIR-V] Fix some GEP legalization (PR #150943)

Nathan Gauër via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 29 05:53:28 PDT 2025


================
@@ -1588,7 +1721,22 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
   }
   if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
     Value *Pointer = GEPI->getPointerOperand();
-    Type *OpTy = GEPI->getSourceElementType();
+    Type *OpTy = nullptr;
+
+    // Knowing the accessed type is mandatory for logical SPIR-V. Sadly,
+    // the GEP source element type should not be used for this purpose, and
+    // the alternative type-scavenging method is not working.
+    // Physical SPIR-V can work around this, but not logical, hence still
+    // try to rely on the broken type scavenging for logical.
+    if (TM->getSubtargetImpl()->isLogicalSPIRV()) {
+      Value *Src = getPointerRoot(Pointer);
+      OpTy = GR->findDeducedElementType(Src);
+    }
----------------
Keenuts wrote:

Adding a switch to only change this for i8 GEP.
As for the given code, this is another issue impacting structured GEPs (non-i8) when accessing nested fields:

```
struct S {
    int arr[10];
};

-> s.arr[index]
```

In this case, the generated GEP is something like:
`getelementptr [10 x int], %ptr, i32 0, i32 %index` instead of
`getelementptr [10 x int], %ptr, i32 0, i32 0, i32 %index`

-> The first index is usually not used to index into a nested field, but to index into the implicit array represented by the pointer. For this reason, our GEP lowering usually discards the first index. But here, this means we'd generate:
`OpAccessChain %v4f %ptr %index` instead of the required `OpAccessChain %v4f %ptr %index`.

I should work on some kind of "fixOpAccessChainDepth` step or something like that. But since this impacts structured GEP and not i8 gep, I'd move this to another PR.

https://github.com/llvm/llvm-project/pull/150943


More information about the llvm-commits mailing list