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