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_POST_OPT_PASSES_H_ 18 #define ART_COMPILER_DEX_POST_OPT_PASSES_H_ 19 20 #include "compiler_internals.h" 21 #include "pass_me.h" 22 23 namespace art { 24 25 /** 26 * @class InitializeData 27 * @brief There is some data that needs to be initialized before performing 28 * the post optimization passes. 29 */ 30 class InitializeData : public PassME { 31 public: InitializeData()32 InitializeData() : PassME("InitializeData") { 33 } 34 Start(PassDataHolder * data)35 void Start(PassDataHolder* data) const { 36 // New blocks may have been inserted so the first thing we do is ensure that 37 // the c_unit's number of blocks matches the actual count of basic blocks. 38 DCHECK(data != nullptr); 39 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 40 DCHECK(c_unit != nullptr); 41 c_unit->mir_graph.get()->InitializeBasicBlockData(); 42 c_unit->mir_graph.get()->SSATransformationStart(); 43 } 44 }; 45 46 /** 47 * @class MethodUseCount 48 * @brief Count the register uses of the method 49 */ 50 class MethodUseCount : public PassME { 51 public: MethodUseCount()52 MethodUseCount() : PassME("UseCount") { 53 } 54 55 bool Worker(const PassDataHolder* data) const; 56 57 bool Gate(const PassDataHolder* data) const; 58 }; 59 60 /** 61 * @class ClearPhiInformation 62 * @brief Clear the PHI nodes from the CFG. 63 */ 64 class ClearPhiInstructions : public PassME { 65 public: ClearPhiInstructions()66 ClearPhiInstructions() : PassME("ClearPhiInstructions") { 67 } 68 69 bool Worker(const PassDataHolder* data) const; 70 }; 71 72 /** 73 * @class CalculatePredecessors 74 * @brief Calculate the predecessor BitVector of each Basicblock. 75 */ 76 class CalculatePredecessors : public PassME { 77 public: CalculatePredecessors()78 CalculatePredecessors() : PassME("CalculatePredecessors") { 79 } 80 81 void Start(PassDataHolder* data) const; 82 }; 83 84 /** 85 * @class DFSOrders 86 * @brief Compute the DFS order of the MIR graph 87 */ 88 class DFSOrders : public PassME { 89 public: DFSOrders()90 DFSOrders() : PassME("DFSOrders") { 91 } 92 Start(PassDataHolder * data)93 void Start(PassDataHolder* data) const { 94 DCHECK(data != nullptr); 95 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 96 DCHECK(c_unit != nullptr); 97 c_unit->mir_graph.get()->ComputeDFSOrders(); 98 } 99 }; 100 101 /** 102 * @class BuildDomination 103 * @brief Build the domination information of the MIR Graph 104 */ 105 class BuildDomination : public PassME { 106 public: BuildDomination()107 BuildDomination() : PassME("BuildDomination") { 108 } 109 Start(PassDataHolder * data)110 void Start(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.get()->ComputeDominators(); 115 c_unit->mir_graph.get()->CompilerInitializeSSAConversion(); 116 } 117 End(PassDataHolder * data)118 void End(PassDataHolder* data) const { 119 DCHECK(data != nullptr); 120 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 121 DCHECK(c_unit != nullptr); 122 // Verify the dataflow information after the pass. 123 if (c_unit->enable_debug & (1 << kDebugVerifyDataflow)) { 124 c_unit->mir_graph->VerifyDataflow(); 125 } 126 } 127 }; 128 129 /** 130 * @class TopologicalSortOrders 131 * @brief Compute the topological sort order of the MIR graph 132 */ 133 class TopologicalSortOrders : public PassME { 134 public: TopologicalSortOrders()135 TopologicalSortOrders() : PassME("TopologicalSortOrders") { 136 } 137 Start(PassDataHolder * data)138 void Start(PassDataHolder* data) const { 139 DCHECK(data != nullptr); 140 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 141 DCHECK(c_unit != nullptr); 142 c_unit->mir_graph.get()->ComputeTopologicalSortOrder(); 143 } 144 }; 145 146 /** 147 * @class DefBlockMatrix 148 * @brief Calculate the matrix of definition per basic block 149 */ 150 class DefBlockMatrix : public PassME { 151 public: DefBlockMatrix()152 DefBlockMatrix() : PassME("DefBlockMatrix") { 153 } 154 Start(PassDataHolder * data)155 void Start(PassDataHolder* data) const { 156 DCHECK(data != nullptr); 157 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 158 DCHECK(c_unit != nullptr); 159 c_unit->mir_graph.get()->ComputeDefBlockMatrix(); 160 } 161 }; 162 163 /** 164 * @class CreatePhiNodes 165 * @brief Pass to create the phi nodes after SSA calculation 166 */ 167 class CreatePhiNodes : public PassME { 168 public: CreatePhiNodes()169 CreatePhiNodes() : PassME("CreatePhiNodes") { 170 } 171 Start(PassDataHolder * data)172 void Start(PassDataHolder* data) const { 173 DCHECK(data != nullptr); 174 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 175 DCHECK(c_unit != nullptr); 176 c_unit->mir_graph.get()->InsertPhiNodes(); 177 } 178 }; 179 180 /** 181 * @class ClearVisitedFlag 182 * @brief Pass to clear the visited flag for all basic blocks. 183 */ 184 185 class ClearVisitedFlag : public PassME { 186 public: ClearVisitedFlag()187 ClearVisitedFlag() : PassME("ClearVisitedFlag") { 188 } 189 Start(PassDataHolder * data)190 void Start(PassDataHolder* data) const { 191 DCHECK(data != nullptr); 192 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 193 DCHECK(c_unit != nullptr); 194 c_unit->mir_graph.get()->ClearAllVisitedFlags(); 195 } 196 }; 197 198 /** 199 * @class SSAConversion 200 * @brief Pass for SSA conversion of MIRs 201 */ 202 class SSAConversion : public PassME { 203 public: SSAConversion()204 SSAConversion() : PassME("SSAConversion") { 205 } 206 Start(PassDataHolder * data)207 void Start(PassDataHolder* data) const { 208 DCHECK(data != nullptr); 209 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 210 DCHECK(c_unit != nullptr); 211 MIRGraph *mir_graph = c_unit->mir_graph.get(); 212 mir_graph->DoDFSPreOrderSSARename(mir_graph->GetEntryBlock()); 213 } 214 }; 215 216 /** 217 * @class PhiNodeOperands 218 * @brief Pass to insert the Phi node operands to basic blocks 219 */ 220 class PhiNodeOperands : public PassME { 221 public: PhiNodeOperands()222 PhiNodeOperands() : PassME("PhiNodeOperands", kPreOrderDFSTraversal) { 223 } 224 Worker(const PassDataHolder * data)225 bool Worker(const PassDataHolder* data) const { 226 DCHECK(data != nullptr); 227 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; 228 DCHECK(c_unit != nullptr); 229 BasicBlock* bb = down_cast<const PassMEDataHolder*>(data)->bb; 230 DCHECK(bb != nullptr); 231 c_unit->mir_graph->InsertPhiNodeOperands(bb); 232 // No need of repeating, so just return false. 233 return false; 234 } 235 }; 236 237 /** 238 * @class InitRegLocations 239 * @brief Initialize Register Locations. 240 */ 241 class PerformInitRegLocations : public PassME { 242 public: PerformInitRegLocations()243 PerformInitRegLocations() : PassME("PerformInitRegLocation") { 244 } 245 Start(PassDataHolder * data)246 void Start(PassDataHolder* data) const { 247 DCHECK(data != nullptr); 248 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 249 DCHECK(c_unit != nullptr); 250 c_unit->mir_graph->InitRegLocations(); 251 } 252 }; 253 254 /** 255 * @class ConstantPropagation 256 * @brief Perform a constant propagation pass. 257 */ 258 class ConstantPropagation : public PassME { 259 public: ConstantPropagation()260 ConstantPropagation() : PassME("ConstantPropagation") { 261 } 262 Worker(const PassDataHolder * data)263 bool Worker(const PassDataHolder* data) const { 264 DCHECK(data != nullptr); 265 CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; 266 DCHECK(c_unit != nullptr); 267 BasicBlock* bb = down_cast<const PassMEDataHolder*>(data)->bb; 268 DCHECK(bb != nullptr); 269 c_unit->mir_graph->DoConstantPropagation(bb); 270 // No need of repeating, so just return false. 271 return false; 272 } 273 Start(PassDataHolder * data)274 void Start(PassDataHolder* data) const { 275 DCHECK(data != nullptr); 276 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 277 DCHECK(c_unit != nullptr); 278 c_unit->mir_graph->InitializeConstantPropagation(); 279 } 280 }; 281 282 /** 283 * @class FreeData 284 * @brief There is some data that needs to be freed after performing the post optimization passes. 285 */ 286 class FreeData : public PassME { 287 public: FreeData()288 FreeData() : PassME("FreeData") { 289 } 290 End(PassDataHolder * data)291 void End(PassDataHolder* data) const { 292 DCHECK(data != nullptr); 293 CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit; 294 DCHECK(c_unit != nullptr); 295 c_unit->mir_graph.get()->SSATransformationEnd(); 296 } 297 }; 298 299 } // namespace art 300 301 #endif // ART_COMPILER_DEX_POST_OPT_PASSES_H_ 302