For performance reasons, are recursions ever replaced with while loops? I know the code looks much uglier, but let's take the following example:
void print_countdown(long long n) {
if (n!=0) {
printf("Placeholder for a function\n");
print_countdown(n-1);
} else
printf("Done!\n");
}
If the number is 1 million, then this will have an overhead of:
- 1 million copies of the
nvar (saved from rdi, put back in rdi for the recursive call, if the recursive work includes a function call, otherwise it can stay in rdi.) call funcpush rbp ... popfunction prologue or something else for stack alignment, depending on optimization level and compiler choices.
In other words, while the code is readable, for anything like > 1000 loops, this seems to be better rewritten to something like:
void print_countdown(long long n) {
while (n < MAX_LOOPS) {
if (n!=0) {
printf("Placeholder for a function\n");
n = n-1;
} else
printf("Done!");
}
}
The assembly code (Godbolt) also looks much, much simpler in the while format -- ~20 lines vs ~40 lines.
Is it common to do this kind of loop-rewriting, and are there ever times in a recursive function call where it cannot be re-written to a loop ?
-O3and find out. (But basically, replacing call foo / ret with jmp foo is standard tailcall optimization. In a recursive function, this creates a loop that can be optimized further.)-O3is not required, I only said that to chime in with tf3's comment. (I didn't notice the Godbolt link right away because links are less visible on code formatting, which the link text used for no reason.)