[regalloc] Fix issue where FindOptimalSpillingPos missed some ranges

Currently, FindOptimalSpillingPos uses GetSpillState on the loop header
block when attempting to find the live range that covers the top of the
loop. However, GetSpillState represents the state at the end of a block,
and is not written until the allocator leaves the block. So when `pos`
is within the loop header block, FindOptimalSpillingPos is incorrectly
recommending a split rather than recommending a spill of the live range
covering the loop top. This change implements a better search for the
live range that covers the beginning of the loop.

Bug: v8:10606
Change-Id: I454a009b5806d1a01ee59d6d34b9e9ef8784d294
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2274308
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#68656}
This commit is contained in:
Seth Brenith 2020-07-01 09:18:07 -07:00 committed by Commit Bot
parent ee229d9e96
commit 4769e1586b

View File

@ -3081,15 +3081,12 @@ LifetimePosition RegisterAllocator::FindOptimalSpillingPos(
(range->TopLevel()->Start() == loop_start &&
range->TopLevel()->SpillAtLoopHeaderNotBeneficial()))
return pos;
auto& loop_header_state =
data()->GetSpillState(loop_header->rpo_number());
for (LiveRange* live_at_header : loop_header_state) {
if (live_at_header->TopLevel() != range->TopLevel() ||
!live_at_header->Covers(loop_start) || live_at_header->spilled()) {
continue;
}
LiveRange* check_use = live_at_header;
for (; check_use != nullptr && check_use->Start() < pos;
LiveRange* live_at_header = range->TopLevel()->GetChildCovers(loop_start);
if (live_at_header != nullptr && !live_at_header->spilled()) {
for (LiveRange* check_use = live_at_header;
check_use != nullptr && check_use->Start() < pos;
check_use = check_use->next()) {
// If we find a use for which spilling is detrimental, don't spill
// at the loop header
@ -3104,7 +3101,6 @@ LifetimePosition RegisterAllocator::FindOptimalSpillingPos(
// No register beneficial use inside the loop before the pos.
*begin_spill_out = live_at_header;
pos = loop_start;
break;
}
// Try hoisting out to an outer loop.