blob: b2c348bef112ecccd0d295df3f2e35e51761196c [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/**
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800140 * @class NullCheckEliminationAndTypeInference
141 * @brief Null check elimination and type inference.
142 */
James C Scott4f596682014-05-01 05:52:04 -0700143class NullCheckEliminationAndTypeInference : public PassME {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800144 public:
Vladimir Marko75ba13f2014-01-28 12:15:24 +0000145 NullCheckEliminationAndTypeInference()
Vladimir Marko622bdbe2014-06-19 14:59:05 +0100146 : PassME("NCE_TypeInference", kRepeatingTopologicalSortTraversal, "4_post_nce_cfg") {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800147 }
148
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700149 void Start(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700150 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700151 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
152 DCHECK(c_unit != nullptr);
153 c_unit->mir_graph->EliminateNullChecksAndInferTypesStart();
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);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700163 return c_unit->mir_graph->EliminateNullChecksAndInferTypes(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);
170 c_unit->mir_graph->EliminateNullChecksAndInferTypesEnd();
Vladimir Markobfea9c22014-01-17 17:49:33 +0000171 }
172};
173
James C Scott4f596682014-05-01 05:52:04 -0700174class ClassInitCheckElimination : public PassME {
Vladimir Markobfea9c22014-01-17 17:49:33 +0000175 public:
Vladimir Marko622bdbe2014-06-19 14:59:05 +0100176 ClassInitCheckElimination()
Vladimir Marko55fff042014-07-10 12:42:52 +0100177 : PassME("ClInitCheckElimination", kLoopRepeatingTopologicalSortTraversal) {
Vladimir Markobfea9c22014-01-17 17:49:33 +0000178 }
179
James C Scott4f596682014-05-01 05:52:04 -0700180 bool Gate(const PassDataHolder* data) const {
181 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700182 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
183 DCHECK(c_unit != nullptr);
184 return c_unit->mir_graph->EliminateClassInitChecksGate();
Vladimir Markobfea9c22014-01-17 17:49:33 +0000185 }
186
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700187 bool Worker(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700188 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700189 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700190 CompilationUnit* c_unit = pass_me_data_holder->c_unit;
191 DCHECK(c_unit != nullptr);
James C Scott4f596682014-05-01 05:52:04 -0700192 BasicBlock* bb = pass_me_data_holder->bb;
193 DCHECK(bb != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700194 return c_unit->mir_graph->EliminateClassInitChecks(bb);
Vladimir Markobfea9c22014-01-17 17:49:33 +0000195 }
196
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700197 void End(PassDataHolder* data) const {
James C Scott4f596682014-05-01 05:52:04 -0700198 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700199 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
200 DCHECK(c_unit != nullptr);
201 c_unit->mir_graph->EliminateClassInitChecksEnd();
Vladimir Markobfea9c22014-01-17 17:49:33 +0000202 }
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800203};
204
205/**
Vladimir Marko95a05972014-05-30 10:01:32 +0100206 * @class GlobalValueNumberingPass
207 * @brief Performs the global value numbering pass.
208 */
209class GlobalValueNumberingPass : public PassME {
210 public:
211 GlobalValueNumberingPass()
Vladimir Marko55fff042014-07-10 12:42:52 +0100212 : PassME("GVN", kLoopRepeatingTopologicalSortTraversal, "4_post_gvn_cfg") {
Vladimir Marko95a05972014-05-30 10:01:32 +0100213 }
214
Vladimir Marko55fff042014-07-10 12:42:52 +0100215 bool Gate(const PassDataHolder* data) const OVERRIDE {
Vladimir Marko95a05972014-05-30 10:01:32 +0100216 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700217 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
218 DCHECK(c_unit != nullptr);
219 return c_unit->mir_graph->ApplyGlobalValueNumberingGate();
Vladimir Marko95a05972014-05-30 10:01:32 +0100220 }
221
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700222 bool Worker(PassDataHolder* data) const {
Vladimir Marko95a05972014-05-30 10:01:32 +0100223 DCHECK(data != nullptr);
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700224 PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700225 CompilationUnit* c_unit = pass_me_data_holder->c_unit;
226 DCHECK(c_unit != nullptr);
Vladimir Marko95a05972014-05-30 10:01:32 +0100227 BasicBlock* bb = pass_me_data_holder->bb;
228 DCHECK(bb != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700229 return c_unit->mir_graph->ApplyGlobalValueNumbering(bb);
Vladimir Marko95a05972014-05-30 10:01:32 +0100230 }
231
Vladimir Marko55fff042014-07-10 12:42:52 +0100232 void End(PassDataHolder* data) const OVERRIDE {
Vladimir Marko95a05972014-05-30 10:01:32 +0100233 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700234 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
235 DCHECK(c_unit != nullptr);
236 c_unit->mir_graph->ApplyGlobalValueNumberingEnd();
Vladimir Marko95a05972014-05-30 10:01:32 +0100237 }
238};
239
240/**
241 * @class BBCombine
242 * @brief Perform the basic block combination pass.
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800243 */
James C Scott4f596682014-05-01 05:52:04 -0700244class BBCombine : public PassME {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800245 public:
James C Scott4f596682014-05-01 05:52:04 -0700246 BBCombine() : PassME("BBCombine", kPreOrderDFSTraversal, "5_post_bbcombine_cfg") {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800247 }
248
James C Scott4f596682014-05-01 05:52:04 -0700249 bool Gate(const PassDataHolder* data) const {
250 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700251 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
252 DCHECK(c_unit != nullptr);
253 return ((c_unit->disable_opt & (1 << kSuppressExceptionEdges)) != 0);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800254 }
255
Jean Christophe Beyler09321df2014-07-18 15:33:57 -0700256 bool Worker(PassDataHolder* data) const;
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800257};
258
259/**
260 * @class BasicBlock Optimizations
261 * @brief Any simple BasicBlock optimization can be put here.
262 */
James C Scott4f596682014-05-01 05:52:04 -0700263class BBOptimizations : public PassME {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800264 public:
James C Scott4f596682014-05-01 05:52:04 -0700265 BBOptimizations() : PassME("BBOptimizations", kNoNodes, "5_post_bbo_cfg") {
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800266 }
267
James C Scott4f596682014-05-01 05:52:04 -0700268 bool Gate(const PassDataHolder* data) const {
269 DCHECK(data != nullptr);
Jean Christophe Beyler75bcc372014-09-04 08:15:11 -0700270 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
271 DCHECK(c_unit != nullptr);
272 return ((c_unit->disable_opt & (1 << kBBOpt)) == 0);
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800273 }
274
Jean Christophe Beylere1f65bc2014-06-09 10:18:26 -0700275 void Start(PassDataHolder* data) const;
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800276};
277
278} // namespace art
279
280#endif // ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_