Skip to content

Commit

Permalink
ARM NEON sign_minmax function
Browse files Browse the repository at this point in the history
  • Loading branch information
sadko4u committed Nov 28, 2024
1 parent 4dc2d01 commit a0367d0
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 4 deletions.
124 changes: 124 additions & 0 deletions include/private/dsp/arch/arm/neon-d32/search/minmax.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,130 @@ namespace lsp

#undef SEL_NONE
#undef SEL_ABS
#undef MINMAX2_SEARCH_CORE

void sign_minmax(const float *src, size_t count, float *min, float *max)
{
ARCH_ARM_ASM(
__ASM_EMIT("veor q0, q0") \
__ASM_EMIT("veor q1, q0") \
__ASM_EMIT("cmp %[count], #0") \
__ASM_EMIT("bls 8f") \
__ASM_EMIT("vld1.32 {d0[], d1[]}, [%[src]]") /* q0 = min */ \
__ASM_EMIT("vabs.f32 q2, q0") /* q2 = abs(min) */ \
__ASM_EMIT("vmov q1, q0") /* q1 = max */ \
__ASM_EMIT("vmov q3, q2") /* q3 = abs(max) */ \
__ASM_EMIT("subs %[count], #16") \
__ASM_EMIT("blt 2f") \
/* x16 blocks */ \
__ASM_EMIT("1:") \
__ASM_EMIT("vldm %[src]!, {q8-q11}") /* q8 = x0, q9 = x1, q10 = x2, q11 = x3 */ \
__ASM_EMIT("vabs.f32 q12, q8") /* q12 = abs(x0) */ \
__ASM_EMIT("vabs.f32 q13, q9") /* q13 = abs(x1) */ \
__ASM_EMIT("vabs.f32 q14, q10") /* q14 = abs(x2) */ \
__ASM_EMIT("vabs.f32 q15, q11") /* q15 = abs(x3) */ \
__ASM_EMIT("fclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
__ASM_EMIT("fcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
__ASM_EMIT("fclt.f32 q4, q2, q13") /* q4 = [abs(min) < abs(x1) ] */ \
__ASM_EMIT("fcgt.f32 q5, q3, q13") /* q4 = [abs(max) > abs(x1) ] */ \
__ASM_EMIT("vbif q0, q9, q4") /* q0 = [abs(min) < abs(x1) ] ? min : x1 */ \
__ASM_EMIT("vbif q1, q9, q5") /* q1 = [abs(max) > abs(x1) ] ? res : x1 */ \
__ASM_EMIT("vbif q2, q13, q4") /* q12 = [abs(min) < abs(x1) ] ? abs(min) : abs(x1) */ \
__ASM_EMIT("vbif q3, q13, q5") /* q13 = [abs(max) > abs(x1) ] ? abs(max) : abs(x1) */ \
__ASM_EMIT("fclt.f32 q4, q2, q14") /* q4 = [abs(min) < abs(x1) ] */ \
__ASM_EMIT("fcgt.f32 q5, q3, q14") /* q4 = [abs(max) > abs(x1) ] */ \
__ASM_EMIT("vbif q0, q10, q4") /* q0 = [abs(min) < abs(x2) ] ? min : x2 */ \
__ASM_EMIT("vbif q1, q10, q5") /* q1 = [abs(max) > abs(x2) ] ? res : x2 */ \
__ASM_EMIT("vbif q2, q14, q4") /* q12 = [abs(min) < abs(x2) ] ? abs(min) : abs(x2) */ \
__ASM_EMIT("vbif q3, q14, q5") /* q13 = [abs(max) > abs(x2) ] ? abs(max) : abs(x2) */ \
__ASM_EMIT("fclt.f32 q4, q2, q15") /* q4 = [abs(min) < abs(x1) ] */ \
__ASM_EMIT("fcgt.f32 q5, q3, q15") /* q4 = [abs(max) > abs(x1) ] */ \
__ASM_EMIT("vbif q0, q11, q4") /* q0 = [abs(min) < abs(x3) ] ? min : x3 */ \
__ASM_EMIT("vbif q1, q11, q5") /* q1 = [abs(max) > abs(x3) ] ? res : x3 */ \
__ASM_EMIT("vbif q2, q15, q4") /* q12 = [abs(min) < abs(x3) ] ? abs(min) : abs(x3) */ \
__ASM_EMIT("vbif q3, q15, q5") /* q13 = [abs(max) > abs(x3) ] ? abs(max) : abs(x3) */ \
__ASM_EMIT("subs %[count], #16") \
__ASM_EMIT("bhs 1b") \
__ASM_EMIT("2:") \
/* x8 block */ \
__ASM_EMIT("adds %[count], #8") \
__ASM_EMIT("blt 4f") \
__ASM_EMIT("vldm %[src]!, {q8-q9}") /* q8 = x0, q9 = x1 */ \
__ASM_EMIT("vabs.f32 q12, q8") /* q12 = abs(x0) */ \
__ASM_EMIT("vabs.f32 q13, q9") /* q13 = abs(x1) */ \
__ASM_EMIT("fclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
__ASM_EMIT("fcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
__ASM_EMIT("fclt.f32 q4, q2, q13") /* q4 = [abs(min) < abs(x1) ] */ \
__ASM_EMIT("fcgt.f32 q5, q3, q13") /* q4 = [abs(max) > abs(x1) ] */ \
__ASM_EMIT("vbif q0, q9, q4") /* q0 = [abs(min) < abs(x1) ] ? min : x1 */ \
__ASM_EMIT("vbif q1, q9, q5") /* q1 = [abs(max) > abs(x1) ] ? res : x1 */ \
__ASM_EMIT("vbif q2, q13, q4") /* q12 = [abs(min) < abs(x1) ] ? abs(min) : abs(x1) */ \
__ASM_EMIT("vbif q3, q13, q5") /* q13 = [abs(max) > abs(x1) ] ? abs(max) : abs(x1) */ \
__ASM_EMIT("sub %[count], #8") \
__ASM_EMIT("4:") \
/* x4 block */ \
__ASM_EMIT("adds %[count], #4") \
__ASM_EMIT("blt 6f") \
__ASM_EMIT("vldm %[src]!, {q8}") /* q8 = x0, q9 = x1 */ \
__ASM_EMIT("vabs.f32 q12, q8") /* q12 = abs(x0) */ \
__ASM_EMIT("fclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
__ASM_EMIT("fcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
__ASM_EMIT("sub %[count], #4") \
__ASM_EMIT("6:") \
__ASM_EMIT("vext.32 q8, q0, q0, #2") /* q8 = x0 */ \
__ASM_EMIT("vext.32 q12, q2, q2, #2") /* q12 = abs(x0) */ \
__ASM_EMIT("fclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
__ASM_EMIT("fcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
__ASM_EMIT("vext.32 q8, q0, q0, #1") /* q8 = x0 */ \
__ASM_EMIT("vext.32 q12, q2, q2, #1") /* q12 = abs(x0) */ \
__ASM_EMIT(OP " q4, q2, q12") /* q4 = [abs(res0) <=> abs(x0) ] */ \
__ASM_EMIT("fclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
__ASM_EMIT("fcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
/* x1 block */ \
__ASM_EMIT("adds %[count], #3") \
__ASM_EMIT("blt 8f") \
__ASM_EMIT("7:") \
__ASM_EMIT("vld1.32 {d16[], d17[]}, [%[src]]!") \
__ASM_EMIT("vabs.f32 q12, q8") /* q12 = abs(x0) */ \
__ASM_EMIT("fclt.f32 q4, q2, q12") /* q4 = [abs(min) < abs(x0) ] */ \
__ASM_EMIT("fcgt.f32 q5, q3, q12") /* q4 = [abs(max) > abs(x0) ] */ \
__ASM_EMIT("vbif q0, q8, q4") /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
__ASM_EMIT("vbif q1, q8, q5") /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
__ASM_EMIT("vbif q2, q12, q4") /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
__ASM_EMIT("vbif q3, q12, q5") /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
__ASM_EMIT("subs %[count], #1") \
__ASM_EMIT("bge 7b") \
__ASM_EMIT("8:") \
/* end */ \
__ASM_EMIT("vst1.32 {d0[0]}, [%[min]]") \
__ASM_EMIT("vst1.32 {d2[0]}, [%[max]]")
: [count] "+r" (count), [src] "+r" (src)
: [min] "r" (min), [max] "r" (max)
: "cc",
"q1", "q2", "q3", "q4", "q5",
"q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
);
}
} /* namespace neon_d32 */
} /* namespace lsp */

Expand Down
1 change: 1 addition & 0 deletions src/main/arm/neon-d32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@
EXPORT1(abs_minmax);
EXPORT1(sign_min);
EXPORT1(sign_max);
EXPORT1(sign_minmax);

EXPORT1(min_index);
EXPORT1(max_index);
Expand Down
4 changes: 2 additions & 2 deletions src/test/ptest/search/sign_minmax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace lsp
IF_ARCH_ARM(
namespace neon_d32
{
// void sign_minmax(const float *src, size_t count, float *min, float *max);
void sign_minmax(const float *src, size_t count, float *min, float *max);
}
)

Expand Down Expand Up @@ -106,7 +106,7 @@ PTEST_BEGIN("dsp.search", sign_minmax, 5, 1000)
IF_ARCH_X86(CALL(sse::sign_minmax));
IF_ARCH_X86(CALL(avx::sign_minmax));
IF_ARCH_X86(CALL(avx512::sign_minmax));
// IF_ARCH_ARM(CALL(neon_d32::sign_minmax));
IF_ARCH_ARM(CALL(neon_d32::sign_minmax));
// IF_ARCH_AARCH64(CALL(asimd::sign_minmax));
PTEST_SEPARATOR;
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/utest/search/sign_minmax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace lsp
IF_ARCH_ARM(
namespace neon_d32
{
// void sign_minmax(const float *src, size_t count, float *min, float *max);
void sign_minmax(const float *src, size_t count, float *min, float *max);
}
)

Expand Down Expand Up @@ -109,7 +109,7 @@ UTEST_BEGIN("dsp.search", sign_minmax)
IF_ARCH_X86(CALL(sse::sign_minmax, 16));
IF_ARCH_X86(CALL(avx::sign_minmax, 32));
IF_ARCH_X86(CALL(avx512::sign_minmax, 64));
// IF_ARCH_ARM(CALL(neon_d32::sign_minmax, 16));
IF_ARCH_ARM(CALL(neon_d32::sign_minmax, 16));
// IF_ARCH_AARCH64(CALL(asimd::sign_minmax, 16));
}
UTEST_END
Expand Down

0 comments on commit a0367d0

Please sign in to comment.