[5/5] aarch64: vp9itxfm: Do a simpler half/quarter idct16/idct32 when possible (alternative 1)

Message ID 1480584422-24237-6-git-send-email-martin@martin.st
State Superseded
Headers show

Commit Message

Martin Storsjö Dec. 1, 2016, 9:27 a.m.
This work is sponsored by, and copyright, Google.

This increases the code size of libavcodec/aarch64/vp9itxfm_neon.o
from 14740 to 18504 bytes.

Before:
vp9_inv_dct_dct_16x16_sub1_add_neon:     235.3
vp9_inv_dct_dct_16x16_sub2_add_neon:    1051.0
vp9_inv_dct_dct_16x16_sub4_add_neon:    1051.0
vp9_inv_dct_dct_16x16_sub8_add_neon:    1051.0
vp9_inv_dct_dct_16x16_sub12_add_neon:   1390.3
vp9_inv_dct_dct_16x16_sub16_add_neon:   1390.1
vp9_inv_dct_dct_32x32_sub1_add_neon:     556.5
vp9_inv_dct_dct_32x32_sub2_add_neon:    5199.1
vp9_inv_dct_dct_32x32_sub4_add_neon:    5199.9
vp9_inv_dct_dct_32x32_sub8_add_neon:    5196.9
vp9_inv_dct_dct_32x32_sub12_add_neon:   6171.6
vp9_inv_dct_dct_32x32_sub16_add_neon:   6170.9
vp9_inv_dct_dct_32x32_sub20_add_neon:   7147.1
vp9_inv_dct_dct_32x32_sub24_add_neon:   7147.0
vp9_inv_dct_dct_32x32_sub28_add_neon:   8118.8
vp9_inv_dct_dct_32x32_sub32_add_neon:   8125.8

After:
vp9_inv_dct_dct_16x16_sub1_add_neon:     235.3
vp9_inv_dct_dct_16x16_sub2_add_neon:     697.0
vp9_inv_dct_dct_16x16_sub4_add_neon:     697.0
vp9_inv_dct_dct_16x16_sub8_add_neon:     908.0
vp9_inv_dct_dct_16x16_sub12_add_neon:   1399.6
vp9_inv_dct_dct_16x16_sub16_add_neon:   1403.3
vp9_inv_dct_dct_32x32_sub1_add_neon:     554.1
vp9_inv_dct_dct_32x32_sub2_add_neon:    3879.7
vp9_inv_dct_dct_32x32_sub4_add_neon:    3952.2
vp9_inv_dct_dct_32x32_sub8_add_neon:    3948.4
vp9_inv_dct_dct_32x32_sub12_add_neon:   5462.1
vp9_inv_dct_dct_32x32_sub16_add_neon:   5461.7
vp9_inv_dct_dct_32x32_sub20_add_neon:   7169.2
vp9_inv_dct_dct_32x32_sub24_add_neon:   7162.4
vp9_inv_dct_dct_32x32_sub28_add_neon:   8137.4
vp9_inv_dct_dct_32x32_sub32_add_neon:   8136.7

I.e. in general a very minor overhead for the full subpartition case due
to the additional cmps, but a significant speedup for the cases when we
only need to process a small part of the actual input data.
---
If we wouldn't have made the core transforms standalone functions,
the code size would end up at around 28 KB.
---
 libavcodec/aarch64/vp9itxfm_neon.S | 367 +++++++++++++++++++++++++++++++++++--
 1 file changed, 347 insertions(+), 20 deletions(-)

Comments

Janne Grunau Feb. 5, 2017, 9:37 a.m. | #1
On 2016-12-01 11:27:01 +0200, Martin Storsjö wrote:
> This work is sponsored by, and copyright, Google.
> 
> This increases the code size of libavcodec/aarch64/vp9itxfm_neon.o
> from 14740 to 18504 bytes.
> 
> Before:
> vp9_inv_dct_dct_16x16_sub1_add_neon:     235.3
> vp9_inv_dct_dct_16x16_sub2_add_neon:    1051.0
> vp9_inv_dct_dct_16x16_sub4_add_neon:    1051.0
> vp9_inv_dct_dct_16x16_sub8_add_neon:    1051.0
> vp9_inv_dct_dct_16x16_sub12_add_neon:   1390.3
> vp9_inv_dct_dct_16x16_sub16_add_neon:   1390.1
> vp9_inv_dct_dct_32x32_sub1_add_neon:     556.5
> vp9_inv_dct_dct_32x32_sub2_add_neon:    5199.1
> vp9_inv_dct_dct_32x32_sub4_add_neon:    5199.9
> vp9_inv_dct_dct_32x32_sub8_add_neon:    5196.9
> vp9_inv_dct_dct_32x32_sub12_add_neon:   6171.6
> vp9_inv_dct_dct_32x32_sub16_add_neon:   6170.9
> vp9_inv_dct_dct_32x32_sub20_add_neon:   7147.1
> vp9_inv_dct_dct_32x32_sub24_add_neon:   7147.0
> vp9_inv_dct_dct_32x32_sub28_add_neon:   8118.8
> vp9_inv_dct_dct_32x32_sub32_add_neon:   8125.8
> 
> After:
> vp9_inv_dct_dct_16x16_sub1_add_neon:     235.3
> vp9_inv_dct_dct_16x16_sub2_add_neon:     697.0
> vp9_inv_dct_dct_16x16_sub4_add_neon:     697.0
> vp9_inv_dct_dct_16x16_sub8_add_neon:     908.0
> vp9_inv_dct_dct_16x16_sub12_add_neon:   1399.6
> vp9_inv_dct_dct_16x16_sub16_add_neon:   1403.3
> vp9_inv_dct_dct_32x32_sub1_add_neon:     554.1
> vp9_inv_dct_dct_32x32_sub2_add_neon:    3879.7
> vp9_inv_dct_dct_32x32_sub4_add_neon:    3952.2
> vp9_inv_dct_dct_32x32_sub8_add_neon:    3948.4
> vp9_inv_dct_dct_32x32_sub12_add_neon:   5462.1
> vp9_inv_dct_dct_32x32_sub16_add_neon:   5461.7
> vp9_inv_dct_dct_32x32_sub20_add_neon:   7169.2
> vp9_inv_dct_dct_32x32_sub24_add_neon:   7162.4
> vp9_inv_dct_dct_32x32_sub28_add_neon:   8137.4
> vp9_inv_dct_dct_32x32_sub32_add_neon:   8136.7
> 
> I.e. in general a very minor overhead for the full subpartition case due
> to the additional cmps, but a significant speedup for the cases when we
> only need to process a small part of the actual input data.
> ---
> If we wouldn't have made the core transforms standalone functions,
> the code size would end up at around 28 KB.
> ---
>  libavcodec/aarch64/vp9itxfm_neon.S | 367 +++++++++++++++++++++++++++++++++++--
>  1 file changed, 347 insertions(+), 20 deletions(-)
> 
> diff --git a/libavcodec/aarch64/vp9itxfm_neon.S b/libavcodec/aarch64/vp9itxfm_neon.S
> index be9643e..bb79348 100644
> --- a/libavcodec/aarch64/vp9itxfm_neon.S
> +++ b/libavcodec/aarch64/vp9itxfm_neon.S
> @@ -75,6 +75,16 @@ endconst
>  .endif
>  .endm
>  
> +// Same as dmbutterfly0 above, but treating the input in in2 as zero,
> +// writing the same output into both out1 and out2.
> +.macro dmbutterfly0_h out1, out2, in1, in2, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6
> +        smull           \tmp1\().4s,  \in1\().4h,  v0.h[0]
> +        smull2          \tmp2\().4s,  \in1\().8h,  v0.h[0]
> +        rshrn           \out1\().4h,  \tmp1\().4s, #14
> +        rshrn2          \out1\().8h,  \tmp2\().4s, #14
> +        mov             \out2\().16b, \out1\().16b
> +.endm
> +
>  // out1,out2 = in1 * coef1 - in2 * coef2
>  // out3,out4 = in1 * coef2 + in2 * coef1
>  // out are 4 x .4s registers, in are 2 x .8h registers
> @@ -104,6 +114,43 @@ endconst
>          rshrn2          \inout2\().8h, \tmp4\().4s,  #14
>  .endm
>  
> +// Same as dmbutterfly above, but treating the input in inout2 as zero
> +.macro dmbutterfly_h1 inout1, inout2, coef1, coef2, tmp1, tmp2, tmp3, tmp4
> +        smull           \tmp1\().4s, \inout1\().4h, \coef1
> +        smull2          \tmp2\().4s, \inout1\().8h, \coef1
> +        smull           \tmp3\().4s, \inout1\().4h, \coef2
> +        smull2          \tmp4\().4s, \inout1\().8h, \coef2
> +        rshrn           \inout1\().4h, \tmp1\().4s, #14
> +        rshrn2          \inout1\().8h, \tmp2\().4s, #14
> +        rshrn           \inout2\().4h, \tmp3\().4s, #14
> +        rshrn2          \inout2\().8h, \tmp4\().4s, #14
> +.endm
> +
> +// Same as dmbutterfly above, but treating the input in inout1 as zero
> +.macro dmbutterfly_h2 inout1, inout2, coef1, coef2, tmp1, tmp2, tmp3, tmp4
> +        smull           \tmp1\().4s, \inout2\().4h, \coef2
> +        smull2          \tmp2\().4s, \inout2\().8h, \coef2
> +        smull           \tmp3\().4s, \inout2\().4h, \coef1
> +        smull2          \tmp4\().4s, \inout2\().8h, \coef1
> +        neg             \tmp1\().4s, \tmp1\().4s
> +        neg             \tmp2\().4s, \tmp2\().4s
> +        rshrn           \inout2\().4h, \tmp3\().4s, #14
> +        rshrn2          \inout2\().8h, \tmp4\().4s, #14
> +        rshrn           \inout1\().4h, \tmp1\().4s, #14
> +        rshrn2          \inout1\().8h, \tmp2\().4s, #14
> +.endm
> +
> +.macro dsmull_h out1, out2, in, coef
> +        smull           \out1\().4s, \in\().4h, \coef
> +        smull2          \out2\().4s, \in\().8h, \coef
> +.endm
> +
> +.macro drshrn_h out, in1, in2, shift
> +        rshrn           \out\().4h, \in1\().4s, \shift
> +        rshrn2          \out\().8h, \in2\().4s, \shift
> +.endm
> +
> +
>  // out1 = in1 + in2
>  // out2 = in1 - in2
>  .macro butterfly_8h out1, out2, in1, in2
> @@ -463,7 +510,7 @@ function idct16x16_dc_add_neon
>          ret
>  endfunc
>  
> -function idct16
> +.macro idct16_full
>          dmbutterfly0    v16, v24, v16, v24, v2, v3, v4, v5, v6, v7 // v16 = t0a,  v24 = t1a
>          dmbutterfly     v20, v28, v0.h[1], v0.h[2], v2, v3, v4, v5 // v20 = t2a,  v28 = t3a
>          dmbutterfly     v18, v30, v0.h[3], v0.h[4], v2, v3, v4, v5 // v18 = t4a,  v30 = t7a
> @@ -485,7 +532,10 @@ function idct16
>          dmbutterfly0    v22, v26, v22, v26, v2, v3, v18, v19, v30, v31        // v22 = t6a,  v26 = t5a
>          dmbutterfly     v23, v25, v0.h[1], v0.h[2], v18, v19, v30, v31        // v23 = t9a,  v25 = t14a
>          dmbutterfly     v27, v21, v0.h[1], v0.h[2], v18, v19, v30, v31, neg=1 // v27 = t13a, v21 = t10a
> +        idct16_end

I think it would be clearer if idct16_end is used directly from the 
macro. it would probably also make sense to move idct16_end and avoid 
the idct16_full macro. The patch might be smaller and it is immediately 
obvious that there is no code change but the resulting code is more 
comlicated than it needs to be. same applies to arm if we go with 
alternative 1.

> +.endm
>  
> +.macro idct16_end
>          butterfly_8h    v18, v7,  v4,  v7                // v18 = t0a,  v7  = t7a
>          butterfly_8h    v19, v22, v5,  v22               // v19 = t1a,  v22 = t6
>          butterfly_8h    v4,  v26, v20, v26               // v4  = t2a,  v26 = t5
> @@ -507,6 +557,68 @@ function idct16
>          butterfly_8h    v20, v27, v6,  v27               // v20 = out[4], v27 = out[11]
>          butterfly_8h    v21, v26, v26, v3                // v21 = out[5], v26 = out[10]
>          ret
> +.endm
> +
> +function idct16
> +        idct16_full
> +endfunc
> +
> +function idct16_half
> +        dmbutterfly0_h  v16, v24, v16, v24, v2, v3, v4, v5, v6, v7 // v16 = t0a,  v24 = t1a
> +        dmbutterfly_h1  v20, v28, v0.h[1], v0.h[2], v2, v3, v4, v5 // v20 = t2a,  v28 = t3a
> +        dmbutterfly_h1  v18, v30, v0.h[3], v0.h[4], v2, v3, v4, v5 // v18 = t4a,  v30 = t7a
> +        dmbutterfly_h2  v26, v22, v0.h[5], v0.h[6], v2, v3, v4, v5 // v26 = t5a,  v22 = t6a
> +        dmbutterfly_h1  v17, v31, v0.h[7], v1.h[0], v2, v3, v4, v5 // v17 = t8a,  v31 = t15a
> +        dmbutterfly_h2  v25, v23, v1.h[1], v1.h[2], v2, v3, v4, v5 // v25 = t9a,  v23 = t14a
> +        dmbutterfly_h1  v21, v27, v1.h[3], v1.h[4], v2, v3, v4, v5 // v21 = t10a, v27 = t13a
> +        dmbutterfly_h2  v29, v19, v1.h[5], v1.h[6], v2, v3, v4, v5 // v29 = t11a, v19 = t12a
> +
> +        butterfly_8h    v4,  v28, v16, v28               // v4  = t0,   v28 = t3
> +        butterfly_8h    v5,  v20, v24, v20               // v5  = t1,   v20 = t2
> +        butterfly_8h    v6,  v26, v18, v26               // v6  = t4,   v26 = t5
> +        butterfly_8h    v7,  v22, v30, v22               // v7  = t7,   v22 = t6
> +        butterfly_8h    v16, v25, v17, v25               // v16 = t8,   v25 = t9
> +        butterfly_8h    v24, v21, v29, v21               // v24 = t11,  v21 = t10
> +        butterfly_8h    v17, v27, v19, v27               // v17 = t12,  v27 = t13
> +        butterfly_8h    v29, v23, v31, v23               // v29 = t15,  v23 = t14
> +
> +        dmbutterfly0    v22, v26, v22, v26, v2, v3, v18, v19, v30, v31        // v22 = t6a,  v26 = t5a
> +        dmbutterfly     v23, v25, v0.h[1], v0.h[2], v18, v19, v30, v31        // v23 = t9a,  v25 = t14a
> +        dmbutterfly     v27, v21, v0.h[1], v0.h[2], v18, v19, v30, v31, neg=1 // v27 = t13a, v21 = t10a
> +        idct16_end
> +endfunc
> +
> +function idct16_quarter
> +        dsmull_h        v24, v25, v19, v1.h[6]
> +        dsmull_h        v4,  v5,  v17, v0.h[7]
> +        dsmull_h        v7,  v6,  v18, v0.h[4]
> +        dsmull_h        v30, v31, v18, v0.h[3]
> +        neg             v24.4s,  v24.4s
> +        neg             v25.4s,  v25.4s
> +        dsmull_h        v29, v28, v17, v1.h[0]
> +        dsmull_h        v26, v27, v19, v1.h[5]
> +        dsmull_h        v22, v23, v16, v0.h[0]
> +        drshrn_h        v24, v24, v25, #14
> +        drshrn_h        v16, v4,  v5,  #14
> +        drshrn_h        v7,  v7,  v6,  #14
> +        drshrn_h        v6,  v30, v31, #14
> +        drshrn_h        v29, v29, v28, #14
> +        drshrn_h        v17, v26, v27, #14
> +        drshrn_h        v28, v22, v23, #14
> +
> +        dmbutterfly_l   v20, v21, v22, v23, v17, v24, v0.h[1], v0.h[2]
> +        dmbutterfly_l   v18, v19, v30, v31, v29, v16, v0.h[1], v0.h[2]
> +        neg             v22.4s,  v22.4s
> +        neg             v23.4s,  v23.4s
> +        drshrn_h        v27, v20, v21, #14
> +        drshrn_h        v21, v22, v23, #14
> +        drshrn_h        v23, v18, v19, #14
> +        drshrn_h        v25, v30, v31, #14
> +        mov             v4.16b,  v28.16b
> +        mov             v5.16b,  v28.16b
> +        dmbutterfly0    v22, v26, v7,  v6,  v18, v19, v30, v31
> +        mov             v20.16b, v28.16b
> +        idct16_end
>  endfunc
>  
>  function iadst16
> @@ -609,12 +721,37 @@ function \txfm\()16_1d_8x16_pass1_neon
>          mov             x14, x30
>  
>          movi            v2.8h, #0
> +
> +.ifc \txfm,idct
> +        cmp             w3, #10
> +        b.le            3f
> +        cmp             w3, #38
> +        b.le            4f
> +.endif
> +
>  .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
>          load_clear      \i,  x2,  x9
>  .endr
>  
>          bl              \txfm\()16
> +.ifc \txfm,idct
> +        b               5f
> +
> +3:
> +.irp i, 16, 17, 18, 19
> +        load_clear      \i,  x2,  x9
> +.endr
> +        bl              idct16_quarter
> +        b               5f
>  
> +4:
> +.irp i, 16, 17, 18, 19, 20, 21, 22, 23
> +        load_clear      \i,  x2,  x9
> +.endr
> +        bl              idct16_half
> +.endif
> +
> +5:
>          // Do two 8x8 transposes. Originally, v16-v31 contain the
>          // 16 rows. Afterwards, v16-v23 and v24-v31 contain the two
>          // transposed 8x8 blocks.
> @@ -654,38 +791,60 @@ endfunc
>  // x0 = dst
>  // x1 = dst stride
>  // x2 = src (temp buffer)
> -// x3 = slice offset
> +// w3 = eob
>  // x9 = temp buffer stride
> +// x13 = slice offset
>  function \txfm\()16_1d_8x16_pass2_neon
>          mov             x14, x30
> +.ifc \txfm,idct
> +        cmp             w3, #10
> +        b.le            3f
> +        cmp             w3, #38
> +        b.le            4f
> +.endif
>  .irp i, 16, 17, 18, 19, 20, 21, 22, 23
>          load            \i,  x2,  x9
>  .endr
> -        cbz             x3,  1f
> +        cbz             x13, 1f
>  .irp i, 24, 25, 26, 27, 28, 29, 30, 31
>          load            \i,  x2,  x9
>  .endr
>  1:
>  
> -        add             x3,  x0,  x1
> -        lsl             x1,  x1,  #1
>          bl              \txfm\()16
> +.ifc \txfm,idct
> +        b               5f
> +3:
> +.irp i, 16, 17, 18, 19
> +        load            \i,  x2,  x9
> +.endr
> +        bl              idct16_quarter
> +        b               5f
> +4:
> +.irp i, 16, 17, 18, 19, 20, 21, 22, 23
> +        load            \i,  x2,  x9
> +.endr
> +        bl              idct16_half
> +.endif
>  
> +5:
> +        add             x8,  x0,  x1
> +        lsl             x1,  x1,  #1
>  .macro load_add_store coef0, coef1, coef2, coef3, coef4, coef5, coef6, coef7, tmp1, tmp2
>          srshr           \coef0, \coef0, #6
>          ld1             {v2.8b},  [x0], x1
>          srshr           \coef1, \coef1, #6
> -        ld1             {v3.8b},  [x3], x1
> +        ld1             {v3.8b},  [x8], x1
>          srshr           \coef2, \coef2, #6
>          ld1             {v4.8b},  [x0], x1
>          srshr           \coef3, \coef3, #6
>          uaddw           \coef0, \coef0, v2.8b
> -        ld1             {v5.8b},  [x3], x1
> +        ld1             {v5.8b},  [x8], x1
>          uaddw           \coef1, \coef1, v3.8b
>          srshr           \coef4, \coef4, #6
>          ld1             {v6.8b},  [x0], x1
>          srshr           \coef5, \coef5, #6
> -        ld1             {v7.8b},  [x3], x1
> +        ld1             {v7.8b},  [x8], x1
>          sqxtun          v2.8b,  \coef0
>          srshr           \coef6, \coef6, #6
>          sqxtun          v3.8b,  \coef1
> @@ -693,27 +852,27 @@ function \txfm\()16_1d_8x16_pass2_neon
>          uaddw           \coef2, \coef2, v4.8b
>          ld1             {\tmp1},  [x0], x1
>          uaddw           \coef3, \coef3, v5.8b
> -        ld1             {\tmp2},  [x3], x1
> +        ld1             {\tmp2},  [x8], x1
>          sqxtun          v4.8b,  \coef2
>          sub             x0,  x0,  x1, lsl #2
> -        sub             x3,  x3,  x1, lsl #2
> +        sub             x8,  x8,  x1, lsl #2
>          sqxtun          v5.8b,  \coef3
>          uaddw           \coef4, \coef4, v6.8b
>          st1             {v2.8b},  [x0], x1
>          uaddw           \coef5, \coef5, v7.8b
> -        st1             {v3.8b},  [x3], x1
> +        st1             {v3.8b},  [x8], x1
>          sqxtun          v6.8b,  \coef4
>          st1             {v4.8b},  [x0], x1
>          sqxtun          v7.8b,  \coef5
> -        st1             {v5.8b},  [x3], x1
> +        st1             {v5.8b},  [x8], x1
>          uaddw           \coef6, \coef6, \tmp1
>          st1             {v6.8b},  [x0], x1
>          uaddw           \coef7, \coef7, \tmp2
> -        st1             {v7.8b},  [x3], x1
> +        st1             {v7.8b},  [x8], x1
>          sqxtun          \tmp1,  \coef6
>          sqxtun          \tmp2,  \coef7
>          st1             {\tmp1},  [x0], x1
> -        st1             {\tmp2},  [x3], x1
> +        st1             {\tmp2},  [x8], x1
>  .endm
>          load_add_store  v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v16.8b, v17.8b
>          load_add_store  v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h, v16.8b, v17.8b
> @@ -750,6 +909,7 @@ function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
>          movrel          x10, idct_coeffs
>  .ifnc \txfm1\()_\txfm2,idct_idct
>          movrel          x11, iadst16_coeffs
> +        mov             w3,  #256
>  .endif
>  .ifc \txfm1,idct
>          ld1             {v0.8h,v1.8h}, [x10]
> @@ -792,7 +952,7 @@ function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
>          add             x0,  x4,  #(\i)
>          mov             x1,  x5
>          add             x2,  sp,  #(\i*2)
> -        mov             x3,  #\i
> +        mov             x13, #\i
>          bl              \txfm2\()16_1d_8x16_pass2_neon
>  .endr
>  
> @@ -848,7 +1008,7 @@ function idct32x32_dc_add_neon
>          ret
>  endfunc
>  
> -function idct32_odd
> +.macro idct32_odd_full
>          ld1             {v0.8h,v1.8h}, [x11]
>  
>          dmbutterfly     v16, v31, v0.h[0], v0.h[1], v4, v5, v6, v7 // v16 = t16a, v31 = t31a
> @@ -875,7 +1035,10 @@ function idct32_odd
>          dmbutterfly     v27, v20, v0.h[3], v0.h[4], v16, v17, v18, v19, neg=1 // v27 = t29a, v20 = t18a
>          dmbutterfly     v21, v26, v0.h[5], v0.h[6], v16, v17, v18, v19        // v21 = t21a, v26 = t26a
>          dmbutterfly     v25, v22, v0.h[5], v0.h[6], v16, v17, v18, v19, neg=1 // v25 = t25a, v22 = t22a
> +        idct32_end

see the comment for the idct16

> +.endm
>  
> +.macro idct32_end
>          butterfly_8h    v16, v5,  v4,  v5  // v16 = t16a, v5  = t19a
>          butterfly_8h    v17, v20, v23, v20 // v17 = t17,  v20 = t18
>          butterfly_8h    v18, v6,  v7,  v6  // v18 = t23a, v6  = t20a
> @@ -904,6 +1067,88 @@ function idct32_odd
>          dmbutterfly0    v25, v22, v25, v22, v2, v3, v4, v5, v6, v7 // v25 = t25,  v22 = t22
>          dmbutterfly0    v24, v23, v24, v23, v2, v3, v4, v5, v6, v7 // v24 = t24a, v23 = t23a
>          ret
> +.endm
> +
> +function idct32_odd
> +        idct32_odd_full
> +endfunc
> +
> +function idct32_odd_half
> +        ld1             {v0.8h,v1.8h}, [x11]
> +
> +        dmbutterfly_h1  v16, v31, v0.h[0], v0.h[1], v4, v5, v6, v7 // v16 = t16a, v31 = t31a
> +        dmbutterfly_h2  v24, v23, v0.h[2], v0.h[3], v4, v5, v6, v7 // v24 = t17a, v23 = t30a
> +        dmbutterfly_h1  v20, v27, v0.h[4], v0.h[5], v4, v5, v6, v7 // v20 = t18a, v27 = t29a
> +        dmbutterfly_h2  v28, v19, v0.h[6], v0.h[7], v4, v5, v6, v7 // v28 = t19a, v19 = t28a
> +        dmbutterfly_h1  v18, v29, v1.h[0], v1.h[1], v4, v5, v6, v7 // v18 = t20a, v29 = t27a
> +        dmbutterfly_h2  v26, v21, v1.h[2], v1.h[3], v4, v5, v6, v7 // v26 = t21a, v21 = t26a
> +        dmbutterfly_h1  v22, v25, v1.h[4], v1.h[5], v4, v5, v6, v7 // v22 = t22a, v25 = t25a
> +        dmbutterfly_h2  v30, v17, v1.h[6], v1.h[7], v4, v5, v6, v7 // v30 = t23a, v17 = t24a
> +
> +        ld1             {v0.8h}, [x10]
> +
> +        butterfly_8h    v4,  v24, v16, v24 // v4  = t16, v24 = t17
> +        butterfly_8h    v5,  v20, v28, v20 // v5  = t19, v20 = t18
> +        butterfly_8h    v6,  v26, v18, v26 // v6  = t20, v26 = t21
> +        butterfly_8h    v7,  v22, v30, v22 // v7  = t23, v22 = t22
> +        butterfly_8h    v28, v25, v17, v25 // v28 = t24, v25 = t25
> +        butterfly_8h    v30, v21, v29, v21 // v30 = t27, v21 = t26
> +        butterfly_8h    v29, v23, v31, v23 // v29 = t31, v23 = t30
> +        butterfly_8h    v31, v27, v19, v27 // v31 = t28, v27 = t29
> +
> +        dmbutterfly     v23, v24, v0.h[3], v0.h[4], v16, v17, v18, v19        // v23 = t17a, v24 = t30a
> +        dmbutterfly     v27, v20, v0.h[3], v0.h[4], v16, v17, v18, v19, neg=1 // v27 = t29a, v20 = t18a
> +        dmbutterfly     v21, v26, v0.h[5], v0.h[6], v16, v17, v18, v19        // v21 = t21a, v26 = t26a
> +        dmbutterfly     v25, v22, v0.h[5], v0.h[6], v16, v17, v18, v19, neg=1 // v25 = t25a, v22 = t22a
> +        idct32_end
> +endfunc
> +
> +function idct32_odd_quarter
> +        ld1             {v0.8h,v1.8h}, [x11]
> +
> +        dsmull_h        v4,  v5,  v16, v0.h[0]
> +        dsmull_h        v28, v29, v19, v0.h[7]
> +        dsmull_h        v30, v31, v16, v0.h[1]
> +        dsmull_h        v22, v23, v17, v1.h[6]
> +        dsmull_h        v7,  v6,  v17, v1.h[7]
> +        dsmull_h        v26, v27, v19, v0.h[6]
> +        dsmull_h        v20, v21, v18, v1.h[0]
> +        dsmull_h        v24, v25, v18, v1.h[1]
> +
> +        ld1             {v0.8h}, [x10]
> +
> +        neg             v28.4s, v28.4s
> +        neg             v29.4s, v29.4s
> +        neg             v7.4s,  v7.4s
> +        neg             v6.4s,  v6.4s
> +
> +        drshrn_h        v4,  v4,  v5,  #14
> +        drshrn_h        v5,  v28, v29, #14
> +        drshrn_h        v29, v30, v31, #14
> +        drshrn_h        v28, v22, v23, #14
> +        drshrn_h        v7,  v7,  v6,  #14
> +        drshrn_h        v31, v26, v27, #14
> +        drshrn_h        v6,  v20, v21, #14
> +        drshrn_h        v30, v24, v25, #14
> +
> +        dmbutterfly_l   v16, v17, v18, v19, v29, v4,  v0.h[3], v0.h[4]
> +        dmbutterfly_l   v27, v26, v20, v21, v31, v5,  v0.h[3], v0.h[4]
> +        drshrn_h        v23, v16, v17, #14
> +        drshrn_h        v24, v18, v19, #14
> +        neg             v20.4s, v20.4s
> +        neg             v21.4s, v21.4s
> +        drshrn_h        v27, v27, v26, #14
> +        drshrn_h        v20, v20, v21, #14
> +        dmbutterfly_l   v16, v17, v18, v19, v30, v6,  v0.h[5], v0.h[6]
> +        drshrn_h        v21, v16, v17, #14
> +        drshrn_h        v26, v18, v19, #14
> +        dmbutterfly_l   v16, v17, v18, v19, v28, v7,  v0.h[5], v0.h[6]
> +        drshrn_h        v25, v16, v17, #14
> +        neg             v18.4s, v18.4s
> +        neg             v19.4s, v19.4s
> +        drshrn_h        v22, v18, v19, #14
> +
> +        idct32_end
>  endfunc
>  
>  // Do an 32-point IDCT of a 8x32 slice out of a 32x32 matrix.
> @@ -923,6 +1168,11 @@ function idct32_1d_8x32_pass1_neon
>  
>          movi            v4.8h, #0
>  
> +        cmp             w3,  #4
> +        b.le            3f
> +        cmp             w3,  #135
> +        b.le            4f
> +
>          // v16 = IN(0), v17 = IN(2) ... v31 = IN(30)
>  .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
>          ld1             {v\i\().8h}, [x2]
> @@ -930,7 +1180,25 @@ function idct32_1d_8x32_pass1_neon
>  .endr
>  
>          bl              idct16
> +        sub             x2,  x2,  x9, lsl #4
> +        b               5f
> +3:
> +.irp i, 16, 17, 18, 19
> +        ld1             {v\i\().8h}, [x2]
> +        st1             {v4.8h},  [x2], x9
> +.endr
> +        bl              idct16_quarter
> +        sub             x2,  x2,  x9, lsl #2
> +        b               5f
> +4:
> +.irp i, 16, 17, 18, 19, 20, 21, 22, 23
> +        ld1             {v\i\().8h}, [x2]
> +        st1             {v4.8h},  [x2], x9
> +.endr
> +        bl              idct16_half
> +        sub             x2,  x2,  x9, lsl #3
>  
> +5:
>          // Do two 8x8 transposes. Originally, v16-v31 contain the
>          // 16 rows. Afterwards, v16-v23 and v24-v31 contain the
>          // two transposed 8x8 blocks.
> @@ -962,12 +1230,16 @@ function idct32_1d_8x32_pass1_neon
>          sub             x0,  x0,  #512
>  .purgem store_rev
>  
> -        // Move x2 back to the start of the input, and move
> -        // to the first odd row
> -        sub             x2,  x2,  x9, lsl #4
> +        // Move x2 to the first odd row
>          add             x2,  x2,  #64
>  
>          movi            v4.8h, #0
> +
> +        cmp             w3,  #34
> +        b.le            3f
> +        cmp             w3,  #135
> +        b.le            4f
> +
>          // v16 = IN(1), v17 = IN(3) ... v31 = IN(31)
>  .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
>          ld1             {v\i\().8h}, [x2]
> @@ -975,7 +1247,22 @@ function idct32_1d_8x32_pass1_neon
>  .endr
>  
>          bl              idct32_odd
> +        b               5f
> +3:
> +.irp i, 16, 17, 18, 19
> +        ld1             {v\i\().8h}, [x2]
> +        st1             {v4.8h},  [x2], x9
> +.endr
> +        bl              idct32_odd_quarter
> +        b               5f
> +4:
> +.irp i, 16, 17, 18, 19, 20, 21, 22, 23
> +        ld1             {v\i\().8h}, [x2]
> +        st1             {v4.8h},  [x2], x9
> +.endr
> +        bl              idct32_odd_half
>  
> +5:
>          transpose_8x8H v31, v30, v29, v28, v27, v26, v25, v24, v2, v3
>          transpose_8x8H v23, v22, v21, v20, v19, v18, v17, v16, v2, v3
>  
> @@ -1027,6 +1314,11 @@ function idct32_1d_8x32_pass2_neon
>          mov             x14, x30
>          ld1             {v0.8h,v1.8h}, [x10]
>  
> +        cmp             w3,  #34
> +        b.le            3f
> +        cmp             w3,  #135
> +        b.le            4f
> +
>          // v16 = IN(0), v17 = IN(2) ... v31 = IN(30)
>  .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
>          ld1             {v\i\().8h}, [x2], x9
> @@ -1034,7 +1326,22 @@ function idct32_1d_8x32_pass2_neon
>          sub             x2,  x2,  x9, lsl #4
>  
>          bl              idct16
> +        b               5f
> +3:
> +.irp i, 16, 17, 18, 19
> +        ld1             {v\i\().8h}, [x2], x9
> +.endr
> +        sub             x2,  x2,  x9, lsl #2
> +        bl              idct16_quarter
> +        b               5f
> +4:
> +.irp i, 16, 17, 18, 19, 20, 21, 22, 23
> +        ld1             {v\i\().8h}, [x2], x9
> +.endr
> +        sub             x2,  x2,  x9, lsl #3
> +        bl              idct16_half
>  
> +5:
>  .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
>          st1             {v\i\().8h}, [x2], x9
>  .endr
> @@ -1042,15 +1349,35 @@ function idct32_1d_8x32_pass2_neon
>          sub             x2,  x2,  x9, lsl #4
>          add             x2,  x2,  #64
>  
> +        cmp             w3,  #34
> +        b.le            3f
> +        cmp             w3,  #135
> +        b.le            4f
> +
>          // v16 = IN(1), v17 = IN(3) ... v31 = IN(31)
>  .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
>          ld1             {v\i\().8h}, [x2], x9
>  .endr
>          sub             x2,  x2,  x9, lsl #4
> -        sub             x2,  x2,  #64
>  
>          bl              idct32_odd
> +        b               5f
> +3:
> +.irp i, 16, 17, 18, 19
> +        ld1             {v\i\().8h}, [x2], x9
> +.endr
> +        sub             x2,  x2,  x9, lsl #2
> +        bl              idct32_odd_quarter
> +        b               5f
> +4:
> +.irp i, 16, 17, 18, 19, 20, 21, 22, 23
> +        ld1             {v\i\().8h}, [x2], x9
> +.endr
> +        sub             x2,  x2,  x9, lsl #3
> +        bl              idct32_odd_half
>  
> +5:
> +        sub             x2,  x2,  #64
>  .macro load_acc_store a, b, c, d, neg=0
>  .if \neg == 0
>          ld1             {v4.8h},  [x2], x9

otherwise ok with the changes from the arm version folded into this

Janne
Martin Storsjö Feb. 5, 2017, 12:05 p.m. | #2
On Sun, 5 Feb 2017, Janne Grunau wrote:

> On 2016-12-01 11:27:01 +0200, Martin Storsjö wrote:
>> This work is sponsored by, and copyright, Google.
>> 
>> This increases the code size of libavcodec/aarch64/vp9itxfm_neon.o
>> from 14740 to 18504 bytes.
>> 
>> Before:
>> vp9_inv_dct_dct_16x16_sub1_add_neon:     235.3
>> vp9_inv_dct_dct_16x16_sub2_add_neon:    1051.0
>> vp9_inv_dct_dct_16x16_sub4_add_neon:    1051.0
>> vp9_inv_dct_dct_16x16_sub8_add_neon:    1051.0
>> vp9_inv_dct_dct_16x16_sub12_add_neon:   1390.3
>> vp9_inv_dct_dct_16x16_sub16_add_neon:   1390.1
>> vp9_inv_dct_dct_32x32_sub1_add_neon:     556.5
>> vp9_inv_dct_dct_32x32_sub2_add_neon:    5199.1
>> vp9_inv_dct_dct_32x32_sub4_add_neon:    5199.9
>> vp9_inv_dct_dct_32x32_sub8_add_neon:    5196.9
>> vp9_inv_dct_dct_32x32_sub12_add_neon:   6171.6
>> vp9_inv_dct_dct_32x32_sub16_add_neon:   6170.9
>> vp9_inv_dct_dct_32x32_sub20_add_neon:   7147.1
>> vp9_inv_dct_dct_32x32_sub24_add_neon:   7147.0
>> vp9_inv_dct_dct_32x32_sub28_add_neon:   8118.8
>> vp9_inv_dct_dct_32x32_sub32_add_neon:   8125.8
>> 
>> After:
>> vp9_inv_dct_dct_16x16_sub1_add_neon:     235.3
>> vp9_inv_dct_dct_16x16_sub2_add_neon:     697.0
>> vp9_inv_dct_dct_16x16_sub4_add_neon:     697.0
>> vp9_inv_dct_dct_16x16_sub8_add_neon:     908.0
>> vp9_inv_dct_dct_16x16_sub12_add_neon:   1399.6
>> vp9_inv_dct_dct_16x16_sub16_add_neon:   1403.3
>> vp9_inv_dct_dct_32x32_sub1_add_neon:     554.1
>> vp9_inv_dct_dct_32x32_sub2_add_neon:    3879.7
>> vp9_inv_dct_dct_32x32_sub4_add_neon:    3952.2
>> vp9_inv_dct_dct_32x32_sub8_add_neon:    3948.4
>> vp9_inv_dct_dct_32x32_sub12_add_neon:   5462.1
>> vp9_inv_dct_dct_32x32_sub16_add_neon:   5461.7
>> vp9_inv_dct_dct_32x32_sub20_add_neon:   7169.2
>> vp9_inv_dct_dct_32x32_sub24_add_neon:   7162.4
>> vp9_inv_dct_dct_32x32_sub28_add_neon:   8137.4
>> vp9_inv_dct_dct_32x32_sub32_add_neon:   8136.7
>> 
>> I.e. in general a very minor overhead for the full subpartition case due
>> to the additional cmps, but a significant speedup for the cases when we
>> only need to process a small part of the actual input data.
>> ---
>> If we wouldn't have made the core transforms standalone functions,
>> the code size would end up at around 28 KB.
>> ---
>>  libavcodec/aarch64/vp9itxfm_neon.S | 367 +++++++++++++++++++++++++++++++++++--
>>  1 file changed, 347 insertions(+), 20 deletions(-)
>> 
>> diff --git a/libavcodec/aarch64/vp9itxfm_neon.S b/libavcodec/aarch64/vp9itxfm_neon.S
>> index be9643e..bb79348 100644
>> --- a/libavcodec/aarch64/vp9itxfm_neon.S
>> +++ b/libavcodec/aarch64/vp9itxfm_neon.S
>> @@ -75,6 +75,16 @@ endconst
>>  .endif
>>  .endm
>> 
>> +// Same as dmbutterfly0 above, but treating the input in in2 as zero,
>> +// writing the same output into both out1 and out2.
>> +.macro dmbutterfly0_h out1, out2, in1, in2, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6
>> +        smull           \tmp1\().4s,  \in1\().4h,  v0.h[0]
>> +        smull2          \tmp2\().4s,  \in1\().8h,  v0.h[0]
>> +        rshrn           \out1\().4h,  \tmp1\().4s, #14
>> +        rshrn2          \out1\().8h,  \tmp2\().4s, #14
>> +        mov             \out2\().16b, \out1\().16b
>> +.endm
>> +
>>  // out1,out2 = in1 * coef1 - in2 * coef2
>>  // out3,out4 = in1 * coef2 + in2 * coef1
>>  // out are 4 x .4s registers, in are 2 x .8h registers
>> @@ -104,6 +114,43 @@ endconst
>>          rshrn2          \inout2\().8h, \tmp4\().4s,  #14
>>  .endm
>> 
>> +// Same as dmbutterfly above, but treating the input in inout2 as zero
>> +.macro dmbutterfly_h1 inout1, inout2, coef1, coef2, tmp1, tmp2, tmp3, tmp4
>> +        smull           \tmp1\().4s, \inout1\().4h, \coef1
>> +        smull2          \tmp2\().4s, \inout1\().8h, \coef1
>> +        smull           \tmp3\().4s, \inout1\().4h, \coef2
>> +        smull2          \tmp4\().4s, \inout1\().8h, \coef2
>> +        rshrn           \inout1\().4h, \tmp1\().4s, #14
>> +        rshrn2          \inout1\().8h, \tmp2\().4s, #14
>> +        rshrn           \inout2\().4h, \tmp3\().4s, #14
>> +        rshrn2          \inout2\().8h, \tmp4\().4s, #14
>> +.endm
>> +
>> +// Same as dmbutterfly above, but treating the input in inout1 as zero
>> +.macro dmbutterfly_h2 inout1, inout2, coef1, coef2, tmp1, tmp2, tmp3, tmp4
>> +        smull           \tmp1\().4s, \inout2\().4h, \coef2
>> +        smull2          \tmp2\().4s, \inout2\().8h, \coef2
>> +        smull           \tmp3\().4s, \inout2\().4h, \coef1
>> +        smull2          \tmp4\().4s, \inout2\().8h, \coef1
>> +        neg             \tmp1\().4s, \tmp1\().4s
>> +        neg             \tmp2\().4s, \tmp2\().4s
>> +        rshrn           \inout2\().4h, \tmp3\().4s, #14
>> +        rshrn2          \inout2\().8h, \tmp4\().4s, #14
>> +        rshrn           \inout1\().4h, \tmp1\().4s, #14
>> +        rshrn2          \inout1\().8h, \tmp2\().4s, #14
>> +.endm
>> +
>> +.macro dsmull_h out1, out2, in, coef
>> +        smull           \out1\().4s, \in\().4h, \coef
>> +        smull2          \out2\().4s, \in\().8h, \coef
>> +.endm
>> +
>> +.macro drshrn_h out, in1, in2, shift
>> +        rshrn           \out\().4h, \in1\().4s, \shift
>> +        rshrn2          \out\().8h, \in2\().4s, \shift
>> +.endm
>> +
>> +
>>  // out1 = in1 + in2
>>  // out2 = in1 - in2
>>  .macro butterfly_8h out1, out2, in1, in2
>> @@ -463,7 +510,7 @@ function idct16x16_dc_add_neon
>>          ret
>>  endfunc
>> 
>> -function idct16
>> +.macro idct16_full
>>          dmbutterfly0    v16, v24, v16, v24, v2, v3, v4, v5, v6, v7 // v16 = t0a,  v24 = t1a
>>          dmbutterfly     v20, v28, v0.h[1], v0.h[2], v2, v3, v4, v5 // v20 = t2a,  v28 = t3a
>>          dmbutterfly     v18, v30, v0.h[3], v0.h[4], v2, v3, v4, v5 // v18 = t4a,  v30 = t7a
>> @@ -485,7 +532,10 @@ function idct16
>>          dmbutterfly0    v22, v26, v22, v26, v2, v3, v18, v19, v30, v31        // v22 = t6a,  v26 = t5a
>>          dmbutterfly     v23, v25, v0.h[1], v0.h[2], v18, v19, v30, v31        // v23 = t9a,  v25 = t14a
>>          dmbutterfly     v27, v21, v0.h[1], v0.h[2], v18, v19, v30, v31, neg=1 // v27 = t13a, v21 = t10a
>> +        idct16_end
>
> I think it would be clearer if idct16_end is used directly from the 
> macro. it would probably also make sense to move idct16_end and avoid 
> the idct16_full macro. The patch might be smaller and it is immediately 
> obvious that there is no code change but the resulting code is more 
> comlicated than it needs to be. same applies to arm if we go with 
> alternative 1.

Ok, so you mean like this?

function idct16
         dmbutterfly...
         ....
         idct16_end
endfunc

The same goes for alt 2 as well, these parts are identical in both.

// Martin
Janne Grunau Feb. 9, 2017, 7:47 a.m. | #3
On 2017-02-05 14:05:49 +0200, Martin Storsjö wrote:
> On Sun, 5 Feb 2017, Janne Grunau wrote:
> 
> >> // out1 = in1 + in2
> >> // out2 = in1 - in2
> >> .macro butterfly_8h out1, out2, in1, in2
> >>@@ -463,7 +510,7 @@ function idct16x16_dc_add_neon
> >>         ret
> >> endfunc
> >>
> >>-function idct16
> >>+.macro idct16_full
> >>         dmbutterfly0    v16, v24, v16, v24, v2, v3, v4, v5, v6, v7 // v16 = t0a,  v24 = t1a
> >>         dmbutterfly     v20, v28, v0.h[1], v0.h[2], v2, v3, v4, v5 // v20 = t2a,  v28 = t3a
> >>         dmbutterfly     v18, v30, v0.h[3], v0.h[4], v2, v3, v4, v5 // v18 = t4a,  v30 = t7a
> >>@@ -485,7 +532,10 @@ function idct16
> >>         dmbutterfly0    v22, v26, v22, v26, v2, v3, v18, v19, v30, v31        // v22 = t6a,  v26 = t5a
> >>         dmbutterfly     v23, v25, v0.h[1], v0.h[2], v18, v19, v30, v31        // v23 = t9a,  v25 = t14a
> >>         dmbutterfly     v27, v21, v0.h[1], v0.h[2], v18, v19, v30, v31, neg=1 // v27 = t13a, v21 = t10a
> >>+        idct16_end
> >
> >I think it would be clearer if idct16_end is used directly from the macro.
> >it would probably also make sense to move idct16_end and avoid the
> >idct16_full macro. The patch might be smaller and it is immediately
> >obvious that there is no code change but the resulting code is more
> >comlicated than it needs to be. same applies to arm if we go with
> >alternative 1.
> 
> Ok, so you mean like this?
> 
> function idct16
>         dmbutterfly...
>         ....
>         idct16_end
> endfunc

that would be one option, the other would be to move the idct_end 
instructions as a macro out of the the existing idct16 function and use 
it as macro. That would make the full idct structural identical to the 
half and quarter version and avoid a macro only used once.

Janne
Martin Storsjö Feb. 9, 2017, 7:50 a.m. | #4
On Thu, 9 Feb 2017, Janne Grunau wrote:

> On 2017-02-05 14:05:49 +0200, Martin Storsjö wrote:
>> On Sun, 5 Feb 2017, Janne Grunau wrote:
>> 
>> >> // out1 = in1 + in2
>> >> // out2 = in1 - in2
>> >> .macro butterfly_8h out1, out2, in1, in2
>> >>@@ -463,7 +510,7 @@ function idct16x16_dc_add_neon
>> >>         ret
>> >> endfunc
>> >>
>> >>-function idct16
>> >>+.macro idct16_full
>> >>         dmbutterfly0    v16, v24, v16, v24, v2, v3, v4, v5, v6, v7 // v16 = t0a,  v24 = t1a
>> >>         dmbutterfly     v20, v28, v0.h[1], v0.h[2], v2, v3, v4, v5 // v20 = t2a,  v28 = t3a
>> >>         dmbutterfly     v18, v30, v0.h[3], v0.h[4], v2, v3, v4, v5 // v18 = t4a,  v30 = t7a
>> >>@@ -485,7 +532,10 @@ function idct16
>> >>         dmbutterfly0    v22, v26, v22, v26, v2, v3, v18, v19, v30, v31        // v22 = t6a,  v26 = t5a
>> >>         dmbutterfly     v23, v25, v0.h[1], v0.h[2], v18, v19, v30, v31        // v23 = t9a,  v25 = t14a
>> >>         dmbutterfly     v27, v21, v0.h[1], v0.h[2], v18, v19, v30, v31, neg=1 // v27 = t13a, v21 = t10a
>> >>+        idct16_end
>> >
>> >I think it would be clearer if idct16_end is used directly from the macro.
>> >it would probably also make sense to move idct16_end and avoid the
>> >idct16_full macro. The patch might be smaller and it is immediately
>> >obvious that there is no code change but the resulting code is more
>> >comlicated than it needs to be. same applies to arm if we go with
>> >alternative 1.
>> 
>> Ok, so you mean like this?
>> 
>> function idct16
>>         dmbutterfly...
>>         ....
>>         idct16_end
>> endfunc
>
> that would be one option, the other would be to move the idct_end 
> instructions as a macro out of the the existing idct16 function and use 
> it as macro. That would make the full idct structural identical to the 
> half and quarter version and avoid a macro only used once.

I'm not really following what you're suggesting here - can you outline it 
with a code sample like mine above?

// Martin
Janne Grunau Feb. 9, 2017, 8:06 a.m. | #5
On 2017-02-09 09:50:48 +0200, Martin Storsjö wrote:
> On Thu, 9 Feb 2017, Janne Grunau wrote:
> 
> >On 2017-02-05 14:05:49 +0200, Martin Storsjö wrote:
> >>On Sun, 5 Feb 2017, Janne Grunau wrote:
> >>
> >>>> // out1 = in1 + in2
> >>>> // out2 = in1 - in2
> >>>> .macro butterfly_8h out1, out2, in1, in2
> >>>>@@ -463,7 +510,7 @@ function idct16x16_dc_add_neon
> >>>>         ret
> >>>> endfunc
> >>>>
> >>>>-function idct16
> >>>>+.macro idct16_full
> >>>>         dmbutterfly0    v16, v24, v16, v24, v2, v3, v4, v5, v6, v7 // v16 = t0a,  v24 = t1a
> >>>>         dmbutterfly     v20, v28, v0.h[1], v0.h[2], v2, v3, v4, v5 // v20 = t2a,  v28 = t3a
> >>>>         dmbutterfly     v18, v30, v0.h[3], v0.h[4], v2, v3, v4, v5 // v18 = t4a,  v30 = t7a
> >>>>@@ -485,7 +532,10 @@ function idct16
> >>>>         dmbutterfly0    v22, v26, v22, v26, v2, v3, v18, v19, v30, v31        // v22 = t6a,  v26 = t5a
> >>>>         dmbutterfly     v23, v25, v0.h[1], v0.h[2], v18, v19, v30, v31        // v23 = t9a,  v25 = t14a
> >>>>         dmbutterfly     v27, v21, v0.h[1], v0.h[2], v18, v19, v30, v31, neg=1 // v27 = t13a, v21 = t10a
> >>>>+        idct16_end
> >>>
> >>>I think it would be clearer if idct16_end is used directly from the macro.
> >>>it would probably also make sense to move idct16_end and avoid the
> >>>idct16_full macro. The patch might be smaller and it is immediately
> >>>obvious that there is no code change but the resulting code is more
> >>>comlicated than it needs to be. same applies to arm if we go with
> >>>alternative 1.
> >>
> >>Ok, so you mean like this?
> >>
> >>function idct16
> >>        dmbutterfly...
> >>        ....
> >>        idct16_end
> >>endfunc
> >
> >that would be one option, the other would be to move the idct_end
> >instructions as a macro out of the the existing idct16 function and use it
> >as macro. That would make the full idct structural identical to the half
> >and quarter version and avoid a macro only used once.
> 
> I'm not really following what you're suggesting here - can you outline it
> with a code sample like mine above?

sorry, it seems I wasn't fully awake. I misread your code snipped. To 
avoid any confusing here is what I ment outlined as pseudo patch:

@@
+.macro idct16_end
+    [code from the existing idct16 function]
+.endm
+
 function idct16
@@ ...
 
+    idct16_end
-    [code moved to the idct16_end macro]
 endfunc

Janne
Martin Storsjö Feb. 9, 2017, 8:19 a.m. | #6
On Thu, 9 Feb 2017, Janne Grunau wrote:

> On 2017-02-09 09:50:48 +0200, Martin Storsjö wrote:
>> On Thu, 9 Feb 2017, Janne Grunau wrote:
>> 
>> >On 2017-02-05 14:05:49 +0200, Martin Storsjö wrote:
>> >>On Sun, 5 Feb 2017, Janne Grunau wrote:
>> >>
>> >>>> // out1 = in1 + in2
>> >>>> // out2 = in1 - in2
>> >>>> .macro butterfly_8h out1, out2, in1, in2
>> >>>>@@ -463,7 +510,7 @@ function idct16x16_dc_add_neon
>> >>>>         ret
>> >>>> endfunc
>> >>>>
>> >>>>-function idct16
>> >>>>+.macro idct16_full
>> >>>>         dmbutterfly0    v16, v24, v16, v24, v2, v3, v4, v5, v6, v7 // v16 = t0a,  v24 = t1a
>> >>>>         dmbutterfly     v20, v28, v0.h[1], v0.h[2], v2, v3, v4, v5 // v20 = t2a,  v28 = t3a
>> >>>>         dmbutterfly     v18, v30, v0.h[3], v0.h[4], v2, v3, v4, v5 // v18 = t4a,  v30 = t7a
>> >>>>@@ -485,7 +532,10 @@ function idct16
>> >>>>         dmbutterfly0    v22, v26, v22, v26, v2, v3, v18, v19, v30, v31        // v22 = t6a,  v26 = t5a
>> >>>>         dmbutterfly     v23, v25, v0.h[1], v0.h[2], v18, v19, v30, v31        // v23 = t9a,  v25 = t14a
>> >>>>         dmbutterfly     v27, v21, v0.h[1], v0.h[2], v18, v19, v30, v31, neg=1 // v27 = t13a, v21 = t10a
>> >>>>+        idct16_end
>> >>>
>> >>>I think it would be clearer if idct16_end is used directly from the macro.
>> >>>it would probably also make sense to move idct16_end and avoid the
>> >>>idct16_full macro. The patch might be smaller and it is immediately
>> >>>obvious that there is no code change but the resulting code is more
>> >>>comlicated than it needs to be. same applies to arm if we go with
>> >>>alternative 1.
>> >>
>> >>Ok, so you mean like this?
>> >>
>> >>function idct16
>> >>        dmbutterfly...
>> >>        ....
>> >>        idct16_end
>> >>endfunc
>> >
>> >that would be one option, the other would be to move the idct_end
>> >instructions as a macro out of the the existing idct16 function and use it
>> >as macro. That would make the full idct structural identical to the half
>> >and quarter version and avoid a macro only used once.
>> 
>> I'm not really following what you're suggesting here - can you outline it
>> with a code sample like mine above?
>
> sorry, it seems I wasn't fully awake. I misread your code snipped. To 
> avoid any confusing here is what I ment outlined as pseudo patch:
>
> @@
> +.macro idct16_end
> +    [code from the existing idct16 function]
> +.endm
> +
> function idct16
> @@ ...
> 
> +    idct16_end
> -    [code moved to the idct16_end macro]
> endfunc

Right - yes, that's exactly what I meant, and what I did locally based on 
your earlier comment.

// Martin

Patch

diff --git a/libavcodec/aarch64/vp9itxfm_neon.S b/libavcodec/aarch64/vp9itxfm_neon.S
index be9643e..bb79348 100644
--- a/libavcodec/aarch64/vp9itxfm_neon.S
+++ b/libavcodec/aarch64/vp9itxfm_neon.S
@@ -75,6 +75,16 @@  endconst
 .endif
 .endm
 
+// Same as dmbutterfly0 above, but treating the input in in2 as zero,
+// writing the same output into both out1 and out2.
+.macro dmbutterfly0_h out1, out2, in1, in2, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6
+        smull           \tmp1\().4s,  \in1\().4h,  v0.h[0]
+        smull2          \tmp2\().4s,  \in1\().8h,  v0.h[0]
+        rshrn           \out1\().4h,  \tmp1\().4s, #14
+        rshrn2          \out1\().8h,  \tmp2\().4s, #14
+        mov             \out2\().16b, \out1\().16b
+.endm
+
 // out1,out2 = in1 * coef1 - in2 * coef2
 // out3,out4 = in1 * coef2 + in2 * coef1
 // out are 4 x .4s registers, in are 2 x .8h registers
@@ -104,6 +114,43 @@  endconst
         rshrn2          \inout2\().8h, \tmp4\().4s,  #14
 .endm
 
+// Same as dmbutterfly above, but treating the input in inout2 as zero
+.macro dmbutterfly_h1 inout1, inout2, coef1, coef2, tmp1, tmp2, tmp3, tmp4
+        smull           \tmp1\().4s, \inout1\().4h, \coef1
+        smull2          \tmp2\().4s, \inout1\().8h, \coef1
+        smull           \tmp3\().4s, \inout1\().4h, \coef2
+        smull2          \tmp4\().4s, \inout1\().8h, \coef2
+        rshrn           \inout1\().4h, \tmp1\().4s, #14
+        rshrn2          \inout1\().8h, \tmp2\().4s, #14
+        rshrn           \inout2\().4h, \tmp3\().4s, #14
+        rshrn2          \inout2\().8h, \tmp4\().4s, #14
+.endm
+
+// Same as dmbutterfly above, but treating the input in inout1 as zero
+.macro dmbutterfly_h2 inout1, inout2, coef1, coef2, tmp1, tmp2, tmp3, tmp4
+        smull           \tmp1\().4s, \inout2\().4h, \coef2
+        smull2          \tmp2\().4s, \inout2\().8h, \coef2
+        smull           \tmp3\().4s, \inout2\().4h, \coef1
+        smull2          \tmp4\().4s, \inout2\().8h, \coef1
+        neg             \tmp1\().4s, \tmp1\().4s
+        neg             \tmp2\().4s, \tmp2\().4s
+        rshrn           \inout2\().4h, \tmp3\().4s, #14
+        rshrn2          \inout2\().8h, \tmp4\().4s, #14
+        rshrn           \inout1\().4h, \tmp1\().4s, #14
+        rshrn2          \inout1\().8h, \tmp2\().4s, #14
+.endm
+
+.macro dsmull_h out1, out2, in, coef
+        smull           \out1\().4s, \in\().4h, \coef
+        smull2          \out2\().4s, \in\().8h, \coef
+.endm
+
+.macro drshrn_h out, in1, in2, shift
+        rshrn           \out\().4h, \in1\().4s, \shift
+        rshrn2          \out\().8h, \in2\().4s, \shift
+.endm
+
+
 // out1 = in1 + in2
 // out2 = in1 - in2
 .macro butterfly_8h out1, out2, in1, in2
@@ -463,7 +510,7 @@  function idct16x16_dc_add_neon
         ret
 endfunc
 
-function idct16
+.macro idct16_full
         dmbutterfly0    v16, v24, v16, v24, v2, v3, v4, v5, v6, v7 // v16 = t0a,  v24 = t1a
         dmbutterfly     v20, v28, v0.h[1], v0.h[2], v2, v3, v4, v5 // v20 = t2a,  v28 = t3a
         dmbutterfly     v18, v30, v0.h[3], v0.h[4], v2, v3, v4, v5 // v18 = t4a,  v30 = t7a
@@ -485,7 +532,10 @@  function idct16
         dmbutterfly0    v22, v26, v22, v26, v2, v3, v18, v19, v30, v31        // v22 = t6a,  v26 = t5a
         dmbutterfly     v23, v25, v0.h[1], v0.h[2], v18, v19, v30, v31        // v23 = t9a,  v25 = t14a
         dmbutterfly     v27, v21, v0.h[1], v0.h[2], v18, v19, v30, v31, neg=1 // v27 = t13a, v21 = t10a
+        idct16_end
+.endm
 
+.macro idct16_end
         butterfly_8h    v18, v7,  v4,  v7                // v18 = t0a,  v7  = t7a
         butterfly_8h    v19, v22, v5,  v22               // v19 = t1a,  v22 = t6
         butterfly_8h    v4,  v26, v20, v26               // v4  = t2a,  v26 = t5
@@ -507,6 +557,68 @@  function idct16
         butterfly_8h    v20, v27, v6,  v27               // v20 = out[4], v27 = out[11]
         butterfly_8h    v21, v26, v26, v3                // v21 = out[5], v26 = out[10]
         ret
+.endm
+
+function idct16
+        idct16_full
+endfunc
+
+function idct16_half
+        dmbutterfly0_h  v16, v24, v16, v24, v2, v3, v4, v5, v6, v7 // v16 = t0a,  v24 = t1a
+        dmbutterfly_h1  v20, v28, v0.h[1], v0.h[2], v2, v3, v4, v5 // v20 = t2a,  v28 = t3a
+        dmbutterfly_h1  v18, v30, v0.h[3], v0.h[4], v2, v3, v4, v5 // v18 = t4a,  v30 = t7a
+        dmbutterfly_h2  v26, v22, v0.h[5], v0.h[6], v2, v3, v4, v5 // v26 = t5a,  v22 = t6a
+        dmbutterfly_h1  v17, v31, v0.h[7], v1.h[0], v2, v3, v4, v5 // v17 = t8a,  v31 = t15a
+        dmbutterfly_h2  v25, v23, v1.h[1], v1.h[2], v2, v3, v4, v5 // v25 = t9a,  v23 = t14a
+        dmbutterfly_h1  v21, v27, v1.h[3], v1.h[4], v2, v3, v4, v5 // v21 = t10a, v27 = t13a
+        dmbutterfly_h2  v29, v19, v1.h[5], v1.h[6], v2, v3, v4, v5 // v29 = t11a, v19 = t12a
+
+        butterfly_8h    v4,  v28, v16, v28               // v4  = t0,   v28 = t3
+        butterfly_8h    v5,  v20, v24, v20               // v5  = t1,   v20 = t2
+        butterfly_8h    v6,  v26, v18, v26               // v6  = t4,   v26 = t5
+        butterfly_8h    v7,  v22, v30, v22               // v7  = t7,   v22 = t6
+        butterfly_8h    v16, v25, v17, v25               // v16 = t8,   v25 = t9
+        butterfly_8h    v24, v21, v29, v21               // v24 = t11,  v21 = t10
+        butterfly_8h    v17, v27, v19, v27               // v17 = t12,  v27 = t13
+        butterfly_8h    v29, v23, v31, v23               // v29 = t15,  v23 = t14
+
+        dmbutterfly0    v22, v26, v22, v26, v2, v3, v18, v19, v30, v31        // v22 = t6a,  v26 = t5a
+        dmbutterfly     v23, v25, v0.h[1], v0.h[2], v18, v19, v30, v31        // v23 = t9a,  v25 = t14a
+        dmbutterfly     v27, v21, v0.h[1], v0.h[2], v18, v19, v30, v31, neg=1 // v27 = t13a, v21 = t10a
+        idct16_end
+endfunc
+
+function idct16_quarter
+        dsmull_h        v24, v25, v19, v1.h[6]
+        dsmull_h        v4,  v5,  v17, v0.h[7]
+        dsmull_h        v7,  v6,  v18, v0.h[4]
+        dsmull_h        v30, v31, v18, v0.h[3]
+        neg             v24.4s,  v24.4s
+        neg             v25.4s,  v25.4s
+        dsmull_h        v29, v28, v17, v1.h[0]
+        dsmull_h        v26, v27, v19, v1.h[5]
+        dsmull_h        v22, v23, v16, v0.h[0]
+        drshrn_h        v24, v24, v25, #14
+        drshrn_h        v16, v4,  v5,  #14
+        drshrn_h        v7,  v7,  v6,  #14
+        drshrn_h        v6,  v30, v31, #14
+        drshrn_h        v29, v29, v28, #14
+        drshrn_h        v17, v26, v27, #14
+        drshrn_h        v28, v22, v23, #14
+
+        dmbutterfly_l   v20, v21, v22, v23, v17, v24, v0.h[1], v0.h[2]
+        dmbutterfly_l   v18, v19, v30, v31, v29, v16, v0.h[1], v0.h[2]
+        neg             v22.4s,  v22.4s
+        neg             v23.4s,  v23.4s
+        drshrn_h        v27, v20, v21, #14
+        drshrn_h        v21, v22, v23, #14
+        drshrn_h        v23, v18, v19, #14
+        drshrn_h        v25, v30, v31, #14
+        mov             v4.16b,  v28.16b
+        mov             v5.16b,  v28.16b
+        dmbutterfly0    v22, v26, v7,  v6,  v18, v19, v30, v31
+        mov             v20.16b, v28.16b
+        idct16_end
 endfunc
 
 function iadst16
@@ -609,12 +721,37 @@  function \txfm\()16_1d_8x16_pass1_neon
         mov             x14, x30
 
         movi            v2.8h, #0
+
+.ifc \txfm,idct
+        cmp             w3, #10
+        b.le            3f
+        cmp             w3, #38
+        b.le            4f
+.endif
+
 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
         load_clear      \i,  x2,  x9
 .endr
 
         bl              \txfm\()16
+.ifc \txfm,idct
+        b               5f
+
+3:
+.irp i, 16, 17, 18, 19
+        load_clear      \i,  x2,  x9
+.endr
+        bl              idct16_quarter
+        b               5f
 
+4:
+.irp i, 16, 17, 18, 19, 20, 21, 22, 23
+        load_clear      \i,  x2,  x9
+.endr
+        bl              idct16_half
+.endif
+
+5:
         // Do two 8x8 transposes. Originally, v16-v31 contain the
         // 16 rows. Afterwards, v16-v23 and v24-v31 contain the two
         // transposed 8x8 blocks.
@@ -654,38 +791,60 @@  endfunc
 // x0 = dst
 // x1 = dst stride
 // x2 = src (temp buffer)
-// x3 = slice offset
+// w3 = eob
 // x9 = temp buffer stride
+// x13 = slice offset
 function \txfm\()16_1d_8x16_pass2_neon
         mov             x14, x30
+.ifc \txfm,idct
+        cmp             w3, #10
+        b.le            3f
+        cmp             w3, #38
+        b.le            4f
+.endif
 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
         load            \i,  x2,  x9
 .endr
-        cbz             x3,  1f
+        cbz             x13, 1f
 .irp i, 24, 25, 26, 27, 28, 29, 30, 31
         load            \i,  x2,  x9
 .endr
 1:
 
-        add             x3,  x0,  x1
-        lsl             x1,  x1,  #1
         bl              \txfm\()16
+.ifc \txfm,idct
+        b               5f
+3:
+.irp i, 16, 17, 18, 19
+        load            \i,  x2,  x9
+.endr
+        bl              idct16_quarter
+        b               5f
+4:
+.irp i, 16, 17, 18, 19, 20, 21, 22, 23
+        load            \i,  x2,  x9
+.endr
+        bl              idct16_half
+.endif
 
+5:
+        add             x8,  x0,  x1
+        lsl             x1,  x1,  #1
 .macro load_add_store coef0, coef1, coef2, coef3, coef4, coef5, coef6, coef7, tmp1, tmp2
         srshr           \coef0, \coef0, #6
         ld1             {v2.8b},  [x0], x1
         srshr           \coef1, \coef1, #6
-        ld1             {v3.8b},  [x3], x1
+        ld1             {v3.8b},  [x8], x1
         srshr           \coef2, \coef2, #6
         ld1             {v4.8b},  [x0], x1
         srshr           \coef3, \coef3, #6
         uaddw           \coef0, \coef0, v2.8b
-        ld1             {v5.8b},  [x3], x1
+        ld1             {v5.8b},  [x8], x1
         uaddw           \coef1, \coef1, v3.8b
         srshr           \coef4, \coef4, #6
         ld1             {v6.8b},  [x0], x1
         srshr           \coef5, \coef5, #6
-        ld1             {v7.8b},  [x3], x1
+        ld1             {v7.8b},  [x8], x1
         sqxtun          v2.8b,  \coef0
         srshr           \coef6, \coef6, #6
         sqxtun          v3.8b,  \coef1
@@ -693,27 +852,27 @@  function \txfm\()16_1d_8x16_pass2_neon
         uaddw           \coef2, \coef2, v4.8b
         ld1             {\tmp1},  [x0], x1
         uaddw           \coef3, \coef3, v5.8b
-        ld1             {\tmp2},  [x3], x1
+        ld1             {\tmp2},  [x8], x1
         sqxtun          v4.8b,  \coef2
         sub             x0,  x0,  x1, lsl #2
-        sub             x3,  x3,  x1, lsl #2
+        sub             x8,  x8,  x1, lsl #2
         sqxtun          v5.8b,  \coef3
         uaddw           \coef4, \coef4, v6.8b
         st1             {v2.8b},  [x0], x1
         uaddw           \coef5, \coef5, v7.8b
-        st1             {v3.8b},  [x3], x1
+        st1             {v3.8b},  [x8], x1
         sqxtun          v6.8b,  \coef4
         st1             {v4.8b},  [x0], x1
         sqxtun          v7.8b,  \coef5
-        st1             {v5.8b},  [x3], x1
+        st1             {v5.8b},  [x8], x1
         uaddw           \coef6, \coef6, \tmp1
         st1             {v6.8b},  [x0], x1
         uaddw           \coef7, \coef7, \tmp2
-        st1             {v7.8b},  [x3], x1
+        st1             {v7.8b},  [x8], x1
         sqxtun          \tmp1,  \coef6
         sqxtun          \tmp2,  \coef7
         st1             {\tmp1},  [x0], x1
-        st1             {\tmp2},  [x3], x1
+        st1             {\tmp2},  [x8], x1
 .endm
         load_add_store  v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v16.8b, v17.8b
         load_add_store  v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h, v16.8b, v17.8b
@@ -750,6 +909,7 @@  function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
         movrel          x10, idct_coeffs
 .ifnc \txfm1\()_\txfm2,idct_idct
         movrel          x11, iadst16_coeffs
+        mov             w3,  #256
 .endif
 .ifc \txfm1,idct
         ld1             {v0.8h,v1.8h}, [x10]
@@ -792,7 +952,7 @@  function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
         add             x0,  x4,  #(\i)
         mov             x1,  x5
         add             x2,  sp,  #(\i*2)
-        mov             x3,  #\i
+        mov             x13, #\i
         bl              \txfm2\()16_1d_8x16_pass2_neon
 .endr
 
@@ -848,7 +1008,7 @@  function idct32x32_dc_add_neon
         ret
 endfunc
 
-function idct32_odd
+.macro idct32_odd_full
         ld1             {v0.8h,v1.8h}, [x11]
 
         dmbutterfly     v16, v31, v0.h[0], v0.h[1], v4, v5, v6, v7 // v16 = t16a, v31 = t31a
@@ -875,7 +1035,10 @@  function idct32_odd
         dmbutterfly     v27, v20, v0.h[3], v0.h[4], v16, v17, v18, v19, neg=1 // v27 = t29a, v20 = t18a
         dmbutterfly     v21, v26, v0.h[5], v0.h[6], v16, v17, v18, v19        // v21 = t21a, v26 = t26a
         dmbutterfly     v25, v22, v0.h[5], v0.h[6], v16, v17, v18, v19, neg=1 // v25 = t25a, v22 = t22a
+        idct32_end
+.endm
 
+.macro idct32_end
         butterfly_8h    v16, v5,  v4,  v5  // v16 = t16a, v5  = t19a
         butterfly_8h    v17, v20, v23, v20 // v17 = t17,  v20 = t18
         butterfly_8h    v18, v6,  v7,  v6  // v18 = t23a, v6  = t20a
@@ -904,6 +1067,88 @@  function idct32_odd
         dmbutterfly0    v25, v22, v25, v22, v2, v3, v4, v5, v6, v7 // v25 = t25,  v22 = t22
         dmbutterfly0    v24, v23, v24, v23, v2, v3, v4, v5, v6, v7 // v24 = t24a, v23 = t23a
         ret
+.endm
+
+function idct32_odd
+        idct32_odd_full
+endfunc
+
+function idct32_odd_half
+        ld1             {v0.8h,v1.8h}, [x11]
+
+        dmbutterfly_h1  v16, v31, v0.h[0], v0.h[1], v4, v5, v6, v7 // v16 = t16a, v31 = t31a
+        dmbutterfly_h2  v24, v23, v0.h[2], v0.h[3], v4, v5, v6, v7 // v24 = t17a, v23 = t30a
+        dmbutterfly_h1  v20, v27, v0.h[4], v0.h[5], v4, v5, v6, v7 // v20 = t18a, v27 = t29a
+        dmbutterfly_h2  v28, v19, v0.h[6], v0.h[7], v4, v5, v6, v7 // v28 = t19a, v19 = t28a
+        dmbutterfly_h1  v18, v29, v1.h[0], v1.h[1], v4, v5, v6, v7 // v18 = t20a, v29 = t27a
+        dmbutterfly_h2  v26, v21, v1.h[2], v1.h[3], v4, v5, v6, v7 // v26 = t21a, v21 = t26a
+        dmbutterfly_h1  v22, v25, v1.h[4], v1.h[5], v4, v5, v6, v7 // v22 = t22a, v25 = t25a
+        dmbutterfly_h2  v30, v17, v1.h[6], v1.h[7], v4, v5, v6, v7 // v30 = t23a, v17 = t24a
+
+        ld1             {v0.8h}, [x10]
+
+        butterfly_8h    v4,  v24, v16, v24 // v4  = t16, v24 = t17
+        butterfly_8h    v5,  v20, v28, v20 // v5  = t19, v20 = t18
+        butterfly_8h    v6,  v26, v18, v26 // v6  = t20, v26 = t21
+        butterfly_8h    v7,  v22, v30, v22 // v7  = t23, v22 = t22
+        butterfly_8h    v28, v25, v17, v25 // v28 = t24, v25 = t25
+        butterfly_8h    v30, v21, v29, v21 // v30 = t27, v21 = t26
+        butterfly_8h    v29, v23, v31, v23 // v29 = t31, v23 = t30
+        butterfly_8h    v31, v27, v19, v27 // v31 = t28, v27 = t29
+
+        dmbutterfly     v23, v24, v0.h[3], v0.h[4], v16, v17, v18, v19        // v23 = t17a, v24 = t30a
+        dmbutterfly     v27, v20, v0.h[3], v0.h[4], v16, v17, v18, v19, neg=1 // v27 = t29a, v20 = t18a
+        dmbutterfly     v21, v26, v0.h[5], v0.h[6], v16, v17, v18, v19        // v21 = t21a, v26 = t26a
+        dmbutterfly     v25, v22, v0.h[5], v0.h[6], v16, v17, v18, v19, neg=1 // v25 = t25a, v22 = t22a
+        idct32_end
+endfunc
+
+function idct32_odd_quarter
+        ld1             {v0.8h,v1.8h}, [x11]
+
+        dsmull_h        v4,  v5,  v16, v0.h[0]
+        dsmull_h        v28, v29, v19, v0.h[7]
+        dsmull_h        v30, v31, v16, v0.h[1]
+        dsmull_h        v22, v23, v17, v1.h[6]
+        dsmull_h        v7,  v6,  v17, v1.h[7]
+        dsmull_h        v26, v27, v19, v0.h[6]
+        dsmull_h        v20, v21, v18, v1.h[0]
+        dsmull_h        v24, v25, v18, v1.h[1]
+
+        ld1             {v0.8h}, [x10]
+
+        neg             v28.4s, v28.4s
+        neg             v29.4s, v29.4s
+        neg             v7.4s,  v7.4s
+        neg             v6.4s,  v6.4s
+
+        drshrn_h        v4,  v4,  v5,  #14
+        drshrn_h        v5,  v28, v29, #14
+        drshrn_h        v29, v30, v31, #14
+        drshrn_h        v28, v22, v23, #14
+        drshrn_h        v7,  v7,  v6,  #14
+        drshrn_h        v31, v26, v27, #14
+        drshrn_h        v6,  v20, v21, #14
+        drshrn_h        v30, v24, v25, #14
+
+        dmbutterfly_l   v16, v17, v18, v19, v29, v4,  v0.h[3], v0.h[4]
+        dmbutterfly_l   v27, v26, v20, v21, v31, v5,  v0.h[3], v0.h[4]
+        drshrn_h        v23, v16, v17, #14
+        drshrn_h        v24, v18, v19, #14
+        neg             v20.4s, v20.4s
+        neg             v21.4s, v21.4s
+        drshrn_h        v27, v27, v26, #14
+        drshrn_h        v20, v20, v21, #14
+        dmbutterfly_l   v16, v17, v18, v19, v30, v6,  v0.h[5], v0.h[6]
+        drshrn_h        v21, v16, v17, #14
+        drshrn_h        v26, v18, v19, #14
+        dmbutterfly_l   v16, v17, v18, v19, v28, v7,  v0.h[5], v0.h[6]
+        drshrn_h        v25, v16, v17, #14
+        neg             v18.4s, v18.4s
+        neg             v19.4s, v19.4s
+        drshrn_h        v22, v18, v19, #14
+
+        idct32_end
 endfunc
 
 // Do an 32-point IDCT of a 8x32 slice out of a 32x32 matrix.
@@ -923,6 +1168,11 @@  function idct32_1d_8x32_pass1_neon
 
         movi            v4.8h, #0
 
+        cmp             w3,  #4
+        b.le            3f
+        cmp             w3,  #135
+        b.le            4f
+
         // v16 = IN(0), v17 = IN(2) ... v31 = IN(30)
 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
         ld1             {v\i\().8h}, [x2]
@@ -930,7 +1180,25 @@  function idct32_1d_8x32_pass1_neon
 .endr
 
         bl              idct16
+        sub             x2,  x2,  x9, lsl #4
+        b               5f
+3:
+.irp i, 16, 17, 18, 19
+        ld1             {v\i\().8h}, [x2]
+        st1             {v4.8h},  [x2], x9
+.endr
+        bl              idct16_quarter
+        sub             x2,  x2,  x9, lsl #2
+        b               5f
+4:
+.irp i, 16, 17, 18, 19, 20, 21, 22, 23
+        ld1             {v\i\().8h}, [x2]
+        st1             {v4.8h},  [x2], x9
+.endr
+        bl              idct16_half
+        sub             x2,  x2,  x9, lsl #3
 
+5:
         // Do two 8x8 transposes. Originally, v16-v31 contain the
         // 16 rows. Afterwards, v16-v23 and v24-v31 contain the
         // two transposed 8x8 blocks.
@@ -962,12 +1230,16 @@  function idct32_1d_8x32_pass1_neon
         sub             x0,  x0,  #512
 .purgem store_rev
 
-        // Move x2 back to the start of the input, and move
-        // to the first odd row
-        sub             x2,  x2,  x9, lsl #4
+        // Move x2 to the first odd row
         add             x2,  x2,  #64
 
         movi            v4.8h, #0
+
+        cmp             w3,  #34
+        b.le            3f
+        cmp             w3,  #135
+        b.le            4f
+
         // v16 = IN(1), v17 = IN(3) ... v31 = IN(31)
 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
         ld1             {v\i\().8h}, [x2]
@@ -975,7 +1247,22 @@  function idct32_1d_8x32_pass1_neon
 .endr
 
         bl              idct32_odd
+        b               5f
+3:
+.irp i, 16, 17, 18, 19
+        ld1             {v\i\().8h}, [x2]
+        st1             {v4.8h},  [x2], x9
+.endr
+        bl              idct32_odd_quarter
+        b               5f
+4:
+.irp i, 16, 17, 18, 19, 20, 21, 22, 23
+        ld1             {v\i\().8h}, [x2]
+        st1             {v4.8h},  [x2], x9
+.endr
+        bl              idct32_odd_half
 
+5:
         transpose_8x8H v31, v30, v29, v28, v27, v26, v25, v24, v2, v3
         transpose_8x8H v23, v22, v21, v20, v19, v18, v17, v16, v2, v3
 
@@ -1027,6 +1314,11 @@  function idct32_1d_8x32_pass2_neon
         mov             x14, x30
         ld1             {v0.8h,v1.8h}, [x10]
 
+        cmp             w3,  #34
+        b.le            3f
+        cmp             w3,  #135
+        b.le            4f
+
         // v16 = IN(0), v17 = IN(2) ... v31 = IN(30)
 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
         ld1             {v\i\().8h}, [x2], x9
@@ -1034,7 +1326,22 @@  function idct32_1d_8x32_pass2_neon
         sub             x2,  x2,  x9, lsl #4
 
         bl              idct16
+        b               5f
+3:
+.irp i, 16, 17, 18, 19
+        ld1             {v\i\().8h}, [x2], x9
+.endr
+        sub             x2,  x2,  x9, lsl #2
+        bl              idct16_quarter
+        b               5f
+4:
+.irp i, 16, 17, 18, 19, 20, 21, 22, 23
+        ld1             {v\i\().8h}, [x2], x9
+.endr
+        sub             x2,  x2,  x9, lsl #3
+        bl              idct16_half
 
+5:
 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
         st1             {v\i\().8h}, [x2], x9
 .endr
@@ -1042,15 +1349,35 @@  function idct32_1d_8x32_pass2_neon
         sub             x2,  x2,  x9, lsl #4
         add             x2,  x2,  #64
 
+        cmp             w3,  #34
+        b.le            3f
+        cmp             w3,  #135
+        b.le            4f
+
         // v16 = IN(1), v17 = IN(3) ... v31 = IN(31)
 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
         ld1             {v\i\().8h}, [x2], x9
 .endr
         sub             x2,  x2,  x9, lsl #4
-        sub             x2,  x2,  #64
 
         bl              idct32_odd
+        b               5f
+3:
+.irp i, 16, 17, 18, 19
+        ld1             {v\i\().8h}, [x2], x9
+.endr
+        sub             x2,  x2,  x9, lsl #2
+        bl              idct32_odd_quarter
+        b               5f
+4:
+.irp i, 16, 17, 18, 19, 20, 21, 22, 23
+        ld1             {v\i\().8h}, [x2], x9
+.endr
+        sub             x2,  x2,  x9, lsl #3
+        bl              idct32_odd_half
 
+5:
+        sub             x2,  x2,  #64
 .macro load_acc_store a, b, c, d, neg=0
 .if \neg == 0
         ld1             {v4.8h},  [x2], x9