blob: f3a2fca30db0393e46bfc27710ed8a64c292d52c [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
17#ifndef ART_SRC_COMPILER_DEX_DATAFLOW_ITERATOR_H_
18#define ART_SRC_COMPILER_DEX_DATAFLOW_ITERATOR_H_
19
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:
buzbee311ca162013-02-28 15:56:43 -080044
buzbee0665fe02013-03-21 12:32:21 -070045 virtual ~DataflowIterator(){}
buzbee311ca162013-02-28 15:56:43 -080046
buzbee0665fe02013-03-21 12:32:21 -070047 // Return the next BasicBlock* to visit.
48 BasicBlock* Next() {
49 DCHECK(!is_iterative_);
50 return NextBody(false);
51 }
52
53 /*
54 * Return the next BasicBlock* to visit, and tell the iterator whether any change
55 * has occurred that requires another full pass over the block list.
56 */
57 BasicBlock* Next(bool had_change) {
58 DCHECK(is_iterative_);
59 return NextBody(had_change);
60 }
61
62 protected:
63 DataflowIterator(MIRGraph* mir_graph, bool is_iterative, int start_idx, int end_idx,
64 bool reverse)
65 : mir_graph_(mir_graph),
66 is_iterative_(is_iterative),
67 start_idx_(start_idx),
68 end_idx_(end_idx),
69 reverse_(reverse) {}
70
71 virtual BasicBlock* NextBody(bool had_change);
72
73 MIRGraph* const mir_graph_;
74 const bool is_iterative_;
75 const int start_idx_;
76 const int end_idx_;
77 const bool reverse_;
buzbee311ca162013-02-28 15:56:43 -080078 GrowableList* block_id_list_;
79 GrowableListIterator all_nodes_iterator_;
buzbee0665fe02013-03-21 12:32:21 -070080 int idx_;
81 bool changed_;
buzbee311ca162013-02-28 15:56:43 -080082
83 }; // DataflowIterator
buzbee0665fe02013-03-21 12:32:21 -070084
85 class ReachableNodesIterator : public DataflowIterator {
86 public:
87
88 ReachableNodesIterator(MIRGraph* mir_graph, bool is_iterative)
89 : DataflowIterator(mir_graph, is_iterative, 0,
90 mir_graph->GetNumReachableBlocks(), false) {
91 idx_ = start_idx_;
92 block_id_list_ = mir_graph->GetDfsOrder();
93 }
94 };
95
96 class PreOrderDfsIterator : public DataflowIterator {
97 public:
98
99 PreOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
100 : DataflowIterator(mir_graph, is_iterative, 0,
101 mir_graph->GetNumReachableBlocks(), false) {
102 idx_ = start_idx_;
103 block_id_list_ = mir_graph->GetDfsOrder();
104 }
105 };
106
107 class PostOrderDfsIterator : public DataflowIterator {
108 public:
109
110 PostOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
111 : DataflowIterator(mir_graph, is_iterative, 0,
112 mir_graph->GetNumReachableBlocks(), false) {
113 idx_ = start_idx_;
114 block_id_list_ = mir_graph->GetDfsPostOrder();
115 }
116 };
117
118 class ReversePostOrderDfsIterator : public DataflowIterator {
119 public:
120
121 ReversePostOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
122 : DataflowIterator(mir_graph, is_iterative,
123 mir_graph->GetNumReachableBlocks() -1, 0, true) {
124 idx_ = start_idx_;
125 block_id_list_ = mir_graph->GetDfsPostOrder();
126 }
127 };
128
129 class PostOrderDOMIterator : public DataflowIterator {
130 public:
131
132 PostOrderDOMIterator(MIRGraph* mir_graph, bool is_iterative)
133 : DataflowIterator(mir_graph, is_iterative, 0,
134 mir_graph->GetNumReachableBlocks(), false) {
135 idx_ = start_idx_;
136 block_id_list_ = mir_graph->GetDomPostOrder();
137 }
138 };
139
140 class AllNodesIterator : public DataflowIterator {
141 public:
142
143 AllNodesIterator(MIRGraph* mir_graph, bool is_iterative)
144 : DataflowIterator(mir_graph, is_iterative, 0, 0, false) {
145 GrowableListIteratorInit(mir_graph->GetBlockList(), &all_nodes_iterator_);
146 }
147
148 virtual BasicBlock* NextBody(bool had_change);
149 };
150
buzbee311ca162013-02-28 15:56:43 -0800151} // namespace art
152
153#endif // ART_SRC_COMPILER_DEX_DATAFLOW_ITERATOR_H_