What Compilers can and cannot Do
Clang/LLVM Compilation Pipeline
This lecture completes more of the story from Lecture 5 about the compilation process
Why study the compiler optimizations?
- Compiler can have a big impact on software performance
- Compilers can save you performance-engineering work.
- Compilers help ensure that simple, readable, and maintainable code is fast
- You can understand the differences between the source code and the IR or assembly
- Compilers can make mistakes
- Understanding compilers can help you use them more effectively.
Simple Model of the Compiler
An optimizing compiler performs a sequence of transformation passes on the code
LLVM IR -> Transform -> Transform -> Transform -> ... -> Transform -> Optimized LLVM IR
- Each transofrmation pass analyzes and edits the code to try to optimize the code’s performance
- A transformation pass might run multiple times
- Passes run in a predetermined order that seems to work well most of the time
Clang/LLVM can produce reports for many of its transformation passes, not just vectorization:
-Rpass=<string>: Produces reports of which optimizations matching
-Rpass-missed<string>: Produces reports of which optimizations matching
<string>were not successful.
-Rpass-analysis=<string>: Produces reports of the analyses performed by optimizations matching
<string> is a regular expression. To see the whole report, use “.*” as the string.
The good news: The compiler can tell you a lot about what’s doing
- Many transformation passes in LLVM can report places where they successfully transform code.
- Many can also report the conclusions of their analysis.
The bad news: Reports can be hard to understand.
- The reports can be long and use LLVM jargon.
- Not all transformation passes generate reports.
- Reports don’t always tell the whole story.
We want context for understanding these reports
- Example compiler optimizations
- Optimizing a scalar
- Optimizing a structure
- Optimizing function calls
- Optimizing loops
- Diagnosing failures
- Case Study 1
- Case Study 2
- Case Study 3
- Data Structures
- Register allocation
- Memory to registers
- Scalar replacement of aggregates