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 #include "ecmascript/compiler/gate_accessor.h"
16 #include "ecmascript/compiler/pass.h"
17 #include "ecmascript/compiler/share_gate_meta_data.h"
18 #include "ecmascript/compiler/share_opcodes.h"
19 #include "ecmascript/compiler/value_numbering.h"
20 #include "ecmascript/compiler/verifier.h"
21 #include "ecmascript/compiler/typed_bytecode_lowering.h"
22 #include "ecmascript/compiler/typed_hcr_lowering.h"
23 #include "ecmascript/elements.h"
24 #include "ecmascript/mem/concurrent_marker.h"
25 #include "ecmascript/mem/native_area_allocator.h"
26 #include "ecmascript/tests/test_helper.h"
27 #include "gtest/gtest.h"
28 #include <cstddef>
29 #include <vector>
30 
31 namespace panda::test {
32 class GlobalValueNumberingTests : public testing::Test {};
33 
34 using ecmascript::kungfu::Circuit;
35 using ecmascript::kungfu::CircuitBuilder;
36 using ecmascript::kungfu::CombinedPassVisitor;
37 using ecmascript::kungfu::EcmaOpcode;
38 using ecmascript::kungfu::Environment;
39 using ecmascript::kungfu::GateAccessor;
40 using ecmascript::kungfu::GateRef;
41 using ecmascript::kungfu::PGOSampleType;
42 using ecmascript::kungfu::ValueNumbering;
43 using ecmascript::kungfu::Verifier;
44 
45 
HWTEST_F_L0(GlobalValueNumberingTests, AllInputsCheckedTest)46 HWTEST_F_L0(GlobalValueNumberingTests, AllInputsCheckedTest)
47 {
48     // construct a circuit
49     ecmascript::NativeAreaAllocator allocator;
50     Circuit circuit(&allocator);
51     ecmascript::Chunk chunk(&allocator);
52     GateAccessor acc(&circuit);
53     CircuitBuilder builder(&circuit);
54     Environment env(0, &builder);
55     builder.SetEnvironment(&env);
56     auto x = builder.Arguments(1);
57     auto y = builder.Arguments(2);
58     auto z = builder.Arguments(3);
59     auto add1 = builder.Int64Add(x, y);
60     auto add2 = builder.Int64Add(x, y);
61     auto add3 = builder.Int64Add(x, z);
62 
63     CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk);
64     ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false);
65 
66     EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate());
67     EXPECT_EQ(valuenumber.VisitGate(add2), add1);
68     EXPECT_EQ(valuenumber.VisitGate(add3), Circuit::NullGate());
69 }
70 
71 
HWTEST_F_L0(GlobalValueNumberingTests, DeadNodesTest)72 HWTEST_F_L0(GlobalValueNumberingTests, DeadNodesTest)
73 {
74     // construct a circuit
75     ecmascript::NativeAreaAllocator allocator;
76     Circuit circuit(&allocator);
77     ecmascript::Chunk chunk(&allocator);
78     GateAccessor acc(&circuit);
79     CircuitBuilder builder(&circuit);
80     Environment env(0, &builder);
81     builder.SetEnvironment(&env);
82     auto x = builder.Arguments(1);
83     auto y = builder.Arguments(2);
84 
85     auto add1 = builder.Int64Add(x, y);
86     auto add2 = builder.Int64Add(x, y);
87 
88     CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk);
89     ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false);
90 
91     EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate());
92     acc.DeleteGate(add1);
93     EXPECT_EQ(valuenumber.VisitGate(add2), Circuit::NullGate());
94 }
95 
HWTEST_F_L0(GlobalValueNumberingTests, WontReplaceNodeWithItself)96 HWTEST_F_L0(GlobalValueNumberingTests, WontReplaceNodeWithItself)
97 {
98     // construct a circuit
99     ecmascript::NativeAreaAllocator allocator;
100     Circuit circuit(&allocator);
101     ecmascript::Chunk chunk(&allocator);
102     GateAccessor acc(&circuit);
103     CircuitBuilder builder(&circuit);
104     Environment env(0, &builder);
105     builder.SetEnvironment(&env);
106     auto x = builder.Arguments(1);
107     auto y = builder.Arguments(2);
108 
109     auto add1 = builder.Int64Add(x, y);
110 
111     CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk);
112     ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false);
113 
114     EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate());
115     EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate());
116 }
117 
118 
HWTEST_F_L0(GlobalValueNumberingTests, E2ESimpleAddTest)119 HWTEST_F_L0(GlobalValueNumberingTests, E2ESimpleAddTest)
120 {
121     // construct a circuit
122     ecmascript::NativeAreaAllocator allocator;
123     Circuit circuit(&allocator);
124     ecmascript::Chunk chunk(&allocator);
125     GateAccessor acc(&circuit);
126     CircuitBuilder builder(&circuit);
127     Environment env(0, &builder);
128     builder.SetEnvironment(&env);
129 
130     auto x = builder.Arguments(1);
131     auto y = builder.Arguments(2);
132 
133 
134     auto add1 = builder.Int64Add(x, y);
135     auto add2 = builder.Int64Add(x, y);
136     auto add3 = builder.Int64Add(add1, add2);
137 
138     builder.Return(add3);
139     EXPECT_TRUE(Verifier::Run(&circuit));
140     CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk);
141     ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false);
142     visitor.AddPass(&valuenumber);
143     visitor.VisitGraph();
144     EXPECT_TRUE(Verifier::Run(&circuit));
145     EXPECT_TRUE(acc.GetValueIn(add3, 0) == acc.GetValueIn(add3, 1));
146     EXPECT_EQ(valuenumber.GetoptimizedGateCount(), 1);
147 }
148 
HWTEST_F_L0(GlobalValueNumberingTests, GrowStressTest)149 HWTEST_F_L0(GlobalValueNumberingTests, GrowStressTest)
150 {
151     // construct a circuit
152     ecmascript::NativeAreaAllocator allocator;
153     Circuit circuit(&allocator);
154     ecmascript::Chunk chunk(&allocator);
155     GateAccessor acc(&circuit);
156     CircuitBuilder builder(&circuit);
157     Environment env(0, &builder);
158     builder.SetEnvironment(&env);
159 
160     std::vector<GateRef> results;
161     auto x = builder.Arguments(1);
162     auto y = builder.Arguments(2);
163 
164     for (int i = 0; i < 10000; i++) {
165         auto add1 = builder.Int64Add(x, y);
166         results.push_back(add1);
167     }
168 
169     GateRef before = results[0];
170     for (int i = 1; i < 10000; i++) {
171         before = builder.Int64Add(before, results[i]);
172     }
173 
174     builder.Return(before);
175     EXPECT_TRUE(Verifier::Run(&circuit));
176     CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk);
177     ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false);
178     visitor.AddPass(&valuenumber);
179     visitor.VisitGraph();
180     EXPECT_TRUE(Verifier::Run(&circuit));
181     EXPECT_EQ(valuenumber.GetoptimizedGateCount(), 9999);
182 }
183 
184 
HWTEST_F_L0(GlobalValueNumberingTests, ComplexAddTest)185 HWTEST_F_L0(GlobalValueNumberingTests, ComplexAddTest)
186 {
187     // construct a circuit
188     ecmascript::NativeAreaAllocator allocator;
189     Circuit circuit(&allocator);
190     ecmascript::Chunk chunk(&allocator);
191     GateAccessor acc(&circuit);
192     CircuitBuilder builder(&circuit);
193     Environment env(0, &builder);
194     builder.SetEnvironment(&env);
195 
196     auto x = builder.Arguments(1);
197     auto y = builder.Arguments(2);
198 
199     auto add1 = builder.Int64Add(x, y);
200     auto add2 = builder.Int64Add(x, y);
201     auto add3 = builder.Int64Add(add1, add2);
202 
203     auto add4 = builder.Int64Add(x, y);
204     auto add5 = builder.Int64Add(x, y);
205     auto add6 = builder.Int64Add(add4, add5);
206 
207     auto add7 = builder.Int64Add(add3, add6);
208     builder.Return(add7);
209     EXPECT_TRUE(Verifier::Run(&circuit));
210     CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk);
211     ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false);
212     visitor.AddPass(&valuenumber);
213     visitor.VisitGraph();
214     EXPECT_TRUE(Verifier::Run(&circuit));
215     EXPECT_EQ(valuenumber.GetoptimizedGateCount(), 4);
216 }
217 
218 } // namespace panda::test