mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 05:00:41 +02:00
Update DeadFlagStoreElimiateion pass
This commit is contained in:
1 parent
0a78651cce
commit
92a64aad2e
1 file changed
+11
-87
@@ -18,10 +18,10 @@ struct FlagInfo {
|
||||
* @brief This is a temporary pass to detect simple multiblock dead flag stores
|
||||
*
|
||||
* First pass computes which flags are read and written per block
|
||||
*
|
||||
*
|
||||
* Second pass computes which flags are stored, but overwritten by the next block(s).
|
||||
* It also propagates this information a few times to catch dead flags across multiple blocks.
|
||||
*
|
||||
*
|
||||
* Third pass removes the dead stores.
|
||||
*
|
||||
*/
|
||||
@@ -30,33 +30,13 @@ bool DeadFlagStoreElimination::Run(IREmitter *IREmit) {
|
||||
|
||||
bool Changed = false;
|
||||
auto CurrentIR = IREmit->ViewIR();
|
||||
uintptr_t ListBegin = CurrentIR.GetListData();
|
||||
uintptr_t DataBegin = CurrentIR.GetData();
|
||||
|
||||
auto Begin = CurrentIR.begin();
|
||||
auto Op = Begin();
|
||||
|
||||
OrderedNode *RealNode = Op->GetNode(ListBegin);
|
||||
auto HeaderOp = RealNode->Op(DataBegin)->CW<FEXCore::IR::IROp_IRHeader>();
|
||||
LogMan::Throw::A(HeaderOp->Header.Op == OP_IRHEADER, "First op wasn't IRHeader");
|
||||
|
||||
// Pass 1
|
||||
// Compute flags read/writes per block
|
||||
// This is conservative and doesn't try to be smart about loads after writes
|
||||
{
|
||||
OrderedNode *BlockNode = HeaderOp->Blocks.GetNode(ListBegin);
|
||||
|
||||
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 (1) {
|
||||
auto CodeOp = CodeBegin();
|
||||
OrderedNode *CodeNode = CodeOp->GetNode(ListBegin);
|
||||
auto IROp = CodeNode->Op(DataBegin);
|
||||
for (auto [BlockNode, BlockIROp] : CurrentIR.GetBlocks()) {
|
||||
for (auto [CodeNode, IROp] : CurrentIR.GetCode(BlockNode)) {
|
||||
|
||||
if (IROp->Op == OP_STOREFLAG) {
|
||||
auto Op = IROp->CW<IR::IROp_StoreFlag>();
|
||||
@@ -67,17 +47,6 @@ bool DeadFlagStoreElimination::Run(IREmitter *IREmit) {
|
||||
FlagMap[BlockNode].reads |= 1 << Op->Flag;
|
||||
}
|
||||
|
||||
// CodeLast is inclusive. So we still need to dump the CodeLast op as well
|
||||
if (CodeBegin == CodeLast) {
|
||||
break;
|
||||
}
|
||||
++CodeBegin;
|
||||
}
|
||||
|
||||
if (BlockIROp->Next.ID() == 0) {
|
||||
break;
|
||||
} else {
|
||||
BlockNode = BlockIROp->Next.GetNode(ListBegin);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,23 +56,12 @@ bool DeadFlagStoreElimination::Run(IREmitter *IREmit) {
|
||||
// Propagate the information a few times to eliminate more
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
OrderedNode *BlockNode = HeaderOp->Blocks.GetNode(ListBegin);
|
||||
|
||||
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 (1) {
|
||||
auto CodeOp = CodeBegin();
|
||||
OrderedNode *CodeNode = CodeOp->GetNode(ListBegin);
|
||||
auto IROp = CodeNode->Op(DataBegin);
|
||||
for (auto [BlockNode, BlockIROp] : CurrentIR.GetBlocks()) {
|
||||
for (auto [CodeNode, IROp] : CurrentIR.GetCode(BlockNode)) {
|
||||
|
||||
if (IROp->Op == OP_JUMP) {
|
||||
auto Op = IROp->CW<IR::IROp_Jump>();
|
||||
OrderedNode *TargetNode = Op->Header.Args[0].GetNode(ListBegin);
|
||||
OrderedNode *TargetNode = CurrentIR.GetNode(Op->Header.Args[0]);
|
||||
|
||||
// stores to remove are written by the next block but not read
|
||||
FlagMap[BlockNode].kill = FlagMap[TargetNode].writes & ~(FlagMap[TargetNode].reads);
|
||||
@@ -114,8 +72,8 @@ bool DeadFlagStoreElimination::Run(IREmitter *IREmit) {
|
||||
else if (IROp->Op == OP_CONDJUMP) {
|
||||
auto Op = IROp->CW<IR::IROp_CondJump>();
|
||||
|
||||
OrderedNode *TrueTargetNode = Op->Header.Args[1].GetNode(ListBegin);
|
||||
OrderedNode *FalseTargetNode = Op->Header.Args[2].GetNode(ListBegin);
|
||||
OrderedNode *TrueTargetNode = CurrentIR.GetNode(Op->Header.Args[1]);
|
||||
OrderedNode *FalseTargetNode = CurrentIR.GetNode(Op->Header.Args[2]);
|
||||
|
||||
// stores to remove are written by the next blocks but not read
|
||||
FlagMap[BlockNode].kill = FlagMap[TrueTargetNode].writes & ~(FlagMap[TrueTargetNode].reads);
|
||||
@@ -124,18 +82,6 @@ bool DeadFlagStoreElimination::Run(IREmitter *IREmit) {
|
||||
// Flags that are written by the next blocks can be considered as written by this block, if not read
|
||||
FlagMap[BlockNode].writes |= FlagMap[BlockNode].kill & ~FlagMap[BlockNode].reads;
|
||||
}
|
||||
|
||||
// CodeLast is inclusive. So we still need to dump the CodeLast op as well
|
||||
if (CodeBegin == CodeLast) {
|
||||
break;
|
||||
}
|
||||
++CodeBegin;
|
||||
}
|
||||
|
||||
if (BlockIROp->Next.ID() == 0) {
|
||||
break;
|
||||
} else {
|
||||
BlockNode = BlockIROp->Next.GetNode(ListBegin);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,19 +89,8 @@ bool DeadFlagStoreElimination::Run(IREmitter *IREmit) {
|
||||
// Pass 3
|
||||
// Remove the dead stores
|
||||
{
|
||||
OrderedNode *BlockNode = HeaderOp->Blocks.GetNode(ListBegin);
|
||||
|
||||
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 (1) {
|
||||
auto CodeOp = CodeBegin();
|
||||
OrderedNode *CodeNode = CodeOp->GetNode(ListBegin);
|
||||
auto IROp = CodeNode->Op(DataBegin);
|
||||
for (auto [BlockNode, BlockIROp] : CurrentIR.GetBlocks()) {
|
||||
for (auto [CodeNode, IROp] : CurrentIR.GetCode(BlockNode)) {
|
||||
|
||||
if (IROp->Op == OP_STOREFLAG) {
|
||||
auto Op = IROp->CW<IR::IROp_StoreFlag>();
|
||||
@@ -166,17 +101,6 @@ bool DeadFlagStoreElimination::Run(IREmitter *IREmit) {
|
||||
}
|
||||
}
|
||||
|
||||
// CodeLast is inclusive. So we still need to dump the CodeLast op as well
|
||||
if (CodeBegin == CodeLast) {
|
||||
break;
|
||||
}
|
||||
++CodeBegin;
|
||||
}
|
||||
|
||||
if (BlockIROp->Next.ID() == 0) {
|
||||
break;
|
||||
} else {
|
||||
BlockNode = BlockIROp->Next.GetNode(ListBegin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user