From 105d0a36adfb7083ea64d22ddfb2b91deea7f265 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 30 May 2025 15:45:55 -0400 Subject: [PATCH] RedundantFlagCalculationElimination: dont use hashmap combined results on node from this and the previous commit: N Min Max Median Avg Stddev x 50 0.44433582 0.46988457 0.45344824 0.45320041 0.0043288623 + 50 0.4385365 0.46615359 0.45026179 0.44996216 0.0045742233 Difference at 95.0% confidence -0.00323825 +/- 0.00176704 -0.71453% +/- 0.389903% (Student's t, pooled s = 0.00445323) Signed-off-by: Alyssa Rosenzweig --- .../RedundantFlagCalculationElimination.cpp | 69 ++++++++++--------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/FEXCore/Source/Interface/IR/Passes/RedundantFlagCalculationElimination.cpp b/FEXCore/Source/Interface/IR/Passes/RedundantFlagCalculationElimination.cpp index e18e35e44..59549f487 100644 --- a/FEXCore/Source/Interface/IR/Passes/RedundantFlagCalculationElimination.cpp +++ b/FEXCore/Source/Interface/IR/Passes/RedundantFlagCalculationElimination.cpp @@ -97,46 +97,49 @@ private: }; struct BlockInfo { - fextl::vector Predecessors; + fextl::vector Predecessors; + Ref Node; uint8_t Flags; bool InWorklist; }; struct ControlFlowGraph { - fextl::unordered_map BlockMap; + fextl::vector BlockMap; IRListView& IR; - void AddBlock(fextl::deque& Worklist, Ref Block) { - uint32_t ID = IR.GetID(Block).Value; + void Init(fextl::deque& Worklist, uint32_t BlockCount) { + BlockMap.resize(BlockCount); - // Add the block with conservative flags and already in the worklist. - auto Info = &BlockMap.emplace(ID, BlockInfo {{}, FLAG_ALL, true}).first->second; + for (unsigned ID = 0; ID < BlockCount; ++ID) { + // Add the block with conservative flags and already in the worklist. + auto Info = BlockInfo {{}, nullptr, FLAG_ALL, true}; - // Add some initial capacity - Info->Predecessors.reserve(2); + // Add some initial capacity + Info.Predecessors.reserve(2); - // Add to worklist - Worklist.push_back(Block); + BlockMap[ID] = Info; + Worklist.push_back(ID); + } } BlockInfo* Get(uint32_t Block) { - return &BlockMap.try_emplace(Block).first->second; + return &BlockMap[Block]; } - BlockInfo* Get(Ref Block) { - return Get(IR.GetID(Block).Value); + BlockInfo* Get(IROp_CodeBlock* Block) { + return &BlockMap[Block->ID]; } BlockInfo* Get(OrderedNodeWrapper Block) { - return Get(Block.ID().Value); + return Get(IR.GetOp(Block)); } - void RecordEdge(Ref From, Ref To) { + void RecordEdge(uint32_t From, OrderedNodeWrapper To) { auto Info = Get(To); Info->Predecessors.push_back(From); } - void AddWorklist(fextl::deque& Worklist, Ref Block) { + void AddWorklist(fextl::deque& Worklist, uint32_t Block) { auto Info = Get(Block); if (!Info->InWorklist) { Info->InWorklist = true; @@ -637,8 +640,8 @@ bool DeadFlagCalculationEliminination::ProcessBlock(IREmitter* IREmit, IRListVie // For the purposes of global propagation, the content of our progress doesn't // matter -- only the difference in our final FlagsRead contributes to changes // in the predecessors. - uint32_t OldFlagsRead = CFG.Get(Block)->Flags; - CFG.Get(Block)->Flags = FlagsRead; + uint32_t OldFlagsRead = CFG.Get(BlockIROp->ID)->Flags; + CFG.Get(BlockIROp->ID)->Flags = FlagsRead; return (OldFlagsRead != FlagsRead); } @@ -650,12 +653,14 @@ void DeadFlagCalculationEliminination::OptimizeParity(IREmitter* IREmit, IRListV // Initialize conservatively: all blocks need full parity. This initialization // matters for proper handling of backedges. for (auto [Block, BlockHeader] : CurrentIR.GetBlocks()) { - CFG.Get(Block)->Flags = FULL; + auto ID = BlockHeader->C()->ID; + CFG.Get(ID)->Flags = FULL; } for (auto [Block, BlockHeader] : CurrentIR.GetBlocks()) { + auto ID = BlockHeader->C()->ID; bool Full = false; - auto Predecessors = CFG.Get(Block)->Predecessors; + auto Predecessors = CFG.Get(ID)->Predecessors; if (Predecessors.empty()) { // Conservatively assume there was full parity before the start block @@ -701,7 +706,7 @@ void DeadFlagCalculationEliminination::OptimizeParity(IREmitter* IREmit, IRListV } // Record our final state for our successors to read. - CFG.Get(Block)->Flags = Full ? FULL : PARTIAL; + CFG.Get(ID)->Flags = Full ? FULL : PARTIAL; } } @@ -709,28 +714,28 @@ void DeadFlagCalculationEliminination::Run(IREmitter* IREmit) { FEXCORE_PROFILE_SCOPED("PassManager::DFE"); auto CurrentIR = IREmit->ViewIR(); - fextl::deque Worklist; + fextl::deque Worklist; + // Initialize CFG ControlFlowGraph CFG {.IR = CurrentIR}; - - // Gather blocks - for (auto [BlockNode, BlockHeader] : CurrentIR.GetBlocks()) { - CFG.AddBlock(Worklist, BlockNode); - } + CFG.Init(Worklist, CurrentIR.GetHeader()->BlockCount); // Gather CFG for (auto [BlockNode, BlockHeader] : CurrentIR.GetBlocks()) { - auto CodeLast = CurrentIR.at(BlockHeader->C()->Last); + auto Block = BlockHeader->C(); + auto CodeLast = CurrentIR.at(Block->Last); --CodeLast; auto [ExitNode, ExitOp] = CodeLast(); if (ExitOp->Op == IR::OP_CONDJUMP) { auto Op = ExitOp->CW(); - CFG.RecordEdge(BlockNode, CurrentIR.GetNode(Op->TrueBlock)); - CFG.RecordEdge(BlockNode, CurrentIR.GetNode(Op->FalseBlock)); + CFG.RecordEdge(Block->ID, Op->TrueBlock); + CFG.RecordEdge(Block->ID, Op->FalseBlock); } else if (ExitOp->Op == IR::OP_JUMP) { - CFG.RecordEdge(BlockNode, CurrentIR.GetNode(ExitOp->Args[0])); + CFG.RecordEdge(Block->ID, ExitOp->Args[0]); } + + CFG.Get(Block->ID)->Node = BlockNode; } // After processing a block, if we made progress, we must process its @@ -741,7 +746,7 @@ void DeadFlagCalculationEliminination::Run(IREmitter* IREmit) { auto Info = CFG.Get(Block); Info->InWorklist = false; - if (ProcessBlock(IREmit, CurrentIR, Block, CFG)) { + if (ProcessBlock(IREmit, CurrentIR, Info->Node, CFG)) { for (auto Pred : Info->Predecessors) { CFG.AddWorklist(Worklist, Pred); }