Commit 1a36ac01 authored by Stephan Herhut's avatar Stephan Herhut Committed by Commit Bot

[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/1346114Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Commit-Queue: Stephan Herhut <herhut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57687}
parent 49c7b308
......@@ -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_;
......
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