LLVM Compiler System The LLVM Compiler Infrastructure Provides reusable components for building compilers Lecture 2 Reduce the time/cost to build a new compiler Build different kinds of compilers Overview of the LLVM Compiler Our homework assignments focus on static compilers There are also JITs, trace-based optimizers, etc. Dominic Chen The LLVM Compiler Framework End-to-end compilers using the LLVM infrastructure Thanks to: Support for C and C++ is robust and aggressive Vikram Adve, Jonathan Burket, Deby Katz, Java, Scheme and others are in development David Koes, Chris Lattner, Gennady Pekhimenko, Emit C code or native code for x86, SPARC, PowerPC and Olatunji Ruwase, for their slides
Carnegie Mellon Carnegie Mellon
Visualizing the LLVM Compiler System LLVM: From Source to Binary More Intermediate Form Object Code C Source Code Source Code Language LLVM IR x86 Clang Frontend C Specific (clang) ARM Clang AST Clang LLVM C++ Back End (Front End) Optimizer LLVM IR Optimizer (opt) Sparc Java Three-Phase Design The LLVM Optimizer is a series of “passes” SelectionDAG –Analysis and optimization passes, run one after another Target-Independent – Analysis passes do not change code, optimization passes do MachineInst Code Generator LLVM Intermediate Form is a Virtual Instruction Set More (llc) –Language- and target-independent form Architecture Used to perform the same passes for all source and target languages Specific MCInst / Assembly –Internal Representation (IR) and external (persistent) representation
Carnegie Mellon Carnegie Mellon
1 C Source Code Clang AST
TranslationUnitDecl 0xd8185a0 <
Read “Life of an instruction in LLVM”: http://eli.thegreenplace.net/2012/11/24/life-of-an-instruction-in-llvm Carnegie Mellon Carnegie Mellon
Clang AST LLVM IR In-Memory Data Structure CompoundStmt
DeclStmt DeclStmt ReturnStmt Bitcode (.bc files) Text Format (.ll files) 42 43 C0 DE 21 0C 00 00 define i32 @main() #0 { IntegerLiteral IntegerLiteral BinaryOperator 06 10 32 39 92 01 84 0C llvm-dis entry: 0A 32 44 24 48 0A 90 21 llvm-asm %retval = alloca i32, align 4 18 00 00 00 98 00 00 00 %a = alloca i32, align 4 ImplicitCastExpr ImplicitCastExpr E6 C6 21 1D E6 A1 1C DA ... …
DeclRefExpr DeclRefExpr Bitcode files and LLVM IR text files are lossless serialization formats! We can pause optimization and come back later.
Carnegie Mellon Carnegie Mellon
2 EntryToken Constant<0> FrameIndex<0> undef 0xa00e308 0xa027550 0xa0275e0 0xa027670 ch i32 i32 i32 Machine Inst 0 1 2 3 Constant<5> FrameIndex<1> store
0 1 2 3 X86ISD::RET_FLAG [ORD=11] 0xa027e50 ch Carnegie Mellon Carnegie Mellon
MCInst Assembly #BB#0: # %entry pushl %ebp #
3 LLVM: From Source to Binary Linking and Link-Time Optimization More C Source Code Language Clang Frontend Specific (clang) Clang AST Bitcode file for JIT .o file LLVM IR Optimizer (opt) LLVM Linker .o file
SelectionDAG LLVM Backend Native Executable
Target-Independent Performs Link-Time Optimizations MachineInst Code Generator More (llc) Architecture Specific MCInst / Assembly
Carnegie Mellon Carnegie Mellon
Goals of LLVM Intermediate Representation (IR) LLVM Instruction Set Overview
Easy to produce, understand, and define Low-level and target-independent semantics Language- and Target-Independent RISC-like three address code One IR for analysis and optimization Infinite virtual register set in SSA form Supports high- and low-level optimization Simple, low-level control flow constructs Load/store instructions with typed-pointers Optimize as much as early as possible
loop: ; preds = %bb0, %loop %i.1 = phi i32 [ 0, %bb0 ], [ %i.2, %loop ] %AiAddr = getelementptr float* %A, i32 %i.1 for (i = 0; i < N; i++) call void @Sum(float %AiAddr, %pair* %P) Sum(&A[i], &P); %i.2 = add i32 %i.1, 1 %exitcond = icmp eq i32 %i.1, %N br i1 %exitcond, label %outloop, label %loop
Carnegie Mellon Carnegie Mellon
4 LLVM Instruction Set Overview (continued) Lowering Source-Level Types to LLVM
High-level information exposed in the code Source language types are lowered: Explicit dataflow through SSA form (more later in the class) Rich type systems expanded to simple types Explicit control-flow graph (even for exceptions) Implicit & abstract types are made explicit & concrete Explicit language-independent type-information Examples of lowering: Explicit typed pointer arithmetic Reference turn into pointers: T& -> T* Preserves array subscript and structure indexing Complex numbers: complex fload -> {float, float} Bitfields: struct X { int Y:4; int Z:2; } -> { i32 } loop: ; preds = %bb0, %loop The entire type system consists of: %i.1 = phi i32 [ 0, %bb0 ], [ %i.2, %loop ] %AiAddr = getelementptr float* %A, i32 %i.1 Primitives: label, void, float, integer, … for (i = 0; i < N; i++) call void @Sum(float %AiAddr, %pair* %P) Arbitrary bitwidth integers (i1, i32, i64, i1942652) Sum(&A[i], &P); %i.2 = add i32 %i.1, 1 Derived: pointer, array, structure, function (unions get turned into casts) %exitcond = icmp eq i32 %i.1, %N No high-level types Nice syntax for calls is br i1 %exitcond, label %outloop, label %loop Type system allows arbitrary casts preserved Carnegie Mellon Carnegie Mellon
Example Function in LLVM IR Example Function in LLVM IR
define i32 @main() #0 { define i32 @main() #0 { entry: entry: %retval = alloca i32, align 4 %retval = alloca i32, align 4 %a = alloca i32, align 4 %a = alloca i32, align 4 int main() { Explicit stack allocation define i32 @main() #0 { %b = alloca i32, align 4 %b = alloca i32, align 4 int a = 5; entry: clang store i32 0, i32* %retval store i32 0, i32* %retval int b = 3; mem2reg %sub = sub nsw i32 5, 3 store i32 5, i32* %a, align 4 Explicit store i32 5, i32* %a, align 4 return a - b; Loads and ret i32 %sub store i32 3, i32* %b, align 4 store i32 3, i32* %b, align 4 } Stores } %0 = load i32* %a, align 4 %0 = load i32* %a, align 4 %1 = load i32* %b, align 4 %1 = load i32* %b, align 4 %sub = sub nsw i32 %0, %1 %sub = sub nsw i32 %0, %1 Not always possible: ret i32 %sub ret i32 %sub Sometimes stack operations } Explicit } are too complex Types
Carnegie Mellon Carnegie Mellon
5 LLVM Instruction Hierarchy LLVM Instructions <--> Values
define i32 @main() #0 { int main() { entry: int x; %retval = alloca i32, align 4 int y = 2; %x = alloca i32, align 4 int z = 3; clang + no m2r %y = alloca i32, align 4 x = y+z; %z = alloca i32, align 4 y = x+z; store i32 0, i32* %retval z = x+y; store i32 1, i32* %x, align 4 } store i32 2, i32* %y, align 4 store i32 3, i32* %z, align 4 %0 = load i32* %y, align 4 %1 = load i32* %z, align 4 %add = add nsw i32 %0, %1 store i32 %add, i32* %x, align 4 …
Carnegie Mellon Carnegie Mellon
LLVM Instructions <--> Values LLVM Instructions <--> Values int main() { ; Function Attrs: nounwind int main() { ; Function Attrs: nounwind int x; define i32 @main() #0 { int x; define i32 @main() #0 { int y = 2; entry: int y = 2; entry: int z = 3; clang + mem2reg %add = add nsw i32 2, 3 int z = 3; clang + mem2reg %add = add nsw i32 2, 3 x = y+z; %add1 = add nsw i32 %add, 3 x = y+z; %add1 = add nsw i32 %add, 3 y = x+z; %add2 = add nsw i32 %add, %add1 y = x+z; %add2 = add nsw i32 %add, %add1 z = x+y; ret i32 0 z = x+y; ret i32 0 } } } }
Instruction I: %add1 = add nsw i32 %add, 3 Instruction I: %add1 = add nsw i32 %add, 3 outs() << *(I.getOperand(0)); “%add = add nsw i32 2, 3” Operand 1 Operand 2 You can’t “get” %add1 from Instruction I. outs() << *(I.getOperand(0)->getOperand(0)); “2” Instruction serves as the Value %add1. Only makes sense for an SSA Compiler
Carnegie Mellon Carnegie Mellon
6 LLVM Program Structure Module Traversal of the LLVM IR data structure Module contains Functions and GlobalVariables usually occurs through doubly-linked Module is a unit of analysis, compilation, and optimization Function Function ... Function lists Function contains BasicBlocks and Arguments Functions roughly correspond to functions in C BasicBlock contains a list of Instructions Function Each block ends in a control flow instruction Basic Basic ... Basic Instruction is an opcode + vector of operands Block Block Block
LLVM also supports Basic Block the Visitor Pattern (more next time) Instruction Instruction ... Instruction
Carnegie Mellon Carnegie Mellon
LLVM Pass Manager LLVM Tools
Compiler is organized as a series of “passes”: Basic LLVM Tools Each pass is an analysis or transformation llvm-dis: Convert from .bc (IR binary) to .ll (human-readable IR text) Each pass can depend on results from previous passes llvm-as: Convert from .ll (human-readable IR text) to .bc (IR binary) Six useful types of passes: opt: LLVM optimizer BasicBlockPass: iterate over basic blocks, in no particular order llc: LLVM static compiler CallGraphSCCPass: iterate over SCC’s, in bottom-up call graph order lli: LLVM bitcode interpreter FunctionPass: iterate over functions, in no particular order llvm-link: LLVM bitcode linker LoopPass: iterate over loops, in reverse nested order llvm-ar: LLVM archiver ModulePass: general interprocedural pass over a program Some Additional Tools RegionPass: iterate over single-entry/exit regions, in reverse nested order bugpoint - automatic test case reduction tool Passes have different constraints (e.g. FunctionPass): llvm-extract - extract a function from an LLVM module FunctionPass can only look at the “current function” llvm-bcanalyzer - LLVM bitcode analyzer Cannot maintain state across functions FileCheck - Flexible pattern matching file verifier tblgen - Target Description To C++ Code Generator Carnegie Mellon Carnegie Mellon
7 opt: LLVM modular optimizer
Invoke arbitrary sequence of passes : Completely control PassManager from command line Supports loading passes as plugins from *.so files
opt -load foo.so -pass1 -pass2 -pass3 x.bc -o y.bc
Passes “register” themselves: When you write a pass, you must write the registration
RegisterPass
Carnegie Mellon
8