| Index: src/compiler/register-allocator.cc
|
| diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
|
| index c96a7e94f7fe333ecb78d546b27d90a40f012ba6..cff644d24c9c42167c62b4ed2b37191511256e71 100644
|
| --- a/src/compiler/register-allocator.cc
|
| +++ b/src/compiler/register-allocator.cc
|
| @@ -69,6 +69,11 @@ bool IsBlockBoundary(const InstructionSequence* code, LifetimePosition pos) {
|
| }
|
|
|
|
|
| +Instruction* GetLastInstruction(InstructionSequence* code,
|
| + const InstructionBlock* block) {
|
| + return code->InstructionAt(block->last_instruction_index());
|
| +}
|
| +
|
| } // namespace
|
|
|
|
|
| @@ -833,67 +838,12 @@ void RegisterAllocationData::SetLiveRangeAssignedRegister(LiveRange* range,
|
| }
|
|
|
|
|
| -LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data)
|
| +ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data)
|
| : data_(data) {}
|
|
|
|
|
| -BitVector* LiveRangeBuilder::ComputeLiveOut(const InstructionBlock* block) {
|
| - // Compute live out for the given block, except not including backward
|
| - // successor edges.
|
| - auto live_out = new (allocation_zone())
|
| - BitVector(code()->VirtualRegisterCount(), allocation_zone());
|
| -
|
| - // Process all successor blocks.
|
| - for (auto succ : block->successors()) {
|
| - // Add values live on entry to the successor. Note the successor's
|
| - // live_in will not be computed yet for backwards edges.
|
| - auto live_in = live_in_sets()[succ.ToSize()];
|
| - if (live_in != nullptr) live_out->Union(*live_in);
|
| -
|
| - // All phi input operands corresponding to this successor edge are live
|
| - // out from this block.
|
| - auto successor = code()->InstructionBlockAt(succ);
|
| - size_t index = successor->PredecessorIndexOf(block->rpo_number());
|
| - DCHECK(index < successor->PredecessorCount());
|
| - for (auto phi : successor->phis()) {
|
| - live_out->Add(phi->operands()[index]);
|
| - }
|
| - }
|
| - return live_out;
|
| -}
|
| -
|
| -
|
| -void LiveRangeBuilder::AddInitialIntervals(const InstructionBlock* block,
|
| - BitVector* live_out) {
|
| - // Add an interval that includes the entire block to the live range for
|
| - // each live_out value.
|
| - auto start = LifetimePosition::GapFromInstructionIndex(
|
| - block->first_instruction_index());
|
| - auto end = LifetimePosition::InstructionFromInstructionIndex(
|
| - block->last_instruction_index()).NextStart();
|
| - BitVector::Iterator iterator(live_out);
|
| - while (!iterator.Done()) {
|
| - int operand_index = iterator.Current();
|
| - auto range = LiveRangeFor(operand_index);
|
| - range->AddUseInterval(start, end, allocation_zone());
|
| - iterator.Advance();
|
| - }
|
| -}
|
| -
|
| -
|
| -Instruction* LiveRangeBuilder::GetLastInstruction(
|
| - const InstructionBlock* block) {
|
| - return code()->InstructionAt(block->last_instruction_index());
|
| -}
|
| -
|
| -
|
| -int LiveRangeBuilder::FixedDoubleLiveRangeID(int index) {
|
| - return -index - 1 - config()->num_general_registers();
|
| -}
|
| -
|
| -
|
| -InstructionOperand* LiveRangeBuilder::AllocateFixed(UnallocatedOperand* operand,
|
| - int pos, bool is_tagged) {
|
| +InstructionOperand* ConstraintBuilder::AllocateFixed(
|
| + UnallocatedOperand* operand, int pos, bool is_tagged) {
|
| TRACE("Allocating fixed reg for op %d\n", operand->virtual_register());
|
| DCHECK(operand->HasFixedPolicy());
|
| InstructionOperand allocated;
|
| @@ -921,87 +871,14 @@ InstructionOperand* LiveRangeBuilder::AllocateFixed(UnallocatedOperand* operand,
|
| }
|
|
|
|
|
| -LiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
|
| - DCHECK(index < config()->num_general_registers());
|
| - auto result = fixed_live_ranges()[index];
|
| - if (result == nullptr) {
|
| - result = data()->NewLiveRange(FixedLiveRangeID(index));
|
| - DCHECK(result->IsFixed());
|
| - result->set_kind(GENERAL_REGISTERS);
|
| - data()->SetLiveRangeAssignedRegister(result, index);
|
| - fixed_live_ranges()[index] = result;
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -
|
| -LiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) {
|
| - DCHECK(index < config()->num_aliased_double_registers());
|
| - auto result = fixed_double_live_ranges()[index];
|
| - if (result == nullptr) {
|
| - result = data()->NewLiveRange(FixedDoubleLiveRangeID(index));
|
| - DCHECK(result->IsFixed());
|
| - result->set_kind(DOUBLE_REGISTERS);
|
| - data()->SetLiveRangeAssignedRegister(result, index);
|
| - fixed_double_live_ranges()[index] = result;
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -
|
| -LiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
|
| - if (operand->IsUnallocated()) {
|
| - return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register());
|
| - } else if (operand->IsConstant()) {
|
| - return LiveRangeFor(ConstantOperand::cast(operand)->virtual_register());
|
| - } else if (operand->IsRegister()) {
|
| - return FixedLiveRangeFor(RegisterOperand::cast(operand)->index());
|
| - } else if (operand->IsDoubleRegister()) {
|
| - return FixedDoubleLiveRangeFor(
|
| - DoubleRegisterOperand::cast(operand)->index());
|
| - } else {
|
| - return nullptr;
|
| - }
|
| -}
|
| -
|
| -
|
| -void LiveRangeBuilder::Define(LifetimePosition position,
|
| - InstructionOperand* operand,
|
| - InstructionOperand* hint) {
|
| - auto range = LiveRangeFor(operand);
|
| - if (range == nullptr) return;
|
| -
|
| - if (range->IsEmpty() || range->Start().Value() > position.Value()) {
|
| - // Can happen if there is a definition without use.
|
| - range->AddUseInterval(position, position.NextStart(), allocation_zone());
|
| - range->AddUsePosition(position.NextStart(), nullptr, nullptr,
|
| - allocation_zone());
|
| - } else {
|
| - range->ShortenTo(position);
|
| - }
|
| -
|
| - if (operand->IsUnallocated()) {
|
| - auto unalloc_operand = UnallocatedOperand::cast(operand);
|
| - range->AddUsePosition(position, unalloc_operand, hint, allocation_zone());
|
| - }
|
| -}
|
| -
|
| -
|
| -void LiveRangeBuilder::Use(LifetimePosition block_start,
|
| - LifetimePosition position,
|
| - InstructionOperand* operand,
|
| - InstructionOperand* hint) {
|
| - auto range = LiveRangeFor(operand);
|
| - if (range == nullptr) return;
|
| - if (operand->IsUnallocated()) {
|
| - UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand);
|
| - range->AddUsePosition(position, unalloc_operand, hint, allocation_zone());
|
| +void ConstraintBuilder::MeetRegisterConstraints() {
|
| + for (auto block : code()->instruction_blocks()) {
|
| + MeetRegisterConstraints(block);
|
| }
|
| - range->AddUseInterval(block_start, position, allocation_zone());
|
| }
|
|
|
|
|
| -void LiveRangeBuilder::MeetRegisterConstraints(const InstructionBlock* block) {
|
| +void ConstraintBuilder::MeetRegisterConstraints(const InstructionBlock* block) {
|
| int start = block->first_instruction_index();
|
| int end = block->last_instruction_index();
|
| DCHECK_NE(-1, start);
|
| @@ -1014,7 +891,7 @@ void LiveRangeBuilder::MeetRegisterConstraints(const InstructionBlock* block) {
|
| }
|
|
|
|
|
| -void LiveRangeBuilder::MeetRegisterConstraintsForLastInstructionInBlock(
|
| +void ConstraintBuilder::MeetRegisterConstraintsForLastInstructionInBlock(
|
| const InstructionBlock* block) {
|
| int end = block->last_instruction_index();
|
| auto last_instruction = InstructionAt(end);
|
| @@ -1060,7 +937,7 @@ void LiveRangeBuilder::MeetRegisterConstraintsForLastInstructionInBlock(
|
| }
|
|
|
|
|
| -void LiveRangeBuilder::MeetConstraintsAfter(int instr_index) {
|
| +void ConstraintBuilder::MeetConstraintsAfter(int instr_index) {
|
| auto first = InstructionAt(instr_index);
|
| // Handle fixed temporaries.
|
| for (size_t i = 0; i < first->TempCount(); i++) {
|
| @@ -1108,7 +985,7 @@ void LiveRangeBuilder::MeetConstraintsAfter(int instr_index) {
|
| }
|
|
|
|
|
| -void LiveRangeBuilder::MeetConstraintsBefore(int instr_index) {
|
| +void ConstraintBuilder::MeetConstraintsBefore(int instr_index) {
|
| auto second = InstructionAt(instr_index);
|
| // Handle fixed input operands of second instruction.
|
| for (size_t i = 0; i < second->InputCount(); i++) {
|
| @@ -1153,6 +1030,177 @@ void LiveRangeBuilder::MeetConstraintsBefore(int instr_index) {
|
| }
|
|
|
|
|
| +void ConstraintBuilder::ResolvePhis() {
|
| + // Process the blocks in reverse order.
|
| + for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) {
|
| + ResolvePhis(block);
|
| + }
|
| +}
|
| +
|
| +
|
| +void ConstraintBuilder::ResolvePhis(const InstructionBlock* block) {
|
| + for (auto phi : block->phis()) {
|
| + int phi_vreg = phi->virtual_register();
|
| + auto map_value = new (allocation_zone())
|
| + RegisterAllocationData::PhiMapValue(phi, block, allocation_zone());
|
| + auto res = data()->phi_map().insert(std::make_pair(phi_vreg, map_value));
|
| + DCHECK(res.second);
|
| + USE(res);
|
| + auto& output = phi->output();
|
| + for (size_t i = 0; i < phi->operands().size(); ++i) {
|
| + InstructionBlock* cur_block =
|
| + code()->InstructionBlockAt(block->predecessors()[i]);
|
| + UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]);
|
| + auto move = data()->AddGapMove(cur_block->last_instruction_index(),
|
| + Instruction::END, input, output);
|
| + map_value->incoming_moves.push_back(move);
|
| + DCHECK(!InstructionAt(cur_block->last_instruction_index())
|
| + ->HasReferenceMap());
|
| + }
|
| + auto live_range = LiveRangeFor(phi_vreg);
|
| + int gap_index = block->first_instruction_index();
|
| + live_range->SpillAtDefinition(allocation_zone(), gap_index, &output);
|
| + live_range->SetSpillStartIndex(gap_index);
|
| + // We use the phi-ness of some nodes in some later heuristics.
|
| + live_range->set_is_phi(true);
|
| + live_range->set_is_non_loop_phi(!block->IsLoopHeader());
|
| + }
|
| +}
|
| +
|
| +
|
| +LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data)
|
| + : data_(data) {}
|
| +
|
| +
|
| +BitVector* LiveRangeBuilder::ComputeLiveOut(const InstructionBlock* block) {
|
| + // Compute live out for the given block, except not including backward
|
| + // successor edges.
|
| + auto live_out = new (allocation_zone())
|
| + BitVector(code()->VirtualRegisterCount(), allocation_zone());
|
| +
|
| + // Process all successor blocks.
|
| + for (auto succ : block->successors()) {
|
| + // Add values live on entry to the successor. Note the successor's
|
| + // live_in will not be computed yet for backwards edges.
|
| + auto live_in = live_in_sets()[succ.ToSize()];
|
| + if (live_in != nullptr) live_out->Union(*live_in);
|
| +
|
| + // All phi input operands corresponding to this successor edge are live
|
| + // out from this block.
|
| + auto successor = code()->InstructionBlockAt(succ);
|
| + size_t index = successor->PredecessorIndexOf(block->rpo_number());
|
| + DCHECK(index < successor->PredecessorCount());
|
| + for (auto phi : successor->phis()) {
|
| + live_out->Add(phi->operands()[index]);
|
| + }
|
| + }
|
| + return live_out;
|
| +}
|
| +
|
| +
|
| +void LiveRangeBuilder::AddInitialIntervals(const InstructionBlock* block,
|
| + BitVector* live_out) {
|
| + // Add an interval that includes the entire block to the live range for
|
| + // each live_out value.
|
| + auto start = LifetimePosition::GapFromInstructionIndex(
|
| + block->first_instruction_index());
|
| + auto end = LifetimePosition::InstructionFromInstructionIndex(
|
| + block->last_instruction_index()).NextStart();
|
| + BitVector::Iterator iterator(live_out);
|
| + while (!iterator.Done()) {
|
| + int operand_index = iterator.Current();
|
| + auto range = LiveRangeFor(operand_index);
|
| + range->AddUseInterval(start, end, allocation_zone());
|
| + iterator.Advance();
|
| + }
|
| +}
|
| +
|
| +
|
| +int LiveRangeBuilder::FixedDoubleLiveRangeID(int index) {
|
| + return -index - 1 - config()->num_general_registers();
|
| +}
|
| +
|
| +
|
| +LiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
|
| + DCHECK(index < config()->num_general_registers());
|
| + auto result = data()->fixed_live_ranges()[index];
|
| + if (result == nullptr) {
|
| + result = data()->NewLiveRange(FixedLiveRangeID(index));
|
| + DCHECK(result->IsFixed());
|
| + result->set_kind(GENERAL_REGISTERS);
|
| + data()->SetLiveRangeAssignedRegister(result, index);
|
| + data()->fixed_live_ranges()[index] = result;
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +
|
| +LiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) {
|
| + DCHECK(index < config()->num_aliased_double_registers());
|
| + auto result = data()->fixed_double_live_ranges()[index];
|
| + if (result == nullptr) {
|
| + result = data()->NewLiveRange(FixedDoubleLiveRangeID(index));
|
| + DCHECK(result->IsFixed());
|
| + result->set_kind(DOUBLE_REGISTERS);
|
| + data()->SetLiveRangeAssignedRegister(result, index);
|
| + data()->fixed_double_live_ranges()[index] = result;
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +
|
| +LiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
|
| + if (operand->IsUnallocated()) {
|
| + return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register());
|
| + } else if (operand->IsConstant()) {
|
| + return LiveRangeFor(ConstantOperand::cast(operand)->virtual_register());
|
| + } else if (operand->IsRegister()) {
|
| + return FixedLiveRangeFor(RegisterOperand::cast(operand)->index());
|
| + } else if (operand->IsDoubleRegister()) {
|
| + return FixedDoubleLiveRangeFor(
|
| + DoubleRegisterOperand::cast(operand)->index());
|
| + } else {
|
| + return nullptr;
|
| + }
|
| +}
|
| +
|
| +
|
| +void LiveRangeBuilder::Define(LifetimePosition position,
|
| + InstructionOperand* operand,
|
| + InstructionOperand* hint) {
|
| + auto range = LiveRangeFor(operand);
|
| + if (range == nullptr) return;
|
| +
|
| + if (range->IsEmpty() || range->Start().Value() > position.Value()) {
|
| + // Can happen if there is a definition without use.
|
| + range->AddUseInterval(position, position.NextStart(), allocation_zone());
|
| + range->AddUsePosition(position.NextStart(), nullptr, nullptr,
|
| + allocation_zone());
|
| + } else {
|
| + range->ShortenTo(position);
|
| + }
|
| +
|
| + if (operand->IsUnallocated()) {
|
| + auto unalloc_operand = UnallocatedOperand::cast(operand);
|
| + range->AddUsePosition(position, unalloc_operand, hint, allocation_zone());
|
| + }
|
| +}
|
| +
|
| +
|
| +void LiveRangeBuilder::Use(LifetimePosition block_start,
|
| + LifetimePosition position,
|
| + InstructionOperand* operand,
|
| + InstructionOperand* hint) {
|
| + auto range = LiveRangeFor(operand);
|
| + if (range == nullptr) return;
|
| + if (operand->IsUnallocated()) {
|
| + UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand);
|
| + range->AddUsePosition(position, unalloc_operand, hint, allocation_zone());
|
| + }
|
| + range->AddUseInterval(block_start, position, allocation_zone());
|
| +}
|
| +
|
| +
|
| bool LiveRangeBuilder::IsOutputRegisterOf(Instruction* instr, int index) {
|
| for (size_t i = 0; i < instr->OutputCount(); i++) {
|
| auto output = instr->OutputAt(i);
|
| @@ -1184,7 +1232,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
|
| index--) {
|
| auto curr_position =
|
| LifetimePosition::InstructionFromInstructionIndex(index);
|
| - auto instr = InstructionAt(index);
|
| + auto instr = code()->InstructionAt(index);
|
| DCHECK(instr != nullptr);
|
| DCHECK(curr_position.IsInstructionPosition());
|
| // Process output, inputs, and temps of this instruction.
|
| @@ -1308,51 +1356,6 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
|
| }
|
|
|
|
|
| -void LiveRangeBuilder::ResolvePhis(const InstructionBlock* block) {
|
| - for (auto phi : block->phis()) {
|
| - int phi_vreg = phi->virtual_register();
|
| - auto map_value = new (allocation_zone())
|
| - RegisterAllocationData::PhiMapValue(phi, block, allocation_zone());
|
| - auto res = phi_map().insert(std::make_pair(phi_vreg, map_value));
|
| - DCHECK(res.second);
|
| - USE(res);
|
| - auto& output = phi->output();
|
| - for (size_t i = 0; i < phi->operands().size(); ++i) {
|
| - InstructionBlock* cur_block =
|
| - code()->InstructionBlockAt(block->predecessors()[i]);
|
| - UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]);
|
| - auto move = data()->AddGapMove(cur_block->last_instruction_index(),
|
| - Instruction::END, input, output);
|
| - map_value->incoming_moves.push_back(move);
|
| - DCHECK(!InstructionAt(cur_block->last_instruction_index())
|
| - ->HasReferenceMap());
|
| - }
|
| - auto live_range = LiveRangeFor(phi_vreg);
|
| - int gap_index = block->first_instruction_index();
|
| - live_range->SpillAtDefinition(allocation_zone(), gap_index, &output);
|
| - live_range->SetSpillStartIndex(gap_index);
|
| - // We use the phi-ness of some nodes in some later heuristics.
|
| - live_range->set_is_phi(true);
|
| - live_range->set_is_non_loop_phi(!block->IsLoopHeader());
|
| - }
|
| -}
|
| -
|
| -
|
| -void LiveRangeBuilder::MeetRegisterConstraints() {
|
| - for (auto block : code()->instruction_blocks()) {
|
| - MeetRegisterConstraints(block);
|
| - }
|
| -}
|
| -
|
| -
|
| -void LiveRangeBuilder::ResolvePhis() {
|
| - // Process the blocks in reverse order.
|
| - for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) {
|
| - ResolvePhis(block);
|
| - }
|
| -}
|
| -
|
| -
|
| void LiveRangeBuilder::BuildLiveRanges() {
|
| // Process the blocks in reverse order.
|
| for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0;
|
| @@ -1374,7 +1377,7 @@ void LiveRangeBuilder::BuildLiveRanges() {
|
| live->Remove(phi_vreg);
|
| InstructionOperand* hint = nullptr;
|
| auto instr = GetLastInstruction(
|
| - code()->InstructionBlockAt(block->predecessors()[0]));
|
| + code(), code()->InstructionBlockAt(block->predecessors()[0]));
|
| for (auto move : *instr->GetParallelMove(Instruction::END)) {
|
| auto& to = move->destination();
|
| if (to.IsUnallocated() &&
|
| @@ -1415,7 +1418,7 @@ void LiveRangeBuilder::BuildLiveRanges() {
|
| }
|
| }
|
|
|
| - for (auto range : live_ranges()) {
|
| + for (auto range : data()->live_ranges()) {
|
| if (range == nullptr) continue;
|
| range->set_kind(RequiredRegisterKind(range->id()));
|
| // Give slots to all ranges with a non fixed slot use.
|
| @@ -1474,14 +1477,16 @@ LinearScanAllocator::LinearScanAllocator(RegisterAllocationData* data,
|
| // TryAllocateFreeReg and AllocateBlockedReg assume this
|
| // when allocating local arrays.
|
| DCHECK(RegisterConfiguration::kMaxDoubleRegisters >=
|
| - config()->num_general_registers());
|
| + this->data()->config()->num_general_registers());
|
| }
|
|
|
|
|
| void LinearScanAllocator::AllocateRegisters() {
|
| DCHECK(unhandled_live_ranges().empty());
|
| + DCHECK(active_live_ranges().empty());
|
| + DCHECK(inactive_live_ranges().empty());
|
|
|
| - for (auto range : live_ranges()) {
|
| + for (auto range : data()->live_ranges()) {
|
| if (range == nullptr) continue;
|
| if (range->Kind() == mode_) {
|
| AddToUnhandledUnsorted(range);
|
| @@ -1490,9 +1495,6 @@ void LinearScanAllocator::AllocateRegisters() {
|
| SortUnhandled();
|
| DCHECK(UnhandledIsSorted());
|
|
|
| - DCHECK(active_live_ranges().empty());
|
| - DCHECK(inactive_live_ranges().empty());
|
| -
|
| auto& fixed_ranges = GetFixedRegisters(data(), mode_);
|
| for (auto current : fixed_ranges) {
|
| if (current != nullptr) {
|
| @@ -1565,17 +1567,14 @@ void LinearScanAllocator::AllocateRegisters() {
|
| AddToActive(current);
|
| }
|
| }
|
| -
|
| - active_live_ranges().clear();
|
| - inactive_live_ranges().clear();
|
| }
|
|
|
|
|
| const char* LinearScanAllocator::RegisterName(int allocation_index) const {
|
| if (mode_ == GENERAL_REGISTERS) {
|
| - return config()->general_register_name(allocation_index);
|
| + return data()->config()->general_register_name(allocation_index);
|
| } else {
|
| - return config()->double_register_name(allocation_index);
|
| + return data()->config()->double_register_name(allocation_index);
|
| }
|
| }
|
|
|
| @@ -1910,8 +1909,8 @@ bool LinearScanAllocator::TryReuseSpillForPhi(LiveRange* range) {
|
| if (range->IsChild() || !range->is_phi()) return false;
|
| DCHECK(!range->HasSpillOperand());
|
|
|
| - auto lookup = phi_map().find(range->id());
|
| - DCHECK(lookup != phi_map().end());
|
| + auto lookup = data()->phi_map().find(range->id());
|
| + DCHECK(lookup != data()->phi_map().end());
|
| auto phi = lookup->second->phi;
|
| auto block = lookup->second->block;
|
| // Count the number of spilled operands.
|
| @@ -2190,7 +2189,7 @@ void ReferenceMapPopulator::PopulateReferenceMaps() {
|
| // Iterate over the first parts of multi-part live ranges.
|
| if (range->IsChild()) continue;
|
| // Skip non-reference values.
|
| - if (!IsReference(range->id())) continue;
|
| + if (!data()->IsReference(range->id())) continue;
|
| // Skip empty live ranges.
|
| if (range->IsEmpty()) continue;
|
|
|
| @@ -2444,7 +2443,7 @@ void LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block,
|
| position = Instruction::START;
|
| } else {
|
| DCHECK(pred->SuccessorCount() == 1);
|
| - DCHECK(!data()
|
| + DCHECK(!code()
|
| ->InstructionAt(pred->last_instruction_index())
|
| ->HasReferenceMap());
|
| gap_index = pred->last_instruction_index();
|
|
|