summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/ssa_liveness_analysis.cc
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2014-11-24 17:47:10 +0000
committerNicolas Geoffray <ngeoffray@google.com>2014-11-24 18:05:48 +0000
commita8eed3acbc39c71ec22dc2943e71eaa07c6507dd (patch)
tree73f00c656e118c118c0b7dd8985df06624ca4666 /compiler/optimizing/ssa_liveness_analysis.cc
parent4d3ed1a6f34bd31ed30faaca0433cf2a4b19bb7b (diff)
downloadart-a8eed3acbc39c71ec22dc2943e71eaa07c6507dd.zip
art-a8eed3acbc39c71ec22dc2943e71eaa07c6507dd.tar.gz
art-a8eed3acbc39c71ec22dc2943e71eaa07c6507dd.tar.bz2
Revert "Revert "Fix the computation of linear ordering.""
PS2 fixes the obvious typos/wrong refactoring. This reverts commit e50fa5887b1342b845826197d81950e26753fc9c. Change-Id: I22f81d63a12cf01aafd61535abc2399d936d49c2
Diffstat (limited to 'compiler/optimizing/ssa_liveness_analysis.cc')
-rw-r--r--compiler/optimizing/ssa_liveness_analysis.cc93
1 files changed, 53 insertions, 40 deletions
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 0085b27..660a5c5 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -28,11 +28,6 @@ void SsaLivenessAnalysis::Analyze() {
ComputeLiveness();
}
-static bool IsLoopExit(HLoopInformation* current, HLoopInformation* to) {
- // `to` is either not part of a loop, or `current` is an inner loop of `to`.
- return to == nullptr || (current != to && current->IsIn(*to));
-}
-
static bool IsLoop(HLoopInformation* info) {
return info != nullptr;
}
@@ -48,46 +43,64 @@ static bool IsInnerLoop(HLoopInformation* outer, HLoopInformation* inner) {
&& inner->IsIn(*outer);
}
-static void VisitBlockForLinearization(HBasicBlock* block,
- GrowableArray<HBasicBlock*>* order,
- ArenaBitVector* visited) {
- if (visited->IsBitSet(block->GetBlockId())) {
- return;
- }
- visited->SetBit(block->GetBlockId());
- size_t number_of_successors = block->GetSuccessors().Size();
- if (number_of_successors == 0) {
- // Nothing to do.
- } else if (number_of_successors == 1) {
- VisitBlockForLinearization(block->GetSuccessors().Get(0), order, visited);
- } else {
- DCHECK_EQ(number_of_successors, 2u);
- HBasicBlock* first_successor = block->GetSuccessors().Get(0);
- HBasicBlock* second_successor = block->GetSuccessors().Get(1);
- HLoopInformation* my_loop = block->GetLoopInformation();
- HLoopInformation* first_loop = first_successor->GetLoopInformation();
- HLoopInformation* second_loop = second_successor->GetLoopInformation();
-
- if (!IsLoop(my_loop)) {
- // Nothing to do. Current order is fine.
- } else if (IsLoopExit(my_loop, second_loop) && InSameLoop(my_loop, first_loop)) {
- // Visit the loop exit first in post order.
- std::swap(first_successor, second_successor);
- } else if (IsInnerLoop(my_loop, first_loop) && !IsInnerLoop(my_loop, second_loop)) {
- // Visit the inner loop last in post order.
- std::swap(first_successor, second_successor);
+static void AddToListForLinearization(GrowableArray<HBasicBlock*>* worklist, HBasicBlock* block) {
+ size_t insert_at = worklist->Size();
+ HLoopInformation* block_loop = block->GetLoopInformation();
+ for (; insert_at > 0; --insert_at) {
+ HBasicBlock* current = worklist->Get(insert_at - 1);
+ HLoopInformation* current_loop = current->GetLoopInformation();
+ if (InSameLoop(block_loop, current_loop)
+ || !IsLoop(current_loop)
+ || IsInnerLoop(current_loop, block_loop)) {
+ // The block can be processed immediately.
+ break;
}
- VisitBlockForLinearization(first_successor, order, visited);
- VisitBlockForLinearization(second_successor, order, visited);
}
- order->Add(block);
+ worklist->InsertAt(insert_at, block);
}
void SsaLivenessAnalysis::LinearizeGraph() {
- // For simplicity of the implementation, we create post linear order. The order for
- // computing live ranges is the reverse of that order.
- ArenaBitVector visited(graph_.GetArena(), graph_.GetBlocks().Size(), false);
- VisitBlockForLinearization(graph_.GetEntryBlock(), &linear_post_order_, &visited);
+ // Create a reverse post ordering with the following properties:
+ // - Blocks in a loop are consecutive,
+ // - Back-edge is the last block before loop exits.
+
+ // (1): Record the number of forward predecessors for each block. This is to
+ // ensure the resulting order is reverse post order. We could use the
+ // current reverse post order in the graph, but it would require making
+ // order queries to a GrowableArray, which is not the best data structure
+ // for it.
+ GrowableArray<uint32_t> forward_predecessors(graph_.GetArena(), graph_.GetBlocks().Size());
+ forward_predecessors.SetSize(graph_.GetBlocks().Size());
+ for (size_t i = 0, e = graph_.GetBlocks().Size(); i < e; ++i) {
+ HBasicBlock* block = graph_.GetBlocks().Get(i);
+ size_t number_of_forward_predecessors = block->GetPredecessors().Size();
+ if (block->IsLoopHeader()) {
+ // We rely on having simplified the CFG.
+ DCHECK_EQ(1u, block->GetLoopInformation()->NumberOfBackEdges());
+ number_of_forward_predecessors--;
+ }
+ forward_predecessors.Put(block->GetBlockId(), number_of_forward_predecessors);
+ }
+
+ // (2): Following a worklist approach, first start with the entry block, and
+ // iterate over the successors. When all non-back edge predecessors of a
+ // successor block are visited, the successor block is added in the worklist
+ // following an order that satisfies the requirements to build our linear graph.
+ GrowableArray<HBasicBlock*> worklist(graph_.GetArena(), 1);
+ worklist.Add(graph_.GetEntryBlock());
+ do {
+ HBasicBlock* current = worklist.Pop();
+ linear_order_.Add(current);
+ for (size_t i = 0, e = current->GetSuccessors().Size(); i < e; ++i) {
+ HBasicBlock* successor = current->GetSuccessors().Get(i);
+ int block_id = successor->GetBlockId();
+ size_t number_of_remaining_predecessors = forward_predecessors.Get(block_id);
+ if (number_of_remaining_predecessors == 1) {
+ AddToListForLinearization(&worklist, successor);
+ }
+ forward_predecessors.Put(block_id, number_of_remaining_predecessors - 1);
+ }
+ } while (!worklist.IsEmpty());
}
void SsaLivenessAnalysis::NumberInstructions() {