Commit d024b9a1 authored by Stephan Herhut's avatar Stephan Herhut Committed by Commit Bot

[regalloc] Introduce LiveRangeBundles

The idea behind this change is to restore some information about
pre-ssa values to aid register allocation in sharing spill slots and
reusing registers for connected live ranges.

By itself, this change does not improve much but it allows upcoming
changes to freely spill and reload ranges without worrying about
keeping the assignment stable.

Change-Id: I9320522592546655cc8fd0236d45fe075276a49e
Reviewed-on: https://chromium-review.googlesource.com/c/1375665
Commit-Queue: Stephan Herhut <herhut@chromium.org>
Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58688}
parent ba56d282
This diff is collapsed.
......@@ -300,6 +300,7 @@ class V8_EXPORT_PRIVATE UsePosition final
class SpillRange;
class RegisterAllocationData;
class TopLevelLiveRange;
class LiveRangeBundle;
// Representation of SSA values' live ranges as a collection of (continuous)
// intervals over the instruction ordering.
......@@ -425,6 +426,11 @@ class V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) {
void Print(const RegisterConfiguration* config, bool with_children) const;
void Print(bool with_children) const;
void set_bundle(LiveRangeBundle* bundle) { bundle_ = bundle; }
LiveRangeBundle* get_bundle() const { return bundle_; }
bool RegisterFromBundle(int* hint) const;
void UpdateBundleRegister(int reg) const;
private:
friend class TopLevelLiveRange;
explicit LiveRange(int relative_id, MachineRepresentation rep,
......@@ -461,10 +467,79 @@ class V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) {
mutable UsePosition* current_hint_position_;
// Cache the last position splintering stopped at.
mutable UsePosition* splitting_pointer_;
LiveRangeBundle* bundle_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(LiveRange);
};
struct LiveRangeOrdering {
bool operator()(const LiveRange* left, const LiveRange* right) const {
return left->Start() < right->Start();
}
};
class LiveRangeBundle : public ZoneObject {
public:
void MergeSpillRanges();
int id() { return id_; }
int reg() { return reg_; }
void set_reg(int reg) {
DCHECK_EQ(reg_, kUnassignedRegister);
reg_ = reg;
}
private:
friend class BundleBuilder;
static int bundle_id;
class Range {
public:
Range(int s, int e) : start(s), end(e) {}
Range(LifetimePosition s, LifetimePosition e)
: start(s.value()), end(e.value()) {}
int start;
int end;
};
struct RangeOrdering {
bool operator()(const Range left, const Range right) const {
return left.start < right.start;
}
};
bool UsesOverlap(UseInterval* interval) {
auto use = uses_.begin();
while (interval != nullptr && use != uses_.end()) {
if (use->end <= interval->start().value()) {
++use;
} else if (interval->end().value() <= use->start) {
interval = interval->next();
} else {
return true;
}
}
return false;
}
void InsertUses(UseInterval* interval) {
while (interval != nullptr) {
auto done = uses_.insert({interval->start(), interval->end()});
USE(done);
DCHECK_EQ(done.second, 1);
interval = interval->next();
}
}
explicit LiveRangeBundle(Zone* zone) : ranges_(zone), uses_(zone) {}
bool TryAddRange(LiveRange* range);
bool TryMerge(LiveRangeBundle* other);
ZoneSet<LiveRange*, LiveRangeOrdering> ranges_;
ZoneSet<Range, RangeOrdering> uses_;
int id_ = bundle_id++;
int reg_ = kUnassignedRegister;
};
class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
public:
explicit TopLevelLiveRange(int vreg, MachineRepresentation rep);
......@@ -948,6 +1023,18 @@ class LiveRangeBuilder final : public ZoneObject {
DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder);
};
class BundleBuilder final : public ZoneObject {
public:
explicit BundleBuilder(RegisterAllocationData* data) : data_(data) {}
void BuildBundles();
private:
RegisterAllocationData* data() const { return data_; }
InstructionSequence* code() const { return data_->code(); }
RegisterAllocationData* data_;
};
class RegisterAllocator : public ZoneObject {
public:
RegisterAllocator(RegisterAllocationData* data, RegisterKind kind);
......
......@@ -776,7 +776,11 @@ void GraphC1Visualizer::PrintLiveRange(const LiveRange* range, const char* type,
os_ << " " << parent->vreg() << ":" << parent->relative_id();
// TODO(herhut) Find something useful to print for the hint field
os_ << " unknown";
if (range->get_bundle() != nullptr) {
os_ << " B" << range->get_bundle()->id();
} else {
os_ << " unknown";
}
for (const UseInterval* interval = range->first_interval();
interval != nullptr; interval = interval->next()) {
......
......@@ -1668,6 +1668,14 @@ struct BuildLiveRangesPhase {
}
};
struct BuildBundlesPhase {
static const char* phase_name() { return "build live range bundles"; }
void Run(PipelineData* data, Zone* temp_zone) {
BundleBuilder builder(data->register_allocation_data());
builder.BuildBundles();
}
};
struct SplinterLiveRangesPhase {
static const char* phase_name() { return "splinter live ranges"; }
......@@ -2816,6 +2824,8 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config,
Run<MeetRegisterConstraintsPhase>();
Run<ResolvePhisPhase>();
Run<BuildLiveRangesPhase>();
Run<BuildBundlesPhase>();
TraceSequence(info(), data, "before register allocation");
if (verifier != nullptr) {
CHECK(!data->register_allocation_data()->ExistsUseWithoutDefinition());
......
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