2023-04-21 11:24:24 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ecmascript/compiler/graph_linearizer.h"
|
|
|
|
#include "ecmascript/compiler/scheduler.h"
|
|
|
|
|
|
|
|
namespace panda::ecmascript::kungfu {
|
|
|
|
void GraphLinearizer::Run(ControlFlowGraph &result)
|
|
|
|
{
|
2023-05-10 12:44:07 +00:00
|
|
|
LinearizeGraph();
|
|
|
|
LinearizeRegions(result);
|
2023-04-21 11:24:24 +00:00
|
|
|
if (IsLogEnabled()) {
|
|
|
|
LOG_COMPILER(INFO) << "";
|
|
|
|
LOG_COMPILER(INFO) << "\033[34m"
|
|
|
|
<< "===================="
|
|
|
|
<< " After graph linearizer "
|
|
|
|
<< "[" << GetMethodName() << "]"
|
|
|
|
<< "===================="
|
|
|
|
<< "\033[0m";
|
|
|
|
PrintGraph("Build Basic Block");
|
|
|
|
LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class CFGBuilder {
|
|
|
|
public:
|
|
|
|
explicit CFGBuilder(GraphLinearizer *linearizer)
|
|
|
|
: linearizer_(linearizer), pendingList_(linearizer->chunk_),
|
2023-06-09 02:13:24 +00:00
|
|
|
endStateList_(linearizer->chunk_),
|
|
|
|
acc_(linearizer->circuit_), scheduleLIR_(linearizer->IsSchedueLIR()) {}
|
2023-04-21 11:24:24 +00:00
|
|
|
|
|
|
|
void Run()
|
|
|
|
{
|
|
|
|
VisitStateGates();
|
|
|
|
// connect region
|
2023-05-08 07:50:22 +00:00
|
|
|
for (auto rootGate : linearizer_->regionRootList_) {
|
2023-04-21 11:24:24 +00:00
|
|
|
auto toRegion = linearizer_->GateToRegion(rootGate);
|
2023-04-27 12:26:51 +00:00
|
|
|
auto numStateIn = acc_.GetStateCount(rootGate);
|
|
|
|
for (size_t i = 0; i < numStateIn; i++) {
|
|
|
|
auto input = acc_.GetState(rootGate, i);
|
2023-05-08 07:50:22 +00:00
|
|
|
ASSERT(acc_.IsState(input) || acc_.GetOpCode(input) == OpCode::STATE_ENTRY);
|
2023-06-09 02:13:24 +00:00
|
|
|
auto fromRegion = linearizer_->FindPredRegion(input);
|
2023-04-21 11:24:24 +00:00
|
|
|
fromRegion->AddSucc(toRegion);
|
|
|
|
}
|
|
|
|
}
|
2023-06-09 02:13:24 +00:00
|
|
|
for (auto fixedGate : endStateList_) {
|
|
|
|
auto state = acc_.GetState(fixedGate);
|
|
|
|
auto region = linearizer_->FindPredRegion(state);
|
|
|
|
linearizer_->AddFixedGateToRegion(fixedGate, region);
|
|
|
|
linearizer_->ScheduleGate(fixedGate, region);
|
|
|
|
}
|
2023-04-21 11:24:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void VisitStateGates()
|
|
|
|
{
|
|
|
|
ASSERT(pendingList_.empty());
|
|
|
|
linearizer_->circuit_->AdvanceTime();
|
|
|
|
auto startGate = acc_.GetStateRoot();
|
|
|
|
acc_.SetMark(startGate, MarkCode::VISITED);
|
|
|
|
pendingList_.emplace_back(startGate);
|
|
|
|
|
|
|
|
while (!pendingList_.empty()) {
|
|
|
|
auto curGate = pendingList_.back();
|
|
|
|
pendingList_.pop_back();
|
2023-06-09 02:13:24 +00:00
|
|
|
VisitStateGate(curGate);
|
2023-04-21 11:24:24 +00:00
|
|
|
if (acc_.GetOpCode(curGate) != OpCode::LOOP_BACK) {
|
|
|
|
auto uses = acc_.Uses(curGate);
|
|
|
|
for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
|
2023-05-08 07:50:22 +00:00
|
|
|
if (acc_.IsStateIn(useIt) && acc_.IsState(*useIt) && acc_.GetMark(*useIt) == MarkCode::NO_MARK) {
|
2023-04-21 11:24:24 +00:00
|
|
|
acc_.SetMark(*useIt, MarkCode::VISITED);
|
|
|
|
pendingList_.emplace_back(*useIt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 02:13:24 +00:00
|
|
|
void VisitStateGate(GateRef gate)
|
|
|
|
{
|
|
|
|
if (scheduleLIR_) {
|
|
|
|
linearizer_->CreateGateRegion(gate);
|
|
|
|
} else {
|
|
|
|
auto op = acc_.GetOpCode(gate);
|
|
|
|
switch (op) {
|
|
|
|
case OpCode::LOOP_BEGIN:
|
|
|
|
case OpCode::MERGE:
|
|
|
|
case OpCode::IF_TRUE:
|
|
|
|
case OpCode::IF_FALSE:
|
|
|
|
case OpCode::SWITCH_CASE:
|
|
|
|
case OpCode::STATE_ENTRY:
|
|
|
|
case OpCode::IF_EXCEPTION:
|
|
|
|
case OpCode::IF_SUCCESS:
|
|
|
|
linearizer_->CreateGateRegion(gate);
|
|
|
|
break;
|
|
|
|
case OpCode::LOOP_BACK:
|
|
|
|
case OpCode::IF_BRANCH:
|
|
|
|
case OpCode::SWITCH_BRANCH:
|
|
|
|
case OpCode::RETURN:
|
|
|
|
case OpCode::RETURN_VOID:
|
|
|
|
case OpCode::TYPED_CONDITION_JUMP:
|
|
|
|
endStateList_.emplace_back(gate);
|
|
|
|
break;
|
|
|
|
case OpCode::JS_BYTECODE:
|
|
|
|
if (IsStateSplit(gate)) {
|
|
|
|
endStateList_.emplace_back(gate);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsStateSplit(GateRef gate)
|
|
|
|
{
|
|
|
|
size_t stateOut = 0;
|
|
|
|
auto uses = acc_.Uses(gate);
|
|
|
|
for (auto it = uses.begin(); it != uses.end(); it++) {
|
|
|
|
if (acc_.IsStateIn(it)) {
|
|
|
|
auto op = acc_.GetOpCode(*it);
|
|
|
|
switch (op) {
|
|
|
|
case OpCode::IF_TRUE:
|
|
|
|
case OpCode::IF_FALSE:
|
|
|
|
case OpCode::IF_EXCEPTION:
|
|
|
|
case OpCode::IF_SUCCESS:
|
|
|
|
stateOut++;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return stateOut > 1; // 1: depend out
|
|
|
|
}
|
|
|
|
|
2023-04-21 11:24:24 +00:00
|
|
|
private:
|
|
|
|
GraphLinearizer* linearizer_;
|
|
|
|
ChunkDeque<GateRef> pendingList_;
|
2023-06-09 02:13:24 +00:00
|
|
|
ChunkVector<GateRef> endStateList_;
|
2023-04-21 11:24:24 +00:00
|
|
|
GateAccessor acc_;
|
2023-06-09 02:13:24 +00:00
|
|
|
bool scheduleLIR_;
|
2023-04-21 11:24:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class ImmediateDominatorsGenerator {
|
|
|
|
public:
|
|
|
|
explicit ImmediateDominatorsGenerator(GraphLinearizer *linearizer, Chunk* chunk, size_t size)
|
|
|
|
: linearizer_(linearizer), pendingList_(chunk),
|
|
|
|
dfsList_(chunk), dfsTimestamp_(size, chunk), dfsFatherIdx_(size, chunk),
|
|
|
|
bbDfsTimestampToIdx_(size, chunk), semiDom_(size, chunk), immDom_(size, chunk),
|
|
|
|
minIdx_(size, chunk), parentIdx_(size, chunk), semiDomTree_(chunk) {}
|
|
|
|
|
|
|
|
void Run()
|
|
|
|
{
|
|
|
|
BuildDfsFather();
|
|
|
|
BuildDomTree();
|
|
|
|
BuildImmediateDominator();
|
|
|
|
BuildImmediateDominatorDepth();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BuildDfsFather()
|
|
|
|
{
|
|
|
|
size_t timestamp = 0;
|
|
|
|
auto entry = linearizer_->regionList_.front();
|
2023-05-16 13:37:00 +00:00
|
|
|
linearizer_->circuit_->AdvanceTime();
|
|
|
|
entry->SetVisited(linearizer_->acc_);
|
2023-04-21 11:24:24 +00:00
|
|
|
ASSERT(pendingList_.empty());
|
|
|
|
pendingList_.emplace_back(entry);
|
|
|
|
while (!pendingList_.empty()) {
|
|
|
|
auto curRegion = pendingList_.back();
|
|
|
|
pendingList_.pop_back();
|
|
|
|
dfsList_.emplace_back(curRegion->id_);
|
|
|
|
dfsTimestamp_[curRegion->id_] = timestamp++;
|
|
|
|
for (auto succ : curRegion->succs_) {
|
2023-05-16 13:37:00 +00:00
|
|
|
if (!succ->IsVisited(linearizer_->acc_)) {
|
|
|
|
succ->SetVisited(linearizer_->acc_);
|
2023-04-21 11:24:24 +00:00
|
|
|
pendingList_.emplace_back(succ);
|
|
|
|
dfsFatherIdx_[succ->id_] = dfsTimestamp_[curRegion->id_];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (size_t idx = 0; idx < dfsList_.size(); idx++) {
|
|
|
|
bbDfsTimestampToIdx_[dfsList_[idx]] = idx;
|
|
|
|
}
|
|
|
|
ASSERT(timestamp == linearizer_->regionList_.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t UnionFind(size_t idx)
|
|
|
|
{
|
|
|
|
size_t pIdx = parentIdx_[idx];
|
|
|
|
if (pIdx == idx) {
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
size_t unionFindSetRoot = UnionFind(pIdx);
|
|
|
|
if (semiDom_[minIdx_[idx]] > semiDom_[minIdx_[pIdx]]) {
|
|
|
|
minIdx_[idx] = minIdx_[pIdx];
|
|
|
|
}
|
|
|
|
return parentIdx_[idx] = unionFindSetRoot;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Merge(size_t fatherIdx, size_t sonIdx)
|
|
|
|
{
|
|
|
|
size_t parentFatherIdx = UnionFind(fatherIdx);
|
|
|
|
size_t parentSonIdx = UnionFind(sonIdx);
|
|
|
|
parentIdx_[parentSonIdx] = parentFatherIdx;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BuildDomTree()
|
|
|
|
{
|
|
|
|
auto ®ionList = linearizer_->regionList_;
|
|
|
|
for (size_t i = 0; i < dfsList_.size(); i++) {
|
|
|
|
ChunkDeque<size_t> sonList(linearizer_->chunk_);
|
|
|
|
semiDomTree_.emplace_back(std::move(sonList));
|
|
|
|
}
|
|
|
|
std::iota(parentIdx_.begin(), parentIdx_.end(), 0);
|
|
|
|
std::iota(semiDom_.begin(), semiDom_.end(), 0);
|
|
|
|
semiDom_[0] = semiDom_.size();
|
|
|
|
|
|
|
|
for (size_t idx = dfsList_.size() - 1; idx >= 1; idx--) {
|
|
|
|
for (const auto &preRegion : regionList[dfsList_[idx]]->preds_) {
|
|
|
|
size_t preRegionIdx = bbDfsTimestampToIdx_[preRegion->id_];
|
|
|
|
if (bbDfsTimestampToIdx_[preRegion->id_] < idx) {
|
|
|
|
semiDom_[idx] = std::min(semiDom_[idx], preRegionIdx);
|
|
|
|
} else {
|
|
|
|
UnionFind(preRegionIdx);
|
|
|
|
semiDom_[idx] = std::min(semiDom_[idx], semiDom_[minIdx_[preRegionIdx]]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (const auto &succDomIdx : semiDomTree_[idx]) {
|
|
|
|
UnionFind(succDomIdx);
|
|
|
|
if (idx == semiDom_[minIdx_[succDomIdx]]) {
|
|
|
|
immDom_[succDomIdx] = idx;
|
|
|
|
} else {
|
|
|
|
immDom_[succDomIdx] = minIdx_[succDomIdx];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
minIdx_[idx] = idx;
|
|
|
|
Merge(dfsFatherIdx_[dfsList_[idx]], idx);
|
|
|
|
semiDomTree_[semiDom_[idx]].emplace_back(idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BuildImmediateDominator()
|
|
|
|
{
|
|
|
|
for (size_t idx = 1; idx < dfsList_.size(); idx++) {
|
|
|
|
if (immDom_[idx] != semiDom_[idx]) {
|
|
|
|
immDom_[idx] = immDom_[immDom_[idx]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
auto entry = linearizer_->regionList_.front();
|
|
|
|
entry->iDominator_ = entry;
|
|
|
|
entry->depth_ = 0;
|
|
|
|
auto ®ionList = linearizer_->regionList_;
|
|
|
|
for (size_t i = 1; i < immDom_.size(); i++) {
|
|
|
|
auto index = dfsList_[i];
|
|
|
|
auto dominatedRegion = regionList[index];
|
|
|
|
auto domIndex = dfsList_[immDom_[i]];
|
|
|
|
auto immDomRegion = regionList[domIndex];
|
2023-05-22 11:27:06 +00:00
|
|
|
immDomRegion->depth_ = static_cast<int32_t>(immDom_[i]);
|
2023-04-21 11:24:24 +00:00
|
|
|
dominatedRegion->iDominator_ = immDomRegion;
|
|
|
|
immDomRegion->dominatedRegions_.emplace_back(dominatedRegion);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BuildImmediateDominatorDepth()
|
|
|
|
{
|
|
|
|
auto entry = linearizer_->regionList_.front();
|
|
|
|
entry->depth_ = 0;
|
|
|
|
|
|
|
|
ASSERT(pendingList_.empty());
|
|
|
|
pendingList_.emplace_back(entry);
|
|
|
|
while (!pendingList_.empty()) {
|
|
|
|
auto curRegion = pendingList_.back();
|
|
|
|
pendingList_.pop_back();
|
|
|
|
|
|
|
|
for (auto succ : curRegion->dominatedRegions_) {
|
|
|
|
ASSERT(succ->iDominator_->depth_ != GateRegion::INVALID_DEPTH);
|
|
|
|
succ->depth_ = succ->iDominator_->depth_ + 1;
|
|
|
|
pendingList_.emplace_back(succ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
GraphLinearizer* linearizer_;
|
|
|
|
ChunkDeque<GateRegion*> pendingList_;
|
|
|
|
ChunkVector<size_t> dfsList_;
|
|
|
|
ChunkVector<size_t> dfsTimestamp_;
|
|
|
|
ChunkVector<size_t> dfsFatherIdx_;
|
|
|
|
ChunkVector<size_t> bbDfsTimestampToIdx_;
|
|
|
|
ChunkVector<size_t> semiDom_;
|
|
|
|
ChunkVector<size_t> immDom_;
|
|
|
|
ChunkVector<size_t> minIdx_;
|
|
|
|
ChunkVector<size_t> parentIdx_;
|
|
|
|
ChunkVector<ChunkDeque<size_t>> semiDomTree_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class GateScheduler {
|
|
|
|
public:
|
|
|
|
explicit GateScheduler(GraphLinearizer *linearizer)
|
|
|
|
: linearizer_(linearizer), fixedGateList_(linearizer->chunk_),
|
2023-05-10 12:44:07 +00:00
|
|
|
pendingList_(linearizer->chunk_), acc_(linearizer->circuit_),
|
2023-06-09 02:13:24 +00:00
|
|
|
scheduleUpperBound_(linearizer_->scheduleUpperBound_) {}
|
2023-04-21 11:24:24 +00:00
|
|
|
|
|
|
|
void InitializeFixedGate()
|
|
|
|
{
|
2023-05-08 07:50:22 +00:00
|
|
|
auto ®ionRoots = linearizer_->regionRootList_;
|
|
|
|
auto size = regionRoots.size();
|
2023-04-21 11:24:24 +00:00
|
|
|
for (size_t i = 0; i < size; i++) {
|
2023-05-08 07:50:22 +00:00
|
|
|
auto fixedGate = regionRoots[i];
|
2023-04-21 11:24:24 +00:00
|
|
|
auto region = linearizer_->GateToRegion(fixedGate);
|
|
|
|
// fixed Gate's output
|
|
|
|
auto uses = acc_.Uses(fixedGate);
|
|
|
|
for (auto it = uses.begin(); it != uses.end(); it++) {
|
|
|
|
GateRef succGate = *it;
|
2023-06-09 02:13:24 +00:00
|
|
|
if (acc_.IsStateIn(it) && acc_.IsFixed(succGate)) {
|
2023-04-21 11:24:24 +00:00
|
|
|
linearizer_->AddFixedGateToRegion(succGate, region);
|
|
|
|
fixedGateList_.emplace_back(succGate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Prepare()
|
|
|
|
{
|
|
|
|
InitializeFixedGate();
|
2023-05-08 07:50:22 +00:00
|
|
|
auto ®ionRoots = linearizer_->regionRootList_;
|
|
|
|
ASSERT(pendingList_.empty());
|
|
|
|
for (const auto rootGate : regionRoots) {
|
2023-04-21 11:24:24 +00:00
|
|
|
pendingList_.emplace_back(rootGate);
|
|
|
|
}
|
|
|
|
while (!pendingList_.empty()) {
|
|
|
|
auto curGate = pendingList_.back();
|
|
|
|
pendingList_.pop_back();
|
|
|
|
auto numIns = acc_.GetNumIns(curGate);
|
|
|
|
for (size_t i = 0; i < numIns; i++) {
|
2023-05-08 07:50:22 +00:00
|
|
|
VisitPreparedGate(Edge(curGate, i));
|
2023-04-21 11:24:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScheduleUpperBound()
|
|
|
|
{
|
2023-05-10 12:44:07 +00:00
|
|
|
if (!scheduleUpperBound_) {
|
|
|
|
return;
|
|
|
|
}
|
2023-05-08 07:50:22 +00:00
|
|
|
auto ®ionRoots = linearizer_->regionRootList_;
|
|
|
|
ASSERT(pendingList_.empty());
|
|
|
|
for (const auto rootGate : regionRoots) {
|
2023-04-21 11:24:24 +00:00
|
|
|
pendingList_.emplace_back(rootGate);
|
|
|
|
}
|
|
|
|
while (!pendingList_.empty()) {
|
|
|
|
auto curGate = pendingList_.back();
|
|
|
|
pendingList_.pop_back();
|
|
|
|
auto uses = acc_.Uses(curGate);
|
|
|
|
for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
|
|
|
|
VisitUpperBoundGate(useIt.GetEdge());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-08 07:50:22 +00:00
|
|
|
void VisitUpperBoundGate(Edge edge)
|
|
|
|
{
|
|
|
|
GateRef succGate = edge.GetGate();
|
2023-05-10 12:44:07 +00:00
|
|
|
auto& succInfo = linearizer_->GetGateInfo(succGate);
|
|
|
|
if (!succInfo.IsSchedulable()) {
|
2023-05-08 07:50:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
ASSERT(succInfo.upperBound != nullptr);
|
|
|
|
auto curGate = acc_.GetIn(succGate, edge.GetIndex());
|
|
|
|
auto curUpperBound = linearizer_->GateToUpperBound(curGate);
|
|
|
|
ASSERT(IsInSameDominatorChain(curUpperBound, succInfo.upperBound));
|
|
|
|
if (curUpperBound->depth_ > succInfo.upperBound->depth_) {
|
|
|
|
succInfo.upperBound = curUpperBound;
|
|
|
|
pendingList_.emplace_back(succGate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-21 11:24:24 +00:00
|
|
|
void ScheduleFloatingGate()
|
|
|
|
{
|
2023-05-08 07:50:22 +00:00
|
|
|
auto ®ionRoots = linearizer_->regionRootList_;
|
|
|
|
for (const auto rootGate : regionRoots) {
|
2023-04-21 11:24:24 +00:00
|
|
|
auto ins = acc_.Ins(rootGate);
|
|
|
|
for (auto it = ins.begin(); it != ins.end(); it++) {
|
|
|
|
pendingList_.emplace_back(*it);
|
|
|
|
while (!pendingList_.empty()) {
|
|
|
|
auto curGate = pendingList_.back();
|
|
|
|
pendingList_.pop_back();
|
|
|
|
VisitScheduleGate(curGate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-08 07:50:22 +00:00
|
|
|
void VisitPreparedGate(Edge edge)
|
2023-04-21 11:24:24 +00:00
|
|
|
{
|
|
|
|
auto curGate = edge.GetGate();
|
|
|
|
auto prevGate = acc_.GetIn(curGate, edge.GetIndex());
|
2023-06-09 02:13:24 +00:00
|
|
|
if (acc_.IsProlog(prevGate) || acc_.IsRoot(prevGate)) {
|
2023-04-21 11:24:24 +00:00
|
|
|
return;
|
|
|
|
}
|
2023-05-10 12:44:07 +00:00
|
|
|
auto& prevInfo = linearizer_->GetGateInfo(prevGate);
|
|
|
|
if (prevInfo.IsNone()) {
|
|
|
|
if (scheduleUpperBound_) {
|
|
|
|
prevInfo.upperBound = linearizer_->GetEntryRegion();
|
|
|
|
}
|
2023-04-21 11:24:24 +00:00
|
|
|
ASSERT(prevInfo.schedulableUseCount == 0);
|
|
|
|
prevInfo.state_ = GraphLinearizer::ScheduleState::SCHEDELABLE;
|
|
|
|
pendingList_.emplace_back(prevGate);
|
|
|
|
}
|
2023-05-10 12:44:07 +00:00
|
|
|
auto& curInfo = linearizer_->GetGateInfo(curGate);
|
2023-06-09 02:13:24 +00:00
|
|
|
if (prevInfo.IsSchedulable() && curInfo.IsSchedulable()) {
|
2023-04-21 11:24:24 +00:00
|
|
|
prevInfo.schedulableUseCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VisitScheduleGate(GateRef curGate)
|
|
|
|
{
|
2023-05-10 12:44:07 +00:00
|
|
|
auto& curInfo = linearizer_->GetGateInfo(curGate);
|
|
|
|
if (!curInfo.IsSchedulable() ||
|
2023-04-21 11:24:24 +00:00
|
|
|
(curInfo.schedulableUseCount != 0) || (curInfo.region != nullptr)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto region = GetCommonDominatorOfAllUses(curGate);
|
2023-05-10 12:44:07 +00:00
|
|
|
if (scheduleUpperBound_) {
|
|
|
|
ASSERT(curInfo.upperBound != nullptr);
|
|
|
|
ASSERT(GetCommonDominator(region, curInfo.upperBound) == curInfo.upperBound);
|
|
|
|
region = curInfo.upperBound;
|
|
|
|
}
|
2023-04-21 11:24:24 +00:00
|
|
|
ScheduleGate(curGate, region);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScheduleGate(GateRef gate, GateRegion* region)
|
|
|
|
{
|
|
|
|
auto ins = acc_.Ins(gate);
|
|
|
|
for (auto it = ins.begin(); it != ins.end(); it++) {
|
|
|
|
auto inputGate = *it;
|
2023-05-10 12:44:07 +00:00
|
|
|
auto& inputInfo = linearizer_->GetGateInfo(inputGate);
|
|
|
|
if (!inputInfo.IsSchedulable()) {
|
2023-04-21 11:24:24 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
inputInfo.schedulableUseCount--;
|
|
|
|
if (inputInfo.schedulableUseCount == 0) {
|
|
|
|
pendingList_.emplace_back(inputGate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ASSERT(!linearizer_->IsScheduled(gate));
|
|
|
|
linearizer_->ScheduleGate(gate, region);
|
|
|
|
}
|
|
|
|
|
|
|
|
GateRegion* GetCommonDominatorOfAllUses(GateRef curGate)
|
|
|
|
{
|
|
|
|
GateRegion* region = nullptr;
|
|
|
|
auto uses = acc_.Uses(curGate);
|
|
|
|
for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
|
|
|
|
GateRef useGate = *useIt;
|
2023-05-10 12:44:07 +00:00
|
|
|
auto& useInfo = linearizer_->GetGateInfo(useGate);
|
|
|
|
if (useInfo.IsNone()) {
|
2023-04-21 11:24:24 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
GateRegion* useRegion = useInfo.region;
|
2023-05-10 12:44:07 +00:00
|
|
|
if (useInfo.IsSelector()) {
|
2023-04-21 11:24:24 +00:00
|
|
|
GateRef state = acc_.GetState(useGate);
|
2023-06-09 02:13:24 +00:00
|
|
|
ASSERT(acc_.IsCFGMerge(state));
|
2023-04-21 11:24:24 +00:00
|
|
|
useGate = acc_.GetIn(state, useIt.GetIndex() - 1); // -1: for state
|
2023-06-09 02:13:24 +00:00
|
|
|
useRegion = linearizer_->FindPredRegion(useGate);
|
|
|
|
} else if (acc_.IsCFGMerge(useGate)) {
|
|
|
|
useGate = acc_.GetIn(useGate, useIt.GetIndex());
|
|
|
|
useRegion = linearizer_->FindPredRegion(useGate);
|
2023-04-21 11:24:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (region == nullptr) {
|
|
|
|
region = useRegion;
|
|
|
|
} else {
|
|
|
|
ASSERT(useRegion != nullptr);
|
|
|
|
region = GetCommonDominator(region, useRegion);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return region;
|
|
|
|
}
|
|
|
|
|
|
|
|
GateRegion* GetCommonDominator(GateRegion* left, GateRegion* right) const
|
|
|
|
{
|
|
|
|
while (left != right) {
|
|
|
|
if (left->depth_ < right->depth_) {
|
|
|
|
right = right->iDominator_;
|
|
|
|
} else {
|
|
|
|
left = left->iDominator_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return left;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsInSameDominatorChain(GateRegion* left, GateRegion* right) const
|
|
|
|
{
|
|
|
|
auto dom = GetCommonDominator(left, right);
|
|
|
|
return left == dom || right == dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScheduleFixedGate()
|
|
|
|
{
|
|
|
|
for (auto gate : fixedGateList_) {
|
|
|
|
GateRegion* region = linearizer_->GateToRegion(gate);
|
|
|
|
linearizer_->ScheduleGate(gate, region);
|
|
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
|
|
Verify();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void Verify()
|
|
|
|
{
|
|
|
|
std::vector<GateRef> gateList;
|
|
|
|
linearizer_->circuit_->GetAllGates(gateList);
|
|
|
|
for (const auto &gate : gateList) {
|
2023-06-09 02:13:24 +00:00
|
|
|
auto& gateInfo = linearizer_->GetGateInfo(gate);
|
|
|
|
if (gateInfo.IsSchedulable()) {
|
2023-04-21 11:24:24 +00:00
|
|
|
ASSERT(linearizer_->IsScheduled(gate));
|
|
|
|
}
|
2023-06-09 02:13:24 +00:00
|
|
|
ASSERT(gateInfo.schedulableUseCount == 0);
|
2023-04-21 11:24:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
GraphLinearizer* linearizer_ {nullptr};
|
|
|
|
ChunkVector<GateRef> fixedGateList_;
|
|
|
|
ChunkDeque<GateRef> pendingList_;
|
|
|
|
GateAccessor acc_;
|
2023-05-10 12:44:07 +00:00
|
|
|
bool scheduleUpperBound_{false};
|
2023-04-21 11:24:24 +00:00
|
|
|
};
|
|
|
|
|
2023-05-10 12:44:07 +00:00
|
|
|
void GraphLinearizer::LinearizeGraph()
|
2023-04-21 11:24:24 +00:00
|
|
|
{
|
|
|
|
gateIdToGateInfo_.resize(circuit_->GetMaxGateId() + 1, GateInfo{nullptr}); // 1: max + 1 = size
|
|
|
|
CFGBuilder builder(this);
|
|
|
|
builder.Run();
|
|
|
|
ImmediateDominatorsGenerator generator(this, chunk_, regionList_.size());
|
|
|
|
generator.Run();
|
|
|
|
GateScheduler scheduler(this);
|
|
|
|
scheduler.Prepare();
|
|
|
|
scheduler.ScheduleUpperBound();
|
|
|
|
scheduler.ScheduleFloatingGate();
|
|
|
|
scheduler.ScheduleFixedGate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphLinearizer::CreateGateRegion(GateRef gate)
|
|
|
|
{
|
|
|
|
ASSERT(GateToRegion(gate) == nullptr);
|
|
|
|
auto region = new (chunk_) GateRegion(chunk_);
|
|
|
|
region->id_ = regionList_.size();
|
|
|
|
regionList_.emplace_back(region);
|
2023-05-10 12:44:07 +00:00
|
|
|
if (acc_.GetOpCode(gate) == OpCode::LOOP_BEGIN) {
|
|
|
|
loopNumber_++;
|
|
|
|
region->stateKind_ = GateRegion::StateKind::LOOP_HEAD;
|
|
|
|
}
|
2023-04-21 11:24:24 +00:00
|
|
|
AddRootGateToRegion(gate, region);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphLinearizer::LinearizeRegions(ControlFlowGraph &result)
|
|
|
|
{
|
2023-05-10 12:44:07 +00:00
|
|
|
ASSERT(result.size() == 0);
|
|
|
|
result.resize(regionList_.size());
|
2023-04-21 11:24:24 +00:00
|
|
|
auto uses = acc_.Uses(acc_.GetArgRoot());
|
|
|
|
for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
|
|
|
|
regionList_.front()->gateList_.emplace_back(*useIt);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < regionList_.size(); i++) {
|
|
|
|
auto region = regionList_[i];
|
|
|
|
auto &gateList = region->gateList_;
|
|
|
|
result[i].insert(result[i].end(), gateList.begin(), gateList.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 02:13:24 +00:00
|
|
|
GateRegion* GraphLinearizer::FindPredRegion(GateRef input)
|
|
|
|
{
|
|
|
|
GateRegion* predRegion = GateToRegion(input);
|
|
|
|
while (predRegion == nullptr) {
|
|
|
|
ASSERT(acc_.GetStateCount(input) == 1); // 1: fall through block
|
|
|
|
input = acc_.GetState(input);
|
|
|
|
predRegion = GateToRegion(input);
|
|
|
|
}
|
|
|
|
ASSERT(predRegion != nullptr);
|
|
|
|
return predRegion;
|
|
|
|
}
|
|
|
|
|
2023-04-21 11:24:24 +00:00
|
|
|
void GraphLinearizer::PrintGraph(const char* title)
|
|
|
|
{
|
|
|
|
LOG_COMPILER(INFO) << "======================== " << title << " ========================";
|
|
|
|
for (size_t i = 0; i < regionList_.size(); i++) {
|
|
|
|
auto bb = regionList_[i];
|
|
|
|
auto front = bb->gateList_.front();
|
|
|
|
auto opcode = acc_.GetOpCode(front);
|
|
|
|
LOG_COMPILER(INFO) << "B" << bb->id_ << ": " << "depth: [" << bb->depth_ << "] "
|
|
|
|
<< opcode << "(" << acc_.GetId(front) << ") "
|
|
|
|
<< "IDom B" << bb->iDominator_->id_;
|
|
|
|
std::string log("\tPreds: ");
|
|
|
|
for (size_t k = 0; k < bb->preds_.size(); ++k) {
|
|
|
|
log += std::to_string(bb->preds_[k]->id_) + ", ";
|
|
|
|
}
|
|
|
|
LOG_COMPILER(INFO) << log;
|
|
|
|
std::string log1("\tSucces: ");
|
|
|
|
for (size_t j = 0; j < bb->succs_.size(); j++) {
|
|
|
|
log1 += std::to_string(bb->succs_[j]->id_) + ", ";
|
|
|
|
}
|
|
|
|
LOG_COMPILER(INFO) << log1;
|
|
|
|
for (auto it = bb->gateList_.crbegin(); it != bb->gateList_.crend(); it++) {
|
|
|
|
acc_.Print(*it);
|
|
|
|
}
|
|
|
|
LOG_COMPILER(INFO) << "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // namespace panda::ecmascript::kungfu
|