| Index: runtime/vm/flow_graph_allocator.cc
|
| diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
|
| index 05eb238ec8756ef19b08835185c94ac49715e502..9c06671149811bbf73e88bbe8e835a290c452257 100644
|
| --- a/runtime/vm/flow_graph_allocator.cc
|
| +++ b/runtime/vm/flow_graph_allocator.cc
|
| @@ -351,9 +351,10 @@ LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() {
|
|
|
|
|
| // Block location from the start of the instruction to its end.
|
| -void FlowGraphAllocator::BlockLocation(Location loc, intptr_t pos) {
|
| +void FlowGraphAllocator::BlockLocation(Location loc,
|
| + intptr_t from,
|
| + intptr_t to) {
|
| ASSERT(loc.IsRegister());
|
| - ASSERT(IsInstructionStartPosition(pos));
|
| const Register reg = loc.reg();
|
| if (blocked_cpu_regs_[reg]) return;
|
| if (cpu_regs_[reg].length() == 0) {
|
| @@ -364,7 +365,7 @@ void FlowGraphAllocator::BlockLocation(Location loc, intptr_t pos) {
|
| temporaries_.Add(range);
|
| #endif
|
| }
|
| - cpu_regs_[reg][0]->AddUseInterval(pos, pos + 1);
|
| + cpu_regs_[reg][0]->AddUseInterval(from, to);
|
| }
|
|
|
|
|
| @@ -683,15 +684,15 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
|
| // Input is expected in a fixed register. Expected shape of
|
| // live ranges:
|
| //
|
| - // i i'
|
| + // j' i i'
|
| // value --*
|
| - // register [--)
|
| + // register [-----)
|
| //
|
| MoveOperands* move =
|
| - AddMoveAt(pos, *in_ref, Location::PrefersRegister());
|
| - BlockLocation(*in_ref, pos);
|
| - range->AddUseInterval(block->start_pos(), pos);
|
| - range->AddUse(pos, move->src_slot());
|
| + AddMoveAt(pos - 1, *in_ref, Location::PrefersRegister());
|
| + BlockLocation(*in_ref, pos - 1, pos + 1);
|
| + range->AddUseInterval(block->start_pos(), pos - 1);
|
| + range->AddUse(pos - 1, move->src_slot());
|
| } else {
|
| // Normal unallocated input. Expected shape of
|
| // live ranges:
|
| @@ -715,7 +716,7 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
|
|
|
| Location temp = locs->temp(j);
|
| if (temp.IsRegister()) {
|
| - BlockLocation(temp, pos);
|
| + BlockLocation(temp, pos, pos + 1);
|
| } else if (temp.IsUnallocated()) {
|
| LiveRange* range = MakeLiveRangeForTemporary();
|
| range->AddUseInterval(pos, pos + 1);
|
| @@ -736,7 +737,8 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
|
|
|
| for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) {
|
| BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)),
|
| - pos);
|
| + pos,
|
| + pos + 1);
|
| }
|
|
|
| #if defined(DEBUG)
|
| @@ -781,7 +783,7 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
|
| // register [--)
|
| // output [-------
|
| //
|
| - BlockLocation(*out, pos);
|
| + BlockLocation(*out, pos, pos + 1);
|
|
|
| if (range->vreg() == kTempVirtualRegister) return;
|
|
|
| @@ -1077,6 +1079,19 @@ UsePosition* AllocationFinger::FirstRegisterBeneficialUse(intptr_t after) {
|
| }
|
|
|
|
|
| +void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) {
|
| + if ((first_register_use_ != NULL) &&
|
| + (first_register_use_->pos() >= first_use_after_split_pos)) {
|
| + first_register_use_ = NULL;
|
| + }
|
| +
|
| + if ((first_register_beneficial_use_ != NULL) &&
|
| + (first_register_beneficial_use_->pos() >= first_use_after_split_pos)) {
|
| + first_register_beneficial_use_ = NULL;
|
| + }
|
| +}
|
| +
|
| +
|
| intptr_t UseInterval::Intersect(UseInterval* other) {
|
| if (this->start() <= other->start()) {
|
| if (other->start() < this->end()) return other->start();
|
| @@ -1118,7 +1133,6 @@ LiveRange* LiveRange::SplitAt(intptr_t split_pos) {
|
| interval = finger_.first_pending_use_interval();
|
| }
|
|
|
| - ASSERT(interval->start() < split_pos);
|
| ASSERT(split_pos < End());
|
|
|
| // Corner case. We need to start over to find previous interval.
|
| @@ -1180,6 +1194,11 @@ LiveRange* LiveRange::SplitAt(intptr_t split_pos) {
|
|
|
| last_use_interval_ = last_before_split;
|
| last_use_interval_->next_ = NULL;
|
| +
|
| + if (first_use_after_split != NULL) {
|
| + finger_.UpdateAfterSplit(first_use_after_split->pos());
|
| + }
|
| +
|
| return next_sibling_;
|
| }
|
|
|
| @@ -1429,7 +1448,7 @@ bool FlowGraphAllocator::UpdateFreeUntil(Register reg,
|
| allocated->finger()->first_pending_use_interval();
|
| if (first_pending_use_interval->Contains(start)) {
|
| // This is an active interval.
|
| - if (allocated->vreg() <= 0) {
|
| + if (allocated->vreg() < 0) {
|
| // This register blocked by an interval that
|
| // can't be spilled.
|
| return false;
|
| @@ -1808,6 +1827,21 @@ void FlowGraphAllocator::AllocateRegisters() {
|
| DumpLiveness();
|
| }
|
|
|
| + if (FLAG_print_ssa_liveranges) {
|
| + const Function& function = builder_->parsed_function().function();
|
| +
|
| + OS::Print("-- [before ssa allocator] ranges [%s] ---------\n",
|
| + function.ToFullyQualifiedCString());
|
| + PrintLiveRanges();
|
| + OS::Print("----------------------------------------------\n");
|
| +
|
| + OS::Print("-- [before ssa allocator] ir [%s] -------------\n",
|
| + function.ToFullyQualifiedCString());
|
| + FlowGraphPrinter printer(Function::Handle(), block_order_, true);
|
| + printer.PrintBlocks();
|
| + OS::Print("----------------------------------------------\n");
|
| + }
|
| +
|
| AllocateCPURegisters();
|
|
|
| ResolveControlFlow();
|
|
|