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 // All types and some common constants that are potentially required in
109 // FoldSpecConstantOpAndCompositeTest.
CommonTypesAndConstants()110 std::vector<std::string> CommonTypesAndConstants() {
111 return std::vector<std::string>{
112 // clang-format off
113 // scalar types
114 "%bool = OpTypeBool",
115 "%ushort = OpTypeInt 16 0",
116 "%short = OpTypeInt 16 1",
117 "%uint = OpTypeInt 32 0",
118 "%int = OpTypeInt 32 1",
119 "%ulong = OpTypeInt 64 0",
120 "%long = OpTypeInt 64 1",
121 "%float = OpTypeFloat 32",
122 "%double = OpTypeFloat 64",
123 // vector types
124 "%v2bool = OpTypeVector %bool 2",
125 "%v2uint = OpTypeVector %uint 2",
126 "%v2int = OpTypeVector %int 2",
127 "%v3int = OpTypeVector %int 3",
128 "%v4int = OpTypeVector %int 4",
129 "%v2long = OpTypeVector %long 2",
130 "%v2ulong = OpTypeVector %ulong 2",
131 "%v2float = OpTypeVector %float 2",
132 "%v2double = OpTypeVector %double 2",
133 // variable pointer types
134 "%_pf_bool = OpTypePointer Function %bool",
135 "%_pf_uint = OpTypePointer Function %uint",
136 "%_pf_int = OpTypePointer Function %int",
137 "%_pf_float = OpTypePointer Function %float",
138 "%_pf_double = OpTypePointer Function %double",
139 "%_pf_v2int = OpTypePointer Function %v2int",
140 "%_pf_v2float = OpTypePointer Function %v2float",
141 "%_pf_v2double = OpTypePointer Function %v2double",
142 // struct types
143 "%inner_struct = OpTypeStruct %bool %int %float",
144 "%outer_struct = OpTypeStruct %inner_struct %int",
145 "%flat_struct = OpTypeStruct %bool %int %float",
146
147 // common constants
148 // scalar constants:
149 "%bool_true = OpConstantTrue %bool",
150 "%bool_false = OpConstantFalse %bool",
151 "%bool_null = OpConstantNull %bool",
152 "%signed_zero = OpConstant %int 0",
153 "%unsigned_zero = OpConstant %uint 0",
154 "%long_zero = OpConstant %long 0",
155 "%ulong_zero = OpConstant %ulong 0",
156 "%signed_one = OpConstant %int 1",
157 "%unsigned_one = OpConstant %uint 1",
158 "%signed_two = OpConstant %int 2",
159 "%unsigned_two = OpConstant %uint 2",
160 "%signed_three = OpConstant %int 3",
161 "%unsigned_three = OpConstant %uint 3",
162 "%signed_null = OpConstantNull %int",
163 "%unsigned_null = OpConstantNull %uint",
164 "%signed_minus_one = OpConstant %int -1",
165 // vector constants:
166 "%bool_true_vec = OpConstantComposite %v2bool %bool_true %bool_true",
167 "%bool_false_vec = OpConstantComposite %v2bool %bool_false %bool_false",
168 "%bool_null_vec = OpConstantNull %v2bool",
169 "%signed_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
170 "%unsigned_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
171 "%signed_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
172 "%unsigned_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
173 "%signed_two_vec = OpConstantComposite %v2int %signed_two %signed_two",
174 "%unsigned_two_vec = OpConstantComposite %v2uint %unsigned_two %unsigned_two",
175 "%signed_three_vec = OpConstantComposite %v2int %signed_three %signed_three",
176 "%unsigned_three_vec = OpConstantComposite %v2uint %unsigned_three %unsigned_three",
177 "%signed_null_vec = OpConstantNull %v2int",
178 "%unsigned_null_vec = OpConstantNull %v2uint",
179 "%signed_minus_one_vec = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
180 "%v4int_0_1_2_3 = OpConstantComposite %v4int %signed_zero %signed_one %signed_two %signed_three",
181 // clang-format on
182 };
183 }
184
185 // A helper function to strip OpName instructions from the given string of
186 // disassembly code. Returns the string with all OpName instruction stripped.
StripOpNameInstructions(const std::string & str)187 std::string StripOpNameInstructions(const std::string& str) {
188 std::stringstream ss(str);
189 std::ostringstream oss;
190 std::string inst_str;
191 while (std::getline(ss, inst_str, '\n')) {
192 if (inst_str.find("OpName %") == std::string::npos) {
193 oss << inst_str << '\n';
194 }
195 }
196 return oss.str();
197 }
198
199 struct FoldSpecConstantOpAndCompositePassTestCase {
200 // Original constants with unfolded spec constants.
201 std::vector<std::string> original;
202 // Expected cosntants after folding.
203 std::vector<std::string> expected;
204 };
205
206 using FoldSpecConstantOpAndCompositePassTest = PassTest<
207 ::testing::TestWithParam<FoldSpecConstantOpAndCompositePassTestCase>>;
208
TEST_P(FoldSpecConstantOpAndCompositePassTest,ParamTestCase)209 TEST_P(FoldSpecConstantOpAndCompositePassTest, ParamTestCase) {
210 AssemblyBuilder test_code_builder, expected_code_builder;
211 const auto& tc = GetParam();
212 test_code_builder.AppendTypesConstantsGlobals(CommonTypesAndConstants());
213 test_code_builder.AppendTypesConstantsGlobals(tc.original);
214 expected_code_builder.AppendTypesConstantsGlobals(CommonTypesAndConstants());
215 expected_code_builder.AppendTypesConstantsGlobals(tc.expected);
216 const std::string original = test_code_builder.GetCode();
217 const std::string expected = expected_code_builder.GetCode();
218
219 // Run the optimization and get the result code in disassembly.
220 std::string optimized;
221 auto status = Pass::Status::SuccessWithoutChange;
222 std::tie(optimized, status) =
223 SinglePassRunAndDisassemble<FoldSpecConstantOpAndCompositePass>(
224 original, /* skip_nop = */ true, /* do_validation = */ false);
225
226 // Check the optimized code, but ignore the OpName instructions.
227 EXPECT_NE(Pass::Status::Failure, status);
228 EXPECT_EQ(
229 StripOpNameInstructions(expected) == StripOpNameInstructions(original),
230 status == Pass::Status::SuccessWithoutChange);
231 EXPECT_EQ(StripOpNameInstructions(expected),
232 StripOpNameInstructions(optimized));
233 }
234
235 // Tests that OpSpecConstantComposite opcodes are replace with
236 // OpConstantComposite correctly.
237 INSTANTIATE_TEST_SUITE_P(
238 Composite, FoldSpecConstantOpAndCompositePassTest,
239 ::testing::ValuesIn(std::vector<
240 FoldSpecConstantOpAndCompositePassTestCase>({
241 // clang-format off
242 // normal vector
243 {
244 // original
245 {
246 "%spec_v2bool = OpSpecConstantComposite %v2bool %bool_true %bool_false",
247 "%spec_v2uint = OpSpecConstantComposite %v2uint %unsigned_one %unsigned_one",
248 "%spec_v2int_a = OpSpecConstantComposite %v2int %signed_one %signed_two",
249 // Spec constants whose value can not be fully resolved should
250 // not be processed.
251 "%spec_int = OpSpecConstant %int 99",
252 "%spec_v2int_b = OpSpecConstantComposite %v2int %signed_one %spec_int",
253 },
254 // expected
255 {
256 "%spec_v2bool = OpConstantComposite %v2bool %bool_true %bool_false",
257 "%spec_v2uint = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
258 "%spec_v2int_a = OpConstantComposite %v2int %signed_one %signed_two",
259 "%spec_int = OpSpecConstant %int 99",
260 "%spec_v2int_b = OpSpecConstantComposite %v2int %signed_one %spec_int",
261 },
262 },
263 // vector with null constants
264 {
265 // original
266 {
267 "%null_bool = OpConstantNull %bool",
268 "%null_int = OpConstantNull %int",
269 "%spec_v2bool = OpSpecConstantComposite %v2bool %null_bool %null_bool",
270 "%spec_v3int = OpSpecConstantComposite %v3int %null_int %null_int %null_int",
271 "%spec_v4int = OpSpecConstantComposite %v4int %null_int %null_int %null_int %null_int",
272 },
273 // expected
274 {
275 "%null_bool = OpConstantNull %bool",
276 "%null_int = OpConstantNull %int",
277 "%spec_v2bool = OpConstantComposite %v2bool %null_bool %null_bool",
278 "%spec_v3int = OpConstantComposite %v3int %null_int %null_int %null_int",
279 "%spec_v4int = OpConstantComposite %v4int %null_int %null_int %null_int %null_int",
280 },
281 },
282 // flat struct
283 {
284 // original
285 {
286 "%float_1 = OpConstant %float 1",
287 "%flat_1 = OpSpecConstantComposite %flat_struct %bool_true %signed_null %float_1",
288 // following struct should not be folded as the value of
289 // %spec_float is not determined.
290 "%spec_float = OpSpecConstant %float 1",
291 "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_one %spec_float",
292 },
293 // expected
294 {
295 "%float_1 = OpConstant %float 1",
296 "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
297 "%spec_float = OpSpecConstant %float 1",
298 "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_one %spec_float",
299 }
300 },
301 // nested struct
302 {
303 // original
304 {
305 "%float_1 = OpConstant %float 1",
306 "%inner_1 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %float_1",
307 "%outer_1 = OpSpecConstantComposite %outer_struct %inner_1 %signed_one",
308 // following structs should not be folded as the value of
309 // %spec_float is not determined.
310 "%spec_float = OpSpecConstant %float 1",
311 "%inner_2 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
312 "%outer_2 = OpSpecConstantComposite %outer_struct %inner_2 %signed_one",
313 },
314 // expected
315 {
316 "%float_1 = OpConstant %float 1",
317 "%inner_1 = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
318 "%outer_1 = OpConstantComposite %outer_struct %inner_1 %signed_one",
319 "%spec_float = OpSpecConstant %float 1",
320 "%inner_2 = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
321 "%outer_2 = OpSpecConstantComposite %outer_struct %inner_2 %signed_one",
322 }
323 },
324 // composite constants touched by OpUndef should be skipped
325 {
326 // original
327 {
328 "%undef = OpUndef %float",
329 "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
330 "%outer = OpSpecConstantComposite %outer_struct %inner %signed_one",
331 },
332 // expected
333 {
334 "%undef = OpUndef %float",
335 "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
336 "%outer = OpSpecConstantComposite %outer_struct %inner %signed_one",
337 },
338 },
339 // Fold an QuantizetoF16 instruction
340 {
341 // original
342 {
343 "%float_1 = OpConstant %float 1",
344 "%quant_float = OpSpecConstantOp %float QuantizeToF16 %float_1",
345 },
346 // expected
347 {
348 "%float_1 = OpConstant %float 1",
349 "%quant_float = OpConstant %float 1",
350 },
351 }
352 // clang-format on
353 })));
354
355 // Tests for operations that resulting in different types.
356 INSTANTIATE_TEST_SUITE_P(
357 Cast, FoldSpecConstantOpAndCompositePassTest,
358 ::testing::ValuesIn(std::vector<
359 FoldSpecConstantOpAndCompositePassTestCase>({
360 // clang-format off
361 // int -> bool scalar
362 {
363 // original
364 {
365 "%spec_bool_t = OpSpecConstantOp %bool INotEqual %signed_three %signed_zero",
366 "%spec_bool_f = OpSpecConstantOp %bool INotEqual %signed_zero %signed_zero",
367 "%spec_bool_from_null = OpSpecConstantOp %bool INotEqual %signed_null %signed_zero",
368 },
369 // expected
370 {
371 "%spec_bool_t = OpConstantTrue %bool",
372 "%spec_bool_f = OpConstantFalse %bool",
373 "%spec_bool_from_null = OpConstantFalse %bool",
374 },
375 },
376
377 // uint -> bool scalar
378 {
379 // original
380 {
381 "%spec_bool_t = OpSpecConstantOp %bool INotEqual %unsigned_three %unsigned_zero",
382 "%spec_bool_f = OpSpecConstantOp %bool INotEqual %unsigned_zero %unsigned_zero",
383 "%spec_bool_from_null = OpSpecConstantOp %bool INotEqual %unsigned_null %unsigned_zero",
384 },
385 // expected
386 {
387 "%spec_bool_t = OpConstantTrue %bool",
388 "%spec_bool_f = OpConstantFalse %bool",
389 "%spec_bool_from_null = OpConstantFalse %bool",
390 },
391 },
392
393 // bool -> int scalar
394 {
395 // original
396 {
397 "%spec_int_one = OpSpecConstantOp %int Select %bool_true %signed_one %signed_zero",
398 "%spec_int_zero = OpSpecConstantOp %int Select %bool_false %signed_one %signed_zero",
399 "%spec_int_from_null = OpSpecConstantOp %int Select %bool_null %signed_one %signed_zero",
400 },
401 // expected
402 {
403 "%spec_int_one = OpConstant %int 1",
404 "%spec_int_zero = OpConstant %int 0",
405 "%spec_int_from_null = OpConstant %int 0",
406 },
407 },
408
409 // uint -> int scalar
410 {
411 // original
412 {
413 "%spec_int_one = OpSpecConstantOp %int IAdd %unsigned_one %signed_zero",
414 "%spec_int_zero = OpSpecConstantOp %int IAdd %unsigned_zero %signed_zero",
415 "%spec_int_from_null = OpSpecConstantOp %int IAdd %unsigned_null %unsigned_zero",
416 },
417 // expected
418 {
419 "%spec_int_one = OpConstant %int 1",
420 "%spec_int_zero = OpConstant %int 0",
421 "%spec_int_from_null = OpConstant %int 0",
422 },
423 },
424
425 // bool -> uint scalar
426 {
427 // original
428 {
429 "%spec_uint_one = OpSpecConstantOp %uint Select %bool_true %unsigned_one %unsigned_zero",
430 "%spec_uint_zero = OpSpecConstantOp %uint Select %bool_false %unsigned_one %unsigned_zero",
431 "%spec_uint_from_null = OpSpecConstantOp %uint Select %bool_null %unsigned_one %unsigned_zero",
432 },
433 // expected
434 {
435 "%spec_uint_one = OpConstant %uint 1",
436 "%spec_uint_zero = OpConstant %uint 0",
437 "%spec_uint_from_null = OpConstant %uint 0",
438 },
439 },
440
441 // int -> uint scalar
442 {
443 // original
444 {
445 "%spec_uint_one = OpSpecConstantOp %uint IAdd %signed_one %unsigned_zero",
446 "%spec_uint_zero = OpSpecConstantOp %uint IAdd %signed_zero %unsigned_zero",
447 "%spec_uint_from_null = OpSpecConstantOp %uint IAdd %signed_null %unsigned_zero",
448 },
449 // expected
450 {
451 "%spec_uint_one = OpConstant %uint 1",
452 "%spec_uint_zero = OpConstant %uint 0",
453 "%spec_uint_from_null = OpConstant %uint 0",
454 },
455 },
456
457 // int -> bool vector
458 {
459 // original
460 {
461 "%spec_bool_t_vec = OpSpecConstantOp %v2bool INotEqual %signed_three_vec %signed_zero_vec",
462 "%spec_bool_f_vec = OpSpecConstantOp %v2bool INotEqual %signed_zero_vec %signed_zero_vec",
463 "%spec_bool_from_null = OpSpecConstantOp %v2bool INotEqual %signed_null_vec %signed_zero_vec",
464 },
465 // expected
466 {
467 "%true = OpConstantTrue %bool",
468 "%true_0 = OpConstantTrue %bool",
469 "%spec_bool_t_vec = OpConstantComposite %v2bool %bool_true %bool_true",
470 "%false = OpConstantFalse %bool",
471 "%false_0 = OpConstantFalse %bool",
472 "%spec_bool_f_vec = OpConstantComposite %v2bool %bool_false %bool_false",
473 "%false_1 = OpConstantFalse %bool",
474 "%false_2 = OpConstantFalse %bool",
475 "%spec_bool_from_null = OpConstantComposite %v2bool %bool_false %bool_false",
476 },
477 },
478
479 // uint -> bool vector
480 {
481 // original
482 {
483 "%spec_bool_t_vec = OpSpecConstantOp %v2bool INotEqual %unsigned_three_vec %unsigned_zero_vec",
484 "%spec_bool_f_vec = OpSpecConstantOp %v2bool INotEqual %unsigned_zero_vec %unsigned_zero_vec",
485 "%spec_bool_from_null = OpSpecConstantOp %v2bool INotEqual %unsigned_null_vec %unsigned_zero_vec",
486 },
487 // expected
488 {
489 "%true = OpConstantTrue %bool",
490 "%true_0 = OpConstantTrue %bool",
491 "%spec_bool_t_vec = OpConstantComposite %v2bool %bool_true %bool_true",
492 "%false = OpConstantFalse %bool",
493 "%false_0 = OpConstantFalse %bool",
494 "%spec_bool_f_vec = OpConstantComposite %v2bool %bool_false %bool_false",
495 "%false_1 = OpConstantFalse %bool",
496 "%false_2 = OpConstantFalse %bool",
497 "%spec_bool_from_null = OpConstantComposite %v2bool %bool_false %bool_false",
498 },
499 },
500
501 // bool -> int vector
502 {
503 // original
504 {
505 "%spec_int_one_vec = OpSpecConstantOp %v2int Select %bool_true_vec %signed_one_vec %signed_zero_vec",
506 "%spec_int_zero_vec = OpSpecConstantOp %v2int Select %bool_false_vec %signed_one_vec %signed_zero_vec",
507 "%spec_int_from_null = OpSpecConstantOp %v2int Select %bool_null_vec %signed_one_vec %signed_zero_vec",
508 },
509 // expected
510 {
511 "%int_1 = OpConstant %int 1",
512 "%int_1_0 = OpConstant %int 1",
513 "%spec_int_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
514 "%int_0 = OpConstant %int 0",
515 "%int_0_0 = OpConstant %int 0",
516 "%spec_int_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
517 "%int_0_1 = OpConstant %int 0",
518 "%int_0_2 = OpConstant %int 0",
519 "%spec_int_from_null = OpConstantComposite %v2int %signed_zero %signed_zero",
520 },
521 },
522
523 // uint -> int vector
524 {
525 // original
526 {
527 "%spec_int_one_vec = OpSpecConstantOp %v2int IAdd %unsigned_one_vec %signed_zero_vec",
528 "%spec_int_zero_vec = OpSpecConstantOp %v2int IAdd %unsigned_zero_vec %signed_zero_vec",
529 "%spec_int_from_null = OpSpecConstantOp %v2int IAdd %unsigned_null_vec %signed_zero_vec",
530 },
531 // expected
532 {
533 "%int_1 = OpConstant %int 1",
534 "%int_1_0 = OpConstant %int 1",
535 "%spec_int_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
536 "%int_0 = OpConstant %int 0",
537 "%int_0_0 = OpConstant %int 0",
538 "%spec_int_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
539 "%int_0_1 = OpConstant %int 0",
540 "%int_0_2 = OpConstant %int 0",
541 "%spec_int_from_null = OpConstantComposite %v2int %signed_zero %signed_zero",
542 },
543 },
544
545 // bool -> uint vector
546 {
547 // original
548 {
549 "%spec_uint_one_vec = OpSpecConstantOp %v2uint Select %bool_true_vec %unsigned_one_vec %unsigned_zero_vec",
550 "%spec_uint_zero_vec = OpSpecConstantOp %v2uint Select %bool_false_vec %unsigned_one_vec %unsigned_zero_vec",
551 "%spec_uint_from_null = OpSpecConstantOp %v2uint Select %bool_null_vec %unsigned_one_vec %unsigned_zero_vec",
552 },
553 // expected
554 {
555 "%uint_1 = OpConstant %uint 1",
556 "%uint_1_0 = OpConstant %uint 1",
557 "%spec_uint_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
558 "%uint_0 = OpConstant %uint 0",
559 "%uint_0_0 = OpConstant %uint 0",
560 "%spec_uint_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
561 "%uint_0_1 = OpConstant %uint 0",
562 "%uint_0_2 = OpConstant %uint 0",
563 "%spec_uint_from_null = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
564 },
565 },
566
567 // int -> uint vector
568 {
569 // original
570 {
571 "%spec_uint_one_vec = OpSpecConstantOp %v2uint IAdd %signed_one_vec %unsigned_zero_vec",
572 "%spec_uint_zero_vec = OpSpecConstantOp %v2uint IAdd %signed_zero_vec %unsigned_zero_vec",
573 "%spec_uint_from_null = OpSpecConstantOp %v2uint IAdd %signed_null_vec %unsigned_zero_vec",
574 },
575 // expected
576 {
577 "%uint_1 = OpConstant %uint 1",
578 "%uint_1_0 = OpConstant %uint 1",
579 "%spec_uint_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
580 "%uint_0 = OpConstant %uint 0",
581 "%uint_0_0 = OpConstant %uint 0",
582 "%spec_uint_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
583 "%uint_0_1 = OpConstant %uint 0",
584 "%uint_0_2 = OpConstant %uint 0",
585 "%spec_uint_from_null = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
586 },
587 },
588
589 // UConvert scalar
590 {
591 // original
592 {
593 "%spec_uint_zero = OpSpecConstantOp %uint UConvert %bool_false",
594 "%spec_uint_one = OpSpecConstantOp %uint UConvert %bool_true",
595 "%spec_ulong_zero = OpSpecConstantOp %ulong UConvert %unsigned_zero",
596 "%spec_ulong_one = OpSpecConstantOp %ulong UConvert %unsigned_one",
597 "%spec_short_zero = OpSpecConstantOp %ushort UConvert %unsigned_zero",
598 "%spec_short_one = OpSpecConstantOp %ushort UConvert %unsigned_one",
599 "%uint_max = OpConstant %uint 4294967295",
600 "%spec_ushort_max = OpSpecConstantOp %ushort UConvert %uint_max",
601 "%uint_0xDDDDDDDD = OpConstant %uint 3722304989",
602 "%spec_ushort_0xDDDD = OpSpecConstantOp %ushort UConvert %uint_0xDDDDDDDD",
603 },
604 // expected
605 {
606 "%spec_uint_zero = OpConstant %uint 0",
607 "%spec_uint_one = OpConstant %uint 1",
608 "%spec_ulong_zero = OpConstant %ulong 0",
609 "%spec_ulong_one = OpConstant %ulong 1",
610 "%spec_short_zero = OpConstant %ushort 0",
611 "%spec_short_one = OpConstant %ushort 1",
612 "%uint_max = OpConstant %uint 4294967295",
613 "%spec_ushort_max = OpConstant %ushort 65535",
614 "%uint_0xDDDDDDDD = OpConstant %uint 3722304989",
615 "%spec_ushort_0xDDDD = OpConstant %ushort 56797",
616 },
617 },
618
619 // SConvert scalar
620 {
621 // original
622 {
623 "%spec_long_zero = OpSpecConstantOp %long SConvert %signed_zero",
624 "%spec_long_one = OpSpecConstantOp %long SConvert %signed_one",
625 "%spec_long_minus_one = OpSpecConstantOp %long SConvert %signed_minus_one",
626 "%spec_short_minus_one_trunc = OpSpecConstantOp %short SConvert %signed_minus_one",
627 "%int_2_to_17_minus_one = OpConstant %int 131071",
628 "%spec_short_minus_one_trunc2 = OpSpecConstantOp %short SConvert %int_2_to_17_minus_one",
629 },
630 // expected
631 {
632 "%spec_long_zero = OpConstant %long 0",
633 "%spec_long_one = OpConstant %long 1",
634 "%spec_long_minus_one = OpConstant %long -1",
635 "%spec_short_minus_one_trunc = OpConstant %short -1",
636 "%int_2_to_17_minus_one = OpConstant %int 131071",
637 "%spec_short_minus_one_trunc2 = OpConstant %short -1",
638 },
639 },
640
641 // UConvert vector
642 {
643 // original
644 {
645 "%spec_v2uint_zero = OpSpecConstantOp %v2uint UConvert %bool_false_vec",
646 "%spec_v2uint_one = OpSpecConstantOp %v2uint UConvert %bool_true_vec",
647 "%spec_v2ulong_zero = OpSpecConstantOp %v2ulong UConvert %unsigned_zero_vec",
648 "%spec_v2ulong_one = OpSpecConstantOp %v2ulong UConvert %unsigned_one_vec",
649 },
650 // expected
651 {
652 "%uint_0 = OpConstant %uint 0",
653 "%uint_0_0 = OpConstant %uint 0",
654 "%spec_v2uint_zero = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
655 "%uint_1 = OpConstant %uint 1",
656 "%uint_1_0 = OpConstant %uint 1",
657 "%spec_v2uint_one = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
658 "%ulong_0 = OpConstant %ulong 0",
659 "%ulong_0_0 = OpConstant %ulong 0",
660 "%spec_v2ulong_zero = OpConstantComposite %v2ulong %ulong_zero %ulong_zero",
661 "%ulong_1 = OpConstant %ulong 1",
662 "%ulong_1_0 = OpConstant %ulong 1",
663 "%spec_v2ulong_one = OpConstantComposite %v2ulong %ulong_1 %ulong_1",
664 },
665 },
666
667 // SConvert vector
668 {
669 // original
670 {
671 "%spec_v2long_zero = OpSpecConstantOp %v2long SConvert %signed_zero_vec",
672 "%spec_v2long_one = OpSpecConstantOp %v2long SConvert %signed_one_vec",
673 "%spec_v2long_minus_one = OpSpecConstantOp %v2long SConvert %signed_minus_one_vec",
674 },
675 // expected
676 {
677 "%long_0 = OpConstant %long 0",
678 "%long_0_0 = OpConstant %long 0",
679 "%spec_v2long_zero = OpConstantComposite %v2long %long_zero %long_zero",
680 "%long_1 = OpConstant %long 1",
681 "%long_1_0 = OpConstant %long 1",
682 "%spec_v2long_one = OpConstantComposite %v2long %long_1 %long_1",
683 "%long_n1 = OpConstant %long -1",
684 "%long_n1_0 = OpConstant %long -1",
685 "%spec_v2long_minus_one = OpConstantComposite %v2long %long_n1 %long_n1",
686 },
687 },
688 // clang-format on
689 })));
690
691 // Tests about boolean scalar logical operations and comparison operations with
692 // scalar int/uint type.
693 INSTANTIATE_TEST_SUITE_P(
694 Logical, FoldSpecConstantOpAndCompositePassTest,
695 ::testing::ValuesIn(std::vector<
696 FoldSpecConstantOpAndCompositePassTestCase>({
697 // clang-format off
698 // scalar integer comparison
699 {
700 // original
701 {
702 "%int_minus_1 = OpConstant %int -1",
703
704 "%slt_0_1 = OpSpecConstantOp %bool SLessThan %signed_zero %signed_one",
705 "%sgt_0_1 = OpSpecConstantOp %bool SGreaterThan %signed_zero %signed_one",
706 "%sle_2_2 = OpSpecConstantOp %bool SLessThanEqual %signed_two %signed_two",
707 "%sge_2_1 = OpSpecConstantOp %bool SGreaterThanEqual %signed_two %signed_one",
708 "%sge_2_null = OpSpecConstantOp %bool SGreaterThanEqual %signed_two %signed_null",
709 "%sge_minus_1_null = OpSpecConstantOp %bool SGreaterThanEqual %int_minus_1 %signed_null",
710
711 "%ult_0_1 = OpSpecConstantOp %bool ULessThan %unsigned_zero %unsigned_one",
712 "%ugt_0_1 = OpSpecConstantOp %bool UGreaterThan %unsigned_zero %unsigned_one",
713 "%ule_2_3 = OpSpecConstantOp %bool ULessThanEqual %unsigned_two %unsigned_three",
714 "%uge_1_1 = OpSpecConstantOp %bool UGreaterThanEqual %unsigned_one %unsigned_one",
715 "%uge_2_null = OpSpecConstantOp %bool UGreaterThanEqual %unsigned_two %unsigned_null",
716 "%uge_minus_1_null = OpSpecConstantOp %bool UGreaterThanEqual %int_minus_1 %unsigned_null",
717 },
718 // expected
719 {
720 "%int_minus_1 = OpConstant %int -1",
721
722 "%slt_0_1 = OpConstantTrue %bool",
723 "%sgt_0_1 = OpConstantFalse %bool",
724 "%sle_2_2 = OpConstantTrue %bool",
725 "%sge_2_1 = OpConstantTrue %bool",
726 "%sge_2_null = OpConstantTrue %bool",
727 "%sge_minus_1_null = OpConstantFalse %bool",
728
729 "%ult_0_1 = OpConstantTrue %bool",
730 "%ugt_0_1 = OpConstantFalse %bool",
731 "%ule_2_3 = OpConstantTrue %bool",
732 "%uge_1_1 = OpConstantTrue %bool",
733 "%uge_2_null = OpConstantTrue %bool",
734 "%uge_minus_1_null = OpConstantTrue %bool",
735 },
736 },
737 // Logical and, or, xor.
738 {
739 // original
740 {
741 "%logical_or = OpSpecConstantOp %bool LogicalOr %bool_true %bool_false",
742 "%logical_and = OpSpecConstantOp %bool LogicalAnd %bool_true %bool_false",
743 "%logical_not = OpSpecConstantOp %bool LogicalNot %bool_true",
744 "%logical_eq = OpSpecConstantOp %bool LogicalEqual %bool_true %bool_true",
745 "%logical_neq = OpSpecConstantOp %bool LogicalNotEqual %bool_true %bool_true",
746 "%logical_and_null = OpSpecConstantOp %bool LogicalAnd %bool_true %bool_null",
747 },
748 // expected
749 {
750 "%logical_or = OpConstantTrue %bool",
751 "%logical_and = OpConstantFalse %bool",
752 "%logical_not = OpConstantFalse %bool",
753 "%logical_eq = OpConstantTrue %bool",
754 "%logical_neq = OpConstantFalse %bool",
755 "%logical_and_null = OpConstantFalse %bool",
756 },
757 },
758 // clang-format on
759 })));
760
761 // Tests about arithmetic operations for scalar int and uint types.
762 INSTANTIATE_TEST_SUITE_P(
763 ScalarArithmetic, FoldSpecConstantOpAndCompositePassTest,
764 ::testing::ValuesIn(std::vector<
765 FoldSpecConstantOpAndCompositePassTestCase>({
766 // clang-format off
767 // scalar integer negate
768 {
769 // original
770 {
771 "%int_minus_1 = OpSpecConstantOp %int SNegate %signed_one",
772 "%int_minus_2 = OpSpecConstantOp %int SNegate %signed_two",
773 "%int_neg_null = OpSpecConstantOp %int SNegate %signed_null",
774 "%int_max = OpConstant %int 2147483647",
775 "%int_neg_max = OpSpecConstantOp %int SNegate %int_max",
776 },
777 // expected
778 {
779 "%int_minus_1 = OpConstant %int -1",
780 "%int_minus_2 = OpConstant %int -2",
781 "%int_neg_null = OpConstant %int 0",
782 "%int_max = OpConstant %int 2147483647",
783 "%int_neg_max = OpConstant %int -2147483647",
784 },
785 },
786 // scalar integer not
787 {
788 // original
789 {
790 "%uint_4294967294 = OpSpecConstantOp %uint Not %unsigned_one",
791 "%uint_4294967293 = OpSpecConstantOp %uint Not %unsigned_two",
792 "%uint_neg_null = OpSpecConstantOp %uint Not %unsigned_null",
793 },
794 // expected
795 {
796 "%uint_4294967294 = OpConstant %uint 4294967294",
797 "%uint_4294967293 = OpConstant %uint 4294967293",
798 "%uint_neg_null = OpConstant %uint 4294967295",
799 },
800 },
801 // scalar integer add, sub, mul, div
802 {
803 // original
804 {
805 "%signed_max = OpConstant %int 2147483647",
806 "%signed_min = OpConstant %int -2147483648",
807
808 "%spec_int_iadd = OpSpecConstantOp %int IAdd %signed_three %signed_two",
809 "%spec_int_isub = OpSpecConstantOp %int ISub %signed_one %spec_int_iadd",
810 "%spec_int_sdiv = OpSpecConstantOp %int SDiv %spec_int_isub %signed_two",
811 "%spec_int_imul = OpSpecConstantOp %int IMul %spec_int_sdiv %signed_three",
812 "%spec_int_iadd_null = OpSpecConstantOp %int IAdd %spec_int_imul %signed_null",
813 "%spec_int_imul_null = OpSpecConstantOp %int IMul %spec_int_iadd_null %signed_null",
814 "%spec_int_iadd_overflow = OpSpecConstantOp %int IAdd %signed_max %signed_three",
815 "%spec_int_isub_overflow = OpSpecConstantOp %int ISub %signed_min %signed_three",
816
817 "%spec_uint_iadd = OpSpecConstantOp %uint IAdd %unsigned_three %unsigned_two",
818 "%spec_uint_isub = OpSpecConstantOp %uint ISub %unsigned_one %spec_uint_iadd",
819 "%spec_uint_udiv = OpSpecConstantOp %uint UDiv %spec_uint_isub %unsigned_three",
820 "%spec_uint_imul = OpSpecConstantOp %uint IMul %spec_uint_udiv %unsigned_two",
821 "%spec_uint_isub_null = OpSpecConstantOp %uint ISub %spec_uint_imul %signed_null",
822 },
823 // expected
824 {
825 "%signed_max = OpConstant %int 2147483647",
826 "%signed_min = OpConstant %int -2147483648",
827
828 "%spec_int_iadd = OpConstant %int 5",
829 "%spec_int_isub = OpConstant %int -4",
830 "%spec_int_sdiv = OpConstant %int -2",
831 "%spec_int_imul = OpConstant %int -6",
832 "%spec_int_iadd_null = OpConstant %int -6",
833 "%spec_int_imul_null = OpConstant %int 0",
834 "%spec_int_iadd_overflow = OpConstant %int -2147483646",
835 "%spec_int_isub_overflow = OpConstant %int 2147483645",
836
837 "%spec_uint_iadd = OpConstant %uint 5",
838 "%spec_uint_isub = OpConstant %uint 4294967292",
839 "%spec_uint_udiv = OpConstant %uint 1431655764",
840 "%spec_uint_imul = OpConstant %uint 2863311528",
841 "%spec_uint_isub_null = OpConstant %uint 2863311528",
842 },
843 },
844 // scalar integer rem, mod
845 {
846 // original
847 {
848 // common constants
849 "%int_7 = OpConstant %int 7",
850 "%uint_7 = OpConstant %uint 7",
851 "%int_minus_7 = OpConstant %int -7",
852 "%int_minus_3 = OpConstant %int -3",
853
854 // srem
855 "%7_srem_3 = OpSpecConstantOp %int SRem %int_7 %signed_three",
856 "%minus_7_srem_3 = OpSpecConstantOp %int SRem %int_minus_7 %signed_three",
857 "%7_srem_minus_3 = OpSpecConstantOp %int SRem %int_7 %int_minus_3",
858 "%minus_7_srem_minus_3 = OpSpecConstantOp %int SRem %int_minus_7 %int_minus_3",
859 // smod
860 "%7_smod_3 = OpSpecConstantOp %int SMod %int_7 %signed_three",
861 "%minus_7_smod_3 = OpSpecConstantOp %int SMod %int_minus_7 %signed_three",
862 "%7_smod_minus_3 = OpSpecConstantOp %int SMod %int_7 %int_minus_3",
863 "%minus_7_smod_minus_3 = OpSpecConstantOp %int SMod %int_minus_7 %int_minus_3",
864 // umod
865 "%7_umod_3 = OpSpecConstantOp %uint UMod %uint_7 %unsigned_three",
866 // null constant
867 "%null_srem_3 = OpSpecConstantOp %int SRem %signed_null %signed_three",
868 "%null_smod_3 = OpSpecConstantOp %int SMod %signed_null %signed_three",
869 "%null_umod_3 = OpSpecConstantOp %uint UMod %unsigned_null %unsigned_three",
870 },
871 // expected
872 {
873 // common constants
874 "%int_7 = OpConstant %int 7",
875 "%uint_7 = OpConstant %uint 7",
876 "%int_minus_7 = OpConstant %int -7",
877 "%int_minus_3 = OpConstant %int -3",
878
879 // srem
880 "%7_srem_3 = OpConstant %int 1",
881 "%minus_7_srem_3 = OpConstant %int -1",
882 "%7_srem_minus_3 = OpConstant %int 1",
883 "%minus_7_srem_minus_3 = OpConstant %int -1",
884 // smod
885 "%7_smod_3 = OpConstant %int 1",
886 "%minus_7_smod_3 = OpConstant %int 2",
887 "%7_smod_minus_3 = OpConstant %int -2",
888 "%minus_7_smod_minus_3 = OpConstant %int -1",
889 // umod
890 "%7_umod_3 = OpConstant %uint 1",
891 // null constant
892 "%null_srem_3 = OpConstant %int 0",
893 "%null_smod_3 = OpConstant %int 0",
894 "%null_umod_3 = OpConstant %uint 0",
895 },
896 },
897 // scalar integer bitwise and shift
898 {
899 // original
900 {
901 // bitwise
902 "%xor_1_3 = OpSpecConstantOp %int BitwiseXor %signed_one %signed_three",
903 "%and_1_2 = OpSpecConstantOp %int BitwiseAnd %signed_one %xor_1_3",
904 "%or_1_2 = OpSpecConstantOp %int BitwiseOr %signed_one %xor_1_3",
905 "%xor_3_null = OpSpecConstantOp %int BitwiseXor %or_1_2 %signed_null",
906
907 // shift
908 "%unsigned_31 = OpConstant %uint 31",
909 "%unsigned_left_shift_max = OpSpecConstantOp %uint ShiftLeftLogical %unsigned_one %unsigned_31",
910 "%unsigned_right_shift_logical = OpSpecConstantOp %uint ShiftRightLogical %unsigned_left_shift_max %unsigned_31",
911 "%signed_right_shift_arithmetic = OpSpecConstantOp %int ShiftRightArithmetic %unsigned_left_shift_max %unsigned_31",
912 "%left_shift_null_31 = OpSpecConstantOp %uint ShiftLeftLogical %unsigned_null %unsigned_31",
913 "%right_shift_31_null = OpSpecConstantOp %uint ShiftRightLogical %unsigned_31 %unsigned_null",
914 },
915 // expected
916 {
917 "%xor_1_3 = OpConstant %int 2",
918 "%and_1_2 = OpConstant %int 0",
919 "%or_1_2 = OpConstant %int 3",
920 "%xor_3_null = OpConstant %int 3",
921
922 "%unsigned_31 = OpConstant %uint 31",
923 "%unsigned_left_shift_max = OpConstant %uint 2147483648",
924 "%unsigned_right_shift_logical = OpConstant %uint 1",
925 "%signed_right_shift_arithmetic = OpConstant %int -1",
926 "%left_shift_null_31 = OpConstant %uint 0",
927 "%right_shift_31_null = OpConstant %uint 31",
928 },
929 },
930 // Skip folding if any operands have undetermined value.
931 {
932 // original
933 {
934 "%spec_int = OpSpecConstant %int 1",
935 "%spec_iadd = OpSpecConstantOp %int IAdd %signed_three %spec_int",
936 },
937 // expected
938 {
939 "%spec_int = OpSpecConstant %int 1",
940 "%spec_iadd = OpSpecConstantOp %int IAdd %signed_three %spec_int",
941 },
942 },
943 // clang-format on
944 })));
945
946 // Tests about arithmetic operations for vector int and uint types.
947 INSTANTIATE_TEST_SUITE_P(
948 VectorArithmetic, FoldSpecConstantOpAndCompositePassTest,
949 ::testing::ValuesIn(std::vector<
950 FoldSpecConstantOpAndCompositePassTestCase>({
951 // clang-format off
952 // vector integer negate
953 {
954 // original
955 {
956 "%v2int_minus_1 = OpSpecConstantOp %v2int SNegate %signed_one_vec",
957 "%v2int_minus_2 = OpSpecConstantOp %v2int SNegate %signed_two_vec",
958 "%v2int_neg_null = OpSpecConstantOp %v2int SNegate %signed_null_vec",
959 },
960 // expected
961 {
962 "%int_n1 = OpConstant %int -1",
963 "%int_n1_0 = OpConstant %int -1",
964 "%v2int_minus_1 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
965 "%int_n2 = OpConstant %int -2",
966 "%int_n2_0 = OpConstant %int -2",
967 "%v2int_minus_2 = OpConstantComposite %v2int %int_n2 %int_n2",
968 "%int_0 = OpConstant %int 0",
969 "%int_0_0 = OpConstant %int 0",
970 "%v2int_neg_null = OpConstantComposite %v2int %signed_zero %signed_zero",
971 },
972 },
973 // vector integer (including null vetors) add, sub, div, mul
974 {
975 // original
976 {
977 "%spec_v2int_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %signed_two_vec",
978 "%spec_v2int_isub = OpSpecConstantOp %v2int ISub %signed_one_vec %spec_v2int_iadd",
979 "%spec_v2int_sdiv = OpSpecConstantOp %v2int SDiv %spec_v2int_isub %signed_two_vec",
980 "%spec_v2int_imul = OpSpecConstantOp %v2int IMul %spec_v2int_sdiv %signed_three_vec",
981 "%spec_v2int_iadd_null = OpSpecConstantOp %v2int IAdd %spec_v2int_imul %signed_null_vec",
982
983 "%spec_v2uint_iadd = OpSpecConstantOp %v2uint IAdd %unsigned_three_vec %unsigned_two_vec",
984 "%spec_v2uint_isub = OpSpecConstantOp %v2uint ISub %unsigned_one_vec %spec_v2uint_iadd",
985 "%spec_v2uint_udiv = OpSpecConstantOp %v2uint UDiv %spec_v2uint_isub %unsigned_three_vec",
986 "%spec_v2uint_imul = OpSpecConstantOp %v2uint IMul %spec_v2uint_udiv %unsigned_two_vec",
987 "%spec_v2uint_isub_null = OpSpecConstantOp %v2uint ISub %spec_v2uint_imul %signed_null_vec",
988 },
989 // expected
990 {
991 "%int_5 = OpConstant %int 5",
992 "%int_5_0 = OpConstant %int 5",
993 "%spec_v2int_iadd = OpConstantComposite %v2int %int_5 %int_5",
994 "%int_n4 = OpConstant %int -4",
995 "%int_n4_0 = OpConstant %int -4",
996 "%spec_v2int_isub = OpConstantComposite %v2int %int_n4 %int_n4",
997 "%int_n2 = OpConstant %int -2",
998 "%int_n2_0 = OpConstant %int -2",
999 "%spec_v2int_sdiv = OpConstantComposite %v2int %int_n2 %int_n2",
1000 "%int_n6 = OpConstant %int -6",
1001 "%int_n6_0 = OpConstant %int -6",
1002 "%spec_v2int_imul = OpConstantComposite %v2int %int_n6 %int_n6",
1003 "%int_n6_1 = OpConstant %int -6",
1004 "%int_n6_2 = OpConstant %int -6",
1005 "%spec_v2int_iadd_null = OpConstantComposite %v2int %int_n6 %int_n6",
1006
1007 "%uint_5 = OpConstant %uint 5",
1008 "%uint_5_0 = OpConstant %uint 5",
1009 "%spec_v2uint_iadd = OpConstantComposite %v2uint %uint_5 %uint_5",
1010 "%uint_4294967292 = OpConstant %uint 4294967292",
1011 "%uint_4294967292_0 = OpConstant %uint 4294967292",
1012 "%spec_v2uint_isub = OpConstantComposite %v2uint %uint_4294967292 %uint_4294967292",
1013 "%uint_1431655764 = OpConstant %uint 1431655764",
1014 "%uint_1431655764_0 = OpConstant %uint 1431655764",
1015 "%spec_v2uint_udiv = OpConstantComposite %v2uint %uint_1431655764 %uint_1431655764",
1016 "%uint_2863311528 = OpConstant %uint 2863311528",
1017 "%uint_2863311528_0 = OpConstant %uint 2863311528",
1018 "%spec_v2uint_imul = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528",
1019 "%uint_2863311528_1 = OpConstant %uint 2863311528",
1020 "%uint_2863311528_2 = OpConstant %uint 2863311528",
1021 "%spec_v2uint_isub_null = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528",
1022 },
1023 },
1024 // vector integer rem, mod
1025 {
1026 // original
1027 {
1028 // common constants
1029 "%int_7 = OpConstant %int 7",
1030 "%v2int_7 = OpConstantComposite %v2int %int_7 %int_7",
1031 "%uint_7 = OpConstant %uint 7",
1032 "%v2uint_7 = OpConstantComposite %v2uint %uint_7 %uint_7",
1033 "%int_minus_7 = OpConstant %int -7",
1034 "%v2int_minus_7 = OpConstantComposite %v2int %int_minus_7 %int_minus_7",
1035 "%int_minus_3 = OpConstant %int -3",
1036 "%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3",
1037
1038 // srem
1039 "%7_srem_3 = OpSpecConstantOp %v2int SRem %v2int_7 %signed_three_vec",
1040 "%minus_7_srem_3 = OpSpecConstantOp %v2int SRem %v2int_minus_7 %signed_three_vec",
1041 "%7_srem_minus_3 = OpSpecConstantOp %v2int SRem %v2int_7 %v2int_minus_3",
1042 "%minus_7_srem_minus_3 = OpSpecConstantOp %v2int SRem %v2int_minus_7 %v2int_minus_3",
1043 // smod
1044 "%7_smod_3 = OpSpecConstantOp %v2int SMod %v2int_7 %signed_three_vec",
1045 "%minus_7_smod_3 = OpSpecConstantOp %v2int SMod %v2int_minus_7 %signed_three_vec",
1046 "%7_smod_minus_3 = OpSpecConstantOp %v2int SMod %v2int_7 %v2int_minus_3",
1047 "%minus_7_smod_minus_3 = OpSpecConstantOp %v2int SMod %v2int_minus_7 %v2int_minus_3",
1048 // umod
1049 "%7_umod_3 = OpSpecConstantOp %v2uint UMod %v2uint_7 %unsigned_three_vec",
1050 },
1051 // expected
1052 {
1053 // common constants
1054 "%int_7 = OpConstant %int 7",
1055 "%v2int_7 = OpConstantComposite %v2int %int_7 %int_7",
1056 "%uint_7 = OpConstant %uint 7",
1057 "%v2uint_7 = OpConstantComposite %v2uint %uint_7 %uint_7",
1058 "%int_minus_7 = OpConstant %int -7",
1059 "%v2int_minus_7 = OpConstantComposite %v2int %int_minus_7 %int_minus_7",
1060 "%int_minus_3 = OpConstant %int -3",
1061 "%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3",
1062
1063 // srem
1064 "%int_1 = OpConstant %int 1",
1065 "%int_1_0 = OpConstant %int 1",
1066 "%7_srem_3 = OpConstantComposite %v2int %signed_one %signed_one",
1067 "%int_n1 = OpConstant %int -1",
1068 "%int_n1_0 = OpConstant %int -1",
1069 "%minus_7_srem_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
1070 "%int_1_1 = OpConstant %int 1",
1071 "%int_1_2 = OpConstant %int 1",
1072 "%7_srem_minus_3 = OpConstantComposite %v2int %signed_one %signed_one",
1073 "%int_n1_1 = OpConstant %int -1",
1074 "%int_n1_2 = OpConstant %int -1",
1075 "%minus_7_srem_minus_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
1076 // smod
1077 "%int_1_3 = OpConstant %int 1",
1078 "%int_1_4 = OpConstant %int 1",
1079 "%7_smod_3 = OpConstantComposite %v2int %signed_one %signed_one",
1080 "%int_2 = OpConstant %int 2",
1081 "%int_2_0 = OpConstant %int 2",
1082 "%minus_7_smod_3 = OpConstantComposite %v2int %signed_two %signed_two",
1083 "%int_n2 = OpConstant %int -2",
1084 "%int_n2_0 = OpConstant %int -2",
1085 "%7_smod_minus_3 = OpConstantComposite %v2int %int_n2 %int_n2",
1086 "%int_n1_3 = OpConstant %int -1",
1087 "%int_n1_4 = OpConstant %int -1",
1088 "%minus_7_smod_minus_3 = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
1089 // umod
1090 "%uint_1 = OpConstant %uint 1",
1091 "%uint_1_0 = OpConstant %uint 1",
1092 "%7_umod_3 = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
1093 },
1094 },
1095 // vector integer bitwise, shift
1096 {
1097 // original
1098 {
1099 "%xor_1_3 = OpSpecConstantOp %v2int BitwiseXor %signed_one_vec %signed_three_vec",
1100 "%and_1_2 = OpSpecConstantOp %v2int BitwiseAnd %signed_one_vec %xor_1_3",
1101 "%or_1_2 = OpSpecConstantOp %v2int BitwiseOr %signed_one_vec %xor_1_3",
1102
1103 "%unsigned_31 = OpConstant %uint 31",
1104 "%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31",
1105 "%unsigned_left_shift_max = OpSpecConstantOp %v2uint ShiftLeftLogical %unsigned_one_vec %v2unsigned_31",
1106 "%unsigned_right_shift_logical = OpSpecConstantOp %v2uint ShiftRightLogical %unsigned_left_shift_max %v2unsigned_31",
1107 "%signed_right_shift_arithmetic = OpSpecConstantOp %v2int ShiftRightArithmetic %unsigned_left_shift_max %v2unsigned_31",
1108 },
1109 // expected
1110 {
1111 "%int_2 = OpConstant %int 2",
1112 "%int_2_0 = OpConstant %int 2",
1113 "%xor_1_3 = OpConstantComposite %v2int %signed_two %signed_two",
1114 "%int_0 = OpConstant %int 0",
1115 "%int_0_0 = OpConstant %int 0",
1116 "%and_1_2 = OpConstantComposite %v2int %signed_zero %signed_zero",
1117 "%int_3 = OpConstant %int 3",
1118 "%int_3_0 = OpConstant %int 3",
1119 "%or_1_2 = OpConstantComposite %v2int %signed_three %signed_three",
1120
1121 "%unsigned_31 = OpConstant %uint 31",
1122 "%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31",
1123 "%uint_2147483648 = OpConstant %uint 2147483648",
1124 "%uint_2147483648_0 = OpConstant %uint 2147483648",
1125 "%unsigned_left_shift_max = OpConstantComposite %v2uint %uint_2147483648 %uint_2147483648",
1126 "%uint_1 = OpConstant %uint 1",
1127 "%uint_1_0 = OpConstant %uint 1",
1128 "%unsigned_right_shift_logical = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
1129 "%int_n1 = OpConstant %int -1",
1130 "%int_n1_0 = OpConstant %int -1",
1131 "%signed_right_shift_arithmetic = OpConstantComposite %v2int %signed_minus_one %signed_minus_one",
1132 },
1133 },
1134 // Skip folding if any vector operands or components of the operands
1135 // have undetermined value.
1136 {
1137 // original
1138 {
1139 "%spec_int = OpSpecConstant %int 1",
1140 "%spec_vec = OpSpecConstantComposite %v2int %signed_zero %spec_int",
1141 "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %spec_vec",
1142 },
1143 // expected
1144 {
1145 "%spec_int = OpSpecConstant %int 1",
1146 "%spec_vec = OpSpecConstantComposite %v2int %signed_zero %spec_int",
1147 "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %spec_vec",
1148 },
1149 },
1150 // Skip folding if any vector operands are defined by OpUndef
1151 {
1152 // original
1153 {
1154 "%undef = OpUndef %int",
1155 "%vec = OpConstantComposite %v2int %undef %signed_one",
1156 "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %vec",
1157 },
1158 // expected
1159 {
1160 "%undef = OpUndef %int",
1161 "%vec = OpConstantComposite %v2int %undef %signed_one",
1162 "%spec_iadd = OpSpecConstantOp %v2int IAdd %signed_three_vec %vec",
1163 },
1164 },
1165 // clang-format on
1166 })));
1167
1168 // Tests for SpecConstantOp CompositeExtract instruction
1169 INSTANTIATE_TEST_SUITE_P(
1170 CompositeExtract, FoldSpecConstantOpAndCompositePassTest,
1171 ::testing::ValuesIn(std::vector<
1172 FoldSpecConstantOpAndCompositePassTestCase>({
1173 // clang-format off
1174 // normal vector
1175 {
1176 // original
1177 {
1178 "%r = OpSpecConstantOp %int CompositeExtract %signed_three_vec 0",
1179 "%x = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 0",
1180 "%y = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 1",
1181 "%z = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 2",
1182 "%w = OpSpecConstantOp %int CompositeExtract %v4int_0_1_2_3 3",
1183 },
1184 // expected
1185 {
1186 "%r = OpConstant %int 3",
1187 "%x = OpConstant %int 0",
1188 "%y = OpConstant %int 1",
1189 "%z = OpConstant %int 2",
1190 "%w = OpConstant %int 3",
1191 },
1192 },
1193 // null vector
1194 {
1195 // original
1196 {
1197 "%x = OpSpecConstantOp %int CompositeExtract %signed_null_vec 0",
1198 "%y = OpSpecConstantOp %int CompositeExtract %signed_null_vec 1",
1199 "%null_v4int = OpConstantNull %v4int",
1200 "%z = OpSpecConstantOp %int CompositeExtract %signed_null_vec 2",
1201 },
1202 // expected
1203 {
1204 "%x = OpConstantNull %int",
1205 "%y = OpConstantNull %int",
1206 "%null_v4int = OpConstantNull %v4int",
1207 "%z = OpConstantNull %int",
1208 }
1209 },
1210 // normal flat struct
1211 {
1212 // original
1213 {
1214 "%float_1 = OpConstant %float 1",
1215 "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
1216 "%extract_bool = OpSpecConstantOp %bool CompositeExtract %flat_1 0",
1217 "%extract_int = OpSpecConstantOp %int CompositeExtract %flat_1 1",
1218 "%extract_float_1 = OpSpecConstantOp %float CompositeExtract %flat_1 2",
1219 // foldable composite constants built with OpSpecConstantComposite
1220 // should also be processed.
1221 "%flat_2 = OpSpecConstantComposite %flat_struct %bool_true %signed_null %float_1",
1222 "%extract_float_2 = OpSpecConstantOp %float CompositeExtract %flat_2 2",
1223 },
1224 // expected
1225 {
1226 "%float_1 = OpConstant %float 1",
1227 "%flat_1 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
1228 "%extract_bool = OpConstantTrue %bool",
1229 "%extract_int = OpConstantNull %int",
1230 "%extract_float_1 = OpConstant %float 1",
1231 "%flat_2 = OpConstantComposite %flat_struct %bool_true %signed_null %float_1",
1232 "%extract_float_2 = OpConstant %float 1",
1233 },
1234 },
1235 // null flat struct
1236 {
1237 // original
1238 {
1239 "%flat = OpConstantNull %flat_struct",
1240 "%extract_bool = OpSpecConstantOp %bool CompositeExtract %flat 0",
1241 "%extract_int = OpSpecConstantOp %int CompositeExtract %flat 1",
1242 "%extract_float = OpSpecConstantOp %float CompositeExtract %flat 2",
1243 },
1244 // expected
1245 {
1246 "%flat = OpConstantNull %flat_struct",
1247 "%extract_bool = OpConstantNull %bool",
1248 "%extract_int = OpConstantNull %int",
1249 "%extract_float = OpConstantNull %float",
1250 },
1251 },
1252 // normal nested struct
1253 {
1254 // original
1255 {
1256 "%float_1 = OpConstant %float 1",
1257 "%inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
1258 "%outer = OpConstantComposite %outer_struct %inner %signed_one",
1259 "%extract_inner = OpSpecConstantOp %inner_struct CompositeExtract %outer 0",
1260 "%extract_int = OpSpecConstantOp %int CompositeExtract %outer 1",
1261 "%extract_inner_float = OpSpecConstantOp %float CompositeExtract %outer 0 2",
1262 },
1263 // expected
1264 {
1265 "%float_1 = OpConstant %float 1",
1266 "%inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
1267 "%outer = OpConstantComposite %outer_struct %inner %signed_one",
1268 "%extract_inner = OpConstantComposite %inner_struct %bool_true %signed_null %float_1",
1269 "%extract_int = OpConstant %int 1",
1270 "%extract_inner_float = OpConstant %float 1",
1271 },
1272 },
1273 // null nested struct
1274 {
1275 // original
1276 {
1277 "%outer = OpConstantNull %outer_struct",
1278 "%extract_inner = OpSpecConstantOp %inner_struct CompositeExtract %outer 0",
1279 "%extract_int = OpSpecConstantOp %int CompositeExtract %outer 1",
1280 "%extract_inner_float = OpSpecConstantOp %float CompositeExtract %outer 0 2",
1281 },
1282 // expected
1283 {
1284 "%outer = OpConstantNull %outer_struct",
1285 "%extract_inner = OpConstantNull %inner_struct",
1286 "%extract_int = OpConstantNull %int",
1287 "%extract_inner_float = OpConstantNull %float",
1288 },
1289 },
1290 // skip folding if the any composite constant's value are not fully
1291 // determined, even though the extracting target might have
1292 // determined value.
1293 {
1294 // original
1295 {
1296 "%float_1 = OpConstant %float 1",
1297 "%spec_float = OpSpecConstant %float 1",
1298 "%spec_inner = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
1299 "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %signed_one",
1300 "%spec_vec = OpSpecConstantComposite %v2float %spec_float %float_1",
1301 "%extract_inner = OpSpecConstantOp %int CompositeExtract %spec_inner 1",
1302 "%extract_outer = OpSpecConstantOp %int CompositeExtract %spec_outer 1",
1303 "%extract_vec = OpSpecConstantOp %float CompositeExtract %spec_vec 1",
1304 },
1305 // expected
1306 {
1307 "%float_1 = OpConstant %float 1",
1308 "%spec_float = OpSpecConstant %float 1",
1309 "%spec_inner = OpSpecConstantComposite %inner_struct %bool_true %signed_null %spec_float",
1310 "%spec_outer = OpSpecConstantComposite %outer_struct %spec_inner %signed_one",
1311 "%spec_vec = OpSpecConstantComposite %v2float %spec_float %float_1",
1312 "%extract_inner = OpSpecConstantOp %int CompositeExtract %spec_inner 1",
1313 "%extract_outer = OpSpecConstantOp %int CompositeExtract %spec_outer 1",
1314 "%extract_vec = OpSpecConstantOp %float CompositeExtract %spec_vec 1",
1315 },
1316 },
1317 // skip if the composite constant depends on the result of OpUndef,
1318 // even though the composite extract target element does not depends
1319 // on the OpUndef.
1320 {
1321 // original
1322 {
1323 "%undef = OpUndef %float",
1324 "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
1325 "%outer = OpConstantComposite %outer_struct %inner %signed_one",
1326 "%extract_inner = OpSpecConstantOp %int CompositeExtract %inner 1",
1327 "%extract_outer = OpSpecConstantOp %int CompositeExtract %outer 1",
1328 },
1329 // expected
1330 {
1331 "%undef = OpUndef %float",
1332 "%inner = OpConstantComposite %inner_struct %bool_true %signed_one %undef",
1333 "%outer = OpConstantComposite %outer_struct %inner %signed_one",
1334 "%extract_inner = OpSpecConstantOp %int CompositeExtract %inner 1",
1335 "%extract_outer = OpSpecConstantOp %int CompositeExtract %outer 1",
1336 },
1337 },
1338 // TODO(qining): Add tests for Array and other composite type constants.
1339 // clang-format on
1340 })));
1341
1342 // Tests the swizzle operations for spec const vectors.
1343 INSTANTIATE_TEST_SUITE_P(
1344 VectorShuffle, FoldSpecConstantOpAndCompositePassTest,
1345 ::testing::ValuesIn(std::vector<
1346 FoldSpecConstantOpAndCompositePassTestCase>({
1347 // clang-format off
1348 // normal vector
1349 {
1350 // original
1351 {
1352 "%xy = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 0 1",
1353 "%yz = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 1 2",
1354 "%zw = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 2 3",
1355 "%wx = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 3 0",
1356 "%xx = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 0 0",
1357 "%yyy = OpSpecConstantOp %v3int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 1 1 1",
1358 "%wwww = OpSpecConstantOp %v4int VectorShuffle %v4int_0_1_2_3 %v4int_0_1_2_3 2 2 2 2",
1359 },
1360 // expected
1361 {
1362 "%xy = OpConstantComposite %v2int %signed_zero %signed_one",
1363 "%yz = OpConstantComposite %v2int %signed_one %signed_two",
1364 "%zw = OpConstantComposite %v2int %signed_two %signed_three",
1365 "%wx = OpConstantComposite %v2int %signed_three %signed_zero",
1366 "%xx = OpConstantComposite %v2int %signed_zero %signed_zero",
1367 "%yyy = OpConstantComposite %v3int %signed_one %signed_one %signed_one",
1368 "%wwww = OpConstantComposite %v4int %signed_two %signed_two %signed_two %signed_two",
1369 },
1370 },
1371 // null vector
1372 {
1373 // original
1374 {
1375 "%a = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %v4int_0_1_2_3 0 1",
1376 "%b = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %v4int_0_1_2_3 2 3",
1377 "%c = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %signed_null_vec 3 4",
1378 "%d = OpSpecConstantOp %v2int VectorShuffle %signed_null_vec %signed_null_vec 1 2",
1379 },
1380 // expected
1381 {
1382 "%a = OpConstantComposite %v2int %signed_null %signed_null",
1383 "%b = OpConstantComposite %v2int %signed_zero %signed_one",
1384 "%c = OpConstantComposite %v2int %signed_three %signed_null",
1385 "%d = OpConstantComposite %v2int %signed_null %signed_null",
1386 }
1387 },
1388 // skip if any of the components of the vector operands do not have
1389 // determined value, even though the result vector might not be
1390 // built with those undermined values.
1391 {
1392 // original
1393 {
1394 "%spec_int = OpSpecConstant %int 1",
1395 "%spec_ivec = OpSpecConstantComposite %v2int %signed_null %spec_int",
1396 "%a = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 0 1",
1397 "%b = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 3 4",
1398 },
1399 // expected
1400 {
1401 "%spec_int = OpSpecConstant %int 1",
1402 "%spec_ivec = OpSpecConstantComposite %v2int %signed_null %spec_int",
1403 "%a = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 0 1",
1404 "%b = OpSpecConstantOp %v2int VectorShuffle %v4int_0_1_2_3 %spec_ivec 3 4",
1405 },
1406 },
1407 // Skip if any components of the two vector operands depend on
1408 // the result of OpUndef. Even though the selected components do
1409 // not depend on the OpUndef result.
1410 {
1411 // original
1412 {
1413 "%undef = OpUndef %int",
1414 "%vec_1 = OpConstantComposite %v2int %undef %signed_one",
1415 "%dep = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 0 3",
1416 "%not_dep_element = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 1 3",
1417 "%no_dep_vector = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 2 3",
1418 },
1419 // expected
1420 {
1421 "%undef = OpUndef %int",
1422 "%vec_1 = OpConstantComposite %v2int %undef %signed_one",
1423 "%dep = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 0 3",
1424 "%not_dep_element = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 1 3",
1425 "%no_dep_vector = OpSpecConstantOp %v2int VectorShuffle %vec_1 %signed_three_vec 2 3",
1426 },
1427 },
1428 // clang-format on
1429 })));
1430
1431 // Test with long use-def chain.
1432 INSTANTIATE_TEST_SUITE_P(
1433 LongDefUseChain, FoldSpecConstantOpAndCompositePassTest,
1434 ::testing::ValuesIn(std::vector<
1435 FoldSpecConstantOpAndCompositePassTestCase>({
1436 // clang-format off
1437 // Long Def-Use chain with binary operations.
1438 {
1439 // original
1440 {
1441 "%array_size = OpConstant %int 4",
1442 "%type_arr_int_4 = OpTypeArray %int %array_size",
1443 "%spec_int_0 = OpConstant %int 100",
1444 "%spec_int_1 = OpConstant %int 1",
1445 "%spec_int_2 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_1",
1446 "%spec_int_3 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_2",
1447 "%spec_int_4 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_3",
1448 "%spec_int_5 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_4",
1449 "%spec_int_6 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_5",
1450 "%spec_int_7 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_6",
1451 "%spec_int_8 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_7",
1452 "%spec_int_9 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_8",
1453 "%spec_int_10 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_9",
1454 "%spec_int_11 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_10",
1455 "%spec_int_12 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_11",
1456 "%spec_int_13 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_12",
1457 "%spec_int_14 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_13",
1458 "%spec_int_15 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_14",
1459 "%spec_int_16 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_15",
1460 "%spec_int_17 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_16",
1461 "%spec_int_18 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_17",
1462 "%spec_int_19 = OpSpecConstantOp %int IAdd %spec_int_0 %spec_int_18",
1463 "%spec_int_20 = OpSpecConstantOp %int ISub %spec_int_0 %spec_int_19",
1464 "%used_vec_a = OpSpecConstantComposite %v2int %spec_int_18 %spec_int_19",
1465 "%used_vec_b = OpSpecConstantOp %v2int IMul %used_vec_a %used_vec_a",
1466 "%spec_int_21 = OpSpecConstantOp %int CompositeExtract %used_vec_b 0",
1467 "%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21",
1468 // Spec constants whose values can not be fully resolved should
1469 // not be processed.
1470 "%spec_int_22 = OpSpecConstant %int 123",
1471 "%spec_int_23 = OpSpecConstantOp %int IAdd %spec_int_22 %signed_one",
1472 },
1473 // expected
1474 {
1475 "%array_size = OpConstant %int 4",
1476 "%type_arr_int_4 = OpTypeArray %int %array_size",
1477 "%spec_int_0 = OpConstant %int 100",
1478 "%spec_int_1 = OpConstant %int 1",
1479 "%spec_int_2 = OpConstant %int 101",
1480 "%spec_int_3 = OpConstant %int -1",
1481 "%spec_int_4 = OpConstant %int 99",
1482 "%spec_int_5 = OpConstant %int 1",
1483 "%spec_int_6 = OpConstant %int 101",
1484 "%spec_int_7 = OpConstant %int -1",
1485 "%spec_int_8 = OpConstant %int 99",
1486 "%spec_int_9 = OpConstant %int 1",
1487 "%spec_int_10 = OpConstant %int 101",
1488 "%spec_int_11 = OpConstant %int -1",
1489 "%spec_int_12 = OpConstant %int 99",
1490 "%spec_int_13 = OpConstant %int 1",
1491 "%spec_int_14 = OpConstant %int 101",
1492 "%spec_int_15 = OpConstant %int -1",
1493 "%spec_int_16 = OpConstant %int 101",
1494 "%spec_int_17 = OpConstant %int 201",
1495 "%spec_int_18 = OpConstant %int -101",
1496 "%spec_int_19 = OpConstant %int -1",
1497 "%spec_int_20 = OpConstant %int 101",
1498 "%used_vec_a = OpConstantComposite %v2int %spec_int_18 %spec_int_19",
1499 "%int_10201 = OpConstant %int 10201",
1500 "%int_1 = OpConstant %int 1",
1501 "%used_vec_b = OpConstantComposite %v2int %int_10201 %signed_one",
1502 "%spec_int_21 = OpConstant %int 10201",
1503 "%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21",
1504 "%spec_int_22 = OpSpecConstant %int 123",
1505 "%spec_int_23 = OpSpecConstantOp %int IAdd %spec_int_22 %signed_one",
1506 },
1507 },
1508 // Long Def-Use chain with swizzle
1509 })));
1510
1511 } // namespace
1512 } // namespace opt
1513 } // namespace spvtools
1514