1/**
2 * Copyright (c) 2021-2022 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 "optimizer/ir/basicblock.h"
17#include "optimizer/ir/graph.h"
18#include "rpo.h"
19
20namespace panda::compiler {
21Rpo::Rpo(Graph *graph) : Analysis(graph), rpo_vector_(graph->GetAllocator()->Adapter()) {}
22
23/**
24 *  Depth-first search
25 * `blocks_count` needs for filling `rpo_vector_` in reverse order
26 */
27void Rpo::DFS(BasicBlock *block, size_t *blocks_count)
28{
29    ASSERT(block != nullptr);
30    block->SetMarker(marker_);
31
32    for (auto succ_block : block->GetSuccsBlocks()) {
33        if (!succ_block->IsMarked(marker_)) {
34            DFS(succ_block, blocks_count);
35        }
36    }
37
38    ASSERT(blocks_count != nullptr && *blocks_count > 0);
39    rpo_vector_[--(*blocks_count)] = block;
40}
41
42bool Rpo::RunImpl()
43{
44    size_t blocks_count = GetGraph()->GetAliveBlocksCount();
45    rpo_vector_.resize(blocks_count);
46    if (blocks_count == 0) {
47        return true;
48    }
49    marker_ = GetGraph()->NewMarker();
50    ASSERT_PRINT(marker_ != UNDEF_MARKER, "There are no free markers. Please erase unused markers");
51    DFS(GetGraph()->GetStartBlock(), &blocks_count);
52#ifndef NDEBUG
53    if (blocks_count != 0) {
54        std::cerr << "There are unreachable blocks:\n";
55        for (auto bb : *GetGraph()) {
56            if (bb != nullptr && !bb->IsMarked(marker_)) {
57                bb->Dump(&std::cerr);
58            }
59        }
60        UNREACHABLE();
61    }
62#endif  // NDEBUG
63    GetGraph()->EraseMarker(marker_);
64    return true;
65}
66}  // namespace panda::compiler
67