[PATCH] D115383: ADT: Add SmallVectorImpl::truncate() to replace uses of set_size()

Duncan P. N. Exon Smith via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 8 12:53:47 PST 2021


dexonsmith created this revision.
dexonsmith added a reviewer: dblaikie.
dexonsmith requested review of this revision.
Herald added a project: LLVM.

Add `SmallVectorImpl::truncate()`, a variant of `resize()` that cannot
increase the size.

- Compared to `resize()`, this has no code path for growing the allocation and can be better optimized.
- Compared to `set_size()`, this formally calls destructors, and does not skip any constructors.
- Compared to `pop_back_n()`, this takes the new desired size, which in many contexts is more intuitive than the number of elements to remove.

The immediate motivation is to pair this with `resize_for_overwrite()`
to remove uses of `set_size()`, which can then be made private.

See also: https://reviews.llvm.org/D115380


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D115383

Files:
  llvm/include/llvm/ADT/SmallVector.h
  llvm/unittests/ADT/SmallVectorTest.cpp


Index: llvm/unittests/ADT/SmallVectorTest.cpp
===================================================================
--- llvm/unittests/ADT/SmallVectorTest.cpp
+++ llvm/unittests/ADT/SmallVectorTest.cpp
@@ -309,6 +309,32 @@
   EXPECT_EQ(5, Constructable::getNumDestructorCalls());
 }
 
+// Truncate test.
+TYPED_TEST(SmallVectorTest, TruncateTest) {
+  SCOPED_TRACE("TruncateTest");
+
+  this->theVector.reserve(3);
+  this->makeSequence(this->theVector, 1, 3);
+  this->theVector.truncate(1);
+
+  this->assertValuesInOrder(this->theVector, 1u, 1);
+  EXPECT_EQ(6, Constructable::getNumConstructorCalls());
+  EXPECT_EQ(5, Constructable::getNumDestructorCalls());
+
+#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
+  EXPECT_DEATH(this->theVector.truncate(2), "Cannot increase size");
+#endif
+  this->theVector.truncate(1);
+  this->assertValuesInOrder(this->theVector, 1u, 1);
+  EXPECT_EQ(6, Constructable::getNumConstructorCalls());
+  EXPECT_EQ(5, Constructable::getNumDestructorCalls());
+
+  this->theVector.truncate(0);
+  this->assertEmpty(this->theVector);
+  EXPECT_EQ(6, Constructable::getNumConstructorCalls());
+  EXPECT_EQ(6, Constructable::getNumDestructorCalls());
+}
+
 // Resize bigger test.
 TYPED_TEST(SmallVectorTest, ResizeGrowTest) {
   SCOPED_TRACE("ResizeGrowTest");
Index: llvm/include/llvm/ADT/SmallVector.h
===================================================================
--- llvm/include/llvm/ADT/SmallVector.h
+++ llvm/include/llvm/ADT/SmallVector.h
@@ -593,7 +593,7 @@
       return;
 
     if (N < this->size()) {
-      this->pop_back_n(this->size() - N);
+      this->truncate(N);
       return;
     }
 
@@ -612,12 +612,19 @@
   /// Like resize, but \ref T is POD, the new values won't be initialized.
   void resize_for_overwrite(size_type N) { resizeImpl<true>(N); }
 
+  /// Like resize, but requires that \p N is less than \a size().
+  void truncate(size_type N) {
+    assert(this->size() >= N && "Cannot increase size with truncate");
+    this->destroy_range(this->begin() + N, this->end());
+    this->set_size(N);
+  }
+
   void resize(size_type N, ValueParamT NV) {
     if (N == this->size())
       return;
 
     if (N < this->size()) {
-      this->pop_back_n(this->size() - N);
+      this->truncate(N);
       return;
     }
 
@@ -632,8 +639,7 @@
 
   void pop_back_n(size_type NumItems) {
     assert(this->size() >= NumItems);
-    this->destroy_range(this->end() - NumItems, this->end());
-    this->set_size(this->size() - NumItems);
+    truncate(this->size() - NumItems);
   }
 
   LLVM_NODISCARD T pop_back_val() {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D115383.392893.patch
Type: text/x-patch
Size: 2573 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211208/7d5c0760/attachment.bin>


More information about the llvm-commits mailing list