mirror of
https://github.com/FEX-Emu/FEX.git
synced 2025-02-05 05:46:35 +00:00
Add Dead Code Elimitation pass
Refactor the previous WIP to use NumUses
This commit is contained in:
parent
b34465544a
commit
b148afef4b
@ -10,6 +10,7 @@ void PassManager::AddDefaultPasses() {
|
||||
Passes.emplace_back(std::unique_ptr<FEXCore::IR::Pass>(CreateRedundantFlagCalculationEliminination()));
|
||||
Passes.emplace_back(std::unique_ptr<FEXCore::IR::Pass>(CreateSyscallOptimization()));
|
||||
Passes.emplace_back(std::unique_ptr<FEXCore::IR::Pass>(CreatePassDeadContextStoreElimination()));
|
||||
Passes.emplace_back(std::unique_ptr<FEXCore::IR::Pass>(CreatePassDeadCodeElimination()));
|
||||
|
||||
// If the IR is compacted post-RA then the node indexing gets messed up and the backend isn't able to find the register assigned to a node
|
||||
// Compact before IR, don't worry about RA generating spills/fills
|
||||
|
@ -8,6 +8,7 @@ FEXCore::IR::Pass* CreateRedundantContextLoadElimination();
|
||||
FEXCore::IR::Pass* CreatePassDeadContextStoreElimination();
|
||||
FEXCore::IR::Pass* CreateSyscallOptimization();
|
||||
FEXCore::IR::Pass* CreateRedundantFlagCalculationEliminination();
|
||||
FEXCore::IR::Pass* CreatePassDeadCodeElimination();
|
||||
FEXCore::IR::Pass* CreateIRCompaction();
|
||||
|
||||
namespace Validation {
|
||||
|
@ -9,42 +9,15 @@ class DeadCodeElimination final : public FEXCore::IR::Pass {
|
||||
bool Run(OpDispatchBuilder *Disp) override;
|
||||
|
||||
private:
|
||||
std::vector<int8_t> SSAStatus;
|
||||
void markUsed(OrderedNodeWrapper *CodeOp, IROp_Header *IROp);
|
||||
};
|
||||
|
||||
enum {
|
||||
UNKNOWN,
|
||||
UNUSED,
|
||||
USED,
|
||||
};
|
||||
|
||||
|
||||
bool DeadCodeElimination::Run(OpDispatchBuilder *Disp) {
|
||||
bool Changed = false;
|
||||
auto CurrentIR = Disp->ViewIR();
|
||||
|
||||
uint32_t SSACount = CurrentIR.GetSSACount();
|
||||
|
||||
SSAStatus = std::vector<int8_t>(SSACount, UNKNOWN);
|
||||
|
||||
uintptr_t ListBegin = CurrentIR.GetListData();
|
||||
uintptr_t DataBegin = CurrentIR.GetData();
|
||||
|
||||
std::function<void(OrderedNodeWrapper)> MarkUsed = [&] (OrderedNodeWrapper CodeOp) {
|
||||
if (SSAStatus[CodeOp.ID()] == USED)
|
||||
return;
|
||||
SSAStatus[CodeOp.ID()] = USED;
|
||||
|
||||
OrderedNode *CodeNode = CodeOp.GetNode(ListBegin);
|
||||
auto IROp = CodeNode->Op(DataBegin);
|
||||
|
||||
uint8_t NumArgs = IR::GetArgs(IROp->Op);
|
||||
for (uint8_t i = 0; i < NumArgs; ++i) {
|
||||
MarkUsed(IROp->Args[i]);
|
||||
}
|
||||
};
|
||||
|
||||
auto Begin = CurrentIR.begin();
|
||||
auto Op = Begin();
|
||||
|
||||
@ -54,7 +27,7 @@ bool DeadCodeElimination::Run(OpDispatchBuilder *Disp) {
|
||||
|
||||
OrderedNode *BlockNode = HeaderOp->Blocks.GetNode(ListBegin);
|
||||
|
||||
// First, iterate over IR nodes in all blocks, marking them as used or unused
|
||||
int NumRemoved = 0;
|
||||
|
||||
while (1) {
|
||||
auto BlockIROp = BlockNode->Op(DataBegin)->CW<FEXCore::IR::IROp_CodeBlock>();
|
||||
@ -64,58 +37,47 @@ bool DeadCodeElimination::Run(OpDispatchBuilder *Disp) {
|
||||
auto CodeBegin = CurrentIR.at(BlockIROp->Begin);
|
||||
auto CodeLast = CurrentIR.at(BlockIROp->Last);
|
||||
|
||||
bool controlFlowEnded = false;
|
||||
while (1) {
|
||||
auto CodeOp = CodeBegin();
|
||||
auto CodeOp = CodeLast();
|
||||
OrderedNode *CodeNode = CodeOp->GetNode(ListBegin);
|
||||
auto IROp = CodeNode->Op(DataBegin);
|
||||
auto ssa = CodeOp->ID();
|
||||
|
||||
if (SSAStatus[ssa] == UNKNOWN) {
|
||||
SSAStatus[ssa] = UNUSED;
|
||||
}
|
||||
|
||||
if (!controlFlowEnded) {
|
||||
switch (IROp->Op) {
|
||||
// State storage
|
||||
case OP_STORECONTEXT:
|
||||
case OP_STOREFLAG:
|
||||
case OP_STOREMEM:
|
||||
case OP_CAS:
|
||||
MarkUsed(*CodeOp);
|
||||
break;
|
||||
// IO
|
||||
case OP_SYSCALL:
|
||||
MarkUsed(*CodeOp);
|
||||
break;
|
||||
// Control flow
|
||||
case OP_BREAK:
|
||||
case OP_JUMP:
|
||||
case OP_EXITFUNCTION:
|
||||
SSAStatus[ssa] = USED;
|
||||
controlFlowEnded = true; // Kill any IR instructions after this
|
||||
break;
|
||||
case OP_CONDJUMP:
|
||||
SSAStatus[ssa] = USED;
|
||||
MarkUsed(IROp->Args[0]); // Mark the condition as used
|
||||
break;
|
||||
case OP_ENDBLOCK:
|
||||
// Only keep this when incrementing
|
||||
auto Op = IROp->C<IROp_EndBlock>();
|
||||
if (Op->RIPIncrement) {
|
||||
SSAStatus[ssa] = USED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// leave everything else marked as unused
|
||||
break;
|
||||
switch (IROp->Op) {
|
||||
// State/memory storage
|
||||
case OP_STORECONTEXT:
|
||||
case OP_STOREFLAG:
|
||||
case OP_STOREMEM:
|
||||
case OP_CAS:
|
||||
// Keep
|
||||
break;
|
||||
// IO
|
||||
case OP_SYSCALL:
|
||||
// Keep
|
||||
break;
|
||||
// Control flow
|
||||
case OP_BREAK:
|
||||
case OP_JUMP:
|
||||
case OP_ENDFUNCTION:
|
||||
case OP_EXITFUNCTION:
|
||||
case OP_CONDJUMP:
|
||||
// Keep
|
||||
break;
|
||||
case OP_DUMMY:
|
||||
case OP_ENDBLOCK:
|
||||
// Keep, so we don't have to update block first/last
|
||||
break;
|
||||
default:
|
||||
if (CodeNode->GetUses() == 0) {
|
||||
NumRemoved++;
|
||||
Disp->Remove(CodeNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (CodeBegin == CodeLast) {
|
||||
break;
|
||||
}
|
||||
++CodeBegin;
|
||||
|
||||
if (CodeLast == CodeBegin) {
|
||||
break;
|
||||
}
|
||||
--CodeLast;
|
||||
}
|
||||
|
||||
if (BlockIROp->Next.ID() == 0) {
|
||||
@ -125,38 +87,7 @@ bool DeadCodeElimination::Run(OpDispatchBuilder *Disp) {
|
||||
}
|
||||
}
|
||||
|
||||
// Loop over blocks
|
||||
while (1) {
|
||||
auto BlockIROp = BlockNode->Op(DataBegin)->CW<FEXCore::IR::IROp_CodeBlock>();
|
||||
LogMan::Throw::A(BlockIROp->Header.Op == OP_CODEBLOCK, "IR type failed to be a code block");
|
||||
|
||||
// We grab these nodes this way so we can iterate easily
|
||||
auto CodeBegin = CurrentIR.at(BlockIROp->Begin);
|
||||
auto CodeLast = CurrentIR.at(BlockIROp->Last);
|
||||
|
||||
while (SSAStatus[CodeBegin()->ID()] != USED) {
|
||||
if (CodeBegin == CodeLast) {
|
||||
|
||||
}
|
||||
++CodeBegin;
|
||||
|
||||
|
||||
}
|
||||
|
||||
auto &prev = BlockIROp->Begin;
|
||||
|
||||
while (1) {
|
||||
auto CodeOp = CodeBegin();
|
||||
|
||||
if (SSAStatus[CodeOp->ID()] == USED) {
|
||||
prev = CodeOp->WrapOffset();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Changed;
|
||||
return NumRemoved != 0;
|
||||
}
|
||||
|
||||
void DeadCodeElimination::markUsed(OrderedNodeWrapper *CodeOp, IROp_Header *IROp) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user