I have a pointer int* p, and do some operations in a loop. I do not modify the memory, just read. If I add const to the pointer (both cases, const int* p, and int* const p), can it help a compiler to optimize the code?

I know other merits of const, like safety or self-documentation, I ask about this particular case. Rephrasing the question: can const give the compiler any useful (for optimization) information, ever?

Do you really mean int const* p? Or int* const p? What loop? What are you iterating over?
–
Lightness Races in OrbitJan 31 '12 at 10:46

1

You could just do it and compare the generated code :-?
–
cnicutarJan 31 '12 at 10:47

1

The only way to determine this for a given CPU, compiler, OS, etc is to benchmark it, and the result will then only be valid for this particular configuration of course. It sounds like premature optimisation to me.
–
Paul RJan 31 '12 at 10:49

2

@JakubM. Then in the end do what's most natural. If the memory need not be changed, make it const and call it a day.
–
cnicutarJan 31 '12 at 11:00

1

Instead of looking for optimizations in those calls and ruining the API and readability of your functions you might want to look for bottlenecks elsewhere. That said, I can imagine that a you might find a difference in speed if you do a huge number of calls to a function with / without const modifier, because the compiler needs to insert a cast at the callee.
–
BortJan 31 '12 at 11:11

6 Answers
6

While this is obviously specific to the implementation, it is hard to see how changing a pointer from int* to int const* could ever provide any additional information that the compiler would not otherwise have known.

In both cases, the value pointed to can change during the execution of the loop.

This is simply wrong; int const* is equivalent to const int * which does not point to writeable memory. (What you mean is probably int * const)
–
Jo SoDec 15 '13 at 2:37

1

@JoSo: No, this is correct. All that int const * indicates is that the int may not be modified through that particular pointer. If the int was originally non-const, then it can be modified by another part of the code, or can be modified by the same part of the code after a cast.
–
MankarseDec 15 '13 at 22:37

I got your answer wrong, and cannot retrace how this happened. Sorry for that. Worse, obviously it's not allowed to remove a (down)vote unless the answer is edited... :(
–
Jo SoDec 16 '13 at 0:02

No. Using const like that will not provide the compiler with any information that can be used for optimization.

Theoretically, for it to be a help to your compiler, the optimizer must be able to prove that nobody will ever use const_cast on your const pointer yet be unable to otherwise prove that the variable is never written to. Such a situation is highly unlikely.

If the compiler is able to prove all that additional information, it does not need the const qualification anymore. So even then the const will not help with optimisation.
–
MankarseJan 31 '12 at 11:21

@Mankarse: unless for some silly implementation-specific reason, e.g. a particular optimizer doesn't bother doing the analysis unless the pointer is const-qualified. But you're still correct in what you say, because by my argument anything can affect optimzation -- the number of vowels in your variable names, or whether you indent with tabs vs spaces. The only question is how plausible it is that the optimizer ignores certain potentially-useful information in some circumstances but not others.
–
Steve JessopJan 31 '12 at 12:32

It can help or it can make no difference or it can make it worse. The only way to know is to try both and inspect the emitted machine code.

Modern compilers are very smart so they can often deduce that memory is unchanged without any qualifiers (pr they can deduce many other optimizations are possible without code being written in manner easier to analyze) yet they are rather complex and so have a lot of deficiencies and often can't optimize every possible thing at every opportunity.

Do you have any example when it can make it worse?
–
Jakub M.Jan 31 '12 at 11:00

@Jakub M.: Not for this specific case, but I've seen literally dozens of cases when a compiler failed to emit optimal code.
–
sharptoothJan 31 '12 at 11:28

2

it can make it worse is rather an overstatement and too generalized statement unless substantiated with an example, const can make no difference or some difference, and the difference is negligible enough to not consider it's usage as a optimization criteria, it should only be used to write a more correct maintainable code.
–
Alok SaveJan 31 '12 at 11:38

I think the compiler can't do much in your scenario. The fact that your pointer declared as const int * const p doesn't guarantee that the memory can't be changed externally, e.g. by another thread. Therefore the compiler must generate code that reads the memory value on each iteration of your loop.

But if you are not going to write to the memory location and you know that no other piece of code will, then you can create a local variable and use it similar to this:

Compilers usually don't consider other threads unless you specifically add volatile. Any function call would get in the way though.
–
Per JohanssonJan 31 '12 at 14:01

@PerJohansson: you are probably right. Anyway, another thread was just an example. Side effect of any function call is a good example, too. I just wanted to point out that any optimization performed by the compiler must (and does!) preserve original semantics of the code, while optimizing out memory reads inside a loop certainly doesn't, and therefore will not be performed. But since there's no legal way to change the val externally (outside of the function body), the compiler is free to optimize.
–
Igor KorkhovJan 31 '12 at 14:16

You don't say which compiler you are using. But if you are both reading and writing to memory you could benefit from using "restrict" or similar. The compiler does not know if your pointers are aliasing the same memory so any store often forces loading other values again. "restrict" tells the compiler that no aliasing of the pointer is happening and can keep using values loaded before a subsequent write. Another way to avoid the aliasing issue is to load your values into local variables then the compiler is not forced to reload after a write.