blob: 2920190a5a061d1788389e597e854ec6fa369d8f [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#ifndef ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
18#define ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
19
Andreas Gampe53c913b2014-08-12 23:19:23 -070020#include "base/casts.h"
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -080021#include "compiler_internals.h"
James C Scott4f596682014-05-01 05:52:04 -070022#include "pass_me.h"
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -080023
24namespace art {
25
26/**
Vladimir Markobe0e5462014-02-26 11:24:15 +000027 * @class CacheFieldLoweringInfo
28 * @brief Cache the lowering info for fields used by IGET/IPUT/SGET/SPUT insns.
29 */
James C Scott4f596682014-05-01 05:52:04 -070030class CacheFieldLoweringInfo : public PassME {
Vladimir Markobe0e5462014-02-26 11:24:15 +000031 public:
James C Scott4f596682014-05-01 05:52:04 -070032 CacheFieldLoweringInfo() : PassME("CacheFieldLoweringInfo", kNoNodes) {
Vladimir Markobe0e5462014-02-26 11:24:15 +000033 }
34
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -070035 void Start(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -070036 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -070037 CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
James C Scott4f596682014-05-01 05:52:04 -070038 DCHECK(cUnit != nullptr);
Vladimir Markobe0e5462014-02-26 11:24:15 +000039 cUnit->mir_graph->DoCacheFieldLoweringInfo();
40 }
Vladimir Marko3d73ba22014-03-06 15:18:04 +000041
James C Scott4f596682014-05-01 05:52:04 -070042 bool Gate(const PassDataHolder* data) const {
43 DCHECK(data != nullptr);
44 CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
45 DCHECK(cUnit != nullptr);
Vladimir Marko3d73ba22014-03-06 15:18:04 +000046 return cUnit->mir_graph->HasFieldAccess();
47 }
Vladimir Markobe0e5462014-02-26 11:24:15 +000048};
49
50/**
Vladimir Markof096aad2014-01-23 15:51:58 +000051 * @class CacheMethodLoweringInfo
52 * @brief Cache the lowering info for methods called by INVOKEs.
53 */
James C Scott4f596682014-05-01 05:52:04 -070054class CacheMethodLoweringInfo : public PassME {
Vladimir Markof096aad2014-01-23 15:51:58 +000055 public:
James C Scott4f596682014-05-01 05:52:04 -070056 CacheMethodLoweringInfo() : PassME("CacheMethodLoweringInfo", kNoNodes) {
Vladimir Markof096aad2014-01-23 15:51:58 +000057 }
58
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -070059 void Start(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -070060 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -070061 CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
James C Scott4f596682014-05-01 05:52:04 -070062 DCHECK(cUnit != nullptr);
Vladimir Markof096aad2014-01-23 15:51:58 +000063 cUnit->mir_graph->DoCacheMethodLoweringInfo();
64 }
Vladimir Marko3d73ba22014-03-06 15:18:04 +000065
James C Scott4f596682014-05-01 05:52:04 -070066 bool Gate(const PassDataHolder* data) const {
67 DCHECK(data != nullptr);
68 CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
69 DCHECK(cUnit != nullptr);
Vladimir Marko3d73ba22014-03-06 15:18:04 +000070 return cUnit->mir_graph->HasInvokes();
71 }
Vladimir Markof096aad2014-01-23 15:51:58 +000072};
73
74/**
Razvan A Lupusorucb804742014-07-09 16:42:19 -070075 * @class SpecialMethodInliner
76 * @brief Performs method inlining pass on special kinds of methods.
77 * @details Special methods are methods that fall in one of the following categories:
78 * empty, instance getter, instance setter, argument return, and constant return.
Vladimir Marko9820b7c2014-01-02 16:40:37 +000079 */
Razvan A Lupusorucb804742014-07-09 16:42:19 -070080class SpecialMethodInliner : public PassME {
Vladimir Marko9820b7c2014-01-02 16:40:37 +000081 public:
Razvan A Lupusorucb804742014-07-09 16:42:19 -070082 SpecialMethodInliner() : PassME("SpecialMethodInliner") {
Vladimir Marko9820b7c2014-01-02 16:40:37 +000083 }
84
James C Scott4f596682014-05-01 05:52:04 -070085 bool Gate(const PassDataHolder* data) const {
86 DCHECK(data != nullptr);
87 CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
88 DCHECK(cUnit != nullptr);
Razvan A Lupusorucb804742014-07-09 16:42:19 -070089 return cUnit->mir_graph->InlineSpecialMethodsGate();
Vladimir Marko9820b7c2014-01-02 16:40:37 +000090 }
91
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -070092 void Start(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -070093 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -070094 CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
James C Scott4f596682014-05-01 05:52:04 -070095 DCHECK(cUnit != nullptr);
Razvan A Lupusorucb804742014-07-09 16:42:19 -070096 cUnit->mir_graph->InlineSpecialMethodsStart();
Vladimir Marko9820b7c2014-01-02 16:40:37 +000097 }
98
Jean Christophe Beyler09321df2014-07-18 15:33:57 -070099 bool Worker(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700100 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700101 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
James C Scott4f596682014-05-01 05:52:04 -0700102 CompilationUnit* cUnit = pass_me_data_holder->c_unit;
103 DCHECK(cUnit != nullptr);
104 BasicBlock* bb = pass_me_data_holder->bb;
105 DCHECK(bb != nullptr);
Razvan A Lupusorucb804742014-07-09 16:42:19 -0700106 cUnit->mir_graph->InlineSpecialMethods(bb);
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000107 // No need of repeating, so just return false.
108 return false;
109 }
110
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700111 void End(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700112 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700113 CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
James C Scott4f596682014-05-01 05:52:04 -0700114 DCHECK(cUnit != nullptr);
Razvan A Lupusorucb804742014-07-09 16:42:19 -0700115 cUnit->mir_graph->InlineSpecialMethodsEnd();
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000116 }
117};
118
119/**
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800120 * @class CodeLayout
121 * @brief Perform the code layout pass.
122 */
James C Scott4f596682014-05-01 05:52:04 -0700123class CodeLayout : public PassME {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800124 public:
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700125 CodeLayout() : PassME("CodeLayout", kAllNodes, kOptimizationBasicBlockChange, "2_post_layout_cfg") {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800126 }
127
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700128 void Start(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700129 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700130 CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
James C Scott4f596682014-05-01 05:52:04 -0700131 DCHECK(cUnit != nullptr);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800132 cUnit->mir_graph->VerifyDataflow();
133 }
134
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700135 bool Worker(PassDataHolder* data) const;
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800136};
137
138/**
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800139 * @class NullCheckEliminationAndTypeInference
140 * @brief Null check elimination and type inference.
141 */
James C Scott4f596682014-05-01 05:52:04 -0700142class NullCheckEliminationAndTypeInference : public PassME {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800143 public:
Vladimir Marko75ba13f2014-01-28 12:15:24 +0000144 NullCheckEliminationAndTypeInference()
Vladimir Marko622bdbe2014-06-19 14:59:05 +0100145 : PassME("NCE_TypeInference", kRepeatingTopologicalSortTraversal, "4_post_nce_cfg") {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800146 }
147
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700148 void Start(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700149 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700150 CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
James C Scott4f596682014-05-01 05:52:04 -0700151 DCHECK(cUnit != nullptr);
Vladimir Markobfea9c22014-01-17 17:49:33 +0000152 cUnit->mir_graph->EliminateNullChecksAndInferTypesStart();
153 }
154
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700155 bool Worker(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700156 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700157 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
James C Scott4f596682014-05-01 05:52:04 -0700158 CompilationUnit* cUnit = pass_me_data_holder->c_unit;
159 DCHECK(cUnit != nullptr);
160 BasicBlock* bb = pass_me_data_holder->bb;
161 DCHECK(bb != nullptr);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800162 return cUnit->mir_graph->EliminateNullChecksAndInferTypes(bb);
163 }
Vladimir Markobfea9c22014-01-17 17:49:33 +0000164
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700165 void End(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700166 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700167 CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
James C Scott4f596682014-05-01 05:52:04 -0700168 DCHECK(cUnit != nullptr);
Vladimir Markobfea9c22014-01-17 17:49:33 +0000169 cUnit->mir_graph->EliminateNullChecksAndInferTypesEnd();
170 }
171};
172
James C Scott4f596682014-05-01 05:52:04 -0700173class ClassInitCheckElimination : public PassME {
Vladimir Markobfea9c22014-01-17 17:49:33 +0000174 public:
Vladimir Marko622bdbe2014-06-19 14:59:05 +0100175 ClassInitCheckElimination()
Vladimir Marko55fff042014-07-10 12:42:52 +0100176 : PassME("ClInitCheckElimination", kLoopRepeatingTopologicalSortTraversal) {
Vladimir Markobfea9c22014-01-17 17:49:33 +0000177 }
178
James C Scott4f596682014-05-01 05:52:04 -0700179 bool Gate(const PassDataHolder* data) const {
180 DCHECK(data != nullptr);
181 CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
182 DCHECK(cUnit != nullptr);
Vladimir Markobfea9c22014-01-17 17:49:33 +0000183 return cUnit->mir_graph->EliminateClassInitChecksGate();
184 }
185
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700186 bool Worker(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700187 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700188 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
James C Scott4f596682014-05-01 05:52:04 -0700189 CompilationUnit* cUnit = pass_me_data_holder->c_unit;
190 DCHECK(cUnit != nullptr);
191 BasicBlock* bb = pass_me_data_holder->bb;
192 DCHECK(bb != nullptr);
Vladimir Markobfea9c22014-01-17 17:49:33 +0000193 return cUnit->mir_graph->EliminateClassInitChecks(bb);
194 }
195
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700196 void End(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700197 DCHECK(data != nullptr);
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700198 CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
James C Scott4f596682014-05-01 05:52:04 -0700199 DCHECK(cUnit != nullptr);
Vladimir Markobfea9c22014-01-17 17:49:33 +0000200 cUnit->mir_graph->EliminateClassInitChecksEnd();
201 }
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800202};
203
204/**
Vladimir Marko95a05972014-05-30 10:01:32 +0100205 * @class GlobalValueNumberingPass
206 * @brief Performs the global value numbering pass.
207 */
208class GlobalValueNumberingPass : public PassME {
209 public:
210 GlobalValueNumberingPass()
Vladimir Marko55fff042014-07-10 12:42:52 +0100211 : PassME("GVN", kLoopRepeatingTopologicalSortTraversal, "4_post_gvn_cfg") {
Vladimir Marko95a05972014-05-30 10:01:32 +0100212 }
213
Vladimir Marko55fff042014-07-10 12:42:52 +0100214 bool Gate(const PassDataHolder* data) const OVERRIDE {
Vladimir Marko95a05972014-05-30 10:01:32 +0100215 DCHECK(data != nullptr);
216 CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
217 DCHECK(cUnit != nullptr);
218 return cUnit->mir_graph->ApplyGlobalValueNumberingGate();
219 }
220
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700221 bool Worker(PassDataHolder* data) const {
Vladimir Marko95a05972014-05-30 10:01:32 +0100222 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700223 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
Vladimir Marko95a05972014-05-30 10:01:32 +0100224 CompilationUnit* cUnit = pass_me_data_holder->c_unit;
225 DCHECK(cUnit != nullptr);
226 BasicBlock* bb = pass_me_data_holder->bb;
227 DCHECK(bb != nullptr);
228 return cUnit->mir_graph->ApplyGlobalValueNumbering(bb);
229 }
230
Vladimir Marko55fff042014-07-10 12:42:52 +0100231 void End(PassDataHolder* data) const OVERRIDE {
Vladimir Marko95a05972014-05-30 10:01:32 +0100232 DCHECK(data != nullptr);
233 CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
234 DCHECK(cUnit != nullptr);
235 cUnit->mir_graph->ApplyGlobalValueNumberingEnd();
236 }
237};
238
239/**
240 * @class BBCombine
241 * @brief Perform the basic block combination pass.
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800242 */
James C Scott4f596682014-05-01 05:52:04 -0700243class BBCombine : public PassME {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800244 public:
James C Scott4f596682014-05-01 05:52:04 -0700245 BBCombine() : PassME("BBCombine", kPreOrderDFSTraversal, "5_post_bbcombine_cfg") {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800246 }
247
James C Scott4f596682014-05-01 05:52:04 -0700248 bool Gate(const PassDataHolder* data) const {
249 DCHECK(data != nullptr);
250 CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
251 DCHECK(cUnit != nullptr);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800252 return ((cUnit->disable_opt & (1 << kSuppressExceptionEdges)) != 0);
253 }
254
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700255 bool Worker(PassDataHolder* data) const;
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800256};
257
258/**
259 * @class BasicBlock Optimizations
260 * @brief Any simple BasicBlock optimization can be put here.
261 */
James C Scott4f596682014-05-01 05:52:04 -0700262class BBOptimizations : public PassME {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800263 public:
James C Scott4f596682014-05-01 05:52:04 -0700264 BBOptimizations() : PassME("BBOptimizations", kNoNodes, "5_post_bbo_cfg") {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800265 }
266
James C Scott4f596682014-05-01 05:52:04 -0700267 bool Gate(const PassDataHolder* data) const {
268 DCHECK(data != nullptr);
269 CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
270 DCHECK(cUnit != nullptr);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800271 return ((cUnit->disable_opt & (1 << kBBOpt)) == 0);
272 }
273
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700274 void Start(PassDataHolder* data) const;
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800275};
276
277} // namespace art
278
279#endif // ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_