diff options
author | 2019-02-24 13:58:47 +0100 | |
---|---|---|
committer | 2019-02-24 18:45:16 +0100 | |
commit | 0e07f9ac34ec82066792fb9fdaaf04546b582fab (patch) | |
tree | d860998701e88434732d228681d78e42c96775fa /src/lib/netlist/plib/palloc.h | |
parent | a7a81862837cf8df3bc19c601b9d06ffb16262c9 (diff) |
netlist: more alignment related refactoring. (nw)
Diffstat (limited to 'src/lib/netlist/plib/palloc.h')
-rw-r--r-- | src/lib/netlist/plib/palloc.h | 124 |
1 files changed, 84 insertions, 40 deletions
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index 44f3bdb395e..c7aad9372d3 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -28,19 +28,21 @@ namespace plib { // Memory allocation //============================================================ -#if (USE_ALIGNED_OPTIMIZATIONS) + static constexpr bool is_pow2(std::size_t v) noexcept { return !(v & (v-1)); } + +#if (USE_ALIGNED_ALLOCATION) static inline void *paligned_alloc( size_t alignment, size_t size ) { #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) return _aligned_malloc(size, alignment); #elif defined(__APPLE__) - void* p; - if (::posix_memalign(&p, alignment, size) != 0) { - p = nullptr; - } - return p; + void* p; + if (::posix_memalign(&p, alignment, size) != 0) { + p = nullptr; + } + return p; #else - return aligned_alloc(alignment, size); + return aligned_alloc(alignment, size); #endif } @@ -79,19 +81,35 @@ namespace plib { { ::operator delete(ptr); } +#endif template <typename T, std::size_t ALIGN> inline C14CONSTEXPR T *assume_aligned_ptr(T *p) noexcept { + static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)"); + static_assert(is_pow2(ALIGN), "Alignment must be a power of 2"); + //auto t = reinterpret_cast<std::uintptr_t>(p); + //if (t & (ALIGN-1)) + // printf("alignment error!"); +#if (USE_ALIGNED_HINTS) + return reinterpret_cast<T *>(__builtin_assume_aligned(p, ALIGN)); +#else return p; +#endif } template <typename T, std::size_t ALIGN> inline C14CONSTEXPR const T *assume_aligned_ptr(const T *p) noexcept { + static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)"); + static_assert(is_pow2(ALIGN), "Alignment must be a power of 2"); +#if (USE_ALIGNED_HINTS) + return reinterpret_cast<const T *>(__builtin_assume_aligned(p, ALIGN)); +#else return p; - } #endif + } + template<typename T, typename... Args> inline T *pnew(Args&&... args) { @@ -124,8 +142,8 @@ namespace plib { constexpr pdefault_deleter() noexcept = default; template<typename U, typename = typename - std::enable_if<std::is_convertible< U*, T*>::value>::type> - pdefault_deleter(const pdefault_deleter<U>&) noexcept { } + std::enable_if<std::is_convertible< U*, T*>::value>::type> + pdefault_deleter(const pdefault_deleter<U>&) noexcept { } void operator()(T *p) const { @@ -245,33 +263,38 @@ namespace plib { return std::move(a); } + //============================================================ + // Aligned allocator for use with containers + //============================================================ + template <class T, std::size_t ALIGN = alignof(T)> class aligned_allocator { public: - using value_type = T; + using value_type = T; + static constexpr const std::size_t align_size = (USE_ALIGNED_ALLOCATION) ? ALIGN : alignof(std::max_align_t); - static_assert(ALIGN >= alignof(T) && (ALIGN % alignof(T)) == 0, - "ALIGN must be greater than alignof(T) and a multiple"); + static_assert(align_size >= alignof(T) && (align_size % alignof(T)) == 0, + "ALIGN must be greater than alignof(T) and a multiple"); - aligned_allocator() noexcept = default; - ~aligned_allocator() noexcept = default; + aligned_allocator() noexcept = default; + ~aligned_allocator() noexcept = default; - aligned_allocator(const aligned_allocator&) noexcept = default; - aligned_allocator& operator=(const aligned_allocator&) noexcept = delete; + aligned_allocator(const aligned_allocator&) noexcept = default; + aligned_allocator& operator=(const aligned_allocator&) noexcept = delete; - aligned_allocator(aligned_allocator&&) noexcept = default; - aligned_allocator& operator=(aligned_allocator&&) = delete; + aligned_allocator(aligned_allocator&&) noexcept = default; + aligned_allocator& operator=(aligned_allocator&&) = delete; - template <class U> - aligned_allocator(const aligned_allocator<U, ALIGN>& rhs) noexcept - { - unused_var(rhs); - } + template <class U> + aligned_allocator(const aligned_allocator<U, ALIGN>& rhs) noexcept + { + unused_var(rhs); + } - template <class U> struct rebind + template <class U> struct rebind { - using other = aligned_allocator<U, ALIGN>; + using other = aligned_allocator<U, ALIGN>; }; T* allocate(std::size_t n) @@ -306,12 +329,38 @@ namespace plib { return !(lhs == rhs); } - // FIXME: needs to be somewhere else -#if 0 - template <class T, std::size_t ALIGN = alignof(T)> - using aligned_vector = std::vector<T, aligned_allocator<T, alignof(T)>>; - //using aligned_vector = std::vector<T, aligned_allocator<T, ALIGN>>; -#else + //============================================================ + // traits to determine alignment size and stride size + // from types supporting alignment + //============================================================ + + PDEFINE_HAS_MEMBER(has_align, align_size); + + template <typename T, typename X = void> + struct align_traits + { + static constexpr const std::size_t align_size = alignof(std::max_align_t); + static constexpr const std::size_t stride_size = + (sizeof(T) % align_size == 0 ? 1 //T is a multiple of align_size + : (align_size % sizeof(T) != 0 ? align_size // align_size is not a multiple of T + : align_size / sizeof(T))); + }; + + template <typename T> + struct align_traits<T, typename std::enable_if<has_align<T>::value, void>::type> + { + static constexpr const std::size_t align_size = T::align_size; + static constexpr const std::size_t stride_size = + (sizeof(T) % align_size == 0 ? 1 //T is a multiple of align_size + : (align_size % sizeof(T) != 0 ? align_size // align_size is not a multiple of T + : align_size / sizeof(T))); + }; + + //============================================================ + // Aligned vector + //============================================================ + + // FIXME: needs a separate file template <class T, std::size_t ALIGN = alignof(T)> class aligned_vector : public std::vector<T, aligned_allocator<T, ALIGN>> { @@ -326,13 +375,13 @@ namespace plib { using base::base; - reference operator[](size_type i) noexcept + C14CONSTEXPR reference operator[](size_type i) noexcept { - return assume_aligned_ptr<T, ALIGN>(this->data())[i]; + return assume_aligned_ptr<T, ALIGN>(&((*this)[0]))[i]; } constexpr const_reference operator[](size_type i) const noexcept { - return assume_aligned_ptr<T, ALIGN>(this->data())[i]; + return assume_aligned_ptr<T, ALIGN>(&((*this)[0]))[i]; } pointer data() noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); } @@ -340,11 +389,6 @@ namespace plib { }; - -#endif - - - } // namespace plib #endif /* PALLOC_H_ */ |