| Index: src/lithium-allocator.cc
|
| diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc
|
| index 91a98112b61bd60a50b56d98f8ca4eebacdf01ff..303370c2809553c4f7a94d763f13cae7e8d05b43 100644
|
| --- a/src/lithium-allocator.cc
|
| +++ b/src/lithium-allocator.cc
|
| @@ -196,6 +196,18 @@ UsePosition* LiveRange::NextUsePositionRegisterIsBeneficial(
|
| }
|
|
|
|
|
| +UsePosition* LiveRange::PreviousUsePositionRegisterIsBeneficial(
|
| + LifetimePosition start) {
|
| + UsePosition* pos = first_pos();
|
| + UsePosition* prev = NULL;
|
| + while (pos != NULL && pos->pos().Value() < start.Value()) {
|
| + if (pos->RegisterIsBeneficial()) prev = pos;
|
| + pos = pos->next();
|
| + }
|
| + return prev;
|
| +}
|
| +
|
| +
|
| UsePosition* LiveRange::NextRegisterPosition(LifetimePosition start) {
|
| UsePosition* pos = NextUsePosition(start);
|
| while (pos != NULL && !pos->RequiresRegister()) {
|
| @@ -1936,6 +1948,39 @@ void LAllocator::AllocateBlockedReg(LiveRange* current) {
|
| }
|
|
|
|
|
| +LifetimePosition LAllocator::FindOptimalSpillingPos(LiveRange* range,
|
| + LifetimePosition pos) {
|
| + HBasicBlock* block = GetBlock(pos.InstructionStart());
|
| + HBasicBlock* loop_header =
|
| + block->IsLoopHeader() ? block : block->parent_loop_header();
|
| +
|
| + if (loop_header == NULL) return pos;
|
| +
|
| + UsePosition* prev_use =
|
| + range->PreviousUsePositionRegisterIsBeneficial(pos);
|
| +
|
| + while (loop_header != NULL) {
|
| + // We are going to spill live range inside the loop.
|
| + // If possible try to move spilling position backwards to loop header.
|
| + // This will reduce number of memory moves on the back edge.
|
| + LifetimePosition loop_start = LifetimePosition::FromInstructionIndex(
|
| + loop_header->first_instruction_index());
|
| +
|
| + if (range->Covers(loop_start)) {
|
| + if (prev_use == NULL || prev_use->pos().Value() < loop_start.Value()) {
|
| + // No register beneficial use inside the loop before the pos.
|
| + pos = loop_start;
|
| + }
|
| + }
|
| +
|
| + // Try hoisting out to an outer loop.
|
| + loop_header = loop_header->parent_loop_header();
|
| + }
|
| +
|
| + return pos;
|
| +}
|
| +
|
| +
|
| void LAllocator::SplitAndSpillIntersecting(LiveRange* current) {
|
| ASSERT(current->HasRegisterAssigned());
|
| int reg = current->assigned_register();
|
| @@ -1944,10 +1989,11 @@ void LAllocator::SplitAndSpillIntersecting(LiveRange* current) {
|
| LiveRange* range = active_live_ranges_[i];
|
| if (range->assigned_register() == reg) {
|
| UsePosition* next_pos = range->NextRegisterPosition(current->Start());
|
| + LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos);
|
| if (next_pos == NULL) {
|
| - SpillAfter(range, split_pos);
|
| + SpillAfter(range, spill_pos);
|
| } else {
|
| - SpillBetween(range, split_pos, next_pos->pos());
|
| + SpillBetween(range, spill_pos, next_pos->pos());
|
| }
|
| ActiveToHandled(range);
|
| --i;
|
|
|