mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
x86 SIMD: build only baseline ISA tiers under PlayStation clang
Clang's immintrin.h for PlayStation targets (and clang-cl) declares only the intrinsics of ISAs the whole build enables, so the AVX2 and AVX-512 kernels that sinc_resampler, pixconv, float_to_s16 and state_manager compile under per-function targets do not exist there. On those compilers a tier is built only when the baseline carries it: the PS4 keeps sinc's AVX kernel, the PS5 keeps the AVX2 tiers, and the run-time choice never picks a tier that was left out.
This commit is contained in:
1 parent
7b23ab8aa4
commit
cabaa7b04d
4 files changed
+67
No files matched your search
@@ -140,12 +140,27 @@ void convert_float_to_s16_init_simd(void)
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#if _MSC_VER >= 1911
|
||||
#define FLOAT_TO_S16_HAVE_WIDE 1
|
||||
#define FLOAT_TO_S16_HAVE_AVX512 1
|
||||
#define FLOAT_TO_S16_TARGET_AVX2
|
||||
#define FLOAT_TO_S16_TARGET_AVX512
|
||||
#endif
|
||||
#elif defined(__clang__) && (defined(__SCE__) || defined(_MSC_VER))
|
||||
/* Clang's immintrin.h for PlayStation and clang-cl only declares the
|
||||
* intrinsics of ISAs enabled for the whole build, so per-function
|
||||
* targets cannot reach them; build a tier only when the baseline has
|
||||
* it (PS5's Zen 2 keeps AVX2, PS4's Jaguar has neither). */
|
||||
#ifdef __AVX2__
|
||||
#define FLOAT_TO_S16_HAVE_WIDE 1
|
||||
#define FLOAT_TO_S16_TARGET_AVX2
|
||||
#ifdef __AVX512F__
|
||||
#define FLOAT_TO_S16_HAVE_AVX512 1
|
||||
#define FLOAT_TO_S16_TARGET_AVX512
|
||||
#endif
|
||||
#endif
|
||||
#elif (defined(__clang__) && __clang_major__ >= 4) \
|
||||
|| (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 5)
|
||||
#define FLOAT_TO_S16_HAVE_WIDE 1
|
||||
#define FLOAT_TO_S16_HAVE_AVX512 1
|
||||
#define FLOAT_TO_S16_TARGET_AVX2 __attribute__((target("avx2")))
|
||||
#define FLOAT_TO_S16_TARGET_AVX512 __attribute__((target("avx512f")))
|
||||
#endif
|
||||
@@ -206,6 +221,7 @@ static size_t float_to_s16_avx2(int16_t *s, const float *in, size_t len)
|
||||
/* Sixteen samples a step, the last step masked: the loads and the
|
||||
* saturating narrow-and-store skip lanes past the end instead of a
|
||||
* scalar tail, so it converts the whole buffer. */
|
||||
#ifdef FLOAT_TO_S16_HAVE_AVX512
|
||||
FLOAT_TO_S16_TARGET_AVX512
|
||||
static void float_to_s16_avx512(int16_t *s, const float *in, size_t len)
|
||||
{
|
||||
@@ -235,6 +251,7 @@ static void float_to_s16_avx512(int16_t *s, const float *in, size_t len)
|
||||
FLOAT_TO_S16_ZEROUPPER();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The SSE2 / AltiVec / Allegrex loop and the scalar tail. */
|
||||
static void convert_float_to_s16_base(int16_t *s, const float *in, size_t len)
|
||||
@@ -390,11 +407,13 @@ void convert_float_to_s16(int16_t *s, const float *in, size_t len)
|
||||
if (float_to_s16_tier_cap >= 0 && tier > float_to_s16_tier_cap)
|
||||
tier = float_to_s16_tier_cap;
|
||||
#endif
|
||||
#ifdef FLOAT_TO_S16_HAVE_AVX512
|
||||
if (tier == 2)
|
||||
{
|
||||
float_to_s16_avx512(s, in, len);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (tier == 1)
|
||||
{
|
||||
size_t done = float_to_s16_avx2(s, in, len);
|
||||
@@ -413,8 +432,10 @@ void convert_float_to_s16_init_simd(void)
|
||||
float_to_s16_tier = 0;
|
||||
if (cpu & RETRO_SIMD_AVX2)
|
||||
float_to_s16_tier = 1;
|
||||
#ifdef FLOAT_TO_S16_HAVE_AVX512
|
||||
if (cpu & RETRO_SIMD_AVX512)
|
||||
float_to_s16_tier = 2;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -63,6 +63,18 @@
|
||||
#define SINC_HAVE_AVX512 1
|
||||
#define SINC_TARGET_AVX512
|
||||
#endif
|
||||
#elif defined(__clang__) && (defined(__SCE__) || defined(_MSC_VER))
|
||||
/* Clang's immintrin.h for PlayStation and clang-cl only declares the
|
||||
* intrinsics of ISAs enabled for the whole build, so per-function
|
||||
* targets cannot reach them; build a tier only when the baseline has it. */
|
||||
#ifdef __AVX__
|
||||
#define SINC_HAVE_AVX 1
|
||||
#define SINC_TARGET_AVX
|
||||
#endif
|
||||
#ifdef __AVX512F__
|
||||
#define SINC_HAVE_AVX512 1
|
||||
#define SINC_TARGET_AVX512
|
||||
#endif
|
||||
#elif (defined(__clang__) && __clang_major__ >= 4) \
|
||||
|| (defined(__GNUC__) && !defined(__clang__) \
|
||||
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)))
|
||||
|
||||
@@ -177,12 +177,27 @@ void conv_0rgb1555_rgb565(void *output_, const void *input_,
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#if _MSC_VER >= 1911
|
||||
#define PIXCONV_HAVE_WIDE 1
|
||||
#define PIXCONV_HAVE_AVX512 1
|
||||
#define PIXCONV_TARGET_AVX2
|
||||
#define PIXCONV_TARGET_AVX512
|
||||
#endif
|
||||
#elif defined(__clang__) && (defined(__SCE__) || defined(_MSC_VER))
|
||||
/* Clang's immintrin.h for PlayStation and clang-cl only declares the
|
||||
* intrinsics of ISAs enabled for the whole build, so per-function
|
||||
* targets cannot reach them; build a tier only when the baseline has
|
||||
* it (PS5's Zen 2 keeps AVX2, PS4's Jaguar has neither). */
|
||||
#ifdef __AVX2__
|
||||
#define PIXCONV_HAVE_WIDE 1
|
||||
#define PIXCONV_TARGET_AVX2
|
||||
#if defined(__AVX512F__) && defined(__AVX512BW__)
|
||||
#define PIXCONV_HAVE_AVX512 1
|
||||
#define PIXCONV_TARGET_AVX512
|
||||
#endif
|
||||
#endif
|
||||
#elif (defined(__clang__) && __clang_major__ >= 4) \
|
||||
|| (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 5)
|
||||
#define PIXCONV_HAVE_WIDE 1
|
||||
#define PIXCONV_HAVE_AVX512 1
|
||||
#define PIXCONV_TARGET_AVX2 __attribute__((target("avx2")))
|
||||
#define PIXCONV_TARGET_AVX512 __attribute__((target("avx512f,avx512bw")))
|
||||
#endif
|
||||
@@ -229,8 +244,10 @@ static int pixconv_simd_tier(void)
|
||||
tier = 0;
|
||||
if (cpu & RETRO_SIMD_AVX2)
|
||||
tier = 1;
|
||||
#ifdef PIXCONV_HAVE_AVX512
|
||||
if (cpu & RETRO_SIMD_AVX512)
|
||||
tier = 2;
|
||||
#endif
|
||||
retro_atomic_store_release_int(&pixconv_tier_cached, 4 | tier);
|
||||
}
|
||||
#ifdef PIXCONV_TEST_HOOKS
|
||||
@@ -314,6 +331,7 @@ static void pixconv_16to32_avx2(uint32_t *output, const uint16_t *input,
|
||||
PIXCONV_ZEROUPPER();
|
||||
}
|
||||
|
||||
#ifdef PIXCONV_HAVE_AVX512
|
||||
PIXCONV_TARGET_AVX512
|
||||
static void pixconv_16to32_avx512(uint32_t *output, const uint16_t *input,
|
||||
int width, int height, int out_stride, int in_stride, int fmt)
|
||||
@@ -371,6 +389,8 @@ static void pixconv_16to32_avx512(uint32_t *output, const uint16_t *input,
|
||||
PIXCONV_ZEROUPPER();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Runs the conversion wide and returns 1, or returns 0 for the caller's
|
||||
* own SSE2 path. */
|
||||
static int pixconv_16to32_wide(void *output, const void *input,
|
||||
@@ -378,10 +398,12 @@ static int pixconv_16to32_wide(void *output, const void *input,
|
||||
{
|
||||
switch (pixconv_simd_tier())
|
||||
{
|
||||
#ifdef PIXCONV_HAVE_AVX512
|
||||
case 2:
|
||||
pixconv_16to32_avx512((uint32_t*)output, (const uint16_t*)input,
|
||||
width, height, out_stride, in_stride, fmt);
|
||||
return 1;
|
||||
#endif
|
||||
case 1:
|
||||
pixconv_16to32_avx2((uint32_t*)output, (const uint16_t*)input,
|
||||
width, height, out_stride, in_stride, fmt);
|
||||
|
||||
@@ -77,6 +77,17 @@
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
|
||||
#include <immintrin.h>
|
||||
#include <features/features_cpu.h>
|
||||
#if defined(__clang__) && (defined(__SCE__) || defined(_MSC_VER))
|
||||
/* Clang's immintrin.h for PlayStation and clang-cl only declares the
|
||||
* intrinsics of ISAs enabled for the whole build, so per-function
|
||||
* targets cannot reach them; build a tier only when the baseline has it. */
|
||||
#ifdef __AVX2__
|
||||
#define STATE_MANAGER_HAVE_AVX2_SCAN 1
|
||||
#endif
|
||||
#if defined(__AVX512F__) && defined(__AVX512BW__)
|
||||
#define STATE_MANAGER_HAVE_AVX512_SCAN 1
|
||||
#endif
|
||||
#else
|
||||
#define STATE_MANAGER_HAVE_AVX2_SCAN 1
|
||||
/* AVX-512BW intrinsics need GCC 5 or Clang 4. RETRO_SIMD_AVX512 promises
|
||||
* BW, so the flag alone gates the scanner at runtime. */
|
||||
@@ -86,6 +97,7 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Tail padding on each block, in bytes. Must be >= the widest vector load
|
||||
* find_change() or find_same() can issue (64 for AVX-512). */
|
||||
|
||||
Reference in new issue
Block a user