• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 "unit_test.h"
17 #include "optimizer/optimizations/vn.h"
18 #include "optimizer/optimizations/cleanup.h"
19 #include "optimizer/ir/graph_cloner.h"
20 
21 namespace panda::compiler {
22 class VNTest : public AsmTest {
23 public:
VNTest()24     VNTest() : graph_(CreateGraphWithDefaultRuntime()) {}
25 
GetGraph()26     Graph *GetGraph() override
27     {
28         return graph_;
29     }
30 
31 private:
32     Graph *graph_;
33 };
34 
TEST_F(VNTest,VnTestApply1)35 TEST_F(VNTest, VnTestApply1)
36 {
37     // Remove duplicate arithmetic instructions
38     GRAPH(GetGraph())
39     {
40         PARAMETER(0, 0).u64();
41         PARAMETER(1, 1).u64();
42         PARAMETER(2, 2).f64();
43         PARAMETER(3, 3).f64();
44         PARAMETER(4, 4).f32();
45         PARAMETER(5, 5).f32();
46 
47         BASIC_BLOCK(2, -1)
48         {
49             INST(6, Opcode::Add).u64().Inputs(0, 1);
50             INST(7, Opcode::Sub).u32().Inputs(1, 0);
51             INST(8, Opcode::Mul).f32().Inputs(4, 5);
52             INST(9, Opcode::Div).f64().Inputs(3, 2);
53             INST(10, Opcode::Sub).u32().Inputs(1, 0);
54             INST(11, Opcode::Div).f64().Inputs(3, 2);
55             INST(12, Opcode::Mul).f32().Inputs(4, 5);
56             INST(13, Opcode::Add).u64().Inputs(0, 1);
57             INST(20, Opcode::SaveState).NoVregs();
58             INST(14, Opcode::CallStatic).b().InputsAutoType(6, 7, 8, 9, 10, 11, 12, 13, 20);
59             INST(15, Opcode::ReturnVoid);
60         }
61     }
62     Graph *graph_et = CreateGraphWithDefaultRuntime();
63     GRAPH(graph_et)
64     {
65         PARAMETER(0, 0).u64();
66         PARAMETER(1, 1).u64();
67         PARAMETER(2, 2).f64();
68         PARAMETER(3, 3).f64();
69         PARAMETER(4, 4).f32();
70         PARAMETER(5, 5).f32();
71 
72         BASIC_BLOCK(2, -1)
73         {
74             INST(6, Opcode::Add).u64().Inputs(0, 1);
75             INST(7, Opcode::Sub).u32().Inputs(1, 0);
76             INST(8, Opcode::Mul).f32().Inputs(4, 5);
77             INST(9, Opcode::Div).f64().Inputs(3, 2);
78             INST(10, Opcode::Sub).u32().Inputs(1, 0);
79             INST(11, Opcode::Div).f64().Inputs(3, 2);
80             INST(12, Opcode::Mul).f32().Inputs(4, 5);
81             INST(13, Opcode::Add).u64().Inputs(0, 1);
82             INST(20, Opcode::SaveState).NoVregs();
83             INST(14, Opcode::CallStatic).b().InputsAutoType(6, 7, 8, 9, 7, 9, 8, 6, 20);
84             INST(15, Opcode::ReturnVoid);
85         }
86     }
87 
88     GetGraph()->RunPass<ValNum>();
89     GraphChecker(GetGraph()).Check();
90     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
91 }
92 
TEST_F(VNTest,VnTestApply2)93 TEST_F(VNTest, VnTestApply2)
94 {
95     // Remove duplicate Cast,  AddI, Fcmp and Cmp instructions
96     GRAPH(GetGraph())
97     {
98         PARAMETER(0, 0).u64();
99         PARAMETER(1, 1).u64();
100         PARAMETER(2, 2).f64();
101         PARAMETER(3, 3).f64();
102         PARAMETER(4, 4).f32();
103         PARAMETER(5, 5).f32();
104 
105         BASIC_BLOCK(2, 3, 4)
106         {
107             INST(6, Opcode::Cast).u64().SrcType(DataType::FLOAT64).Inputs(2);
108             INST(7, Opcode::AddI).u32().Imm(10ULL).Inputs(1);
109             INST(8, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT64).Fcmpg(true).Inputs(2, 3);
110             INST(9, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT32).Fcmpg(false).Inputs(4, 5);
111             INST(10, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1);
112             INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10);
113         }
114         BASIC_BLOCK(3, -1)
115         {
116             INST(23, Opcode::SaveState).NoVregs();
117             INST(12, Opcode::CallStatic).b().InputsAutoType(6, 7, 8, 9, 23);
118             INST(13, Opcode::ReturnVoid);
119         }
120         BASIC_BLOCK(4, 5, 6)
121         {
122             INST(14, Opcode::Cast).u64().SrcType(DataType::FLOAT64).Inputs(2);
123             INST(15, Opcode::AddI).u32().Imm(10ULL).Inputs(1);
124             INST(16, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT64).Fcmpg(true).Inputs(2, 3);
125             INST(17, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT32).Fcmpg(false).Inputs(4, 5);
126             INST(18, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1);
127             INST(19, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(18);
128         }
129         BASIC_BLOCK(5, -1)
130         {
131             INST(24, Opcode::SaveState).NoVregs();
132             INST(20, Opcode::CallStatic).b().InputsAutoType(17, 16, 15, 14, 24);
133             INST(21, Opcode::ReturnVoid);
134         }
135         BASIC_BLOCK(6, -1)
136         {
137             INST(22, Opcode::ReturnVoid);
138         }
139     }
140     Graph *graph_et = CreateGraphWithDefaultRuntime();
141     GRAPH(graph_et)
142     {
143         PARAMETER(0, 0).u64();
144         PARAMETER(1, 1).u64();
145         PARAMETER(2, 2).f64();
146         PARAMETER(3, 3).f64();
147         PARAMETER(4, 4).f32();
148         PARAMETER(5, 5).f32();
149 
150         BASIC_BLOCK(2, 3, 4)
151         {
152             INST(6, Opcode::Cast).u64().SrcType(DataType::FLOAT64).Inputs(2);
153             INST(7, Opcode::AddI).u32().Imm(10ULL).Inputs(1);
154             INST(8, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT64).Fcmpg(true).Inputs(2, 3);
155             INST(9, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT32).Fcmpg(false).Inputs(4, 5);
156             INST(10, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1);
157             INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10);
158         }
159         BASIC_BLOCK(3, -1)
160         {
161             INST(23, Opcode::SaveState).NoVregs();
162             INST(12, Opcode::CallStatic).b().InputsAutoType(6, 7, 8, 9, 23);
163             INST(13, Opcode::ReturnVoid);
164         }
165         BASIC_BLOCK(4, 5, 6)
166         {
167             INST(14, Opcode::Cast).u64().SrcType(DataType::FLOAT64).Inputs(2);
168             INST(15, Opcode::AddI).u32().Imm(10ULL).Inputs(1);
169             INST(16, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT64).Fcmpg(true).Inputs(2, 3);
170             INST(17, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT32).Fcmpg(false).Inputs(4, 5);
171             INST(18, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1);
172             INST(19, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10);
173         }
174         BASIC_BLOCK(5, -1)
175         {
176             INST(24, Opcode::SaveState).NoVregs();
177             INST(20, Opcode::CallStatic).b().InputsAutoType(9, 8, 7, 6, 24);
178             INST(21, Opcode::ReturnVoid);
179         }
180         BASIC_BLOCK(6, -1)
181         {
182             INST(22, Opcode::ReturnVoid);
183         }
184     }
185 
186     GetGraph()->RunPass<ValNum>();
187     GraphChecker(GetGraph()).Check();
188     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
189 }
190 
TEST_F(VNTest,VnTestNotApply1)191 TEST_F(VNTest, VnTestNotApply1)
192 {
193     // Arithmetic instructions has different type, inputs, opcodes
194     GRAPH(GetGraph())
195     {
196         PARAMETER(0, 0).u64();
197         PARAMETER(1, 1).u64();
198         PARAMETER(2, 2).f64();
199         PARAMETER(3, 3).f64();
200         PARAMETER(4, 4).f32();
201         PARAMETER(5, 5).f32();
202 
203         BASIC_BLOCK(2, -1)
204         {
205             INST(6, Opcode::Add).u64().Inputs(0, 1);
206             INST(7, Opcode::Add).u16().Inputs(0, 1);
207             INST(8, Opcode::Add).u32().Inputs(0, 7);
208             INST(9, Opcode::Div).f64().Inputs(2, 3);
209             INST(10, Opcode::Div).f64().Inputs(3, 2);
210             INST(11, Opcode::Mul).f64().Inputs(2, 3);
211             INST(12, Opcode::Sub).f32().Inputs(4, 5);
212             INST(13, Opcode::Sub).f32().Inputs(5, 4);
213             INST(14, Opcode::Abs).f32().Inputs(4);
214             INST(15, Opcode::Neg).f32().Inputs(4);
215             INST(20, Opcode::SaveState).NoVregs();
216             INST(16, Opcode::CallStatic).b().InputsAutoType(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20);
217             INST(17, Opcode::ReturnVoid);
218         }
219     }
220     Graph *graph_et = CreateGraphWithDefaultRuntime();
221     // graph_et is equal the graph
222     GRAPH(graph_et)
223     {
224         PARAMETER(0, 0).u64();
225         PARAMETER(1, 1).u64();
226         PARAMETER(2, 2).f64();
227         PARAMETER(3, 3).f64();
228         PARAMETER(4, 4).f32();
229         PARAMETER(5, 5).f32();
230 
231         BASIC_BLOCK(2, -1)
232         {
233             INST(6, Opcode::Add).u64().Inputs(0, 1);
234             INST(7, Opcode::Add).u16().Inputs(0, 1);
235             INST(8, Opcode::Add).u32().Inputs(0, 7);
236             INST(9, Opcode::Div).f64().Inputs(2, 3);
237             INST(10, Opcode::Div).f64().Inputs(3, 2);
238             INST(11, Opcode::Mul).f64().Inputs(2, 3);
239             INST(12, Opcode::Sub).f32().Inputs(4, 5);
240             INST(13, Opcode::Sub).f32().Inputs(5, 4);
241             INST(14, Opcode::Abs).f32().Inputs(4);
242             INST(15, Opcode::Neg).f32().Inputs(4);
243             INST(20, Opcode::SaveState).NoVregs();
244             INST(16, Opcode::CallStatic).b().InputsAutoType(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20);
245             INST(17, Opcode::ReturnVoid);
246         }
247     }
248 
249     GetGraph()->RunPass<ValNum>();
250     GraphChecker(GetGraph()).Check();
251     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
252 }
253 
TEST_F(VNTest,VnTestNotApply2)254 TEST_F(VNTest, VnTestNotApply2)
255 {
256     // Can't applies:
257     //  - Cast instructions have different types
258     //  - AddI instructions have different constant
259     //  - Fcmp instructions have different fcmpg flag
260     //  - Cmp instructions have different CC
261     GRAPH(GetGraph())
262     {
263         PARAMETER(0, 0).u64();
264         PARAMETER(1, 1).u64();
265         PARAMETER(2, 2).f64();
266         PARAMETER(3, 3).f64();
267         PARAMETER(4, 4).f32();
268         PARAMETER(5, 5).f32();
269 
270         BASIC_BLOCK(2, 3, 4)
271         {
272             INST(6, Opcode::Cast).u32().SrcType(DataType::FLOAT64).Inputs(2);
273             INST(7, Opcode::AddI).u32().Imm(9ULL).Inputs(1);
274             INST(8, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT64).Fcmpg(false).Inputs(2, 3);
275             INST(9, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT32).Fcmpg(true).Inputs(4, 5);
276             INST(10, Opcode::Compare).b().CC(CC_LT).Inputs(0, 1);
277             INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10);
278         }
279         BASIC_BLOCK(3, -1)
280         {
281             INST(23, Opcode::SaveState).NoVregs();
282             INST(12, Opcode::CallStatic).b().InputsAutoType(6, 7, 8, 9, 23);
283             INST(13, Opcode::ReturnVoid);
284         }
285         BASIC_BLOCK(4, 5, 6)
286         {
287             INST(14, Opcode::Cast).u64().SrcType(DataType::FLOAT64).Inputs(2);
288             INST(15, Opcode::AddI).u32().Imm(10ULL).Inputs(1);
289             INST(16, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT64).Fcmpg(true).Inputs(2, 3);
290             INST(17, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT32).Fcmpg(false).Inputs(4, 5);
291             INST(18, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1);
292             INST(19, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(18);
293         }
294         BASIC_BLOCK(5, -1)
295         {
296             INST(24, Opcode::SaveState).NoVregs();
297             INST(20, Opcode::CallStatic).b().InputsAutoType(17, 16, 15, 14, 24);
298             INST(21, Opcode::ReturnVoid);
299         }
300         BASIC_BLOCK(6, -1)
301         {
302             INST(22, Opcode::ReturnVoid);
303         }
304     }
305     Graph *graph_et = CreateGraphWithDefaultRuntime();
306     // graph_et is equal the graph
307     GRAPH(graph_et)
308     {
309         PARAMETER(0, 0).u64();
310         PARAMETER(1, 1).u64();
311         PARAMETER(2, 2).f64();
312         PARAMETER(3, 3).f64();
313         PARAMETER(4, 4).f32();
314         PARAMETER(5, 5).f32();
315 
316         BASIC_BLOCK(2, 3, 4)
317         {
318             INST(6, Opcode::Cast).u32().SrcType(DataType::FLOAT64).Inputs(2);
319             INST(7, Opcode::AddI).u32().Imm(9ULL).Inputs(1);
320             INST(8, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT64).Fcmpg(false).Inputs(2, 3);
321             INST(9, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT32).Fcmpg(true).Inputs(4, 5);
322             INST(10, Opcode::Compare).b().CC(CC_LT).Inputs(0, 1);
323             INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10);
324         }
325         BASIC_BLOCK(3, -1)
326         {
327             INST(23, Opcode::SaveState).NoVregs();
328             INST(12, Opcode::CallStatic).b().InputsAutoType(6, 7, 8, 9, 23);
329             INST(13, Opcode::ReturnVoid);
330         }
331         BASIC_BLOCK(4, 5, 6)
332         {
333             INST(14, Opcode::Cast).u64().SrcType(DataType::FLOAT64).Inputs(2);
334             INST(15, Opcode::AddI).u32().Imm(10ULL).Inputs(1);
335             INST(16, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT64).Fcmpg(true).Inputs(2, 3);
336             INST(17, Opcode::Cmp).s32().SrcType(DataType::Type::FLOAT32).Fcmpg(false).Inputs(4, 5);
337             INST(18, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1);
338             INST(19, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(18);
339         }
340         BASIC_BLOCK(5, -1)
341         {
342             INST(24, Opcode::SaveState).NoVregs();
343             INST(20, Opcode::CallStatic).b().InputsAutoType(17, 16, 15, 14, 24);
344             INST(21, Opcode::ReturnVoid);
345         }
346         BASIC_BLOCK(6, -1)
347         {
348             INST(22, Opcode::ReturnVoid);
349         }
350     }
351 
352     GetGraph()->RunPass<ValNum>();
353     GraphChecker(GetGraph()).Check();
354     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
355 }
356 
TEST_F(VNTest,VnTestNotApply3)357 TEST_F(VNTest, VnTestNotApply3)
358 {
359     // Can't applies:
360     //  - Arithmetic instructions aren't dominate
361     //  - CallStatic, LoadArray and StoreArray has NO_CSE
362     GRAPH(GetGraph())
363     {
364         PARAMETER(0, 0).u64();
365         PARAMETER(1, 1).u64();
366         PARAMETER(2, 2).f64();
367         PARAMETER(3, 3).f64();
368         PARAMETER(4, 4).ref();
369         PARAMETER(5, 5).ref();
370         PARAMETER(6, 6).s32();
371 
372         BASIC_BLOCK(2, 3, 4)
373         {
374             INST(7, Opcode::LoadArray).u64().Inputs(5, 6);
375             INST(8, Opcode::LoadArray).u64().Inputs(5, 6);
376             INST(9, Opcode::StoreArray).f64().Inputs(4, 6, 3);
377             INST(10, Opcode::StoreArray).f64().Inputs(4, 6, 3);
378             INST(11, Opcode::Compare).b().CC(CC_LT).Inputs(7, 8);
379             INST(12, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(11);
380         }
381         BASIC_BLOCK(3, -1)
382         {
383             INST(13, Opcode::Add).u64().Inputs(0, 1);
384             INST(14, Opcode::Sub).u64().Inputs(0, 1);
385             INST(15, Opcode::Mul).f64().Inputs(2, 3);
386             INST(16, Opcode::Div).f64().Inputs(2, 3);
387             INST(30, Opcode::SaveState).NoVregs();
388             INST(17, Opcode::CallStatic).b().InputsAutoType(13, 14, 15, 16, 30);
389             INST(18, Opcode::CallStatic).b().InputsAutoType(13, 14, 15, 16, 30);
390             INST(19, Opcode::ReturnVoid);
391         }
392         BASIC_BLOCK(4, -1)
393         {
394             INST(20, Opcode::Add).u64().Inputs(0, 1);
395             INST(21, Opcode::Sub).u64().Inputs(0, 1);
396             INST(22, Opcode::Mul).f64().Inputs(2, 3);
397             INST(23, Opcode::Div).f64().Inputs(2, 3);
398             INST(31, Opcode::SaveState).NoVregs();
399             INST(24, Opcode::CallStatic).b().InputsAutoType(20, 21, 22, 23, 31);
400             INST(25, Opcode::ReturnVoid);
401         }
402     }
403 
404     GetGraph()->RunPass<ValNum>();
405     GraphChecker(GetGraph()).Check();
406     ASSERT_EQ(INS(13).GetVN(), INS(20).GetVN());
407     ASSERT_EQ(INS(14).GetVN(), INS(21).GetVN());
408     ASSERT_EQ(INS(15).GetVN(), INS(22).GetVN());
409     ASSERT_EQ(INS(16).GetVN(), INS(23).GetVN());
410 
411     Graph *graph_et = CreateGraphWithDefaultRuntime();
412     // graph_et is equal the graph
413     GRAPH(graph_et)
414     {
415         PARAMETER(0, 0).u64();
416         PARAMETER(1, 1).u64();
417         PARAMETER(2, 2).f64();
418         PARAMETER(3, 3).f64();
419         PARAMETER(4, 4).ref();
420         PARAMETER(5, 5).ref();
421         PARAMETER(6, 6).s32();
422 
423         BASIC_BLOCK(2, 3, 4)
424         {
425             INST(7, Opcode::LoadArray).u64().Inputs(5, 6);
426             INST(8, Opcode::LoadArray).u64().Inputs(5, 6);
427             INST(9, Opcode::StoreArray).f64().Inputs(4, 6, 3);
428             INST(10, Opcode::StoreArray).f64().Inputs(4, 6, 3);
429             INST(11, Opcode::Compare).b().CC(CC_LT).Inputs(7, 8);
430             INST(12, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(11);
431         }
432         BASIC_BLOCK(3, -1)
433         {
434             INST(13, Opcode::Add).u64().Inputs(0, 1);
435             INST(14, Opcode::Sub).u64().Inputs(0, 1);
436             INST(15, Opcode::Mul).f64().Inputs(2, 3);
437             INST(16, Opcode::Div).f64().Inputs(2, 3);
438             INST(30, Opcode::SaveState).NoVregs();
439             INST(17, Opcode::CallStatic).b().InputsAutoType(13, 14, 15, 16, 30);
440             INST(18, Opcode::CallStatic).b().InputsAutoType(13, 14, 15, 16, 30);
441             INST(19, Opcode::ReturnVoid);
442         }
443         BASIC_BLOCK(4, -1)
444         {
445             INST(20, Opcode::Add).u64().Inputs(0, 1);
446             INST(21, Opcode::Sub).u64().Inputs(0, 1);
447             INST(22, Opcode::Mul).f64().Inputs(2, 3);
448             INST(23, Opcode::Div).f64().Inputs(2, 3);
449             INST(31, Opcode::SaveState).NoVregs();
450             INST(24, Opcode::CallStatic).b().InputsAutoType(20, 21, 22, 23, 31);
451             INST(25, Opcode::ReturnVoid);
452         }
453     }
454 
455     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
456 }
457 
TEST_F(VNTest,VnTestApply3)458 TEST_F(VNTest, VnTestApply3)
459 {
460     GRAPH(GetGraph())
461     {
462         PARAMETER(0, 0).ref();
463         CONSTANT(1, 0);
464         CONSTANT(2, 1);
465         BASIC_BLOCK(2, 3)
466         {
467             INST(3, Opcode::SaveState).Inputs(0, 1, 2).SrcVregs({0, 1, 2});
468             INST(4, Opcode::NullCheck).ref().Inputs(0, 3);
469             INST(5, Opcode::LenArray).s32().Inputs(4);
470         }
471         BASIC_BLOCK(3, 5, 4)
472         {
473             INST(7, Opcode::Phi).s32().Inputs(1, 20);
474             INST(11, Opcode::SafePoint).Inputs(0, 5, 7).SrcVregs({0, 1, 2});
475             INST(12, Opcode::Compare).CC(CC_EQ).b().Inputs(7, 5);  // i < X
476             INST(13, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(12);
477         }
478         BASIC_BLOCK(4, 3)
479         {
480             INST(15, Opcode::SaveState).Inputs(0, 1, 2, 5, 7).SrcVregs({0, 1, 2, 3, 4});
481             INST(16, Opcode::NullCheck).ref().Inputs(0, 15);
482             INST(17, Opcode::LenArray).s32().Inputs(16);
483             INST(18, Opcode::BoundsCheck).s32().Inputs(17, 7, 15);
484             INST(19, Opcode::StoreArray).s64().Inputs(16, 18, 1);
485             INST(20, Opcode::Add).s32().Inputs(7, 2);
486         }
487         BASIC_BLOCK(5, 1)
488         {
489             INST(23, Opcode::Return).ref().Inputs(0);
490         }
491     }
492     GetGraph()->RunPass<ValNum>();
493     GraphChecker(GetGraph()).Check();
494     ASSERT_EQ(INS(5).GetVN(), INS(17).GetVN());
495 
496     Graph *graph_et = CreateGraphWithDefaultRuntime();
497     // graph_et is equal the graph
498     GRAPH(graph_et)
499     {
500         PARAMETER(0, 0).ref();
501         CONSTANT(1, 0);
502         CONSTANT(2, 1);
503         BASIC_BLOCK(2, 3)
504         {
505             INST(3, Opcode::SaveState).Inputs(0, 1, 2).SrcVregs({0, 1, 2});
506             INST(4, Opcode::NullCheck).ref().Inputs(0, 3);
507             INST(5, Opcode::LenArray).s32().Inputs(4);
508         }
509         BASIC_BLOCK(3, 5, 4)
510         {
511             INST(7, Opcode::Phi).s32().Inputs(1, 20);
512             INST(11, Opcode::SafePoint).Inputs(0, 5, 7).SrcVregs({0, 1, 2});
513             INST(12, Opcode::Compare).CC(CC_EQ).b().Inputs(7, 5);  // i < X
514             INST(13, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(12);
515         }
516         BASIC_BLOCK(4, 3)
517         {
518             INST(15, Opcode::SaveState).Inputs(0, 1, 2, 5, 7).SrcVregs({0, 1, 2, 3, 4});
519             INST(16, Opcode::NullCheck).ref().Inputs(0, 15);
520             INST(17, Opcode::LenArray).s32().Inputs(16);
521             INST(18, Opcode::BoundsCheck).s32().Inputs(5, 7, 15);
522             INST(19, Opcode::StoreArray).s64().Inputs(16, 18, 1);
523             INST(20, Opcode::Add).s32().Inputs(7, 2);
524         }
525         BASIC_BLOCK(5, 1)
526         {
527             INST(23, Opcode::Return).ref().Inputs(0);
528         }
529     }
530     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
531 }
532 
TEST_F(VNTest,CleanupTrigger)533 TEST_F(VNTest, CleanupTrigger)
534 {
535     GRAPH(GetGraph())
536     {
537         PARAMETER(0, 0).u64();
538         PARAMETER(1, 1).u64();
539         BASIC_BLOCK(2, 3, 4)
540         {
541             INST(5, Opcode::Add).u64().Inputs(0, 1);
542             INST(6, Opcode::Add).u64().Inputs(0, 1);
543             INST(7, Opcode::Compare).b().Inputs(0, 1);
544             INST(8, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(7);
545         }
546         BASIC_BLOCK(3, 4) {}
547         BASIC_BLOCK(4, -1)
548         {
549             INST(9, Opcode::Phi).u64().Inputs({{2, 6}, {3, 5}});
550             INST(10, Opcode::Return).u64().Inputs(9);
551         }
552     }
553 
554     GraphChecker(GetGraph()).Check();
555     GetGraph()->RunPass<ValNum>();
556 
557     auto graph = CreateGraphWithDefaultRuntime();
558     GRAPH(graph)
559     {
560         PARAMETER(0, 0).u64();
561         PARAMETER(1, 1).u64();
562         BASIC_BLOCK(2, 3, 4)
563         {
564             INST(5, Opcode::Add).u64().Inputs(0, 1);
565             INST(6, Opcode::Add).u64().Inputs(0, 1);
566             INST(7, Opcode::Compare).b().Inputs(0, 1);
567             INST(8, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(7);
568         }
569         BASIC_BLOCK(3, 4) {}
570         BASIC_BLOCK(4, -1)
571         {
572             INST(9, Opcode::Phi).u64().Inputs({{2, 5}, {3, 5}});
573             INST(10, Opcode::Return).u64().Inputs(9);
574         }
575     }
576     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
577 }
578 
TEST_F(VNTest,OSR)579 TEST_F(VNTest, OSR)
580 {
581     GRAPH(GetGraph())
582     {
583         PARAMETER(0, 0).u64();
584         PARAMETER(1, 1).u64();
585         BASIC_BLOCK(2, 3, 4)
586         {
587             INST(2, Opcode::Add).u64().Inputs(0, 1);
588             INST(3, Opcode::Compare).b().Inputs(0, 2);
589             INST(4, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(3);
590         }
591         BASIC_BLOCK(3, 3, 4)
592         {
593             INST(5, Opcode::Phi).u64().Inputs({{2, 0}, {3, 6}});
594             INST(6, Opcode::Sub).u64().Inputs(5, 1);
595             INST(7, Opcode::Compare).b().Inputs(6, 1);
596             INST(8, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(7);
597         }
598         BASIC_BLOCK(4, -1)
599         {
600             INST(9, Opcode::Phi).u64().Inputs({{2, 0}, {3, 6}});
601             INST(10, Opcode::Add).u64().Inputs(0, 1);
602             INST(11, Opcode::Add).u64().Inputs(9, 10);
603             INST(12, Opcode::Return).u64().Inputs(11);
604         }
605     }
606 
607     // Remove Inst 11 without OSR
608 
609     GetGraph()->RunPass<ValNum>();
610     GetGraph()->RunPass<Cleanup>();
611 
612     auto graph = CreateGraphWithDefaultRuntime();
613 
614     GRAPH(graph)
615     {
616         PARAMETER(0, 0).u64();
617         PARAMETER(1, 1).u64();
618         BASIC_BLOCK(2, 3, 4)
619         {
620             INST(2, Opcode::Add).u64().Inputs(0, 1);
621             INST(3, Opcode::Compare).b().Inputs(0, 2);
622             INST(4, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(3);
623         }
624         BASIC_BLOCK(3, 3, 4)
625         {
626             INST(5, Opcode::Phi).u64().Inputs({{2, 0}, {3, 6}});
627             INST(6, Opcode::Sub).u64().Inputs(5, 1);
628             INST(7, Opcode::Compare).b().Inputs(6, 1);
629             INST(8, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(7);
630         }
631         BASIC_BLOCK(4, -1)
632         {
633             INST(9, Opcode::Phi).u64().Inputs({{2, 0}, {3, 6}});
634             INST(11, Opcode::Add).u64().Inputs(9, 2);
635             INST(12, Opcode::Return).u64().Inputs(11);
636         }
637     }
638 
639     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
640 
641     auto graph_osr = CreateGraphOsrWithDefaultRuntime();
642 
643     GRAPH(graph_osr)
644     {
645         PARAMETER(0, 0).u64();
646         PARAMETER(1, 1).u64();
647         BASIC_BLOCK(2, 3, 4)
648         {
649             INST(2, Opcode::Add).u64().Inputs(0, 1);
650             INST(3, Opcode::Compare).b().Inputs(0, 2);
651             INST(4, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(3);
652         }
653         BASIC_BLOCK(3, 3, 4)
654         {
655             INST(5, Opcode::Phi).u64().Inputs({{2, 0}, {3, 6}});
656             INST(13, Opcode::SaveStateOsr).Inputs(0, 1, 5).SrcVregs({0, 1, 2});
657             INST(6, Opcode::Sub).u64().Inputs(5, 1);
658             INST(7, Opcode::Compare).b().Inputs(6, 1);
659             INST(8, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(7);
660         }
661         BASIC_BLOCK(4, -1)
662         {
663             INST(9, Opcode::Phi).u64().Inputs({{2, 0}, {3, 6}});
664             INST(10, Opcode::Add).u64().Inputs(0, 1);
665             INST(11, Opcode::Add).u64().Inputs(9, 10);
666             INST(12, Opcode::Return).u64().Inputs(11);
667         }
668     }
669 
670     for (auto bb : graph_osr->GetBlocksRPO()) {
671         if (bb->IsLoopHeader()) {
672             bb->SetOsrEntry(true);
673         }
674     }
675 
676     auto clone_osr = GraphCloner(graph_osr, graph_osr->GetAllocator(), graph_osr->GetLocalAllocator()).CloneGraph();
677 
678     // Don't remove Inst 11 with OSR
679 
680     graph_osr->RunPass<ValNum>();
681     graph_osr->RunPass<Cleanup>();
682 
683     ASSERT_TRUE(GraphComparator().Compare(clone_osr, graph_osr));
684 }
685 
TEST_F(VNTest,VnTestCommutative)686 TEST_F(VNTest, VnTestCommutative)
687 {
688     // Remove commutative arithmetic instructions(See 2516)
689     GRAPH(GetGraph())
690     {
691         PARAMETER(0, 0).u64();
692         PARAMETER(1, 1).u64();
693 
694         BASIC_BLOCK(2, -1)
695         {
696             INST(2, Opcode::Add).u64().Inputs(0, 1);
697             INST(3, Opcode::Mul).u64().Inputs(0, 1);
698             INST(4, Opcode::Xor).u64().Inputs(0, 1);
699             INST(5, Opcode::Or).u64().Inputs(0, 1);
700             INST(6, Opcode::And).u64().Inputs(0, 1);
701             INST(7, Opcode::Min).u64().Inputs(0, 1);
702             INST(8, Opcode::Max).u64().Inputs(0, 1);
703             INST(9, Opcode::Add).u64().Inputs(1, 0);
704             INST(10, Opcode::Mul).u64().Inputs(1, 0);
705             INST(11, Opcode::Xor).u64().Inputs(1, 0);
706             INST(12, Opcode::Or).u64().Inputs(1, 0);
707             INST(13, Opcode::And).u64().Inputs(1, 0);
708             INST(14, Opcode::Min).u64().Inputs(1, 0);
709             INST(15, Opcode::Max).u64().Inputs(1, 0);
710             INST(20, Opcode::SaveState).NoVregs();
711             INST(16, Opcode::CallStatic).b().InputsAutoType(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20);
712             INST(17, Opcode::ReturnVoid);
713         }
714     }
715     Graph *graph_et = CreateGraphWithDefaultRuntime();
716     GRAPH(graph_et)
717     {
718         PARAMETER(0, 0).u64();
719         PARAMETER(1, 1).u64();
720 
721         BASIC_BLOCK(2, -1)
722         {
723             INST(2, Opcode::Add).u64().Inputs(0, 1);
724             INST(3, Opcode::Mul).u64().Inputs(0, 1);
725             INST(4, Opcode::Xor).u64().Inputs(0, 1);
726             INST(5, Opcode::Or).u64().Inputs(0, 1);
727             INST(6, Opcode::And).u64().Inputs(0, 1);
728             INST(7, Opcode::Min).u64().Inputs(0, 1);
729             INST(8, Opcode::Max).u64().Inputs(0, 1);
730             INST(20, Opcode::SaveState).NoVregs();
731             INST(16, Opcode::CallStatic).b().InputsAutoType(2, 3, 4, 5, 6, 7, 8, 2, 3, 4, 5, 6, 7, 8, 20);
732             INST(17, Opcode::ReturnVoid);
733         }
734     }
735 
736     GetGraph()->RunPass<ValNum>();
737     GetGraph()->RunPass<Cleanup>();
738     GraphChecker(GetGraph()).Check();
739     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
740 }
741 
TEST_F(VNTest,VnTestCommutativeNotAppliedNoApplied)742 TEST_F(VNTest, VnTestCommutativeNotAppliedNoApplied)
743 {
744     // We don't remove float commutative arithmetic instructions and not commutative instruction(sub)
745     GRAPH(GetGraph())
746     {
747         PARAMETER(0, 0).f64();
748         PARAMETER(1, 1).f64();
749         PARAMETER(2, 2).u64();
750         PARAMETER(3, 3).u64();
751 
752         BASIC_BLOCK(2, -1)
753         {
754             INST(4, Opcode::Add).f64().Inputs(0, 1);
755             INST(5, Opcode::Mul).f64().Inputs(0, 1);
756             INST(6, Opcode::Min).f64().Inputs(0, 1);
757             INST(7, Opcode::Max).f64().Inputs(0, 1);
758             INST(8, Opcode::Sub).u64().Inputs(2, 3);
759             INST(9, Opcode::Add).f64().Inputs(1, 0);
760             INST(10, Opcode::Mul).f64().Inputs(1, 0);
761             INST(11, Opcode::Min).f64().Inputs(1, 0);
762             INST(12, Opcode::Max).f64().Inputs(1, 0);
763             INST(13, Opcode::Sub).u64().Inputs(3, 2);
764             INST(20, Opcode::SaveState).NoVregs();
765             INST(14, Opcode::CallStatic).b().InputsAutoType(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 20);
766             INST(15, Opcode::ReturnVoid);
767         }
768     }
769     Graph *graph_et = CreateGraphWithDefaultRuntime();
770     GRAPH(graph_et)
771     {
772         PARAMETER(0, 0).f64();
773         PARAMETER(1, 1).f64();
774         PARAMETER(2, 2).u64();
775         PARAMETER(3, 3).u64();
776 
777         BASIC_BLOCK(2, -1)
778         {
779             INST(4, Opcode::Add).f64().Inputs(0, 1);
780             INST(5, Opcode::Mul).f64().Inputs(0, 1);
781             INST(6, Opcode::Min).f64().Inputs(0, 1);
782             INST(7, Opcode::Max).f64().Inputs(0, 1);
783             INST(8, Opcode::Sub).u64().Inputs(2, 3);
784             INST(9, Opcode::Add).f64().Inputs(1, 0);
785             INST(10, Opcode::Mul).f64().Inputs(1, 0);
786             INST(11, Opcode::Min).f64().Inputs(1, 0);
787             INST(12, Opcode::Max).f64().Inputs(1, 0);
788             INST(13, Opcode::Sub).u64().Inputs(3, 2);
789             INST(20, Opcode::SaveState).NoVregs();
790             INST(14, Opcode::CallStatic).b().InputsAutoType(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 20);
791             INST(15, Opcode::ReturnVoid);
792         }
793     }
794 
795     GetGraph()->RunPass<ValNum>();
796     GetGraph()->RunPass<Cleanup>();
797     GraphChecker(GetGraph()).Check();
798     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
799 }
800 
TEST_F(VNTest,VnTestIsInstance)801 TEST_F(VNTest, VnTestIsInstance)
802 {
803     GRAPH(GetGraph())
804     {
805         PARAMETER(0, 0).ref();
806         PARAMETER(1, 1).ref();
807         BASIC_BLOCK(2, -1)
808         {
809             INST(12, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
810             INST(2, Opcode::LoadClass).ref().Inputs(12).TypeId(1);
811             INST(3, Opcode::IsInstance).b().Inputs(0, 2, 12).TypeId(1);
812             INST(4, Opcode::LoadClass).ref().Inputs(12).TypeId(1);
813             INST(5, Opcode::IsInstance).b().Inputs(0, 4, 12).TypeId(1);
814             INST(6, Opcode::LoadClass).ref().Inputs(12).TypeId(1);
815             INST(7, Opcode::IsInstance).b().Inputs(1, 6, 12).TypeId(1);
816             INST(8, Opcode::LoadClass).ref().Inputs(12).TypeId(2);
817             INST(9, Opcode::IsInstance).b().Inputs(0, 8, 12).TypeId(2);
818             INST(20, Opcode::SaveState).NoVregs();
819             INST(10, Opcode::CallStatic).b().InputsAutoType(3, 5, 7, 9, 20);
820             INST(11, Opcode::ReturnVoid);
821         }
822     }
823     Graph *graph_et = CreateGraphWithDefaultRuntime();
824     GRAPH(graph_et)
825     {
826         PARAMETER(0, 0).ref();
827         PARAMETER(1, 1).ref();
828         BASIC_BLOCK(2, -1)
829         {
830             INST(12, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
831             INST(2, Opcode::LoadClass).ref().Inputs(12).TypeId(1);
832             INST(3, Opcode::IsInstance).b().Inputs(0, 2, 12).TypeId(1);
833             INST(7, Opcode::IsInstance).b().Inputs(1, 2, 12).TypeId(1);
834             INST(8, Opcode::LoadClass).ref().Inputs(12).TypeId(2);
835             INST(9, Opcode::IsInstance).b().Inputs(0, 8, 12).TypeId(2);
836             INST(20, Opcode::SaveState).NoVregs();
837             INST(10, Opcode::CallStatic).b().InputsAutoType(3, 3, 7, 9, 20);
838             INST(11, Opcode::ReturnVoid);
839         }
840     }
841 
842     GetGraph()->RunPass<ValNum>();
843     GetGraph()->RunPass<Cleanup>();
844     GraphChecker(GetGraph()).Check();
845     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
846 }
847 
TEST_F(VNTest,VnTestInitDifferentClasses)848 TEST_F(VNTest, VnTestInitDifferentClasses)
849 {
850     GRAPH(GetGraph())
851     {
852         BASIC_BLOCK(2, -1)
853         {
854             INST(1, Opcode::SaveState).NoVregs();
855             INST(2, Opcode::InitClass).Inputs(1).TypeId(1);
856             INST(3, Opcode::InitClass).Inputs(1).TypeId(2);
857             INST(4, Opcode::ReturnVoid);
858         }
859     }
860 
861     auto clone_graph =
862         GraphCloner(GetGraph(), GetGraph()->GetAllocator(), GetGraph()->GetLocalAllocator()).CloneGraph();
863 
864     GetGraph()->RunPass<ValNum>();
865     GetGraph()->RunPass<Cleanup>();
866     GraphChecker(GetGraph()).Check();
867     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), clone_graph));
868 }
869 
TEST_F(VNTest,VnTestInitClass)870 TEST_F(VNTest, VnTestInitClass)
871 {
872     GRAPH(GetGraph())
873     {
874         BASIC_BLOCK(2, -1)
875         {
876             INST(1, Opcode::SaveState).NoVregs();
877             INST(2, Opcode::InitClass).Inputs(1).TypeId(1);
878             INST(3, Opcode::InitClass).Inputs(1).TypeId(1);
879             INST(4, Opcode::ReturnVoid);
880         }
881     }
882 
883     Graph *graph_et = CreateGraphWithDefaultRuntime();
884     GRAPH(graph_et)
885     {
886         BASIC_BLOCK(2, -1)
887         {
888             INST(1, Opcode::SaveState).NoVregs();
889             INST(2, Opcode::InitClass).Inputs(1).TypeId(1);
890             INST(4, Opcode::ReturnVoid);
891         }
892     }
893 
894     GetGraph()->RunPass<ValNum>();
895     GetGraph()->RunPass<Cleanup>();
896     GraphChecker(GetGraph()).Check();
897     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
898 }
899 
TEST_F(VNTest,VnTestInitAfterLoad)900 TEST_F(VNTest, VnTestInitAfterLoad)
901 {
902     // If InitClass instruction dominates LoadAndInitClass, replace it with LoadAndInitClass
903     // and remove the old LoadAndInitClass
904     // We cannot move outputs of LoadAndInitClass to LoadClass
905     GRAPH(GetGraph())
906     {
907         PARAMETER(0, 0).ref();
908         BASIC_BLOCK(2, -1)
909         {
910             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
911             INST(2, Opcode::LoadClass).ref().Inputs(1).TypeId(1);
912             INST(3, Opcode::IsInstance).b().Inputs(0, 2, 1).TypeId(1);
913             INST(4, Opcode::InitClass).Inputs(1).TypeId(1);
914             INST(5, Opcode::CallStatic).v0id().InputsAutoType(1);
915             INST(6, Opcode::LoadAndInitClass).ref().Inputs(1).TypeId(1);
916             INST(7, Opcode::NewObject).ref().Inputs(6, 1).TypeId(1);
917             INST(8, Opcode::Return).b().Inputs(3);
918         }
919     }
920     Graph *graph_et = CreateGraphWithDefaultRuntime();
921     GRAPH(graph_et)
922     {
923         PARAMETER(0, 0).ref();
924         BASIC_BLOCK(2, -1)
925         {
926             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
927             INST(2, Opcode::LoadClass).ref().Inputs(1).TypeId(1);
928             INST(3, Opcode::IsInstance).b().Inputs(0, 2, 1).TypeId(1);
929             INST(4, Opcode::LoadAndInitClass).ref().Inputs(1).TypeId(1);
930             INST(5, Opcode::CallStatic).v0id().InputsAutoType(1);
931             INST(7, Opcode::NewObject).ref().Inputs(4, 1).TypeId(1);
932             INST(8, Opcode::Return).b().Inputs(3);
933         }
934     }
935 
936     GetGraph()->RunPass<ValNum>();
937     GetGraph()->RunPass<Cleanup>();
938     GraphChecker(GetGraph()).Check();
939     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
940 }
941 
TEST_F(VNTest,VnTestLoadAfterInit)942 TEST_F(VNTest, VnTestLoadAfterInit)
943 {
944     GRAPH(GetGraph())
945     {
946         PARAMETER(0, 0).ref();
947         BASIC_BLOCK(2, -1)
948         {
949             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
950             INST(2, Opcode::LoadClass).ref().Inputs(1).TypeId(1);
951             INST(3, Opcode::IsInstance).b().Inputs(0, 2, 1).TypeId(1);
952             INST(4, Opcode::InitClass).Inputs(1).TypeId(1);
953             INST(5, Opcode::CallStatic).v0id().InputsAutoType(1);
954             INST(6, Opcode::LoadClass).ref().Inputs(1).TypeId(1);
955             INST(7, Opcode::CheckCast).b().Inputs(0, 6, 1).TypeId(1);
956             INST(8, Opcode::Return).b().Inputs(3);
957         }
958     }
959     Graph *graph_et = CreateGraphWithDefaultRuntime();
960     GRAPH(graph_et)
961     {
962         PARAMETER(0, 0).ref();
963         BASIC_BLOCK(2, -1)
964         {
965             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
966             INST(2, Opcode::LoadClass).ref().Inputs(1).TypeId(1);
967             INST(3, Opcode::IsInstance).b().Inputs(0, 2, 1).TypeId(1);
968             INST(4, Opcode::InitClass).Inputs(1).TypeId(1);
969             INST(5, Opcode::CallStatic).v0id().InputsAutoType(1);
970             INST(7, Opcode::CheckCast).b().Inputs(0, 2, 1).TypeId(1);
971             INST(8, Opcode::Return).b().Inputs(3);
972         }
973     }
974 
975     GetGraph()->RunPass<ValNum>();
976     GetGraph()->RunPass<Cleanup>();
977     GraphChecker(GetGraph()).Check();
978     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
979 }
980 
TEST_F(VNTest,VnTestLoadAndInit)981 TEST_F(VNTest, VnTestLoadAndInit)
982 {
983     // If InitClass, LoadClass, or LoadAndInitClass is dominated by LoadAndInitClass
984     // with the same TypeId, remove the dominated instruction
985     GRAPH(GetGraph())
986     {
987         PARAMETER(0, 0).ref();
988         BASIC_BLOCK(2, -1)
989         {
990             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
991             INST(2, Opcode::LoadAndInitClass).ref().Inputs(1).TypeId(1);
992             INST(3, Opcode::NewObject).ref().Inputs(2, 1).TypeId(1);
993             INST(4, Opcode::LoadClass).ref().Inputs(1).TypeId(1);
994             INST(5, Opcode::CheckCast).b().Inputs(0, 4, 1).TypeId(1);
995             INST(6, Opcode::InitClass).Inputs(1).TypeId(1);
996             INST(7, Opcode::LoadAndInitClass).ref().Inputs(1).TypeId(1);
997             INST(8, Opcode::NewObject).ref().Inputs(7, 1).TypeId(1);
998             INST(9, Opcode::ReturnVoid).v0id();
999         }
1000     }
1001     Graph *graph_et = CreateGraphWithDefaultRuntime();
1002     GRAPH(graph_et)
1003     {
1004         PARAMETER(0, 0).ref();
1005         BASIC_BLOCK(2, -1)
1006         {
1007             INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0});
1008             INST(2, Opcode::LoadAndInitClass).ref().Inputs(1).TypeId(1);
1009             INST(3, Opcode::NewObject).ref().Inputs(2, 1).TypeId(1);
1010             INST(5, Opcode::CheckCast).b().Inputs(0, 2, 1).TypeId(1);
1011             INST(8, Opcode::NewObject).ref().Inputs(2, 1).TypeId(1);
1012             INST(9, Opcode::ReturnVoid).v0id();
1013         }
1014     }
1015 
1016     GetGraph()->RunPass<ValNum>();
1017     GetGraph()->RunPass<Cleanup>();
1018     GraphChecker(GetGraph()).Check();
1019     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
1020 }
1021 
TEST_F(VNTest,Domination)1022 TEST_F(VNTest, Domination)
1023 {
1024     GRAPH(GetGraph())
1025     {
1026         PARAMETER(0, 0).s64();
1027         PARAMETER(1, 1).s64();
1028 
1029         BASIC_BLOCK(2, 3, 4)
1030         {
1031             INST(2, Opcode::IfImm).SrcType(DataType::INT64).CC(CC_EQ).Imm(0).Inputs(0);
1032         }
1033         BASIC_BLOCK(3, 5)
1034         {
1035             INST(4, Opcode::Mul).s64().Inputs(0, 1);
1036         }
1037         BASIC_BLOCK(4, 5)
1038         {
1039             // this inst does not dominate similar Add insts from bb 5
1040             INST(5, Opcode::Add).s64().Inputs(0, 1);
1041         }
1042         BASIC_BLOCK(5, -1)
1043         {
1044             INST(6, Opcode::Phi).s64().Inputs({{3, 4}, {4, 5}});
1045             // this inst dominates similar Add insts in this bb
1046             INST(7, Opcode::Add).s64().Inputs(0, 1);
1047             INST(8, Opcode::Mul).s64().Inputs(6, 7);
1048 
1049             INST(9, Opcode::Add).s64().Inputs(0, 1);
1050             INST(10, Opcode::Mul).s64().Inputs(8, 9);
1051 
1052             INST(11, Opcode::Add).s64().Inputs(0, 1);
1053             INST(12, Opcode::Mul).s64().Inputs(10, 11);
1054 
1055             INST(13, Opcode::Return).s64().Inputs(12);
1056         }
1057     }
1058 
1059     GraphChecker(GetGraph()).Check();
1060     GetGraph()->RunPass<ValNum>();
1061     GetGraph()->RunPass<Cleanup>();
1062     GraphChecker(GetGraph()).Check();
1063 
1064     Graph *graph = CreateGraphWithDefaultRuntime();
1065     GRAPH(graph)
1066     {
1067         PARAMETER(0, 0).s64();
1068         PARAMETER(1, 1).s64();
1069 
1070         BASIC_BLOCK(2, 3, 4)
1071         {
1072             INST(2, Opcode::IfImm).SrcType(DataType::INT64).CC(CC_EQ).Imm(0).Inputs(0);
1073         }
1074         BASIC_BLOCK(3, 5)
1075         {
1076             INST(4, Opcode::Mul).s64().Inputs(0, 1);
1077         }
1078         BASIC_BLOCK(4, 5)
1079         {
1080             // this inst does not dominate similar Add insts from bb 5
1081             INST(5, Opcode::Add).s64().Inputs(0, 1);
1082         }
1083         BASIC_BLOCK(5, -1)
1084         {
1085             INST(6, Opcode::Phi).s64().Inputs({{3, 4}, {4, 5}});
1086             // this inst dominates similar Add insts in this bb
1087             INST(7, Opcode::Add).s64().Inputs(0, 1);
1088             INST(8, Opcode::Mul).s64().Inputs(6, 7);
1089 
1090             INST(10, Opcode::Mul).s64().Inputs(8, 7);
1091 
1092             INST(12, Opcode::Mul).s64().Inputs(10, 7);
1093 
1094             INST(13, Opcode::Return).s64().Inputs(12);
1095         }
1096     }
1097 
1098     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1099 }
1100 
1101 }  // namespace panda::compiler
1102