blob: da44ffd99c5a2ea18e29d39f6db03a49d83d424c [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,
30 * necessitating another pass over the list.
31 *
32 * To support this usage, we have is_iterative_. If false, the iteration is a one-shot
33 * pass through the pre-computed list using Next(). If true, the caller must tell the
34 * iterator whether a change has been made that necessitates another pass. Use
35 * Next(had_change) for this. The general idea is that the iterative_ use case means
36 * that the iterator will keep repeating the full basic block list until a complete pass
37 * is made through it with no changes. Note that calling Next(true) does not affect
38 * the iteration order or short-curcuit the current pass - it simply tells the iterator
39 * that once it has finished walking through the block list it should reset and do another
40 * full pass through the list.
41 */
buzbee311ca162013-02-28 15:56:43 -080042 class DataflowIterator {
43 public:
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070044 virtual ~DataflowIterator() {}
buzbee311ca162013-02-28 15:56:43 -080045
buzbee0665fe02013-03-21 12:32:21 -070046 // Return the next BasicBlock* to visit.
47 BasicBlock* Next() {
48 DCHECK(!is_iterative_);
49 return NextBody(false);
50 }
51
52 /*
53 * Return the next BasicBlock* to visit, and tell the iterator whether any change
54 * has occurred that requires another full pass over the block list.
55 */
56 BasicBlock* Next(bool had_change) {
57 DCHECK(is_iterative_);
58 return NextBody(had_change);
59 }
60
61 protected:
62 DataflowIterator(MIRGraph* mir_graph, bool is_iterative, int start_idx, int end_idx,
63 bool reverse)
64 : mir_graph_(mir_graph),
65 is_iterative_(is_iterative),
66 start_idx_(start_idx),
67 end_idx_(end_idx),
Ian Rogerse7a5b7d2013-04-18 20:09:02 -070068 reverse_(reverse),
69 block_id_list_(NULL),
70 idx_(0),
71 changed_(false) {}
buzbee0665fe02013-03-21 12:32:21 -070072
Ian Rogers8d3a1172013-06-04 01:13:28 -070073 virtual BasicBlock* NextBody(bool had_change) ALWAYS_INLINE;
buzbee0665fe02013-03-21 12:32:21 -070074
75 MIRGraph* const mir_graph_;
76 const bool is_iterative_;
77 const int start_idx_;
78 const int end_idx_;
79 const bool reverse_;
buzbee862a7602013-04-05 10:58:54 -070080 GrowableArray<int>* block_id_list_;
buzbee0665fe02013-03-21 12:32:21 -070081 int idx_;
82 bool changed_;
Brian Carlstrom7934ac22013-07-26 10:54:15 -070083 }; // DataflowIterator
buzbee0665fe02013-03-21 12:32:21 -070084
85 class ReachableNodesIterator : public DataflowIterator {
86 public:
buzbee0665fe02013-03-21 12:32:21 -070087 ReachableNodesIterator(MIRGraph* mir_graph, bool is_iterative)
88 : DataflowIterator(mir_graph, is_iterative, 0,
89 mir_graph->GetNumReachableBlocks(), false) {
90 idx_ = start_idx_;
91 block_id_list_ = mir_graph->GetDfsOrder();
92 }
93 };
94
95 class PreOrderDfsIterator : public DataflowIterator {
96 public:
buzbee0665fe02013-03-21 12:32:21 -070097 PreOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
98 : DataflowIterator(mir_graph, is_iterative, 0,
99 mir_graph->GetNumReachableBlocks(), false) {
100 idx_ = start_idx_;
101 block_id_list_ = mir_graph->GetDfsOrder();
102 }
103 };
104
105 class PostOrderDfsIterator : public DataflowIterator {
106 public:
buzbee0665fe02013-03-21 12:32:21 -0700107 PostOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
108 : DataflowIterator(mir_graph, is_iterative, 0,
109 mir_graph->GetNumReachableBlocks(), false) {
110 idx_ = start_idx_;
111 block_id_list_ = mir_graph->GetDfsPostOrder();
112 }
113 };
114
115 class ReversePostOrderDfsIterator : public DataflowIterator {
116 public:
buzbee0665fe02013-03-21 12:32:21 -0700117 ReversePostOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
118 : DataflowIterator(mir_graph, is_iterative,
119 mir_graph->GetNumReachableBlocks() -1, 0, true) {
120 idx_ = start_idx_;
121 block_id_list_ = mir_graph->GetDfsPostOrder();
122 }
123 };
124
125 class PostOrderDOMIterator : public DataflowIterator {
126 public:
buzbee0665fe02013-03-21 12:32:21 -0700127 PostOrderDOMIterator(MIRGraph* mir_graph, bool is_iterative)
128 : DataflowIterator(mir_graph, is_iterative, 0,
129 mir_graph->GetNumReachableBlocks(), false) {
130 idx_ = start_idx_;
131 block_id_list_ = mir_graph->GetDomPostOrder();
132 }
133 };
134
135 class AllNodesIterator : public DataflowIterator {
136 public:
buzbee0665fe02013-03-21 12:32:21 -0700137 AllNodesIterator(MIRGraph* mir_graph, bool is_iterative)
138 : DataflowIterator(mir_graph, is_iterative, 0, 0, false) {
buzbee862a7602013-04-05 10:58:54 -0700139 all_nodes_iterator_ =
Brian Carlstromdf629502013-07-17 22:39:56 -0700140 new (mir_graph->GetArena()) GrowableArray<BasicBlock*>::Iterator(mir_graph->GetBlockList());
buzbee862a7602013-04-05 10:58:54 -0700141 }
142
Ian Rogers8d3a1172013-06-04 01:13:28 -0700143 void Reset() {
buzbee862a7602013-04-05 10:58:54 -0700144 all_nodes_iterator_->Reset();
buzbee0665fe02013-03-21 12:32:21 -0700145 }
146
Ian Rogers8d3a1172013-06-04 01:13:28 -0700147 BasicBlock* NextBody(bool had_change) ALWAYS_INLINE;
buzbee862a7602013-04-05 10:58:54 -0700148
149 private:
150 GrowableArray<BasicBlock*>::Iterator* all_nodes_iterator_;
buzbee0665fe02013-03-21 12:32:21 -0700151 };
152
buzbee311ca162013-02-28 15:56:43 -0800153} // namespace art
154
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700155#endif // ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_