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