14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023 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/combined_pass_visitor.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_ciint32_t CombinedPassVisitor::GetGateOrder(GateRef gate)
214514f5e3Sopenharmony_ci{
224514f5e3Sopenharmony_ci    auto id = acc_.GetId(gate);
234514f5e3Sopenharmony_ci    if (id >= orderList_.size()) {
244514f5e3Sopenharmony_ci        Resize(id + 1, -1);
254514f5e3Sopenharmony_ci    }
264514f5e3Sopenharmony_ci    return orderList_[acc_.GetId(gate)];
274514f5e3Sopenharmony_ci}
284514f5e3Sopenharmony_ci
294514f5e3Sopenharmony_civoid CombinedPassVisitor::SetGateOrder(GateRef gate, int32_t orderId)
304514f5e3Sopenharmony_ci{
314514f5e3Sopenharmony_ci    auto id = acc_.GetId(gate);
324514f5e3Sopenharmony_ci    if (id >= orderList_.size()) {
334514f5e3Sopenharmony_ci        Resize(id + 1, -1);
344514f5e3Sopenharmony_ci    }
354514f5e3Sopenharmony_ci    orderList_[acc_.GetId(gate)] = orderId;
364514f5e3Sopenharmony_ci}
374514f5e3Sopenharmony_ci
384514f5e3Sopenharmony_civoid CombinedPassVisitor::Resize(int32_t size, int32_t num)
394514f5e3Sopenharmony_ci{
404514f5e3Sopenharmony_ci    orderList_.resize(size, num);
414514f5e3Sopenharmony_ci}
424514f5e3Sopenharmony_ci
434514f5e3Sopenharmony_civoid CombinedPassVisitor::AddPass(PassVisitor* pass)
444514f5e3Sopenharmony_ci{
454514f5e3Sopenharmony_ci    passList_.emplace_back(pass);
464514f5e3Sopenharmony_ci}
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_civoid CombinedPassVisitor::LogicallyReplaceGate(GateRef gate, GateRef replacement)
494514f5e3Sopenharmony_ci{
504514f5e3Sopenharmony_ci    auto uses = acc_.Uses(gate);
514514f5e3Sopenharmony_ci    for (auto it = uses.begin(); it != uses.end();) {
524514f5e3Sopenharmony_ci        if (acc_.GetMark(*it) == MarkCode::FINISHED) {
534514f5e3Sopenharmony_ci            PushChangedGate(*it);
544514f5e3Sopenharmony_ci        }
554514f5e3Sopenharmony_ci        it = acc_.ReplaceIn(it, replacement);
564514f5e3Sopenharmony_ci    }
574514f5e3Sopenharmony_ci}
584514f5e3Sopenharmony_civoid CombinedPassVisitor::RelaxStateAndDepend(GateRef gate)
594514f5e3Sopenharmony_ci{
604514f5e3Sopenharmony_ci    ReplaceGate(gate, StateDepend {acc_.GetState(gate), acc_.GetDep(gate)}, gate);
614514f5e3Sopenharmony_ci}
624514f5e3Sopenharmony_ci
634514f5e3Sopenharmony_civoid CombinedPassVisitor::ReplaceGate(GateRef gate, GateRef replacement)
644514f5e3Sopenharmony_ci{
654514f5e3Sopenharmony_ci    GateRef depend = Circuit::NullGate();
664514f5e3Sopenharmony_ci    if (acc_.GetDependCount(gate) > 0) {
674514f5e3Sopenharmony_ci        ASSERT(acc_.GetDependCount(gate) == 1 || acc_.GetOpCode(replacement) == OpCode::DEAD); // 1: one dep
684514f5e3Sopenharmony_ci        depend = acc_.GetDep(gate);
694514f5e3Sopenharmony_ci    }
704514f5e3Sopenharmony_ci    GateRef state = Circuit::NullGate();
714514f5e3Sopenharmony_ci    if (acc_.GetStateCount(gate) > 0) {
724514f5e3Sopenharmony_ci        ASSERT(acc_.GetStateCount(gate) == 1 || acc_.GetOpCode(replacement) == OpCode::DEAD);  // 1: one state
734514f5e3Sopenharmony_ci        state = acc_.GetState(gate);
744514f5e3Sopenharmony_ci    }
754514f5e3Sopenharmony_ci    ReplaceGate(gate, StateDepend {state, depend}, replacement);
764514f5e3Sopenharmony_ci    acc_.DeleteGate(gate);
774514f5e3Sopenharmony_ci}
784514f5e3Sopenharmony_ci
794514f5e3Sopenharmony_civoid CombinedPassVisitor::ReplaceGate(GateRef gate, StateDepend stateDepend, GateRef replacement)
804514f5e3Sopenharmony_ci{
814514f5e3Sopenharmony_ci    auto state = stateDepend.State();
824514f5e3Sopenharmony_ci    auto depend = stateDepend.Depend();
834514f5e3Sopenharmony_ci    auto uses = acc_.Uses(gate);
844514f5e3Sopenharmony_ci    for (auto it = uses.begin(); it != uses.end();) {
854514f5e3Sopenharmony_ci        if (acc_.GetMark(*it) == MarkCode::FINISHED) {
864514f5e3Sopenharmony_ci            PushChangedGate(*it);
874514f5e3Sopenharmony_ci        }
884514f5e3Sopenharmony_ci        if (acc_.GetOpCode(replacement) == OpCode::DEAD) {
894514f5e3Sopenharmony_ci            it = acc_.ReplaceIn(it, replacement);
904514f5e3Sopenharmony_ci        } else if (acc_.IsStateIn(it)) {
914514f5e3Sopenharmony_ci            ASSERT(state != Circuit::NullGate());
924514f5e3Sopenharmony_ci            it = acc_.ReplaceIn(it, state);
934514f5e3Sopenharmony_ci        } else if (acc_.IsDependIn(it)) {
944514f5e3Sopenharmony_ci            ASSERT(depend != Circuit::NullGate());
954514f5e3Sopenharmony_ci            it = acc_.ReplaceIn(it, depend);
964514f5e3Sopenharmony_ci        } else {
974514f5e3Sopenharmony_ci            it = acc_.ReplaceIn(it, replacement);
984514f5e3Sopenharmony_ci        }
994514f5e3Sopenharmony_ci    }
1004514f5e3Sopenharmony_ci#ifndef NDEBUG
1014514f5e3Sopenharmony_ci    acc_.GetCircuit()->AddComment(replacement,  "old V " + std::to_string(acc_.GetId(gate)));
1024514f5e3Sopenharmony_ci#endif
1034514f5e3Sopenharmony_ci}
1044514f5e3Sopenharmony_ci
1054514f5e3Sopenharmony_civoid CombinedPassVisitor::VistDependSelectorForLoop(GateRef gate)
1064514f5e3Sopenharmony_ci{
1074514f5e3Sopenharmony_ci    auto use = acc_.Uses(gate);
1084514f5e3Sopenharmony_ci    for (auto useIt = use.begin(); useIt != use.end(); useIt++) {
1094514f5e3Sopenharmony_ci        if (acc_.GetOpCode(*useIt) == OpCode::DEPEND_SELECTOR) {
1104514f5e3Sopenharmony_ci            PushChangedGate(*useIt);
1114514f5e3Sopenharmony_ci        }
1124514f5e3Sopenharmony_ci    }
1134514f5e3Sopenharmony_ci}
1144514f5e3Sopenharmony_ci
1154514f5e3Sopenharmony_civoid CombinedPassVisitor::VisitGraph()
1164514f5e3Sopenharmony_ci{
1174514f5e3Sopenharmony_ci    for (auto pass : passList_) {
1184514f5e3Sopenharmony_ci        pass->Initialize();
1194514f5e3Sopenharmony_ci    }
1204514f5e3Sopenharmony_ci    circuit_->AdvanceTime();
1214514f5e3Sopenharmony_ci    orderCount_ = 0;
1224514f5e3Sopenharmony_ci    Resize(circuit_->GetMaxGateId() + 1, -1);
1234514f5e3Sopenharmony_ci    std::vector<GateRef> gateList;
1244514f5e3Sopenharmony_ci    circuit_->GetAllGates(gateList);
1254514f5e3Sopenharmony_ci    for (auto gate : gateList) {
1264514f5e3Sopenharmony_ci        if (acc_.GetOpCode(gate) == OpCode::LOOP_BEGIN) {
1274514f5e3Sopenharmony_ci            PushChangedGate(gate);
1284514f5e3Sopenharmony_ci            // For empty loop and no RETURN opcode
1294514f5e3Sopenharmony_ci            VistDependSelectorForLoop(gate);
1304514f5e3Sopenharmony_ci        }
1314514f5e3Sopenharmony_ci    }
1324514f5e3Sopenharmony_ci    // Visit gate needing to start from RETURN, otherwise it may lead to incomplete early elimination in some scenarios.
1334514f5e3Sopenharmony_ci    GateRef returnList = acc_.GetReturnRoot();
1344514f5e3Sopenharmony_ci    auto uses = acc_.Uses(returnList);
1354514f5e3Sopenharmony_ci    for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
1364514f5e3Sopenharmony_ci        PushChangedGate(*useIt);
1374514f5e3Sopenharmony_ci    }
1384514f5e3Sopenharmony_ci
1394514f5e3Sopenharmony_ci    while (true) {
1404514f5e3Sopenharmony_ci        if (!workList_.empty()) {
1414514f5e3Sopenharmony_ci            Edge& current = workList_.back();
1424514f5e3Sopenharmony_ci            VisitTopGate(current);
1434514f5e3Sopenharmony_ci        } else if (!changedList_.empty()) {
1444514f5e3Sopenharmony_ci            GateRef gate = changedList_.back();
1454514f5e3Sopenharmony_ci            changedList_.pop_back();
1464514f5e3Sopenharmony_ci            if (acc_.GetMark(gate) == MarkCode::PREVISIT) {
1474514f5e3Sopenharmony_ci                PushGate(gate, 0);
1484514f5e3Sopenharmony_ci            }
1494514f5e3Sopenharmony_ci        } else {
1504514f5e3Sopenharmony_ci            for (auto pass : passList_) {
1514514f5e3Sopenharmony_ci                pass->Finalize();
1524514f5e3Sopenharmony_ci            }
1534514f5e3Sopenharmony_ci            break;
1544514f5e3Sopenharmony_ci        }
1554514f5e3Sopenharmony_ci    }
1564514f5e3Sopenharmony_ci}
1574514f5e3Sopenharmony_ci
1584514f5e3Sopenharmony_civoid CombinedPassVisitor::ReVisitGate(GateRef gate)
1594514f5e3Sopenharmony_ci{
1604514f5e3Sopenharmony_ci    if (acc_.GetMark(gate) == MarkCode::FINISHED) {
1614514f5e3Sopenharmony_ci        PushChangedGate(gate);
1624514f5e3Sopenharmony_ci    }
1634514f5e3Sopenharmony_ci}
1644514f5e3Sopenharmony_ci
1654514f5e3Sopenharmony_ci
1664514f5e3Sopenharmony_ciGateRef CombinedPassVisitor::VisitGate(GateRef gate)
1674514f5e3Sopenharmony_ci{
1684514f5e3Sopenharmony_ci    [[maybe_unused]] auto scopedGate = circuit_->VisitGateBegin(gate);
1694514f5e3Sopenharmony_ci    auto skip = passList_.end();
1704514f5e3Sopenharmony_ci    for (auto i = passList_.begin(); i != passList_.end();) {
1714514f5e3Sopenharmony_ci        if (i == skip) {
1724514f5e3Sopenharmony_ci            i++;
1734514f5e3Sopenharmony_ci            continue;
1744514f5e3Sopenharmony_ci        }
1754514f5e3Sopenharmony_ci        GateRef replacement = (*i)->VisitGate(gate);
1764514f5e3Sopenharmony_ci        if (replacement == gate) {
1774514f5e3Sopenharmony_ci            skip = i;
1784514f5e3Sopenharmony_ci            i = passList_.begin();
1794514f5e3Sopenharmony_ci            continue;
1804514f5e3Sopenharmony_ci        } else if (replacement != Circuit::NullGate()) {
1814514f5e3Sopenharmony_ci            return replacement;
1824514f5e3Sopenharmony_ci        }
1834514f5e3Sopenharmony_ci        i++;
1844514f5e3Sopenharmony_ci    }
1854514f5e3Sopenharmony_ci    if (skip == passList_.end()) {
1864514f5e3Sopenharmony_ci        return Circuit::NullGate();
1874514f5e3Sopenharmony_ci    }
1884514f5e3Sopenharmony_ci    return gate;
1894514f5e3Sopenharmony_ci}
1904514f5e3Sopenharmony_ci// Reverse post-order
1914514f5e3Sopenharmony_civoid CombinedPassVisitor::VisitTopGate(Edge& current)
1924514f5e3Sopenharmony_ci{
1934514f5e3Sopenharmony_ci    GateRef gate = current.GetGate();
1944514f5e3Sopenharmony_ci    // gate is delete or dead
1954514f5e3Sopenharmony_ci    if (acc_.IsNop(gate)) {
1964514f5e3Sopenharmony_ci        PopGate(gate);
1974514f5e3Sopenharmony_ci        return;
1984514f5e3Sopenharmony_ci    }
1994514f5e3Sopenharmony_ci    auto numIns = acc_.GetNumIns(gate);
2004514f5e3Sopenharmony_ci    auto start = current.GetIndex();
2014514f5e3Sopenharmony_ci    if (start >= numIns) {
2024514f5e3Sopenharmony_ci        start = 0;
2034514f5e3Sopenharmony_ci    }
2044514f5e3Sopenharmony_ci    for (size_t i = start; i < numIns; i++) {
2054514f5e3Sopenharmony_ci        GateRef input = acc_.GetIn(gate, i);
2064514f5e3Sopenharmony_ci        if (input == gate) {
2074514f5e3Sopenharmony_ci            continue;
2084514f5e3Sopenharmony_ci        }
2094514f5e3Sopenharmony_ci        // find not visited gate, push stack
2104514f5e3Sopenharmony_ci        if (acc_.GetMark(input) < MarkCode::VISITED) {
2114514f5e3Sopenharmony_ci            PushGate(input, 0);
2124514f5e3Sopenharmony_ci            // next index
2134514f5e3Sopenharmony_ci            current.SetIndex(i + 1);
2144514f5e3Sopenharmony_ci            return;
2154514f5e3Sopenharmony_ci        }
2164514f5e3Sopenharmony_ci    }
2174514f5e3Sopenharmony_ci    for (size_t i = 0; i < start; i++) {
2184514f5e3Sopenharmony_ci        GateRef input = acc_.GetIn(gate, i);
2194514f5e3Sopenharmony_ci        if (input == gate) {
2204514f5e3Sopenharmony_ci            continue;
2214514f5e3Sopenharmony_ci        }
2224514f5e3Sopenharmony_ci        // find not visited gate, push stack
2234514f5e3Sopenharmony_ci        if (acc_.GetMark(input) < MarkCode::VISITED) {
2244514f5e3Sopenharmony_ci            PushGate(input, 0);
2254514f5e3Sopenharmony_ci            // next index
2264514f5e3Sopenharmony_ci            current.SetIndex(i + 1);
2274514f5e3Sopenharmony_ci            return;
2284514f5e3Sopenharmony_ci        }
2294514f5e3Sopenharmony_ci    }
2304514f5e3Sopenharmony_ci    // all input are visited
2314514f5e3Sopenharmony_ci    if (GetGateOrder(gate) == -1) { // -1 : not visited before
2324514f5e3Sopenharmony_ci        SetGateOrder(gate, ++orderCount_);
2334514f5e3Sopenharmony_ci    }
2344514f5e3Sopenharmony_ci    GateRef replacement = VisitGate(gate);
2354514f5e3Sopenharmony_ci    PopGate(gate);
2364514f5e3Sopenharmony_ci    if (replacement == Circuit::NullGate()) {
2374514f5e3Sopenharmony_ci        return;
2384514f5e3Sopenharmony_ci    }
2394514f5e3Sopenharmony_ci    if (replacement != gate) {
2404514f5e3Sopenharmony_ci        ReplaceGate(gate, replacement);
2414514f5e3Sopenharmony_ci    } else {
2424514f5e3Sopenharmony_ci        // revisit not on stack gate.
2434514f5e3Sopenharmony_ci        auto uses = acc_.Uses(gate);
2444514f5e3Sopenharmony_ci        for (auto it = uses.begin(); it != uses.end(); it++) {
2454514f5e3Sopenharmony_ci            if (acc_.GetMark(*it) == MarkCode::FINISHED) {
2464514f5e3Sopenharmony_ci                PushChangedGate(*it);
2474514f5e3Sopenharmony_ci            }
2484514f5e3Sopenharmony_ci        }
2494514f5e3Sopenharmony_ci    }
2504514f5e3Sopenharmony_ci}
2514514f5e3Sopenharmony_ci
2524514f5e3Sopenharmony_civoid CombinedPassVisitor::PrintStack()
2534514f5e3Sopenharmony_ci{
2544514f5e3Sopenharmony_ci    std::string log;
2554514f5e3Sopenharmony_ci    for (size_t i = 0; i < workList_.size(); i++) {
2564514f5e3Sopenharmony_ci        Edge current = workList_[i];
2574514f5e3Sopenharmony_ci        GateRef gate = current.GetGate();
2584514f5e3Sopenharmony_ci        log += std::to_string(acc_.GetId(gate)) + ", ";
2594514f5e3Sopenharmony_ci    }
2604514f5e3Sopenharmony_ci    LOG_COMPILER(INFO) << std::dec << log;
2614514f5e3Sopenharmony_ci}
2624514f5e3Sopenharmony_ci
2634514f5e3Sopenharmony_civoid CombinedPassVisitor::PrintLog(const std::string& phaseName)
2644514f5e3Sopenharmony_ci{
2654514f5e3Sopenharmony_ci    if (enableLog_) {
2664514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "";
2674514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "\033[34m"
2684514f5e3Sopenharmony_ci                        << "===================="
2694514f5e3Sopenharmony_ci                        << " After " << phaseName << " "
2704514f5e3Sopenharmony_ci                        << "[" << methodName_ << "]"
2714514f5e3Sopenharmony_ci                        << "===================="
2724514f5e3Sopenharmony_ci                        << "\033[0m";
2734514f5e3Sopenharmony_ci        circuit_->PrintAllGatesWithBytecode();
2744514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
2754514f5e3Sopenharmony_ci    }
2764514f5e3Sopenharmony_ci}
2774514f5e3Sopenharmony_ci
2784514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu
279