1 // Copyright (c) 2016 Google Inc.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 #include "source/opt/fold.h"
15
16 #include <limits>
17 #include <memory>
18 #include <string>
19 #include <vector>
20
21 #include "effcee/effcee.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "source/opt/build_module.h"
25 #include "source/opt/def_use_manager.h"
26 #include "source/opt/ir_context.h"
27 #include "source/opt/module.h"
28 #include "spirv-tools/libspirv.hpp"
29
30 namespace spvtools {
31 namespace opt {
32 namespace {
33
34 using ::testing::Contains;
35
Disassemble(const std::string & original,IRContext * context,uint32_t disassemble_options=0)36 std::string Disassemble(const std::string& original, IRContext* context,
37 uint32_t disassemble_options = 0) {
38 std::vector<uint32_t> optimized_bin;
39 context->module()->ToBinary(&optimized_bin, true);
40 spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
41 SpirvTools tools(target_env);
42 std::string optimized_asm;
43 EXPECT_TRUE(
44 tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options))
45 << "Disassembling failed for shader:\n"
46 << original << std::endl;
47 return optimized_asm;
48 }
49
Match(const std::string & original,IRContext * context,uint32_t disassemble_options=0)50 void Match(const std::string& original, IRContext* context,
51 uint32_t disassemble_options = 0) {
52 std::string disassembly = Disassemble(original, context, disassemble_options);
53 auto match_result = effcee::Match(disassembly, original);
54 EXPECT_EQ(effcee::Result::Status::Ok, match_result.status())
55 << match_result.message() << "\nChecking result:\n"
56 << disassembly;
57 }
58
59 template <class ResultType>
60 struct InstructionFoldingCase {
InstructionFoldingCasespvtools::opt::__anon8bea92fa0111::InstructionFoldingCase61 InstructionFoldingCase(const std::string& tb, uint32_t id, ResultType result)
62 : test_body(tb), id_to_fold(id), expected_result(result) {}
63
64 std::string test_body;
65 uint32_t id_to_fold;
66 ResultType expected_result;
67 };
68
GetInstructionToFold(const std::string test_body,const uint32_t id_to_fold,spv_target_env spv_env)69 std::tuple<std::unique_ptr<IRContext>, Instruction*> GetInstructionToFold(
70 const std::string test_body, const uint32_t id_to_fold,
71 spv_target_env spv_env) {
72 // Build module.
73 std::unique_ptr<IRContext> context =
74 BuildModule(spv_env, nullptr, test_body,
75 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
76 EXPECT_NE(nullptr, context);
77 if (context == nullptr) {
78 return {nullptr, nullptr};
79 }
80
81 // Fold the instruction to test.
82 if (id_to_fold != 0) {
83 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
84 Instruction* inst = def_use_mgr->GetDef(id_to_fold);
85 return {std::move(context), inst};
86 }
87
88 // If there is not ID, we get the instruction just before a terminator
89 // instruction. That could be a return or abort. This is used for cases where
90 // the instruction we want to fold does not have a result id.
91 Function* func = &*context->module()->begin();
92 for (auto& bb : *func) {
93 Instruction* terminator = bb.terminator();
94 if (terminator->IsReturnOrAbort()) {
95 return {std::move(context), terminator->PreviousNode()};
96 }
97 }
98 return {nullptr, nullptr};
99 }
100
FoldInstruction(const std::string test_body,const uint32_t id_to_fold,spv_target_env spv_env)101 std::tuple<std::unique_ptr<IRContext>, Instruction*> FoldInstruction(
102 const std::string test_body, const uint32_t id_to_fold,
103 spv_target_env spv_env) {
104 // Build module.
105 std::unique_ptr<IRContext> context;
106 Instruction* inst = nullptr;
107 std::tie(context, inst) =
108 GetInstructionToFold(test_body, id_to_fold, spv_env);
109
110 if (context == nullptr) {
111 return {nullptr, nullptr};
112 }
113
114 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
115 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
116 EXPECT_EQ(inst->result_id(), original_inst->result_id());
117 EXPECT_EQ(inst->type_id(), original_inst->type_id());
118
119 if (!succeeded && inst != nullptr) {
120 EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
121 for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
122 EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
123 }
124 }
125
126 return {std::move(context), succeeded ? inst : nullptr};
127 }
128
129 template <class ElementType, class Function>
CheckForExpectedScalarConstant(Instruction * inst,ElementType expected_result,Function GetValue)130 void CheckForExpectedScalarConstant(Instruction* inst,
131 ElementType expected_result,
132 Function GetValue) {
133 ASSERT_TRUE(inst);
134
135 IRContext* context = inst->context();
136 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
137 while (inst->opcode() == spv::Op::OpCopyObject) {
138 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
139 }
140
141 // Make sure we have a constant.
142 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
143 const analysis::Constant* constant = const_mrg->GetConstantFromInst(inst);
144 ASSERT_TRUE(constant);
145
146 // Make sure the constant is a scalar.
147 const analysis::ScalarConstant* result = constant->AsScalarConstant();
148 ASSERT_TRUE(result);
149
150 // Check if the result matches the expected value.
151 // If ExpectedType is not a float type, it should cast the value to a double
152 // and never get a nan.
153 if (!std::isnan(static_cast<double>(expected_result))) {
154 EXPECT_EQ(expected_result, GetValue(result));
155 } else {
156 EXPECT_TRUE(std::isnan(static_cast<double>(GetValue(result))));
157 }
158 }
159
160 template <class ElementType, class Function>
CheckForExpectedVectorConstant(Instruction * inst,std::vector<ElementType> expected_result,Function GetValue)161 void CheckForExpectedVectorConstant(Instruction* inst,
162 std::vector<ElementType> expected_result,
163 Function GetValue) {
164 ASSERT_TRUE(inst);
165
166 IRContext* context = inst->context();
167 EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
168 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
169 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
170 std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
171 EXPECT_THAT(opcodes, Contains(inst->opcode()));
172 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
173 const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
174 EXPECT_NE(result, nullptr);
175 if (result != nullptr) {
176 const std::vector<const analysis::Constant*>& componenets =
177 result->AsVectorConstant()->GetComponents();
178 EXPECT_EQ(componenets.size(), expected_result.size());
179 for (size_t i = 0; i < componenets.size(); i++) {
180 EXPECT_EQ(expected_result[i], GetValue(componenets[i]));
181 }
182 }
183 }
184
185 using IntegerInstructionFoldingTest =
186 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
187
TEST_P(IntegerInstructionFoldingTest,Case)188 TEST_P(IntegerInstructionFoldingTest, Case) {
189 const auto& tc = GetParam();
190
191 std::unique_ptr<IRContext> context;
192 Instruction* inst;
193 std::tie(context, inst) =
194 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
195 CheckForExpectedScalarConstant(
196 inst, tc.expected_result, [](const analysis::Constant* c) {
197 return c->AsScalarConstant()->GetU32BitValue();
198 });
199 }
200
201 // Returns a common SPIR-V header for all of the test that follow.
202 #define INT_0_ID 100
203 #define TRUE_ID 101
204 #define VEC2_0_ID 102
205 #define INT_7_ID 103
206 #define FLOAT_0_ID 104
207 #define DOUBLE_0_ID 105
208 #define VEC4_0_ID 106
209 #define DVEC4_0_ID 106
210 #define HALF_0_ID 108
Header()211 const std::string& Header() {
212 static const std::string header = R"(OpCapability Shader
213 OpCapability Float16
214 OpCapability Float64
215 OpCapability Int8
216 OpCapability Int16
217 OpCapability Int64
218 %1 = OpExtInstImport "GLSL.std.450"
219 OpMemoryModel Logical GLSL450
220 OpEntryPoint Fragment %main "main"
221 OpExecutionMode %main OriginUpperLeft
222 OpSource GLSL 140
223 OpName %main "main"
224 %void = OpTypeVoid
225 %void_func = OpTypeFunction %void
226 %bool = OpTypeBool
227 %float = OpTypeFloat 32
228 %double = OpTypeFloat 64
229 %half = OpTypeFloat 16
230 %101 = OpConstantTrue %bool ; Need a def with an numerical id to define id maps.
231 %true = OpConstantTrue %bool
232 %false = OpConstantFalse %bool
233 %bool_null = OpConstantNull %bool
234 %short = OpTypeInt 16 1
235 %ushort = OpTypeInt 16 0
236 %byte = OpTypeInt 8 1
237 %ubyte = OpTypeInt 8 0
238 %int = OpTypeInt 32 1
239 %long = OpTypeInt 64 1
240 %uint = OpTypeInt 32 0
241 %ulong = OpTypeInt 64 0
242 %v2int = OpTypeVector %int 2
243 %v4int = OpTypeVector %int 4
244 %v2short = OpTypeVector %short 2
245 %v2long = OpTypeVector %long 2
246 %v4long = OpTypeVector %long 4
247 %v4float = OpTypeVector %float 4
248 %v4double = OpTypeVector %double 4
249 %v2uint = OpTypeVector %uint 2
250 %v2ulong = OpTypeVector %ulong 2
251 %v2float = OpTypeVector %float 2
252 %v2double = OpTypeVector %double 2
253 %v2half = OpTypeVector %half 2
254 %v2bool = OpTypeVector %bool 2
255 %m2x2int = OpTypeMatrix %v2int 2
256 %mat4v2float = OpTypeMatrix %v2float 4
257 %mat2v4float = OpTypeMatrix %v4float 2
258 %mat4v4float = OpTypeMatrix %v4float 4
259 %mat4v4double = OpTypeMatrix %v4double 4
260 %struct_v2int_int_int = OpTypeStruct %v2int %int %int
261 %_ptr_int = OpTypePointer Function %int
262 %_ptr_uint = OpTypePointer Function %uint
263 %_ptr_bool = OpTypePointer Function %bool
264 %_ptr_float = OpTypePointer Function %float
265 %_ptr_double = OpTypePointer Function %double
266 %_ptr_half = OpTypePointer Function %half
267 %_ptr_long = OpTypePointer Function %long
268 %_ptr_ulong = OpTypePointer Function %ulong
269 %_ptr_v2int = OpTypePointer Function %v2int
270 %_ptr_v4int = OpTypePointer Function %v4int
271 %_ptr_v4float = OpTypePointer Function %v4float
272 %_ptr_v4double = OpTypePointer Function %v4double
273 %_ptr_struct_v2int_int_int = OpTypePointer Function %struct_v2int_int_int
274 %_ptr_v2float = OpTypePointer Function %v2float
275 %_ptr_v2double = OpTypePointer Function %v2double
276 %int_2 = OpConstant %int 2
277 %int_arr_2 = OpTypeArray %int %int_2
278 %short_0 = OpConstant %short 0
279 %short_2 = OpConstant %short 2
280 %short_3 = OpConstant %short 3
281 %short_n5 = OpConstant %short -5
282 %ubyte_1 = OpConstant %ubyte 1
283 %byte_n1 = OpConstant %byte -1
284 %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps.
285 %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps.
286 %int_0 = OpConstant %int 0
287 %int_1 = OpConstant %int 1
288 %int_3 = OpConstant %int 3
289 %int_4 = OpConstant %int 4
290 %int_10 = OpConstant %int 10
291 %int_1073741824 = OpConstant %int 1073741824
292 %int_n1 = OpConstant %int -1
293 %int_n24 = OpConstant %int -24
294 %int_n858993459 = OpConstant %int -858993459
295 %int_min = OpConstant %int -2147483648
296 %int_max = OpConstant %int 2147483647
297 %long_0 = OpConstant %long 0
298 %long_1 = OpConstant %long 1
299 %long_2 = OpConstant %long 2
300 %long_3 = OpConstant %long 3
301 %long_n3 = OpConstant %long -3
302 %long_7 = OpConstant %long 7
303 %long_n7 = OpConstant %long -7
304 %long_10 = OpConstant %long 10
305 %long_32768 = OpConstant %long 32768
306 %long_n57344 = OpConstant %long -57344
307 %long_n4611686018427387904 = OpConstant %long -4611686018427387904
308 %long_4611686018427387904 = OpConstant %long 4611686018427387904
309 %long_n1 = OpConstant %long -1
310 %long_n3689348814741910323 = OpConstant %long -3689348814741910323
311 %long_min = OpConstant %long -9223372036854775808
312 %long_max = OpConstant %long 9223372036854775807
313 %ulong_7 = OpConstant %ulong 7
314 %ulong_4611686018427387904 = OpConstant %ulong 4611686018427387904
315 %uint_0 = OpConstant %uint 0
316 %uint_1 = OpConstant %uint 1
317 %uint_2 = OpConstant %uint 2
318 %uint_3 = OpConstant %uint 3
319 %uint_4 = OpConstant %uint 4
320 %uint_32 = OpConstant %uint 32
321 %uint_42 = OpConstant %uint 42
322 %uint_2147483649 = OpConstant %uint 2147483649
323 %uint_max = OpConstant %uint 4294967295
324 %ulong_0 = OpConstant %ulong 0
325 %ulong_1 = OpConstant %ulong 1
326 %ulong_2 = OpConstant %ulong 2
327 %ulong_9223372036854775809 = OpConstant %ulong 9223372036854775809
328 %ulong_max = OpConstant %ulong 18446744073709551615
329 %v2int_undef = OpUndef %v2int
330 %v2int_0_0 = OpConstantComposite %v2int %int_0 %int_0
331 %v2int_1_0 = OpConstantComposite %v2int %int_1 %int_0
332 %v2int_2_2 = OpConstantComposite %v2int %int_2 %int_2
333 %v2int_2_3 = OpConstantComposite %v2int %int_2 %int_3
334 %v2int_3_2 = OpConstantComposite %v2int %int_3 %int_2
335 %v2int_n1_n24 = OpConstantComposite %v2int %int_n1 %int_n24
336 %v2int_4_4 = OpConstantComposite %v2int %int_4 %int_4
337 %v2int_min_max = OpConstantComposite %v2int %int_min %int_max
338 %v2short_2_n5 = OpConstantComposite %v2short %short_2 %short_n5
339 %v2long_2_2 = OpConstantComposite %v2long %long_2 %long_2
340 %v2long_2_3 = OpConstantComposite %v2long %long_2 %long_3
341 %v2bool_null = OpConstantNull %v2bool
342 %v2bool_true_false = OpConstantComposite %v2bool %true %false
343 %v2bool_false_true = OpConstantComposite %v2bool %false %true
344 %struct_v2int_int_int_null = OpConstantNull %struct_v2int_int_int
345 %v2int_null = OpConstantNull %v2int
346 %102 = OpConstantComposite %v2int %103 %103
347 %v4int_undef = OpUndef %v4int
348 %v4int_0_0_0_0 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
349 %m2x2int_undef = OpUndef %m2x2int
350 %struct_undef_0_0 = OpConstantComposite %struct_v2int_int_int %v2int_undef %int_0 %int_0
351 %float_n1 = OpConstant %float -1
352 %104 = OpConstant %float 0 ; Need a def with an numerical id to define id maps.
353 %float_null = OpConstantNull %float
354 %float_0 = OpConstant %float 0
355 %float_n0 = OpConstant %float -0.0
356 %float_1 = OpConstant %float 1
357 %float_2 = OpConstant %float 2
358 %float_3 = OpConstant %float 3
359 %float_4 = OpConstant %float 4
360 %float_2049 = OpConstant %float 2049
361 %float_n2049 = OpConstant %float -2049
362 %float_0p5 = OpConstant %float 0.5
363 %float_0p2 = OpConstant %float 0.2
364 %float_pi = OpConstant %float 1.5555
365 %float_1e16 = OpConstant %float 1e16
366 %float_n1e16 = OpConstant %float -1e16
367 %float_1en16 = OpConstant %float 1e-16
368 %float_n1en16 = OpConstant %float -1e-16
369 %v2float_0_0 = OpConstantComposite %v2float %float_0 %float_0
370 %v2float_2_2 = OpConstantComposite %v2float %float_2 %float_2
371 %v2float_2_3 = OpConstantComposite %v2float %float_2 %float_3
372 %v2float_3_2 = OpConstantComposite %v2float %float_3 %float_2
373 %v2float_4_4 = OpConstantComposite %v2float %float_4 %float_4
374 %v2float_2_0p5 = OpConstantComposite %v2float %float_2 %float_0p5
375 %v2float_0p2_0p5 = OpConstantComposite %v2float %float_0p2 %float_0p5
376 %v2float_null = OpConstantNull %v2float
377 %double_n1 = OpConstant %double -1
378 %105 = OpConstant %double 0 ; Need a def with an numerical id to define id maps.
379 %double_null = OpConstantNull %double
380 %double_0 = OpConstant %double 0
381 %double_n0 = OpConstant %double -0.0
382 %double_1 = OpConstant %double 1
383 %double_2 = OpConstant %double 2
384 %double_3 = OpConstant %double 3
385 %double_4 = OpConstant %double 4
386 %double_5 = OpConstant %double 5
387 %double_0p5 = OpConstant %double 0.5
388 %double_0p2 = OpConstant %double 0.2
389 %v2double_0_0 = OpConstantComposite %v2double %double_0 %double_0
390 %v2double_2_2 = OpConstantComposite %v2double %double_2 %double_2
391 %v2double_2_3 = OpConstantComposite %v2double %double_2 %double_3
392 %v2double_3_2 = OpConstantComposite %v2double %double_3 %double_2
393 %v2double_4_4 = OpConstantComposite %v2double %double_4 %double_4
394 %v2double_2_0p5 = OpConstantComposite %v2double %double_2 %double_0p5
395 %v2double_null = OpConstantNull %v2double
396 %108 = OpConstant %half 0
397 %half_1 = OpConstant %half 1
398 %half_2 = OpConstant %half 2
399 %half_0_1 = OpConstantComposite %v2half %108 %half_1
400 %106 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
401 %v4float_0_0_0_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
402 %v4float_0_0_0_1 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
403 %v4float_0_1_0_0 = OpConstantComposite %v4float %float_0 %float_1 %float_null %float_0
404 %v4float_1_1_1_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
405 %v4float_1_2_3_4 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
406 %v4float_null = OpConstantNull %v4float
407 %mat2v4float_null = OpConstantNull %mat2v4float
408 %mat4v4float_null = OpConstantNull %mat4v4float
409 %mat4v4float_1_2_3_4 = OpConstantComposite %mat4v4float %v4float_1_2_3_4 %v4float_1_2_3_4 %v4float_1_2_3_4 %v4float_1_2_3_4
410 %mat4v4float_1_2_3_4_null = OpConstantComposite %mat4v4float %v4float_1_2_3_4 %v4float_null %v4float_1_2_3_4 %v4float_null
411 %107 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
412 %v4double_0_0_0_0 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
413 %v4double_0_0_0_1 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_1
414 %v4double_0_1_0_0 = OpConstantComposite %v4double %double_0 %double_1 %double_null %double_0
415 %v4double_1_1_1_1 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_1
416 %v4double_1_2_3_4 = OpConstantComposite %v4double %double_1 %double_2 %double_3 %double_4
417 %v4double_1_1_1_0p5 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_0p5
418 %v4double_null = OpConstantNull %v4double
419 %mat4v4double_null = OpConstantNull %mat4v4double
420 %mat4v4double_1_2_3_4 = OpConstantComposite %mat4v4double %v4double_1_2_3_4 %v4double_1_2_3_4 %v4double_1_2_3_4 %v4double_1_2_3_4
421 %mat4v4double_1_2_3_4_null = OpConstantComposite %mat4v4double %v4double_1_2_3_4 %v4double_null %v4double_1_2_3_4 %v4double_null
422 %v4float_n1_2_1_3 = OpConstantComposite %v4float %float_n1 %float_2 %float_1 %float_3
423 %uint_0x3f800000 = OpConstant %uint 0x3f800000
424 %uint_0xbf800000 = OpConstant %uint 0xbf800000
425 %v2uint_0x3f800000_0xbf800000 = OpConstantComposite %v2uint %uint_0x3f800000 %uint_0xbf800000
426 %long_0xbf8000003f800000 = OpConstant %long 0xbf8000003f800000
427 %int_0x3FF00000 = OpConstant %int 0x3FF00000
428 %int_0x00000000 = OpConstant %int 0x00000000
429 %int_0xC05FD666 = OpConstant %int 0xC05FD666
430 %int_0x66666666 = OpConstant %int 0x66666666
431 %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666 = OpConstantComposite %v4int %int_0x00000000 %int_0x3FF00000 %int_0x66666666 %int_0xC05FD666
432 %ushort_0x4400 = OpConstant %ushort 0x4400
433 %short_0x4400 = OpConstant %short 0x4400
434 %ushort_0xBC00 = OpConstant %ushort 0xBC00
435 %short_0xBC00 = OpConstant %short 0xBC00
436 %int_arr_2_undef = OpUndef %int_arr_2
437 )";
438
439 return header;
440 }
441
442 // Returns the header with definitions of float NaN and double NaN. Since FC
443 // "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" finds
444 // %double_nan = OpConstant %double -0x1.8p+1024 instead of
445 // %double_n0 = OpConstant %double -0,
446 // we separates those definitions from Header().
HeaderWithNaN()447 const std::string& HeaderWithNaN() {
448 static const std::string headerWithNaN =
449 Header() +
450 R"(%float_nan = OpConstant %float -0x1.8p+128
451 %double_nan = OpConstant %double -0x1.8p+1024
452 )";
453
454 return headerWithNaN;
455 }
456
457 // clang-format off
458 INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTest,
459 ::testing::Values(
460 // Test case 0: fold 0*n
461 InstructionFoldingCase<uint32_t>(
462 Header() + "%main = OpFunction %void None %void_func\n" +
463 "%main_lab = OpLabel\n" +
464 "%n = OpVariable %_ptr_int Function\n" +
465 "%load = OpLoad %int %n\n" +
466 "%2 = OpIMul %int %int_0 %load\n" +
467 "OpReturn\n" +
468 "OpFunctionEnd",
469 2, 0),
470 // Test case 1: fold n*0
471 InstructionFoldingCase<uint32_t>(
472 Header() + "%main = OpFunction %void None %void_func\n" +
473 "%main_lab = OpLabel\n" +
474 "%n = OpVariable %_ptr_int Function\n" +
475 "%load = OpLoad %int %n\n" +
476 "%2 = OpIMul %int %load %int_0\n" +
477 "OpReturn\n" +
478 "OpFunctionEnd",
479 2, 0),
480 // Test case 2: fold 0/n (signed)
481 InstructionFoldingCase<uint32_t>(
482 Header() + "%main = OpFunction %void None %void_func\n" +
483 "%main_lab = OpLabel\n" +
484 "%n = OpVariable %_ptr_int Function\n" +
485 "%load = OpLoad %int %n\n" +
486 "%2 = OpSDiv %int %int_0 %load\n" +
487 "OpReturn\n" +
488 "OpFunctionEnd",
489 2, 0),
490 // Test case 3: fold n/0 (signed)
491 InstructionFoldingCase<uint32_t>(
492 Header() + "%main = OpFunction %void None %void_func\n" +
493 "%main_lab = OpLabel\n" +
494 "%n = OpVariable %_ptr_int Function\n" +
495 "%load = OpLoad %int %n\n" +
496 "%2 = OpSDiv %int %load %int_0\n" +
497 "OpReturn\n" +
498 "OpFunctionEnd",
499 2, 0),
500 // Test case 4: fold 0/n (unsigned)
501 InstructionFoldingCase<uint32_t>(
502 Header() + "%main = OpFunction %void None %void_func\n" +
503 "%main_lab = OpLabel\n" +
504 "%n = OpVariable %_ptr_uint Function\n" +
505 "%load = OpLoad %uint %n\n" +
506 "%2 = OpUDiv %uint %uint_0 %load\n" +
507 "OpReturn\n" +
508 "OpFunctionEnd",
509 2, 0),
510 // Test case 5: fold n/0 (unsigned)
511 InstructionFoldingCase<uint32_t>(
512 Header() + "%main = OpFunction %void None %void_func\n" +
513 "%main_lab = OpLabel\n" +
514 "%n = OpVariable %_ptr_int Function\n" +
515 "%load = OpLoad %int %n\n" +
516 "%2 = OpSDiv %int %load %int_0\n" +
517 "OpReturn\n" +
518 "OpFunctionEnd",
519 2, 0),
520 // Test case 6: fold 0 remainder n
521 InstructionFoldingCase<uint32_t>(
522 Header() + "%main = OpFunction %void None %void_func\n" +
523 "%main_lab = OpLabel\n" +
524 "%n = OpVariable %_ptr_int Function\n" +
525 "%load = OpLoad %int %n\n" +
526 "%2 = OpSRem %int %int_0 %load\n" +
527 "OpReturn\n" +
528 "OpFunctionEnd",
529 2, 0),
530 // Test case 7: fold n remainder 0
531 InstructionFoldingCase<uint32_t>(
532 Header() + "%main = OpFunction %void None %void_func\n" +
533 "%main_lab = OpLabel\n" +
534 "%n = OpVariable %_ptr_int Function\n" +
535 "%load = OpLoad %int %n\n" +
536 "%2 = OpSRem %int %load %int_0\n" +
537 "OpReturn\n" +
538 "OpFunctionEnd",
539 2, 0),
540 // Test case 8: fold 0%n (signed)
541 InstructionFoldingCase<uint32_t>(
542 Header() + "%main = OpFunction %void None %void_func\n" +
543 "%main_lab = OpLabel\n" +
544 "%n = OpVariable %_ptr_int Function\n" +
545 "%load = OpLoad %int %n\n" +
546 "%2 = OpSMod %int %int_0 %load\n" +
547 "OpReturn\n" +
548 "OpFunctionEnd",
549 2, 0),
550 // Test case 9: fold n%0 (signed)
551 InstructionFoldingCase<uint32_t>(
552 Header() + "%main = OpFunction %void None %void_func\n" +
553 "%main_lab = OpLabel\n" +
554 "%n = OpVariable %_ptr_int Function\n" +
555 "%load = OpLoad %int %n\n" +
556 "%2 = OpSMod %int %load %int_0\n" +
557 "OpReturn\n" +
558 "OpFunctionEnd",
559 2, 0),
560 // Test case 10: fold 0%n (unsigned)
561 InstructionFoldingCase<uint32_t>(
562 Header() + "%main = OpFunction %void None %void_func\n" +
563 "%main_lab = OpLabel\n" +
564 "%n = OpVariable %_ptr_uint Function\n" +
565 "%load = OpLoad %uint %n\n" +
566 "%2 = OpUMod %uint %uint_0 %load\n" +
567 "OpReturn\n" +
568 "OpFunctionEnd",
569 2, 0),
570 // Test case 11: fold n%0 (unsigned)
571 InstructionFoldingCase<uint32_t>(
572 Header() + "%main = OpFunction %void None %void_func\n" +
573 "%main_lab = OpLabel\n" +
574 "%n = OpVariable %_ptr_uint Function\n" +
575 "%load = OpLoad %uint %n\n" +
576 "%2 = OpUMod %uint %load %uint_0\n" +
577 "OpReturn\n" +
578 "OpFunctionEnd",
579 2, 0),
580 // Test case 12: fold n << 32
581 InstructionFoldingCase<uint32_t>(
582 Header() + "%main = OpFunction %void None %void_func\n" +
583 "%main_lab = OpLabel\n" +
584 "%n = OpVariable %_ptr_uint Function\n" +
585 "%load = OpLoad %uint %n\n" +
586 "%2 = OpShiftLeftLogical %uint %load %uint_32\n" +
587 "OpReturn\n" +
588 "OpFunctionEnd",
589 2, 0),
590 // Test case 13: fold n >> 32
591 InstructionFoldingCase<uint32_t>(
592 Header() + "%main = OpFunction %void None %void_func\n" +
593 "%main_lab = OpLabel\n" +
594 "%n = OpVariable %_ptr_uint Function\n" +
595 "%load = OpLoad %uint %n\n" +
596 "%2 = OpShiftRightLogical %uint %load %uint_32\n" +
597 "OpReturn\n" +
598 "OpFunctionEnd",
599 2, 0),
600 // Test case 14: fold n | 0xFFFFFFFF
601 InstructionFoldingCase<uint32_t>(
602 Header() + "%main = OpFunction %void None %void_func\n" +
603 "%main_lab = OpLabel\n" +
604 "%n = OpVariable %_ptr_uint Function\n" +
605 "%load = OpLoad %uint %n\n" +
606 "%2 = OpBitwiseOr %uint %load %uint_max\n" +
607 "OpReturn\n" +
608 "OpFunctionEnd",
609 2, 0xFFFFFFFF),
610 // Test case 15: fold 0xFFFFFFFF | n
611 InstructionFoldingCase<uint32_t>(
612 Header() + "%main = OpFunction %void None %void_func\n" +
613 "%main_lab = OpLabel\n" +
614 "%n = OpVariable %_ptr_uint Function\n" +
615 "%load = OpLoad %uint %n\n" +
616 "%2 = OpBitwiseOr %uint %uint_max %load\n" +
617 "OpReturn\n" +
618 "OpFunctionEnd",
619 2, 0xFFFFFFFF),
620 // Test case 16: fold n & 0
621 InstructionFoldingCase<uint32_t>(
622 Header() + "%main = OpFunction %void None %void_func\n" +
623 "%main_lab = OpLabel\n" +
624 "%n = OpVariable %_ptr_uint Function\n" +
625 "%load = OpLoad %uint %n\n" +
626 "%2 = OpBitwiseAnd %uint %load %uint_0\n" +
627 "OpReturn\n" +
628 "OpFunctionEnd",
629 2, 0),
630 // Test case 17: fold 1/0 (signed)
631 InstructionFoldingCase<uint32_t>(
632 Header() + "%main = OpFunction %void None %void_func\n" +
633 "%main_lab = OpLabel\n" +
634 "%2 = OpSDiv %int %int_1 %int_0\n" +
635 "OpReturn\n" +
636 "OpFunctionEnd",
637 2, 0),
638 // Test case 18: fold 1/0 (unsigned)
639 InstructionFoldingCase<uint32_t>(
640 Header() + "%main = OpFunction %void None %void_func\n" +
641 "%main_lab = OpLabel\n" +
642 "%2 = OpUDiv %uint %uint_1 %uint_0\n" +
643 "OpReturn\n" +
644 "OpFunctionEnd",
645 2, 0),
646 // Test case 19: fold OpSRem 1 0 (signed)
647 InstructionFoldingCase<uint32_t>(
648 Header() + "%main = OpFunction %void None %void_func\n" +
649 "%main_lab = OpLabel\n" +
650 "%2 = OpSRem %int %int_1 %int_0\n" +
651 "OpReturn\n" +
652 "OpFunctionEnd",
653 2, 0),
654 // Test case 20: fold 1%0 (signed)
655 InstructionFoldingCase<uint32_t>(
656 Header() + "%main = OpFunction %void None %void_func\n" +
657 "%main_lab = OpLabel\n" +
658 "%2 = OpSMod %int %int_1 %int_0\n" +
659 "OpReturn\n" +
660 "OpFunctionEnd",
661 2, 0),
662 // Test case 21: fold 1%0 (unsigned)
663 InstructionFoldingCase<uint32_t>(
664 Header() + "%main = OpFunction %void None %void_func\n" +
665 "%main_lab = OpLabel\n" +
666 "%2 = OpUMod %uint %uint_1 %uint_0\n" +
667 "OpReturn\n" +
668 "OpFunctionEnd",
669 2, 0),
670 // Test case 22: fold unsigned n >> 42 (undefined, so set to zero).
671 InstructionFoldingCase<uint32_t>(
672 Header() + "%main = OpFunction %void None %void_func\n" +
673 "%main_lab = OpLabel\n" +
674 "%n = OpVariable %_ptr_uint Function\n" +
675 "%load = OpLoad %uint %n\n" +
676 "%2 = OpShiftRightLogical %uint %load %uint_42\n" +
677 "OpReturn\n" +
678 "OpFunctionEnd",
679 2, 0),
680 // Test case 23: fold signed n >> 42 (undefined, so set to zero).
681 InstructionFoldingCase<uint32_t>(
682 Header() + "%main = OpFunction %void None %void_func\n" +
683 "%main_lab = OpLabel\n" +
684 "%n = OpVariable %_ptr_int Function\n" +
685 "%load = OpLoad %int %n\n" +
686 "%2 = OpShiftRightLogical %int %load %uint_42\n" +
687 "OpReturn\n" +
688 "OpFunctionEnd",
689 2, 0),
690 // Test case 24: fold n << 42 (undefined, so set to zero).
691 InstructionFoldingCase<uint32_t>(
692 Header() + "%main = OpFunction %void None %void_func\n" +
693 "%main_lab = OpLabel\n" +
694 "%n = OpVariable %_ptr_int Function\n" +
695 "%load = OpLoad %int %n\n" +
696 "%2 = OpShiftLeftLogical %int %load %uint_42\n" +
697 "OpReturn\n" +
698 "OpFunctionEnd",
699 2, 0),
700 // Test case 25: fold -24 >> 32 (defined as -1)
701 InstructionFoldingCase<uint32_t>(
702 Header() + "%main = OpFunction %void None %void_func\n" +
703 "%main_lab = OpLabel\n" +
704 "%2 = OpShiftRightArithmetic %int %int_n24 %uint_32\n" +
705 "OpReturn\n" +
706 "OpFunctionEnd",
707 2, -1),
708 // Test case 26: fold 2 >> 32 (signed)
709 InstructionFoldingCase<uint32_t>(
710 Header() + "%main = OpFunction %void None %void_func\n" +
711 "%main_lab = OpLabel\n" +
712 "%2 = OpShiftRightArithmetic %int %int_2 %uint_32\n" +
713 "OpReturn\n" +
714 "OpFunctionEnd",
715 2, 0),
716 // Test case 27: fold 2 >> 32 (unsigned)
717 InstructionFoldingCase<uint32_t>(
718 Header() + "%main = OpFunction %void None %void_func\n" +
719 "%main_lab = OpLabel\n" +
720 "%2 = OpShiftRightLogical %int %int_2 %uint_32\n" +
721 "OpReturn\n" +
722 "OpFunctionEnd",
723 2, 0),
724 // Test case 28: fold 2 << 32
725 InstructionFoldingCase<uint32_t>(
726 Header() + "%main = OpFunction %void None %void_func\n" +
727 "%main_lab = OpLabel\n" +
728 "%2 = OpShiftLeftLogical %int %int_2 %uint_32\n" +
729 "OpReturn\n" +
730 "OpFunctionEnd",
731 2, 0),
732 // Test case 29: fold -INT_MIN
733 InstructionFoldingCase<uint32_t>(
734 Header() + "%main = OpFunction %void None %void_func\n" +
735 "%main_lab = OpLabel\n" +
736 "%2 = OpSNegate %int %int_min\n" +
737 "OpReturn\n" +
738 "OpFunctionEnd",
739 2, std::numeric_limits<int32_t>::min()),
740 // Test case 30: fold UMin 3 4
741 InstructionFoldingCase<uint32_t>(
742 Header() + "%main = OpFunction %void None %void_func\n" +
743 "%main_lab = OpLabel\n" +
744 "%2 = OpExtInst %uint %1 UMin %uint_3 %uint_4\n" +
745 "OpReturn\n" +
746 "OpFunctionEnd",
747 2, 3),
748 // Test case 31: fold UMin 4 2
749 InstructionFoldingCase<uint32_t>(
750 Header() + "%main = OpFunction %void None %void_func\n" +
751 "%main_lab = OpLabel\n" +
752 "%2 = OpExtInst %uint %1 UMin %uint_4 %uint_2\n" +
753 "OpReturn\n" +
754 "OpFunctionEnd",
755 2, 2),
756 // Test case 32: fold SMin 3 4
757 InstructionFoldingCase<uint32_t>(
758 Header() + "%main = OpFunction %void None %void_func\n" +
759 "%main_lab = OpLabel\n" +
760 "%2 = OpExtInst %int %1 UMin %int_3 %int_4\n" +
761 "OpReturn\n" +
762 "OpFunctionEnd",
763 2, 3),
764 // Test case 33: fold SMin 4 2
765 InstructionFoldingCase<uint32_t>(
766 Header() + "%main = OpFunction %void None %void_func\n" +
767 "%main_lab = OpLabel\n" +
768 "%2 = OpExtInst %int %1 SMin %int_4 %int_2\n" +
769 "OpReturn\n" +
770 "OpFunctionEnd",
771 2, 2),
772 // Test case 34: fold UMax 3 4
773 InstructionFoldingCase<uint32_t>(
774 Header() + "%main = OpFunction %void None %void_func\n" +
775 "%main_lab = OpLabel\n" +
776 "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_4\n" +
777 "OpReturn\n" +
778 "OpFunctionEnd",
779 2, 4),
780 // Test case 35: fold UMax 3 2
781 InstructionFoldingCase<uint32_t>(
782 Header() + "%main = OpFunction %void None %void_func\n" +
783 "%main_lab = OpLabel\n" +
784 "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_2\n" +
785 "OpReturn\n" +
786 "OpFunctionEnd",
787 2, 3),
788 // Test case 36: fold SMax 3 4
789 InstructionFoldingCase<uint32_t>(
790 Header() + "%main = OpFunction %void None %void_func\n" +
791 "%main_lab = OpLabel\n" +
792 "%2 = OpExtInst %int %1 UMax %int_3 %int_4\n" +
793 "OpReturn\n" +
794 "OpFunctionEnd",
795 2, 4),
796 // Test case 37: fold SMax 3 2
797 InstructionFoldingCase<uint32_t>(
798 Header() + "%main = OpFunction %void None %void_func\n" +
799 "%main_lab = OpLabel\n" +
800 "%2 = OpExtInst %int %1 SMax %int_3 %int_2\n" +
801 "OpReturn\n" +
802 "OpFunctionEnd",
803 2, 3),
804 // Test case 38: fold UClamp 2 3 4
805 InstructionFoldingCase<uint32_t>(
806 Header() + "%main = OpFunction %void None %void_func\n" +
807 "%main_lab = OpLabel\n" +
808 "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_3 %uint_4\n" +
809 "OpReturn\n" +
810 "OpFunctionEnd",
811 2, 3),
812 // Test case 39: fold UClamp 2 0 4
813 InstructionFoldingCase<uint32_t>(
814 Header() + "%main = OpFunction %void None %void_func\n" +
815 "%main_lab = OpLabel\n" +
816 "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_4\n" +
817 "OpReturn\n" +
818 "OpFunctionEnd",
819 2, 2),
820 // Test case 40: fold UClamp 2 0 1
821 InstructionFoldingCase<uint32_t>(
822 Header() + "%main = OpFunction %void None %void_func\n" +
823 "%main_lab = OpLabel\n" +
824 "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_1\n" +
825 "OpReturn\n" +
826 "OpFunctionEnd",
827 2, 1),
828 // Test case 41: fold SClamp 2 3 4
829 InstructionFoldingCase<uint32_t>(
830 Header() + "%main = OpFunction %void None %void_func\n" +
831 "%main_lab = OpLabel\n" +
832 "%2 = OpExtInst %int %1 SClamp %int_2 %int_3 %int_4\n" +
833 "OpReturn\n" +
834 "OpFunctionEnd",
835 2, 3),
836 // Test case 42: fold SClamp 2 0 4
837 InstructionFoldingCase<uint32_t>(
838 Header() + "%main = OpFunction %void None %void_func\n" +
839 "%main_lab = OpLabel\n" +
840 "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_4\n" +
841 "OpReturn\n" +
842 "OpFunctionEnd",
843 2, 2),
844 // Test case 43: fold SClamp 2 0 1
845 InstructionFoldingCase<uint32_t>(
846 Header() + "%main = OpFunction %void None %void_func\n" +
847 "%main_lab = OpLabel\n" +
848 "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_1\n" +
849 "OpReturn\n" +
850 "OpFunctionEnd",
851 2, 1),
852 // Test case 44: SClamp 1 2 x
853 InstructionFoldingCase<uint32_t>(
854 Header() + "%main = OpFunction %void None %void_func\n" +
855 "%main_lab = OpLabel\n" +
856 "%undef = OpUndef %int\n" +
857 "%2 = OpExtInst %int %1 SClamp %int_1 %int_2 %undef\n" +
858 "OpReturn\n" +
859 "OpFunctionEnd",
860 2, 2),
861 // Test case 45: SClamp 2 x 1
862 InstructionFoldingCase<uint32_t>(
863 Header() + "%main = OpFunction %void None %void_func\n" +
864 "%main_lab = OpLabel\n" +
865 "%undef = OpUndef %int\n" +
866 "%2 = OpExtInst %int %1 SClamp %int_2 %undef %int_1\n" +
867 "OpReturn\n" +
868 "OpFunctionEnd",
869 2, 1),
870 // Test case 46: UClamp 1 2 x
871 InstructionFoldingCase<uint32_t>(
872 Header() + "%main = OpFunction %void None %void_func\n" +
873 "%main_lab = OpLabel\n" +
874 "%undef = OpUndef %uint\n" +
875 "%2 = OpExtInst %uint %1 UClamp %uint_1 %uint_2 %undef\n" +
876 "OpReturn\n" +
877 "OpFunctionEnd",
878 2, 2),
879 // Test case 47: UClamp 2 x 1
880 InstructionFoldingCase<uint32_t>(
881 Header() + "%main = OpFunction %void None %void_func\n" +
882 "%main_lab = OpLabel\n" +
883 "%undef = OpUndef %uint\n" +
884 "%2 = OpExtInst %uint %1 UClamp %uint_2 %undef %uint_1\n" +
885 "OpReturn\n" +
886 "OpFunctionEnd",
887 2, 1),
888 // Test case 48: Bit-cast int 0 to unsigned int
889 InstructionFoldingCase<uint32_t>(
890 Header() + "%main = OpFunction %void None %void_func\n" +
891 "%main_lab = OpLabel\n" +
892 "%2 = OpBitcast %uint %int_0\n" +
893 "OpReturn\n" +
894 "OpFunctionEnd",
895 2, 0),
896 // Test case 49: Bit-cast int -24 to unsigned int
897 InstructionFoldingCase<uint32_t>(
898 Header() + "%main = OpFunction %void None %void_func\n" +
899 "%main_lab = OpLabel\n" +
900 "%2 = OpBitcast %uint %int_n24\n" +
901 "OpReturn\n" +
902 "OpFunctionEnd",
903 2, static_cast<uint32_t>(-24)),
904 // Test case 50: Bit-cast float 1.0f to unsigned int
905 InstructionFoldingCase<uint32_t>(
906 Header() + "%main = OpFunction %void None %void_func\n" +
907 "%main_lab = OpLabel\n" +
908 "%2 = OpBitcast %uint %float_1\n" +
909 "OpReturn\n" +
910 "OpFunctionEnd",
911 2, static_cast<uint32_t>(0x3f800000)),
912 // Test case 51: Bit-cast ushort 0xBC00 to ushort
913 InstructionFoldingCase<uint32_t>(
914 Header() + "%main = OpFunction %void None %void_func\n" +
915 "%main_lab = OpLabel\n" +
916 "%2 = OpBitcast %ushort %ushort_0xBC00\n" +
917 "OpReturn\n" +
918 "OpFunctionEnd",
919 2, 0xBC00),
920 // Test case 52: Bit-cast short 0xBC00 to ushort
921 InstructionFoldingCase<uint32_t>(
922 Header() + "%main = OpFunction %void None %void_func\n" +
923 "%main_lab = OpLabel\n" +
924 "%2 = OpBitcast %ushort %short_0xBC00\n" +
925 "OpReturn\n" +
926 "OpFunctionEnd",
927 2, 0xFFFFBC00),
928 // Test case 53: Bit-cast half 1 to ushort
929 InstructionFoldingCase<uint32_t>(
930 Header() + "%main = OpFunction %void None %void_func\n" +
931 "%main_lab = OpLabel\n" +
932 "%2 = OpBitcast %ushort %half_1\n" +
933 "OpReturn\n" +
934 "OpFunctionEnd",
935 2, 0x3C00),
936 // Test case 54: Bit-cast ushort 0xBC00 to short
937 InstructionFoldingCase<uint32_t>(
938 Header() + "%main = OpFunction %void None %void_func\n" +
939 "%main_lab = OpLabel\n" +
940 "%2 = OpBitcast %short %ushort_0xBC00\n" +
941 "OpReturn\n" +
942 "OpFunctionEnd",
943 2, 0xBC00),
944 // Test case 55: Bit-cast short 0xBC00 to short
945 InstructionFoldingCase<uint32_t>(
946 Header() + "%main = OpFunction %void None %void_func\n" +
947 "%main_lab = OpLabel\n" +
948 "%2 = OpBitcast %short %short_0xBC00\n" +
949 "OpReturn\n" +
950 "OpFunctionEnd",
951 2, 0xFFFFBC00),
952 // Test case 56: Bit-cast half 1 to short
953 InstructionFoldingCase<uint32_t>(
954 Header() + "%main = OpFunction %void None %void_func\n" +
955 "%main_lab = OpLabel\n" +
956 "%2 = OpBitcast %short %half_1\n" +
957 "OpReturn\n" +
958 "OpFunctionEnd",
959 2, 0x3C00),
960 // Test case 57: Bit-cast ushort 0xBC00 to half
961 InstructionFoldingCase<uint32_t>(
962 Header() + "%main = OpFunction %void None %void_func\n" +
963 "%main_lab = OpLabel\n" +
964 "%2 = OpBitcast %half %ushort_0xBC00\n" +
965 "OpReturn\n" +
966 "OpFunctionEnd",
967 2, 0xBC00),
968 // Test case 58: Bit-cast short 0xBC00 to half
969 InstructionFoldingCase<uint32_t>(
970 Header() + "%main = OpFunction %void None %void_func\n" +
971 "%main_lab = OpLabel\n" +
972 "%2 = OpBitcast %half %short_0xBC00\n" +
973 "OpReturn\n" +
974 "OpFunctionEnd",
975 2, 0xFFFFBC00),
976 // Test case 59: Bit-cast half 1 to half
977 InstructionFoldingCase<uint32_t>(
978 Header() + "%main = OpFunction %void None %void_func\n" +
979 "%main_lab = OpLabel\n" +
980 "%2 = OpBitcast %half %half_1\n" +
981 "OpReturn\n" +
982 "OpFunctionEnd",
983 2, 0x3C00),
984 // Test case 60: Bit-cast ubyte 1 to byte
985 InstructionFoldingCase<uint32_t>(
986 Header() + "%main = OpFunction %void None %void_func\n" +
987 "%main_lab = OpLabel\n" +
988 "%2 = OpBitcast %byte %ubyte_1\n" +
989 "OpReturn\n" +
990 "OpFunctionEnd",
991 2, 1),
992 // Test case 61: Bit-cast byte -1 to ubyte
993 InstructionFoldingCase<uint32_t>(
994 Header() + "%main = OpFunction %void None %void_func\n" +
995 "%main_lab = OpLabel\n" +
996 "%2 = OpBitcast %ubyte %byte_n1\n" +
997 "OpReturn\n" +
998 "OpFunctionEnd",
999 2, 0xFFFFFFFF),
1000 // Test case 62: Negate 2.
1001 InstructionFoldingCase<uint32_t>(
1002 Header() + "%main = OpFunction %void None %void_func\n" +
1003 "%main_lab = OpLabel\n" +
1004 "%2 = OpSNegate %int %int_2\n" +
1005 "OpReturn\n" +
1006 "OpFunctionEnd",
1007 2, -2),
1008 // Test case 63: Negate negative short.
1009 InstructionFoldingCase<uint32_t>(
1010 Header() + "%main = OpFunction %void None %void_func\n" +
1011 "%main_lab = OpLabel\n" +
1012 "%2 = OpSNegate %short %short_0xBC00\n" +
1013 "OpReturn\n" +
1014 "OpFunctionEnd",
1015 2, 0x4400 /* expected to be sign extended. */),
1016 // Test case 64: Negate positive short.
1017 InstructionFoldingCase<uint32_t>(
1018 Header() + "%main = OpFunction %void None %void_func\n" +
1019 "%main_lab = OpLabel\n" +
1020 "%2 = OpSNegate %short %short_0x4400\n" +
1021 "OpReturn\n" +
1022 "OpFunctionEnd",
1023 2, 0xFFFFBC00 /* expected to be sign extended. */),
1024 // Test case 65: Negate a negative short.
1025 InstructionFoldingCase<uint32_t>(
1026 Header() + "%main = OpFunction %void None %void_func\n" +
1027 "%main_lab = OpLabel\n" +
1028 "%2 = OpSNegate %ushort %ushort_0xBC00\n" +
1029 "OpReturn\n" +
1030 "OpFunctionEnd",
1031 2, 0x4400 /* expected to be zero extended. */),
1032 // Test case 66: Negate positive short.
1033 InstructionFoldingCase<uint32_t>(
1034 Header() + "%main = OpFunction %void None %void_func\n" +
1035 "%main_lab = OpLabel\n" +
1036 "%2 = OpSNegate %ushort %ushort_0x4400\n" +
1037 "OpReturn\n" +
1038 "OpFunctionEnd",
1039 2, 0xBC00 /* expected to be zero extended. */),
1040 // Test case 67: Fold 2 + 3 (short)
1041 InstructionFoldingCase<uint32_t>(
1042 Header() + "%main = OpFunction %void None %void_func\n" +
1043 "%main_lab = OpLabel\n" +
1044 "%2 = OpIAdd %short %short_2 %short_3\n" +
1045 "OpReturn\n" +
1046 "OpFunctionEnd",
1047 2, 5),
1048 // Test case 68: Fold 2 + -5 (short)
1049 InstructionFoldingCase<uint32_t>(
1050 Header() + "%main = OpFunction %void None %void_func\n" +
1051 "%main_lab = OpLabel\n" +
1052 "%2 = OpIAdd %short %short_2 %short_n5\n" +
1053 "OpReturn\n" +
1054 "OpFunctionEnd",
1055 2, -3),
1056 // Test case 69: Fold int(3ll)
1057 InstructionFoldingCase<uint32_t>(
1058 Header() + "%main = OpFunction %void None %void_func\n" +
1059 "%main_lab = OpLabel\n" +
1060 "%2 = OpSConvert %int %long_3\n" +
1061 "OpReturn\n" +
1062 "OpFunctionEnd",
1063 2, 3),
1064 // Test case 70: Fold short(-3ll)
1065 InstructionFoldingCase<uint32_t>(
1066 Header() + "%main = OpFunction %void None %void_func\n" +
1067 "%main_lab = OpLabel\n" +
1068 "%2 = OpSConvert %short %long_n3\n" +
1069 "OpReturn\n" +
1070 "OpFunctionEnd",
1071 2, -3),
1072 // Test case 71: Fold short(32768ll) - This should do a sign extend when
1073 // converting to short.
1074 InstructionFoldingCase<uint32_t>(
1075 Header() + "%main = OpFunction %void None %void_func\n" +
1076 "%main_lab = OpLabel\n" +
1077 "%2 = OpSConvert %short %long_32768\n" +
1078 "OpReturn\n" +
1079 "OpFunctionEnd",
1080 2, -32768),
1081 // Test case 72: Fold short(-57344) - This should do a sign extend when
1082 // converting to short making the upper bits 0.
1083 InstructionFoldingCase<uint32_t>(
1084 Header() + "%main = OpFunction %void None %void_func\n" +
1085 "%main_lab = OpLabel\n" +
1086 "%2 = OpSConvert %short %long_n57344\n" +
1087 "OpReturn\n" +
1088 "OpFunctionEnd",
1089 2, 8192),
1090 // Test case 73: Fold int(-5(short)). The -5 should be interpreted as an unsigned value, and be zero extended to 32-bits.
1091 InstructionFoldingCase<uint32_t>(
1092 Header() + "%main = OpFunction %void None %void_func\n" +
1093 "%main_lab = OpLabel\n" +
1094 "%2 = OpUConvert %uint %short_n5\n" +
1095 "OpReturn\n" +
1096 "OpFunctionEnd",
1097 2, 65531),
1098 // Test case 74: Fold short(-24(int)). The upper bits should be cleared. So 0xFFFFFFE8 should become 0x0000FFE8.
1099 InstructionFoldingCase<uint32_t>(
1100 Header() + "%main = OpFunction %void None %void_func\n" +
1101 "%main_lab = OpLabel\n" +
1102 "%2 = OpUConvert %ushort %int_n24\n" +
1103 "OpReturn\n" +
1104 "OpFunctionEnd",
1105 2, 65512)
1106 ));
1107 // clang-format on
1108
1109 using LongIntegerInstructionFoldingTest =
1110 ::testing::TestWithParam<InstructionFoldingCase<uint64_t>>;
1111
TEST_P(LongIntegerInstructionFoldingTest,Case)1112 TEST_P(LongIntegerInstructionFoldingTest, Case) {
1113 const auto& tc = GetParam();
1114
1115 std::unique_ptr<IRContext> context;
1116 Instruction* inst;
1117 std::tie(context, inst) =
1118 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1119 CheckForExpectedScalarConstant(
1120 inst, tc.expected_result, [](const analysis::Constant* c) {
1121 return c->AsScalarConstant()->GetU64BitValue();
1122 });
1123 }
1124
1125 INSTANTIATE_TEST_SUITE_P(
1126 TestCase, LongIntegerInstructionFoldingTest,
1127 ::testing::Values(
1128 // Test case 0: fold 1+4611686018427387904
1129 InstructionFoldingCase<uint64_t>(
1130 Header() + "%main = OpFunction %void None %void_func\n" +
1131 "%main_lab = OpLabel\n" +
1132 "%n = OpVariable %_ptr_int Function\n" +
1133 "%load = OpLoad %int %n\n" +
1134 "%2 = OpIAdd %long %long_1 %long_4611686018427387904\n" +
1135 "OpReturn\n" + "OpFunctionEnd",
1136 2, 1 + 4611686018427387904),
1137 // Test case 1: fold 1-4611686018427387904
1138 InstructionFoldingCase<uint64_t>(
1139 Header() + "%main = OpFunction %void None %void_func\n" +
1140 "%main_lab = OpLabel\n" +
1141 "%n = OpVariable %_ptr_int Function\n" +
1142 "%load = OpLoad %int %n\n" +
1143 "%2 = OpISub %long %long_1 %long_4611686018427387904\n" +
1144 "OpReturn\n" + "OpFunctionEnd",
1145 2, 1 - 4611686018427387904),
1146 // Test case 2: fold 2*4611686018427387904
1147 InstructionFoldingCase<uint64_t>(
1148 Header() + "%main = OpFunction %void None %void_func\n" +
1149 "%main_lab = OpLabel\n" +
1150 "%n = OpVariable %_ptr_int Function\n" +
1151 "%load = OpLoad %int %n\n" +
1152 "%2 = OpIMul %long %long_2 %long_4611686018427387904\n" +
1153 "OpReturn\n" + "OpFunctionEnd",
1154 2, 9223372036854775808ull),
1155 // Test case 3: fold 4611686018427387904/2 (unsigned)
1156 InstructionFoldingCase<uint64_t>(
1157 Header() + "%main = OpFunction %void None %void_func\n" +
1158 "%main_lab = OpLabel\n" +
1159 "%n = OpVariable %_ptr_int Function\n" +
1160 "%load = OpLoad %int %n\n" +
1161 "%2 = OpUDiv %ulong %ulong_4611686018427387904 %ulong_2\n" +
1162 "OpReturn\n" + "OpFunctionEnd",
1163 2, 4611686018427387904 / 2),
1164 // Test case 4: fold 4611686018427387904/2 (signed)
1165 InstructionFoldingCase<uint64_t>(
1166 Header() + "%main = OpFunction %void None %void_func\n" +
1167 "%main_lab = OpLabel\n" +
1168 "%n = OpVariable %_ptr_int Function\n" +
1169 "%load = OpLoad %int %n\n" +
1170 "%2 = OpSDiv %long %long_4611686018427387904 %long_2\n" +
1171 "OpReturn\n" + "OpFunctionEnd",
1172 2, 4611686018427387904 / 2),
1173 // Test case 5: fold -4611686018427387904/2 (signed)
1174 InstructionFoldingCase<uint64_t>(
1175 Header() + "%main = OpFunction %void None %void_func\n" +
1176 "%main_lab = OpLabel\n" +
1177 "%n = OpVariable %_ptr_int Function\n" +
1178 "%load = OpLoad %int %n\n" +
1179 "%2 = OpSDiv %long %long_n4611686018427387904 %long_2\n" +
1180 "OpReturn\n" + "OpFunctionEnd",
1181 2, -4611686018427387904 / 2),
1182 // Test case 6: fold 4611686018427387904 mod 7 (unsigned)
1183 InstructionFoldingCase<uint64_t>(
1184 Header() + "%main = OpFunction %void None %void_func\n" +
1185 "%main_lab = OpLabel\n" +
1186 "%n = OpVariable %_ptr_int Function\n" +
1187 "%load = OpLoad %int %n\n" +
1188 "%2 = OpUMod %ulong %ulong_4611686018427387904 %ulong_7\n" +
1189 "OpReturn\n" + "OpFunctionEnd",
1190 2, 4611686018427387904ull % 7ull),
1191 // Test case 7: fold 7 mod 3 (signed)
1192 InstructionFoldingCase<uint64_t>(
1193 Header() + "%main = OpFunction %void None %void_func\n" +
1194 "%main_lab = OpLabel\n" +
1195 "%n = OpVariable %_ptr_int Function\n" +
1196 "%load = OpLoad %int %n\n" +
1197 "%2 = OpSMod %long %long_7 %long_3\n" + "OpReturn\n" +
1198 "OpFunctionEnd",
1199 2, 1ull),
1200 // Test case 8: fold 7 rem 3 (signed)
1201 InstructionFoldingCase<uint64_t>(
1202 Header() + "%main = OpFunction %void None %void_func\n" +
1203 "%main_lab = OpLabel\n" +
1204 "%n = OpVariable %_ptr_int Function\n" +
1205 "%load = OpLoad %int %n\n" +
1206 "%2 = OpSRem %long %long_7 %long_3\n" + "OpReturn\n" +
1207 "OpFunctionEnd",
1208 2, 1ull),
1209 // Test case 9: fold 7 mod -3 (signed)
1210 InstructionFoldingCase<uint64_t>(
1211 Header() + "%main = OpFunction %void None %void_func\n" +
1212 "%main_lab = OpLabel\n" +
1213 "%n = OpVariable %_ptr_int Function\n" +
1214 "%load = OpLoad %int %n\n" +
1215 "%2 = OpSMod %long %long_7 %long_n3\n" + "OpReturn\n" +
1216 "OpFunctionEnd",
1217 2, -2ll),
1218 // Test case 10: fold 7 rem 3 (signed)
1219 InstructionFoldingCase<uint64_t>(
1220 Header() + "%main = OpFunction %void None %void_func\n" +
1221 "%main_lab = OpLabel\n" +
1222 "%n = OpVariable %_ptr_int Function\n" +
1223 "%load = OpLoad %int %n\n" +
1224 "%2 = OpSRem %long %long_7 %long_n3\n" + "OpReturn\n" +
1225 "OpFunctionEnd",
1226 2, 1ll),
1227 // Test case 11: fold -7 mod 3 (signed)
1228 InstructionFoldingCase<uint64_t>(
1229 Header() + "%main = OpFunction %void None %void_func\n" +
1230 "%main_lab = OpLabel\n" +
1231 "%n = OpVariable %_ptr_int Function\n" +
1232 "%load = OpLoad %int %n\n" +
1233 "%2 = OpSMod %long %long_n7 %long_3\n" + "OpReturn\n" +
1234 "OpFunctionEnd",
1235 2, 2ll),
1236 // Test case 12: fold -7 rem 3 (signed)
1237 InstructionFoldingCase<uint64_t>(
1238 Header() + "%main = OpFunction %void None %void_func\n" +
1239 "%main_lab = OpLabel\n" +
1240 "%n = OpVariable %_ptr_int Function\n" +
1241 "%load = OpLoad %int %n\n" +
1242 "%2 = OpSRem %long %long_n7 %long_3\n" + "OpReturn\n" +
1243 "OpFunctionEnd",
1244 2, -1ll),
1245 // Test case 13: fold long(-24)
1246 InstructionFoldingCase<uint64_t>(
1247 Header() + "%main = OpFunction %void None %void_func\n" +
1248 "%main_lab = OpLabel\n" +
1249 "%n = OpVariable %_ptr_int Function\n" +
1250 "%load = OpLoad %int %n\n" +
1251 "%2 = OpSConvert %long %int_n24\n" + "OpReturn\n" +
1252 "OpFunctionEnd",
1253 2, -24ll),
1254 // Test case 14: fold long(-24)
1255 InstructionFoldingCase<uint64_t>(
1256 Header() + "%main = OpFunction %void None %void_func\n" +
1257 "%main_lab = OpLabel\n" +
1258 "%n = OpVariable %_ptr_int Function\n" +
1259 "%load = OpLoad %int %n\n" + "%2 = OpSConvert %long %int_10\n" +
1260 "OpReturn\n" + "OpFunctionEnd",
1261 2, 10ll),
1262 // Test case 15: fold long(-24(short)).
1263 // The upper bits should be cleared. So 0xFFFFFFE8 should become
1264 // 0x000000000000FFE8.
1265 InstructionFoldingCase<uint64_t>(
1266 Header() + "%main = OpFunction %void None %void_func\n" +
1267 "%main_lab = OpLabel\n" + "%2 = OpUConvert %ulong %short_n5\n" +
1268 "OpReturn\n" + "OpFunctionEnd",
1269 2, 65531ull)));
1270
1271 using UIntVectorInstructionFoldingTest =
1272 ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint32_t>>>;
1273
TEST_P(UIntVectorInstructionFoldingTest,Case)1274 TEST_P(UIntVectorInstructionFoldingTest, Case) {
1275 const auto& tc = GetParam();
1276
1277 std::unique_ptr<IRContext> context;
1278 Instruction* inst;
1279 std::tie(context, inst) =
1280 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1281 CheckForExpectedVectorConstant(
1282 inst, tc.expected_result,
1283 [](const analysis::Constant* c) { return c->GetU32(); });
1284 }
1285
1286 // clang-format off
1287 INSTANTIATE_TEST_SUITE_P(TestCase, UIntVectorInstructionFoldingTest,
1288 ::testing::Values(
1289 // Test case 0: fold 0*n
1290 InstructionFoldingCase<std::vector<uint32_t>>(
1291 Header() + "%main = OpFunction %void None %void_func\n" +
1292 "%main_lab = OpLabel\n" +
1293 "%n = OpVariable %_ptr_int Function\n" +
1294 "%load = OpLoad %int %n\n" +
1295 "%2 = OpVectorShuffle %v2int %v2int_2_2 %v2int_2_3 0 3\n" +
1296 "OpReturn\n" +
1297 "OpFunctionEnd",
1298 2, {2,3}),
1299 InstructionFoldingCase<std::vector<uint32_t>>(
1300 Header() + "%main = OpFunction %void None %void_func\n" +
1301 "%main_lab = OpLabel\n" +
1302 "%n = OpVariable %_ptr_int Function\n" +
1303 "%load = OpLoad %int %n\n" +
1304 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
1305 "OpReturn\n" +
1306 "OpFunctionEnd",
1307 2, {0,3}),
1308 // Test case 4: fold bit-cast int -24 to unsigned int
1309 InstructionFoldingCase<std::vector<uint32_t>>(
1310 Header() + "%main = OpFunction %void None %void_func\n" +
1311 "%main_lab = OpLabel\n" +
1312 "%n = OpVariable %_ptr_int Function\n" +
1313 "%load = OpLoad %int %n\n" +
1314 "%2 = OpBitcast %v2uint %v2int_min_max\n" +
1315 "OpReturn\n" +
1316 "OpFunctionEnd",
1317 2, {2147483648, 2147483647}),
1318 // Test case 5: fold SNegate vector of uint
1319 InstructionFoldingCase<std::vector<uint32_t>>(
1320 Header() + "%main = OpFunction %void None %void_func\n" +
1321 "%main_lab = OpLabel\n" +
1322 "%n = OpVariable %_ptr_int Function\n" +
1323 "%load = OpLoad %int %n\n" +
1324 "%2 = OpSNegate %v2uint %v2uint_0x3f800000_0xbf800000\n" +
1325 "OpReturn\n" +
1326 "OpFunctionEnd",
1327 2, {static_cast<uint32_t>(-0x3f800000), static_cast<uint32_t>(-0xbf800000)}),
1328 // Test case 6: fold vector components of uint (including integer overflow)
1329 InstructionFoldingCase<std::vector<uint32_t>>(
1330 Header() + "%main = OpFunction %void None %void_func\n" +
1331 "%main_lab = OpLabel\n" +
1332 "%2 = OpIAdd %v2uint %v2uint_0x3f800000_0xbf800000 %v2uint_0x3f800000_0xbf800000\n" +
1333 "OpReturn\n" +
1334 "OpFunctionEnd",
1335 2, {0x7f000000u, 0x7f000000u}),
1336 // Test case 6: fold vector components of uint
1337 InstructionFoldingCase<std::vector<uint32_t>>(
1338 Header() + "%main = OpFunction %void None %void_func\n" +
1339 "%main_lab = OpLabel\n" +
1340 "%2 = OpSConvert %v2int %v2short_2_n5\n" +
1341 "OpReturn\n" +
1342 "OpFunctionEnd",
1343 2, {2,static_cast<uint32_t>(-5)}),
1344 // Test case 6: fold vector components of uint (incuding integer overflow)
1345 InstructionFoldingCase<std::vector<uint32_t>>(
1346 Header() + "%main = OpFunction %void None %void_func\n" +
1347 "%main_lab = OpLabel\n" +
1348 "%2 = OpUConvert %v2uint %v2short_2_n5\n" +
1349 "OpReturn\n" +
1350 "OpFunctionEnd",
1351 2, {2,65531})
1352 ));
1353 // clang-format on
1354
1355 using IntVectorInstructionFoldingTest =
1356 ::testing::TestWithParam<InstructionFoldingCase<std::vector<int32_t>>>;
1357
TEST_P(IntVectorInstructionFoldingTest,Case)1358 TEST_P(IntVectorInstructionFoldingTest, Case) {
1359 const auto& tc = GetParam();
1360
1361 std::unique_ptr<IRContext> context;
1362 Instruction* inst;
1363 std::tie(context, inst) =
1364 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1365
1366 CheckForExpectedVectorConstant(
1367 inst, tc.expected_result,
1368 [](const analysis::Constant* c) { return c->GetS32(); });
1369 }
1370
1371 // clang-format off
1372 INSTANTIATE_TEST_SUITE_P(TestCase, IntVectorInstructionFoldingTest,
1373 ::testing::Values(
1374 // Test case 0: fold negate of a vector
1375 InstructionFoldingCase<std::vector<int32_t>>(
1376 Header() + "%main = OpFunction %void None %void_func\n" +
1377 "%main_lab = OpLabel\n" +
1378 "%2 = OpSNegate %v2int %v2int_2_3\n" +
1379 "OpReturn\n" +
1380 "OpFunctionEnd",
1381 2, {-2, -3}),
1382 // Test case 1: fold negate of a vector containing negative values.
1383 InstructionFoldingCase<std::vector<int32_t>>(
1384 Header() + "%main = OpFunction %void None %void_func\n" +
1385 "%main_lab = OpLabel\n" +
1386 "%2 = OpSNegate %v2int %v2int_n1_n24\n" +
1387 "OpReturn\n" +
1388 "OpFunctionEnd",
1389 2, {1, 24}),
1390 // Test case 2: fold negate of a vector at the limits
1391 InstructionFoldingCase<std::vector<int32_t>>(
1392 Header() + "%main = OpFunction %void None %void_func\n" +
1393 "%main_lab = OpLabel\n" +
1394 "%2 = OpSNegate %v2int %v2int_min_max\n" +
1395 "OpReturn\n" +
1396 "OpFunctionEnd",
1397 2, {INT_MIN, -INT_MAX}),
1398 // Test case 3: fold vector components of int
1399 InstructionFoldingCase<std::vector<int32_t>>(
1400 Header() + "%main = OpFunction %void None %void_func\n" +
1401 "%main_lab = OpLabel\n" +
1402 "%2 = OpIMul %v2int %v2int_2_3 %v2int_2_3\n" +
1403 "OpReturn\n" +
1404 "OpFunctionEnd",
1405 2, {4,9})
1406 ));
1407 // clang-format on
1408
1409 using LongIntVectorInstructionFoldingTest =
1410 ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint64_t>>>;
1411
TEST_P(LongIntVectorInstructionFoldingTest,Case)1412 TEST_P(LongIntVectorInstructionFoldingTest, Case) {
1413 const auto& tc = GetParam();
1414
1415 std::unique_ptr<IRContext> context;
1416 Instruction* inst;
1417 std::tie(context, inst) =
1418 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1419 CheckForExpectedVectorConstant(
1420 inst, tc.expected_result,
1421 [](const analysis::Constant* c) { return c->GetU64(); });
1422 }
1423
1424 // clang-format off
1425 INSTANTIATE_TEST_SUITE_P(TestCase, LongIntVectorInstructionFoldingTest,
1426 ::testing::Values(
1427 // Test case 0: fold {2,2} + {2,3} (Testing that the vector logic works
1428 // correctly. Scalar tests will check that the 64-bit values are correctly
1429 // folded.)
1430 InstructionFoldingCase<std::vector<uint64_t>>(
1431 Header() + "%main = OpFunction %void None %void_func\n" +
1432 "%main_lab = OpLabel\n" +
1433 "%n = OpVariable %_ptr_int Function\n" +
1434 "%load = OpLoad %int %n\n" +
1435 "%2 = OpIAdd %v2long %v2long_2_2 %v2long_2_3\n" +
1436 "OpReturn\n" +
1437 "OpFunctionEnd",
1438 2, {4,5}),
1439 // Test case 0: fold {2,2} / {2,3} (Testing that the vector logic works
1440 // correctly. Scalar tests will check that the 64-bit values are correctly
1441 // folded.)
1442 InstructionFoldingCase<std::vector<uint64_t>>(
1443 Header() + "%main = OpFunction %void None %void_func\n" +
1444 "%main_lab = OpLabel\n" +
1445 "%n = OpVariable %_ptr_int Function\n" +
1446 "%load = OpLoad %int %n\n" +
1447 "%2 = OpSDiv %v2long %v2long_2_2 %v2long_2_3\n" +
1448 "OpReturn\n" +
1449 "OpFunctionEnd",
1450 2, {1,0})
1451 ));
1452 // clang-format on
1453
1454 using DoubleVectorInstructionFoldingTest =
1455 ::testing::TestWithParam<InstructionFoldingCase<std::vector<double>>>;
1456
TEST_P(DoubleVectorInstructionFoldingTest,Case)1457 TEST_P(DoubleVectorInstructionFoldingTest, Case) {
1458 const auto& tc = GetParam();
1459
1460 std::unique_ptr<IRContext> context;
1461 Instruction* inst;
1462 std::tie(context, inst) =
1463 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1464 CheckForExpectedVectorConstant(
1465 inst, tc.expected_result,
1466 [](const analysis::Constant* c) { return c->GetDouble(); });
1467 }
1468
1469 // clang-format off
1470 INSTANTIATE_TEST_SUITE_P(TestCase, DoubleVectorInstructionFoldingTest,
1471 ::testing::Values(
1472 // Test case 0: bit-cast int {0x3FF00000,0x00000000,0xC05FD666,0x66666666}
1473 // to double vector
1474 InstructionFoldingCase<std::vector<double>>(
1475 Header() + "%main = OpFunction %void None %void_func\n" +
1476 "%main_lab = OpLabel\n" +
1477 "%2 = OpBitcast %v2double %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666\n" +
1478 "OpReturn\n" +
1479 "OpFunctionEnd",
1480 2, {1.0,-127.35}),
1481 // Test case 1: OpVectorTimesMatrix Non-Zero Zero {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {1.0, 2.0, 3.0, 4.0} {0.0, 0.0, 0.0, 0.0}
1482 InstructionFoldingCase<std::vector<double>>(
1483 Header() +
1484 "%main = OpFunction %void None %void_func\n" +
1485 "%main_lab = OpLabel\n" +
1486 "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_null\n" +
1487 "OpReturn\n" +
1488 "OpFunctionEnd",
1489 2, {0.0,0.0,0.0,0.0}),
1490 // Test case 2: OpVectorTimesMatrix Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1491 InstructionFoldingCase<std::vector<double>>(
1492 Header() +
1493 "%main = OpFunction %void None %void_func\n" +
1494 "%main_lab = OpLabel\n" +
1495 "%2 = OpVectorTimesMatrix %v4double %v4double_null %mat4v4double_1_2_3_4\n" +
1496 "OpReturn\n" +
1497 "OpFunctionEnd",
1498 2, {0.0,0.0,0.0,0.0}),
1499 // Test case 3: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {1.0, 2.0, 3.0, 4.0} {30.0, 30.0, 30.0, 30.0}
1500 InstructionFoldingCase<std::vector<double>>(
1501 Header() +
1502 "%main = OpFunction %void None %void_func\n" +
1503 "%main_lab = OpLabel\n" +
1504 "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_1_2_3_4\n" +
1505 "OpReturn\n" +
1506 "OpFunctionEnd",
1507 2, {30.0,30.0,30.0,30.0}),
1508 // Test case 4: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {1.0, 2.0, 3.0, 4.0} {30.0, 0.0, 30.0, 0.0}
1509 InstructionFoldingCase<std::vector<double>>(
1510 Header() +
1511 "%main = OpFunction %void None %void_func\n" +
1512 "%main_lab = OpLabel\n" +
1513 "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_1_2_3_4_null\n" +
1514 "OpReturn\n" +
1515 "OpFunctionEnd",
1516 2, {30.0,0.0,30.0,0.0}),
1517 // Test case 5: OpMatrixTimesVector Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {0.0, 0.0, 0.0, 0.0}
1518 InstructionFoldingCase<std::vector<double>>(
1519 Header() +
1520 "%main = OpFunction %void None %void_func\n" +
1521 "%main_lab = OpLabel\n" +
1522 "%2 = OpMatrixTimesVector %v4double %mat4v4double_null %v4double_1_2_3_4\n" +
1523 "OpReturn\n" +
1524 "OpFunctionEnd",
1525 2, {0.0,0.0,0.0,0.0}),
1526 // Test case 6: OpMatrixTimesVector Non-Zero Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1527 InstructionFoldingCase<std::vector<double>>(
1528 Header() +
1529 "%main = OpFunction %void None %void_func\n" +
1530 "%main_lab = OpLabel\n" +
1531 "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4 %v4double_null\n" +
1532 "OpReturn\n" +
1533 "OpFunctionEnd",
1534 2, {0.0,0.0,0.0,0.0}),
1535 // Test case 7: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {10.0, 20.0, 30.0, 40.0}
1536 InstructionFoldingCase<std::vector<double>>(
1537 Header() +
1538 "%main = OpFunction %void None %void_func\n" +
1539 "%main_lab = OpLabel\n" +
1540 "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4 %v4double_1_2_3_4\n" +
1541 "OpReturn\n" +
1542 "OpFunctionEnd",
1543 2, {10.0,20.0,30.0,40.0}),
1544 // Test case 8: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {10.0, 20.0, 30.0, 40.0}
1545 InstructionFoldingCase<std::vector<double>>(
1546 Header() +
1547 "%main = OpFunction %void None %void_func\n" +
1548 "%main_lab = OpLabel\n" +
1549 "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4_null %v4double_1_2_3_4\n" +
1550 "OpReturn\n" +
1551 "OpFunctionEnd",
1552 2, {4.0,8.0,12.0,16.0})
1553 ));
1554
1555 using FloatVectorInstructionFoldingTest =
1556 ::testing::TestWithParam<InstructionFoldingCase<std::vector<float>>>;
1557
TEST_P(FloatVectorInstructionFoldingTest,Case)1558 TEST_P(FloatVectorInstructionFoldingTest, Case) {
1559 const auto& tc = GetParam();
1560
1561 std::unique_ptr<IRContext> context;
1562 Instruction* inst;
1563 std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
1564 CheckForExpectedVectorConstant(inst, tc.expected_result, [](const analysis::Constant* c){ return c->GetFloat();});
1565 }
1566
1567 // clang-format off
1568 INSTANTIATE_TEST_SUITE_P(TestCase, FloatVectorInstructionFoldingTest,
1569 ::testing::Values(
1570 // Test case 0: FMix {2.0, 2.0}, {2.0, 3.0} {0.2,0.5}
1571 InstructionFoldingCase<std::vector<float>>(
1572 Header() + "%main = OpFunction %void None %void_func\n" +
1573 "%main_lab = OpLabel\n" +
1574 "%2 = OpExtInst %v2float %1 FMix %v2float_2_3 %v2float_0_0 %v2float_0p2_0p5\n" +
1575 "OpReturn\n" +
1576 "OpFunctionEnd",
1577 2, {1.6f,1.5f}),
1578 // Test case 1: bit-cast unsigned int vector {0x3f800000, 0xbf800000} to
1579 // float vector
1580 InstructionFoldingCase<std::vector<float>>(
1581 Header() + "%main = OpFunction %void None %void_func\n" +
1582 "%main_lab = OpLabel\n" +
1583 "%2 = OpBitcast %v2float %v2uint_0x3f800000_0xbf800000\n" +
1584 "OpReturn\n" +
1585 "OpFunctionEnd",
1586 2, {1.0f,-1.0f}),
1587 // Test case 2: bit-cast long int 0xbf8000003f800000 to float vector
1588 InstructionFoldingCase<std::vector<float>>(
1589 Header() + "%main = OpFunction %void None %void_func\n" +
1590 "%main_lab = OpLabel\n" +
1591 "%2 = OpBitcast %v2float %long_0xbf8000003f800000\n" +
1592 "OpReturn\n" +
1593 "OpFunctionEnd",
1594 2, {1.0f,-1.0f}),
1595 // Test case 3: OpVectorTimesMatrix Non-Zero Zero {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {1.0, 2.0, 3.0, 4.0} {0.0, 0.0, 0.0, 0.0}
1596 InstructionFoldingCase<std::vector<float>>(
1597 Header() +
1598 "%main = OpFunction %void None %void_func\n" +
1599 "%main_lab = OpLabel\n" +
1600 "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_null\n" +
1601 "OpReturn\n" +
1602 "OpFunctionEnd",
1603 2, {0.0f,0.0f,0.0f,0.0f}),
1604 // Test case 4: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {1.0, 2.0, 3.0, 4.0} {30.0, 0.0, 30.0, 0.0}
1605 InstructionFoldingCase<std::vector<float>>(
1606 Header() +
1607 "%main = OpFunction %void None %void_func\n" +
1608 "%main_lab = OpLabel\n" +
1609 "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_1_2_3_4_null\n" +
1610 "OpReturn\n" +
1611 "OpFunctionEnd",
1612 2, {30.0,0.0,30.0,0.0}),
1613 // Test case 5: OpVectorTimesMatrix Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1614 InstructionFoldingCase<std::vector<float>>(
1615 Header() +
1616 "%main = OpFunction %void None %void_func\n" +
1617 "%main_lab = OpLabel\n" +
1618 "%2 = OpVectorTimesMatrix %v4float %v4float_null %mat4v4float_1_2_3_4\n" +
1619 "OpReturn\n" +
1620 "OpFunctionEnd",
1621 2, {0.0f,0.0f,0.0f,0.0f}),
1622 // Test case 6: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {1.0, 2.0, 3.0, 4.0} {30.0, 30.0, 30.0, 30.0}
1623 InstructionFoldingCase<std::vector<float>>(
1624 Header() +
1625 "%main = OpFunction %void None %void_func\n" +
1626 "%main_lab = OpLabel\n" +
1627 "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_1_2_3_4\n" +
1628 "OpReturn\n" +
1629 "OpFunctionEnd",
1630 2, {30.0f,30.0f,30.0f,30.0f}),
1631 // Test case 7: OpMatrixTimesVector Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {0.0, 0.0, 0.0, 0.0}
1632 InstructionFoldingCase<std::vector<float>>(
1633 Header() +
1634 "%main = OpFunction %void None %void_func\n" +
1635 "%main_lab = OpLabel\n" +
1636 "%2 = OpMatrixTimesVector %v4float %mat4v4float_null %v4float_1_2_3_4\n" +
1637 "OpReturn\n" +
1638 "OpFunctionEnd",
1639 2, {0.0f,0.0f,0.0f,0.0f}),
1640 // Test case 8: OpMatrixTimesVector Non-Zero Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1641 InstructionFoldingCase<std::vector<float>>(
1642 Header() +
1643 "%main = OpFunction %void None %void_func\n" +
1644 "%main_lab = OpLabel\n" +
1645 "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4 %v4float_null\n" +
1646 "OpReturn\n" +
1647 "OpFunctionEnd",
1648 2, {0.0f,0.0f,0.0f,0.0f}),
1649 // Test case 9: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {10.0, 20.0, 30.0, 40.0}
1650 InstructionFoldingCase<std::vector<float>>(
1651 Header() +
1652 "%main = OpFunction %void None %void_func\n" +
1653 "%main_lab = OpLabel\n" +
1654 "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4 %v4float_1_2_3_4\n" +
1655 "OpReturn\n" +
1656 "OpFunctionEnd",
1657 2, {10.0f,20.0f,30.0f,40.0f}),
1658 // Test case 10: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {10.0, 20.0, 30.0, 40.0}
1659 InstructionFoldingCase<std::vector<float>>(
1660 Header() +
1661 "%main = OpFunction %void None %void_func\n" +
1662 "%main_lab = OpLabel\n" +
1663 "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4_null %v4float_1_2_3_4\n" +
1664 "OpReturn\n" +
1665 "OpFunctionEnd",
1666 2, {4.0,8.0,12.0,16.0})
1667 ));
1668 // clang-format on
1669
1670 using FloatMatrixInstructionFoldingTest = ::testing::TestWithParam<
1671 InstructionFoldingCase<std::vector<std::vector<float>>>>;
1672
TEST_P(FloatMatrixInstructionFoldingTest,Case)1673 TEST_P(FloatMatrixInstructionFoldingTest, Case) {
1674 const auto& tc = GetParam();
1675
1676 std::unique_ptr<IRContext> context;
1677 Instruction* inst;
1678 std::tie(context, inst) =
1679 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1680
1681 EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
1682 if (inst->opcode() == spv::Op::OpCopyObject) {
1683 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
1684 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
1685 analysis::ConstantManager* const_mgr = context->get_constant_mgr();
1686 const analysis::Constant* result = const_mgr->GetConstantFromInst(inst);
1687 EXPECT_NE(result, nullptr);
1688 if (result != nullptr) {
1689 std::vector<const analysis::Constant*> matrix =
1690 result->AsMatrixConstant()->GetComponents();
1691 EXPECT_EQ(matrix.size(), tc.expected_result.size());
1692 for (size_t c = 0; c < matrix.size(); c++) {
1693 if (matrix[c]->AsNullConstant() != nullptr) {
1694 matrix[c] = const_mgr->GetNullCompositeConstant(matrix[c]->type());
1695 }
1696 const analysis::VectorConstant* column_const =
1697 matrix[c]->AsVectorConstant();
1698 ASSERT_NE(column_const, nullptr);
1699 const std::vector<const analysis::Constant*>& column =
1700 column_const->GetComponents();
1701 EXPECT_EQ(column.size(), tc.expected_result[c].size());
1702 for (size_t r = 0; r < column.size(); r++) {
1703 EXPECT_EQ(tc.expected_result[c][r], column[r]->GetFloat());
1704 }
1705 }
1706 }
1707 }
1708 }
1709
1710 // clang-format off
1711 INSTANTIATE_TEST_SUITE_P(TestCase, FloatMatrixInstructionFoldingTest,
1712 ::testing::Values(
1713 // Test case 0: OpTranspose square null matrix
1714 InstructionFoldingCase<std::vector<std::vector<float>>>(
1715 Header() + "%main = OpFunction %void None %void_func\n" +
1716 "%main_lab = OpLabel\n" +
1717 "%2 = OpTranspose %mat4v4float %mat4v4float_null\n" +
1718 "OpReturn\n" +
1719 "OpFunctionEnd",
1720 2, {{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f}}),
1721 // Test case 1: OpTranspose rectangular null matrix
1722 InstructionFoldingCase<std::vector<std::vector<float>>>(
1723 Header() + "%main = OpFunction %void None %void_func\n" +
1724 "%main_lab = OpLabel\n" +
1725 "%2 = OpTranspose %mat4v2float %mat2v4float_null\n" +
1726 "OpReturn\n" +
1727 "OpFunctionEnd",
1728 2, {{0.0f, 0.0f},{0.0f, 0.0f},{0.0f, 0.0f},{0.0f, 0.0f}}),
1729 InstructionFoldingCase<std::vector<std::vector<float>>>(
1730 Header() + "%main = OpFunction %void None %void_func\n" +
1731 "%main_lab = OpLabel\n" +
1732 "%2 = OpTranspose %mat4v4float %mat4v4float_1_2_3_4\n" +
1733 "OpReturn\n" +
1734 "OpFunctionEnd",
1735 2, {{1.0f, 1.0f, 1.0f, 1.0f},{2.0f, 2.0f, 2.0f, 2.0f},{3.0f, 3.0f, 3.0f, 3.0f},{4.0f, 4.0f, 4.0f, 4.0f}})
1736 ));
1737 // clang-format on
1738
1739 using BooleanInstructionFoldingTest =
1740 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
1741
TEST_P(BooleanInstructionFoldingTest,Case)1742 TEST_P(BooleanInstructionFoldingTest, Case) {
1743 const auto& tc = GetParam();
1744
1745 std::unique_ptr<IRContext> context;
1746 Instruction* inst;
1747 std::tie(context, inst) =
1748 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1749 CheckForExpectedScalarConstant(
1750 inst, tc.expected_result,
1751 [](const analysis::Constant* c) { return c->AsBoolConstant()->value(); });
1752 }
1753
1754 // clang-format off
1755 INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTest,
1756 ::testing::Values(
1757 // Test case 0: fold true || n
1758 InstructionFoldingCase<bool>(
1759 Header() + "%main = OpFunction %void None %void_func\n" +
1760 "%main_lab = OpLabel\n" +
1761 "%n = OpVariable %_ptr_bool Function\n" +
1762 "%load = OpLoad %bool %n\n" +
1763 "%2 = OpLogicalOr %bool %true %load\n" +
1764 "OpReturn\n" +
1765 "OpFunctionEnd",
1766 2, true),
1767 // Test case 1: fold n || true
1768 InstructionFoldingCase<bool>(
1769 Header() + "%main = OpFunction %void None %void_func\n" +
1770 "%main_lab = OpLabel\n" +
1771 "%n = OpVariable %_ptr_bool Function\n" +
1772 "%load = OpLoad %bool %n\n" +
1773 "%2 = OpLogicalOr %bool %load %true\n" +
1774 "OpReturn\n" +
1775 "OpFunctionEnd",
1776 2, true),
1777 // Test case 2: fold false && n
1778 InstructionFoldingCase<bool>(
1779 Header() + "%main = OpFunction %void None %void_func\n" +
1780 "%main_lab = OpLabel\n" +
1781 "%n = OpVariable %_ptr_bool Function\n" +
1782 "%load = OpLoad %bool %n\n" +
1783 "%2 = OpLogicalAnd %bool %false %load\n" +
1784 "OpReturn\n" +
1785 "OpFunctionEnd",
1786 2, false),
1787 // Test case 3: fold n && false
1788 InstructionFoldingCase<bool>(
1789 Header() + "%main = OpFunction %void None %void_func\n" +
1790 "%main_lab = OpLabel\n" +
1791 "%n = OpVariable %_ptr_bool Function\n" +
1792 "%load = OpLoad %bool %n\n" +
1793 "%2 = OpLogicalAnd %bool %load %false\n" +
1794 "OpReturn\n" +
1795 "OpFunctionEnd",
1796 2, false),
1797 // Test case 4: fold n < 0 (unsigned)
1798 InstructionFoldingCase<bool>(
1799 Header() + "%main = OpFunction %void None %void_func\n" +
1800 "%main_lab = OpLabel\n" +
1801 "%n = OpVariable %_ptr_uint Function\n" +
1802 "%load = OpLoad %uint %n\n" +
1803 "%2 = OpULessThan %bool %load %uint_0\n" +
1804 "OpReturn\n" +
1805 "OpFunctionEnd",
1806 2, false),
1807 // Test case 5: fold UINT_MAX < n (unsigned)
1808 InstructionFoldingCase<bool>(
1809 Header() + "%main = OpFunction %void None %void_func\n" +
1810 "%main_lab = OpLabel\n" +
1811 "%n = OpVariable %_ptr_uint Function\n" +
1812 "%load = OpLoad %uint %n\n" +
1813 "%2 = OpULessThan %bool %uint_max %load\n" +
1814 "OpReturn\n" +
1815 "OpFunctionEnd",
1816 2, false),
1817 // Test case 6: fold INT_MAX < n (signed)
1818 InstructionFoldingCase<bool>(
1819 Header() + "%main = OpFunction %void None %void_func\n" +
1820 "%main_lab = OpLabel\n" +
1821 "%n = OpVariable %_ptr_int Function\n" +
1822 "%load = OpLoad %int %n\n" +
1823 "%2 = OpSLessThan %bool %int_max %load\n" +
1824 "OpReturn\n" +
1825 "OpFunctionEnd",
1826 2, false),
1827 // Test case 7: fold n < INT_MIN (signed)
1828 InstructionFoldingCase<bool>(
1829 Header() + "%main = OpFunction %void None %void_func\n" +
1830 "%main_lab = OpLabel\n" +
1831 "%n = OpVariable %_ptr_int Function\n" +
1832 "%load = OpLoad %int %n\n" +
1833 "%2 = OpSLessThan %bool %load %int_min\n" +
1834 "OpReturn\n" +
1835 "OpFunctionEnd",
1836 2, false),
1837 // Test case 8: fold 0 > n (unsigned)
1838 InstructionFoldingCase<bool>(
1839 Header() + "%main = OpFunction %void None %void_func\n" +
1840 "%main_lab = OpLabel\n" +
1841 "%n = OpVariable %_ptr_uint Function\n" +
1842 "%load = OpLoad %uint %n\n" +
1843 "%2 = OpUGreaterThan %bool %uint_0 %load\n" +
1844 "OpReturn\n" +
1845 "OpFunctionEnd",
1846 2, false),
1847 // Test case 9: fold n > UINT_MAX (unsigned)
1848 InstructionFoldingCase<bool>(
1849 Header() + "%main = OpFunction %void None %void_func\n" +
1850 "%main_lab = OpLabel\n" +
1851 "%n = OpVariable %_ptr_uint Function\n" +
1852 "%load = OpLoad %uint %n\n" +
1853 "%2 = OpUGreaterThan %bool %load %uint_max\n" +
1854 "OpReturn\n" +
1855 "OpFunctionEnd",
1856 2, false),
1857 // Test case 10: fold n > INT_MAX (signed)
1858 InstructionFoldingCase<bool>(
1859 Header() + "%main = OpFunction %void None %void_func\n" +
1860 "%main_lab = OpLabel\n" +
1861 "%n = OpVariable %_ptr_int Function\n" +
1862 "%load = OpLoad %int %n\n" +
1863 "%2 = OpSGreaterThan %bool %load %int_max\n" +
1864 "OpReturn\n" +
1865 "OpFunctionEnd",
1866 2, false),
1867 // Test case 11: fold INT_MIN > n (signed)
1868 InstructionFoldingCase<bool>(
1869 Header() + "%main = OpFunction %void None %void_func\n" +
1870 "%main_lab = OpLabel\n" +
1871 "%n = OpVariable %_ptr_uint Function\n" +
1872 "%load = OpLoad %uint %n\n" +
1873 "%2 = OpSGreaterThan %bool %int_min %load\n" +
1874 "OpReturn\n" +
1875 "OpFunctionEnd",
1876 2, false),
1877 // Test case 12: fold 0 <= n (unsigned)
1878 InstructionFoldingCase<bool>(
1879 Header() + "%main = OpFunction %void None %void_func\n" +
1880 "%main_lab = OpLabel\n" +
1881 "%n = OpVariable %_ptr_uint Function\n" +
1882 "%load = OpLoad %uint %n\n" +
1883 "%2 = OpULessThanEqual %bool %uint_0 %load\n" +
1884 "OpReturn\n" +
1885 "OpFunctionEnd",
1886 2, true),
1887 // Test case 13: fold n <= UINT_MAX (unsigned)
1888 InstructionFoldingCase<bool>(
1889 Header() + "%main = OpFunction %void None %void_func\n" +
1890 "%main_lab = OpLabel\n" +
1891 "%n = OpVariable %_ptr_uint Function\n" +
1892 "%load = OpLoad %uint %n\n" +
1893 "%2 = OpULessThanEqual %bool %load %uint_max\n" +
1894 "OpReturn\n" +
1895 "OpFunctionEnd",
1896 2, true),
1897 // Test case 14: fold INT_MIN <= n (signed)
1898 InstructionFoldingCase<bool>(
1899 Header() + "%main = OpFunction %void None %void_func\n" +
1900 "%main_lab = OpLabel\n" +
1901 "%n = OpVariable %_ptr_int Function\n" +
1902 "%load = OpLoad %int %n\n" +
1903 "%2 = OpSLessThanEqual %bool %int_min %load\n" +
1904 "OpReturn\n" +
1905 "OpFunctionEnd",
1906 2, true),
1907 // Test case 15: fold n <= INT_MAX (signed)
1908 InstructionFoldingCase<bool>(
1909 Header() + "%main = OpFunction %void None %void_func\n" +
1910 "%main_lab = OpLabel\n" +
1911 "%n = OpVariable %_ptr_int Function\n" +
1912 "%load = OpLoad %int %n\n" +
1913 "%2 = OpSLessThanEqual %bool %load %int_max\n" +
1914 "OpReturn\n" +
1915 "OpFunctionEnd",
1916 2, true),
1917 // Test case 16: fold n >= 0 (unsigned)
1918 InstructionFoldingCase<bool>(
1919 Header() + "%main = OpFunction %void None %void_func\n" +
1920 "%main_lab = OpLabel\n" +
1921 "%n = OpVariable %_ptr_uint Function\n" +
1922 "%load = OpLoad %uint %n\n" +
1923 "%2 = OpUGreaterThanEqual %bool %load %uint_0\n" +
1924 "OpReturn\n" +
1925 "OpFunctionEnd",
1926 2, true),
1927 // Test case 17: fold UINT_MAX >= n (unsigned)
1928 InstructionFoldingCase<bool>(
1929 Header() + "%main = OpFunction %void None %void_func\n" +
1930 "%main_lab = OpLabel\n" +
1931 "%n = OpVariable %_ptr_uint Function\n" +
1932 "%load = OpLoad %uint %n\n" +
1933 "%2 = OpUGreaterThanEqual %bool %uint_max %load\n" +
1934 "OpReturn\n" +
1935 "OpFunctionEnd",
1936 2, true),
1937 // Test case 18: fold n >= INT_MIN (signed)
1938 InstructionFoldingCase<bool>(
1939 Header() + "%main = OpFunction %void None %void_func\n" +
1940 "%main_lab = OpLabel\n" +
1941 "%n = OpVariable %_ptr_int Function\n" +
1942 "%load = OpLoad %int %n\n" +
1943 "%2 = OpSGreaterThanEqual %bool %load %int_min\n" +
1944 "OpReturn\n" +
1945 "OpFunctionEnd",
1946 2, true),
1947 // Test case 19: fold INT_MAX >= n (signed)
1948 InstructionFoldingCase<bool>(
1949 Header() + "%main = OpFunction %void None %void_func\n" +
1950 "%main_lab = OpLabel\n" +
1951 "%n = OpVariable %_ptr_int Function\n" +
1952 "%load = OpLoad %int %n\n" +
1953 "%2 = OpSGreaterThanEqual %bool %int_max %load\n" +
1954 "OpReturn\n" +
1955 "OpFunctionEnd",
1956 2, true)
1957 ));
1958
1959 INSTANTIATE_TEST_SUITE_P(FClampAndCmpLHS, BooleanInstructionFoldingTest,
1960 ::testing::Values(
1961 // Test case 0: fold 0.0 > clamp(n, 0.0, 1.0)
1962 InstructionFoldingCase<bool>(
1963 Header() + "%main = OpFunction %void None %void_func\n" +
1964 "%main_lab = OpLabel\n" +
1965 "%n = OpVariable %_ptr_float Function\n" +
1966 "%ld = OpLoad %float %n\n" +
1967 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1968 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
1969 "OpReturn\n" +
1970 "OpFunctionEnd",
1971 2, false),
1972 // Test case 1: fold 0.0 > clamp(n, -1.0, -1.0)
1973 InstructionFoldingCase<bool>(
1974 Header() + "%main = OpFunction %void None %void_func\n" +
1975 "%main_lab = OpLabel\n" +
1976 "%n = OpVariable %_ptr_float Function\n" +
1977 "%ld = OpLoad %float %n\n" +
1978 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
1979 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
1980 "OpReturn\n" +
1981 "OpFunctionEnd",
1982 2, true),
1983 // Test case 2: fold 0.0 >= clamp(n, 1, 2)
1984 InstructionFoldingCase<bool>(
1985 Header() + "%main = OpFunction %void None %void_func\n" +
1986 "%main_lab = OpLabel\n" +
1987 "%n = OpVariable %_ptr_float Function\n" +
1988 "%ld = OpLoad %float %n\n" +
1989 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1990 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
1991 "OpReturn\n" +
1992 "OpFunctionEnd",
1993 2, false),
1994 // Test case 3: fold 0.0 >= clamp(n, -1.0, 0.0)
1995 InstructionFoldingCase<bool>(
1996 Header() + "%main = OpFunction %void None %void_func\n" +
1997 "%main_lab = OpLabel\n" +
1998 "%n = OpVariable %_ptr_float Function\n" +
1999 "%ld = OpLoad %float %n\n" +
2000 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2001 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
2002 "OpReturn\n" +
2003 "OpFunctionEnd",
2004 2, true),
2005 // Test case 4: fold 0.0 <= clamp(n, 0.0, 1.0)
2006 InstructionFoldingCase<bool>(
2007 Header() + "%main = OpFunction %void None %void_func\n" +
2008 "%main_lab = OpLabel\n" +
2009 "%n = OpVariable %_ptr_float Function\n" +
2010 "%ld = OpLoad %float %n\n" +
2011 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2012 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
2013 "OpReturn\n" +
2014 "OpFunctionEnd",
2015 2, true),
2016 // Test case 5: fold 0.0 <= clamp(n, -1.0, -1.0)
2017 InstructionFoldingCase<bool>(
2018 Header() + "%main = OpFunction %void None %void_func\n" +
2019 "%main_lab = OpLabel\n" +
2020 "%n = OpVariable %_ptr_float Function\n" +
2021 "%ld = OpLoad %float %n\n" +
2022 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
2023 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
2024 "OpReturn\n" +
2025 "OpFunctionEnd",
2026 2, false),
2027 // Test case 6: fold 0.0 < clamp(n, 1, 2)
2028 InstructionFoldingCase<bool>(
2029 Header() + "%main = OpFunction %void None %void_func\n" +
2030 "%main_lab = OpLabel\n" +
2031 "%n = OpVariable %_ptr_float Function\n" +
2032 "%ld = OpLoad %float %n\n" +
2033 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2034 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
2035 "OpReturn\n" +
2036 "OpFunctionEnd",
2037 2, true),
2038 // Test case 7: fold 0.0 < clamp(n, -1.0, 0.0)
2039 InstructionFoldingCase<bool>(
2040 Header() + "%main = OpFunction %void None %void_func\n" +
2041 "%main_lab = OpLabel\n" +
2042 "%n = OpVariable %_ptr_float Function\n" +
2043 "%ld = OpLoad %float %n\n" +
2044 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2045 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
2046 "OpReturn\n" +
2047 "OpFunctionEnd",
2048 2, false),
2049 // Test case 8: fold 0.0 > clamp(n, 0.0, 1.0)
2050 InstructionFoldingCase<bool>(
2051 Header() + "%main = OpFunction %void None %void_func\n" +
2052 "%main_lab = OpLabel\n" +
2053 "%n = OpVariable %_ptr_float Function\n" +
2054 "%ld = OpLoad %float %n\n" +
2055 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2056 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
2057 "OpReturn\n" +
2058 "OpFunctionEnd",
2059 2, false),
2060 // Test case 9: fold 0.0 > clamp(n, -1.0, -1.0)
2061 InstructionFoldingCase<bool>(
2062 Header() + "%main = OpFunction %void None %void_func\n" +
2063 "%main_lab = OpLabel\n" +
2064 "%n = OpVariable %_ptr_float Function\n" +
2065 "%ld = OpLoad %float %n\n" +
2066 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
2067 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
2068 "OpReturn\n" +
2069 "OpFunctionEnd",
2070 2, true),
2071 // Test case 10: fold 0.0 >= clamp(n, 1, 2)
2072 InstructionFoldingCase<bool>(
2073 Header() + "%main = OpFunction %void None %void_func\n" +
2074 "%main_lab = OpLabel\n" +
2075 "%n = OpVariable %_ptr_float Function\n" +
2076 "%ld = OpLoad %float %n\n" +
2077 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2078 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
2079 "OpReturn\n" +
2080 "OpFunctionEnd",
2081 2, false),
2082 // Test case 11: fold 0.0 >= clamp(n, -1.0, 0.0)
2083 InstructionFoldingCase<bool>(
2084 Header() + "%main = OpFunction %void None %void_func\n" +
2085 "%main_lab = OpLabel\n" +
2086 "%n = OpVariable %_ptr_float Function\n" +
2087 "%ld = OpLoad %float %n\n" +
2088 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2089 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
2090 "OpReturn\n" +
2091 "OpFunctionEnd",
2092 2, true),
2093 // Test case 12: fold 0.0 <= clamp(n, 0.0, 1.0)
2094 InstructionFoldingCase<bool>(
2095 Header() + "%main = OpFunction %void None %void_func\n" +
2096 "%main_lab = OpLabel\n" +
2097 "%n = OpVariable %_ptr_float Function\n" +
2098 "%ld = OpLoad %float %n\n" +
2099 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2100 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
2101 "OpReturn\n" +
2102 "OpFunctionEnd",
2103 2, true),
2104 // Test case 13: fold 0.0 <= clamp(n, -1.0, -1.0)
2105 InstructionFoldingCase<bool>(
2106 Header() + "%main = OpFunction %void None %void_func\n" +
2107 "%main_lab = OpLabel\n" +
2108 "%n = OpVariable %_ptr_float Function\n" +
2109 "%ld = OpLoad %float %n\n" +
2110 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
2111 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
2112 "OpReturn\n" +
2113 "OpFunctionEnd",
2114 2, false),
2115 // Test case 14: fold 0.0 < clamp(n, 1, 2)
2116 InstructionFoldingCase<bool>(
2117 Header() + "%main = OpFunction %void None %void_func\n" +
2118 "%main_lab = OpLabel\n" +
2119 "%n = OpVariable %_ptr_float Function\n" +
2120 "%ld = OpLoad %float %n\n" +
2121 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2122 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
2123 "OpReturn\n" +
2124 "OpFunctionEnd",
2125 2, true),
2126 // Test case 15: fold 0.0 < clamp(n, -1.0, 0.0)
2127 InstructionFoldingCase<bool>(
2128 Header() + "%main = OpFunction %void None %void_func\n" +
2129 "%main_lab = OpLabel\n" +
2130 "%n = OpVariable %_ptr_float Function\n" +
2131 "%ld = OpLoad %float %n\n" +
2132 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2133 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
2134 "OpReturn\n" +
2135 "OpFunctionEnd",
2136 2, false)
2137 ));
2138
2139 INSTANTIATE_TEST_SUITE_P(FClampAndCmpRHS, BooleanInstructionFoldingTest,
2140 ::testing::Values(
2141 // Test case 0: fold clamp(n, 0.0, 1.0) > 1.0
2142 InstructionFoldingCase<bool>(
2143 Header() + "%main = OpFunction %void None %void_func\n" +
2144 "%main_lab = OpLabel\n" +
2145 "%n = OpVariable %_ptr_float Function\n" +
2146 "%ld = OpLoad %float %n\n" +
2147 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2148 "%2 = OpFOrdGreaterThan %bool %clamp %float_1\n" +
2149 "OpReturn\n" +
2150 "OpFunctionEnd",
2151 2, false),
2152 // Test case 1: fold clamp(n, 1.0, 1.0) > 0.0
2153 InstructionFoldingCase<bool>(
2154 Header() + "%main = OpFunction %void None %void_func\n" +
2155 "%main_lab = OpLabel\n" +
2156 "%n = OpVariable %_ptr_float Function\n" +
2157 "%ld = OpLoad %float %n\n" +
2158 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
2159 "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
2160 "OpReturn\n" +
2161 "OpFunctionEnd",
2162 2, true),
2163 // Test case 2: fold clamp(n, 1, 2) >= 0.0
2164 InstructionFoldingCase<bool>(
2165 Header() + "%main = OpFunction %void None %void_func\n" +
2166 "%main_lab = OpLabel\n" +
2167 "%n = OpVariable %_ptr_float Function\n" +
2168 "%ld = OpLoad %float %n\n" +
2169 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2170 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
2171 "OpReturn\n" +
2172 "OpFunctionEnd",
2173 2, true),
2174 // Test case 3: fold clamp(n, 1.0, 2.0) >= 3.0
2175 InstructionFoldingCase<bool>(
2176 Header() + "%main = OpFunction %void None %void_func\n" +
2177 "%main_lab = OpLabel\n" +
2178 "%n = OpVariable %_ptr_float Function\n" +
2179 "%ld = OpLoad %float %n\n" +
2180 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2181 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_3\n" +
2182 "OpReturn\n" +
2183 "OpFunctionEnd",
2184 2, false),
2185 // Test case 4: fold clamp(n, 0.0, 1.0) <= 1.0
2186 InstructionFoldingCase<bool>(
2187 Header() + "%main = OpFunction %void None %void_func\n" +
2188 "%main_lab = OpLabel\n" +
2189 "%n = OpVariable %_ptr_float Function\n" +
2190 "%ld = OpLoad %float %n\n" +
2191 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2192 "%2 = OpFOrdLessThanEqual %bool %clamp %float_1\n" +
2193 "OpReturn\n" +
2194 "OpFunctionEnd",
2195 2, true),
2196 // Test case 5: fold clamp(n, 1.0, 2.0) <= 0.0
2197 InstructionFoldingCase<bool>(
2198 Header() + "%main = OpFunction %void None %void_func\n" +
2199 "%main_lab = OpLabel\n" +
2200 "%n = OpVariable %_ptr_float Function\n" +
2201 "%ld = OpLoad %float %n\n" +
2202 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2203 "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
2204 "OpReturn\n" +
2205 "OpFunctionEnd",
2206 2, false),
2207 // Test case 6: fold clamp(n, 1, 2) < 3
2208 InstructionFoldingCase<bool>(
2209 Header() + "%main = OpFunction %void None %void_func\n" +
2210 "%main_lab = OpLabel\n" +
2211 "%n = OpVariable %_ptr_float Function\n" +
2212 "%ld = OpLoad %float %n\n" +
2213 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2214 "%2 = OpFOrdLessThan %bool %clamp %float_3\n" +
2215 "OpReturn\n" +
2216 "OpFunctionEnd",
2217 2, true),
2218 // Test case 7: fold clamp(n, -1.0, 0.0) < -1.0
2219 InstructionFoldingCase<bool>(
2220 Header() + "%main = OpFunction %void None %void_func\n" +
2221 "%main_lab = OpLabel\n" +
2222 "%n = OpVariable %_ptr_float Function\n" +
2223 "%ld = OpLoad %float %n\n" +
2224 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2225 "%2 = OpFOrdLessThan %bool %clamp %float_n1\n" +
2226 "OpReturn\n" +
2227 "OpFunctionEnd",
2228 2, false),
2229 // Test case 8: fold clamp(n, 0.0, 1.0) > 1.0
2230 InstructionFoldingCase<bool>(
2231 Header() + "%main = OpFunction %void None %void_func\n" +
2232 "%main_lab = OpLabel\n" +
2233 "%n = OpVariable %_ptr_float Function\n" +
2234 "%ld = OpLoad %float %n\n" +
2235 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2236 "%2 = OpFUnordGreaterThan %bool %clamp %float_1\n" +
2237 "OpReturn\n" +
2238 "OpFunctionEnd",
2239 2, false),
2240 // Test case 9: fold clamp(n, 1.0, 2.0) > 0.0
2241 InstructionFoldingCase<bool>(
2242 Header() + "%main = OpFunction %void None %void_func\n" +
2243 "%main_lab = OpLabel\n" +
2244 "%n = OpVariable %_ptr_float Function\n" +
2245 "%ld = OpLoad %float %n\n" +
2246 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2247 "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
2248 "OpReturn\n" +
2249 "OpFunctionEnd",
2250 2, true),
2251 // Test case 10: fold clamp(n, 1, 2) >= 3.0
2252 InstructionFoldingCase<bool>(
2253 Header() + "%main = OpFunction %void None %void_func\n" +
2254 "%main_lab = OpLabel\n" +
2255 "%n = OpVariable %_ptr_float Function\n" +
2256 "%ld = OpLoad %float %n\n" +
2257 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2258 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_3\n" +
2259 "OpReturn\n" +
2260 "OpFunctionEnd",
2261 2, false),
2262 // Test case 11: fold clamp(n, -1.0, 0.0) >= -1.0
2263 InstructionFoldingCase<bool>(
2264 Header() + "%main = OpFunction %void None %void_func\n" +
2265 "%main_lab = OpLabel\n" +
2266 "%n = OpVariable %_ptr_float Function\n" +
2267 "%ld = OpLoad %float %n\n" +
2268 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2269 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_n1\n" +
2270 "OpReturn\n" +
2271 "OpFunctionEnd",
2272 2, true),
2273 // Test case 12: fold clamp(n, 0.0, 1.0) <= 1.0
2274 InstructionFoldingCase<bool>(
2275 Header() + "%main = OpFunction %void None %void_func\n" +
2276 "%main_lab = OpLabel\n" +
2277 "%n = OpVariable %_ptr_float Function\n" +
2278 "%ld = OpLoad %float %n\n" +
2279 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2280 "%2 = OpFUnordLessThanEqual %bool %clamp %float_1\n" +
2281 "OpReturn\n" +
2282 "OpFunctionEnd",
2283 2, true),
2284 // Test case 13: fold clamp(n, 1.0, 1.0) <= 0.0
2285 InstructionFoldingCase<bool>(
2286 Header() + "%main = OpFunction %void None %void_func\n" +
2287 "%main_lab = OpLabel\n" +
2288 "%n = OpVariable %_ptr_float Function\n" +
2289 "%ld = OpLoad %float %n\n" +
2290 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
2291 "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
2292 "OpReturn\n" +
2293 "OpFunctionEnd",
2294 2, false),
2295 // Test case 14: fold clamp(n, 1, 2) < 3
2296 InstructionFoldingCase<bool>(
2297 Header() + "%main = OpFunction %void None %void_func\n" +
2298 "%main_lab = OpLabel\n" +
2299 "%n = OpVariable %_ptr_float Function\n" +
2300 "%ld = OpLoad %float %n\n" +
2301 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2302 "%2 = OpFUnordLessThan %bool %clamp %float_3\n" +
2303 "OpReturn\n" +
2304 "OpFunctionEnd",
2305 2, true),
2306 // Test case 15: fold clamp(n, -1.0, 0.0) < -1.0
2307 InstructionFoldingCase<bool>(
2308 Header() + "%main = OpFunction %void None %void_func\n" +
2309 "%main_lab = OpLabel\n" +
2310 "%n = OpVariable %_ptr_float Function\n" +
2311 "%ld = OpLoad %float %n\n" +
2312 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2313 "%2 = OpFUnordLessThan %bool %clamp %float_n1\n" +
2314 "OpReturn\n" +
2315 "OpFunctionEnd",
2316 2, false),
2317 // Test case 16: fold clamp(n, -1.0, 0.0) < -1.0 (one test for double)
2318 InstructionFoldingCase<bool>(
2319 Header() + "%main = OpFunction %void None %void_func\n" +
2320 "%main_lab = OpLabel\n" +
2321 "%n = OpVariable %_ptr_double Function\n" +
2322 "%ld = OpLoad %double %n\n" +
2323 "%clamp = OpExtInst %double %1 FClamp %ld %double_n1 %double_0\n" +
2324 "%2 = OpFUnordLessThan %bool %clamp %double_n1\n" +
2325 "OpReturn\n" +
2326 "OpFunctionEnd",
2327 2, false)
2328 ));
2329 // clang-format on
2330
2331 using FloatInstructionFoldingTest =
2332 ::testing::TestWithParam<InstructionFoldingCase<float>>;
2333
TEST_P(FloatInstructionFoldingTest,Case)2334 TEST_P(FloatInstructionFoldingTest, Case) {
2335 const auto& tc = GetParam();
2336
2337 std::unique_ptr<IRContext> context;
2338 Instruction* inst;
2339 std::tie(context, inst) =
2340 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
2341
2342 CheckForExpectedScalarConstant(inst, tc.expected_result,
2343 [](const analysis::Constant* c) {
2344 return c->AsFloatConstant()->GetFloatValue();
2345 });
2346 }
2347
2348 // Not testing NaNs because there are no expectations concerning NaNs according
2349 // to the "Precision and Operation of SPIR-V Instructions" section of the Vulkan
2350 // specification.
2351
2352 // clang-format off
2353 INSTANTIATE_TEST_SUITE_P(FloatConstantFoldingTest, FloatInstructionFoldingTest,
2354 ::testing::Values(
2355 // Test case 0: Fold 2.0 - 1.0
2356 InstructionFoldingCase<float>(
2357 Header() + "%main = OpFunction %void None %void_func\n" +
2358 "%main_lab = OpLabel\n" +
2359 "%2 = OpFSub %float %float_2 %float_1\n" +
2360 "OpReturn\n" +
2361 "OpFunctionEnd",
2362 2, 1.0),
2363 // Test case 1: Fold 2.0 + 1.0
2364 InstructionFoldingCase<float>(
2365 Header() + "%main = OpFunction %void None %void_func\n" +
2366 "%main_lab = OpLabel\n" +
2367 "%2 = OpFAdd %float %float_2 %float_1\n" +
2368 "OpReturn\n" +
2369 "OpFunctionEnd",
2370 2, 3.0),
2371 // Test case 2: Fold 3.0 * 2.0
2372 InstructionFoldingCase<float>(
2373 Header() + "%main = OpFunction %void None %void_func\n" +
2374 "%main_lab = OpLabel\n" +
2375 "%2 = OpFMul %float %float_3 %float_2\n" +
2376 "OpReturn\n" +
2377 "OpFunctionEnd",
2378 2, 6.0),
2379 // Test case 3: Fold 1.0 / 2.0
2380 InstructionFoldingCase<float>(
2381 Header() + "%main = OpFunction %void None %void_func\n" +
2382 "%main_lab = OpLabel\n" +
2383 "%2 = OpFDiv %float %float_1 %float_2\n" +
2384 "OpReturn\n" +
2385 "OpFunctionEnd",
2386 2, 0.5),
2387 // Test case 4: Fold 1.0 / 0.0
2388 InstructionFoldingCase<float>(
2389 Header() + "%main = OpFunction %void None %void_func\n" +
2390 "%main_lab = OpLabel\n" +
2391 "%2 = OpFDiv %float %float_1 %float_0\n" +
2392 "OpReturn\n" +
2393 "OpFunctionEnd",
2394 2, std::numeric_limits<float>::infinity()),
2395 // Test case 5: Fold -1.0 / 0.0
2396 InstructionFoldingCase<float>(
2397 Header() + "%main = OpFunction %void None %void_func\n" +
2398 "%main_lab = OpLabel\n" +
2399 "%2 = OpFDiv %float %float_n1 %float_0\n" +
2400 "OpReturn\n" +
2401 "OpFunctionEnd",
2402 2, -std::numeric_limits<float>::infinity()),
2403 // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
2404 InstructionFoldingCase<float>(
2405 Header() + "%main = OpFunction %void None %void_func\n" +
2406 "%main_lab = OpLabel\n" +
2407 "%2 = OpDot %float %v2float_2_3 %v2float_2_0p5\n" +
2408 "OpReturn\n" +
2409 "OpFunctionEnd",
2410 2, 5.5f),
2411 // Test case 7: Fold (0.0, 0.0) dot v
2412 InstructionFoldingCase<float>(
2413 Header() + "%main = OpFunction %void None %void_func\n" +
2414 "%main_lab = OpLabel\n" +
2415 "%v = OpVariable %_ptr_v2float Function\n" +
2416 "%2 = OpLoad %v2float %v\n" +
2417 "%3 = OpDot %float %v2float_0_0 %2\n" +
2418 "OpReturn\n" +
2419 "OpFunctionEnd",
2420 3, 0.0f),
2421 // Test case 8: Fold v dot (0.0, 0.0)
2422 InstructionFoldingCase<float>(
2423 Header() + "%main = OpFunction %void None %void_func\n" +
2424 "%main_lab = OpLabel\n" +
2425 "%v = OpVariable %_ptr_v2float Function\n" +
2426 "%2 = OpLoad %v2float %v\n" +
2427 "%3 = OpDot %float %2 %v2float_0_0\n" +
2428 "OpReturn\n" +
2429 "OpFunctionEnd",
2430 3, 0.0f),
2431 // Test case 9: Fold Null dot v
2432 InstructionFoldingCase<float>(
2433 Header() + "%main = OpFunction %void None %void_func\n" +
2434 "%main_lab = OpLabel\n" +
2435 "%v = OpVariable %_ptr_v2float Function\n" +
2436 "%2 = OpLoad %v2float %v\n" +
2437 "%3 = OpDot %float %v2float_null %2\n" +
2438 "OpReturn\n" +
2439 "OpFunctionEnd",
2440 3, 0.0f),
2441 // Test case 10: Fold v dot Null
2442 InstructionFoldingCase<float>(
2443 Header() + "%main = OpFunction %void None %void_func\n" +
2444 "%main_lab = OpLabel\n" +
2445 "%v = OpVariable %_ptr_v2float Function\n" +
2446 "%2 = OpLoad %v2float %v\n" +
2447 "%3 = OpDot %float %2 %v2float_null\n" +
2448 "OpReturn\n" +
2449 "OpFunctionEnd",
2450 3, 0.0f),
2451 // Test case 11: Fold -2.0
2452 InstructionFoldingCase<float>(
2453 Header() + "%main = OpFunction %void None %void_func\n" +
2454 "%main_lab = OpLabel\n" +
2455 "%2 = OpFNegate %float %float_2\n" +
2456 "OpReturn\n" +
2457 "OpFunctionEnd",
2458 2, -2),
2459 // Test case 12: QuantizeToF16 1.0
2460 InstructionFoldingCase<float>(
2461 Header() + "%main = OpFunction %void None %void_func\n" +
2462 "%main_lab = OpLabel\n" +
2463 "%2 = OpQuantizeToF16 %float %float_1\n" +
2464 "OpReturn\n" +
2465 "OpFunctionEnd",
2466 2, 1.0),
2467 // Test case 13: QuantizeToF16 positive non exact
2468 InstructionFoldingCase<float>(
2469 Header() + "%main = OpFunction %void None %void_func\n" +
2470 "%main_lab = OpLabel\n" +
2471 "%2 = OpQuantizeToF16 %float %float_2049\n" +
2472 "OpReturn\n" +
2473 "OpFunctionEnd",
2474 2, 2048),
2475 // Test case 14: QuantizeToF16 negative non exact
2476 InstructionFoldingCase<float>(
2477 Header() + "%main = OpFunction %void None %void_func\n" +
2478 "%main_lab = OpLabel\n" +
2479 "%2 = OpQuantizeToF16 %float %float_n2049\n" +
2480 "OpReturn\n" +
2481 "OpFunctionEnd",
2482 2, -2048),
2483 // Test case 15: QuantizeToF16 large positive
2484 InstructionFoldingCase<float>(
2485 Header() + "%main = OpFunction %void None %void_func\n" +
2486 "%main_lab = OpLabel\n" +
2487 "%2 = OpQuantizeToF16 %float %float_1e16\n" +
2488 "OpReturn\n" +
2489 "OpFunctionEnd",
2490 2, std::numeric_limits<float>::infinity()),
2491 // Test case 16: QuantizeToF16 large negative
2492 InstructionFoldingCase<float>(
2493 Header() + "%main = OpFunction %void None %void_func\n" +
2494 "%main_lab = OpLabel\n" +
2495 "%2 = OpQuantizeToF16 %float %float_n1e16\n" +
2496 "OpReturn\n" +
2497 "OpFunctionEnd",
2498 2, -std::numeric_limits<float>::infinity()),
2499 // Test case 17: QuantizeToF16 small positive
2500 InstructionFoldingCase<float>(
2501 Header() + "%main = OpFunction %void None %void_func\n" +
2502 "%main_lab = OpLabel\n" +
2503 "%2 = OpQuantizeToF16 %float %float_1en16\n" +
2504 "OpReturn\n" +
2505 "OpFunctionEnd",
2506 2, 0.0),
2507 // Test case 18: QuantizeToF16 small negative
2508 InstructionFoldingCase<float>(
2509 Header() + "%main = OpFunction %void None %void_func\n" +
2510 "%main_lab = OpLabel\n" +
2511 "%2 = OpQuantizeToF16 %float %float_n1en16\n" +
2512 "OpReturn\n" +
2513 "OpFunctionEnd",
2514 2, 0.0),
2515 // Test case 19: QuantizeToF16 nan
2516 InstructionFoldingCase<float>(
2517 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2518 "%main_lab = OpLabel\n" +
2519 "%2 = OpQuantizeToF16 %float %float_nan\n" +
2520 "OpReturn\n" +
2521 "OpFunctionEnd",
2522 2, std::numeric_limits<float>::quiet_NaN()),
2523 // Test case 20: FMix 1.0 4.0 0.2
2524 InstructionFoldingCase<float>(
2525 Header() + "%main = OpFunction %void None %void_func\n" +
2526 "%main_lab = OpLabel\n" +
2527 "%2 = OpExtInst %float %1 FMix %float_1 %float_4 %float_0p2\n" +
2528 "OpReturn\n" +
2529 "OpFunctionEnd",
2530 2, 1.6f),
2531 // Test case 21: FMin 1.0 4.0
2532 InstructionFoldingCase<float>(
2533 Header() + "%main = OpFunction %void None %void_func\n" +
2534 "%main_lab = OpLabel\n" +
2535 "%2 = OpExtInst %float %1 FMin %float_1 %float_4\n" +
2536 "OpReturn\n" +
2537 "OpFunctionEnd",
2538 2, 1.0f),
2539 // Test case 22: FMin 4.0 0.2
2540 InstructionFoldingCase<float>(
2541 Header() + "%main = OpFunction %void None %void_func\n" +
2542 "%main_lab = OpLabel\n" +
2543 "%2 = OpExtInst %float %1 FMin %float_4 %float_0p2\n" +
2544 "OpReturn\n" +
2545 "OpFunctionEnd",
2546 2, 0.2f),
2547 // Test case 23: FMax 1.0 4.0
2548 InstructionFoldingCase<float>(
2549 Header() + "%main = OpFunction %void None %void_func\n" +
2550 "%main_lab = OpLabel\n" +
2551 "%2 = OpExtInst %float %1 FMax %float_1 %float_4\n" +
2552 "OpReturn\n" +
2553 "OpFunctionEnd",
2554 2, 4.0f),
2555 // Test case 24: FMax 1.0 0.2
2556 InstructionFoldingCase<float>(
2557 Header() + "%main = OpFunction %void None %void_func\n" +
2558 "%main_lab = OpLabel\n" +
2559 "%2 = OpExtInst %float %1 FMax %float_1 %float_0p2\n" +
2560 "OpReturn\n" +
2561 "OpFunctionEnd",
2562 2, 1.0f),
2563 // Test case 25: FClamp 1.0 0.2 4.0
2564 InstructionFoldingCase<float>(
2565 Header() + "%main = OpFunction %void None %void_func\n" +
2566 "%main_lab = OpLabel\n" +
2567 "%2 = OpExtInst %float %1 FClamp %float_1 %float_0p2 %float_4\n" +
2568 "OpReturn\n" +
2569 "OpFunctionEnd",
2570 2, 1.0f),
2571 // Test case 26: FClamp 0.2 2.0 4.0
2572 InstructionFoldingCase<float>(
2573 Header() + "%main = OpFunction %void None %void_func\n" +
2574 "%main_lab = OpLabel\n" +
2575 "%2 = OpExtInst %float %1 FClamp %float_0p2 %float_2 %float_4\n" +
2576 "OpReturn\n" +
2577 "OpFunctionEnd",
2578 2, 2.0f),
2579 // Test case 27: FClamp 2049.0 2.0 4.0
2580 InstructionFoldingCase<float>(
2581 Header() + "%main = OpFunction %void None %void_func\n" +
2582 "%main_lab = OpLabel\n" +
2583 "%2 = OpExtInst %float %1 FClamp %float_2049 %float_2 %float_4\n" +
2584 "OpReturn\n" +
2585 "OpFunctionEnd",
2586 2, 4.0f),
2587 // Test case 28: FClamp 1.0 2.0 x
2588 InstructionFoldingCase<float>(
2589 Header() + "%main = OpFunction %void None %void_func\n" +
2590 "%main_lab = OpLabel\n" +
2591 "%undef = OpUndef %float\n" +
2592 "%2 = OpExtInst %float %1 FClamp %float_1 %float_2 %undef\n" +
2593 "OpReturn\n" +
2594 "OpFunctionEnd",
2595 2, 2.0),
2596 // Test case 29: FClamp 1.0 x 0.5
2597 InstructionFoldingCase<float>(
2598 Header() + "%main = OpFunction %void None %void_func\n" +
2599 "%main_lab = OpLabel\n" +
2600 "%undef = OpUndef %float\n" +
2601 "%2 = OpExtInst %float %1 FClamp %float_1 %undef %float_0p5\n" +
2602 "OpReturn\n" +
2603 "OpFunctionEnd",
2604 2, 0.5),
2605 // Test case 30: Sin 0.0
2606 InstructionFoldingCase<float>(
2607 Header() + "%main = OpFunction %void None %void_func\n" +
2608 "%main_lab = OpLabel\n" +
2609 "%2 = OpExtInst %float %1 Sin %float_0\n" +
2610 "OpReturn\n" +
2611 "OpFunctionEnd",
2612 2, 0.0),
2613 // Test case 31: Cos 0.0
2614 InstructionFoldingCase<float>(
2615 Header() + "%main = OpFunction %void None %void_func\n" +
2616 "%main_lab = OpLabel\n" +
2617 "%2 = OpExtInst %float %1 Cos %float_0\n" +
2618 "OpReturn\n" +
2619 "OpFunctionEnd",
2620 2, 1.0),
2621 // Test case 32: Tan 0.0
2622 InstructionFoldingCase<float>(
2623 Header() + "%main = OpFunction %void None %void_func\n" +
2624 "%main_lab = OpLabel\n" +
2625 "%2 = OpExtInst %float %1 Tan %float_0\n" +
2626 "OpReturn\n" +
2627 "OpFunctionEnd",
2628 2, 0.0),
2629 // Test case 33: Asin 0.0
2630 InstructionFoldingCase<float>(
2631 Header() + "%main = OpFunction %void None %void_func\n" +
2632 "%main_lab = OpLabel\n" +
2633 "%2 = OpExtInst %float %1 Asin %float_0\n" +
2634 "OpReturn\n" +
2635 "OpFunctionEnd",
2636 2, 0.0),
2637 // Test case 34: Acos 1.0
2638 InstructionFoldingCase<float>(
2639 Header() + "%main = OpFunction %void None %void_func\n" +
2640 "%main_lab = OpLabel\n" +
2641 "%2 = OpExtInst %float %1 Acos %float_1\n" +
2642 "OpReturn\n" +
2643 "OpFunctionEnd",
2644 2, 0.0),
2645 // Test case 35: Atan 0.0
2646 InstructionFoldingCase<float>(
2647 Header() + "%main = OpFunction %void None %void_func\n" +
2648 "%main_lab = OpLabel\n" +
2649 "%2 = OpExtInst %float %1 Atan %float_0\n" +
2650 "OpReturn\n" +
2651 "OpFunctionEnd",
2652 2, 0.0),
2653 // Test case 36: Exp 0.0
2654 InstructionFoldingCase<float>(
2655 Header() + "%main = OpFunction %void None %void_func\n" +
2656 "%main_lab = OpLabel\n" +
2657 "%2 = OpExtInst %float %1 Exp %float_0\n" +
2658 "OpReturn\n" +
2659 "OpFunctionEnd",
2660 2, 1.0),
2661 // Test case 37: Log 1.0
2662 InstructionFoldingCase<float>(
2663 Header() + "%main = OpFunction %void None %void_func\n" +
2664 "%main_lab = OpLabel\n" +
2665 "%2 = OpExtInst %float %1 Log %float_1\n" +
2666 "OpReturn\n" +
2667 "OpFunctionEnd",
2668 2, 0.0),
2669 // Test case 38: Exp2 2.0
2670 InstructionFoldingCase<float>(
2671 Header() + "%main = OpFunction %void None %void_func\n" +
2672 "%main_lab = OpLabel\n" +
2673 "%2 = OpExtInst %float %1 Exp2 %float_2\n" +
2674 "OpReturn\n" +
2675 "OpFunctionEnd",
2676 2, 4.0),
2677 // Test case 39: Log2 4.0
2678 InstructionFoldingCase<float>(
2679 Header() + "%main = OpFunction %void None %void_func\n" +
2680 "%main_lab = OpLabel\n" +
2681 "%2 = OpExtInst %float %1 Log2 %float_4\n" +
2682 "OpReturn\n" +
2683 "OpFunctionEnd",
2684 2, 2.0),
2685 // Test case 40: Sqrt 4.0
2686 InstructionFoldingCase<float>(
2687 Header() + "%main = OpFunction %void None %void_func\n" +
2688 "%main_lab = OpLabel\n" +
2689 "%2 = OpExtInst %float %1 Sqrt %float_4\n" +
2690 "OpReturn\n" +
2691 "OpFunctionEnd",
2692 2, 2.0),
2693 // Test case 41: Atan2 0.0 1.0
2694 InstructionFoldingCase<float>(
2695 Header() + "%main = OpFunction %void None %void_func\n" +
2696 "%main_lab = OpLabel\n" +
2697 "%2 = OpExtInst %float %1 Atan2 %float_0 %float_1\n" +
2698 "OpReturn\n" +
2699 "OpFunctionEnd",
2700 2, 0.0),
2701 // Test case 42: Pow 2.0 3.0
2702 InstructionFoldingCase<float>(
2703 Header() + "%main = OpFunction %void None %void_func\n" +
2704 "%main_lab = OpLabel\n" +
2705 "%2 = OpExtInst %float %1 Pow %float_2 %float_3\n" +
2706 "OpReturn\n" +
2707 "OpFunctionEnd",
2708 2, 8.0),
2709 // Test case 43: Fold 1.0 / -0.0.
2710 InstructionFoldingCase<float>(
2711 Header() + "%main = OpFunction %void None %void_func\n" +
2712 "%main_lab = OpLabel\n" +
2713 "%2 = OpFDiv %float %float_1 %float_n0\n" +
2714 "OpReturn\n" +
2715 "OpFunctionEnd",
2716 2, -std::numeric_limits<float>::infinity()),
2717 // Test case 44: Fold -1.0 / -0.0
2718 InstructionFoldingCase<float>(
2719 Header() + "%main = OpFunction %void None %void_func\n" +
2720 "%main_lab = OpLabel\n" +
2721 "%2 = OpFDiv %float %float_n1 %float_n0\n" +
2722 "OpReturn\n" +
2723 "OpFunctionEnd",
2724 2, std::numeric_limits<float>::infinity()),
2725 // Test case 45: Fold 0.0 / 0.0
2726 InstructionFoldingCase<float>(
2727 Header() + "%main = OpFunction %void None %void_func\n" +
2728 "%main_lab = OpLabel\n" +
2729 "%2 = OpFDiv %float %float_0 %float_0\n" +
2730 "OpReturn\n" +
2731 "OpFunctionEnd",
2732 2, std::numeric_limits<float>::quiet_NaN()),
2733 // Test case 46: Fold 0.0 / -0.0
2734 InstructionFoldingCase<float>(
2735 Header() + "%main = OpFunction %void None %void_func\n" +
2736 "%main_lab = OpLabel\n" +
2737 "%2 = OpFDiv %float %float_0 %float_n0\n" +
2738 "OpReturn\n" +
2739 "OpFunctionEnd",
2740 2, std::numeric_limits<float>::quiet_NaN())
2741 ));
2742 // clang-format on
2743
2744 using DoubleInstructionFoldingTest =
2745 ::testing::TestWithParam<InstructionFoldingCase<double>>;
2746
TEST_P(DoubleInstructionFoldingTest,Case)2747 TEST_P(DoubleInstructionFoldingTest, Case) {
2748 const auto& tc = GetParam();
2749
2750 std::unique_ptr<IRContext> context;
2751 Instruction* inst;
2752 std::tie(context, inst) =
2753 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
2754 CheckForExpectedScalarConstant(
2755 inst, tc.expected_result, [](const analysis::Constant* c) {
2756 return c->AsFloatConstant()->GetDoubleValue();
2757 });
2758 }
2759
2760 // clang-format off
2761 INSTANTIATE_TEST_SUITE_P(DoubleConstantFoldingTest, DoubleInstructionFoldingTest,
2762 ::testing::Values(
2763 // Test case 0: Fold 2.0 - 1.0
2764 InstructionFoldingCase<double>(
2765 Header() + "%main = OpFunction %void None %void_func\n" +
2766 "%main_lab = OpLabel\n" +
2767 "%2 = OpFSub %double %double_2 %double_1\n" +
2768 "OpReturn\n" +
2769 "OpFunctionEnd",
2770 2, 1.0),
2771 // Test case 1: Fold 2.0 + 1.0
2772 InstructionFoldingCase<double>(
2773 Header() + "%main = OpFunction %void None %void_func\n" +
2774 "%main_lab = OpLabel\n" +
2775 "%2 = OpFAdd %double %double_2 %double_1\n" +
2776 "OpReturn\n" +
2777 "OpFunctionEnd",
2778 2, 3.0),
2779 // Test case 2: Fold 3.0 * 2.0
2780 InstructionFoldingCase<double>(
2781 Header() + "%main = OpFunction %void None %void_func\n" +
2782 "%main_lab = OpLabel\n" +
2783 "%2 = OpFMul %double %double_3 %double_2\n" +
2784 "OpReturn\n" +
2785 "OpFunctionEnd",
2786 2, 6.0),
2787 // Test case 3: Fold 1.0 / 2.0
2788 InstructionFoldingCase<double>(
2789 Header() + "%main = OpFunction %void None %void_func\n" +
2790 "%main_lab = OpLabel\n" +
2791 "%2 = OpFDiv %double %double_1 %double_2\n" +
2792 "OpReturn\n" +
2793 "OpFunctionEnd",
2794 2, 0.5),
2795 // Test case 4: Fold 1.0 / 0.0
2796 InstructionFoldingCase<double>(
2797 Header() + "%main = OpFunction %void None %void_func\n" +
2798 "%main_lab = OpLabel\n" +
2799 "%2 = OpFDiv %double %double_1 %double_0\n" +
2800 "OpReturn\n" +
2801 "OpFunctionEnd",
2802 2, std::numeric_limits<double>::infinity()),
2803 // Test case 5: Fold -1.0 / 0.0
2804 InstructionFoldingCase<double>(
2805 Header() + "%main = OpFunction %void None %void_func\n" +
2806 "%main_lab = OpLabel\n" +
2807 "%2 = OpFDiv %double %double_n1 %double_0\n" +
2808 "OpReturn\n" +
2809 "OpFunctionEnd",
2810 2, -std::numeric_limits<double>::infinity()),
2811 // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
2812 InstructionFoldingCase<double>(
2813 Header() + "%main = OpFunction %void None %void_func\n" +
2814 "%main_lab = OpLabel\n" +
2815 "%2 = OpDot %double %v2double_2_3 %v2double_2_0p5\n" +
2816 "OpReturn\n" +
2817 "OpFunctionEnd",
2818 2, 5.5f),
2819 // Test case 7: Fold (0.0, 0.0) dot v
2820 InstructionFoldingCase<double>(
2821 Header() + "%main = OpFunction %void None %void_func\n" +
2822 "%main_lab = OpLabel\n" +
2823 "%v = OpVariable %_ptr_v2double Function\n" +
2824 "%2 = OpLoad %v2double %v\n" +
2825 "%3 = OpDot %double %v2double_0_0 %2\n" +
2826 "OpReturn\n" +
2827 "OpFunctionEnd",
2828 3, 0.0f),
2829 // Test case 8: Fold v dot (0.0, 0.0)
2830 InstructionFoldingCase<double>(
2831 Header() + "%main = OpFunction %void None %void_func\n" +
2832 "%main_lab = OpLabel\n" +
2833 "%v = OpVariable %_ptr_v2double Function\n" +
2834 "%2 = OpLoad %v2double %v\n" +
2835 "%3 = OpDot %double %2 %v2double_0_0\n" +
2836 "OpReturn\n" +
2837 "OpFunctionEnd",
2838 3, 0.0f),
2839 // Test case 9: Fold Null dot v
2840 InstructionFoldingCase<double>(
2841 Header() + "%main = OpFunction %void None %void_func\n" +
2842 "%main_lab = OpLabel\n" +
2843 "%v = OpVariable %_ptr_v2double Function\n" +
2844 "%2 = OpLoad %v2double %v\n" +
2845 "%3 = OpDot %double %v2double_null %2\n" +
2846 "OpReturn\n" +
2847 "OpFunctionEnd",
2848 3, 0.0f),
2849 // Test case 10: Fold v dot Null
2850 InstructionFoldingCase<double>(
2851 Header() + "%main = OpFunction %void None %void_func\n" +
2852 "%main_lab = OpLabel\n" +
2853 "%v = OpVariable %_ptr_v2double Function\n" +
2854 "%2 = OpLoad %v2double %v\n" +
2855 "%3 = OpDot %double %2 %v2double_null\n" +
2856 "OpReturn\n" +
2857 "OpFunctionEnd",
2858 3, 0.0f),
2859 // Test case 11: Fold -2.0
2860 InstructionFoldingCase<double>(
2861 Header() + "%main = OpFunction %void None %void_func\n" +
2862 "%main_lab = OpLabel\n" +
2863 "%2 = OpFNegate %double %double_2\n" +
2864 "OpReturn\n" +
2865 "OpFunctionEnd",
2866 2, -2),
2867 // Test case 12: FMin 1.0 4.0
2868 InstructionFoldingCase<double>(
2869 Header() + "%main = OpFunction %void None %void_func\n" +
2870 "%main_lab = OpLabel\n" +
2871 "%2 = OpExtInst %double %1 FMin %double_1 %double_4\n" +
2872 "OpReturn\n" +
2873 "OpFunctionEnd",
2874 2, 1.0),
2875 // Test case 13: FMin 4.0 0.2
2876 InstructionFoldingCase<double>(
2877 Header() + "%main = OpFunction %void None %void_func\n" +
2878 "%main_lab = OpLabel\n" +
2879 "%2 = OpExtInst %double %1 FMin %double_4 %double_0p2\n" +
2880 "OpReturn\n" +
2881 "OpFunctionEnd",
2882 2, 0.2),
2883 // Test case 14: FMax 1.0 4.0
2884 InstructionFoldingCase<double>(
2885 Header() + "%main = OpFunction %void None %void_func\n" +
2886 "%main_lab = OpLabel\n" +
2887 "%2 = OpExtInst %double %1 FMax %double_1 %double_4\n" +
2888 "OpReturn\n" +
2889 "OpFunctionEnd",
2890 2, 4.0),
2891 // Test case 15: FMax 1.0 0.2
2892 InstructionFoldingCase<double>(
2893 Header() + "%main = OpFunction %void None %void_func\n" +
2894 "%main_lab = OpLabel\n" +
2895 "%2 = OpExtInst %double %1 FMax %double_1 %double_0p2\n" +
2896 "OpReturn\n" +
2897 "OpFunctionEnd",
2898 2, 1.0),
2899 // Test case 16: FClamp 1.0 0.2 4.0
2900 InstructionFoldingCase<double>(
2901 Header() + "%main = OpFunction %void None %void_func\n" +
2902 "%main_lab = OpLabel\n" +
2903 "%2 = OpExtInst %double %1 FClamp %double_1 %double_0p2 %double_4\n" +
2904 "OpReturn\n" +
2905 "OpFunctionEnd",
2906 2, 1.0),
2907 // Test case 17: FClamp 0.2 2.0 4.0
2908 InstructionFoldingCase<double>(
2909 Header() + "%main = OpFunction %void None %void_func\n" +
2910 "%main_lab = OpLabel\n" +
2911 "%2 = OpExtInst %double %1 FClamp %double_0p2 %double_2 %double_4\n" +
2912 "OpReturn\n" +
2913 "OpFunctionEnd",
2914 2, 2.0),
2915 // Test case 18: FClamp 5.0 2.0 4.0
2916 InstructionFoldingCase<double>(
2917 Header() + "%main = OpFunction %void None %void_func\n" +
2918 "%main_lab = OpLabel\n" +
2919 "%2 = OpExtInst %double %1 FClamp %double_5 %double_2 %double_4\n" +
2920 "OpReturn\n" +
2921 "OpFunctionEnd",
2922 2, 4.0),
2923 // Test case 19: FClamp 1.0 2.0 x
2924 InstructionFoldingCase<double>(
2925 Header() + "%main = OpFunction %void None %void_func\n" +
2926 "%main_lab = OpLabel\n" +
2927 "%undef = OpUndef %double\n" +
2928 "%2 = OpExtInst %double %1 FClamp %double_1 %double_2 %undef\n" +
2929 "OpReturn\n" +
2930 "OpFunctionEnd",
2931 2, 2.0),
2932 // Test case 20: FClamp 1.0 x 0.5
2933 InstructionFoldingCase<double>(
2934 Header() + "%main = OpFunction %void None %void_func\n" +
2935 "%main_lab = OpLabel\n" +
2936 "%undef = OpUndef %double\n" +
2937 "%2 = OpExtInst %double %1 FClamp %double_1 %undef %double_0p5\n" +
2938 "OpReturn\n" +
2939 "OpFunctionEnd",
2940 2, 0.5),
2941 // Test case 21: Sqrt 4.0
2942 InstructionFoldingCase<double>(
2943 Header() + "%main = OpFunction %void None %void_func\n" +
2944 "%main_lab = OpLabel\n" +
2945 "%undef = OpUndef %double\n" +
2946 "%2 = OpExtInst %double %1 Sqrt %double_4\n" +
2947 "OpReturn\n" +
2948 "OpFunctionEnd",
2949 2, 2.0),
2950 // Test case 22: Pow 2.0 3.0
2951 InstructionFoldingCase<double>(
2952 Header() + "%main = OpFunction %void None %void_func\n" +
2953 "%main_lab = OpLabel\n" +
2954 "%undef = OpUndef %double\n" +
2955 "%2 = OpExtInst %double %1 Pow %double_2 %double_3\n" +
2956 "OpReturn\n" +
2957 "OpFunctionEnd",
2958 2, 8.0),
2959 // Test case 23: Fold 1.0 / -0.0.
2960 InstructionFoldingCase<double>(
2961 Header() + "%main = OpFunction %void None %void_func\n" +
2962 "%main_lab = OpLabel\n" +
2963 "%2 = OpFDiv %double %double_1 %double_n0\n" +
2964 "OpReturn\n" +
2965 "OpFunctionEnd",
2966 2, -std::numeric_limits<double>::infinity()),
2967 // Test case 24: Fold -1.0 / -0.0
2968 InstructionFoldingCase<double>(
2969 Header() + "%main = OpFunction %void None %void_func\n" +
2970 "%main_lab = OpLabel\n" +
2971 "%2 = OpFDiv %double %double_n1 %double_n0\n" +
2972 "OpReturn\n" +
2973 "OpFunctionEnd",
2974 2, std::numeric_limits<double>::infinity()),
2975 // Test case 25: Fold 0.0 / 0.0
2976 InstructionFoldingCase<double>(
2977 Header() + "%main = OpFunction %void None %void_func\n" +
2978 "%main_lab = OpLabel\n" +
2979 "%2 = OpFDiv %double %double_0 %double_0\n" +
2980 "OpReturn\n" +
2981 "OpFunctionEnd",
2982 2, std::numeric_limits<double>::quiet_NaN()),
2983 // Test case 26: Fold 0.0 / -0.0
2984 InstructionFoldingCase<double>(
2985 Header() + "%main = OpFunction %void None %void_func\n" +
2986 "%main_lab = OpLabel\n" +
2987 "%2 = OpFDiv %double %double_0 %double_n0\n" +
2988 "OpReturn\n" +
2989 "OpFunctionEnd",
2990 2, std::numeric_limits<double>::quiet_NaN())
2991 ));
2992 // clang-format on
2993
2994 // clang-format off
2995 INSTANTIATE_TEST_SUITE_P(DoubleOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
2996 ::testing::Values(
2997 // Test case 0: fold 1.0 == 2.0
2998 InstructionFoldingCase<bool>(
2999 Header() + "%main = OpFunction %void None %void_func\n" +
3000 "%main_lab = OpLabel\n" +
3001 "%2 = OpFOrdEqual %bool %double_1 %double_2\n" +
3002 "OpReturn\n" +
3003 "OpFunctionEnd",
3004 2, false),
3005 // Test case 1: fold 1.0 != 2.0
3006 InstructionFoldingCase<bool>(
3007 Header() + "%main = OpFunction %void None %void_func\n" +
3008 "%main_lab = OpLabel\n" +
3009 "%2 = OpFOrdNotEqual %bool %double_1 %double_2\n" +
3010 "OpReturn\n" +
3011 "OpFunctionEnd",
3012 2, true),
3013 // Test case 2: fold 1.0 < 2.0
3014 InstructionFoldingCase<bool>(
3015 Header() + "%main = OpFunction %void None %void_func\n" +
3016 "%main_lab = OpLabel\n" +
3017 "%2 = OpFOrdLessThan %bool %double_1 %double_2\n" +
3018 "OpReturn\n" +
3019 "OpFunctionEnd",
3020 2, true),
3021 // Test case 3: fold 1.0 > 2.0
3022 InstructionFoldingCase<bool>(
3023 Header() + "%main = OpFunction %void None %void_func\n" +
3024 "%main_lab = OpLabel\n" +
3025 "%2 = OpFOrdGreaterThan %bool %double_1 %double_2\n" +
3026 "OpReturn\n" +
3027 "OpFunctionEnd",
3028 2, false),
3029 // Test case 4: fold 1.0 <= 2.0
3030 InstructionFoldingCase<bool>(
3031 Header() + "%main = OpFunction %void None %void_func\n" +
3032 "%main_lab = OpLabel\n" +
3033 "%2 = OpFOrdLessThanEqual %bool %double_1 %double_2\n" +
3034 "OpReturn\n" +
3035 "OpFunctionEnd",
3036 2, true),
3037 // Test case 5: fold 1.0 >= 2.0
3038 InstructionFoldingCase<bool>(
3039 Header() + "%main = OpFunction %void None %void_func\n" +
3040 "%main_lab = OpLabel\n" +
3041 "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_2\n" +
3042 "OpReturn\n" +
3043 "OpFunctionEnd",
3044 2, false),
3045 // Test case 6: fold 1.0 == 1.0
3046 InstructionFoldingCase<bool>(
3047 Header() + "%main = OpFunction %void None %void_func\n" +
3048 "%main_lab = OpLabel\n" +
3049 "%2 = OpFOrdEqual %bool %double_1 %double_1\n" +
3050 "OpReturn\n" +
3051 "OpFunctionEnd",
3052 2, true),
3053 // Test case 7: fold 1.0 != 1.0
3054 InstructionFoldingCase<bool>(
3055 Header() + "%main = OpFunction %void None %void_func\n" +
3056 "%main_lab = OpLabel\n" +
3057 "%2 = OpFOrdNotEqual %bool %double_1 %double_1\n" +
3058 "OpReturn\n" +
3059 "OpFunctionEnd",
3060 2, false),
3061 // Test case 8: fold 1.0 < 1.0
3062 InstructionFoldingCase<bool>(
3063 Header() + "%main = OpFunction %void None %void_func\n" +
3064 "%main_lab = OpLabel\n" +
3065 "%2 = OpFOrdLessThan %bool %double_1 %double_1\n" +
3066 "OpReturn\n" +
3067 "OpFunctionEnd",
3068 2, false),
3069 // Test case 9: fold 1.0 > 1.0
3070 InstructionFoldingCase<bool>(
3071 Header() + "%main = OpFunction %void None %void_func\n" +
3072 "%main_lab = OpLabel\n" +
3073 "%2 = OpFOrdGreaterThan %bool %double_1 %double_1\n" +
3074 "OpReturn\n" +
3075 "OpFunctionEnd",
3076 2, false),
3077 // Test case 10: fold 1.0 <= 1.0
3078 InstructionFoldingCase<bool>(
3079 Header() + "%main = OpFunction %void None %void_func\n" +
3080 "%main_lab = OpLabel\n" +
3081 "%2 = OpFOrdLessThanEqual %bool %double_1 %double_1\n" +
3082 "OpReturn\n" +
3083 "OpFunctionEnd",
3084 2, true),
3085 // Test case 11: fold 1.0 >= 1.0
3086 InstructionFoldingCase<bool>(
3087 Header() + "%main = OpFunction %void None %void_func\n" +
3088 "%main_lab = OpLabel\n" +
3089 "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_1\n" +
3090 "OpReturn\n" +
3091 "OpFunctionEnd",
3092 2, true),
3093 // Test case 12: fold 2.0 < 1.0
3094 InstructionFoldingCase<bool>(
3095 Header() + "%main = OpFunction %void None %void_func\n" +
3096 "%main_lab = OpLabel\n" +
3097 "%2 = OpFOrdLessThan %bool %double_2 %double_1\n" +
3098 "OpReturn\n" +
3099 "OpFunctionEnd",
3100 2, false),
3101 // Test case 13: fold 2.0 > 1.0
3102 InstructionFoldingCase<bool>(
3103 Header() + "%main = OpFunction %void None %void_func\n" +
3104 "%main_lab = OpLabel\n" +
3105 "%2 = OpFOrdGreaterThan %bool %double_2 %double_1\n" +
3106 "OpReturn\n" +
3107 "OpFunctionEnd",
3108 2, true),
3109 // Test case 14: fold 2.0 <= 1.0
3110 InstructionFoldingCase<bool>(
3111 Header() + "%main = OpFunction %void None %void_func\n" +
3112 "%main_lab = OpLabel\n" +
3113 "%2 = OpFOrdLessThanEqual %bool %double_2 %double_1\n" +
3114 "OpReturn\n" +
3115 "OpFunctionEnd",
3116 2, false),
3117 // Test case 15: fold 2.0 >= 1.0
3118 InstructionFoldingCase<bool>(
3119 Header() + "%main = OpFunction %void None %void_func\n" +
3120 "%main_lab = OpLabel\n" +
3121 "%2 = OpFOrdGreaterThanEqual %bool %double_2 %double_1\n" +
3122 "OpReturn\n" +
3123 "OpFunctionEnd",
3124 2, true)
3125 ));
3126
3127 INSTANTIATE_TEST_SUITE_P(DoubleUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3128 ::testing::Values(
3129 // Test case 0: fold 1.0 == 2.0
3130 InstructionFoldingCase<bool>(
3131 Header() + "%main = OpFunction %void None %void_func\n" +
3132 "%main_lab = OpLabel\n" +
3133 "%2 = OpFUnordEqual %bool %double_1 %double_2\n" +
3134 "OpReturn\n" +
3135 "OpFunctionEnd",
3136 2, false),
3137 // Test case 1: fold 1.0 != 2.0
3138 InstructionFoldingCase<bool>(
3139 Header() + "%main = OpFunction %void None %void_func\n" +
3140 "%main_lab = OpLabel\n" +
3141 "%2 = OpFUnordNotEqual %bool %double_1 %double_2\n" +
3142 "OpReturn\n" +
3143 "OpFunctionEnd",
3144 2, true),
3145 // Test case 2: fold 1.0 < 2.0
3146 InstructionFoldingCase<bool>(
3147 Header() + "%main = OpFunction %void None %void_func\n" +
3148 "%main_lab = OpLabel\n" +
3149 "%2 = OpFUnordLessThan %bool %double_1 %double_2\n" +
3150 "OpReturn\n" +
3151 "OpFunctionEnd",
3152 2, true),
3153 // Test case 3: fold 1.0 > 2.0
3154 InstructionFoldingCase<bool>(
3155 Header() + "%main = OpFunction %void None %void_func\n" +
3156 "%main_lab = OpLabel\n" +
3157 "%2 = OpFUnordGreaterThan %bool %double_1 %double_2\n" +
3158 "OpReturn\n" +
3159 "OpFunctionEnd",
3160 2, false),
3161 // Test case 4: fold 1.0 <= 2.0
3162 InstructionFoldingCase<bool>(
3163 Header() + "%main = OpFunction %void None %void_func\n" +
3164 "%main_lab = OpLabel\n" +
3165 "%2 = OpFUnordLessThanEqual %bool %double_1 %double_2\n" +
3166 "OpReturn\n" +
3167 "OpFunctionEnd",
3168 2, true),
3169 // Test case 5: fold 1.0 >= 2.0
3170 InstructionFoldingCase<bool>(
3171 Header() + "%main = OpFunction %void None %void_func\n" +
3172 "%main_lab = OpLabel\n" +
3173 "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_2\n" +
3174 "OpReturn\n" +
3175 "OpFunctionEnd",
3176 2, false),
3177 // Test case 6: fold 1.0 == 1.0
3178 InstructionFoldingCase<bool>(
3179 Header() + "%main = OpFunction %void None %void_func\n" +
3180 "%main_lab = OpLabel\n" +
3181 "%2 = OpFUnordEqual %bool %double_1 %double_1\n" +
3182 "OpReturn\n" +
3183 "OpFunctionEnd",
3184 2, true),
3185 // Test case 7: fold 1.0 != 1.0
3186 InstructionFoldingCase<bool>(
3187 Header() + "%main = OpFunction %void None %void_func\n" +
3188 "%main_lab = OpLabel\n" +
3189 "%2 = OpFUnordNotEqual %bool %double_1 %double_1\n" +
3190 "OpReturn\n" +
3191 "OpFunctionEnd",
3192 2, false),
3193 // Test case 8: fold 1.0 < 1.0
3194 InstructionFoldingCase<bool>(
3195 Header() + "%main = OpFunction %void None %void_func\n" +
3196 "%main_lab = OpLabel\n" +
3197 "%2 = OpFUnordLessThan %bool %double_1 %double_1\n" +
3198 "OpReturn\n" +
3199 "OpFunctionEnd",
3200 2, false),
3201 // Test case 9: fold 1.0 > 1.0
3202 InstructionFoldingCase<bool>(
3203 Header() + "%main = OpFunction %void None %void_func\n" +
3204 "%main_lab = OpLabel\n" +
3205 "%2 = OpFUnordGreaterThan %bool %double_1 %double_1\n" +
3206 "OpReturn\n" +
3207 "OpFunctionEnd",
3208 2, false),
3209 // Test case 10: fold 1.0 <= 1.0
3210 InstructionFoldingCase<bool>(
3211 Header() + "%main = OpFunction %void None %void_func\n" +
3212 "%main_lab = OpLabel\n" +
3213 "%2 = OpFUnordLessThanEqual %bool %double_1 %double_1\n" +
3214 "OpReturn\n" +
3215 "OpFunctionEnd",
3216 2, true),
3217 // Test case 11: fold 1.0 >= 1.0
3218 InstructionFoldingCase<bool>(
3219 Header() + "%main = OpFunction %void None %void_func\n" +
3220 "%main_lab = OpLabel\n" +
3221 "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_1\n" +
3222 "OpReturn\n" +
3223 "OpFunctionEnd",
3224 2, true),
3225 // Test case 12: fold 2.0 < 1.0
3226 InstructionFoldingCase<bool>(
3227 Header() + "%main = OpFunction %void None %void_func\n" +
3228 "%main_lab = OpLabel\n" +
3229 "%2 = OpFUnordLessThan %bool %double_2 %double_1\n" +
3230 "OpReturn\n" +
3231 "OpFunctionEnd",
3232 2, false),
3233 // Test case 13: fold 2.0 > 1.0
3234 InstructionFoldingCase<bool>(
3235 Header() + "%main = OpFunction %void None %void_func\n" +
3236 "%main_lab = OpLabel\n" +
3237 "%2 = OpFUnordGreaterThan %bool %double_2 %double_1\n" +
3238 "OpReturn\n" +
3239 "OpFunctionEnd",
3240 2, true),
3241 // Test case 14: fold 2.0 <= 1.0
3242 InstructionFoldingCase<bool>(
3243 Header() + "%main = OpFunction %void None %void_func\n" +
3244 "%main_lab = OpLabel\n" +
3245 "%2 = OpFUnordLessThanEqual %bool %double_2 %double_1\n" +
3246 "OpReturn\n" +
3247 "OpFunctionEnd",
3248 2, false),
3249 // Test case 15: fold 2.0 >= 1.0
3250 InstructionFoldingCase<bool>(
3251 Header() + "%main = OpFunction %void None %void_func\n" +
3252 "%main_lab = OpLabel\n" +
3253 "%2 = OpFUnordGreaterThanEqual %bool %double_2 %double_1\n" +
3254 "OpReturn\n" +
3255 "OpFunctionEnd",
3256 2, true)
3257 ));
3258
3259 INSTANTIATE_TEST_SUITE_P(FloatOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3260 ::testing::Values(
3261 // Test case 0: fold 1.0 == 2.0
3262 InstructionFoldingCase<bool>(
3263 Header() + "%main = OpFunction %void None %void_func\n" +
3264 "%main_lab = OpLabel\n" +
3265 "%2 = OpFOrdEqual %bool %float_1 %float_2\n" +
3266 "OpReturn\n" +
3267 "OpFunctionEnd",
3268 2, false),
3269 // Test case 1: fold 1.0 != 2.0
3270 InstructionFoldingCase<bool>(
3271 Header() + "%main = OpFunction %void None %void_func\n" +
3272 "%main_lab = OpLabel\n" +
3273 "%2 = OpFOrdNotEqual %bool %float_1 %float_2\n" +
3274 "OpReturn\n" +
3275 "OpFunctionEnd",
3276 2, true),
3277 // Test case 2: fold 1.0 < 2.0
3278 InstructionFoldingCase<bool>(
3279 Header() + "%main = OpFunction %void None %void_func\n" +
3280 "%main_lab = OpLabel\n" +
3281 "%2 = OpFOrdLessThan %bool %float_1 %float_2\n" +
3282 "OpReturn\n" +
3283 "OpFunctionEnd",
3284 2, true),
3285 // Test case 3: fold 1.0 > 2.0
3286 InstructionFoldingCase<bool>(
3287 Header() + "%main = OpFunction %void None %void_func\n" +
3288 "%main_lab = OpLabel\n" +
3289 "%2 = OpFOrdGreaterThan %bool %float_1 %float_2\n" +
3290 "OpReturn\n" +
3291 "OpFunctionEnd",
3292 2, false),
3293 // Test case 4: fold 1.0 <= 2.0
3294 InstructionFoldingCase<bool>(
3295 Header() + "%main = OpFunction %void None %void_func\n" +
3296 "%main_lab = OpLabel\n" +
3297 "%2 = OpFOrdLessThanEqual %bool %float_1 %float_2\n" +
3298 "OpReturn\n" +
3299 "OpFunctionEnd",
3300 2, true),
3301 // Test case 5: fold 1.0 >= 2.0
3302 InstructionFoldingCase<bool>(
3303 Header() + "%main = OpFunction %void None %void_func\n" +
3304 "%main_lab = OpLabel\n" +
3305 "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_2\n" +
3306 "OpReturn\n" +
3307 "OpFunctionEnd",
3308 2, false),
3309 // Test case 6: fold 1.0 == 1.0
3310 InstructionFoldingCase<bool>(
3311 Header() + "%main = OpFunction %void None %void_func\n" +
3312 "%main_lab = OpLabel\n" +
3313 "%2 = OpFOrdEqual %bool %float_1 %float_1\n" +
3314 "OpReturn\n" +
3315 "OpFunctionEnd",
3316 2, true),
3317 // Test case 7: fold 1.0 != 1.0
3318 InstructionFoldingCase<bool>(
3319 Header() + "%main = OpFunction %void None %void_func\n" +
3320 "%main_lab = OpLabel\n" +
3321 "%2 = OpFOrdNotEqual %bool %float_1 %float_1\n" +
3322 "OpReturn\n" +
3323 "OpFunctionEnd",
3324 2, false),
3325 // Test case 8: fold 1.0 < 1.0
3326 InstructionFoldingCase<bool>(
3327 Header() + "%main = OpFunction %void None %void_func\n" +
3328 "%main_lab = OpLabel\n" +
3329 "%2 = OpFOrdLessThan %bool %float_1 %float_1\n" +
3330 "OpReturn\n" +
3331 "OpFunctionEnd",
3332 2, false),
3333 // Test case 9: fold 1.0 > 1.0
3334 InstructionFoldingCase<bool>(
3335 Header() + "%main = OpFunction %void None %void_func\n" +
3336 "%main_lab = OpLabel\n" +
3337 "%2 = OpFOrdGreaterThan %bool %float_1 %float_1\n" +
3338 "OpReturn\n" +
3339 "OpFunctionEnd",
3340 2, false),
3341 // Test case 10: fold 1.0 <= 1.0
3342 InstructionFoldingCase<bool>(
3343 Header() + "%main = OpFunction %void None %void_func\n" +
3344 "%main_lab = OpLabel\n" +
3345 "%2 = OpFOrdLessThanEqual %bool %float_1 %float_1\n" +
3346 "OpReturn\n" +
3347 "OpFunctionEnd",
3348 2, true),
3349 // Test case 11: fold 1.0 >= 1.0
3350 InstructionFoldingCase<bool>(
3351 Header() + "%main = OpFunction %void None %void_func\n" +
3352 "%main_lab = OpLabel\n" +
3353 "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_1\n" +
3354 "OpReturn\n" +
3355 "OpFunctionEnd",
3356 2, true),
3357 // Test case 12: fold 2.0 < 1.0
3358 InstructionFoldingCase<bool>(
3359 Header() + "%main = OpFunction %void None %void_func\n" +
3360 "%main_lab = OpLabel\n" +
3361 "%2 = OpFOrdLessThan %bool %float_2 %float_1\n" +
3362 "OpReturn\n" +
3363 "OpFunctionEnd",
3364 2, false),
3365 // Test case 13: fold 2.0 > 1.0
3366 InstructionFoldingCase<bool>(
3367 Header() + "%main = OpFunction %void None %void_func\n" +
3368 "%main_lab = OpLabel\n" +
3369 "%2 = OpFOrdGreaterThan %bool %float_2 %float_1\n" +
3370 "OpReturn\n" +
3371 "OpFunctionEnd",
3372 2, true),
3373 // Test case 14: fold 2.0 <= 1.0
3374 InstructionFoldingCase<bool>(
3375 Header() + "%main = OpFunction %void None %void_func\n" +
3376 "%main_lab = OpLabel\n" +
3377 "%2 = OpFOrdLessThanEqual %bool %float_2 %float_1\n" +
3378 "OpReturn\n" +
3379 "OpFunctionEnd",
3380 2, false),
3381 // Test case 15: fold 2.0 >= 1.0
3382 InstructionFoldingCase<bool>(
3383 Header() + "%main = OpFunction %void None %void_func\n" +
3384 "%main_lab = OpLabel\n" +
3385 "%2 = OpFOrdGreaterThanEqual %bool %float_2 %float_1\n" +
3386 "OpReturn\n" +
3387 "OpFunctionEnd",
3388 2, true)
3389 ));
3390
3391 INSTANTIATE_TEST_SUITE_P(FloatUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3392 ::testing::Values(
3393 // Test case 0: fold 1.0 == 2.0
3394 InstructionFoldingCase<bool>(
3395 Header() + "%main = OpFunction %void None %void_func\n" +
3396 "%main_lab = OpLabel\n" +
3397 "%2 = OpFUnordEqual %bool %float_1 %float_2\n" +
3398 "OpReturn\n" +
3399 "OpFunctionEnd",
3400 2, false),
3401 // Test case 1: fold 1.0 != 2.0
3402 InstructionFoldingCase<bool>(
3403 Header() + "%main = OpFunction %void None %void_func\n" +
3404 "%main_lab = OpLabel\n" +
3405 "%2 = OpFUnordNotEqual %bool %float_1 %float_2\n" +
3406 "OpReturn\n" +
3407 "OpFunctionEnd",
3408 2, true),
3409 // Test case 2: fold 1.0 < 2.0
3410 InstructionFoldingCase<bool>(
3411 Header() + "%main = OpFunction %void None %void_func\n" +
3412 "%main_lab = OpLabel\n" +
3413 "%2 = OpFUnordLessThan %bool %float_1 %float_2\n" +
3414 "OpReturn\n" +
3415 "OpFunctionEnd",
3416 2, true),
3417 // Test case 3: fold 1.0 > 2.0
3418 InstructionFoldingCase<bool>(
3419 Header() + "%main = OpFunction %void None %void_func\n" +
3420 "%main_lab = OpLabel\n" +
3421 "%2 = OpFUnordGreaterThan %bool %float_1 %float_2\n" +
3422 "OpReturn\n" +
3423 "OpFunctionEnd",
3424 2, false),
3425 // Test case 4: fold 1.0 <= 2.0
3426 InstructionFoldingCase<bool>(
3427 Header() + "%main = OpFunction %void None %void_func\n" +
3428 "%main_lab = OpLabel\n" +
3429 "%2 = OpFUnordLessThanEqual %bool %float_1 %float_2\n" +
3430 "OpReturn\n" +
3431 "OpFunctionEnd",
3432 2, true),
3433 // Test case 5: fold 1.0 >= 2.0
3434 InstructionFoldingCase<bool>(
3435 Header() + "%main = OpFunction %void None %void_func\n" +
3436 "%main_lab = OpLabel\n" +
3437 "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_2\n" +
3438 "OpReturn\n" +
3439 "OpFunctionEnd",
3440 2, false),
3441 // Test case 6: fold 1.0 == 1.0
3442 InstructionFoldingCase<bool>(
3443 Header() + "%main = OpFunction %void None %void_func\n" +
3444 "%main_lab = OpLabel\n" +
3445 "%2 = OpFUnordEqual %bool %float_1 %float_1\n" +
3446 "OpReturn\n" +
3447 "OpFunctionEnd",
3448 2, true),
3449 // Test case 7: fold 1.0 != 1.0
3450 InstructionFoldingCase<bool>(
3451 Header() + "%main = OpFunction %void None %void_func\n" +
3452 "%main_lab = OpLabel\n" +
3453 "%2 = OpFUnordNotEqual %bool %float_1 %float_1\n" +
3454 "OpReturn\n" +
3455 "OpFunctionEnd",
3456 2, false),
3457 // Test case 8: fold 1.0 < 1.0
3458 InstructionFoldingCase<bool>(
3459 Header() + "%main = OpFunction %void None %void_func\n" +
3460 "%main_lab = OpLabel\n" +
3461 "%2 = OpFUnordLessThan %bool %float_1 %float_1\n" +
3462 "OpReturn\n" +
3463 "OpFunctionEnd",
3464 2, false),
3465 // Test case 9: fold 1.0 > 1.0
3466 InstructionFoldingCase<bool>(
3467 Header() + "%main = OpFunction %void None %void_func\n" +
3468 "%main_lab = OpLabel\n" +
3469 "%2 = OpFUnordGreaterThan %bool %float_1 %float_1\n" +
3470 "OpReturn\n" +
3471 "OpFunctionEnd",
3472 2, false),
3473 // Test case 10: fold 1.0 <= 1.0
3474 InstructionFoldingCase<bool>(
3475 Header() + "%main = OpFunction %void None %void_func\n" +
3476 "%main_lab = OpLabel\n" +
3477 "%2 = OpFUnordLessThanEqual %bool %float_1 %float_1\n" +
3478 "OpReturn\n" +
3479 "OpFunctionEnd",
3480 2, true),
3481 // Test case 11: fold 1.0 >= 1.0
3482 InstructionFoldingCase<bool>(
3483 Header() + "%main = OpFunction %void None %void_func\n" +
3484 "%main_lab = OpLabel\n" +
3485 "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_1\n" +
3486 "OpReturn\n" +
3487 "OpFunctionEnd",
3488 2, true),
3489 // Test case 12: fold 2.0 < 1.0
3490 InstructionFoldingCase<bool>(
3491 Header() + "%main = OpFunction %void None %void_func\n" +
3492 "%main_lab = OpLabel\n" +
3493 "%2 = OpFUnordLessThan %bool %float_2 %float_1\n" +
3494 "OpReturn\n" +
3495 "OpFunctionEnd",
3496 2, false),
3497 // Test case 13: fold 2.0 > 1.0
3498 InstructionFoldingCase<bool>(
3499 Header() + "%main = OpFunction %void None %void_func\n" +
3500 "%main_lab = OpLabel\n" +
3501 "%2 = OpFUnordGreaterThan %bool %float_2 %float_1\n" +
3502 "OpReturn\n" +
3503 "OpFunctionEnd",
3504 2, true),
3505 // Test case 14: fold 2.0 <= 1.0
3506 InstructionFoldingCase<bool>(
3507 Header() + "%main = OpFunction %void None %void_func\n" +
3508 "%main_lab = OpLabel\n" +
3509 "%2 = OpFUnordLessThanEqual %bool %float_2 %float_1\n" +
3510 "OpReturn\n" +
3511 "OpFunctionEnd",
3512 2, false),
3513 // Test case 15: fold 2.0 >= 1.0
3514 InstructionFoldingCase<bool>(
3515 Header() + "%main = OpFunction %void None %void_func\n" +
3516 "%main_lab = OpLabel\n" +
3517 "%2 = OpFUnordGreaterThanEqual %bool %float_2 %float_1\n" +
3518 "OpReturn\n" +
3519 "OpFunctionEnd",
3520 2, true)
3521 ));
3522
3523 INSTANTIATE_TEST_SUITE_P(DoubleNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3524 ::testing::Values(
3525 // Test case 0: fold NaN == 0 (ord)
3526 InstructionFoldingCase<bool>(
3527 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3528 "%main_lab = OpLabel\n" +
3529 "%2 = OpFOrdEqual %bool %double_nan %double_0\n" +
3530 "OpReturn\n" +
3531 "OpFunctionEnd",
3532 2, false),
3533 // Test case 1: fold NaN == NaN (unord)
3534 InstructionFoldingCase<bool>(
3535 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3536 "%main_lab = OpLabel\n" +
3537 "%2 = OpFUnordEqual %bool %double_nan %double_0\n" +
3538 "OpReturn\n" +
3539 "OpFunctionEnd",
3540 2, true),
3541 // Test case 2: fold NaN != NaN (ord)
3542 InstructionFoldingCase<bool>(
3543 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3544 "%main_lab = OpLabel\n" +
3545 "%2 = OpFOrdNotEqual %bool %double_nan %double_0\n" +
3546 "OpReturn\n" +
3547 "OpFunctionEnd",
3548 2, false),
3549 // Test case 3: fold NaN != NaN (unord)
3550 InstructionFoldingCase<bool>(
3551 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3552 "%main_lab = OpLabel\n" +
3553 "%2 = OpFUnordNotEqual %bool %double_nan %double_0\n" +
3554 "OpReturn\n" +
3555 "OpFunctionEnd",
3556 2, true)
3557 ));
3558
3559 INSTANTIATE_TEST_SUITE_P(FloatNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3560 ::testing::Values(
3561 // Test case 0: fold NaN == 0 (ord)
3562 InstructionFoldingCase<bool>(
3563 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3564 "%main_lab = OpLabel\n" +
3565 "%2 = OpFOrdEqual %bool %float_nan %float_0\n" +
3566 "OpReturn\n" +
3567 "OpFunctionEnd",
3568 2, false),
3569 // Test case 1: fold NaN == NaN (unord)
3570 InstructionFoldingCase<bool>(
3571 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3572 "%main_lab = OpLabel\n" +
3573 "%2 = OpFUnordEqual %bool %float_nan %float_0\n" +
3574 "OpReturn\n" +
3575 "OpFunctionEnd",
3576 2, true),
3577 // Test case 2: fold NaN != NaN (ord)
3578 InstructionFoldingCase<bool>(
3579 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3580 "%main_lab = OpLabel\n" +
3581 "%2 = OpFOrdNotEqual %bool %float_nan %float_0\n" +
3582 "OpReturn\n" +
3583 "OpFunctionEnd",
3584 2, false),
3585 // Test case 3: fold NaN != NaN (unord)
3586 InstructionFoldingCase<bool>(
3587 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3588 "%main_lab = OpLabel\n" +
3589 "%2 = OpFUnordNotEqual %bool %float_nan %float_0\n" +
3590 "OpReturn\n" +
3591 "OpFunctionEnd",
3592 2, true)
3593 ));
3594 // clang-format on
3595
3596 template <class ResultType>
3597 struct InstructionFoldingCaseWithMap {
InstructionFoldingCaseWithMapspvtools::opt::__anon8bea92fa0111::InstructionFoldingCaseWithMap3598 InstructionFoldingCaseWithMap(const std::string& tb, uint32_t id,
3599 ResultType result,
3600 std::function<uint32_t(uint32_t)> map)
3601 : test_body(tb), id_to_fold(id), expected_result(result), id_map(map) {}
3602
3603 std::string test_body;
3604 uint32_t id_to_fold;
3605 ResultType expected_result;
3606 std::function<uint32_t(uint32_t)> id_map;
3607 };
3608
3609 using IntegerInstructionFoldingTestWithMap =
3610 ::testing::TestWithParam<InstructionFoldingCaseWithMap<uint32_t>>;
3611
TEST_P(IntegerInstructionFoldingTestWithMap,Case)3612 TEST_P(IntegerInstructionFoldingTestWithMap, Case) {
3613 const auto& tc = GetParam();
3614
3615 std::unique_ptr<IRContext> context;
3616 Instruction* inst;
3617 std::tie(context, inst) =
3618 GetInstructionToFold(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_5);
3619
3620 inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
3621 tc.id_map);
3622 EXPECT_NE(inst, nullptr);
3623
3624 CheckForExpectedScalarConstant(inst, tc.expected_result,
3625 [](const analysis::Constant* c) {
3626 return c->AsIntConstant()->GetU32BitValue();
3627 });
3628 }
3629 // clang-format off
3630
3631 INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTestWithMap,
3632 ::testing::Values(
3633 // Test case 0: fold %3 = 0; %3 * n
3634 InstructionFoldingCaseWithMap<uint32_t>(
3635 Header() + "%main = OpFunction %void None %void_func\n" +
3636 "%main_lab = OpLabel\n" +
3637 "%n = OpVariable %_ptr_int Function\n" +
3638 "%load = OpLoad %int %n\n" +
3639 "%3 = OpCopyObject %int %int_0\n"
3640 "%2 = OpIMul %int %3 %load\n" +
3641 "OpReturn\n" +
3642 "OpFunctionEnd",
__anon8bea92fa0d02(uint32_t id) 3643 2, 0, [](uint32_t id) {return (id == 3 ? INT_0_ID : id);})
3644 ));
3645 // clang-format on
3646
3647 using BooleanInstructionFoldingTestWithMap =
3648 ::testing::TestWithParam<InstructionFoldingCaseWithMap<bool>>;
3649
TEST_P(BooleanInstructionFoldingTestWithMap,Case)3650 TEST_P(BooleanInstructionFoldingTestWithMap, Case) {
3651 const auto& tc = GetParam();
3652
3653 std::unique_ptr<IRContext> context;
3654 Instruction* inst;
3655 std::tie(context, inst) =
3656 GetInstructionToFold(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_5);
3657 inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
3658 tc.id_map);
3659 ASSERT_NE(inst, nullptr);
3660 CheckForExpectedScalarConstant(
3661 inst, tc.expected_result,
3662 [](const analysis::Constant* c) { return c->AsBoolConstant()->value(); });
3663 }
3664
3665 // clang-format off
3666 INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTestWithMap,
3667 ::testing::Values(
3668 // Test case 0: fold %3 = true; %3 || n
3669 InstructionFoldingCaseWithMap<bool>(
3670 Header() + "%main = OpFunction %void None %void_func\n" +
3671 "%main_lab = OpLabel\n" +
3672 "%n = OpVariable %_ptr_bool Function\n" +
3673 "%load = OpLoad %bool %n\n" +
3674 "%3 = OpCopyObject %bool %true\n" +
3675 "%2 = OpLogicalOr %bool %3 %load\n" +
3676 "OpReturn\n" +
3677 "OpFunctionEnd",
__anon8bea92fa0f02(uint32_t id) 3678 2, true, [](uint32_t id) {return (id == 3 ? TRUE_ID : id);})
3679 ));
3680 // clang-format on
3681
3682 using GeneralInstructionFoldingTest =
3683 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
3684
TEST_P(GeneralInstructionFoldingTest,Case)3685 TEST_P(GeneralInstructionFoldingTest, Case) {
3686 const auto& tc = GetParam();
3687
3688 std::unique_ptr<IRContext> context;
3689 Instruction* inst;
3690 std::tie(context, inst) =
3691 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
3692
3693 EXPECT_TRUE((inst == nullptr) == (tc.expected_result == 0));
3694 if (inst != nullptr) {
3695 EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
3696 EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
3697 }
3698 }
3699
3700 // clang-format off
3701 INSTANTIATE_TEST_SUITE_P(IntegerArithmeticTestCases, GeneralInstructionFoldingTest,
3702 ::testing::Values(
3703 // Test case 0: Don't fold n * m
3704 InstructionFoldingCase<uint32_t>(
3705 Header() + "%main = OpFunction %void None %void_func\n" +
3706 "%main_lab = OpLabel\n" +
3707 "%n = OpVariable %_ptr_int Function\n" +
3708 "%m = OpVariable %_ptr_int Function\n" +
3709 "%load_n = OpLoad %int %n\n" +
3710 "%load_m = OpLoad %int %m\n" +
3711 "%2 = OpIMul %int %load_n %load_m\n" +
3712 "OpReturn\n" +
3713 "OpFunctionEnd",
3714 2, 0),
3715 // Test case 1: Don't fold n / m (unsigned)
3716 InstructionFoldingCase<uint32_t>(
3717 Header() + "%main = OpFunction %void None %void_func\n" +
3718 "%main_lab = OpLabel\n" +
3719 "%n = OpVariable %_ptr_uint Function\n" +
3720 "%m = OpVariable %_ptr_uint Function\n" +
3721 "%load_n = OpLoad %uint %n\n" +
3722 "%load_m = OpLoad %uint %m\n" +
3723 "%2 = OpUDiv %uint %load_n %load_m\n" +
3724 "OpReturn\n" +
3725 "OpFunctionEnd",
3726 2, 0),
3727 // Test case 2: Don't fold n / m (signed)
3728 InstructionFoldingCase<uint32_t>(
3729 Header() + "%main = OpFunction %void None %void_func\n" +
3730 "%main_lab = OpLabel\n" +
3731 "%n = OpVariable %_ptr_int Function\n" +
3732 "%m = OpVariable %_ptr_int Function\n" +
3733 "%load_n = OpLoad %int %n\n" +
3734 "%load_m = OpLoad %int %m\n" +
3735 "%2 = OpSDiv %int %load_n %load_m\n" +
3736 "OpReturn\n" +
3737 "OpFunctionEnd",
3738 2, 0),
3739 // Test case 3: Don't fold n remainder m
3740 InstructionFoldingCase<uint32_t>(
3741 Header() + "%main = OpFunction %void None %void_func\n" +
3742 "%main_lab = OpLabel\n" +
3743 "%n = OpVariable %_ptr_int Function\n" +
3744 "%m = OpVariable %_ptr_int Function\n" +
3745 "%load_n = OpLoad %int %n\n" +
3746 "%load_m = OpLoad %int %m\n" +
3747 "%2 = OpSRem %int %load_n %load_m\n" +
3748 "OpReturn\n" +
3749 "OpFunctionEnd",
3750 2, 0),
3751 // Test case 4: Don't fold n % m (signed)
3752 InstructionFoldingCase<uint32_t>(
3753 Header() + "%main = OpFunction %void None %void_func\n" +
3754 "%main_lab = OpLabel\n" +
3755 "%n = OpVariable %_ptr_int Function\n" +
3756 "%m = OpVariable %_ptr_int Function\n" +
3757 "%load_n = OpLoad %int %n\n" +
3758 "%load_m = OpLoad %int %m\n" +
3759 "%2 = OpSMod %int %load_n %load_m\n" +
3760 "OpReturn\n" +
3761 "OpFunctionEnd",
3762 2, 0),
3763 // Test case 5: Don't fold n % m (unsigned)
3764 InstructionFoldingCase<uint32_t>(
3765 Header() + "%main = OpFunction %void None %void_func\n" +
3766 "%main_lab = OpLabel\n" +
3767 "%n = OpVariable %_ptr_uint Function\n" +
3768 "%m = OpVariable %_ptr_uint Function\n" +
3769 "%load_n = OpLoad %uint %n\n" +
3770 "%load_m = OpLoad %uint %m\n" +
3771 "%2 = OpUMod %int %load_n %load_m\n" +
3772 "OpReturn\n" +
3773 "OpFunctionEnd",
3774 2, 0),
3775 // Test case 6: Don't fold n << m
3776 InstructionFoldingCase<uint32_t>(
3777 Header() + "%main = OpFunction %void None %void_func\n" +
3778 "%main_lab = OpLabel\n" +
3779 "%n = OpVariable %_ptr_uint Function\n" +
3780 "%m = OpVariable %_ptr_uint Function\n" +
3781 "%load_n = OpLoad %uint %n\n" +
3782 "%load_m = OpLoad %uint %m\n" +
3783 "%2 = OpShiftRightLogical %int %load_n %load_m\n" +
3784 "OpReturn\n" +
3785 "OpFunctionEnd",
3786 2, 0),
3787 // Test case 7: Don't fold n >> m
3788 InstructionFoldingCase<uint32_t>(
3789 Header() + "%main = OpFunction %void None %void_func\n" +
3790 "%main_lab = OpLabel\n" +
3791 "%n = OpVariable %_ptr_uint Function\n" +
3792 "%m = OpVariable %_ptr_uint Function\n" +
3793 "%load_n = OpLoad %uint %n\n" +
3794 "%load_m = OpLoad %uint %m\n" +
3795 "%2 = OpShiftLeftLogical %int %load_n %load_m\n" +
3796 "OpReturn\n" +
3797 "OpFunctionEnd",
3798 2, 0),
3799 // Test case 8: Don't fold n | m
3800 InstructionFoldingCase<uint32_t>(
3801 Header() + "%main = OpFunction %void None %void_func\n" +
3802 "%main_lab = OpLabel\n" +
3803 "%n = OpVariable %_ptr_uint Function\n" +
3804 "%m = OpVariable %_ptr_uint Function\n" +
3805 "%load_n = OpLoad %uint %n\n" +
3806 "%load_m = OpLoad %uint %m\n" +
3807 "%2 = OpBitwiseOr %int %load_n %load_m\n" +
3808 "OpReturn\n" +
3809 "OpFunctionEnd",
3810 2, 0),
3811 // Test case 9: Don't fold n & m
3812 InstructionFoldingCase<uint32_t>(
3813 Header() + "%main = OpFunction %void None %void_func\n" +
3814 "%main_lab = OpLabel\n" +
3815 "%n = OpVariable %_ptr_uint Function\n" +
3816 "%m = OpVariable %_ptr_uint Function\n" +
3817 "%load_n = OpLoad %uint %n\n" +
3818 "%load_m = OpLoad %uint %m\n" +
3819 "%2 = OpBitwiseAnd %int %load_n %load_m\n" +
3820 "OpReturn\n" +
3821 "OpFunctionEnd",
3822 2, 0),
3823 // Test case 10: Don't fold n < m (unsigned)
3824 InstructionFoldingCase<uint32_t>(
3825 Header() + "%main = OpFunction %void None %void_func\n" +
3826 "%main_lab = OpLabel\n" +
3827 "%n = OpVariable %_ptr_uint Function\n" +
3828 "%m = OpVariable %_ptr_uint Function\n" +
3829 "%load_n = OpLoad %uint %n\n" +
3830 "%load_m = OpLoad %uint %m\n" +
3831 "%2 = OpULessThan %bool %load_n %load_m\n" +
3832 "OpReturn\n" +
3833 "OpFunctionEnd",
3834 2, 0),
3835 // Test case 11: Don't fold n > m (unsigned)
3836 InstructionFoldingCase<uint32_t>(
3837 Header() + "%main = OpFunction %void None %void_func\n" +
3838 "%main_lab = OpLabel\n" +
3839 "%n = OpVariable %_ptr_uint Function\n" +
3840 "%m = OpVariable %_ptr_uint Function\n" +
3841 "%load_n = OpLoad %uint %n\n" +
3842 "%load_m = OpLoad %uint %m\n" +
3843 "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
3844 "OpReturn\n" +
3845 "OpFunctionEnd",
3846 2, 0),
3847 // Test case 12: Don't fold n <= m (unsigned)
3848 InstructionFoldingCase<uint32_t>(
3849 Header() + "%main = OpFunction %void None %void_func\n" +
3850 "%main_lab = OpLabel\n" +
3851 "%n = OpVariable %_ptr_uint Function\n" +
3852 "%m = OpVariable %_ptr_uint Function\n" +
3853 "%load_n = OpLoad %uint %n\n" +
3854 "%load_m = OpLoad %uint %m\n" +
3855 "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
3856 "OpReturn\n" +
3857 "OpFunctionEnd",
3858 2, 0),
3859 // Test case 13: Don't fold n >= m (unsigned)
3860 InstructionFoldingCase<uint32_t>(
3861 Header() + "%main = OpFunction %void None %void_func\n" +
3862 "%main_lab = OpLabel\n" +
3863 "%n = OpVariable %_ptr_uint Function\n" +
3864 "%m = OpVariable %_ptr_uint Function\n" +
3865 "%load_n = OpLoad %uint %n\n" +
3866 "%load_m = OpLoad %uint %m\n" +
3867 "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
3868 "OpReturn\n" +
3869 "OpFunctionEnd",
3870 2, 0),
3871 // Test case 14: Don't fold n < m (signed)
3872 InstructionFoldingCase<uint32_t>(
3873 Header() + "%main = OpFunction %void None %void_func\n" +
3874 "%main_lab = OpLabel\n" +
3875 "%n = OpVariable %_ptr_int Function\n" +
3876 "%m = OpVariable %_ptr_int Function\n" +
3877 "%load_n = OpLoad %int %n\n" +
3878 "%load_m = OpLoad %int %m\n" +
3879 "%2 = OpULessThan %bool %load_n %load_m\n" +
3880 "OpReturn\n" +
3881 "OpFunctionEnd",
3882 2, 0),
3883 // Test case 15: Don't fold n > m (signed)
3884 InstructionFoldingCase<uint32_t>(
3885 Header() + "%main = OpFunction %void None %void_func\n" +
3886 "%main_lab = OpLabel\n" +
3887 "%n = OpVariable %_ptr_int Function\n" +
3888 "%m = OpVariable %_ptr_int Function\n" +
3889 "%load_n = OpLoad %int %n\n" +
3890 "%load_m = OpLoad %int %m\n" +
3891 "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
3892 "OpReturn\n" +
3893 "OpFunctionEnd",
3894 2, 0),
3895 // Test case 16: Don't fold n <= m (signed)
3896 InstructionFoldingCase<uint32_t>(
3897 Header() + "%main = OpFunction %void None %void_func\n" +
3898 "%main_lab = OpLabel\n" +
3899 "%n = OpVariable %_ptr_int Function\n" +
3900 "%m = OpVariable %_ptr_int Function\n" +
3901 "%load_n = OpLoad %int %n\n" +
3902 "%load_m = OpLoad %int %m\n" +
3903 "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
3904 "OpReturn\n" +
3905 "OpFunctionEnd",
3906 2, 0),
3907 // Test case 17: Don't fold n >= m (signed)
3908 InstructionFoldingCase<uint32_t>(
3909 Header() + "%main = OpFunction %void None %void_func\n" +
3910 "%main_lab = OpLabel\n" +
3911 "%n = OpVariable %_ptr_int Function\n" +
3912 "%m = OpVariable %_ptr_int Function\n" +
3913 "%load_n = OpLoad %int %n\n" +
3914 "%load_m = OpLoad %int %m\n" +
3915 "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
3916 "OpReturn\n" +
3917 "OpFunctionEnd",
3918 2, 0),
3919 // Test case 18: Don't fold n || m
3920 InstructionFoldingCase<uint32_t>(
3921 Header() + "%main = OpFunction %void None %void_func\n" +
3922 "%main_lab = OpLabel\n" +
3923 "%n = OpVariable %_ptr_bool Function\n" +
3924 "%m = OpVariable %_ptr_bool Function\n" +
3925 "%load_n = OpLoad %bool %n\n" +
3926 "%load_m = OpLoad %bool %m\n" +
3927 "%2 = OpLogicalOr %bool %load_n %load_m\n" +
3928 "OpReturn\n" +
3929 "OpFunctionEnd",
3930 2, 0),
3931 // Test case 19: Don't fold n && m
3932 InstructionFoldingCase<uint32_t>(
3933 Header() + "%main = OpFunction %void None %void_func\n" +
3934 "%main_lab = OpLabel\n" +
3935 "%n = OpVariable %_ptr_bool Function\n" +
3936 "%m = OpVariable %_ptr_bool Function\n" +
3937 "%load_n = OpLoad %bool %n\n" +
3938 "%load_m = OpLoad %bool %m\n" +
3939 "%2 = OpLogicalAnd %bool %load_n %load_m\n" +
3940 "OpReturn\n" +
3941 "OpFunctionEnd",
3942 2, 0),
3943 // Test case 20: Don't fold n * 3
3944 InstructionFoldingCase<uint32_t>(
3945 Header() + "%main = OpFunction %void None %void_func\n" +
3946 "%main_lab = OpLabel\n" +
3947 "%n = OpVariable %_ptr_int Function\n" +
3948 "%load_n = OpLoad %int %n\n" +
3949 "%2 = OpIMul %int %load_n %int_3\n" +
3950 "OpReturn\n" +
3951 "OpFunctionEnd",
3952 2, 0),
3953 // Test case 21: Don't fold n / 3 (unsigned)
3954 InstructionFoldingCase<uint32_t>(
3955 Header() + "%main = OpFunction %void None %void_func\n" +
3956 "%main_lab = OpLabel\n" +
3957 "%n = OpVariable %_ptr_uint Function\n" +
3958 "%load_n = OpLoad %uint %n\n" +
3959 "%2 = OpUDiv %uint %load_n %uint_3\n" +
3960 "OpReturn\n" +
3961 "OpFunctionEnd",
3962 2, 0),
3963 // Test case 22: Don't fold n / 3 (signed)
3964 InstructionFoldingCase<uint32_t>(
3965 Header() + "%main = OpFunction %void None %void_func\n" +
3966 "%main_lab = OpLabel\n" +
3967 "%n = OpVariable %_ptr_int Function\n" +
3968 "%load_n = OpLoad %int %n\n" +
3969 "%2 = OpSDiv %int %load_n %int_3\n" +
3970 "OpReturn\n" +
3971 "OpFunctionEnd",
3972 2, 0),
3973 // Test case 23: Don't fold n remainder 3
3974 InstructionFoldingCase<uint32_t>(
3975 Header() + "%main = OpFunction %void None %void_func\n" +
3976 "%main_lab = OpLabel\n" +
3977 "%n = OpVariable %_ptr_int Function\n" +
3978 "%load_n = OpLoad %int %n\n" +
3979 "%2 = OpSRem %int %load_n %int_3\n" +
3980 "OpReturn\n" +
3981 "OpFunctionEnd",
3982 2, 0),
3983 // Test case 24: Don't fold n % 3 (signed)
3984 InstructionFoldingCase<uint32_t>(
3985 Header() + "%main = OpFunction %void None %void_func\n" +
3986 "%main_lab = OpLabel\n" +
3987 "%n = OpVariable %_ptr_int Function\n" +
3988 "%load_n = OpLoad %int %n\n" +
3989 "%2 = OpSMod %int %load_n %int_3\n" +
3990 "OpReturn\n" +
3991 "OpFunctionEnd",
3992 2, 0),
3993 // Test case 25: Don't fold n % 3 (unsigned)
3994 InstructionFoldingCase<uint32_t>(
3995 Header() + "%main = OpFunction %void None %void_func\n" +
3996 "%main_lab = OpLabel\n" +
3997 "%n = OpVariable %_ptr_uint Function\n" +
3998 "%load_n = OpLoad %uint %n\n" +
3999 "%2 = OpUMod %int %load_n %int_3\n" +
4000 "OpReturn\n" +
4001 "OpFunctionEnd",
4002 2, 0),
4003 // Test case 26: Don't fold n << 3
4004 InstructionFoldingCase<uint32_t>(
4005 Header() + "%main = OpFunction %void None %void_func\n" +
4006 "%main_lab = OpLabel\n" +
4007 "%n = OpVariable %_ptr_uint Function\n" +
4008 "%load_n = OpLoad %uint %n\n" +
4009 "%2 = OpShiftRightLogical %int %load_n %int_3\n" +
4010 "OpReturn\n" +
4011 "OpFunctionEnd",
4012 2, 0),
4013 // Test case 27: Don't fold n >> 3
4014 InstructionFoldingCase<uint32_t>(
4015 Header() + "%main = OpFunction %void None %void_func\n" +
4016 "%main_lab = OpLabel\n" +
4017 "%n = OpVariable %_ptr_uint Function\n" +
4018 "%load_n = OpLoad %uint %n\n" +
4019 "%2 = OpShiftLeftLogical %int %load_n %int_3\n" +
4020 "OpReturn\n" +
4021 "OpFunctionEnd",
4022 2, 0),
4023 // Test case 28: Don't fold n | 3
4024 InstructionFoldingCase<uint32_t>(
4025 Header() + "%main = OpFunction %void None %void_func\n" +
4026 "%main_lab = OpLabel\n" +
4027 "%n = OpVariable %_ptr_uint Function\n" +
4028 "%load_n = OpLoad %uint %n\n" +
4029 "%2 = OpBitwiseOr %int %load_n %int_3\n" +
4030 "OpReturn\n" +
4031 "OpFunctionEnd",
4032 2, 0),
4033 // Test case 29: Don't fold n & 3
4034 InstructionFoldingCase<uint32_t>(
4035 Header() + "%main = OpFunction %void None %void_func\n" +
4036 "%main_lab = OpLabel\n" +
4037 "%n = OpVariable %_ptr_uint Function\n" +
4038 "%load_n = OpLoad %uint %n\n" +
4039 "%2 = OpBitwiseAnd %uint %load_n %uint_3\n" +
4040 "OpReturn\n" +
4041 "OpFunctionEnd",
4042 2, 0),
4043 // Test case 30: Don't fold n < 3 (unsigned)
4044 InstructionFoldingCase<uint32_t>(
4045 Header() + "%main = OpFunction %void None %void_func\n" +
4046 "%main_lab = OpLabel\n" +
4047 "%n = OpVariable %_ptr_uint Function\n" +
4048 "%load_n = OpLoad %uint %n\n" +
4049 "%2 = OpULessThan %bool %load_n %uint_3\n" +
4050 "OpReturn\n" +
4051 "OpFunctionEnd",
4052 2, 0),
4053 // Test case 31: Don't fold n > 3 (unsigned)
4054 InstructionFoldingCase<uint32_t>(
4055 Header() + "%main = OpFunction %void None %void_func\n" +
4056 "%main_lab = OpLabel\n" +
4057 "%n = OpVariable %_ptr_uint Function\n" +
4058 "%load_n = OpLoad %uint %n\n" +
4059 "%2 = OpUGreaterThan %bool %load_n %uint_3\n" +
4060 "OpReturn\n" +
4061 "OpFunctionEnd",
4062 2, 0),
4063 // Test case 32: Don't fold n <= 3 (unsigned)
4064 InstructionFoldingCase<uint32_t>(
4065 Header() + "%main = OpFunction %void None %void_func\n" +
4066 "%main_lab = OpLabel\n" +
4067 "%n = OpVariable %_ptr_uint Function\n" +
4068 "%load_n = OpLoad %uint %n\n" +
4069 "%2 = OpULessThanEqual %bool %load_n %uint_3\n" +
4070 "OpReturn\n" +
4071 "OpFunctionEnd",
4072 2, 0),
4073 // Test case 33: Don't fold n >= 3 (unsigned)
4074 InstructionFoldingCase<uint32_t>(
4075 Header() + "%main = OpFunction %void None %void_func\n" +
4076 "%main_lab = OpLabel\n" +
4077 "%n = OpVariable %_ptr_uint Function\n" +
4078 "%load_n = OpLoad %uint %n\n" +
4079 "%2 = OpUGreaterThanEqual %bool %load_n %uint_3\n" +
4080 "OpReturn\n" +
4081 "OpFunctionEnd",
4082 2, 0),
4083 // Test case 34: Don't fold n < 3 (signed)
4084 InstructionFoldingCase<uint32_t>(
4085 Header() + "%main = OpFunction %void None %void_func\n" +
4086 "%main_lab = OpLabel\n" +
4087 "%n = OpVariable %_ptr_int Function\n" +
4088 "%load_n = OpLoad %int %n\n" +
4089 "%2 = OpULessThan %bool %load_n %int_3\n" +
4090 "OpReturn\n" +
4091 "OpFunctionEnd",
4092 2, 0),
4093 // Test case 35: Don't fold n > 3 (signed)
4094 InstructionFoldingCase<uint32_t>(
4095 Header() + "%main = OpFunction %void None %void_func\n" +
4096 "%main_lab = OpLabel\n" +
4097 "%n = OpVariable %_ptr_int Function\n" +
4098 "%load_n = OpLoad %int %n\n" +
4099 "%2 = OpUGreaterThan %bool %load_n %int_3\n" +
4100 "OpReturn\n" +
4101 "OpFunctionEnd",
4102 2, 0),
4103 // Test case 36: Don't fold n <= 3 (signed)
4104 InstructionFoldingCase<uint32_t>(
4105 Header() + "%main = OpFunction %void None %void_func\n" +
4106 "%main_lab = OpLabel\n" +
4107 "%n = OpVariable %_ptr_int Function\n" +
4108 "%load_n = OpLoad %int %n\n" +
4109 "%2 = OpULessThanEqual %bool %load_n %int_3\n" +
4110 "OpReturn\n" +
4111 "OpFunctionEnd",
4112 2, 0),
4113 // Test case 37: Don't fold n >= 3 (signed)
4114 InstructionFoldingCase<uint32_t>(
4115 Header() + "%main = OpFunction %void None %void_func\n" +
4116 "%main_lab = OpLabel\n" +
4117 "%n = OpVariable %_ptr_int Function\n" +
4118 "%load_n = OpLoad %int %n\n" +
4119 "%2 = OpUGreaterThanEqual %bool %load_n %int_3\n" +
4120 "OpReturn\n" +
4121 "OpFunctionEnd",
4122 2, 0),
4123 // Test case 38: fold 1*n
4124 InstructionFoldingCase<uint32_t>(
4125 Header() + "%main = OpFunction %void None %void_func\n" +
4126 "%main_lab = OpLabel\n" +
4127 "%n = OpVariable %_ptr_int Function\n" +
4128 "%3 = OpLoad %int %n\n" +
4129 "%2 = OpIMul %int %int_1 %3\n" +
4130 "OpReturn\n" +
4131 "OpFunctionEnd",
4132 2, 3),
4133 // Test case 39: fold n*1
4134 InstructionFoldingCase<uint32_t>(
4135 Header() + "%main = OpFunction %void None %void_func\n" +
4136 "%main_lab = OpLabel\n" +
4137 "%n = OpVariable %_ptr_int Function\n" +
4138 "%3 = OpLoad %int %n\n" +
4139 "%2 = OpIMul %int %3 %int_1\n" +
4140 "OpReturn\n" +
4141 "OpFunctionEnd",
4142 2, 3),
4143 // Test case 40: Don't fold comparisons of 64-bit types
4144 // (https://github.com/KhronosGroup/SPIRV-Tools/issues/3343).
4145 InstructionFoldingCase<uint32_t>(
4146 Header() + "%main = OpFunction %void None %void_func\n" +
4147 "%main_lab = OpLabel\n" +
4148 "%2 = OpSLessThan %bool %long_0 %long_2\n" +
4149 "OpReturn\n" +
4150 "OpFunctionEnd",
4151 2, 0)
4152 ));
4153
4154 INSTANTIATE_TEST_SUITE_P(CompositeExtractFoldingTest, GeneralInstructionFoldingTest,
4155 ::testing::Values(
4156 // Test case 0: fold Insert feeding extract
4157 InstructionFoldingCase<uint32_t>(
4158 Header() + "%main = OpFunction %void None %void_func\n" +
4159 "%main_lab = OpLabel\n" +
4160 "%n = OpVariable %_ptr_int Function\n" +
4161 "%2 = OpLoad %int %n\n" +
4162 "%3 = OpCompositeInsert %v4int %2 %v4int_0_0_0_0 0\n" +
4163 "%4 = OpCompositeInsert %v4int %int_1 %3 1\n" +
4164 "%5 = OpCompositeInsert %v4int %int_1 %4 2\n" +
4165 "%6 = OpCompositeInsert %v4int %int_1 %5 3\n" +
4166 "%7 = OpCompositeExtract %int %6 0\n" +
4167 "OpReturn\n" +
4168 "OpFunctionEnd",
4169 7, 2),
4170 // Test case 1: fold Composite construct feeding extract (position 0)
4171 InstructionFoldingCase<uint32_t>(
4172 Header() + "%main = OpFunction %void None %void_func\n" +
4173 "%main_lab = OpLabel\n" +
4174 "%n = OpVariable %_ptr_int Function\n" +
4175 "%2 = OpLoad %int %n\n" +
4176 "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %int_0\n" +
4177 "%4 = OpCompositeExtract %int %3 0\n" +
4178 "OpReturn\n" +
4179 "OpFunctionEnd",
4180 4, 2),
4181 // Test case 2: fold Composite construct feeding extract (position 3)
4182 InstructionFoldingCase<uint32_t>(
4183 Header() + "%main = OpFunction %void None %void_func\n" +
4184 "%main_lab = OpLabel\n" +
4185 "%n = OpVariable %_ptr_int Function\n" +
4186 "%2 = OpLoad %int %n\n" +
4187 "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %100\n" +
4188 "%4 = OpCompositeExtract %int %3 3\n" +
4189 "OpReturn\n" +
4190 "OpFunctionEnd",
4191 4, INT_0_ID),
4192 // Test case 3: fold Composite construct with vectors feeding extract (scalar element)
4193 InstructionFoldingCase<uint32_t>(
4194 Header() + "%main = OpFunction %void None %void_func\n" +
4195 "%main_lab = OpLabel\n" +
4196 "%n = OpVariable %_ptr_int Function\n" +
4197 "%2 = OpLoad %int %n\n" +
4198 "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
4199 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
4200 "%5 = OpCompositeExtract %int %4 3\n" +
4201 "OpReturn\n" +
4202 "OpFunctionEnd",
4203 5, INT_0_ID),
4204 // Test case 4: fold Composite construct with vectors feeding extract (start of vector element)
4205 InstructionFoldingCase<uint32_t>(
4206 Header() + "%main = OpFunction %void None %void_func\n" +
4207 "%main_lab = OpLabel\n" +
4208 "%n = OpVariable %_ptr_int Function\n" +
4209 "%2 = OpLoad %int %n\n" +
4210 "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
4211 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
4212 "%5 = OpCompositeExtract %int %4 0\n" +
4213 "OpReturn\n" +
4214 "OpFunctionEnd",
4215 5, 2),
4216 // Test case 5: fold Composite construct with vectors feeding extract (middle of vector element)
4217 InstructionFoldingCase<uint32_t>(
4218 Header() + "%main = OpFunction %void None %void_func\n" +
4219 "%main_lab = OpLabel\n" +
4220 "%n = OpVariable %_ptr_int Function\n" +
4221 "%2 = OpLoad %int %n\n" +
4222 "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
4223 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
4224 "%5 = OpCompositeExtract %int %4 1\n" +
4225 "OpReturn\n" +
4226 "OpFunctionEnd",
4227 5, 2),
4228 // Test case 6: fold Composite construct with multiple indices.
4229 InstructionFoldingCase<uint32_t>(
4230 Header() + "%main = OpFunction %void None %void_func\n" +
4231 "%main_lab = OpLabel\n" +
4232 "%n = OpVariable %_ptr_int Function\n" +
4233 "%2 = OpLoad %int %n\n" +
4234 "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
4235 "%4 = OpCompositeConstruct %struct_v2int_int_int %3 %int_0 %100\n" +
4236 "%5 = OpCompositeExtract %int %4 0 1\n" +
4237 "OpReturn\n" +
4238 "OpFunctionEnd",
4239 5, 2),
4240 // Test case 7: fold constant extract.
4241 InstructionFoldingCase<uint32_t>(
4242 Header() + "%main = OpFunction %void None %void_func\n" +
4243 "%main_lab = OpLabel\n" +
4244 "%2 = OpCompositeExtract %int %102 1\n" +
4245 "OpReturn\n" +
4246 "OpFunctionEnd",
4247 2, INT_7_ID),
4248 // Test case 8: constant struct has OpUndef
4249 InstructionFoldingCase<uint32_t>(
4250 Header() + "%main = OpFunction %void None %void_func\n" +
4251 "%main_lab = OpLabel\n" +
4252 "%2 = OpCompositeExtract %int %struct_undef_0_0 0 1\n" +
4253 "OpReturn\n" +
4254 "OpFunctionEnd",
4255 2, 0),
4256 // Test case 9: Extracting a member of element inserted via Insert
4257 InstructionFoldingCase<uint32_t>(
4258 Header() + "%main = OpFunction %void None %void_func\n" +
4259 "%main_lab = OpLabel\n" +
4260 "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
4261 "%2 = OpLoad %struct_v2int_int_int %n\n" +
4262 "%3 = OpCompositeInsert %struct_v2int_int_int %102 %2 0\n" +
4263 "%4 = OpCompositeExtract %int %3 0 1\n" +
4264 "OpReturn\n" +
4265 "OpFunctionEnd",
4266 4, 103),
4267 // Test case 10: Extracting a element that is partially changed by Insert. (Don't fold)
4268 InstructionFoldingCase<uint32_t>(
4269 Header() + "%main = OpFunction %void None %void_func\n" +
4270 "%main_lab = OpLabel\n" +
4271 "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
4272 "%2 = OpLoad %struct_v2int_int_int %n\n" +
4273 "%3 = OpCompositeInsert %struct_v2int_int_int %int_0 %2 0 1\n" +
4274 "%4 = OpCompositeExtract %v2int %3 0\n" +
4275 "OpReturn\n" +
4276 "OpFunctionEnd",
4277 4, 0),
4278 // Test case 11: Extracting from result of vector shuffle (first input)
4279 InstructionFoldingCase<uint32_t>(
4280 Header() + "%main = OpFunction %void None %void_func\n" +
4281 "%main_lab = OpLabel\n" +
4282 "%n = OpVariable %_ptr_v2int Function\n" +
4283 "%2 = OpLoad %v2int %n\n" +
4284 "%3 = OpVectorShuffle %v2int %102 %2 3 0\n" +
4285 "%4 = OpCompositeExtract %int %3 1\n" +
4286 "OpReturn\n" +
4287 "OpFunctionEnd",
4288 4, INT_7_ID),
4289 // Test case 12: Extracting from result of vector shuffle (second input)
4290 InstructionFoldingCase<uint32_t>(
4291 Header() + "%main = OpFunction %void None %void_func\n" +
4292 "%main_lab = OpLabel\n" +
4293 "%n = OpVariable %_ptr_v2int Function\n" +
4294 "%2 = OpLoad %v2int %n\n" +
4295 "%3 = OpVectorShuffle %v2int %2 %102 2 0\n" +
4296 "%4 = OpCompositeExtract %int %3 0\n" +
4297 "OpReturn\n" +
4298 "OpFunctionEnd",
4299 4, INT_7_ID),
4300 // Test case 13: https://github.com/KhronosGroup/SPIRV-Tools/issues/2608
4301 // Out of bounds access. Do not fold.
4302 InstructionFoldingCase<uint32_t>(
4303 Header() + "%main = OpFunction %void None %void_func\n" +
4304 "%main_lab = OpLabel\n" +
4305 "%2 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n" +
4306 "%3 = OpCompositeExtract %float %2 4\n" +
4307 "OpReturn\n" +
4308 "OpFunctionEnd",
4309 3, 0),
4310 // Test case 14: https://github.com/KhronosGroup/SPIRV-Tools/issues/3631
4311 // Extract the component right after the vector constituent.
4312 InstructionFoldingCase<uint32_t>(
4313 Header() + "%main = OpFunction %void None %void_func\n" +
4314 "%main_lab = OpLabel\n" +
4315 "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
4316 "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
4317 "%4 = OpCompositeExtract %int %3 2\n" +
4318 "OpReturn\n" +
4319 "OpFunctionEnd",
4320 4, INT_0_ID),
4321 // Test case 15:
4322 // Don't fold extract fed by construct with vector result if the index is
4323 // past the last element.
4324 InstructionFoldingCase<uint32_t>(
4325 Header() + "%main = OpFunction %void None %void_func\n" +
4326 "%main_lab = OpLabel\n" +
4327 "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
4328 "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
4329 "%4 = OpCompositeExtract %int %3 4\n" +
4330 "OpReturn\n" +
4331 "OpFunctionEnd",
4332 4, 0)
4333 ));
4334
4335 INSTANTIATE_TEST_SUITE_P(CompositeConstructFoldingTest, GeneralInstructionFoldingTest,
4336 ::testing::Values(
4337 // Test case 0: fold Extracts feeding construct
4338 InstructionFoldingCase<uint32_t>(
4339 Header() + "%main = OpFunction %void None %void_func\n" +
4340 "%main_lab = OpLabel\n" +
4341 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
4342 "%3 = OpCompositeExtract %int %2 0\n" +
4343 "%4 = OpCompositeExtract %int %2 1\n" +
4344 "%5 = OpCompositeExtract %int %2 2\n" +
4345 "%6 = OpCompositeExtract %int %2 3\n" +
4346 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
4347 "OpReturn\n" +
4348 "OpFunctionEnd",
4349 7, 2),
4350 // Test case 1: Don't fold Extracts feeding construct (Different source)
4351 InstructionFoldingCase<uint32_t>(
4352 Header() + "%main = OpFunction %void None %void_func\n" +
4353 "%main_lab = OpLabel\n" +
4354 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
4355 "%3 = OpCompositeExtract %int %2 0\n" +
4356 "%4 = OpCompositeExtract %int %2 1\n" +
4357 "%5 = OpCompositeExtract %int %2 2\n" +
4358 "%6 = OpCompositeExtract %int %v4int_0_0_0_0 3\n" +
4359 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
4360 "OpReturn\n" +
4361 "OpFunctionEnd",
4362 7, 0),
4363 // Test case 2: Don't fold Extracts feeding construct (bad indices)
4364 InstructionFoldingCase<uint32_t>(
4365 Header() + "%main = OpFunction %void None %void_func\n" +
4366 "%main_lab = OpLabel\n" +
4367 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
4368 "%3 = OpCompositeExtract %int %2 0\n" +
4369 "%4 = OpCompositeExtract %int %2 0\n" +
4370 "%5 = OpCompositeExtract %int %2 2\n" +
4371 "%6 = OpCompositeExtract %int %2 3\n" +
4372 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
4373 "OpReturn\n" +
4374 "OpFunctionEnd",
4375 7, 0),
4376 // Test case 3: Don't fold Extracts feeding construct (different type)
4377 InstructionFoldingCase<uint32_t>(
4378 Header() + "%main = OpFunction %void None %void_func\n" +
4379 "%main_lab = OpLabel\n" +
4380 "%2 = OpCopyObject %struct_v2int_int_int %struct_v2int_int_int_null\n" +
4381 "%3 = OpCompositeExtract %v2int %2 0\n" +
4382 "%4 = OpCompositeExtract %int %2 1\n" +
4383 "%5 = OpCompositeExtract %int %2 2\n" +
4384 "%7 = OpCompositeConstruct %v4int %3 %4 %5\n" +
4385 "OpReturn\n" +
4386 "OpFunctionEnd",
4387 7, 0),
4388 // Test case 4: Fold construct with constants to constant.
4389 InstructionFoldingCase<uint32_t>(
4390 Header() + "%main = OpFunction %void None %void_func\n" +
4391 "%main_lab = OpLabel\n" +
4392 "%2 = OpCompositeConstruct %v2int %103 %103\n" +
4393 "OpReturn\n" +
4394 "OpFunctionEnd",
4395 2, VEC2_0_ID),
4396 // Test case 5: Don't segfault when trying to fold an OpCompositeConstruct
4397 // for an empty struct, and we reached the id limit.
4398 InstructionFoldingCase<uint32_t>(
4399 Header() + "%empty_struct = OpTypeStruct\n" +
4400 "%main = OpFunction %void None %void_func\n" +
4401 "%main_lab = OpLabel\n" +
4402 "%4194303 = OpCompositeConstruct %empty_struct\n" +
4403 "OpReturn\n" +
4404 "OpFunctionEnd",
4405 4194303, 0)
4406 ));
4407
4408 INSTANTIATE_TEST_SUITE_P(PhiFoldingTest, GeneralInstructionFoldingTest,
4409 ::testing::Values(
4410 // Test case 0: Fold phi with the same values for all edges.
4411 InstructionFoldingCase<uint32_t>(
4412 Header() + "%main = OpFunction %void None %void_func\n" +
4413 "%main_lab = OpLabel\n" +
4414 " OpBranchConditional %true %l1 %l2\n" +
4415 "%l1 = OpLabel\n" +
4416 " OpBranch %merge_lab\n" +
4417 "%l2 = OpLabel\n" +
4418 " OpBranch %merge_lab\n" +
4419 "%merge_lab = OpLabel\n" +
4420 "%2 = OpPhi %int %100 %l1 %100 %l2\n" +
4421 "OpReturn\n" +
4422 "OpFunctionEnd",
4423 2, INT_0_ID),
4424 // Test case 1: Fold phi in pass through loop.
4425 InstructionFoldingCase<uint32_t>(
4426 Header() + "%main = OpFunction %void None %void_func\n" +
4427 "%main_lab = OpLabel\n" +
4428 " OpBranch %l1\n" +
4429 "%l1 = OpLabel\n" +
4430 "%2 = OpPhi %int %100 %main_lab %2 %l1\n" +
4431 " OpBranchConditional %true %l1 %merge_lab\n" +
4432 "%merge_lab = OpLabel\n" +
4433 "OpReturn\n" +
4434 "OpFunctionEnd",
4435 2, INT_0_ID),
4436 // Test case 2: Don't Fold phi because of different values.
4437 InstructionFoldingCase<uint32_t>(
4438 Header() + "%main = OpFunction %void None %void_func\n" +
4439 "%main_lab = OpLabel\n" +
4440 " OpBranch %l1\n" +
4441 "%l1 = OpLabel\n" +
4442 "%2 = OpPhi %int %int_0 %main_lab %int_3 %l1\n" +
4443 " OpBranchConditional %true %l1 %merge_lab\n" +
4444 "%merge_lab = OpLabel\n" +
4445 "OpReturn\n" +
4446 "OpFunctionEnd",
4447 2, 0)
4448 ));
4449
4450 INSTANTIATE_TEST_SUITE_P(FloatRedundantFoldingTest, GeneralInstructionFoldingTest,
4451 ::testing::Values(
4452 // Test case 0: Don't fold n + 1.0
4453 InstructionFoldingCase<uint32_t>(
4454 Header() + "%main = OpFunction %void None %void_func\n" +
4455 "%main_lab = OpLabel\n" +
4456 "%n = OpVariable %_ptr_float Function\n" +
4457 "%3 = OpLoad %float %n\n" +
4458 "%2 = OpFAdd %float %3 %float_2\n" +
4459 "OpReturn\n" +
4460 "OpFunctionEnd",
4461 2, 0),
4462 // Test case 1: Don't fold n - 1.0
4463 InstructionFoldingCase<uint32_t>(
4464 Header() + "%main = OpFunction %void None %void_func\n" +
4465 "%main_lab = OpLabel\n" +
4466 "%n = OpVariable %_ptr_float Function\n" +
4467 "%3 = OpLoad %float %n\n" +
4468 "%2 = OpFSub %float %3 %float_2\n" +
4469 "OpReturn\n" +
4470 "OpFunctionEnd",
4471 2, 0),
4472 // Test case 2: Don't fold n * 2.0
4473 InstructionFoldingCase<uint32_t>(
4474 Header() + "%main = OpFunction %void None %void_func\n" +
4475 "%main_lab = OpLabel\n" +
4476 "%n = OpVariable %_ptr_float Function\n" +
4477 "%3 = OpLoad %float %n\n" +
4478 "%2 = OpFMul %float %3 %float_2\n" +
4479 "OpReturn\n" +
4480 "OpFunctionEnd",
4481 2, 0),
4482 // Test case 3: Fold n + 0.0
4483 InstructionFoldingCase<uint32_t>(
4484 Header() + "%main = OpFunction %void None %void_func\n" +
4485 "%main_lab = OpLabel\n" +
4486 "%n = OpVariable %_ptr_float Function\n" +
4487 "%3 = OpLoad %float %n\n" +
4488 "%2 = OpFAdd %float %3 %float_0\n" +
4489 "OpReturn\n" +
4490 "OpFunctionEnd",
4491 2, 3),
4492 // Test case 4: Fold 0.0 + n
4493 InstructionFoldingCase<uint32_t>(
4494 Header() + "%main = OpFunction %void None %void_func\n" +
4495 "%main_lab = OpLabel\n" +
4496 "%n = OpVariable %_ptr_float Function\n" +
4497 "%3 = OpLoad %float %n\n" +
4498 "%2 = OpFAdd %float %float_0 %3\n" +
4499 "OpReturn\n" +
4500 "OpFunctionEnd",
4501 2, 3),
4502 // Test case 5: Fold n - 0.0
4503 InstructionFoldingCase<uint32_t>(
4504 Header() + "%main = OpFunction %void None %void_func\n" +
4505 "%main_lab = OpLabel\n" +
4506 "%n = OpVariable %_ptr_float Function\n" +
4507 "%3 = OpLoad %float %n\n" +
4508 "%2 = OpFSub %float %3 %float_0\n" +
4509 "OpReturn\n" +
4510 "OpFunctionEnd",
4511 2, 3),
4512 // Test case 6: Fold n * 1.0
4513 InstructionFoldingCase<uint32_t>(
4514 Header() + "%main = OpFunction %void None %void_func\n" +
4515 "%main_lab = OpLabel\n" +
4516 "%n = OpVariable %_ptr_float Function\n" +
4517 "%3 = OpLoad %float %n\n" +
4518 "%2 = OpFMul %float %3 %float_1\n" +
4519 "OpReturn\n" +
4520 "OpFunctionEnd",
4521 2, 3),
4522 // Test case 7: Fold 1.0 * n
4523 InstructionFoldingCase<uint32_t>(
4524 Header() + "%main = OpFunction %void None %void_func\n" +
4525 "%main_lab = OpLabel\n" +
4526 "%n = OpVariable %_ptr_float Function\n" +
4527 "%3 = OpLoad %float %n\n" +
4528 "%2 = OpFMul %float %float_1 %3\n" +
4529 "OpReturn\n" +
4530 "OpFunctionEnd",
4531 2, 3),
4532 // Test case 8: Fold n / 1.0
4533 InstructionFoldingCase<uint32_t>(
4534 Header() + "%main = OpFunction %void None %void_func\n" +
4535 "%main_lab = OpLabel\n" +
4536 "%n = OpVariable %_ptr_float Function\n" +
4537 "%3 = OpLoad %float %n\n" +
4538 "%2 = OpFDiv %float %3 %float_1\n" +
4539 "OpReturn\n" +
4540 "OpFunctionEnd",
4541 2, 3),
4542 // Test case 9: Fold n * 0.0
4543 InstructionFoldingCase<uint32_t>(
4544 Header() + "%main = OpFunction %void None %void_func\n" +
4545 "%main_lab = OpLabel\n" +
4546 "%n = OpVariable %_ptr_float Function\n" +
4547 "%3 = OpLoad %float %n\n" +
4548 "%2 = OpFMul %float %3 %104\n" +
4549 "OpReturn\n" +
4550 "OpFunctionEnd",
4551 2, FLOAT_0_ID),
4552 // Test case 10: Fold 0.0 * n
4553 InstructionFoldingCase<uint32_t>(
4554 Header() + "%main = OpFunction %void None %void_func\n" +
4555 "%main_lab = OpLabel\n" +
4556 "%n = OpVariable %_ptr_float Function\n" +
4557 "%3 = OpLoad %float %n\n" +
4558 "%2 = OpFMul %float %104 %3\n" +
4559 "OpReturn\n" +
4560 "OpFunctionEnd",
4561 2, FLOAT_0_ID),
4562 // Test case 11: Fold 0.0 / n
4563 InstructionFoldingCase<uint32_t>(
4564 Header() + "%main = OpFunction %void None %void_func\n" +
4565 "%main_lab = OpLabel\n" +
4566 "%n = OpVariable %_ptr_float Function\n" +
4567 "%3 = OpLoad %float %n\n" +
4568 "%2 = OpFDiv %float %104 %3\n" +
4569 "OpReturn\n" +
4570 "OpFunctionEnd",
4571 2, FLOAT_0_ID),
4572 // Test case 12: Don't fold mix(a, b, 2.0)
4573 InstructionFoldingCase<uint32_t>(
4574 Header() + "%main = OpFunction %void None %void_func\n" +
4575 "%main_lab = OpLabel\n" +
4576 "%a = OpVariable %_ptr_float Function\n" +
4577 "%b = OpVariable %_ptr_float Function\n" +
4578 "%3 = OpLoad %float %a\n" +
4579 "%4 = OpLoad %float %b\n" +
4580 "%2 = OpExtInst %float %1 FMix %3 %4 %float_2\n" +
4581 "OpReturn\n" +
4582 "OpFunctionEnd",
4583 2, 0),
4584 // Test case 13: Fold mix(a, b, 0.0)
4585 InstructionFoldingCase<uint32_t>(
4586 Header() + "%main = OpFunction %void None %void_func\n" +
4587 "%main_lab = OpLabel\n" +
4588 "%a = OpVariable %_ptr_float Function\n" +
4589 "%b = OpVariable %_ptr_float Function\n" +
4590 "%3 = OpLoad %float %a\n" +
4591 "%4 = OpLoad %float %b\n" +
4592 "%2 = OpExtInst %float %1 FMix %3 %4 %float_0\n" +
4593 "OpReturn\n" +
4594 "OpFunctionEnd",
4595 2, 3),
4596 // Test case 14: Fold mix(a, b, 1.0)
4597 InstructionFoldingCase<uint32_t>(
4598 Header() + "%main = OpFunction %void None %void_func\n" +
4599 "%main_lab = OpLabel\n" +
4600 "%a = OpVariable %_ptr_float Function\n" +
4601 "%b = OpVariable %_ptr_float Function\n" +
4602 "%3 = OpLoad %float %a\n" +
4603 "%4 = OpLoad %float %b\n" +
4604 "%2 = OpExtInst %float %1 FMix %3 %4 %float_1\n" +
4605 "OpReturn\n" +
4606 "OpFunctionEnd",
4607 2, 4),
4608 // Test case 15: Fold vector fadd with null
4609 InstructionFoldingCase<uint32_t>(
4610 Header() + "%main = OpFunction %void None %void_func\n" +
4611 "%main_lab = OpLabel\n" +
4612 "%a = OpVariable %_ptr_v2float Function\n" +
4613 "%2 = OpLoad %v2float %a\n" +
4614 "%3 = OpFAdd %v2float %2 %v2float_null\n" +
4615 "OpReturn\n" +
4616 "OpFunctionEnd",
4617 3, 2),
4618 // Test case 16: Fold vector fadd with null
4619 InstructionFoldingCase<uint32_t>(
4620 Header() + "%main = OpFunction %void None %void_func\n" +
4621 "%main_lab = OpLabel\n" +
4622 "%a = OpVariable %_ptr_v2float Function\n" +
4623 "%2 = OpLoad %v2float %a\n" +
4624 "%3 = OpFAdd %v2float %v2float_null %2\n" +
4625 "OpReturn\n" +
4626 "OpFunctionEnd",
4627 3, 2),
4628 // Test case 17: Fold vector fsub with null
4629 InstructionFoldingCase<uint32_t>(
4630 Header() + "%main = OpFunction %void None %void_func\n" +
4631 "%main_lab = OpLabel\n" +
4632 "%a = OpVariable %_ptr_v2float Function\n" +
4633 "%2 = OpLoad %v2float %a\n" +
4634 "%3 = OpFSub %v2float %2 %v2float_null\n" +
4635 "OpReturn\n" +
4636 "OpFunctionEnd",
4637 3, 2),
4638 // Test case 18: Fold 0.0(half) * n
4639 InstructionFoldingCase<uint32_t>(
4640 Header() + "%main = OpFunction %void None %void_func\n" +
4641 "%main_lab = OpLabel\n" +
4642 "%n = OpVariable %_ptr_half Function\n" +
4643 "%3 = OpLoad %half %n\n" +
4644 "%2 = OpFMul %half %108 %3\n" +
4645 "OpReturn\n" +
4646 "OpFunctionEnd",
4647 2, HALF_0_ID),
4648 // Test case 19: Don't fold 1.0(half) * n
4649 InstructionFoldingCase<uint32_t>(
4650 Header() + "%main = OpFunction %void None %void_func\n" +
4651 "%main_lab = OpLabel\n" +
4652 "%n = OpVariable %_ptr_half Function\n" +
4653 "%3 = OpLoad %half %n\n" +
4654 "%2 = OpFMul %half %half_1 %3\n" +
4655 "OpReturn\n" +
4656 "OpFunctionEnd",
4657 2, 0),
4658 // Test case 20: Don't fold 1.0 * 1.0 (half)
4659 InstructionFoldingCase<uint32_t>(
4660 Header() + "%main = OpFunction %void None %void_func\n" +
4661 "%main_lab = OpLabel\n" +
4662 "%2 = OpFMul %half %half_1 %half_1\n" +
4663 "OpReturn\n" +
4664 "OpFunctionEnd",
4665 2, 0),
4666 // Test case 21: Don't fold (0.0, 1.0) * (0.0, 1.0) (half)
4667 InstructionFoldingCase<uint32_t>(
4668 Header() + "%main = OpFunction %void None %void_func\n" +
4669 "%main_lab = OpLabel\n" +
4670 "%2 = OpFMul %v2half %half_0_1 %half_0_1\n" +
4671 "OpReturn\n" +
4672 "OpFunctionEnd",
4673 2, 0),
4674 // Test case 22: Don't fold (0.0, 1.0) dotp (0.0, 1.0) (half)
4675 InstructionFoldingCase<uint32_t>(
4676 Header() + "%main = OpFunction %void None %void_func\n" +
4677 "%main_lab = OpLabel\n" +
4678 "%2 = OpDot %half %half_0_1 %half_0_1\n" +
4679 "OpReturn\n" +
4680 "OpFunctionEnd",
4681 2, 0),
4682 // Test case 23: Don't fold 1.0(half) / 2.0(half)
4683 // We do not have to code to emulate 16-bit float operations. Just make sure we do not crash.
4684 InstructionFoldingCase<uint32_t>(
4685 Header() + "%main = OpFunction %void None %void_func\n" +
4686 "%main_lab = OpLabel\n" +
4687 "%n = OpVariable %_ptr_half Function\n" +
4688 "%3 = OpLoad %half %n\n" +
4689 "%2 = OpFDiv %half %half_1 %half_2\n" +
4690 "OpReturn\n" +
4691 "OpFunctionEnd",
4692 2, 0)
4693 ));
4694
4695 INSTANTIATE_TEST_SUITE_P(DoubleRedundantFoldingTest, GeneralInstructionFoldingTest,
4696 ::testing::Values(
4697 // Test case 0: Don't fold n + 1.0
4698 InstructionFoldingCase<uint32_t>(
4699 Header() + "%main = OpFunction %void None %void_func\n" +
4700 "%main_lab = OpLabel\n" +
4701 "%n = OpVariable %_ptr_double Function\n" +
4702 "%3 = OpLoad %double %n\n" +
4703 "%2 = OpFAdd %double %3 %double_2\n" +
4704 "OpReturn\n" +
4705 "OpFunctionEnd",
4706 2, 0),
4707 // Test case 1: Don't fold n - 1.0
4708 InstructionFoldingCase<uint32_t>(
4709 Header() + "%main = OpFunction %void None %void_func\n" +
4710 "%main_lab = OpLabel\n" +
4711 "%n = OpVariable %_ptr_double Function\n" +
4712 "%3 = OpLoad %double %n\n" +
4713 "%2 = OpFSub %double %3 %double_2\n" +
4714 "OpReturn\n" +
4715 "OpFunctionEnd",
4716 2, 0),
4717 // Test case 2: Don't fold n * 2.0
4718 InstructionFoldingCase<uint32_t>(
4719 Header() + "%main = OpFunction %void None %void_func\n" +
4720 "%main_lab = OpLabel\n" +
4721 "%n = OpVariable %_ptr_double Function\n" +
4722 "%3 = OpLoad %double %n\n" +
4723 "%2 = OpFMul %double %3 %double_2\n" +
4724 "OpReturn\n" +
4725 "OpFunctionEnd",
4726 2, 0),
4727 // Test case 3: Fold n + 0.0
4728 InstructionFoldingCase<uint32_t>(
4729 Header() + "%main = OpFunction %void None %void_func\n" +
4730 "%main_lab = OpLabel\n" +
4731 "%n = OpVariable %_ptr_double Function\n" +
4732 "%3 = OpLoad %double %n\n" +
4733 "%2 = OpFAdd %double %3 %double_0\n" +
4734 "OpReturn\n" +
4735 "OpFunctionEnd",
4736 2, 3),
4737 // Test case 4: Fold 0.0 + n
4738 InstructionFoldingCase<uint32_t>(
4739 Header() + "%main = OpFunction %void None %void_func\n" +
4740 "%main_lab = OpLabel\n" +
4741 "%n = OpVariable %_ptr_double Function\n" +
4742 "%3 = OpLoad %double %n\n" +
4743 "%2 = OpFAdd %double %double_0 %3\n" +
4744 "OpReturn\n" +
4745 "OpFunctionEnd",
4746 2, 3),
4747 // Test case 5: Fold n - 0.0
4748 InstructionFoldingCase<uint32_t>(
4749 Header() + "%main = OpFunction %void None %void_func\n" +
4750 "%main_lab = OpLabel\n" +
4751 "%n = OpVariable %_ptr_double Function\n" +
4752 "%3 = OpLoad %double %n\n" +
4753 "%2 = OpFSub %double %3 %double_0\n" +
4754 "OpReturn\n" +
4755 "OpFunctionEnd",
4756 2, 3),
4757 // Test case 6: Fold n * 1.0
4758 InstructionFoldingCase<uint32_t>(
4759 Header() + "%main = OpFunction %void None %void_func\n" +
4760 "%main_lab = OpLabel\n" +
4761 "%n = OpVariable %_ptr_double Function\n" +
4762 "%3 = OpLoad %double %n\n" +
4763 "%2 = OpFMul %double %3 %double_1\n" +
4764 "OpReturn\n" +
4765 "OpFunctionEnd",
4766 2, 3),
4767 // Test case 7: Fold 1.0 * n
4768 InstructionFoldingCase<uint32_t>(
4769 Header() + "%main = OpFunction %void None %void_func\n" +
4770 "%main_lab = OpLabel\n" +
4771 "%n = OpVariable %_ptr_double Function\n" +
4772 "%3 = OpLoad %double %n\n" +
4773 "%2 = OpFMul %double %double_1 %3\n" +
4774 "OpReturn\n" +
4775 "OpFunctionEnd",
4776 2, 3),
4777 // Test case 8: Fold n / 1.0
4778 InstructionFoldingCase<uint32_t>(
4779 Header() + "%main = OpFunction %void None %void_func\n" +
4780 "%main_lab = OpLabel\n" +
4781 "%n = OpVariable %_ptr_double Function\n" +
4782 "%3 = OpLoad %double %n\n" +
4783 "%2 = OpFDiv %double %3 %double_1\n" +
4784 "OpReturn\n" +
4785 "OpFunctionEnd",
4786 2, 3),
4787 // Test case 9: Fold n * 0.0
4788 InstructionFoldingCase<uint32_t>(
4789 Header() + "%main = OpFunction %void None %void_func\n" +
4790 "%main_lab = OpLabel\n" +
4791 "%n = OpVariable %_ptr_double Function\n" +
4792 "%3 = OpLoad %double %n\n" +
4793 "%2 = OpFMul %double %3 %105\n" +
4794 "OpReturn\n" +
4795 "OpFunctionEnd",
4796 2, DOUBLE_0_ID),
4797 // Test case 10: Fold 0.0 * n
4798 InstructionFoldingCase<uint32_t>(
4799 Header() + "%main = OpFunction %void None %void_func\n" +
4800 "%main_lab = OpLabel\n" +
4801 "%n = OpVariable %_ptr_double Function\n" +
4802 "%3 = OpLoad %double %n\n" +
4803 "%2 = OpFMul %double %105 %3\n" +
4804 "OpReturn\n" +
4805 "OpFunctionEnd",
4806 2, DOUBLE_0_ID),
4807 // Test case 11: Fold 0.0 / n
4808 InstructionFoldingCase<uint32_t>(
4809 Header() + "%main = OpFunction %void None %void_func\n" +
4810 "%main_lab = OpLabel\n" +
4811 "%n = OpVariable %_ptr_double Function\n" +
4812 "%3 = OpLoad %double %n\n" +
4813 "%2 = OpFDiv %double %105 %3\n" +
4814 "OpReturn\n" +
4815 "OpFunctionEnd",
4816 2, DOUBLE_0_ID),
4817 // Test case 12: Don't fold mix(a, b, 2.0)
4818 InstructionFoldingCase<uint32_t>(
4819 Header() + "%main = OpFunction %void None %void_func\n" +
4820 "%main_lab = OpLabel\n" +
4821 "%a = OpVariable %_ptr_double Function\n" +
4822 "%b = OpVariable %_ptr_double Function\n" +
4823 "%3 = OpLoad %double %a\n" +
4824 "%4 = OpLoad %double %b\n" +
4825 "%2 = OpExtInst %double %1 FMix %3 %4 %double_2\n" +
4826 "OpReturn\n" +
4827 "OpFunctionEnd",
4828 2, 0),
4829 // Test case 13: Fold mix(a, b, 0.0)
4830 InstructionFoldingCase<uint32_t>(
4831 Header() + "%main = OpFunction %void None %void_func\n" +
4832 "%main_lab = OpLabel\n" +
4833 "%a = OpVariable %_ptr_double Function\n" +
4834 "%b = OpVariable %_ptr_double Function\n" +
4835 "%3 = OpLoad %double %a\n" +
4836 "%4 = OpLoad %double %b\n" +
4837 "%2 = OpExtInst %double %1 FMix %3 %4 %double_0\n" +
4838 "OpReturn\n" +
4839 "OpFunctionEnd",
4840 2, 3),
4841 // Test case 14: Fold mix(a, b, 1.0)
4842 InstructionFoldingCase<uint32_t>(
4843 Header() + "%main = OpFunction %void None %void_func\n" +
4844 "%main_lab = OpLabel\n" +
4845 "%a = OpVariable %_ptr_double Function\n" +
4846 "%b = OpVariable %_ptr_double Function\n" +
4847 "%3 = OpLoad %double %a\n" +
4848 "%4 = OpLoad %double %b\n" +
4849 "%2 = OpExtInst %double %1 FMix %3 %4 %double_1\n" +
4850 "OpReturn\n" +
4851 "OpFunctionEnd",
4852 2, 4)
4853 ));
4854
4855 INSTANTIATE_TEST_SUITE_P(FloatVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
4856 ::testing::Values(
4857 // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
4858 InstructionFoldingCase<uint32_t>(
4859 Header() + "%main = OpFunction %void None %void_func\n" +
4860 "%main_lab = OpLabel\n" +
4861 "%n = OpVariable %_ptr_v4float Function\n" +
4862 "%3 = OpLoad %v4float %n\n" +
4863 "%2 = OpFMul %v4float %3 %v4float_0_0_0_1\n" +
4864 "OpReturn\n" +
4865 "OpFunctionEnd",
4866 2, 0),
4867 // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
4868 InstructionFoldingCase<uint32_t>(
4869 Header() + "%main = OpFunction %void None %void_func\n" +
4870 "%main_lab = OpLabel\n" +
4871 "%n = OpVariable %_ptr_v4float Function\n" +
4872 "%3 = OpLoad %v4float %n\n" +
4873 "%2 = OpFMul %v4float %3 %106\n" +
4874 "OpReturn\n" +
4875 "OpFunctionEnd",
4876 2, VEC4_0_ID),
4877 // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
4878 InstructionFoldingCase<uint32_t>(
4879 Header() + "%main = OpFunction %void None %void_func\n" +
4880 "%main_lab = OpLabel\n" +
4881 "%n = OpVariable %_ptr_v4float Function\n" +
4882 "%3 = OpLoad %v4float %n\n" +
4883 "%2 = OpFMul %v4float %3 %v4float_1_1_1_1\n" +
4884 "OpReturn\n" +
4885 "OpFunctionEnd",
4886 2, 3)
4887 ));
4888
4889 INSTANTIATE_TEST_SUITE_P(DoubleVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
4890 ::testing::Values(
4891 // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
4892 InstructionFoldingCase<uint32_t>(
4893 Header() + "%main = OpFunction %void None %void_func\n" +
4894 "%main_lab = OpLabel\n" +
4895 "%n = OpVariable %_ptr_v4double Function\n" +
4896 "%3 = OpLoad %v4double %n\n" +
4897 "%2 = OpFMul %v4double %3 %v4double_0_0_0_1\n" +
4898 "OpReturn\n" +
4899 "OpFunctionEnd",
4900 2, 0),
4901 // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
4902 InstructionFoldingCase<uint32_t>(
4903 Header() + "%main = OpFunction %void None %void_func\n" +
4904 "%main_lab = OpLabel\n" +
4905 "%n = OpVariable %_ptr_v4double Function\n" +
4906 "%3 = OpLoad %v4double %n\n" +
4907 "%2 = OpFMul %v4double %3 %106\n" +
4908 "OpReturn\n" +
4909 "OpFunctionEnd",
4910 2, DVEC4_0_ID),
4911 // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
4912 InstructionFoldingCase<uint32_t>(
4913 Header() + "%main = OpFunction %void None %void_func\n" +
4914 "%main_lab = OpLabel\n" +
4915 "%n = OpVariable %_ptr_v4double Function\n" +
4916 "%3 = OpLoad %v4double %n\n" +
4917 "%2 = OpFMul %v4double %3 %v4double_1_1_1_1\n" +
4918 "OpReturn\n" +
4919 "OpFunctionEnd",
4920 2, 3)
4921 ));
4922
4923 INSTANTIATE_TEST_SUITE_P(IntegerRedundantFoldingTest, GeneralInstructionFoldingTest,
4924 ::testing::Values(
4925 // Test case 0: Don't fold n + 1
4926 InstructionFoldingCase<uint32_t>(
4927 Header() + "%main = OpFunction %void None %void_func\n" +
4928 "%main_lab = OpLabel\n" +
4929 "%n = OpVariable %_ptr_uint Function\n" +
4930 "%3 = OpLoad %uint %n\n" +
4931 "%2 = OpIAdd %uint %3 %uint_1\n" +
4932 "OpReturn\n" +
4933 "OpFunctionEnd",
4934 2, 0),
4935 // Test case 1: Don't fold 1 + n
4936 InstructionFoldingCase<uint32_t>(
4937 Header() + "%main = OpFunction %void None %void_func\n" +
4938 "%main_lab = OpLabel\n" +
4939 "%n = OpVariable %_ptr_uint Function\n" +
4940 "%3 = OpLoad %uint %n\n" +
4941 "%2 = OpIAdd %uint %uint_1 %3\n" +
4942 "OpReturn\n" +
4943 "OpFunctionEnd",
4944 2, 0),
4945 // Test case 2: Fold n + 0
4946 InstructionFoldingCase<uint32_t>(
4947 Header() + "%main = OpFunction %void None %void_func\n" +
4948 "%main_lab = OpLabel\n" +
4949 "%n = OpVariable %_ptr_uint Function\n" +
4950 "%3 = OpLoad %uint %n\n" +
4951 "%2 = OpIAdd %uint %3 %uint_0\n" +
4952 "OpReturn\n" +
4953 "OpFunctionEnd",
4954 2, 3),
4955 // Test case 3: Fold 0 + n
4956 InstructionFoldingCase<uint32_t>(
4957 Header() + "%main = OpFunction %void None %void_func\n" +
4958 "%main_lab = OpLabel\n" +
4959 "%n = OpVariable %_ptr_uint Function\n" +
4960 "%3 = OpLoad %uint %n\n" +
4961 "%2 = OpIAdd %uint %uint_0 %3\n" +
4962 "OpReturn\n" +
4963 "OpFunctionEnd",
4964 2, 3),
4965 // Test case 4: Don't fold n + (1,0)
4966 InstructionFoldingCase<uint32_t>(
4967 Header() + "%main = OpFunction %void None %void_func\n" +
4968 "%main_lab = OpLabel\n" +
4969 "%n = OpVariable %_ptr_v2int Function\n" +
4970 "%3 = OpLoad %v2int %n\n" +
4971 "%2 = OpIAdd %v2int %3 %v2int_1_0\n" +
4972 "OpReturn\n" +
4973 "OpFunctionEnd",
4974 2, 0),
4975 // Test case 5: Don't fold (1,0) + n
4976 InstructionFoldingCase<uint32_t>(
4977 Header() + "%main = OpFunction %void None %void_func\n" +
4978 "%main_lab = OpLabel\n" +
4979 "%n = OpVariable %_ptr_v2int Function\n" +
4980 "%3 = OpLoad %v2int %n\n" +
4981 "%2 = OpIAdd %v2int %v2int_1_0 %3\n" +
4982 "OpReturn\n" +
4983 "OpFunctionEnd",
4984 2, 0),
4985 // Test case 6: Fold n + (0,0)
4986 InstructionFoldingCase<uint32_t>(
4987 Header() + "%main = OpFunction %void None %void_func\n" +
4988 "%main_lab = OpLabel\n" +
4989 "%n = OpVariable %_ptr_v2int Function\n" +
4990 "%3 = OpLoad %v2int %n\n" +
4991 "%2 = OpIAdd %v2int %3 %v2int_0_0\n" +
4992 "OpReturn\n" +
4993 "OpFunctionEnd",
4994 2, 3),
4995 // Test case 7: Fold (0,0) + n
4996 InstructionFoldingCase<uint32_t>(
4997 Header() + "%main = OpFunction %void None %void_func\n" +
4998 "%main_lab = OpLabel\n" +
4999 "%n = OpVariable %_ptr_v2int Function\n" +
5000 "%3 = OpLoad %v2int %n\n" +
5001 "%2 = OpIAdd %v2int %v2int_0_0 %3\n" +
5002 "OpReturn\n" +
5003 "OpFunctionEnd",
5004 2, 3),
5005 // Test case 8: Don't fold because of undefined value. Using 4294967295
5006 // means that entry is undefined. We do not expect it to ever happen, so
5007 // not worth folding.
5008 InstructionFoldingCase<uint32_t>(
5009 Header() + "%main = OpFunction %void None %void_func\n" +
5010 "%main_lab = OpLabel\n" +
5011 "%n = OpVariable %_ptr_int Function\n" +
5012 "%load = OpLoad %int %n\n" +
5013 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 4294967295 3\n" +
5014 "OpReturn\n" +
5015 "OpFunctionEnd",
5016 2, 0),
5017 // Test case 9: Don't fold because of undefined value. Using 4294967295
5018 // means that entry is undefined. We do not expect it to ever happen, so
5019 // not worth folding.
5020 InstructionFoldingCase<uint32_t>(
5021 Header() + "%main = OpFunction %void None %void_func\n" +
5022 "%main_lab = OpLabel\n" +
5023 "%n = OpVariable %_ptr_int Function\n" +
5024 "%load = OpLoad %int %n\n" +
5025 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 4294967295 \n" +
5026 "OpReturn\n" +
5027 "OpFunctionEnd",
5028 2, 0)
5029 ));
5030
5031 INSTANTIATE_TEST_SUITE_P(ClampAndCmpLHS, GeneralInstructionFoldingTest,
5032 ::testing::Values(
5033 // Test case 0: Don't Fold 0.0 < clamp(-1, 1)
5034 InstructionFoldingCase<uint32_t>(
5035 Header() + "%main = OpFunction %void None %void_func\n" +
5036 "%main_lab = OpLabel\n" +
5037 "%n = OpVariable %_ptr_float Function\n" +
5038 "%ld = OpLoad %float %n\n" +
5039 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5040 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
5041 "OpReturn\n" +
5042 "OpFunctionEnd",
5043 2, 0),
5044 // Test case 1: Don't Fold 0.0 < clamp(-1, 1)
5045 InstructionFoldingCase<uint32_t>(
5046 Header() + "%main = OpFunction %void None %void_func\n" +
5047 "%main_lab = OpLabel\n" +
5048 "%n = OpVariable %_ptr_float Function\n" +
5049 "%ld = OpLoad %float %n\n" +
5050 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5051 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
5052 "OpReturn\n" +
5053 "OpFunctionEnd",
5054 2, 0),
5055 // Test case 2: Don't Fold 0.0 <= clamp(-1, 1)
5056 InstructionFoldingCase<uint32_t>(
5057 Header() + "%main = OpFunction %void None %void_func\n" +
5058 "%main_lab = OpLabel\n" +
5059 "%n = OpVariable %_ptr_float Function\n" +
5060 "%ld = OpLoad %float %n\n" +
5061 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5062 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
5063 "OpReturn\n" +
5064 "OpFunctionEnd",
5065 2, 0),
5066 // Test case 3: Don't Fold 0.0 <= clamp(-1, 1)
5067 InstructionFoldingCase<uint32_t>(
5068 Header() + "%main = OpFunction %void None %void_func\n" +
5069 "%main_lab = OpLabel\n" +
5070 "%n = OpVariable %_ptr_float Function\n" +
5071 "%ld = OpLoad %float %n\n" +
5072 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5073 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
5074 "OpReturn\n" +
5075 "OpFunctionEnd",
5076 2, 0),
5077 // Test case 4: Don't Fold 0.0 > clamp(-1, 1)
5078 InstructionFoldingCase<uint32_t>(
5079 Header() + "%main = OpFunction %void None %void_func\n" +
5080 "%main_lab = OpLabel\n" +
5081 "%n = OpVariable %_ptr_float Function\n" +
5082 "%ld = OpLoad %float %n\n" +
5083 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5084 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
5085 "OpReturn\n" +
5086 "OpFunctionEnd",
5087 2, 0),
5088 // Test case 5: Don't Fold 0.0 > clamp(-1, 1)
5089 InstructionFoldingCase<uint32_t>(
5090 Header() + "%main = OpFunction %void None %void_func\n" +
5091 "%main_lab = OpLabel\n" +
5092 "%n = OpVariable %_ptr_float Function\n" +
5093 "%ld = OpLoad %float %n\n" +
5094 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5095 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
5096 "OpReturn\n" +
5097 "OpFunctionEnd",
5098 2, 0),
5099 // Test case 6: Don't Fold 0.0 >= clamp(-1, 1)
5100 InstructionFoldingCase<uint32_t>(
5101 Header() + "%main = OpFunction %void None %void_func\n" +
5102 "%main_lab = OpLabel\n" +
5103 "%n = OpVariable %_ptr_float Function\n" +
5104 "%ld = OpLoad %float %n\n" +
5105 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5106 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
5107 "OpReturn\n" +
5108 "OpFunctionEnd",
5109 2, 0),
5110 // Test case 7: Don't Fold 0.0 >= clamp(-1, 1)
5111 InstructionFoldingCase<uint32_t>(
5112 Header() + "%main = OpFunction %void None %void_func\n" +
5113 "%main_lab = OpLabel\n" +
5114 "%n = OpVariable %_ptr_float Function\n" +
5115 "%ld = OpLoad %float %n\n" +
5116 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5117 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
5118 "OpReturn\n" +
5119 "OpFunctionEnd",
5120 2, 0),
5121 // Test case 8: Don't Fold 0.0 < clamp(0, 1)
5122 InstructionFoldingCase<uint32_t>(
5123 Header() + "%main = OpFunction %void None %void_func\n" +
5124 "%main_lab = OpLabel\n" +
5125 "%n = OpVariable %_ptr_float Function\n" +
5126 "%ld = OpLoad %float %n\n" +
5127 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
5128 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
5129 "OpReturn\n" +
5130 "OpFunctionEnd",
5131 2, 0),
5132 // Test case 9: Don't Fold 0.0 < clamp(0, 1)
5133 InstructionFoldingCase<uint32_t>(
5134 Header() + "%main = OpFunction %void None %void_func\n" +
5135 "%main_lab = OpLabel\n" +
5136 "%n = OpVariable %_ptr_float Function\n" +
5137 "%ld = OpLoad %float %n\n" +
5138 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
5139 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
5140 "OpReturn\n" +
5141 "OpFunctionEnd",
5142 2, 0),
5143 // Test case 10: Don't Fold 0.0 > clamp(-1, 0)
5144 InstructionFoldingCase<uint32_t>(
5145 Header() + "%main = OpFunction %void None %void_func\n" +
5146 "%main_lab = OpLabel\n" +
5147 "%n = OpVariable %_ptr_float Function\n" +
5148 "%ld = OpLoad %float %n\n" +
5149 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5150 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
5151 "OpReturn\n" +
5152 "OpFunctionEnd",
5153 2, 0),
5154 // Test case 11: Don't Fold 0.0 > clamp(-1, 0)
5155 InstructionFoldingCase<uint32_t>(
5156 Header() + "%main = OpFunction %void None %void_func\n" +
5157 "%main_lab = OpLabel\n" +
5158 "%n = OpVariable %_ptr_float Function\n" +
5159 "%ld = OpLoad %float %n\n" +
5160 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5161 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
5162 "OpReturn\n" +
5163 "OpFunctionEnd",
5164 2, 0)
5165 ));
5166
5167 INSTANTIATE_TEST_SUITE_P(ClampAndCmpRHS, GeneralInstructionFoldingTest,
5168 ::testing::Values(
5169 // Test case 0: Don't Fold clamp(-1, 1) < 0.0
5170 InstructionFoldingCase<uint32_t>(
5171 Header() + "%main = OpFunction %void None %void_func\n" +
5172 "%main_lab = OpLabel\n" +
5173 "%n = OpVariable %_ptr_float Function\n" +
5174 "%ld = OpLoad %float %n\n" +
5175 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5176 "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
5177 "OpReturn\n" +
5178 "OpFunctionEnd",
5179 2, 0),
5180 // Test case 1: Don't Fold clamp(-1, 1) < 0.0
5181 InstructionFoldingCase<uint32_t>(
5182 Header() + "%main = OpFunction %void None %void_func\n" +
5183 "%main_lab = OpLabel\n" +
5184 "%n = OpVariable %_ptr_float Function\n" +
5185 "%ld = OpLoad %float %n\n" +
5186 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5187 "%2 = OpFOrdLessThan %bool %clamp %float_0\n" +
5188 "OpReturn\n" +
5189 "OpFunctionEnd",
5190 2, 0),
5191 // Test case 2: Don't Fold clamp(-1, 1) <= 0.0
5192 InstructionFoldingCase<uint32_t>(
5193 Header() + "%main = OpFunction %void None %void_func\n" +
5194 "%main_lab = OpLabel\n" +
5195 "%n = OpVariable %_ptr_float Function\n" +
5196 "%ld = OpLoad %float %n\n" +
5197 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5198 "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
5199 "OpReturn\n" +
5200 "OpFunctionEnd",
5201 2, 0),
5202 // Test case 3: Don't Fold clamp(-1, 1) <= 0.0
5203 InstructionFoldingCase<uint32_t>(
5204 Header() + "%main = OpFunction %void None %void_func\n" +
5205 "%main_lab = OpLabel\n" +
5206 "%n = OpVariable %_ptr_float Function\n" +
5207 "%ld = OpLoad %float %n\n" +
5208 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5209 "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
5210 "OpReturn\n" +
5211 "OpFunctionEnd",
5212 2, 0),
5213 // Test case 4: Don't Fold clamp(-1, 1) > 0.0
5214 InstructionFoldingCase<uint32_t>(
5215 Header() + "%main = OpFunction %void None %void_func\n" +
5216 "%main_lab = OpLabel\n" +
5217 "%n = OpVariable %_ptr_float Function\n" +
5218 "%ld = OpLoad %float %n\n" +
5219 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5220 "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
5221 "OpReturn\n" +
5222 "OpFunctionEnd",
5223 2, 0),
5224 // Test case 5: Don't Fold clamp(-1, 1) > 0.0
5225 InstructionFoldingCase<uint32_t>(
5226 Header() + "%main = OpFunction %void None %void_func\n" +
5227 "%main_lab = OpLabel\n" +
5228 "%n = OpVariable %_ptr_float Function\n" +
5229 "%ld = OpLoad %float %n\n" +
5230 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5231 "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
5232 "OpReturn\n" +
5233 "OpFunctionEnd",
5234 2, 0),
5235 // Test case 6: Don't Fold clamp(-1, 1) >= 0.0
5236 InstructionFoldingCase<uint32_t>(
5237 Header() + "%main = OpFunction %void None %void_func\n" +
5238 "%main_lab = OpLabel\n" +
5239 "%n = OpVariable %_ptr_float Function\n" +
5240 "%ld = OpLoad %float %n\n" +
5241 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5242 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_0\n" +
5243 "OpReturn\n" +
5244 "OpFunctionEnd",
5245 2, 0),
5246 // Test case 7: Don't Fold clamp(-1, 1) >= 0.0
5247 InstructionFoldingCase<uint32_t>(
5248 Header() + "%main = OpFunction %void None %void_func\n" +
5249 "%main_lab = OpLabel\n" +
5250 "%n = OpVariable %_ptr_float Function\n" +
5251 "%ld = OpLoad %float %n\n" +
5252 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5253 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
5254 "OpReturn\n" +
5255 "OpFunctionEnd",
5256 2, 0),
5257 // Test case 8: Don't Fold clamp(-1, 0) < 0.0
5258 InstructionFoldingCase<uint32_t>(
5259 Header() + "%main = OpFunction %void None %void_func\n" +
5260 "%main_lab = OpLabel\n" +
5261 "%n = OpVariable %_ptr_float Function\n" +
5262 "%ld = OpLoad %float %n\n" +
5263 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5264 "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
5265 "OpReturn\n" +
5266 "OpFunctionEnd",
5267 2, 0),
5268 // Test case 9: Don't Fold clamp(0, 1) < 1
5269 InstructionFoldingCase<uint32_t>(
5270 Header() + "%main = OpFunction %void None %void_func\n" +
5271 "%main_lab = OpLabel\n" +
5272 "%n = OpVariable %_ptr_float Function\n" +
5273 "%ld = OpLoad %float %n\n" +
5274 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
5275 "%2 = OpFOrdLessThan %bool %clamp %float_1\n" +
5276 "OpReturn\n" +
5277 "OpFunctionEnd",
5278 2, 0),
5279 // Test case 10: Don't Fold clamp(-1, 0) > -1
5280 InstructionFoldingCase<uint32_t>(
5281 Header() + "%main = OpFunction %void None %void_func\n" +
5282 "%main_lab = OpLabel\n" +
5283 "%n = OpVariable %_ptr_float Function\n" +
5284 "%ld = OpLoad %float %n\n" +
5285 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5286 "%2 = OpFUnordGreaterThan %bool %clamp %float_n1\n" +
5287 "OpReturn\n" +
5288 "OpFunctionEnd",
5289 2, 0),
5290 // Test case 11: Don't Fold clamp(-1, 0) > -1
5291 InstructionFoldingCase<uint32_t>(
5292 Header() + "%main = OpFunction %void None %void_func\n" +
5293 "%main_lab = OpLabel\n" +
5294 "%n = OpVariable %_ptr_float Function\n" +
5295 "%ld = OpLoad %float %n\n" +
5296 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5297 "%2 = OpFOrdGreaterThan %bool %clamp %float_n1\n" +
5298 "OpReturn\n" +
5299 "OpFunctionEnd",
5300 2, 0)
5301 ));
5302
5303 INSTANTIATE_TEST_SUITE_P(FToIConstantFoldingTest, IntegerInstructionFoldingTest,
5304 ::testing::Values(
5305 // Test case 0: Fold int(3.0)
5306 InstructionFoldingCase<uint32_t>(
5307 Header() + "%main = OpFunction %void None %void_func\n" +
5308 "%main_lab = OpLabel\n" +
5309 "%2 = OpConvertFToS %int %float_3\n" +
5310 "OpReturn\n" +
5311 "OpFunctionEnd",
5312 2, 3),
5313 // Test case 1: Fold uint(3.0)
5314 InstructionFoldingCase<uint32_t>(
5315 Header() + "%main = OpFunction %void None %void_func\n" +
5316 "%main_lab = OpLabel\n" +
5317 "%2 = OpConvertFToU %int %float_3\n" +
5318 "OpReturn\n" +
5319 "OpFunctionEnd",
5320 2, 3)
5321 ));
5322
5323 INSTANTIATE_TEST_SUITE_P(IToFConstantFoldingTest, FloatInstructionFoldingTest,
5324 ::testing::Values(
5325 // Test case 0: Fold float(3)
5326 InstructionFoldingCase<float>(
5327 Header() + "%main = OpFunction %void None %void_func\n" +
5328 "%main_lab = OpLabel\n" +
5329 "%2 = OpConvertSToF %float %int_3\n" +
5330 "OpReturn\n" +
5331 "OpFunctionEnd",
5332 2, 3.0),
5333 // Test case 1: Fold float(3u)
5334 InstructionFoldingCase<float>(
5335 Header() + "%main = OpFunction %void None %void_func\n" +
5336 "%main_lab = OpLabel\n" +
5337 "%2 = OpConvertUToF %float %uint_3\n" +
5338 "OpReturn\n" +
5339 "OpFunctionEnd",
5340 2, 3.0)
5341 ));
5342 // clang-format on
5343
5344 using ToNegateFoldingTest =
5345 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
5346
TEST_P(ToNegateFoldingTest,Case)5347 TEST_P(ToNegateFoldingTest, Case) {
5348 const auto& tc = GetParam();
5349
5350 std::unique_ptr<IRContext> context;
5351 Instruction* inst;
5352 std::tie(context, inst) =
5353 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
5354
5355 EXPECT_TRUE((inst == nullptr) == (tc.expected_result == 0));
5356 if (inst != nullptr) {
5357 EXPECT_EQ(inst->opcode(), spv::Op::OpFNegate);
5358 EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
5359 }
5360 }
5361
5362 // clang-format off
5363 INSTANTIATE_TEST_SUITE_P(FloatRedundantSubFoldingTest, ToNegateFoldingTest,
5364 ::testing::Values(
5365 // Test case 0: Don't fold 1.0 - n
5366 InstructionFoldingCase<uint32_t>(
5367 Header() + "%main = OpFunction %void None %void_func\n" +
5368 "%main_lab = OpLabel\n" +
5369 "%n = OpVariable %_ptr_float Function\n" +
5370 "%3 = OpLoad %float %n\n" +
5371 "%2 = OpFSub %float %float_1 %3\n" +
5372 "OpReturn\n" +
5373 "OpFunctionEnd",
5374 2, 0),
5375 // Test case 1: Fold 0.0 - n
5376 InstructionFoldingCase<uint32_t>(
5377 Header() + "%main = OpFunction %void None %void_func\n" +
5378 "%main_lab = OpLabel\n" +
5379 "%n = OpVariable %_ptr_float Function\n" +
5380 "%3 = OpLoad %float %n\n" +
5381 "%2 = OpFSub %float %float_0 %3\n" +
5382 "OpReturn\n" +
5383 "OpFunctionEnd",
5384 2, 3),
5385 // Test case 2: Don't fold (0,0,0,1) - n
5386 InstructionFoldingCase<uint32_t>(
5387 Header() + "%main = OpFunction %void None %void_func\n" +
5388 "%main_lab = OpLabel\n" +
5389 "%n = OpVariable %_ptr_v4float Function\n" +
5390 "%3 = OpLoad %v4float %n\n" +
5391 "%2 = OpFSub %v4float %v4float_0_0_0_1 %3\n" +
5392 "OpReturn\n" +
5393 "OpFunctionEnd",
5394 2, 0),
5395 // Test case 3: Fold (0,0,0,0) - n
5396 InstructionFoldingCase<uint32_t>(
5397 Header() + "%main = OpFunction %void None %void_func\n" +
5398 "%main_lab = OpLabel\n" +
5399 "%n = OpVariable %_ptr_v4float Function\n" +
5400 "%3 = OpLoad %v4float %n\n" +
5401 "%2 = OpFSub %v4float %v4float_0_0_0_0 %3\n" +
5402 "OpReturn\n" +
5403 "OpFunctionEnd",
5404 2, 3)
5405 ));
5406
5407 INSTANTIATE_TEST_SUITE_P(DoubleRedundantSubFoldingTest, ToNegateFoldingTest,
5408 ::testing::Values(
5409 // Test case 0: Don't fold 1.0 - n
5410 InstructionFoldingCase<uint32_t>(
5411 Header() + "%main = OpFunction %void None %void_func\n" +
5412 "%main_lab = OpLabel\n" +
5413 "%n = OpVariable %_ptr_double Function\n" +
5414 "%3 = OpLoad %double %n\n" +
5415 "%2 = OpFSub %double %double_1 %3\n" +
5416 "OpReturn\n" +
5417 "OpFunctionEnd",
5418 2, 0),
5419 // Test case 1: Fold 0.0 - n
5420 InstructionFoldingCase<uint32_t>(
5421 Header() + "%main = OpFunction %void None %void_func\n" +
5422 "%main_lab = OpLabel\n" +
5423 "%n = OpVariable %_ptr_double Function\n" +
5424 "%3 = OpLoad %double %n\n" +
5425 "%2 = OpFSub %double %double_0 %3\n" +
5426 "OpReturn\n" +
5427 "OpFunctionEnd",
5428 2, 3),
5429 // Test case 2: Don't fold (0,0,0,1) - n
5430 InstructionFoldingCase<uint32_t>(
5431 Header() + "%main = OpFunction %void None %void_func\n" +
5432 "%main_lab = OpLabel\n" +
5433 "%n = OpVariable %_ptr_v4double Function\n" +
5434 "%3 = OpLoad %v4double %n\n" +
5435 "%2 = OpFSub %v4double %v4double_0_0_0_1 %3\n" +
5436 "OpReturn\n" +
5437 "OpFunctionEnd",
5438 2, 0),
5439 // Test case 3: Fold (0,0,0,0) - n
5440 InstructionFoldingCase<uint32_t>(
5441 Header() + "%main = OpFunction %void None %void_func\n" +
5442 "%main_lab = OpLabel\n" +
5443 "%n = OpVariable %_ptr_v4double Function\n" +
5444 "%3 = OpLoad %v4double %n\n" +
5445 "%2 = OpFSub %v4double %v4double_0_0_0_0 %3\n" +
5446 "OpReturn\n" +
5447 "OpFunctionEnd",
5448 2, 3)
5449 ));
5450
5451 using MatchingInstructionFoldingTest =
5452 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
5453
TEST_P(MatchingInstructionFoldingTest,Case)5454 TEST_P(MatchingInstructionFoldingTest, Case) {
5455 const auto& tc = GetParam();
5456
5457 std::unique_ptr<IRContext> context;
5458 Instruction* inst;
5459 std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
5460
5461 EXPECT_EQ(inst != nullptr, tc.expected_result);
5462 if (inst != nullptr) {
5463 Match(tc.test_body, context.get());
5464 }
5465 }
5466
5467 INSTANTIATE_TEST_SUITE_P(RedundantIntegerMatching, MatchingInstructionFoldingTest,
5468 ::testing::Values(
5469 // Test case 0: Fold 0 + n (change sign)
5470 InstructionFoldingCase<bool>(
5471 Header() +
5472 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
5473 "; CHECK: %2 = OpBitcast [[uint]] %3\n" +
5474 "%main = OpFunction %void None %void_func\n" +
5475 "%main_lab = OpLabel\n" +
5476 "%n = OpVariable %_ptr_int Function\n" +
5477 "%3 = OpLoad %uint %n\n" +
5478 "%2 = OpIAdd %uint %int_0 %3\n" +
5479 "OpReturn\n" +
5480 "OpFunctionEnd\n",
5481 2, true),
5482 // Test case 0: Fold 0 + n (change sign)
5483 InstructionFoldingCase<bool>(
5484 Header() +
5485 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5486 "; CHECK: %2 = OpBitcast [[int]] %3\n" +
5487 "%main = OpFunction %void None %void_func\n" +
5488 "%main_lab = OpLabel\n" +
5489 "%n = OpVariable %_ptr_int Function\n" +
5490 "%3 = OpLoad %int %n\n" +
5491 "%2 = OpIAdd %int %uint_0 %3\n" +
5492 "OpReturn\n" +
5493 "OpFunctionEnd\n",
5494 2, true)
5495 ));
5496
5497 INSTANTIATE_TEST_SUITE_P(MergeNegateTest, MatchingInstructionFoldingTest,
5498 ::testing::Values(
5499 // Test case 0: fold consecutive fnegate
5500 // -(-x) = x
5501 InstructionFoldingCase<bool>(
5502 Header() +
5503 "; CHECK: [[ld:%\\w+]] = OpLoad [[float:%\\w+]]\n" +
5504 "; CHECK: %4 = OpCopyObject [[float]] [[ld]]\n" +
5505 "%main = OpFunction %void None %void_func\n" +
5506 "%main_lab = OpLabel\n" +
5507 "%var = OpVariable %_ptr_float Function\n" +
5508 "%2 = OpLoad %float %var\n" +
5509 "%3 = OpFNegate %float %2\n" +
5510 "%4 = OpFNegate %float %3\n" +
5511 "OpReturn\n" +
5512 "OpFunctionEnd",
5513 4, true),
5514 // Test case 1: fold fnegate(fmul with const).
5515 // -(x * 2.0) = x * -2.0
5516 InstructionFoldingCase<bool>(
5517 Header() +
5518 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5519 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5520 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5521 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
5522 "%main = OpFunction %void None %void_func\n" +
5523 "%main_lab = OpLabel\n" +
5524 "%var = OpVariable %_ptr_float Function\n" +
5525 "%2 = OpLoad %float %var\n" +
5526 "%3 = OpFMul %float %2 %float_2\n" +
5527 "%4 = OpFNegate %float %3\n" +
5528 "OpReturn\n" +
5529 "OpFunctionEnd",
5530 4, true),
5531 // Test case 2: fold fnegate(fmul with const).
5532 // -(2.0 * x) = x * 2.0
5533 InstructionFoldingCase<bool>(
5534 Header() +
5535 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5536 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5537 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5538 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
5539 "%main = OpFunction %void None %void_func\n" +
5540 "%main_lab = OpLabel\n" +
5541 "%var = OpVariable %_ptr_float Function\n" +
5542 "%2 = OpLoad %float %var\n" +
5543 "%3 = OpFMul %float %float_2 %2\n" +
5544 "%4 = OpFNegate %float %3\n" +
5545 "OpReturn\n" +
5546 "OpFunctionEnd",
5547 4, true),
5548 // Test case 3: fold fnegate(fdiv with const).
5549 // -(x / 2.0) = x * -0.5
5550 InstructionFoldingCase<bool>(
5551 Header() +
5552 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5553 "; CHECK: [[float_n0p5:%\\w+]] = OpConstant [[float]] -0.5\n" +
5554 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5555 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n0p5]]\n" +
5556 "%main = OpFunction %void None %void_func\n" +
5557 "%main_lab = OpLabel\n" +
5558 "%var = OpVariable %_ptr_float Function\n" +
5559 "%2 = OpLoad %float %var\n" +
5560 "%3 = OpFDiv %float %2 %float_2\n" +
5561 "%4 = OpFNegate %float %3\n" +
5562 "OpReturn\n" +
5563 "OpFunctionEnd",
5564 4, true),
5565 // Test case 4: fold fnegate(fdiv with const).
5566 // -(2.0 / x) = -2.0 / x
5567 InstructionFoldingCase<bool>(
5568 Header() +
5569 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5570 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5571 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5572 "; CHECK: %4 = OpFDiv [[float]] [[float_n2]] [[ld]]\n" +
5573 "%main = OpFunction %void None %void_func\n" +
5574 "%main_lab = OpLabel\n" +
5575 "%var = OpVariable %_ptr_float Function\n" +
5576 "%2 = OpLoad %float %var\n" +
5577 "%3 = OpFDiv %float %float_2 %2\n" +
5578 "%4 = OpFNegate %float %3\n" +
5579 "OpReturn\n" +
5580 "OpFunctionEnd",
5581 4, true),
5582 // Test case 5: fold fnegate(fadd with const).
5583 // -(2.0 + x) = -2.0 - x
5584 InstructionFoldingCase<bool>(
5585 Header() +
5586 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5587 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5588 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5589 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
5590 "%main = OpFunction %void None %void_func\n" +
5591 "%main_lab = OpLabel\n" +
5592 "%var = OpVariable %_ptr_float Function\n" +
5593 "%2 = OpLoad %float %var\n" +
5594 "%3 = OpFAdd %float %float_2 %2\n" +
5595 "%4 = OpFNegate %float %3\n" +
5596 "OpReturn\n" +
5597 "OpFunctionEnd",
5598 4, true),
5599 // Test case 6: fold fnegate(fadd with const).
5600 // -(x + 2.0) = -2.0 - x
5601 InstructionFoldingCase<bool>(
5602 Header() +
5603 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5604 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5605 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5606 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
5607 "%main = OpFunction %void None %void_func\n" +
5608 "%main_lab = OpLabel\n" +
5609 "%var = OpVariable %_ptr_float Function\n" +
5610 "%2 = OpLoad %float %var\n" +
5611 "%3 = OpFAdd %float %2 %float_2\n" +
5612 "%4 = OpFNegate %float %3\n" +
5613 "OpReturn\n" +
5614 "OpFunctionEnd",
5615 4, true),
5616 // Test case 7: fold fnegate(fsub with const).
5617 // -(2.0 - x) = x - 2.0
5618 InstructionFoldingCase<bool>(
5619 Header() +
5620 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5621 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5622 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5623 "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_2]]\n" +
5624 "%main = OpFunction %void None %void_func\n" +
5625 "%main_lab = OpLabel\n" +
5626 "%var = OpVariable %_ptr_float Function\n" +
5627 "%2 = OpLoad %float %var\n" +
5628 "%3 = OpFSub %float %float_2 %2\n" +
5629 "%4 = OpFNegate %float %3\n" +
5630 "OpReturn\n" +
5631 "OpFunctionEnd",
5632 4, true),
5633 // Test case 8: fold fnegate(fsub with const).
5634 // -(x - 2.0) = 2.0 - x
5635 InstructionFoldingCase<bool>(
5636 Header() +
5637 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5638 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5639 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5640 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
5641 "%main = OpFunction %void None %void_func\n" +
5642 "%main_lab = OpLabel\n" +
5643 "%var = OpVariable %_ptr_float Function\n" +
5644 "%2 = OpLoad %float %var\n" +
5645 "%3 = OpFSub %float %2 %float_2\n" +
5646 "%4 = OpFNegate %float %3\n" +
5647 "OpReturn\n" +
5648 "OpFunctionEnd",
5649 4, true),
5650 // Test case 9: fold consecutive snegate
5651 // -(-x) = x
5652 InstructionFoldingCase<bool>(
5653 Header() +
5654 "; CHECK: [[ld:%\\w+]] = OpLoad [[int:%\\w+]]\n" +
5655 "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
5656 "%main = OpFunction %void None %void_func\n" +
5657 "%main_lab = OpLabel\n" +
5658 "%var = OpVariable %_ptr_int Function\n" +
5659 "%2 = OpLoad %int %var\n" +
5660 "%3 = OpSNegate %int %2\n" +
5661 "%4 = OpSNegate %int %3\n" +
5662 "OpReturn\n" +
5663 "OpFunctionEnd",
5664 4, true),
5665 // Test case 10: fold consecutive vector negate
5666 // -(-x) = x
5667 InstructionFoldingCase<bool>(
5668 Header() +
5669 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float:%\\w+]]\n" +
5670 "; CHECK: %4 = OpCopyObject [[v2float]] [[ld]]\n" +
5671 "%main = OpFunction %void None %void_func\n" +
5672 "%main_lab = OpLabel\n" +
5673 "%var = OpVariable %_ptr_v2float Function\n" +
5674 "%2 = OpLoad %v2float %var\n" +
5675 "%3 = OpFNegate %v2float %2\n" +
5676 "%4 = OpFNegate %v2float %3\n" +
5677 "OpReturn\n" +
5678 "OpFunctionEnd",
5679 4, true),
5680 // Test case 11: fold snegate(iadd with const).
5681 // -(2 + x) = -2 - x
5682 InstructionFoldingCase<bool>(
5683 Header() +
5684 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5685 "; CHECK: OpConstant [[int]] -2147483648\n" +
5686 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
5687 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5688 "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
5689 "%main = OpFunction %void None %void_func\n" +
5690 "%main_lab = OpLabel\n" +
5691 "%var = OpVariable %_ptr_int Function\n" +
5692 "%2 = OpLoad %int %var\n" +
5693 "%3 = OpIAdd %int %int_2 %2\n" +
5694 "%4 = OpSNegate %int %3\n" +
5695 "OpReturn\n" +
5696 "OpFunctionEnd",
5697 4, true),
5698 // Test case 12: fold snegate(iadd with const).
5699 // -(x + 2) = -2 - x
5700 InstructionFoldingCase<bool>(
5701 Header() +
5702 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5703 "; CHECK: OpConstant [[int]] -2147483648\n" +
5704 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
5705 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5706 "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
5707 "%main = OpFunction %void None %void_func\n" +
5708 "%main_lab = OpLabel\n" +
5709 "%var = OpVariable %_ptr_int Function\n" +
5710 "%2 = OpLoad %int %var\n" +
5711 "%3 = OpIAdd %int %2 %int_2\n" +
5712 "%4 = OpSNegate %int %3\n" +
5713 "OpReturn\n" +
5714 "OpFunctionEnd",
5715 4, true),
5716 // Test case 13: fold snegate(isub with const).
5717 // -(2 - x) = x - 2
5718 InstructionFoldingCase<bool>(
5719 Header() +
5720 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5721 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
5722 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5723 "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_2]]\n" +
5724 "%main = OpFunction %void None %void_func\n" +
5725 "%main_lab = OpLabel\n" +
5726 "%var = OpVariable %_ptr_int Function\n" +
5727 "%2 = OpLoad %int %var\n" +
5728 "%3 = OpISub %int %int_2 %2\n" +
5729 "%4 = OpSNegate %int %3\n" +
5730 "OpReturn\n" +
5731 "OpFunctionEnd",
5732 4, true),
5733 // Test case 14: fold snegate(isub with const).
5734 // -(x - 2) = 2 - x
5735 InstructionFoldingCase<bool>(
5736 Header() +
5737 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5738 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
5739 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5740 "; CHECK: %4 = OpISub [[int]] [[int_2]] [[ld]]\n" +
5741 "%main = OpFunction %void None %void_func\n" +
5742 "%main_lab = OpLabel\n" +
5743 "%var = OpVariable %_ptr_int Function\n" +
5744 "%2 = OpLoad %int %var\n" +
5745 "%3 = OpISub %int %2 %int_2\n" +
5746 "%4 = OpSNegate %int %3\n" +
5747 "OpReturn\n" +
5748 "OpFunctionEnd",
5749 4, true),
5750 // Test case 15: fold snegate(iadd with const).
5751 // -(x + 2) = -2 - x
5752 InstructionFoldingCase<bool>(
5753 Header() +
5754 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5755 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
5756 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5757 "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
5758 "%main = OpFunction %void None %void_func\n" +
5759 "%main_lab = OpLabel\n" +
5760 "%var = OpVariable %_ptr_long Function\n" +
5761 "%2 = OpLoad %long %var\n" +
5762 "%3 = OpIAdd %long %2 %long_2\n" +
5763 "%4 = OpSNegate %long %3\n" +
5764 "OpReturn\n" +
5765 "OpFunctionEnd",
5766 4, true),
5767 // Test case 16: fold snegate(isub with const).
5768 // -(2 - x) = x - 2
5769 InstructionFoldingCase<bool>(
5770 Header() +
5771 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5772 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5773 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5774 "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_2]]\n" +
5775 "%main = OpFunction %void None %void_func\n" +
5776 "%main_lab = OpLabel\n" +
5777 "%var = OpVariable %_ptr_long Function\n" +
5778 "%2 = OpLoad %long %var\n" +
5779 "%3 = OpISub %long %long_2 %2\n" +
5780 "%4 = OpSNegate %long %3\n" +
5781 "OpReturn\n" +
5782 "OpFunctionEnd",
5783 4, true),
5784 // Test case 17: fold snegate(isub with const).
5785 // -(x - 2) = 2 - x
5786 InstructionFoldingCase<bool>(
5787 Header() +
5788 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5789 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5790 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5791 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
5792 "%main = OpFunction %void None %void_func\n" +
5793 "%main_lab = OpLabel\n" +
5794 "%var = OpVariable %_ptr_long Function\n" +
5795 "%2 = OpLoad %long %var\n" +
5796 "%3 = OpISub %long %2 %long_2\n" +
5797 "%4 = OpSNegate %long %3\n" +
5798 "OpReturn\n" +
5799 "OpFunctionEnd",
5800 4, true),
5801 // Test case 18: fold -vec4(-1.0, 2.0, 1.0, 3.0)
5802 InstructionFoldingCase<bool>(
5803 Header() +
5804 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5805 "; CHECK: [[v4float:%\\w+]] = OpTypeVector [[float]] 4{{[[:space:]]}}\n" +
5806 "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1{{[[:space:]]}}\n" +
5807 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1{{[[:space:]]}}\n" +
5808 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5809 "; CHECK: [[float_n3:%\\w+]] = OpConstant [[float]] -3{{[[:space:]]}}\n" +
5810 "; CHECK: [[v4float_1_n2_n1_n3:%\\w+]] = OpConstantComposite [[v4float]] [[float_1]] [[float_n2]] [[float_n1]] [[float_n3]]\n" +
5811 "; CHECK: %2 = OpCopyObject [[v4float]] [[v4float_1_n2_n1_n3]]\n" +
5812 "%main = OpFunction %void None %void_func\n" +
5813 "%main_lab = OpLabel\n" +
5814 "%2 = OpFNegate %v4float %v4float_n1_2_1_3\n" +
5815 "OpReturn\n" +
5816 "OpFunctionEnd",
5817 2, true),
5818 // Test case 19: fold vector fnegate with null
5819 InstructionFoldingCase<bool>(
5820 Header() +
5821 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5822 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
5823 "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" +
5824 "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_n0]] [[double_n0]]\n" +
5825 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
5826 "%main = OpFunction %void None %void_func\n" +
5827 "%main_lab = OpLabel\n" +
5828 "%2 = OpFNegate %v2double %v2double_null\n" +
5829 "OpReturn\n" +
5830 "OpFunctionEnd",
5831 2, true)
5832 ));
5833
5834 INSTANTIATE_TEST_SUITE_P(ReciprocalFDivTest, MatchingInstructionFoldingTest,
5835 ::testing::Values(
5836 // Test case 0: scalar reicprocal
5837 // x / 0.5 = x * 2.0
5838 InstructionFoldingCase<bool>(
5839 Header() +
5840 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5841 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5842 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5843 "; CHECK: %3 = OpFMul [[float]] [[ld]] [[float_2]]\n" +
5844 "%main = OpFunction %void None %void_func\n" +
5845 "%main_lab = OpLabel\n" +
5846 "%var = OpVariable %_ptr_float Function\n" +
5847 "%2 = OpLoad %float %var\n" +
5848 "%3 = OpFDiv %float %2 %float_0p5\n" +
5849 "OpReturn\n" +
5850 "OpFunctionEnd\n",
5851 3, true),
5852 // Test case 1: Unfoldable
5853 InstructionFoldingCase<bool>(
5854 Header() +
5855 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5856 "; CHECK: [[float_0:%\\w+]] = OpConstant [[float]] 0\n" +
5857 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5858 "; CHECK: %3 = OpFDiv [[float]] [[ld]] [[float_0]]\n" +
5859 "%main = OpFunction %void None %void_func\n" +
5860 "%main_lab = OpLabel\n" +
5861 "%var = OpVariable %_ptr_float Function\n" +
5862 "%2 = OpLoad %float %var\n" +
5863 "%3 = OpFDiv %float %2 %104\n" +
5864 "OpReturn\n" +
5865 "OpFunctionEnd\n",
5866 3, false),
5867 // Test case 2: Vector reciprocal
5868 // x / {2.0, 0.5} = x * {0.5, 2.0}
5869 InstructionFoldingCase<bool>(
5870 Header() +
5871 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5872 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
5873 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5874 "; CHECK: [[float_0p5:%\\w+]] = OpConstant [[float]] 0.5\n" +
5875 "; CHECK: [[v2float_0p5_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_0p5]] [[float_2]]\n" +
5876 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
5877 "; CHECK: %3 = OpFMul [[v2float]] [[ld]] [[v2float_0p5_2]]\n" +
5878 "%main = OpFunction %void None %void_func\n" +
5879 "%main_lab = OpLabel\n" +
5880 "%var = OpVariable %_ptr_v2float Function\n" +
5881 "%2 = OpLoad %v2float %var\n" +
5882 "%3 = OpFDiv %v2float %2 %v2float_2_0p5\n" +
5883 "OpReturn\n" +
5884 "OpFunctionEnd\n",
5885 3, true),
5886 // Test case 3: double reciprocal
5887 // x / 2.0 = x * 0.5
5888 InstructionFoldingCase<bool>(
5889 Header() +
5890 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5891 "; CHECK: [[double_0p5:%\\w+]] = OpConstant [[double]] 0.5\n" +
5892 "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
5893 "; CHECK: %3 = OpFMul [[double]] [[ld]] [[double_0p5]]\n" +
5894 "%main = OpFunction %void None %void_func\n" +
5895 "%main_lab = OpLabel\n" +
5896 "%var = OpVariable %_ptr_double Function\n" +
5897 "%2 = OpLoad %double %var\n" +
5898 "%3 = OpFDiv %double %2 %double_2\n" +
5899 "OpReturn\n" +
5900 "OpFunctionEnd\n",
5901 3, true),
5902 // Test case 4: don't fold x / 0.
5903 InstructionFoldingCase<bool>(
5904 Header() +
5905 "%main = OpFunction %void None %void_func\n" +
5906 "%main_lab = OpLabel\n" +
5907 "%var = OpVariable %_ptr_v2float Function\n" +
5908 "%2 = OpLoad %v2float %var\n" +
5909 "%3 = OpFDiv %v2float %2 %v2float_null\n" +
5910 "OpReturn\n" +
5911 "OpFunctionEnd\n",
5912 3, false)
5913 ));
5914
5915 INSTANTIATE_TEST_SUITE_P(MergeMulTest, MatchingInstructionFoldingTest,
5916 ::testing::Values(
5917 // Test case 0: fold consecutive fmuls
5918 // (x * 3.0) * 2.0 = x * 6.0
5919 InstructionFoldingCase<bool>(
5920 Header() +
5921 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5922 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5923 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5924 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
5925 "%main = OpFunction %void None %void_func\n" +
5926 "%main_lab = OpLabel\n" +
5927 "%var = OpVariable %_ptr_float Function\n" +
5928 "%2 = OpLoad %float %var\n" +
5929 "%3 = OpFMul %float %2 %float_3\n" +
5930 "%4 = OpFMul %float %3 %float_2\n" +
5931 "OpReturn\n" +
5932 "OpFunctionEnd\n",
5933 4, true),
5934 // Test case 1: fold consecutive fmuls
5935 // 2.0 * (x * 3.0) = x * 6.0
5936 InstructionFoldingCase<bool>(
5937 Header() +
5938 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5939 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5940 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5941 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
5942 "%main = OpFunction %void None %void_func\n" +
5943 "%main_lab = OpLabel\n" +
5944 "%var = OpVariable %_ptr_float Function\n" +
5945 "%2 = OpLoad %float %var\n" +
5946 "%3 = OpFMul %float %2 %float_3\n" +
5947 "%4 = OpFMul %float %float_2 %3\n" +
5948 "OpReturn\n" +
5949 "OpFunctionEnd\n",
5950 4, true),
5951 // Test case 2: fold consecutive fmuls
5952 // (3.0 * x) * 2.0 = x * 6.0
5953 InstructionFoldingCase<bool>(
5954 Header() +
5955 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5956 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5957 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5958 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
5959 "%main = OpFunction %void None %void_func\n" +
5960 "%main_lab = OpLabel\n" +
5961 "%var = OpVariable %_ptr_float Function\n" +
5962 "%2 = OpLoad %float %var\n" +
5963 "%3 = OpFMul %float %float_3 %2\n" +
5964 "%4 = OpFMul %float %float_2 %3\n" +
5965 "OpReturn\n" +
5966 "OpFunctionEnd\n",
5967 4, true),
5968 // Test case 3: fold vector fmul
5969 InstructionFoldingCase<bool>(
5970 Header() +
5971 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5972 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
5973 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5974 "; CHECK: [[v2float_6_6:%\\w+]] = OpConstantComposite [[v2float]] [[float_6]] [[float_6]]\n" +
5975 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
5976 "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_6_6]]\n" +
5977 "%main = OpFunction %void None %void_func\n" +
5978 "%main_lab = OpLabel\n" +
5979 "%var = OpVariable %_ptr_v2float Function\n" +
5980 "%2 = OpLoad %v2float %var\n" +
5981 "%3 = OpFMul %v2float %2 %v2float_2_3\n" +
5982 "%4 = OpFMul %v2float %3 %v2float_3_2\n" +
5983 "OpReturn\n" +
5984 "OpFunctionEnd\n",
5985 4, true),
5986 // Test case 4: fold double fmuls
5987 // (x * 3.0) * 2.0 = x * 6.0
5988 InstructionFoldingCase<bool>(
5989 Header() +
5990 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5991 "; CHECK: [[double_6:%\\w+]] = OpConstant [[double]] 6\n" +
5992 "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
5993 "; CHECK: %4 = OpFMul [[double]] [[ld]] [[double_6]]\n" +
5994 "%main = OpFunction %void None %void_func\n" +
5995 "%main_lab = OpLabel\n" +
5996 "%var = OpVariable %_ptr_double Function\n" +
5997 "%2 = OpLoad %double %var\n" +
5998 "%3 = OpFMul %double %2 %double_3\n" +
5999 "%4 = OpFMul %double %3 %double_2\n" +
6000 "OpReturn\n" +
6001 "OpFunctionEnd\n",
6002 4, true),
6003 // Test case 5: fold 32 bit imuls
6004 // (x * 3) * 2 = x * 6
6005 InstructionFoldingCase<bool>(
6006 Header() +
6007 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6008 "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
6009 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6010 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_6]]\n" +
6011 "%main = OpFunction %void None %void_func\n" +
6012 "%main_lab = OpLabel\n" +
6013 "%var = OpVariable %_ptr_int Function\n" +
6014 "%2 = OpLoad %int %var\n" +
6015 "%3 = OpIMul %int %2 %int_3\n" +
6016 "%4 = OpIMul %int %3 %int_2\n" +
6017 "OpReturn\n" +
6018 "OpFunctionEnd\n",
6019 4, true),
6020 // Test case 6: fold 64 bit imuls
6021 // (x * 3) * 2 = x * 6
6022 InstructionFoldingCase<bool>(
6023 Header() +
6024 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6025 "; CHECK: [[long_6:%\\w+]] = OpConstant [[long]] 6\n" +
6026 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6027 "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_6]]\n" +
6028 "%main = OpFunction %void None %void_func\n" +
6029 "%main_lab = OpLabel\n" +
6030 "%var = OpVariable %_ptr_long Function\n" +
6031 "%2 = OpLoad %long %var\n" +
6032 "%3 = OpIMul %long %2 %long_3\n" +
6033 "%4 = OpIMul %long %3 %long_2\n" +
6034 "OpReturn\n" +
6035 "OpFunctionEnd\n",
6036 4, true),
6037 // Test case 7: merge vector integer mults
6038 InstructionFoldingCase<bool>(
6039 Header() +
6040 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6041 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
6042 "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
6043 "; CHECK: [[v2int_6_6:%\\w+]] = OpConstantComposite [[v2int]] [[int_6]] [[int_6]]\n" +
6044 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
6045 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_6_6]]\n" +
6046 "%main = OpFunction %void None %void_func\n" +
6047 "%main_lab = OpLabel\n" +
6048 "%var = OpVariable %_ptr_v2int Function\n" +
6049 "%2 = OpLoad %v2int %var\n" +
6050 "%3 = OpIMul %v2int %2 %v2int_2_3\n" +
6051 "%4 = OpIMul %v2int %3 %v2int_3_2\n" +
6052 "OpReturn\n" +
6053 "OpFunctionEnd\n",
6054 4, true),
6055 // Test case 8: merge fmul of fdiv
6056 // 2.0 * (2.0 / x) = 4.0 / x
6057 InstructionFoldingCase<bool>(
6058 Header() +
6059 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6060 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
6061 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6062 "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
6063 "%main = OpFunction %void None %void_func\n" +
6064 "%main_lab = OpLabel\n" +
6065 "%var = OpVariable %_ptr_float Function\n" +
6066 "%2 = OpLoad %float %var\n" +
6067 "%3 = OpFDiv %float %float_2 %2\n" +
6068 "%4 = OpFMul %float %float_2 %3\n" +
6069 "OpReturn\n" +
6070 "OpFunctionEnd\n",
6071 4, true),
6072 // Test case 9: merge fmul of fdiv
6073 // (2.0 / x) * 2.0 = 4.0 / x
6074 InstructionFoldingCase<bool>(
6075 Header() +
6076 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6077 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
6078 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6079 "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
6080 "%main = OpFunction %void None %void_func\n" +
6081 "%main_lab = OpLabel\n" +
6082 "%var = OpVariable %_ptr_float Function\n" +
6083 "%2 = OpLoad %float %var\n" +
6084 "%3 = OpFDiv %float %float_2 %2\n" +
6085 "%4 = OpFMul %float %3 %float_2\n" +
6086 "OpReturn\n" +
6087 "OpFunctionEnd\n",
6088 4, true),
6089 // Test case 10: Do not merge imul of sdiv
6090 // 4 * (x / 2)
6091 InstructionFoldingCase<bool>(
6092 Header() +
6093 "%main = OpFunction %void None %void_func\n" +
6094 "%main_lab = OpLabel\n" +
6095 "%var = OpVariable %_ptr_int Function\n" +
6096 "%2 = OpLoad %int %var\n" +
6097 "%3 = OpSDiv %int %2 %int_2\n" +
6098 "%4 = OpIMul %int %int_4 %3\n" +
6099 "OpReturn\n" +
6100 "OpFunctionEnd\n",
6101 4, false),
6102 // Test case 11: Do not merge imul of sdiv
6103 // (x / 2) * 4
6104 InstructionFoldingCase<bool>(
6105 Header() +
6106 "%main = OpFunction %void None %void_func\n" +
6107 "%main_lab = OpLabel\n" +
6108 "%var = OpVariable %_ptr_int Function\n" +
6109 "%2 = OpLoad %int %var\n" +
6110 "%3 = OpSDiv %int %2 %int_2\n" +
6111 "%4 = OpIMul %int %3 %int_4\n" +
6112 "OpReturn\n" +
6113 "OpFunctionEnd\n",
6114 4, false),
6115 // Test case 12: Do not merge imul of udiv
6116 // 4 * (x / 2)
6117 InstructionFoldingCase<bool>(
6118 Header() +
6119 "%main = OpFunction %void None %void_func\n" +
6120 "%main_lab = OpLabel\n" +
6121 "%var = OpVariable %_ptr_uint Function\n" +
6122 "%2 = OpLoad %uint %var\n" +
6123 "%3 = OpUDiv %uint %2 %uint_2\n" +
6124 "%4 = OpIMul %uint %uint_4 %3\n" +
6125 "OpReturn\n" +
6126 "OpFunctionEnd\n",
6127 4, false),
6128 // Test case 13: Do not merge imul of udiv
6129 // (x / 2) * 4
6130 InstructionFoldingCase<bool>(
6131 Header() +
6132 "%main = OpFunction %void None %void_func\n" +
6133 "%main_lab = OpLabel\n" +
6134 "%var = OpVariable %_ptr_uint Function\n" +
6135 "%2 = OpLoad %uint %var\n" +
6136 "%3 = OpUDiv %uint %2 %uint_2\n" +
6137 "%4 = OpIMul %uint %3 %uint_4\n" +
6138 "OpReturn\n" +
6139 "OpFunctionEnd\n",
6140 4, false),
6141 // Test case 14: Don't fold
6142 // (x / 3) * 4
6143 InstructionFoldingCase<bool>(
6144 Header() +
6145 "%main = OpFunction %void None %void_func\n" +
6146 "%main_lab = OpLabel\n" +
6147 "%var = OpVariable %_ptr_uint Function\n" +
6148 "%2 = OpLoad %uint %var\n" +
6149 "%3 = OpUDiv %uint %2 %uint_3\n" +
6150 "%4 = OpIMul %uint %3 %uint_4\n" +
6151 "OpReturn\n" +
6152 "OpFunctionEnd\n",
6153 4, false),
6154 // Test case 15: merge vector fmul of fdiv
6155 // (x / {2,2}) * {4,4} = x * {2,2}
6156 InstructionFoldingCase<bool>(
6157 Header() +
6158 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6159 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6160 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6161 "; CHECK: [[v2float_2_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_2]] [[float_2]]\n" +
6162 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
6163 "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_2_2]]\n" +
6164 "%main = OpFunction %void None %void_func\n" +
6165 "%main_lab = OpLabel\n" +
6166 "%var = OpVariable %_ptr_v2float Function\n" +
6167 "%2 = OpLoad %v2float %var\n" +
6168 "%3 = OpFDiv %v2float %2 %v2float_2_2\n" +
6169 "%4 = OpFMul %v2float %3 %v2float_4_4\n" +
6170 "OpReturn\n" +
6171 "OpFunctionEnd\n",
6172 4, true),
6173 // Test case 16: merge vector imul of snegate
6174 // (-x) * {2,2} = x * {-2,-2}
6175 InstructionFoldingCase<bool>(
6176 Header() +
6177 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6178 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
6179 "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
6180 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
6181 "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
6182 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
6183 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
6184 "%main = OpFunction %void None %void_func\n" +
6185 "%main_lab = OpLabel\n" +
6186 "%var = OpVariable %_ptr_v2int Function\n" +
6187 "%2 = OpLoad %v2int %var\n" +
6188 "%3 = OpSNegate %v2int %2\n" +
6189 "%4 = OpIMul %v2int %3 %v2int_2_2\n" +
6190 "OpReturn\n" +
6191 "OpFunctionEnd\n",
6192 4, true),
6193 // Test case 17: merge vector imul of snegate
6194 // {2,2} * (-x) = x * {-2,-2}
6195 InstructionFoldingCase<bool>(
6196 Header() +
6197 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6198 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
6199 "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
6200 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
6201 "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
6202 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
6203 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
6204 "%main = OpFunction %void None %void_func\n" +
6205 "%main_lab = OpLabel\n" +
6206 "%var = OpVariable %_ptr_v2int Function\n" +
6207 "%2 = OpLoad %v2int %var\n" +
6208 "%3 = OpSNegate %v2int %2\n" +
6209 "%4 = OpIMul %v2int %v2int_2_2 %3\n" +
6210 "OpReturn\n" +
6211 "OpFunctionEnd\n",
6212 4, true),
6213 // Test case 18: Fold OpVectorTimesScalar
6214 // {4,4} = OpVectorTimesScalar v2float {2,2} 2
6215 InstructionFoldingCase<bool>(
6216 Header() +
6217 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6218 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6219 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
6220 "; CHECK: [[v2float_4_4:%\\w+]] = OpConstantComposite [[v2float]] [[float_4]] [[float_4]]\n" +
6221 "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_4_4]]\n" +
6222 "%main = OpFunction %void None %void_func\n" +
6223 "%main_lab = OpLabel\n" +
6224 "%2 = OpVectorTimesScalar %v2float %v2float_2_2 %float_2\n" +
6225 "OpReturn\n" +
6226 "OpFunctionEnd",
6227 2, true),
6228 // Test case 19: Fold OpVectorTimesScalar
6229 // {0,0} = OpVectorTimesScalar v2float v2float_null -1
6230 InstructionFoldingCase<bool>(
6231 Header() +
6232 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6233 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6234 "; CHECK: [[v2float_null:%\\w+]] = OpConstantNull [[v2float]]\n" +
6235 "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_null]]\n" +
6236 "%main = OpFunction %void None %void_func\n" +
6237 "%main_lab = OpLabel\n" +
6238 "%2 = OpVectorTimesScalar %v2float %v2float_null %float_n1\n" +
6239 "OpReturn\n" +
6240 "OpFunctionEnd",
6241 2, true),
6242 // Test case 20: Fold OpVectorTimesScalar
6243 // {4,4} = OpVectorTimesScalar v2double {2,2} 2
6244 InstructionFoldingCase<bool>(
6245 Header() +
6246 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6247 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6248 "; CHECK: [[double_4:%\\w+]] = OpConstant [[double]] 4\n" +
6249 "; CHECK: [[v2double_4_4:%\\w+]] = OpConstantComposite [[v2double]] [[double_4]] [[double_4]]\n" +
6250 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_4_4]]\n" +
6251 "%main = OpFunction %void None %void_func\n" +
6252 "%main_lab = OpLabel\n" +
6253 "%2 = OpVectorTimesScalar %v2double %v2double_2_2 %double_2\n" +
6254 "OpReturn\n" +
6255 "OpFunctionEnd",
6256 2, true),
6257 // Test case 21: Fold OpVectorTimesScalar
6258 // {0,0} = OpVectorTimesScalar v2double {0,0} n
6259 InstructionFoldingCase<bool>(
6260 Header() +
6261 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6262 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6263 "; CHECK: {{%\\w+}} = OpConstant [[double]] 0\n" +
6264 "; CHECK: [[double_0:%\\w+]] = OpConstant [[double]] 0\n" +
6265 "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_0]] [[double_0]]\n" +
6266 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
6267 "%main = OpFunction %void None %void_func\n" +
6268 "%main_lab = OpLabel\n" +
6269 "%n = OpVariable %_ptr_double Function\n" +
6270 "%load = OpLoad %double %n\n" +
6271 "%2 = OpVectorTimesScalar %v2double %v2double_0_0 %load\n" +
6272 "OpReturn\n" +
6273 "OpFunctionEnd",
6274 2, true),
6275 // Test case 22: Fold OpVectorTimesScalar
6276 // {0,0} = OpVectorTimesScalar v2double n 0
6277 InstructionFoldingCase<bool>(
6278 Header() +
6279 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6280 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6281 "; CHECK: [[v2double_null:%\\w+]] = OpConstantNull [[v2double]]\n" +
6282 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_null]]\n" +
6283 "%main = OpFunction %void None %void_func\n" +
6284 "%main_lab = OpLabel\n" +
6285 "%n = OpVariable %_ptr_v2double Function\n" +
6286 "%load = OpLoad %v2double %n\n" +
6287 "%2 = OpVectorTimesScalar %v2double %load %double_0\n" +
6288 "OpReturn\n" +
6289 "OpFunctionEnd",
6290 2, true),
6291 // Test case 23: merge fmul of fdiv
6292 // x * (y / x) = y
6293 InstructionFoldingCase<bool>(
6294 Header() +
6295 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6296 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6297 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6298 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6299 "%main = OpFunction %void None %void_func\n" +
6300 "%main_lab = OpLabel\n" +
6301 "%x = OpVariable %_ptr_float Function\n" +
6302 "%y = OpVariable %_ptr_float Function\n" +
6303 "%2 = OpLoad %float %x\n" +
6304 "%3 = OpLoad %float %y\n" +
6305 "%4 = OpFDiv %float %3 %2\n" +
6306 "%5 = OpFMul %float %2 %4\n" +
6307 "OpReturn\n" +
6308 "OpFunctionEnd\n",
6309 5, true),
6310 // Test case 24: merge fmul of fdiv
6311 // (y / x) * x = y
6312 InstructionFoldingCase<bool>(
6313 Header() +
6314 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6315 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6316 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6317 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6318 "%main = OpFunction %void None %void_func\n" +
6319 "%main_lab = OpLabel\n" +
6320 "%x = OpVariable %_ptr_float Function\n" +
6321 "%y = OpVariable %_ptr_float Function\n" +
6322 "%2 = OpLoad %float %x\n" +
6323 "%3 = OpLoad %float %y\n" +
6324 "%4 = OpFDiv %float %3 %2\n" +
6325 "%5 = OpFMul %float %4 %2\n" +
6326 "OpReturn\n" +
6327 "OpFunctionEnd\n",
6328 5, true),
6329 // Test case 25: fold overflowing signed 32 bit imuls
6330 // (x * 1073741824) * 2 = x * int_min
6331 InstructionFoldingCase<bool>(
6332 Header() +
6333 "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
6334 "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
6335 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6336 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_min]]\n" +
6337 "%main = OpFunction %void None %void_func\n" +
6338 "%main_lab = OpLabel\n" +
6339 "%var = OpVariable %_ptr_int Function\n" +
6340 "%2 = OpLoad %int %var\n" +
6341 "%3 = OpIMul %int %2 %int_1073741824\n" +
6342 "%4 = OpIMul %int %3 %int_2\n" +
6343 "OpReturn\n" +
6344 "OpFunctionEnd\n",
6345 4, true),
6346 // Test case 26: fold overflowing signed 64 bit imuls
6347 // (x * 4611686018427387904) * 2 = x * long_min
6348 InstructionFoldingCase<bool>(
6349 Header() +
6350 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6351 "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
6352 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6353 "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_min]]\n" +
6354 "%main = OpFunction %void None %void_func\n" +
6355 "%main_lab = OpLabel\n" +
6356 "%var = OpVariable %_ptr_long Function\n" +
6357 "%2 = OpLoad %long %var\n" +
6358 "%3 = OpIMul %long %2 %long_4611686018427387904\n" +
6359 "%4 = OpIMul %long %3 %long_2\n" +
6360 "OpReturn\n" +
6361 "OpFunctionEnd\n",
6362 4, true),
6363 // Test case 27: fold overflowing 32 bit unsigned imuls
6364 // (x * 2147483649) * 2 = x * 2
6365 InstructionFoldingCase<bool>(
6366 Header() +
6367 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
6368 "; CHECK: [[uint_2:%\\w+]] = OpConstant [[uint]] 2\n" +
6369 "; CHECK: [[ld:%\\w+]] = OpLoad [[uint]]\n" +
6370 "; CHECK: %4 = OpIMul [[uint]] [[ld]] [[uint_2]]\n" +
6371 "%main = OpFunction %void None %void_func\n" +
6372 "%main_lab = OpLabel\n" +
6373 "%var = OpVariable %_ptr_uint Function\n" +
6374 "%2 = OpLoad %uint %var\n" +
6375 "%3 = OpIMul %uint %2 %uint_2147483649\n" +
6376 "%4 = OpIMul %uint %3 %uint_2\n" +
6377 "OpReturn\n" +
6378 "OpFunctionEnd\n",
6379 4, true),
6380 // Test case 28: fold overflowing 64 bit unsigned imuls
6381 // (x * 9223372036854775809) * 2 = x * 2
6382 InstructionFoldingCase<bool>(
6383 Header() +
6384 "; CHECK: [[ulong:%\\w+]] = OpTypeInt 64 0\n" +
6385 "; CHECK: [[ulong_2:%\\w+]] = OpConstant [[ulong]] 2\n" +
6386 "; CHECK: [[ld:%\\w+]] = OpLoad [[ulong]]\n" +
6387 "; CHECK: %4 = OpIMul [[ulong]] [[ld]] [[ulong_2]]\n" +
6388 "%main = OpFunction %void None %void_func\n" +
6389 "%main_lab = OpLabel\n" +
6390 "%var = OpVariable %_ptr_ulong Function\n" +
6391 "%2 = OpLoad %ulong %var\n" +
6392 "%3 = OpIMul %ulong %2 %ulong_9223372036854775809\n" +
6393 "%4 = OpIMul %ulong %3 %ulong_2\n" +
6394 "OpReturn\n" +
6395 "OpFunctionEnd\n",
6396 4, true),
6397 // Test case 29: fold underflowing signed 32 bit imuls
6398 // (x * (-858993459)) * 10 = x * 2
6399 InstructionFoldingCase<bool>(
6400 Header() +
6401 "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
6402 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
6403 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6404 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_2]]\n" +
6405 "%main = OpFunction %void None %void_func\n" +
6406 "%main_lab = OpLabel\n" +
6407 "%var = OpVariable %_ptr_int Function\n" +
6408 "%2 = OpLoad %int %var\n" +
6409 "%3 = OpIMul %int %2 %int_n858993459\n" +
6410 "%4 = OpIMul %int %3 %int_10\n" +
6411 "OpReturn\n" +
6412 "OpFunctionEnd\n",
6413 4, true),
6414 // Test case 30: fold underflowing signed 64 bit imuls
6415 // (x * (-3689348814741910323)) * 10 = x * 2
6416 InstructionFoldingCase<bool>(
6417 Header() +
6418 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6419 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
6420 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6421 "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_2]]\n" +
6422 "%main = OpFunction %void None %void_func\n" +
6423 "%main_lab = OpLabel\n" +
6424 "%var = OpVariable %_ptr_long Function\n" +
6425 "%2 = OpLoad %long %var\n" +
6426 "%3 = OpIMul %long %2 %long_n3689348814741910323\n" +
6427 "%4 = OpIMul %long %3 %long_10\n" +
6428 "OpReturn\n" +
6429 "OpFunctionEnd\n",
6430 4, true)
6431 ));
6432
6433 INSTANTIATE_TEST_SUITE_P(MergeDivTest, MatchingInstructionFoldingTest,
6434 ::testing::Values(
6435 // Test case 0: merge consecutive fdiv
6436 // 4.0 / (2.0 / x) = 2.0 * x
6437 InstructionFoldingCase<bool>(
6438 Header() +
6439 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6440 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6441 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6442 "; CHECK: %4 = OpFMul [[float]] [[float_2]] [[ld]]\n" +
6443 "%main = OpFunction %void None %void_func\n" +
6444 "%main_lab = OpLabel\n" +
6445 "%var = OpVariable %_ptr_float Function\n" +
6446 "%2 = OpLoad %float %var\n" +
6447 "%3 = OpFDiv %float %float_2 %2\n" +
6448 "%4 = OpFDiv %float %float_4 %3\n" +
6449 "OpReturn\n" +
6450 "OpFunctionEnd\n",
6451 4, true),
6452 // Test case 1: merge consecutive fdiv
6453 // 4.0 / (x / 2.0) = 8.0 / x
6454 InstructionFoldingCase<bool>(
6455 Header() +
6456 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6457 "; CHECK: [[float_8:%\\w+]] = OpConstant [[float]] 8\n" +
6458 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6459 "; CHECK: %4 = OpFDiv [[float]] [[float_8]] [[ld]]\n" +
6460 "%main = OpFunction %void None %void_func\n" +
6461 "%main_lab = OpLabel\n" +
6462 "%var = OpVariable %_ptr_float Function\n" +
6463 "%2 = OpLoad %float %var\n" +
6464 "%3 = OpFDiv %float %2 %float_2\n" +
6465 "%4 = OpFDiv %float %float_4 %3\n" +
6466 "OpReturn\n" +
6467 "OpFunctionEnd\n",
6468 4, true),
6469 // Test case 2: merge consecutive fdiv
6470 // (4.0 / x) / 2.0 = 2.0 / x
6471 InstructionFoldingCase<bool>(
6472 Header() +
6473 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6474 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6475 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6476 "; CHECK: %4 = OpFDiv [[float]] [[float_2]] [[ld]]\n" +
6477 "%main = OpFunction %void None %void_func\n" +
6478 "%main_lab = OpLabel\n" +
6479 "%var = OpVariable %_ptr_float Function\n" +
6480 "%2 = OpLoad %float %var\n" +
6481 "%3 = OpFDiv %float %float_4 %2\n" +
6482 "%4 = OpFDiv %float %3 %float_2\n" +
6483 "OpReturn\n" +
6484 "OpFunctionEnd\n",
6485 4, true),
6486 // Test case 3: Do not merge consecutive sdiv
6487 // 4 / (2 / x)
6488 InstructionFoldingCase<bool>(
6489 Header() +
6490 "%main = OpFunction %void None %void_func\n" +
6491 "%main_lab = OpLabel\n" +
6492 "%var = OpVariable %_ptr_int Function\n" +
6493 "%2 = OpLoad %int %var\n" +
6494 "%3 = OpSDiv %int %int_2 %2\n" +
6495 "%4 = OpSDiv %int %int_4 %3\n" +
6496 "OpReturn\n" +
6497 "OpFunctionEnd\n",
6498 4, false),
6499 // Test case 4: Do not merge consecutive sdiv
6500 // 4 / (x / 2)
6501 InstructionFoldingCase<bool>(
6502 Header() +
6503 "%main = OpFunction %void None %void_func\n" +
6504 "%main_lab = OpLabel\n" +
6505 "%var = OpVariable %_ptr_int Function\n" +
6506 "%2 = OpLoad %int %var\n" +
6507 "%3 = OpSDiv %int %2 %int_2\n" +
6508 "%4 = OpSDiv %int %int_4 %3\n" +
6509 "OpReturn\n" +
6510 "OpFunctionEnd\n",
6511 4, false),
6512 // Test case 5: Do not merge consecutive sdiv
6513 // (4 / x) / 2
6514 InstructionFoldingCase<bool>(
6515 Header() +
6516 "%main = OpFunction %void None %void_func\n" +
6517 "%main_lab = OpLabel\n" +
6518 "%var = OpVariable %_ptr_int Function\n" +
6519 "%2 = OpLoad %int %var\n" +
6520 "%3 = OpSDiv %int %int_4 %2\n" +
6521 "%4 = OpSDiv %int %3 %int_2\n" +
6522 "OpReturn\n" +
6523 "OpFunctionEnd\n",
6524 4, false),
6525 // Test case 6: Do not merge consecutive sdiv
6526 // (x / 4) / 2
6527 InstructionFoldingCase<bool>(
6528 Header() +
6529 "%main = OpFunction %void None %void_func\n" +
6530 "%main_lab = OpLabel\n" +
6531 "%var = OpVariable %_ptr_int Function\n" +
6532 "%2 = OpLoad %int %var\n" +
6533 "%3 = OpSDiv %int %2 %int_4\n" +
6534 "%4 = OpSDiv %int %3 %int_2\n" +
6535 "OpReturn\n" +
6536 "OpFunctionEnd\n",
6537 4, false),
6538 // Test case 7: Do not merge sdiv of imul
6539 // 4 / (2 * x)
6540 InstructionFoldingCase<bool>(
6541 Header() +
6542 "%main = OpFunction %void None %void_func\n" +
6543 "%main_lab = OpLabel\n" +
6544 "%var = OpVariable %_ptr_int Function\n" +
6545 "%2 = OpLoad %int %var\n" +
6546 "%3 = OpIMul %int %int_2 %2\n" +
6547 "%4 = OpSDiv %int %int_4 %3\n" +
6548 "OpReturn\n" +
6549 "OpFunctionEnd\n",
6550 4, false),
6551 // Test case 8: Do not merge sdiv of imul
6552 // 4 / (x * 2)
6553 InstructionFoldingCase<bool>(
6554 Header() +
6555 "%main = OpFunction %void None %void_func\n" +
6556 "%main_lab = OpLabel\n" +
6557 "%var = OpVariable %_ptr_int Function\n" +
6558 "%2 = OpLoad %int %var\n" +
6559 "%3 = OpIMul %int %2 %int_2\n" +
6560 "%4 = OpSDiv %int %int_4 %3\n" +
6561 "OpReturn\n" +
6562 "OpFunctionEnd\n",
6563 4, false),
6564 // Test case 9: Do not merge sdiv of imul
6565 // (4 * x) / 2
6566 InstructionFoldingCase<bool>(
6567 Header() +
6568 "%main = OpFunction %void None %void_func\n" +
6569 "%main_lab = OpLabel\n" +
6570 "%var = OpVariable %_ptr_int Function\n" +
6571 "%2 = OpLoad %int %var\n" +
6572 "%3 = OpIMul %int %int_4 %2\n" +
6573 "%4 = OpSDiv %int %3 %int_2\n" +
6574 "OpReturn\n" +
6575 "OpFunctionEnd\n",
6576 4, false),
6577 // Test case 10: Do not merge sdiv of imul
6578 // (x * 4) / 2
6579 InstructionFoldingCase<bool>(
6580 Header() +
6581 "%main = OpFunction %void None %void_func\n" +
6582 "%main_lab = OpLabel\n" +
6583 "%var = OpVariable %_ptr_int Function\n" +
6584 "%2 = OpLoad %int %var\n" +
6585 "%3 = OpIMul %int %2 %int_4\n" +
6586 "%4 = OpSDiv %int %3 %int_2\n" +
6587 "OpReturn\n" +
6588 "OpFunctionEnd\n",
6589 4, false),
6590 // Test case 11: Do not merge sdiv of snegate. If %2 is INT_MIN, then the
6591 // sign of %3 will be the same as %2. This cannot be accounted for in OpSDiv.
6592 // Specifically, (-INT_MIN) / 2 != INT_MIN / -2.
6593 InstructionFoldingCase<bool>(
6594 Header() +
6595 "%main = OpFunction %void None %void_func\n" +
6596 "%main_lab = OpLabel\n" +
6597 "%var = OpVariable %_ptr_int Function\n" +
6598 "%2 = OpLoad %int %var\n" +
6599 "%3 = OpSNegate %int %2\n" +
6600 "%4 = OpSDiv %int %3 %int_2\n" +
6601 "OpReturn\n" +
6602 "OpFunctionEnd\n",
6603 4, false),
6604 // Test case 12: Do not merge sdiv of snegate. If %2 is INT_MIN, then the
6605 // sign of %3 will be the same as %2. This cannot be accounted for in OpSDiv.
6606 // Specifically, 2 / (-INT_MIN) != -2 / INT_MIN.
6607 InstructionFoldingCase<bool>(
6608 Header() +
6609 "%main = OpFunction %void None %void_func\n" +
6610 "%main_lab = OpLabel\n" +
6611 "%var = OpVariable %_ptr_int Function\n" +
6612 "%2 = OpLoad %int %var\n" +
6613 "%3 = OpSNegate %int %2\n" +
6614 "%4 = OpSDiv %int %int_2 %3\n" +
6615 "OpReturn\n" +
6616 "OpFunctionEnd\n",
6617 4, false),
6618 // Test case 13: Don't merge
6619 // (x / {null}) / {null}
6620 InstructionFoldingCase<bool>(
6621 Header() +
6622 "%main = OpFunction %void None %void_func\n" +
6623 "%main_lab = OpLabel\n" +
6624 "%var = OpVariable %_ptr_v2float Function\n" +
6625 "%2 = OpLoad %float %var\n" +
6626 "%3 = OpFDiv %float %2 %v2float_null\n" +
6627 "%4 = OpFDiv %float %3 %v2float_null\n" +
6628 "OpReturn\n" +
6629 "OpFunctionEnd\n",
6630 4, false),
6631 // Test case 14: merge fmul of fdiv
6632 // (y * x) / x = y
6633 InstructionFoldingCase<bool>(
6634 Header() +
6635 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6636 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6637 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6638 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6639 "%main = OpFunction %void None %void_func\n" +
6640 "%main_lab = OpLabel\n" +
6641 "%x = OpVariable %_ptr_float Function\n" +
6642 "%y = OpVariable %_ptr_float Function\n" +
6643 "%2 = OpLoad %float %x\n" +
6644 "%3 = OpLoad %float %y\n" +
6645 "%4 = OpFMul %float %3 %2\n" +
6646 "%5 = OpFDiv %float %4 %2\n" +
6647 "OpReturn\n" +
6648 "OpFunctionEnd\n",
6649 5, true),
6650 // Test case 15: merge fmul of fdiv
6651 // (x * y) / x = y
6652 InstructionFoldingCase<bool>(
6653 Header() +
6654 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6655 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6656 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6657 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6658 "%main = OpFunction %void None %void_func\n" +
6659 "%main_lab = OpLabel\n" +
6660 "%x = OpVariable %_ptr_float Function\n" +
6661 "%y = OpVariable %_ptr_float Function\n" +
6662 "%2 = OpLoad %float %x\n" +
6663 "%3 = OpLoad %float %y\n" +
6664 "%4 = OpFMul %float %2 %3\n" +
6665 "%5 = OpFDiv %float %4 %2\n" +
6666 "OpReturn\n" +
6667 "OpFunctionEnd\n",
6668 5, true),
6669 // Test case 16: Do not merge udiv of snegate
6670 // (-x) / 2u
6671 InstructionFoldingCase<bool>(
6672 Header() +
6673 "%main = OpFunction %void None %void_func\n" +
6674 "%main_lab = OpLabel\n" +
6675 "%var = OpVariable %_ptr_uint Function\n" +
6676 "%2 = OpLoad %uint %var\n" +
6677 "%3 = OpSNegate %uint %2\n" +
6678 "%4 = OpUDiv %uint %3 %uint_2\n" +
6679 "OpReturn\n" +
6680 "OpFunctionEnd\n",
6681 4, false),
6682 // Test case 17: Do not merge udiv of snegate
6683 // 2u / (-x)
6684 InstructionFoldingCase<bool>(
6685 Header() +
6686 "%main = OpFunction %void None %void_func\n" +
6687 "%main_lab = OpLabel\n" +
6688 "%var = OpVariable %_ptr_uint Function\n" +
6689 "%2 = OpLoad %uint %var\n" +
6690 "%3 = OpSNegate %uint %2\n" +
6691 "%4 = OpUDiv %uint %uint_2 %3\n" +
6692 "OpReturn\n" +
6693 "OpFunctionEnd\n",
6694 4, false)
6695 ));
6696
6697 INSTANTIATE_TEST_SUITE_P(MergeAddTest, MatchingInstructionFoldingTest,
6698 ::testing::Values(
6699 // Test case 0: merge add of negate
6700 // (-x) + 2 = 2 - x
6701 InstructionFoldingCase<bool>(
6702 Header() +
6703 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6704 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6705 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6706 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
6707 "%main = OpFunction %void None %void_func\n" +
6708 "%main_lab = OpLabel\n" +
6709 "%var = OpVariable %_ptr_float Function\n" +
6710 "%2 = OpLoad %float %var\n" +
6711 "%3 = OpFNegate %float %2\n" +
6712 "%4 = OpFAdd %float %3 %float_2\n" +
6713 "OpReturn\n" +
6714 "OpFunctionEnd\n",
6715 4, true),
6716 // Test case 1: merge add of negate
6717 // 2 + (-x) = 2 - x
6718 InstructionFoldingCase<bool>(
6719 Header() +
6720 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6721 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6722 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6723 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
6724 "%main = OpFunction %void None %void_func\n" +
6725 "%main_lab = OpLabel\n" +
6726 "%var = OpVariable %_ptr_float Function\n" +
6727 "%2 = OpLoad %float %var\n" +
6728 "%3 = OpSNegate %float %2\n" +
6729 "%4 = OpIAdd %float %float_2 %3\n" +
6730 "OpReturn\n" +
6731 "OpFunctionEnd\n",
6732 4, true),
6733 // Test case 2: merge add of negate
6734 // (-x) + 2 = 2 - x
6735 InstructionFoldingCase<bool>(
6736 Header() +
6737 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
6738 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
6739 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6740 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
6741 "%main = OpFunction %void None %void_func\n" +
6742 "%main_lab = OpLabel\n" +
6743 "%var = OpVariable %_ptr_long Function\n" +
6744 "%2 = OpLoad %long %var\n" +
6745 "%3 = OpSNegate %long %2\n" +
6746 "%4 = OpIAdd %long %3 %long_2\n" +
6747 "OpReturn\n" +
6748 "OpFunctionEnd\n",
6749 4, true),
6750 // Test case 3: merge add of negate
6751 // 2 + (-x) = 2 - x
6752 InstructionFoldingCase<bool>(
6753 Header() +
6754 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
6755 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
6756 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6757 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
6758 "%main = OpFunction %void None %void_func\n" +
6759 "%main_lab = OpLabel\n" +
6760 "%var = OpVariable %_ptr_long Function\n" +
6761 "%2 = OpLoad %long %var\n" +
6762 "%3 = OpSNegate %long %2\n" +
6763 "%4 = OpIAdd %long %long_2 %3\n" +
6764 "OpReturn\n" +
6765 "OpFunctionEnd\n",
6766 4, true),
6767 // Test case 4: merge add of subtract
6768 // (x - 1) + 2 = x + 1
6769 InstructionFoldingCase<bool>(
6770 Header() +
6771 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6772 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
6773 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6774 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
6775 "%main = OpFunction %void None %void_func\n" +
6776 "%main_lab = OpLabel\n" +
6777 "%var = OpVariable %_ptr_float Function\n" +
6778 "%2 = OpLoad %float %var\n" +
6779 "%3 = OpFSub %float %2 %float_1\n" +
6780 "%4 = OpFAdd %float %3 %float_2\n" +
6781 "OpReturn\n" +
6782 "OpFunctionEnd\n",
6783 4, true),
6784 // Test case 5: merge add of subtract
6785 // (1 - x) + 2 = 3 - x
6786 InstructionFoldingCase<bool>(
6787 Header() +
6788 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6789 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6790 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6791 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
6792 "%main = OpFunction %void None %void_func\n" +
6793 "%main_lab = OpLabel\n" +
6794 "%var = OpVariable %_ptr_float Function\n" +
6795 "%2 = OpLoad %float %var\n" +
6796 "%3 = OpFSub %float %float_1 %2\n" +
6797 "%4 = OpFAdd %float %3 %float_2\n" +
6798 "OpReturn\n" +
6799 "OpFunctionEnd\n",
6800 4, true),
6801 // Test case 6: merge add of subtract
6802 // 2 + (x - 1) = x + 1
6803 InstructionFoldingCase<bool>(
6804 Header() +
6805 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6806 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
6807 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6808 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
6809 "%main = OpFunction %void None %void_func\n" +
6810 "%main_lab = OpLabel\n" +
6811 "%var = OpVariable %_ptr_float Function\n" +
6812 "%2 = OpLoad %float %var\n" +
6813 "%3 = OpFSub %float %2 %float_1\n" +
6814 "%4 = OpFAdd %float %float_2 %3\n" +
6815 "OpReturn\n" +
6816 "OpFunctionEnd\n",
6817 4, true),
6818 // Test case 7: merge add of subtract
6819 // 2 + (1 - x) = 3 - x
6820 InstructionFoldingCase<bool>(
6821 Header() +
6822 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6823 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6824 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6825 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
6826 "%main = OpFunction %void None %void_func\n" +
6827 "%main_lab = OpLabel\n" +
6828 "%var = OpVariable %_ptr_float Function\n" +
6829 "%2 = OpLoad %float %var\n" +
6830 "%3 = OpFSub %float %float_1 %2\n" +
6831 "%4 = OpFAdd %float %float_2 %3\n" +
6832 "OpReturn\n" +
6833 "OpFunctionEnd\n",
6834 4, true),
6835 // Test case 8: merge add of add
6836 // (x + 1) + 2 = x + 3
6837 InstructionFoldingCase<bool>(
6838 Header() +
6839 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6840 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6841 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6842 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
6843 "%main = OpFunction %void None %void_func\n" +
6844 "%main_lab = OpLabel\n" +
6845 "%var = OpVariable %_ptr_float Function\n" +
6846 "%2 = OpLoad %float %var\n" +
6847 "%3 = OpFAdd %float %2 %float_1\n" +
6848 "%4 = OpFAdd %float %3 %float_2\n" +
6849 "OpReturn\n" +
6850 "OpFunctionEnd\n",
6851 4, true),
6852 // Test case 9: merge add of add
6853 // (1 + x) + 2 = 3 + x
6854 InstructionFoldingCase<bool>(
6855 Header() +
6856 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6857 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6858 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6859 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
6860 "%main = OpFunction %void None %void_func\n" +
6861 "%main_lab = OpLabel\n" +
6862 "%var = OpVariable %_ptr_float Function\n" +
6863 "%2 = OpLoad %float %var\n" +
6864 "%3 = OpFAdd %float %float_1 %2\n" +
6865 "%4 = OpFAdd %float %3 %float_2\n" +
6866 "OpReturn\n" +
6867 "OpFunctionEnd\n",
6868 4, true),
6869 // Test case 10: merge add of add
6870 // 2 + (x + 1) = x + 1
6871 InstructionFoldingCase<bool>(
6872 Header() +
6873 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6874 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6875 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6876 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
6877 "%main = OpFunction %void None %void_func\n" +
6878 "%main_lab = OpLabel\n" +
6879 "%var = OpVariable %_ptr_float Function\n" +
6880 "%2 = OpLoad %float %var\n" +
6881 "%3 = OpFAdd %float %2 %float_1\n" +
6882 "%4 = OpFAdd %float %float_2 %3\n" +
6883 "OpReturn\n" +
6884 "OpFunctionEnd\n",
6885 4, true),
6886 // Test case 11: merge add of add
6887 // 2 + (1 + x) = 3 - x
6888 InstructionFoldingCase<bool>(
6889 Header() +
6890 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6891 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6892 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6893 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
6894 "%main = OpFunction %void None %void_func\n" +
6895 "%main_lab = OpLabel\n" +
6896 "%var = OpVariable %_ptr_float Function\n" +
6897 "%2 = OpLoad %float %var\n" +
6898 "%3 = OpFAdd %float %float_1 %2\n" +
6899 "%4 = OpFAdd %float %float_2 %3\n" +
6900 "OpReturn\n" +
6901 "OpFunctionEnd\n",
6902 4, true),
6903 // Test case 12: fold overflowing signed 32 bit iadds
6904 // (x + int_max) + 1 = x + int_min
6905 InstructionFoldingCase<bool>(
6906 Header() +
6907 "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
6908 "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
6909 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6910 "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_min]]\n" +
6911 "%main = OpFunction %void None %void_func\n" +
6912 "%main_lab = OpLabel\n" +
6913 "%var = OpVariable %_ptr_int Function\n" +
6914 "%2 = OpLoad %int %var\n" +
6915 "%3 = OpIAdd %int %2 %int_max\n" +
6916 "%4 = OpIAdd %int %3 %int_1\n" +
6917 "OpReturn\n" +
6918 "OpFunctionEnd\n",
6919 4, true),
6920 // Test case 13: fold overflowing signed 64 bit iadds
6921 // (x + long_max) + 1 = x + long_min
6922 InstructionFoldingCase<bool>(
6923 Header() +
6924 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6925 "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
6926 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6927 "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_min]]\n" +
6928 "%main = OpFunction %void None %void_func\n" +
6929 "%main_lab = OpLabel\n" +
6930 "%var = OpVariable %_ptr_long Function\n" +
6931 "%2 = OpLoad %long %var\n" +
6932 "%3 = OpIAdd %long %2 %long_max\n" +
6933 "%4 = OpIAdd %long %3 %long_1\n" +
6934 "OpReturn\n" +
6935 "OpFunctionEnd\n",
6936 4, true),
6937 // Test case 14: fold overflowing 32 bit unsigned iadds
6938 // (x + uint_max) + 2 = x + 1
6939 InstructionFoldingCase<bool>(
6940 Header() +
6941 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
6942 "; CHECK: [[uint_1:%\\w+]] = OpConstant [[uint]] 1\n" +
6943 "; CHECK: [[ld:%\\w+]] = OpLoad [[uint]]\n" +
6944 "; CHECK: %4 = OpIAdd [[uint]] [[ld]] [[uint_1]]\n" +
6945 "%main = OpFunction %void None %void_func\n" +
6946 "%main_lab = OpLabel\n" +
6947 "%var = OpVariable %_ptr_uint Function\n" +
6948 "%2 = OpLoad %uint %var\n" +
6949 "%3 = OpIAdd %uint %2 %uint_max\n" +
6950 "%4 = OpIAdd %uint %3 %uint_2\n" +
6951 "OpReturn\n" +
6952 "OpFunctionEnd\n",
6953 4, true),
6954 // Test case 15: fold overflowing 64 bit unsigned iadds
6955 // (x + ulong_max) + 2 = x + 1
6956 InstructionFoldingCase<bool>(
6957 Header() +
6958 "; CHECK: [[ulong:%\\w+]] = OpTypeInt 64 0\n" +
6959 "; CHECK: [[ulong_1:%\\w+]] = OpConstant [[ulong]] 1\n" +
6960 "; CHECK: [[ld:%\\w+]] = OpLoad [[ulong]]\n" +
6961 "; CHECK: %4 = OpIAdd [[ulong]] [[ld]] [[ulong_1]]\n" +
6962 "%main = OpFunction %void None %void_func\n" +
6963 "%main_lab = OpLabel\n" +
6964 "%var = OpVariable %_ptr_ulong Function\n" +
6965 "%2 = OpLoad %ulong %var\n" +
6966 "%3 = OpIAdd %ulong %2 %ulong_max\n" +
6967 "%4 = OpIAdd %ulong %3 %ulong_2\n" +
6968 "OpReturn\n" +
6969 "OpFunctionEnd\n",
6970 4, true),
6971 // Test case 16: fold underflowing signed 32 bit iadds
6972 // (x + int_min) + (-1) = x + int_max
6973 InstructionFoldingCase<bool>(
6974 Header() +
6975 "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
6976 "; CHECK: [[int_max:%\\w+]] = OpConstant [[int]] 2147483647\n" +
6977 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6978 "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_max]]\n" +
6979 "%main = OpFunction %void None %void_func\n" +
6980 "%main_lab = OpLabel\n" +
6981 "%var = OpVariable %_ptr_int Function\n" +
6982 "%2 = OpLoad %int %var\n" +
6983 "%3 = OpIAdd %int %2 %int_min\n" +
6984 "%4 = OpIAdd %int %3 %int_n1\n" +
6985 "OpReturn\n" +
6986 "OpFunctionEnd\n",
6987 4, true),
6988 // Test case 17: fold underflowing signed 64 bit iadds
6989 // (x + long_min) + (-1) = x + long_max
6990 InstructionFoldingCase<bool>(
6991 Header() +
6992 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6993 "; CHECK: [[long_max:%\\w+]] = OpConstant [[long]] 9223372036854775807\n" +
6994 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6995 "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_max]]\n" +
6996 "%main = OpFunction %void None %void_func\n" +
6997 "%main_lab = OpLabel\n" +
6998 "%var = OpVariable %_ptr_long Function\n" +
6999 "%2 = OpLoad %long %var\n" +
7000 "%3 = OpIAdd %long %2 %long_min\n" +
7001 "%4 = OpIAdd %long %3 %long_n1\n" +
7002 "OpReturn\n" +
7003 "OpFunctionEnd\n",
7004 4, true)
7005 ));
7006
7007 INSTANTIATE_TEST_SUITE_P(MergeGenericAddSub, MatchingInstructionFoldingTest,
7008 ::testing::Values(
7009 // Test case 0: merge of add of sub
7010 // (a - b) + b => a
7011 InstructionFoldingCase<bool>(
7012 Header() +
7013 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7014 "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
7015 "%main = OpFunction %void None %void_func\n" +
7016 "%main_lab = OpLabel\n" +
7017 "%var0 = OpVariable %_ptr_float Function\n" +
7018 "%var1 = OpVariable %_ptr_float Function\n" +
7019 "%3 = OpLoad %float %var0\n" +
7020 "%4 = OpLoad %float %var1\n" +
7021 "%5 = OpFSub %float %3 %4\n" +
7022 "%6 = OpFAdd %float %5 %4\n" +
7023 "OpReturn\n" +
7024 "OpFunctionEnd\n",
7025 6, true),
7026 // Test case 1: merge of add of sub
7027 // b + (a - b) => a
7028 InstructionFoldingCase<bool>(
7029 Header() +
7030 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7031 "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
7032 "%main = OpFunction %void None %void_func\n" +
7033 "%main_lab = OpLabel\n" +
7034 "%var0 = OpVariable %_ptr_float Function\n" +
7035 "%var1 = OpVariable %_ptr_float Function\n" +
7036 "%3 = OpLoad %float %var0\n" +
7037 "%4 = OpLoad %float %var1\n" +
7038 "%5 = OpFSub %float %3 %4\n" +
7039 "%6 = OpFAdd %float %4 %5\n" +
7040 "OpReturn\n" +
7041 "OpFunctionEnd\n",
7042 6, true)
7043 ));
7044
7045 INSTANTIATE_TEST_SUITE_P(FactorAddMul, MatchingInstructionFoldingTest,
7046 ::testing::Values(
7047 // Test case 0: factor of add of muls
7048 // (a * b) + (a * c) => a * (b + c)
7049 InstructionFoldingCase<bool>(
7050 Header() +
7051 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7052 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7053 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7054 "%main = OpFunction %void None %void_func\n" +
7055 "%main_lab = OpLabel\n" +
7056 "%var0 = OpVariable %_ptr_float Function\n" +
7057 "%var1 = OpVariable %_ptr_float Function\n" +
7058 "%var2 = OpVariable %_ptr_float Function\n" +
7059 "%4 = OpLoad %float %var0\n" +
7060 "%5 = OpLoad %float %var1\n" +
7061 "%6 = OpLoad %float %var2\n" +
7062 "%7 = OpFMul %float %6 %4\n" +
7063 "%8 = OpFMul %float %6 %5\n" +
7064 "%9 = OpFAdd %float %7 %8\n" +
7065 "OpReturn\n" +
7066 "OpFunctionEnd\n",
7067 9, true),
7068 // Test case 1: factor of add of muls
7069 // (b * a) + (a * c) => a * (b + c)
7070 InstructionFoldingCase<bool>(
7071 Header() +
7072 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7073 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7074 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7075 "%main = OpFunction %void None %void_func\n" +
7076 "%main_lab = OpLabel\n" +
7077 "%var0 = OpVariable %_ptr_float Function\n" +
7078 "%var1 = OpVariable %_ptr_float Function\n" +
7079 "%var2 = OpVariable %_ptr_float Function\n" +
7080 "%4 = OpLoad %float %var0\n" +
7081 "%5 = OpLoad %float %var1\n" +
7082 "%6 = OpLoad %float %var2\n" +
7083 "%7 = OpFMul %float %4 %6\n" +
7084 "%8 = OpFMul %float %6 %5\n" +
7085 "%9 = OpFAdd %float %7 %8\n" +
7086 "OpReturn\n" +
7087 "OpFunctionEnd\n",
7088 9, true),
7089 // Test case 2: factor of add of muls
7090 // (a * b) + (c * a) => a * (b + c)
7091 InstructionFoldingCase<bool>(
7092 Header() +
7093 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7094 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7095 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7096 "%main = OpFunction %void None %void_func\n" +
7097 "%main_lab = OpLabel\n" +
7098 "%var0 = OpVariable %_ptr_float Function\n" +
7099 "%var1 = OpVariable %_ptr_float Function\n" +
7100 "%var2 = OpVariable %_ptr_float Function\n" +
7101 "%4 = OpLoad %float %var0\n" +
7102 "%5 = OpLoad %float %var1\n" +
7103 "%6 = OpLoad %float %var2\n" +
7104 "%7 = OpFMul %float %6 %4\n" +
7105 "%8 = OpFMul %float %5 %6\n" +
7106 "%9 = OpFAdd %float %7 %8\n" +
7107 "OpReturn\n" +
7108 "OpFunctionEnd\n",
7109 9, true),
7110 // Test case 3: factor of add of muls
7111 // (b * a) + (c * a) => a * (b + c)
7112 InstructionFoldingCase<bool>(
7113 Header() +
7114 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7115 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7116 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7117 "%main = OpFunction %void None %void_func\n" +
7118 "%main_lab = OpLabel\n" +
7119 "%var0 = OpVariable %_ptr_float Function\n" +
7120 "%var1 = OpVariable %_ptr_float Function\n" +
7121 "%var2 = OpVariable %_ptr_float Function\n" +
7122 "%4 = OpLoad %float %var0\n" +
7123 "%5 = OpLoad %float %var1\n" +
7124 "%6 = OpLoad %float %var2\n" +
7125 "%7 = OpFMul %float %4 %6\n" +
7126 "%8 = OpFMul %float %5 %6\n" +
7127 "%9 = OpFAdd %float %7 %8\n" +
7128 "OpReturn\n" +
7129 "OpFunctionEnd\n",
7130 9, true)
7131 ));
7132
7133 INSTANTIATE_TEST_SUITE_P(MergeSubTest, MatchingInstructionFoldingTest,
7134 ::testing::Values(
7135 // Test case 0: merge sub of negate
7136 // (-x) - 2 = -2 - x
7137 InstructionFoldingCase<bool>(
7138 Header() +
7139 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7140 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
7141 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7142 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
7143 "%main = OpFunction %void None %void_func\n" +
7144 "%main_lab = OpLabel\n" +
7145 "%var = OpVariable %_ptr_float Function\n" +
7146 "%2 = OpLoad %float %var\n" +
7147 "%3 = OpFNegate %float %2\n" +
7148 "%4 = OpFSub %float %3 %float_2\n" +
7149 "OpReturn\n" +
7150 "OpFunctionEnd\n",
7151 4, true),
7152 // Test case 1: merge sub of negate
7153 // 2 - (-x) = x + 2
7154 InstructionFoldingCase<bool>(
7155 Header() +
7156 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7157 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
7158 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7159 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_2]]\n" +
7160 "%main = OpFunction %void None %void_func\n" +
7161 "%main_lab = OpLabel\n" +
7162 "%var = OpVariable %_ptr_float Function\n" +
7163 "%2 = OpLoad %float %var\n" +
7164 "%3 = OpFNegate %float %2\n" +
7165 "%4 = OpFSub %float %float_2 %3\n" +
7166 "OpReturn\n" +
7167 "OpFunctionEnd\n",
7168 4, true),
7169 // Test case 2: merge sub of negate
7170 // (-x) - 2 = -2 - x
7171 InstructionFoldingCase<bool>(
7172 Header() +
7173 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
7174 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
7175 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7176 "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
7177 "%main = OpFunction %void None %void_func\n" +
7178 "%main_lab = OpLabel\n" +
7179 "%var = OpVariable %_ptr_long Function\n" +
7180 "%2 = OpLoad %long %var\n" +
7181 "%3 = OpSNegate %long %2\n" +
7182 "%4 = OpISub %long %3 %long_2\n" +
7183 "OpReturn\n" +
7184 "OpFunctionEnd\n",
7185 4, true),
7186 // Test case 3: merge sub of negate
7187 // 2 - (-x) = x + 2
7188 InstructionFoldingCase<bool>(
7189 Header() +
7190 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
7191 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
7192 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7193 "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_2]]\n" +
7194 "%main = OpFunction %void None %void_func\n" +
7195 "%main_lab = OpLabel\n" +
7196 "%var = OpVariable %_ptr_long Function\n" +
7197 "%2 = OpLoad %long %var\n" +
7198 "%3 = OpSNegate %long %2\n" +
7199 "%4 = OpISub %long %long_2 %3\n" +
7200 "OpReturn\n" +
7201 "OpFunctionEnd\n",
7202 4, true),
7203 // Test case 4: merge add of subtract
7204 // (x + 2) - 1 = x + 1
7205 InstructionFoldingCase<bool>(
7206 Header() +
7207 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7208 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7209 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7210 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7211 "%main = OpFunction %void None %void_func\n" +
7212 "%main_lab = OpLabel\n" +
7213 "%var = OpVariable %_ptr_float Function\n" +
7214 "%2 = OpLoad %float %var\n" +
7215 "%3 = OpFAdd %float %2 %float_2\n" +
7216 "%4 = OpFSub %float %3 %float_1\n" +
7217 "OpReturn\n" +
7218 "OpFunctionEnd\n",
7219 4, true),
7220 // Test case 5: merge add of subtract
7221 // (2 + x) - 1 = x + 1
7222 InstructionFoldingCase<bool>(
7223 Header() +
7224 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7225 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7226 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7227 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7228 "%main = OpFunction %void None %void_func\n" +
7229 "%main_lab = OpLabel\n" +
7230 "%var = OpVariable %_ptr_float Function\n" +
7231 "%2 = OpLoad %float %var\n" +
7232 "%3 = OpFAdd %float %float_2 %2\n" +
7233 "%4 = OpFSub %float %3 %float_1\n" +
7234 "OpReturn\n" +
7235 "OpFunctionEnd\n",
7236 4, true),
7237 // Test case 6: merge add of subtract
7238 // 2 - (x + 1) = 1 - x
7239 InstructionFoldingCase<bool>(
7240 Header() +
7241 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7242 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7243 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7244 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
7245 "%main = OpFunction %void None %void_func\n" +
7246 "%main_lab = OpLabel\n" +
7247 "%var = OpVariable %_ptr_float Function\n" +
7248 "%2 = OpLoad %float %var\n" +
7249 "%3 = OpFAdd %float %2 %float_1\n" +
7250 "%4 = OpFSub %float %float_2 %3\n" +
7251 "OpReturn\n" +
7252 "OpFunctionEnd\n",
7253 4, true),
7254 // Test case 7: merge add of subtract
7255 // 2 - (1 + x) = 1 - x
7256 InstructionFoldingCase<bool>(
7257 Header() +
7258 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7259 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7260 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7261 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
7262 "%main = OpFunction %void None %void_func\n" +
7263 "%main_lab = OpLabel\n" +
7264 "%var = OpVariable %_ptr_float Function\n" +
7265 "%2 = OpLoad %float %var\n" +
7266 "%3 = OpFAdd %float %float_1 %2\n" +
7267 "%4 = OpFSub %float %float_2 %3\n" +
7268 "OpReturn\n" +
7269 "OpFunctionEnd\n",
7270 4, true),
7271 // Test case 8: merge subtract of subtract
7272 // (x - 2) - 1 = x - 3
7273 InstructionFoldingCase<bool>(
7274 Header() +
7275 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7276 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7277 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7278 "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_3]]\n" +
7279 "%main = OpFunction %void None %void_func\n" +
7280 "%main_lab = OpLabel\n" +
7281 "%var = OpVariable %_ptr_float Function\n" +
7282 "%2 = OpLoad %float %var\n" +
7283 "%3 = OpFSub %float %2 %float_2\n" +
7284 "%4 = OpFSub %float %3 %float_1\n" +
7285 "OpReturn\n" +
7286 "OpFunctionEnd\n",
7287 4, true),
7288 // Test case 9: merge subtract of subtract
7289 // (2 - x) - 1 = 1 - x
7290 InstructionFoldingCase<bool>(
7291 Header() +
7292 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7293 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7294 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7295 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
7296 "%main = OpFunction %void None %void_func\n" +
7297 "%main_lab = OpLabel\n" +
7298 "%var = OpVariable %_ptr_float Function\n" +
7299 "%2 = OpLoad %float %var\n" +
7300 "%3 = OpFSub %float %float_2 %2\n" +
7301 "%4 = OpFSub %float %3 %float_1\n" +
7302 "OpReturn\n" +
7303 "OpFunctionEnd\n",
7304 4, true),
7305 // Test case 10: merge subtract of subtract
7306 // 2 - (x - 1) = 3 - x
7307 InstructionFoldingCase<bool>(
7308 Header() +
7309 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7310 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7311 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7312 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
7313 "%main = OpFunction %void None %void_func\n" +
7314 "%main_lab = OpLabel\n" +
7315 "%var = OpVariable %_ptr_float Function\n" +
7316 "%2 = OpLoad %float %var\n" +
7317 "%3 = OpFSub %float %2 %float_1\n" +
7318 "%4 = OpFSub %float %float_2 %3\n" +
7319 "OpReturn\n" +
7320 "OpFunctionEnd\n",
7321 4, true),
7322 // Test case 11: merge subtract of subtract
7323 // 1 - (2 - x) = x + (-1)
7324 InstructionFoldingCase<bool>(
7325 Header() +
7326 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7327 "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
7328 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7329 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_n1]]\n" +
7330 "%main = OpFunction %void None %void_func\n" +
7331 "%main_lab = OpLabel\n" +
7332 "%var = OpVariable %_ptr_float Function\n" +
7333 "%2 = OpLoad %float %var\n" +
7334 "%3 = OpFSub %float %float_2 %2\n" +
7335 "%4 = OpFSub %float %float_1 %3\n" +
7336 "OpReturn\n" +
7337 "OpFunctionEnd\n",
7338 4, true),
7339 // Test case 12: merge subtract of subtract
7340 // 2 - (1 - x) = x + 1
7341 InstructionFoldingCase<bool>(
7342 Header() +
7343 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7344 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7345 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7346 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7347 "%main = OpFunction %void None %void_func\n" +
7348 "%main_lab = OpLabel\n" +
7349 "%var = OpVariable %_ptr_float Function\n" +
7350 "%2 = OpLoad %float %var\n" +
7351 "%3 = OpFSub %float %float_1 %2\n" +
7352 "%4 = OpFSub %float %float_2 %3\n" +
7353 "OpReturn\n" +
7354 "OpFunctionEnd\n",
7355 4, true),
7356 // Test case 13: merge subtract of subtract with mixed types.
7357 // 2 - (1 - x) = x + 1
7358 InstructionFoldingCase<bool>(
7359 Header() +
7360 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7361 "; CHECK: [[int_1:%\\w+]] = OpConstant [[int]] 1\n" +
7362 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
7363 "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_1]]\n" +
7364 "%main = OpFunction %void None %void_func\n" +
7365 "%main_lab = OpLabel\n" +
7366 "%var = OpVariable %_ptr_int Function\n" +
7367 "%2 = OpLoad %int %var\n" +
7368 "%3 = OpISub %int %uint_1 %2\n" +
7369 "%4 = OpISub %int %int_2 %3\n" +
7370 "OpReturn\n" +
7371 "OpFunctionEnd\n",
7372 4, true),
7373 // Test case 14: fold overflowing signed 32 bit isubs
7374 // (x - int_max) - 1 = x - int_min
7375 InstructionFoldingCase<bool>(
7376 Header() +
7377 "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
7378 "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
7379 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
7380 "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_min]]\n" +
7381 "%main = OpFunction %void None %void_func\n" +
7382 "%main_lab = OpLabel\n" +
7383 "%var = OpVariable %_ptr_int Function\n" +
7384 "%2 = OpLoad %int %var\n" +
7385 "%3 = OpISub %int %2 %int_max\n" +
7386 "%4 = OpISub %int %3 %int_1\n" +
7387 "OpReturn\n" +
7388 "OpFunctionEnd\n",
7389 4, true),
7390 // Test case 15: fold overflowing signed 64 bit isubs
7391 // (x - long_max) - 1 = x - long_min
7392 InstructionFoldingCase<bool>(
7393 Header() +
7394 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
7395 "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
7396 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7397 "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_min]]\n" +
7398 "%main = OpFunction %void None %void_func\n" +
7399 "%main_lab = OpLabel\n" +
7400 "%var = OpVariable %_ptr_long Function\n" +
7401 "%2 = OpLoad %long %var\n" +
7402 "%3 = OpISub %long %2 %long_max\n" +
7403 "%4 = OpISub %long %3 %long_1\n" +
7404 "OpReturn\n" +
7405 "OpFunctionEnd\n",
7406 4, true)
7407 ));
7408
7409 INSTANTIATE_TEST_SUITE_P(SelectFoldingTest, MatchingInstructionFoldingTest,
7410 ::testing::Values(
7411 // Test case 0: Fold select with the same values for both sides
7412 InstructionFoldingCase<bool>(
7413 Header() +
7414 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7415 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7416 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7417 "%main = OpFunction %void None %void_func\n" +
7418 "%main_lab = OpLabel\n" +
7419 "%n = OpVariable %_ptr_bool Function\n" +
7420 "%load = OpLoad %bool %n\n" +
7421 "%2 = OpSelect %int %load %100 %100\n" +
7422 "OpReturn\n" +
7423 "OpFunctionEnd",
7424 2, true),
7425 // Test case 1: Fold select true to left side
7426 InstructionFoldingCase<bool>(
7427 Header() +
7428 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7429 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7430 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7431 "%main = OpFunction %void None %void_func\n" +
7432 "%main_lab = OpLabel\n" +
7433 "%n = OpVariable %_ptr_int Function\n" +
7434 "%load = OpLoad %bool %n\n" +
7435 "%2 = OpSelect %int %true %100 %n\n" +
7436 "OpReturn\n" +
7437 "OpFunctionEnd",
7438 2, true),
7439 // Test case 2: Fold select false to right side
7440 InstructionFoldingCase<bool>(
7441 Header() +
7442 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7443 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7444 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7445 "%main = OpFunction %void None %void_func\n" +
7446 "%main_lab = OpLabel\n" +
7447 "%n = OpVariable %_ptr_int Function\n" +
7448 "%load = OpLoad %bool %n\n" +
7449 "%2 = OpSelect %int %false %n %100\n" +
7450 "OpReturn\n" +
7451 "OpFunctionEnd",
7452 2, true),
7453 // Test case 3: Fold select null to right side
7454 InstructionFoldingCase<bool>(
7455 Header() +
7456 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7457 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7458 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7459 "%main = OpFunction %void None %void_func\n" +
7460 "%main_lab = OpLabel\n" +
7461 "%n = OpVariable %_ptr_int Function\n" +
7462 "%load = OpLoad %int %n\n" +
7463 "%2 = OpSelect %int %bool_null %load %100\n" +
7464 "OpReturn\n" +
7465 "OpFunctionEnd",
7466 2, true),
7467 // Test case 4: vector null
7468 InstructionFoldingCase<bool>(
7469 Header() +
7470 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7471 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
7472 "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7473 "; CHECK: [[v2int2_2:%\\w+]] = OpConstantComposite [[v2int]] [[int2]] [[int2]]\n" +
7474 "; CHECK: %2 = OpCopyObject [[v2int]] [[v2int2_2]]\n" +
7475 "%main = OpFunction %void None %void_func\n" +
7476 "%main_lab = OpLabel\n" +
7477 "%n = OpVariable %_ptr_v2int Function\n" +
7478 "%load = OpLoad %v2int %n\n" +
7479 "%2 = OpSelect %v2int %v2bool_null %load %v2int_2_2\n" +
7480 "OpReturn\n" +
7481 "OpFunctionEnd",
7482 2, true),
7483 // Test case 5: vector select
7484 InstructionFoldingCase<bool>(
7485 Header() +
7486 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7487 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
7488 "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 0 3\n" +
7489 "%main = OpFunction %void None %void_func\n" +
7490 "%main_lab = OpLabel\n" +
7491 "%m = OpVariable %_ptr_v2int Function\n" +
7492 "%n = OpVariable %_ptr_v2int Function\n" +
7493 "%2 = OpLoad %v2int %n\n" +
7494 "%3 = OpLoad %v2int %n\n" +
7495 "%4 = OpSelect %v2int %v2bool_true_false %2 %3\n" +
7496 "OpReturn\n" +
7497 "OpFunctionEnd",
7498 4, true),
7499 // Test case 6: vector select
7500 InstructionFoldingCase<bool>(
7501 Header() +
7502 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7503 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
7504 "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 2 1\n" +
7505 "%main = OpFunction %void None %void_func\n" +
7506 "%main_lab = OpLabel\n" +
7507 "%m = OpVariable %_ptr_v2int Function\n" +
7508 "%n = OpVariable %_ptr_v2int Function\n" +
7509 "%2 = OpLoad %v2int %n\n" +
7510 "%3 = OpLoad %v2int %n\n" +
7511 "%4 = OpSelect %v2int %v2bool_false_true %2 %3\n" +
7512 "OpReturn\n" +
7513 "OpFunctionEnd",
7514 4, true)
7515 ));
7516
7517 INSTANTIATE_TEST_SUITE_P(CompositeExtractOrInsertMatchingTest, MatchingInstructionFoldingTest,
7518 ::testing::Values(
7519 // Test case 0: Extracting from result of consecutive shuffles of differing
7520 // size.
7521 InstructionFoldingCase<bool>(
7522 Header() +
7523 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7524 "; CHECK: %5 = OpCompositeExtract [[int]] %2 2\n" +
7525 "%main = OpFunction %void None %void_func\n" +
7526 "%main_lab = OpLabel\n" +
7527 "%n = OpVariable %_ptr_v4int Function\n" +
7528 "%2 = OpLoad %v4int %n\n" +
7529 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
7530 "%4 = OpVectorShuffle %v4int %2 %3 0 4 2 5\n" +
7531 "%5 = OpCompositeExtract %int %4 1\n" +
7532 "OpReturn\n" +
7533 "OpFunctionEnd",
7534 5, true),
7535 // Test case 1: Extracting from result of vector shuffle of differing
7536 // input and result sizes.
7537 InstructionFoldingCase<bool>(
7538 Header() +
7539 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7540 "; CHECK: %4 = OpCompositeExtract [[int]] %2 2\n" +
7541 "%main = OpFunction %void None %void_func\n" +
7542 "%main_lab = OpLabel\n" +
7543 "%n = OpVariable %_ptr_v4int Function\n" +
7544 "%2 = OpLoad %v4int %n\n" +
7545 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
7546 "%4 = OpCompositeExtract %int %3 0\n" +
7547 "OpReturn\n" +
7548 "OpFunctionEnd",
7549 4, true),
7550 // Test case 2: Extracting from result of vector shuffle of differing
7551 // input and result sizes.
7552 InstructionFoldingCase<bool>(
7553 Header() +
7554 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7555 "; CHECK: %4 = OpCompositeExtract [[int]] %2 3\n" +
7556 "%main = OpFunction %void None %void_func\n" +
7557 "%main_lab = OpLabel\n" +
7558 "%n = OpVariable %_ptr_v4int Function\n" +
7559 "%2 = OpLoad %v4int %n\n" +
7560 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
7561 "%4 = OpCompositeExtract %int %3 1\n" +
7562 "OpReturn\n" +
7563 "OpFunctionEnd",
7564 4, true),
7565 // Test case 3: Using fmix feeding extract with a 1 in the a position.
7566 InstructionFoldingCase<bool>(
7567 Header() +
7568 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7569 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
7570 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
7571 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7572 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7573 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[n]]\n" +
7574 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 1\n" +
7575 "%main = OpFunction %void None %void_func\n" +
7576 "%main_lab = OpLabel\n" +
7577 "%m = OpVariable %_ptr_v4double Function\n" +
7578 "%n = OpVariable %_ptr_v4double Function\n" +
7579 "%2 = OpLoad %v4double %m\n" +
7580 "%3 = OpLoad %v4double %n\n" +
7581 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
7582 "%5 = OpCompositeExtract %double %4 1\n" +
7583 "OpReturn\n" +
7584 "OpFunctionEnd",
7585 5, true),
7586 // Test case 4: Using fmix feeding extract with a 0 in the a position.
7587 InstructionFoldingCase<bool>(
7588 Header() +
7589 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7590 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
7591 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
7592 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7593 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7594 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
7595 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 2\n" +
7596 "%main = OpFunction %void None %void_func\n" +
7597 "%main_lab = OpLabel\n" +
7598 "%m = OpVariable %_ptr_v4double Function\n" +
7599 "%n = OpVariable %_ptr_v4double Function\n" +
7600 "%2 = OpLoad %v4double %m\n" +
7601 "%3 = OpLoad %v4double %n\n" +
7602 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
7603 "%5 = OpCompositeExtract %double %4 2\n" +
7604 "OpReturn\n" +
7605 "OpFunctionEnd",
7606 5, true),
7607 // Test case 5: Using fmix feeding extract with a null for the alpha
7608 InstructionFoldingCase<bool>(
7609 Header() +
7610 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7611 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
7612 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
7613 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7614 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7615 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
7616 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 0\n" +
7617 "%main = OpFunction %void None %void_func\n" +
7618 "%main_lab = OpLabel\n" +
7619 "%m = OpVariable %_ptr_v4double Function\n" +
7620 "%n = OpVariable %_ptr_v4double Function\n" +
7621 "%2 = OpLoad %v4double %m\n" +
7622 "%3 = OpLoad %v4double %n\n" +
7623 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_null\n" +
7624 "%5 = OpCompositeExtract %double %4 0\n" +
7625 "OpReturn\n" +
7626 "OpFunctionEnd",
7627 5, true),
7628 // Test case 6: Don't fold: Using fmix feeding extract with 0.5 in the a
7629 // position.
7630 InstructionFoldingCase<bool>(
7631 Header() +
7632 "%main = OpFunction %void None %void_func\n" +
7633 "%main_lab = OpLabel\n" +
7634 "%m = OpVariable %_ptr_v4double Function\n" +
7635 "%n = OpVariable %_ptr_v4double Function\n" +
7636 "%2 = OpLoad %v4double %m\n" +
7637 "%3 = OpLoad %v4double %n\n" +
7638 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_1_1_1_0p5\n" +
7639 "%5 = OpCompositeExtract %double %4 3\n" +
7640 "OpReturn\n" +
7641 "OpFunctionEnd",
7642 5, false),
7643 // Test case 7: Extracting the undefined literal value from a vector
7644 // shuffle.
7645 InstructionFoldingCase<bool>(
7646 Header() +
7647 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7648 "; CHECK: %4 = OpUndef [[int]]\n" +
7649 "%main = OpFunction %void None %void_func\n" +
7650 "%main_lab = OpLabel\n" +
7651 "%n = OpVariable %_ptr_v4int Function\n" +
7652 "%2 = OpLoad %v4int %n\n" +
7653 "%3 = OpVectorShuffle %v2int %2 %2 2 4294967295\n" +
7654 "%4 = OpCompositeExtract %int %3 1\n" +
7655 "OpReturn\n" +
7656 "OpFunctionEnd",
7657 4, true),
7658 // Test case 8: Inserting every element of a vector turns into a composite construct.
7659 InstructionFoldingCase<bool>(
7660 Header() +
7661 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7662 "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
7663 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7664 "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7665 "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
7666 "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
7667 "; CHECK: %5 = OpCopyObject [[v4]] [[construct]]\n" +
7668 "%main = OpFunction %void None %void_func\n" +
7669 "%main_lab = OpLabel\n" +
7670 "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
7671 "%3 = OpCompositeInsert %v4int %int_1 %2 1\n" +
7672 "%4 = OpCompositeInsert %v4int %int_2 %3 2\n" +
7673 "%5 = OpCompositeInsert %v4int %int_3 %4 3\n" +
7674 "OpReturn\n" +
7675 "OpFunctionEnd",
7676 5, true),
7677 // Test case 9: Inserting every element of a vector turns into a composite construct in a different order.
7678 InstructionFoldingCase<bool>(
7679 Header() +
7680 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7681 "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
7682 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7683 "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7684 "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
7685 "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
7686 "; CHECK: %5 = OpCopyObject [[v4]] [[construct]]\n" +
7687 "%main = OpFunction %void None %void_func\n" +
7688 "%main_lab = OpLabel\n" +
7689 "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
7690 "%4 = OpCompositeInsert %v4int %int_2 %2 2\n" +
7691 "%3 = OpCompositeInsert %v4int %int_1 %4 1\n" +
7692 "%5 = OpCompositeInsert %v4int %int_3 %3 3\n" +
7693 "OpReturn\n" +
7694 "OpFunctionEnd",
7695 5, true),
7696 // Test case 10: Check multiple inserts to the same position are handled correctly.
7697 InstructionFoldingCase<bool>(
7698 Header() +
7699 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7700 "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
7701 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7702 "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7703 "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
7704 "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
7705 "; CHECK: %6 = OpCopyObject [[v4]] [[construct]]\n" +
7706 "%main = OpFunction %void None %void_func\n" +
7707 "%main_lab = OpLabel\n" +
7708 "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
7709 "%3 = OpCompositeInsert %v4int %int_2 %2 2\n" +
7710 "%4 = OpCompositeInsert %v4int %int_4 %3 1\n" +
7711 "%5 = OpCompositeInsert %v4int %int_1 %4 1\n" +
7712 "%6 = OpCompositeInsert %v4int %int_3 %5 3\n" +
7713 "OpReturn\n" +
7714 "OpFunctionEnd",
7715 6, true),
7716 // Test case 11: The last indexes are 0 and 1, but they have different first indexes. This should not be folded.
7717 InstructionFoldingCase<bool>(
7718 Header() +
7719 "%main = OpFunction %void None %void_func\n" +
7720 "%main_lab = OpLabel\n" +
7721 "%2 = OpCompositeInsert %m2x2int %100 %m2x2int_undef 0 0\n" +
7722 "%3 = OpCompositeInsert %m2x2int %int_1 %2 1 1\n" +
7723 "OpReturn\n" +
7724 "OpFunctionEnd",
7725 3, false),
7726 // Test case 12: Don't fold when there is a partial insertion.
7727 InstructionFoldingCase<bool>(
7728 Header() +
7729 "%main = OpFunction %void None %void_func\n" +
7730 "%main_lab = OpLabel\n" +
7731 "%2 = OpCompositeInsert %m2x2int %v2int_1_0 %m2x2int_undef 0\n" +
7732 "%3 = OpCompositeInsert %m2x2int %int_4 %2 0 0\n" +
7733 "%4 = OpCompositeInsert %m2x2int %v2int_2_3 %3 1\n" +
7734 "OpReturn\n" +
7735 "OpFunctionEnd",
7736 4, false),
7737 // Test case 13: Insert into a column of a matrix
7738 InstructionFoldingCase<bool>(
7739 Header() +
7740 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7741 "; CHECK-DAG: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
7742 "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
7743 "; CHECK-DAG: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
7744 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7745 // We keep this insert in the chain. DeadInsertElimPass should remove it.
7746 "; CHECK: [[insert:%\\w+]] = OpCompositeInsert [[m2x2]] %100 [[m2x2_undef]] 0 0\n" +
7747 "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v2]] %100 [[int1]]\n" +
7748 "; CHECK: %3 = OpCompositeInsert [[m2x2]] [[construct]] [[insert]] 0\n" +
7749 "%main = OpFunction %void None %void_func\n" +
7750 "%main_lab = OpLabel\n" +
7751 "%2 = OpCompositeInsert %m2x2int %100 %m2x2int_undef 0 0\n" +
7752 "%3 = OpCompositeInsert %m2x2int %int_1 %2 0 1\n" +
7753 "OpReturn\n" +
7754 "OpFunctionEnd",
7755 3, true),
7756 // Test case 14: Insert all elements of the matrix.
7757 InstructionFoldingCase<bool>(
7758 Header() +
7759 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7760 "; CHECK-DAG: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
7761 "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
7762 "; CHECK-DAG: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
7763 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7764 "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7765 "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
7766 "; CHECK: [[c0:%\\w+]] = OpCompositeConstruct [[v2]] %100 [[int1]]\n" +
7767 "; CHECK: [[c1:%\\w+]] = OpCompositeConstruct [[v2]] [[int2]] [[int3]]\n" +
7768 "; CHECK: [[matrix:%\\w+]] = OpCompositeConstruct [[m2x2]] [[c0]] [[c1]]\n" +
7769 "; CHECK: %5 = OpCopyObject [[m2x2]] [[matrix]]\n" +
7770 "%main = OpFunction %void None %void_func\n" +
7771 "%main_lab = OpLabel\n" +
7772 "%2 = OpCompositeConstruct %v2int %100 %int_1\n" +
7773 "%3 = OpCompositeInsert %m2x2int %2 %m2x2int_undef 0\n" +
7774 "%4 = OpCompositeInsert %m2x2int %int_2 %3 1 0\n" +
7775 "%5 = OpCompositeInsert %m2x2int %int_3 %4 1 1\n" +
7776 "OpReturn\n" +
7777 "OpFunctionEnd",
7778 5, true),
7779 // Test case 15: Replace construct with extract when reconstructing a member
7780 // of another object.
7781 InstructionFoldingCase<bool>(
7782 Header() +
7783 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7784 "; CHECK: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
7785 "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
7786 "; CHECK: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
7787 "; CHECK: %5 = OpCompositeExtract [[v2]] [[m2x2_undef]]\n" +
7788 "%main = OpFunction %void None %void_func\n" +
7789 "%main_lab = OpLabel\n" +
7790 "%3 = OpCompositeExtract %int %m2x2int_undef 1 0\n" +
7791 "%4 = OpCompositeExtract %int %m2x2int_undef 1 1\n" +
7792 "%5 = OpCompositeConstruct %v2int %3 %4\n" +
7793 "OpReturn\n" +
7794 "OpFunctionEnd",
7795 5, true),
7796 // Test case 16: Don't fold when type cannot be deduced to a constant.
7797 InstructionFoldingCase<bool>(
7798 Header() +
7799 "%main = OpFunction %void None %void_func\n" +
7800 "%main_lab = OpLabel\n" +
7801 "%4 = OpCompositeInsert %struct_v2int_int_int %int_1 %struct_v2int_int_int_null 2\n" +
7802 "OpReturn\n" +
7803 "OpFunctionEnd",
7804 4, false),
7805 // Test case 17: Don't fold when index into composite is out of bounds.
7806 InstructionFoldingCase<bool>(
7807 Header() +
7808 "%main = OpFunction %void None %void_func\n" +
7809 "%main_lab = OpLabel\n" +
7810 "%4 = OpCompositeExtract %int %struct_v2int_int_int 3\n" +
7811 "OpReturn\n" +
7812 "OpFunctionEnd",
7813 4, false),
7814 // Test case 18: Fold when every element of an array is inserted.
7815 InstructionFoldingCase<bool>(
7816 Header() +
7817 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7818 "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7819 "; CHECK-DAG: [[arr_type:%\\w+]] = OpTypeArray [[int]] [[int2]]\n" +
7820 "; CHECK-DAG: [[int10:%\\w+]] = OpConstant [[int]] 10\n" +
7821 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7822 "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[arr_type]] [[int10]] [[int1]]\n" +
7823 "; CHECK: %5 = OpCopyObject [[arr_type]] [[construct]]\n" +
7824 "%main = OpFunction %void None %void_func\n" +
7825 "%main_lab = OpLabel\n" +
7826 "%4 = OpCompositeInsert %int_arr_2 %int_10 %int_arr_2_undef 0\n" +
7827 "%5 = OpCompositeInsert %int_arr_2 %int_1 %4 1\n" +
7828 "OpReturn\n" +
7829 "OpFunctionEnd",
7830 5, true)
7831 ));
7832
7833 INSTANTIATE_TEST_SUITE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
7834 ::testing::Values(
7835 // Test case 0: Using OpDot to extract last element.
7836 InstructionFoldingCase<bool>(
7837 Header() +
7838 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7839 "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
7840 "%main = OpFunction %void None %void_func\n" +
7841 "%main_lab = OpLabel\n" +
7842 "%n = OpVariable %_ptr_v4float Function\n" +
7843 "%2 = OpLoad %v4float %n\n" +
7844 "%3 = OpDot %float %2 %v4float_0_0_0_1\n" +
7845 "OpReturn\n" +
7846 "OpFunctionEnd",
7847 3, true),
7848 // Test case 1: Using OpDot to extract last element.
7849 InstructionFoldingCase<bool>(
7850 Header() +
7851 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7852 "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
7853 "%main = OpFunction %void None %void_func\n" +
7854 "%main_lab = OpLabel\n" +
7855 "%n = OpVariable %_ptr_v4float Function\n" +
7856 "%2 = OpLoad %v4float %n\n" +
7857 "%3 = OpDot %float %v4float_0_0_0_1 %2\n" +
7858 "OpReturn\n" +
7859 "OpFunctionEnd",
7860 3, true),
7861 // Test case 2: Using OpDot to extract second element.
7862 InstructionFoldingCase<bool>(
7863 Header() +
7864 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7865 "; CHECK: %3 = OpCompositeExtract [[float]] %2 1\n" +
7866 "%main = OpFunction %void None %void_func\n" +
7867 "%main_lab = OpLabel\n" +
7868 "%n = OpVariable %_ptr_v4float Function\n" +
7869 "%2 = OpLoad %v4float %n\n" +
7870 "%3 = OpDot %float %v4float_0_1_0_0 %2\n" +
7871 "OpReturn\n" +
7872 "OpFunctionEnd",
7873 3, true),
7874 // Test case 3: Using OpDot to extract last element.
7875 InstructionFoldingCase<bool>(
7876 Header() +
7877 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7878 "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
7879 "%main = OpFunction %void None %void_func\n" +
7880 "%main_lab = OpLabel\n" +
7881 "%n = OpVariable %_ptr_v4double Function\n" +
7882 "%2 = OpLoad %v4double %n\n" +
7883 "%3 = OpDot %double %2 %v4double_0_0_0_1\n" +
7884 "OpReturn\n" +
7885 "OpFunctionEnd",
7886 3, true),
7887 // Test case 4: Using OpDot to extract last element.
7888 InstructionFoldingCase<bool>(
7889 Header() +
7890 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7891 "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
7892 "%main = OpFunction %void None %void_func\n" +
7893 "%main_lab = OpLabel\n" +
7894 "%n = OpVariable %_ptr_v4double Function\n" +
7895 "%2 = OpLoad %v4double %n\n" +
7896 "%3 = OpDot %double %v4double_0_0_0_1 %2\n" +
7897 "OpReturn\n" +
7898 "OpFunctionEnd",
7899 3, true),
7900 // Test case 5: Using OpDot to extract second element.
7901 InstructionFoldingCase<bool>(
7902 Header() +
7903 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7904 "; CHECK: %3 = OpCompositeExtract [[double]] %2 1\n" +
7905 "%main = OpFunction %void None %void_func\n" +
7906 "%main_lab = OpLabel\n" +
7907 "%n = OpVariable %_ptr_v4double Function\n" +
7908 "%2 = OpLoad %v4double %n\n" +
7909 "%3 = OpDot %double %v4double_0_1_0_0 %2\n" +
7910 "OpReturn\n" +
7911 "OpFunctionEnd",
7912 3, true)
7913 ));
7914
7915 INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionFoldingTest,
7916 ::testing::Values(
7917 // Test case 0: Using OpDot to extract last element.
7918 InstructionFoldingCase<bool>(
7919 Header() +
7920 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7921 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
7922 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v2int]]\n" +
7923 "; CHECK: OpVectorShuffle\n" +
7924 "; CHECK: %3 = OpVectorShuffle [[v2int]] [[null]] {{%\\w+}} 4294967295 2\n" +
7925 "%main = OpFunction %void None %void_func\n" +
7926 "%main_lab = OpLabel\n" +
7927 "%n = OpVariable %_ptr_int Function\n" +
7928 "%load = OpLoad %int %n\n" +
7929 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 3 0xFFFFFFFF \n" +
7930 "%3 = OpVectorShuffle %v2int %2 %v2int_2_3 1 2 \n" +
7931 "OpReturn\n" +
7932 "OpFunctionEnd",
7933 3, true)
7934 ));
7935
7936 INSTANTIATE_TEST_SUITE_P(FmaGenerationMatchingTest, MatchingInstructionFoldingTest,
7937 ::testing::Values(
7938 // Test case 0: (x * y) + a = Fma(x, y, a)
7939 InstructionFoldingCase<bool>(
7940 Header() +
7941 "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
7942 "; CHECK: OpFunction\n" +
7943 "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7944 "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7945 "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7946 "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
7947 "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
7948 "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
7949 "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
7950 "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
7951 "%main = OpFunction %void None %void_func\n" +
7952 "%main_lab = OpLabel\n" +
7953 "%x = OpVariable %_ptr_float Function\n" +
7954 "%y = OpVariable %_ptr_float Function\n" +
7955 "%a = OpVariable %_ptr_float Function\n" +
7956 "%lx = OpLoad %float %x\n" +
7957 "%ly = OpLoad %float %y\n" +
7958 "%mul = OpFMul %float %lx %ly\n" +
7959 "%la = OpLoad %float %a\n" +
7960 "%3 = OpFAdd %float %mul %la\n" +
7961 "OpStore %a %3\n" +
7962 "OpReturn\n" +
7963 "OpFunctionEnd",
7964 3, true),
7965 // Test case 1: a + (x * y) = Fma(x, y, a)
7966 InstructionFoldingCase<bool>(
7967 Header() +
7968 "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
7969 "; CHECK: OpFunction\n" +
7970 "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7971 "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7972 "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7973 "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
7974 "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
7975 "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
7976 "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
7977 "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
7978 "%main = OpFunction %void None %void_func\n" +
7979 "%main_lab = OpLabel\n" +
7980 "%x = OpVariable %_ptr_float Function\n" +
7981 "%y = OpVariable %_ptr_float Function\n" +
7982 "%a = OpVariable %_ptr_float Function\n" +
7983 "%lx = OpLoad %float %x\n" +
7984 "%ly = OpLoad %float %y\n" +
7985 "%mul = OpFMul %float %lx %ly\n" +
7986 "%la = OpLoad %float %a\n" +
7987 "%3 = OpFAdd %float %la %mul\n" +
7988 "OpStore %a %3\n" +
7989 "OpReturn\n" +
7990 "OpFunctionEnd",
7991 3, true),
7992 // Test case 2: (x * y) + a = Fma(x, y, a) with vectors
7993 InstructionFoldingCase<bool>(
7994 Header() +
7995 "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
7996 "; CHECK: OpFunction\n" +
7997 "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7998 "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
7999 "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8000 "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
8001 "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
8002 "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
8003 "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
8004 "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
8005 "%main = OpFunction %void None %void_func\n" +
8006 "%main_lab = OpLabel\n" +
8007 "%x = OpVariable %_ptr_v4float Function\n" +
8008 "%y = OpVariable %_ptr_v4float Function\n" +
8009 "%a = OpVariable %_ptr_v4float Function\n" +
8010 "%lx = OpLoad %v4float %x\n" +
8011 "%ly = OpLoad %v4float %y\n" +
8012 "%mul = OpFMul %v4float %lx %ly\n" +
8013 "%la = OpLoad %v4float %a\n" +
8014 "%3 = OpFAdd %v4float %mul %la\n" +
8015 "OpStore %a %3\n" +
8016 "OpReturn\n" +
8017 "OpFunctionEnd",
8018 3, true),
8019 // Test case 3: a + (x * y) = Fma(x, y, a) with vectors
8020 InstructionFoldingCase<bool>(
8021 Header() +
8022 "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
8023 "; CHECK: OpFunction\n" +
8024 "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8025 "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8026 "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8027 "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
8028 "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
8029 "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
8030 "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
8031 "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
8032 "%main = OpFunction %void None %void_func\n" +
8033 "%main_lab = OpLabel\n" +
8034 "%x = OpVariable %_ptr_float Function\n" +
8035 "%y = OpVariable %_ptr_float Function\n" +
8036 "%a = OpVariable %_ptr_float Function\n" +
8037 "%lx = OpLoad %float %x\n" +
8038 "%ly = OpLoad %float %y\n" +
8039 "%mul = OpFMul %float %lx %ly\n" +
8040 "%la = OpLoad %float %a\n" +
8041 "%3 = OpFAdd %float %la %mul\n" +
8042 "OpStore %a %3\n" +
8043 "OpReturn\n" +
8044 "OpFunctionEnd",
8045 3, true),
8046 // Test 4: that the OpExtInstImport instruction is generated if it is missing.
8047 InstructionFoldingCase<bool>(
8048 std::string() +
8049 "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
8050 "; CHECK: OpFunction\n" +
8051 "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8052 "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8053 "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8054 "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
8055 "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
8056 "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
8057 "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[la]]\n" +
8058 "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
8059 "OpCapability Shader\n" +
8060 "OpMemoryModel Logical GLSL450\n" +
8061 "OpEntryPoint Fragment %main \"main\"\n" +
8062 "OpExecutionMode %main OriginUpperLeft\n" +
8063 "OpSource GLSL 140\n" +
8064 "OpName %main \"main\"\n" +
8065 "%void = OpTypeVoid\n" +
8066 "%void_func = OpTypeFunction %void\n" +
8067 "%bool = OpTypeBool\n" +
8068 "%float = OpTypeFloat 32\n" +
8069 "%_ptr_float = OpTypePointer Function %float\n" +
8070 "%main = OpFunction %void None %void_func\n" +
8071 "%main_lab = OpLabel\n" +
8072 "%x = OpVariable %_ptr_float Function\n" +
8073 "%y = OpVariable %_ptr_float Function\n" +
8074 "%a = OpVariable %_ptr_float Function\n" +
8075 "%lx = OpLoad %float %x\n" +
8076 "%ly = OpLoad %float %y\n" +
8077 "%mul = OpFMul %float %lx %ly\n" +
8078 "%la = OpLoad %float %a\n" +
8079 "%3 = OpFAdd %float %mul %la\n" +
8080 "OpStore %a %3\n" +
8081 "OpReturn\n" +
8082 "OpFunctionEnd",
8083 3, true),
8084 // Test 5: Don't fold if the multiple is marked no contract.
8085 InstructionFoldingCase<bool>(
8086 std::string() +
8087 "OpCapability Shader\n" +
8088 "OpMemoryModel Logical GLSL450\n" +
8089 "OpEntryPoint Fragment %main \"main\"\n" +
8090 "OpExecutionMode %main OriginUpperLeft\n" +
8091 "OpSource GLSL 140\n" +
8092 "OpName %main \"main\"\n" +
8093 "OpDecorate %mul NoContraction\n" +
8094 "%void = OpTypeVoid\n" +
8095 "%void_func = OpTypeFunction %void\n" +
8096 "%bool = OpTypeBool\n" +
8097 "%float = OpTypeFloat 32\n" +
8098 "%_ptr_float = OpTypePointer Function %float\n" +
8099 "%main = OpFunction %void None %void_func\n" +
8100 "%main_lab = OpLabel\n" +
8101 "%x = OpVariable %_ptr_float Function\n" +
8102 "%y = OpVariable %_ptr_float Function\n" +
8103 "%a = OpVariable %_ptr_float Function\n" +
8104 "%lx = OpLoad %float %x\n" +
8105 "%ly = OpLoad %float %y\n" +
8106 "%mul = OpFMul %float %lx %ly\n" +
8107 "%la = OpLoad %float %a\n" +
8108 "%3 = OpFAdd %float %mul %la\n" +
8109 "OpStore %a %3\n" +
8110 "OpReturn\n" +
8111 "OpFunctionEnd",
8112 3, false),
8113 // Test 6: Don't fold if the add is marked no contract.
8114 InstructionFoldingCase<bool>(
8115 std::string() +
8116 "OpCapability Shader\n" +
8117 "OpMemoryModel Logical GLSL450\n" +
8118 "OpEntryPoint Fragment %main \"main\"\n" +
8119 "OpExecutionMode %main OriginUpperLeft\n" +
8120 "OpSource GLSL 140\n" +
8121 "OpName %main \"main\"\n" +
8122 "OpDecorate %3 NoContraction\n" +
8123 "%void = OpTypeVoid\n" +
8124 "%void_func = OpTypeFunction %void\n" +
8125 "%bool = OpTypeBool\n" +
8126 "%float = OpTypeFloat 32\n" +
8127 "%_ptr_float = OpTypePointer Function %float\n" +
8128 "%main = OpFunction %void None %void_func\n" +
8129 "%main_lab = OpLabel\n" +
8130 "%x = OpVariable %_ptr_float Function\n" +
8131 "%y = OpVariable %_ptr_float Function\n" +
8132 "%a = OpVariable %_ptr_float Function\n" +
8133 "%lx = OpLoad %float %x\n" +
8134 "%ly = OpLoad %float %y\n" +
8135 "%mul = OpFMul %float %lx %ly\n" +
8136 "%la = OpLoad %float %a\n" +
8137 "%3 = OpFAdd %float %mul %la\n" +
8138 "OpStore %a %3\n" +
8139 "OpReturn\n" +
8140 "OpFunctionEnd",
8141 3, false),
8142 // Test case 7: (x * y) - a = Fma(x, y, -a)
8143 InstructionFoldingCase<bool>(
8144 Header() +
8145 "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
8146 "; CHECK: OpFunction\n" +
8147 "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8148 "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8149 "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8150 "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
8151 "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
8152 "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
8153 "; CHECK: [[na:%\\w+]] = OpFNegate {{%\\w+}} [[la]]\n" +
8154 "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[na]]\n" +
8155 "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
8156 "%main = OpFunction %void None %void_func\n" +
8157 "%main_lab = OpLabel\n" +
8158 "%x = OpVariable %_ptr_float Function\n" +
8159 "%y = OpVariable %_ptr_float Function\n" +
8160 "%a = OpVariable %_ptr_float Function\n" +
8161 "%lx = OpLoad %float %x\n" +
8162 "%ly = OpLoad %float %y\n" +
8163 "%mul = OpFMul %float %lx %ly\n" +
8164 "%la = OpLoad %float %a\n" +
8165 "%3 = OpFSub %float %mul %la\n" +
8166 "OpStore %a %3\n" +
8167 "OpReturn\n" +
8168 "OpFunctionEnd",
8169 3, true),
8170 // Test case 8: a - (x * y) = Fma(-x, y, a)
8171 InstructionFoldingCase<bool>(
8172 Header() +
8173 "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
8174 "; CHECK: OpFunction\n" +
8175 "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8176 "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8177 "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
8178 "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
8179 "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
8180 "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
8181 "; CHECK: [[nx:%\\w+]] = OpFNegate {{%\\w+}} [[lx]]\n" +
8182 "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[nx]] [[ly]] [[la]]\n" +
8183 "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
8184 "%main = OpFunction %void None %void_func\n" +
8185 "%main_lab = OpLabel\n" +
8186 "%x = OpVariable %_ptr_float Function\n" +
8187 "%y = OpVariable %_ptr_float Function\n" +
8188 "%a = OpVariable %_ptr_float Function\n" +
8189 "%lx = OpLoad %float %x\n" +
8190 "%ly = OpLoad %float %y\n" +
8191 "%mul = OpFMul %float %lx %ly\n" +
8192 "%la = OpLoad %float %a\n" +
8193 "%3 = OpFSub %float %la %mul\n" +
8194 "OpStore %a %3\n" +
8195 "OpReturn\n" +
8196 "OpFunctionEnd",
8197 3, true)
8198 ));
8199
8200 using MatchingInstructionWithNoResultFoldingTest =
8201 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8202
8203 // Test folding instructions that do not have a result. The instruction
8204 // that will be folded is the last instruction before the return. If there
8205 // are multiple returns, there is not guarantee which one is used.
TEST_P(MatchingInstructionWithNoResultFoldingTest,Case)8206 TEST_P(MatchingInstructionWithNoResultFoldingTest, Case) {
8207 const auto& tc = GetParam();
8208
8209 std::unique_ptr<IRContext> context;
8210 Instruction* inst;
8211 std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
8212
8213 // Find the instruction to test.
8214 EXPECT_EQ(inst != nullptr, tc.expected_result);
8215 if (inst != nullptr) {
8216 Match(tc.test_body, context.get());
8217 }
8218 }
8219
8220 INSTANTIATE_TEST_SUITE_P(StoreMatchingTest, MatchingInstructionWithNoResultFoldingTest,
8221 ::testing::Values(
8222 // Test case 0: Remove store of undef.
8223 InstructionFoldingCase<bool>(
8224 Header() +
8225 "; CHECK: OpLabel\n" +
8226 "; CHECK-NOT: OpStore\n" +
8227 "; CHECK: OpReturn\n" +
8228 "%main = OpFunction %void None %void_func\n" +
8229 "%main_lab = OpLabel\n" +
8230 "%n = OpVariable %_ptr_v4double Function\n" +
8231 "%undef = OpUndef %v4double\n" +
8232 "OpStore %n %undef\n" +
8233 "OpReturn\n" +
8234 "OpFunctionEnd",
8235 0 /* OpStore */, true),
8236 // Test case 1: Keep volatile store.
8237 InstructionFoldingCase<bool>(
8238 Header() +
8239 "%main = OpFunction %void None %void_func\n" +
8240 "%main_lab = OpLabel\n" +
8241 "%n = OpVariable %_ptr_v4double Function\n" +
8242 "%undef = OpUndef %v4double\n" +
8243 "OpStore %n %undef Volatile\n" +
8244 "OpReturn\n" +
8245 "OpFunctionEnd",
8246 0 /* OpStore */, false)
8247 ));
8248
8249 INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoResultFoldingTest,
8250 ::testing::Values(
8251 // Test case 0: Basic test 1
8252 InstructionFoldingCase<bool>(
8253 Header() +
8254 "; CHECK: OpVectorShuffle\n" +
8255 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 3 6 7\n" +
8256 "; CHECK: OpReturn\n" +
8257 "%main = OpFunction %void None %void_func\n" +
8258 "%main_lab = OpLabel\n" +
8259 "%2 = OpVariable %_ptr_v4double Function\n" +
8260 "%3 = OpVariable %_ptr_v4double Function\n" +
8261 "%4 = OpVariable %_ptr_v4double Function\n" +
8262 "%5 = OpLoad %v4double %2\n" +
8263 "%6 = OpLoad %v4double %3\n" +
8264 "%7 = OpLoad %v4double %4\n" +
8265 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8266 "%9 = OpVectorShuffle %v4double %7 %8 2 3 4 5\n" +
8267 "OpReturn\n" +
8268 "OpFunctionEnd",
8269 9, true),
8270 // Test case 1: Basic test 2
8271 InstructionFoldingCase<bool>(
8272 Header() +
8273 "; CHECK: OpVectorShuffle\n" +
8274 "; CHECK: OpVectorShuffle {{%\\w+}} %6 %7 0 1 4 5\n" +
8275 "; CHECK: OpReturn\n" +
8276 "%main = OpFunction %void None %void_func\n" +
8277 "%main_lab = OpLabel\n" +
8278 "%2 = OpVariable %_ptr_v4double Function\n" +
8279 "%3 = OpVariable %_ptr_v4double Function\n" +
8280 "%4 = OpVariable %_ptr_v4double Function\n" +
8281 "%5 = OpLoad %v4double %2\n" +
8282 "%6 = OpLoad %v4double %3\n" +
8283 "%7 = OpLoad %v4double %4\n" +
8284 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8285 "%9 = OpVectorShuffle %v4double %8 %7 2 3 4 5\n" +
8286 "OpReturn\n" +
8287 "OpFunctionEnd",
8288 9, true),
8289 // Test case 2: Basic test 3
8290 InstructionFoldingCase<bool>(
8291 Header() +
8292 "; CHECK: OpVectorShuffle\n" +
8293 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 2 4 5\n" +
8294 "; CHECK: OpReturn\n" +
8295 "%main = OpFunction %void None %void_func\n" +
8296 "%main_lab = OpLabel\n" +
8297 "%2 = OpVariable %_ptr_v4double Function\n" +
8298 "%3 = OpVariable %_ptr_v4double Function\n" +
8299 "%4 = OpVariable %_ptr_v4double Function\n" +
8300 "%5 = OpLoad %v4double %2\n" +
8301 "%6 = OpLoad %v4double %3\n" +
8302 "%7 = OpLoad %v4double %4\n" +
8303 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8304 "%9 = OpVectorShuffle %v4double %8 %7 1 0 4 5\n" +
8305 "OpReturn\n" +
8306 "OpFunctionEnd",
8307 9, true),
8308 // Test case 3: Basic test 4
8309 InstructionFoldingCase<bool>(
8310 Header() +
8311 "; CHECK: OpVectorShuffle\n" +
8312 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %6 2 3 5 4\n" +
8313 "; CHECK: OpReturn\n" +
8314 "%main = OpFunction %void None %void_func\n" +
8315 "%main_lab = OpLabel\n" +
8316 "%2 = OpVariable %_ptr_v4double Function\n" +
8317 "%3 = OpVariable %_ptr_v4double Function\n" +
8318 "%4 = OpVariable %_ptr_v4double Function\n" +
8319 "%5 = OpLoad %v4double %2\n" +
8320 "%6 = OpLoad %v4double %3\n" +
8321 "%7 = OpLoad %v4double %4\n" +
8322 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8323 "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 6\n" +
8324 "OpReturn\n" +
8325 "OpFunctionEnd",
8326 9, true),
8327 // Test case 4: Don't fold, need both operands of the feeder.
8328 InstructionFoldingCase<bool>(
8329 Header() +
8330 "%main = OpFunction %void None %void_func\n" +
8331 "%main_lab = OpLabel\n" +
8332 "%2 = OpVariable %_ptr_v4double Function\n" +
8333 "%3 = OpVariable %_ptr_v4double Function\n" +
8334 "%4 = OpVariable %_ptr_v4double Function\n" +
8335 "%5 = OpLoad %v4double %2\n" +
8336 "%6 = OpLoad %v4double %3\n" +
8337 "%7 = OpLoad %v4double %4\n" +
8338 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8339 "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 5\n" +
8340 "OpReturn\n" +
8341 "OpFunctionEnd",
8342 9, false),
8343 // Test case 5: Don't fold, need both operands of the feeder.
8344 InstructionFoldingCase<bool>(
8345 Header() +
8346 "%main = OpFunction %void None %void_func\n" +
8347 "%main_lab = OpLabel\n" +
8348 "%2 = OpVariable %_ptr_v4double Function\n" +
8349 "%3 = OpVariable %_ptr_v4double Function\n" +
8350 "%4 = OpVariable %_ptr_v4double Function\n" +
8351 "%5 = OpLoad %v4double %2\n" +
8352 "%6 = OpLoad %v4double %3\n" +
8353 "%7 = OpLoad %v4double %4\n" +
8354 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8355 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
8356 "OpReturn\n" +
8357 "OpFunctionEnd",
8358 9, false),
8359 // Test case 6: Fold, need both operands of the feeder, but they are the same.
8360 InstructionFoldingCase<bool>(
8361 Header() +
8362 "; CHECK: OpVectorShuffle\n" +
8363 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 2 7 5\n" +
8364 "; CHECK: OpReturn\n" +
8365 "%main = OpFunction %void None %void_func\n" +
8366 "%main_lab = OpLabel\n" +
8367 "%2 = OpVariable %_ptr_v4double Function\n" +
8368 "%3 = OpVariable %_ptr_v4double Function\n" +
8369 "%4 = OpVariable %_ptr_v4double Function\n" +
8370 "%5 = OpLoad %v4double %2\n" +
8371 "%6 = OpLoad %v4double %3\n" +
8372 "%7 = OpLoad %v4double %4\n" +
8373 "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
8374 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
8375 "OpReturn\n" +
8376 "OpFunctionEnd",
8377 9, true),
8378 // Test case 7: Fold, need both operands of the feeder, but they are the same.
8379 InstructionFoldingCase<bool>(
8380 Header() +
8381 "; CHECK: OpVectorShuffle\n" +
8382 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 0 5 7\n" +
8383 "; CHECK: OpReturn\n" +
8384 "%main = OpFunction %void None %void_func\n" +
8385 "%main_lab = OpLabel\n" +
8386 "%2 = OpVariable %_ptr_v4double Function\n" +
8387 "%3 = OpVariable %_ptr_v4double Function\n" +
8388 "%4 = OpVariable %_ptr_v4double Function\n" +
8389 "%5 = OpLoad %v4double %2\n" +
8390 "%6 = OpLoad %v4double %3\n" +
8391 "%7 = OpLoad %v4double %4\n" +
8392 "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
8393 "%9 = OpVectorShuffle %v4double %7 %8 2 0 7 5\n" +
8394 "OpReturn\n" +
8395 "OpFunctionEnd",
8396 9, true),
8397 // Test case 8: Replace first operand with a smaller vector.
8398 InstructionFoldingCase<bool>(
8399 Header() +
8400 "; CHECK: OpVectorShuffle\n" +
8401 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 0 5 3\n" +
8402 "; CHECK: OpReturn\n" +
8403 "%main = OpFunction %void None %void_func\n" +
8404 "%main_lab = OpLabel\n" +
8405 "%2 = OpVariable %_ptr_v2double Function\n" +
8406 "%3 = OpVariable %_ptr_v4double Function\n" +
8407 "%4 = OpVariable %_ptr_v4double Function\n" +
8408 "%5 = OpLoad %v2double %2\n" +
8409 "%6 = OpLoad %v4double %3\n" +
8410 "%7 = OpLoad %v4double %4\n" +
8411 "%8 = OpVectorShuffle %v4double %5 %5 0 1 2 3\n" +
8412 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
8413 "OpReturn\n" +
8414 "OpFunctionEnd",
8415 9, true),
8416 // Test case 9: Replace first operand with a larger vector.
8417 InstructionFoldingCase<bool>(
8418 Header() +
8419 "; CHECK: OpVectorShuffle\n" +
8420 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 0 7 5\n" +
8421 "; CHECK: OpReturn\n" +
8422 "%main = OpFunction %void None %void_func\n" +
8423 "%main_lab = OpLabel\n" +
8424 "%2 = OpVariable %_ptr_v4double Function\n" +
8425 "%3 = OpVariable %_ptr_v4double Function\n" +
8426 "%4 = OpVariable %_ptr_v4double Function\n" +
8427 "%5 = OpLoad %v4double %2\n" +
8428 "%6 = OpLoad %v4double %3\n" +
8429 "%7 = OpLoad %v4double %4\n" +
8430 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8431 "%9 = OpVectorShuffle %v4double %8 %7 1 0 5 3\n" +
8432 "OpReturn\n" +
8433 "OpFunctionEnd",
8434 9, true),
8435 // Test case 10: Replace unused operand with null.
8436 InstructionFoldingCase<bool>(
8437 Header() +
8438 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8439 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8440 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
8441 "; CHECK: OpVectorShuffle\n" +
8442 "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %7 4 2 5 3\n" +
8443 "; CHECK: OpReturn\n" +
8444 "%main = OpFunction %void None %void_func\n" +
8445 "%main_lab = OpLabel\n" +
8446 "%2 = OpVariable %_ptr_v4double Function\n" +
8447 "%3 = OpVariable %_ptr_v4double Function\n" +
8448 "%4 = OpVariable %_ptr_v4double Function\n" +
8449 "%5 = OpLoad %v4double %2\n" +
8450 "%6 = OpLoad %v4double %3\n" +
8451 "%7 = OpLoad %v4double %4\n" +
8452 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8453 "%9 = OpVectorShuffle %v4double %8 %7 4 2 5 3\n" +
8454 "OpReturn\n" +
8455 "OpFunctionEnd",
8456 9, true),
8457 // Test case 11: Replace unused operand with null.
8458 InstructionFoldingCase<bool>(
8459 Header() +
8460 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8461 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8462 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
8463 "; CHECK: OpVectorShuffle\n" +
8464 "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %5 2 2 5 5\n" +
8465 "; CHECK: OpReturn\n" +
8466 "%main = OpFunction %void None %void_func\n" +
8467 "%main_lab = OpLabel\n" +
8468 "%2 = OpVariable %_ptr_v4double Function\n" +
8469 "%3 = OpVariable %_ptr_v4double Function\n" +
8470 "%5 = OpLoad %v4double %2\n" +
8471 "%6 = OpLoad %v4double %3\n" +
8472 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8473 "%9 = OpVectorShuffle %v4double %8 %8 2 2 3 3\n" +
8474 "OpReturn\n" +
8475 "OpFunctionEnd",
8476 9, true),
8477 // Test case 12: Replace unused operand with null.
8478 InstructionFoldingCase<bool>(
8479 Header() +
8480 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8481 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8482 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
8483 "; CHECK: OpVectorShuffle\n" +
8484 "; CHECK: OpVectorShuffle {{%\\w+}} %7 [[null]] 2 0 1 3\n" +
8485 "; CHECK: OpReturn\n" +
8486 "%main = OpFunction %void None %void_func\n" +
8487 "%main_lab = OpLabel\n" +
8488 "%2 = OpVariable %_ptr_v4double Function\n" +
8489 "%3 = OpVariable %_ptr_v4double Function\n" +
8490 "%4 = OpVariable %_ptr_v4double Function\n" +
8491 "%5 = OpLoad %v4double %2\n" +
8492 "%6 = OpLoad %v4double %3\n" +
8493 "%7 = OpLoad %v4double %4\n" +
8494 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8495 "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" +
8496 "OpReturn\n" +
8497 "OpFunctionEnd",
8498 9, true),
8499 // Test case 13: Shuffle with undef literal.
8500 InstructionFoldingCase<bool>(
8501 Header() +
8502 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8503 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8504 "; CHECK: OpVectorShuffle\n" +
8505 "; CHECK: OpVectorShuffle {{%\\w+}} %7 {{%\\w+}} 2 0 1 4294967295\n" +
8506 "; CHECK: OpReturn\n" +
8507 "%main = OpFunction %void None %void_func\n" +
8508 "%main_lab = OpLabel\n" +
8509 "%2 = OpVariable %_ptr_v4double Function\n" +
8510 "%3 = OpVariable %_ptr_v4double Function\n" +
8511 "%4 = OpVariable %_ptr_v4double Function\n" +
8512 "%5 = OpLoad %v4double %2\n" +
8513 "%6 = OpLoad %v4double %3\n" +
8514 "%7 = OpLoad %v4double %4\n" +
8515 "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
8516 "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" +
8517 "OpReturn\n" +
8518 "OpFunctionEnd",
8519 9, true),
8520 // Test case 14: Shuffle with undef literal and change size of first input vector.
8521 InstructionFoldingCase<bool>(
8522 Header() +
8523 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8524 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8525 "; CHECK: OpVectorShuffle\n" +
8526 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 1 4 4294967295\n" +
8527 "; CHECK: OpReturn\n" +
8528 "%main = OpFunction %void None %void_func\n" +
8529 "%main_lab = OpLabel\n" +
8530 "%2 = OpVariable %_ptr_v4double Function\n" +
8531 "%3 = OpVariable %_ptr_v4double Function\n" +
8532 "%4 = OpVariable %_ptr_v4double Function\n" +
8533 "%5 = OpLoad %v4double %2\n" +
8534 "%6 = OpLoad %v4double %3\n" +
8535 "%7 = OpLoad %v4double %4\n" +
8536 "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
8537 "%9 = OpVectorShuffle %v4double %8 %7 0 1 2 4294967295\n" +
8538 "OpReturn\n" +
8539 "OpFunctionEnd",
8540 9, true)
8541 ));
8542
8543 using EntryPointFoldingTest =
8544 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8545
TEST_P(EntryPointFoldingTest,Case)8546 TEST_P(EntryPointFoldingTest, Case) {
8547 const auto& tc = GetParam();
8548
8549 // Build module.
8550 std::unique_ptr<IRContext> context =
8551 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
8552 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
8553 ASSERT_NE(nullptr, context);
8554
8555 // Find the first entry point. That is the instruction we want to fold.
8556 Instruction* inst = nullptr;
8557 ASSERT_FALSE(context->module()->entry_points().empty());
8558 inst = &*context->module()->entry_points().begin();
8559 assert(inst && "Invalid test. Could not find entry point instruction to fold.");
8560 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
8561 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
8562 EXPECT_EQ(succeeded, tc.expected_result);
8563 if (succeeded) {
8564 Match(tc.test_body, context.get());
8565 }
8566 }
8567
8568 INSTANTIATE_TEST_SUITE_P(OpEntryPointFoldingTest, EntryPointFoldingTest,
8569 ::testing::Values(
8570 // Test case 0: Basic test 1
8571 InstructionFoldingCase<bool>(std::string() +
8572 "; CHECK: OpEntryPoint Fragment %2 \"main\" %3\n" +
8573 "OpCapability Shader\n" +
8574 "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
8575 "OpMemoryModel Logical GLSL450\n" +
8576 "OpEntryPoint Fragment %2 \"main\" %3 %3 %3\n" +
8577 "OpExecutionMode %2 OriginUpperLeft\n" +
8578 "OpSource GLSL 430\n" +
8579 "OpDecorate %3 Location 0\n" +
8580 "%void = OpTypeVoid\n" +
8581 "%5 = OpTypeFunction %void\n" +
8582 "%float = OpTypeFloat 32\n" +
8583 "%v4float = OpTypeVector %float 4\n" +
8584 "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
8585 "%3 = OpVariable %_ptr_Output_v4float Output\n" +
8586 "%int = OpTypeInt 32 1\n" +
8587 "%int_0 = OpConstant %int 0\n" +
8588 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
8589 "%2 = OpFunction %void None %5\n" +
8590 "%12 = OpLabel\n" +
8591 "OpReturn\n" +
8592 "OpFunctionEnd\n",
8593 9, true),
8594 InstructionFoldingCase<bool>(std::string() +
8595 "; CHECK: OpEntryPoint Fragment %2 \"main\" %3 %4\n" +
8596 "OpCapability Shader\n" +
8597 "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
8598 "OpMemoryModel Logical GLSL450\n" +
8599 "OpEntryPoint Fragment %2 \"main\" %3 %4 %3\n" +
8600 "OpExecutionMode %2 OriginUpperLeft\n" +
8601 "OpSource GLSL 430\n" +
8602 "OpDecorate %3 Location 0\n" +
8603 "%void = OpTypeVoid\n" +
8604 "%5 = OpTypeFunction %void\n" +
8605 "%float = OpTypeFloat 32\n" +
8606 "%v4float = OpTypeVector %float 4\n" +
8607 "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
8608 "%3 = OpVariable %_ptr_Output_v4float Output\n" +
8609 "%4 = OpVariable %_ptr_Output_v4float Output\n" +
8610 "%int = OpTypeInt 32 1\n" +
8611 "%int_0 = OpConstant %int 0\n" +
8612 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
8613 "%2 = OpFunction %void None %5\n" +
8614 "%12 = OpLabel\n" +
8615 "OpReturn\n" +
8616 "OpFunctionEnd\n",
8617 9, true),
8618 InstructionFoldingCase<bool>(std::string() +
8619 "; CHECK: OpEntryPoint Fragment %2 \"main\" %4 %3\n" +
8620 "OpCapability Shader\n" +
8621 "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
8622 "OpMemoryModel Logical GLSL450\n" +
8623 "OpEntryPoint Fragment %2 \"main\" %4 %4 %3\n" +
8624 "OpExecutionMode %2 OriginUpperLeft\n" +
8625 "OpSource GLSL 430\n" +
8626 "OpDecorate %3 Location 0\n" +
8627 "%void = OpTypeVoid\n" +
8628 "%5 = OpTypeFunction %void\n" +
8629 "%float = OpTypeFloat 32\n" +
8630 "%v4float = OpTypeVector %float 4\n" +
8631 "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
8632 "%3 = OpVariable %_ptr_Output_v4float Output\n" +
8633 "%4 = OpVariable %_ptr_Output_v4float Output\n" +
8634 "%int = OpTypeInt 32 1\n" +
8635 "%int_0 = OpConstant %int 0\n" +
8636 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
8637 "%2 = OpFunction %void None %5\n" +
8638 "%12 = OpLabel\n" +
8639 "OpReturn\n" +
8640 "OpFunctionEnd\n",
8641 9, true)
8642 ));
8643
8644 using SPV14FoldingTest =
8645 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8646
TEST_P(SPV14FoldingTest,Case)8647 TEST_P(SPV14FoldingTest, Case) {
8648 const auto& tc = GetParam();
8649
8650 std::unique_ptr<IRContext> context;
8651 Instruction* inst;
8652 std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_4);
8653
8654 EXPECT_EQ(inst != nullptr, tc.expected_result);
8655 if (inst != nullptr) {
8656 Match(tc.test_body, context.get());
8657 }
8658 }
8659
8660 INSTANTIATE_TEST_SUITE_P(SPV14FoldingTest, SPV14FoldingTest,
8661 ::testing::Values(
8662 // Test case 0: select vectors with scalar condition.
8663 InstructionFoldingCase<bool>(std::string() +
8664 "; CHECK-NOT: OpSelect\n" +
8665 "; CHECK: %3 = OpCopyObject {{%\\w+}} %1\n" +
8666 "OpCapability Shader\n" +
8667 "OpCapability Linkage\n" +
8668 "%void = OpTypeVoid\n" +
8669 "%bool = OpTypeBool\n" +
8670 "%true = OpConstantTrue %bool\n" +
8671 "%int = OpTypeInt 32 0\n" +
8672 "%int4 = OpTypeVector %int 4\n" +
8673 "%int_0 = OpConstant %int 0\n" +
8674 "%int_1 = OpConstant %int 1\n" +
8675 "%1 = OpUndef %int4\n" +
8676 "%2 = OpUndef %int4\n" +
8677 "%void_fn = OpTypeFunction %void\n" +
8678 "%func = OpFunction %void None %void_fn\n" +
8679 "%entry = OpLabel\n" +
8680 "%3 = OpSelect %int4 %true %1 %2\n" +
8681 "OpReturn\n" +
8682 "OpFunctionEnd\n"
8683 ,
8684 3, true),
8685 // Test case 1: select struct with scalar condition.
8686 InstructionFoldingCase<bool>(std::string() +
8687 "; CHECK-NOT: OpSelect\n" +
8688 "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
8689 "OpCapability Shader\n" +
8690 "OpCapability Linkage\n" +
8691 "%void = OpTypeVoid\n" +
8692 "%bool = OpTypeBool\n" +
8693 "%true = OpConstantFalse %bool\n" +
8694 "%int = OpTypeInt 32 0\n" +
8695 "%struct = OpTypeStruct %int %int %int %int\n" +
8696 "%int_0 = OpConstant %int 0\n" +
8697 "%int_1 = OpConstant %int 1\n" +
8698 "%1 = OpUndef %struct\n" +
8699 "%2 = OpUndef %struct\n" +
8700 "%void_fn = OpTypeFunction %void\n" +
8701 "%func = OpFunction %void None %void_fn\n" +
8702 "%entry = OpLabel\n" +
8703 "%3 = OpSelect %struct %true %1 %2\n" +
8704 "OpReturn\n" +
8705 "OpFunctionEnd\n"
8706 ,
8707 3, true),
8708 // Test case 1: select array with scalar condition.
8709 InstructionFoldingCase<bool>(std::string() +
8710 "; CHECK-NOT: OpSelect\n" +
8711 "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
8712 "OpCapability Shader\n" +
8713 "OpCapability Linkage\n" +
8714 "%void = OpTypeVoid\n" +
8715 "%bool = OpTypeBool\n" +
8716 "%true = OpConstantFalse %bool\n" +
8717 "%int = OpTypeInt 32 0\n" +
8718 "%int_0 = OpConstant %int 0\n" +
8719 "%int_1 = OpConstant %int 1\n" +
8720 "%int_4 = OpConstant %int 4\n" +
8721 "%array = OpTypeStruct %int %int %int %int\n" +
8722 "%1 = OpUndef %array\n" +
8723 "%2 = OpUndef %array\n" +
8724 "%void_fn = OpTypeFunction %void\n" +
8725 "%func = OpFunction %void None %void_fn\n" +
8726 "%entry = OpLabel\n" +
8727 "%3 = OpSelect %array %true %1 %2\n" +
8728 "OpReturn\n" +
8729 "OpFunctionEnd\n"
8730 ,
8731 3, true)
8732 ));
8733
FloatControlsHeader(const std::string & capabilities)8734 std::string FloatControlsHeader(const std::string& capabilities) {
8735 std::string header = R"(
8736 OpCapability Shader
8737 )" + capabilities + R"(
8738 %void = OpTypeVoid
8739 %float = OpTypeFloat 32
8740 %float_0 = OpConstant %float 0
8741 %float_1 = OpConstant %float 1
8742 %void_fn = OpTypeFunction %void
8743 %func = OpFunction %void None %void_fn
8744 %entry = OpLabel
8745 )";
8746
8747 return header;
8748 }
8749
8750 using FloatControlsFoldingTest =
8751 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8752
TEST_P(FloatControlsFoldingTest,Case)8753 TEST_P(FloatControlsFoldingTest, Case) {
8754 const auto& tc = GetParam();
8755
8756 std::unique_ptr<IRContext> context;
8757 Instruction* inst;
8758 std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_4);
8759
8760 EXPECT_EQ(inst != nullptr, tc.expected_result);
8761 if (inst != nullptr) {
8762 Match(tc.test_body, context.get());
8763 }
8764 }
8765
8766 INSTANTIATE_TEST_SUITE_P(FloatControlsFoldingTest, FloatControlsFoldingTest,
8767 ::testing::Values(
8768 // Test case 0: no folding with DenormPreserve
8769 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormPreserve") +
8770 "%1 = OpFAdd %float %float_0 %float_1\n" +
8771 "OpReturn\n" +
8772 "OpFunctionEnd\n"
8773 ,
8774 1, false),
8775 // Test case 1: no folding with DenormFlushToZero
8776 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormFlushToZero") +
8777 "%1 = OpFAdd %float %float_0 %float_1\n" +
8778 "OpReturn\n" +
8779 "OpFunctionEnd\n"
8780 ,
8781 1, false),
8782 // Test case 2: no folding with SignedZeroInfNanPreserve
8783 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability SignedZeroInfNanPreserve") +
8784 "%1 = OpFAdd %float %float_0 %float_1\n" +
8785 "OpReturn\n" +
8786 "OpFunctionEnd\n"
8787 ,
8788 1, false),
8789 // Test case 3: no folding with RoundingModeRTE
8790 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTE") +
8791 "%1 = OpFAdd %float %float_0 %float_1\n" +
8792 "OpReturn\n" +
8793 "OpFunctionEnd\n"
8794 ,
8795 1, false),
8796 // Test case 4: no folding with RoundingModeRTZ
8797 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTZ") +
8798 "%1 = OpFAdd %float %float_0 %float_1\n" +
8799 "OpReturn\n" +
8800 "OpFunctionEnd\n"
8801 ,
8802 1, false)
8803 ));
8804
ImageOperandsTestBody(const std::string & image_instruction)8805 std::string ImageOperandsTestBody(const std::string& image_instruction) {
8806 std::string body = R"(
8807 OpCapability Shader
8808 OpCapability ImageGatherExtended
8809 OpMemoryModel Logical GLSL450
8810 OpEntryPoint Fragment %main "main"
8811 OpExecutionMode %main OriginUpperLeft
8812 OpDecorate %Texture DescriptorSet 0
8813 OpDecorate %Texture Binding 0
8814 %int = OpTypeInt 32 1
8815 %int_n1 = OpConstant %int -1
8816 %5 = OpConstant %int 0
8817 %float = OpTypeFloat 32
8818 %float_0 = OpConstant %float 0
8819 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
8820 %type_sampled_image = OpTypeSampledImage %type_2d_image
8821 %type_sampler = OpTypeSampler
8822 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
8823 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
8824 %_ptr_int = OpTypePointer Function %int
8825 %v2int = OpTypeVector %int 2
8826 %10 = OpTypeVector %float 4
8827 %void = OpTypeVoid
8828 %22 = OpTypeFunction %void
8829 %v2float = OpTypeVector %float 2
8830 %v3int = OpTypeVector %int 3
8831 %Texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
8832 %gSampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
8833 %110 = OpConstantComposite %v2int %5 %5
8834 %101 = OpConstantComposite %v2int %int_n1 %int_n1
8835 %20 = OpConstantComposite %v2float %float_0 %float_0
8836 %main = OpFunction %void None %22
8837 %23 = OpLabel
8838 %var = OpVariable %_ptr_int Function
8839 %88 = OpLoad %type_2d_image %Texture
8840 %val = OpLoad %int %var
8841 %sampler = OpLoad %type_sampler %gSampler
8842 %26 = OpSampledImage %type_sampled_image %88 %sampler
8843 )" + image_instruction + R"(
8844 OpReturn
8845 OpFunctionEnd
8846 )";
8847
8848 return body;
8849 }
8850
8851 INSTANTIATE_TEST_SUITE_P(ImageOperandsBitmaskFoldingTest, MatchingInstructionWithNoResultFoldingTest,
8852 ::testing::Values(
8853 // Test case 0: OpImageFetch without Offset
8854 InstructionFoldingCase<bool>(ImageOperandsTestBody(
8855 "%89 = OpImageFetch %10 %88 %101 Lod %5 \n")
8856 , 89, false),
8857 // Test case 1: OpImageFetch with non-const offset
8858 InstructionFoldingCase<bool>(ImageOperandsTestBody(
8859 "%89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %val \n")
8860 , 89, false),
8861 // Test case 2: OpImageFetch with Lod and Offset
8862 InstructionFoldingCase<bool>(ImageOperandsTestBody(
8863 " %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %101 \n"
8864 "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod|ConstOffset %5 %101 \n")
8865 , 89, true),
8866 // Test case 3: OpImageFetch with Bias and Offset
8867 InstructionFoldingCase<bool>(ImageOperandsTestBody(
8868 " %89 = OpImageFetch %10 %88 %101 Bias|Offset %5 %101 \n"
8869 "; CHECK: %89 = OpImageFetch %10 %88 %101 Bias|ConstOffset %5 %101 \n")
8870 , 89, true),
8871 // Test case 4: OpImageFetch with Grad and Offset.
8872 // Grad adds 2 operands to the instruction.
8873 InstructionFoldingCase<bool>(ImageOperandsTestBody(
8874 " %89 = OpImageFetch %10 %88 %101 Grad|Offset %5 %5 %101 \n"
8875 "; CHECK: %89 = OpImageFetch %10 %88 %101 Grad|ConstOffset %5 %5 %101 \n")
8876 , 89, true),
8877 // Test case 5: OpImageFetch with Offset and MinLod.
8878 // This is an example of a case where the bitmask bit-offset is larger than
8879 // that of the Offset.
8880 InstructionFoldingCase<bool>(ImageOperandsTestBody(
8881 " %89 = OpImageFetch %10 %88 %101 Offset|MinLod %101 %5 \n"
8882 "; CHECK: %89 = OpImageFetch %10 %88 %101 ConstOffset|MinLod %101 %5 \n")
8883 , 89, true),
8884 // Test case 6: OpImageGather with constant Offset
8885 InstructionFoldingCase<bool>(ImageOperandsTestBody(
8886 " %89 = OpImageGather %10 %26 %20 %5 Offset %101 \n"
8887 "; CHECK: %89 = OpImageGather %10 %26 %20 %5 ConstOffset %101 \n")
8888 , 89, true),
8889 // Test case 7: OpImageWrite with constant Offset
8890 InstructionFoldingCase<bool>(ImageOperandsTestBody(
8891 " OpImageWrite %88 %5 %101 Offset %101 \n"
8892 "; CHECK: OpImageWrite %88 %5 %101 ConstOffset %101 \n")
8893 , 0 /* No result-id */, true),
8894 // Test case 8: OpImageFetch with zero constant Offset
8895 InstructionFoldingCase<bool>(ImageOperandsTestBody(
8896 " %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %110 \n"
8897 "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod %5 \n")
8898 , 89, true)
8899 ));
8900
8901 } // namespace
8902 } // namespace opt
8903 } // namespace spvtools
8904