arm: vp9itxfm: Avoid reloading the idct32 coefficients

The idct32x32 function actually pushed q4-q7 onto the stack even
though it didn't clobber them; there are plenty of registers that
can be used to allow keeping all the idct coefficients in registers
without having to reload different subsets of them at different
stages in the transform.

Since the idct16 core transform avoids clobbering q4-q7 (but clobbers
q2-q3 instead, to avoid needing to back up and restore q4-q7 at all
in the idct16 function), and the lanewise vmul needs a register in
the q0-q3 range, we move the stored coefficients from q2-q3 into q4-q5
while doing idct16.

While keeping these coefficients in registers, we still can skip pushing
q7.

Before:                              Cortex A7       A8       A9      A53
vp9_inv_dct_dct_32x32_sub32_add_neon:  18553.8  17182.7  14303.3  12089.7
After:
vp9_inv_dct_dct_32x32_sub32_add_neon:  18470.3  16717.7  14173.6  11860.8

This is cherrypicked from libav commit
402546a172.

Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
Martin Storsjö 2017-01-02 22:50:38 +02:00
parent a88db8b9a0
commit 600f4c9b03

View File

@ -1185,58 +1185,51 @@ function idct32x32_dc_add_neon
endfunc
.macro idct32_end
butterfly d16, d5, d4, d5 @ d16 = t16a, d5 = t19a
butterfly d16, d9, d8, d9 @ d16 = t16a, d9 = t19a
butterfly d17, d20, d23, d20 @ d17 = t17, d20 = t18
butterfly d18, d6, d7, d6 @ d18 = t23a, d6 = t20a
butterfly d18, d10, d11, d10 @ d18 = t23a, d10 = t20a
butterfly d19, d21, d22, d21 @ d19 = t22, d21 = t21
butterfly d4, d28, d28, d30 @ d4 = t24a, d28 = t27a
butterfly d8, d28, d28, d30 @ d8 = t24a, d28 = t27a
butterfly d23, d26, d25, d26 @ d23 = t25, d26 = t26
butterfly d7, d29, d29, d31 @ d7 = t31a, d29 = t28a
butterfly d11, d29, d29, d31 @ d11 = t31a, d29 = t28a
butterfly d22, d27, d24, d27 @ d22 = t30, d27 = t29
mbutterfly d27, d20, d0[1], d0[2], q12, q15 @ d27 = t18a, d20 = t29a
mbutterfly d29, d5, d0[1], d0[2], q12, q15 @ d29 = t19, d5 = t28
mbutterfly d28, d6, d0[1], d0[2], q12, q15, neg=1 @ d28 = t27, d6 = t20
mbutterfly d29, d9, d0[1], d0[2], q12, q15 @ d29 = t19, d9 = t28
mbutterfly d28, d10, d0[1], d0[2], q12, q15, neg=1 @ d28 = t27, d10 = t20
mbutterfly d26, d21, d0[1], d0[2], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
butterfly d31, d24, d7, d4 @ d31 = t31, d24 = t24
butterfly d31, d24, d11, d8 @ d31 = t31, d24 = t24
butterfly d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
butterfly_r d23, d16, d16, d18 @ d23 = t23, d16 = t16
butterfly_r d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
butterfly d18, d21, d27, d21 @ d18 = t18, d21 = t21
butterfly_r d27, d28, d5, d28 @ d27 = t27a, d28 = t28a
butterfly d4, d26, d20, d26 @ d4 = t29, d26 = t26
butterfly d19, d20, d29, d6 @ d19 = t19a, d20 = t20
vmov d29, d4 @ d29 = t29
butterfly_r d27, d28, d9, d28 @ d27 = t27a, d28 = t28a
butterfly d8, d26, d20, d26 @ d8 = t29, d26 = t26
butterfly d19, d20, d29, d10 @ d19 = t19a, d20 = t20
vmov d29, d8 @ d29 = t29
mbutterfly0 d27, d20, d27, d20, d4, d6, q2, q3 @ d27 = t27, d20 = t20
mbutterfly0 d26, d21, d26, d21, d4, d6, q2, q3 @ d26 = t26a, d21 = t21a
mbutterfly0 d25, d22, d25, d22, d4, d6, q2, q3 @ d25 = t25, d22 = t22
mbutterfly0 d24, d23, d24, d23, d4, d6, q2, q3 @ d24 = t24a, d23 = t23a
mbutterfly0 d27, d20, d27, d20, d8, d10, q4, q5 @ d27 = t27, d20 = t20
mbutterfly0 d26, d21, d26, d21, d8, d10, q4, q5 @ d26 = t26a, d21 = t21a
mbutterfly0 d25, d22, d25, d22, d8, d10, q4, q5 @ d25 = t25, d22 = t22
mbutterfly0 d24, d23, d24, d23, d8, d10, q4, q5 @ d24 = t24a, d23 = t23a
bx lr
.endm
function idct32_odd
movrel r12, idct_coeffs
add r12, r12, #32
vld1.16 {q0-q1}, [r12,:128]
mbutterfly d16, d31, d4[0], d4[1], q4, q5 @ d16 = t16a, d31 = t31a
mbutterfly d24, d23, d4[2], d4[3], q4, q5 @ d24 = t17a, d23 = t30a
mbutterfly d20, d27, d5[0], d5[1], q4, q5 @ d20 = t18a, d27 = t29a
mbutterfly d28, d19, d5[2], d5[3], q4, q5 @ d28 = t19a, d19 = t28a
mbutterfly d18, d29, d6[0], d6[1], q4, q5 @ d18 = t20a, d29 = t27a
mbutterfly d26, d21, d6[2], d6[3], q4, q5 @ d26 = t21a, d21 = t26a
mbutterfly d22, d25, d7[0], d7[1], q4, q5 @ d22 = t22a, d25 = t25a
mbutterfly d30, d17, d7[2], d7[3], q4, q5 @ d30 = t23a, d17 = t24a
mbutterfly d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
mbutterfly d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
mbutterfly d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
mbutterfly d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
mbutterfly d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
mbutterfly d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
mbutterfly d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
mbutterfly d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
sub r12, r12, #32
vld1.16 {q0}, [r12,:128]
butterfly d4, d24, d16, d24 @ d4 = t16, d24 = t17
butterfly d5, d20, d28, d20 @ d5 = t19, d20 = t18
butterfly d6, d26, d18, d26 @ d6 = t20, d26 = t21
butterfly d7, d22, d30, d22 @ d7 = t23, d22 = t22
butterfly d8, d24, d16, d24 @ d8 = t16, d24 = t17
butterfly d9, d20, d28, d20 @ d9 = t19, d20 = t18
butterfly d10, d26, d18, d26 @ d10 = t20, d26 = t21
butterfly d11, d22, d30, d22 @ d11 = t23, d22 = t22
butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25
butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26
butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30
@ -1250,26 +1243,19 @@ function idct32_odd
endfunc
function idct32_odd_half
movrel r12, idct_coeffs
add r12, r12, #32
vld1.16 {q0-q1}, [r12,:128]
mbutterfly_h1 d16, d31, d4[0], d4[1], q4, q5 @ d16 = t16a, d31 = t31a
mbutterfly_h2 d24, d23, d4[2], d4[3], q4, q5 @ d24 = t17a, d23 = t30a
mbutterfly_h1 d20, d27, d5[0], d5[1], q4, q5 @ d20 = t18a, d27 = t29a
mbutterfly_h2 d28, d19, d5[2], d5[3], q4, q5 @ d28 = t19a, d19 = t28a
mbutterfly_h1 d18, d29, d6[0], d6[1], q4, q5 @ d18 = t20a, d29 = t27a
mbutterfly_h2 d26, d21, d6[2], d6[3], q4, q5 @ d26 = t21a, d21 = t26a
mbutterfly_h1 d22, d25, d7[0], d7[1], q4, q5 @ d22 = t22a, d25 = t25a
mbutterfly_h2 d30, d17, d7[2], d7[3], q4, q5 @ d30 = t23a, d17 = t24a
mbutterfly_h1 d16, d31, d0[0], d0[1], q2, q3 @ d16 = t16a, d31 = t31a
mbutterfly_h2 d24, d23, d0[2], d0[3], q2, q3 @ d24 = t17a, d23 = t30a
mbutterfly_h1 d20, d27, d1[0], d1[1], q2, q3 @ d20 = t18a, d27 = t29a
mbutterfly_h2 d28, d19, d1[2], d1[3], q2, q3 @ d28 = t19a, d19 = t28a
mbutterfly_h1 d18, d29, d2[0], d2[1], q2, q3 @ d18 = t20a, d29 = t27a
mbutterfly_h2 d26, d21, d2[2], d2[3], q2, q3 @ d26 = t21a, d21 = t26a
mbutterfly_h1 d22, d25, d3[0], d3[1], q2, q3 @ d22 = t22a, d25 = t25a
mbutterfly_h2 d30, d17, d3[2], d3[3], q2, q3 @ d30 = t23a, d17 = t24a
sub r12, r12, #32
vld1.16 {q0}, [r12,:128]
butterfly d4, d24, d16, d24 @ d4 = t16, d24 = t17
butterfly d5, d20, d28, d20 @ d5 = t19, d20 = t18
butterfly d6, d26, d18, d26 @ d6 = t20, d26 = t21
butterfly d7, d22, d30, d22 @ d7 = t23, d22 = t22
butterfly d8, d24, d16, d24 @ d8 = t16, d24 = t17
butterfly d9, d20, d28, d20 @ d9 = t19, d20 = t18
butterfly d10, d26, d18, d26 @ d10 = t20, d26 = t21
butterfly d11, d22, d30, d22 @ d11 = t23, d22 = t22
butterfly d28, d25, d17, d25 @ d28 = t24, d25 = t25
butterfly d30, d21, d29, d21 @ d30 = t27, d21 = t26
butterfly d29, d23, d31, d23 @ d29 = t31, d23 = t30
@ -1284,45 +1270,38 @@ function idct32_odd_half
endfunc
function idct32_odd_quarter
movrel r12, idct_coeffs
add r12, r12, #32
vld1.16 {q0-q1}, [r12,:128]
vmull.s16 q2, d16, d0[0]
vmull.s16 q14, d19, d1[3]
vmull.s16 q15, d16, d0[1]
vmull.s16 q11, d17, d3[2]
vmull.s16 q3, d17, d3[3]
vmull.s16 q13, d19, d1[2]
vmull.s16 q10, d18, d2[0]
vmull.s16 q12, d18, d2[1]
sub r12, r12, #32
vld1.16 {q0}, [r12,:128]
vmull.s16 q4, d16, d4[0]
vmull.s16 q14, d19, d5[3]
vmull.s16 q15, d16, d4[1]
vmull.s16 q11, d17, d7[2]
vmull.s16 q5, d17, d7[3]
vmull.s16 q13, d19, d5[2]
vmull.s16 q10, d18, d6[0]
vmull.s16 q12, d18, d6[1]
vneg.s32 q14, q14
vneg.s32 q3, q3
vneg.s32 q5, q5
vrshrn.s32 d4, q2, #14
vrshrn.s32 d5, q14, #14
vrshrn.s32 d8, q4, #14
vrshrn.s32 d9, q14, #14
vrshrn.s32 d29, q15, #14
vrshrn.s32 d28, q11, #14
vrshrn.s32 d7, q3, #14
vrshrn.s32 d11, q5, #14
vrshrn.s32 d31, q13, #14
vrshrn.s32 d6, q10, #14
vrshrn.s32 d10, q10, #14
vrshrn.s32 d30, q12, #14
mbutterfly_l q8, q9, d29, d4, d0[3], d1[0]
mbutterfly_l q13, q10, d31, d5, d0[3], d1[0]
mbutterfly_l q8, q9, d29, d8, d0[3], d1[0]
mbutterfly_l q13, q10, d31, d9, d0[3], d1[0]
vrshrn.s32 d23, q8, #14
vrshrn.s32 d24, q9, #14
vneg.s32 q10, q10
vrshrn.s32 d27, q13, #14
vrshrn.s32 d20, q10, #14
mbutterfly_l q8, q9, d30, d6, d1[1], d1[2]
mbutterfly_l q8, q9, d30, d10, d1[1], d1[2]
vrshrn.s32 d21, q8, #14
vrshrn.s32 d26, q9, #14
mbutterfly_l q8, q9, d28, d7, d1[1], d1[2]
mbutterfly_l q8, q9, d28, d11, d1[1], d1[2]
vrshrn.s32 d25, q8, #14
vneg.s32 q9, q9
vrshrn.s32 d22, q9, #14
@ -1343,8 +1322,11 @@ endfunc
function idct32_1d_4x32_pass1\suffix\()_neon
push {lr}
movrel r12, idct_coeffs
vld1.16 {q0-q1}, [r12,:128]
@ idct16 clobbers q2-q3 (since it doesn't clobber q4-q7 at all
@ when doing the normal 16x16 idct), so move the idct32_odd coeffs
@ to q4-q5
vmov q4, q2
vmov q5, q3
@ Double stride of the input, since we only read every other line
mov r12, #128
@ -1372,6 +1354,11 @@ function idct32_1d_4x32_pass1\suffix\()_neon
bl idct16\suffix
@ Move the idct32_odd coeffs back into q2-q3 for idct32_odd;
@ the constants for a vmul with a lane must be in q0-q3.
vmov q2, q4
vmov q3, q5
@ Do four 4x4 transposes. Originally, d16-d31 contain the
@ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
@ contain the transposed 4x4 blocks.
@ -1407,24 +1394,24 @@ function idct32_1d_4x32_pass1\suffix\()_neon
.endif
add r2, r2, #64
vmov.s16 d4, #0
vmov.s16 d8, #0
@ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
.ifb \suffix
.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
vld1.16 {d\i}, [r2,:64]
vst1.16 {d4}, [r2,:64], r12
vst1.16 {d8}, [r2,:64], r12
.endr
.endif
.ifc \suffix,_quarter
.irp i, 16, 17, 18, 19
vld1.16 {d\i}, [r2,:64]
vst1.16 {d4}, [r2,:64], r12
vst1.16 {d8}, [r2,:64], r12
.endr
.endif
.ifc \suffix,_half
.irp i, 16, 17, 18, 19, 20, 21, 22, 23
vld1.16 {d\i}, [r2,:64]
vst1.16 {d4}, [r2,:64], r12
vst1.16 {d8}, [r2,:64], r12
.endr
.endif
@ -1437,15 +1424,15 @@ function idct32_1d_4x32_pass1\suffix\()_neon
@ from the output.
.macro store_rev a, b, c, d
.irp i, \a, \b, \c, \d
vld1.16 {d4}, [r0,:64]
vadd.s16 d4, d4, d\i
vst1.16 {d4}, [r0,:64]!
vld1.16 {d8}, [r0,:64]
vadd.s16 d8, d8, d\i
vst1.16 {d8}, [r0,:64]!
vrev64.16 d\i, d\i
.endr
.irp i, \d, \c, \b, \a
vld1.16 {d4}, [r0,:64]
vsub.s16 d4, d4, d\i
vst1.16 {d4}, [r0,:64]!
vld1.16 {d8}, [r0,:64]
vsub.s16 d8, d8, d\i
vst1.16 {d8}, [r0,:64]!
.endr
.endm
@ -1466,8 +1453,8 @@ endfunc
@ r2 = src (temp buffer)
function idct32_1d_4x32_pass2\suffix\()_neon
push {lr}
movrel r12, idct_coeffs
vld1.16 {q0-q1}, [r12,:128]
vmov q4, q2
vmov q5, q3
mov r12, #128
@ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
@ -1492,6 +1479,9 @@ function idct32_1d_4x32_pass2\suffix\()_neon
bl idct16\suffix
vmov q2, q4
vmov q3, q5
.irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
vst1.16 {d\i}, [r2,:64], r12
.endr
@ -1524,38 +1514,38 @@ function idct32_1d_4x32_pass2\suffix\()_neon
mov r12, #128
.macro load_acc_store a, b, c, d, neg=0
vld1.16 {d4}, [r2,:64], r12
vld1.16 {d5}, [r2,:64], r12
vld1.16 {d8}, [r2,:64], r12
vld1.16 {d9}, [r2,:64], r12
.if \neg == 0
vadd.s16 d4, d4, d\a
vld1.16 {d6}, [r2,:64], r12
vadd.s16 d5, d5, d\b
vld1.16 {d7}, [r2,:64], r12
vadd.s16 d6, d6, d\c
vadd.s16 d7, d7, d\d
vadd.s16 d8, d8, d\a
vld1.16 {d10}, [r2,:64], r12
vadd.s16 d9, d9, d\b
vld1.16 {d11}, [r2,:64], r12
vadd.s16 d10, d10, d\c
vadd.s16 d11, d11, d\d
.else
vsub.s16 d4, d4, d\a
vld1.16 {d6}, [r2,:64], r12
vsub.s16 d5, d5, d\b
vld1.16 {d7}, [r2,:64], r12
vsub.s16 d6, d6, d\c
vsub.s16 d7, d7, d\d
vsub.s16 d8, d8, d\a
vld1.16 {d10}, [r2,:64], r12
vsub.s16 d9, d9, d\b
vld1.16 {d11}, [r2,:64], r12
vsub.s16 d10, d10, d\c
vsub.s16 d11, d11, d\d
.endif
vld1.32 {d2[]}, [r0,:32], r1
vld1.32 {d2[1]}, [r0,:32], r1
vrshr.s16 q2, q2, #6
vld1.32 {d3[]}, [r0,:32], r1
vrshr.s16 q3, q3, #6
vld1.32 {d3[1]}, [r0,:32], r1
vld1.32 {d12[]}, [r0,:32], r1
vld1.32 {d12[1]}, [r0,:32], r1
vrshr.s16 q4, q4, #6
vld1.32 {d13[]}, [r0,:32], r1
vrshr.s16 q5, q5, #6
vld1.32 {d13[1]}, [r0,:32], r1
sub r0, r0, r1, lsl #2
vaddw.u8 q2, q2, d2
vaddw.u8 q3, q3, d3
vqmovun.s16 d4, q2
vqmovun.s16 d5, q3
vst1.32 {d4[0]}, [r0,:32], r1
vst1.32 {d4[1]}, [r0,:32], r1
vst1.32 {d5[0]}, [r0,:32], r1
vst1.32 {d5[1]}, [r0,:32], r1
vaddw.u8 q4, q4, d12
vaddw.u8 q5, q5, d13
vqmovun.s16 d8, q4
vqmovun.s16 d9, q5
vst1.32 {d8[0]}, [r0,:32], r1
vst1.32 {d8[1]}, [r0,:32], r1
vst1.32 {d9[0]}, [r0,:32], r1
vst1.32 {d9[1]}, [r0,:32], r1
.endm
load_acc_store 31, 30, 29, 28
load_acc_store 27, 26, 25, 24
@ -1584,7 +1574,7 @@ function ff_vp9_idct_idct_32x32_add_neon, export=1
cmp r3, #1
beq idct32x32_dc_add_neon
push {r4-r8,lr}
vpush {q4-q7}
vpush {q4-q6}
movrel r8, min_eob_idct_idct_32 + 2
@ Align the stack, allocate a temp buffer
@ -1598,6 +1588,10 @@ A and r7, sp, #15
mov r5, r1
mov r6, r2
movrel r12, idct_coeffs
vld1.16 {q0-q1}, [r12,:128]!
vld1.16 {q2-q3}, [r12,:128]
cmp r3, #34
ble idct32x32_quarter_add_neon
cmp r3, #135
@ -1636,7 +1630,7 @@ A and r7, sp, #15
.endr
add sp, sp, r7
vpop {q4-q7}
vpop {q4-q6}
pop {r4-r8,pc}
endfunc
@ -1668,7 +1662,7 @@ function idct32x32_quarter_add_neon
.endr
add sp, sp, r7
vpop {q4-q7}
vpop {q4-q6}
pop {r4-r8,pc}
endfunc
@ -1706,6 +1700,6 @@ function idct32x32_half_add_neon
.endr
add sp, sp, r7
vpop {q4-q7}
vpop {q4-q6}
pop {r4-r8,pc}
endfunc