From 92a64aad2e36b2f9130cbcccf494c87480296cc3 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Fri, 11 Sep 2020 15:17:57 +1200 Subject: [PATCH] Update DeadFlagStoreElimiateion pass --- .../IR/Passes/DeadFlagStoreElimination.cpp | 98 +++---------------- 1 file changed, 11 insertions(+), 87 deletions(-) diff --git a/External/FEXCore/Source/Interface/IR/Passes/DeadFlagStoreElimination.cpp b/External/FEXCore/Source/Interface/IR/Passes/DeadFlagStoreElimination.cpp index 55eae62e3..54a233ea5 100644 --- a/External/FEXCore/Source/Interface/IR/Passes/DeadFlagStoreElimination.cpp +++ b/External/FEXCore/Source/Interface/IR/Passes/DeadFlagStoreElimination.cpp @@ -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(); - 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(); - 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(); @@ -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(); - 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(); - 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(); - 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(); - 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(); @@ -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); } } }