Commit 2b93b8aa authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Change End to take a variable number of inputs.

This simplifies the handling of the End node. Based on this CL we will
finally fix terminating every loop from the beginning (via Terminate
nodes) and fix inlining of Throw, Deoptimize and Terminate.

R=mstarzinger@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#28620}
parent d2334e90
......@@ -440,7 +440,7 @@ AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
try_nesting_level_(0),
input_buffer_size_(0),
input_buffer_(nullptr),
exit_control_(nullptr),
exit_controls_(local_zone),
loop_assignment_analysis_(loop),
state_values_cache_(jsgraph),
liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()),
......@@ -535,7 +535,11 @@ bool AstGraphBuilder::CreateGraph(bool constant_context, bool stack_check) {
}
// Finish the basic structure of the graph.
graph()->SetEnd(graph()->NewNode(common()->End(), exit_control()));
DCHECK_NE(0u, exit_controls_.size());
int const input_count = static_cast<int>(exit_controls_.size());
Node** const inputs = &exit_controls_.front();
Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
graph()->SetEnd(end);
// Compute local variable liveness information and use it to relax
// frame states.
......@@ -3571,11 +3575,8 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
if (environment()->IsMarkedAsUnreachable()) return;
if (exit_control() != NULL) {
exit = MergeControl(exit_control(), exit);
}
environment()->MarkAsUnreachable();
set_exit_control(exit);
exit_controls_.push_back(exit);
}
......
......@@ -96,8 +96,8 @@ class AstGraphBuilder : public AstVisitor {
int input_buffer_size_;
Node** input_buffer_;
// Merge of all control nodes that exit the function body.
Node* exit_control_;
// Control nodes that exit the function body.
ZoneVector<Node*> exit_controls_;
// Result of loop assignment analysis performed before graph creation.
LoopAssignmentAnalysis* loop_assignment_analysis_;
......@@ -130,14 +130,12 @@ class AstGraphBuilder : public AstVisitor {
ZoneVector<Handle<Object>>* globals() { return &globals_; }
Scope* current_scope() const;
Node* current_context() const;
Node* exit_control() const { return exit_control_; }
LivenessAnalyzer* liveness_analyzer() { return &liveness_analyzer_; }
void set_environment(Environment* env) { environment_ = env; }
void set_ast_context(AstContext* ctx) { ast_context_ = ctx; }
void set_execution_control(ControlScope* ctrl) { execution_control_ = ctrl; }
void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; }
void set_exit_control(Node* exit) { exit_control_ = exit; }
// Create the main graph body by visiting the AST.
void CreateGraphBody(bool stack_check);
......
......@@ -102,7 +102,6 @@ std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) {
#define CACHED_OP_LIST(V) \
V(Dead, Operator::kFoldable, 0, 0, 0, 0, 0, 1) \
V(End, Operator::kKontrol, 0, 0, 1, 0, 0, 0) \
V(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
V(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
V(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
......@@ -116,6 +115,17 @@ std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) {
V(OsrLoopEntry, Operator::kFoldable, 0, 1, 1, 0, 1, 1)
#define CACHED_END_LIST(V) \
V(1) \
V(2) \
V(3) \
V(4) \
V(5) \
V(6) \
V(7) \
V(8)
#define CACHED_EFFECT_PHI_LIST(V) \
V(1) \
V(2) \
......@@ -200,6 +210,19 @@ struct CommonOperatorGlobalCache final {
CACHED_OP_LIST(CACHED)
#undef CACHED
template <size_t kInputCount>
struct EndOperator final : public Operator {
EndOperator()
: Operator( // --
IrOpcode::kEnd, Operator::kKontrol, // opcode
"End", // name
0, 0, kInputCount, 0, 0, 0) {} // counts
};
#define CACHED_END(input_count) \
EndOperator<input_count> kEnd##input_count##Operator;
CACHED_END_LIST(CACHED_END)
#undef CACHED_END
template <BranchHint kBranchHint>
struct BranchOperator final : public Operator1<BranchHint> {
BranchOperator()
......@@ -329,6 +352,25 @@ CACHED_OP_LIST(CACHED)
#undef CACHED
const Operator* CommonOperatorBuilder::End(size_t control_input_count) {
DCHECK_NE(0u, control_input_count); // Disallow empty ends.
switch (control_input_count) {
#define CACHED_END(input_count) \
case input_count: \
return &cache_.kEnd##input_count##Operator;
CACHED_END_LIST(CACHED_END)
#undef CACHED_END
default:
break;
}
// Uncached.
return new (zone()) Operator( //--
IrOpcode::kEnd, Operator::kKontrol, // opcode
"End", // name
0, 0, control_input_count, 0, 0, 0); // counts
}
const Operator* CommonOperatorBuilder::Branch(BranchHint hint) {
switch (hint) {
case BranchHint::kNone:
......
......@@ -89,7 +89,7 @@ class CommonOperatorBuilder final : public ZoneObject {
explicit CommonOperatorBuilder(Zone* zone);
const Operator* Dead();
const Operator* End();
const Operator* End(size_t control_input_count);
const Operator* Branch(BranchHint = BranchHint::kNone);
const Operator* IfTrue();
const Operator* IfFalse();
......
......@@ -184,25 +184,13 @@ class ControlReducerImpl final : public AdvancedReducer {
Node* end = graph()->end();
if (end->opcode() == IrOpcode::kDead) {
// End is actually the dead node. Make a new end.
end = graph()->NewNode(common()->End(), terminate);
end = graph()->NewNode(common()->End(1), terminate);
graph()->SetEnd(end);
return end;
}
// End is not dead.
Node* merge = end->InputAt(0);
if (merge == NULL || merge->opcode() == IrOpcode::kDead) {
// The end node died; just connect end to {terminate}.
end->ReplaceInput(0, terminate);
} else if (merge->opcode() != IrOpcode::kMerge) {
// Introduce a final merge node for {end->InputAt(0)} and {terminate}.
merge = graph()->NewNode(common()->Merge(2), merge, terminate);
end->ReplaceInput(0, merge);
terminate = merge;
} else {
// Append a new input to the final merge at the end.
merge->AppendInput(graph()->zone(), terminate);
merge->set_op(common()->Merge(merge->InputCount()));
}
// Append a new input to the end.
end->AppendInput(graph()->zone(), terminate);
end->set_op(common()->End(end->InputCount()));
return terminate;
}
......@@ -313,6 +301,9 @@ class ControlReducerImpl final : public AdvancedReducer {
case IrOpcode::kEffectPhi:
result = ReducePhi(node);
break;
case IrOpcode::kEnd:
result = ReduceEnd(node);
break;
default:
break;
}
......@@ -404,6 +395,31 @@ class ControlReducerImpl final : public AdvancedReducer {
return branch;
}
// Reduce end by trimming away dead inputs.
Node* ReduceEnd(Node* node) {
// Count the number of live inputs.
int live = 0;
for (int index = 0; index < node->InputCount(); ++index) {
// Skip dead inputs.
if (node->InputAt(index)->opcode() == IrOpcode::kDead) continue;
// Compact live inputs.
if (index != live) node->ReplaceInput(live, node->InputAt(index));
++live;
}
TRACE("ReduceEnd: #%d:%s (%d of %d live)\n", node->id(),
node->op()->mnemonic(), live, node->InputCount());
if (live == 0) return dead(); // No remaining inputs.
if (live < node->InputCount()) {
node->set_op(common()->End(live));
node->TrimInputCount(live);
}
return node;
}
// Reduce merges by trimming away dead inputs from the merge and phis.
Node* ReduceMerge(Node* node) {
// Count the number of live inputs.
......
......@@ -165,50 +165,36 @@ Reduction JSInliner::InlineCall(Node* call, Node* start, Node* end) {
}
}
// TODO(turbofan): This can be unified once End takes a variable number of
// inputs.
Node* value_output;
Node* effect_output;
Node* control_output;
Node* final_merge = NodeProperties::GetControlInput(end);
if (final_merge->opcode() == IrOpcode::kReturn) {
value_output = NodeProperties::GetValueInput(final_merge, 0);
effect_output = NodeProperties::GetEffectInput(final_merge, 0);
control_output = NodeProperties::GetControlInput(final_merge, 0);
} else {
NodeVector values(local_zone_);
NodeVector effects(local_zone_);
NodeVector controls(local_zone_);
DCHECK_EQ(IrOpcode::kMerge, final_merge->opcode());
for (Node* const input : final_merge->inputs()) {
switch (input->opcode()) {
case IrOpcode::kReturn:
values.push_back(NodeProperties::GetValueInput(input, 0));
effects.push_back(NodeProperties::GetEffectInput(input));
controls.push_back(NodeProperties::GetControlInput(input));
break;
default:
// TODO(turbofan): Handle Throw, Terminate and Deoptimize here.
UNREACHABLE();
break;
}
NodeVector values(local_zone_);
NodeVector effects(local_zone_);
NodeVector controls(local_zone_);
for (Node* const input : end->inputs()) {
switch (input->opcode()) {
case IrOpcode::kReturn:
values.push_back(NodeProperties::GetValueInput(input, 0));
effects.push_back(NodeProperties::GetEffectInput(input));
controls.push_back(NodeProperties::GetControlInput(input));
break;
default:
// TODO(turbofan): Handle Throw, Terminate and Deoptimize here.
UNREACHABLE();
break;
}
DCHECK_NE(0u, values.size());
DCHECK_EQ(values.size(), effects.size());
DCHECK_EQ(values.size(), controls.size());
int const input_count = static_cast<int>(controls.size());
control_output = jsgraph_->graph()->NewNode(
jsgraph_->common()->Merge(input_count), input_count, &controls.front());
values.push_back(control_output);
effects.push_back(control_output);
value_output = jsgraph_->graph()->NewNode(
jsgraph_->common()->Phi(kMachAnyTagged, input_count),
static_cast<int>(values.size()), &values.front());
effect_output = jsgraph_->graph()->NewNode(
jsgraph_->common()->EffectPhi(input_count),
static_cast<int>(effects.size()), &effects.front());
}
DCHECK_NE(0u, values.size());
DCHECK_EQ(values.size(), effects.size());
DCHECK_EQ(values.size(), controls.size());
int const input_count = static_cast<int>(controls.size());
Node* control_output = jsgraph_->graph()->NewNode(
jsgraph_->common()->Merge(input_count), input_count, &controls.front());
values.push_back(control_output);
effects.push_back(control_output);
Node* value_output = jsgraph_->graph()->NewNode(
jsgraph_->common()->Phi(kMachAnyTagged, input_count),
static_cast<int>(values.size()), &values.front());
Node* effect_output = jsgraph_->graph()->NewNode(
jsgraph_->common()->EffectPhi(input_count),
static_cast<int>(effects.size()), &effects.front());
ReplaceWithValue(call, value_output, effect_output, control_output);
......
......@@ -163,16 +163,8 @@ void NodeProperties::RemoveNonValueInputs(Node* node) {
void NodeProperties::MergeControlToEnd(Graph* graph,
CommonOperatorBuilder* common,
Node* node) {
// Connect the node to the merge exiting the graph.
Node* end_pred = NodeProperties::GetControlInput(graph->end());
if (end_pred->opcode() == IrOpcode::kMerge) {
int inputs = end_pred->op()->ControlInputCount() + 1;
end_pred->AppendInput(graph->zone(), node);
end_pred->set_op(common->Merge(inputs));
} else {
Node* merge = graph->NewNode(common->Merge(2), end_pred, node);
NodeProperties::ReplaceControlInput(graph->end(), merge);
}
graph->end()->AppendInput(graph->zone(), node);
graph->end()->set_op(common->End(graph->end()->InputCount()));
}
......
......@@ -228,20 +228,15 @@ static void PeelOuterLoopsForOsr(Graph* graph, CommonOperatorBuilder* common,
}
// Merge the ends of the graph copies.
Node* end = graph->end();
tmp_inputs.clear();
for (int i = -1; i < static_cast<int>(copies.size()); i++) {
Node* input = end->InputAt(0);
if (i >= 0) input = copies[i]->at(input->id());
if (input->opcode() == IrOpcode::kMerge) {
for (Node* node : input->inputs()) tmp_inputs.push_back(node);
} else {
tmp_inputs.push_back(input);
Node* const end = graph->end();
int const input_count = end->InputCount();
for (int i = 0; i < input_count; ++i) {
NodeId const id = end->InputAt(i)->id();
for (NodeVector* const copy : copies) {
end->AppendInput(graph->zone(), copy->at(id));
end->set_op(common->End(end->InputCount()));
}
}
int count = static_cast<int>(tmp_inputs.size());
Node* merge = graph->NewNode(common->Merge(count), count, &tmp_inputs[0]);
end->ReplaceInput(0, merge);
if (FLAG_trace_turbo_graph) { // Simple textual RPO.
OFStream os(stdout);
......
......@@ -37,7 +37,7 @@ void SimplifiedGraphBuilder::Return(Node* value) {
void SimplifiedGraphBuilder::End() {
Node* end = graph()->NewNode(common()->End(), return_);
Node* end = graph()->NewNode(common()->End(1), return_);
graph()->SetEnd(end);
}
......
......@@ -88,7 +88,7 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> {
Node* change = this->graph()->NewNode(op, p0);
Node* ret = this->graph()->NewNode(this->common()->Return(), change,
this->start(), this->start());
Node* end = this->graph()->NewNode(this->common()->End(), ret);
Node* end = this->graph()->NewNode(this->common()->End(1), ret);
this->graph()->SetEnd(end);
LowerChange(change);
}
......@@ -104,7 +104,7 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> {
change, this->start(), this->start());
Node* ret = this->graph()->NewNode(
this->common()->Return(), this->Int32Constant(0), store, this->start());
Node* end = this->graph()->NewNode(this->common()->End(), ret);
Node* end = this->graph()->NewNode(this->common()->End(1), ret);
this->graph()->SetEnd(end);
LowerChange(change);
}
......@@ -119,7 +119,7 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> {
Node* change = this->graph()->NewNode(op, load);
Node* ret = this->graph()->NewNode(this->common()->Return(), change,
this->start(), this->start());
Node* end = this->graph()->NewNode(this->common()->End(), ret);
Node* end = this->graph()->NewNode(this->common()->End(1), ret);
this->graph()->SetEnd(end);
LowerChange(change);
}
......
......@@ -69,7 +69,7 @@ class ControlReducerTester : HandleAndZoneScope {
graph(main_zone()),
jsgraph(main_isolate(), &graph, &common, NULL, NULL),
start(graph.NewNode(common.Start(1))),
end(graph.NewNode(common.End(), start)),
end(graph.NewNode(common.End(1), start)),
p0(graph.NewNode(common.Parameter(0), start)),
zero(jsgraph.Int32Constant(0)),
one(jsgraph.OneConstant()),
......@@ -161,7 +161,7 @@ class ControlReducerTester : HandleAndZoneScope {
void ReducePhiIterative(Node* expect, Node* phi) {
p0->ReplaceInput(0, start); // hack: parameters may be trimmed.
Node* ret = graph.NewNode(common.Return(), phi, start, start);
Node* end = graph.NewNode(common.End(), ret);
Node* end = graph.NewNode(common.End(1), ret);
graph.SetEnd(end);
ControlReducer::ReduceGraph(main_zone(), &jsgraph);
CheckInputs(end, ret);
......@@ -175,7 +175,7 @@ class ControlReducerTester : HandleAndZoneScope {
void ReduceMergeIterative(Node* expect, Node* merge) {
p0->ReplaceInput(0, start); // hack: parameters may be trimmed.
Node* end = graph.NewNode(common.End(), merge);
Node* end = graph.NewNode(common.End(1), merge);
graph.SetEnd(end);
ReduceGraph();
CheckInputs(end, expect);
......@@ -412,7 +412,7 @@ TEST(Trim_cycle1) {
ControlReducerTester T;
Node* loop = T.graph.NewNode(T.common.Loop(1), T.start, T.start);
loop->ReplaceInput(1, loop);
Node* end = T.graph.NewNode(T.common.End(), loop);
Node* end = T.graph.NewNode(T.common.End(1), loop);
T.graph.SetEnd(end);
CHECK(IsUsedBy(T.start, loop));
......@@ -434,7 +434,7 @@ TEST(Trim_cycle2) {
ControlReducerTester T;
Node* loop = T.graph.NewNode(T.common.Loop(2), T.start, T.start);
loop->ReplaceInput(1, loop);
Node* end = T.graph.NewNode(T.common.End(), loop);
Node* end = T.graph.NewNode(T.common.End(1), loop);
Node* phi =
T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, loop);
T.graph.SetEnd(end);
......@@ -1072,7 +1072,7 @@ TEST(CMergeReduce_dead_chain1) {
for (int j = 0; j < i; j++) {
merge = R.graph.NewNode(R.common.Merge(1), merge);
}
Node* end = R.graph.NewNode(R.common.End(), merge);
Node* end = R.graph.NewNode(R.common.End(1), merge);
R.graph.SetEnd(end);
R.ReduceGraph();
CHECK(merge->IsDead());
......
......@@ -41,7 +41,7 @@ class JSConstantCacheTester : public HandleAndZoneScope,
JSGraph(main_isolate(), &main_graph_, &main_common_, &main_javascript_,
&main_machine_) {
main_graph_.SetStart(main_graph_.NewNode(common()->Start(0)));
main_graph_.SetEnd(main_graph_.NewNode(common()->End()));
main_graph_.SetEnd(main_graph_.NewNode(common()->End(1)));
main_typer_.Run();
}
......
......@@ -222,7 +222,7 @@ TEST(SpecializeToContext) {
Node* ret =
t.graph()->NewNode(t.common()->Return(), add, effect_use, start);
Node* end = t.graph()->NewNode(t.common()->End(), ret);
Node* end = t.graph()->NewNode(t.common()->End(1), ret);
USE(end);
t.graph()->SetEnd(end);
......
......@@ -41,7 +41,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
typer(main_isolate(), &graph, MaybeHandle<Context>()),
context_node(NULL) {
graph.SetStart(graph.NewNode(common.Start(num_parameters)));
graph.SetEnd(graph.NewNode(common.End()));
graph.SetEnd(graph.NewNode(common.End(1)));
typer.Run();
}
......
......@@ -41,7 +41,7 @@ class LoopFinderTester : HandleAndZoneScope {
graph(main_zone()),
jsgraph(main_isolate(), &graph, &common, NULL, NULL),
start(graph.NewNode(common.Start(1))),
end(graph.NewNode(common.End(), start)),
end(graph.NewNode(common.End(1), start)),
p0(graph.NewNode(common.Parameter(0), start)),
zero(jsgraph.Int32Constant(0)),
one(jsgraph.OneConstant()),
......
......@@ -51,7 +51,7 @@ class OsrDeconstructorTester : public HandleAndZoneScope {
jsgraph(main_isolate(), &graph, &common, NULL, NULL),
start(graph.NewNode(common.Start(1))),
p0(graph.NewNode(common.Parameter(0), start)),
end(graph.NewNode(common.End(), start)),
end(graph.NewNode(common.End(1), start)),
osr_normal_entry(graph.NewNode(common.OsrNormalEntry(), start, start)),
osr_loop_entry(graph.NewNode(common.OsrLoopEntry(), start, start)),
self(graph.NewNode(common.Int32Constant(0xaabbccdd))) {
......@@ -377,7 +377,7 @@ TEST(Deconstruct_osr_nested1) {
Node* ret =
T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit);
Node* end = T.graph.NewNode(T.common.End(), ret);
Node* end = T.graph.NewNode(T.common.End(1), ret);
T.graph.SetEnd(end);
T.DeconstructOsr();
......@@ -444,7 +444,7 @@ TEST(Deconstruct_osr_nested2) {
Node* ret =
T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit);
Node* end = T.graph.NewNode(T.common.End(), ret);
Node* end = T.graph.NewNode(T.common.End(1), ret);
T.graph.SetEnd(end);
T.DeconstructOsr();
......@@ -549,7 +549,7 @@ TEST(Deconstruct_osr_nested3) {
Node* ret =
T.graph.NewNode(T.common.Return(), loop0_cntr, T.start, loop0.exit);
Node* end = T.graph.NewNode(T.common.End(), ret);
Node* end = T.graph.NewNode(T.common.End(1), ret);
T.graph.SetEnd(end);
T.DeconstructOsr();
......
......@@ -50,7 +50,7 @@ TEST(RunMathFloorStub) {
js.UndefinedConstant(), js.UndefinedConstant(),
numberParam, dummyContext, start, start);
Node* ret = graph.NewNode(common.Return(), call, call, start);
Node* end = graph.NewNode(common.End(), ret);
Node* end = graph.NewNode(common.End(1), ret);
graph.SetStart(start);
graph.SetEnd(end);
FunctionTester ft(&graph);
......@@ -89,7 +89,7 @@ TEST(RunStringLengthTFStub) {
graph.NewNode(common.Call(descriptor), theCode, receiverParam, nameParam,
slotParam, vectorParam, dummyContext, start, start);
Node* ret = graph.NewNode(common.Return(), call, call, start);
Node* end = graph.NewNode(common.End(), ret);
Node* end = graph.NewNode(common.End(1), ret);
graph.SetStart(start);
graph.SetEnd(end);
FunctionTester ft(&graph);
......@@ -132,7 +132,7 @@ TEST(RunStringAddTFStub) {
Node* call = graph.NewNode(common.Call(descriptor), theCode, leftParam,
rightParam, dummyContext, start, start);
Node* ret = graph.NewNode(common.Return(), call, call, start);
Node* end = graph.NewNode(common.End(), ret);
Node* end = graph.NewNode(common.End(1), ret);
graph.SetStart(start);
graph.SetEnd(end);
FunctionTester ft(&graph);
......
......@@ -710,7 +710,7 @@ class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders {
graph()->SetStart(start);
ret =
graph()->NewNode(common()->Return(), jsgraph.Constant(0), start, start);
end = graph()->NewNode(common()->End(), ret);
end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
p0 = graph()->NewNode(common()->Parameter(0), start);
p1 = graph()->NewNode(common()->Parameter(1), start);
......
......@@ -49,7 +49,6 @@ const SharedOperator kSharedOperators[] = {
value_output_count, effect_output_count, control_output_count \
}
SHARED(Dead, Operator::kFoldable, 0, 0, 0, 0, 0, 1),
SHARED(End, Operator::kKontrol, 0, 0, 1, 0, 0, 0),
SHARED(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
SHARED(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
SHARED(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
......@@ -162,6 +161,9 @@ const double kDoubleValues[] = {-std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::signaling_NaN()};
const size_t kInputCounts[] = {3, 4, 100, 255, 1024, 65000};
const int32_t kInt32Values[] = {
std::numeric_limits<int32_t>::min(), -1914954528, -1698749618, -1578693386,
-1577976073, -1573998034, -1529085059, -1499540537, -1299205097,
......@@ -182,6 +184,22 @@ const BranchHint kHints[] = {BranchHint::kNone, BranchHint::kTrue,
} // namespace
TEST_F(CommonOperatorTest, End) {
TRACED_FOREACH(size_t, input_count, kInputCounts) {
const Operator* const op = common()->End(input_count);
EXPECT_EQ(IrOpcode::kEnd, op->opcode());
EXPECT_EQ(Operator::kKontrol, op->properties());
EXPECT_EQ(0, op->ValueInputCount());
EXPECT_EQ(0, op->EffectInputCount());
EXPECT_EQ(input_count, op->ControlInputCount());
EXPECT_EQ(input_count, OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(0, op->ValueOutputCount());
EXPECT_EQ(0, op->EffectOutputCount());
EXPECT_EQ(0, op->ControlOutputCount());
}
}
TEST_F(CommonOperatorTest, Branch) {
TRACED_FOREACH(BranchHint, hint, kHints) {
const Operator* const op = common()->Branch(hint);
......
......@@ -27,7 +27,7 @@ class ControlEquivalenceTest : public GraphTest {
protected:
void ComputeEquivalence(Node* node) {
graph()->SetEnd(graph()->NewNode(common()->End(), node));
graph()->SetEnd(graph()->NewNode(common()->End(1), node));
if (FLAG_trace_turbo) {
OFStream os(stdout);
os << AsDOT(*graph());
......@@ -79,7 +79,7 @@ class ControlEquivalenceTest : public GraphTest {
}
Node* End(Node* control) {
return Store(graph()->NewNode(common()->End(), control));
return Store(graph()->NewNode(common()->End(1), control));
}
private:
......
......@@ -62,7 +62,7 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch1) {
Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
Node* merge =
graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
graph()->SetEnd(graph()->NewNode(common()->End(), merge));
graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
Optimize();
Capture<Node*> switch_capture;
EXPECT_THAT(end(),
......@@ -93,7 +93,7 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch2) {
Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
Node* merge =
graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
graph()->SetEnd(graph()->NewNode(common()->End(), merge));
graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
Optimize();
Capture<Node*> switch_capture;
EXPECT_THAT(
......@@ -119,7 +119,7 @@ TEST_F(ControlFlowOptimizerTest, CloneBranch) {
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
graph()->SetEnd(graph()->NewNode(common()->End(), merge));
graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
Optimize();
Capture<Node*> branch1_capture, branch2_capture;
EXPECT_THAT(
......
......@@ -57,11 +57,10 @@ TEST_F(ControlReducerTest, NonTerminatingLoop) {
Node* loop = graph()->NewNode(common()->Loop(2), graph()->start());
loop->AppendInput(graph()->zone(), loop);
ReduceGraph();
EXPECT_THAT(
graph()->end(),
IsEnd(IsMerge(graph()->start(),
EXPECT_THAT(graph()->end(),
IsEnd(graph()->start(),
IsTerminate(graph()->start(),
AllOf(loop, IsLoop(graph()->start(), loop))))));
AllOf(loop, IsLoop(graph()->start(), loop)))));
}
......@@ -74,10 +73,9 @@ TEST_F(ControlReducerTest, NonTerminatingLoopWithEffectPhi) {
ReduceGraph();
EXPECT_THAT(
graph()->end(),
IsEnd(IsMerge(
graph()->start(),
IsTerminate(AllOf(ephi, IsEffectPhi(graph()->start(), ephi, loop)),
AllOf(loop, IsLoop(graph()->start(), loop))))));
IsEnd(graph()->start(),
IsTerminate(AllOf(ephi, IsEffectPhi(graph()->start(), ephi, loop)),
AllOf(loop, IsLoop(graph()->start(), loop)))));
}
......@@ -93,13 +91,12 @@ TEST_F(ControlReducerTest, NonTerminatingLoopWithTwoEffectPhis) {
ReduceGraph();
EXPECT_THAT(
graph()->end(),
IsEnd(IsMerge(
graph()->start(),
IsTerminate(
IsEffectSet(
AllOf(ephi1, IsEffectPhi(graph()->start(), ephi1, loop)),
AllOf(ephi2, IsEffectPhi(graph()->start(), ephi2, loop))),
AllOf(loop, IsLoop(graph()->start(), loop))))));
IsEnd(graph()->start(),
IsTerminate(
IsEffectSet(
AllOf(ephi1, IsEffectPhi(graph()->start(), ephi1, loop)),
AllOf(ephi2, IsEffectPhi(graph()->start(), ephi2, loop))),
AllOf(loop, IsLoop(graph()->start(), loop)))));
}
......@@ -320,7 +317,6 @@ TEST_F(ControlReducerTest, SelectTwoPhis) {
EXPECT_THAT(graph()->end(), IsEnd(ret));
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -13,7 +13,7 @@ namespace compiler {
GraphTest::GraphTest(int num_parameters) : common_(zone()), graph_(zone()) {
graph()->SetStart(graph()->NewNode(common()->Start(num_parameters)));
graph()->SetEnd(graph()->NewNode(common()->End(), graph()->start()));
graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
}
......
......@@ -267,7 +267,7 @@ TEST_F(JSIntrinsicLoweringTest, Likely) {
Node* const to_boolean =
graph()->NewNode(javascript()->ToBoolean(), likely, context);
Diamond d(graph(), common(), to_boolean);
graph()->SetEnd(graph()->NewNode(common()->End(), d.merge));
graph()->SetEnd(graph()->NewNode(common()->End(1), d.merge));
ASSERT_EQ(BranchHint::kNone, BranchHintOf(d.branch->op()));
Reduction const r = Reduce(likely);
......@@ -362,7 +362,7 @@ TEST_F(JSIntrinsicLoweringTest, Unlikely) {
Node* const to_boolean =
graph()->NewNode(javascript()->ToBoolean(), unlikely, context);
Diamond d(graph(), common(), to_boolean);
graph()->SetEnd(graph()->NewNode(common()->End(), d.merge));
graph()->SetEnd(graph()->NewNode(common()->End(1), d.merge));
ASSERT_EQ(BranchHint::kNone, BranchHintOf(d.branch->op()));
Reduction const r = Reduce(unlikely);
......
......@@ -114,7 +114,7 @@ TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstSmi) {
Node* ret = ReturnLoadNamedFromGlobal(
kName, graph()->start(), graph()->start(),
JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
Reduction r = Reduce(ret->InputAt(0),
JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
......@@ -131,7 +131,7 @@ TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstSmiWithDeoptimization) {
Node* ret = ReturnLoadNamedFromGlobal(
kName, graph()->start(), graph()->start(),
JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
Reduction r = Reduce(ret->InputAt(0),
JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
......@@ -157,7 +157,7 @@ TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstNumber) {
Node* ret = ReturnLoadNamedFromGlobal(
kName, graph()->start(), graph()->start(),
JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
Reduction r = Reduce(ret->InputAt(0),
JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
......@@ -175,7 +175,7 @@ TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstNumberWithDeoptimization) {
Node* ret = ReturnLoadNamedFromGlobal(
kName, graph()->start(), graph()->start(),
JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
Reduction r = Reduce(ret->InputAt(0),
JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
......@@ -201,7 +201,7 @@ TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstString) {
Node* ret = ReturnLoadNamedFromGlobal(
kName, graph()->start(), graph()->start(),
JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
Reduction r = Reduce(ret->InputAt(0),
JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
......@@ -219,7 +219,7 @@ TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstStringWithDeoptimization) {
Node* ret = ReturnLoadNamedFromGlobal(
kName, graph()->start(), graph()->start(),
JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
Reduction r = Reduce(ret->InputAt(0),
JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
......@@ -245,7 +245,7 @@ TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellSmi) {
Node* ret = ReturnLoadNamedFromGlobal(
kName, graph()->start(), graph()->start(),
JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
Reduction r = Reduce(ret->InputAt(0),
JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
......@@ -262,7 +262,7 @@ TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellSmiWithDeoptimization) {
Node* ret = ReturnLoadNamedFromGlobal(
kName, graph()->start(), graph()->start(),
JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
Reduction r = Reduce(ret->InputAt(0),
JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
......@@ -296,7 +296,7 @@ TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellString) {
Node* ret = ReturnLoadNamedFromGlobal(
kName, graph()->start(), graph()->start(),
JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
Reduction r = Reduce(ret->InputAt(0),
JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
......@@ -314,7 +314,7 @@ TEST_F(JSTypeFeedbackTest,
Node* ret = ReturnLoadNamedFromGlobal(
kName, graph()->start(), graph()->start(),
JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
Reduction r = Reduce(ret->InputAt(0),
JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
......
......@@ -1320,8 +1320,15 @@ class IsUnopMatcher final : public NodeMatcher {
} // namespace
Matcher<Node*> IsEnd(const Matcher<Node*>& control_matcher) {
return MakeMatcher(new IsControl1Matcher(IrOpcode::kEnd, control_matcher));
Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher) {
return MakeMatcher(new IsControl1Matcher(IrOpcode::kEnd, control0_matcher));
}
Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher,
const Matcher<Node*>& control1_matcher) {
return MakeMatcher(new IsControl2Matcher(IrOpcode::kEnd, control0_matcher,
control1_matcher));
}
......
......@@ -31,7 +31,9 @@ class Node;
using ::testing::Matcher;
Matcher<Node*> IsEnd(const Matcher<Node*>& control_matcher);
Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher);
Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher,
const Matcher<Node*>& control1_matcher);
Matcher<Node*> IsBranch(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsMerge(const Matcher<Node*>& control0_matcher,
......
......@@ -631,7 +631,7 @@ TEST_F(SchedulerRPOTest, LoopMultibackedge) {
TEST_F(SchedulerTest, BuildScheduleEmpty) {
graph()->SetStart(graph()->NewNode(common()->Start(0)));
graph()->SetEnd(graph()->NewNode(common()->End(), graph()->start()));
graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
}
......@@ -643,7 +643,7 @@ TEST_F(SchedulerTest, BuildScheduleOneParameter) {
Node* ret = graph()->NewNode(common()->Return(), p1, graph()->start(),
graph()->start());
graph()->SetEnd(graph()->NewNode(common()->End(), ret));
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
}
......@@ -668,8 +668,7 @@ TEST_F(SchedulerTest, BuildScheduleIfSplit) {
graph()->NewNode(common()->Return(), p4, graph()->start(), true_branch);
Node* ret2 =
graph()->NewNode(common()->Return(), p5, graph()->start(), false_branch);
Node* merge = graph()->NewNode(common()->Merge(2), ret1, ret2);
graph()->SetEnd(graph()->NewNode(common()->End(), merge));
graph()->SetEnd(graph()->NewNode(common()->End(2), ret1, ret2));
ComputeAndVerifySchedule(13);
}
......@@ -698,7 +697,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond1) {
Node* p0 = graph()->NewNode(common()->Parameter(0), start);
Node* d1 = CreateDiamond(graph(), common(), p0);
Node* ret = graph()->NewNode(common()->Return(), d1, start, start);
Node* end = graph()->NewNode(common()->End(), ret, start);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -716,7 +715,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond2) {
Node* d2 = CreateDiamond(graph(), common(), p1);
Node* add = graph()->NewNode(&kIntAdd, d1, d2);
Node* ret = graph()->NewNode(common()->Return(), add, start, start);
Node* end = graph()->NewNode(common()->End(), ret, start);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -735,7 +734,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond3) {
Node* add = graph()->NewNode(&kIntAdd, d1, d2);
Node* d3 = CreateDiamond(graph(), common(), add);
Node* ret = graph()->NewNode(common()->Return(), d3, start, start);
Node* end = graph()->NewNode(common()->End(), ret, start);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -772,7 +771,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamonds) {
Node* ephi1 = graph()->NewNode(common()->EffectPhi(2), start, map, m);
Node* ret = graph()->NewNode(common()->Return(), phi, ephi1, start);
Node* end = graph()->NewNode(common()->End(), ret, start);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -816,7 +815,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamondWithChain) {
Node* add = graph()->NewNode(&kIntAdd, phiA2, phiB2);
Node* ret = graph()->NewNode(common()->Return(), add, start, start);
Node* end = graph()->NewNode(common()->End(), ret, start);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -850,7 +849,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamondWithLoop) {
Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), fv, ind, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
Node* end = graph()->NewNode(common()->End(), ret, start);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -883,7 +882,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond1) {
ind->ReplaceInput(1, phi1); // close induction variable.
Node* ret = graph()->NewNode(common()->Return(), ind, start, f);
Node* end = graph()->NewNode(common()->End(), ret, f);
Node* end = graph()->NewNode(common()->End(2), ret, f);
graph()->SetEnd(end);
......@@ -917,7 +916,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond2) {
ind->ReplaceInput(1, add); // close induction variable.
Node* ret = graph()->NewNode(common()->Return(), ind, start, f);
Node* end = graph()->NewNode(common()->End(), ret, f);
Node* end = graph()->NewNode(common()->End(2), ret, f);
graph()->SetEnd(end);
......@@ -963,7 +962,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond3) {
ind->ReplaceInput(1, add); // close induction variable.
Node* ret = graph()->NewNode(common()->Return(), ind, start, f);
Node* end = graph()->NewNode(common()->End(), ret, f);
Node* end = graph()->NewNode(common()->End(2), ret, f);
graph()->SetEnd(end);
......@@ -997,7 +996,7 @@ TARGET_TEST_F(SchedulerTest, PhisPushedDownToDifferentBranches) {
graph()->NewNode(common()->Phi(kMachAnyTagged, 2), phi, phi2, m2);
Node* ret = graph()->NewNode(common()->Return(), phi3, start, start);
Node* end = graph()->NewNode(common()->End(), ret, start);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -1018,7 +1017,7 @@ TARGET_TEST_F(SchedulerTest, BranchHintTrue) {
Node* m = graph()->NewNode(common()->Merge(2), t, f);
Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), tv, fv, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
Node* end = graph()->NewNode(common()->End(), ret, start);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -1042,7 +1041,7 @@ TARGET_TEST_F(SchedulerTest, BranchHintFalse) {
Node* m = graph()->NewNode(common()->Merge(2), t, f);
Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), tv, fv, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
Node* end = graph()->NewNode(common()->End(), ret, start);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -1068,7 +1067,7 @@ TARGET_TEST_F(SchedulerTest, CallException) {
Node* m = graph()->NewNode(common()->Merge(2), ok2, hdl);
Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), c2, p0, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, m);
Node* end = graph()->NewNode(common()->End(), ret);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -1087,7 +1086,7 @@ TARGET_TEST_F(SchedulerTest, TailCall) {
Node* p0 = graph()->NewNode(common()->Parameter(0), start);
Node* call = graph()->NewNode(&kMockTailCall, p0, start, start);
Node* end = graph()->NewNode(common()->End(), call);
Node* end = graph()->NewNode(common()->End(1), call);
graph()->SetEnd(end);
......@@ -1110,7 +1109,7 @@ TARGET_TEST_F(SchedulerTest, Switch) {
Node* m = graph()->NewNode(common()->Merge(3), c0, c1, d);
Node* phi = graph()->NewNode(common()->Phi(kMachInt32, 3), v0, v1, vd, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, m);
Node* end = graph()->NewNode(common()->End(), ret);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -1133,7 +1132,7 @@ TARGET_TEST_F(SchedulerTest, FloatingSwitch) {
Node* m = graph()->NewNode(common()->Merge(3), c0, c1, d);
Node* phi = graph()->NewNode(common()->Phi(kMachInt32, 3), v0, v1, vd, m);
Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
Node* end = graph()->NewNode(common()->End(), ret);
Node* end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
......@@ -1153,7 +1152,7 @@ TARGET_TEST_F(SchedulerTest, Terminate) {
Node* terminate = graph()->NewNode(common()->Terminate(), effect, loop);
effect->ReplaceInput(1, terminate);
Node* end = graph()->NewNode(common()->End(), terminate);
Node* end = graph()->NewNode(common()->End(1), terminate);
graph()->SetEnd(end);
......
......@@ -61,7 +61,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject1) {
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
Node* if_exception = graph()->NewNode(common()->IfException(), call);
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
Node* end = graph()->NewNode(common()->End(), if_exception);
Node* end = graph()->NewNode(common()->End(1), if_exception);
graph()->SetEnd(end);
Reduction r = Reduce(ret);
ASSERT_FALSE(r.Changed());
......@@ -126,7 +126,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction1) {
Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
Node* if_exception = graph()->NewNode(common()->IfException(), call);
Node* ret = graph()->NewNode(common()->Return(), call, call, if_success);
Node* end = graph()->NewNode(common()->End(), if_exception);
Node* end = graph()->NewNode(common()->End(1), if_exception);
graph()->SetEnd(end);
Reduction r = Reduce(ret);
ASSERT_FALSE(r.Changed());
......
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