Commit 682df6dd authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] New attempt to implement the Int64Lowering of phis.

The new implementation deals with cycles in the TF graph in two steps:
1) The lowering of phis is delayed to avoid cyclic dependencies.
2) The replacement nodes of phis are created already when the phi is
   pushed onto the stack so that other nodes can use these replacements
   for their lowering.

R=titzer@chromium.org

Review URL: https://codereview.chromium.org/1844553002

Cr-Commit-Position: refs/heads/master@{#35126}
parent 6f75a216
......@@ -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
......@@ -47,6 +47,7 @@ class Int64Lowering {
Node* GetReplacementLow(Node* node);
bool HasReplacementHigh(Node* node);
Node* GetReplacementHigh(Node* node);
void PreparePhiReplacement(Node* phi);
struct NodeState {
Node* node;
......@@ -58,9 +59,10 @@ class Int64Lowering {
MachineOperatorBuilder* machine_;
CommonOperatorBuilder* common_;
NodeMarker<State> state_;
ZoneStack<NodeState> stack_;
ZoneDeque<NodeState> stack_;
Replacement* replacements_;
Signature<MachineRepresentation>* signature_;
Node* placeholder_;
};
} // namespace compiler
......
......@@ -41,7 +41,7 @@
#define FOREACH_I64_OPERATOR(V) \
V(DepthFirst, true) \
V(I64Phi, false) \
V(I64Phi, true) \
V(I64Const, true) \
V(I64Return, true) \
V(I64Param, true) \
......
......@@ -29,7 +29,6 @@ class GraphTest : public TestWithContext, public TestWithIsolateAndZone {
explicit GraphTest(int num_parameters = 1);
~GraphTest() override;
protected:
Node* start() { return graph()->start(); }
Node* end() { return graph()->end(); }
......
......@@ -642,6 +642,48 @@ TEST_F(Int64LoweringTest, I64Popcnt) {
IsWord32Popcnt(IsInt32Constant(high_word_value(0)))),
IsInt32Constant(0), start(), start()));
}
TEST_F(Int64LoweringTest, I64PhiWord64) {
LowerGraph(graph()->NewNode(common()->Phi(MachineRepresentation::kWord64, 2),
Int64Constant(value(0)), Int64Constant(value(1)),
start()),
MachineRepresentation::kWord64);
EXPECT_THAT(graph()->end()->InputAt(1),
IsReturn2(IsPhi(MachineRepresentation::kWord32,
IsInt32Constant(low_word_value(0)),
IsInt32Constant(low_word_value(1)), start()),
IsPhi(MachineRepresentation::kWord32,
IsInt32Constant(high_word_value(0)),
IsInt32Constant(high_word_value(1)), start()),
start(), start()));
}
void TestPhi(Int64LoweringTest* test, MachineRepresentation rep, Node* v1,
Node* v2) {
test->LowerGraph(test->graph()->NewNode(test->common()->Phi(rep, 2), v1, v2,
test->start()),
rep);
EXPECT_THAT(test->graph()->end()->InputAt(1),
IsReturn(IsPhi(rep, v1, v2, test->start()), test->start(),
test->start()));
}
TEST_F(Int64LoweringTest, I64PhiFloat32) {
TestPhi(this, MachineRepresentation::kFloat32, Float32Constant(1.5),
Float32Constant(2.5));
}
TEST_F(Int64LoweringTest, I64PhiFloat64) {
TestPhi(this, MachineRepresentation::kFloat64, Float32Constant(1.5),
Float32Constant(2.5));
}
TEST_F(Int64LoweringTest, I64PhiWord32) {
TestPhi(this, MachineRepresentation::kWord32, Float32Constant(1),
Float32Constant(2));
}
} // namespace compiler
} // namespace internal
} // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment