5c830fccf4
Compared to the MMX version, this version benefits from wider registers and pmaddubsw. It also has fewer unnecessary loads and stores: On x64, the MMX version has 12 unnecessary GPR loads and 6 stores in each line when width is eight; for width 16, there are 17 unnecessary GPR loads and six stores per line. Even the 32bit SSSE3 version only has six loads and zero stores per line more than the x64 version. Furthermore, in contrast to the MMX version, the SSSE3 version also does not clobber the array of block pointers given to it. Benchmarks: inner_add_yblock_2_c: 29.2 ( 1.00x) inner_add_yblock_2_mmx: 32.5 ( 0.90x) inner_add_yblock_2_ssse3: 28.6 ( 1.02x) inner_add_yblock_4_c: 85.2 ( 1.00x) inner_add_yblock_4_mmx: 89.2 ( 0.96x) inner_add_yblock_4_ssse3: 84.5 ( 1.01x) inner_add_yblock_8_c: 302.0 ( 1.00x) inner_add_yblock_8_mmx: 77.0 ( 3.92x) inner_add_yblock_8_ssse3: 30.6 ( 9.85x) inner_add_yblock_16_c: 1164.7 ( 1.00x) inner_add_yblock_16_mmx: 260.4 ( 4.47x) inner_add_yblock_16_ssse3: 82.3 (14.15x) Both the MMX and SSSE3 versions leave the size 2 and 4 cases to ff_snow_inner_add_yblock_c() (but the MMX version has a prologue at the beginning that it needs to undo before the call, leading to the higher overhead for these sizes). I don't know why the SSSE3 version is marginally faster than the C version in these cases. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
192 lines
6.3 KiB
NASM
192 lines
6.3 KiB
NASM
;*
|
|
;* ASM optimized Snow DSP functions
|
|
;*
|
|
;* This file is part of FFmpeg.
|
|
;*
|
|
;* FFmpeg is free software; you can redistribute it and/or
|
|
;* modify it under the terms of the GNU Lesser General Public
|
|
;* License as published by the Free Software Foundation; either
|
|
;* version 2.1 of the License, or (at your option) any later version.
|
|
;*
|
|
;* FFmpeg is distributed in the hope that it will be useful,
|
|
;* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
;* Lesser General Public License for more details.
|
|
;*
|
|
;* You should have received a copy of the GNU Lesser General Public
|
|
;* License along with FFmpeg; if not, write to the Free Software
|
|
;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
;******************************************************************************
|
|
|
|
%include "libavutil/x86/x86util.asm"
|
|
|
|
cextern snow_inner_add_yblock_c
|
|
|
|
SECTION .text
|
|
|
|
%assign FRAC_BITS 4
|
|
%assign LOG2_OBMC_MAX 6
|
|
|
|
%macro ADD_YBLOCK_PROLOGUE 1
|
|
%assign stack_offset 0
|
|
%if ARCH_X86_32
|
|
PROLOGUE 1, 7, 7+(%1>>4), obmc, offset, dst8, lines, b_h, src_x, dst
|
|
; copy all four block pointers to the stack to be able to load
|
|
; them via esp
|
|
mov r2, r2m
|
|
mov b_hd, b_hm
|
|
mov src_xd, src_xm
|
|
movups m1, [r2]
|
|
mov linesq, r7m
|
|
shl src_xd, 1 ; convert src_x from IDWTELEM to bytes
|
|
mov dst8q, r9m
|
|
mov src_xm, src_xd
|
|
; Just reuse the space for the arguments to store the block pointers.
|
|
%if HAVE_ALIGNED_STACK
|
|
movaps r0m, m1
|
|
%else
|
|
movups r0m, m1
|
|
%endif
|
|
%define src_strideq r6m
|
|
%else ; X64
|
|
PROLOGUE 1, 12, 7+(%1>>4), obmc, offset, dst8, lines, b_h, src_x, src_stride, dst, block0, block1, block2, block3
|
|
mov block0q, [r2q]
|
|
mov block1q, [r2q + gprsize]
|
|
mov block2q, [r2q + 2*gprsize]
|
|
mov block3q, [r2q + 3*gprsize]
|
|
movifnidn b_hd, b_hm
|
|
movifnidn src_xd, src_xm
|
|
shl src_xd, 1 ; convert src_x from IDWTELEM to bytes and zero-extend it
|
|
movsxd src_strideq, src_stridem
|
|
mov linesq, r7mp
|
|
mov dst8q, r9mp
|
|
%endif
|
|
xor offsetd, offsetd
|
|
psllw m0, FRAC_BITS - 1 ; pw_m8
|
|
%endmacro
|
|
|
|
%macro LOAD_BLOCKPOINTER_FOR_X86_32 2
|
|
%if ARCH_X86_32
|
|
; we put block #i into the spot of register r#i
|
|
mov r5, r %+ %1 %+ m
|
|
mov r6, r %+ %2 %+ m
|
|
%xdefine block%1q r5
|
|
%xdefine block%2q r6
|
|
%endif
|
|
%endmacro
|
|
|
|
INIT_XMM ssse3
|
|
; void ff_snow_inner_add_yblock_ssse3(const uint8_t *obmc, const int obmc_stride,
|
|
; uint8_t **block, int b_w, int b_h, int src_x,
|
|
; int src_stride, IDWTELEM *const *lines,
|
|
; int add, uint8_t *dst8);
|
|
; Don't use cglobal to load args, as we may want to perform
|
|
; a tail call to ff_snow_inner_add_yblock.
|
|
cglobal snow_inner_add_yblock
|
|
pcmpeqw m0, m0
|
|
%if ARCH_X86_32
|
|
mov r0d, r3m ; block width
|
|
cmp r0d, 16
|
|
je .w16
|
|
cmp r0d, 8
|
|
jne snow_inner_add_yblock_c
|
|
cmp r1mp, 16
|
|
jne snow_inner_add_yblock_c
|
|
%else
|
|
; all arguments used to check for support are already in registers
|
|
cmp r3d, 16
|
|
je .w16
|
|
cmp r3d, 8
|
|
jne snow_inner_add_yblock_c
|
|
cmp r1d, 16
|
|
jne snow_inner_add_yblock_c
|
|
%endif
|
|
ADD_YBLOCK_PROLOGUE 8
|
|
.loop8:
|
|
LOAD_BLOCKPOINTER_FOR_X86_32 1, 3
|
|
movq m3, [block3q+offsetq]
|
|
movq m4, [block1q+offsetq]
|
|
mova m1, [obmcq]
|
|
mova m2, [obmcq+16*8]
|
|
%if ARCH_X86_64
|
|
mov dstq, [linesq]
|
|
%endif
|
|
LOAD_BLOCKPOINTER_FOR_X86_32 0, 2
|
|
movq m5, [block2q+offsetq]
|
|
movq m6, [block0q+offsetq]
|
|
punpcklbw m3, m4
|
|
%if ARCH_X86_32
|
|
mov dstq, [linesq]
|
|
add dstq, src_xm
|
|
%endif
|
|
SBUTTERFLY bw, 1, 2, 4
|
|
%if ARCH_X86_64
|
|
movu m4, [dstq+src_xq]
|
|
%else
|
|
movu m4, [dstq]
|
|
%endif
|
|
pmaddubsw m3, m1
|
|
add obmcq, 16
|
|
punpcklbw m5, m6
|
|
pmaddubsw m5, m2
|
|
add linesq, gprsize
|
|
paddw m3, m5
|
|
psubw m4, m0 ; + 1<<(FRAC_BITS-1)
|
|
psrlw m3, LOG2_OBMC_MAX - FRAC_BITS
|
|
paddw m3, m4
|
|
psraw m3, FRAC_BITS
|
|
packuswb m3, m3
|
|
movq [dst8q+offsetq], m3
|
|
add offsetq, src_strideq
|
|
dec b_hd
|
|
jnz .loop8
|
|
RET
|
|
.w16:
|
|
ADD_YBLOCK_PROLOGUE 16
|
|
.loop16:
|
|
LOAD_BLOCKPOINTER_FOR_X86_32 2, 3
|
|
mova m3, [block3q+offsetq]
|
|
mova m4, [block2q+offsetq]
|
|
mova m1, [obmcq]
|
|
mova m2, [obmcq+16]
|
|
LOAD_BLOCKPOINTER_FOR_X86_32 0, 1
|
|
SBUTTERFLY bw, 3, 4, 7
|
|
mova m5, [block1q+offsetq]
|
|
mova m6, [block0q+offsetq]
|
|
SBUTTERFLY bw, 1, 2, 7
|
|
mov dstq, [linesq]
|
|
pmaddubsw m3, m1
|
|
mova m1, [obmcq+32*16]
|
|
pmaddubsw m4, m2
|
|
mova m2, [obmcq+32*16+16]
|
|
%if ARCH_X86_32
|
|
add dstq, src_xm
|
|
%endif
|
|
SBUTTERFLY bw, 5, 6, 7
|
|
SBUTTERFLY bw, 1, 2, 7
|
|
pmaddubsw m5, m1
|
|
add linesq, gprsize
|
|
pmaddubsw m6, m2
|
|
paddw m3, m5
|
|
paddw m4, m6
|
|
psrlw m3, LOG2_OBMC_MAX - FRAC_BITS
|
|
psrlw m4, LOG2_OBMC_MAX - FRAC_BITS
|
|
add obmcq, 32
|
|
%if ARCH_X86_32
|
|
paddw m3, [dstq]
|
|
paddw m4, [dstq+16]
|
|
%else
|
|
paddw m3, [dstq+src_xq]
|
|
paddw m4, [dstq+src_xq+16]
|
|
%endif
|
|
psubw m3, m0 ; + 1<<(FRAC_BITS-1)
|
|
psubw m4, m0 ; + 1<<(FRAC_BITS-1)
|
|
psraw m3, FRAC_BITS
|
|
psraw m4, FRAC_BITS
|
|
packuswb m3, m4
|
|
movu [dst8q+offsetq], m3
|
|
add offsetq, src_strideq
|
|
dec b_hd
|
|
jnz .loop16
|
|
RET
|