blob: 42e656e9d5315abebed1cd6f6cdb8573a1fa3544 [file] [log] [blame]
// Copyright (c) 2018, 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.
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/backend/loops.h"
#include "vm/bit_vector.h"
#include "vm/compiler/backend/il.h"
namespace dart {
LoopInfo::LoopInfo(intptr_t id, BlockEntryInstr* header, BitVector* blocks)
: id_(id),
header_(header),
blocks_(blocks),
back_edges_(),
outer_(nullptr),
inner_(nullptr),
next_(nullptr) {}
void LoopInfo::AddBlocks(BitVector* blocks) {
blocks_->AddAll(blocks);
}
void LoopInfo::AddBackEdge(BlockEntryInstr* block) {
back_edges_.Add(block);
}
bool LoopInfo::IsBackEdge(BlockEntryInstr* block) const {
for (intptr_t i = 0, n = back_edges_.length(); i < n; i++) {
if (back_edges_[i] == block) {
return true;
}
}
return false;
}
bool LoopInfo::IsIn(LoopInfo* other) const {
if (other != nullptr) {
return other->blocks_->Contains(header_->preorder_number());
}
return false;
}
intptr_t LoopInfo::NestingDepth() const {
intptr_t nesting_depth = 1;
for (LoopInfo* o = outer_; o != nullptr; o = o->outer()) {
nesting_depth++;
}
return nesting_depth;
}
const char* LoopInfo::ToCString() const {
char buffer[1024];
BufferFormatter f(buffer, sizeof(buffer));
f.Print("%*c", static_cast<int>(2 * NestingDepth()), ' ');
f.Print("loop%" Pd " B%" Pd " ", id_, header_->block_id());
intptr_t num_blocks = 0;
for (BitVector::Iterator it(blocks_); !it.Done(); it.Advance()) {
num_blocks++;
}
f.Print("#blocks=%" Pd, num_blocks);
if (outer_) f.Print(" outer=%" Pd, outer_->id_);
if (inner_) f.Print(" inner=%" Pd, inner_->id_);
if (next_) f.Print(" next=%" Pd, next_->id_);
f.Print(" [");
for (intptr_t i = 0, n = back_edges_.length(); i < n; i++) {
f.Print(" B%" Pd, back_edges_[i]->block_id());
}
f.Print(" ]");
return Thread::Current()->zone()->MakeCopyOfString(buffer);
}
LoopHierarchy::LoopHierarchy(ZoneGrowableArray<BlockEntryInstr*>* headers,
const GrowableArray<BlockEntryInstr*>& preorder)
: headers_(headers), preorder_(preorder), top_(nullptr) {
Build();
}
void LoopHierarchy::Build() {
// Link every entry block to the closest enveloping loop.
for (intptr_t i = 0, n = headers_->length(); i < n; ++i) {
LoopInfo* loop = (*headers_)[i]->loop_info();
for (BitVector::Iterator it(loop->blocks()); !it.Done(); it.Advance()) {
BlockEntryInstr* block = preorder_[it.Current()];
if (block->loop_info() == nullptr) {
block->set_loop_info(loop);
} else {
ASSERT(block->loop_info()->IsIn(loop));
}
}
}
// Build hierarchy from headers.
for (intptr_t i = 0, n = headers_->length(); i < n; ++i) {
BlockEntryInstr* header = (*headers_)[i];
LoopInfo* loop = header->loop_info();
LoopInfo* dom_loop = header->dominator()->loop_info();
ASSERT(loop->outer_ == nullptr);
ASSERT(loop->next_ == nullptr);
if (loop->IsIn(dom_loop)) {
loop->outer_ = dom_loop;
loop->next_ = dom_loop->inner_;
dom_loop->inner_ = loop;
} else {
loop->next_ = top_;
top_ = loop;
}
}
// If tracing is requested, print the loop hierarchy.
if (FLAG_trace_optimization) {
Print(top());
}
}
void LoopHierarchy::Print(LoopInfo* loop) {
for (; loop != nullptr; loop = loop->next_) {
THR_Print("%s {", loop->ToCString());
for (BitVector::Iterator it(loop->blocks()); !it.Done(); it.Advance()) {
THR_Print(" B%" Pd, preorder_[it.Current()]->block_id());
}
THR_Print(" }\n");
Print(loop->inner_);
}
}
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)