Run ControlReducer early after graph building, then again later.
authortitzer@chromium.org <titzer@chromium.org>
Wed, 29 Oct 2014 15:27:27 +0000 (15:27 +0000)
committertitzer@chromium.org <titzer@chromium.org>
Wed, 29 Oct 2014 15:27:58 +0000 (15:27 +0000)
The justification for doing this is to reduce the size of the graph and
therefore speedup later phases of compilation. The control reducer also
obviates the need to run the PhiReducer, since it subsumes it.

R=mstarzinger@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#24986}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24986 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/compiler/ast-graph-builder.cc
src/compiler/js-graph.h
src/compiler/pipeline.cc
src/compiler/scheduler.cc
test/cctest/compiler/test-scheduler.cc

index 4887260..92eec86 100644 (file)
@@ -8,6 +8,7 @@
 #include "src/compiler/ast-loop-assignment-analyzer.h"
 #include "src/compiler/control-builders.h"
 #include "src/compiler/machine-operator.h"
+#include "src/compiler/node-matchers.h"
 #include "src/compiler/node-properties-inl.h"
 #include "src/compiler/node-properties.h"
 #include "src/full-codegen.h"
@@ -2059,9 +2060,31 @@ Node* AstGraphBuilder::BuildLoadGlobalObject() {
 }
 
 
-Node* AstGraphBuilder::BuildToBoolean(Node* value) {
-  // TODO(mstarzinger): Possible optimization is to NOP for boolean values.
-  return NewNode(javascript()->ToBoolean(), value);
+Node* AstGraphBuilder::BuildToBoolean(Node* input) {
+  // TODO(titzer): this should be in a JSOperatorReducer.
+  switch (input->opcode()) {
+    case IrOpcode::kInt32Constant:
+      return jsgraph_->BooleanConstant(!Int32Matcher(input).Is(0));
+    case IrOpcode::kFloat64Constant:
+      return jsgraph_->BooleanConstant(!Float64Matcher(input).Is(0));
+    case IrOpcode::kNumberConstant:
+      return jsgraph_->BooleanConstant(!NumberMatcher(input).Is(0));
+    case IrOpcode::kHeapConstant: {
+      Handle<Object> object = HeapObjectMatcher<Object>(input).Value().handle();
+      if (object->IsTrue()) return jsgraph_->TrueConstant();
+      if (object->IsFalse()) return jsgraph_->FalseConstant();
+      // TODO(turbofan): other constants.
+      break;
+    }
+    default:
+      break;
+  }
+  if (NodeProperties::IsTyped(input)) {
+    Type* upper = NodeProperties::GetBounds(input).upper;
+    if (upper->Is(Type::Boolean())) return input;
+  }
+
+  return NewNode(javascript()->ToBoolean(), input);
 }
 
 
index 4f74d6f..83e103d 100644 (file)
@@ -67,6 +67,11 @@ class JSGraph : public ZoneObject {
     return Int32Constant(bit_cast<int32_t>(value));
   }
 
+  // Creates a HeapConstant node for either true or false.
+  Node* BooleanConstant(bool is_true) {
+    return is_true ? TrueConstant() : FalseConstant();
+  }
+
   // Creates a Int64Constant node, usually canonicalized.
   Node* Int64Constant(int64_t value);
   Node* Uint64Constant(uint64_t value) {
index a7d5ed1..fc0a432 100644 (file)
@@ -22,7 +22,6 @@
 #include "src/compiler/js-inlining.h"
 #include "src/compiler/js-typed-lowering.h"
 #include "src/compiler/machine-operator-reducer.h"
-#include "src/compiler/phi-reducer.h"
 #include "src/compiler/pipeline-statistics.h"
 #include "src/compiler/register-allocator.h"
 #include "src/compiler/schedule.h"
@@ -323,19 +322,21 @@ Handle<Code> Pipeline::GenerateCode() {
     graph_builder.CreateGraph();
     context_node = graph_builder.GetFunctionContext();
   }
-  {
-    PhaseScope phase_scope(pipeline_statistics.get(), "phi reduction");
-    PhiReducer phi_reducer;
-    GraphReducer graph_reducer(data.graph());
-    graph_reducer.AddReducer(&phi_reducer);
-    graph_reducer.ReduceGraph();
-    // TODO(mstarzinger): Running reducer once ought to be enough for everyone.
-    graph_reducer.ReduceGraph();
-    graph_reducer.ReduceGraph();
-  }
 
   VerifyAndPrintGraph(data.graph(), "Initial untyped", true);
 
+  {
+    PhaseScope phase_scope(pipeline_statistics.get(),
+                           "early control reduction");
+    SourcePositionTable::Scope pos(data.source_positions(),
+                                   SourcePosition::Unknown());
+    ZonePool::Scope zone_scope(data.zone_pool());
+    ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(),
+                                data.common());
+
+    VerifyAndPrintGraph(data.graph(), "Early Control reduced", true);
+  }
+
   if (info()->is_context_specializing()) {
     SourcePositionTable::Scope pos(data.source_positions(),
                                    SourcePosition::Unknown());
@@ -432,14 +433,15 @@ Handle<Code> Pipeline::GenerateCode() {
     }
 
     {
-      PhaseScope phase_scope(pipeline_statistics.get(), "control reduction");
+      PhaseScope phase_scope(pipeline_statistics.get(),
+                             "late control reduction");
       SourcePositionTable::Scope pos(data.source_positions(),
                                      SourcePosition::Unknown());
       ZonePool::Scope zone_scope(data.zone_pool());
       ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(),
                                   data.common());
 
-      VerifyAndPrintGraph(data.graph(), "Control reduced");
+      VerifyAndPrintGraph(data.graph(), "Late Control reduced");
     }
   }
 
index d9e67ee..f2e1425 100644 (file)
@@ -241,9 +241,7 @@ class CFGBuilder {
   // backwards from end through control edges, building and connecting the
   // basic blocks for control nodes.
   void Run() {
-    Graph* graph = scheduler_->graph_;
-    FixNode(schedule_->start(), graph->start());
-    Queue(graph->end());
+    Queue(scheduler_->graph_->end());
 
     while (!queue_.empty()) {  // Breadth-first backwards traversal.
       Node* node = queue_.front();
@@ -257,8 +255,6 @@ class CFGBuilder {
     for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) {
       ConnectBlocks(*i);  // Connect block to its predecessor/successors.
     }
-
-    FixNode(schedule_->end(), graph->end());
   }
 
   // Run the control flow graph construction for a minimal control-connected
@@ -293,29 +289,40 @@ class CFGBuilder {
  private:
   void FixNode(BasicBlock* block, Node* node) {
     schedule_->AddNode(block, node);
-    scheduler_->GetData(node)->is_connected_control_ = true;
     scheduler_->UpdatePlacement(node, Scheduler::kFixed);
   }
 
   void Queue(Node* node) {
-    // Mark the connected control nodes as they queued.
+    // Mark the connected control nodes as they are queued.
     Scheduler::SchedulerData* data = scheduler_->GetData(node);
     if (!data->is_connected_control_) {
+      data->is_connected_control_ = true;
       BuildBlocks(node);
       queue_.push(node);
       control_.push_back(node);
-      data->is_connected_control_ = true;
     }
   }
 
 
   void BuildBlocks(Node* node) {
     switch (node->opcode()) {
+      case IrOpcode::kEnd:
+        FixNode(schedule_->end(), node);
+        break;
+      case IrOpcode::kStart:
+        FixNode(schedule_->start(), node);
+        break;
       case IrOpcode::kLoop:
       case IrOpcode::kMerge:
-      case IrOpcode::kTerminate:
         BuildBlockForNode(node);
         break;
+      case IrOpcode::kTerminate: {
+        // Put Terminate in the loop to which it refers.
+        Node* loop = NodeProperties::GetControlInput(node);
+        BasicBlock* block = BuildBlockForNode(loop);
+        FixNode(block, node);
+        break;
+      }
       case IrOpcode::kBranch:
         BuildBlocksForSuccessors(node, IrOpcode::kIfTrue, IrOpcode::kIfFalse);
         break;
@@ -343,13 +350,15 @@ class CFGBuilder {
     }
   }
 
-  void BuildBlockForNode(Node* node) {
-    if (schedule_->block(node) == NULL) {
-      BasicBlock* block = schedule_->NewBasicBlock();
+  BasicBlock* BuildBlockForNode(Node* node) {
+    BasicBlock* block = schedule_->block(node);
+    if (block == NULL) {
+      block = schedule_->NewBasicBlock();
       Trace("Create block B%d for #%d:%s\n", block->id().ToInt(), node->id(),
             node->op()->mnemonic());
       FixNode(block, node);
     }
+    return block;
   }
 
   void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a,
index f6019f7..0ade4d1 100644 (file)
@@ -1955,7 +1955,7 @@ TEST(ScheduleTerminate) {
 
   graph.SetEnd(end);
 
-  Schedule* schedule = ComputeAndVerifySchedule(5, &graph);
+  Schedule* schedule = ComputeAndVerifySchedule(6, &graph);
   BasicBlock* block = schedule->block(loop);
   CHECK_NE(NULL, loop);
   CHECK_EQ(block, schedule->block(effect));