• 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_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