When implementing algorithms that operate on complex data structures (trees, graphs, dominator structures), abstract the traversal mechanism from the operation performed at each node. Use visitor patterns or callbacks to separate concerns, making algorithms more maintainable and reusable.
When implementing algorithms that operate on complex data structures (trees, graphs, dominator structures), abstract the traversal mechanism from the operation performed at each node. Use visitor patterns or callbacks to separate concerns, making algorithms more maintainable and reusable.
For example, instead of directly traversing a data structure and performing operations:
// Tightly coupled approach
void ScaleLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk)
{
for (BasicBlock* const curBlk : BasicBlockRangeList(begBlk, endBlk))
{
// Direct operations on curBlk mixed with traversal logic
if (curBlk->hasProfileWeight()) continue;
if (curBlk->isRunRarely()) continue;
if (!m_reachabilitySets->GetDfsTree()->Contains(curBlk)) continue;
// More operations...
}
}
Abstract the traversal pattern to separate it from node operations:
// Decoupled approach
void ScaleLoopBlocks(FlowGraphNaturalLoop* loop)
{
loop->VisitLoopBlocks([&](BasicBlock* curBlk) -> BasicBlockVisit {
if (curBlk->hasProfileWeight()) return BasicBlockVisit::Continue;
if (curBlk->isRunRarely()) return BasicBlockVisit::Continue;
// Operations on curBlk without traversal concerns
return BasicBlockVisit::Continue;
});
}
This approach offers several benefits:
Enter the URL of a public GitHub repository