[llvm] [WebAssembly] Replace Reachability with SCCs in Irreducible CFG Fixer (PR #179722)
Heejin Ahn via llvm-commits
llvm-commits at lists.llvm.org
Sat Feb 14 06:35:13 PST 2026
================
@@ -120,65 +113,138 @@ class ReachabilityGraph {
assert(I != LoopEnterers.end());
return I->second;
}
+ unsigned getSCCId(MachineBasicBlock *MBB) const {
+ return SccId[getIndex(MBB)];
+ }
private:
MachineBasicBlock *Entry;
const BlockSet &Blocks;
+ DenseMap<MachineBasicBlock *, unsigned> BlockIndex;
BlockSet Loopers, LoopEntries;
DenseMap<MachineBasicBlock *, BlockSet> LoopEnterers;
bool inRegion(MachineBasicBlock *MBB) const { return Blocks.count(MBB); }
- // Maps a block to all the other blocks it can reach.
- DenseMap<MachineBasicBlock *, BlockSet> Reachable;
+ // Per-node adjacency in the region (excluding edges to Entry).
+ SmallVector<SmallVector<unsigned, 4>, 0> Succs;
+ SmallVector<bool, 0> SelfLoop;
+
+ // SCC = Strongly-connected component
+ // Map of an MBB's index (provided by `BlockIndex`) to it's assigned SCC
+ SmallVector<unsigned, 0> SccId;
+ // The number of elements in each SCC
+ SmallVector<unsigned, 0> SccSize;
+
+ unsigned getIndex(MachineBasicBlock *MBB) const {
+ auto It = BlockIndex.find(MBB);
+ assert(It != BlockIndex.end());
+ return It->second;
+ }
void calculate() {
- // Reachability computation work list. Contains pairs of recent additions
- // (A, B) where we just added a link A => B.
- using BlockPair = std::pair<MachineBasicBlock *, MachineBasicBlock *>;
- SmallVector<BlockPair, 4> WorkList;
+ auto NumBlocks = Blocks.size();
+ Succs.assign(NumBlocks, {});
+ SelfLoop.assign(NumBlocks, false);
+
+ unsigned MMBIdx = 0;
+ BlockIndex.clear();
+ BlockIndex.reserve(NumBlocks);
+ for (auto *MBB : Blocks)
+ BlockIndex[MBB] = MMBIdx++;
// Add all relevant direct branches.
+ MMBIdx = 0;
for (auto *MBB : Blocks) {
for (auto *Succ : MBB->successors()) {
if (Succ != Entry && inRegion(Succ)) {
- Reachable[MBB].insert(Succ);
- WorkList.emplace_back(MBB, Succ);
+ if (Succ == MBB)
+ SelfLoop[MMBIdx] = true;
+ Succs[MMBIdx].push_back(getIndex(Succ));
}
}
+
+ ++MMBIdx;
}
- while (!WorkList.empty()) {
- MachineBasicBlock *MBB, *Succ;
- std::tie(MBB, Succ) = WorkList.pop_back_val();
- assert(inRegion(MBB) && Succ != Entry && inRegion(Succ));
- if (MBB != Entry) {
- // We recently added MBB => Succ, and that means we may have enabled
- // Pred => MBB => Succ.
- for (auto *Pred : MBB->predecessors()) {
- if (Reachable[Pred].insert(Succ).second) {
- WorkList.emplace_back(Pred, Succ);
+ // Tarjan SCC (iterative) on the region graph.
+ SccId.assign(NumBlocks, std::numeric_limits<unsigned>::max());
+ SccSize.clear();
+ SmallVector<int, 0> Index(NumBlocks, -1);
+ SmallVector<int, 0> Lowlink(NumBlocks, 0);
+ SmallVector<unsigned, 0> Stack;
+ SmallVector<bool, 0> OnStack(NumBlocks, false);
+ int NextIndex = 0;
+
+ struct Frame {
+ unsigned V;
+ unsigned NextSucc;
+ };
+ SmallVector<Frame, 0> DFS;
+
+ auto pushNode = [&](unsigned V) {
+ Index[V] = Lowlink[V] = NextIndex++;
+ Stack.push_back(V);
+ OnStack[V] = true;
+ DFS.push_back({V, 0});
+ };
+
+ for (unsigned V = 0; V < NumBlocks; ++V) {
+ if (Index[V] != -1)
+ continue;
+ pushNode(V);
+ while (!DFS.empty()) {
+ Frame &F = DFS.back();
+ unsigned Cur = F.V;
+ if (F.NextSucc < Succs[Cur].size()) {
+ unsigned W = Succs[Cur][F.NextSucc++];
+ if (Index[W] == -1) {
+ pushNode(W);
+ } else if (OnStack[W]) {
+ Lowlink[Cur] = std::min(Lowlink[Cur], Index[W]);
+ }
+ continue;
+ }
+
+ // Finished exploring Cur.
----------------
aheejin wrote:
```suggestion
// Finished exploring Cur. Check if Cur is the root of a SCC, and if so,
// create one.
```
https://github.com/llvm/llvm-project/pull/179722
More information about the llvm-commits
mailing list