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

Alexis Engelke via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 8 11:16:36 PDT 2024


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

Avoids one heap allocation per basic block per dominator tree and improves data locality.

[c-t-t](http://llvm-compile-time-tracker.com/compare.php?from=fbb0619fe2acea4ac8764d13b754505ed8f1b578&to=7d6bcb79154bac9d4df6559535cc8c310b1617c2&stat=instructions:u) stage2-O3 -0.52%

>From 7d6bcb79154bac9d4df6559535cc8c310b1617c2 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    | 28 +++++++++++--------
 .../llvm/Support/GenericDomTreeConstruction.h | 15 ++++------
 2 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/llvm/include/llvm/Support/GenericDomTree.h b/llvm/include/llvm/Support/GenericDomTree.h
index 7e2b68e6faea29..00ce3df9c99f1b 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"
@@ -37,6 +38,7 @@
 #include <cstddef>
 #include <iterator>
 #include <memory>
+#include <new>
 #include <type_traits>
 #include <utility>
 
@@ -258,8 +260,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.
@@ -269,6 +270,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;
@@ -281,8 +284,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();
   }
 
@@ -292,6 +296,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;
@@ -398,7 +403,7 @@ class DominatorTreeBase {
   /// statically unreachable block.
   DomTreeNodeBase<NodeT> *getNode(const NodeT *BB) const {
     if (auto Idx = getNodeIndex(BB); Idx && *Idx < DomTreeNodes.size())
-      return DomTreeNodes[*Idx].get();
+      return DomTreeNodes[*Idx];
     return nullptr;
   }
 
@@ -718,7 +723,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;
@@ -902,13 +907,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
@@ -993,6 +998,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 9aab5ec60f4a25..6f2a798135e800 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