LCOV - code coverage report
Current view: top level - gcore - gdal_avx2_emulation.hpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 58 58 100.0 %
Date: 2024-11-21 22:18:42 Functions: 25 25 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * Project:  GDAL
       3             :  * Purpose:  AVX2 emulation with SSE2 + a few SSE4.1 emulation
       4             :  * Author:   Even Rouault <even dot rouault at spatialys dot com>
       5             :  *
       6             :  ******************************************************************************
       7             :  * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
       8             :  *
       9             :  * SPDX-License-Identifier: MIT
      10             :  ****************************************************************************/
      11             : 
      12             : #ifndef GDAL_AVX2_EMULATION_H_INCLUDED
      13             : #define GDAL_AVX2_EMULATION_H_INCLUDED
      14             : 
      15             : #include <emmintrin.h>
      16             : 
      17             : #ifdef __SSE4_1__
      18             : #include <smmintrin.h>
      19             : 
      20             : #define GDALmm_min_epu16 _mm_min_epu16
      21             : #define GDALmm_max_epu16 _mm_max_epu16
      22             : #define GDALmm_mullo_epi32 _mm_mullo_epi32
      23             : #define GDALmm_cvtepu8_epi16 _mm_cvtepu8_epi16
      24             : #define GDALmm_cvtepu16_epi32 _mm_cvtepu16_epi32
      25             : #define GDALmm_cvtepu16_epi64 _mm_cvtepu16_epi64
      26             : #define GDALmm_cvtepu32_epi64 _mm_cvtepu32_epi64
      27             : 
      28             : #else
      29             : // Emulation of SSE4.1 _mm_min_epu16 and _mm_max_epu16 with SSE2 only
      30             : 
      31             : static inline __m128i GDALAVX2Emul_mm_cmple_epu16(__m128i x, __m128i y)
      32             : {
      33             :     return _mm_cmpeq_epi16(_mm_subs_epu16(x, y), _mm_setzero_si128());
      34             : }
      35             : 
      36             : static inline __m128i GDALAVX2Emul_mm_ternary(__m128i mask, __m128i then_reg,
      37             :                                               __m128i else_reg)
      38             : {
      39             :     return _mm_or_si128(_mm_and_si128(mask, then_reg),
      40             :                         _mm_andnot_si128(mask, else_reg));
      41             : }
      42             : 
      43             : static inline __m128i GDALmm_min_epu16(__m128i x, __m128i y)
      44             : {
      45             :     const __m128i mask = GDALAVX2Emul_mm_cmple_epu16(x, y);
      46             :     return GDALAVX2Emul_mm_ternary(mask, x, y);
      47             : }
      48             : 
      49             : static inline __m128i GDALmm_max_epu16(__m128i x, __m128i y)
      50             : {
      51             :     const __m128i mask = GDALAVX2Emul_mm_cmple_epu16(x, y);
      52             :     return GDALAVX2Emul_mm_ternary(mask, y, x);
      53             : }
      54             : 
      55             : static inline __m128i GDALmm_mullo_epi32(__m128i x, __m128i y)
      56             : {
      57             :     const __m128i mul02 = _mm_shuffle_epi32(_mm_mul_epu32(x, y), 2 << 2);
      58             :     const __m128i mul13 = _mm_shuffle_epi32(
      59             :         _mm_mul_epu32(_mm_srli_si128(x, 4), _mm_srli_si128(y, 4)), 2 << 2);
      60             :     return _mm_unpacklo_epi32(mul02, mul13);
      61             :     ;
      62             : }
      63             : 
      64             : static inline __m128i GDALmm_cvtepu8_epi16(__m128i x)
      65             : {
      66             :     return _mm_unpacklo_epi8(x, _mm_setzero_si128());
      67             : }
      68             : 
      69             : static inline __m128i GDALmm_cvtepu16_epi32(__m128i x)
      70             : {
      71             :     return _mm_unpacklo_epi16(x, _mm_setzero_si128());
      72             : }
      73             : 
      74             : static inline __m128i GDALmm_cvtepu16_epi64(__m128i x)
      75             : {
      76             :     return _mm_unpacklo_epi32(_mm_unpacklo_epi16(x, _mm_setzero_si128()),
      77             :                               _mm_setzero_si128());
      78             : }
      79             : 
      80             : static inline __m128i GDALmm_cvtepu32_epi64(__m128i x)
      81             : {
      82             :     return _mm_unpacklo_epi32(x, _mm_setzero_si128());
      83             : }
      84             : 
      85             : #endif  // __SSE4_1__
      86             : 
      87             : #ifdef __AVX2__
      88             : 
      89             : #include <immintrin.h>
      90             : 
      91             : typedef __m256i GDALm256i;
      92             : 
      93             : #define GDALmm256_set1_epi8 _mm256_set1_epi8
      94             : #define GDALmm256_set1_epi16 _mm256_set1_epi16
      95             : #define GDALmm256_set1_epi32 _mm256_set1_epi32
      96             : #define GDALmm256_setzero_si256 _mm256_setzero_si256
      97             : #define GDALmm256_load_si256 _mm256_load_si256
      98             : #define GDALmm256_store_si256 _mm256_store_si256
      99             : #define GDALmm256_storeu_si256 _mm256_storeu_si256
     100             : #define GDALmm256_cmpeq_epi8 _mm256_cmpeq_epi8
     101             : #define GDALmm256_sad_epu8 _mm256_sad_epu8
     102             : #define GDALmm256_add_epi32 _mm256_add_epi32
     103             : #define GDALmm256_andnot_si256 _mm256_andnot_si256
     104             : #define GDALmm256_and_si256 _mm256_and_si256
     105             : #define GDALmm256_or_si256 _mm256_or_si256
     106             : #define GDALmm256_min_epu8 _mm256_min_epu8
     107             : #define GDALmm256_max_epu8 _mm256_max_epu8
     108             : #define GDALmm256_extracti128_si256 _mm256_extracti128_si256
     109             : #define GDALmm256_cvtepu8_epi16 _mm256_cvtepu8_epi16
     110             : #define GDALmm256_madd_epi16 _mm256_madd_epi16
     111             : #define GDALmm256_min_epu16 _mm256_min_epu16
     112             : #define GDALmm256_max_epu16 _mm256_max_epu16
     113             : #define GDALmm256_cvtepu16_epi32 _mm256_cvtepu16_epi32
     114             : #define GDALmm256_cvtepu16_epi64 _mm256_cvtepu16_epi64
     115             : #define GDALmm256_cvtepu32_epi64 _mm256_cvtepu32_epi64
     116             : #define GDALmm256_mullo_epi32 _mm256_mullo_epi32
     117             : #define GDALmm256_add_epi64 _mm256_add_epi64
     118             : #define GDALmm256_add_epi16 _mm256_add_epi16
     119             : #define GDALmm256_sub_epi16 _mm256_sub_epi16
     120             : #define GDALmm256_min_epi16 _mm256_min_epi16
     121             : #define GDALmm256_max_epi16 _mm256_max_epi16
     122             : #define GDALmm256_srli_epi16 _mm256_srli_epi16
     123             : #define GDALmm256_srli_epi32 _mm256_srli_epi32
     124             : #define GDALmm256_srli_epi64 _mm256_srli_epi64
     125             : #define GDALmm256_set1_epi64x _mm256_set1_epi64x
     126             : 
     127             : #else
     128             : 
     129             : typedef struct
     130             : {
     131             :     __m128i low;
     132             :     __m128i high;
     133             : } GDALm256i;
     134             : 
     135        2480 : static inline GDALm256i GDALmm256_set1_epi8(char c)
     136             : {
     137             :     GDALm256i reg;
     138        2480 :     reg.low = _mm_set1_epi8(c);
     139        2480 :     reg.high = _mm_set1_epi8(c);
     140        2480 :     return reg;
     141             : }
     142             : 
     143       21409 : static inline GDALm256i GDALmm256_set1_epi16(short s)
     144             : {
     145             :     GDALm256i reg;
     146       21409 :     reg.low = _mm_set1_epi16(s);
     147       21409 :     reg.high = _mm_set1_epi16(s);
     148       21409 :     return reg;
     149             : }
     150             : 
     151        1165 : static inline GDALm256i GDALmm256_set1_epi32(int i)
     152             : {
     153             :     GDALm256i reg;
     154        1165 :     reg.low = _mm_set1_epi32(i);
     155        1165 :     reg.high = _mm_set1_epi32(i);
     156        1165 :     return reg;
     157             : }
     158             : 
     159        1165 : static inline GDALm256i GDALmm256_set1_epi64x(long long i)
     160             : {
     161             :     GDALm256i reg;
     162        1165 :     reg.low = _mm_set1_epi64x(i);
     163        1165 :     reg.high = _mm_set1_epi64x(i);
     164        1165 :     return reg;
     165             : }
     166             : 
     167      546605 : static inline GDALm256i GDALmm256_setzero_si256()
     168             : {
     169             :     GDALm256i reg;
     170      546605 :     reg.low = _mm_setzero_si128();
     171      546605 :     reg.high = _mm_setzero_si128();
     172      546605 :     return reg;
     173             : }
     174             : 
     175     1607720 : static inline GDALm256i GDALmm256_load_si256(GDALm256i const *p)
     176             : {
     177             :     GDALm256i reg;
     178     1607720 :     reg.low = _mm_load_si128(reinterpret_cast<__m128i const *>(p));
     179     1607720 :     reg.high = _mm_load_si128(reinterpret_cast<__m128i const *>(
     180             :         reinterpret_cast<const char *>(p) + 16));
     181     1607720 :     return reg;
     182             : }
     183             : 
     184       44858 : static inline void GDALmm256_store_si256(GDALm256i *p, GDALm256i reg)
     185             : {
     186       44858 :     _mm_store_si128(reinterpret_cast<__m128i *>(p), reg.low);
     187       44858 :     _mm_store_si128(
     188             :         reinterpret_cast<__m128i *>(reinterpret_cast<char *>(p) + 16),
     189             :         reg.high);
     190       44858 : }
     191             : 
     192        3054 : static inline void GDALmm256_storeu_si256(GDALm256i *p, GDALm256i reg)
     193             : {
     194        3054 :     _mm_storeu_si128(reinterpret_cast<__m128i *>(p), reg.low);
     195        3054 :     _mm_storeu_si128(
     196             :         reinterpret_cast<__m128i *>(reinterpret_cast<char *>(p) + 16),
     197             :         reg.high);
     198        3054 : }
     199             : 
     200             : #define DEFINE_BINARY_MM256(mm256name, mm128name)                              \
     201             :     static inline GDALm256i mm256name(GDALm256i r1, GDALm256i r2)              \
     202             :     {                                                                          \
     203             :         GDALm256i reg;                                                         \
     204             :         reg.low = mm128name(r1.low, r2.low);                                   \
     205             :         reg.high = mm128name(r1.high, r2.high);                                \
     206             :         return reg;                                                            \
     207             :     }
     208             : 
     209       37677 : DEFINE_BINARY_MM256(GDALmm256_cmpeq_epi8, _mm_cmpeq_epi8)
     210     1507570 : DEFINE_BINARY_MM256(GDALmm256_sad_epu8, _mm_sad_epu8)
     211     5091120 : DEFINE_BINARY_MM256(GDALmm256_add_epi32, _mm_add_epi32)
     212       37677 : DEFINE_BINARY_MM256(GDALmm256_andnot_si256, _mm_andnot_si128)
     213     2114050 : DEFINE_BINARY_MM256(GDALmm256_and_si256, _mm_and_si128)
     214       24522 : DEFINE_BINARY_MM256(GDALmm256_or_si256, _mm_or_si128)
     215      503109 : DEFINE_BINARY_MM256(GDALmm256_min_epu8, _mm_min_epu8)
     216     1602630 : DEFINE_BINARY_MM256(GDALmm256_max_epu8, _mm_max_epu8)
     217     3285800 : DEFINE_BINARY_MM256(GDALmm256_madd_epi16, _mm_madd_epi16)
     218             : DEFINE_BINARY_MM256(GDALmm256_min_epu16, GDALmm_min_epu16)
     219             : DEFINE_BINARY_MM256(GDALmm256_max_epu16, GDALmm_max_epu16)
     220             : DEFINE_BINARY_MM256(GDALmm256_mullo_epi32, GDALmm_mullo_epi32)
     221      595500 : DEFINE_BINARY_MM256(GDALmm256_add_epi64, _mm_add_epi64)
     222     2877720 : DEFINE_BINARY_MM256(GDALmm256_add_epi16, _mm_add_epi16)
     223        6744 : DEFINE_BINARY_MM256(GDALmm256_sub_epi16, _mm_sub_epi16)
     224     2847170 : DEFINE_BINARY_MM256(GDALmm256_min_epi16, _mm_min_epi16)
     225     2847170 : DEFINE_BINARY_MM256(GDALmm256_max_epi16, _mm_max_epi16)
     226             : 
     227             : static inline __m128i GDALmm256_extracti128_si256(GDALm256i reg, int index)
     228             : {
     229             :     return (index == 0) ? reg.low : reg.high;
     230             : }
     231             : 
     232             : #define DEFINE_CVTE_MM256(mm256name, mm128name)                                \
     233             :     static inline GDALm256i mm256name(__m128i x)                               \
     234             :     {                                                                          \
     235             :         GDALm256i reg;                                                         \
     236             :         reg.low = mm128name(x);                                                \
     237             :         reg.high = mm128name(_mm_srli_si128(x, 8));                            \
     238             :         return reg;                                                            \
     239             :     }
     240             : 
     241             : DEFINE_CVTE_MM256(GDALmm256_cvtepu8_epi16, GDALmm_cvtepu8_epi16)
     242             : DEFINE_CVTE_MM256(GDALmm256_cvtepu16_epi32, GDALmm_cvtepu16_epi32)
     243             : DEFINE_CVTE_MM256(GDALmm256_cvtepu16_epi64, GDALmm_cvtepu16_epi64)
     244             : DEFINE_CVTE_MM256(GDALmm256_cvtepu32_epi64, GDALmm_cvtepu32_epi64)
     245             : 
     246      498009 : static inline GDALm256i GDALmm256_srli_epi16(GDALm256i reg, int imm)
     247             : {
     248             :     GDALm256i ret;
     249      498009 :     ret.low = _mm_srli_epi16(reg.low, imm);
     250      498009 :     ret.high = _mm_srli_epi16(reg.high, imm);
     251      498009 :     return ret;
     252             : }
     253             : 
     254       99250 : static inline GDALm256i GDALmm256_srli_epi32(GDALm256i reg, int imm)
     255             : {
     256             :     GDALm256i ret;
     257       99250 :     ret.low = _mm_srli_epi32(reg.low, imm);
     258       99250 :     ret.high = _mm_srli_epi32(reg.high, imm);
     259       99250 :     return ret;
     260             : }
     261             : 
     262       99250 : static inline GDALm256i GDALmm256_srli_epi64(GDALm256i reg, int imm)
     263             : {
     264             :     GDALm256i ret;
     265       99250 :     ret.low = _mm_srli_epi64(reg.low, imm);
     266       99250 :     ret.high = _mm_srli_epi64(reg.high, imm);
     267       99250 :     return ret;
     268             : }
     269             : 
     270             : #endif
     271             : 
     272             : #endif /* GDAL_AVX2_EMULATION_H_INCLUDED */

Generated by: LCOV version 1.14