Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Unified Diff: src/compiler/coalesced-live-ranges.cc

Issue 1219063017: [turbofan] Unit tests for live range conflicts. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/coalesced-live-ranges.h ('k') | src/compiler/greedy-allocator.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/coalesced-live-ranges.cc
diff --git a/src/compiler/coalesced-live-ranges.cc b/src/compiler/coalesced-live-ranges.cc
index e81f5518bd636908b93cd2a6bfc57f4f8f64e5f0..44dd336c83fc81b181199cad3cdff071e0e95018 100644
--- a/src/compiler/coalesced-live-ranges.cc
+++ b/src/compiler/coalesced-live-ranges.cc
@@ -10,136 +10,131 @@ namespace v8 {
namespace internal {
namespace compiler {
-#define TRACE(...) \
- do { \
- if (FLAG_trace_alloc) PrintF(__VA_ARGS__); \
- } while (false)
+LiveRangeConflictIterator::LiveRangeConflictIterator(const LiveRange* range,
+ IntervalStore* storage)
+ : query_(range->first_interval()),
+ pos_(storage->end()),
+ intervals_(storage) {
+ MovePosAndQueryToFirstConflict();
+}
-const float CoalescedLiveRanges::kAllocatedRangeMultiplier = 10.0;
-void CoalescedLiveRanges::AllocateRange(LiveRange* range) {
- UpdateWeightAtAllocation(range);
- for (auto interval = range->first_interval(); interval != nullptr;
- interval = interval->next()) {
- storage().insert({interval->start(), interval->end(), range});
- }
+LiveRange* LiveRangeConflictIterator::Current() const {
+ if (IsFinished()) return nullptr;
+ return pos_->range_;
}
-void CoalescedLiveRanges::Remove(LiveRange* range) {
- for (auto interval = range->first_interval(); interval != nullptr;
- interval = interval->next()) {
- storage().erase({interval->start(), interval->end(), nullptr});
- }
- range->UnsetAssignedRegister();
-}
+void LiveRangeConflictIterator::MovePosToFirstConflictForQuery() {
+ DCHECK(query_ != nullptr);
+ auto end = intervals_->end();
+ LifetimePosition q_start = query_->start();
+ LifetimePosition q_end = query_->end();
+ if (intervals_->empty() || intervals_->rbegin()->end_ <= q_start ||
+ intervals_->begin()->start_ >= q_end) {
+ pos_ = end;
+ return;
+ }
-float CoalescedLiveRanges::GetMaximumConflictingWeight(
- const LiveRange* range) const {
- float ret = LiveRange::kInvalidWeight;
- auto end = storage().end();
- for (auto query = range->first_interval(); query != nullptr;
- query = query->next()) {
- auto conflict = GetFirstConflict(query);
-
- if (conflict == end) continue;
- for (; QueryIntersectsAllocatedInterval(query, conflict); ++conflict) {
- // It is possible we'll visit the same range multiple times, because
- // successive (not necessarily consecutive) intervals belong to the same
- // range, or because different intervals of the query range have the same
- // range as conflict.
- DCHECK_NE(conflict->range->weight(), LiveRange::kInvalidWeight);
- ret = Max(ret, conflict->range->weight());
- if (ret == LiveRange::kMaxWeight) break;
+ pos_ = intervals_->upper_bound(AsAllocatedInterval(q_start));
+ // pos is either at the end (no start strictly greater than q_start) or
+ // at some position with the aforementioned property. In either case, the
+ // allocated interval before this one may intersect our query:
+ // either because, although it starts before this query's start, it ends
+ // after; or because it starts exactly at the query start. So unless we're
+ // right at the beginning of the storage - meaning the first allocated
+ // interval is also starting after this query's start - see what's behind.
+ if (pos_ != intervals_->begin()) {
+ --pos_;
+ if (!QueryIntersectsAllocatedInterval()) {
+ // The interval behind wasn't intersecting, so move back.
+ ++pos_;
}
}
- return ret;
+ if (pos_ == end || !QueryIntersectsAllocatedInterval()) {
+ pos_ = end;
+ }
}
-void CoalescedLiveRanges::EvictAndRescheduleConflicts(
- LiveRange* range, AllocationScheduler* scheduler) {
- auto end = storage().end();
-
- for (auto query = range->first_interval(); query != nullptr;
- query = query->next()) {
- auto conflict = GetFirstConflict(query);
- if (conflict == end) continue;
- while (QueryIntersectsAllocatedInterval(query, conflict)) {
- LiveRange* range_to_evict = conflict->range;
- // Bypass successive intervals belonging to the same range, because we're
- // about to remove this range, and we don't want the storage iterator to
- // become invalid.
- while (conflict != end && conflict->range == range_to_evict) {
- ++conflict;
- }
-
- DCHECK(range_to_evict->HasRegisterAssigned());
- CHECK(!range_to_evict->IsFixed());
- Remove(range_to_evict);
- UpdateWeightAtEviction(range_to_evict);
- TRACE("Evicted range %d.\n", range_to_evict->id());
- scheduler->Schedule(range_to_evict);
+void LiveRangeConflictIterator::MovePosAndQueryToFirstConflict() {
+ auto end = intervals_->end();
+ for (; query_ != nullptr; query_ = query_->next()) {
+ MovePosToFirstConflictForQuery();
+ if (pos_ != end) {
+ DCHECK(QueryIntersectsAllocatedInterval());
+ return;
}
}
+
+ Invalidate();
}
-bool CoalescedLiveRanges::VerifyAllocationsAreValid() const {
- LifetimePosition last_end = LifetimePosition::GapFromInstructionIndex(0);
- for (auto i : storage_) {
- if (i.start < last_end) {
- return false;
- }
- last_end = i.end;
+void LiveRangeConflictIterator::IncrementPosAndSkipOverRepetitions() {
+ auto end = intervals_->end();
+ DCHECK(pos_ != end);
+ LiveRange* current_conflict = Current();
+ while (pos_ != end && pos_->range_ == current_conflict) {
+ ++pos_;
}
- return true;
}
-void CoalescedLiveRanges::UpdateWeightAtAllocation(LiveRange* range) {
- DCHECK_NE(range->weight(), LiveRange::kInvalidWeight);
- range->set_weight(range->weight() * kAllocatedRangeMultiplier);
+LiveRange* LiveRangeConflictIterator::InternalGetNext(bool clean_behind) {
+ if (IsFinished()) return nullptr;
+
+ LiveRange* to_clear = Current();
+ IncrementPosAndSkipOverRepetitions();
+ // At this point, pos_ is either at the end, or on an interval that doesn't
+ // correspond to the same range as to_clear. This interval may not even be
+ // a conflict.
+ if (clean_behind) {
+ // Since we parked pos_ on an iterator that won't be affected by removal,
+ // we can safely delete to_clear's intervals.
+ for (auto interval = to_clear->first_interval(); interval != nullptr;
+ interval = interval->next()) {
+ AllocatedInterval erase_key(interval->start(), interval->end(), nullptr);
+ intervals_->erase(erase_key);
+ }
+ }
+ // We may have parked pos_ at the end, or on a non-conflict. In that case,
+ // move to the next query and reinitialize pos and query. This may invalidate
+ // the iterator, if no more conflicts are available.
+ if (!QueryIntersectsAllocatedInterval()) {
+ query_ = query_->next();
+ MovePosAndQueryToFirstConflict();
+ }
+ return Current();
}
-void CoalescedLiveRanges::UpdateWeightAtEviction(LiveRange* range) {
- DCHECK_NE(range->weight(), LiveRange::kInvalidWeight);
- range->set_weight(range->weight() / kAllocatedRangeMultiplier);
+LiveRangeConflictIterator CoalescedLiveRanges::GetConflicts(
+ const LiveRange* range) {
+ return LiveRangeConflictIterator(range, &intervals());
}
-CoalescedLiveRanges::interval_iterator CoalescedLiveRanges::GetFirstConflict(
- const UseInterval* query) const {
- DCHECK(query != nullptr);
- auto end = storage().end();
- LifetimePosition q_start = query->start();
- LifetimePosition q_end = query->end();
-
- if (storage().empty() || storage().rbegin()->end <= q_start ||
- storage().begin()->start >= q_end) {
- return end;
+void CoalescedLiveRanges::AllocateRange(LiveRange* range) {
+ for (auto interval = range->first_interval(); interval != nullptr;
+ interval = interval->next()) {
+ AllocatedInterval to_insert(interval->start(), interval->end(), range);
+ intervals().insert(to_insert);
}
+}
- auto ret = storage().upper_bound(AsAllocatedInterval(q_start));
- // ret is either at the end (no start strictly greater than q_start) or
- // at some position with the aforementioned property. In either case, the
- // allocated interval before this one may intersect our query:
- // either because, although it starts before this query's start, it ends
- // after; or because it starts exactly at the query start. So unless we're
- // right at the beginning of the storage - meaning the first allocated
- // interval is also starting after this query's start - see what's behind.
- if (ret != storage().begin()) {
- --ret;
- if (!QueryIntersectsAllocatedInterval(query, ret)) {
- // The interval behind wasn't intersecting, so move back.
- ++ret;
+
+bool CoalescedLiveRanges::VerifyAllocationsAreValidForTesting() const {
+ LifetimePosition last_end = LifetimePosition::GapFromInstructionIndex(0);
+ for (auto i : intervals_) {
+ if (i.start_ < last_end) {
+ return false;
}
+ last_end = i.end_;
}
- if (ret != end && QueryIntersectsAllocatedInterval(query, ret)) return ret;
- return end;
+ return true;
}
« no previous file with comments | « src/compiler/coalesced-live-ranges.h ('k') | src/compiler/greedy-allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698