xref: /aosp_15_r20/external/swiftshader/third_party/SPIRV-Tools/test/opt/fold_test.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 // Copyright (c) 2016 Google Inc.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #include "source/opt/fold.h"
15 
16 #include <limits>
17 #include <memory>
18 #include <string>
19 #include <vector>
20 
21 #include "effcee/effcee.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "source/opt/build_module.h"
25 #include "source/opt/def_use_manager.h"
26 #include "source/opt/ir_context.h"
27 #include "source/opt/module.h"
28 #include "spirv-tools/libspirv.hpp"
29 
30 namespace spvtools {
31 namespace opt {
32 namespace {
33 
34 using ::testing::Contains;
35 
Disassemble(const std::string & original,IRContext * context,uint32_t disassemble_options=0)36 std::string Disassemble(const std::string& original, IRContext* context,
37                         uint32_t disassemble_options = 0) {
38   std::vector<uint32_t> optimized_bin;
39   context->module()->ToBinary(&optimized_bin, true);
40   spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
41   SpirvTools tools(target_env);
42   std::string optimized_asm;
43   EXPECT_TRUE(
44       tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options))
45       << "Disassembling failed for shader:\n"
46       << original << std::endl;
47   return optimized_asm;
48 }
49 
Match(const std::string & original,IRContext * context,uint32_t disassemble_options=0)50 void Match(const std::string& original, IRContext* context,
51            uint32_t disassemble_options = 0) {
52   std::string disassembly = Disassemble(original, context, disassemble_options);
53   auto match_result = effcee::Match(disassembly, original);
54   EXPECT_EQ(effcee::Result::Status::Ok, match_result.status())
55       << match_result.message() << "\nChecking result:\n"
56       << disassembly;
57 }
58 
59 template <class ResultType>
60 struct InstructionFoldingCase {
InstructionFoldingCasespvtools::opt::__anon8bea92fa0111::InstructionFoldingCase61   InstructionFoldingCase(const std::string& tb, uint32_t id, ResultType result)
62       : test_body(tb), id_to_fold(id), expected_result(result) {}
63 
64   std::string test_body;
65   uint32_t id_to_fold;
66   ResultType expected_result;
67 };
68 
GetInstructionToFold(const std::string test_body,const uint32_t id_to_fold,spv_target_env spv_env)69 std::tuple<std::unique_ptr<IRContext>, Instruction*> GetInstructionToFold(
70     const std::string test_body, const uint32_t id_to_fold,
71     spv_target_env spv_env) {
72   // Build module.
73   std::unique_ptr<IRContext> context =
74       BuildModule(spv_env, nullptr, test_body,
75                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
76   EXPECT_NE(nullptr, context);
77   if (context == nullptr) {
78     return {nullptr, nullptr};
79   }
80 
81   // Fold the instruction to test.
82   if (id_to_fold != 0) {
83     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
84     Instruction* inst = def_use_mgr->GetDef(id_to_fold);
85     return {std::move(context), inst};
86   }
87 
88   // If there is not ID, we get the instruction just before a terminator
89   // instruction. That could be a return or abort. This is used for cases where
90   // the instruction we want to fold does not have a result id.
91   Function* func = &*context->module()->begin();
92   for (auto& bb : *func) {
93     Instruction* terminator = bb.terminator();
94     if (terminator->IsReturnOrAbort()) {
95       return {std::move(context), terminator->PreviousNode()};
96     }
97   }
98   return {nullptr, nullptr};
99 }
100 
FoldInstruction(const std::string test_body,const uint32_t id_to_fold,spv_target_env spv_env)101 std::tuple<std::unique_ptr<IRContext>, Instruction*> FoldInstruction(
102     const std::string test_body, const uint32_t id_to_fold,
103     spv_target_env spv_env) {
104   // Build module.
105   std::unique_ptr<IRContext> context;
106   Instruction* inst = nullptr;
107   std::tie(context, inst) =
108       GetInstructionToFold(test_body, id_to_fold, spv_env);
109 
110   if (context == nullptr) {
111     return {nullptr, nullptr};
112   }
113 
114   std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
115   bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
116   EXPECT_EQ(inst->result_id(), original_inst->result_id());
117   EXPECT_EQ(inst->type_id(), original_inst->type_id());
118 
119   if (!succeeded && inst != nullptr) {
120     EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
121     for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
122       EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
123     }
124   }
125 
126   return {std::move(context), succeeded ? inst : nullptr};
127 }
128 
129 template <class ElementType, class Function>
CheckForExpectedScalarConstant(Instruction * inst,ElementType expected_result,Function GetValue)130 void CheckForExpectedScalarConstant(Instruction* inst,
131                                     ElementType expected_result,
132                                     Function GetValue) {
133   ASSERT_TRUE(inst);
134 
135   IRContext* context = inst->context();
136   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
137   while (inst->opcode() == spv::Op::OpCopyObject) {
138     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
139   }
140 
141   // Make sure we have a constant.
142   analysis::ConstantManager* const_mrg = context->get_constant_mgr();
143   const analysis::Constant* constant = const_mrg->GetConstantFromInst(inst);
144   ASSERT_TRUE(constant);
145 
146   // Make sure the constant is a scalar.
147   const analysis::ScalarConstant* result = constant->AsScalarConstant();
148   ASSERT_TRUE(result);
149 
150   // Check if the result matches the expected value.
151   // If ExpectedType is not a float type, it should cast the value to a double
152   // and never get a nan.
153   if (!std::isnan(static_cast<double>(expected_result))) {
154     EXPECT_EQ(expected_result, GetValue(result));
155   } else {
156     EXPECT_TRUE(std::isnan(static_cast<double>(GetValue(result))));
157   }
158 }
159 
160 template <class ElementType, class Function>
CheckForExpectedVectorConstant(Instruction * inst,std::vector<ElementType> expected_result,Function GetValue)161 void CheckForExpectedVectorConstant(Instruction* inst,
162                                     std::vector<ElementType> expected_result,
163                                     Function GetValue) {
164   ASSERT_TRUE(inst);
165 
166   IRContext* context = inst->context();
167   EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
168   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
169   inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
170   std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
171   EXPECT_THAT(opcodes, Contains(inst->opcode()));
172   analysis::ConstantManager* const_mrg = context->get_constant_mgr();
173   const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
174   EXPECT_NE(result, nullptr);
175   if (result != nullptr) {
176     const std::vector<const analysis::Constant*>& componenets =
177         result->AsVectorConstant()->GetComponents();
178     EXPECT_EQ(componenets.size(), expected_result.size());
179     for (size_t i = 0; i < componenets.size(); i++) {
180       EXPECT_EQ(expected_result[i], GetValue(componenets[i]));
181     }
182   }
183 }
184 
185 using IntegerInstructionFoldingTest =
186     ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
187 
TEST_P(IntegerInstructionFoldingTest,Case)188 TEST_P(IntegerInstructionFoldingTest, Case) {
189   const auto& tc = GetParam();
190 
191   std::unique_ptr<IRContext> context;
192   Instruction* inst;
193   std::tie(context, inst) =
194       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
195   CheckForExpectedScalarConstant(
196       inst, tc.expected_result, [](const analysis::Constant* c) {
197         return c->AsScalarConstant()->GetU32BitValue();
198       });
199 }
200 
201 // Returns a common SPIR-V header for all of the test that follow.
202 #define INT_0_ID 100
203 #define TRUE_ID 101
204 #define VEC2_0_ID 102
205 #define INT_7_ID 103
206 #define FLOAT_0_ID 104
207 #define DOUBLE_0_ID 105
208 #define VEC4_0_ID 106
209 #define DVEC4_0_ID 106
210 #define HALF_0_ID 108
Header()211 const std::string& Header() {
212   static const std::string header = R"(OpCapability Shader
213 OpCapability Float16
214 OpCapability Float64
215 OpCapability Int8
216 OpCapability Int16
217 OpCapability Int64
218 %1 = OpExtInstImport "GLSL.std.450"
219 OpMemoryModel Logical GLSL450
220 OpEntryPoint Fragment %main "main"
221 OpExecutionMode %main OriginUpperLeft
222 OpSource GLSL 140
223 OpName %main "main"
224 %void = OpTypeVoid
225 %void_func = OpTypeFunction %void
226 %bool = OpTypeBool
227 %float = OpTypeFloat 32
228 %double = OpTypeFloat 64
229 %half = OpTypeFloat 16
230 %101 = OpConstantTrue %bool ; Need a def with an numerical id to define id maps.
231 %true = OpConstantTrue %bool
232 %false = OpConstantFalse %bool
233 %bool_null = OpConstantNull %bool
234 %short = OpTypeInt 16 1
235 %ushort = OpTypeInt 16 0
236 %byte = OpTypeInt 8 1
237 %ubyte = OpTypeInt 8 0
238 %int = OpTypeInt 32 1
239 %long = OpTypeInt 64 1
240 %uint = OpTypeInt 32 0
241 %ulong = OpTypeInt 64 0
242 %v2int = OpTypeVector %int 2
243 %v4int = OpTypeVector %int 4
244 %v2short = OpTypeVector %short 2
245 %v2long = OpTypeVector %long 2
246 %v4long = OpTypeVector %long 4
247 %v4float = OpTypeVector %float 4
248 %v4double = OpTypeVector %double 4
249 %v2uint = OpTypeVector %uint 2
250 %v2ulong = OpTypeVector %ulong 2
251 %v2float = OpTypeVector %float 2
252 %v2double = OpTypeVector %double 2
253 %v2half = OpTypeVector %half 2
254 %v2bool = OpTypeVector %bool 2
255 %m2x2int = OpTypeMatrix %v2int 2
256 %mat4v2float = OpTypeMatrix %v2float 4
257 %mat2v4float = OpTypeMatrix %v4float 2
258 %mat4v4float = OpTypeMatrix %v4float 4
259 %mat4v4double = OpTypeMatrix %v4double 4
260 %struct_v2int_int_int = OpTypeStruct %v2int %int %int
261 %_ptr_int = OpTypePointer Function %int
262 %_ptr_uint = OpTypePointer Function %uint
263 %_ptr_bool = OpTypePointer Function %bool
264 %_ptr_float = OpTypePointer Function %float
265 %_ptr_double = OpTypePointer Function %double
266 %_ptr_half = OpTypePointer Function %half
267 %_ptr_long = OpTypePointer Function %long
268 %_ptr_ulong = OpTypePointer Function %ulong
269 %_ptr_v2int = OpTypePointer Function %v2int
270 %_ptr_v4int = OpTypePointer Function %v4int
271 %_ptr_v4float = OpTypePointer Function %v4float
272 %_ptr_v4double = OpTypePointer Function %v4double
273 %_ptr_struct_v2int_int_int = OpTypePointer Function %struct_v2int_int_int
274 %_ptr_v2float = OpTypePointer Function %v2float
275 %_ptr_v2double = OpTypePointer Function %v2double
276 %int_2 = OpConstant %int 2
277 %int_arr_2 = OpTypeArray %int %int_2
278 %short_0 = OpConstant %short 0
279 %short_2 = OpConstant %short 2
280 %short_3 = OpConstant %short 3
281 %short_n5 = OpConstant %short -5
282 %ubyte_1 = OpConstant %ubyte 1
283 %byte_n1 = OpConstant %byte -1
284 %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps.
285 %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps.
286 %int_0 = OpConstant %int 0
287 %int_1 = OpConstant %int 1
288 %int_3 = OpConstant %int 3
289 %int_4 = OpConstant %int 4
290 %int_10 = OpConstant %int 10
291 %int_1073741824 = OpConstant %int 1073741824
292 %int_n1 = OpConstant %int -1
293 %int_n24 = OpConstant %int -24
294 %int_n858993459 = OpConstant %int -858993459
295 %int_min = OpConstant %int -2147483648
296 %int_max = OpConstant %int 2147483647
297 %long_0 = OpConstant %long 0
298 %long_1 = OpConstant %long 1
299 %long_2 = OpConstant %long 2
300 %long_3 = OpConstant %long 3
301 %long_n3 = OpConstant %long -3
302 %long_7 = OpConstant %long 7
303 %long_n7 = OpConstant %long -7
304 %long_10 = OpConstant %long 10
305 %long_32768 = OpConstant %long 32768
306 %long_n57344 = OpConstant %long -57344
307 %long_n4611686018427387904 = OpConstant %long -4611686018427387904
308 %long_4611686018427387904 = OpConstant %long 4611686018427387904
309 %long_n1 = OpConstant %long -1
310 %long_n3689348814741910323 = OpConstant %long -3689348814741910323
311 %long_min = OpConstant %long -9223372036854775808
312 %long_max = OpConstant %long 9223372036854775807
313 %ulong_7 = OpConstant %ulong 7
314 %ulong_4611686018427387904 = OpConstant %ulong 4611686018427387904
315 %uint_0 = OpConstant %uint 0
316 %uint_1 = OpConstant %uint 1
317 %uint_2 = OpConstant %uint 2
318 %uint_3 = OpConstant %uint 3
319 %uint_4 = OpConstant %uint 4
320 %uint_32 = OpConstant %uint 32
321 %uint_42 = OpConstant %uint 42
322 %uint_2147483649 = OpConstant %uint 2147483649
323 %uint_max = OpConstant %uint 4294967295
324 %ulong_0 = OpConstant %ulong 0
325 %ulong_1 = OpConstant %ulong 1
326 %ulong_2 = OpConstant %ulong 2
327 %ulong_9223372036854775809 = OpConstant %ulong 9223372036854775809
328 %ulong_max = OpConstant %ulong 18446744073709551615
329 %v2int_undef = OpUndef %v2int
330 %v2int_0_0 = OpConstantComposite %v2int %int_0 %int_0
331 %v2int_1_0 = OpConstantComposite %v2int %int_1 %int_0
332 %v2int_2_2 = OpConstantComposite %v2int %int_2 %int_2
333 %v2int_2_3 = OpConstantComposite %v2int %int_2 %int_3
334 %v2int_3_2 = OpConstantComposite %v2int %int_3 %int_2
335 %v2int_n1_n24 = OpConstantComposite %v2int %int_n1 %int_n24
336 %v2int_4_4 = OpConstantComposite %v2int %int_4 %int_4
337 %v2int_min_max = OpConstantComposite %v2int %int_min %int_max
338 %v2short_2_n5 = OpConstantComposite %v2short %short_2 %short_n5
339 %v2long_2_2 = OpConstantComposite %v2long %long_2 %long_2
340 %v2long_2_3 = OpConstantComposite %v2long %long_2 %long_3
341 %v2bool_null = OpConstantNull %v2bool
342 %v2bool_true_false = OpConstantComposite %v2bool %true %false
343 %v2bool_false_true = OpConstantComposite %v2bool %false %true
344 %struct_v2int_int_int_null = OpConstantNull %struct_v2int_int_int
345 %v2int_null = OpConstantNull %v2int
346 %102 = OpConstantComposite %v2int %103 %103
347 %v4int_undef = OpUndef %v4int
348 %v4int_0_0_0_0 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
349 %m2x2int_undef = OpUndef %m2x2int
350 %struct_undef_0_0 = OpConstantComposite %struct_v2int_int_int %v2int_undef %int_0 %int_0
351 %float_n1 = OpConstant %float -1
352 %104 = OpConstant %float 0 ; Need a def with an numerical id to define id maps.
353 %float_null = OpConstantNull %float
354 %float_0 = OpConstant %float 0
355 %float_n0 = OpConstant %float -0.0
356 %float_1 = OpConstant %float 1
357 %float_2 = OpConstant %float 2
358 %float_3 = OpConstant %float 3
359 %float_4 = OpConstant %float 4
360 %float_2049 = OpConstant %float 2049
361 %float_n2049 = OpConstant %float -2049
362 %float_0p5 = OpConstant %float 0.5
363 %float_0p2 = OpConstant %float 0.2
364 %float_pi = OpConstant %float 1.5555
365 %float_1e16 = OpConstant %float 1e16
366 %float_n1e16 = OpConstant %float -1e16
367 %float_1en16 = OpConstant %float 1e-16
368 %float_n1en16 = OpConstant %float -1e-16
369 %v2float_0_0 = OpConstantComposite %v2float %float_0 %float_0
370 %v2float_2_2 = OpConstantComposite %v2float %float_2 %float_2
371 %v2float_2_3 = OpConstantComposite %v2float %float_2 %float_3
372 %v2float_3_2 = OpConstantComposite %v2float %float_3 %float_2
373 %v2float_4_4 = OpConstantComposite %v2float %float_4 %float_4
374 %v2float_2_0p5 = OpConstantComposite %v2float %float_2 %float_0p5
375 %v2float_0p2_0p5 = OpConstantComposite %v2float %float_0p2 %float_0p5
376 %v2float_null = OpConstantNull %v2float
377 %double_n1 = OpConstant %double -1
378 %105 = OpConstant %double 0 ; Need a def with an numerical id to define id maps.
379 %double_null = OpConstantNull %double
380 %double_0 = OpConstant %double 0
381 %double_n0 = OpConstant %double -0.0
382 %double_1 = OpConstant %double 1
383 %double_2 = OpConstant %double 2
384 %double_3 = OpConstant %double 3
385 %double_4 = OpConstant %double 4
386 %double_5 = OpConstant %double 5
387 %double_0p5 = OpConstant %double 0.5
388 %double_0p2 = OpConstant %double 0.2
389 %v2double_0_0 = OpConstantComposite %v2double %double_0 %double_0
390 %v2double_2_2 = OpConstantComposite %v2double %double_2 %double_2
391 %v2double_2_3 = OpConstantComposite %v2double %double_2 %double_3
392 %v2double_3_2 = OpConstantComposite %v2double %double_3 %double_2
393 %v2double_4_4 = OpConstantComposite %v2double %double_4 %double_4
394 %v2double_2_0p5 = OpConstantComposite %v2double %double_2 %double_0p5
395 %v2double_null = OpConstantNull %v2double
396 %108 = OpConstant %half 0
397 %half_1 = OpConstant %half 1
398 %half_2 = OpConstant %half 2
399 %half_0_1 = OpConstantComposite %v2half %108 %half_1
400 %106 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
401 %v4float_0_0_0_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
402 %v4float_0_0_0_1 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
403 %v4float_0_1_0_0 = OpConstantComposite %v4float %float_0 %float_1 %float_null %float_0
404 %v4float_1_1_1_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
405 %v4float_1_2_3_4 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
406 %v4float_null = OpConstantNull %v4float
407 %mat2v4float_null = OpConstantNull %mat2v4float
408 %mat4v4float_null = OpConstantNull %mat4v4float
409 %mat4v4float_1_2_3_4 = OpConstantComposite %mat4v4float %v4float_1_2_3_4 %v4float_1_2_3_4 %v4float_1_2_3_4 %v4float_1_2_3_4
410 %mat4v4float_1_2_3_4_null = OpConstantComposite %mat4v4float %v4float_1_2_3_4 %v4float_null %v4float_1_2_3_4 %v4float_null
411 %107 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
412 %v4double_0_0_0_0 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
413 %v4double_0_0_0_1 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_1
414 %v4double_0_1_0_0 = OpConstantComposite %v4double %double_0 %double_1 %double_null %double_0
415 %v4double_1_1_1_1 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_1
416 %v4double_1_2_3_4 = OpConstantComposite %v4double %double_1 %double_2 %double_3 %double_4
417 %v4double_1_1_1_0p5 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_0p5
418 %v4double_null = OpConstantNull %v4double
419 %mat4v4double_null = OpConstantNull %mat4v4double
420 %mat4v4double_1_2_3_4 = OpConstantComposite %mat4v4double %v4double_1_2_3_4 %v4double_1_2_3_4 %v4double_1_2_3_4 %v4double_1_2_3_4
421 %mat4v4double_1_2_3_4_null = OpConstantComposite %mat4v4double %v4double_1_2_3_4 %v4double_null %v4double_1_2_3_4 %v4double_null
422 %v4float_n1_2_1_3 = OpConstantComposite %v4float %float_n1 %float_2 %float_1 %float_3
423 %uint_0x3f800000 = OpConstant %uint 0x3f800000
424 %uint_0xbf800000 = OpConstant %uint 0xbf800000
425 %v2uint_0x3f800000_0xbf800000 = OpConstantComposite %v2uint %uint_0x3f800000 %uint_0xbf800000
426 %long_0xbf8000003f800000 = OpConstant %long 0xbf8000003f800000
427 %int_0x3FF00000 = OpConstant %int 0x3FF00000
428 %int_0x00000000 = OpConstant %int 0x00000000
429 %int_0xC05FD666 = OpConstant %int 0xC05FD666
430 %int_0x66666666 = OpConstant %int 0x66666666
431 %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666 = OpConstantComposite %v4int %int_0x00000000 %int_0x3FF00000 %int_0x66666666 %int_0xC05FD666
432 %ushort_0x4400 = OpConstant %ushort 0x4400
433 %short_0x4400 = OpConstant %short 0x4400
434 %ushort_0xBC00 = OpConstant %ushort 0xBC00
435 %short_0xBC00 = OpConstant %short 0xBC00
436 %int_arr_2_undef = OpUndef %int_arr_2
437 )";
438 
439   return header;
440 }
441 
442 // Returns the header with definitions of float NaN and double NaN. Since FC
443 // "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" finds
444 // %double_nan = OpConstant %double -0x1.8p+1024 instead of
445 // %double_n0 = OpConstant %double -0,
446 // we separates those definitions from Header().
HeaderWithNaN()447 const std::string& HeaderWithNaN() {
448   static const std::string headerWithNaN =
449       Header() +
450       R"(%float_nan = OpConstant %float -0x1.8p+128
451 %double_nan = OpConstant %double -0x1.8p+1024
452 )";
453 
454   return headerWithNaN;
455 }
456 
457 // clang-format off
458 INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTest,
459                         ::testing::Values(
460   // Test case 0: fold 0*n
461   InstructionFoldingCase<uint32_t>(
462     Header() + "%main = OpFunction %void None %void_func\n" +
463     "%main_lab = OpLabel\n" +
464            "%n = OpVariable %_ptr_int Function\n" +
465         "%load = OpLoad %int %n\n" +
466            "%2 = OpIMul %int %int_0 %load\n" +
467                 "OpReturn\n" +
468                 "OpFunctionEnd",
469     2, 0),
470   // Test case 1: fold n*0
471   InstructionFoldingCase<uint32_t>(
472     Header() + "%main = OpFunction %void None %void_func\n" +
473         "%main_lab = OpLabel\n" +
474         "%n = OpVariable %_ptr_int Function\n" +
475         "%load = OpLoad %int %n\n" +
476         "%2 = OpIMul %int %load %int_0\n" +
477         "OpReturn\n" +
478         "OpFunctionEnd",
479     2, 0),
480   // Test case 2: fold 0/n (signed)
481   InstructionFoldingCase<uint32_t>(
482     Header() + "%main = OpFunction %void None %void_func\n" +
483         "%main_lab = OpLabel\n" +
484         "%n = OpVariable %_ptr_int Function\n" +
485         "%load = OpLoad %int %n\n" +
486         "%2 = OpSDiv %int %int_0 %load\n" +
487         "OpReturn\n" +
488         "OpFunctionEnd",
489         2, 0),
490   // Test case 3: fold n/0 (signed)
491   InstructionFoldingCase<uint32_t>(
492     Header() + "%main = OpFunction %void None %void_func\n" +
493         "%main_lab = OpLabel\n" +
494         "%n = OpVariable %_ptr_int Function\n" +
495         "%load = OpLoad %int %n\n" +
496         "%2 = OpSDiv %int %load %int_0\n" +
497         "OpReturn\n" +
498         "OpFunctionEnd",
499     2, 0),
500   // Test case 4: fold 0/n (unsigned)
501   InstructionFoldingCase<uint32_t>(
502     Header() + "%main = OpFunction %void None %void_func\n" +
503         "%main_lab = OpLabel\n" +
504         "%n = OpVariable %_ptr_uint Function\n" +
505         "%load = OpLoad %uint %n\n" +
506         "%2 = OpUDiv %uint %uint_0 %load\n" +
507         "OpReturn\n" +
508         "OpFunctionEnd",
509     2, 0),
510   // Test case 5: fold n/0 (unsigned)
511   InstructionFoldingCase<uint32_t>(
512     Header() + "%main = OpFunction %void None %void_func\n" +
513         "%main_lab = OpLabel\n" +
514         "%n = OpVariable %_ptr_int Function\n" +
515         "%load = OpLoad %int %n\n" +
516         "%2 = OpSDiv %int %load %int_0\n" +
517         "OpReturn\n" +
518         "OpFunctionEnd",
519     2, 0),
520   // Test case 6: fold 0 remainder n
521   InstructionFoldingCase<uint32_t>(
522     Header() + "%main = OpFunction %void None %void_func\n" +
523         "%main_lab = OpLabel\n" +
524         "%n = OpVariable %_ptr_int Function\n" +
525         "%load = OpLoad %int %n\n" +
526         "%2 = OpSRem %int %int_0 %load\n" +
527         "OpReturn\n" +
528         "OpFunctionEnd",
529     2, 0),
530   // Test case 7: fold n remainder 0
531   InstructionFoldingCase<uint32_t>(
532     Header() + "%main = OpFunction %void None %void_func\n" +
533         "%main_lab = OpLabel\n" +
534         "%n = OpVariable %_ptr_int Function\n" +
535         "%load = OpLoad %int %n\n" +
536         "%2 = OpSRem %int %load %int_0\n" +
537         "OpReturn\n" +
538         "OpFunctionEnd",
539     2, 0),
540   // Test case 8: fold 0%n (signed)
541   InstructionFoldingCase<uint32_t>(
542     Header() + "%main = OpFunction %void None %void_func\n" +
543         "%main_lab = OpLabel\n" +
544         "%n = OpVariable %_ptr_int Function\n" +
545         "%load = OpLoad %int %n\n" +
546         "%2 = OpSMod %int %int_0 %load\n" +
547         "OpReturn\n" +
548         "OpFunctionEnd",
549     2, 0),
550   // Test case 9: fold n%0 (signed)
551   InstructionFoldingCase<uint32_t>(
552     Header() + "%main = OpFunction %void None %void_func\n" +
553         "%main_lab = OpLabel\n" +
554         "%n = OpVariable %_ptr_int Function\n" +
555         "%load = OpLoad %int %n\n" +
556         "%2 = OpSMod %int %load %int_0\n" +
557         "OpReturn\n" +
558         "OpFunctionEnd",
559     2, 0),
560   // Test case 10: fold 0%n (unsigned)
561   InstructionFoldingCase<uint32_t>(
562     Header() + "%main = OpFunction %void None %void_func\n" +
563         "%main_lab = OpLabel\n" +
564         "%n = OpVariable %_ptr_uint Function\n" +
565         "%load = OpLoad %uint %n\n" +
566         "%2 = OpUMod %uint %uint_0 %load\n" +
567         "OpReturn\n" +
568         "OpFunctionEnd",
569     2, 0),
570   // Test case 11: fold n%0 (unsigned)
571   InstructionFoldingCase<uint32_t>(
572     Header() + "%main = OpFunction %void None %void_func\n" +
573         "%main_lab = OpLabel\n" +
574         "%n = OpVariable %_ptr_uint Function\n" +
575         "%load = OpLoad %uint %n\n" +
576         "%2 = OpUMod %uint %load %uint_0\n" +
577         "OpReturn\n" +
578         "OpFunctionEnd",
579     2, 0),
580   // Test case 12: fold n << 32
581   InstructionFoldingCase<uint32_t>(
582       Header() + "%main = OpFunction %void None %void_func\n" +
583           "%main_lab = OpLabel\n" +
584           "%n = OpVariable %_ptr_uint Function\n" +
585           "%load = OpLoad %uint %n\n" +
586           "%2 = OpShiftLeftLogical %uint %load %uint_32\n" +
587           "OpReturn\n" +
588           "OpFunctionEnd",
589       2, 0),
590   // Test case 13: fold n >> 32
591   InstructionFoldingCase<uint32_t>(
592       Header() + "%main = OpFunction %void None %void_func\n" +
593           "%main_lab = OpLabel\n" +
594           "%n = OpVariable %_ptr_uint Function\n" +
595           "%load = OpLoad %uint %n\n" +
596           "%2 = OpShiftRightLogical %uint %load %uint_32\n" +
597           "OpReturn\n" +
598           "OpFunctionEnd",
599       2, 0),
600   // Test case 14: fold n | 0xFFFFFFFF
601   InstructionFoldingCase<uint32_t>(
602       Header() + "%main = OpFunction %void None %void_func\n" +
603   "%main_lab = OpLabel\n" +
604   "%n = OpVariable %_ptr_uint Function\n" +
605   "%load = OpLoad %uint %n\n" +
606   "%2 = OpBitwiseOr %uint %load %uint_max\n" +
607   "OpReturn\n" +
608   "OpFunctionEnd",
609   2, 0xFFFFFFFF),
610   // Test case 15: fold 0xFFFFFFFF | n
611   InstructionFoldingCase<uint32_t>(
612       Header() + "%main = OpFunction %void None %void_func\n" +
613           "%main_lab = OpLabel\n" +
614           "%n = OpVariable %_ptr_uint Function\n" +
615           "%load = OpLoad %uint %n\n" +
616           "%2 = OpBitwiseOr %uint %uint_max %load\n" +
617           "OpReturn\n" +
618           "OpFunctionEnd",
619       2, 0xFFFFFFFF),
620   // Test case 16: fold n & 0
621   InstructionFoldingCase<uint32_t>(
622       Header() + "%main = OpFunction %void None %void_func\n" +
623           "%main_lab = OpLabel\n" +
624           "%n = OpVariable %_ptr_uint Function\n" +
625           "%load = OpLoad %uint %n\n" +
626           "%2 = OpBitwiseAnd %uint %load %uint_0\n" +
627           "OpReturn\n" +
628           "OpFunctionEnd",
629       2, 0),
630   // Test case 17: fold 1/0 (signed)
631   InstructionFoldingCase<uint32_t>(
632       Header() + "%main = OpFunction %void None %void_func\n" +
633           "%main_lab = OpLabel\n" +
634           "%2 = OpSDiv %int %int_1 %int_0\n" +
635           "OpReturn\n" +
636           "OpFunctionEnd",
637       2, 0),
638   // Test case 18: fold 1/0 (unsigned)
639   InstructionFoldingCase<uint32_t>(
640       Header() + "%main = OpFunction %void None %void_func\n" +
641           "%main_lab = OpLabel\n" +
642           "%2 = OpUDiv %uint %uint_1 %uint_0\n" +
643           "OpReturn\n" +
644           "OpFunctionEnd",
645       2, 0),
646   // Test case 19: fold OpSRem 1 0 (signed)
647   InstructionFoldingCase<uint32_t>(
648       Header() + "%main = OpFunction %void None %void_func\n" +
649           "%main_lab = OpLabel\n" +
650           "%2 = OpSRem %int %int_1 %int_0\n" +
651           "OpReturn\n" +
652           "OpFunctionEnd",
653       2, 0),
654   // Test case 20: fold 1%0 (signed)
655   InstructionFoldingCase<uint32_t>(
656       Header() + "%main = OpFunction %void None %void_func\n" +
657           "%main_lab = OpLabel\n" +
658           "%2 = OpSMod %int %int_1 %int_0\n" +
659           "OpReturn\n" +
660           "OpFunctionEnd",
661       2, 0),
662   // Test case 21: fold 1%0 (unsigned)
663   InstructionFoldingCase<uint32_t>(
664       Header() + "%main = OpFunction %void None %void_func\n" +
665           "%main_lab = OpLabel\n" +
666           "%2 = OpUMod %uint %uint_1 %uint_0\n" +
667           "OpReturn\n" +
668           "OpFunctionEnd",
669       2, 0),
670   // Test case 22: fold unsigned n >> 42 (undefined, so set to zero).
671   InstructionFoldingCase<uint32_t>(
672       Header() + "%main = OpFunction %void None %void_func\n" +
673           "%main_lab = OpLabel\n" +
674           "%n = OpVariable %_ptr_uint Function\n" +
675           "%load = OpLoad %uint %n\n" +
676           "%2 = OpShiftRightLogical %uint %load %uint_42\n" +
677           "OpReturn\n" +
678           "OpFunctionEnd",
679       2, 0),
680   // Test case 23: fold signed n >> 42 (undefined, so set to zero).
681   InstructionFoldingCase<uint32_t>(
682       Header() + "%main = OpFunction %void None %void_func\n" +
683           "%main_lab = OpLabel\n" +
684           "%n = OpVariable %_ptr_int Function\n" +
685           "%load = OpLoad %int %n\n" +
686           "%2 = OpShiftRightLogical %int %load %uint_42\n" +
687           "OpReturn\n" +
688           "OpFunctionEnd",
689       2, 0),
690   // Test case 24: fold n << 42 (undefined, so set to zero).
691   InstructionFoldingCase<uint32_t>(
692       Header() + "%main = OpFunction %void None %void_func\n" +
693           "%main_lab = OpLabel\n" +
694           "%n = OpVariable %_ptr_int Function\n" +
695           "%load = OpLoad %int %n\n" +
696           "%2 = OpShiftLeftLogical %int %load %uint_42\n" +
697           "OpReturn\n" +
698           "OpFunctionEnd",
699       2, 0),
700   // Test case 25: fold -24 >> 32 (defined as -1)
701   InstructionFoldingCase<uint32_t>(
702       Header() + "%main = OpFunction %void None %void_func\n" +
703           "%main_lab = OpLabel\n" +
704           "%2 = OpShiftRightArithmetic %int %int_n24 %uint_32\n" +
705           "OpReturn\n" +
706           "OpFunctionEnd",
707       2, -1),
708   // Test case 26: fold 2 >> 32 (signed)
709   InstructionFoldingCase<uint32_t>(
710       Header() + "%main = OpFunction %void None %void_func\n" +
711           "%main_lab = OpLabel\n" +
712           "%2 = OpShiftRightArithmetic %int %int_2 %uint_32\n" +
713           "OpReturn\n" +
714           "OpFunctionEnd",
715       2, 0),
716   // Test case 27: fold 2 >> 32 (unsigned)
717   InstructionFoldingCase<uint32_t>(
718       Header() + "%main = OpFunction %void None %void_func\n" +
719           "%main_lab = OpLabel\n" +
720           "%2 = OpShiftRightLogical %int %int_2 %uint_32\n" +
721           "OpReturn\n" +
722           "OpFunctionEnd",
723       2, 0),
724   // Test case 28: fold 2 << 32
725   InstructionFoldingCase<uint32_t>(
726       Header() + "%main = OpFunction %void None %void_func\n" +
727           "%main_lab = OpLabel\n" +
728           "%2 = OpShiftLeftLogical %int %int_2 %uint_32\n" +
729           "OpReturn\n" +
730           "OpFunctionEnd",
731       2, 0),
732   // Test case 29: fold -INT_MIN
733   InstructionFoldingCase<uint32_t>(
734       Header() + "%main = OpFunction %void None %void_func\n" +
735           "%main_lab = OpLabel\n" +
736           "%2 = OpSNegate %int %int_min\n" +
737           "OpReturn\n" +
738           "OpFunctionEnd",
739       2, std::numeric_limits<int32_t>::min()),
740   // Test case 30: fold UMin 3 4
741   InstructionFoldingCase<uint32_t>(
742       Header() + "%main = OpFunction %void None %void_func\n" +
743           "%main_lab = OpLabel\n" +
744           "%2 = OpExtInst %uint %1 UMin %uint_3 %uint_4\n" +
745           "OpReturn\n" +
746           "OpFunctionEnd",
747       2, 3),
748   // Test case 31: fold UMin 4 2
749   InstructionFoldingCase<uint32_t>(
750       Header() + "%main = OpFunction %void None %void_func\n" +
751           "%main_lab = OpLabel\n" +
752           "%2 = OpExtInst %uint %1 UMin %uint_4 %uint_2\n" +
753           "OpReturn\n" +
754           "OpFunctionEnd",
755       2, 2),
756   // Test case 32: fold SMin 3 4
757   InstructionFoldingCase<uint32_t>(
758       Header() + "%main = OpFunction %void None %void_func\n" +
759           "%main_lab = OpLabel\n" +
760           "%2 = OpExtInst %int %1 UMin %int_3 %int_4\n" +
761           "OpReturn\n" +
762           "OpFunctionEnd",
763       2, 3),
764   // Test case 33: fold SMin 4 2
765   InstructionFoldingCase<uint32_t>(
766       Header() + "%main = OpFunction %void None %void_func\n" +
767           "%main_lab = OpLabel\n" +
768           "%2 = OpExtInst %int %1 SMin %int_4 %int_2\n" +
769           "OpReturn\n" +
770           "OpFunctionEnd",
771       2, 2),
772   // Test case 34: fold UMax 3 4
773   InstructionFoldingCase<uint32_t>(
774       Header() + "%main = OpFunction %void None %void_func\n" +
775           "%main_lab = OpLabel\n" +
776           "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_4\n" +
777           "OpReturn\n" +
778           "OpFunctionEnd",
779       2, 4),
780   // Test case 35: fold UMax 3 2
781   InstructionFoldingCase<uint32_t>(
782       Header() + "%main = OpFunction %void None %void_func\n" +
783           "%main_lab = OpLabel\n" +
784           "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_2\n" +
785           "OpReturn\n" +
786           "OpFunctionEnd",
787       2, 3),
788   // Test case 36: fold SMax 3 4
789   InstructionFoldingCase<uint32_t>(
790       Header() + "%main = OpFunction %void None %void_func\n" +
791           "%main_lab = OpLabel\n" +
792           "%2 = OpExtInst %int %1 UMax %int_3 %int_4\n" +
793           "OpReturn\n" +
794           "OpFunctionEnd",
795       2, 4),
796   // Test case 37: fold SMax 3 2
797   InstructionFoldingCase<uint32_t>(
798       Header() + "%main = OpFunction %void None %void_func\n" +
799           "%main_lab = OpLabel\n" +
800           "%2 = OpExtInst %int %1 SMax %int_3 %int_2\n" +
801           "OpReturn\n" +
802           "OpFunctionEnd",
803       2, 3),
804   // Test case 38: fold UClamp 2 3 4
805   InstructionFoldingCase<uint32_t>(
806       Header() + "%main = OpFunction %void None %void_func\n" +
807           "%main_lab = OpLabel\n" +
808           "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_3 %uint_4\n" +
809           "OpReturn\n" +
810           "OpFunctionEnd",
811       2, 3),
812   // Test case 39: fold UClamp 2 0 4
813   InstructionFoldingCase<uint32_t>(
814       Header() + "%main = OpFunction %void None %void_func\n" +
815           "%main_lab = OpLabel\n" +
816           "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_4\n" +
817           "OpReturn\n" +
818           "OpFunctionEnd",
819       2, 2),
820   // Test case 40: fold UClamp 2 0 1
821   InstructionFoldingCase<uint32_t>(
822       Header() + "%main = OpFunction %void None %void_func\n" +
823           "%main_lab = OpLabel\n" +
824           "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_1\n" +
825           "OpReturn\n" +
826           "OpFunctionEnd",
827       2, 1),
828   // Test case 41: fold SClamp 2 3 4
829   InstructionFoldingCase<uint32_t>(
830       Header() + "%main = OpFunction %void None %void_func\n" +
831           "%main_lab = OpLabel\n" +
832           "%2 = OpExtInst %int %1 SClamp %int_2 %int_3 %int_4\n" +
833           "OpReturn\n" +
834           "OpFunctionEnd",
835       2, 3),
836   // Test case 42: fold SClamp 2 0 4
837   InstructionFoldingCase<uint32_t>(
838       Header() + "%main = OpFunction %void None %void_func\n" +
839           "%main_lab = OpLabel\n" +
840           "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_4\n" +
841           "OpReturn\n" +
842           "OpFunctionEnd",
843       2, 2),
844   // Test case 43: fold SClamp 2 0 1
845   InstructionFoldingCase<uint32_t>(
846       Header() + "%main = OpFunction %void None %void_func\n" +
847           "%main_lab = OpLabel\n" +
848           "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_1\n" +
849           "OpReturn\n" +
850           "OpFunctionEnd",
851       2, 1),
852   // Test case 44: SClamp 1 2 x
853   InstructionFoldingCase<uint32_t>(
854       Header() + "%main = OpFunction %void None %void_func\n" +
855           "%main_lab = OpLabel\n" +
856           "%undef = OpUndef %int\n" +
857           "%2 = OpExtInst %int %1 SClamp %int_1 %int_2 %undef\n" +
858           "OpReturn\n" +
859           "OpFunctionEnd",
860       2, 2),
861   // Test case 45: SClamp 2 x 1
862   InstructionFoldingCase<uint32_t>(
863       Header() + "%main = OpFunction %void None %void_func\n" +
864           "%main_lab = OpLabel\n" +
865           "%undef = OpUndef %int\n" +
866           "%2 = OpExtInst %int %1 SClamp %int_2 %undef %int_1\n" +
867           "OpReturn\n" +
868           "OpFunctionEnd",
869       2, 1),
870   // Test case 46: UClamp 1 2 x
871   InstructionFoldingCase<uint32_t>(
872       Header() + "%main = OpFunction %void None %void_func\n" +
873           "%main_lab = OpLabel\n" +
874           "%undef = OpUndef %uint\n" +
875           "%2 = OpExtInst %uint %1 UClamp %uint_1 %uint_2 %undef\n" +
876           "OpReturn\n" +
877           "OpFunctionEnd",
878       2, 2),
879   // Test case 47: UClamp 2 x 1
880   InstructionFoldingCase<uint32_t>(
881       Header() + "%main = OpFunction %void None %void_func\n" +
882           "%main_lab = OpLabel\n" +
883           "%undef = OpUndef %uint\n" +
884           "%2 = OpExtInst %uint %1 UClamp %uint_2 %undef %uint_1\n" +
885           "OpReturn\n" +
886           "OpFunctionEnd",
887       2, 1),
888     // Test case 48: Bit-cast int 0 to unsigned int
889     InstructionFoldingCase<uint32_t>(
890         Header() + "%main = OpFunction %void None %void_func\n" +
891             "%main_lab = OpLabel\n" +
892             "%2 = OpBitcast %uint %int_0\n" +
893             "OpReturn\n" +
894             "OpFunctionEnd",
895         2, 0),
896     // Test case 49: Bit-cast int -24 to unsigned int
897     InstructionFoldingCase<uint32_t>(
898         Header() + "%main = OpFunction %void None %void_func\n" +
899             "%main_lab = OpLabel\n" +
900             "%2 = OpBitcast %uint %int_n24\n" +
901             "OpReturn\n" +
902             "OpFunctionEnd",
903         2, static_cast<uint32_t>(-24)),
904     // Test case 50: Bit-cast float 1.0f to unsigned int
905     InstructionFoldingCase<uint32_t>(
906         Header() + "%main = OpFunction %void None %void_func\n" +
907             "%main_lab = OpLabel\n" +
908             "%2 = OpBitcast %uint %float_1\n" +
909             "OpReturn\n" +
910             "OpFunctionEnd",
911         2, static_cast<uint32_t>(0x3f800000)),
912     // Test case 51: Bit-cast ushort 0xBC00 to ushort
913     InstructionFoldingCase<uint32_t>(
914         Header() + "%main = OpFunction %void None %void_func\n" +
915             "%main_lab = OpLabel\n" +
916             "%2 = OpBitcast %ushort %ushort_0xBC00\n" +
917             "OpReturn\n" +
918             "OpFunctionEnd",
919         2, 0xBC00),
920     // Test case 52: Bit-cast short 0xBC00 to ushort
921     InstructionFoldingCase<uint32_t>(
922         Header() + "%main = OpFunction %void None %void_func\n" +
923             "%main_lab = OpLabel\n" +
924             "%2 = OpBitcast %ushort %short_0xBC00\n" +
925             "OpReturn\n" +
926             "OpFunctionEnd",
927         2, 0xFFFFBC00),
928     // Test case 53: Bit-cast half 1 to ushort
929     InstructionFoldingCase<uint32_t>(
930         Header() + "%main = OpFunction %void None %void_func\n" +
931             "%main_lab = OpLabel\n" +
932             "%2 = OpBitcast %ushort %half_1\n" +
933             "OpReturn\n" +
934             "OpFunctionEnd",
935         2, 0x3C00),
936     // Test case 54: Bit-cast ushort 0xBC00 to short
937     InstructionFoldingCase<uint32_t>(
938         Header() + "%main = OpFunction %void None %void_func\n" +
939             "%main_lab = OpLabel\n" +
940             "%2 = OpBitcast %short %ushort_0xBC00\n" +
941             "OpReturn\n" +
942             "OpFunctionEnd",
943         2, 0xBC00),
944     // Test case 55: Bit-cast short 0xBC00 to short
945     InstructionFoldingCase<uint32_t>(
946         Header() + "%main = OpFunction %void None %void_func\n" +
947             "%main_lab = OpLabel\n" +
948             "%2 = OpBitcast %short %short_0xBC00\n" +
949             "OpReturn\n" +
950             "OpFunctionEnd",
951         2, 0xFFFFBC00),
952     // Test case 56: Bit-cast half 1 to short
953     InstructionFoldingCase<uint32_t>(
954         Header() + "%main = OpFunction %void None %void_func\n" +
955             "%main_lab = OpLabel\n" +
956             "%2 = OpBitcast %short %half_1\n" +
957             "OpReturn\n" +
958             "OpFunctionEnd",
959         2, 0x3C00),
960     // Test case 57: Bit-cast ushort 0xBC00 to half
961     InstructionFoldingCase<uint32_t>(
962         Header() + "%main = OpFunction %void None %void_func\n" +
963             "%main_lab = OpLabel\n" +
964             "%2 = OpBitcast %half %ushort_0xBC00\n" +
965             "OpReturn\n" +
966             "OpFunctionEnd",
967         2, 0xBC00),
968     // Test case 58: Bit-cast short 0xBC00 to half
969     InstructionFoldingCase<uint32_t>(
970         Header() + "%main = OpFunction %void None %void_func\n" +
971             "%main_lab = OpLabel\n" +
972             "%2 = OpBitcast %half %short_0xBC00\n" +
973             "OpReturn\n" +
974             "OpFunctionEnd",
975         2, 0xFFFFBC00),
976     // Test case 59: Bit-cast half 1 to half
977     InstructionFoldingCase<uint32_t>(
978         Header() + "%main = OpFunction %void None %void_func\n" +
979             "%main_lab = OpLabel\n" +
980             "%2 = OpBitcast %half %half_1\n" +
981             "OpReturn\n" +
982             "OpFunctionEnd",
983         2, 0x3C00),
984     // Test case 60: Bit-cast ubyte 1 to byte
985     InstructionFoldingCase<uint32_t>(
986         Header() + "%main = OpFunction %void None %void_func\n" +
987             "%main_lab = OpLabel\n" +
988             "%2 = OpBitcast %byte %ubyte_1\n" +
989             "OpReturn\n" +
990             "OpFunctionEnd",
991         2, 1),
992     // Test case 61: Bit-cast byte -1 to ubyte
993     InstructionFoldingCase<uint32_t>(
994         Header() + "%main = OpFunction %void None %void_func\n" +
995             "%main_lab = OpLabel\n" +
996             "%2 = OpBitcast %ubyte %byte_n1\n" +
997             "OpReturn\n" +
998             "OpFunctionEnd",
999         2, 0xFFFFFFFF),
1000     // Test case 62: Negate 2.
1001     InstructionFoldingCase<uint32_t>(
1002         Header() + "%main = OpFunction %void None %void_func\n" +
1003             "%main_lab = OpLabel\n" +
1004             "%2 = OpSNegate %int %int_2\n" +
1005             "OpReturn\n" +
1006             "OpFunctionEnd",
1007         2, -2),
1008     // Test case 63: Negate negative short.
1009     InstructionFoldingCase<uint32_t>(
1010         Header() + "%main = OpFunction %void None %void_func\n" +
1011             "%main_lab = OpLabel\n" +
1012             "%2 = OpSNegate %short %short_0xBC00\n" +
1013             "OpReturn\n" +
1014             "OpFunctionEnd",
1015         2, 0x4400 /* expected to be sign extended. */),
1016     // Test case 64: Negate positive short.
1017     InstructionFoldingCase<uint32_t>(
1018         Header() + "%main = OpFunction %void None %void_func\n" +
1019             "%main_lab = OpLabel\n" +
1020             "%2 = OpSNegate %short %short_0x4400\n" +
1021             "OpReturn\n" +
1022             "OpFunctionEnd",
1023         2, 0xFFFFBC00 /* expected to be sign extended. */),
1024     // Test case 65: Negate a negative short.
1025     InstructionFoldingCase<uint32_t>(
1026         Header() + "%main = OpFunction %void None %void_func\n" +
1027             "%main_lab = OpLabel\n" +
1028             "%2 = OpSNegate %ushort %ushort_0xBC00\n" +
1029             "OpReturn\n" +
1030             "OpFunctionEnd",
1031         2, 0x4400 /* expected to be zero extended. */),
1032     // Test case 66: Negate positive short.
1033     InstructionFoldingCase<uint32_t>(
1034         Header() + "%main = OpFunction %void None %void_func\n" +
1035             "%main_lab = OpLabel\n" +
1036             "%2 = OpSNegate %ushort %ushort_0x4400\n" +
1037             "OpReturn\n" +
1038             "OpFunctionEnd",
1039         2, 0xBC00 /* expected to be zero extended. */),
1040     // Test case 67: Fold 2 + 3 (short)
1041     InstructionFoldingCase<uint32_t>(
1042         Header() + "%main = OpFunction %void None %void_func\n" +
1043             "%main_lab = OpLabel\n" +
1044             "%2 = OpIAdd %short %short_2 %short_3\n" +
1045             "OpReturn\n" +
1046             "OpFunctionEnd",
1047         2, 5),
1048     // Test case 68: Fold 2 + -5 (short)
1049     InstructionFoldingCase<uint32_t>(
1050         Header() + "%main = OpFunction %void None %void_func\n" +
1051             "%main_lab = OpLabel\n" +
1052             "%2 = OpIAdd %short %short_2 %short_n5\n" +
1053             "OpReturn\n" +
1054             "OpFunctionEnd",
1055         2, -3),
1056   // Test case 69: Fold int(3ll)
1057   InstructionFoldingCase<uint32_t>(
1058       Header() + "%main = OpFunction %void None %void_func\n" +
1059           "%main_lab = OpLabel\n" +
1060           "%2 = OpSConvert %int %long_3\n" +
1061           "OpReturn\n" +
1062           "OpFunctionEnd",
1063       2, 3),
1064   // Test case 70: Fold short(-3ll)
1065   InstructionFoldingCase<uint32_t>(
1066       Header() + "%main = OpFunction %void None %void_func\n" +
1067           "%main_lab = OpLabel\n" +
1068           "%2 = OpSConvert %short %long_n3\n" +
1069           "OpReturn\n" +
1070           "OpFunctionEnd",
1071       2, -3),
1072   // Test case 71: Fold short(32768ll) - This should do a sign extend when
1073   // converting to short.
1074   InstructionFoldingCase<uint32_t>(
1075       Header() + "%main = OpFunction %void None %void_func\n" +
1076           "%main_lab = OpLabel\n" +
1077           "%2 = OpSConvert %short %long_32768\n" +
1078           "OpReturn\n" +
1079           "OpFunctionEnd",
1080       2, -32768),
1081   // Test case 72: Fold short(-57344) - This should do a sign extend when
1082   // converting to short making the upper bits 0.
1083   InstructionFoldingCase<uint32_t>(
1084       Header() + "%main = OpFunction %void None %void_func\n" +
1085           "%main_lab = OpLabel\n" +
1086           "%2 = OpSConvert %short %long_n57344\n" +
1087           "OpReturn\n" +
1088           "OpFunctionEnd",
1089       2, 8192),
1090   // Test case 73: Fold int(-5(short)). The -5 should be interpreted as an unsigned value, and be zero extended to 32-bits.
1091   InstructionFoldingCase<uint32_t>(
1092       Header() + "%main = OpFunction %void None %void_func\n" +
1093           "%main_lab = OpLabel\n" +
1094           "%2 = OpUConvert %uint %short_n5\n" +
1095           "OpReturn\n" +
1096           "OpFunctionEnd",
1097       2, 65531),
1098   // Test case 74: Fold short(-24(int)). The upper bits should be cleared. So 0xFFFFFFE8 should become 0x0000FFE8.
1099   InstructionFoldingCase<uint32_t>(
1100       Header() + "%main = OpFunction %void None %void_func\n" +
1101           "%main_lab = OpLabel\n" +
1102           "%2 = OpUConvert %ushort %int_n24\n" +
1103           "OpReturn\n" +
1104           "OpFunctionEnd",
1105       2, 65512)
1106 ));
1107 // clang-format on
1108 
1109 using LongIntegerInstructionFoldingTest =
1110     ::testing::TestWithParam<InstructionFoldingCase<uint64_t>>;
1111 
TEST_P(LongIntegerInstructionFoldingTest,Case)1112 TEST_P(LongIntegerInstructionFoldingTest, Case) {
1113   const auto& tc = GetParam();
1114 
1115   std::unique_ptr<IRContext> context;
1116   Instruction* inst;
1117   std::tie(context, inst) =
1118       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1119   CheckForExpectedScalarConstant(
1120       inst, tc.expected_result, [](const analysis::Constant* c) {
1121         return c->AsScalarConstant()->GetU64BitValue();
1122       });
1123 }
1124 
1125 INSTANTIATE_TEST_SUITE_P(
1126     TestCase, LongIntegerInstructionFoldingTest,
1127     ::testing::Values(
1128         // Test case 0: fold 1+4611686018427387904
1129         InstructionFoldingCase<uint64_t>(
1130             Header() + "%main = OpFunction %void None %void_func\n" +
1131                 "%main_lab = OpLabel\n" +
1132                 "%n = OpVariable %_ptr_int Function\n" +
1133                 "%load = OpLoad %int %n\n" +
1134                 "%2 = OpIAdd %long %long_1 %long_4611686018427387904\n" +
1135                 "OpReturn\n" + "OpFunctionEnd",
1136             2, 1 + 4611686018427387904),
1137         // Test case 1: fold 1-4611686018427387904
1138         InstructionFoldingCase<uint64_t>(
1139             Header() + "%main = OpFunction %void None %void_func\n" +
1140                 "%main_lab = OpLabel\n" +
1141                 "%n = OpVariable %_ptr_int Function\n" +
1142                 "%load = OpLoad %int %n\n" +
1143                 "%2 = OpISub %long %long_1 %long_4611686018427387904\n" +
1144                 "OpReturn\n" + "OpFunctionEnd",
1145             2, 1 - 4611686018427387904),
1146         // Test case 2: fold 2*4611686018427387904
1147         InstructionFoldingCase<uint64_t>(
1148             Header() + "%main = OpFunction %void None %void_func\n" +
1149                 "%main_lab = OpLabel\n" +
1150                 "%n = OpVariable %_ptr_int Function\n" +
1151                 "%load = OpLoad %int %n\n" +
1152                 "%2 = OpIMul %long %long_2 %long_4611686018427387904\n" +
1153                 "OpReturn\n" + "OpFunctionEnd",
1154             2, 9223372036854775808ull),
1155         // Test case 3: fold 4611686018427387904/2 (unsigned)
1156         InstructionFoldingCase<uint64_t>(
1157             Header() + "%main = OpFunction %void None %void_func\n" +
1158                 "%main_lab = OpLabel\n" +
1159                 "%n = OpVariable %_ptr_int Function\n" +
1160                 "%load = OpLoad %int %n\n" +
1161                 "%2 = OpUDiv %ulong %ulong_4611686018427387904 %ulong_2\n" +
1162                 "OpReturn\n" + "OpFunctionEnd",
1163             2, 4611686018427387904 / 2),
1164         // Test case 4: fold 4611686018427387904/2 (signed)
1165         InstructionFoldingCase<uint64_t>(
1166             Header() + "%main = OpFunction %void None %void_func\n" +
1167                 "%main_lab = OpLabel\n" +
1168                 "%n = OpVariable %_ptr_int Function\n" +
1169                 "%load = OpLoad %int %n\n" +
1170                 "%2 = OpSDiv %long %long_4611686018427387904 %long_2\n" +
1171                 "OpReturn\n" + "OpFunctionEnd",
1172             2, 4611686018427387904 / 2),
1173         // Test case 5: fold -4611686018427387904/2 (signed)
1174         InstructionFoldingCase<uint64_t>(
1175             Header() + "%main = OpFunction %void None %void_func\n" +
1176                 "%main_lab = OpLabel\n" +
1177                 "%n = OpVariable %_ptr_int Function\n" +
1178                 "%load = OpLoad %int %n\n" +
1179                 "%2 = OpSDiv %long %long_n4611686018427387904 %long_2\n" +
1180                 "OpReturn\n" + "OpFunctionEnd",
1181             2, -4611686018427387904 / 2),
1182         // Test case 6: fold 4611686018427387904 mod 7 (unsigned)
1183         InstructionFoldingCase<uint64_t>(
1184             Header() + "%main = OpFunction %void None %void_func\n" +
1185                 "%main_lab = OpLabel\n" +
1186                 "%n = OpVariable %_ptr_int Function\n" +
1187                 "%load = OpLoad %int %n\n" +
1188                 "%2 = OpUMod %ulong %ulong_4611686018427387904 %ulong_7\n" +
1189                 "OpReturn\n" + "OpFunctionEnd",
1190             2, 4611686018427387904ull % 7ull),
1191         // Test case 7: fold 7 mod 3 (signed)
1192         InstructionFoldingCase<uint64_t>(
1193             Header() + "%main = OpFunction %void None %void_func\n" +
1194                 "%main_lab = OpLabel\n" +
1195                 "%n = OpVariable %_ptr_int Function\n" +
1196                 "%load = OpLoad %int %n\n" +
1197                 "%2 = OpSMod %long %long_7 %long_3\n" + "OpReturn\n" +
1198                 "OpFunctionEnd",
1199             2, 1ull),
1200         // Test case 8: fold 7 rem 3 (signed)
1201         InstructionFoldingCase<uint64_t>(
1202             Header() + "%main = OpFunction %void None %void_func\n" +
1203                 "%main_lab = OpLabel\n" +
1204                 "%n = OpVariable %_ptr_int Function\n" +
1205                 "%load = OpLoad %int %n\n" +
1206                 "%2 = OpSRem %long %long_7 %long_3\n" + "OpReturn\n" +
1207                 "OpFunctionEnd",
1208             2, 1ull),
1209         // Test case 9: fold 7 mod -3 (signed)
1210         InstructionFoldingCase<uint64_t>(
1211             Header() + "%main = OpFunction %void None %void_func\n" +
1212                 "%main_lab = OpLabel\n" +
1213                 "%n = OpVariable %_ptr_int Function\n" +
1214                 "%load = OpLoad %int %n\n" +
1215                 "%2 = OpSMod %long %long_7 %long_n3\n" + "OpReturn\n" +
1216                 "OpFunctionEnd",
1217             2, -2ll),
1218         // Test case 10: fold 7 rem 3 (signed)
1219         InstructionFoldingCase<uint64_t>(
1220             Header() + "%main = OpFunction %void None %void_func\n" +
1221                 "%main_lab = OpLabel\n" +
1222                 "%n = OpVariable %_ptr_int Function\n" +
1223                 "%load = OpLoad %int %n\n" +
1224                 "%2 = OpSRem %long %long_7 %long_n3\n" + "OpReturn\n" +
1225                 "OpFunctionEnd",
1226             2, 1ll),
1227         // Test case 11: fold -7 mod 3 (signed)
1228         InstructionFoldingCase<uint64_t>(
1229             Header() + "%main = OpFunction %void None %void_func\n" +
1230                 "%main_lab = OpLabel\n" +
1231                 "%n = OpVariable %_ptr_int Function\n" +
1232                 "%load = OpLoad %int %n\n" +
1233                 "%2 = OpSMod %long %long_n7 %long_3\n" + "OpReturn\n" +
1234                 "OpFunctionEnd",
1235             2, 2ll),
1236         // Test case 12: fold -7 rem 3 (signed)
1237         InstructionFoldingCase<uint64_t>(
1238             Header() + "%main = OpFunction %void None %void_func\n" +
1239                 "%main_lab = OpLabel\n" +
1240                 "%n = OpVariable %_ptr_int Function\n" +
1241                 "%load = OpLoad %int %n\n" +
1242                 "%2 = OpSRem %long %long_n7 %long_3\n" + "OpReturn\n" +
1243                 "OpFunctionEnd",
1244             2, -1ll),
1245         // Test case 13: fold long(-24)
1246         InstructionFoldingCase<uint64_t>(
1247             Header() + "%main = OpFunction %void None %void_func\n" +
1248                 "%main_lab = OpLabel\n" +
1249                 "%n = OpVariable %_ptr_int Function\n" +
1250                 "%load = OpLoad %int %n\n" +
1251                 "%2 = OpSConvert %long %int_n24\n" + "OpReturn\n" +
1252                 "OpFunctionEnd",
1253             2, -24ll),
1254         // Test case 14: fold long(-24)
1255         InstructionFoldingCase<uint64_t>(
1256             Header() + "%main = OpFunction %void None %void_func\n" +
1257                 "%main_lab = OpLabel\n" +
1258                 "%n = OpVariable %_ptr_int Function\n" +
1259                 "%load = OpLoad %int %n\n" + "%2 = OpSConvert %long %int_10\n" +
1260                 "OpReturn\n" + "OpFunctionEnd",
1261             2, 10ll),
1262         // Test case 15: fold long(-24(short)).
1263         // The upper bits should be cleared. So 0xFFFFFFE8 should become
1264         // 0x000000000000FFE8.
1265         InstructionFoldingCase<uint64_t>(
1266             Header() + "%main = OpFunction %void None %void_func\n" +
1267                 "%main_lab = OpLabel\n" + "%2 = OpUConvert %ulong %short_n5\n" +
1268                 "OpReturn\n" + "OpFunctionEnd",
1269             2, 65531ull)));
1270 
1271 using UIntVectorInstructionFoldingTest =
1272     ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint32_t>>>;
1273 
TEST_P(UIntVectorInstructionFoldingTest,Case)1274 TEST_P(UIntVectorInstructionFoldingTest, Case) {
1275   const auto& tc = GetParam();
1276 
1277   std::unique_ptr<IRContext> context;
1278   Instruction* inst;
1279   std::tie(context, inst) =
1280       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1281   CheckForExpectedVectorConstant(
1282       inst, tc.expected_result,
1283       [](const analysis::Constant* c) { return c->GetU32(); });
1284 }
1285 
1286 // clang-format off
1287 INSTANTIATE_TEST_SUITE_P(TestCase, UIntVectorInstructionFoldingTest,
1288 ::testing::Values(
1289     // Test case 0: fold 0*n
1290     InstructionFoldingCase<std::vector<uint32_t>>(
1291         Header() + "%main = OpFunction %void None %void_func\n" +
1292             "%main_lab = OpLabel\n" +
1293             "%n = OpVariable %_ptr_int Function\n" +
1294             "%load = OpLoad %int %n\n" +
1295             "%2 = OpVectorShuffle %v2int %v2int_2_2 %v2int_2_3 0 3\n" +
1296             "OpReturn\n" +
1297             "OpFunctionEnd",
1298         2, {2,3}),
1299     InstructionFoldingCase<std::vector<uint32_t>>(
1300       Header() + "%main = OpFunction %void None %void_func\n" +
1301           "%main_lab = OpLabel\n" +
1302           "%n = OpVariable %_ptr_int Function\n" +
1303           "%load = OpLoad %int %n\n" +
1304           "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
1305           "OpReturn\n" +
1306           "OpFunctionEnd",
1307       2, {0,3}),
1308     // Test case 4: fold bit-cast int -24 to unsigned int
1309     InstructionFoldingCase<std::vector<uint32_t>>(
1310       Header() + "%main = OpFunction %void None %void_func\n" +
1311           "%main_lab = OpLabel\n" +
1312           "%n = OpVariable %_ptr_int Function\n" +
1313           "%load = OpLoad %int %n\n" +
1314           "%2 = OpBitcast %v2uint %v2int_min_max\n" +
1315           "OpReturn\n" +
1316           "OpFunctionEnd",
1317       2, {2147483648, 2147483647}),
1318     // Test case 5: fold SNegate vector of uint
1319     InstructionFoldingCase<std::vector<uint32_t>>(
1320       Header() + "%main = OpFunction %void None %void_func\n" +
1321           "%main_lab = OpLabel\n" +
1322           "%n = OpVariable %_ptr_int Function\n" +
1323           "%load = OpLoad %int %n\n" +
1324           "%2 = OpSNegate %v2uint %v2uint_0x3f800000_0xbf800000\n" +
1325           "OpReturn\n" +
1326           "OpFunctionEnd",
1327       2, {static_cast<uint32_t>(-0x3f800000), static_cast<uint32_t>(-0xbf800000)}),
1328     // Test case 6: fold vector components of uint (including integer overflow)
1329     InstructionFoldingCase<std::vector<uint32_t>>(
1330       Header() + "%main = OpFunction %void None %void_func\n" +
1331           "%main_lab = OpLabel\n" +
1332           "%2 = OpIAdd %v2uint %v2uint_0x3f800000_0xbf800000 %v2uint_0x3f800000_0xbf800000\n" +
1333           "OpReturn\n" +
1334           "OpFunctionEnd",
1335       2, {0x7f000000u, 0x7f000000u}),
1336     // Test case 6: fold vector components of uint
1337     InstructionFoldingCase<std::vector<uint32_t>>(
1338         Header() + "%main = OpFunction %void None %void_func\n" +
1339             "%main_lab = OpLabel\n" +
1340             "%2 = OpSConvert %v2int %v2short_2_n5\n" +
1341             "OpReturn\n" +
1342             "OpFunctionEnd",
1343         2, {2,static_cast<uint32_t>(-5)}),
1344     // Test case 6: fold vector components of uint (incuding integer overflow)
1345     InstructionFoldingCase<std::vector<uint32_t>>(
1346         Header() + "%main = OpFunction %void None %void_func\n" +
1347             "%main_lab = OpLabel\n" +
1348             "%2 = OpUConvert %v2uint %v2short_2_n5\n" +
1349             "OpReturn\n" +
1350             "OpFunctionEnd",
1351         2, {2,65531})
1352 ));
1353 // clang-format on
1354 
1355 using IntVectorInstructionFoldingTest =
1356     ::testing::TestWithParam<InstructionFoldingCase<std::vector<int32_t>>>;
1357 
TEST_P(IntVectorInstructionFoldingTest,Case)1358 TEST_P(IntVectorInstructionFoldingTest, Case) {
1359   const auto& tc = GetParam();
1360 
1361   std::unique_ptr<IRContext> context;
1362   Instruction* inst;
1363   std::tie(context, inst) =
1364       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1365 
1366   CheckForExpectedVectorConstant(
1367       inst, tc.expected_result,
1368       [](const analysis::Constant* c) { return c->GetS32(); });
1369 }
1370 
1371 // clang-format off
1372 INSTANTIATE_TEST_SUITE_P(TestCase, IntVectorInstructionFoldingTest,
1373 ::testing::Values(
1374     // Test case 0: fold negate of a vector
1375     InstructionFoldingCase<std::vector<int32_t>>(
1376       Header() + "%main = OpFunction %void None %void_func\n" +
1377           "%main_lab = OpLabel\n" +
1378           "%2 = OpSNegate %v2int %v2int_2_3\n" +
1379           "OpReturn\n" +
1380           "OpFunctionEnd",
1381       2, {-2, -3}),
1382     // Test case 1: fold negate of a vector containing negative values.
1383     InstructionFoldingCase<std::vector<int32_t>>(
1384       Header() + "%main = OpFunction %void None %void_func\n" +
1385           "%main_lab = OpLabel\n" +
1386           "%2 = OpSNegate %v2int %v2int_n1_n24\n" +
1387           "OpReturn\n" +
1388           "OpFunctionEnd",
1389       2, {1, 24}),
1390     // Test case 2: fold negate of a vector at the limits
1391     InstructionFoldingCase<std::vector<int32_t>>(
1392       Header() + "%main = OpFunction %void None %void_func\n" +
1393           "%main_lab = OpLabel\n" +
1394           "%2 = OpSNegate %v2int %v2int_min_max\n" +
1395           "OpReturn\n" +
1396           "OpFunctionEnd",
1397       2, {INT_MIN, -INT_MAX}),
1398     // Test case 3: fold vector components of int
1399     InstructionFoldingCase<std::vector<int32_t>>(
1400       Header() + "%main = OpFunction %void None %void_func\n" +
1401           "%main_lab = OpLabel\n" +
1402           "%2 = OpIMul %v2int %v2int_2_3 %v2int_2_3\n" +
1403           "OpReturn\n" +
1404           "OpFunctionEnd",
1405       2, {4,9})
1406 ));
1407 // clang-format on
1408 
1409 using LongIntVectorInstructionFoldingTest =
1410     ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint64_t>>>;
1411 
TEST_P(LongIntVectorInstructionFoldingTest,Case)1412 TEST_P(LongIntVectorInstructionFoldingTest, Case) {
1413   const auto& tc = GetParam();
1414 
1415   std::unique_ptr<IRContext> context;
1416   Instruction* inst;
1417   std::tie(context, inst) =
1418       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1419   CheckForExpectedVectorConstant(
1420       inst, tc.expected_result,
1421       [](const analysis::Constant* c) { return c->GetU64(); });
1422 }
1423 
1424 // clang-format off
1425 INSTANTIATE_TEST_SUITE_P(TestCase, LongIntVectorInstructionFoldingTest,
1426   ::testing::Values(
1427      // Test case 0: fold {2,2} + {2,3} (Testing that the vector logic works
1428      // correctly. Scalar tests will check that the 64-bit values are correctly
1429      // folded.)
1430      InstructionFoldingCase<std::vector<uint64_t>>(
1431          Header() + "%main = OpFunction %void None %void_func\n" +
1432              "%main_lab = OpLabel\n" +
1433              "%n = OpVariable %_ptr_int Function\n" +
1434              "%load = OpLoad %int %n\n" +
1435              "%2 = OpIAdd %v2long %v2long_2_2 %v2long_2_3\n" +
1436              "OpReturn\n" +
1437              "OpFunctionEnd",
1438          2, {4,5}),
1439       // Test case 0: fold {2,2} / {2,3} (Testing that the vector logic works
1440       // correctly. Scalar tests will check that the 64-bit values are correctly
1441       // folded.)
1442      InstructionFoldingCase<std::vector<uint64_t>>(
1443          Header() + "%main = OpFunction %void None %void_func\n" +
1444              "%main_lab = OpLabel\n" +
1445              "%n = OpVariable %_ptr_int Function\n" +
1446              "%load = OpLoad %int %n\n" +
1447              "%2 = OpSDiv %v2long %v2long_2_2 %v2long_2_3\n" +
1448              "OpReturn\n" +
1449              "OpFunctionEnd",
1450          2, {1,0})
1451   ));
1452 // clang-format on
1453 
1454 using DoubleVectorInstructionFoldingTest =
1455     ::testing::TestWithParam<InstructionFoldingCase<std::vector<double>>>;
1456 
TEST_P(DoubleVectorInstructionFoldingTest,Case)1457 TEST_P(DoubleVectorInstructionFoldingTest, Case) {
1458   const auto& tc = GetParam();
1459 
1460   std::unique_ptr<IRContext> context;
1461   Instruction* inst;
1462   std::tie(context, inst) =
1463       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1464   CheckForExpectedVectorConstant(
1465       inst, tc.expected_result,
1466       [](const analysis::Constant* c) { return c->GetDouble(); });
1467 }
1468 
1469 // clang-format off
1470 INSTANTIATE_TEST_SUITE_P(TestCase, DoubleVectorInstructionFoldingTest,
1471 ::testing::Values(
1472    // Test case 0: bit-cast int {0x3FF00000,0x00000000,0xC05FD666,0x66666666}
1473    //              to double vector
1474    InstructionFoldingCase<std::vector<double>>(
1475        Header() + "%main = OpFunction %void None %void_func\n" +
1476            "%main_lab = OpLabel\n" +
1477            "%2 = OpBitcast %v2double %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666\n" +
1478            "OpReturn\n" +
1479            "OpFunctionEnd",
1480        2, {1.0,-127.35}),
1481    // Test case 1: OpVectorTimesMatrix Non-Zero Zero {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {1.0, 2.0, 3.0, 4.0} {0.0, 0.0, 0.0, 0.0}
1482    InstructionFoldingCase<std::vector<double>>(
1483        Header() +
1484        "%main = OpFunction %void None %void_func\n" +
1485        "%main_lab = OpLabel\n" +
1486        "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_null\n" +
1487        "OpReturn\n" +
1488        "OpFunctionEnd",
1489        2, {0.0,0.0,0.0,0.0}),
1490    // Test case 2: OpVectorTimesMatrix Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1491    InstructionFoldingCase<std::vector<double>>(
1492        Header() +
1493        "%main = OpFunction %void None %void_func\n" +
1494        "%main_lab = OpLabel\n" +
1495        "%2 = OpVectorTimesMatrix %v4double %v4double_null %mat4v4double_1_2_3_4\n" +
1496        "OpReturn\n" +
1497        "OpFunctionEnd",
1498        2, {0.0,0.0,0.0,0.0}),
1499    // Test case 3: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {1.0, 2.0, 3.0, 4.0} {30.0, 30.0, 30.0, 30.0}
1500    InstructionFoldingCase<std::vector<double>>(
1501        Header() +
1502        "%main = OpFunction %void None %void_func\n" +
1503        "%main_lab = OpLabel\n" +
1504        "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_1_2_3_4\n" +
1505        "OpReturn\n" +
1506        "OpFunctionEnd",
1507        2, {30.0,30.0,30.0,30.0}),
1508    // Test case 4: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {1.0, 2.0, 3.0, 4.0} {30.0, 0.0, 30.0, 0.0}
1509    InstructionFoldingCase<std::vector<double>>(
1510        Header() +
1511        "%main = OpFunction %void None %void_func\n" +
1512        "%main_lab = OpLabel\n" +
1513        "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_1_2_3_4_null\n" +
1514        "OpReturn\n" +
1515        "OpFunctionEnd",
1516        2, {30.0,0.0,30.0,0.0}),
1517    // Test case 5: OpMatrixTimesVector Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {0.0, 0.0, 0.0, 0.0}
1518    InstructionFoldingCase<std::vector<double>>(
1519        Header() +
1520        "%main = OpFunction %void None %void_func\n" +
1521        "%main_lab = OpLabel\n" +
1522        "%2 = OpMatrixTimesVector %v4double %mat4v4double_null %v4double_1_2_3_4\n" +
1523        "OpReturn\n" +
1524        "OpFunctionEnd",
1525        2, {0.0,0.0,0.0,0.0}),
1526    // Test case 6: OpMatrixTimesVector Non-Zero Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1527    InstructionFoldingCase<std::vector<double>>(
1528        Header() +
1529        "%main = OpFunction %void None %void_func\n" +
1530        "%main_lab = OpLabel\n" +
1531        "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4 %v4double_null\n" +
1532        "OpReturn\n" +
1533        "OpFunctionEnd",
1534        2, {0.0,0.0,0.0,0.0}),
1535    // Test case 7: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {10.0, 20.0, 30.0, 40.0}
1536    InstructionFoldingCase<std::vector<double>>(
1537        Header() +
1538        "%main = OpFunction %void None %void_func\n" +
1539        "%main_lab = OpLabel\n" +
1540        "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4 %v4double_1_2_3_4\n" +
1541        "OpReturn\n" +
1542        "OpFunctionEnd",
1543        2, {10.0,20.0,30.0,40.0}),
1544    // Test case 8: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {10.0, 20.0, 30.0, 40.0}
1545    InstructionFoldingCase<std::vector<double>>(
1546        Header() +
1547        "%main = OpFunction %void None %void_func\n" +
1548        "%main_lab = OpLabel\n" +
1549        "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4_null %v4double_1_2_3_4\n" +
1550        "OpReturn\n" +
1551        "OpFunctionEnd",
1552        2, {4.0,8.0,12.0,16.0})
1553 ));
1554 
1555 using FloatVectorInstructionFoldingTest =
1556     ::testing::TestWithParam<InstructionFoldingCase<std::vector<float>>>;
1557 
TEST_P(FloatVectorInstructionFoldingTest,Case)1558 TEST_P(FloatVectorInstructionFoldingTest, Case) {
1559   const auto& tc = GetParam();
1560 
1561   std::unique_ptr<IRContext> context;
1562   Instruction* inst;
1563   std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
1564   CheckForExpectedVectorConstant(inst, tc.expected_result, [](const analysis::Constant* c){ return c->GetFloat();});
1565 }
1566 
1567 // clang-format off
1568 INSTANTIATE_TEST_SUITE_P(TestCase, FloatVectorInstructionFoldingTest,
1569 ::testing::Values(
1570    // Test case 0: FMix {2.0, 2.0}, {2.0, 3.0} {0.2,0.5}
1571    InstructionFoldingCase<std::vector<float>>(
1572        Header() + "%main = OpFunction %void None %void_func\n" +
1573            "%main_lab = OpLabel\n" +
1574            "%2 = OpExtInst %v2float %1 FMix %v2float_2_3 %v2float_0_0 %v2float_0p2_0p5\n" +
1575            "OpReturn\n" +
1576            "OpFunctionEnd",
1577        2, {1.6f,1.5f}),
1578    // Test case 1: bit-cast unsigned int vector {0x3f800000, 0xbf800000} to
1579    //              float vector
1580    InstructionFoldingCase<std::vector<float>>(
1581        Header() + "%main = OpFunction %void None %void_func\n" +
1582            "%main_lab = OpLabel\n" +
1583            "%2 = OpBitcast %v2float %v2uint_0x3f800000_0xbf800000\n" +
1584            "OpReturn\n" +
1585            "OpFunctionEnd",
1586        2, {1.0f,-1.0f}),
1587    // Test case 2: bit-cast long int 0xbf8000003f800000 to float vector
1588    InstructionFoldingCase<std::vector<float>>(
1589        Header() + "%main = OpFunction %void None %void_func\n" +
1590            "%main_lab = OpLabel\n" +
1591            "%2 = OpBitcast %v2float %long_0xbf8000003f800000\n" +
1592            "OpReturn\n" +
1593            "OpFunctionEnd",
1594        2, {1.0f,-1.0f}),
1595    // Test case 3: OpVectorTimesMatrix Non-Zero Zero {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {1.0, 2.0, 3.0, 4.0} {0.0, 0.0, 0.0, 0.0}
1596    InstructionFoldingCase<std::vector<float>>(
1597        Header() +
1598        "%main = OpFunction %void None %void_func\n" +
1599        "%main_lab = OpLabel\n" +
1600        "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_null\n" +
1601        "OpReturn\n" +
1602        "OpFunctionEnd",
1603        2, {0.0f,0.0f,0.0f,0.0f}),
1604    // Test case 4: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {1.0, 2.0, 3.0, 4.0} {30.0, 0.0, 30.0, 0.0}
1605    InstructionFoldingCase<std::vector<float>>(
1606        Header() +
1607        "%main = OpFunction %void None %void_func\n" +
1608        "%main_lab = OpLabel\n" +
1609        "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_1_2_3_4_null\n" +
1610        "OpReturn\n" +
1611        "OpFunctionEnd",
1612        2, {30.0,0.0,30.0,0.0}),
1613    // Test case 5: OpVectorTimesMatrix Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1614    InstructionFoldingCase<std::vector<float>>(
1615        Header() +
1616        "%main = OpFunction %void None %void_func\n" +
1617        "%main_lab = OpLabel\n" +
1618        "%2 = OpVectorTimesMatrix %v4float %v4float_null %mat4v4float_1_2_3_4\n" +
1619        "OpReturn\n" +
1620        "OpFunctionEnd",
1621        2, {0.0f,0.0f,0.0f,0.0f}),
1622    // Test case 6: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {1.0, 2.0, 3.0, 4.0} {30.0, 30.0, 30.0, 30.0}
1623    InstructionFoldingCase<std::vector<float>>(
1624        Header() +
1625        "%main = OpFunction %void None %void_func\n" +
1626        "%main_lab = OpLabel\n" +
1627        "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_1_2_3_4\n" +
1628        "OpReturn\n" +
1629        "OpFunctionEnd",
1630        2, {30.0f,30.0f,30.0f,30.0f}),
1631    // Test case 7: OpMatrixTimesVector Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {0.0, 0.0, 0.0, 0.0}
1632    InstructionFoldingCase<std::vector<float>>(
1633        Header() +
1634        "%main = OpFunction %void None %void_func\n" +
1635        "%main_lab = OpLabel\n" +
1636        "%2 = OpMatrixTimesVector %v4float %mat4v4float_null %v4float_1_2_3_4\n" +
1637        "OpReturn\n" +
1638        "OpFunctionEnd",
1639        2, {0.0f,0.0f,0.0f,0.0f}),
1640    // Test case 8: OpMatrixTimesVector Non-Zero Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1641    InstructionFoldingCase<std::vector<float>>(
1642        Header() +
1643        "%main = OpFunction %void None %void_func\n" +
1644        "%main_lab = OpLabel\n" +
1645        "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4 %v4float_null\n" +
1646        "OpReturn\n" +
1647        "OpFunctionEnd",
1648        2, {0.0f,0.0f,0.0f,0.0f}),
1649    // Test case 9: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {10.0, 20.0, 30.0, 40.0}
1650    InstructionFoldingCase<std::vector<float>>(
1651        Header() +
1652        "%main = OpFunction %void None %void_func\n" +
1653        "%main_lab = OpLabel\n" +
1654        "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4 %v4float_1_2_3_4\n" +
1655        "OpReturn\n" +
1656        "OpFunctionEnd",
1657        2, {10.0f,20.0f,30.0f,40.0f}),
1658    // Test case 10: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {10.0, 20.0, 30.0, 40.0}
1659    InstructionFoldingCase<std::vector<float>>(
1660        Header() +
1661        "%main = OpFunction %void None %void_func\n" +
1662        "%main_lab = OpLabel\n" +
1663        "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4_null %v4float_1_2_3_4\n" +
1664        "OpReturn\n" +
1665        "OpFunctionEnd",
1666        2, {4.0,8.0,12.0,16.0})
1667 ));
1668 // clang-format on
1669 
1670 using FloatMatrixInstructionFoldingTest = ::testing::TestWithParam<
1671     InstructionFoldingCase<std::vector<std::vector<float>>>>;
1672 
TEST_P(FloatMatrixInstructionFoldingTest,Case)1673 TEST_P(FloatMatrixInstructionFoldingTest, Case) {
1674   const auto& tc = GetParam();
1675 
1676   std::unique_ptr<IRContext> context;
1677   Instruction* inst;
1678   std::tie(context, inst) =
1679       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1680 
1681   EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
1682   if (inst->opcode() == spv::Op::OpCopyObject) {
1683     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
1684     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
1685     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
1686     const analysis::Constant* result = const_mgr->GetConstantFromInst(inst);
1687     EXPECT_NE(result, nullptr);
1688     if (result != nullptr) {
1689       std::vector<const analysis::Constant*> matrix =
1690           result->AsMatrixConstant()->GetComponents();
1691       EXPECT_EQ(matrix.size(), tc.expected_result.size());
1692       for (size_t c = 0; c < matrix.size(); c++) {
1693         if (matrix[c]->AsNullConstant() != nullptr) {
1694           matrix[c] = const_mgr->GetNullCompositeConstant(matrix[c]->type());
1695         }
1696         const analysis::VectorConstant* column_const =
1697             matrix[c]->AsVectorConstant();
1698         ASSERT_NE(column_const, nullptr);
1699         const std::vector<const analysis::Constant*>& column =
1700             column_const->GetComponents();
1701         EXPECT_EQ(column.size(), tc.expected_result[c].size());
1702         for (size_t r = 0; r < column.size(); r++) {
1703           EXPECT_EQ(tc.expected_result[c][r], column[r]->GetFloat());
1704         }
1705       }
1706     }
1707   }
1708 }
1709 
1710 // clang-format off
1711 INSTANTIATE_TEST_SUITE_P(TestCase, FloatMatrixInstructionFoldingTest,
1712 ::testing::Values(
1713    // Test case 0: OpTranspose square null matrix
1714    InstructionFoldingCase<std::vector<std::vector<float>>>(
1715        Header() + "%main = OpFunction %void None %void_func\n" +
1716            "%main_lab = OpLabel\n" +
1717            "%2 = OpTranspose %mat4v4float %mat4v4float_null\n" +
1718            "OpReturn\n" +
1719            "OpFunctionEnd",
1720        2, {{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f}}),
1721    // Test case 1: OpTranspose rectangular null matrix
1722    InstructionFoldingCase<std::vector<std::vector<float>>>(
1723        Header() + "%main = OpFunction %void None %void_func\n" +
1724            "%main_lab = OpLabel\n" +
1725            "%2 = OpTranspose %mat4v2float %mat2v4float_null\n" +
1726            "OpReturn\n" +
1727            "OpFunctionEnd",
1728        2, {{0.0f, 0.0f},{0.0f, 0.0f},{0.0f, 0.0f},{0.0f, 0.0f}}),
1729    InstructionFoldingCase<std::vector<std::vector<float>>>(
1730        Header() + "%main = OpFunction %void None %void_func\n" +
1731            "%main_lab = OpLabel\n" +
1732            "%2 = OpTranspose %mat4v4float %mat4v4float_1_2_3_4\n" +
1733            "OpReturn\n" +
1734            "OpFunctionEnd",
1735        2, {{1.0f, 1.0f, 1.0f, 1.0f},{2.0f, 2.0f, 2.0f, 2.0f},{3.0f, 3.0f, 3.0f, 3.0f},{4.0f, 4.0f, 4.0f, 4.0f}})
1736 ));
1737 // clang-format on
1738 
1739 using BooleanInstructionFoldingTest =
1740     ::testing::TestWithParam<InstructionFoldingCase<bool>>;
1741 
TEST_P(BooleanInstructionFoldingTest,Case)1742 TEST_P(BooleanInstructionFoldingTest, Case) {
1743   const auto& tc = GetParam();
1744 
1745   std::unique_ptr<IRContext> context;
1746   Instruction* inst;
1747   std::tie(context, inst) =
1748       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1749   CheckForExpectedScalarConstant(
1750       inst, tc.expected_result,
1751       [](const analysis::Constant* c) { return c->AsBoolConstant()->value(); });
1752 }
1753 
1754 // clang-format off
1755 INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTest,
1756                         ::testing::Values(
1757   // Test case 0: fold true || n
1758   InstructionFoldingCase<bool>(
1759       Header() + "%main = OpFunction %void None %void_func\n" +
1760           "%main_lab = OpLabel\n" +
1761           "%n = OpVariable %_ptr_bool Function\n" +
1762           "%load = OpLoad %bool %n\n" +
1763           "%2 = OpLogicalOr %bool %true %load\n" +
1764           "OpReturn\n" +
1765           "OpFunctionEnd",
1766       2, true),
1767   // Test case 1: fold n || true
1768   InstructionFoldingCase<bool>(
1769       Header() + "%main = OpFunction %void None %void_func\n" +
1770           "%main_lab = OpLabel\n" +
1771           "%n = OpVariable %_ptr_bool Function\n" +
1772           "%load = OpLoad %bool %n\n" +
1773           "%2 = OpLogicalOr %bool %load %true\n" +
1774           "OpReturn\n" +
1775           "OpFunctionEnd",
1776       2, true),
1777   // Test case 2: fold false && n
1778   InstructionFoldingCase<bool>(
1779       Header() + "%main = OpFunction %void None %void_func\n" +
1780           "%main_lab = OpLabel\n" +
1781           "%n = OpVariable %_ptr_bool Function\n" +
1782           "%load = OpLoad %bool %n\n" +
1783           "%2 = OpLogicalAnd %bool %false %load\n" +
1784           "OpReturn\n" +
1785           "OpFunctionEnd",
1786       2, false),
1787   // Test case 3: fold n && false
1788   InstructionFoldingCase<bool>(
1789       Header() + "%main = OpFunction %void None %void_func\n" +
1790           "%main_lab = OpLabel\n" +
1791           "%n = OpVariable %_ptr_bool Function\n" +
1792           "%load = OpLoad %bool %n\n" +
1793           "%2 = OpLogicalAnd %bool %load %false\n" +
1794           "OpReturn\n" +
1795           "OpFunctionEnd",
1796       2, false),
1797   // Test case 4: fold n < 0 (unsigned)
1798   InstructionFoldingCase<bool>(
1799       Header() + "%main = OpFunction %void None %void_func\n" +
1800           "%main_lab = OpLabel\n" +
1801           "%n = OpVariable %_ptr_uint Function\n" +
1802           "%load = OpLoad %uint %n\n" +
1803           "%2 = OpULessThan %bool %load %uint_0\n" +
1804           "OpReturn\n" +
1805           "OpFunctionEnd",
1806       2, false),
1807   // Test case 5: fold UINT_MAX < n (unsigned)
1808   InstructionFoldingCase<bool>(
1809       Header() + "%main = OpFunction %void None %void_func\n" +
1810           "%main_lab = OpLabel\n" +
1811           "%n = OpVariable %_ptr_uint Function\n" +
1812           "%load = OpLoad %uint %n\n" +
1813           "%2 = OpULessThan %bool %uint_max %load\n" +
1814           "OpReturn\n" +
1815           "OpFunctionEnd",
1816       2, false),
1817   // Test case 6: fold INT_MAX < n (signed)
1818   InstructionFoldingCase<bool>(
1819       Header() + "%main = OpFunction %void None %void_func\n" +
1820           "%main_lab = OpLabel\n" +
1821           "%n = OpVariable %_ptr_int Function\n" +
1822           "%load = OpLoad %int %n\n" +
1823           "%2 = OpSLessThan %bool %int_max %load\n" +
1824           "OpReturn\n" +
1825           "OpFunctionEnd",
1826       2, false),
1827   // Test case 7: fold n < INT_MIN (signed)
1828   InstructionFoldingCase<bool>(
1829       Header() + "%main = OpFunction %void None %void_func\n" +
1830           "%main_lab = OpLabel\n" +
1831           "%n = OpVariable %_ptr_int Function\n" +
1832           "%load = OpLoad %int %n\n" +
1833           "%2 = OpSLessThan %bool %load %int_min\n" +
1834           "OpReturn\n" +
1835           "OpFunctionEnd",
1836       2, false),
1837   // Test case 8: fold 0 > n (unsigned)
1838   InstructionFoldingCase<bool>(
1839       Header() + "%main = OpFunction %void None %void_func\n" +
1840           "%main_lab = OpLabel\n" +
1841           "%n = OpVariable %_ptr_uint Function\n" +
1842           "%load = OpLoad %uint %n\n" +
1843           "%2 = OpUGreaterThan %bool %uint_0 %load\n" +
1844           "OpReturn\n" +
1845           "OpFunctionEnd",
1846       2, false),
1847   // Test case 9: fold n > UINT_MAX (unsigned)
1848   InstructionFoldingCase<bool>(
1849       Header() + "%main = OpFunction %void None %void_func\n" +
1850           "%main_lab = OpLabel\n" +
1851           "%n = OpVariable %_ptr_uint Function\n" +
1852           "%load = OpLoad %uint %n\n" +
1853           "%2 = OpUGreaterThan %bool %load %uint_max\n" +
1854           "OpReturn\n" +
1855           "OpFunctionEnd",
1856       2, false),
1857   // Test case 10: fold n > INT_MAX (signed)
1858   InstructionFoldingCase<bool>(
1859       Header() + "%main = OpFunction %void None %void_func\n" +
1860           "%main_lab = OpLabel\n" +
1861           "%n = OpVariable %_ptr_int Function\n" +
1862           "%load = OpLoad %int %n\n" +
1863           "%2 = OpSGreaterThan %bool %load %int_max\n" +
1864           "OpReturn\n" +
1865           "OpFunctionEnd",
1866       2, false),
1867   // Test case 11: fold INT_MIN > n (signed)
1868   InstructionFoldingCase<bool>(
1869       Header() + "%main = OpFunction %void None %void_func\n" +
1870           "%main_lab = OpLabel\n" +
1871           "%n = OpVariable %_ptr_uint Function\n" +
1872           "%load = OpLoad %uint %n\n" +
1873           "%2 = OpSGreaterThan %bool %int_min %load\n" +
1874           "OpReturn\n" +
1875           "OpFunctionEnd",
1876       2, false),
1877   // Test case 12: fold 0 <= n (unsigned)
1878   InstructionFoldingCase<bool>(
1879       Header() + "%main = OpFunction %void None %void_func\n" +
1880           "%main_lab = OpLabel\n" +
1881           "%n = OpVariable %_ptr_uint Function\n" +
1882           "%load = OpLoad %uint %n\n" +
1883           "%2 = OpULessThanEqual %bool %uint_0 %load\n" +
1884           "OpReturn\n" +
1885           "OpFunctionEnd",
1886       2, true),
1887   // Test case 13: fold n <= UINT_MAX (unsigned)
1888   InstructionFoldingCase<bool>(
1889       Header() + "%main = OpFunction %void None %void_func\n" +
1890           "%main_lab = OpLabel\n" +
1891           "%n = OpVariable %_ptr_uint Function\n" +
1892           "%load = OpLoad %uint %n\n" +
1893           "%2 = OpULessThanEqual %bool %load %uint_max\n" +
1894           "OpReturn\n" +
1895           "OpFunctionEnd",
1896       2, true),
1897   // Test case 14: fold INT_MIN <= n (signed)
1898   InstructionFoldingCase<bool>(
1899       Header() + "%main = OpFunction %void None %void_func\n" +
1900           "%main_lab = OpLabel\n" +
1901           "%n = OpVariable %_ptr_int Function\n" +
1902           "%load = OpLoad %int %n\n" +
1903           "%2 = OpSLessThanEqual %bool %int_min %load\n" +
1904           "OpReturn\n" +
1905           "OpFunctionEnd",
1906       2, true),
1907   // Test case 15: fold n <= INT_MAX (signed)
1908   InstructionFoldingCase<bool>(
1909       Header() + "%main = OpFunction %void None %void_func\n" +
1910           "%main_lab = OpLabel\n" +
1911           "%n = OpVariable %_ptr_int Function\n" +
1912           "%load = OpLoad %int %n\n" +
1913           "%2 = OpSLessThanEqual %bool %load %int_max\n" +
1914           "OpReturn\n" +
1915           "OpFunctionEnd",
1916       2, true),
1917   // Test case 16: fold n >= 0 (unsigned)
1918   InstructionFoldingCase<bool>(
1919       Header() + "%main = OpFunction %void None %void_func\n" +
1920           "%main_lab = OpLabel\n" +
1921           "%n = OpVariable %_ptr_uint Function\n" +
1922           "%load = OpLoad %uint %n\n" +
1923           "%2 = OpUGreaterThanEqual %bool %load %uint_0\n" +
1924           "OpReturn\n" +
1925           "OpFunctionEnd",
1926       2, true),
1927   // Test case 17: fold UINT_MAX >= n (unsigned)
1928   InstructionFoldingCase<bool>(
1929       Header() + "%main = OpFunction %void None %void_func\n" +
1930           "%main_lab = OpLabel\n" +
1931           "%n = OpVariable %_ptr_uint Function\n" +
1932           "%load = OpLoad %uint %n\n" +
1933           "%2 = OpUGreaterThanEqual %bool %uint_max %load\n" +
1934           "OpReturn\n" +
1935           "OpFunctionEnd",
1936       2, true),
1937   // Test case 18: fold n >= INT_MIN (signed)
1938   InstructionFoldingCase<bool>(
1939       Header() + "%main = OpFunction %void None %void_func\n" +
1940           "%main_lab = OpLabel\n" +
1941           "%n = OpVariable %_ptr_int Function\n" +
1942           "%load = OpLoad %int %n\n" +
1943           "%2 = OpSGreaterThanEqual %bool %load %int_min\n" +
1944           "OpReturn\n" +
1945           "OpFunctionEnd",
1946       2, true),
1947   // Test case 19: fold INT_MAX >= n (signed)
1948   InstructionFoldingCase<bool>(
1949       Header() + "%main = OpFunction %void None %void_func\n" +
1950           "%main_lab = OpLabel\n" +
1951           "%n = OpVariable %_ptr_int Function\n" +
1952           "%load = OpLoad %int %n\n" +
1953           "%2 = OpSGreaterThanEqual %bool %int_max %load\n" +
1954           "OpReturn\n" +
1955           "OpFunctionEnd",
1956       2, true)
1957 ));
1958 
1959 INSTANTIATE_TEST_SUITE_P(FClampAndCmpLHS, BooleanInstructionFoldingTest,
1960 ::testing::Values(
1961     // Test case 0: fold 0.0 > clamp(n, 0.0, 1.0)
1962     InstructionFoldingCase<bool>(
1963         Header() + "%main = OpFunction %void None %void_func\n" +
1964             "%main_lab = OpLabel\n" +
1965             "%n = OpVariable %_ptr_float Function\n" +
1966             "%ld = OpLoad %float %n\n" +
1967             "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1968             "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
1969             "OpReturn\n" +
1970             "OpFunctionEnd",
1971         2, false),
1972     // Test case 1: fold 0.0 > clamp(n, -1.0, -1.0)
1973     InstructionFoldingCase<bool>(
1974         Header() + "%main = OpFunction %void None %void_func\n" +
1975             "%main_lab = OpLabel\n" +
1976             "%n = OpVariable %_ptr_float Function\n" +
1977             "%ld = OpLoad %float %n\n" +
1978             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
1979             "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
1980             "OpReturn\n" +
1981             "OpFunctionEnd",
1982         2, true),
1983     // Test case 2: fold 0.0 >= clamp(n, 1, 2)
1984     InstructionFoldingCase<bool>(
1985         Header() + "%main = OpFunction %void None %void_func\n" +
1986             "%main_lab = OpLabel\n" +
1987             "%n = OpVariable %_ptr_float Function\n" +
1988             "%ld = OpLoad %float %n\n" +
1989             "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1990             "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
1991             "OpReturn\n" +
1992             "OpFunctionEnd",
1993         2, false),
1994     // Test case 3: fold 0.0 >= clamp(n, -1.0, 0.0)
1995     InstructionFoldingCase<bool>(
1996         Header() + "%main = OpFunction %void None %void_func\n" +
1997             "%main_lab = OpLabel\n" +
1998             "%n = OpVariable %_ptr_float Function\n" +
1999             "%ld = OpLoad %float %n\n" +
2000             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2001             "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
2002             "OpReturn\n" +
2003             "OpFunctionEnd",
2004         2, true),
2005     // Test case 4: fold 0.0 <= clamp(n, 0.0, 1.0)
2006     InstructionFoldingCase<bool>(
2007         Header() + "%main = OpFunction %void None %void_func\n" +
2008             "%main_lab = OpLabel\n" +
2009             "%n = OpVariable %_ptr_float Function\n" +
2010             "%ld = OpLoad %float %n\n" +
2011             "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2012             "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
2013             "OpReturn\n" +
2014             "OpFunctionEnd",
2015         2, true),
2016     // Test case 5: fold 0.0 <= clamp(n, -1.0, -1.0)
2017     InstructionFoldingCase<bool>(
2018         Header() + "%main = OpFunction %void None %void_func\n" +
2019             "%main_lab = OpLabel\n" +
2020             "%n = OpVariable %_ptr_float Function\n" +
2021             "%ld = OpLoad %float %n\n" +
2022             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
2023             "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
2024             "OpReturn\n" +
2025             "OpFunctionEnd",
2026         2, false),
2027     // Test case 6: fold 0.0 < clamp(n, 1, 2)
2028     InstructionFoldingCase<bool>(
2029         Header() + "%main = OpFunction %void None %void_func\n" +
2030             "%main_lab = OpLabel\n" +
2031             "%n = OpVariable %_ptr_float Function\n" +
2032             "%ld = OpLoad %float %n\n" +
2033             "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2034             "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
2035             "OpReturn\n" +
2036             "OpFunctionEnd",
2037         2, true),
2038     // Test case 7: fold 0.0 < clamp(n, -1.0, 0.0)
2039     InstructionFoldingCase<bool>(
2040         Header() + "%main = OpFunction %void None %void_func\n" +
2041             "%main_lab = OpLabel\n" +
2042             "%n = OpVariable %_ptr_float Function\n" +
2043             "%ld = OpLoad %float %n\n" +
2044             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2045             "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
2046             "OpReturn\n" +
2047             "OpFunctionEnd",
2048         2, false),
2049     // Test case 8: fold 0.0 > clamp(n, 0.0, 1.0)
2050     InstructionFoldingCase<bool>(
2051         Header() + "%main = OpFunction %void None %void_func\n" +
2052             "%main_lab = OpLabel\n" +
2053             "%n = OpVariable %_ptr_float Function\n" +
2054             "%ld = OpLoad %float %n\n" +
2055             "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2056             "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
2057             "OpReturn\n" +
2058             "OpFunctionEnd",
2059         2, false),
2060     // Test case 9: fold 0.0 > clamp(n, -1.0, -1.0)
2061     InstructionFoldingCase<bool>(
2062         Header() + "%main = OpFunction %void None %void_func\n" +
2063             "%main_lab = OpLabel\n" +
2064             "%n = OpVariable %_ptr_float Function\n" +
2065             "%ld = OpLoad %float %n\n" +
2066             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
2067             "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
2068             "OpReturn\n" +
2069             "OpFunctionEnd",
2070         2, true),
2071     // Test case 10: fold 0.0 >= clamp(n, 1, 2)
2072     InstructionFoldingCase<bool>(
2073         Header() + "%main = OpFunction %void None %void_func\n" +
2074             "%main_lab = OpLabel\n" +
2075             "%n = OpVariable %_ptr_float Function\n" +
2076             "%ld = OpLoad %float %n\n" +
2077             "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2078             "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
2079             "OpReturn\n" +
2080             "OpFunctionEnd",
2081         2, false),
2082     // Test case 11: fold 0.0 >= clamp(n, -1.0, 0.0)
2083     InstructionFoldingCase<bool>(
2084         Header() + "%main = OpFunction %void None %void_func\n" +
2085             "%main_lab = OpLabel\n" +
2086             "%n = OpVariable %_ptr_float Function\n" +
2087             "%ld = OpLoad %float %n\n" +
2088             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2089             "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
2090             "OpReturn\n" +
2091             "OpFunctionEnd",
2092         2, true),
2093     // Test case 12: fold 0.0 <= clamp(n, 0.0, 1.0)
2094     InstructionFoldingCase<bool>(
2095         Header() + "%main = OpFunction %void None %void_func\n" +
2096             "%main_lab = OpLabel\n" +
2097             "%n = OpVariable %_ptr_float Function\n" +
2098             "%ld = OpLoad %float %n\n" +
2099             "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2100             "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
2101             "OpReturn\n" +
2102             "OpFunctionEnd",
2103         2, true),
2104     // Test case 13: fold 0.0 <= clamp(n, -1.0, -1.0)
2105     InstructionFoldingCase<bool>(
2106         Header() + "%main = OpFunction %void None %void_func\n" +
2107             "%main_lab = OpLabel\n" +
2108             "%n = OpVariable %_ptr_float Function\n" +
2109             "%ld = OpLoad %float %n\n" +
2110             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
2111             "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
2112             "OpReturn\n" +
2113             "OpFunctionEnd",
2114         2, false),
2115     // Test case 14: fold 0.0 < clamp(n, 1, 2)
2116     InstructionFoldingCase<bool>(
2117         Header() + "%main = OpFunction %void None %void_func\n" +
2118             "%main_lab = OpLabel\n" +
2119             "%n = OpVariable %_ptr_float Function\n" +
2120             "%ld = OpLoad %float %n\n" +
2121             "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2122             "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
2123             "OpReturn\n" +
2124             "OpFunctionEnd",
2125         2, true),
2126     // Test case 15: fold 0.0 < clamp(n, -1.0, 0.0)
2127     InstructionFoldingCase<bool>(
2128         Header() + "%main = OpFunction %void None %void_func\n" +
2129             "%main_lab = OpLabel\n" +
2130             "%n = OpVariable %_ptr_float Function\n" +
2131             "%ld = OpLoad %float %n\n" +
2132             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2133             "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
2134             "OpReturn\n" +
2135             "OpFunctionEnd",
2136         2, false)
2137 ));
2138 
2139 INSTANTIATE_TEST_SUITE_P(FClampAndCmpRHS, BooleanInstructionFoldingTest,
2140 ::testing::Values(
2141     // Test case 0: fold clamp(n, 0.0, 1.0) > 1.0
2142     InstructionFoldingCase<bool>(
2143       Header() + "%main = OpFunction %void None %void_func\n" +
2144       "%main_lab = OpLabel\n" +
2145       "%n = OpVariable %_ptr_float Function\n" +
2146       "%ld = OpLoad %float %n\n" +
2147       "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2148       "%2 = OpFOrdGreaterThan %bool %clamp %float_1\n" +
2149       "OpReturn\n" +
2150       "OpFunctionEnd",
2151       2, false),
2152     // Test case 1: fold clamp(n, 1.0, 1.0) > 0.0
2153     InstructionFoldingCase<bool>(
2154       Header() + "%main = OpFunction %void None %void_func\n" +
2155       "%main_lab = OpLabel\n" +
2156       "%n = OpVariable %_ptr_float Function\n" +
2157       "%ld = OpLoad %float %n\n" +
2158       "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
2159       "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
2160       "OpReturn\n" +
2161       "OpFunctionEnd",
2162       2, true),
2163     // Test case 2: fold clamp(n, 1, 2) >= 0.0
2164     InstructionFoldingCase<bool>(
2165       Header() + "%main = OpFunction %void None %void_func\n" +
2166       "%main_lab = OpLabel\n" +
2167       "%n = OpVariable %_ptr_float Function\n" +
2168       "%ld = OpLoad %float %n\n" +
2169       "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2170       "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
2171       "OpReturn\n" +
2172       "OpFunctionEnd",
2173       2, true),
2174     // Test case 3: fold clamp(n, 1.0, 2.0) >= 3.0
2175     InstructionFoldingCase<bool>(
2176       Header() + "%main = OpFunction %void None %void_func\n" +
2177       "%main_lab = OpLabel\n" +
2178       "%n = OpVariable %_ptr_float Function\n" +
2179       "%ld = OpLoad %float %n\n" +
2180       "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2181       "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_3\n" +
2182       "OpReturn\n" +
2183       "OpFunctionEnd",
2184       2, false),
2185     // Test case 4: fold clamp(n, 0.0, 1.0) <= 1.0
2186     InstructionFoldingCase<bool>(
2187         Header() + "%main = OpFunction %void None %void_func\n" +
2188             "%main_lab = OpLabel\n" +
2189             "%n = OpVariable %_ptr_float Function\n" +
2190             "%ld = OpLoad %float %n\n" +
2191             "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2192             "%2 = OpFOrdLessThanEqual %bool %clamp %float_1\n" +
2193             "OpReturn\n" +
2194             "OpFunctionEnd",
2195         2, true),
2196     // Test case 5: fold clamp(n, 1.0, 2.0) <= 0.0
2197     InstructionFoldingCase<bool>(
2198         Header() + "%main = OpFunction %void None %void_func\n" +
2199             "%main_lab = OpLabel\n" +
2200             "%n = OpVariable %_ptr_float Function\n" +
2201             "%ld = OpLoad %float %n\n" +
2202             "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2203             "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
2204             "OpReturn\n" +
2205             "OpFunctionEnd",
2206         2, false),
2207     // Test case 6: fold clamp(n, 1, 2) < 3
2208     InstructionFoldingCase<bool>(
2209         Header() + "%main = OpFunction %void None %void_func\n" +
2210             "%main_lab = OpLabel\n" +
2211             "%n = OpVariable %_ptr_float Function\n" +
2212             "%ld = OpLoad %float %n\n" +
2213             "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2214             "%2 = OpFOrdLessThan %bool %clamp %float_3\n" +
2215             "OpReturn\n" +
2216             "OpFunctionEnd",
2217         2, true),
2218     // Test case 7: fold clamp(n, -1.0, 0.0) < -1.0
2219     InstructionFoldingCase<bool>(
2220         Header() + "%main = OpFunction %void None %void_func\n" +
2221             "%main_lab = OpLabel\n" +
2222             "%n = OpVariable %_ptr_float Function\n" +
2223             "%ld = OpLoad %float %n\n" +
2224             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2225             "%2 = OpFOrdLessThan %bool %clamp %float_n1\n" +
2226             "OpReturn\n" +
2227             "OpFunctionEnd",
2228         2, false),
2229     // Test case 8: fold clamp(n, 0.0, 1.0) > 1.0
2230     InstructionFoldingCase<bool>(
2231         Header() + "%main = OpFunction %void None %void_func\n" +
2232             "%main_lab = OpLabel\n" +
2233             "%n = OpVariable %_ptr_float Function\n" +
2234             "%ld = OpLoad %float %n\n" +
2235             "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2236             "%2 = OpFUnordGreaterThan %bool %clamp %float_1\n" +
2237             "OpReturn\n" +
2238             "OpFunctionEnd",
2239         2, false),
2240     // Test case 9: fold clamp(n, 1.0, 2.0) > 0.0
2241     InstructionFoldingCase<bool>(
2242         Header() + "%main = OpFunction %void None %void_func\n" +
2243             "%main_lab = OpLabel\n" +
2244             "%n = OpVariable %_ptr_float Function\n" +
2245             "%ld = OpLoad %float %n\n" +
2246             "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2247             "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
2248             "OpReturn\n" +
2249             "OpFunctionEnd",
2250         2, true),
2251     // Test case 10: fold clamp(n, 1, 2) >= 3.0
2252     InstructionFoldingCase<bool>(
2253         Header() + "%main = OpFunction %void None %void_func\n" +
2254             "%main_lab = OpLabel\n" +
2255             "%n = OpVariable %_ptr_float Function\n" +
2256             "%ld = OpLoad %float %n\n" +
2257             "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2258             "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_3\n" +
2259             "OpReturn\n" +
2260             "OpFunctionEnd",
2261         2, false),
2262     // Test case 11: fold clamp(n, -1.0, 0.0) >= -1.0
2263     InstructionFoldingCase<bool>(
2264         Header() + "%main = OpFunction %void None %void_func\n" +
2265             "%main_lab = OpLabel\n" +
2266             "%n = OpVariable %_ptr_float Function\n" +
2267             "%ld = OpLoad %float %n\n" +
2268             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2269             "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_n1\n" +
2270             "OpReturn\n" +
2271             "OpFunctionEnd",
2272         2, true),
2273     // Test case 12: fold clamp(n, 0.0, 1.0) <= 1.0
2274     InstructionFoldingCase<bool>(
2275         Header() + "%main = OpFunction %void None %void_func\n" +
2276             "%main_lab = OpLabel\n" +
2277             "%n = OpVariable %_ptr_float Function\n" +
2278             "%ld = OpLoad %float %n\n" +
2279             "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2280             "%2 = OpFUnordLessThanEqual %bool %clamp %float_1\n" +
2281             "OpReturn\n" +
2282             "OpFunctionEnd",
2283         2, true),
2284     // Test case 13: fold clamp(n, 1.0, 1.0) <= 0.0
2285     InstructionFoldingCase<bool>(
2286         Header() + "%main = OpFunction %void None %void_func\n" +
2287             "%main_lab = OpLabel\n" +
2288             "%n = OpVariable %_ptr_float Function\n" +
2289             "%ld = OpLoad %float %n\n" +
2290             "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
2291             "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
2292             "OpReturn\n" +
2293             "OpFunctionEnd",
2294         2, false),
2295     // Test case 14: fold clamp(n, 1, 2) < 3
2296     InstructionFoldingCase<bool>(
2297         Header() + "%main = OpFunction %void None %void_func\n" +
2298             "%main_lab = OpLabel\n" +
2299             "%n = OpVariable %_ptr_float Function\n" +
2300             "%ld = OpLoad %float %n\n" +
2301             "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2302             "%2 = OpFUnordLessThan %bool %clamp %float_3\n" +
2303             "OpReturn\n" +
2304             "OpFunctionEnd",
2305         2, true),
2306     // Test case 15: fold clamp(n, -1.0, 0.0) < -1.0
2307     InstructionFoldingCase<bool>(
2308         Header() + "%main = OpFunction %void None %void_func\n" +
2309             "%main_lab = OpLabel\n" +
2310             "%n = OpVariable %_ptr_float Function\n" +
2311             "%ld = OpLoad %float %n\n" +
2312             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2313             "%2 = OpFUnordLessThan %bool %clamp %float_n1\n" +
2314             "OpReturn\n" +
2315             "OpFunctionEnd",
2316         2, false),
2317     // Test case 16: fold clamp(n, -1.0, 0.0) < -1.0 (one test for double)
2318     InstructionFoldingCase<bool>(
2319         Header() + "%main = OpFunction %void None %void_func\n" +
2320             "%main_lab = OpLabel\n" +
2321             "%n = OpVariable %_ptr_double Function\n" +
2322             "%ld = OpLoad %double %n\n" +
2323             "%clamp = OpExtInst %double %1 FClamp %ld %double_n1 %double_0\n" +
2324             "%2 = OpFUnordLessThan %bool %clamp %double_n1\n" +
2325             "OpReturn\n" +
2326             "OpFunctionEnd",
2327         2, false)
2328 ));
2329 // clang-format on
2330 
2331 using FloatInstructionFoldingTest =
2332     ::testing::TestWithParam<InstructionFoldingCase<float>>;
2333 
TEST_P(FloatInstructionFoldingTest,Case)2334 TEST_P(FloatInstructionFoldingTest, Case) {
2335   const auto& tc = GetParam();
2336 
2337   std::unique_ptr<IRContext> context;
2338   Instruction* inst;
2339   std::tie(context, inst) =
2340       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
2341 
2342   CheckForExpectedScalarConstant(inst, tc.expected_result,
2343                                  [](const analysis::Constant* c) {
2344                                    return c->AsFloatConstant()->GetFloatValue();
2345                                  });
2346 }
2347 
2348 // Not testing NaNs because there are no expectations concerning NaNs according
2349 // to the "Precision and Operation of SPIR-V Instructions" section of the Vulkan
2350 // specification.
2351 
2352 // clang-format off
2353 INSTANTIATE_TEST_SUITE_P(FloatConstantFoldingTest, FloatInstructionFoldingTest,
2354 ::testing::Values(
2355     // Test case 0: Fold 2.0 - 1.0
2356     InstructionFoldingCase<float>(
2357         Header() + "%main = OpFunction %void None %void_func\n" +
2358             "%main_lab = OpLabel\n" +
2359             "%2 = OpFSub %float %float_2 %float_1\n" +
2360             "OpReturn\n" +
2361             "OpFunctionEnd",
2362         2, 1.0),
2363     // Test case 1: Fold 2.0 + 1.0
2364     InstructionFoldingCase<float>(
2365         Header() + "%main = OpFunction %void None %void_func\n" +
2366             "%main_lab = OpLabel\n" +
2367             "%2 = OpFAdd %float %float_2 %float_1\n" +
2368             "OpReturn\n" +
2369             "OpFunctionEnd",
2370         2, 3.0),
2371     // Test case 2: Fold 3.0 * 2.0
2372     InstructionFoldingCase<float>(
2373         Header() + "%main = OpFunction %void None %void_func\n" +
2374             "%main_lab = OpLabel\n" +
2375             "%2 = OpFMul %float %float_3 %float_2\n" +
2376             "OpReturn\n" +
2377             "OpFunctionEnd",
2378         2, 6.0),
2379     // Test case 3: Fold 1.0 / 2.0
2380     InstructionFoldingCase<float>(
2381         Header() + "%main = OpFunction %void None %void_func\n" +
2382             "%main_lab = OpLabel\n" +
2383             "%2 = OpFDiv %float %float_1 %float_2\n" +
2384             "OpReturn\n" +
2385             "OpFunctionEnd",
2386         2, 0.5),
2387     // Test case 4: Fold 1.0 / 0.0
2388     InstructionFoldingCase<float>(
2389         Header() + "%main = OpFunction %void None %void_func\n" +
2390             "%main_lab = OpLabel\n" +
2391             "%2 = OpFDiv %float %float_1 %float_0\n" +
2392             "OpReturn\n" +
2393             "OpFunctionEnd",
2394         2, std::numeric_limits<float>::infinity()),
2395     // Test case 5: Fold -1.0 / 0.0
2396     InstructionFoldingCase<float>(
2397         Header() + "%main = OpFunction %void None %void_func\n" +
2398             "%main_lab = OpLabel\n" +
2399             "%2 = OpFDiv %float %float_n1 %float_0\n" +
2400             "OpReturn\n" +
2401             "OpFunctionEnd",
2402         2, -std::numeric_limits<float>::infinity()),
2403     // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
2404     InstructionFoldingCase<float>(
2405         Header() + "%main = OpFunction %void None %void_func\n" +
2406             "%main_lab = OpLabel\n" +
2407             "%2 = OpDot %float %v2float_2_3 %v2float_2_0p5\n" +
2408             "OpReturn\n" +
2409             "OpFunctionEnd",
2410         2, 5.5f),
2411     // Test case 7: Fold (0.0, 0.0) dot v
2412     InstructionFoldingCase<float>(
2413         Header() + "%main = OpFunction %void None %void_func\n" +
2414             "%main_lab = OpLabel\n" +
2415             "%v = OpVariable %_ptr_v2float Function\n" +
2416             "%2 = OpLoad %v2float %v\n" +
2417             "%3 = OpDot %float %v2float_0_0 %2\n" +
2418             "OpReturn\n" +
2419             "OpFunctionEnd",
2420         3, 0.0f),
2421     // Test case 8: Fold v dot (0.0, 0.0)
2422     InstructionFoldingCase<float>(
2423         Header() + "%main = OpFunction %void None %void_func\n" +
2424             "%main_lab = OpLabel\n" +
2425             "%v = OpVariable %_ptr_v2float Function\n" +
2426             "%2 = OpLoad %v2float %v\n" +
2427             "%3 = OpDot %float %2 %v2float_0_0\n" +
2428             "OpReturn\n" +
2429             "OpFunctionEnd",
2430         3, 0.0f),
2431     // Test case 9: Fold Null dot v
2432     InstructionFoldingCase<float>(
2433         Header() + "%main = OpFunction %void None %void_func\n" +
2434             "%main_lab = OpLabel\n" +
2435             "%v = OpVariable %_ptr_v2float Function\n" +
2436             "%2 = OpLoad %v2float %v\n" +
2437             "%3 = OpDot %float %v2float_null %2\n" +
2438             "OpReturn\n" +
2439             "OpFunctionEnd",
2440         3, 0.0f),
2441     // Test case 10: Fold v dot Null
2442     InstructionFoldingCase<float>(
2443         Header() + "%main = OpFunction %void None %void_func\n" +
2444             "%main_lab = OpLabel\n" +
2445             "%v = OpVariable %_ptr_v2float Function\n" +
2446             "%2 = OpLoad %v2float %v\n" +
2447             "%3 = OpDot %float %2 %v2float_null\n" +
2448             "OpReturn\n" +
2449             "OpFunctionEnd",
2450         3, 0.0f),
2451     // Test case 11: Fold -2.0
2452     InstructionFoldingCase<float>(
2453         Header() + "%main = OpFunction %void None %void_func\n" +
2454             "%main_lab = OpLabel\n" +
2455             "%2 = OpFNegate %float %float_2\n" +
2456             "OpReturn\n" +
2457             "OpFunctionEnd",
2458         2, -2),
2459     // Test case 12: QuantizeToF16 1.0
2460     InstructionFoldingCase<float>(
2461         Header() + "%main = OpFunction %void None %void_func\n" +
2462             "%main_lab = OpLabel\n" +
2463             "%2 = OpQuantizeToF16 %float %float_1\n" +
2464             "OpReturn\n" +
2465             "OpFunctionEnd",
2466         2, 1.0),
2467     // Test case 13: QuantizeToF16 positive non exact
2468     InstructionFoldingCase<float>(
2469         Header() + "%main = OpFunction %void None %void_func\n" +
2470             "%main_lab = OpLabel\n" +
2471             "%2 = OpQuantizeToF16 %float %float_2049\n" +
2472             "OpReturn\n" +
2473             "OpFunctionEnd",
2474         2, 2048),
2475     // Test case 14: QuantizeToF16 negative non exact
2476     InstructionFoldingCase<float>(
2477         Header() + "%main = OpFunction %void None %void_func\n" +
2478             "%main_lab = OpLabel\n" +
2479             "%2 = OpQuantizeToF16 %float %float_n2049\n" +
2480             "OpReturn\n" +
2481             "OpFunctionEnd",
2482         2, -2048),
2483     // Test case 15: QuantizeToF16 large positive
2484     InstructionFoldingCase<float>(
2485         Header() + "%main = OpFunction %void None %void_func\n" +
2486             "%main_lab = OpLabel\n" +
2487             "%2 = OpQuantizeToF16 %float %float_1e16\n" +
2488             "OpReturn\n" +
2489             "OpFunctionEnd",
2490         2, std::numeric_limits<float>::infinity()),
2491     // Test case 16: QuantizeToF16 large negative
2492     InstructionFoldingCase<float>(
2493         Header() + "%main = OpFunction %void None %void_func\n" +
2494             "%main_lab = OpLabel\n" +
2495             "%2 = OpQuantizeToF16 %float %float_n1e16\n" +
2496             "OpReturn\n" +
2497             "OpFunctionEnd",
2498         2, -std::numeric_limits<float>::infinity()),
2499     // Test case 17: QuantizeToF16 small positive
2500     InstructionFoldingCase<float>(
2501         Header() + "%main = OpFunction %void None %void_func\n" +
2502             "%main_lab = OpLabel\n" +
2503             "%2 = OpQuantizeToF16 %float %float_1en16\n" +
2504             "OpReturn\n" +
2505             "OpFunctionEnd",
2506         2, 0.0),
2507     // Test case 18: QuantizeToF16 small negative
2508     InstructionFoldingCase<float>(
2509         Header() + "%main = OpFunction %void None %void_func\n" +
2510             "%main_lab = OpLabel\n" +
2511             "%2 = OpQuantizeToF16 %float %float_n1en16\n" +
2512             "OpReturn\n" +
2513             "OpFunctionEnd",
2514         2, 0.0),
2515     // Test case 19: QuantizeToF16 nan
2516     InstructionFoldingCase<float>(
2517         HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2518             "%main_lab = OpLabel\n" +
2519             "%2 = OpQuantizeToF16 %float %float_nan\n" +
2520             "OpReturn\n" +
2521             "OpFunctionEnd",
2522         2, std::numeric_limits<float>::quiet_NaN()),
2523     // Test case 20: FMix 1.0 4.0 0.2
2524     InstructionFoldingCase<float>(
2525         Header() + "%main = OpFunction %void None %void_func\n" +
2526             "%main_lab = OpLabel\n" +
2527             "%2 = OpExtInst %float %1 FMix %float_1 %float_4 %float_0p2\n" +
2528             "OpReturn\n" +
2529             "OpFunctionEnd",
2530         2, 1.6f),
2531     // Test case 21: FMin 1.0 4.0
2532     InstructionFoldingCase<float>(
2533         Header() + "%main = OpFunction %void None %void_func\n" +
2534             "%main_lab = OpLabel\n" +
2535             "%2 = OpExtInst %float %1 FMin %float_1 %float_4\n" +
2536             "OpReturn\n" +
2537             "OpFunctionEnd",
2538         2, 1.0f),
2539     // Test case 22: FMin 4.0 0.2
2540     InstructionFoldingCase<float>(
2541         Header() + "%main = OpFunction %void None %void_func\n" +
2542             "%main_lab = OpLabel\n" +
2543             "%2 = OpExtInst %float %1 FMin %float_4 %float_0p2\n" +
2544             "OpReturn\n" +
2545             "OpFunctionEnd",
2546         2, 0.2f),
2547     // Test case 23: FMax 1.0 4.0
2548     InstructionFoldingCase<float>(
2549         Header() + "%main = OpFunction %void None %void_func\n" +
2550             "%main_lab = OpLabel\n" +
2551             "%2 = OpExtInst %float %1 FMax %float_1 %float_4\n" +
2552             "OpReturn\n" +
2553             "OpFunctionEnd",
2554         2, 4.0f),
2555     // Test case 24: FMax 1.0 0.2
2556     InstructionFoldingCase<float>(
2557         Header() + "%main = OpFunction %void None %void_func\n" +
2558             "%main_lab = OpLabel\n" +
2559             "%2 = OpExtInst %float %1 FMax %float_1 %float_0p2\n" +
2560             "OpReturn\n" +
2561             "OpFunctionEnd",
2562         2, 1.0f),
2563     // Test case 25: FClamp 1.0 0.2 4.0
2564     InstructionFoldingCase<float>(
2565         Header() + "%main = OpFunction %void None %void_func\n" +
2566             "%main_lab = OpLabel\n" +
2567             "%2 = OpExtInst %float %1 FClamp %float_1 %float_0p2 %float_4\n" +
2568             "OpReturn\n" +
2569             "OpFunctionEnd",
2570         2, 1.0f),
2571     // Test case 26: FClamp 0.2 2.0 4.0
2572     InstructionFoldingCase<float>(
2573         Header() + "%main = OpFunction %void None %void_func\n" +
2574             "%main_lab = OpLabel\n" +
2575             "%2 = OpExtInst %float %1 FClamp %float_0p2 %float_2 %float_4\n" +
2576             "OpReturn\n" +
2577             "OpFunctionEnd",
2578         2, 2.0f),
2579     // Test case 27: FClamp 2049.0 2.0 4.0
2580     InstructionFoldingCase<float>(
2581         Header() + "%main = OpFunction %void None %void_func\n" +
2582             "%main_lab = OpLabel\n" +
2583             "%2 = OpExtInst %float %1 FClamp %float_2049 %float_2 %float_4\n" +
2584             "OpReturn\n" +
2585             "OpFunctionEnd",
2586         2, 4.0f),
2587     // Test case 28: FClamp 1.0 2.0 x
2588     InstructionFoldingCase<float>(
2589         Header() + "%main = OpFunction %void None %void_func\n" +
2590             "%main_lab = OpLabel\n" +
2591             "%undef = OpUndef %float\n" +
2592             "%2 = OpExtInst %float %1 FClamp %float_1 %float_2 %undef\n" +
2593             "OpReturn\n" +
2594             "OpFunctionEnd",
2595         2, 2.0),
2596     // Test case 29: FClamp 1.0 x 0.5
2597     InstructionFoldingCase<float>(
2598         Header() + "%main = OpFunction %void None %void_func\n" +
2599             "%main_lab = OpLabel\n" +
2600             "%undef = OpUndef %float\n" +
2601             "%2 = OpExtInst %float %1 FClamp %float_1 %undef %float_0p5\n" +
2602             "OpReturn\n" +
2603             "OpFunctionEnd",
2604         2, 0.5),
2605     // Test case 30: Sin 0.0
2606     InstructionFoldingCase<float>(
2607         Header() + "%main = OpFunction %void None %void_func\n" +
2608             "%main_lab = OpLabel\n" +
2609             "%2 = OpExtInst %float %1 Sin %float_0\n" +
2610             "OpReturn\n" +
2611             "OpFunctionEnd",
2612         2, 0.0),
2613     // Test case 31: Cos 0.0
2614     InstructionFoldingCase<float>(
2615         Header() + "%main = OpFunction %void None %void_func\n" +
2616             "%main_lab = OpLabel\n" +
2617             "%2 = OpExtInst %float %1 Cos %float_0\n" +
2618             "OpReturn\n" +
2619             "OpFunctionEnd",
2620         2, 1.0),
2621     // Test case 32: Tan 0.0
2622     InstructionFoldingCase<float>(
2623         Header() + "%main = OpFunction %void None %void_func\n" +
2624             "%main_lab = OpLabel\n" +
2625             "%2 = OpExtInst %float %1 Tan %float_0\n" +
2626             "OpReturn\n" +
2627             "OpFunctionEnd",
2628         2, 0.0),
2629     // Test case 33: Asin 0.0
2630     InstructionFoldingCase<float>(
2631         Header() + "%main = OpFunction %void None %void_func\n" +
2632             "%main_lab = OpLabel\n" +
2633             "%2 = OpExtInst %float %1 Asin %float_0\n" +
2634             "OpReturn\n" +
2635             "OpFunctionEnd",
2636         2, 0.0),
2637     // Test case 34: Acos 1.0
2638     InstructionFoldingCase<float>(
2639         Header() + "%main = OpFunction %void None %void_func\n" +
2640             "%main_lab = OpLabel\n" +
2641             "%2 = OpExtInst %float %1 Acos %float_1\n" +
2642             "OpReturn\n" +
2643             "OpFunctionEnd",
2644         2, 0.0),
2645     // Test case 35: Atan 0.0
2646     InstructionFoldingCase<float>(
2647         Header() + "%main = OpFunction %void None %void_func\n" +
2648             "%main_lab = OpLabel\n" +
2649             "%2 = OpExtInst %float %1 Atan %float_0\n" +
2650             "OpReturn\n" +
2651             "OpFunctionEnd",
2652         2, 0.0),
2653     // Test case 36: Exp 0.0
2654     InstructionFoldingCase<float>(
2655         Header() + "%main = OpFunction %void None %void_func\n" +
2656             "%main_lab = OpLabel\n" +
2657             "%2 = OpExtInst %float %1 Exp %float_0\n" +
2658             "OpReturn\n" +
2659             "OpFunctionEnd",
2660         2, 1.0),
2661     // Test case 37: Log 1.0
2662     InstructionFoldingCase<float>(
2663         Header() + "%main = OpFunction %void None %void_func\n" +
2664             "%main_lab = OpLabel\n" +
2665             "%2 = OpExtInst %float %1 Log %float_1\n" +
2666             "OpReturn\n" +
2667             "OpFunctionEnd",
2668         2, 0.0),
2669     // Test case 38: Exp2 2.0
2670     InstructionFoldingCase<float>(
2671         Header() + "%main = OpFunction %void None %void_func\n" +
2672             "%main_lab = OpLabel\n" +
2673             "%2 = OpExtInst %float %1 Exp2 %float_2\n" +
2674             "OpReturn\n" +
2675             "OpFunctionEnd",
2676         2, 4.0),
2677     // Test case 39: Log2 4.0
2678     InstructionFoldingCase<float>(
2679         Header() + "%main = OpFunction %void None %void_func\n" +
2680             "%main_lab = OpLabel\n" +
2681             "%2 = OpExtInst %float %1 Log2 %float_4\n" +
2682             "OpReturn\n" +
2683             "OpFunctionEnd",
2684         2, 2.0),
2685     // Test case 40: Sqrt 4.0
2686     InstructionFoldingCase<float>(
2687         Header() + "%main = OpFunction %void None %void_func\n" +
2688             "%main_lab = OpLabel\n" +
2689             "%2 = OpExtInst %float %1 Sqrt %float_4\n" +
2690             "OpReturn\n" +
2691             "OpFunctionEnd",
2692         2, 2.0),
2693     // Test case 41: Atan2 0.0 1.0
2694     InstructionFoldingCase<float>(
2695         Header() + "%main = OpFunction %void None %void_func\n" +
2696             "%main_lab = OpLabel\n" +
2697             "%2 = OpExtInst %float %1 Atan2 %float_0 %float_1\n" +
2698             "OpReturn\n" +
2699             "OpFunctionEnd",
2700         2, 0.0),
2701     // Test case 42: Pow 2.0 3.0
2702     InstructionFoldingCase<float>(
2703         Header() + "%main = OpFunction %void None %void_func\n" +
2704             "%main_lab = OpLabel\n" +
2705             "%2 = OpExtInst %float %1 Pow %float_2 %float_3\n" +
2706             "OpReturn\n" +
2707             "OpFunctionEnd",
2708         2, 8.0),
2709     // Test case 43: Fold 1.0 / -0.0.
2710     InstructionFoldingCase<float>(
2711         Header() + "%main = OpFunction %void None %void_func\n" +
2712             "%main_lab = OpLabel\n" +
2713             "%2 = OpFDiv %float %float_1 %float_n0\n" +
2714             "OpReturn\n" +
2715             "OpFunctionEnd",
2716         2, -std::numeric_limits<float>::infinity()),
2717     // Test case 44: Fold -1.0 / -0.0
2718     InstructionFoldingCase<float>(
2719         Header() + "%main = OpFunction %void None %void_func\n" +
2720             "%main_lab = OpLabel\n" +
2721             "%2 = OpFDiv %float %float_n1 %float_n0\n" +
2722             "OpReturn\n" +
2723             "OpFunctionEnd",
2724         2, std::numeric_limits<float>::infinity()),
2725     // Test case 45: Fold 0.0 / 0.0
2726     InstructionFoldingCase<float>(
2727         Header() + "%main = OpFunction %void None %void_func\n" +
2728             "%main_lab = OpLabel\n" +
2729             "%2 = OpFDiv %float %float_0 %float_0\n" +
2730             "OpReturn\n" +
2731             "OpFunctionEnd",
2732         2, std::numeric_limits<float>::quiet_NaN()),
2733     // Test case 46: Fold 0.0 / -0.0
2734     InstructionFoldingCase<float>(
2735         Header() + "%main = OpFunction %void None %void_func\n" +
2736             "%main_lab = OpLabel\n" +
2737             "%2 = OpFDiv %float %float_0 %float_n0\n" +
2738             "OpReturn\n" +
2739             "OpFunctionEnd",
2740         2, std::numeric_limits<float>::quiet_NaN())
2741 ));
2742 // clang-format on
2743 
2744 using DoubleInstructionFoldingTest =
2745     ::testing::TestWithParam<InstructionFoldingCase<double>>;
2746 
TEST_P(DoubleInstructionFoldingTest,Case)2747 TEST_P(DoubleInstructionFoldingTest, Case) {
2748   const auto& tc = GetParam();
2749 
2750   std::unique_ptr<IRContext> context;
2751   Instruction* inst;
2752   std::tie(context, inst) =
2753       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
2754   CheckForExpectedScalarConstant(
2755       inst, tc.expected_result, [](const analysis::Constant* c) {
2756         return c->AsFloatConstant()->GetDoubleValue();
2757       });
2758 }
2759 
2760 // clang-format off
2761 INSTANTIATE_TEST_SUITE_P(DoubleConstantFoldingTest, DoubleInstructionFoldingTest,
2762 ::testing::Values(
2763     // Test case 0: Fold 2.0 - 1.0
2764     InstructionFoldingCase<double>(
2765         Header() + "%main = OpFunction %void None %void_func\n" +
2766             "%main_lab = OpLabel\n" +
2767             "%2 = OpFSub %double %double_2 %double_1\n" +
2768             "OpReturn\n" +
2769             "OpFunctionEnd",
2770         2, 1.0),
2771         // Test case 1: Fold 2.0 + 1.0
2772         InstructionFoldingCase<double>(
2773             Header() + "%main = OpFunction %void None %void_func\n" +
2774                 "%main_lab = OpLabel\n" +
2775                 "%2 = OpFAdd %double %double_2 %double_1\n" +
2776                 "OpReturn\n" +
2777                 "OpFunctionEnd",
2778             2, 3.0),
2779         // Test case 2: Fold 3.0 * 2.0
2780         InstructionFoldingCase<double>(
2781             Header() + "%main = OpFunction %void None %void_func\n" +
2782                 "%main_lab = OpLabel\n" +
2783                 "%2 = OpFMul %double %double_3 %double_2\n" +
2784                 "OpReturn\n" +
2785                 "OpFunctionEnd",
2786             2, 6.0),
2787         // Test case 3: Fold 1.0 / 2.0
2788         InstructionFoldingCase<double>(
2789             Header() + "%main = OpFunction %void None %void_func\n" +
2790                 "%main_lab = OpLabel\n" +
2791                 "%2 = OpFDiv %double %double_1 %double_2\n" +
2792                 "OpReturn\n" +
2793                 "OpFunctionEnd",
2794             2, 0.5),
2795         // Test case 4: Fold 1.0 / 0.0
2796         InstructionFoldingCase<double>(
2797             Header() + "%main = OpFunction %void None %void_func\n" +
2798                 "%main_lab = OpLabel\n" +
2799                 "%2 = OpFDiv %double %double_1 %double_0\n" +
2800                 "OpReturn\n" +
2801                 "OpFunctionEnd",
2802             2, std::numeric_limits<double>::infinity()),
2803         // Test case 5: Fold -1.0 / 0.0
2804         InstructionFoldingCase<double>(
2805             Header() + "%main = OpFunction %void None %void_func\n" +
2806                 "%main_lab = OpLabel\n" +
2807                 "%2 = OpFDiv %double %double_n1 %double_0\n" +
2808                 "OpReturn\n" +
2809                 "OpFunctionEnd",
2810             2, -std::numeric_limits<double>::infinity()),
2811         // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
2812         InstructionFoldingCase<double>(
2813             Header() + "%main = OpFunction %void None %void_func\n" +
2814                 "%main_lab = OpLabel\n" +
2815                 "%2 = OpDot %double %v2double_2_3 %v2double_2_0p5\n" +
2816                 "OpReturn\n" +
2817                 "OpFunctionEnd",
2818             2, 5.5f),
2819         // Test case 7: Fold (0.0, 0.0) dot v
2820         InstructionFoldingCase<double>(
2821             Header() + "%main = OpFunction %void None %void_func\n" +
2822                 "%main_lab = OpLabel\n" +
2823                 "%v = OpVariable %_ptr_v2double Function\n" +
2824                 "%2 = OpLoad %v2double %v\n" +
2825                 "%3 = OpDot %double %v2double_0_0 %2\n" +
2826                 "OpReturn\n" +
2827                 "OpFunctionEnd",
2828             3, 0.0f),
2829         // Test case 8: Fold v dot (0.0, 0.0)
2830         InstructionFoldingCase<double>(
2831             Header() + "%main = OpFunction %void None %void_func\n" +
2832                 "%main_lab = OpLabel\n" +
2833                 "%v = OpVariable %_ptr_v2double Function\n" +
2834                 "%2 = OpLoad %v2double %v\n" +
2835                 "%3 = OpDot %double %2 %v2double_0_0\n" +
2836                 "OpReturn\n" +
2837                 "OpFunctionEnd",
2838             3, 0.0f),
2839         // Test case 9: Fold Null dot v
2840         InstructionFoldingCase<double>(
2841             Header() + "%main = OpFunction %void None %void_func\n" +
2842                 "%main_lab = OpLabel\n" +
2843                 "%v = OpVariable %_ptr_v2double Function\n" +
2844                 "%2 = OpLoad %v2double %v\n" +
2845                 "%3 = OpDot %double %v2double_null %2\n" +
2846                 "OpReturn\n" +
2847                 "OpFunctionEnd",
2848             3, 0.0f),
2849         // Test case 10: Fold v dot Null
2850         InstructionFoldingCase<double>(
2851             Header() + "%main = OpFunction %void None %void_func\n" +
2852                 "%main_lab = OpLabel\n" +
2853                 "%v = OpVariable %_ptr_v2double Function\n" +
2854                 "%2 = OpLoad %v2double %v\n" +
2855                 "%3 = OpDot %double %2 %v2double_null\n" +
2856                 "OpReturn\n" +
2857                 "OpFunctionEnd",
2858             3, 0.0f),
2859         // Test case 11: Fold -2.0
2860         InstructionFoldingCase<double>(
2861             Header() + "%main = OpFunction %void None %void_func\n" +
2862                 "%main_lab = OpLabel\n" +
2863                 "%2 = OpFNegate %double %double_2\n" +
2864                 "OpReturn\n" +
2865                 "OpFunctionEnd",
2866             2, -2),
2867         // Test case 12: FMin 1.0 4.0
2868         InstructionFoldingCase<double>(
2869             Header() + "%main = OpFunction %void None %void_func\n" +
2870                 "%main_lab = OpLabel\n" +
2871                 "%2 = OpExtInst %double %1 FMin %double_1 %double_4\n" +
2872                 "OpReturn\n" +
2873                 "OpFunctionEnd",
2874             2, 1.0),
2875         // Test case 13: FMin 4.0 0.2
2876         InstructionFoldingCase<double>(
2877             Header() + "%main = OpFunction %void None %void_func\n" +
2878                 "%main_lab = OpLabel\n" +
2879                 "%2 = OpExtInst %double %1 FMin %double_4 %double_0p2\n" +
2880                 "OpReturn\n" +
2881                 "OpFunctionEnd",
2882             2, 0.2),
2883         // Test case 14: FMax 1.0 4.0
2884         InstructionFoldingCase<double>(
2885             Header() + "%main = OpFunction %void None %void_func\n" +
2886                 "%main_lab = OpLabel\n" +
2887                 "%2 = OpExtInst %double %1 FMax %double_1 %double_4\n" +
2888                 "OpReturn\n" +
2889                 "OpFunctionEnd",
2890             2, 4.0),
2891         // Test case 15: FMax 1.0 0.2
2892         InstructionFoldingCase<double>(
2893             Header() + "%main = OpFunction %void None %void_func\n" +
2894                 "%main_lab = OpLabel\n" +
2895                 "%2 = OpExtInst %double %1 FMax %double_1 %double_0p2\n" +
2896                 "OpReturn\n" +
2897                 "OpFunctionEnd",
2898             2, 1.0),
2899         // Test case 16: FClamp 1.0 0.2 4.0
2900         InstructionFoldingCase<double>(
2901             Header() + "%main = OpFunction %void None %void_func\n" +
2902                 "%main_lab = OpLabel\n" +
2903                 "%2 = OpExtInst %double %1 FClamp %double_1 %double_0p2 %double_4\n" +
2904                 "OpReturn\n" +
2905                 "OpFunctionEnd",
2906             2, 1.0),
2907         // Test case 17: FClamp 0.2 2.0 4.0
2908         InstructionFoldingCase<double>(
2909             Header() + "%main = OpFunction %void None %void_func\n" +
2910                 "%main_lab = OpLabel\n" +
2911                 "%2 = OpExtInst %double %1 FClamp %double_0p2 %double_2 %double_4\n" +
2912                 "OpReturn\n" +
2913                 "OpFunctionEnd",
2914             2, 2.0),
2915         // Test case 18: FClamp 5.0 2.0 4.0
2916         InstructionFoldingCase<double>(
2917             Header() + "%main = OpFunction %void None %void_func\n" +
2918                 "%main_lab = OpLabel\n" +
2919                 "%2 = OpExtInst %double %1 FClamp %double_5 %double_2 %double_4\n" +
2920                 "OpReturn\n" +
2921                 "OpFunctionEnd",
2922             2, 4.0),
2923         // Test case 19: FClamp 1.0 2.0 x
2924         InstructionFoldingCase<double>(
2925             Header() + "%main = OpFunction %void None %void_func\n" +
2926                 "%main_lab = OpLabel\n" +
2927                 "%undef = OpUndef %double\n" +
2928                 "%2 = OpExtInst %double %1 FClamp %double_1 %double_2 %undef\n" +
2929                 "OpReturn\n" +
2930                 "OpFunctionEnd",
2931             2, 2.0),
2932         // Test case 20: FClamp 1.0 x 0.5
2933         InstructionFoldingCase<double>(
2934             Header() + "%main = OpFunction %void None %void_func\n" +
2935                 "%main_lab = OpLabel\n" +
2936                 "%undef = OpUndef %double\n" +
2937                 "%2 = OpExtInst %double %1 FClamp %double_1 %undef %double_0p5\n" +
2938                 "OpReturn\n" +
2939                 "OpFunctionEnd",
2940             2, 0.5),
2941         // Test case 21: Sqrt 4.0
2942         InstructionFoldingCase<double>(
2943             Header() + "%main = OpFunction %void None %void_func\n" +
2944                 "%main_lab = OpLabel\n" +
2945                 "%undef = OpUndef %double\n" +
2946                 "%2 = OpExtInst %double %1 Sqrt %double_4\n" +
2947                 "OpReturn\n" +
2948                 "OpFunctionEnd",
2949             2, 2.0),
2950         // Test case 22: Pow 2.0 3.0
2951         InstructionFoldingCase<double>(
2952             Header() + "%main = OpFunction %void None %void_func\n" +
2953                 "%main_lab = OpLabel\n" +
2954                 "%undef = OpUndef %double\n" +
2955                 "%2 = OpExtInst %double %1 Pow %double_2 %double_3\n" +
2956                 "OpReturn\n" +
2957                 "OpFunctionEnd",
2958             2, 8.0),
2959         // Test case 23: Fold 1.0 / -0.0.
2960         InstructionFoldingCase<double>(
2961             Header() + "%main = OpFunction %void None %void_func\n" +
2962                 "%main_lab = OpLabel\n" +
2963                 "%2 = OpFDiv %double %double_1 %double_n0\n" +
2964                 "OpReturn\n" +
2965                 "OpFunctionEnd",
2966             2, -std::numeric_limits<double>::infinity()),
2967         // Test case 24: Fold -1.0 / -0.0
2968         InstructionFoldingCase<double>(
2969             Header() + "%main = OpFunction %void None %void_func\n" +
2970                 "%main_lab = OpLabel\n" +
2971                 "%2 = OpFDiv %double %double_n1 %double_n0\n" +
2972                 "OpReturn\n" +
2973                 "OpFunctionEnd",
2974             2, std::numeric_limits<double>::infinity()),
2975         // Test case 25: Fold 0.0 / 0.0
2976         InstructionFoldingCase<double>(
2977             Header() + "%main = OpFunction %void None %void_func\n" +
2978                 "%main_lab = OpLabel\n" +
2979                 "%2 = OpFDiv %double %double_0 %double_0\n" +
2980                 "OpReturn\n" +
2981                 "OpFunctionEnd",
2982             2, std::numeric_limits<double>::quiet_NaN()),
2983         // Test case 26: Fold 0.0 / -0.0
2984         InstructionFoldingCase<double>(
2985             Header() + "%main = OpFunction %void None %void_func\n" +
2986                 "%main_lab = OpLabel\n" +
2987                 "%2 = OpFDiv %double %double_0 %double_n0\n" +
2988                 "OpReturn\n" +
2989                 "OpFunctionEnd",
2990             2, std::numeric_limits<double>::quiet_NaN())
2991 ));
2992 // clang-format on
2993 
2994 // clang-format off
2995 INSTANTIATE_TEST_SUITE_P(DoubleOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
2996                         ::testing::Values(
2997   // Test case 0: fold 1.0 == 2.0
2998   InstructionFoldingCase<bool>(
2999       Header() + "%main = OpFunction %void None %void_func\n" +
3000           "%main_lab = OpLabel\n" +
3001           "%2 = OpFOrdEqual %bool %double_1 %double_2\n" +
3002           "OpReturn\n" +
3003           "OpFunctionEnd",
3004       2, false),
3005   // Test case 1: fold 1.0 != 2.0
3006   InstructionFoldingCase<bool>(
3007       Header() + "%main = OpFunction %void None %void_func\n" +
3008           "%main_lab = OpLabel\n" +
3009           "%2 = OpFOrdNotEqual %bool %double_1 %double_2\n" +
3010           "OpReturn\n" +
3011           "OpFunctionEnd",
3012       2, true),
3013   // Test case 2: fold 1.0 < 2.0
3014   InstructionFoldingCase<bool>(
3015       Header() + "%main = OpFunction %void None %void_func\n" +
3016           "%main_lab = OpLabel\n" +
3017           "%2 = OpFOrdLessThan %bool %double_1 %double_2\n" +
3018           "OpReturn\n" +
3019           "OpFunctionEnd",
3020       2, true),
3021   // Test case 3: fold 1.0 > 2.0
3022   InstructionFoldingCase<bool>(
3023       Header() + "%main = OpFunction %void None %void_func\n" +
3024           "%main_lab = OpLabel\n" +
3025           "%2 = OpFOrdGreaterThan %bool %double_1 %double_2\n" +
3026           "OpReturn\n" +
3027           "OpFunctionEnd",
3028       2, false),
3029   // Test case 4: fold 1.0 <= 2.0
3030   InstructionFoldingCase<bool>(
3031       Header() + "%main = OpFunction %void None %void_func\n" +
3032           "%main_lab = OpLabel\n" +
3033           "%2 = OpFOrdLessThanEqual %bool %double_1 %double_2\n" +
3034           "OpReturn\n" +
3035           "OpFunctionEnd",
3036       2, true),
3037   // Test case 5: fold 1.0 >= 2.0
3038   InstructionFoldingCase<bool>(
3039       Header() + "%main = OpFunction %void None %void_func\n" +
3040           "%main_lab = OpLabel\n" +
3041           "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_2\n" +
3042           "OpReturn\n" +
3043           "OpFunctionEnd",
3044       2, false),
3045   // Test case 6: fold 1.0 == 1.0
3046   InstructionFoldingCase<bool>(
3047       Header() + "%main = OpFunction %void None %void_func\n" +
3048           "%main_lab = OpLabel\n" +
3049           "%2 = OpFOrdEqual %bool %double_1 %double_1\n" +
3050           "OpReturn\n" +
3051           "OpFunctionEnd",
3052       2, true),
3053   // Test case 7: fold 1.0 != 1.0
3054   InstructionFoldingCase<bool>(
3055       Header() + "%main = OpFunction %void None %void_func\n" +
3056           "%main_lab = OpLabel\n" +
3057           "%2 = OpFOrdNotEqual %bool %double_1 %double_1\n" +
3058           "OpReturn\n" +
3059           "OpFunctionEnd",
3060       2, false),
3061   // Test case 8: fold 1.0 < 1.0
3062   InstructionFoldingCase<bool>(
3063       Header() + "%main = OpFunction %void None %void_func\n" +
3064           "%main_lab = OpLabel\n" +
3065           "%2 = OpFOrdLessThan %bool %double_1 %double_1\n" +
3066           "OpReturn\n" +
3067           "OpFunctionEnd",
3068       2, false),
3069   // Test case 9: fold 1.0 > 1.0
3070   InstructionFoldingCase<bool>(
3071       Header() + "%main = OpFunction %void None %void_func\n" +
3072           "%main_lab = OpLabel\n" +
3073           "%2 = OpFOrdGreaterThan %bool %double_1 %double_1\n" +
3074           "OpReturn\n" +
3075           "OpFunctionEnd",
3076       2, false),
3077   // Test case 10: fold 1.0 <= 1.0
3078   InstructionFoldingCase<bool>(
3079       Header() + "%main = OpFunction %void None %void_func\n" +
3080           "%main_lab = OpLabel\n" +
3081           "%2 = OpFOrdLessThanEqual %bool %double_1 %double_1\n" +
3082           "OpReturn\n" +
3083           "OpFunctionEnd",
3084       2, true),
3085   // Test case 11: fold 1.0 >= 1.0
3086   InstructionFoldingCase<bool>(
3087       Header() + "%main = OpFunction %void None %void_func\n" +
3088           "%main_lab = OpLabel\n" +
3089           "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_1\n" +
3090           "OpReturn\n" +
3091           "OpFunctionEnd",
3092       2, true),
3093   // Test case 12: fold 2.0 < 1.0
3094   InstructionFoldingCase<bool>(
3095       Header() + "%main = OpFunction %void None %void_func\n" +
3096           "%main_lab = OpLabel\n" +
3097           "%2 = OpFOrdLessThan %bool %double_2 %double_1\n" +
3098           "OpReturn\n" +
3099           "OpFunctionEnd",
3100       2, false),
3101   // Test case 13: fold 2.0 > 1.0
3102   InstructionFoldingCase<bool>(
3103       Header() + "%main = OpFunction %void None %void_func\n" +
3104           "%main_lab = OpLabel\n" +
3105           "%2 = OpFOrdGreaterThan %bool %double_2 %double_1\n" +
3106           "OpReturn\n" +
3107           "OpFunctionEnd",
3108       2, true),
3109   // Test case 14: fold 2.0 <= 1.0
3110   InstructionFoldingCase<bool>(
3111       Header() + "%main = OpFunction %void None %void_func\n" +
3112           "%main_lab = OpLabel\n" +
3113           "%2 = OpFOrdLessThanEqual %bool %double_2 %double_1\n" +
3114           "OpReturn\n" +
3115           "OpFunctionEnd",
3116       2, false),
3117   // Test case 15: fold 2.0 >= 1.0
3118   InstructionFoldingCase<bool>(
3119       Header() + "%main = OpFunction %void None %void_func\n" +
3120           "%main_lab = OpLabel\n" +
3121           "%2 = OpFOrdGreaterThanEqual %bool %double_2 %double_1\n" +
3122           "OpReturn\n" +
3123           "OpFunctionEnd",
3124       2, true)
3125 ));
3126 
3127 INSTANTIATE_TEST_SUITE_P(DoubleUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3128                         ::testing::Values(
3129   // Test case 0: fold 1.0 == 2.0
3130   InstructionFoldingCase<bool>(
3131       Header() + "%main = OpFunction %void None %void_func\n" +
3132           "%main_lab = OpLabel\n" +
3133           "%2 = OpFUnordEqual %bool %double_1 %double_2\n" +
3134           "OpReturn\n" +
3135           "OpFunctionEnd",
3136       2, false),
3137   // Test case 1: fold 1.0 != 2.0
3138   InstructionFoldingCase<bool>(
3139       Header() + "%main = OpFunction %void None %void_func\n" +
3140           "%main_lab = OpLabel\n" +
3141           "%2 = OpFUnordNotEqual %bool %double_1 %double_2\n" +
3142           "OpReturn\n" +
3143           "OpFunctionEnd",
3144       2, true),
3145   // Test case 2: fold 1.0 < 2.0
3146   InstructionFoldingCase<bool>(
3147       Header() + "%main = OpFunction %void None %void_func\n" +
3148           "%main_lab = OpLabel\n" +
3149           "%2 = OpFUnordLessThan %bool %double_1 %double_2\n" +
3150           "OpReturn\n" +
3151           "OpFunctionEnd",
3152       2, true),
3153   // Test case 3: fold 1.0 > 2.0
3154   InstructionFoldingCase<bool>(
3155       Header() + "%main = OpFunction %void None %void_func\n" +
3156           "%main_lab = OpLabel\n" +
3157           "%2 = OpFUnordGreaterThan %bool %double_1 %double_2\n" +
3158           "OpReturn\n" +
3159           "OpFunctionEnd",
3160       2, false),
3161   // Test case 4: fold 1.0 <= 2.0
3162   InstructionFoldingCase<bool>(
3163       Header() + "%main = OpFunction %void None %void_func\n" +
3164           "%main_lab = OpLabel\n" +
3165           "%2 = OpFUnordLessThanEqual %bool %double_1 %double_2\n" +
3166           "OpReturn\n" +
3167           "OpFunctionEnd",
3168       2, true),
3169   // Test case 5: fold 1.0 >= 2.0
3170   InstructionFoldingCase<bool>(
3171       Header() + "%main = OpFunction %void None %void_func\n" +
3172           "%main_lab = OpLabel\n" +
3173           "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_2\n" +
3174           "OpReturn\n" +
3175           "OpFunctionEnd",
3176       2, false),
3177   // Test case 6: fold 1.0 == 1.0
3178   InstructionFoldingCase<bool>(
3179       Header() + "%main = OpFunction %void None %void_func\n" +
3180           "%main_lab = OpLabel\n" +
3181           "%2 = OpFUnordEqual %bool %double_1 %double_1\n" +
3182           "OpReturn\n" +
3183           "OpFunctionEnd",
3184       2, true),
3185   // Test case 7: fold 1.0 != 1.0
3186   InstructionFoldingCase<bool>(
3187       Header() + "%main = OpFunction %void None %void_func\n" +
3188           "%main_lab = OpLabel\n" +
3189           "%2 = OpFUnordNotEqual %bool %double_1 %double_1\n" +
3190           "OpReturn\n" +
3191           "OpFunctionEnd",
3192       2, false),
3193   // Test case 8: fold 1.0 < 1.0
3194   InstructionFoldingCase<bool>(
3195       Header() + "%main = OpFunction %void None %void_func\n" +
3196           "%main_lab = OpLabel\n" +
3197           "%2 = OpFUnordLessThan %bool %double_1 %double_1\n" +
3198           "OpReturn\n" +
3199           "OpFunctionEnd",
3200       2, false),
3201   // Test case 9: fold 1.0 > 1.0
3202   InstructionFoldingCase<bool>(
3203       Header() + "%main = OpFunction %void None %void_func\n" +
3204           "%main_lab = OpLabel\n" +
3205           "%2 = OpFUnordGreaterThan %bool %double_1 %double_1\n" +
3206           "OpReturn\n" +
3207           "OpFunctionEnd",
3208       2, false),
3209   // Test case 10: fold 1.0 <= 1.0
3210   InstructionFoldingCase<bool>(
3211       Header() + "%main = OpFunction %void None %void_func\n" +
3212           "%main_lab = OpLabel\n" +
3213           "%2 = OpFUnordLessThanEqual %bool %double_1 %double_1\n" +
3214           "OpReturn\n" +
3215           "OpFunctionEnd",
3216       2, true),
3217   // Test case 11: fold 1.0 >= 1.0
3218   InstructionFoldingCase<bool>(
3219       Header() + "%main = OpFunction %void None %void_func\n" +
3220           "%main_lab = OpLabel\n" +
3221           "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_1\n" +
3222           "OpReturn\n" +
3223           "OpFunctionEnd",
3224       2, true),
3225   // Test case 12: fold 2.0 < 1.0
3226   InstructionFoldingCase<bool>(
3227       Header() + "%main = OpFunction %void None %void_func\n" +
3228           "%main_lab = OpLabel\n" +
3229           "%2 = OpFUnordLessThan %bool %double_2 %double_1\n" +
3230           "OpReturn\n" +
3231           "OpFunctionEnd",
3232       2, false),
3233   // Test case 13: fold 2.0 > 1.0
3234   InstructionFoldingCase<bool>(
3235       Header() + "%main = OpFunction %void None %void_func\n" +
3236           "%main_lab = OpLabel\n" +
3237           "%2 = OpFUnordGreaterThan %bool %double_2 %double_1\n" +
3238           "OpReturn\n" +
3239           "OpFunctionEnd",
3240       2, true),
3241   // Test case 14: fold 2.0 <= 1.0
3242   InstructionFoldingCase<bool>(
3243       Header() + "%main = OpFunction %void None %void_func\n" +
3244           "%main_lab = OpLabel\n" +
3245           "%2 = OpFUnordLessThanEqual %bool %double_2 %double_1\n" +
3246           "OpReturn\n" +
3247           "OpFunctionEnd",
3248       2, false),
3249   // Test case 15: fold 2.0 >= 1.0
3250   InstructionFoldingCase<bool>(
3251       Header() + "%main = OpFunction %void None %void_func\n" +
3252           "%main_lab = OpLabel\n" +
3253           "%2 = OpFUnordGreaterThanEqual %bool %double_2 %double_1\n" +
3254           "OpReturn\n" +
3255           "OpFunctionEnd",
3256       2, true)
3257 ));
3258 
3259 INSTANTIATE_TEST_SUITE_P(FloatOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3260                         ::testing::Values(
3261   // Test case 0: fold 1.0 == 2.0
3262   InstructionFoldingCase<bool>(
3263       Header() + "%main = OpFunction %void None %void_func\n" +
3264           "%main_lab = OpLabel\n" +
3265           "%2 = OpFOrdEqual %bool %float_1 %float_2\n" +
3266           "OpReturn\n" +
3267           "OpFunctionEnd",
3268       2, false),
3269   // Test case 1: fold 1.0 != 2.0
3270   InstructionFoldingCase<bool>(
3271       Header() + "%main = OpFunction %void None %void_func\n" +
3272           "%main_lab = OpLabel\n" +
3273           "%2 = OpFOrdNotEqual %bool %float_1 %float_2\n" +
3274           "OpReturn\n" +
3275           "OpFunctionEnd",
3276       2, true),
3277   // Test case 2: fold 1.0 < 2.0
3278   InstructionFoldingCase<bool>(
3279       Header() + "%main = OpFunction %void None %void_func\n" +
3280           "%main_lab = OpLabel\n" +
3281           "%2 = OpFOrdLessThan %bool %float_1 %float_2\n" +
3282           "OpReturn\n" +
3283           "OpFunctionEnd",
3284       2, true),
3285   // Test case 3: fold 1.0 > 2.0
3286   InstructionFoldingCase<bool>(
3287       Header() + "%main = OpFunction %void None %void_func\n" +
3288           "%main_lab = OpLabel\n" +
3289           "%2 = OpFOrdGreaterThan %bool %float_1 %float_2\n" +
3290           "OpReturn\n" +
3291           "OpFunctionEnd",
3292       2, false),
3293   // Test case 4: fold 1.0 <= 2.0
3294   InstructionFoldingCase<bool>(
3295       Header() + "%main = OpFunction %void None %void_func\n" +
3296           "%main_lab = OpLabel\n" +
3297           "%2 = OpFOrdLessThanEqual %bool %float_1 %float_2\n" +
3298           "OpReturn\n" +
3299           "OpFunctionEnd",
3300       2, true),
3301   // Test case 5: fold 1.0 >= 2.0
3302   InstructionFoldingCase<bool>(
3303       Header() + "%main = OpFunction %void None %void_func\n" +
3304           "%main_lab = OpLabel\n" +
3305           "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_2\n" +
3306           "OpReturn\n" +
3307           "OpFunctionEnd",
3308       2, false),
3309   // Test case 6: fold 1.0 == 1.0
3310   InstructionFoldingCase<bool>(
3311       Header() + "%main = OpFunction %void None %void_func\n" +
3312           "%main_lab = OpLabel\n" +
3313           "%2 = OpFOrdEqual %bool %float_1 %float_1\n" +
3314           "OpReturn\n" +
3315           "OpFunctionEnd",
3316       2, true),
3317   // Test case 7: fold 1.0 != 1.0
3318   InstructionFoldingCase<bool>(
3319       Header() + "%main = OpFunction %void None %void_func\n" +
3320           "%main_lab = OpLabel\n" +
3321           "%2 = OpFOrdNotEqual %bool %float_1 %float_1\n" +
3322           "OpReturn\n" +
3323           "OpFunctionEnd",
3324       2, false),
3325   // Test case 8: fold 1.0 < 1.0
3326   InstructionFoldingCase<bool>(
3327       Header() + "%main = OpFunction %void None %void_func\n" +
3328           "%main_lab = OpLabel\n" +
3329           "%2 = OpFOrdLessThan %bool %float_1 %float_1\n" +
3330           "OpReturn\n" +
3331           "OpFunctionEnd",
3332       2, false),
3333   // Test case 9: fold 1.0 > 1.0
3334   InstructionFoldingCase<bool>(
3335       Header() + "%main = OpFunction %void None %void_func\n" +
3336           "%main_lab = OpLabel\n" +
3337           "%2 = OpFOrdGreaterThan %bool %float_1 %float_1\n" +
3338           "OpReturn\n" +
3339           "OpFunctionEnd",
3340       2, false),
3341   // Test case 10: fold 1.0 <= 1.0
3342   InstructionFoldingCase<bool>(
3343       Header() + "%main = OpFunction %void None %void_func\n" +
3344           "%main_lab = OpLabel\n" +
3345           "%2 = OpFOrdLessThanEqual %bool %float_1 %float_1\n" +
3346           "OpReturn\n" +
3347           "OpFunctionEnd",
3348       2, true),
3349   // Test case 11: fold 1.0 >= 1.0
3350   InstructionFoldingCase<bool>(
3351       Header() + "%main = OpFunction %void None %void_func\n" +
3352           "%main_lab = OpLabel\n" +
3353           "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_1\n" +
3354           "OpReturn\n" +
3355           "OpFunctionEnd",
3356       2, true),
3357   // Test case 12: fold 2.0 < 1.0
3358   InstructionFoldingCase<bool>(
3359       Header() + "%main = OpFunction %void None %void_func\n" +
3360           "%main_lab = OpLabel\n" +
3361           "%2 = OpFOrdLessThan %bool %float_2 %float_1\n" +
3362           "OpReturn\n" +
3363           "OpFunctionEnd",
3364       2, false),
3365   // Test case 13: fold 2.0 > 1.0
3366   InstructionFoldingCase<bool>(
3367       Header() + "%main = OpFunction %void None %void_func\n" +
3368           "%main_lab = OpLabel\n" +
3369           "%2 = OpFOrdGreaterThan %bool %float_2 %float_1\n" +
3370           "OpReturn\n" +
3371           "OpFunctionEnd",
3372       2, true),
3373   // Test case 14: fold 2.0 <= 1.0
3374   InstructionFoldingCase<bool>(
3375       Header() + "%main = OpFunction %void None %void_func\n" +
3376           "%main_lab = OpLabel\n" +
3377           "%2 = OpFOrdLessThanEqual %bool %float_2 %float_1\n" +
3378           "OpReturn\n" +
3379           "OpFunctionEnd",
3380       2, false),
3381   // Test case 15: fold 2.0 >= 1.0
3382   InstructionFoldingCase<bool>(
3383       Header() + "%main = OpFunction %void None %void_func\n" +
3384           "%main_lab = OpLabel\n" +
3385           "%2 = OpFOrdGreaterThanEqual %bool %float_2 %float_1\n" +
3386           "OpReturn\n" +
3387           "OpFunctionEnd",
3388       2, true)
3389 ));
3390 
3391 INSTANTIATE_TEST_SUITE_P(FloatUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3392                         ::testing::Values(
3393   // Test case 0: fold 1.0 == 2.0
3394   InstructionFoldingCase<bool>(
3395       Header() + "%main = OpFunction %void None %void_func\n" +
3396           "%main_lab = OpLabel\n" +
3397           "%2 = OpFUnordEqual %bool %float_1 %float_2\n" +
3398           "OpReturn\n" +
3399           "OpFunctionEnd",
3400       2, false),
3401   // Test case 1: fold 1.0 != 2.0
3402   InstructionFoldingCase<bool>(
3403       Header() + "%main = OpFunction %void None %void_func\n" +
3404           "%main_lab = OpLabel\n" +
3405           "%2 = OpFUnordNotEqual %bool %float_1 %float_2\n" +
3406           "OpReturn\n" +
3407           "OpFunctionEnd",
3408       2, true),
3409   // Test case 2: fold 1.0 < 2.0
3410   InstructionFoldingCase<bool>(
3411       Header() + "%main = OpFunction %void None %void_func\n" +
3412           "%main_lab = OpLabel\n" +
3413           "%2 = OpFUnordLessThan %bool %float_1 %float_2\n" +
3414           "OpReturn\n" +
3415           "OpFunctionEnd",
3416       2, true),
3417   // Test case 3: fold 1.0 > 2.0
3418   InstructionFoldingCase<bool>(
3419       Header() + "%main = OpFunction %void None %void_func\n" +
3420           "%main_lab = OpLabel\n" +
3421           "%2 = OpFUnordGreaterThan %bool %float_1 %float_2\n" +
3422           "OpReturn\n" +
3423           "OpFunctionEnd",
3424       2, false),
3425   // Test case 4: fold 1.0 <= 2.0
3426   InstructionFoldingCase<bool>(
3427       Header() + "%main = OpFunction %void None %void_func\n" +
3428           "%main_lab = OpLabel\n" +
3429           "%2 = OpFUnordLessThanEqual %bool %float_1 %float_2\n" +
3430           "OpReturn\n" +
3431           "OpFunctionEnd",
3432       2, true),
3433   // Test case 5: fold 1.0 >= 2.0
3434   InstructionFoldingCase<bool>(
3435       Header() + "%main = OpFunction %void None %void_func\n" +
3436           "%main_lab = OpLabel\n" +
3437           "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_2\n" +
3438           "OpReturn\n" +
3439           "OpFunctionEnd",
3440       2, false),
3441   // Test case 6: fold 1.0 == 1.0
3442   InstructionFoldingCase<bool>(
3443       Header() + "%main = OpFunction %void None %void_func\n" +
3444           "%main_lab = OpLabel\n" +
3445           "%2 = OpFUnordEqual %bool %float_1 %float_1\n" +
3446           "OpReturn\n" +
3447           "OpFunctionEnd",
3448       2, true),
3449   // Test case 7: fold 1.0 != 1.0
3450   InstructionFoldingCase<bool>(
3451       Header() + "%main = OpFunction %void None %void_func\n" +
3452           "%main_lab = OpLabel\n" +
3453           "%2 = OpFUnordNotEqual %bool %float_1 %float_1\n" +
3454           "OpReturn\n" +
3455           "OpFunctionEnd",
3456       2, false),
3457   // Test case 8: fold 1.0 < 1.0
3458   InstructionFoldingCase<bool>(
3459       Header() + "%main = OpFunction %void None %void_func\n" +
3460           "%main_lab = OpLabel\n" +
3461           "%2 = OpFUnordLessThan %bool %float_1 %float_1\n" +
3462           "OpReturn\n" +
3463           "OpFunctionEnd",
3464       2, false),
3465   // Test case 9: fold 1.0 > 1.0
3466   InstructionFoldingCase<bool>(
3467       Header() + "%main = OpFunction %void None %void_func\n" +
3468           "%main_lab = OpLabel\n" +
3469           "%2 = OpFUnordGreaterThan %bool %float_1 %float_1\n" +
3470           "OpReturn\n" +
3471           "OpFunctionEnd",
3472       2, false),
3473   // Test case 10: fold 1.0 <= 1.0
3474   InstructionFoldingCase<bool>(
3475       Header() + "%main = OpFunction %void None %void_func\n" +
3476           "%main_lab = OpLabel\n" +
3477           "%2 = OpFUnordLessThanEqual %bool %float_1 %float_1\n" +
3478           "OpReturn\n" +
3479           "OpFunctionEnd",
3480       2, true),
3481   // Test case 11: fold 1.0 >= 1.0
3482   InstructionFoldingCase<bool>(
3483       Header() + "%main = OpFunction %void None %void_func\n" +
3484           "%main_lab = OpLabel\n" +
3485           "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_1\n" +
3486           "OpReturn\n" +
3487           "OpFunctionEnd",
3488       2, true),
3489   // Test case 12: fold 2.0 < 1.0
3490   InstructionFoldingCase<bool>(
3491       Header() + "%main = OpFunction %void None %void_func\n" +
3492           "%main_lab = OpLabel\n" +
3493           "%2 = OpFUnordLessThan %bool %float_2 %float_1\n" +
3494           "OpReturn\n" +
3495           "OpFunctionEnd",
3496       2, false),
3497   // Test case 13: fold 2.0 > 1.0
3498   InstructionFoldingCase<bool>(
3499       Header() + "%main = OpFunction %void None %void_func\n" +
3500           "%main_lab = OpLabel\n" +
3501           "%2 = OpFUnordGreaterThan %bool %float_2 %float_1\n" +
3502           "OpReturn\n" +
3503           "OpFunctionEnd",
3504       2, true),
3505   // Test case 14: fold 2.0 <= 1.0
3506   InstructionFoldingCase<bool>(
3507       Header() + "%main = OpFunction %void None %void_func\n" +
3508           "%main_lab = OpLabel\n" +
3509           "%2 = OpFUnordLessThanEqual %bool %float_2 %float_1\n" +
3510           "OpReturn\n" +
3511           "OpFunctionEnd",
3512       2, false),
3513   // Test case 15: fold 2.0 >= 1.0
3514   InstructionFoldingCase<bool>(
3515       Header() + "%main = OpFunction %void None %void_func\n" +
3516           "%main_lab = OpLabel\n" +
3517           "%2 = OpFUnordGreaterThanEqual %bool %float_2 %float_1\n" +
3518           "OpReturn\n" +
3519           "OpFunctionEnd",
3520       2, true)
3521 ));
3522 
3523 INSTANTIATE_TEST_SUITE_P(DoubleNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3524                         ::testing::Values(
3525   // Test case 0: fold NaN == 0 (ord)
3526   InstructionFoldingCase<bool>(
3527       HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3528           "%main_lab = OpLabel\n" +
3529           "%2 = OpFOrdEqual %bool %double_nan %double_0\n" +
3530           "OpReturn\n" +
3531           "OpFunctionEnd",
3532       2, false),
3533   // Test case 1: fold NaN == NaN (unord)
3534   InstructionFoldingCase<bool>(
3535       HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3536           "%main_lab = OpLabel\n" +
3537           "%2 = OpFUnordEqual %bool %double_nan %double_0\n" +
3538           "OpReturn\n" +
3539           "OpFunctionEnd",
3540       2, true),
3541   // Test case 2: fold NaN != NaN (ord)
3542   InstructionFoldingCase<bool>(
3543       HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3544           "%main_lab = OpLabel\n" +
3545           "%2 = OpFOrdNotEqual %bool %double_nan %double_0\n" +
3546           "OpReturn\n" +
3547           "OpFunctionEnd",
3548       2, false),
3549   // Test case 3: fold NaN != NaN (unord)
3550   InstructionFoldingCase<bool>(
3551       HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3552           "%main_lab = OpLabel\n" +
3553           "%2 = OpFUnordNotEqual %bool %double_nan %double_0\n" +
3554           "OpReturn\n" +
3555           "OpFunctionEnd",
3556       2, true)
3557 ));
3558 
3559 INSTANTIATE_TEST_SUITE_P(FloatNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3560                         ::testing::Values(
3561   // Test case 0: fold NaN == 0 (ord)
3562   InstructionFoldingCase<bool>(
3563       HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3564           "%main_lab = OpLabel\n" +
3565           "%2 = OpFOrdEqual %bool %float_nan %float_0\n" +
3566           "OpReturn\n" +
3567           "OpFunctionEnd",
3568       2, false),
3569   // Test case 1: fold NaN == NaN (unord)
3570   InstructionFoldingCase<bool>(
3571       HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3572           "%main_lab = OpLabel\n" +
3573           "%2 = OpFUnordEqual %bool %float_nan %float_0\n" +
3574           "OpReturn\n" +
3575           "OpFunctionEnd",
3576       2, true),
3577   // Test case 2: fold NaN != NaN (ord)
3578   InstructionFoldingCase<bool>(
3579       HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3580           "%main_lab = OpLabel\n" +
3581           "%2 = OpFOrdNotEqual %bool %float_nan %float_0\n" +
3582           "OpReturn\n" +
3583           "OpFunctionEnd",
3584       2, false),
3585   // Test case 3: fold NaN != NaN (unord)
3586   InstructionFoldingCase<bool>(
3587       HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3588           "%main_lab = OpLabel\n" +
3589           "%2 = OpFUnordNotEqual %bool %float_nan %float_0\n" +
3590           "OpReturn\n" +
3591           "OpFunctionEnd",
3592       2, true)
3593 ));
3594 // clang-format on
3595 
3596 template <class ResultType>
3597 struct InstructionFoldingCaseWithMap {
InstructionFoldingCaseWithMapspvtools::opt::__anon8bea92fa0111::InstructionFoldingCaseWithMap3598   InstructionFoldingCaseWithMap(const std::string& tb, uint32_t id,
3599                                 ResultType result,
3600                                 std::function<uint32_t(uint32_t)> map)
3601       : test_body(tb), id_to_fold(id), expected_result(result), id_map(map) {}
3602 
3603   std::string test_body;
3604   uint32_t id_to_fold;
3605   ResultType expected_result;
3606   std::function<uint32_t(uint32_t)> id_map;
3607 };
3608 
3609 using IntegerInstructionFoldingTestWithMap =
3610     ::testing::TestWithParam<InstructionFoldingCaseWithMap<uint32_t>>;
3611 
TEST_P(IntegerInstructionFoldingTestWithMap,Case)3612 TEST_P(IntegerInstructionFoldingTestWithMap, Case) {
3613   const auto& tc = GetParam();
3614 
3615   std::unique_ptr<IRContext> context;
3616   Instruction* inst;
3617   std::tie(context, inst) =
3618       GetInstructionToFold(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_5);
3619 
3620   inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
3621                                                                      tc.id_map);
3622   EXPECT_NE(inst, nullptr);
3623 
3624   CheckForExpectedScalarConstant(inst, tc.expected_result,
3625                                  [](const analysis::Constant* c) {
3626                                    return c->AsIntConstant()->GetU32BitValue();
3627                                  });
3628 }
3629 // clang-format off
3630 
3631 INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTestWithMap,
3632   ::testing::Values(
3633       // Test case 0: fold %3 = 0; %3 * n
3634       InstructionFoldingCaseWithMap<uint32_t>(
3635           Header() + "%main = OpFunction %void None %void_func\n" +
3636               "%main_lab = OpLabel\n" +
3637               "%n = OpVariable %_ptr_int Function\n" +
3638               "%load = OpLoad %int %n\n" +
3639               "%3 = OpCopyObject %int %int_0\n"
3640               "%2 = OpIMul %int %3 %load\n" +
3641               "OpReturn\n" +
3642               "OpFunctionEnd",
__anon8bea92fa0d02(uint32_t id) 3643           2, 0, [](uint32_t id) {return (id == 3 ? INT_0_ID : id);})
3644   ));
3645 // clang-format on
3646 
3647 using BooleanInstructionFoldingTestWithMap =
3648     ::testing::TestWithParam<InstructionFoldingCaseWithMap<bool>>;
3649 
TEST_P(BooleanInstructionFoldingTestWithMap,Case)3650 TEST_P(BooleanInstructionFoldingTestWithMap, Case) {
3651   const auto& tc = GetParam();
3652 
3653   std::unique_ptr<IRContext> context;
3654   Instruction* inst;
3655   std::tie(context, inst) =
3656       GetInstructionToFold(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_5);
3657   inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
3658                                                                      tc.id_map);
3659   ASSERT_NE(inst, nullptr);
3660   CheckForExpectedScalarConstant(
3661       inst, tc.expected_result,
3662       [](const analysis::Constant* c) { return c->AsBoolConstant()->value(); });
3663 }
3664 
3665 // clang-format off
3666 INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTestWithMap,
3667   ::testing::Values(
3668       // Test case 0: fold %3 = true; %3 || n
3669       InstructionFoldingCaseWithMap<bool>(
3670           Header() + "%main = OpFunction %void None %void_func\n" +
3671               "%main_lab = OpLabel\n" +
3672               "%n = OpVariable %_ptr_bool Function\n" +
3673               "%load = OpLoad %bool %n\n" +
3674               "%3 = OpCopyObject %bool %true\n" +
3675               "%2 = OpLogicalOr %bool %3 %load\n" +
3676               "OpReturn\n" +
3677               "OpFunctionEnd",
__anon8bea92fa0f02(uint32_t id) 3678           2, true, [](uint32_t id) {return (id == 3 ? TRUE_ID : id);})
3679   ));
3680 // clang-format on
3681 
3682 using GeneralInstructionFoldingTest =
3683     ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
3684 
TEST_P(GeneralInstructionFoldingTest,Case)3685 TEST_P(GeneralInstructionFoldingTest, Case) {
3686   const auto& tc = GetParam();
3687 
3688   std::unique_ptr<IRContext> context;
3689   Instruction* inst;
3690   std::tie(context, inst) =
3691       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
3692 
3693   EXPECT_TRUE((inst == nullptr) == (tc.expected_result == 0));
3694   if (inst != nullptr) {
3695     EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
3696     EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
3697   }
3698 }
3699 
3700 // clang-format off
3701 INSTANTIATE_TEST_SUITE_P(IntegerArithmeticTestCases, GeneralInstructionFoldingTest,
3702                         ::testing::Values(
3703     // Test case 0: Don't fold n * m
3704     InstructionFoldingCase<uint32_t>(
3705         Header() + "%main = OpFunction %void None %void_func\n" +
3706             "%main_lab = OpLabel\n" +
3707             "%n = OpVariable %_ptr_int Function\n" +
3708             "%m = OpVariable %_ptr_int Function\n" +
3709             "%load_n = OpLoad %int %n\n" +
3710             "%load_m = OpLoad %int %m\n" +
3711             "%2 = OpIMul %int %load_n %load_m\n" +
3712             "OpReturn\n" +
3713             "OpFunctionEnd",
3714         2, 0),
3715     // Test case 1: Don't fold n / m (unsigned)
3716     InstructionFoldingCase<uint32_t>(
3717         Header() + "%main = OpFunction %void None %void_func\n" +
3718             "%main_lab = OpLabel\n" +
3719             "%n = OpVariable %_ptr_uint Function\n" +
3720             "%m = OpVariable %_ptr_uint Function\n" +
3721             "%load_n = OpLoad %uint %n\n" +
3722             "%load_m = OpLoad %uint %m\n" +
3723             "%2 = OpUDiv %uint %load_n %load_m\n" +
3724             "OpReturn\n" +
3725             "OpFunctionEnd",
3726         2, 0),
3727     // Test case 2: Don't fold n / m (signed)
3728     InstructionFoldingCase<uint32_t>(
3729         Header() + "%main = OpFunction %void None %void_func\n" +
3730             "%main_lab = OpLabel\n" +
3731             "%n = OpVariable %_ptr_int Function\n" +
3732             "%m = OpVariable %_ptr_int Function\n" +
3733             "%load_n = OpLoad %int %n\n" +
3734             "%load_m = OpLoad %int %m\n" +
3735             "%2 = OpSDiv %int %load_n %load_m\n" +
3736             "OpReturn\n" +
3737             "OpFunctionEnd",
3738         2, 0),
3739     // Test case 3: Don't fold n remainder m
3740     InstructionFoldingCase<uint32_t>(
3741         Header() + "%main = OpFunction %void None %void_func\n" +
3742             "%main_lab = OpLabel\n" +
3743             "%n = OpVariable %_ptr_int Function\n" +
3744             "%m = OpVariable %_ptr_int Function\n" +
3745             "%load_n = OpLoad %int %n\n" +
3746             "%load_m = OpLoad %int %m\n" +
3747             "%2 = OpSRem %int %load_n %load_m\n" +
3748             "OpReturn\n" +
3749             "OpFunctionEnd",
3750         2, 0),
3751     // Test case 4: Don't fold n % m (signed)
3752     InstructionFoldingCase<uint32_t>(
3753         Header() + "%main = OpFunction %void None %void_func\n" +
3754             "%main_lab = OpLabel\n" +
3755             "%n = OpVariable %_ptr_int Function\n" +
3756             "%m = OpVariable %_ptr_int Function\n" +
3757             "%load_n = OpLoad %int %n\n" +
3758             "%load_m = OpLoad %int %m\n" +
3759             "%2 = OpSMod %int %load_n %load_m\n" +
3760             "OpReturn\n" +
3761             "OpFunctionEnd",
3762         2, 0),
3763     // Test case 5: Don't fold n % m (unsigned)
3764     InstructionFoldingCase<uint32_t>(
3765         Header() + "%main = OpFunction %void None %void_func\n" +
3766             "%main_lab = OpLabel\n" +
3767             "%n = OpVariable %_ptr_uint Function\n" +
3768             "%m = OpVariable %_ptr_uint Function\n" +
3769             "%load_n = OpLoad %uint %n\n" +
3770             "%load_m = OpLoad %uint %m\n" +
3771             "%2 = OpUMod %int %load_n %load_m\n" +
3772             "OpReturn\n" +
3773             "OpFunctionEnd",
3774         2, 0),
3775     // Test case 6: Don't fold n << m
3776     InstructionFoldingCase<uint32_t>(
3777         Header() + "%main = OpFunction %void None %void_func\n" +
3778             "%main_lab = OpLabel\n" +
3779             "%n = OpVariable %_ptr_uint Function\n" +
3780             "%m = OpVariable %_ptr_uint Function\n" +
3781             "%load_n = OpLoad %uint %n\n" +
3782             "%load_m = OpLoad %uint %m\n" +
3783             "%2 = OpShiftRightLogical %int %load_n %load_m\n" +
3784             "OpReturn\n" +
3785             "OpFunctionEnd",
3786         2, 0),
3787     // Test case 7: Don't fold n >> m
3788     InstructionFoldingCase<uint32_t>(
3789         Header() + "%main = OpFunction %void None %void_func\n" +
3790             "%main_lab = OpLabel\n" +
3791             "%n = OpVariable %_ptr_uint Function\n" +
3792             "%m = OpVariable %_ptr_uint Function\n" +
3793             "%load_n = OpLoad %uint %n\n" +
3794             "%load_m = OpLoad %uint %m\n" +
3795             "%2 = OpShiftLeftLogical %int %load_n %load_m\n" +
3796             "OpReturn\n" +
3797             "OpFunctionEnd",
3798         2, 0),
3799     // Test case 8: Don't fold n | m
3800     InstructionFoldingCase<uint32_t>(
3801         Header() + "%main = OpFunction %void None %void_func\n" +
3802             "%main_lab = OpLabel\n" +
3803             "%n = OpVariable %_ptr_uint Function\n" +
3804             "%m = OpVariable %_ptr_uint Function\n" +
3805             "%load_n = OpLoad %uint %n\n" +
3806             "%load_m = OpLoad %uint %m\n" +
3807             "%2 = OpBitwiseOr %int %load_n %load_m\n" +
3808             "OpReturn\n" +
3809             "OpFunctionEnd",
3810         2, 0),
3811     // Test case 9: Don't fold n & m
3812     InstructionFoldingCase<uint32_t>(
3813         Header() + "%main = OpFunction %void None %void_func\n" +
3814             "%main_lab = OpLabel\n" +
3815             "%n = OpVariable %_ptr_uint Function\n" +
3816             "%m = OpVariable %_ptr_uint Function\n" +
3817             "%load_n = OpLoad %uint %n\n" +
3818             "%load_m = OpLoad %uint %m\n" +
3819             "%2 = OpBitwiseAnd %int %load_n %load_m\n" +
3820             "OpReturn\n" +
3821             "OpFunctionEnd",
3822         2, 0),
3823     // Test case 10: Don't fold n < m (unsigned)
3824     InstructionFoldingCase<uint32_t>(
3825         Header() + "%main = OpFunction %void None %void_func\n" +
3826             "%main_lab = OpLabel\n" +
3827             "%n = OpVariable %_ptr_uint Function\n" +
3828             "%m = OpVariable %_ptr_uint Function\n" +
3829             "%load_n = OpLoad %uint %n\n" +
3830             "%load_m = OpLoad %uint %m\n" +
3831             "%2 = OpULessThan %bool %load_n %load_m\n" +
3832             "OpReturn\n" +
3833             "OpFunctionEnd",
3834         2, 0),
3835     // Test case 11: Don't fold n > m (unsigned)
3836     InstructionFoldingCase<uint32_t>(
3837         Header() + "%main = OpFunction %void None %void_func\n" +
3838             "%main_lab = OpLabel\n" +
3839             "%n = OpVariable %_ptr_uint Function\n" +
3840             "%m = OpVariable %_ptr_uint Function\n" +
3841             "%load_n = OpLoad %uint %n\n" +
3842             "%load_m = OpLoad %uint %m\n" +
3843             "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
3844             "OpReturn\n" +
3845             "OpFunctionEnd",
3846         2, 0),
3847     // Test case 12: Don't fold n <= m (unsigned)
3848     InstructionFoldingCase<uint32_t>(
3849         Header() + "%main = OpFunction %void None %void_func\n" +
3850             "%main_lab = OpLabel\n" +
3851             "%n = OpVariable %_ptr_uint Function\n" +
3852             "%m = OpVariable %_ptr_uint Function\n" +
3853             "%load_n = OpLoad %uint %n\n" +
3854             "%load_m = OpLoad %uint %m\n" +
3855             "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
3856             "OpReturn\n" +
3857             "OpFunctionEnd",
3858         2, 0),
3859     // Test case 13: Don't fold n >= m (unsigned)
3860     InstructionFoldingCase<uint32_t>(
3861         Header() + "%main = OpFunction %void None %void_func\n" +
3862             "%main_lab = OpLabel\n" +
3863             "%n = OpVariable %_ptr_uint Function\n" +
3864             "%m = OpVariable %_ptr_uint Function\n" +
3865             "%load_n = OpLoad %uint %n\n" +
3866             "%load_m = OpLoad %uint %m\n" +
3867             "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
3868             "OpReturn\n" +
3869             "OpFunctionEnd",
3870         2, 0),
3871     // Test case 14: Don't fold n < m (signed)
3872     InstructionFoldingCase<uint32_t>(
3873         Header() + "%main = OpFunction %void None %void_func\n" +
3874             "%main_lab = OpLabel\n" +
3875             "%n = OpVariable %_ptr_int Function\n" +
3876             "%m = OpVariable %_ptr_int Function\n" +
3877             "%load_n = OpLoad %int %n\n" +
3878             "%load_m = OpLoad %int %m\n" +
3879             "%2 = OpULessThan %bool %load_n %load_m\n" +
3880             "OpReturn\n" +
3881             "OpFunctionEnd",
3882         2, 0),
3883     // Test case 15: Don't fold n > m (signed)
3884     InstructionFoldingCase<uint32_t>(
3885         Header() + "%main = OpFunction %void None %void_func\n" +
3886             "%main_lab = OpLabel\n" +
3887             "%n = OpVariable %_ptr_int Function\n" +
3888             "%m = OpVariable %_ptr_int Function\n" +
3889             "%load_n = OpLoad %int %n\n" +
3890             "%load_m = OpLoad %int %m\n" +
3891             "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
3892             "OpReturn\n" +
3893             "OpFunctionEnd",
3894         2, 0),
3895     // Test case 16: Don't fold n <= m (signed)
3896     InstructionFoldingCase<uint32_t>(
3897         Header() + "%main = OpFunction %void None %void_func\n" +
3898             "%main_lab = OpLabel\n" +
3899             "%n = OpVariable %_ptr_int Function\n" +
3900             "%m = OpVariable %_ptr_int Function\n" +
3901             "%load_n = OpLoad %int %n\n" +
3902             "%load_m = OpLoad %int %m\n" +
3903             "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
3904             "OpReturn\n" +
3905             "OpFunctionEnd",
3906         2, 0),
3907     // Test case 17: Don't fold n >= m (signed)
3908     InstructionFoldingCase<uint32_t>(
3909         Header() + "%main = OpFunction %void None %void_func\n" +
3910             "%main_lab = OpLabel\n" +
3911             "%n = OpVariable %_ptr_int Function\n" +
3912             "%m = OpVariable %_ptr_int Function\n" +
3913             "%load_n = OpLoad %int %n\n" +
3914             "%load_m = OpLoad %int %m\n" +
3915             "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
3916             "OpReturn\n" +
3917             "OpFunctionEnd",
3918         2, 0),
3919     // Test case 18: Don't fold n || m
3920     InstructionFoldingCase<uint32_t>(
3921         Header() + "%main = OpFunction %void None %void_func\n" +
3922             "%main_lab = OpLabel\n" +
3923             "%n = OpVariable %_ptr_bool Function\n" +
3924             "%m = OpVariable %_ptr_bool Function\n" +
3925             "%load_n = OpLoad %bool %n\n" +
3926             "%load_m = OpLoad %bool %m\n" +
3927             "%2 = OpLogicalOr %bool %load_n %load_m\n" +
3928             "OpReturn\n" +
3929             "OpFunctionEnd",
3930         2, 0),
3931     // Test case 19: Don't fold n && m
3932     InstructionFoldingCase<uint32_t>(
3933         Header() + "%main = OpFunction %void None %void_func\n" +
3934             "%main_lab = OpLabel\n" +
3935             "%n = OpVariable %_ptr_bool Function\n" +
3936             "%m = OpVariable %_ptr_bool Function\n" +
3937             "%load_n = OpLoad %bool %n\n" +
3938             "%load_m = OpLoad %bool %m\n" +
3939             "%2 = OpLogicalAnd %bool %load_n %load_m\n" +
3940             "OpReturn\n" +
3941             "OpFunctionEnd",
3942         2, 0),
3943     // Test case 20: Don't fold n * 3
3944     InstructionFoldingCase<uint32_t>(
3945         Header() + "%main = OpFunction %void None %void_func\n" +
3946             "%main_lab = OpLabel\n" +
3947             "%n = OpVariable %_ptr_int Function\n" +
3948             "%load_n = OpLoad %int %n\n" +
3949             "%2 = OpIMul %int %load_n %int_3\n" +
3950             "OpReturn\n" +
3951             "OpFunctionEnd",
3952         2, 0),
3953     // Test case 21: Don't fold n / 3 (unsigned)
3954     InstructionFoldingCase<uint32_t>(
3955         Header() + "%main = OpFunction %void None %void_func\n" +
3956             "%main_lab = OpLabel\n" +
3957             "%n = OpVariable %_ptr_uint Function\n" +
3958             "%load_n = OpLoad %uint %n\n" +
3959             "%2 = OpUDiv %uint %load_n %uint_3\n" +
3960             "OpReturn\n" +
3961             "OpFunctionEnd",
3962         2, 0),
3963     // Test case 22: Don't fold n / 3 (signed)
3964     InstructionFoldingCase<uint32_t>(
3965         Header() + "%main = OpFunction %void None %void_func\n" +
3966             "%main_lab = OpLabel\n" +
3967             "%n = OpVariable %_ptr_int Function\n" +
3968             "%load_n = OpLoad %int %n\n" +
3969             "%2 = OpSDiv %int %load_n %int_3\n" +
3970             "OpReturn\n" +
3971             "OpFunctionEnd",
3972         2, 0),
3973     // Test case 23: Don't fold n remainder 3
3974     InstructionFoldingCase<uint32_t>(
3975         Header() + "%main = OpFunction %void None %void_func\n" +
3976             "%main_lab = OpLabel\n" +
3977             "%n = OpVariable %_ptr_int Function\n" +
3978             "%load_n = OpLoad %int %n\n" +
3979             "%2 = OpSRem %int %load_n %int_3\n" +
3980             "OpReturn\n" +
3981             "OpFunctionEnd",
3982         2, 0),
3983     // Test case 24: Don't fold n % 3 (signed)
3984     InstructionFoldingCase<uint32_t>(
3985         Header() + "%main = OpFunction %void None %void_func\n" +
3986             "%main_lab = OpLabel\n" +
3987             "%n = OpVariable %_ptr_int Function\n" +
3988             "%load_n = OpLoad %int %n\n" +
3989             "%2 = OpSMod %int %load_n %int_3\n" +
3990             "OpReturn\n" +
3991             "OpFunctionEnd",
3992         2, 0),
3993     // Test case 25: Don't fold n % 3 (unsigned)
3994     InstructionFoldingCase<uint32_t>(
3995         Header() + "%main = OpFunction %void None %void_func\n" +
3996             "%main_lab = OpLabel\n" +
3997             "%n = OpVariable %_ptr_uint Function\n" +
3998             "%load_n = OpLoad %uint %n\n" +
3999             "%2 = OpUMod %int %load_n %int_3\n" +
4000             "OpReturn\n" +
4001             "OpFunctionEnd",
4002         2, 0),
4003     // Test case 26: Don't fold n << 3
4004     InstructionFoldingCase<uint32_t>(
4005         Header() + "%main = OpFunction %void None %void_func\n" +
4006             "%main_lab = OpLabel\n" +
4007             "%n = OpVariable %_ptr_uint Function\n" +
4008             "%load_n = OpLoad %uint %n\n" +
4009             "%2 = OpShiftRightLogical %int %load_n %int_3\n" +
4010             "OpReturn\n" +
4011             "OpFunctionEnd",
4012         2, 0),
4013     // Test case 27: Don't fold n >> 3
4014     InstructionFoldingCase<uint32_t>(
4015         Header() + "%main = OpFunction %void None %void_func\n" +
4016             "%main_lab = OpLabel\n" +
4017             "%n = OpVariable %_ptr_uint Function\n" +
4018             "%load_n = OpLoad %uint %n\n" +
4019             "%2 = OpShiftLeftLogical %int %load_n %int_3\n" +
4020             "OpReturn\n" +
4021             "OpFunctionEnd",
4022         2, 0),
4023     // Test case 28: Don't fold n | 3
4024     InstructionFoldingCase<uint32_t>(
4025         Header() + "%main = OpFunction %void None %void_func\n" +
4026             "%main_lab = OpLabel\n" +
4027             "%n = OpVariable %_ptr_uint Function\n" +
4028             "%load_n = OpLoad %uint %n\n" +
4029             "%2 = OpBitwiseOr %int %load_n %int_3\n" +
4030             "OpReturn\n" +
4031             "OpFunctionEnd",
4032         2, 0),
4033     // Test case 29: Don't fold n & 3
4034     InstructionFoldingCase<uint32_t>(
4035         Header() + "%main = OpFunction %void None %void_func\n" +
4036             "%main_lab = OpLabel\n" +
4037             "%n = OpVariable %_ptr_uint Function\n" +
4038             "%load_n = OpLoad %uint %n\n" +
4039             "%2 = OpBitwiseAnd %uint %load_n %uint_3\n" +
4040             "OpReturn\n" +
4041             "OpFunctionEnd",
4042         2, 0),
4043     // Test case 30: Don't fold n < 3 (unsigned)
4044     InstructionFoldingCase<uint32_t>(
4045         Header() + "%main = OpFunction %void None %void_func\n" +
4046             "%main_lab = OpLabel\n" +
4047             "%n = OpVariable %_ptr_uint Function\n" +
4048             "%load_n = OpLoad %uint %n\n" +
4049             "%2 = OpULessThan %bool %load_n %uint_3\n" +
4050             "OpReturn\n" +
4051             "OpFunctionEnd",
4052         2, 0),
4053     // Test case 31: Don't fold n > 3 (unsigned)
4054     InstructionFoldingCase<uint32_t>(
4055         Header() + "%main = OpFunction %void None %void_func\n" +
4056             "%main_lab = OpLabel\n" +
4057             "%n = OpVariable %_ptr_uint Function\n" +
4058             "%load_n = OpLoad %uint %n\n" +
4059             "%2 = OpUGreaterThan %bool %load_n %uint_3\n" +
4060             "OpReturn\n" +
4061             "OpFunctionEnd",
4062         2, 0),
4063     // Test case 32: Don't fold n <= 3 (unsigned)
4064     InstructionFoldingCase<uint32_t>(
4065         Header() + "%main = OpFunction %void None %void_func\n" +
4066             "%main_lab = OpLabel\n" +
4067             "%n = OpVariable %_ptr_uint Function\n" +
4068             "%load_n = OpLoad %uint %n\n" +
4069             "%2 = OpULessThanEqual %bool %load_n %uint_3\n" +
4070             "OpReturn\n" +
4071             "OpFunctionEnd",
4072         2, 0),
4073     // Test case 33: Don't fold n >= 3 (unsigned)
4074     InstructionFoldingCase<uint32_t>(
4075         Header() + "%main = OpFunction %void None %void_func\n" +
4076             "%main_lab = OpLabel\n" +
4077             "%n = OpVariable %_ptr_uint Function\n" +
4078             "%load_n = OpLoad %uint %n\n" +
4079             "%2 = OpUGreaterThanEqual %bool %load_n %uint_3\n" +
4080             "OpReturn\n" +
4081             "OpFunctionEnd",
4082         2, 0),
4083     // Test case 34: Don't fold n < 3 (signed)
4084     InstructionFoldingCase<uint32_t>(
4085         Header() + "%main = OpFunction %void None %void_func\n" +
4086             "%main_lab = OpLabel\n" +
4087             "%n = OpVariable %_ptr_int Function\n" +
4088             "%load_n = OpLoad %int %n\n" +
4089             "%2 = OpULessThan %bool %load_n %int_3\n" +
4090             "OpReturn\n" +
4091             "OpFunctionEnd",
4092         2, 0),
4093     // Test case 35: Don't fold n > 3 (signed)
4094     InstructionFoldingCase<uint32_t>(
4095         Header() + "%main = OpFunction %void None %void_func\n" +
4096             "%main_lab = OpLabel\n" +
4097             "%n = OpVariable %_ptr_int Function\n" +
4098             "%load_n = OpLoad %int %n\n" +
4099             "%2 = OpUGreaterThan %bool %load_n %int_3\n" +
4100             "OpReturn\n" +
4101             "OpFunctionEnd",
4102         2, 0),
4103     // Test case 36: Don't fold n <= 3 (signed)
4104     InstructionFoldingCase<uint32_t>(
4105         Header() + "%main = OpFunction %void None %void_func\n" +
4106             "%main_lab = OpLabel\n" +
4107             "%n = OpVariable %_ptr_int Function\n" +
4108             "%load_n = OpLoad %int %n\n" +
4109             "%2 = OpULessThanEqual %bool %load_n %int_3\n" +
4110             "OpReturn\n" +
4111             "OpFunctionEnd",
4112         2, 0),
4113     // Test case 37: Don't fold n >= 3 (signed)
4114     InstructionFoldingCase<uint32_t>(
4115         Header() + "%main = OpFunction %void None %void_func\n" +
4116             "%main_lab = OpLabel\n" +
4117             "%n = OpVariable %_ptr_int Function\n" +
4118             "%load_n = OpLoad %int %n\n" +
4119             "%2 = OpUGreaterThanEqual %bool %load_n %int_3\n" +
4120             "OpReturn\n" +
4121             "OpFunctionEnd",
4122         2, 0),
4123     // Test case 38: fold 1*n
4124     InstructionFoldingCase<uint32_t>(
4125         Header() + "%main = OpFunction %void None %void_func\n" +
4126             "%main_lab = OpLabel\n" +
4127             "%n = OpVariable %_ptr_int Function\n" +
4128             "%3 = OpLoad %int %n\n" +
4129             "%2 = OpIMul %int %int_1 %3\n" +
4130             "OpReturn\n" +
4131             "OpFunctionEnd",
4132         2, 3),
4133     // Test case 39: fold n*1
4134     InstructionFoldingCase<uint32_t>(
4135         Header() + "%main = OpFunction %void None %void_func\n" +
4136             "%main_lab = OpLabel\n" +
4137             "%n = OpVariable %_ptr_int Function\n" +
4138             "%3 = OpLoad %int %n\n" +
4139             "%2 = OpIMul %int %3 %int_1\n" +
4140             "OpReturn\n" +
4141             "OpFunctionEnd",
4142         2, 3),
4143     // Test case 40: Don't fold comparisons of 64-bit types
4144     // (https://github.com/KhronosGroup/SPIRV-Tools/issues/3343).
4145     InstructionFoldingCase<uint32_t>(
4146         Header() + "%main = OpFunction %void None %void_func\n" +
4147           "%main_lab = OpLabel\n" +
4148           "%2 = OpSLessThan %bool %long_0 %long_2\n" +
4149           "OpReturn\n" +
4150           "OpFunctionEnd",
4151         2, 0)
4152 ));
4153 
4154 INSTANTIATE_TEST_SUITE_P(CompositeExtractFoldingTest, GeneralInstructionFoldingTest,
4155 ::testing::Values(
4156     // Test case 0: fold Insert feeding extract
4157     InstructionFoldingCase<uint32_t>(
4158         Header() + "%main = OpFunction %void None %void_func\n" +
4159             "%main_lab = OpLabel\n" +
4160             "%n = OpVariable %_ptr_int Function\n" +
4161             "%2 = OpLoad %int %n\n" +
4162             "%3 = OpCompositeInsert %v4int %2 %v4int_0_0_0_0 0\n" +
4163             "%4 = OpCompositeInsert %v4int %int_1 %3 1\n" +
4164             "%5 = OpCompositeInsert %v4int %int_1 %4 2\n" +
4165             "%6 = OpCompositeInsert %v4int %int_1 %5 3\n" +
4166             "%7 = OpCompositeExtract %int %6 0\n" +
4167             "OpReturn\n" +
4168             "OpFunctionEnd",
4169         7, 2),
4170     // Test case 1: fold Composite construct feeding extract (position 0)
4171     InstructionFoldingCase<uint32_t>(
4172         Header() + "%main = OpFunction %void None %void_func\n" +
4173             "%main_lab = OpLabel\n" +
4174             "%n = OpVariable %_ptr_int Function\n" +
4175             "%2 = OpLoad %int %n\n" +
4176             "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %int_0\n" +
4177             "%4 = OpCompositeExtract %int %3 0\n" +
4178             "OpReturn\n" +
4179             "OpFunctionEnd",
4180         4, 2),
4181     // Test case 2: fold Composite construct feeding extract (position 3)
4182     InstructionFoldingCase<uint32_t>(
4183         Header() + "%main = OpFunction %void None %void_func\n" +
4184             "%main_lab = OpLabel\n" +
4185             "%n = OpVariable %_ptr_int Function\n" +
4186             "%2 = OpLoad %int %n\n" +
4187             "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %100\n" +
4188             "%4 = OpCompositeExtract %int %3 3\n" +
4189             "OpReturn\n" +
4190             "OpFunctionEnd",
4191         4, INT_0_ID),
4192     // Test case 3: fold Composite construct with vectors feeding extract (scalar element)
4193     InstructionFoldingCase<uint32_t>(
4194         Header() + "%main = OpFunction %void None %void_func\n" +
4195             "%main_lab = OpLabel\n" +
4196             "%n = OpVariable %_ptr_int Function\n" +
4197             "%2 = OpLoad %int %n\n" +
4198             "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
4199             "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
4200             "%5 = OpCompositeExtract %int %4 3\n" +
4201             "OpReturn\n" +
4202             "OpFunctionEnd",
4203         5, INT_0_ID),
4204     // Test case 4: fold Composite construct with vectors feeding extract (start of vector element)
4205     InstructionFoldingCase<uint32_t>(
4206         Header() + "%main = OpFunction %void None %void_func\n" +
4207             "%main_lab = OpLabel\n" +
4208             "%n = OpVariable %_ptr_int Function\n" +
4209             "%2 = OpLoad %int %n\n" +
4210             "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
4211             "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
4212             "%5 = OpCompositeExtract %int %4 0\n" +
4213             "OpReturn\n" +
4214             "OpFunctionEnd",
4215         5, 2),
4216     // Test case 5: fold Composite construct with vectors feeding extract (middle of vector element)
4217     InstructionFoldingCase<uint32_t>(
4218         Header() + "%main = OpFunction %void None %void_func\n" +
4219             "%main_lab = OpLabel\n" +
4220             "%n = OpVariable %_ptr_int Function\n" +
4221             "%2 = OpLoad %int %n\n" +
4222             "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
4223             "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
4224             "%5 = OpCompositeExtract %int %4 1\n" +
4225             "OpReturn\n" +
4226             "OpFunctionEnd",
4227         5, 2),
4228     // Test case 6: fold Composite construct with multiple indices.
4229     InstructionFoldingCase<uint32_t>(
4230         Header() + "%main = OpFunction %void None %void_func\n" +
4231             "%main_lab = OpLabel\n" +
4232             "%n = OpVariable %_ptr_int Function\n" +
4233             "%2 = OpLoad %int %n\n" +
4234             "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
4235             "%4 = OpCompositeConstruct %struct_v2int_int_int %3 %int_0 %100\n" +
4236             "%5 = OpCompositeExtract %int %4 0 1\n" +
4237             "OpReturn\n" +
4238             "OpFunctionEnd",
4239         5, 2),
4240     // Test case 7: fold constant extract.
4241     InstructionFoldingCase<uint32_t>(
4242         Header() + "%main = OpFunction %void None %void_func\n" +
4243             "%main_lab = OpLabel\n" +
4244             "%2 = OpCompositeExtract %int %102 1\n" +
4245             "OpReturn\n" +
4246             "OpFunctionEnd",
4247         2, INT_7_ID),
4248     // Test case 8: constant struct has OpUndef
4249     InstructionFoldingCase<uint32_t>(
4250         Header() + "%main = OpFunction %void None %void_func\n" +
4251             "%main_lab = OpLabel\n" +
4252             "%2 = OpCompositeExtract %int %struct_undef_0_0 0 1\n" +
4253             "OpReturn\n" +
4254             "OpFunctionEnd",
4255         2, 0),
4256     // Test case 9: Extracting a member of element inserted via Insert
4257     InstructionFoldingCase<uint32_t>(
4258         Header() + "%main = OpFunction %void None %void_func\n" +
4259             "%main_lab = OpLabel\n" +
4260             "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
4261             "%2 = OpLoad %struct_v2int_int_int %n\n" +
4262             "%3 = OpCompositeInsert %struct_v2int_int_int %102 %2 0\n" +
4263             "%4 = OpCompositeExtract %int %3 0 1\n" +
4264             "OpReturn\n" +
4265             "OpFunctionEnd",
4266         4, 103),
4267     // Test case 10: Extracting a element that is partially changed by Insert. (Don't fold)
4268     InstructionFoldingCase<uint32_t>(
4269         Header() + "%main = OpFunction %void None %void_func\n" +
4270             "%main_lab = OpLabel\n" +
4271             "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
4272             "%2 = OpLoad %struct_v2int_int_int %n\n" +
4273             "%3 = OpCompositeInsert %struct_v2int_int_int %int_0 %2 0 1\n" +
4274             "%4 = OpCompositeExtract %v2int %3 0\n" +
4275             "OpReturn\n" +
4276             "OpFunctionEnd",
4277         4, 0),
4278     // Test case 11: Extracting from result of vector shuffle (first input)
4279     InstructionFoldingCase<uint32_t>(
4280         Header() + "%main = OpFunction %void None %void_func\n" +
4281             "%main_lab = OpLabel\n" +
4282             "%n = OpVariable %_ptr_v2int Function\n" +
4283             "%2 = OpLoad %v2int %n\n" +
4284             "%3 = OpVectorShuffle %v2int %102 %2 3 0\n" +
4285             "%4 = OpCompositeExtract %int %3 1\n" +
4286             "OpReturn\n" +
4287             "OpFunctionEnd",
4288         4, INT_7_ID),
4289     // Test case 12: Extracting from result of vector shuffle (second input)
4290     InstructionFoldingCase<uint32_t>(
4291         Header() + "%main = OpFunction %void None %void_func\n" +
4292             "%main_lab = OpLabel\n" +
4293             "%n = OpVariable %_ptr_v2int Function\n" +
4294             "%2 = OpLoad %v2int %n\n" +
4295             "%3 = OpVectorShuffle %v2int %2 %102 2 0\n" +
4296             "%4 = OpCompositeExtract %int %3 0\n" +
4297             "OpReturn\n" +
4298             "OpFunctionEnd",
4299         4, INT_7_ID),
4300     // Test case 13: https://github.com/KhronosGroup/SPIRV-Tools/issues/2608
4301     // Out of bounds access.  Do not fold.
4302     InstructionFoldingCase<uint32_t>(
4303         Header() + "%main = OpFunction %void None %void_func\n" +
4304             "%main_lab = OpLabel\n" +
4305             "%2 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n" +
4306             "%3 = OpCompositeExtract %float %2 4\n" +
4307             "OpReturn\n" +
4308             "OpFunctionEnd",
4309         3, 0),
4310     // Test case 14: https://github.com/KhronosGroup/SPIRV-Tools/issues/3631
4311     // Extract the component right after the vector constituent.
4312     InstructionFoldingCase<uint32_t>(
4313         Header() + "%main = OpFunction %void None %void_func\n" +
4314             "%main_lab = OpLabel\n" +
4315             "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
4316             "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
4317             "%4 = OpCompositeExtract %int %3 2\n" +
4318             "OpReturn\n" +
4319             "OpFunctionEnd",
4320         4, INT_0_ID),
4321     // Test case 15:
4322     // Don't fold extract fed by construct with vector result if the index is
4323     // past the last element.
4324     InstructionFoldingCase<uint32_t>(
4325         Header() + "%main = OpFunction %void None %void_func\n" +
4326             "%main_lab = OpLabel\n" +
4327             "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
4328             "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
4329             "%4 = OpCompositeExtract %int %3 4\n" +
4330             "OpReturn\n" +
4331             "OpFunctionEnd",
4332         4, 0)
4333 ));
4334 
4335 INSTANTIATE_TEST_SUITE_P(CompositeConstructFoldingTest, GeneralInstructionFoldingTest,
4336 ::testing::Values(
4337     // Test case 0: fold Extracts feeding construct
4338     InstructionFoldingCase<uint32_t>(
4339         Header() + "%main = OpFunction %void None %void_func\n" +
4340             "%main_lab = OpLabel\n" +
4341             "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
4342             "%3 = OpCompositeExtract %int %2 0\n" +
4343             "%4 = OpCompositeExtract %int %2 1\n" +
4344             "%5 = OpCompositeExtract %int %2 2\n" +
4345             "%6 = OpCompositeExtract %int %2 3\n" +
4346             "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
4347             "OpReturn\n" +
4348             "OpFunctionEnd",
4349         7, 2),
4350     // Test case 1: Don't fold Extracts feeding construct (Different source)
4351     InstructionFoldingCase<uint32_t>(
4352         Header() + "%main = OpFunction %void None %void_func\n" +
4353             "%main_lab = OpLabel\n" +
4354             "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
4355             "%3 = OpCompositeExtract %int %2 0\n" +
4356             "%4 = OpCompositeExtract %int %2 1\n" +
4357             "%5 = OpCompositeExtract %int %2 2\n" +
4358             "%6 = OpCompositeExtract %int %v4int_0_0_0_0 3\n" +
4359             "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
4360             "OpReturn\n" +
4361             "OpFunctionEnd",
4362         7, 0),
4363     // Test case 2: Don't fold Extracts feeding construct (bad indices)
4364     InstructionFoldingCase<uint32_t>(
4365         Header() + "%main = OpFunction %void None %void_func\n" +
4366             "%main_lab = OpLabel\n" +
4367             "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
4368             "%3 = OpCompositeExtract %int %2 0\n" +
4369             "%4 = OpCompositeExtract %int %2 0\n" +
4370             "%5 = OpCompositeExtract %int %2 2\n" +
4371             "%6 = OpCompositeExtract %int %2 3\n" +
4372             "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
4373             "OpReturn\n" +
4374             "OpFunctionEnd",
4375         7, 0),
4376     // Test case 3: Don't fold Extracts feeding construct (different type)
4377     InstructionFoldingCase<uint32_t>(
4378         Header() + "%main = OpFunction %void None %void_func\n" +
4379             "%main_lab = OpLabel\n" +
4380             "%2 = OpCopyObject %struct_v2int_int_int %struct_v2int_int_int_null\n" +
4381             "%3 = OpCompositeExtract %v2int %2 0\n" +
4382             "%4 = OpCompositeExtract %int %2 1\n" +
4383             "%5 = OpCompositeExtract %int %2 2\n" +
4384             "%7 = OpCompositeConstruct %v4int %3 %4 %5\n" +
4385             "OpReturn\n" +
4386             "OpFunctionEnd",
4387         7, 0),
4388     // Test case 4: Fold construct with constants to constant.
4389     InstructionFoldingCase<uint32_t>(
4390         Header() + "%main = OpFunction %void None %void_func\n" +
4391             "%main_lab = OpLabel\n" +
4392             "%2 = OpCompositeConstruct %v2int %103 %103\n" +
4393             "OpReturn\n" +
4394             "OpFunctionEnd",
4395         2, VEC2_0_ID),
4396     // Test case 5: Don't segfault when trying to fold an OpCompositeConstruct
4397     // for an empty struct, and we reached the id limit.
4398     InstructionFoldingCase<uint32_t>(
4399         Header() + "%empty_struct = OpTypeStruct\n" +
4400             "%main = OpFunction %void None %void_func\n" +
4401             "%main_lab = OpLabel\n" +
4402             "%4194303 = OpCompositeConstruct %empty_struct\n" +
4403             "OpReturn\n" +
4404             "OpFunctionEnd",
4405         4194303, 0)
4406 ));
4407 
4408 INSTANTIATE_TEST_SUITE_P(PhiFoldingTest, GeneralInstructionFoldingTest,
4409 ::testing::Values(
4410   // Test case 0: Fold phi with the same values for all edges.
4411   InstructionFoldingCase<uint32_t>(
4412       Header() + "%main = OpFunction %void None %void_func\n" +
4413           "%main_lab = OpLabel\n" +
4414           "            OpBranchConditional %true %l1 %l2\n" +
4415           "%l1 = OpLabel\n" +
4416           "      OpBranch %merge_lab\n" +
4417           "%l2 = OpLabel\n" +
4418           "      OpBranch %merge_lab\n" +
4419           "%merge_lab = OpLabel\n" +
4420           "%2 = OpPhi %int %100 %l1 %100 %l2\n" +
4421           "OpReturn\n" +
4422           "OpFunctionEnd",
4423       2, INT_0_ID),
4424   // Test case 1: Fold phi in pass through loop.
4425   InstructionFoldingCase<uint32_t>(
4426       Header() + "%main = OpFunction %void None %void_func\n" +
4427           "%main_lab = OpLabel\n" +
4428           "            OpBranch %l1\n" +
4429           "%l1 = OpLabel\n" +
4430           "%2 = OpPhi %int %100 %main_lab %2 %l1\n" +
4431           "      OpBranchConditional %true %l1 %merge_lab\n" +
4432           "%merge_lab = OpLabel\n" +
4433           "OpReturn\n" +
4434           "OpFunctionEnd",
4435       2, INT_0_ID),
4436   // Test case 2: Don't Fold phi because of different values.
4437   InstructionFoldingCase<uint32_t>(
4438       Header() + "%main = OpFunction %void None %void_func\n" +
4439           "%main_lab = OpLabel\n" +
4440           "            OpBranch %l1\n" +
4441           "%l1 = OpLabel\n" +
4442           "%2 = OpPhi %int %int_0 %main_lab %int_3 %l1\n" +
4443           "      OpBranchConditional %true %l1 %merge_lab\n" +
4444           "%merge_lab = OpLabel\n" +
4445           "OpReturn\n" +
4446           "OpFunctionEnd",
4447       2, 0)
4448 ));
4449 
4450 INSTANTIATE_TEST_SUITE_P(FloatRedundantFoldingTest, GeneralInstructionFoldingTest,
4451                         ::testing::Values(
4452     // Test case 0: Don't fold n + 1.0
4453     InstructionFoldingCase<uint32_t>(
4454         Header() + "%main = OpFunction %void None %void_func\n" +
4455             "%main_lab = OpLabel\n" +
4456             "%n = OpVariable %_ptr_float Function\n" +
4457             "%3 = OpLoad %float %n\n" +
4458             "%2 = OpFAdd %float %3 %float_2\n" +
4459             "OpReturn\n" +
4460             "OpFunctionEnd",
4461         2, 0),
4462     // Test case 1: Don't fold n - 1.0
4463     InstructionFoldingCase<uint32_t>(
4464         Header() + "%main = OpFunction %void None %void_func\n" +
4465             "%main_lab = OpLabel\n" +
4466             "%n = OpVariable %_ptr_float Function\n" +
4467             "%3 = OpLoad %float %n\n" +
4468             "%2 = OpFSub %float %3 %float_2\n" +
4469             "OpReturn\n" +
4470             "OpFunctionEnd",
4471         2, 0),
4472     // Test case 2: Don't fold n * 2.0
4473     InstructionFoldingCase<uint32_t>(
4474         Header() + "%main = OpFunction %void None %void_func\n" +
4475             "%main_lab = OpLabel\n" +
4476             "%n = OpVariable %_ptr_float Function\n" +
4477             "%3 = OpLoad %float %n\n" +
4478             "%2 = OpFMul %float %3 %float_2\n" +
4479             "OpReturn\n" +
4480             "OpFunctionEnd",
4481         2, 0),
4482     // Test case 3: Fold n + 0.0
4483     InstructionFoldingCase<uint32_t>(
4484         Header() + "%main = OpFunction %void None %void_func\n" +
4485             "%main_lab = OpLabel\n" +
4486             "%n = OpVariable %_ptr_float Function\n" +
4487             "%3 = OpLoad %float %n\n" +
4488             "%2 = OpFAdd %float %3 %float_0\n" +
4489             "OpReturn\n" +
4490             "OpFunctionEnd",
4491         2, 3),
4492     // Test case 4: Fold 0.0 + n
4493     InstructionFoldingCase<uint32_t>(
4494         Header() + "%main = OpFunction %void None %void_func\n" +
4495             "%main_lab = OpLabel\n" +
4496             "%n = OpVariable %_ptr_float Function\n" +
4497             "%3 = OpLoad %float %n\n" +
4498             "%2 = OpFAdd %float %float_0 %3\n" +
4499             "OpReturn\n" +
4500             "OpFunctionEnd",
4501         2, 3),
4502     // Test case 5: Fold n - 0.0
4503     InstructionFoldingCase<uint32_t>(
4504         Header() + "%main = OpFunction %void None %void_func\n" +
4505             "%main_lab = OpLabel\n" +
4506             "%n = OpVariable %_ptr_float Function\n" +
4507             "%3 = OpLoad %float %n\n" +
4508             "%2 = OpFSub %float %3 %float_0\n" +
4509             "OpReturn\n" +
4510             "OpFunctionEnd",
4511         2, 3),
4512     // Test case 6: Fold n * 1.0
4513     InstructionFoldingCase<uint32_t>(
4514         Header() + "%main = OpFunction %void None %void_func\n" +
4515             "%main_lab = OpLabel\n" +
4516             "%n = OpVariable %_ptr_float Function\n" +
4517             "%3 = OpLoad %float %n\n" +
4518             "%2 = OpFMul %float %3 %float_1\n" +
4519             "OpReturn\n" +
4520             "OpFunctionEnd",
4521         2, 3),
4522     // Test case 7: Fold 1.0 * n
4523     InstructionFoldingCase<uint32_t>(
4524         Header() + "%main = OpFunction %void None %void_func\n" +
4525             "%main_lab = OpLabel\n" +
4526             "%n = OpVariable %_ptr_float Function\n" +
4527             "%3 = OpLoad %float %n\n" +
4528             "%2 = OpFMul %float %float_1 %3\n" +
4529             "OpReturn\n" +
4530             "OpFunctionEnd",
4531         2, 3),
4532     // Test case 8: Fold n / 1.0
4533     InstructionFoldingCase<uint32_t>(
4534         Header() + "%main = OpFunction %void None %void_func\n" +
4535             "%main_lab = OpLabel\n" +
4536             "%n = OpVariable %_ptr_float Function\n" +
4537             "%3 = OpLoad %float %n\n" +
4538             "%2 = OpFDiv %float %3 %float_1\n" +
4539             "OpReturn\n" +
4540             "OpFunctionEnd",
4541         2, 3),
4542     // Test case 9: Fold n * 0.0
4543     InstructionFoldingCase<uint32_t>(
4544         Header() + "%main = OpFunction %void None %void_func\n" +
4545             "%main_lab = OpLabel\n" +
4546             "%n = OpVariable %_ptr_float Function\n" +
4547             "%3 = OpLoad %float %n\n" +
4548             "%2 = OpFMul %float %3 %104\n" +
4549             "OpReturn\n" +
4550             "OpFunctionEnd",
4551         2, FLOAT_0_ID),
4552     // Test case 10: Fold 0.0 * n
4553     InstructionFoldingCase<uint32_t>(
4554         Header() + "%main = OpFunction %void None %void_func\n" +
4555             "%main_lab = OpLabel\n" +
4556             "%n = OpVariable %_ptr_float Function\n" +
4557             "%3 = OpLoad %float %n\n" +
4558             "%2 = OpFMul %float %104 %3\n" +
4559             "OpReturn\n" +
4560             "OpFunctionEnd",
4561         2, FLOAT_0_ID),
4562     // Test case 11: Fold 0.0 / n
4563     InstructionFoldingCase<uint32_t>(
4564         Header() + "%main = OpFunction %void None %void_func\n" +
4565             "%main_lab = OpLabel\n" +
4566             "%n = OpVariable %_ptr_float Function\n" +
4567             "%3 = OpLoad %float %n\n" +
4568             "%2 = OpFDiv %float %104 %3\n" +
4569             "OpReturn\n" +
4570             "OpFunctionEnd",
4571         2, FLOAT_0_ID),
4572     // Test case 12: Don't fold mix(a, b, 2.0)
4573     InstructionFoldingCase<uint32_t>(
4574         Header() + "%main = OpFunction %void None %void_func\n" +
4575             "%main_lab = OpLabel\n" +
4576             "%a = OpVariable %_ptr_float Function\n" +
4577             "%b = OpVariable %_ptr_float Function\n" +
4578             "%3 = OpLoad %float %a\n" +
4579             "%4 = OpLoad %float %b\n" +
4580             "%2 = OpExtInst %float %1 FMix %3 %4 %float_2\n" +
4581             "OpReturn\n" +
4582             "OpFunctionEnd",
4583         2, 0),
4584     // Test case 13: Fold mix(a, b, 0.0)
4585     InstructionFoldingCase<uint32_t>(
4586         Header() + "%main = OpFunction %void None %void_func\n" +
4587             "%main_lab = OpLabel\n" +
4588             "%a = OpVariable %_ptr_float Function\n" +
4589             "%b = OpVariable %_ptr_float Function\n" +
4590             "%3 = OpLoad %float %a\n" +
4591             "%4 = OpLoad %float %b\n" +
4592             "%2 = OpExtInst %float %1 FMix %3 %4 %float_0\n" +
4593             "OpReturn\n" +
4594             "OpFunctionEnd",
4595         2, 3),
4596     // Test case 14: Fold mix(a, b, 1.0)
4597     InstructionFoldingCase<uint32_t>(
4598         Header() + "%main = OpFunction %void None %void_func\n" +
4599             "%main_lab = OpLabel\n" +
4600             "%a = OpVariable %_ptr_float Function\n" +
4601             "%b = OpVariable %_ptr_float Function\n" +
4602             "%3 = OpLoad %float %a\n" +
4603             "%4 = OpLoad %float %b\n" +
4604             "%2 = OpExtInst %float %1 FMix %3 %4 %float_1\n" +
4605             "OpReturn\n" +
4606             "OpFunctionEnd",
4607         2, 4),
4608     // Test case 15: Fold vector fadd with null
4609     InstructionFoldingCase<uint32_t>(
4610         Header() + "%main = OpFunction %void None %void_func\n" +
4611             "%main_lab = OpLabel\n" +
4612             "%a = OpVariable %_ptr_v2float Function\n" +
4613             "%2 = OpLoad %v2float %a\n" +
4614             "%3 = OpFAdd %v2float %2 %v2float_null\n" +
4615             "OpReturn\n" +
4616             "OpFunctionEnd",
4617         3, 2),
4618     // Test case 16: Fold vector fadd with null
4619     InstructionFoldingCase<uint32_t>(
4620         Header() + "%main = OpFunction %void None %void_func\n" +
4621             "%main_lab = OpLabel\n" +
4622             "%a = OpVariable %_ptr_v2float Function\n" +
4623             "%2 = OpLoad %v2float %a\n" +
4624             "%3 = OpFAdd %v2float %v2float_null %2\n" +
4625             "OpReturn\n" +
4626             "OpFunctionEnd",
4627         3, 2),
4628     // Test case 17: Fold vector fsub with null
4629     InstructionFoldingCase<uint32_t>(
4630         Header() + "%main = OpFunction %void None %void_func\n" +
4631             "%main_lab = OpLabel\n" +
4632             "%a = OpVariable %_ptr_v2float Function\n" +
4633             "%2 = OpLoad %v2float %a\n" +
4634             "%3 = OpFSub %v2float %2 %v2float_null\n" +
4635             "OpReturn\n" +
4636             "OpFunctionEnd",
4637         3, 2),
4638     // Test case 18: Fold 0.0(half) * n
4639     InstructionFoldingCase<uint32_t>(
4640         Header() + "%main = OpFunction %void None %void_func\n" +
4641             "%main_lab = OpLabel\n" +
4642             "%n = OpVariable %_ptr_half Function\n" +
4643             "%3 = OpLoad %half %n\n" +
4644             "%2 = OpFMul %half %108 %3\n" +
4645             "OpReturn\n" +
4646             "OpFunctionEnd",
4647         2, HALF_0_ID),
4648     // Test case 19: Don't fold 1.0(half) * n
4649     InstructionFoldingCase<uint32_t>(
4650         Header() + "%main = OpFunction %void None %void_func\n" +
4651             "%main_lab = OpLabel\n" +
4652             "%n = OpVariable %_ptr_half Function\n" +
4653             "%3 = OpLoad %half %n\n" +
4654             "%2 = OpFMul %half %half_1 %3\n" +
4655             "OpReturn\n" +
4656             "OpFunctionEnd",
4657         2, 0),
4658     // Test case 20: Don't fold 1.0 * 1.0 (half)
4659     InstructionFoldingCase<uint32_t>(
4660         Header() + "%main = OpFunction %void None %void_func\n" +
4661             "%main_lab = OpLabel\n" +
4662             "%2 = OpFMul %half %half_1 %half_1\n" +
4663             "OpReturn\n" +
4664             "OpFunctionEnd",
4665         2, 0),
4666     // Test case 21: Don't fold (0.0, 1.0) * (0.0, 1.0) (half)
4667     InstructionFoldingCase<uint32_t>(
4668         Header() + "%main = OpFunction %void None %void_func\n" +
4669             "%main_lab = OpLabel\n" +
4670             "%2 = OpFMul %v2half %half_0_1 %half_0_1\n" +
4671             "OpReturn\n" +
4672             "OpFunctionEnd",
4673         2, 0),
4674     // Test case 22: Don't fold (0.0, 1.0) dotp (0.0, 1.0) (half)
4675     InstructionFoldingCase<uint32_t>(
4676         Header() + "%main = OpFunction %void None %void_func\n" +
4677             "%main_lab = OpLabel\n" +
4678             "%2 = OpDot %half %half_0_1 %half_0_1\n" +
4679             "OpReturn\n" +
4680             "OpFunctionEnd",
4681         2, 0),
4682     // Test case 23: Don't fold 1.0(half) / 2.0(half)
4683     // We do not have to code to emulate 16-bit float operations. Just make sure we do not crash.
4684     InstructionFoldingCase<uint32_t>(
4685         Header() + "%main = OpFunction %void None %void_func\n" +
4686             "%main_lab = OpLabel\n" +
4687             "%n = OpVariable %_ptr_half Function\n" +
4688             "%3 = OpLoad %half %n\n" +
4689             "%2 = OpFDiv %half %half_1 %half_2\n" +
4690             "OpReturn\n" +
4691             "OpFunctionEnd",
4692         2, 0)
4693 ));
4694 
4695 INSTANTIATE_TEST_SUITE_P(DoubleRedundantFoldingTest, GeneralInstructionFoldingTest,
4696                         ::testing::Values(
4697     // Test case 0: Don't fold n + 1.0
4698     InstructionFoldingCase<uint32_t>(
4699         Header() + "%main = OpFunction %void None %void_func\n" +
4700             "%main_lab = OpLabel\n" +
4701             "%n = OpVariable %_ptr_double Function\n" +
4702             "%3 = OpLoad %double %n\n" +
4703             "%2 = OpFAdd %double %3 %double_2\n" +
4704             "OpReturn\n" +
4705             "OpFunctionEnd",
4706         2, 0),
4707     // Test case 1: Don't fold n - 1.0
4708     InstructionFoldingCase<uint32_t>(
4709         Header() + "%main = OpFunction %void None %void_func\n" +
4710             "%main_lab = OpLabel\n" +
4711             "%n = OpVariable %_ptr_double Function\n" +
4712             "%3 = OpLoad %double %n\n" +
4713             "%2 = OpFSub %double %3 %double_2\n" +
4714             "OpReturn\n" +
4715             "OpFunctionEnd",
4716         2, 0),
4717     // Test case 2: Don't fold n * 2.0
4718     InstructionFoldingCase<uint32_t>(
4719         Header() + "%main = OpFunction %void None %void_func\n" +
4720             "%main_lab = OpLabel\n" +
4721             "%n = OpVariable %_ptr_double Function\n" +
4722             "%3 = OpLoad %double %n\n" +
4723             "%2 = OpFMul %double %3 %double_2\n" +
4724             "OpReturn\n" +
4725             "OpFunctionEnd",
4726         2, 0),
4727     // Test case 3: Fold n + 0.0
4728     InstructionFoldingCase<uint32_t>(
4729         Header() + "%main = OpFunction %void None %void_func\n" +
4730             "%main_lab = OpLabel\n" +
4731             "%n = OpVariable %_ptr_double Function\n" +
4732             "%3 = OpLoad %double %n\n" +
4733             "%2 = OpFAdd %double %3 %double_0\n" +
4734             "OpReturn\n" +
4735             "OpFunctionEnd",
4736         2, 3),
4737     // Test case 4: Fold 0.0 + n
4738     InstructionFoldingCase<uint32_t>(
4739         Header() + "%main = OpFunction %void None %void_func\n" +
4740             "%main_lab = OpLabel\n" +
4741             "%n = OpVariable %_ptr_double Function\n" +
4742             "%3 = OpLoad %double %n\n" +
4743             "%2 = OpFAdd %double %double_0 %3\n" +
4744             "OpReturn\n" +
4745             "OpFunctionEnd",
4746         2, 3),
4747     // Test case 5: Fold n - 0.0
4748     InstructionFoldingCase<uint32_t>(
4749         Header() + "%main = OpFunction %void None %void_func\n" +
4750             "%main_lab = OpLabel\n" +
4751             "%n = OpVariable %_ptr_double Function\n" +
4752             "%3 = OpLoad %double %n\n" +
4753             "%2 = OpFSub %double %3 %double_0\n" +
4754             "OpReturn\n" +
4755             "OpFunctionEnd",
4756         2, 3),
4757     // Test case 6: Fold n * 1.0
4758     InstructionFoldingCase<uint32_t>(
4759         Header() + "%main = OpFunction %void None %void_func\n" +
4760             "%main_lab = OpLabel\n" +
4761             "%n = OpVariable %_ptr_double Function\n" +
4762             "%3 = OpLoad %double %n\n" +
4763             "%2 = OpFMul %double %3 %double_1\n" +
4764             "OpReturn\n" +
4765             "OpFunctionEnd",
4766         2, 3),
4767     // Test case 7: Fold 1.0 * n
4768     InstructionFoldingCase<uint32_t>(
4769         Header() + "%main = OpFunction %void None %void_func\n" +
4770             "%main_lab = OpLabel\n" +
4771             "%n = OpVariable %_ptr_double Function\n" +
4772             "%3 = OpLoad %double %n\n" +
4773             "%2 = OpFMul %double %double_1 %3\n" +
4774             "OpReturn\n" +
4775             "OpFunctionEnd",
4776         2, 3),
4777     // Test case 8: Fold n / 1.0
4778     InstructionFoldingCase<uint32_t>(
4779         Header() + "%main = OpFunction %void None %void_func\n" +
4780             "%main_lab = OpLabel\n" +
4781             "%n = OpVariable %_ptr_double Function\n" +
4782             "%3 = OpLoad %double %n\n" +
4783             "%2 = OpFDiv %double %3 %double_1\n" +
4784             "OpReturn\n" +
4785             "OpFunctionEnd",
4786         2, 3),
4787     // Test case 9: Fold n * 0.0
4788     InstructionFoldingCase<uint32_t>(
4789         Header() + "%main = OpFunction %void None %void_func\n" +
4790             "%main_lab = OpLabel\n" +
4791             "%n = OpVariable %_ptr_double Function\n" +
4792             "%3 = OpLoad %double %n\n" +
4793             "%2 = OpFMul %double %3 %105\n" +
4794             "OpReturn\n" +
4795             "OpFunctionEnd",
4796         2, DOUBLE_0_ID),
4797     // Test case 10: Fold 0.0 * n
4798     InstructionFoldingCase<uint32_t>(
4799         Header() + "%main = OpFunction %void None %void_func\n" +
4800             "%main_lab = OpLabel\n" +
4801             "%n = OpVariable %_ptr_double Function\n" +
4802             "%3 = OpLoad %double %n\n" +
4803             "%2 = OpFMul %double %105 %3\n" +
4804             "OpReturn\n" +
4805             "OpFunctionEnd",
4806         2, DOUBLE_0_ID),
4807     // Test case 11: Fold 0.0 / n
4808     InstructionFoldingCase<uint32_t>(
4809         Header() + "%main = OpFunction %void None %void_func\n" +
4810             "%main_lab = OpLabel\n" +
4811             "%n = OpVariable %_ptr_double Function\n" +
4812             "%3 = OpLoad %double %n\n" +
4813             "%2 = OpFDiv %double %105 %3\n" +
4814             "OpReturn\n" +
4815             "OpFunctionEnd",
4816         2, DOUBLE_0_ID),
4817     // Test case 12: Don't fold mix(a, b, 2.0)
4818     InstructionFoldingCase<uint32_t>(
4819         Header() + "%main = OpFunction %void None %void_func\n" +
4820             "%main_lab = OpLabel\n" +
4821             "%a = OpVariable %_ptr_double Function\n" +
4822             "%b = OpVariable %_ptr_double Function\n" +
4823             "%3 = OpLoad %double %a\n" +
4824             "%4 = OpLoad %double %b\n" +
4825             "%2 = OpExtInst %double %1 FMix %3 %4 %double_2\n" +
4826             "OpReturn\n" +
4827             "OpFunctionEnd",
4828         2, 0),
4829     // Test case 13: Fold mix(a, b, 0.0)
4830     InstructionFoldingCase<uint32_t>(
4831         Header() + "%main = OpFunction %void None %void_func\n" +
4832             "%main_lab = OpLabel\n" +
4833             "%a = OpVariable %_ptr_double Function\n" +
4834             "%b = OpVariable %_ptr_double Function\n" +
4835             "%3 = OpLoad %double %a\n" +
4836             "%4 = OpLoad %double %b\n" +
4837             "%2 = OpExtInst %double %1 FMix %3 %4 %double_0\n" +
4838             "OpReturn\n" +
4839             "OpFunctionEnd",
4840         2, 3),
4841     // Test case 14: Fold mix(a, b, 1.0)
4842     InstructionFoldingCase<uint32_t>(
4843         Header() + "%main = OpFunction %void None %void_func\n" +
4844             "%main_lab = OpLabel\n" +
4845             "%a = OpVariable %_ptr_double Function\n" +
4846             "%b = OpVariable %_ptr_double Function\n" +
4847             "%3 = OpLoad %double %a\n" +
4848             "%4 = OpLoad %double %b\n" +
4849             "%2 = OpExtInst %double %1 FMix %3 %4 %double_1\n" +
4850             "OpReturn\n" +
4851             "OpFunctionEnd",
4852         2, 4)
4853 ));
4854 
4855 INSTANTIATE_TEST_SUITE_P(FloatVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
4856                         ::testing::Values(
4857     // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
4858     InstructionFoldingCase<uint32_t>(
4859         Header() + "%main = OpFunction %void None %void_func\n" +
4860             "%main_lab = OpLabel\n" +
4861             "%n = OpVariable %_ptr_v4float Function\n" +
4862             "%3 = OpLoad %v4float %n\n" +
4863             "%2 = OpFMul %v4float %3 %v4float_0_0_0_1\n" +
4864             "OpReturn\n" +
4865             "OpFunctionEnd",
4866         2, 0),
4867     // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
4868     InstructionFoldingCase<uint32_t>(
4869         Header() + "%main = OpFunction %void None %void_func\n" +
4870             "%main_lab = OpLabel\n" +
4871             "%n = OpVariable %_ptr_v4float Function\n" +
4872             "%3 = OpLoad %v4float %n\n" +
4873             "%2 = OpFMul %v4float %3 %106\n" +
4874             "OpReturn\n" +
4875             "OpFunctionEnd",
4876         2, VEC4_0_ID),
4877     // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
4878     InstructionFoldingCase<uint32_t>(
4879         Header() + "%main = OpFunction %void None %void_func\n" +
4880             "%main_lab = OpLabel\n" +
4881             "%n = OpVariable %_ptr_v4float Function\n" +
4882             "%3 = OpLoad %v4float %n\n" +
4883             "%2 = OpFMul %v4float %3 %v4float_1_1_1_1\n" +
4884             "OpReturn\n" +
4885             "OpFunctionEnd",
4886         2, 3)
4887 ));
4888 
4889 INSTANTIATE_TEST_SUITE_P(DoubleVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
4890                         ::testing::Values(
4891     // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
4892     InstructionFoldingCase<uint32_t>(
4893         Header() + "%main = OpFunction %void None %void_func\n" +
4894             "%main_lab = OpLabel\n" +
4895             "%n = OpVariable %_ptr_v4double Function\n" +
4896             "%3 = OpLoad %v4double %n\n" +
4897             "%2 = OpFMul %v4double %3 %v4double_0_0_0_1\n" +
4898             "OpReturn\n" +
4899             "OpFunctionEnd",
4900         2, 0),
4901     // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
4902     InstructionFoldingCase<uint32_t>(
4903         Header() + "%main = OpFunction %void None %void_func\n" +
4904             "%main_lab = OpLabel\n" +
4905             "%n = OpVariable %_ptr_v4double Function\n" +
4906             "%3 = OpLoad %v4double %n\n" +
4907             "%2 = OpFMul %v4double %3 %106\n" +
4908             "OpReturn\n" +
4909             "OpFunctionEnd",
4910         2, DVEC4_0_ID),
4911     // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
4912     InstructionFoldingCase<uint32_t>(
4913         Header() + "%main = OpFunction %void None %void_func\n" +
4914             "%main_lab = OpLabel\n" +
4915             "%n = OpVariable %_ptr_v4double Function\n" +
4916             "%3 = OpLoad %v4double %n\n" +
4917             "%2 = OpFMul %v4double %3 %v4double_1_1_1_1\n" +
4918             "OpReturn\n" +
4919             "OpFunctionEnd",
4920         2, 3)
4921 ));
4922 
4923 INSTANTIATE_TEST_SUITE_P(IntegerRedundantFoldingTest, GeneralInstructionFoldingTest,
4924                         ::testing::Values(
4925     // Test case 0: Don't fold n + 1
4926     InstructionFoldingCase<uint32_t>(
4927         Header() + "%main = OpFunction %void None %void_func\n" +
4928             "%main_lab = OpLabel\n" +
4929             "%n = OpVariable %_ptr_uint Function\n" +
4930             "%3 = OpLoad %uint %n\n" +
4931             "%2 = OpIAdd %uint %3 %uint_1\n" +
4932             "OpReturn\n" +
4933             "OpFunctionEnd",
4934         2, 0),
4935     // Test case 1: Don't fold 1 + n
4936     InstructionFoldingCase<uint32_t>(
4937         Header() + "%main = OpFunction %void None %void_func\n" +
4938             "%main_lab = OpLabel\n" +
4939             "%n = OpVariable %_ptr_uint Function\n" +
4940             "%3 = OpLoad %uint %n\n" +
4941             "%2 = OpIAdd %uint %uint_1 %3\n" +
4942             "OpReturn\n" +
4943             "OpFunctionEnd",
4944         2, 0),
4945     // Test case 2: Fold n + 0
4946     InstructionFoldingCase<uint32_t>(
4947         Header() + "%main = OpFunction %void None %void_func\n" +
4948             "%main_lab = OpLabel\n" +
4949             "%n = OpVariable %_ptr_uint Function\n" +
4950             "%3 = OpLoad %uint %n\n" +
4951             "%2 = OpIAdd %uint %3 %uint_0\n" +
4952             "OpReturn\n" +
4953             "OpFunctionEnd",
4954         2, 3),
4955     // Test case 3: Fold 0 + n
4956     InstructionFoldingCase<uint32_t>(
4957         Header() + "%main = OpFunction %void None %void_func\n" +
4958             "%main_lab = OpLabel\n" +
4959             "%n = OpVariable %_ptr_uint Function\n" +
4960             "%3 = OpLoad %uint %n\n" +
4961             "%2 = OpIAdd %uint %uint_0 %3\n" +
4962             "OpReturn\n" +
4963             "OpFunctionEnd",
4964         2, 3),
4965     // Test case 4: Don't fold n + (1,0)
4966     InstructionFoldingCase<uint32_t>(
4967         Header() + "%main = OpFunction %void None %void_func\n" +
4968             "%main_lab = OpLabel\n" +
4969             "%n = OpVariable %_ptr_v2int Function\n" +
4970             "%3 = OpLoad %v2int %n\n" +
4971             "%2 = OpIAdd %v2int %3 %v2int_1_0\n" +
4972             "OpReturn\n" +
4973             "OpFunctionEnd",
4974         2, 0),
4975     // Test case 5: Don't fold (1,0) + n
4976     InstructionFoldingCase<uint32_t>(
4977         Header() + "%main = OpFunction %void None %void_func\n" +
4978             "%main_lab = OpLabel\n" +
4979             "%n = OpVariable %_ptr_v2int Function\n" +
4980             "%3 = OpLoad %v2int %n\n" +
4981             "%2 = OpIAdd %v2int %v2int_1_0 %3\n" +
4982             "OpReturn\n" +
4983             "OpFunctionEnd",
4984         2, 0),
4985     // Test case 6: Fold n + (0,0)
4986     InstructionFoldingCase<uint32_t>(
4987         Header() + "%main = OpFunction %void None %void_func\n" +
4988             "%main_lab = OpLabel\n" +
4989             "%n = OpVariable %_ptr_v2int Function\n" +
4990             "%3 = OpLoad %v2int %n\n" +
4991             "%2 = OpIAdd %v2int %3 %v2int_0_0\n" +
4992             "OpReturn\n" +
4993             "OpFunctionEnd",
4994         2, 3),
4995     // Test case 7: Fold (0,0) + n
4996     InstructionFoldingCase<uint32_t>(
4997         Header() + "%main = OpFunction %void None %void_func\n" +
4998             "%main_lab = OpLabel\n" +
4999             "%n = OpVariable %_ptr_v2int Function\n" +
5000             "%3 = OpLoad %v2int %n\n" +
5001             "%2 = OpIAdd %v2int %v2int_0_0 %3\n" +
5002             "OpReturn\n" +
5003             "OpFunctionEnd",
5004         2, 3),
5005     // Test case 8: Don't fold because of undefined value. Using 4294967295
5006     // means that entry is undefined. We do not expect it to ever happen, so
5007     // not worth folding.
5008     InstructionFoldingCase<uint32_t>(
5009         Header() + "%main = OpFunction %void None %void_func\n" +
5010             "%main_lab = OpLabel\n" +
5011             "%n = OpVariable %_ptr_int Function\n" +
5012             "%load = OpLoad %int %n\n" +
5013             "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 4294967295 3\n" +
5014             "OpReturn\n" +
5015             "OpFunctionEnd",
5016         2, 0),
5017     // Test case 9: Don't fold because of undefined value. Using 4294967295
5018     // means that entry is undefined. We do not expect it to ever happen, so
5019     // not worth folding.
5020     InstructionFoldingCase<uint32_t>(
5021         Header() + "%main = OpFunction %void None %void_func\n" +
5022             "%main_lab = OpLabel\n" +
5023             "%n = OpVariable %_ptr_int Function\n" +
5024             "%load = OpLoad %int %n\n" +
5025             "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 4294967295 \n" +
5026             "OpReturn\n" +
5027             "OpFunctionEnd",
5028         2, 0)
5029 ));
5030 
5031 INSTANTIATE_TEST_SUITE_P(ClampAndCmpLHS, GeneralInstructionFoldingTest,
5032 ::testing::Values(
5033     // Test case 0: Don't Fold 0.0 < clamp(-1, 1)
5034     InstructionFoldingCase<uint32_t>(
5035         Header() + "%main = OpFunction %void None %void_func\n" +
5036             "%main_lab = OpLabel\n" +
5037             "%n = OpVariable %_ptr_float Function\n" +
5038             "%ld = OpLoad %float %n\n" +
5039             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5040             "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
5041             "OpReturn\n" +
5042             "OpFunctionEnd",
5043         2, 0),
5044     // Test case 1: Don't Fold 0.0 < clamp(-1, 1)
5045     InstructionFoldingCase<uint32_t>(
5046         Header() + "%main = OpFunction %void None %void_func\n" +
5047             "%main_lab = OpLabel\n" +
5048             "%n = OpVariable %_ptr_float Function\n" +
5049             "%ld = OpLoad %float %n\n" +
5050             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5051             "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
5052             "OpReturn\n" +
5053             "OpFunctionEnd",
5054         2, 0),
5055     // Test case 2: Don't Fold 0.0 <= clamp(-1, 1)
5056     InstructionFoldingCase<uint32_t>(
5057         Header() + "%main = OpFunction %void None %void_func\n" +
5058             "%main_lab = OpLabel\n" +
5059             "%n = OpVariable %_ptr_float Function\n" +
5060             "%ld = OpLoad %float %n\n" +
5061             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5062             "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
5063             "OpReturn\n" +
5064             "OpFunctionEnd",
5065         2, 0),
5066     // Test case 3: Don't Fold 0.0 <= clamp(-1, 1)
5067     InstructionFoldingCase<uint32_t>(
5068         Header() + "%main = OpFunction %void None %void_func\n" +
5069             "%main_lab = OpLabel\n" +
5070             "%n = OpVariable %_ptr_float Function\n" +
5071             "%ld = OpLoad %float %n\n" +
5072             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5073             "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
5074             "OpReturn\n" +
5075             "OpFunctionEnd",
5076         2, 0),
5077     // Test case 4: Don't Fold 0.0 > clamp(-1, 1)
5078     InstructionFoldingCase<uint32_t>(
5079         Header() + "%main = OpFunction %void None %void_func\n" +
5080             "%main_lab = OpLabel\n" +
5081             "%n = OpVariable %_ptr_float Function\n" +
5082             "%ld = OpLoad %float %n\n" +
5083             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5084             "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
5085             "OpReturn\n" +
5086             "OpFunctionEnd",
5087         2, 0),
5088     // Test case 5: Don't Fold 0.0 > clamp(-1, 1)
5089     InstructionFoldingCase<uint32_t>(
5090         Header() + "%main = OpFunction %void None %void_func\n" +
5091             "%main_lab = OpLabel\n" +
5092             "%n = OpVariable %_ptr_float Function\n" +
5093             "%ld = OpLoad %float %n\n" +
5094             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5095             "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
5096             "OpReturn\n" +
5097             "OpFunctionEnd",
5098         2, 0),
5099     // Test case 6: Don't Fold 0.0 >= clamp(-1, 1)
5100     InstructionFoldingCase<uint32_t>(
5101         Header() + "%main = OpFunction %void None %void_func\n" +
5102             "%main_lab = OpLabel\n" +
5103             "%n = OpVariable %_ptr_float Function\n" +
5104             "%ld = OpLoad %float %n\n" +
5105             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5106             "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
5107             "OpReturn\n" +
5108             "OpFunctionEnd",
5109         2, 0),
5110     // Test case 7: Don't Fold 0.0 >= clamp(-1, 1)
5111     InstructionFoldingCase<uint32_t>(
5112         Header() + "%main = OpFunction %void None %void_func\n" +
5113             "%main_lab = OpLabel\n" +
5114             "%n = OpVariable %_ptr_float Function\n" +
5115             "%ld = OpLoad %float %n\n" +
5116             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5117             "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
5118             "OpReturn\n" +
5119             "OpFunctionEnd",
5120         2, 0),
5121     // Test case 8: Don't Fold 0.0 < clamp(0, 1)
5122     InstructionFoldingCase<uint32_t>(
5123         Header() + "%main = OpFunction %void None %void_func\n" +
5124             "%main_lab = OpLabel\n" +
5125             "%n = OpVariable %_ptr_float Function\n" +
5126             "%ld = OpLoad %float %n\n" +
5127             "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
5128             "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
5129             "OpReturn\n" +
5130             "OpFunctionEnd",
5131         2, 0),
5132     // Test case 9: Don't Fold 0.0 < clamp(0, 1)
5133     InstructionFoldingCase<uint32_t>(
5134         Header() + "%main = OpFunction %void None %void_func\n" +
5135             "%main_lab = OpLabel\n" +
5136             "%n = OpVariable %_ptr_float Function\n" +
5137             "%ld = OpLoad %float %n\n" +
5138             "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
5139             "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
5140             "OpReturn\n" +
5141             "OpFunctionEnd",
5142         2, 0),
5143     // Test case 10: Don't Fold 0.0 > clamp(-1, 0)
5144     InstructionFoldingCase<uint32_t>(
5145         Header() + "%main = OpFunction %void None %void_func\n" +
5146             "%main_lab = OpLabel\n" +
5147             "%n = OpVariable %_ptr_float Function\n" +
5148             "%ld = OpLoad %float %n\n" +
5149             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5150             "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
5151             "OpReturn\n" +
5152             "OpFunctionEnd",
5153         2, 0),
5154     // Test case 11: Don't Fold 0.0 > clamp(-1, 0)
5155     InstructionFoldingCase<uint32_t>(
5156         Header() + "%main = OpFunction %void None %void_func\n" +
5157             "%main_lab = OpLabel\n" +
5158             "%n = OpVariable %_ptr_float Function\n" +
5159             "%ld = OpLoad %float %n\n" +
5160             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5161             "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
5162             "OpReturn\n" +
5163             "OpFunctionEnd",
5164         2, 0)
5165 ));
5166 
5167 INSTANTIATE_TEST_SUITE_P(ClampAndCmpRHS, GeneralInstructionFoldingTest,
5168 ::testing::Values(
5169     // Test case 0: Don't Fold clamp(-1, 1) < 0.0
5170     InstructionFoldingCase<uint32_t>(
5171       Header() + "%main = OpFunction %void None %void_func\n" +
5172           "%main_lab = OpLabel\n" +
5173           "%n = OpVariable %_ptr_float Function\n" +
5174           "%ld = OpLoad %float %n\n" +
5175           "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5176           "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
5177           "OpReturn\n" +
5178           "OpFunctionEnd",
5179       2, 0),
5180     // Test case 1: Don't Fold clamp(-1, 1) < 0.0
5181     InstructionFoldingCase<uint32_t>(
5182       Header() + "%main = OpFunction %void None %void_func\n" +
5183           "%main_lab = OpLabel\n" +
5184           "%n = OpVariable %_ptr_float Function\n" +
5185           "%ld = OpLoad %float %n\n" +
5186           "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5187           "%2 = OpFOrdLessThan %bool %clamp %float_0\n" +
5188           "OpReturn\n" +
5189           "OpFunctionEnd",
5190       2, 0),
5191     // Test case 2: Don't Fold clamp(-1, 1) <= 0.0
5192     InstructionFoldingCase<uint32_t>(
5193       Header() + "%main = OpFunction %void None %void_func\n" +
5194           "%main_lab = OpLabel\n" +
5195           "%n = OpVariable %_ptr_float Function\n" +
5196           "%ld = OpLoad %float %n\n" +
5197           "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5198           "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
5199           "OpReturn\n" +
5200           "OpFunctionEnd",
5201       2, 0),
5202     // Test case 3: Don't Fold clamp(-1, 1) <= 0.0
5203     InstructionFoldingCase<uint32_t>(
5204       Header() + "%main = OpFunction %void None %void_func\n" +
5205           "%main_lab = OpLabel\n" +
5206           "%n = OpVariable %_ptr_float Function\n" +
5207           "%ld = OpLoad %float %n\n" +
5208           "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5209           "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
5210           "OpReturn\n" +
5211           "OpFunctionEnd",
5212       2, 0),
5213     // Test case 4: Don't Fold clamp(-1, 1) > 0.0
5214     InstructionFoldingCase<uint32_t>(
5215         Header() + "%main = OpFunction %void None %void_func\n" +
5216             "%main_lab = OpLabel\n" +
5217             "%n = OpVariable %_ptr_float Function\n" +
5218             "%ld = OpLoad %float %n\n" +
5219             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5220             "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
5221             "OpReturn\n" +
5222             "OpFunctionEnd",
5223         2, 0),
5224     // Test case 5: Don't Fold clamp(-1, 1) > 0.0
5225     InstructionFoldingCase<uint32_t>(
5226         Header() + "%main = OpFunction %void None %void_func\n" +
5227             "%main_lab = OpLabel\n" +
5228             "%n = OpVariable %_ptr_float Function\n" +
5229             "%ld = OpLoad %float %n\n" +
5230             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5231             "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
5232             "OpReturn\n" +
5233             "OpFunctionEnd",
5234         2, 0),
5235     // Test case 6: Don't Fold clamp(-1, 1) >= 0.0
5236     InstructionFoldingCase<uint32_t>(
5237         Header() + "%main = OpFunction %void None %void_func\n" +
5238             "%main_lab = OpLabel\n" +
5239             "%n = OpVariable %_ptr_float Function\n" +
5240             "%ld = OpLoad %float %n\n" +
5241             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5242             "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_0\n" +
5243             "OpReturn\n" +
5244             "OpFunctionEnd",
5245         2, 0),
5246     // Test case 7: Don't Fold clamp(-1, 1) >= 0.0
5247     InstructionFoldingCase<uint32_t>(
5248         Header() + "%main = OpFunction %void None %void_func\n" +
5249             "%main_lab = OpLabel\n" +
5250             "%n = OpVariable %_ptr_float Function\n" +
5251             "%ld = OpLoad %float %n\n" +
5252             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5253             "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
5254             "OpReturn\n" +
5255             "OpFunctionEnd",
5256         2, 0),
5257     // Test case 8: Don't Fold clamp(-1, 0) < 0.0
5258     InstructionFoldingCase<uint32_t>(
5259         Header() + "%main = OpFunction %void None %void_func\n" +
5260             "%main_lab = OpLabel\n" +
5261             "%n = OpVariable %_ptr_float Function\n" +
5262             "%ld = OpLoad %float %n\n" +
5263             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5264             "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
5265             "OpReturn\n" +
5266             "OpFunctionEnd",
5267         2, 0),
5268     // Test case 9: Don't Fold clamp(0, 1) < 1
5269     InstructionFoldingCase<uint32_t>(
5270         Header() + "%main = OpFunction %void None %void_func\n" +
5271             "%main_lab = OpLabel\n" +
5272             "%n = OpVariable %_ptr_float Function\n" +
5273             "%ld = OpLoad %float %n\n" +
5274             "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
5275             "%2 = OpFOrdLessThan %bool %clamp %float_1\n" +
5276             "OpReturn\n" +
5277             "OpFunctionEnd",
5278         2, 0),
5279     // Test case 10: Don't Fold clamp(-1, 0) > -1
5280     InstructionFoldingCase<uint32_t>(
5281         Header() + "%main = OpFunction %void None %void_func\n" +
5282             "%main_lab = OpLabel\n" +
5283             "%n = OpVariable %_ptr_float Function\n" +
5284             "%ld = OpLoad %float %n\n" +
5285             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5286             "%2 = OpFUnordGreaterThan %bool %clamp %float_n1\n" +
5287             "OpReturn\n" +
5288             "OpFunctionEnd",
5289         2, 0),
5290     // Test case 11: Don't Fold clamp(-1, 0) > -1
5291     InstructionFoldingCase<uint32_t>(
5292         Header() + "%main = OpFunction %void None %void_func\n" +
5293             "%main_lab = OpLabel\n" +
5294             "%n = OpVariable %_ptr_float Function\n" +
5295             "%ld = OpLoad %float %n\n" +
5296             "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5297             "%2 = OpFOrdGreaterThan %bool %clamp %float_n1\n" +
5298             "OpReturn\n" +
5299             "OpFunctionEnd",
5300         2, 0)
5301 ));
5302 
5303 INSTANTIATE_TEST_SUITE_P(FToIConstantFoldingTest, IntegerInstructionFoldingTest,
5304                         ::testing::Values(
5305     // Test case 0: Fold int(3.0)
5306     InstructionFoldingCase<uint32_t>(
5307         Header() + "%main = OpFunction %void None %void_func\n" +
5308             "%main_lab = OpLabel\n" +
5309             "%2 = OpConvertFToS %int %float_3\n" +
5310             "OpReturn\n" +
5311             "OpFunctionEnd",
5312         2, 3),
5313     // Test case 1: Fold uint(3.0)
5314     InstructionFoldingCase<uint32_t>(
5315         Header() + "%main = OpFunction %void None %void_func\n" +
5316             "%main_lab = OpLabel\n" +
5317             "%2 = OpConvertFToU %int %float_3\n" +
5318             "OpReturn\n" +
5319             "OpFunctionEnd",
5320         2, 3)
5321 ));
5322 
5323 INSTANTIATE_TEST_SUITE_P(IToFConstantFoldingTest, FloatInstructionFoldingTest,
5324                         ::testing::Values(
5325     // Test case 0: Fold float(3)
5326     InstructionFoldingCase<float>(
5327         Header() + "%main = OpFunction %void None %void_func\n" +
5328             "%main_lab = OpLabel\n" +
5329             "%2 = OpConvertSToF %float %int_3\n" +
5330             "OpReturn\n" +
5331             "OpFunctionEnd",
5332         2, 3.0),
5333     // Test case 1: Fold float(3u)
5334     InstructionFoldingCase<float>(
5335         Header() + "%main = OpFunction %void None %void_func\n" +
5336             "%main_lab = OpLabel\n" +
5337             "%2 = OpConvertUToF %float %uint_3\n" +
5338             "OpReturn\n" +
5339             "OpFunctionEnd",
5340         2, 3.0)
5341 ));
5342 // clang-format on
5343 
5344 using ToNegateFoldingTest =
5345     ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
5346 
TEST_P(ToNegateFoldingTest,Case)5347 TEST_P(ToNegateFoldingTest, Case) {
5348   const auto& tc = GetParam();
5349 
5350   std::unique_ptr<IRContext> context;
5351   Instruction* inst;
5352   std::tie(context, inst) =
5353       FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
5354 
5355   EXPECT_TRUE((inst == nullptr) == (tc.expected_result == 0));
5356   if (inst != nullptr) {
5357     EXPECT_EQ(inst->opcode(), spv::Op::OpFNegate);
5358     EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
5359   }
5360 }
5361 
5362 // clang-format off
5363 INSTANTIATE_TEST_SUITE_P(FloatRedundantSubFoldingTest, ToNegateFoldingTest,
5364                         ::testing::Values(
5365     // Test case 0: Don't fold 1.0 - n
5366     InstructionFoldingCase<uint32_t>(
5367         Header() + "%main = OpFunction %void None %void_func\n" +
5368             "%main_lab = OpLabel\n" +
5369             "%n = OpVariable %_ptr_float Function\n" +
5370             "%3 = OpLoad %float %n\n" +
5371             "%2 = OpFSub %float %float_1 %3\n" +
5372             "OpReturn\n" +
5373             "OpFunctionEnd",
5374         2, 0),
5375     // Test case 1: Fold 0.0 - n
5376     InstructionFoldingCase<uint32_t>(
5377         Header() + "%main = OpFunction %void None %void_func\n" +
5378             "%main_lab = OpLabel\n" +
5379             "%n = OpVariable %_ptr_float Function\n" +
5380             "%3 = OpLoad %float %n\n" +
5381             "%2 = OpFSub %float %float_0 %3\n" +
5382             "OpReturn\n" +
5383             "OpFunctionEnd",
5384         2, 3),
5385 	// Test case 2: Don't fold (0,0,0,1) - n
5386     InstructionFoldingCase<uint32_t>(
5387         Header() + "%main = OpFunction %void None %void_func\n" +
5388             "%main_lab = OpLabel\n" +
5389             "%n = OpVariable %_ptr_v4float Function\n" +
5390             "%3 = OpLoad %v4float %n\n" +
5391             "%2 = OpFSub %v4float %v4float_0_0_0_1 %3\n" +
5392             "OpReturn\n" +
5393             "OpFunctionEnd",
5394         2, 0),
5395 	// Test case 3: Fold (0,0,0,0) - n
5396     InstructionFoldingCase<uint32_t>(
5397         Header() + "%main = OpFunction %void None %void_func\n" +
5398             "%main_lab = OpLabel\n" +
5399             "%n = OpVariable %_ptr_v4float Function\n" +
5400             "%3 = OpLoad %v4float %n\n" +
5401             "%2 = OpFSub %v4float %v4float_0_0_0_0 %3\n" +
5402             "OpReturn\n" +
5403             "OpFunctionEnd",
5404         2, 3)
5405 ));
5406 
5407 INSTANTIATE_TEST_SUITE_P(DoubleRedundantSubFoldingTest, ToNegateFoldingTest,
5408                         ::testing::Values(
5409     // Test case 0: Don't fold 1.0 - n
5410     InstructionFoldingCase<uint32_t>(
5411         Header() + "%main = OpFunction %void None %void_func\n" +
5412             "%main_lab = OpLabel\n" +
5413             "%n = OpVariable %_ptr_double Function\n" +
5414             "%3 = OpLoad %double %n\n" +
5415             "%2 = OpFSub %double %double_1 %3\n" +
5416             "OpReturn\n" +
5417             "OpFunctionEnd",
5418         2, 0),
5419     // Test case 1: Fold 0.0 - n
5420     InstructionFoldingCase<uint32_t>(
5421         Header() + "%main = OpFunction %void None %void_func\n" +
5422             "%main_lab = OpLabel\n" +
5423             "%n = OpVariable %_ptr_double Function\n" +
5424             "%3 = OpLoad %double %n\n" +
5425             "%2 = OpFSub %double %double_0 %3\n" +
5426             "OpReturn\n" +
5427             "OpFunctionEnd",
5428         2, 3),
5429 	// Test case 2: Don't fold (0,0,0,1) - n
5430     InstructionFoldingCase<uint32_t>(
5431         Header() + "%main = OpFunction %void None %void_func\n" +
5432             "%main_lab = OpLabel\n" +
5433             "%n = OpVariable %_ptr_v4double Function\n" +
5434             "%3 = OpLoad %v4double %n\n" +
5435             "%2 = OpFSub %v4double %v4double_0_0_0_1 %3\n" +
5436             "OpReturn\n" +
5437             "OpFunctionEnd",
5438         2, 0),
5439 	// Test case 3: Fold (0,0,0,0) - n
5440     InstructionFoldingCase<uint32_t>(
5441         Header() + "%main = OpFunction %void None %void_func\n" +
5442             "%main_lab = OpLabel\n" +
5443             "%n = OpVariable %_ptr_v4double Function\n" +
5444             "%3 = OpLoad %v4double %n\n" +
5445             "%2 = OpFSub %v4double %v4double_0_0_0_0 %3\n" +
5446             "OpReturn\n" +
5447             "OpFunctionEnd",
5448         2, 3)
5449 ));
5450 
5451 using MatchingInstructionFoldingTest =
5452     ::testing::TestWithParam<InstructionFoldingCase<bool>>;
5453 
TEST_P(MatchingInstructionFoldingTest,Case)5454 TEST_P(MatchingInstructionFoldingTest, Case) {
5455   const auto& tc = GetParam();
5456 
5457   std::unique_ptr<IRContext> context;
5458   Instruction* inst;
5459   std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
5460 
5461   EXPECT_EQ(inst != nullptr, tc.expected_result);
5462   if (inst != nullptr) {
5463     Match(tc.test_body, context.get());
5464   }
5465 }
5466 
5467 INSTANTIATE_TEST_SUITE_P(RedundantIntegerMatching, MatchingInstructionFoldingTest,
5468 ::testing::Values(
5469     // Test case 0: Fold 0 + n (change sign)
5470     InstructionFoldingCase<bool>(
5471         Header() +
5472             "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
5473             "; CHECK: %2 = OpBitcast [[uint]] %3\n" +
5474             "%main = OpFunction %void None %void_func\n" +
5475             "%main_lab = OpLabel\n" +
5476             "%n = OpVariable %_ptr_int Function\n" +
5477             "%3 = OpLoad %uint %n\n" +
5478             "%2 = OpIAdd %uint %int_0 %3\n" +
5479             "OpReturn\n" +
5480             "OpFunctionEnd\n",
5481         2, true),
5482     // Test case 0: Fold 0 + n (change sign)
5483     InstructionFoldingCase<bool>(
5484         Header() +
5485             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5486             "; CHECK: %2 = OpBitcast [[int]] %3\n" +
5487             "%main = OpFunction %void None %void_func\n" +
5488             "%main_lab = OpLabel\n" +
5489             "%n = OpVariable %_ptr_int Function\n" +
5490             "%3 = OpLoad %int %n\n" +
5491             "%2 = OpIAdd %int %uint_0 %3\n" +
5492             "OpReturn\n" +
5493             "OpFunctionEnd\n",
5494         2, true)
5495 ));
5496 
5497 INSTANTIATE_TEST_SUITE_P(MergeNegateTest, MatchingInstructionFoldingTest,
5498 ::testing::Values(
5499   // Test case 0: fold consecutive fnegate
5500   // -(-x) = x
5501   InstructionFoldingCase<bool>(
5502     Header() +
5503       "; CHECK: [[ld:%\\w+]] = OpLoad [[float:%\\w+]]\n" +
5504       "; CHECK: %4 = OpCopyObject [[float]] [[ld]]\n" +
5505       "%main = OpFunction %void None %void_func\n" +
5506       "%main_lab = OpLabel\n" +
5507       "%var = OpVariable %_ptr_float Function\n" +
5508       "%2 = OpLoad %float %var\n" +
5509       "%3 = OpFNegate %float %2\n" +
5510       "%4 = OpFNegate %float %3\n" +
5511       "OpReturn\n" +
5512       "OpFunctionEnd",
5513     4, true),
5514   // Test case 1: fold fnegate(fmul with const).
5515   // -(x * 2.0) = x * -2.0
5516   InstructionFoldingCase<bool>(
5517     Header() +
5518       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5519       "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5520       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5521       "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
5522       "%main = OpFunction %void None %void_func\n" +
5523       "%main_lab = OpLabel\n" +
5524       "%var = OpVariable %_ptr_float Function\n" +
5525       "%2 = OpLoad %float %var\n" +
5526       "%3 = OpFMul %float %2 %float_2\n" +
5527       "%4 = OpFNegate %float %3\n" +
5528       "OpReturn\n" +
5529       "OpFunctionEnd",
5530     4, true),
5531   // Test case 2: fold fnegate(fmul with const).
5532   // -(2.0 * x) = x * 2.0
5533   InstructionFoldingCase<bool>(
5534     Header() +
5535       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5536       "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5537       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5538       "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
5539       "%main = OpFunction %void None %void_func\n" +
5540       "%main_lab = OpLabel\n" +
5541       "%var = OpVariable %_ptr_float Function\n" +
5542       "%2 = OpLoad %float %var\n" +
5543       "%3 = OpFMul %float %float_2 %2\n" +
5544       "%4 = OpFNegate %float %3\n" +
5545       "OpReturn\n" +
5546       "OpFunctionEnd",
5547     4, true),
5548   // Test case 3: fold fnegate(fdiv with const).
5549   // -(x / 2.0) = x * -0.5
5550   InstructionFoldingCase<bool>(
5551     Header() +
5552       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5553       "; CHECK: [[float_n0p5:%\\w+]] = OpConstant [[float]] -0.5\n" +
5554       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5555       "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n0p5]]\n" +
5556       "%main = OpFunction %void None %void_func\n" +
5557       "%main_lab = OpLabel\n" +
5558       "%var = OpVariable %_ptr_float Function\n" +
5559       "%2 = OpLoad %float %var\n" +
5560       "%3 = OpFDiv %float %2 %float_2\n" +
5561       "%4 = OpFNegate %float %3\n" +
5562       "OpReturn\n" +
5563       "OpFunctionEnd",
5564     4, true),
5565   // Test case 4: fold fnegate(fdiv with const).
5566   // -(2.0 / x) = -2.0 / x
5567   InstructionFoldingCase<bool>(
5568     Header() +
5569       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5570       "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5571       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5572       "; CHECK: %4 = OpFDiv [[float]] [[float_n2]] [[ld]]\n" +
5573       "%main = OpFunction %void None %void_func\n" +
5574       "%main_lab = OpLabel\n" +
5575       "%var = OpVariable %_ptr_float Function\n" +
5576       "%2 = OpLoad %float %var\n" +
5577       "%3 = OpFDiv %float %float_2 %2\n" +
5578       "%4 = OpFNegate %float %3\n" +
5579       "OpReturn\n" +
5580       "OpFunctionEnd",
5581     4, true),
5582   // Test case 5: fold fnegate(fadd with const).
5583   // -(2.0 + x) = -2.0 - x
5584   InstructionFoldingCase<bool>(
5585     Header() +
5586       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5587       "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5588       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5589       "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
5590       "%main = OpFunction %void None %void_func\n" +
5591       "%main_lab = OpLabel\n" +
5592       "%var = OpVariable %_ptr_float Function\n" +
5593       "%2 = OpLoad %float %var\n" +
5594       "%3 = OpFAdd %float %float_2 %2\n" +
5595       "%4 = OpFNegate %float %3\n" +
5596       "OpReturn\n" +
5597       "OpFunctionEnd",
5598     4, true),
5599   // Test case 6: fold fnegate(fadd with const).
5600   // -(x + 2.0) = -2.0 - x
5601   InstructionFoldingCase<bool>(
5602     Header() +
5603       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5604       "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5605       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5606       "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
5607       "%main = OpFunction %void None %void_func\n" +
5608       "%main_lab = OpLabel\n" +
5609       "%var = OpVariable %_ptr_float Function\n" +
5610       "%2 = OpLoad %float %var\n" +
5611       "%3 = OpFAdd %float %2 %float_2\n" +
5612       "%4 = OpFNegate %float %3\n" +
5613       "OpReturn\n" +
5614       "OpFunctionEnd",
5615     4, true),
5616   // Test case 7: fold fnegate(fsub with const).
5617   // -(2.0 - x) = x - 2.0
5618   InstructionFoldingCase<bool>(
5619     Header() +
5620       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5621       "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5622       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5623       "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_2]]\n" +
5624       "%main = OpFunction %void None %void_func\n" +
5625       "%main_lab = OpLabel\n" +
5626       "%var = OpVariable %_ptr_float Function\n" +
5627       "%2 = OpLoad %float %var\n" +
5628       "%3 = OpFSub %float %float_2 %2\n" +
5629       "%4 = OpFNegate %float %3\n" +
5630       "OpReturn\n" +
5631       "OpFunctionEnd",
5632     4, true),
5633   // Test case 8: fold fnegate(fsub with const).
5634   // -(x - 2.0) = 2.0 - x
5635   InstructionFoldingCase<bool>(
5636     Header() +
5637       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5638       "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5639       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5640       "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
5641       "%main = OpFunction %void None %void_func\n" +
5642       "%main_lab = OpLabel\n" +
5643       "%var = OpVariable %_ptr_float Function\n" +
5644       "%2 = OpLoad %float %var\n" +
5645       "%3 = OpFSub %float %2 %float_2\n" +
5646       "%4 = OpFNegate %float %3\n" +
5647       "OpReturn\n" +
5648       "OpFunctionEnd",
5649     4, true),
5650   // Test case 9: fold consecutive snegate
5651   // -(-x) = x
5652   InstructionFoldingCase<bool>(
5653     Header() +
5654       "; CHECK: [[ld:%\\w+]] = OpLoad [[int:%\\w+]]\n" +
5655       "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
5656       "%main = OpFunction %void None %void_func\n" +
5657       "%main_lab = OpLabel\n" +
5658       "%var = OpVariable %_ptr_int Function\n" +
5659       "%2 = OpLoad %int %var\n" +
5660       "%3 = OpSNegate %int %2\n" +
5661       "%4 = OpSNegate %int %3\n" +
5662       "OpReturn\n" +
5663       "OpFunctionEnd",
5664     4, true),
5665   // Test case 10: fold consecutive vector negate
5666   // -(-x) = x
5667   InstructionFoldingCase<bool>(
5668     Header() +
5669       "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float:%\\w+]]\n" +
5670       "; CHECK: %4 = OpCopyObject [[v2float]] [[ld]]\n" +
5671       "%main = OpFunction %void None %void_func\n" +
5672       "%main_lab = OpLabel\n" +
5673       "%var = OpVariable %_ptr_v2float Function\n" +
5674       "%2 = OpLoad %v2float %var\n" +
5675       "%3 = OpFNegate %v2float %2\n" +
5676       "%4 = OpFNegate %v2float %3\n" +
5677       "OpReturn\n" +
5678       "OpFunctionEnd",
5679     4, true),
5680   // Test case 11: fold snegate(iadd with const).
5681   // -(2 + x) = -2 - x
5682   InstructionFoldingCase<bool>(
5683     Header() +
5684       "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5685       "; CHECK: OpConstant [[int]] -2147483648\n" +
5686       "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
5687       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5688       "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
5689       "%main = OpFunction %void None %void_func\n" +
5690       "%main_lab = OpLabel\n" +
5691       "%var = OpVariable %_ptr_int Function\n" +
5692       "%2 = OpLoad %int %var\n" +
5693       "%3 = OpIAdd %int %int_2 %2\n" +
5694       "%4 = OpSNegate %int %3\n" +
5695       "OpReturn\n" +
5696       "OpFunctionEnd",
5697     4, true),
5698   // Test case 12: fold snegate(iadd with const).
5699   // -(x + 2) = -2 - x
5700   InstructionFoldingCase<bool>(
5701     Header() +
5702       "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5703       "; CHECK: OpConstant [[int]] -2147483648\n" +
5704       "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
5705       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5706       "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
5707       "%main = OpFunction %void None %void_func\n" +
5708       "%main_lab = OpLabel\n" +
5709       "%var = OpVariable %_ptr_int Function\n" +
5710       "%2 = OpLoad %int %var\n" +
5711       "%3 = OpIAdd %int %2 %int_2\n" +
5712       "%4 = OpSNegate %int %3\n" +
5713       "OpReturn\n" +
5714       "OpFunctionEnd",
5715     4, true),
5716   // Test case 13: fold snegate(isub with const).
5717   // -(2 - x) = x - 2
5718   InstructionFoldingCase<bool>(
5719     Header() +
5720       "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5721       "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
5722       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5723       "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_2]]\n" +
5724       "%main = OpFunction %void None %void_func\n" +
5725       "%main_lab = OpLabel\n" +
5726       "%var = OpVariable %_ptr_int Function\n" +
5727       "%2 = OpLoad %int %var\n" +
5728       "%3 = OpISub %int %int_2 %2\n" +
5729       "%4 = OpSNegate %int %3\n" +
5730       "OpReturn\n" +
5731       "OpFunctionEnd",
5732     4, true),
5733   // Test case 14: fold snegate(isub with const).
5734   // -(x - 2) = 2 - x
5735   InstructionFoldingCase<bool>(
5736     Header() +
5737       "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5738       "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
5739       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5740       "; CHECK: %4 = OpISub [[int]] [[int_2]] [[ld]]\n" +
5741       "%main = OpFunction %void None %void_func\n" +
5742       "%main_lab = OpLabel\n" +
5743       "%var = OpVariable %_ptr_int Function\n" +
5744       "%2 = OpLoad %int %var\n" +
5745       "%3 = OpISub %int %2 %int_2\n" +
5746       "%4 = OpSNegate %int %3\n" +
5747       "OpReturn\n" +
5748       "OpFunctionEnd",
5749     4, true),
5750   // Test case 15: fold snegate(iadd with const).
5751   // -(x + 2) = -2 - x
5752   InstructionFoldingCase<bool>(
5753     Header() +
5754       "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5755       "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
5756       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5757       "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
5758       "%main = OpFunction %void None %void_func\n" +
5759       "%main_lab = OpLabel\n" +
5760       "%var = OpVariable %_ptr_long Function\n" +
5761       "%2 = OpLoad %long %var\n" +
5762       "%3 = OpIAdd %long %2 %long_2\n" +
5763       "%4 = OpSNegate %long %3\n" +
5764       "OpReturn\n" +
5765       "OpFunctionEnd",
5766     4, true),
5767   // Test case 16: fold snegate(isub with const).
5768   // -(2 - x) = x - 2
5769   InstructionFoldingCase<bool>(
5770     Header() +
5771       "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5772       "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5773       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5774       "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_2]]\n" +
5775       "%main = OpFunction %void None %void_func\n" +
5776       "%main_lab = OpLabel\n" +
5777       "%var = OpVariable %_ptr_long Function\n" +
5778       "%2 = OpLoad %long %var\n" +
5779       "%3 = OpISub %long %long_2 %2\n" +
5780       "%4 = OpSNegate %long %3\n" +
5781       "OpReturn\n" +
5782       "OpFunctionEnd",
5783     4, true),
5784   // Test case 17: fold snegate(isub with const).
5785   // -(x - 2) = 2 - x
5786   InstructionFoldingCase<bool>(
5787     Header() +
5788       "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5789       "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5790       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5791       "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
5792       "%main = OpFunction %void None %void_func\n" +
5793       "%main_lab = OpLabel\n" +
5794       "%var = OpVariable %_ptr_long Function\n" +
5795       "%2 = OpLoad %long %var\n" +
5796       "%3 = OpISub %long %2 %long_2\n" +
5797       "%4 = OpSNegate %long %3\n" +
5798       "OpReturn\n" +
5799       "OpFunctionEnd",
5800     4, true),
5801     // Test case 18: fold -vec4(-1.0, 2.0, 1.0, 3.0)
5802     InstructionFoldingCase<bool>(
5803         Header() +
5804       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5805       "; CHECK: [[v4float:%\\w+]] = OpTypeVector [[float]] 4{{[[:space:]]}}\n" +
5806       "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1{{[[:space:]]}}\n" +
5807       "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1{{[[:space:]]}}\n" +
5808       "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5809       "; CHECK: [[float_n3:%\\w+]] = OpConstant [[float]] -3{{[[:space:]]}}\n" +
5810       "; CHECK: [[v4float_1_n2_n1_n3:%\\w+]] = OpConstantComposite [[v4float]] [[float_1]] [[float_n2]] [[float_n1]] [[float_n3]]\n" +
5811       "; CHECK: %2 = OpCopyObject [[v4float]] [[v4float_1_n2_n1_n3]]\n" +
5812         "%main = OpFunction %void None %void_func\n" +
5813             "%main_lab = OpLabel\n" +
5814             "%2 = OpFNegate %v4float %v4float_n1_2_1_3\n" +
5815             "OpReturn\n" +
5816             "OpFunctionEnd",
5817         2, true),
5818     // Test case 19: fold vector fnegate with null
5819     InstructionFoldingCase<bool>(
5820         Header() +
5821       "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5822       "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
5823       "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" +
5824       "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_n0]] [[double_n0]]\n" +
5825       "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
5826         "%main = OpFunction %void None %void_func\n" +
5827             "%main_lab = OpLabel\n" +
5828             "%2 = OpFNegate %v2double %v2double_null\n" +
5829             "OpReturn\n" +
5830             "OpFunctionEnd",
5831         2, true)
5832 ));
5833 
5834 INSTANTIATE_TEST_SUITE_P(ReciprocalFDivTest, MatchingInstructionFoldingTest,
5835 ::testing::Values(
5836   // Test case 0: scalar reicprocal
5837   // x / 0.5 = x * 2.0
5838   InstructionFoldingCase<bool>(
5839     Header() +
5840       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5841       "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5842       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5843       "; CHECK: %3 = OpFMul [[float]] [[ld]] [[float_2]]\n" +
5844       "%main = OpFunction %void None %void_func\n" +
5845       "%main_lab = OpLabel\n" +
5846       "%var = OpVariable %_ptr_float Function\n" +
5847       "%2 = OpLoad %float %var\n" +
5848       "%3 = OpFDiv %float %2 %float_0p5\n" +
5849       "OpReturn\n" +
5850       "OpFunctionEnd\n",
5851     3, true),
5852   // Test case 1: Unfoldable
5853   InstructionFoldingCase<bool>(
5854     Header() +
5855       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5856       "; CHECK: [[float_0:%\\w+]] = OpConstant [[float]] 0\n" +
5857       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5858       "; CHECK: %3 = OpFDiv [[float]] [[ld]] [[float_0]]\n" +
5859       "%main = OpFunction %void None %void_func\n" +
5860       "%main_lab = OpLabel\n" +
5861       "%var = OpVariable %_ptr_float Function\n" +
5862       "%2 = OpLoad %float %var\n" +
5863       "%3 = OpFDiv %float %2 %104\n" +
5864       "OpReturn\n" +
5865       "OpFunctionEnd\n",
5866     3, false),
5867   // Test case 2: Vector reciprocal
5868   // x / {2.0, 0.5} = x * {0.5, 2.0}
5869   InstructionFoldingCase<bool>(
5870     Header() +
5871       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5872       "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
5873       "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5874       "; CHECK: [[float_0p5:%\\w+]] = OpConstant [[float]] 0.5\n" +
5875       "; CHECK: [[v2float_0p5_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_0p5]] [[float_2]]\n" +
5876       "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
5877       "; CHECK: %3 = OpFMul [[v2float]] [[ld]] [[v2float_0p5_2]]\n" +
5878       "%main = OpFunction %void None %void_func\n" +
5879       "%main_lab = OpLabel\n" +
5880       "%var = OpVariable %_ptr_v2float Function\n" +
5881       "%2 = OpLoad %v2float %var\n" +
5882       "%3 = OpFDiv %v2float %2 %v2float_2_0p5\n" +
5883       "OpReturn\n" +
5884       "OpFunctionEnd\n",
5885     3, true),
5886   // Test case 3: double reciprocal
5887   // x / 2.0 = x * 0.5
5888   InstructionFoldingCase<bool>(
5889     Header() +
5890       "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5891       "; CHECK: [[double_0p5:%\\w+]] = OpConstant [[double]] 0.5\n" +
5892       "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
5893       "; CHECK: %3 = OpFMul [[double]] [[ld]] [[double_0p5]]\n" +
5894       "%main = OpFunction %void None %void_func\n" +
5895       "%main_lab = OpLabel\n" +
5896       "%var = OpVariable %_ptr_double Function\n" +
5897       "%2 = OpLoad %double %var\n" +
5898       "%3 = OpFDiv %double %2 %double_2\n" +
5899       "OpReturn\n" +
5900       "OpFunctionEnd\n",
5901     3, true),
5902   // Test case 4: don't fold x / 0.
5903   InstructionFoldingCase<bool>(
5904     Header() +
5905       "%main = OpFunction %void None %void_func\n" +
5906       "%main_lab = OpLabel\n" +
5907       "%var = OpVariable %_ptr_v2float Function\n" +
5908       "%2 = OpLoad %v2float %var\n" +
5909       "%3 = OpFDiv %v2float %2 %v2float_null\n" +
5910       "OpReturn\n" +
5911       "OpFunctionEnd\n",
5912     3, false)
5913 ));
5914 
5915 INSTANTIATE_TEST_SUITE_P(MergeMulTest, MatchingInstructionFoldingTest,
5916 ::testing::Values(
5917   // Test case 0: fold consecutive fmuls
5918   // (x * 3.0) * 2.0 = x * 6.0
5919   InstructionFoldingCase<bool>(
5920     Header() +
5921       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5922       "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5923       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5924       "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
5925       "%main = OpFunction %void None %void_func\n" +
5926       "%main_lab = OpLabel\n" +
5927       "%var = OpVariable %_ptr_float Function\n" +
5928       "%2 = OpLoad %float %var\n" +
5929       "%3 = OpFMul %float %2 %float_3\n" +
5930       "%4 = OpFMul %float %3 %float_2\n" +
5931       "OpReturn\n" +
5932       "OpFunctionEnd\n",
5933     4, true),
5934   // Test case 1: fold consecutive fmuls
5935   // 2.0 * (x * 3.0) = x * 6.0
5936   InstructionFoldingCase<bool>(
5937     Header() +
5938       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5939       "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5940       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5941       "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
5942       "%main = OpFunction %void None %void_func\n" +
5943       "%main_lab = OpLabel\n" +
5944       "%var = OpVariable %_ptr_float Function\n" +
5945       "%2 = OpLoad %float %var\n" +
5946       "%3 = OpFMul %float %2 %float_3\n" +
5947       "%4 = OpFMul %float %float_2 %3\n" +
5948       "OpReturn\n" +
5949       "OpFunctionEnd\n",
5950     4, true),
5951   // Test case 2: fold consecutive fmuls
5952   // (3.0 * x) * 2.0 = x * 6.0
5953   InstructionFoldingCase<bool>(
5954     Header() +
5955       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5956       "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5957       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5958       "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
5959       "%main = OpFunction %void None %void_func\n" +
5960       "%main_lab = OpLabel\n" +
5961       "%var = OpVariable %_ptr_float Function\n" +
5962       "%2 = OpLoad %float %var\n" +
5963       "%3 = OpFMul %float %float_3 %2\n" +
5964       "%4 = OpFMul %float %float_2 %3\n" +
5965       "OpReturn\n" +
5966       "OpFunctionEnd\n",
5967     4, true),
5968   // Test case 3: fold vector fmul
5969   InstructionFoldingCase<bool>(
5970     Header() +
5971       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5972       "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
5973       "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5974       "; CHECK: [[v2float_6_6:%\\w+]] = OpConstantComposite [[v2float]] [[float_6]] [[float_6]]\n" +
5975       "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
5976       "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_6_6]]\n" +
5977       "%main = OpFunction %void None %void_func\n" +
5978       "%main_lab = OpLabel\n" +
5979       "%var = OpVariable %_ptr_v2float Function\n" +
5980       "%2 = OpLoad %v2float %var\n" +
5981       "%3 = OpFMul %v2float %2 %v2float_2_3\n" +
5982       "%4 = OpFMul %v2float %3 %v2float_3_2\n" +
5983       "OpReturn\n" +
5984       "OpFunctionEnd\n",
5985     4, true),
5986   // Test case 4: fold double fmuls
5987   // (x * 3.0) * 2.0 = x * 6.0
5988   InstructionFoldingCase<bool>(
5989     Header() +
5990       "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5991       "; CHECK: [[double_6:%\\w+]] = OpConstant [[double]] 6\n" +
5992       "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
5993       "; CHECK: %4 = OpFMul [[double]] [[ld]] [[double_6]]\n" +
5994       "%main = OpFunction %void None %void_func\n" +
5995       "%main_lab = OpLabel\n" +
5996       "%var = OpVariable %_ptr_double Function\n" +
5997       "%2 = OpLoad %double %var\n" +
5998       "%3 = OpFMul %double %2 %double_3\n" +
5999       "%4 = OpFMul %double %3 %double_2\n" +
6000       "OpReturn\n" +
6001       "OpFunctionEnd\n",
6002     4, true),
6003   // Test case 5: fold 32 bit imuls
6004   // (x * 3) * 2 = x * 6
6005   InstructionFoldingCase<bool>(
6006     Header() +
6007       "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6008       "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
6009       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6010       "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_6]]\n" +
6011       "%main = OpFunction %void None %void_func\n" +
6012       "%main_lab = OpLabel\n" +
6013       "%var = OpVariable %_ptr_int Function\n" +
6014       "%2 = OpLoad %int %var\n" +
6015       "%3 = OpIMul %int %2 %int_3\n" +
6016       "%4 = OpIMul %int %3 %int_2\n" +
6017       "OpReturn\n" +
6018       "OpFunctionEnd\n",
6019     4, true),
6020   // Test case 6: fold 64 bit imuls
6021   // (x * 3) * 2 = x * 6
6022   InstructionFoldingCase<bool>(
6023     Header() +
6024       "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6025       "; CHECK: [[long_6:%\\w+]] = OpConstant [[long]] 6\n" +
6026       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6027       "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_6]]\n" +
6028       "%main = OpFunction %void None %void_func\n" +
6029       "%main_lab = OpLabel\n" +
6030       "%var = OpVariable %_ptr_long Function\n" +
6031       "%2 = OpLoad %long %var\n" +
6032       "%3 = OpIMul %long %2 %long_3\n" +
6033       "%4 = OpIMul %long %3 %long_2\n" +
6034       "OpReturn\n" +
6035       "OpFunctionEnd\n",
6036     4, true),
6037   // Test case 7: merge vector integer mults
6038   InstructionFoldingCase<bool>(
6039     Header() +
6040       "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6041       "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
6042       "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
6043       "; CHECK: [[v2int_6_6:%\\w+]] = OpConstantComposite [[v2int]] [[int_6]] [[int_6]]\n" +
6044       "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
6045       "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_6_6]]\n" +
6046       "%main = OpFunction %void None %void_func\n" +
6047       "%main_lab = OpLabel\n" +
6048       "%var = OpVariable %_ptr_v2int Function\n" +
6049       "%2 = OpLoad %v2int %var\n" +
6050       "%3 = OpIMul %v2int %2 %v2int_2_3\n" +
6051       "%4 = OpIMul %v2int %3 %v2int_3_2\n" +
6052       "OpReturn\n" +
6053       "OpFunctionEnd\n",
6054     4, true),
6055   // Test case 8: merge fmul of fdiv
6056   // 2.0 * (2.0 / x) = 4.0 / x
6057   InstructionFoldingCase<bool>(
6058     Header() +
6059       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6060       "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
6061       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6062       "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
6063       "%main = OpFunction %void None %void_func\n" +
6064       "%main_lab = OpLabel\n" +
6065       "%var = OpVariable %_ptr_float Function\n" +
6066       "%2 = OpLoad %float %var\n" +
6067       "%3 = OpFDiv %float %float_2 %2\n" +
6068       "%4 = OpFMul %float %float_2 %3\n" +
6069       "OpReturn\n" +
6070       "OpFunctionEnd\n",
6071     4, true),
6072   // Test case 9: merge fmul of fdiv
6073   // (2.0 / x) * 2.0 = 4.0 / x
6074   InstructionFoldingCase<bool>(
6075     Header() +
6076       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6077       "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
6078       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6079       "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
6080       "%main = OpFunction %void None %void_func\n" +
6081       "%main_lab = OpLabel\n" +
6082       "%var = OpVariable %_ptr_float Function\n" +
6083       "%2 = OpLoad %float %var\n" +
6084       "%3 = OpFDiv %float %float_2 %2\n" +
6085       "%4 = OpFMul %float %3 %float_2\n" +
6086       "OpReturn\n" +
6087       "OpFunctionEnd\n",
6088     4, true),
6089   // Test case 10: Do not merge imul of sdiv
6090   // 4 * (x / 2)
6091   InstructionFoldingCase<bool>(
6092     Header() +
6093       "%main = OpFunction %void None %void_func\n" +
6094       "%main_lab = OpLabel\n" +
6095       "%var = OpVariable %_ptr_int Function\n" +
6096       "%2 = OpLoad %int %var\n" +
6097       "%3 = OpSDiv %int %2 %int_2\n" +
6098       "%4 = OpIMul %int %int_4 %3\n" +
6099       "OpReturn\n" +
6100       "OpFunctionEnd\n",
6101     4, false),
6102   // Test case 11: Do not merge imul of sdiv
6103   // (x / 2) * 4
6104   InstructionFoldingCase<bool>(
6105     Header() +
6106       "%main = OpFunction %void None %void_func\n" +
6107       "%main_lab = OpLabel\n" +
6108       "%var = OpVariable %_ptr_int Function\n" +
6109       "%2 = OpLoad %int %var\n" +
6110       "%3 = OpSDiv %int %2 %int_2\n" +
6111       "%4 = OpIMul %int %3 %int_4\n" +
6112       "OpReturn\n" +
6113       "OpFunctionEnd\n",
6114     4, false),
6115   // Test case 12: Do not merge imul of udiv
6116   // 4 * (x / 2)
6117   InstructionFoldingCase<bool>(
6118     Header() +
6119       "%main = OpFunction %void None %void_func\n" +
6120       "%main_lab = OpLabel\n" +
6121       "%var = OpVariable %_ptr_uint Function\n" +
6122       "%2 = OpLoad %uint %var\n" +
6123       "%3 = OpUDiv %uint %2 %uint_2\n" +
6124       "%4 = OpIMul %uint %uint_4 %3\n" +
6125       "OpReturn\n" +
6126       "OpFunctionEnd\n",
6127     4, false),
6128   // Test case 13: Do not merge imul of udiv
6129   // (x / 2) * 4
6130   InstructionFoldingCase<bool>(
6131     Header() +
6132       "%main = OpFunction %void None %void_func\n" +
6133       "%main_lab = OpLabel\n" +
6134       "%var = OpVariable %_ptr_uint Function\n" +
6135       "%2 = OpLoad %uint %var\n" +
6136       "%3 = OpUDiv %uint %2 %uint_2\n" +
6137       "%4 = OpIMul %uint %3 %uint_4\n" +
6138       "OpReturn\n" +
6139       "OpFunctionEnd\n",
6140     4, false),
6141   // Test case 14: Don't fold
6142   // (x / 3) * 4
6143   InstructionFoldingCase<bool>(
6144     Header() +
6145       "%main = OpFunction %void None %void_func\n" +
6146       "%main_lab = OpLabel\n" +
6147       "%var = OpVariable %_ptr_uint Function\n" +
6148       "%2 = OpLoad %uint %var\n" +
6149       "%3 = OpUDiv %uint %2 %uint_3\n" +
6150       "%4 = OpIMul %uint %3 %uint_4\n" +
6151       "OpReturn\n" +
6152       "OpFunctionEnd\n",
6153     4, false),
6154   // Test case 15: merge vector fmul of fdiv
6155   // (x / {2,2}) * {4,4} = x * {2,2}
6156   InstructionFoldingCase<bool>(
6157     Header() +
6158       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6159       "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6160       "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6161       "; CHECK: [[v2float_2_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_2]] [[float_2]]\n" +
6162       "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
6163       "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_2_2]]\n" +
6164       "%main = OpFunction %void None %void_func\n" +
6165       "%main_lab = OpLabel\n" +
6166       "%var = OpVariable %_ptr_v2float Function\n" +
6167       "%2 = OpLoad %v2float %var\n" +
6168       "%3 = OpFDiv %v2float %2 %v2float_2_2\n" +
6169       "%4 = OpFMul %v2float %3 %v2float_4_4\n" +
6170       "OpReturn\n" +
6171       "OpFunctionEnd\n",
6172     4, true),
6173   // Test case 16: merge vector imul of snegate
6174   // (-x) * {2,2} = x * {-2,-2}
6175   InstructionFoldingCase<bool>(
6176     Header() +
6177       "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6178       "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
6179       "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
6180       "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
6181       "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
6182       "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
6183       "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
6184       "%main = OpFunction %void None %void_func\n" +
6185       "%main_lab = OpLabel\n" +
6186       "%var = OpVariable %_ptr_v2int Function\n" +
6187       "%2 = OpLoad %v2int %var\n" +
6188       "%3 = OpSNegate %v2int %2\n" +
6189       "%4 = OpIMul %v2int %3 %v2int_2_2\n" +
6190       "OpReturn\n" +
6191       "OpFunctionEnd\n",
6192     4, true),
6193   // Test case 17: merge vector imul of snegate
6194   // {2,2} * (-x) = x * {-2,-2}
6195   InstructionFoldingCase<bool>(
6196     Header() +
6197       "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6198       "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
6199       "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
6200       "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
6201       "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
6202       "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
6203       "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
6204       "%main = OpFunction %void None %void_func\n" +
6205       "%main_lab = OpLabel\n" +
6206       "%var = OpVariable %_ptr_v2int Function\n" +
6207       "%2 = OpLoad %v2int %var\n" +
6208       "%3 = OpSNegate %v2int %2\n" +
6209       "%4 = OpIMul %v2int %v2int_2_2 %3\n" +
6210       "OpReturn\n" +
6211       "OpFunctionEnd\n",
6212     4, true),
6213   // Test case 18: Fold OpVectorTimesScalar
6214   // {4,4} = OpVectorTimesScalar v2float {2,2} 2
6215   InstructionFoldingCase<bool>(
6216     Header() +
6217       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6218       "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6219       "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
6220       "; CHECK: [[v2float_4_4:%\\w+]] = OpConstantComposite [[v2float]] [[float_4]] [[float_4]]\n" +
6221       "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_4_4]]\n" +
6222       "%main = OpFunction %void None %void_func\n" +
6223       "%main_lab = OpLabel\n" +
6224       "%2 = OpVectorTimesScalar %v2float %v2float_2_2 %float_2\n" +
6225       "OpReturn\n" +
6226       "OpFunctionEnd",
6227     2, true),
6228   // Test case 19: Fold OpVectorTimesScalar
6229   // {0,0} = OpVectorTimesScalar v2float v2float_null -1
6230   InstructionFoldingCase<bool>(
6231     Header() +
6232       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6233       "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6234       "; CHECK: [[v2float_null:%\\w+]] = OpConstantNull [[v2float]]\n" +
6235       "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_null]]\n" +
6236       "%main = OpFunction %void None %void_func\n" +
6237       "%main_lab = OpLabel\n" +
6238       "%2 = OpVectorTimesScalar %v2float %v2float_null %float_n1\n" +
6239       "OpReturn\n" +
6240       "OpFunctionEnd",
6241     2, true),
6242   // Test case 20: Fold OpVectorTimesScalar
6243   // {4,4} = OpVectorTimesScalar v2double {2,2} 2
6244   InstructionFoldingCase<bool>(
6245     Header() +
6246       "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6247       "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6248       "; CHECK: [[double_4:%\\w+]] = OpConstant [[double]] 4\n" +
6249       "; CHECK: [[v2double_4_4:%\\w+]] = OpConstantComposite [[v2double]] [[double_4]] [[double_4]]\n" +
6250       "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_4_4]]\n" +
6251       "%main = OpFunction %void None %void_func\n" +
6252       "%main_lab = OpLabel\n" +
6253       "%2 = OpVectorTimesScalar %v2double %v2double_2_2 %double_2\n" +
6254       "OpReturn\n" +
6255       "OpFunctionEnd",
6256     2, true),
6257   // Test case 21: Fold OpVectorTimesScalar
6258   // {0,0} = OpVectorTimesScalar v2double {0,0} n
6259   InstructionFoldingCase<bool>(
6260     Header() +
6261         "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6262         "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6263         "; CHECK: {{%\\w+}} = OpConstant [[double]] 0\n" +
6264         "; CHECK: [[double_0:%\\w+]] = OpConstant [[double]] 0\n" +
6265         "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_0]] [[double_0]]\n" +
6266         "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
6267         "%main = OpFunction %void None %void_func\n" +
6268         "%main_lab = OpLabel\n" +
6269         "%n = OpVariable %_ptr_double Function\n" +
6270         "%load = OpLoad %double %n\n" +
6271         "%2 = OpVectorTimesScalar %v2double %v2double_0_0 %load\n" +
6272         "OpReturn\n" +
6273         "OpFunctionEnd",
6274     2, true),
6275   // Test case 22: Fold OpVectorTimesScalar
6276   // {0,0} = OpVectorTimesScalar v2double n 0
6277   InstructionFoldingCase<bool>(
6278     Header() +
6279         "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6280         "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6281         "; CHECK: [[v2double_null:%\\w+]] = OpConstantNull [[v2double]]\n" +
6282         "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_null]]\n" +
6283         "%main = OpFunction %void None %void_func\n" +
6284         "%main_lab = OpLabel\n" +
6285         "%n = OpVariable %_ptr_v2double Function\n" +
6286         "%load = OpLoad %v2double %n\n" +
6287         "%2 = OpVectorTimesScalar %v2double %load %double_0\n" +
6288         "OpReturn\n" +
6289         "OpFunctionEnd",
6290     2, true),
6291   // Test case 23: merge fmul of fdiv
6292   // x * (y / x) = y
6293   InstructionFoldingCase<bool>(
6294     Header() +
6295         "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6296         "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6297         "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6298         "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6299         "%main = OpFunction %void None %void_func\n" +
6300         "%main_lab = OpLabel\n" +
6301         "%x = OpVariable %_ptr_float Function\n" +
6302         "%y = OpVariable %_ptr_float Function\n" +
6303         "%2 = OpLoad %float %x\n" +
6304         "%3 = OpLoad %float %y\n" +
6305         "%4 = OpFDiv %float %3 %2\n" +
6306         "%5 = OpFMul %float %2 %4\n" +
6307         "OpReturn\n" +
6308         "OpFunctionEnd\n",
6309     5, true),
6310   // Test case 24: merge fmul of fdiv
6311   // (y / x) * x = y
6312   InstructionFoldingCase<bool>(
6313     Header() +
6314         "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6315         "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6316         "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6317         "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6318         "%main = OpFunction %void None %void_func\n" +
6319         "%main_lab = OpLabel\n" +
6320         "%x = OpVariable %_ptr_float Function\n" +
6321         "%y = OpVariable %_ptr_float Function\n" +
6322         "%2 = OpLoad %float %x\n" +
6323         "%3 = OpLoad %float %y\n" +
6324         "%4 = OpFDiv %float %3 %2\n" +
6325         "%5 = OpFMul %float %4 %2\n" +
6326         "OpReturn\n" +
6327         "OpFunctionEnd\n",
6328     5, true),
6329   // Test case 25: fold overflowing signed 32 bit imuls
6330   // (x * 1073741824) * 2 = x * int_min
6331   InstructionFoldingCase<bool>(
6332     Header() +
6333       "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
6334       "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
6335       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6336       "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_min]]\n" +
6337       "%main = OpFunction %void None %void_func\n" +
6338       "%main_lab = OpLabel\n" +
6339       "%var = OpVariable %_ptr_int Function\n" +
6340       "%2 = OpLoad %int %var\n" +
6341       "%3 = OpIMul %int %2 %int_1073741824\n" +
6342       "%4 = OpIMul %int %3 %int_2\n" +
6343       "OpReturn\n" +
6344       "OpFunctionEnd\n",
6345     4, true),
6346   // Test case 26: fold overflowing signed 64 bit imuls
6347   // (x * 4611686018427387904) * 2 = x * long_min
6348   InstructionFoldingCase<bool>(
6349     Header() +
6350       "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6351       "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
6352       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6353       "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_min]]\n" +
6354       "%main = OpFunction %void None %void_func\n" +
6355       "%main_lab = OpLabel\n" +
6356       "%var = OpVariable %_ptr_long Function\n" +
6357       "%2 = OpLoad %long %var\n" +
6358       "%3 = OpIMul %long %2 %long_4611686018427387904\n" +
6359       "%4 = OpIMul %long %3 %long_2\n" +
6360       "OpReturn\n" +
6361       "OpFunctionEnd\n",
6362     4, true),
6363   // Test case 27: fold overflowing 32 bit unsigned imuls
6364   // (x * 2147483649) * 2 = x * 2
6365   InstructionFoldingCase<bool>(
6366     Header() +
6367       "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
6368       "; CHECK: [[uint_2:%\\w+]] = OpConstant [[uint]] 2\n" +
6369       "; CHECK: [[ld:%\\w+]] = OpLoad [[uint]]\n" +
6370       "; CHECK: %4 = OpIMul [[uint]] [[ld]] [[uint_2]]\n" +
6371       "%main = OpFunction %void None %void_func\n" +
6372       "%main_lab = OpLabel\n" +
6373       "%var = OpVariable %_ptr_uint Function\n" +
6374       "%2 = OpLoad %uint %var\n" +
6375       "%3 = OpIMul %uint %2 %uint_2147483649\n" +
6376       "%4 = OpIMul %uint %3 %uint_2\n" +
6377       "OpReturn\n" +
6378       "OpFunctionEnd\n",
6379     4, true),
6380   // Test case 28: fold overflowing 64 bit unsigned imuls
6381   // (x * 9223372036854775809) * 2 = x * 2
6382   InstructionFoldingCase<bool>(
6383     Header() +
6384       "; CHECK: [[ulong:%\\w+]] = OpTypeInt 64 0\n" +
6385       "; CHECK: [[ulong_2:%\\w+]] = OpConstant [[ulong]] 2\n" +
6386       "; CHECK: [[ld:%\\w+]] = OpLoad [[ulong]]\n" +
6387       "; CHECK: %4 = OpIMul [[ulong]] [[ld]] [[ulong_2]]\n" +
6388       "%main = OpFunction %void None %void_func\n" +
6389       "%main_lab = OpLabel\n" +
6390       "%var = OpVariable %_ptr_ulong Function\n" +
6391       "%2 = OpLoad %ulong %var\n" +
6392       "%3 = OpIMul %ulong %2 %ulong_9223372036854775809\n" +
6393       "%4 = OpIMul %ulong %3 %ulong_2\n" +
6394       "OpReturn\n" +
6395       "OpFunctionEnd\n",
6396     4, true),
6397   // Test case 29: fold underflowing signed 32 bit imuls
6398   // (x * (-858993459)) * 10 = x * 2
6399   InstructionFoldingCase<bool>(
6400     Header() +
6401       "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
6402       "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
6403       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6404       "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_2]]\n" +
6405       "%main = OpFunction %void None %void_func\n" +
6406       "%main_lab = OpLabel\n" +
6407       "%var = OpVariable %_ptr_int Function\n" +
6408       "%2 = OpLoad %int %var\n" +
6409       "%3 = OpIMul %int %2 %int_n858993459\n" +
6410       "%4 = OpIMul %int %3 %int_10\n" +
6411       "OpReturn\n" +
6412       "OpFunctionEnd\n",
6413     4, true),
6414   // Test case 30: fold underflowing signed 64 bit imuls
6415   // (x * (-3689348814741910323)) * 10 = x * 2
6416   InstructionFoldingCase<bool>(
6417     Header() +
6418       "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6419       "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
6420       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6421       "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_2]]\n" +
6422       "%main = OpFunction %void None %void_func\n" +
6423       "%main_lab = OpLabel\n" +
6424       "%var = OpVariable %_ptr_long Function\n" +
6425       "%2 = OpLoad %long %var\n" +
6426       "%3 = OpIMul %long %2 %long_n3689348814741910323\n" +
6427       "%4 = OpIMul %long %3 %long_10\n" +
6428       "OpReturn\n" +
6429       "OpFunctionEnd\n",
6430     4, true)
6431 ));
6432 
6433 INSTANTIATE_TEST_SUITE_P(MergeDivTest, MatchingInstructionFoldingTest,
6434 ::testing::Values(
6435   // Test case 0: merge consecutive fdiv
6436   // 4.0 / (2.0 / x) = 2.0 * x
6437   InstructionFoldingCase<bool>(
6438     Header() +
6439       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6440       "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6441       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6442       "; CHECK: %4 = OpFMul [[float]] [[float_2]] [[ld]]\n" +
6443       "%main = OpFunction %void None %void_func\n" +
6444       "%main_lab = OpLabel\n" +
6445       "%var = OpVariable %_ptr_float Function\n" +
6446       "%2 = OpLoad %float %var\n" +
6447       "%3 = OpFDiv %float %float_2 %2\n" +
6448       "%4 = OpFDiv %float %float_4 %3\n" +
6449       "OpReturn\n" +
6450       "OpFunctionEnd\n",
6451     4, true),
6452   // Test case 1: merge consecutive fdiv
6453   // 4.0 / (x / 2.0) = 8.0 / x
6454   InstructionFoldingCase<bool>(
6455     Header() +
6456       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6457       "; CHECK: [[float_8:%\\w+]] = OpConstant [[float]] 8\n" +
6458       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6459       "; CHECK: %4 = OpFDiv [[float]] [[float_8]] [[ld]]\n" +
6460       "%main = OpFunction %void None %void_func\n" +
6461       "%main_lab = OpLabel\n" +
6462       "%var = OpVariable %_ptr_float Function\n" +
6463       "%2 = OpLoad %float %var\n" +
6464       "%3 = OpFDiv %float %2 %float_2\n" +
6465       "%4 = OpFDiv %float %float_4 %3\n" +
6466       "OpReturn\n" +
6467       "OpFunctionEnd\n",
6468     4, true),
6469   // Test case 2: merge consecutive fdiv
6470   // (4.0 / x) / 2.0 = 2.0 / x
6471   InstructionFoldingCase<bool>(
6472     Header() +
6473       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6474       "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6475       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6476       "; CHECK: %4 = OpFDiv [[float]] [[float_2]] [[ld]]\n" +
6477       "%main = OpFunction %void None %void_func\n" +
6478       "%main_lab = OpLabel\n" +
6479       "%var = OpVariable %_ptr_float Function\n" +
6480       "%2 = OpLoad %float %var\n" +
6481       "%3 = OpFDiv %float %float_4 %2\n" +
6482       "%4 = OpFDiv %float %3 %float_2\n" +
6483       "OpReturn\n" +
6484       "OpFunctionEnd\n",
6485     4, true),
6486   // Test case 3: Do not merge consecutive sdiv
6487   // 4 / (2 / x)
6488   InstructionFoldingCase<bool>(
6489     Header() +
6490       "%main = OpFunction %void None %void_func\n" +
6491       "%main_lab = OpLabel\n" +
6492       "%var = OpVariable %_ptr_int Function\n" +
6493       "%2 = OpLoad %int %var\n" +
6494       "%3 = OpSDiv %int %int_2 %2\n" +
6495       "%4 = OpSDiv %int %int_4 %3\n" +
6496       "OpReturn\n" +
6497       "OpFunctionEnd\n",
6498     4, false),
6499   // Test case 4: Do not merge consecutive sdiv
6500   // 4 / (x / 2)
6501   InstructionFoldingCase<bool>(
6502     Header() +
6503       "%main = OpFunction %void None %void_func\n" +
6504       "%main_lab = OpLabel\n" +
6505       "%var = OpVariable %_ptr_int Function\n" +
6506       "%2 = OpLoad %int %var\n" +
6507       "%3 = OpSDiv %int %2 %int_2\n" +
6508       "%4 = OpSDiv %int %int_4 %3\n" +
6509       "OpReturn\n" +
6510       "OpFunctionEnd\n",
6511     4, false),
6512   // Test case 5: Do not merge consecutive sdiv
6513   // (4 / x) / 2
6514   InstructionFoldingCase<bool>(
6515     Header() +
6516       "%main = OpFunction %void None %void_func\n" +
6517       "%main_lab = OpLabel\n" +
6518       "%var = OpVariable %_ptr_int Function\n" +
6519       "%2 = OpLoad %int %var\n" +
6520       "%3 = OpSDiv %int %int_4 %2\n" +
6521       "%4 = OpSDiv %int %3 %int_2\n" +
6522       "OpReturn\n" +
6523       "OpFunctionEnd\n",
6524     4, false),
6525   // Test case 6: Do not merge consecutive sdiv
6526   // (x / 4) / 2
6527   InstructionFoldingCase<bool>(
6528     Header() +
6529       "%main = OpFunction %void None %void_func\n" +
6530       "%main_lab = OpLabel\n" +
6531       "%var = OpVariable %_ptr_int Function\n" +
6532       "%2 = OpLoad %int %var\n" +
6533       "%3 = OpSDiv %int %2 %int_4\n" +
6534       "%4 = OpSDiv %int %3 %int_2\n" +
6535       "OpReturn\n" +
6536       "OpFunctionEnd\n",
6537     4, false),
6538   // Test case 7: Do not merge sdiv of imul
6539   // 4 / (2 * x)
6540   InstructionFoldingCase<bool>(
6541     Header() +
6542       "%main = OpFunction %void None %void_func\n" +
6543       "%main_lab = OpLabel\n" +
6544       "%var = OpVariable %_ptr_int Function\n" +
6545       "%2 = OpLoad %int %var\n" +
6546       "%3 = OpIMul %int %int_2 %2\n" +
6547       "%4 = OpSDiv %int %int_4 %3\n" +
6548       "OpReturn\n" +
6549       "OpFunctionEnd\n",
6550     4, false),
6551   // Test case 8: Do not merge sdiv of imul
6552   // 4 / (x * 2)
6553   InstructionFoldingCase<bool>(
6554     Header() +
6555       "%main = OpFunction %void None %void_func\n" +
6556       "%main_lab = OpLabel\n" +
6557       "%var = OpVariable %_ptr_int Function\n" +
6558       "%2 = OpLoad %int %var\n" +
6559       "%3 = OpIMul %int %2 %int_2\n" +
6560       "%4 = OpSDiv %int %int_4 %3\n" +
6561       "OpReturn\n" +
6562       "OpFunctionEnd\n",
6563     4, false),
6564   // Test case 9: Do not merge sdiv of imul
6565   // (4 * x) / 2
6566   InstructionFoldingCase<bool>(
6567     Header() +
6568       "%main = OpFunction %void None %void_func\n" +
6569       "%main_lab = OpLabel\n" +
6570       "%var = OpVariable %_ptr_int Function\n" +
6571       "%2 = OpLoad %int %var\n" +
6572       "%3 = OpIMul %int %int_4 %2\n" +
6573       "%4 = OpSDiv %int %3 %int_2\n" +
6574       "OpReturn\n" +
6575       "OpFunctionEnd\n",
6576     4, false),
6577   // Test case 10: Do not merge sdiv of imul
6578   // (x * 4) / 2
6579   InstructionFoldingCase<bool>(
6580     Header() +
6581       "%main = OpFunction %void None %void_func\n" +
6582       "%main_lab = OpLabel\n" +
6583       "%var = OpVariable %_ptr_int Function\n" +
6584       "%2 = OpLoad %int %var\n" +
6585       "%3 = OpIMul %int %2 %int_4\n" +
6586       "%4 = OpSDiv %int %3 %int_2\n" +
6587       "OpReturn\n" +
6588       "OpFunctionEnd\n",
6589     4, false),
6590   // Test case 11: Do not merge sdiv of snegate.  If %2 is INT_MIN, then the
6591   // sign of %3 will be the same as %2.  This cannot be accounted for in OpSDiv.
6592   // Specifically, (-INT_MIN) / 2 != INT_MIN / -2.
6593   InstructionFoldingCase<bool>(
6594     Header() +
6595       "%main = OpFunction %void None %void_func\n" +
6596       "%main_lab = OpLabel\n" +
6597       "%var = OpVariable %_ptr_int Function\n" +
6598       "%2 = OpLoad %int %var\n" +
6599       "%3 = OpSNegate %int %2\n" +
6600       "%4 = OpSDiv %int %3 %int_2\n" +
6601       "OpReturn\n" +
6602       "OpFunctionEnd\n",
6603     4, false),
6604   // Test case 12: Do not merge sdiv of snegate.  If %2 is INT_MIN, then the
6605   // sign of %3 will be the same as %2.  This cannot be accounted for in OpSDiv.
6606   // Specifically, 2 / (-INT_MIN) != -2 / INT_MIN.
6607   InstructionFoldingCase<bool>(
6608     Header() +
6609       "%main = OpFunction %void None %void_func\n" +
6610       "%main_lab = OpLabel\n" +
6611       "%var = OpVariable %_ptr_int Function\n" +
6612       "%2 = OpLoad %int %var\n" +
6613       "%3 = OpSNegate %int %2\n" +
6614       "%4 = OpSDiv %int %int_2 %3\n" +
6615       "OpReturn\n" +
6616       "OpFunctionEnd\n",
6617     4, false),
6618   // Test case 13: Don't merge
6619   // (x / {null}) / {null}
6620   InstructionFoldingCase<bool>(
6621     Header() +
6622       "%main = OpFunction %void None %void_func\n" +
6623       "%main_lab = OpLabel\n" +
6624       "%var = OpVariable %_ptr_v2float Function\n" +
6625       "%2 = OpLoad %float %var\n" +
6626       "%3 = OpFDiv %float %2 %v2float_null\n" +
6627       "%4 = OpFDiv %float %3 %v2float_null\n" +
6628       "OpReturn\n" +
6629       "OpFunctionEnd\n",
6630     4, false),
6631   // Test case 14: merge fmul of fdiv
6632   // (y * x) / x = y
6633   InstructionFoldingCase<bool>(
6634     Header() +
6635         "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6636         "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6637         "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6638         "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6639         "%main = OpFunction %void None %void_func\n" +
6640         "%main_lab = OpLabel\n" +
6641         "%x = OpVariable %_ptr_float Function\n" +
6642         "%y = OpVariable %_ptr_float Function\n" +
6643         "%2 = OpLoad %float %x\n" +
6644         "%3 = OpLoad %float %y\n" +
6645         "%4 = OpFMul %float %3 %2\n" +
6646         "%5 = OpFDiv %float %4 %2\n" +
6647         "OpReturn\n" +
6648         "OpFunctionEnd\n",
6649     5, true),
6650   // Test case 15: merge fmul of fdiv
6651   // (x * y) / x = y
6652   InstructionFoldingCase<bool>(
6653     Header() +
6654         "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6655         "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6656         "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6657         "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6658         "%main = OpFunction %void None %void_func\n" +
6659         "%main_lab = OpLabel\n" +
6660         "%x = OpVariable %_ptr_float Function\n" +
6661         "%y = OpVariable %_ptr_float Function\n" +
6662         "%2 = OpLoad %float %x\n" +
6663         "%3 = OpLoad %float %y\n" +
6664         "%4 = OpFMul %float %2 %3\n" +
6665         "%5 = OpFDiv %float %4 %2\n" +
6666         "OpReturn\n" +
6667         "OpFunctionEnd\n",
6668     5, true),
6669   // Test case 16: Do not merge udiv of snegate
6670   // (-x) / 2u
6671   InstructionFoldingCase<bool>(
6672     Header() +
6673       "%main = OpFunction %void None %void_func\n" +
6674       "%main_lab = OpLabel\n" +
6675       "%var = OpVariable %_ptr_uint Function\n" +
6676       "%2 = OpLoad %uint %var\n" +
6677       "%3 = OpSNegate %uint %2\n" +
6678       "%4 = OpUDiv %uint %3 %uint_2\n" +
6679       "OpReturn\n" +
6680       "OpFunctionEnd\n",
6681     4, false),
6682   // Test case 17: Do not merge udiv of snegate
6683   // 2u / (-x)
6684   InstructionFoldingCase<bool>(
6685     Header() +
6686       "%main = OpFunction %void None %void_func\n" +
6687       "%main_lab = OpLabel\n" +
6688       "%var = OpVariable %_ptr_uint Function\n" +
6689       "%2 = OpLoad %uint %var\n" +
6690       "%3 = OpSNegate %uint %2\n" +
6691       "%4 = OpUDiv %uint %uint_2 %3\n" +
6692       "OpReturn\n" +
6693       "OpFunctionEnd\n",
6694     4, false)
6695 ));
6696 
6697 INSTANTIATE_TEST_SUITE_P(MergeAddTest, MatchingInstructionFoldingTest,
6698 ::testing::Values(
6699   // Test case 0: merge add of negate
6700   // (-x) + 2 = 2 - x
6701   InstructionFoldingCase<bool>(
6702     Header() +
6703       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6704       "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6705       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6706       "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
6707       "%main = OpFunction %void None %void_func\n" +
6708       "%main_lab = OpLabel\n" +
6709       "%var = OpVariable %_ptr_float Function\n" +
6710       "%2 = OpLoad %float %var\n" +
6711       "%3 = OpFNegate %float %2\n" +
6712       "%4 = OpFAdd %float %3 %float_2\n" +
6713       "OpReturn\n" +
6714       "OpFunctionEnd\n",
6715     4, true),
6716   // Test case 1: merge add of negate
6717   // 2 + (-x) = 2 - x
6718   InstructionFoldingCase<bool>(
6719     Header() +
6720       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6721       "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6722       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6723       "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
6724       "%main = OpFunction %void None %void_func\n" +
6725       "%main_lab = OpLabel\n" +
6726       "%var = OpVariable %_ptr_float Function\n" +
6727       "%2 = OpLoad %float %var\n" +
6728       "%3 = OpSNegate %float %2\n" +
6729       "%4 = OpIAdd %float %float_2 %3\n" +
6730       "OpReturn\n" +
6731       "OpFunctionEnd\n",
6732     4, true),
6733   // Test case 2: merge add of negate
6734   // (-x) + 2 = 2 - x
6735   InstructionFoldingCase<bool>(
6736     Header() +
6737       "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
6738       "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
6739       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6740       "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
6741       "%main = OpFunction %void None %void_func\n" +
6742       "%main_lab = OpLabel\n" +
6743       "%var = OpVariable %_ptr_long Function\n" +
6744       "%2 = OpLoad %long %var\n" +
6745       "%3 = OpSNegate %long %2\n" +
6746       "%4 = OpIAdd %long %3 %long_2\n" +
6747       "OpReturn\n" +
6748       "OpFunctionEnd\n",
6749     4, true),
6750   // Test case 3: merge add of negate
6751   // 2 + (-x) = 2 - x
6752   InstructionFoldingCase<bool>(
6753     Header() +
6754       "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
6755       "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
6756       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6757       "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
6758       "%main = OpFunction %void None %void_func\n" +
6759       "%main_lab = OpLabel\n" +
6760       "%var = OpVariable %_ptr_long Function\n" +
6761       "%2 = OpLoad %long %var\n" +
6762       "%3 = OpSNegate %long %2\n" +
6763       "%4 = OpIAdd %long %long_2 %3\n" +
6764       "OpReturn\n" +
6765       "OpFunctionEnd\n",
6766     4, true),
6767   // Test case 4: merge add of subtract
6768   // (x - 1) + 2 = x + 1
6769   InstructionFoldingCase<bool>(
6770     Header() +
6771       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6772       "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
6773       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6774       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
6775       "%main = OpFunction %void None %void_func\n" +
6776       "%main_lab = OpLabel\n" +
6777       "%var = OpVariable %_ptr_float Function\n" +
6778       "%2 = OpLoad %float %var\n" +
6779       "%3 = OpFSub %float %2 %float_1\n" +
6780       "%4 = OpFAdd %float %3 %float_2\n" +
6781       "OpReturn\n" +
6782       "OpFunctionEnd\n",
6783     4, true),
6784   // Test case 5: merge add of subtract
6785   // (1 - x) + 2 = 3 - x
6786   InstructionFoldingCase<bool>(
6787     Header() +
6788       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6789       "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6790       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6791       "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
6792       "%main = OpFunction %void None %void_func\n" +
6793       "%main_lab = OpLabel\n" +
6794       "%var = OpVariable %_ptr_float Function\n" +
6795       "%2 = OpLoad %float %var\n" +
6796       "%3 = OpFSub %float %float_1 %2\n" +
6797       "%4 = OpFAdd %float %3 %float_2\n" +
6798       "OpReturn\n" +
6799       "OpFunctionEnd\n",
6800     4, true),
6801   // Test case 6: merge add of subtract
6802   // 2 + (x - 1) = x + 1
6803   InstructionFoldingCase<bool>(
6804     Header() +
6805       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6806       "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
6807       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6808       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
6809       "%main = OpFunction %void None %void_func\n" +
6810       "%main_lab = OpLabel\n" +
6811       "%var = OpVariable %_ptr_float Function\n" +
6812       "%2 = OpLoad %float %var\n" +
6813       "%3 = OpFSub %float %2 %float_1\n" +
6814       "%4 = OpFAdd %float %float_2 %3\n" +
6815       "OpReturn\n" +
6816       "OpFunctionEnd\n",
6817     4, true),
6818   // Test case 7: merge add of subtract
6819   // 2 + (1 - x) = 3 - x
6820   InstructionFoldingCase<bool>(
6821     Header() +
6822       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6823       "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6824       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6825       "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
6826       "%main = OpFunction %void None %void_func\n" +
6827       "%main_lab = OpLabel\n" +
6828       "%var = OpVariable %_ptr_float Function\n" +
6829       "%2 = OpLoad %float %var\n" +
6830       "%3 = OpFSub %float %float_1 %2\n" +
6831       "%4 = OpFAdd %float %float_2 %3\n" +
6832       "OpReturn\n" +
6833       "OpFunctionEnd\n",
6834     4, true),
6835   // Test case 8: merge add of add
6836   // (x + 1) + 2 = x + 3
6837   InstructionFoldingCase<bool>(
6838     Header() +
6839       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6840       "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6841       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6842       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
6843       "%main = OpFunction %void None %void_func\n" +
6844       "%main_lab = OpLabel\n" +
6845       "%var = OpVariable %_ptr_float Function\n" +
6846       "%2 = OpLoad %float %var\n" +
6847       "%3 = OpFAdd %float %2 %float_1\n" +
6848       "%4 = OpFAdd %float %3 %float_2\n" +
6849       "OpReturn\n" +
6850       "OpFunctionEnd\n",
6851     4, true),
6852   // Test case 9: merge add of add
6853   // (1 + x) + 2 = 3 + x
6854   InstructionFoldingCase<bool>(
6855     Header() +
6856       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6857       "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6858       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6859       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
6860       "%main = OpFunction %void None %void_func\n" +
6861       "%main_lab = OpLabel\n" +
6862       "%var = OpVariable %_ptr_float Function\n" +
6863       "%2 = OpLoad %float %var\n" +
6864       "%3 = OpFAdd %float %float_1 %2\n" +
6865       "%4 = OpFAdd %float %3 %float_2\n" +
6866       "OpReturn\n" +
6867       "OpFunctionEnd\n",
6868     4, true),
6869   // Test case 10: merge add of add
6870   // 2 + (x + 1) = x + 1
6871   InstructionFoldingCase<bool>(
6872     Header() +
6873       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6874       "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6875       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6876       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
6877       "%main = OpFunction %void None %void_func\n" +
6878       "%main_lab = OpLabel\n" +
6879       "%var = OpVariable %_ptr_float Function\n" +
6880       "%2 = OpLoad %float %var\n" +
6881       "%3 = OpFAdd %float %2 %float_1\n" +
6882       "%4 = OpFAdd %float %float_2 %3\n" +
6883       "OpReturn\n" +
6884       "OpFunctionEnd\n",
6885     4, true),
6886   // Test case 11: merge add of add
6887   // 2 + (1 + x) = 3 - x
6888   InstructionFoldingCase<bool>(
6889     Header() +
6890       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6891       "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6892       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6893       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
6894       "%main = OpFunction %void None %void_func\n" +
6895       "%main_lab = OpLabel\n" +
6896       "%var = OpVariable %_ptr_float Function\n" +
6897       "%2 = OpLoad %float %var\n" +
6898       "%3 = OpFAdd %float %float_1 %2\n" +
6899       "%4 = OpFAdd %float %float_2 %3\n" +
6900       "OpReturn\n" +
6901       "OpFunctionEnd\n",
6902     4, true),
6903   // Test case 12: fold overflowing signed 32 bit iadds
6904   // (x + int_max) + 1 = x + int_min
6905   InstructionFoldingCase<bool>(
6906     Header() +
6907       "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
6908       "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
6909       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6910       "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_min]]\n" +
6911       "%main = OpFunction %void None %void_func\n" +
6912       "%main_lab = OpLabel\n" +
6913       "%var = OpVariable %_ptr_int Function\n" +
6914       "%2 = OpLoad %int %var\n" +
6915       "%3 = OpIAdd %int %2 %int_max\n" +
6916       "%4 = OpIAdd %int %3 %int_1\n" +
6917       "OpReturn\n" +
6918       "OpFunctionEnd\n",
6919     4, true),
6920   // Test case 13: fold overflowing signed 64 bit iadds
6921   // (x + long_max) + 1 = x + long_min
6922   InstructionFoldingCase<bool>(
6923     Header() +
6924       "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6925       "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
6926       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6927       "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_min]]\n" +
6928       "%main = OpFunction %void None %void_func\n" +
6929       "%main_lab = OpLabel\n" +
6930       "%var = OpVariable %_ptr_long Function\n" +
6931       "%2 = OpLoad %long %var\n" +
6932       "%3 = OpIAdd %long %2 %long_max\n" +
6933       "%4 = OpIAdd %long %3 %long_1\n" +
6934       "OpReturn\n" +
6935       "OpFunctionEnd\n",
6936     4, true),
6937   // Test case 14: fold overflowing 32 bit unsigned iadds
6938   // (x + uint_max) + 2 = x + 1
6939   InstructionFoldingCase<bool>(
6940     Header() +
6941       "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
6942       "; CHECK: [[uint_1:%\\w+]] = OpConstant [[uint]] 1\n" +
6943       "; CHECK: [[ld:%\\w+]] = OpLoad [[uint]]\n" +
6944       "; CHECK: %4 = OpIAdd [[uint]] [[ld]] [[uint_1]]\n" +
6945       "%main = OpFunction %void None %void_func\n" +
6946       "%main_lab = OpLabel\n" +
6947       "%var = OpVariable %_ptr_uint Function\n" +
6948       "%2 = OpLoad %uint %var\n" +
6949       "%3 = OpIAdd %uint %2 %uint_max\n" +
6950       "%4 = OpIAdd %uint %3 %uint_2\n" +
6951       "OpReturn\n" +
6952       "OpFunctionEnd\n",
6953     4, true),
6954   // Test case 15: fold overflowing 64 bit unsigned iadds
6955   // (x + ulong_max) + 2 = x + 1
6956   InstructionFoldingCase<bool>(
6957     Header() +
6958       "; CHECK: [[ulong:%\\w+]] = OpTypeInt 64 0\n" +
6959       "; CHECK: [[ulong_1:%\\w+]] = OpConstant [[ulong]] 1\n" +
6960       "; CHECK: [[ld:%\\w+]] = OpLoad [[ulong]]\n" +
6961       "; CHECK: %4 = OpIAdd [[ulong]] [[ld]] [[ulong_1]]\n" +
6962       "%main = OpFunction %void None %void_func\n" +
6963       "%main_lab = OpLabel\n" +
6964       "%var = OpVariable %_ptr_ulong Function\n" +
6965       "%2 = OpLoad %ulong %var\n" +
6966       "%3 = OpIAdd %ulong %2 %ulong_max\n" +
6967       "%4 = OpIAdd %ulong %3 %ulong_2\n" +
6968       "OpReturn\n" +
6969       "OpFunctionEnd\n",
6970     4, true),
6971   // Test case 16: fold underflowing signed 32 bit iadds
6972   // (x + int_min) + (-1) = x + int_max
6973   InstructionFoldingCase<bool>(
6974     Header() +
6975       "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
6976       "; CHECK: [[int_max:%\\w+]] = OpConstant [[int]] 2147483647\n" +
6977       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6978       "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_max]]\n" +
6979       "%main = OpFunction %void None %void_func\n" +
6980       "%main_lab = OpLabel\n" +
6981       "%var = OpVariable %_ptr_int Function\n" +
6982       "%2 = OpLoad %int %var\n" +
6983       "%3 = OpIAdd %int %2 %int_min\n" +
6984       "%4 = OpIAdd %int %3 %int_n1\n" +
6985       "OpReturn\n" +
6986       "OpFunctionEnd\n",
6987     4, true),
6988   // Test case 17: fold underflowing signed 64 bit iadds
6989   // (x + long_min) + (-1) = x + long_max
6990   InstructionFoldingCase<bool>(
6991     Header() +
6992       "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6993       "; CHECK: [[long_max:%\\w+]] = OpConstant [[long]] 9223372036854775807\n" +
6994       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6995       "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_max]]\n" +
6996       "%main = OpFunction %void None %void_func\n" +
6997       "%main_lab = OpLabel\n" +
6998       "%var = OpVariable %_ptr_long Function\n" +
6999       "%2 = OpLoad %long %var\n" +
7000       "%3 = OpIAdd %long %2 %long_min\n" +
7001       "%4 = OpIAdd %long %3 %long_n1\n" +
7002       "OpReturn\n" +
7003       "OpFunctionEnd\n",
7004     4, true)
7005 ));
7006 
7007 INSTANTIATE_TEST_SUITE_P(MergeGenericAddSub, MatchingInstructionFoldingTest,
7008 ::testing::Values(
7009     // Test case 0: merge of add of sub
7010     // (a - b) + b => a
7011     InstructionFoldingCase<bool>(
7012       Header() +
7013       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7014       "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
7015       "%main = OpFunction %void None %void_func\n" +
7016       "%main_lab = OpLabel\n" +
7017       "%var0 = OpVariable %_ptr_float Function\n" +
7018       "%var1 = OpVariable %_ptr_float Function\n" +
7019       "%3 = OpLoad %float %var0\n" +
7020       "%4 = OpLoad %float %var1\n" +
7021       "%5 = OpFSub %float %3 %4\n" +
7022       "%6 = OpFAdd %float %5 %4\n" +
7023       "OpReturn\n" +
7024       "OpFunctionEnd\n",
7025       6, true),
7026   // Test case 1: merge of add of sub
7027   // b + (a - b) => a
7028   InstructionFoldingCase<bool>(
7029     Header() +
7030     "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7031     "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
7032     "%main = OpFunction %void None %void_func\n" +
7033     "%main_lab = OpLabel\n" +
7034     "%var0 = OpVariable %_ptr_float Function\n" +
7035     "%var1 = OpVariable %_ptr_float Function\n" +
7036     "%3 = OpLoad %float %var0\n" +
7037     "%4 = OpLoad %float %var1\n" +
7038     "%5 = OpFSub %float %3 %4\n" +
7039     "%6 = OpFAdd %float %4 %5\n" +
7040     "OpReturn\n" +
7041     "OpFunctionEnd\n",
7042     6, true)
7043 ));
7044 
7045 INSTANTIATE_TEST_SUITE_P(FactorAddMul, MatchingInstructionFoldingTest,
7046 ::testing::Values(
7047     // Test case 0: factor of add of muls
7048     // (a * b) + (a * c) => a * (b + c)
7049     InstructionFoldingCase<bool>(
7050       Header() +
7051       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7052       "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7053       "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7054       "%main = OpFunction %void None %void_func\n" +
7055       "%main_lab = OpLabel\n" +
7056       "%var0 = OpVariable %_ptr_float Function\n" +
7057       "%var1 = OpVariable %_ptr_float Function\n" +
7058       "%var2 = OpVariable %_ptr_float Function\n" +
7059       "%4 = OpLoad %float %var0\n" +
7060       "%5 = OpLoad %float %var1\n" +
7061       "%6 = OpLoad %float %var2\n" +
7062       "%7 = OpFMul %float %6 %4\n" +
7063       "%8 = OpFMul %float %6 %5\n" +
7064       "%9 = OpFAdd %float %7 %8\n" +
7065       "OpReturn\n" +
7066       "OpFunctionEnd\n",
7067       9, true),
7068   // Test case 1: factor of add of muls
7069   // (b * a) + (a * c) => a * (b + c)
7070   InstructionFoldingCase<bool>(
7071     Header() +
7072     "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7073     "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7074     "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7075     "%main = OpFunction %void None %void_func\n" +
7076     "%main_lab = OpLabel\n" +
7077     "%var0 = OpVariable %_ptr_float Function\n" +
7078     "%var1 = OpVariable %_ptr_float Function\n" +
7079     "%var2 = OpVariable %_ptr_float Function\n" +
7080     "%4 = OpLoad %float %var0\n" +
7081     "%5 = OpLoad %float %var1\n" +
7082     "%6 = OpLoad %float %var2\n" +
7083     "%7 = OpFMul %float %4 %6\n" +
7084     "%8 = OpFMul %float %6 %5\n" +
7085     "%9 = OpFAdd %float %7 %8\n" +
7086     "OpReturn\n" +
7087     "OpFunctionEnd\n",
7088     9, true),
7089   // Test case 2: factor of add of muls
7090   // (a * b) + (c * a) => a * (b + c)
7091   InstructionFoldingCase<bool>(
7092     Header() +
7093     "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7094     "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7095     "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7096     "%main = OpFunction %void None %void_func\n" +
7097     "%main_lab = OpLabel\n" +
7098     "%var0 = OpVariable %_ptr_float Function\n" +
7099     "%var1 = OpVariable %_ptr_float Function\n" +
7100     "%var2 = OpVariable %_ptr_float Function\n" +
7101     "%4 = OpLoad %float %var0\n" +
7102     "%5 = OpLoad %float %var1\n" +
7103     "%6 = OpLoad %float %var2\n" +
7104     "%7 = OpFMul %float %6 %4\n" +
7105     "%8 = OpFMul %float %5 %6\n" +
7106     "%9 = OpFAdd %float %7 %8\n" +
7107     "OpReturn\n" +
7108     "OpFunctionEnd\n",
7109     9, true),
7110   // Test case 3: factor of add of muls
7111   // (b * a) + (c * a) => a * (b + c)
7112   InstructionFoldingCase<bool>(
7113     Header() +
7114     "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7115     "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7116     "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7117     "%main = OpFunction %void None %void_func\n" +
7118     "%main_lab = OpLabel\n" +
7119     "%var0 = OpVariable %_ptr_float Function\n" +
7120     "%var1 = OpVariable %_ptr_float Function\n" +
7121     "%var2 = OpVariable %_ptr_float Function\n" +
7122     "%4 = OpLoad %float %var0\n" +
7123     "%5 = OpLoad %float %var1\n" +
7124     "%6 = OpLoad %float %var2\n" +
7125     "%7 = OpFMul %float %4 %6\n" +
7126     "%8 = OpFMul %float %5 %6\n" +
7127     "%9 = OpFAdd %float %7 %8\n" +
7128     "OpReturn\n" +
7129     "OpFunctionEnd\n",
7130     9, true)
7131 ));
7132 
7133 INSTANTIATE_TEST_SUITE_P(MergeSubTest, MatchingInstructionFoldingTest,
7134 ::testing::Values(
7135   // Test case 0: merge sub of negate
7136   // (-x) - 2 = -2 - x
7137   InstructionFoldingCase<bool>(
7138     Header() +
7139       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7140       "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
7141       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7142       "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
7143       "%main = OpFunction %void None %void_func\n" +
7144       "%main_lab = OpLabel\n" +
7145       "%var = OpVariable %_ptr_float Function\n" +
7146       "%2 = OpLoad %float %var\n" +
7147       "%3 = OpFNegate %float %2\n" +
7148       "%4 = OpFSub %float %3 %float_2\n" +
7149       "OpReturn\n" +
7150       "OpFunctionEnd\n",
7151     4, true),
7152   // Test case 1: merge sub of negate
7153   // 2 - (-x) = x + 2
7154   InstructionFoldingCase<bool>(
7155     Header() +
7156       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7157       "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
7158       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7159       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_2]]\n" +
7160       "%main = OpFunction %void None %void_func\n" +
7161       "%main_lab = OpLabel\n" +
7162       "%var = OpVariable %_ptr_float Function\n" +
7163       "%2 = OpLoad %float %var\n" +
7164       "%3 = OpFNegate %float %2\n" +
7165       "%4 = OpFSub %float %float_2 %3\n" +
7166       "OpReturn\n" +
7167       "OpFunctionEnd\n",
7168     4, true),
7169   // Test case 2: merge sub of negate
7170   // (-x) - 2 = -2 - x
7171   InstructionFoldingCase<bool>(
7172     Header() +
7173       "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
7174       "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
7175       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7176       "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
7177       "%main = OpFunction %void None %void_func\n" +
7178       "%main_lab = OpLabel\n" +
7179       "%var = OpVariable %_ptr_long Function\n" +
7180       "%2 = OpLoad %long %var\n" +
7181       "%3 = OpSNegate %long %2\n" +
7182       "%4 = OpISub %long %3 %long_2\n" +
7183       "OpReturn\n" +
7184       "OpFunctionEnd\n",
7185     4, true),
7186   // Test case 3: merge sub of negate
7187   // 2 - (-x) = x + 2
7188   InstructionFoldingCase<bool>(
7189     Header() +
7190       "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
7191       "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
7192       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7193       "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_2]]\n" +
7194       "%main = OpFunction %void None %void_func\n" +
7195       "%main_lab = OpLabel\n" +
7196       "%var = OpVariable %_ptr_long Function\n" +
7197       "%2 = OpLoad %long %var\n" +
7198       "%3 = OpSNegate %long %2\n" +
7199       "%4 = OpISub %long %long_2 %3\n" +
7200       "OpReturn\n" +
7201       "OpFunctionEnd\n",
7202     4, true),
7203   // Test case 4: merge add of subtract
7204   // (x + 2) - 1 = x + 1
7205   InstructionFoldingCase<bool>(
7206     Header() +
7207       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7208       "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7209       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7210       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7211       "%main = OpFunction %void None %void_func\n" +
7212       "%main_lab = OpLabel\n" +
7213       "%var = OpVariable %_ptr_float Function\n" +
7214       "%2 = OpLoad %float %var\n" +
7215       "%3 = OpFAdd %float %2 %float_2\n" +
7216       "%4 = OpFSub %float %3 %float_1\n" +
7217       "OpReturn\n" +
7218       "OpFunctionEnd\n",
7219     4, true),
7220   // Test case 5: merge add of subtract
7221   // (2 + x) - 1 = x + 1
7222   InstructionFoldingCase<bool>(
7223     Header() +
7224       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7225       "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7226       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7227       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7228       "%main = OpFunction %void None %void_func\n" +
7229       "%main_lab = OpLabel\n" +
7230       "%var = OpVariable %_ptr_float Function\n" +
7231       "%2 = OpLoad %float %var\n" +
7232       "%3 = OpFAdd %float %float_2 %2\n" +
7233       "%4 = OpFSub %float %3 %float_1\n" +
7234       "OpReturn\n" +
7235       "OpFunctionEnd\n",
7236     4, true),
7237   // Test case 6: merge add of subtract
7238   // 2 - (x + 1) = 1 - x
7239   InstructionFoldingCase<bool>(
7240     Header() +
7241       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7242       "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7243       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7244       "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
7245       "%main = OpFunction %void None %void_func\n" +
7246       "%main_lab = OpLabel\n" +
7247       "%var = OpVariable %_ptr_float Function\n" +
7248       "%2 = OpLoad %float %var\n" +
7249       "%3 = OpFAdd %float %2 %float_1\n" +
7250       "%4 = OpFSub %float %float_2 %3\n" +
7251       "OpReturn\n" +
7252       "OpFunctionEnd\n",
7253     4, true),
7254   // Test case 7: merge add of subtract
7255   // 2 - (1 + x) = 1 - x
7256   InstructionFoldingCase<bool>(
7257     Header() +
7258       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7259       "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7260       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7261       "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
7262       "%main = OpFunction %void None %void_func\n" +
7263       "%main_lab = OpLabel\n" +
7264       "%var = OpVariable %_ptr_float Function\n" +
7265       "%2 = OpLoad %float %var\n" +
7266       "%3 = OpFAdd %float %float_1 %2\n" +
7267       "%4 = OpFSub %float %float_2 %3\n" +
7268       "OpReturn\n" +
7269       "OpFunctionEnd\n",
7270     4, true),
7271   // Test case 8: merge subtract of subtract
7272   // (x - 2) - 1 = x - 3
7273   InstructionFoldingCase<bool>(
7274     Header() +
7275       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7276       "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7277       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7278       "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_3]]\n" +
7279       "%main = OpFunction %void None %void_func\n" +
7280       "%main_lab = OpLabel\n" +
7281       "%var = OpVariable %_ptr_float Function\n" +
7282       "%2 = OpLoad %float %var\n" +
7283       "%3 = OpFSub %float %2 %float_2\n" +
7284       "%4 = OpFSub %float %3 %float_1\n" +
7285       "OpReturn\n" +
7286       "OpFunctionEnd\n",
7287     4, true),
7288   // Test case 9: merge subtract of subtract
7289   // (2 - x) - 1 = 1 - x
7290   InstructionFoldingCase<bool>(
7291     Header() +
7292       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7293       "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7294       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7295       "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
7296       "%main = OpFunction %void None %void_func\n" +
7297       "%main_lab = OpLabel\n" +
7298       "%var = OpVariable %_ptr_float Function\n" +
7299       "%2 = OpLoad %float %var\n" +
7300       "%3 = OpFSub %float %float_2 %2\n" +
7301       "%4 = OpFSub %float %3 %float_1\n" +
7302       "OpReturn\n" +
7303       "OpFunctionEnd\n",
7304     4, true),
7305   // Test case 10: merge subtract of subtract
7306   // 2 - (x - 1) = 3 - x
7307   InstructionFoldingCase<bool>(
7308     Header() +
7309       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7310       "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7311       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7312       "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
7313       "%main = OpFunction %void None %void_func\n" +
7314       "%main_lab = OpLabel\n" +
7315       "%var = OpVariable %_ptr_float Function\n" +
7316       "%2 = OpLoad %float %var\n" +
7317       "%3 = OpFSub %float %2 %float_1\n" +
7318       "%4 = OpFSub %float %float_2 %3\n" +
7319       "OpReturn\n" +
7320       "OpFunctionEnd\n",
7321     4, true),
7322   // Test case 11: merge subtract of subtract
7323   // 1 - (2 - x) = x + (-1)
7324   InstructionFoldingCase<bool>(
7325     Header() +
7326       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7327       "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
7328       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7329       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_n1]]\n" +
7330       "%main = OpFunction %void None %void_func\n" +
7331       "%main_lab = OpLabel\n" +
7332       "%var = OpVariable %_ptr_float Function\n" +
7333       "%2 = OpLoad %float %var\n" +
7334       "%3 = OpFSub %float %float_2 %2\n" +
7335       "%4 = OpFSub %float %float_1 %3\n" +
7336       "OpReturn\n" +
7337       "OpFunctionEnd\n",
7338     4, true),
7339   // Test case 12: merge subtract of subtract
7340   // 2 - (1 - x) = x + 1
7341   InstructionFoldingCase<bool>(
7342     Header() +
7343       "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7344       "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7345       "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7346       "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7347       "%main = OpFunction %void None %void_func\n" +
7348       "%main_lab = OpLabel\n" +
7349       "%var = OpVariable %_ptr_float Function\n" +
7350       "%2 = OpLoad %float %var\n" +
7351       "%3 = OpFSub %float %float_1 %2\n" +
7352       "%4 = OpFSub %float %float_2 %3\n" +
7353       "OpReturn\n" +
7354       "OpFunctionEnd\n",
7355     4, true),
7356   // Test case 13: merge subtract of subtract with mixed types.
7357   // 2 - (1 - x) = x + 1
7358   InstructionFoldingCase<bool>(
7359     Header() +
7360       "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7361       "; CHECK: [[int_1:%\\w+]] = OpConstant [[int]] 1\n" +
7362       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
7363       "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_1]]\n" +
7364       "%main = OpFunction %void None %void_func\n" +
7365       "%main_lab = OpLabel\n" +
7366       "%var = OpVariable %_ptr_int Function\n" +
7367       "%2 = OpLoad %int %var\n" +
7368       "%3 = OpISub %int %uint_1 %2\n" +
7369       "%4 = OpISub %int %int_2 %3\n" +
7370       "OpReturn\n" +
7371       "OpFunctionEnd\n",
7372     4, true),
7373   // Test case 14: fold overflowing signed 32 bit isubs
7374   // (x - int_max) - 1 = x - int_min
7375   InstructionFoldingCase<bool>(
7376     Header() +
7377       "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
7378       "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
7379       "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
7380       "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_min]]\n" +
7381       "%main = OpFunction %void None %void_func\n" +
7382       "%main_lab = OpLabel\n" +
7383       "%var = OpVariable %_ptr_int Function\n" +
7384       "%2 = OpLoad %int %var\n" +
7385       "%3 = OpISub %int %2 %int_max\n" +
7386       "%4 = OpISub %int %3 %int_1\n" +
7387       "OpReturn\n" +
7388       "OpFunctionEnd\n",
7389     4, true),
7390   // Test case 15: fold overflowing signed 64 bit isubs
7391   // (x - long_max) - 1 = x - long_min
7392   InstructionFoldingCase<bool>(
7393     Header() +
7394       "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
7395       "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
7396       "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7397       "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_min]]\n" +
7398       "%main = OpFunction %void None %void_func\n" +
7399       "%main_lab = OpLabel\n" +
7400       "%var = OpVariable %_ptr_long Function\n" +
7401       "%2 = OpLoad %long %var\n" +
7402       "%3 = OpISub %long %2 %long_max\n" +
7403       "%4 = OpISub %long %3 %long_1\n" +
7404       "OpReturn\n" +
7405       "OpFunctionEnd\n",
7406     4, true)
7407 ));
7408 
7409 INSTANTIATE_TEST_SUITE_P(SelectFoldingTest, MatchingInstructionFoldingTest,
7410 ::testing::Values(
7411   // Test case 0: Fold select with the same values for both sides
7412   InstructionFoldingCase<bool>(
7413       Header() +
7414           "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7415           "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7416           "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7417           "%main = OpFunction %void None %void_func\n" +
7418           "%main_lab = OpLabel\n" +
7419           "%n = OpVariable %_ptr_bool Function\n" +
7420           "%load = OpLoad %bool %n\n" +
7421           "%2 = OpSelect %int %load %100 %100\n" +
7422           "OpReturn\n" +
7423           "OpFunctionEnd",
7424       2, true),
7425   // Test case 1: Fold select true to left side
7426   InstructionFoldingCase<bool>(
7427       Header() +
7428           "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7429           "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7430           "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7431           "%main = OpFunction %void None %void_func\n" +
7432           "%main_lab = OpLabel\n" +
7433           "%n = OpVariable %_ptr_int Function\n" +
7434           "%load = OpLoad %bool %n\n" +
7435           "%2 = OpSelect %int %true %100 %n\n" +
7436           "OpReturn\n" +
7437           "OpFunctionEnd",
7438       2, true),
7439   // Test case 2: Fold select false to right side
7440   InstructionFoldingCase<bool>(
7441       Header() +
7442           "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7443           "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7444           "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7445           "%main = OpFunction %void None %void_func\n" +
7446           "%main_lab = OpLabel\n" +
7447           "%n = OpVariable %_ptr_int Function\n" +
7448           "%load = OpLoad %bool %n\n" +
7449           "%2 = OpSelect %int %false %n %100\n" +
7450           "OpReturn\n" +
7451           "OpFunctionEnd",
7452       2, true),
7453   // Test case 3: Fold select null to right side
7454   InstructionFoldingCase<bool>(
7455       Header() +
7456           "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7457           "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7458           "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7459           "%main = OpFunction %void None %void_func\n" +
7460           "%main_lab = OpLabel\n" +
7461           "%n = OpVariable %_ptr_int Function\n" +
7462           "%load = OpLoad %int %n\n" +
7463           "%2 = OpSelect %int %bool_null %load %100\n" +
7464           "OpReturn\n" +
7465           "OpFunctionEnd",
7466       2, true),
7467   // Test case 4: vector null
7468   InstructionFoldingCase<bool>(
7469       Header() +
7470           "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7471           "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
7472           "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7473           "; CHECK: [[v2int2_2:%\\w+]] = OpConstantComposite [[v2int]] [[int2]] [[int2]]\n" +
7474           "; CHECK: %2 = OpCopyObject [[v2int]] [[v2int2_2]]\n" +
7475           "%main = OpFunction %void None %void_func\n" +
7476           "%main_lab = OpLabel\n" +
7477           "%n = OpVariable %_ptr_v2int Function\n" +
7478           "%load = OpLoad %v2int %n\n" +
7479           "%2 = OpSelect %v2int %v2bool_null %load %v2int_2_2\n" +
7480           "OpReturn\n" +
7481           "OpFunctionEnd",
7482       2, true),
7483   // Test case 5: vector select
7484   InstructionFoldingCase<bool>(
7485       Header() +
7486           "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7487           "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
7488           "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 0 3\n" +
7489           "%main = OpFunction %void None %void_func\n" +
7490           "%main_lab = OpLabel\n" +
7491           "%m = OpVariable %_ptr_v2int Function\n" +
7492           "%n = OpVariable %_ptr_v2int Function\n" +
7493           "%2 = OpLoad %v2int %n\n" +
7494           "%3 = OpLoad %v2int %n\n" +
7495           "%4 = OpSelect %v2int %v2bool_true_false %2 %3\n" +
7496           "OpReturn\n" +
7497           "OpFunctionEnd",
7498       4, true),
7499   // Test case 6: vector select
7500   InstructionFoldingCase<bool>(
7501       Header() +
7502           "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7503           "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
7504           "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 2 1\n" +
7505           "%main = OpFunction %void None %void_func\n" +
7506           "%main_lab = OpLabel\n" +
7507           "%m = OpVariable %_ptr_v2int Function\n" +
7508           "%n = OpVariable %_ptr_v2int Function\n" +
7509           "%2 = OpLoad %v2int %n\n" +
7510           "%3 = OpLoad %v2int %n\n" +
7511           "%4 = OpSelect %v2int %v2bool_false_true %2 %3\n" +
7512           "OpReturn\n" +
7513           "OpFunctionEnd",
7514       4, true)
7515 ));
7516 
7517 INSTANTIATE_TEST_SUITE_P(CompositeExtractOrInsertMatchingTest, MatchingInstructionFoldingTest,
7518 ::testing::Values(
7519     // Test case 0: Extracting from result of consecutive shuffles of differing
7520     // size.
7521     InstructionFoldingCase<bool>(
7522         Header() +
7523             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7524             "; CHECK: %5 = OpCompositeExtract [[int]] %2 2\n" +
7525             "%main = OpFunction %void None %void_func\n" +
7526             "%main_lab = OpLabel\n" +
7527             "%n = OpVariable %_ptr_v4int Function\n" +
7528             "%2 = OpLoad %v4int %n\n" +
7529             "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
7530             "%4 = OpVectorShuffle %v4int %2 %3 0 4 2 5\n" +
7531             "%5 = OpCompositeExtract %int %4 1\n" +
7532             "OpReturn\n" +
7533             "OpFunctionEnd",
7534         5, true),
7535     // Test case 1: Extracting from result of vector shuffle of differing
7536     // input and result sizes.
7537     InstructionFoldingCase<bool>(
7538         Header() +
7539             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7540             "; CHECK: %4 = OpCompositeExtract [[int]] %2 2\n" +
7541             "%main = OpFunction %void None %void_func\n" +
7542             "%main_lab = OpLabel\n" +
7543             "%n = OpVariable %_ptr_v4int Function\n" +
7544             "%2 = OpLoad %v4int %n\n" +
7545             "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
7546             "%4 = OpCompositeExtract %int %3 0\n" +
7547             "OpReturn\n" +
7548             "OpFunctionEnd",
7549         4, true),
7550     // Test case 2: Extracting from result of vector shuffle of differing
7551     // input and result sizes.
7552     InstructionFoldingCase<bool>(
7553         Header() +
7554             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7555             "; CHECK: %4 = OpCompositeExtract [[int]] %2 3\n" +
7556             "%main = OpFunction %void None %void_func\n" +
7557             "%main_lab = OpLabel\n" +
7558             "%n = OpVariable %_ptr_v4int Function\n" +
7559             "%2 = OpLoad %v4int %n\n" +
7560             "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
7561             "%4 = OpCompositeExtract %int %3 1\n" +
7562             "OpReturn\n" +
7563             "OpFunctionEnd",
7564         4, true),
7565     // Test case 3: Using fmix feeding extract with a 1 in the a position.
7566     InstructionFoldingCase<bool>(
7567         Header() +
7568             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7569             "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
7570             "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
7571             "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7572             "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7573             "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[n]]\n" +
7574             "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 1\n" +
7575             "%main = OpFunction %void None %void_func\n" +
7576             "%main_lab = OpLabel\n" +
7577             "%m = OpVariable %_ptr_v4double Function\n" +
7578             "%n = OpVariable %_ptr_v4double Function\n" +
7579             "%2 = OpLoad %v4double %m\n" +
7580             "%3 = OpLoad %v4double %n\n" +
7581             "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
7582             "%5 = OpCompositeExtract %double %4 1\n" +
7583             "OpReturn\n" +
7584             "OpFunctionEnd",
7585         5, true),
7586     // Test case 4: Using fmix feeding extract with a 0 in the a position.
7587     InstructionFoldingCase<bool>(
7588         Header() +
7589             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7590             "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
7591             "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
7592             "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7593             "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7594             "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
7595             "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 2\n" +
7596             "%main = OpFunction %void None %void_func\n" +
7597             "%main_lab = OpLabel\n" +
7598             "%m = OpVariable %_ptr_v4double Function\n" +
7599             "%n = OpVariable %_ptr_v4double Function\n" +
7600             "%2 = OpLoad %v4double %m\n" +
7601             "%3 = OpLoad %v4double %n\n" +
7602             "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
7603             "%5 = OpCompositeExtract %double %4 2\n" +
7604             "OpReturn\n" +
7605             "OpFunctionEnd",
7606         5, true),
7607     // Test case 5: Using fmix feeding extract with a null for the alpha
7608     InstructionFoldingCase<bool>(
7609         Header() +
7610             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7611             "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
7612             "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
7613             "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7614             "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7615             "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
7616             "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 0\n" +
7617             "%main = OpFunction %void None %void_func\n" +
7618             "%main_lab = OpLabel\n" +
7619             "%m = OpVariable %_ptr_v4double Function\n" +
7620             "%n = OpVariable %_ptr_v4double Function\n" +
7621             "%2 = OpLoad %v4double %m\n" +
7622             "%3 = OpLoad %v4double %n\n" +
7623             "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_null\n" +
7624             "%5 = OpCompositeExtract %double %4 0\n" +
7625             "OpReturn\n" +
7626             "OpFunctionEnd",
7627         5, true),
7628     // Test case 6: Don't fold: Using fmix feeding extract with 0.5 in the a
7629     // position.
7630     InstructionFoldingCase<bool>(
7631         Header() +
7632             "%main = OpFunction %void None %void_func\n" +
7633             "%main_lab = OpLabel\n" +
7634             "%m = OpVariable %_ptr_v4double Function\n" +
7635             "%n = OpVariable %_ptr_v4double Function\n" +
7636             "%2 = OpLoad %v4double %m\n" +
7637             "%3 = OpLoad %v4double %n\n" +
7638             "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_1_1_1_0p5\n" +
7639             "%5 = OpCompositeExtract %double %4 3\n" +
7640             "OpReturn\n" +
7641             "OpFunctionEnd",
7642         5, false),
7643     // Test case 7: Extracting the undefined literal value from a vector
7644     // shuffle.
7645     InstructionFoldingCase<bool>(
7646         Header() +
7647             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7648             "; CHECK: %4 = OpUndef [[int]]\n" +
7649             "%main = OpFunction %void None %void_func\n" +
7650             "%main_lab = OpLabel\n" +
7651             "%n = OpVariable %_ptr_v4int Function\n" +
7652             "%2 = OpLoad %v4int %n\n" +
7653             "%3 = OpVectorShuffle %v2int %2 %2 2 4294967295\n" +
7654             "%4 = OpCompositeExtract %int %3 1\n" +
7655             "OpReturn\n" +
7656             "OpFunctionEnd",
7657         4, true),
7658     // Test case 8: Inserting every element of a vector turns into a composite construct.
7659     InstructionFoldingCase<bool>(
7660         Header() +
7661             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7662             "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
7663             "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7664             "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7665             "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
7666             "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
7667             "; CHECK: %5 = OpCopyObject [[v4]] [[construct]]\n" +
7668             "%main = OpFunction %void None %void_func\n" +
7669             "%main_lab = OpLabel\n" +
7670             "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
7671             "%3 = OpCompositeInsert %v4int %int_1 %2 1\n" +
7672             "%4 = OpCompositeInsert %v4int %int_2 %3 2\n" +
7673             "%5 = OpCompositeInsert %v4int %int_3 %4 3\n" +
7674             "OpReturn\n" +
7675             "OpFunctionEnd",
7676         5, true),
7677     // Test case 9: Inserting every element of a vector turns into a composite construct in a different order.
7678     InstructionFoldingCase<bool>(
7679         Header() +
7680             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7681             "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
7682             "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7683             "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7684             "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
7685             "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
7686             "; CHECK: %5 = OpCopyObject [[v4]] [[construct]]\n" +
7687             "%main = OpFunction %void None %void_func\n" +
7688             "%main_lab = OpLabel\n" +
7689             "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
7690             "%4 = OpCompositeInsert %v4int %int_2 %2 2\n" +
7691             "%3 = OpCompositeInsert %v4int %int_1 %4 1\n" +
7692             "%5 = OpCompositeInsert %v4int %int_3 %3 3\n" +
7693             "OpReturn\n" +
7694             "OpFunctionEnd",
7695         5, true),
7696     // Test case 10: Check multiple inserts to the same position are handled correctly.
7697     InstructionFoldingCase<bool>(
7698         Header() +
7699             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7700             "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
7701             "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7702             "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7703             "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
7704             "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
7705             "; CHECK: %6 = OpCopyObject [[v4]] [[construct]]\n" +
7706             "%main = OpFunction %void None %void_func\n" +
7707             "%main_lab = OpLabel\n" +
7708             "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
7709             "%3 = OpCompositeInsert %v4int %int_2 %2 2\n" +
7710             "%4 = OpCompositeInsert %v4int %int_4 %3 1\n" +
7711             "%5 = OpCompositeInsert %v4int %int_1 %4 1\n" +
7712             "%6 = OpCompositeInsert %v4int %int_3 %5 3\n" +
7713             "OpReturn\n" +
7714             "OpFunctionEnd",
7715         6, true),
7716     // Test case 11: The last indexes are 0 and 1, but they have different first indexes.  This should not be folded.
7717     InstructionFoldingCase<bool>(
7718         Header() +
7719             "%main = OpFunction %void None %void_func\n" +
7720             "%main_lab = OpLabel\n" +
7721             "%2 = OpCompositeInsert %m2x2int %100 %m2x2int_undef 0 0\n" +
7722             "%3 = OpCompositeInsert %m2x2int %int_1 %2 1 1\n" +
7723             "OpReturn\n" +
7724             "OpFunctionEnd",
7725         3, false),
7726     // Test case 12: Don't fold when there is a partial insertion.
7727     InstructionFoldingCase<bool>(
7728         Header() +
7729             "%main = OpFunction %void None %void_func\n" +
7730             "%main_lab = OpLabel\n" +
7731             "%2 = OpCompositeInsert %m2x2int %v2int_1_0 %m2x2int_undef 0\n" +
7732             "%3 = OpCompositeInsert %m2x2int %int_4 %2 0 0\n" +
7733             "%4 = OpCompositeInsert %m2x2int %v2int_2_3 %3 1\n" +
7734             "OpReturn\n" +
7735             "OpFunctionEnd",
7736         4, false),
7737     // Test case 13: Insert into a column of a matrix
7738     InstructionFoldingCase<bool>(
7739         Header() +
7740             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7741             "; CHECK-DAG: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
7742             "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
7743             "; CHECK-DAG: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
7744             "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7745 // We keep this insert in the chain.  DeadInsertElimPass should remove it.
7746             "; CHECK: [[insert:%\\w+]] = OpCompositeInsert [[m2x2]] %100 [[m2x2_undef]] 0 0\n" +
7747             "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v2]] %100 [[int1]]\n" +
7748             "; CHECK: %3 = OpCompositeInsert [[m2x2]] [[construct]] [[insert]] 0\n" +
7749             "%main = OpFunction %void None %void_func\n" +
7750             "%main_lab = OpLabel\n" +
7751             "%2 = OpCompositeInsert %m2x2int %100 %m2x2int_undef 0 0\n" +
7752             "%3 = OpCompositeInsert %m2x2int %int_1 %2 0 1\n" +
7753             "OpReturn\n" +
7754             "OpFunctionEnd",
7755         3, true),
7756     // Test case 14: Insert all elements of the matrix.
7757     InstructionFoldingCase<bool>(
7758         Header() +
7759             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7760             "; CHECK-DAG: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
7761             "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
7762             "; CHECK-DAG: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
7763             "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7764             "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7765             "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
7766             "; CHECK: [[c0:%\\w+]] = OpCompositeConstruct [[v2]] %100 [[int1]]\n" +
7767             "; CHECK: [[c1:%\\w+]] = OpCompositeConstruct [[v2]] [[int2]] [[int3]]\n" +
7768             "; CHECK: [[matrix:%\\w+]] = OpCompositeConstruct [[m2x2]] [[c0]] [[c1]]\n" +
7769             "; CHECK: %5 = OpCopyObject [[m2x2]] [[matrix]]\n" +
7770             "%main = OpFunction %void None %void_func\n" +
7771             "%main_lab = OpLabel\n" +
7772             "%2 = OpCompositeConstruct %v2int %100 %int_1\n" +
7773             "%3 = OpCompositeInsert %m2x2int %2 %m2x2int_undef 0\n" +
7774             "%4 = OpCompositeInsert %m2x2int %int_2 %3 1 0\n" +
7775             "%5 = OpCompositeInsert %m2x2int %int_3 %4 1 1\n" +
7776             "OpReturn\n" +
7777             "OpFunctionEnd",
7778         5, true),
7779     // Test case 15: Replace construct with extract when reconstructing a member
7780     // of another object.
7781     InstructionFoldingCase<bool>(
7782         Header() +
7783             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7784             "; CHECK: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
7785             "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
7786             "; CHECK: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
7787             "; CHECK: %5 = OpCompositeExtract [[v2]] [[m2x2_undef]]\n" +
7788             "%main = OpFunction %void None %void_func\n" +
7789             "%main_lab = OpLabel\n" +
7790             "%3 = OpCompositeExtract %int %m2x2int_undef 1 0\n" +
7791             "%4 = OpCompositeExtract %int %m2x2int_undef 1 1\n" +
7792             "%5 = OpCompositeConstruct %v2int %3 %4\n" +
7793             "OpReturn\n" +
7794             "OpFunctionEnd",
7795         5, true),
7796     // Test case 16: Don't fold when type cannot be deduced to a constant.
7797     InstructionFoldingCase<bool>(
7798         Header() +
7799             "%main = OpFunction %void None %void_func\n" +
7800             "%main_lab = OpLabel\n" +
7801             "%4 = OpCompositeInsert %struct_v2int_int_int %int_1 %struct_v2int_int_int_null 2\n" +
7802             "OpReturn\n" +
7803             "OpFunctionEnd",
7804         4, false),
7805     // Test case 17: Don't fold when index into composite is out of bounds.
7806     InstructionFoldingCase<bool>(
7807 	Header() +
7808             "%main = OpFunction %void None %void_func\n" +
7809 	    "%main_lab = OpLabel\n" +
7810 	    "%4 = OpCompositeExtract %int %struct_v2int_int_int 3\n" +
7811 	    "OpReturn\n" +
7812 	    "OpFunctionEnd",
7813 	4, false),
7814     // Test case 18: Fold when every element of an array is inserted.
7815     InstructionFoldingCase<bool>(
7816         Header() +
7817             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7818             "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7819             "; CHECK-DAG: [[arr_type:%\\w+]] = OpTypeArray [[int]] [[int2]]\n" +
7820             "; CHECK-DAG: [[int10:%\\w+]] = OpConstant [[int]] 10\n" +
7821             "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7822             "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[arr_type]] [[int10]] [[int1]]\n" +
7823             "; CHECK: %5 = OpCopyObject [[arr_type]] [[construct]]\n" +
7824             "%main = OpFunction %void None %void_func\n" +
7825             "%main_lab = OpLabel\n" +
7826             "%4 = OpCompositeInsert %int_arr_2 %int_10 %int_arr_2_undef 0\n" +
7827             "%5 = OpCompositeInsert %int_arr_2 %int_1 %4 1\n" +
7828             "OpReturn\n" +
7829             "OpFunctionEnd",
7830         5, true)
7831 ));
7832 
7833 INSTANTIATE_TEST_SUITE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
7834 ::testing::Values(
7835     // Test case 0: Using OpDot to extract last element.
7836     InstructionFoldingCase<bool>(
7837         Header() +
7838             "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7839             "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
7840             "%main = OpFunction %void None %void_func\n" +
7841             "%main_lab = OpLabel\n" +
7842             "%n = OpVariable %_ptr_v4float Function\n" +
7843             "%2 = OpLoad %v4float %n\n" +
7844             "%3 = OpDot %float %2 %v4float_0_0_0_1\n" +
7845             "OpReturn\n" +
7846             "OpFunctionEnd",
7847         3, true),
7848     // Test case 1: Using OpDot to extract last element.
7849     InstructionFoldingCase<bool>(
7850         Header() +
7851             "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7852             "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
7853             "%main = OpFunction %void None %void_func\n" +
7854             "%main_lab = OpLabel\n" +
7855             "%n = OpVariable %_ptr_v4float Function\n" +
7856             "%2 = OpLoad %v4float %n\n" +
7857             "%3 = OpDot %float %v4float_0_0_0_1 %2\n" +
7858             "OpReturn\n" +
7859             "OpFunctionEnd",
7860         3, true),
7861     // Test case 2: Using OpDot to extract second element.
7862     InstructionFoldingCase<bool>(
7863         Header() +
7864             "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7865             "; CHECK: %3 = OpCompositeExtract [[float]] %2 1\n" +
7866             "%main = OpFunction %void None %void_func\n" +
7867             "%main_lab = OpLabel\n" +
7868             "%n = OpVariable %_ptr_v4float Function\n" +
7869             "%2 = OpLoad %v4float %n\n" +
7870             "%3 = OpDot %float %v4float_0_1_0_0 %2\n" +
7871             "OpReturn\n" +
7872             "OpFunctionEnd",
7873         3, true),
7874     // Test case 3: Using OpDot to extract last element.
7875     InstructionFoldingCase<bool>(
7876         Header() +
7877             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7878             "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
7879             "%main = OpFunction %void None %void_func\n" +
7880             "%main_lab = OpLabel\n" +
7881             "%n = OpVariable %_ptr_v4double Function\n" +
7882             "%2 = OpLoad %v4double %n\n" +
7883             "%3 = OpDot %double %2 %v4double_0_0_0_1\n" +
7884             "OpReturn\n" +
7885             "OpFunctionEnd",
7886         3, true),
7887     // Test case 4: Using OpDot to extract last element.
7888     InstructionFoldingCase<bool>(
7889         Header() +
7890             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7891             "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
7892             "%main = OpFunction %void None %void_func\n" +
7893             "%main_lab = OpLabel\n" +
7894             "%n = OpVariable %_ptr_v4double Function\n" +
7895             "%2 = OpLoad %v4double %n\n" +
7896             "%3 = OpDot %double %v4double_0_0_0_1 %2\n" +
7897             "OpReturn\n" +
7898             "OpFunctionEnd",
7899         3, true),
7900     // Test case 5: Using OpDot to extract second element.
7901     InstructionFoldingCase<bool>(
7902         Header() +
7903             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7904             "; CHECK: %3 = OpCompositeExtract [[double]] %2 1\n" +
7905             "%main = OpFunction %void None %void_func\n" +
7906             "%main_lab = OpLabel\n" +
7907             "%n = OpVariable %_ptr_v4double Function\n" +
7908             "%2 = OpLoad %v4double %n\n" +
7909             "%3 = OpDot %double %v4double_0_1_0_0 %2\n" +
7910             "OpReturn\n" +
7911             "OpFunctionEnd",
7912         3, true)
7913 ));
7914 
7915 INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionFoldingTest,
7916 ::testing::Values(
7917     // Test case 0: Using OpDot to extract last element.
7918     InstructionFoldingCase<bool>(
7919         Header() +
7920             "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7921             "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
7922             "; CHECK: [[null:%\\w+]] = OpConstantNull [[v2int]]\n" +
7923             "; CHECK: OpVectorShuffle\n" +
7924             "; CHECK: %3 = OpVectorShuffle [[v2int]] [[null]] {{%\\w+}} 4294967295 2\n" +
7925             "%main = OpFunction %void None %void_func\n" +
7926             "%main_lab = OpLabel\n" +
7927             "%n = OpVariable %_ptr_int Function\n" +
7928             "%load = OpLoad %int %n\n" +
7929             "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 3 0xFFFFFFFF \n" +
7930             "%3 = OpVectorShuffle %v2int %2 %v2int_2_3 1 2 \n" +
7931             "OpReturn\n" +
7932             "OpFunctionEnd",
7933         3, true)
7934  ));
7935 
7936 INSTANTIATE_TEST_SUITE_P(FmaGenerationMatchingTest, MatchingInstructionFoldingTest,
7937 ::testing::Values(
7938    // Test case 0: (x * y) + a = Fma(x, y, a)
7939    InstructionFoldingCase<bool>(
7940        Header() +
7941            "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
7942            "; CHECK: OpFunction\n" +
7943            "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7944            "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7945            "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7946            "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
7947            "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
7948            "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
7949            "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
7950            "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
7951            "%main = OpFunction %void None %void_func\n" +
7952            "%main_lab = OpLabel\n" +
7953            "%x = OpVariable %_ptr_float Function\n" +
7954            "%y = OpVariable %_ptr_float Function\n" +
7955            "%a = OpVariable %_ptr_float Function\n" +
7956            "%lx = OpLoad %float %x\n" +
7957            "%ly = OpLoad %float %y\n" +
7958            "%mul = OpFMul %float %lx %ly\n" +
7959            "%la = OpLoad %float %a\n" +
7960            "%3 = OpFAdd %float %mul %la\n" +
7961            "OpStore %a %3\n" +
7962            "OpReturn\n" +
7963            "OpFunctionEnd",
7964        3, true),
7965     // Test case 1:  a + (x * y) = Fma(x, y, a)
7966    InstructionFoldingCase<bool>(
7967        Header() +
7968            "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
7969            "; CHECK: OpFunction\n" +
7970            "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7971            "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7972            "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7973            "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
7974            "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
7975            "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
7976            "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
7977            "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
7978            "%main = OpFunction %void None %void_func\n" +
7979            "%main_lab = OpLabel\n" +
7980            "%x = OpVariable %_ptr_float Function\n" +
7981            "%y = OpVariable %_ptr_float Function\n" +
7982            "%a = OpVariable %_ptr_float Function\n" +
7983            "%lx = OpLoad %float %x\n" +
7984            "%ly = OpLoad %float %y\n" +
7985            "%mul = OpFMul %float %lx %ly\n" +
7986            "%la = OpLoad %float %a\n" +
7987            "%3 = OpFAdd %float %la %mul\n" +
7988            "OpStore %a %3\n" +
7989            "OpReturn\n" +
7990            "OpFunctionEnd",
7991        3, true),
7992    // Test case 2: (x * y) + a = Fma(x, y, a) with vectors
7993    InstructionFoldingCase<bool>(
7994        Header() +
7995            "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
7996            "; CHECK: OpFunction\n" +
7997            "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7998            "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7999            "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8000            "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
8001            "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
8002            "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
8003            "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
8004            "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
8005            "%main = OpFunction %void None %void_func\n" +
8006            "%main_lab = OpLabel\n" +
8007            "%x = OpVariable %_ptr_v4float Function\n" +
8008            "%y = OpVariable %_ptr_v4float Function\n" +
8009            "%a = OpVariable %_ptr_v4float Function\n" +
8010            "%lx = OpLoad %v4float %x\n" +
8011            "%ly = OpLoad %v4float %y\n" +
8012            "%mul = OpFMul %v4float %lx %ly\n" +
8013            "%la = OpLoad %v4float %a\n" +
8014            "%3 = OpFAdd %v4float %mul %la\n" +
8015            "OpStore %a %3\n" +
8016            "OpReturn\n" +
8017            "OpFunctionEnd",
8018        3, true),
8019     // Test case 3:  a + (x * y) = Fma(x, y, a) with vectors
8020    InstructionFoldingCase<bool>(
8021        Header() +
8022            "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
8023            "; CHECK: OpFunction\n" +
8024            "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8025            "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8026            "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8027            "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
8028            "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
8029            "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
8030            "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
8031            "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
8032            "%main = OpFunction %void None %void_func\n" +
8033            "%main_lab = OpLabel\n" +
8034            "%x = OpVariable %_ptr_float Function\n" +
8035            "%y = OpVariable %_ptr_float Function\n" +
8036            "%a = OpVariable %_ptr_float Function\n" +
8037            "%lx = OpLoad %float %x\n" +
8038            "%ly = OpLoad %float %y\n" +
8039            "%mul = OpFMul %float %lx %ly\n" +
8040            "%la = OpLoad %float %a\n" +
8041            "%3 = OpFAdd %float %la %mul\n" +
8042            "OpStore %a %3\n" +
8043            "OpReturn\n" +
8044            "OpFunctionEnd",
8045        3, true),
8046     // Test 4: that the OpExtInstImport instruction is generated if it is missing.
8047    InstructionFoldingCase<bool>(
8048            std::string() +
8049            "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
8050            "; CHECK: OpFunction\n" +
8051            "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8052            "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8053            "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8054            "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
8055            "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
8056            "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
8057            "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
8058            "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
8059            "OpCapability Shader\n" +
8060            "OpMemoryModel Logical GLSL450\n" +
8061            "OpEntryPoint Fragment %main \"main\"\n" +
8062            "OpExecutionMode %main OriginUpperLeft\n" +
8063            "OpSource GLSL 140\n" +
8064            "OpName %main \"main\"\n" +
8065            "%void = OpTypeVoid\n" +
8066            "%void_func = OpTypeFunction %void\n" +
8067            "%bool = OpTypeBool\n" +
8068            "%float = OpTypeFloat 32\n" +
8069            "%_ptr_float = OpTypePointer Function %float\n" +
8070            "%main = OpFunction %void None %void_func\n" +
8071            "%main_lab = OpLabel\n" +
8072            "%x = OpVariable %_ptr_float Function\n" +
8073            "%y = OpVariable %_ptr_float Function\n" +
8074            "%a = OpVariable %_ptr_float Function\n" +
8075            "%lx = OpLoad %float %x\n" +
8076            "%ly = OpLoad %float %y\n" +
8077            "%mul = OpFMul %float %lx %ly\n" +
8078            "%la = OpLoad %float %a\n" +
8079            "%3 = OpFAdd %float %mul %la\n" +
8080            "OpStore %a %3\n" +
8081            "OpReturn\n" +
8082            "OpFunctionEnd",
8083        3, true),
8084    // Test 5: Don't fold if the multiple is marked no contract.
8085    InstructionFoldingCase<bool>(
8086        std::string() +
8087            "OpCapability Shader\n" +
8088            "OpMemoryModel Logical GLSL450\n" +
8089            "OpEntryPoint Fragment %main \"main\"\n" +
8090            "OpExecutionMode %main OriginUpperLeft\n" +
8091            "OpSource GLSL 140\n" +
8092            "OpName %main \"main\"\n" +
8093            "OpDecorate %mul NoContraction\n" +
8094            "%void = OpTypeVoid\n" +
8095            "%void_func = OpTypeFunction %void\n" +
8096            "%bool = OpTypeBool\n" +
8097            "%float = OpTypeFloat 32\n" +
8098            "%_ptr_float = OpTypePointer Function %float\n" +
8099            "%main = OpFunction %void None %void_func\n" +
8100            "%main_lab = OpLabel\n" +
8101            "%x = OpVariable %_ptr_float Function\n" +
8102            "%y = OpVariable %_ptr_float Function\n" +
8103            "%a = OpVariable %_ptr_float Function\n" +
8104            "%lx = OpLoad %float %x\n" +
8105            "%ly = OpLoad %float %y\n" +
8106            "%mul = OpFMul %float %lx %ly\n" +
8107            "%la = OpLoad %float %a\n" +
8108            "%3 = OpFAdd %float %mul %la\n" +
8109            "OpStore %a %3\n" +
8110            "OpReturn\n" +
8111            "OpFunctionEnd",
8112        3, false),
8113        // Test 6: Don't fold if the add is marked no contract.
8114        InstructionFoldingCase<bool>(
8115            std::string() +
8116                "OpCapability Shader\n" +
8117                "OpMemoryModel Logical GLSL450\n" +
8118                "OpEntryPoint Fragment %main \"main\"\n" +
8119                "OpExecutionMode %main OriginUpperLeft\n" +
8120                "OpSource GLSL 140\n" +
8121                "OpName %main \"main\"\n" +
8122                "OpDecorate %3 NoContraction\n" +
8123                "%void = OpTypeVoid\n" +
8124                "%void_func = OpTypeFunction %void\n" +
8125                "%bool = OpTypeBool\n" +
8126                "%float = OpTypeFloat 32\n" +
8127                "%_ptr_float = OpTypePointer Function %float\n" +
8128                "%main = OpFunction %void None %void_func\n" +
8129                "%main_lab = OpLabel\n" +
8130                "%x = OpVariable %_ptr_float Function\n" +
8131                "%y = OpVariable %_ptr_float Function\n" +
8132                "%a = OpVariable %_ptr_float Function\n" +
8133                "%lx = OpLoad %float %x\n" +
8134                "%ly = OpLoad %float %y\n" +
8135                "%mul = OpFMul %float %lx %ly\n" +
8136                "%la = OpLoad %float %a\n" +
8137                "%3 = OpFAdd %float %mul %la\n" +
8138                "OpStore %a %3\n" +
8139                "OpReturn\n" +
8140                "OpFunctionEnd",
8141            3, false),
8142     // Test case 7: (x * y) - a = Fma(x, y, -a)
8143     InstructionFoldingCase<bool>(
8144        Header() +
8145            "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
8146            "; CHECK: OpFunction\n" +
8147            "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8148            "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8149            "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8150            "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
8151            "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
8152            "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
8153            "; CHECK: [[na:%\\w+]] = OpFNegate {{%\\w+}} [[la]]\n" +
8154            "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[na]]\n" +
8155            "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
8156            "%main = OpFunction %void None %void_func\n" +
8157            "%main_lab = OpLabel\n" +
8158            "%x = OpVariable %_ptr_float Function\n" +
8159            "%y = OpVariable %_ptr_float Function\n" +
8160            "%a = OpVariable %_ptr_float Function\n" +
8161            "%lx = OpLoad %float %x\n" +
8162            "%ly = OpLoad %float %y\n" +
8163            "%mul = OpFMul %float %lx %ly\n" +
8164            "%la = OpLoad %float %a\n" +
8165            "%3 = OpFSub %float %mul %la\n" +
8166            "OpStore %a %3\n" +
8167            "OpReturn\n" +
8168            "OpFunctionEnd",
8169        3, true),
8170    // Test case 8: a - (x * y) = Fma(-x, y, a)
8171    InstructionFoldingCase<bool>(
8172        Header() +
8173            "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
8174            "; CHECK: OpFunction\n" +
8175            "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8176            "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8177            "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8178            "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
8179            "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
8180            "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
8181            "; CHECK: [[nx:%\\w+]] = OpFNegate {{%\\w+}} [[lx]]\n" +
8182            "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[nx]] [[ly]] [[la]]\n" +
8183            "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
8184            "%main = OpFunction %void None %void_func\n" +
8185            "%main_lab = OpLabel\n" +
8186            "%x = OpVariable %_ptr_float Function\n" +
8187            "%y = OpVariable %_ptr_float Function\n" +
8188            "%a = OpVariable %_ptr_float Function\n" +
8189            "%lx = OpLoad %float %x\n" +
8190            "%ly = OpLoad %float %y\n" +
8191            "%mul = OpFMul %float %lx %ly\n" +
8192            "%la = OpLoad %float %a\n" +
8193            "%3 = OpFSub %float %la %mul\n" +
8194            "OpStore %a %3\n" +
8195            "OpReturn\n" +
8196            "OpFunctionEnd",
8197        3, true)
8198 ));
8199 
8200 using MatchingInstructionWithNoResultFoldingTest =
8201 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8202 
8203 // Test folding instructions that do not have a result.  The instruction
8204 // that will be folded is the last instruction before the return.  If there
8205 // are multiple returns, there is not guarantee which one is used.
TEST_P(MatchingInstructionWithNoResultFoldingTest,Case)8206 TEST_P(MatchingInstructionWithNoResultFoldingTest, Case) {
8207   const auto& tc = GetParam();
8208 
8209   std::unique_ptr<IRContext> context;
8210   Instruction* inst;
8211   std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
8212 
8213   // Find the instruction to test.
8214   EXPECT_EQ(inst != nullptr, tc.expected_result);
8215   if (inst != nullptr) {
8216     Match(tc.test_body, context.get());
8217   }
8218 }
8219 
8220 INSTANTIATE_TEST_SUITE_P(StoreMatchingTest, MatchingInstructionWithNoResultFoldingTest,
8221 ::testing::Values(
8222     // Test case 0: Remove store of undef.
8223     InstructionFoldingCase<bool>(
8224         Header() +
8225             "; CHECK: OpLabel\n" +
8226             "; CHECK-NOT: OpStore\n" +
8227             "; CHECK: OpReturn\n" +
8228             "%main = OpFunction %void None %void_func\n" +
8229             "%main_lab = OpLabel\n" +
8230             "%n = OpVariable %_ptr_v4double Function\n" +
8231             "%undef = OpUndef %v4double\n" +
8232             "OpStore %n %undef\n" +
8233             "OpReturn\n" +
8234             "OpFunctionEnd",
8235         0 /* OpStore */, true),
8236     // Test case 1: Keep volatile store.
8237     InstructionFoldingCase<bool>(
8238         Header() +
8239             "%main = OpFunction %void None %void_func\n" +
8240             "%main_lab = OpLabel\n" +
8241             "%n = OpVariable %_ptr_v4double Function\n" +
8242             "%undef = OpUndef %v4double\n" +
8243             "OpStore %n %undef Volatile\n" +
8244             "OpReturn\n" +
8245             "OpFunctionEnd",
8246         0 /* OpStore */, false)
8247 ));
8248 
8249 INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoResultFoldingTest,
8250 ::testing::Values(
8251     // Test case 0: Basic test 1
8252     InstructionFoldingCase<bool>(
8253         Header() +
8254             "; CHECK: OpVectorShuffle\n" +
8255             "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 3 6 7\n" +
8256             "; CHECK: OpReturn\n" +
8257             "%main = OpFunction %void None %void_func\n" +
8258             "%main_lab = OpLabel\n" +
8259             "%2 = OpVariable %_ptr_v4double Function\n" +
8260             "%3 = OpVariable %_ptr_v4double Function\n" +
8261             "%4 = OpVariable %_ptr_v4double Function\n" +
8262             "%5 = OpLoad %v4double %2\n" +
8263             "%6 = OpLoad %v4double %3\n" +
8264             "%7 = OpLoad %v4double %4\n" +
8265             "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8266             "%9 = OpVectorShuffle %v4double %7 %8 2 3 4 5\n" +
8267             "OpReturn\n" +
8268             "OpFunctionEnd",
8269         9, true),
8270     // Test case 1: Basic test 2
8271     InstructionFoldingCase<bool>(
8272         Header() +
8273             "; CHECK: OpVectorShuffle\n" +
8274             "; CHECK: OpVectorShuffle {{%\\w+}} %6 %7 0 1 4 5\n" +
8275             "; CHECK: OpReturn\n" +
8276             "%main = OpFunction %void None %void_func\n" +
8277             "%main_lab = OpLabel\n" +
8278             "%2 = OpVariable %_ptr_v4double Function\n" +
8279             "%3 = OpVariable %_ptr_v4double Function\n" +
8280             "%4 = OpVariable %_ptr_v4double Function\n" +
8281             "%5 = OpLoad %v4double %2\n" +
8282             "%6 = OpLoad %v4double %3\n" +
8283             "%7 = OpLoad %v4double %4\n" +
8284             "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8285             "%9 = OpVectorShuffle %v4double %8 %7 2 3 4 5\n" +
8286             "OpReturn\n" +
8287             "OpFunctionEnd",
8288         9, true),
8289     // Test case 2: Basic test 3
8290     InstructionFoldingCase<bool>(
8291         Header() +
8292             "; CHECK: OpVectorShuffle\n" +
8293             "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 2 4 5\n" +
8294             "; CHECK: OpReturn\n" +
8295             "%main = OpFunction %void None %void_func\n" +
8296             "%main_lab = OpLabel\n" +
8297             "%2 = OpVariable %_ptr_v4double Function\n" +
8298             "%3 = OpVariable %_ptr_v4double Function\n" +
8299             "%4 = OpVariable %_ptr_v4double Function\n" +
8300             "%5 = OpLoad %v4double %2\n" +
8301             "%6 = OpLoad %v4double %3\n" +
8302             "%7 = OpLoad %v4double %4\n" +
8303             "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8304             "%9 = OpVectorShuffle %v4double %8 %7 1 0 4 5\n" +
8305             "OpReturn\n" +
8306             "OpFunctionEnd",
8307         9, true),
8308     // Test case 3: Basic test 4
8309     InstructionFoldingCase<bool>(
8310         Header() +
8311             "; CHECK: OpVectorShuffle\n" +
8312             "; CHECK: OpVectorShuffle {{%\\w+}} %7 %6 2 3 5 4\n" +
8313             "; CHECK: OpReturn\n" +
8314             "%main = OpFunction %void None %void_func\n" +
8315             "%main_lab = OpLabel\n" +
8316             "%2 = OpVariable %_ptr_v4double Function\n" +
8317             "%3 = OpVariable %_ptr_v4double Function\n" +
8318             "%4 = OpVariable %_ptr_v4double Function\n" +
8319             "%5 = OpLoad %v4double %2\n" +
8320             "%6 = OpLoad %v4double %3\n" +
8321             "%7 = OpLoad %v4double %4\n" +
8322             "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8323             "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 6\n" +
8324             "OpReturn\n" +
8325             "OpFunctionEnd",
8326         9, true),
8327     // Test case 4: Don't fold, need both operands of the feeder.
8328     InstructionFoldingCase<bool>(
8329         Header() +
8330             "%main = OpFunction %void None %void_func\n" +
8331             "%main_lab = OpLabel\n" +
8332             "%2 = OpVariable %_ptr_v4double Function\n" +
8333             "%3 = OpVariable %_ptr_v4double Function\n" +
8334             "%4 = OpVariable %_ptr_v4double Function\n" +
8335             "%5 = OpLoad %v4double %2\n" +
8336             "%6 = OpLoad %v4double %3\n" +
8337             "%7 = OpLoad %v4double %4\n" +
8338             "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8339             "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 5\n" +
8340             "OpReturn\n" +
8341             "OpFunctionEnd",
8342         9, false),
8343     // Test case 5: Don't fold, need both operands of the feeder.
8344     InstructionFoldingCase<bool>(
8345         Header() +
8346             "%main = OpFunction %void None %void_func\n" +
8347             "%main_lab = OpLabel\n" +
8348             "%2 = OpVariable %_ptr_v4double Function\n" +
8349             "%3 = OpVariable %_ptr_v4double Function\n" +
8350             "%4 = OpVariable %_ptr_v4double Function\n" +
8351             "%5 = OpLoad %v4double %2\n" +
8352             "%6 = OpLoad %v4double %3\n" +
8353             "%7 = OpLoad %v4double %4\n" +
8354             "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8355             "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
8356             "OpReturn\n" +
8357             "OpFunctionEnd",
8358         9, false),
8359     // Test case 6: Fold, need both operands of the feeder, but they are the same.
8360     InstructionFoldingCase<bool>(
8361         Header() +
8362             "; CHECK: OpVectorShuffle\n" +
8363             "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 2 7 5\n" +
8364             "; CHECK: OpReturn\n" +
8365             "%main = OpFunction %void None %void_func\n" +
8366             "%main_lab = OpLabel\n" +
8367             "%2 = OpVariable %_ptr_v4double Function\n" +
8368             "%3 = OpVariable %_ptr_v4double Function\n" +
8369             "%4 = OpVariable %_ptr_v4double Function\n" +
8370             "%5 = OpLoad %v4double %2\n" +
8371             "%6 = OpLoad %v4double %3\n" +
8372             "%7 = OpLoad %v4double %4\n" +
8373             "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
8374             "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
8375             "OpReturn\n" +
8376             "OpFunctionEnd",
8377         9, true),
8378     // Test case 7: Fold, need both operands of the feeder, but they are the same.
8379     InstructionFoldingCase<bool>(
8380         Header() +
8381             "; CHECK: OpVectorShuffle\n" +
8382             "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 0 5 7\n" +
8383             "; CHECK: OpReturn\n" +
8384             "%main = OpFunction %void None %void_func\n" +
8385             "%main_lab = OpLabel\n" +
8386             "%2 = OpVariable %_ptr_v4double Function\n" +
8387             "%3 = OpVariable %_ptr_v4double Function\n" +
8388             "%4 = OpVariable %_ptr_v4double Function\n" +
8389             "%5 = OpLoad %v4double %2\n" +
8390             "%6 = OpLoad %v4double %3\n" +
8391             "%7 = OpLoad %v4double %4\n" +
8392             "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
8393             "%9 = OpVectorShuffle %v4double %7 %8 2 0 7 5\n" +
8394             "OpReturn\n" +
8395             "OpFunctionEnd",
8396         9, true),
8397     // Test case 8: Replace first operand with a smaller vector.
8398     InstructionFoldingCase<bool>(
8399         Header() +
8400             "; CHECK: OpVectorShuffle\n" +
8401             "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 0 5 3\n" +
8402             "; CHECK: OpReturn\n" +
8403             "%main = OpFunction %void None %void_func\n" +
8404             "%main_lab = OpLabel\n" +
8405             "%2 = OpVariable %_ptr_v2double Function\n" +
8406             "%3 = OpVariable %_ptr_v4double Function\n" +
8407             "%4 = OpVariable %_ptr_v4double Function\n" +
8408             "%5 = OpLoad %v2double %2\n" +
8409             "%6 = OpLoad %v4double %3\n" +
8410             "%7 = OpLoad %v4double %4\n" +
8411             "%8 = OpVectorShuffle %v4double %5 %5 0 1 2 3\n" +
8412             "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
8413             "OpReturn\n" +
8414             "OpFunctionEnd",
8415         9, true),
8416     // Test case 9: Replace first operand with a larger vector.
8417     InstructionFoldingCase<bool>(
8418         Header() +
8419             "; CHECK: OpVectorShuffle\n" +
8420             "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 0 7 5\n" +
8421             "; CHECK: OpReturn\n" +
8422             "%main = OpFunction %void None %void_func\n" +
8423             "%main_lab = OpLabel\n" +
8424             "%2 = OpVariable %_ptr_v4double Function\n" +
8425             "%3 = OpVariable %_ptr_v4double Function\n" +
8426             "%4 = OpVariable %_ptr_v4double Function\n" +
8427             "%5 = OpLoad %v4double %2\n" +
8428             "%6 = OpLoad %v4double %3\n" +
8429             "%7 = OpLoad %v4double %4\n" +
8430             "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8431             "%9 = OpVectorShuffle %v4double %8 %7 1 0 5 3\n" +
8432             "OpReturn\n" +
8433             "OpFunctionEnd",
8434         9, true),
8435     // Test case 10: Replace unused operand with null.
8436     InstructionFoldingCase<bool>(
8437         Header() +
8438             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8439             "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8440             "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
8441             "; CHECK: OpVectorShuffle\n" +
8442             "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %7 4 2 5 3\n" +
8443             "; CHECK: OpReturn\n" +
8444             "%main = OpFunction %void None %void_func\n" +
8445             "%main_lab = OpLabel\n" +
8446             "%2 = OpVariable %_ptr_v4double Function\n" +
8447             "%3 = OpVariable %_ptr_v4double Function\n" +
8448             "%4 = OpVariable %_ptr_v4double Function\n" +
8449             "%5 = OpLoad %v4double %2\n" +
8450             "%6 = OpLoad %v4double %3\n" +
8451             "%7 = OpLoad %v4double %4\n" +
8452             "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8453             "%9 = OpVectorShuffle %v4double %8 %7 4 2 5 3\n" +
8454             "OpReturn\n" +
8455             "OpFunctionEnd",
8456         9, true),
8457     // Test case 11: Replace unused operand with null.
8458     InstructionFoldingCase<bool>(
8459         Header() +
8460             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8461             "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8462             "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
8463             "; CHECK: OpVectorShuffle\n" +
8464             "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %5 2 2 5 5\n" +
8465             "; CHECK: OpReturn\n" +
8466             "%main = OpFunction %void None %void_func\n" +
8467             "%main_lab = OpLabel\n" +
8468             "%2 = OpVariable %_ptr_v4double Function\n" +
8469             "%3 = OpVariable %_ptr_v4double Function\n" +
8470             "%5 = OpLoad %v4double %2\n" +
8471             "%6 = OpLoad %v4double %3\n" +
8472             "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8473             "%9 = OpVectorShuffle %v4double %8 %8 2 2 3 3\n" +
8474             "OpReturn\n" +
8475             "OpFunctionEnd",
8476         9, true),
8477     // Test case 12: Replace unused operand with null.
8478     InstructionFoldingCase<bool>(
8479         Header() +
8480             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8481             "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8482             "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
8483             "; CHECK: OpVectorShuffle\n" +
8484             "; CHECK: OpVectorShuffle {{%\\w+}} %7 [[null]] 2 0 1 3\n" +
8485             "; CHECK: OpReturn\n" +
8486             "%main = OpFunction %void None %void_func\n" +
8487             "%main_lab = OpLabel\n" +
8488             "%2 = OpVariable %_ptr_v4double Function\n" +
8489             "%3 = OpVariable %_ptr_v4double Function\n" +
8490             "%4 = OpVariable %_ptr_v4double Function\n" +
8491             "%5 = OpLoad %v4double %2\n" +
8492             "%6 = OpLoad %v4double %3\n" +
8493             "%7 = OpLoad %v4double %4\n" +
8494             "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8495             "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" +
8496             "OpReturn\n" +
8497             "OpFunctionEnd",
8498         9, true),
8499     // Test case 13: Shuffle with undef literal.
8500     InstructionFoldingCase<bool>(
8501         Header() +
8502             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8503             "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8504             "; CHECK: OpVectorShuffle\n" +
8505             "; CHECK: OpVectorShuffle {{%\\w+}} %7 {{%\\w+}} 2 0 1 4294967295\n" +
8506             "; CHECK: OpReturn\n" +
8507             "%main = OpFunction %void None %void_func\n" +
8508             "%main_lab = OpLabel\n" +
8509             "%2 = OpVariable %_ptr_v4double Function\n" +
8510             "%3 = OpVariable %_ptr_v4double Function\n" +
8511             "%4 = OpVariable %_ptr_v4double Function\n" +
8512             "%5 = OpLoad %v4double %2\n" +
8513             "%6 = OpLoad %v4double %3\n" +
8514             "%7 = OpLoad %v4double %4\n" +
8515             "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
8516             "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" +
8517             "OpReturn\n" +
8518             "OpFunctionEnd",
8519         9, true),
8520     // Test case 14: Shuffle with undef literal and change size of first input vector.
8521     InstructionFoldingCase<bool>(
8522         Header() +
8523             "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8524             "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8525             "; CHECK: OpVectorShuffle\n" +
8526             "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 1 4 4294967295\n" +
8527             "; CHECK: OpReturn\n" +
8528             "%main = OpFunction %void None %void_func\n" +
8529             "%main_lab = OpLabel\n" +
8530             "%2 = OpVariable %_ptr_v4double Function\n" +
8531             "%3 = OpVariable %_ptr_v4double Function\n" +
8532             "%4 = OpVariable %_ptr_v4double Function\n" +
8533             "%5 = OpLoad %v4double %2\n" +
8534             "%6 = OpLoad %v4double %3\n" +
8535             "%7 = OpLoad %v4double %4\n" +
8536             "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
8537             "%9 = OpVectorShuffle %v4double %8 %7 0 1 2 4294967295\n" +
8538             "OpReturn\n" +
8539             "OpFunctionEnd",
8540         9, true)
8541 ));
8542 
8543 using EntryPointFoldingTest =
8544 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8545 
TEST_P(EntryPointFoldingTest,Case)8546 TEST_P(EntryPointFoldingTest, Case) {
8547   const auto& tc = GetParam();
8548 
8549   // Build module.
8550   std::unique_ptr<IRContext> context =
8551       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
8552                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
8553   ASSERT_NE(nullptr, context);
8554 
8555   // Find the first entry point. That is the instruction we want to fold.
8556   Instruction* inst = nullptr;
8557   ASSERT_FALSE(context->module()->entry_points().empty());
8558   inst = &*context->module()->entry_points().begin();
8559   assert(inst && "Invalid test.  Could not find entry point instruction to fold.");
8560   std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
8561   bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
8562   EXPECT_EQ(succeeded, tc.expected_result);
8563   if (succeeded) {
8564     Match(tc.test_body, context.get());
8565   }
8566 }
8567 
8568 INSTANTIATE_TEST_SUITE_P(OpEntryPointFoldingTest, EntryPointFoldingTest,
8569 ::testing::Values(
8570     // Test case 0: Basic test 1
8571     InstructionFoldingCase<bool>(std::string() +
8572                     "; CHECK: OpEntryPoint Fragment %2 \"main\" %3\n" +
8573                              "OpCapability Shader\n" +
8574                         "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
8575                              "OpMemoryModel Logical GLSL450\n" +
8576                              "OpEntryPoint Fragment %2 \"main\" %3 %3 %3\n" +
8577                              "OpExecutionMode %2 OriginUpperLeft\n" +
8578                              "OpSource GLSL 430\n" +
8579                              "OpDecorate %3 Location 0\n" +
8580                      "%void = OpTypeVoid\n" +
8581                         "%5 = OpTypeFunction %void\n" +
8582                     "%float = OpTypeFloat 32\n" +
8583                   "%v4float = OpTypeVector %float 4\n" +
8584       "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
8585                         "%3 = OpVariable %_ptr_Output_v4float Output\n" +
8586                       "%int = OpTypeInt 32 1\n" +
8587                     "%int_0 = OpConstant %int 0\n" +
8588 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
8589                         "%2 = OpFunction %void None %5\n" +
8590                        "%12 = OpLabel\n" +
8591                              "OpReturn\n" +
8592                              "OpFunctionEnd\n",
8593         9, true),
8594     InstructionFoldingCase<bool>(std::string() +
8595                     "; CHECK: OpEntryPoint Fragment %2 \"main\" %3 %4\n" +
8596                              "OpCapability Shader\n" +
8597                         "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
8598                              "OpMemoryModel Logical GLSL450\n" +
8599                              "OpEntryPoint Fragment %2 \"main\" %3 %4 %3\n" +
8600                              "OpExecutionMode %2 OriginUpperLeft\n" +
8601                              "OpSource GLSL 430\n" +
8602                              "OpDecorate %3 Location 0\n" +
8603                      "%void = OpTypeVoid\n" +
8604                         "%5 = OpTypeFunction %void\n" +
8605                     "%float = OpTypeFloat 32\n" +
8606                   "%v4float = OpTypeVector %float 4\n" +
8607       "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
8608                         "%3 = OpVariable %_ptr_Output_v4float Output\n" +
8609                         "%4 = OpVariable %_ptr_Output_v4float Output\n" +
8610                       "%int = OpTypeInt 32 1\n" +
8611                     "%int_0 = OpConstant %int 0\n" +
8612 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
8613                         "%2 = OpFunction %void None %5\n" +
8614                        "%12 = OpLabel\n" +
8615                              "OpReturn\n" +
8616                              "OpFunctionEnd\n",
8617         9, true),
8618     InstructionFoldingCase<bool>(std::string() +
8619                     "; CHECK: OpEntryPoint Fragment %2 \"main\" %4 %3\n" +
8620                              "OpCapability Shader\n" +
8621                         "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
8622                              "OpMemoryModel Logical GLSL450\n" +
8623                              "OpEntryPoint Fragment %2 \"main\" %4 %4 %3\n" +
8624                              "OpExecutionMode %2 OriginUpperLeft\n" +
8625                              "OpSource GLSL 430\n" +
8626                              "OpDecorate %3 Location 0\n" +
8627                      "%void = OpTypeVoid\n" +
8628                         "%5 = OpTypeFunction %void\n" +
8629                     "%float = OpTypeFloat 32\n" +
8630                   "%v4float = OpTypeVector %float 4\n" +
8631       "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
8632                         "%3 = OpVariable %_ptr_Output_v4float Output\n" +
8633                         "%4 = OpVariable %_ptr_Output_v4float Output\n" +
8634                       "%int = OpTypeInt 32 1\n" +
8635                     "%int_0 = OpConstant %int 0\n" +
8636 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
8637                         "%2 = OpFunction %void None %5\n" +
8638                        "%12 = OpLabel\n" +
8639                              "OpReturn\n" +
8640                              "OpFunctionEnd\n",
8641         9, true)
8642 ));
8643 
8644 using SPV14FoldingTest =
8645 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8646 
TEST_P(SPV14FoldingTest,Case)8647 TEST_P(SPV14FoldingTest, Case) {
8648   const auto& tc = GetParam();
8649 
8650   std::unique_ptr<IRContext> context;
8651   Instruction* inst;
8652   std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_4);
8653 
8654   EXPECT_EQ(inst != nullptr, tc.expected_result);
8655   if (inst !=  nullptr) {
8656     Match(tc.test_body, context.get());
8657   }
8658 }
8659 
8660 INSTANTIATE_TEST_SUITE_P(SPV14FoldingTest, SPV14FoldingTest,
8661 ::testing::Values(
8662     // Test case 0: select vectors with scalar condition.
8663     InstructionFoldingCase<bool>(std::string() +
8664 "; CHECK-NOT: OpSelect\n" +
8665 "; CHECK: %3 = OpCopyObject {{%\\w+}} %1\n" +
8666 "OpCapability Shader\n" +
8667 "OpCapability Linkage\n" +
8668 "%void = OpTypeVoid\n" +
8669 "%bool = OpTypeBool\n" +
8670 "%true = OpConstantTrue %bool\n" +
8671 "%int = OpTypeInt 32 0\n" +
8672 "%int4 = OpTypeVector %int 4\n" +
8673 "%int_0 = OpConstant %int 0\n" +
8674 "%int_1 = OpConstant %int 1\n" +
8675 "%1 = OpUndef %int4\n" +
8676 "%2 = OpUndef %int4\n" +
8677 "%void_fn = OpTypeFunction %void\n" +
8678 "%func = OpFunction %void None %void_fn\n" +
8679 "%entry = OpLabel\n" +
8680 "%3 = OpSelect %int4 %true %1 %2\n" +
8681 "OpReturn\n" +
8682 "OpFunctionEnd\n"
8683 ,
8684                                  3, true),
8685     // Test case 1: select struct with scalar condition.
8686     InstructionFoldingCase<bool>(std::string() +
8687 "; CHECK-NOT: OpSelect\n" +
8688 "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
8689 "OpCapability Shader\n" +
8690 "OpCapability Linkage\n" +
8691 "%void = OpTypeVoid\n" +
8692 "%bool = OpTypeBool\n" +
8693 "%true = OpConstantFalse %bool\n" +
8694 "%int = OpTypeInt 32 0\n" +
8695 "%struct = OpTypeStruct %int %int %int %int\n" +
8696 "%int_0 = OpConstant %int 0\n" +
8697 "%int_1 = OpConstant %int 1\n" +
8698 "%1 = OpUndef %struct\n" +
8699 "%2 = OpUndef %struct\n" +
8700 "%void_fn = OpTypeFunction %void\n" +
8701 "%func = OpFunction %void None %void_fn\n" +
8702 "%entry = OpLabel\n" +
8703 "%3 = OpSelect %struct %true %1 %2\n" +
8704 "OpReturn\n" +
8705 "OpFunctionEnd\n"
8706 ,
8707                                  3, true),
8708     // Test case 1: select array with scalar condition.
8709     InstructionFoldingCase<bool>(std::string() +
8710 "; CHECK-NOT: OpSelect\n" +
8711 "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
8712 "OpCapability Shader\n" +
8713 "OpCapability Linkage\n" +
8714 "%void = OpTypeVoid\n" +
8715 "%bool = OpTypeBool\n" +
8716 "%true = OpConstantFalse %bool\n" +
8717 "%int = OpTypeInt 32 0\n" +
8718 "%int_0 = OpConstant %int 0\n" +
8719 "%int_1 = OpConstant %int 1\n" +
8720 "%int_4 = OpConstant %int 4\n" +
8721 "%array = OpTypeStruct %int %int %int %int\n" +
8722 "%1 = OpUndef %array\n" +
8723 "%2 = OpUndef %array\n" +
8724 "%void_fn = OpTypeFunction %void\n" +
8725 "%func = OpFunction %void None %void_fn\n" +
8726 "%entry = OpLabel\n" +
8727 "%3 = OpSelect %array %true %1 %2\n" +
8728 "OpReturn\n" +
8729 "OpFunctionEnd\n"
8730 ,
8731                                  3, true)
8732 ));
8733 
FloatControlsHeader(const std::string & capabilities)8734 std::string FloatControlsHeader(const std::string& capabilities) {
8735   std::string header = R"(
8736 OpCapability Shader
8737 )" + capabilities + R"(
8738 %void = OpTypeVoid
8739 %float = OpTypeFloat 32
8740 %float_0 = OpConstant %float 0
8741 %float_1 = OpConstant %float 1
8742 %void_fn = OpTypeFunction %void
8743 %func = OpFunction %void None %void_fn
8744 %entry = OpLabel
8745 )";
8746 
8747   return header;
8748 }
8749 
8750 using FloatControlsFoldingTest =
8751 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8752 
TEST_P(FloatControlsFoldingTest,Case)8753 TEST_P(FloatControlsFoldingTest, Case) {
8754   const auto& tc = GetParam();
8755 
8756   std::unique_ptr<IRContext> context;
8757   Instruction* inst;
8758   std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_4);
8759 
8760   EXPECT_EQ(inst != nullptr, tc.expected_result);
8761   if (inst != nullptr) {
8762     Match(tc.test_body, context.get());
8763   }
8764 }
8765 
8766 INSTANTIATE_TEST_SUITE_P(FloatControlsFoldingTest, FloatControlsFoldingTest,
8767 ::testing::Values(
8768     // Test case 0: no folding with DenormPreserve
8769     InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormPreserve") +
8770                                  "%1 = OpFAdd %float %float_0 %float_1\n" +
8771                                  "OpReturn\n" +
8772                                  "OpFunctionEnd\n"
8773 ,
8774                                  1, false),
8775     // Test case 1: no folding with DenormFlushToZero
8776     InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormFlushToZero") +
8777                                  "%1 = OpFAdd %float %float_0 %float_1\n" +
8778                                  "OpReturn\n" +
8779                                  "OpFunctionEnd\n"
8780 ,
8781                                  1, false),
8782     // Test case 2: no folding with SignedZeroInfNanPreserve
8783     InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability SignedZeroInfNanPreserve") +
8784                                  "%1 = OpFAdd %float %float_0 %float_1\n" +
8785                                  "OpReturn\n" +
8786                                  "OpFunctionEnd\n"
8787 ,
8788                                  1, false),
8789     // Test case 3: no folding with RoundingModeRTE
8790     InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTE") +
8791                                  "%1 = OpFAdd %float %float_0 %float_1\n" +
8792                                  "OpReturn\n" +
8793                                  "OpFunctionEnd\n"
8794 ,
8795                                  1, false),
8796     // Test case 4: no folding with RoundingModeRTZ
8797     InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTZ") +
8798                                  "%1 = OpFAdd %float %float_0 %float_1\n" +
8799                                  "OpReturn\n" +
8800                                  "OpFunctionEnd\n"
8801 ,
8802                                  1, false)
8803 ));
8804 
ImageOperandsTestBody(const std::string & image_instruction)8805 std::string ImageOperandsTestBody(const std::string& image_instruction) {
8806   std::string body = R"(
8807                OpCapability Shader
8808                OpCapability ImageGatherExtended
8809                OpMemoryModel Logical GLSL450
8810                OpEntryPoint Fragment %main "main"
8811                OpExecutionMode %main OriginUpperLeft
8812                OpDecorate %Texture DescriptorSet 0
8813                OpDecorate %Texture Binding 0
8814         %int = OpTypeInt 32 1
8815      %int_n1 = OpConstant %int -1
8816           %5 = OpConstant %int 0
8817       %float = OpTypeFloat 32
8818     %float_0 = OpConstant %float 0
8819 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
8820 %type_sampled_image = OpTypeSampledImage %type_2d_image
8821 %type_sampler = OpTypeSampler
8822 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
8823 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
8824    %_ptr_int = OpTypePointer Function %int
8825       %v2int = OpTypeVector %int 2
8826          %10 = OpTypeVector %float 4
8827        %void = OpTypeVoid
8828          %22 = OpTypeFunction %void
8829     %v2float = OpTypeVector %float 2
8830       %v3int = OpTypeVector %int 3
8831     %Texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
8832    %gSampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
8833         %110 = OpConstantComposite %v2int %5 %5
8834         %101 = OpConstantComposite %v2int %int_n1 %int_n1
8835          %20 = OpConstantComposite %v2float %float_0 %float_0
8836        %main = OpFunction %void None %22
8837          %23 = OpLabel
8838         %var = OpVariable %_ptr_int Function
8839          %88 = OpLoad %type_2d_image %Texture
8840         %val = OpLoad %int %var
8841     %sampler = OpLoad %type_sampler %gSampler
8842          %26 = OpSampledImage %type_sampled_image %88 %sampler
8843 )" + image_instruction + R"(
8844                OpReturn
8845                OpFunctionEnd
8846 )";
8847 
8848   return body;
8849 }
8850 
8851 INSTANTIATE_TEST_SUITE_P(ImageOperandsBitmaskFoldingTest, MatchingInstructionWithNoResultFoldingTest,
8852 ::testing::Values(
8853     // Test case 0: OpImageFetch without Offset
8854     InstructionFoldingCase<bool>(ImageOperandsTestBody(
8855         "%89 = OpImageFetch %10 %88 %101 Lod %5 \n")
8856         , 89, false),
8857     // Test case 1: OpImageFetch with non-const offset
8858     InstructionFoldingCase<bool>(ImageOperandsTestBody(
8859         "%89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %val \n")
8860         , 89, false),
8861     // Test case 2: OpImageFetch with Lod and Offset
8862     InstructionFoldingCase<bool>(ImageOperandsTestBody(
8863       "         %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %101      \n"
8864       "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod|ConstOffset %5 %101 \n")
8865       , 89, true),
8866     // Test case 3: OpImageFetch with Bias and Offset
8867     InstructionFoldingCase<bool>(ImageOperandsTestBody(
8868       "         %89 = OpImageFetch %10 %88 %101 Bias|Offset %5 %101      \n"
8869       "; CHECK: %89 = OpImageFetch %10 %88 %101 Bias|ConstOffset %5 %101 \n")
8870       , 89, true),
8871     // Test case 4: OpImageFetch with Grad and Offset.
8872     // Grad adds 2 operands to the instruction.
8873     InstructionFoldingCase<bool>(ImageOperandsTestBody(
8874       "         %89 = OpImageFetch %10 %88 %101 Grad|Offset %5 %5 %101      \n"
8875       "; CHECK: %89 = OpImageFetch %10 %88 %101 Grad|ConstOffset %5 %5 %101 \n")
8876       , 89, true),
8877     // Test case 5: OpImageFetch with Offset and MinLod.
8878     // This is an example of a case where the bitmask bit-offset is larger than
8879     // that of the Offset.
8880     InstructionFoldingCase<bool>(ImageOperandsTestBody(
8881       "         %89 = OpImageFetch %10 %88 %101 Offset|MinLod %101 %5      \n"
8882       "; CHECK: %89 = OpImageFetch %10 %88 %101 ConstOffset|MinLod %101 %5 \n")
8883       , 89, true),
8884     // Test case 6: OpImageGather with constant Offset
8885     InstructionFoldingCase<bool>(ImageOperandsTestBody(
8886       "         %89 = OpImageGather %10 %26 %20 %5 Offset %101      \n"
8887       "; CHECK: %89 = OpImageGather %10 %26 %20 %5 ConstOffset %101 \n")
8888       , 89, true),
8889     // Test case 7: OpImageWrite with constant Offset
8890     InstructionFoldingCase<bool>(ImageOperandsTestBody(
8891       "         OpImageWrite %88 %5 %101 Offset %101      \n"
8892       "; CHECK: OpImageWrite %88 %5 %101 ConstOffset %101 \n")
8893       , 0 /* No result-id */, true),
8894     // Test case 8: OpImageFetch with zero constant Offset
8895     InstructionFoldingCase<bool>(ImageOperandsTestBody(
8896         "         %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %110      \n"
8897         "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod %5 \n")
8898         , 89, true)
8899 ));
8900 
8901 }  // namespace
8902 }  // namespace opt
8903 }  // namespace spvtools
8904