[llvm] [IR] Use single map in PredIteratorCache (NFC) (PR #101950)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 5 02:59:50 PDT 2024


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/101950

Use a single map storing ArrayRef instead of two separate maps for the base pointer and size. This saves one map lookup per cache accesses.

This is an alternative to https://github.com/llvm/llvm-project/pull/101885 with a similar compile-time improvement: http://llvm-compile-time-tracker.com/compare.php?from=1fa7f05b709748e8a36936cbb5508070c8214354&to=1af82f2ca51aa324c772941770dd3ee4043b2b4d&stat=instructions:u

>From 15f339ca0f1614050793c5103a23d6fe88bbef8e Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 5 Aug 2024 10:35:47 +0200
Subject: [PATCH] [IR] Use single map in PredIteratorCache (NFC)

Use a single map storing ArrayRef instead of two separate maps
for the base pointer and size. This saves one map lookup per
cache accesses.

This is an alternative to https://github.com/llvm/llvm-project/pull/101885.
---
 llvm/include/llvm/IR/PredIteratorCache.h | 43 ++++++------------------
 1 file changed, 10 insertions(+), 33 deletions(-)

diff --git a/llvm/include/llvm/IR/PredIteratorCache.h b/llvm/include/llvm/IR/PredIteratorCache.h
index fc8cf20e9f759..d52e78b25fc33 100644
--- a/llvm/include/llvm/IR/PredIteratorCache.h
+++ b/llvm/include/llvm/IR/PredIteratorCache.h
@@ -25,52 +25,29 @@ namespace llvm {
 /// predecessor iterator queries.  This is useful for code that repeatedly
 /// wants the predecessor list for the same blocks.
 class PredIteratorCache {
-  /// BlockToPredsMap - Pointer to null-terminated list.
-  mutable DenseMap<BasicBlock *, BasicBlock **> BlockToPredsMap;
-  mutable DenseMap<BasicBlock *, unsigned> BlockToPredCountMap;
+  /// Cached list of predecessors, allocated in Memory.
+  mutable DenseMap<BasicBlock *, ArrayRef<BasicBlock *>> BlockToPredsMap;
 
   /// Memory - This is the space that holds cached preds.
   BumpPtrAllocator Memory;
 
-private:
-  /// GetPreds - Get a cached list for the null-terminated predecessor list of
-  /// the specified block.  This can be used in a loop like this:
-  ///   for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI)
-  ///      use(*PI);
-  /// instead of:
-  /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
-  BasicBlock **GetPreds(BasicBlock *BB) {
-    BasicBlock **&Entry = BlockToPredsMap[BB];
-    if (Entry)
+public:
+  size_t size(BasicBlock *BB) { return get(BB).size(); }
+  ArrayRef<BasicBlock *> get(BasicBlock *BB) {
+    ArrayRef<BasicBlock *> &Entry = BlockToPredsMap[BB];
+    if (Entry.data())
       return Entry;
 
     SmallVector<BasicBlock *, 32> PredCache(predecessors(BB));
-    PredCache.push_back(nullptr); // null terminator.
-
-    BlockToPredCountMap[BB] = PredCache.size() - 1;
-
-    Entry = Memory.Allocate<BasicBlock *>(PredCache.size());
-    std::copy(PredCache.begin(), PredCache.end(), Entry);
+    BasicBlock **Data = Memory.Allocate<BasicBlock *>(PredCache.size());
+    std::copy(PredCache.begin(), PredCache.end(), Data);
+    Entry = ArrayRef(Data, PredCache.size());
     return Entry;
   }
 
-  unsigned GetNumPreds(BasicBlock *BB) const {
-    auto Result = BlockToPredCountMap.find(BB);
-    if (Result != BlockToPredCountMap.end())
-      return Result->second;
-    return BlockToPredCountMap[BB] = pred_size(BB);
-  }
-
-public:
-  size_t size(BasicBlock *BB) const { return GetNumPreds(BB); }
-  ArrayRef<BasicBlock *> get(BasicBlock *BB) {
-    return ArrayRef(GetPreds(BB), GetNumPreds(BB));
-  }
-
   /// clear - Remove all information.
   void clear() {
     BlockToPredsMap.clear();
-    BlockToPredCountMap.clear();
     Memory.Reset();
   }
 };



More information about the llvm-commits mailing list