[llvm] [IDF] Use BitVectors indexed by DFS number for visited sets (NFC). (PR #227832)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 1 10:04:30 PDT 2026


https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/227832

>From 4405abaeab711aeb6deef1875aafc37cdac56b97 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 29 Sep 2026 09:18:31 +0100
Subject: [PATCH 1/2] [IDF] Use BitVectors indexed by DFS number for visited
 sets (NFC).

IDFCalculatorBase::calculate tracks visited dominator tree nodes in two
SmallPtrSets. The DFS numbers computed at the start of calculate are
unique and dense in [0, number of nodes), with the DFS out-number of the
root being the number of nodes, so use them to index BitVectors instead.

This reduces hashing overhead and improves compile-time, depending on
configuration/workload:

stage1-O3: -0.04%
stage1-ReleaseThinLTO: -0.05%
stage1-ReleaseLTO-g: -0.22%
stage1-aarch64-O3: -0.06%
stage2-O3: -0.04%
stage2-clang: -0.04%

https://llvm-compile-time-tracker.com/compare.php?from=b96b66160ace30c2b5eef1f4afdb14c95ecc26cd&to=5ffb13d6d1f87195bba8af13366a152a7de2bfe0&stat=instructions:u
---
 .../GenericIteratedDominanceFrontier.h        | 26 ++++++++++++-------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h b/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h
index c52b2cab377bf87..4e9b30a97060144 100644
--- a/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h
+++ b/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h
@@ -23,6 +23,7 @@
 #ifndef LLVM_SUPPORT_GENERICITERATEDDOMINANCEFRONTIER_H
 #define LLVM_SUPPORT_GENERICITERATEDDOMINANCEFRONTIER_H
 
+#include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/iterator_range.h"
@@ -144,18 +145,20 @@ void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
 
   DT.updateDFSNumbers();
 
+  // The DFS in-numbers are unique and dense in [0, number of nodes), with the
+  // root's DFS out-number being the number of nodes. Use them to index the
+  // visited sets.
+  const DomTreeNodeBase<NodeTy> *RootNode = DT.getRootNode();
+  unsigned NumNodes = RootNode ? RootNode->getDFSNumOut() : 0;
+
   SmallVector<DomTreeNodeBase<NodeTy> *, 32> Worklist;
-  SmallPtrSet<DomTreeNodeBase<NodeTy> *, 16> VisitedPQ;
-  SmallPtrSet<DomTreeNodeBase<NodeTy> *, 16> VisitedWorklist;
-  if (useLiveIn) {
-    VisitedPQ.reserve(LiveInBlocks->size());
-    VisitedWorklist.reserve(LiveInBlocks->size());
-  }
+  BitVector VisitedPQ(NumNodes);
+  BitVector VisitedWorklist(NumNodes);
 
   for (NodeTy *BB : *DefBlocks)
     if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB)) {
       PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
-      VisitedWorklist.insert(Node);
+      VisitedWorklist.set(Node->getDFSNumIn());
     }
 
   while (!PQ.empty()) {
@@ -184,8 +187,9 @@ void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
         if (SuccLevel > RootLevel)
           return;
 
-        if (!VisitedPQ.insert(SuccNode).second)
+        if (VisitedPQ.test(SuccNode->getDFSNumIn()))
           return;
+        VisitedPQ.set(SuccNode->getDFSNumIn());
 
         NodeTy *SuccBB = SuccNode->getBlock();
         if (useLiveIn && !LiveInBlocks->count(SuccBB))
@@ -201,8 +205,10 @@ void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
         DoWork(Succ);
 
       for (auto DomChild : *Node) {
-        if (VisitedWorklist.insert(DomChild).second)
-          Worklist.push_back(DomChild);
+        if (VisitedWorklist.test(DomChild->getDFSNumIn()))
+          continue;
+        VisitedWorklist.set(DomChild->getDFSNumIn());
+        Worklist.push_back(DomChild);
       }
     }
   }

>From 26453e778b0f5feab44b9ffe801655e9a8a1f769 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 1 Oct 2026 09:54:03 +0100
Subject: [PATCH 2/2] Use SmallVector<bool>

---
 .../Support/GenericIteratedDominanceFrontier.h   | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h b/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h
index 4e9b30a97060144..32baf09b8b19d30 100644
--- a/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h
+++ b/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h
@@ -23,7 +23,6 @@
 #ifndef LLVM_SUPPORT_GENERICITERATEDDOMINANCEFRONTIER_H
 #define LLVM_SUPPORT_GENERICITERATEDDOMINANCEFRONTIER_H
 
-#include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/iterator_range.h"
@@ -152,13 +151,13 @@ void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
   unsigned NumNodes = RootNode ? RootNode->getDFSNumOut() : 0;
 
   SmallVector<DomTreeNodeBase<NodeTy> *, 32> Worklist;
-  BitVector VisitedPQ(NumNodes);
-  BitVector VisitedWorklist(NumNodes);
+  SmallVector<bool, 32> VisitedPQ(NumNodes, false);
+  SmallVector<bool, 32> VisitedWorklist(NumNodes, false);
 
   for (NodeTy *BB : *DefBlocks)
     if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB)) {
       PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
-      VisitedWorklist.set(Node->getDFSNumIn());
+      VisitedWorklist[Node->getDFSNumIn()] = true;
     }
 
   while (!PQ.empty()) {
@@ -187,9 +186,8 @@ void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
         if (SuccLevel > RootLevel)
           return;
 
-        if (VisitedPQ.test(SuccNode->getDFSNumIn()))
+        if (std::exchange(VisitedPQ[SuccNode->getDFSNumIn()], true))
           return;
-        VisitedPQ.set(SuccNode->getDFSNumIn());
 
         NodeTy *SuccBB = SuccNode->getBlock();
         if (useLiveIn && !LiveInBlocks->count(SuccBB))
@@ -205,10 +203,8 @@ void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
         DoWork(Succ);
 
       for (auto DomChild : *Node) {
-        if (VisitedWorklist.test(DomChild->getDFSNumIn()))
-          continue;
-        VisitedWorklist.set(DomChild->getDFSNumIn());
-        Worklist.push_back(DomChild);
+        if (!std::exchange(VisitedWorklist[DomChild->getDFSNumIn()], true))
+          Worklist.push_back(DomChild);
       }
     }
   }



More information about the llvm-commits mailing list