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 <limits>
15 #include <memory>
16 #include <string>
17 #include <unordered_set>
18 #include <vector>
19
20 #include "effcee/effcee.h"
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "source/opt/build_module.h"
24 #include "source/opt/def_use_manager.h"
25 #include "source/opt/fold.h"
26 #include "source/opt/ir_context.h"
27 #include "source/opt/module.h"
28 #include "spirv-tools/libspirv.hpp"
29 #include "test/opt/pass_utils.h"
30
31 namespace spvtools {
32 namespace opt {
33 namespace {
34
35 using ::testing::Contains;
36
Disassemble(const std::string & original,IRContext * context,uint32_t disassemble_options=0)37 std::string Disassemble(const std::string& original, IRContext* context,
38 uint32_t disassemble_options = 0) {
39 std::vector<uint32_t> optimized_bin;
40 context->module()->ToBinary(&optimized_bin, true);
41 spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
42 SpirvTools tools(target_env);
43 std::string optimized_asm;
44 EXPECT_TRUE(
45 tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options))
46 << "Disassembling failed for shader:\n"
47 << original << std::endl;
48 return optimized_asm;
49 }
50
Match(const std::string & original,IRContext * context,uint32_t disassemble_options=0)51 void Match(const std::string& original, IRContext* context,
52 uint32_t disassemble_options = 0) {
53 std::string disassembly = Disassemble(original, context, disassemble_options);
54 auto match_result = effcee::Match(disassembly, original);
55 EXPECT_EQ(effcee::Result::Status::Ok, match_result.status())
56 << match_result.message() << "\nChecking result:\n"
57 << disassembly;
58 }
59
60 template <class ResultType>
61 struct InstructionFoldingCase {
InstructionFoldingCasespvtools::opt::__anonaa214b840111::InstructionFoldingCase62 InstructionFoldingCase(const std::string& tb, uint32_t id, ResultType result)
63 : test_body(tb), id_to_fold(id), expected_result(result) {}
64
65 std::string test_body;
66 uint32_t id_to_fold;
67 ResultType expected_result;
68 };
69
70 using IntegerInstructionFoldingTest =
71 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
72
TEST_P(IntegerInstructionFoldingTest,Case)73 TEST_P(IntegerInstructionFoldingTest, Case) {
74 const auto& tc = GetParam();
75
76 // Build module.
77 std::unique_ptr<IRContext> context =
78 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
79 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
80 ASSERT_NE(nullptr, context);
81
82 // Fold the instruction to test.
83 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
84 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
85 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
86
87 // Make sure the instruction folded as expected.
88 EXPECT_TRUE(succeeded);
89 if (inst != nullptr) {
90 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
91 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
92 EXPECT_EQ(inst->opcode(), SpvOpConstant);
93 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
94 const analysis::IntConstant* result =
95 const_mrg->GetConstantFromInst(inst)->AsIntConstant();
96 EXPECT_NE(result, nullptr);
97 if (result != nullptr) {
98 EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
99 }
100 }
101 }
102
103 // Returns a common SPIR-V header for all of the test that follow.
104 #define INT_0_ID 100
105 #define TRUE_ID 101
106 #define VEC2_0_ID 102
107 #define INT_7_ID 103
108 #define FLOAT_0_ID 104
109 #define DOUBLE_0_ID 105
110 #define VEC4_0_ID 106
111 #define DVEC4_0_ID 106
112 #define HALF_0_ID 108
Header()113 const std::string& Header() {
114 static const std::string header = R"(OpCapability Shader
115 OpCapability Float16
116 OpCapability Float64
117 OpCapability Int16
118 OpCapability Int64
119 %1 = OpExtInstImport "GLSL.std.450"
120 OpMemoryModel Logical GLSL450
121 OpEntryPoint Fragment %main "main"
122 OpExecutionMode %main OriginUpperLeft
123 OpSource GLSL 140
124 OpName %main "main"
125 %void = OpTypeVoid
126 %void_func = OpTypeFunction %void
127 %bool = OpTypeBool
128 %float = OpTypeFloat 32
129 %double = OpTypeFloat 64
130 %half = OpTypeFloat 16
131 %101 = OpConstantTrue %bool ; Need a def with an numerical id to define id maps.
132 %true = OpConstantTrue %bool
133 %false = OpConstantFalse %bool
134 %bool_null = OpConstantNull %bool
135 %short = OpTypeInt 16 1
136 %int = OpTypeInt 32 1
137 %long = OpTypeInt 64 1
138 %uint = OpTypeInt 32 0
139 %v2int = OpTypeVector %int 2
140 %v4int = OpTypeVector %int 4
141 %v4float = OpTypeVector %float 4
142 %v4double = OpTypeVector %double 4
143 %v2float = OpTypeVector %float 2
144 %v2double = OpTypeVector %double 2
145 %v2bool = OpTypeVector %bool 2
146 %struct_v2int_int_int = OpTypeStruct %v2int %int %int
147 %_ptr_int = OpTypePointer Function %int
148 %_ptr_uint = OpTypePointer Function %uint
149 %_ptr_bool = OpTypePointer Function %bool
150 %_ptr_float = OpTypePointer Function %float
151 %_ptr_double = OpTypePointer Function %double
152 %_ptr_half = OpTypePointer Function %half
153 %_ptr_long = OpTypePointer Function %long
154 %_ptr_v2int = OpTypePointer Function %v2int
155 %_ptr_v4int = OpTypePointer Function %v4int
156 %_ptr_v4float = OpTypePointer Function %v4float
157 %_ptr_v4double = OpTypePointer Function %v4double
158 %_ptr_struct_v2int_int_int = OpTypePointer Function %struct_v2int_int_int
159 %_ptr_v2float = OpTypePointer Function %v2float
160 %_ptr_v2double = OpTypePointer Function %v2double
161 %short_0 = OpConstant %short 0
162 %short_2 = OpConstant %short 2
163 %short_3 = OpConstant %short 3
164 %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps.
165 %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps.
166 %int_0 = OpConstant %int 0
167 %int_1 = OpConstant %int 1
168 %int_2 = OpConstant %int 2
169 %int_3 = OpConstant %int 3
170 %int_4 = OpConstant %int 4
171 %int_n24 = OpConstant %int -24
172 %int_min = OpConstant %int -2147483648
173 %int_max = OpConstant %int 2147483647
174 %long_0 = OpConstant %long 0
175 %long_2 = OpConstant %long 2
176 %long_3 = OpConstant %long 3
177 %uint_0 = OpConstant %uint 0
178 %uint_1 = OpConstant %uint 1
179 %uint_2 = OpConstant %uint 2
180 %uint_3 = OpConstant %uint 3
181 %uint_4 = OpConstant %uint 4
182 %uint_32 = OpConstant %uint 32
183 %uint_42 = OpConstant %uint 42
184 %uint_max = OpConstant %uint 4294967295
185 %v2int_undef = OpUndef %v2int
186 %v2int_0_0 = OpConstantComposite %v2int %int_0 %int_0
187 %v2int_1_0 = OpConstantComposite %v2int %int_1 %int_0
188 %v2int_2_2 = OpConstantComposite %v2int %int_2 %int_2
189 %v2int_2_3 = OpConstantComposite %v2int %int_2 %int_3
190 %v2int_3_2 = OpConstantComposite %v2int %int_3 %int_2
191 %v2int_4_4 = OpConstantComposite %v2int %int_4 %int_4
192 %v2bool_null = OpConstantNull %v2bool
193 %v2bool_true_false = OpConstantComposite %v2bool %true %false
194 %v2bool_false_true = OpConstantComposite %v2bool %false %true
195 %struct_v2int_int_int_null = OpConstantNull %struct_v2int_int_int
196 %v2int_null = OpConstantNull %v2int
197 %102 = OpConstantComposite %v2int %103 %103
198 %v4int_0_0_0_0 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
199 %struct_undef_0_0 = OpConstantComposite %struct_v2int_int_int %v2int_undef %int_0 %int_0
200 %float_n1 = OpConstant %float -1
201 %104 = OpConstant %float 0 ; Need a def with an numerical id to define id maps.
202 %float_null = OpConstantNull %float
203 %float_0 = OpConstant %float 0
204 %float_1 = OpConstant %float 1
205 %float_2 = OpConstant %float 2
206 %float_3 = OpConstant %float 3
207 %float_4 = OpConstant %float 4
208 %float_0p5 = OpConstant %float 0.5
209 %v2float_0_0 = OpConstantComposite %v2float %float_0 %float_0
210 %v2float_2_2 = OpConstantComposite %v2float %float_2 %float_2
211 %v2float_2_3 = OpConstantComposite %v2float %float_2 %float_3
212 %v2float_3_2 = OpConstantComposite %v2float %float_3 %float_2
213 %v2float_4_4 = OpConstantComposite %v2float %float_4 %float_4
214 %v2float_2_0p5 = OpConstantComposite %v2float %float_2 %float_0p5
215 %v2float_null = OpConstantNull %v2float
216 %double_n1 = OpConstant %double -1
217 %105 = OpConstant %double 0 ; Need a def with an numerical id to define id maps.
218 %double_null = OpConstantNull %double
219 %double_0 = OpConstant %double 0
220 %double_1 = OpConstant %double 1
221 %double_2 = OpConstant %double 2
222 %double_3 = OpConstant %double 3
223 %double_4 = OpConstant %double 4
224 %double_0p5 = OpConstant %double 0.5
225 %v2double_0_0 = OpConstantComposite %v2double %double_0 %double_0
226 %v2double_2_2 = OpConstantComposite %v2double %double_2 %double_2
227 %v2double_2_3 = OpConstantComposite %v2double %double_2 %double_3
228 %v2double_3_2 = OpConstantComposite %v2double %double_3 %double_2
229 %v2double_4_4 = OpConstantComposite %v2double %double_4 %double_4
230 %v2double_2_0p5 = OpConstantComposite %v2double %double_2 %double_0p5
231 %v2double_null = OpConstantNull %v2double
232 %108 = OpConstant %half 0
233 %half_1 = OpConstant %half 1
234 %106 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
235 %v4float_0_0_0_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
236 %v4float_0_0_0_1 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
237 %v4float_0_1_0_0 = OpConstantComposite %v4float %float_0 %float_1 %float_null %float_0
238 %v4float_1_1_1_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
239 %107 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
240 %v4double_0_0_0_0 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
241 %v4double_0_0_0_1 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_1
242 %v4double_0_1_0_0 = OpConstantComposite %v4double %double_0 %double_1 %double_null %double_0
243 %v4double_1_1_1_1 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_1
244 %v4double_1_1_1_0p5 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_0p5
245 %v4double_null = OpConstantNull %v4double
246 %v4float_n1_2_1_3 = OpConstantComposite %v4float %float_n1 %float_2 %float_1 %float_3
247 )";
248
249 return header;
250 }
251
252 // Returns the header with definitions of float NaN and double NaN. Since FC
253 // "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" finds
254 // %double_nan = OpConstant %double -0x1.8p+1024 instead of
255 // %double_n0 = OpConstant %double -0,
256 // we separates those definitions from Header().
HeaderWithNaN()257 const std::string& HeaderWithNaN() {
258 static const std::string headerWithNaN =
259 Header() +
260 R"(%float_nan = OpConstant %float -0x1.8p+128
261 %double_nan = OpConstant %double -0x1.8p+1024
262 )";
263
264 return headerWithNaN;
265 }
266
267 // clang-format off
268 INSTANTIATE_TEST_CASE_P(TestCase, IntegerInstructionFoldingTest,
269 ::testing::Values(
270 // Test case 0: fold 0*n
271 InstructionFoldingCase<uint32_t>(
272 Header() + "%main = OpFunction %void None %void_func\n" +
273 "%main_lab = OpLabel\n" +
274 "%n = OpVariable %_ptr_int Function\n" +
275 "%load = OpLoad %int %n\n" +
276 "%2 = OpIMul %int %int_0 %load\n" +
277 "OpReturn\n" +
278 "OpFunctionEnd",
279 2, 0),
280 // Test case 1: fold n*0
281 InstructionFoldingCase<uint32_t>(
282 Header() + "%main = OpFunction %void None %void_func\n" +
283 "%main_lab = OpLabel\n" +
284 "%n = OpVariable %_ptr_int Function\n" +
285 "%load = OpLoad %int %n\n" +
286 "%2 = OpIMul %int %load %int_0\n" +
287 "OpReturn\n" +
288 "OpFunctionEnd",
289 2, 0),
290 // Test case 2: fold 0/n (signed)
291 InstructionFoldingCase<uint32_t>(
292 Header() + "%main = OpFunction %void None %void_func\n" +
293 "%main_lab = OpLabel\n" +
294 "%n = OpVariable %_ptr_int Function\n" +
295 "%load = OpLoad %int %n\n" +
296 "%2 = OpSDiv %int %int_0 %load\n" +
297 "OpReturn\n" +
298 "OpFunctionEnd",
299 2, 0),
300 // Test case 3: fold n/0 (signed)
301 InstructionFoldingCase<uint32_t>(
302 Header() + "%main = OpFunction %void None %void_func\n" +
303 "%main_lab = OpLabel\n" +
304 "%n = OpVariable %_ptr_int Function\n" +
305 "%load = OpLoad %int %n\n" +
306 "%2 = OpSDiv %int %load %int_0\n" +
307 "OpReturn\n" +
308 "OpFunctionEnd",
309 2, 0),
310 // Test case 4: fold 0/n (unsigned)
311 InstructionFoldingCase<uint32_t>(
312 Header() + "%main = OpFunction %void None %void_func\n" +
313 "%main_lab = OpLabel\n" +
314 "%n = OpVariable %_ptr_uint Function\n" +
315 "%load = OpLoad %uint %n\n" +
316 "%2 = OpUDiv %uint %uint_0 %load\n" +
317 "OpReturn\n" +
318 "OpFunctionEnd",
319 2, 0),
320 // Test case 5: fold n/0 (unsigned)
321 InstructionFoldingCase<uint32_t>(
322 Header() + "%main = OpFunction %void None %void_func\n" +
323 "%main_lab = OpLabel\n" +
324 "%n = OpVariable %_ptr_int Function\n" +
325 "%load = OpLoad %int %n\n" +
326 "%2 = OpSDiv %int %load %int_0\n" +
327 "OpReturn\n" +
328 "OpFunctionEnd",
329 2, 0),
330 // Test case 6: fold 0 remainder n
331 InstructionFoldingCase<uint32_t>(
332 Header() + "%main = OpFunction %void None %void_func\n" +
333 "%main_lab = OpLabel\n" +
334 "%n = OpVariable %_ptr_int Function\n" +
335 "%load = OpLoad %int %n\n" +
336 "%2 = OpSRem %int %int_0 %load\n" +
337 "OpReturn\n" +
338 "OpFunctionEnd",
339 2, 0),
340 // Test case 7: fold n remainder 0
341 InstructionFoldingCase<uint32_t>(
342 Header() + "%main = OpFunction %void None %void_func\n" +
343 "%main_lab = OpLabel\n" +
344 "%n = OpVariable %_ptr_int Function\n" +
345 "%load = OpLoad %int %n\n" +
346 "%2 = OpSRem %int %load %int_0\n" +
347 "OpReturn\n" +
348 "OpFunctionEnd",
349 2, 0),
350 // Test case 8: fold 0%n (signed)
351 InstructionFoldingCase<uint32_t>(
352 Header() + "%main = OpFunction %void None %void_func\n" +
353 "%main_lab = OpLabel\n" +
354 "%n = OpVariable %_ptr_int Function\n" +
355 "%load = OpLoad %int %n\n" +
356 "%2 = OpSMod %int %int_0 %load\n" +
357 "OpReturn\n" +
358 "OpFunctionEnd",
359 2, 0),
360 // Test case 9: fold n%0 (signed)
361 InstructionFoldingCase<uint32_t>(
362 Header() + "%main = OpFunction %void None %void_func\n" +
363 "%main_lab = OpLabel\n" +
364 "%n = OpVariable %_ptr_int Function\n" +
365 "%load = OpLoad %int %n\n" +
366 "%2 = OpSMod %int %load %int_0\n" +
367 "OpReturn\n" +
368 "OpFunctionEnd",
369 2, 0),
370 // Test case 10: fold 0%n (unsigned)
371 InstructionFoldingCase<uint32_t>(
372 Header() + "%main = OpFunction %void None %void_func\n" +
373 "%main_lab = OpLabel\n" +
374 "%n = OpVariable %_ptr_uint Function\n" +
375 "%load = OpLoad %uint %n\n" +
376 "%2 = OpUMod %uint %uint_0 %load\n" +
377 "OpReturn\n" +
378 "OpFunctionEnd",
379 2, 0),
380 // Test case 11: fold n%0 (unsigned)
381 InstructionFoldingCase<uint32_t>(
382 Header() + "%main = OpFunction %void None %void_func\n" +
383 "%main_lab = OpLabel\n" +
384 "%n = OpVariable %_ptr_uint Function\n" +
385 "%load = OpLoad %uint %n\n" +
386 "%2 = OpUMod %uint %load %uint_0\n" +
387 "OpReturn\n" +
388 "OpFunctionEnd",
389 2, 0),
390 // Test case 12: fold n << 32
391 InstructionFoldingCase<uint32_t>(
392 Header() + "%main = OpFunction %void None %void_func\n" +
393 "%main_lab = OpLabel\n" +
394 "%n = OpVariable %_ptr_uint Function\n" +
395 "%load = OpLoad %uint %n\n" +
396 "%2 = OpShiftLeftLogical %uint %load %uint_32\n" +
397 "OpReturn\n" +
398 "OpFunctionEnd",
399 2, 0),
400 // Test case 13: fold n >> 32
401 InstructionFoldingCase<uint32_t>(
402 Header() + "%main = OpFunction %void None %void_func\n" +
403 "%main_lab = OpLabel\n" +
404 "%n = OpVariable %_ptr_uint Function\n" +
405 "%load = OpLoad %uint %n\n" +
406 "%2 = OpShiftRightLogical %uint %load %uint_32\n" +
407 "OpReturn\n" +
408 "OpFunctionEnd",
409 2, 0),
410 // Test case 14: fold n | 0xFFFFFFFF
411 InstructionFoldingCase<uint32_t>(
412 Header() + "%main = OpFunction %void None %void_func\n" +
413 "%main_lab = OpLabel\n" +
414 "%n = OpVariable %_ptr_uint Function\n" +
415 "%load = OpLoad %uint %n\n" +
416 "%2 = OpBitwiseOr %uint %load %uint_max\n" +
417 "OpReturn\n" +
418 "OpFunctionEnd",
419 2, 0xFFFFFFFF),
420 // Test case 15: fold 0xFFFFFFFF | n
421 InstructionFoldingCase<uint32_t>(
422 Header() + "%main = OpFunction %void None %void_func\n" +
423 "%main_lab = OpLabel\n" +
424 "%n = OpVariable %_ptr_uint Function\n" +
425 "%load = OpLoad %uint %n\n" +
426 "%2 = OpBitwiseOr %uint %uint_max %load\n" +
427 "OpReturn\n" +
428 "OpFunctionEnd",
429 2, 0xFFFFFFFF),
430 // Test case 16: fold n & 0
431 InstructionFoldingCase<uint32_t>(
432 Header() + "%main = OpFunction %void None %void_func\n" +
433 "%main_lab = OpLabel\n" +
434 "%n = OpVariable %_ptr_uint Function\n" +
435 "%load = OpLoad %uint %n\n" +
436 "%2 = OpBitwiseAnd %uint %load %uint_0\n" +
437 "OpReturn\n" +
438 "OpFunctionEnd",
439 2, 0),
440 // Test case 17: fold 1/0 (signed)
441 InstructionFoldingCase<uint32_t>(
442 Header() + "%main = OpFunction %void None %void_func\n" +
443 "%main_lab = OpLabel\n" +
444 "%2 = OpSDiv %int %int_1 %int_0\n" +
445 "OpReturn\n" +
446 "OpFunctionEnd",
447 2, 0),
448 // Test case 18: fold 1/0 (unsigned)
449 InstructionFoldingCase<uint32_t>(
450 Header() + "%main = OpFunction %void None %void_func\n" +
451 "%main_lab = OpLabel\n" +
452 "%2 = OpUDiv %uint %uint_1 %uint_0\n" +
453 "OpReturn\n" +
454 "OpFunctionEnd",
455 2, 0),
456 // Test case 19: fold OpSRem 1 0 (signed)
457 InstructionFoldingCase<uint32_t>(
458 Header() + "%main = OpFunction %void None %void_func\n" +
459 "%main_lab = OpLabel\n" +
460 "%2 = OpSRem %int %int_1 %int_0\n" +
461 "OpReturn\n" +
462 "OpFunctionEnd",
463 2, 0),
464 // Test case 20: fold 1%0 (signed)
465 InstructionFoldingCase<uint32_t>(
466 Header() + "%main = OpFunction %void None %void_func\n" +
467 "%main_lab = OpLabel\n" +
468 "%2 = OpSMod %int %int_1 %int_0\n" +
469 "OpReturn\n" +
470 "OpFunctionEnd",
471 2, 0),
472 // Test case 21: fold 1%0 (unsigned)
473 InstructionFoldingCase<uint32_t>(
474 Header() + "%main = OpFunction %void None %void_func\n" +
475 "%main_lab = OpLabel\n" +
476 "%2 = OpUMod %uint %uint_1 %uint_0\n" +
477 "OpReturn\n" +
478 "OpFunctionEnd",
479 2, 0),
480 // Test case 22: fold unsigned n >> 42 (undefined, so set to zero).
481 InstructionFoldingCase<uint32_t>(
482 Header() + "%main = OpFunction %void None %void_func\n" +
483 "%main_lab = OpLabel\n" +
484 "%n = OpVariable %_ptr_uint Function\n" +
485 "%load = OpLoad %uint %n\n" +
486 "%2 = OpShiftRightLogical %uint %load %uint_42\n" +
487 "OpReturn\n" +
488 "OpFunctionEnd",
489 2, 0),
490 // Test case 23: fold signed n >> 42 (undefined, so set to zero).
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 = OpShiftRightLogical %int %load %uint_42\n" +
497 "OpReturn\n" +
498 "OpFunctionEnd",
499 2, 0),
500 // Test case 24: fold n << 42 (undefined, so set to zero).
501 InstructionFoldingCase<uint32_t>(
502 Header() + "%main = OpFunction %void None %void_func\n" +
503 "%main_lab = OpLabel\n" +
504 "%n = OpVariable %_ptr_int Function\n" +
505 "%load = OpLoad %int %n\n" +
506 "%2 = OpShiftLeftLogical %int %load %uint_42\n" +
507 "OpReturn\n" +
508 "OpFunctionEnd",
509 2, 0),
510 // Test case 25: fold -24 >> 32 (defined as -1)
511 InstructionFoldingCase<uint32_t>(
512 Header() + "%main = OpFunction %void None %void_func\n" +
513 "%main_lab = OpLabel\n" +
514 "%2 = OpShiftRightArithmetic %int %int_n24 %uint_32\n" +
515 "OpReturn\n" +
516 "OpFunctionEnd",
517 2, -1),
518 // Test case 26: fold 2 >> 32 (signed)
519 InstructionFoldingCase<uint32_t>(
520 Header() + "%main = OpFunction %void None %void_func\n" +
521 "%main_lab = OpLabel\n" +
522 "%2 = OpShiftRightArithmetic %int %int_2 %uint_32\n" +
523 "OpReturn\n" +
524 "OpFunctionEnd",
525 2, 0),
526 // Test case 27: fold 2 >> 32 (unsigned)
527 InstructionFoldingCase<uint32_t>(
528 Header() + "%main = OpFunction %void None %void_func\n" +
529 "%main_lab = OpLabel\n" +
530 "%2 = OpShiftRightLogical %int %int_2 %uint_32\n" +
531 "OpReturn\n" +
532 "OpFunctionEnd",
533 2, 0),
534 // Test case 28: fold 2 << 32
535 InstructionFoldingCase<uint32_t>(
536 Header() + "%main = OpFunction %void None %void_func\n" +
537 "%main_lab = OpLabel\n" +
538 "%2 = OpShiftLeftLogical %int %int_2 %uint_32\n" +
539 "OpReturn\n" +
540 "OpFunctionEnd",
541 2, 0),
542 // Test case 29: fold -INT_MIN
543 InstructionFoldingCase<uint32_t>(
544 Header() + "%main = OpFunction %void None %void_func\n" +
545 "%main_lab = OpLabel\n" +
546 "%2 = OpSNegate %int %int_min\n" +
547 "OpReturn\n" +
548 "OpFunctionEnd",
549 2, std::numeric_limits<int32_t>::min())
550 ));
551 // clang-format on
552
553 using IntVectorInstructionFoldingTest =
554 ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint32_t>>>;
555
TEST_P(IntVectorInstructionFoldingTest,Case)556 TEST_P(IntVectorInstructionFoldingTest, Case) {
557 const auto& tc = GetParam();
558
559 // Build module.
560 std::unique_ptr<IRContext> context =
561 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
562 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
563 ASSERT_NE(nullptr, context);
564
565 // Fold the instruction to test.
566 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
567 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
568 SpvOp original_opcode = inst->opcode();
569 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
570
571 // Make sure the instruction folded as expected.
572 EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
573 if (succeeded && inst != nullptr) {
574 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
575 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
576 std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
577 EXPECT_THAT(opcodes, Contains(inst->opcode()));
578 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
579 const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
580 EXPECT_NE(result, nullptr);
581 if (result != nullptr) {
582 const std::vector<const analysis::Constant*>& componenets =
583 result->AsVectorConstant()->GetComponents();
584 EXPECT_EQ(componenets.size(), tc.expected_result.size());
585 for (size_t i = 0; i < componenets.size(); i++) {
586 EXPECT_EQ(tc.expected_result[i], componenets[i]->GetU32());
587 }
588 }
589 }
590 }
591
592 // clang-format off
593 INSTANTIATE_TEST_CASE_P(TestCase, IntVectorInstructionFoldingTest,
594 ::testing::Values(
595 // Test case 0: fold 0*n
596 InstructionFoldingCase<std::vector<uint32_t>>(
597 Header() + "%main = OpFunction %void None %void_func\n" +
598 "%main_lab = OpLabel\n" +
599 "%n = OpVariable %_ptr_int Function\n" +
600 "%load = OpLoad %int %n\n" +
601 "%2 = OpVectorShuffle %v2int %v2int_2_2 %v2int_2_3 0 3\n" +
602 "OpReturn\n" +
603 "OpFunctionEnd",
604 2, {2,3}),
605 InstructionFoldingCase<std::vector<uint32_t>>(
606 Header() + "%main = OpFunction %void None %void_func\n" +
607 "%main_lab = OpLabel\n" +
608 "%n = OpVariable %_ptr_int Function\n" +
609 "%load = OpLoad %int %n\n" +
610 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
611 "OpReturn\n" +
612 "OpFunctionEnd",
613 2, {0,3}),
614 InstructionFoldingCase<std::vector<uint32_t>>(
615 Header() + "%main = OpFunction %void None %void_func\n" +
616 "%main_lab = OpLabel\n" +
617 "%n = OpVariable %_ptr_int Function\n" +
618 "%load = OpLoad %int %n\n" +
619 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 4294967295 3\n" +
620 "OpReturn\n" +
621 "OpFunctionEnd",
622 2, {0,0}),
623 InstructionFoldingCase<std::vector<uint32_t>>(
624 Header() + "%main = OpFunction %void None %void_func\n" +
625 "%main_lab = OpLabel\n" +
626 "%n = OpVariable %_ptr_int Function\n" +
627 "%load = OpLoad %int %n\n" +
628 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 4294967295 \n" +
629 "OpReturn\n" +
630 "OpFunctionEnd",
631 2, {0,0})
632 ));
633 // clang-format on
634
635 using BooleanInstructionFoldingTest =
636 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
637
TEST_P(BooleanInstructionFoldingTest,Case)638 TEST_P(BooleanInstructionFoldingTest, Case) {
639 const auto& tc = GetParam();
640
641 // Build module.
642 std::unique_ptr<IRContext> context =
643 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
644 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
645 ASSERT_NE(nullptr, context);
646
647 // Fold the instruction to test.
648 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
649 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
650 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
651
652 // Make sure the instruction folded as expected.
653 EXPECT_TRUE(succeeded);
654 if (inst != nullptr) {
655 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
656 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
657 std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
658 EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
659 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
660 const analysis::BoolConstant* result =
661 const_mrg->GetConstantFromInst(inst)->AsBoolConstant();
662 EXPECT_NE(result, nullptr);
663 if (result != nullptr) {
664 EXPECT_EQ(result->value(), tc.expected_result);
665 }
666 }
667 }
668
669 // clang-format off
670 INSTANTIATE_TEST_CASE_P(TestCase, BooleanInstructionFoldingTest,
671 ::testing::Values(
672 // Test case 0: fold true || n
673 InstructionFoldingCase<bool>(
674 Header() + "%main = OpFunction %void None %void_func\n" +
675 "%main_lab = OpLabel\n" +
676 "%n = OpVariable %_ptr_bool Function\n" +
677 "%load = OpLoad %bool %n\n" +
678 "%2 = OpLogicalOr %bool %true %load\n" +
679 "OpReturn\n" +
680 "OpFunctionEnd",
681 2, true),
682 // Test case 1: fold n || true
683 InstructionFoldingCase<bool>(
684 Header() + "%main = OpFunction %void None %void_func\n" +
685 "%main_lab = OpLabel\n" +
686 "%n = OpVariable %_ptr_bool Function\n" +
687 "%load = OpLoad %bool %n\n" +
688 "%2 = OpLogicalOr %bool %load %true\n" +
689 "OpReturn\n" +
690 "OpFunctionEnd",
691 2, true),
692 // Test case 2: fold false && n
693 InstructionFoldingCase<bool>(
694 Header() + "%main = OpFunction %void None %void_func\n" +
695 "%main_lab = OpLabel\n" +
696 "%n = OpVariable %_ptr_bool Function\n" +
697 "%load = OpLoad %bool %n\n" +
698 "%2 = OpLogicalAnd %bool %false %load\n" +
699 "OpReturn\n" +
700 "OpFunctionEnd",
701 2, false),
702 // Test case 3: fold n && false
703 InstructionFoldingCase<bool>(
704 Header() + "%main = OpFunction %void None %void_func\n" +
705 "%main_lab = OpLabel\n" +
706 "%n = OpVariable %_ptr_bool Function\n" +
707 "%load = OpLoad %bool %n\n" +
708 "%2 = OpLogicalAnd %bool %load %false\n" +
709 "OpReturn\n" +
710 "OpFunctionEnd",
711 2, false),
712 // Test case 4: fold n < 0 (unsigned)
713 InstructionFoldingCase<bool>(
714 Header() + "%main = OpFunction %void None %void_func\n" +
715 "%main_lab = OpLabel\n" +
716 "%n = OpVariable %_ptr_uint Function\n" +
717 "%load = OpLoad %uint %n\n" +
718 "%2 = OpULessThan %bool %load %uint_0\n" +
719 "OpReturn\n" +
720 "OpFunctionEnd",
721 2, false),
722 // Test case 5: fold UINT_MAX < n (unsigned)
723 InstructionFoldingCase<bool>(
724 Header() + "%main = OpFunction %void None %void_func\n" +
725 "%main_lab = OpLabel\n" +
726 "%n = OpVariable %_ptr_uint Function\n" +
727 "%load = OpLoad %uint %n\n" +
728 "%2 = OpULessThan %bool %uint_max %load\n" +
729 "OpReturn\n" +
730 "OpFunctionEnd",
731 2, false),
732 // Test case 6: fold INT_MAX < n (signed)
733 InstructionFoldingCase<bool>(
734 Header() + "%main = OpFunction %void None %void_func\n" +
735 "%main_lab = OpLabel\n" +
736 "%n = OpVariable %_ptr_int Function\n" +
737 "%load = OpLoad %int %n\n" +
738 "%2 = OpSLessThan %bool %int_max %load\n" +
739 "OpReturn\n" +
740 "OpFunctionEnd",
741 2, false),
742 // Test case 7: fold n < INT_MIN (signed)
743 InstructionFoldingCase<bool>(
744 Header() + "%main = OpFunction %void None %void_func\n" +
745 "%main_lab = OpLabel\n" +
746 "%n = OpVariable %_ptr_int Function\n" +
747 "%load = OpLoad %int %n\n" +
748 "%2 = OpSLessThan %bool %load %int_min\n" +
749 "OpReturn\n" +
750 "OpFunctionEnd",
751 2, false),
752 // Test case 8: fold 0 > n (unsigned)
753 InstructionFoldingCase<bool>(
754 Header() + "%main = OpFunction %void None %void_func\n" +
755 "%main_lab = OpLabel\n" +
756 "%n = OpVariable %_ptr_uint Function\n" +
757 "%load = OpLoad %uint %n\n" +
758 "%2 = OpUGreaterThan %bool %uint_0 %load\n" +
759 "OpReturn\n" +
760 "OpFunctionEnd",
761 2, false),
762 // Test case 9: fold n > UINT_MAX (unsigned)
763 InstructionFoldingCase<bool>(
764 Header() + "%main = OpFunction %void None %void_func\n" +
765 "%main_lab = OpLabel\n" +
766 "%n = OpVariable %_ptr_uint Function\n" +
767 "%load = OpLoad %uint %n\n" +
768 "%2 = OpUGreaterThan %bool %load %uint_max\n" +
769 "OpReturn\n" +
770 "OpFunctionEnd",
771 2, false),
772 // Test case 10: fold n > INT_MAX (signed)
773 InstructionFoldingCase<bool>(
774 Header() + "%main = OpFunction %void None %void_func\n" +
775 "%main_lab = OpLabel\n" +
776 "%n = OpVariable %_ptr_int Function\n" +
777 "%load = OpLoad %int %n\n" +
778 "%2 = OpSGreaterThan %bool %load %int_max\n" +
779 "OpReturn\n" +
780 "OpFunctionEnd",
781 2, false),
782 // Test case 11: fold INT_MIN > n (signed)
783 InstructionFoldingCase<bool>(
784 Header() + "%main = OpFunction %void None %void_func\n" +
785 "%main_lab = OpLabel\n" +
786 "%n = OpVariable %_ptr_uint Function\n" +
787 "%load = OpLoad %uint %n\n" +
788 "%2 = OpSGreaterThan %bool %int_min %load\n" +
789 "OpReturn\n" +
790 "OpFunctionEnd",
791 2, false),
792 // Test case 12: fold 0 <= n (unsigned)
793 InstructionFoldingCase<bool>(
794 Header() + "%main = OpFunction %void None %void_func\n" +
795 "%main_lab = OpLabel\n" +
796 "%n = OpVariable %_ptr_uint Function\n" +
797 "%load = OpLoad %uint %n\n" +
798 "%2 = OpULessThanEqual %bool %uint_0 %load\n" +
799 "OpReturn\n" +
800 "OpFunctionEnd",
801 2, true),
802 // Test case 13: fold n <= UINT_MAX (unsigned)
803 InstructionFoldingCase<bool>(
804 Header() + "%main = OpFunction %void None %void_func\n" +
805 "%main_lab = OpLabel\n" +
806 "%n = OpVariable %_ptr_uint Function\n" +
807 "%load = OpLoad %uint %n\n" +
808 "%2 = OpULessThanEqual %bool %load %uint_max\n" +
809 "OpReturn\n" +
810 "OpFunctionEnd",
811 2, true),
812 // Test case 14: fold INT_MIN <= n (signed)
813 InstructionFoldingCase<bool>(
814 Header() + "%main = OpFunction %void None %void_func\n" +
815 "%main_lab = OpLabel\n" +
816 "%n = OpVariable %_ptr_int Function\n" +
817 "%load = OpLoad %int %n\n" +
818 "%2 = OpSLessThanEqual %bool %int_min %load\n" +
819 "OpReturn\n" +
820 "OpFunctionEnd",
821 2, true),
822 // Test case 15: fold n <= INT_MAX (signed)
823 InstructionFoldingCase<bool>(
824 Header() + "%main = OpFunction %void None %void_func\n" +
825 "%main_lab = OpLabel\n" +
826 "%n = OpVariable %_ptr_int Function\n" +
827 "%load = OpLoad %int %n\n" +
828 "%2 = OpSLessThanEqual %bool %load %int_max\n" +
829 "OpReturn\n" +
830 "OpFunctionEnd",
831 2, true),
832 // Test case 16: fold n >= 0 (unsigned)
833 InstructionFoldingCase<bool>(
834 Header() + "%main = OpFunction %void None %void_func\n" +
835 "%main_lab = OpLabel\n" +
836 "%n = OpVariable %_ptr_uint Function\n" +
837 "%load = OpLoad %uint %n\n" +
838 "%2 = OpUGreaterThanEqual %bool %load %uint_0\n" +
839 "OpReturn\n" +
840 "OpFunctionEnd",
841 2, true),
842 // Test case 17: fold UINT_MAX >= n (unsigned)
843 InstructionFoldingCase<bool>(
844 Header() + "%main = OpFunction %void None %void_func\n" +
845 "%main_lab = OpLabel\n" +
846 "%n = OpVariable %_ptr_uint Function\n" +
847 "%load = OpLoad %uint %n\n" +
848 "%2 = OpUGreaterThanEqual %bool %uint_max %load\n" +
849 "OpReturn\n" +
850 "OpFunctionEnd",
851 2, true),
852 // Test case 18: fold n >= INT_MIN (signed)
853 InstructionFoldingCase<bool>(
854 Header() + "%main = OpFunction %void None %void_func\n" +
855 "%main_lab = OpLabel\n" +
856 "%n = OpVariable %_ptr_int Function\n" +
857 "%load = OpLoad %int %n\n" +
858 "%2 = OpSGreaterThanEqual %bool %load %int_min\n" +
859 "OpReturn\n" +
860 "OpFunctionEnd",
861 2, true),
862 // Test case 19: fold INT_MAX >= n (signed)
863 InstructionFoldingCase<bool>(
864 Header() + "%main = OpFunction %void None %void_func\n" +
865 "%main_lab = OpLabel\n" +
866 "%n = OpVariable %_ptr_int Function\n" +
867 "%load = OpLoad %int %n\n" +
868 "%2 = OpSGreaterThanEqual %bool %int_max %load\n" +
869 "OpReturn\n" +
870 "OpFunctionEnd",
871 2, true)
872 ));
873
874 INSTANTIATE_TEST_CASE_P(FClampAndCmpLHS, BooleanInstructionFoldingTest,
875 ::testing::Values(
876 // Test case 0: fold 0.0 > clamp(n, 0.0, 1.0)
877 InstructionFoldingCase<bool>(
878 Header() + "%main = OpFunction %void None %void_func\n" +
879 "%main_lab = OpLabel\n" +
880 "%n = OpVariable %_ptr_float Function\n" +
881 "%ld = OpLoad %float %n\n" +
882 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
883 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
884 "OpReturn\n" +
885 "OpFunctionEnd",
886 2, false),
887 // Test case 1: fold 0.0 > clamp(n, -1.0, -1.0)
888 InstructionFoldingCase<bool>(
889 Header() + "%main = OpFunction %void None %void_func\n" +
890 "%main_lab = OpLabel\n" +
891 "%n = OpVariable %_ptr_float Function\n" +
892 "%ld = OpLoad %float %n\n" +
893 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
894 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
895 "OpReturn\n" +
896 "OpFunctionEnd",
897 2, true),
898 // Test case 2: fold 0.0 >= clamp(n, 1, 2)
899 InstructionFoldingCase<bool>(
900 Header() + "%main = OpFunction %void None %void_func\n" +
901 "%main_lab = OpLabel\n" +
902 "%n = OpVariable %_ptr_float Function\n" +
903 "%ld = OpLoad %float %n\n" +
904 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
905 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
906 "OpReturn\n" +
907 "OpFunctionEnd",
908 2, false),
909 // Test case 3: fold 0.0 >= clamp(n, -1.0, 0.0)
910 InstructionFoldingCase<bool>(
911 Header() + "%main = OpFunction %void None %void_func\n" +
912 "%main_lab = OpLabel\n" +
913 "%n = OpVariable %_ptr_float Function\n" +
914 "%ld = OpLoad %float %n\n" +
915 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
916 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
917 "OpReturn\n" +
918 "OpFunctionEnd",
919 2, true),
920 // Test case 4: fold 0.0 <= clamp(n, 0.0, 1.0)
921 InstructionFoldingCase<bool>(
922 Header() + "%main = OpFunction %void None %void_func\n" +
923 "%main_lab = OpLabel\n" +
924 "%n = OpVariable %_ptr_float Function\n" +
925 "%ld = OpLoad %float %n\n" +
926 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
927 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
928 "OpReturn\n" +
929 "OpFunctionEnd",
930 2, true),
931 // Test case 5: fold 0.0 <= clamp(n, -1.0, -1.0)
932 InstructionFoldingCase<bool>(
933 Header() + "%main = OpFunction %void None %void_func\n" +
934 "%main_lab = OpLabel\n" +
935 "%n = OpVariable %_ptr_float Function\n" +
936 "%ld = OpLoad %float %n\n" +
937 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
938 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
939 "OpReturn\n" +
940 "OpFunctionEnd",
941 2, false),
942 // Test case 6: fold 0.0 < clamp(n, 1, 2)
943 InstructionFoldingCase<bool>(
944 Header() + "%main = OpFunction %void None %void_func\n" +
945 "%main_lab = OpLabel\n" +
946 "%n = OpVariable %_ptr_float Function\n" +
947 "%ld = OpLoad %float %n\n" +
948 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
949 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
950 "OpReturn\n" +
951 "OpFunctionEnd",
952 2, true),
953 // Test case 7: fold 0.0 < clamp(n, -1.0, 0.0)
954 InstructionFoldingCase<bool>(
955 Header() + "%main = OpFunction %void None %void_func\n" +
956 "%main_lab = OpLabel\n" +
957 "%n = OpVariable %_ptr_float Function\n" +
958 "%ld = OpLoad %float %n\n" +
959 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
960 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
961 "OpReturn\n" +
962 "OpFunctionEnd",
963 2, false),
964 // Test case 8: fold 0.0 > clamp(n, 0.0, 1.0)
965 InstructionFoldingCase<bool>(
966 Header() + "%main = OpFunction %void None %void_func\n" +
967 "%main_lab = OpLabel\n" +
968 "%n = OpVariable %_ptr_float Function\n" +
969 "%ld = OpLoad %float %n\n" +
970 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
971 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
972 "OpReturn\n" +
973 "OpFunctionEnd",
974 2, false),
975 // Test case 9: fold 0.0 > clamp(n, -1.0, -1.0)
976 InstructionFoldingCase<bool>(
977 Header() + "%main = OpFunction %void None %void_func\n" +
978 "%main_lab = OpLabel\n" +
979 "%n = OpVariable %_ptr_float Function\n" +
980 "%ld = OpLoad %float %n\n" +
981 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
982 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
983 "OpReturn\n" +
984 "OpFunctionEnd",
985 2, true),
986 // Test case 10: fold 0.0 >= clamp(n, 1, 2)
987 InstructionFoldingCase<bool>(
988 Header() + "%main = OpFunction %void None %void_func\n" +
989 "%main_lab = OpLabel\n" +
990 "%n = OpVariable %_ptr_float Function\n" +
991 "%ld = OpLoad %float %n\n" +
992 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
993 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
994 "OpReturn\n" +
995 "OpFunctionEnd",
996 2, false),
997 // Test case 11: fold 0.0 >= clamp(n, -1.0, 0.0)
998 InstructionFoldingCase<bool>(
999 Header() + "%main = OpFunction %void None %void_func\n" +
1000 "%main_lab = OpLabel\n" +
1001 "%n = OpVariable %_ptr_float Function\n" +
1002 "%ld = OpLoad %float %n\n" +
1003 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1004 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
1005 "OpReturn\n" +
1006 "OpFunctionEnd",
1007 2, true),
1008 // Test case 12: fold 0.0 <= clamp(n, 0.0, 1.0)
1009 InstructionFoldingCase<bool>(
1010 Header() + "%main = OpFunction %void None %void_func\n" +
1011 "%main_lab = OpLabel\n" +
1012 "%n = OpVariable %_ptr_float Function\n" +
1013 "%ld = OpLoad %float %n\n" +
1014 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1015 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
1016 "OpReturn\n" +
1017 "OpFunctionEnd",
1018 2, true),
1019 // Test case 13: fold 0.0 <= clamp(n, -1.0, -1.0)
1020 InstructionFoldingCase<bool>(
1021 Header() + "%main = OpFunction %void None %void_func\n" +
1022 "%main_lab = OpLabel\n" +
1023 "%n = OpVariable %_ptr_float Function\n" +
1024 "%ld = OpLoad %float %n\n" +
1025 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
1026 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
1027 "OpReturn\n" +
1028 "OpFunctionEnd",
1029 2, false),
1030 // Test case 14: fold 0.0 < clamp(n, 1, 2)
1031 InstructionFoldingCase<bool>(
1032 Header() + "%main = OpFunction %void None %void_func\n" +
1033 "%main_lab = OpLabel\n" +
1034 "%n = OpVariable %_ptr_float Function\n" +
1035 "%ld = OpLoad %float %n\n" +
1036 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1037 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
1038 "OpReturn\n" +
1039 "OpFunctionEnd",
1040 2, true),
1041 // Test case 15: fold 0.0 < clamp(n, -1.0, 0.0)
1042 InstructionFoldingCase<bool>(
1043 Header() + "%main = OpFunction %void None %void_func\n" +
1044 "%main_lab = OpLabel\n" +
1045 "%n = OpVariable %_ptr_float Function\n" +
1046 "%ld = OpLoad %float %n\n" +
1047 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1048 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
1049 "OpReturn\n" +
1050 "OpFunctionEnd",
1051 2, false)
1052 ));
1053
1054 INSTANTIATE_TEST_CASE_P(FClampAndCmpRHS, BooleanInstructionFoldingTest,
1055 ::testing::Values(
1056 // Test case 0: fold clamp(n, 0.0, 1.0) > 1.0
1057 InstructionFoldingCase<bool>(
1058 Header() + "%main = OpFunction %void None %void_func\n" +
1059 "%main_lab = OpLabel\n" +
1060 "%n = OpVariable %_ptr_float Function\n" +
1061 "%ld = OpLoad %float %n\n" +
1062 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1063 "%2 = OpFOrdGreaterThan %bool %clamp %float_1\n" +
1064 "OpReturn\n" +
1065 "OpFunctionEnd",
1066 2, false),
1067 // Test case 1: fold clamp(n, 1.0, 1.0) > 0.0
1068 InstructionFoldingCase<bool>(
1069 Header() + "%main = OpFunction %void None %void_func\n" +
1070 "%main_lab = OpLabel\n" +
1071 "%n = OpVariable %_ptr_float Function\n" +
1072 "%ld = OpLoad %float %n\n" +
1073 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
1074 "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
1075 "OpReturn\n" +
1076 "OpFunctionEnd",
1077 2, true),
1078 // Test case 2: fold clamp(n, 1, 2) >= 0.0
1079 InstructionFoldingCase<bool>(
1080 Header() + "%main = OpFunction %void None %void_func\n" +
1081 "%main_lab = OpLabel\n" +
1082 "%n = OpVariable %_ptr_float Function\n" +
1083 "%ld = OpLoad %float %n\n" +
1084 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1085 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
1086 "OpReturn\n" +
1087 "OpFunctionEnd",
1088 2, true),
1089 // Test case 3: fold clamp(n, 1.0, 2.0) >= 3.0
1090 InstructionFoldingCase<bool>(
1091 Header() + "%main = OpFunction %void None %void_func\n" +
1092 "%main_lab = OpLabel\n" +
1093 "%n = OpVariable %_ptr_float Function\n" +
1094 "%ld = OpLoad %float %n\n" +
1095 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1096 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_3\n" +
1097 "OpReturn\n" +
1098 "OpFunctionEnd",
1099 2, false),
1100 // Test case 4: fold clamp(n, 0.0, 1.0) <= 1.0
1101 InstructionFoldingCase<bool>(
1102 Header() + "%main = OpFunction %void None %void_func\n" +
1103 "%main_lab = OpLabel\n" +
1104 "%n = OpVariable %_ptr_float Function\n" +
1105 "%ld = OpLoad %float %n\n" +
1106 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1107 "%2 = OpFOrdLessThanEqual %bool %clamp %float_1\n" +
1108 "OpReturn\n" +
1109 "OpFunctionEnd",
1110 2, true),
1111 // Test case 5: fold clamp(n, 1.0, 2.0) <= 0.0
1112 InstructionFoldingCase<bool>(
1113 Header() + "%main = OpFunction %void None %void_func\n" +
1114 "%main_lab = OpLabel\n" +
1115 "%n = OpVariable %_ptr_float Function\n" +
1116 "%ld = OpLoad %float %n\n" +
1117 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1118 "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
1119 "OpReturn\n" +
1120 "OpFunctionEnd",
1121 2, false),
1122 // Test case 6: fold clamp(n, 1, 2) < 3
1123 InstructionFoldingCase<bool>(
1124 Header() + "%main = OpFunction %void None %void_func\n" +
1125 "%main_lab = OpLabel\n" +
1126 "%n = OpVariable %_ptr_float Function\n" +
1127 "%ld = OpLoad %float %n\n" +
1128 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1129 "%2 = OpFOrdLessThan %bool %clamp %float_3\n" +
1130 "OpReturn\n" +
1131 "OpFunctionEnd",
1132 2, true),
1133 // Test case 7: fold clamp(n, -1.0, 0.0) < -1.0
1134 InstructionFoldingCase<bool>(
1135 Header() + "%main = OpFunction %void None %void_func\n" +
1136 "%main_lab = OpLabel\n" +
1137 "%n = OpVariable %_ptr_float Function\n" +
1138 "%ld = OpLoad %float %n\n" +
1139 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1140 "%2 = OpFOrdLessThan %bool %clamp %float_n1\n" +
1141 "OpReturn\n" +
1142 "OpFunctionEnd",
1143 2, false),
1144 // Test case 8: fold clamp(n, 0.0, 1.0) > 1.0
1145 InstructionFoldingCase<bool>(
1146 Header() + "%main = OpFunction %void None %void_func\n" +
1147 "%main_lab = OpLabel\n" +
1148 "%n = OpVariable %_ptr_float Function\n" +
1149 "%ld = OpLoad %float %n\n" +
1150 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1151 "%2 = OpFUnordGreaterThan %bool %clamp %float_1\n" +
1152 "OpReturn\n" +
1153 "OpFunctionEnd",
1154 2, false),
1155 // Test case 9: fold clamp(n, 1.0, 2.0) > 0.0
1156 InstructionFoldingCase<bool>(
1157 Header() + "%main = OpFunction %void None %void_func\n" +
1158 "%main_lab = OpLabel\n" +
1159 "%n = OpVariable %_ptr_float Function\n" +
1160 "%ld = OpLoad %float %n\n" +
1161 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1162 "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
1163 "OpReturn\n" +
1164 "OpFunctionEnd",
1165 2, true),
1166 // Test case 10: fold clamp(n, 1, 2) >= 3.0
1167 InstructionFoldingCase<bool>(
1168 Header() + "%main = OpFunction %void None %void_func\n" +
1169 "%main_lab = OpLabel\n" +
1170 "%n = OpVariable %_ptr_float Function\n" +
1171 "%ld = OpLoad %float %n\n" +
1172 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1173 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_3\n" +
1174 "OpReturn\n" +
1175 "OpFunctionEnd",
1176 2, false),
1177 // Test case 11: fold clamp(n, -1.0, 0.0) >= -1.0
1178 InstructionFoldingCase<bool>(
1179 Header() + "%main = OpFunction %void None %void_func\n" +
1180 "%main_lab = OpLabel\n" +
1181 "%n = OpVariable %_ptr_float Function\n" +
1182 "%ld = OpLoad %float %n\n" +
1183 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1184 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_n1\n" +
1185 "OpReturn\n" +
1186 "OpFunctionEnd",
1187 2, true),
1188 // Test case 12: fold clamp(n, 0.0, 1.0) <= 1.0
1189 InstructionFoldingCase<bool>(
1190 Header() + "%main = OpFunction %void None %void_func\n" +
1191 "%main_lab = OpLabel\n" +
1192 "%n = OpVariable %_ptr_float Function\n" +
1193 "%ld = OpLoad %float %n\n" +
1194 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1195 "%2 = OpFUnordLessThanEqual %bool %clamp %float_1\n" +
1196 "OpReturn\n" +
1197 "OpFunctionEnd",
1198 2, true),
1199 // Test case 13: fold clamp(n, 1.0, 1.0) <= 0.0
1200 InstructionFoldingCase<bool>(
1201 Header() + "%main = OpFunction %void None %void_func\n" +
1202 "%main_lab = OpLabel\n" +
1203 "%n = OpVariable %_ptr_float Function\n" +
1204 "%ld = OpLoad %float %n\n" +
1205 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
1206 "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
1207 "OpReturn\n" +
1208 "OpFunctionEnd",
1209 2, false),
1210 // Test case 14: fold clamp(n, 1, 2) < 3
1211 InstructionFoldingCase<bool>(
1212 Header() + "%main = OpFunction %void None %void_func\n" +
1213 "%main_lab = OpLabel\n" +
1214 "%n = OpVariable %_ptr_float Function\n" +
1215 "%ld = OpLoad %float %n\n" +
1216 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1217 "%2 = OpFUnordLessThan %bool %clamp %float_3\n" +
1218 "OpReturn\n" +
1219 "OpFunctionEnd",
1220 2, true),
1221 // Test case 15: fold clamp(n, -1.0, 0.0) < -1.0
1222 InstructionFoldingCase<bool>(
1223 Header() + "%main = OpFunction %void None %void_func\n" +
1224 "%main_lab = OpLabel\n" +
1225 "%n = OpVariable %_ptr_float Function\n" +
1226 "%ld = OpLoad %float %n\n" +
1227 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1228 "%2 = OpFUnordLessThan %bool %clamp %float_n1\n" +
1229 "OpReturn\n" +
1230 "OpFunctionEnd",
1231 2, false),
1232 // Test case 16: fold clamp(n, -1.0, 0.0) < -1.0 (one test for double)
1233 InstructionFoldingCase<bool>(
1234 Header() + "%main = OpFunction %void None %void_func\n" +
1235 "%main_lab = OpLabel\n" +
1236 "%n = OpVariable %_ptr_double Function\n" +
1237 "%ld = OpLoad %double %n\n" +
1238 "%clamp = OpExtInst %double %1 FClamp %ld %double_n1 %double_0\n" +
1239 "%2 = OpFUnordLessThan %bool %clamp %double_n1\n" +
1240 "OpReturn\n" +
1241 "OpFunctionEnd",
1242 2, false)
1243 ));
1244 // clang-format on
1245
1246 using FloatInstructionFoldingTest =
1247 ::testing::TestWithParam<InstructionFoldingCase<float>>;
1248
TEST_P(FloatInstructionFoldingTest,Case)1249 TEST_P(FloatInstructionFoldingTest, Case) {
1250 const auto& tc = GetParam();
1251
1252 // Build module.
1253 std::unique_ptr<IRContext> context =
1254 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
1255 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1256 ASSERT_NE(nullptr, context);
1257
1258 // Fold the instruction to test.
1259 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
1260 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
1261 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
1262
1263 // Make sure the instruction folded as expected.
1264 EXPECT_TRUE(succeeded);
1265 if (inst != nullptr) {
1266 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
1267 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
1268 EXPECT_EQ(inst->opcode(), SpvOpConstant);
1269 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
1270 const analysis::FloatConstant* result =
1271 const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
1272 EXPECT_NE(result, nullptr);
1273 if (result != nullptr) {
1274 EXPECT_EQ(result->GetFloatValue(), tc.expected_result);
1275 }
1276 }
1277 }
1278
1279 // Not testing NaNs because there are no expectations concerning NaNs according
1280 // to the "Precision and Operation of SPIR-V Instructions" section of the Vulkan
1281 // specification.
1282
1283 // clang-format off
1284 INSTANTIATE_TEST_CASE_P(FloatConstantFoldingTest, FloatInstructionFoldingTest,
1285 ::testing::Values(
1286 // Test case 0: Fold 2.0 - 1.0
1287 InstructionFoldingCase<float>(
1288 Header() + "%main = OpFunction %void None %void_func\n" +
1289 "%main_lab = OpLabel\n" +
1290 "%2 = OpFSub %float %float_2 %float_1\n" +
1291 "OpReturn\n" +
1292 "OpFunctionEnd",
1293 2, 1.0),
1294 // Test case 1: Fold 2.0 + 1.0
1295 InstructionFoldingCase<float>(
1296 Header() + "%main = OpFunction %void None %void_func\n" +
1297 "%main_lab = OpLabel\n" +
1298 "%2 = OpFAdd %float %float_2 %float_1\n" +
1299 "OpReturn\n" +
1300 "OpFunctionEnd",
1301 2, 3.0),
1302 // Test case 2: Fold 3.0 * 2.0
1303 InstructionFoldingCase<float>(
1304 Header() + "%main = OpFunction %void None %void_func\n" +
1305 "%main_lab = OpLabel\n" +
1306 "%2 = OpFMul %float %float_3 %float_2\n" +
1307 "OpReturn\n" +
1308 "OpFunctionEnd",
1309 2, 6.0),
1310 // Test case 3: Fold 1.0 / 2.0
1311 InstructionFoldingCase<float>(
1312 Header() + "%main = OpFunction %void None %void_func\n" +
1313 "%main_lab = OpLabel\n" +
1314 "%2 = OpFDiv %float %float_1 %float_2\n" +
1315 "OpReturn\n" +
1316 "OpFunctionEnd",
1317 2, 0.5),
1318 // Test case 4: Fold 1.0 / 0.0
1319 InstructionFoldingCase<float>(
1320 Header() + "%main = OpFunction %void None %void_func\n" +
1321 "%main_lab = OpLabel\n" +
1322 "%2 = OpFDiv %float %float_1 %float_0\n" +
1323 "OpReturn\n" +
1324 "OpFunctionEnd",
1325 2, std::numeric_limits<float>::infinity()),
1326 // Test case 5: Fold -1.0 / 0.0
1327 InstructionFoldingCase<float>(
1328 Header() + "%main = OpFunction %void None %void_func\n" +
1329 "%main_lab = OpLabel\n" +
1330 "%2 = OpFDiv %float %float_n1 %float_0\n" +
1331 "OpReturn\n" +
1332 "OpFunctionEnd",
1333 2, -std::numeric_limits<float>::infinity()),
1334 // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
1335 InstructionFoldingCase<float>(
1336 Header() + "%main = OpFunction %void None %void_func\n" +
1337 "%main_lab = OpLabel\n" +
1338 "%2 = OpDot %float %v2float_2_3 %v2float_2_0p5\n" +
1339 "OpReturn\n" +
1340 "OpFunctionEnd",
1341 2, 5.5f),
1342 // Test case 7: Fold (0.0, 0.0) dot v
1343 InstructionFoldingCase<float>(
1344 Header() + "%main = OpFunction %void None %void_func\n" +
1345 "%main_lab = OpLabel\n" +
1346 "%v = OpVariable %_ptr_v2float Function\n" +
1347 "%2 = OpLoad %v2float %v\n" +
1348 "%3 = OpDot %float %v2float_0_0 %2\n" +
1349 "OpReturn\n" +
1350 "OpFunctionEnd",
1351 3, 0.0f),
1352 // Test case 8: Fold v dot (0.0, 0.0)
1353 InstructionFoldingCase<float>(
1354 Header() + "%main = OpFunction %void None %void_func\n" +
1355 "%main_lab = OpLabel\n" +
1356 "%v = OpVariable %_ptr_v2float Function\n" +
1357 "%2 = OpLoad %v2float %v\n" +
1358 "%3 = OpDot %float %2 %v2float_0_0\n" +
1359 "OpReturn\n" +
1360 "OpFunctionEnd",
1361 3, 0.0f),
1362 // Test case 9: Fold Null dot v
1363 InstructionFoldingCase<float>(
1364 Header() + "%main = OpFunction %void None %void_func\n" +
1365 "%main_lab = OpLabel\n" +
1366 "%v = OpVariable %_ptr_v2float Function\n" +
1367 "%2 = OpLoad %v2float %v\n" +
1368 "%3 = OpDot %float %v2float_null %2\n" +
1369 "OpReturn\n" +
1370 "OpFunctionEnd",
1371 3, 0.0f),
1372 // Test case 10: Fold v dot Null
1373 InstructionFoldingCase<float>(
1374 Header() + "%main = OpFunction %void None %void_func\n" +
1375 "%main_lab = OpLabel\n" +
1376 "%v = OpVariable %_ptr_v2float Function\n" +
1377 "%2 = OpLoad %v2float %v\n" +
1378 "%3 = OpDot %float %2 %v2float_null\n" +
1379 "OpReturn\n" +
1380 "OpFunctionEnd",
1381 3, 0.0f),
1382 // Test case 11: Fold -2.0
1383 InstructionFoldingCase<float>(
1384 Header() + "%main = OpFunction %void None %void_func\n" +
1385 "%main_lab = OpLabel\n" +
1386 "%2 = OpFNegate %float %float_2\n" +
1387 "OpReturn\n" +
1388 "OpFunctionEnd",
1389 2, -2)
1390 ));
1391 // clang-format on
1392
1393 using DoubleInstructionFoldingTest =
1394 ::testing::TestWithParam<InstructionFoldingCase<double>>;
1395
TEST_P(DoubleInstructionFoldingTest,Case)1396 TEST_P(DoubleInstructionFoldingTest, Case) {
1397 const auto& tc = GetParam();
1398
1399 // Build module.
1400 std::unique_ptr<IRContext> context =
1401 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
1402 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1403 ASSERT_NE(nullptr, context);
1404
1405 // Fold the instruction to test.
1406 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
1407 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
1408 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
1409
1410 // Make sure the instruction folded as expected.
1411 EXPECT_TRUE(succeeded);
1412 if (inst != nullptr) {
1413 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
1414 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
1415 EXPECT_EQ(inst->opcode(), SpvOpConstant);
1416 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
1417 const analysis::FloatConstant* result =
1418 const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
1419 EXPECT_NE(result, nullptr);
1420 if (result != nullptr) {
1421 EXPECT_EQ(result->GetDoubleValue(), tc.expected_result);
1422 }
1423 }
1424 }
1425
1426 // clang-format off
1427 INSTANTIATE_TEST_CASE_P(DoubleConstantFoldingTest, DoubleInstructionFoldingTest,
1428 ::testing::Values(
1429 // Test case 0: Fold 2.0 - 1.0
1430 InstructionFoldingCase<double>(
1431 Header() + "%main = OpFunction %void None %void_func\n" +
1432 "%main_lab = OpLabel\n" +
1433 "%2 = OpFSub %double %double_2 %double_1\n" +
1434 "OpReturn\n" +
1435 "OpFunctionEnd",
1436 2, 1.0),
1437 // Test case 1: Fold 2.0 + 1.0
1438 InstructionFoldingCase<double>(
1439 Header() + "%main = OpFunction %void None %void_func\n" +
1440 "%main_lab = OpLabel\n" +
1441 "%2 = OpFAdd %double %double_2 %double_1\n" +
1442 "OpReturn\n" +
1443 "OpFunctionEnd",
1444 2, 3.0),
1445 // Test case 2: Fold 3.0 * 2.0
1446 InstructionFoldingCase<double>(
1447 Header() + "%main = OpFunction %void None %void_func\n" +
1448 "%main_lab = OpLabel\n" +
1449 "%2 = OpFMul %double %double_3 %double_2\n" +
1450 "OpReturn\n" +
1451 "OpFunctionEnd",
1452 2, 6.0),
1453 // Test case 3: Fold 1.0 / 2.0
1454 InstructionFoldingCase<double>(
1455 Header() + "%main = OpFunction %void None %void_func\n" +
1456 "%main_lab = OpLabel\n" +
1457 "%2 = OpFDiv %double %double_1 %double_2\n" +
1458 "OpReturn\n" +
1459 "OpFunctionEnd",
1460 2, 0.5),
1461 // Test case 4: Fold 1.0 / 0.0
1462 InstructionFoldingCase<double>(
1463 Header() + "%main = OpFunction %void None %void_func\n" +
1464 "%main_lab = OpLabel\n" +
1465 "%2 = OpFDiv %double %double_1 %double_0\n" +
1466 "OpReturn\n" +
1467 "OpFunctionEnd",
1468 2, std::numeric_limits<double>::infinity()),
1469 // Test case 5: Fold -1.0 / 0.0
1470 InstructionFoldingCase<double>(
1471 Header() + "%main = OpFunction %void None %void_func\n" +
1472 "%main_lab = OpLabel\n" +
1473 "%2 = OpFDiv %double %double_n1 %double_0\n" +
1474 "OpReturn\n" +
1475 "OpFunctionEnd",
1476 2, -std::numeric_limits<double>::infinity()),
1477 // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
1478 InstructionFoldingCase<double>(
1479 Header() + "%main = OpFunction %void None %void_func\n" +
1480 "%main_lab = OpLabel\n" +
1481 "%2 = OpDot %double %v2double_2_3 %v2double_2_0p5\n" +
1482 "OpReturn\n" +
1483 "OpFunctionEnd",
1484 2, 5.5f),
1485 // Test case 7: Fold (0.0, 0.0) dot v
1486 InstructionFoldingCase<double>(
1487 Header() + "%main = OpFunction %void None %void_func\n" +
1488 "%main_lab = OpLabel\n" +
1489 "%v = OpVariable %_ptr_v2double Function\n" +
1490 "%2 = OpLoad %v2double %v\n" +
1491 "%3 = OpDot %double %v2double_0_0 %2\n" +
1492 "OpReturn\n" +
1493 "OpFunctionEnd",
1494 3, 0.0f),
1495 // Test case 8: Fold v dot (0.0, 0.0)
1496 InstructionFoldingCase<double>(
1497 Header() + "%main = OpFunction %void None %void_func\n" +
1498 "%main_lab = OpLabel\n" +
1499 "%v = OpVariable %_ptr_v2double Function\n" +
1500 "%2 = OpLoad %v2double %v\n" +
1501 "%3 = OpDot %double %2 %v2double_0_0\n" +
1502 "OpReturn\n" +
1503 "OpFunctionEnd",
1504 3, 0.0f),
1505 // Test case 9: Fold Null dot v
1506 InstructionFoldingCase<double>(
1507 Header() + "%main = OpFunction %void None %void_func\n" +
1508 "%main_lab = OpLabel\n" +
1509 "%v = OpVariable %_ptr_v2double Function\n" +
1510 "%2 = OpLoad %v2double %v\n" +
1511 "%3 = OpDot %double %v2double_null %2\n" +
1512 "OpReturn\n" +
1513 "OpFunctionEnd",
1514 3, 0.0f),
1515 // Test case 10: Fold v dot Null
1516 InstructionFoldingCase<double>(
1517 Header() + "%main = OpFunction %void None %void_func\n" +
1518 "%main_lab = OpLabel\n" +
1519 "%v = OpVariable %_ptr_v2double Function\n" +
1520 "%2 = OpLoad %v2double %v\n" +
1521 "%3 = OpDot %double %2 %v2double_null\n" +
1522 "OpReturn\n" +
1523 "OpFunctionEnd",
1524 3, 0.0f),
1525 // Test case 11: Fold -2.0
1526 InstructionFoldingCase<double>(
1527 Header() + "%main = OpFunction %void None %void_func\n" +
1528 "%main_lab = OpLabel\n" +
1529 "%2 = OpFNegate %double %double_2\n" +
1530 "OpReturn\n" +
1531 "OpFunctionEnd",
1532 2, -2)
1533 ));
1534 // clang-format on
1535
1536 // clang-format off
1537 INSTANTIATE_TEST_CASE_P(DoubleOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
1538 ::testing::Values(
1539 // Test case 0: fold 1.0 == 2.0
1540 InstructionFoldingCase<bool>(
1541 Header() + "%main = OpFunction %void None %void_func\n" +
1542 "%main_lab = OpLabel\n" +
1543 "%2 = OpFOrdEqual %bool %double_1 %double_2\n" +
1544 "OpReturn\n" +
1545 "OpFunctionEnd",
1546 2, false),
1547 // Test case 1: fold 1.0 != 2.0
1548 InstructionFoldingCase<bool>(
1549 Header() + "%main = OpFunction %void None %void_func\n" +
1550 "%main_lab = OpLabel\n" +
1551 "%2 = OpFOrdNotEqual %bool %double_1 %double_2\n" +
1552 "OpReturn\n" +
1553 "OpFunctionEnd",
1554 2, true),
1555 // Test case 2: fold 1.0 < 2.0
1556 InstructionFoldingCase<bool>(
1557 Header() + "%main = OpFunction %void None %void_func\n" +
1558 "%main_lab = OpLabel\n" +
1559 "%2 = OpFOrdLessThan %bool %double_1 %double_2\n" +
1560 "OpReturn\n" +
1561 "OpFunctionEnd",
1562 2, true),
1563 // Test case 3: fold 1.0 > 2.0
1564 InstructionFoldingCase<bool>(
1565 Header() + "%main = OpFunction %void None %void_func\n" +
1566 "%main_lab = OpLabel\n" +
1567 "%2 = OpFOrdGreaterThan %bool %double_1 %double_2\n" +
1568 "OpReturn\n" +
1569 "OpFunctionEnd",
1570 2, false),
1571 // Test case 4: fold 1.0 <= 2.0
1572 InstructionFoldingCase<bool>(
1573 Header() + "%main = OpFunction %void None %void_func\n" +
1574 "%main_lab = OpLabel\n" +
1575 "%2 = OpFOrdLessThanEqual %bool %double_1 %double_2\n" +
1576 "OpReturn\n" +
1577 "OpFunctionEnd",
1578 2, true),
1579 // Test case 5: fold 1.0 >= 2.0
1580 InstructionFoldingCase<bool>(
1581 Header() + "%main = OpFunction %void None %void_func\n" +
1582 "%main_lab = OpLabel\n" +
1583 "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_2\n" +
1584 "OpReturn\n" +
1585 "OpFunctionEnd",
1586 2, false),
1587 // Test case 6: fold 1.0 == 1.0
1588 InstructionFoldingCase<bool>(
1589 Header() + "%main = OpFunction %void None %void_func\n" +
1590 "%main_lab = OpLabel\n" +
1591 "%2 = OpFOrdEqual %bool %double_1 %double_1\n" +
1592 "OpReturn\n" +
1593 "OpFunctionEnd",
1594 2, true),
1595 // Test case 7: fold 1.0 != 1.0
1596 InstructionFoldingCase<bool>(
1597 Header() + "%main = OpFunction %void None %void_func\n" +
1598 "%main_lab = OpLabel\n" +
1599 "%2 = OpFOrdNotEqual %bool %double_1 %double_1\n" +
1600 "OpReturn\n" +
1601 "OpFunctionEnd",
1602 2, false),
1603 // Test case 8: fold 1.0 < 1.0
1604 InstructionFoldingCase<bool>(
1605 Header() + "%main = OpFunction %void None %void_func\n" +
1606 "%main_lab = OpLabel\n" +
1607 "%2 = OpFOrdLessThan %bool %double_1 %double_1\n" +
1608 "OpReturn\n" +
1609 "OpFunctionEnd",
1610 2, false),
1611 // Test case 9: fold 1.0 > 1.0
1612 InstructionFoldingCase<bool>(
1613 Header() + "%main = OpFunction %void None %void_func\n" +
1614 "%main_lab = OpLabel\n" +
1615 "%2 = OpFOrdGreaterThan %bool %double_1 %double_1\n" +
1616 "OpReturn\n" +
1617 "OpFunctionEnd",
1618 2, false),
1619 // Test case 10: fold 1.0 <= 1.0
1620 InstructionFoldingCase<bool>(
1621 Header() + "%main = OpFunction %void None %void_func\n" +
1622 "%main_lab = OpLabel\n" +
1623 "%2 = OpFOrdLessThanEqual %bool %double_1 %double_1\n" +
1624 "OpReturn\n" +
1625 "OpFunctionEnd",
1626 2, true),
1627 // Test case 11: fold 1.0 >= 1.0
1628 InstructionFoldingCase<bool>(
1629 Header() + "%main = OpFunction %void None %void_func\n" +
1630 "%main_lab = OpLabel\n" +
1631 "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_1\n" +
1632 "OpReturn\n" +
1633 "OpFunctionEnd",
1634 2, true),
1635 // Test case 12: fold 2.0 < 1.0
1636 InstructionFoldingCase<bool>(
1637 Header() + "%main = OpFunction %void None %void_func\n" +
1638 "%main_lab = OpLabel\n" +
1639 "%2 = OpFOrdLessThan %bool %double_2 %double_1\n" +
1640 "OpReturn\n" +
1641 "OpFunctionEnd",
1642 2, false),
1643 // Test case 13: fold 2.0 > 1.0
1644 InstructionFoldingCase<bool>(
1645 Header() + "%main = OpFunction %void None %void_func\n" +
1646 "%main_lab = OpLabel\n" +
1647 "%2 = OpFOrdGreaterThan %bool %double_2 %double_1\n" +
1648 "OpReturn\n" +
1649 "OpFunctionEnd",
1650 2, true),
1651 // Test case 14: fold 2.0 <= 1.0
1652 InstructionFoldingCase<bool>(
1653 Header() + "%main = OpFunction %void None %void_func\n" +
1654 "%main_lab = OpLabel\n" +
1655 "%2 = OpFOrdLessThanEqual %bool %double_2 %double_1\n" +
1656 "OpReturn\n" +
1657 "OpFunctionEnd",
1658 2, false),
1659 // Test case 15: fold 2.0 >= 1.0
1660 InstructionFoldingCase<bool>(
1661 Header() + "%main = OpFunction %void None %void_func\n" +
1662 "%main_lab = OpLabel\n" +
1663 "%2 = OpFOrdGreaterThanEqual %bool %double_2 %double_1\n" +
1664 "OpReturn\n" +
1665 "OpFunctionEnd",
1666 2, true)
1667 ));
1668
1669 INSTANTIATE_TEST_CASE_P(DoubleUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
1670 ::testing::Values(
1671 // Test case 0: fold 1.0 == 2.0
1672 InstructionFoldingCase<bool>(
1673 Header() + "%main = OpFunction %void None %void_func\n" +
1674 "%main_lab = OpLabel\n" +
1675 "%2 = OpFUnordEqual %bool %double_1 %double_2\n" +
1676 "OpReturn\n" +
1677 "OpFunctionEnd",
1678 2, false),
1679 // Test case 1: fold 1.0 != 2.0
1680 InstructionFoldingCase<bool>(
1681 Header() + "%main = OpFunction %void None %void_func\n" +
1682 "%main_lab = OpLabel\n" +
1683 "%2 = OpFUnordNotEqual %bool %double_1 %double_2\n" +
1684 "OpReturn\n" +
1685 "OpFunctionEnd",
1686 2, true),
1687 // Test case 2: fold 1.0 < 2.0
1688 InstructionFoldingCase<bool>(
1689 Header() + "%main = OpFunction %void None %void_func\n" +
1690 "%main_lab = OpLabel\n" +
1691 "%2 = OpFUnordLessThan %bool %double_1 %double_2\n" +
1692 "OpReturn\n" +
1693 "OpFunctionEnd",
1694 2, true),
1695 // Test case 3: fold 1.0 > 2.0
1696 InstructionFoldingCase<bool>(
1697 Header() + "%main = OpFunction %void None %void_func\n" +
1698 "%main_lab = OpLabel\n" +
1699 "%2 = OpFUnordGreaterThan %bool %double_1 %double_2\n" +
1700 "OpReturn\n" +
1701 "OpFunctionEnd",
1702 2, false),
1703 // Test case 4: fold 1.0 <= 2.0
1704 InstructionFoldingCase<bool>(
1705 Header() + "%main = OpFunction %void None %void_func\n" +
1706 "%main_lab = OpLabel\n" +
1707 "%2 = OpFUnordLessThanEqual %bool %double_1 %double_2\n" +
1708 "OpReturn\n" +
1709 "OpFunctionEnd",
1710 2, true),
1711 // Test case 5: fold 1.0 >= 2.0
1712 InstructionFoldingCase<bool>(
1713 Header() + "%main = OpFunction %void None %void_func\n" +
1714 "%main_lab = OpLabel\n" +
1715 "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_2\n" +
1716 "OpReturn\n" +
1717 "OpFunctionEnd",
1718 2, false),
1719 // Test case 6: fold 1.0 == 1.0
1720 InstructionFoldingCase<bool>(
1721 Header() + "%main = OpFunction %void None %void_func\n" +
1722 "%main_lab = OpLabel\n" +
1723 "%2 = OpFUnordEqual %bool %double_1 %double_1\n" +
1724 "OpReturn\n" +
1725 "OpFunctionEnd",
1726 2, true),
1727 // Test case 7: fold 1.0 != 1.0
1728 InstructionFoldingCase<bool>(
1729 Header() + "%main = OpFunction %void None %void_func\n" +
1730 "%main_lab = OpLabel\n" +
1731 "%2 = OpFUnordNotEqual %bool %double_1 %double_1\n" +
1732 "OpReturn\n" +
1733 "OpFunctionEnd",
1734 2, false),
1735 // Test case 8: fold 1.0 < 1.0
1736 InstructionFoldingCase<bool>(
1737 Header() + "%main = OpFunction %void None %void_func\n" +
1738 "%main_lab = OpLabel\n" +
1739 "%2 = OpFUnordLessThan %bool %double_1 %double_1\n" +
1740 "OpReturn\n" +
1741 "OpFunctionEnd",
1742 2, false),
1743 // Test case 9: fold 1.0 > 1.0
1744 InstructionFoldingCase<bool>(
1745 Header() + "%main = OpFunction %void None %void_func\n" +
1746 "%main_lab = OpLabel\n" +
1747 "%2 = OpFUnordGreaterThan %bool %double_1 %double_1\n" +
1748 "OpReturn\n" +
1749 "OpFunctionEnd",
1750 2, false),
1751 // Test case 10: fold 1.0 <= 1.0
1752 InstructionFoldingCase<bool>(
1753 Header() + "%main = OpFunction %void None %void_func\n" +
1754 "%main_lab = OpLabel\n" +
1755 "%2 = OpFUnordLessThanEqual %bool %double_1 %double_1\n" +
1756 "OpReturn\n" +
1757 "OpFunctionEnd",
1758 2, true),
1759 // Test case 11: fold 1.0 >= 1.0
1760 InstructionFoldingCase<bool>(
1761 Header() + "%main = OpFunction %void None %void_func\n" +
1762 "%main_lab = OpLabel\n" +
1763 "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_1\n" +
1764 "OpReturn\n" +
1765 "OpFunctionEnd",
1766 2, true),
1767 // Test case 12: fold 2.0 < 1.0
1768 InstructionFoldingCase<bool>(
1769 Header() + "%main = OpFunction %void None %void_func\n" +
1770 "%main_lab = OpLabel\n" +
1771 "%2 = OpFUnordLessThan %bool %double_2 %double_1\n" +
1772 "OpReturn\n" +
1773 "OpFunctionEnd",
1774 2, false),
1775 // Test case 13: fold 2.0 > 1.0
1776 InstructionFoldingCase<bool>(
1777 Header() + "%main = OpFunction %void None %void_func\n" +
1778 "%main_lab = OpLabel\n" +
1779 "%2 = OpFUnordGreaterThan %bool %double_2 %double_1\n" +
1780 "OpReturn\n" +
1781 "OpFunctionEnd",
1782 2, true),
1783 // Test case 14: fold 2.0 <= 1.0
1784 InstructionFoldingCase<bool>(
1785 Header() + "%main = OpFunction %void None %void_func\n" +
1786 "%main_lab = OpLabel\n" +
1787 "%2 = OpFUnordLessThanEqual %bool %double_2 %double_1\n" +
1788 "OpReturn\n" +
1789 "OpFunctionEnd",
1790 2, false),
1791 // Test case 15: fold 2.0 >= 1.0
1792 InstructionFoldingCase<bool>(
1793 Header() + "%main = OpFunction %void None %void_func\n" +
1794 "%main_lab = OpLabel\n" +
1795 "%2 = OpFUnordGreaterThanEqual %bool %double_2 %double_1\n" +
1796 "OpReturn\n" +
1797 "OpFunctionEnd",
1798 2, true)
1799 ));
1800
1801 INSTANTIATE_TEST_CASE_P(FloatOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
1802 ::testing::Values(
1803 // Test case 0: fold 1.0 == 2.0
1804 InstructionFoldingCase<bool>(
1805 Header() + "%main = OpFunction %void None %void_func\n" +
1806 "%main_lab = OpLabel\n" +
1807 "%2 = OpFOrdEqual %bool %float_1 %float_2\n" +
1808 "OpReturn\n" +
1809 "OpFunctionEnd",
1810 2, false),
1811 // Test case 1: fold 1.0 != 2.0
1812 InstructionFoldingCase<bool>(
1813 Header() + "%main = OpFunction %void None %void_func\n" +
1814 "%main_lab = OpLabel\n" +
1815 "%2 = OpFOrdNotEqual %bool %float_1 %float_2\n" +
1816 "OpReturn\n" +
1817 "OpFunctionEnd",
1818 2, true),
1819 // Test case 2: fold 1.0 < 2.0
1820 InstructionFoldingCase<bool>(
1821 Header() + "%main = OpFunction %void None %void_func\n" +
1822 "%main_lab = OpLabel\n" +
1823 "%2 = OpFOrdLessThan %bool %float_1 %float_2\n" +
1824 "OpReturn\n" +
1825 "OpFunctionEnd",
1826 2, true),
1827 // Test case 3: fold 1.0 > 2.0
1828 InstructionFoldingCase<bool>(
1829 Header() + "%main = OpFunction %void None %void_func\n" +
1830 "%main_lab = OpLabel\n" +
1831 "%2 = OpFOrdGreaterThan %bool %float_1 %float_2\n" +
1832 "OpReturn\n" +
1833 "OpFunctionEnd",
1834 2, false),
1835 // Test case 4: fold 1.0 <= 2.0
1836 InstructionFoldingCase<bool>(
1837 Header() + "%main = OpFunction %void None %void_func\n" +
1838 "%main_lab = OpLabel\n" +
1839 "%2 = OpFOrdLessThanEqual %bool %float_1 %float_2\n" +
1840 "OpReturn\n" +
1841 "OpFunctionEnd",
1842 2, true),
1843 // Test case 5: fold 1.0 >= 2.0
1844 InstructionFoldingCase<bool>(
1845 Header() + "%main = OpFunction %void None %void_func\n" +
1846 "%main_lab = OpLabel\n" +
1847 "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_2\n" +
1848 "OpReturn\n" +
1849 "OpFunctionEnd",
1850 2, false),
1851 // Test case 6: fold 1.0 == 1.0
1852 InstructionFoldingCase<bool>(
1853 Header() + "%main = OpFunction %void None %void_func\n" +
1854 "%main_lab = OpLabel\n" +
1855 "%2 = OpFOrdEqual %bool %float_1 %float_1\n" +
1856 "OpReturn\n" +
1857 "OpFunctionEnd",
1858 2, true),
1859 // Test case 7: fold 1.0 != 1.0
1860 InstructionFoldingCase<bool>(
1861 Header() + "%main = OpFunction %void None %void_func\n" +
1862 "%main_lab = OpLabel\n" +
1863 "%2 = OpFOrdNotEqual %bool %float_1 %float_1\n" +
1864 "OpReturn\n" +
1865 "OpFunctionEnd",
1866 2, false),
1867 // Test case 8: fold 1.0 < 1.0
1868 InstructionFoldingCase<bool>(
1869 Header() + "%main = OpFunction %void None %void_func\n" +
1870 "%main_lab = OpLabel\n" +
1871 "%2 = OpFOrdLessThan %bool %float_1 %float_1\n" +
1872 "OpReturn\n" +
1873 "OpFunctionEnd",
1874 2, false),
1875 // Test case 9: fold 1.0 > 1.0
1876 InstructionFoldingCase<bool>(
1877 Header() + "%main = OpFunction %void None %void_func\n" +
1878 "%main_lab = OpLabel\n" +
1879 "%2 = OpFOrdGreaterThan %bool %float_1 %float_1\n" +
1880 "OpReturn\n" +
1881 "OpFunctionEnd",
1882 2, false),
1883 // Test case 10: fold 1.0 <= 1.0
1884 InstructionFoldingCase<bool>(
1885 Header() + "%main = OpFunction %void None %void_func\n" +
1886 "%main_lab = OpLabel\n" +
1887 "%2 = OpFOrdLessThanEqual %bool %float_1 %float_1\n" +
1888 "OpReturn\n" +
1889 "OpFunctionEnd",
1890 2, true),
1891 // Test case 11: fold 1.0 >= 1.0
1892 InstructionFoldingCase<bool>(
1893 Header() + "%main = OpFunction %void None %void_func\n" +
1894 "%main_lab = OpLabel\n" +
1895 "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_1\n" +
1896 "OpReturn\n" +
1897 "OpFunctionEnd",
1898 2, true),
1899 // Test case 12: fold 2.0 < 1.0
1900 InstructionFoldingCase<bool>(
1901 Header() + "%main = OpFunction %void None %void_func\n" +
1902 "%main_lab = OpLabel\n" +
1903 "%2 = OpFOrdLessThan %bool %float_2 %float_1\n" +
1904 "OpReturn\n" +
1905 "OpFunctionEnd",
1906 2, false),
1907 // Test case 13: fold 2.0 > 1.0
1908 InstructionFoldingCase<bool>(
1909 Header() + "%main = OpFunction %void None %void_func\n" +
1910 "%main_lab = OpLabel\n" +
1911 "%2 = OpFOrdGreaterThan %bool %float_2 %float_1\n" +
1912 "OpReturn\n" +
1913 "OpFunctionEnd",
1914 2, true),
1915 // Test case 14: fold 2.0 <= 1.0
1916 InstructionFoldingCase<bool>(
1917 Header() + "%main = OpFunction %void None %void_func\n" +
1918 "%main_lab = OpLabel\n" +
1919 "%2 = OpFOrdLessThanEqual %bool %float_2 %float_1\n" +
1920 "OpReturn\n" +
1921 "OpFunctionEnd",
1922 2, false),
1923 // Test case 15: fold 2.0 >= 1.0
1924 InstructionFoldingCase<bool>(
1925 Header() + "%main = OpFunction %void None %void_func\n" +
1926 "%main_lab = OpLabel\n" +
1927 "%2 = OpFOrdGreaterThanEqual %bool %float_2 %float_1\n" +
1928 "OpReturn\n" +
1929 "OpFunctionEnd",
1930 2, true)
1931 ));
1932
1933 INSTANTIATE_TEST_CASE_P(FloatUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
1934 ::testing::Values(
1935 // Test case 0: fold 1.0 == 2.0
1936 InstructionFoldingCase<bool>(
1937 Header() + "%main = OpFunction %void None %void_func\n" +
1938 "%main_lab = OpLabel\n" +
1939 "%2 = OpFUnordEqual %bool %float_1 %float_2\n" +
1940 "OpReturn\n" +
1941 "OpFunctionEnd",
1942 2, false),
1943 // Test case 1: fold 1.0 != 2.0
1944 InstructionFoldingCase<bool>(
1945 Header() + "%main = OpFunction %void None %void_func\n" +
1946 "%main_lab = OpLabel\n" +
1947 "%2 = OpFUnordNotEqual %bool %float_1 %float_2\n" +
1948 "OpReturn\n" +
1949 "OpFunctionEnd",
1950 2, true),
1951 // Test case 2: fold 1.0 < 2.0
1952 InstructionFoldingCase<bool>(
1953 Header() + "%main = OpFunction %void None %void_func\n" +
1954 "%main_lab = OpLabel\n" +
1955 "%2 = OpFUnordLessThan %bool %float_1 %float_2\n" +
1956 "OpReturn\n" +
1957 "OpFunctionEnd",
1958 2, true),
1959 // Test case 3: fold 1.0 > 2.0
1960 InstructionFoldingCase<bool>(
1961 Header() + "%main = OpFunction %void None %void_func\n" +
1962 "%main_lab = OpLabel\n" +
1963 "%2 = OpFUnordGreaterThan %bool %float_1 %float_2\n" +
1964 "OpReturn\n" +
1965 "OpFunctionEnd",
1966 2, false),
1967 // Test case 4: fold 1.0 <= 2.0
1968 InstructionFoldingCase<bool>(
1969 Header() + "%main = OpFunction %void None %void_func\n" +
1970 "%main_lab = OpLabel\n" +
1971 "%2 = OpFUnordLessThanEqual %bool %float_1 %float_2\n" +
1972 "OpReturn\n" +
1973 "OpFunctionEnd",
1974 2, true),
1975 // Test case 5: fold 1.0 >= 2.0
1976 InstructionFoldingCase<bool>(
1977 Header() + "%main = OpFunction %void None %void_func\n" +
1978 "%main_lab = OpLabel\n" +
1979 "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_2\n" +
1980 "OpReturn\n" +
1981 "OpFunctionEnd",
1982 2, false),
1983 // Test case 6: fold 1.0 == 1.0
1984 InstructionFoldingCase<bool>(
1985 Header() + "%main = OpFunction %void None %void_func\n" +
1986 "%main_lab = OpLabel\n" +
1987 "%2 = OpFUnordEqual %bool %float_1 %float_1\n" +
1988 "OpReturn\n" +
1989 "OpFunctionEnd",
1990 2, true),
1991 // Test case 7: fold 1.0 != 1.0
1992 InstructionFoldingCase<bool>(
1993 Header() + "%main = OpFunction %void None %void_func\n" +
1994 "%main_lab = OpLabel\n" +
1995 "%2 = OpFUnordNotEqual %bool %float_1 %float_1\n" +
1996 "OpReturn\n" +
1997 "OpFunctionEnd",
1998 2, false),
1999 // Test case 8: fold 1.0 < 1.0
2000 InstructionFoldingCase<bool>(
2001 Header() + "%main = OpFunction %void None %void_func\n" +
2002 "%main_lab = OpLabel\n" +
2003 "%2 = OpFUnordLessThan %bool %float_1 %float_1\n" +
2004 "OpReturn\n" +
2005 "OpFunctionEnd",
2006 2, false),
2007 // Test case 9: fold 1.0 > 1.0
2008 InstructionFoldingCase<bool>(
2009 Header() + "%main = OpFunction %void None %void_func\n" +
2010 "%main_lab = OpLabel\n" +
2011 "%2 = OpFUnordGreaterThan %bool %float_1 %float_1\n" +
2012 "OpReturn\n" +
2013 "OpFunctionEnd",
2014 2, false),
2015 // Test case 10: fold 1.0 <= 1.0
2016 InstructionFoldingCase<bool>(
2017 Header() + "%main = OpFunction %void None %void_func\n" +
2018 "%main_lab = OpLabel\n" +
2019 "%2 = OpFUnordLessThanEqual %bool %float_1 %float_1\n" +
2020 "OpReturn\n" +
2021 "OpFunctionEnd",
2022 2, true),
2023 // Test case 11: fold 1.0 >= 1.0
2024 InstructionFoldingCase<bool>(
2025 Header() + "%main = OpFunction %void None %void_func\n" +
2026 "%main_lab = OpLabel\n" +
2027 "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_1\n" +
2028 "OpReturn\n" +
2029 "OpFunctionEnd",
2030 2, true),
2031 // Test case 12: fold 2.0 < 1.0
2032 InstructionFoldingCase<bool>(
2033 Header() + "%main = OpFunction %void None %void_func\n" +
2034 "%main_lab = OpLabel\n" +
2035 "%2 = OpFUnordLessThan %bool %float_2 %float_1\n" +
2036 "OpReturn\n" +
2037 "OpFunctionEnd",
2038 2, false),
2039 // Test case 13: fold 2.0 > 1.0
2040 InstructionFoldingCase<bool>(
2041 Header() + "%main = OpFunction %void None %void_func\n" +
2042 "%main_lab = OpLabel\n" +
2043 "%2 = OpFUnordGreaterThan %bool %float_2 %float_1\n" +
2044 "OpReturn\n" +
2045 "OpFunctionEnd",
2046 2, true),
2047 // Test case 14: fold 2.0 <= 1.0
2048 InstructionFoldingCase<bool>(
2049 Header() + "%main = OpFunction %void None %void_func\n" +
2050 "%main_lab = OpLabel\n" +
2051 "%2 = OpFUnordLessThanEqual %bool %float_2 %float_1\n" +
2052 "OpReturn\n" +
2053 "OpFunctionEnd",
2054 2, false),
2055 // Test case 15: fold 2.0 >= 1.0
2056 InstructionFoldingCase<bool>(
2057 Header() + "%main = OpFunction %void None %void_func\n" +
2058 "%main_lab = OpLabel\n" +
2059 "%2 = OpFUnordGreaterThanEqual %bool %float_2 %float_1\n" +
2060 "OpReturn\n" +
2061 "OpFunctionEnd",
2062 2, true)
2063 ));
2064
2065 INSTANTIATE_TEST_CASE_P(DoubleNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
2066 ::testing::Values(
2067 // Test case 0: fold NaN == 0 (ord)
2068 InstructionFoldingCase<bool>(
2069 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2070 "%main_lab = OpLabel\n" +
2071 "%2 = OpFOrdEqual %bool %double_nan %double_0\n" +
2072 "OpReturn\n" +
2073 "OpFunctionEnd",
2074 2, false),
2075 // Test case 1: fold NaN == NaN (unord)
2076 InstructionFoldingCase<bool>(
2077 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2078 "%main_lab = OpLabel\n" +
2079 "%2 = OpFUnordEqual %bool %double_nan %double_0\n" +
2080 "OpReturn\n" +
2081 "OpFunctionEnd",
2082 2, true),
2083 // Test case 2: fold NaN != NaN (ord)
2084 InstructionFoldingCase<bool>(
2085 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2086 "%main_lab = OpLabel\n" +
2087 "%2 = OpFOrdNotEqual %bool %double_nan %double_0\n" +
2088 "OpReturn\n" +
2089 "OpFunctionEnd",
2090 2, false),
2091 // Test case 3: fold NaN != NaN (unord)
2092 InstructionFoldingCase<bool>(
2093 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2094 "%main_lab = OpLabel\n" +
2095 "%2 = OpFUnordNotEqual %bool %double_nan %double_0\n" +
2096 "OpReturn\n" +
2097 "OpFunctionEnd",
2098 2, true)
2099 ));
2100
2101 INSTANTIATE_TEST_CASE_P(FloatNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
2102 ::testing::Values(
2103 // Test case 0: fold NaN == 0 (ord)
2104 InstructionFoldingCase<bool>(
2105 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2106 "%main_lab = OpLabel\n" +
2107 "%2 = OpFOrdEqual %bool %float_nan %float_0\n" +
2108 "OpReturn\n" +
2109 "OpFunctionEnd",
2110 2, false),
2111 // Test case 1: fold NaN == NaN (unord)
2112 InstructionFoldingCase<bool>(
2113 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2114 "%main_lab = OpLabel\n" +
2115 "%2 = OpFUnordEqual %bool %float_nan %float_0\n" +
2116 "OpReturn\n" +
2117 "OpFunctionEnd",
2118 2, true),
2119 // Test case 2: fold NaN != NaN (ord)
2120 InstructionFoldingCase<bool>(
2121 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2122 "%main_lab = OpLabel\n" +
2123 "%2 = OpFOrdNotEqual %bool %float_nan %float_0\n" +
2124 "OpReturn\n" +
2125 "OpFunctionEnd",
2126 2, false),
2127 // Test case 3: fold NaN != NaN (unord)
2128 InstructionFoldingCase<bool>(
2129 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2130 "%main_lab = OpLabel\n" +
2131 "%2 = OpFUnordNotEqual %bool %float_nan %float_0\n" +
2132 "OpReturn\n" +
2133 "OpFunctionEnd",
2134 2, true)
2135 ));
2136 // clang-format on
2137
2138 template <class ResultType>
2139 struct InstructionFoldingCaseWithMap {
InstructionFoldingCaseWithMapspvtools::opt::__anonaa214b840111::InstructionFoldingCaseWithMap2140 InstructionFoldingCaseWithMap(const std::string& tb, uint32_t id,
2141 ResultType result,
2142 std::function<uint32_t(uint32_t)> map)
2143 : test_body(tb), id_to_fold(id), expected_result(result), id_map(map) {}
2144
2145 std::string test_body;
2146 uint32_t id_to_fold;
2147 ResultType expected_result;
2148 std::function<uint32_t(uint32_t)> id_map;
2149 };
2150
2151 using IntegerInstructionFoldingTestWithMap =
2152 ::testing::TestWithParam<InstructionFoldingCaseWithMap<uint32_t>>;
2153
TEST_P(IntegerInstructionFoldingTestWithMap,Case)2154 TEST_P(IntegerInstructionFoldingTestWithMap, Case) {
2155 const auto& tc = GetParam();
2156
2157 // Build module.
2158 std::unique_ptr<IRContext> context =
2159 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
2160 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2161 ASSERT_NE(nullptr, context);
2162
2163 // Fold the instruction to test.
2164 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
2165 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
2166 inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
2167 tc.id_map);
2168
2169 // Make sure the instruction folded as expected.
2170 EXPECT_NE(inst, nullptr);
2171 if (inst != nullptr) {
2172 EXPECT_EQ(inst->opcode(), SpvOpConstant);
2173 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
2174 const analysis::IntConstant* result =
2175 const_mrg->GetConstantFromInst(inst)->AsIntConstant();
2176 EXPECT_NE(result, nullptr);
2177 if (result != nullptr) {
2178 EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
2179 }
2180 }
2181 }
2182 // clang-format off
2183 INSTANTIATE_TEST_CASE_P(TestCase, IntegerInstructionFoldingTestWithMap,
2184 ::testing::Values(
2185 // Test case 0: fold %3 = 0; %3 * n
2186 InstructionFoldingCaseWithMap<uint32_t>(
2187 Header() + "%main = OpFunction %void None %void_func\n" +
2188 "%main_lab = OpLabel\n" +
2189 "%n = OpVariable %_ptr_int Function\n" +
2190 "%load = OpLoad %int %n\n" +
2191 "%3 = OpCopyObject %int %int_0\n"
2192 "%2 = OpIMul %int %3 %load\n" +
2193 "OpReturn\n" +
2194 "OpFunctionEnd",
__anonaa214b840202(uint32_t id) 2195 2, 0, [](uint32_t id) {return (id == 3 ? INT_0_ID : id);})
2196 ));
2197 // clang-format on
2198
2199 using BooleanInstructionFoldingTestWithMap =
2200 ::testing::TestWithParam<InstructionFoldingCaseWithMap<bool>>;
2201
TEST_P(BooleanInstructionFoldingTestWithMap,Case)2202 TEST_P(BooleanInstructionFoldingTestWithMap, Case) {
2203 const auto& tc = GetParam();
2204
2205 // Build module.
2206 std::unique_ptr<IRContext> context =
2207 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
2208 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2209 ASSERT_NE(nullptr, context);
2210
2211 // Fold the instruction to test.
2212 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
2213 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
2214 inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
2215 tc.id_map);
2216
2217 // Make sure the instruction folded as expected.
2218 EXPECT_NE(inst, nullptr);
2219 if (inst != nullptr) {
2220 std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
2221 EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
2222 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
2223 const analysis::BoolConstant* result =
2224 const_mrg->GetConstantFromInst(inst)->AsBoolConstant();
2225 EXPECT_NE(result, nullptr);
2226 if (result != nullptr) {
2227 EXPECT_EQ(result->value(), tc.expected_result);
2228 }
2229 }
2230 }
2231
2232 // clang-format off
2233 INSTANTIATE_TEST_CASE_P(TestCase, BooleanInstructionFoldingTestWithMap,
2234 ::testing::Values(
2235 // Test case 0: fold %3 = true; %3 || n
2236 InstructionFoldingCaseWithMap<bool>(
2237 Header() + "%main = OpFunction %void None %void_func\n" +
2238 "%main_lab = OpLabel\n" +
2239 "%n = OpVariable %_ptr_bool Function\n" +
2240 "%load = OpLoad %bool %n\n" +
2241 "%3 = OpCopyObject %bool %true\n" +
2242 "%2 = OpLogicalOr %bool %3 %load\n" +
2243 "OpReturn\n" +
2244 "OpFunctionEnd",
__anonaa214b840302(uint32_t id) 2245 2, true, [](uint32_t id) {return (id == 3 ? TRUE_ID : id);})
2246 ));
2247 // clang-format on
2248
2249 using GeneralInstructionFoldingTest =
2250 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
2251
TEST_P(GeneralInstructionFoldingTest,Case)2252 TEST_P(GeneralInstructionFoldingTest, Case) {
2253 const auto& tc = GetParam();
2254
2255 // Build module.
2256 std::unique_ptr<IRContext> context =
2257 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
2258 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2259 ASSERT_NE(nullptr, context);
2260
2261 // Fold the instruction to test.
2262 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
2263 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
2264 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
2265 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
2266
2267 // Make sure the instruction folded as expected.
2268 EXPECT_EQ(inst->result_id(), original_inst->result_id());
2269 EXPECT_EQ(inst->type_id(), original_inst->type_id());
2270 EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
2271 if (succeeded) {
2272 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
2273 EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
2274 } else {
2275 EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
2276 for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
2277 EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
2278 }
2279 }
2280 }
2281
2282 // clang-format off
2283 INSTANTIATE_TEST_CASE_P(IntegerArithmeticTestCases, GeneralInstructionFoldingTest,
2284 ::testing::Values(
2285 // Test case 0: Don't fold n * m
2286 InstructionFoldingCase<uint32_t>(
2287 Header() + "%main = OpFunction %void None %void_func\n" +
2288 "%main_lab = OpLabel\n" +
2289 "%n = OpVariable %_ptr_int Function\n" +
2290 "%m = OpVariable %_ptr_int Function\n" +
2291 "%load_n = OpLoad %int %n\n" +
2292 "%load_m = OpLoad %int %m\n" +
2293 "%2 = OpIMul %int %load_n %load_m\n" +
2294 "OpReturn\n" +
2295 "OpFunctionEnd",
2296 2, 0),
2297 // Test case 1: Don't fold n / m (unsigned)
2298 InstructionFoldingCase<uint32_t>(
2299 Header() + "%main = OpFunction %void None %void_func\n" +
2300 "%main_lab = OpLabel\n" +
2301 "%n = OpVariable %_ptr_uint Function\n" +
2302 "%m = OpVariable %_ptr_uint Function\n" +
2303 "%load_n = OpLoad %uint %n\n" +
2304 "%load_m = OpLoad %uint %m\n" +
2305 "%2 = OpUDiv %uint %load_n %load_m\n" +
2306 "OpReturn\n" +
2307 "OpFunctionEnd",
2308 2, 0),
2309 // Test case 2: Don't fold n / m (signed)
2310 InstructionFoldingCase<uint32_t>(
2311 Header() + "%main = OpFunction %void None %void_func\n" +
2312 "%main_lab = OpLabel\n" +
2313 "%n = OpVariable %_ptr_int Function\n" +
2314 "%m = OpVariable %_ptr_int Function\n" +
2315 "%load_n = OpLoad %int %n\n" +
2316 "%load_m = OpLoad %int %m\n" +
2317 "%2 = OpSDiv %int %load_n %load_m\n" +
2318 "OpReturn\n" +
2319 "OpFunctionEnd",
2320 2, 0),
2321 // Test case 3: Don't fold n remainder m
2322 InstructionFoldingCase<uint32_t>(
2323 Header() + "%main = OpFunction %void None %void_func\n" +
2324 "%main_lab = OpLabel\n" +
2325 "%n = OpVariable %_ptr_int Function\n" +
2326 "%m = OpVariable %_ptr_int Function\n" +
2327 "%load_n = OpLoad %int %n\n" +
2328 "%load_m = OpLoad %int %m\n" +
2329 "%2 = OpSRem %int %load_n %load_m\n" +
2330 "OpReturn\n" +
2331 "OpFunctionEnd",
2332 2, 0),
2333 // Test case 4: Don't fold n % m (signed)
2334 InstructionFoldingCase<uint32_t>(
2335 Header() + "%main = OpFunction %void None %void_func\n" +
2336 "%main_lab = OpLabel\n" +
2337 "%n = OpVariable %_ptr_int Function\n" +
2338 "%m = OpVariable %_ptr_int Function\n" +
2339 "%load_n = OpLoad %int %n\n" +
2340 "%load_m = OpLoad %int %m\n" +
2341 "%2 = OpSMod %int %load_n %load_m\n" +
2342 "OpReturn\n" +
2343 "OpFunctionEnd",
2344 2, 0),
2345 // Test case 5: Don't fold n % m (unsigned)
2346 InstructionFoldingCase<uint32_t>(
2347 Header() + "%main = OpFunction %void None %void_func\n" +
2348 "%main_lab = OpLabel\n" +
2349 "%n = OpVariable %_ptr_uint Function\n" +
2350 "%m = OpVariable %_ptr_uint Function\n" +
2351 "%load_n = OpLoad %uint %n\n" +
2352 "%load_m = OpLoad %uint %m\n" +
2353 "%2 = OpUMod %int %load_n %load_m\n" +
2354 "OpReturn\n" +
2355 "OpFunctionEnd",
2356 2, 0),
2357 // Test case 6: Don't fold n << m
2358 InstructionFoldingCase<uint32_t>(
2359 Header() + "%main = OpFunction %void None %void_func\n" +
2360 "%main_lab = OpLabel\n" +
2361 "%n = OpVariable %_ptr_uint Function\n" +
2362 "%m = OpVariable %_ptr_uint Function\n" +
2363 "%load_n = OpLoad %uint %n\n" +
2364 "%load_m = OpLoad %uint %m\n" +
2365 "%2 = OpShiftRightLogical %int %load_n %load_m\n" +
2366 "OpReturn\n" +
2367 "OpFunctionEnd",
2368 2, 0),
2369 // Test case 7: Don't fold n >> m
2370 InstructionFoldingCase<uint32_t>(
2371 Header() + "%main = OpFunction %void None %void_func\n" +
2372 "%main_lab = OpLabel\n" +
2373 "%n = OpVariable %_ptr_uint Function\n" +
2374 "%m = OpVariable %_ptr_uint Function\n" +
2375 "%load_n = OpLoad %uint %n\n" +
2376 "%load_m = OpLoad %uint %m\n" +
2377 "%2 = OpShiftLeftLogical %int %load_n %load_m\n" +
2378 "OpReturn\n" +
2379 "OpFunctionEnd",
2380 2, 0),
2381 // Test case 8: Don't fold n | m
2382 InstructionFoldingCase<uint32_t>(
2383 Header() + "%main = OpFunction %void None %void_func\n" +
2384 "%main_lab = OpLabel\n" +
2385 "%n = OpVariable %_ptr_uint Function\n" +
2386 "%m = OpVariable %_ptr_uint Function\n" +
2387 "%load_n = OpLoad %uint %n\n" +
2388 "%load_m = OpLoad %uint %m\n" +
2389 "%2 = OpBitwiseOr %int %load_n %load_m\n" +
2390 "OpReturn\n" +
2391 "OpFunctionEnd",
2392 2, 0),
2393 // Test case 9: Don't fold n & m
2394 InstructionFoldingCase<uint32_t>(
2395 Header() + "%main = OpFunction %void None %void_func\n" +
2396 "%main_lab = OpLabel\n" +
2397 "%n = OpVariable %_ptr_uint Function\n" +
2398 "%m = OpVariable %_ptr_uint Function\n" +
2399 "%load_n = OpLoad %uint %n\n" +
2400 "%load_m = OpLoad %uint %m\n" +
2401 "%2 = OpBitwiseAnd %int %load_n %load_m\n" +
2402 "OpReturn\n" +
2403 "OpFunctionEnd",
2404 2, 0),
2405 // Test case 10: Don't fold n < m (unsigned)
2406 InstructionFoldingCase<uint32_t>(
2407 Header() + "%main = OpFunction %void None %void_func\n" +
2408 "%main_lab = OpLabel\n" +
2409 "%n = OpVariable %_ptr_uint Function\n" +
2410 "%m = OpVariable %_ptr_uint Function\n" +
2411 "%load_n = OpLoad %uint %n\n" +
2412 "%load_m = OpLoad %uint %m\n" +
2413 "%2 = OpULessThan %bool %load_n %load_m\n" +
2414 "OpReturn\n" +
2415 "OpFunctionEnd",
2416 2, 0),
2417 // Test case 11: Don't fold n > m (unsigned)
2418 InstructionFoldingCase<uint32_t>(
2419 Header() + "%main = OpFunction %void None %void_func\n" +
2420 "%main_lab = OpLabel\n" +
2421 "%n = OpVariable %_ptr_uint Function\n" +
2422 "%m = OpVariable %_ptr_uint Function\n" +
2423 "%load_n = OpLoad %uint %n\n" +
2424 "%load_m = OpLoad %uint %m\n" +
2425 "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
2426 "OpReturn\n" +
2427 "OpFunctionEnd",
2428 2, 0),
2429 // Test case 12: Don't fold n <= m (unsigned)
2430 InstructionFoldingCase<uint32_t>(
2431 Header() + "%main = OpFunction %void None %void_func\n" +
2432 "%main_lab = OpLabel\n" +
2433 "%n = OpVariable %_ptr_uint Function\n" +
2434 "%m = OpVariable %_ptr_uint Function\n" +
2435 "%load_n = OpLoad %uint %n\n" +
2436 "%load_m = OpLoad %uint %m\n" +
2437 "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
2438 "OpReturn\n" +
2439 "OpFunctionEnd",
2440 2, 0),
2441 // Test case 13: Don't fold n >= m (unsigned)
2442 InstructionFoldingCase<uint32_t>(
2443 Header() + "%main = OpFunction %void None %void_func\n" +
2444 "%main_lab = OpLabel\n" +
2445 "%n = OpVariable %_ptr_uint Function\n" +
2446 "%m = OpVariable %_ptr_uint Function\n" +
2447 "%load_n = OpLoad %uint %n\n" +
2448 "%load_m = OpLoad %uint %m\n" +
2449 "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
2450 "OpReturn\n" +
2451 "OpFunctionEnd",
2452 2, 0),
2453 // Test case 14: Don't fold n < m (signed)
2454 InstructionFoldingCase<uint32_t>(
2455 Header() + "%main = OpFunction %void None %void_func\n" +
2456 "%main_lab = OpLabel\n" +
2457 "%n = OpVariable %_ptr_int Function\n" +
2458 "%m = OpVariable %_ptr_int Function\n" +
2459 "%load_n = OpLoad %int %n\n" +
2460 "%load_m = OpLoad %int %m\n" +
2461 "%2 = OpULessThan %bool %load_n %load_m\n" +
2462 "OpReturn\n" +
2463 "OpFunctionEnd",
2464 2, 0),
2465 // Test case 15: Don't fold n > m (signed)
2466 InstructionFoldingCase<uint32_t>(
2467 Header() + "%main = OpFunction %void None %void_func\n" +
2468 "%main_lab = OpLabel\n" +
2469 "%n = OpVariable %_ptr_int Function\n" +
2470 "%m = OpVariable %_ptr_int Function\n" +
2471 "%load_n = OpLoad %int %n\n" +
2472 "%load_m = OpLoad %int %m\n" +
2473 "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
2474 "OpReturn\n" +
2475 "OpFunctionEnd",
2476 2, 0),
2477 // Test case 16: Don't fold n <= m (signed)
2478 InstructionFoldingCase<uint32_t>(
2479 Header() + "%main = OpFunction %void None %void_func\n" +
2480 "%main_lab = OpLabel\n" +
2481 "%n = OpVariable %_ptr_int Function\n" +
2482 "%m = OpVariable %_ptr_int Function\n" +
2483 "%load_n = OpLoad %int %n\n" +
2484 "%load_m = OpLoad %int %m\n" +
2485 "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
2486 "OpReturn\n" +
2487 "OpFunctionEnd",
2488 2, 0),
2489 // Test case 17: Don't fold n >= m (signed)
2490 InstructionFoldingCase<uint32_t>(
2491 Header() + "%main = OpFunction %void None %void_func\n" +
2492 "%main_lab = OpLabel\n" +
2493 "%n = OpVariable %_ptr_int Function\n" +
2494 "%m = OpVariable %_ptr_int Function\n" +
2495 "%load_n = OpLoad %int %n\n" +
2496 "%load_m = OpLoad %int %m\n" +
2497 "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
2498 "OpReturn\n" +
2499 "OpFunctionEnd",
2500 2, 0),
2501 // Test case 18: Don't fold n || m
2502 InstructionFoldingCase<uint32_t>(
2503 Header() + "%main = OpFunction %void None %void_func\n" +
2504 "%main_lab = OpLabel\n" +
2505 "%n = OpVariable %_ptr_bool Function\n" +
2506 "%m = OpVariable %_ptr_bool Function\n" +
2507 "%load_n = OpLoad %bool %n\n" +
2508 "%load_m = OpLoad %bool %m\n" +
2509 "%2 = OpLogicalOr %bool %load_n %load_m\n" +
2510 "OpReturn\n" +
2511 "OpFunctionEnd",
2512 2, 0),
2513 // Test case 19: Don't fold n && m
2514 InstructionFoldingCase<uint32_t>(
2515 Header() + "%main = OpFunction %void None %void_func\n" +
2516 "%main_lab = OpLabel\n" +
2517 "%n = OpVariable %_ptr_bool Function\n" +
2518 "%m = OpVariable %_ptr_bool Function\n" +
2519 "%load_n = OpLoad %bool %n\n" +
2520 "%load_m = OpLoad %bool %m\n" +
2521 "%2 = OpLogicalAnd %bool %load_n %load_m\n" +
2522 "OpReturn\n" +
2523 "OpFunctionEnd",
2524 2, 0),
2525 // Test case 20: Don't fold n * 3
2526 InstructionFoldingCase<uint32_t>(
2527 Header() + "%main = OpFunction %void None %void_func\n" +
2528 "%main_lab = OpLabel\n" +
2529 "%n = OpVariable %_ptr_int Function\n" +
2530 "%load_n = OpLoad %int %n\n" +
2531 "%2 = OpIMul %int %load_n %int_3\n" +
2532 "OpReturn\n" +
2533 "OpFunctionEnd",
2534 2, 0),
2535 // Test case 21: Don't fold n / 3 (unsigned)
2536 InstructionFoldingCase<uint32_t>(
2537 Header() + "%main = OpFunction %void None %void_func\n" +
2538 "%main_lab = OpLabel\n" +
2539 "%n = OpVariable %_ptr_uint Function\n" +
2540 "%load_n = OpLoad %uint %n\n" +
2541 "%2 = OpUDiv %uint %load_n %uint_3\n" +
2542 "OpReturn\n" +
2543 "OpFunctionEnd",
2544 2, 0),
2545 // Test case 22: Don't fold n / 3 (signed)
2546 InstructionFoldingCase<uint32_t>(
2547 Header() + "%main = OpFunction %void None %void_func\n" +
2548 "%main_lab = OpLabel\n" +
2549 "%n = OpVariable %_ptr_int Function\n" +
2550 "%load_n = OpLoad %int %n\n" +
2551 "%2 = OpSDiv %int %load_n %int_3\n" +
2552 "OpReturn\n" +
2553 "OpFunctionEnd",
2554 2, 0),
2555 // Test case 23: Don't fold n remainder 3
2556 InstructionFoldingCase<uint32_t>(
2557 Header() + "%main = OpFunction %void None %void_func\n" +
2558 "%main_lab = OpLabel\n" +
2559 "%n = OpVariable %_ptr_int Function\n" +
2560 "%load_n = OpLoad %int %n\n" +
2561 "%2 = OpSRem %int %load_n %int_3\n" +
2562 "OpReturn\n" +
2563 "OpFunctionEnd",
2564 2, 0),
2565 // Test case 24: Don't fold n % 3 (signed)
2566 InstructionFoldingCase<uint32_t>(
2567 Header() + "%main = OpFunction %void None %void_func\n" +
2568 "%main_lab = OpLabel\n" +
2569 "%n = OpVariable %_ptr_int Function\n" +
2570 "%load_n = OpLoad %int %n\n" +
2571 "%2 = OpSMod %int %load_n %int_3\n" +
2572 "OpReturn\n" +
2573 "OpFunctionEnd",
2574 2, 0),
2575 // Test case 25: Don't fold n % 3 (unsigned)
2576 InstructionFoldingCase<uint32_t>(
2577 Header() + "%main = OpFunction %void None %void_func\n" +
2578 "%main_lab = OpLabel\n" +
2579 "%n = OpVariable %_ptr_uint Function\n" +
2580 "%load_n = OpLoad %uint %n\n" +
2581 "%2 = OpUMod %int %load_n %int_3\n" +
2582 "OpReturn\n" +
2583 "OpFunctionEnd",
2584 2, 0),
2585 // Test case 26: Don't fold n << 3
2586 InstructionFoldingCase<uint32_t>(
2587 Header() + "%main = OpFunction %void None %void_func\n" +
2588 "%main_lab = OpLabel\n" +
2589 "%n = OpVariable %_ptr_uint Function\n" +
2590 "%load_n = OpLoad %uint %n\n" +
2591 "%2 = OpShiftRightLogical %int %load_n %int_3\n" +
2592 "OpReturn\n" +
2593 "OpFunctionEnd",
2594 2, 0),
2595 // Test case 27: Don't fold n >> 3
2596 InstructionFoldingCase<uint32_t>(
2597 Header() + "%main = OpFunction %void None %void_func\n" +
2598 "%main_lab = OpLabel\n" +
2599 "%n = OpVariable %_ptr_uint Function\n" +
2600 "%load_n = OpLoad %uint %n\n" +
2601 "%2 = OpShiftLeftLogical %int %load_n %int_3\n" +
2602 "OpReturn\n" +
2603 "OpFunctionEnd",
2604 2, 0),
2605 // Test case 28: Don't fold n | 3
2606 InstructionFoldingCase<uint32_t>(
2607 Header() + "%main = OpFunction %void None %void_func\n" +
2608 "%main_lab = OpLabel\n" +
2609 "%n = OpVariable %_ptr_uint Function\n" +
2610 "%load_n = OpLoad %uint %n\n" +
2611 "%2 = OpBitwiseOr %int %load_n %int_3\n" +
2612 "OpReturn\n" +
2613 "OpFunctionEnd",
2614 2, 0),
2615 // Test case 29: Don't fold n & 3
2616 InstructionFoldingCase<uint32_t>(
2617 Header() + "%main = OpFunction %void None %void_func\n" +
2618 "%main_lab = OpLabel\n" +
2619 "%n = OpVariable %_ptr_uint Function\n" +
2620 "%load_n = OpLoad %uint %n\n" +
2621 "%2 = OpBitwiseAnd %uint %load_n %uint_3\n" +
2622 "OpReturn\n" +
2623 "OpFunctionEnd",
2624 2, 0),
2625 // Test case 30: Don't fold n < 3 (unsigned)
2626 InstructionFoldingCase<uint32_t>(
2627 Header() + "%main = OpFunction %void None %void_func\n" +
2628 "%main_lab = OpLabel\n" +
2629 "%n = OpVariable %_ptr_uint Function\n" +
2630 "%load_n = OpLoad %uint %n\n" +
2631 "%2 = OpULessThan %bool %load_n %uint_3\n" +
2632 "OpReturn\n" +
2633 "OpFunctionEnd",
2634 2, 0),
2635 // Test case 31: Don't fold n > 3 (unsigned)
2636 InstructionFoldingCase<uint32_t>(
2637 Header() + "%main = OpFunction %void None %void_func\n" +
2638 "%main_lab = OpLabel\n" +
2639 "%n = OpVariable %_ptr_uint Function\n" +
2640 "%load_n = OpLoad %uint %n\n" +
2641 "%2 = OpUGreaterThan %bool %load_n %uint_3\n" +
2642 "OpReturn\n" +
2643 "OpFunctionEnd",
2644 2, 0),
2645 // Test case 32: Don't fold n <= 3 (unsigned)
2646 InstructionFoldingCase<uint32_t>(
2647 Header() + "%main = OpFunction %void None %void_func\n" +
2648 "%main_lab = OpLabel\n" +
2649 "%n = OpVariable %_ptr_uint Function\n" +
2650 "%load_n = OpLoad %uint %n\n" +
2651 "%2 = OpULessThanEqual %bool %load_n %uint_3\n" +
2652 "OpReturn\n" +
2653 "OpFunctionEnd",
2654 2, 0),
2655 // Test case 33: Don't fold n >= 3 (unsigned)
2656 InstructionFoldingCase<uint32_t>(
2657 Header() + "%main = OpFunction %void None %void_func\n" +
2658 "%main_lab = OpLabel\n" +
2659 "%n = OpVariable %_ptr_uint Function\n" +
2660 "%load_n = OpLoad %uint %n\n" +
2661 "%2 = OpUGreaterThanEqual %bool %load_n %uint_3\n" +
2662 "OpReturn\n" +
2663 "OpFunctionEnd",
2664 2, 0),
2665 // Test case 34: Don't fold n < 3 (signed)
2666 InstructionFoldingCase<uint32_t>(
2667 Header() + "%main = OpFunction %void None %void_func\n" +
2668 "%main_lab = OpLabel\n" +
2669 "%n = OpVariable %_ptr_int Function\n" +
2670 "%load_n = OpLoad %int %n\n" +
2671 "%2 = OpULessThan %bool %load_n %int_3\n" +
2672 "OpReturn\n" +
2673 "OpFunctionEnd",
2674 2, 0),
2675 // Test case 35: Don't fold n > 3 (signed)
2676 InstructionFoldingCase<uint32_t>(
2677 Header() + "%main = OpFunction %void None %void_func\n" +
2678 "%main_lab = OpLabel\n" +
2679 "%n = OpVariable %_ptr_int Function\n" +
2680 "%load_n = OpLoad %int %n\n" +
2681 "%2 = OpUGreaterThan %bool %load_n %int_3\n" +
2682 "OpReturn\n" +
2683 "OpFunctionEnd",
2684 2, 0),
2685 // Test case 36: Don't fold n <= 3 (signed)
2686 InstructionFoldingCase<uint32_t>(
2687 Header() + "%main = OpFunction %void None %void_func\n" +
2688 "%main_lab = OpLabel\n" +
2689 "%n = OpVariable %_ptr_int Function\n" +
2690 "%load_n = OpLoad %int %n\n" +
2691 "%2 = OpULessThanEqual %bool %load_n %int_3\n" +
2692 "OpReturn\n" +
2693 "OpFunctionEnd",
2694 2, 0),
2695 // Test case 37: Don't fold n >= 3 (signed)
2696 InstructionFoldingCase<uint32_t>(
2697 Header() + "%main = OpFunction %void None %void_func\n" +
2698 "%main_lab = OpLabel\n" +
2699 "%n = OpVariable %_ptr_int Function\n" +
2700 "%load_n = OpLoad %int %n\n" +
2701 "%2 = OpUGreaterThanEqual %bool %load_n %int_3\n" +
2702 "OpReturn\n" +
2703 "OpFunctionEnd",
2704 2, 0),
2705 // Test case 38: Don't fold 2 + 3 (long), bad length
2706 InstructionFoldingCase<uint32_t>(
2707 Header() + "%main = OpFunction %void None %void_func\n" +
2708 "%main_lab = OpLabel\n" +
2709 "%2 = OpIAdd %long %long_2 %long_3\n" +
2710 "OpReturn\n" +
2711 "OpFunctionEnd",
2712 2, 0),
2713 // Test case 39: Don't fold 2 + 3 (short), bad length
2714 InstructionFoldingCase<uint32_t>(
2715 Header() + "%main = OpFunction %void None %void_func\n" +
2716 "%main_lab = OpLabel\n" +
2717 "%2 = OpIAdd %short %short_2 %short_3\n" +
2718 "OpReturn\n" +
2719 "OpFunctionEnd",
2720 2, 0),
2721 // Test case 40: fold 1*n
2722 InstructionFoldingCase<uint32_t>(
2723 Header() + "%main = OpFunction %void None %void_func\n" +
2724 "%main_lab = OpLabel\n" +
2725 "%n = OpVariable %_ptr_int Function\n" +
2726 "%3 = OpLoad %int %n\n" +
2727 "%2 = OpIMul %int %int_1 %3\n" +
2728 "OpReturn\n" +
2729 "OpFunctionEnd",
2730 2, 3),
2731 // Test case 41: fold n*1
2732 InstructionFoldingCase<uint32_t>(
2733 Header() + "%main = OpFunction %void None %void_func\n" +
2734 "%main_lab = OpLabel\n" +
2735 "%n = OpVariable %_ptr_int Function\n" +
2736 "%3 = OpLoad %int %n\n" +
2737 "%2 = OpIMul %int %3 %int_1\n" +
2738 "OpReturn\n" +
2739 "OpFunctionEnd",
2740 2, 3)
2741 ));
2742
2743 INSTANTIATE_TEST_CASE_P(CompositeExtractFoldingTest, GeneralInstructionFoldingTest,
2744 ::testing::Values(
2745 // Test case 0: fold Insert feeding extract
2746 InstructionFoldingCase<uint32_t>(
2747 Header() + "%main = OpFunction %void None %void_func\n" +
2748 "%main_lab = OpLabel\n" +
2749 "%n = OpVariable %_ptr_int Function\n" +
2750 "%2 = OpLoad %int %n\n" +
2751 "%3 = OpCompositeInsert %v4int %2 %v4int_0_0_0_0 0\n" +
2752 "%4 = OpCompositeInsert %v4int %int_1 %3 1\n" +
2753 "%5 = OpCompositeInsert %v4int %int_1 %4 2\n" +
2754 "%6 = OpCompositeInsert %v4int %int_1 %5 3\n" +
2755 "%7 = OpCompositeExtract %int %6 0\n" +
2756 "OpReturn\n" +
2757 "OpFunctionEnd",
2758 7, 2),
2759 // Test case 1: fold Composite construct feeding extract (position 0)
2760 InstructionFoldingCase<uint32_t>(
2761 Header() + "%main = OpFunction %void None %void_func\n" +
2762 "%main_lab = OpLabel\n" +
2763 "%n = OpVariable %_ptr_int Function\n" +
2764 "%2 = OpLoad %int %n\n" +
2765 "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %int_0\n" +
2766 "%4 = OpCompositeExtract %int %3 0\n" +
2767 "OpReturn\n" +
2768 "OpFunctionEnd",
2769 4, 2),
2770 // Test case 2: fold Composite construct feeding extract (position 3)
2771 InstructionFoldingCase<uint32_t>(
2772 Header() + "%main = OpFunction %void None %void_func\n" +
2773 "%main_lab = OpLabel\n" +
2774 "%n = OpVariable %_ptr_int Function\n" +
2775 "%2 = OpLoad %int %n\n" +
2776 "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %100\n" +
2777 "%4 = OpCompositeExtract %int %3 3\n" +
2778 "OpReturn\n" +
2779 "OpFunctionEnd",
2780 4, INT_0_ID),
2781 // Test case 3: fold Composite construct with vectors feeding extract (scalar element)
2782 InstructionFoldingCase<uint32_t>(
2783 Header() + "%main = OpFunction %void None %void_func\n" +
2784 "%main_lab = OpLabel\n" +
2785 "%n = OpVariable %_ptr_int Function\n" +
2786 "%2 = OpLoad %int %n\n" +
2787 "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
2788 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
2789 "%5 = OpCompositeExtract %int %4 3\n" +
2790 "OpReturn\n" +
2791 "OpFunctionEnd",
2792 5, INT_0_ID),
2793 // Test case 4: fold Composite construct with vectors feeding extract (start of vector element)
2794 InstructionFoldingCase<uint32_t>(
2795 Header() + "%main = OpFunction %void None %void_func\n" +
2796 "%main_lab = OpLabel\n" +
2797 "%n = OpVariable %_ptr_int Function\n" +
2798 "%2 = OpLoad %int %n\n" +
2799 "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
2800 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
2801 "%5 = OpCompositeExtract %int %4 0\n" +
2802 "OpReturn\n" +
2803 "OpFunctionEnd",
2804 5, 2),
2805 // Test case 5: fold Composite construct with vectors feeding extract (middle of vector element)
2806 InstructionFoldingCase<uint32_t>(
2807 Header() + "%main = OpFunction %void None %void_func\n" +
2808 "%main_lab = OpLabel\n" +
2809 "%n = OpVariable %_ptr_int Function\n" +
2810 "%2 = OpLoad %int %n\n" +
2811 "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
2812 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
2813 "%5 = OpCompositeExtract %int %4 1\n" +
2814 "OpReturn\n" +
2815 "OpFunctionEnd",
2816 5, 2),
2817 // Test case 6: fold Composite construct with multiple indices.
2818 InstructionFoldingCase<uint32_t>(
2819 Header() + "%main = OpFunction %void None %void_func\n" +
2820 "%main_lab = OpLabel\n" +
2821 "%n = OpVariable %_ptr_int Function\n" +
2822 "%2 = OpLoad %int %n\n" +
2823 "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
2824 "%4 = OpCompositeConstruct %struct_v2int_int_int %3 %int_0 %100\n" +
2825 "%5 = OpCompositeExtract %int %4 0 1\n" +
2826 "OpReturn\n" +
2827 "OpFunctionEnd",
2828 5, 2),
2829 // Test case 7: fold constant extract.
2830 InstructionFoldingCase<uint32_t>(
2831 Header() + "%main = OpFunction %void None %void_func\n" +
2832 "%main_lab = OpLabel\n" +
2833 "%2 = OpCompositeExtract %int %102 1\n" +
2834 "OpReturn\n" +
2835 "OpFunctionEnd",
2836 2, INT_7_ID),
2837 // Test case 8: constant struct has OpUndef
2838 InstructionFoldingCase<uint32_t>(
2839 Header() + "%main = OpFunction %void None %void_func\n" +
2840 "%main_lab = OpLabel\n" +
2841 "%2 = OpCompositeExtract %int %struct_undef_0_0 0 1\n" +
2842 "OpReturn\n" +
2843 "OpFunctionEnd",
2844 2, 0),
2845 // Test case 9: Extracting a member of element inserted via Insert
2846 InstructionFoldingCase<uint32_t>(
2847 Header() + "%main = OpFunction %void None %void_func\n" +
2848 "%main_lab = OpLabel\n" +
2849 "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
2850 "%2 = OpLoad %struct_v2int_int_int %n\n" +
2851 "%3 = OpCompositeInsert %struct_v2int_int_int %102 %2 0\n" +
2852 "%4 = OpCompositeExtract %int %3 0 1\n" +
2853 "OpReturn\n" +
2854 "OpFunctionEnd",
2855 4, 103),
2856 // Test case 10: Extracting a element that is partially changed by Insert. (Don't fold)
2857 InstructionFoldingCase<uint32_t>(
2858 Header() + "%main = OpFunction %void None %void_func\n" +
2859 "%main_lab = OpLabel\n" +
2860 "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
2861 "%2 = OpLoad %struct_v2int_int_int %n\n" +
2862 "%3 = OpCompositeInsert %struct_v2int_int_int %int_0 %2 0 1\n" +
2863 "%4 = OpCompositeExtract %v2int %3 0\n" +
2864 "OpReturn\n" +
2865 "OpFunctionEnd",
2866 4, 0),
2867 // Test case 11: Extracting from result of vector shuffle (first input)
2868 InstructionFoldingCase<uint32_t>(
2869 Header() + "%main = OpFunction %void None %void_func\n" +
2870 "%main_lab = OpLabel\n" +
2871 "%n = OpVariable %_ptr_v2int Function\n" +
2872 "%2 = OpLoad %v2int %n\n" +
2873 "%3 = OpVectorShuffle %v2int %102 %2 3 0\n" +
2874 "%4 = OpCompositeExtract %int %3 1\n" +
2875 "OpReturn\n" +
2876 "OpFunctionEnd",
2877 4, INT_7_ID),
2878 // Test case 12: Extracting from result of vector shuffle (second input)
2879 InstructionFoldingCase<uint32_t>(
2880 Header() + "%main = OpFunction %void None %void_func\n" +
2881 "%main_lab = OpLabel\n" +
2882 "%n = OpVariable %_ptr_v2int Function\n" +
2883 "%2 = OpLoad %v2int %n\n" +
2884 "%3 = OpVectorShuffle %v2int %2 %102 2 0\n" +
2885 "%4 = OpCompositeExtract %int %3 0\n" +
2886 "OpReturn\n" +
2887 "OpFunctionEnd",
2888 4, INT_7_ID)
2889 ));
2890
2891 INSTANTIATE_TEST_CASE_P(CompositeConstructFoldingTest, GeneralInstructionFoldingTest,
2892 ::testing::Values(
2893 // Test case 0: fold Extracts feeding construct
2894 InstructionFoldingCase<uint32_t>(
2895 Header() + "%main = OpFunction %void None %void_func\n" +
2896 "%main_lab = OpLabel\n" +
2897 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
2898 "%3 = OpCompositeExtract %int %2 0\n" +
2899 "%4 = OpCompositeExtract %int %2 1\n" +
2900 "%5 = OpCompositeExtract %int %2 2\n" +
2901 "%6 = OpCompositeExtract %int %2 3\n" +
2902 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
2903 "OpReturn\n" +
2904 "OpFunctionEnd",
2905 7, 2),
2906 // Test case 1: Don't fold Extracts feeding construct (Different source)
2907 InstructionFoldingCase<uint32_t>(
2908 Header() + "%main = OpFunction %void None %void_func\n" +
2909 "%main_lab = OpLabel\n" +
2910 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
2911 "%3 = OpCompositeExtract %int %2 0\n" +
2912 "%4 = OpCompositeExtract %int %2 1\n" +
2913 "%5 = OpCompositeExtract %int %2 2\n" +
2914 "%6 = OpCompositeExtract %int %v4int_0_0_0_0 3\n" +
2915 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
2916 "OpReturn\n" +
2917 "OpFunctionEnd",
2918 7, 0),
2919 // Test case 2: Don't fold Extracts feeding construct (bad indices)
2920 InstructionFoldingCase<uint32_t>(
2921 Header() + "%main = OpFunction %void None %void_func\n" +
2922 "%main_lab = OpLabel\n" +
2923 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
2924 "%3 = OpCompositeExtract %int %2 0\n" +
2925 "%4 = OpCompositeExtract %int %2 0\n" +
2926 "%5 = OpCompositeExtract %int %2 2\n" +
2927 "%6 = OpCompositeExtract %int %2 3\n" +
2928 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
2929 "OpReturn\n" +
2930 "OpFunctionEnd",
2931 7, 0),
2932 // Test case 3: Don't fold Extracts feeding construct (different type)
2933 InstructionFoldingCase<uint32_t>(
2934 Header() + "%main = OpFunction %void None %void_func\n" +
2935 "%main_lab = OpLabel\n" +
2936 "%2 = OpCopyObject %struct_v2int_int_int %struct_v2int_int_int_null\n" +
2937 "%3 = OpCompositeExtract %v2int %2 0\n" +
2938 "%4 = OpCompositeExtract %int %2 1\n" +
2939 "%5 = OpCompositeExtract %int %2 2\n" +
2940 "%7 = OpCompositeConstruct %v4int %3 %4 %5\n" +
2941 "OpReturn\n" +
2942 "OpFunctionEnd",
2943 7, 0),
2944 // Test case 4: Fold construct with constants to constant.
2945 InstructionFoldingCase<uint32_t>(
2946 Header() + "%main = OpFunction %void None %void_func\n" +
2947 "%main_lab = OpLabel\n" +
2948 "%2 = OpCompositeConstruct %v2int %103 %103\n" +
2949 "OpReturn\n" +
2950 "OpFunctionEnd",
2951 2, VEC2_0_ID)
2952 ));
2953
2954 INSTANTIATE_TEST_CASE_P(PhiFoldingTest, GeneralInstructionFoldingTest,
2955 ::testing::Values(
2956 // Test case 0: Fold phi with the same values for all edges.
2957 InstructionFoldingCase<uint32_t>(
2958 Header() + "%main = OpFunction %void None %void_func\n" +
2959 "%main_lab = OpLabel\n" +
2960 " OpBranchConditional %true %l1 %l2\n" +
2961 "%l1 = OpLabel\n" +
2962 " OpBranch %merge_lab\n" +
2963 "%l2 = OpLabel\n" +
2964 " OpBranch %merge_lab\n" +
2965 "%merge_lab = OpLabel\n" +
2966 "%2 = OpPhi %int %100 %l1 %100 %l2\n" +
2967 "OpReturn\n" +
2968 "OpFunctionEnd",
2969 2, INT_0_ID),
2970 // Test case 1: Fold phi in pass through loop.
2971 InstructionFoldingCase<uint32_t>(
2972 Header() + "%main = OpFunction %void None %void_func\n" +
2973 "%main_lab = OpLabel\n" +
2974 " OpBranch %l1\n" +
2975 "%l1 = OpLabel\n" +
2976 "%2 = OpPhi %int %100 %main_lab %2 %l1\n" +
2977 " OpBranchConditional %true %l1 %merge_lab\n" +
2978 "%merge_lab = OpLabel\n" +
2979 "OpReturn\n" +
2980 "OpFunctionEnd",
2981 2, INT_0_ID),
2982 // Test case 2: Don't Fold phi because of different values.
2983 InstructionFoldingCase<uint32_t>(
2984 Header() + "%main = OpFunction %void None %void_func\n" +
2985 "%main_lab = OpLabel\n" +
2986 " OpBranch %l1\n" +
2987 "%l1 = OpLabel\n" +
2988 "%2 = OpPhi %int %int_0 %main_lab %int_3 %l1\n" +
2989 " OpBranchConditional %true %l1 %merge_lab\n" +
2990 "%merge_lab = OpLabel\n" +
2991 "OpReturn\n" +
2992 "OpFunctionEnd",
2993 2, 0)
2994 ));
2995
2996 INSTANTIATE_TEST_CASE_P(FloatRedundantFoldingTest, GeneralInstructionFoldingTest,
2997 ::testing::Values(
2998 // Test case 0: Don't fold n + 1.0
2999 InstructionFoldingCase<uint32_t>(
3000 Header() + "%main = OpFunction %void None %void_func\n" +
3001 "%main_lab = OpLabel\n" +
3002 "%n = OpVariable %_ptr_float Function\n" +
3003 "%3 = OpLoad %float %n\n" +
3004 "%2 = OpFAdd %float %3 %float_2\n" +
3005 "OpReturn\n" +
3006 "OpFunctionEnd",
3007 2, 0),
3008 // Test case 1: Don't fold n - 1.0
3009 InstructionFoldingCase<uint32_t>(
3010 Header() + "%main = OpFunction %void None %void_func\n" +
3011 "%main_lab = OpLabel\n" +
3012 "%n = OpVariable %_ptr_float Function\n" +
3013 "%3 = OpLoad %float %n\n" +
3014 "%2 = OpFSub %float %3 %float_2\n" +
3015 "OpReturn\n" +
3016 "OpFunctionEnd",
3017 2, 0),
3018 // Test case 2: Don't fold n * 2.0
3019 InstructionFoldingCase<uint32_t>(
3020 Header() + "%main = OpFunction %void None %void_func\n" +
3021 "%main_lab = OpLabel\n" +
3022 "%n = OpVariable %_ptr_float Function\n" +
3023 "%3 = OpLoad %float %n\n" +
3024 "%2 = OpFMul %float %3 %float_2\n" +
3025 "OpReturn\n" +
3026 "OpFunctionEnd",
3027 2, 0),
3028 // Test case 3: Fold n + 0.0
3029 InstructionFoldingCase<uint32_t>(
3030 Header() + "%main = OpFunction %void None %void_func\n" +
3031 "%main_lab = OpLabel\n" +
3032 "%n = OpVariable %_ptr_float Function\n" +
3033 "%3 = OpLoad %float %n\n" +
3034 "%2 = OpFAdd %float %3 %float_0\n" +
3035 "OpReturn\n" +
3036 "OpFunctionEnd",
3037 2, 3),
3038 // Test case 4: Fold 0.0 + n
3039 InstructionFoldingCase<uint32_t>(
3040 Header() + "%main = OpFunction %void None %void_func\n" +
3041 "%main_lab = OpLabel\n" +
3042 "%n = OpVariable %_ptr_float Function\n" +
3043 "%3 = OpLoad %float %n\n" +
3044 "%2 = OpFAdd %float %float_0 %3\n" +
3045 "OpReturn\n" +
3046 "OpFunctionEnd",
3047 2, 3),
3048 // Test case 5: Fold n - 0.0
3049 InstructionFoldingCase<uint32_t>(
3050 Header() + "%main = OpFunction %void None %void_func\n" +
3051 "%main_lab = OpLabel\n" +
3052 "%n = OpVariable %_ptr_float Function\n" +
3053 "%3 = OpLoad %float %n\n" +
3054 "%2 = OpFSub %float %3 %float_0\n" +
3055 "OpReturn\n" +
3056 "OpFunctionEnd",
3057 2, 3),
3058 // Test case 6: Fold n * 1.0
3059 InstructionFoldingCase<uint32_t>(
3060 Header() + "%main = OpFunction %void None %void_func\n" +
3061 "%main_lab = OpLabel\n" +
3062 "%n = OpVariable %_ptr_float Function\n" +
3063 "%3 = OpLoad %float %n\n" +
3064 "%2 = OpFMul %float %3 %float_1\n" +
3065 "OpReturn\n" +
3066 "OpFunctionEnd",
3067 2, 3),
3068 // Test case 7: Fold 1.0 * n
3069 InstructionFoldingCase<uint32_t>(
3070 Header() + "%main = OpFunction %void None %void_func\n" +
3071 "%main_lab = OpLabel\n" +
3072 "%n = OpVariable %_ptr_float Function\n" +
3073 "%3 = OpLoad %float %n\n" +
3074 "%2 = OpFMul %float %float_1 %3\n" +
3075 "OpReturn\n" +
3076 "OpFunctionEnd",
3077 2, 3),
3078 // Test case 8: Fold n / 1.0
3079 InstructionFoldingCase<uint32_t>(
3080 Header() + "%main = OpFunction %void None %void_func\n" +
3081 "%main_lab = OpLabel\n" +
3082 "%n = OpVariable %_ptr_float Function\n" +
3083 "%3 = OpLoad %float %n\n" +
3084 "%2 = OpFDiv %float %3 %float_1\n" +
3085 "OpReturn\n" +
3086 "OpFunctionEnd",
3087 2, 3),
3088 // Test case 9: Fold n * 0.0
3089 InstructionFoldingCase<uint32_t>(
3090 Header() + "%main = OpFunction %void None %void_func\n" +
3091 "%main_lab = OpLabel\n" +
3092 "%n = OpVariable %_ptr_float Function\n" +
3093 "%3 = OpLoad %float %n\n" +
3094 "%2 = OpFMul %float %3 %104\n" +
3095 "OpReturn\n" +
3096 "OpFunctionEnd",
3097 2, FLOAT_0_ID),
3098 // Test case 10: Fold 0.0 * n
3099 InstructionFoldingCase<uint32_t>(
3100 Header() + "%main = OpFunction %void None %void_func\n" +
3101 "%main_lab = OpLabel\n" +
3102 "%n = OpVariable %_ptr_float Function\n" +
3103 "%3 = OpLoad %float %n\n" +
3104 "%2 = OpFMul %float %104 %3\n" +
3105 "OpReturn\n" +
3106 "OpFunctionEnd",
3107 2, FLOAT_0_ID),
3108 // Test case 11: Fold 0.0 / n
3109 InstructionFoldingCase<uint32_t>(
3110 Header() + "%main = OpFunction %void None %void_func\n" +
3111 "%main_lab = OpLabel\n" +
3112 "%n = OpVariable %_ptr_float Function\n" +
3113 "%3 = OpLoad %float %n\n" +
3114 "%2 = OpFDiv %float %104 %3\n" +
3115 "OpReturn\n" +
3116 "OpFunctionEnd",
3117 2, FLOAT_0_ID),
3118 // Test case 12: Don't fold mix(a, b, 2.0)
3119 InstructionFoldingCase<uint32_t>(
3120 Header() + "%main = OpFunction %void None %void_func\n" +
3121 "%main_lab = OpLabel\n" +
3122 "%a = OpVariable %_ptr_float Function\n" +
3123 "%b = OpVariable %_ptr_float Function\n" +
3124 "%3 = OpLoad %float %a\n" +
3125 "%4 = OpLoad %float %b\n" +
3126 "%2 = OpExtInst %float %1 FMix %3 %4 %float_2\n" +
3127 "OpReturn\n" +
3128 "OpFunctionEnd",
3129 2, 0),
3130 // Test case 13: Fold mix(a, b, 0.0)
3131 InstructionFoldingCase<uint32_t>(
3132 Header() + "%main = OpFunction %void None %void_func\n" +
3133 "%main_lab = OpLabel\n" +
3134 "%a = OpVariable %_ptr_float Function\n" +
3135 "%b = OpVariable %_ptr_float Function\n" +
3136 "%3 = OpLoad %float %a\n" +
3137 "%4 = OpLoad %float %b\n" +
3138 "%2 = OpExtInst %float %1 FMix %3 %4 %float_0\n" +
3139 "OpReturn\n" +
3140 "OpFunctionEnd",
3141 2, 3),
3142 // Test case 14: Fold mix(a, b, 1.0)
3143 InstructionFoldingCase<uint32_t>(
3144 Header() + "%main = OpFunction %void None %void_func\n" +
3145 "%main_lab = OpLabel\n" +
3146 "%a = OpVariable %_ptr_float Function\n" +
3147 "%b = OpVariable %_ptr_float Function\n" +
3148 "%3 = OpLoad %float %a\n" +
3149 "%4 = OpLoad %float %b\n" +
3150 "%2 = OpExtInst %float %1 FMix %3 %4 %float_1\n" +
3151 "OpReturn\n" +
3152 "OpFunctionEnd",
3153 2, 4),
3154 // Test case 15: Fold vector fadd with null
3155 InstructionFoldingCase<uint32_t>(
3156 Header() + "%main = OpFunction %void None %void_func\n" +
3157 "%main_lab = OpLabel\n" +
3158 "%a = OpVariable %_ptr_v2float Function\n" +
3159 "%2 = OpLoad %v2float %a\n" +
3160 "%3 = OpFAdd %v2float %2 %v2float_null\n" +
3161 "OpReturn\n" +
3162 "OpFunctionEnd",
3163 3, 2),
3164 // Test case 16: Fold vector fadd with null
3165 InstructionFoldingCase<uint32_t>(
3166 Header() + "%main = OpFunction %void None %void_func\n" +
3167 "%main_lab = OpLabel\n" +
3168 "%a = OpVariable %_ptr_v2float Function\n" +
3169 "%2 = OpLoad %v2float %a\n" +
3170 "%3 = OpFAdd %v2float %v2float_null %2\n" +
3171 "OpReturn\n" +
3172 "OpFunctionEnd",
3173 3, 2),
3174 // Test case 15: Fold vector fsub with null
3175 InstructionFoldingCase<uint32_t>(
3176 Header() + "%main = OpFunction %void None %void_func\n" +
3177 "%main_lab = OpLabel\n" +
3178 "%a = OpVariable %_ptr_v2float Function\n" +
3179 "%2 = OpLoad %v2float %a\n" +
3180 "%3 = OpFSub %v2float %2 %v2float_null\n" +
3181 "OpReturn\n" +
3182 "OpFunctionEnd",
3183 3, 2),
3184 // Test case 16: Fold 0.0(half) * n
3185 InstructionFoldingCase<uint32_t>(
3186 Header() + "%main = OpFunction %void None %void_func\n" +
3187 "%main_lab = OpLabel\n" +
3188 "%n = OpVariable %_ptr_half Function\n" +
3189 "%3 = OpLoad %half %n\n" +
3190 "%2 = OpFMul %half %108 %3\n" +
3191 "OpReturn\n" +
3192 "OpFunctionEnd",
3193 2, HALF_0_ID),
3194 // Test case 17: Don't fold 1.0(half) * n
3195 InstructionFoldingCase<uint32_t>(
3196 Header() + "%main = OpFunction %void None %void_func\n" +
3197 "%main_lab = OpLabel\n" +
3198 "%n = OpVariable %_ptr_half Function\n" +
3199 "%3 = OpLoad %half %n\n" +
3200 "%2 = OpFMul %half %half_1 %3\n" +
3201 "OpReturn\n" +
3202 "OpFunctionEnd",
3203 2, 0),
3204 // Test case 18: Don't fold 1.0 * 1.0 (half)
3205 InstructionFoldingCase<uint32_t>(
3206 Header() + "%main = OpFunction %void None %void_func\n" +
3207 "%main_lab = OpLabel\n" +
3208 "%2 = OpFMul %half %half_1 %half_1\n" +
3209 "OpReturn\n" +
3210 "OpFunctionEnd",
3211 2, 0)
3212 ));
3213
3214 INSTANTIATE_TEST_CASE_P(DoubleRedundantFoldingTest, GeneralInstructionFoldingTest,
3215 ::testing::Values(
3216 // Test case 0: Don't fold n + 1.0
3217 InstructionFoldingCase<uint32_t>(
3218 Header() + "%main = OpFunction %void None %void_func\n" +
3219 "%main_lab = OpLabel\n" +
3220 "%n = OpVariable %_ptr_double Function\n" +
3221 "%3 = OpLoad %double %n\n" +
3222 "%2 = OpFAdd %double %3 %double_2\n" +
3223 "OpReturn\n" +
3224 "OpFunctionEnd",
3225 2, 0),
3226 // Test case 1: Don't fold n - 1.0
3227 InstructionFoldingCase<uint32_t>(
3228 Header() + "%main = OpFunction %void None %void_func\n" +
3229 "%main_lab = OpLabel\n" +
3230 "%n = OpVariable %_ptr_double Function\n" +
3231 "%3 = OpLoad %double %n\n" +
3232 "%2 = OpFSub %double %3 %double_2\n" +
3233 "OpReturn\n" +
3234 "OpFunctionEnd",
3235 2, 0),
3236 // Test case 2: Don't fold n * 2.0
3237 InstructionFoldingCase<uint32_t>(
3238 Header() + "%main = OpFunction %void None %void_func\n" +
3239 "%main_lab = OpLabel\n" +
3240 "%n = OpVariable %_ptr_double Function\n" +
3241 "%3 = OpLoad %double %n\n" +
3242 "%2 = OpFMul %double %3 %double_2\n" +
3243 "OpReturn\n" +
3244 "OpFunctionEnd",
3245 2, 0),
3246 // Test case 3: Fold n + 0.0
3247 InstructionFoldingCase<uint32_t>(
3248 Header() + "%main = OpFunction %void None %void_func\n" +
3249 "%main_lab = OpLabel\n" +
3250 "%n = OpVariable %_ptr_double Function\n" +
3251 "%3 = OpLoad %double %n\n" +
3252 "%2 = OpFAdd %double %3 %double_0\n" +
3253 "OpReturn\n" +
3254 "OpFunctionEnd",
3255 2, 3),
3256 // Test case 4: Fold 0.0 + n
3257 InstructionFoldingCase<uint32_t>(
3258 Header() + "%main = OpFunction %void None %void_func\n" +
3259 "%main_lab = OpLabel\n" +
3260 "%n = OpVariable %_ptr_double Function\n" +
3261 "%3 = OpLoad %double %n\n" +
3262 "%2 = OpFAdd %double %double_0 %3\n" +
3263 "OpReturn\n" +
3264 "OpFunctionEnd",
3265 2, 3),
3266 // Test case 5: Fold n - 0.0
3267 InstructionFoldingCase<uint32_t>(
3268 Header() + "%main = OpFunction %void None %void_func\n" +
3269 "%main_lab = OpLabel\n" +
3270 "%n = OpVariable %_ptr_double Function\n" +
3271 "%3 = OpLoad %double %n\n" +
3272 "%2 = OpFSub %double %3 %double_0\n" +
3273 "OpReturn\n" +
3274 "OpFunctionEnd",
3275 2, 3),
3276 // Test case 6: Fold n * 1.0
3277 InstructionFoldingCase<uint32_t>(
3278 Header() + "%main = OpFunction %void None %void_func\n" +
3279 "%main_lab = OpLabel\n" +
3280 "%n = OpVariable %_ptr_double Function\n" +
3281 "%3 = OpLoad %double %n\n" +
3282 "%2 = OpFMul %double %3 %double_1\n" +
3283 "OpReturn\n" +
3284 "OpFunctionEnd",
3285 2, 3),
3286 // Test case 7: Fold 1.0 * n
3287 InstructionFoldingCase<uint32_t>(
3288 Header() + "%main = OpFunction %void None %void_func\n" +
3289 "%main_lab = OpLabel\n" +
3290 "%n = OpVariable %_ptr_double Function\n" +
3291 "%3 = OpLoad %double %n\n" +
3292 "%2 = OpFMul %double %double_1 %3\n" +
3293 "OpReturn\n" +
3294 "OpFunctionEnd",
3295 2, 3),
3296 // Test case 8: Fold n / 1.0
3297 InstructionFoldingCase<uint32_t>(
3298 Header() + "%main = OpFunction %void None %void_func\n" +
3299 "%main_lab = OpLabel\n" +
3300 "%n = OpVariable %_ptr_double Function\n" +
3301 "%3 = OpLoad %double %n\n" +
3302 "%2 = OpFDiv %double %3 %double_1\n" +
3303 "OpReturn\n" +
3304 "OpFunctionEnd",
3305 2, 3),
3306 // Test case 9: Fold n * 0.0
3307 InstructionFoldingCase<uint32_t>(
3308 Header() + "%main = OpFunction %void None %void_func\n" +
3309 "%main_lab = OpLabel\n" +
3310 "%n = OpVariable %_ptr_double Function\n" +
3311 "%3 = OpLoad %double %n\n" +
3312 "%2 = OpFMul %double %3 %105\n" +
3313 "OpReturn\n" +
3314 "OpFunctionEnd",
3315 2, DOUBLE_0_ID),
3316 // Test case 10: Fold 0.0 * n
3317 InstructionFoldingCase<uint32_t>(
3318 Header() + "%main = OpFunction %void None %void_func\n" +
3319 "%main_lab = OpLabel\n" +
3320 "%n = OpVariable %_ptr_double Function\n" +
3321 "%3 = OpLoad %double %n\n" +
3322 "%2 = OpFMul %double %105 %3\n" +
3323 "OpReturn\n" +
3324 "OpFunctionEnd",
3325 2, DOUBLE_0_ID),
3326 // Test case 11: Fold 0.0 / n
3327 InstructionFoldingCase<uint32_t>(
3328 Header() + "%main = OpFunction %void None %void_func\n" +
3329 "%main_lab = OpLabel\n" +
3330 "%n = OpVariable %_ptr_double Function\n" +
3331 "%3 = OpLoad %double %n\n" +
3332 "%2 = OpFDiv %double %105 %3\n" +
3333 "OpReturn\n" +
3334 "OpFunctionEnd",
3335 2, DOUBLE_0_ID),
3336 // Test case 12: Don't fold mix(a, b, 2.0)
3337 InstructionFoldingCase<uint32_t>(
3338 Header() + "%main = OpFunction %void None %void_func\n" +
3339 "%main_lab = OpLabel\n" +
3340 "%a = OpVariable %_ptr_double Function\n" +
3341 "%b = OpVariable %_ptr_double Function\n" +
3342 "%3 = OpLoad %double %a\n" +
3343 "%4 = OpLoad %double %b\n" +
3344 "%2 = OpExtInst %double %1 FMix %3 %4 %double_2\n" +
3345 "OpReturn\n" +
3346 "OpFunctionEnd",
3347 2, 0),
3348 // Test case 13: Fold mix(a, b, 0.0)
3349 InstructionFoldingCase<uint32_t>(
3350 Header() + "%main = OpFunction %void None %void_func\n" +
3351 "%main_lab = OpLabel\n" +
3352 "%a = OpVariable %_ptr_double Function\n" +
3353 "%b = OpVariable %_ptr_double Function\n" +
3354 "%3 = OpLoad %double %a\n" +
3355 "%4 = OpLoad %double %b\n" +
3356 "%2 = OpExtInst %double %1 FMix %3 %4 %double_0\n" +
3357 "OpReturn\n" +
3358 "OpFunctionEnd",
3359 2, 3),
3360 // Test case 14: Fold mix(a, b, 1.0)
3361 InstructionFoldingCase<uint32_t>(
3362 Header() + "%main = OpFunction %void None %void_func\n" +
3363 "%main_lab = OpLabel\n" +
3364 "%a = OpVariable %_ptr_double Function\n" +
3365 "%b = OpVariable %_ptr_double Function\n" +
3366 "%3 = OpLoad %double %a\n" +
3367 "%4 = OpLoad %double %b\n" +
3368 "%2 = OpExtInst %double %1 FMix %3 %4 %double_1\n" +
3369 "OpReturn\n" +
3370 "OpFunctionEnd",
3371 2, 4)
3372 ));
3373
3374 INSTANTIATE_TEST_CASE_P(FloatVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
3375 ::testing::Values(
3376 // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
3377 InstructionFoldingCase<uint32_t>(
3378 Header() + "%main = OpFunction %void None %void_func\n" +
3379 "%main_lab = OpLabel\n" +
3380 "%n = OpVariable %_ptr_v4float Function\n" +
3381 "%3 = OpLoad %v4float %n\n" +
3382 "%2 = OpFMul %v4float %3 %v4float_0_0_0_1\n" +
3383 "OpReturn\n" +
3384 "OpFunctionEnd",
3385 2, 0),
3386 // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
3387 InstructionFoldingCase<uint32_t>(
3388 Header() + "%main = OpFunction %void None %void_func\n" +
3389 "%main_lab = OpLabel\n" +
3390 "%n = OpVariable %_ptr_v4float Function\n" +
3391 "%3 = OpLoad %v4float %n\n" +
3392 "%2 = OpFMul %v4float %3 %106\n" +
3393 "OpReturn\n" +
3394 "OpFunctionEnd",
3395 2, VEC4_0_ID),
3396 // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
3397 InstructionFoldingCase<uint32_t>(
3398 Header() + "%main = OpFunction %void None %void_func\n" +
3399 "%main_lab = OpLabel\n" +
3400 "%n = OpVariable %_ptr_v4float Function\n" +
3401 "%3 = OpLoad %v4float %n\n" +
3402 "%2 = OpFMul %v4float %3 %v4float_1_1_1_1\n" +
3403 "OpReturn\n" +
3404 "OpFunctionEnd",
3405 2, 3)
3406 ));
3407
3408 INSTANTIATE_TEST_CASE_P(DoubleVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
3409 ::testing::Values(
3410 // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
3411 InstructionFoldingCase<uint32_t>(
3412 Header() + "%main = OpFunction %void None %void_func\n" +
3413 "%main_lab = OpLabel\n" +
3414 "%n = OpVariable %_ptr_v4double Function\n" +
3415 "%3 = OpLoad %v4double %n\n" +
3416 "%2 = OpFMul %v4double %3 %v4double_0_0_0_1\n" +
3417 "OpReturn\n" +
3418 "OpFunctionEnd",
3419 2, 0),
3420 // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
3421 InstructionFoldingCase<uint32_t>(
3422 Header() + "%main = OpFunction %void None %void_func\n" +
3423 "%main_lab = OpLabel\n" +
3424 "%n = OpVariable %_ptr_v4double Function\n" +
3425 "%3 = OpLoad %v4double %n\n" +
3426 "%2 = OpFMul %v4double %3 %106\n" +
3427 "OpReturn\n" +
3428 "OpFunctionEnd",
3429 2, DVEC4_0_ID),
3430 // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
3431 InstructionFoldingCase<uint32_t>(
3432 Header() + "%main = OpFunction %void None %void_func\n" +
3433 "%main_lab = OpLabel\n" +
3434 "%n = OpVariable %_ptr_v4double Function\n" +
3435 "%3 = OpLoad %v4double %n\n" +
3436 "%2 = OpFMul %v4double %3 %v4double_1_1_1_1\n" +
3437 "OpReturn\n" +
3438 "OpFunctionEnd",
3439 2, 3)
3440 ));
3441
3442 INSTANTIATE_TEST_CASE_P(IntegerRedundantFoldingTest, GeneralInstructionFoldingTest,
3443 ::testing::Values(
3444 // Test case 0: Don't fold n + 1
3445 InstructionFoldingCase<uint32_t>(
3446 Header() + "%main = OpFunction %void None %void_func\n" +
3447 "%main_lab = OpLabel\n" +
3448 "%n = OpVariable %_ptr_uint Function\n" +
3449 "%3 = OpLoad %uint %n\n" +
3450 "%2 = OpIAdd %uint %3 %uint_1\n" +
3451 "OpReturn\n" +
3452 "OpFunctionEnd",
3453 2, 0),
3454 // Test case 1: Don't fold 1 + n
3455 InstructionFoldingCase<uint32_t>(
3456 Header() + "%main = OpFunction %void None %void_func\n" +
3457 "%main_lab = OpLabel\n" +
3458 "%n = OpVariable %_ptr_uint Function\n" +
3459 "%3 = OpLoad %uint %n\n" +
3460 "%2 = OpIAdd %uint %uint_1 %3\n" +
3461 "OpReturn\n" +
3462 "OpFunctionEnd",
3463 2, 0),
3464 // Test case 2: Fold n + 0
3465 InstructionFoldingCase<uint32_t>(
3466 Header() + "%main = OpFunction %void None %void_func\n" +
3467 "%main_lab = OpLabel\n" +
3468 "%n = OpVariable %_ptr_uint Function\n" +
3469 "%3 = OpLoad %uint %n\n" +
3470 "%2 = OpIAdd %uint %3 %uint_0\n" +
3471 "OpReturn\n" +
3472 "OpFunctionEnd",
3473 2, 3),
3474 // Test case 3: Fold 0 + n
3475 InstructionFoldingCase<uint32_t>(
3476 Header() + "%main = OpFunction %void None %void_func\n" +
3477 "%main_lab = OpLabel\n" +
3478 "%n = OpVariable %_ptr_uint Function\n" +
3479 "%3 = OpLoad %uint %n\n" +
3480 "%2 = OpIAdd %uint %uint_0 %3\n" +
3481 "OpReturn\n" +
3482 "OpFunctionEnd",
3483 2, 3),
3484 // Test case 4: Don't fold n + (1,0)
3485 InstructionFoldingCase<uint32_t>(
3486 Header() + "%main = OpFunction %void None %void_func\n" +
3487 "%main_lab = OpLabel\n" +
3488 "%n = OpVariable %_ptr_v2int Function\n" +
3489 "%3 = OpLoad %v2int %n\n" +
3490 "%2 = OpIAdd %v2int %3 %v2int_1_0\n" +
3491 "OpReturn\n" +
3492 "OpFunctionEnd",
3493 2, 0),
3494 // Test case 5: Don't fold (1,0) + n
3495 InstructionFoldingCase<uint32_t>(
3496 Header() + "%main = OpFunction %void None %void_func\n" +
3497 "%main_lab = OpLabel\n" +
3498 "%n = OpVariable %_ptr_v2int Function\n" +
3499 "%3 = OpLoad %v2int %n\n" +
3500 "%2 = OpIAdd %v2int %v2int_1_0 %3\n" +
3501 "OpReturn\n" +
3502 "OpFunctionEnd",
3503 2, 0),
3504 // Test case 6: Fold n + (0,0)
3505 InstructionFoldingCase<uint32_t>(
3506 Header() + "%main = OpFunction %void None %void_func\n" +
3507 "%main_lab = OpLabel\n" +
3508 "%n = OpVariable %_ptr_v2int Function\n" +
3509 "%3 = OpLoad %v2int %n\n" +
3510 "%2 = OpIAdd %v2int %3 %v2int_0_0\n" +
3511 "OpReturn\n" +
3512 "OpFunctionEnd",
3513 2, 3),
3514 // Test case 7: Fold (0,0) + n
3515 InstructionFoldingCase<uint32_t>(
3516 Header() + "%main = OpFunction %void None %void_func\n" +
3517 "%main_lab = OpLabel\n" +
3518 "%n = OpVariable %_ptr_v2int Function\n" +
3519 "%3 = OpLoad %v2int %n\n" +
3520 "%2 = OpIAdd %v2int %v2int_0_0 %3\n" +
3521 "OpReturn\n" +
3522 "OpFunctionEnd",
3523 2, 3)
3524 ));
3525
3526 INSTANTIATE_TEST_CASE_P(ClampAndCmpLHS, GeneralInstructionFoldingTest,
3527 ::testing::Values(
3528 // Test case 0: Don't Fold 0.0 < clamp(-1, 1)
3529 InstructionFoldingCase<uint32_t>(
3530 Header() + "%main = OpFunction %void None %void_func\n" +
3531 "%main_lab = OpLabel\n" +
3532 "%n = OpVariable %_ptr_float Function\n" +
3533 "%ld = OpLoad %float %n\n" +
3534 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3535 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
3536 "OpReturn\n" +
3537 "OpFunctionEnd",
3538 2, 0),
3539 // Test case 1: Don't Fold 0.0 < clamp(-1, 1)
3540 InstructionFoldingCase<uint32_t>(
3541 Header() + "%main = OpFunction %void None %void_func\n" +
3542 "%main_lab = OpLabel\n" +
3543 "%n = OpVariable %_ptr_float Function\n" +
3544 "%ld = OpLoad %float %n\n" +
3545 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3546 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
3547 "OpReturn\n" +
3548 "OpFunctionEnd",
3549 2, 0),
3550 // Test case 2: Don't Fold 0.0 <= clamp(-1, 1)
3551 InstructionFoldingCase<uint32_t>(
3552 Header() + "%main = OpFunction %void None %void_func\n" +
3553 "%main_lab = OpLabel\n" +
3554 "%n = OpVariable %_ptr_float Function\n" +
3555 "%ld = OpLoad %float %n\n" +
3556 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3557 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
3558 "OpReturn\n" +
3559 "OpFunctionEnd",
3560 2, 0),
3561 // Test case 3: Don't Fold 0.0 <= clamp(-1, 1)
3562 InstructionFoldingCase<uint32_t>(
3563 Header() + "%main = OpFunction %void None %void_func\n" +
3564 "%main_lab = OpLabel\n" +
3565 "%n = OpVariable %_ptr_float Function\n" +
3566 "%ld = OpLoad %float %n\n" +
3567 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3568 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
3569 "OpReturn\n" +
3570 "OpFunctionEnd",
3571 2, 0),
3572 // Test case 4: Don't Fold 0.0 > clamp(-1, 1)
3573 InstructionFoldingCase<uint32_t>(
3574 Header() + "%main = OpFunction %void None %void_func\n" +
3575 "%main_lab = OpLabel\n" +
3576 "%n = OpVariable %_ptr_float Function\n" +
3577 "%ld = OpLoad %float %n\n" +
3578 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3579 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
3580 "OpReturn\n" +
3581 "OpFunctionEnd",
3582 2, 0),
3583 // Test case 5: Don't Fold 0.0 > clamp(-1, 1)
3584 InstructionFoldingCase<uint32_t>(
3585 Header() + "%main = OpFunction %void None %void_func\n" +
3586 "%main_lab = OpLabel\n" +
3587 "%n = OpVariable %_ptr_float Function\n" +
3588 "%ld = OpLoad %float %n\n" +
3589 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3590 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
3591 "OpReturn\n" +
3592 "OpFunctionEnd",
3593 2, 0),
3594 // Test case 6: Don't Fold 0.0 >= clamp(-1, 1)
3595 InstructionFoldingCase<uint32_t>(
3596 Header() + "%main = OpFunction %void None %void_func\n" +
3597 "%main_lab = OpLabel\n" +
3598 "%n = OpVariable %_ptr_float Function\n" +
3599 "%ld = OpLoad %float %n\n" +
3600 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3601 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
3602 "OpReturn\n" +
3603 "OpFunctionEnd",
3604 2, 0),
3605 // Test case 7: Don't Fold 0.0 >= clamp(-1, 1)
3606 InstructionFoldingCase<uint32_t>(
3607 Header() + "%main = OpFunction %void None %void_func\n" +
3608 "%main_lab = OpLabel\n" +
3609 "%n = OpVariable %_ptr_float Function\n" +
3610 "%ld = OpLoad %float %n\n" +
3611 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3612 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
3613 "OpReturn\n" +
3614 "OpFunctionEnd",
3615 2, 0),
3616 // Test case 8: Don't Fold 0.0 < clamp(0, 1)
3617 InstructionFoldingCase<uint32_t>(
3618 Header() + "%main = OpFunction %void None %void_func\n" +
3619 "%main_lab = OpLabel\n" +
3620 "%n = OpVariable %_ptr_float Function\n" +
3621 "%ld = OpLoad %float %n\n" +
3622 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
3623 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
3624 "OpReturn\n" +
3625 "OpFunctionEnd",
3626 2, 0),
3627 // Test case 9: Don't Fold 0.0 < clamp(0, 1)
3628 InstructionFoldingCase<uint32_t>(
3629 Header() + "%main = OpFunction %void None %void_func\n" +
3630 "%main_lab = OpLabel\n" +
3631 "%n = OpVariable %_ptr_float Function\n" +
3632 "%ld = OpLoad %float %n\n" +
3633 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
3634 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
3635 "OpReturn\n" +
3636 "OpFunctionEnd",
3637 2, 0),
3638 // Test case 10: Don't Fold 0.0 > clamp(-1, 0)
3639 InstructionFoldingCase<uint32_t>(
3640 Header() + "%main = OpFunction %void None %void_func\n" +
3641 "%main_lab = OpLabel\n" +
3642 "%n = OpVariable %_ptr_float Function\n" +
3643 "%ld = OpLoad %float %n\n" +
3644 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
3645 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
3646 "OpReturn\n" +
3647 "OpFunctionEnd",
3648 2, 0),
3649 // Test case 11: Don't Fold 0.0 > clamp(-1, 0)
3650 InstructionFoldingCase<uint32_t>(
3651 Header() + "%main = OpFunction %void None %void_func\n" +
3652 "%main_lab = OpLabel\n" +
3653 "%n = OpVariable %_ptr_float Function\n" +
3654 "%ld = OpLoad %float %n\n" +
3655 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
3656 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
3657 "OpReturn\n" +
3658 "OpFunctionEnd",
3659 2, 0)
3660 ));
3661
3662 INSTANTIATE_TEST_CASE_P(ClampAndCmpRHS, GeneralInstructionFoldingTest,
3663 ::testing::Values(
3664 // Test case 0: Don't Fold clamp(-1, 1) < 0.0
3665 InstructionFoldingCase<uint32_t>(
3666 Header() + "%main = OpFunction %void None %void_func\n" +
3667 "%main_lab = OpLabel\n" +
3668 "%n = OpVariable %_ptr_float Function\n" +
3669 "%ld = OpLoad %float %n\n" +
3670 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3671 "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
3672 "OpReturn\n" +
3673 "OpFunctionEnd",
3674 2, 0),
3675 // Test case 1: Don't Fold clamp(-1, 1) < 0.0
3676 InstructionFoldingCase<uint32_t>(
3677 Header() + "%main = OpFunction %void None %void_func\n" +
3678 "%main_lab = OpLabel\n" +
3679 "%n = OpVariable %_ptr_float Function\n" +
3680 "%ld = OpLoad %float %n\n" +
3681 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3682 "%2 = OpFOrdLessThan %bool %clamp %float_0\n" +
3683 "OpReturn\n" +
3684 "OpFunctionEnd",
3685 2, 0),
3686 // Test case 2: Don't Fold clamp(-1, 1) <= 0.0
3687 InstructionFoldingCase<uint32_t>(
3688 Header() + "%main = OpFunction %void None %void_func\n" +
3689 "%main_lab = OpLabel\n" +
3690 "%n = OpVariable %_ptr_float Function\n" +
3691 "%ld = OpLoad %float %n\n" +
3692 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3693 "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
3694 "OpReturn\n" +
3695 "OpFunctionEnd",
3696 2, 0),
3697 // Test case 3: Don't Fold clamp(-1, 1) <= 0.0
3698 InstructionFoldingCase<uint32_t>(
3699 Header() + "%main = OpFunction %void None %void_func\n" +
3700 "%main_lab = OpLabel\n" +
3701 "%n = OpVariable %_ptr_float Function\n" +
3702 "%ld = OpLoad %float %n\n" +
3703 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3704 "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
3705 "OpReturn\n" +
3706 "OpFunctionEnd",
3707 2, 0),
3708 // Test case 4: Don't Fold clamp(-1, 1) > 0.0
3709 InstructionFoldingCase<uint32_t>(
3710 Header() + "%main = OpFunction %void None %void_func\n" +
3711 "%main_lab = OpLabel\n" +
3712 "%n = OpVariable %_ptr_float Function\n" +
3713 "%ld = OpLoad %float %n\n" +
3714 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3715 "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
3716 "OpReturn\n" +
3717 "OpFunctionEnd",
3718 2, 0),
3719 // Test case 5: Don't Fold clamp(-1, 1) > 0.0
3720 InstructionFoldingCase<uint32_t>(
3721 Header() + "%main = OpFunction %void None %void_func\n" +
3722 "%main_lab = OpLabel\n" +
3723 "%n = OpVariable %_ptr_float Function\n" +
3724 "%ld = OpLoad %float %n\n" +
3725 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3726 "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
3727 "OpReturn\n" +
3728 "OpFunctionEnd",
3729 2, 0),
3730 // Test case 6: Don't Fold clamp(-1, 1) >= 0.0
3731 InstructionFoldingCase<uint32_t>(
3732 Header() + "%main = OpFunction %void None %void_func\n" +
3733 "%main_lab = OpLabel\n" +
3734 "%n = OpVariable %_ptr_float Function\n" +
3735 "%ld = OpLoad %float %n\n" +
3736 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3737 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_0\n" +
3738 "OpReturn\n" +
3739 "OpFunctionEnd",
3740 2, 0),
3741 // Test case 7: Don't Fold clamp(-1, 1) >= 0.0
3742 InstructionFoldingCase<uint32_t>(
3743 Header() + "%main = OpFunction %void None %void_func\n" +
3744 "%main_lab = OpLabel\n" +
3745 "%n = OpVariable %_ptr_float Function\n" +
3746 "%ld = OpLoad %float %n\n" +
3747 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
3748 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
3749 "OpReturn\n" +
3750 "OpFunctionEnd",
3751 2, 0),
3752 // Test case 8: Don't Fold clamp(-1, 0) < 0.0
3753 InstructionFoldingCase<uint32_t>(
3754 Header() + "%main = OpFunction %void None %void_func\n" +
3755 "%main_lab = OpLabel\n" +
3756 "%n = OpVariable %_ptr_float Function\n" +
3757 "%ld = OpLoad %float %n\n" +
3758 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
3759 "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
3760 "OpReturn\n" +
3761 "OpFunctionEnd",
3762 2, 0),
3763 // Test case 9: Don't Fold clamp(0, 1) < 1
3764 InstructionFoldingCase<uint32_t>(
3765 Header() + "%main = OpFunction %void None %void_func\n" +
3766 "%main_lab = OpLabel\n" +
3767 "%n = OpVariable %_ptr_float Function\n" +
3768 "%ld = OpLoad %float %n\n" +
3769 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
3770 "%2 = OpFOrdLessThan %bool %clamp %float_1\n" +
3771 "OpReturn\n" +
3772 "OpFunctionEnd",
3773 2, 0),
3774 // Test case 10: Don't Fold clamp(-1, 0) > -1
3775 InstructionFoldingCase<uint32_t>(
3776 Header() + "%main = OpFunction %void None %void_func\n" +
3777 "%main_lab = OpLabel\n" +
3778 "%n = OpVariable %_ptr_float Function\n" +
3779 "%ld = OpLoad %float %n\n" +
3780 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
3781 "%2 = OpFUnordGreaterThan %bool %clamp %float_n1\n" +
3782 "OpReturn\n" +
3783 "OpFunctionEnd",
3784 2, 0),
3785 // Test case 11: Don't Fold clamp(-1, 0) > -1
3786 InstructionFoldingCase<uint32_t>(
3787 Header() + "%main = OpFunction %void None %void_func\n" +
3788 "%main_lab = OpLabel\n" +
3789 "%n = OpVariable %_ptr_float Function\n" +
3790 "%ld = OpLoad %float %n\n" +
3791 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
3792 "%2 = OpFOrdGreaterThan %bool %clamp %float_n1\n" +
3793 "OpReturn\n" +
3794 "OpFunctionEnd",
3795 2, 0)
3796 ));
3797
3798 INSTANTIATE_TEST_CASE_P(FToIConstantFoldingTest, IntegerInstructionFoldingTest,
3799 ::testing::Values(
3800 // Test case 0: Fold int(3.0)
3801 InstructionFoldingCase<uint32_t>(
3802 Header() + "%main = OpFunction %void None %void_func\n" +
3803 "%main_lab = OpLabel\n" +
3804 "%2 = OpConvertFToS %int %float_3\n" +
3805 "OpReturn\n" +
3806 "OpFunctionEnd",
3807 2, 3),
3808 // Test case 1: Fold uint(3.0)
3809 InstructionFoldingCase<uint32_t>(
3810 Header() + "%main = OpFunction %void None %void_func\n" +
3811 "%main_lab = OpLabel\n" +
3812 "%2 = OpConvertFToU %int %float_3\n" +
3813 "OpReturn\n" +
3814 "OpFunctionEnd",
3815 2, 3)
3816 ));
3817
3818 INSTANTIATE_TEST_CASE_P(IToFConstantFoldingTest, FloatInstructionFoldingTest,
3819 ::testing::Values(
3820 // Test case 0: Fold float(3)
3821 InstructionFoldingCase<float>(
3822 Header() + "%main = OpFunction %void None %void_func\n" +
3823 "%main_lab = OpLabel\n" +
3824 "%2 = OpConvertSToF %float %int_3\n" +
3825 "OpReturn\n" +
3826 "OpFunctionEnd",
3827 2, 3.0),
3828 // Test case 1: Fold float(3u)
3829 InstructionFoldingCase<float>(
3830 Header() + "%main = OpFunction %void None %void_func\n" +
3831 "%main_lab = OpLabel\n" +
3832 "%2 = OpConvertUToF %float %uint_3\n" +
3833 "OpReturn\n" +
3834 "OpFunctionEnd",
3835 2, 3.0)
3836 ));
3837 // clang-format on
3838
3839 using ToNegateFoldingTest =
3840 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
3841
TEST_P(ToNegateFoldingTest,Case)3842 TEST_P(ToNegateFoldingTest, Case) {
3843 const auto& tc = GetParam();
3844
3845 // Build module.
3846 std::unique_ptr<IRContext> context =
3847 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
3848 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3849 ASSERT_NE(nullptr, context);
3850
3851 // Fold the instruction to test.
3852 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
3853 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
3854 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
3855 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
3856
3857 // Make sure the instruction folded as expected.
3858 EXPECT_EQ(inst->result_id(), original_inst->result_id());
3859 EXPECT_EQ(inst->type_id(), original_inst->type_id());
3860 EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
3861 if (succeeded) {
3862 EXPECT_EQ(inst->opcode(), SpvOpFNegate);
3863 EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
3864 } else {
3865 EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
3866 for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
3867 EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
3868 }
3869 }
3870 }
3871
3872 // clang-format off
3873 INSTANTIATE_TEST_CASE_P(FloatRedundantSubFoldingTest, ToNegateFoldingTest,
3874 ::testing::Values(
3875 // Test case 0: Don't fold 1.0 - n
3876 InstructionFoldingCase<uint32_t>(
3877 Header() + "%main = OpFunction %void None %void_func\n" +
3878 "%main_lab = OpLabel\n" +
3879 "%n = OpVariable %_ptr_float Function\n" +
3880 "%3 = OpLoad %float %n\n" +
3881 "%2 = OpFSub %float %float_1 %3\n" +
3882 "OpReturn\n" +
3883 "OpFunctionEnd",
3884 2, 0),
3885 // Test case 1: Fold 0.0 - n
3886 InstructionFoldingCase<uint32_t>(
3887 Header() + "%main = OpFunction %void None %void_func\n" +
3888 "%main_lab = OpLabel\n" +
3889 "%n = OpVariable %_ptr_float Function\n" +
3890 "%3 = OpLoad %float %n\n" +
3891 "%2 = OpFSub %float %float_0 %3\n" +
3892 "OpReturn\n" +
3893 "OpFunctionEnd",
3894 2, 3),
3895 // Test case 2: Don't fold (0,0,0,1) - n
3896 InstructionFoldingCase<uint32_t>(
3897 Header() + "%main = OpFunction %void None %void_func\n" +
3898 "%main_lab = OpLabel\n" +
3899 "%n = OpVariable %_ptr_v4float Function\n" +
3900 "%3 = OpLoad %v4float %n\n" +
3901 "%2 = OpFSub %v4float %v4float_0_0_0_1 %3\n" +
3902 "OpReturn\n" +
3903 "OpFunctionEnd",
3904 2, 0),
3905 // Test case 3: Fold (0,0,0,0) - n
3906 InstructionFoldingCase<uint32_t>(
3907 Header() + "%main = OpFunction %void None %void_func\n" +
3908 "%main_lab = OpLabel\n" +
3909 "%n = OpVariable %_ptr_v4float Function\n" +
3910 "%3 = OpLoad %v4float %n\n" +
3911 "%2 = OpFSub %v4float %v4float_0_0_0_0 %3\n" +
3912 "OpReturn\n" +
3913 "OpFunctionEnd",
3914 2, 3)
3915 ));
3916
3917 INSTANTIATE_TEST_CASE_P(DoubleRedundantSubFoldingTest, ToNegateFoldingTest,
3918 ::testing::Values(
3919 // Test case 0: Don't fold 1.0 - n
3920 InstructionFoldingCase<uint32_t>(
3921 Header() + "%main = OpFunction %void None %void_func\n" +
3922 "%main_lab = OpLabel\n" +
3923 "%n = OpVariable %_ptr_double Function\n" +
3924 "%3 = OpLoad %double %n\n" +
3925 "%2 = OpFSub %double %double_1 %3\n" +
3926 "OpReturn\n" +
3927 "OpFunctionEnd",
3928 2, 0),
3929 // Test case 1: Fold 0.0 - n
3930 InstructionFoldingCase<uint32_t>(
3931 Header() + "%main = OpFunction %void None %void_func\n" +
3932 "%main_lab = OpLabel\n" +
3933 "%n = OpVariable %_ptr_double Function\n" +
3934 "%3 = OpLoad %double %n\n" +
3935 "%2 = OpFSub %double %double_0 %3\n" +
3936 "OpReturn\n" +
3937 "OpFunctionEnd",
3938 2, 3),
3939 // Test case 2: Don't fold (0,0,0,1) - n
3940 InstructionFoldingCase<uint32_t>(
3941 Header() + "%main = OpFunction %void None %void_func\n" +
3942 "%main_lab = OpLabel\n" +
3943 "%n = OpVariable %_ptr_v4double Function\n" +
3944 "%3 = OpLoad %v4double %n\n" +
3945 "%2 = OpFSub %v4double %v4double_0_0_0_1 %3\n" +
3946 "OpReturn\n" +
3947 "OpFunctionEnd",
3948 2, 0),
3949 // Test case 3: Fold (0,0,0,0) - n
3950 InstructionFoldingCase<uint32_t>(
3951 Header() + "%main = OpFunction %void None %void_func\n" +
3952 "%main_lab = OpLabel\n" +
3953 "%n = OpVariable %_ptr_v4double Function\n" +
3954 "%3 = OpLoad %v4double %n\n" +
3955 "%2 = OpFSub %v4double %v4double_0_0_0_0 %3\n" +
3956 "OpReturn\n" +
3957 "OpFunctionEnd",
3958 2, 3)
3959 ));
3960
3961 using MatchingInstructionFoldingTest =
3962 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
3963
TEST_P(MatchingInstructionFoldingTest,Case)3964 TEST_P(MatchingInstructionFoldingTest, Case) {
3965 const auto& tc = GetParam();
3966
3967 // Build module.
3968 std::unique_ptr<IRContext> context =
3969 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
3970 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3971 ASSERT_NE(nullptr, context);
3972
3973 // Fold the instruction to test.
3974 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
3975 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
3976 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
3977 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
3978 EXPECT_EQ(succeeded, tc.expected_result);
3979 if (succeeded) {
3980 Match(tc.test_body, context.get());
3981 }
3982 }
3983
3984 INSTANTIATE_TEST_CASE_P(RedundantIntegerMatching, MatchingInstructionFoldingTest,
3985 ::testing::Values(
3986 // Test case 0: Fold 0 + n (change sign)
3987 InstructionFoldingCase<bool>(
3988 Header() +
3989 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
3990 "; CHECK: %2 = OpBitcast [[uint]] %3\n" +
3991 "%main = OpFunction %void None %void_func\n" +
3992 "%main_lab = OpLabel\n" +
3993 "%n = OpVariable %_ptr_int Function\n" +
3994 "%3 = OpLoad %uint %n\n" +
3995 "%2 = OpIAdd %uint %int_0 %3\n" +
3996 "OpReturn\n" +
3997 "OpFunctionEnd\n",
3998 2, true),
3999 // Test case 0: Fold 0 + n (change sign)
4000 InstructionFoldingCase<bool>(
4001 Header() +
4002 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4003 "; CHECK: %2 = OpBitcast [[int]] %3\n" +
4004 "%main = OpFunction %void None %void_func\n" +
4005 "%main_lab = OpLabel\n" +
4006 "%n = OpVariable %_ptr_int Function\n" +
4007 "%3 = OpLoad %int %n\n" +
4008 "%2 = OpIAdd %int %uint_0 %3\n" +
4009 "OpReturn\n" +
4010 "OpFunctionEnd\n",
4011 2, true)
4012 ));
4013
4014 INSTANTIATE_TEST_CASE_P(MergeNegateTest, MatchingInstructionFoldingTest,
4015 ::testing::Values(
4016 // Test case 0: fold consecutive fnegate
4017 // -(-x) = x
4018 InstructionFoldingCase<bool>(
4019 Header() +
4020 "; CHECK: [[ld:%\\w+]] = OpLoad [[float:%\\w+]]\n" +
4021 "; CHECK: %4 = OpCopyObject [[float]] [[ld]]\n" +
4022 "%main = OpFunction %void None %void_func\n" +
4023 "%main_lab = OpLabel\n" +
4024 "%var = OpVariable %_ptr_float Function\n" +
4025 "%2 = OpLoad %float %var\n" +
4026 "%3 = OpFNegate %float %2\n" +
4027 "%4 = OpFNegate %float %3\n" +
4028 "OpReturn\n" +
4029 "OpFunctionEnd",
4030 4, true),
4031 // Test case 1: fold fnegate(fmul with const).
4032 // -(x * 2.0) = x * -2.0
4033 InstructionFoldingCase<bool>(
4034 Header() +
4035 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4036 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
4037 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4038 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
4039 "%main = OpFunction %void None %void_func\n" +
4040 "%main_lab = OpLabel\n" +
4041 "%var = OpVariable %_ptr_float Function\n" +
4042 "%2 = OpLoad %float %var\n" +
4043 "%3 = OpFMul %float %2 %float_2\n" +
4044 "%4 = OpFNegate %float %3\n" +
4045 "OpReturn\n" +
4046 "OpFunctionEnd",
4047 4, true),
4048 // Test case 2: fold fnegate(fmul with const).
4049 // -(2.0 * x) = x * 2.0
4050 InstructionFoldingCase<bool>(
4051 Header() +
4052 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4053 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
4054 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4055 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
4056 "%main = OpFunction %void None %void_func\n" +
4057 "%main_lab = OpLabel\n" +
4058 "%var = OpVariable %_ptr_float Function\n" +
4059 "%2 = OpLoad %float %var\n" +
4060 "%3 = OpFMul %float %float_2 %2\n" +
4061 "%4 = OpFNegate %float %3\n" +
4062 "OpReturn\n" +
4063 "OpFunctionEnd",
4064 4, true),
4065 // Test case 3: fold fnegate(fdiv with const).
4066 // -(x / 2.0) = x * -0.5
4067 InstructionFoldingCase<bool>(
4068 Header() +
4069 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4070 "; CHECK: [[float_n0p5:%\\w+]] = OpConstant [[float]] -0.5\n" +
4071 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4072 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n0p5]]\n" +
4073 "%main = OpFunction %void None %void_func\n" +
4074 "%main_lab = OpLabel\n" +
4075 "%var = OpVariable %_ptr_float Function\n" +
4076 "%2 = OpLoad %float %var\n" +
4077 "%3 = OpFDiv %float %2 %float_2\n" +
4078 "%4 = OpFNegate %float %3\n" +
4079 "OpReturn\n" +
4080 "OpFunctionEnd",
4081 4, true),
4082 // Test case 4: fold fnegate(fdiv with const).
4083 // -(2.0 / x) = -2.0 / x
4084 InstructionFoldingCase<bool>(
4085 Header() +
4086 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4087 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
4088 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4089 "; CHECK: %4 = OpFDiv [[float]] [[float_n2]] [[ld]]\n" +
4090 "%main = OpFunction %void None %void_func\n" +
4091 "%main_lab = OpLabel\n" +
4092 "%var = OpVariable %_ptr_float Function\n" +
4093 "%2 = OpLoad %float %var\n" +
4094 "%3 = OpFDiv %float %float_2 %2\n" +
4095 "%4 = OpFNegate %float %3\n" +
4096 "OpReturn\n" +
4097 "OpFunctionEnd",
4098 4, true),
4099 // Test case 5: fold fnegate(fadd with const).
4100 // -(2.0 + x) = -2.0 - x
4101 InstructionFoldingCase<bool>(
4102 Header() +
4103 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4104 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
4105 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4106 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
4107 "%main = OpFunction %void None %void_func\n" +
4108 "%main_lab = OpLabel\n" +
4109 "%var = OpVariable %_ptr_float Function\n" +
4110 "%2 = OpLoad %float %var\n" +
4111 "%3 = OpFAdd %float %float_2 %2\n" +
4112 "%4 = OpFNegate %float %3\n" +
4113 "OpReturn\n" +
4114 "OpFunctionEnd",
4115 4, true),
4116 // Test case 6: fold fnegate(fadd with const).
4117 // -(x + 2.0) = -2.0 - x
4118 InstructionFoldingCase<bool>(
4119 Header() +
4120 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4121 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
4122 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4123 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
4124 "%main = OpFunction %void None %void_func\n" +
4125 "%main_lab = OpLabel\n" +
4126 "%var = OpVariable %_ptr_float Function\n" +
4127 "%2 = OpLoad %float %var\n" +
4128 "%3 = OpFAdd %float %2 %float_2\n" +
4129 "%4 = OpFNegate %float %3\n" +
4130 "OpReturn\n" +
4131 "OpFunctionEnd",
4132 4, true),
4133 // Test case 7: fold fnegate(fsub with const).
4134 // -(2.0 - x) = x - 2.0
4135 InstructionFoldingCase<bool>(
4136 Header() +
4137 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4138 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4139 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4140 "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_2]]\n" +
4141 "%main = OpFunction %void None %void_func\n" +
4142 "%main_lab = OpLabel\n" +
4143 "%var = OpVariable %_ptr_float Function\n" +
4144 "%2 = OpLoad %float %var\n" +
4145 "%3 = OpFSub %float %float_2 %2\n" +
4146 "%4 = OpFNegate %float %3\n" +
4147 "OpReturn\n" +
4148 "OpFunctionEnd",
4149 4, true),
4150 // Test case 8: fold fnegate(fsub with const).
4151 // -(x - 2.0) = 2.0 - x
4152 InstructionFoldingCase<bool>(
4153 Header() +
4154 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4155 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4156 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4157 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
4158 "%main = OpFunction %void None %void_func\n" +
4159 "%main_lab = OpLabel\n" +
4160 "%var = OpVariable %_ptr_float Function\n" +
4161 "%2 = OpLoad %float %var\n" +
4162 "%3 = OpFSub %float %2 %float_2\n" +
4163 "%4 = OpFNegate %float %3\n" +
4164 "OpReturn\n" +
4165 "OpFunctionEnd",
4166 4, true),
4167 // Test case 9: fold consecutive snegate
4168 // -(-x) = x
4169 InstructionFoldingCase<bool>(
4170 Header() +
4171 "; CHECK: [[ld:%\\w+]] = OpLoad [[int:%\\w+]]\n" +
4172 "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
4173 "%main = OpFunction %void None %void_func\n" +
4174 "%main_lab = OpLabel\n" +
4175 "%var = OpVariable %_ptr_int Function\n" +
4176 "%2 = OpLoad %int %var\n" +
4177 "%3 = OpSNegate %int %2\n" +
4178 "%4 = OpSNegate %int %3\n" +
4179 "OpReturn\n" +
4180 "OpFunctionEnd",
4181 4, true),
4182 // Test case 10: fold consecutive vector negate
4183 // -(-x) = x
4184 InstructionFoldingCase<bool>(
4185 Header() +
4186 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float:%\\w+]]\n" +
4187 "; CHECK: %4 = OpCopyObject [[v2float]] [[ld]]\n" +
4188 "%main = OpFunction %void None %void_func\n" +
4189 "%main_lab = OpLabel\n" +
4190 "%var = OpVariable %_ptr_v2float Function\n" +
4191 "%2 = OpLoad %v2float %var\n" +
4192 "%3 = OpFNegate %v2float %2\n" +
4193 "%4 = OpFNegate %v2float %3\n" +
4194 "OpReturn\n" +
4195 "OpFunctionEnd",
4196 4, true),
4197 // Test case 11: fold snegate(iadd with const).
4198 // -(2 + x) = -2 - x
4199 InstructionFoldingCase<bool>(
4200 Header() +
4201 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4202 "; CHECK: OpConstant [[int]] -2147483648\n" +
4203 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
4204 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
4205 "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
4206 "%main = OpFunction %void None %void_func\n" +
4207 "%main_lab = OpLabel\n" +
4208 "%var = OpVariable %_ptr_int Function\n" +
4209 "%2 = OpLoad %int %var\n" +
4210 "%3 = OpIAdd %int %int_2 %2\n" +
4211 "%4 = OpSNegate %int %3\n" +
4212 "OpReturn\n" +
4213 "OpFunctionEnd",
4214 4, true),
4215 // Test case 12: fold snegate(iadd with const).
4216 // -(x + 2) = -2 - x
4217 InstructionFoldingCase<bool>(
4218 Header() +
4219 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4220 "; CHECK: OpConstant [[int]] -2147483648\n" +
4221 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
4222 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
4223 "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
4224 "%main = OpFunction %void None %void_func\n" +
4225 "%main_lab = OpLabel\n" +
4226 "%var = OpVariable %_ptr_int Function\n" +
4227 "%2 = OpLoad %int %var\n" +
4228 "%3 = OpIAdd %int %2 %int_2\n" +
4229 "%4 = OpSNegate %int %3\n" +
4230 "OpReturn\n" +
4231 "OpFunctionEnd",
4232 4, true),
4233 // Test case 13: fold snegate(isub with const).
4234 // -(2 - x) = x - 2
4235 InstructionFoldingCase<bool>(
4236 Header() +
4237 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4238 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
4239 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
4240 "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_2]]\n" +
4241 "%main = OpFunction %void None %void_func\n" +
4242 "%main_lab = OpLabel\n" +
4243 "%var = OpVariable %_ptr_int Function\n" +
4244 "%2 = OpLoad %int %var\n" +
4245 "%3 = OpISub %int %int_2 %2\n" +
4246 "%4 = OpSNegate %int %3\n" +
4247 "OpReturn\n" +
4248 "OpFunctionEnd",
4249 4, true),
4250 // Test case 14: fold snegate(isub with const).
4251 // -(x - 2) = 2 - x
4252 InstructionFoldingCase<bool>(
4253 Header() +
4254 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4255 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
4256 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
4257 "; CHECK: %4 = OpISub [[int]] [[int_2]] [[ld]]\n" +
4258 "%main = OpFunction %void None %void_func\n" +
4259 "%main_lab = OpLabel\n" +
4260 "%var = OpVariable %_ptr_int Function\n" +
4261 "%2 = OpLoad %int %var\n" +
4262 "%3 = OpISub %int %2 %int_2\n" +
4263 "%4 = OpSNegate %int %3\n" +
4264 "OpReturn\n" +
4265 "OpFunctionEnd",
4266 4, true),
4267 // Test case 15: fold snegate(iadd with const).
4268 // -(x + 2) = -2 - x
4269 InstructionFoldingCase<bool>(
4270 Header() +
4271 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
4272 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2\n" +
4273 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
4274 "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
4275 "%main = OpFunction %void None %void_func\n" +
4276 "%main_lab = OpLabel\n" +
4277 "%var = OpVariable %_ptr_long Function\n" +
4278 "%2 = OpLoad %long %var\n" +
4279 "%3 = OpIAdd %long %2 %long_2\n" +
4280 "%4 = OpSNegate %long %3\n" +
4281 "OpReturn\n" +
4282 "OpFunctionEnd",
4283 4, true),
4284 // Test case 16: fold snegate(isub with const).
4285 // -(2 - x) = x - 2
4286 InstructionFoldingCase<bool>(
4287 Header() +
4288 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
4289 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
4290 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
4291 "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_2]]\n" +
4292 "%main = OpFunction %void None %void_func\n" +
4293 "%main_lab = OpLabel\n" +
4294 "%var = OpVariable %_ptr_long Function\n" +
4295 "%2 = OpLoad %long %var\n" +
4296 "%3 = OpISub %long %long_2 %2\n" +
4297 "%4 = OpSNegate %long %3\n" +
4298 "OpReturn\n" +
4299 "OpFunctionEnd",
4300 4, true),
4301 // Test case 17: fold snegate(isub with const).
4302 // -(x - 2) = 2 - x
4303 InstructionFoldingCase<bool>(
4304 Header() +
4305 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
4306 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
4307 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
4308 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
4309 "%main = OpFunction %void None %void_func\n" +
4310 "%main_lab = OpLabel\n" +
4311 "%var = OpVariable %_ptr_long Function\n" +
4312 "%2 = OpLoad %long %var\n" +
4313 "%3 = OpISub %long %2 %long_2\n" +
4314 "%4 = OpSNegate %long %3\n" +
4315 "OpReturn\n" +
4316 "OpFunctionEnd",
4317 4, true),
4318 // Test case 18: fold -vec4(-1.0, 2.0, 1.0, 3.0)
4319 InstructionFoldingCase<bool>(
4320 Header() +
4321 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4322 "; CHECK: [[v4float:%\\w+]] = OpTypeVector [[float]] 4\n" +
4323 "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
4324 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
4325 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
4326 "; CHECK: [[float_n3:%\\w+]] = OpConstant [[float]] -3\n" +
4327 "; CHECK: [[v4float_1_n2_n1_n3:%\\w+]] = OpConstantComposite [[v4float]] [[float_1]] [[float_n2]] [[float_n1]] [[float_n3]]\n" +
4328 "; CHECK: %2 = OpCopyObject [[v4float]] [[v4float_1_n2_n1_n3]]\n" +
4329 "%main = OpFunction %void None %void_func\n" +
4330 "%main_lab = OpLabel\n" +
4331 "%2 = OpFNegate %v4float %v4float_n1_2_1_3\n" +
4332 "OpReturn\n" +
4333 "OpFunctionEnd",
4334 2, true),
4335 // Test case 19: fold vector fnegate with null
4336 InstructionFoldingCase<bool>(
4337 Header() +
4338 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
4339 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
4340 "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" +
4341 "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_n0]] [[double_n0]]\n" +
4342 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
4343 "%main = OpFunction %void None %void_func\n" +
4344 "%main_lab = OpLabel\n" +
4345 "%2 = OpFNegate %v2double %v2double_null\n" +
4346 "OpReturn\n" +
4347 "OpFunctionEnd",
4348 2, true)
4349 ));
4350
4351 INSTANTIATE_TEST_CASE_P(ReciprocalFDivTest, MatchingInstructionFoldingTest,
4352 ::testing::Values(
4353 // Test case 0: scalar reicprocal
4354 // x / 0.5 = x * 2.0
4355 InstructionFoldingCase<bool>(
4356 Header() +
4357 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4358 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4359 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4360 "; CHECK: %3 = OpFMul [[float]] [[ld]] [[float_2]]\n" +
4361 "%main = OpFunction %void None %void_func\n" +
4362 "%main_lab = OpLabel\n" +
4363 "%var = OpVariable %_ptr_float Function\n" +
4364 "%2 = OpLoad %float %var\n" +
4365 "%3 = OpFDiv %float %2 %float_0p5\n" +
4366 "OpReturn\n" +
4367 "OpFunctionEnd\n",
4368 3, true),
4369 // Test case 1: Unfoldable
4370 InstructionFoldingCase<bool>(
4371 Header() +
4372 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4373 "; CHECK: [[float_0:%\\w+]] = OpConstant [[float]] 0\n" +
4374 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4375 "; CHECK: %3 = OpFDiv [[float]] [[ld]] [[float_0]]\n" +
4376 "%main = OpFunction %void None %void_func\n" +
4377 "%main_lab = OpLabel\n" +
4378 "%var = OpVariable %_ptr_float Function\n" +
4379 "%2 = OpLoad %float %var\n" +
4380 "%3 = OpFDiv %float %2 %104\n" +
4381 "OpReturn\n" +
4382 "OpFunctionEnd\n",
4383 3, false),
4384 // Test case 2: Vector reciprocal
4385 // x / {2.0, 0.5} = x * {0.5, 2.0}
4386 InstructionFoldingCase<bool>(
4387 Header() +
4388 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4389 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
4390 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4391 "; CHECK: [[float_0p5:%\\w+]] = OpConstant [[float]] 0.5\n" +
4392 "; CHECK: [[v2float_0p5_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_0p5]] [[float_2]]\n" +
4393 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
4394 "; CHECK: %3 = OpFMul [[v2float]] [[ld]] [[v2float_0p5_2]]\n" +
4395 "%main = OpFunction %void None %void_func\n" +
4396 "%main_lab = OpLabel\n" +
4397 "%var = OpVariable %_ptr_v2float Function\n" +
4398 "%2 = OpLoad %v2float %var\n" +
4399 "%3 = OpFDiv %v2float %2 %v2float_2_0p5\n" +
4400 "OpReturn\n" +
4401 "OpFunctionEnd\n",
4402 3, true),
4403 // Test case 3: double reciprocal
4404 // x / 2.0 = x * 0.5
4405 InstructionFoldingCase<bool>(
4406 Header() +
4407 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
4408 "; CHECK: [[double_0p5:%\\w+]] = OpConstant [[double]] 0.5\n" +
4409 "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
4410 "; CHECK: %3 = OpFMul [[double]] [[ld]] [[double_0p5]]\n" +
4411 "%main = OpFunction %void None %void_func\n" +
4412 "%main_lab = OpLabel\n" +
4413 "%var = OpVariable %_ptr_double Function\n" +
4414 "%2 = OpLoad %double %var\n" +
4415 "%3 = OpFDiv %double %2 %double_2\n" +
4416 "OpReturn\n" +
4417 "OpFunctionEnd\n",
4418 3, true),
4419 // Test case 4: don't fold x / 0.
4420 InstructionFoldingCase<bool>(
4421 Header() +
4422 "%main = OpFunction %void None %void_func\n" +
4423 "%main_lab = OpLabel\n" +
4424 "%var = OpVariable %_ptr_v2float Function\n" +
4425 "%2 = OpLoad %v2float %var\n" +
4426 "%3 = OpFDiv %v2float %2 %v2float_null\n" +
4427 "OpReturn\n" +
4428 "OpFunctionEnd\n",
4429 3, false)
4430 ));
4431
4432 INSTANTIATE_TEST_CASE_P(MergeMulTest, MatchingInstructionFoldingTest,
4433 ::testing::Values(
4434 // Test case 0: fold consecutive fmuls
4435 // (x * 3.0) * 2.0 = x * 6.0
4436 InstructionFoldingCase<bool>(
4437 Header() +
4438 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4439 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
4440 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4441 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
4442 "%main = OpFunction %void None %void_func\n" +
4443 "%main_lab = OpLabel\n" +
4444 "%var = OpVariable %_ptr_float Function\n" +
4445 "%2 = OpLoad %float %var\n" +
4446 "%3 = OpFMul %float %2 %float_3\n" +
4447 "%4 = OpFMul %float %3 %float_2\n" +
4448 "OpReturn\n" +
4449 "OpFunctionEnd\n",
4450 4, true),
4451 // Test case 1: fold consecutive fmuls
4452 // 2.0 * (x * 3.0) = x * 6.0
4453 InstructionFoldingCase<bool>(
4454 Header() +
4455 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4456 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
4457 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4458 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
4459 "%main = OpFunction %void None %void_func\n" +
4460 "%main_lab = OpLabel\n" +
4461 "%var = OpVariable %_ptr_float Function\n" +
4462 "%2 = OpLoad %float %var\n" +
4463 "%3 = OpFMul %float %2 %float_3\n" +
4464 "%4 = OpFMul %float %float_2 %3\n" +
4465 "OpReturn\n" +
4466 "OpFunctionEnd\n",
4467 4, true),
4468 // Test case 2: fold consecutive fmuls
4469 // (3.0 * x) * 2.0 = x * 6.0
4470 InstructionFoldingCase<bool>(
4471 Header() +
4472 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4473 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
4474 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4475 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
4476 "%main = OpFunction %void None %void_func\n" +
4477 "%main_lab = OpLabel\n" +
4478 "%var = OpVariable %_ptr_float Function\n" +
4479 "%2 = OpLoad %float %var\n" +
4480 "%3 = OpFMul %float %float_3 %2\n" +
4481 "%4 = OpFMul %float %float_2 %3\n" +
4482 "OpReturn\n" +
4483 "OpFunctionEnd\n",
4484 4, true),
4485 // Test case 3: fold vector fmul
4486 InstructionFoldingCase<bool>(
4487 Header() +
4488 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4489 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
4490 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
4491 "; CHECK: [[v2float_6_6:%\\w+]] = OpConstantComposite [[v2float]] [[float_6]] [[float_6]]\n" +
4492 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
4493 "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_6_6]]\n" +
4494 "%main = OpFunction %void None %void_func\n" +
4495 "%main_lab = OpLabel\n" +
4496 "%var = OpVariable %_ptr_v2float Function\n" +
4497 "%2 = OpLoad %v2float %var\n" +
4498 "%3 = OpFMul %v2float %2 %v2float_2_3\n" +
4499 "%4 = OpFMul %v2float %3 %v2float_3_2\n" +
4500 "OpReturn\n" +
4501 "OpFunctionEnd\n",
4502 4, true),
4503 // Test case 4: fold double fmuls
4504 // (x * 3.0) * 2.0 = x * 6.0
4505 InstructionFoldingCase<bool>(
4506 Header() +
4507 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
4508 "; CHECK: [[double_6:%\\w+]] = OpConstant [[double]] 6\n" +
4509 "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
4510 "; CHECK: %4 = OpFMul [[double]] [[ld]] [[double_6]]\n" +
4511 "%main = OpFunction %void None %void_func\n" +
4512 "%main_lab = OpLabel\n" +
4513 "%var = OpVariable %_ptr_double Function\n" +
4514 "%2 = OpLoad %double %var\n" +
4515 "%3 = OpFMul %double %2 %double_3\n" +
4516 "%4 = OpFMul %double %3 %double_2\n" +
4517 "OpReturn\n" +
4518 "OpFunctionEnd\n",
4519 4, true),
4520 // Test case 5: fold 32 bit imuls
4521 // (x * 3) * 2 = x * 6
4522 InstructionFoldingCase<bool>(
4523 Header() +
4524 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4525 "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
4526 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
4527 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_6]]\n" +
4528 "%main = OpFunction %void None %void_func\n" +
4529 "%main_lab = OpLabel\n" +
4530 "%var = OpVariable %_ptr_int Function\n" +
4531 "%2 = OpLoad %int %var\n" +
4532 "%3 = OpIMul %int %2 %int_3\n" +
4533 "%4 = OpIMul %int %3 %int_2\n" +
4534 "OpReturn\n" +
4535 "OpFunctionEnd\n",
4536 4, true),
4537 // Test case 6: fold 64 bit imuls
4538 // (x * 3) * 2 = x * 6
4539 InstructionFoldingCase<bool>(
4540 Header() +
4541 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
4542 "; CHECK: [[long_6:%\\w+]] = OpConstant [[long]] 6\n" +
4543 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
4544 "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_6]]\n" +
4545 "%main = OpFunction %void None %void_func\n" +
4546 "%main_lab = OpLabel\n" +
4547 "%var = OpVariable %_ptr_long Function\n" +
4548 "%2 = OpLoad %long %var\n" +
4549 "%3 = OpIMul %long %2 %long_3\n" +
4550 "%4 = OpIMul %long %3 %long_2\n" +
4551 "OpReturn\n" +
4552 "OpFunctionEnd\n",
4553 4, true),
4554 // Test case 7: merge vector integer mults
4555 InstructionFoldingCase<bool>(
4556 Header() +
4557 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4558 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
4559 "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
4560 "; CHECK: [[v2int_6_6:%\\w+]] = OpConstantComposite [[v2int]] [[int_6]] [[int_6]]\n" +
4561 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
4562 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_6_6]]\n" +
4563 "%main = OpFunction %void None %void_func\n" +
4564 "%main_lab = OpLabel\n" +
4565 "%var = OpVariable %_ptr_v2int Function\n" +
4566 "%2 = OpLoad %v2int %var\n" +
4567 "%3 = OpIMul %v2int %2 %v2int_2_3\n" +
4568 "%4 = OpIMul %v2int %3 %v2int_3_2\n" +
4569 "OpReturn\n" +
4570 "OpFunctionEnd\n",
4571 4, true),
4572 // Test case 8: merge fmul of fdiv
4573 // 2.0 * (2.0 / x) = 4.0 / x
4574 InstructionFoldingCase<bool>(
4575 Header() +
4576 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4577 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
4578 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4579 "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
4580 "%main = OpFunction %void None %void_func\n" +
4581 "%main_lab = OpLabel\n" +
4582 "%var = OpVariable %_ptr_float Function\n" +
4583 "%2 = OpLoad %float %var\n" +
4584 "%3 = OpFDiv %float %float_2 %2\n" +
4585 "%4 = OpFMul %float %float_2 %3\n" +
4586 "OpReturn\n" +
4587 "OpFunctionEnd\n",
4588 4, true),
4589 // Test case 9: merge fmul of fdiv
4590 // (2.0 / x) * 2.0 = 4.0 / x
4591 InstructionFoldingCase<bool>(
4592 Header() +
4593 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4594 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
4595 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4596 "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
4597 "%main = OpFunction %void None %void_func\n" +
4598 "%main_lab = OpLabel\n" +
4599 "%var = OpVariable %_ptr_float Function\n" +
4600 "%2 = OpLoad %float %var\n" +
4601 "%3 = OpFDiv %float %float_2 %2\n" +
4602 "%4 = OpFMul %float %3 %float_2\n" +
4603 "OpReturn\n" +
4604 "OpFunctionEnd\n",
4605 4, true),
4606 // Test case 10: Do not merge imul of sdiv
4607 // 4 * (x / 2)
4608 InstructionFoldingCase<bool>(
4609 Header() +
4610 "%main = OpFunction %void None %void_func\n" +
4611 "%main_lab = OpLabel\n" +
4612 "%var = OpVariable %_ptr_int Function\n" +
4613 "%2 = OpLoad %int %var\n" +
4614 "%3 = OpSDiv %int %2 %int_2\n" +
4615 "%4 = OpIMul %int %int_4 %3\n" +
4616 "OpReturn\n" +
4617 "OpFunctionEnd\n",
4618 4, false),
4619 // Test case 11: Do not merge imul of sdiv
4620 // (x / 2) * 4
4621 InstructionFoldingCase<bool>(
4622 Header() +
4623 "%main = OpFunction %void None %void_func\n" +
4624 "%main_lab = OpLabel\n" +
4625 "%var = OpVariable %_ptr_int Function\n" +
4626 "%2 = OpLoad %int %var\n" +
4627 "%3 = OpSDiv %int %2 %int_2\n" +
4628 "%4 = OpIMul %int %3 %int_4\n" +
4629 "OpReturn\n" +
4630 "OpFunctionEnd\n",
4631 4, false),
4632 // Test case 12: Do not merge imul of udiv
4633 // 4 * (x / 2)
4634 InstructionFoldingCase<bool>(
4635 Header() +
4636 "%main = OpFunction %void None %void_func\n" +
4637 "%main_lab = OpLabel\n" +
4638 "%var = OpVariable %_ptr_uint Function\n" +
4639 "%2 = OpLoad %uint %var\n" +
4640 "%3 = OpUDiv %uint %2 %uint_2\n" +
4641 "%4 = OpIMul %uint %uint_4 %3\n" +
4642 "OpReturn\n" +
4643 "OpFunctionEnd\n",
4644 4, false),
4645 // Test case 13: Do not merge imul of udiv
4646 // (x / 2) * 4
4647 InstructionFoldingCase<bool>(
4648 Header() +
4649 "%main = OpFunction %void None %void_func\n" +
4650 "%main_lab = OpLabel\n" +
4651 "%var = OpVariable %_ptr_uint Function\n" +
4652 "%2 = OpLoad %uint %var\n" +
4653 "%3 = OpUDiv %uint %2 %uint_2\n" +
4654 "%4 = OpIMul %uint %3 %uint_4\n" +
4655 "OpReturn\n" +
4656 "OpFunctionEnd\n",
4657 4, false),
4658 // Test case 14: Don't fold
4659 // (x / 3) * 4
4660 InstructionFoldingCase<bool>(
4661 Header() +
4662 "%main = OpFunction %void None %void_func\n" +
4663 "%main_lab = OpLabel\n" +
4664 "%var = OpVariable %_ptr_uint Function\n" +
4665 "%2 = OpLoad %uint %var\n" +
4666 "%3 = OpUDiv %uint %2 %uint_3\n" +
4667 "%4 = OpIMul %uint %3 %uint_4\n" +
4668 "OpReturn\n" +
4669 "OpFunctionEnd\n",
4670 4, false),
4671 // Test case 15: merge vector fmul of fdiv
4672 // (x / {2,2}) * {4,4} = x * {2,2}
4673 InstructionFoldingCase<bool>(
4674 Header() +
4675 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4676 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
4677 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4678 "; CHECK: [[v2float_2_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_2]] [[float_2]]\n" +
4679 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
4680 "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_2_2]]\n" +
4681 "%main = OpFunction %void None %void_func\n" +
4682 "%main_lab = OpLabel\n" +
4683 "%var = OpVariable %_ptr_v2float Function\n" +
4684 "%2 = OpLoad %v2float %var\n" +
4685 "%3 = OpFDiv %v2float %2 %v2float_2_2\n" +
4686 "%4 = OpFMul %v2float %3 %v2float_4_4\n" +
4687 "OpReturn\n" +
4688 "OpFunctionEnd\n",
4689 4, true),
4690 // Test case 16: merge vector imul of snegate
4691 // (-x) * {2,2} = x * {-2,-2}
4692 InstructionFoldingCase<bool>(
4693 Header() +
4694 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4695 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
4696 "; CHECK: OpConstant [[int]] -2147483648\n" +
4697 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
4698 "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
4699 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
4700 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
4701 "%main = OpFunction %void None %void_func\n" +
4702 "%main_lab = OpLabel\n" +
4703 "%var = OpVariable %_ptr_v2int Function\n" +
4704 "%2 = OpLoad %v2int %var\n" +
4705 "%3 = OpSNegate %v2int %2\n" +
4706 "%4 = OpIMul %v2int %3 %v2int_2_2\n" +
4707 "OpReturn\n" +
4708 "OpFunctionEnd\n",
4709 4, true),
4710 // Test case 17: merge vector imul of snegate
4711 // {2,2} * (-x) = x * {-2,-2}
4712 InstructionFoldingCase<bool>(
4713 Header() +
4714 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4715 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
4716 "; CHECK: OpConstant [[int]] -2147483648\n" +
4717 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
4718 "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
4719 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
4720 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
4721 "%main = OpFunction %void None %void_func\n" +
4722 "%main_lab = OpLabel\n" +
4723 "%var = OpVariable %_ptr_v2int Function\n" +
4724 "%2 = OpLoad %v2int %var\n" +
4725 "%3 = OpSNegate %v2int %2\n" +
4726 "%4 = OpIMul %v2int %v2int_2_2 %3\n" +
4727 "OpReturn\n" +
4728 "OpFunctionEnd\n",
4729 4, true),
4730 // Test case 18: Fold OpVectorTimesScalar
4731 // {4,4} = OpVectorTimesScalar v2float {2,2} 2
4732 InstructionFoldingCase<bool>(
4733 Header() +
4734 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4735 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
4736 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
4737 "; CHECK: [[v2float_4_4:%\\w+]] = OpConstantComposite [[v2float]] [[float_4]] [[float_4]]\n" +
4738 "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_4_4]]\n" +
4739 "%main = OpFunction %void None %void_func\n" +
4740 "%main_lab = OpLabel\n" +
4741 "%2 = OpVectorTimesScalar %v2float %v2float_2_2 %float_2\n" +
4742 "OpReturn\n" +
4743 "OpFunctionEnd",
4744 2, true),
4745 // Test case 19: Fold OpVectorTimesScalar
4746 // {0,0} = OpVectorTimesScalar v2float v2float_null -1
4747 InstructionFoldingCase<bool>(
4748 Header() +
4749 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4750 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
4751 "; CHECK: [[v2float_null:%\\w+]] = OpConstantNull [[v2float]]\n" +
4752 "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_null]]\n" +
4753 "%main = OpFunction %void None %void_func\n" +
4754 "%main_lab = OpLabel\n" +
4755 "%2 = OpVectorTimesScalar %v2float %v2float_null %float_n1\n" +
4756 "OpReturn\n" +
4757 "OpFunctionEnd",
4758 2, true),
4759 // Test case 20: Fold OpVectorTimesScalar
4760 // {4,4} = OpVectorTimesScalar v2double {2,2} 2
4761 InstructionFoldingCase<bool>(
4762 Header() +
4763 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
4764 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
4765 "; CHECK: [[double_4:%\\w+]] = OpConstant [[double]] 4\n" +
4766 "; CHECK: [[v2double_4_4:%\\w+]] = OpConstantComposite [[v2double]] [[double_4]] [[double_4]]\n" +
4767 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_4_4]]\n" +
4768 "%main = OpFunction %void None %void_func\n" +
4769 "%main_lab = OpLabel\n" +
4770 "%2 = OpVectorTimesScalar %v2double %v2double_2_2 %double_2\n" +
4771 "OpReturn\n" +
4772 "OpFunctionEnd",
4773 2, true),
4774 // Test case 21: Fold OpVectorTimesScalar
4775 // {0,0} = OpVectorTimesScalar v2double {0,0} n
4776 InstructionFoldingCase<bool>(
4777 Header() +
4778 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
4779 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
4780 "; CHECK: {{%\\w+}} = OpConstant [[double]] 0\n" +
4781 "; CHECK: [[double_0:%\\w+]] = OpConstant [[double]] 0\n" +
4782 "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_0]] [[double_0]]\n" +
4783 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
4784 "%main = OpFunction %void None %void_func\n" +
4785 "%main_lab = OpLabel\n" +
4786 "%n = OpVariable %_ptr_double Function\n" +
4787 "%load = OpLoad %double %n\n" +
4788 "%2 = OpVectorTimesScalar %v2double %v2double_0_0 %load\n" +
4789 "OpReturn\n" +
4790 "OpFunctionEnd",
4791 2, true),
4792 // Test case 22: Fold OpVectorTimesScalar
4793 // {0,0} = OpVectorTimesScalar v2double n 0
4794 InstructionFoldingCase<bool>(
4795 Header() +
4796 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
4797 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
4798 "; CHECK: [[v2double_null:%\\w+]] = OpConstantNull [[v2double]]\n" +
4799 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_null]]\n" +
4800 "%main = OpFunction %void None %void_func\n" +
4801 "%main_lab = OpLabel\n" +
4802 "%n = OpVariable %_ptr_v2double Function\n" +
4803 "%load = OpLoad %v2double %n\n" +
4804 "%2 = OpVectorTimesScalar %v2double %load %double_0\n" +
4805 "OpReturn\n" +
4806 "OpFunctionEnd",
4807 2, true),
4808 // Test case 23: merge fmul of fdiv
4809 // x * (y / x) = y
4810 InstructionFoldingCase<bool>(
4811 Header() +
4812 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4813 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
4814 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
4815 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
4816 "%main = OpFunction %void None %void_func\n" +
4817 "%main_lab = OpLabel\n" +
4818 "%x = OpVariable %_ptr_float Function\n" +
4819 "%y = OpVariable %_ptr_float Function\n" +
4820 "%2 = OpLoad %float %x\n" +
4821 "%3 = OpLoad %float %y\n" +
4822 "%4 = OpFDiv %float %3 %2\n" +
4823 "%5 = OpFMul %float %2 %4\n" +
4824 "OpReturn\n" +
4825 "OpFunctionEnd\n",
4826 5, true),
4827 // Test case 24: merge fmul of fdiv
4828 // (y / x) * x = y
4829 InstructionFoldingCase<bool>(
4830 Header() +
4831 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4832 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
4833 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
4834 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
4835 "%main = OpFunction %void None %void_func\n" +
4836 "%main_lab = OpLabel\n" +
4837 "%x = OpVariable %_ptr_float Function\n" +
4838 "%y = OpVariable %_ptr_float Function\n" +
4839 "%2 = OpLoad %float %x\n" +
4840 "%3 = OpLoad %float %y\n" +
4841 "%4 = OpFDiv %float %3 %2\n" +
4842 "%5 = OpFMul %float %4 %2\n" +
4843 "OpReturn\n" +
4844 "OpFunctionEnd\n",
4845 5, true)
4846 ));
4847
4848 INSTANTIATE_TEST_CASE_P(MergeDivTest, MatchingInstructionFoldingTest,
4849 ::testing::Values(
4850 // Test case 0: merge consecutive fdiv
4851 // 4.0 / (2.0 / x) = 2.0 * x
4852 InstructionFoldingCase<bool>(
4853 Header() +
4854 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4855 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4856 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4857 "; CHECK: %4 = OpFMul [[float]] [[float_2]] [[ld]]\n" +
4858 "%main = OpFunction %void None %void_func\n" +
4859 "%main_lab = OpLabel\n" +
4860 "%var = OpVariable %_ptr_float Function\n" +
4861 "%2 = OpLoad %float %var\n" +
4862 "%3 = OpFDiv %float %float_2 %2\n" +
4863 "%4 = OpFDiv %float %float_4 %3\n" +
4864 "OpReturn\n" +
4865 "OpFunctionEnd\n",
4866 4, true),
4867 // Test case 1: merge consecutive fdiv
4868 // 4.0 / (x / 2.0) = 8.0 / x
4869 InstructionFoldingCase<bool>(
4870 Header() +
4871 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4872 "; CHECK: [[float_8:%\\w+]] = OpConstant [[float]] 8\n" +
4873 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4874 "; CHECK: %4 = OpFDiv [[float]] [[float_8]] [[ld]]\n" +
4875 "%main = OpFunction %void None %void_func\n" +
4876 "%main_lab = OpLabel\n" +
4877 "%var = OpVariable %_ptr_float Function\n" +
4878 "%2 = OpLoad %float %var\n" +
4879 "%3 = OpFDiv %float %2 %float_2\n" +
4880 "%4 = OpFDiv %float %float_4 %3\n" +
4881 "OpReturn\n" +
4882 "OpFunctionEnd\n",
4883 4, true),
4884 // Test case 2: merge consecutive fdiv
4885 // (4.0 / x) / 2.0 = 2.0 / x
4886 InstructionFoldingCase<bool>(
4887 Header() +
4888 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4889 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4890 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4891 "; CHECK: %4 = OpFDiv [[float]] [[float_2]] [[ld]]\n" +
4892 "%main = OpFunction %void None %void_func\n" +
4893 "%main_lab = OpLabel\n" +
4894 "%var = OpVariable %_ptr_float Function\n" +
4895 "%2 = OpLoad %float %var\n" +
4896 "%3 = OpFDiv %float %float_4 %2\n" +
4897 "%4 = OpFDiv %float %3 %float_2\n" +
4898 "OpReturn\n" +
4899 "OpFunctionEnd\n",
4900 4, true),
4901 // Test case 3: Do not merge consecutive sdiv
4902 // 4 / (2 / x)
4903 InstructionFoldingCase<bool>(
4904 Header() +
4905 "%main = OpFunction %void None %void_func\n" +
4906 "%main_lab = OpLabel\n" +
4907 "%var = OpVariable %_ptr_int Function\n" +
4908 "%2 = OpLoad %int %var\n" +
4909 "%3 = OpSDiv %int %int_2 %2\n" +
4910 "%4 = OpSDiv %int %int_4 %3\n" +
4911 "OpReturn\n" +
4912 "OpFunctionEnd\n",
4913 4, false),
4914 // Test case 4: Do not merge consecutive sdiv
4915 // 4 / (x / 2)
4916 InstructionFoldingCase<bool>(
4917 Header() +
4918 "%main = OpFunction %void None %void_func\n" +
4919 "%main_lab = OpLabel\n" +
4920 "%var = OpVariable %_ptr_int Function\n" +
4921 "%2 = OpLoad %int %var\n" +
4922 "%3 = OpSDiv %int %2 %int_2\n" +
4923 "%4 = OpSDiv %int %int_4 %3\n" +
4924 "OpReturn\n" +
4925 "OpFunctionEnd\n",
4926 4, false),
4927 // Test case 5: Do not merge consecutive sdiv
4928 // (4 / x) / 2
4929 InstructionFoldingCase<bool>(
4930 Header() +
4931 "%main = OpFunction %void None %void_func\n" +
4932 "%main_lab = OpLabel\n" +
4933 "%var = OpVariable %_ptr_int Function\n" +
4934 "%2 = OpLoad %int %var\n" +
4935 "%3 = OpSDiv %int %int_4 %2\n" +
4936 "%4 = OpSDiv %int %3 %int_2\n" +
4937 "OpReturn\n" +
4938 "OpFunctionEnd\n",
4939 4, false),
4940 // Test case 6: Do not merge consecutive sdiv
4941 // (x / 4) / 2
4942 InstructionFoldingCase<bool>(
4943 Header() +
4944 "%main = OpFunction %void None %void_func\n" +
4945 "%main_lab = OpLabel\n" +
4946 "%var = OpVariable %_ptr_int Function\n" +
4947 "%2 = OpLoad %int %var\n" +
4948 "%3 = OpSDiv %int %2 %int_4\n" +
4949 "%4 = OpSDiv %int %3 %int_2\n" +
4950 "OpReturn\n" +
4951 "OpFunctionEnd\n",
4952 4, false),
4953 // Test case 7: Do not merge sdiv of imul
4954 // 4 / (2 * x)
4955 InstructionFoldingCase<bool>(
4956 Header() +
4957 "%main = OpFunction %void None %void_func\n" +
4958 "%main_lab = OpLabel\n" +
4959 "%var = OpVariable %_ptr_int Function\n" +
4960 "%2 = OpLoad %int %var\n" +
4961 "%3 = OpIMul %int %int_2 %2\n" +
4962 "%4 = OpSDiv %int %int_4 %3\n" +
4963 "OpReturn\n" +
4964 "OpFunctionEnd\n",
4965 4, false),
4966 // Test case 8: Do not merge sdiv of imul
4967 // 4 / (x * 2)
4968 InstructionFoldingCase<bool>(
4969 Header() +
4970 "%main = OpFunction %void None %void_func\n" +
4971 "%main_lab = OpLabel\n" +
4972 "%var = OpVariable %_ptr_int Function\n" +
4973 "%2 = OpLoad %int %var\n" +
4974 "%3 = OpIMul %int %2 %int_2\n" +
4975 "%4 = OpSDiv %int %int_4 %3\n" +
4976 "OpReturn\n" +
4977 "OpFunctionEnd\n",
4978 4, false),
4979 // Test case 9: Do not merge sdiv of imul
4980 // (4 * x) / 2
4981 InstructionFoldingCase<bool>(
4982 Header() +
4983 "%main = OpFunction %void None %void_func\n" +
4984 "%main_lab = OpLabel\n" +
4985 "%var = OpVariable %_ptr_int Function\n" +
4986 "%2 = OpLoad %int %var\n" +
4987 "%3 = OpIMul %int %int_4 %2\n" +
4988 "%4 = OpSDiv %int %3 %int_2\n" +
4989 "OpReturn\n" +
4990 "OpFunctionEnd\n",
4991 4, false),
4992 // Test case 10: Do not merge sdiv of imul
4993 // (x * 4) / 2
4994 InstructionFoldingCase<bool>(
4995 Header() +
4996 "%main = OpFunction %void None %void_func\n" +
4997 "%main_lab = OpLabel\n" +
4998 "%var = OpVariable %_ptr_int Function\n" +
4999 "%2 = OpLoad %int %var\n" +
5000 "%3 = OpIMul %int %2 %int_4\n" +
5001 "%4 = OpSDiv %int %3 %int_2\n" +
5002 "OpReturn\n" +
5003 "OpFunctionEnd\n",
5004 4, false),
5005 // Test case 11: merge sdiv of snegate
5006 // (-x) / 2 = x / -2
5007 InstructionFoldingCase<bool>(
5008 Header() +
5009 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5010 "; CHECK: OpConstant [[int]] -2147483648\n" +
5011 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
5012 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5013 "; CHECK: %4 = OpSDiv [[int]] [[ld]] [[int_n2]]\n" +
5014 "%main = OpFunction %void None %void_func\n" +
5015 "%main_lab = OpLabel\n" +
5016 "%var = OpVariable %_ptr_int Function\n" +
5017 "%2 = OpLoad %int %var\n" +
5018 "%3 = OpSNegate %int %2\n" +
5019 "%4 = OpSDiv %int %3 %int_2\n" +
5020 "OpReturn\n" +
5021 "OpFunctionEnd\n",
5022 4, true),
5023 // Test case 12: merge sdiv of snegate
5024 // 2 / (-x) = -2 / x
5025 InstructionFoldingCase<bool>(
5026 Header() +
5027 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5028 "; CHECK: OpConstant [[int]] -2147483648\n" +
5029 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
5030 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5031 "; CHECK: %4 = OpSDiv [[int]] [[int_n2]] [[ld]]\n" +
5032 "%main = OpFunction %void None %void_func\n" +
5033 "%main_lab = OpLabel\n" +
5034 "%var = OpVariable %_ptr_int Function\n" +
5035 "%2 = OpLoad %int %var\n" +
5036 "%3 = OpSNegate %int %2\n" +
5037 "%4 = OpSDiv %int %int_2 %3\n" +
5038 "OpReturn\n" +
5039 "OpFunctionEnd\n",
5040 4, true),
5041 // Test case 13: Don't merge
5042 // (x / {null}) / {null}
5043 InstructionFoldingCase<bool>(
5044 Header() +
5045 "%main = OpFunction %void None %void_func\n" +
5046 "%main_lab = OpLabel\n" +
5047 "%var = OpVariable %_ptr_v2float Function\n" +
5048 "%2 = OpLoad %float %var\n" +
5049 "%3 = OpFDiv %float %2 %v2float_null\n" +
5050 "%4 = OpFDiv %float %3 %v2float_null\n" +
5051 "OpReturn\n" +
5052 "OpFunctionEnd\n",
5053 4, false),
5054 // Test case 14: merge fmul of fdiv
5055 // (y * x) / x = y
5056 InstructionFoldingCase<bool>(
5057 Header() +
5058 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5059 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
5060 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
5061 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
5062 "%main = OpFunction %void None %void_func\n" +
5063 "%main_lab = OpLabel\n" +
5064 "%x = OpVariable %_ptr_float Function\n" +
5065 "%y = OpVariable %_ptr_float Function\n" +
5066 "%2 = OpLoad %float %x\n" +
5067 "%3 = OpLoad %float %y\n" +
5068 "%4 = OpFMul %float %3 %2\n" +
5069 "%5 = OpFDiv %float %4 %2\n" +
5070 "OpReturn\n" +
5071 "OpFunctionEnd\n",
5072 5, true),
5073 // Test case 15: merge fmul of fdiv
5074 // (x * y) / x = y
5075 InstructionFoldingCase<bool>(
5076 Header() +
5077 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5078 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
5079 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
5080 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
5081 "%main = OpFunction %void None %void_func\n" +
5082 "%main_lab = OpLabel\n" +
5083 "%x = OpVariable %_ptr_float Function\n" +
5084 "%y = OpVariable %_ptr_float Function\n" +
5085 "%2 = OpLoad %float %x\n" +
5086 "%3 = OpLoad %float %y\n" +
5087 "%4 = OpFMul %float %2 %3\n" +
5088 "%5 = OpFDiv %float %4 %2\n" +
5089 "OpReturn\n" +
5090 "OpFunctionEnd\n",
5091 5, true)
5092 ));
5093
5094 INSTANTIATE_TEST_CASE_P(MergeAddTest, MatchingInstructionFoldingTest,
5095 ::testing::Values(
5096 // Test case 0: merge add of negate
5097 // (-x) + 2 = 2 - x
5098 InstructionFoldingCase<bool>(
5099 Header() +
5100 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5101 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5102 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5103 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
5104 "%main = OpFunction %void None %void_func\n" +
5105 "%main_lab = OpLabel\n" +
5106 "%var = OpVariable %_ptr_float Function\n" +
5107 "%2 = OpLoad %float %var\n" +
5108 "%3 = OpFNegate %float %2\n" +
5109 "%4 = OpFAdd %float %3 %float_2\n" +
5110 "OpReturn\n" +
5111 "OpFunctionEnd\n",
5112 4, true),
5113 // Test case 1: merge add of negate
5114 // 2 + (-x) = 2 - x
5115 InstructionFoldingCase<bool>(
5116 Header() +
5117 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5118 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5119 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5120 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
5121 "%main = OpFunction %void None %void_func\n" +
5122 "%main_lab = OpLabel\n" +
5123 "%var = OpVariable %_ptr_float Function\n" +
5124 "%2 = OpLoad %float %var\n" +
5125 "%3 = OpSNegate %float %2\n" +
5126 "%4 = OpIAdd %float %float_2 %3\n" +
5127 "OpReturn\n" +
5128 "OpFunctionEnd\n",
5129 4, true),
5130 // Test case 2: merge add of negate
5131 // (-x) + 2 = 2 - x
5132 InstructionFoldingCase<bool>(
5133 Header() +
5134 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5135 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5136 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5137 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
5138 "%main = OpFunction %void None %void_func\n" +
5139 "%main_lab = OpLabel\n" +
5140 "%var = OpVariable %_ptr_long Function\n" +
5141 "%2 = OpLoad %long %var\n" +
5142 "%3 = OpSNegate %long %2\n" +
5143 "%4 = OpIAdd %long %3 %long_2\n" +
5144 "OpReturn\n" +
5145 "OpFunctionEnd\n",
5146 4, true),
5147 // Test case 3: merge add of negate
5148 // 2 + (-x) = 2 - x
5149 InstructionFoldingCase<bool>(
5150 Header() +
5151 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5152 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5153 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5154 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
5155 "%main = OpFunction %void None %void_func\n" +
5156 "%main_lab = OpLabel\n" +
5157 "%var = OpVariable %_ptr_long Function\n" +
5158 "%2 = OpLoad %long %var\n" +
5159 "%3 = OpSNegate %long %2\n" +
5160 "%4 = OpIAdd %long %long_2 %3\n" +
5161 "OpReturn\n" +
5162 "OpFunctionEnd\n",
5163 4, true),
5164 // Test case 4: merge add of subtract
5165 // (x - 1) + 2 = x + 1
5166 InstructionFoldingCase<bool>(
5167 Header() +
5168 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5169 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
5170 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5171 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
5172 "%main = OpFunction %void None %void_func\n" +
5173 "%main_lab = OpLabel\n" +
5174 "%var = OpVariable %_ptr_float Function\n" +
5175 "%2 = OpLoad %float %var\n" +
5176 "%3 = OpFSub %float %2 %float_1\n" +
5177 "%4 = OpFAdd %float %3 %float_2\n" +
5178 "OpReturn\n" +
5179 "OpFunctionEnd\n",
5180 4, true),
5181 // Test case 5: merge add of subtract
5182 // (1 - x) + 2 = 3 - x
5183 InstructionFoldingCase<bool>(
5184 Header() +
5185 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5186 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5187 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5188 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
5189 "%main = OpFunction %void None %void_func\n" +
5190 "%main_lab = OpLabel\n" +
5191 "%var = OpVariable %_ptr_float Function\n" +
5192 "%2 = OpLoad %float %var\n" +
5193 "%3 = OpFSub %float %float_1 %2\n" +
5194 "%4 = OpFAdd %float %3 %float_2\n" +
5195 "OpReturn\n" +
5196 "OpFunctionEnd\n",
5197 4, true),
5198 // Test case 6: merge add of subtract
5199 // 2 + (x - 1) = x + 1
5200 InstructionFoldingCase<bool>(
5201 Header() +
5202 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5203 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
5204 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5205 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
5206 "%main = OpFunction %void None %void_func\n" +
5207 "%main_lab = OpLabel\n" +
5208 "%var = OpVariable %_ptr_float Function\n" +
5209 "%2 = OpLoad %float %var\n" +
5210 "%3 = OpFSub %float %2 %float_1\n" +
5211 "%4 = OpFAdd %float %float_2 %3\n" +
5212 "OpReturn\n" +
5213 "OpFunctionEnd\n",
5214 4, true),
5215 // Test case 7: merge add of subtract
5216 // 2 + (1 - x) = 3 - x
5217 InstructionFoldingCase<bool>(
5218 Header() +
5219 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5220 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5221 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5222 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
5223 "%main = OpFunction %void None %void_func\n" +
5224 "%main_lab = OpLabel\n" +
5225 "%var = OpVariable %_ptr_float Function\n" +
5226 "%2 = OpLoad %float %var\n" +
5227 "%3 = OpFSub %float %float_1 %2\n" +
5228 "%4 = OpFAdd %float %float_2 %3\n" +
5229 "OpReturn\n" +
5230 "OpFunctionEnd\n",
5231 4, true),
5232 // Test case 8: merge add of add
5233 // (x + 1) + 2 = x + 3
5234 InstructionFoldingCase<bool>(
5235 Header() +
5236 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5237 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5238 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5239 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
5240 "%main = OpFunction %void None %void_func\n" +
5241 "%main_lab = OpLabel\n" +
5242 "%var = OpVariable %_ptr_float Function\n" +
5243 "%2 = OpLoad %float %var\n" +
5244 "%3 = OpFAdd %float %2 %float_1\n" +
5245 "%4 = OpFAdd %float %3 %float_2\n" +
5246 "OpReturn\n" +
5247 "OpFunctionEnd\n",
5248 4, true),
5249 // Test case 9: merge add of add
5250 // (1 + x) + 2 = 3 + x
5251 InstructionFoldingCase<bool>(
5252 Header() +
5253 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5254 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5255 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5256 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
5257 "%main = OpFunction %void None %void_func\n" +
5258 "%main_lab = OpLabel\n" +
5259 "%var = OpVariable %_ptr_float Function\n" +
5260 "%2 = OpLoad %float %var\n" +
5261 "%3 = OpFAdd %float %float_1 %2\n" +
5262 "%4 = OpFAdd %float %3 %float_2\n" +
5263 "OpReturn\n" +
5264 "OpFunctionEnd\n",
5265 4, true),
5266 // Test case 10: merge add of add
5267 // 2 + (x + 1) = x + 1
5268 InstructionFoldingCase<bool>(
5269 Header() +
5270 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5271 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5272 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5273 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
5274 "%main = OpFunction %void None %void_func\n" +
5275 "%main_lab = OpLabel\n" +
5276 "%var = OpVariable %_ptr_float Function\n" +
5277 "%2 = OpLoad %float %var\n" +
5278 "%3 = OpFAdd %float %2 %float_1\n" +
5279 "%4 = OpFAdd %float %float_2 %3\n" +
5280 "OpReturn\n" +
5281 "OpFunctionEnd\n",
5282 4, true),
5283 // Test case 11: merge add of add
5284 // 2 + (1 + x) = 3 - x
5285 InstructionFoldingCase<bool>(
5286 Header() +
5287 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5288 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5289 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5290 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
5291 "%main = OpFunction %void None %void_func\n" +
5292 "%main_lab = OpLabel\n" +
5293 "%var = OpVariable %_ptr_float Function\n" +
5294 "%2 = OpLoad %float %var\n" +
5295 "%3 = OpFAdd %float %float_1 %2\n" +
5296 "%4 = OpFAdd %float %float_2 %3\n" +
5297 "OpReturn\n" +
5298 "OpFunctionEnd\n",
5299 4, true)
5300 ));
5301
5302 INSTANTIATE_TEST_CASE_P(MergeSubTest, MatchingInstructionFoldingTest,
5303 ::testing::Values(
5304 // Test case 0: merge sub of negate
5305 // (-x) - 2 = -2 - x
5306 InstructionFoldingCase<bool>(
5307 Header() +
5308 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5309 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
5310 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5311 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
5312 "%main = OpFunction %void None %void_func\n" +
5313 "%main_lab = OpLabel\n" +
5314 "%var = OpVariable %_ptr_float Function\n" +
5315 "%2 = OpLoad %float %var\n" +
5316 "%3 = OpFNegate %float %2\n" +
5317 "%4 = OpFSub %float %3 %float_2\n" +
5318 "OpReturn\n" +
5319 "OpFunctionEnd\n",
5320 4, true),
5321 // Test case 1: merge sub of negate
5322 // 2 - (-x) = x + 2
5323 InstructionFoldingCase<bool>(
5324 Header() +
5325 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5326 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5327 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5328 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_2]]\n" +
5329 "%main = OpFunction %void None %void_func\n" +
5330 "%main_lab = OpLabel\n" +
5331 "%var = OpVariable %_ptr_float Function\n" +
5332 "%2 = OpLoad %float %var\n" +
5333 "%3 = OpFNegate %float %2\n" +
5334 "%4 = OpFSub %float %float_2 %3\n" +
5335 "OpReturn\n" +
5336 "OpFunctionEnd\n",
5337 4, true),
5338 // Test case 2: merge sub of negate
5339 // (-x) - 2 = -2 - x
5340 InstructionFoldingCase<bool>(
5341 Header() +
5342 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5343 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2\n" +
5344 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5345 "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
5346 "%main = OpFunction %void None %void_func\n" +
5347 "%main_lab = OpLabel\n" +
5348 "%var = OpVariable %_ptr_long Function\n" +
5349 "%2 = OpLoad %long %var\n" +
5350 "%3 = OpSNegate %long %2\n" +
5351 "%4 = OpISub %long %3 %long_2\n" +
5352 "OpReturn\n" +
5353 "OpFunctionEnd\n",
5354 4, true),
5355 // Test case 3: merge sub of negate
5356 // 2 - (-x) = x + 2
5357 InstructionFoldingCase<bool>(
5358 Header() +
5359 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5360 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5361 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5362 "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_2]]\n" +
5363 "%main = OpFunction %void None %void_func\n" +
5364 "%main_lab = OpLabel\n" +
5365 "%var = OpVariable %_ptr_long Function\n" +
5366 "%2 = OpLoad %long %var\n" +
5367 "%3 = OpSNegate %long %2\n" +
5368 "%4 = OpISub %long %long_2 %3\n" +
5369 "OpReturn\n" +
5370 "OpFunctionEnd\n",
5371 4, true),
5372 // Test case 4: merge add of subtract
5373 // (x + 2) - 1 = x + 1
5374 InstructionFoldingCase<bool>(
5375 Header() +
5376 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5377 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
5378 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5379 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
5380 "%main = OpFunction %void None %void_func\n" +
5381 "%main_lab = OpLabel\n" +
5382 "%var = OpVariable %_ptr_float Function\n" +
5383 "%2 = OpLoad %float %var\n" +
5384 "%3 = OpFAdd %float %2 %float_2\n" +
5385 "%4 = OpFSub %float %3 %float_1\n" +
5386 "OpReturn\n" +
5387 "OpFunctionEnd\n",
5388 4, true),
5389 // Test case 5: merge add of subtract
5390 // (2 + x) - 1 = x + 1
5391 InstructionFoldingCase<bool>(
5392 Header() +
5393 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5394 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
5395 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5396 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
5397 "%main = OpFunction %void None %void_func\n" +
5398 "%main_lab = OpLabel\n" +
5399 "%var = OpVariable %_ptr_float Function\n" +
5400 "%2 = OpLoad %float %var\n" +
5401 "%3 = OpFAdd %float %float_2 %2\n" +
5402 "%4 = OpFSub %float %3 %float_1\n" +
5403 "OpReturn\n" +
5404 "OpFunctionEnd\n",
5405 4, true),
5406 // Test case 6: merge add of subtract
5407 // 2 - (x + 1) = 1 - x
5408 InstructionFoldingCase<bool>(
5409 Header() +
5410 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5411 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
5412 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5413 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
5414 "%main = OpFunction %void None %void_func\n" +
5415 "%main_lab = OpLabel\n" +
5416 "%var = OpVariable %_ptr_float Function\n" +
5417 "%2 = OpLoad %float %var\n" +
5418 "%3 = OpFAdd %float %2 %float_1\n" +
5419 "%4 = OpFSub %float %float_2 %3\n" +
5420 "OpReturn\n" +
5421 "OpFunctionEnd\n",
5422 4, true),
5423 // Test case 7: merge add of subtract
5424 // 2 - (1 + x) = 1 - x
5425 InstructionFoldingCase<bool>(
5426 Header() +
5427 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5428 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
5429 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5430 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
5431 "%main = OpFunction %void None %void_func\n" +
5432 "%main_lab = OpLabel\n" +
5433 "%var = OpVariable %_ptr_float Function\n" +
5434 "%2 = OpLoad %float %var\n" +
5435 "%3 = OpFAdd %float %float_1 %2\n" +
5436 "%4 = OpFSub %float %float_2 %3\n" +
5437 "OpReturn\n" +
5438 "OpFunctionEnd\n",
5439 4, true),
5440 // Test case 8: merge subtract of subtract
5441 // (x - 2) - 1 = x - 3
5442 InstructionFoldingCase<bool>(
5443 Header() +
5444 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5445 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5446 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5447 "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_3]]\n" +
5448 "%main = OpFunction %void None %void_func\n" +
5449 "%main_lab = OpLabel\n" +
5450 "%var = OpVariable %_ptr_float Function\n" +
5451 "%2 = OpLoad %float %var\n" +
5452 "%3 = OpFSub %float %2 %float_2\n" +
5453 "%4 = OpFSub %float %3 %float_1\n" +
5454 "OpReturn\n" +
5455 "OpFunctionEnd\n",
5456 4, true),
5457 // Test case 9: merge subtract of subtract
5458 // (2 - x) - 1 = 1 - x
5459 InstructionFoldingCase<bool>(
5460 Header() +
5461 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5462 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
5463 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5464 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
5465 "%main = OpFunction %void None %void_func\n" +
5466 "%main_lab = OpLabel\n" +
5467 "%var = OpVariable %_ptr_float Function\n" +
5468 "%2 = OpLoad %float %var\n" +
5469 "%3 = OpFSub %float %float_2 %2\n" +
5470 "%4 = OpFSub %float %3 %float_1\n" +
5471 "OpReturn\n" +
5472 "OpFunctionEnd\n",
5473 4, true),
5474 // Test case 10: merge subtract of subtract
5475 // 2 - (x - 1) = 3 - x
5476 InstructionFoldingCase<bool>(
5477 Header() +
5478 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5479 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5480 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5481 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
5482 "%main = OpFunction %void None %void_func\n" +
5483 "%main_lab = OpLabel\n" +
5484 "%var = OpVariable %_ptr_float Function\n" +
5485 "%2 = OpLoad %float %var\n" +
5486 "%3 = OpFSub %float %2 %float_1\n" +
5487 "%4 = OpFSub %float %float_2 %3\n" +
5488 "OpReturn\n" +
5489 "OpFunctionEnd\n",
5490 4, true),
5491 // Test case 11: merge subtract of subtract
5492 // 1 - (2 - x) = x + (-1)
5493 InstructionFoldingCase<bool>(
5494 Header() +
5495 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5496 "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
5497 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5498 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_n1]]\n" +
5499 "%main = OpFunction %void None %void_func\n" +
5500 "%main_lab = OpLabel\n" +
5501 "%var = OpVariable %_ptr_float Function\n" +
5502 "%2 = OpLoad %float %var\n" +
5503 "%3 = OpFSub %float %float_2 %2\n" +
5504 "%4 = OpFSub %float %float_1 %3\n" +
5505 "OpReturn\n" +
5506 "OpFunctionEnd\n",
5507 4, true),
5508 // Test case 12: merge subtract of subtract
5509 // 2 - (1 - x) = x + 1
5510 InstructionFoldingCase<bool>(
5511 Header() +
5512 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5513 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
5514 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5515 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
5516 "%main = OpFunction %void None %void_func\n" +
5517 "%main_lab = OpLabel\n" +
5518 "%var = OpVariable %_ptr_float Function\n" +
5519 "%2 = OpLoad %float %var\n" +
5520 "%3 = OpFSub %float %float_1 %2\n" +
5521 "%4 = OpFSub %float %float_2 %3\n" +
5522 "OpReturn\n" +
5523 "OpFunctionEnd\n",
5524 4, true)
5525 ));
5526
5527 INSTANTIATE_TEST_CASE_P(SelectFoldingTest, MatchingInstructionFoldingTest,
5528 ::testing::Values(
5529 // Test case 0: Fold select with the same values for both sides
5530 InstructionFoldingCase<bool>(
5531 Header() +
5532 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5533 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
5534 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
5535 "%main = OpFunction %void None %void_func\n" +
5536 "%main_lab = OpLabel\n" +
5537 "%n = OpVariable %_ptr_bool Function\n" +
5538 "%load = OpLoad %bool %n\n" +
5539 "%2 = OpSelect %int %load %100 %100\n" +
5540 "OpReturn\n" +
5541 "OpFunctionEnd",
5542 2, true),
5543 // Test case 1: Fold select true to left side
5544 InstructionFoldingCase<bool>(
5545 Header() +
5546 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5547 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
5548 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
5549 "%main = OpFunction %void None %void_func\n" +
5550 "%main_lab = OpLabel\n" +
5551 "%n = OpVariable %_ptr_int Function\n" +
5552 "%load = OpLoad %bool %n\n" +
5553 "%2 = OpSelect %int %true %100 %n\n" +
5554 "OpReturn\n" +
5555 "OpFunctionEnd",
5556 2, true),
5557 // Test case 2: Fold select false to right side
5558 InstructionFoldingCase<bool>(
5559 Header() +
5560 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5561 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
5562 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
5563 "%main = OpFunction %void None %void_func\n" +
5564 "%main_lab = OpLabel\n" +
5565 "%n = OpVariable %_ptr_int Function\n" +
5566 "%load = OpLoad %bool %n\n" +
5567 "%2 = OpSelect %int %false %n %100\n" +
5568 "OpReturn\n" +
5569 "OpFunctionEnd",
5570 2, true),
5571 // Test case 3: Fold select null to right side
5572 InstructionFoldingCase<bool>(
5573 Header() +
5574 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5575 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
5576 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
5577 "%main = OpFunction %void None %void_func\n" +
5578 "%main_lab = OpLabel\n" +
5579 "%n = OpVariable %_ptr_int Function\n" +
5580 "%load = OpLoad %int %n\n" +
5581 "%2 = OpSelect %int %bool_null %load %100\n" +
5582 "OpReturn\n" +
5583 "OpFunctionEnd",
5584 2, true),
5585 // Test case 4: vector null
5586 InstructionFoldingCase<bool>(
5587 Header() +
5588 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5589 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
5590 "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
5591 "; CHECK: [[v2int2_2:%\\w+]] = OpConstantComposite [[v2int]] [[int2]] [[int2]]\n" +
5592 "; CHECK: %2 = OpCopyObject [[v2int]] [[v2int2_2]]\n" +
5593 "%main = OpFunction %void None %void_func\n" +
5594 "%main_lab = OpLabel\n" +
5595 "%n = OpVariable %_ptr_v2int Function\n" +
5596 "%load = OpLoad %v2int %n\n" +
5597 "%2 = OpSelect %v2int %v2bool_null %load %v2int_2_2\n" +
5598 "OpReturn\n" +
5599 "OpFunctionEnd",
5600 2, true),
5601 // Test case 5: vector select
5602 InstructionFoldingCase<bool>(
5603 Header() +
5604 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5605 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
5606 "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 0 3\n" +
5607 "%main = OpFunction %void None %void_func\n" +
5608 "%main_lab = OpLabel\n" +
5609 "%m = OpVariable %_ptr_v2int Function\n" +
5610 "%n = OpVariable %_ptr_v2int Function\n" +
5611 "%2 = OpLoad %v2int %n\n" +
5612 "%3 = OpLoad %v2int %n\n" +
5613 "%4 = OpSelect %v2int %v2bool_true_false %2 %3\n" +
5614 "OpReturn\n" +
5615 "OpFunctionEnd",
5616 4, true),
5617 // Test case 6: vector select
5618 InstructionFoldingCase<bool>(
5619 Header() +
5620 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5621 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
5622 "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 2 1\n" +
5623 "%main = OpFunction %void None %void_func\n" +
5624 "%main_lab = OpLabel\n" +
5625 "%m = OpVariable %_ptr_v2int Function\n" +
5626 "%n = OpVariable %_ptr_v2int Function\n" +
5627 "%2 = OpLoad %v2int %n\n" +
5628 "%3 = OpLoad %v2int %n\n" +
5629 "%4 = OpSelect %v2int %v2bool_false_true %2 %3\n" +
5630 "OpReturn\n" +
5631 "OpFunctionEnd",
5632 4, true)
5633 ));
5634
5635 INSTANTIATE_TEST_CASE_P(CompositeExtractMatchingTest, MatchingInstructionFoldingTest,
5636 ::testing::Values(
5637 // Test case 0: Extracting from result of consecutive shuffles of differing
5638 // size.
5639 InstructionFoldingCase<bool>(
5640 Header() +
5641 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5642 "; CHECK: %5 = OpCompositeExtract [[int]] %2 2\n" +
5643 "%main = OpFunction %void None %void_func\n" +
5644 "%main_lab = OpLabel\n" +
5645 "%n = OpVariable %_ptr_v4int Function\n" +
5646 "%2 = OpLoad %v4int %n\n" +
5647 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
5648 "%4 = OpVectorShuffle %v4int %2 %3 0 4 2 5\n" +
5649 "%5 = OpCompositeExtract %int %4 1\n" +
5650 "OpReturn\n" +
5651 "OpFunctionEnd",
5652 5, true),
5653 // Test case 1: Extracting from result of vector shuffle of differing
5654 // input and result sizes.
5655 InstructionFoldingCase<bool>(
5656 Header() +
5657 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5658 "; CHECK: %4 = OpCompositeExtract [[int]] %2 2\n" +
5659 "%main = OpFunction %void None %void_func\n" +
5660 "%main_lab = OpLabel\n" +
5661 "%n = OpVariable %_ptr_v4int Function\n" +
5662 "%2 = OpLoad %v4int %n\n" +
5663 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
5664 "%4 = OpCompositeExtract %int %3 0\n" +
5665 "OpReturn\n" +
5666 "OpFunctionEnd",
5667 4, true),
5668 // Test case 2: Extracting from result of vector shuffle of differing
5669 // input and result sizes.
5670 InstructionFoldingCase<bool>(
5671 Header() +
5672 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5673 "; CHECK: %4 = OpCompositeExtract [[int]] %2 3\n" +
5674 "%main = OpFunction %void None %void_func\n" +
5675 "%main_lab = OpLabel\n" +
5676 "%n = OpVariable %_ptr_v4int Function\n" +
5677 "%2 = OpLoad %v4int %n\n" +
5678 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
5679 "%4 = OpCompositeExtract %int %3 1\n" +
5680 "OpReturn\n" +
5681 "OpFunctionEnd",
5682 4, true),
5683 // Test case 3: Using fmix feeding extract with a 1 in the a position.
5684 InstructionFoldingCase<bool>(
5685 Header() +
5686 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5687 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
5688 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
5689 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
5690 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
5691 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[n]]\n" +
5692 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 1\n" +
5693 "%main = OpFunction %void None %void_func\n" +
5694 "%main_lab = OpLabel\n" +
5695 "%m = OpVariable %_ptr_v4double Function\n" +
5696 "%n = OpVariable %_ptr_v4double Function\n" +
5697 "%2 = OpLoad %v4double %m\n" +
5698 "%3 = OpLoad %v4double %n\n" +
5699 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
5700 "%5 = OpCompositeExtract %double %4 1\n" +
5701 "OpReturn\n" +
5702 "OpFunctionEnd",
5703 5, true),
5704 // Test case 4: Using fmix feeding extract with a 0 in the a position.
5705 InstructionFoldingCase<bool>(
5706 Header() +
5707 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5708 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
5709 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
5710 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
5711 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
5712 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
5713 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 2\n" +
5714 "%main = OpFunction %void None %void_func\n" +
5715 "%main_lab = OpLabel\n" +
5716 "%m = OpVariable %_ptr_v4double Function\n" +
5717 "%n = OpVariable %_ptr_v4double Function\n" +
5718 "%2 = OpLoad %v4double %m\n" +
5719 "%3 = OpLoad %v4double %n\n" +
5720 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
5721 "%5 = OpCompositeExtract %double %4 2\n" +
5722 "OpReturn\n" +
5723 "OpFunctionEnd",
5724 5, true),
5725 // Test case 5: Using fmix feeding extract with a null for the alpha
5726 InstructionFoldingCase<bool>(
5727 Header() +
5728 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5729 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
5730 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
5731 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
5732 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
5733 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
5734 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 0\n" +
5735 "%main = OpFunction %void None %void_func\n" +
5736 "%main_lab = OpLabel\n" +
5737 "%m = OpVariable %_ptr_v4double Function\n" +
5738 "%n = OpVariable %_ptr_v4double Function\n" +
5739 "%2 = OpLoad %v4double %m\n" +
5740 "%3 = OpLoad %v4double %n\n" +
5741 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_null\n" +
5742 "%5 = OpCompositeExtract %double %4 0\n" +
5743 "OpReturn\n" +
5744 "OpFunctionEnd",
5745 5, true),
5746 // Test case 6: Don't fold: Using fmix feeding extract with 0.5 in the a
5747 // position.
5748 InstructionFoldingCase<bool>(
5749 Header() +
5750 "%main = OpFunction %void None %void_func\n" +
5751 "%main_lab = OpLabel\n" +
5752 "%m = OpVariable %_ptr_v4double Function\n" +
5753 "%n = OpVariable %_ptr_v4double Function\n" +
5754 "%2 = OpLoad %v4double %m\n" +
5755 "%3 = OpLoad %v4double %n\n" +
5756 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_1_1_1_0p5\n" +
5757 "%5 = OpCompositeExtract %double %4 3\n" +
5758 "OpReturn\n" +
5759 "OpFunctionEnd",
5760 5, false),
5761 // Test case 7: Extracting the undefined literal value from a vector
5762 // shuffle.
5763 InstructionFoldingCase<bool>(
5764 Header() +
5765 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5766 "; CHECK: %4 = OpUndef [[int]]\n" +
5767 "%main = OpFunction %void None %void_func\n" +
5768 "%main_lab = OpLabel\n" +
5769 "%n = OpVariable %_ptr_v4int Function\n" +
5770 "%2 = OpLoad %v4int %n\n" +
5771 "%3 = OpVectorShuffle %v2int %2 %2 2 4294967295\n" +
5772 "%4 = OpCompositeExtract %int %3 1\n" +
5773 "OpReturn\n" +
5774 "OpFunctionEnd",
5775 4, true)
5776 ));
5777
5778 INSTANTIATE_TEST_CASE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
5779 ::testing::Values(
5780 // Test case 0: Using OpDot to extract last element.
5781 InstructionFoldingCase<bool>(
5782 Header() +
5783 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5784 "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
5785 "%main = OpFunction %void None %void_func\n" +
5786 "%main_lab = OpLabel\n" +
5787 "%n = OpVariable %_ptr_v4float Function\n" +
5788 "%2 = OpLoad %v4float %n\n" +
5789 "%3 = OpDot %float %2 %v4float_0_0_0_1\n" +
5790 "OpReturn\n" +
5791 "OpFunctionEnd",
5792 3, true),
5793 // Test case 1: Using OpDot to extract last element.
5794 InstructionFoldingCase<bool>(
5795 Header() +
5796 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5797 "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
5798 "%main = OpFunction %void None %void_func\n" +
5799 "%main_lab = OpLabel\n" +
5800 "%n = OpVariable %_ptr_v4float Function\n" +
5801 "%2 = OpLoad %v4float %n\n" +
5802 "%3 = OpDot %float %v4float_0_0_0_1 %2\n" +
5803 "OpReturn\n" +
5804 "OpFunctionEnd",
5805 3, true),
5806 // Test case 2: Using OpDot to extract second element.
5807 InstructionFoldingCase<bool>(
5808 Header() +
5809 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5810 "; CHECK: %3 = OpCompositeExtract [[float]] %2 1\n" +
5811 "%main = OpFunction %void None %void_func\n" +
5812 "%main_lab = OpLabel\n" +
5813 "%n = OpVariable %_ptr_v4float Function\n" +
5814 "%2 = OpLoad %v4float %n\n" +
5815 "%3 = OpDot %float %v4float_0_1_0_0 %2\n" +
5816 "OpReturn\n" +
5817 "OpFunctionEnd",
5818 3, true),
5819 // Test case 3: Using OpDot to extract last element.
5820 InstructionFoldingCase<bool>(
5821 Header() +
5822 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5823 "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
5824 "%main = OpFunction %void None %void_func\n" +
5825 "%main_lab = OpLabel\n" +
5826 "%n = OpVariable %_ptr_v4double Function\n" +
5827 "%2 = OpLoad %v4double %n\n" +
5828 "%3 = OpDot %double %2 %v4double_0_0_0_1\n" +
5829 "OpReturn\n" +
5830 "OpFunctionEnd",
5831 3, true),
5832 // Test case 4: Using OpDot to extract last element.
5833 InstructionFoldingCase<bool>(
5834 Header() +
5835 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5836 "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
5837 "%main = OpFunction %void None %void_func\n" +
5838 "%main_lab = OpLabel\n" +
5839 "%n = OpVariable %_ptr_v4double Function\n" +
5840 "%2 = OpLoad %v4double %n\n" +
5841 "%3 = OpDot %double %v4double_0_0_0_1 %2\n" +
5842 "OpReturn\n" +
5843 "OpFunctionEnd",
5844 3, true),
5845 // Test case 5: Using OpDot to extract second element.
5846 InstructionFoldingCase<bool>(
5847 Header() +
5848 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5849 "; CHECK: %3 = OpCompositeExtract [[double]] %2 1\n" +
5850 "%main = OpFunction %void None %void_func\n" +
5851 "%main_lab = OpLabel\n" +
5852 "%n = OpVariable %_ptr_v4double Function\n" +
5853 "%2 = OpLoad %v4double %n\n" +
5854 "%3 = OpDot %double %v4double_0_1_0_0 %2\n" +
5855 "OpReturn\n" +
5856 "OpFunctionEnd",
5857 3, true)
5858 ));
5859
5860 using MatchingInstructionWithNoResultFoldingTest =
5861 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
5862
5863 // Test folding instructions that do not have a result. The instruction
5864 // that will be folded is the last instruction before the return. If there
5865 // are multiple returns, there is not guarentee which one is used.
TEST_P(MatchingInstructionWithNoResultFoldingTest,Case)5866 TEST_P(MatchingInstructionWithNoResultFoldingTest, Case) {
5867 const auto& tc = GetParam();
5868
5869 // Build module.
5870 std::unique_ptr<IRContext> context =
5871 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
5872 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5873 ASSERT_NE(nullptr, context);
5874
5875 // Fold the instruction to test.
5876 Instruction* inst = nullptr;
5877 Function* func = &*context->module()->begin();
5878 for (auto& bb : *func) {
5879 Instruction* terminator = bb.terminator();
5880 if (terminator->IsReturnOrAbort()) {
5881 inst = terminator->PreviousNode();
5882 break;
5883 }
5884 }
5885 assert(inst && "Invalid test. Could not find instruction to fold.");
5886 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
5887 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
5888 EXPECT_EQ(succeeded, tc.expected_result);
5889 if (succeeded) {
5890 Match(tc.test_body, context.get());
5891 }
5892 }
5893
5894 INSTANTIATE_TEST_CASE_P(StoreMatchingTest, MatchingInstructionWithNoResultFoldingTest,
5895 ::testing::Values(
5896 // Test case 0: Remove store of undef.
5897 InstructionFoldingCase<bool>(
5898 Header() +
5899 "; CHECK: OpLabel\n" +
5900 "; CHECK-NOT: OpStore\n" +
5901 "; CHECK: OpReturn\n" +
5902 "%main = OpFunction %void None %void_func\n" +
5903 "%main_lab = OpLabel\n" +
5904 "%n = OpVariable %_ptr_v4double Function\n" +
5905 "%undef = OpUndef %v4double\n" +
5906 "OpStore %n %undef\n" +
5907 "OpReturn\n" +
5908 "OpFunctionEnd",
5909 0 /* OpStore */, true),
5910 // Test case 1: Keep volatile store.
5911 InstructionFoldingCase<bool>(
5912 Header() +
5913 "%main = OpFunction %void None %void_func\n" +
5914 "%main_lab = OpLabel\n" +
5915 "%n = OpVariable %_ptr_v4double Function\n" +
5916 "%undef = OpUndef %v4double\n" +
5917 "OpStore %n %undef Volatile\n" +
5918 "OpReturn\n" +
5919 "OpFunctionEnd",
5920 0 /* OpStore */, false)
5921 ));
5922
5923 INSTANTIATE_TEST_CASE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoResultFoldingTest,
5924 ::testing::Values(
5925 // Test case 0: Basic test 1
5926 InstructionFoldingCase<bool>(
5927 Header() +
5928 "; CHECK: OpVectorShuffle\n" +
5929 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 3 6 7\n" +
5930 "; CHECK: OpReturn\n" +
5931 "%main = OpFunction %void None %void_func\n" +
5932 "%main_lab = OpLabel\n" +
5933 "%2 = OpVariable %_ptr_v4double Function\n" +
5934 "%3 = OpVariable %_ptr_v4double Function\n" +
5935 "%4 = OpVariable %_ptr_v4double Function\n" +
5936 "%5 = OpLoad %v4double %2\n" +
5937 "%6 = OpLoad %v4double %3\n" +
5938 "%7 = OpLoad %v4double %4\n" +
5939 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
5940 "%9 = OpVectorShuffle %v4double %7 %8 2 3 4 5\n" +
5941 "OpReturn\n" +
5942 "OpFunctionEnd",
5943 9, true),
5944 // Test case 1: Basic test 2
5945 InstructionFoldingCase<bool>(
5946 Header() +
5947 "; CHECK: OpVectorShuffle\n" +
5948 "; CHECK: OpVectorShuffle {{%\\w+}} %6 %7 0 1 4 5\n" +
5949 "; CHECK: OpReturn\n" +
5950 "%main = OpFunction %void None %void_func\n" +
5951 "%main_lab = OpLabel\n" +
5952 "%2 = OpVariable %_ptr_v4double Function\n" +
5953 "%3 = OpVariable %_ptr_v4double Function\n" +
5954 "%4 = OpVariable %_ptr_v4double Function\n" +
5955 "%5 = OpLoad %v4double %2\n" +
5956 "%6 = OpLoad %v4double %3\n" +
5957 "%7 = OpLoad %v4double %4\n" +
5958 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
5959 "%9 = OpVectorShuffle %v4double %8 %7 2 3 4 5\n" +
5960 "OpReturn\n" +
5961 "OpFunctionEnd",
5962 9, true),
5963 // Test case 2: Basic test 3
5964 InstructionFoldingCase<bool>(
5965 Header() +
5966 "; CHECK: OpVectorShuffle\n" +
5967 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 2 4 5\n" +
5968 "; CHECK: OpReturn\n" +
5969 "%main = OpFunction %void None %void_func\n" +
5970 "%main_lab = OpLabel\n" +
5971 "%2 = OpVariable %_ptr_v4double Function\n" +
5972 "%3 = OpVariable %_ptr_v4double Function\n" +
5973 "%4 = OpVariable %_ptr_v4double Function\n" +
5974 "%5 = OpLoad %v4double %2\n" +
5975 "%6 = OpLoad %v4double %3\n" +
5976 "%7 = OpLoad %v4double %4\n" +
5977 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
5978 "%9 = OpVectorShuffle %v4double %8 %7 1 0 4 5\n" +
5979 "OpReturn\n" +
5980 "OpFunctionEnd",
5981 9, true),
5982 // Test case 3: Basic test 4
5983 InstructionFoldingCase<bool>(
5984 Header() +
5985 "; CHECK: OpVectorShuffle\n" +
5986 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %6 2 3 5 4\n" +
5987 "; CHECK: OpReturn\n" +
5988 "%main = OpFunction %void None %void_func\n" +
5989 "%main_lab = OpLabel\n" +
5990 "%2 = OpVariable %_ptr_v4double Function\n" +
5991 "%3 = OpVariable %_ptr_v4double Function\n" +
5992 "%4 = OpVariable %_ptr_v4double Function\n" +
5993 "%5 = OpLoad %v4double %2\n" +
5994 "%6 = OpLoad %v4double %3\n" +
5995 "%7 = OpLoad %v4double %4\n" +
5996 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
5997 "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 6\n" +
5998 "OpReturn\n" +
5999 "OpFunctionEnd",
6000 9, true),
6001 // Test case 4: Don't fold, need both operands of the feeder.
6002 InstructionFoldingCase<bool>(
6003 Header() +
6004 "%main = OpFunction %void None %void_func\n" +
6005 "%main_lab = OpLabel\n" +
6006 "%2 = OpVariable %_ptr_v4double Function\n" +
6007 "%3 = OpVariable %_ptr_v4double Function\n" +
6008 "%4 = OpVariable %_ptr_v4double Function\n" +
6009 "%5 = OpLoad %v4double %2\n" +
6010 "%6 = OpLoad %v4double %3\n" +
6011 "%7 = OpLoad %v4double %4\n" +
6012 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
6013 "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 5\n" +
6014 "OpReturn\n" +
6015 "OpFunctionEnd",
6016 9, false),
6017 // Test case 5: Don't fold, need both operands of the feeder.
6018 InstructionFoldingCase<bool>(
6019 Header() +
6020 "%main = OpFunction %void None %void_func\n" +
6021 "%main_lab = OpLabel\n" +
6022 "%2 = OpVariable %_ptr_v4double Function\n" +
6023 "%3 = OpVariable %_ptr_v4double Function\n" +
6024 "%4 = OpVariable %_ptr_v4double Function\n" +
6025 "%5 = OpLoad %v4double %2\n" +
6026 "%6 = OpLoad %v4double %3\n" +
6027 "%7 = OpLoad %v4double %4\n" +
6028 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
6029 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
6030 "OpReturn\n" +
6031 "OpFunctionEnd",
6032 9, false),
6033 // Test case 6: Fold, need both operands of the feeder, but they are the same.
6034 InstructionFoldingCase<bool>(
6035 Header() +
6036 "; CHECK: OpVectorShuffle\n" +
6037 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 2 7 5\n" +
6038 "; CHECK: OpReturn\n" +
6039 "%main = OpFunction %void None %void_func\n" +
6040 "%main_lab = OpLabel\n" +
6041 "%2 = OpVariable %_ptr_v4double Function\n" +
6042 "%3 = OpVariable %_ptr_v4double Function\n" +
6043 "%4 = OpVariable %_ptr_v4double Function\n" +
6044 "%5 = OpLoad %v4double %2\n" +
6045 "%6 = OpLoad %v4double %3\n" +
6046 "%7 = OpLoad %v4double %4\n" +
6047 "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
6048 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
6049 "OpReturn\n" +
6050 "OpFunctionEnd",
6051 9, true),
6052 // Test case 7: Fold, need both operands of the feeder, but they are the same.
6053 InstructionFoldingCase<bool>(
6054 Header() +
6055 "; CHECK: OpVectorShuffle\n" +
6056 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 0 5 7\n" +
6057 "; CHECK: OpReturn\n" +
6058 "%main = OpFunction %void None %void_func\n" +
6059 "%main_lab = OpLabel\n" +
6060 "%2 = OpVariable %_ptr_v4double Function\n" +
6061 "%3 = OpVariable %_ptr_v4double Function\n" +
6062 "%4 = OpVariable %_ptr_v4double Function\n" +
6063 "%5 = OpLoad %v4double %2\n" +
6064 "%6 = OpLoad %v4double %3\n" +
6065 "%7 = OpLoad %v4double %4\n" +
6066 "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
6067 "%9 = OpVectorShuffle %v4double %7 %8 2 0 7 5\n" +
6068 "OpReturn\n" +
6069 "OpFunctionEnd",
6070 9, true),
6071 // Test case 8: Replace first operand with a smaller vector.
6072 InstructionFoldingCase<bool>(
6073 Header() +
6074 "; CHECK: OpVectorShuffle\n" +
6075 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 0 5 3\n" +
6076 "; CHECK: OpReturn\n" +
6077 "%main = OpFunction %void None %void_func\n" +
6078 "%main_lab = OpLabel\n" +
6079 "%2 = OpVariable %_ptr_v2double Function\n" +
6080 "%3 = OpVariable %_ptr_v4double Function\n" +
6081 "%4 = OpVariable %_ptr_v4double Function\n" +
6082 "%5 = OpLoad %v2double %2\n" +
6083 "%6 = OpLoad %v4double %3\n" +
6084 "%7 = OpLoad %v4double %4\n" +
6085 "%8 = OpVectorShuffle %v4double %5 %5 0 1 2 3\n" +
6086 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
6087 "OpReturn\n" +
6088 "OpFunctionEnd",
6089 9, true),
6090 // Test case 9: Replace first operand with a larger vector.
6091 InstructionFoldingCase<bool>(
6092 Header() +
6093 "; CHECK: OpVectorShuffle\n" +
6094 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 0 7 5\n" +
6095 "; CHECK: OpReturn\n" +
6096 "%main = OpFunction %void None %void_func\n" +
6097 "%main_lab = OpLabel\n" +
6098 "%2 = OpVariable %_ptr_v4double Function\n" +
6099 "%3 = OpVariable %_ptr_v4double Function\n" +
6100 "%4 = OpVariable %_ptr_v4double Function\n" +
6101 "%5 = OpLoad %v4double %2\n" +
6102 "%6 = OpLoad %v4double %3\n" +
6103 "%7 = OpLoad %v4double %4\n" +
6104 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
6105 "%9 = OpVectorShuffle %v4double %8 %7 1 0 5 3\n" +
6106 "OpReturn\n" +
6107 "OpFunctionEnd",
6108 9, true),
6109 // Test case 10: Replace unused operand with null.
6110 InstructionFoldingCase<bool>(
6111 Header() +
6112 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6113 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6114 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
6115 "; CHECK: OpVectorShuffle\n" +
6116 "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %7 4 2 5 3\n" +
6117 "; CHECK: OpReturn\n" +
6118 "%main = OpFunction %void None %void_func\n" +
6119 "%main_lab = OpLabel\n" +
6120 "%2 = OpVariable %_ptr_v4double Function\n" +
6121 "%3 = OpVariable %_ptr_v4double Function\n" +
6122 "%4 = OpVariable %_ptr_v4double Function\n" +
6123 "%5 = OpLoad %v4double %2\n" +
6124 "%6 = OpLoad %v4double %3\n" +
6125 "%7 = OpLoad %v4double %4\n" +
6126 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
6127 "%9 = OpVectorShuffle %v4double %8 %7 4 2 5 3\n" +
6128 "OpReturn\n" +
6129 "OpFunctionEnd",
6130 9, true),
6131 // Test case 11: Replace unused operand with null.
6132 InstructionFoldingCase<bool>(
6133 Header() +
6134 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6135 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6136 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
6137 "; CHECK: OpVectorShuffle\n" +
6138 "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %5 2 2 5 5\n" +
6139 "; CHECK: OpReturn\n" +
6140 "%main = OpFunction %void None %void_func\n" +
6141 "%main_lab = OpLabel\n" +
6142 "%2 = OpVariable %_ptr_v4double Function\n" +
6143 "%3 = OpVariable %_ptr_v4double Function\n" +
6144 "%5 = OpLoad %v4double %2\n" +
6145 "%6 = OpLoad %v4double %3\n" +
6146 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
6147 "%9 = OpVectorShuffle %v4double %8 %8 2 2 3 3\n" +
6148 "OpReturn\n" +
6149 "OpFunctionEnd",
6150 9, true),
6151 // Test case 12: Replace unused operand with null.
6152 InstructionFoldingCase<bool>(
6153 Header() +
6154 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6155 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6156 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
6157 "; CHECK: OpVectorShuffle\n" +
6158 "; CHECK: OpVectorShuffle {{%\\w+}} %7 [[null]] 2 0 1 3\n" +
6159 "; CHECK: OpReturn\n" +
6160 "%main = OpFunction %void None %void_func\n" +
6161 "%main_lab = OpLabel\n" +
6162 "%2 = OpVariable %_ptr_v4double Function\n" +
6163 "%3 = OpVariable %_ptr_v4double Function\n" +
6164 "%4 = OpVariable %_ptr_v4double Function\n" +
6165 "%5 = OpLoad %v4double %2\n" +
6166 "%6 = OpLoad %v4double %3\n" +
6167 "%7 = OpLoad %v4double %4\n" +
6168 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
6169 "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" +
6170 "OpReturn\n" +
6171 "OpFunctionEnd",
6172 9, true),
6173 // Test case 13: Shuffle with undef literal.
6174 InstructionFoldingCase<bool>(
6175 Header() +
6176 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6177 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6178 "; CHECK: OpVectorShuffle\n" +
6179 "; CHECK: OpVectorShuffle {{%\\w+}} %7 {{%\\w+}} 2 0 1 4294967295\n" +
6180 "; CHECK: OpReturn\n" +
6181 "%main = OpFunction %void None %void_func\n" +
6182 "%main_lab = OpLabel\n" +
6183 "%2 = OpVariable %_ptr_v4double Function\n" +
6184 "%3 = OpVariable %_ptr_v4double Function\n" +
6185 "%4 = OpVariable %_ptr_v4double Function\n" +
6186 "%5 = OpLoad %v4double %2\n" +
6187 "%6 = OpLoad %v4double %3\n" +
6188 "%7 = OpLoad %v4double %4\n" +
6189 "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
6190 "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" +
6191 "OpReturn\n" +
6192 "OpFunctionEnd",
6193 9, true)
6194 ));
6195
6196 } // namespace
6197 } // namespace opt
6198 } // namespace spvtools
6199