I would like to optimize some C++ code. Let have a simplified example:
int DoSomeStuff(const char* data)
{
while(data != NULL)
{
//compute something and use optimization as much as possible
}
return result;
}
I know that *data
is not changed elsewhere. I mean it's not changed in any other thread, but the compiler cannot know. Is there some way to tell the compiler that data on the pointer are not changed for the entire lifetime of the scope?
UPDATE:
int DoSomeStuff(const volatile char* data)
{
while(data != NULL)
{
//compiler should assume that the data are changed elsewhere
}
return result;
}
So, with the same degree of knowledge, humans can produce assembly code that is at least as performant as the compilation result. It can probably be even better, as a human developer can optimize for a given task, while the compiler can only apply generic optimizations.
Compiler optimization is generally implemented using a sequence of optimizing transformations, algorithms which take a program and transform it to produce a semantically equivalent output program that uses fewer resources or executes faster.
Only const on an object definition actually makes it immutable. The main point of using const is not to assist the compiler in optimizations but to protect yourself from mistakes.
Turning on optimization flags makes the compiler attempt to improve the performance and/or code size at the expense of compilation time and possibly the ability to debug the program. The compiler performs optimization based on the knowledge it has of the program.
According to the standard (7.1.6.1):
A pointer or reference to a cv-qualified type need not actually point or refer
to a cv-qualified object, but it is treated as if it does
So I understand it as: the compiler will optimize all access to a const qualified variable as if it really was a const data and could not be modified by a path to a non const variable.
According to the standard (1.10):
The execution of a program contains a data race if it contains two conflicting
actions in different threads, at least one of which is not atomic, and neither
happens before the other. Any such data race results in undefined behavior.
A conflicting action is defined as:
Two expression evaluations conflict if one of them modifies a memory location
(1.7) and the other one accesses or modifies the same memory location.
The happens-before relationship is complex but as I understand it, unless you explicitly used atomic operations (or mutexes) in your code, accessing the same variable from two threads (one writing, another one reading/writing) is undefined behavior. This case being undefined behavior I don't think the compiler will protect you, and it is free to optimize.
Volatile is designed to prevent optimization (7.1.6.1):
volatile is a hint to the implementation to avoid aggressive optimization
involving the object because the value of the object might be changed by means
undetectable by an implementation
Think about a memory mapped I/O register (like a special input port). Even though you cannot write it (because your hardware implementation is read-only), you cannot optimiza your read accesses (because they will return a different byte each time). This special I/O port may be a temperature sensor for instance.
The compiler is already allowed to assume *data
is not modified by another thread. Modifying data in one thread and accessing it in another thread without proper synchronisation is Undefined Behaviour. The compiler is totally free to do anything at all with a program that contains undefined behaviour.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With