[llvm] [Support] Use bump ptr allocator for domtree nodes (PR #102516)

Alexis Engelke via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 12 10:54:37 PST 2026


https://github.com/aengelke updated https://github.com/llvm/llvm-project/pull/102516

>From 77c878227671af5143b272f09ee2b260130c9d25 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Thu, 8 Aug 2024 15:25:40 +0000
Subject: [PATCH] [Support] Use bump ptr allocator for domtree nodes

---
 llvm/include/llvm/Support/GenericDomTree.h    | 29 ++++++++++++-------
 .../llvm/Support/GenericDomTreeConstruction.h | 15 ++++------
 2 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/llvm/include/llvm/Support/GenericDomTree.h b/llvm/include/llvm/Support/GenericDomTree.h
index b6aae9f7928e3..8b5b7a388529a 100644
--- a/llvm/include/llvm/Support/GenericDomTree.h
+++ b/llvm/include/llvm/Support/GenericDomTree.h
@@ -29,6 +29,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
 #include "llvm/Support/CFGDiff.h"
 #include "llvm/Support/CFGUpdate.h"
 #include "llvm/Support/raw_ostream.h"
@@ -36,6 +37,7 @@
 #include <cassert>
 #include <cstddef>
 #include <memory>
+#include <new>
 #include <type_traits>
 #include <utility>
 
@@ -257,8 +259,7 @@ class DominatorTreeBase {
   // Dominators always have a single root, postdominators can have more.
   SmallVector<NodeT *, IsPostDom ? 4 : 1> Roots;
 
-  using DomTreeNodeStorageTy =
-      SmallVector<std::unique_ptr<DomTreeNodeBase<NodeT>>>;
+  using DomTreeNodeStorageTy = SmallVector<DomTreeNodeBase<NodeT> *>;
   DomTreeNodeStorageTy DomTreeNodes;
   // For graphs where blocks don't have numbers, create a numbering here.
   // TODO: use an empty struct with [[no_unique_address]] in C++20.
@@ -268,6 +269,8 @@ class DominatorTreeBase {
   DomTreeNodeBase<NodeT> *RootNode = nullptr;
   ParentPtr Parent = nullptr;
 
+  SpecificBumpPtrAllocator<DomTreeNodeBase<NodeT>> NodeAllocator;
+
   mutable bool DFSInfoValid = false;
   mutable unsigned int SlowQueries = 0;
   unsigned BlockNumberEpoch = 0;
@@ -280,8 +283,9 @@ class DominatorTreeBase {
   DominatorTreeBase(DominatorTreeBase &&Arg)
       : Roots(std::move(Arg.Roots)), DomTreeNodes(std::move(Arg.DomTreeNodes)),
         NodeNumberMap(std::move(Arg.NodeNumberMap)), RootNode(Arg.RootNode),
-        Parent(Arg.Parent), DFSInfoValid(Arg.DFSInfoValid),
-        SlowQueries(Arg.SlowQueries), BlockNumberEpoch(Arg.BlockNumberEpoch) {
+        Parent(Arg.Parent), NodeAllocator(std::move(Arg.NodeAllocator)),
+        DFSInfoValid(Arg.DFSInfoValid), SlowQueries(Arg.SlowQueries),
+        BlockNumberEpoch(Arg.BlockNumberEpoch) {
     Arg.wipe();
   }
 
@@ -293,6 +297,7 @@ class DominatorTreeBase {
     NodeNumberMap = std::move(RHS.NodeNumberMap);
     RootNode = RHS.RootNode;
     Parent = RHS.Parent;
+    NodeAllocator = std::move(RHS.NodeAllocator);
     DFSInfoValid = RHS.DFSInfoValid;
     SlowQueries = RHS.SlowQueries;
     BlockNumberEpoch = RHS.BlockNumberEpoch;
@@ -401,7 +406,7 @@ class DominatorTreeBase {
     assert((!BB || Parent == NodeTrait::getParent(const_cast<NodeT *>(BB))) &&
            "cannot get DomTreeNode of block with different parent");
     if (auto Idx = getNodeIndex(BB); Idx && *Idx < DomTreeNodes.size())
-      return DomTreeNodes[*Idx].get();
+      return DomTreeNodes[*Idx];
     return nullptr;
   }
 
@@ -737,7 +742,7 @@ class DominatorTreeBase {
     std::optional<unsigned> IdxOpt = getNodeIndex(BB);
     assert(IdxOpt && DomTreeNodes[*IdxOpt] &&
            "Removing node that isn't in dominator tree.");
-    DomTreeNodeBase<NodeT> *Node = DomTreeNodes[*IdxOpt].get();
+    DomTreeNodeBase<NodeT> *Node = DomTreeNodes[*IdxOpt];
     assert(Node->isLeaf() && "Node is not a leaf node.");
 
     DFSInfoValid = false;
@@ -913,6 +918,7 @@ class DominatorTreeBase {
     RootNode = nullptr;
     Parent = nullptr;
     DFSInfoValid = false;
+    NodeAllocator.DestroyAll();
     SlowQueries = 0;
   }
 
@@ -921,13 +927,13 @@ class DominatorTreeBase {
 
   DomTreeNodeBase<NodeT> *createNode(NodeT *BB,
                                      DomTreeNodeBase<NodeT> *IDom = nullptr) {
-    auto Node = std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDom);
-    auto *NodePtr = Node.get();
+    auto *Node =
+        new (NodeAllocator.Allocate()) DomTreeNodeBase<NodeT>(BB, IDom);
     unsigned NodeIdx = getNodeIndexForInsert(BB);
-    DomTreeNodes[NodeIdx] = std::move(Node);
+    DomTreeNodes[NodeIdx] = Node;
     if (IDom)
-      IDom->addChild(NodePtr);
-    return NodePtr;
+      IDom->addChild(Node);
+    return Node;
   }
 
   // NewBB is split and now it has one successor. Update dominator tree to
@@ -1012,6 +1018,7 @@ class DominatorTreeBase {
       NodeNumberMap.clear();
     RootNode = nullptr;
     Parent = nullptr;
+    NodeAllocator.DestroyAll();
   }
 };
 
diff --git a/llvm/include/llvm/Support/GenericDomTreeConstruction.h b/llvm/include/llvm/Support/GenericDomTreeConstruction.h
index 557c9ec319e33..9d520b45f3d88 100644
--- a/llvm/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/llvm/include/llvm/Support/GenericDomTreeConstruction.h
@@ -1246,8 +1246,7 @@ struct SemiNCAInfo {
     clear();
     doFullDFSWalk(DT, AlwaysDescend);
 
-    for (auto &NodeToTN : DT.DomTreeNodes) {
-      const TreeNodePtr TN = NodeToTN.get();
+    for (auto *TN : DT.DomTreeNodes) {
       if (!TN)
         continue;
       const NodePtr BB = TN->getBlock();
@@ -1281,8 +1280,7 @@ struct SemiNCAInfo {
   // have level L + 1.
   // Running time: O(N).
   static bool VerifyLevels(const DomTreeT &DT) {
-    for (auto &NodeToTN : DT.DomTreeNodes) {
-      const TreeNodePtr TN = NodeToTN.get();
+    for (auto *TN : DT.DomTreeNodes) {
       if (!TN)
         continue;
       const NodePtr BB = TN->getBlock();
@@ -1338,8 +1336,7 @@ struct SemiNCAInfo {
 
     // For each tree node verify if children's DFS numbers cover their parent's
     // DFS numbers with no gaps.
-    for (const auto &NodeToTN : DT.DomTreeNodes) {
-      const TreeNodePtr Node = NodeToTN.get();
+    for (auto *Node : DT.DomTreeNodes) {
       if (!Node)
         continue;
 
@@ -1453,8 +1450,7 @@ struct SemiNCAInfo {
   // This means that if a node gets disconnected from the graph, then all of
   // the nodes it dominated previously will now become unreachable.
   bool verifyParentProperty(const DomTreeT &DT) {
-    for (auto &NodeToTN : DT.DomTreeNodes) {
-      const TreeNodePtr TN = NodeToTN.get();
+    for (auto *TN : DT.DomTreeNodes) {
       if (!TN)
         continue;
       const NodePtr BB = TN->getBlock();
@@ -1489,8 +1485,7 @@ struct SemiNCAInfo {
   // This means that if a node gets disconnected from the graph, then all of its
   // siblings will now still be reachable.
   bool verifySiblingProperty(const DomTreeT &DT) {
-    for (auto &NodeToTN : DT.DomTreeNodes) {
-      const TreeNodePtr TN = NodeToTN.get();
+    for (auto *TN : DT.DomTreeNodes) {
       if (!TN)
         continue;
       const NodePtr BB = TN->getBlock();



More information about the llvm-commits mailing list