Commit b2378c74 authored by dcarney's avatar dcarney Committed by Commit bot

[turbofan] remove checks for virtual register overflow

R=bmeurer@chromium.org

BUG=

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

Cr-Commit-Position: refs/heads/master@{#25968}
parent 80a7be5c
......@@ -458,6 +458,13 @@ InstructionSequence::InstructionSequence(Zone* instruction_zone,
}
int InstructionSequence::NextVirtualRegister() {
int virtual_register = next_virtual_register_++;
CHECK_NE(virtual_register, UnallocatedOperand::kInvalidVirtualRegister);
return virtual_register;
}
BlockStartInstruction* InstructionSequence::GetBlockStart(
BasicBlock::RpoNumber rpo) const {
const InstructionBlock* block = InstructionBlockAt(rpo);
......
......@@ -73,9 +73,9 @@ class InstructionOperand : public ZoneObject {
static void TearDownCaches();
protected:
typedef BitField64<Kind, 0, 3> KindField;
typedef BitField<Kind, 0, 3> KindField;
uint64_t value_;
uint32_t value_;
};
typedef ZoneVector<InstructionOperand*> InstructionOperandVector;
......@@ -115,27 +115,29 @@ class UnallocatedOperand : public InstructionOperand {
USED_AT_END
};
static const int kInvalidVirtualRegister = -1;
explicit UnallocatedOperand(ExtendedPolicy policy)
: InstructionOperand(UNALLOCATED, 0) {
value_ |= VirtualRegisterField::encode(kInvalidVirtualRegister);
: InstructionOperand(UNALLOCATED, 0),
virtual_register_(kInvalidVirtualRegister) {
value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
value_ |= ExtendedPolicyField::encode(policy);
value_ |= LifetimeField::encode(USED_AT_END);
}
UnallocatedOperand(BasicPolicy policy, int index)
: InstructionOperand(UNALLOCATED, 0) {
: InstructionOperand(UNALLOCATED, 0),
virtual_register_(kInvalidVirtualRegister) {
DCHECK(policy == FIXED_SLOT);
value_ |= VirtualRegisterField::encode(kInvalidVirtualRegister);
value_ |= BasicPolicyField::encode(policy);
value_ |= static_cast<int64_t>(index) << FixedSlotIndexField::kShift;
value_ |= static_cast<int32_t>(index) << FixedSlotIndexField::kShift;
DCHECK(this->fixed_slot_index() == index);
}
UnallocatedOperand(ExtendedPolicy policy, int index)
: InstructionOperand(UNALLOCATED, 0) {
: InstructionOperand(UNALLOCATED, 0),
virtual_register_(kInvalidVirtualRegister) {
DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
value_ |= VirtualRegisterField::encode(kInvalidVirtualRegister);
value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
value_ |= ExtendedPolicyField::encode(policy);
value_ |= LifetimeField::encode(USED_AT_END);
......@@ -143,8 +145,8 @@ class UnallocatedOperand : public InstructionOperand {
}
UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime)
: InstructionOperand(UNALLOCATED, 0) {
value_ |= VirtualRegisterField::encode(kInvalidVirtualRegister);
: InstructionOperand(UNALLOCATED, 0),
virtual_register_(kInvalidVirtualRegister) {
value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
value_ |= ExtendedPolicyField::encode(policy);
value_ |= LifetimeField::encode(lifetime);
......@@ -172,35 +174,32 @@ class UnallocatedOperand : public InstructionOperand {
// because it accommodates a larger pay-load.
//
// For FIXED_SLOT policy:
// +------------------------------------------+
// | slot_index | vreg | 0 | 001 |
// +------------------------------------------+
// +-----------------------------+
// | slot_index | 0 | 001 |
// +-----------------------------+
//
// For all other (extended) policies:
// +------------------------------------------+
// | reg_index | L | PPP | vreg | 1 | 001 | L ... Lifetime
// +------------------------------------------+ P ... Policy
// +----------------------------------+
// | reg_index | L | PPP | 1 | 001 | L ... Lifetime
// +----------------------------------+ P ... Policy
//
// The slot index is a signed value which requires us to decode it manually
// instead of using the BitField64 utility class.
// instead of using the BitField utility class.
// The superclass has a KindField.
STATIC_ASSERT(KindField::kSize == 3);
// BitFields for all unallocated operands.
class BasicPolicyField : public BitField64<BasicPolicy, 3, 1> {};
class VirtualRegisterField : public BitField64<unsigned, 4, 30> {};
class BasicPolicyField : public BitField<BasicPolicy, 3, 1> {};
// BitFields specific to BasicPolicy::FIXED_SLOT.
class FixedSlotIndexField : public BitField64<int, 34, 30> {};
class FixedSlotIndexField : public BitField<int, 4, 28> {};
// BitFields specific to BasicPolicy::EXTENDED_POLICY.
class ExtendedPolicyField : public BitField64<ExtendedPolicy, 34, 3> {};
class LifetimeField : public BitField64<Lifetime, 37, 1> {};
class FixedRegisterField : public BitField64<int, 38, 6> {};
class ExtendedPolicyField : public BitField<ExtendedPolicy, 4, 3> {};
class LifetimeField : public BitField<Lifetime, 7, 1> {};
class FixedRegisterField : public BitField<int, 8, 6> {};
static const int kInvalidVirtualRegister = VirtualRegisterField::kMax;
static const int kMaxVirtualRegisters = VirtualRegisterField::kMax;
static const int kFixedSlotIndexWidth = FixedSlotIndexField::kSize;
static const int kMaxFixedSlotIndex = (1 << (kFixedSlotIndexWidth - 1)) - 1;
static const int kMinFixedSlotIndex = -(1 << (kFixedSlotIndexWidth - 1));
......@@ -244,7 +243,7 @@ class UnallocatedOperand : public InstructionOperand {
// [fixed_slot_index]: Only for FIXED_SLOT.
int fixed_slot_index() const {
DCHECK(HasFixedSlotPolicy());
return static_cast<int>(bit_cast<int64_t>(value_) >>
return static_cast<int>(bit_cast<int32_t>(value_) >>
FixedSlotIndexField::kShift);
}
......@@ -255,16 +254,18 @@ class UnallocatedOperand : public InstructionOperand {
}
// [virtual_register]: The virtual register ID for this operand.
int virtual_register() const { return VirtualRegisterField::decode(value_); }
void set_virtual_register(unsigned id) {
value_ = VirtualRegisterField::update(value_, id);
}
int32_t virtual_register() const { return virtual_register_; }
void set_virtual_register(int32_t id) { virtual_register_ = id; }
// [lifetime]: Only for non-FIXED_SLOT.
bool IsUsedAtStart() const {
DCHECK(basic_policy() == EXTENDED_POLICY);
return LifetimeField::decode(value_) == USED_AT_START;
}
private:
// TODO(dcarney): this should really be unsigned.
int32_t virtual_register_;
};
......@@ -947,7 +948,7 @@ class InstructionSequence FINAL : public ZoneObject {
InstructionSequence(Zone* zone, InstructionBlocks* instruction_blocks);
int NextVirtualRegister() { return next_virtual_register_++; }
int NextVirtualRegister();
int VirtualRegisterCount() const { return next_virtual_register_; }
const InstructionBlocks& instruction_blocks() const {
......
......@@ -1004,12 +1004,6 @@ void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
bool run_verifier) {
PipelineData* data = this->data_;
int node_count = data->sequence()->VirtualRegisterCount();
if (node_count > UnallocatedOperand::kMaxVirtualRegisters) {
data->set_compilation_failed();
return;
}
// Don't track usage for this zone in compiler stats.
SmartPointer<Zone> verifier_zone;
RegisterAllocatorVerifier* verifier = nullptr;
......@@ -1041,15 +1035,7 @@ void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
CHECK(!data->register_allocator()->ExistsUseWithoutDefinition());
}
Run<AllocateGeneralRegistersPhase>();
if (!data->register_allocator()->AllocationOk()) {
data->set_compilation_failed();
return;
}
Run<AllocateDoubleRegistersPhase>();
if (!data->register_allocator()->AllocationOk()) {
data->set_compilation_failed();
return;
}
if (FLAG_turbo_reuse_spill_slots) {
Run<ReuseSpillSlotsPhase>();
}
......
......@@ -575,8 +575,7 @@ RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
reusable_slots_(local_zone()),
spill_ranges_(local_zone()),
mode_(UNALLOCATED_REGISTERS),
num_registers_(-1),
allocation_ok_(true) {
num_registers_(-1) {
DCHECK(this->config()->num_general_registers() <=
RegisterConfiguration::kMaxGeneralRegisters);
DCHECK(this->config()->num_double_registers() <=
......@@ -1024,7 +1023,6 @@ bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) {
auto spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
CHECK(first_op_spill->TryMerge(spill_range));
SpillBetween(range, range->Start(), pos->pos());
if (!AllocationOk()) return false;
DCHECK(UnhandledIsSorted());
return true;
}
......@@ -1043,7 +1041,6 @@ void RegisterAllocator::MeetRegisterConstraints(const InstructionBlock* block) {
if (i < end) instr = InstructionAt(i + 1);
if (i > start) prev_instr = InstructionAt(i - 1);
MeetConstraintsBetween(prev_instr, instr, i);
if (!AllocationOk()) return;
}
}
......@@ -1932,7 +1929,6 @@ void RegisterAllocator::AllocateRegisters() {
// Do not spill live range eagerly if use position that can benefit from
// the register is too close to the start of live range.
SpillBetween(current, current->Start(), pos->pos());
if (!AllocationOk()) return;
DCHECK(UnhandledIsSorted());
continue;
}
......@@ -1942,7 +1938,6 @@ void RegisterAllocator::AllocateRegisters() {
if (TryReuseSpillForPhi(current)) {
continue;
}
if (!AllocationOk()) return;
}
for (size_t i = 0; i < active_live_ranges().size(); ++i) {
......@@ -1970,11 +1965,7 @@ void RegisterAllocator::AllocateRegisters() {
DCHECK(!current->HasRegisterAssigned() && !current->IsSpilled());
bool result = TryAllocateFreeReg(current);
if (!AllocationOk()) return;
if (!result) AllocateBlockedReg(current);
if (!AllocationOk()) return;
if (current->HasRegisterAssigned()) {
AddToActive(current);
}
......@@ -2186,7 +2177,6 @@ bool RegisterAllocator::TryAllocateFreeReg(LiveRange* current) {
// Register reg is available at the range start but becomes blocked before
// the range end. Split current at position where it becomes blocked.
auto tail = SplitRangeAt(current, pos);
if (!AllocationOk()) return false;
AddToUnhandledSorted(tail);
}
......@@ -2267,7 +2257,6 @@ void RegisterAllocator::AllocateBlockedReg(LiveRange* current) {
// position.
LiveRange* tail = SplitBetween(current, current->Start(),
block_pos[reg].InstructionStart());
if (!AllocationOk()) return;
AddToUnhandledSorted(tail);
}
......@@ -2346,7 +2335,6 @@ void RegisterAllocator::SplitAndSpillIntersecting(LiveRange* current) {
// current live-range is larger than their end.
SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos());
}
if (!AllocationOk()) return;
ActiveToHandled(range);
--i;
}
......@@ -2365,7 +2353,6 @@ void RegisterAllocator::SplitAndSpillIntersecting(LiveRange* current) {
next_intersection = Min(next_intersection, next_pos->pos());
SpillBetween(range, split_pos, next_intersection);
}
if (!AllocationOk()) return;
InactiveToHandled(range);
--i;
}
......@@ -2393,7 +2380,6 @@ LiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range,
!InstructionAt(pos.InstructionIndex())->IsControl());
int vreg = GetVirtualRegister();
if (!AllocationOk()) return nullptr;
auto result = LiveRangeFor(vreg);
range->SplitAt(pos, result, local_zone());
return result;
......@@ -2451,7 +2437,6 @@ LifetimePosition RegisterAllocator::FindOptimalSplitPos(LifetimePosition start,
void RegisterAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) {
auto second_part = SplitRangeAt(range, pos);
if (!AllocationOk()) return;
Spill(second_part);
}
......@@ -2468,7 +2453,6 @@ void RegisterAllocator::SpillBetweenUntil(LiveRange* range,
LifetimePosition end) {
CHECK(start.Value() < end.Value());
auto second_part = SplitRangeAt(range, start);
if (!AllocationOk()) return;
if (second_part->Start().Value() < end.Value()) {
// The split result intersects with [start, end[.
......@@ -2477,7 +2461,6 @@ void RegisterAllocator::SpillBetweenUntil(LiveRange* range,
auto third_part = SplitBetween(
second_part, Max(second_part->Start().InstructionEnd(), until),
end.PrevInstruction().InstructionEnd());
if (!AllocationOk()) return;
DCHECK(third_part != second_part);
......
......@@ -377,8 +377,6 @@ class RegisterAllocator FINAL : public ZoneObject {
InstructionSequence* code,
const char* debug_name = nullptr);
bool AllocationOk() { return allocation_ok_; }
const ZoneVector<LiveRange*>& live_ranges() const { return live_ranges_; }
const ZoneVector<LiveRange*>& fixed_live_ranges() const {
return fixed_live_ranges_;
......@@ -421,15 +419,7 @@ class RegisterAllocator FINAL : public ZoneObject {
void ResolveControlFlow();
private:
int GetVirtualRegister() {
int vreg = code()->NextVirtualRegister();
if (vreg >= UnallocatedOperand::kMaxVirtualRegisters) {
allocation_ok_ = false;
// Maintain the invariant that we return something below the maximum.
return 0;
}
return vreg;
}
int GetVirtualRegister() { return code()->NextVirtualRegister(); }
// Checks whether the value of a given virtual register is a reference.
// TODO(titzer): rename this to IsReference.
......@@ -625,9 +615,6 @@ class RegisterAllocator FINAL : public ZoneObject {
BitVector* assigned_registers_;
BitVector* assigned_double_registers_;
// Indicates success or failure during register allocation.
bool allocation_ok_;
#ifdef DEBUG
LifetimePosition allocation_finger_;
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment