blob: 79d8f5104fcfb51bf433288ed0bb8810d0a98429 [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_ME_H_
18#define ART_COMPILER_DEX_PASS_ME_H_
19
20#include <string>
Andreas Gampe0b9203e2015-01-22 20:39:27 -080021
22#include "base/logging.h"
James C Scott4f596682014-05-01 05:52:04 -070023#include "pass.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080024#include "safe_map.h"
James C Scott4f596682014-05-01 05:52:04 -070025
26namespace art {
27
28// Forward declarations.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070029class BasicBlock;
James C Scott4f596682014-05-01 05:52:04 -070030struct CompilationUnit;
James C Scott4f596682014-05-01 05:52:04 -070031
32/**
33 * @brief OptimizationFlag is an enumeration to perform certain tasks for a given pass.
34 * @details Each enum should be a power of 2 to be correctly used.
35 */
36enum OptimizationFlag {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070037 kOptimizationBasicBlockChange = 1, /// @brief Has there been a change to a BasicBlock?
38 kOptimizationDefUsesChange = 2, /// @brief Has there been a change to a def-use?
39 kLoopStructureChange = 4, /// @brief Has there been a loop structural change?
James C Scott4f596682014-05-01 05:52:04 -070040};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070041std::ostream& operator<<(std::ostream& os, const OptimizationFlag& rhs);
James C Scott4f596682014-05-01 05:52:04 -070042
43// Data holder class.
44class PassMEDataHolder: public PassDataHolder {
Mathieu Chartier5bdab122015-01-26 18:30:19 -080045 public:
46 CompilationUnit* c_unit;
47 BasicBlock* bb;
48 void* data; /**< @brief Any data the pass wants to use */
49 bool dirty; /**< @brief Has the pass rendered the CFG dirty, requiring post-opt? */
James C Scott4f596682014-05-01 05:52:04 -070050};
51
52enum DataFlowAnalysisMode {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070053 kAllNodes = 0, /// @brief All nodes.
54 kPreOrderDFSTraversal, /// @brief Depth-First-Search / Pre-Order.
55 kRepeatingPreOrderDFSTraversal, /// @brief Depth-First-Search / Repeating Pre-Order.
56 kReversePostOrderDFSTraversal, /// @brief Depth-First-Search / Reverse Post-Order.
57 kRepeatingPostOrderDFSTraversal, /// @brief Depth-First-Search / Repeating Post-Order.
58 kRepeatingReversePostOrderDFSTraversal, /// @brief Depth-First-Search / Repeating Reverse Post-Order.
59 kPostOrderDOMTraversal, /// @brief Dominator tree / Post-Order.
60 kTopologicalSortTraversal, /// @brief Topological Order traversal.
61 kLoopRepeatingTopologicalSortTraversal, /// @brief Loop-repeating Topological Order traversal.
62 kNoNodes, /// @brief Skip BasicBlock traversal.
James C Scott4f596682014-05-01 05:52:04 -070063};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070064std::ostream& operator<<(std::ostream& os, const DataFlowAnalysisMode& rhs);
James C Scott4f596682014-05-01 05:52:04 -070065
66/**
67 * @class Pass
68 * @brief Pass is the Pass structure for the optimizations.
69 * @details The following structure has the different optimization passes that we are going to do.
70 */
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070071class PassME : public Pass {
James C Scott4f596682014-05-01 05:52:04 -070072 public:
73 explicit PassME(const char* name, DataFlowAnalysisMode type = kAllNodes,
74 unsigned int flags = 0u, const char* dump = "")
75 : Pass(name), traversal_type_(type), flags_(flags), dump_cfg_folder_(dump) {
76 }
77
78 PassME(const char* name, DataFlowAnalysisMode type, const char* dump)
79 : Pass(name), traversal_type_(type), flags_(0), dump_cfg_folder_(dump) {
80 }
81
82 PassME(const char* name, const char* dump)
83 : Pass(name), traversal_type_(kAllNodes), flags_(0), dump_cfg_folder_(dump) {
84 }
85
86 ~PassME() {
Razvan A Lupusorubd25d4b2014-07-02 18:16:51 -070087 default_options_.clear();
James C Scott4f596682014-05-01 05:52:04 -070088 }
89
90 virtual DataFlowAnalysisMode GetTraversal() const {
91 return traversal_type_;
92 }
93
Razvan A Lupusorubd25d4b2014-07-02 18:16:51 -070094 /**
95 * @return Returns whether the pass has any configurable options.
96 */
97 bool HasOptions() const {
98 return default_options_.size() != 0;
99 }
100
101 /**
102 * @brief Prints the pass options along with default settings if there are any.
103 * @details The printing is done using LOG(INFO).
104 */
105 void PrintPassDefaultOptions() const {
Mathieu Chartier5bdab122015-01-26 18:30:19 -0800106 for (const auto& option : default_options_) {
107 LOG(INFO) << "\t" << option.first << ":" << std::dec << option.second;
Razvan A Lupusorubd25d4b2014-07-02 18:16:51 -0700108 }
109 }
110
111 /**
112 * @brief Prints the pass options along with either default or overridden setting.
113 * @param overridden_options The overridden settings for this pass.
114 */
115 void PrintPassOptions(SafeMap<const std::string, int>& overridden_options) const {
116 // We walk through the default options only to get the pass names. We use GetPassOption to
117 // also consider the overridden ones.
Mathieu Chartier5bdab122015-01-26 18:30:19 -0800118 for (const auto& option : default_options_) {
119 LOG(INFO) << "\t" << option.first << ":" << std::dec
120 << GetPassOption(option.first, overridden_options);
Razvan A Lupusorubd25d4b2014-07-02 18:16:51 -0700121 }
122 }
123
James C Scott4f596682014-05-01 05:52:04 -0700124 const char* GetDumpCFGFolder() const {
125 return dump_cfg_folder_;
126 }
127
128 bool GetFlag(OptimizationFlag flag) const {
129 return (flags_ & flag);
130 }
131
132 protected:
Razvan A Lupusorubd25d4b2014-07-02 18:16:51 -0700133 int GetPassOption(const char* option_name, const SafeMap<const std::string, int>& overridden_options) const {
134 // First check if there are any overridden settings.
135 auto overridden_it = overridden_options.find(std::string(option_name));
136 if (overridden_it != overridden_options.end()) {
137 return overridden_it->second;
138 }
139
140 // Next check the default options.
141 auto default_it = default_options_.find(option_name);
142
143 if (default_it == default_options_.end()) {
144 // An invalid option is being requested.
145 DCHECK(false);
146 return 0;
147 }
148
149 return default_it->second;
150 }
151
James C Scott4f596682014-05-01 05:52:04 -0700152 /** @brief Type of traversal: determines the order to execute the pass on the BasicBlocks. */
153 const DataFlowAnalysisMode traversal_type_;
154
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700155 /** @brief Flags for additional directives: used to determine if a particular post-optimization pass is necessary. */
James C Scott4f596682014-05-01 05:52:04 -0700156 const unsigned int flags_;
157
158 /** @brief CFG Dump Folder: what sub-folder to use for dumping the CFGs post pass. */
159 const char* const dump_cfg_folder_;
Razvan A Lupusorubd25d4b2014-07-02 18:16:51 -0700160
161 /**
162 * @brief Contains a map of options with the default settings.
163 * @details The constructor of the specific pass instance should fill this
164 * with default options.
165 * */
166 SafeMap<const char*, int> default_options_;
James C Scott4f596682014-05-01 05:52:04 -0700167};
168} // namespace art
169#endif // ART_COMPILER_DEX_PASS_ME_H_