Commit c9283148 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Cleanup Schedule and related classes.

- Move unit tests to schedule-unittests.cc.
- Remove pre-C++11 cruft.
- Fix some include weirdness.

R=mstarzinger@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#26220}
parent 8ccc696b
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/compiler/common-operator.h" #include "src/compiler/common-operator.h"
#include "src/compiler/graph.h" #include "src/compiler/graph.h"
#include "src/compiler/machine-operator.h" #include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
#include "src/compiler/operator-properties.h" #include "src/compiler/operator-properties.h"
#include "src/compiler/schedule.h" #include "src/compiler/schedule.h"
......
...@@ -570,17 +570,15 @@ void GraphC1Visualizer::PrintSchedule(const char* phase, ...@@ -570,17 +570,15 @@ void GraphC1Visualizer::PrintSchedule(const char* phase,
PrintIndent(); PrintIndent();
os_ << "predecessors"; os_ << "predecessors";
for (BasicBlock::Predecessors::iterator j = current->predecessors_begin(); for (BasicBlock* predecessor : current->predecessors()) {
j != current->predecessors_end(); ++j) { os_ << " \"B" << predecessor->id() << "\"";
os_ << " \"B" << (*j)->id() << "\"";
} }
os_ << "\n"; os_ << "\n";
PrintIndent(); PrintIndent();
os_ << "successors"; os_ << "successors";
for (BasicBlock::Successors::iterator j = current->successors_begin(); for (BasicBlock* successor : current->successors()) {
j != current->successors_end(); ++j) { os_ << " \"B" << successor->id() << "\"";
os_ << " \"B" << (*j)->id() << "\"";
} }
os_ << "\n"; os_ << "\n";
...@@ -665,9 +663,8 @@ void GraphC1Visualizer::PrintSchedule(const char* phase, ...@@ -665,9 +663,8 @@ void GraphC1Visualizer::PrintSchedule(const char* phase,
os_ << -1 - current->id().ToInt() << " Goto"; os_ << -1 - current->id().ToInt() << " Goto";
} }
os_ << " ->"; os_ << " ->";
for (BasicBlock::Successors::iterator j = current->successors_begin(); for (BasicBlock* successor : current->successors()) {
j != current->successors_end(); ++j) { os_ << " B" << successor->id();
os_ << " B" << (*j)->id();
} }
if (FLAG_trace_turbo_types && current->control_input() != NULL) { if (FLAG_trace_turbo_types && current->control_input() != NULL) {
os_ << " "; os_ << " ";
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/compiler/common-operator.h" #include "src/compiler/common-operator.h"
#include "src/compiler/instruction.h" #include "src/compiler/instruction.h"
#include "src/compiler/machine-operator.h" #include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
#include "src/zone-containers.h" #include "src/zone-containers.h"
namespace v8 { namespace v8 {
...@@ -21,6 +22,8 @@ struct CallBuffer; // TODO(bmeurer): Remove this. ...@@ -21,6 +22,8 @@ struct CallBuffer; // TODO(bmeurer): Remove this.
class FlagsContinuation; class FlagsContinuation;
class Linkage; class Linkage;
// Instruction selection generates an InstructionSequence for a given Schedule.
class InstructionSelector FINAL { class InstructionSelector FINAL {
public: public:
// Forward declarations. // Forward declarations.
......
...@@ -387,14 +387,12 @@ static InstructionBlock* InstructionBlockFor(Zone* zone, ...@@ -387,14 +387,12 @@ static InstructionBlock* InstructionBlockFor(Zone* zone,
GetLoopEndRpo(block), block->deferred()); GetLoopEndRpo(block), block->deferred());
// Map successors and precessors // Map successors and precessors
instr_block->successors().reserve(block->SuccessorCount()); instr_block->successors().reserve(block->SuccessorCount());
for (auto it = block->successors_begin(); it != block->successors_end(); for (BasicBlock* successor : block->successors()) {
++it) { instr_block->successors().push_back(successor->GetRpoNumber());
instr_block->successors().push_back((*it)->GetRpoNumber());
} }
instr_block->predecessors().reserve(block->PredecessorCount()); instr_block->predecessors().reserve(block->PredecessorCount());
for (auto it = block->predecessors_begin(); it != block->predecessors_end(); for (BasicBlock* predecessor : block->predecessors()) {
++it) { instr_block->predecessors().push_back(predecessor->GetRpoNumber());
instr_block->predecessors().push_back((*it)->GetRpoNumber());
} }
return instr_block; return instr_block;
} }
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "src/compiler/schedule.h"
#include "src/compiler/node.h" #include "src/compiler/node.h"
#include "src/compiler/node-properties.h" #include "src/compiler/node-properties.h"
#include "src/compiler/node-properties-inl.h" #include "src/compiler/node-properties-inl.h"
#include "src/compiler/schedule.h"
#include "src/ostreams.h" #include "src/ostreams.h"
namespace v8 { namespace v8 {
...@@ -235,13 +236,10 @@ void Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) { ...@@ -235,13 +236,10 @@ void Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) {
void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) { void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) {
for (BasicBlock::Predecessors::iterator i = from->successors_begin(); for (BasicBlock* const successor : from->successors()) {
i != from->successors_end(); ++i) { to->AddSuccessor(successor);
BasicBlock* succ = *i; for (BasicBlock*& predecessor : successor->predecessors()) {
to->AddSuccessor(succ); if (predecessor == from) predecessor = to;
for (BasicBlock::Predecessors::iterator j = succ->predecessors_begin();
j != succ->predecessors_end(); ++j) {
if (*j == from) *j = to;
} }
} }
from->ClearSuccessors(); from->ClearSuccessors();
...@@ -264,24 +262,18 @@ void Schedule::SetBlockForNode(BasicBlock* block, Node* node) { ...@@ -264,24 +262,18 @@ void Schedule::SetBlockForNode(BasicBlock* block, Node* node) {
std::ostream& operator<<(std::ostream& os, const Schedule& s) { std::ostream& operator<<(std::ostream& os, const Schedule& s) {
// TODO(svenpanne) Const-correct the RPO stuff/iterators. for (BasicBlock* block : *s.rpo_order()) {
BasicBlockVector* rpo = const_cast<Schedule*>(&s)->rpo_order();
for (BasicBlockVectorIter i = rpo->begin(); i != rpo->end(); ++i) {
BasicBlock* block = *i;
os << "--- BLOCK B" << block->id(); os << "--- BLOCK B" << block->id();
if (block->deferred()) os << " (deferred)"; if (block->deferred()) os << " (deferred)";
if (block->PredecessorCount() != 0) os << " <- "; if (block->PredecessorCount() != 0) os << " <- ";
bool comma = false; bool comma = false;
for (BasicBlock::Predecessors::iterator j = block->predecessors_begin(); for (BasicBlock const* predecessor : block->predecessors()) {
j != block->predecessors_end(); ++j) {
if (comma) os << ", "; if (comma) os << ", ";
comma = true; comma = true;
os << "B" << (*j)->id(); os << "B" << predecessor->id();
} }
os << " ---\n"; os << " ---\n";
for (BasicBlock::const_iterator j = block->begin(); j != block->end(); for (Node* node : *block) {
++j) {
Node* node = *j;
os << " " << *node; os << " " << *node;
if (NodeProperties::IsTyped(node)) { if (NodeProperties::IsTyped(node)) {
Bounds bounds = NodeProperties::GetBounds(node); Bounds bounds = NodeProperties::GetBounds(node);
...@@ -304,11 +296,10 @@ std::ostream& operator<<(std::ostream& os, const Schedule& s) { ...@@ -304,11 +296,10 @@ std::ostream& operator<<(std::ostream& os, const Schedule& s) {
} }
os << " -> "; os << " -> ";
comma = false; comma = false;
for (BasicBlock::Successors::iterator j = block->successors_begin(); for (BasicBlock const* successor : block->successors()) {
j != block->successors_end(); ++j) {
if (comma) os << ", "; if (comma) os << ", ";
comma = true; comma = true;
os << "B" << (*j)->id(); os << "B" << successor->id();
} }
os << "\n"; os << "\n";
} }
......
...@@ -6,23 +6,24 @@ ...@@ -6,23 +6,24 @@
#define V8_COMPILER_SCHEDULE_H_ #define V8_COMPILER_SCHEDULE_H_
#include <iosfwd> #include <iosfwd>
#include <vector>
#include "src/v8.h" #include "src/zone-containers.h"
#include "src/compiler/node.h"
#include "src/compiler/opcodes.h"
#include "src/zone.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
// Forward declarations.
class BasicBlock; class BasicBlock;
class BasicBlockInstrumentor; class BasicBlockInstrumentor;
class Graph;
class ConstructScheduleData;
class CodeGenerator; // Because of a namespace bug in clang. class CodeGenerator; // Because of a namespace bug in clang.
class ConstructScheduleData;
class Node;
typedef ZoneVector<BasicBlock*> BasicBlockVector;
typedef ZoneVector<Node*> NodeVector;
// A basic block contains an ordered list of nodes and ends with a control // A basic block contains an ordered list of nodes and ends with a control
// node. Note that if a basic block has phis, then all phis must appear as the // node. Note that if a basic block has phis, then all phis must appear as the
...@@ -83,36 +84,26 @@ class BasicBlock FINAL : public ZoneObject { ...@@ -83,36 +84,26 @@ class BasicBlock FINAL : public ZoneObject {
Id id() const { return id_; } Id id() const { return id_; }
// Predecessors and successors. // Predecessors.
typedef ZoneVector<BasicBlock*> Predecessors; BasicBlockVector& predecessors() { return predecessors_; }
Predecessors::iterator predecessors_begin() { return predecessors_.begin(); } const BasicBlockVector& predecessors() const { return predecessors_; }
Predecessors::iterator predecessors_end() { return predecessors_.end(); }
Predecessors::const_iterator predecessors_begin() const {
return predecessors_.begin();
}
Predecessors::const_iterator predecessors_end() const {
return predecessors_.end();
}
size_t PredecessorCount() const { return predecessors_.size(); } size_t PredecessorCount() const { return predecessors_.size(); }
BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; } BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; }
void ClearPredecessors() { predecessors_.clear(); } void ClearPredecessors() { predecessors_.clear(); }
void AddPredecessor(BasicBlock* predecessor); void AddPredecessor(BasicBlock* predecessor);
typedef ZoneVector<BasicBlock*> Successors; // Successors.
Successors::iterator successors_begin() { return successors_.begin(); } BasicBlockVector& successors() { return successors_; }
Successors::iterator successors_end() { return successors_.end(); } const BasicBlockVector& successors() const { return successors_; }
Successors::const_iterator successors_begin() const {
return successors_.begin();
}
Successors::const_iterator successors_end() const {
return successors_.end();
}
size_t SuccessorCount() const { return successors_.size(); } size_t SuccessorCount() const { return successors_.size(); }
BasicBlock* SuccessorAt(size_t index) { return successors_[index]; } BasicBlock* SuccessorAt(size_t index) { return successors_[index]; }
void ClearSuccessors() { successors_.clear(); } void ClearSuccessors() { successors_.clear(); }
void AddSuccessor(BasicBlock* successor); void AddSuccessor(BasicBlock* successor);
// Nodes in the basic block. // Nodes in the basic block.
typedef Node* value_type;
bool empty() const { return nodes_.empty(); }
size_t size() const { return nodes_.size(); }
Node* NodeAt(size_t index) { return nodes_[index]; } Node* NodeAt(size_t index) { return nodes_[index]; }
size_t NodeCount() const { return nodes_.size(); } size_t NodeCount() const { return nodes_.size(); }
...@@ -191,20 +182,17 @@ class BasicBlock FINAL : public ZoneObject { ...@@ -191,20 +182,17 @@ class BasicBlock FINAL : public ZoneObject {
Node* control_input_; // Input value for control. Node* control_input_; // Input value for control.
NodeVector nodes_; // nodes of this block in forward order. NodeVector nodes_; // nodes of this block in forward order.
Successors successors_; BasicBlockVector successors_;
Predecessors predecessors_; BasicBlockVector predecessors_;
Id id_; Id id_;
DISALLOW_COPY_AND_ASSIGN(BasicBlock); DISALLOW_COPY_AND_ASSIGN(BasicBlock);
}; };
std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c); std::ostream& operator<<(std::ostream&, const BasicBlock::Control&);
std::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id); std::ostream& operator<<(std::ostream&, const BasicBlock::Id&);
std::ostream& operator<<(std::ostream& os, const BasicBlock::RpoNumber& rpo); std::ostream& operator<<(std::ostream&, const BasicBlock::RpoNumber&);
typedef ZoneVector<BasicBlock*> BasicBlockVector;
typedef BasicBlockVector::iterator BasicBlockVectorIter;
typedef BasicBlockVector::reverse_iterator BasicBlockVectorRIter;
// A schedule represents the result of assigning nodes to basic blocks // A schedule represents the result of assigning nodes to basic blocks
// and ordering them within basic blocks. Prior to computing a schedule, // and ordering them within basic blocks. Prior to computing a schedule,
...@@ -286,7 +274,7 @@ class Schedule FINAL : public ZoneObject { ...@@ -286,7 +274,7 @@ class Schedule FINAL : public ZoneObject {
DISALLOW_COPY_AND_ASSIGN(Schedule); DISALLOW_COPY_AND_ASSIGN(Schedule);
}; };
std::ostream& operator<<(std::ostream& os, const Schedule& s); std::ostream& operator<<(std::ostream&, const Schedule&);
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
......
...@@ -1032,8 +1032,8 @@ void Scheduler::ComputeSpecialRPONumbering() { ...@@ -1032,8 +1032,8 @@ void Scheduler::ComputeSpecialRPONumbering() {
void Scheduler::PropagateImmediateDominators(BasicBlock* block) { void Scheduler::PropagateImmediateDominators(BasicBlock* block) {
for (/*nop*/; block != NULL; block = block->rpo_next()) { for (/*nop*/; block != NULL; block = block->rpo_next()) {
BasicBlock::Predecessors::iterator pred = block->predecessors_begin(); auto pred = block->predecessors().begin();
BasicBlock::Predecessors::iterator end = block->predecessors_end(); auto end = block->predecessors().end();
DCHECK(pred != end); // All blocks except start have predecessors. DCHECK(pred != end); // All blocks except start have predecessors.
BasicBlock* dominator = *pred; BasicBlock* dominator = *pred;
// For multiple predecessors, walk up the dominator tree until a common // For multiple predecessors, walk up the dominator tree until a common
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/v8.h" #include "src/v8.h"
#include "src/compiler/node.h"
#include "src/compiler/opcodes.h" #include "src/compiler/opcodes.h"
#include "src/compiler/schedule.h" #include "src/compiler/schedule.h"
#include "src/compiler/zone-pool.h" #include "src/compiler/zone-pool.h"
...@@ -16,10 +17,13 @@ namespace v8 { ...@@ -16,10 +17,13 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
// Forward declarations.
class CFGBuilder; class CFGBuilder;
class ControlEquivalence; class ControlEquivalence;
class Graph;
class SpecialRPONumberer; class SpecialRPONumberer;
// Computes a schedule from a graph, placing nodes into basic blocks and // Computes a schedule from a graph, placing nodes into basic blocks and
// ordering the basic blocks in the special RPO order. // ordering the basic blocks in the special RPO order.
class Scheduler { class Scheduler {
......
...@@ -840,15 +840,13 @@ void ScheduleVerifier::Run(Schedule* schedule) { ...@@ -840,15 +840,13 @@ void ScheduleVerifier::Run(Schedule* schedule) {
++b) { ++b) {
CHECK_EQ((*b), schedule->GetBlockById((*b)->id())); CHECK_EQ((*b), schedule->GetBlockById((*b)->id()));
// All predecessors and successors should be in rpo and in this schedule. // All predecessors and successors should be in rpo and in this schedule.
for (BasicBlock::Predecessors::iterator j = (*b)->predecessors_begin(); for (BasicBlock const* predecessor : (*b)->predecessors()) {
j != (*b)->predecessors_end(); ++j) { CHECK_GE(predecessor->rpo_number(), 0);
CHECK_GE((*j)->rpo_number(), 0); CHECK_EQ(predecessor, schedule->GetBlockById(predecessor->id()));
CHECK_EQ((*j), schedule->GetBlockById((*j)->id())); }
} for (BasicBlock const* successor : (*b)->successors()) {
for (BasicBlock::Successors::iterator j = (*b)->successors_begin(); CHECK_GE(successor->rpo_number(), 0);
j != (*b)->successors_end(); ++j) { CHECK_EQ(successor, schedule->GetBlockById(successor->id()));
CHECK_GE((*j)->rpo_number(), 0);
CHECK_EQ((*j), schedule->GetBlockById((*j)->id()));
} }
} }
......
...@@ -88,7 +88,6 @@ ...@@ -88,7 +88,6 @@
'compiler/test-run-properties.cc', 'compiler/test-run-properties.cc',
'compiler/test-run-stackcheck.cc', 'compiler/test-run-stackcheck.cc',
'compiler/test-run-variables.cc', 'compiler/test-run-variables.cc',
'compiler/test-schedule.cc',
'compiler/test-scheduler.cc', 'compiler/test-scheduler.cc',
'compiler/test-simplified-lowering.cc', 'compiler/test-simplified-lowering.cc',
'compiler/test-typer.cc', 'compiler/test-typer.cc',
......
...@@ -131,10 +131,7 @@ TEST(InstructionBasic) { ...@@ -131,10 +131,7 @@ TEST(InstructionBasic) {
BasicBlockVector* blocks = R.schedule.rpo_order(); BasicBlockVector* blocks = R.schedule.rpo_order();
CHECK_EQ(static_cast<int>(blocks->size()), R.code->InstructionBlockCount()); CHECK_EQ(static_cast<int>(blocks->size()), R.code->InstructionBlockCount());
int index = 0; for (auto block : *blocks) {
for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end();
i++, index++) {
BasicBlock* block = *i;
CHECK_EQ(block->rpo_number(), R.BlockAt(block)->rpo_number().ToInt()); CHECK_EQ(block->rpo_number(), R.BlockAt(block)->rpo_number().ToInt());
CHECK_EQ(block->id().ToInt(), R.BlockAt(block)->id().ToInt()); CHECK_EQ(block->id().ToInt(), R.BlockAt(block)->id().ToInt());
CHECK_EQ(NULL, block->loop_end()); CHECK_EQ(NULL, block->loop_end());
......
// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/v8.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include "src/compiler/schedule.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
using namespace v8::internal::compiler;
static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
"dummy", 0, 0, 0, 0, 0, 0);
TEST(TestScheduleAllocation) {
HandleAndZoneScope scope;
Schedule schedule(scope.main_zone());
CHECK_NE(NULL, schedule.start());
CHECK_EQ(schedule.start(), schedule.GetBlockById(BasicBlock::Id::FromInt(0)));
}
TEST(TestScheduleAddNode) {
HandleAndZoneScope scope;
Schedule schedule(scope.main_zone());
Graph graph(scope.main_zone());
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator);
BasicBlock* entry = schedule.start();
schedule.AddNode(entry, n0);
schedule.AddNode(entry, n1);
CHECK_EQ(entry, schedule.block(n0));
CHECK_EQ(entry, schedule.block(n1));
CHECK(schedule.SameBasicBlock(n0, n1));
Node* n2 = graph.NewNode(&dummy_operator);
CHECK_EQ(NULL, schedule.block(n2));
}
TEST(TestScheduleAddGoto) {
HandleAndZoneScope scope;
Schedule schedule(scope.main_zone());
BasicBlock* entry = schedule.start();
BasicBlock* next = schedule.NewBasicBlock();
schedule.AddGoto(entry, next);
CHECK_EQ(0, static_cast<int>(entry->PredecessorCount()));
CHECK_EQ(1, static_cast<int>(entry->SuccessorCount()));
CHECK_EQ(next, entry->SuccessorAt(0));
CHECK_EQ(1, static_cast<int>(next->PredecessorCount()));
CHECK_EQ(entry, next->PredecessorAt(0));
CHECK_EQ(0, static_cast<int>(next->SuccessorCount()));
}
TEST(TestScheduleAddBranch) {
HandleAndZoneScope scope;
Schedule schedule(scope.main_zone());
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
Node* n0 = graph.NewNode(&dummy_operator);
Node* b = graph.NewNode(common.Branch(), n0);
BasicBlock* entry = schedule.start();
BasicBlock* tblock = schedule.NewBasicBlock();
BasicBlock* fblock = schedule.NewBasicBlock();
schedule.AddBranch(entry, b, tblock, fblock);
CHECK_EQ(0, static_cast<int>(entry->PredecessorCount()));
CHECK_EQ(2, static_cast<int>(entry->SuccessorCount()));
CHECK_EQ(tblock, entry->SuccessorAt(0));
CHECK_EQ(fblock, entry->SuccessorAt(1));
CHECK_EQ(1, static_cast<int>(tblock->PredecessorCount()));
CHECK_EQ(entry, tblock->PredecessorAt(0));
CHECK_EQ(0, static_cast<int>(tblock->SuccessorCount()));
CHECK_EQ(1, static_cast<int>(fblock->PredecessorCount()));
CHECK_EQ(entry, fblock->PredecessorAt(0));
CHECK_EQ(0, static_cast<int>(fblock->SuccessorCount()));
}
TEST(TestScheduleAddReturn) {
HandleAndZoneScope scope;
Schedule schedule(scope.main_zone());
Graph graph(scope.main_zone());
Node* n0 = graph.NewNode(&dummy_operator);
BasicBlock* entry = schedule.start();
schedule.AddReturn(entry, n0);
CHECK_EQ(0, static_cast<int>(entry->PredecessorCount()));
CHECK_EQ(1, static_cast<int>(entry->SuccessorCount()));
CHECK_EQ(schedule.end(), entry->SuccessorAt(0));
}
TEST(TestScheduleAddThrow) {
HandleAndZoneScope scope;
Schedule schedule(scope.main_zone());
Graph graph(scope.main_zone());
Node* n0 = graph.NewNode(&dummy_operator);
BasicBlock* entry = schedule.start();
schedule.AddThrow(entry, n0);
CHECK_EQ(0, static_cast<int>(entry->PredecessorCount()));
CHECK_EQ(1, static_cast<int>(entry->SuccessorCount()));
CHECK_EQ(schedule.end(), entry->SuccessorAt(0));
}
TEST(TestScheduleInsertBranch) {
HandleAndZoneScope scope;
Schedule schedule(scope.main_zone());
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
Node* n0 = graph.NewNode(&dummy_operator);
Node* n1 = graph.NewNode(&dummy_operator);
Node* b = graph.NewNode(common.Branch(), n1);
BasicBlock* entry = schedule.start();
BasicBlock* tblock = schedule.NewBasicBlock();
BasicBlock* fblock = schedule.NewBasicBlock();
BasicBlock* merge = schedule.NewBasicBlock();
schedule.AddReturn(entry, n0);
schedule.AddGoto(tblock, merge);
schedule.AddGoto(fblock, merge);
schedule.InsertBranch(entry, merge, b, tblock, fblock);
CHECK_EQ(0, static_cast<int>(entry->PredecessorCount()));
CHECK_EQ(2, static_cast<int>(entry->SuccessorCount()));
CHECK_EQ(tblock, entry->SuccessorAt(0));
CHECK_EQ(fblock, entry->SuccessorAt(1));
CHECK_EQ(2, static_cast<int>(merge->PredecessorCount()));
CHECK_EQ(1, static_cast<int>(merge->SuccessorCount()));
CHECK_EQ(schedule.end(), merge->SuccessorAt(0));
CHECK_EQ(1, static_cast<int>(schedule.end()->PredecessorCount()));
CHECK_EQ(0, static_cast<int>(schedule.end()->SuccessorCount()));
CHECK_EQ(merge, schedule.end()->PredecessorAt(0));
}
TEST(BuildMulNodeGraph) {
HandleAndZoneScope scope;
Schedule schedule(scope.main_zone());
Graph graph(scope.main_zone());
CommonOperatorBuilder common(scope.main_zone());
// TODO(titzer): use test operators.
MachineOperatorBuilder machine(scope.main_zone());
Node* start = graph.NewNode(common.Start(0));
graph.SetStart(start);
Node* param0 = graph.NewNode(common.Parameter(0), graph.start());
Node* param1 = graph.NewNode(common.Parameter(1), graph.start());
Node* mul = graph.NewNode(machine.Int32Mul(), param0, param1);
Node* ret = graph.NewNode(common.Return(), mul, start);
USE(ret);
}
...@@ -86,21 +86,13 @@ static TestLoop* CreateLoop(Schedule* schedule, int count) { ...@@ -86,21 +86,13 @@ static TestLoop* CreateLoop(Schedule* schedule, int count) {
} }
static int GetScheduledNodeCount(Schedule* schedule) { static int GetScheduledNodeCount(const Schedule* schedule) {
int node_count = 0; size_t node_count = 0;
for (BasicBlockVectorIter i = schedule->rpo_order()->begin(); for (auto block : *schedule->rpo_order()) {
i != schedule->rpo_order()->end(); ++i) { node_count += block->NodeCount();
BasicBlock* block = *i; if (block->control() != BasicBlock::kNone) ++node_count;
for (BasicBlock::const_iterator j = block->begin(); j != block->end();
++j) {
++node_count;
}
BasicBlock::Control control = block->control();
if (control != BasicBlock::kNone) {
++node_count;
}
} }
return node_count; return static_cast<int>(node_count);
} }
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/node.h"
#include "src/compiler/schedule.h"
#include "test/unittests/test-utils.h"
#include "testing/gmock/include/gmock/gmock.h"
using testing::ElementsAre;
namespace v8 {
namespace internal {
namespace compiler {
typedef TestWithZone ScheduleTest;
namespace {
const Operator kBranchOperator(IrOpcode::kBranch, Operator::kNoProperties,
"Branch", 0, 0, 0, 0, 0, 0);
const Operator kDummyOperator(IrOpcode::kParameter, Operator::kNoProperties,
"Dummy", 0, 0, 0, 0, 0, 0);
} // namespace
TEST_F(ScheduleTest, Constructor) {
Schedule schedule(zone());
EXPECT_NE(nullptr, schedule.start());
EXPECT_EQ(schedule.start(),
schedule.GetBlockById(BasicBlock::Id::FromInt(0)));
EXPECT_NE(nullptr, schedule.end());
EXPECT_EQ(schedule.end(), schedule.GetBlockById(BasicBlock::Id::FromInt(1)));
EXPECT_NE(schedule.start(), schedule.end());
}
TEST_F(ScheduleTest, AddNode) {
Schedule schedule(zone());
BasicBlock* start = schedule.start();
Node* node0 = Node::New(zone(), 0, &kDummyOperator, 0, nullptr, false);
EXPECT_EQ(nullptr, schedule.block(node0));
schedule.AddNode(start, node0);
EXPECT_EQ(start, schedule.block(node0));
EXPECT_THAT(*start, ElementsAre(node0));
Node* node1 = Node::New(zone(), 1, &kDummyOperator, 0, nullptr, false);
EXPECT_EQ(nullptr, schedule.block(node1));
schedule.AddNode(start, node1);
EXPECT_EQ(start, schedule.block(node1));
EXPECT_THAT(*start, ElementsAre(node0, node1));
EXPECT_TRUE(schedule.SameBasicBlock(node0, node1));
}
TEST_F(ScheduleTest, AddGoto) {
Schedule schedule(zone());
BasicBlock* start = schedule.start();
BasicBlock* end = schedule.end();
BasicBlock* block = schedule.NewBasicBlock();
schedule.AddGoto(start, block);
EXPECT_EQ(0u, start->PredecessorCount());
EXPECT_EQ(1u, start->SuccessorCount());
EXPECT_EQ(block, start->SuccessorAt(0));
EXPECT_THAT(start->successors(), ElementsAre(block));
EXPECT_EQ(1u, block->PredecessorCount());
EXPECT_EQ(0u, block->SuccessorCount());
EXPECT_EQ(start, block->PredecessorAt(0));
EXPECT_THAT(block->predecessors(), ElementsAre(start));
EXPECT_EQ(0u, end->PredecessorCount());
EXPECT_EQ(0u, end->SuccessorCount());
}
TEST_F(ScheduleTest, AddBranch) {
Schedule schedule(zone());
BasicBlock* start = schedule.start();
Node* branch = Node::New(zone(), 0, &kBranchOperator, 0, nullptr, false);
BasicBlock* tblock = schedule.NewBasicBlock();
BasicBlock* fblock = schedule.NewBasicBlock();
schedule.AddBranch(start, branch, tblock, fblock);
EXPECT_EQ(start, schedule.block(branch));
EXPECT_EQ(0u, start->PredecessorCount());
EXPECT_EQ(2u, start->SuccessorCount());
EXPECT_EQ(tblock, start->SuccessorAt(0));
EXPECT_EQ(fblock, start->SuccessorAt(1));
EXPECT_THAT(start->successors(), ElementsAre(tblock, fblock));
EXPECT_EQ(1u, tblock->PredecessorCount());
EXPECT_EQ(0u, tblock->SuccessorCount());
EXPECT_EQ(start, tblock->PredecessorAt(0));
EXPECT_THAT(tblock->predecessors(), ElementsAre(start));
EXPECT_EQ(1u, fblock->PredecessorCount());
EXPECT_EQ(0u, fblock->SuccessorCount());
EXPECT_EQ(start, fblock->PredecessorAt(0));
EXPECT_THAT(fblock->predecessors(), ElementsAre(start));
}
TEST_F(ScheduleTest, AddReturn) {
Schedule schedule(zone());
BasicBlock* start = schedule.start();
BasicBlock* end = schedule.end();
Node* node = Node::New(zone(), 0, &kDummyOperator, 0, nullptr, false);
schedule.AddReturn(start, node);
EXPECT_EQ(0u, start->PredecessorCount());
EXPECT_EQ(1u, start->SuccessorCount());
EXPECT_EQ(end, start->SuccessorAt(0));
EXPECT_THAT(start->successors(), ElementsAre(end));
}
TEST_F(ScheduleTest, InsertBranch) {
Schedule schedule(zone());
BasicBlock* start = schedule.start();
BasicBlock* end = schedule.end();
Node* node = Node::New(zone(), 0, &kDummyOperator, 0, nullptr, false);
Node* branch = Node::New(zone(), 0, &kBranchOperator, 0, nullptr, false);
BasicBlock* tblock = schedule.NewBasicBlock();
BasicBlock* fblock = schedule.NewBasicBlock();
BasicBlock* mblock = schedule.NewBasicBlock();
schedule.AddReturn(start, node);
schedule.AddGoto(tblock, mblock);
schedule.AddGoto(fblock, mblock);
schedule.InsertBranch(start, mblock, branch, tblock, fblock);
EXPECT_EQ(0u, start->PredecessorCount());
EXPECT_EQ(2u, start->SuccessorCount());
EXPECT_EQ(tblock, start->SuccessorAt(0));
EXPECT_EQ(fblock, start->SuccessorAt(1));
EXPECT_THAT(start->successors(), ElementsAre(tblock, fblock));
EXPECT_EQ(2u, mblock->PredecessorCount());
EXPECT_EQ(1u, mblock->SuccessorCount());
EXPECT_EQ(end, mblock->SuccessorAt(0));
EXPECT_THAT(mblock->predecessors(), ElementsAre(tblock, fblock));
EXPECT_THAT(mblock->successors(), ElementsAre(end));
EXPECT_EQ(1u, end->PredecessorCount());
EXPECT_EQ(0u, end->SuccessorCount());
EXPECT_EQ(mblock, end->PredecessorAt(0));
EXPECT_THAT(end->predecessors(), ElementsAre(mblock));
}
} // namespace compiler
} // namespace internal
} // namespace v8
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
'compiler/node-unittest.cc', 'compiler/node-unittest.cc',
'compiler/opcodes-unittest.cc', 'compiler/opcodes-unittest.cc',
'compiler/register-allocator-unittest.cc', 'compiler/register-allocator-unittest.cc',
'compiler/schedule-unittest.cc',
'compiler/select-lowering-unittest.cc', 'compiler/select-lowering-unittest.cc',
'compiler/simplified-operator-reducer-unittest.cc', 'compiler/simplified-operator-reducer-unittest.cc',
'compiler/simplified-operator-unittest.cc', 'compiler/simplified-operator-unittest.cc',
......
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