AirEliminateDeadCode.cpp [plain text]
#include "config.h"
#include "AirEliminateDeadCode.h"
#if ENABLE(B3_JIT)
#include "AirCode.h"
#include "AirInstInlines.h"
#include "AirPhaseScope.h"
#include "AirTmpInlines.h"
#include "AirTmpSet.h"
#include <wtf/IndexSet.h>
namespace JSC { namespace B3 { namespace Air {
bool eliminateDeadCode(Code& code)
{
PhaseScope phaseScope(code, "eliminateDeadCode");
TmpSet liveTmps;
IndexSet<StackSlot*> liveStackSlots;
bool changed { false };
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 isInstLive = [&] (Inst& inst) -> bool {
if (inst.hasNonArgEffects())
return true;
bool storesToLive = false;
inst.forEachArg(
[&] (Arg& arg, Arg::Role role, Bank, Width) {
if (!Arg::isAnyDef(role))
return;
if (role == Arg::Scratch)
return;
storesToLive |= isArgLive(arg);
});
return storesToLive;
};
auto handleInst = [&] (Inst& inst) -> bool {
if (!isInstLive(inst))
return false;
for (Arg& arg : inst.args) {
if (arg.isStack() && !arg.stackSlot()->isLocked())
changed |= liveStackSlots.add(arg.stackSlot());
arg.forEachTmpFast(
[&] (Tmp& tmp) {
if (!tmp.isReg())
changed |= liveTmps.add(tmp);
});
}
return true;
};
Vector<Inst*> possiblyDead;
for (BasicBlock* block : code) {
for (Inst& inst : *block) {
if (!handleInst(inst))
possiblyDead.append(&inst);
}
}
auto runForward = [&] () -> bool {
changed = false;
possiblyDead.removeAllMatching(
[&] (Inst* inst) -> bool {
bool result = handleInst(*inst);
changed |= result;
return result;
});
return changed;
};
auto runBackward = [&] () -> bool {
changed = false;
for (unsigned i = possiblyDead.size(); i--;) {
bool result = handleInst(*possiblyDead[i]);
if (result) {
possiblyDead[i] = possiblyDead.last();
possiblyDead.removeLast();
changed = true;
}
}
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)