[llvm] [SPIRV] Legalize byte-buffer reinterpretation ptrcasts (#192523) (PR #212999)

Farzon Lotfi via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 24 20:21:22 PDT 2026


================
@@ -222,15 +222,207 @@ class SPIRVLegalizePointerCastImpl {
     return std::make_pair(GEP, CurrentTy);
   }
 
+  static IntrinsicInst *getResourceGetPointer(Value *Ptr) {
+    if (auto *II = dyn_cast<IntrinsicInst>(Ptr))
+      if (II->getIntrinsicID() == Intrinsic::spv_resource_getpointer)
+        return II;
+    return nullptr;
+  }
+
+  Value *gepByteOffset(IRBuilder<> &B, Value *BasePtr, unsigned ByteOffset) {
+    if (ByteOffset == 0)
+      return BasePtr;
+
+    IntrinsicInst *ResourcePtr = getResourceGetPointer(BasePtr);
+    assert(ResourcePtr &&
+           "byte layout pointer must come from spv.resource.getpointer");
+
+    Value *Handle = ResourcePtr->getOperand(0);
+    Value *BaseOffset = ResourcePtr->getOperand(1);
+    Value *NewOffset;
+    if (auto *CI = dyn_cast<ConstantInt>(BaseOffset))
+      NewOffset =
+          ConstantInt::get(CI->getType(), CI->getZExtValue() + ByteOffset);
+    else
+      NewOffset = B.CreateAdd(
+          BaseOffset, ConstantInt::get(BaseOffset->getType(), ByteOffset));
+    SmallVector<OperandBundleDef> OpBundles;
+    ResourcePtr->getOperandBundlesAsDefs(OpBundles);
+    CallInst *ResourcePtrAtOffset = B.CreateCall(
+        ResourcePtr->getFunctionType(), ResourcePtr->getCalledOperand(),
+        {Handle, NewOffset}, OpBundles);
+    ResourcePtrAtOffset->setAttributes(ResourcePtr->getAttributes());
+    ResourcePtrAtOffset->setCallingConv(ResourcePtr->getCallingConv());
+    Type *I8Ty = Type::getInt8Ty(B.getContext());
+    GR->buildAssignPtr(B, I8Ty, ResourcePtrAtOffset);
+    return ResourcePtrAtOffset;
+  }
+
+  Value *scalarToStoreInt(IRBuilder<> &B, Value *Scalar) {
+    Type *Ty = Scalar->getType();
+    const DataLayout &DL = B.GetInsertBlock()->getModule()->getDataLayout();
+    Type *IntTy =
+        IntegerType::get(B.getContext(), DL.getTypeStoreSizeInBits(Ty));
+    if (Ty == IntTy)
+      return Scalar;
+    if (Ty->isIntOrIntVectorTy())
+      return B.CreateIntCast(Scalar, IntTy, /*isSigned=*/false);
+    return B.CreateBitCast(Scalar, IntTy);
+  }
+
+  Value *storeIntToScalar(IRBuilder<> &B, Value *IntVal, Type *ScalarTy) {
+    if (IntVal->getType() == ScalarTy)
+      return IntVal;
+    if (ScalarTy->isIntOrIntVectorTy())
+      return B.CreateIntCast(IntVal, ScalarTy, /*isSigned=*/false);
+    return B.CreateBitCast(IntVal, ScalarTy);
+  }
+
+  void storeScalarToByteLayout(IRBuilder<> &B, Value *Src, Value *Dst,
+                               Align Alignment) {
+    LLVMContext &Ctx = B.getContext();
+    Type *I8Ty = Type::getInt8Ty(Ctx);
+    const DataLayout &DL = B.GetInsertBlock()->getModule()->getDataLayout();
+    Value *IntVal = scalarToStoreInt(B, Src);
+    unsigned NumBytes = DL.getTypeStoreSize(Src->getType());
+
+    for (unsigned I = 0; I < NumBytes; ++I) {
+      Value *Shifted =
+          I == 0 ? IntVal
+                 : B.CreateLShr(IntVal,
+                                ConstantInt::get(IntVal->getType(), 8 * I));
+      Value *Byte = B.CreateTrunc(Shifted, I8Ty);
+      buildAssignType(B, I8Ty, Byte);
+      Value *Ptr = gepByteOffset(B, Dst, I);
+      StoreInst *SI = B.CreateStore(Byte, Ptr);
+      SI->setAlignment(commonAlignment(Alignment, I));
+    }
----------------
farzonl wrote:

I kind of hope the compiler hoists this terinary int something like this because looping over a branch that is only taken once kind of sucks.
```cpp
auto StoreByte = [&](unsigned I, Value *Shifted) {
  Value *Byte = B.CreateTrunc(Shifted, I8Ty);
  buildAssignType(B, I8Ty, Byte);
  Value *Ptr = gepByteOffset(B, Dst, I);
  StoreInst *SI = B.CreateStore(Byte, Ptr);
  SI->setAlignment(commonAlignment(Alignment, I));
};
  if (NumBytes > 0) 
    StoreByte(0, IntVal);

  for (unsigned I = 1; I < NumBytes; ++I) {
    Value *Shifted = B.CreateLShr(IntVal, ConstantInt::get(IntVal->getType(), 8 * I));
    StoreByte(I, Shifted);
  }
```

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


More information about the llvm-commits mailing list