Index: src/compiler/register-allocator.cc |
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc |
index a0cdec1cd71218584eeafff3b888fecaabe25711..33211c9017d2992197cd1a441308da2e9d53c063 100644 |
--- a/src/compiler/register-allocator.cc |
+++ b/src/compiler/register-allocator.cc |
@@ -165,6 +165,7 @@ void LiveRange::SpillAtDefinition(Zone* zone, int gap_index, |
void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence, |
InstructionOperand* op, |
bool might_be_duplicated) { |
+ DCHECK_IMPLIES(op->IsConstant(), spills_at_definition_ == nullptr); |
DCHECK(!IsChild()); |
auto zone = sequence->zone(); |
for (auto to_spill = spills_at_definition_; to_spill != nullptr; |
@@ -194,7 +195,7 @@ void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence, |
void LiveRange::SetSpillOperand(InstructionOperand* operand) { |
DCHECK(HasNoSpillType()); |
- DCHECK(!operand->IsUnallocated()); |
+ DCHECK(!operand->IsUnallocated() && !operand->IsImmediate()); |
spill_type_ = SpillType::kSpillOperand; |
spill_operand_ = operand; |
} |
@@ -208,9 +209,8 @@ void LiveRange::SetSpillRange(SpillRange* spill_range) { |
} |
-void LiveRange::CommitSpillOperand(InstructionOperand* operand) { |
+void LiveRange::CommitSpillOperand(AllocatedOperand* operand) { |
DCHECK(HasSpillRange()); |
- DCHECK(!operand->IsUnallocated()); |
DCHECK(!IsChild()); |
spill_type_ = SpillType::kSpillOperand; |
spill_operand_ = operand; |
@@ -274,9 +274,9 @@ InstructionOperand* LiveRange::GetAssignedOperand( |
DCHECK(!IsSpilled()); |
switch (Kind()) { |
case GENERAL_REGISTERS: |
- return cache->RegisterOperand(assigned_register()); |
+ return cache->GetRegisterOperand(assigned_register()); |
case DOUBLE_REGISTERS: |
- return cache->DoubleRegisterOperand(assigned_register()); |
+ return cache->GetDoubleRegisterOperand(assigned_register()); |
default: |
UNREACHABLE(); |
} |
@@ -537,14 +537,14 @@ void LiveRange::ConvertUsesToOperand(InstructionOperand* op, |
switch (pos->type()) { |
case UsePositionType::kRequiresSlot: |
if (spill_op != nullptr) { |
- pos->operand()->ConvertTo(spill_op->kind(), spill_op->index()); |
+ InstructionOperand::ReplaceWith(pos->operand(), spill_op); |
} |
break; |
case UsePositionType::kRequiresRegister: |
DCHECK(op->IsRegister() || op->IsDoubleRegister()); |
// Fall through. |
case UsePositionType::kAny: |
- pos->operand()->ConvertTo(op->kind(), op->index()); |
+ InstructionOperand::ReplaceWith(pos->operand(), op); |
break; |
} |
} |
@@ -599,12 +599,10 @@ LifetimePosition LiveRange::FirstIntersection(LiveRange* other) { |
InstructionOperandCache::InstructionOperandCache() { |
for (size_t i = 0; i < arraysize(general_register_operands_); ++i) { |
- general_register_operands_[i] = |
- i::compiler::RegisterOperand(static_cast<int>(i)); |
+ general_register_operands_[i] = RegisterOperand(static_cast<int>(i)); |
} |
for (size_t i = 0; i < arraysize(double_register_operands_); ++i) { |
- double_register_operands_[i] = |
- i::compiler::DoubleRegisterOperand(static_cast<int>(i)); |
+ double_register_operands_[i] = DoubleRegisterOperand(static_cast<int>(i)); |
} |
} |
@@ -707,18 +705,20 @@ InstructionOperand* RegisterAllocator::AllocateFixed( |
UnallocatedOperand* operand, int pos, bool is_tagged) { |
TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); |
DCHECK(operand->HasFixedPolicy()); |
+ InstructionOperand allocated; |
if (operand->HasFixedSlotPolicy()) { |
- operand->ConvertTo(InstructionOperand::STACK_SLOT, |
- operand->fixed_slot_index()); |
+ allocated = AllocatedOperand(InstructionOperand::STACK_SLOT, |
+ operand->fixed_slot_index()); |
} else if (operand->HasFixedRegisterPolicy()) { |
- int reg_index = operand->fixed_register_index(); |
- operand->ConvertTo(InstructionOperand::REGISTER, reg_index); |
+ allocated = AllocatedOperand(InstructionOperand::REGISTER, |
+ operand->fixed_register_index()); |
} else if (operand->HasFixedDoubleRegisterPolicy()) { |
- int reg_index = operand->fixed_register_index(); |
- operand->ConvertTo(InstructionOperand::DOUBLE_REGISTER, reg_index); |
+ allocated = AllocatedOperand(InstructionOperand::DOUBLE_REGISTER, |
+ operand->fixed_register_index()); |
} else { |
UNREACHABLE(); |
} |
+ InstructionOperand::ReplaceWith(operand, &allocated); |
if (is_tagged) { |
TRACE("Fixed reg is tagged at %d\n", pos); |
auto instr = InstructionAt(pos); |
@@ -789,11 +789,12 @@ LiveRange* RegisterAllocator::LiveRangeFor(InstructionOperand* operand) { |
if (operand->IsUnallocated()) { |
return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register()); |
} else if (operand->IsConstant()) { |
- return LiveRangeFor(ConstantOperand::cast(operand)->index()); |
+ return LiveRangeFor(ConstantOperand::cast(operand)->virtual_register()); |
} else if (operand->IsRegister()) { |
- return FixedLiveRangeFor(operand->index()); |
+ return FixedLiveRangeFor(RegisterOperand::cast(operand)->index()); |
} else if (operand->IsDoubleRegister()) { |
- return FixedDoubleLiveRangeFor(operand->index()); |
+ return FixedDoubleLiveRangeFor( |
+ DoubleRegisterOperand::cast(operand)->index()); |
} else { |
return nullptr; |
} |
@@ -922,7 +923,7 @@ bool SpillRange::TryMerge(SpillRange* other) { |
} |
-void SpillRange::SetOperand(InstructionOperand* op) { |
+void SpillRange::SetOperand(AllocatedOperand* op) { |
for (auto range : live_ranges()) { |
DCHECK(range->GetSpillRange() == this); |
range->CommitSpillOperand(op); |
@@ -977,7 +978,7 @@ void RegisterAllocator::AssignSpillSlots() { |
auto op_kind = kind == DOUBLE_REGISTERS |
? InstructionOperand::DOUBLE_STACK_SLOT |
: InstructionOperand::STACK_SLOT; |
- auto op = InstructionOperand::New(code_zone(), op_kind, index); |
+ auto op = AllocatedOperand::New(code_zone(), op_kind, index); |
range->SetOperand(op); |
} |
} |
@@ -1117,8 +1118,9 @@ void RegisterAllocator::MeetRegisterConstraintsForLastInstructionInBlock( |
AllocateFixed(output, -1, false); |
// This value is produced on the stack, we never need to spill it. |
if (output->IsStackSlot()) { |
- DCHECK(output->index() < frame_->GetSpillSlotCount()); |
- range->SetSpillOperand(output); |
+ DCHECK(StackSlotOperand::cast(output)->index() < |
+ frame_->GetSpillSlotCount()); |
+ range->SetSpillOperand(StackSlotOperand::cast(output)); |
range->SetSpillStartIndex(end); |
assigned = true; |
} |
@@ -1160,7 +1162,7 @@ void RegisterAllocator::MeetConstraintsAfter(int instr_index) { |
for (size_t i = 0; i < first->OutputCount(); i++) { |
InstructionOperand* output = first->OutputAt(i); |
if (output->IsConstant()) { |
- int output_vreg = output->index(); |
+ int output_vreg = ConstantOperand::cast(output)->virtual_register(); |
auto range = LiveRangeFor(output_vreg); |
range->SetSpillStartIndex(instr_index + 1); |
range->SetSpillOperand(output); |
@@ -1176,8 +1178,9 @@ void RegisterAllocator::MeetConstraintsAfter(int instr_index) { |
// This value is produced on the stack, we never need to spill it. |
if (first_output->IsStackSlot()) { |
- DCHECK(first_output->index() < frame_->GetSpillSlotCount()); |
- range->SetSpillOperand(first_output); |
+ DCHECK(StackSlotOperand::cast(first_output)->index() < |
+ frame_->GetSpillSlotCount()); |
+ range->SetSpillOperand(StackSlotOperand::cast(first_output)); |
range->SetSpillStartIndex(instr_index + 1); |
assigned = true; |
} |
@@ -1241,7 +1244,8 @@ void RegisterAllocator::MeetConstraintsBefore(int instr_index) { |
bool RegisterAllocator::IsOutputRegisterOf(Instruction* instr, int index) { |
for (size_t i = 0; i < instr->OutputCount(); i++) { |
auto output = instr->OutputAt(i); |
- if (output->IsRegister() && output->index() == index) return true; |
+ if (output->IsRegister() && RegisterOperand::cast(output)->index() == index) |
+ return true; |
} |
return false; |
} |
@@ -1251,7 +1255,9 @@ bool RegisterAllocator::IsOutputDoubleRegisterOf(Instruction* instr, |
int index) { |
for (size_t i = 0; i < instr->OutputCount(); i++) { |
auto output = instr->OutputAt(i); |
- if (output->IsDoubleRegister() && output->index() == index) return true; |
+ if (output->IsDoubleRegister() && |
+ DoubleRegisterOperand::cast(output)->index() == index) |
+ return true; |
} |
return false; |
} |
@@ -1279,7 +1285,7 @@ void RegisterAllocator::ProcessInstructions(const InstructionBlock* block, |
int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); |
live->Remove(out_vreg); |
} else if (output->IsConstant()) { |
- int out_vreg = output->index(); |
+ int out_vreg = ConstantOperand::cast(output)->virtual_register(); |
live->Remove(out_vreg); |
} |
Define(curr_position, output, nullptr); |
@@ -1367,7 +1373,6 @@ void RegisterAllocator::ProcessInstructions(const InstructionBlock* block, |
int to_vreg = UnallocatedOperand::cast(to)->virtual_register(); |
auto to_range = LiveRangeFor(to_vreg); |
if (to_range->is_phi()) { |
- DCHECK(!FLAG_turbo_delay_ssa_decon); |
if (to_range->is_non_loop_phi()) { |
hint = to_range->current_hint_operand(); |
} |
@@ -1401,15 +1406,13 @@ void RegisterAllocator::ResolvePhis(const InstructionBlock* block) { |
DCHECK(res.second); |
USE(res); |
auto& output = phi->output(); |
- if (!FLAG_turbo_delay_ssa_decon) { |
- for (size_t i = 0; i < phi->operands().size(); ++i) { |
- InstructionBlock* cur_block = |
- code()->InstructionBlockAt(block->predecessors()[i]); |
- AddGapMove(cur_block->last_instruction_index(), Instruction::END, |
- &phi->inputs()[i], &output); |
- DCHECK(!InstructionAt(cur_block->last_instruction_index()) |
- ->HasPointerMap()); |
- } |
+ for (size_t i = 0; i < phi->operands().size(); ++i) { |
+ InstructionBlock* cur_block = |
+ code()->InstructionBlockAt(block->predecessors()[i]); |
+ AddGapMove(cur_block->last_instruction_index(), Instruction::END, |
+ &phi->inputs()[i], &output); |
+ DCHECK( |
+ !InstructionAt(cur_block->last_instruction_index())->HasPointerMap()); |
} |
auto live_range = LiveRangeFor(phi_vreg); |
int gap_index = block->first_instruction_index(); |
@@ -1664,27 +1667,6 @@ void RegisterAllocator::ResolveControlFlow() { |
LiveRangeFinder finder(*this); |
for (auto block : code()->instruction_blocks()) { |
if (CanEagerlyResolveControlFlow(block)) continue; |
- if (FLAG_turbo_delay_ssa_decon) { |
- // resolve phis |
- for (auto phi : block->phis()) { |
- auto* block_bound = |
- finder.ArrayFor(phi->virtual_register())->FindSucc(block); |
- auto phi_output = |
- block_bound->range_->GetAssignedOperand(operand_cache()); |
- phi->output().ConvertTo(phi_output->kind(), phi_output->index()); |
- size_t pred_index = 0; |
- for (auto pred : block->predecessors()) { |
- const InstructionBlock* pred_block = code()->InstructionBlockAt(pred); |
- auto* pred_bound = finder.ArrayFor(phi->operands()[pred_index]) |
- ->FindPred(pred_block); |
- auto pred_op = |
- pred_bound->range_->GetAssignedOperand(operand_cache()); |
- phi->inputs()[pred_index] = *pred_op; |
- ResolveControlFlow(block, phi_output, pred_block, pred_op); |
- pred_index++; |
- } |
- } |
- } |
auto live = live_in_sets_[block->rpo_number().ToInt()]; |
BitVector::Iterator iterator(live); |
while (!iterator.Done()) { |
@@ -1745,26 +1727,24 @@ void RegisterAllocator::BuildLiveRanges() { |
// block. |
int phi_vreg = phi->virtual_register(); |
live->Remove(phi_vreg); |
- if (!FLAG_turbo_delay_ssa_decon) { |
- InstructionOperand* hint = nullptr; |
- InstructionOperand* phi_operand = nullptr; |
- auto instr = GetLastInstruction( |
- code()->InstructionBlockAt(block->predecessors()[0])); |
- auto move = instr->GetParallelMove(Instruction::END); |
- for (int j = 0; j < move->move_operands()->length(); ++j) { |
- auto to = move->move_operands()->at(j).destination(); |
- if (to->IsUnallocated() && |
- UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) { |
- hint = move->move_operands()->at(j).source(); |
- phi_operand = to; |
- break; |
- } |
+ InstructionOperand* hint = nullptr; |
+ InstructionOperand* phi_operand = nullptr; |
+ auto instr = GetLastInstruction( |
+ code()->InstructionBlockAt(block->predecessors()[0])); |
+ auto move = instr->GetParallelMove(Instruction::END); |
+ for (int j = 0; j < move->move_operands()->length(); ++j) { |
+ auto to = move->move_operands()->at(j).destination(); |
+ if (to->IsUnallocated() && |
+ UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) { |
+ hint = move->move_operands()->at(j).source(); |
+ phi_operand = to; |
+ break; |
} |
- DCHECK(hint != nullptr); |
- auto block_start = LifetimePosition::GapFromInstructionIndex( |
- block->first_instruction_index()); |
- Define(block_start, phi_operand, hint); |
} |
+ DCHECK(hint != nullptr); |
+ auto block_start = LifetimePosition::GapFromInstructionIndex( |
+ block->first_instruction_index()); |
+ Define(block_start, phi_operand, hint); |
} |
// Now live is live_in for this block except not including values live |
@@ -2184,7 +2164,7 @@ bool RegisterAllocator::TryAllocateFreeReg(LiveRange* current) { |
auto hint = current->FirstHint(); |
if (hint != nullptr && (hint->IsRegister() || hint->IsDoubleRegister())) { |
- int register_index = hint->index(); |
+ int register_index = AllocatedOperand::cast(hint)->index(); |
TRACE("Found reg hint %s (free until [%d) for live range %d (end %d[).\n", |
RegisterName(register_index), free_until_pos[register_index].Value(), |
current->id(), current->End().Value()); |