This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to optimize/parallize this one?

Hi all,

I am quite new to use the C5509A with assembly code.
I have the following piece of C code which is one of the bottlenecks in my algorithm:

                // D[15:12] for IF0 (left) and IF1 (right)
                pBuf = *pRaw++;
                wLeft   = ( (pBuf & 0xF000) >> 12) << 12;
                wRight  = ( (pBuf & 0x0F00) >>  8) << 12;
                // D[11: 8] for IF0 (left) and IF1 (right)
                wLeft  |= ( (pBuf & 0x00F0) >>  4) <<  8;
                wRight |= ( (pBuf & 0x000F) >>  0) <<  8;
                // D[ 7: 4] for IF0 (left) and IF1 (right)
                pBuf = *pRaw++;
                wLeft  |= ( (pBuf & 0xF000) >> 12) <<  4;
                wRight |= ( (pBuf & 0x0F00) >>  8) <<  4;
                // D[ 7: 4] for IF0 (left) and IF1 (right)
                wLeft  |= ( (pBuf & 0x00F0) >>  4) <<  0;
                wRight |= ( (pBuf & 0x000F) >>  0) <<  0;
                // store
                *pLeft++ = wLeft,
                *pRight++ = wRight;

This piece is inside of a loop with 4096 iterations. pBuf, pRaw, wLeft, wRight, pLeft and pRight are all Uint16. I would have like to optimize this code using the power of C55x assembly. I have first analyzed the compiler's assembly output in release mode (but with Full-Debug Information turned on in order to easily locate the code). In my opinion, the compiler's optimizations look quite fine to me (see below if needed).
But how can I optimize this code, where to begin? I think just using simple assembly instructions there's not a lot to do. I bet if I could employ parallelism this might give it quite a boost. I have started to think how I could re-arrange the sequences, usage of registers and accumulators, but I got lost very quickly.

Could anyone please give me some Ideas how to handle this problem (how to get started, some specific tricks and workarounds, other hints)?

Thank you for all your help.

Best regards,

Andreas

 

; wLeft  |= ( (pBuf & 0x00F0) >>  4) <<  8;                      
   MOV *AR2,AC0                                
   MOV *AR2,AR1 || SFTL AC0,#4,AC0             
   AND #61440,AR1,AR1                          
   AND #3840,AC0,AR4                           
   OR AR4,AR1                                  
; wRight |= ( (pBuf & 0x000F) >>  0) <<  8;                      
   MOV *AR2+,AR4                               
   AND #61440,AC0,AC0                          
   AND #15,AR4,AC1                             
   OR AC1 << #8, AC0                           
; pBuf = *pRaw++;                                                
   MOV *AR2+,AC1                               
; wLeft  |= ( (pBuf & 0xF000) >> 12) <<  4;                      
   BFXTR #65280,AC1,AR4                        
   AND #65520,AR4,AR4                          
   OR AR4,AR1                                  
; wRight |= ( (pBuf & 0x0F00) >>  8) <<  4;                      
   BFXTR #65520,AC1,AR4                        
   AND #240,AR4,AR7                            
   OR AR7,AC0                                  
; wLeft  |= ( (pBuf & 0x00F0) >>  4) <<  0;                      
   AND #15,AR4,AR4                             
   OR AR4,AR1                                  
; wRight |= ( (pBuf & 0x000F) >>  0) <<  0;                      
   AND #15,AC1,AR4                             
   OR AR4,AC0                                  
; *pLeft++ = wLeft,                                              
   MOV AR1,*AR3+                               
   MOV AC0,*AR0+                               

 

  • Since the code is involved with only bit shift and bit-wise operators, we shouldn't expect a magic ASM speed-up here. My suggestion is to use DU and AU simultaneously as much as possible:

    _test_asm:
        ; AR0: pLeft
        ; AR1: pRight
        ; AR2: pBuf (32-bit aligned)
        ; T0:  length
        T1 = #-4 ||    AC3 = #0xF000
        T0 = T0 - #1 || AC0 = dbl(*AR2+)
        BRC0 = T0
        localrepeat {
            AR3 = AC0 & #0x000F || AC0 = AC0 << T1
            AR4 = AC0 & #0x00F0 || AC1 = AC0 & #0x000F
            AR3 = AR3 | AR4 || AC0 = AC0 << T1
            AR4 = AC0 & #0x0F00 || AC2 = AC0 & #0x00F0
           
            AC0 = AC0 << T1 || AC1 = AC1 | AC2
            AR3 = AR3 | AR4 || AC2 = AC0 & #0x0F00
            AR4 = AC0 & #0xF000 || AC1 = AC1 | AC2
            AR3 = AR3 | AR4 || AC0 = AC0 << T1
            *AR1+ = AR3 || AC0 = AC0 & AC3
            AC0 = dbl(*AR2+) || AC1 = AC1 | AC0
            *AR0+ = AC1
        }
        return

  • Hi Cong,

    Thanks you a lot for your suggestions. This helped me much better to understand how to go on... I did not test your code yet. But I think I will be able to manage on my own.

    Best regards,

    Andreas