T-SIMD v31.1.0
A C++ template SIMD library
Loading...
Searching...
No Matches
defs.H
1// ===========================================================================
2//
3// encapsulates compiler- and architecture-specific definitions and constructs
4//
5// This source code file is part of the following software:
6//
7// - the low-level C++ template SIMD library
8// - the SIMD implementation of the MinWarping and the 2D-Warping methods
9// for local visual homing.
10//
11// The software is provided based on the accompanying license agreement in the
12// file LICENSE.md.
13// The software is provided "as is" without any warranty by the licensor and
14// without any liability of the licensor, and the software may not be
15// distributed by the licensee; see the license agreement for details.
16//
17// (C) Ralf Möller
18// Computer Engineering
19// Faculty of Technology
20// Bielefeld University
21// www.ti.uni-bielefeld.de
22//
23// ===========================================================================
24
25#pragma once
26#ifndef SIMD_DEFS_H_
27#define SIMD_DEFS_H_
28
29#include <cstring>
30#include <iostream>
31
32// TODO: implement and test for other compilers
33// TODO: static inline on primary function templates useful?
34// TODO: (static not allowed on function template specializations)
35// TODO: MS world: inline __forceinline?
36
37// ---------------------------------------------------------------------------
38// preprocessor symbols
39// ---------------------------------------------------------------------------
40
41// NOTE: these symbols should be defined before including any T-SIMD header file
42// (e.g. by passing them to the compiler via the command line) otherwise
43// they might not have the desired effect
44
45// SIMD_ALIGN_CHK:
46// if defined, alignment checks of pointers are added in aligned load
47// and store functions (if necessary on given architecture)
48
49// MAX_SIMD_WIDTH:
50// if defined, NATIVE_SIMD_WIDTH will be at most to this value
51// must be at least 16, as smaller vector widths are not supported
52
53// ---------------------------------------------------------------------------
54// architecture-specific definitions
55// ---------------------------------------------------------------------------
56
57#if defined(__i386__) || defined(__x86_64__)
58#define SIMDVEC_INTEL_ENABLE 1
59
60#ifdef __AVX512F__
61// this can be used to check whether 64-byte support is available
62#define _SIMD_VEC_64_AVAIL_
63#ifdef __AVX512BW__
64// this can be used to check whether full 64-byte support is available
65#define _SIMD_VEC_64_FULL_AVAIL_
66#endif
67#endif
68
69#ifdef __AVX__
70// this can be used to check whether 32-byte support is available
71#define _SIMD_VEC_32_AVAIL_
72#ifdef __AVX2__
73// this can be used to check whether full 32-byte support is available
74#define _SIMD_VEC_32_FULL_AVAIL_
75#endif
76#endif
77
78#ifdef __SSE2__
79#define _SIMD_VEC_16_AVAIL_
80#endif
81
82// determine NATIVE_SIMD_WIDTH
83#ifdef _SIMD_VEC_64_AVAIL_
84#define NATIVE_SIMD_WIDTH 64
85#elif defined(_SIMD_VEC_32_AVAIL_)
86#define NATIVE_SIMD_WIDTH 32
87#else
88#define NATIVE_SIMD_WIDTH 16
89#endif
90
91#endif // defined(__i386__) || defined(__x86_64__)
92
93// 31. Mar 22 (rm): gcc on ARM doesn't define __arm__
94// #if defined(__arm__) && (defined(__ARM_NEON__) || defined(__ARM_NEON))
95// 20. May 23 (Jonas Keller): apparently, some gcc versions in ARM *only* define
96// __arm__, so added checks for more possible defines to cover as many compilers
97// as possible
98// #if defined(__ARM_NEON__) || defined(__ARM_NEON)
99#if defined(__arm__) || defined(__aarch64__) || defined(__ARM_NEON__) || \
100 defined(__ARM_NEON) || defined(_M_ARM) || defined(_M_ARM64)
101#define SIMDVEC_NEON_ENABLE 1
102
103#define _SIMD_VEC_16_AVAIL_
104
105// determine NATIVE_SIMD_WIDTH
106#define NATIVE_SIMD_WIDTH 16
107
108#endif // arm defines
109
110// 20. May 23 (Jonas Keller):
111// added error message if no SIMD support was detected
112#ifndef _SIMD_VEC_16_AVAIL_
113#error "no SIMD support detected"
114#endif
115
116// determine double support
117#if defined(SIMDVEC_INTEL_ENABLE) || defined(__aarch64__)
118#define SIMD_64BIT_TYPES 1
119#endif
120
121// set NATIVE_SIMD_WIDTH to be at most MAX_SIMD_WIDTH
122#ifdef MAX_SIMD_WIDTH
123#if NATIVE_SIMD_WIDTH > MAX_SIMD_WIDTH
124#undef NATIVE_SIMD_WIDTH
125#if MAX_SIMD_WIDTH >= 64
126#define NATIVE_SIMD_WIDTH 64
127#elif MAX_SIMD_WIDTH >= 32
128#define NATIVE_SIMD_WIDTH 32
129#elif MAX_SIMD_WIDTH >= 16
130#define NATIVE_SIMD_WIDTH 16
131#else
132#error "MAX_SIMD_WIDTH must be at least 16"
133#endif
134#endif
135#endif
136
137// ---------------------------------------------------------------------------
138// g++, clang++ and icc
139// ---------------------------------------------------------------------------
140
141// thanks to Wolfram Schenck for icc tests
142// 30. Aug 22 (Jonas Keller): clang++ on windows does not define __GNUC__
143// #ifdef __GNUC__
144#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)
145#define SIMD_DEFS_DEFINED
146#define SIMD_INLINE inline __attribute__((always_inline))
147#define SIMD_ATTR_ALIGNED(ALIGN) __attribute__((aligned(ALIGN)))
148#define SIMD_ATTR_PACKED_STRUCT struct __attribute__((__packed__))
149#define SIMD_FULL_MEMBARRIER __sync_synchronize()
150#endif
151
152// TODO: MSVC?
153
154// ---------------------------------------------------------------------------
155// compiler-independent stuff
156// ---------------------------------------------------------------------------
157
158#ifndef SIMD_DEFS_DEFINED
159#error "attribute definitions missing for this compiler"
160#endif
161
162// macro to set the default value SIMD_WIDTH template parameter to
163// NATIVE_WIDTH if NATIVE_WIDTH is defined
164#ifdef NATIVE_SIMD_WIDTH
165#define SIMD_WIDTH_DEFAULT_NATIVE SIMD_WIDTH = NATIVE_SIMD_WIDTH
166#else
167#define SIMD_WIDTH_DEFAULT_NATIVE SIMD_WIDTH
168#endif
169
170namespace simd {
171namespace internal {
172template <typename Tout, typename Tin>
173SIMD_INLINE Tout bit_cast(Tin in)
174{
175 static_assert(std::is_trivially_copyable<Tout>::value,
176 "Tout must be trivially copyable");
177 static_assert(std::is_trivially_copyable<Tin>::value,
178 "Tin must be trivially copyable");
179 Tout out;
180 // set out to zero for padding in case sizeof(in) < sizeof(out)
181 std::memset(&out, 0, sizeof(out));
182 std::memcpy(&out, &in, std::min(sizeof(in), sizeof(out)));
183 return out;
184}
185} // namespace internal
186} // namespace simd
187
188// 29. Mar 23 (Jonas Keller): added SIMD_ENABLE_IF macro
189
190// macros to make enable_if SFINAE more convenient and readable
191#define SIMD_ENABLE_IF(EXPR) typename = typename std::enable_if<(EXPR)>::type
192
193// 26. Sep 23 (Jonas Keller): added SIMD_IF_CONSTEXPR macro
194
195// Macro for if's that can be evaluated at compile time.
196// Defined as "if constexpr" in C++17, otherwise as a regular "if".
197// If "constexpr if" is not available the compiler should still optimize the
198// regular "if" away since the condition is known at compile time.
199#ifdef __cpp_if_constexpr
200#define SIMD_IF_CONSTEXPR if constexpr
201#else
202#define SIMD_IF_CONSTEXPR if
203#endif
204
205// 08. Apr 23 (Jonas Keller): added SIMD_CHECK_ALIGNMENT macro
206
207// macro to check alignment of a pointer
208// does nothing if SIMD_ALIGN_CHK is not defined
209// does not use assert() because assert() may be disabled (e.g. in release
210// builds)
211
212#ifdef SIMD_ALIGN_CHK
213#define SIMD_CHECK_ALIGNMENT(PTR, ALIGN) \
214 if (reinterpret_cast<uintptr_t>(PTR) % (ALIGN) != 0) { \
215 ::std::cerr << "SIMD_CHECK_ALIGNMENT: " << __FILE__ << ":" << __LINE__ \
216 << ": " << __func__ << ": " << #PTR << " = " << (PTR) \
217 << " is not aligned to " << (ALIGN) << " bytes" \
218 << ::std::endl; \
219 ::std::abort(); \
220 }
221#else
222#define SIMD_CHECK_ALIGNMENT(PTR, ALIGN) ((void) 0)
223#endif
224
225#endif
Namespace for T-SIMD.
Definition time_measurement.H:161