blob: 133593ceb9d255a1a61c354eb9f98971e822247a [file] [log] [blame]
James C Scott4f596682014-05-01 05:52:04 -07001/*
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"
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070021#include "dataflow_iterator.h"
22#include "dataflow_iterator-inl.h"
James C Scott4f596682014-05-01 05:52:04 -070023#include "pass_driver.h"
24#include "pass_me.h"
25
26namespace art {
27
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070028template <typename PassDriverType>
29class PassDriverME: public PassDriver<PassDriverType> {
James C Scott4f596682014-05-01 05:52:04 -070030 public:
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070031 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
37 ~PassDriverME() {
38 }
39
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;
Vladimir Marko622bdbe2014-06-19 14:59:05 +010065 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;
Vladimir Marko55fff042014-07-10 12:42:52 +010071 case kLoopRepeatingTopologicalSortTraversal:
72 DoWalkBasicBlocks<LoopRepeatingTopologicalSortIterator>(&pass_me_data_holder_, me_pass);
73 break;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070074 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
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
148 const char* GetDumpCFGFolder() const {
149 return dump_cfg_folder_;
150 }
151
James C Scott4f596682014-05-01 05:52:04 -0700152 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_;
James C Scott4f596682014-05-01 05:52:04 -0700158
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700159 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>
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};
James C Scott4f596682014-05-01 05:52:04 -0700179} // namespace art
180#endif // ART_COMPILER_DEX_PASS_DRIVER_ME_H_
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700181