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 @@
#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);
}
......
......@@ -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) {
......
......@@ -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");
}
}
......
......@@ -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,
......
......@@ -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));
......
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