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#include "trace/trace.h" 17#include "pass_manager.h" 18#include "optimizer/ir/graph_checker.h" 19#include "optimizer/analysis/dominators_tree.h" 20#include "optimizer/analysis/linear_order.h" 21#include "optimizer/analysis/liveness_analyzer.h" 22#include "optimizer/analysis/loop_analyzer.h" 23#include "optimizer/analysis/rpo.h" 24#include "optimizer/optimizations/cleanup.h" 25 26// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 27#define ENABLE_IR_DUMP 28 29namespace panda::compiler { 30PassManager::PassManager(Graph *graph, PassManager *parent_pm) 31 : graph_(graph), 32 optimizations_(graph->GetAllocator()->Adapter()), 33 ANALYSES(details::PredefinedAnalyses::Instantiate<Analysis *>(graph_->GetAllocator(), graph_)), 34 stats_((parent_pm == nullptr) ? graph->GetAllocator()->New<PassManagerStatistics>(graph) 35 : parent_pm->GetStatistics()) 36{ 37} 38 39#if defined(ENABLE_IR_DUMP) && !defined(PANDA_TARGET_MACOS) 40static std::string ClearFileName(std::string str, std::string_view suffix) 41{ 42 std::string delimiters = "~`@#$%^&*()-+=\\|/\"<>;,.[]"; 43 for (const char &c : delimiters) { 44 std::replace(str.begin(), str.end(), c, '_'); 45 } 46 return str.substr(0, NAME_MAX - suffix.size()); 47} 48#endif // ENABLE_IR_DUMP && !PANDA_TARGET_MACOS 49 50std::string PassManager::GetFileName([[maybe_unused]] const char *pass_name, [[maybe_unused]] const std::string &suffix) 51{ 52#if defined(ENABLE_IR_DUMP) && !defined(PANDA_TARGET_MACOS) 53 std::stringstream ss_filename; 54 std::stringstream ss_fullpath; 55 ASSERT(GetGraph()->GetRuntime() != nullptr); 56 57 std::string folder_name(options.GetCompilerDumpFolder()); 58 59 os::CreateDirectories(folder_name); 60 constexpr auto IMM_3 = 3; 61 constexpr auto IMM_4 = 4; 62 ss_filename << std::setw(IMM_3) << std::setfill('0') << execution_counter << "_"; 63 if (pass_name != nullptr) { 64 ss_filename << "pass_" << std::setw(IMM_4) << std::setfill('0') << stats_->GetCurrentPassIndex() << "_"; 65 } 66 if (GetGraph()->GetParentGraph() != nullptr) { 67 ss_filename << "inlined_"; 68 } 69 ss_filename << GetGraph()->GetRuntime()->GetClassNameFromMethod(GetGraph()->GetMethod()) << "_" 70 << GetGraph()->GetRuntime()->GetMethodName(GetGraph()->GetMethod()); 71 if (GetGraph()->IsOsrMode()) { 72 ss_filename << "_OSR"; 73 } 74 if (pass_name != nullptr) { 75 ss_filename << "_" << pass_name; 76 } 77 ss_fullpath << folder_name.c_str() << "/" << ClearFileName(ss_filename.str(), suffix) << suffix; 78 return ss_fullpath.str(); 79#else 80 return ""; 81#endif // ENABLE_IR_DUMP && !PANDA_TARGET_MACOS 82} 83void PassManager::DumpGraph([[maybe_unused]] const char *pass_name) 84{ 85#if defined(ENABLE_IR_DUMP) && !defined(PANDA_TARGET_MACOS) 86 std::ofstream strm(GetFileName(pass_name, ".ir")); 87 if (!strm.is_open()) { 88 std::cerr << errno << " ERROR: " << strerror(errno) << "\n" << GetFileName(pass_name, ".ir") << std::endl; 89 } 90 ASSERT(strm.is_open()); 91 GetGraph()->Dump(&strm); 92#endif // ENABLE_IR_DUMP && !PANDA_TARGET_MACOS 93} 94void PassManager::DumpLifeIntervals([[maybe_unused]] const char *pass_name) 95{ 96#if defined(ENABLE_IR_DUMP) && !defined(PANDA_TARGET_MACOS) 97 if (!GetGraph()->IsAnalysisValid<LivenessAnalyzer>()) { 98 return; 99 } 100 std::ofstream strm(GetFileName(pass_name, ".li")); 101 if (!strm.is_open()) { 102 std::cerr << errno << " ERROR: " << strerror(errno) << "\n" << GetFileName(pass_name, ".li") << std::endl; 103 } 104 105 ASSERT(strm.is_open()); 106 GetGraph()->GetAnalysis<LivenessAnalyzer>().DumpLifeIntervals(strm); 107#endif // ENABLE_IR_DUMP && !PANDA_TARGET_MACOS 108} 109 110bool PassManager::RunPass(Pass *pass, size_t local_mem_size_before_pass) 111{ 112 if (pass->IsAnalysis() && pass->IsValid()) { 113 return true; 114 } 115 116 if (!pass->IsAnalysis() && !static_cast<Optimization *>(pass)->IsEnable()) { 117 return false; 118 } 119 120 if (!IsCheckMode()) { 121 stats_->ProcessBeforeRun(*pass); 122 if (first_execution_ && GetGraph()->GetParentGraph() == nullptr) { 123 StartExecution(); 124 first_execution_ = false; 125 } 126 } 127 128#ifndef NDEBUG 129 if (options.IsCompilerEnableTracing()) { 130 trace::BeginTracePoint(pass->GetPassName()); 131 } 132#endif // NDEBUG 133 134 bool result = pass->Run(); 135 136#ifndef NDEBUG 137 if (options.IsCompilerEnableTracing()) { 138 trace::EndTracePoint(); 139 } 140#endif // NDEBUG 141 142 if (!IsCheckMode()) { 143 ASSERT(graph_->GetLocalAllocator()->GetAllocatedSize() >= local_mem_size_before_pass); 144 stats_->ProcessAfterRun(graph_->GetLocalAllocator()->GetAllocatedSize() - local_mem_size_before_pass); 145 } 146 147 if (pass->IsAnalysis()) { 148 pass->SetValid(result); 149 } 150 if (options.IsCompilerDump() && pass->ShouldDump() && !IsCheckMode()) { 151 if (!options.IsCompilerDumpFinal()) { 152 DumpGraph(pass->GetPassName()); 153 } 154 } 155 156#ifndef NDEBUG 157 bool checker_enabled = options.IsCompilerCheckGraph(); 158 if (options.IsCompilerCheckFinal()) { 159 checker_enabled = false; 160 } 161 if (result && !pass->IsAnalysis() && checker_enabled) { 162 GraphChecker(graph_).Check(); 163 } 164#endif 165 return result; 166} 167 168ArenaAllocator *PassManager::GetAllocator() 169{ 170 return graph_->GetAllocator(); 171} 172 173ArenaAllocator *PassManager::GetLocalAllocator() 174{ 175 return graph_->GetLocalAllocator(); 176} 177 178void PassManager::Finalize() const 179{ 180 if (options.IsCompilerPrintStats()) { 181 stats_->PrintStatistics(); 182 } 183 if (options.WasSetCompilerDumpStatsCsv()) { 184 stats_->DumpStatisticsCsv(); 185 } 186} 187} // namespace panda::compiler 188