Question:
Let's look at some simple code.
void f() {
}
// ...
f();
It is clear that the function f
does nothing (more precisely, does not do any useful work), so the compiler can safely "throw" it without changing the behavior of the program. (We do not take the return address from there, because it is a "dirty hack", and it may not even work.)
Let's complicate the task:
void g(int x) {
}
int calc_x() {
// Долго и упорно что-то вычисляем.
}
// ...
g(42); // Ни на что не влияет.
g(calc_x()); // А вот тут непонятно...
It is clear that g(42)
can be omitted. But throwing out g(calc_x())
is generally not allowed, because calc_x
can have side effects.
Accordingly, the question is: under what conditions will the compiler have the right to throw out calls to the g
function?
PS I understand that the compiler may even leave the f()
call if all optimizations are disabled. The question should be understood exactly as it is written – it will not throw it away, but has the right to throw it away .
Answer:
The compiler may turn a call to g(calc_x());
into the following [pseudo]code:
int x = ...;
calc_x код
x теперь чем-то проинициализирован.
Здесь мог бы быть код из g, но его там нет. Увы.
Those. the compiler has inlined both functions, after which it sees that x
is not used anywhere and at this stage it can throw out the code altogether.
For example, here is the following C++ code:
void g(int x) {
}
int calc_x() {
int x = 0;
while(x < 500)
{
++x;
}
return x;
}
int main()
{
g(42);
g(calc_x());
}
It turns into this assembler (both in the studio and in gcc):
main:
xor eax, eax
ret
If you try to deduce a general pattern, then you can consider this: if the compiler can prove that the code has no side effects, then it can throw it away. Otherwise, he has no right to touch him. Simple calculations, this is code free from side effects, so the compiler throws it out, in the example above. But "maybe" does not mean that he will throw it away. Therefore, you cannot rely on it.