Reputation: 797
I created this program. It does nothing of interest but use processing power.
Looking at the output with objdump -d
, I can see the three rand
calls and corresponding mov
instructions near the end even when compiling with O3 .
Why doesn't the compiler realize that memory isn't going to be used and just replace the bottom half with while(1){}
? I'm using gcc
, but I'm mostly interested in what is required by the standard.
/*
* Create a program that does nothing except slow down the computer.
*/
#include <cstdlib>
#include <unistd.h>
int getRand(int max) {
return rand() % max;
}
int main() {
for (int thread = 0; thread < 5; thread++) {
fork();
}
int len = 1000;
int *garbage = (int*)malloc(sizeof(int)*len);
for (int x = 0; x < len; x++) {
garbage[x] = x;
}
while (true) {
garbage[getRand(len)] = garbage[getRand(len)] - garbage[getRand(len)];
}
}
Upvotes: 4
Views: 310
Reputation:
Leave it a chance to crash by array overflow ! The compiler won't speculate on the range of outputs of getRand
.
Upvotes: 0
Reputation: 18974
It can't, in general, tell that rand()
doesn't have observable side-effects here, and it isn't required to remove those calls.
It could remove the writes, but it may be the use of arrays is enough to suppress that.
The standard neither requires nor prohibits what it is doing. As long as the program has the correct observable behaviour any optimisation is purely a quality of implementation matter.
Upvotes: 5
Reputation: 110155
Because GCC isn't smart enough to perform this optimization on dynamically allocated memory. However, if you change garbage
to be a local array instead, GCC compiles the loop to this:
.L4:
call rand
call rand
call rand
jmp .L4
This just calls rand
repeatedly (which is needed because the call has side effects), but optimizes out the reads and writes.
If GCC was even smarter, it could also optimize out the rand
calls, because its side effects only affect any later rand
calls, and in this case there aren't any. However, this sort of optimization would probably be a waste of compiler writers' time.
Upvotes: 10
Reputation: 141628
This code causes undefined behaviour because it has an infinite loop with no observable behaviour. Therefore any result is permissible.
In C++14 the text is 1.10/27:
The implementation may assume that any thread will eventually do one of the following:
- terminate,
- make a call to a library I/O function,
- access or modify a volatile object, or
- perform a synchronization operation or an atomic operation.
[Note: This is intended to allow compiler transformations such as removal of empty loops, even when termination cannot be proven. —end note ]
I wouldn't say that rand()
counts as an I/O function.
Upvotes: 3