Files
sdk/runtime/vm/intermediate_language.cc
T
kmillikin@google.com be9bc9c068 Compute immediate dominators using SEMI-NCA.
This is a version of the Lengauer-Tarjan algorithm that is both simpler and
faster.

R=srdjan@google.com
BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com//9729015

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@5737 260f80e4-7a28-3924-810f-c04153c831b5
2012-03-21 23:45:20 +00:00

200 lines
6.0 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/intermediate_language.h"
#include "vm/object.h"
#include "vm/os.h"
#include "vm/scopes.h"
namespace dart {
// ==== Support for visiting flow graphs.
#define DEFINE_ACCEPT(ShortName, ClassName) \
void ClassName::Accept(FlowGraphVisitor* visitor) { \
visitor->Visit##ShortName(this); \
}
FOR_EACH_COMPUTATION(DEFINE_ACCEPT)
#undef DEFINE_ACCEPT
Instruction* JoinEntryInstr::Accept(FlowGraphVisitor* visitor) {
visitor->VisitJoinEntry(this);
return successor_;
}
Instruction* TargetEntryInstr::Accept(FlowGraphVisitor* visitor) {
visitor->VisitTargetEntry(this);
return successor_;
}
Instruction* PickTempInstr::Accept(FlowGraphVisitor* visitor) {
visitor->VisitPickTemp(this);
return successor_;
}
Instruction* TuckTempInstr::Accept(FlowGraphVisitor* visitor) {
visitor->VisitTuckTemp(this);
return successor_;
}
Instruction* DoInstr::Accept(FlowGraphVisitor* visitor) {
visitor->VisitDo(this);
return successor_;
}
Instruction* BindInstr::Accept(FlowGraphVisitor* visitor) {
visitor->VisitBind(this);
return successor_;
}
Instruction* ReturnInstr::Accept(FlowGraphVisitor* visitor) {
visitor->VisitReturn(this);
return NULL;
}
Instruction* ThrowInstr::Accept(FlowGraphVisitor* visitor) {
visitor->VisitThrow(this);
return NULL;
}
Instruction* ReThrowInstr::Accept(FlowGraphVisitor* visitor) {
visitor->VisitReThrow(this);
return NULL;
}
Instruction* BranchInstr::Accept(FlowGraphVisitor* visitor) {
visitor->VisitBranch(this);
return NULL;
}
// Default implementation of visiting basic blocks. Can be overridden.
void FlowGraphVisitor::VisitBlocks() {
for (intptr_t i = 0; i < block_order_.length(); ++i) {
Instruction* current = block_order_[i]->Accept(this);
while ((current != NULL) && !current->IsBlockEntry()) {
current = current->Accept(this);
}
}
}
// ==== Postorder graph traversal.
void JoinEntryInstr::DiscoverBlocks(
BlockEntryInstr* current_block,
GrowableArray<BlockEntryInstr*>* preorder,
GrowableArray<BlockEntryInstr*>* postorder,
GrowableArray<intptr_t>* parent) {
// The global graph entry is a TargetEntryInstr, so we can assume
// current_block is non-null and preorder array is non-empty.
ASSERT(current_block != NULL);
ASSERT(!preorder->is_empty());
// 1. Record control-flow-graph basic-block predecessors.
predecessors_.Add(current_block);
// 2. If the block has already been reached by the traversal, we are done.
if (preorder_number() >= 0) return;
// 3. The last entry in the preorder array is the spanning-tree parent.
intptr_t parent_number = preorder->length() - 1;
parent->Add(parent_number);
// 4. Assign preorder number and add the block entry to the list.
set_preorder_number(parent_number + 1);
preorder->Add(this);
// The preorder and parent arrays are both indexed by preorder block
// number, so they should stay in lockstep.
ASSERT(preorder->length() == parent->length());
// 5. Iterate straight-line successors until a branch instruction or
// another basic block entry instruction, and visit that instruction.
ASSERT(successor_ != NULL);
Instruction* next = successor_;
while ((next != NULL) && !next->IsBlockEntry() && !next->IsBranch()) {
set_last_instruction(next);
next = next->StraightLineSuccessor();
}
if (next != NULL) {
next->DiscoverBlocks(this, preorder, postorder, parent);
}
// 6. Assign postorder number and add the block entry to the list.
set_postorder_number(postorder->length());
postorder->Add(this);
}
void TargetEntryInstr::DiscoverBlocks(
BlockEntryInstr* current_block,
GrowableArray<BlockEntryInstr*>* preorder,
GrowableArray<BlockEntryInstr*>* postorder,
GrowableArray<intptr_t>* parent) {
// 1. Record control-flow-graph basic-block predecessors.
ASSERT(predecessor_ == NULL);
predecessor_ = current_block; // Might be NULL (for the graph entry).
// 2. There is a single predecessor, so we should only reach this block once.
ASSERT(preorder_number() == -1);
// 3. The last entry in the preorder array is the spanning-tree parent.
// The global graph entry has no parent, indicated by -1.
intptr_t parent_number = preorder->length() - 1;
parent->Add(parent_number);
// 4. Assign preorder number and add the block entry to the list.
set_preorder_number(parent_number + 1);
preorder->Add(this);
// The preorder and parent arrays are indexed by preorder block number, so
// they should stay in lockstep.
ASSERT(preorder->length() == parent->length());
// 5. Iterate straight-line successors until a branch instruction or
// another basic block entry instruction, and visit that instruction.
ASSERT(successor_ != NULL);
Instruction* next = successor_;
while ((next != NULL) && !next->IsBlockEntry() && !next->IsBranch()) {
set_last_instruction(next);
next = next->StraightLineSuccessor();
}
if (next != NULL) {
next->DiscoverBlocks(this, preorder, postorder, parent);
}
// 6. Assign postorder number and add the block entry to the list.
set_postorder_number(postorder->length());
postorder->Add(this);
}
void BranchInstr::DiscoverBlocks(
BlockEntryInstr* current_block,
GrowableArray<BlockEntryInstr*>* preorder,
GrowableArray<BlockEntryInstr*>* postorder,
GrowableArray<intptr_t>* parent) {
current_block->set_last_instruction(this);
// Visit the false successor before the true successor so they appear in
// true/false order in reverse postorder used as the block ordering in the
// nonoptimizing compiler.
ASSERT(true_successor_ != NULL);
ASSERT(false_successor_ != NULL);
false_successor_->DiscoverBlocks(current_block, preorder, postorder, parent);
true_successor_->DiscoverBlocks(current_block, preorder, postorder, parent);
}
} // namespace dart