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