Commit 5a177426 authored by titzer@chromium.org's avatar titzer@chromium.org

Add Terminate operator.

Terminate is need for non-terminating loops (NTLs) that can appear after optimizing control flow. It gathers the control and effect(s) from a NTL and connects them to end so that they are not dead-code removed.

R=mstarzinger@chromium.org
BUG=

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24812 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7a70d6a0
...@@ -155,6 +155,13 @@ const Operator* CommonOperatorBuilder::Loop(int controls) { ...@@ -155,6 +155,13 @@ const Operator* CommonOperatorBuilder::Loop(int controls) {
} }
const Operator* CommonOperatorBuilder::Terminate(int effects) {
return new (zone()) Operator1<int>(IrOpcode::kTerminate,
Operator::kNoRead | Operator::kNoWrite, 0,
0, "Terminate", effects);
}
const Operator* CommonOperatorBuilder::Parameter(int index) { const Operator* CommonOperatorBuilder::Parameter(int index) {
return new (zone()) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1, return new (zone()) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1,
1, "Parameter", index); 1, "Parameter", index);
......
...@@ -137,6 +137,7 @@ class CommonOperatorBuilder FINAL { ...@@ -137,6 +137,7 @@ class CommonOperatorBuilder FINAL {
const Operator* IfTrue(); const Operator* IfTrue();
const Operator* IfFalse(); const Operator* IfFalse();
const Operator* Throw(); const Operator* Throw();
const Operator* Terminate(int effects);
const Operator* Return(); const Operator* Return();
const Operator* Start(int num_formal_parameters); const Operator* Start(int num_formal_parameters);
......
...@@ -457,6 +457,7 @@ MachineType InstructionSelector::GetMachineType(Node* node) { ...@@ -457,6 +457,7 @@ MachineType InstructionSelector::GetMachineType(Node* node) {
case IrOpcode::kIfFalse: case IrOpcode::kIfFalse:
case IrOpcode::kEffectPhi: case IrOpcode::kEffectPhi:
case IrOpcode::kMerge: case IrOpcode::kMerge:
case IrOpcode::kTerminate:
// No code needed for these graph artifacts. // No code needed for these graph artifacts.
return kMachNone; return kMachNone;
case IrOpcode::kFinish: case IrOpcode::kFinish:
......
...@@ -7,13 +7,14 @@ ...@@ -7,13 +7,14 @@
// Opcodes for control operators. // Opcodes for control operators.
#define INNER_CONTROL_OP_LIST(V) \ #define INNER_CONTROL_OP_LIST(V) \
V(Dead) \ V(Dead) \
V(Loop) \ V(Loop) \
V(Branch) \ V(Branch) \
V(IfTrue) \ V(IfTrue) \
V(IfFalse) \ V(IfFalse) \
V(Merge) \ V(Merge) \
V(Return) \ V(Return) \
V(Terminate) \
V(Throw) V(Throw)
#define CONTROL_OP_LIST(V) \ #define CONTROL_OP_LIST(V) \
......
...@@ -104,7 +104,8 @@ inline int OperatorProperties::GetFrameStateInputCount(const Operator* op) { ...@@ -104,7 +104,8 @@ inline int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
inline int OperatorProperties::GetEffectInputCount(const Operator* op) { inline int OperatorProperties::GetEffectInputCount(const Operator* op) {
if (op->opcode() == IrOpcode::kEffectPhi || if (op->opcode() == IrOpcode::kEffectPhi ||
op->opcode() == IrOpcode::kFinish) { op->opcode() == IrOpcode::kFinish ||
op->opcode() == IrOpcode::kTerminate) {
return OpParameter<int>(op); return OpParameter<int>(op);
} }
if (op->HasProperty(Operator::kNoRead) && op->HasProperty(Operator::kNoWrite)) if (op->HasProperty(Operator::kNoRead) && op->HasProperty(Operator::kNoWrite))
...@@ -154,7 +155,8 @@ inline bool OperatorProperties::HasValueOutput(const Operator* op) { ...@@ -154,7 +155,8 @@ inline bool OperatorProperties::HasValueOutput(const Operator* op) {
inline bool OperatorProperties::HasEffectOutput(const Operator* op) { inline bool OperatorProperties::HasEffectOutput(const Operator* op) {
return op->opcode() == IrOpcode::kStart || return op->opcode() == IrOpcode::kStart ||
op->opcode() == IrOpcode::kValueEffect || op->opcode() == IrOpcode::kValueEffect ||
(op->opcode() != IrOpcode::kFinish && GetEffectInputCount(op) > 0); (op->opcode() != IrOpcode::kFinish &&
op->opcode() != IrOpcode::kTerminate && GetEffectInputCount(op) > 0);
} }
inline bool OperatorProperties::HasControlOutput(const Operator* op) { inline bool OperatorProperties::HasControlOutput(const Operator* op) {
......
...@@ -243,6 +243,12 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) { ...@@ -243,6 +243,12 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
// Type is empty. // Type is empty.
CheckNotTyped(node); CheckNotTyped(node);
break; break;
case IrOpcode::kTerminate:
// Type is empty.
CheckNotTyped(node);
CHECK_EQ(1, control_count);
CHECK_EQ(input_count, 1 + effect_count);
break;
// Common operators // Common operators
// ---------------- // ----------------
......
...@@ -1888,4 +1888,31 @@ TEST(BranchHintFalse) { ...@@ -1888,4 +1888,31 @@ TEST(BranchHintFalse) {
CHECK(!schedule->block(f)->deferred()); CHECK(!schedule->block(f)->deferred());
} }
TEST(ScheduleTerminate) {
HandleAndZoneScope scope;
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
Node* start = graph.NewNode(common.Start(1));
graph.SetStart(start);
Node* loop = graph.NewNode(common.Loop(2), start, start);
loop->ReplaceInput(1, loop); // self loop, NTL.
Node* effect = graph.NewNode(common.EffectPhi(1), start, loop);
effect->ReplaceInput(0, effect);
Node* terminate = graph.NewNode(common.Terminate(1), effect, loop);
Node* end = graph.NewNode(common.End(), terminate);
graph.SetEnd(end);
Schedule* schedule = ComputeAndVerifySchedule(5, &graph);
BasicBlock* block = schedule->block(loop);
CHECK_NE(NULL, loop);
CHECK_EQ(block, schedule->block(effect));
CHECK_GE(block->rpo_number(), 0);
}
#endif #endif
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