#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-properties.h"
#include "src/compiler/schedule.h"
PrintIndent();
os_ << "predecessors";
- for (BasicBlock::Predecessors::iterator j = current->predecessors_begin();
- j != current->predecessors_end(); ++j) {
- os_ << " \"B" << (*j)->id() << "\"";
+ for (BasicBlock* predecessor : current->predecessors()) {
+ os_ << " \"B" << predecessor->id() << "\"";
}
os_ << "\n";
PrintIndent();
os_ << "successors";
- for (BasicBlock::Successors::iterator j = current->successors_begin();
- j != current->successors_end(); ++j) {
- os_ << " \"B" << (*j)->id() << "\"";
+ for (BasicBlock* successor : current->successors()) {
+ os_ << " \"B" << successor->id() << "\"";
}
os_ << "\n";
os_ << -1 - current->id().ToInt() << " Goto";
}
os_ << " ->";
- for (BasicBlock::Successors::iterator j = current->successors_begin();
- j != current->successors_end(); ++j) {
- os_ << " B" << (*j)->id();
+ for (BasicBlock* successor : current->successors()) {
+ os_ << " B" << successor->id();
}
if (FLAG_trace_turbo_types && current->control_input() != NULL) {
os_ << " ";
#include "src/compiler/common-operator.h"
#include "src/compiler/instruction.h"
#include "src/compiler/machine-operator.h"
+#include "src/compiler/node.h"
#include "src/zone-containers.h"
namespace v8 {
class FlagsContinuation;
class Linkage;
+
+// Instruction selection generates an InstructionSequence for a given Schedule.
class InstructionSelector FINAL {
public:
// Forward declarations.
GetLoopEndRpo(block), block->deferred());
// Map successors and precessors
instr_block->successors().reserve(block->SuccessorCount());
- for (auto it = block->successors_begin(); it != block->successors_end();
- ++it) {
- instr_block->successors().push_back((*it)->GetRpoNumber());
+ for (BasicBlock* successor : block->successors()) {
+ instr_block->successors().push_back(successor->GetRpoNumber());
}
instr_block->predecessors().reserve(block->PredecessorCount());
- for (auto it = block->predecessors_begin(); it != block->predecessors_end();
- ++it) {
- instr_block->predecessors().push_back((*it)->GetRpoNumber());
+ for (BasicBlock* predecessor : block->predecessors()) {
+ instr_block->predecessors().push_back(predecessor->GetRpoNumber());
}
return instr_block;
}
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/compiler/schedule.h"
+
#include "src/compiler/node.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/node-properties-inl.h"
-#include "src/compiler/schedule.h"
#include "src/ostreams.h"
namespace v8 {
void Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) {
- for (BasicBlock::Predecessors::iterator i = from->successors_begin();
- i != from->successors_end(); ++i) {
- BasicBlock* succ = *i;
- to->AddSuccessor(succ);
- for (BasicBlock::Predecessors::iterator j = succ->predecessors_begin();
- j != succ->predecessors_end(); ++j) {
- if (*j == from) *j = to;
+ for (BasicBlock* const successor : from->successors()) {
+ to->AddSuccessor(successor);
+ for (BasicBlock*& predecessor : successor->predecessors()) {
+ if (predecessor == from) predecessor = to;
}
}
from->ClearSuccessors();
std::ostream& operator<<(std::ostream& os, const Schedule& s) {
- // TODO(svenpanne) Const-correct the RPO stuff/iterators.
- BasicBlockVector* rpo = const_cast<Schedule*>(&s)->rpo_order();
- for (BasicBlockVectorIter i = rpo->begin(); i != rpo->end(); ++i) {
- BasicBlock* block = *i;
+ for (BasicBlock* block : *s.rpo_order()) {
os << "--- BLOCK B" << block->id();
if (block->deferred()) os << " (deferred)";
if (block->PredecessorCount() != 0) os << " <- ";
bool comma = false;
- for (BasicBlock::Predecessors::iterator j = block->predecessors_begin();
- j != block->predecessors_end(); ++j) {
+ for (BasicBlock const* predecessor : block->predecessors()) {
if (comma) os << ", ";
comma = true;
- os << "B" << (*j)->id();
+ os << "B" << predecessor->id();
}
os << " ---\n";
- for (BasicBlock::const_iterator j = block->begin(); j != block->end();
- ++j) {
- Node* node = *j;
+ for (Node* node : *block) {
os << " " << *node;
if (NodeProperties::IsTyped(node)) {
Bounds bounds = NodeProperties::GetBounds(node);
}
os << " -> ";
comma = false;
- for (BasicBlock::Successors::iterator j = block->successors_begin();
- j != block->successors_end(); ++j) {
+ for (BasicBlock const* successor : block->successors()) {
if (comma) os << ", ";
comma = true;
- os << "B" << (*j)->id();
+ os << "B" << successor->id();
}
os << "\n";
}
#define V8_COMPILER_SCHEDULE_H_
#include <iosfwd>
-#include <vector>
-#include "src/v8.h"
-
-#include "src/compiler/node.h"
-#include "src/compiler/opcodes.h"
-#include "src/zone.h"
+#include "src/zone-containers.h"
namespace v8 {
namespace internal {
namespace compiler {
+// Forward declarations.
class BasicBlock;
class BasicBlockInstrumentor;
-class Graph;
-class ConstructScheduleData;
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
// node. Note that if a basic block has phis, then all phis must appear as the
Id id() const { return id_; }
- // Predecessors and successors.
- typedef ZoneVector<BasicBlock*> Predecessors;
- Predecessors::iterator predecessors_begin() { return predecessors_.begin(); }
- 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();
- }
+ // Predecessors.
+ BasicBlockVector& predecessors() { return predecessors_; }
+ const BasicBlockVector& predecessors() const { return predecessors_; }
size_t PredecessorCount() const { return predecessors_.size(); }
BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; }
void ClearPredecessors() { predecessors_.clear(); }
void AddPredecessor(BasicBlock* predecessor);
- typedef ZoneVector<BasicBlock*> Successors;
- Successors::iterator successors_begin() { return successors_.begin(); }
- Successors::iterator successors_end() { return successors_.end(); }
- Successors::const_iterator successors_begin() const {
- return successors_.begin();
- }
- Successors::const_iterator successors_end() const {
- return successors_.end();
- }
+ // Successors.
+ BasicBlockVector& successors() { return successors_; }
+ const BasicBlockVector& successors() const { return successors_; }
size_t SuccessorCount() const { return successors_.size(); }
BasicBlock* SuccessorAt(size_t index) { return successors_[index]; }
void ClearSuccessors() { successors_.clear(); }
void AddSuccessor(BasicBlock* successor);
// 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]; }
size_t NodeCount() const { return nodes_.size(); }
Node* control_input_; // Input value for control.
NodeVector nodes_; // nodes of this block in forward order.
- Successors successors_;
- Predecessors predecessors_;
+ BasicBlockVector successors_;
+ BasicBlockVector predecessors_;
Id id_;
DISALLOW_COPY_AND_ASSIGN(BasicBlock);
};
-std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c);
-std::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id);
-std::ostream& operator<<(std::ostream& os, const BasicBlock::RpoNumber& rpo);
+std::ostream& operator<<(std::ostream&, const BasicBlock::Control&);
+std::ostream& operator<<(std::ostream&, const BasicBlock::Id&);
+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
// and ordering them within basic blocks. Prior to computing a 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 internal
void Scheduler::PropagateImmediateDominators(BasicBlock* block) {
for (/*nop*/; block != NULL; block = block->rpo_next()) {
- BasicBlock::Predecessors::iterator pred = block->predecessors_begin();
- BasicBlock::Predecessors::iterator end = block->predecessors_end();
+ auto pred = block->predecessors().begin();
+ auto end = block->predecessors().end();
DCHECK(pred != end); // All blocks except start have predecessors.
BasicBlock* dominator = *pred;
// For multiple predecessors, walk up the dominator tree until a common
#include "src/v8.h"
+#include "src/compiler/node.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/schedule.h"
#include "src/compiler/zone-pool.h"
namespace internal {
namespace compiler {
+// Forward declarations.
class CFGBuilder;
class ControlEquivalence;
+class Graph;
class SpecialRPONumberer;
+
// Computes a schedule from a graph, placing nodes into basic blocks and
// ordering the basic blocks in the special RPO order.
class Scheduler {
++b) {
CHECK_EQ((*b), schedule->GetBlockById((*b)->id()));
// All predecessors and successors should be in rpo and in this schedule.
- for (BasicBlock::Predecessors::iterator j = (*b)->predecessors_begin();
- j != (*b)->predecessors_end(); ++j) {
- CHECK_GE((*j)->rpo_number(), 0);
- CHECK_EQ((*j), schedule->GetBlockById((*j)->id()));
- }
- for (BasicBlock::Successors::iterator j = (*b)->successors_begin();
- j != (*b)->successors_end(); ++j) {
- CHECK_GE((*j)->rpo_number(), 0);
- CHECK_EQ((*j), schedule->GetBlockById((*j)->id()));
+ for (BasicBlock const* predecessor : (*b)->predecessors()) {
+ CHECK_GE(predecessor->rpo_number(), 0);
+ CHECK_EQ(predecessor, schedule->GetBlockById(predecessor->id()));
+ }
+ for (BasicBlock const* successor : (*b)->successors()) {
+ CHECK_GE(successor->rpo_number(), 0);
+ CHECK_EQ(successor, schedule->GetBlockById(successor->id()));
}
}
'compiler/test-run-properties.cc',
'compiler/test-run-stackcheck.cc',
'compiler/test-run-variables.cc',
- 'compiler/test-schedule.cc',
'compiler/test-scheduler.cc',
'compiler/test-simplified-lowering.cc',
'compiler/test-typer.cc',
BasicBlockVector* blocks = R.schedule.rpo_order();
CHECK_EQ(static_cast<int>(blocks->size()), R.code->InstructionBlockCount());
- int index = 0;
- for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end();
- i++, index++) {
- BasicBlock* block = *i;
+ for (auto block : *blocks) {
CHECK_EQ(block->rpo_number(), R.BlockAt(block)->rpo_number().ToInt());
CHECK_EQ(block->id().ToInt(), R.BlockAt(block)->id().ToInt());
CHECK_EQ(NULL, block->loop_end());
+++ /dev/null
-// 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);
-}
}
-static int GetScheduledNodeCount(Schedule* schedule) {
- int node_count = 0;
- for (BasicBlockVectorIter i = schedule->rpo_order()->begin();
- i != schedule->rpo_order()->end(); ++i) {
- BasicBlock* block = *i;
- for (BasicBlock::const_iterator j = block->begin(); j != block->end();
- ++j) {
- ++node_count;
- }
- BasicBlock::Control control = block->control();
- if (control != BasicBlock::kNone) {
- ++node_count;
- }
+static int GetScheduledNodeCount(const Schedule* schedule) {
+ size_t node_count = 0;
+ for (auto block : *schedule->rpo_order()) {
+ node_count += block->NodeCount();
+ if (block->control() != BasicBlock::kNone) ++node_count;
}
- return node_count;
+ return static_cast<int>(node_count);
}
--- /dev/null
+// 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
'compiler/node-unittest.cc',
'compiler/opcodes-unittest.cc',
'compiler/register-allocator-unittest.cc',
+ 'compiler/schedule-unittest.cc',
'compiler/select-lowering-unittest.cc',
'compiler/simplified-operator-reducer-unittest.cc',
'compiler/simplified-operator-unittest.cc',