1*e0c1b49fSNick Terrell /* 2*e0c1b49fSNick Terrell * Copyright (c) Yann Collet, Facebook, Inc. 3*e0c1b49fSNick Terrell * All rights reserved. 4*e0c1b49fSNick Terrell * 5*e0c1b49fSNick Terrell * This source code is licensed under both the BSD-style license (found in the 6*e0c1b49fSNick Terrell * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7*e0c1b49fSNick Terrell * in the COPYING file in the root directory of this source tree). 8*e0c1b49fSNick Terrell * You may select, at your option, one of the above-listed licenses. 9*e0c1b49fSNick Terrell */ 10*e0c1b49fSNick Terrell 11*e0c1b49fSNick Terrell #ifndef ZSTD_COMPILER_H 12*e0c1b49fSNick Terrell #define ZSTD_COMPILER_H 13*e0c1b49fSNick Terrell 14*e0c1b49fSNick Terrell /*-******************************************************* 15*e0c1b49fSNick Terrell * Compiler specifics 16*e0c1b49fSNick Terrell *********************************************************/ 17*e0c1b49fSNick Terrell /* force inlining */ 18*e0c1b49fSNick Terrell 19*e0c1b49fSNick Terrell #if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ 20*e0c1b49fSNick Terrell # define INLINE_KEYWORD inline 21*e0c1b49fSNick Terrell #else 22*e0c1b49fSNick Terrell # define INLINE_KEYWORD 23*e0c1b49fSNick Terrell #endif 24*e0c1b49fSNick Terrell 25*e0c1b49fSNick Terrell #define FORCE_INLINE_ATTR __attribute__((always_inline)) 26*e0c1b49fSNick Terrell 27*e0c1b49fSNick Terrell 28*e0c1b49fSNick Terrell /* 29*e0c1b49fSNick Terrell On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC). 30*e0c1b49fSNick Terrell This explictly marks such functions as __cdecl so that the code will still compile 31*e0c1b49fSNick Terrell if a CC other than __cdecl has been made the default. 32*e0c1b49fSNick Terrell */ 33*e0c1b49fSNick Terrell #define WIN_CDECL 34*e0c1b49fSNick Terrell 35*e0c1b49fSNick Terrell /* 36*e0c1b49fSNick Terrell * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant 37*e0c1b49fSNick Terrell * parameters. They must be inlined for the compiler to eliminate the constant 38*e0c1b49fSNick Terrell * branches. 39*e0c1b49fSNick Terrell */ 40*e0c1b49fSNick Terrell #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR 41*e0c1b49fSNick Terrell /* 42*e0c1b49fSNick Terrell * HINT_INLINE is used to help the compiler generate better code. It is *not* 43*e0c1b49fSNick Terrell * used for "templates", so it can be tweaked based on the compilers 44*e0c1b49fSNick Terrell * performance. 45*e0c1b49fSNick Terrell * 46*e0c1b49fSNick Terrell * gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the 47*e0c1b49fSNick Terrell * always_inline attribute. 48*e0c1b49fSNick Terrell * 49*e0c1b49fSNick Terrell * clang up to 5.0.0 (trunk) benefit tremendously from the always_inline 50*e0c1b49fSNick Terrell * attribute. 51*e0c1b49fSNick Terrell */ 52*e0c1b49fSNick Terrell #if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5 53*e0c1b49fSNick Terrell # define HINT_INLINE static INLINE_KEYWORD 54*e0c1b49fSNick Terrell #else 55*e0c1b49fSNick Terrell # define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR 56*e0c1b49fSNick Terrell #endif 57*e0c1b49fSNick Terrell 58*e0c1b49fSNick Terrell /* UNUSED_ATTR tells the compiler it is okay if the function is unused. */ 59*e0c1b49fSNick Terrell #define UNUSED_ATTR __attribute__((unused)) 60*e0c1b49fSNick Terrell 61*e0c1b49fSNick Terrell /* force no inlining */ 62*e0c1b49fSNick Terrell #define FORCE_NOINLINE static __attribute__((__noinline__)) 63*e0c1b49fSNick Terrell 64*e0c1b49fSNick Terrell 65*e0c1b49fSNick Terrell /* target attribute */ 66*e0c1b49fSNick Terrell #ifndef __has_attribute 67*e0c1b49fSNick Terrell #define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ 68*e0c1b49fSNick Terrell #endif 69*e0c1b49fSNick Terrell #define TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) 70*e0c1b49fSNick Terrell 71*e0c1b49fSNick Terrell /* Enable runtime BMI2 dispatch based on the CPU. 72*e0c1b49fSNick Terrell * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default. 73*e0c1b49fSNick Terrell */ 74*e0c1b49fSNick Terrell #ifndef DYNAMIC_BMI2 75*e0c1b49fSNick Terrell #if ((defined(__clang__) && __has_attribute(__target__)) \ 76*e0c1b49fSNick Terrell || (defined(__GNUC__) \ 77*e0c1b49fSNick Terrell && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \ 78*e0c1b49fSNick Terrell && (defined(__x86_64__) || defined(_M_X86)) \ 79*e0c1b49fSNick Terrell && !defined(__BMI2__) 80*e0c1b49fSNick Terrell # define DYNAMIC_BMI2 1 81*e0c1b49fSNick Terrell #else 82*e0c1b49fSNick Terrell # define DYNAMIC_BMI2 0 83*e0c1b49fSNick Terrell #endif 84*e0c1b49fSNick Terrell #endif 85*e0c1b49fSNick Terrell 86*e0c1b49fSNick Terrell /* prefetch 87*e0c1b49fSNick Terrell * can be disabled, by declaring NO_PREFETCH build macro */ 88*e0c1b49fSNick Terrell #if ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) 89*e0c1b49fSNick Terrell # define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) 90*e0c1b49fSNick Terrell # define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) 91*e0c1b49fSNick Terrell #elif defined(__aarch64__) 92*e0c1b49fSNick Terrell # define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))) 93*e0c1b49fSNick Terrell # define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))) 94*e0c1b49fSNick Terrell #else 95*e0c1b49fSNick Terrell # define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ 96*e0c1b49fSNick Terrell # define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ 97*e0c1b49fSNick Terrell #endif /* NO_PREFETCH */ 98*e0c1b49fSNick Terrell 99*e0c1b49fSNick Terrell #define CACHELINE_SIZE 64 100*e0c1b49fSNick Terrell 101*e0c1b49fSNick Terrell #define PREFETCH_AREA(p, s) { \ 102*e0c1b49fSNick Terrell const char* const _ptr = (const char*)(p); \ 103*e0c1b49fSNick Terrell size_t const _size = (size_t)(s); \ 104*e0c1b49fSNick Terrell size_t _pos; \ 105*e0c1b49fSNick Terrell for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \ 106*e0c1b49fSNick Terrell PREFETCH_L2(_ptr + _pos); \ 107*e0c1b49fSNick Terrell } \ 108*e0c1b49fSNick Terrell } 109*e0c1b49fSNick Terrell 110*e0c1b49fSNick Terrell /* vectorization 111*e0c1b49fSNick Terrell * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax */ 112*e0c1b49fSNick Terrell #if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) 113*e0c1b49fSNick Terrell # if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5) 114*e0c1b49fSNick Terrell # define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) 115*e0c1b49fSNick Terrell # else 116*e0c1b49fSNick Terrell # define DONT_VECTORIZE _Pragma("GCC optimize(\"no-tree-vectorize\")") 117*e0c1b49fSNick Terrell # endif 118*e0c1b49fSNick Terrell #else 119*e0c1b49fSNick Terrell # define DONT_VECTORIZE 120*e0c1b49fSNick Terrell #endif 121*e0c1b49fSNick Terrell 122*e0c1b49fSNick Terrell /* Tell the compiler that a branch is likely or unlikely. 123*e0c1b49fSNick Terrell * Only use these macros if it causes the compiler to generate better code. 124*e0c1b49fSNick Terrell * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc 125*e0c1b49fSNick Terrell * and clang, please do. 126*e0c1b49fSNick Terrell */ 127*e0c1b49fSNick Terrell #define LIKELY(x) (__builtin_expect((x), 1)) 128*e0c1b49fSNick Terrell #define UNLIKELY(x) (__builtin_expect((x), 0)) 129*e0c1b49fSNick Terrell 130*e0c1b49fSNick Terrell /* disable warnings */ 131*e0c1b49fSNick Terrell 132*e0c1b49fSNick Terrell /*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/ 133*e0c1b49fSNick Terrell 134*e0c1b49fSNick Terrell 135*e0c1b49fSNick Terrell /* compat. with non-clang compilers */ 136*e0c1b49fSNick Terrell #ifndef __has_builtin 137*e0c1b49fSNick Terrell # define __has_builtin(x) 0 138*e0c1b49fSNick Terrell #endif 139*e0c1b49fSNick Terrell 140*e0c1b49fSNick Terrell /* compat. with non-clang compilers */ 141*e0c1b49fSNick Terrell #ifndef __has_feature 142*e0c1b49fSNick Terrell # define __has_feature(x) 0 143*e0c1b49fSNick Terrell #endif 144*e0c1b49fSNick Terrell 145*e0c1b49fSNick Terrell /* C-language Attributes are added in C23. */ 146*e0c1b49fSNick Terrell #if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute) 147*e0c1b49fSNick Terrell # define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) 148*e0c1b49fSNick Terrell #else 149*e0c1b49fSNick Terrell # define ZSTD_HAS_C_ATTRIBUTE(x) 0 150*e0c1b49fSNick Terrell #endif 151*e0c1b49fSNick Terrell 152*e0c1b49fSNick Terrell /* Only use C++ attributes in C++. Some compilers report support for C++ 153*e0c1b49fSNick Terrell * attributes when compiling with C. 154*e0c1b49fSNick Terrell */ 155*e0c1b49fSNick Terrell #define ZSTD_HAS_CPP_ATTRIBUTE(x) 0 156*e0c1b49fSNick Terrell 157*e0c1b49fSNick Terrell /* Define ZSTD_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute. 158*e0c1b49fSNick Terrell * - C23: https://en.cppreference.com/w/c/language/attributes/fallthrough 159*e0c1b49fSNick Terrell * - CPP17: https://en.cppreference.com/w/cpp/language/attributes/fallthrough 160*e0c1b49fSNick Terrell * - Else: __attribute__((__fallthrough__)) 161*e0c1b49fSNick Terrell */ 162*e0c1b49fSNick Terrell #define ZSTD_FALLTHROUGH fallthrough 163*e0c1b49fSNick Terrell 164*e0c1b49fSNick Terrell /* detects whether we are being compiled under msan */ 165*e0c1b49fSNick Terrell 166*e0c1b49fSNick Terrell 167*e0c1b49fSNick Terrell /* detects whether we are being compiled under asan */ 168*e0c1b49fSNick Terrell 169*e0c1b49fSNick Terrell 170*e0c1b49fSNick Terrell #endif /* ZSTD_COMPILER_H */ 171