| Index: src/compiler/control-reducer.cc
|
| diff --git a/src/compiler/control-reducer.cc b/src/compiler/control-reducer.cc
|
| index 7f4bf317496270ce723f3adf46bd3b5a7e5d02e6..d40d414cfe1785ddb6f41e673af795432ba74a91 100644
|
| --- a/src/compiler/control-reducer.cc
|
| +++ b/src/compiler/control-reducer.cc
|
| @@ -169,44 +169,80 @@ class ControlReducerImpl {
|
| Node* ConnectNTL(Node* loop) {
|
| TRACE(("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic()));
|
|
|
| - if (loop->opcode() != IrOpcode::kTerminate) {
|
| - // Insert a {Terminate} node if the loop has effects.
|
| - ZoneDeque<Node*> effects(zone_);
|
| - for (Node* const use : loop->uses()) {
|
| - if (use->opcode() == IrOpcode::kEffectPhi) effects.push_back(use);
|
| - }
|
| - int count = static_cast<int>(effects.size());
|
| - if (count > 0) {
|
| - Node** inputs = zone_->NewArray<Node*>(1 + count);
|
| - for (int i = 0; i < count; i++) inputs[i] = effects[i];
|
| - inputs[count] = loop;
|
| - loop = graph()->NewNode(common_->Terminate(count), 1 + count, inputs);
|
| - TRACE(("AddTerminate: #%d:%s[%d]\n", loop->id(), loop->op()->mnemonic(),
|
| - count));
|
| + Node* always = graph()->NewNode(common_->Always());
|
| + // Mark the node as visited so that we can revisit later.
|
| + MarkAsVisited(always);
|
| +
|
| + Node* branch = graph()->NewNode(common_->Branch(), always, loop);
|
| + // Mark the node as visited so that we can revisit later.
|
| + MarkAsVisited(branch);
|
| +
|
| + Node* if_true = graph()->NewNode(common_->IfTrue(), branch);
|
| + // Mark the node as visited so that we can revisit later.
|
| + MarkAsVisited(if_true);
|
| +
|
| + Node* if_false = graph()->NewNode(common_->IfFalse(), branch);
|
| + // Mark the node as visited so that we can revisit later.
|
| + MarkAsVisited(if_false);
|
| +
|
| + // Hook up the branch into the loop and collect all loop effects.
|
| + NodeVector effects(zone_);
|
| + for (auto edge : loop->use_edges()) {
|
| + DCHECK_EQ(loop, edge.to());
|
| + DCHECK(NodeProperties::IsControlEdge(edge));
|
| + if (edge.from() == branch) continue;
|
| + switch (edge.from()->opcode()) {
|
| +#define CASE(Opcode) case IrOpcode::k##Opcode:
|
| + CONTROL_OP_LIST(CASE)
|
| +#undef CASE
|
| + // Update all control nodes (except {branch}) pointing to the {loop}.
|
| + edge.UpdateTo(if_true);
|
| + break;
|
| + case IrOpcode::kEffectPhi:
|
| + effects.push_back(edge.from());
|
| + break;
|
| + default:
|
| + break;
|
| }
|
| }
|
|
|
| - Node* to_add = loop;
|
| + // Compute effects for the Return.
|
| + Node* effect = graph()->start();
|
| + int const effects_count = static_cast<int>(effects.size());
|
| + if (effects_count == 1) {
|
| + effect = effects[0];
|
| + } else if (effects_count > 1) {
|
| + effect = graph()->NewNode(common_->EffectSet(effects_count),
|
| + effects_count, &effects.front());
|
| + // Mark the node as visited so that we can revisit later.
|
| + MarkAsVisited(effect);
|
| + }
|
| +
|
| + // Add a return to connect the NTL to the end.
|
| + Node* ret = graph()->NewNode(
|
| + common_->Return(), jsgraph_->UndefinedConstant(), effect, if_false);
|
| + // Mark the node as visited so that we can revisit later.
|
| + MarkAsVisited(ret);
|
| +
|
| Node* end = graph()->end();
|
| CHECK_EQ(IrOpcode::kEnd, end->opcode());
|
| Node* merge = end->InputAt(0);
|
| if (merge == NULL || merge->opcode() == IrOpcode::kDead) {
|
| - // The end node died; just connect end to {loop}.
|
| - end->ReplaceInput(0, loop);
|
| + // The end node died; just connect end to {ret}.
|
| + end->ReplaceInput(0, ret);
|
| } else if (merge->opcode() != IrOpcode::kMerge) {
|
| - // Introduce a final merge node for {end->InputAt(0)} and {loop}.
|
| - merge = graph()->NewNode(common_->Merge(2), merge, loop);
|
| + // Introduce a final merge node for {end->InputAt(0)} and {ret}.
|
| + merge = graph()->NewNode(common_->Merge(2), merge, ret);
|
| end->ReplaceInput(0, merge);
|
| - to_add = merge;
|
| + ret = merge;
|
| // Mark the node as visited so that we can revisit later.
|
| - EnsureStateSize(merge->id());
|
| - state_[merge->id()] = kVisited;
|
| + MarkAsVisited(merge);
|
| } else {
|
| // Append a new input to the final merge at the end.
|
| - merge->AppendInput(graph()->zone(), loop);
|
| + merge->AppendInput(graph()->zone(), ret);
|
| merge->set_op(common_->Merge(merge->InputCount()));
|
| }
|
| - return to_add;
|
| + return ret;
|
| }
|
|
|
| void AddNodesReachableFromEnd(ReachabilityMarker& marked, NodeVector& nodes) {
|
| @@ -337,6 +373,13 @@ class ControlReducerImpl {
|
| }
|
| }
|
|
|
| + // Mark {node} as visited.
|
| + void MarkAsVisited(Node* node) {
|
| + size_t id = static_cast<size_t>(node->id());
|
| + EnsureStateSize(id);
|
| + state_[id] = kVisited;
|
| + }
|
| +
|
| Node* dead() {
|
| if (dead_ == NULL) dead_ = graph()->NewNode(common_->Dead());
|
| return dead_;
|
|
|