[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@gmail.com>
This commit is contained in:
Florian Hahn
2025-01-16 15:57:01 +00:00
committed by GitHub
parent c281b127ab
commit eac23a5b97
2 changed files with 27 additions and 12 deletions

View File

@@ -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 @@ public:
_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)

View File

@@ -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 @@ public:
//
// 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 const_iterator begin() const _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(__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 @@ private:
}
_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