From 47608c900ae56804d0f9f7cb5aca69f3d5f05823 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Thu, 2 May 2013 09:51:07 +0000 Subject: [PATCH] Allow more virtual registers to be encoded in LUnallocated. This is a preparation which allows us to bump the virtual register width from 15 to 18 bit without sacrificing width for other fields inside an unallocated lithium operand. R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/14639008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14513 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 2 +- src/compiler.cc | 4 +- src/ia32/lithium-ia32.cc | 2 +- src/lithium-allocator.cc | 14 +-- src/lithium.cc | 15 +-- src/lithium.h | 206 +++++++++++++++++++++++++-------------- src/mips/lithium-mips.cc | 2 +- src/x64/lithium-x64.cc | 2 +- 8 files changed, 154 insertions(+), 93 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 7e81ca60e8..0d84ef37bb 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -2453,7 +2453,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. - if (spill_index > LUnallocated::kMaxFixedIndex) { + if (spill_index > LUnallocated::kMaxFixedSlotIndex) { Abort("Too many spill slots needed for OSR"); spill_index = 0; } diff --git a/src/compiler.cc b/src/compiler.cc index dce817129c..adb6eaf8d8 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -299,14 +299,14 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() { // // The encoding is as a signed value, with parameters and receiver using // the negative indices and locals the non-negative ones. - const int parameter_limit = -LUnallocated::kMinFixedIndex; + const int parameter_limit = -LUnallocated::kMinFixedSlotIndex; Scope* scope = info()->scope(); if ((scope->num_parameters() + 1) > parameter_limit) { info()->set_bailout_reason("too many parameters"); return AbortOptimization(); } - const int locals_limit = LUnallocated::kMaxFixedIndex; + const int locals_limit = LUnallocated::kMaxFixedSlotIndex; if (!info()->osr_ast_id().IsNone() && scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) { info()->set_bailout_reason("too many parameters/locals"); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index cffe5b1626..371c16c8e6 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -2584,7 +2584,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. - if (spill_index > LUnallocated::kMaxFixedIndex) { + if (spill_index > LUnallocated::kMaxFixedSlotIndex) { Abort("Too many spill slots needed for OSR"); spill_index = 0; } diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc index a010f4ea80..d66f6b096a 100644 --- a/src/lithium-allocator.cc +++ b/src/lithium-allocator.cc @@ -625,13 +625,13 @@ LOperand* LAllocator::AllocateFixed(LUnallocated* operand, bool is_tagged) { TraceAlloc("Allocating fixed reg for op %d\n", operand->virtual_register()); ASSERT(operand->HasFixedPolicy()); - if (operand->policy() == LUnallocated::FIXED_SLOT) { - operand->ConvertTo(LOperand::STACK_SLOT, operand->fixed_index()); - } else if (operand->policy() == LUnallocated::FIXED_REGISTER) { - int reg_index = operand->fixed_index(); + if (operand->HasFixedSlotPolicy()) { + operand->ConvertTo(LOperand::STACK_SLOT, operand->fixed_slot_index()); + } else if (operand->HasFixedRegisterPolicy()) { + int reg_index = operand->fixed_register_index(); operand->ConvertTo(LOperand::REGISTER, reg_index); - } else if (operand->policy() == LUnallocated::FIXED_DOUBLE_REGISTER) { - int reg_index = operand->fixed_index(); + } else if (operand->HasFixedDoubleRegisterPolicy()) { + int reg_index = operand->fixed_register_index(); operand->ConvertTo(LOperand::DOUBLE_REGISTER, reg_index); } else { UNREACHABLE(); @@ -846,7 +846,7 @@ void LAllocator::MeetConstraintsBetween(LInstruction* first, bool is_tagged = HasTaggedValue(cur_input->virtual_register()); AllocateFixed(cur_input, gap_index + 1, is_tagged); AddConstraintsGapMove(gap_index, input_copy, cur_input); - } else if (cur_input->policy() == LUnallocated::WRITABLE_REGISTER) { + } else if (cur_input->HasWritableRegisterPolicy()) { // The live range of writable input registers always goes until the end // of the instruction. ASSERT(!cur_input->IsUsedAtStart()); diff --git a/src/lithium.cc b/src/lithium.cc index 10d7f71332..539f4eefba 100644 --- a/src/lithium.cc +++ b/src/lithium.cc @@ -58,24 +58,27 @@ void LOperand::PrintTo(StringStream* stream) { case UNALLOCATED: unalloc = LUnallocated::cast(this); stream->Add("v%d", unalloc->virtual_register()); - switch (unalloc->policy()) { + if (unalloc->basic_policy() == LUnallocated::FIXED_SLOT) { + stream->Add("(=%dS)", unalloc->fixed_slot_index()); + break; + } + switch (unalloc->extended_policy()) { case LUnallocated::NONE: break; case LUnallocated::FIXED_REGISTER: { + int reg_index = unalloc->fixed_register_index(); const char* register_name = - Register::AllocationIndexToString(unalloc->fixed_index()); + Register::AllocationIndexToString(reg_index); stream->Add("(=%s)", register_name); break; } case LUnallocated::FIXED_DOUBLE_REGISTER: { + int reg_index = unalloc->fixed_register_index(); const char* double_register_name = - DoubleRegister::AllocationIndexToString(unalloc->fixed_index()); + DoubleRegister::AllocationIndexToString(reg_index); stream->Add("(=%s)", double_register_name); break; } - case LUnallocated::FIXED_SLOT: - stream->Add("(=%dS)", unalloc->fixed_index()); - break; case LUnallocated::MUST_HAVE_REGISTER: stream->Add("(R)"); break; diff --git a/src/lithium.h b/src/lithium.h index 24182747e3..25229991a6 100644 --- a/src/lithium.h +++ b/src/lithium.h @@ -92,12 +92,16 @@ class LOperand: public ZoneObject { class LUnallocated: public LOperand { public: - enum Policy { + enum BasicPolicy { + FIXED_SLOT, + EXTENDED_POLICY + }; + + enum ExtendedPolicy { NONE, ANY, FIXED_REGISTER, FIXED_DOUBLE_REGISTER, - FIXED_SLOT, MUST_HAVE_REGISTER, WRITABLE_REGISTER, SAME_AS_FIRST_INPUT @@ -117,76 +121,32 @@ class LUnallocated: public LOperand { USED_AT_END }; - explicit LUnallocated(Policy policy) : LOperand(UNALLOCATED, 0) { - Initialize(policy, 0, USED_AT_END); + explicit LUnallocated(ExtendedPolicy policy) : LOperand(UNALLOCATED, 0) { + value_ |= BasicPolicyField::encode(EXTENDED_POLICY); + value_ |= ExtendedPolicyField::encode(policy); + value_ |= LifetimeField::encode(USED_AT_END); } - LUnallocated(Policy policy, int fixed_index) : LOperand(UNALLOCATED, 0) { - Initialize(policy, fixed_index, USED_AT_END); + LUnallocated(BasicPolicy policy, int index) : LOperand(UNALLOCATED, 0) { + ASSERT(policy == FIXED_SLOT); + value_ |= BasicPolicyField::encode(policy); + value_ |= index << FixedSlotIndexField::kShift; + ASSERT(this->fixed_slot_index() == index); } - LUnallocated(Policy policy, Lifetime lifetime) : LOperand(UNALLOCATED, 0) { - Initialize(policy, 0, lifetime); + LUnallocated(ExtendedPolicy policy, int index) : LOperand(UNALLOCATED, 0) { + ASSERT(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER); + value_ |= BasicPolicyField::encode(EXTENDED_POLICY); + value_ |= ExtendedPolicyField::encode(policy); + value_ |= LifetimeField::encode(USED_AT_END); + value_ |= FixedRegisterField::encode(index); } - // The superclass has a KindField. Some policies have a signed fixed - // index in the upper bits. - static const int kPolicyWidth = 3; - static const int kLifetimeWidth = 1; - static const int kVirtualRegisterWidth = 15; - - static const int kPolicyShift = kKindFieldWidth; - static const int kLifetimeShift = kPolicyShift + kPolicyWidth; - static const int kVirtualRegisterShift = kLifetimeShift + kLifetimeWidth; - static const int kFixedIndexShift = - kVirtualRegisterShift + kVirtualRegisterWidth; - static const int kFixedIndexWidth = 32 - kFixedIndexShift; - STATIC_ASSERT(kFixedIndexWidth > 5); - - class PolicyField : public BitField { }; - - class LifetimeField - : public BitField { - }; - - class VirtualRegisterField - : public BitField { - }; - - static const int kMaxVirtualRegisters = 1 << kVirtualRegisterWidth; - static const int kMaxFixedIndex = (1 << (kFixedIndexWidth - 1)) - 1; - static const int kMinFixedIndex = -(1 << (kFixedIndexWidth - 1)); - - bool HasAnyPolicy() const { - return policy() == ANY; - } - bool HasFixedPolicy() const { - return policy() == FIXED_REGISTER || - policy() == FIXED_DOUBLE_REGISTER || - policy() == FIXED_SLOT; - } - bool HasRegisterPolicy() const { - return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER; - } - bool HasSameAsInputPolicy() const { - return policy() == SAME_AS_FIRST_INPUT; - } - Policy policy() const { return PolicyField::decode(value_); } - void set_policy(Policy policy) { - value_ = PolicyField::update(value_, policy); - } - int fixed_index() const { - return static_cast(value_) >> kFixedIndexShift; - } - - int virtual_register() const { - return VirtualRegisterField::decode(value_); - } - - void set_virtual_register(unsigned id) { - value_ = VirtualRegisterField::update(value_, id); + LUnallocated(ExtendedPolicy policy, Lifetime lifetime) + : LOperand(UNALLOCATED, 0) { + value_ |= BasicPolicyField::encode(EXTENDED_POLICY); + value_ |= ExtendedPolicyField::encode(policy); + value_ |= LifetimeField::encode(lifetime); } LUnallocated* CopyUnconstrained(Zone* zone) { @@ -200,16 +160,114 @@ class LUnallocated: public LOperand { return reinterpret_cast(op); } - bool IsUsedAtStart() { - return LifetimeField::decode(value_) == USED_AT_START; + // The encoding used for LUnallocated operands depends on the policy that is + // stored within the operand. The FIXED_SLOT policy uses a compact encoding + // because it accommodates a larger pay-load. + // + // For FIXED_SLOT policy: + // +------------------------------------------+ + // | slot_index | vreg | 0 | 001 | + // +------------------------------------------+ + // + // For all other (extended) policies: + // +------------------------------------------+ + // | reg_index | L | PPP | vreg | 1 | 001 | L ... Lifetime + // +------------------------------------------+ P ... Policy + // + // The slot index is a signed value which requires us to decode it manually + // instead of using the BitField utility class. + + // The superclass has a KindField. + STATIC_ASSERT(kKindFieldWidth == 3); + + // BitFields for all unallocated operands. + class BasicPolicyField : public BitField {}; + // TODO(mstarzinger): Bump this from 15 bit to 18 bit in a follow-up CL. + class VirtualRegisterField : public BitField {}; + + // BitFields specific to BasicPolicy::FIXED_SLOT. + class FixedSlotIndexField : public BitField {}; + + // BitFields specific to BasicPolicy::EXTENDED_POLICY. + class ExtendedPolicyField : public BitField {}; + class LifetimeField : public BitField {}; + class FixedRegisterField : public BitField {}; + + static const int kMaxVirtualRegisters = VirtualRegisterField::kMax + 1; + static const int kFixedSlotIndexWidth = FixedSlotIndexField::kSize; + static const int kMaxFixedSlotIndex = (1 << (kFixedSlotIndexWidth - 1)) - 1; + static const int kMinFixedSlotIndex = -(1 << (kFixedSlotIndexWidth - 1)); + + // Predicates for the operand policy. + bool HasAnyPolicy() const { + return basic_policy() == EXTENDED_POLICY && + extended_policy() == ANY; + } + bool HasFixedPolicy() const { + return basic_policy() == FIXED_SLOT || + extended_policy() == FIXED_REGISTER || + extended_policy() == FIXED_DOUBLE_REGISTER; + } + bool HasRegisterPolicy() const { + return basic_policy() == EXTENDED_POLICY && ( + extended_policy() == WRITABLE_REGISTER || + extended_policy() == MUST_HAVE_REGISTER); + } + bool HasSameAsInputPolicy() const { + return basic_policy() == EXTENDED_POLICY && + extended_policy() == SAME_AS_FIRST_INPUT; + } + bool HasFixedSlotPolicy() const { + return basic_policy() == FIXED_SLOT; + } + bool HasFixedRegisterPolicy() const { + return basic_policy() == EXTENDED_POLICY && + extended_policy() == FIXED_REGISTER; + } + bool HasFixedDoubleRegisterPolicy() const { + return basic_policy() == EXTENDED_POLICY && + extended_policy() == FIXED_DOUBLE_REGISTER; + } + bool HasWritableRegisterPolicy() const { + return basic_policy() == EXTENDED_POLICY && + extended_policy() == WRITABLE_REGISTER; } - private: - void Initialize(Policy policy, int fixed_index, Lifetime lifetime) { - value_ |= PolicyField::encode(policy); - value_ |= LifetimeField::encode(lifetime); - value_ |= fixed_index << kFixedIndexShift; - ASSERT(this->fixed_index() == fixed_index); + // [basic_policy]: Distinguish between FIXED_SLOT and all other policies. + BasicPolicy basic_policy() const { + return BasicPolicyField::decode(value_); + } + + // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. + ExtendedPolicy extended_policy() const { + ASSERT(basic_policy() == EXTENDED_POLICY); + return ExtendedPolicyField::decode(value_); + } + + // [fixed_slot_index]: Only for FIXED_SLOT. + int fixed_slot_index() const { + ASSERT(HasFixedSlotPolicy()); + return static_cast(value_) >> FixedSlotIndexField::kShift; + } + + // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER. + int fixed_register_index() const { + ASSERT(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy()); + return FixedRegisterField::decode(value_); + } + + // [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); + } + + // [lifetime]: Only for non-FIXED_SLOT. + bool IsUsedAtStart() { + ASSERT(basic_policy() == EXTENDED_POLICY); + return LifetimeField::decode(value_) == USED_AT_START; } }; diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index d346a29b0b..79817c31f8 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -2328,7 +2328,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. - if (spill_index > LUnallocated::kMaxFixedIndex) { + if (spill_index > LUnallocated::kMaxFixedSlotIndex) { Abort("Too many spill slots needed for OSR"); spill_index = 0; } diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 094f5ed346..d75d1b08ba 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -2384,7 +2384,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. - if (spill_index > LUnallocated::kMaxFixedIndex) { + if (spill_index > LUnallocated::kMaxFixedSlotIndex) { Abort("Too many spill slots needed for OSR"); spill_index = 0; }