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

No one assigned

    Type

    Projects

    Status

    Planning

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions