1 /* 2 * Simd Library (http://ermig1979.github.io/Simd). 3 * 4 * Copyright (c) 2011-2018 Yermalayeu Ihar. 5 * 2016-2016 Sintegrial Technologies. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 */ 25 #ifndef __SimdMemory_h__ 26 #define __SimdMemory_h__ 27 28 #include "Simd/SimdDefs.h" 29 #include "Simd/SimdMath.h" 30 31 #if defined(__GNUC__) && defined(SIMD_ALLOCATE_ERROR_MESSAGE) 32 #include <iostream> 33 #endif 34 35 namespace Simd 36 { AlignHiAny(size_t size,size_t align)37 SIMD_INLINE size_t AlignHiAny(size_t size, size_t align) 38 { 39 return (size + align - 1) / align * align; 40 } 41 AlignLoAny(size_t size,size_t align)42 SIMD_INLINE size_t AlignLoAny(size_t size, size_t align) 43 { 44 return size / align * align; 45 } 46 AlignHi(size_t size,size_t align)47 SIMD_INLINE size_t AlignHi(size_t size, size_t align) 48 { 49 return (size + align - 1) & ~(align - 1); 50 } 51 AlignHi(const void * ptr,size_t align)52 SIMD_INLINE void * AlignHi(const void * ptr, size_t align) 53 { 54 return (void *)((((size_t)ptr) + align - 1) & ~(align - 1)); 55 } 56 AlignLo(size_t size,size_t align)57 SIMD_INLINE size_t AlignLo(size_t size, size_t align) 58 { 59 return size & ~(align - 1); 60 } 61 AlignLo(const void * ptr,size_t align)62 SIMD_INLINE void * AlignLo(const void * ptr, size_t align) 63 { 64 return (void *)(((size_t)ptr) & ~(align - 1)); 65 } 66 Aligned(size_t size,size_t align)67 SIMD_INLINE bool Aligned(size_t size, size_t align) 68 { 69 return size == AlignLo(size, align); 70 } 71 Aligned(const void * ptr,size_t align)72 SIMD_INLINE bool Aligned(const void * ptr, size_t align) 73 { 74 return ptr == AlignLo(ptr, align); 75 } 76 77 SIMD_INLINE void * Allocate(size_t size, size_t align = SIMD_ALIGN) 78 { 79 #ifdef SIMD_NO_MANS_LAND 80 size += 2 * SIMD_NO_MANS_LAND; 81 #endif 82 void * ptr = NULL; 83 #if defined(_MSC_VER) 84 ptr = _aligned_malloc(size, align); 85 #elif defined(__MINGW32__) || defined(__MINGW64__) 86 ptr = __mingw_aligned_malloc(size, align); 87 #elif defined(__GNUC__) 88 align = AlignHi(align, sizeof(void *)); 89 size = AlignHi(size, align); 90 int result = ::posix_memalign(&ptr, align, size); 91 #ifdef SIMD_ALLOCATE_ERROR_MESSAGE 92 if (result != 0) 93 std::cout << "The function posix_memalign can't allocate " << size << " bytes with align " << align << " !" << std::endl << std::flush; 94 #endif 95 #ifdef SIMD_ALLOCATE_ASSERT 96 assert(result == 0); 97 #endif 98 #else 99 ptr = malloc(size); 100 #endif 101 102 #ifdef SIMD_NO_MANS_LAND 103 if (ptr) 104 ptr = (char*)ptr + SIMD_NO_MANS_LAND; 105 #endif 106 return ptr; 107 } 108 Free(void * ptr)109 SIMD_INLINE void Free(void * ptr) 110 { 111 #ifdef SIMD_NO_MANS_LAND 112 if (ptr) 113 ptr = (char*)ptr - SIMD_NO_MANS_LAND; 114 #endif 115 #if defined(_MSC_VER) 116 _aligned_free(ptr); 117 #elif defined(__MINGW32__) || defined(__MINGW64__) 118 return __mingw_aligned_free(ptr); 119 #else 120 free(ptr); 121 #endif 122 } 123 124 struct Deletable 125 { ~DeletableDeletable126 virtual ~Deletable() {} 127 }; 128 129 #ifdef SIMD_SSE_ENABLE 130 namespace Sse 131 { 132 SIMD_INLINE bool Aligned(size_t size, size_t align = sizeof(__m128)) 133 { 134 return Simd::Aligned(size, align); 135 } 136 137 SIMD_INLINE bool Aligned(const void * ptr, size_t align = sizeof(__m128)) 138 { 139 return Simd::Aligned(ptr, align); 140 } 141 } 142 #endif// SIMD_SSE_ENABLE 143 144 #ifdef SIMD_SSE2_ENABLE 145 namespace Sse2 146 { 147 using Sse::Aligned; 148 } 149 #endif// SIMD_SSE2_ENABLE 150 151 #ifdef SIMD_SSE3_ENABLE 152 namespace Sse3 153 { 154 using Sse::Aligned; 155 } 156 #endif// SIMD_SSE3_ENABLE 157 158 #ifdef SIMD_SSSE3_ENABLE 159 namespace Ssse3 160 { 161 using Sse::Aligned; 162 } 163 #endif// SIMD_SSSE3_ENABLE 164 165 #ifdef SIMD_SSE41_ENABLE 166 namespace Sse41 167 { 168 using Sse::Aligned; 169 } 170 #endif// SIMD_SSE41_ENABLE 171 172 #ifdef SIMD_SSE42_ENABLE 173 namespace Sse42 174 { 175 } 176 #endif// SIMD_SSE42_ENABLE 177 178 #ifdef SIMD_AVX_ENABLE 179 namespace Avx 180 { 181 SIMD_INLINE bool Aligned(size_t size, size_t align = sizeof(__m256)) 182 { 183 return Simd::Aligned(size, align); 184 } 185 186 SIMD_INLINE bool Aligned(const void * ptr, size_t align = sizeof(__m256)) 187 { 188 return Simd::Aligned(ptr, align); 189 } 190 } 191 #endif// SIMD_AVX_ENABLE 192 193 #ifdef SIMD_AVX2_ENABLE 194 namespace Avx2 195 { 196 using Avx::Aligned; 197 } 198 #endif// SIMD_AVX2_ENABLE 199 200 #ifdef SIMD_NEON_ENABLE 201 namespace Neon 202 { 203 SIMD_INLINE bool Aligned(size_t size, size_t align = sizeof(uint8x16_t)) 204 { 205 return Simd::Aligned(size, align); 206 } 207 208 SIMD_INLINE bool Aligned(const void * ptr, size_t align = sizeof(uint8x16_t)) 209 { 210 return Simd::Aligned(ptr, align); 211 } 212 } 213 #endif// SIMD_NEON_ENABLE 214 } 215 216 #endif//__SimdMemory_h__ 217