• 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 
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