• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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