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 26namespace panda::compiler { 27class Graph; 28class Pass; 29class Analysis; 30class LivenessAnalyzer; 31class LoopAnalyzer; 32class DominatorsTree; 33class Rpo; 34class LinearOrder; 35// NOLINTNEXTLINE(fuchsia-multiple-inheritance) 36 37namespace details { 38template <typename... Types> 39class PassTypeList { 40public: 41 using IdentifierType = size_t; 42 using TupleType = std::tuple<std::decay_t<Types>...>; 43 44 template <typename T> 45 static constexpr bool HasType() 46 { 47 return std::disjunction_v<std::is_same<T, Types>...>; 48 } 49 50 template <typename T, typename... 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> 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 72using PredefinedAnalyses = 73 PassTypeList<LivenessAnalyzer, LoopAnalyzer, DominatorsTree, Rpo, LinearOrder>; 74} // namespace details 75 76class PassManager { 77public: 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> 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> 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 118 Graph *GetGraph() 119 { 120 return graph_; 121 } 122 123 void Finalize() const; 124 125 PassManagerStatistics *GetStatistics() 126 { 127 return stats_; 128 } 129 130 void SetCheckMode(bool v) 131 { 132 check_mode_ = v; 133 } 134 135 bool IsCheckMode() const 136 { 137 return check_mode_; 138 } 139 140 // NOLINTNEXTLINE(readability-convert-member-functions-to-static) 141 size_t GetExecutionCounter() const 142 { 143 return execution_counter; 144 } 145 146 // NOLINTNEXTLINE(readability-convert-member-functions-to-static) 147 void StartExecution() 148 { 149 execution_counter++; 150 } 151 152private: 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