mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
GS/arm64: fix MSVC C2995 in the __builtin_shufflevector shim
MSVC's arm64 <arm64_neon.h> defines int32x4_t, float32x4_t and int16x8_t as typedefs of the same __n128 type, so the shim's separate int32x4_t and float32x4_t gsneon_shuffle overloads collapsed to an identical signature and cl.exe rejected the second as a redefinition (error C2995) -- the first time the shim actually reached the MSVC compile. Drop the float32x4_t overload (and its gsneon_pickf helper). A single 4-lane/32-bit overload now serves both int and float shuffles: a lane copy is bit-preserving, so the s32 lane ops reproduce the exact float result, and float32x4_t is literally the same __n128 type on MSVC. The 8-lane/16-bit overload is distinguished by arity and is unaffected. clang/clang-cl keep __builtin_shufflevector, so the whole shim block is #if'd out there -- this only changes the pure-MSVC path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5cbcadaa1e
commit
7c48e1f939
@@ -25,14 +25,6 @@ static __forceinline int32_t gsneon_pick(int32x4_t a, int32x4_t b)
|
||||
return vgetq_lane_s32(b, I - 4);
|
||||
}
|
||||
template <int I>
|
||||
static __forceinline float32_t gsneon_pickf(float32x4_t a, float32x4_t b)
|
||||
{
|
||||
if constexpr (I < 4)
|
||||
return vgetq_lane_f32(a, I);
|
||||
else
|
||||
return vgetq_lane_f32(b, I - 4);
|
||||
}
|
||||
template <int I>
|
||||
static __forceinline int16_t gsneon_pick16(int16x8_t a, int16x8_t b)
|
||||
{
|
||||
if constexpr (I < 8)
|
||||
@@ -41,6 +33,14 @@ static __forceinline int16_t gsneon_pick16(int16x8_t a, int16x8_t b)
|
||||
return vgetq_lane_s16(b, I - 8);
|
||||
}
|
||||
|
||||
// MSVC's arm64 <arm64_neon.h> makes int32x4_t, float32x4_t and int16x8_t all
|
||||
// typedefs of the same underlying __n128, so we can't provide distinct
|
||||
// int32x4_t/float32x4_t overloads -- they'd have an identical signature and cl
|
||||
// rejects the second as a redefinition (C2995). Keep a single 4-lane (32-bit)
|
||||
// overload and a single 8-lane (16-bit) overload, distinguished only by arity.
|
||||
// A lane copy is bit-preserving, so routing float32x4_t shuffles (the three
|
||||
// GSVector4 call sites) through the s32 lane ops reproduces the exact float
|
||||
// result -- float32x4_t is the very same __n128 type here.
|
||||
template <int I0, int I1, int I2, int I3>
|
||||
static __forceinline int32x4_t gsneon_shuffle(int32x4_t a, int32x4_t b)
|
||||
{
|
||||
@@ -51,16 +51,6 @@ static __forceinline int32x4_t gsneon_shuffle(int32x4_t a, int32x4_t b)
|
||||
r = vsetq_lane_s32(gsneon_pick<I3>(a, b), r, 3);
|
||||
return r;
|
||||
}
|
||||
template <int I0, int I1, int I2, int I3>
|
||||
static __forceinline float32x4_t gsneon_shuffle(float32x4_t a, float32x4_t b)
|
||||
{
|
||||
float32x4_t r = vdupq_n_f32(0.0f);
|
||||
r = vsetq_lane_f32(gsneon_pickf<I0>(a, b), r, 0);
|
||||
r = vsetq_lane_f32(gsneon_pickf<I1>(a, b), r, 1);
|
||||
r = vsetq_lane_f32(gsneon_pickf<I2>(a, b), r, 2);
|
||||
r = vsetq_lane_f32(gsneon_pickf<I3>(a, b), r, 3);
|
||||
return r;
|
||||
}
|
||||
template <int I0, int I1, int I2, int I3, int I4, int I5, int I6, int I7>
|
||||
static __forceinline int16x8_t gsneon_shuffle(int16x8_t a, int16x8_t b)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user