[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:53 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));
+ }
+ }
+
+ Value *loadScalarFromByteLayout(IRBuilder<> &B, Type *AccessTy, Value *Src,
+ Align Alignment) {
+ LLVMContext &Ctx = B.getContext();
+ Type *I8Ty = Type::getInt8Ty(Ctx);
+ const DataLayout &DL = B.GetInsertBlock()->getModule()->getDataLayout();
+ unsigned NumBytes = DL.getTypeStoreSize(AccessTy);
+ Type *IntTy = IntegerType::get(Ctx, DL.getTypeStoreSizeInBits(AccessTy));
+ Value *IntVal = ConstantInt::get(IntTy, 0);
+
+ for (unsigned I = 0; I < NumBytes; ++I) {
+ Value *Ptr = gepByteOffset(B, Src, I);
+ LoadInst *LI = B.CreateLoad(I8Ty, Ptr);
+ LI->setAlignment(commonAlignment(Alignment, I));
+ buildAssignType(B, I8Ty, LI);
+ Value *Extended = B.CreateZExt(LI, IntTy);
+ buildAssignType(B, IntTy, Extended);
+ Value *Shifted =
+ I == 0 ? Extended
----------------
farzonl wrote:
same comment here.
https://github.com/llvm/llvm-project/pull/212999
More information about the llvm-commits
mailing list