[turbofan] resolve all references before populating reference maps
BUG= Review URL: https://codereview.chromium.org/1112213005 Cr-Commit-Position: refs/heads/master@{#28157}
This commit is contained in:
parent
ac1c88a9b2
commit
c5c8eb3fd1
@ -210,7 +210,7 @@ std::ostream& operator<<(std::ostream& os,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ReferenceMap::RecordReference(const InstructionOperand& op) {
|
void ReferenceMap::RecordReference(const AllocatedOperand& op) {
|
||||||
// Do not record arguments as pointers.
|
// Do not record arguments as pointers.
|
||||||
if (op.IsStackSlot() && StackSlotOperand::cast(op).index() < 0) return;
|
if (op.IsStackSlot() && StackSlotOperand::cast(op).index() < 0) return;
|
||||||
DCHECK(!op.IsDoubleRegister() && !op.IsDoubleStackSlot());
|
DCHECK(!op.IsDoubleRegister() && !op.IsDoubleStackSlot());
|
||||||
|
@ -592,7 +592,7 @@ class ReferenceMap final : public ZoneObject {
|
|||||||
instruction_position_ = pos;
|
instruction_position_ = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordReference(const InstructionOperand& op);
|
void RecordReference(const AllocatedOperand& op);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
|
friend std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
|
||||||
|
@ -902,6 +902,7 @@ RegisterAllocationData::RegisterAllocationData(
|
|||||||
fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr,
|
fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr,
|
||||||
allocation_zone()),
|
allocation_zone()),
|
||||||
spill_ranges_(allocation_zone()),
|
spill_ranges_(allocation_zone()),
|
||||||
|
delayed_references_(allocation_zone()),
|
||||||
assigned_registers_(nullptr),
|
assigned_registers_(nullptr),
|
||||||
assigned_double_registers_(nullptr),
|
assigned_double_registers_(nullptr),
|
||||||
virtual_register_count_(code->VirtualRegisterCount()) {
|
virtual_register_count_(code->VirtualRegisterCount()) {
|
||||||
@ -1057,7 +1058,7 @@ InstructionOperand* ConstraintBuilder::AllocateFixed(
|
|||||||
TRACE("Fixed reg is tagged at %d\n", pos);
|
TRACE("Fixed reg is tagged at %d\n", pos);
|
||||||
auto instr = InstructionAt(pos);
|
auto instr = InstructionAt(pos);
|
||||||
if (instr->HasReferenceMap()) {
|
if (instr->HasReferenceMap()) {
|
||||||
instr->reference_map()->RecordReference(*operand);
|
instr->reference_map()->RecordReference(*AllocatedOperand::cast(operand));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return operand;
|
return operand;
|
||||||
@ -1206,10 +1207,13 @@ void ConstraintBuilder::MeetConstraintsBefore(int instr_index) {
|
|||||||
int input_vreg = cur_input->virtual_register();
|
int input_vreg = cur_input->virtual_register();
|
||||||
UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg);
|
UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg);
|
||||||
cur_input->set_virtual_register(second_output->virtual_register());
|
cur_input->set_virtual_register(second_output->virtual_register());
|
||||||
data()->AddGapMove(instr_index, Instruction::END, input_copy, *cur_input);
|
auto gap_move = data()->AddGapMove(instr_index, Instruction::END,
|
||||||
|
input_copy, *cur_input);
|
||||||
if (IsReference(input_vreg) && !IsReference(output_vreg)) {
|
if (IsReference(input_vreg) && !IsReference(output_vreg)) {
|
||||||
if (second->HasReferenceMap()) {
|
if (second->HasReferenceMap()) {
|
||||||
second->reference_map()->RecordReference(input_copy);
|
RegisterAllocationData::DelayedReference delayed_reference = {
|
||||||
|
second->reference_map(), &gap_move->source()};
|
||||||
|
data()->delayed_references().push_back(delayed_reference);
|
||||||
}
|
}
|
||||||
} else if (!IsReference(input_vreg) && IsReference(output_vreg)) {
|
} else if (!IsReference(input_vreg) && IsReference(output_vreg)) {
|
||||||
// The input is assumed to immediately have a tagged representation,
|
// The input is assumed to immediately have a tagged representation,
|
||||||
@ -2755,7 +2759,11 @@ bool ReferenceMapPopulator::SafePointsAreInOrder() const {
|
|||||||
|
|
||||||
void ReferenceMapPopulator::PopulateReferenceMaps() {
|
void ReferenceMapPopulator::PopulateReferenceMaps() {
|
||||||
DCHECK(SafePointsAreInOrder());
|
DCHECK(SafePointsAreInOrder());
|
||||||
|
// Map all delayed references.
|
||||||
|
for (auto& delayed_reference : data()->delayed_references()) {
|
||||||
|
delayed_reference.map->RecordReference(
|
||||||
|
AllocatedOperand::cast(*delayed_reference.operand));
|
||||||
|
}
|
||||||
// Iterate over all safe point positions and record a pointer
|
// Iterate over all safe point positions and record a pointer
|
||||||
// for all spilled live ranges at this point.
|
// for all spilled live ranges at this point.
|
||||||
int last_range_start = 0;
|
int last_range_start = 0;
|
||||||
@ -2792,6 +2800,20 @@ void ReferenceMapPopulator::PopulateReferenceMaps() {
|
|||||||
if (map->instruction_position() >= start) break;
|
if (map->instruction_position() >= start) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InstructionOperand spill_operand;
|
||||||
|
if (((range->HasSpillOperand() &&
|
||||||
|
!range->GetSpillOperand()->IsConstant()) ||
|
||||||
|
range->HasSpillRange())) {
|
||||||
|
if (range->HasSpillOperand()) {
|
||||||
|
spill_operand = *range->GetSpillOperand();
|
||||||
|
} else {
|
||||||
|
spill_operand = range->GetSpillRangeOperand();
|
||||||
|
}
|
||||||
|
DCHECK(spill_operand.IsStackSlot());
|
||||||
|
DCHECK_EQ(kRepTagged,
|
||||||
|
AllocatedOperand::cast(spill_operand).machine_type());
|
||||||
|
}
|
||||||
|
|
||||||
// Step through the safe points to see whether they are in the range.
|
// Step through the safe points to see whether they are in the range.
|
||||||
for (auto it = first_it; it != reference_maps->end(); ++it) {
|
for (auto it = first_it; it != reference_maps->end(); ++it) {
|
||||||
auto map = *it;
|
auto map = *it;
|
||||||
@ -2812,21 +2834,11 @@ void ReferenceMapPopulator::PopulateReferenceMaps() {
|
|||||||
|
|
||||||
// Check if the live range is spilled and the safe point is after
|
// Check if the live range is spilled and the safe point is after
|
||||||
// the spill position.
|
// the spill position.
|
||||||
if (((range->HasSpillOperand() &&
|
if (!spill_operand.IsInvalid() &&
|
||||||
!range->GetSpillOperand()->IsConstant()) ||
|
|
||||||
range->HasSpillRange()) &&
|
|
||||||
safe_point >= range->spill_start_index()) {
|
safe_point >= range->spill_start_index()) {
|
||||||
TRACE("Pointer for range %d (spilled at %d) at safe point %d\n",
|
TRACE("Pointer for range %d (spilled at %d) at safe point %d\n",
|
||||||
range->id(), range->spill_start_index(), safe_point);
|
range->id(), range->spill_start_index(), safe_point);
|
||||||
InstructionOperand operand;
|
map->RecordReference(AllocatedOperand::cast(spill_operand));
|
||||||
if (range->HasSpillOperand()) {
|
|
||||||
operand = *range->GetSpillOperand();
|
|
||||||
} else {
|
|
||||||
operand = range->GetSpillRangeOperand();
|
|
||||||
}
|
|
||||||
DCHECK(operand.IsStackSlot());
|
|
||||||
DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type());
|
|
||||||
map->RecordReference(operand);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cur->spilled()) {
|
if (!cur->spilled()) {
|
||||||
@ -2837,7 +2849,7 @@ void ReferenceMapPopulator::PopulateReferenceMaps() {
|
|||||||
auto operand = cur->GetAssignedOperand();
|
auto operand = cur->GetAssignedOperand();
|
||||||
DCHECK(!operand.IsStackSlot());
|
DCHECK(!operand.IsStackSlot());
|
||||||
DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type());
|
DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type());
|
||||||
map->RecordReference(operand);
|
map->RecordReference(AllocatedOperand::cast(operand));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -528,6 +528,12 @@ class RegisterAllocationData final : public ZoneObject {
|
|||||||
};
|
};
|
||||||
typedef ZoneMap<int, PhiMapValue*> PhiMap;
|
typedef ZoneMap<int, PhiMapValue*> PhiMap;
|
||||||
|
|
||||||
|
struct DelayedReference {
|
||||||
|
ReferenceMap* map;
|
||||||
|
InstructionOperand* operand;
|
||||||
|
};
|
||||||
|
typedef ZoneVector<DelayedReference> DelayedReferences;
|
||||||
|
|
||||||
RegisterAllocationData(const RegisterConfiguration* config,
|
RegisterAllocationData(const RegisterConfiguration* config,
|
||||||
Zone* allocation_zone, Frame* frame,
|
Zone* allocation_zone, Frame* frame,
|
||||||
InstructionSequence* code,
|
InstructionSequence* code,
|
||||||
@ -547,6 +553,7 @@ class RegisterAllocationData final : public ZoneObject {
|
|||||||
}
|
}
|
||||||
ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; }
|
ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; }
|
||||||
ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; }
|
ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; }
|
||||||
|
DelayedReferences& delayed_references() { return delayed_references_; }
|
||||||
InstructionSequence* code() const { return code_; }
|
InstructionSequence* code() const { return code_; }
|
||||||
// This zone is for datastructures only needed during register allocation
|
// This zone is for datastructures only needed during register allocation
|
||||||
// phases.
|
// phases.
|
||||||
@ -595,6 +602,7 @@ class RegisterAllocationData final : public ZoneObject {
|
|||||||
ZoneVector<LiveRange*> fixed_live_ranges_;
|
ZoneVector<LiveRange*> fixed_live_ranges_;
|
||||||
ZoneVector<LiveRange*> fixed_double_live_ranges_;
|
ZoneVector<LiveRange*> fixed_double_live_ranges_;
|
||||||
ZoneVector<SpillRange*> spill_ranges_;
|
ZoneVector<SpillRange*> spill_ranges_;
|
||||||
|
DelayedReferences delayed_references_;
|
||||||
BitVector* assigned_registers_;
|
BitVector* assigned_registers_;
|
||||||
BitVector* assigned_double_registers_;
|
BitVector* assigned_double_registers_;
|
||||||
int virtual_register_count_;
|
int virtual_register_count_;
|
||||||
|
Loading…
Reference in New Issue
Block a user