Compute reaching definitions.

Use the classical worklist algorithm to compute reaching definitions.
All nodes are initially put on the worklist.  Until the worklist is
empty, nodes are removed, their RD_in is recomputed, and if it changes
their successors are added to the worklist.

Review URL: http://codereview.chromium.org/853004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4113 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d896e4f6
...@@ -1903,13 +1903,21 @@ int ReachingDefinitions::IndexFor(Variable* var, int variable_count) { ...@@ -1903,13 +1903,21 @@ int ReachingDefinitions::IndexFor(Variable* var, int variable_count) {
void Node::InitializeReachingDefinitions(int definition_count, void Node::InitializeReachingDefinitions(int definition_count,
List<BitVector*>* variables) { List<BitVector*>* variables,
WorkList<Node>* worklist,
bool mark) {
ASSERT(!IsMarkedWith(mark));
rd_.Initialize(definition_count); rd_.Initialize(definition_count);
MarkWith(mark);
worklist->Insert(this);
} }
void BlockNode::InitializeReachingDefinitions(int definition_count, void BlockNode::InitializeReachingDefinitions(int definition_count,
List<BitVector*>* variables) { List<BitVector*>* variables,
WorkList<Node>* worklist,
bool mark) {
ASSERT(!IsMarkedWith(mark));
int instruction_count = instructions_.length(); int instruction_count = instructions_.length();
int variable_count = variables->length(); int variable_count = variables->length();
...@@ -1932,6 +1940,119 @@ void BlockNode::InitializeReachingDefinitions(int definition_count, ...@@ -1932,6 +1940,119 @@ void BlockNode::InitializeReachingDefinitions(int definition_count,
// This one is generated. // This one is generated.
rd_.gen()->Add(expr->num()); rd_.gen()->Add(expr->num());
} }
// Add all blocks except the entry node to the worklist.
if (predecessor_ != NULL) {
MarkWith(mark);
worklist->Insert(this);
}
}
void ExitNode::ComputeRDOut(BitVector* result) {
// Should not be the predecessor of any node.
UNREACHABLE();
}
void BlockNode::ComputeRDOut(BitVector* result) {
// All definitions reaching this block ...
result->CopyFrom(*rd_.rd_in());
// ... except those killed by the block ...
result->Subtract(*rd_.kill());
// ... but including those generated by the block.
result->Union(*rd_.gen());
}
void BranchNode::ComputeRDOut(BitVector* result) {
// Branch nodes don't kill or generate definitions.
result->CopyFrom(*rd_.rd_in());
}
void JoinNode::ComputeRDOut(BitVector* result) {
// Join nodes don't kill or generate definitions.
result->CopyFrom(*rd_.rd_in());
}
void ExitNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
// The exit node has no successors so we can just update in place. New
// RD_in is the union over all predecessors.
int definition_count = rd_.rd_in()->length();
rd_.rd_in()->Clear();
BitVector temp(definition_count);
for (int i = 0, len = predecessors_.length(); i < len; i++) {
// Because ComputeRDOut always overwrites temp and its value is
// always read out before calling ComputeRDOut again, we do not
// have to clear it on each iteration of the loop.
predecessors_[i]->ComputeRDOut(&temp);
rd_.rd_in()->Union(temp);
}
}
void BlockNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
// The entry block has no predecessor. Its RD_in does not change.
if (predecessor_ == NULL) return;
BitVector new_rd_in(rd_.rd_in()->length());
predecessor_->ComputeRDOut(&new_rd_in);
if (rd_.rd_in()->Equals(new_rd_in)) return;
// Update RD_in.
rd_.rd_in()->CopyFrom(new_rd_in);
// Add the successor to the worklist if not already present.
if (!successor_->IsMarkedWith(mark)) {
successor_->MarkWith(mark);
worklist->Insert(successor_);
}
}
void BranchNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
BitVector new_rd_in(rd_.rd_in()->length());
predecessor_->ComputeRDOut(&new_rd_in);
if (rd_.rd_in()->Equals(new_rd_in)) return;
// Update RD_in.
rd_.rd_in()->CopyFrom(new_rd_in);
// Add the successors to the worklist if not already present.
if (!successor0_->IsMarkedWith(mark)) {
successor0_->MarkWith(mark);
worklist->Insert(successor0_);
}
if (!successor1_->IsMarkedWith(mark)) {
successor1_->MarkWith(mark);
worklist->Insert(successor1_);
}
}
void JoinNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
int definition_count = rd_.rd_in()->length();
BitVector new_rd_in(definition_count);
// New RD_in is the union over all predecessors.
BitVector temp(definition_count);
for (int i = 0, len = predecessors_.length(); i < len; i++) {
predecessors_[i]->ComputeRDOut(&temp);
new_rd_in.Union(temp);
}
if (rd_.rd_in()->Equals(new_rd_in)) return;
// Update RD_in.
rd_.rd_in()->CopyFrom(new_rd_in);
// Add the successor to the worklist if not already present.
if (!successor_->IsMarkedWith(mark)) {
successor_->MarkWith(mark);
worklist->Insert(successor_);
}
} }
...@@ -1940,7 +2061,7 @@ void ReachingDefinitions::Compute() { ...@@ -1940,7 +2061,7 @@ void ReachingDefinitions::Compute() {
int variable_count = variables_.length(); int variable_count = variables_.length();
int definition_count = definitions_->length(); int definition_count = definitions_->length();
int block_count = postorder_->length(); int node_count = postorder_->length();
// Step 1: For each variable, identify the set of all its definitions in // Step 1: For each variable, identify the set of all its definitions in
// the body. // the body.
...@@ -1972,10 +2093,25 @@ void ReachingDefinitions::Compute() { ...@@ -1972,10 +2093,25 @@ void ReachingDefinitions::Compute() {
} }
} }
// Step 2: Compute KILL and GEN for each block node, initialize RD. // Step 2: Compute KILL and GEN for each block node, initialize RD_in for
for (int i = block_count - 1; i >= 0; i--) { // all nodes, and mark and add all nodes to the worklist in reverse
// postorder. All nodes should currently have the same mark.
bool mark = postorder_->at(0)->IsMarkedWith(false); // Negation of current.
WorkList<Node> worklist(node_count);
for (int i = node_count - 1; i >= 0; i--) {
postorder_->at(i)->InitializeReachingDefinitions(definition_count, postorder_->at(i)->InitializeReachingDefinitions(definition_count,
&variables_); &variables_,
&worklist,
mark);
}
// Step 3: Until the worklist is empty, remove an item compute and update
// its rd_in based on its predecessor's rd_out. If rd_in has changed, add
// all necessary successors to the worklist.
while (!worklist.is_empty()) {
Node* node = worklist.Remove();
node->MarkWith(!mark);
node->UpdateRDIn(&worklist, mark);
} }
} }
......
...@@ -120,6 +120,13 @@ class BitVector: public ZoneObject { ...@@ -120,6 +120,13 @@ class BitVector: public ZoneObject {
return true; return true;
} }
bool Equals(const BitVector& other) {
for (int i = 0; i < data_length_; i++) {
if (data_[i] != other.data_[i]) return false;
}
return true;
}
int length() const { return length_; } int length() const { return length_; }
private: private:
...@@ -129,7 +136,51 @@ class BitVector: public ZoneObject { ...@@ -129,7 +136,51 @@ class BitVector: public ZoneObject {
}; };
class ReachingDefinitionsData BASE_EMBEDDED { // Simple fixed-capacity list-based worklist (managed as a queue) of
// pointers to T.
template<typename T>
class WorkList BASE_EMBEDDED {
public:
// The worklist cannot grow bigger than size. We keep one item empty to
// distinguish between empty and full.
WorkList(int size)
: capacity_(size + 1), head_(0), tail_(0), queue_(capacity_) {
for (int i = 0; i < capacity_; i++) queue_.Add(NULL);
}
bool is_empty() { return head_ == tail_; }
bool is_full() {
// The worklist is full if head is at 0 and tail is at capacity - 1:
// head == 0 && tail == capacity-1 ==> tail - head == capacity - 1
// or if tail is immediately to the left of head:
// tail+1 == head ==> tail - head == -1
int diff = tail_ - head_;
return (diff == -1 || diff == capacity_ - 1);
}
void Insert(T* item) {
ASSERT(!is_full());
queue_[tail_++] = item;
if (tail_ == capacity_) tail_ = 0;
}
T* Remove() {
ASSERT(!is_empty());
T* item = queue_[head_++];
if (head_ == capacity_) head_ = 0;
return item;
}
private:
int capacity_; // Including one empty slot.
int head_; // Where the first item is.
int tail_; // Where the next inserted item will go.
List<T*> queue_;
};
struct ReachingDefinitionsData BASE_EMBEDDED {
public: public:
ReachingDefinitionsData() : rd_in_(NULL), kill_(NULL), gen_(NULL) {} ReachingDefinitionsData() : rd_in_(NULL), kill_(NULL), gen_(NULL) {}
...@@ -179,7 +230,11 @@ class Node: public ZoneObject { ...@@ -179,7 +230,11 @@ class Node: public ZoneObject {
// Functions used by data-flow analyses. // Functions used by data-flow analyses.
virtual void InitializeReachingDefinitions(int definition_count, virtual void InitializeReachingDefinitions(int definition_count,
List<BitVector*>* variables); List<BitVector*>* variables,
WorkList<Node>* worklist,
bool mark);
virtual void ComputeRDOut(BitVector* result) = 0;
virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark) = 0;
#ifdef DEBUG #ifdef DEBUG
void AssignNodeNumber(); void AssignNodeNumber();
...@@ -216,6 +271,9 @@ class ExitNode: public Node { ...@@ -216,6 +271,9 @@ class ExitNode: public Node {
ZoneList<Node*>* preorder, ZoneList<Node*>* preorder,
ZoneList<Node*>* postorder); ZoneList<Node*>* postorder);
void ComputeRDOut(BitVector* result);
void UpdateRDIn(WorkList<Node>* worklist, bool mark);
#ifdef DEBUG #ifdef DEBUG
void PrintText(); void PrintText();
#endif #endif
...@@ -261,7 +319,11 @@ class BlockNode: public Node { ...@@ -261,7 +319,11 @@ class BlockNode: public Node {
ZoneList<Node*>* postorder); ZoneList<Node*>* postorder);
void InitializeReachingDefinitions(int definition_count, void InitializeReachingDefinitions(int definition_count,
List<BitVector*>* variables); List<BitVector*>* variables,
WorkList<Node>* worklist,
bool mark);
void ComputeRDOut(BitVector* result);
void UpdateRDIn(WorkList<Node>* worklist, bool mark);
#ifdef DEBUG #ifdef DEBUG
void PrintText(); void PrintText();
...@@ -301,6 +363,9 @@ class BranchNode: public Node { ...@@ -301,6 +363,9 @@ class BranchNode: public Node {
ZoneList<Node*>* preorder, ZoneList<Node*>* preorder,
ZoneList<Node*>* postorder); ZoneList<Node*>* postorder);
void ComputeRDOut(BitVector* result);
void UpdateRDIn(WorkList<Node>* worklist, bool mark);
#ifdef DEBUG #ifdef DEBUG
void PrintText(); void PrintText();
#endif #endif
...@@ -340,6 +405,9 @@ class JoinNode: public Node { ...@@ -340,6 +405,9 @@ class JoinNode: public Node {
ZoneList<Node*>* preorder, ZoneList<Node*>* preorder,
ZoneList<Node*>* postorder); ZoneList<Node*>* postorder);
void ComputeRDOut(BitVector* result);
void UpdateRDIn(WorkList<Node>* worklist, bool mark);
#ifdef DEBUG #ifdef DEBUG
void PrintText(); void PrintText();
#endif #endif
......
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