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_PASS_DRIVER_ME_H_ 18 #define ART_COMPILER_DEX_PASS_DRIVER_ME_H_ 19 20 #include "bb_optimizations.h" 21 #include "dataflow_iterator.h" 22 #include "dataflow_iterator-inl.h" 23 #include "pass_driver.h" 24 #include "pass_me.h" 25 26 namespace art { 27 28 template <typename PassDriverType> 29 class PassDriverME: public PassDriver<PassDriverType> { 30 public: PassDriverME(CompilationUnit * cu)31 explicit PassDriverME(CompilationUnit* cu) 32 : pass_me_data_holder_(), dump_cfg_folder_("/sdcard/") { 33 pass_me_data_holder_.bb = nullptr; 34 pass_me_data_holder_.c_unit = cu; 35 } 36 ~PassDriverME()37 ~PassDriverME() { 38 } 39 DispatchPass(const Pass * pass)40 void DispatchPass(const Pass* pass) { 41 VLOG(compiler) << "Dispatching " << pass->GetName(); 42 const PassME* me_pass = down_cast<const PassME*>(pass); 43 44 DataFlowAnalysisMode mode = me_pass->GetTraversal(); 45 46 switch (mode) { 47 case kPreOrderDFSTraversal: 48 DoWalkBasicBlocks<PreOrderDfsIterator>(&pass_me_data_holder_, me_pass); 49 break; 50 case kRepeatingPreOrderDFSTraversal: 51 DoWalkBasicBlocks<RepeatingPreOrderDfsIterator>(&pass_me_data_holder_, me_pass); 52 break; 53 case kRepeatingPostOrderDFSTraversal: 54 DoWalkBasicBlocks<RepeatingPostOrderDfsIterator>(&pass_me_data_holder_, me_pass); 55 break; 56 case kReversePostOrderDFSTraversal: 57 DoWalkBasicBlocks<ReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass); 58 break; 59 case kRepeatingReversePostOrderDFSTraversal: 60 DoWalkBasicBlocks<RepeatingReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass); 61 break; 62 case kPostOrderDOMTraversal: 63 DoWalkBasicBlocks<PostOrderDOMIterator>(&pass_me_data_holder_, me_pass); 64 break; 65 case kTopologicalSortTraversal: 66 DoWalkBasicBlocks<TopologicalSortIterator>(&pass_me_data_holder_, me_pass); 67 break; 68 case kRepeatingTopologicalSortTraversal: 69 DoWalkBasicBlocks<RepeatingTopologicalSortIterator>(&pass_me_data_holder_, me_pass); 70 break; 71 case kLoopRepeatingTopologicalSortTraversal: 72 DoWalkBasicBlocks<LoopRepeatingTopologicalSortIterator>(&pass_me_data_holder_, me_pass); 73 break; 74 case kAllNodes: 75 DoWalkBasicBlocks<AllNodesIterator>(&pass_me_data_holder_, me_pass); 76 break; 77 case kNoNodes: 78 break; 79 default: 80 LOG(FATAL) << "Iterator mode not handled in dispatcher: " << mode; 81 break; 82 } 83 } 84 RunPass(const Pass * pass,bool time_split)85 bool RunPass(const Pass* pass, bool time_split) { 86 // Paranoid: c_unit and pass cannot be nullptr, and the pass should have a name 87 DCHECK(pass != nullptr); 88 DCHECK(pass->GetName() != nullptr && pass->GetName()[0] != 0); 89 CompilationUnit* c_unit = pass_me_data_holder_.c_unit; 90 DCHECK(c_unit != nullptr); 91 92 // Do we perform a time split 93 if (time_split) { 94 c_unit->NewTimingSplit(pass->GetName()); 95 } 96 97 // Check the pass gate first. 98 bool should_apply_pass = pass->Gate(&pass_me_data_holder_); 99 if (should_apply_pass) { 100 bool old_print_pass = c_unit->print_pass; 101 102 c_unit->print_pass = PassDriver<PassDriverType>::default_print_passes_; 103 104 const char* print_pass_list = PassDriver<PassDriverType>::print_pass_list_.c_str(); 105 106 if (print_pass_list != nullptr && strstr(print_pass_list, pass->GetName()) != nullptr) { 107 c_unit->print_pass = true; 108 } 109 110 // Applying the pass: first start, doWork, and end calls. 111 this->ApplyPass(&pass_me_data_holder_, pass); 112 113 bool should_dump = ((c_unit->enable_debug & (1 << kDebugDumpCFG)) != 0); 114 115 const char* dump_pass_list = PassDriver<PassDriverType>::dump_pass_list_.c_str(); 116 117 if (dump_pass_list != nullptr) { 118 bool found = strstr(dump_pass_list, pass->GetName()); 119 should_dump = (should_dump || found); 120 } 121 122 if (should_dump) { 123 // Do we want to log it? 124 if ((c_unit->enable_debug& (1 << kDebugDumpCFG)) != 0) { 125 // Do we have a pass folder? 126 const PassME* me_pass = (down_cast<const PassME*>(pass)); 127 const char* passFolder = me_pass->GetDumpCFGFolder(); 128 DCHECK(passFolder != nullptr); 129 130 if (passFolder[0] != 0) { 131 // Create directory prefix. 132 std::string prefix = GetDumpCFGFolder(); 133 prefix += passFolder; 134 prefix += "/"; 135 136 c_unit->mir_graph->DumpCFG(prefix.c_str(), false); 137 } 138 } 139 } 140 141 c_unit->print_pass = old_print_pass; 142 } 143 144 // If the pass gate passed, we can declare success. 145 return should_apply_pass; 146 } 147 GetDumpCFGFolder()148 const char* GetDumpCFGFolder() const { 149 return dump_cfg_folder_; 150 } 151 152 protected: 153 /** @brief The data holder that contains data needed for the PassDriverME. */ 154 PassMEDataHolder pass_me_data_holder_; 155 156 /** @brief Dump CFG base folder: where is the base folder for dumping CFGs. */ 157 const char* dump_cfg_folder_; 158 DoWalkBasicBlocks(PassMEDataHolder * data,const PassME * pass,DataflowIterator * iterator)159 static void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass, 160 DataflowIterator* iterator) { 161 // Paranoid: Check the iterator before walking the BasicBlocks. 162 DCHECK(iterator != nullptr); 163 bool change = false; 164 for (BasicBlock* bb = iterator->Next(change); bb != nullptr; bb = iterator->Next(change)) { 165 data->bb = bb; 166 change = pass->Worker(data); 167 } 168 } 169 170 template <typename Iterator> DoWalkBasicBlocks(PassMEDataHolder * data,const PassME * pass)171 inline static void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass) { 172 DCHECK(data != nullptr); 173 CompilationUnit* c_unit = data->c_unit; 174 DCHECK(c_unit != nullptr); 175 Iterator iterator(c_unit->mir_graph.get()); 176 DoWalkBasicBlocks(data, pass, &iterator); 177 } 178 }; 179 } // namespace art 180 #endif // ART_COMPILER_DEX_PASS_DRIVER_ME_H_ 181 182