On Wed, Oct 05, 2011 at 07:03:52AM +0200, Kostya Shishkov wrote:
> On Tue, Oct 04, 2011 at 10:32:16PM +0200, Janne Grunau wrote:
> > +void ff_rv30dsp_init_neon(RV34DSPContext *c, DSPContext* dsp)
> > +{
> > +    c->rv34_inv_transform_tab[0] = ff_rv34_inv_transform_neon;
> > +    c->rv34_inv_transform_tab[1] = ff_rv34_inv_transform_noround_neon;
> > +
> > +    return;
>
> this return is silly

removed

> > diff --git a/libavcodec/arm/rv34dsp_neon.S b/libavcodec/arm/rv34dsp_neon.S
> > new file mode 100644
> > index 0000000..9414db2
> > --- /dev/null
> > +++ b/libavcodec/arm/rv34dsp_neon.S
>
> Also wouldn't it be faster to use the oldest trick in the book for some
> multiplications (e.g. X*7 = (X << 3) - X, etc.)?

It is for some. Converting the multiplications by 7 and 17 to shift+add
made the functions more than 10% faster. The final multiplication in the
noround version got slower for reasons I don't understand.

Janne
---8<--
4.3 times faster, more than 5% overall speedup on bourne.rvmb

3336 dezicycles in rv34_inv_transform,         8387851 runs, 757 skips
 767 dezicycles in ff_rv34_inv_transform_neon, 8388447 runs, 161 skips

3871 dezicycles in rv34_inv_transform_noround,         261884 runs, 260 skips
 889 dezicycles in ff_rv34_inv_transform_noround_neon, 262135 runs,   9 skips
---
 libavcodec/arm/Makefile            |    4 +
 libavcodec/arm/rv34dsp_init_neon.c |   34 +++++++++++
 libavcodec/arm/rv34dsp_neon.S      |  116 ++++++++++++++++++++++++++++++++++++
 libavcodec/rv34dsp.c               |    3 +
 libavcodec/rv34dsp.h               |    2 +
 5 files changed, 159 insertions(+), 0 deletions(-)
 create mode 100644 libavcodec/arm/rv34dsp_init_neon.c
 create mode 100644 libavcodec/arm/rv34dsp_neon.S

diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile
index d6a6961..cc73fa4 100644
--- a/libavcodec/arm/Makefile
+++ b/libavcodec/arm/Makefile
@@ -62,7 +62,10 @@ NEON-OBJS-$(CONFIG_AC3DSP)             += arm/ac3dsp_neon.o
 NEON-OBJS-$(CONFIG_DCA_DECODER)        += arm/dcadsp_neon.o             \
                                           arm/synth_filter_neon.o       \
 
+NEON-OBJS-$(CONFIG_RV30_DECODER)       += arm/rv34dsp_neon.o            \
+
 NEON-OBJS-$(CONFIG_RV40_DECODER)       += arm/rv40dsp_neon.o            \
+                                          arm/rv34dsp_neon.o            \
 
 NEON-OBJS-$(CONFIG_VP3_DECODER)        += arm/vp3dsp_neon.o
 
@@ -79,6 +82,7 @@ OBJS-$(HAVE_NEON)                      += 
arm/dsputil_init_neon.o       \
                                           arm/fmtconvert_neon.o         \
                                           arm/int_neon.o                \
                                           arm/mpegvideo_neon.o          \
+                                          arm/rv34dsp_init_neon.o       \
                                           arm/rv40dsp_init_neon.o       \
                                           arm/simple_idct_neon.o        \
                                           $(NEON-OBJS-yes)
diff --git a/libavcodec/arm/rv34dsp_init_neon.c 
b/libavcodec/arm/rv34dsp_init_neon.c
new file mode 100644
index 0000000..fe6aefd
--- /dev/null
+++ b/libavcodec/arm/rv34dsp_init_neon.c
@@ -0,0 +1,34 @@
+/*
+ * ARM NEON optimised DSP functions
+ * Copyright (c) 2011 Janne Grunau <[email protected]>
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+
+#include "libavcodec/avcodec.h"
+#include "libavcodec/rv34dsp.h"
+
+void ff_rv34_inv_transform_neon(DCTELEM *block);
+void ff_rv34_inv_transform_noround_neon(DCTELEM *block);
+
+void ff_rv34dsp_init_neon(RV34DSPContext *c, DSPContext* dsp)
+{
+    c->rv34_inv_transform_tab[0] = ff_rv34_inv_transform_neon;
+    c->rv34_inv_transform_tab[1] = ff_rv34_inv_transform_noround_neon;
+}
diff --git a/libavcodec/arm/rv34dsp_neon.S b/libavcodec/arm/rv34dsp_neon.S
new file mode 100644
index 0000000..6f5c17d
--- /dev/null
+++ b/libavcodec/arm/rv34dsp_neon.S
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2011 Janne Grunau <[email protected]>
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/arm/asm.S"
+
+.macro rv34_row_transform
+        mov             r1,  #16
+        vld1.16         {d28}, [r0], r1 @ load block[i+8*0]
+        vmov.s32        d0,  #13
+        vld1.16         {d29}, [r0], r1 @ load block[i+8*1]
+        vld1.16         {d30}, [r0], r1 @ load block[i+8*2]
+        vshll.s16       q12, d29,  #3
+        vld1.16         {d31}, [r0], r1 @ load block[i+8*3]
+        vshll.s16       q13, d29, #4
+        vaddl.s16       q10, d28, d30   @ block[i+8*0] + block[i+8*2]
+        vsubl.s16       q11, d28, d30   @ block[i+8*0] - block[i+8*2]
+        vsubw.s16       q12, d29        @ z2 = block[i+8*1]*7
+        vaddw.s16       q13, d29        @ z3 = block[i+8*1]*17
+        vshll.s16       q1,  d31, #4
+        vshll.s16       q9,  d31, #3
+        vaddw.s16       q1,  q1,  d31
+        vmul.i32        q11, q11, d0[0] @ z1 = 13*(block[i+8*0] - block[i+8*2])
+        vsubw.s16       q9,  q9,  d31
+        vsub.s32        q12, q12, q1    @ z2 = block[i+8*1]*7 - block[i+8*3]*17
+        vmul.i32        q10, q10, d0[0] @ z0 = 13*(block[i+8*0] + block[i+8*2])
+        vadd.s32        q13, q13, q9    @ z3 = block[i+8*1]*17 + block[i+8*3]*7
+        vadd.s32        q2,  q11, q12   @ z1 + z2
+        vsub.s32        q3,  q11, q12   @ z1 - z2
+        vadd.s32        q1,  q10, q13   @ z0 + z3
+        vsub.s32        q8,  q10, q13   @ z0 - z3
+.endm
+
+.macro rv34_inv_transform_common
+        vtrn.32         q1,  q2
+        vtrn.32         q3,  q8
+        vswp            d3,  d6
+        vswp            d5,  d16
+        vshl.s32        q12, q2,  #3
+        vadd.s32        q10, q1,  q3
+        vsub.s32        q11, q1,  q3
+        vsub.s32        q12, q12, q2
+        vshl.s32        q9,  q2,  #4
+        vmul.s32        q13, q11, d0[0]
+        vshl.s32        q11, q8,  #4
+        vadd.s32        q9,  q9,  q2
+        vshl.s32        q15, q8,  #3
+        vadd.s32        q11, q11, q8
+        vmul.s32        q14, q10, d0[0]
+        vsub.s32        q12, q12, q11
+        vsub.s32        q8,  q15, q8
+        vadd.s32        q9,  q9,  q8
+        vadd.s32        q2,  q13, q12   @ z1 + z2
+        vadd.s32        q1,  q14, q9    @ z0 + z3
+        vsub.s32        q3,  q13, q12   @ z1 - z2
+        vsub.s32        q15, q14, q9    @ z0 - z3
+.endm
+
+        .text
+        .align
+
+/* void ff_rv34_inv_transform_neon(DCTELEM *block); */
+function ff_rv34_inv_transform_neon, export=1
+        pld             [r0]
+        mov             r2,  r0
+        rv34_row_transform
+        rv34_inv_transform_common
+        vrshrn.s32      d1,  q2,  #10   @ (z1 + z2) >> 10
+        vrshrn.s32      d0,  q1,  #10   @ (z0 + z3) >> 10
+        vrshrn.s32      d2,  q3,  #10   @ (z1 - z2) >> 10
+        vrshrn.s32      d3,  q15, #10   @ (z0 - z3) >> 10
+        vst4.16         {d0[0], d1[0], d2[0], d3[0]}, [r2], r1
+        vst4.16         {d0[1], d1[1], d2[1], d3[1]}, [r2], r1
+        vst4.16         {d0[2], d1[2], d2[2], d3[2]}, [r2], r1
+        vst4.16         {d0[3], d1[3], d2[3], d3[3]}, [r2], r1
+        bx              lr
+endfunc
+
+/* void rv34_inv_transform_noround_neon(DCTELEM *block); */
+function ff_rv34_inv_transform_noround_neon, export=1
+        pld             [r0]
+        mov             r2,  r0
+        rv34_row_transform
+        vmov.s32        d1,  #3
+        rv34_inv_transform_common
+@ the following multiplications aren't faster as shift+and
+        vmul.s32        q11, q2,  d1[0] @ (z1 + z2)*3
+        vmul.s32        q10, q1,  d1[0] @ (z0 + z3)*3
+        vmul.s32        q12, q3,  d1[0] @ (z1 - z2)*3
+        vmul.s32        q13, q15, d1[0] @ (z0 - z3)*3
+        vshrn.s32       d0,  q10, #11   @ (z0 + z3)*3 >> 11
+        vshrn.s32       d1,  q11, #11   @ (z1 + z2)*3 >> 11
+        vshrn.s32       d2,  q12, #11   @ (z1 - z2)*3 >> 11
+        vshrn.s32       d3,  q13, #11   @ (z0 - z3)*3 >> 11
+        vst4.16         {d0[0], d1[0], d2[0], d3[0]}, [r2], r1
+        vst4.16         {d0[1], d1[1], d2[1], d3[1]}, [r2], r1
+        vst4.16         {d0[2], d1[2], d2[2], d3[2]}, [r2], r1
+        vst4.16         {d0[3], d1[3], d2[3], d3[3]}, [r2], r1
+        bx              lr
+endfunc
\ No newline at end of file
diff --git a/libavcodec/rv34dsp.c b/libavcodec/rv34dsp.c
index c853acd..367c871 100644
--- a/libavcodec/rv34dsp.c
+++ b/libavcodec/rv34dsp.c
@@ -105,4 +105,7 @@ static void rv34_inv_transform_noround(DCTELEM *block){
 av_cold void ff_rv34dsp_init(RV34DSPContext *c, DSPContext* dsp) {
     c->rv34_inv_transform_tab[0] = rv34_inv_transform;
     c->rv34_inv_transform_tab[1] = rv34_inv_transform_noround;
+
+    if (HAVE_NEON)
+        ff_rv34dsp_init_neon(c, dsp);
 }
diff --git a/libavcodec/rv34dsp.h b/libavcodec/rv34dsp.h
index 5f1f359..42fd4cf 100644
--- a/libavcodec/rv34dsp.h
+++ b/libavcodec/rv34dsp.h
@@ -49,6 +49,8 @@ void ff_rv30dsp_init(RV34DSPContext *c, DSPContext* dsp);
 void ff_rv34dsp_init(RV34DSPContext *c, DSPContext* dsp);
 void ff_rv40dsp_init(RV34DSPContext *c, DSPContext* dsp);
 
+void ff_rv34dsp_init_neon(RV34DSPContext *c, DSPContext *dsp);
+
 void ff_rv40dsp_init_x86(RV34DSPContext *c, DSPContext *dsp);
 void ff_rv40dsp_init_neon(RV34DSPContext *c, DSPContext *dsp);
 
-- 
1.7.7

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to