Skip to content

[DirectX] Validation errors: Pointer type bitcast must be have same size and Bitcast on struct types is not allowed #147109

Open
@Icohedron

Description

@Icohedron

The Problem

After resolving #146974, validation errors of the form Pointer type bitcast must be have same size and Bitcast on struct types is not allowed appear.
There are 16 occurrences of both errors in total, and they all originate from two DML shaders: OneHot_256_uint16_native_int64_emulated_4 and OneHot_256_uint16_native_int32_native_4

Reproducing the problem

Validate one of the problematic DML shaders mentioned.

dxv validation/OneHot_256_uint16_native_int32_native_4.dat

This minimal shader also reproduces the validation error when validated after being compiled https://godbolt.org/z/GexqvYc1d

// compile args: -E CSMain -T cs_6_2 -enable-16bit-types 
RWStructuredBuffer<uint> output;
struct MyStruct {
  uint arr[2];
};
[numthreads(1, 1, 1)]
void CSMain(uint3 Tid: SV_DispatchThreadID) {
  MyStruct s = {Tid.x, 0};
  uint d = s.arr[Tid.y];
  output[0] = d ;
}
Function: CSMain: error: Pointer type bitcast must be have same size.
note: at '%3 = bitcast %struct.MyStruct* %s.i to i32*' in block 'entry' of function 'CSMain'.
Function: CSMain: error: Bitcast on struct types is not allowed.
note: at '%4 = bitcast %struct.MyStruct* %s.i to [1 x %struct.MyStruct]*' in block 'entry' of function 'CSMain'.
Function: CSMain: error: Pointer type bitcast must be have same size.
note: at '%5 = bitcast %struct.MyStruct* %arrayinit.element.i1 to i32*' in block 'entry' of function 'CSMain'.
Function: CSMain: error: Bitcast on struct types is not allowed.
note: at '%6 = bitcast %struct.MyStruct* %s.i to [2 x i32]*' in block 'entry' of function 'CSMain'.
Validation failed.

Observations

Adding -Xclang -emit-llvm to the compile args, we can see the following loads, stores, and GEPs being emitted:

%struct.MyStruct = type { [2 x i32] }
  %1 = alloca %struct.MyStruct, align 4, !DIAssignID !56
  store i32 %3, ptr %1, align 4, !dbg !99, !tbaa !100, !DIAssignID !104
  %5 = getelementptr inbounds nuw i8, ptr %1, i32 4, !dbg !99
  store i32 0, ptr %5, align 4, !dbg !99, !tbaa !100, !DIAssignID !105
  %6 = getelementptr inbounds nuw [2 x i32], ptr %1, i32 0, i32 %4, !dbg !106
  %7 = load i32, ptr %6, align 4, !dbg !106, !tbaa !100

Case 1: Direct store of an i32 into a struct

This is similar to issue #147114 but it's a direct store into a struct alloca as opposed to an array alloca.

The store instruction

  %1 = alloca %struct.MyStruct, align 4, !DIAssignID !56
  store i32 %3, ptr %1, align 4, !dbg !99, !tbaa !100, !DIAssignID !104

causes the dxil-prepare pass to emit the bitcast

  %1 = alloca %struct.MyStruct, align 4, !DIAssignID !56
  %5 = bitcast ptr %1 to ptr, !dbg !108
  store i32 %3, ptr %5, align 4, !dbg !108

which triggers the validation error

Function: CSMain: error: Pointer type bitcast must be have same size.
note: at '%3 = bitcast %struct.MyStruct* %s.i to i32*' in block 'entry' of function 'CSMain'.

Case 2: i8 GEP improperly legalized for structs

The i8 GEP emitted by Clang

  %1 = alloca %struct.MyStruct, align 4, !DIAssignID !56
  %5 = getelementptr inbounds nuw i8, ptr %1, i32 4, !dbg !99
  store i32 0, ptr %5, align 4, !dbg !99, !tbaa !100, !DIAssignID !105

gets transformed by the dxil-legalize pass to

  %1 = alloca %struct.MyStruct, align 4, !DIAssignID !56
  %5 = getelementptr inbounds nuw [1 x %struct.MyStruct], ptr %1, i32 0, i32 0, !dbg !99
  store i32 0, ptr %5, align 4, !dbg !99, !tbaa !100, !DIAssignID !105

which causes the dxil-prepare pass to emit bitcasts

  %1 = alloca %struct.MyStruct, align 4, !DIAssignID !56
  %6 = bitcast ptr %1 to ptr, !dbg !108
  %7 = getelementptr inbounds nuw [1 x %struct.MyStruct], ptr %6, i32 0, i32 0, !dbg !108
  %8 = bitcast ptr %7 to ptr, !dbg !108
  store i32 0, ptr %8, align 4, !dbg !108

causing the validation errors

Function: CSMain: error: Bitcast on struct types is not allowed.
note: at '%4 = bitcast %struct.MyStruct* %s.i to [1 x %struct.MyStruct]*' in block 'entry' of function 'CSMain'.
Function: CSMain: error: Pointer type bitcast must be have same size.
note: at '%5 = bitcast %struct.MyStruct* %arrayinit.element.i1 to i32*' in block 'entry' of function 'CSMain'.

Case 3: Clang emits a [2 x i32] GEP for the struct access

The following GEP is emitted by Clang

  %1 = alloca %struct.MyStruct, align 4, !DIAssignID !56
  %6 = getelementptr inbounds nuw [2 x i32], ptr %1, i32 0, i32 %4, !dbg !106

for which dxil-prepare inserts a bitcast

  %1 = alloca %struct.MyStruct, align 4, !DIAssignID !56
  %9 = bitcast ptr %1 to ptr, !dbg !111
  %10 = getelementptr inbounds nuw [2 x i32], ptr %9, i32 0, i32 %4, !dbg !111

and triggers the validation error

Function: CSMain: error: Bitcast on struct types is not allowed.
note: at '%6 = bitcast %struct.MyStruct* %s.i to [2 x i32]*' in block 'entry' of function 'CSMain'.

Metadata

Metadata

Assignees

Type

Projects

Status

Planning

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions