Make special RPO computation iterative during scheduling.

This contains the following changes squashed together:
- Switch BasicBlock::loop_end to be a basic block instead of an RPO.
- Switch ScheduleLate to use dominator depth instead of RPO.
- Switch ScheduleEarly to use dominator depth instead of RPO.
- Push out absolute RPO ordering everywhere else in the scheduler.
- Keep linked list of blocks in RPO order while scheduling.
- Switch from RPO number to depth for dominator calculation.

R=jarin@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25138}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25138 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 33dde8d9
......@@ -346,7 +346,7 @@ static BasicBlock::RpoNumber GetRpo(BasicBlock* block) {
static BasicBlock::RpoNumber GetLoopEndRpo(const BasicBlock* block) {
if (!block->IsLoopHeader()) return BasicBlock::RpoNumber::Invalid();
return BasicBlock::RpoNumber::FromInt(block->loop_end());
return block->loop_end()->GetRpoNumber();
}
......
......@@ -16,10 +16,11 @@ BasicBlock::BasicBlock(Zone* zone, Id id)
: ao_number_(-1),
rpo_number_(-1),
deferred_(false),
dominator_depth_(-1),
dominator_(NULL),
loop_header_(NULL),
loop_end_(NULL),
loop_depth_(0),
loop_end_(-1),
control_(kNone),
control_input_(NULL),
nodes_(zone),
......@@ -32,8 +33,9 @@ bool BasicBlock::LoopContains(BasicBlock* block) const {
// RPO numbers must be initialized.
DCHECK(rpo_number_ >= 0);
DCHECK(block->rpo_number_ >= 0);
if (loop_end_ < 0) return false; // This is not a loop.
return block->rpo_number_ >= rpo_number_ && block->rpo_number_ < loop_end_;
if (loop_end_ == NULL) return false; // This is not a loop.
return block->rpo_number_ >= rpo_number_ &&
block->rpo_number_ < loop_end_->rpo_number_;
}
......@@ -60,6 +62,11 @@ void BasicBlock::set_control_input(Node* control_input) {
}
void BasicBlock::set_dominator_depth(int32_t dominator_depth) {
dominator_depth_ = dominator_depth;
}
void BasicBlock::set_dominator(BasicBlock* dominator) {
dominator_ = dominator;
}
......@@ -75,7 +82,7 @@ void BasicBlock::set_rpo_number(int32_t rpo_number) {
}
void BasicBlock::set_loop_end(int32_t loop_end) { loop_end_ = loop_end; }
void BasicBlock::set_loop_end(BasicBlock* loop_end) { loop_end_ = loop_end; }
void BasicBlock::set_loop_header(BasicBlock* loop_header) {
......
......@@ -145,18 +145,21 @@ class BasicBlock FINAL : public ZoneObject {
bool deferred() const { return deferred_; }
void set_deferred(bool deferred) { deferred_ = deferred; }
int32_t dominator_depth() const { return dominator_depth_; }
void set_dominator_depth(int32_t dominator_depth);
BasicBlock* dominator() const { return dominator_; }
void set_dominator(BasicBlock* dominator);
BasicBlock* loop_header() const { return loop_header_; }
void set_loop_header(BasicBlock* loop_header);
BasicBlock* loop_end() const { return loop_end_; }
void set_loop_end(BasicBlock* loop_end);
int32_t loop_depth() const { return loop_depth_; }
void set_loop_depth(int32_t loop_depth);
int32_t loop_end() const { return loop_end_; }
void set_loop_end(int32_t loop_end);
RpoNumber GetAoNumber() const { return RpoNumber::FromInt(ao_number_); }
int32_t ao_number() const { return ao_number_; }
void set_ao_number(int32_t ao_number) { ao_number_ = ao_number; }
......@@ -166,19 +169,20 @@ class BasicBlock FINAL : public ZoneObject {
void set_rpo_number(int32_t rpo_number);
// Loop membership helpers.
inline bool IsLoopHeader() const { return loop_end_ >= 0; }
inline bool IsLoopHeader() const { return loop_end_ != NULL; }
bool LoopContains(BasicBlock* block) const;
private:
int32_t ao_number_; // assembly order number of the block.
int32_t rpo_number_; // special RPO number of the block.
bool deferred_; // true if the block contains deferred code.
int32_t dominator_depth_; // Depth within the dominator tree.
BasicBlock* dominator_; // Immediate dominator of the block.
BasicBlock* loop_header_; // Pointer to dominating loop header basic block,
// NULL if none. For loop headers, this points to
// enclosing loop header.
BasicBlock* loop_end_; // end of the loop, if this block is a loop header.
int32_t loop_depth_; // loop nesting, 0 is top-level
int32_t loop_end_; // end of the loop, if this block is a loop header.
Control control_; // Control at the end of the block.
Node* control_input_; // Input value for control.
......
This diff is collapsed.
......@@ -16,6 +16,8 @@ namespace v8 {
namespace internal {
namespace compiler {
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 {
......@@ -60,6 +62,7 @@ class Scheduler {
NodeVector schedule_root_nodes_; // Fixed root nodes seed the worklist.
ZoneQueue<Node*> schedule_queue_; // Worklist of schedulable nodes.
ZoneVector<SchedulerData> node_data_; // Per-node data for all nodes.
SpecialRPONumberer* special_rpo_; // Special RPO numbering of blocks.
Scheduler(Zone* zone, Graph* graph, Schedule* schedule);
......@@ -73,7 +76,6 @@ class Scheduler {
void IncrementUnscheduledUseCount(Node* node, int index, Node* from);
void DecrementUnscheduledUseCount(Node* node, int index, Node* from);
inline int GetRPONumber(BasicBlock* block);
BasicBlock* GetCommonDominator(BasicBlock* b1, BasicBlock* b2);
// Phase 1: Build control-flow graph.
......@@ -97,6 +99,9 @@ class Scheduler {
friend class ScheduleLateNodeVisitor;
void ScheduleLate();
// Phase 6: Seal the final schedule.
void SealFinalSchedule();
void FuseFloatingControl(BasicBlock* block, Node* node);
void MovePlannedNodes(BasicBlock* from, BasicBlock* to);
};
......
......@@ -139,7 +139,7 @@ TEST(InstructionBasic) {
BasicBlock* block = *i;
CHECK_EQ(block->rpo_number(), R.BlockAt(block)->rpo_number().ToInt());
CHECK_EQ(block->id().ToInt(), R.BlockAt(block)->id().ToInt());
CHECK_EQ(-1, block->loop_end());
CHECK_EQ(NULL, block->loop_end());
}
}
......
......@@ -30,7 +30,7 @@ static void CheckRPONumbers(BasicBlockVector* order, size_t expected,
for (int i = 0; i < static_cast<int>(order->size()); i++) {
CHECK(order->at(i)->rpo_number() == i);
if (!loops_allowed) {
CHECK_LT(order->at(i)->loop_end(), 0);
CHECK_EQ(NULL, order->at(i)->loop_end());
CHECK_EQ(NULL, order->at(i)->loop_header());
}
}
......@@ -40,19 +40,21 @@ static void CheckRPONumbers(BasicBlockVector* order, size_t expected,
static void CheckLoop(BasicBlockVector* order, BasicBlock** blocks,
int body_size) {
BasicBlock* header = blocks[0];
CHECK_GT(header->loop_end(), 0);
CHECK_EQ(body_size, (header->loop_end() - header->rpo_number()));
BasicBlock* end = header->loop_end();
CHECK_NE(NULL, end);
CHECK_GT(end->rpo_number(), 0);
CHECK_EQ(body_size, end->rpo_number() - header->rpo_number());
for (int i = 0; i < body_size; i++) {
int num = blocks[i]->rpo_number();
CHECK(num >= header->rpo_number() && num < header->loop_end());
CHECK_GE(blocks[i]->rpo_number(), header->rpo_number());
CHECK_LT(blocks[i]->rpo_number(), end->rpo_number());
CHECK(header->LoopContains(blocks[i]));
CHECK(header->IsLoopHeader() || blocks[i]->loop_header() == header);
}
if (header->rpo_number() > 0) {
CHECK_NE(order->at(header->rpo_number() - 1)->loop_header(), header);
}
if (header->loop_end() < static_cast<int>(order->size())) {
CHECK_NE(order->at(header->loop_end())->loop_header(), header);
if (end->rpo_number() < static_cast<int>(order->size())) {
CHECK_NE(order->at(end->rpo_number())->loop_header(), header);
}
}
......
......@@ -97,7 +97,7 @@ class RegisterAllocatorTest : public TestWithZone {
if (loop_header.IsValid()) {
basic_block->set_loop_depth(1);
basic_block->set_loop_header(basic_blocks_[loop_header.ToSize()]);
basic_block->set_loop_end(loop_end.ToInt());
basic_block->set_loop_end(basic_blocks_[loop_end.ToSize()]);
}
InstructionBlock* instruction_block =
new (zone()) InstructionBlock(zone(), basic_block);
......
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