[turbofan] update SpillRange to use ZoneVector
R=bmeurer@chromium.org BUG= Review URL: https://codereview.chromium.org/793323002 Cr-Commit-Position: refs/heads/master@{#25777}
This commit is contained in:
parent
7e9ca491a4
commit
91ed586ec2
@ -725,9 +725,8 @@ void GraphC1Visualizer::PrintLiveRange(LiveRange* range, const char* type) {
|
|||||||
}
|
}
|
||||||
} else if (range->IsSpilled()) {
|
} else if (range->IsSpilled()) {
|
||||||
int index = -1;
|
int index = -1;
|
||||||
if (range->TopLevel()->GetSpillRange() != nullptr &&
|
if (range->TopLevel()->HasSpillRange()) {
|
||||||
range->TopLevel()->GetSpillRange()->id() != -1) {
|
index = kMaxInt; // This hasn't been set yet.
|
||||||
index = range->TopLevel()->GetSpillRange()->id();
|
|
||||||
} else {
|
} else {
|
||||||
index = range->TopLevel()->GetSpillOperand()->index();
|
index = range->TopLevel()->GetSpillOperand()->index();
|
||||||
}
|
}
|
||||||
|
@ -710,8 +710,8 @@ LiveRange* RegisterAllocator::FixedDoubleLiveRangeFor(int index) {
|
|||||||
|
|
||||||
|
|
||||||
LiveRange* RegisterAllocator::LiveRangeFor(int index) {
|
LiveRange* RegisterAllocator::LiveRangeFor(int index) {
|
||||||
if (index >= static_cast<int>(live_ranges_.size())) {
|
if (index >= static_cast<int>(live_ranges().size())) {
|
||||||
live_ranges_.resize(index + 1, nullptr);
|
live_ranges().resize(index + 1, nullptr);
|
||||||
}
|
}
|
||||||
auto result = live_ranges()[index];
|
auto result = live_ranges()[index];
|
||||||
if (result == nullptr) {
|
if (result == nullptr) {
|
||||||
@ -819,14 +819,13 @@ static bool AreUseIntervalsIntersecting(UseInterval* interval1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SpillRange::SpillRange(LiveRange* range, int id, Zone* zone)
|
SpillRange::SpillRange(LiveRange* range, Zone* zone) : live_ranges_(zone) {
|
||||||
: id_(id), live_ranges_(1, zone), end_position_(range->End()) {
|
|
||||||
auto src = range->first_interval();
|
auto src = range->first_interval();
|
||||||
UseInterval* result = nullptr;
|
UseInterval* result = nullptr;
|
||||||
UseInterval* node = nullptr;
|
UseInterval* node = nullptr;
|
||||||
// Copy the nodes
|
// Copy the nodes
|
||||||
while (src != nullptr) {
|
while (src != nullptr) {
|
||||||
UseInterval* new_node = new (zone) UseInterval(src->start(), src->end());
|
auto new_node = new (zone) UseInterval(src->start(), src->end());
|
||||||
if (result == nullptr) {
|
if (result == nullptr) {
|
||||||
result = new_node;
|
result = new_node;
|
||||||
} else {
|
} else {
|
||||||
@ -836,54 +835,58 @@ SpillRange::SpillRange(LiveRange* range, int id, Zone* zone)
|
|||||||
src = src->next();
|
src = src->next();
|
||||||
}
|
}
|
||||||
use_interval_ = result;
|
use_interval_ = result;
|
||||||
live_ranges_.Add(range, zone);
|
live_ranges().push_back(range);
|
||||||
|
end_position_ = node->end();
|
||||||
DCHECK(!range->HasSpillRange());
|
DCHECK(!range->HasSpillRange());
|
||||||
range->SetSpillRange(this);
|
range->SetSpillRange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SpillRange::IsIntersectingWith(SpillRange* other) {
|
bool SpillRange::IsIntersectingWith(SpillRange* other) const {
|
||||||
if (End().Value() <= other->use_interval_->start().Value() ||
|
if (this->use_interval_ == nullptr || other->use_interval_ == nullptr ||
|
||||||
other->End().Value() <= use_interval_->start().Value()) {
|
this->End().Value() <= other->use_interval_->start().Value() ||
|
||||||
|
other->End().Value() <= this->use_interval_->start().Value()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return AreUseIntervalsIntersecting(use_interval_, other->use_interval_);
|
return AreUseIntervalsIntersecting(use_interval_, other->use_interval_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SpillRange::TryMerge(SpillRange* other, Zone* zone) {
|
bool SpillRange::TryMerge(SpillRange* other) {
|
||||||
if (Kind() == other->Kind() &&
|
if (Kind() != other->Kind() || IsIntersectingWith(other)) return false;
|
||||||
!AreUseIntervalsIntersecting(use_interval_, other->use_interval_)) {
|
|
||||||
if (End().Value() < other->End().Value()) {
|
auto max = LifetimePosition::MaxPosition();
|
||||||
|
if (End().Value() < other->End().Value() &&
|
||||||
|
other->End().Value() != max.Value()) {
|
||||||
end_position_ = other->End();
|
end_position_ = other->End();
|
||||||
}
|
}
|
||||||
|
other->end_position_ = max;
|
||||||
|
|
||||||
MergeDisjointIntervals(other->use_interval_, zone);
|
MergeDisjointIntervals(other->use_interval_);
|
||||||
other->use_interval_ = nullptr;
|
other->use_interval_ = nullptr;
|
||||||
|
|
||||||
for (int i = 0; i < other->live_ranges_.length(); i++) {
|
for (auto range : other->live_ranges()) {
|
||||||
DCHECK(other->live_ranges_.at(i)->GetSpillRange() == other);
|
DCHECK(range->GetSpillRange() == other);
|
||||||
other->live_ranges_.at(i)->SetSpillRange(this);
|
range->SetSpillRange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
live_ranges_.AddAll(other->live_ranges_, zone);
|
live_ranges().insert(live_ranges().end(), other->live_ranges().begin(),
|
||||||
other->live_ranges_.Clear();
|
other->live_ranges().end());
|
||||||
|
other->live_ranges().clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SpillRange::SetOperand(InstructionOperand* op) {
|
void SpillRange::SetOperand(InstructionOperand* op) {
|
||||||
for (int i = 0; i < live_ranges_.length(); i++) {
|
for (auto range : live_ranges()) {
|
||||||
DCHECK(live_ranges_.at(i)->GetSpillRange() == this);
|
DCHECK(range->GetSpillRange() == this);
|
||||||
live_ranges_.at(i)->CommitSpillOperand(op);
|
range->CommitSpillOperand(op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SpillRange::MergeDisjointIntervals(UseInterval* other, Zone* zone) {
|
void SpillRange::MergeDisjointIntervals(UseInterval* other) {
|
||||||
UseInterval* tail = nullptr;
|
UseInterval* tail = nullptr;
|
||||||
auto current = use_interval_;
|
auto current = use_interval_;
|
||||||
while (other != nullptr) {
|
while (other != nullptr) {
|
||||||
@ -892,11 +895,9 @@ void SpillRange::MergeDisjointIntervals(UseInterval* other, Zone* zone) {
|
|||||||
current->start().Value() > other->start().Value()) {
|
current->start().Value() > other->start().Value()) {
|
||||||
std::swap(current, other);
|
std::swap(current, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check disjointness
|
// Check disjointness
|
||||||
DCHECK(other == nullptr ||
|
DCHECK(other == nullptr ||
|
||||||
current->end().Value() <= other->start().Value());
|
current->end().Value() <= other->start().Value());
|
||||||
|
|
||||||
// Append the 'current' node to the result accumulator and move forward
|
// Append the 'current' node to the result accumulator and move forward
|
||||||
if (tail == nullptr) {
|
if (tail == nullptr) {
|
||||||
use_interval_ = current;
|
use_interval_ = current;
|
||||||
@ -920,7 +921,7 @@ void RegisterAllocator::ReuseSpillSlots() {
|
|||||||
for (size_t j = i + 1; j < spill_ranges().size(); j++) {
|
for (size_t j = i + 1; j < spill_ranges().size(); j++) {
|
||||||
auto other = spill_ranges()[j];
|
auto other = spill_ranges()[j];
|
||||||
if (!other->IsEmpty()) {
|
if (!other->IsEmpty()) {
|
||||||
range->TryMerge(other, local_zone());
|
range->TryMerge(other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -956,9 +957,7 @@ void RegisterAllocator::CommitAssignment() {
|
|||||||
|
|
||||||
SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) {
|
SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) {
|
||||||
DCHECK(FLAG_turbo_reuse_spill_slots);
|
DCHECK(FLAG_turbo_reuse_spill_slots);
|
||||||
int spill_id = static_cast<int>(spill_ranges().size());
|
auto spill_range = new (local_zone()) SpillRange(range, local_zone());
|
||||||
auto spill_range =
|
|
||||||
new (local_zone()) SpillRange(range, spill_id, local_zone());
|
|
||||||
spill_ranges().push_back(spill_range);
|
spill_ranges().push_back(spill_range);
|
||||||
return spill_range;
|
return spill_range;
|
||||||
}
|
}
|
||||||
@ -1008,13 +1007,11 @@ bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) {
|
|||||||
int op = phi->operands()[i];
|
int op = phi->operands()[i];
|
||||||
auto op_range = LiveRangeFor(op);
|
auto op_range = LiveRangeFor(op);
|
||||||
auto op_spill = op_range->GetSpillRange();
|
auto op_spill = op_range->GetSpillRange();
|
||||||
if (op_spill != nullptr) {
|
if (op_spill != nullptr &&
|
||||||
if (op_spill->id() == first_op_spill->id() ||
|
(op_spill == first_op_spill || first_op_spill->TryMerge(op_spill))) {
|
||||||
first_op_spill->TryMerge(op_spill, local_zone())) {
|
|
||||||
num_merged++;
|
num_merged++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Only continue if enough operands could be merged to the
|
// Only continue if enough operands could be merged to the
|
||||||
// same spill slot.
|
// same spill slot.
|
||||||
@ -1033,12 +1030,12 @@ bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) {
|
|||||||
auto pos = range->NextUsePositionRegisterIsBeneficial(next_pos);
|
auto pos = range->NextUsePositionRegisterIsBeneficial(next_pos);
|
||||||
if (pos == nullptr) {
|
if (pos == nullptr) {
|
||||||
auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
|
auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
|
||||||
CHECK(first_op_spill->TryMerge(spill_range, local_zone()));
|
CHECK(first_op_spill->TryMerge(spill_range));
|
||||||
Spill(range);
|
Spill(range);
|
||||||
return true;
|
return true;
|
||||||
} else if (pos->pos().Value() > range->Start().NextInstruction().Value()) {
|
} else if (pos->pos().Value() > range->Start().NextInstruction().Value()) {
|
||||||
auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
|
auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
|
||||||
CHECK(first_op_spill->TryMerge(spill_range, local_zone()));
|
CHECK(first_op_spill->TryMerge(spill_range));
|
||||||
SpillBetween(range, range->Start(), pos->pos());
|
SpillBetween(range, range->Start(), pos->pos());
|
||||||
if (!AllocationOk()) return false;
|
if (!AllocationOk()) return false;
|
||||||
DCHECK(UnhandledIsSorted());
|
DCHECK(UnhandledIsSorted());
|
||||||
|
@ -105,7 +105,7 @@ class LifetimePosition FINAL {
|
|||||||
class UseInterval FINAL : public ZoneObject {
|
class UseInterval FINAL : public ZoneObject {
|
||||||
public:
|
public:
|
||||||
UseInterval(LifetimePosition start, LifetimePosition end)
|
UseInterval(LifetimePosition start, LifetimePosition end)
|
||||||
: start_(start), end_(end), next_(NULL) {
|
: start_(start), end_(end), next_(nullptr) {
|
||||||
DCHECK(start.Value() < end.Value());
|
DCHECK(start.Value() < end.Value());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ class UsePosition FINAL : public ZoneObject {
|
|||||||
InstructionOperand* hint);
|
InstructionOperand* hint);
|
||||||
|
|
||||||
InstructionOperand* operand() const { return operand_; }
|
InstructionOperand* operand() const { return operand_; }
|
||||||
bool HasOperand() const { return operand_ != NULL; }
|
bool HasOperand() const { return operand_ != nullptr; }
|
||||||
|
|
||||||
InstructionOperand* hint() const { return hint_; }
|
InstructionOperand* hint() const { return hint_; }
|
||||||
bool HasHint() const;
|
bool HasHint() const;
|
||||||
@ -184,15 +184,15 @@ class LiveRange FINAL : public ZoneObject {
|
|||||||
UseInterval* first_interval() const { return first_interval_; }
|
UseInterval* first_interval() const { return first_interval_; }
|
||||||
UsePosition* first_pos() const { return first_pos_; }
|
UsePosition* first_pos() const { return first_pos_; }
|
||||||
LiveRange* parent() const { return parent_; }
|
LiveRange* parent() const { return parent_; }
|
||||||
LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; }
|
LiveRange* TopLevel() { return (parent_ == nullptr) ? this : parent_; }
|
||||||
const LiveRange* TopLevel() const {
|
const LiveRange* TopLevel() const {
|
||||||
return (parent_ == NULL) ? this : parent_;
|
return (parent_ == nullptr) ? this : parent_;
|
||||||
}
|
}
|
||||||
LiveRange* next() const { return next_; }
|
LiveRange* next() const { return next_; }
|
||||||
bool IsChild() const { return parent() != NULL; }
|
bool IsChild() const { return parent() != nullptr; }
|
||||||
int id() const { return id_; }
|
int id() const { return id_; }
|
||||||
bool IsFixed() const { return id_ < 0; }
|
bool IsFixed() const { return id_ < 0; }
|
||||||
bool IsEmpty() const { return first_interval() == NULL; }
|
bool IsEmpty() const { return first_interval() == nullptr; }
|
||||||
InstructionOperand* CreateAssignedOperand(Zone* zone) const;
|
InstructionOperand* CreateAssignedOperand(Zone* zone) const;
|
||||||
int assigned_register() const { return assigned_register_; }
|
int assigned_register() const { return assigned_register_; }
|
||||||
int spill_start_index() const { return spill_start_index_; }
|
int spill_start_index() const { return spill_start_index_; }
|
||||||
@ -245,9 +245,9 @@ class LiveRange FINAL : public ZoneObject {
|
|||||||
}
|
}
|
||||||
InstructionOperand* FirstHint() const {
|
InstructionOperand* FirstHint() const {
|
||||||
UsePosition* pos = first_pos_;
|
UsePosition* pos = first_pos_;
|
||||||
while (pos != NULL && !pos->HasHint()) pos = pos->next();
|
while (pos != nullptr && !pos->HasHint()) pos = pos->next();
|
||||||
if (pos != NULL) return pos->hint();
|
if (pos != nullptr) return pos->hint();
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LifetimePosition Start() const {
|
LifetimePosition Start() const {
|
||||||
@ -345,26 +345,28 @@ class LiveRange FINAL : public ZoneObject {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class SpillRange : public ZoneObject {
|
class SpillRange FINAL : public ZoneObject {
|
||||||
public:
|
public:
|
||||||
SpillRange(LiveRange* range, int id, Zone* zone);
|
SpillRange(LiveRange* range, Zone* zone);
|
||||||
bool TryMerge(SpillRange* other, Zone* zone);
|
|
||||||
|
UseInterval* interval() const { return use_interval_; }
|
||||||
|
RegisterKind Kind() const { return live_ranges_[0]->Kind(); }
|
||||||
|
bool IsEmpty() const { return live_ranges_.empty(); }
|
||||||
|
bool TryMerge(SpillRange* other);
|
||||||
void SetOperand(InstructionOperand* op);
|
void SetOperand(InstructionOperand* op);
|
||||||
bool IsEmpty() { return live_ranges_.length() == 0; }
|
|
||||||
int id() const { return id_; }
|
|
||||||
UseInterval* interval() { return use_interval_; }
|
|
||||||
RegisterKind Kind() const { return live_ranges_.at(0)->Kind(); }
|
|
||||||
LifetimePosition End() const { return end_position_; }
|
|
||||||
bool IsIntersectingWith(SpillRange* other);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int id_;
|
LifetimePosition End() const { return end_position_; }
|
||||||
ZoneList<LiveRange*> live_ranges_;
|
ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; }
|
||||||
|
bool IsIntersectingWith(SpillRange* other) const;
|
||||||
|
// Merge intervals, making sure the use intervals are sorted
|
||||||
|
void MergeDisjointIntervals(UseInterval* other);
|
||||||
|
|
||||||
|
ZoneVector<LiveRange*> live_ranges_;
|
||||||
UseInterval* use_interval_;
|
UseInterval* use_interval_;
|
||||||
LifetimePosition end_position_;
|
LifetimePosition end_position_;
|
||||||
|
|
||||||
// Merge intervals, making sure the use intervals are sorted
|
DISALLOW_COPY_AND_ASSIGN(SpillRange);
|
||||||
void MergeDisjointIntervals(UseInterval* other, Zone* zone);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user