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

Unified Diff: src/compiler/register-allocator.cc

Issue 2347563004: [turbofan] Avoid large deopt blocks (Closed)
Patch Set: A few more adjustments Created 4 years, 3 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/register-allocator.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/register-allocator.cc
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
index efcdcb42e64eb79ef0546c0215c1974feb5bb6c8..e2df7bbba3301c469446d50bcf306b6da7420307 100644
--- a/src/compiler/register-allocator.cc
+++ b/src/compiler/register-allocator.cc
@@ -342,6 +342,11 @@ UsePositionHintType UsePosition::HintTypeForOperand(
return UsePositionHintType::kNone;
}
+void UsePosition::SetHint(UsePosition* use_pos) {
+ DCHECK_NOT_NULL(use_pos);
+ hint_ = use_pos;
+ flags_ = HintTypeField::update(flags_, UsePositionHintType::kUsePos);
+}
void UsePosition::ResolveHint(UsePosition* use_pos) {
DCHECK_NOT_NULL(use_pos);
@@ -581,7 +586,10 @@ void LiveRange::AdvanceLastProcessedMarker(
LiveRange* LiveRange::SplitAt(LifetimePosition position, Zone* zone) {
int new_id = TopLevel()->GetNextChildId();
LiveRange* child = new (zone) LiveRange(new_id, representation(), TopLevel());
- DetachAt(position, child, zone);
+ // If we split, we do so because we're about to switch registers or move
+ // to/from
Jarin 2016/09/29 14:20:34 nit: merge the comment with the next line.
+ // a slot, so there's no value in connecting hints.
+ DetachAt(position, child, zone, false);
child->top_level_ = TopLevel();
child->next_ = next_;
@@ -589,9 +597,8 @@ LiveRange* LiveRange::SplitAt(LifetimePosition position, Zone* zone) {
return child;
}
-
UsePosition* LiveRange::DetachAt(LifetimePosition position, LiveRange* result,
- Zone* zone) {
+ Zone* zone, bool connect_hints) {
DCHECK(Start() < position);
DCHECK(End() > position);
DCHECK(result->IsEmpty());
@@ -670,6 +677,9 @@ UsePosition* LiveRange::DetachAt(LifetimePosition position, LiveRange* result,
last_processed_use_ = nullptr;
current_interval_ = nullptr;
+ if (connect_hints && use_before != nullptr && use_after != nullptr) {
+ use_after->SetHint(use_before);
+ }
#ifdef DEBUG
VerifyChildStructure();
result->VerifyChildStructure();
@@ -716,6 +726,18 @@ bool LiveRange::ShouldBeAllocatedBefore(const LiveRange* other) const {
LifetimePosition start = Start();
LifetimePosition other_start = other->Start();
if (start == other_start) {
+ bool this_is_splinter = TopLevel()->IsSplinter();
+ bool other_is_splinter = other->TopLevel()->IsSplinter();
+ if (this_is_splinter && other_is_splinter &&
+ (this->FirstHintPosition() == nullptr) ==
+ (other->FirstHintPosition() == nullptr)) {
+ if (this->FirstHintPosition() != nullptr &&
+ other->FirstHintPosition() == nullptr)
Jarin 2016/09/29 14:20:35 I have no idea what these conditions say. The con
Mircea Trofin 2016/09/30 05:16:51 Ya, they make no sense as written. Fixed.
+ return true;
+ if (this->FirstHintPosition() == nullptr &&
+ other->FirstHintPosition() != nullptr)
Jarin 2016/09/29 14:20:35 Also seems to be always false, which means that al
Mircea Trofin 2016/09/30 05:16:51 Acknowledged.
+ return false;
+ }
UsePosition* pos = first_pos();
if (pos == nullptr) return false;
UsePosition* other_pos = other->first_pos();
@@ -912,17 +934,20 @@ void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end,
if (end >= End()) {
DCHECK(start > Start());
- DetachAt(start, &splinter_temp, zone);
+ DetachAt(start, &splinter_temp, zone, true);
Jarin 2016/09/29 14:20:35 Here it is not really clear what "true" refers to.
Mircea Trofin 2016/09/30 05:16:51 Done.
next_ = nullptr;
} else {
DCHECK(start < End() && Start() < end);
const int kInvalidId = std::numeric_limits<int>::max();
- UsePosition* last = DetachAt(start, &splinter_temp, zone);
+ UsePosition* last = DetachAt(start, &splinter_temp, zone, true);
LiveRange end_part(kInvalidId, this->representation(), nullptr);
- last_in_splinter = splinter_temp.DetachAt(end, &end_part, zone);
+ // The last chunk exits the deferred region, and we don't want to connect
+ // hints here, because the non-deferred region shouldn't be affected
+ // by allocation decisions on the deferred path.
+ last_in_splinter = splinter_temp.DetachAt(end, &end_part, zone, false);
next_ = end_part.next_;
last_interval_->set_next(end_part.first_interval_);
@@ -2401,7 +2426,13 @@ void RegisterAllocator::SplitAndSpillRangesDefinedByMemoryOperand() {
if (next_pos.IsGapPosition()) {
next_pos = next_pos.NextStart();
}
- UsePosition* pos = range->NextUsePositionRegisterIsBeneficial(next_pos);
+
+ // With splinters, we can be more strict and skip over positions
+ // not strictly needing registers.
+ UsePosition* pos =
+ range->IsSplinter()
+ ? range->NextRegisterPosition(next_pos)
+ : range->NextUsePositionRegisterIsBeneficial(next_pos);
Jarin 2016/09/29 14:20:35 Does this make any measurable difference?
Mircea Trofin 2016/09/30 05:16:51 I remember seeing a case where this helped avoid a
// If the range already has a spill operand and it doesn't need a
// register immediately, split it and spill the first part of the range.
if (pos == nullptr) {
@@ -2804,6 +2835,29 @@ bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) {
}
}
+ if (current->TopLevel()->IsSplinter()) {
+ // We weren't able to give the splinter the hinted register. Whatever we do,
+ // it will result in a move. For splinters, our goal is to minimize
Jarin 2016/09/29 14:20:35 I do not understand this reasoning - if there is n
Mircea Trofin 2016/09/30 05:16:51 The hint says, for splinters, what operand the pre
Jarin 2016/09/30 13:23:03 I still do not really understand when we get here.
Mircea Trofin 2016/09/30 14:45:48 The hints for splinters are added when we create t
+ // moves, for code size, not their quality - meaning, no need to try hard
+ // and keep the value in a register.
+ // If we can spill the whole range, great. Otherwise, split above the
+ // first use needing a register and spill the top part. No need to involve
+ // the hint (e.g. what if we could give the upper chunk the hint), because
+ // we
Jarin 2016/09/29 14:20:35 What's up with the formatting of the comments in t
Mircea Trofin 2016/09/30 05:16:51 probably git cl format :) I'll re-brush them.
+ // would then have at least the same number of moves.
+ const UsePosition* next_reg =
+ current->NextRegisterPosition(current->Start());
+ if (next_reg == nullptr) {
+ Spill(current);
+ return true;
+ } else if (next_reg->pos().PrevStart() > current->Start()) {
+ LiveRange* tail = SplitRangeAt(current, next_reg->pos().PrevStart());
+ AddToUnhandledSorted(tail);
+ Spill(current);
+ return true;
+ }
+ }
+
// Find the register which stays free for the longest time.
int reg = codes[0];
for (int i = 1; i < num_codes; ++i) {
« no previous file with comments | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698