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

Compiler Reports

Clang/LLVM can produce reports for many of its transformation passes, not just vectorization:

  • -Rpass=<string>: Produces reports of which optimizations matching <string> were successful.
  • -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>

The argument <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

Outline

  • 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

Compiler Optimizations

  • Data Structures
    • Register allocation
    • Memory to registers
    • Scalar replacement of aggregates