shithub: dav1d

Download patch

ref: 80aa7823fbbfe5e3b8c1aeba2dad9234f5225d30
parent: f57189e30080c6d5a0389533e722f6f2bac20272
author: Martin Storsjö <martin@martin.st>
date: Thu Aug 27 19:35:43 EDT 2020

arm32: mc: NEON implementation of avg/mask/w_avg for 16 bpc

                      Cortex A7       A8       A9      A53      A72      A73
avg_w4_16bpc_neon:        131.4     81.8    117.3    111.0     50.9     58.8
avg_w8_16bpc_neon:        291.9    173.1    293.1    230.9    114.7    128.8
avg_w16_16bpc_neon:       803.3    480.1    821.4    645.8    345.7    384.9
avg_w32_16bpc_neon:      3350.0   1833.1   3188.1   2343.5   1343.9   1500.6
avg_w64_16bpc_neon:      8185.9   4390.6  10448.2   6078.8   3303.6   3466.7
avg_w128_16bpc_neon:    22384.3  10901.2  33721.9  16782.7   8165.1   8416.5
w_avg_w4_16bpc_neon:      251.3    165.8    203.9    158.3     99.6    106.9
w_avg_w8_16bpc_neon:      638.4    427.8    555.7    365.1    283.2    277.4
w_avg_w16_16bpc_neon:    1912.3   1257.5   1623.4   1056.5    879.5    841.8
w_avg_w32_16bpc_neon:    7461.3   4889.6   6383.8   3966.3   3286.8   3296.8
w_avg_w64_16bpc_neon:   18689.3  11698.1  18487.3  10134.1   8156.2   7939.5
w_avg_w128_16bpc_neon:  48776.6  28989.0  53203.3  26004.1  20055.2  20049.4
mask_w4_16bpc_neon:       298.6    189.2    242.3    191.6    115.2    129.6
mask_w8_16bpc_neon:       768.6    501.5    646.1    432.4    302.9    326.8
mask_w16_16bpc_neon:     2320.5   1480.9   1873.0   1270.2    932.2    976.1
mask_w32_16bpc_neon:     9412.0   5791.9   7348.5   4875.1   3896.4   3821.1
mask_w64_16bpc_neon:    23385.9  13875.6  21383.8  12235.9   9469.2   9160.2
mask_w128_16bpc_neon:   60466.4  34762.6  61055.9  31214.0  23299.0  23324.5

For comparison, the corresponding numbers for the existing arm64
implementation:

avg_w4_16bpc_neon:                                    78.0     38.5     50.0
avg_w8_16bpc_neon:                                   198.3    105.4    117.8
avg_w16_16bpc_neon:                                  614.9    339.9    376.7
avg_w32_16bpc_neon:                                 2313.8   1391.1   1487.7
avg_w64_16bpc_neon:                                 5733.3   3269.1   3648.4
avg_w128_16bpc_neon:                               15105.9   8143.5   8970.4
w_avg_w4_16bpc_neon:                                 119.2     87.7     92.9
w_avg_w8_16bpc_neon:                                 322.9    252.3    263.5
w_avg_w16_16bpc_neon:                               1016.8    794.0    828.6
w_avg_w32_16bpc_neon:                               3910.9   3159.6   3308.3
w_avg_w64_16bpc_neon:                               9499.6   7933.9   8026.5
w_avg_w128_16bpc_neon:                             24508.3  19502.0  20389.8
mask_w4_16bpc_neon:                                  138.9     98.7    106.7
mask_w8_16bpc_neon:                                  375.5    301.1    302.7
mask_w16_16bpc_neon:                                1217.2   1064.6    954.4
mask_w32_16bpc_neon:                                4821.0   4018.4   3825.7
mask_w64_16bpc_neon:                               12262.7   9471.3   9169.7
mask_w128_16bpc_neon:                              31356.6  22657.6  23324.5

--- /dev/null
+++ b/src/arm/32/mc16.S
@@ -1,0 +1,274 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Janne Grunau
+ * Copyright © 2020, Martin Storsjo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "src/arm/asm.S"
+#include "util.S"
+
+#define PREP_BIAS 8192
+
+.macro avg d0, d00, d01, d1, d10, d11
+        vld1.16         {q0, q1}, [r2, :128]!
+        vld1.16         {q2, q3}, [r3, :128]!
+        vqadd.s16       q0,  q0,  q2
+        vqadd.s16       q1,  q1,  q3
+        vmax.s16        q0,  q0,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
+        vmax.s16        q1,  q1,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
+        vqsub.s16       q0,  q0,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
+        vqsub.s16       q1,  q1,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
+        vshl.s16        \d0, q0,  q13 // -(intermediate_bits+1)
+        vshl.s16        \d1, q1,  q13 // -(intermediate_bits+1)
+.endm
+
+.macro w_avg d0, d00, d01, d1, d10, d11
+        vld1.16         {q0, q1}, [r2, :128]!
+        vld1.16         {q2, q3}, [r3, :128]!
+        // This difference requires a 17 bit range, and all bits are
+        // significant for the following multiplication.
+        vsubl.s16       \d0, d4,  d0
+        vsubl.s16       q0,  d5,  d1
+        vsubl.s16       \d1, d6,  d2
+        vsubl.s16       q1,  d7,  d3
+        vmul.s32        \d0, \d0, q4
+        vmul.s32        q0,  q0,  q4
+        vmul.s32        \d1, \d1, q4
+        vmul.s32        q1,  q1,  q4
+        vshr.s32        \d0, \d0, #4
+        vshr.s32        q0,  q0,  #4
+        vshr.s32        \d1, \d1, #4
+        vshr.s32        q1,  q1,  #4
+        vaddw.s16       \d0, \d0, d4
+        vaddw.s16       q0,  q0,  d5
+        vaddw.s16       \d1, \d1, d6
+        vaddw.s16       q1,  q1,  d7
+        vmovn.i32       \d00, \d0
+        vmovn.i32       \d01, q0
+        vmovn.i32       \d10, \d1
+        vmovn.i32       \d11, q1
+        vrshl.s16       \d0, \d0, q13 // -intermediate_bits
+        vrshl.s16       \d1, \d1, q13 // -intermediate_bits
+        vadd.s16        \d0, \d0, q12 // PREP_BIAS >> intermediate_bits
+        vadd.s16        \d1, \d1, q12 // PREP_BIAS >> intermediate_bits
+        vmin.s16        \d0, \d0, q15 // bitdepth_max
+        vmin.s16        \d1, \d1, q15 // bitdepth_max
+        vmax.s16        \d0, \d0, q14 // 0
+        vmax.s16        \d1, \d1, q14 // 0
+.endm
+
+.macro mask d0, d00, d01, d1, d10, d11
+        vld1.8          {q7},     [r6, :128]!
+        vld1.16         {q0, q1}, [r2, :128]!
+        vneg.s8         q7,  q7
+        vld1.16         {q2, q3}, [r3, :128]!
+        vmovl.s8        q6,  d14
+        vmovl.s8        q7,  d15
+        vmovl.s16       q4,  d12
+        vmovl.s16       q5,  d13
+        vmovl.s16       q6,  d14
+        vmovl.s16       q7,  d15
+        vsubl.s16       \d0, d4,  d0
+        vsubl.s16       q0,  d5,  d1
+        vsubl.s16       \d1, d6,  d2
+        vsubl.s16       q1,  d7,  d3
+        vmul.s32        \d0, \d0, q4
+        vmul.s32        q0,  q0,  q5
+        vmul.s32        \d1, \d1, q6
+        vmul.s32        q1,  q1,  q7
+        vshr.s32        \d0, \d0, #6
+        vshr.s32        q0,  q0,  #6
+        vshr.s32        \d1, \d1, #6
+        vshr.s32        q1,  q1,  #6
+        vaddw.s16       \d0, \d0, d4
+        vaddw.s16       q0,  q0,  d5
+        vaddw.s16       \d1, \d1, d6
+        vaddw.s16       q1,  q1,  d7
+        vmovn.i32       \d00, \d0
+        vmovn.i32       \d01, q0
+        vmovn.i32       \d10, \d1
+        vmovn.i32       \d11, q1
+        vrshl.s16       \d0, \d0, q13 // -intermediate_bits
+        vrshl.s16       \d1, \d1, q13 // -intermediate_bits
+        vadd.s16        \d0, \d0, q12 // PREP_BIAS >> intermediate_bits
+        vadd.s16        \d1, \d1, q12 // PREP_BIAS >> intermediate_bits
+        vmin.s16        \d0, \d0, q15 // bitdepth_max
+        vmin.s16        \d1, \d1, q15 // bitdepth_max
+        vmax.s16        \d0, \d0, q14 // 0
+        vmax.s16        \d1, \d1, q14 // 0
+.endm
+
+.macro bidir_fn type, bdmax
+function \type\()_16bpc_neon, export=1
+        push            {r4-r7,lr}
+        ldr             r4,  [sp, #20]
+        ldr             r5,  [sp, #24]
+        ldr             r6,  [sp, #28]
+        clz             r4,  r4
+.ifnc \type, avg
+        ldr             r7,  [sp, #32]
+        vmov.i16        q14, #0
+        vdup.16         q15, r7         // bitdepth_max
+.endif
+.ifc \type, w_avg
+        vpush           {q4}
+.endif
+.ifc \type, mask
+        vpush           {q4-q7}
+.endif
+        clz             r7,  \bdmax
+        sub             r7,  r7,  #18   // intermediate_bits = clz(bitdepth_max) - 18
+.ifc \type, avg
+        mov             lr,  #1
+        movw            r12, #2*PREP_BIAS
+        lsl             lr,  lr,  r7    // 1 << intermediate_bits
+        neg             r12, r12         // -2*PREP_BIAS
+        add             r7,  r7,  #1
+        sub             r12, r12, lr    // -2*PREP_BIAS - 1 << intermediate_bits
+        neg             r7,  r7         // -(intermediate_bits+1)
+        vdup.16         q12, r12         // -2*PREP_BIAS - 1 << intermediate_bits
+        vdup.16         q13, r7         // -(intermediate_bits+1)
+.else
+        mov             r12, #PREP_BIAS
+        lsr             r12, r12, r7    // PREP_BIAS >> intermediate_bits
+        neg             r7,  r7         // -intermediate_bits
+        vdup.16         q12, r12         // PREP_BIAS >> intermediate_bits
+        vdup.16         q13, r7         // -intermediate_bits
+.endif
+.ifc \type, w_avg
+        vdup.32         q4,  r6
+        vneg.s32        q4,  q4
+.endif
+        adr             r7,  L(\type\()_tbl)
+        sub             r4,  r4,  #24
+        \type           q8,  d16, d17, q9,  d18, d19
+        ldr             r4,  [r7, r4, lsl #2]
+        add             r7,  r7,  r4
+        bx              r7
+
+        .align 2
+L(\type\()_tbl):
+        .word 1280f - L(\type\()_tbl) + CONFIG_THUMB
+        .word 640f  - L(\type\()_tbl) + CONFIG_THUMB
+        .word 320f  - L(\type\()_tbl) + CONFIG_THUMB
+        .word 160f  - L(\type\()_tbl) + CONFIG_THUMB
+        .word 80f   - L(\type\()_tbl) + CONFIG_THUMB
+        .word 40f   - L(\type\()_tbl) + CONFIG_THUMB
+
+40:
+        add             r7,  r0,  r1
+        lsl             r1,  r1,  #1
+4:
+        subs            r5,  r5,  #4
+        vst1.16         {d16},  [r0, :64], r1
+        vst1.16         {d17},  [r7, :64], r1
+        vst1.16         {d18},  [r0, :64], r1
+        vst1.16         {d19},  [r7, :64], r1
+        ble             0f
+        \type           q8,  d16, d17, q9,  d18, d19
+        b               4b
+80:
+        add             r7,  r0,  r1
+        lsl             r1,  r1,  #1
+8:
+        vst1.16         {q8},  [r0, :128], r1
+        subs            r5,  r5,  #2
+        vst1.16         {q9},  [r7, :128], r1
+        ble             0f
+        \type           q8,  d16, d17, q9,  d18, d19
+        b               8b
+160:
+16:
+        \type           q10, d20, d21, q11, d22, d23
+        vst1.16         {q8,  q9},  [r0, :128], r1
+        subs            r5,  r5,  #2
+        vst1.16         {q10, q11}, [r0, :128], r1
+        ble             0f
+        \type           q8,  d16, d17, q9,  d18, d19
+        b               16b
+320:
+        add             r7,  r0,  #32
+32:
+        \type           q10, d20, d21, q11, d22, d23
+        vst1.16         {q8,  q9},  [r0, :128], r1
+        subs            r5,  r5,  #1
+        vst1.16         {q10, q11}, [r7, :128], r1
+        ble             0f
+        \type           q8,  d16, d17, q9,  d18, d19
+        b               32b
+640:
+        add             r7,  r0,  #32
+        mov             r12, #64
+        sub             r1,  r1,  #64
+64:
+        \type           q10, d20, d21, q11, d22, d23
+        vst1.16         {q8,  q9},  [r0, :128], r12
+        \type           q8,  d16, d17, q9,  d18, d19
+        vst1.16         {q10, q11}, [r7, :128], r12
+        \type           q10, d20, d21, q11, d22, d23
+        vst1.16         {q8,  q9},  [r0, :128], r1
+        subs            r5,  r5,  #1
+        vst1.16         {q10, q11}, [r7, :128], r1
+        ble             0f
+        \type           q8,  d16, d17, q9,  d18, d19
+        b               64b
+1280:
+        add             r7,  r0,  #32
+        mov             r12, #64
+        sub             r1,  r1,  #192
+128:
+        \type           q10, d20, d21, q11, d22, d23
+        vst1.16         {q8,  q9},  [r0, :128], r12
+        \type           q8,  d16, d17, q9,  d18, d19
+        vst1.16         {q10, q11}, [r7, :128], r12
+        \type           q10, d20, d21, q11, d22, d23
+        vst1.16         {q8,  q9},  [r0, :128], r12
+        \type           q8,  d16, d17, q9,  d18, d19
+        vst1.16         {q10, q11}, [r7, :128], r12
+        \type           q10, d20, d21, q11, d22, d23
+        vst1.16         {q8,  q9},  [r0, :128], r12
+        \type           q8,  d16, d17, q9,  d18, d19
+        vst1.16         {q10, q11}, [r7, :128], r12
+        \type           q10, d20, d21, q11, d22, d23
+        vst1.16         {q8,  q9},  [r0, :128], r1
+        subs            r5,  r5,  #1
+        vst1.16         {q10, q11}, [r7, :128], r1
+        ble             0f
+        \type           q8,  d16, d17, q9,  d18, d19
+        b               128b
+0:
+.ifc \type, mask
+        vpop            {q4-q7}
+.endif
+.ifc \type, w_avg
+        vpop            {q4}
+.endif
+        pop             {r4-r7,pc}
+endfunc
+.endm
+
+bidir_fn avg, r6
+bidir_fn w_avg, r7
+bidir_fn mask, r7
--- a/src/arm/mc_init_tmpl.c
+++ b/src/arm/mc_init_tmpl.c
@@ -99,10 +99,12 @@
     init_mct_fn(FILTER_2D_8TAP_SHARP_SMOOTH,   8tap_sharp_smooth,   neon);
     init_mct_fn(FILTER_2D_8TAP_SHARP,          8tap_sharp,          neon);
     init_mct_fn(FILTER_2D_BILINEAR,            bilin,               neon);
+#endif
 
     c->avg = BF(dav1d_avg, neon);
     c->w_avg = BF(dav1d_w_avg, neon);
     c->mask = BF(dav1d_mask, neon);
+#if BITDEPTH == 8 || ARCH_AARCH64
     c->blend = BF(dav1d_blend, neon);
     c->blend_h = BF(dav1d_blend_h, neon);
     c->blend_v = BF(dav1d_blend_v, neon);
--- a/src/meson.build
+++ b/src/meson.build
@@ -147,6 +147,7 @@
 
             if dav1d_bitdepths.contains('16')
                 libdav1d_sources += files(
+                    'arm/32/mc16.S',
                 )
             endif
         endif