Commit fa9c4149 authored by Evan Nemerson's avatar Evan Nemerson

sse4.2, neon/c{ge,gt,le,lt}: some improved 64-bit comparisons

These are based on some StackOverflow answers linked to in this here:
https://stackoverflow.com/questions/65441496/what-is-the-most-efficient-way-to-do-unsigned-64-bit-comparison-on-sse2
parent 8cd136a4
...@@ -209,6 +209,8 @@ simde_uint64x2_t ...@@ -209,6 +209,8 @@ simde_uint64x2_t
simde_vcgeq_s64(simde_int64x2_t a, simde_int64x2_t b) { simde_vcgeq_s64(simde_int64x2_t a, simde_int64x2_t b) {
#if defined(SIMDE_ARM_NEON_A64V8_NATIVE) #if defined(SIMDE_ARM_NEON_A64V8_NATIVE)
return vcgeq_s64(a, b); return vcgeq_s64(a, b);
#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE)
return vreinterpretq_u64_s32(vmvnq_s32(vreinterpretq_s32_s64(vshrq_n_s64(vqsubq_s64(a, b), 63))));
#elif defined(SIMDE_X86_SSE4_2_NATIVE) #elif defined(SIMDE_X86_SSE4_2_NATIVE)
return _mm_or_si128(_mm_cmpgt_epi64(a, b), _mm_cmpeq_epi64(a, b)); return _mm_or_si128(_mm_cmpgt_epi64(a, b), _mm_cmpeq_epi64(a, b));
#elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE)
......
...@@ -211,8 +211,15 @@ simde_uint64x2_t ...@@ -211,8 +211,15 @@ simde_uint64x2_t
simde_vcgtq_s64(simde_int64x2_t a, simde_int64x2_t b) { simde_vcgtq_s64(simde_int64x2_t a, simde_int64x2_t b) {
#if defined(SIMDE_ARM_NEON_A64V8_NATIVE) #if defined(SIMDE_ARM_NEON_A64V8_NATIVE)
return vcgtq_s64(a, b); return vcgtq_s64(a, b);
#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE)
return vreinterpretq_u64_s64(vshrq_n_s64(vqsubq_s64(b, a), 63));
#elif defined(SIMDE_X86_SSE4_2_NATIVE) #elif defined(SIMDE_X86_SSE4_2_NATIVE)
return _mm_cmpgt_epi64(a, b); return _mm_cmpgt_epi64(a, b);
#elif defined(SIMDE_X86_SSE2_NATIVE)
/* https://stackoverflow.com/a/65175746/501126 */
__m128i r = _mm_and_si128(_mm_cmpeq_epi32(a, b), _mm_sub_epi64(b, a));
r = _mm_or_si128(r, _mm_cmpgt_epi32(a, b));
return _mm_shuffle_epi32(r, _MM_SHUFFLE(3,3,1,1));
#elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE)
return HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long), vec_cmpgt(a, b)); return HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long), vec_cmpgt(a, b));
#else #else
......
...@@ -209,6 +209,8 @@ simde_uint64x2_t ...@@ -209,6 +209,8 @@ simde_uint64x2_t
simde_vcleq_s64(simde_int64x2_t a, simde_int64x2_t b) { simde_vcleq_s64(simde_int64x2_t a, simde_int64x2_t b) {
#if defined(SIMDE_ARM_NEON_A64V8_NATIVE) #if defined(SIMDE_ARM_NEON_A64V8_NATIVE)
return vcleq_s64(a, b); return vcleq_s64(a, b);
#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE)
return vreinterpretq_u64_s32(vmvnq_s32(vreinterpretq_s32_s64(vshrq_n_s64(vqsubq_s64(b, a), 63))));
#elif defined(SIMDE_X86_SSE4_2_NATIVE) #elif defined(SIMDE_X86_SSE4_2_NATIVE)
return _mm_or_si128(_mm_cmpgt_epi64(b, a), _mm_cmpeq_epi64(a, b)); return _mm_or_si128(_mm_cmpgt_epi64(b, a), _mm_cmpeq_epi64(a, b));
#elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE)
......
...@@ -211,6 +211,8 @@ simde_uint64x2_t ...@@ -211,6 +211,8 @@ simde_uint64x2_t
simde_vcltq_s64(simde_int64x2_t a, simde_int64x2_t b) { simde_vcltq_s64(simde_int64x2_t a, simde_int64x2_t b) {
#if defined(SIMDE_ARM_NEON_A64V8_NATIVE) #if defined(SIMDE_ARM_NEON_A64V8_NATIVE)
return vcltq_s64(a, b); return vcltq_s64(a, b);
#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE)
return vreinterpretq_u64_s64(vshrq_n_s64(vqsubq_s64(a, b), 63));
#elif defined(SIMDE_X86_SSE4_2_NATIVE) #elif defined(SIMDE_X86_SSE4_2_NATIVE)
return _mm_cmpgt_epi64(b, a); return _mm_cmpgt_epi64(b, a);
#elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE)
......
...@@ -136,8 +136,13 @@ int simde_mm_cmpestrz (simde__m128i a, int la, simde__m128i b, int lb, const int ...@@ -136,8 +136,13 @@ int simde_mm_cmpestrz (simde__m128i a, int la, simde__m128i b, int lb, const int
SIMDE_FUNCTION_ATTRIBUTES SIMDE_FUNCTION_ATTRIBUTES
simde__m128i simde__m128i
simde_mm_cmpgt_epi64 (simde__m128i a, simde__m128i b) { simde_mm_cmpgt_epi64 (simde__m128i a, simde__m128i b) {
#if defined(SIMDE_X86_SSE4_2_NATIVE) #if defined(SIMDE_X86_SSE4_2_NATIVE) && 0
return _mm_cmpgt_epi64(a, b); return _mm_cmpgt_epi64(a, b);
#elif defined(SIMDE_X86_SSE2_NATIVE)
/* https://stackoverflow.com/a/65175746/501126 */
__m128i r = _mm_and_si128(_mm_cmpeq_epi32(a, b), _mm_sub_epi64(b, a));
r = _mm_or_si128(r, _mm_cmpgt_epi32(a, b));
return _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1));
#else #else
simde__m128i_private simde__m128i_private
r_, r_,
...@@ -147,31 +152,8 @@ simde_mm_cmpgt_epi64 (simde__m128i a, simde__m128i b) { ...@@ -147,31 +152,8 @@ simde_mm_cmpgt_epi64 (simde__m128i a, simde__m128i b) {
#if defined(SIMDE_ARM_NEON_A64V8_NATIVE) #if defined(SIMDE_ARM_NEON_A64V8_NATIVE)
r_.neon_u64 = vcgtq_s64(a_.neon_i64, b_.neon_i64); r_.neon_u64 = vcgtq_s64(a_.neon_i64, b_.neon_i64);
#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE)
// ARMv7 lacks vcgtq_s64. /* https://stackoverflow.com/a/65223269/501126 */
// This is based off of Clang's SSE2 polyfill: r_.neon_i64 = vshrq_n_s64(vqsubq_s64(b_.neon_i64, a_.neon_i64), 63);
// (a > b) -> ((a_hi > b_hi) || (a_lo > b_lo && a_hi == b_hi))
// Mask the sign bit out since we need a signed AND an unsigned comparison
// and it is ugly to try and split them.
int32x4_t mask = vreinterpretq_s32_s64(vdupq_n_s64(0x80000000ull));
int32x4_t a_mask = veorq_s32(a_.neon_i32, mask);
int32x4_t b_mask = veorq_s32(b_.neon_i32, mask);
// Check if a > b
int64x2_t greater = vreinterpretq_s64_u32(vcgtq_s32(a_mask, b_mask));
// Copy upper mask to lower mask
// a_hi > b_hi
int64x2_t gt_hi = vshrq_n_s64(greater, 63);
// Copy lower mask to upper mask
// a_lo > b_lo
int64x2_t gt_lo = vsliq_n_s64(greater, greater, 32);
// Compare for equality
int64x2_t equal = vreinterpretq_s64_u32(vceqq_s32(a_mask, b_mask));
// Copy upper mask to lower mask
// a_hi == b_hi
int64x2_t eq_hi = vshrq_n_s64(equal, 63);
// a_hi > b_hi || (a_lo > b_lo && a_hi == b_hi)
int64x2_t ret = vorrq_s64(gt_hi, vandq_s64(gt_lo, eq_hi));
r_.neon_i64 = ret;
#elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE)
r_.altivec_u64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long), vec_cmpgt(a_.altivec_i64, b_.altivec_i64)); r_.altivec_u64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long), vec_cmpgt(a_.altivec_i64, b_.altivec_i64));
#elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment