llvm / llvm/llvm-project

[SPIRV] Reconstituted arrays in structs can end up with extra padding.

Open
#180,600 0 comments 0 reactions 0 assignees View on GitHub
backend:SPIR-V HLSL
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Given the following HLSL, I'm seeing an assertion in SPIRVLegalizePointerCast.cpp, in `buildLegalizedLoad`:
```
Assertion failed: ResultOpt && "Failed to load from aggregate: " "Could not find compatible memory layout.", file E:/code/llvm.org/llvm/lib/Target/SPIRV/SPIRVLegalizePointerCast.cpp, line 213
```

This assert is happening because we end with a load of cbuffer padding in `SPIRVLegalizePointerCast::transformLoad`, but the problem occurred earlier.

```hlsl
struct X {
int a1;
};
struct Y : X {
int a2;
int a3;
};
struct Z {
X xs[2];
Y y;
};

cbuffer cb0 : register(b0) {
Z zs[2];
};

RWStructuredBuffer Out : register(u1);

[numthreads(1,1,1)]
void main() {
Out[0] = zs[1].y.a2;
}
```
Compiler explorer: https://hlsl.godbolt.org/z/4xv3T9nTK

The problem here is that SPIRVUtils's `reconstitutePeeledArrayType` function isn't handling padding after the array correctly. Taking a look at the before/after of the SPIRVEmitIntrinsics pass, we see the issue,

`clang-dxc -spirv -T cs_6_5 -fvk-use-dx-layout x.hlsl -mllvm -stop-before=emit-intrinsics`
```llvm
%Z = type <{ <{ [1 x <{ %X, target("spirv.Padding", 12) }>], %X }>, target("spirv.Padding", 12), %Y }>
%X = type <{ i32 }>
%Y = type <{ i32, i32, i32 }>
```

clang-dxc -spirv -T cs_6_5 -fvk-use-dx-layout x.hlsl -mllvm -stop-after=emit-intrinsics
```llvm
%Z = type <{ <{ [1 x <{ %X, target("spirv.Padding", 12) }>], %X }>, target("spirv.Padding", 12), %Y }>
%X = type <{ i32 }>
%Y = type <{ i32, i32, i32 }>
%Z.0 = type <{ [2 x <{ %X, target("spirv.Padding", 12) }>], target("spirv.Padding", 12), %Y }>
```

The reconstituted type, `%Z.0`, has padding within the `2 x %X` array and also after it, but this doesn't match the physical layout of the original `%Z`, which should have `%Y` directly following the `%X` array. The correct reconstituted type should be:

```llvm
%Z.0 = type <{ [2 x <{ %X, target("spirv.Padding", 12) }>], %Y }>
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.