From: mstarzinger@chromium.org Date: Thu, 2 May 2013 09:51:07 +0000 (+0000) Subject: Allow more virtual registers to be encoded in LUnallocated. X-Git-Tag: upstream/4.7.83~14373 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=47608c900ae56804d0f9f7cb5aca69f3d5f05823;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 7e81ca6..0d84ef3 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 dce8171..adb6eaf 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 cffe5b1..371c16c 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 a010f4e..d66f6b0 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 10d7f71..539f4ee 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 2418274..2522999 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,99 +121,153 @@ 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 { - }; + LUnallocated(ExtendedPolicy policy, Lifetime lifetime) + : LOperand(UNALLOCATED, 0) { + value_ |= BasicPolicyField::encode(EXTENDED_POLICY); + value_ |= ExtendedPolicyField::encode(policy); + value_ |= LifetimeField::encode(lifetime); + } - class VirtualRegisterField - : public BitField { - }; + LUnallocated* CopyUnconstrained(Zone* zone) { + LUnallocated* result = new(zone) LUnallocated(ANY); + result->set_virtual_register(virtual_register()); + return result; + } - static const int kMaxVirtualRegisters = 1 << kVirtualRegisterWidth; - static const int kMaxFixedIndex = (1 << (kFixedIndexWidth - 1)) - 1; - static const int kMinFixedIndex = -(1 << (kFixedIndexWidth - 1)); + static LUnallocated* cast(LOperand* op) { + ASSERT(op->IsUnallocated()); + return reinterpret_cast(op); + } + // 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 policy() == ANY; + return basic_policy() == EXTENDED_POLICY && + extended_policy() == ANY; } bool HasFixedPolicy() const { - return policy() == FIXED_REGISTER || - policy() == FIXED_DOUBLE_REGISTER || - policy() == FIXED_SLOT; + return basic_policy() == FIXED_SLOT || + extended_policy() == FIXED_REGISTER || + extended_policy() == FIXED_DOUBLE_REGISTER; } bool HasRegisterPolicy() const { - return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER; + return basic_policy() == EXTENDED_POLICY && ( + extended_policy() == WRITABLE_REGISTER || + extended_policy() == MUST_HAVE_REGISTER); } bool HasSameAsInputPolicy() const { - return policy() == SAME_AS_FIRST_INPUT; + 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; } - Policy policy() const { return PolicyField::decode(value_); } - void set_policy(Policy policy) { - value_ = PolicyField::update(value_, policy); + bool HasFixedDoubleRegisterPolicy() const { + return basic_policy() == EXTENDED_POLICY && + extended_policy() == FIXED_DOUBLE_REGISTER; } - int fixed_index() const { - return static_cast(value_) >> kFixedIndexShift; + bool HasWritableRegisterPolicy() const { + return basic_policy() == EXTENDED_POLICY && + extended_policy() == WRITABLE_REGISTER; } - int virtual_register() const { - return VirtualRegisterField::decode(value_); + // [basic_policy]: Distinguish between FIXED_SLOT and all other policies. + BasicPolicy basic_policy() const { + return BasicPolicyField::decode(value_); } - void set_virtual_register(unsigned id) { - value_ = VirtualRegisterField::update(value_, id); + // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. + ExtendedPolicy extended_policy() const { + ASSERT(basic_policy() == EXTENDED_POLICY); + return ExtendedPolicyField::decode(value_); } - LUnallocated* CopyUnconstrained(Zone* zone) { - LUnallocated* result = new(zone) LUnallocated(ANY); - result->set_virtual_register(virtual_register()); - return result; + // [fixed_slot_index]: Only for FIXED_SLOT. + int fixed_slot_index() const { + ASSERT(HasFixedSlotPolicy()); + return static_cast(value_) >> FixedSlotIndexField::kShift; } - static LUnallocated* cast(LOperand* op) { - ASSERT(op->IsUnallocated()); - return reinterpret_cast(op); + // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER. + int fixed_register_index() const { + ASSERT(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy()); + return FixedRegisterField::decode(value_); } - bool IsUsedAtStart() { - return LifetimeField::decode(value_) == USED_AT_START; + // [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); } - 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); + // [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 d346a29..79817c3 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 094f5ed..d75d1b0 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; }