xref: /llvm-project/llvm/test/CodeGen/DirectX/BufferLoad.ll (revision 011b618644113996e2c0a8e57db40f89d20878e3)
1; RUN: opt -S -dxil-op-lower %s | FileCheck %s
2
3target triple = "dxil-pc-shadermodel6.6-compute"
4
5declare void @scalar_user(float)
6declare void @vector_user(<4 x float>)
7declare void @check_user(i1)
8
9define void @loadv4f32() {
10  ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
11  ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
12  %buffer = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0)
13      @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_0_0_0(
14          i32 0, i32 0, i32 1, i32 0, i1 false)
15
16  ; The temporary casts should all have been cleaned up
17  ; CHECK-NOT: %dx.resource.casthandle
18
19  ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR:]]
20  %load0 = call {<4 x float>, i1} @llvm.dx.resource.load.typedbuffer(
21      target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 0)
22  %data0 = extractvalue {<4 x float>, i1} %load0, 0
23
24  ; The extract order depends on the users, so don't enforce that here.
25  ; CHECK-DAG: [[VAL0_0:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA0]], 0
26  %data0_0 = extractelement <4 x float> %data0, i32 0
27  ; CHECK-DAG: [[VAL0_2:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA0]], 2
28  %data0_2 = extractelement <4 x float> %data0, i32 2
29
30  ; If all of the uses are extracts, we skip creating a vector
31  ; CHECK-NOT: insertelement
32  ; CHECK-DAG: call void @scalar_user(float [[VAL0_0]])
33  ; CHECK-DAG: call void @scalar_user(float [[VAL0_2]])
34  call void @scalar_user(float %data0_0)
35  call void @scalar_user(float %data0_2)
36
37  ; CHECK: [[DATA4:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 4, i32 undef) #[[#ATTR]]
38  %load4 = call {<4 x float>, i1} @llvm.dx.resource.load.typedbuffer(
39      target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 4)
40  %data4 = extractvalue {<4 x float>, i1} %load4, 0
41
42  ; CHECK: extractvalue %dx.types.ResRet.f32 [[DATA4]], 0
43  ; CHECK: extractvalue %dx.types.ResRet.f32 [[DATA4]], 1
44  ; CHECK: extractvalue %dx.types.ResRet.f32 [[DATA4]], 2
45  ; CHECK: extractvalue %dx.types.ResRet.f32 [[DATA4]], 3
46  ; CHECK: insertelement <4 x float> undef
47  ; CHECK: insertelement <4 x float>
48  ; CHECK: insertelement <4 x float>
49  ; CHECK: insertelement <4 x float>
50  call void @vector_user(<4 x float> %data4)
51
52  ; CHECK: [[DATA12:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 12, i32 undef) #[[#ATTR]]
53  %load12 = call {<4 x float>, i1} @llvm.dx.resource.load.typedbuffer(
54      target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 12)
55  %data12 = extractvalue {<4 x float>, i1} %load12, 0
56
57  ; CHECK: [[DATA12_3:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA12]], 3
58  %data12_3 = extractelement <4 x float> %data12, i32 3
59
60  ; If there are a mix of users we need the vector, but extracts are direct
61  ; CHECK: call void @scalar_user(float [[DATA12_3]])
62  call void @scalar_user(float %data12_3)
63  call void @vector_user(<4 x float> %data12)
64
65  ret void
66}
67
68define void @index_dynamic(i32 %bufindex, i32 %elemindex) {
69  ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
70  ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
71  %buffer = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0)
72      @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_0_0_0(
73          i32 0, i32 0, i32 1, i32 0, i1 false)
74
75  ; CHECK: [[LOAD:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 %bufindex, i32 undef) #[[#ATTR]]
76  %load = call {<4 x float>, i1} @llvm.dx.resource.load.typedbuffer(
77      target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 %bufindex)
78  %data = extractvalue {<4 x float>, i1} %load, 0
79
80  ; CHECK: [[ALLOCA:%.*]] = alloca [4 x float]
81  ; CHECK: [[V0:%.*]] = extractvalue %dx.types.ResRet.f32 [[LOAD]], 0
82  ; CHECK: [[A0:%.*]] = getelementptr inbounds [4 x float], ptr [[ALLOCA]], i32 0, i32 0
83  ; CHECK: store float [[V0]], ptr [[A0]]
84  ; CHECK: [[V1:%.*]] = extractvalue %dx.types.ResRet.f32 [[LOAD]], 1
85  ; CHECK: [[A1:%.*]] = getelementptr inbounds [4 x float], ptr [[ALLOCA]], i32 0, i32 1
86  ; CHECK: store float [[V1]], ptr [[A1]]
87  ; CHECK: [[V2:%.*]] = extractvalue %dx.types.ResRet.f32 [[LOAD]], 2
88  ; CHECK: [[A2:%.*]] = getelementptr inbounds [4 x float], ptr [[ALLOCA]], i32 0, i32 2
89  ; CHECK: store float [[V2]], ptr [[A2]]
90  ; CHECK: [[V3:%.*]] = extractvalue %dx.types.ResRet.f32 [[LOAD]], 3
91  ; CHECK: [[A3:%.*]] = getelementptr inbounds [4 x float], ptr [[ALLOCA]], i32 0, i32 3
92  ; CHECK: store float [[V3]], ptr [[A3]]
93  ;
94  ; CHECK: [[PTR:%.*]] = getelementptr inbounds [4 x float], ptr [[ALLOCA]], i32 0, i32 %elemindex
95  ; CHECK: [[X:%.*]] = load float, ptr [[PTR]]
96  %x = extractelement <4 x float> %data, i32 %elemindex
97
98  ; CHECK: call void @scalar_user(float [[X]])
99  call void @scalar_user(float %x)
100
101  ret void
102}
103
104define void @loadf32() {
105  ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
106  ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
107  %buffer = call target("dx.TypedBuffer", float, 0, 0, 0)
108      @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_0_0_0(
109          i32 0, i32 0, i32 1, i32 0, i1 false)
110
111  ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
112  %load0 = call {float, i1} @llvm.dx.resource.load.typedbuffer(
113      target("dx.TypedBuffer", float, 0, 0, 0) %buffer, i32 0)
114  %data0 = extractvalue {float, i1} %load0, 0
115
116  ; CHECK: [[VAL0:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA0]], 0
117  ; CHECK: call void @scalar_user(float [[VAL0]])
118  call void @scalar_user(float %data0)
119
120  ret void
121}
122
123define void @loadv2f32() {
124  ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
125  ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
126  %buffer = call target("dx.TypedBuffer", <2 x float>, 0, 0, 0)
127      @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f32_0_0_0(
128          i32 0, i32 0, i32 1, i32 0, i1 false)
129
130  ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
131  %data0 = call {<2 x float>, i1} @llvm.dx.resource.load.typedbuffer(
132      target("dx.TypedBuffer", <2 x float>, 0, 0, 0) %buffer, i32 0)
133
134  ret void
135}
136
137define void @loadv4f32_checkbit() {
138  ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
139  ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
140  %buffer = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0)
141      @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_0_0_0(
142          i32 0, i32 0, i32 1, i32 0, i1 false)
143
144  ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
145  %data0 = call {<4 x float>, i1} @llvm.dx.resource.load.typedbuffer.f32(
146      target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i32 0)
147
148  ; CHECK: [[STATUS:%.*]] = extractvalue %dx.types.ResRet.f32 [[DATA0]], 4
149  ; CHECK: [[MAPPED:%.*]] = call i1 @dx.op.checkAccessFullyMapped.i32(i32 71, i32 [[STATUS]]) #[[#ATTR]]
150  %check = extractvalue {<4 x float>, i1} %data0, 1
151
152  ; CHECK: call void @check_user(i1 [[MAPPED]])
153  call void @check_user(i1 %check)
154
155  ret void
156}
157
158define void @loadv4i32() {
159  ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
160  ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
161  %buffer = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
162      @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4i32_0_0_0(
163          i32 0, i32 0, i32 1, i32 0, i1 false)
164
165  ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.i32 @dx.op.bufferLoad.i32(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
166  %data0 = call {<4 x i32>, i1} @llvm.dx.resource.load.typedbuffer(
167      target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) %buffer, i32 0)
168
169  ret void
170}
171
172define void @loadv4f16() {
173  ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
174  ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
175  %buffer = call target("dx.TypedBuffer", <4 x half>, 0, 0, 0)
176      @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f16_0_0_0(
177          i32 0, i32 0, i32 1, i32 0, i1 false)
178
179  ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.f16 @dx.op.bufferLoad.f16(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
180  %data0 = call {<4 x half>, i1} @llvm.dx.resource.load.typedbuffer(
181      target("dx.TypedBuffer", <4 x half>, 0, 0, 0) %buffer, i32 0)
182
183  ret void
184}
185
186define void @loadv4i16() {
187  ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
188  ; CHECK: [[HANDLE:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]]
189  %buffer = call target("dx.TypedBuffer", <4 x i16>, 0, 0, 0)
190      @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4i16_0_0_0(
191          i32 0, i32 0, i32 1, i32 0, i1 false)
192
193  ; CHECK: [[DATA0:%.*]] = call %dx.types.ResRet.i16 @dx.op.bufferLoad.i16(i32 68, %dx.types.Handle [[HANDLE]], i32 0, i32 undef) #[[#ATTR]]
194  %data0 = call {<4 x i16>, i1} @llvm.dx.resource.load.typedbuffer(
195      target("dx.TypedBuffer", <4 x i16>, 0, 0, 0) %buffer, i32 0)
196
197  ret void
198}
199
200; CHECK: attributes #[[#ATTR]] = {{{.*}} memory(read) {{.*}}}
201