• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef COMPILER_OPTIMIZER_PASS_MANAGER_H
17 #define COMPILER_OPTIMIZER_PASS_MANAGER_H
18 
19 #include <tuple>
20 #include "compiler_options.h"
21 #include "pass.h"
22 #include "utils/bit_field.h"
23 #include "utils/arena_containers.h"
24 #include "pass_manager_statistics.h"
25 
26 namespace panda::compiler {
27 class Graph;
28 class Pass;
29 class Analysis;
30 class LivenessAnalyzer;
31 class LoopAnalyzer;
32 class DominatorsTree;
33 class Rpo;
34 class LinearOrder;
35 // NOLINTNEXTLINE(fuchsia-multiple-inheritance)
36 
37 namespace details {
38 template <typename... Types>
39 class PassTypeList {
40 public:
41     using IdentifierType = size_t;
42     using TupleType = std::tuple<std::decay_t<Types>...>;
43 
44     template <typename T>
HasType()45     static constexpr bool HasType()
46     {
47         return std::disjunction_v<std::is_same<T, Types>...>;
48     }
49 
50     template <typename T, typename... Args>
Instantiate(ArenaAllocator * allocator,Args &&...args)51     static ArenaVector<T> Instantiate(ArenaAllocator *allocator, Args &&... args)
52     {
53         ArenaVector<T> vec(allocator->Adapter());
54         vec.reserve(sizeof...(Types));
55         ((vec.push_back(allocator->New<Types>((std::forward<Args>(args))...))), ...);
56         return vec;
57     }
58 
59     template <typename Type, std::size_t... Indexes>
GetIndex(std::index_sequence<Indexes...>)60     static constexpr size_t GetIndex(std::index_sequence<Indexes... /* unused */>)
61     {
62         static_assert(HasType<Type>());
63         return (0 + ... +
64                 (std::is_same_v<Type, std::tuple_element_t<Indexes, TupleType>> ? size_t(Indexes) : size_t {}));
65     }
66 
67     template <typename Type>
68     static constexpr IdentifierType ID = GetIndex<std::decay_t<Type>>(std::index_sequence_for<Types...> {});
69     static constexpr size_t SIZE = sizeof...(Types);
70 };
71 
72 using PredefinedAnalyses =
73     PassTypeList<LivenessAnalyzer, LoopAnalyzer, DominatorsTree, Rpo, LinearOrder>;
74 }  // namespace details
75 
76 class PassManager {
77 public:
78     PassManager(Graph *graph, PassManager *parent_pm);
79 
80     ArenaAllocator *GetAllocator();
81     ArenaAllocator *GetLocalAllocator();
82 
83     bool RunPass(Pass *pass, size_t local_mem_size_before_pass);
84 
85     template <typename T, typename... Args>
RunPass(Args...args)86     bool RunPass(Args... args)
87     {
88         auto local_mem_size_before = GetLocalAllocator()->GetAllocatedSize();
89         bool res = false;
90         // NOLINTNEXTLINE(readability-braces-around-statements)
91         if constexpr (details::PredefinedAnalyses::HasType<T>()) {
92             static_assert(sizeof...(Args) == 0);
93             res = RunPass(ANALYSES[details::PredefinedAnalyses::ID<T>], local_mem_size_before);
94             // NOLINTNEXTLINE(readability-misleading-indentation)
95         } else {
96             T pass(graph_, std::forward<Args>(args)...);
97             res = RunPass(&pass, local_mem_size_before);
98         }
99         if (!IsCheckMode()) {
100             if (options.IsCompilerResetLocalAllocator()) {
101                 ASSERT(GetLocalAllocator() != GetAllocator());
102                 GetLocalAllocator()->Resize(local_mem_size_before);
103             }
104         }
105         return res;
106     }
107 
108     template <typename T>
GetAnalysis()109     T &GetAnalysis()
110     {
111         static_assert(std::is_base_of_v<Analysis, std::decay_t<T>>);
112         return *static_cast<T *>(ANALYSES[details::PredefinedAnalyses::ID<T>]);
113     }
114     std::string GetFileName(const char *pass_name = nullptr, const std::string &suffix = ".cfg");
115     void DumpGraph(const char *pass_name);
116     void DumpLifeIntervals(const char *pass_name);
117 
GetGraph()118     Graph *GetGraph()
119     {
120         return graph_;
121     }
122 
123     void Finalize() const;
124 
GetStatistics()125     PassManagerStatistics *GetStatistics()
126     {
127         return stats_;
128     }
129 
SetCheckMode(bool v)130     void SetCheckMode(bool v)
131     {
132         check_mode_ = v;
133     }
134 
IsCheckMode()135     bool IsCheckMode() const
136     {
137         return check_mode_;
138     }
139 
140     // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
GetExecutionCounter()141     size_t GetExecutionCounter() const
142     {
143         return execution_counter;
144     }
145 
146     // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
StartExecution()147     void StartExecution()
148     {
149         execution_counter++;
150     }
151 
152 private:
153     Graph *graph_ {nullptr};
154     ArenaVector<Optimization *> optimizations_;
155     const ArenaVector<Analysis *> ANALYSES;
156 
157     PassManagerStatistics *stats_ {nullptr};
158     inline static size_t execution_counter {0};
159 
160     // Whether passes are run by checker.
161     bool check_mode_ {false};
162 
163     bool first_execution_ {true};
164 };
165 }  // namespace panda::compiler
166 
167 #endif  // COMPILER_OPTIMIZER_PASS_MANAGER_H
168