8 #include "src/compiler/graph.h" 9 #include "src/compiler/graph-reducer.h" 10 #include "src/compiler/node.h" 11 #include "src/compiler/node-properties.h" 12 #include "src/compiler/verifier.h" 18 enum class GraphReducer::State : uint8_t {
26 void Reducer::Finalize() {}
28 GraphReducer::GraphReducer(Zone* zone, Graph* graph, Node* dead)
35 if (dead !=
nullptr) {
36 NodeProperties::SetType(dead_, Type::None());
40 GraphReducer::~GraphReducer() =
default;
43 void GraphReducer::AddReducer(Reducer* reducer) {
44 reducers_.push_back(reducer);
48 void GraphReducer::ReduceNode(Node* node) {
49 DCHECK(stack_.empty());
50 DCHECK(revisit_.empty());
53 if (!stack_.empty()) {
57 }
else if (!revisit_.empty()) {
59 Node*
const node = revisit_.front();
61 if (state_.Get(node) == State::kRevisit) {
67 for (Reducer*
const reducer : reducers_) reducer->Finalize();
70 if (revisit_.empty())
break;
73 DCHECK(revisit_.empty());
74 DCHECK(stack_.empty());
78 void GraphReducer::ReduceGraph() { ReduceNode(graph()->end()); }
81 Reduction GraphReducer::Reduce(Node*
const node) {
82 auto skip = reducers_.end();
83 for (
auto i = reducers_.begin();
i != reducers_.end();) {
85 Reduction reduction = (*i)->Reduce(node);
86 if (!reduction.Changed()) {
88 }
else if (reduction.replacement() == node) {
92 if (FLAG_trace_turbo_reduction) {
93 StdoutStream{} <<
"- In-place update of " << *node <<
" by reducer " 94 << (*i)->reducer_name() << std::endl;
97 i = reducers_.begin();
101 if (FLAG_trace_turbo_reduction) {
102 StdoutStream{} <<
"- Replacement of " << *node <<
" with " 103 << *(reduction.replacement()) <<
" by reducer " 104 << (*i)->reducer_name() << std::endl;
111 if (skip == reducers_.end()) {
113 return Reducer::NoChange();
116 return Reducer::Changed(node);
120 void GraphReducer::ReduceTop() {
121 NodeState& entry = stack_.top();
122 Node* node = entry.node;
123 DCHECK_EQ(State::kOnStack, state_.Get(node));
125 if (node->IsDead())
return Pop();
127 Node::Inputs node_inputs = node->inputs();
130 int start = entry.input_index < node_inputs.count() ? entry.input_index : 0;
131 for (
int i = start;
i < node_inputs.count(); ++
i) {
132 Node* input = node_inputs[
i];
133 if (input != node && Recurse(input)) {
134 entry.input_index =
i + 1;
138 for (
int i = 0;
i < start; ++
i) {
139 Node* input = node_inputs[
i];
140 if (input != node && Recurse(input)) {
141 entry.input_index =
i + 1;
147 NodeId
const max_id =
static_cast<NodeId
>(graph()->NodeCount() - 1);
150 Reduction reduction = Reduce(node);
153 if (!reduction.Changed())
return Pop();
156 Node*
const replacement = reduction.replacement();
157 if (replacement == node) {
159 Node::Inputs node_inputs = node->inputs();
160 for (
int i = 0;
i < node_inputs.count(); ++
i) {
161 Node* input = node_inputs[
i];
162 if (input != node && Recurse(input)) {
163 entry.input_index =
i + 1;
173 if (replacement != node) {
174 Replace(node, replacement, max_id);
177 for (Node*
const user : node->uses()) {
179 if (user != node) Revisit(user);
185 void GraphReducer::Replace(Node* node, Node* replacement) {
186 Replace(node, replacement, std::numeric_limits<NodeId>::max());
190 void GraphReducer::Replace(Node* node, Node* replacement, NodeId max_id) {
191 if (node == graph()->start()) graph()->SetStart(replacement);
192 if (node == graph()->end()) graph()->SetEnd(replacement);
193 if (replacement->id() <= max_id) {
196 for (Edge edge : node->use_edges()) {
197 Node*
const user = edge.from();
198 Verifier::VerifyEdgeInputReplacement(edge, replacement);
199 edge.UpdateTo(replacement);
201 if (user != node) Revisit(user);
207 for (Edge edge : node->use_edges()) {
208 Node*
const user = edge.from();
209 if (user->id() <= max_id) {
210 edge.UpdateTo(replacement);
212 if (user != node) Revisit(user);
216 if (node->uses().empty()) node->Kill();
219 Recurse(replacement);
224 void GraphReducer::ReplaceWithValue(Node* node, Node* value, Node* effect,
226 if (effect ==
nullptr && node->op()->EffectInputCount() > 0) {
227 effect = NodeProperties::GetEffectInput(node);
229 if (control ==
nullptr && node->op()->ControlInputCount() > 0) {
230 control = NodeProperties::GetControlInput(node);
234 for (Edge edge : node->use_edges()) {
235 Node*
const user = edge.from();
236 DCHECK(!user->IsDead());
237 if (NodeProperties::IsControlEdge(edge)) {
238 if (user->opcode() == IrOpcode::kIfSuccess) {
239 Replace(user, control);
240 }
else if (user->opcode() == IrOpcode::kIfException) {
241 DCHECK_NOT_NULL(dead_);
242 edge.UpdateTo(dead_);
245 DCHECK_NOT_NULL(control);
246 edge.UpdateTo(control);
249 }
else if (NodeProperties::IsEffectEdge(edge)) {
250 DCHECK_NOT_NULL(effect);
251 edge.UpdateTo(effect);
254 DCHECK_NOT_NULL(value);
255 edge.UpdateTo(value);
262 void GraphReducer::Pop() {
263 Node* node = stack_.top().node;
264 state_.Set(node, State::kVisited);
269 void GraphReducer::Push(Node*
const node) {
270 DCHECK_NE(State::kOnStack, state_.Get(node));
271 state_.Set(node, State::kOnStack);
272 stack_.push({node, 0});
276 bool GraphReducer::Recurse(Node* node) {
277 if (state_.Get(node) > State::kRevisit)
return false;
283 void GraphReducer::Revisit(Node* node) {
284 if (state_.Get(node) == State::kVisited) {
285 state_.Set(node, State::kRevisit);