1/*
2 * Copyright (c) 2024 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/useless_gate_elimination.h"
17
18namespace panda::ecmascript::kungfu {
19
20void UselessGateElimination::PushGate(GateRef gate)
21{
22    workList_.push_back(gate);
23    acc_.SetMark(gate, MarkCode::VISITED);
24}
25
26void UselessGateElimination::InitList()
27{
28    circuit_->AdvanceTime();
29    GateRef returnList = acc_.GetReturnRoot();
30    auto uses = acc_.Uses(returnList);
31    for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
32        PushGate(*useIt);
33    }
34    circuit_->GetAllGates(gateList_);
35    for (auto gate : gateList_) {
36        if (acc_.GetOpCode(gate) == OpCode::LOOP_BEGIN) {
37            PushGate(gate);
38        } else if (acc_.IsProlog(gate) || acc_.IsRoot(gate)) {
39            acc_.SetMark(gate, MarkCode::VISITED);
40        }
41    }
42}
43
44void UselessGateElimination::MarkGate()
45{
46    while (!workList_.empty()) {
47        GateRef gate = workList_.back();
48        workList_.pop_back();
49        std::vector<GateRef> ins;
50        acc_.GetIns(gate, ins);
51        for (auto in : ins) {
52            if (acc_.GetMark(in) != MarkCode::VISITED) {
53                PushGate(in);
54            }
55        }
56    }
57}
58
59void UselessGateElimination::ReplaceDead(GateRef gate)
60{
61    auto uses = acc_.Uses(gate);
62    for (auto it = uses.begin(); it != uses.end();) {
63        it = acc_.ReplaceIn(it, circuit_->DeadGate());
64    }
65    acc_.DeleteGate(gate);
66}
67
68void UselessGateElimination::EliminateUnmarkedGate()
69{
70    for (auto gate : gateList_) {
71        if (acc_.GetMark(gate) != MarkCode::VISITED) {
72            ReplaceDead(gate);
73        }
74    }
75}
76
77std::string UselessGateElimination::GetMethodName()
78{
79    return methodName_;
80}
81
82void UselessGateElimination::Run()
83{
84    InitList();
85    MarkGate();
86    EliminateUnmarkedGate();
87    if (enableLog_) {
88        LOG_COMPILER(INFO) << "";
89        LOG_COMPILER(INFO) << "\033[34m"
90                           << "===================="
91                           << " After Useless Gate Elimination "
92                           << "[" << GetMethodName() << "]"
93                           << "===================="
94                           << "\033[0m";
95        circuit_->PrintAllGatesWithBytecode();
96        LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
97    }
98}
99
100}