In this cookbook I will discuss several techniques to reduce the compile time of the llvm frontend clang. I will put the focus on heavy template and constexpr code.
First it is important to understand the internals of clang. Clang is a collection of tools which are pipelined.
- Performs the actions of the C preprocessor
- The command line option
-E
stops clang after this stage
- Parses the source code and generates the AST
- The command line option
-precompile
stops clang after this stage
- Converts the AST into an optimizer-specific intermediate representation (IR)
- Source
- InstantiateClass / InstantiateFunction
- PerformPendingInstantiations
- CodeGen Function
- PerfFunctionPasses
- PerfModulePasses / OptModule
- The command line option
-emit-llvm
stops clang after this stage
- Converts the IR into target-specific assembly code
- CodeGenPasses
- The command line option
-S
stops clang after this stage
- Converts target-specific assembly code into target-specific machine code object files
- The command line option
-c
stops clang after this stage
- Combines multiple object files into a single image
Since clang 9 you can analyse compile time very detailed with the cxx flag -ftime-trace
. This flag generates a json file which can be loaded into the chrome trace analyser chrome://tracing/
or an online tool
Once you have generated the json file and opened it in chrome you will notice the different stages of the clang pipeline e.g. source, frontend, and backend.
- It can be hard to read through the trace if you use anonymous functions (lambdas) since they will be listed as
(anonymous class)::operator()
. For better readability you should use templated functions or Functors.