5

Here is the case,

I've tried to investigate a little bit advantages/disadvantages of implementation functions as follows :

void foo(const int a, const int b)
{
    ...
}

with common function prototype which is used as API and it's included in header file as shown below :

void foo(int a, int b)

I've found quite a huge discussion about this topic in the following question:

Similar Q

I agree there with answer from the rlerallut who is saying about self-documenting code and about being a little bit paranoid on the angle of security of your code.

However and this is the question, someone wrote there that using const for the usual parameters passed to the function can bring some optimization benefits. My question is does anybody have real life example which proves this claim ?

Community
  • 1
  • 1
Lazureus
  • 462
  • 4
  • 19
  • Did you saw this one? http://stackoverflow.com/questions/6313730/does-const-correctness-give-the-compiler-more-room-for-optimization – michaelmeyer Feb 19 '14 at 00:26
  • This answer basically concerns `const` pointers about which I weren't thinking actually. I don't know does this answer can be applied to the normal parameters passed by value.I find also this answer a little bit confusing, especially there is a claim that casting away `const` pointer and modifying it's value in local scope is not UB, but doing the same with global scope is UB. There was a comment pointing this inconsistency but wasn't taken into account I suppose. – Lazureus Feb 19 '14 at 01:03
  • 1
    The benefit of a const value parameter is it keeps the coder from inadvertently modifying it. If it helps the optimizer at all, it will be too little to notice, and the optimizer itself only helps you in a very peculiar type of code - tight CPU loops, in your code (not in libraries) that you spend a big fraction of time in. Many people think it's a good thing everywhere, when it actually only helps in those little closets of code where the program counter likes to hide. What it does for you in the rest of the code is make it harder to debug. – Mike Dunlavey Feb 19 '14 at 01:18
  • 1
    Any "real life example" is going to be specific to a particular compiler, which I presume is not what you're looking for. A good compiler could discover by itself that an argument is never altered and optimize appropriate, `const` or not. The better reason to use `const` on function parameters is that it guards you against certain kinds of programming error. – keshlam Feb 19 '14 at 01:18
  • I'd love to have real life example for e.g. gcc or gcc-arm-none-eabi for STM32. Those compilers I can easily test and check the assembler output of two tested codes. I want to do this by compiling tested function with const keyword in definition and without and then make a comparision. I should notice the difference, don't you think ? – Lazureus Feb 19 '14 at 01:29
  • 1
    No, I don't think you should notice the difference... because, as I said, a decent optimizer should be able to do the right thing without the hint. – keshlam Feb 19 '14 at 02:12
  • I wish the compiler I use, would notice that calling `io_func(address, 0x1001); io_func(address+4, 0x1002);` with const int arguments could be implemented as `ldr r2, address; ldr r3, 0x1001; call io_func; addi r2, 4; addi r3, 1; call io_func;`. But it doesn't. – Aki Suihkonen Feb 19 '14 at 07:08
  • The optimization I'd care for, really boils down to the question, if the attribute `const` weighs more than the ABI which differentiates caller saved registers from callee saved registers. – Aki Suihkonen Feb 19 '14 at 07:15
  • @AkiSuihkonen Actually I don't understand what you mean by question: "if the attribute const weighs more than the ABI which differentiates caller saved registers from callee saved registers", can you give me some hint where to find information about your remark? – Lazureus Feb 19 '14 at 08:19
  • That's the point: nowhere. If the ABI dictates that caller can trash the arguments even though they are marked 'const', then it's not possible to optimize [locally] the sequence I proposed. – Aki Suihkonen Feb 19 '14 at 08:42

1 Answers1

2

"it might help the compiler optimize things a bit (though it's a long shot)."

I cant see how it would make a difference. It is most useful in this case to generate compiler warnings/errors when you try to modify the const variable...

If you were to try to invent an experiment to compare a function parameter declared as const or not for the purpose of optimization, pass by value. That means that this experiment would not modify the variable(s) because when const is used you would expect a warning/error. An optimizer that might be able to care, would already know that the variable is not modified in the code with or without the declaration and can then act accordingly. How would that declaration matter? If I found such a thing I would file the difference as a bug to the compiler bugboard.

For example here is a missed opportunity I found when playing with const vs not.

Note const or not doesnt matter...

void fun0x ( int a, int b);
void fun1x ( const int a, const int b);
int fun0 ( int a, int b )
{
    fun0x(a,b);
    return(a+b);
}
int fun1 ( const int a, const int b )
{
    fun1x(a,b);
    return(a+b);
}

gcc produced with a -O2 and -O3 (and -O1?)

00000000 <fun0>:
   0:   e92d4038    push    {r3, r4, r5, lr}
   4:   e1a05000    mov r5, r0
   8:   e1a04001    mov r4, r1
   c:   ebfffffe    bl  0 <fun0x>
  10:   e0850004    add r0, r5, r4
  14:   e8bd4038    pop {r3, r4, r5, lr}
  18:   e12fff1e    bx  lr

0000001c <fun1>:
  1c:   e92d4038    push    {r3, r4, r5, lr}
  20:   e1a05000    mov r5, r0
  24:   e1a04001    mov r4, r1
  28:   ebfffffe    bl  0 <fun1x>
  2c:   e0850004    add r0, r5, r4
  30:   e8bd4038    pop {r3, r4, r5, lr}
  34:   e12fff1e    bx  lr

Where this would have worked with less cycles...

push {r4,lr}
add r4,r0,r1
bl fun1x
mov r0,r4
pop {r4,lr}
bx lr

clang/llvm did the same thing the add after the function call burning extra stack locations.

Googling showed mostly discussions about const by reference rather than const by value and then the nuances of C and C++ as to what will or wont or can or cant change with the const declaration, etc.

If you use the const on a global variable then it can leave that item in .text and not have it in .data (and for your STM32 microcontroller not have to copy it from flash to ram). But that doesnt fit into your rules. the optimizer may not care and may not actually reach out to that variables home it might know to encode it directly into the instruction as an immediate based on the instruction set, etc...All things held equal though a non-const would have that same benefit if not declared volatile...

Following your rules the const saves on some human error, if you try to put that const variable on the left side of an equals sign the compiler will let you know.

I would consider it a violation of your rules, but if inside the function where it was pass by value you then did some pass by reference things and played the pass by reference const vs not optimization game....

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • Is this code after your sentence "Where this would have worked with less cycles..." is the clang output ? – Lazureus Feb 19 '14 at 08:32
  • Nope, that is hand coded, clang actually did a stack frame so it was gcc like with more instructions. – old_timer Feb 20 '14 at 18:26