AirEliminateDeadCode.cpp [plain text]
#include "config.h"
#include "AirEliminateDeadCode.h"
#if ENABLE(B3_JIT)
#include "AirCode.h"
#include "AirInstInlines.h"
#include "AirPhaseScope.h"
#include "B3IndexSet.h"
namespace JSC { namespace B3 { namespace Air {
bool eliminateDeadCode(Code& code)
{
PhaseScope phaseScope(code, "eliminateDeadCode");
HashSet<Tmp> liveTmps;
IndexSet<StackSlot> liveStackSlots;
bool changed;
auto isArgLive = [&] (const Arg& arg) -> bool {
switch (arg.kind()) {
case Arg::Tmp:
if (arg.isReg())
return true;
return liveTmps.contains(arg.tmp());
case Arg::Stack:
if (arg.stackSlot()->isLocked())
return true;
return liveStackSlots.contains(arg.stackSlot());
default:
return true;
}
};
auto addLiveArg = [&] (const Arg& arg) -> bool {
switch (arg.kind()) {
case Arg::Tmp:
if (arg.isReg())
return false;
return liveTmps.add(arg.tmp()).isNewEntry;
case Arg::Stack:
if (arg.stackSlot()->isLocked())
return false;
return liveStackSlots.add(arg.stackSlot());
default:
return false;
}
};
auto isInstLive = [&] (Inst& inst) -> bool {
if (inst.hasNonArgEffects())
return true;
bool storesToLive = false;
inst.forEachArg(
[&] (Arg& arg, Arg::Role role, Arg::Type, Arg::Width) {
if (!Arg::isAnyDef(role))
return;
if (role == Arg::Scratch)
return;
storesToLive |= isArgLive(arg);
});
return storesToLive;
};
auto handleInst = [&] (Inst& inst) {
if (!isInstLive(inst))
return;
for (Arg& arg : inst.args) {
changed |= addLiveArg(arg);
arg.forEachTmpFast(
[&] (Tmp& tmp) {
changed |= addLiveArg(tmp);
});
}
};
auto runForward = [&] () -> bool {
changed = false;
for (BasicBlock* block : code) {
for (Inst& inst : *block)
handleInst(inst);
}
return changed;
};
auto runBackward = [&] () -> bool {
changed = false;
for (unsigned blockIndex = code.size(); blockIndex--;) {
BasicBlock* block = code[blockIndex];
for (unsigned instIndex = block->size(); instIndex--;)
handleInst(block->at(instIndex));
}
return changed;
};
for (;;) {
if (!runBackward())
break;
if (!runBackward())
break;
if (!runForward())
break;
}
unsigned removedInstCount = 0;
for (BasicBlock* block : code) {
removedInstCount += block->insts().removeAllMatching(
[&] (Inst& inst) -> bool {
return !isInstLive(inst);
});
}
return !!removedInstCount;
}
} } }
#endif // ENABLE(B3_JIT)