blob: 031c5cf87d42bc01a7376a54c5ecde275ab758d7 [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;
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070071 case kAllNodes:
72 DoWalkBasicBlocks<AllNodesIterator>(&pass_me_data_holder_, me_pass);
73 break;
74 case kNoNodes:
75 break;
76 default:
77 LOG(FATAL) << "Iterator mode not handled in dispatcher: " << mode;
78 break;
79 }
80 }
81
82 bool RunPass(const Pass* pass, bool time_split) {
83 // Paranoid: c_unit and pass cannot be nullptr, and the pass should have a name
84 DCHECK(pass != nullptr);
85 DCHECK(pass->GetName() != nullptr && pass->GetName()[0] != 0);
86 CompilationUnit* c_unit = pass_me_data_holder_.c_unit;
87 DCHECK(c_unit != nullptr);
88
89 // Do we perform a time split
90 if (time_split) {
91 c_unit->NewTimingSplit(pass->GetName());
92 }
93
94 // Check the pass gate first.
95 bool should_apply_pass = pass->Gate(&pass_me_data_holder_);
96 if (should_apply_pass) {
97 bool old_print_pass = c_unit->print_pass;
98
99 c_unit->print_pass = PassDriver<PassDriverType>::default_print_passes_;
100
101 const char* print_pass_list = PassDriver<PassDriverType>::print_pass_list_.c_str();
102
103 if (print_pass_list != nullptr && strstr(print_pass_list, pass->GetName()) != nullptr) {
104 c_unit->print_pass = true;
105 }
106
107 // Applying the pass: first start, doWork, and end calls.
108 this->ApplyPass(&pass_me_data_holder_, pass);
109
110 bool should_dump = ((c_unit->enable_debug & (1 << kDebugDumpCFG)) != 0);
111
112 const char* dump_pass_list = PassDriver<PassDriverType>::dump_pass_list_.c_str();
113
114 if (dump_pass_list != nullptr) {
115 bool found = strstr(dump_pass_list, pass->GetName());
116 should_dump = (should_dump || found);
117 }
118
119 if (should_dump) {
120 // Do we want to log it?
121 if ((c_unit->enable_debug& (1 << kDebugDumpCFG)) != 0) {
122 // Do we have a pass folder?
123 const PassME* me_pass = (down_cast<const PassME*>(pass));
124 const char* passFolder = me_pass->GetDumpCFGFolder();
125 DCHECK(passFolder != nullptr);
126
127 if (passFolder[0] != 0) {
128 // Create directory prefix.
129 std::string prefix = GetDumpCFGFolder();
130 prefix += passFolder;
131 prefix += "/";
132
133 c_unit->mir_graph->DumpCFG(prefix.c_str(), false);
134 }
135 }
136 }
137
138 c_unit->print_pass = old_print_pass;
139 }
140
141 // If the pass gate passed, we can declare success.
142 return should_apply_pass;
143 }
144
145 const char* GetDumpCFGFolder() const {
146 return dump_cfg_folder_;
147 }
148
James C Scott4f596682014-05-01 05:52:04 -0700149 protected:
150 /** @brief The data holder that contains data needed for the PassDriverME. */
151 PassMEDataHolder pass_me_data_holder_;
152
153 /** @brief Dump CFG base folder: where is the base folder for dumping CFGs. */
154 const char* dump_cfg_folder_;
James C Scott4f596682014-05-01 05:52:04 -0700155
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700156 static void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass,
157 DataflowIterator* iterator) {
158 // Paranoid: Check the iterator before walking the BasicBlocks.
159 DCHECK(iterator != nullptr);
160 bool change = false;
161 for (BasicBlock* bb = iterator->Next(change); bb != nullptr; bb = iterator->Next(change)) {
162 data->bb = bb;
163 change = pass->Worker(data);
164 }
165 }
166
167 template <typename Iterator>
168 inline static void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass) {
169 DCHECK(data != nullptr);
170 CompilationUnit* c_unit = data->c_unit;
171 DCHECK(c_unit != nullptr);
172 Iterator iterator(c_unit->mir_graph.get());
173 DoWalkBasicBlocks(data, pass, &iterator);
174 }
175};
James C Scott4f596682014-05-01 05:52:04 -0700176} // namespace art
177#endif // ART_COMPILER_DEX_PASS_DRIVER_ME_H_
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700178