Move m_id and m_lastUseId to LifetimeInfo

These two fields represent the results of liveness analysis,
so group them together that way.
Esse commit está contido em:
Edwin Smith
2013-05-02 07:10:51 -07:00
commit de Sara Golemon
commit 494e87cbd1
11 arquivos alterados com 159 adições e 124 exclusões
+3 -2
Ver Arquivo
@@ -5113,7 +5113,7 @@ void cgTrace(Trace* trace, Asm& amain, Asm& astubs, Transl::TranslatorX64* tx64,
}
void CodeGenerator::print() const {
JIT::print(std::cout, m_curTrace, m_state.asmInfo);
JIT::print(std::cout, m_curTrace, m_state.lifetime, m_state.asmInfo);
}
/*
@@ -5152,10 +5152,11 @@ void genCodeForTrace(Trace* trace,
IRFactory* irFactory,
vector<TransBCMapping>* bcMap,
Transl::TranslatorX64* tx64,
const LifetimeInfo* lifetime,
AsmInfo* asmInfo) {
assert(trace->isMain());
LiveRegs live_regs = computeLiveRegs(irFactory, trace->front());
CodegenState state(irFactory, live_regs, asmInfo);
CodegenState state(irFactory, live_regs, lifetime, asmInfo);
cgTrace(trace, as, astubs, tx64, bcMap, state);
for (Trace* exit : trace->getExitTraces()) {
cgTrace(exit, astubs, astubs, tx64, nullptr, state);
+8 -1
Ver Arquivo
@@ -73,10 +73,12 @@ typedef StateVector<IRInstruction, RegSet> LiveRegs;
// and address information produced during codegen.
struct CodegenState {
CodegenState(const IRFactory* factory, const LiveRegs& liveRegs,
const LifetimeInfo* lifetime,
AsmInfo* asmInfo)
: patches(factory, nullptr)
, lastMarker(nullptr)
, liveRegs(liveRegs)
, lifetime(lifetime)
, asmInfo(asmInfo)
{}
@@ -96,6 +98,10 @@ struct CodegenState {
// registers.
const LiveRegs& liveRegs;
// Optional information used when pretty-printing code after codegen.
// when not available, these are nullptrs.
const LifetimeInfo* lifetime;
// Output: start/end ranges of machine code addresses of each instruction.
AsmInfo* asmInfo;
};
@@ -535,7 +541,8 @@ void genCodeForTrace(Trace* trace,
IRFactory* irFactory,
vector<TransBCMapping>* bcMap,
TranslatorX64* tx64,
AsmInfo *asmInfo = nullptr);
const LifetimeInfo* lifetime = nullptr,
AsmInfo* asmInfo = nullptr);
}}}
-4
Ver Arquivo
@@ -35,7 +35,6 @@
#include "runtime/vm/translator/hopt/cse.h"
#include "runtime/vm/translator/hopt/simplifier.h"
#include "runtime/vm/translator/hopt/print.h"
#include "runtime/vm/translator/hopt/codegen.h"
// Include last to localize effects to this file
#include "util/assert_throw.h"
@@ -296,7 +295,6 @@ IRInstruction::IRInstruction(Arena& arena, const IRInstruction* inst, IId iid)
, m_numSrcs(inst->m_numSrcs)
, m_numDsts(inst->m_numDsts)
, m_iid(iid)
, m_id(0)
, m_srcs(m_numSrcs ? new (arena) SSATmp*[m_numSrcs] : nullptr)
, m_dst(nullptr)
, m_taken(nullptr)
@@ -595,7 +593,6 @@ void IRInstruction::convertToNop() {
m_op = nop.m_op;
m_typeParam = nop.m_typeParam;
m_numSrcs = nop.m_numSrcs;
m_id = nop.m_id;
m_srcs = nop.m_srcs;
m_numDsts = nop.m_numDsts;
m_dst = nop.m_dst;
@@ -633,7 +630,6 @@ void IRInstruction::become(IRFactory* factory, IRInstruction* other) {
// dests---the whole point of become() is things still point to us.
m_op = other->m_op;
m_typeParam = other->m_typeParam;
m_id = other->m_id;
m_taken = other->m_taken;
m_tca = other->m_tca;
m_numSrcs = other->m_numSrcs;
+6 -25
Ver Arquivo
@@ -1621,6 +1621,7 @@ struct AsmInfo;
class IRFactory;
class Simplifier;
struct Block;
struct LifetimeInfo;
bool isRefCounted(SSATmp* opnd);
@@ -1649,7 +1650,6 @@ struct IRInstruction {
, m_numSrcs(numSrcs)
, m_numDsts(0)
, m_iid(kTransient)
, m_id(0)
, m_srcs(srcs)
, m_dst(nullptr)
, m_taken(nullptr)
@@ -1665,8 +1665,7 @@ struct IRInstruction {
* Construct an IRInstruction as a deep copy of `inst', using
* arena to allocate memory for its srcs/dests.
*/
explicit IRInstruction(Arena& arena, const IRInstruction* inst,
IId iid);
explicit IRInstruction(Arena& arena, const IRInstruction* inst, IId iid);
/*
* Initialize the source list for this IRInstruction. We must not
@@ -1824,20 +1823,13 @@ struct IRInstruction {
m_dst = newDsts;
}
TCA getTCA() const { return m_tca; }
void setTCA(TCA newTCA) { m_tca = newTCA; }
/*
* An instruction's 'id' has different meanings depending on the
* compilation phase.
*/
uint32_t getId() const { return m_id; }
void setId(uint32_t newId) { m_id = newId; }
TCA getTCA() const { return m_tca; }
void setTCA(TCA newTCA) { m_tca = newTCA; }
/*
* Instruction id (iid) is stable and useful as an array index.
*/
uint32_t getIId() const {
uint32_t getIId() const {
assert(m_iid != kTransient);
return m_iid;
}
@@ -1909,7 +1901,6 @@ private:
uint16_t m_numSrcs;
uint16_t m_numDsts;
const IId m_iid;
uint32_t m_id;
SSATmp** m_srcs;
SSATmp* m_dst; // if HasDest or NaryDest
Block* m_taken; // for branches, guards, and jmp
@@ -1971,12 +1962,6 @@ public:
void setInstruction(IRInstruction* i) { m_inst = i; }
Type type() const { return m_type; }
void setType(Type t) { m_type = t; }
uint32_t getLastUseId() const { return m_lastUseId; }
void setLastUseId(uint32_t newId) { m_lastUseId = newId; }
uint32_t getUseCount() const { return m_useCount; }
void setUseCount(uint32_t count) { m_useCount = count; }
void incUseCount() { m_useCount++; }
uint32_t decUseCount() { return --m_useCount; }
bool isSpilled() const { return m_isSpilled; }
bool isBoxed() const { return type().isBoxed(); }
bool isString() const { return isA(Type::Str); }
@@ -2079,8 +2064,6 @@ private:
: m_inst(i)
, m_type(outputType(i, dstId))
, m_id(opndId)
, m_lastUseId(0)
, m_useCount(0)
, m_isSpilled(false)
{
m_regs[0] = m_regs[1] = Transl::InvalidReg;
@@ -2090,9 +2073,7 @@ private:
IRInstruction* m_inst;
Type m_type; // type when defined
const uint32_t m_id;
uint32_t m_lastUseId;
uint16_t m_useCount;
uint32_t m_id;
bool m_isSpilled;
/*
@@ -24,6 +24,7 @@
#include "util/arena.h"
#include "runtime/vm/translator/hopt/ir.h"
#include "runtime/vm/translator/hopt/cse.h"
#include "runtime/base/memory/memory_manager.h"
namespace HPHP { namespace VM { namespace JIT {
+12 -7
Ver Arquivo
@@ -1907,29 +1907,34 @@ void TranslatorX64::hhirTraceCodeGen(vector<TransBCMapping>* bcMap) {
assert(m_useHHIR);
JIT::Trace* trace = m_hhbcTrans->getTrace();
auto finishPass = [&](const char* msg) {
dumpTrace(1, trace, msg);
auto finishPass = [&](const char* msg,
const JIT::LifetimeInfo* lifetime = nullptr) {
dumpTrace(1, trace, msg, lifetime);
assert(JIT::checkCfg(trace, *m_irFactory));
};
finishPass(" after initial translation ");
JIT::optimizeTrace(trace, m_hhbcTrans->getTraceBuilder());
finishPass(" after optimizing ");
JIT::allocRegsForTrace(trace, m_irFactory.get());
finishPass(" after reg alloc ");
auto* factory = m_irFactory.get();
if (JIT::dumpIREnabled() || RuntimeOption::EvalJitCompareHHIR) {
JIT::LifetimeInfo lifetime(m_irFactory.get());
JIT::allocRegsForTrace(trace, m_irFactory.get(), &lifetime);
finishPass(" after reg alloc ", &lifetime);
JIT::AsmInfo ai(factory);
JIT::genCodeForTrace(trace, a, astubs, factory, bcMap, this, &ai);
JIT::genCodeForTrace(trace, a, astubs, factory, bcMap, this,
&lifetime, &ai);
if (RuntimeOption::EvalJitCompareHHIR) {
std::ostringstream out;
dumpTraceImpl(trace, out, &ai);
dumpTraceImpl(trace, out, &lifetime, &ai);
m_lastHHIRDump = out.str();
} else {
dumpTrace(1, trace, " after code gen ", &ai);
dumpTrace(1, trace, " after code gen ", &lifetime, &ai);
}
} else {
JIT::allocRegsForTrace(trace, m_irFactory.get());
finishPass(" after reg alloc ");
JIT::genCodeForTrace(trace, a, astubs, factory, bcMap, this);
}
+54 -52
Ver Arquivo
@@ -39,7 +39,7 @@ struct LinearScan : private boost::noncopyable {
static const int NumRegs = 16;
explicit LinearScan(IRFactory*);
void allocRegs(Trace*);
void allocRegs(Trace*, LifetimeInfo* lifetime);
private:
class RegState {
@@ -145,6 +145,15 @@ private:
RegState* getFreeReg(bool preferCallerSaved);
RegState* getReg(RegState* reg);
template<typename Inner, int DumpVal=4>
void dumpIR(const Inner* in, const char* msg) {
if (dumpIREnabled(DumpVal)) {
std::ostringstream str;
print(str, in, &m_lifetime);
HPHP::Trace::traceRelease("--- %s: %s\n", msg, str.str().c_str());
}
}
private:
// Register allocation may generate Spill/Reload.
IRFactory* const m_irFactory;
@@ -164,6 +173,10 @@ private:
// have not spilled have -1.
StateVector<SSATmp, int32_t> m_spillSlots;
LifetimeInfo m_lifetime; // Internal lifetime state
LinearIdVector& m_linear; // linear id for each inst
UsesVector& m_uses; // use count of each tmp
// 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<IRInstruction*> m_natives;
@@ -233,6 +246,9 @@ void LinearScan::StateSave::restore(LinearScan* ls) {
LinearScan::LinearScan(IRFactory* irFactory)
: m_irFactory(irFactory)
, m_spillSlots(irFactory, -1)
, m_lifetime(irFactory)
, m_linear(m_lifetime.linear)
, m_uses(m_lifetime.uses)
, m_jmps(irFactory, JmpList())
{
for (int i = 0; i < kNumX64Regs; i++) {
@@ -262,15 +278,6 @@ LinearScan::LinearScan(IRFactory* irFactory)
}
}
template<typename Inner, int DumpVal=4>
static inline void dumpIR(const Inner* in, const char* msg) {
if (dumpIREnabled(DumpVal)) {
std::ostringstream str;
print(str, in);
HPHP::Trace::traceRelease("--- %s: %s\n", msg, str.str().c_str());
}
}
void LinearScan::allocRegToInstruction(InstructionList::iterator it) {
IRInstruction* inst = &*it;
dumpIR<IRInstruction, 4>(inst, "allocating to instruction");
@@ -312,7 +319,7 @@ void LinearScan::allocRegToInstruction(InstructionList::iterator it) {
// <spillTmp>'s last use ID.
// Replace <tmp> with <reloadTmp> in <inst>.
SSATmp* reloadTmp = reload->getDst();
reloadTmp->setLastUseId(spillTmp->getLastUseId());
m_uses[reloadTmp].lastUse = m_uses[spillTmp].lastUse;
m_spillSlots[reloadTmp] = slotId;
inst->setSrc(i, reloadTmp);
// reloadTmp and tmp share the same type. Since it was spilled, it
@@ -328,7 +335,7 @@ void LinearScan::allocRegToInstruction(InstructionList::iterator it) {
}
}
freeRegsAtId(inst->getId());
freeRegsAtId(m_linear[inst]);
// Update next native.
if (getNextNative() == inst) {
assert(!m_natives.empty());
@@ -391,14 +398,14 @@ void LinearScan::allocRegToInstruction(InstructionList::iterator it) {
assert(!dst.isA(Type::FramePtr) || abnormalFramePtr);
assert(!dst.isA(Type::StkPtr) || abnormalStkPtr);
if (!RuntimeOption::EvalHHIRDeadCodeElim || dst.getLastUseId() != 0) {
if (!RuntimeOption::EvalHHIRDeadCodeElim || m_uses[dst].lastUse != 0) {
allocRegToTmp(&dst, i);
}
}
}
if (!RuntimeOption::EvalHHIRDeadCodeElim) {
// if any outputs were unused, free regs now.
freeRegsAtId(inst->getId());
freeRegsAtId(m_linear[inst]);
}
}
@@ -406,7 +413,7 @@ void LinearScan::allocRegToTmp(SSATmp* ssaTmp, uint32_t index) {
bool preferCallerSaved = true;
if (RuntimeOption::EvalHHIREnableCalleeSavedOpt) {
// Prefer caller-saved registers iff <ssaTmp> doesn't span native.
preferCallerSaved = (ssaTmp->getLastUseId() <= getNextNativeId());
preferCallerSaved = (m_uses[ssaTmp].lastUse <= getNextNativeId());
}
RegState* reg = nullptr;
@@ -465,7 +472,7 @@ void LinearScan::allocRegToTmp(SSATmp* ssaTmp, uint32_t index) {
if (m_spillSlots[ssaTmp] == -1) {
createSpillSlot(ssaTmp);
}
ssaTmp->setLastUseId(getNextNativeId());
m_uses[ssaTmp].lastUse = getNextNativeId();
}
allocRegToTmp(reg, ssaTmp, index);
@@ -475,14 +482,14 @@ void LinearScan::allocRegToTmp(RegState* reg, SSATmp* ssaTmp, uint32_t index) {
reg->m_ssaTmp = ssaTmp;
// mark inst as using this register
ssaTmp->setReg(PhysReg(reg->m_regNo), index);
uint32_t lastUseId = ssaTmp->getLastUseId();
uint32_t lastUseId = m_uses[ssaTmp].lastUse;
if (reg->isReserved()) {
return;
}
// insert into the list of assigned registers sorted by last use id
auto it = m_allocatedRegs.begin();
for (; it != m_allocatedRegs.end(); ++it) {
if (lastUseId > (*it)->m_ssaTmp->getLastUseId()) {
if (lastUseId > m_uses[(*it)->m_ssaTmp].lastUse) {
break;
}
}
@@ -519,7 +526,7 @@ uint32_t LinearScan::assignSpillLoc() {
for (int locIndex = 0;
locIndex < src->numNeededRegs();
++locIndex) {
if (dst->getLastUseId() <= getNextNativeId()) {
if (m_uses[dst].lastUse <= getNextNativeId()) {
TRACE(3, "[counter] 1 spill a tmp that does not span native\n");
} else {
TRACE(3, "[counter] 1 spill a tmp that spans native\n");
@@ -594,14 +601,7 @@ void LinearScan::insertAllocFreeSpillAux(Trace* trace,
void LinearScan::collectInfo(BlockList::iterator it, Trace* trace) {
m_natives.clear();
m_jmps.reset();
for (auto* block : m_blocks) {
for (auto& inst : *block) {
for (auto& dst : inst.getDsts()) {
dst.setLastUseId(0);
}
}
}
m_uses.reset();
while (it != m_blocks.end()) {
Block* block = *it++;
@@ -611,15 +611,15 @@ void LinearScan::collectInfo(BlockList::iterator it, Trace* trace) {
int lastId = block->getTrace()->getData();
for (IRInstruction& inst : *block) {
for (auto* src : inst.getSrcs()) {
if (lastId > src->getLastUseId()) {
src->setLastUseId(lastId);
if (lastId > m_uses[src].lastUse) {
m_uses[src].lastUse = lastId;
}
}
}
} else {
for (IRInstruction& inst : *block) {
for (auto* src : inst.getSrcs()) {
src->setLastUseId(inst.getId());
m_uses[src].lastUse = m_linear[inst];
}
if (inst.isNative()) m_natives.push_back(&inst);
}
@@ -886,24 +886,16 @@ void LinearScan::preAllocSpillLoc(uint32_t numSpillLocs) {
// Assign ids to each instruction in linear order.
void LinearScan::numberInstructions(const BlockList& blocks) {
m_spillSlots.reset();
forEachInst(
blocks,
[](IRInstruction* inst) {
for (SSATmp& dst : inst->getDsts()) {
dst.setLastUseId(0);
dst.setUseCount(0);
}
}
);
m_uses.reset();
uint32_t nextId = 1;
for (auto* block : blocks) {
for (auto& inst : *block) {
if (inst.op() == Marker) continue; // don't number markers
uint32_t id = nextId++;
inst.setId(id);
m_linear[inst] = id;
for (SSATmp* tmp : inst.getSrcs()) {
tmp->setLastUseId(id);
tmp->incUseCount();
m_uses[tmp].lastUse = id;
m_uses[tmp].count++;
}
}
if (block->getTaken() && block->isMain() && !block->getTaken()->isMain()) {
@@ -969,7 +961,7 @@ void LinearScan::genSpillStats(Trace* trace, int numSpillLocs) {
}
void LinearScan::allocRegs(Trace* trace) {
void LinearScan::allocRegs(Trace* trace, LifetimeInfo* lifetime) {
if (RuntimeOption::EvalHHIREnableCoalescing) {
// <coalesce> doesn't need instruction numbering.
coalesce(trace);
@@ -1011,6 +1003,11 @@ void LinearScan::allocRegs(Trace* trace) {
}
if (m_slots.size()) genSpillStats(trace, numSpillLocs);
if (lifetime) {
lifetime->linear = std::move(m_linear);
lifetime->uses = std::move(m_uses);
}
}
void LinearScan::allocRegsOneTrace(BlockList::iterator& blockIt,
@@ -1107,8 +1104,10 @@ void LinearScan::allocRegsToTrace() {
void LinearScan::rematerialize() {
numberInstructions(m_blocks);
dumpTrace(6, m_blocks.front()->getTrace(), "before rematerialization");
if (dumpIREnabled(6)) {
dumpTrace(6, m_blocks.front()->getTrace(), "before rematerialization",
&m_lifetime);
}
rematerializeAux();
numberInstructions(m_blocks);
// We only replaced Reloads in rematerializeAux().
@@ -1275,11 +1274,13 @@ void LinearScan::rematerializeAux() {
void LinearScan::removeUnusedSpills() {
for (SlotInfo& slot : m_slots) {
IRInstruction* spill = slot.spillTmp->inst();
if (spill->getDst()->getUseCount() == 0) {
if (m_uses[spill->getDst()].count == 0) {
Block* block = spill->getBlock();
block->erase(block->iteratorTo(spill));
SSATmp* src = spill->getSrc(0);
if (src->decUseCount() == 0) {
auto uses = m_uses[src].count - 1;
m_uses[src].count = uses;
if (uses == 0) {
Opcode srcOpc = src->inst()->op();
// Not all instructions are able to take noreg as its dest
// reg. We pick LdLoc and IncRef because they occur often.
@@ -1302,7 +1303,7 @@ void LinearScan::freeRegsAtId(uint32_t id) {
auto next = it; ++next;
RegState* reg = *it;
assert(reg->m_ssaTmp);
if (reg->m_ssaTmp->getLastUseId() <= id) {
if (m_uses[reg->m_ssaTmp].lastUse <= id) {
m_allocatedRegs.erase(it);
freeReg(reg);
}
@@ -1441,7 +1442,7 @@ uint32_t LinearScan::createSpillSlot(SSATmp* tmp) {
si.latestReload = tmp;
m_slots.push_back(si);
// The spill slot inherits the last use ID of the spilled tmp.
si.spillTmp->setLastUseId(tmp->getLastUseId());
m_uses[si.spillTmp].lastUse = m_uses[tmp].lastUse;
return slotId;
}
@@ -1451,7 +1452,7 @@ IRInstruction* LinearScan::getNextNative() const {
uint32_t LinearScan::getNextNativeId() const {
IRInstruction* nextNative = getNextNative();
return (nextNative ? nextNative->getId() : -1);
return nextNative ? m_linear[nextNative] : -1;
}
SSATmp* LinearScan::getSpilledTmp(SSATmp* tmp) {
@@ -1505,8 +1506,9 @@ void LinearScan::PreColoringHint::add(SSATmp* tmp, uint32_t index, int argNum) {
//////////////////////////////////////////////////////////////////////
void allocRegsForTrace(Trace* trace, IRFactory* irFactory) {
LinearScan(irFactory).allocRegs(trace);
void allocRegsForTrace(Trace* trace, IRFactory* irFactory,
LifetimeInfo* lifetime) {
LinearScan(irFactory).allocRegs(trace, lifetime);
}
}}} // HPHP::VM::JIT
+29 -1
Ver Arquivo
@@ -17,16 +17,44 @@
#ifndef incl_HPHP_VM_LINEAR_SCAN_H_
#define incl_HPHP_VM_LINEAR_SCAN_H_
#include "runtime/vm/translator/hopt/state_vector.h"
namespace HPHP { namespace VM { namespace JIT {
class Trace;
class IRFactory;
struct UseInfo {
UseInfo() : lastUse(0), count(0) {}
uint32_t lastUse; // linear id of last use
uint32_t count; // number of uses
};
typedef StateVector<IRInstruction, uint32_t> LinearIdVector;
typedef StateVector<SSATmp, UseInfo> UsesVector;
struct LifetimeInfo {
explicit LifetimeInfo(const IRFactory* factory)
: linear(factory, 0), uses(factory, UseInfo()) {
}
explicit LifetimeInfo(const LinearIdVector& linear,
const UsesVector& uses)
: linear(linear), uses(uses) {
}
explicit LifetimeInfo(LinearIdVector&& linear,
UsesVector&& uses)
: linear(linear), uses(uses) {
}
LinearIdVector linear; // linear id of each instruction
UsesVector uses; // last use id and use count of each tmp
};
/*
* The main entry point for register allocation. Called prior to code
* generation.
*/
void allocRegsForTrace(Trace*, IRFactory*);
void allocRegsForTrace(Trace*, IRFactory*, LifetimeInfo* lifetime = nullptr);
}}}
+33 -26
Ver Arquivo
@@ -65,26 +65,28 @@ void printOpcode(std::ostream& os, const IRInstruction* inst) {
<< color(ANSI_COLOR_END);
}
void printDst(std::ostream& os, const IRInstruction* inst) {
void printDst(std::ostream& os, const IRInstruction* inst,
const LifetimeInfo* lifetime) {
if (inst->getNumDsts() == 0) return;
const char* sep = "";
for (const SSATmp& dst : inst->getDsts()) {
os << punc(sep);
print(os, &dst, true);
print(os, &dst, lifetime, true);
sep = ", ";
}
os << punc(" = ");
}
void printSrc(std::ostream& ostream, const IRInstruction* inst, uint32_t i) {
void printSrc(std::ostream& ostream, const IRInstruction* inst, uint32_t i,
const LifetimeInfo* lifetime) {
SSATmp* src = inst->getSrc(i);
if (src != nullptr) {
if (inst->getId() != 0 && !src->isConst() &&
src->getLastUseId() == inst->getId()) {
if (lifetime && lifetime->linear[inst] != 0 && !src->isConst() &&
lifetime->uses[src].lastUse == lifetime->linear[inst]) {
ostream << "~";
}
print(ostream, src);
print(ostream, src, lifetime);
} else {
ostream << color(ANSI_COLOR_RED)
<< "!!!NULL @ " << i
@@ -93,7 +95,8 @@ void printSrc(std::ostream& ostream, const IRInstruction* inst, uint32_t i) {
}
}
void printSrcs(std::ostream& os, const IRInstruction* inst) {
void printSrcs(std::ostream& os, const IRInstruction* inst,
const LifetimeInfo* lifetime) {
bool first = true;
if (inst->op() == IncStat) {
os << " " << Stats::g_counterNames[inst->getSrc(0)->getValInt()]
@@ -107,7 +110,7 @@ void printSrcs(std::ostream& os, const IRInstruction* inst) {
os << " ";
first = false;
}
printSrc(os, inst, i);
printSrc(os, inst, i, lifetime);
}
}
@@ -118,7 +121,8 @@ void printLabel(std::ostream& os, const Block* block) {
os << color(ANSI_COLOR_END);
}
void print(std::ostream& ostream, const IRInstruction* inst) {
void print(std::ostream& ostream, const IRInstruction* inst,
const LifetimeInfo* lifetime) {
if (inst->op() == Marker) {
auto* marker = inst->getExtra<Marker>();
ostream << color(ANSI_COLOR_BLUE)
@@ -132,17 +136,17 @@ void print(std::ostream& ostream, const IRInstruction* inst) {
if (!inst->isTransient()) {
ostream << color(ANSI_COLOR_YELLOW);
if (!inst->getId()) {
if (!lifetime || !lifetime->linear[inst]) {
ostream << folly::format("({:02d}) ", inst->getIId());
} else {
ostream << folly::format("({:02d}@{:02d}) ", inst->getIId(),
inst->getId());
lifetime->linear[inst]);
}
ostream << color(ANSI_COLOR_END);
}
printDst(ostream, inst);
printDst(ostream, inst, lifetime);
printOpcode(ostream, inst);
printSrcs(ostream, inst);
printSrcs(ostream, inst, lifetime);
if (Block* taken = inst->getTaken()) {
ostream << punc(" -> ");
@@ -223,7 +227,8 @@ static void printConst(std::ostream& os, IRInstruction* inst) {
}
}
void print(std::ostream& os, const SSATmp* tmp, bool printLastUse) {
void print(std::ostream& os, const SSATmp* tmp, const LifetimeInfo* lifetime,
bool printLastUse) {
if (tmp->inst()->op() == DefConst) {
printConst(os, tmp->inst());
return;
@@ -231,9 +236,9 @@ void print(std::ostream& os, const SSATmp* tmp, bool printLastUse) {
os << color(ANSI_COLOR_WHITE);
os << "t" << tmp->getId();
os << color(ANSI_COLOR_END);
if (printLastUse && tmp->getLastUseId() != 0) {
if (printLastUse && lifetime && lifetime->uses[tmp].lastUse != 0) {
os << color(ANSI_COLOR_GRAY)
<< "@" << tmp->getLastUseId() << "#" << tmp->getUseCount()
<< "@" << lifetime->uses[tmp].lastUse << "#" << lifetime->uses[tmp].count
<< color(ANSI_COLOR_END);
}
if (tmp->isSpilled() || tmp->numAllocatedRegs() > 0) {
@@ -264,10 +269,11 @@ void print(const SSATmp* tmp) {
}
void print(const Trace* trace) {
print(std::cout, trace, nullptr);
print(std::cout, trace);
}
void print(std::ostream& os, const Trace* trace, const AsmInfo* asmInfo) {
void print(std::ostream& os, const Trace* trace, const LifetimeInfo* lifetime,
const AsmInfo* asmInfo) {
static const int kIndent = 4;
Disasm disasm(Disasm::Options().indent(kIndent + 4)
.printEncoding(dumpIREnabled(6))
@@ -292,7 +298,7 @@ void print(std::ostream& os, const Trace* trace, const AsmInfo* asmInfo) {
if (inst.op() == Marker) {
os << std::string(kIndent, ' ');
JIT::print(os, &inst);
JIT::print(os, &inst, lifetime);
os << '\n';
// Don't print bytecode in a non-main trace.
@@ -325,14 +331,14 @@ void print(std::ostream& os, const Trace* trace, const AsmInfo* asmInfo) {
os << std::string(kIndent +
folly::format("({}) ", inst.getIId()).str().size(),
' ');
JIT::print(os, inst.getDst(i), false);
JIT::print(os, inst.getDst(i), lifetime, false);
os << punc(" = ") << color(ANSI_COLOR_CYAN) << "phi "
<< color(ANSI_COLOR_END);
bool first = true;
inst.getBlock()->forEachSrc(i, [&](IRInstruction* jmp, SSATmp*) {
if (!first) os << punc(", ");
first = false;
printSrc(os, jmp, i);
printSrc(os, jmp, i, lifetime);
os << punc("@");
printLabel(os, jmp->getBlock());
});
@@ -341,7 +347,7 @@ void print(std::ostream& os, const Trace* trace, const AsmInfo* asmInfo) {
}
os << std::string(kIndent, ' ');
JIT::print(os, &inst);
JIT::print(os, &inst, lifetime);
os << '\n';
if (asmInfo) {
@@ -379,19 +385,20 @@ void print(std::ostream& os, const Trace* trace, const AsmInfo* asmInfo) {
os << "\n" << color(ANSI_COLOR_GREEN)
<< " ------- Exit Trace -------"
<< color(ANSI_COLOR_END) << '\n';
print(os, exitTrace, asmInfo);
print(os, exitTrace, lifetime, asmInfo);
}
}
void dumpTraceImpl(const Trace* trace, std::ostream& out,
const LifetimeInfo* lifetime,
const AsmInfo* asmInfo) {
print(out, trace, asmInfo);
print(out, trace, lifetime, asmInfo);
}
// Suggested captions: "before jiffy removal", "after goat saturation",
// etc.
void dumpTrace(int level, const Trace* trace, const char* caption,
AsmInfo* ai) {
const LifetimeInfo* lifetime, AsmInfo* ai) {
if (dumpIREnabled(level)) {
std::ostringstream str;
auto bannerFmt = "{:-^40}\n";
@@ -399,7 +406,7 @@ void dumpTrace(int level, const Trace* trace, const char* caption,
<< folly::format(bannerFmt, caption)
<< color(ANSI_COLOR_END)
;
dumpTraceImpl(trace, str, ai);
dumpTraceImpl(trace, str, lifetime, ai);
str << color(ANSI_COLOR_BLACK, ANSI_BGCOLOR_GREEN)
<< folly::format(bannerFmt, "")
<< color(ANSI_COLOR_END)
+10 -4
Ver Arquivo
@@ -19,6 +19,7 @@
#include <iosfwd>
#include "util/trace.h"
#include "runtime/vm/translator/hopt/linearscan.h"
namespace HPHP {
namespace VM {
@@ -29,19 +30,23 @@ class SSATmp;
struct Block;
struct AsmInfo;
class Trace;
struct LifetimeInfo;
// IRInstruction
void print(std::ostream& ostream, const IRInstruction*);
void print(std::ostream& ostream, const IRInstruction*,
const LifetimeInfo* lifetime = nullptr);
void print(const IRInstruction*);
void printSrc(std::ostream& ostream, const IRInstruction*, uint32_t srcIndex);
void printSrc(std::ostream& ostream, const IRInstruction*, uint32_t srcIndex,
const LifetimeInfo* lifetime);
// SSATmp
void print(std::ostream& ostream, const SSATmp*,
bool printLastUse = false);
const LifetimeInfo* lifetime = nullptr, bool printLastUse = false);
void print(const SSATmp*);
// Trace
void print(std::ostream& ostream, const Trace*,
const LifetimeInfo* lifetime = nullptr,
const AsmInfo* asmInfo = nullptr);
void print(const Trace*);
@@ -54,8 +59,9 @@ static inline bool dumpIREnabled(int level = 1) {
}
void dumpTraceImpl(const Trace* trace, std::ostream& out,
const AsmInfo* asmInfo = nullptr);
const LifetimeInfo*, const AsmInfo*);
void dumpTrace(int level, const Trace* trace, const char* caption,
const LifetimeInfo* lifetime = nullptr,
AsmInfo* ai = nullptr);
}}}
+3 -2
Ver Arquivo
@@ -61,8 +61,9 @@ struct StateVector {
const_reference operator[](const Key& k) const { return (*this)[&k]; }
const_reference operator[](const Key* k) const {
assert(factoryId(k) < m_info.size());
return m_info[factoryId(k)];
assert(factoryId(k) < count(m_factory, (Key*)nullptr));
auto id = factoryId(k);
return id < m_info.size() ? m_info[id] : m_init;
}
iterator begin() { return m_info.begin(); }