Add Terminate operator.
authortitzer@chromium.org <titzer@chromium.org>
Wed, 22 Oct 2014 17:15:38 +0000 (17:15 +0000)
committertitzer@chromium.org <titzer@chromium.org>
Wed, 22 Oct 2014 17:15:38 +0000 (17:15 +0000)
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

src/compiler/common-operator.cc
src/compiler/common-operator.h
src/compiler/instruction-selector.cc
src/compiler/opcodes.h
src/compiler/operator-properties-inl.h
src/compiler/verifier.cc
test/cctest/compiler/test-scheduler.cc

index e7d712a..c9dea87 100644 (file)
@@ -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) {
   return new (zone()) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1,
                                      1, "Parameter", index);
index c65e1a7..c59ca49 100644 (file)
@@ -137,6 +137,7 @@ class CommonOperatorBuilder FINAL {
   const Operator* IfTrue();
   const Operator* IfFalse();
   const Operator* Throw();
+  const Operator* Terminate(int effects);
   const Operator* Return();
 
   const Operator* Start(int num_formal_parameters);
index e1b859f..17c227a 100644 (file)
@@ -457,6 +457,7 @@ MachineType InstructionSelector::GetMachineType(Node* node) {
     case IrOpcode::kIfFalse:
     case IrOpcode::kEffectPhi:
     case IrOpcode::kMerge:
+    case IrOpcode::kTerminate:
       // No code needed for these graph artifacts.
       return kMachNone;
     case IrOpcode::kFinish:
index 8b68e60..cbc0d07 100644 (file)
@@ -7,13 +7,14 @@
 
 // Opcodes for control operators.
 #define INNER_CONTROL_OP_LIST(V) \
-  V(Dead)                  \
-  V(Loop)                  \
-  V(Branch)                \
-  V(IfTrue)                \
-  V(IfFalse)               \
-  V(Merge)                 \
-  V(Return)                \
+  V(Dead)                        \
+  V(Loop)                        \
+  V(Branch)                      \
+  V(IfTrue)                      \
+  V(IfFalse)                     \
+  V(Merge)                       \
+  V(Return)                      \
+  V(Terminate)                   \
   V(Throw)
 
 #define CONTROL_OP_LIST(V) \
index 70810c6..4d85171 100644 (file)
@@ -104,7 +104,8 @@ inline int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
 
 inline int OperatorProperties::GetEffectInputCount(const Operator* op) {
   if (op->opcode() == IrOpcode::kEffectPhi ||
-      op->opcode() == IrOpcode::kFinish) {
+      op->opcode() == IrOpcode::kFinish ||
+      op->opcode() == IrOpcode::kTerminate) {
     return OpParameter<int>(op);
   }
   if (op->HasProperty(Operator::kNoRead) && op->HasProperty(Operator::kNoWrite))
@@ -154,7 +155,8 @@ inline bool OperatorProperties::HasValueOutput(const Operator* op) {
 inline bool OperatorProperties::HasEffectOutput(const Operator* op) {
   return op->opcode() == IrOpcode::kStart ||
          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) {
index ab70ade..d0b40e7 100644 (file)
@@ -243,6 +243,12 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
       // Type is empty.
       CheckNotTyped(node);
       break;
+    case IrOpcode::kTerminate:
+      // Type is empty.
+      CheckNotTyped(node);
+      CHECK_EQ(1, control_count);
+      CHECK_EQ(input_count, 1 + effect_count);
+      break;
 
     // Common operators
     // ----------------
index c5412e0..894f0f0 100644 (file)
@@ -1888,4 +1888,31 @@ TEST(BranchHintFalse) {
   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