simde-align.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /* Alignment
  2. * Created by Evan Nemerson <[email protected]>
  3. *
  4. * To the extent possible under law, the authors have waived all
  5. * copyright and related or neighboring rights to this code. For
  6. * details, see the Creative Commons Zero 1.0 Universal license at
  7. * <https://creativecommons.org/publicdomain/zero/1.0/>
  8. *
  9. * SPDX-License-Identifier: CC0-1.0
  10. *
  11. **********************************************************************
  12. *
  13. * This is portability layer which should help iron out some
  14. * differences across various compilers, as well as various verisons of
  15. * C and C++.
  16. *
  17. * It was originally developed for SIMD Everywhere
  18. * (<https://github.com/simd-everywhere/simde>), but since its only
  19. * dependency is Hedley (<https://nemequ.github.io/hedley>, also CC0)
  20. * it can easily be used in other projects, so please feel free to do
  21. * so.
  22. *
  23. * If you do use this in your project, please keep a link to SIMDe in
  24. * your code to remind you where to report any bugs and/or check for
  25. * updated versions.
  26. *
  27. * # API Overview
  28. *
  29. * The API has several parts, and most macros have a few variations.
  30. * There are APIs for declaring aligned fields/variables, optimization
  31. * hints, and run-time alignment checks.
  32. *
  33. * Briefly, macros ending with "_TO" take numeric values and are great
  34. * when you know the value you would like to use. Macros ending with
  35. * "_LIKE", on the other hand, accept a type and are used when you want
  36. * to use the alignment of a type instead of hardcoding a value.
  37. *
  38. * Documentation for each section of the API is inline.
  39. *
  40. * True to form, MSVC is the main problem and imposes several
  41. * limitations on the effectiveness of the APIs. Detailed descriptions
  42. * of the limitations of each macro are inline, but in general:
  43. *
  44. * * On C11+ or C++11+ code written using this API will work. The
  45. * ASSUME macros may or may not generate a hint to the compiler, but
  46. * that is only an optimization issue and will not actually cause
  47. * failures.
  48. * * If you're using pretty much any compiler other than MSVC,
  49. * everything should basically work as well as in C11/C++11.
  50. */
  51. #if !defined(SIMDE_ALIGN_H)
  52. #define SIMDE_ALIGN_H
  53. #include "hedley.h"
  54. /* I know this seems a little silly, but some non-hosted compilers
  55. * don't have stddef.h, so we try to accomodate them. */
  56. #if !defined(SIMDE_ALIGN_SIZE_T_)
  57. #if defined(__SIZE_TYPE__)
  58. #define SIMDE_ALIGN_SIZE_T_ __SIZE_TYPE__
  59. #elif defined(__SIZE_T_TYPE__)
  60. #define SIMDE_ALIGN_SIZE_T_ __SIZE_TYPE__
  61. #elif defined(__cplusplus)
  62. #include <cstddef>
  63. #define SIMDE_ALIGN_SIZE_T_ size_t
  64. #else
  65. #include <stddef.h>
  66. #define SIMDE_ALIGN_SIZE_T_ size_t
  67. #endif
  68. #endif
  69. #if !defined(SIMDE_ALIGN_INTPTR_T_)
  70. #if defined(__INTPTR_TYPE__)
  71. #define SIMDE_ALIGN_INTPTR_T_ __INTPTR_TYPE__
  72. #elif defined(__PTRDIFF_TYPE__)
  73. #define SIMDE_ALIGN_INTPTR_T_ __PTRDIFF_TYPE__
  74. #elif defined(__PTRDIFF_T_TYPE__)
  75. #define SIMDE_ALIGN_INTPTR_T_ __PTRDIFF_T_TYPE__
  76. #elif defined(__cplusplus)
  77. #include <cstddef>
  78. #define SIMDE_ALIGN_INTPTR_T_ ptrdiff_t
  79. #else
  80. #include <stddef.h>
  81. #define SIMDE_ALIGN_INTPTR_T_ ptrdiff_t
  82. #endif
  83. #endif
  84. #if defined(SIMDE_ALIGN_DEBUG)
  85. #if defined(__cplusplus)
  86. #include <cstdio>
  87. #else
  88. #include <stdio.h>
  89. #endif
  90. #endif
  91. /* SIMDE_ALIGN_OF(Type)
  92. *
  93. * The SIMDE_ALIGN_OF macro works like alignof, or _Alignof, or
  94. * __alignof, or __alignof__, or __ALIGNOF__, depending on the compiler.
  95. * It isn't defined everywhere (only when the compiler has some alignof-
  96. * like feature we can use to implement it), but it should work in most
  97. * modern compilers, as well as C11 and C++11.
  98. *
  99. * If we can't find an implementation for SIMDE_ALIGN_OF then the macro
  100. * will not be defined, so if you can handle that situation sensibly
  101. * you may need to sprinkle some ifdefs into your code.
  102. */
  103. #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
  104. (0 && HEDLEY_HAS_FEATURE(c_alignof))
  105. #define SIMDE_ALIGN_OF(Type) _Alignof(Type)
  106. #elif (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
  107. (0 && HEDLEY_HAS_FEATURE(cxx_alignof))
  108. #define SIMDE_ALIGN_OF(Type) alignof(Type)
  109. #elif HEDLEY_GCC_VERSION_CHECK(2, 95, 0) || \
  110. HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \
  111. HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \
  112. HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) || \
  113. HEDLEY_TINYC_VERSION_CHECK(0, 9, 24) || \
  114. HEDLEY_PGI_VERSION_CHECK(19, 10, 0) || \
  115. HEDLEY_CRAY_VERSION_CHECK(10, 0, 0) || \
  116. HEDLEY_TI_ARMCL_VERSION_CHECK(16, 9, 0) || \
  117. HEDLEY_TI_CL2000_VERSION_CHECK(16, 9, 0) || \
  118. HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) || \
  119. HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
  120. HEDLEY_TI_CL430_VERSION_CHECK(16, 9, 0) || \
  121. HEDLEY_TI_CLPRU_VERSION_CHECK(2, 3, 2) || defined(__IBM__ALIGNOF__) || \
  122. defined(__clang__)
  123. #define SIMDE_ALIGN_OF(Type) __alignof__(Type)
  124. #elif HEDLEY_IAR_VERSION_CHECK(8, 40, 0)
  125. #define SIMDE_ALIGN_OF(Type) __ALIGNOF__(Type)
  126. #elif HEDLEY_MSVC_VERSION_CHECK(19, 0, 0)
  127. /* Probably goes back much further, but MS takes down their old docs.
  128. * If you can verify that this works in earlier versions please let
  129. * me know! */
  130. #define SIMDE_ALIGN_OF(Type) __alignof(Type)
  131. #endif
  132. /* SIMDE_ALIGN_MAXIMUM:
  133. *
  134. * This is the maximum alignment that the compiler supports. You can
  135. * define the value prior to including SIMDe if necessary, but in that
  136. * case *please* submit an issue so we can add the platform to the
  137. * detection code.
  138. *
  139. * Most compilers are okay with types which are aligned beyond what
  140. * they think is the maximum, as long as the alignment is a power
  141. * of two. MSVC is the exception (of course), so we need to cap the
  142. * alignment requests at values that the implementation supports.
  143. *
  144. * XL C/C++ will accept values larger than 16 (which is the alignment
  145. * of an AltiVec vector), but will not reliably align to the larger
  146. * value, so so we cap the value at 16 there.
  147. *
  148. * If the compiler accepts any power-of-two value within reason then
  149. * this macro should be left undefined, and the SIMDE_ALIGN_CAP
  150. * macro will just return the value passed to it. */
  151. #if !defined(SIMDE_ALIGN_MAXIMUM)
  152. #if defined(HEDLEY_MSVC_VERSION)
  153. #if defined(_M_IX86) || defined(_M_AMD64)
  154. #if HEDLEY_MSVC_VERSION_CHECK(19, 14, 0)
  155. #define SIMDE_ALIGN_PLATFORM_MAXIMUM 64
  156. #elif HEDLEY_MSVC_VERSION_CHECK(16, 0, 0)
  157. /* VS 2010 is really a guess based on Wikipedia; if anyone can
  158. * test with old VS versions I'd really appreciate it. */
  159. #define SIMDE_ALIGN_PLATFORM_MAXIMUM 32
  160. #else
  161. #define SIMDE_ALIGN_PLATFORM_MAXIMUM 16
  162. #endif
  163. #elif defined(_M_ARM) || defined(_M_ARM64)
  164. #define SIMDE_ALIGN_PLATFORM_MAXIMUM 8
  165. #endif
  166. #elif defined(HEDLEY_IBM_VERSION)
  167. #define SIMDE_ALIGN_PLATFORM_MAXIMUM 16
  168. #endif
  169. #endif
  170. /* You can mostly ignore these; they're intended for internal use.
  171. * If you do need to use them please let me know; if they fulfill
  172. * a common use case I'll probably drop the trailing underscore
  173. * and make them part of the public API. */
  174. #if defined(SIMDE_ALIGN_PLATFORM_MAXIMUM)
  175. #if SIMDE_ALIGN_PLATFORM_MAXIMUM >= 64
  176. #define SIMDE_ALIGN_64_ 64
  177. #define SIMDE_ALIGN_32_ 32
  178. #define SIMDE_ALIGN_16_ 16
  179. #define SIMDE_ALIGN_8_ 8
  180. #elif SIMDE_ALIGN_PLATFORM_MAXIMUM >= 32
  181. #define SIMDE_ALIGN_64_ 32
  182. #define SIMDE_ALIGN_32_ 32
  183. #define SIMDE_ALIGN_16_ 16
  184. #define SIMDE_ALIGN_8_ 8
  185. #elif SIMDE_ALIGN_PLATFORM_MAXIMUM >= 16
  186. #define SIMDE_ALIGN_64_ 16
  187. #define SIMDE_ALIGN_32_ 16
  188. #define SIMDE_ALIGN_16_ 16
  189. #define SIMDE_ALIGN_8_ 8
  190. #elif SIMDE_ALIGN_PLATFORM_MAXIMUM >= 8
  191. #define SIMDE_ALIGN_64_ 8
  192. #define SIMDE_ALIGN_32_ 8
  193. #define SIMDE_ALIGN_16_ 8
  194. #define SIMDE_ALIGN_8_ 8
  195. #else
  196. #error Max alignment expected to be >= 8
  197. #endif
  198. #else
  199. #define SIMDE_ALIGN_64_ 64
  200. #define SIMDE_ALIGN_32_ 32
  201. #define SIMDE_ALIGN_16_ 16
  202. #define SIMDE_ALIGN_8_ 8
  203. #endif
  204. /**
  205. * SIMDE_ALIGN_CAP(Alignment)
  206. *
  207. * Returns the minimum of Alignment or SIMDE_ALIGN_MAXIMUM.
  208. */
  209. #if defined(SIMDE_ALIGN_MAXIMUM)
  210. #define SIMDE_ALIGN_CAP(Alignment) \
  211. (((Alignment) < (SIMDE_ALIGN_PLATFORM_MAXIMUM)) \
  212. ? (Alignment) \
  213. : (SIMDE_ALIGN_PLATFORM_MAXIMUM))
  214. #else
  215. #define SIMDE_ALIGN_CAP(Alignment) (Alignment)
  216. #endif
  217. /* SIMDE_ALIGN_TO(Alignment)
  218. *
  219. * SIMDE_ALIGN_TO is used to declare types or variables. It basically
  220. * maps to the align attribute in most compilers, the align declspec
  221. * in MSVC, or _Alignas/alignas in C11/C++11.
  222. *
  223. * Example:
  224. *
  225. * struct i32x4 {
  226. * SIMDE_ALIGN_TO(16) int32_t values[4];
  227. * }
  228. *
  229. * Limitations:
  230. *
  231. * MSVC requires that the Alignment parameter be numeric; you can't do
  232. * something like `SIMDE_ALIGN_TO(SIMDE_ALIGN_OF(int))`. This is
  233. * unfortunate because that's really how the LIKE macros are
  234. * implemented, and I am not aware of a way to get anything like this
  235. * to work without using the C11/C++11 keywords.
  236. *
  237. * It also means that we can't use SIMDE_ALIGN_CAP to limit the
  238. * alignment to the value specified, which MSVC also requires, so on
  239. * MSVC you should use the `SIMDE_ALIGN_TO_8/16/32/64` macros instead.
  240. * They work like `SIMDE_ALIGN_TO(SIMDE_ALIGN_CAP(Alignment))` would,
  241. * but should be safe to use on MSVC.
  242. *
  243. * All this is to say that, if you want your code to work on MSVC, you
  244. * should use the SIMDE_ALIGN_TO_8/16/32/64 macros below instead of
  245. * SIMDE_ALIGN_TO(8/16/32/64).
  246. */
  247. #if HEDLEY_HAS_ATTRIBUTE(aligned) || HEDLEY_GCC_VERSION_CHECK(2, 95, 0) || \
  248. HEDLEY_CRAY_VERSION_CHECK(8, 4, 0) || \
  249. HEDLEY_IBM_VERSION_CHECK(11, 1, 0) || \
  250. HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \
  251. HEDLEY_PGI_VERSION_CHECK(19, 4, 0) || \
  252. HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \
  253. HEDLEY_TINYC_VERSION_CHECK(0, 9, 24) || \
  254. HEDLEY_TI_ARMCL_VERSION_CHECK(16, 9, 0) || \
  255. HEDLEY_TI_CL2000_VERSION_CHECK(16, 9, 0) || \
  256. HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) || \
  257. HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
  258. HEDLEY_TI_CL430_VERSION_CHECK(16, 9, 0) || \
  259. HEDLEY_TI_CLPRU_VERSION_CHECK(2, 3, 2)
  260. #define SIMDE_ALIGN_TO(Alignment) \
  261. __attribute__((__aligned__(SIMDE_ALIGN_CAP(Alignment))))
  262. #elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L))
  263. #define SIMDE_ALIGN_TO(Alignment) _Alignas(SIMDE_ALIGN_CAP(Alignment))
  264. #elif (defined(__cplusplus) && (__cplusplus >= 201103L))
  265. #define SIMDE_ALIGN_TO(Alignment) alignas(SIMDE_ALIGN_CAP(Alignment))
  266. #elif defined(HEDLEY_MSVC_VERSION)
  267. #define SIMDE_ALIGN_TO(Alignment) __declspec(align(Alignment))
  268. /* Unfortunately MSVC can't handle __declspec(align(__alignof(Type)));
  269. * the alignment passed to the declspec has to be an integer. */
  270. #define SIMDE_ALIGN_OF_UNUSABLE_FOR_LIKE
  271. #endif
  272. #define SIMDE_ALIGN_TO_64 SIMDE_ALIGN_TO(SIMDE_ALIGN_64_)
  273. #define SIMDE_ALIGN_TO_32 SIMDE_ALIGN_TO(SIMDE_ALIGN_32_)
  274. #define SIMDE_ALIGN_TO_16 SIMDE_ALIGN_TO(SIMDE_ALIGN_16_)
  275. #define SIMDE_ALIGN_TO_8 SIMDE_ALIGN_TO(SIMDE_ALIGN_8_)
  276. /* SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment)
  277. *
  278. * SIMDE_ALIGN_ASSUME_TO is semantically similar to C++20's
  279. * std::assume_aligned, or __builtin_assume_aligned. It tells the
  280. * compiler to assume that the provided pointer is aligned to an
  281. * `Alignment`-byte boundary.
  282. *
  283. * If you define SIMDE_ALIGN_DEBUG prior to including this header then
  284. * SIMDE_ALIGN_ASSUME_TO will turn into a runtime check. We don't
  285. * integrate with NDEBUG in this header, but it may be a good idea to
  286. * put something like this in your code:
  287. *
  288. * #if !defined(NDEBUG)
  289. * #define SIMDE_ALIGN_DEBUG
  290. * #endif
  291. * #include <.../simde-align.h>
  292. */
  293. #if HEDLEY_HAS_BUILTIN(__builtin_assume_aligned) || \
  294. HEDLEY_GCC_VERSION_CHECK(4, 7, 0)
  295. #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) \
  296. HEDLEY_REINTERPRET_CAST( \
  297. __typeof__(Pointer), \
  298. __builtin_assume_aligned( \
  299. HEDLEY_CONST_CAST( \
  300. void *, HEDLEY_REINTERPRET_CAST(const void *, \
  301. Pointer)), \
  302. Alignment))
  303. #elif HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
  304. #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) \
  305. (__extension__({ \
  306. __typeof__(v) simde_assume_aligned_t_ = (Pointer); \
  307. __assume_aligned(simde_assume_aligned_t_, Alignment); \
  308. simde_assume_aligned_t_; \
  309. }))
  310. #elif defined(__cplusplus) && (__cplusplus > 201703L)
  311. #include <memory>
  312. #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) \
  313. std::assume_aligned<Alignment>(Pointer)
  314. #else
  315. #if defined(__cplusplus)
  316. template<typename T>
  317. HEDLEY_ALWAYS_INLINE static T *
  318. simde_align_assume_to_unchecked(T *ptr, const size_t alignment)
  319. #else
  320. HEDLEY_ALWAYS_INLINE static void *
  321. simde_align_assume_to_unchecked(void *ptr, const size_t alignment)
  322. #endif
  323. {
  324. HEDLEY_ASSUME((HEDLEY_REINTERPRET_CAST(size_t, (ptr)) %
  325. SIMDE_ALIGN_CAP(alignment)) == 0);
  326. return ptr;
  327. }
  328. #if defined(__cplusplus)
  329. #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) \
  330. simde_align_assume_to_unchecked((Pointer), (Alignment))
  331. #else
  332. #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) \
  333. simde_align_assume_to_unchecked( \
  334. HEDLEY_CONST_CAST(void *, HEDLEY_REINTERPRET_CAST( \
  335. const void *, Pointer)), \
  336. (Alignment))
  337. #endif
  338. #endif
  339. #if !defined(SIMDE_ALIGN_DEBUG)
  340. #define SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment) \
  341. SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment)
  342. #else
  343. #include <stdio.h>
  344. #if defined(__cplusplus)
  345. template<typename T>
  346. static HEDLEY_ALWAYS_INLINE T *
  347. simde_align_assume_to_checked_uncapped(T *ptr, const size_t alignment,
  348. const char *file, int line,
  349. const char *ptrname)
  350. #else
  351. static HEDLEY_ALWAYS_INLINE void *
  352. simde_align_assume_to_checked_uncapped(void *ptr, const size_t alignment,
  353. const char *file, int line,
  354. const char *ptrname)
  355. #endif
  356. {
  357. if (HEDLEY_UNLIKELY(
  358. (HEDLEY_REINTERPRET_CAST(SIMDE_ALIGN_INTPTR_T_, (ptr)) %
  359. HEDLEY_STATIC_CAST(SIMDE_ALIGN_INTPTR_T_,
  360. SIMDE_ALIGN_CAP(alignment))) != 0)) {
  361. fprintf(stderr,
  362. "%s:%d: alignment check failed for `%s' (%p %% %u == %u)\n",
  363. file, line, ptrname,
  364. HEDLEY_REINTERPRET_CAST(const void *, ptr),
  365. HEDLEY_STATIC_CAST(unsigned int,
  366. SIMDE_ALIGN_CAP(alignment)),
  367. HEDLEY_STATIC_CAST(
  368. unsigned int,
  369. HEDLEY_REINTERPRET_CAST(SIMDE_ALIGN_INTPTR_T_,
  370. (ptr)) %
  371. HEDLEY_STATIC_CAST(
  372. SIMDE_ALIGN_INTPTR_T_,
  373. SIMDE_ALIGN_CAP(alignment))));
  374. }
  375. return ptr;
  376. }
  377. #if defined(__cplusplus)
  378. #define SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment) \
  379. simde_align_assume_to_checked_uncapped((Pointer), (Alignment), \
  380. __FILE__, __LINE__, #Pointer)
  381. #else
  382. #define SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment) \
  383. simde_align_assume_to_checked_uncapped( \
  384. HEDLEY_CONST_CAST(void *, HEDLEY_REINTERPRET_CAST( \
  385. const void *, Pointer)), \
  386. (Alignment), __FILE__, __LINE__, #Pointer)
  387. #endif
  388. #endif
  389. /* SIMDE_ALIGN_LIKE(Type)
  390. * SIMDE_ALIGN_LIKE_#(Type)
  391. *
  392. * The SIMDE_ALIGN_LIKE macros are similar to the SIMDE_ALIGN_TO macros
  393. * except instead of an integer they take a type; basically, it's just
  394. * a more convenient way to do something like:
  395. *
  396. * SIMDE_ALIGN_TO(SIMDE_ALIGN_OF(Type))
  397. *
  398. * The versions with a numeric suffix will fall back on using a numeric
  399. * value in the event we can't use SIMDE_ALIGN_OF(Type). This is
  400. * mainly for MSVC, where __declspec(align()) can't handle anything
  401. * other than hard-coded numeric values.
  402. */
  403. #if defined(SIMDE_ALIGN_OF) && defined(SIMDE_ALIGN_TO) && \
  404. !defined(SIMDE_ALIGN_OF_UNUSABLE_FOR_LIKE)
  405. #define SIMDE_ALIGN_LIKE(Type) SIMDE_ALIGN_TO(SIMDE_ALIGN_OF(Type))
  406. #define SIMDE_ALIGN_LIKE_64(Type) SIMDE_ALIGN_LIKE(Type)
  407. #define SIMDE_ALIGN_LIKE_32(Type) SIMDE_ALIGN_LIKE(Type)
  408. #define SIMDE_ALIGN_LIKE_16(Type) SIMDE_ALIGN_LIKE(Type)
  409. #define SIMDE_ALIGN_LIKE_8(Type) SIMDE_ALIGN_LIKE(Type)
  410. #else
  411. #define SIMDE_ALIGN_LIKE_64(Type) SIMDE_ALIGN_TO_64
  412. #define SIMDE_ALIGN_LIKE_32(Type) SIMDE_ALIGN_TO_32
  413. #define SIMDE_ALIGN_LIKE_16(Type) SIMDE_ALIGN_TO_16
  414. #define SIMDE_ALIGN_LIKE_8(Type) SIMDE_ALIGN_TO_8
  415. #endif
  416. /* SIMDE_ALIGN_ASSUME_LIKE(Pointer, Type)
  417. *
  418. * Tihs is similar to SIMDE_ALIGN_ASSUME_TO, except that it takes a
  419. * type instead of a numeric value. */
  420. #if defined(SIMDE_ALIGN_OF) && defined(SIMDE_ALIGN_ASSUME_TO)
  421. #define SIMDE_ALIGN_ASSUME_LIKE(Pointer, Type) \
  422. SIMDE_ALIGN_ASSUME_TO(Pointer, SIMDE_ALIGN_OF(Type))
  423. #endif
  424. /* SIMDE_ALIGN_CAST(Type, Pointer)
  425. *
  426. * SIMDE_ALIGN_CAST is like C++'s reinterpret_cast, but it will try
  427. * to silence warnings that some compilers may produce if you try
  428. * to assign to a type with increased alignment requirements.
  429. *
  430. * Note that it does *not* actually attempt to tell the compiler that
  431. * the pointer is aligned like the destination should be; that's the
  432. * job of the next macro. This macro is necessary for stupid APIs
  433. * like _mm_loadu_si128 where the input is a __m128i* but the function
  434. * is specifically for data which isn't necessarily aligned to
  435. * _Alignof(__m128i).
  436. */
  437. #if HEDLEY_HAS_WARNING("-Wcast-align") || defined(__clang__) || \
  438. HEDLEY_GCC_VERSION_CHECK(3, 4, 0)
  439. #define SIMDE_ALIGN_CAST(Type, Pointer) \
  440. (__extension__({ \
  441. HEDLEY_DIAGNOSTIC_PUSH \
  442. _Pragma("GCC diagnostic ignored \"-Wcast-align\"") \
  443. Type simde_r_ = \
  444. HEDLEY_REINTERPRET_CAST(Type, Pointer); \
  445. HEDLEY_DIAGNOSTIC_POP \
  446. simde_r_; \
  447. }))
  448. #else
  449. #define SIMDE_ALIGN_CAST(Type, Pointer) HEDLEY_REINTERPRET_CAST(Type, Pointer)
  450. #endif
  451. /* SIMDE_ALIGN_ASSUME_CAST(Type, Pointer)
  452. *
  453. * This is sort of like a combination of a reinterpret_cast and a
  454. * SIMDE_ALIGN_ASSUME_LIKE. It uses SIMDE_ALIGN_ASSUME_LIKE to tell
  455. * the compiler that the pointer is aligned like the specified type
  456. * and casts the pointer to the specified type while suppressing any
  457. * warnings from the compiler about casting to a type with greater
  458. * alignment requirements.
  459. */
  460. #define SIMDE_ALIGN_ASSUME_CAST(Type, Pointer) \
  461. SIMDE_ALIGN_ASSUME_LIKE(SIMDE_ALIGN_CAST(Type, Pointer), Type)
  462. #endif /* !defined(SIMDE_ALIGN_H) */