1/*
2 * Copyright (c) 2023 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 "ecmascript/compiler/combined_pass_visitor.h"
17#include "ecmascript/compiler/dead_code_elimination.h"
18#include "ecmascript/compiler/verifier.h"
19#include "ecmascript/tests/test_helper.h"
20
21namespace panda::test {
22class DeadCodeEliminationTests : public testing::Test {
23};
24using ecmascript::kungfu::Chunk;
25using ecmascript::kungfu::CombinedPassVisitor;
26using ecmascript::kungfu::Circuit;
27using ecmascript::kungfu::CircuitBuilder;
28using ecmascript::kungfu::DeadCodeElimination;
29using ecmascript::kungfu::Environment;
30using ecmascript::kungfu::OpCode;
31using ecmascript::kungfu::GateType;
32using ecmascript::kungfu::MachineType;
33using ecmascript::kungfu::GateAccessor;
34using ecmascript::kungfu::GateRef;
35using ecmascript::kungfu::Verifier;
36using ecmascript::NativeAreaAllocator;
37
38HWTEST_F_L0(DeadCodeEliminationTests, CommonEliminationFramework)
39{
40    // construct a circuit
41    ecmascript::NativeAreaAllocator allocator;
42    Circuit circuit(&allocator);
43    CircuitBuilder builder(&circuit);
44    GateAccessor acc(&circuit);
45    auto depend = acc.GetDependRoot();
46    auto arg0 = builder.Arguments(0);
47    auto dead = circuit.DeadGate();
48    auto ifBranch = circuit.NewGate(circuit.IfBranch(0), {dead, arg0});
49    auto ifTrue = circuit.NewGate(circuit.IfTrue(), {ifBranch});
50    auto ifFalse = circuit.NewGate(circuit.IfFalse(), {ifBranch});
51    auto trueReturn = circuit.NewGate(circuit.Return(), {ifTrue, depend, arg0, circuit.GetReturnRoot()});
52    auto falseReturn = circuit.NewGate(circuit.Return(), {ifFalse, depend, arg0, circuit.GetReturnRoot()});
53    Chunk chunk(&allocator);
54    CombinedPassVisitor visitor(&circuit, false, "dead code elimination", &chunk);
55    DeadCodeElimination elimination(&circuit, &visitor, &chunk);
56    visitor.AddPass(&elimination);
57    visitor.VisitGraph();
58    EXPECT_TRUE(acc.IsNop(ifBranch));
59    EXPECT_TRUE(acc.IsNop(ifTrue));
60    EXPECT_TRUE(acc.IsNop(ifFalse));
61    EXPECT_TRUE(acc.IsNop(trueReturn));
62    EXPECT_TRUE(acc.IsNop(falseReturn));
63}
64
65HWTEST_F_L0(DeadCodeEliminationTests, MergeEliminationFramework)
66{
67    // construct a circuit
68    ecmascript::NativeAreaAllocator allocator;
69    Circuit circuit(&allocator);
70    CircuitBuilder builder(&circuit);
71    Environment env(0, &builder);
72    builder.SetEnvironment(&env);
73    GateAccessor acc(&circuit);
74    auto entry = acc.GetStateRoot();
75    auto depend = acc.GetDependRoot();
76    auto arg0 = builder.Arguments(0);
77    auto arg1 = builder.Arguments(1);
78    auto arg2 = builder.Arguments(2);
79    auto dead = circuit.DeadGate();
80    auto icmp = circuit.NewGate(circuit.Icmp(1), MachineType::I1, {arg0, arg1}, GateType::NJSValue());
81    auto ifBranch = circuit.NewGate(circuit.IfBranch(0), {entry, icmp});
82    circuit.NewGate(circuit.IfTrue(), {ifBranch});
83    auto ifFalse = circuit.NewGate(circuit.IfFalse(), {ifBranch});
84    auto merge = circuit.NewGate(circuit.Merge(2), {dead, ifFalse});
85    auto valueSelector = circuit.NewGate(circuit.ValueSelector(2), {merge, arg1, arg2});
86    auto circuitReturn = circuit.NewGate(circuit.Return(), {merge, depend, valueSelector, circuit.GetReturnRoot()});
87    Chunk chunk(&allocator);
88    CombinedPassVisitor visitor(&circuit, false, "dead code elimination", &chunk);
89    DeadCodeElimination elimination(&circuit, &visitor, &chunk);
90    visitor.AddPass(&elimination);
91    visitor.VisitGraph();
92    EXPECT_TRUE(acc.IsNop(merge));
93    EXPECT_TRUE(acc.IsNop(valueSelector));
94    EXPECT_TRUE(acc.GetValueIn(circuitReturn) == arg2);
95}
96
97HWTEST_F_L0(DeadCodeEliminationTests, MergeInputEliminationFramework)
98{
99    // construct a circuit
100    ecmascript::NativeAreaAllocator allocator;
101    Circuit circuit(&allocator);
102    CircuitBuilder builder(&circuit);
103    Environment env(0, &builder);
104    builder.SetEnvironment(&env);
105    GateAccessor acc(&circuit);
106    auto entry = acc.GetStateRoot();
107    auto depend = acc.GetDependRoot();
108    auto arg0 = builder.Arguments(0);
109    auto arg1 = builder.Arguments(1);
110    auto arg2 = builder.Arguments(2);
111    auto dead = circuit.DeadGate();
112    auto icmp = circuit.NewGate(circuit.Icmp(1), MachineType::I1, {arg0, arg1}, GateType::NJSValue());
113    auto ifBranch = circuit.NewGate(circuit.IfBranch(0), {entry, icmp});
114    auto ifTrue = circuit.NewGate(circuit.IfTrue(), {ifBranch});
115    auto ifFalse = circuit.NewGate(circuit.IfFalse(), {ifBranch});
116    auto ifBranch2 = circuit.NewGate(circuit.IfBranch(0), {ifTrue, icmp});
117    auto ifTrue2 = circuit.NewGate(circuit.IfTrue(), {ifBranch2});
118    circuit.NewGate(circuit.IfFalse(), {ifBranch2});
119    auto merge = circuit.NewGate(circuit.Merge(3), {ifTrue2, dead, ifFalse});
120    auto valueSelector = circuit.NewGate(circuit.ValueSelector(3), {merge, arg0, arg1, arg2});
121    auto circuitReturn = circuit.NewGate(circuit.Return(), {merge, depend, valueSelector, circuit.GetReturnRoot()});
122    Chunk chunk(&allocator);
123    CombinedPassVisitor visitor(&circuit, false, "dead code elimination", &chunk);
124    DeadCodeElimination elimination(&circuit, &visitor, &chunk);
125    visitor.AddPass(&elimination);
126    visitor.VisitGraph();
127    EXPECT_TRUE(acc.GetOpCode(merge) == OpCode::MERGE);
128    EXPECT_TRUE(acc.GetOpCode(valueSelector) == OpCode::VALUE_SELECTOR);
129    EXPECT_TRUE(acc.GetValueIn(circuitReturn) == valueSelector);
130    EXPECT_TRUE(acc.GetNumIns(merge) == 2);
131    EXPECT_TRUE(acc.GetNumIns(valueSelector) == 3);
132    EXPECT_TRUE(acc.GetIn(merge, 0) == ifTrue2);
133    EXPECT_TRUE(acc.GetIn(merge, 1) == ifFalse);
134    EXPECT_TRUE(acc.GetIn(valueSelector, 1) == arg0);
135    EXPECT_TRUE(acc.GetIn(valueSelector, 2) == arg2);
136}
137
138}