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()),
}
// 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.
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);
}
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_;
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);
#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) \
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) \
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()
#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:
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();
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;
}
case IrOpcode::kEffectPhi:
result = ReducePhi(node);
break;
+ case IrOpcode::kEnd:
+ result = ReduceEnd(node);
+ break;
default:
break;
}
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.
}
}
- // 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);
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()));
}
}
// 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);
void SimplifiedGraphBuilder::End() {
- Node* end = graph()->NewNode(common()->End(), return_);
+ Node* end = graph()->NewNode(common()->End(1), return_);
graph()->SetEnd(end);
}
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);
}
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);
}
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);
}
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()),
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);
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);
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));
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);
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());
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();
}
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);
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();
}
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()),
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))) {
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();
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();
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();
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);
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);
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);
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);
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),
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,
} // 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);
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());
}
Node* End(Node* control) {
- return Store(graph()->NewNode(common()->End(), control));
+ return Store(graph()->NewNode(common()->End(1), control));
}
private:
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(),
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(
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(
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)))));
}
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)))));
}
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)))));
}
EXPECT_THAT(graph()->end(), IsEnd(ret));
}
-
} // namespace compiler
} // namespace internal
} // namespace v8
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()));
}
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
} // 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));
}
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,
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));
}
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));
}
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);
}
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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());
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());