Skip to content

Commit d155c3c

Browse files
committed
ARM NEON sign_minmax function
1 parent 4dc2d01 commit d155c3c

File tree

4 files changed

+128
-4
lines changed

4 files changed

+128
-4
lines changed

include/private/dsp/arch/arm/neon-d32/search/minmax.h

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,129 @@ namespace lsp
420420

421421
#undef SEL_NONE
422422
#undef SEL_ABS
423+
#undef MINMAX2_SEARCH_CORE
424+
425+
void sign_minmax(const float *src, size_t count, float *min, float *max)
426+
{
427+
ARCH_ARM_ASM(
428+
__ASM_EMIT("veor q0, q0") \
429+
__ASM_EMIT("veor q1, q0") \
430+
__ASM_EMIT("cmp %[count], #0") \
431+
__ASM_EMIT("bls 8f") \
432+
__ASM_EMIT("vld1.32 {d0[], d1[]}, [%[src]]") /* q0 = min */ \
433+
__ASM_EMIT("vabs.f32 q2, q0") /* q2 = abs(min) */ \
434+
__ASM_EMIT("vmov q1, q0") /* q1 = max */ \
435+
__ASM_EMIT("vmov q3, q2") /* q3 = abs(max) */ \
436+
__ASM_EMIT("subs %[count], #16") \
437+
__ASM_EMIT("blt 2f") \
438+
/* x16 blocks */ \
439+
__ASM_EMIT("1:") \
440+
__ASM_EMIT("vldm %[src]!, {q8-q11}") /* q8 = x0, q9 = x1, q10 = x2, q11 = x3 */ \
441+
__ASM_EMIT("vabs.f32 q12, q8") /* q12 = abs(x0) */ \
442+
__ASM_EMIT("vabs.f32 q13, q9") /* q13 = abs(x1) */ \
443+
__ASM_EMIT("vabs.f32 q14, q10") /* q14 = abs(x2) */ \
444+
__ASM_EMIT("vabs.f32 q15, q11") /* q15 = abs(x3) */ \
445+
__ASM_EMIT("vclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
446+
__ASM_EMIT("vcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
447+
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
448+
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
449+
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
450+
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
451+
__ASM_EMIT("vclt.f32 q4, q2, q13") /* q4 = [abs(min) < abs(x1) ] */ \
452+
__ASM_EMIT("vcgt.f32 q5, q3, q13") /* q4 = [abs(max) > abs(x1) ] */ \
453+
__ASM_EMIT("vbif q0, q9, q4") /* q0 = [abs(min) < abs(x1) ] ? min : x1 */ \
454+
__ASM_EMIT("vbif q1, q9, q5") /* q1 = [abs(max) > abs(x1) ] ? res : x1 */ \
455+
__ASM_EMIT("vbif q2, q13, q4") /* q12 = [abs(min) < abs(x1) ] ? abs(min) : abs(x1) */ \
456+
__ASM_EMIT("vbif q3, q13, q5") /* q13 = [abs(max) > abs(x1) ] ? abs(max) : abs(x1) */ \
457+
__ASM_EMIT("vclt.f32 q4, q2, q14") /* q4 = [abs(min) < abs(x1) ] */ \
458+
__ASM_EMIT("vcgt.f32 q5, q3, q14") /* q4 = [abs(max) > abs(x1) ] */ \
459+
__ASM_EMIT("vbif q0, q10, q4") /* q0 = [abs(min) < abs(x2) ] ? min : x2 */ \
460+
__ASM_EMIT("vbif q1, q10, q5") /* q1 = [abs(max) > abs(x2) ] ? res : x2 */ \
461+
__ASM_EMIT("vbif q2, q14, q4") /* q12 = [abs(min) < abs(x2) ] ? abs(min) : abs(x2) */ \
462+
__ASM_EMIT("vbif q3, q14, q5") /* q13 = [abs(max) > abs(x2) ] ? abs(max) : abs(x2) */ \
463+
__ASM_EMIT("vclt.f32 q4, q2, q15") /* q4 = [abs(min) < abs(x1) ] */ \
464+
__ASM_EMIT("vcgt.f32 q5, q3, q15") /* q4 = [abs(max) > abs(x1) ] */ \
465+
__ASM_EMIT("vbif q0, q11, q4") /* q0 = [abs(min) < abs(x3) ] ? min : x3 */ \
466+
__ASM_EMIT("vbif q1, q11, q5") /* q1 = [abs(max) > abs(x3) ] ? res : x3 */ \
467+
__ASM_EMIT("vbif q2, q15, q4") /* q12 = [abs(min) < abs(x3) ] ? abs(min) : abs(x3) */ \
468+
__ASM_EMIT("vbif q3, q15, q5") /* q13 = [abs(max) > abs(x3) ] ? abs(max) : abs(x3) */ \
469+
__ASM_EMIT("subs %[count], #16") \
470+
__ASM_EMIT("bhs 1b") \
471+
__ASM_EMIT("2:") \
472+
/* x8 block */ \
473+
__ASM_EMIT("adds %[count], #8") \
474+
__ASM_EMIT("blt 4f") \
475+
__ASM_EMIT("vldm %[src]!, {q8-q9}") /* q8 = x0, q9 = x1 */ \
476+
__ASM_EMIT("vabs.f32 q12, q8") /* q12 = abs(x0) */ \
477+
__ASM_EMIT("vabs.f32 q13, q9") /* q13 = abs(x1) */ \
478+
__ASM_EMIT("vclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
479+
__ASM_EMIT("vcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
480+
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
481+
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
482+
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
483+
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
484+
__ASM_EMIT("vclt.f32 q4, q2, q13") /* q4 = [abs(min) < abs(x1) ] */ \
485+
__ASM_EMIT("vcgt.f32 q5, q3, q13") /* q4 = [abs(max) > abs(x1) ] */ \
486+
__ASM_EMIT("vbif q0, q9, q4") /* q0 = [abs(min) < abs(x1) ] ? min : x1 */ \
487+
__ASM_EMIT("vbif q1, q9, q5") /* q1 = [abs(max) > abs(x1) ] ? res : x1 */ \
488+
__ASM_EMIT("vbif q2, q13, q4") /* q12 = [abs(min) < abs(x1) ] ? abs(min) : abs(x1) */ \
489+
__ASM_EMIT("vbif q3, q13, q5") /* q13 = [abs(max) > abs(x1) ] ? abs(max) : abs(x1) */ \
490+
__ASM_EMIT("sub %[count], #8") \
491+
__ASM_EMIT("4:") \
492+
/* x4 block */ \
493+
__ASM_EMIT("adds %[count], #4") \
494+
__ASM_EMIT("blt 6f") \
495+
__ASM_EMIT("vldm %[src]!, {q8}") /* q8 = x0, q9 = x1 */ \
496+
__ASM_EMIT("vabs.f32 q12, q8") /* q12 = abs(x0) */ \
497+
__ASM_EMIT("vclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
498+
__ASM_EMIT("vcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
499+
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
500+
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
501+
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
502+
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
503+
__ASM_EMIT("sub %[count], #4") \
504+
__ASM_EMIT("6:") \
505+
__ASM_EMIT("vext.32 q8, q0, q0, #2") /* q8 = x0 */ \
506+
__ASM_EMIT("vext.32 q12, q2, q2, #2") /* q12 = abs(x0) */ \
507+
__ASM_EMIT("vclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
508+
__ASM_EMIT("vcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
509+
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
510+
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
511+
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
512+
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
513+
__ASM_EMIT("vext.32 q8, q0, q0, #1") /* q8 = x0 */ \
514+
__ASM_EMIT("vext.32 q12, q2, q2, #1") /* q12 = abs(x0) */ \
515+
__ASM_EMIT("vclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
516+
__ASM_EMIT("vcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
517+
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
518+
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
519+
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
520+
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
521+
/* x1 block */ \
522+
__ASM_EMIT("adds %[count], #3") \
523+
__ASM_EMIT("blt 8f") \
524+
__ASM_EMIT("7:") \
525+
__ASM_EMIT("vld1.32 {d16[], d17[]}, [%[src]]!") \
526+
__ASM_EMIT("vabs.f32 q12, q8") /* q12 = abs(x0) */ \
527+
__ASM_EMIT("vclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
528+
__ASM_EMIT("vcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
529+
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
530+
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
531+
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
532+
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
533+
__ASM_EMIT("subs %[count], #1") \
534+
__ASM_EMIT("bge 7b") \
535+
__ASM_EMIT("8:") \
536+
/* end */ \
537+
__ASM_EMIT("vst1.32 {d0[0]}, [%[min]]") \
538+
__ASM_EMIT("vst1.32 {d2[0]}, [%[max]]")
539+
: [count] "+r" (count), [src] "+r" (src)
540+
: [min] "r" (min), [max] "r" (max)
541+
: "cc",
542+
"q1", "q2", "q3", "q4", "q5",
543+
"q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
544+
);
545+
}
423546
} /* namespace neon_d32 */
424547
} /* namespace lsp */
425548

src/main/arm/neon-d32.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@
367367
EXPORT1(abs_minmax);
368368
EXPORT1(sign_min);
369369
EXPORT1(sign_max);
370+
EXPORT1(sign_minmax);
370371

371372
EXPORT1(min_index);
372373
EXPORT1(max_index);

src/test/ptest/search/sign_minmax.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace lsp
5454
IF_ARCH_ARM(
5555
namespace neon_d32
5656
{
57-
// void sign_minmax(const float *src, size_t count, float *min, float *max);
57+
void sign_minmax(const float *src, size_t count, float *min, float *max);
5858
}
5959
)
6060

@@ -106,7 +106,7 @@ PTEST_BEGIN("dsp.search", sign_minmax, 5, 1000)
106106
IF_ARCH_X86(CALL(sse::sign_minmax));
107107
IF_ARCH_X86(CALL(avx::sign_minmax));
108108
IF_ARCH_X86(CALL(avx512::sign_minmax));
109-
// IF_ARCH_ARM(CALL(neon_d32::sign_minmax));
109+
IF_ARCH_ARM(CALL(neon_d32::sign_minmax));
110110
// IF_ARCH_AARCH64(CALL(asimd::sign_minmax));
111111
PTEST_SEPARATOR;
112112
}

src/test/utest/search/sign_minmax.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ namespace lsp
5151
IF_ARCH_ARM(
5252
namespace neon_d32
5353
{
54-
// void sign_minmax(const float *src, size_t count, float *min, float *max);
54+
void sign_minmax(const float *src, size_t count, float *min, float *max);
5555
}
5656
)
5757

@@ -109,7 +109,7 @@ UTEST_BEGIN("dsp.search", sign_minmax)
109109
IF_ARCH_X86(CALL(sse::sign_minmax, 16));
110110
IF_ARCH_X86(CALL(avx::sign_minmax, 32));
111111
IF_ARCH_X86(CALL(avx512::sign_minmax, 64));
112-
// IF_ARCH_ARM(CALL(neon_d32::sign_minmax, 16));
112+
IF_ARCH_ARM(CALL(neon_d32::sign_minmax, 16));
113113
// IF_ARCH_AARCH64(CALL(asimd::sign_minmax, 16));
114114
}
115115
UTEST_END

0 commit comments

Comments
 (0)