• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 <random>
17 
18 #include "ecmascript/compiler/circuit_optimizer.h"
19 #include "ecmascript/compiler/early_elimination.h"
20 #include "ecmascript/compiler/verifier.h"
21 #include "ecmascript/mem/native_area_allocator.h"
22 #include "ecmascript/tests/test_helper.h"
23 
24 namespace panda::test {
25 class CircuitOptimizerTests : public testing::Test {
26 };
27 
28 using ecmascript::kungfu::Circuit;
29 using ecmascript::kungfu::OpCode;
30 using ecmascript::kungfu::GateType;
31 using ecmascript::kungfu::MachineType;
32 using ecmascript::kungfu::GateAccessor;
33 using ecmascript::kungfu::GateRef;
34 
HWTEST_F_L0(CircuitOptimizerTests,TestLatticeEquationsSystemSolverFramework)35 HWTEST_F_L0(CircuitOptimizerTests, TestLatticeEquationsSystemSolverFramework)
36 {
37     // construct a circuit
38     ecmascript::NativeAreaAllocator allocator;
39     Circuit circuit(&allocator);
40     GateAccessor acc(&circuit);
41     auto n = circuit.NewArg(MachineType::I64, 0, GateType::NJSValue(),
42                             acc.GetArgRoot());
43     auto constantA = circuit.GetConstantGate(MachineType::I64, 1, GateType::NJSValue());
44     auto constantB = circuit.GetConstantGate(MachineType::I64,
45         2, GateType::NJSValue()); // 2: idx 2
46     auto constantC = circuit.GetConstantGate(MachineType::I64, 1, GateType::NJSValue());
47     auto constantD = circuit.GetConstantGate(MachineType::I64, 0, GateType::NJSValue());
48     auto loopBegin = circuit.NewGate(circuit.LoopBegin(),
49                                      MachineType::NOVALUE,
50                                      { acc.GetStateRoot(), Circuit::NullGate() },
51                                      GateType::Empty());
52     auto selectorA = circuit.NewGate(circuit.ValueSelector(2), // 2: valuesIn
53                                      MachineType::I64,
54                                      { loopBegin, constantA, Circuit::NullGate() },
55                                      GateType::NJSValue());
56     auto selectorB = circuit.NewGate(circuit.ValueSelector(2), // 2: valuesIn
57                                      MachineType::I64,
58                                      { loopBegin, n, Circuit::NullGate() },
59                                      GateType::NJSValue());
60     auto newX = circuit.NewGate(circuit.Sub(),
61                                 MachineType::I64,
62                                 {constantB, selectorA},
63                                 GateType::NJSValue());
64     acc.NewIn(selectorA, 2, newX);
65     acc.NewIn(selectorB,
66               2,
67               circuit.NewGate(circuit.Sub(),
68                               MachineType::I64,
69                               {selectorB, constantC},
70                               GateType::NJSValue()));
71     auto predicate = circuit.NewGate(circuit.Icmp(
72                                      static_cast<uint64_t>(ecmascript::kungfu::ICmpCondition::NE)),
73                                      MachineType::I1,
74                                      {selectorB, constantD},
75                                      GateType::NJSValue());
76     auto ifBranch = circuit.NewGate(circuit.IfBranch(),
77                                     {loopBegin, predicate});
78     auto ifTrue = circuit.NewGate(circuit.IfTrue(),
79                                   {ifBranch});
80     auto ifFalse = circuit.NewGate(circuit.IfFalse(),
81                                    {ifBranch});
82     auto loopBack = circuit.NewGate(circuit.LoopBack(),
83                                     {ifTrue});
84     acc.NewIn(loopBegin, 1, loopBack);
85     auto ret = circuit.NewGate(circuit.Return(),
86                                { ifFalse,
87                                 acc.GetDependRoot(),
88                                 newX,
89                                 acc.GetReturnRoot() });
90     // verify the circuit
91     {
92         auto verifyResult = ecmascript::kungfu::Verifier::Run(&circuit);
93         EXPECT_EQ(verifyResult, true);
94     }
95     {
96         ecmascript::kungfu::LatticeUpdateRuleSCCP rule;
97         ecmascript::kungfu::LatticeEquationsSystemSolverFramework solver(&rule);
98         // optimize the circuit
99         auto optimizeResult = solver.Run(&circuit, false);
100         EXPECT_EQ(optimizeResult, true);
101         // check optimization result (returned value is constant 1)
102         EXPECT_TRUE(solver.GetReachabilityLattice(ret).IsReachable());
103         EXPECT_TRUE(solver.GetValueLattice(acc.GetIn(ret, 2)).GetValue() == 1);
104     }
105     {
106         // modify the initial value of x to 2
107         acc.SetMetaData(constantA, circuit.Constant(2));
108     }
109     {
110         ecmascript::kungfu::LatticeUpdateRuleSCCP rule;
111         ecmascript::kungfu::LatticeEquationsSystemSolverFramework solver(&rule);
112         // optimize the circuit
113         auto optimizeResult = solver.Run(&circuit, false);
114         EXPECT_EQ(optimizeResult, true);
115         // check optimization result (returned value is not constant)
116         EXPECT_TRUE(solver.GetReachabilityLattice(ret).IsReachable());
117         EXPECT_TRUE(solver.GetValueLattice(acc.GetIn(ret, 2)).IsBot());
118     }
119     {
120         // set the initial value of n to fixed value 0 (instead of function argument)
121         acc.SetMetaData(n, circuit.Constant(0));
122     }
123     {
124         ecmascript::kungfu::LatticeUpdateRuleSCCP rule;
125         ecmascript::kungfu::LatticeEquationsSystemSolverFramework solver(&rule);
126         // optimize the circuit
127         auto optimizeResult = solver.Run(&circuit, false);
128         EXPECT_EQ(optimizeResult, true);
129         // check optimization result (returned value is constant 0)
130         EXPECT_TRUE(solver.GetReachabilityLattice(ret).IsReachable());
131         EXPECT_TRUE(solver.GetValueLattice(acc.GetIn(ret, 2)).GetValue() == 0);
132     }
133 }
134 
HWTEST_F_L0(CircuitOptimizerTests,TestSubgraphRewriteFramework)135 HWTEST_F_L0(CircuitOptimizerTests, TestSubgraphRewriteFramework)
136 {
137     ecmascript::NativeAreaAllocator allocator;
138     Circuit circuit(&allocator);
139     GateAccessor acc(&circuit);
140     const uint64_t numOfConstants = 100;
141     const uint64_t numOfUses = 10;
142     std::random_device randomDevice;
143     std::mt19937_64 rng(randomDevice());
144     std::multimap<uint64_t, GateRef> constantsSet;
145     for (uint64_t iter = 0; iter < numOfUses; iter++) {
146         for (uint64_t idx = 0; idx < numOfConstants; idx++) {
147             constantsSet.insert(
148                 std::make_pair(rng(),
149                                circuit.GetConstantGate(MachineType::I64,
150                                                        idx,
151                                                        GateType::NJSValue())));
152         }
153     }
154     while (constantsSet.size() > 1) {
155         const auto elementA = constantsSet.begin();
156         const auto operandA = elementA->second;
157         constantsSet.erase(elementA);
158         const auto elementB = constantsSet.begin();
159         const auto operandB = elementB->second;
160         constantsSet.erase(elementB);
161         constantsSet.insert(
162             std::make_pair(rng(),
163                            circuit.NewGate(circuit.Add(),
164                                            MachineType::I64,
165                                            {operandA,
166                                             operandB},
167                                            GateType::NJSValue())));
168     }
169     auto ret = circuit.NewGate(circuit.Return(),
170                                { acc.GetStateRoot(),
171                                 acc.GetDependRoot(),
172                                 constantsSet.begin()->second,
173                                 acc.GetReturnRoot() });
174     ecmascript::kungfu::SubgraphRewriteRuleCP rule;
175     ecmascript::kungfu::SubGraphRewriteFramework rewriter(&rule);
176     rewriter.Run(&circuit);
177     auto returnValue = acc.GetIn(ret, 2);
178     EXPECT_TRUE(acc.GetOpCode(returnValue) == OpCode::CONSTANT);
179     EXPECT_TRUE(acc.GetConstantValue(returnValue) == (numOfUses) * (numOfConstants) * (numOfConstants - 1) / 2);
180 }
181 
HWTEST_F_L0(CircuitOptimizerTests,TestLatticeUpdateRuleSCCP)182 HWTEST_F_L0(CircuitOptimizerTests, TestLatticeUpdateRuleSCCP)
183 {
184     ecmascript::NativeAreaAllocator allocator;
185     Circuit circuit(&allocator);
186     GateAccessor acc(&circuit);
187     auto constantA = circuit.NewGate(circuit.Constant(-8848),
188                                      MachineType::I32,
189                                      GateType::NJSValue());
190     auto constantB = circuit.NewGate(circuit.Constant(4),
191                                      MachineType::I32,
192                                      GateType::NJSValue());
193     auto newX = circuit.NewGate(circuit.Sdiv(),
194                                 MachineType::I32,
195                                 {constantA, constantB},
196                                 GateType::NJSValue());
197     auto ret = circuit.NewGate(circuit.Return(),
198                                { acc.GetStateRoot(),
199                                 circuit.GetDependRoot(),
200                                 newX,
201                                 acc.GetReturnRoot()});
202     {
203         int32_t x = -8848;
204         int32_t y = 4;
205         ecmascript::kungfu::LatticeUpdateRuleSCCP rule;
206         ecmascript::kungfu::LatticeEquationsSystemSolverFramework solver(&rule);
207         // optimize the circuit
208         auto optimizeResult = solver.Run(&circuit, false);
209         EXPECT_EQ(optimizeResult, true);
210         // check optimization result (returned value is constant -2212)
211         EXPECT_TRUE(solver.GetReachabilityLattice(ret).IsReachable());
212         EXPECT_EQ(solver.GetValueLattice(acc.GetIn(ret, 2)).GetValue(),
213                   ecmascript::base::bit_cast<uint32_t>(x / y));
214     }
215     {
216         acc.SetMetaData(newX, circuit.Udiv());
217         uint32_t x = -8848;
218         uint32_t y = 4;
219         ecmascript::kungfu::LatticeUpdateRuleSCCP rule;
220         ecmascript::kungfu::LatticeEquationsSystemSolverFramework solver(&rule);
221         // optimize the circuit
222         auto optimizeResult = solver.Run(&circuit, false);
223         EXPECT_EQ(optimizeResult, true);
224         // check optimization result (returned value is constant 1073739612)
225         EXPECT_TRUE(solver.GetReachabilityLattice(ret).IsReachable());
226         EXPECT_EQ(solver.GetValueLattice(acc.GetIn(ret, 2)).GetValue(), x / y);
227     }
228     {
229         // modify the initial type of constantA to int8_t
230         acc.SetMachineType(constantA, MachineType::I8);
231         // modify the initial value of constantA to 200
232         acc.SetMetaData(constantA, circuit.Constant(200));
233         // modify the initial type of constantB to int8_t
234         acc.SetMachineType(constantB, MachineType::I8);
235         // modify the initial value of constantB to 200
236         acc.SetMetaData(constantB, circuit.Constant(200));
237         acc.SetMachineType(newX, MachineType::I8);
238         acc.SetMetaData(newX, circuit.Add());
239         ecmascript::kungfu::LatticeUpdateRuleSCCP rule;
240         ecmascript::kungfu::LatticeEquationsSystemSolverFramework solver(&rule);
241         // optimize the circuit
242         auto optimizeResult = solver.Run(&circuit, false);
243         EXPECT_EQ(optimizeResult, true);
244         // check optimization result (returned value is constant 144)
245         EXPECT_TRUE(solver.GetReachabilityLattice(ret).IsReachable());
246         EXPECT_EQ(solver.GetValueLattice(acc.GetIn(ret, 2)).GetValue(), 144);
247     }
248     {
249         float x = 9.6;
250         float y = 6.9;
251         // modify the initial type of constantA to float
252         acc.SetMachineType(constantA, MachineType::F32);
253         // modify the initial value of constantA to 9.6
254         acc.SetMetaData(constantA, circuit.Constant(ecmascript::base::bit_cast<uint32_t>(x)));
255         // modify the initial type of constantB to float
256         acc.SetMachineType(constantB, MachineType::F32);
257         // modify the initial value of constantB to 6.9
258         acc.SetMetaData(constantB, circuit.Constant(ecmascript::base::bit_cast<uint32_t>(y)));
259         acc.SetMachineType(newX, MachineType::F32);
260         acc.SetMetaData(newX, circuit.Fmod());
261         ecmascript::kungfu::LatticeUpdateRuleSCCP rule;
262         ecmascript::kungfu::LatticeEquationsSystemSolverFramework solver(&rule);
263         // optimize the circuit
264         auto optimizeResult = solver.Run(&circuit, false);
265         EXPECT_EQ(optimizeResult, true);
266         // check optimization result (returned value is constant 2.7)
267         EXPECT_TRUE(solver.GetReachabilityLattice(ret).IsReachable());
268         EXPECT_EQ(ecmascript::base::bit_cast<double>(solver.GetValueLattice(acc.GetIn(ret, 2)).GetValue().value()),
269                   fmod(x, y));
270     }
271 }
272 
HWTEST_F_L0(CircuitOptimizerTests,TestSmallSizeGlobalValueNumbering)273 HWTEST_F_L0(CircuitOptimizerTests, TestSmallSizeGlobalValueNumbering) {
274     // construct a circuit
275     ecmascript::NativeAreaAllocator allocator;
276     Circuit circuit(&allocator);
277     GateAccessor acc(&circuit);
278     auto constantA = circuit.NewGate(circuit.Constant(1),
279         MachineType::I64, GateType::NJSValue());
280     auto constantB = circuit.NewGate(circuit.Constant(1),
281         MachineType::I64, GateType::NJSValue());
282     auto argA = circuit.NewArg(MachineType::I64, 1,
283                                GateType::NJSValue(),
284                                acc.GetArgRoot());
285     auto argB = circuit.NewArg(MachineType::I64, 2,
286                                GateType::NJSValue(),
287                                acc.GetArgRoot());
288 
289     auto add1 = circuit.NewGate(circuit.Add(),
290                                MachineType::I64,
291                                {constantA, argA},
292                                GateType::NJSValue());
293 
294     auto add2 = circuit.NewGate(circuit.Add(),
295                                 MachineType::I64,
296                                 { constantB, argA },
297                                 GateType::NJSValue());
298 
299     auto add3 = circuit.NewGate(circuit.Add(),
300                                 MachineType::I64,
301                                 { constantA, argB },
302                                 GateType::NJSValue());
303     ecmascript::kungfu::GlobalValueNumbering(&circuit, false).Run();
304     EXPECT_FALSE(acc.GetMetaData(add3)->IsNop());
305     EXPECT_FALSE(acc.GetMetaData(argA)->IsNop());
306     EXPECT_FALSE(acc.GetMetaData(argB)->IsNop());
307     EXPECT_TRUE(acc.GetMetaData(constantA)->IsNop() || acc.GetMetaData(constantB)->IsNop());
308     EXPECT_FALSE(acc.GetMetaData(constantA)->IsNop() && acc.GetMetaData(constantB)->IsNop());
309     EXPECT_TRUE(acc.GetMetaData(add1)->IsNop() || acc.GetMetaData(add2)->IsNop());
310     EXPECT_FALSE(acc.GetMetaData(add1)->IsNop() && acc.GetMetaData(add2)->IsNop());
311 }
312 
HWTEST_F_L0(CircuitOptimizerTests,TestMultiLevelGlobalValueNumbering)313 HWTEST_F_L0(CircuitOptimizerTests, TestMultiLevelGlobalValueNumbering) {
314     ecmascript::NativeAreaAllocator allocator;
315     Circuit circuit(&allocator);
316     GateAccessor acc(&circuit);
317     std::random_device randomDevice;
318     std::mt19937_64 rng(randomDevice());
319     std::vector<GateRef> args;
320     for (uint32_t i = 0; i < 5; ++i) {
321         args.push_back(circuit.NewArg(MachineType::I64, i, GateType::NJSValue(),
322             acc.GetArgRoot()));
323     }
324     std::map<GateRef, std::vector<GateRef>> addToAdds;
325     std::map<GateRef, GateRef> addToAdd;
326     std::map<std::pair<GateRef, GateRef>, GateRef> pairToAdd;
327     std::vector<GateRef> adds;
328     for (uint32_t i = 0; i < 50; ++i) {
329         std::pair<GateRef, GateRef> p(args[rng() % 5], args[rng() % 5]);
330         auto add = circuit.NewGate(circuit.Add(),
331                                    MachineType::I64,
332                                    {p.first, p.second},
333                                    GateType::NJSValue());
334         adds.push_back(add);
335         if (pairToAdd.count(p) == 0) {
336             pairToAdd[p] = add;
337             addToAdds[add] = std::vector<GateRef>(0);
338         }
339         addToAdd[add] = pairToAdd[p];
340         addToAdds[addToAdd[add]].emplace_back(add);
341     }
342     std::map<GateRef, std::vector<GateRef>> subToSubs;
343     std::map<GateRef, GateRef> subToSub;
344     std::map<std::pair<GateRef, GateRef>, GateRef> pairToSub;
345     std::vector<GateRef> subs;
346     for (uint32_t i = 0; i < 50; ++i) {
347         std::pair<GateRef, GateRef> p(adds[rng() % 5], adds[rng() % 5]);
348         auto sub = circuit.NewGate(circuit.Sub(),
349                                MachineType::I64,
350                                {p.first, p.second},
351                                GateType::NJSValue());
352         subs.push_back(sub);
353         // remove redundant adds.
354         std::pair<GateRef, GateRef> np(addToAdd[p.first], addToAdd[p.second]);
355         if (pairToSub.count(np) == 0) {
356             pairToSub[np] = sub;
357             subToSubs[sub] = std::vector<GateRef>(0);
358         }
359         subToSub[sub] = pairToSub[np];
360         subToSubs[subToSub[sub]].emplace_back(sub);
361     }
362     ecmascript::kungfu::GlobalValueNumbering(&circuit, false).Run();
363     std::map<GateRef, GateRef> gateToKing;
364     for (const auto &p : addToAdds) {
365         uint32_t cnt = 0;
366         GateRef kingGate;
367         for (auto gate : p.second) {
368             if (acc.GetOpCode(gate) != OpCode::NOP) {
369                 cnt++;
370                 kingGate = gate;
371             }
372         }
373         EXPECT_TRUE(cnt == 1);
374         for (auto gate : p.second) {
375             gateToKing[gate] = kingGate;
376         }
377     }
378     for (const auto &p : subToSubs) {
379         uint32_t cnt = 0;
380         GateRef kingGate;
381         for (auto gate : p.second) {
382             if (acc.GetOpCode(gate) != OpCode::NOP) {
383                 cnt++;
384                 kingGate = gate;
385             }
386         }
387         EXPECT_TRUE(cnt == 1);
388         for (auto gate : p.second) {
389             gateToKing[gate] = kingGate;
390         }
391     }
392     std::vector<GateRef> gates;
393     acc.GetAllGates(gates);
394     for (auto gate : gates) {
395         if (acc.GetOpCode(gate) == OpCode::NOP) {
396             continue;
397         }
398         std::vector<GateRef> ins;
399         for (auto in : ins) {
400             EXPECT_TRUE(in == gateToKing[in]);
401         }
402     }
403 }
404 
HWTEST_F_L0(CircuitOptimizerTests,TestSmallWorldGlobalValueNumbering)405 HWTEST_F_L0(CircuitOptimizerTests, TestSmallWorldGlobalValueNumbering) {
406     ecmascript::NativeAreaAllocator allocator;
407     Circuit circuit(&allocator);
408     GateAccessor acc(&circuit);
409     std::random_device randomDevice;
410     std::mt19937_64 rng(randomDevice());
411     std::vector<GateRef> args;
412     for (uint32_t i = 0; i < 3; ++i) {
413         args.push_back(circuit.NewArg(MachineType::I64, i,
414             GateType::NJSValue(), acc.GetArgRoot()));
415     }
416     std::map<GateRef, std::vector<GateRef>> addToAdds;
417     std::map<GateRef, GateRef> addToAdd;
418     std::map<std::pair<GateRef, GateRef>, GateRef> pairToAdd;
419     std::vector<GateRef> adds;
420     std::vector<GateRef> toBeSelect;
421     for (uint32_t i = 0; i < 10; ++i) {
422         std::pair<GateRef, GateRef> p(args[rng() % 3], args[rng() % 3]);
423         auto add = circuit.NewGate(circuit.Add(),
424                                    MachineType::I64,
425                                    {p.first, p.second},
426                                    GateType::NJSValue());
427         adds.emplace_back(add);
428         toBeSelect.emplace_back(add);
429         toBeSelect.emplace_back(add);
430         if (pairToAdd.count(p) == 0) {
431             pairToAdd[p] = add;
432             addToAdds[add] = std::vector<GateRef>(0);
433         }
434         addToAdd[add] = pairToAdd[p];
435         addToAdds[addToAdd[add]].emplace_back(add);
436     }
437     for (uint32_t i = 0; i < 1000; ++i) {
438         std::pair<GateRef, GateRef> p(toBeSelect[rng() % toBeSelect.size()], toBeSelect[rng() % toBeSelect.size()]);
439         auto add = circuit.NewGate(circuit.Add(), MachineType::I64,
440                                    {p.first, p.second},
441                                    GateType::NJSValue());
442         adds.emplace_back(add);
443         toBeSelect.emplace_back(add);
444         toBeSelect.emplace_back(add);
445         toBeSelect.emplace_back(p.first);
446         toBeSelect.emplace_back(p.second);
447 
448         std::pair<GateRef, GateRef> np(addToAdd[p.first], addToAdd[p.second]);
449         if (pairToAdd.count(np) == 0) {
450             pairToAdd[np] = add;
451             addToAdds[add] = std::vector<GateRef>(0);
452         }
453         addToAdd[add] = pairToAdd[np];
454         addToAdds[addToAdd[add]].emplace_back(add);
455     }
456     ecmascript::kungfu::GlobalValueNumbering(&circuit, false).Run();
457     std::map<GateRef, GateRef> gateToKing;
458     for (const auto &p : addToAdds) {
459         uint32_t cnt = 0;
460         GateRef kingGate;
461         for (auto gate : p.second) {
462             if (acc.GetOpCode(gate) != OpCode::NOP) {
463                 cnt++;
464                 kingGate = gate;
465             }
466         }
467         EXPECT_TRUE(cnt == 1);
468         for (auto gate : p.second) {
469             gateToKing[gate] = kingGate;
470         }
471     }
472     std::vector<GateRef> gates;
473     acc.GetAllGates(gates);
474     for (auto gate : gates) {
475         if (acc.GetOpCode(gate) == OpCode::NOP) {
476             continue;
477         }
478         std::vector<GateRef> ins;
479         for (auto in : ins) {
480             EXPECT_TRUE(in == gateToKing[in]);
481         }
482     }
483 }
484 
HWTEST_F_L0(CircuitOptimizerTests,TestEarlyElimination)485 HWTEST_F_L0(CircuitOptimizerTests, TestEarlyElimination) {
486     // construct a circuit
487     ecmascript::NativeAreaAllocator allocator;
488     Circuit circuit(&allocator);
489     GateAccessor acc(&circuit);
490     auto receiver = circuit.NewArg(MachineType::I64, 1,
491                                    GateType::AnyType(),
492                                    acc.GetArgRoot());
493     auto index = circuit.NewGate(circuit.Constant(1),
494                                  MachineType::I64, GateType::NJSValue());
495     auto load0 = circuit.NewGate(circuit.LoadElement(0),
496                                 MachineType::ANYVALUE,
497                                 { acc.GetStateRoot(), acc.GetDependRoot(), receiver, index },
498                                 GateType::AnyType());
499     auto load1 = circuit.NewGate(circuit.LoadElement(0),
500                                 MachineType::ANYVALUE,
501                                 { load0, load0, receiver, index },
502                                 GateType::AnyType());
503     ecmascript::kungfu::EarlyElimination(&circuit, false, "test", &allocator).Run();
504     EXPECT_FALSE(acc.GetMetaData(load0)->IsNop());
505     EXPECT_TRUE(acc.GetMetaData(load1)->IsNop());
506 }
507 
HWTEST_F_L0(CircuitOptimizerTests,TestNotEarlyElimination)508 HWTEST_F_L0(CircuitOptimizerTests, TestNotEarlyElimination) {
509     // construct a circuit
510     ecmascript::NativeAreaAllocator allocator;
511     Circuit circuit(&allocator);
512     GateAccessor acc(&circuit);
513     auto receiver = circuit.NewArg(MachineType::I64, 1,
514                                    GateType::AnyType(),
515                                    acc.GetArgRoot());
516     auto index = circuit.NewGate(circuit.Constant(1),
517                                  MachineType::I64, GateType::NJSValue());
518     auto load0 = circuit.NewGate(circuit.LoadElement(0),
519                                  MachineType::ANYVALUE,
520                                  { acc.GetStateRoot(), acc.GetDependRoot(), receiver, index },
521                                  GateType::AnyType());
522     auto store = circuit.NewGate(circuit.StoreElement(0),
523                                  MachineType::NOVALUE,
524                                  { load0, load0, receiver, index, index },
525                                  GateType::AnyType());
526     auto load1 = circuit.NewGate(circuit.LoadElement(0),
527                                  MachineType::ANYVALUE,
528                                  { store, store, receiver, index },
529                                  GateType::AnyType());
530     ecmascript::kungfu::EarlyElimination(&circuit, false, "test", &allocator).Run();
531     EXPECT_FALSE(acc.GetMetaData(load0)->IsNop());
532     EXPECT_FALSE(acc.GetMetaData(load1)->IsNop());
533 }
534 
HWTEST_F_L0(CircuitOptimizerTests,TestMergeEarlyElimination)535 HWTEST_F_L0(CircuitOptimizerTests, TestMergeEarlyElimination) {
536     // construct a circuit
537     ecmascript::NativeAreaAllocator allocator;
538     Circuit circuit(&allocator);
539     GateAccessor acc(&circuit);
540     auto receiver = circuit.NewArg(MachineType::I64, 1,
541                                    GateType::AnyType(),
542                                    acc.GetArgRoot());
543     auto index = circuit.NewGate(circuit.Constant(1),
544                                  MachineType::I64, GateType::NJSValue());
545     auto condition = circuit.NewGate(circuit.Constant(1),
546                                      MachineType::I1, GateType::NJSValue());
547     auto load0 = circuit.NewGate(circuit.LoadElement(0),
548                                  MachineType::ANYVALUE,
549                                  { acc.GetStateRoot(), acc.GetDependRoot(), receiver, index },
550                                  GateType::AnyType());
551     auto ifBranch = circuit.NewGate(circuit.IfBranch(), {load0, condition});
552     auto ifTrue = circuit.NewGate(circuit.IfTrue(), {ifBranch});
553     auto ifFalse = circuit.NewGate(circuit.IfFalse(), {ifBranch});
554     auto ifTrueDepend = circuit.NewGate(circuit.DependRelay(), { ifTrue, load0 });
555     auto ifFalseDepend = circuit.NewGate(circuit.DependRelay(), { ifFalse, load0 });
556     auto load1 = circuit.NewGate(circuit.LoadElement(0),
557                                  MachineType::ANYVALUE,
558                                  { ifTrue, ifTrueDepend, receiver, index },
559                                  GateType::AnyType());
560     auto load2 = circuit.NewGate(circuit.LoadElement(0),
561                                  MachineType::ANYVALUE,
562                                  { ifFalse, ifFalseDepend, receiver, index },
563                                  GateType::AnyType());
564     auto merge = circuit.NewGate(circuit.Merge(2), {load1, load2});
565     auto dependSelector = circuit.NewGate(circuit.DependSelector(2),
566                                           {merge, load1, load2});
567     auto load3 = circuit.NewGate(circuit.LoadElement(0),
568                                  MachineType::ANYVALUE,
569                                  { merge, dependSelector, receiver, index },
570                                  GateType::AnyType());
571     ecmascript::kungfu::EarlyElimination(&circuit, false, "test", &allocator).Run();
572     EXPECT_FALSE(acc.GetMetaData(load0)->IsNop());
573     EXPECT_TRUE(acc.GetMetaData(load1)->IsNop());
574     EXPECT_TRUE(acc.GetMetaData(load2)->IsNop());
575     EXPECT_TRUE(acc.GetMetaData(load3)->IsNop());
576 }
577 } // namespace panda::test