1 // Copyright (c) 2016 Google Inc.
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 <sstream>
16 #include <string>
17 #include <vector>
18
19 #include "test/opt/assembly_builder.h"
20 #include "test/opt/pass_fixture.h"
21 #include "test/opt/pass_utils.h"
22
23 namespace spvtools {
24 namespace opt {
25 namespace {
26
27 using FoldSpecConstantOpAndCompositePassBasicTest = PassTest<::testing::Test>;
28
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, Empty)29 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, Empty) {
30 SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
31 "", "", /* skip_nop = */ true);
32 }
33
34 // A test of the basic functionality of FoldSpecConstantOpAndCompositePass.
35 // A spec constant defined with an integer addition operation should be folded
36 // to a normal constant with fixed value.
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, Basic)37 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, Basic) {
38 AssemblyBuilder builder;
39 builder.AppendTypesConstantsGlobals({
40 // clang-format off
41 "%int = OpTypeInt 32 1",
42 "%frozen_spec_const_int = OpConstant %int 1",
43 "%const_int = OpConstant %int 2",
44 // Folding target:
45 "%spec_add = OpSpecConstantOp %int IAdd %frozen_spec_const_int %const_int",
46 // clang-format on
47 });
48
49 std::vector<const char*> expected = {
50 // clang-format off
51 "OpCapability Shader",
52 "OpCapability Float64",
53 "%1 = OpExtInstImport \"GLSL.std.450\"",
54 "OpMemoryModel Logical GLSL450",
55 "OpEntryPoint Vertex %main \"main\"",
56 "OpName %void \"void\"",
57 "OpName %main_func_type \"main_func_type\"",
58 "OpName %main \"main\"",
59 "OpName %main_func_entry_block \"main_func_entry_block\"",
60 "OpName %int \"int\"",
61 "OpName %frozen_spec_const_int \"frozen_spec_const_int\"",
62 "OpName %const_int \"const_int\"",
63 "OpName %spec_add \"spec_add\"",
64 "%void = OpTypeVoid",
65 "%main_func_type = OpTypeFunction %void",
66 "%int = OpTypeInt 32 1",
67 "%frozen_spec_const_int = OpConstant %int 1",
68 "%const_int = OpConstant %int 2",
69 // The SpecConstantOp IAdd instruction should be replace by OpConstant
70 // instruction:
71 "%spec_add = OpConstant %int 3",
72 "%main = OpFunction %void None %main_func_type",
73 "%main_func_entry_block = OpLabel",
74 "OpReturn",
75 "OpFunctionEnd",
76 // clang-format on
77 };
78 SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
79 builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
80 }
81
82 // A test of skipping folding an instruction when the instruction result type
83 // has decorations.
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, SkipWhenTypeHasDecorations)84 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
85 SkipWhenTypeHasDecorations) {
86 AssemblyBuilder builder;
87 builder
88 .AppendAnnotations({
89 // clang-format off
90 "OpDecorate %int RelaxedPrecision",
91 // clang-format on
92 })
93 .AppendTypesConstantsGlobals({
94 // clang-format off
95 "%int = OpTypeInt 32 1",
96 "%frozen_spec_const_int = OpConstant %int 1",
97 "%const_int = OpConstant %int 2",
98 // The following spec constant should not be folded as the result type
99 // has relaxed precision decoration.
100 "%spec_add = OpSpecConstantOp %int IAdd %frozen_spec_const_int %const_int",
101 // clang-format on
102 });
103
104 SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
105 builder.GetCode(), builder.GetCode(), /* skip_nop = */ true);
106 }
107
108 // Test where OpSpecConstantOp depends on another OpSpecConstantOp with
109 // CompositeExtract
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, StackedCompositeExtract)110 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, StackedCompositeExtract) {
111 AssemblyBuilder builder;
112 builder.AppendTypesConstantsGlobals({
113 // clang-format off
114 "%uint = OpTypeInt 32 0",
115 "%v3uint = OpTypeVector %uint 3",
116 "%uint_2 = OpConstant %uint 2",
117 "%uint_3 = OpConstant %uint 3",
118 // Folding target:
119 "%composite_0 = OpSpecConstantComposite %v3uint %uint_2 %uint_3 %uint_2",
120 "%op_0 = OpSpecConstantOp %uint CompositeExtract %composite_0 0",
121 "%op_1 = OpSpecConstantOp %uint CompositeExtract %composite_0 1",
122 "%op_2 = OpSpecConstantOp %uint IMul %op_0 %op_1",
123 "%composite_1 = OpSpecConstantComposite %v3uint %op_0 %op_1 %op_2",
124 "%op_3 = OpSpecConstantOp %uint CompositeExtract %composite_1 0",
125 "%op_4 = OpSpecConstantOp %uint IMul %op_2 %op_3",
126 // clang-format on
127 });
128
129 std::vector<const char*> expected = {
130 // clang-format off
131 "OpCapability Shader",
132 "OpCapability Float64",
133 "%1 = OpExtInstImport \"GLSL.std.450\"",
134 "OpMemoryModel Logical GLSL450",
135 "OpEntryPoint Vertex %main \"main\"",
136 "OpName %void \"void\"",
137 "OpName %main_func_type \"main_func_type\"",
138 "OpName %main \"main\"",
139 "OpName %main_func_entry_block \"main_func_entry_block\"",
140 "OpName %uint \"uint\"",
141 "OpName %v3uint \"v3uint\"",
142 "OpName %uint_2 \"uint_2\"",
143 "OpName %uint_3 \"uint_3\"",
144 "OpName %composite_0 \"composite_0\"",
145 "OpName %op_0 \"op_0\"",
146 "OpName %op_1 \"op_1\"",
147 "OpName %op_2 \"op_2\"",
148 "OpName %composite_1 \"composite_1\"",
149 "OpName %op_3 \"op_3\"",
150 "OpName %op_4 \"op_4\"",
151 "%void = OpTypeVoid",
152 "%main_func_type = OpTypeFunction %void",
153 "%uint = OpTypeInt 32 0",
154 "%v3uint = OpTypeVector %uint 3",
155 "%uint_2 = OpConstant %uint 2",
156 "%uint_3 = OpConstant %uint 3",
157 "%composite_0 = OpConstantComposite %v3uint %uint_2 %uint_3 %uint_2",
158 "%op_0 = OpConstant %uint 2",
159 "%op_1 = OpConstant %uint 3",
160 "%op_2 = OpConstant %uint 6",
161 "%composite_1 = OpConstantComposite %v3uint %op_0 %op_1 %op_2",
162 "%op_3 = OpConstant %uint 2",
163 "%op_4 = OpConstant %uint 12",
164 "%main = OpFunction %void None %main_func_type",
165 "%main_func_entry_block = OpLabel",
166 "OpReturn",
167 "OpFunctionEnd",
168 // clang-format on
169 };
170 SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
171 builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
172 }
173
174 // Test where OpSpecConstantOp depends on another OpSpecConstantOp with
175 // VectorShuffle
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, StackedVectorShuffle)176 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, StackedVectorShuffle) {
177 AssemblyBuilder builder;
178 builder.AppendTypesConstantsGlobals({
179 // clang-format off
180 "%uint = OpTypeInt 32 0",
181 "%v3uint = OpTypeVector %uint 3",
182 "%uint_1 = OpConstant %uint 1",
183 "%uint_2 = OpConstant %uint 2",
184 "%uint_3 = OpConstant %uint 3",
185 "%uint_4 = OpConstant %uint 4",
186 "%uint_5 = OpConstant %uint 5",
187 "%uint_6 = OpConstant %uint 6",
188 // Folding target:
189 "%composite_0 = OpSpecConstantComposite %v3uint %uint_1 %uint_2 %uint_3",
190 "%composite_1 = OpSpecConstantComposite %v3uint %uint_4 %uint_5 %uint_6",
191 "%vecshuffle = OpSpecConstantOp %v3uint VectorShuffle %composite_0 %composite_1 0 5 3",
192 "%op = OpSpecConstantOp %uint CompositeExtract %vecshuffle 1",
193 // clang-format on
194 });
195
196 std::vector<const char*> expected = {
197 // clang-format off
198 "OpCapability Shader",
199 "OpCapability Float64",
200 "%1 = OpExtInstImport \"GLSL.std.450\"",
201 "OpMemoryModel Logical GLSL450",
202 "OpEntryPoint Vertex %main \"main\"",
203 "OpName %void \"void\"",
204 "OpName %main_func_type \"main_func_type\"",
205 "OpName %main \"main\"",
206 "OpName %main_func_entry_block \"main_func_entry_block\"",
207 "OpName %uint \"uint\"",
208 "OpName %v3uint \"v3uint\"",
209 "OpName %uint_1 \"uint_1\"",
210 "OpName %uint_2 \"uint_2\"",
211 "OpName %uint_3 \"uint_3\"",
212 "OpName %uint_4 \"uint_4\"",
213 "OpName %uint_5 \"uint_5\"",
214 "OpName %uint_6 \"uint_6\"",
215 "OpName %composite_0 \"composite_0\"",
216 "OpName %composite_1 \"composite_1\"",
217 "OpName %vecshuffle \"vecshuffle\"",
218 "OpName %op \"op\"",
219 "%void = OpTypeVoid",
220 "%main_func_type = OpTypeFunction %void",
221 "%uint = OpTypeInt 32 0",
222 "%v3uint = OpTypeVector %uint 3",
223 "%uint_1 = OpConstant %uint 1",
224 "%uint_2 = OpConstant %uint 2",
225 "%uint_3 = OpConstant %uint 3",
226 "%uint_4 = OpConstant %uint 4",
227 "%uint_5 = OpConstant %uint 5",
228 "%uint_6 = OpConstant %uint 6",
229 "%composite_0 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3",
230 "%composite_1 = OpConstantComposite %v3uint %uint_4 %uint_5 %uint_6",
231 "%vecshuffle = OpConstantComposite %v3uint %uint_1 %uint_6 %uint_4",
232 "%op = OpConstant %uint 6",
233 "%main = OpFunction %void None %main_func_type",
234 "%main_func_entry_block = OpLabel",
235 "OpReturn",
236 "OpFunctionEnd",
237 // clang-format on
238 };
239 SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
240 builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
241 }
242
243 // Test CompositeExtract with matrix
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeExtractMaxtrix)244 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeExtractMaxtrix) {
245 AssemblyBuilder builder;
246 builder.AppendTypesConstantsGlobals({
247 // clang-format off
248 "%uint = OpTypeInt 32 0",
249 "%v3uint = OpTypeVector %uint 3",
250 "%mat3x3 = OpTypeMatrix %v3uint 3",
251 "%uint_1 = OpConstant %uint 1",
252 "%uint_2 = OpConstant %uint 2",
253 "%uint_3 = OpConstant %uint 3",
254 // Folding target:
255 "%a = OpSpecConstantComposite %v3uint %uint_1 %uint_1 %uint_1",
256 "%b = OpSpecConstantComposite %v3uint %uint_1 %uint_1 %uint_3",
257 "%c = OpSpecConstantComposite %v3uint %uint_1 %uint_2 %uint_1",
258 "%op = OpSpecConstantComposite %mat3x3 %a %b %c",
259 "%x = OpSpecConstantOp %uint CompositeExtract %op 2 1",
260 "%y = OpSpecConstantOp %uint CompositeExtract %op 1 2",
261 // clang-format on
262 });
263
264 std::vector<const char*> expected = {
265 // clang-format off
266 "OpCapability Shader",
267 "OpCapability Float64",
268 "%1 = OpExtInstImport \"GLSL.std.450\"",
269 "OpMemoryModel Logical GLSL450",
270 "OpEntryPoint Vertex %main \"main\"",
271 "OpName %void \"void\"",
272 "OpName %main_func_type \"main_func_type\"",
273 "OpName %main \"main\"",
274 "OpName %main_func_entry_block \"main_func_entry_block\"",
275 "OpName %uint \"uint\"",
276 "OpName %v3uint \"v3uint\"",
277 "OpName %mat3x3 \"mat3x3\"",
278 "OpName %uint_1 \"uint_1\"",
279 "OpName %uint_2 \"uint_2\"",
280 "OpName %uint_3 \"uint_3\"",
281 "OpName %a \"a\"",
282 "OpName %b \"b\"",
283 "OpName %c \"c\"",
284 "OpName %op \"op\"",
285 "OpName %x \"x\"",
286 "OpName %y \"y\"",
287 "%void = OpTypeVoid",
288 "%main_func_type = OpTypeFunction %void",
289 "%uint = OpTypeInt 32 0",
290 "%v3uint = OpTypeVector %uint 3",
291 "%mat3x3 = OpTypeMatrix %v3uint 3",
292 "%uint_1 = OpConstant %uint 1",
293 "%uint_2 = OpConstant %uint 2",
294 "%uint_3 = OpConstant %uint 3",
295 "%a = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1",
296 "%b = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_3",
297 "%c = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_1",
298 "%op = OpConstantComposite %mat3x3 %a %b %c",
299 "%x = OpConstant %uint 2",
300 "%y = OpConstant %uint 3",
301 "%main = OpFunction %void None %main_func_type",
302 "%main_func_entry_block = OpLabel",
303 "OpReturn",
304 "OpFunctionEnd",
305 // clang-format on
306 };
307 SinglePassRunAndCheck<FoldSpecConstantOpAndCompositePass>(
308 builder.GetCode(), JoinAllInsts(expected), /* skip_nop = */ true);
309 }
310
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVector)311 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVector) {
312 const std::string test =
313 R"(
314 OpCapability Shader
315 OpMemoryModel Logical GLSL450
316 OpEntryPoint GLCompute %1 "main"
317 OpExecutionMode %1 LocalSize 1 1 1
318 %void = OpTypeVoid
319 %3 = OpTypeFunction %void
320 %uint = OpTypeInt 32 0
321 %v3uint = OpTypeVector %uint 3
322 %uint_2 = OpConstant %uint 2
323 %uint_3 = OpConstant %uint 3
324 %8 = OpConstantNull %uint
325 %9 = OpSpecConstantComposite %v3uint %uint_2 %uint_2 %uint_2
326 ; CHECK: %15 = OpConstantComposite %v3uint %uint_3 %uint_2 %uint_2
327 ; CHECK: %uint_3_0 = OpConstant %uint 3
328 ; CHECK: %17 = OpConstantComposite %v3uint %8 %uint_2 %uint_2
329 ; CHECK: %18 = OpConstantNull %uint
330 %10 = OpSpecConstantOp %v3uint CompositeInsert %uint_3 %9 0
331 %11 = OpSpecConstantOp %uint CompositeExtract %10 0
332 %12 = OpSpecConstantOp %v3uint CompositeInsert %8 %9 0
333 %13 = OpSpecConstantOp %uint CompositeExtract %12 0
334 %1 = OpFunction %void None %3
335 %14 = OpLabel
336 OpReturn
337 OpFunctionEnd
338 )";
339
340 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
341 }
342
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVectorIntoMatrix)343 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
344 CompositeInsertVectorIntoMatrix) {
345 const std::string test =
346 R"(
347 OpCapability Shader
348 OpMemoryModel Logical GLSL450
349 OpEntryPoint GLCompute %1 "main"
350 OpExecutionMode %1 LocalSize 1 1 1
351 %void = OpTypeVoid
352 %3 = OpTypeFunction %void
353 %float = OpTypeFloat 32
354 %v2float = OpTypeVector %float 2
355 %mat2v2float = OpTypeMatrix %v2float 2
356 %float_0 = OpConstant %float 0
357 %float_1 = OpConstant %float 1
358 %float_2 = OpConstant %float 2
359 %v2float_01 = OpConstantComposite %v2float %float_0 %float_1
360 %v2float_12 = OpConstantComposite %v2float %float_1 %float_2
361
362 ; CHECK: %10 = OpConstantComposite %v2float %float_0 %float_1
363 ; CHECK: %11 = OpConstantComposite %v2float %float_1 %float_2
364 ; CHECK: %12 = OpConstantComposite %mat2v2float %11 %11
365 %mat2v2float_1212 = OpConstantComposite %mat2v2float %v2float_12 %v2float_12
366
367 ; CHECK: %15 = OpConstantComposite %mat2v2float %10 %11
368 %spec_0 = OpSpecConstantOp %mat2v2float CompositeInsert %v2float_01 %mat2v2float_1212 0
369 %1 = OpFunction %void None %3
370 %label = OpLabel
371 OpReturn
372 OpFunctionEnd
373 )";
374
375 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
376 }
377
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertMatrix)378 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertMatrix) {
379 const std::string test =
380 R"(
381 OpCapability Shader
382 OpMemoryModel Logical GLSL450
383 OpEntryPoint GLCompute %1 "main"
384 OpExecutionMode %1 LocalSize 1 1 1
385 %void = OpTypeVoid
386 %3 = OpTypeFunction %void
387 %float = OpTypeFloat 32
388 %v3float = OpTypeVector %float 3
389 %mat3v3float = OpTypeMatrix %v3float 3
390 %float_1 = OpConstant %float 1
391 %float_2 = OpConstant %float 2
392 %9 = OpSpecConstantComposite %v3float %float_1 %float_1 %float_1
393 %10 = OpSpecConstantComposite %v3float %float_1 %float_1 %float_1
394 %11 = OpSpecConstantComposite %v3float %float_1 %float_2 %float_1
395 %12 = OpSpecConstantComposite %mat3v3float %9 %10 %11
396 ; CHECK: %float_2_0 = OpConstant %float 2
397 ; CHECK: %18 = OpConstantComposite %v3float %float_1 %float_1 %float_2
398 ; CHECK: %19 = OpConstantComposite %mat3v3float %9 %18 %11
399 ; CHECK: %float_2_1 = OpConstant %float 2
400 %13 = OpSpecConstantOp %float CompositeExtract %12 2 1
401 %14 = OpSpecConstantOp %mat3v3float CompositeInsert %13 %12 1 2
402 %15 = OpSpecConstantOp %float CompositeExtract %14 1 2
403 %1 = OpFunction %void None %3
404 %16 = OpLabel
405 OpReturn
406 OpFunctionEnd
407 )";
408
409 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
410 }
411
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertFloatNull)412 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertFloatNull) {
413 const std::string test =
414 R"(
415 OpCapability Shader
416 OpMemoryModel Logical GLSL450
417 OpEntryPoint GLCompute %1 "main"
418 OpExecutionMode %1 LocalSize 1 1 1
419 %void = OpTypeVoid
420 %3 = OpTypeFunction %void
421 %float = OpTypeFloat 32
422 %v3float = OpTypeVector %float 3
423 %float_1 = OpConstant %float 1
424
425 ; CHECK: %7 = OpConstantNull %float
426 ; CHECK: %8 = OpConstantComposite %v3float %7 %7 %7
427 ; CHECK: %12 = OpConstantComposite %v3float %7 %7 %float_1
428 %null = OpConstantNull %float
429 %spec_0 = OpConstantComposite %v3float %null %null %null
430 %spec_1 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_0 2
431
432 ; CHECK: %float_1_0 = OpConstant %float 1
433 %spec_2 = OpSpecConstantOp %float CompositeExtract %spec_1 2
434 %1 = OpFunction %void None %3
435 %label = OpLabel
436 OpReturn
437 OpFunctionEnd
438 )";
439
440 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
441 }
442
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertFloatSetNull)443 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
444 CompositeInsertFloatSetNull) {
445 const std::string test =
446 R"(
447 OpCapability Shader
448 OpMemoryModel Logical GLSL450
449 OpEntryPoint GLCompute %1 "main"
450 OpExecutionMode %1 LocalSize 1 1 1
451 %void = OpTypeVoid
452 %3 = OpTypeFunction %void
453 %float = OpTypeFloat 32
454 %v3float = OpTypeVector %float 3
455 %float_1 = OpConstant %float 1
456
457 ; CHECK: %7 = OpConstantNull %float
458 ; CHECK: %8 = OpConstantComposite %v3float %7 %7 %float_1
459 ; CHECK: %12 = OpConstantComposite %v3float %7 %7 %7
460 %null = OpConstantNull %float
461 %spec_0 = OpConstantComposite %v3float %null %null %float_1
462 %spec_1 = OpSpecConstantOp %v3float CompositeInsert %null %spec_0 2
463
464 ; CHECK: %13 = OpConstantNull %float
465 %spec_2 = OpSpecConstantOp %float CompositeExtract %spec_1 2
466 %1 = OpFunction %void None %3
467 %label = OpLabel
468 OpReturn
469 OpFunctionEnd
470 )";
471
472 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
473 }
474
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVectorNull)475 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVectorNull) {
476 const std::string test =
477 R"(
478 OpCapability Shader
479 OpMemoryModel Logical GLSL450
480 OpEntryPoint GLCompute %1 "main"
481 OpExecutionMode %1 LocalSize 1 1 1
482 %void = OpTypeVoid
483 %3 = OpTypeFunction %void
484 %float = OpTypeFloat 32
485 %v3float = OpTypeVector %float 3
486 %float_1 = OpConstant %float 1
487 %null = OpConstantNull %v3float
488
489 ; CHECK: %11 = OpConstantNull %float
490 ; CHECK: %12 = OpConstantComposite %v3float %11 %11 %float_1
491 %spec_0 = OpSpecConstantOp %v3float CompositeInsert %float_1 %null 2
492
493
494 ; CHECK: %float_1_0 = OpConstant %float 1
495 %spec_1 = OpSpecConstantOp %float CompositeExtract %spec_0 2
496 %1 = OpFunction %void None %3
497 %label = OpLabel
498 OpReturn
499 OpFunctionEnd
500 )";
501
502 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
503 }
504
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertNullVectorIntoMatrix)505 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
506 CompositeInsertNullVectorIntoMatrix) {
507 const std::string test =
508 R"(
509 OpCapability Shader
510 OpMemoryModel Logical GLSL450
511 OpEntryPoint GLCompute %1 "main"
512 OpExecutionMode %1 LocalSize 1 1 1
513 %void = OpTypeVoid
514 %3 = OpTypeFunction %void
515 %float = OpTypeFloat 32
516 %v2float = OpTypeVector %float 2
517 %mat2v2float = OpTypeMatrix %v2float 2
518 %null = OpConstantNull %mat2v2float
519 %float_1 = OpConstant %float 1
520 %float_2 = OpConstant %float 2
521 %v2float_12 = OpConstantComposite %v2float %float_1 %float_2
522
523 ; CHECK: %13 = OpConstantNull %v2float
524 ; CHECK: %14 = OpConstantComposite %mat2v2float %10 %13
525 %spec_0 = OpSpecConstantOp %mat2v2float CompositeInsert %v2float_12 %null 0
526 %1 = OpFunction %void None %3
527 %label = OpLabel
528 OpReturn
529 OpFunctionEnd
530 )";
531
532 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
533 }
534
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVectorKeepNull)535 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
536 CompositeInsertVectorKeepNull) {
537 const std::string test =
538 R"(
539 OpCapability Shader
540 OpMemoryModel Logical GLSL450
541 OpEntryPoint GLCompute %1 "main"
542 OpExecutionMode %1 LocalSize 1 1 1
543 %void = OpTypeVoid
544 %3 = OpTypeFunction %void
545 %float = OpTypeFloat 32
546 %v3float = OpTypeVector %float 3
547 %float_0 = OpConstant %float 0
548 %null_float = OpConstantNull %float
549 %null_vec = OpConstantNull %v3float
550
551 ; CHECK: %15 = OpConstantComposite %v3float %7 %7 %float_0
552 %spec_0 = OpSpecConstantOp %v3float CompositeInsert %float_0 %null_vec 2
553
554 ; CHECK: %float_0_0 = OpConstant %float 0
555 %spec_1 = OpSpecConstantOp %float CompositeExtract %spec_0 2
556
557 ; CHECK: %17 = OpConstantComposite %v3float %7 %7 %7
558 %spec_2 = OpSpecConstantOp %v3float CompositeInsert %null_float %null_vec 2
559
560 ; CHECK: %18 = OpConstantNull %float
561 %spec_3 = OpSpecConstantOp %float CompositeExtract %spec_2 2
562 %1 = OpFunction %void None %3
563 %label = OpLabel
564 %add = OpFAdd %float %spec_3 %spec_3
565 OpReturn
566 OpFunctionEnd
567 )";
568
569 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
570 }
571
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVectorChainNull)572 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
573 CompositeInsertVectorChainNull) {
574 const std::string test =
575 R"(
576 OpCapability Shader
577 OpMemoryModel Logical GLSL450
578 OpEntryPoint GLCompute %1 "main"
579 OpExecutionMode %1 LocalSize 1 1 1
580 %void = OpTypeVoid
581 %3 = OpTypeFunction %void
582 %float = OpTypeFloat 32
583 %v3float = OpTypeVector %float 3
584 %float_1 = OpConstant %float 1
585 %null = OpConstantNull %v3float
586
587 ; CHECK: %15 = OpConstantNull %float
588 ; CHECK: %16 = OpConstantComposite %v3float %15 %15 %float_1
589 ; CHECK: %17 = OpConstantComposite %v3float %15 %float_1 %float_1
590 ; CHECK: %18 = OpConstantComposite %v3float %float_1 %float_1 %float_1
591 %spec_0 = OpSpecConstantOp %v3float CompositeInsert %float_1 %null 2
592 %spec_1 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_0 1
593 %spec_2 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_1 0
594
595 ; CHECK: %float_1_0 = OpConstant %float 1
596 ; CHECK: %float_1_1 = OpConstant %float 1
597 ; CHECK: %float_1_2 = OpConstant %float 1
598 %spec_3 = OpSpecConstantOp %float CompositeExtract %spec_2 0
599 %spec_4 = OpSpecConstantOp %float CompositeExtract %spec_2 1
600 %spec_5 = OpSpecConstantOp %float CompositeExtract %spec_2 2
601 %1 = OpFunction %void None %3
602 %label = OpLabel
603 OpReturn
604 OpFunctionEnd
605 )";
606
607 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
608 }
609
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertVectorChainReset)610 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest,
611 CompositeInsertVectorChainReset) {
612 const std::string test =
613 R"(
614 OpCapability Shader
615 OpMemoryModel Logical GLSL450
616 OpEntryPoint GLCompute %1 "main"
617 OpExecutionMode %1 LocalSize 1 1 1
618 %void = OpTypeVoid
619 %3 = OpTypeFunction %void
620 %float = OpTypeFloat 32
621 %v3float = OpTypeVector %float 3
622 %float_1 = OpConstant %float 1
623 %null = OpConstantNull %float
624 ; CHECK: %8 = OpConstantComposite %v3float %7 %7 %float_1
625 %spec_0 = OpConstantComposite %v3float %null %null %float_1
626
627 ; set to null
628 ; CHECK: %13 = OpConstantComposite %v3float %7 %7 %7
629 %spec_1 = OpSpecConstantOp %v3float CompositeInsert %null %spec_0 2
630
631 ; set to back to original value
632 ; CHECK: %14 = OpConstantComposite %v3float %7 %7 %float_1
633 %spec_2 = OpSpecConstantOp %v3float CompositeInsert %float_1 %spec_1 2
634
635 ; CHECK: %float_1_0 = OpConstant %float 1
636 %spec_3 = OpSpecConstantOp %float CompositeExtract %spec_2 2
637 %1 = OpFunction %void None %3
638 %label = OpLabel
639 OpReturn
640 OpFunctionEnd
641 )";
642
643 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
644 }
645
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertMatrixNull)646 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, CompositeInsertMatrixNull) {
647 const std::string test =
648 R"(
649 OpCapability Shader
650 OpMemoryModel Logical GLSL450
651 OpEntryPoint GLCompute %main "main"
652 OpExecutionMode %main LocalSize 1 1 1
653 %void = OpTypeVoid
654 %func = OpTypeFunction %void
655 %float = OpTypeFloat 32
656 %int = OpTypeInt 32 0
657 %v2float = OpTypeVector %float 2
658 %mat2v2float = OpTypeMatrix %v2float 2
659 %null = OpConstantNull %mat2v2float
660 %float_1 = OpConstant %float 1
661 ; CHECK: %13 = OpConstantNull %v2float
662 ; CHECK: %14 = OpConstantNull %float
663 ; CHECK: %15 = OpConstantComposite %v2float %float_1 %14
664 ; CHECK: %16 = OpConstantComposite %mat2v2float %13 %15
665 %spec = OpSpecConstantOp %mat2v2float CompositeInsert %float_1 %null 1 0
666 ; extra type def to make sure new type def are not just thrown at end
667 %v2int = OpTypeVector %int 2
668 %main = OpFunction %void None %func
669 %label = OpLabel
670 OpReturn
671 OpFunctionEnd
672 )";
673
674 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
675 }
676
677 // Silently ignore spec constants that cannot be folded
TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, UnfoldableOp)678 TEST_F(FoldSpecConstantOpAndCompositePassBasicTest, UnfoldableOp) {
679 const std::string test = R"(
680 OpCapability Shader
681 OpCapability SignedZeroInfNanPreserve
682 OpExtension "SPV_KHR_float_controls"
683 OpMemoryModel Logical GLSL450
684 OpEntryPoint Vertex %main "main"
685 OpSource GLSL 450
686 OpDecorate %v SpecId 1
687 %void = OpTypeVoid
688 %3 = OpTypeFunction %void
689 %float = OpTypeFloat 32
690 %v = OpConstant %float 0x1p-1
691 %c = OpSpecConstantOp %float QuantizeToF16 %v
692 ;CHECK: {{%\w+}} = OpSpecConstantOp {{%\w+}} QuantizeToF16 {{%\w+}}
693 %main = OpFunction %void None %3
694 %5 = OpLabel
695 OpReturn
696 OpFunctionEnd
697 )";
698
699 SinglePassRunAndMatch<FoldSpecConstantOpAndCompositePass>(test, false);
700 }
701
702 // All types and some common constants that are potentially required in
703 // FoldSpecConstantOpAndCompositeTest.
CommonTypesAndConstants()704 std::vector<std::string> CommonTypesAndConstants() {
705 return std::vector<std::string>{
706 // clang-format off
707 // scalar types
708 "%bool = OpTypeBool",
709 "%ushort = OpTypeInt 16 0",
710 "%short = OpTypeInt 16 1",
711 "%uint = OpTypeInt 32 0",
712 "%int = OpTypeInt 32 1",
713 "%ulong = OpTypeInt 64 0",
714 "%long = OpTypeInt 64 1",
715 "%float = OpTypeFloat 32",
716 "%double = OpTypeFloat 64",
717 // vector types
718 "%v2bool = OpTypeVector %bool 2",
719 "%v2uint = OpTypeVector %uint 2",
720 "%v2int = OpTypeVector %int 2",
721 "%v3int = OpTypeVector %int 3",
722 "%v4int = OpTypeVector %int 4",
723 "%v2long = OpTypeVector %long 2",
724 "%v2ulong = OpTypeVector %ulong 2",
725 "%v2float = OpTypeVector %float 2",
726 "%v2double = OpTypeVector %double 2",
727 // variable pointer types
728 "%_pf_bool = OpTypePointer Function %bool",
729 "%_pf_uint = OpTypePointer Function %uint",
730 "%_pf_int = OpTypePointer Function %int",
731 "%_pf_float = OpTypePointer Function %float",
732 "%_pf_double = OpTypePointer Function %double",
733 "%_pf_v2int = OpTypePointer Function %v2int",
734 "%_pf_v2float = OpTypePointer Function %v2float",
735 "%_pf_v2double = OpTypePointer Function %v2double",
736 // struct types
737 "%inner_struct = OpTypeStruct %bool %int %float",
738 "%outer_struct = OpTypeStruct %inner_struct %int",
739 "%flat_struct = OpTypeStruct %bool %int %float",
740
741 // common constants
742 // scalar constants:
743 "%bool_true = OpConstantTrue %bool",
744 "%bool_false = OpConstantFalse %bool",
745 "%bool_null = OpConstantNull %bool",
746 "%signed_zero = OpConstant %int 0",
747 "%unsigned_zero = OpConstant %uint 0",
748 "%long_zero = OpConstant %long 0",
749 "%ulong_zero = OpConstant %ulong 0",
750 "%signed_one = OpConstant %int 1",
751 "%unsigned_one = OpConstant %uint 1",
752 "%signed_two = OpConstant %int 2",
753 "%unsigned_two = OpConstant %uint 2",
754 "%signed_three = OpConstant %int 3",
755 "%unsigned_three = OpConstant %uint 3",
756 "%signed_null = OpConstantNull %int",
757 "%unsigned_null = OpConstantNull %uint",
758 "%signed_minus_one = OpConstant %int -1",
759 // vector constants:
760 "%bool_true_vec = OpConstantComposite %v2bool %bool_true %bool_true",
761 "%bool_false_vec = OpConstantComposite %v2bool %bool_false %bool_false",
762 "%bool_null_vec = OpConstantNull %v2bool",
763 "%signed_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
764 "%unsigned_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
765 "%signed_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
766 "%unsigned_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
767 "%signed_two_vec = OpConstantComposite %v2int %signed_two %signed_two",
768 "%unsigned_two_vec = OpConstantComposite %v2uint %unsigned_two %unsigned_two",
769 "%signed_three_vec = OpConstantComposite %v2int %signed_three %signed_three",
770 "%unsigned_three_vec = OpConstantComposite %v2uint %unsigned_three %unsigned_three",
771 "%signed_null_vec = OpConstantNull %v2int",
772 "%unsigned_null_vec = OpConstantNull %v2uint",
773 "%signed_minus_one_vec = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
774 "%v4int_0_1_2_3 = OpConstantComposite %v4int %signed_zero %signed_one %signed_two %signed_three",
775 // clang-format on
776 };
777 }
778
779 // A helper function to strip OpName instructions from the given string of
780 // disassembly code. Returns the string with all OpName instruction stripped.
StripOpNameInstructions(const std::string& str)781 std::string StripOpNameInstructions(const std::string& str) {
782 std::stringstream ss(str);
783 std::ostringstream oss;
784 std::string inst_str;
785 while (std::getline(ss, inst_str, '\n')) {
786 if (inst_str.find("OpName %") == std::string::npos) {
787 oss << inst_str << '\n';
788 }
789 }
790 return oss.str();
791 }
792
793 struct FoldSpecConstantOpAndCompositePassTestCase {
794 // Original constants with unfolded spec constants.
795 std::vector<std::string> original;
796 // Expected constant after folding.
797 std::vector<std::string> expected;
798 };
799
800 using FoldSpecConstantOpAndCompositePassTest = PassTest<
801 ::testing::TestWithParam<FoldSpecConstantOpAndCompositePassTestCase>>;
802
TEST_P(FoldSpecConstantOpAndCompositePassTest, ParamTestCase)803 TEST_P(FoldSpecConstantOpAndCompositePassTest, ParamTestCase) {
804 AssemblyBuilder test_code_builder, expected_code_builder;
805 const auto& tc = GetParam();
806 test_code_builder.AppendTypesConstantsGlobals(CommonTypesAndConstants());
807 test_code_builder.AppendTypesConstantsGlobals(tc.original);
808 expected_code_builder.AppendTypesConstantsGlobals(CommonTypesAndConstants());
809 expected_code_builder.AppendTypesConstantsGlobals(tc.expected);
810 const std::string original = test_code_builder.GetCode();
811 const std::string expected = expected_code_builder.GetCode();
812
813 // Run the optimization and get the result code in disassembly.
814 std::string optimized;
815 auto status = Pass::Status::SuccessWithoutChange;
816 std::tie(optimized, status) =
817 SinglePassRunAndDisassemble<FoldSpecConstantOpAndCompositePass>(
818 original, /* skip_nop = */ true, /* do_validation = */ false);
819
820 // Check the optimized code, but ignore the OpName instructions.
821 EXPECT_NE(Pass::Status::Failure, status);
822 EXPECT_EQ(
823 StripOpNameInstructions(expected) == StripOpNameInstructions(original),
824 status == Pass::Status::SuccessWithoutChange);
825 EXPECT_EQ(StripOpNameInstructions(expected),
826 StripOpNameInstructions(optimized));
827 }
828
829 // Tests that OpSpecConstantComposite opcodes are replace with
830 // OpConstantComposite correctly.
831 INSTANTIATE_TEST_SUITE_P(
832 Composite, FoldSpecConstantOpAndCompositePassTest,
833 ::testing::ValuesIn(std::vector<
834 FoldSpecConstantOpAndCompositePassTestCase>({
835 // clang-format off
836 // normal vector
837 {
838 // original
839 {
840 "%spec_v2bool = OpSpecConstantComposite %v2bool %bool_true %bool_false",
841 "%spec_v2uint = OpSpecConstantComposite %v2uint %unsigned_one %unsigned_one",
842 "%spec_v2int_a = OpSpecConstantComposite %v2int %signed_one %signed_two",
843 // Spec constants whose value can not be fully resolved should
844 // not be processed.
845 "%spec_int = OpSpecConstant %int 99",
846 "%spec_v2int_b = OpSpecConstantComposite %v2int %signed_one %spec_int",
847 },
848 // expected
849 {
850 "%spec_v2bool = OpConstantComposite %v2bool %bool_true %bool_false",
851 "%spec_v2uint = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
852 "%spec_v2int_a = OpConstantComposite %v2int %signed_one %signed_two",
853 "%spec_int = OpSpecConstant %int 99",
854 "%spec_v2int_b = OpSpecConstantComposite %v2int %signed_one %spec_int",
855 },
856 },
857 // vector with null constants
858 {
859 // original
860 {
861 "%null_bool = OpConstantNull %bool",
862 "%null_int = OpConstantNull %int",
863 "%spec_v2bool = OpSpecConstantComposite %v2bool %null_bool %null_bool",
864 "%spec_v3int = OpSpecConstantComposite %v3int %null_int %null_int %null_int",
865 "%spec_v4int = OpSpecConstantComposite %v4int %null_int %null_int %null_int %null_int",
866 },
867 // expected
868 {
869 "%null_bool = OpConstantNull %bool",
870 "%null_int = OpConstantNull %int",
871 "%spec_v2bool = OpConstantComposite %v2bool %null_bool %null_bool",
872 "%spec_v3int = OpConstantComposite %v3int %null_int %null_int %null_int",
873 "%spec_v4int = OpConstantComposite %v4int %null_int %null_int %null_int %null_int",
874 },
875 },
876 // flat struct
877 {
878 // original
879 {
880 "%float_1 = OpConstant %float 1",
881 "%flat_1 = OpSpecConstantComposite %flat_struct %bool_true %signed_null %float_1",
882 // following struct should not be folded as the value of
883 // %spec_float is not determined.
884 "%spec_float = OpSpecConstant %float 1",
885 "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_one %spec_float",
886 },
887 // expected
888 {
889 "%float_1 = OpConstant %float 1",
890 "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
891 "%spec_float = OpSpecConstant %float 1",
892 "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_one %spec_float",
893 }
894 },
895 // nested struct
896 {
897 // original
898 {
899 "%float_1 = OpConstant %float 1",
900 "%inner_1 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %float_1",
901 "%outer_1 = OpSpecConstantComposite %outer_struct %inner_1 %signed_one",
902 // following structs should not be folded as the value of
903 // %spec_float is not determined.
904 "%spec_float = OpSpecConstant %float 1",
905 "%inner_2 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
906 "%outer_2 = OpSpecConstantComposite %outer_struct %inner_2 %signed_one",
907 },
908 // expected
909 {
910 "%float_1 = OpConstant %float 1",
911 "%inner_1 = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
912 "%outer_1 = OpConstantComposite %outer_struct %inner_1 %signed_one",
913 "%spec_float = OpSpecConstant %float 1",
914 "%inner_2 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
915 "%outer_2 = OpSpecConstantComposite %outer_struct %inner_2 %signed_one",
916 }
917 },
918 // composite constants touched by OpUndef should be skipped
919 {
920 // original
921 {
922 "%undef = OpUndef %float",
923 "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
924 "%outer = OpSpecConstantComposite %outer_struct %inner %signed_one",
925 },
926 // expected
927 {
928 "%undef = OpUndef %float",
929 "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
930 "%outer = OpSpecConstantComposite %outer_struct %inner %signed_one",
931 },
932 },
933 // Fold an QuantizetoF16 instruction
934 {
935 // original
936 {
937 "%float_1 = OpConstant %float 1",
938 "%quant_float = OpSpecConstantOp %float QuantizeToF16 %float_1",
939 },
940 // expected
941 {
942 "%float_1 = OpConstant %float 1",
943 "%quant_float = OpConstant %float 1",
944 },
945 }
946 // clang-format on
947 })));
948
949 // Tests for operations that resulting in different types.
950 INSTANTIATE_TEST_SUITE_P(
951 Cast, FoldSpecConstantOpAndCompositePassTest,
952 ::testing::ValuesIn(std::vector<
953 FoldSpecConstantOpAndCompositePassTestCase>({
954 // clang-format off
955 // int -> bool scalar
956 {
957 // original
958 {
959 "%spec_bool_t = OpSpecConstantOp %bool INotEqual %signed_three %signed_zero",
960 "%spec_bool_f = OpSpecConstantOp %bool INotEqual %signed_zero %signed_zero",
961 "%spec_bool_from_null = OpSpecConstantOp %bool INotEqual %signed_null %signed_zero",
962 },
963 // expected
964 {
965 "%spec_bool_t = OpConstantTrue %bool",
966 "%spec_bool_f = OpConstantFalse %bool",
967 "%spec_bool_from_null = OpConstantFalse %bool",
968 },
969 },
970
971 // uint -> bool scalar
972 {
973 // original
974 {
975 "%spec_bool_t = OpSpecConstantOp %bool INotEqual %unsigned_three %unsigned_zero",
976 "%spec_bool_f = OpSpecConstantOp %bool INotEqual %unsigned_zero %unsigned_zero",
977 "%spec_bool_from_null = OpSpecConstantOp %bool INotEqual %unsigned_null %unsigned_zero",
978 },
979 // expected
980 {
981 "%spec_bool_t = OpConstantTrue %bool",
982 "%spec_bool_f = OpConstantFalse %bool",
983 "%spec_bool_from_null = OpConstantFalse %bool",
984 },
985 },
986
987 // bool -> int scalar
988 {
989 // original
990 {
991 "%spec_int_one = OpSpecConstantOp %int Select %bool_true %signed_one %signed_zero",
992 "%spec_int_zero = OpSpecConstantOp %int Select %bool_false %signed_one %signed_zero",
993 "%spec_int_from_null = OpSpecConstantOp %int Select %bool_null %signed_one %signed_zero",
994 },
995 // expected
996 {
997 "%spec_int_one = OpConstant %int 1",
998 "%spec_int_zero = OpConstant %int 0",
999 "%spec_int_from_null = OpConstant %int 0",
1000 },
1001 },
1002
1003 // uint -> int scalar
1004 {
1005 // original
1006 {
1007 "%spec_int_one = OpSpecConstantOp %int IAdd %unsigned_one %signed_zero",
1008 "%spec_int_zero = OpSpecConstantOp %int IAdd %unsigned_zero %signed_zero",
1009 "%spec_int_from_null = OpSpecConstantOp %int IAdd %unsigned_null %unsigned_zero",
1010 },
1011 // expected
1012 {
1013 "%spec_int_one = OpConstant %int 1",
1014 "%spec_int_zero = OpConstant %int 0",
1015 "%spec_int_from_null = OpConstant %int 0",
1016 },
1017 },
1018
1019 // bool -> uint scalar
1020 {
1021 // original
1022 {
1023 "%spec_uint_one = OpSpecConstantOp %uint Select %bool_true %unsigned_one %unsigned_zero",
1024 "%spec_uint_zero = OpSpecConstantOp %uint Select %bool_false %unsigned_one %unsigned_zero",
1025 "%spec_uint_from_null = OpSpecConstantOp %uint Select %bool_null %unsigned_one %unsigned_zero",
1026 },
1027 // expected
1028 {
1029 "%spec_uint_one = OpConstant %uint 1",
1030 "%spec_uint_zero = OpConstant %uint 0",
1031 "%spec_uint_from_null = OpConstant %uint 0",
1032 },
1033 },
1034
1035 // int -> uint scalar
1036 {
1037 // original
1038 {
1039 "%spec_uint_one = OpSpecConstantOp %uint IAdd %signed_one %unsigned_zero",
1040 "%spec_uint_zero = OpSpecConstantOp %uint IAdd %signed_zero %unsigned_zero",
1041 "%spec_uint_from_null = OpSpecConstantOp %uint IAdd %signed_null %unsigned_zero",
1042 },
1043 // expected
1044 {
1045 "%spec_uint_one = OpConstant %uint 1",
1046 "%spec_uint_zero = OpConstant %uint 0",
1047 "%spec_uint_from_null = OpConstant %uint 0",
1048 },
1049 },
1050
1051 // int -> bool vector
1052 {
1053 // original
1054 {
1055 "%spec_bool_t_vec = OpSpecConstantOp %v2bool INotEqual %signed_three_vec %signed_zero_vec",
1056 "%spec_bool_f_vec = OpSpecConstantOp %v2bool INotEqual %signed_zero_vec %signed_zero_vec",
1057 "%spec_bool_from_null = OpSpecConstantOp %v2bool INotEqual %signed_null_vec %signed_zero_vec",
1058 },
1059 // expected
1060 {
1061 "%true = OpConstantTrue %bool",
1062 "%true_0 = OpConstantTrue %bool",
1063 "%spec_bool_t_vec = OpConstantComposite %v2bool %bool_true %bool_true",
1064 "%false = OpConstantFalse %bool",
1065 "%false_0 = OpConstantFalse %bool",
1066 "%spec_bool_f_vec = OpConstantComposite %v2bool %bool_false %bool_false",
1067 "%false_1 = OpConstantFalse %bool",
1068 "%false_2 = OpConstantFalse %bool",
1069 "%spec_bool_from_null = OpConstantComposite %v2bool %bool_false %bool_false",
1070 },
1071 },
1072
1073 // uint -> bool vector
1074 {
1075 // original
1076 {
1077 "%spec_bool_t_vec = OpSpecConstantOp %v2bool INotEqual %unsigned_three_vec %unsigned_zero_vec",
1078 "%spec_bool_f_vec = OpSpecConstantOp %v2bool INotEqual %unsigned_zero_vec %unsigned_zero_vec",
1079 "%spec_bool_from_null = OpSpecConstantOp %v2bool INotEqual %unsigned_null_vec %unsigned_zero_vec",
1080 },
1081 // expected
1082 {
1083 "%true = OpConstantTrue %bool",
1084 "%true_0 = OpConstantTrue %bool",
1085 "%spec_bool_t_vec = OpConstantComposite %v2bool %bool_true %bool_true",
1086 "%false = OpConstantFalse %bool",
1087 "%false_0 = OpConstantFalse %bool",
1088 "%spec_bool_f_vec = OpConstantComposite %v2bool %bool_false %bool_false",
1089 "%false_1 = OpConstantFalse %bool",
1090 "%false_2 = OpConstantFalse %bool",
1091 "%spec_bool_from_null = OpConstantComposite %v2bool %bool_false %bool_false",
1092 },
1093 },
1094
1095 // bool -> int vector
1096 {
1097 // original
1098 {
1099 "%spec_int_one_vec = OpSpecConstantOp %v2int Select %bool_true_vec %signed_one_vec %signed_zero_vec",
1100 "%spec_int_zero_vec = OpSpecConstantOp %v2int Select %bool_false_vec %signed_one_vec %signed_zero_vec",
1101 "%spec_int_from_null = OpSpecConstantOp %v2int Select %bool_null_vec %signed_one_vec %signed_zero_vec",
1102 },
1103 // expected
1104 {
1105 "%int_1 = OpConstant %int 1",
1106 "%int_1_0 = OpConstant %int 1",
1107 "%spec_int_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
1108 "%int_0 = OpConstant %int 0",
1109 "%int_0_0 = OpConstant %int 0",
1110 "%spec_int_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
1111 "%int_0_1 = OpConstant %int 0",
1112 "%int_0_2 = OpConstant %int 0",
1113 "%spec_int_from_null = OpConstantComposite %v2int %signed_zero %signed_zero",
1114 },
1115 },
1116
1117 // uint -> int vector
1118 {
1119 // original
1120 {
1121 "%spec_int_one_vec = OpSpecConstantOp %v2int IAdd %unsigned_one_vec %signed_zero_vec",
1122 "%spec_int_zero_vec = OpSpecConstantOp %v2int IAdd %unsigned_zero_vec %signed_zero_vec",
1123 "%spec_int_from_null = OpSpecConstantOp %v2int IAdd %unsigned_null_vec %signed_zero_vec",
1124 },
1125 // expected
1126 {
1127 "%int_1 = OpConstant %int 1",
1128 "%int_1_0 = OpConstant %int 1",
1129 "%spec_int_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
1130 "%int_0 = OpConstant %int 0",
1131 "%int_0_0 = OpConstant %int 0",
1132 "%spec_int_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
1133 "%int_0_1 = OpConstant %int 0",
1134 "%int_0_2 = OpConstant %int 0",
1135 "%spec_int_from_null = OpConstantComposite %v2int %signed_zero %signed_zero",
1136 },
1137 },
1138
1139 // bool -> uint vector
1140 {
1141 // original
1142 {
1143 "%spec_uint_one_vec = OpSpecConstantOp %v2uint Select %bool_true_vec %unsigned_one_vec %unsigned_zero_vec",
1144 "%spec_uint_zero_vec = OpSpecConstantOp %v2uint Select %bool_false_vec %unsigned_one_vec %unsigned_zero_vec",
1145 "%spec_uint_from_null = OpSpecConstantOp %v2uint Select %bool_null_vec %unsigned_one_vec %unsigned_zero_vec",
1146 },
1147 // expected
1148 {
1149 "%uint_1 = OpConstant %uint 1",
1150 "%uint_1_0 = OpConstant %uint 1",
1151 "%spec_uint_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
1152 "%uint_0 = OpConstant %uint 0",
1153 "%uint_0_0 = OpConstant %uint 0",
1154 "%spec_uint_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
1155 "%uint_0_1 = OpConstant %uint 0",
1156 "%uint_0_2 = OpConstant %uint 0",
1157 "%spec_uint_from_null = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
1158 },
1159 },
1160
1161 // int -> uint vector
1162 {
1163 // original
1164 {
1165 "%spec_uint_one_vec = OpSpecConstantOp %v2uint IAdd %signed_one_vec %unsigned_zero_vec",
1166 "%spec_uint_zero_vec = OpSpecConstantOp %v2uint IAdd %signed_zero_vec %unsigned_zero_vec",
1167 "%spec_uint_from_null = OpSpecConstantOp %v2uint IAdd %signed_null_vec %unsigned_zero_vec",
1168 },
1169 // expected
1170 {
1171 "%uint_1 = OpConstant %uint 1",
1172 "%uint_1_0 = OpConstant %uint 1",
1173 "%spec_uint_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
1174 "%uint_0 = OpConstant %uint 0",
1175 "%uint_0_0 = OpConstant %uint 0",
1176 "%spec_uint_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
1177 "%uint_0_1 = OpConstant %uint 0",
1178 "%uint_0_2 = OpConstant %uint 0",
1179 "%spec_uint_from_null = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
1180 },
1181 },
1182
1183 // UConvert scalar
1184 {
1185 // original
1186 {
1187 "%spec_uint_zero = OpSpecConstantOp %uint UConvert %bool_false",
1188 "%spec_uint_one = OpSpecConstantOp %uint UConvert %bool_true",
1189 "%spec_ulong_zero = OpSpecConstantOp %ulong UConvert %unsigned_zero",
1190 "%spec_ulong_one = OpSpecConstantOp %ulong UConvert %unsigned_one",
1191 "%spec_short_zero = OpSpecConstantOp %ushort UConvert %unsigned_zero",
1192 "%spec_short_one = OpSpecConstantOp %ushort UConvert %unsigned_one",
1193 "%uint_max = OpConstant %uint 4294967295",
1194 "%spec_ushort_max = OpSpecConstantOp %ushort UConvert %uint_max",
1195 "%uint_0xDDDDDDDD = OpConstant %uint 3722304989",
1196 "%spec_ushort_0xDDDD = OpSpecConstantOp %ushort UConvert %uint_0xDDDDDDDD",
1197 },
1198 // expected
1199 {
1200 "%spec_uint_zero = OpConstant %uint 0",
1201 "%spec_uint_one = OpConstant %uint 1",
1202 "%spec_ulong_zero = OpConstant %ulong 0",
1203 "%spec_ulong_one = OpConstant %ulong 1",
1204 "%spec_short_zero = OpConstant %ushort 0",
1205 "%spec_short_one = OpConstant %ushort 1",
1206 "%uint_max = OpConstant %uint 4294967295",
1207 "%spec_ushort_max = OpConstant %ushort 65535",
1208 "%uint_0xDDDDDDDD = OpConstant %uint 3722304989",
1209 "%spec_ushort_0xDDDD = OpConstant %ushort 56797",
1210 },
1211 },
1212
1213 // SConvert scalar
1214 {
1215 // original
1216 {
1217 "%spec_long_zero = OpSpecConstantOp %long SConvert %signed_zero",
1218 "%spec_long_one = OpSpecConstantOp %long SConvert %signed_one",
1219 "%spec_long_minus_one = OpSpecConstantOp %long SConvert %signed_minus_one",
1220 "%spec_short_minus_one_trunc = OpSpecConstantOp %short SConvert %signed_minus_one",
1221 "%int_2_to_17_minus_one = OpConstant %int 131071",
1222 "%spec_short_minus_one_trunc2 = OpSpecConstantOp %short SConvert %int_2_to_17_minus_one",
1223 },
1224 // expected
1225 {
1226 "%spec_long_zero = OpConstant %long 0",
1227 "%spec_long_one = OpConstant %long 1",
1228 "%spec_long_minus_one = OpConstant %long -1",
1229 "%spec_short_minus_one_trunc = OpConstant %short -1",
1230 "%int_2_to_17_minus_one = OpConstant %int 131071",
1231 "%spec_short_minus_one_trunc2 = OpConstant %short -1",
1232 },
1233 },
1234
1235 // UConvert vector
1236 {
1237 // original
1238 {
1239 "%spec_v2uint_zero = OpSpecConstantOp %v2uint UConvert %bool_false_vec",
1240 "%spec_v2uint_one = OpSpecConstantOp %v2uint UConvert %bool_true_vec",
1241 "%spec_v2ulong_zero = OpSpecConstantOp %v2ulong UConvert %unsigned_zero_vec",
1242 "%spec_v2ulong_one = OpSpecConstantOp %v2ulong UConvert %unsigned_one_vec",
1243 },
1244 // expected
1245 {
1246 "%uint_0 = OpConstant %uint 0",
1247 "%uint_0_0 = OpConstant %uint 0",
1248 "%spec_v2uint_zero = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
1249 "%uint_1 = OpConstant %uint 1",
1250 "%uint_1_0 = OpConstant %uint 1",
1251 "%spec_v2uint_one = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
1252 "%ulong_0 = OpConstant %ulong 0",
1253 "%ulong_0_0 = OpConstant %ulong 0",
1254 "%spec_v2ulong_zero = OpConstantComposite %v2ulong %ulong_zero %ulong_zero",
1255 "%ulong_1 = OpConstant %ulong 1",
1256 "%ulong_1_0 = OpConstant %ulong 1",
1257 "%spec_v2ulong_one = OpConstantComposite %v2ulong %ulong_1 %ulong_1",
1258 },
1259 },
1260
1261 // SConvert vector
1262 {
1263 // original
1264 {
1265 "%spec_v2long_zero = OpSpecConstantOp %v2long SConvert %signed_zero_vec",
1266 "%spec_v2long_one = OpSpecConstantOp %v2long SConvert %signed_one_vec",
1267 "%spec_v2long_minus_one = OpSpecConstantOp %v2long SConvert %signed_minus_one_vec",
1268 },
1269 // expected
1270 {
1271 "%long_0 = OpConstant %long 0",
1272 "%long_0_0 = OpConstant %long 0",
1273 "%spec_v2long_zero = OpConstantComposite %v2long %long_zero %long_zero",
1274 "%long_1 = OpConstant %long 1",
1275 "%long_1_0 = OpConstant %long 1",
1276 "%spec_v2long_one = OpConstantComposite %v2long %long_1 %long_1",
1277 "%long_n1 = OpConstant %long -1",
1278 "%long_n1_0 = OpConstant %long -1",
1279 "%spec_v2long_minus_one = OpConstantComposite %v2long %long_n1 %long_n1",
1280 },
1281 },
1282 // clang-format on
1283 })));
1284
1285 // Tests about boolean scalar logical operations and comparison operations with
1286 // scalar int/uint type.
1287 INSTANTIATE_TEST_SUITE_P(
1288 Logical, FoldSpecConstantOpAndCompositePassTest,
1289 ::testing::ValuesIn(std::vector<
1290 FoldSpecConstantOpAndCompositePassTestCase>({
1291 // clang-format off
1292 // scalar integer comparison
1293 {
1294 // original
1295 {
1296 "%int_minus_1 = OpConstant %int -1",
1297
1298 "%slt_0_1 = OpSpecConstantOp %bool SLessThan %signed_zero %signed_one",
1299 "%sgt_0_1 = OpSpecConstantOp %bool SGreaterThan %signed_zero %signed_one",
1300 "%sle_2_2 = OpSpecConstantOp %bool SLessThanEqual %signed_two %signed_two",
1301 "%sge_2_1 = OpSpecConstantOp %bool SGreaterThanEqual %signed_two %signed_one",
1302 "%sge_2_null = OpSpecConstantOp %bool SGreaterThanEqual %signed_two %signed_null",
1303 "%sge_minus_1_null = OpSpecConstantOp %bool SGreaterThanEqual %int_minus_1 %signed_null",
1304
1305 "%ult_0_1 = OpSpecConstantOp %bool ULessThan %unsigned_zero %unsigned_one",
1306 "%ugt_0_1 = OpSpecConstantOp %bool UGreaterThan %unsigned_zero %unsigned_one",
1307 "%ule_2_3 = OpSpecConstantOp %bool ULessThanEqual %unsigned_two %unsigned_three",
1308 "%uge_1_1 = OpSpecConstantOp %bool UGreaterThanEqual %unsigned_one %unsigned_one",
1309 "%uge_2_null = OpSpecConstantOp %bool UGreaterThanEqual %unsigned_two %unsigned_null",
1310 "%uge_minus_1_null = OpSpecConstantOp %bool UGreaterThanEqual %int_minus_1 %unsigned_null",
1311 },
1312 // expected
1313 {
1314 "%int_minus_1 = OpConstant %int -1",
1315
1316 "%slt_0_1 = OpConstantTrue %bool",
1317 "%sgt_0_1 = OpConstantFalse %bool",
1318 "%sle_2_2 = OpConstantTrue %bool",
1319 "%sge_2_1 = OpConstantTrue %bool",
1320 "%sge_2_null = OpConstantTrue %bool",
1321 "%sge_minus_1_null = OpConstantFalse %bool",
1322
1323 "%ult_0_1 = OpConstantTrue %bool",
1324 "%ugt_0_1 = OpConstantFalse %bool",
1325 "%ule_2_3 = OpConstantTrue %bool",
1326 "%uge_1_1 = OpConstantTrue %bool",
1327 "%uge_2_null = OpConstantTrue %bool",
1328 "%uge_minus_1_null = OpConstantTrue %bool",
1329 },
1330 },
1331 // Logical and, or, xor.
1332 {
1333 // original
1334 {
1335 "%logical_or = OpSpecConstantOp %bool LogicalOr %bool_true %bool_false",
1336 "%logical_and = OpSpecConstantOp %bool LogicalAnd %bool_true %bool_false",
1337 "%logical_not = OpSpecConstantOp %bool LogicalNot %bool_true",
1338 "%logical_eq = OpSpecConstantOp %bool LogicalEqual %bool_true %bool_true",
1339 "%logical_neq = OpSpecConstantOp %bool LogicalNotEqual %bool_true %bool_true",
1340 "%logical_and_null = OpSpecConstantOp %bool LogicalAnd %bool_true %bool_null",
1341 },
1342 // expected
1343 {
1344 "%logical_or = OpConstantTrue %bool",
1345 "%logical_and = OpConstantFalse %bool",
1346 "%logical_not = OpConstantFalse %bool",
1347 "%logical_eq = OpConstantTrue %bool",
1348 "%logical_neq = OpConstantFalse %bool",
1349 "%logical_and_null = OpConstantFalse %bool",
1350 },
1351 },
1352 // clang-format on
1353 })));
1354
1355 // Tests about arithmetic operations for scalar int and uint types.
1356 INSTANTIATE_TEST_SUITE_P(
1357 ScalarArithmetic, FoldSpecConstantOpAndCompositePassTest,
1358 ::testing::ValuesIn(std::vector<
1359 FoldSpecConstantOpAndCompositePassTestCase>({
1360 // clang-format off
1361 // scalar integer negate
1362 {
1363 // original
1364 {
1365 "%int_minus_1 = OpSpecConstantOp %int SNegate %signed_one",
1366 "%int_minus_2 = OpSpecConstantOp %int SNegate %signed_two",
1367 "%int_neg_null = OpSpecConstantOp %int SNegate %signed_null",
1368 "%int_max = OpConstant %int 2147483647",
1369 "%int_neg_max = OpSpecConstantOp %int SNegate %int_max",
1370 },
1371 // expected
1372 {
1373 "%int_minus_1 = OpConstant %int -1",
1374 "%int_minus_2 = OpConstant %int -2",
1375 "%int_neg_null = OpConstant %int 0",
1376 "%int_max = OpConstant %int 2147483647",
1377 "%int_neg_max = OpConstant %int -2147483647",
1378 },
1379 },
1380 // scalar integer not
1381 {
1382 // original
1383 {
1384 "%uint_4294967294 = OpSpecConstantOp %uint Not %unsigned_one",
1385 "%uint_4294967293 = OpSpecConstantOp %uint Not %unsigned_two",
1386 "%uint_neg_null = OpSpecConstantOp %uint Not %unsigned_null",
1387 },
1388 // expected
1389 {
1390 "%uint_4294967294 = OpConstant %uint 4294967294",
1391 "%uint_4294967293 = OpConstant %uint 4294967293",
1392 "%uint_neg_null = OpConstant %uint 4294967295",
1393 },
1394 },
1395 // scalar integer add, sub, mul, div
1396 {
1397 // original
1398 {
1399 "%signed_max = OpConstant %int 2147483647",
1400 "%signed_min = OpConstant %int -2147483648",
1401
1402 "%spec_int_iadd = OpSpecConstantOp %int IAdd %signed_three %signed_two",
1403 "%spec_int_isub = OpSpecConstantOp %int ISub %signed_one %spec_int_iadd",
1404 "%spec_int_sdiv = OpSpecConstantOp %int SDiv %spec_int_isub %signed_two",
1405 "%spec_int_imul = OpSpecConstantOp %int IMul %spec_int_sdiv %signed_three",
1406 "%spec_int_iadd_null = OpSpecConstantOp %int IAdd %spec_int_imul %signed_null",
1407 "%spec_int_imul_null = OpSpecConstantOp %int IMul %spec_int_iadd_null %signed_null",
1408 "%spec_int_iadd_overflow = OpSpecConstantOp %int IAdd %signed_max %signed_three",
1409 "%spec_int_isub_overflow = OpSpecConstantOp %int ISub %signed_min %signed_three",
1410
1411 "%spec_uint_iadd = OpSpecConstantOp %uint IAdd %unsigned_three %unsigned_two",
1412 "%spec_uint_isub = OpSpecConstantOp %uint ISub %unsigned_one %spec_uint_iadd",
1413 "%spec_uint_udiv = OpSpecConstantOp %uint UDiv %spec_uint_isub %unsigned_three",
1414 "%spec_uint_imul = OpSpecConstantOp %uint IMul %spec_uint_udiv %unsigned_two",
1415 "%spec_uint_isub_null = OpSpecConstantOp %uint ISub %spec_uint_imul %signed_null",
1416 },
1417 // expected
1418 {
1419 "%signed_max = OpConstant %int 2147483647",
1420 "%signed_min = OpConstant %int -2147483648",
1421
1422 "%spec_int_iadd = OpConstant %int 5",
1423 "%spec_int_isub = OpConstant %int -4",
1424 "%spec_int_sdiv = OpConstant %int -2",
1425 "%spec_int_imul = OpConstant %int -6",
1426 "%spec_int_iadd_null = OpConstant %int -6",
1427 "%spec_int_imul_null = OpConstant %int 0",
1428 "%spec_int_iadd_overflow = OpConstant %int -2147483646",
1429 "%spec_int_isub_overflow = OpConstant %int 2147483645",
1430
1431 "%spec_uint_iadd = OpConstant %uint 5",
1432 "%spec_uint_isub = OpConstant %uint 4294967292",
1433 "%spec_uint_udiv = OpConstant %uint 1431655764",
1434 "%spec_uint_imul = OpConstant %uint 2863311528",
1435 "%spec_uint_isub_null = OpConstant %uint 2863311528",
1436 },
1437 },
1438 // scalar integer rem, mod
1439 {
1440 // original
1441 {
1442 // common constants
1443 "%int_7 = OpConstant %int 7",
1444 "%uint_7 = OpConstant %uint 7",
1445 "%int_minus_7 = OpConstant %int -7",
1446 "%int_minus_3 = OpConstant %int -3",
1447
1448 // srem
1449 "%7_srem_3 = OpSpecConstantOp %int SRem %int_7 %signed_three",
1450 "%minus_7_srem_3 = OpSpecConstantOp %int SRem %int_minus_7 %signed_three",
1451 "%7_srem_minus_3 = OpSpecConstantOp %int SRem %int_7 %int_minus_3",
1452 "%minus_7_srem_minus_3 = OpSpecConstantOp %int SRem %int_minus_7 %int_minus_3",
1453 // smod
1454 "%7_smod_3 = OpSpecConstantOp %int SMod %int_7 %signed_three",
1455 "%minus_7_smod_3 = OpSpecConstantOp %int SMod %int_minus_7 %signed_three",
1456 "%7_smod_minus_3 = OpSpecConstantOp %int SMod %int_7 %int_minus_3",
1457 "%minus_7_smod_minus_3 = OpSpecConstantOp %int SMod %int_minus_7 %int_minus_3",
1458 // umod
1459 "%7_umod_3 = OpSpecConstantOp %uint UMod %uint_7 %unsigned_three",
1460 // null constant
1461 "%null_srem_3 = OpSpecConstantOp %int SRem %signed_null %signed_three",
1462 "%null_smod_3 = OpSpecConstantOp %int SMod %signed_null %signed_three",
1463 "%null_umod_3 = OpSpecConstantOp %uint UMod %unsigned_null %unsigned_three",
1464 },
1465 // expected
1466 {
1467 // common constants
1468 "%int_7 = OpConstant %int 7",
1469 "%uint_7 = OpConstant %uint 7",
1470 "%int_minus_7 = OpConstant %int -7",
1471 "%int_minus_3 = OpConstant %int -3",
1472
1473 // srem
1474 "%7_srem_3 = OpConstant %int 1",
1475 "%minus_7_srem_3 = OpConstant %int -1",
1476 "%7_srem_minus_3 = OpConstant %int 1",
1477 "%minus_7_srem_minus_3 = OpConstant %int -1",
1478 // smod
1479 "%7_smod_3 = OpConstant %int 1",
1480 "%minus_7_smod_3 = OpConstant %int 2",
1481 "%7_smod_minus_3 = OpConstant %int -2",
1482 "%minus_7_smod_minus_3 = OpConstant %int -1",
1483 // umod
1484 "%7_umod_3 = OpConstant %uint 1",
1485 // null constant
1486 "%null_srem_3 = OpConstant %int 0",
1487 "%null_smod_3 = OpConstant %int 0",
1488 "%null_umod_3 = OpConstant %uint 0",
1489 },
1490 },
1491 // scalar integer bitwise and shift
1492 {
1493 // original
1494 {
1495 // bitwise
1496 "%xor_1_3 = OpSpecConstantOp %int BitwiseXor %signed_one %signed_three",
1497 "%and_1_2 = OpSpecConstantOp %int BitwiseAnd %signed_one %xor_1_3",
1498 "%or_1_2 = OpSpecConstantOp %int BitwiseOr %signed_one %xor_1_3",
1499 "%xor_3_null = OpSpecConstantOp %int BitwiseXor %or_1_2 %signed_null",
1500
1501 // shift
1502 "%unsigned_31 = OpConstant %uint 31",
1503 "%unsigned_left_shift_max = OpSpecConstantOp %uint ShiftLeftLogical %unsigned_one %unsigned_31",
1504 "%unsigned_right_shift_logical = OpSpecConstantOp %uint ShiftRightLogical %unsigned_left_shift_max %unsigned_31",
1505 "%signed_right_shift_arithmetic = OpSpecConstantOp %int ShiftRightArithmetic %unsigned_left_shift_max %unsigned_31",
1506 "%left_shift_null_31 = OpSpecConstantOp %uint ShiftLeftLogical %unsigned_null %unsigned_31",
1507 "%right_shift_31_null = OpSpecConstantOp %uint ShiftRightLogical %unsigned_31 %unsigned_null",
1508 },
1509 // expected
1510 {
1511 "%xor_1_3 = OpConstant %int 2",
1512 "%and_1_2 = OpConstant %int 0",
1513 "%or_1_2 = OpConstant %int 3",
1514 "%xor_3_null = OpConstant %int 3",
1515
1516 "%unsigned_31 = OpConstant %uint 31",
1517 "%unsigned_left_shift_max = OpConstant %uint 2147483648",
1518 "%unsigned_right_shift_logical = OpConstant %uint 1",
1519 "%signed_right_shift_arithmetic = OpConstant %int -1",
1520 "%left_shift_null_31 = OpConstant %uint 0",
1521 "%right_shift_31_null = OpConstant %uint 31",
1522 },
1523 },
1524 // Skip folding if any operands have undetermined value.
1525 {
1526 // original
1527 {
1528 "%spec_int = OpSpecConstant %int 1",
1529 "%spec_iadd = OpSpecConstantOp %int IAdd %signed_three %spec_int",
1530 },
1531 // expected
1532 {
1533 "%spec_int = OpSpecConstant %int 1",
1534 "%spec_iadd = OpSpecConstantOp %int IAdd %signed_three %spec_int",
1535 },
1536 },
1537 // clang-format on
1538 })));
1539
1540 // Tests about arithmetic operations for vector int and uint types.
1541 INSTANTIATE_TEST_SUITE_P(
1542 VectorArithmetic, FoldSpecConstantOpAndCompositePassTest,
1543 ::testing::ValuesIn(std::vector<
1544 FoldSpecConstantOpAndCompositePassTestCase>({
1545 // clang-format off
1546 // vector integer negate
1547 {
1548 // original
1549 {
1550 "%v2int_minus_1 = OpSpecConstantOp %v2int SNegate %signed_one_vec",
1551 "%v2int_minus_2 = OpSpecConstantOp %v2int SNegate %signed_two_vec",
1552 "%v2int_neg_null = OpSpecConstantOp %v2int SNegate %signed_null_vec",
1553 },
1554 // expected
1555 {
1556 "%int_n1 = OpConstant %int -1",
1557 "%int_n1_0 = OpConstant %int -1",
1558 "%v2int_minus_1 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
1559 "%int_n2 = OpConstant %int -2",
1560 "%int_n2_0 = OpConstant %int -2",
1561 "%v2int_minus_2 = OpConstantComposite %v2int %int_n2 %int_n2",
1562 "%int_0 = OpConstant %int 0",
1563 "%int_0_0 = OpConstant %int 0",
1564 "%v2int_neg_null = OpConstantComposite %v2int %signed_zero %signed_zero",
1565 },
1566 },
1567 // vector integer (including null vetors) add, sub, div, mul
1568 {
1569 // original
1570 {
1571 "%spec_v2int_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %signed_two_vec",
1572 "%spec_v2int_isub = OpSpecConstantOp %v2int ISub %signed_one_vec %spec_v2int_iadd",
1573 "%spec_v2int_sdiv = OpSpecConstantOp %v2int SDiv %spec_v2int_isub %signed_two_vec",
1574 "%spec_v2int_imul = OpSpecConstantOp %v2int IMul %spec_v2int_sdiv %signed_three_vec",
1575 "%spec_v2int_iadd_null = OpSpecConstantOp %v2int IAdd %spec_v2int_imul %signed_null_vec",
1576
1577 "%spec_v2uint_iadd = OpSpecConstantOp %v2uint IAdd %unsigned_three_vec %unsigned_two_vec",
1578 "%spec_v2uint_isub = OpSpecConstantOp %v2uint ISub %unsigned_one_vec %spec_v2uint_iadd",
1579 "%spec_v2uint_udiv = OpSpecConstantOp %v2uint UDiv %spec_v2uint_isub %unsigned_three_vec",
1580 "%spec_v2uint_imul = OpSpecConstantOp %v2uint IMul %spec_v2uint_udiv %unsigned_two_vec",
1581 "%spec_v2uint_isub_null = OpSpecConstantOp %v2uint ISub %spec_v2uint_imul %signed_null_vec",
1582 },
1583 // expected
1584 {
1585 "%int_5 = OpConstant %int 5",
1586 "%int_5_0 = OpConstant %int 5",
1587 "%spec_v2int_iadd = OpConstantComposite %v2int %int_5 %int_5",
1588 "%int_n4 = OpConstant %int -4",
1589 "%int_n4_0 = OpConstant %int -4",
1590 "%spec_v2int_isub = OpConstantComposite %v2int %int_n4 %int_n4",
1591 "%int_n2 = OpConstant %int -2",
1592 "%int_n2_0 = OpConstant %int -2",
1593 "%spec_v2int_sdiv = OpConstantComposite %v2int %int_n2 %int_n2",
1594 "%int_n6 = OpConstant %int -6",
1595 "%int_n6_0 = OpConstant %int -6",
1596 "%spec_v2int_imul = OpConstantComposite %v2int %int_n6 %int_n6",
1597 "%int_n6_1 = OpConstant %int -6",
1598 "%int_n6_2 = OpConstant %int -6",
1599 "%spec_v2int_iadd_null = OpConstantComposite %v2int %int_n6 %int_n6",
1600
1601 "%uint_5 = OpConstant %uint 5",
1602 "%uint_5_0 = OpConstant %uint 5",
1603 "%spec_v2uint_iadd = OpConstantComposite %v2uint %uint_5 %uint_5",
1604 "%uint_4294967292 = OpConstant %uint 4294967292",
1605 "%uint_4294967292_0 = OpConstant %uint 4294967292",
1606 "%spec_v2uint_isub = OpConstantComposite %v2uint %uint_4294967292 %uint_4294967292",
1607 "%uint_1431655764 = OpConstant %uint 1431655764",
1608 "%uint_1431655764_0 = OpConstant %uint 1431655764",
1609 "%spec_v2uint_udiv = OpConstantComposite %v2uint %uint_1431655764 %uint_1431655764",
1610 "%uint_2863311528 = OpConstant %uint 2863311528",
1611 "%uint_2863311528_0 = OpConstant %uint 2863311528",
1612 "%spec_v2uint_imul = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528",
1613 "%uint_2863311528_1 = OpConstant %uint 2863311528",
1614 "%uint_2863311528_2 = OpConstant %uint 2863311528",
1615 "%spec_v2uint_isub_null = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528",
1616 },
1617 },
1618 // vector integer rem, mod
1619 {
1620 // original
1621 {
1622 // common constants
1623 "%int_7 = OpConstant %int 7",
1624 "%v2int_7 = OpConstantComposite %v2int %int_7 %int_7",
1625 "%uint_7 = OpConstant %uint 7",
1626 "%v2uint_7 = OpConstantComposite %v2uint %uint_7 %uint_7",
1627 "%int_minus_7 = OpConstant %int -7",
1628 "%v2int_minus_7 = OpConstantComposite %v2int %int_minus_7 %int_minus_7",
1629 "%int_minus_3 = OpConstant %int -3",
1630 "%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3",
1631
1632 // srem
1633 "%7_srem_3 = OpSpecConstantOp %v2int SRem %v2int_7 %signed_three_vec",
1634 "%minus_7_srem_3 = OpSpecConstantOp %v2int SRem %v2int_minus_7 %signed_three_vec",
1635 "%7_srem_minus_3 = OpSpecConstantOp %v2int SRem %v2int_7 %v2int_minus_3",
1636 "%minus_7_srem_minus_3 = OpSpecConstantOp %v2int SRem %v2int_minus_7 %v2int_minus_3",
1637 // smod
1638 "%7_smod_3 = OpSpecConstantOp %v2int SMod %v2int_7 %signed_three_vec",
1639 "%minus_7_smod_3 = OpSpecConstantOp %v2int SMod %v2int_minus_7 %signed_three_vec",
1640 "%7_smod_minus_3 = OpSpecConstantOp %v2int SMod %v2int_7 %v2int_minus_3",
1641 "%minus_7_smod_minus_3 = OpSpecConstantOp %v2int SMod %v2int_minus_7 %v2int_minus_3",
1642 // umod
1643 "%7_umod_3 = OpSpecConstantOp %v2uint UMod %v2uint_7 %unsigned_three_vec",
1644 },
1645 // expected
1646 {
1647 // common constants
1648 "%int_7 = OpConstant %int 7",
1649 "%v2int_7 = OpConstantComposite %v2int %int_7 %int_7",
1650 "%uint_7 = OpConstant %uint 7",
1651 "%v2uint_7 = OpConstantComposite %v2uint %uint_7 %uint_7",
1652 "%int_minus_7 = OpConstant %int -7",
1653 "%v2int_minus_7 = OpConstantComposite %v2int %int_minus_7 %int_minus_7",
1654 "%int_minus_3 = OpConstant %int -3",
1655 "%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3",
1656
1657 // srem
1658 "%int_1 = OpConstant %int 1",
1659 "%int_1_0 = OpConstant %int 1",
1660 "%7_srem_3 = OpConstantComposite %v2int %signed_one %signed_one",
1661 "%int_n1 = OpConstant %int -1",
1662 "%int_n1_0 = OpConstant %int -1",
1663 "%minus_7_srem_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
1664 "%int_1_1 = OpConstant %int 1",
1665 "%int_1_2 = OpConstant %int 1",
1666 "%7_srem_minus_3 = OpConstantComposite %v2int %signed_one %signed_one",
1667 "%int_n1_1 = OpConstant %int -1",
1668 "%int_n1_2 = OpConstant %int -1",
1669 "%minus_7_srem_minus_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
1670 // smod
1671 "%int_1_3 = OpConstant %int 1",
1672 "%int_1_4 = OpConstant %int 1",
1673 "%7_smod_3 = OpConstantComposite %v2int %signed_one %signed_one",
1674 "%int_2 = OpConstant %int 2",
1675 "%int_2_0 = OpConstant %int 2",
1676 "%minus_7_smod_3 = OpConstantComposite %v2int %signed_two %signed_two",
1677 "%int_n2 = OpConstant %int -2",
1678 "%int_n2_0 = OpConstant %int -2",
1679 "%7_smod_minus_3 = OpConstantComposite %v2int %int_n2 %int_n2",
1680 "%int_n1_3 = OpConstant %int -1",
1681 "%int_n1_4 = OpConstant %int -1",
1682 "%minus_7_smod_minus_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
1683 // umod
1684 "%uint_1 = OpConstant %uint 1",
1685 "%uint_1_0 = OpConstant %uint 1",
1686 "%7_umod_3 = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
1687 },
1688 },
1689 // vector integer bitwise, shift
1690 {
1691 // original
1692 {
1693 "%xor_1_3 = OpSpecConstantOp %v2int BitwiseXor %signed_one_vec %signed_three_vec",
1694 "%and_1_2 = OpSpecConstantOp %v2int BitwiseAnd %signed_one_vec %xor_1_3",
1695 "%or_1_2 = OpSpecConstantOp %v2int BitwiseOr %signed_one_vec %xor_1_3",
1696
1697 "%unsigned_31 = OpConstant %uint 31",
1698 "%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31",
1699 "%unsigned_left_shift_max = OpSpecConstantOp %v2uint ShiftLeftLogical %unsigned_one_vec %v2unsigned_31",
1700 "%unsigned_right_shift_logical = OpSpecConstantOp %v2uint ShiftRightLogical %unsigned_left_shift_max %v2unsigned_31",
1701 "%signed_right_shift_arithmetic = OpSpecConstantOp %v2int ShiftRightArithmetic %unsigned_left_shift_max %v2unsigned_31",
1702 },
1703 // expected
1704 {
1705 "%int_2 = OpConstant %int 2",
1706 "%int_2_0 = OpConstant %int 2",
1707 "%xor_1_3 = OpConstantComposite %v2int %signed_two %signed_two",
1708 "%int_0 = OpConstant %int 0",
1709 "%int_0_0 = OpConstant %int 0",
1710 "%and_1_2 = OpConstantComposite %v2int %signed_zero %signed_zero",
1711 "%int_3 = OpConstant %int 3",
1712 "%int_3_0 = OpConstant %int 3",
1713 "%or_1_2 = OpConstantComposite %v2int %signed_three %signed_three",
1714
1715 "%unsigned_31 = OpConstant %uint 31",
1716 "%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31",
1717 "%uint_2147483648 = OpConstant %uint 2147483648",
1718 "%uint_2147483648_0 = OpConstant %uint 2147483648",
1719 "%unsigned_left_shift_max = OpConstantComposite %v2uint %uint_2147483648 %uint_2147483648",
1720 "%uint_1 = OpConstant %uint 1",
1721 "%uint_1_0 = OpConstant %uint 1",
1722 "%unsigned_right_shift_logical = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
1723 "%int_n1 = OpConstant %int -1",
1724 "%int_n1_0 = OpConstant %int -1",
1725 "%signed_right_shift_arithmetic = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
1726 },
1727 },
1728 // Skip folding if any vector operands or components of the operands
1729 // have undetermined value.
1730 {
1731 // original
1732 {
1733 "%spec_int = OpSpecConstant %int 1",
1734 "%spec_vec = OpSpecConstantComposite %v2int %signed_zero %spec_int",
1735 "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %spec_vec",
1736 },
1737 // expected
1738 {
1739 "%spec_int = OpSpecConstant %int 1",
1740 "%spec_vec = OpSpecConstantComposite %v2int %signed_zero %spec_int",
1741 "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %spec_vec",
1742 },
1743 },
1744 // Skip folding if any vector operands are defined by OpUndef
1745 {
1746 // original
1747 {
1748 "%undef = OpUndef %int",
1749 "%vec = OpConstantComposite %v2int %undef %signed_one",
1750 "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %vec",
1751 },
1752 // expected
1753 {
1754 "%undef = OpUndef %int",
1755 "%vec = OpConstantComposite %v2int %undef %signed_one",
1756 "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %vec",
1757 },
1758 },
1759 // clang-format on
1760 })));
1761
1762 // Tests for SpecConstantOp CompositeExtract instruction
1763 INSTANTIATE_TEST_SUITE_P(
1764 CompositeExtract, FoldSpecConstantOpAndCompositePassTest,
1765 ::testing::ValuesIn(std::vector<
1766 FoldSpecConstantOpAndCompositePassTestCase>({
1767 // clang-format off
1768 // normal vector
1769 {
1770 // original
1771 {
1772 "%r = OpSpecConstantOp %int CompositeExtract %signed_three_vec 0",
1773 "%x = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 0",
1774 "%y = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 1",
1775 "%z = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 2",
1776 "%w = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 3",
1777 },
1778 // expected
1779 {
1780 "%r = OpConstant %int 3",
1781 "%x = OpConstant %int 0",
1782 "%y = OpConstant %int 1",
1783 "%z = OpConstant %int 2",
1784 "%w = OpConstant %int 3",
1785 },
1786 },
1787 // null vector
1788 {
1789 // original
1790 {
1791 "%x = OpSpecConstantOp %int CompositeExtract %signed_null_vec 0",
1792 "%y = OpSpecConstantOp %int CompositeExtract %signed_null_vec 1",
1793 "%null_v4int = OpConstantNull %v4int",
1794 "%z = OpSpecConstantOp %int CompositeExtract %signed_null_vec 2",
1795 },
1796 // expected
1797 {
1798 "%x = OpConstantNull %int",
1799 "%y = OpConstantNull %int",
1800 "%null_v4int = OpConstantNull %v4int",
1801 "%z = OpConstantNull %int",
1802 }
1803 },
1804 // normal flat struct
1805 {
1806 // original
1807 {
1808 "%float_1 = OpConstant %float 1",
1809 "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
1810 "%extract_bool = OpSpecConstantOp %bool CompositeExtract %flat_1 0",
1811 "%extract_int = OpSpecConstantOp %int CompositeExtract %flat_1 1",
1812 "%extract_float_1 = OpSpecConstantOp %float CompositeExtract %flat_1 2",
1813 // foldable composite constants built with OpSpecConstantComposite
1814 // should also be processed.
1815 "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_null %float_1",
1816 "%extract_float_2 = OpSpecConstantOp %float CompositeExtract %flat_2 2",
1817 },
1818 // expected
1819 {
1820 "%float_1 = OpConstant %float 1",
1821 "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
1822 "%extract_bool = OpConstantTrue %bool",
1823 "%extract_int = OpConstantNull %int",
1824 "%extract_float_1 = OpConstant %float 1",
1825 "%flat_2 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
1826 "%extract_float_2 = OpConstant %float 1",
1827 },
1828 },
1829 // null flat struct
1830 {
1831 // original
1832 {
1833 "%flat = OpConstantNull %flat_struct",
1834 "%extract_bool = OpSpecConstantOp %bool CompositeExtract %flat 0",
1835 "%extract_int = OpSpecConstantOp %int CompositeExtract %flat 1",
1836 "%extract_float = OpSpecConstantOp %float CompositeExtract %flat 2",
1837 },
1838 // expected
1839 {
1840 "%flat = OpConstantNull %flat_struct",
1841 "%extract_bool = OpConstantNull %bool",
1842 "%extract_int = OpConstantNull %int",
1843 "%extract_float = OpConstantNull %float",
1844 },
1845 },
1846 // normal nested struct
1847 {
1848 // original
1849 {
1850 "%float_1 = OpConstant %float 1",
1851 "%inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
1852 "%outer = OpConstantComposite %outer_struct %inner %signed_one",
1853 "%extract_inner = OpSpecConstantOp %inner_struct CompositeExtract %outer 0",
1854 "%extract_int = OpSpecConstantOp %int CompositeExtract %outer 1",
1855 "%extract_inner_float = OpSpecConstantOp %float CompositeExtract %outer 0 2",
1856 },
1857 // expected
1858 {
1859 "%float_1 = OpConstant %float 1",
1860 "%inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
1861 "%outer = OpConstantComposite %outer_struct %inner %signed_one",
1862 "%extract_inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
1863 "%extract_int = OpConstant %int 1",
1864 "%extract_inner_float = OpConstant %float 1",
1865 },
1866 },
1867 // null nested struct
1868 {
1869 // original
1870 {
1871 "%outer = OpConstantNull %outer_struct",
1872 "%extract_inner = OpSpecConstantOp %inner_struct CompositeExtract %outer 0",
1873 "%extract_int = OpSpecConstantOp %int CompositeExtract %outer 1",
1874 "%extract_inner_float = OpSpecConstantOp %float CompositeExtract %outer 0 2",
1875 },
1876 // expected
1877 {
1878 "%outer = OpConstantNull %outer_struct",
1879 "%extract_inner = OpConstantNull %inner_struct",
1880 "%extract_int = OpConstantNull %int",
1881 "%extract_inner_float = OpConstantNull %float",
1882 },
1883 },
1884 // skip folding if the any composite constant's value are not fully
1885 // determined, even though the extracting target might have
1886 // determined value.
1887 {
1888 // original
1889 {
1890 "%float_1 = OpConstant %float 1",
1891 "%spec_float = OpSpecConstant %float 1",
1892 "%spec_inner = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
1893 "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %signed_one",
1894 "%spec_vec = OpSpecConstantComposite %v2float %spec_float %float_1",
1895 "%extract_inner = OpSpecConstantOp %int CompositeExtract %spec_inner 1",
1896 "%extract_outer = OpSpecConstantOp %int CompositeExtract %spec_outer 1",
1897 "%extract_vec = OpSpecConstantOp %float CompositeExtract %spec_vec 1",
1898 },
1899 // expected
1900 {
1901 "%float_1 = OpConstant %float 1",
1902 "%spec_float = OpSpecConstant %float 1",
1903 "%spec_inner = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
1904 "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %signed_one",
1905 "%spec_vec = OpSpecConstantComposite %v2float %spec_float %float_1",
1906 "%extract_inner = OpSpecConstantOp %int CompositeExtract %spec_inner 1",
1907 "%extract_outer = OpSpecConstantOp %int CompositeExtract %spec_outer 1",
1908 "%extract_vec = OpSpecConstantOp %float CompositeExtract %spec_vec 1",
1909 },
1910 },
1911 // skip if the composite constant depends on the result of OpUndef,
1912 // even though the composite extract target element does not depends
1913 // on the OpUndef.
1914 {
1915 // original
1916 {
1917 "%undef = OpUndef %float",
1918 "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
1919 "%outer = OpConstantComposite %outer_struct %inner %signed_one",
1920 "%extract_inner = OpSpecConstantOp %int CompositeExtract %inner 1",
1921 "%extract_outer = OpSpecConstantOp %int CompositeExtract %outer 1",
1922 },
1923 // expected
1924 {
1925 "%undef = OpUndef %float",
1926 "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
1927 "%outer = OpConstantComposite %outer_struct %inner %signed_one",
1928 "%extract_inner = OpSpecConstantOp %int CompositeExtract %inner 1",
1929 "%extract_outer = OpSpecConstantOp %int CompositeExtract %outer 1",
1930 },
1931 },
1932 // TODO(qining): Add tests for Array and other composite type constants.
1933 // clang-format on
1934 })));
1935
1936 // Tests the swizzle operations for spec const vectors.
1937 INSTANTIATE_TEST_SUITE_P(
1938 VectorShuffle, FoldSpecConstantOpAndCompositePassTest,
1939 ::testing::ValuesIn(std::vector<
1940 FoldSpecConstantOpAndCompositePassTestCase>({
1941 // clang-format off
1942 // normal vector
1943 {
1944 // original
1945 {
1946 "%xy = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 0 1",
1947 "%yz = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 1 2",
1948 "%zw = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 2 3",
1949 "%wx = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 3 0",
1950 "%xx = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 0 0",
1951 "%yyy = OpSpecConstantOp %v3int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 1 1 1",
1952 "%wwww = OpSpecConstantOp %v4int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 2 2 2 2",
1953 },
1954 // expected
1955 {
1956 "%xy = OpConstantComposite %v2int %signed_zero %signed_one",
1957 "%yz = OpConstantComposite %v2int %signed_one %signed_two",
1958 "%zw = OpConstantComposite %v2int %signed_two %signed_three",
1959 "%wx = OpConstantComposite %v2int %signed_three %signed_zero",
1960 "%xx = OpConstantComposite %v2int %signed_zero %signed_zero",
1961 "%yyy = OpConstantComposite %v3int %signed_one %signed_one %signed_one",
1962 "%wwww = OpConstantComposite %v4int %signed_two %signed_two %signed_two %signed_two",
1963 },
1964 },
1965 // null vector
1966 {
1967 // original
1968 {
1969 "%a = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %v4int_0_1_2_3 0 1",
1970 "%b = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %v4int_0_1_2_3 2 3",
1971 "%c = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %signed_null_vec 3 4",
1972 "%d = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %signed_null_vec 1 2",
1973 },
1974 // expected
1975 {
1976 "%a = OpConstantComposite %v2int %signed_null %signed_null",
1977 "%b = OpConstantComposite %v2int %signed_zero %signed_one",
1978 "%c = OpConstantComposite %v2int %signed_three %signed_null",
1979 "%d = OpConstantComposite %v2int %signed_null %signed_null",
1980 }
1981 },
1982 // skip if any of the components of the vector operands do not have
1983 // determined value, even though the result vector might not be
1984 // built with those undermined values.
1985 {
1986 // original
1987 {
1988 "%spec_int = OpSpecConstant %int 1",
1989 "%spec_ivec = OpSpecConstantComposite %v2int %signed_null %spec_int",
1990 "%a = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 0 1",
1991 "%b = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 3 4",
1992 },
1993 // expected
1994 {
1995 "%spec_int = OpSpecConstant %int 1",
1996 "%spec_ivec = OpSpecConstantComposite %v2int %signed_null %spec_int",
1997 "%a = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 0 1",
1998 "%b = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 3 4",
1999 },
2000 },
2001 // Skip if any components of the two vector operands depend on
2002 // the result of OpUndef. Even though the selected components do
2003 // not depend on the OpUndef result.
2004 {
2005 // original
2006 {
2007 "%undef = OpUndef %int",
2008 "%vec_1 = OpConstantComposite %v2int %undef %signed_one",
2009 "%dep = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 0 3",
2010 "%not_dep_element = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 1 3",
2011 "%no_dep_vector = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 2 3",
2012 },
2013 // expected
2014 {
2015 "%undef = OpUndef %int",
2016 "%vec_1 = OpConstantComposite %v2int %undef %signed_one",
2017 "%dep = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 0 3",
2018 "%not_dep_element = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 1 3",
2019 "%no_dep_vector = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 2 3",
2020 },
2021 },
2022 // clang-format on
2023 })));
2024
2025 // Test with long use-def chain.
2026 INSTANTIATE_TEST_SUITE_P(
2027 LongDefUseChain, FoldSpecConstantOpAndCompositePassTest,
2028 ::testing::ValuesIn(std::vector<
2029 FoldSpecConstantOpAndCompositePassTestCase>({
2030 // clang-format off
2031 // Long Def-Use chain with binary operations.
2032 {
2033 // original
2034 {
2035 "%array_size = OpConstant %int 4",
2036 "%type_arr_int_4 = OpTypeArray %int %array_size",
2037 "%spec_int_0 = OpConstant %int 100",
2038 "%spec_int_1 = OpConstant %int 1",
2039 "%spec_int_2 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_1",
2040 "%spec_int_3 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_2",
2041 "%spec_int_4 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_3",
2042 "%spec_int_5 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_4",
2043 "%spec_int_6 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_5",
2044 "%spec_int_7 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_6",
2045 "%spec_int_8 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_7",
2046 "%spec_int_9 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_8",
2047 "%spec_int_10 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_9",
2048 "%spec_int_11 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_10",
2049 "%spec_int_12 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_11",
2050 "%spec_int_13 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_12",
2051 "%spec_int_14 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_13",
2052 "%spec_int_15 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_14",
2053 "%spec_int_16 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_15",
2054 "%spec_int_17 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_16",
2055 "%spec_int_18 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_17",
2056 "%spec_int_19 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_18",
2057 "%spec_int_20 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_19",
2058 "%used_vec_a = OpSpecConstantComposite %v2int %spec_int_18 %spec_int_19",
2059 "%used_vec_b = OpSpecConstantOp %v2int IMul %used_vec_a %used_vec_a",
2060 "%spec_int_21 = OpSpecConstantOp %int CompositeExtract %used_vec_b 0",
2061 "%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21",
2062 // Spec constants whose values can not be fully resolved should
2063 // not be processed.
2064 "%spec_int_22 = OpSpecConstant %int 123",
2065 "%spec_int_23 = OpSpecConstantOp %int IAdd %spec_int_22 %signed_one",
2066 },
2067 // expected
2068 {
2069 "%array_size = OpConstant %int 4",
2070 "%type_arr_int_4 = OpTypeArray %int %array_size",
2071 "%spec_int_0 = OpConstant %int 100",
2072 "%spec_int_1 = OpConstant %int 1",
2073 "%spec_int_2 = OpConstant %int 101",
2074 "%spec_int_3 = OpConstant %int -1",
2075 "%spec_int_4 = OpConstant %int 99",
2076 "%spec_int_5 = OpConstant %int 1",
2077 "%spec_int_6 = OpConstant %int 101",
2078 "%spec_int_7 = OpConstant %int -1",
2079 "%spec_int_8 = OpConstant %int 99",
2080 "%spec_int_9 = OpConstant %int 1",
2081 "%spec_int_10 = OpConstant %int 101",
2082 "%spec_int_11 = OpConstant %int -1",
2083 "%spec_int_12 = OpConstant %int 99",
2084 "%spec_int_13 = OpConstant %int 1",
2085 "%spec_int_14 = OpConstant %int 101",
2086 "%spec_int_15 = OpConstant %int -1",
2087 "%spec_int_16 = OpConstant %int 101",
2088 "%spec_int_17 = OpConstant %int 201",
2089 "%spec_int_18 = OpConstant %int -101",
2090 "%spec_int_19 = OpConstant %int -1",
2091 "%spec_int_20 = OpConstant %int 101",
2092 "%used_vec_a = OpConstantComposite %v2int %spec_int_18 %spec_int_19",
2093 "%int_10201 = OpConstant %int 10201",
2094 "%int_1 = OpConstant %int 1",
2095 "%used_vec_b = OpConstantComposite %v2int %int_10201 %signed_one",
2096 "%spec_int_21 = OpConstant %int 10201",
2097 "%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21",
2098 "%spec_int_22 = OpSpecConstant %int 123",
2099 "%spec_int_23 = OpSpecConstantOp %int IAdd %spec_int_22 %signed_one",
2100 },
2101 },
2102 // Long Def-Use chain with swizzle
2103 })));
2104
2105 } // namespace
2106 } // namespace opt
2107 } // namespace spvtools
2108