Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: src/compiler/graph-reducer.cc

Issue 1122423003: [turbofan] Add support for advanced reducers. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Make windows happy. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <functional> 5 #include <functional>
6 6
7 #include "src/compiler/graph.h" 7 #include "src/compiler/graph.h"
8 #include "src/compiler/graph-reducer.h" 8 #include "src/compiler/graph-reducer.h"
9 #include "src/compiler/node.h" 9 #include "src/compiler/node.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 namespace compiler { 13 namespace compiler {
14 14
15 bool Reducer::Finish() { return true; }
16
17
15 enum class GraphReducer::State : uint8_t { 18 enum class GraphReducer::State : uint8_t {
16 kUnvisited, 19 kUnvisited,
17 kRevisit, 20 kRevisit,
18 kOnStack, 21 kOnStack,
19 kVisited 22 kVisited
20 }; 23 };
21 24
22 25
23 GraphReducer::GraphReducer(Graph* graph, Zone* zone) 26 GraphReducer::GraphReducer(Graph* graph, Zone* zone)
24 : graph_(graph), 27 : graph_(graph),
25 state_(graph, 4), 28 state_(graph, 4),
26 reducers_(zone), 29 reducers_(zone),
27 revisit_(zone), 30 revisit_(zone),
28 stack_(zone) {} 31 stack_(zone) {}
29 32
30 33
34 GraphReducer::~GraphReducer() {
35 for (Reducer* reducer : reducers_) reducer->set_observer(nullptr);
36 }
37
38
31 void GraphReducer::AddReducer(Reducer* reducer) { 39 void GraphReducer::AddReducer(Reducer* reducer) {
32 reducers_.push_back(reducer); 40 reducers_.push_back(reducer);
41 reducer->set_observer(this);
33 } 42 }
34 43
35 44
36 void GraphReducer::ReduceNode(Node* node) { 45 void GraphReducer::ReduceNode(Node* node) {
37 DCHECK(stack_.empty()); 46 DCHECK(stack_.empty());
38 DCHECK(revisit_.empty()); 47 DCHECK(revisit_.empty());
39 Push(node); 48 Push(node);
40 for (;;) { 49 for (;;) {
41 if (!stack_.empty()) { 50 if (!stack_.empty()) {
42 // Process the node on the top of the stack, potentially pushing more or 51 // Process the node on the top of the stack, potentially pushing more or
43 // popping the node off the stack. 52 // popping the node off the stack.
44 ReduceTop(); 53 ReduceTop();
45 } else if (!revisit_.empty()) { 54 } else if (!revisit_.empty()) {
46 // If the stack becomes empty, revisit any nodes in the revisit queue. 55 // If the stack becomes empty, revisit any nodes in the revisit queue.
47 Node* const node = revisit_.top(); 56 Node* const node = revisit_.top();
48 revisit_.pop(); 57 revisit_.pop();
49 if (state_.Get(node) == State::kRevisit) { 58 if (state_.Get(node) == State::kRevisit) {
50 // state can change while in queue. 59 // state can change while in queue.
51 Push(node); 60 Push(node);
52 } 61 }
53 } else { 62 } else {
54 break; 63 break;
55 } 64 }
56 } 65 }
57 DCHECK(revisit_.empty()); 66 DCHECK(revisit_.empty());
58 DCHECK(stack_.empty()); 67 DCHECK(stack_.empty());
59 } 68 }
60 69
61 70
62 void GraphReducer::ReduceGraph() { ReduceNode(graph()->end()); } 71 void GraphReducer::ReduceGraph() {
72 for (;;) {
73 ReduceNode(graph()->end());
74 if (Finish()) break;
75 // Reset all marks on the graph in preparation to re-reduce the graph.
76 state_.Reset(graph());
77 }
78 }
63 79
64 80
65 Reduction GraphReducer::Reduce(Node* const node) { 81 Reduction GraphReducer::Reduce(Node* const node) {
66 auto skip = reducers_.end(); 82 auto skip = reducers_.end();
67 for (auto i = reducers_.begin(); i != reducers_.end();) { 83 for (auto i = reducers_.begin(); i != reducers_.end();) {
68 if (i != skip) { 84 if (i != skip) {
69 Reduction reduction = (*i)->Reduce(node); 85 Reduction reduction = (*i)->Reduce(node);
70 if (!reduction.Changed()) { 86 if (!reduction.Changed()) {
71 // No change from this reducer. 87 // No change from this reducer.
72 } else if (reduction.replacement() == node) { 88 } else if (reduction.replacement() == node) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 for (int i = 0; i < node->InputCount(); ++i) { 144 for (int i = 0; i < node->InputCount(); ++i) {
129 Node* input = node->InputAt(i); 145 Node* input = node->InputAt(i);
130 entry.input_index = i + 1; 146 entry.input_index = i + 1;
131 if (input != node && Recurse(input)) return; 147 if (input != node && Recurse(input)) return;
132 } 148 }
133 } 149 }
134 150
135 // After reducing the node, pop it off the stack. 151 // After reducing the node, pop it off the stack.
136 Pop(); 152 Pop();
137 153
138 // Revisit all uses of the node.
139 for (Node* const use : node->uses()) {
140 // Don't revisit this node if it refers to itself.
141 if (use != node) Revisit(use);
142 }
143
144 // Check if we have a new replacement. 154 // Check if we have a new replacement.
145 if (replacement != node) { 155 if (replacement != node) {
146 if (node == graph()->start()) graph()->SetStart(replacement); 156 // Replace the old uses of {node} with {replacement}.
147 if (node == graph()->end()) graph()->SetEnd(replacement); 157 Replace(node, replacement, node_count);
148 // If {node} was replaced by an old node, unlink {node} and assume that 158 } else {
149 // {replacement} was already reduced and finish. 159 // Revisit all uses of the node.
150 if (replacement->id() < node_count) { 160 for (Node* const user : node->uses()) {
151 node->ReplaceUses(replacement); 161 // Don't revisit this node if it refers to itself.
152 node->Kill(); 162 if (user != node) Revisit(user);
153 } else {
154 // Otherwise {node} was replaced by a new node. Replace all old uses of
155 // {node} with {replacement}. New nodes created by this reduction can
156 // use {node}.
157 for (Edge edge : node->use_edges()) {
158 if (edge.from()->id() < node_count) {
159 edge.UpdateTo(replacement);
160 }
161 }
162 // Unlink {node} if it's no longer used.
163 if (node->uses().empty()) {
164 node->Kill();
165 }
166
167 // If there was a replacement, reduce it after popping {node}.
168 Recurse(replacement);
169 } 163 }
170 } 164 }
171 } 165 }
172 166
167
168 void GraphReducer::Replace(Node* node, Node* replacement) {
169 if (node == graph()->start()) graph()->SetStart(replacement);
170 if (node == graph()->end()) graph()->SetEnd(replacement);
171 for (Edge edge : node->use_edges()) {
172 Node* const user = edge.from();
173 edge.UpdateTo(replacement);
174 // Don't revisit this node if it refers to itself.
175 if (user != node) Revisit(user);
176 }
177 node->Kill();
178 }
179
180
181 void GraphReducer::Replace(Node* node, Node* replacement, NodeId max_id) {
182 if (node == graph()->start()) graph()->SetStart(replacement);
183 if (node == graph()->end()) graph()->SetEnd(replacement);
184 // If {node} was replaced by an old node, unlink {node} and assume that
185 // {replacement} was already reduced and finish.
186 if (replacement->id() < max_id) {
187 for (Edge edge : node->use_edges()) {
188 Node* const user = edge.from();
189 edge.UpdateTo(replacement);
190 // Don't revisit this node if it refers to itself.
191 if (user != node) Revisit(user);
192 }
193 node->Kill();
194 } else {
195 // Otherwise {node} was replaced by a new node. Replace all old uses of
196 // {node} with {replacement}. New nodes created by this reduction can
197 // use {node}.
198 for (Edge edge : node->use_edges()) {
199 Node* const user = edge.from();
200 if (user->id() < max_id) {
201 edge.UpdateTo(replacement);
202 // Don't revisit this node if it refers to itself.
203 if (user != node) Revisit(user);
204 }
205 }
206 // Unlink {node} if it's no longer used.
207 if (node->uses().empty()) node->Kill();
208
209 // If there was a replacement, reduce it after popping {node}.
210 Recurse(replacement);
211 }
212 }
213
173 214
174 void GraphReducer::Pop() { 215 void GraphReducer::Pop() {
175 Node* node = stack_.top().node; 216 Node* node = stack_.top().node;
176 state_.Set(node, State::kVisited); 217 state_.Set(node, State::kVisited);
177 stack_.pop(); 218 stack_.pop();
178 } 219 }
179 220
180 221
181 void GraphReducer::Push(Node* const node) { 222 void GraphReducer::Push(Node* const node) {
182 DCHECK(state_.Get(node) != State::kOnStack); 223 DCHECK(state_.Get(node) != State::kOnStack);
(...skipping 12 matching lines...) Expand all
195 void GraphReducer::Revisit(Node* node) { 236 void GraphReducer::Revisit(Node* node) {
196 if (state_.Get(node) == State::kVisited) { 237 if (state_.Get(node) == State::kVisited) {
197 state_.Set(node, State::kRevisit); 238 state_.Set(node, State::kRevisit);
198 revisit_.push(node); 239 revisit_.push(node);
199 } 240 }
200 } 241 }
201 242
202 } // namespace compiler 243 } // namespace compiler
203 } // namespace internal 244 } // namespace internal
204 } // namespace v8 245 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698