• AVR Freaks

Helpful ReplyHot!PIC18F26K22 XC8 1.33 C code optimisation

Page: 12345 > Showing page 1 of 5
Author
Kabak
Super Member
  • Total Posts : 250
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
2021/01/27 00:22:44 (permalink)
0

PIC18F26K22 XC8 1.33 C code optimisation

I want to optimize this function

typedef union _Any_Byte_Bit {
volatile    uchar Byte;
    struct
    {
        uint8_t bit0    :1;
        uint8_t bit1    :1;
        uint8_t bit2    :1;
        uint8_t bit3    :1;
        uint8_t bit4    :1;
        uint8_t bit5    :1;
        uint8_t bit6    :1;
        uint8_t bit7    :1;
    };
} ByteBits;
 
 
inline uchar LCD_ST77xx_Rotate_Byte ( uchar In_Byte )
{
    ByteBits Out;
    uchar Temp = 0b10000000;
    Out.Byte = 0x0;
            
    for( uchar i = 0; i < 8; ++i )
    {
        ( Temp & In_Byte ) > 0 ? Out.bit7 = 1 : Out.Byte;

        i < 7 ? Out.Byte >>= 1 : Out.Byte;
        
        Temp = Temp >> 1;
    }
    return Out.Byte;
}

 
I trying it in ASM. Code is smaller a bit then in C, works, but only in FREE MODE  ( not even STANDARD )
 
inline uchar LCD_ST77xx_Rotate_Byte ( uchar In_Byte )
{
 
   volatile uchar Temp = 0b10000000;    
   volatile uchar i = 7;
   volatile uchar _In_Byte = In_Byte;
   volatile uchar Out = 0;
   
#asm
start_Rotate_Byte:
   MOVF     LCD_ST77xx_Rotate_Byte@_In_Byte,w
   ANDWF    LCD_ST77xx_Rotate_Byte@Temp,w
   BZ       Zero
   BSF      LCD_ST77xx_Rotate_Byte@Out,7
Zero:
   MOVF     LCD_ST77xx_Rotate_Byte@i,w
   BNZ      Continue
   GOTO     Exit
Continue:
   RRNCF    LCD_ST77xx_Rotate_Byte@Out,f
   DECF     LCD_ST77xx_Rotate_Byte@i,f
   RRNCF    LCD_ST77xx_Rotate_Byte@Temp,f
   GOTO     start_Rotate_Byte
Exit:
#endasm   

    return ( Out );
 
}

 
Why it doesn't work in STANDARD mode ?  And could this function be optimized more?
post edited by Kabak - 2021/01/27 00:44:02
#1
ric
Super Member
  • Total Posts : 29861
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 03:54:47 (permalink)
+3 (3)
Sometimes brute force is the best solution. Try this:
uchar LCD_ST77xx_Rotate_Byte ( uchar In_Byte )
{
   volatile uchar _In_Byte = In_Byte;
   volatile uchar Out = 0;
   
#asm
   RRCF     LCD_ST77xx_Rotate_Byte@_In_Byte,f    ;1
   RLCF     LCD_ST77xx_Rotate_Byte@Out,f

   RRCF     LCD_ST77xx_Rotate_Byte@_In_Byte,f    ;2
   RLCF     LCD_ST77xx_Rotate_Byte@Out,f

   RRCF     LCD_ST77xx_Rotate_Byte@_In_Byte,f    ;3
   RLCF     LCD_ST77xx_Rotate_Byte@Out,f

   RRCF     LCD_ST77xx_Rotate_Byte@_In_Byte,f    ;4
   RLCF     LCD_ST77xx_Rotate_Byte@Out,f

   RRCF     LCD_ST77xx_Rotate_Byte@_In_Byte,f    ;5
   RLCF     LCD_ST77xx_Rotate_Byte@Out,f

   RRCF     LCD_ST77xx_Rotate_Byte@_In_Byte,f    ;6
   RLCF     LCD_ST77xx_Rotate_Byte@Out,f

   RRCF     LCD_ST77xx_Rotate_Byte@_In_Byte,f    ;7
   RLCF     LCD_ST77xx_Rotate_Byte@Out,f

   RRCF     LCD_ST77xx_Rotate_Byte@_In_Byte,f    ;8
   RLCF     LCD_ST77xx_Rotate_Byte@Out,f
#endasm   

    return ( Out );
}

 (totally untested, but I think you'll get the idea.)
post edited by ric - 2021/01/27 03:59:27

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#2
Kabak
Super Member
  • Total Posts : 250
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:01:31 (permalink)
0
Yes, I understand an idea, and seems your code fastest possible variant in my case. - I really need speed in this part of my application.

And yes, it works.
 
Thank you, Ric  
#3
ric
Super Member
  • Total Posts : 29861
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:06:38 (permalink)
0
n.b. "mirror" is a better description of what you are doing, rather than "rotate".

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#4
blue_led
New Users
  • Total Posts : 87
  • Reward points : 0
  • Status: online
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:09:43 (permalink)
0
calling that function and without lcd (?) update, exit value will be the same as input after 8 rotations ?
#5
Kabak
Super Member
  • Total Posts : 250
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:18:18 (permalink)
0
blue_led
calling that function and without lcd (?) update, exit value will be the same as input after 8 rotations ?


after 16 rotations
#6
ric
Super Member
  • Total Posts : 29861
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:19:43 (permalink)
+2 (2)
n.b. why are you exclusively using the "?" operator for doing tests in C?
That is the least efficient possible way to do tests!
e.g.
        ( Temp & In_Byte ) > 0 ? Out.bit7 = 1 : Out.Byte;

Seems to be a really awkward way to do:
if (( Temp & In_Byte ) > 0)
    Out.bit7 = 1;

and
i < 7 ? Out.Byte >>= 1 : Out.Byte;

is clearer as:
if (i < 7)
    Out.Byte >>= 1;

 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#7
Kabak
Super Member
  • Total Posts : 250
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:24:20 (permalink)
0
ric
n.b. why are you exclusively using the "?" operator for doing tests in C?
That is the least efficient possible way to do tests!
e.g.
        ( Temp & In_Byte ) > 0 ? Out.bit7 = 1 : Out.Byte;

Seems to be a really awkward way to do:
if (( Temp & In_Byte ) > 0)
 
 
 
 
 
 
 
    Out.bit7 = 1;

and
i < 7 ? Out.Byte >>= 1 : Out.Byte;

is clearer as:
if (i < 7)
 
 
 
 
 
 
 
    Out.Byte >>= 1;

 


Why are you shure about that ?
I didn't check it out.  It seems to me , XC8 compiler generate the same code for If or ? operators
 
If nothing done after or before ' : ' no code was generated in this case. I am sure
post edited by Kabak - 2021/01/27 05:32:13
#8
ric
Super Member
  • Total Posts : 29861
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:31:20 (permalink)
+1 (1)
Kabak
If nothing done after or before ' : '    no code was generated in this case. I am shure

Are you looking in the LST files to see what it did?
It makes your C code very hard to read with all that convoluted, do nothing fluff.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#9
Kabak
Super Member
  • Total Posts : 250
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:34:55 (permalink)
0
My C function variant
 
17493 003F1E 6E06 movwf LCD_ST77xx_Rotate_Byte@In_Byte,c
 17494
 17495 ;lcd_ST77xx.c: 426: ByteBits Out;
 17496 ;lcd_ST77xx.c: 427: uchar Temp = 0b10000000;
 17497 003F20 0E80 movlw 128
 17498 003F22 6E07 movwf LCD_ST77xx_Rotate_Byte@Temp,c
 17499
 17500 ;lcd_ST77xx.c: 429: Out.Byte = 0x0;
 17501 003F24 6A09 clrf LCD_ST77xx_Rotate_Byte@Out,c ;volatile
 17502
 17503 ;lcd_ST77xx.c: 431: for( uchar i = 0; i < 8; ++i )
 17504 003F26 6A08 clrf LCD_ST77xx_Rotate_Byte@i,c
 17505 003F28 l5015:
 17506
 17507 ;lcd_ST77xx.c: 432: {
 17508 ;lcd_ST77xx.c: 433: ( Temp & In_Byte ) > 0 ? Out.bit7 = 1 : Out.Byte;
 17509 003F28 5007 movf LCD_ST77xx_Rotate_Byte@Temp,w,c
 17510 003F2A 1406 andwf LCD_ST77xx_Rotate_Byte@In_Byte,w,c
 17511 003F2C A4D8 btfss status,2,c
 17512 003F2E 8E09 bsf LCD_ST77xx_Rotate_Byte@Out,7,c ;volatile
 17513
 17514 ;lcd_ST77xx.c: 435: i < 7 ? Out.Byte >>= 1 : Out.Byte;
 17515 003F30 0E07 movlw 7
 17516 003F32 5C08 subwf LCD_ST77xx_Rotate_Byte@i,w,c
 17517 003F34 E202 bc l5023
 17518 003F36 90D8 bcf status,0,c
 17519 003F38 3209 rrcf LCD_ST77xx_Rotate_Byte@Out,f,c
 17520 003F3A l5023:
 17521
 17522 ;lcd_ST77xx.c: 437: Temp = Temp >> 1;
 17523 003F3A 90D8 bcf status,0,c
 17524 003F3C 3207 rrcf LCD_ST77xx_Rotate_Byte@Temp,f,c
 17525 003F3E 2A08 incf LCD_ST77xx_Rotate_Byte@i,f,c
 17526 003F40 0E07 movlw 7
 17527 003F42 6408 cpfsgt LCD_ST77xx_Rotate_Byte@i,c
 17528 003F44 D7F1 goto l5015
 17529
 17530 ;lcd_ST77xx.c: 438: }
 17531 ;lcd_ST77xx.c: 439: return Out.Byte;
 17532 003F46 5009 movf LCD_ST77xx_Rotate_Byte@Out,w,c ;volatile
 17533 003F48 0012 return

 
My ASM variant
 
19784 00511A 0E80 movlw 128
 19785 00511C 6E21 movwf LCD_ST77xx_Rotate_Byte@Temp,c ;volatile
 19786
 19787 ;lcd_ST77xx.c: 401: volatile uchar i = 7;
 19788 00511E 0E07 movlw 7
 19789 005120 6E22 movwf LCD_ST77xx_Rotate_Byte@i,c ;volatile
 19790
 19791 ;lcd_ST77xx.c: 402: volatile uchar _In_Byte = In_Byte;
 19792 005122 C020 F023 movff LCD_ST77xx_Rotate_Byte@In_Byte,LCD_ST77xx_Rotate_Byte@_In_Byte ;volatile
 19793
 19794 ;lcd_ST77xx.c: 403: volatile uchar Out = 0;
 19795 005126 0E00 movlw 0
 19796 005128 6E24 movwf LCD_ST77xx_Rotate_Byte@Out,c ;volatile
 19797 00512A start_Rotate_Byte:
 19798
 19799 ;#
 19800 00512A 5023 movf LCD_ST77xx_Rotate_Byte@_In_Byte,w,c ;#
 19801 00512C 1421 andwf LCD_ST77xx_Rotate_Byte@Temp,w,c ;#
 19802 00512E E001 bz Zero ;#
 19803 005130 8F24 bsf LCD_ST77xx_Rotate_Byte@Out,7,b ;#
 19804 005132 Zero:
 19805
 19806 ;#
 19807 005132 5022 movf LCD_ST77xx_Rotate_Byte@i,w,c ;#
 19808 005134 E102 bnz Continue ;#
 19809 005136 EFA2 F028 goto Exit ;#
 19810 00513A Continue:
 19811
 19812 ;#
 19813 00513A 4224 rrncf LCD_ST77xx_Rotate_Byte@Out,f,c ;#
 19814 00513C 0622 decf LCD_ST77xx_Rotate_Byte@i,f,c ;#
 19815 00513E 4221 rrncf LCD_ST77xx_Rotate_Byte@Temp,f,c ;#
 19816 005140 EF95 F028 goto start_Rotate_Byte ;#
 19817 005144 Exit:
 19818
 19819 ;lcd_ST77xx.c: 423: return ( Out );
 19820 005144 5024 movf LCD_ST77xx_Rotate_Byte@Out,w,c ;volatile
 19821 005146 0012 return

 
By the way, XC8 compiler did his job very nice
post edited by Kabak - 2021/01/27 05:36:02
#10
blue_led
New Users
  • Total Posts : 87
  • Reward points : 0
  • Status: online
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:41:11 (permalink)
0
seen later. flip byte
for me asm look like this
 

movlw 0x08
   movwf step
loop:
   rrcf input,F
   rlcf output
   decfsz step, F
   goto loop
   return ; optional

  
post edited by blue_led - 2021/01/27 05:43:51
#11
Kabak
Super Member
  • Total Posts : 250
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:42:34 (permalink)
0
Its a pity, but in  ?  true : false ; 
no part of operator could be omitted.
 
And yes, this operator looks more readable in many cases, then too many if / else   ( IMHO )
#12
Kabak
Super Member
  • Total Posts : 250
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 05:48:31 (permalink)
0
blue_led
seen later. flip byte
for me asm look like this
 
movlw 0x08
   movwf step
loop:
   rrcf input,F
   rlcf output
   decfsz step, F
   goto loop
   return ; optional

  


Did you check 7 times GOTO faster than straight 16 rotations ?
 
It's a smallest possible variant, but not sure about speed
post edited by Kabak - 2021/01/27 05:51:15
#13
blue_led
New Users
  • Total Posts : 87
  • Reward points : 0
  • Status: online
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 06:20:13 (permalink)
0 (2)
depend what you want.
speed > 16 rotation
code space > loop
none > XC16
 
turbo speed. minimal impact code length.
 
movlw 0x04
   movwf step
loop:
   rrcf input,F
   rlcf output, F
   rrcf input,F
   rlcf output, F
   decfsz step, F
   goto loop
   return ; optional

 
 
post edited by blue_led - 2021/01/27 06:25:09
#14
1and0
Access is Denied
  • Total Posts : 12080
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 13:08:07 (permalink)
+3 (3)
Kabak
I want to optimize this function
inline uchar LCD_ST77xx_Rotate_Byte ( uchar In_Byte )
{
    ByteBits Out;
    uchar Temp = 0b10000000;
    Out.Byte = 0x0;
            
    for( uchar i = 0; i < 8; ++i )
    {
        ( Temp & In_Byte ) > 0 ? Out.bit7 = 1 : Out.Byte;

        i < 7 ? Out.Byte >>= 1 : Out.Byte;
        
        Temp = Temp >> 1;
    }
    return Out.Byte;
}


Honestly, my first reaction when I read your code in Post #1 is WTF.!  It is difficult to read and understand, and I agreed with Ric that your code is convoluted even when the compiler "did his job very nice".

As I've said about your terminology in the other thread, I also agreed with Ric that this operation is a mirror (or reverse) and not a rotate. Correct usage of terms makes for easier understanding. ;)

Anyway, the fastest way would be a 256-byte lookup table at the expense of more program memory space.

This function takes 12 instruction cycles to reverse bits in a byte, excluding the RETURN.
uint8_t BitReversal(uint8_t X)
{
    X = WREG;      // abcdefgh
#asm
    swapf   BitReversal@X,w
    xorwf   BitReversal@X,w
    andlw   0x66
    xorwf   BitReversal@X
    rrcf    BitReversal@X,w
    rrcf    BitReversal@X
    andlw   0x55
    addwf   BitReversal@X
    rrcf    BitReversal@X
    addwf   BitReversal@X
    rlncf   BitReversal@X,w
#endasm
    return  WREG;  // hgfedcba
}

#15
RISC
Super Member
  • Total Posts : 5960
  • Reward points : 0
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 16:02:19 (permalink)
+1 (1)
Hi,
Since several years I think XC8 free version of the compiler has some optimization.
You should try XC8 v2.41 which is the actual version
Regards

For support make sure to check first here : http://microchipdeveloper.com
There are hundreds of PIC, AVR, SAM...which one do YOU use ?
#16
Kabak
Super Member
  • Total Posts : 250
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 22:04:47 (permalink)
0
1and0
Honestly, my first reaction when I read your code in Post #1 is WTF.!  It is difficult to read and understand, and I agreed with Ric that your code is convoluted even when the compiler "did his job very nice".

As I've said about your terminology in the other thread, I also agreed with Ric that this operation is a mirror (or reverse) and not a rotate. Correct usage of terms makes for easier understanding. ;)

Anyway, the fastest way would be a 256-byte lookup table at the expense of more program memory space.

This function takes 12 instruction cycles to reverse bits in a byte, excluding the RETURN.
uint8_t BitReversal(uint8_t X)
{
    X = WREG;      // abcdefgh
#asm
    swapf   BitReversal@X,w
    xorwf   BitReversal@X,w
    andlw   0x66
    xorwf   BitReversal@X
    rrcf    BitReversal@X,w
    rrcf    BitReversal@X
    andlw   0x55
    addwf   BitReversal@X
    rrcf    BitReversal@X
    addwf   BitReversal@X
    rlncf   BitReversal@X,w
#endasm
    return  WREG;  // hgfedcba
}



WOW !  You are some kind of Harry Houdini in digital world. Your skills are impressive
 
Sorry for my terminology,  I'm not a native English speaker. 
 
For me using ? C operator is regular practice
post edited by Kabak - 2021/01/27 22:08:46
#17
Kabak
Super Member
  • Total Posts : 250
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 22:11:52 (permalink)
0
RISC
Hi,
Since several years I think XC8 free version of the compiler has some optimization.
You should try XC8 v2.41 which is the actual version
Regards


I don't think it's compatable with 1and0 skills in code optimisation.  And I love #asm - #endasm  not asm("") construction
 
Does XC8 2.41 supports variable references in functions call ?
post edited by Kabak - 2021/01/27 22:14:45
#18
ric
Super Member
  • Total Posts : 29861
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/27 22:20:01 (permalink)
+1 (1)
XC8 v2.xx can do everything that 1.xx can do if you select "C90" mode.
Some of the syntax changes to make it more compatible with "ANSI C" when you select C99 mode.
Unfortunately, this includes the #asm syntax, you can only use asm("") syntax in C99.
 
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#19
Kabak
Super Member
  • Total Posts : 250
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
Re: PIC18F26K22 XC8 1.33 C code optimisation 2021/01/28 00:21:57 (permalink)
-1 (1)
ric
XC8 v2.xx can do everything that 1.xx can do if you select "C90" mode.
Some of the syntax changes to make it more compatible with "ANSI C" when you select C99 mode.
Unfortunately, this includes the #asm syntax, you can only use asm("") syntax in C99.


And no passing variables by references.
#20
Page: 12345 > Showing page 1 of 5
Jump to:
© 2021 APG vNext Commercial Version 4.5