Clang is a neat compiler. I like using it.

For some manual optimization of a source code I was interested in the exact difference between the automatic optimization levels -O1 to -O3. What are they doing anyway?

It turns out, this info is not so easy to come by.

The official documentation of Clang specifies quite coarsely the different levels:

-O2: Moderate level of optimization;
-O1: Somewhere between -O0 and -O2


Luckily there’s StackOverflow.

In this answer by Antoine, the two lines needed to get the optimization passes are printed:

llvm-as < /dev/null | opt -O1 -disable-output -debug-pass=Arguments
echo 'int;' | clang -xc -O1 - -o /dev/null -\#\#\#

The first line uses opt, which is the modular LLVM optimizer and analyzer, running on LLVM source files and, I reckon, being independent of the actual programming language. 1

The second command prints the optimization passes which clang, the C/C++ driver of LLVM, puts on top of opt.

This will not explain anything, but solely print the switches used. To understand what lies beneath each switch, LLVM has an explanatory website about the passes (opt --help will also print them, apparently). 2

Luckily, Antoine has compiled the passes Clang uses in the above posting. (At least until Clang 3.8.)

  1. Although I can’t find -disable-output and -debug-pass in the list of options of opt’s help… 

  2. For some of the options clang prints, the description is available through clang -cc1 --help, where cc1 is the frontend; find your’s through clang -\#\#\# -c file.c