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