Update DeadFlagStoreElimiateion pass

This commit is contained in:
Scott Mansell committed 2020-09-11 21:50:30 +12:00
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);
}
}
}