• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
20 #include "compiler_internals.h"
21 #include "pass_me.h"
22 
23 namespace art {
24 
25 /**
26  * @class CacheFieldLoweringInfo
27  * @brief Cache the lowering info for fields used by IGET/IPUT/SGET/SPUT insns.
28  */
29 class CacheFieldLoweringInfo : public PassME {
30  public:
CacheFieldLoweringInfo()31   CacheFieldLoweringInfo() : PassME("CacheFieldLoweringInfo", kNoNodes) {
32   }
33 
Start(PassDataHolder * data)34   void Start(PassDataHolder* data) const {
35     DCHECK(data != nullptr);
36     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
37     DCHECK(cUnit != nullptr);
38     cUnit->mir_graph->DoCacheFieldLoweringInfo();
39   }
40 
Gate(const PassDataHolder * data)41   bool Gate(const PassDataHolder* data) const {
42     DCHECK(data != nullptr);
43     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
44     DCHECK(cUnit != nullptr);
45     return cUnit->mir_graph->HasFieldAccess();
46   }
47 };
48 
49 /**
50  * @class CacheMethodLoweringInfo
51  * @brief Cache the lowering info for methods called by INVOKEs.
52  */
53 class CacheMethodLoweringInfo : public PassME {
54  public:
CacheMethodLoweringInfo()55   CacheMethodLoweringInfo() : PassME("CacheMethodLoweringInfo", kNoNodes) {
56   }
57 
Start(PassDataHolder * data)58   void Start(PassDataHolder* data) const {
59     DCHECK(data != nullptr);
60     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
61     DCHECK(cUnit != nullptr);
62     cUnit->mir_graph->DoCacheMethodLoweringInfo();
63   }
64 
Gate(const PassDataHolder * data)65   bool Gate(const PassDataHolder* data) const {
66     DCHECK(data != nullptr);
67     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
68     DCHECK(cUnit != nullptr);
69     return cUnit->mir_graph->HasInvokes();
70   }
71 };
72 
73 /**
74  * @class SpecialMethodInliner
75  * @brief Performs method inlining pass on special kinds of methods.
76  * @details Special methods are methods that fall in one of the following categories:
77  * empty, instance getter, instance setter, argument return, and constant return.
78  */
79 class SpecialMethodInliner : public PassME {
80  public:
SpecialMethodInliner()81   SpecialMethodInliner() : PassME("SpecialMethodInliner") {
82   }
83 
Gate(const PassDataHolder * data)84   bool Gate(const PassDataHolder* data) const {
85     DCHECK(data != nullptr);
86     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
87     DCHECK(cUnit != nullptr);
88     return cUnit->mir_graph->InlineSpecialMethodsGate();
89   }
90 
Start(PassDataHolder * data)91   void Start(PassDataHolder* data) const {
92     DCHECK(data != nullptr);
93     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
94     DCHECK(cUnit != nullptr);
95     cUnit->mir_graph->InlineSpecialMethodsStart();
96   }
97 
Worker(const PassDataHolder * data)98   bool Worker(const PassDataHolder* data) const {
99     DCHECK(data != nullptr);
100     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
101     CompilationUnit* cUnit = pass_me_data_holder->c_unit;
102     DCHECK(cUnit != nullptr);
103     BasicBlock* bb = pass_me_data_holder->bb;
104     DCHECK(bb != nullptr);
105     cUnit->mir_graph->InlineSpecialMethods(bb);
106     // No need of repeating, so just return false.
107     return false;
108   }
109 
End(PassDataHolder * data)110   void End(PassDataHolder* data) const {
111     DCHECK(data != nullptr);
112     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
113     DCHECK(cUnit != nullptr);
114     cUnit->mir_graph->InlineSpecialMethodsEnd();
115   }
116 };
117 
118 /**
119  * @class CodeLayout
120  * @brief Perform the code layout pass.
121  */
122 class CodeLayout : public PassME {
123  public:
CodeLayout()124   CodeLayout() : PassME("CodeLayout", kAllNodes, kOptimizationBasicBlockChange, "2_post_layout_cfg") {
125   }
126 
Start(PassDataHolder * data)127   void Start(PassDataHolder* data) const {
128     DCHECK(data != nullptr);
129     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
130     DCHECK(cUnit != nullptr);
131     cUnit->mir_graph->VerifyDataflow();
132   }
133 
134   bool Worker(const PassDataHolder* data) const;
135 };
136 
137 /**
138  * @class NullCheckEliminationAndTypeInference
139  * @brief Null check elimination and type inference.
140  */
141 class NullCheckEliminationAndTypeInference : public PassME {
142  public:
NullCheckEliminationAndTypeInference()143   NullCheckEliminationAndTypeInference()
144     : PassME("NCE_TypeInference", kRepeatingTopologicalSortTraversal, "4_post_nce_cfg") {
145   }
146 
Start(PassDataHolder * data)147   void Start(PassDataHolder* data) const {
148     DCHECK(data != nullptr);
149     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
150     DCHECK(cUnit != nullptr);
151     cUnit->mir_graph->EliminateNullChecksAndInferTypesStart();
152   }
153 
Worker(const PassDataHolder * data)154   bool Worker(const PassDataHolder* data) const {
155     DCHECK(data != nullptr);
156     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
157     CompilationUnit* cUnit = pass_me_data_holder->c_unit;
158     DCHECK(cUnit != nullptr);
159     BasicBlock* bb = pass_me_data_holder->bb;
160     DCHECK(bb != nullptr);
161     return cUnit->mir_graph->EliminateNullChecksAndInferTypes(bb);
162   }
163 
End(PassDataHolder * data)164   void End(PassDataHolder* data) const {
165     DCHECK(data != nullptr);
166     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
167     DCHECK(cUnit != nullptr);
168     cUnit->mir_graph->EliminateNullChecksAndInferTypesEnd();
169   }
170 };
171 
172 class ClassInitCheckElimination : public PassME {
173  public:
ClassInitCheckElimination()174   ClassInitCheckElimination()
175     : PassME("ClInitCheckElimination", kLoopRepeatingTopologicalSortTraversal) {
176   }
177 
Gate(const PassDataHolder * data)178   bool Gate(const PassDataHolder* data) const {
179     DCHECK(data != nullptr);
180     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
181     DCHECK(cUnit != nullptr);
182     return cUnit->mir_graph->EliminateClassInitChecksGate();
183   }
184 
Worker(const PassDataHolder * data)185   bool Worker(const PassDataHolder* data) const {
186     DCHECK(data != nullptr);
187     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
188     CompilationUnit* cUnit = pass_me_data_holder->c_unit;
189     DCHECK(cUnit != nullptr);
190     BasicBlock* bb = pass_me_data_holder->bb;
191     DCHECK(bb != nullptr);
192     return cUnit->mir_graph->EliminateClassInitChecks(bb);
193   }
194 
End(PassDataHolder * data)195   void End(PassDataHolder* data) const {
196     DCHECK(data != nullptr);
197     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
198     DCHECK(cUnit != nullptr);
199     cUnit->mir_graph->EliminateClassInitChecksEnd();
200   }
201 };
202 
203 /**
204  * @class GlobalValueNumberingPass
205  * @brief Performs the global value numbering pass.
206  */
207 class GlobalValueNumberingPass : public PassME {
208  public:
GlobalValueNumberingPass()209   GlobalValueNumberingPass()
210     : PassME("GVN", kLoopRepeatingTopologicalSortTraversal, "4_post_gvn_cfg") {
211   }
212 
Gate(const PassDataHolder * data)213   bool Gate(const PassDataHolder* data) const OVERRIDE {
214     DCHECK(data != nullptr);
215     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
216     DCHECK(cUnit != nullptr);
217     return cUnit->mir_graph->ApplyGlobalValueNumberingGate();
218   }
219 
Worker(const PassDataHolder * data)220   bool Worker(const PassDataHolder* data) const OVERRIDE {
221     DCHECK(data != nullptr);
222     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
223     CompilationUnit* cUnit = pass_me_data_holder->c_unit;
224     DCHECK(cUnit != nullptr);
225     BasicBlock* bb = pass_me_data_holder->bb;
226     DCHECK(bb != nullptr);
227     return cUnit->mir_graph->ApplyGlobalValueNumbering(bb);
228   }
229 
End(PassDataHolder * data)230   void End(PassDataHolder* data) const OVERRIDE {
231     DCHECK(data != nullptr);
232     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
233     DCHECK(cUnit != nullptr);
234     cUnit->mir_graph->ApplyGlobalValueNumberingEnd();
235   }
236 };
237 
238 /**
239  * @class BBCombine
240  * @brief Perform the basic block combination pass.
241  */
242 class BBCombine : public PassME {
243  public:
BBCombine()244   BBCombine() : PassME("BBCombine", kPreOrderDFSTraversal, "5_post_bbcombine_cfg") {
245   }
246 
Gate(const PassDataHolder * data)247   bool Gate(const PassDataHolder* data) const {
248     DCHECK(data != nullptr);
249     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
250     DCHECK(cUnit != nullptr);
251     return ((cUnit->disable_opt & (1 << kSuppressExceptionEdges)) != 0);
252   }
253 
254   bool Worker(const PassDataHolder* data) const;
255 };
256 
257 /**
258  * @class BasicBlock Optimizations
259  * @brief Any simple BasicBlock optimization can be put here.
260  */
261 class BBOptimizations : public PassME {
262  public:
BBOptimizations()263   BBOptimizations() : PassME("BBOptimizations", kNoNodes, "5_post_bbo_cfg") {
264   }
265 
Gate(const PassDataHolder * data)266   bool Gate(const PassDataHolder* data) const {
267     DCHECK(data != nullptr);
268     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
269     DCHECK(cUnit != nullptr);
270     return ((cUnit->disable_opt & (1 << kBBOpt)) == 0);
271   }
272 
273   void Start(PassDataHolder* data) const;
274 };
275 
276 }  // namespace art
277 
278 #endif  // ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
279