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-05-03 15:49:35 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      10             :  * copy of this software and associated documentation files (the "Software"),
      11             :  * to deal in the Software without restriction, including without limitation
      12             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      13             :  * and/or sell copies of the Software, and to permit persons to whom the
      14             :  * Software is furnished to do so, subject to the following conditions:
      15             :  *
      16             :  * The above copyright notice and this permission notice shall be included
      17             :  * in all copies or substantial portions of the Software.
      18             :  *
      19             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      20             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      22             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      23             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      24             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      25             :  * DEALINGS IN THE SOFTWARE.
      26             :  ****************************************************************************/
      27             : 
      28             : #ifndef GDAL_AVX2_EMULATION_H_INCLUDED
      29             : #define GDAL_AVX2_EMULATION_H_INCLUDED
      30             : 
      31             : #include <emmintrin.h>
      32             : 
      33             : #ifdef __SSE4_1__
      34             : #include <smmintrin.h>
      35             : 
      36             : #define GDALmm_min_epu16 _mm_min_epu16
      37             : #define GDALmm_max_epu16 _mm_max_epu16
      38             : #define GDALmm_mullo_epi32 _mm_mullo_epi32
      39             : #define GDALmm_cvtepu8_epi16 _mm_cvtepu8_epi16
      40             : #define GDALmm_cvtepu16_epi32 _mm_cvtepu16_epi32
      41             : #define GDALmm_cvtepu16_epi64 _mm_cvtepu16_epi64
      42             : #define GDALmm_cvtepu32_epi64 _mm_cvtepu32_epi64
      43             : 
      44             : #else
      45             : // Emulation of SSE4.1 _mm_min_epu16 and _mm_max_epu16 with SSE2 only
      46             : 
      47             : static inline __m128i GDALAVX2Emul_mm_cmple_epu16(__m128i x, __m128i y)
      48             : {
      49             :     return _mm_cmpeq_epi16(_mm_subs_epu16(x, y), _mm_setzero_si128());
      50             : }
      51             : 
      52             : static inline __m128i GDALAVX2Emul_mm_ternary(__m128i mask, __m128i then_reg,
      53             :                                               __m128i else_reg)
      54             : {
      55             :     return _mm_or_si128(_mm_and_si128(mask, then_reg),
      56             :                         _mm_andnot_si128(mask, else_reg));
      57             : }
      58             : 
      59             : static inline __m128i GDALmm_min_epu16(__m128i x, __m128i y)
      60             : {
      61             :     const __m128i mask = GDALAVX2Emul_mm_cmple_epu16(x, y);
      62             :     return GDALAVX2Emul_mm_ternary(mask, x, y);
      63             : }
      64             : 
      65             : static inline __m128i GDALmm_max_epu16(__m128i x, __m128i y)
      66             : {
      67             :     const __m128i mask = GDALAVX2Emul_mm_cmple_epu16(x, y);
      68             :     return GDALAVX2Emul_mm_ternary(mask, y, x);
      69             : }
      70             : 
      71             : static inline __m128i GDALmm_mullo_epi32(__m128i x, __m128i y)
      72             : {
      73             :     const __m128i mul02 = _mm_shuffle_epi32(_mm_mul_epu32(x, y), 2 << 2);
      74             :     const __m128i mul13 = _mm_shuffle_epi32(
      75             :         _mm_mul_epu32(_mm_srli_si128(x, 4), _mm_srli_si128(y, 4)), 2 << 2);
      76             :     return _mm_unpacklo_epi32(mul02, mul13);
      77             :     ;
      78             : }
      79             : 
      80             : static inline __m128i GDALmm_cvtepu8_epi16(__m128i x)
      81             : {
      82             :     return _mm_unpacklo_epi8(x, _mm_setzero_si128());
      83             : }
      84             : 
      85             : static inline __m128i GDALmm_cvtepu16_epi32(__m128i x)
      86             : {
      87             :     return _mm_unpacklo_epi16(x, _mm_setzero_si128());
      88             : }
      89             : 
      90             : static inline __m128i GDALmm_cvtepu16_epi64(__m128i x)
      91             : {
      92             :     return _mm_unpacklo_epi32(_mm_unpacklo_epi16(x, _mm_setzero_si128()),
      93             :                               _mm_setzero_si128());
      94             : }
      95             : 
      96             : static inline __m128i GDALmm_cvtepu32_epi64(__m128i x)
      97             : {
      98             :     return _mm_unpacklo_epi32(x, _mm_setzero_si128());
      99             : }
     100             : 
     101             : #endif  // __SSE4_1__
     102             : 
     103             : #ifdef __AVX2__
     104             : 
     105             : #include <immintrin.h>
     106             : 
     107             : typedef __m256i GDALm256i;
     108             : 
     109             : #define GDALmm256_set1_epi8 _mm256_set1_epi8
     110             : #define GDALmm256_set1_epi16 _mm256_set1_epi16
     111             : #define GDALmm256_set1_epi32 _mm256_set1_epi32
     112             : #define GDALmm256_setzero_si256 _mm256_setzero_si256
     113             : #define GDALmm256_load_si256 _mm256_load_si256
     114             : #define GDALmm256_store_si256 _mm256_store_si256
     115             : #define GDALmm256_storeu_si256 _mm256_storeu_si256
     116             : #define GDALmm256_cmpeq_epi8 _mm256_cmpeq_epi8
     117             : #define GDALmm256_sad_epu8 _mm256_sad_epu8
     118             : #define GDALmm256_add_epi32 _mm256_add_epi32
     119             : #define GDALmm256_andnot_si256 _mm256_andnot_si256
     120             : #define GDALmm256_and_si256 _mm256_and_si256
     121             : #define GDALmm256_or_si256 _mm256_or_si256
     122             : #define GDALmm256_min_epu8 _mm256_min_epu8
     123             : #define GDALmm256_max_epu8 _mm256_max_epu8
     124             : #define GDALmm256_extracti128_si256 _mm256_extracti128_si256
     125             : #define GDALmm256_cvtepu8_epi16 _mm256_cvtepu8_epi16
     126             : #define GDALmm256_madd_epi16 _mm256_madd_epi16
     127             : #define GDALmm256_min_epu16 _mm256_min_epu16
     128             : #define GDALmm256_max_epu16 _mm256_max_epu16
     129             : #define GDALmm256_cvtepu16_epi32 _mm256_cvtepu16_epi32
     130             : #define GDALmm256_cvtepu16_epi64 _mm256_cvtepu16_epi64
     131             : #define GDALmm256_cvtepu32_epi64 _mm256_cvtepu32_epi64
     132             : #define GDALmm256_mullo_epi32 _mm256_mullo_epi32
     133             : #define GDALmm256_add_epi64 _mm256_add_epi64
     134             : #define GDALmm256_add_epi16 _mm256_add_epi16
     135             : #define GDALmm256_sub_epi16 _mm256_sub_epi16
     136             : #define GDALmm256_min_epi16 _mm256_min_epi16
     137             : #define GDALmm256_max_epi16 _mm256_max_epi16
     138             : #define GDALmm256_srli_epi16 _mm256_srli_epi16
     139             : #define GDALmm256_srli_epi32 _mm256_srli_epi32
     140             : #define GDALmm256_srli_epi64 _mm256_srli_epi64
     141             : #define GDALmm256_set1_epi64x _mm256_set1_epi64x
     142             : 
     143             : #else
     144             : 
     145             : typedef struct
     146             : {
     147             :     __m128i low;
     148             :     __m128i high;
     149             : } GDALm256i;
     150             : 
     151        2480 : static inline GDALm256i GDALmm256_set1_epi8(char c)
     152             : {
     153             :     GDALm256i reg;
     154        2480 :     reg.low = _mm_set1_epi8(c);
     155        2480 :     reg.high = _mm_set1_epi8(c);
     156        2480 :     return reg;
     157             : }
     158             : 
     159       21185 : static inline GDALm256i GDALmm256_set1_epi16(short s)
     160             : {
     161             :     GDALm256i reg;
     162       21185 :     reg.low = _mm_set1_epi16(s);
     163       21185 :     reg.high = _mm_set1_epi16(s);
     164       21185 :     return reg;
     165             : }
     166             : 
     167        1048 : static inline GDALm256i GDALmm256_set1_epi32(int i)
     168             : {
     169             :     GDALm256i reg;
     170        1048 :     reg.low = _mm_set1_epi32(i);
     171        1048 :     reg.high = _mm_set1_epi32(i);
     172        1048 :     return reg;
     173             : }
     174             : 
     175        1048 : static inline GDALm256i GDALmm256_set1_epi64x(long long i)
     176             : {
     177             :     GDALm256i reg;
     178        1048 :     reg.low = _mm_set1_epi64x(i);
     179        1048 :     reg.high = _mm_set1_epi64x(i);
     180        1048 :     return reg;
     181             : }
     182             : 
     183      546017 : static inline GDALm256i GDALmm256_setzero_si256()
     184             : {
     185             :     GDALm256i reg;
     186      546017 :     reg.low = _mm_setzero_si128();
     187      546017 :     reg.high = _mm_setzero_si128();
     188      546017 :     return reg;
     189             : }
     190             : 
     191     1595430 : static inline GDALm256i GDALmm256_load_si256(GDALm256i const *p)
     192             : {
     193             :     GDALm256i reg;
     194     1595430 :     reg.low = _mm_load_si128(reinterpret_cast<__m128i const *>(p));
     195     1595430 :     reg.high = _mm_load_si128(reinterpret_cast<__m128i const *>(
     196             :         reinterpret_cast<const char *>(p) + 16));
     197     1595430 :     return reg;
     198             : }
     199             : 
     200       44535 : static inline void GDALmm256_store_si256(GDALm256i *p, GDALm256i reg)
     201             : {
     202       44535 :     _mm_store_si128(reinterpret_cast<__m128i *>(p), reg.low);
     203       44535 :     _mm_store_si128(
     204             :         reinterpret_cast<__m128i *>(reinterpret_cast<char *>(p) + 16),
     205             :         reg.high);
     206       44535 : }
     207             : 
     208        2586 : static inline void GDALmm256_storeu_si256(GDALm256i *p, GDALm256i reg)
     209             : {
     210        2586 :     _mm_storeu_si128(reinterpret_cast<__m128i *>(p), reg.low);
     211        2586 :     _mm_storeu_si128(
     212             :         reinterpret_cast<__m128i *>(reinterpret_cast<char *>(p) + 16),
     213             :         reg.high);
     214        2586 : }
     215             : 
     216             : #define DEFINE_BINARY_MM256(mm256name, mm128name)                              \
     217             :     static inline GDALm256i mm256name(GDALm256i r1, GDALm256i r2)              \
     218             :     {                                                                          \
     219             :         GDALm256i reg;                                                         \
     220             :         reg.low = mm128name(r1.low, r2.low);                                   \
     221             :         reg.high = mm128name(r1.high, r2.high);                                \
     222             :         return reg;                                                            \
     223             :     }
     224             : 
     225       37677 : DEFINE_BINARY_MM256(GDALmm256_cmpeq_epi8, _mm_cmpeq_epi8)
     226     1507150 : DEFINE_BINARY_MM256(GDALmm256_sad_epu8, _mm_sad_epu8)
     227     5078630 : DEFINE_BINARY_MM256(GDALmm256_add_epi32, _mm_add_epi32)
     228       37677 : DEFINE_BINARY_MM256(GDALmm256_andnot_si256, _mm_andnot_si128)
     229     2102400 : DEFINE_BINARY_MM256(GDALmm256_and_si256, _mm_and_si128)
     230       24522 : DEFINE_BINARY_MM256(GDALmm256_or_si256, _mm_or_si128)
     231      483966 : DEFINE_BINARY_MM256(GDALmm256_min_epu8, _mm_min_epu8)
     232     1572040 : DEFINE_BINARY_MM256(GDALmm256_max_epu8, _mm_max_epu8)
     233     3279350 : DEFINE_BINARY_MM256(GDALmm256_madd_epi16, _mm_madd_epi16)
     234             : DEFINE_BINARY_MM256(GDALmm256_min_epu16, GDALmm_min_epu16)
     235             : DEFINE_BINARY_MM256(GDALmm256_max_epu16, GDALmm_max_epu16)
     236             : DEFINE_BINARY_MM256(GDALmm256_mullo_epi32, GDALmm_mullo_epi32)
     237      584268 : DEFINE_BINARY_MM256(GDALmm256_add_epi64, _mm_add_epi64)
     238     2871760 : DEFINE_BINARY_MM256(GDALmm256_add_epi16, _mm_add_epi16)
     239        6042 : DEFINE_BINARY_MM256(GDALmm256_sub_epi16, _mm_sub_epi16)
     240     2841560 : DEFINE_BINARY_MM256(GDALmm256_min_epi16, _mm_min_epi16)
     241     2841560 : DEFINE_BINARY_MM256(GDALmm256_max_epi16, _mm_max_epi16)
     242             : 
     243             : static inline __m128i GDALmm256_extracti128_si256(GDALm256i reg, int index)
     244             : {
     245             :     return (index == 0) ? reg.low : reg.high;
     246             : }
     247             : 
     248             : #define DEFINE_CVTE_MM256(mm256name, mm128name)                                \
     249             :     static inline GDALm256i mm256name(__m128i x)                               \
     250             :     {                                                                          \
     251             :         GDALm256i reg;                                                         \
     252             :         reg.low = mm128name(x);                                                \
     253             :         reg.high = mm128name(_mm_srli_si128(x, 8));                            \
     254             :         return reg;                                                            \
     255             :     }
     256             : 
     257             : DEFINE_CVTE_MM256(GDALmm256_cvtepu8_epi16, GDALmm_cvtepu8_epi16)
     258             : DEFINE_CVTE_MM256(GDALmm256_cvtepu16_epi32, GDALmm_cvtepu16_epi32)
     259             : DEFINE_CVTE_MM256(GDALmm256_cvtepu16_epi64, GDALmm_cvtepu16_epi64)
     260             : DEFINE_CVTE_MM256(GDALmm256_cvtepu32_epi64, GDALmm_cvtepu32_epi64)
     261             : 
     262      497869 : static inline GDALm256i GDALmm256_srli_epi16(GDALm256i reg, int imm)
     263             : {
     264             :     GDALm256i ret;
     265      497869 :     ret.low = _mm_srli_epi16(reg.low, imm);
     266      497869 :     ret.high = _mm_srli_epi16(reg.high, imm);
     267      497869 :     return ret;
     268             : }
     269             : 
     270       97378 : static inline GDALm256i GDALmm256_srli_epi32(GDALm256i reg, int imm)
     271             : {
     272             :     GDALm256i ret;
     273       97378 :     ret.low = _mm_srli_epi32(reg.low, imm);
     274       97378 :     ret.high = _mm_srli_epi32(reg.high, imm);
     275       97378 :     return ret;
     276             : }
     277             : 
     278       97378 : static inline GDALm256i GDALmm256_srli_epi64(GDALm256i reg, int imm)
     279             : {
     280             :     GDALm256i ret;
     281       97378 :     ret.low = _mm_srli_epi64(reg.low, imm);
     282       97378 :     ret.high = _mm_srli_epi64(reg.high, imm);
     283       97378 :     return ret;
     284             : }
     285             : 
     286             : #endif
     287             : 
     288             : #endif /* GDAL_AVX2_EMULATION_H_INCLUDED */

Generated by: LCOV version 1.14