/** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef COMPILER_OPTIMIZER_PASS_MANAGER_H #define COMPILER_OPTIMIZER_PASS_MANAGER_H #include #include "compiler_options.h" #include "pass.h" #include "utils/bit_field.h" #include "utils/arena_containers.h" #include "pass_manager_statistics.h" namespace panda::compiler { class Graph; class Pass; class Analysis; class LivenessAnalyzer; class LoopAnalyzer; class DominatorsTree; class Rpo; class LinearOrder; // NOLINTNEXTLINE(fuchsia-multiple-inheritance) namespace details { template class PassTypeList { public: using IdentifierType = size_t; using TupleType = std::tuple...>; template static constexpr bool HasType() { return std::disjunction_v...>; } template static ArenaVector Instantiate(ArenaAllocator *allocator, Args &&... args) { ArenaVector vec(allocator->Adapter()); vec.reserve(sizeof...(Types)); ((vec.push_back(allocator->New((std::forward(args))...))), ...); return vec; } template static constexpr size_t GetIndex(std::index_sequence) { static_assert(HasType()); return (0 + ... + (std::is_same_v> ? size_t(Indexes) : size_t {})); } template static constexpr IdentifierType ID = GetIndex>(std::index_sequence_for {}); static constexpr size_t SIZE = sizeof...(Types); }; using PredefinedAnalyses = PassTypeList; } // namespace details class PassManager { public: PassManager(Graph *graph, PassManager *parent_pm); ArenaAllocator *GetAllocator(); ArenaAllocator *GetLocalAllocator(); bool RunPass(Pass *pass, size_t local_mem_size_before_pass); template bool RunPass(Args... args) { auto local_mem_size_before = GetLocalAllocator()->GetAllocatedSize(); bool res = false; // NOLINTNEXTLINE(readability-braces-around-statements) if constexpr (details::PredefinedAnalyses::HasType()) { static_assert(sizeof...(Args) == 0); res = RunPass(ANALYSES[details::PredefinedAnalyses::ID], local_mem_size_before); // NOLINTNEXTLINE(readability-misleading-indentation) } else { T pass(graph_, std::forward(args)...); res = RunPass(&pass, local_mem_size_before); } if (!IsCheckMode()) { if (options.IsCompilerResetLocalAllocator()) { ASSERT(GetLocalAllocator() != GetAllocator()); GetLocalAllocator()->Resize(local_mem_size_before); } } return res; } template T &GetAnalysis() { static_assert(std::is_base_of_v>); return *static_cast(ANALYSES[details::PredefinedAnalyses::ID]); } std::string GetFileName(const char *pass_name = nullptr, const std::string &suffix = ".cfg"); void DumpGraph(const char *pass_name); void DumpLifeIntervals(const char *pass_name); Graph *GetGraph() { return graph_; } void Finalize() const; PassManagerStatistics *GetStatistics() { return stats_; } void SetCheckMode(bool v) { check_mode_ = v; } bool IsCheckMode() const { return check_mode_; } // NOLINTNEXTLINE(readability-convert-member-functions-to-static) size_t GetExecutionCounter() const { return execution_counter; } // NOLINTNEXTLINE(readability-convert-member-functions-to-static) void StartExecution() { execution_counter++; } private: Graph *graph_ {nullptr}; ArenaVector optimizations_; const ArenaVector ANALYSES; PassManagerStatistics *stats_ {nullptr}; inline static size_t execution_counter {0}; // Whether passes are run by checker. bool check_mode_ {false}; bool first_execution_ {true}; }; } // namespace panda::compiler #endif // COMPILER_OPTIMIZER_PASS_MANAGER_H