pass_driver_me.h revision 1fd4821f6b3ac57a44c2ce91025686da4641d197
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
26namespace art {
27
28template <typename PassDriverType>
29class PassDriverME: public PassDriver<PassDriverType> {
30 public:
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
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 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
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
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
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>
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