• 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 "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 
29 namespace panda::compiler {
PassManager(Graph * graph,PassManager * parent_pm)30 PassManager::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)
ClearFileName(std::string str,std::string_view suffix)40 static 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 
GetFileName(const char * pass_name,const std::string & suffix)50 std::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 }
DumpGraph(const char * pass_name)83 void 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 }
DumpLifeIntervals(const char * pass_name)94 void 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 
RunPass(Pass * pass,size_t local_mem_size_before_pass)110 bool 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 
GetAllocator()168 ArenaAllocator *PassManager::GetAllocator()
169 {
170     return graph_->GetAllocator();
171 }
172 
GetLocalAllocator()173 ArenaAllocator *PassManager::GetLocalAllocator()
174 {
175     return graph_->GetLocalAllocator();
176 }
177 
Finalize() const178 void 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