Commit 2a57f036 authored by titzer@chromium.org's avatar titzer@chromium.org

Run ControlReducer early after graph building, then again later.

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
parent f02d4acb
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "src/compiler/ast-loop-assignment-analyzer.h" #include "src/compiler/ast-loop-assignment-analyzer.h"
#include "src/compiler/control-builders.h" #include "src/compiler/control-builders.h"
#include "src/compiler/machine-operator.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-inl.h"
#include "src/compiler/node-properties.h" #include "src/compiler/node-properties.h"
#include "src/full-codegen.h" #include "src/full-codegen.h"
...@@ -2059,9 +2060,31 @@ Node* AstGraphBuilder::BuildLoadGlobalObject() { ...@@ -2059,9 +2060,31 @@ Node* AstGraphBuilder::BuildLoadGlobalObject() {
} }
Node* AstGraphBuilder::BuildToBoolean(Node* value) { Node* AstGraphBuilder::BuildToBoolean(Node* input) {
// TODO(mstarzinger): Possible optimization is to NOP for boolean values. // TODO(titzer): this should be in a JSOperatorReducer.
return NewNode(javascript()->ToBoolean(), value); 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);
} }
......
...@@ -67,6 +67,11 @@ class JSGraph : public ZoneObject { ...@@ -67,6 +67,11 @@ class JSGraph : public ZoneObject {
return Int32Constant(bit_cast<int32_t>(value)); 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. // Creates a Int64Constant node, usually canonicalized.
Node* Int64Constant(int64_t value); Node* Int64Constant(int64_t value);
Node* Uint64Constant(uint64_t value) { Node* Uint64Constant(uint64_t value) {
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include "src/compiler/js-inlining.h" #include "src/compiler/js-inlining.h"
#include "src/compiler/js-typed-lowering.h" #include "src/compiler/js-typed-lowering.h"
#include "src/compiler/machine-operator-reducer.h" #include "src/compiler/machine-operator-reducer.h"
#include "src/compiler/phi-reducer.h"
#include "src/compiler/pipeline-statistics.h" #include "src/compiler/pipeline-statistics.h"
#include "src/compiler/register-allocator.h" #include "src/compiler/register-allocator.h"
#include "src/compiler/schedule.h" #include "src/compiler/schedule.h"
...@@ -323,19 +322,21 @@ Handle<Code> Pipeline::GenerateCode() { ...@@ -323,19 +322,21 @@ Handle<Code> Pipeline::GenerateCode() {
graph_builder.CreateGraph(); graph_builder.CreateGraph();
context_node = graph_builder.GetFunctionContext(); 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); 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()) { if (info()->is_context_specializing()) {
SourcePositionTable::Scope pos(data.source_positions(), SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown()); SourcePosition::Unknown());
...@@ -432,14 +433,15 @@ Handle<Code> Pipeline::GenerateCode() { ...@@ -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(), SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown()); SourcePosition::Unknown());
ZonePool::Scope zone_scope(data.zone_pool()); ZonePool::Scope zone_scope(data.zone_pool());
ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(), ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(),
data.common()); data.common());
VerifyAndPrintGraph(data.graph(), "Control reduced"); VerifyAndPrintGraph(data.graph(), "Late Control reduced");
} }
} }
......
...@@ -241,9 +241,7 @@ class CFGBuilder { ...@@ -241,9 +241,7 @@ class CFGBuilder {
// backwards from end through control edges, building and connecting the // backwards from end through control edges, building and connecting the
// basic blocks for control nodes. // basic blocks for control nodes.
void Run() { void Run() {
Graph* graph = scheduler_->graph_; Queue(scheduler_->graph_->end());
FixNode(schedule_->start(), graph->start());
Queue(graph->end());
while (!queue_.empty()) { // Breadth-first backwards traversal. while (!queue_.empty()) { // Breadth-first backwards traversal.
Node* node = queue_.front(); Node* node = queue_.front();
...@@ -257,8 +255,6 @@ class CFGBuilder { ...@@ -257,8 +255,6 @@ class CFGBuilder {
for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) { for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) {
ConnectBlocks(*i); // Connect block to its predecessor/successors. ConnectBlocks(*i); // Connect block to its predecessor/successors.
} }
FixNode(schedule_->end(), graph->end());
} }
// Run the control flow graph construction for a minimal control-connected // Run the control flow graph construction for a minimal control-connected
...@@ -293,29 +289,40 @@ class CFGBuilder { ...@@ -293,29 +289,40 @@ class CFGBuilder {
private: private:
void FixNode(BasicBlock* block, Node* node) { void FixNode(BasicBlock* block, Node* node) {
schedule_->AddNode(block, node); schedule_->AddNode(block, node);
scheduler_->GetData(node)->is_connected_control_ = true;
scheduler_->UpdatePlacement(node, Scheduler::kFixed); scheduler_->UpdatePlacement(node, Scheduler::kFixed);
} }
void Queue(Node* node) { 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); Scheduler::SchedulerData* data = scheduler_->GetData(node);
if (!data->is_connected_control_) { if (!data->is_connected_control_) {
data->is_connected_control_ = true;
BuildBlocks(node); BuildBlocks(node);
queue_.push(node); queue_.push(node);
control_.push_back(node); control_.push_back(node);
data->is_connected_control_ = true;
} }
} }
void BuildBlocks(Node* node) { void BuildBlocks(Node* node) {
switch (node->opcode()) { switch (node->opcode()) {
case IrOpcode::kEnd:
FixNode(schedule_->end(), node);
break;
case IrOpcode::kStart:
FixNode(schedule_->start(), node);
break;
case IrOpcode::kLoop: case IrOpcode::kLoop:
case IrOpcode::kMerge: case IrOpcode::kMerge:
case IrOpcode::kTerminate:
BuildBlockForNode(node); BuildBlockForNode(node);
break; 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: case IrOpcode::kBranch:
BuildBlocksForSuccessors(node, IrOpcode::kIfTrue, IrOpcode::kIfFalse); BuildBlocksForSuccessors(node, IrOpcode::kIfTrue, IrOpcode::kIfFalse);
break; break;
...@@ -343,13 +350,15 @@ class CFGBuilder { ...@@ -343,13 +350,15 @@ class CFGBuilder {
} }
} }
void BuildBlockForNode(Node* node) { BasicBlock* BuildBlockForNode(Node* node) {
if (schedule_->block(node) == NULL) { BasicBlock* block = schedule_->block(node);
BasicBlock* block = schedule_->NewBasicBlock(); if (block == NULL) {
block = schedule_->NewBasicBlock();
Trace("Create block B%d for #%d:%s\n", block->id().ToInt(), node->id(), Trace("Create block B%d for #%d:%s\n", block->id().ToInt(), node->id(),
node->op()->mnemonic()); node->op()->mnemonic());
FixNode(block, node); FixNode(block, node);
} }
return block;
} }
void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a, void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a,
......
...@@ -1955,7 +1955,7 @@ TEST(ScheduleTerminate) { ...@@ -1955,7 +1955,7 @@ TEST(ScheduleTerminate) {
graph.SetEnd(end); graph.SetEnd(end);
Schedule* schedule = ComputeAndVerifySchedule(5, &graph); Schedule* schedule = ComputeAndVerifySchedule(6, &graph);
BasicBlock* block = schedule->block(loop); BasicBlock* block = schedule->block(loop);
CHECK_NE(NULL, loop); CHECK_NE(NULL, loop);
CHECK_EQ(block, schedule->block(effect)); CHECK_EQ(block, schedule->block(effect));
......
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