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 
501 }  // namespace
502 }  // namespace opt
503 }  // namespace spvtools
504