}
+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()) {
}
+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();
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());
}
if (!AllocationOk()) return;
ActiveToHandled(range);
// Modifies internal state of live range!
UsePosition* NextUsePositionRegisterIsBeneficial(LifetimePosition start);
+ // Returns use position for which register is beneficial in this live
+ // range and which precedes start.
+ UsePosition* PreviousUsePositionRegisterIsBeneficial(LifetimePosition start);
+
// Can this live range be spilled at this position.
bool CanBeSpilled(LifetimePosition pos);
void SplitAndSpillIntersecting(LiveRange* range);
+ // If we are trying to spill a range inside the loop try to
+ // hoist spill position out to the point just before the loop.
+ LifetimePosition FindOptimalSpillingPos(LiveRange* range,
+ LifetimePosition pos);
+
void Spill(LiveRange* range);
bool IsBlockBoundary(LifetimePosition pos);