[turbofan] Introduce DeadValue and DeadEffect operators.
authormstarzinger <mstarzinger@chromium.org>
Thu, 18 Jun 2015 08:17:09 +0000 (01:17 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 18 Jun 2015 08:17:17 +0000 (08:17 +0000)
R=bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#29104}

22 files changed:
src/compiler/ast-graph-builder.cc
src/compiler/ast-graph-builder.h
src/compiler/common-operator.cc
src/compiler/common-operator.h
src/compiler/control-reducer.cc
src/compiler/graph-visualizer.cc
src/compiler/js-graph.cc
src/compiler/js-graph.h
src/compiler/js-inlining.cc
src/compiler/loop-peeling.cc
src/compiler/opcodes.h
src/compiler/operator-properties.cc
src/compiler/pipeline.cc
src/compiler/simplified-lowering.cc
src/compiler/typer.cc
src/compiler/verifier.cc
test/cctest/compiler/test-control-reducer.cc
test/cctest/compiler/test-loop-analysis.cc
test/unittests/compiler/common-operator-unittest.cc
test/unittests/compiler/graph-reducer-unittest.cc
test/unittests/compiler/graph-trimmer-unittest.cc
test/unittests/compiler/node-properties-unittest.cc

index b1ad32f..159536c 100644 (file)
@@ -403,7 +403,7 @@ class AstGraphBuilder::FrameStateBeforeAndAfter {
 
     if (count >= 1) {
       // Add the frame state for after the operation.
-      DCHECK_EQ(IrOpcode::kDead,
+      DCHECK_EQ(IrOpcode::kDeadValue,
                 NodeProperties::GetFrameStateInput(node, 0)->opcode());
 
       Node* frame_state_after =
@@ -416,7 +416,7 @@ class AstGraphBuilder::FrameStateBeforeAndAfter {
 
     if (count >= 2) {
       // Add the frame state for before the operation.
-      DCHECK_EQ(IrOpcode::kDead,
+      DCHECK_EQ(IrOpcode::kDeadValue,
                 NodeProperties::GetFrameStateInput(node, 1)->opcode());
       NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
     }
@@ -3759,8 +3759,7 @@ void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
                                         OutputFrameStateCombine combine) {
   if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
-
-    DCHECK_EQ(IrOpcode::kDead,
+    DCHECK_EQ(IrOpcode::kDeadValue,
               NodeProperties::GetFrameStateInput(node, 0)->opcode());
     NodeProperties::ReplaceFrameStateInput(
         node, 0, environment()->Checkpoint(ast_id, combine));
@@ -3815,9 +3814,9 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
     }
     for (int i = 0; i < frame_state_count; i++) {
       // The frame state will be inserted later. Here we misuse
-      // the {DeadControl} node as a sentinel to be later overwritten
+      // the {DeadValue} node as a sentinel to be later overwritten
       // with the real frame state.
-      *current_input++ = jsgraph()->DeadControl();
+      *current_input++ = jsgraph()->DeadValue();
     }
     if (has_effect) {
       *current_input++ = environment_->GetEffectDependency();
index f80c1f6..69b3560 100644 (file)
@@ -489,7 +489,7 @@ class AstGraphBuilder::Environment : public ZoneObject {
     liveness_block_ = nullptr;
   }
   bool IsMarkedAsUnreachable() {
-    return GetControlDependency()->opcode() == IrOpcode::kDead;
+    return GetControlDependency()->opcode() == IrOpcode::kDeadControl;
   }
 
   // Merge another environment into this one.
index a8cfbb3..c58fc7c 100644 (file)
@@ -116,7 +116,9 @@ 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(DeadValue, Operator::kPure, 0, 0, 0, 1, 0, 0)          \
+  V(DeadEffect, Operator::kPure, 0, 0, 0, 0, 1, 0)         \
+  V(DeadControl, Operator::kFoldable, 0, 0, 0, 0, 0, 1)    \
   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)       \
index 08553bc..af20b10 100644 (file)
@@ -96,7 +96,6 @@ class CommonOperatorBuilder final : public ZoneObject {
  public:
   explicit CommonOperatorBuilder(Zone* zone);
 
-  const Operator* Dead();
   const Operator* End(size_t control_input_count);
   const Operator* Branch(BranchHint = BranchHint::kNone);
   const Operator* IfTrue();
@@ -111,6 +110,10 @@ class CommonOperatorBuilder final : public ZoneObject {
   const Operator* Return();
   const Operator* Terminate();
 
+  const Operator* DeadValue();
+  const Operator* DeadEffect();
+  const Operator* DeadControl();
+
   const Operator* Start(int num_formal_parameters);
   const Operator* Loop(int control_input_count);
   const Operator* Merge(int control_input_count);
index 6e085ad..a81a6ee 100644 (file)
@@ -47,7 +47,7 @@ class ControlReducerImpl final : public AdvancedReducer {
         node->opcode() == IrOpcode::kLoop) {
       // If a node has only one control input and it is dead, replace with dead.
       Node* control = NodeProperties::GetControlInput(node);
-      if (control->opcode() == IrOpcode::kDead) {
+      if (control->opcode() == IrOpcode::kDeadControl) {
         TRACE("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic());
         return Replace(control);
       }
@@ -125,8 +125,10 @@ class ControlReducerImpl final : public AdvancedReducer {
     auto const inputs = node->inputs();
     for (auto it = inputs.begin(); n > 1; --n, ++it) {
       Node* input = *it;
-      if (input->opcode() == IrOpcode::kDead) continue;  // ignore dead inputs.
-      if (input != node && input != replacement) {       // non-redundant input.
+      // Ignore dead inputs.
+      if (input->opcode() == IrOpcode::kDeadControl) continue;
+      // Non-redundant input.
+      if (input != node && input != replacement) {
         if (replacement != NULL) return node;
         replacement = input;
       }
@@ -148,7 +150,7 @@ class ControlReducerImpl final : public AdvancedReducer {
     int live = 0;
     for (int index = 0; index < node->InputCount(); ++index) {
       // Skip dead inputs.
-      if (node->InputAt(index)->opcode() == IrOpcode::kDead) continue;
+      if (node->InputAt(index)->opcode() == IrOpcode::kDeadControl) continue;
       // Compact live inputs.
       if (index != live) node->ReplaceInput(live, node->InputAt(index));
       ++live;
@@ -174,7 +176,7 @@ class ControlReducerImpl final : public AdvancedReducer {
     int index = 0;
     int live_index = 0;
     for (Node* const input : node->inputs()) {
-      if (input->opcode() != IrOpcode::kDead) {
+      if (input->opcode() != IrOpcode::kDeadControl) {
         live++;
         live_index = index;
       }
@@ -288,7 +290,7 @@ class ControlReducerImpl final : public AdvancedReducer {
     int live = 0;
     for (int i = 0; i < merge->InputCount(); i++) {
       // skip dead inputs.
-      if (merge->InputAt(i)->opcode() == IrOpcode::kDead) continue;
+      if (merge->InputAt(i)->opcode() == IrOpcode::kDeadControl) continue;
       // compact live inputs.
       if (live != i) node->ReplaceInput(live, node->InputAt(i));
       live++;
index 313edb9..123b361 100644 (file)
@@ -256,7 +256,7 @@ void GraphVisualizer::PrintNode(Node* node, bool gray) {
   os_ << "    shape=\"record\"\n";
   switch (node->opcode()) {
     case IrOpcode::kEnd:
-    case IrOpcode::kDead:
+    case IrOpcode::kDeadControl:
     case IrOpcode::kStart:
       os_ << "    style=\"diagonals\"\n";
       break;
index 35984b8..10e20a1 100644 (file)
@@ -203,8 +203,13 @@ Node* JSGraph::EmptyFrameState() {
 }
 
 
+Node* JSGraph::DeadValue() {
+  return CACHED(kDeadValue, graph()->NewNode(common()->DeadValue()));
+}
+
+
 Node* JSGraph::DeadControl() {
-  return CACHED(kDeadControl, graph()->NewNode(common()->Dead()));
+  return CACHED(kDeadControl, graph()->NewNode(common()->DeadControl()));
 }
 
 
index dda1277..b6b1322 100644 (file)
@@ -117,7 +117,10 @@ class JSGraph : public ZoneObject {
   // cannot deopt.
   Node* EmptyFrameState();
 
-  // Create a control node that serves as control dependency for dead nodes.
+  // Creates a value node that servers as value input for dead nodes.
+  Node* DeadValue();
+
+  // Creates a control node that serves as control dependency for dead nodes.
   Node* DeadControl();
 
   JSOperatorBuilder* javascript() const { return javascript_; }
@@ -142,6 +145,7 @@ class JSGraph : public ZoneObject {
     kOneConstant,
     kNaNConstant,
     kEmptyFrameState,
+    kDeadValue,
     kDeadControl,
     kNumCachedNodes  // Must remain last.
   };
index 3569330..e85e608 100644 (file)
@@ -62,8 +62,8 @@ class JSCallFunctionAccessor {
 class CopyVisitor {
  public:
   CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone)
-      : sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "Sentinel", 0, 0,
-                     0, 0, 0, 0),
+      : sentinel_op_(IrOpcode::kDeadControl, Operator::kNoProperties,
+                     "Sentinel", 0, 0, 0, 0, 0, 0),
         sentinel_(target_graph->NewNode(&sentinel_op_)),
         copies_(source_graph->NodeCount(), sentinel_, temp_zone),
         source_graph_(source_graph),
index 8c980aa..4c5f0d4 100644 (file)
@@ -212,7 +212,7 @@ PeeledIteration* LoopPeeler::Peel(Graph* graph, CommonOperatorBuilder* common,
       5 + (loop->TotalSize() + exits.size() + rets.size()) * 2;
   Peeling peeling(graph, tmp_zone, estimated_peeled_size, &iter->node_pairs_);
 
-  Node* dead = graph->NewNode(common->Dead());
+  Node* dead = graph->NewNode(common->DeadControl());
 
   // Map the loop header nodes to their entry values.
   for (Node* node : loop_tree->HeaderNodes(loop)) {
index fc67e74..1c2a23c 100644 (file)
@@ -10,7 +10,6 @@
 // Opcodes for control operators.
 #define CONTROL_OP_LIST(V) \
   V(Start)                 \
-  V(Dead)                  \
   V(Loop)                  \
   V(Branch)                \
   V(Switch)                \
@@ -27,6 +26,7 @@
   V(Terminate)             \
   V(OsrNormalEntry)        \
   V(OsrLoopEntry)          \
+  V(DeadControl)           \
   V(Throw)                 \
   V(End)
 
 
 #define COMMON_OP_LIST(V) \
   CONSTANT_OP_LIST(V)     \
-  INNER_OP_LIST(V)
+  INNER_OP_LIST(V)        \
+  V(DeadEffect)           \
+  V(DeadValue)
+
 
 // Opcodes for JavaScript operators.
 #define JS_COMPARE_BINOP_LIST(V) \
@@ -318,7 +321,7 @@ class IrOpcode {
 
   // Returns true if opcode for common operator.
   static bool IsCommonOpcode(Value value) {
-    return kStart <= value && value <= kProjection;
+    return kStart <= value && value <= kDeadValue;
   }
 
   // Returns true if opcode for control operator.
index 4a7f1d9..dce4f42 100644 (file)
@@ -117,7 +117,7 @@ int OperatorProperties::GetTotalInputCount(const Operator* op) {
 bool OperatorProperties::IsBasicBlockBegin(const Operator* op) {
   Operator::Opcode const opcode = op->opcode();
   return opcode == IrOpcode::kStart || opcode == IrOpcode::kEnd ||
-         opcode == IrOpcode::kDead || opcode == IrOpcode::kLoop ||
+         opcode == IrOpcode::kDeadControl || opcode == IrOpcode::kLoop ||
          opcode == IrOpcode::kMerge || opcode == IrOpcode::kIfTrue ||
          opcode == IrOpcode::kIfFalse || opcode == IrOpcode::kIfSuccess ||
          opcode == IrOpcode::kIfException || opcode == IrOpcode::kIfValue ||
index bb8198e..125bbdd 100644 (file)
@@ -407,7 +407,7 @@ class SourcePositionWrapper final : public Reducer {
 class JSGraphReducer final : public GraphReducer {
  public:
   JSGraphReducer(JSGraph* jsgraph, Zone* zone)
-      : GraphReducer(zone, jsgraph->graph(), jsgraph->TheHoleConstant(),
+      : GraphReducer(zone, jsgraph->graph(), jsgraph->DeadValue(),
                      jsgraph->DeadControl()) {}
   ~JSGraphReducer() final {}
 };
index 825de35..8ef86aa 100644 (file)
@@ -497,7 +497,7 @@ class RepresentationSelector {
       // Common operators.
       //------------------------------------------------------------------
       case IrOpcode::kStart:
-      case IrOpcode::kDead:
+      case IrOpcode::kDeadControl:
         return VisitLeaf(node, 0);
       case IrOpcode::kParameter: {
         // TODO(titzer): use representation from linkage.
index f92de92..f960153 100644 (file)
@@ -253,7 +253,6 @@ class Typer::Visitor : public Reducer {
 #undef DECLARE_CASE
 
 #define DECLARE_CASE(x) case IrOpcode::k##x:
-      DECLARE_CASE(Dead)
       DECLARE_CASE(Loop)
       DECLARE_CASE(Branch)
       DECLARE_CASE(IfTrue)
@@ -269,6 +268,7 @@ class Typer::Visitor : public Reducer {
       DECLARE_CASE(Terminate)
       DECLARE_CASE(OsrNormalEntry)
       DECLARE_CASE(OsrLoopEntry)
+      DECLARE_CASE(DeadControl)
       DECLARE_CASE(Throw)
       DECLARE_CASE(End)
 #undef DECLARE_CASE
@@ -298,7 +298,6 @@ class Typer::Visitor : public Reducer {
 #undef DECLARE_CASE
 
 #define DECLARE_CASE(x) case IrOpcode::k##x:
-      DECLARE_CASE(Dead)
       DECLARE_CASE(Loop)
       DECLARE_CASE(Branch)
       DECLARE_CASE(IfTrue)
@@ -314,6 +313,7 @@ class Typer::Visitor : public Reducer {
       DECLARE_CASE(Terminate)
       DECLARE_CASE(OsrNormalEntry)
       DECLARE_CASE(OsrLoopEntry)
+      DECLARE_CASE(DeadControl)
       DECLARE_CASE(Throw)
       DECLARE_CASE(End)
 #undef DECLARE_CASE
@@ -742,6 +742,17 @@ Bounds Typer::Visitor::TypeFinish(Node* node) {
 }
 
 
+Bounds Typer::Visitor::TypeDeadValue(Node* node) {
+  return Bounds(Type::None(zone()), Type::Any(zone()));
+}
+
+
+Bounds Typer::Visitor::TypeDeadEffect(Node* node) {
+  UNREACHABLE();
+  return Bounds();
+}
+
+
 Bounds Typer::Visitor::TypeFrameState(Node* node) {
   // TODO(rossberg): Ideally FrameState wouldn't have a value output.
   return Bounds(Type::None(zone()), Type::Internal(zone()));
index e678f4e..bf039e3 100644 (file)
@@ -192,7 +192,9 @@ void Verifier::Visitor::Check(Node* node) {
       // Type is empty.
       CheckNotTyped(node);
       break;
-    case IrOpcode::kDead:
+    case IrOpcode::kDeadValue:
+    case IrOpcode::kDeadEffect:
+    case IrOpcode::kDeadControl:
       // Dead is never connected to the graph.
       // TODO(mstarzinger): Make the GraphReducer immediately perform control
       // reduction in case control is killed. This will prevent {Dead} from
index e34dc9a..2f0cb17 100644 (file)
@@ -75,7 +75,7 @@ class ControlReducerTester : HandleAndZoneScope {
         one(jsgraph.OneConstant()),
         half(jsgraph.Constant(0.5)),
         self(graph.NewNode(common.Int32Constant(0xaabbccdd))),
-        dead(graph.NewNode(common.Dead())) {
+        dead(graph.NewNode(common.DeadControl())) {
     graph.SetEnd(end);
     graph.SetStart(start);
     leaf[0] = zero;
@@ -185,12 +185,16 @@ class ControlReducerTester : HandleAndZoneScope {
       if (use->opcode() == IrOpcode::kIfTrue) {
         Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use);
         if (expected == kTrue) CHECK_EQ(control, result);
-        if (expected == kFalse) CHECK_EQ(IrOpcode::kDead, result->opcode());
+        if (expected == kFalse) {
+          CHECK_EQ(IrOpcode::kDeadControl, result->opcode());
+        }
         if (expected == kUnknown) CHECK_EQ(use, result);
       } else if (use->opcode() == IrOpcode::kIfFalse) {
         Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use);
         if (expected == kFalse) CHECK_EQ(control, result);
-        if (expected == kTrue) CHECK_EQ(IrOpcode::kDead, result->opcode());
+        if (expected == kTrue) {
+          CHECK_EQ(IrOpcode::kDeadControl, result->opcode());
+        }
         if (expected == kUnknown) CHECK_EQ(use, result);
       } else {
         UNREACHABLE();
@@ -793,7 +797,7 @@ TEST(CMergeReduce_exhaustive_4) {
     int count = selector.count;
     if (count == 0) {
       // result should be dead.
-      CHECK_EQ(IrOpcode::kDead, result->opcode());
+      CHECK_EQ(IrOpcode::kDeadControl, result->opcode());
     } else if (count == 1) {
       // merge should be replaced with one of the controls.
       CHECK_EQ(controls[selector.single_index()], result);
index 6560ae3..a62a3ab 100644 (file)
@@ -47,7 +47,7 @@ class LoopFinderTester : HandleAndZoneScope {
         one(jsgraph.OneConstant()),
         half(jsgraph.Constant(0.5)),
         self(graph.NewNode(common.Int32Constant(0xaabbccdd))),
-        dead(graph.NewNode(common.Dead())),
+        dead(graph.NewNode(common.DeadControl())),
         loop_tree(NULL) {
     graph.SetEnd(end);
     graph.SetStart(start);
index 26e861c..973182c 100644 (file)
@@ -48,13 +48,15 @@ const SharedOperator kSharedOperators[] = {
         value_input_count, effect_input_count, control_input_count,          \
         value_output_count, effect_output_count, control_output_count        \
   }
-    SHARED(Dead, Operator::kFoldable, 0, 0, 0, 0, 0, 1),
     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),
     SHARED(Throw, Operator::kKontrol, 1, 1, 1, 0, 0, 1),
     SHARED(Return, Operator::kNoThrow, 1, 1, 1, 0, 0, 1),
-    SHARED(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1)
+    SHARED(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1),
+    SHARED(DeadValue, Operator::kPure, 0, 0, 0, 1, 0, 0),
+    SHARED(DeadEffect, Operator::kPure, 0, 0, 0, 0, 1, 0),
+    SHARED(DeadControl, Operator::kFoldable, 0, 0, 0, 0, 0, 1)
 #undef SHARED
 };
 
index 2d54e21..a8e003d 100644 (file)
@@ -275,11 +275,11 @@ struct ReplaceWithValueReducer final : public AdvancedReducer {
   using AdvancedReducer::ReplaceWithValue;
 };
 
-const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties,
+const Operator kMockOperator(IrOpcode::kDeadControl, Operator::kNoProperties,
                              "MockOperator", 0, 0, 0, 1, 0, 0);
-const Operator kMockOpEffect(IrOpcode::kDead, Operator::kNoProperties,
+const Operator kMockOpEffect(IrOpcode::kDeadControl, Operator::kNoProperties,
                              "MockOpEffect", 0, 1, 0, 1, 1, 0);
-const Operator kMockOpControl(IrOpcode::kDead, Operator::kNoProperties,
+const Operator kMockOpControl(IrOpcode::kDeadControl, Operator::kNoProperties,
                               "MockOpControl", 0, 0, 1, 1, 0, 1);
 
 const IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught;
index 36892e6..03a38d5 100644 (file)
@@ -32,10 +32,10 @@ class GraphTrimmerTest : public GraphTest {
 
 namespace {
 
-const Operator kDead0(IrOpcode::kDead, Operator::kNoProperties, "Dead0", 0, 0,
-                      1, 0, 0, 0);
-const Operator kLive0(IrOpcode::kDead, Operator::kNoProperties, "Live0", 0, 0,
-                      1, 0, 0, 1);
+const Operator kDead0(IrOpcode::kDeadControl, Operator::kNoProperties, "Dead0",
+                      0, 0, 1, 0, 0, 0);
+const Operator kLive0(IrOpcode::kDeadControl, Operator::kNoProperties, "Live0",
+                      0, 0, 1, 0, 0, 1);
 
 }  // namespace
 
index 463948d..f73d464 100644 (file)
@@ -32,7 +32,7 @@ class NodePropertiesTest : public TestWithZone {
 
 namespace {
 
-const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties,
+const Operator kMockOperator(IrOpcode::kDeadControl, Operator::kNoProperties,
                              "MockOperator", 0, 0, 0, 1, 1, 2);
 const Operator kMockCallOperator(IrOpcode::kCall, Operator::kNoProperties,
                                  "MockCallOperator", 0, 0, 0, 0, 0, 2);