[clang] [llvm] Explicit types in cbuffer layouts (PR #156919)

Steven Perron via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 3 07:04:39 PDT 2025


================
@@ -4678,6 +4678,26 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
         emitArraySubscriptGEP(*this, Int8Ty, Addr.emitRawPointer(*this),
                               ScaledIdx, false, SignedIndices, E->getExprLoc());
     Addr = Address(EltPtr, OrigBaseElemTy, EltAlign);
+  } else if (E->getType().getAddressSpace() == LangAS::hlsl_constant) {
+    // This is an array inside of a cbuffer.
+    Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
+    auto *Idx = EmitIdxAfterBase(/*Promote*/true);
+
+    // ...
+    CharUnits RowAlignedSize = getContext()
+                                   .getTypeSizeInChars(E->getType())
+                                   .alignTo(CharUnits::fromQuantity(16));
+
+    llvm::Value *RowAlignedSizeVal =
+        llvm::ConstantInt::get(Idx->getType(), RowAlignedSize.getQuantity());
+    llvm::Value *ScaledIdx = Builder.CreateMul(Idx, RowAlignedSizeVal);
+
+    CharUnits EltAlign =
+      getArrayElementAlign(Addr.getAlignment(), Idx, RowAlignedSize);
+    llvm::Value *EltPtr =
+        emitArraySubscriptGEP(*this, Int8Ty, Addr.emitRawPointer(*this),
+                              ScaledIdx, false, SignedIndices, E->getExprLoc());
----------------
s-perron wrote:

@bogner You are still generating this GEP with an i8. Can we change this to a GEP on the array type.

Start with the test at the end. Compile with `clang-dxc test_minimal_peeling.hlsl -T cs_6_8 -spirv -fcgl`

The access to myArray is:

```
  %3 = load i32, ptr %index, align 4, !tbaa !4
  %idxprom = zext i32 %3 to i64
  %4 = mul i64 %idxprom, 16
  %arrayidx = getelementptr i8, ptr addrspace(12) @myArray, i64 %4 ; <-- problem for SPIR-V.
  %f = getelementptr inbounds nuw %struct.OrigType, ptr addrspace(12) %arrayidx, i32 0, i32 0
  %5 = load float, ptr addrspace(12) %f, align 1, !tbaa !14
```

It would be better if it could be 

```
  %3 = load i32, ptr %index, align 4, !tbaa !4
  %idxprom = zext i32 %3 to i64
  %arrayidx = getelementptr [4 x <{ %OrigType, target("spirv.Padding", 12) }>], ptr addrspace(12) @myArray, i64 %idxprom ; <-- Explicit array
  %f = getelementptr inbounds nuw %struct.OrigType, ptr addrspace(12) %arrayidx, i32 0, i32 0
  %5 = load float, ptr addrspace(12) %f, align 1, !tbaa !14
```

You use the original array size with the padding.

```
struct OrigType {
  float f;
};

cbuffer MyCBuffer {
  OrigType myArray[4];
  float anotherValue;
};

RWBuffer<float4> output;

[numthreads(1, 1, 1)]
void main(uint3 DTid : SV_DispatchThreadID) {
  uint index = DTid.x % 4;
  float v = myArray[index].f;
  float f = anotherValue;
  output[0] = float4(v, f, 0, 0);
}
```

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


More information about the llvm-commits mailing list