[llvm] WIP [ADT][NFC] SmallVector performance improvements (PR #169291)

Slava Gurevich via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 24 02:58:35 PST 2025


https://github.com/noclowns updated https://github.com/llvm/llvm-project/pull/169291

>From c8657b9df3eab519ed11c476839a3116080b0d3c Mon Sep 17 00:00:00 2001
From: Slava Gurevich <sgurevich at gmail.com>
Date: Sun, 23 Nov 2025 23:38:43 -0800
Subject: [PATCH] WIP [ADT][NFC] SmallVector performance improvements
 SmallVector performance optimizations. SmallVector is used prolifically
 throughout the code base making it a good optimization target.

- Use "if constexpr"(c++17)
- Batch initialize the POD types in resize() that's in hot path.

Performance benchmark:
check-llvm Testing Time delta shows ~6% improvement

Testing:
check-llvm
check-llvm-unit
---
 llvm/include/llvm/ADT/SmallVector.h | 44 +++++++++++++++++++----------
 1 file changed, 29 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h
index 51109d1f416f2..0c8955060b38a 100644
--- a/llvm/include/llvm/ADT/SmallVector.h
+++ b/llvm/include/llvm/ADT/SmallVector.h
@@ -238,7 +238,7 @@ class SmallVectorTemplateCommon
 
     bool ReferencesStorage = false;
     int64_t Index = -1;
-    if (!U::TakesParamByValue) {
+    if constexpr (!U::TakesParamByValue) {
       if (LLVM_UNLIKELY(This->isReferenceToStorage(&Elt))) {
         ReferencesStorage = true;
         Index = &Elt - This->begin();
@@ -627,11 +627,22 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T> {
     }
 
     this->reserve(N);
-    for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
-      if (ForOverwrite)
-        new (&*I) T;
-      else
-        new (&*I) T();
+
+    // Use batch init for trivial types
+    if constexpr (std::is_trivially_copyable_v<T> &&
+                  std::is_trivially_default_constructible_v<T> &&
+                  std::is_trivially_destructible_v<T>) {
+      if constexpr (!ForOverwrite)
+        std::memset(this->end(), 0, (N - this->size()) * sizeof(T));
+      // ForOverwrite: skip initialization entirely
+    } else {
+      // Non-trivial types: construct individually
+      for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
+        if constexpr (ForOverwrite)
+          new (&*I) T;
+        else
+          new (&*I) T();
+    }
     this->set_size(N);
   }
 
@@ -801,9 +812,10 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T> {
     // the reference (never happens if TakesParamByValue).
     static_assert(!TakesParamByValue || std::is_same<ArgType, T>::value,
                   "ArgType must be 'T' when taking by value!");
-    if (!TakesParamByValue && this->isReferenceToRange(EltPtr, I, this->end()))
-      ++EltPtr;
-
+    if constexpr (!TakesParamByValue) {
+      if (this->isReferenceToRange(EltPtr, I, this->end()))
+        ++EltPtr;
+    }
     *I = ::std::forward<ArgType>(*EltPtr);
     return I;
   }
@@ -849,9 +861,10 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T> {
 
       // If we just moved the element we're inserting, be sure to update
       // the reference (never happens if TakesParamByValue).
-      if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
-        EltPtr += NumToInsert;
-
+      if constexpr (!TakesParamByValue) {
+        if (I <= EltPtr && EltPtr < this->end())
+          EltPtr += NumToInsert;
+      }
       std::fill_n(I, NumToInsert, *EltPtr);
       return I;
     }
@@ -867,9 +880,10 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T> {
 
     // If we just moved the element we're inserting, be sure to update
     // the reference (never happens if TakesParamByValue).
-    if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
-      EltPtr += NumToInsert;
-
+    if constexpr (!TakesParamByValue) {
+      if (I <= EltPtr && EltPtr < this->end())
+        EltPtr += NumToInsert;
+    }
     // Replace the overwritten part.
     std::fill_n(I, NumOverwritten, *EltPtr);
 



More information about the llvm-commits mailing list