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