changeset 4040:9eaea06c5ba6 libavcodec

optimize sign decoding code in decode_residual() x86 is 4% faster on P3 C sign stuff + x86 code for everything else is also faster then before (sorry forgot to test pure C) ... and if i replace the second occurance of the sign decoding in decode_residual by the asm too then everything gets slower iam starting to think that it might be best to write the whole function in asm, playing this avoid random deoptimizations game with gcc is not fun at all
author michael
date Thu, 19 Oct 2006 01:19:03 +0000
parents 866a83726985
children 0113ceb0f953
files cabac.h h264.c
diffstat 2 files changed, 83 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/cabac.h	Wed Oct 18 09:37:25 2006 +0000
+++ b/cabac.h	Thu Oct 19 01:19:03 2006 +0000
@@ -575,6 +575,36 @@
 }
 
 static int get_cabac_bypass(CABACContext *c){
+#if 0 //not faster
+    int bit;
+    asm volatile(
+        "movl "RANGE    "(%1), %%ebx            \n\t"
+        "movl "LOW      "(%1), %%eax            \n\t"
+        "shl $17, %%ebx                         \n\t"
+        "add %%eax, %%eax                       \n\t"
+        "sub %%ebx, %%eax                       \n\t"
+        "cdq                                    \n\t"
+        "and %%edx, %%ebx                       \n\t"
+        "add %%ebx, %%eax                       \n\t"
+        "test %%ax, %%ax                        \n\t"
+        " jnz 1f                                \n\t"
+        "movl "BYTE     "(%1), %%ebx            \n\t"
+        "subl $0xFFFF, %%eax                    \n\t"
+        "movzwl (%%ebx), %%ecx                  \n\t"
+        "bswap %%ecx                            \n\t"
+        "shrl $15, %%ecx                        \n\t"
+        "addl $2, %%ebx                         \n\t"
+        "addl %%ecx, %%eax                      \n\t"
+        "movl %%ebx, "BYTE     "(%1)            \n\t"
+        "1:                                     \n\t"
+        "movl %%eax, "LOW      "(%1)            \n\t"
+
+        :"=&d"(bit)
+        :"r"(c)
+        : "%eax", "%ebx", "%ecx", "memory"
+    );
+    return bit+1;
+#else
     int range;
     c->low += c->low;
 
@@ -588,7 +618,58 @@
         c->low -= range;
         return 1;
     }
+#endif
 }
+
+
+static always_inline int get_cabac_bypass_sign(CABACContext *c, int val){
+#ifdef ARCH_X86
+    int bit;
+    asm volatile(
+        "movl "RANGE    "(%1), %%ebx            \n\t"
+        "movl "LOW      "(%1), %%eax            \n\t"
+        "shl $17, %%ebx                         \n\t"
+        "add %%eax, %%eax                       \n\t"
+        "sub %%ebx, %%eax                       \n\t"
+        "cdq                                    \n\t"
+        "and %%edx, %%ebx                       \n\t"
+        "add %%ebx, %%eax                       \n\t"
+        "xor %%edx, %%ecx                       \n\t"
+        "sub %%edx, %%ecx                       \n\t"
+        "test %%ax, %%ax                        \n\t"
+        " jnz 1f                                \n\t"
+        "movl "BYTE     "(%1), %%ebx            \n\t"
+        "subl $0xFFFF, %%eax                    \n\t"
+        "movzwl (%%ebx), %%edx                  \n\t"
+        "bswap %%edx                            \n\t"
+        "shrl $15, %%edx                        \n\t"
+        "addl $2, %%ebx                         \n\t"
+        "addl %%edx, %%eax                      \n\t"
+        "movl %%ebx, "BYTE     "(%1)            \n\t"
+        "1:                                     \n\t"
+        "movl %%eax, "LOW      "(%1)            \n\t"
+
+        :"+c"(val)
+        :"r"(c)
+        : "%eax", "%ebx", "%edx", "memory"
+    );
+    return val;
+#else
+    int range, mask;
+    c->low += c->low;
+
+    if(!(c->low & CABAC_MASK))
+        refill(c);
+
+    range= c->range<<17;
+    c->low -= range;
+    mask= c->low >> 31;
+    range &= mask;
+    c->low += range;
+    return (val^mask)-mask;
+#endif
+}
+
 //FIXME the x86 code from this file should be moved into i386/h264 or cabac something.c/h (note ill kill you if you move my code away from under my fingers before iam finished with it!)
 //FIXME use some macros to avoid duplicatin get_cabac (cant be done yet as that would make optimization work hard)
 #ifdef ARCH_X86
--- a/h264.c	Wed Oct 18 09:37:25 2006 +0000
+++ b/h264.c	Thu Oct 19 01:19:03 2006 +0000
@@ -6168,11 +6168,9 @@
 
         if( get_cabac( CC, ctx ) == 0 ) {
             if( !qmul ) {
-                if( get_cabac_bypass( CC ) ) block[j] = -1;
-                else                                block[j] =  1;
+                block[j] = get_cabac_bypass_sign( CC, -1);
             }else{
-                if( get_cabac_bypass( CC ) ) block[j] = (-qmul[j] + 32) >> 6;
-                else                                block[j] = ( qmul[j] + 32) >> 6;
+                block[j] = (get_cabac_bypass_sign( CC, -qmul[j]) + 32) >> 6;;
             }
 
             abslevel1++;