blob: b45d6a45ae036fbaefddf441441c628d3f6b21a6 [file] [log] [blame]
buzbee311ca162013-02-28 15:56:43 -08001/*
2 * Copyright (C) 2013 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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_
18#define ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_
buzbee311ca162013-02-28 15:56:43 -080019
20#include "compiler_ir.h"
21#include "mir_graph.h"
22
23namespace art {
24
buzbee0665fe02013-03-21 12:32:21 -070025 /*
26 * This class supports iterating over lists of basic blocks in various
27 * interesting orders. Note that for efficiency, the visit orders have been pre-computed.
28 * The order itself will not change during the iteration. However, for some uses,
29 * auxiliary data associated with the basic blocks may be changed during the iteration,
buzbee56c71782013-09-05 17:13:19 -070030 * necessitating another pass over the list. If this behavior is required, use the
31 * "Repeating" variant. For the repeating variant, the caller must tell the iterator
32 * whether a change has been made that necessitates another pass. Note that calling Next(true)
33 * does not affect the iteration order or short-circuit the current pass - it simply tells
34 * the iterator that once it has finished walking through the block list it should reset and
35 * do another full pass through the list.
buzbee0665fe02013-03-21 12:32:21 -070036 */
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080037 /**
38 * @class DataflowIterator
39 * @brief The main iterator class, all other iterators derive of this one to define an iteration order.
40 */
buzbee311ca162013-02-28 15:56:43 -080041 class DataflowIterator {
42 public:
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070043 virtual ~DataflowIterator() {}
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080044
45 /**
46 * @brief How many times have we repeated the iterator across the BasicBlocks?
47 * @return the number of iteration repetitions.
48 */
buzbee1da1e2f2013-11-15 13:37:01 -080049 int32_t GetRepeatCount() { return repeats_; }
buzbee311ca162013-02-28 15:56:43 -080050
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080051 /**
52 * @brief Has the user of the iterator reported a change yet?
53 * @details Does not mean there was or not a change, it is only whether the user passed a true to the Next function call.
54 * @return whether the user of the iterator reported a change yet.
55 */
56 int32_t GetChanged() { return changed_; }
57
58 /**
59 * @brief Get the next BasicBlock depending on iteration order.
60 * @param had_change did the user of the iteration change the previous BasicBlock.
61 * @return the next BasicBlock following the iteration order, 0 if finished.
62 */
63 virtual BasicBlock* Next(bool had_change = false) = 0;
64
buzbee0665fe02013-03-21 12:32:21 -070065 protected:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080066 /**
67 * @param mir_graph the MIRGraph we are interested in.
68 * @param start_idx the first index we want to iterate across.
69 * @param end_idx the last index we want to iterate (not included).
70 */
buzbee0d829482013-10-11 15:24:55 -070071 DataflowIterator(MIRGraph* mir_graph, int32_t start_idx, int32_t end_idx)
buzbee0665fe02013-03-21 12:32:21 -070072 : mir_graph_(mir_graph),
buzbee0665fe02013-03-21 12:32:21 -070073 start_idx_(start_idx),
74 end_idx_(end_idx),
Ian Rogerse7a5b7d2013-04-18 20:09:02 -070075 block_id_list_(NULL),
76 idx_(0),
buzbee1da1e2f2013-11-15 13:37:01 -080077 repeats_(0),
Ian Rogerse7a5b7d2013-04-18 20:09:02 -070078 changed_(false) {}
buzbee0665fe02013-03-21 12:32:21 -070079
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080080 /**
81 * @brief Get the next BasicBlock iterating forward.
82 * @return the next BasicBlock iterating forward.
83 */
buzbee56c71782013-09-05 17:13:19 -070084 virtual BasicBlock* ForwardSingleNext() ALWAYS_INLINE;
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080085
86 /**
87 * @brief Get the next BasicBlock iterating backward.
88 * @return the next BasicBlock iterating backward.
89 */
buzbee56c71782013-09-05 17:13:19 -070090 virtual BasicBlock* ReverseSingleNext() ALWAYS_INLINE;
buzbee0665fe02013-03-21 12:32:21 -070091
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080092 /**
93 * @brief Get the next BasicBlock iterating forward, restart if a BasicBlock was reported changed during the last iteration.
94 * @return the next BasicBlock iterating forward, with chance of repeating the iteration.
95 */
96 virtual BasicBlock* ForwardRepeatNext() ALWAYS_INLINE;
buzbee1da1e2f2013-11-15 13:37:01 -080097
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080098 /**
99 * @brief Get the next BasicBlock iterating backward, restart if a BasicBlock was reported changed during the last iteration.
100 * @return the next BasicBlock iterating backward, with chance of repeating the iteration.
101 */
102 virtual BasicBlock* ReverseRepeatNext() ALWAYS_INLINE;
103
104 MIRGraph* const mir_graph_; /**< @brief the MIRGraph */
105 const int32_t start_idx_; /**< @brief the start index for the iteration */
106 const int32_t end_idx_; /**< @brief the last index for the iteration */
107 GrowableArray<BasicBlockId>* block_id_list_; /**< @brief the list of BasicBlocks we want to iterate on */
108 int32_t idx_; /**< @brief Current index for the iterator */
109 int32_t repeats_; /**< @brief Number of repeats over the iteration */
110 bool changed_; /**< @brief Has something changed during the current iteration? */
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700111 }; // DataflowIterator
buzbee0665fe02013-03-21 12:32:21 -0700112
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800113 /**
114 * @class PreOrderDfsIterator
115 * @brief Used to perform a Pre-order Depth-First-Search Iteration of a MIRGraph.
116 */
buzbee0665fe02013-03-21 12:32:21 -0700117 class PreOrderDfsIterator : public DataflowIterator {
118 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800119 /**
120 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
121 * @param mir_graph The MIRGraph considered.
122 */
buzbee56c71782013-09-05 17:13:19 -0700123 explicit PreOrderDfsIterator(MIRGraph* mir_graph)
124 : DataflowIterator(mir_graph, 0, mir_graph->GetNumReachableBlocks()) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800125 // Extra setup for the PreOrderDfsIterator.
buzbee0665fe02013-03-21 12:32:21 -0700126 idx_ = start_idx_;
127 block_id_list_ = mir_graph->GetDfsOrder();
128 }
buzbee56c71782013-09-05 17:13:19 -0700129
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800130 /**
131 * @brief Get the next BasicBlock depending on iteration order.
132 * @param had_change did the user of the iteration change the previous BasicBlock.
133 * @return the next BasicBlock following the iteration order, 0 if finished.
134 */
135 virtual BasicBlock* Next(bool had_change = false) {
136 // Update changed: if had_changed is true, we remember it for the whole iteration.
137 changed_ |= had_change;
138
buzbee56c71782013-09-05 17:13:19 -0700139 return ForwardSingleNext();
140 }
buzbee0665fe02013-03-21 12:32:21 -0700141 };
142
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800143 /**
144 * @class RepeatingPreOrderDfsIterator
145 * @brief Used to perform a Repeating Pre-order Depth-First-Search Iteration of a MIRGraph.
146 * @details If there is a change during an iteration, the iteration starts over at the end of the iteration.
147 */
buzbee56c71782013-09-05 17:13:19 -0700148 class RepeatingPreOrderDfsIterator : public DataflowIterator {
buzbee0665fe02013-03-21 12:32:21 -0700149 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800150 /**
151 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
152 * @param mir_graph The MIRGraph considered.
153 */
buzbee56c71782013-09-05 17:13:19 -0700154 explicit RepeatingPreOrderDfsIterator(MIRGraph* mir_graph)
155 : DataflowIterator(mir_graph, 0, mir_graph->GetNumReachableBlocks()) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800156 // Extra setup for the RepeatingPreOrderDfsIterator.
buzbee56c71782013-09-05 17:13:19 -0700157 idx_ = start_idx_;
158 block_id_list_ = mir_graph->GetDfsOrder();
159 }
160
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800161 /**
162 * @brief Get the next BasicBlock depending on iteration order.
163 * @param had_change did the user of the iteration change the previous BasicBlock.
164 * @return the next BasicBlock following the iteration order, 0 if finished.
165 */
166 virtual BasicBlock* Next(bool had_change = false) {
167 // Update changed: if had_changed is true, we remember it for the whole iteration.
168 changed_ |= had_change;
169
170 return ForwardRepeatNext();
buzbee56c71782013-09-05 17:13:19 -0700171 }
172 };
173
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800174 /**
175 * @class RepeatingPostOrderDfsIterator
176 * @brief Used to perform a Repeating Post-order Depth-First-Search Iteration of a MIRGraph.
177 * @details If there is a change during an iteration, the iteration starts over at the end of the iteration.
178 */
buzbee56c71782013-09-05 17:13:19 -0700179 class RepeatingPostOrderDfsIterator : public DataflowIterator {
180 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800181 /**
182 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
183 * @param mir_graph The MIRGraph considered.
184 */
buzbee56c71782013-09-05 17:13:19 -0700185 explicit RepeatingPostOrderDfsIterator(MIRGraph* mir_graph)
186 : DataflowIterator(mir_graph, 0, mir_graph->GetNumReachableBlocks()) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800187 // Extra setup for the RepeatingPostOrderDfsIterator.
buzbee0665fe02013-03-21 12:32:21 -0700188 idx_ = start_idx_;
189 block_id_list_ = mir_graph->GetDfsPostOrder();
190 }
buzbee56c71782013-09-05 17:13:19 -0700191
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800192 /**
193 * @brief Get the next BasicBlock depending on iteration order.
194 * @param had_change did the user of the iteration change the previous BasicBlock.
195 * @return the next BasicBlock following the iteration order, 0 if finished.
196 */
197 virtual BasicBlock* Next(bool had_change = false) {
198 // Update changed: if had_changed is true, we remember it for the whole iteration.
199 changed_ |= had_change;
200
201 return ForwardRepeatNext();
buzbee56c71782013-09-05 17:13:19 -0700202 }
buzbee0665fe02013-03-21 12:32:21 -0700203 };
204
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800205 /**
206 * @class ReversePostOrderDfsIterator
207 * @brief Used to perform a Reverse Post-order Depth-First-Search Iteration of a MIRGraph.
208 */
buzbee0665fe02013-03-21 12:32:21 -0700209 class ReversePostOrderDfsIterator : public DataflowIterator {
210 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800211 /**
212 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
213 * @param mir_graph The MIRGraph considered.
214 */
buzbee56c71782013-09-05 17:13:19 -0700215 explicit ReversePostOrderDfsIterator(MIRGraph* mir_graph)
216 : DataflowIterator(mir_graph, mir_graph->GetNumReachableBlocks() -1, 0) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800217 // Extra setup for the ReversePostOrderDfsIterator.
buzbee0665fe02013-03-21 12:32:21 -0700218 idx_ = start_idx_;
219 block_id_list_ = mir_graph->GetDfsPostOrder();
220 }
buzbee56c71782013-09-05 17:13:19 -0700221
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800222 /**
223 * @brief Get the next BasicBlock depending on iteration order.
224 * @param had_change did the user of the iteration change the previous BasicBlock.
225 * @return the next BasicBlock following the iteration order, 0 if finished.
226 */
227 virtual BasicBlock* Next(bool had_change = false) {
228 // Update changed: if had_changed is true, we remember it for the whole iteration.
229 changed_ |= had_change;
230
buzbee56c71782013-09-05 17:13:19 -0700231 return ReverseSingleNext();
232 }
233 };
234
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800235 /**
236 * @class ReversePostOrderDfsIterator
237 * @brief Used to perform a Repeating Reverse Post-order Depth-First-Search Iteration of a MIRGraph.
238 * @details If there is a change during an iteration, the iteration starts over at the end of the iteration.
239 */
buzbee56c71782013-09-05 17:13:19 -0700240 class RepeatingReversePostOrderDfsIterator : public DataflowIterator {
241 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800242 /**
243 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
244 * @param mir_graph The MIRGraph considered.
245 */
buzbee56c71782013-09-05 17:13:19 -0700246 explicit RepeatingReversePostOrderDfsIterator(MIRGraph* mir_graph)
247 : DataflowIterator(mir_graph, mir_graph->GetNumReachableBlocks() -1, 0) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800248 // Extra setup for the RepeatingReversePostOrderDfsIterator
buzbee56c71782013-09-05 17:13:19 -0700249 idx_ = start_idx_;
250 block_id_list_ = mir_graph->GetDfsPostOrder();
251 }
252
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800253 /**
254 * @brief Get the next BasicBlock depending on iteration order.
255 * @param had_change did the user of the iteration change the previous BasicBlock.
256 * @return the next BasicBlock following the iteration order, 0 if finished.
257 */
258 virtual BasicBlock* Next(bool had_change = false) {
259 // Update changed: if had_changed is true, we remember it for the whole iteration.
260 changed_ |= had_change;
261
262 return ReverseRepeatNext();
buzbee56c71782013-09-05 17:13:19 -0700263 }
buzbee0665fe02013-03-21 12:32:21 -0700264 };
265
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800266 /**
267 * @class PostOrderDOMIterator
268 * @brief Used to perform a Post-order Domination Iteration of a MIRGraph.
269 */
buzbee0665fe02013-03-21 12:32:21 -0700270 class PostOrderDOMIterator : public DataflowIterator {
271 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800272 /**
273 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
274 * @param mir_graph The MIRGraph considered.
275 */
buzbee56c71782013-09-05 17:13:19 -0700276 explicit PostOrderDOMIterator(MIRGraph* mir_graph)
277 : DataflowIterator(mir_graph, 0, mir_graph->GetNumReachableBlocks()) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800278 // Extra setup for thePostOrderDOMIterator.
buzbee0665fe02013-03-21 12:32:21 -0700279 idx_ = start_idx_;
280 block_id_list_ = mir_graph->GetDomPostOrder();
281 }
buzbee56c71782013-09-05 17:13:19 -0700282
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800283 /**
284 * @brief Get the next BasicBlock depending on iteration order.
285 * @param had_change did the user of the iteration change the previous BasicBlock.
286 * @return the next BasicBlock following the iteration order, 0 if finished.
287 */
288 virtual BasicBlock* Next(bool had_change = false) {
289 // Update changed: if had_changed is true, we remember it for the whole iteration.
290 changed_ |= had_change;
291
buzbee56c71782013-09-05 17:13:19 -0700292 return ForwardSingleNext();
293 }
buzbee0665fe02013-03-21 12:32:21 -0700294 };
295
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800296 /**
297 * @class AllNodesIterator
298 * @brief Used to perform an iteration on all the BasicBlocks a MIRGraph.
299 */
buzbee0665fe02013-03-21 12:32:21 -0700300 class AllNodesIterator : public DataflowIterator {
301 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800302 /**
303 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
304 * @param mir_graph The MIRGraph considered.
305 */
buzbee56c71782013-09-05 17:13:19 -0700306 explicit AllNodesIterator(MIRGraph* mir_graph)
Vladimir Marko75ba13f2014-01-28 12:15:24 +0000307 : DataflowIterator(mir_graph, 0, 0),
308 all_nodes_iterator_(mir_graph->GetBlockList()) {
buzbee862a7602013-04-05 10:58:54 -0700309 }
310
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800311 /**
312 * @brief Resetting the iterator.
313 */
Ian Rogers8d3a1172013-06-04 01:13:28 -0700314 void Reset() {
Vladimir Marko75ba13f2014-01-28 12:15:24 +0000315 all_nodes_iterator_.Reset();
buzbee0665fe02013-03-21 12:32:21 -0700316 }
317
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800318 /**
319 * @brief Get the next BasicBlock depending on iteration order.
320 * @param had_change did the user of the iteration change the previous BasicBlock.
321 * @return the next BasicBlock following the iteration order, 0 if finished.
322 */
323 virtual BasicBlock* Next(bool had_change = false) ALWAYS_INLINE;
buzbee862a7602013-04-05 10:58:54 -0700324
325 private:
Vladimir Marko75ba13f2014-01-28 12:15:24 +0000326 GrowableArray<BasicBlock*>::Iterator all_nodes_iterator_; /**< @brief The list of all the nodes */
buzbee0665fe02013-03-21 12:32:21 -0700327 };
328
buzbee311ca162013-02-28 15:56:43 -0800329} // namespace art
330
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700331#endif // ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_