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