[x265] [PATCH 2 of 2] asm: ARM NEON version of DCT[8x8]

Min Chen chenm003 at 163.com
Thu May 12 19:50:06 CEST 2016


# HG changeset patch
# User Min Chen <min.chen at multicorewareinc.com>
# Date 1463075384 18000
# Node ID 98fdbf00b01eef722dd804e676c0c81429873cca
# Parent  f880db0a9a9b352077014aa69571d3169a37a2fc
asm: ARM NEON version of DCT[8x8]
---
 source/common/arm/asm-primitives.cpp |    1 +
 source/common/arm/dct-a.S            |  278 ++++++++++++++++++++++++++++++++++
 source/common/arm/dct8.h             |    1 +
 3 files changed, 280 insertions(+), 0 deletions(-)

diff -r f880db0a9a9b -r 98fdbf00b01e source/common/arm/asm-primitives.cpp
--- a/source/common/arm/asm-primitives.cpp	Thu May 12 12:49:41 2016 -0500
+++ b/source/common/arm/asm-primitives.cpp	Thu May 12 12:49:44 2016 -0500
@@ -930,6 +930,7 @@
         p.chroma[X265_CSP_I444].pu[LUMA_48x64].filter_vsp = PFX(interp_4tap_vert_sp_48x64_neon);
 
         p.cu[BLOCK_4x4].dct = PFX(dct_4x4_neon);
+        p.cu[BLOCK_8x8].dct = PFX(dct_8x8_neon);
     }
     if (cpuMask & X265_CPU_ARMV6)
     {
diff -r f880db0a9a9b -r 98fdbf00b01e source/common/arm/dct-a.S
--- a/source/common/arm/dct-a.S	Thu May 12 12:49:41 2016 -0500
+++ b/source/common/arm/dct-a.S	Thu May 12 12:49:44 2016 -0500
@@ -120,3 +120,281 @@
     bx              lr
 endfunc
 
+.align 4
+ctr4:
+.word 83            // d0[0] = 83
+.word 36            // d0[1] = 36
+ctr8:
+.word 75            // d1[0] = 75
+.word 89            // d1[1] = 89
+.word 18            // d2[0] = 18
+.word 50            // d2[1] = 50
+
+
+/* uses registers q4 - q7 for temp values */
+.macro tr4 r0, r1, r2, r3
+    vsub.s32    q8, \r0, \r3    // EO0
+    vadd.s32    q9, \r0, \r3    // EE0
+    vadd.s32    q10, \r1, \r2   // EE1
+    vsub.s32    q11, \r1, \r2   // EO1
+
+    vmul.s32    \r1, q8, d0[0]  // 83 * EO0
+    vmul.s32    \r3, q8, d0[1]  // 36 * EO0
+    vshl.s32    q9, q9, #6      // 64 * EE0
+    vshl.s32    q10, q10, #6    // 64 * EE1
+    vmla.s32    \r1, q11, d0[1] // 83 * EO0 + 36 * EO1
+    vmls.s32    \r3, q11, d0[0] // 36 * EO0 - 83 * EO1
+    vadd.s32    \r0, q9, q10    // 64 * (EE0 + EE1)
+    vsub.s32    \r2, q9, q10    // 64 * (EE0 - EE1)
+.endm
+
+
+.macro tr8 r0, r1, r2, r3
+    vmul.s32  q12, \r0, d1[1]   //  89 * src1
+    vmul.s32  q13, \r0, d1[0]   //  75 * src1
+    vmul.s32  q14, \r0, d2[1]   //  50 * src1
+    vmul.s32  q15, \r0, d2[0]   //  18 * src1
+
+    vmla.s32  q12, \r1, d1[0]   //  75 * src3
+    vmls.s32  q13, \r1, d2[0]   // -18 * src3
+    vmls.s32  q14, \r1, d1[1]   // -89 * src3
+    vmls.s32  q15, \r1, d2[1]   // -50 * src3
+
+    vmla.s32  q12, \r2, d2[1]   //  50 * src5
+    vmls.s32  q13, \r2, d1[1]   // -89 * src5
+    vmla.s32  q14, \r2, d2[0]   //  18 * src5
+    vmla.s32  q15, \r2, d1[0]   //  75 * src5
+
+    vmla.s32  q12, \r3, d2[0]   //  18 * src7
+    vmls.s32  q13, \r3, d2[1]   // -50 * src7
+    vmla.s32  q14, \r3, d1[0]   //  75 * src7
+    vmls.s32  q15, \r3, d1[1]   // -89 * src7
+.endm
+
+
+// TODO: in the DCT-2D stage, I spending 4x8=32 LD/ST operators because I haven't temporary buffer
+/* void dct8_c(const int16_t* src, int16_t* dst, intptr_t srcStride) */
+function x265_dct_8x8_neon
+    vpush {q4-q7}
+
+    mov r2, r2, lsl #1
+
+    adr r3, ctr4
+    vld1.16 {d0-d2}, [r3]
+    mov r3, r1
+
+    // DCT-1D
+    // top half
+    vld1.16 {q12}, [r0], r2
+    vld1.16 {q13}, [r0], r2
+    vld1.16 {q14}, [r0], r2
+    vld1.16 {q15}, [r0], r2
+
+    TRANSPOSE4x4x2_16 d24, d26, d28, d30,  d25, d27, d29, d31
+
+    // |--|
+    // |24|
+    // |26|
+    // |28|
+    // |30|
+    // |25|
+    // |27|
+    // |29|
+    // |31|
+    // |--|
+
+    vaddl.s16 q4, d28, d27
+    vaddl.s16 q5, d30, d25
+    vaddl.s16 q2, d24, d31
+    vaddl.s16 q3, d26, d29
+
+    tr4 q2, q3, q4, q5
+
+    vqrshrn.s32 d20, q3, 2
+    vqrshrn.s32 d16, q2, 2
+    vqrshrn.s32 d17, q4, 2
+    vqrshrn.s32 d21, q5, 2
+
+    vsubl.s16 q2, d24, d31
+    vsubl.s16 q3, d26, d29
+    vsubl.s16 q4, d28, d27
+    vsubl.s16 q5, d30, d25
+
+    tr8 q2, q3, q4, q5
+
+    vqrshrn.s32 d18, q12, 2
+    vqrshrn.s32 d22, q13, 2
+    vqrshrn.s32 d19, q14, 2
+    vqrshrn.s32 d23, q15, 2
+
+    vstm r1!, {d16-d23]
+
+    // bottom half
+    vld1.16 {q12}, [r0], r2
+    vld1.16 {q13}, [r0], r2
+    vld1.16 {q14}, [r0], r2
+    vld1.16 {q15}, [r0], r2
+    mov r2, #8*2
+
+    TRANSPOSE4x4x2_16 d24, d26, d28, d30,  d25, d27, d29, d31
+
+    // |--|
+    // |24|
+    // |26|
+    // |28|
+    // |30|
+    // |25|
+    // |27|
+    // |29|
+    // |31|
+    // |--|
+
+    vaddl.s16 q4, d28, d27
+    vaddl.s16 q5, d30, d25
+    vaddl.s16 q2, d24, d31
+    vaddl.s16 q3, d26, d29
+
+    tr4 q2, q3, q4, q5
+
+    vqrshrn.s32 d20, q3, 2
+    vqrshrn.s32 d16, q2, 2
+    vqrshrn.s32 d17, q4, 2
+    vqrshrn.s32 d21, q5, 2
+
+    vsubl.s16 q2, d24, d31
+    vsubl.s16 q3, d26, d29
+    vsubl.s16 q4, d28, d27
+    vsubl.s16 q5, d30, d25
+
+    tr8 q2, q3, q4, q5
+
+    vqrshrn.s32 d18, q12, 2
+    vqrshrn.s32 d22, q13, 2
+    vqrshrn.s32 d19, q14, 2
+    vqrshrn.s32 d23, q15, 2
+
+    vstm r1, {d16-d23]
+    mov r1, r3
+
+    // DCT-2D
+    // left half
+    vld1.16 {d24}, [r1], r2
+    vld1.16 {d26}, [r1], r2
+    vld1.16 {d28}, [r1], r2
+    vld1.16 {d30}, [r1], r2
+    vld1.16 {d25}, [r1], r2
+    vld1.16 {d27}, [r1], r2
+    vld1.16 {d29}, [r1], r2
+    vld1.16 {d31}, [r1], r2
+    mov r1, r3
+
+    TRANSPOSE4x4x2_16 d24, d26, d28, d30,  d25, d27, d29, d31
+
+    // |--|
+    // |24|
+    // |26|
+    // |28|
+    // |30|
+    // |25|
+    // |27|
+    // |29|
+    // |31|
+    // |--|
+
+    vaddl.s16 q4, d28, d27
+    vaddl.s16 q5, d30, d25
+    vaddl.s16 q2, d24, d31
+    vaddl.s16 q3, d26, d29
+
+    tr4 q2, q3, q4, q5
+
+    vqrshrn.s32 d18, q3, 9
+    vqrshrn.s32 d16, q2, 9
+    vqrshrn.s32 d20, q4, 9
+    vqrshrn.s32 d22, q5, 9
+
+    vsubl.s16 q2, d24, d31
+    vsubl.s16 q3, d26, d29
+    vsubl.s16 q4, d28, d27
+    vsubl.s16 q5, d30, d25
+
+    tr8 q2, q3, q4, q5
+
+    vqrshrn.s32 d17, q12, 9
+    vqrshrn.s32 d19, q13, 9
+    vqrshrn.s32 d21, q14, 9
+    vqrshrn.s32 d23, q15, 9
+
+    add r3, #8
+    vst1.16 {d16}, [r1], r2
+    vst1.16 {d17}, [r1], r2
+    vst1.16 {d18}, [r1], r2
+    vst1.16 {d19}, [r1], r2
+    vst1.16 {d20}, [r1], r2
+    vst1.16 {d21}, [r1], r2
+    vst1.16 {d22}, [r1], r2
+    vst1.16 {d23}, [r1], r2
+    mov r1, r3
+
+
+    // right half
+    vld1.16 {d24}, [r1], r2
+    vld1.16 {d26}, [r1], r2
+    vld1.16 {d28}, [r1], r2
+    vld1.16 {d30}, [r1], r2
+    vld1.16 {d25}, [r1], r2
+    vld1.16 {d27}, [r1], r2
+    vld1.16 {d29}, [r1], r2
+    vld1.16 {d31}, [r1], r2
+    mov r1, r3
+
+    TRANSPOSE4x4x2_16 d24, d26, d28, d30,  d25, d27, d29, d31
+
+    // |--|
+    // |24|
+    // |26|
+    // |28|
+    // |30|
+    // |25|
+    // |27|
+    // |29|
+    // |31|
+    // |--|
+
+    vaddl.s16 q4, d28, d27
+    vaddl.s16 q5, d30, d25
+    vaddl.s16 q2, d24, d31
+    vaddl.s16 q3, d26, d29
+
+    tr4 q2, q3, q4, q5
+
+    vqrshrn.s32 d18, q3, 9
+    vqrshrn.s32 d16, q2, 9
+    vqrshrn.s32 d20, q4, 9
+    vqrshrn.s32 d22, q5, 9
+
+    vsubl.s16 q2, d24, d31
+    vsubl.s16 q3, d26, d29
+    vsubl.s16 q4, d28, d27
+    vsubl.s16 q5, d30, d25
+
+    tr8 q2, q3, q4, q5
+
+    vqrshrn.s32 d17, q12, 9
+    vqrshrn.s32 d19, q13, 9
+    vqrshrn.s32 d21, q14, 9
+    vqrshrn.s32 d23, q15, 9
+
+    vst1.16 {d16}, [r1], r2
+    vst1.16 {d17}, [r1], r2
+    vst1.16 {d18}, [r1], r2
+    vst1.16 {d19}, [r1], r2
+    vst1.16 {d20}, [r1], r2
+    vst1.16 {d21}, [r1], r2
+    vst1.16 {d22}, [r1], r2
+    vst1.16 {d23}, [r1], r2
+
+    vpop {q4-q7}
+    bx lr
+endfunc
+
diff -r f880db0a9a9b -r 98fdbf00b01e source/common/arm/dct8.h
--- a/source/common/arm/dct8.h	Thu May 12 12:49:41 2016 -0500
+++ b/source/common/arm/dct8.h	Thu May 12 12:49:44 2016 -0500
@@ -26,5 +26,6 @@
 #define X265_DCT8_ARM_H
 
 void PFX(dct_4x4_neon)(const int16_t* src, int16_t* dst, intptr_t srcStride);
+void PFX(dct_8x8_neon)(const int16_t* src, int16_t* dst, intptr_t srcStride);
 
 #endif // ifndef X265_DCT8_ARM_H



More information about the x265-devel mailing list