1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "macros.h"
17 #include "unit_test.h"
18 #include "libpandabase/utils/utils.h"
19 #include "optimizer/optimizations/const_folding.h"
20 #include "optimizer/optimizations/cleanup.h"
21 #include "optimizer/code_generator/codegen.h"
22
23 #include <optional>
24
25 namespace ark::compiler {
26
27 // NOLINTBEGIN(readability-magic-numbers)
28 class ConstFoldingTest : public CommonTest {
29 public:
ConstFoldingTest()30 ConstFoldingTest() : graph_(CreateGraphStartEndBlocks()) {}
31 ~ConstFoldingTest() override = default;
32
33 NO_COPY_SEMANTIC(ConstFoldingTest);
34 NO_MOVE_SEMANTIC(ConstFoldingTest);
35
36 using ConstFoldingFunc = bool (*)(Inst *inst);
37
GetGraph()38 Graph *GetGraph()
39 {
40 return graph_;
41 }
42
43 template <class T>
CmpTest(T l,T r,int64_t result,DataType::Type srcType,bool fcmpg=false)44 void CmpTest(T l, T r, int64_t result, DataType::Type srcType, bool fcmpg = false)
45 {
46 auto graph = CreateEmptyGraph();
47 GRAPH(graph)
48 {
49 CONSTANT(0U, l);
50 CONSTANT(1U, r);
51 BASIC_BLOCK(2U, 1U)
52 {
53 INST(2U, Opcode::Cmp).s32().SrcType(srcType).Inputs(0U, 1U);
54 INST(3U, Opcode::Return).s32().Inputs(2U);
55 }
56 }
57 if (DataType::IsFloatType(srcType)) {
58 INS(2U).CastToCmp()->SetFcmpg(fcmpg);
59 ASSERT_EQ(INS(2U).CastToCmp()->IsFcmpg(), fcmpg);
60 }
61 ASSERT_EQ(ConstFoldingCmp(&INS(2U)), true);
62 GraphChecker(graph).Check();
63
64 ConstantInst *inst = graph->FindConstant(DataType::INT64, result);
65 ASSERT(inst != nullptr);
66 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
67 }
68
69 template <class From, class To>
CastTest(From src,To dst,DataType::Type dstType)70 void CastTest(From src, To dst, DataType::Type dstType)
71 {
72 auto graph = CreateEmptyGraph();
73 GRAPH(graph)
74 {
75 CONSTANT(0U, src);
76 BASIC_BLOCK(2U, 1U)
77 {
78 INST(1U, Opcode::Cast).SrcType(INS(0U).GetType()).Inputs(0U);
79 INS(1U).SetType(dstType);
80 INST(2U, Opcode::Return).Inputs(1U);
81 INS(2U).SetType(dstType);
82 }
83 }
84 ASSERT_EQ(ConstFoldingCast(&INS(1U)), true);
85 GraphChecker(graph).Check();
86
87 ConstantInst *inst = nullptr;
88 if (DataType::GetCommonType(dstType) == DataType::INT64) {
89 inst = graph->FindConstant(DataType::INT64, dst);
90 } else if (dstType == DataType::FLOAT32) {
91 inst = graph->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(dst));
92 } else if (dstType == DataType::FLOAT64) {
93 inst = graph->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(dst));
94 }
95 ASSERT(inst != nullptr);
96 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
97 }
98
CheckCompareEqualInputs(DataType::Type paramType,ConditionCode cc,std::optional<uint64_t> result)99 void CheckCompareEqualInputs(DataType::Type paramType, ConditionCode cc, std::optional<uint64_t> result)
100 {
101 auto graph = CreateEmptyGraph();
102 GRAPH(graph)
103 {
104 PARAMETER(0U, 0U);
105 INS(0U).SetType(paramType);
106 BASIC_BLOCK(2U, 1U)
107 {
108 INST(1U, Opcode::Compare).b().CC(cc).Inputs(0U, 0U);
109 INST(2U, Opcode::Return).b().Inputs(1U);
110 }
111 }
112 ASSERT_EQ(ConstFoldingCompare(&INS(1U)), result.has_value());
113 if (result.has_value()) {
114 auto inst = graph->FindConstant(DataType::INT64, *result);
115 ASSERT(inst != nullptr);
116 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
117 }
118 GraphChecker(graph).Check();
119 }
120
CheckCompareLoadImmediate(RuntimeInterface::ClassPtr class1,RuntimeInterface::ClassPtr class2,ConditionCode cc,uint64_t result)121 void CheckCompareLoadImmediate(RuntimeInterface::ClassPtr class1, RuntimeInterface::ClassPtr class2,
122 ConditionCode cc, uint64_t result)
123 {
124 auto graph = CreateEmptyGraph();
125 GRAPH(graph)
126 {
127 BASIC_BLOCK(2U, 1U)
128 {
129 INST(0U, Opcode::LoadImmediate).ref().Class(class1);
130 INST(1U, Opcode::LoadImmediate).ref().Class(class2);
131 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::REFERENCE).CC(cc).Inputs(0U, 1U);
132 INST(3U, Opcode::Return).b().Inputs(2U);
133 }
134 }
135 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
136 auto inst = graph->FindConstant(DataType::INT64, result);
137 ASSERT(inst != nullptr);
138 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
139 GraphChecker(graph).Check();
140 }
141
142 enum InputValue : char {
143 NAN1_F = 0,
144 NAN2_F,
145 NAN1_D,
146 NAN2_D,
147 NUMBER_F,
148 NUMBER_D,
149 };
150
CheckCompareWithNan(DataType::Type sourceType,InputValue input0,InputValue input1,ConditionCode cc,bool result)151 void CheckCompareWithNan(DataType::Type sourceType, InputValue input0, InputValue input1, ConditionCode cc,
152 bool result)
153 {
154 // Check that position is not changed
155 static_assert(InputValue::NAN1_F == 0U && InputValue::NAN2_F == 1U && InputValue::NAN1_D == 2U &&
156 InputValue::NAN2_D == 3U && InputValue::NUMBER_F == 4U && InputValue::NUMBER_D == 5U);
157 const auto nan1ValueF = bit_cast<float>(NAN_FLOAT);
158 const auto nan2ValueF = bit_cast<float>(NAN_FLOAT | 0x1U);
159 const auto nan1ValueD = bit_cast<double>(NAN_DOUBLE);
160 const auto nan2ValueD = bit_cast<double>(NAN_DOUBLE | 0x1U);
161
162 auto graph = CreateEmptyGraph();
163 GRAPH(graph)
164 {
165 CONSTANT(0U, nan1ValueF).f32();
166 CONSTANT(1U, nan2ValueF).f32();
167 CONSTANT(2U, nan1ValueD).f64();
168 CONSTANT(3U, nan2ValueD).f64();
169 PARAMETER(4U, 1.0F).f32();
170 PARAMETER(5U, 2.0_D).f64();
171 CONSTANT(8U, 1U); // It is bool True
172 CONSTANT(9U, 0U); // It is bool False
173
174 BASIC_BLOCK(2U, 1U)
175 {
176 // Indexes in InputValue is equal id in graph. Assert at the begin of the function is check that
177 INST(6U, Opcode::Compare)
178 .b()
179 .SrcType(sourceType)
180 .CC(cc)
181 .Inputs(static_cast<size_t>(input0), static_cast<size_t>(input1));
182 INST(7U, Opcode::Return).b().Inputs(6U);
183 }
184 }
185
186 ConstFoldingCompare(&INS(6U));
187 ASSERT_EQ(INS(7U).GetInput(0U).GetInst(), result ? &INS(8U) : &INS(9U));
188 }
189
CheckNegNan(InputValue input,bool isOptimized)190 void CheckNegNan(InputValue input, bool isOptimized)
191 {
192 // Check that position is not changed
193 static_assert(InputValue::NAN1_F == 0U && InputValue::NAN2_F == 1U && InputValue::NAN1_D == 2U &&
194 InputValue::NAN2_D == 3U && InputValue::NUMBER_F == 4U && InputValue::NUMBER_D == 5U);
195
196 const auto nan1ValueF = bit_cast<float>(NAN_FLOAT);
197 const auto nan2ValueF = bit_cast<float>(NAN_FLOAT | 0x1U);
198 const auto nan1ValueD = bit_cast<double>(NAN_DOUBLE);
199 const auto nan2ValueD = bit_cast<double>(NAN_DOUBLE | 0x1U);
200
201 bool isFloat32 = IsFloat32InputValue(input);
202 auto graph = CreateEmptyGraph();
203 GRAPH(graph)
204 {
205 CONSTANT(0U, nan1ValueF).f32();
206 CONSTANT(1U, nan2ValueF).f32();
207 CONSTANT(2U, nan1ValueD).f64();
208 CONSTANT(3U, nan2ValueD).f64();
209 PARAMETER(4U, 1.0F).f32();
210 PARAMETER(5U, 2.0_D).f64();
211
212 BASIC_BLOCK(2U, 1U)
213 {
214 // Indexes in InputValue is equal id in graph. Assert at the begin of the function is check that
215 if (isFloat32) {
216 INST(6U, Opcode::Neg).f32().Inputs(static_cast<size_t>(input));
217 INST(7U, Opcode::Return).f32().Inputs(6U);
218 } else {
219 INST(6U, Opcode::Neg).f64().Inputs(static_cast<size_t>(input));
220 INST(7U, Opcode::Return).f64().Inputs(6U);
221 }
222 }
223 }
224
225 ConstFoldingNeg(&INS(6U));
226 ASSERT_EQ(INS(7U).GetInput(0U).GetInst(), isOptimized ? &INS(input) : &INS(6U));
227 }
228
CheckBinaryMathWithNan(Opcode opc,InputValue input0,InputValue input1,bool isOptimized)229 void CheckBinaryMathWithNan(Opcode opc, InputValue input0, InputValue input1, bool isOptimized)
230 {
231 // Check that position is not changed
232 static_assert(InputValue::NAN1_F == 0U && InputValue::NAN2_F == 1U && InputValue::NAN1_D == 2U &&
233 InputValue::NAN2_D == 3U && InputValue::NUMBER_F == 4U && InputValue::NUMBER_D == 5U);
234
235 const auto nan1ValueF = bit_cast<float>(NAN_FLOAT);
236 const auto nan2ValueF = bit_cast<float>(NAN_FLOAT | 0x1U);
237 const auto nan1ValueD = bit_cast<double>(NAN_DOUBLE);
238 const auto nan2ValueD = bit_cast<double>(NAN_DOUBLE | 0x1U);
239
240 bool isFloat32 = IsFloat32InputValue(input0);
241 auto graph = CreateEmptyGraph();
242 GRAPH(graph)
243 {
244 CONSTANT(0U, nan1ValueF).f32();
245 CONSTANT(1U, nan2ValueF).f32();
246 CONSTANT(2U, nan1ValueD).f64();
247 CONSTANT(3U, nan2ValueD).f64();
248 PARAMETER(4U, 1.0F).f32();
249 PARAMETER(5U, 2.0_D).f64();
250
251 BASIC_BLOCK(2U, 1U)
252 {
253 // Indexes in InputValue is equal id in graph. Assert at the begin of the function is check that
254 if (isFloat32) {
255 INST(6U, opc).f32().Inputs(static_cast<size_t>(input0), static_cast<size_t>(input1));
256 INST(7U, Opcode::Return).f32().Inputs(6U);
257 } else {
258 INST(6U, opc).f64().Inputs(static_cast<size_t>(input0), static_cast<size_t>(input1));
259 INST(7U, Opcode::Return).f64().Inputs(6U);
260 }
261 }
262 }
263 auto func = GetConstFoldingFunc(opc);
264 ASSERT_EQ(func(&INS(6U)), isOptimized);
265 if (isOptimized) {
266 ASSERT_EQ(INS(7U).GetInput(0U).GetInst()->IsConst(), true);
267 ASSERT_EQ(INS(7U).GetInput(0U).GetInst()->CastToConstant()->IsNaNConst(), true);
268 } else {
269 ASSERT_EQ(INS(7U).GetInput(0U).GetInst(), &INS(6U));
270 }
271 }
272
CheckNanBinaryMathManyCases(Opcode opc)273 void CheckNanBinaryMathManyCases(Opcode opc)
274 {
275 ASSERT(opc == Opcode::Mul || opc == Opcode::Div || opc == Opcode::Mod || opc == Opcode::Add ||
276 opc == Opcode::Sub || opc == Opcode::Min || opc == Opcode::Max);
277
278 // opc number and Nan
279 CheckBinaryMathWithNan(opc, InputValue::NAN1_F, InputValue::NUMBER_F, true);
280 CheckBinaryMathWithNan(opc, InputValue::NAN2_F, InputValue::NUMBER_F, true);
281 CheckBinaryMathWithNan(opc, InputValue::NAN1_D, InputValue::NUMBER_D, true);
282 CheckBinaryMathWithNan(opc, InputValue::NAN2_D, InputValue::NUMBER_D, true);
283
284 // opc Nan and number
285 CheckBinaryMathWithNan(opc, InputValue::NUMBER_F, InputValue::NAN1_F, true);
286 CheckBinaryMathWithNan(opc, InputValue::NUMBER_F, InputValue::NAN2_F, true);
287 CheckBinaryMathWithNan(opc, InputValue::NUMBER_D, InputValue::NAN1_D, true);
288 CheckBinaryMathWithNan(opc, InputValue::NUMBER_D, InputValue::NAN2_D, true);
289
290 // opc with same Nan
291 CheckBinaryMathWithNan(opc, InputValue::NAN1_F, InputValue::NAN1_F, true);
292 CheckBinaryMathWithNan(opc, InputValue::NAN2_F, InputValue::NAN2_F, true);
293 CheckBinaryMathWithNan(opc, InputValue::NAN1_D, InputValue::NAN1_D, true);
294 CheckBinaryMathWithNan(opc, InputValue::NAN2_D, InputValue::NAN2_D, true);
295
296 // opc with different Nan
297 CheckBinaryMathWithNan(opc, InputValue::NAN1_F, InputValue::NAN2_F, true);
298 CheckBinaryMathWithNan(opc, InputValue::NAN2_F, InputValue::NAN1_F, true);
299 CheckBinaryMathWithNan(opc, InputValue::NAN1_D, InputValue::NAN2_D, true);
300 CheckBinaryMathWithNan(opc, InputValue::NAN2_D, InputValue::NAN1_D, true);
301
302 CheckBinaryMathWithNan(opc, InputValue::NUMBER_F, InputValue::NUMBER_F, false);
303 CheckBinaryMathWithNan(opc, InputValue::NUMBER_D, InputValue::NUMBER_D, false);
304 }
305
306 private:
IsFloat32InputValue(InputValue input)307 bool IsFloat32InputValue(InputValue input)
308 {
309 switch (input) {
310 case NAN1_F:
311 case NAN2_F:
312 case NUMBER_F:
313 return true;
314 case NAN1_D:
315 case NAN2_D:
316 case NUMBER_D:
317 return false;
318 default:
319 UNREACHABLE();
320 }
321 }
322
GetConstFoldingFunc(Opcode opc)323 ConstFoldingFunc GetConstFoldingFunc(Opcode opc)
324 {
325 switch (opc) {
326 case Opcode::Mul:
327 return ConstFoldingMul;
328 case Opcode::Div:
329 return ConstFoldingDiv;
330 case Opcode::Mod:
331 return ConstFoldingMod;
332 case Opcode::Add:
333 return ConstFoldingAdd;
334 case Opcode::Sub:
335 return ConstFoldingSub;
336 case Opcode::Min:
337 return ConstFoldingMin;
338 case Opcode::Max:
339 return ConstFoldingMax;
340 default:
341 UNREACHABLE();
342 }
343 }
344
345 private:
346 Graph *graph_;
347 };
348
TEST_F(ConstFoldingTest,NegInt64Test)349 TEST_F(ConstFoldingTest, NegInt64Test)
350 {
351 GRAPH(GetGraph())
352 {
353 CONSTANT(0U, UINT64_MAX);
354 BASIC_BLOCK(2U, 1U)
355 {
356 INST(1U, Opcode::Neg).s64().Inputs(0U);
357 INST(2U, Opcode::Return).s64().Inputs(1U);
358 }
359 }
360 int result = 1;
361 ASSERT_EQ(ConstFoldingNeg(&INS(1U)), true);
362 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
363 ASSERT(inst != nullptr);
364 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
365 GraphChecker(GetGraph()).Check();
366 }
367
TEST_F(ConstFoldingTest,NegInt32Test)368 TEST_F(ConstFoldingTest, NegInt32Test)
369 {
370 GRAPH(GetGraph())
371 {
372 CONSTANT(0U, 1U);
373 BASIC_BLOCK(2U, 1U)
374 {
375 INST(1U, Opcode::Neg).s32().Inputs(0U);
376 INST(2U, Opcode::Return).s32().Inputs(1U);
377 }
378 }
379 int32_t result = -1;
380 ASSERT_EQ(ConstFoldingNeg(&INS(1U)), true);
381 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
382 ASSERT(inst != nullptr);
383 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
384 GraphChecker(GetGraph()).Check();
385 }
386
TEST_F(ConstFoldingTest,Constant32NegIntTest)387 TEST_F(ConstFoldingTest, Constant32NegIntTest)
388 {
389 auto graph = CreateEmptyBytecodeGraph();
390 GRAPH(graph)
391 {
392 CONSTANT(0U, 1U);
393 BASIC_BLOCK(2U, 1U)
394 {
395 INST(1U, Opcode::Neg).s32().Inputs(0U);
396 INST(2U, Opcode::Return).s32().Inputs(1U);
397 }
398 }
399 int32_t result = -1;
400 ASSERT_EQ(ConstFoldingNeg(&INS(1U)), true);
401 auto inst = graph->FindConstant(DataType::INT32, result);
402 ASSERT(inst != nullptr);
403 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
404 GraphChecker(graph).Check();
405 }
406
TEST_F(ConstFoldingTest,NegFloatTest)407 TEST_F(ConstFoldingTest, NegFloatTest)
408 {
409 GRAPH(GetGraph())
410 {
411 CONSTANT(0, static_cast<float>(12U));
412 BASIC_BLOCK(2U, 1U)
413 {
414 INST(1U, Opcode::Neg).f32().Inputs(0U);
415 INST(2U, Opcode::Return).f32().Inputs(1U);
416 }
417 }
418 float result = -12.0;
419 ASSERT_EQ(ConstFoldingNeg(&INS(1U)), true);
420 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(result));
421 ASSERT(inst != nullptr);
422 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
423 GraphChecker(GetGraph()).Check();
424 }
425
TEST_F(ConstFoldingTest,NegDoubleTest)426 TEST_F(ConstFoldingTest, NegDoubleTest)
427 {
428 GRAPH(GetGraph())
429 {
430 CONSTANT(0U, 12.0_D);
431 BASIC_BLOCK(2U, 1U)
432 {
433 INST(1U, Opcode::Neg).f64().Inputs(0U);
434 INST(2U, Opcode::Return).f64().Inputs(1U);
435 }
436 }
437 double result = -12.0_D;
438 ASSERT_EQ(ConstFoldingNeg(&INS(1U)), true);
439 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(result));
440 ASSERT(inst != nullptr);
441 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
442 GraphChecker(GetGraph()).Check();
443 }
444
TEST_F(ConstFoldingTest,AbsIntTest)445 TEST_F(ConstFoldingTest, AbsIntTest)
446 {
447 GRAPH(GetGraph())
448 {
449 CONSTANT(0U, -1L);
450 BASIC_BLOCK(2U, 1U)
451 {
452 INST(1U, Opcode::Abs).s64().Inputs(0U);
453 INST(2U, Opcode::Return).s64().Inputs(1U);
454 }
455 }
456 int64_t result = 1;
457 ASSERT_EQ(ConstFoldingAbs(&INS(1U)), true);
458 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
459 ASSERT(inst != nullptr);
460 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
461 GraphChecker(GetGraph()).Check();
462 }
463
TEST_F(ConstFoldingTest,Constant32AbsIntTest)464 TEST_F(ConstFoldingTest, Constant32AbsIntTest)
465 {
466 auto graph = CreateEmptyBytecodeGraph();
467 GRAPH(graph)
468 {
469 CONSTANT(0U, -1L);
470 BASIC_BLOCK(2U, 1U)
471 {
472 INST(1U, Opcode::Abs).s32().Inputs(0U);
473 INST(2U, Opcode::Return).s32().Inputs(1U);
474 }
475 }
476 int64_t result = 1;
477 ASSERT_EQ(ConstFoldingAbs(&INS(1U)), true);
478 auto inst = graph->FindConstant(DataType::INT32, result);
479 ASSERT(inst != nullptr);
480 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
481 GraphChecker(graph).Check();
482 }
483
TEST_F(ConstFoldingTest,AbsFloatTest)484 TEST_F(ConstFoldingTest, AbsFloatTest)
485 {
486 GRAPH(GetGraph())
487 {
488 CONSTANT(0U, static_cast<float>(-12.0F));
489 BASIC_BLOCK(2U, 1U)
490 {
491 INST(1U, Opcode::Abs).f32().Inputs(0U);
492 INST(2U, Opcode::Return).f32().Inputs(1U);
493 }
494 }
495 float result = 12.0F;
496 ASSERT_EQ(ConstFoldingAbs(&INS(1U)), true);
497 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(result));
498 ASSERT(inst != nullptr);
499 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
500 GraphChecker(GetGraph()).Check();
501 }
502
TEST_F(ConstFoldingTest,AbsDoubleTest)503 TEST_F(ConstFoldingTest, AbsDoubleTest)
504 {
505 GRAPH(GetGraph())
506 {
507 CONSTANT(0U, -12.0_D);
508 BASIC_BLOCK(2U, 1U)
509 {
510 INST(1U, Opcode::Abs).f64().Inputs(0U);
511 INST(2U, Opcode::Return).f64().Inputs(1U);
512 }
513 }
514 double result = 12.0_D;
515 ASSERT_EQ(ConstFoldingAbs(&INS(1U)), true);
516 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(result));
517 ASSERT(inst != nullptr);
518 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
519 GraphChecker(GetGraph()).Check();
520 }
521
TEST_F(ConstFoldingTest,NotIntTest)522 TEST_F(ConstFoldingTest, NotIntTest)
523 {
524 GRAPH(GetGraph())
525 {
526 CONSTANT(0U, -12L);
527 BASIC_BLOCK(2U, 1U)
528 {
529 INST(1U, Opcode::Not).s64().Inputs(0U);
530 INST(2U, Opcode::Return).s64().Inputs(1U);
531 }
532 }
533 int result = 11;
534 ASSERT_EQ(ConstFoldingNot(&INS(1U)), true);
535 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
536 ASSERT(inst != nullptr);
537 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
538 GraphChecker(GetGraph()).Check();
539 }
540
TEST_F(ConstFoldingTest,Constant32NotIntTest)541 TEST_F(ConstFoldingTest, Constant32NotIntTest)
542 {
543 auto graph = CreateEmptyBytecodeGraph();
544 GRAPH(graph)
545 {
546 CONSTANT(0U, -12L);
547 BASIC_BLOCK(2U, 1U)
548 {
549 INST(1U, Opcode::Not).s32().Inputs(0U);
550 INST(2U, Opcode::Return).s32().Inputs(1U);
551 }
552 }
553 int result = 11;
554 ASSERT_EQ(ConstFoldingNot(&INS(1U)), true);
555 auto inst = graph->FindConstant(DataType::INT32, result);
556 ASSERT(inst != nullptr);
557 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
558 GraphChecker(graph).Check();
559 }
560
TEST_F(ConstFoldingTest,AddIntTest)561 TEST_F(ConstFoldingTest, AddIntTest)
562 {
563 GRAPH(GetGraph())
564 {
565 CONSTANT(0U, 3U);
566 CONSTANT(1U, -2L);
567 BASIC_BLOCK(2U, 1U)
568 {
569 INST(2U, Opcode::Add).s64().Inputs(0U, 1U);
570 INST(3U, Opcode::Return).s64().Inputs(2U);
571 }
572 }
573 int result = 1;
574 ASSERT_EQ(ConstFoldingAdd(&INS(2U)), true);
575 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
576 ASSERT(inst != nullptr);
577 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
578 GraphChecker(GetGraph()).Check();
579 }
580
TEST_F(ConstFoldingTest,Constant32AddIntTest)581 TEST_F(ConstFoldingTest, Constant32AddIntTest)
582 {
583 auto graph = CreateEmptyBytecodeGraph();
584 GRAPH(graph)
585 {
586 CONSTANT(0U, 3U);
587 CONSTANT(1U, -2L);
588 BASIC_BLOCK(2U, 1U)
589 {
590 INST(2U, Opcode::Add).s32().Inputs(0U, 1U);
591 INST(3U, Opcode::Return).s32().Inputs(2U);
592 }
593 }
594 int result = 1;
595 ASSERT_EQ(ConstFoldingAdd(&INS(2U)), true);
596 auto inst = graph->FindConstant(DataType::INT32, result);
597 ASSERT(inst != nullptr);
598 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
599 GraphChecker(graph).Check();
600 }
601
TEST_F(ConstFoldingTest,AddInt8Test)602 TEST_F(ConstFoldingTest, AddInt8Test)
603 {
604 GRAPH(GetGraph())
605 {
606 CONSTANT(0U, static_cast<uint8_t>(0xffffffffU));
607 CONSTANT(1U, static_cast<uint8_t>(1U));
608 BASIC_BLOCK(2U, 1U)
609 {
610 INST(2U, Opcode::Add).u8().Inputs(0U, 1U);
611 INST(3U, Opcode::Return).u8().Inputs(2U);
612 }
613 }
614 int result = 0;
615 ASSERT_EQ(ConstFoldingAdd(&INS(2U)), true);
616 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
617 ASSERT(inst != nullptr);
618 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
619 GraphChecker(GetGraph()).Check();
620 }
621
TEST_F(ConstFoldingTest,Constant32AddInt8Test)622 TEST_F(ConstFoldingTest, Constant32AddInt8Test)
623 {
624 auto graph = CreateEmptyBytecodeGraph();
625 GRAPH(graph)
626 {
627 CONSTANT(0U, (uint8_t)0xffffffffU);
628 CONSTANT(1U, (uint8_t)1U);
629 BASIC_BLOCK(2U, 1U)
630 {
631 INST(2U, Opcode::Add).u8().Inputs(0U, 1U);
632 INST(3U, Opcode::Return).u8().Inputs(2U);
633 }
634 }
635 int result = 0;
636 ASSERT_EQ(ConstFoldingAdd(&INS(2U)), true);
637 auto inst = graph->FindConstant(DataType::INT32, result);
638 ASSERT(inst != nullptr);
639 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
640 GraphChecker(graph).Check();
641 }
642
TEST_F(ConstFoldingTest,AddFloatTest)643 TEST_F(ConstFoldingTest, AddFloatTest)
644 {
645 GRAPH(GetGraph())
646 {
647 CONSTANT(0U, static_cast<float>(3.0F));
648 CONSTANT(1U, static_cast<float>(-2.0F));
649 BASIC_BLOCK(2U, 1U)
650 {
651 INST(2U, Opcode::Add).f32().Inputs(0U, 1U);
652 INST(3U, Opcode::Return).f32().Inputs(2U);
653 }
654 }
655 float result = 1.0F;
656 ASSERT_EQ(ConstFoldingAdd(&INS(2U)), true);
657 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(result));
658 ASSERT(inst != nullptr);
659 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
660 GraphChecker(GetGraph()).Check();
661 }
662
TEST_F(ConstFoldingTest,AddDoubleTest)663 TEST_F(ConstFoldingTest, AddDoubleTest)
664 {
665 GRAPH(GetGraph())
666 {
667 CONSTANT(0U, 3.0_D);
668 CONSTANT(1U, -2.0_D);
669 BASIC_BLOCK(2U, 1U)
670 {
671 INST(2U, Opcode::Add).f64().Inputs(0U, 1U);
672 INST(3U, Opcode::Return).f64().Inputs(2U);
673 }
674 }
675 double result = 1.0;
676 ASSERT_EQ(ConstFoldingAdd(&INS(2U)), true);
677 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(result));
678 ASSERT(inst != nullptr);
679 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
680 GraphChecker(GetGraph()).Check();
681 }
682
TEST_F(ConstFoldingTest,SubIntTest)683 TEST_F(ConstFoldingTest, SubIntTest)
684 {
685 GRAPH(GetGraph())
686 {
687 CONSTANT(0U, 0U);
688 CONSTANT(1U, 1U);
689 BASIC_BLOCK(2U, 1U)
690 {
691 INST(2U, Opcode::Sub).s8().Inputs(0U, 1U);
692 INST(3U, Opcode::Return).s8().Inputs(2U);
693 }
694 }
695 int result = 0xffffffff;
696 ASSERT_EQ(ConstFoldingSub(&INS(2U)), true);
697 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
698 ASSERT(inst != nullptr);
699 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
700 GraphChecker(GetGraph()).Check();
701 }
702
TEST_F(ConstFoldingTest,Constant32SubIntTest)703 TEST_F(ConstFoldingTest, Constant32SubIntTest)
704 {
705 auto graph = CreateEmptyBytecodeGraph();
706 GRAPH(graph)
707 {
708 CONSTANT(0U, 0U);
709 CONSTANT(1U, 1U);
710 BASIC_BLOCK(2U, 1U)
711 {
712 INST(2U, Opcode::Sub).s8().Inputs(0U, 1U);
713 INST(3U, Opcode::Return).s8().Inputs(2U);
714 }
715 }
716 int result = 0xffffffff;
717 ASSERT_EQ(ConstFoldingSub(&INS(2U)), true);
718 auto inst = graph->FindConstant(DataType::INT32, result);
719 ASSERT(inst != nullptr);
720 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
721 GraphChecker(graph).Check();
722 }
723
TEST_F(ConstFoldingTest,SubUIntTest)724 TEST_F(ConstFoldingTest, SubUIntTest)
725 {
726 GRAPH(GetGraph())
727 {
728 CONSTANT(0U, 0U);
729 CONSTANT(1U, 1U);
730 BASIC_BLOCK(2U, 1U)
731 {
732 INST(2U, Opcode::Sub).u8().Inputs(0U, 1U);
733 INST(3U, Opcode::Return).u8().Inputs(2U);
734 }
735 }
736 int result = 0xff;
737 ASSERT_EQ(ConstFoldingSub(&INS(2U)), true);
738 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
739 ASSERT(inst != nullptr);
740 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
741 GraphChecker(GetGraph()).Check();
742 }
743
TEST_F(ConstFoldingTest,Constant32SubUIntTest)744 TEST_F(ConstFoldingTest, Constant32SubUIntTest)
745 {
746 auto graph = CreateEmptyBytecodeGraph();
747 GRAPH(graph)
748 {
749 CONSTANT(0U, 0U);
750 CONSTANT(1U, 1U);
751 BASIC_BLOCK(2U, 1U)
752 {
753 INST(2U, Opcode::Sub).u8().Inputs(0U, 1U);
754 INST(3U, Opcode::Return).u8().Inputs(2U);
755 }
756 }
757 int result = 0xff;
758 ASSERT_EQ(ConstFoldingSub(&INS(2U)), true);
759 auto inst = graph->FindConstant(DataType::INT32, result);
760 ASSERT(inst != nullptr);
761 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
762 GraphChecker(graph).Check();
763 }
764
TEST_F(ConstFoldingTest,SubFloatTest)765 TEST_F(ConstFoldingTest, SubFloatTest)
766 {
767 GRAPH(GetGraph())
768 {
769 CONSTANT(0U, static_cast<float>(3.0F));
770 CONSTANT(1U, static_cast<float>(2.0F));
771 BASIC_BLOCK(2U, 1U)
772 {
773 INST(2U, Opcode::Sub).f32().Inputs(0U, 1U);
774 INST(3U, Opcode::Return).f32().Inputs(2U);
775 }
776 }
777 float result = 1.0F;
778 ASSERT_EQ(ConstFoldingSub(&INS(2U)), true);
779 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(result));
780 ASSERT(inst != nullptr);
781 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
782 GraphChecker(GetGraph()).Check();
783 }
784
TEST_F(ConstFoldingTest,SubDoubleTest)785 TEST_F(ConstFoldingTest, SubDoubleTest)
786 {
787 GRAPH(GetGraph())
788 {
789 CONSTANT(0U, 3.0_D);
790 CONSTANT(1U, 2.0_D);
791 BASIC_BLOCK(2U, 1U)
792 {
793 INST(2U, Opcode::Sub).f64().Inputs(0U, 1U);
794 INST(3U, Opcode::Return).f64().Inputs(2U);
795 }
796 }
797 double result = 1.0;
798 ASSERT_EQ(ConstFoldingSub(&INS(2U)), true);
799 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(result));
800 ASSERT(inst != nullptr);
801 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
802 GraphChecker(GetGraph()).Check();
803 }
804
TEST_F(ConstFoldingTest,SubTestIntXsubX)805 TEST_F(ConstFoldingTest, SubTestIntXsubX)
806 {
807 GRAPH(GetGraph())
808 {
809 PARAMETER(0U, 0U).u64();
810 BASIC_BLOCK(2U, 1U)
811 {
812 INST(1U, Opcode::Sub).u64().Inputs(0U, 0U);
813 INST(2U, Opcode::Return).u64().Inputs(1U);
814 }
815 }
816 ASSERT_EQ(ConstFoldingSub(&INS(1U)), true);
817 int result = 0;
818 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
819 ASSERT(inst != nullptr);
820 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
821 GraphChecker(GetGraph()).Check();
822 }
823
TEST_F(ConstFoldingTest,Constant32SubTestIntXsubX)824 TEST_F(ConstFoldingTest, Constant32SubTestIntXsubX)
825 {
826 auto graph = CreateEmptyBytecodeGraph();
827 GRAPH(graph)
828 {
829 PARAMETER(0U, 0U).u32();
830 BASIC_BLOCK(2U, 1U)
831 {
832 INST(1U, Opcode::Sub).u32().Inputs(0U, 0U);
833 INST(2U, Opcode::Return).u32().Inputs(1U);
834 }
835 }
836 ASSERT_EQ(ConstFoldingSub(&INS(1U)), true);
837 int result = 0;
838 auto inst = graph->FindConstant(DataType::INT32, result);
839 ASSERT(inst != nullptr);
840 ASSERT_EQ(INS(2U).GetInput(0U).GetInst(), inst);
841 GraphChecker(graph).Check();
842 }
843
TEST_F(ConstFoldingTest,SubTestDoubleXsubX)844 TEST_F(ConstFoldingTest, SubTestDoubleXsubX)
845 {
846 GRAPH(GetGraph())
847 {
848 PARAMETER(0U, 0U).f64();
849 BASIC_BLOCK(2U, 1U)
850 {
851 INST(1U, Opcode::Sub).f64().Inputs(0U, 0U);
852 INST(2U, Opcode::Return).f64().Inputs(1U);
853 }
854 }
855 // the optimization "x-x -> 0" is not applicable for floating point values
856 ASSERT_EQ(ConstFoldingSub(&INS(1U)), false);
857 }
858
TEST_F(ConstFoldingTest,MulIntTest)859 TEST_F(ConstFoldingTest, MulIntTest)
860 {
861 GRAPH(GetGraph())
862 {
863 CONSTANT(0U, 3U);
864 CONSTANT(1U, 2U);
865 BASIC_BLOCK(2U, 1U)
866 {
867 INST(2U, Opcode::Mul).u64().Inputs(0U, 1U);
868 INST(3U, Opcode::Return).u64().Inputs(2U);
869 }
870 }
871 int result = 6;
872 ASSERT_EQ(ConstFoldingMul(&INS(2U)), true);
873 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
874 ASSERT(inst != nullptr);
875 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
876 GraphChecker(GetGraph()).Check();
877 }
878
TEST_F(ConstFoldingTest,MulWithNan)879 TEST_F(ConstFoldingTest, MulWithNan)
880 {
881 CheckNanBinaryMathManyCases(Opcode::Mul);
882 }
883
TEST_F(ConstFoldingTest,DivWithNan)884 TEST_F(ConstFoldingTest, DivWithNan)
885 {
886 CheckNanBinaryMathManyCases(Opcode::Div);
887 }
888
TEST_F(ConstFoldingTest,ModWithNan)889 TEST_F(ConstFoldingTest, ModWithNan)
890 {
891 CheckNanBinaryMathManyCases(Opcode::Mod);
892 }
893
TEST_F(ConstFoldingTest,AddWithNan)894 TEST_F(ConstFoldingTest, AddWithNan)
895 {
896 CheckNanBinaryMathManyCases(Opcode::Div);
897 }
898
TEST_F(ConstFoldingTest,SubWithNan)899 TEST_F(ConstFoldingTest, SubWithNan)
900 {
901 CheckNanBinaryMathManyCases(Opcode::Mod);
902 }
903
TEST_F(ConstFoldingTest,MinWithNan)904 TEST_F(ConstFoldingTest, MinWithNan)
905 {
906 CheckNanBinaryMathManyCases(Opcode::Min);
907 }
908
TEST_F(ConstFoldingTest,MaxWithNan)909 TEST_F(ConstFoldingTest, MaxWithNan)
910 {
911 CheckNanBinaryMathManyCases(Opcode::Max);
912 }
913
TEST_F(ConstFoldingTest,Constant32MulIntTest)914 TEST_F(ConstFoldingTest, Constant32MulIntTest)
915 {
916 auto graph = CreateEmptyBytecodeGraph();
917 GRAPH(graph)
918 {
919 CONSTANT(0U, 3U);
920 CONSTANT(1U, 2U);
921 BASIC_BLOCK(2U, 1U)
922 {
923 INST(2U, Opcode::Mul).u32().Inputs(0U, 1U);
924 INST(3U, Opcode::Return).u32().Inputs(2U);
925 }
926 }
927 int result = 6;
928 ASSERT_EQ(ConstFoldingMul(&INS(2U)), true);
929 auto inst = graph->FindConstant(DataType::INT32, result);
930 ASSERT(inst != nullptr);
931 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
932 GraphChecker(graph).Check();
933 }
934
TEST_F(ConstFoldingTest,MulFloatTest)935 TEST_F(ConstFoldingTest, MulFloatTest)
936 {
937 GRAPH(GetGraph())
938 {
939 CONSTANT(0U, static_cast<float>(3.0F));
940 CONSTANT(1U, static_cast<float>(2.0F));
941 BASIC_BLOCK(2U, 1U)
942 {
943 INST(2U, Opcode::Mul).f32().Inputs(0U, 1U);
944 INST(3U, Opcode::Return).f32().Inputs(2U);
945 }
946 }
947 float result = 6.0F;
948 ASSERT_EQ(ConstFoldingMul(&INS(2U)), true);
949 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(result));
950 ASSERT(inst != nullptr);
951 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
952 GraphChecker(GetGraph()).Check();
953 }
954
TEST_F(ConstFoldingTest,MulDoubleTest)955 TEST_F(ConstFoldingTest, MulDoubleTest)
956 {
957 GRAPH(GetGraph())
958 {
959 CONSTANT(0U, 3.0_D);
960 CONSTANT(1U, 2.0_D);
961 BASIC_BLOCK(2U, 1U)
962 {
963 INST(2U, Opcode::Mul).f64().Inputs(0U, 1U);
964 INST(3U, Opcode::Return).f64().Inputs(2U);
965 }
966 }
967 double result = 6.0_D;
968 ASSERT_EQ(ConstFoldingMul(&INS(2U)), true);
969 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(result));
970 ASSERT(inst != nullptr);
971 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
972 GraphChecker(GetGraph()).Check();
973 }
974
TEST_F(ConstFoldingTest,DivIntTest)975 TEST_F(ConstFoldingTest, DivIntTest)
976 {
977 GRAPH(GetGraph())
978 {
979 CONSTANT(0U, 3U);
980 CONSTANT(1U, 2U);
981 BASIC_BLOCK(2U, 1U)
982 {
983 INST(2U, Opcode::Div).u64().Inputs(0U, 1U);
984 INST(3U, Opcode::Return).u64().Inputs(2U);
985 }
986 }
987 int result = 1;
988 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), true);
989 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
990 ASSERT(inst != nullptr);
991 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
992 GraphChecker(GetGraph()).Check();
993 }
994
TEST_F(ConstFoldingTest,Constant32DivIntTest)995 TEST_F(ConstFoldingTest, Constant32DivIntTest)
996 {
997 auto graph = CreateEmptyBytecodeGraph();
998 GRAPH(graph)
999 {
1000 CONSTANT(0U, 3U);
1001 CONSTANT(1U, 2U);
1002 BASIC_BLOCK(2U, 1U)
1003 {
1004 INST(2U, Opcode::Div).u32().Inputs(0U, 1U);
1005 INST(3U, Opcode::Return).u32().Inputs(2U);
1006 }
1007 }
1008 int result = 1;
1009 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), true);
1010 auto inst = graph->FindConstant(DataType::INT32, result);
1011 ASSERT(inst != nullptr);
1012 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1013 GraphChecker(graph).Check();
1014 }
1015
TEST_F(ConstFoldingTest,DivIntTest1)1016 TEST_F(ConstFoldingTest, DivIntTest1)
1017 {
1018 GRAPH(GetGraph())
1019 {
1020 CONSTANT(0U, 0xffffffff80000000U);
1021 CONSTANT(1U, 0xffffffffffffffffU);
1022 BASIC_BLOCK(2U, 1U)
1023 {
1024 INST(2U, Opcode::Div).s32().Inputs(0U, 1U);
1025 INST(3U, Opcode::Return).s32().Inputs(2U);
1026 }
1027 }
1028 int32_t result = 0x80000000;
1029 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), true);
1030 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1031 ASSERT(inst != nullptr);
1032 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1033 GraphChecker(GetGraph()).Check();
1034 }
1035
TEST_F(ConstFoldingTest,Constant32DivIntTest1)1036 TEST_F(ConstFoldingTest, Constant32DivIntTest1)
1037 {
1038 auto graph = CreateEmptyBytecodeGraph();
1039 GRAPH(graph)
1040 {
1041 CONSTANT(0U, 0xffffffff80000000U);
1042 CONSTANT(1U, 0xffffffffffffffffU);
1043 BASIC_BLOCK(2U, 1U)
1044 {
1045 INST(2U, Opcode::Div).s32().Inputs(0U, 1U);
1046 INST(3U, Opcode::Return).s32().Inputs(2U);
1047 }
1048 }
1049 int32_t result = 0x80000000;
1050 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), true);
1051 auto inst = graph->FindConstant(DataType::INT32, result);
1052 ASSERT(inst != nullptr);
1053 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1054 GraphChecker(graph).Check();
1055 }
1056
TEST_F(ConstFoldingTest,DivIntTest2)1057 TEST_F(ConstFoldingTest, DivIntTest2)
1058 {
1059 GRAPH(GetGraph())
1060 {
1061 CONSTANT(0U, 0x8000000000000000U);
1062 CONSTANT(1U, 0xffffffffffffffffU);
1063 BASIC_BLOCK(2U, 1U)
1064 {
1065 INST(2U, Opcode::Div).s32().Inputs(0U, 1U);
1066 INST(3U, Opcode::Return).s32().Inputs(2U);
1067 }
1068 }
1069 int64_t result = 0x8000000000000000;
1070 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), true);
1071 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1072 ASSERT(inst != nullptr);
1073 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1074 GraphChecker(GetGraph()).Check();
1075 }
1076
TEST_F(ConstFoldingTest,Constant32DivIntTest2)1077 TEST_F(ConstFoldingTest, Constant32DivIntTest2)
1078 {
1079 auto graph = CreateEmptyBytecodeGraph();
1080 GRAPH(graph)
1081 {
1082 CONSTANT(0U, 0x80000000U);
1083 CONSTANT(1U, 0xffffffffU);
1084 BASIC_BLOCK(2U, 1U)
1085 {
1086 INST(2U, Opcode::Div).s32().Inputs(0U, 1U);
1087 INST(3U, Opcode::Return).s32().Inputs(2U);
1088 }
1089 }
1090 int32_t result = 0x80000000;
1091 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), true);
1092 auto inst = graph->FindConstant(DataType::INT32, result);
1093 ASSERT(inst != nullptr);
1094 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1095 GraphChecker(graph).Check();
1096 }
1097
TEST_F(ConstFoldingTest,UDivIntTest)1098 TEST_F(ConstFoldingTest, UDivIntTest)
1099 {
1100 GRAPH(GetGraph())
1101 {
1102 CONSTANT(0U, 0xffffffff80000000U);
1103 CONSTANT(1U, 1U);
1104 BASIC_BLOCK(2U, 1U)
1105 {
1106 INST(2U, Opcode::Div).u32().Inputs(0U, 1U);
1107 INST(3U, Opcode::Return).u32().Inputs(2U);
1108 }
1109 }
1110 int64_t result = 0x80000000;
1111 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), true);
1112 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1113 ASSERT(inst != nullptr);
1114 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1115 GraphChecker(GetGraph()).Check();
1116 }
1117
TEST_F(ConstFoldingTest,Constant32UDivIntTest)1118 TEST_F(ConstFoldingTest, Constant32UDivIntTest)
1119 {
1120 auto graph = CreateEmptyBytecodeGraph();
1121 GRAPH(graph)
1122 {
1123 CONSTANT(0U, 0xffffffff80000000U);
1124 CONSTANT(1U, 1U);
1125 BASIC_BLOCK(2U, 1U)
1126 {
1127 INST(2U, Opcode::Div).u32().Inputs(0U, 1U);
1128 INST(3U, Opcode::Return).u32().Inputs(2U);
1129 }
1130 }
1131 int64_t result = 0x80000000;
1132 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), true);
1133 auto inst = graph->FindConstant(DataType::INT32, result);
1134 ASSERT(inst != nullptr);
1135 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1136 GraphChecker(graph).Check();
1137 }
1138
TEST_F(ConstFoldingTest,DivFloatTest)1139 TEST_F(ConstFoldingTest, DivFloatTest)
1140 {
1141 GRAPH(GetGraph())
1142 {
1143 CONSTANT(0U, static_cast<float>(3.0F));
1144 CONSTANT(1U, static_cast<float>(2.0F));
1145 BASIC_BLOCK(2U, 1U)
1146 {
1147 INST(2U, Opcode::Div).f32().Inputs(0U, 1U);
1148 INST(3U, Opcode::Return).f32().Inputs(2U);
1149 }
1150 }
1151 float result = 1.5F;
1152 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), true);
1153 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(result));
1154 ASSERT(inst != nullptr);
1155 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1156 GraphChecker(GetGraph()).Check();
1157 }
1158
TEST_F(ConstFoldingTest,DivDoubleTest)1159 TEST_F(ConstFoldingTest, DivDoubleTest)
1160 {
1161 GRAPH(GetGraph())
1162 {
1163 CONSTANT(0U, 3.0_D);
1164 CONSTANT(1U, 2.0_D);
1165 BASIC_BLOCK(2U, 1U)
1166 {
1167 INST(2U, Opcode::Div).f64().Inputs(0U, 1U);
1168 INST(3U, Opcode::Return).f64().Inputs(2U);
1169 }
1170 }
1171 double result = 1.5_D;
1172 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), true);
1173 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(result));
1174 ASSERT(inst != nullptr);
1175 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1176 GraphChecker(GetGraph()).Check();
1177 }
1178
TEST_F(ConstFoldingTest,MinIntTest)1179 TEST_F(ConstFoldingTest, MinIntTest)
1180 {
1181 GRAPH(GetGraph())
1182 {
1183 CONSTANT(0U, 3U);
1184 CONSTANT(1U, 2U);
1185 BASIC_BLOCK(2U, 1U)
1186 {
1187 INST(2U, Opcode::Min).u64().Inputs(0U, 1U);
1188 INST(3U, Opcode::Return).u64().Inputs(2U);
1189 }
1190 }
1191 int result = 2;
1192 ASSERT_EQ(ConstFoldingMin(&INS(2U)), true);
1193 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1194 ASSERT(inst != nullptr);
1195 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1196 GraphChecker(GetGraph()).Check();
1197 }
1198
TEST_F(ConstFoldingTest,MinFloatTest)1199 TEST_F(ConstFoldingTest, MinFloatTest)
1200 {
1201 GRAPH(GetGraph())
1202 {
1203 CONSTANT(0U, static_cast<float>(3.0F));
1204 CONSTANT(1U, static_cast<float>(2.0F));
1205 BASIC_BLOCK(2U, 1U)
1206 {
1207 INST(2U, Opcode::Min).f32().Inputs(0U, 1U);
1208 INST(3U, Opcode::Return).f32().Inputs(2U);
1209 }
1210 }
1211 float result = 2.0F;
1212 ASSERT_EQ(ConstFoldingMin(&INS(2U)), true);
1213 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(result));
1214 ASSERT(inst != nullptr);
1215 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1216 GraphChecker(GetGraph()).Check();
1217 }
1218
TEST_F(ConstFoldingTest,MinFloatNegativeZeroTest)1219 TEST_F(ConstFoldingTest, MinFloatNegativeZeroTest)
1220 {
1221 GRAPH(GetGraph())
1222 {
1223 CONSTANT(0U, -0.0F);
1224 CONSTANT(1U, +0.0F);
1225 BASIC_BLOCK(2U, 1U)
1226 {
1227 INST(2U, Opcode::Min).f32().Inputs(0U, 1U);
1228 INST(3U, Opcode::Min).f32().Inputs(1U, 0U);
1229 INST(4U, Opcode::Min).f32().Inputs(2U, 3U);
1230 INST(5U, Opcode::Return).f32().Inputs(4U);
1231 }
1232 }
1233 ASSERT_EQ(ConstFoldingMin(&INS(2U)), true);
1234 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(-0.0));
1235 ASSERT(inst != nullptr);
1236 ASSERT_EQ(INS(4U).GetInput(0U).GetInst(), inst);
1237 ASSERT_EQ(ConstFoldingMin(&INS(3U)), true);
1238 ASSERT_EQ(INS(4U).GetInput(1U).GetInst(), inst);
1239 GraphChecker(GetGraph()).Check();
1240 }
1241
TEST_F(ConstFoldingTest,MinFloatNaNTest)1242 TEST_F(ConstFoldingTest, MinFloatNaNTest)
1243 {
1244 GRAPH(GetGraph())
1245 {
1246 CONSTANT(0U, std::numeric_limits<float>::quiet_NaN());
1247 CONSTANT(1U, 1.3F);
1248 BASIC_BLOCK(2U, 1U)
1249 {
1250 INST(2U, Opcode::Min).f32().Inputs(0U, 1U);
1251 INST(3U, Opcode::Min).f32().Inputs(1U, 0U);
1252 INST(4U, Opcode::Min).f32().Inputs(2U, 3U);
1253 INST(5U, Opcode::Return).f32().Inputs(4U);
1254 }
1255 }
1256 ASSERT_EQ(ConstFoldingMin(&INS(2U)), true);
1257 auto inst =
1258 GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(std::numeric_limits<float>::quiet_NaN()));
1259 ASSERT(inst != nullptr);
1260 ASSERT_EQ(INS(4U).GetInput(0U).GetInst(), inst);
1261 ASSERT_EQ(ConstFoldingMin(&INS(3U)), true);
1262 ASSERT_EQ(INS(4U).GetInput(1U).GetInst(), inst);
1263 GraphChecker(GetGraph()).Check();
1264 }
1265
TEST_F(ConstFoldingTest,MinDoubleTest)1266 TEST_F(ConstFoldingTest, MinDoubleTest)
1267 {
1268 GRAPH(GetGraph())
1269 {
1270 CONSTANT(0U, 3.0_D);
1271 CONSTANT(1U, 2.0_D);
1272 BASIC_BLOCK(2U, 1U)
1273 {
1274 INST(2U, Opcode::Min).f64().Inputs(0U, 1U);
1275 INST(3U, Opcode::Return).f64().Inputs(2U);
1276 }
1277 }
1278 double result = 2.0_D;
1279 ASSERT_EQ(ConstFoldingMin(&INS(2U)), true);
1280 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(result));
1281 ASSERT(inst != nullptr);
1282 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1283 GraphChecker(GetGraph()).Check();
1284 }
1285
TEST_F(ConstFoldingTest,MinDoubleNegativeZeroTest)1286 TEST_F(ConstFoldingTest, MinDoubleNegativeZeroTest)
1287 {
1288 GRAPH(GetGraph())
1289 {
1290 CONSTANT(0U, -0.0);
1291 CONSTANT(1U, +0.0);
1292 BASIC_BLOCK(2U, 1U)
1293 {
1294 INST(2U, Opcode::Min).f64().Inputs(0U, 1U);
1295 INST(3U, Opcode::Min).f64().Inputs(1U, 0U);
1296 INST(4U, Opcode::Min).f64().Inputs(2U, 3U);
1297 INST(5U, Opcode::Return).f64().Inputs(4U);
1298 }
1299 }
1300 ASSERT_EQ(ConstFoldingMin(&INS(2U)), true);
1301 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(-0.0));
1302 ASSERT(inst != nullptr);
1303 ASSERT_EQ(INS(4U).GetInput(0U).GetInst(), inst);
1304 ASSERT_EQ(ConstFoldingMin(&INS(3U)), true);
1305 ASSERT_EQ(INS(4U).GetInput(1U).GetInst(), inst);
1306 GraphChecker(GetGraph()).Check();
1307 }
1308
TEST_F(ConstFoldingTest,MinDoubleNaNTest)1309 TEST_F(ConstFoldingTest, MinDoubleNaNTest)
1310 {
1311 GRAPH(GetGraph())
1312 {
1313 CONSTANT(0U, std::numeric_limits<double>::quiet_NaN());
1314 CONSTANT(1U, 1.3_D);
1315 BASIC_BLOCK(2U, 1U)
1316 {
1317 INST(2U, Opcode::Min).f64().Inputs(0U, 1U);
1318 INST(3U, Opcode::Min).f64().Inputs(1U, 0U);
1319 INST(4U, Opcode::Min).f64().Inputs(2U, 3U);
1320 INST(5U, Opcode::Return).f64().Inputs(4U);
1321 }
1322 }
1323 ASSERT_EQ(ConstFoldingMin(&INS(2U)), true);
1324 auto inst = GetGraph()->FindConstant(DataType::FLOAT64,
1325 bit_cast<uint64_t, double>(std::numeric_limits<double>::quiet_NaN()));
1326 ASSERT(inst != nullptr);
1327 ASSERT_EQ(INS(4U).GetInput(0U).GetInst(), inst);
1328 ASSERT_EQ(ConstFoldingMin(&INS(3U)), true);
1329 ASSERT_EQ(INS(4U).GetInput(1U).GetInst(), inst);
1330 GraphChecker(GetGraph()).Check();
1331 }
1332
TEST_F(ConstFoldingTest,CompareFloatNan)1333 TEST_F(ConstFoldingTest, CompareFloatNan)
1334 {
1335 // Not equal number and NaN
1336 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN1_F, InputValue::NUMBER_F, ConditionCode::CC_NE, true);
1337 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN2_F, InputValue::NUMBER_F, ConditionCode::CC_NE, true);
1338 // Not equal NaN and number
1339 CheckCompareWithNan(DataType::FLOAT32, InputValue::NUMBER_F, InputValue::NAN1_F, ConditionCode::CC_NE, true);
1340 CheckCompareWithNan(DataType::FLOAT32, InputValue::NUMBER_F, InputValue::NAN2_F, ConditionCode::CC_NE, true);
1341 // Equal with different NaN
1342 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN1_F, InputValue::NAN2_F, ConditionCode::CC_NE, true);
1343 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN2_F, InputValue::NAN1_F, ConditionCode::CC_NE, true);
1344 // Not equal with same NaN
1345 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN1_F, InputValue::NAN1_F, ConditionCode::CC_NE, true);
1346 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN2_F, InputValue::NAN2_F, ConditionCode::CC_NE, true);
1347
1348 // Cases CC_EQ, CC_LT, CC_LE, CC_GT, CC_GE always return false
1349 std::array<ConditionCode, 5U> allCcWithFalse = {CC_EQ, CC_LT, CC_LE, CC_GT, CC_GE};
1350 for (auto cc : allCcWithFalse) {
1351 // Equal with different NaN
1352 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN1_F, InputValue::NAN2_F, cc, false);
1353 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN2_F, InputValue::NAN1_F, cc, false);
1354 // Equal with same NaN
1355 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN1_F, InputValue::NAN1_F, cc, false);
1356 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN2_F, InputValue::NAN2_F, cc, false);
1357
1358 CheckCompareWithNan(DataType::FLOAT32, InputValue::NUMBER_F, InputValue::NAN1_F, cc, false);
1359 CheckCompareWithNan(DataType::FLOAT32, InputValue::NUMBER_F, InputValue::NAN2_F, cc, false);
1360 // Equal with NaN and number
1361 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN1_F, InputValue::NUMBER_F, cc, false);
1362 CheckCompareWithNan(DataType::FLOAT32, InputValue::NAN2_F, InputValue::NUMBER_F, cc, false);
1363 }
1364 }
1365
TEST_F(ConstFoldingTest,CompareDoubleNan)1366 TEST_F(ConstFoldingTest, CompareDoubleNan)
1367 {
1368 // Not equal number and NaN
1369 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN1_D, InputValue::NUMBER_D, ConditionCode::CC_NE, true);
1370 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN2_D, InputValue::NUMBER_D, ConditionCode::CC_NE, true);
1371 // Not equal NaN and number
1372 CheckCompareWithNan(DataType::FLOAT64, InputValue::NUMBER_D, InputValue::NAN1_D, ConditionCode::CC_NE, true);
1373 CheckCompareWithNan(DataType::FLOAT64, InputValue::NUMBER_D, InputValue::NAN2_D, ConditionCode::CC_NE, true);
1374 // Equal with different NaN
1375 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN1_D, InputValue::NAN2_D, ConditionCode::CC_NE, true);
1376 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN2_D, InputValue::NAN1_D, ConditionCode::CC_NE, true);
1377 // Not equal with same NaN
1378 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN1_D, InputValue::NAN1_D, ConditionCode::CC_NE, true);
1379 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN2_D, InputValue::NAN2_D, ConditionCode::CC_NE, true);
1380
1381 // Cases CC_EQ, CC_LT, CC_LE, CC_GT, CC_GE always return false
1382 std::array<ConditionCode, 5U> allCcWithFalse = {CC_EQ, CC_LT, CC_LE, CC_GT, CC_GE};
1383 for (auto cc : allCcWithFalse) {
1384 // Equal with different NaN
1385 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN1_D, InputValue::NAN2_D, cc, false);
1386 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN2_D, InputValue::NAN1_D, cc, false);
1387 // Equal with same NaN
1388 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN1_D, InputValue::NAN1_D, cc, false);
1389 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN2_D, InputValue::NAN2_D, cc, false);
1390
1391 CheckCompareWithNan(DataType::FLOAT64, InputValue::NUMBER_D, InputValue::NAN1_D, cc, false);
1392 CheckCompareWithNan(DataType::FLOAT64, InputValue::NUMBER_D, InputValue::NAN2_D, cc, false);
1393 // Equal with NaN and number
1394 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN1_D, InputValue::NUMBER_D, cc, false);
1395 CheckCompareWithNan(DataType::FLOAT64, InputValue::NAN2_D, InputValue::NUMBER_D, cc, false);
1396 }
1397 }
1398
TEST_F(ConstFoldingTest,CmpNan)1399 TEST_F(ConstFoldingTest, CmpNan)
1400 {
1401 const auto nan1ValueF = bit_cast<float>(NAN_FLOAT);
1402 const auto nan1ValueD = bit_cast<double>(NAN_DOUBLE);
1403
1404 auto graph = CreateEmptyGraph();
1405 GRAPH(graph)
1406 {
1407 CONSTANT(0U, nan1ValueF).f32();
1408 CONSTANT(2U, nan1ValueD).f64();
1409 PARAMETER(4U, 1.0F).f32();
1410 PARAMETER(5U, 2.0_D).f64();
1411 CONSTANT(8U, 1L); // It is bool True
1412 CONSTANT(9U, -1L); // It is bool False
1413
1414 BASIC_BLOCK(2U, 1U)
1415 {
1416 // Replace with constant 1
1417 INST(10U, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT64).Fcmpg(true).Inputs(2U, 5U);
1418 INST(11U, Opcode::Neg).s32().Inputs(10U);
1419
1420 // Replace with constant -1
1421 INST(12U, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT64).Fcmpg(false).Inputs(2U, 5U);
1422 INST(13U, Opcode::Neg).s32().Inputs(12U);
1423
1424 // Replace with constant 1
1425 INST(14U, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT32).Fcmpg(true).Inputs(0U, 4U);
1426 INST(15U, Opcode::Neg).s32().Inputs(14U);
1427
1428 // Replace with constant -1
1429 INST(16U, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT32).Fcmpg(false).Inputs(0U, 4U);
1430 INST(17U, Opcode::Neg).s32().Inputs(16U);
1431 INST(7U, Opcode::Return).b().Inputs(8U);
1432 }
1433 }
1434
1435 ConstFoldingCmp(&INS(10U));
1436 ConstFoldingCmp(&INS(12U));
1437 ConstFoldingCmp(&INS(14U));
1438 ConstFoldingCmp(&INS(16U));
1439 ASSERT_EQ(INS(11U).GetInput(0U).GetInst(), &INS(8U));
1440 ASSERT_EQ(INS(13U).GetInput(0U).GetInst(), &INS(9U));
1441 ASSERT_EQ(INS(15U).GetInput(0U).GetInst(), &INS(8U));
1442 ASSERT_EQ(INS(17U).GetInput(0U).GetInst(), &INS(9U));
1443 }
1444
TEST_F(ConstFoldingTest,NegationNan)1445 TEST_F(ConstFoldingTest, NegationNan)
1446 {
1447 CheckNegNan(InputValue::NAN1_F, true);
1448 CheckNegNan(InputValue::NAN2_F, true);
1449 CheckNegNan(InputValue::NUMBER_F, false);
1450 CheckNegNan(InputValue::NAN1_D, true);
1451 CheckNegNan(InputValue::NAN2_D, true);
1452 CheckNegNan(InputValue::NUMBER_D, false);
1453 }
1454
TEST_F(ConstFoldingTest,MaxIntTest)1455 TEST_F(ConstFoldingTest, MaxIntTest)
1456 {
1457 GRAPH(GetGraph())
1458 {
1459 CONSTANT(0U, 3U);
1460 CONSTANT(1U, 2U);
1461 BASIC_BLOCK(2U, 1U)
1462 {
1463 INST(2U, Opcode::Max).u64().Inputs(0U, 1U);
1464 INST(3U, Opcode::Return).u64().Inputs(2U);
1465 }
1466 }
1467 int result = 3;
1468 ASSERT_EQ(ConstFoldingMax(&INS(2U)), true);
1469 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1470 ASSERT(inst != nullptr);
1471 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1472 GraphChecker(GetGraph()).Check();
1473 }
1474
TEST_F(ConstFoldingTest,MaxFloatTest)1475 TEST_F(ConstFoldingTest, MaxFloatTest)
1476 {
1477 GRAPH(GetGraph())
1478 {
1479 CONSTANT(0U, static_cast<float>(3.0F));
1480 CONSTANT(1U, static_cast<float>(2.0F));
1481 BASIC_BLOCK(2U, 1U)
1482 {
1483 INST(2U, Opcode::Max).f32().Inputs(0U, 1U);
1484 INST(3U, Opcode::Return).f32().Inputs(2U);
1485 }
1486 }
1487 float result = 3.0F;
1488 ASSERT_EQ(ConstFoldingMax(&INS(2U)), true);
1489 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(result));
1490 ASSERT(inst != nullptr);
1491 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1492 GraphChecker(GetGraph()).Check();
1493 }
1494
TEST_F(ConstFoldingTest,MaxFloatNegativeZeroTest)1495 TEST_F(ConstFoldingTest, MaxFloatNegativeZeroTest)
1496 {
1497 GRAPH(GetGraph())
1498 {
1499 CONSTANT(0U, -0.0F);
1500 CONSTANT(1U, +0.0F);
1501 BASIC_BLOCK(2U, 1U)
1502 {
1503 INST(2U, Opcode::Max).f32().Inputs(0U, 1U);
1504 INST(3U, Opcode::Max).f32().Inputs(1U, 0U);
1505 INST(4U, Opcode::Min).f32().Inputs(2U, 3U);
1506 INST(5U, Opcode::Return).f32().Inputs(4U);
1507 }
1508 }
1509 ASSERT_EQ(ConstFoldingMax(&INS(2U)), true);
1510 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(+0.0));
1511 ASSERT(inst != nullptr);
1512 ASSERT_EQ(INS(4U).GetInput(0U).GetInst(), inst);
1513 ASSERT_EQ(ConstFoldingMax(&INS(3U)), true);
1514 ASSERT_EQ(INS(4U).GetInput(1U).GetInst(), inst);
1515 GraphChecker(GetGraph()).Check();
1516 }
1517
TEST_F(ConstFoldingTest,MaxFloatNaNTest)1518 TEST_F(ConstFoldingTest, MaxFloatNaNTest)
1519 {
1520 GRAPH(GetGraph())
1521 {
1522 CONSTANT(0U, std::numeric_limits<float>::quiet_NaN());
1523 CONSTANT(1U, 1.3F);
1524 BASIC_BLOCK(2U, 1U)
1525 {
1526 INST(2U, Opcode::Max).f32().Inputs(0U, 1U);
1527 INST(3U, Opcode::Max).f32().Inputs(1U, 0U);
1528 INST(4U, Opcode::Min).f32().Inputs(2U, 3U);
1529 INST(5U, Opcode::Return).f32().Inputs(4U);
1530 }
1531 }
1532 ASSERT_EQ(ConstFoldingMax(&INS(2U)), true);
1533 auto inst =
1534 GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(std::numeric_limits<float>::quiet_NaN()));
1535 ASSERT(inst != nullptr);
1536 ASSERT_EQ(INS(4U).GetInput(0U).GetInst(), inst);
1537 ASSERT_EQ(ConstFoldingMax(&INS(3U)), true);
1538 ASSERT_EQ(INS(4U).GetInput(1U).GetInst(), inst);
1539 GraphChecker(GetGraph()).Check();
1540 }
1541
TEST_F(ConstFoldingTest,MaxDoubleTest)1542 TEST_F(ConstFoldingTest, MaxDoubleTest)
1543 {
1544 GRAPH(GetGraph())
1545 {
1546 CONSTANT(0U, 3.0_D);
1547 CONSTANT(1U, 2.0_D);
1548 BASIC_BLOCK(2U, 1U)
1549 {
1550 INST(2U, Opcode::Max).f64().Inputs(0U, 1U);
1551 INST(3U, Opcode::Return).f64().Inputs(2U);
1552 }
1553 }
1554 double result = 3.0_D;
1555 ASSERT_EQ(ConstFoldingMax(&INS(2U)), true);
1556 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(result));
1557 ASSERT(inst != nullptr);
1558 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1559 GraphChecker(GetGraph()).Check();
1560 }
1561
TEST_F(ConstFoldingTest,MaxDoubleNegativeZeroTest)1562 TEST_F(ConstFoldingTest, MaxDoubleNegativeZeroTest)
1563 {
1564 GRAPH(GetGraph())
1565 {
1566 CONSTANT(0U, -0.0);
1567 CONSTANT(1U, +0.0);
1568 BASIC_BLOCK(2U, 1U)
1569 {
1570 INST(2U, Opcode::Max).f64().Inputs(0U, 1U);
1571 INST(3U, Opcode::Max).f64().Inputs(1U, 0U);
1572 INST(4U, Opcode::Min).f64().Inputs(2U, 3U);
1573 INST(5U, Opcode::Return).f64().Inputs(4U);
1574 }
1575 }
1576 ASSERT_EQ(ConstFoldingMax(&INS(2U)), true);
1577 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(+0.0));
1578 ASSERT(inst != nullptr);
1579 ASSERT_EQ(INS(4U).GetInput(0U).GetInst(), inst);
1580 ASSERT_EQ(ConstFoldingMax(&INS(3U)), true);
1581 ASSERT_EQ(INS(4U).GetInput(1U).GetInst(), inst);
1582 GraphChecker(GetGraph()).Check();
1583 }
1584
TEST_F(ConstFoldingTest,MaxDoubleNaNTest)1585 TEST_F(ConstFoldingTest, MaxDoubleNaNTest)
1586 {
1587 GRAPH(GetGraph())
1588 {
1589 CONSTANT(0U, std::numeric_limits<double>::quiet_NaN());
1590 CONSTANT(1U, 1.3_D);
1591 BASIC_BLOCK(2U, 1U)
1592 {
1593 INST(2U, Opcode::Max).f64().Inputs(0U, 1U);
1594 INST(3U, Opcode::Max).f64().Inputs(1U, 0U);
1595 INST(4U, Opcode::Min).f64().Inputs(2U, 3U);
1596 INST(5U, Opcode::Return).f64().Inputs(4U);
1597 }
1598 }
1599 ASSERT_EQ(ConstFoldingMax(&INS(2U)), true);
1600 auto inst = GetGraph()->FindConstant(DataType::FLOAT64,
1601 bit_cast<uint64_t, double>(std::numeric_limits<double>::quiet_NaN()));
1602 ASSERT(inst != nullptr);
1603 ASSERT_EQ(INS(4U).GetInput(0U).GetInst(), inst);
1604 ASSERT_EQ(ConstFoldingMax(&INS(3U)), true);
1605 ASSERT_EQ(INS(4U).GetInput(1U).GetInst(), inst);
1606 GraphChecker(GetGraph()).Check();
1607 }
1608
TEST_F(ConstFoldingTest,ShlTest)1609 TEST_F(ConstFoldingTest, ShlTest)
1610 {
1611 GRAPH(GetGraph())
1612 {
1613 CONSTANT(0U, 1U);
1614 CONSTANT(1U, 2U);
1615 BASIC_BLOCK(2U, 1U)
1616 {
1617 INST(2U, Opcode::Shl).u64().Inputs(0U, 1U);
1618 INST(3U, Opcode::Return).u64().Inputs(2U);
1619 }
1620 }
1621 int result = 4;
1622 ASSERT_EQ(ConstFoldingShl(&INS(2U)), true);
1623 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1624 ASSERT(inst != nullptr);
1625 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1626 GraphChecker(GetGraph()).Check();
1627 }
1628
TEST_F(ConstFoldingTest,Constant32ShlTest)1629 TEST_F(ConstFoldingTest, Constant32ShlTest)
1630 {
1631 auto graph = CreateEmptyBytecodeGraph();
1632 GRAPH(graph)
1633 {
1634 CONSTANT(0U, 1U);
1635 CONSTANT(1U, 2U);
1636 BASIC_BLOCK(2U, 1U)
1637 {
1638 INST(2U, Opcode::Shl).u32().Inputs(0U, 1U);
1639 INST(3U, Opcode::Return).u32().Inputs(2U);
1640 }
1641 }
1642 int result = 4;
1643 ASSERT_EQ(ConstFoldingShl(&INS(2U)), true);
1644 auto inst = graph->FindConstant(DataType::INT32, result);
1645 ASSERT(inst != nullptr);
1646 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1647 GraphChecker(graph).Check();
1648 }
1649
TEST_F(ConstFoldingTest,Shl64Test)1650 TEST_F(ConstFoldingTest, Shl64Test)
1651 {
1652 GRAPH(GetGraph())
1653 {
1654 CONSTANT(0U, 1U);
1655 CONSTANT(1U, 66U);
1656 BASIC_BLOCK(2U, 1U)
1657 {
1658 INST(2U, Opcode::Shl).u64().Inputs(0U, 1U);
1659 INST(3U, Opcode::Return).u64().Inputs(2U);
1660 }
1661 }
1662 int result = 4;
1663 ASSERT_EQ(ConstFoldingShl(&INS(2U)), true);
1664 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1665 ASSERT(inst != nullptr);
1666 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1667 GraphChecker(GetGraph()).Check();
1668 }
1669
TEST_F(ConstFoldingTest,Shl32Test)1670 TEST_F(ConstFoldingTest, Shl32Test)
1671 {
1672 GRAPH(GetGraph())
1673 {
1674 CONSTANT(0U, 1U);
1675 CONSTANT(1U, 34U);
1676 BASIC_BLOCK(2U, 1U)
1677 {
1678 INST(2U, Opcode::Shl).u32().Inputs(0U, 1U);
1679 INST(3U, Opcode::Return).u32().Inputs(2U);
1680 }
1681 }
1682 int result = 4;
1683 ASSERT_EQ(ConstFoldingShl(&INS(2U)), true);
1684 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1685 ASSERT(inst != nullptr);
1686 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1687 GraphChecker(GetGraph()).Check();
1688 }
1689
TEST_F(ConstFoldingTest,Constant32Shl32Test)1690 TEST_F(ConstFoldingTest, Constant32Shl32Test)
1691 {
1692 auto graph = CreateEmptyBytecodeGraph();
1693 GRAPH(graph)
1694 {
1695 CONSTANT(0U, 1U);
1696 CONSTANT(1U, 34U);
1697 BASIC_BLOCK(2U, 1U)
1698 {
1699 INST(2U, Opcode::Shl).u32().Inputs(0U, 1U);
1700 INST(3U, Opcode::Return).u32().Inputs(2U);
1701 }
1702 }
1703 int result = 4;
1704 ASSERT_EQ(ConstFoldingShl(&INS(2U)), true);
1705 auto inst = graph->FindConstant(DataType::INT32, result);
1706 ASSERT(inst != nullptr);
1707 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1708 GraphChecker(graph).Check();
1709 }
1710
TEST_F(ConstFoldingTest,ShrTest)1711 TEST_F(ConstFoldingTest, ShrTest)
1712 {
1713 GRAPH(GetGraph())
1714 {
1715 CONSTANT(0U, 4U);
1716 CONSTANT(1U, 2U);
1717 BASIC_BLOCK(2U, 1U)
1718 {
1719 INST(2U, Opcode::Shr).u64().Inputs(0U, 1U);
1720 INST(3U, Opcode::Return).u64().Inputs(2U);
1721 }
1722 }
1723 int result = 1;
1724 ASSERT_EQ(ConstFoldingShr(&INS(2U)), true);
1725 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1726 ASSERT(inst != nullptr);
1727 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1728 GraphChecker(GetGraph()).Check();
1729 }
1730
TEST_F(ConstFoldingTest,Constant32ShrTest)1731 TEST_F(ConstFoldingTest, Constant32ShrTest)
1732 {
1733 auto graph = CreateEmptyBytecodeGraph();
1734 GRAPH(graph)
1735 {
1736 CONSTANT(0U, 4U);
1737 CONSTANT(1U, 2U);
1738 BASIC_BLOCK(2U, 1U)
1739 {
1740 INST(2U, Opcode::Shr).u32().Inputs(0U, 1U);
1741 INST(3U, Opcode::Return).u32().Inputs(2U);
1742 }
1743 }
1744 int result = 1;
1745 ASSERT_EQ(ConstFoldingShr(&INS(2U)), true);
1746 auto inst = graph->FindConstant(DataType::INT32, result);
1747 ASSERT(inst != nullptr);
1748 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1749 GraphChecker(graph).Check();
1750 }
1751
TEST_F(ConstFoldingTest,AShrUTest)1752 TEST_F(ConstFoldingTest, AShrUTest)
1753 {
1754 GRAPH(GetGraph())
1755 {
1756 CONSTANT(0U, 4U);
1757 CONSTANT(1U, 2U);
1758 BASIC_BLOCK(2U, 1U)
1759 {
1760 INST(2U, Opcode::AShr).u64().Inputs(0U, 1U);
1761 INST(3U, Opcode::Return).u64().Inputs(2U);
1762 }
1763 }
1764 uint64_t result = 1;
1765 ASSERT_EQ(ConstFoldingAShr(&INS(2U)), true);
1766 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1767 ASSERT(inst != nullptr);
1768 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1769 GraphChecker(GetGraph()).Check();
1770 }
1771
TEST_F(ConstFoldingTest,Constant32AShrUTest)1772 TEST_F(ConstFoldingTest, Constant32AShrUTest)
1773 {
1774 auto graph = CreateEmptyBytecodeGraph();
1775 GRAPH(graph)
1776 {
1777 CONSTANT(0U, 4U);
1778 CONSTANT(1U, 2U);
1779 BASIC_BLOCK(2U, 1U)
1780 {
1781 INST(2U, Opcode::AShr).u32().Inputs(0U, 1U);
1782 INST(3U, Opcode::Return).u32().Inputs(2U);
1783 }
1784 }
1785 uint32_t result = 1;
1786 ASSERT_EQ(ConstFoldingAShr(&INS(2U)), true);
1787 auto inst = graph->FindConstant(DataType::INT32, result);
1788 ASSERT(inst != nullptr);
1789 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1790 GraphChecker(graph).Check();
1791 }
1792
TEST_F(ConstFoldingTest,AShrTest)1793 TEST_F(ConstFoldingTest, AShrTest)
1794 {
1795 GRAPH(GetGraph())
1796 {
1797 CONSTANT(0U, -4L);
1798 CONSTANT(1U, 2U);
1799 BASIC_BLOCK(2U, 1U)
1800 {
1801 INST(2U, Opcode::AShr).s64().Inputs(0U, 1U);
1802 INST(3U, Opcode::Return).s64().Inputs(2U);
1803 }
1804 }
1805 int64_t result = -1;
1806 ASSERT_EQ(ConstFoldingAShr(&INS(2U)), true);
1807 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1808 ASSERT(inst != nullptr);
1809 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1810 GraphChecker(GetGraph()).Check();
1811 }
1812
TEST_F(ConstFoldingTest,Constant32AShrTest)1813 TEST_F(ConstFoldingTest, Constant32AShrTest)
1814 {
1815 auto graph = CreateEmptyBytecodeGraph();
1816 GRAPH(graph)
1817 {
1818 CONSTANT(0U, -4L);
1819 CONSTANT(1U, 2U);
1820 BASIC_BLOCK(2U, 1U)
1821 {
1822 INST(2U, Opcode::AShr).s32().Inputs(0U, 1U);
1823 INST(3U, Opcode::Return).s32().Inputs(2U);
1824 }
1825 }
1826 int64_t result = -1;
1827 ASSERT_EQ(ConstFoldingAShr(&INS(2U)), true);
1828 auto inst = graph->FindConstant(DataType::INT32, result);
1829 ASSERT(inst != nullptr);
1830 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1831 GraphChecker(graph).Check();
1832 }
1833
TEST_F(ConstFoldingTest,Shr32Test)1834 TEST_F(ConstFoldingTest, Shr32Test)
1835 {
1836 GRAPH(GetGraph())
1837 {
1838 CONSTANT(0U, -4L);
1839 CONSTANT(1U, 4U);
1840 BASIC_BLOCK(2U, 1U)
1841 {
1842 INST(2U, Opcode::Shr).s32().Inputs(0U, 1U);
1843 INST(3U, Opcode::Return).s32().Inputs(2U);
1844 }
1845 }
1846 int64_t result = 0xfffffff;
1847 ASSERT_EQ(ConstFoldingShr(&INS(2U)), true);
1848 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1849 ASSERT(inst != nullptr);
1850 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1851 GraphChecker(GetGraph()).Check();
1852 }
1853
TEST_F(ConstFoldingTest,Constant32Shr32Test)1854 TEST_F(ConstFoldingTest, Constant32Shr32Test)
1855 {
1856 auto graph = CreateEmptyBytecodeGraph();
1857 GRAPH(graph)
1858 {
1859 CONSTANT(0U, -4L);
1860 CONSTANT(1U, 4U);
1861 BASIC_BLOCK(2U, 1U)
1862 {
1863 INST(2U, Opcode::Shr).s32().Inputs(0U, 1U);
1864 INST(3U, Opcode::Return).s32().Inputs(2U);
1865 }
1866 }
1867 int64_t result = 0xfffffff;
1868 ASSERT_EQ(ConstFoldingShr(&INS(2U)), true);
1869 auto inst = graph->FindConstant(DataType::INT32, result);
1870 ASSERT(inst != nullptr);
1871 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1872 GraphChecker(graph).Check();
1873 }
1874
TEST_F(ConstFoldingTest,ModTestInt)1875 TEST_F(ConstFoldingTest, ModTestInt)
1876 {
1877 GRAPH(GetGraph())
1878 {
1879 CONSTANT(0U, 3U);
1880 CONSTANT(1U, 2U);
1881 BASIC_BLOCK(2U, 1U)
1882 {
1883 INST(2U, Opcode::Mod).u64().Inputs(0U, 1U);
1884 INST(3U, Opcode::Return).u64().Inputs(2U);
1885 }
1886 }
1887 int result = 1;
1888 ASSERT_EQ(ConstFoldingMod(&INS(2U)), true);
1889 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1890 ASSERT(inst != nullptr);
1891 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1892 GraphChecker(GetGraph()).Check();
1893 }
1894
TEST_F(ConstFoldingTest,Constant32ModTestInt)1895 TEST_F(ConstFoldingTest, Constant32ModTestInt)
1896 {
1897 auto graph = CreateEmptyBytecodeGraph();
1898 GRAPH(graph)
1899 {
1900 CONSTANT(0U, 3U);
1901 CONSTANT(1U, 2U);
1902 BASIC_BLOCK(2U, 1U)
1903 {
1904 INST(2U, Opcode::Mod).u32().Inputs(0U, 1U);
1905 INST(3U, Opcode::Return).u32().Inputs(2U);
1906 }
1907 }
1908 int result = 1;
1909 ASSERT_EQ(ConstFoldingMod(&INS(2U)), true);
1910 auto inst = graph->FindConstant(DataType::INT32, result);
1911 ASSERT(inst != nullptr);
1912 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1913 GraphChecker(graph).Check();
1914 }
1915
TEST_F(ConstFoldingTest,ModIntTest1)1916 TEST_F(ConstFoldingTest, ModIntTest1)
1917 {
1918 GRAPH(GetGraph())
1919 {
1920 CONSTANT(0U, 0xffffffff80000000U);
1921 CONSTANT(1U, 0xffffffffffffffffU);
1922 BASIC_BLOCK(2U, 1U)
1923 {
1924 INST(2U, Opcode::Mod).s32().Inputs(0U, 1U);
1925 INST(3U, Opcode::Return).s32().Inputs(2U);
1926 }
1927 }
1928 int32_t result = 0;
1929 ASSERT_EQ(ConstFoldingMod(&INS(2U)), true);
1930 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
1931 ASSERT(inst != nullptr);
1932 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1933 GraphChecker(GetGraph()).Check();
1934 }
1935
TEST_F(ConstFoldingTest,Constant32ModIntTest1)1936 TEST_F(ConstFoldingTest, Constant32ModIntTest1)
1937 {
1938 auto graph = CreateEmptyBytecodeGraph();
1939 GRAPH(graph)
1940 {
1941 CONSTANT(0U, 0xffffffff80000000U);
1942 CONSTANT(1U, 0xffffffffffffffffU);
1943 BASIC_BLOCK(2U, 1U)
1944 {
1945 INST(2U, Opcode::Mod).s32().Inputs(0U, 1U);
1946 INST(3U, Opcode::Return).s32().Inputs(2U);
1947 }
1948 }
1949 int32_t result = 0;
1950 ASSERT_EQ(ConstFoldingMod(&INS(2U)), true);
1951 auto inst = graph->FindConstant(DataType::INT32, result);
1952 ASSERT(inst != nullptr);
1953 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1954 GraphChecker(graph).Check();
1955 }
1956
TEST_F(ConstFoldingTest,ModTestFloat)1957 TEST_F(ConstFoldingTest, ModTestFloat)
1958 {
1959 GRAPH(GetGraph())
1960 {
1961 CONSTANT(0U, 7.3F);
1962 CONSTANT(1U, 2.9F);
1963 BASIC_BLOCK(2U, 1U)
1964 {
1965 INST(2U, Opcode::Mod).f32().Inputs(0U, 1U);
1966 INST(3U, Opcode::Return).f32().Inputs(2U);
1967 }
1968 }
1969 float result = 1.5;
1970 ASSERT_EQ(ConstFoldingMod(&INS(2U)), true);
1971 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(result));
1972 ASSERT(inst != nullptr);
1973 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1974 GraphChecker(GetGraph()).Check();
1975 }
1976
TEST_F(ConstFoldingTest,ModTestDouble)1977 TEST_F(ConstFoldingTest, ModTestDouble)
1978 {
1979 GRAPH(GetGraph())
1980 {
1981 CONSTANT(0U, 15.5_D);
1982 CONSTANT(1U, 2.2_D);
1983 BASIC_BLOCK(2U, 1U)
1984 {
1985 INST(2U, Opcode::Mod).f64().Inputs(0U, 1U);
1986 INST(3U, Opcode::Return).f64().Inputs(2U);
1987 }
1988 }
1989 double result = fmod(15.5_D, 2.2_D);
1990 ASSERT_EQ(ConstFoldingMod(&INS(2U)), true);
1991 auto inst = GetGraph()->FindConstant(DataType::FLOAT64, bit_cast<uint64_t, double>(result));
1992 ASSERT(inst != nullptr);
1993 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
1994 GraphChecker(GetGraph()).Check();
1995 }
1996
TEST_F(ConstFoldingTest,Mod1Test)1997 TEST_F(ConstFoldingTest, Mod1Test)
1998 {
1999 GRAPH(GetGraph())
2000 {
2001 PARAMETER(0U, 0U).u64();
2002 CONSTANT(1U, 1U);
2003 BASIC_BLOCK(2U, 1U)
2004 {
2005 INST(2U, Opcode::Mod).u64().Inputs(0U, 1U);
2006 INST(3U, Opcode::Return).u64().Inputs(2U);
2007 }
2008 }
2009 ASSERT_EQ(ConstFoldingMod(&INS(2U)), true);
2010 int result = 0;
2011 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2012 ASSERT(inst != nullptr);
2013 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2014 GraphChecker(GetGraph()).Check();
2015 }
2016
TEST_F(ConstFoldingTest,Constant32Mod1Test)2017 TEST_F(ConstFoldingTest, Constant32Mod1Test)
2018 {
2019 auto graph = CreateEmptyBytecodeGraph();
2020 GRAPH(graph)
2021 {
2022 PARAMETER(0U, 0U).u32();
2023 CONSTANT(1U, 1U);
2024 BASIC_BLOCK(2U, 1U)
2025 {
2026 INST(2U, Opcode::Mod).u32().Inputs(0U, 1U);
2027 INST(3U, Opcode::Return).u32().Inputs(2U);
2028 }
2029 }
2030 ASSERT_EQ(ConstFoldingMod(&INS(2U)), true);
2031 int result = 0;
2032 auto inst = graph->FindConstant(DataType::INT32, result);
2033 ASSERT(inst != nullptr);
2034 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2035 GraphChecker(graph).Check();
2036 }
2037
TEST_F(ConstFoldingTest,Mod1TestFloat)2038 TEST_F(ConstFoldingTest, Mod1TestFloat)
2039 {
2040 GRAPH(GetGraph())
2041 {
2042 PARAMETER(0U, 0U).f64();
2043 CONSTANT(1U, 1.0);
2044 BASIC_BLOCK(2U, 1U)
2045 {
2046 INST(2U, Opcode::Mod).f64().Inputs(0U, 1U);
2047 INST(3U, Opcode::Return).f64().Inputs(2U);
2048 }
2049 }
2050 // the optimization "x % 1 -> 0" is not applicable for floating point values
2051 ASSERT_EQ(ConstFoldingMod(&INS(2U)), false);
2052 }
2053
TEST_F(ConstFoldingTest,AndTest)2054 TEST_F(ConstFoldingTest, AndTest)
2055 {
2056 GRAPH(GetGraph())
2057 {
2058 CONSTANT(0U, 1U);
2059 CONSTANT(1U, 2U);
2060 BASIC_BLOCK(2U, 1U)
2061 {
2062 INST(2U, Opcode::And).u64().Inputs(0U, 1U);
2063 INST(3U, Opcode::Return).u64().Inputs(2U);
2064 }
2065 }
2066 int result = 0;
2067 ASSERT_EQ(ConstFoldingAnd(&INS(2U)), true);
2068 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2069 ASSERT(inst != nullptr);
2070 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2071 GraphChecker(GetGraph()).Check();
2072 }
2073
TEST_F(ConstFoldingTest,Constant32AndTest)2074 TEST_F(ConstFoldingTest, Constant32AndTest)
2075 {
2076 auto graph = CreateEmptyBytecodeGraph();
2077 GRAPH(graph)
2078 {
2079 CONSTANT(0U, 1U);
2080 CONSTANT(1U, 2U);
2081 BASIC_BLOCK(2U, 1U)
2082 {
2083 INST(2U, Opcode::And).u32().Inputs(0U, 1U);
2084 INST(3U, Opcode::Return).u32().Inputs(2U);
2085 }
2086 }
2087 int result = 0;
2088 ASSERT_EQ(ConstFoldingAnd(&INS(2U)), true);
2089 auto inst = graph->FindConstant(DataType::INT32, result);
2090 ASSERT(inst != nullptr);
2091 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2092 GraphChecker(graph).Check();
2093 }
2094
TEST_F(ConstFoldingTest,OrTest)2095 TEST_F(ConstFoldingTest, OrTest)
2096 {
2097 GRAPH(GetGraph())
2098 {
2099 CONSTANT(0U, 1U);
2100 CONSTANT(1U, 2U);
2101 BASIC_BLOCK(2U, 1U)
2102 {
2103 INST(2U, Opcode::Or).u64().Inputs(0U, 1U);
2104 INST(3U, Opcode::Return).u64().Inputs(2U);
2105 }
2106 }
2107 int result = 3;
2108 ASSERT_EQ(ConstFoldingOr(&INS(2U)), true);
2109 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2110 ASSERT(inst != nullptr);
2111 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2112 GraphChecker(GetGraph()).Check();
2113 }
2114
TEST_F(ConstFoldingTest,Constant32OrTest)2115 TEST_F(ConstFoldingTest, Constant32OrTest)
2116 {
2117 auto graph = CreateEmptyBytecodeGraph();
2118 GRAPH(graph)
2119 {
2120 CONSTANT(0U, 1U);
2121 CONSTANT(1U, 2U);
2122 BASIC_BLOCK(2U, 1U)
2123 {
2124 INST(2U, Opcode::Or).u32().Inputs(0U, 1U);
2125 INST(3U, Opcode::Return).u32().Inputs(2U);
2126 }
2127 }
2128 int result = 3;
2129 ASSERT_EQ(ConstFoldingOr(&INS(2U)), true);
2130 auto inst = graph->FindConstant(DataType::INT32, result);
2131 ASSERT(inst != nullptr);
2132 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2133 GraphChecker(graph).Check();
2134 }
2135
TEST_F(ConstFoldingTest,XorTest)2136 TEST_F(ConstFoldingTest, XorTest)
2137 {
2138 GRAPH(GetGraph())
2139 {
2140 CONSTANT(0U, 1U);
2141 CONSTANT(1U, 2U);
2142 BASIC_BLOCK(2U, 1U)
2143 {
2144 INST(2U, Opcode::Xor).u64().Inputs(0U, 1U);
2145 INST(3U, Opcode::Return).u64().Inputs(2U);
2146 }
2147 }
2148 int result = 3;
2149 ASSERT_EQ(ConstFoldingXor(&INS(2U)), true);
2150 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2151 ASSERT(inst != nullptr);
2152 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2153 GraphChecker(GetGraph()).Check();
2154 }
2155
TEST_F(ConstFoldingTest,Constant32XorTest)2156 TEST_F(ConstFoldingTest, Constant32XorTest)
2157 {
2158 auto graph = CreateEmptyBytecodeGraph();
2159 GRAPH(graph)
2160 {
2161 CONSTANT(0U, 1U);
2162 CONSTANT(1U, 2U);
2163 BASIC_BLOCK(2U, 1U)
2164 {
2165 INST(2U, Opcode::Xor).u32().Inputs(0U, 1U);
2166 INST(3U, Opcode::Return).u32().Inputs(2U);
2167 }
2168 }
2169 int result = 3;
2170 ASSERT_EQ(ConstFoldingXor(&INS(2U)), true);
2171 auto inst = graph->FindConstant(DataType::INT32, result);
2172 ASSERT(inst != nullptr);
2173 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2174 GraphChecker(graph).Check();
2175 }
2176
TEST_F(ConstFoldingTest,CompareEQTest)2177 TEST_F(ConstFoldingTest, CompareEQTest)
2178 {
2179 GRAPH(GetGraph())
2180 {
2181 CONSTANT(0U, 3U);
2182 CONSTANT(1U, 3U);
2183 BASIC_BLOCK(2U, 1U)
2184 {
2185 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_EQ).Inputs(0U, 1U);
2186 INST(3U, Opcode::Return).b().Inputs(2U);
2187 }
2188 }
2189 int result = 1;
2190 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2191 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2192 ASSERT(inst != nullptr);
2193 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2194 GraphChecker(GetGraph()).Check();
2195 }
2196
TEST_F(ConstFoldingTest,Constant32CompareEQTest)2197 TEST_F(ConstFoldingTest, Constant32CompareEQTest)
2198 {
2199 auto graph = CreateEmptyBytecodeGraph();
2200 GRAPH(graph)
2201 {
2202 CONSTANT(0U, 3U);
2203 CONSTANT(1U, 3U);
2204 BASIC_BLOCK(2U, 1U)
2205 {
2206 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_EQ).Inputs(0U, 1U);
2207 INST(3U, Opcode::Return).b().Inputs(2U);
2208 }
2209 }
2210 int result = 1;
2211 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2212 auto inst = graph->FindConstant(DataType::INT32, result);
2213 ASSERT(inst != nullptr);
2214 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2215 GraphChecker(graph).Check();
2216 }
2217
TEST_F(ConstFoldingTest,CompareNETest)2218 TEST_F(ConstFoldingTest, CompareNETest)
2219 {
2220 GRAPH(GetGraph())
2221 {
2222 CONSTANT(0U, 3U);
2223 CONSTANT(1U, 3U);
2224 BASIC_BLOCK(2U, 1U)
2225 {
2226 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_NE).Inputs(0U, 1U);
2227 INST(3U, Opcode::Return).b().Inputs(2U);
2228 }
2229 }
2230 int result = 0;
2231 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2232 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2233 ASSERT(inst != nullptr);
2234 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2235 GraphChecker(GetGraph()).Check();
2236 }
2237
TEST_F(ConstFoldingTest,Constant32CompareNETest)2238 TEST_F(ConstFoldingTest, Constant32CompareNETest)
2239 {
2240 auto graph = CreateEmptyBytecodeGraph();
2241 GRAPH(graph)
2242 {
2243 CONSTANT(0U, 3U);
2244 CONSTANT(1U, 3U);
2245 BASIC_BLOCK(2U, 1U)
2246 {
2247 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_NE).Inputs(0U, 1U);
2248 INST(3U, Opcode::Return).b().Inputs(2U);
2249 }
2250 }
2251 int result = 0;
2252 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2253 auto inst = graph->FindConstant(DataType::INT32, result);
2254 ASSERT(inst != nullptr);
2255 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2256 GraphChecker(graph).Check();
2257 }
2258
TEST_F(ConstFoldingTest,CompareLTTest)2259 TEST_F(ConstFoldingTest, CompareLTTest)
2260 {
2261 GRAPH(GetGraph())
2262 {
2263 CONSTANT(0U, 3U);
2264 CONSTANT(1U, 3U);
2265 BASIC_BLOCK(2U, 1U)
2266 {
2267 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_LT).Inputs(0U, 1U);
2268 INST(3U, Opcode::Return).b().Inputs(2U);
2269 }
2270 }
2271 int result = 0;
2272 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2273 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2274 ASSERT(inst != nullptr);
2275 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2276 GraphChecker(GetGraph()).Check();
2277 }
2278
TEST_F(ConstFoldingTest,Constant32CompareLTTest)2279 TEST_F(ConstFoldingTest, Constant32CompareLTTest)
2280 {
2281 auto graph = CreateEmptyBytecodeGraph();
2282 GRAPH(graph)
2283 {
2284 CONSTANT(0U, 3U);
2285 CONSTANT(1U, 3U);
2286 BASIC_BLOCK(2U, 1U)
2287 {
2288 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_LT).Inputs(0U, 1U);
2289 INST(3U, Opcode::Return).b().Inputs(2U);
2290 }
2291 }
2292 int result = 0;
2293 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2294 auto inst = graph->FindConstant(DataType::INT32, result);
2295 ASSERT(inst != nullptr);
2296 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2297 GraphChecker(graph).Check();
2298 }
2299
TEST_F(ConstFoldingTest,CompareLTTest1)2300 TEST_F(ConstFoldingTest, CompareLTTest1)
2301 {
2302 GRAPH(GetGraph())
2303 {
2304 CONSTANT(0U, -3L);
2305 CONSTANT(1U, 3U);
2306 BASIC_BLOCK(2U, 1U)
2307 {
2308 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_LT).Inputs(0U, 1U);
2309 INST(3U, Opcode::Return).b().Inputs(2U);
2310 }
2311 }
2312 int result = 1;
2313 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2314 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2315 ASSERT(inst != nullptr);
2316 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2317 GraphChecker(GetGraph()).Check();
2318 }
2319
TEST_F(ConstFoldingTest,Constant32CompareLTTest1)2320 TEST_F(ConstFoldingTest, Constant32CompareLTTest1)
2321 {
2322 auto graph = CreateEmptyBytecodeGraph();
2323 GRAPH(graph)
2324 {
2325 CONSTANT(0U, -3L);
2326 CONSTANT(1U, 3U);
2327 BASIC_BLOCK(2U, 1U)
2328 {
2329 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_LT).Inputs(0U, 1U);
2330 INST(3U, Opcode::Return).b().Inputs(2U);
2331 }
2332 }
2333 int result = 1;
2334 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2335 auto inst = graph->FindConstant(DataType::INT32, result);
2336 ASSERT(inst != nullptr);
2337 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2338 GraphChecker(graph).Check();
2339 }
2340
TEST_F(ConstFoldingTest,CompareLETest)2341 TEST_F(ConstFoldingTest, CompareLETest)
2342 {
2343 GRAPH(GetGraph())
2344 {
2345 CONSTANT(0U, 3U);
2346 CONSTANT(1U, 3U);
2347 BASIC_BLOCK(2U, 1U)
2348 {
2349 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_LE).Inputs(0U, 1U);
2350 INST(3U, Opcode::Return).b().Inputs(2U);
2351 }
2352 }
2353 int result = 1;
2354 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2355 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2356 ASSERT(inst != nullptr);
2357 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2358 GraphChecker(GetGraph()).Check();
2359 }
2360
TEST_F(ConstFoldingTest,Constant32CompareLETest)2361 TEST_F(ConstFoldingTest, Constant32CompareLETest)
2362 {
2363 auto graph = CreateEmptyBytecodeGraph();
2364 GRAPH(graph)
2365 {
2366 CONSTANT(0U, 3U);
2367 CONSTANT(1U, 3U);
2368 BASIC_BLOCK(2U, 1U)
2369 {
2370 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_LE).Inputs(0U, 1U);
2371 INST(3U, Opcode::Return).b().Inputs(2U);
2372 }
2373 }
2374 int result = 1;
2375 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2376 auto inst = graph->FindConstant(DataType::INT32, result);
2377 ASSERT(inst != nullptr);
2378 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2379 GraphChecker(graph).Check();
2380 }
2381
TEST_F(ConstFoldingTest,CompareLETest1)2382 TEST_F(ConstFoldingTest, CompareLETest1)
2383 {
2384 GRAPH(GetGraph())
2385 {
2386 CONSTANT(0U, -1L);
2387 CONSTANT(1U, 3U);
2388 BASIC_BLOCK(2U, 1U)
2389 {
2390 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_LE).Inputs(0U, 1U);
2391 INST(3U, Opcode::Return).b().Inputs(2U);
2392 }
2393 }
2394 int result = 1;
2395 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2396 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2397 ASSERT(inst != nullptr);
2398 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2399 GraphChecker(GetGraph()).Check();
2400 }
2401
TEST_F(ConstFoldingTest,Constant32CompareLETest1)2402 TEST_F(ConstFoldingTest, Constant32CompareLETest1)
2403 {
2404 auto graph = CreateEmptyBytecodeGraph();
2405 GRAPH(graph)
2406 {
2407 CONSTANT(0U, -1L);
2408 CONSTANT(1U, 3U);
2409 BASIC_BLOCK(2U, 1U)
2410 {
2411 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_LE).Inputs(0U, 1U);
2412 INST(3U, Opcode::Return).b().Inputs(2U);
2413 }
2414 }
2415 int result = 1;
2416 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2417 auto inst = graph->FindConstant(DataType::INT32, result);
2418 ASSERT(inst != nullptr);
2419 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2420 GraphChecker(graph).Check();
2421 }
2422
TEST_F(ConstFoldingTest,CompareGTTest)2423 TEST_F(ConstFoldingTest, CompareGTTest)
2424 {
2425 GRAPH(GetGraph())
2426 {
2427 CONSTANT(0U, 3U);
2428 CONSTANT(1U, 3U);
2429 BASIC_BLOCK(2U, 1U)
2430 {
2431 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_GT).Inputs(0U, 1U);
2432 INST(3U, Opcode::Return).b().Inputs(2U);
2433 }
2434 }
2435 int result = 0;
2436 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2437 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2438 ASSERT(inst != nullptr);
2439 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2440 GraphChecker(GetGraph()).Check();
2441 }
2442
TEST_F(ConstFoldingTest,Constant32CompareGTTest)2443 TEST_F(ConstFoldingTest, Constant32CompareGTTest)
2444 {
2445 auto graph = CreateEmptyBytecodeGraph();
2446 GRAPH(graph)
2447 {
2448 CONSTANT(0U, 3U);
2449 CONSTANT(1U, 3U);
2450 BASIC_BLOCK(2U, 1U)
2451 {
2452 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_GT).Inputs(0U, 1U);
2453 INST(3U, Opcode::Return).b().Inputs(2U);
2454 }
2455 }
2456 int result = 0;
2457 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2458 auto inst = graph->FindConstant(DataType::INT32, result);
2459 ASSERT(inst != nullptr);
2460 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2461 GraphChecker(graph).Check();
2462 }
2463
TEST_F(ConstFoldingTest,CompareGTTest1)2464 TEST_F(ConstFoldingTest, CompareGTTest1)
2465 {
2466 GRAPH(GetGraph())
2467 {
2468 CONSTANT(0U, -1L);
2469 CONSTANT(1U, -2L);
2470 BASIC_BLOCK(2U, 1U)
2471 {
2472 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_GT).Inputs(0U, 1U);
2473 INST(3U, Opcode::Return).b().Inputs(2U);
2474 }
2475 }
2476 int result = 1;
2477 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2478 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2479 ASSERT(inst != nullptr);
2480 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2481 GraphChecker(GetGraph()).Check();
2482 }
2483
TEST_F(ConstFoldingTest,Constant32CompareGTTest1)2484 TEST_F(ConstFoldingTest, Constant32CompareGTTest1)
2485 {
2486 auto graph = CreateEmptyBytecodeGraph();
2487 GRAPH(graph)
2488 {
2489 CONSTANT(0U, -1L);
2490 CONSTANT(1U, -2L);
2491 BASIC_BLOCK(2U, 1U)
2492 {
2493 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_GT).Inputs(0U, 1U);
2494 INST(3U, Opcode::Return).b().Inputs(2U);
2495 }
2496 }
2497 int result = 1;
2498 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2499 auto inst = graph->FindConstant(DataType::INT32, result);
2500 ASSERT(inst != nullptr);
2501 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2502 GraphChecker(graph).Check();
2503 }
2504
TEST_F(ConstFoldingTest,CompareGETest)2505 TEST_F(ConstFoldingTest, CompareGETest)
2506 {
2507 GRAPH(GetGraph())
2508 {
2509 CONSTANT(0U, 3U);
2510 CONSTANT(1U, 3U);
2511 BASIC_BLOCK(2U, 1U)
2512 {
2513 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_GE).Inputs(0U, 1U);
2514 INST(3U, Opcode::Return).b().Inputs(2U);
2515 }
2516 }
2517 int result = 1;
2518 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2519 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2520 ASSERT(inst != nullptr);
2521 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2522 GraphChecker(GetGraph()).Check();
2523 }
2524
TEST_F(ConstFoldingTest,Constant32CompareGETest)2525 TEST_F(ConstFoldingTest, Constant32CompareGETest)
2526 {
2527 auto graph = CreateEmptyBytecodeGraph();
2528 GRAPH(graph)
2529 {
2530 CONSTANT(0U, 3U);
2531 CONSTANT(1U, 3U);
2532 BASIC_BLOCK(2U, 1U)
2533 {
2534 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_GE).Inputs(0U, 1U);
2535 INST(3U, Opcode::Return).b().Inputs(2U);
2536 }
2537 }
2538 int result = 1;
2539 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2540 auto inst = graph->FindConstant(DataType::INT32, result);
2541 ASSERT(inst != nullptr);
2542 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2543 GraphChecker(graph).Check();
2544 }
2545
TEST_F(ConstFoldingTest,CompareGETest1)2546 TEST_F(ConstFoldingTest, CompareGETest1)
2547 {
2548 GRAPH(GetGraph())
2549 {
2550 CONSTANT(0U, -1L);
2551 CONSTANT(1U, -2L);
2552 BASIC_BLOCK(2U, 1U)
2553 {
2554 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_GE).Inputs(0U, 1U);
2555 INST(3U, Opcode::Return).b().Inputs(2U);
2556 }
2557 }
2558 int result = 1;
2559 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2560 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2561 ASSERT(inst != nullptr);
2562 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2563 GraphChecker(GetGraph()).Check();
2564 }
2565
TEST_F(ConstFoldingTest,Constant32CompareGETest1)2566 TEST_F(ConstFoldingTest, Constant32CompareGETest1)
2567 {
2568 auto graph = CreateEmptyBytecodeGraph();
2569 GRAPH(graph)
2570 {
2571 CONSTANT(0U, -1L);
2572 CONSTANT(1U, -2L);
2573 BASIC_BLOCK(2U, 1U)
2574 {
2575 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_GE).Inputs(0U, 1U);
2576 INST(3U, Opcode::Return).b().Inputs(2U);
2577 }
2578 }
2579 int result = 1;
2580 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2581 auto inst = graph->FindConstant(DataType::INT32, result);
2582 ASSERT(inst != nullptr);
2583 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2584 GraphChecker(graph).Check();
2585 }
2586
TEST_F(ConstFoldingTest,CompareBTest)2587 TEST_F(ConstFoldingTest, CompareBTest)
2588 {
2589 GRAPH(GetGraph())
2590 {
2591 CONSTANT(0U, 3U);
2592 CONSTANT(1U, 3U);
2593 BASIC_BLOCK(2U, 1U)
2594 {
2595 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_B).Inputs(0U, 1U);
2596 INST(3U, Opcode::Return).b().Inputs(2U);
2597 }
2598 }
2599 int result = 0;
2600 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2601 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2602 ASSERT(inst != nullptr);
2603 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2604 GraphChecker(GetGraph()).Check();
2605 }
2606
TEST_F(ConstFoldingTest,Constant32CompareBTest)2607 TEST_F(ConstFoldingTest, Constant32CompareBTest)
2608 {
2609 auto graph = CreateEmptyBytecodeGraph();
2610 GRAPH(graph)
2611 {
2612 CONSTANT(0U, 3U);
2613 CONSTANT(1U, 3U);
2614 BASIC_BLOCK(2U, 1U)
2615 {
2616 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_B).Inputs(0U, 1U);
2617 INST(3U, Opcode::Return).b().Inputs(2U);
2618 }
2619 }
2620 int result = 0;
2621 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2622 auto inst = graph->FindConstant(DataType::INT32, result);
2623 ASSERT(inst != nullptr);
2624 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2625 GraphChecker(graph).Check();
2626 }
2627
TEST_F(ConstFoldingTest,CompareBETest)2628 TEST_F(ConstFoldingTest, CompareBETest)
2629 {
2630 GRAPH(GetGraph())
2631 {
2632 CONSTANT(0U, 3U);
2633 CONSTANT(1U, 3U);
2634 BASIC_BLOCK(2U, 1U)
2635 {
2636 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_BE).Inputs(0U, 1U);
2637 INST(3U, Opcode::Return).b().Inputs(2U);
2638 }
2639 }
2640 int result = 1;
2641 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2642 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2643 ASSERT(inst != nullptr);
2644 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2645 GraphChecker(GetGraph()).Check();
2646 }
2647
TEST_F(ConstFoldingTest,Constant32CompareBETest)2648 TEST_F(ConstFoldingTest, Constant32CompareBETest)
2649 {
2650 auto graph = CreateEmptyBytecodeGraph();
2651 GRAPH(graph)
2652 {
2653 CONSTANT(0U, 3U);
2654 CONSTANT(1U, 3U);
2655 BASIC_BLOCK(2U, 1U)
2656 {
2657 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_BE).Inputs(0U, 1U);
2658 INST(3U, Opcode::Return).b().Inputs(2U);
2659 }
2660 }
2661 int result = 1;
2662 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2663 auto inst = graph->FindConstant(DataType::INT32, result);
2664 ASSERT(inst != nullptr);
2665 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2666 GraphChecker(graph).Check();
2667 }
2668
TEST_F(ConstFoldingTest,CompareATest)2669 TEST_F(ConstFoldingTest, CompareATest)
2670 {
2671 GRAPH(GetGraph())
2672 {
2673 CONSTANT(0U, 3U);
2674 CONSTANT(1U, 3U);
2675 BASIC_BLOCK(2U, 1U)
2676 {
2677 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_A).Inputs(0U, 1U);
2678 INST(3U, Opcode::Return).b().Inputs(2U);
2679 }
2680 }
2681 int result = 0;
2682 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2683 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2684 ASSERT(inst != nullptr);
2685 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2686 GraphChecker(GetGraph()).Check();
2687 }
2688
TEST_F(ConstFoldingTest,Constant32CompareATest)2689 TEST_F(ConstFoldingTest, Constant32CompareATest)
2690 {
2691 auto graph = CreateEmptyBytecodeGraph();
2692 GRAPH(graph)
2693 {
2694 CONSTANT(0U, 3U);
2695 CONSTANT(1U, 3U);
2696 BASIC_BLOCK(2U, 1U)
2697 {
2698 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_A).Inputs(0U, 1U);
2699 INST(3U, Opcode::Return).b().Inputs(2U);
2700 }
2701 }
2702 int result = 0;
2703 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2704 auto inst = graph->FindConstant(DataType::INT32, result);
2705 ASSERT(inst != nullptr);
2706 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2707 GraphChecker(graph).Check();
2708 }
2709
TEST_F(ConstFoldingTest,CompareAETest)2710 TEST_F(ConstFoldingTest, CompareAETest)
2711 {
2712 GRAPH(GetGraph())
2713 {
2714 CONSTANT(0U, 3U);
2715 CONSTANT(1U, 3U);
2716 BASIC_BLOCK(2U, 1U)
2717 {
2718 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_AE).Inputs(0U, 1U);
2719 INST(3U, Opcode::Return).b().Inputs(2U);
2720 }
2721 }
2722 int result = 1;
2723 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2724 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2725 ASSERT(inst != nullptr);
2726 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2727 GraphChecker(GetGraph()).Check();
2728 }
2729
TEST_F(ConstFoldingTest,Constant32CompareAETest)2730 TEST_F(ConstFoldingTest, Constant32CompareAETest)
2731 {
2732 auto graph = CreateEmptyBytecodeGraph();
2733 GRAPH(graph)
2734 {
2735 CONSTANT(0U, 3U);
2736 CONSTANT(1U, 3U);
2737 BASIC_BLOCK(2U, 1U)
2738 {
2739 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT32).CC(CC_AE).Inputs(0U, 1U);
2740 INST(3U, Opcode::Return).b().Inputs(2U);
2741 }
2742 }
2743 int result = 1;
2744 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2745 auto inst = graph->FindConstant(DataType::INT32, result);
2746 ASSERT(inst != nullptr);
2747 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2748 GraphChecker(graph).Check();
2749 }
2750
TEST_F(ConstFoldingTest,CompareZeroWithNullPtr)2751 TEST_F(ConstFoldingTest, CompareZeroWithNullPtr)
2752 {
2753 for (auto cc : {CC_EQ, CC_NE}) {
2754 auto graph = CreateEmptyGraph();
2755 GRAPH(graph)
2756 {
2757 CONSTANT(0U, 0U);
2758 CONSTANT(1U, nullptr);
2759 BASIC_BLOCK(2U, 1U)
2760 {
2761 INST(2U, Opcode::Compare).b().CC(cc).Inputs(0U, 1U);
2762 INST(3U, Opcode::Return).b().Inputs(2U);
2763 }
2764 }
2765 ASSERT_TRUE(ConstFoldingCompare(&INS(2U)));
2766 ASSERT_TRUE(graph->RunPass<Cleanup>());
2767 auto expGraph = CreateEmptyGraph();
2768 GRAPH(expGraph)
2769 {
2770 CONSTANT(0U, (cc == CC_EQ ? 1U : 0U));
2771 BASIC_BLOCK(2U, 1U)
2772 {
2773 INST(3U, Opcode::Return).b().Inputs(0U);
2774 }
2775 }
2776 ASSERT_TRUE(GraphComparator().Compare(graph, expGraph));
2777 }
2778 }
2779
TEST_F(ConstFoldingTest,CompareTstEqTest)2780 TEST_F(ConstFoldingTest, CompareTstEqTest)
2781 {
2782 GRAPH(GetGraph())
2783 {
2784 CONSTANT(0U, 1U);
2785 CONSTANT(1U, 2U);
2786 BASIC_BLOCK(2U, 1U)
2787 {
2788 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_TST_EQ).Inputs(0U, 1U);
2789 INST(3U, Opcode::Return).b().Inputs(2U);
2790 }
2791 }
2792 int result = 1;
2793 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2794 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2795 ASSERT(inst != nullptr);
2796 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2797 GraphChecker(GetGraph()).Check();
2798 }
2799
TEST_F(ConstFoldingTest,CompareTstEqTest1)2800 TEST_F(ConstFoldingTest, CompareTstEqTest1)
2801 {
2802 GRAPH(GetGraph())
2803 {
2804 CONSTANT(0U, 3U);
2805 CONSTANT(1U, 2U);
2806 BASIC_BLOCK(2U, 1U)
2807 {
2808 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_TST_EQ).Inputs(0U, 1U);
2809 INST(3U, Opcode::Return).b().Inputs(2U);
2810 }
2811 }
2812 int result = 0;
2813 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2814 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2815 ASSERT(inst != nullptr);
2816 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2817 GraphChecker(GetGraph()).Check();
2818 }
2819
TEST_F(ConstFoldingTest,CompareTstNeTest)2820 TEST_F(ConstFoldingTest, CompareTstNeTest)
2821 {
2822 GRAPH(GetGraph())
2823 {
2824 CONSTANT(0U, 1U);
2825 CONSTANT(1U, 2U);
2826 BASIC_BLOCK(2U, 1U)
2827 {
2828 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_TST_NE).Inputs(0U, 1U);
2829 INST(3U, Opcode::Return).b().Inputs(2U);
2830 }
2831 }
2832 int result = 0;
2833 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2834 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2835 ASSERT(inst != nullptr);
2836 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2837 GraphChecker(GetGraph()).Check();
2838 }
2839
TEST_F(ConstFoldingTest,CompareTstNeTest1)2840 TEST_F(ConstFoldingTest, CompareTstNeTest1)
2841 {
2842 GRAPH(GetGraph())
2843 {
2844 CONSTANT(0U, 3U);
2845 CONSTANT(1U, 2U);
2846 BASIC_BLOCK(2U, 1U)
2847 {
2848 INST(2U, Opcode::Compare).b().SrcType(DataType::Type::INT64).CC(CC_TST_NE).Inputs(0U, 1U);
2849 INST(3U, Opcode::Return).b().Inputs(2U);
2850 }
2851 }
2852 int result = 1;
2853 ASSERT_EQ(ConstFoldingCompare(&INS(2U)), true);
2854 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
2855 ASSERT(inst != nullptr);
2856 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
2857 GraphChecker(GetGraph()).Check();
2858 }
2859
TEST_F(ConstFoldingTest,CompareEqualInputsTest)2860 TEST_F(ConstFoldingTest, CompareEqualInputsTest)
2861 {
2862 for (int ccInt = CC_LT; ccInt <= CC_AE; ++ccInt) {
2863 auto cc = static_cast<ConditionCode>(ccInt);
2864 for (auto type : {DataType::INT32, DataType::INT64, DataType::FLOAT64}) {
2865 std::optional<bool> result;
2866 switch (cc) {
2867 case ConditionCode::CC_EQ:
2868 case ConditionCode::CC_LE:
2869 case ConditionCode::CC_GE:
2870 case ConditionCode::CC_BE:
2871 case ConditionCode::CC_AE:
2872 if (!IsFloatType(type)) {
2873 result = true;
2874 }
2875 break;
2876 case ConditionCode::CC_NE:
2877 if (!IsFloatType(type)) {
2878 result = false;
2879 }
2880 break;
2881 case ConditionCode::CC_LT:
2882 case ConditionCode::CC_GT:
2883 case ConditionCode::CC_B:
2884 case ConditionCode::CC_A:
2885 result = false;
2886 break;
2887 default:
2888 UNREACHABLE();
2889 }
2890 CheckCompareEqualInputs(type, cc, result);
2891 }
2892 }
2893 }
2894
TEST_F(ConstFoldingTest,CompareLoadImmediateTest)2895 TEST_F(ConstFoldingTest, CompareLoadImmediateTest)
2896 {
2897 auto class1 = reinterpret_cast<RuntimeInterface::ClassPtr>(1U);
2898 auto class2 = reinterpret_cast<RuntimeInterface::ClassPtr>(2U);
2899 CheckCompareLoadImmediate(class1, class1, ConditionCode::CC_EQ, 1U);
2900 CheckCompareLoadImmediate(class1, class2, ConditionCode::CC_EQ, 0U);
2901 CheckCompareLoadImmediate(class1, class1, ConditionCode::CC_NE, 0U);
2902 CheckCompareLoadImmediate(class1, class2, ConditionCode::CC_NE, 1U);
2903 }
2904
TEST_F(ConstFoldingTest,DivZeroTest)2905 TEST_F(ConstFoldingTest, DivZeroTest)
2906 {
2907 GRAPH(GetGraph())
2908 {
2909 CONSTANT(0U, 3U);
2910 CONSTANT(1U, 0U);
2911 BASIC_BLOCK(2U, 1U)
2912 {
2913 INST(2U, Opcode::Div).u64().Inputs(0U, 1U);
2914 INST(3U, Opcode::Return).u64().Inputs(2U);
2915 }
2916 }
2917 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), false);
2918 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(2U));
2919 GraphChecker(GetGraph()).Check();
2920 }
2921
TEST_F(ConstFoldingTest,Constant32DivZeroTest)2922 TEST_F(ConstFoldingTest, Constant32DivZeroTest)
2923 {
2924 auto graph = CreateEmptyBytecodeGraph();
2925 GRAPH(graph)
2926 {
2927 CONSTANT(0U, 3U);
2928 CONSTANT(1U, 0U);
2929 BASIC_BLOCK(2U, 1U)
2930 {
2931 INST(2U, Opcode::Div).u32().Inputs(0U, 1U);
2932 INST(3U, Opcode::Return).u32().Inputs(2U);
2933 }
2934 }
2935 ASSERT_EQ(ConstFoldingDiv(&INS(2U)), false);
2936 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(2U));
2937 GraphChecker(graph).Check();
2938 }
2939
TEST_F(ConstFoldingTest,ModZeroTest)2940 TEST_F(ConstFoldingTest, ModZeroTest)
2941 {
2942 GRAPH(GetGraph())
2943 {
2944 CONSTANT(0U, 3U);
2945 CONSTANT(1U, 0U);
2946 BASIC_BLOCK(2U, 1U)
2947 {
2948 INST(2U, Opcode::Mod).u64().Inputs(0U, 1U);
2949 INST(3U, Opcode::Return).u64().Inputs(2U);
2950 }
2951 }
2952 ASSERT_EQ(ConstFoldingMod(&INS(2U)), false);
2953 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(2U));
2954 GraphChecker(GetGraph()).Check();
2955 }
2956
TEST_F(ConstFoldingTest,Constant32ModZeroTest)2957 TEST_F(ConstFoldingTest, Constant32ModZeroTest)
2958 {
2959 auto graph = CreateEmptyBytecodeGraph();
2960 GRAPH(graph)
2961 {
2962 CONSTANT(0U, 3U);
2963 CONSTANT(1U, 0U);
2964 BASIC_BLOCK(2U, 1U)
2965 {
2966 INST(2U, Opcode::Mod).u32().Inputs(0U, 1U);
2967 INST(3U, Opcode::Return).u32().Inputs(2U);
2968 }
2969 }
2970 ASSERT_EQ(ConstFoldingMod(&INS(2U)), false);
2971 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(2U));
2972 GraphChecker(graph).Check();
2973 }
2974
TEST_F(ConstFoldingTest,MulIntZeroTest)2975 TEST_F(ConstFoldingTest, MulIntZeroTest)
2976 {
2977 GRAPH(GetGraph())
2978 {
2979 PARAMETER(0U, 25U).u64();
2980 CONSTANT(1U, 0U);
2981 BASIC_BLOCK(2U, 1U)
2982 {
2983 INST(2U, Opcode::Mul).u64().Inputs(0U, 1U);
2984 INST(3U, Opcode::Return).u64().Inputs(2U);
2985 }
2986 }
2987 ASSERT_EQ(ConstFoldingMul(&INS(2U)), true);
2988 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(1U));
2989 GraphChecker(GetGraph()).Check();
2990 }
2991
TEST_F(ConstFoldingTest,Constant32MulIntZeroTest)2992 TEST_F(ConstFoldingTest, Constant32MulIntZeroTest)
2993 {
2994 auto graph = CreateEmptyBytecodeGraph();
2995 GRAPH(graph)
2996 {
2997 PARAMETER(0U, 25U).u32();
2998 CONSTANT(1U, 0U);
2999 BASIC_BLOCK(2U, 1U)
3000 {
3001 INST(2U, Opcode::Mul).u32().Inputs(0U, 1U);
3002 INST(3U, Opcode::Return).u32().Inputs(2U);
3003 }
3004 }
3005 ASSERT_EQ(ConstFoldingMul(&INS(2U)), true);
3006 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(1U));
3007 GraphChecker(graph).Check();
3008 }
3009
TEST_F(ConstFoldingTest,MulFloatZeroTest)3010 TEST_F(ConstFoldingTest, MulFloatZeroTest)
3011 {
3012 GRAPH(GetGraph())
3013 {
3014 CONSTANT(0U, static_cast<float>(3.0F));
3015 CONSTANT(1U, static_cast<float>(0.0F));
3016 BASIC_BLOCK(2U, 1U)
3017 {
3018 INST(2U, Opcode::Mul).f32().Inputs(0U, 1U);
3019 INST(3U, Opcode::Return).f32().Inputs(2U);
3020 }
3021 }
3022 ASSERT_EQ(ConstFoldingMul(&INS(2U)), true);
3023 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(1U));
3024 GraphChecker(GetGraph()).Check();
3025 }
3026
TEST_F(ConstFoldingTest,MulDoubleZeroTest)3027 TEST_F(ConstFoldingTest, MulDoubleZeroTest)
3028 {
3029 GRAPH(GetGraph())
3030 {
3031 CONSTANT(0U, 3.0_D);
3032 CONSTANT(1U, 0.0);
3033 BASIC_BLOCK(2U, 1U)
3034 {
3035 INST(2U, Opcode::Mul).f64().Inputs(0U, 1U);
3036 INST(3U, Opcode::Return).f64().Inputs(2U);
3037 }
3038 }
3039 ASSERT_EQ(ConstFoldingMul(&INS(2U)), true);
3040 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(1U));
3041 GraphChecker(GetGraph()).Check();
3042 }
3043
TEST_F(ConstFoldingTest,AndZeroTest)3044 TEST_F(ConstFoldingTest, AndZeroTest)
3045 {
3046 GRAPH(GetGraph())
3047 {
3048 PARAMETER(0U, 25U).u64();
3049 CONSTANT(1U, 0U);
3050 BASIC_BLOCK(2U, 1U)
3051 {
3052 INST(2U, Opcode::And).u64().Inputs(0U, 1U);
3053 INST(3U, Opcode::Return).u64().Inputs(2U);
3054 }
3055 }
3056 ASSERT_EQ(ConstFoldingAnd(&INS(2U)), true);
3057 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(1U));
3058 GraphChecker(GetGraph()).Check();
3059 }
3060
TEST_F(ConstFoldingTest,Constant32AndZeroTest)3061 TEST_F(ConstFoldingTest, Constant32AndZeroTest)
3062 {
3063 auto graph = CreateEmptyBytecodeGraph();
3064 GRAPH(graph)
3065 {
3066 PARAMETER(0U, 25U).u32();
3067 CONSTANT(1U, 0U);
3068 BASIC_BLOCK(2U, 1U)
3069 {
3070 INST(2U, Opcode::And).u32().Inputs(0U, 1U);
3071 INST(3U, Opcode::Return).u32().Inputs(2U);
3072 }
3073 }
3074 ASSERT_EQ(ConstFoldingAnd(&INS(2U)), true);
3075 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(1U));
3076 GraphChecker(graph).Check();
3077 }
3078
TEST_F(ConstFoldingTest,OrMinusOneTest)3079 TEST_F(ConstFoldingTest, OrMinusOneTest)
3080 {
3081 GRAPH(GetGraph())
3082 {
3083 PARAMETER(0U, 25U).u64();
3084 CONSTANT(1U, -1L);
3085 BASIC_BLOCK(2U, 1U)
3086 {
3087 INST(2U, Opcode::Or).u64().Inputs(0U, 1U);
3088 INST(3U, Opcode::Return).u64().Inputs(2U);
3089 }
3090 }
3091 ASSERT_EQ(ConstFoldingOr(&INS(2U)), true);
3092 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(1U));
3093 GraphChecker(GetGraph()).Check();
3094 }
3095
TEST_F(ConstFoldingTest,Constant32OrMinusOneTest)3096 TEST_F(ConstFoldingTest, Constant32OrMinusOneTest)
3097 {
3098 auto graph = CreateEmptyBytecodeGraph();
3099 GRAPH(graph)
3100 {
3101 PARAMETER(0U, 25U).u32();
3102 CONSTANT(1U, -1L);
3103 BASIC_BLOCK(2U, 1U)
3104 {
3105 INST(2U, Opcode::Or).u32().Inputs(0U, 1U);
3106 INST(3U, Opcode::Return).u32().Inputs(2U);
3107 }
3108 }
3109 ASSERT_EQ(ConstFoldingOr(&INS(2U)), true);
3110 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(1U));
3111 GraphChecker(graph).Check();
3112 }
3113
TEST_F(ConstFoldingTest,XorEqualInputs)3114 TEST_F(ConstFoldingTest, XorEqualInputs)
3115 {
3116 GRAPH(GetGraph())
3117 {
3118 PARAMETER(0U, 25U).u64();
3119 BASIC_BLOCK(2U, 1U)
3120 {
3121 INST(2U, Opcode::Xor).u64().Inputs(0U, 0U);
3122 INST(3U, Opcode::Return).u64().Inputs(2U);
3123 }
3124 }
3125 ASSERT_EQ(ConstFoldingXor(&INS(2U)), true);
3126 int result = 0;
3127 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
3128 ASSERT(inst != nullptr);
3129 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
3130 GraphChecker(GetGraph()).Check();
3131 }
3132
TEST_F(ConstFoldingTest,Constant32XorEqualInputs)3133 TEST_F(ConstFoldingTest, Constant32XorEqualInputs)
3134 {
3135 auto graph = CreateEmptyBytecodeGraph();
3136 GRAPH(graph)
3137 {
3138 PARAMETER(0U, 25U).u32();
3139 BASIC_BLOCK(2U, 1U)
3140 {
3141 INST(2U, Opcode::Xor).u32().Inputs(0U, 0U);
3142 INST(3U, Opcode::Return).u32().Inputs(2U);
3143 }
3144 }
3145 ASSERT_EQ(ConstFoldingXor(&INS(2U)), true);
3146 int result = 0;
3147 auto inst = graph->FindConstant(DataType::INT32, result);
3148 ASSERT(inst != nullptr);
3149 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
3150 GraphChecker(graph).Check();
3151 }
3152
TEST_F(ConstFoldingTest,ShlBigOffsetTest)3153 TEST_F(ConstFoldingTest, ShlBigOffsetTest)
3154 {
3155 GRAPH(GetGraph())
3156 {
3157 PARAMETER(0U, 25U).u64();
3158 CONSTANT(1U, 20U);
3159 BASIC_BLOCK(2U, 1U)
3160 {
3161 INST(2U, Opcode::Shl).u16().Inputs(0U, 1U);
3162 INST(3U, Opcode::Return).u16().Inputs(2U);
3163 }
3164 }
3165 ASSERT_EQ(ConstFoldingShl(&INS(2U)), false);
3166 ASSERT_TRUE(CheckInputs(INS(2U), {0U, 1U}));
3167 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(2U));
3168 GraphChecker(GetGraph()).Check();
3169 }
3170
TEST_F(ConstFoldingTest,Constant32ShlBigOffsetTest)3171 TEST_F(ConstFoldingTest, Constant32ShlBigOffsetTest)
3172 {
3173 auto graph = CreateEmptyBytecodeGraph();
3174 GRAPH(graph)
3175 {
3176 PARAMETER(0U, 25U).u32();
3177 CONSTANT(1U, 20U);
3178 BASIC_BLOCK(2U, 1U)
3179 {
3180 INST(2U, Opcode::Shl).u16().Inputs(0U, 1U);
3181 INST(3U, Opcode::Return).u16().Inputs(2U);
3182 }
3183 }
3184 ASSERT_EQ(ConstFoldingShl(&INS(2U)), false);
3185 ASSERT_TRUE(CheckInputs(INS(2U), {0U, 1U}));
3186 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(2U));
3187 GraphChecker(graph).Check();
3188 }
3189
TEST_F(ConstFoldingTest,ShrBigOffsetTest)3190 TEST_F(ConstFoldingTest, ShrBigOffsetTest)
3191 {
3192 GRAPH(GetGraph())
3193 {
3194 PARAMETER(0U, 25U).u64();
3195 CONSTANT(1U, 20U);
3196 BASIC_BLOCK(2U, 1U)
3197 {
3198 INST(2U, Opcode::Shr).u16().Inputs(0U, 1U);
3199 INST(3U, Opcode::Return).u16().Inputs(2U);
3200 }
3201 }
3202 ASSERT_EQ(ConstFoldingShr(&INS(2U)), false);
3203 ASSERT_TRUE(CheckInputs(INS(2U), {0U, 1U}));
3204 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(2U));
3205 GraphChecker(GetGraph()).Check();
3206 }
3207
TEST_F(ConstFoldingTest,Constant32ShrBigOffsetTest)3208 TEST_F(ConstFoldingTest, Constant32ShrBigOffsetTest)
3209 {
3210 auto graph = CreateEmptyBytecodeGraph();
3211 GRAPH(graph)
3212 {
3213 PARAMETER(0U, 25U).u32();
3214 CONSTANT(1U, 20U);
3215 BASIC_BLOCK(2U, 1U)
3216 {
3217 INST(2U, Opcode::Shr).u16().Inputs(0U, 1U);
3218 INST(3U, Opcode::Return).u16().Inputs(2U);
3219 }
3220 }
3221 ASSERT_EQ(ConstFoldingShr(&INS(2U)), false);
3222 ASSERT_TRUE(CheckInputs(INS(2U), {0U, 1U}));
3223 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), &INS(2U));
3224 GraphChecker(graph).Check();
3225 }
3226
TEST_F(ConstFoldingTest,CastTest)3227 TEST_F(ConstFoldingTest, CastTest)
3228 {
3229 uint8_t srcU8 = 0xff;
3230 CastTest(srcU8, static_cast<int8_t>(srcU8), DataType::INT8);
3231 CastTest(srcU8, static_cast<int16_t>(srcU8), DataType::INT16);
3232 CastTest(srcU8, static_cast<uint16_t>(srcU8), DataType::UINT16);
3233
3234 int8_t srcI8 = -1;
3235 CastTest(srcI8, static_cast<float>(srcI8), DataType::FLOAT32);
3236
3237 uint16_t srcU16 = 0xffff;
3238 CastTest(srcU16, static_cast<int8_t>(srcU16), DataType::INT8);
3239 CastTest(srcU16, static_cast<double>(srcU16), DataType::FLOAT64);
3240 CastTest(srcU16, srcU16, DataType::UINT16);
3241
3242 int64_t srcI64 = -1;
3243 CastTest(srcI64, static_cast<uint8_t>(srcI64), DataType::UINT8);
3244
3245 int32_t srcI32 = -1;
3246 CastTest(srcI32, static_cast<int8_t>(srcI32), DataType::INT8);
3247
3248 float srcF = 0.25;
3249 CastTest(srcF, srcF, DataType::FLOAT32);
3250
3251 double srcD = 0.25;
3252 CastTest(srcD, srcD, DataType::FLOAT64);
3253
3254 CastTest(FLT_MAX, static_cast<double>(FLT_MAX), DataType::FLOAT64);
3255 CastTest(FLT_MIN, static_cast<double>(FLT_MIN), DataType::FLOAT64);
3256
3257 // NOTE (schernykh) : ub test? - convert from double_max to float
3258 // DBL_MAX, static_cast<float>(DBL_MAX), DataType::FLOAT32
3259 CastTest(DBL_MIN, static_cast<float>(DBL_MIN), DataType::FLOAT32);
3260
3261 CastTest(0.0F, static_cast<uint64_t>(0.0F), DataType::UINT64);
3262 // FLOAT->INT32
3263 CastTest(FLT_MAX, INT32_MAX, DataType::INT32);
3264 CastTest(-FLT_MAX, INT32_MIN, DataType::INT32);
3265 CastTest(nanf(""), static_cast<int32_t>(0U), DataType::INT32);
3266 CastTest(32.0F, static_cast<int32_t>(32.0F), DataType::INT32);
3267 // FLOAT->INT64
3268 CastTest(FLT_MAX, INT64_MAX, DataType::INT64);
3269 CastTest(-FLT_MAX, INT64_MIN, DataType::INT64);
3270 CastTest(nanf(""), static_cast<int64_t>(0U), DataType::INT64);
3271 CastTest(32.0F, static_cast<int64_t>(32.0F), DataType::INT64);
3272 // DOUBLE->INT32
3273 CastTest(DBL_MAX, INT32_MAX, DataType::INT32);
3274 CastTest(-DBL_MAX, INT32_MIN, DataType::INT32);
3275 CastTest(nan(""), static_cast<int32_t>(0U), DataType::INT32);
3276 CastTest(64.0_D, static_cast<int32_t>(64.0_D), DataType::INT32);
3277 // DOUBLE->INT64
3278 CastTest(DBL_MAX, INT64_MAX, DataType::INT64);
3279 CastTest(-DBL_MAX, INT64_MIN, DataType::INT64);
3280 CastTest(nan(""), static_cast<int64_t>(0U), DataType::INT64);
3281 CastTest(64.0_D, static_cast<int64_t>(64.0_D), DataType::INT64);
3282 }
3283
TEST_F(ConstFoldingTest,CmpTest)3284 TEST_F(ConstFoldingTest, CmpTest)
3285 {
3286 CmpTest(0U, 1U, -1L, DataType::INT32);
3287 CmpTest(1U, 0U, 1U, DataType::INT32);
3288 CmpTest(0U, 0U, 0U, DataType::INT32);
3289
3290 CmpTest(0L, -1L, -1L, DataType::UINT32);
3291 CmpTest(INT64_MIN, INT64_MAX, -1L, DataType::INT64);
3292 CmpTest(INT64_MAX, INT64_MIN, 1U, DataType::INT64);
3293
3294 CmpTest(0.0F, 1.0F, -1L, DataType::FLOAT32);
3295 CmpTest(1.0F, 0.0F, 1U, DataType::FLOAT32);
3296 CmpTest(0.0F, 0.0F, 0U, DataType::FLOAT32);
3297
3298 CmpTest(0.0, 1.0, -1L, DataType::FLOAT64);
3299 CmpTest(1.0, 0.0, 1U, DataType::FLOAT64);
3300 CmpTest(0.0, 0.0, 0U, DataType::FLOAT64);
3301
3302 CmpTest(std::nan("0"), 1.0, -1L, DataType::FLOAT64);
3303 CmpTest(1.0, std::nan("0"), -1L, DataType::FLOAT64);
3304 CmpTest(std::nan("0"), 1.0, 1U, DataType::FLOAT64, true);
3305 CmpTest(1.0, std::nan("0"), 1U, DataType::FLOAT64, true);
3306
3307 CmpTest(std::nanf("0"), 1.0F, -1L, DataType::FLOAT32);
3308 CmpTest(1.0F, std::nanf("0"), -1L, DataType::FLOAT32);
3309 CmpTest(std::nanf("0"), 1.0F, 1U, DataType::FLOAT32, true);
3310 CmpTest(1.0F, std::nanf("0"), 1U, DataType::FLOAT32, true);
3311 }
3312
TEST_F(ConstFoldingTest,CmpEqualInputsIntTest)3313 TEST_F(ConstFoldingTest, CmpEqualInputsIntTest)
3314 {
3315 GRAPH(GetGraph())
3316 {
3317 PARAMETER(0U, 25U).u64();
3318 BASIC_BLOCK(2U, 1U)
3319 {
3320 INST(2U, Opcode::Cmp).i32().Inputs(0U, 0U);
3321 INST(3U, Opcode::Return).i32().Inputs(2U);
3322 }
3323 }
3324 ASSERT_EQ(ConstFoldingCmp(&INS(2U)), true);
3325 int result = 0;
3326 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
3327 ASSERT(inst != nullptr);
3328 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
3329 GraphChecker(GetGraph()).Check();
3330 }
3331
TEST_F(ConstFoldingTest,CmpEqualInputsDoubleTest)3332 TEST_F(ConstFoldingTest, CmpEqualInputsDoubleTest)
3333 {
3334 GRAPH(GetGraph())
3335 {
3336 PARAMETER(0U, 25U).f64();
3337 BASIC_BLOCK(2U, 1U)
3338 {
3339 INST(2U, Opcode::Cmp).i32().Inputs(0U, 0U);
3340 INST(3U, Opcode::Return).i32().Inputs(2U);
3341 }
3342 }
3343 ASSERT_EQ(ConstFoldingCmp(&INS(2U)), false);
3344 }
3345
TEST_F(ConstFoldingTest,SqrtTest)3346 TEST_F(ConstFoldingTest, SqrtTest)
3347 {
3348 GRAPH(GetGraph())
3349 {
3350 CONSTANT(1U, 0.78539816339744828F);
3351 BASIC_BLOCK(2U, 1U)
3352 {
3353 INST(2U, Opcode::Sqrt).f32().Inputs(1U);
3354 INST(3U, Opcode::Return).f32().Inputs(2U);
3355 }
3356 }
3357 float result = 0.88622695207595825;
3358 ASSERT_EQ(ConstFoldingSqrt(&INS(2U)), true);
3359 auto inst = GetGraph()->FindConstant(DataType::FLOAT32, bit_cast<uint32_t, float>(result));
3360 ASSERT(inst != nullptr);
3361 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
3362 GraphChecker(GetGraph()).Check();
3363 }
3364
TEST_F(ConstFoldingTest,MaxIntTest1)3365 TEST_F(ConstFoldingTest, MaxIntTest1)
3366 {
3367 GRAPH(GetGraph())
3368 {
3369 CONSTANT(0U, -1L);
3370 CONSTANT(1U, 2U);
3371 BASIC_BLOCK(2U, 1U)
3372 {
3373 INST(2U, Opcode::Max).s64().Inputs(0U, 1U);
3374 INST(3U, Opcode::Return).s64().Inputs(2U);
3375 }
3376 }
3377 int result = 2;
3378 ASSERT_EQ(ConstFoldingMax(&INS(2U)), true);
3379 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
3380 ASSERT(inst != nullptr);
3381 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
3382 GraphChecker(GetGraph()).Check();
3383 }
3384
TEST_F(ConstFoldingTest,MinIntTest1)3385 TEST_F(ConstFoldingTest, MinIntTest1)
3386 {
3387 GRAPH(GetGraph())
3388 {
3389 CONSTANT(0U, -1L);
3390 CONSTANT(1U, 2U);
3391 BASIC_BLOCK(2U, 1U)
3392 {
3393 INST(2U, Opcode::Min).s64().Inputs(0U, 1U);
3394 INST(3U, Opcode::Return).s64().Inputs(2U);
3395 }
3396 }
3397 int result = -1;
3398 ASSERT_EQ(ConstFoldingMin(&INS(2U)), true);
3399 auto inst = GetGraph()->FindConstant(DataType::INT64, result);
3400 ASSERT(inst != nullptr);
3401 ASSERT_EQ(INS(3U).GetInput(0U).GetInst(), inst);
3402 GraphChecker(GetGraph()).Check();
3403 }
3404 // NOLINTEND(readability-magic-numbers)
3405
3406 } // namespace ark::compiler
3407