65 lines · plain
1// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \2// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s3 4// This test verifies local arrays of resources in HLSL.5 6// CHECK: @_ZL1A = internal global %"class.hlsl::RWBuffer" poison, align 47// CHECK: @_ZL1B = internal global %"class.hlsl::RWBuffer" poison, align 48// CHECK: @_ZL1C = internal global %"class.hlsl::RWBuffer" poison, align 49 10RWBuffer<float> A : register(u1);11RWBuffer<float> B : register(u2);12RWBuffer<float> C : register(u3);13RWStructuredBuffer<float> Out : register(u0);14 15// CHECK: define internal void @_Z4mainv()16// CHECK-NEXT: entry:17[numthreads(4,1,1)]18void main() {19// CHECK-NEXT: %First = alloca [3 x %"class.hlsl::RWBuffer"], align 420// CHECK-NEXT: %Second = alloca [4 x %"class.hlsl::RWBuffer"], align 421 RWBuffer<float> First[3] = { A, B, C };22 RWBuffer<float> Second[4];23 24// Verify initialization of First array from an initialization list25// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %First, ptr {{.*}} @_ZL1A)26// CHECK-NEXT: %[[Ptr1:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %First, i32 127// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[Ptr1]], ptr {{.*}} @_ZL1B)28// CHECK-NEXT: %[[Ptr2:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %First, i32 229// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[Ptr2]], ptr {{.*}} @_ZL1C)30 31// Verify default initialization of Second array, which means there is a loop iterating32// over the array elements and calling the default constructor for each33// CHECK-NEXT: %[[ArrayBeginPtr:.*]] = getelementptr inbounds [4 x %"class.hlsl::RWBuffer"], ptr %Second, i32 0, i32 034// CHECK-NEXT: %[[ArrayEndPtr:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[ArrayBeginPtr]], i32 435// CHECK-NEXT: br label %[[ArrayInitLoop:.*]]36// CHECK: [[ArrayInitLoop]]:37// CHECK-NEXT: %[[ArrayCurPtr:.*]] = phi ptr [ %[[ArrayBeginPtr]], %entry ], [ %[[ArrayNextPtr:.*]], %[[ArrayInitLoop]] ]38// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1Ev(ptr {{.*}} %[[ArrayCurPtr]])39// CHECK-NEXT: %[[ArrayNextPtr]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[ArrayCurPtr]], i32 140// CHECK-NEXT: %[[ArrayInitDone:.*]] = icmp eq ptr %[[ArrayNextPtr]], %[[ArrayEndPtr]]41// CHECK-NEXT: br i1 %[[ArrayInitDone]], label %[[AfterArrayInit:.*]], label %[[ArrayInitLoop]]42// CHECK: [[AfterArrayInit]]:43 44// Initialize First[2] with C45// CHECK: %[[Ptr3:.*]] = getelementptr inbounds [4 x %"class.hlsl::RWBuffer"], ptr %Second, i32 0, i32 246// CHECK: call {{.*}} @_ZN4hlsl8RWBufferIfEaSERKS1_(ptr {{.*}} %[[Ptr3]], ptr {{.*}} @_ZL1C)47 Second[2] = C;48 49 // NOTE: _ZN4hlsl8RWBufferIfEixEj is the subscript operator for RWBuffer<float>50 51// get First[1][0] value52// CHECK: %[[First_1_Ptr:.*]] = getelementptr inbounds [3 x %"class.hlsl::RWBuffer"], ptr %First, i32 0, i32 153// CHECK: %[[BufPtr1:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[First_1_Ptr]], i32 noundef 0)54// CHECK: %[[Value1:.*]] = load float, ptr %[[BufPtr1]], align 455 56// get Second[2][0] value57// CHECK: %[[Second_2_Ptr:.*]] = getelementptr inbounds [4 x %"class.hlsl::RWBuffer"], ptr %Second, i32 0, i32 258// CHECK: %[[BufPtr2:.*]] = call {{.*}} ptr @_ZN4hlsl8RWBufferIfEixEj(ptr {{.*}} %[[Second_2_Ptr]], i32 noundef 0)59// CHECK: %[[Value2:.*]] = load float, ptr %[[BufPtr2]], align 460 61// add them62// CHECK: %{{.*}} = fadd {{.*}} float %[[Value1]], %[[Value2]]63 Out[0] = First[1][0] + Second[2][0];64}65