Add NEON versions of the SATD functions.
authorTim Terriberry <tterribe@xiph.org>
Thu, 24 Feb 2011 14:49:11 +0000 (14:49 +0000)
committerTim Terriberry <tterribe@xiph.org>
Thu, 24 Feb 2011 14:49:11 +0000 (14:49 +0000)
This gives CIF encoding a 37.5% speed up on a Cortex A8.

svn path=/trunk/theora/; revision=17874

lib/Makefile.am
lib/arm/armenc.c
lib/arm/armenc.h
lib/arm/armencfrag.s [new file with mode: 0644]
lib/arm/armfrag.s

index 409f817..45a7cf9 100644 (file)
@@ -12,6 +12,7 @@ EXTRA_DIST = \
        arm/armidct.s \
        arm/armint.h \
        arm/armenc.h \
+       arm/armencfrag.s \
        arm/armenquant.s \
        c64x/c64xint.h \
        c64x/c64xdec.h \
@@ -64,6 +65,7 @@ encoder_shared_x86_sources = \
 encoder_shared_x86_64_sources =
 
 encoder_uniq_arm_sources = \
+       armencfrag-gnu.S \
        armenquant-gnu.S \
        arm/armenc.c
 
@@ -288,12 +290,14 @@ CLEANFILES = \
        armidct-gnu.S \
        armloop-gnu.S \
        armopts-gnu.S \
+       armencfrag-gnu.S
        armenquant-gnu.S
 
 # automake doesn't do dependency tracking for asm files, that I can tell
 armfrag-gnu.S: armopts-gnu.S
 armidct-gnu.S: armopts-gnu.S
 armloop-gnu.S: armopts-gnu.S
+armencfrag-gnu.S: armopts-gnu.S
 armenquant-gnu.S: armopts-gnu.S
 
 # convert ARM asm to GNU as format
index 3e66334..c0c2911 100644 (file)
@@ -40,6 +40,9 @@ void oc_enc_accel_init_arm(oc_enc_ctx *_enc){
 #   if defined(OC_ARM_ASM_NEON)
   if(cpu_flags&OC_CPU_ARM_NEON){
 #    if defined(OC_STATE_USE_VTABLE)
+    _enc->opt_vtable.frag_satd=oc_enc_frag_satd_neon;
+    _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_neon;
+    _enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_neon;
     _enc->opt_vtable.enquant_table_init=oc_enc_enquant_table_init_neon;
     _enc->opt_vtable.enquant_table_fixup=oc_enc_enquant_table_fixup_neon;
     _enc->opt_vtable.quantize=oc_enc_quantize_neon;
index 54bdaae..de3c6bd 100644 (file)
@@ -31,6 +31,13 @@ void oc_enc_accel_init_arm(oc_enc_ctx *_enc);
 #  if defined(OC_ARM_ASM_EDSP)
 #   if defined(OC_ARM_ASM_MEDIA)
 #    if defined(OC_ARM_ASM_NEON)
+unsigned oc_enc_frag_satd_neon(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref,int _ystride);
+unsigned oc_enc_frag_satd2_neon(int *_dc,const unsigned char *_src,
+ const unsigned char *_ref1,const unsigned char *_ref2,int _ystride);
+unsigned oc_enc_frag_intra_satd_neon(int *_dc,
+ const unsigned char *_src,int _ystride);
+
 void oc_enc_enquant_table_init_neon(void *_enquant,
  const ogg_uint16_t _dequant[64]);
 void oc_enc_enquant_table_fixup_neon(void *_enquant[3][3][2],int _nqis);
diff --git a/lib/arm/armencfrag.s b/lib/arm/armencfrag.s
new file mode 100644 (file)
index 0000000..7335dd7
--- /dev/null
@@ -0,0 +1,220 @@
+;********************************************************************
+;*                                                                  *
+;* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
+;* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+;* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+;* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
+;*                                                                  *
+;* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009                *
+;* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+;*                                                                  *
+;********************************************************************
+;
+; function:
+;   last mod: $Id: mmxstate.c 17247 2010-05-28 05:35:32Z tterribe $
+;
+;********************************************************************
+
+       AREA    |.text|, CODE, READONLY
+
+       GET     armopts.s
+
+ [ OC_ARM_ASM_NEON
+       EXPORT  oc_enc_frag_satd_neon
+       EXPORT  oc_enc_frag_satd2_neon
+       EXPORT  oc_enc_frag_intra_satd_neon
+
+oc_enc_frag_satd_neon PROC
+       ; r0 = int                 *_dc
+       ; r1 = const unsigned char *_src
+       ; r2 = const unsigned char *_ref
+       ; r3 = int                  _ystride
+       ; Load src and subtract ref, expanding to 16 bits.
+       VLD1.64         {D16},[r1@64],r3
+       VLD1.64         {D0}, [r2],r3
+       VSUBL.U8        Q8, D16,D0
+       VLD1.64         {D18},[r1@64],r3
+       VLD1.64         {D1}, [r2],r3
+       VSUBL.U8        Q9, D18,D1
+       VLD1.64         {D20},[r1@64],r3
+       VLD1.64         {D2}, [r2],r3
+       VSUBL.U8        Q10,D20,D2
+       VLD1.64         {D22},[r1@64],r3
+       VLD1.64         {D3}, [r2],r3
+       VSUBL.U8        Q11,D22,D3
+       VLD1.64         {D24},[r1@64],r3
+       VLD1.64         {D4}, [r2],r3
+       VSUBL.U8        Q12,D24,D4
+       VLD1.64         {D26},[r1@64],r3
+       VLD1.64         {D5}, [r2],r3
+       VSUBL.U8        Q13,D26,D5
+       VLD1.64         {D28},[r1@64],r3
+       VLD1.64         {D6}, [r2],r3
+       VSUBL.U8        Q14,D28,D6
+       VLD1.64         {D30},[r1@64]
+       VLD1.64         {D7}, [r2]
+       VSUBL.U8        Q15,D30,D7
+oc_int_frag_satd_neon
+       ; Hadamard Stage A
+       VADD.I16        Q0, Q8, Q12
+       VSUB.I16        Q12,Q8, Q12
+       VSUB.I16        Q1, Q9, Q13
+       VADD.I16        Q9, Q9, Q13
+       VSUB.I16        Q2, Q10,Q14
+       VADD.I16        Q10,Q10,Q14
+       VADD.I16        Q3, Q11,Q15
+       VSUB.I16        Q15,Q11,Q15
+       ; Hadamard Stage B
+       VADD.I16        Q8, Q0, Q10
+       VSUB.I16        Q0, Q0, Q10
+       VSUB.I16        Q11,Q9, Q3
+       VADD.I16        Q3, Q9, Q3
+       VSUB.I16        Q14,Q12,Q2
+       VADD.I16        Q2, Q12,Q2
+       VADD.I16        Q13,Q1, Q15
+       VSUB.I16        Q1, Q1, Q15
+       ; Hadamard Stage C & Start 8x8 Transpose
+       VSUB.I16        Q9, Q8, Q3
+       VADD.I16        Q8, Q8, Q3
+       VTRN.16         Q8, Q9
+       VADD.I16        Q10,Q0, Q11
+       VSUB.I16        Q11,Q0, Q11
+       VTRN.16         Q10,Q11
+       VADD.I16        Q12,Q2, Q13
+       VTRN.32         Q8, Q10
+       VSUB.I16        Q13,Q2, Q13
+       VTRN.32         Q9, Q11
+       VSUB.I16        Q15,Q14,Q1
+       VTRN.16         Q12,Q13
+       VADD.I16        Q14,Q14,Q1
+       VTRN.16         Q14,Q15
+       VTRN.32         Q12,Q14
+       VSWP            D17,D24
+       ; Hadamard Stage A & Finish 8x8 Transpose
+       VADD.I16        Q0, Q8, Q12
+       VTRN.32         Q13,Q15
+       VSUB.I16        Q12,Q8, Q12
+       VSWP            D19,D26
+       VSUB.I16        Q1, Q9, Q13
+       VSWP            D21,D28
+       VADD.I16        Q9, Q9, Q13
+       VSWP            D23,D30
+       VSUB.I16        Q2, Q10,Q14
+       VADD.I16        Q10,Q10,Q14
+       VADD.I16        Q3, Q11,Q15
+       VSUB.I16        Q15,Q11,Q15
+       ; Hadamard Stage B
+       VADD.I16        Q8, Q0, Q10
+       VSUB.I16        Q0, Q0, Q10
+       VSUB.I16        Q11,Q9, Q3
+       VADD.I16        Q3, Q9, Q3
+       VSUB.I16        Q14,Q12,Q2
+       VADD.I16        Q2, Q12,Q2
+       VADD.I16        Q13,Q1, Q15
+       VSUB.I16        Q1, Q1, Q15
+       ; Hadamard Stage C & abs & accum
+       VNEG.S16        Q9, Q3
+       ; Compute the (signed) DC component and save it off.
+       VADDL.S16       Q10,D16,D6
+       VABD.S16        Q12,Q8, Q9
+       VABD.S16        Q15,Q11,Q0
+       VST1.32         D20[0],[r0]
+       ; Remove the (abs) DC component from the total.
+       MOV     r3,#0
+       VMOV.I16        D24[0],r3
+       VABA.S16        Q12,Q13,Q2
+       VABA.S16        Q15,Q14,Q1
+       VNEG.S16        Q0, Q0
+       VNEG.S16        Q2, Q2
+       VNEG.S16        Q1, Q1
+       VABA.S16        Q12,Q8, Q3
+       VABA.S16        Q15,Q11,Q0
+       VABA.S16        Q12,Q13,Q2
+       VABA.S16        Q15,Q14,Q1
+       ; We're now using all 16 bits of each value.
+       VPADDL.U16      Q12,Q12
+       VPADAL.U16      Q12,Q15
+       VADD.U32        D24,D24,D25
+       VPADDL.U32      D24,D24
+       VMOV.U32        r0, D24[0]
+       MOV     PC, r14
+       ENDP
+
+oc_enc_frag_satd2_neon PROC
+       ; r0 = int                 *_dc
+       ; r1 = const unsigned char *_src
+       ; r2 = const unsigned char *_ref1
+       ; r3 = const unsigned char *_ref2
+       ; r12= int                  _ystride
+       LDR     r12,[r13]
+       ; Load src and subtract (ref1+ref2>>1), expanding to 16 bits.
+       VLD1.64         {D0}, [r2],r12
+       VLD1.64         {D1}, [r3],r12
+       VLD1.64         {D16},[r1@64],r12
+       VHADD.U8        D0, D0, D1
+       VLD1.64         {D2}, [r2],r12
+       VLD1.64         {D3}, [r3],r12
+       VSUBL.U8        Q8, D16,D0
+       VLD1.64         {D18},[r1@64],r12
+       VHADD.U8        D2, D2, D3
+       VLD1.64         {D4}, [r2],r12
+       VLD1.64         {D5}, [r3],r12
+       VSUBL.U8        Q9, D18,D2
+       VLD1.64         {D20},[r1@64],r12
+       VHADD.U8        D4, D4, D5
+       VLD1.64         {D6}, [r2],r12
+       VLD1.64         {D7}, [r3],r12
+       VSUBL.U8        Q10,D20,D4
+       VLD1.64         {D22},[r1@64],r12
+       VHADD.U8        D6, D6, D7
+       VLD1.64         {D0}, [r2],r12
+       VLD1.64         {D1}, [r3],r12
+       VSUBL.U8        Q11,D22,D6
+       VLD1.64         {D24},[r1@64],r12
+       VHADD.U8        D0, D0, D1
+       VLD1.64         {D2}, [r2],r12
+       VLD1.64         {D3}, [r3],r12
+       VSUBL.U8        Q12,D24,D0
+       VLD1.64         {D26},[r1@64],r12
+       VHADD.U8        D2, D2, D3
+       VLD1.64         {D4}, [r2],r12
+       VLD1.64         {D5}, [r3],r12
+       VSUBL.U8        Q13,D26,D2
+       VLD1.64         {D28},[r1@64],r12
+       VHADD.U8        D4, D4, D5
+       VLD1.64         {D6}, [r2]
+       VSUBL.U8        Q14,D28,D4
+       VLD1.64         {D7}, [r3]
+       VHADD.U8        D6, D6, D7
+       VLD1.64         {D30},[r1@64]
+       VSUBL.U8        Q15,D30,D6
+       B       oc_int_frag_satd_neon
+       ENDP
+
+oc_enc_frag_intra_satd_neon PROC
+       ; r0 = int                 *_dc
+       ; r1 = const unsigned char *_src
+       ; r2 = int                  _ystride
+       ; Load and subtract 128 from src, expanding to 16 bits.
+       VMOV.I8         D0,#128
+       VLD1.64         {D16},[r1@64],r2
+       VSUBL.U8        Q8, D16,D0
+       VLD1.64         {D18},[r1@64],r2
+       VSUBL.U8        Q9, D18,D0
+       VLD1.64         {D20},[r1@64],r2
+       VSUBL.U8        Q10,D20,D0
+       VLD1.64         {D22},[r1@64],r2
+       VSUBL.U8        Q11,D22,D0
+       VLD1.64         {D24},[r1@64],r2
+       VSUBL.U8        Q12,D24,D0
+       VLD1.64         {D26},[r1@64],r2
+       VSUBL.U8        Q13,D26,D0
+       VLD1.64         {D28},[r1@64],r2
+       VSUBL.U8        Q14,D28,D0
+       VLD1.64         {D30},[r1@64]
+       VSUBL.U8        Q15,D30,D0
+       B       oc_int_frag_satd_neon
+       ENDP
+ ]
+
+       END
index ea7d9af..38627ed 100644 (file)
@@ -510,8 +510,7 @@ oc_frag_recon_intra_neon PROC
        ; r0 =       unsigned char *_dst
        ; r1 =       int            _ystride
        ; r2 = const ogg_int16_t    _residue[64]
-       MOV     r3, #128
-       VDUP.S16        Q0, r3
+       VMOV.I16        Q0, #128
        VLDMIA  r2,  {D16-D31}  ; D16= 3333222211110000 etc     ; 9(8) cycles
        VQADD.S16       Q8, Q8, Q0
        VQADD.S16       Q9, Q9, Q0