[turbofan] Cleanup LiveRange a bit.

Review URL: https://codereview.chromium.org/1111563004

Cr-Commit-Position: refs/heads/master@{#28099}
This commit is contained in:
dcarney 2015-04-28 02:59:55 -07:00 committed by Commit bot
parent 1630253f93
commit 12350f16b8
3 changed files with 106 additions and 87 deletions

View File

@ -726,7 +726,7 @@ void GraphC1Visualizer::PrintLiveRange(LiveRange* range, const char* type) {
DCHECK(op.IsRegister());
os_ << " \"" << Register::AllocationIndexToString(assigned_reg) << "\"";
}
} else if (range->IsSpilled()) {
} else if (range->spilled()) {
auto top = range->TopLevel();
int index = -1;
if (top->HasSpillRange()) {
@ -737,9 +737,9 @@ void GraphC1Visualizer::PrintLiveRange(LiveRange* range, const char* type) {
<< "\"";
} else {
index = AllocatedOperand::cast(top->GetSpillOperand())->index();
if (top->Kind() == DOUBLE_REGISTERS) {
if (top->kind() == DOUBLE_REGISTERS) {
os_ << " \"double_stack:" << index << "\"";
} else if (top->Kind() == GENERAL_REGISTERS) {
} else if (top->kind() == GENERAL_REGISTERS) {
os_ << " \"stack:" << index << "\"";
}
}

View File

@ -216,24 +216,21 @@ struct LiveRange::SpillAtDefinitionList : ZoneObject {
LiveRange::LiveRange(int id)
: id_(id),
spilled_(false),
has_slot_use_(false),
is_phi_(false),
is_non_loop_phi_(false),
kind_(UNALLOCATED_REGISTERS),
assigned_register_(kUnassignedRegister),
spill_start_index_(kMaxInt),
bits_(0),
last_interval_(nullptr),
first_interval_(nullptr),
first_pos_(nullptr),
parent_(nullptr),
next_(nullptr),
spill_operand_(nullptr),
spills_at_definition_(nullptr),
current_interval_(nullptr),
last_processed_use_(nullptr),
current_hint_position_(nullptr),
spill_start_index_(kMaxInt),
spill_type_(SpillType::kNoSpillType),
spill_operand_(nullptr),
spills_at_definition_(nullptr) {}
current_hint_position_(nullptr) {
bits_ = SpillTypeField::encode(SpillType::kNoSpillType) |
AssignedRegisterField::encode(kUnassignedRegister);
}
void LiveRange::Verify() const {
@ -252,22 +249,22 @@ void LiveRange::Verify() const {
void LiveRange::set_assigned_register(int reg) {
DCHECK(!HasRegisterAssigned() && !IsSpilled());
assigned_register_ = reg;
DCHECK(!HasRegisterAssigned() && !spilled());
bits_ = AssignedRegisterField::update(bits_, reg);
}
void LiveRange::UnsetAssignedRegister() {
DCHECK(HasRegisterAssigned() && !IsSpilled());
assigned_register_ = kUnassignedRegister;
DCHECK(HasRegisterAssigned() && !spilled());
bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister);
}
void LiveRange::MakeSpilled() {
DCHECK(!IsSpilled());
void LiveRange::Spill() {
DCHECK(!spilled());
DCHECK(!TopLevel()->HasNoSpillType());
spilled_ = true;
assigned_register_ = kUnassignedRegister;
set_spilled(true);
bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister);
}
@ -319,7 +316,7 @@ UsePosition* LiveRange::FirstHintPosition(int* register_index) const {
void LiveRange::SetSpillOperand(InstructionOperand* operand) {
DCHECK(HasNoSpillType());
DCHECK(!operand->IsUnallocated() && !operand->IsImmediate());
spill_type_ = SpillType::kSpillOperand;
set_spill_type(SpillType::kSpillOperand);
spill_operand_ = operand;
}
@ -327,7 +324,7 @@ void LiveRange::SetSpillOperand(InstructionOperand* operand) {
void LiveRange::SetSpillRange(SpillRange* spill_range) {
DCHECK(HasNoSpillType() || HasSpillRange());
DCHECK(spill_range);
spill_type_ = SpillType::kSpillRange;
set_spill_type(SpillType::kSpillRange);
spill_range_ = spill_range;
}
@ -335,7 +332,7 @@ void LiveRange::SetSpillRange(SpillRange* spill_range) {
void LiveRange::CommitSpillOperand(AllocatedOperand* operand) {
DCHECK(HasSpillRange());
DCHECK(!IsChild());
spill_type_ = SpillType::kSpillOperand;
set_spill_type(SpillType::kSpillOperand);
spill_operand_ = operand;
}
@ -395,8 +392,8 @@ bool LiveRange::CanBeSpilled(LifetimePosition pos) const {
InstructionOperand LiveRange::GetAssignedOperand() const {
if (HasRegisterAssigned()) {
DCHECK(!IsSpilled());
switch (Kind()) {
DCHECK(!spilled());
switch (kind()) {
case GENERAL_REGISTERS:
return RegisterOperand(assigned_register());
case DOUBLE_REGISTERS:
@ -405,7 +402,7 @@ InstructionOperand LiveRange::GetAssignedOperand() const {
UNREACHABLE();
}
}
DCHECK(IsSpilled());
DCHECK(spilled());
DCHECK(!HasRegisterAssigned());
auto op = TopLevel()->GetSpillOperand();
DCHECK(!op->IsUnallocated());
@ -469,6 +466,7 @@ void LiveRange::SplitAt(LifetimePosition position, LiveRange* result,
}
current = next;
}
DCHECK(nullptr != after);
// Partition original use intervals to the two live ranges.
auto before = current;
@ -514,7 +512,7 @@ void LiveRange::SplitAt(LifetimePosition position, LiveRange* result,
// Link the new live range in the chain before any of the other
// ranges linked from the range before the split.
result->parent_ = (parent_ == nullptr) ? this : parent_;
result->kind_ = result->parent_->kind_;
result->set_kind(result->parent_->kind());
result->next_ = next_;
next_ = result;
@ -765,7 +763,7 @@ bool SpillRange::IsIntersectingWith(SpillRange* other) const {
bool SpillRange::TryMerge(SpillRange* other) {
if (Kind() != other->Kind() || IsIntersectingWith(other)) return false;
if (kind() != other->kind() || IsIntersectingWith(other)) return false;
auto max = LifetimePosition::MaxPosition();
if (End() < other->End() && other->End() != max) {
@ -1738,13 +1736,13 @@ LifetimePosition RegisterAllocator::FindOptimalSpillingPos(
void RegisterAllocator::Spill(LiveRange* range) {
DCHECK(!range->IsSpilled());
DCHECK(!range->spilled());
TRACE("Spilling live range %d\n", range->id());
auto first = range->TopLevel();
if (first->HasNoSpillType()) {
data()->AssignSpillRangeToLiveRange(first);
}
range->MakeSpilled();
range->Spill();
}
@ -1772,7 +1770,7 @@ void LinearScanAllocator::AllocateRegisters() {
for (auto range : data()->live_ranges()) {
if (range == nullptr) continue;
if (range->Kind() == mode()) {
if (range->kind() == mode()) {
AddToUnhandledUnsorted(range);
}
}
@ -1782,7 +1780,7 @@ void LinearScanAllocator::AllocateRegisters() {
auto& fixed_ranges = GetFixedRegisters(data(), mode());
for (auto current : fixed_ranges) {
if (current != nullptr) {
DCHECK_EQ(mode(), current->Kind());
DCHECK_EQ(mode(), current->kind());
AddToInactive(current);
}
}
@ -1843,7 +1841,7 @@ void LinearScanAllocator::AllocateRegisters() {
}
}
DCHECK(!current->HasRegisterAssigned() && !current->IsSpilled());
DCHECK(!current->HasRegisterAssigned() && !current->spilled());
bool result = TryAllocateFreeReg(current);
if (!result) AllocateBlockedReg(current);
@ -1865,7 +1863,7 @@ const char* LinearScanAllocator::RegisterName(int allocation_index) const {
void LinearScanAllocator::SetLiveRangeAssignedRegister(LiveRange* range,
int reg) {
data()->MarkAllocated(range->Kind(), reg);
data()->MarkAllocated(range->kind(), reg);
range->set_assigned_register(reg);
range->SetUseHints(reg);
if (range->is_phi()) {
@ -1888,7 +1886,7 @@ void LinearScanAllocator::AddToInactive(LiveRange* range) {
void LinearScanAllocator::AddToUnhandledSorted(LiveRange* range) {
if (range == nullptr || range->IsEmpty()) return;
DCHECK(!range->HasRegisterAssigned() && !range->IsSpilled());
DCHECK(!range->HasRegisterAssigned() && !range->spilled());
DCHECK(allocation_finger_ <= range->Start());
for (int i = static_cast<int>(unhandled_live_ranges().size() - 1); i >= 0;
--i) {
@ -1908,7 +1906,7 @@ void LinearScanAllocator::AddToUnhandledSorted(LiveRange* range) {
void LinearScanAllocator::AddToUnhandledUnsorted(LiveRange* range) {
if (range == nullptr || range->IsEmpty()) return;
DCHECK(!range->HasRegisterAssigned() && !range->IsSpilled());
DCHECK(!range->HasRegisterAssigned() && !range->spilled());
TRACE("Add live range %d to unhandled unsorted at end\n", range->id());
unhandled_live_ranges().push_back(range);
}
@ -2186,7 +2184,7 @@ bool LinearScanAllocator::TryReuseSpillForPhi(LiveRange* range) {
while (op_range != nullptr && !op_range->CanCover(pred_end)) {
op_range = op_range->next();
}
if (op_range != nullptr && op_range->IsSpilled()) {
if (op_range != nullptr && op_range->spilled()) {
spilled_count++;
if (first_op == nullptr) {
first_op = op_range->TopLevel();
@ -2560,8 +2558,8 @@ bool GreedyAllocator::HandleSpillOperands(LiveRange* range) {
void GreedyAllocator::AllocateRegisters() {
for (auto range : data()->live_ranges()) {
if (range == nullptr) continue;
if (range->Kind() == mode()) {
DCHECK(!range->HasRegisterAssigned() && !range->IsSpilled());
if (range->kind() == mode()) {
DCHECK(!range->HasRegisterAssigned() && !range->spilled());
TRACE("Enqueueing live range %d to priority queue \n", range->id());
Enqueue(range);
}
@ -2575,7 +2573,7 @@ void GreedyAllocator::AllocateRegisters() {
for (auto* current : GetFixedRegisters(data(), mode())) {
if (current != nullptr) {
DCHECK_EQ(mode(), current->Kind());
DCHECK_EQ(mode(), current->kind());
int reg_nr = current->assigned_register();
bool inserted = allocations_[reg_nr]->Insert(current);
CHECK(inserted);
@ -2654,7 +2652,7 @@ void OperandAssigner::AssignSpillSlots() {
for (auto range : spill_ranges) {
if (range->IsEmpty()) continue;
// Allocate a new operand referring to the spill slot.
auto kind = range->Kind();
auto kind = range->kind();
int index = data()->frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
auto op_kind = kind == DOUBLE_REGISTERS
? AllocatedOperand::DOUBLE_STACK_SLOT
@ -2766,7 +2764,7 @@ void ReferenceMapPopulator::PopulateReferenceMaps() {
map->RecordReference(*range->GetSpillOperand());
}
if (!cur->IsSpilled()) {
if (!cur->spilled()) {
TRACE(
"Pointer in register for range %d (start at %d) "
"at safe point %d\n",
@ -2940,7 +2938,7 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
const auto* pred_block = code()->InstructionBlockAt(pred);
array->Find(block, pred_block, &result);
if (result.cur_cover_ == result.pred_cover_ ||
result.cur_cover_->IsSpilled())
result.cur_cover_->spilled())
continue;
auto pred_op = result.pred_cover_->GetAssignedOperand();
auto cur_op = result.cur_cover_->GetAssignedOperand();
@ -2985,7 +2983,7 @@ void LiveRangeConnector::ConnectRanges(Zone* local_zone) {
auto pos = second_range->Start();
// Add gap move if the two live ranges touch and there is no block
// boundary.
if (second_range->IsSpilled()) continue;
if (second_range->spilled()) continue;
if (first_range->End() != pos) continue;
if (IsBlockBoundary(code(), pos) &&
!CanEagerlyResolveControlFlow(GetInstructionBlock(code(), pos))) {

View File

@ -60,8 +60,8 @@ class LifetimePosition final {
// Returns true if this lifetime position corresponds to a gap START value
bool IsFullStart() const { return (value_ & (kStep - 1)) == 0; }
bool IsGapPosition() { return (value_ & 0x2) == 0; }
bool IsInstructionPosition() { return !IsGapPosition(); }
bool IsGapPosition() const { return (value_ & 0x2) == 0; }
bool IsInstructionPosition() const { return !IsGapPosition(); }
// Returns the lifetime position for the current START.
LifetimePosition Start() const {
@ -287,19 +287,38 @@ class LiveRange final : public ZoneObject {
bool IsFixed() const { return id_ < 0; }
bool IsEmpty() const { return first_interval() == nullptr; }
InstructionOperand GetAssignedOperand() const;
int assigned_register() const { return assigned_register_; }
int spill_start_index() const { return spill_start_index_; }
int assigned_register() const { return AssignedRegisterField::decode(bits_); }
bool HasRegisterAssigned() const {
return assigned_register() != kUnassignedRegister;
}
void set_assigned_register(int reg);
void UnsetAssignedRegister();
void MakeSpilled();
bool is_phi() const { return is_phi_; }
void set_is_phi(bool is_phi) { is_phi_ = is_phi; }
bool is_non_loop_phi() const { return is_non_loop_phi_; }
void set_is_non_loop_phi(bool is_non_loop_phi) {
is_non_loop_phi_ = is_non_loop_phi;
bool spilled() const { return SpilledField::decode(bits_); }
void Spill();
RegisterKind kind() const { return RegisterKindField::decode(bits_); }
void set_kind(RegisterKind kind) {
bits_ = RegisterKindField::update(bits_, kind);
}
// Correct only for parent.
bool is_phi() const { return IsPhiField::decode(bits_); }
void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); }
// Correct only for parent.
bool is_non_loop_phi() const { return IsNonLoopPhiField::decode(bits_); }
void set_is_non_loop_phi(bool value) {
bits_ = IsNonLoopPhiField::update(bits_, value);
}
// Relevant only for parent.
bool has_slot_use() const { return HasSlotUseField::decode(bits_); }
void set_has_slot_use(bool value) {
bits_ = HasSlotUseField::update(bits_, value);
}
bool has_slot_use() const { return has_slot_use_; }
void set_has_slot_use(bool has_slot_use) { has_slot_use_ = has_slot_use; }
// Returns use position in this live range that follows both start
// and last processed use position.
@ -328,12 +347,6 @@ class LiveRange final : public ZoneObject {
// live range to the result live range.
void SplitAt(LifetimePosition position, LiveRange* result, Zone* zone);
RegisterKind Kind() const { return kind_; }
bool HasRegisterAssigned() const {
return assigned_register_ != kUnassignedRegister;
}
bool IsSpilled() const { return spilled_; }
// Returns nullptr when no register is hinted, otherwise sets register_index.
UsePosition* FirstHintPosition(int* register_index) const;
UsePosition* FirstHintPosition() const {
@ -357,20 +370,22 @@ class LiveRange final : public ZoneObject {
}
enum class SpillType { kNoSpillType, kSpillOperand, kSpillRange };
SpillType spill_type() const { return spill_type_; }
SpillType spill_type() const { return SpillTypeField::decode(bits_); }
InstructionOperand* GetSpillOperand() const {
DCHECK(spill_type_ == SpillType::kSpillOperand);
DCHECK(spill_type() == SpillType::kSpillOperand);
return spill_operand_;
}
SpillRange* GetSpillRange() const {
DCHECK(spill_type_ == SpillType::kSpillRange);
DCHECK(spill_type() == SpillType::kSpillRange);
return spill_range_;
}
bool HasNoSpillType() const { return spill_type_ == SpillType::kNoSpillType; }
bool HasSpillOperand() const {
return spill_type_ == SpillType::kSpillOperand;
bool HasNoSpillType() const {
return spill_type() == SpillType::kNoSpillType;
}
bool HasSpillRange() const { return spill_type_ == SpillType::kSpillRange; }
bool HasSpillOperand() const {
return spill_type() == SpillType::kSpillOperand;
}
bool HasSpillRange() const { return spill_type() == SpillType::kSpillRange; }
void SpillAtDefinition(Zone* zone, int gap_index,
InstructionOperand* operand);
@ -405,41 +420,47 @@ class LiveRange final : public ZoneObject {
void SetUseHints(int register_index);
void UnsetUseHints() { SetUseHints(kUnassignedRegister); }
void set_kind(RegisterKind kind) { kind_ = kind; }
private:
struct SpillAtDefinitionList;
void set_spill_type(SpillType value) {
bits_ = SpillTypeField::update(bits_, value);
}
void set_spilled(bool value) { bits_ = SpilledField::update(bits_, value); }
UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const;
void AdvanceLastProcessedMarker(UseInterval* to_start_of,
LifetimePosition but_not_past) const;
// TODO(dcarney): pack this structure better.
typedef BitField<bool, 0, 1> SpilledField;
typedef BitField<bool, 1, 1> HasSlotUseField;
typedef BitField<bool, 2, 1> IsPhiField;
typedef BitField<bool, 3, 1> IsNonLoopPhiField;
typedef BitField<RegisterKind, 4, 2> RegisterKindField;
typedef BitField<SpillType, 6, 2> SpillTypeField;
typedef BitField<int32_t, 8, 6> AssignedRegisterField;
int id_;
bool spilled_ : 1;
bool has_slot_use_ : 1; // Relevant only for parent.
bool is_phi_ : 1; // Correct only for parent.
bool is_non_loop_phi_ : 1; // Correct only for parent.
RegisterKind kind_;
int assigned_register_;
int spill_start_index_;
uint32_t bits_;
UseInterval* last_interval_;
UseInterval* first_interval_;
UsePosition* first_pos_;
LiveRange* parent_;
LiveRange* next_;
union {
// Correct value determined by spill_type()
InstructionOperand* spill_operand_;
SpillRange* spill_range_;
};
SpillAtDefinitionList* spills_at_definition_;
// This is used as a cache, it doesn't affect correctness.
mutable UseInterval* current_interval_;
// This is used as a cache, it doesn't affect correctness.
mutable UsePosition* last_processed_use_;
// This is used as a cache, it's invalid outside of BuildLiveRanges.
mutable UsePosition* current_hint_position_;
int spill_start_index_;
SpillType spill_type_;
union {
InstructionOperand* spill_operand_;
SpillRange* spill_range_;
};
SpillAtDefinitionList* spills_at_definition_;
DISALLOW_COPY_AND_ASSIGN(LiveRange);
};
@ -450,7 +471,7 @@ class SpillRange final : public ZoneObject {
SpillRange(LiveRange* range, Zone* zone);
UseInterval* interval() const { return use_interval_; }
RegisterKind Kind() const { return live_ranges_[0]->Kind(); }
RegisterKind kind() const { return live_ranges_[0]->kind(); }
bool IsEmpty() const { return live_ranges_.empty(); }
bool TryMerge(SpillRange* other);
void SetOperand(AllocatedOperand* op);