[libcxx-commits] [libcxx] eac23a5 - [libc++] Add assumption for align of begin and end pointers of vector. (#108961)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jan 16 07:57:06 PST 2025


Author: Florian Hahn
Date: 2025-01-16T10:57:01-05:00
New Revision: eac23a5b971362cda3c646e018b9f26d0bc1ff3a

URL: https://github.com/llvm/llvm-project/commit/eac23a5b971362cda3c646e018b9f26d0bc1ff3a
DIFF: https://github.com/llvm/llvm-project/commit/eac23a5b971362cda3c646e018b9f26d0bc1ff3a.diff

LOG: [libc++] Add assumption for align of begin and end pointers of vector. (#108961)

Missing information about begin and end pointers of std::vector can lead
to missed optimizations in LLVM.

This patch adds alignment assumptions at the point where the begin and
end pointers are loaded. If the pointers would not have the same
alignment, end might never get hit when incrementing begin.

See https://github.com/llvm/llvm-project/issues/101372 for a discussion
of missed range check optimizations in hardened mode.

Once https://github.com/llvm/llvm-project/pull/108958 lands, the created
`llvm.assume` calls for the alignment should be folded into the `load`
instructions, resulting in no extra instructions after InstCombine.

Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>

Added: 
    

Modified: 
    libcxx/include/__flat_map/key_value_iterator.h
    libcxx/include/__vector/vector.h

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__flat_map/key_value_iterator.h b/libcxx/include/__flat_map/key_value_iterator.h
index 06a23f34299745..3ebb653deb1973 100644
--- a/libcxx/include/__flat_map/key_value_iterator.h
+++ b/libcxx/include/__flat_map/key_value_iterator.h
@@ -15,9 +15,7 @@
 #include <__config>
 #include <__iterator/iterator_traits.h>
 #include <__memory/addressof.h>
-#include <__ranges/access.h>
 #include <__type_traits/conditional.h>
-#include <__type_traits/maybe_const.h>
 #include <__utility/move.h>
 #include <__utility/pair.h>
 
@@ -41,9 +39,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template <class _Owner, class _KeyContainer, class _MappedContainer, bool _Const>
 struct __key_value_iterator {
 private:
-  using __key_iterator _LIBCPP_NODEBUG    = ranges::iterator_t<const _KeyContainer>;
-  using __mapped_iterator _LIBCPP_NODEBUG = ranges::iterator_t<__maybe_const<_Const, _MappedContainer>>;
-  using __reference _LIBCPP_NODEBUG       = _If<_Const, typename _Owner::const_reference, typename _Owner::reference>;
+  using __key_iterator _LIBCPP_NODEBUG = typename _KeyContainer::const_iterator;
+  using __mapped_iterator _LIBCPP_NODEBUG =
+      _If<_Const, typename _MappedContainer::const_iterator, typename _MappedContainer::iterator>;
+  using __reference _LIBCPP_NODEBUG = _If<_Const, typename _Owner::const_reference, typename _Owner::reference>;
 
   struct __arrow_proxy {
     __reference __ref_;
@@ -71,8 +70,8 @@ struct __key_value_iterator {
   _LIBCPP_HIDE_FROM_ABI __key_value_iterator() = default;
 
   _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i)
-    requires _Const && convertible_to<ranges::iterator_t<_KeyContainer>, __key_iterator> &&
-                 convertible_to<ranges::iterator_t<_MappedContainer>, __mapped_iterator>
+    requires _Const && convertible_to<typename _KeyContainer::iterator, __key_iterator> &&
+                 convertible_to<typename _MappedContainer::iterator, __mapped_iterator>
       : __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {}
 
   _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter)

diff  --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 3a7ae531785968..28e9495a314a2d 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -51,6 +51,7 @@
 #include <__type_traits/is_constructible.h>
 #include <__type_traits/is_nothrow_assignable.h>
 #include <__type_traits/is_nothrow_constructible.h>
+#include <__type_traits/is_pointer.h>
 #include <__type_traits/is_same.h>
 #include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/type_identity.h>
@@ -341,13 +342,17 @@ class _LIBCPP_TEMPLATE_VIS vector {
   //
   // Iterators
   //
-  _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __make_iter(this->__begin_); }
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {
+    return __make_iter(__add_alignment_assumption(this->__begin_));
+  }
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
-    return __make_iter(this->__begin_);
+    return __make_iter(__add_alignment_assumption(this->__begin_));
+  }
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {
+    return __make_iter(__add_alignment_assumption(this->__end_));
   }
-  _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __make_iter(this->__end_); }
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT {
-    return __make_iter(this->__end_);
+    return __make_iter(__add_alignment_assumption(this->__end_));
   }
 
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT {
@@ -775,6 +780,17 @@ class _LIBCPP_TEMPLATE_VIS vector {
   }
 
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
+
+  static _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __add_alignment_assumption(pointer __p) _NOEXCEPT {
+#ifndef _LIBCPP_CXX03_LANG
+    if constexpr (is_pointer<pointer>::value) {
+      if (!__libcpp_is_constant_evaluated()) {
+        return static_cast<pointer>(__builtin_assume_aligned(__p, alignof(decltype(*__p))));
+      }
+    }
+#endif
+    return __p;
+  }
 };
 
 #if _LIBCPP_STD_VER >= 17


        


More information about the libcxx-commits mailing list