• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LogicallyReplaceGate(GateRef gate,GateRef replacement)48 void CombinedPassVisitor::LogicallyReplaceGate(GateRef gate, GateRef replacement)
49 {
50     auto uses = acc_.Uses(gate);
51     for (auto it = uses.begin(); it != uses.end();) {
52         if (acc_.GetMark(*it) == MarkCode::FINISHED) {
53             PushChangedGate(*it);
54         }
55         it = acc_.ReplaceIn(it, replacement);
56     }
57 }
RelaxStateAndDepend(GateRef gate)58 void CombinedPassVisitor::RelaxStateAndDepend(GateRef gate)
59 {
60     ReplaceGate(gate, StateDepend {acc_.GetState(gate), acc_.GetDep(gate)}, gate);
61 }
62 
ReplaceGate(GateRef gate,GateRef replacement)63 void CombinedPassVisitor::ReplaceGate(GateRef gate, GateRef replacement)
64 {
65     GateRef depend = Circuit::NullGate();
66     if (acc_.GetDependCount(gate) > 0) {
67         ASSERT(acc_.GetDependCount(gate) == 1 || acc_.GetOpCode(replacement) == OpCode::DEAD); // 1: one dep
68         depend = acc_.GetDep(gate);
69     }
70     GateRef state = Circuit::NullGate();
71     if (acc_.GetStateCount(gate) > 0) {
72         ASSERT(acc_.GetStateCount(gate) == 1 || acc_.GetOpCode(replacement) == OpCode::DEAD);  // 1: one state
73         state = acc_.GetState(gate);
74     }
75     ReplaceGate(gate, StateDepend {state, depend}, replacement);
76     acc_.DeleteGate(gate);
77 }
78 
ReplaceGate(GateRef gate,StateDepend stateDepend,GateRef replacement)79 void CombinedPassVisitor::ReplaceGate(GateRef gate, StateDepend stateDepend, GateRef replacement)
80 {
81     auto state = stateDepend.State();
82     auto depend = stateDepend.Depend();
83     auto uses = acc_.Uses(gate);
84     for (auto it = uses.begin(); it != uses.end();) {
85         if (acc_.GetMark(*it) == MarkCode::FINISHED) {
86             PushChangedGate(*it);
87         }
88         if (acc_.GetOpCode(replacement) == OpCode::DEAD) {
89             it = acc_.ReplaceIn(it, replacement);
90         } else if (acc_.IsStateIn(it)) {
91             ASSERT(state != Circuit::NullGate());
92             it = acc_.ReplaceIn(it, state);
93         } else if (acc_.IsDependIn(it)) {
94             ASSERT(depend != Circuit::NullGate());
95             it = acc_.ReplaceIn(it, depend);
96         } else {
97             it = acc_.ReplaceIn(it, replacement);
98         }
99     }
100 #ifndef NDEBUG
101     acc_.GetCircuit()->AddComment(replacement,  "old V " + std::to_string(acc_.GetId(gate)));
102 #endif
103 }
104 
VistDependSelectorForLoop(GateRef gate)105 void CombinedPassVisitor::VistDependSelectorForLoop(GateRef gate)
106 {
107     auto use = acc_.Uses(gate);
108     for (auto useIt = use.begin(); useIt != use.end(); useIt++) {
109         if (acc_.GetOpCode(*useIt) == OpCode::DEPEND_SELECTOR) {
110             PushChangedGate(*useIt);
111         }
112     }
113 }
114 
VisitGraph()115 void CombinedPassVisitor::VisitGraph()
116 {
117     for (auto pass : passList_) {
118         pass->Initialize();
119     }
120     circuit_->AdvanceTime();
121     orderCount_ = 0;
122     Resize(circuit_->GetMaxGateId() + 1, -1);
123     GateRef returnList = acc_.GetReturnRoot();
124     auto uses = acc_.Uses(returnList);
125     for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
126         PushChangedGate(*useIt);
127     }
128     std::vector<GateRef> gateList;
129     circuit_->GetAllGates(gateList);
130     for (auto gate : gateList) {
131         if (acc_.GetOpCode(gate) == OpCode::LOOP_BEGIN) {
132             PushChangedGate(gate);
133             // For empty loop and no RETURN opcode
134             VistDependSelectorForLoop(gate);
135         }
136     }
137 
138     while (true) {
139         if (!workList_.empty()) {
140             Edge& current = workList_.back();
141             VisitTopGate(current);
142         } else if (!changedList_.empty()) {
143             GateRef gate = changedList_.back();
144             changedList_.pop_back();
145             if (acc_.GetMark(gate) == MarkCode::PREVISIT) {
146                 PushGate(gate, 0);
147             }
148         } else {
149             for (auto pass : passList_) {
150                 pass->Finalize();
151             }
152             break;
153         }
154     }
155 }
156 
ReVisitGate(GateRef gate)157 void CombinedPassVisitor::ReVisitGate(GateRef gate)
158 {
159     if (acc_.GetMark(gate) == MarkCode::FINISHED) {
160         PushChangedGate(gate);
161     }
162 }
163 
164 
VisitGate(GateRef gate)165 GateRef CombinedPassVisitor::VisitGate(GateRef gate)
166 {
167     [[maybe_unused]] auto scopedGate = circuit_->VisitGateBegin(gate);
168     auto skip = passList_.end();
169     for (auto i = passList_.begin(); i != passList_.end();) {
170         if (i == skip) {
171             i++;
172             continue;
173         }
174         GateRef replacement = (*i)->VisitGate(gate);
175         if (replacement == gate) {
176             skip = i;
177             i = passList_.begin();
178             continue;
179         } else if (replacement != Circuit::NullGate()) {
180             return replacement;
181         }
182         i++;
183     }
184     if (skip == passList_.end()) {
185         return Circuit::NullGate();
186     }
187     return gate;
188 }
189 // Reverse post-order
VisitTopGate(Edge & current)190 void CombinedPassVisitor::VisitTopGate(Edge& current)
191 {
192     GateRef gate = current.GetGate();
193     // gate is delete or dead
194     if (acc_.IsNop(gate)) {
195         PopGate(gate);
196         return;
197     }
198     auto numIns = acc_.GetNumIns(gate);
199     auto start = current.GetIndex();
200     if (start >= numIns) {
201         start = 0;
202     }
203     for (size_t i = start; i < numIns; i++) {
204         GateRef input = acc_.GetIn(gate, i);
205         if (input == gate) {
206             continue;
207         }
208         // find not visited gate, push stack
209         if (acc_.GetMark(input) < MarkCode::VISITED) {
210             PushGate(input, 0);
211             // next index
212             current.SetIndex(i + 1);
213             return;
214         }
215     }
216     for (size_t i = 0; i < start; i++) {
217         GateRef input = acc_.GetIn(gate, i);
218         if (input == gate) {
219             continue;
220         }
221         // find not visited gate, push stack
222         if (acc_.GetMark(input) < MarkCode::VISITED) {
223             PushGate(input, 0);
224             // next index
225             current.SetIndex(i + 1);
226             return;
227         }
228     }
229     // all input are visited
230     if (GetGateOrder(gate) == -1) { // -1 : not visited before
231         SetGateOrder(gate, ++orderCount_);
232     }
233     GateRef replacement = VisitGate(gate);
234     PopGate(gate);
235     if (replacement == Circuit::NullGate()) {
236         return;
237     }
238     if (replacement != gate) {
239         ReplaceGate(gate, replacement);
240     } else {
241         // revisit not on stack gate.
242         auto uses = acc_.Uses(gate);
243         for (auto it = uses.begin(); it != uses.end(); it++) {
244             if (acc_.GetMark(*it) == MarkCode::FINISHED) {
245                 PushChangedGate(*it);
246             }
247         }
248     }
249 }
250 
PrintStack()251 void CombinedPassVisitor::PrintStack()
252 {
253     std::string log;
254     for (size_t i = 0; i < workList_.size(); i++) {
255         Edge current = workList_[i];
256         GateRef gate = current.GetGate();
257         log += std::to_string(acc_.GetId(gate)) + ", ";
258     }
259     LOG_COMPILER(INFO) << std::dec << log;
260 }
261 
PrintLog(const std::string & phaseName)262 void CombinedPassVisitor::PrintLog(const std::string& phaseName)
263 {
264     if (enableLog_) {
265         LOG_COMPILER(INFO) << "";
266         LOG_COMPILER(INFO) << "\033[34m"
267                         << "===================="
268                         << " After " << phaseName << " "
269                         << "[" << methodName_ << "]"
270                         << "===================="
271                         << "\033[0m";
272         circuit_->PrintAllGatesWithBytecode();
273         LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
274     }
275 }
276 
277 } // namespace panda::ecmascript::kungfu
278