Jump to content

Recommended Posts

Looking at others code on the board makes me notice some of my habits from

other compilers(?) regarding optimizations for speed or space. Since i've yet to

read any such list regarding this topic and BoostC i figure its time to ask.

 

A few common ones i remember offhand:

-subtracting/deincrementing is faster than adding/incrementing

-not using division saves ~35bytes

-Left Shifting is faster than Right

-Calling a function in an ISR takes longer than outside an ISR

-Never use a function for a single operation, you waste time calling and returning

-Use bit shifting instead of division for speed savings and possible ram savings

(shifting one bit right is equal to dividing by two, etc)

 

i am sure there are many others and i cannot even remember which belong to which

compilers of if some were actually hardware based optimizaions.

 

It would be great if others would list thier known and suspected tweaks here for discussion.

Link to post
Share on other sites

I dont think any of these are valid optimisations with BoostC.

 

-subtracting/deincrementing is faster than adding/incrementing

-Left Shifting is faster than Right

-Calling a function in an ISR takes longer than outside an ISR

 

 

BoostC performs additional optimisations on shift operations.

 

-Use bit shifting instead of division for speed savings and possible ram savings

     (shifting one bit right is equal to dividing by two, etc)

 

 

Edited by Picxie
Link to post
Share on other sites

I just saved a lot of bytes by reducing the number of index access on array vars.

 

a stupid and useless example:

char var[10];

 

for( i= 0; i<10;i++){

if ((var==this) || (var==that)) var=somefunction(var);

var+=2;

}

 

 

if you need to have access on a particular index several times i'm using an extra dummy var.

 

char var[10], dummy;

 

for( i= 0; i<10;i++){

dummy= var;

if ((dummy==this) || (dummy==that)) dummy=somefunction(dummy);

var= dummy+=2;

}

 

something similar happens when you are working with struct variables.

Link to post
Share on other sites

Here are a few tricks that can reduce code size a lot:

 

1. Use smallest data type possible. For example if 8 bits is enough use char and not short or long.

2. Use unsigned data types if possible. Unsigned types generate shorter code than signed.

3. Both arrays and pointers generate a lot of code. Use plain variables instead where possible.

 

Regards,

Pavel

Link to post
Share on other sites

i had forgotten about this one but the good old ()?:; (tri-unary?) function conditionally yields

slightly smaller/faster code on every compiler i've ever used versus using if()else();

The gain varies from 1-3 lines of asm code, which, if in a high use test will amount

to a conciderable savings.

 

The conditional aspect of this is that the fail function must do something it cannot be

left empty or there is no value in using it and will actually result in longer code.

 

(test)?(result=1):(result=0);

VS

if(test)
{
   result=1;
}
else
{
   result=0;
}

Link to post
Share on other sites
Here are a few tricks that can reduce code size a lot:

 

1. Use smallest data type possible. For example if 8 bits is enough use char and not short or long.

2. Use unsigned data types if possible. Unsigned types generate shorter code than signed.

3. Both arrays and pointers generate a lot of code. Use plain variables instead where possible.

 

Regards,

Pavel

 

To add onto this list a bit:

-Write constants into ROM not RAM

-Do not return values from functions that you wont use/do not need

-Reuse common code or write a common function and call it will save huge amounts of space

( i suspect agressive opt in BoostC may negate this last but i've yet to test)

Link to post
Share on other sites
i had forgotten about this one but the good old ()?:; (tri-unary?) function conditionally yields slightly smaller/faster code...

I tried that one out and there's no gain on SourceBoost C (for PIC16) on any optimization level.

 

For code like that, I would expect this:

result = (test ? 1 : 0)

to do better, but it doesn't, either...

Link to post
Share on other sites
i had forgotten about this one but the good old ()?:; (tri-unary?) function conditionally yields slightly smaller/faster code...

I tried that one out and there's no gain on SourceBoost C (for PIC16) on any optimization level.

 

For code like that, I would expect this:

result = (test ? 1 : 0)

to do better, but it doesn't, either...

 

 

Odd, altho my tests were simply:

 

    (testBit)?(_ONE = 1):(_ONE = 0);
0039  08A1      MOVF main_1_testBit, F
003A  1903      BTFSC STATUS,Z
003B  283E      GOTO    label268438744
003C  1486      BSF gbl__ONE,1
003D  283F      GOTO    label268438746
003E        label268438744
003E  1086      BCF gbl__ONE,1
003F        label268438746

        if(testBit)
003F  08A1      MOVF main_1_testBit, F
0040  1903      BTFSC STATUS,Z
0041  2844      GOTO    label268438747
0044        label268438747

        {
            _ONE = 1;
0042  1486      BSF gbl__ONE,1

        }
        else
0043  2837      GOTO    label268438739

        {
            _ONE = 0;
0044  1086      BCF gbl__ONE,1

        }

 

with the asm disassembly, but it looks like i am wrong about the new version of

the compiler. i am glad to see that these are now the same as they are identical

chunks of code.

 

If i recall correctly, the reason they were different is that the if-else used to use two

bit tests to determine logic, which is how you would do it if you had more ifelse tests.

 

Now i am back to using ?:; just for a cleaner look to code i guess. Thanks for testing

that with the new version, it did not even occur to me that it may have changed :D

 

 

----------------

 

Hmm it looks like the if-else might actually be one line shorter now ... altho it is

just a lable line.

Edited by emte
Link to post
Share on other sites
result= test&1;

 

?????

 

Yes that would possibly work in this case as it is an extremly simple example.

But on the otherhand if you were writting code for an indicator light, say to

notify of an AD conversion, you could not use the return value as your test bit.

ie. if test = 4 that mask would fail but (test)?(result=1):(result=0); would work

since all non-zero/positives would set result.

 

i find this handy if you have more than one AD module on your device instead

of using the flags as you can now build an AD FIFO cyclical stack or non-blocking

time sensitive functions. (all that slow eeprom write stuff while your doing another

conversion)

... hmm maybe i should add that example to handy functions ...

Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...