blob: 820dc5a6299ea740153d922aecd098e6278da437 [file] [log] [blame]
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <dlfcn.h>
18
19#include "bb_optimizations.h"
20#include "compiler_internals.h"
21#include "dataflow_iterator.h"
22#include "dataflow_iterator-inl.h"
23#include "pass.h"
24#include "pass_driver.h"
25
26namespace art {
27
Jean Christophe Beyler775c4722014-01-16 08:51:48 -080028namespace { // anonymous namespace
29
30/**
31 * @brief Helper function to create a single instance of a given Pass and can be shared across the threads
32 */
33template <typename PassType>
34const Pass* GetPassInstance() {
35 static const PassType pass;
36 return &pass;
37}
38
39} // anonymous namespace
40
41PassDriver::PassDriver(CompilationUnit* cu, bool create_default_passes) : cu_(cu) {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -080042 dump_cfg_folder_ = "/sdcard/";
43
44 // If need be, create the default passes.
45 if (create_default_passes == true) {
46 CreatePasses();
47 }
48}
49
50PassDriver::~PassDriver() {
51 // Clear the map: done to remove any chance of having a pointer after freeing below
52 pass_map_.clear();
53}
54
Jean Christophe Beyler775c4722014-01-16 08:51:48 -080055void PassDriver::InsertPass(const Pass* new_pass, bool warn_override) {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -080056 assert(new_pass != 0);
57
58 // Get name here to not do it all over the method.
59 const std::string& name = new_pass->GetName();
60
61 // Do we want to warn the user about squashing a pass?
62 if (warn_override == false) {
Jean Christophe Beyler775c4722014-01-16 08:51:48 -080063 auto it = pass_map_.find(name);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -080064
65 if (it != pass_map_.end()) {
66 LOG(INFO) << "Pass name " << name << " already used, overwriting pass";
67 }
68 }
69
70 // Now add to map and list.
71 pass_map_.Put(name, new_pass);
72 pass_list_.push_back(new_pass);
73}
74
75void PassDriver::CreatePasses() {
76 /*
77 * Create the pass list:
78 * - These passes are immutable and are shared across the threads:
79 * - This is achieved via:
80 * - The UniquePtr used here.
81 * - DISALLOW_COPY_AND_ASSIGN in the base Pass class.
82 *
83 * Advantage is that there will be no race conditions here.
84 * Disadvantage is the passes can't change their internal states depending on CompilationUnit:
85 * - This is not yet an issue: no current pass would require it.
86 */
Jean Christophe Beyler775c4722014-01-16 08:51:48 -080087 static const Pass* passes[] = {
88 GetPassInstance<CodeLayout>(),
89 GetPassInstance<SSATransformation>(),
90 GetPassInstance<ConstantPropagation>(),
91 GetPassInstance<InitRegLocations>(),
92 GetPassInstance<MethodUseCount>(),
93 GetPassInstance<NullCheckEliminationAndTypeInferenceInit>(),
94 GetPassInstance<NullCheckEliminationAndTypeInference>(),
95 GetPassInstance<BBCombine>(),
96 GetPassInstance<BBOptimizations>(),
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -080097 };
98
99 // Get number of elements in the array.
100 unsigned int nbr = (sizeof(passes) / sizeof(passes[0]));
101
102 // Insert each pass into the map and into the list via the InsertPass method:
103 // - Map is used for the lookup
104 // - List is used for the pass walk
105 for (unsigned int i = 0; i < nbr; i++) {
Jean Christophe Beyler775c4722014-01-16 08:51:48 -0800106 InsertPass(passes[i]);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800107 }
108}
109
Jean Christophe Beyler775c4722014-01-16 08:51:48 -0800110void PassDriver::HandlePassFlag(CompilationUnit* c_unit, const Pass* pass) {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800111 // Unused parameters for the moment.
112 UNUSED(c_unit);
113 UNUSED(pass);
114}
115
Jean Christophe Beyler775c4722014-01-16 08:51:48 -0800116void PassDriver::DispatchPass(CompilationUnit* c_unit, const Pass* curPass) {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800117 DataflowIterator* iterator = 0;
118
119 LOG(DEBUG) << "Dispatching " << curPass->GetName();
120
121 MIRGraph* mir_graph = c_unit->mir_graph.get();
122 ArenaAllocator *arena = &(c_unit->arena);
123
124 // Let us start by getting the right iterator.
125 DataFlowAnalysisMode mode = curPass->GetTraversal();
126
127 switch (mode) {
128 case kPreOrderDFSTraversal:
129 iterator = new (arena) PreOrderDfsIterator(mir_graph);
130 break;
131 case kRepeatingPreOrderDFSTraversal:
132 iterator = new (arena) RepeatingPreOrderDfsIterator(mir_graph);
133 break;
134 case kRepeatingPostOrderDFSTraversal:
135 iterator = new (arena) RepeatingPostOrderDfsIterator(mir_graph);
136 break;
137 case kReversePostOrderDFSTraversal:
138 iterator = new (arena) ReversePostOrderDfsIterator(mir_graph);
139 break;
140 case kRepeatingReversePostOrderDFSTraversal:
141 iterator = new (arena) RepeatingReversePostOrderDfsIterator(mir_graph);
142 break;
143 case kPostOrderDOMTraversal:
144 iterator = new (arena) PostOrderDOMIterator(mir_graph);
145 break;
146 case kAllNodes:
147 iterator = new (arena) AllNodesIterator(mir_graph);
148 break;
149 default:
150 LOG(DEBUG) << "Iterator mode not handled in dispatcher: " << mode;
151 return;
152 }
153
154 // Paranoid: Check the iterator before walking the BasicBlocks.
155 assert(iterator != 0);
156
157 bool change = false;
158 for (BasicBlock *bb = iterator->Next(change); bb != 0; bb = iterator->Next(change)) {
159 change = curPass->WalkBasicBlocks(c_unit, bb);
160 }
161}
162
Jean Christophe Beyler775c4722014-01-16 08:51:48 -0800163void PassDriver::ApplyPass(CompilationUnit* c_unit, const Pass* curPass) {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800164 curPass->Start(c_unit);
165 DispatchPass(c_unit, curPass);
166 curPass->End(c_unit);
167}
168
Jean Christophe Beyler775c4722014-01-16 08:51:48 -0800169bool PassDriver::RunPass(CompilationUnit* c_unit, const Pass* curPass, bool time_split) {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800170 // Paranoid: c_unit or curPass cannot be 0, and the pass should have a name.
171 if (c_unit == 0 || curPass == 0 || (strcmp(curPass->GetName(), "") == 0)) {
172 return false;
173 }
174
175 // Do we perform a time split
176 if (time_split == true) {
Nicolas Geoffraya3058e72014-01-15 11:44:38 +0000177 c_unit->NewTimingSplit(curPass->GetName());
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800178 }
179
180 // Check the pass gate first.
181 bool shouldApplyPass = curPass->Gate(c_unit);
182
183 if (shouldApplyPass == true) {
184 // Applying the pass: first start, doWork, and end calls.
185 ApplyPass(c_unit, curPass);
186
187 // Clean up if need be.
188 HandlePassFlag(c_unit, curPass);
189
190 // Do we want to log it?
191 if ((c_unit->enable_debug& (1 << kDebugDumpCFG)) != 0) {
192 // Do we have a pass folder?
193 const std::string& passFolder = curPass->GetDumpCFGFolder();
194
195 if (passFolder != "") {
196 // Create directory prefix.
197 std::string prefix = GetDumpCFGFolder();
198 prefix += passFolder;
199 prefix += "/";
200
201 c_unit->mir_graph->DumpCFG(prefix.c_str(), false);
202 }
203 }
204 }
205
206 // If the pass gate passed, we can declare success.
207 return shouldApplyPass;
208}
209
210bool PassDriver::RunPass(CompilationUnit* c_unit, const std::string& pass_name) {
211 // Paranoid: c_unit cannot be 0 and we need a pass name.
212 if (c_unit == 0 || pass_name == "") {
213 return false;
214 }
215
Jean Christophe Beyler775c4722014-01-16 08:51:48 -0800216 const Pass* curPass = GetPass(pass_name);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800217
218 if (curPass != 0) {
219 return RunPass(c_unit, curPass);
220 }
221
222 // Return false, we did not find the pass.
223 return false;
224}
225
226void PassDriver::Launch() {
Jean Christophe Beyler775c4722014-01-16 08:51:48 -0800227 for (const Pass *curPass : pass_list_) {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800228 RunPass(cu_, curPass, true);
229 }
230}
231
232void PassDriver::PrintPassNames() const {
233 LOG(INFO) << "Loop Passes are:";
234
Jean Christophe Beyler775c4722014-01-16 08:51:48 -0800235 for (const Pass *curPass : pass_list_) {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800236 LOG(INFO) << "\t-" << curPass->GetName();
237 }
238}
239
Jean Christophe Beyler775c4722014-01-16 08:51:48 -0800240const Pass* PassDriver::GetPass(const std::string& name) const {
241 auto it = pass_map_.find(name);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800242
243 if (it != pass_map_.end()) {
244 return it->second;
245 }
246
247 return 0;
248}
249
250} // namespace art