From 8985169828570f4e6a288a2fd21b672841dbb8aa Mon Sep 17 00:00:00 2001 From: Edwin Smith Date: Sat, 4 May 2013 09:23:16 -0700 Subject: [PATCH] Move spillslot field from SSATmp to linearscan pass Spillslot is an internal field for the linear scan pass, we don't want it in SSATmp. --- hphp/runtime/vm/translator/hopt/ir.h | 25 ++------- .../runtime/vm/translator/hopt/linearscan.cpp | 54 ++++++++++--------- 2 files changed, 35 insertions(+), 44 deletions(-) diff --git a/hphp/runtime/vm/translator/hopt/ir.h b/hphp/runtime/vm/translator/hopt/ir.h index 7cd707fcd..123a1dada 100644 --- a/hphp/runtime/vm/translator/hopt/ir.h +++ b/hphp/runtime/vm/translator/hopt/ir.h @@ -2072,19 +2072,6 @@ public: SpillInfo getSpillInfo(int idx) const { assert(m_isSpilled); return m_spillInfo[idx]; } - /* - * During register allocation, this is used to track spill locations - * that are assigned to specific SSATmps. A value of -1 is used to - * indicate no spill slot has been assigned. - * - * After register allocation, use getSpillInfo to access information - * about where we've decided to spill/fill a given SSATmp from. - * This value doesn't have any meaning outside of the linearscan - * pass. - */ - int32_t getSpillSlot() const { return m_spillSlot; } - void setSpillSlot(int32_t val) { m_spillSlot = val; } - private: friend class IRFactory; friend class TraceBuilder; @@ -2093,12 +2080,11 @@ private: // destructed, so don't add complex members. SSATmp(uint32_t opndId, IRInstruction* i, int dstId = 0) : m_inst(i) - , m_id(opndId) , m_type(outputType(i, dstId)) + , m_id(opndId) , m_lastUseId(0) , m_useCount(0) , m_isSpilled(false) - , m_spillSlot(-1) { m_regs[0] = m_regs[1] = Transl::InvalidReg; } @@ -2106,12 +2092,11 @@ private: SSATmp& operator=(const SSATmp&); IRInstruction* m_inst; - const uint32_t m_id; Type m_type; // type when defined - uint32_t m_lastUseId; - uint16_t m_useCount; - bool m_isSpilled : 1; - int32_t m_spillSlot : 31; + const uint32_t m_id; + uint32_t m_lastUseId; + uint16_t m_useCount; + bool m_isSpilled; /* * m_regs[0] is always the value of this SSATmp. diff --git a/hphp/runtime/vm/translator/hopt/linearscan.cpp b/hphp/runtime/vm/translator/hopt/linearscan.cpp index 04ad4ec21..bbfb51c7f 100644 --- a/hphp/runtime/vm/translator/hopt/linearscan.cpp +++ b/hphp/runtime/vm/translator/hopt/linearscan.cpp @@ -79,10 +79,10 @@ private: struct SlotInfo { // the SSATmp that represents this spill location - SSATmp* m_spillTmp; + SSATmp* spillTmp; // The latest SSATmp that has the most recent reloaded spilled value // If it's NULL, we have to reload this slot before using it. - SSATmp* m_latestReload; + SSATmp* latestReload; }; class PreColoringHint { @@ -113,6 +113,7 @@ private: void allocRegToTmp(SSATmp* ssaTmp, uint32_t index); void freeRegsAtId(uint32_t id); void spill(SSATmp* tmp); + void numberInstructions(const BlockList& blocks); template SSATmp* cns(T val) { return m_irFactory->cns(val); @@ -158,6 +159,11 @@ private: BlockList m_blocks; // all basic blocks in reverse postorder IdomVector m_idoms; // immediate dominator vector + // any tmp that has been spilled has an entry in this array with + // the spill-slot number, which is an index into m_slots[]. tmps that + // have not spilled have -1. + StateVector m_spillSlots; + // the list of native instructions in the trace sorted by instruction ID; // i.e. a filtered list in the same order as visited by m_blocks. smart::list m_natives; @@ -226,6 +232,7 @@ void LinearScan::StateSave::restore(LinearScan* ls) { LinearScan::LinearScan(IRFactory* irFactory) : m_irFactory(irFactory) + , m_spillSlots(irFactory, -1) , m_jmps(irFactory, JmpList()) { for (int i = 0; i < kNumX64Regs; i++) { @@ -276,10 +283,10 @@ void LinearScan::allocRegToInstruction(InstructionList::iterator it) { smart::vector needsReloading(inst->getNumSrcs(), true); for (uint32_t i = 0; i < inst->getNumSrcs(); ++i) { SSATmp* tmp = inst->getSrc(i); - int32_t slotId = tmp->getSpillSlot(); + int32_t slotId = m_spillSlots[tmp]; if (slotId == -1) { needsReloading[i] = false; - } else if ((tmp = m_slots[slotId].m_latestReload)) { + } else if ((tmp = m_slots[slotId].latestReload)) { needsReloading[i] = false; inst->setSrc(i, tmp); } @@ -292,12 +299,12 @@ void LinearScan::allocRegToInstruction(InstructionList::iterator it) { for (uint32_t i = 0; i < inst->getNumSrcs(); ++i) { if (needsReloading[i]) { SSATmp* tmp = inst->getSrc(i); - int32_t slotId = tmp->getSpillSlot(); + int32_t slotId = m_spillSlots[tmp]; // is spilled, and not reloaded. // Therefore, We need to reload the value into a new SSATmp. // Insert the Reload instruction. - SSATmp* spillTmp = m_slots[slotId].m_spillTmp; + SSATmp* spillTmp = m_slots[slotId].spillTmp; IRInstruction* reload = m_irFactory->gen(Reload, spillTmp); inst->getBlock()->insert(it, reload); @@ -306,7 +313,7 @@ void LinearScan::allocRegToInstruction(InstructionList::iterator it) { // Replace with in . SSATmp* reloadTmp = reload->getDst(); reloadTmp->setLastUseId(spillTmp->getLastUseId()); - reloadTmp->setSpillSlot(slotId); + m_spillSlots[reloadTmp] = slotId; inst->setSrc(i, reloadTmp); // reloadTmp and tmp share the same type. Since it was spilled, it // must be using its entire needed-count of registers. @@ -316,7 +323,7 @@ void LinearScan::allocRegToInstruction(InstructionList::iterator it) { allocRegToTmp(reloadTmp, locIndex); } // Remember this reload tmp in case we can reuse it in later blocks. - m_slots[slotId].m_latestReload = reloadTmp; + m_slots[slotId].latestReload = reloadTmp; dumpIR(reload, "created reload"); } } @@ -457,7 +464,7 @@ void LinearScan::allocRegToTmp(SSATmp* ssaTmp, uint32_t index) { // Setting the last use ID to the next native is conservative. // Setting it to the last use before the next native would be more precise, // but that would be more expensive to compute. - if (ssaTmp->getSpillSlot() == -1) { + if (m_spillSlots[ssaTmp] == -1) { createSpillSlot(ssaTmp); } ssaTmp->setLastUseId(getNextNativeId()); @@ -879,14 +886,14 @@ void LinearScan::preAllocSpillLoc(uint32_t numSpillLocs) { } // Assign ids to each instruction in linear order. -void numberInstructions(const BlockList& blocks) { +void LinearScan::numberInstructions(const BlockList& blocks) { + m_spillSlots.reset(); forEachInst( blocks, [](IRInstruction* inst) { for (SSATmp& dst : inst->getDsts()) { dst.setLastUseId(0); dst.setUseCount(0); - dst.setSpillSlot(-1); } } ); @@ -1035,9 +1042,9 @@ void LinearScan::allocRegsOneTrace(BlockList::iterator& blockIt, // clear remembered reloads that don't dominate this block for (SlotInfo& slot : m_slots) { - if (SSATmp* reload = slot.m_latestReload) { + if (SSATmp* reload = slot.latestReload) { if (!dominates(reload->inst()->getBlock(), block, m_idoms)) { - slot.m_latestReload = nullptr; + slot.latestReload = nullptr; } } } @@ -1068,7 +1075,7 @@ void LinearScan::allocRegsOneTrace(BlockList::iterator& blockIt, while (begin < end) { SlotInfo& slot = m_slots[begin++]; - IRInstruction* spill = slot.m_spillTmp->inst(); + IRInstruction* spill = slot.spillTmp->inst(); IRInstruction* inst = spill->getSrc(0)->inst(); Block* block = inst->getBlock(); if (!isMain && block->getTrace()->isMain()) { @@ -1269,8 +1276,7 @@ void LinearScan::rematerializeAux() { void LinearScan::removeUnusedSpills() { for (SlotInfo& slot : m_slots) { - SSATmp* spillTmp = slot.m_spillTmp; - IRInstruction* spill = spillTmp->inst(); + IRInstruction* spill = slot.spillTmp->inst(); if (spill->getDst()->getUseCount() == 0) { Block* block = spill->getBlock(); block->erase(block->iteratorTo(spill)); @@ -1366,9 +1372,9 @@ void LinearScan::freeReg(RegState* reg) { pushFreeReg(reg); // The shouldn't be reused any more. SSATmp* tmp = reg->m_ssaTmp; - int32_t slotId = tmp->getSpillSlot(); + int32_t slotId = m_spillSlots[tmp]; if (slotId != -1) { - m_slots[slotId].m_latestReload = nullptr; + m_slots[slotId].latestReload = nullptr; } reg->m_ssaTmp = nullptr; } @@ -1415,29 +1421,29 @@ void LinearScan::spill(SSATmp* tmp) { it = next; } - if (tmp->getSpillSlot() == -1) { + if (m_spillSlots[tmp] == -1) { // hasn't been spilled before. // We need to create a new spill slot for it. uint32_t slotId = createSpillSlot(tmp); // createSpillSlot sets the latest reloaded value of slotId to tmp. // Here, we need reset this value because tmp is spilled and no longer // synced with memory. - m_slots[slotId].m_latestReload = nullptr; + m_slots[slotId].latestReload = nullptr; } } // Create a spill slot for . uint32_t LinearScan::createSpillSlot(SSATmp* tmp) { uint32_t slotId = m_slots.size(); - tmp->setSpillSlot(slotId); + m_spillSlots[tmp] = slotId; IRInstruction* spillInst = m_irFactory->gen(Spill, tmp); SSATmp* spillTmp = spillInst->getDst(); SlotInfo si; - si.m_spillTmp = spillTmp; - si.m_latestReload = tmp; + si.spillTmp = spillTmp; + si.latestReload = tmp; m_slots.push_back(si); // The spill slot inherits the last use ID of the spilled tmp. - si.m_spillTmp->setLastUseId(tmp->getLastUseId()); + si.spillTmp->setLastUseId(tmp->getLastUseId()); return slotId; }