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