14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/compiler/scheduler.h" 174514f5e3Sopenharmony_ci#include <cmath> 184514f5e3Sopenharmony_ci#include <stack> 194514f5e3Sopenharmony_ci#include "ecmascript/compiler/gate_accessor.h" 204514f5e3Sopenharmony_ci#include "ecmascript/compiler/verifier.h" 214514f5e3Sopenharmony_ci 224514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu { 234514f5e3Sopenharmony_cisize_t UnionFind(std::vector<size_t> &semiDom, std::vector<size_t> &parent, std::vector<size_t> &minIdx, size_t idx) 244514f5e3Sopenharmony_ci{ 254514f5e3Sopenharmony_ci std::stack<size_t> allIdxs; 264514f5e3Sopenharmony_ci allIdxs.emplace(idx); 274514f5e3Sopenharmony_ci size_t pIdx = parent[idx]; 284514f5e3Sopenharmony_ci while (pIdx != allIdxs.top()) { 294514f5e3Sopenharmony_ci allIdxs.emplace(pIdx); 304514f5e3Sopenharmony_ci pIdx = parent[pIdx]; 314514f5e3Sopenharmony_ci } 324514f5e3Sopenharmony_ci size_t unionFindSetRoot = pIdx; 334514f5e3Sopenharmony_ci while (!allIdxs.empty()) { 344514f5e3Sopenharmony_ci if (semiDom[minIdx[allIdxs.top()]] > semiDom[minIdx[pIdx]]) { 354514f5e3Sopenharmony_ci minIdx[allIdxs.top()] = minIdx[pIdx]; 364514f5e3Sopenharmony_ci } 374514f5e3Sopenharmony_ci parent[allIdxs.top()] = unionFindSetRoot; 384514f5e3Sopenharmony_ci pIdx = allIdxs.top(); 394514f5e3Sopenharmony_ci allIdxs.pop(); 404514f5e3Sopenharmony_ci } 414514f5e3Sopenharmony_ci return unionFindSetRoot; 424514f5e3Sopenharmony_ci} 434514f5e3Sopenharmony_ci 444514f5e3Sopenharmony_civoid Scheduler::CalculateDominatorTree(const Circuit *circuit, 454514f5e3Sopenharmony_ci std::vector<GateRef>& bbGatesList, 464514f5e3Sopenharmony_ci std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx, 474514f5e3Sopenharmony_ci std::vector<size_t> &immDom) 484514f5e3Sopenharmony_ci{ 494514f5e3Sopenharmony_ci GateAccessor acc(const_cast<Circuit*>(circuit)); 504514f5e3Sopenharmony_ci std::unordered_map<GateRef, size_t> dfsTimestamp; 514514f5e3Sopenharmony_ci std::unordered_map<GateRef, size_t> dfsFatherIdx; 524514f5e3Sopenharmony_ci circuit->AdvanceTime(); 534514f5e3Sopenharmony_ci { 544514f5e3Sopenharmony_ci size_t timestamp = 0; 554514f5e3Sopenharmony_ci std::deque<GateRef> pendingList; 564514f5e3Sopenharmony_ci auto startGate = acc.GetStateRoot(); 574514f5e3Sopenharmony_ci acc.SetMark(startGate, MarkCode::VISITED); 584514f5e3Sopenharmony_ci pendingList.push_back(startGate); 594514f5e3Sopenharmony_ci while (!pendingList.empty()) { 604514f5e3Sopenharmony_ci auto curGate = pendingList.back(); 614514f5e3Sopenharmony_ci dfsTimestamp[curGate] = timestamp++; 624514f5e3Sopenharmony_ci pendingList.pop_back(); 634514f5e3Sopenharmony_ci bbGatesList.push_back(curGate); 644514f5e3Sopenharmony_ci if (acc.GetOpCode(curGate) != OpCode::LOOP_BACK) { 654514f5e3Sopenharmony_ci auto uses = acc.Uses(curGate); 664514f5e3Sopenharmony_ci for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) { 674514f5e3Sopenharmony_ci if (useIt.GetIndex() < acc.GetStateCount(*useIt) && 684514f5e3Sopenharmony_ci acc.IsState(*useIt) && acc.GetMark(*useIt) == MarkCode::NO_MARK) { 694514f5e3Sopenharmony_ci acc.SetMark(*useIt, MarkCode::VISITED); 704514f5e3Sopenharmony_ci pendingList.push_back(*useIt); 714514f5e3Sopenharmony_ci dfsFatherIdx[*useIt] = dfsTimestamp[curGate]; 724514f5e3Sopenharmony_ci } 734514f5e3Sopenharmony_ci } 744514f5e3Sopenharmony_ci } 754514f5e3Sopenharmony_ci } 764514f5e3Sopenharmony_ci for (size_t idx = 0; idx < bbGatesList.size(); idx++) { 774514f5e3Sopenharmony_ci bbGatesAddrToIdx[bbGatesList[idx]] = idx; 784514f5e3Sopenharmony_ci } 794514f5e3Sopenharmony_ci } 804514f5e3Sopenharmony_ci immDom.resize(bbGatesList.size()); 814514f5e3Sopenharmony_ci std::vector<size_t> semiDom(bbGatesList.size()); 824514f5e3Sopenharmony_ci std::vector<std::vector<size_t> > semiDomTree(bbGatesList.size()); 834514f5e3Sopenharmony_ci { 844514f5e3Sopenharmony_ci std::vector<size_t> parent(bbGatesList.size()); 854514f5e3Sopenharmony_ci std::iota(parent.begin(), parent.end(), 0); 864514f5e3Sopenharmony_ci std::vector<size_t> minIdx(bbGatesList.size()); 874514f5e3Sopenharmony_ci auto merge = [&] (size_t fatherIdx, size_t sonIdx) -> void { 884514f5e3Sopenharmony_ci size_t parentFatherIdx = UnionFind(semiDom, parent, minIdx, fatherIdx); 894514f5e3Sopenharmony_ci size_t parentSonIdx = UnionFind(semiDom, parent, minIdx, sonIdx); 904514f5e3Sopenharmony_ci parent[parentSonIdx] = parentFatherIdx; 914514f5e3Sopenharmony_ci }; 924514f5e3Sopenharmony_ci std::iota(semiDom.begin(), semiDom.end(), 0); 934514f5e3Sopenharmony_ci semiDom[0] = semiDom.size(); 944514f5e3Sopenharmony_ci ASSERT(bbGatesList.size() > 0); 954514f5e3Sopenharmony_ci for (size_t idx = bbGatesList.size() - 1; idx >= 1; idx--) { 964514f5e3Sopenharmony_ci std::vector<GateRef> preGates; 974514f5e3Sopenharmony_ci acc.GetInStates(bbGatesList[idx], preGates); 984514f5e3Sopenharmony_ci for (const auto &predGate : preGates) { 994514f5e3Sopenharmony_ci if (bbGatesAddrToIdx.count(predGate) > 0) { 1004514f5e3Sopenharmony_ci size_t preGateIdx = bbGatesAddrToIdx[predGate]; 1014514f5e3Sopenharmony_ci if (preGateIdx < idx) { 1024514f5e3Sopenharmony_ci semiDom[idx] = std::min(semiDom[idx], preGateIdx); 1034514f5e3Sopenharmony_ci } else { 1044514f5e3Sopenharmony_ci UnionFind(semiDom, parent, minIdx, preGateIdx); 1054514f5e3Sopenharmony_ci semiDom[idx] = std::min(semiDom[idx], semiDom[minIdx[preGateIdx]]); 1064514f5e3Sopenharmony_ci } 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci } 1094514f5e3Sopenharmony_ci for (const auto &succDomIdx : semiDomTree[idx]) { 1104514f5e3Sopenharmony_ci UnionFind(semiDom, parent, minIdx, succDomIdx); 1114514f5e3Sopenharmony_ci if (idx == semiDom[minIdx[succDomIdx]]) { 1124514f5e3Sopenharmony_ci immDom[succDomIdx] = idx; 1134514f5e3Sopenharmony_ci } else { 1144514f5e3Sopenharmony_ci immDom[succDomIdx] = minIdx[succDomIdx]; 1154514f5e3Sopenharmony_ci } 1164514f5e3Sopenharmony_ci } 1174514f5e3Sopenharmony_ci minIdx[idx] = idx; 1184514f5e3Sopenharmony_ci merge(dfsFatherIdx[bbGatesList[idx]], idx); 1194514f5e3Sopenharmony_ci semiDomTree[semiDom[idx]].push_back(idx); 1204514f5e3Sopenharmony_ci } 1214514f5e3Sopenharmony_ci for (size_t idx = 1; idx < bbGatesList.size(); idx++) { 1224514f5e3Sopenharmony_ci if (immDom[idx] != semiDom[idx]) { 1234514f5e3Sopenharmony_ci immDom[idx] = immDom[immDom[idx]]; 1244514f5e3Sopenharmony_ci } 1254514f5e3Sopenharmony_ci } 1264514f5e3Sopenharmony_ci semiDom[0] = 0; 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci} 1294514f5e3Sopenharmony_ci 1304514f5e3Sopenharmony_civoid Scheduler::Run(const Circuit *circuit, ControlFlowGraph &result, 1314514f5e3Sopenharmony_ci [[maybe_unused]] const std::string& methodName, [[maybe_unused]] bool enableLog) 1324514f5e3Sopenharmony_ci{ 1334514f5e3Sopenharmony_ci GateAccessor acc(const_cast<Circuit*>(circuit)); 1344514f5e3Sopenharmony_ci std::vector<GateRef> bbGatesList; 1354514f5e3Sopenharmony_ci std::unordered_map<GateRef, size_t> bbGatesAddrToIdx; 1364514f5e3Sopenharmony_ci std::vector<size_t> immDom; 1374514f5e3Sopenharmony_ci Scheduler::CalculateDominatorTree(circuit, bbGatesList, bbGatesAddrToIdx, immDom); 1384514f5e3Sopenharmony_ci ASSERT(result.size() == 0); 1394514f5e3Sopenharmony_ci result.resize(bbGatesList.size()); 1404514f5e3Sopenharmony_ci for (size_t idx = 0; idx < bbGatesList.size(); idx++) { 1414514f5e3Sopenharmony_ci result[idx].push_back(bbGatesList[idx]); 1424514f5e3Sopenharmony_ci } 1434514f5e3Sopenharmony_ci // assuming CFG is always reducible 1444514f5e3Sopenharmony_ci std::vector<std::vector<size_t>> sonList(result.size()); 1454514f5e3Sopenharmony_ci for (size_t idx = 1; idx < immDom.size(); idx++) { 1464514f5e3Sopenharmony_ci sonList[immDom[idx]].push_back(idx); 1474514f5e3Sopenharmony_ci } 1484514f5e3Sopenharmony_ci const size_t sizeLog = std::ceil(std::log2(static_cast<double>(result.size())) + 1); 1494514f5e3Sopenharmony_ci std::vector<size_t> timeIn(result.size()); 1504514f5e3Sopenharmony_ci std::vector<size_t> timeOut(result.size()); 1514514f5e3Sopenharmony_ci std::vector<std::vector<size_t>> jumpUp; 1524514f5e3Sopenharmony_ci jumpUp.assign(result.size(), std::vector<size_t>(sizeLog + 1)); 1534514f5e3Sopenharmony_ci { 1544514f5e3Sopenharmony_ci size_t timestamp = 0; 1554514f5e3Sopenharmony_ci struct DFSState { 1564514f5e3Sopenharmony_ci size_t cur; 1574514f5e3Sopenharmony_ci std::vector<size_t> &succList; 1584514f5e3Sopenharmony_ci size_t idx; 1594514f5e3Sopenharmony_ci }; 1604514f5e3Sopenharmony_ci std::stack<DFSState> dfsStack; 1614514f5e3Sopenharmony_ci size_t root = 0; 1624514f5e3Sopenharmony_ci dfsStack.push({root, sonList[root], 0}); 1634514f5e3Sopenharmony_ci timeIn[root] = timestamp++; 1644514f5e3Sopenharmony_ci jumpUp[root][0] = root; 1654514f5e3Sopenharmony_ci for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) { 1664514f5e3Sopenharmony_ci auto jumpUpHalf = jumpUp[root][stepSize - 1]; 1674514f5e3Sopenharmony_ci jumpUp[root][stepSize] = jumpUp[jumpUpHalf][stepSize - 1]; 1684514f5e3Sopenharmony_ci } 1694514f5e3Sopenharmony_ci while (!dfsStack.empty()) { 1704514f5e3Sopenharmony_ci auto &curState = dfsStack.top(); 1714514f5e3Sopenharmony_ci auto &cur = curState.cur; 1724514f5e3Sopenharmony_ci auto &succList = curState.succList; 1734514f5e3Sopenharmony_ci auto &idx = curState.idx; 1744514f5e3Sopenharmony_ci if (idx == succList.size()) { 1754514f5e3Sopenharmony_ci timeOut[cur] = timestamp++; 1764514f5e3Sopenharmony_ci dfsStack.pop(); 1774514f5e3Sopenharmony_ci continue; 1784514f5e3Sopenharmony_ci } 1794514f5e3Sopenharmony_ci const auto &succ = succList[idx]; 1804514f5e3Sopenharmony_ci dfsStack.push({succ, sonList[succ], 0}); 1814514f5e3Sopenharmony_ci timeIn[succ] = timestamp++; 1824514f5e3Sopenharmony_ci jumpUp[succ][0] = cur; 1834514f5e3Sopenharmony_ci for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) { 1844514f5e3Sopenharmony_ci auto jumpUpHalf = jumpUp[succ][stepSize - 1]; 1854514f5e3Sopenharmony_ci jumpUp[succ][stepSize] = jumpUp[jumpUpHalf][stepSize - 1]; 1864514f5e3Sopenharmony_ci } 1874514f5e3Sopenharmony_ci idx++; 1884514f5e3Sopenharmony_ci } 1894514f5e3Sopenharmony_ci } 1904514f5e3Sopenharmony_ci auto isAncestor = [&](size_t nodeA, size_t nodeB) -> bool { 1914514f5e3Sopenharmony_ci return (timeIn[nodeA] <= timeIn[nodeB]) && (timeOut[nodeA] >= timeOut[nodeB]); 1924514f5e3Sopenharmony_ci }; 1934514f5e3Sopenharmony_ci auto lowestCommonAncestor = [&](size_t nodeA, size_t nodeB) -> size_t { 1944514f5e3Sopenharmony_ci if (isAncestor(nodeA, nodeB)) { 1954514f5e3Sopenharmony_ci return nodeA; 1964514f5e3Sopenharmony_ci } 1974514f5e3Sopenharmony_ci if (isAncestor(nodeB, nodeA)) { 1984514f5e3Sopenharmony_ci return nodeB; 1994514f5e3Sopenharmony_ci } 2004514f5e3Sopenharmony_ci for (size_t stepSize = sizeLog + 1; stepSize > 0; stepSize--) { 2014514f5e3Sopenharmony_ci if (!isAncestor(jumpUp[nodeA][stepSize - 1], nodeB)) { 2024514f5e3Sopenharmony_ci nodeA = jumpUp[nodeA][stepSize - 1]; 2034514f5e3Sopenharmony_ci } 2044514f5e3Sopenharmony_ci } 2054514f5e3Sopenharmony_ci return jumpUp[nodeA][0]; 2064514f5e3Sopenharmony_ci }; 2074514f5e3Sopenharmony_ci { 2084514f5e3Sopenharmony_ci std::vector<GateRef> order; 2094514f5e3Sopenharmony_ci std::unordered_map<GateRef, size_t> lowerBound; 2104514f5e3Sopenharmony_ci Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, lowerBound, &order); 2114514f5e3Sopenharmony_ci for (const auto &schedulableGate : order) { 2124514f5e3Sopenharmony_ci result[lowerBound.at(schedulableGate)].push_back(schedulableGate); 2134514f5e3Sopenharmony_ci } 2144514f5e3Sopenharmony_ci std::vector<GateRef> argList; 2154514f5e3Sopenharmony_ci acc.GetOuts(acc.GetArgRoot(), argList); 2164514f5e3Sopenharmony_ci std::sort(argList.begin(), argList.end(), [&](const GateRef &lhs, const GateRef &rhs) -> bool { 2174514f5e3Sopenharmony_ci return acc.TryGetValue(lhs) > acc.TryGetValue(rhs); 2184514f5e3Sopenharmony_ci }); 2194514f5e3Sopenharmony_ci for (const auto &arg : argList) { 2204514f5e3Sopenharmony_ci result.front().push_back(arg); 2214514f5e3Sopenharmony_ci } 2224514f5e3Sopenharmony_ci for (const auto &bbGate : bbGatesList) { 2234514f5e3Sopenharmony_ci auto uses = acc.Uses(bbGate); 2244514f5e3Sopenharmony_ci for (auto i = uses.begin(); i != uses.end(); i++) { 2254514f5e3Sopenharmony_ci GateRef succGate = *i; 2264514f5e3Sopenharmony_ci if (acc.IsFixed(succGate)) { 2274514f5e3Sopenharmony_ci result[bbGatesAddrToIdx.at(acc.GetIn(succGate, 0))].push_back(succGate); 2284514f5e3Sopenharmony_ci } 2294514f5e3Sopenharmony_ci } 2304514f5e3Sopenharmony_ci } 2314514f5e3Sopenharmony_ci } 2324514f5e3Sopenharmony_ci if (enableLog) { 2334514f5e3Sopenharmony_ci Print(&result, circuit); 2344514f5e3Sopenharmony_ci } 2354514f5e3Sopenharmony_ci} 2364514f5e3Sopenharmony_ci 2374514f5e3Sopenharmony_cibool Scheduler::CalculateSchedulingUpperBound(const Circuit *circuit, 2384514f5e3Sopenharmony_ci const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx, 2394514f5e3Sopenharmony_ci const std::function<bool(size_t, size_t)> &isAncestor, 2404514f5e3Sopenharmony_ci const std::vector<GateRef> &schedulableGatesList, 2414514f5e3Sopenharmony_ci std::unordered_map<GateRef, size_t> &upperBound) 2424514f5e3Sopenharmony_ci{ 2434514f5e3Sopenharmony_ci GateAccessor acc(const_cast<Circuit*>(circuit)); 2444514f5e3Sopenharmony_ci struct DFSState { 2454514f5e3Sopenharmony_ci GateRef curGate = Circuit::NullGate(); 2464514f5e3Sopenharmony_ci std::vector<GateRef> predGates; 2474514f5e3Sopenharmony_ci size_t idx = 0; 2484514f5e3Sopenharmony_ci size_t curUpperBound = 0; 2494514f5e3Sopenharmony_ci }; 2504514f5e3Sopenharmony_ci DFSState emptyState = {Circuit::NullGate(), std::vector<GateRef>(0), 0, 0}; 2514514f5e3Sopenharmony_ci bool getReturn = false; 2524514f5e3Sopenharmony_ci std::optional<size_t> returnValue = 0; 2534514f5e3Sopenharmony_ci std::stack<DFSState> dfsStack; 2544514f5e3Sopenharmony_ci auto CheckUnschedulable = [&](GateRef gate) -> void { 2554514f5e3Sopenharmony_ci if (upperBound.count(gate) > 0) { 2564514f5e3Sopenharmony_ci returnValue = upperBound[gate]; 2574514f5e3Sopenharmony_ci getReturn = true; 2584514f5e3Sopenharmony_ci } else if (acc.IsProlog(gate) || acc.IsRoot(gate) || acc.IsVirtualState(gate)) { 2594514f5e3Sopenharmony_ci returnValue = 0; 2604514f5e3Sopenharmony_ci getReturn = true; 2614514f5e3Sopenharmony_ci } else if (acc.IsFixed(gate)) { 2624514f5e3Sopenharmony_ci returnValue = bbGatesAddrToIdx.at(acc.GetIn(gate, 0)); 2634514f5e3Sopenharmony_ci getReturn = true; 2644514f5e3Sopenharmony_ci } else if (acc.IsState(gate)) { 2654514f5e3Sopenharmony_ci returnValue = bbGatesAddrToIdx.at(gate); 2664514f5e3Sopenharmony_ci getReturn = true; 2674514f5e3Sopenharmony_ci } 2684514f5e3Sopenharmony_ci // then gate is schedulable 2694514f5e3Sopenharmony_ci }; 2704514f5e3Sopenharmony_ci for (const auto &schedulableGate : schedulableGatesList) { 2714514f5e3Sopenharmony_ci if (upperBound.count(schedulableGate) != 0) { 2724514f5e3Sopenharmony_ci continue; 2734514f5e3Sopenharmony_ci } 2744514f5e3Sopenharmony_ci getReturn = false; 2754514f5e3Sopenharmony_ci CheckUnschedulable(schedulableGate); 2764514f5e3Sopenharmony_ci if (getReturn) { 2774514f5e3Sopenharmony_ci continue; 2784514f5e3Sopenharmony_ci } 2794514f5e3Sopenharmony_ci dfsStack.push(emptyState); 2804514f5e3Sopenharmony_ci auto &rootState = dfsStack.top(); 2814514f5e3Sopenharmony_ci auto &rootPredGates = rootState.predGates; 2824514f5e3Sopenharmony_ci rootState.curGate = schedulableGate; 2834514f5e3Sopenharmony_ci acc.GetIns(schedulableGate, rootPredGates); 2844514f5e3Sopenharmony_ci while (!dfsStack.empty()) { 2854514f5e3Sopenharmony_ci auto &curState = dfsStack.top(); 2864514f5e3Sopenharmony_ci auto &curGate = curState.curGate; 2874514f5e3Sopenharmony_ci const auto &predGates = curState.predGates; 2884514f5e3Sopenharmony_ci auto &idx = curState.idx; 2894514f5e3Sopenharmony_ci auto &curUpperBound = curState.curUpperBound; 2904514f5e3Sopenharmony_ci if (idx == predGates.size()) { 2914514f5e3Sopenharmony_ci upperBound[curGate] = curUpperBound; 2924514f5e3Sopenharmony_ci returnValue = curUpperBound; 2934514f5e3Sopenharmony_ci dfsStack.pop(); 2944514f5e3Sopenharmony_ci getReturn = true; 2954514f5e3Sopenharmony_ci continue; 2964514f5e3Sopenharmony_ci } 2974514f5e3Sopenharmony_ci if (getReturn) { 2984514f5e3Sopenharmony_ci if (!returnValue.has_value()) { 2994514f5e3Sopenharmony_ci break; 3004514f5e3Sopenharmony_ci } 3014514f5e3Sopenharmony_ci auto predUpperBound = returnValue.value(); 3024514f5e3Sopenharmony_ci if (!isAncestor(curUpperBound, predUpperBound) && !isAncestor(predUpperBound, curUpperBound)) { 3034514f5e3Sopenharmony_ci PrintUpperBoundError(circuit, curGate, predUpperBound, curUpperBound); 3044514f5e3Sopenharmony_ci returnValue = std::nullopt; 3054514f5e3Sopenharmony_ci break; 3064514f5e3Sopenharmony_ci } 3074514f5e3Sopenharmony_ci if (isAncestor(curUpperBound, predUpperBound)) { 3084514f5e3Sopenharmony_ci curUpperBound = predUpperBound; 3094514f5e3Sopenharmony_ci } 3104514f5e3Sopenharmony_ci getReturn = false; 3114514f5e3Sopenharmony_ci idx++; 3124514f5e3Sopenharmony_ci } else { 3134514f5e3Sopenharmony_ci const auto &predGate = predGates[idx]; 3144514f5e3Sopenharmony_ci CheckUnschedulable(predGate); 3154514f5e3Sopenharmony_ci if (getReturn) { 3164514f5e3Sopenharmony_ci continue; 3174514f5e3Sopenharmony_ci } 3184514f5e3Sopenharmony_ci dfsStack.push(emptyState); 3194514f5e3Sopenharmony_ci auto &newState = dfsStack.top(); 3204514f5e3Sopenharmony_ci auto &newPredGates = newState.predGates; 3214514f5e3Sopenharmony_ci newState.curGate = predGate; 3224514f5e3Sopenharmony_ci acc.GetIns(predGate, newPredGates); 3234514f5e3Sopenharmony_ci } 3244514f5e3Sopenharmony_ci } 3254514f5e3Sopenharmony_ci if (!returnValue.has_value()) { 3264514f5e3Sopenharmony_ci return false; 3274514f5e3Sopenharmony_ci } 3284514f5e3Sopenharmony_ci } 3294514f5e3Sopenharmony_ci return true; 3304514f5e3Sopenharmony_ci} 3314514f5e3Sopenharmony_ci 3324514f5e3Sopenharmony_civoid Scheduler::PrintUpperBoundError(const Circuit *circuit, GateRef curGate, 3334514f5e3Sopenharmony_ci GateRef predUpperBound, GateRef curUpperBound) 3344514f5e3Sopenharmony_ci{ 3354514f5e3Sopenharmony_ci GateAccessor ac(const_cast<Circuit*>(circuit)); 3364514f5e3Sopenharmony_ci LOG_COMPILER(ERROR) << "[Verifier][Error] Scheduling upper bound of gate (id=" 3374514f5e3Sopenharmony_ci << ac.GetId(curGate) 3384514f5e3Sopenharmony_ci << ") does not exist, current-upper-bound = " 3394514f5e3Sopenharmony_ci << curUpperBound << ", pred-upper-bound = " 3404514f5e3Sopenharmony_ci << predUpperBound << ", there is no dominator relationship between them."; 3414514f5e3Sopenharmony_ci} 3424514f5e3Sopenharmony_ci 3434514f5e3Sopenharmony_civoid Scheduler::CalculateFixedGatesList(const Circuit *circuit, 3444514f5e3Sopenharmony_ci const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx, 3454514f5e3Sopenharmony_ci std::vector<GateRef> &bbAndFixedGatesList) 3464514f5e3Sopenharmony_ci{ 3474514f5e3Sopenharmony_ci GateAccessor acc(const_cast<Circuit*>(circuit)); 3484514f5e3Sopenharmony_ci for (const auto &item : bbGatesAddrToIdx) { 3494514f5e3Sopenharmony_ci bbAndFixedGatesList.push_back(item.first); 3504514f5e3Sopenharmony_ci auto uses = acc.Uses(item.first); 3514514f5e3Sopenharmony_ci for (auto i = uses.begin(); i != uses.end(); i++) { 3524514f5e3Sopenharmony_ci GateRef succGate = *i; 3534514f5e3Sopenharmony_ci if (acc.IsFixed(succGate)) { 3544514f5e3Sopenharmony_ci bbAndFixedGatesList.push_back(succGate); 3554514f5e3Sopenharmony_ci } 3564514f5e3Sopenharmony_ci } 3574514f5e3Sopenharmony_ci } 3584514f5e3Sopenharmony_ci} 3594514f5e3Sopenharmony_ci 3604514f5e3Sopenharmony_civoid Scheduler::CalculateSchedulingLowerBound(const Circuit *circuit, 3614514f5e3Sopenharmony_ci const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx, 3624514f5e3Sopenharmony_ci const std::function<size_t(size_t, size_t)> &lowestCommonAncestor, 3634514f5e3Sopenharmony_ci std::unordered_map<GateRef, size_t> &lowerBound, 3644514f5e3Sopenharmony_ci std::vector<GateRef> *order) 3654514f5e3Sopenharmony_ci{ 3664514f5e3Sopenharmony_ci GateAccessor acc(const_cast<Circuit*>(circuit)); 3674514f5e3Sopenharmony_ci std::vector<GateRef> bbAndFixedGatesList; 3684514f5e3Sopenharmony_ci CalculateFixedGatesList(circuit, bbGatesAddrToIdx, bbAndFixedGatesList); 3694514f5e3Sopenharmony_ci std::unordered_map<GateRef, size_t> useCount; 3704514f5e3Sopenharmony_ci struct DFSVisitState { 3714514f5e3Sopenharmony_ci std::vector<GateRef> prevGates; 3724514f5e3Sopenharmony_ci size_t idx = 0; 3734514f5e3Sopenharmony_ci }; 3744514f5e3Sopenharmony_ci DFSVisitState emptyVisitState = {std::vector<GateRef>(0), 0}; 3754514f5e3Sopenharmony_ci std::stack<DFSVisitState> dfsVisitStack; 3764514f5e3Sopenharmony_ci for (const auto &gate : bbAndFixedGatesList) { 3774514f5e3Sopenharmony_ci dfsVisitStack.push(emptyVisitState); 3784514f5e3Sopenharmony_ci auto &rootState = dfsVisitStack.top(); 3794514f5e3Sopenharmony_ci auto &rootPrevGates = rootState.prevGates; 3804514f5e3Sopenharmony_ci acc.GetIns(gate, rootPrevGates); 3814514f5e3Sopenharmony_ci while (!dfsVisitStack.empty()) { 3824514f5e3Sopenharmony_ci auto &curState = dfsVisitStack.top(); 3834514f5e3Sopenharmony_ci auto &prevGates = curState.prevGates; 3844514f5e3Sopenharmony_ci auto &idx = curState.idx; 3854514f5e3Sopenharmony_ci if (idx == prevGates.size()) { 3864514f5e3Sopenharmony_ci dfsVisitStack.pop(); 3874514f5e3Sopenharmony_ci continue; 3884514f5e3Sopenharmony_ci } 3894514f5e3Sopenharmony_ci const auto &prevGate = prevGates[idx]; 3904514f5e3Sopenharmony_ci if (!acc.IsSchedulable(prevGate)) { 3914514f5e3Sopenharmony_ci ++idx; 3924514f5e3Sopenharmony_ci continue; 3934514f5e3Sopenharmony_ci } 3944514f5e3Sopenharmony_ci useCount[prevGate]++; 3954514f5e3Sopenharmony_ci if (useCount[prevGate] == 1) { 3964514f5e3Sopenharmony_ci dfsVisitStack.push(emptyVisitState); 3974514f5e3Sopenharmony_ci auto &newState = dfsVisitStack.top(); 3984514f5e3Sopenharmony_ci auto &newPrevGates = newState.prevGates; 3994514f5e3Sopenharmony_ci acc.GetIns(prevGate, newPrevGates); 4004514f5e3Sopenharmony_ci } 4014514f5e3Sopenharmony_ci ++idx; 4024514f5e3Sopenharmony_ci } 4034514f5e3Sopenharmony_ci } 4044514f5e3Sopenharmony_ci struct DFSFinishState { 4054514f5e3Sopenharmony_ci GateRef curGate = Circuit::NullGate(); 4064514f5e3Sopenharmony_ci std::vector<GateRef> prevGates; 4074514f5e3Sopenharmony_ci size_t idx = 0; 4084514f5e3Sopenharmony_ci }; 4094514f5e3Sopenharmony_ci DFSFinishState emptyFinishState = {Circuit::NullGate(), std::vector<GateRef>(0), 0}; 4104514f5e3Sopenharmony_ci std::stack<DFSFinishState> dfsFinishStack; 4114514f5e3Sopenharmony_ci for (const auto &gate : bbAndFixedGatesList) { 4124514f5e3Sopenharmony_ci dfsFinishStack.push(emptyFinishState); 4134514f5e3Sopenharmony_ci auto &rootState = dfsFinishStack.top(); 4144514f5e3Sopenharmony_ci auto &rootPrevGates = rootState.prevGates; 4154514f5e3Sopenharmony_ci rootState.curGate = gate; 4164514f5e3Sopenharmony_ci acc.GetIns(gate, rootPrevGates); 4174514f5e3Sopenharmony_ci while (!dfsFinishStack.empty()) { 4184514f5e3Sopenharmony_ci auto &curState = dfsFinishStack.top(); 4194514f5e3Sopenharmony_ci auto &curGate = curState.curGate; 4204514f5e3Sopenharmony_ci auto &prevGates = curState.prevGates; 4214514f5e3Sopenharmony_ci auto &idx = curState.idx; 4224514f5e3Sopenharmony_ci if (idx == prevGates.size()) { 4234514f5e3Sopenharmony_ci dfsFinishStack.pop(); 4244514f5e3Sopenharmony_ci continue; 4254514f5e3Sopenharmony_ci } 4264514f5e3Sopenharmony_ci const auto &prevGate = prevGates[idx]; 4274514f5e3Sopenharmony_ci if (!acc.IsSchedulable(prevGate)) { 4284514f5e3Sopenharmony_ci ++idx; 4294514f5e3Sopenharmony_ci continue; 4304514f5e3Sopenharmony_ci } 4314514f5e3Sopenharmony_ci useCount[prevGate]--; 4324514f5e3Sopenharmony_ci size_t curLowerBound; 4334514f5e3Sopenharmony_ci if (acc.IsState(curGate)) { // cur_opcode would not be STATE_ENTRY 4344514f5e3Sopenharmony_ci curLowerBound = bbGatesAddrToIdx.at(curGate); 4354514f5e3Sopenharmony_ci } else if (acc.IsSelector(curGate)) { 4364514f5e3Sopenharmony_ci ASSERT(idx > 0); 4374514f5e3Sopenharmony_ci curLowerBound = bbGatesAddrToIdx.at(acc.GetIn(acc.GetIn(curGate, 0), idx - 1)); 4384514f5e3Sopenharmony_ci } else if (acc.IsFixed(curGate)) { 4394514f5e3Sopenharmony_ci ASSERT(idx > 0); 4404514f5e3Sopenharmony_ci curLowerBound = bbGatesAddrToIdx.at(acc.GetIn(curGate, 0)); 4414514f5e3Sopenharmony_ci } else { 4424514f5e3Sopenharmony_ci curLowerBound = lowerBound.at(curGate); 4434514f5e3Sopenharmony_ci } 4444514f5e3Sopenharmony_ci if (lowerBound.count(prevGate) == 0) { 4454514f5e3Sopenharmony_ci lowerBound[prevGate] = curLowerBound; 4464514f5e3Sopenharmony_ci } else { 4474514f5e3Sopenharmony_ci lowerBound[prevGate] = lowestCommonAncestor(lowerBound[prevGate], curLowerBound); 4484514f5e3Sopenharmony_ci } 4494514f5e3Sopenharmony_ci if (useCount[prevGate] == 0) { 4504514f5e3Sopenharmony_ci if (order != nullptr) { 4514514f5e3Sopenharmony_ci order->push_back(prevGate); 4524514f5e3Sopenharmony_ci } 4534514f5e3Sopenharmony_ci dfsFinishStack.push(emptyFinishState); 4544514f5e3Sopenharmony_ci auto &newState = dfsFinishStack.top(); 4554514f5e3Sopenharmony_ci auto &newPrevGates = newState.prevGates; 4564514f5e3Sopenharmony_ci newState.curGate = prevGate; 4574514f5e3Sopenharmony_ci acc.GetIns(prevGate, newPrevGates); 4584514f5e3Sopenharmony_ci } 4594514f5e3Sopenharmony_ci ++idx; 4604514f5e3Sopenharmony_ci } 4614514f5e3Sopenharmony_ci } 4624514f5e3Sopenharmony_ci} 4634514f5e3Sopenharmony_ci 4644514f5e3Sopenharmony_civoid Scheduler::Print(const std::vector<std::vector<GateRef>> *cfg, const Circuit *circuit) 4654514f5e3Sopenharmony_ci{ 4664514f5e3Sopenharmony_ci GateAccessor acc(const_cast<Circuit*>(circuit)); 4674514f5e3Sopenharmony_ci std::vector<GateRef> bbGatesList; 4684514f5e3Sopenharmony_ci std::unordered_map<GateRef, size_t> bbGatesAddrToIdx; 4694514f5e3Sopenharmony_ci std::vector<size_t> immDom; 4704514f5e3Sopenharmony_ci Scheduler::CalculateDominatorTree(circuit, bbGatesList, bbGatesAddrToIdx, immDom); 4714514f5e3Sopenharmony_ci LOG_COMPILER(INFO) << "==================================== Scheduling =================================="; 4724514f5e3Sopenharmony_ci for (size_t bbIdx = 0; bbIdx < cfg->size(); bbIdx++) { 4734514f5e3Sopenharmony_ci auto opcode = acc.GetOpCode((*cfg)[bbIdx].front()); 4744514f5e3Sopenharmony_ci LOG_COMPILER(INFO) << "B" << bbIdx << "_" << opcode << ":" 4754514f5e3Sopenharmony_ci << " immDom=" << immDom[bbIdx]; 4764514f5e3Sopenharmony_ci LOG_COMPILER(INFO) << " pred=["; 4774514f5e3Sopenharmony_ci bool isFirst = true; 4784514f5e3Sopenharmony_ci GateRef head = cfg->at(bbIdx).front(); 4794514f5e3Sopenharmony_ci auto ins = acc.Ins(head); 4804514f5e3Sopenharmony_ci for (auto i = ins.begin(); i != ins.end(); i++) { 4814514f5e3Sopenharmony_ci GateRef predState = *i; 4824514f5e3Sopenharmony_ci if (acc.IsState(predState) || 4834514f5e3Sopenharmony_ci acc.GetOpCode(predState) == OpCode::STATE_ENTRY) { 4844514f5e3Sopenharmony_ci LOG_COMPILER(INFO) << (isFirst ? "" : " ") << bbGatesAddrToIdx.at(predState); 4854514f5e3Sopenharmony_ci isFirst = false; 4864514f5e3Sopenharmony_ci } 4874514f5e3Sopenharmony_ci } 4884514f5e3Sopenharmony_ci LOG_COMPILER(INFO) << "] succ=["; 4894514f5e3Sopenharmony_ci isFirst = true; 4904514f5e3Sopenharmony_ci GateRef h = cfg->at(bbIdx).front(); 4914514f5e3Sopenharmony_ci auto uses = acc.Uses(h); 4924514f5e3Sopenharmony_ci for (auto i = uses.begin(); i != uses.end(); i++) { 4934514f5e3Sopenharmony_ci GateRef succState = *i; 4944514f5e3Sopenharmony_ci if (acc.IsState(succState) || 4954514f5e3Sopenharmony_ci acc.GetOpCode(succState) == OpCode::STATE_ENTRY) { 4964514f5e3Sopenharmony_ci LOG_COMPILER(INFO) << (isFirst ? "" : " ") << bbGatesAddrToIdx.at(succState); 4974514f5e3Sopenharmony_ci isFirst = false; 4984514f5e3Sopenharmony_ci } 4994514f5e3Sopenharmony_ci } 5004514f5e3Sopenharmony_ci LOG_COMPILER(INFO) << "]"; 5014514f5e3Sopenharmony_ci for (size_t instIdx = (*cfg)[bbIdx].size(); instIdx > 0; instIdx--) { 5024514f5e3Sopenharmony_ci acc.Print((*cfg)[bbIdx][instIdx - 1]); 5034514f5e3Sopenharmony_ci } 5044514f5e3Sopenharmony_ci } 5054514f5e3Sopenharmony_ci LOG_COMPILER(INFO) << "==================================== Scheduling =================================="; 5064514f5e3Sopenharmony_ci} 5074514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu 508