Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Unified Diff: src/compiler/register-allocator.cc

Issue 1103533002: [turbofan] remove hint aliasing (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/register-allocator.cc
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
index 28007d47fa11aadc60c0781e3793d76a13d39880..966128ac7221423691e48734de1f89c6fdc8992d 100644
--- a/src/compiler/register-allocator.cc
+++ b/src/compiler/register-allocator.cc
@@ -65,12 +65,37 @@ Instruction* GetLastInstruction(InstructionSequence* code,
return code->InstructionAt(block->last_instruction_index());
}
+
+bool IsOutputRegisterOf(Instruction* instr, int index) {
+ for (size_t i = 0; i < instr->OutputCount(); i++) {
+ auto output = instr->OutputAt(i);
+ if (output->IsRegister() &&
+ RegisterOperand::cast(output)->index() == index) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool IsOutputDoubleRegisterOf(Instruction* instr, int index) {
+ for (size_t i = 0; i < instr->OutputCount(); i++) {
+ auto output = instr->OutputAt(i);
+ if (output->IsDoubleRegister() &&
+ DoubleRegisterOperand::cast(output)->index() == index) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace
UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand,
- InstructionOperand* hint)
- : operand_(operand), hint_(hint), pos_(pos), next_(nullptr), flags_(0) {
+ void* hint, UsePositionHintType hint_type)
+ : operand_(operand), hint_(hint), next_(nullptr), pos_(pos), flags_(0) {
+ DCHECK_IMPLIES(hint == nullptr, hint_type == UsePositionHintType::kNone);
bool register_beneficial = true;
UsePositionType type = UsePositionType::kAny;
if (operand_ != nullptr && operand_->IsUnallocated()) {
@@ -84,14 +109,81 @@ UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand,
register_beneficial = !unalloc->HasAnyPolicy();
}
}
- flags_ = TypeField::encode(type) |
- RegisterBeneficialField::encode(register_beneficial);
+ flags_ = TypeField::encode(type) | HintTypeField::encode(hint_type) |
+ RegisterBeneficialField::encode(register_beneficial) |
+ AssignedRegisterField::encode(kUnassignedRegister);
DCHECK(pos_.IsValid());
}
bool UsePosition::HasHint() const {
- return hint_ != nullptr && !hint_->IsUnallocated();
+ int hint_register;
+ return HintRegister(&hint_register);
+}
+
+
+bool UsePosition::HintRegister(int* register_index) const {
+ if (hint_ == nullptr) return false;
+ switch (HintTypeField::decode(flags_)) {
+ case UsePositionHintType::kNone:
+ case UsePositionHintType::kUnresolved:
+ return false;
+ case UsePositionHintType::kUsePos: {
+ auto use_pos = reinterpret_cast<UsePosition*>(hint_);
+ int assigned_register = AssignedRegisterField::decode(use_pos->flags_);
+ if (assigned_register == kUnassignedRegister) return false;
+ *register_index = assigned_register;
+ return true;
+ }
+ case UsePositionHintType::kOperand: {
+ auto operand = reinterpret_cast<InstructionOperand*>(hint_);
+ int assigned_register = AllocatedOperand::cast(operand)->index();
+ *register_index = assigned_register;
+ return true;
+ }
+ case UsePositionHintType::kPhi: {
+ auto phi = reinterpret_cast<RegisterAllocationData::PhiMapValue*>(hint_);
+ int assigned_register = phi->assigned_register();
+ if (assigned_register == kUnassignedRegister) return false;
+ *register_index = assigned_register;
+ return true;
+ }
+ }
+ UNREACHABLE();
+ return false;
+}
+
+
+UsePositionHintType UsePosition::HintTypeForOperand(
+ const InstructionOperand& op) {
+ switch (op.kind()) {
+ case InstructionOperand::CONSTANT:
+ case InstructionOperand::IMMEDIATE:
+ return UsePositionHintType::kNone;
+ case InstructionOperand::UNALLOCATED:
+ return UsePositionHintType::kUnresolved;
+ case InstructionOperand::ALLOCATED:
+ switch (AllocatedOperand::cast(op).allocated_kind()) {
+ case AllocatedOperand::REGISTER:
+ case AllocatedOperand::DOUBLE_REGISTER:
+ return UsePositionHintType::kOperand;
+ case AllocatedOperand::STACK_SLOT:
+ case AllocatedOperand::DOUBLE_STACK_SLOT:
+ return UsePositionHintType::kNone;
+ }
+ case InstructionOperand::INVALID:
+ break;
+ }
+ UNREACHABLE();
+ return UsePositionHintType::kNone;
+}
+
+
+void UsePosition::ResolveHint(UsePosition* use_pos) {
+ DCHECK_NOT_NULL(use_pos);
+ if (HintTypeField::decode(flags_) != UsePositionHintType::kUnresolved) return;
+ hint_ = use_pos;
+ flags_ = HintTypeField::update(flags_, UsePositionHintType::kUsePos);
}
@@ -129,7 +221,7 @@ LiveRange::LiveRange(int id)
is_phi_(false),
is_non_loop_phi_(false),
kind_(UNALLOCATED_REGISTERS),
- assigned_register_(kInvalidAssignment),
+ assigned_register_(kUnassignedRegister),
last_interval_(nullptr),
first_interval_(nullptr),
first_pos_(nullptr),
@@ -137,7 +229,7 @@ LiveRange::LiveRange(int id)
next_(nullptr),
current_interval_(nullptr),
last_processed_use_(nullptr),
- current_hint_operand_(nullptr),
+ current_hint_position_(nullptr),
spill_start_index_(kMaxInt),
spill_type_(SpillType::kNoSpillType),
spill_operand_(nullptr),
@@ -165,11 +257,17 @@ void LiveRange::set_assigned_register(int reg) {
}
+void LiveRange::UnsetAssignedRegister() {
+ DCHECK(HasRegisterAssigned() && !IsSpilled());
+ assigned_register_ = kUnassignedRegister;
+}
+
+
void LiveRange::MakeSpilled() {
DCHECK(!IsSpilled());
DCHECK(!TopLevel()->HasNoSpillType());
spilled_ = true;
- assigned_register_ = kInvalidAssignment;
+ assigned_register_ = kUnassignedRegister;
}
@@ -210,6 +308,14 @@ void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence,
}
+UsePosition* LiveRange::FirstHintPosition(int* register_index) const {
+ for (auto pos = first_pos_; pos != nullptr; pos = pos->next()) {
+ if (pos->HintRegister(register_index)) return pos;
+ }
+ return nullptr;
+}
+
+
void LiveRange::SetSpillOperand(InstructionOperand* operand) {
DCHECK(HasNoSpillType());
DCHECK(!operand->IsUnallocated() && !operand->IsImmediate());
@@ -494,11 +600,9 @@ void LiveRange::AddUseInterval(LifetimePosition start, LifetimePosition end,
}
-void LiveRange::AddUsePosition(LifetimePosition pos,
- InstructionOperand* operand,
- InstructionOperand* hint, Zone* zone) {
+void LiveRange::AddUsePosition(UsePosition* use_pos) {
+ auto pos = use_pos->pos();
TRACE("Add to live range %d use position %d\n", id_, pos.value());
- auto use_pos = new (zone) UsePosition(pos, operand, hint);
UsePosition* prev_hint = nullptr;
UsePosition* prev = nullptr;
auto current = first_pos_;
@@ -517,7 +621,7 @@ void LiveRange::AddUsePosition(LifetimePosition pos,
}
if (prev_hint == nullptr && use_pos->HasHint()) {
- current_hint_operand_ = hint;
+ current_hint_position_ = use_pos;
}
}
@@ -526,9 +630,7 @@ void LiveRange::ConvertUsesToOperand(const InstructionOperand& op,
InstructionOperand* spill_op) {
for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) {
DCHECK(Start() <= pos->pos() && pos->pos() <= End());
- if (!pos->HasOperand()) {
- continue;
- }
+ if (!pos->HasOperand()) continue;
switch (pos->type()) {
case UsePositionType::kRequiresSlot:
if (spill_op != nullptr) {
@@ -546,6 +648,21 @@ void LiveRange::ConvertUsesToOperand(const InstructionOperand& op,
}
+void LiveRange::SetUseHints(int register_index) {
+ for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) {
+ if (!pos->HasOperand()) continue;
+ switch (pos->type()) {
+ case UsePositionType::kRequiresSlot:
+ break;
+ case UsePositionType::kRequiresRegister:
+ case UsePositionType::kAny:
+ pos->set_assigned_register(register_index);
+ break;
+ }
+ }
+}
+
+
bool LiveRange::CanCover(LifetimePosition position) const {
if (IsEmpty()) return false;
return Start() <= position && position < End();
@@ -702,6 +819,31 @@ void SpillRange::MergeDisjointIntervals(UseInterval* other) {
}
+RegisterAllocationData::PhiMapValue::PhiMapValue(PhiInstruction* phi,
+ const InstructionBlock* block,
+ Zone* zone)
+ : phi_(phi),
+ block_(block),
+ incoming_operands_(zone),
+ assigned_register_(kUnassignedRegister) {
+ incoming_operands_.reserve(phi->operands().size());
+}
+
+
+void RegisterAllocationData::PhiMapValue::AddOperand(
+ InstructionOperand* operand) {
+ incoming_operands_.push_back(operand);
+}
+
+
+void RegisterAllocationData::PhiMapValue::CommitAssignment(
+ const InstructionOperand& assigned) {
+ for (auto operand : incoming_operands_) {
+ InstructionOperand::ReplaceWith(operand, &assigned);
+ }
+}
+
+
RegisterAllocationData::RegisterAllocationData(
const RegisterConfiguration* config, Zone* zone, Frame* frame,
InstructionSequence* code, const char* debug_name)
@@ -757,19 +899,28 @@ MoveOperands* RegisterAllocationData::AddGapMove(
}
-void RegisterAllocationData::AssignPhiInput(
- LiveRange* range, const InstructionOperand& assignment) {
- DCHECK(range->is_phi());
- auto it = phi_map().find(range->id());
- DCHECK(it != phi_map().end());
- for (auto move : it->second->incoming_moves) {
- move->set_destination(assignment);
- }
+LiveRange* RegisterAllocationData::NewLiveRange(int index) {
+ return new (allocation_zone()) LiveRange(index);
}
-LiveRange* RegisterAllocationData::NewLiveRange(int index) {
- return new (allocation_zone()) LiveRange(index);
+RegisterAllocationData::PhiMapValue* RegisterAllocationData::InitializePhiMap(
+ const InstructionBlock* block, PhiInstruction* phi) {
+ auto map_value = new (allocation_zone())
+ RegisterAllocationData::PhiMapValue(phi, block, allocation_zone());
+ auto res =
+ phi_map_.insert(std::make_pair(phi->virtual_register(), map_value));
+ DCHECK(res.second);
+ USE(res);
+ return map_value;
+}
+
+
+RegisterAllocationData::PhiMapValue* RegisterAllocationData::GetPhiMapValueFor(
+ int virtual_register) {
+ auto it = phi_map_.find(virtual_register);
+ DCHECK(it != phi_map_.end());
+ return it->second;
}
@@ -803,19 +954,13 @@ SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange(
}
-void RegisterAllocationData::SetLiveRangeAssignedRegister(LiveRange* range,
- int reg) {
- if (range->Kind() == DOUBLE_REGISTERS) {
- assigned_double_registers_->Add(reg);
+void RegisterAllocationData::MarkAllocated(RegisterKind kind, int index) {
+ if (kind == DOUBLE_REGISTERS) {
+ assigned_double_registers_->Add(index);
} else {
- DCHECK(range->Kind() == GENERAL_REGISTERS);
- assigned_registers_->Add(reg);
+ DCHECK(kind == GENERAL_REGISTERS);
+ assigned_registers_->Add(index);
}
- range->set_assigned_register(reg);
- auto assignment = range->GetAssignedOperand();
- // TODO(dcarney): stop aliasing hint operands.
- range->ConvertUsesToOperand(assignment, nullptr);
- if (range->is_phi()) AssignPhiInput(range, assignment);
}
@@ -1022,19 +1167,16 @@ void ConstraintBuilder::ResolvePhis() {
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 map_value = data()->InitializePhiMap(block, phi);
auto& output = phi->output();
+ // Map the destination operands, so the commitment phase can find them.
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);
+ map_value->AddOperand(&move->destination());
DCHECK(!InstructionAt(cur_block->last_instruction_index())
->HasReferenceMap());
}
@@ -1049,8 +1191,9 @@ void ConstraintBuilder::ResolvePhis(const InstructionBlock* block) {
}
-LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data)
- : data_(data) {}
+LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data,
+ Zone* local_zone)
+ : data_(data), phi_hints_(local_zone) {}
BitVector* LiveRangeBuilder::ComputeLiveOut(const InstructionBlock* block) {
@@ -1109,7 +1252,8 @@ LiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
result = data()->NewLiveRange(FixedLiveRangeID(index));
DCHECK(result->IsFixed());
result->set_kind(GENERAL_REGISTERS);
- data()->SetLiveRangeAssignedRegister(result, index);
+ result->set_assigned_register(index);
+ data()->MarkAllocated(GENERAL_REGISTERS, index);
data()->fixed_live_ranges()[index] = result;
}
return result;
@@ -1123,7 +1267,8 @@ LiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) {
result = data()->NewLiveRange(FixedDoubleLiveRangeID(index));
DCHECK(result->IsFixed());
result->set_kind(DOUBLE_REGISTERS);
- data()->SetLiveRangeAssignedRegister(result, index);
+ result->set_assigned_register(index);
+ data()->MarkAllocated(DOUBLE_REGISTERS, index);
data()->fixed_double_live_ranges()[index] = result;
}
return result;
@@ -1146,60 +1291,49 @@ LiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
}
-void LiveRangeBuilder::Define(LifetimePosition position,
- InstructionOperand* operand,
- InstructionOperand* hint) {
+UsePosition* LiveRangeBuilder::NewUsePosition(LifetimePosition pos,
+ InstructionOperand* operand,
+ void* hint,
+ UsePositionHintType hint_type) {
+ return new (allocation_zone()) UsePosition(pos, operand, hint, hint_type);
+}
+
+
+UsePosition* LiveRangeBuilder::Define(LifetimePosition position,
+ InstructionOperand* operand, void* hint,
+ UsePositionHintType hint_type) {
auto range = LiveRangeFor(operand);
- if (range == nullptr) return;
+ if (range == nullptr) return nullptr;
if (range->IsEmpty() || range->Start() > position) {
// Can happen if there is a definition without use.
range->AddUseInterval(position, position.NextStart(), allocation_zone());
- range->AddUsePosition(position.NextStart(), nullptr, nullptr,
- allocation_zone());
+ range->AddUsePosition(NewUsePosition(position.NextStart()));
} else {
range->ShortenTo(position);
}
-
- if (operand->IsUnallocated()) {
- auto unalloc_operand = UnallocatedOperand::cast(operand);
- range->AddUsePosition(position, unalloc_operand, hint, allocation_zone());
- }
+ if (!operand->IsUnallocated()) return nullptr;
+ auto unalloc_operand = UnallocatedOperand::cast(operand);
+ auto use_pos = NewUsePosition(position, unalloc_operand, hint, hint_type);
+ range->AddUsePosition(use_pos);
+ return use_pos;
}
-void LiveRangeBuilder::Use(LifetimePosition block_start,
- LifetimePosition position,
- InstructionOperand* operand,
- InstructionOperand* hint) {
+UsePosition* LiveRangeBuilder::Use(LifetimePosition block_start,
+ LifetimePosition position,
+ InstructionOperand* operand, void* hint,
+ UsePositionHintType hint_type) {
auto range = LiveRangeFor(operand);
- if (range == nullptr) return;
+ if (range == nullptr) return nullptr;
+ UsePosition* use_pos = nullptr;
if (operand->IsUnallocated()) {
UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand);
- range->AddUsePosition(position, unalloc_operand, hint, allocation_zone());
+ use_pos = NewUsePosition(position, unalloc_operand, hint, hint_type);
+ range->AddUsePosition(use_pos);
}
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);
- if (output->IsRegister() && RegisterOperand::cast(output)->index() == index)
- return true;
- }
- return false;
-}
-
-
-bool LiveRangeBuilder::IsOutputDoubleRegisterOf(Instruction* instr, int index) {
- for (size_t i = 0; i < instr->OutputCount(); i++) {
- auto output = instr->OutputAt(i);
- if (output->IsDoubleRegister() &&
- DoubleRegisterOperand::cast(output)->index() == index)
- return true;
- }
- return false;
+ return use_pos;
}
@@ -1228,7 +1362,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
int out_vreg = ConstantOperand::cast(output)->virtual_register();
live->Remove(out_vreg);
}
- Define(curr_position, output, nullptr);
+ Define(curr_position, output);
}
if (instr->ClobbersRegisters()) {
@@ -1270,7 +1404,7 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
LiveRangeFor(vreg)->set_has_slot_use(true);
}
}
- Use(block_start_position, use_pos, input, nullptr);
+ Use(block_start_position, use_pos, input);
}
for (size_t i = 0; i < instr->TempCount(); i++) {
@@ -1287,8 +1421,8 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
}
}
}
- Use(block_start_position, curr_position.End(), temp, nullptr);
- Define(curr_position, temp, nullptr);
+ Use(block_start_position, curr_position.End(), temp);
+ Define(curr_position, temp);
}
// Process the moves of the instruction's gaps, making their sources live.
@@ -1307,17 +1441,27 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
for (auto cur : *move) {
auto& from = cur->source();
auto& to = cur->destination();
- auto hint = &to;
+ void* hint = &to;
+ UsePositionHintType hint_type = UsePosition::HintTypeForOperand(to);
+ UsePosition* to_use = nullptr;
+ int phi_vreg = -1;
if (to.IsUnallocated()) {
int to_vreg = UnallocatedOperand::cast(to).virtual_register();
auto to_range = LiveRangeFor(to_vreg);
if (to_range->is_phi()) {
+ phi_vreg = to_vreg;
if (to_range->is_non_loop_phi()) {
- hint = to_range->current_hint_operand();
+ hint = to_range->current_hint_position();
+ hint_type = hint == nullptr ? UsePositionHintType::kNone
+ : UsePositionHintType::kUsePos;
+ } else {
+ hint_type = UsePositionHintType::kPhi;
+ hint = data()->GetPhiMapValueFor(to_vreg);
}
} else {
if (live->Contains(to_vreg)) {
- Define(curr_position, &to, &from);
+ to_use = Define(curr_position, &to, &from,
+ UsePosition::HintTypeForOperand(from));
live->Remove(to_vreg);
} else {
cur->Eliminate();
@@ -1325,18 +1469,81 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
}
}
} else {
- Define(curr_position, &to, &from);
+ Define(curr_position, &to);
}
- Use(block_start_position, curr_position, &from, hint);
+ auto from_use =
+ Use(block_start_position, curr_position, &from, hint, hint_type);
+ // Mark range live.
if (from.IsUnallocated()) {
live->Add(UnallocatedOperand::cast(from).virtual_register());
}
+ // Resolve use position hints just created.
+ if (to_use != nullptr && from_use != nullptr) {
+ to_use->ResolveHint(from_use);
+ from_use->ResolveHint(to_use);
+ }
+ DCHECK_IMPLIES(to_use != nullptr, to_use->IsResolved());
+ DCHECK_IMPLIES(from_use != nullptr, from_use->IsResolved());
+ // Potentially resolve phi hint.
+ if (phi_vreg != -1) ResolvePhiHint(&from, from_use);
}
}
}
}
+void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block,
+ BitVector* live) {
+ for (auto phi : block->phis()) {
+ // The live range interval already ends at the first instruction of the
+ // block.
+ int phi_vreg = phi->virtual_register();
+ live->Remove(phi_vreg);
+ InstructionOperand* hint = nullptr;
+ auto instr = GetLastInstruction(
+ code(), code()->InstructionBlockAt(block->predecessors()[0]));
+ for (auto move : *instr->GetParallelMove(Instruction::END)) {
+ auto& to = move->destination();
+ if (to.IsUnallocated() &&
+ UnallocatedOperand::cast(to).virtual_register() == phi_vreg) {
+ hint = &move->source();
+ break;
+ }
+ }
+ DCHECK(hint != nullptr);
+ auto block_start = LifetimePosition::GapFromInstructionIndex(
+ block->first_instruction_index());
+ auto use_pos = Define(block_start, &phi->output(), hint,
+ UsePosition::HintTypeForOperand(*hint));
+ MapPhiHint(hint, use_pos);
+ }
+}
+
+
+void LiveRangeBuilder::ProcessLoopHeader(const InstructionBlock* block,
+ BitVector* live) {
+ DCHECK(block->IsLoopHeader());
+ // Add a live range stretching from the first loop instruction to the last
+ // for each value live on entry to the header.
+ BitVector::Iterator iterator(live);
+ auto start = LifetimePosition::GapFromInstructionIndex(
+ block->first_instruction_index());
+ auto end = LifetimePosition::GapFromInstructionIndex(
+ code()->LastLoopInstructionIndex(block)).NextFullStart();
+ while (!iterator.Done()) {
+ int operand_index = iterator.Current();
+ auto range = LiveRangeFor(operand_index);
+ range->EnsureInterval(start, end, allocation_zone());
+ iterator.Advance();
+ }
+ // Insert all values into the live in sets of all blocks in the loop.
+ for (int i = block->rpo_number().ToInt() + 1; i < block->loop_end().ToInt();
+ ++i) {
+ live_in_sets()[i]->Union(*live);
+ }
+}
+
+
void LiveRangeBuilder::BuildLiveRanges() {
// Process the blocks in reverse order.
for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0;
@@ -1346,59 +1553,17 @@ void LiveRangeBuilder::BuildLiveRanges() {
// Initially consider all live_out values live for the entire block. We
// will shorten these intervals if necessary.
AddInitialIntervals(block, live);
-
// Process the instructions in reverse order, generating and killing
// live values.
ProcessInstructions(block, live);
// All phi output operands are killed by this block.
- for (auto phi : block->phis()) {
- // The live range interval already ends at the first instruction of the
- // block.
- int phi_vreg = phi->virtual_register();
- live->Remove(phi_vreg);
- InstructionOperand* hint = nullptr;
- auto instr = GetLastInstruction(
- code(), code()->InstructionBlockAt(block->predecessors()[0]));
- for (auto move : *instr->GetParallelMove(Instruction::END)) {
- auto& to = move->destination();
- if (to.IsUnallocated() &&
- UnallocatedOperand::cast(to).virtual_register() == phi_vreg) {
- hint = &move->source();
- break;
- }
- }
- DCHECK(hint != nullptr);
- auto block_start = LifetimePosition::GapFromInstructionIndex(
- block->first_instruction_index());
- Define(block_start, &phi->output(), hint);
- }
-
+ ProcessPhis(block, live);
// Now live is live_in for this block except not including values live
// out on backward successor edges.
+ if (block->IsLoopHeader()) ProcessLoopHeader(block, live);
live_in_sets()[block_id] = live;
-
- if (block->IsLoopHeader()) {
- // Add a live range stretching from the first loop instruction to the last
- // for each value live on entry to the header.
- BitVector::Iterator iterator(live);
- auto start = LifetimePosition::GapFromInstructionIndex(
- block->first_instruction_index());
- auto end = LifetimePosition::GapFromInstructionIndex(
- code()->LastLoopInstructionIndex(block)).NextFullStart();
- while (!iterator.Done()) {
- int operand_index = iterator.Current();
- auto range = LiveRangeFor(operand_index);
- range->EnsureInterval(start, end, allocation_zone());
- iterator.Advance();
- }
- // Insert all values into the live in sets of all blocks in the loop.
- for (int i = block->rpo_number().ToInt() + 1;
- i < block->loop_end().ToInt(); ++i) {
- live_in_sets()[i]->Union(*live);
- }
- }
}
-
+ // Postprocess the ranges.
for (auto range : data()->live_ranges()) {
if (range == nullptr) continue;
range->set_kind(RequiredRegisterKind(range->id()));
@@ -1422,13 +1587,30 @@ void LiveRangeBuilder::BuildLiveRanges() {
}
}
}
-
#ifdef DEBUG
Verify();
#endif
}
+void LiveRangeBuilder::MapPhiHint(InstructionOperand* operand,
+ UsePosition* use_pos) {
+ DCHECK(!use_pos->IsResolved());
+ auto res = phi_hints_.insert(std::make_pair(operand, use_pos));
+ DCHECK(res.second);
+ USE(res);
+}
+
+
+void LiveRangeBuilder::ResolvePhiHint(InstructionOperand* operand,
+ UsePosition* use_pos) {
+ auto it = phi_hints_.find(operand);
+ if (it == phi_hints_.end()) return;
+ DCHECK(!it->second->IsResolved());
+ it->second->ResolveHint(use_pos);
+}
+
+
RegisterKind LiveRangeBuilder::RequiredRegisterKind(
int virtual_register) const {
return (code()->IsDouble(virtual_register)) ? DOUBLE_REGISTERS
@@ -1437,6 +1619,9 @@ RegisterKind LiveRangeBuilder::RequiredRegisterKind(
void LiveRangeBuilder::Verify() const {
+ for (auto& hint : phi_hints_) {
+ CHECK(hint.second->IsResolved());
+ }
for (auto current : data()->live_ranges()) {
if (current != nullptr) current->Verify();
}
@@ -1677,6 +1862,17 @@ const char* LinearScanAllocator::RegisterName(int allocation_index) const {
}
+void LinearScanAllocator::SetLiveRangeAssignedRegister(LiveRange* range,
+ int reg) {
+ data()->MarkAllocated(range->Kind(), reg);
+ range->set_assigned_register(reg);
+ range->SetUseHints(reg);
+ if (range->is_phi()) {
+ data()->GetPhiMapValueFor(range->id())->set_assigned_register(reg);
+ }
+}
+
+
void LinearScanAllocator::AddToActive(LiveRange* range) {
TRACE("Add live range %d to active\n", range->id());
active_live_ranges().push_back(range);
@@ -1792,18 +1988,17 @@ bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) {
free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection);
}
- auto hint = current->FirstHint();
- if (hint != nullptr && (hint->IsRegister() || hint->IsDoubleRegister())) {
- int register_index = AllocatedOperand::cast(hint)->index();
+ int hint_register;
+ if (current->FirstHintPosition(&hint_register) != nullptr) {
TRACE("Found reg hint %s (free until [%d) for live range %d (end %d[).\n",
- RegisterName(register_index), free_until_pos[register_index].value(),
+ RegisterName(hint_register), free_until_pos[hint_register].value(),
current->id(), current->End().value());
// The desired register is free until the end of the current live range.
- if (free_until_pos[register_index] >= current->End()) {
+ if (free_until_pos[hint_register] >= current->End()) {
TRACE("Assigning preferred reg %s to live range %d\n",
- RegisterName(register_index), current->id());
- data()->SetLiveRangeAssignedRegister(current, register_index);
+ RegisterName(hint_register), current->id());
+ SetLiveRangeAssignedRegister(current, hint_register);
return true;
}
}
@@ -1835,7 +2030,7 @@ bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) {
DCHECK(pos >= current->End());
TRACE("Assigning free reg %s to live range %d\n", RegisterName(reg),
current->id());
- data()->SetLiveRangeAssignedRegister(current, reg);
+ SetLiveRangeAssignedRegister(current, reg);
return true;
}
@@ -1914,7 +2109,7 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) {
DCHECK(block_pos[reg] >= current->End());
TRACE("Assigning blocked reg %s to live range %d\n", RegisterName(reg),
current->id());
- data()->SetLiveRangeAssignedRegister(current, reg);
+ SetLiveRangeAssignedRegister(current, reg);
// This register was not free. Thus we need to find and spill
// parts of active and inactive live regions that use the same register
@@ -1974,11 +2169,9 @@ void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) {
bool LinearScanAllocator::TryReuseSpillForPhi(LiveRange* range) {
if (range->IsChild() || !range->is_phi()) return false;
DCHECK(!range->HasSpillOperand());
-
- auto lookup = data()->phi_map().find(range->id());
- DCHECK(lookup != data()->phi_map().end());
- auto phi = lookup->second->phi;
- auto block = lookup->second->block;
+ auto phi_map_value = data()->GetPhiMapValueFor(range->id());
+ auto phi = phi_map_value->phi();
+ auto block = phi_map_value->block();
// Count the number of spilled operands.
size_t spilled_count = 0;
LiveRange* first_op = nullptr;
@@ -2199,13 +2392,18 @@ void GreedyAllocator::AssignRangeToRegister(int reg_id, LiveRange* range) {
return;
}
range->set_assigned_register(reg_id);
+ range->SetUseHints(reg_id);
+ if (range->is_phi()) {
+ data()->GetPhiMapValueFor(range->id())->set_assigned_register(reg_id);
+ }
}
float GreedyAllocator::CalculateSpillWeight(LiveRange* range) {
if (range->IsFixed()) return std::numeric_limits<float>::max();
- if (range->FirstHint() != nullptr && range->FirstHint()->IsRegister()) {
+ int hint_register;
+ if (range->FirstHintPosition(&hint_register) != nullptr) {
return std::numeric_limits<float>::max();
}
@@ -2237,6 +2435,11 @@ float GreedyAllocator::CalculateMaxSpillWeight(
void GreedyAllocator::Evict(LiveRange* range) {
bool removed = allocations_[range->assigned_register()]->Remove(range);
CHECK(removed);
+ range->UnsetUseHints();
+ range->UnsetAssignedRegister();
+ if (range->is_phi()) {
+ data()->GetPhiMapValueFor(range->id())->UnsetAssignedRegister();
+ }
}
@@ -2405,13 +2608,11 @@ void GreedyAllocator::AllocateRegisters() {
}
}
- BitVector* assigned_registers = new (zone) BitVector(num_registers(), zone);
for (size_t i = 0; i < allocations_.size(); ++i) {
if (!allocations_[i]->IsEmpty()) {
- assigned_registers->Add(static_cast<int>(i));
+ data()->MarkAllocated(mode(), static_cast<int>(i));
}
}
- data()->frame()->SetAllocatedRegisters(assigned_registers);
}
@@ -2472,7 +2673,9 @@ void OperandAssigner::CommitAssignment() {
}
auto assigned = range->GetAssignedOperand();
range->ConvertUsesToOperand(assigned, spill_operand);
- if (range->is_phi()) data()->AssignPhiInput(range, assigned);
+ if (range->is_phi()) {
+ data()->GetPhiMapValueFor(range->id())->CommitAssignment(assigned);
+ }
if (!range->IsChild() && spill_operand != nullptr) {
range->CommitSpillsAtDefinition(data()->code(), spill_operand,
range->has_slot_use());
« no previous file with comments | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698