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
18 namespace panda::ecmascript::kungfu {
19
GetGateOrder(GateRef gate)20 int32_t CombinedPassVisitor::GetGateOrder(GateRef gate)
21 {
22 auto id = acc_.GetId(gate);
23 if (id >= orderList_.size()) {
24 Resize(id + 1, -1);
25 }
26 return orderList_[acc_.GetId(gate)];
27 }
28
SetGateOrder(GateRef gate,int32_t orderId)29 void CombinedPassVisitor::SetGateOrder(GateRef gate, int32_t orderId)
30 {
31 auto id = acc_.GetId(gate);
32 if (id >= orderList_.size()) {
33 Resize(id + 1, -1);
34 }
35 orderList_[acc_.GetId(gate)] = orderId;
36 }
37
Resize(int32_t size,int32_t num)38 void CombinedPassVisitor::Resize(int32_t size, int32_t num)
39 {
40 orderList_.resize(size, num);
41 }
42
AddPass(PassVisitor * pass)43 void CombinedPassVisitor::AddPass(PassVisitor* pass)
44 {
45 passList_.emplace_back(pass);
46 }
47
ReplaceGate(GateRef gate,GateRef replacement)48 void CombinedPassVisitor::ReplaceGate(GateRef gate, GateRef replacement)
49 {
50 GateRef depend = Circuit::NullGate();
51 if (acc_.GetDependCount(gate) > 0) {
52 ASSERT(acc_.GetDependCount(gate) == 1 || acc_.GetOpCode(replacement) == OpCode::DEAD); // 1: one dep
53 depend = acc_.GetDep(gate);
54 }
55 GateRef state = Circuit::NullGate();
56 if (acc_.GetStateCount(gate) > 0) {
57 ASSERT(acc_.GetStateCount(gate) == 1 || acc_.GetOpCode(replacement) == OpCode::DEAD); // 1: one state
58 state = acc_.GetState(gate);
59 }
60 return ReplaceGate(gate, StateDepend {state, depend}, replacement);
61 }
62
ReplaceGate(GateRef gate,StateDepend stateDepend,GateRef replacement)63 void CombinedPassVisitor::ReplaceGate(GateRef gate, StateDepend stateDepend, GateRef replacement)
64 {
65 ASSERT(gate != replacement);
66 auto state = stateDepend.State();
67 auto depend = stateDepend.Depend();
68 auto uses = acc_.Uses(gate);
69 for (auto it = uses.begin(); it != uses.end();) {
70 if (acc_.GetMark(*it) == MarkCode::FINISHED) {
71 PushChangedGate(*it);
72 }
73 if (acc_.GetOpCode(replacement) == OpCode::DEAD) {
74 it = acc_.ReplaceIn(it, replacement);
75 } else if (acc_.IsStateIn(it)) {
76 ASSERT(state != Circuit::NullGate());
77 it = acc_.ReplaceIn(it, state);
78 } else if (acc_.IsDependIn(it)) {
79 ASSERT(depend != Circuit::NullGate());
80 it = acc_.ReplaceIn(it, depend);
81 } else {
82 it = acc_.ReplaceIn(it, replacement);
83 }
84 }
85 acc_.DeleteGate(gate);
86 }
87
VisitGraph()88 void CombinedPassVisitor::VisitGraph()
89 {
90 for (auto pass : passList_) {
91 pass->Initialize();
92 }
93 circuit_->AdvanceTime();
94 orderCount_ = 0;
95 Resize(circuit_->GetMaxGateId() + 1, -1);
96 GateRef returnList = acc_.GetReturnRoot();
97 auto uses = acc_.Uses(returnList);
98 for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
99 PushChangedGate(*useIt);
100 }
101
102 while (true) {
103 if (!workList_.empty()) {
104 Edge& current = workList_.back();
105 VisitTopGate(current);
106 } else if (!changedList_.empty()) {
107 GateRef gate = changedList_.back();
108 changedList_.pop_back();
109 if (acc_.GetMark(gate) == MarkCode::PREVISIT) {
110 PushGate(gate, 0);
111 }
112 } else {
113 for (auto pass : passList_) {
114 pass->Finalize();
115 }
116 break;
117 }
118 }
119 }
120
ReVisitGate(GateRef gate)121 void CombinedPassVisitor::ReVisitGate(GateRef gate)
122 {
123 if (acc_.GetMark(gate) == MarkCode::FINISHED) {
124 PushChangedGate(gate);
125 }
126 }
127
128
VisitGate(GateRef gate)129 GateRef CombinedPassVisitor::VisitGate(GateRef gate)
130 {
131 auto skip = passList_.end();
132 for (auto i = passList_.begin(); i != passList_.end();) {
133 if (i == skip) {
134 i++;
135 continue;
136 }
137 GateRef replacement = (*i)->VisitGate(gate);
138 if (replacement == gate) {
139 skip = i;
140 i = passList_.begin();
141 continue;
142 } else if (replacement != Circuit::NullGate()) {
143 return replacement;
144 }
145 i++;
146 }
147 if (skip == passList_.end()) {
148 return Circuit::NullGate();
149 }
150 return gate;
151 }
152 // Reverse post-order
VisitTopGate(Edge & current)153 void CombinedPassVisitor::VisitTopGate(Edge& current)
154 {
155 GateRef gate = current.GetGate();
156 // gate is delete or dead
157 if (acc_.IsNop(gate)) {
158 PopGate(gate);
159 return;
160 }
161 auto numIns = acc_.GetNumIns(gate);
162 auto start = current.GetIndex();
163 if (start >= numIns) {
164 start = 0;
165 }
166 for (size_t i = start; i < numIns; i++) {
167 GateRef input = acc_.GetIn(gate, i);
168 if (input == gate) {
169 continue;
170 }
171 // find not visited gate, push stack
172 if (acc_.GetMark(input) < MarkCode::VISITED) {
173 PushGate(input, 0);
174 // next index
175 current.SetIndex(i + 1);
176 return;
177 }
178 }
179 for (size_t i = 0; i < start; i++) {
180 GateRef input = acc_.GetIn(gate, i);
181 if (input == gate) {
182 continue;
183 }
184 // find not visited gate, push stack
185 if (acc_.GetMark(input) < MarkCode::VISITED) {
186 PushGate(input, 0);
187 // next index
188 current.SetIndex(i + 1);
189 return;
190 }
191 }
192 // all input are visited
193 if (GetGateOrder(gate) == -1) { // -1 : not visited before
194 SetGateOrder(gate, ++orderCount_);
195 }
196 GateRef replacement = VisitGate(gate);
197 PopGate(gate);
198 if (replacement == Circuit::NullGate()) {
199 return;
200 }
201 if (replacement != gate) {
202 ReplaceGate(gate, replacement);
203 } else {
204 // revisit not on stack gate.
205 auto uses = acc_.Uses(gate);
206 for (auto it = uses.begin(); it != uses.end(); it++) {
207 if (acc_.GetMark(*it) == MarkCode::FINISHED) {
208 PushChangedGate(*it);
209 }
210 }
211 }
212 }
213
PrintStack()214 void CombinedPassVisitor::PrintStack()
215 {
216 std::string log;
217 for (size_t i = 0; i < workList_.size(); i++) {
218 Edge current = workList_[i];
219 GateRef gate = current.GetGate();
220 log += std::to_string(acc_.GetId(gate)) + ", ";
221 }
222 LOG_COMPILER(INFO) << std::dec << log;
223 }
224
PrintLog(const std::string & phaseName)225 void CombinedPassVisitor::PrintLog(const std::string& phaseName)
226 {
227 if (enableLog_) {
228 LOG_COMPILER(INFO) << "";
229 LOG_COMPILER(INFO) << "\033[34m"
230 << "===================="
231 << " After " << phaseName << " "
232 << "[" << methodName_ << "]"
233 << "===================="
234 << "\033[0m";
235 circuit_->PrintAllGatesWithBytecode();
236 LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
237 }
238 }
239
240 } // namespace panda::ecmascript::kungfu
241