[regalloc] Add debugging helper to print ranges
Adds support to render the live ranges as ascii diagram. This is similar in nature to what the c1visualizer would produce. Also, print the visualization when tracing the register allocator. Change-Id: Ib6a43f67ba356e9a80cacaddfdbd6d589c685483 Reviewed-on: https://chromium-review.googlesource.com/c/1346114 Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Commit-Queue: Stephan Herhut <herhut@chromium.org> Cr-Commit-Position: refs/heads/master@{#57687}
This commit is contained in:
parent
49c7b308d9
commit
1a36ac0191
@ -4,6 +4,8 @@
|
||||
|
||||
#include "src/compiler/backend/register-allocator.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#include "src/assembler-inl.h"
|
||||
#include "src/base/adapters.h"
|
||||
#include "src/compiler/linkage.h"
|
||||
@ -1151,6 +1153,78 @@ std::ostream& operator<<(std::ostream& os,
|
||||
return os;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void PrintBlockRow(std::ostream& os, const InstructionBlocks& blocks) {
|
||||
os << " ";
|
||||
for (auto block : blocks) {
|
||||
LifetimePosition start_pos = LifetimePosition::GapFromInstructionIndex(
|
||||
block->first_instruction_index());
|
||||
LifetimePosition end_pos = LifetimePosition::GapFromInstructionIndex(
|
||||
block->last_instruction_index())
|
||||
.NextFullStart();
|
||||
int length = end_pos.value() - start_pos.value();
|
||||
constexpr int kMaxPrefixLength = 32;
|
||||
char buffer[kMaxPrefixLength];
|
||||
int rpo_number = block->rpo_number().ToInt();
|
||||
const char* deferred_marker = block->IsDeferred() ? "(deferred)" : "";
|
||||
int max_prefix_length = std::min(length, kMaxPrefixLength);
|
||||
int prefix = snprintf(buffer, max_prefix_length, "[-B%d-%s", rpo_number,
|
||||
deferred_marker);
|
||||
os << buffer;
|
||||
int remaining = length - std::min(prefix, max_prefix_length) - 1;
|
||||
for (int i = 0; i < remaining; ++i) os << '-';
|
||||
os << ']';
|
||||
}
|
||||
os << '\n';
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void LinearScanAllocator::PrintRangeOverview(std::ostream& os) {
|
||||
int rowcount = 0;
|
||||
for (auto toplevel : data()->live_ranges()) {
|
||||
if (!CanProcessRange(toplevel)) continue;
|
||||
if (rowcount++ % 10 == 0) PrintBlockRow(os, code()->instruction_blocks());
|
||||
int position = 0;
|
||||
os << std::setw(3) << toplevel->vreg()
|
||||
<< (toplevel->IsSplinter() ? "s:" : ": ");
|
||||
for (LiveRange* range = toplevel; range != nullptr; range = range->next()) {
|
||||
for (UseInterval* interval = range->first_interval(); interval != nullptr;
|
||||
interval = interval->next()) {
|
||||
LifetimePosition start = interval->start();
|
||||
LifetimePosition end = interval->end();
|
||||
CHECK_GE(start.value(), position);
|
||||
for (; start.value() > position; position++) {
|
||||
os << ' ';
|
||||
}
|
||||
int length = end.value() - start.value();
|
||||
constexpr int kMaxPrefixLength = 32;
|
||||
char buffer[kMaxPrefixLength];
|
||||
int max_prefix_length = std::min(length + 1, kMaxPrefixLength);
|
||||
int prefix;
|
||||
if (range->spilled()) {
|
||||
prefix = snprintf(buffer, max_prefix_length, "|ss");
|
||||
} else {
|
||||
const char* reg_name;
|
||||
if (range->assigned_register() == kUnassignedRegister) {
|
||||
reg_name = "???";
|
||||
} else {
|
||||
reg_name = RegisterName(range->assigned_register());
|
||||
}
|
||||
prefix = snprintf(buffer, max_prefix_length, "|%s", reg_name);
|
||||
}
|
||||
os << buffer;
|
||||
position += std::min(prefix, max_prefix_length - 1);
|
||||
CHECK_GE(end.value(), position);
|
||||
const char line_style = range->spilled() ? '-' : '=';
|
||||
for (; end.value() > position; position++) {
|
||||
os << line_style;
|
||||
}
|
||||
}
|
||||
}
|
||||
os << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
SpillRange::SpillRange(TopLevelLiveRange* parent, Zone* zone)
|
||||
: live_ranges_(zone),
|
||||
assigned_slot_(kUnassignedSlot),
|
||||
@ -2720,6 +2794,10 @@ void LinearScanAllocator::AllocateRegisters() {
|
||||
|
||||
ProcessCurrentRange(current);
|
||||
}
|
||||
|
||||
if (FLAG_trace_alloc) {
|
||||
PrintRangeOverview(std::cout);
|
||||
}
|
||||
}
|
||||
|
||||
bool LinearScanAllocator::TrySplitAndSpillSplinter(LiveRange* range) {
|
||||
|
@ -1080,6 +1080,7 @@ class LinearScanAllocator final : public RegisterAllocator {
|
||||
LifetimePosition until, LifetimePosition end);
|
||||
|
||||
void SplitAndSpillIntersecting(LiveRange* range);
|
||||
void PrintRangeOverview(std::ostream& os);
|
||||
|
||||
LiveRangeQueue unhandled_live_ranges_;
|
||||
ZoneVector<LiveRange*> active_live_ranges_;
|
||||
|
Loading…
Reference in New Issue
Block a user