2

There are many statements in C that does nothing. That means that removing them will have no observable change in program behavior.

According to the C standard, Are C compilers allowed to optimize away these redundant statements?

For example, if we have code like this:

#include <stdio.h>

void f(void);

int main(void){

    printf("a");
    f(); // function call statement that provably does nothing

    printf("b");
    1000; // redundant expression statement

    printf("c");
    ; // null statement

    printf("d");
    int x = 1; // assignment statement that is not used

    printf("e");

    return 0;
}

void f(void){
    1000; // redundant expression statement
    ; // null statement
    int x = 1; // assignment statement that is not used
}

Is the compiler allowed to produce the same object code as below? :

#include <stdio.h>

void f(void);

int main(void){
    printf("a");
    printf("b");
    printf("c");
    printf("d");
    printf("e");
    return 0;
}

void f(void){
}
user207421
  • 305,947
  • 44
  • 307
  • 483
Pacerier
  • 86,231
  • 106
  • 366
  • 634
  • 1
    Yes, read Question: [Regarding optimization for 'not a statment' in c?](http://stackoverflow.com/questions/13566662/regarding-optimization-for-not-a-statment-in-c) may be help you. – Grijesh Chauhan Oct 22 '13 at 06:15
  • function calling probably not removed .. try with `-o2` also – Grijesh Chauhan Oct 22 '13 at 06:16
  • @GrijeshChauhan. I meant regardless, are they *allowed* to remove it? – Pacerier Oct 22 '13 at 06:18
  • @parcerier do you have question regarding specific compiler? as I saw in most compiler function call not optimized. – Grijesh Chauhan Oct 22 '13 at 06:21
  • This can tested using http://gcc.godbolt.org/. A simple test with Clang with `-O2` shows that the two codes generate the same assembly. – Kotte Oct 22 '13 at 06:33
  • @GrijeshChauhan, no this is more a question about the C standard, than a particular C compiler implementation. – Pacerier Oct 22 '13 at 09:34

4 Answers4

7

Back in the 80s, a friend of mine told me that he wrote a program that performed an algorithm to calculate pi, and then just printf it out.

When he looked at the compiled exe file, he was amazed to see that the compiler had produced basically : output 3.14159

In short, C (or any other language) compilers are allowed to do anything and everything that does not change the BEHAVIOUR of the program.

This also applies to Java, etc, where the JVM employ several techniques to increase speed (eg. "unwrapping" loops so the code is executed sequentially without going through the looping overhead, etc)

racraman
  • 4,988
  • 1
  • 16
  • 16
  • Your pi example is very interesting. I want to know if compilers do dry runs of the code to optimize it and in this case, it seems it does. Can anyone confirm this? – zeitgeist Sep 18 '21 at 17:33
  • 1
    Interesting question, though out of my area (and I don't think compilers would ever "dry-run" by dumb-compiling + linking + running the source and recording the output). If he programmed a fixed number of iterations, then loop unrolling and constant folding would do the job. However, I would *GUESS* my friend used a while loop (loop until no significant change detected), so I could see the compiler realising there's just constants (no input from external sources) so repeating the calculations until the loop condition is met (so just an enhanced version of fixed iterations). – racraman Sep 19 '21 at 04:50
6

The C standard says (C11 5.1.2.3/4):

In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced (including any caused by calling a function or accessing a volatile object).

So the compiler is free to optimize away a function call unless the function contains any "needed" side effects. The wording is a bit vague and could possibly be interpreted in different ways. But in practice, all compilers will most likely optimize away empty functions.

Lundin
  • 195,001
  • 40
  • 254
  • 396
2

Yes, if told to optimise compilers also may optimse away code that does nothing.

However most compilers do not optimse by default.

For gcc there are one + three levels:

-Ox with  x = {0, 1, 2, 3} (0 does not optimise and is the default)

A quick test with gcc ((Debian 4.4.5-8) 4.4.5) showed that already using -O1 on the OP's example code results in exactly that what the OP's assumes.


Interesting enough even the explicit return 0 is optimised away from -O1 on.

alk
  • 69,737
  • 10
  • 105
  • 255
0

It strongly depends on the compiler what it removes, and to what lengths it goes with that. Some compilers may even remove entire static functions (not just their call, but even their definition) at some settings, while others may be very conservative, and not remove anything. In other words, it might be pretty much the object code as stated, or it could even be

int main(int argc, char**argv) {
   printf("abcde")
   return 0;
}
Norwæ
  • 1,575
  • 8
  • 18