Fix an issue in the register allocator

An optimization I'm working on sent the register allocator a
CFG that looked like this:

  M0
  | \
  |  M1
  M3 | \
  |  |  E4
  |  M8
  | /
  M2
  |
  M5

The RPO was 0 1 8 4 3 2 5.

It assert-fails here because it visited E4 before M3, and it appears
this would incorrectly mark everything as free.

This diff changes the register allocator to skip all non-main-trace
blocks during the first pass over the CFG.  Then each exit block is
visited.
Esse commit está contido em:
Jordan DeLong
2013-05-20 06:48:22 -07:00
commit de Sara Golemon
commit 362f69b6fe
3 arquivos alterados com 39 adições e 9 exclusões
+1 -1
Ver Arquivo
@@ -32,7 +32,7 @@ namespace HPHP { namespace JIT {
*/
template <class Visitor>
struct PostorderSort {
PostorderSort(Visitor &visitor, unsigned num_blocks)
PostorderSort(Visitor& visitor, unsigned num_blocks)
: m_visited(num_blocks), m_visitor(visitor)
{}
+2 -2
Ver Arquivo
@@ -3563,7 +3563,7 @@ void CodeGenerator::cgSpillStack(IRInstruction* inst) {
// we don't need to spill it.
if (inst->op() == LdStack && inst->getSrc(0) == sp &&
inst->getExtra<LdStack>()->offset * sizeof(Cell) == offset) {
FTRACE(1, "{}: Not spilling spill value {} from {}\n",
FTRACE(6, "{}: Not spilling spill value {} from {}\n",
__func__, i, inst->toString());
} else {
cgStore(spReg, offset, val);
@@ -3942,7 +3942,7 @@ void CodeGenerator::recordSyncPoint(Asm& as,
Offset pcOff = m_state.lastMarker->bcOff - m_state.lastMarker->func->base();
FTRACE(3, "IR recordSyncPoint: {} {} {}\n", as.code.frontier, pcOff,
FTRACE(5, "IR recordSyncPoint: {} {} {}\n", as.code.frontier, pcOff,
stackOff);
m_tx64->recordSyncPoint(as, pcOff, stackOff);
}
+36 -6
Ver Arquivo
@@ -33,7 +33,7 @@ namespace JIT{
using namespace Transl::reg;
static const HPHP::Trace::Module TRACEMOD = HPHP::Trace::hhir;
TRACE_SET_MOD(hhir);
int RegisterInfo::numAllocatedRegs() const {
// Return the number of register slots that actually have an allocated
@@ -142,7 +142,8 @@ private:
void initFreeList();
void coalesce(Trace* trace);
void genSpillStats(Trace* trace, int numSpillLocs);
void allocRegsOneTrace(BlockList::iterator& blockIt, ExitTraceMap& etm);
void allocRegsOneTrace(BlockList::iterator& blockIt,
ExitTraceMap& etm);
void allocRegsToTrace();
uint32_t createSpillSlot(SSATmp* tmp);
static SSATmp* getSpilledTmp(SSATmp* tmp);
@@ -168,7 +169,7 @@ private:
template<typename Inner, int DumpVal=4>
void dumpIR(const Inner* in, const char* msg) {
if (dumpIREnabled(DumpVal)) {
if (HPHP::Trace::moduleEnabled(HPHP::Trace::hhir, DumpVal)) {
std::ostringstream str;
print(str, in, &m_allocInfo, &m_lifetime);
HPHP::Trace::traceRelease("--- %s: %s\n", msg, str.str().c_str());
@@ -1125,7 +1126,8 @@ RegAllocInfo LinearScan::allocRegs(Trace* trace, LifetimeInfo* lifetime) {
void LinearScan::allocRegsOneTrace(BlockList::iterator& blockIt,
ExitTraceMap& etm) {
Trace* trace = (*blockIt)->getTrace();
auto const trace = (*blockIt)->getTrace();
collectInfo(blockIt, trace);
computePreColoringHint();
@@ -1145,8 +1147,16 @@ void LinearScan::allocRegsOneTrace(BlockList::iterator& blockIt,
while (blockIt != m_blocks.end()) {
Block* block = *blockIt;
if (block->getTrace() != trace) {
break;
if (!isMain) {
break;
} else {
++blockIt;
continue;
}
}
FTRACE(5, "Block{}: {} ({})\n",
trace->isMain() ? "" : " (exit trace)",
(*blockIt)->getId(), (*blockIt)->postId());
// clear remembered reloads that don't dominate this block
for (SlotInfo& slot : m_slots) {
@@ -1158,7 +1168,7 @@ void LinearScan::allocRegsOneTrace(BlockList::iterator& blockIt,
}
for (auto it = block->begin(), end = block->end(); it != end; ++it) {
allocRegToInstruction(it);
dumpIR<IRInstruction, kExtraLevel>(&*it, "allocated to instruction");
dumpIR<IRInstruction, kExtraLevel>(&*it, "allocated to instruction ");
}
if (isMain) {
assert(block->getTrace()->isMain());
@@ -1213,10 +1223,30 @@ void LinearScan::allocRegsToTrace() {
numberInstructions(m_blocks);
if (HPHP::Trace::moduleEnabled(HPHP::Trace::hhir, 5)) {
std::stringstream s;
s << "RPO: ";
for (auto& b : m_blocks) {
s << folly::format("{}{} ",
b->isMain() ? "M" : "E",
b->getId());
}
s << "\n";
HPHP::Trace::traceRelease("%s\n", s.str().c_str());
}
BlockList::iterator it = m_blocks.begin();
while (it != m_blocks.end()) {
allocRegsOneTrace(it, etm);
}
for (it = m_blocks.begin(); it != m_blocks.end();) {
if ((*it)->isMain()) {
++it;
continue;
}
allocRegsOneTrace(it, etm);
}
}
void LinearScan::rematerialize() {