blob: 964355bb5d6e4e53916381527cebbd34654117d2 [file] [log] [blame]
Jean Christophe Beyler2469e602014-05-06 20:36:55 -07001/*
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
Narayan Kamathfd5a8522014-05-30 11:58:09 +010017#ifndef ART_COMPILER_DEX_POST_OPT_PASSES_H_
18#define ART_COMPILER_DEX_POST_OPT_PASSES_H_
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070019
Andreas Gampe53c913b2014-08-12 23:19:23 -070020#include "dex/quick/mir_to_lir.h"
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070021#include "compiler_internals.h"
22#include "pass_me.h"
23
24namespace art {
25
26/**
Vladimir Markoffda4992014-12-18 17:05:58 +000027 * @class PassMEMirSsaRep
28 * @brief Convenience class for passes that check MIRGraph::MirSsaRepUpToDate().
29 */
30class PassMEMirSsaRep : public PassME {
31 public:
32 PassMEMirSsaRep(const char* name, DataFlowAnalysisMode type = kAllNodes)
33 : PassME(name, type) {
34 }
35
36 bool Gate(const PassDataHolder* data) const OVERRIDE {
37 DCHECK(data != nullptr);
38 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
39 DCHECK(c_unit != nullptr);
40 return !c_unit->mir_graph->MirSsaRepUpToDate();
41 }
42};
43
44/**
45 * @class InitializeSSATransformation
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070046 * @brief There is some data that needs to be initialized before performing
47 * the post optimization passes.
48 */
Vladimir Markoffda4992014-12-18 17:05:58 +000049class InitializeSSATransformation : public PassMEMirSsaRep {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070050 public:
Vladimir Markoffda4992014-12-18 17:05:58 +000051 InitializeSSATransformation() : PassMEMirSsaRep("InitializeSSATransformation", kNoNodes) {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070052 }
53
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -070054 void Start(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070055 // New blocks may have been inserted so the first thing we do is ensure that
56 // the c_unit's number of blocks matches the actual count of basic blocks.
57 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -070058 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070059 DCHECK(c_unit != nullptr);
Vladimir Markoffda4992014-12-18 17:05:58 +000060 c_unit->mir_graph->SSATransformationStart();
61 c_unit->mir_graph->CompilerInitializeSSAConversion();
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070062 }
63};
64
65/**
66 * @class MethodUseCount
67 * @brief Count the register uses of the method
68 */
69class MethodUseCount : public PassME {
70 public:
71 MethodUseCount() : PassME("UseCount") {
72 }
73
Jean Christophe Beyler09321df2014-07-18 15:33:57 -070074 bool Worker(PassDataHolder* data) const;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070075
76 bool Gate(const PassDataHolder* data) const;
77};
78
79/**
80 * @class ClearPhiInformation
81 * @brief Clear the PHI nodes from the CFG.
82 */
Vladimir Markoffda4992014-12-18 17:05:58 +000083class ClearPhiInstructions : public PassMEMirSsaRep {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070084 public:
Vladimir Markoffda4992014-12-18 17:05:58 +000085 ClearPhiInstructions() : PassMEMirSsaRep("ClearPhiInstructions") {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070086 }
87
Jean Christophe Beyler09321df2014-07-18 15:33:57 -070088 bool Worker(PassDataHolder* data) const;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070089};
90
91/**
92 * @class CalculatePredecessors
93 * @brief Calculate the predecessor BitVector of each Basicblock.
94 */
95class CalculatePredecessors : public PassME {
96 public:
Vladimir Markoaa7b8a32014-10-15 11:35:44 +010097 CalculatePredecessors() : PassME("CalculatePredecessors", kNoNodes) {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070098 }
99
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700100 void Start(PassDataHolder* data) const;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700101};
102
103/**
104 * @class DFSOrders
105 * @brief Compute the DFS order of the MIR graph
106 */
107class DFSOrders : public PassME {
108 public:
Vladimir Markoaa7b8a32014-10-15 11:35:44 +0100109 DFSOrders() : PassME("DFSOrders", kNoNodes) {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700110 }
111
Vladimir Marko312eb252014-10-07 15:01:57 +0100112 bool Gate(const PassDataHolder* data) const {
113 DCHECK(data != nullptr);
114 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
115 DCHECK(c_unit != nullptr);
116 return !c_unit->mir_graph->DfsOrdersUpToDate();
117 }
118
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700119 void Start(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700120 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700121 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700122 DCHECK(c_unit != nullptr);
123 c_unit->mir_graph.get()->ComputeDFSOrders();
124 }
125};
126
127/**
128 * @class BuildDomination
129 * @brief Build the domination information of the MIR Graph
130 */
131class BuildDomination : public PassME {
132 public:
Vladimir Markoaa7b8a32014-10-15 11:35:44 +0100133 BuildDomination() : PassME("BuildDomination", kNoNodes) {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700134 }
135
Vladimir Markoffda4992014-12-18 17:05:58 +0000136 bool Gate(const PassDataHolder* data) const {
137 DCHECK(data != nullptr);
138 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
139 DCHECK(c_unit != nullptr);
140 return !c_unit->mir_graph->DominationUpToDate();
141 }
142
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700143 void Start(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700144 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700145 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700146 DCHECK(c_unit != nullptr);
Vladimir Markoffda4992014-12-18 17:05:58 +0000147 c_unit->mir_graph->ComputeDominators();
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700148 }
149
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700150 void End(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700151 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700152 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700153 DCHECK(c_unit != nullptr);
154 // Verify the dataflow information after the pass.
155 if (c_unit->enable_debug & (1 << kDebugVerifyDataflow)) {
156 c_unit->mir_graph->VerifyDataflow();
157 }
158 }
159};
160
161/**
Vladimir Marko622bdbe2014-06-19 14:59:05 +0100162 * @class TopologicalSortOrders
163 * @brief Compute the topological sort order of the MIR graph
164 */
165class TopologicalSortOrders : public PassME {
166 public:
Vladimir Markoaa7b8a32014-10-15 11:35:44 +0100167 TopologicalSortOrders() : PassME("TopologicalSortOrders", kNoNodes) {
Vladimir Marko622bdbe2014-06-19 14:59:05 +0100168 }
169
Vladimir Markoffda4992014-12-18 17:05:58 +0000170 bool Gate(const PassDataHolder* data) const {
171 DCHECK(data != nullptr);
172 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
173 DCHECK(c_unit != nullptr);
174 return !c_unit->mir_graph->TopologicalOrderUpToDate();
175 }
176
Vladimir Marko622bdbe2014-06-19 14:59:05 +0100177 void Start(PassDataHolder* data) const {
178 DCHECK(data != nullptr);
179 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
180 DCHECK(c_unit != nullptr);
181 c_unit->mir_graph.get()->ComputeTopologicalSortOrder();
182 }
183};
184
185/**
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700186 * @class DefBlockMatrix
187 * @brief Calculate the matrix of definition per basic block
188 */
Vladimir Markoffda4992014-12-18 17:05:58 +0000189class DefBlockMatrix : public PassMEMirSsaRep {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700190 public:
Vladimir Markoffda4992014-12-18 17:05:58 +0000191 DefBlockMatrix() : PassMEMirSsaRep("DefBlockMatrix", kNoNodes) {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700192 }
193
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700194 void Start(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700195 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700196 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700197 DCHECK(c_unit != nullptr);
198 c_unit->mir_graph.get()->ComputeDefBlockMatrix();
199 }
200};
201
202/**
203 * @class CreatePhiNodes
204 * @brief Pass to create the phi nodes after SSA calculation
205 */
Vladimir Markoffda4992014-12-18 17:05:58 +0000206class CreatePhiNodes : public PassMEMirSsaRep {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700207 public:
Vladimir Markoffda4992014-12-18 17:05:58 +0000208 CreatePhiNodes() : PassMEMirSsaRep("CreatePhiNodes", kNoNodes) {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700209 }
210
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700211 void Start(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700212 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700213 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700214 DCHECK(c_unit != nullptr);
215 c_unit->mir_graph.get()->InsertPhiNodes();
216 }
217};
218
219/**
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700220 * @class SSAConversion
221 * @brief Pass for SSA conversion of MIRs
222 */
Vladimir Markoffda4992014-12-18 17:05:58 +0000223class SSAConversion : public PassMEMirSsaRep {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700224 public:
Vladimir Markoffda4992014-12-18 17:05:58 +0000225 SSAConversion() : PassMEMirSsaRep("SSAConversion", kNoNodes) {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700226 }
227
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700228 void Start(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700229 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700230 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700231 DCHECK(c_unit != nullptr);
232 MIRGraph *mir_graph = c_unit->mir_graph.get();
Vladimir Markoffda4992014-12-18 17:05:58 +0000233 mir_graph->ClearAllVisitedFlags();
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700234 mir_graph->DoDFSPreOrderSSARename(mir_graph->GetEntryBlock());
235 }
236};
237
238/**
239 * @class PhiNodeOperands
240 * @brief Pass to insert the Phi node operands to basic blocks
241 */
Vladimir Markoffda4992014-12-18 17:05:58 +0000242class PhiNodeOperands : public PassMEMirSsaRep {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700243 public:
Vladimir Markoffda4992014-12-18 17:05:58 +0000244 PhiNodeOperands() : PassMEMirSsaRep("PhiNodeOperands", kPreOrderDFSTraversal) {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700245 }
246
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700247 bool Worker(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700248 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700249 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700250 DCHECK(c_unit != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700251 BasicBlock* bb = down_cast<PassMEDataHolder*>(data)->bb;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700252 DCHECK(bb != nullptr);
253 c_unit->mir_graph->InsertPhiNodeOperands(bb);
254 // No need of repeating, so just return false.
255 return false;
256 }
257};
258
259/**
260 * @class InitRegLocations
261 * @brief Initialize Register Locations.
262 */
Vladimir Markoffda4992014-12-18 17:05:58 +0000263class PerformInitRegLocations : public PassMEMirSsaRep {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700264 public:
Vladimir Markoffda4992014-12-18 17:05:58 +0000265 PerformInitRegLocations() : PassMEMirSsaRep("PerformInitRegLocation", kNoNodes) {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700266 }
267
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700268 void Start(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700269 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700270 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700271 DCHECK(c_unit != nullptr);
272 c_unit->mir_graph->InitRegLocations();
273 }
274};
275
276/**
277 * @class ConstantPropagation
278 * @brief Perform a constant propagation pass.
279 */
Vladimir Markoffda4992014-12-18 17:05:58 +0000280class ConstantPropagation : public PassMEMirSsaRep {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700281 public:
Vladimir Markoffda4992014-12-18 17:05:58 +0000282 ConstantPropagation() : PassMEMirSsaRep("ConstantPropagation") {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700283 }
284
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700285 bool Worker(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700286 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700287 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700288 DCHECK(c_unit != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700289 BasicBlock* bb = down_cast<PassMEDataHolder*>(data)->bb;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700290 DCHECK(bb != nullptr);
291 c_unit->mir_graph->DoConstantPropagation(bb);
292 // No need of repeating, so just return false.
293 return false;
294 }
295
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700296 void Start(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700297 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700298 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700299 DCHECK(c_unit != nullptr);
300 c_unit->mir_graph->InitializeConstantPropagation();
301 }
302};
303
304/**
Vladimir Markoffda4992014-12-18 17:05:58 +0000305 * @class FinishSSATransformation
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700306 * @brief There is some data that needs to be freed after performing the post optimization passes.
307 */
Vladimir Markoffda4992014-12-18 17:05:58 +0000308class FinishSSATransformation : public PassMEMirSsaRep {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700309 public:
Vladimir Markoffda4992014-12-18 17:05:58 +0000310 FinishSSATransformation() : PassMEMirSsaRep("FinishSSATransformation", kNoNodes) {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700311 }
312
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700313 void End(PassDataHolder* data) const {
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700314 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700315 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700316 DCHECK(c_unit != nullptr);
317 c_unit->mir_graph.get()->SSATransformationEnd();
318 }
319};
320
321} // namespace art
322
Narayan Kamathfd5a8522014-05-30 11:58:09 +0100323#endif // ART_COMPILER_DEX_POST_OPT_PASSES_H_