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