AirSpillEverything.cpp [plain text]
#include "config.h"
#include "AirSpillEverything.h"
#if ENABLE(B3_JIT)
#include "AirArgInlines.h"
#include "AirCode.h"
#include "AirInsertionSet.h"
#include "AirInstInlines.h"
#include "AirLiveness.h"
#include "AirPhaseScope.h"
#include "AirRegisterPriority.h"
#include "B3IndexMap.h"
namespace JSC { namespace B3 { namespace Air {
void spillEverything(Code& code)
{
PhaseScope phaseScope(code, "spillEverything");
IndexMap<BasicBlock, Vector<RegisterSet>> usedRegisters(code.size());
GPLiveness gpLiveness(code);
FPLiveness fpLiveness(code);
for (BasicBlock* block : code) {
GPLiveness::LocalCalc gpLocalCalc(gpLiveness, block);
FPLiveness::LocalCalc fpLocalCalc(fpLiveness, block);
usedRegisters[block].resize(block->size() + 1);
auto setUsedRegisters = [&] (unsigned index) {
RegisterSet& registerSet = usedRegisters[block][index];
for (Tmp tmp : gpLocalCalc.live()) {
if (tmp.isReg())
registerSet.set(tmp.reg());
}
for (Tmp tmp : fpLocalCalc.live()) {
if (tmp.isReg())
registerSet.set(tmp.reg());
}
Inst::forEachDefWithExtraClobberedRegs<Tmp>(
block->get(index - 1), block->get(index),
[&] (const Tmp& tmp, Arg::Role, Arg::Type, Arg::Width) {
if (tmp.isReg())
registerSet.set(tmp.reg());
});
};
for (unsigned instIndex = block->size(); instIndex--;) {
setUsedRegisters(instIndex + 1);
gpLocalCalc.execute(instIndex);
fpLocalCalc.execute(instIndex);
}
setUsedRegisters(0);
}
Vector<StackSlot*> allStackSlots[Arg::numTypes];
for (unsigned typeIndex = 0; typeIndex < Arg::numTypes; ++typeIndex) {
Vector<StackSlot*>& stackSlots = allStackSlots[typeIndex];
Arg::Type type = static_cast<Arg::Type>(typeIndex);
stackSlots.resize(code.numTmps(type));
for (unsigned tmpIndex = code.numTmps(type); tmpIndex--;)
stackSlots[tmpIndex] = code.addStackSlot(8, StackSlotKind::Spill);
}
InsertionSet insertionSet(code);
for (BasicBlock* block : code) {
for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) {
RegisterSet& setBefore = usedRegisters[block][instIndex];
RegisterSet& setAfter = usedRegisters[block][instIndex + 1];
Inst& inst = block->at(instIndex);
for (unsigned i = 0; i < inst.args.size(); ++i) {
Arg& arg = inst.args[i];
if (arg.isTmp()) {
if (arg.isReg())
continue;
if (inst.admitsStack(i)) {
StackSlot* stackSlot = allStackSlots[arg.type()][arg.tmpIndex()];
arg = Arg::stack(stackSlot);
continue;
}
}
}
inst.forEachTmp(
[&] (Tmp& tmp, Arg::Role role, Arg::Type type, Arg::Width) {
if (tmp.isReg())
return;
StackSlot* stackSlot = allStackSlots[type][tmp.tmpIndex()];
Arg arg = Arg::stack(stackSlot);
Reg chosenReg;
switch (role) {
case Arg::Use:
case Arg::ColdUse:
for (Reg reg : regsInPriorityOrder(type)) {
if (!setBefore.get(reg)) {
setBefore.set(reg);
chosenReg = reg;
break;
}
}
break;
case Arg::Def:
case Arg::ZDef:
for (Reg reg : regsInPriorityOrder(type)) {
if (!setAfter.get(reg)) {
setAfter.set(reg);
chosenReg = reg;
break;
}
}
break;
case Arg::UseDef:
case Arg::UseZDef:
case Arg::LateUse:
case Arg::LateColdUse:
case Arg::Scratch:
case Arg::EarlyDef:
for (Reg reg : regsInPriorityOrder(type)) {
if (!setBefore.get(reg) && !setAfter.get(reg)) {
setAfter.set(reg);
setBefore.set(reg);
chosenReg = reg;
break;
}
}
break;
case Arg::UseAddr:
RELEASE_ASSERT_NOT_REACHED();
break;
}
RELEASE_ASSERT(chosenReg);
tmp = Tmp(chosenReg);
Opcode move = type == Arg::GP ? Move : MoveDouble;
if (Arg::isAnyUse(role) && role != Arg::Scratch)
insertionSet.insert(instIndex, move, inst.origin, arg, tmp);
if (Arg::isAnyDef(role))
insertionSet.insert(instIndex + 1, move, inst.origin, tmp, arg);
});
}
insertionSet.execute(block);
}
}
} } }
#endif // ENABLE(B3_JIT)