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