• 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/ir/graph_cloner.h"
18 #include "optimizer/optimizations/deoptimize_elimination.h"
19 #include "optimizer/optimizations/cleanup.h"
20 #include "optimizer/ir/runtime_interface.h"
21 
22 namespace panda::compiler {
23 class DeoptimizeEliminationTest : public CommonTest {
24 public:
DeoptimizeEliminationTest()25     DeoptimizeEliminationTest() : graph_(CreateGraphStartEndBlocks()) {}
26 
GetGraph()27     Graph *GetGraph()
28     {
29         return graph_;
30     }
31 
32 protected:
33     Graph *graph_ {nullptr};
34 };
35 
TEST_F(DeoptimizeEliminationTest,DeoptimizeIfTest)36 TEST_F(DeoptimizeEliminationTest, DeoptimizeIfTest)
37 {
38     GRAPH(GetGraph())
39     {
40         PARAMETER(0, 0).s32();
41         CONSTANT(1, 0);
42         BASIC_BLOCK(2, 1)
43         {
44             // without users
45             INST(2, Opcode::SaveStateDeoptimize).Inputs(1).SrcVregs({1});
46             // cleanup delete this
47             INST(10, Opcode::SaveState).Inputs(1).SrcVregs({1});
48 
49             INST(3, Opcode::SaveStateDeoptimize).Inputs(1).SrcVregs({1});
50             INST(4, Opcode::Compare).b().Inputs(0, 1).CC(CC_GT);
51             INST(5, Opcode::DeoptimizeIf).Inputs(4, 3);
52             // 5 is dominate by 7
53             INST(6, Opcode::SaveStateDeoptimize).Inputs(1).SrcVregs({1});
54             INST(7, Opcode::DeoptimizeIf).Inputs(4, 6);
55 
56             // redundant
57             INST(8, Opcode::DeoptimizeIf).Inputs(1, 6);
58 
59             INST(9, Opcode::ReturnVoid).v0id();
60         }
61     }
62     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
63     ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
64     auto graph = CreateEmptyGraph();
65     GRAPH(graph)
66     {
67         PARAMETER(0, 0).s32();
68         CONSTANT(1, 0);
69         BASIC_BLOCK(2, 1)
70         {
71             INST(3, Opcode::SaveStateDeoptimize).Inputs(1).SrcVregs({1});
72             INST(4, Opcode::Compare).b().Inputs(0, 1).CC(CC_GT);
73             INST(5, Opcode::DeoptimizeIf).Inputs(4, 3);
74 
75             INST(9, Opcode::ReturnVoid).v0id();
76         }
77     }
78     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
79 }
80 
TEST_F(DeoptimizeEliminationTest,ChaGuardOneBlockTest)81 TEST_F(DeoptimizeEliminationTest, ChaGuardOneBlockTest)
82 {
83     GRAPH(GetGraph())
84     {
85         CONSTANT(10, 0);
86         BASIC_BLOCK(2, 1)
87         {
88             INST(0, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
89             INST(1, Opcode::IsMustDeoptimize).b();
90             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
91 
92             INST(3, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
93             INST(4, Opcode::IsMustDeoptimize).b();
94             INST(5, Opcode::DeoptimizeIf).Inputs(4, 3);
95 
96             INST(9, Opcode::ReturnVoid).v0id();
97         }
98     }
99     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
100     auto graph = CreateEmptyGraph();
101     GRAPH(graph)
102     {
103         CONSTANT(10, 0);
104         BASIC_BLOCK(2, 1)
105         {
106             INST(0, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
107             INST(1, Opcode::IsMustDeoptimize).b();
108             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
109 
110             INST(3, Opcode::NOP);
111             INST(4, Opcode::NOP);
112             INST(5, Opcode::NOP);
113 
114             INST(9, Opcode::ReturnVoid).v0id();
115         }
116     }
117     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
118 }
119 
TEST_F(DeoptimizeEliminationTest,ChaGuardOneBlockCallTest)120 TEST_F(DeoptimizeEliminationTest, ChaGuardOneBlockCallTest)
121 {
122     // Not applied. Call to runtime between guards.
123     GRAPH(GetGraph())
124     {
125         CONSTANT(10, 0);
126         BASIC_BLOCK(2, 1)
127         {
128             INST(0, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
129             INST(1, Opcode::IsMustDeoptimize).b();
130             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
131             INST(20, Opcode::SaveState).NoVregs();
132             INST(6, Opcode::CallStatic).v0id().InputsAutoType(20);
133 
134             INST(3, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
135             INST(4, Opcode::IsMustDeoptimize).b();
136             INST(5, Opcode::DeoptimizeIf).Inputs(4, 3);
137 
138             INST(9, Opcode::ReturnVoid).v0id();
139         }
140     }
141     auto clone = GraphCloner(GetGraph(), GetGraph()->GetAllocator(), GetGraph()->GetLocalAllocator()).CloneGraph();
142     ASSERT_FALSE(GetGraph()->RunPass<DeoptimizeElimination>());
143     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), clone));
144 }
145 
TEST_F(DeoptimizeEliminationTest,ChaGuardOneBlockSeveralGuardsTest)146 TEST_F(DeoptimizeEliminationTest, ChaGuardOneBlockSeveralGuardsTest)
147 {
148     GRAPH(GetGraph())
149     {
150         CONSTANT(10, 0);
151         BASIC_BLOCK(2, 1)
152         {
153             INST(0, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
154             INST(1, Opcode::IsMustDeoptimize).b();
155             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
156             INST(20, Opcode::SaveState).NoVregs();
157             INST(6, Opcode::CallStatic).v0id().InputsAutoType(20);
158 
159             INST(3, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
160             INST(4, Opcode::IsMustDeoptimize).b();
161             INST(5, Opcode::DeoptimizeIf).Inputs(4, 3);
162 
163             INST(11, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
164             INST(12, Opcode::IsMustDeoptimize).b();
165             INST(13, Opcode::DeoptimizeIf).Inputs(12, 11);
166 
167             INST(9, Opcode::ReturnVoid).v0id();
168         }
169     }
170     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
171     auto graph = CreateEmptyGraph();
172     GRAPH(graph)
173     {
174         CONSTANT(10, 0);
175         BASIC_BLOCK(2, 1)
176         {
177             INST(0, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
178             INST(1, Opcode::IsMustDeoptimize).b();
179             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
180             INST(20, Opcode::SaveState).NoVregs();
181             INST(6, Opcode::CallStatic).v0id().InputsAutoType(20);
182 
183             INST(3, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
184             INST(4, Opcode::IsMustDeoptimize).b();
185             INST(5, Opcode::DeoptimizeIf).Inputs(4, 3);
186 
187             INST(11, Opcode::NOP);
188             INST(12, Opcode::NOP);
189             INST(13, Opcode::NOP);
190 
191             INST(9, Opcode::ReturnVoid).v0id();
192         }
193     }
194     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
195 }
196 
TEST_F(DeoptimizeEliminationTest,ChaGuardOneBlockCallInlinedTest)197 TEST_F(DeoptimizeEliminationTest, ChaGuardOneBlockCallInlinedTest)
198 {
199     GRAPH(GetGraph())
200     {
201         CONSTANT(10, 0);
202         BASIC_BLOCK(2, 1)
203         {
204             INST(0, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
205             INST(1, Opcode::IsMustDeoptimize).b();
206             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
207             INST(20, Opcode::SaveState).NoVregs();
208             INST(6, Opcode::CallStatic).v0id().Inlined().InputsAutoType(20);
209             INST(7, Opcode::ReturnInlined).Inputs(0);
210 
211             INST(3, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
212             INST(4, Opcode::IsMustDeoptimize).b();
213             INST(5, Opcode::DeoptimizeIf).Inputs(4, 3);
214 
215             INST(9, Opcode::ReturnVoid).v0id();
216         }
217     }
218     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
219     auto graph = CreateEmptyGraph();
220     GRAPH(graph)
221     {
222         CONSTANT(10, 0);
223         BASIC_BLOCK(2, 1)
224         {
225             INST(0, Opcode::SaveStateDeoptimize).Inputs(10).SrcVregs({10});
226             INST(1, Opcode::IsMustDeoptimize).b();
227             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
228             INST(20, Opcode::SaveState).NoVregs();
229             INST(6, Opcode::CallStatic).v0id().Inlined().InputsAutoType(20);
230             INST(7, Opcode::ReturnInlined).Inputs(0);
231 
232             INST(3, Opcode::NOP);
233             INST(4, Opcode::NOP);
234             INST(5, Opcode::NOP);
235 
236             INST(9, Opcode::ReturnVoid).v0id();
237         }
238     }
239     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
240 }
241 
TEST_F(DeoptimizeEliminationTest,ChaGuardIfTest)242 TEST_F(DeoptimizeEliminationTest, ChaGuardIfTest)
243 {
244     /*
245      * Not applied.
246      * bb1
247      * guard
248      * |   \
249      * |   bb2
250      * |   runtime call
251      * |  /
252      * bb3
253      * guard
254      */
255     GRAPH(GetGraph())
256     {
257         PARAMETER(10, 0).s32();
258         CONSTANT(11, 1);
259         BASIC_BLOCK(2, 4, 5)
260         {
261             INST(0, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
262             INST(1, Opcode::IsMustDeoptimize).b();
263             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
264             INST(3, Opcode::Compare).b().CC(CC_LT).Inputs(10, 11);
265             INST(4, Opcode::IfImm).CC(CC_NE).Inputs(3).Imm(0);
266         }
267         BASIC_BLOCK(4, 5)
268         {
269             INST(20, Opcode::SaveState).NoVregs();
270             INST(5, Opcode::CallStatic).v0id().InputsAutoType(20);
271         }
272         BASIC_BLOCK(5, 1)
273         {
274             INST(6, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
275             INST(7, Opcode::IsMustDeoptimize).b();
276             INST(8, Opcode::DeoptimizeIf).Inputs(7, 6);
277             INST(9, Opcode::ReturnVoid).v0id();
278         }
279     }
280     auto clone = GraphCloner(GetGraph(), GetGraph()->GetAllocator(), GetGraph()->GetLocalAllocator()).CloneGraph();
281     ASSERT_FALSE(GetGraph()->RunPass<DeoptimizeElimination>());
282     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), clone));
283 }
284 
TEST_F(DeoptimizeEliminationTest,ChaGuardIfSeveralGuardsTest)285 TEST_F(DeoptimizeEliminationTest, ChaGuardIfSeveralGuardsTest)
286 {
287     /*
288      * bb1
289      * guard
290      * call
291      * guard
292      * |   \
293      * |   bb2
294      * |   some inst
295      * |  /
296      * bb3
297      * guard
298      */
299     GRAPH(GetGraph())
300     {
301         PARAMETER(10, 0).s32();
302         CONSTANT(11, 1);
303         BASIC_BLOCK(2, 4, 5)
304         {
305             INST(0, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
306             INST(1, Opcode::IsMustDeoptimize).b();
307             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
308             INST(20, Opcode::SaveState).NoVregs();
309             INST(12, Opcode::CallStatic).v0id().InputsAutoType(20);
310             INST(13, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
311             INST(14, Opcode::IsMustDeoptimize).b();
312             INST(15, Opcode::DeoptimizeIf).Inputs(14, 13);
313             INST(3, Opcode::Compare).b().CC(CC_LT).Inputs(10, 11);
314             INST(4, Opcode::IfImm).CC(CC_NE).Inputs(3).Imm(0);
315         }
316         BASIC_BLOCK(4, 5)
317         {
318             INST(21, Opcode::SaveState).NoVregs();
319             INST(5, Opcode::CallStatic).v0id().Inlined().InputsAutoType(21);
320             INST(16, Opcode::ReturnInlined).Inputs(0);
321         }
322         BASIC_BLOCK(5, 1)
323         {
324             INST(6, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
325             INST(7, Opcode::IsMustDeoptimize).b();
326             INST(8, Opcode::DeoptimizeIf).Inputs(7, 6);
327             INST(9, Opcode::ReturnVoid).v0id();
328         }
329     }
330     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
331     auto graph = CreateEmptyGraph();
332     GRAPH(graph)
333     {
334         PARAMETER(10, 0).s32();
335         CONSTANT(11, 1);
336         BASIC_BLOCK(2, 4, 5)
337         {
338             INST(0, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
339             INST(1, Opcode::IsMustDeoptimize).b();
340             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
341             INST(20, Opcode::SaveState).NoVregs();
342             INST(12, Opcode::CallStatic).v0id().InputsAutoType(20);
343             INST(13, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
344             INST(14, Opcode::IsMustDeoptimize).b();
345             INST(15, Opcode::DeoptimizeIf).Inputs(14, 13);
346             INST(3, Opcode::Compare).b().CC(CC_LT).Inputs(10, 11);
347             INST(4, Opcode::IfImm).CC(CC_NE).Inputs(3).Imm(0);
348         }
349         BASIC_BLOCK(4, 5)
350         {
351             INST(21, Opcode::SaveState).NoVregs();
352             INST(5, Opcode::CallStatic).v0id().Inlined().InputsAutoType(21);
353             INST(16, Opcode::ReturnInlined).Inputs(0);
354         }
355         BASIC_BLOCK(5, 1)
356         {
357             INST(6, Opcode::NOP);
358             INST(7, Opcode::NOP);
359             INST(8, Opcode::NOP);
360             INST(9, Opcode::ReturnVoid).v0id();
361         }
362     }
363     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
364 }
365 
TEST_F(DeoptimizeEliminationTest,ChaGuardLoopTest)366 TEST_F(DeoptimizeEliminationTest, ChaGuardLoopTest)
367 {
368     GRAPH(GetGraph())
369     {
370         CONSTANT(10, 0);
371         CONSTANT(11, 1);
372         CONSTANT(12, 10);
373         BASIC_BLOCK(2, 3)
374         {
375             INST(0, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
376             INST(1, Opcode::IsMustDeoptimize).b();
377             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
378         }
379         BASIC_BLOCK(3, 4, 5)
380         {
381             INST(3, Opcode::Phi).s32().Inputs(10, 7);
382             INST(8, Opcode::Compare).b().CC(CC_LT).Inputs(3, 12);
383             INST(9, Opcode::IfImm).CC(CC_NE).Inputs(8).Imm(0);
384         }
385         BASIC_BLOCK(4, 3)
386         {
387             INST(4, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
388             INST(5, Opcode::IsMustDeoptimize).b();
389             INST(6, Opcode::DeoptimizeIf).Inputs(5, 4);
390             INST(7, Opcode::Add).s32().Inputs(3, 11);
391         }
392         BASIC_BLOCK(5, 1)
393         {
394             INST(13, Opcode::Return).s32().Inputs(3);
395         }
396     }
397     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
398     auto graph = CreateEmptyGraph();
399     GRAPH(graph)
400     {
401         CONSTANT(10, 0);
402         CONSTANT(11, 1);
403         CONSTANT(12, 10);
404         BASIC_BLOCK(2, 3)
405         {
406             INST(0, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
407             INST(1, Opcode::IsMustDeoptimize).b();
408             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
409         }
410         BASIC_BLOCK(3, 4, 5)
411         {
412             INST(3, Opcode::Phi).s32().Inputs(10, 7);
413             INST(8, Opcode::Compare).b().CC(CC_LT).Inputs(3, 12);
414             INST(9, Opcode::IfImm).CC(CC_NE).Inputs(8).Imm(0);
415         }
416         BASIC_BLOCK(4, 3)
417         {
418             INST(4, Opcode::NOP);
419             INST(5, Opcode::NOP);
420             INST(6, Opcode::NOP);
421             INST(7, Opcode::Add).s32().Inputs(3, 11);
422         }
423         BASIC_BLOCK(5, 1)
424         {
425             INST(13, Opcode::Return).s32().Inputs(3);
426         }
427     }
428     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
429 }
430 
TEST_F(DeoptimizeEliminationTest,ChaGuardLoopWithCallAfterGuardTest)431 TEST_F(DeoptimizeEliminationTest, ChaGuardLoopWithCallAfterGuardTest)
432 {
433     GRAPH(GetGraph())
434     {
435         CONSTANT(10, 0);
436         CONSTANT(11, 1);
437         CONSTANT(12, 10);
438         BASIC_BLOCK(2, 3)
439         {
440             INST(0, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
441             INST(1, Opcode::IsMustDeoptimize).b();
442             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
443         }
444         BASIC_BLOCK(3, 4, 5)
445         {
446             INST(3, Opcode::Phi).s32().Inputs(10, 7);
447             INST(8, Opcode::Compare).b().CC(CC_LT).Inputs(3, 12);
448             INST(9, Opcode::IfImm).CC(CC_NE).Inputs(8).Imm(0);
449         }
450         BASIC_BLOCK(4, 3)
451         {
452             INST(4, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
453             INST(5, Opcode::IsMustDeoptimize).b();
454             INST(6, Opcode::DeoptimizeIf).Inputs(5, 4);
455             INST(20, Opcode::SaveState).NoVregs();
456             INST(14, Opcode::CallStatic).v0id().InputsAutoType(20);
457             INST(7, Opcode::Add).s32().Inputs(3, 11);
458         }
459         BASIC_BLOCK(5, 1)
460         {
461             INST(13, Opcode::Return).s32().Inputs(3);
462         }
463     }
464     auto clone = GraphCloner(GetGraph(), GetGraph()->GetAllocator(), GetGraph()->GetLocalAllocator()).CloneGraph();
465     ASSERT_FALSE(GetGraph()->RunPass<DeoptimizeElimination>());
466     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), clone));
467 }
468 
TEST_F(DeoptimizeEliminationTest,ChaGuardLoopWithCallBeforeGuardTest)469 TEST_F(DeoptimizeEliminationTest, ChaGuardLoopWithCallBeforeGuardTest)
470 {
471     GRAPH(GetGraph())
472     {
473         CONSTANT(10, 0);
474         CONSTANT(11, 1);
475         CONSTANT(12, 10);
476         BASIC_BLOCK(2, 3)
477         {
478             INST(0, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
479             INST(1, Opcode::IsMustDeoptimize).b();
480             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
481         }
482         BASIC_BLOCK(3, 4, 5)
483         {
484             INST(3, Opcode::Phi).s32().Inputs(10, 7);
485             INST(8, Opcode::Compare).b().CC(CC_LT).Inputs(3, 12);
486             INST(9, Opcode::IfImm).CC(CC_NE).Inputs(8).Imm(0);
487         }
488         BASIC_BLOCK(4, 3)
489         {
490             INST(20, Opcode::SaveState).NoVregs();
491             INST(14, Opcode::CallStatic).v0id().InputsAutoType(20);
492             INST(4, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
493             INST(5, Opcode::IsMustDeoptimize).b();
494             INST(6, Opcode::DeoptimizeIf).Inputs(5, 4);
495             INST(7, Opcode::Add).s32().Inputs(3, 11);
496         }
497         BASIC_BLOCK(5, 1)
498         {
499             INST(13, Opcode::Return).s32().Inputs(3);
500         }
501     }
502     auto clone = GraphCloner(GetGraph(), GetGraph()->GetAllocator(), GetGraph()->GetLocalAllocator()).CloneGraph();
503     ASSERT_FALSE(GetGraph()->RunPass<DeoptimizeElimination>());
504     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), clone));
505 }
506 
TEST_F(DeoptimizeEliminationTest,ChaGuardLoopWithCallBetweenGuardsWithDomGuardTest)507 TEST_F(DeoptimizeEliminationTest, ChaGuardLoopWithCallBetweenGuardsWithDomGuardTest)
508 {
509     GRAPH(GetGraph())
510     {
511         CONSTANT(10, 0);
512         CONSTANT(11, 1);
513         CONSTANT(12, 10);
514         BASIC_BLOCK(2, 3)
515         {
516             INST(0, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
517             INST(1, Opcode::IsMustDeoptimize).b();
518             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
519         }
520         BASIC_BLOCK(3, 4, 5)
521         {
522             INST(3, Opcode::Phi).s32().Inputs(10, 7);
523             INST(8, Opcode::Compare).b().CC(CC_LT).Inputs(3, 12);
524             INST(9, Opcode::IfImm).CC(CC_NE).Inputs(8).Imm(0);
525         }
526         BASIC_BLOCK(4, 3)
527         {
528             INST(15, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
529             INST(16, Opcode::IsMustDeoptimize).b();
530             INST(17, Opcode::DeoptimizeIf).Inputs(16, 15);
531             INST(20, Opcode::SaveState).NoVregs();
532             INST(14, Opcode::CallStatic).v0id().InputsAutoType(20);
533             INST(4, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
534             INST(5, Opcode::IsMustDeoptimize).b();
535             INST(6, Opcode::DeoptimizeIf).Inputs(5, 4);
536             INST(7, Opcode::Add).s32().Inputs(3, 11);
537         }
538         BASIC_BLOCK(5, 1)
539         {
540             INST(13, Opcode::Return).s32().Inputs(3);
541         }
542     }
543     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
544     auto graph = CreateEmptyGraph();
545     GRAPH(graph)
546     {
547         CONSTANT(10, 0);
548         CONSTANT(11, 1);
549         CONSTANT(12, 10);
550         BASIC_BLOCK(2, 3)
551         {
552             INST(0, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
553             INST(1, Opcode::IsMustDeoptimize).b();
554             INST(2, Opcode::DeoptimizeIf).Inputs(1, 0);
555         }
556         BASIC_BLOCK(3, 4, 5)
557         {
558             INST(3, Opcode::Phi).s32().Inputs(10, 7);
559             INST(8, Opcode::Compare).b().CC(CC_LT).Inputs(3, 12);
560             INST(9, Opcode::IfImm).CC(CC_NE).Inputs(8).Imm(0);
561         }
562         BASIC_BLOCK(4, 3)
563         {
564             INST(15, Opcode::NOP);
565             INST(16, Opcode::NOP);
566             INST(17, Opcode::NOP);
567             INST(20, Opcode::SaveState).NoVregs();
568             INST(14, Opcode::CallStatic).v0id().InputsAutoType(20);
569             INST(4, Opcode::SaveStateDeoptimize).Inputs(10, 11).SrcVregs({0, 1});
570             INST(5, Opcode::IsMustDeoptimize).b();
571             INST(6, Opcode::DeoptimizeIf).Inputs(5, 4);
572             INST(7, Opcode::Add).s32().Inputs(3, 11);
573         }
574         BASIC_BLOCK(5, 1)
575         {
576             INST(13, Opcode::Return).s32().Inputs(3);
577         }
578     }
579     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
580 }
581 
TEST_F(DeoptimizeEliminationTest,ChaGuardLoopWithDuplicatedGuardsTest)582 TEST_F(DeoptimizeEliminationTest, ChaGuardLoopWithDuplicatedGuardsTest)
583 {
584     GRAPH(GetGraph())
585     {
586         CONSTANT(0, 0);
587         CONSTANT(1, 1);
588         PARAMETER(2, 0).s32();
589         BASIC_BLOCK(2, 3, 10)
590         {
591             INST(3, Opcode::Compare).b().CC(CC_LT).Inputs(0, 2);
592             INST(4, Opcode::IfImm).CC(CC_NE).Inputs(3).Imm(0);
593         }
594         BASIC_BLOCK(3, 4, 5)
595         {
596             INST(19, Opcode::Phi).s32().Inputs(0, 14);
597             INST(5, Opcode::SaveStateDeoptimize).Inputs(0, 1, 2).SrcVregs({0, 1, 2});
598             INST(6, Opcode::IsMustDeoptimize).b();
599             INST(7, Opcode::DeoptimizeIf).Inputs(6, 5);
600             INST(8, Opcode::Compare).b().CC(CC_LT).Inputs(0, 2);
601             INST(9, Opcode::IfImm).CC(CC_NE).Inputs(8).Imm(0);
602         }
603         BASIC_BLOCK(4, 5)
604         {
605             INST(10, Opcode::SaveStateDeoptimize).Inputs(0, 1, 2).SrcVregs({0, 1, 2});
606             INST(11, Opcode::IsMustDeoptimize).b();
607             INST(12, Opcode::DeoptimizeIf).Inputs(11, 10);
608         }
609         BASIC_BLOCK(5, 3, 10)
610         {
611             INST(20, Opcode::SaveState).NoVregs();
612             INST(13, Opcode::CallStatic).v0id().InputsAutoType(20);
613             INST(14, Opcode::Add).s32().Inputs(19, 1);
614             INST(15, Opcode::Compare).b().CC(CC_LT).Inputs(14, 2);
615             INST(16, Opcode::IfImm).CC(CC_NE).Inputs(15).Imm(0);
616         }
617 
618         BASIC_BLOCK(10, 1)
619         {
620             INST(17, Opcode::Phi).s32().Inputs(0, 14);
621             INST(18, Opcode::Return).s32().Inputs(17);
622         }
623     }
624     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
625     auto graph = CreateEmptyGraph();
626     GRAPH(graph)
627     {
628         CONSTANT(0, 0);
629         CONSTANT(1, 1);
630         PARAMETER(2, 0).s32();
631         BASIC_BLOCK(2, 3, 10)
632         {
633             INST(3, Opcode::Compare).b().CC(CC_LT).Inputs(0, 2);
634             INST(4, Opcode::IfImm).CC(CC_NE).Inputs(3).Imm(0);
635         }
636         BASIC_BLOCK(3, 4, 5)
637         {
638             INST(19, Opcode::Phi).s32().Inputs(0, 14);
639             INST(5, Opcode::SaveStateDeoptimize).Inputs(0, 1, 2).SrcVregs({0, 1, 2});
640             INST(6, Opcode::IsMustDeoptimize).b();
641             INST(7, Opcode::DeoptimizeIf).Inputs(6, 5);
642             INST(8, Opcode::Compare).b().CC(CC_LT).Inputs(0, 2);
643             INST(9, Opcode::IfImm).CC(CC_NE).Inputs(8).Imm(0);
644         }
645         BASIC_BLOCK(4, 5)
646         {
647             INST(10, Opcode::NOP);
648             INST(11, Opcode::NOP);
649             INST(12, Opcode::NOP);
650         }
651         BASIC_BLOCK(5, 3, 10)
652         {
653             INST(20, Opcode::SaveState).NoVregs();
654             INST(13, Opcode::CallStatic).v0id().InputsAutoType(20);
655             INST(14, Opcode::Add).s32().Inputs(19, 1);
656             INST(15, Opcode::Compare).b().CC(CC_LT).Inputs(14, 2);
657             INST(16, Opcode::IfImm).CC(CC_NE).Inputs(15).Imm(0);
658         }
659 
660         BASIC_BLOCK(10, 1)
661         {
662             INST(17, Opcode::Phi).s32().Inputs(0, 14);
663             INST(18, Opcode::Return).s32().Inputs(17);
664         }
665     }
666     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
667 }
668 
TEST_F(DeoptimizeEliminationTest,ChaGuardNotDominateTest)669 TEST_F(DeoptimizeEliminationTest, ChaGuardNotDominateTest)
670 {
671     GRAPH(GetGraph())
672     {
673         PARAMETER(0, 0).s32();
674         PARAMETER(1, 1).s32();
675         BASIC_BLOCK(2, 3, 4)
676         {
677             INST(2, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1);
678             INST(3, Opcode::IfImm).CC(CC_NE).Inputs(2).Imm(0);
679         }
680         BASIC_BLOCK(3, 4)
681         {
682             INST(4, Opcode::SaveStateDeoptimize).Inputs(0, 1).SrcVregs({0, 1});
683             INST(5, Opcode::IsMustDeoptimize).b();
684             INST(6, Opcode::DeoptimizeIf).Inputs(5, 4);
685         }
686         BASIC_BLOCK(4, 1)
687         {
688             INST(7, Opcode::SaveStateDeoptimize).Inputs(0, 1).SrcVregs({0, 1});
689             INST(8, Opcode::IsMustDeoptimize).b();
690             INST(9, Opcode::DeoptimizeIf).Inputs(8, 7);
691             INST(10, Opcode::ReturnVoid).v0id();
692         }
693     }
694     auto clone = GraphCloner(GetGraph(), GetGraph()->GetAllocator(), GetGraph()->GetLocalAllocator()).CloneGraph();
695     ASSERT_FALSE(GetGraph()->RunPass<DeoptimizeElimination>());
696     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), clone));
697 }
698 
TEST_F(DeoptimizeEliminationTest,ChaGuardIfWithGuardsTest)699 TEST_F(DeoptimizeEliminationTest, ChaGuardIfWithGuardsTest)
700 {
701     /*
702      *    some code
703      *    /       \
704      *  call     call
705      * guard    guard
706      * \          /
707      *  \        /
708      *    guard(*, deleted)
709      */
710     GRAPH(GetGraph())
711     {
712         PARAMETER(0, 0).s32();
713         PARAMETER(1, 1).s32();
714         BASIC_BLOCK(2, 3, 4)
715         {
716             INST(5, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1);
717             INST(6, Opcode::IfImm).CC(CC_NE).Inputs(5).Imm(0);
718         }
719         BASIC_BLOCK(3, 5)
720         {
721             INST(20, Opcode::SaveState).NoVregs();
722             INST(7, Opcode::CallStatic).v0id().InputsAutoType(20);
723             INST(8, Opcode::SaveStateDeoptimize).Inputs(0, 1).SrcVregs({0, 1});
724             INST(9, Opcode::IsMustDeoptimize).b();
725             INST(10, Opcode::DeoptimizeIf).Inputs(9, 8);
726         }
727         BASIC_BLOCK(4, 5)
728         {
729             INST(21, Opcode::SaveState).NoVregs();
730             INST(11, Opcode::CallStatic).v0id().InputsAutoType(21);
731             INST(12, Opcode::SaveStateDeoptimize).Inputs(0, 1).SrcVregs({0, 1});
732             INST(13, Opcode::IsMustDeoptimize).b();
733             INST(14, Opcode::DeoptimizeIf).Inputs(13, 12);
734         }
735         BASIC_BLOCK(5, 1)
736         {
737             INST(15, Opcode::SaveStateDeoptimize).Inputs(0, 1).SrcVregs({0, 1});
738             INST(16, Opcode::IsMustDeoptimize).b();
739             INST(17, Opcode::DeoptimizeIf).Inputs(16, 15);
740             INST(18, Opcode::ReturnVoid).v0id();
741         }
742     }
743     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
744     auto graph = CreateEmptyGraph();
745     GRAPH(graph)
746     {
747         PARAMETER(0, 0).s32();
748         PARAMETER(1, 1).s32();
749         BASIC_BLOCK(2, 3, 4)
750         {
751             INST(5, Opcode::Compare).b().CC(CC_EQ).Inputs(0, 1);
752             INST(6, Opcode::IfImm).CC(CC_NE).Inputs(5).Imm(0);
753         }
754         BASIC_BLOCK(3, 5)
755         {
756             INST(20, Opcode::SaveState).NoVregs();
757             INST(7, Opcode::CallStatic).v0id().InputsAutoType(20);
758             INST(8, Opcode::SaveStateDeoptimize).Inputs(0, 1).SrcVregs({0, 1});
759             INST(9, Opcode::IsMustDeoptimize).b();
760             INST(10, Opcode::DeoptimizeIf).Inputs(9, 8);
761         }
762         BASIC_BLOCK(4, 5)
763         {
764             INST(21, Opcode::SaveState).NoVregs();
765             INST(11, Opcode::CallStatic).v0id().InputsAutoType(21);
766             INST(12, Opcode::SaveStateDeoptimize).Inputs(0, 1).SrcVregs({0, 1});
767             INST(13, Opcode::IsMustDeoptimize).b();
768             INST(14, Opcode::DeoptimizeIf).Inputs(13, 12);
769         }
770         BASIC_BLOCK(5, 1)
771         {
772             INST(15, Opcode::NOP);
773             INST(16, Opcode::NOP);
774             INST(17, Opcode::NOP);
775             INST(18, Opcode::ReturnVoid).v0id();
776         }
777     }
778     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
779 }
780 
TEST_F(DeoptimizeEliminationTest,ReplaceByDeoptimizeTest)781 TEST_F(DeoptimizeEliminationTest, ReplaceByDeoptimizeTest)
782 {
783     GRAPH(GetGraph())
784     {
785         CONSTANT(0, 1);
786         BASIC_BLOCK(2, 1)
787         {
788             INST(2, Opcode::SaveState).Inputs(0).SrcVregs({0});
789             INST(3, Opcode::DeoptimizeIf).Inputs(0, 2);
790             INST(4, Opcode::ReturnVoid).v0id();
791         }
792     }
793     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
794     auto graph = CreateEmptyGraph();
795     GRAPH(graph)
796     {
797         CONSTANT(0, 1);
798         BASIC_BLOCK(2, 1)
799         {
800             INST(2, Opcode::SaveState).Inputs(0).SrcVregs({0});
801             INST(3, Opcode::Deoptimize).DeoptimizeType(DeoptimizeType::INVALID).Inputs(2);
802         }
803     }
804     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
805 }
806 
TEST_F(DeoptimizeEliminationTest,ReplaceByDeoptimizeInliningTest)807 TEST_F(DeoptimizeEliminationTest, ReplaceByDeoptimizeInliningTest)
808 {
809     GRAPH(GetGraph())
810     {
811         CONSTANT(0, 1);
812         BASIC_BLOCK(2, 1)
813         {
814             INST(2, Opcode::SaveState).Inputs(0).SrcVregs({0});
815             INST(3, Opcode::CallStatic).v0id().InputsAutoType(2).Inlined();
816             INST(4, Opcode::SaveState).Inputs(0).SrcVregs({0});
817             INST(7, Opcode::DeoptimizeIf).Inputs(0, 4);
818             INST(5, Opcode::ReturnInlined).Inputs(2);
819             INST(6, Opcode::ReturnVoid).v0id();
820         }
821     }
822     INS(4).CastToSaveState()->SetCallerInst(static_cast<CallInst *>(&INS(3)));
823     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
824     auto graph = CreateEmptyGraph();
825     GRAPH(graph)
826     {
827         CONSTANT(0, 1);
828         BASIC_BLOCK(2, 1)
829         {
830             INST(2, Opcode::SaveState).Inputs(0).SrcVregs({0});
831             INST(3, Opcode::CallStatic).v0id().InputsAutoType(2).Inlined();
832             INST(4, Opcode::SaveState).Inputs(0).SrcVregs({0});
833             INST(5, Opcode::ReturnInlined).Inputs(2);
834             INST(8, Opcode::Deoptimize).Inputs(4);
835         }
836     }
837     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
838 }
839 
TEST_F(DeoptimizeEliminationTest,RemoveSafePoint)840 TEST_F(DeoptimizeEliminationTest, RemoveSafePoint)
841 {
842     GRAPH(GetGraph())
843     {
844         PARAMETER(0, 0).s32();
845         PARAMETER(1, 1).s32();
846         INST(2, Opcode::SafePoint).Inputs(0, 1).SrcVregs({0, 1});
847         BASIC_BLOCK(2, 1)
848         {
849             INST(3, Opcode::Add).s32().Inputs(0, 1);
850             INST(4, Opcode::Return).s32().Inputs(3);
851         }
852     }
853     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
854     GetGraph()->RunPass<Cleanup>();
855     auto graph = CreateEmptyGraph();
856     GRAPH(graph)
857     {
858         PARAMETER(0, 0).s32();
859         PARAMETER(1, 1).s32();
860         BASIC_BLOCK(2, 1)
861         {
862             INST(3, Opcode::Add).s32().Inputs(0, 1);
863             INST(4, Opcode::Return).s32().Inputs(3);
864         }
865     }
866     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
867 }
868 
869 // Not applied, have runtime calls
TEST_F(DeoptimizeEliminationTest,RemoveSafePoint1)870 TEST_F(DeoptimizeEliminationTest, RemoveSafePoint1)
871 {
872     GRAPH(GetGraph())
873     {
874         PARAMETER(0, 0).s32();
875         PARAMETER(1, 1).s32();
876         INST(2, Opcode::SafePoint).Inputs(0, 1).SrcVregs({0, 1});
877         BASIC_BLOCK(2, 1)
878         {
879             INST(20, Opcode::SaveState).NoVregs();
880             INST(5, Opcode::CallStatic).v0id().InputsAutoType(20);
881             INST(3, Opcode::Add).s32().Inputs(0, 1);
882             INST(4, Opcode::Return).s32().Inputs(3);
883         }
884     }
885     auto clone = GraphCloner(GetGraph(), GetGraph()->GetAllocator(), GetGraph()->GetLocalAllocator()).CloneGraph();
886     ASSERT_FALSE(GetGraph()->RunPass<DeoptimizeElimination>());
887     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), clone));
888 }
889 
890 // Not applied, a lot of instructions
TEST_F(DeoptimizeEliminationTest,RemoveSafePoint2)891 TEST_F(DeoptimizeEliminationTest, RemoveSafePoint2)
892 {
893     uint64_t N = options.GetCompilerSafepointEliminationLimit();
894     auto block = GetGraph()->CreateEmptyBlock();
895     GetGraph()->GetStartBlock()->AddSucc(block);
896     block->AddSucc(GetGraph()->GetEndBlock());
897     auto param1 = GetGraph()->CreateInstParameter(0);
898     auto param2 = GetGraph()->CreateInstParameter(1);
899     param1->SetType(DataType::INT32);
900     param2->SetType(DataType::INT32);
901     GetGraph()->GetStartBlock()->AppendInst(param1);
902     GetGraph()->GetStartBlock()->AppendInst(param2);
903     auto sp = GetGraph()->CreateInstSafePoint();
904     sp->AppendInput(param1);
905     sp->AppendInput(param2);
906     sp->SetVirtualRegister(0, VirtualRegister(0, false));
907     sp->SetVirtualRegister(1, VirtualRegister(1, false));
908     GetGraph()->GetStartBlock()->AppendInst(sp);
909     ArenaVector<Inst *> insts(GetGraph()->GetLocalAllocator()->Adapter());
910     insts.push_back(param1);
911     insts.push_back(param2);
912     for (uint64_t i = 2; i <= N + 1; i++) {
913         auto inst = GetGraph()->CreateInstAdd();
914         inst->SetType(DataType::INT32);
915         inst->SetInput(0, insts[i - 2]);
916         inst->SetInput(1, insts[i - 1]);
917         block->AppendInst(inst);
918         insts.push_back(inst);
919     }
920     auto ret = GetGraph()->CreateInstReturn();
921     ret->SetType(DataType::INT32);
922     ret->SetInput(0, insts[N + 1]);
923     block->AppendInst(ret);
924     GraphChecker(GetGraph()).Check();
925     auto clone = GraphCloner(GetGraph(), GetGraph()->GetAllocator(), GetGraph()->GetLocalAllocator()).CloneGraph();
926     ASSERT_FALSE(GetGraph()->RunPass<DeoptimizeElimination>());
927     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), clone));
928 }
929 
930 // Applied, have CallStatic.Inlined
TEST_F(DeoptimizeEliminationTest,RemoveSafePoint3)931 TEST_F(DeoptimizeEliminationTest, RemoveSafePoint3)
932 {
933     GRAPH(GetGraph())
934     {
935         PARAMETER(0, 0).s32();
936         PARAMETER(1, 1).s32();
937         INST(2, Opcode::SafePoint).Inputs(0, 1).SrcVregs({0, 1});
938         BASIC_BLOCK(2, 1)
939         {
940             INST(8, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
941             INST(5, Opcode::CallStatic).v0id().InputsAutoType(8).Inlined();
942             INST(3, Opcode::Add).s32().Inputs(0, 1);
943             INST(7, Opcode::ReturnInlined).Inputs(8);
944             INST(4, Opcode::Return).s32().Inputs(3);
945         }
946     }
947     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
948     GetGraph()->RunPass<Cleanup>();
949     auto graph = CreateEmptyGraph();
950     GRAPH(graph)
951     {
952         PARAMETER(0, 0).s32();
953         PARAMETER(1, 1).s32();
954         BASIC_BLOCK(2, 1)
955         {
956             INST(8, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
957             INST(5, Opcode::CallStatic).v0id().InputsAutoType(8).Inlined();
958             INST(3, Opcode::Add).s32().Inputs(0, 1);
959             INST(7, Opcode::ReturnInlined).Inputs(8);
960             INST(4, Opcode::Return).s32().Inputs(3);
961         }
962     }
963     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
964 }
965 
966 // Removes numeric inputs from SS without Deoptimize and doen't remove with Deoptimize
TEST_F(DeoptimizeEliminationTest,RemovNumericInputs)967 TEST_F(DeoptimizeEliminationTest, RemovNumericInputs)
968 {
969     GRAPH(GetGraph())
970     {
971         PARAMETER(0, 1).b();
972         PARAMETER(1, 2).s32();
973         PARAMETER(2, 3).f64();
974         PARAMETER(3, 4).ref();
975         BASIC_BLOCK(2, -1)
976         {
977             INST(4, Opcode::SaveState).Inputs(0, 1, 2, 3).SrcVregs({0, 1, 2, 3});
978             INST(8, Opcode::DeoptimizeIf).Inputs(0, 4);
979             INST(5, Opcode::SaveState).Inputs(0, 1, 2, 3).SrcVregs({0, 1, 2, 3});
980             INST(6, Opcode::CallStatic).u64().InputsAutoType(0, 1, 2, 3, 5);
981             INST(7, Opcode::Return).u64().Inputs(6);
982         }
983     }
984     Graph *graph_et = CreateEmptyGraph();
985     GRAPH(graph_et)
986     {
987         PARAMETER(0, 1).b();
988         PARAMETER(1, 2).s32();
989         PARAMETER(2, 3).f64();
990         PARAMETER(3, 4).ref();
991         BASIC_BLOCK(2, -1)
992         {
993             INST(4, Opcode::SaveState).Inputs(0, 1, 2, 3).SrcVregs({0, 1, 2, 3});
994             INST(8, Opcode::DeoptimizeIf).Inputs(0, 4);
995             INST(5, Opcode::SaveState).Inputs(3).SrcVregs({3});
996             INST(6, Opcode::CallStatic).u64().InputsAutoType(0, 1, 2, 3, 5);
997             INST(7, Opcode::Return).u64().Inputs(6);
998         }
999     }
1000 
1001     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
1002     GraphChecker(GetGraph()).Check();
1003     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
1004 }
1005 
1006 // Removes object inputs from SS without Deoptimize
TEST_F(DeoptimizeEliminationTest,RemovObjectInputs)1007 TEST_F(DeoptimizeEliminationTest, RemovObjectInputs)
1008 {
1009     // 1 don't removed because they used in SS with deoptimization
1010     GRAPH(GetGraph())
1011     {
1012         PARAMETER(0, 1).b();
1013         PARAMETER(1, 2).ref();
1014         PARAMETER(2, 3).ref();
1015         PARAMETER(3, 4).ref();
1016         BASIC_BLOCK(2, -1)
1017         {
1018             INST(4, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
1019             INST(8, Opcode::DeoptimizeIf).Inputs(0, 4);
1020             INST(5, Opcode::SaveState).Inputs(0, 1, 2, 3).SrcVregs({0, 1, 2, 3});
1021             INST(6, Opcode::CallStatic).u64().InputsAutoType(0, 5);
1022             INST(7, Opcode::Return).u64().Inputs(6);
1023         }
1024     }
1025     Graph *graph_et = CreateEmptyGraph();
1026     GRAPH(graph_et)
1027     {
1028         PARAMETER(0, 1).b();
1029         PARAMETER(1, 2).ref();
1030         PARAMETER(2, 3).ref();
1031         PARAMETER(3, 4).ref();
1032         BASIC_BLOCK(2, -1)
1033         {
1034             INST(4, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
1035             INST(8, Opcode::DeoptimizeIf).Inputs(0, 4);
1036             INST(5, Opcode::SaveState).Inputs(1).SrcVregs({1});
1037             INST(6, Opcode::CallStatic).u64().InputsAutoType(0, 5);
1038             INST(7, Opcode::Return).u64().Inputs(6);
1039         }
1040     }
1041 
1042     ASSERT_TRUE(GetGraph()->RunPass<DeoptimizeElimination>());
1043     GraphChecker(GetGraph()).Check();
1044     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph_et));
1045 }
1046 }  // namespace panda::compiler
1047