Index: src/compiler/int64-lowering.cc |
diff --git a/src/compiler/int64-lowering.cc b/src/compiler/int64-lowering.cc |
index 403d4c961cfc3ebf6668c674138bda1cd1ea6546..b16d245fed113f67c9a54acbf9bc4933e7c8e9cd 100644 |
--- a/src/compiler/int64-lowering.cc |
+++ b/src/compiler/int64-lowering.cc |
@@ -27,8 +27,11 @@ Int64Lowering::Int64Lowering(Graph* graph, MachineOperatorBuilder* machine, |
common_(common), |
state_(graph, 3), |
stack_(zone), |
- replacements_(zone->NewArray<Replacement>(graph->NodeCount())), |
- signature_(signature) { |
+ replacements_(nullptr), |
+ signature_(signature), |
+ placeholder_(graph->NewNode(common->Parameter(-2, "placeholder"), |
+ graph->start())) { |
+ replacements_ = zone->NewArray<Replacement>(graph->NodeCount()); |
memset(replacements_, 0, sizeof(Replacement) * graph->NodeCount()); |
} |
@@ -36,21 +39,28 @@ void Int64Lowering::LowerGraph() { |
if (!machine()->Is32()) { |
return; |
} |
- stack_.push({graph()->end(), 0}); |
+ stack_.push_back({graph()->end(), 0}); |
state_.Set(graph()->end(), State::kOnStack); |
while (!stack_.empty()) { |
- NodeState& top = stack_.top(); |
+ NodeState& top = stack_.back(); |
if (top.input_index == top.node->InputCount()) { |
// All inputs of top have already been lowered, now lower top. |
- stack_.pop(); |
+ stack_.pop_back(); |
state_.Set(top.node, State::kVisited); |
LowerNode(top.node); |
} else { |
// Push the next input onto the stack. |
Node* input = top.node->InputAt(top.input_index++); |
if (state_.Get(input) == State::kUnvisited) { |
- stack_.push({input, 0}); |
+ if (input->opcode() == IrOpcode::kPhi) { |
+ // To break cycles with phi nodes we push phis on a separate stack so |
+ // that they are processed after all other nodes. |
+ PreparePhiReplacement(input); |
+ stack_.push_front({input, 0}); |
+ } else { |
+ stack_.push_back({input, 0}); |
+ } |
state_.Set(input, State::kOnStack); |
} |
} |
@@ -577,6 +587,22 @@ void Int64Lowering::LowerNode(Node* node) { |
graph()->NewNode(common()->Int32Constant(0))); |
break; |
} |
+ case IrOpcode::kPhi: { |
+ MachineRepresentation rep = PhiRepresentationOf(node->op()); |
+ if (rep == MachineRepresentation::kWord64) { |
+ // The replacement nodes have already been created, we only have to |
+ // replace placeholder nodes. |
+ Node* low_node = GetReplacementLow(node); |
+ Node* high_node = GetReplacementHigh(node); |
+ for (int i = 0; i < node->op()->ValueInputCount(); i++) { |
+ low_node->ReplaceInput(i, GetReplacementLow(node->InputAt(i))); |
+ high_node->ReplaceInput(i, GetReplacementHigh(node->InputAt(i))); |
+ } |
+ } else { |
+ DefaultLowering(node); |
+ } |
+ break; |
+ } |
default: { DefaultLowering(node); } |
} |
@@ -643,6 +669,32 @@ Node* Int64Lowering::GetReplacementHigh(Node* node) { |
DCHECK(result); |
return result; |
} |
+ |
+void Int64Lowering::PreparePhiReplacement(Node* phi) { |
+ MachineRepresentation rep = PhiRepresentationOf(phi->op()); |
+ if (rep == MachineRepresentation::kWord64) { |
+ // We have to create the replacements for a phi node before we actually |
+ // lower the phi to break potential cycles in the graph. The replacements of |
+ // input nodes do not exist yet, so we use a placeholder node to pass the |
+ // graph verifier. |
+ int value_count = phi->op()->ValueInputCount(); |
+ Node** inputs_low = zone()->NewArray<Node*>(value_count + 1); |
+ Node** inputs_high = zone()->NewArray<Node*>(value_count + 1); |
+ for (int i = 0; i < value_count; i++) { |
+ inputs_low[i] = placeholder_; |
+ inputs_high[i] = placeholder_; |
+ } |
+ inputs_low[value_count] = NodeProperties::GetControlInput(phi, 0); |
+ inputs_high[value_count] = NodeProperties::GetControlInput(phi, 0); |
+ ReplaceNode(phi, |
+ graph()->NewNode( |
+ common()->Phi(MachineRepresentation::kWord32, value_count), |
+ value_count + 1, inputs_low, false), |
+ graph()->NewNode( |
+ common()->Phi(MachineRepresentation::kWord32, value_count), |
+ value_count + 1, inputs_high, false)); |
+ } |
+} |
} // namespace compiler |
} // namespace internal |
} // namespace v8 |