| Index: src/data-flow.cc
|
| diff --git a/src/data-flow.cc b/src/data-flow.cc
|
| index 434991c8dd34ece0251677f5bee159d32a5a74f2..7cdc46f3ca143e1249b08b1341905efee6d54b15 100644
|
| --- a/src/data-flow.cc
|
| +++ b/src/data-flow.cc
|
| @@ -1902,13 +1902,21 @@ int ReachingDefinitions::IndexFor(Variable* var, int variable_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);
|
| + MarkWith(mark);
|
| + worklist->Insert(this);
|
| }
|
|
|
|
|
| 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 variable_count = variables->length();
|
|
|
| @@ -1931,6 +1939,114 @@ void BlockNode::InitializeReachingDefinitions(int definition_count,
|
| // This one is generated.
|
| rd_.gen()->Add(expr->num());
|
| }
|
| +
|
| + 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();
|
| + for (int i = 0, len = predecessors_.length(); i < len; i++) {
|
| + BitVector temp(definition_count);
|
| + 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.
|
| + for (int i = 0, len = predecessors_.length(); i < len; i++) {
|
| + BitVector temp(definition_count);
|
| + 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_);
|
| + }
|
| }
|
|
|
|
|
| @@ -1939,7 +2055,7 @@ void ReachingDefinitions::Compute() {
|
|
|
| int variable_count = variables_.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
|
| // the body.
|
| @@ -1971,10 +2087,25 @@ void ReachingDefinitions::Compute() {
|
| }
|
| }
|
|
|
| - // Step 2: Compute KILL and GEN for each block node, initialize RD.
|
| - for (int i = block_count - 1; i >= 0; i--) {
|
| + // Step 2: Compute KILL and GEN for each block node, initialize RD_in for
|
| + // 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,
|
| - &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);
|
| }
|
| }
|
|
|
|
|