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* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 37 DCHECK(c_unit != nullptr); 38 c_unit->mir_graph->DoCacheFieldLoweringInfo(); 39 } 40 Gate(const PassDataHolder * data)41 bool Gate(const PassDataHolder* data) const { 42 DCHECK(data != nullptr); 43 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; 44 DCHECK(c_unit != nullptr); 45 return c_unit->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* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 61 DCHECK(c_unit != nullptr); 62 c_unit->mir_graph->DoCacheMethodLoweringInfo(); 63 } 64 Gate(const PassDataHolder * data)65 bool Gate(const PassDataHolder* data) const { 66 DCHECK(data != nullptr); 67 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; 68 DCHECK(c_unit != nullptr); 69 return c_unit->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* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; 87 DCHECK(c_unit != nullptr); 88 return c_unit->mir_graph->InlineSpecialMethodsGate(); 89 } 90 Start(PassDataHolder * data)91 void Start(PassDataHolder* data) const { 92 DCHECK(data != nullptr); 93 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 94 DCHECK(c_unit != nullptr); 95 c_unit->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* c_unit = pass_me_data_holder->c_unit; 102 DCHECK(c_unit != nullptr); 103 BasicBlock* bb = pass_me_data_holder->bb; 104 DCHECK(bb != nullptr); 105 c_unit->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* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 113 DCHECK(c_unit != nullptr); 114 c_unit->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* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 130 DCHECK(c_unit != nullptr); 131 c_unit->mir_graph->VerifyDataflow(); 132 c_unit->mir_graph->ClearAllVisitedFlags(); 133 } 134 135 bool Worker(const PassDataHolder* data) const; 136 }; 137 138 /** 139 * @class NullCheckEliminationAndTypeInference 140 * @brief Null check elimination and type inference. 141 */ 142 class NullCheckEliminationAndTypeInference : public PassME { 143 public: NullCheckEliminationAndTypeInference()144 NullCheckEliminationAndTypeInference() 145 : PassME("NCE_TypeInference", kRepeatingTopologicalSortTraversal, "4_post_nce_cfg") { 146 } 147 Start(PassDataHolder * data)148 void Start(PassDataHolder* data) const { 149 DCHECK(data != nullptr); 150 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 151 DCHECK(c_unit != nullptr); 152 c_unit->mir_graph->EliminateNullChecksAndInferTypesStart(); 153 } 154 Worker(const PassDataHolder * data)155 bool Worker(const PassDataHolder* data) const { 156 DCHECK(data != nullptr); 157 const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data); 158 CompilationUnit* c_unit = pass_me_data_holder->c_unit; 159 DCHECK(c_unit != nullptr); 160 BasicBlock* bb = pass_me_data_holder->bb; 161 DCHECK(bb != nullptr); 162 return c_unit->mir_graph->EliminateNullChecksAndInferTypes(bb); 163 } 164 End(PassDataHolder * data)165 void End(PassDataHolder* data) const { 166 DCHECK(data != nullptr); 167 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 168 DCHECK(c_unit != nullptr); 169 c_unit->mir_graph->EliminateNullChecksAndInferTypesEnd(); 170 } 171 }; 172 173 class ClassInitCheckElimination : public PassME { 174 public: ClassInitCheckElimination()175 ClassInitCheckElimination() 176 : PassME("ClInitCheckElimination", kLoopRepeatingTopologicalSortTraversal) { 177 } 178 Gate(const PassDataHolder * data)179 bool Gate(const PassDataHolder* data) const { 180 DCHECK(data != nullptr); 181 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; 182 DCHECK(c_unit != nullptr); 183 return c_unit->mir_graph->EliminateClassInitChecksGate(); 184 } 185 Worker(const PassDataHolder * data)186 bool Worker(const PassDataHolder* data) const { 187 DCHECK(data != nullptr); 188 const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data); 189 CompilationUnit* c_unit = pass_me_data_holder->c_unit; 190 DCHECK(c_unit != nullptr); 191 BasicBlock* bb = pass_me_data_holder->bb; 192 DCHECK(bb != nullptr); 193 return c_unit->mir_graph->EliminateClassInitChecks(bb); 194 } 195 End(PassDataHolder * data)196 void End(PassDataHolder* data) const { 197 DCHECK(data != nullptr); 198 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 199 DCHECK(c_unit != nullptr); 200 c_unit->mir_graph->EliminateClassInitChecksEnd(); 201 } 202 }; 203 204 /** 205 * @class GlobalValueNumberingPass 206 * @brief Performs the global value numbering pass. 207 */ 208 class GlobalValueNumberingPass : public PassME { 209 public: GlobalValueNumberingPass()210 GlobalValueNumberingPass() 211 : PassME("GVN", kLoopRepeatingTopologicalSortTraversal, "4_post_gvn_cfg") { 212 } 213 Gate(const PassDataHolder * data)214 bool Gate(const PassDataHolder* data) const OVERRIDE { 215 DCHECK(data != nullptr); 216 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; 217 DCHECK(c_unit != nullptr); 218 return c_unit->mir_graph->ApplyGlobalValueNumberingGate(); 219 } 220 Worker(const PassDataHolder * data)221 bool Worker(const PassDataHolder* data) const OVERRIDE { 222 DCHECK(data != nullptr); 223 const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data); 224 CompilationUnit* c_unit = pass_me_data_holder->c_unit; 225 DCHECK(c_unit != nullptr); 226 BasicBlock* bb = pass_me_data_holder->bb; 227 DCHECK(bb != nullptr); 228 return c_unit->mir_graph->ApplyGlobalValueNumbering(bb); 229 } 230 End(PassDataHolder * data)231 void End(PassDataHolder* data) const OVERRIDE { 232 DCHECK(data != nullptr); 233 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 234 DCHECK(c_unit != nullptr); 235 c_unit->mir_graph->ApplyGlobalValueNumberingEnd(); 236 } 237 }; 238 239 /** 240 * @class BBCombine 241 * @brief Perform the basic block combination pass. 242 */ 243 class BBCombine : public PassME { 244 public: BBCombine()245 BBCombine() : PassME("BBCombine", kPreOrderDFSTraversal, "5_post_bbcombine_cfg") { 246 } 247 Gate(const PassDataHolder * data)248 bool Gate(const PassDataHolder* data) const { 249 DCHECK(data != nullptr); 250 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; 251 DCHECK(c_unit != nullptr); 252 return ((c_unit->disable_opt & (1 << kSuppressExceptionEdges)) != 0); 253 } 254 255 bool Worker(const PassDataHolder* data) const; 256 }; 257 258 /** 259 * @class BasicBlock Optimizations 260 * @brief Any simple BasicBlock optimization can be put here. 261 */ 262 class BBOptimizations : public PassME { 263 public: BBOptimizations()264 BBOptimizations() : PassME("BBOptimizations", kNoNodes, "5_post_bbo_cfg") { 265 } 266 Gate(const PassDataHolder * data)267 bool Gate(const PassDataHolder* data) const { 268 DCHECK(data != nullptr); 269 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; 270 DCHECK(c_unit != nullptr); 271 return ((c_unit->disable_opt & (1 << kBBOpt)) == 0); 272 } 273 274 void Start(PassDataHolder* data) const; 275 }; 276 277 } // namespace art 278 279 #endif // ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_ 280