blob: 0407e323cba0a49896c5e6896407e882f3b656df [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 Beyler75bcc372014-09-04 08:15:11 -070037 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
38 DCHECK(c_unit != nullptr);
39 c_unit->mir_graph->DoCacheFieldLoweringInfo();
Vladimir Markobe0e5462014-02-26 11:24:15 +000040 }
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);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -070044 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
45 DCHECK(c_unit != nullptr);
46 return c_unit->mir_graph->HasFieldAccess();
Vladimir Marko3d73ba22014-03-06 15:18:04 +000047 }
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 Beyler75bcc372014-09-04 08:15:11 -070061 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
62 DCHECK(c_unit != nullptr);
63 c_unit->mir_graph->DoCacheMethodLoweringInfo();
Vladimir Markof096aad2014-01-23 15:51:58 +000064 }
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);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -070068 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
69 DCHECK(c_unit != nullptr);
70 return c_unit->mir_graph->HasInvokes();
Vladimir Marko3d73ba22014-03-06 15:18:04 +000071 }
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);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -070087 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
88 DCHECK(c_unit != nullptr);
89 return c_unit->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 Beyler75bcc372014-09-04 08:15:11 -070094 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
95 DCHECK(c_unit != nullptr);
96 c_unit->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);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700102 CompilationUnit* c_unit = pass_me_data_holder->c_unit;
103 DCHECK(c_unit != nullptr);
James C Scott4f596682014-05-01 05:52:04 -0700104 BasicBlock* bb = pass_me_data_holder->bb;
105 DCHECK(bb != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700106 c_unit->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 Beyler75bcc372014-09-04 08:15:11 -0700113 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
114 DCHECK(c_unit != nullptr);
115 c_unit->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 Beyler75bcc372014-09-04 08:15:11 -0700130 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
131 DCHECK(c_unit != nullptr);
132 c_unit->mir_graph->VerifyDataflow();
133 c_unit->mir_graph->ClearAllVisitedFlags();
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800134 }
135
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700136 bool Worker(PassDataHolder* data) const;
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800137};
138
139/**
Vladimir Marko67c72b82014-10-09 12:26:10 +0100140 * @class NullCheckElimination
141 * @brief Null check elimination pass.
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800142 */
Vladimir Marko67c72b82014-10-09 12:26:10 +0100143class NullCheckElimination : public PassME {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800144 public:
Vladimir Marko67c72b82014-10-09 12:26:10 +0100145 NullCheckElimination()
Vladimir Marko7baa6f82014-10-09 18:01:24 +0100146 : PassME("NCE", kRepeatingPreOrderDFSTraversal, "3_post_nce_cfg") {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800147 }
148
Vladimir Marko67c72b82014-10-09 12:26:10 +0100149 bool Gate(const PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700150 DCHECK(data != nullptr);
Vladimir Marko67c72b82014-10-09 12:26:10 +0100151 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700152 DCHECK(c_unit != nullptr);
Vladimir Marko67c72b82014-10-09 12:26:10 +0100153 return c_unit->mir_graph->EliminateNullChecksGate();
Vladimir Markobfea9c22014-01-17 17:49:33 +0000154 }
155
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700156 bool Worker(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700157 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700158 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700159 CompilationUnit* c_unit = pass_me_data_holder->c_unit;
160 DCHECK(c_unit != nullptr);
James C Scott4f596682014-05-01 05:52:04 -0700161 BasicBlock* bb = pass_me_data_holder->bb;
162 DCHECK(bb != nullptr);
Vladimir Marko67c72b82014-10-09 12:26:10 +0100163 return c_unit->mir_graph->EliminateNullChecks(bb);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800164 }
Vladimir Markobfea9c22014-01-17 17:49:33 +0000165
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700166 void End(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700167 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700168 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
169 DCHECK(c_unit != nullptr);
Vladimir Marko67c72b82014-10-09 12:26:10 +0100170 c_unit->mir_graph->EliminateNullChecksEnd();
171 }
172};
173
174/**
175 * @class TypeInference
176 * @brief Type inference pass.
177 */
178class TypeInference : public PassME {
179 public:
180 TypeInference()
Vladimir Marko415ac882014-09-30 18:09:14 +0100181 : PassME("TypeInference", kRepeatingPreOrderDFSTraversal, "4_post_type_cfg") {
Vladimir Marko67c72b82014-10-09 12:26:10 +0100182 }
183
184 bool Worker(PassDataHolder* data) const {
185 DCHECK(data != nullptr);
186 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
187 CompilationUnit* c_unit = pass_me_data_holder->c_unit;
188 DCHECK(c_unit != nullptr);
189 BasicBlock* bb = pass_me_data_holder->bb;
190 DCHECK(bb != nullptr);
191 return c_unit->mir_graph->InferTypes(bb);
Vladimir Markobfea9c22014-01-17 17:49:33 +0000192 }
193};
194
James C Scott4f596682014-05-01 05:52:04 -0700195class ClassInitCheckElimination : public PassME {
Vladimir Markobfea9c22014-01-17 17:49:33 +0000196 public:
Vladimir Marko622bdbe2014-06-19 14:59:05 +0100197 ClassInitCheckElimination()
Vladimir Marko7baa6f82014-10-09 18:01:24 +0100198 : PassME("ClInitCheckElimination", kRepeatingPreOrderDFSTraversal) {
Vladimir Markobfea9c22014-01-17 17:49:33 +0000199 }
200
James C Scott4f596682014-05-01 05:52:04 -0700201 bool Gate(const PassDataHolder* data) const {
202 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700203 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
204 DCHECK(c_unit != nullptr);
205 return c_unit->mir_graph->EliminateClassInitChecksGate();
Vladimir Markobfea9c22014-01-17 17:49:33 +0000206 }
207
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700208 bool Worker(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700209 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700210 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700211 CompilationUnit* c_unit = pass_me_data_holder->c_unit;
212 DCHECK(c_unit != nullptr);
James C Scott4f596682014-05-01 05:52:04 -0700213 BasicBlock* bb = pass_me_data_holder->bb;
214 DCHECK(bb != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700215 return c_unit->mir_graph->EliminateClassInitChecks(bb);
Vladimir Markobfea9c22014-01-17 17:49:33 +0000216 }
217
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700218 void End(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700219 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700220 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
221 DCHECK(c_unit != nullptr);
222 c_unit->mir_graph->EliminateClassInitChecksEnd();
Vladimir Markobfea9c22014-01-17 17:49:33 +0000223 }
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800224};
225
226/**
Vladimir Marko95a05972014-05-30 10:01:32 +0100227 * @class GlobalValueNumberingPass
228 * @brief Performs the global value numbering pass.
229 */
230class GlobalValueNumberingPass : public PassME {
231 public:
232 GlobalValueNumberingPass()
Vladimir Marko55fff042014-07-10 12:42:52 +0100233 : PassME("GVN", kLoopRepeatingTopologicalSortTraversal, "4_post_gvn_cfg") {
Vladimir Marko95a05972014-05-30 10:01:32 +0100234 }
235
Vladimir Marko55fff042014-07-10 12:42:52 +0100236 bool Gate(const PassDataHolder* data) const OVERRIDE {
Vladimir Marko95a05972014-05-30 10:01:32 +0100237 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700238 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
239 DCHECK(c_unit != nullptr);
240 return c_unit->mir_graph->ApplyGlobalValueNumberingGate();
Vladimir Marko95a05972014-05-30 10:01:32 +0100241 }
242
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700243 bool Worker(PassDataHolder* data) const {
Vladimir Marko95a05972014-05-30 10:01:32 +0100244 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700245 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700246 CompilationUnit* c_unit = pass_me_data_holder->c_unit;
247 DCHECK(c_unit != nullptr);
Vladimir Marko95a05972014-05-30 10:01:32 +0100248 BasicBlock* bb = pass_me_data_holder->bb;
249 DCHECK(bb != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700250 return c_unit->mir_graph->ApplyGlobalValueNumbering(bb);
Vladimir Marko95a05972014-05-30 10:01:32 +0100251 }
252
Vladimir Marko55fff042014-07-10 12:42:52 +0100253 void End(PassDataHolder* data) const OVERRIDE {
Vladimir Marko95a05972014-05-30 10:01:32 +0100254 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700255 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
256 DCHECK(c_unit != nullptr);
257 c_unit->mir_graph->ApplyGlobalValueNumberingEnd();
Vladimir Marko95a05972014-05-30 10:01:32 +0100258 }
259};
260
261/**
262 * @class BBCombine
263 * @brief Perform the basic block combination pass.
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800264 */
James C Scott4f596682014-05-01 05:52:04 -0700265class BBCombine : public PassME {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800266 public:
James C Scott4f596682014-05-01 05:52:04 -0700267 BBCombine() : PassME("BBCombine", kPreOrderDFSTraversal, "5_post_bbcombine_cfg") {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800268 }
269
James C Scott4f596682014-05-01 05:52:04 -0700270 bool Gate(const PassDataHolder* data) const {
271 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700272 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
273 DCHECK(c_unit != nullptr);
Vladimir Marko312eb252014-10-07 15:01:57 +0100274 return c_unit->mir_graph->HasTryCatchBlocks() ||
275 ((c_unit->disable_opt & (1 << kSuppressExceptionEdges)) != 0);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800276 }
277
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700278 bool Worker(PassDataHolder* data) const;
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800279};
280
281/**
282 * @class BasicBlock Optimizations
283 * @brief Any simple BasicBlock optimization can be put here.
284 */
James C Scott4f596682014-05-01 05:52:04 -0700285class BBOptimizations : public PassME {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800286 public:
James C Scott4f596682014-05-01 05:52:04 -0700287 BBOptimizations() : PassME("BBOptimizations", kNoNodes, "5_post_bbo_cfg") {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800288 }
289
James C Scott4f596682014-05-01 05:52:04 -0700290 bool Gate(const PassDataHolder* data) const {
291 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700292 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
293 DCHECK(c_unit != nullptr);
294 return ((c_unit->disable_opt & (1 << kBBOpt)) == 0);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800295 }
296
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700297 void Start(PassDataHolder* data) const;
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800298};
299
Vladimir Marko8b858e12014-11-27 14:52:37 +0000300/**
301 * @class SuspendCheckElimination
302 * @brief Any simple BasicBlock optimization can be put here.
303 */
304class SuspendCheckElimination : public PassME {
305 public:
306 SuspendCheckElimination()
307 : PassME("SuspendCheckElimination", kTopologicalSortTraversal, "6_post_sce_cfg") {
308 }
309
310 bool Gate(const PassDataHolder* data) const {
311 DCHECK(data != nullptr);
312 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
313 DCHECK(c_unit != nullptr);
314 return c_unit->mir_graph->EliminateSuspendChecksGate();
315 }
316
317 bool Worker(PassDataHolder* data) const {
318 DCHECK(data != nullptr);
319 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
320 CompilationUnit* c_unit = pass_me_data_holder->c_unit;
321 DCHECK(c_unit != nullptr);
322 BasicBlock* bb = pass_me_data_holder->bb;
323 DCHECK(bb != nullptr);
324 return c_unit->mir_graph->EliminateSuspendChecks(bb);
325 }
326
327 void End(PassDataHolder* data) const {
328 DCHECK(data != nullptr);
329 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
330 DCHECK(c_unit != nullptr);
331 c_unit->mir_graph->EliminateSuspendChecksEnd();
332 }
333};
334
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800335} // namespace art
336
337#endif // ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_