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

Reland "[regalloc] Introduce LiveRangeBundles"

Removed the static field and made it an instance field on the
BundleBuilder.

Change-Id: I58a9f4a744654b262a3e47e6873baffb537eb21b
Reviewed-on: https://chromium-review.googlesource.com/c/1404444Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Commit-Queue: Stephan Herhut <herhut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58709}
parent a1c333e4
This diff is collapsed.
...@@ -300,6 +300,7 @@ class V8_EXPORT_PRIVATE UsePosition final ...@@ -300,6 +300,7 @@ class V8_EXPORT_PRIVATE UsePosition final
class SpillRange; class SpillRange;
class RegisterAllocationData; class RegisterAllocationData;
class TopLevelLiveRange; class TopLevelLiveRange;
class LiveRangeBundle;
// Representation of SSA values' live ranges as a collection of (continuous) // Representation of SSA values' live ranges as a collection of (continuous)
// intervals over the instruction ordering. // intervals over the instruction ordering.
...@@ -425,6 +426,11 @@ class V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -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(const RegisterConfiguration* config, bool with_children) const;
void Print(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: private:
friend class TopLevelLiveRange; friend class TopLevelLiveRange;
explicit LiveRange(int relative_id, MachineRepresentation rep, explicit LiveRange(int relative_id, MachineRepresentation rep,
...@@ -461,10 +467,79 @@ class V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -461,10 +467,79 @@ class V8_EXPORT_PRIVATE LiveRange : public NON_EXPORTED_BASE(ZoneObject) {
mutable UsePosition* current_hint_position_; mutable UsePosition* current_hint_position_;
// Cache the last position splintering stopped at. // Cache the last position splintering stopped at.
mutable UsePosition* splitting_pointer_; mutable UsePosition* splitting_pointer_;
LiveRangeBundle* bundle_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(LiveRange); 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;
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, int id)
: ranges_(zone), uses_(zone), id_(id) {}
bool TryAddRange(LiveRange* range);
bool TryMerge(LiveRangeBundle* other);
ZoneSet<LiveRange*, LiveRangeOrdering> ranges_;
ZoneSet<Range, RangeOrdering> uses_;
int id_;
int reg_ = kUnassignedRegister;
};
class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange { class V8_EXPORT_PRIVATE TopLevelLiveRange final : public LiveRange {
public: public:
explicit TopLevelLiveRange(int vreg, MachineRepresentation rep); explicit TopLevelLiveRange(int vreg, MachineRepresentation rep);
...@@ -948,6 +1023,19 @@ class LiveRangeBuilder final : public ZoneObject { ...@@ -948,6 +1023,19 @@ class LiveRangeBuilder final : public ZoneObject {
DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder); 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_;
int next_bundle_id_ = 0;
};
class RegisterAllocator : public ZoneObject { class RegisterAllocator : public ZoneObject {
public: public:
RegisterAllocator(RegisterAllocationData* data, RegisterKind kind); RegisterAllocator(RegisterAllocationData* data, RegisterKind kind);
......
...@@ -776,7 +776,11 @@ void GraphC1Visualizer::PrintLiveRange(const LiveRange* range, const char* type, ...@@ -776,7 +776,11 @@ void GraphC1Visualizer::PrintLiveRange(const LiveRange* range, const char* type,
os_ << " " << parent->vreg() << ":" << parent->relative_id(); os_ << " " << parent->vreg() << ":" << parent->relative_id();
// TODO(herhut) Find something useful to print for the hint field // 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(); for (const UseInterval* interval = range->first_interval();
interval != nullptr; interval = interval->next()) { interval != nullptr; interval = interval->next()) {
......
...@@ -1668,6 +1668,14 @@ struct BuildLiveRangesPhase { ...@@ -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 { struct SplinterLiveRangesPhase {
static const char* phase_name() { return "splinter live ranges"; } static const char* phase_name() { return "splinter live ranges"; }
...@@ -2816,6 +2824,8 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config, ...@@ -2816,6 +2824,8 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config,
Run<MeetRegisterConstraintsPhase>(); Run<MeetRegisterConstraintsPhase>();
Run<ResolvePhisPhase>(); Run<ResolvePhisPhase>();
Run<BuildLiveRangesPhase>(); Run<BuildLiveRangesPhase>();
Run<BuildBundlesPhase>();
TraceSequence(info(), data, "before register allocation"); TraceSequence(info(), data, "before register allocation");
if (verifier != nullptr) { if (verifier != nullptr) {
CHECK(!data->register_allocation_data()->ExistsUseWithoutDefinition()); 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