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: 31 CacheFieldLoweringInfo() : PassME("CacheFieldLoweringInfo", kNoNodes) { 32 } 33 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 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: 55 CacheMethodLoweringInfo() : PassME("CacheMethodLoweringInfo", kNoNodes) { 56 } 57 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 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: 81 SpecialMethodInliner() : PassME("SpecialMethodInliner") { 82 } 83 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 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 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 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: 124 CodeLayout() : PassME("CodeLayout", kAllNodes, kOptimizationBasicBlockChange, "2_post_layout_cfg") { 125 } 126 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: 143 NullCheckEliminationAndTypeInference() 144 : PassME("NCE_TypeInference", kRepeatingTopologicalSortTraversal, "4_post_nce_cfg") { 145 } 146 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 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 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: 174 ClassInitCheckElimination() 175 : PassME("ClInitCheckElimination", kLoopRepeatingTopologicalSortTraversal) { 176 } 177 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 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 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: 209 GlobalValueNumberingPass() 210 : PassME("GVN", kLoopRepeatingTopologicalSortTraversal, "4_post_gvn_cfg") { 211 } 212 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 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 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: 244 BBCombine() : PassME("BBCombine", kPreOrderDFSTraversal, "5_post_bbcombine_cfg") { 245 } 246 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: 263 BBOptimizations() : PassME("BBOptimizations", kNoNodes, "5_post_bbo_cfg") { 264 } 265 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