1 // Copyright (c) 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <string>
16
17 #include "test/opt/pass_fixture.h"
18 #include "test/opt/pass_utils.h"
19
20 namespace {
21
22 const double kDefaultLoadReductionThreshold = 0.9;
23
24 } // namespace
25
26 namespace spvtools {
27 namespace opt {
28 namespace {
29
30 using ReduceLoadSizeTest = PassTest<::testing::Test>;
31
TEST_F(ReduceLoadSizeTest,cbuffer_load_extract)32 TEST_F(ReduceLoadSizeTest, cbuffer_load_extract) {
33 // Originally from the following HLSL:
34 // struct S {
35 // uint f;
36 // };
37 //
38 //
39 // cbuffer gBuffer { uint a[32]; };
40 //
41 // RWStructuredBuffer<S> gRWSBuffer;
42 //
43 // uint foo(uint p[32]) {
44 // return p[1];
45 // }
46 //
47 // [numthreads(1,1,1)]
48 // void main() {
49 // gRWSBuffer[0].f = foo(a);
50 // }
51 const std::string test =
52 R"(
53 OpCapability Shader
54 OpMemoryModel Logical GLSL450
55 OpEntryPoint GLCompute %main "main"
56 OpExecutionMode %main LocalSize 1 1 1
57 OpSource HLSL 600
58 OpName %type_gBuffer "type.gBuffer"
59 OpMemberName %type_gBuffer 0 "a"
60 OpName %gBuffer "gBuffer"
61 OpName %S "S"
62 OpMemberName %S 0 "f"
63 OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
64 OpName %gRWSBuffer "gRWSBuffer"
65 OpName %main "main"
66 OpDecorate %_arr_uint_uint_32 ArrayStride 16
67 OpMemberDecorate %type_gBuffer 0 Offset 0
68 OpDecorate %type_gBuffer Block
69 OpMemberDecorate %S 0 Offset 0
70 OpDecorate %_runtimearr_S ArrayStride 4
71 OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
72 OpDecorate %type_RWStructuredBuffer_S BufferBlock
73 OpDecorate %gBuffer DescriptorSet 0
74 OpDecorate %gBuffer Binding 0
75 OpDecorate %gRWSBuffer DescriptorSet 0
76 OpDecorate %gRWSBuffer Binding 1
77 %uint = OpTypeInt 32 0
78 %uint_32 = OpConstant %uint 32
79 %_arr_uint_uint_32 = OpTypeArray %uint %uint_32
80 %type_gBuffer = OpTypeStruct %_arr_uint_uint_32
81 %_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer
82 %S = OpTypeStruct %uint
83 %_runtimearr_S = OpTypeRuntimeArray %S
84 %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
85 %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
86 %int = OpTypeInt 32 1
87 %void = OpTypeVoid
88 %15 = OpTypeFunction %void
89 %int_0 = OpConstant %int 0
90 %_ptr_Uniform__arr_uint_uint_32 = OpTypePointer Uniform %_arr_uint_uint_32
91 %uint_0 = OpConstant %uint 0
92 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
93 %gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform
94 %gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
95 %main = OpFunction %void None %15
96 %20 = OpLabel
97 ; CHECK: [[ac1:%\w+]] = OpAccessChain {{%\w+}} %gBuffer %int_0
98 ; CHECK: [[ac2:%\w+]] = OpAccessChain {{%\w+}} [[ac1]] %uint_1
99 ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[ac2]]
100 ; CHECK: OpStore {{%\w+}} [[ld]]
101 %21 = OpAccessChain %_ptr_Uniform__arr_uint_uint_32 %gBuffer %int_0
102 %22 = OpLoad %_arr_uint_uint_32 %21 ; Load of 32-element array.
103 %23 = OpCompositeExtract %uint %22 1
104 %24 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0
105 OpStore %24 %23
106 OpReturn
107 OpFunctionEnd
108 )";
109
110 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
111 SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
112 SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
113 SinglePassRunAndMatch<ReduceLoadSize>(test, false,
114 kDefaultLoadReductionThreshold);
115 }
116
TEST_F(ReduceLoadSizeTest,cbuffer_load_extract_not_affected_by_debug_instr)117 TEST_F(ReduceLoadSizeTest, cbuffer_load_extract_not_affected_by_debug_instr) {
118 // Originally from the following HLSL:
119 // struct S {
120 // uint f;
121 // };
122 //
123 //
124 // cbuffer gBuffer { uint a[32]; };
125 //
126 // RWStructuredBuffer<S> gRWSBuffer;
127 //
128 // uint foo(uint p[32]) {
129 // return p[1];
130 // }
131 //
132 // [numthreads(1,1,1)]
133 // void main() {
134 // gRWSBuffer[0].f = foo(a);
135 // }
136 const std::string test =
137 R"(
138 OpCapability Shader
139 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
140 OpMemoryModel Logical GLSL450
141 OpEntryPoint GLCompute %main "main"
142 OpExecutionMode %main LocalSize 1 1 1
143 OpSource HLSL 600
144 %file_name = OpString "test"
145 %float_name = OpString "float"
146 %main_name = OpString "main"
147 %f_name = OpString "f"
148 OpName %type_gBuffer "type.gBuffer"
149 OpMemberName %type_gBuffer 0 "a"
150 OpName %gBuffer "gBuffer"
151 OpName %S "S"
152 OpMemberName %S 0 "f"
153 OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
154 OpName %gRWSBuffer "gRWSBuffer"
155 OpName %main "main"
156 OpDecorate %_arr_uint_uint_32 ArrayStride 16
157 OpMemberDecorate %type_gBuffer 0 Offset 0
158 OpDecorate %type_gBuffer Block
159 OpMemberDecorate %S 0 Offset 0
160 OpDecorate %_runtimearr_S ArrayStride 4
161 OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
162 OpDecorate %type_RWStructuredBuffer_S BufferBlock
163 OpDecorate %gBuffer DescriptorSet 0
164 OpDecorate %gBuffer Binding 0
165 OpDecorate %gRWSBuffer DescriptorSet 0
166 OpDecorate %gRWSBuffer Binding 1
167 %uint = OpTypeInt 32 0
168 %uint_32 = OpConstant %uint 32
169 %_arr_uint_uint_32 = OpTypeArray %uint %uint_32
170 %type_gBuffer = OpTypeStruct %_arr_uint_uint_32
171 %_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer
172 %S = OpTypeStruct %uint
173 %_runtimearr_S = OpTypeRuntimeArray %S
174 %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
175 %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
176 %int = OpTypeInt 32 1
177 %void = OpTypeVoid
178 %15 = OpTypeFunction %void
179 %int_0 = OpConstant %int 0
180 %_ptr_Uniform__arr_uint_uint_32 = OpTypePointer Uniform %_arr_uint_uint_32
181 %uint_0 = OpConstant %uint 0
182 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
183 %gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform
184 %gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
185 %null_expr = OpExtInst %void %ext DebugExpression
186 %src = OpExtInst %void %ext DebugSource %file_name
187 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
188 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
189 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_tf
190 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
191 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
192 %main = OpFunction %void None %15
193 %20 = OpLabel
194 %s = OpExtInst %void %ext DebugScope %dbg_main
195 ; CHECK: [[ac1:%\w+]] = OpAccessChain {{%\w+}} %gBuffer %int_0
196 ; CHECK: [[ac2:%\w+]] = OpAccessChain {{%\w+}} [[ac1]] %uint_1
197 ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[ac2]]
198 ; CHECK: OpStore {{%\w+}} [[ld]]
199 %21 = OpAccessChain %_ptr_Uniform__arr_uint_uint_32 %gBuffer %int_0
200 %22 = OpLoad %_arr_uint_uint_32 %21 ; Load of 32-element array.
201 %value = OpExtInst %void %ext DebugValue %dbg_f %22 %null_expr
202 %23 = OpCompositeExtract %uint %22 1
203 %24 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0
204 OpStore %24 %23
205 OpReturn
206 OpFunctionEnd
207 )";
208
209 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
210 SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
211 SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
212 SinglePassRunAndMatch<ReduceLoadSize>(test, false,
213 kDefaultLoadReductionThreshold);
214 }
215
TEST_F(ReduceLoadSizeTest,cbuffer_load_extract_vector)216 TEST_F(ReduceLoadSizeTest, cbuffer_load_extract_vector) {
217 // Originally from the following HLSL:
218 // struct S {
219 // uint f;
220 // };
221 //
222 //
223 // cbuffer gBuffer { uint4 a; };
224 //
225 // RWStructuredBuffer<S> gRWSBuffer;
226 //
227 // uint foo(uint p[32]) {
228 // return p[1];
229 // }
230 //
231 // [numthreads(1,1,1)]
232 // void main() {
233 // gRWSBuffer[0].f = foo(a);
234 // }
235 const std::string test =
236 R"(OpCapability Shader
237 OpMemoryModel Logical GLSL450
238 OpEntryPoint GLCompute %main "main"
239 OpExecutionMode %main LocalSize 1 1 1
240 OpSource HLSL 600
241 OpName %type_gBuffer "type.gBuffer"
242 OpMemberName %type_gBuffer 0 "a"
243 OpName %gBuffer "gBuffer"
244 OpName %S "S"
245 OpMemberName %S 0 "f"
246 OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
247 OpName %gRWSBuffer "gRWSBuffer"
248 OpName %main "main"
249 OpMemberDecorate %type_gBuffer 0 Offset 0
250 OpDecorate %type_gBuffer Block
251 OpMemberDecorate %S 0 Offset 0
252 OpDecorate %_runtimearr_S ArrayStride 4
253 OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
254 OpDecorate %type_RWStructuredBuffer_S BufferBlock
255 OpDecorate %gBuffer DescriptorSet 0
256 OpDecorate %gBuffer Binding 0
257 OpDecorate %gRWSBuffer DescriptorSet 0
258 OpDecorate %gRWSBuffer Binding 1
259 %uint = OpTypeInt 32 0
260 %uint_32 = OpConstant %uint 32
261 %v4uint = OpTypeVector %uint 4
262 %type_gBuffer = OpTypeStruct %v4uint
263 %_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer
264 %S = OpTypeStruct %uint
265 %_runtimearr_S = OpTypeRuntimeArray %S
266 %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
267 %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
268 %int = OpTypeInt 32 1
269 %void = OpTypeVoid
270 %15 = OpTypeFunction %void
271 %int_0 = OpConstant %int 0
272 %_ptr_Uniform_v4uint = OpTypePointer Uniform %v4uint
273 %uint_0 = OpConstant %uint 0
274 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
275 %gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform
276 %gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
277 %main = OpFunction %void None %15
278 %20 = OpLabel
279 %21 = OpAccessChain %_ptr_Uniform_v4uint %gBuffer %int_0
280 %22 = OpLoad %v4uint %21
281 %23 = OpCompositeExtract %uint %22 1
282 %24 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0
283 OpStore %24 %23
284 OpReturn
285 OpFunctionEnd
286 )";
287
288 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
289 SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
290 SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
291 SinglePassRunAndCheck<ReduceLoadSize>(test, test, true, false,
292 kDefaultLoadReductionThreshold);
293 }
294
TEST_F(ReduceLoadSizeTest,cbuffer_load_5_extract)295 TEST_F(ReduceLoadSizeTest, cbuffer_load_5_extract) {
296 // All of the elements of the value loaded are used, so we should not
297 // change the load.
298 const std::string test =
299 R"(OpCapability Shader
300 OpMemoryModel Logical GLSL450
301 OpEntryPoint GLCompute %main "main"
302 OpExecutionMode %main LocalSize 1 1 1
303 OpSource HLSL 600
304 OpName %type_gBuffer "type.gBuffer"
305 OpMemberName %type_gBuffer 0 "a"
306 OpName %gBuffer "gBuffer"
307 OpName %S "S"
308 OpMemberName %S 0 "f"
309 OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
310 OpName %gRWSBuffer "gRWSBuffer"
311 OpName %main "main"
312 OpDecorate %_arr_uint_uint_5 ArrayStride 16
313 OpMemberDecorate %type_gBuffer 0 Offset 0
314 OpDecorate %type_gBuffer Block
315 OpMemberDecorate %S 0 Offset 0
316 OpDecorate %_runtimearr_S ArrayStride 4
317 OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
318 OpDecorate %type_RWStructuredBuffer_S BufferBlock
319 OpDecorate %gBuffer DescriptorSet 0
320 OpDecorate %gBuffer Binding 0
321 OpDecorate %gRWSBuffer DescriptorSet 0
322 OpDecorate %gRWSBuffer Binding 1
323 %uint = OpTypeInt 32 0
324 %uint_5 = OpConstant %uint 5
325 %_arr_uint_uint_5 = OpTypeArray %uint %uint_5
326 %type_gBuffer = OpTypeStruct %_arr_uint_uint_5
327 %_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer
328 %S = OpTypeStruct %uint
329 %_runtimearr_S = OpTypeRuntimeArray %S
330 %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
331 %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
332 %int = OpTypeInt 32 1
333 %void = OpTypeVoid
334 %15 = OpTypeFunction %void
335 %int_0 = OpConstant %int 0
336 %_ptr_Uniform__arr_uint_uint_5 = OpTypePointer Uniform %_arr_uint_uint_5
337 %uint_0 = OpConstant %uint 0
338 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
339 %gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform
340 %gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
341 %main = OpFunction %void None %15
342 %20 = OpLabel
343 %21 = OpAccessChain %_ptr_Uniform__arr_uint_uint_5 %gBuffer %int_0
344 %22 = OpLoad %_arr_uint_uint_5 %21
345 %23 = OpCompositeExtract %uint %22 0
346 %24 = OpCompositeExtract %uint %22 1
347 %25 = OpCompositeExtract %uint %22 2
348 %26 = OpCompositeExtract %uint %22 3
349 %27 = OpCompositeExtract %uint %22 4
350 %28 = OpIAdd %uint %23 %24
351 %29 = OpIAdd %uint %28 %25
352 %30 = OpIAdd %uint %29 %26
353 %31 = OpIAdd %uint %20 %27
354 %32 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0
355 OpStore %32 %31
356 OpReturn
357 OpFunctionEnd
358 )";
359
360 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
361 SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
362 SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
363 SinglePassRunAndCheck<ReduceLoadSize>(test, test, true, false,
364 kDefaultLoadReductionThreshold);
365 }
366
TEST_F(ReduceLoadSizeTest,cbuffer_load_fully_used)367 TEST_F(ReduceLoadSizeTest, cbuffer_load_fully_used) {
368 // The result of the load (%22) is used in an instruction that uses the whole
369 // load and has only 1 in operand. This trigger issue #1559.
370 const std::string test =
371 R"(OpCapability Shader
372 OpMemoryModel Logical GLSL450
373 OpEntryPoint GLCompute %main "main"
374 OpExecutionMode %main LocalSize 1 1 1
375 OpSource HLSL 600
376 OpName %type_gBuffer "type.gBuffer"
377 OpMemberName %type_gBuffer 0 "a"
378 OpName %gBuffer "gBuffer"
379 OpName %S "S"
380 OpMemberName %S 0 "f"
381 OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
382 OpName %gRWSBuffer "gRWSBuffer"
383 OpName %main "main"
384 OpMemberDecorate %type_gBuffer 0 Offset 0
385 OpDecorate %type_gBuffer Block
386 OpMemberDecorate %S 0 Offset 0
387 OpDecorate %_runtimearr_S ArrayStride 4
388 OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
389 OpDecorate %type_RWStructuredBuffer_S BufferBlock
390 OpDecorate %gBuffer DescriptorSet 0
391 OpDecorate %gBuffer Binding 0
392 OpDecorate %gRWSBuffer DescriptorSet 0
393 OpDecorate %gRWSBuffer Binding 1
394 %uint = OpTypeInt 32 0
395 %uint_32 = OpConstant %uint 32
396 %v4uint = OpTypeVector %uint 4
397 %float = OpTypeFloat 32
398 %v4float = OpTypeVector %float 4
399 %type_gBuffer = OpTypeStruct %v4uint
400 %_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer
401 %S = OpTypeStruct %uint
402 %_runtimearr_S = OpTypeRuntimeArray %S
403 %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
404 %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
405 %int = OpTypeInt 32 1
406 %void = OpTypeVoid
407 %15 = OpTypeFunction %void
408 %int_0 = OpConstant %int 0
409 %_ptr_Uniform_v4uint = OpTypePointer Uniform %v4uint
410 %uint_0 = OpConstant %uint 0
411 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
412 %gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform
413 %gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
414 %main = OpFunction %void None %15
415 %20 = OpLabel
416 %21 = OpAccessChain %_ptr_Uniform_v4uint %gBuffer %int_0
417 %22 = OpLoad %v4uint %21
418 %23 = OpCompositeExtract %uint %22 1
419 %24 = OpConvertUToF %v4float %22
420 %25 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0
421 OpStore %25 %23
422 OpReturn
423 OpFunctionEnd
424 )";
425
426 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
427 SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
428 SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
429 SinglePassRunAndCheck<ReduceLoadSize>(test, test, true, false,
430 kDefaultLoadReductionThreshold);
431 }
432
TEST_F(ReduceLoadSizeTest,replace_cbuffer_load_fully_used)433 TEST_F(ReduceLoadSizeTest, replace_cbuffer_load_fully_used) {
434 const std::string test =
435 R"(
436 OpCapability Shader
437 OpCapability SampledBuffer
438 OpMemoryModel Logical GLSL450
439 OpEntryPoint Fragment %main "main" %out_var_SV_Target0
440 OpExecutionMode %main OriginUpperLeft
441 OpSource HLSL 600
442 OpName %type_MaterialInstancing_cbuffer "type.MaterialInstancing_cbuffer"
443 OpMemberName %type_MaterialInstancing_cbuffer 0 "MaterialInstancing_constants"
444 OpName %MaterialInstancing_Constants "MaterialInstancing_Constants"
445 OpMemberName %MaterialInstancing_Constants 0 "offset0"
446 OpMemberName %MaterialInstancing_Constants 1 "params"
447 OpName %InstancingParams_Constants "InstancingParams_Constants"
448 OpMemberName %InstancingParams_Constants 0 "offset1"
449 OpName %MaterialInstancing_cbuffer "MaterialInstancing_cbuffer"
450 OpName %out_var_SV_Target0 "out.var.SV_Target0"
451 OpName %main "main"
452 OpDecorate %out_var_SV_Target0 Location 0
453 OpDecorate %MaterialInstancing_cbuffer DescriptorSet 6
454 OpDecorate %MaterialInstancing_cbuffer Binding 0
455 OpMemberDecorate %InstancingParams_Constants 0 Offset 0
456 OpMemberDecorate %MaterialInstancing_Constants 0 Offset 0
457 OpMemberDecorate %MaterialInstancing_Constants 1 Offset 16
458 OpMemberDecorate %type_MaterialInstancing_cbuffer 0 Offset 0
459 OpDecorate %type_MaterialInstancing_cbuffer Block
460 %int = OpTypeInt 32 1
461 %int_0 = OpConstant %int 0
462 %v4int = OpTypeVector %int 4
463 %InstancingParams_Constants = OpTypeStruct %v4int
464 %MaterialInstancing_Constants = OpTypeStruct %v4int %InstancingParams_Constants
465 %type_MaterialInstancing_cbuffer = OpTypeStruct %MaterialInstancing_Constants
466 %_ptr_Uniform_type_MaterialInstancing_cbuffer = OpTypePointer Uniform %type_MaterialInstancing_cbuffer
467 %_ptr_Output_int = OpTypePointer Output %int
468 %void = OpTypeVoid
469 %60 = OpTypeFunction %void
470 %_ptr_Uniform_MaterialInstancing_Constants = OpTypePointer Uniform %MaterialInstancing_Constants
471 %MaterialInstancing_cbuffer = OpVariable %_ptr_Uniform_type_MaterialInstancing_cbuffer Uniform
472 %out_var_SV_Target0 = OpVariable %_ptr_Output_int Output
473 %main = OpFunction %void None %60
474 %80 = OpLabel
475 %131 = OpAccessChain %_ptr_Uniform_MaterialInstancing_Constants %MaterialInstancing_cbuffer %int_0
476 %132 = OpLoad %MaterialInstancing_Constants %131
477 ; CHECK: [[ac1:%\w+]] = OpAccessChain {{%\w+}} %MaterialInstancing_cbuffer %int_0
478 ; CHECK: [[ac2:%\w+]] = OpAccessChain {{%\w+}} [[ac1]] %uint_0
479 ; CHECK: OpLoad %v4int [[ac2]]
480
481 ; CHECK: [[ac3:%\w+]] = OpAccessChain {{%\w+}} [[ac1]] %uint_1
482 ; CHECK: [[ac4:%\w+]] = OpAccessChain {{%\w+}} [[ac3]] %uint_0
483 ; CHECK: OpLoad %v4int [[ac4]]
484 %134 = OpCompositeExtract %v4int %132 0
485 %135 = OpCompositeExtract %InstancingParams_Constants %132 1
486 %136 = OpCompositeExtract %v4int %135 0
487 %149 = OpCompositeExtract %int %134 0
488 %185 = OpCompositeExtract %int %136 0
489 %156 = OpIAdd %int %149 %185
490 OpStore %out_var_SV_Target0 %156
491 OpReturn
492 OpFunctionEnd
493 )";
494
495 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
496 SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
497 SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
498 SinglePassRunAndMatch<ReduceLoadSize>(test, false, 1.1);
499 }
500
TEST_F(ReduceLoadSizeTest,replace_array_with_spec_constant_size)501 TEST_F(ReduceLoadSizeTest, replace_array_with_spec_constant_size) {
502 const std::string test =
503 R"(
504 OpCapability ClipDistance
505 OpExtension " "
506 OpMemoryModel Logical GLSL450
507 OpEntryPoint Fragment %1 " "
508 OpExecutionMode %1 OriginUpperLeft
509 %void = OpTypeVoid
510 %3 = OpTypeFunction %void
511 %int = OpTypeInt 32 1
512 %uint = OpTypeInt 32 0
513 %6 = OpSpecConstant %uint 538976288
514 %_arr_int_6 = OpTypeArray %int %6
515 %_struct_8 = OpTypeStruct %_arr_int_6
516 %_struct_9 = OpTypeStruct %_struct_8
517 %_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9
518 ; CHECK: [[var:%\w+]] = OpVariable %_ptr_Uniform__struct_9 Uniform
519 %11 = OpVariable %_ptr_Uniform__struct_9 Uniform
520 %int_0 = OpConstant %int 0
521 %_ptr_Uniform__arr_int_6 = OpTypePointer Uniform %_arr_int_6
522 %1 = OpFunction %void None %3
523 %14 = OpLabel
524 ; CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Uniform__arr_int_6 [[var]] %int_0 %int_0
525 ; CHECK: [[new_ac:%\w+]] = OpAccessChain %_ptr_Uniform_int [[ac]] %uint_538976288
526 ; CHECK: [[ld:%\w+]] = OpLoad %int [[new_ac]]
527 ; CHECK: %18 = OpIAdd %int [[ld]] [[ld]]
528 %15 = OpAccessChain %_ptr_Uniform__arr_int_6 %11 %int_0 %int_0
529 %16 = OpLoad %_arr_int_6 %15
530 %17 = OpCompositeExtract %int %16 538976288
531 %18 = OpIAdd %int %17 %17
532 OpUnreachable
533 OpFunctionEnd
534 )";
535
536 SinglePassRunAndMatch<ReduceLoadSize>(test, false,
537 kDefaultLoadReductionThreshold);
538 }
539
540 } // namespace
541 } // namespace opt
542 } // namespace spvtools
543