Chromium Code Reviews| Index: runtime/vm/flow_graph_allocator.cc |
| diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc |
| index 03723f4912b0a70c648e673e53fe4dd1be3c053b..02bef2e090a72f12a6f3576196aa7a2536c8a28d 100644 |
| --- a/runtime/vm/flow_graph_allocator.cc |
| +++ b/runtime/vm/flow_graph_allocator.cc |
| @@ -510,6 +510,19 @@ static bool HasOnlyUnconstrainedUsesInLoop(LiveRange* range, |
| } |
| +// Returns true if all uses of the given range have Any allocation policy. |
| +static bool HasOnlyUnconstrainedUses(LiveRange* range) { |
| + UsePosition* use = range->first_use(); |
| + while (use != NULL) { |
| + if (!use->location_slot()->Equals(Location::Any())) { |
| + return false; |
| + } |
| + use = use->next(); |
| + } |
| + return true; |
| +} |
| + |
| + |
| void FlowGraphAllocator::BuildLiveRanges() { |
| const intptr_t block_count = postorder_.length(); |
| ASSERT(postorder_.Last()->IsGraphEntry()); |
| @@ -532,6 +545,10 @@ void FlowGraphAllocator::BuildLiveRanges() { |
| current_interference_set = |
| new BitVector(flow_graph_.max_virtual_register_number()); |
| ASSERT(loop_header->backedge_interference() == NULL); |
| + // All values flowing into the loop header are live at the back-edge and |
| + // can interfere with phi moves. |
| + current_interference_set->AddAll( |
| + live_in_[loop_header->entry()->postorder_number()]); |
| loop_header->set_backedge_interference( |
| current_interference_set); |
| } |
| @@ -828,13 +845,30 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, |
| LocationSummary* locs = current->locs(); |
| Definition* def = current->AsDefinition(); |
| - if ((def != NULL) && |
| - (def->AsConstant() != NULL) && |
| - ((def->ssa_temp_index() == -1) || |
| - (GetLiveRange(def->ssa_temp_index())->first_use() == NULL))) { |
| + if ((def != NULL) && (def->AsConstant() != NULL)) { |
| + LiveRange* range = (def->ssa_temp_index() != -1) ? |
| + GetLiveRange(def->ssa_temp_index()) : NULL; |
| + |
| // Drop definitions of constants that have no uses. |
| - locs->set_out(Location::NoLocation()); |
| - return; |
| + if ((range == NULL) || (range->first_use() == NULL)) { |
| + locs->set_out(Location::NoLocation()); |
| + return; |
| + } |
| + |
| + // If this constant has only unconstrained uses convert them all |
| + // to use the constant directly and drop this definition. |
| + // TODO(vegorov) improve allocation when we have enough registers to keep |
|
Florian Schneider
2013/03/21 13:17:06
insert : after the TODO(vegorov).
Vyacheslav Egorov (Google)
2013/03/22 11:30:35
Done.
|
| + // constants used in the loop in them. |
| + if (HasOnlyUnconstrainedUses(range)) { |
| + const Object& value = def->AsConstant()->value(); |
| + range->set_assigned_location(Location::Constant(value)); |
| + range->set_spill_slot(Location::Constant(value)); |
| + range->finger()->Initialize(range); |
| + ConvertAllUses(range); |
| + |
| + locs->set_out(Location::NoLocation()); |
| + return; |
| + } |
| } |
| const intptr_t pos = current->lifetime_position(); |
| @@ -1709,7 +1743,7 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) { |
| hint.Name(), |
| unallocated->vreg(), |
| free_until)); |
| - } else if (free_until != kMaxPosition) { |
| + } else { |
| for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { |
| if (!blocked_registers_[reg] && (registers_[reg].length() == 0)) { |
| candidate = reg; |
| @@ -1719,6 +1753,23 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) { |
| } |
| } |
| + ASSERT(0 <= kMaxPosition); |
| + if (free_until != kMaxPosition) { |
| + for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { |
| + if (blocked_registers_[reg] || (reg == candidate)) continue; |
| + const intptr_t intersection = |
| + FirstIntersectionWithAllocated(reg, unallocated); |
| + if (intersection > free_until) { |
| + candidate = reg; |
| + free_until = intersection; |
| + if (free_until == kMaxPosition) break; |
| + } |
| + } |
| + } |
| + |
| + // All registers are blocked by active ranges. |
| + if (free_until <= unallocated->Start()) return false; |
| + |
| // We have a very good candidate (either hinted to us or completely free). |
| // If we are in a loop try to reduce number of moves on the back edge by |
| // searching for a candidate that does not interfere with phis on the back |
| @@ -1778,23 +1829,6 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) { |
| } |
| } |
| - ASSERT(0 <= kMaxPosition); |
| - if (free_until != kMaxPosition) { |
| - for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { |
| - if (blocked_registers_[reg] || (reg == candidate)) continue; |
| - const intptr_t intersection = |
| - FirstIntersectionWithAllocated(reg, unallocated); |
| - if (intersection > free_until) { |
| - candidate = reg; |
| - free_until = intersection; |
| - if (free_until == kMaxPosition) break; |
| - } |
| - } |
| - } |
| - |
| - // All registers are blocked by active ranges. |
| - if (free_until <= unallocated->Start()) return false; |
| - |
| TRACE_ALLOC(OS::Print("assigning free register ")); |
| TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print()); |
| TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg())); |