2004-09-22-LCPCLLVMTutorial (1) - The LLVM Compiler...

Info icon This preview shows page 1. Sign up to view the full content.

This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: The LLVM Compiler Framework and Infrastructure Chris Lattner Vikram Adve [email protected] du [email protected] du LCPC Tutorial: September 22, 2004 Acknowledgements UIUC Contributors: External Contributors: Tanya Brethour Misha Brukman Henrik Bach Nate Begeman Cameron Buschardt John Criswell Jeff Cohen Paolo Invernizzi Alkis Evlogimenos Brian Gaeke Brad Jones Vladimir Merzliakov Ruchira Sasanka Anand Shukla Vladimir Prus Reid Spencer Bill Wendling Funding: This work is sponsored by the NSF Next Generation Software program through grants EIA-0093426 (an NSF CAREER award) and EIA-0103756. It is also supported in part by the NSF Operating Systems and Compilers program (grant #CCR9988482), the NSF Embedded Systems program (grant #CCR-0209202), the MARCO/DARPA Gigascale Systems Research Center (GSRC), IBM through the DARPA-funded PERCS project, and the Motorola University Partnerships in Research program. Chris Lattner – LLVM Compiler System The LLVM Compiler Infrastructure Provides reusable components for building compilers Reduce the time/cost to build a new compiler Build static compilers, JITs, trace-based optimizers, ... The LLVM Compiler Framework End-to-end compilers using the LLVM infrastructure C and C++ are robust and aggressive: Java, Scheme and others are in development Emit C code or native code for X86, Sparc, PowerPC Chris Lattner – Three primary LLVM components The LLVM Virtual Instruction Set The common language- and target-independent IR Internal (IR) and external (persistent) representation A collection of well-integrated libraries Analyses, optimizations, code generators, JIT compiler, garbage collection support, profiling, … A collection of tools built from the libraries Assemblers, automatic debugger, linker, code generator, compiler driver, modular optimizer, … Chris Lattner – Tutorial Overview Introduction to the running example LLVM C/C++ Compiler Overview High-level view of an example LLVM compiler The LLVM Virtual Instruction Set IR overview and type-system LLVM C++ IR and important API’s Basics, PassManager, dataflow, ArgPromotion Important LLVM Tools opt, code generator, JIT, test suite, bugpoint Example applications of LLVM Chris Lattner – Running example: arg promotion Consider use of by-reference parameters: int callee(const int &X) { return X+1; } int caller() { return callee(4); } We want: int callee(int X) { return X+1; } int caller() { return callee(4); } compiles to int callee(const int *X) { return *X+1; // memory load } int caller() { int tmp; // stack object tmp = 4; // memory store return callee(&tmp); } Eliminated load in callee Eliminated store in caller Eliminated stack slot for ‘tmp’ Chris Lattner – Why is this hard? Requires interprocedural analysis: Must change the prototype of the callee Must update all call sites we must know all callers What about callers outside the translation unit? Requires alias analysis: Reference could alias other pointers in callee Must know that loaded value doesn’t change from function entry to the load Must know the pointer is not being stored through Reference might not be to a stack object! Chris Lattner – Tutorial Overview Introduction to the running example LLVM C/C++ Compiler Overview High-level view of an example LLVM compiler The LLVM Virtual Instruction Set IR overview and type-system LLVM C++ IR and important API’s Basics, PassManager, dataflow, ArgPromotion Important LLVM Tools opt, code generator, JIT, test suite, bugpoint Example applications of LLVM Chris Lattner – The LLVM C/C++ Compiler From the high level, it is a standard compiler: Compatible with standard makefiles Uses GCC 3.4 C and C++ parser C file llvmgcc .o file C++ file llvmg++ .o file Compile Time llvm linker executable Link Time Distinguishing features: Uses LLVM optimizers, not GCC optimizers .o files contain LLVM IR/bytecode, not machine code Executable can be bytecode (JIT’d) or machine code Chris Lattner – Looking into events at compile-time C file llvmgcc .o file C++ file llvmg++ .o file C to LLVM Frontend Compile-time Optimizer C++ to LLVM Frontend Compile-time Optimizer “cc1” “gccas” “cc1plus” “gccas” Modified version of GCC LLVM IR LLVM Emits LLVM IR as text file Parser Verifier Lowers C AST to LLVM Modified version .bcG++ 40 LLVM Analysis & LLVM of Emits Optimization Passes LLVM IR as text file File Writer Lowers C++ AST to LLVM Dead Global Elimination, IP Constant Propagation, Dead Argument Elimination, Inlining, Reassociation, LICM, Loop Opts, Memory Promotion, Dead Store Elimination, ADCE, … Chris Lattner – Looking into events at link-time .o file .o file .o file .o file LLVM Linker llvm linker executable Link-time Optimizer 20 LLVM Analysis & Optimization Passes Optionally “internalizes”: marks most functions as internal, to improve IPO Perfect place for argument promotion optimization! .bc file for LLVM JIT Native Code Backend “llc” C Code Backend “llc –march=c” Native executable C Compiler “gcc” Link in native .o files and libraries here Chris Lattner – Native executable Goals of the compiler design Analyze and optimize as early as possible: Compile-time opts reduce modify-rebuild-execute cycle Compile-time optimizations reduce work at link-time (by shrinking the program) All IPA/IPO make an open-world assumption Thus, they all work on libraries and at compile-time “Internalize” pass enables “whole program” optzn One IR (without lowering) for analysis & optzn Compile-time optzns can be run at link-time too! The same IR is used as input to the JIT IR design is the key to these goals! Chris Lattner – Tutorial Overview Introduction to the running example LLVM C/C++ Compiler Overview High-level view of an example LLVM compiler The LLVM Virtual Instruction Set IR overview and type-system LLVM C++ IR and important API’s Basics, PassManager, dataflow, ArgPromotion Important LLVM Tools opt, code generator, JIT, test suite, bugpoint Example applications of LLVM Chris Lattner – Goals of LLVM IR Easy to produce, understand, and define! Language- and Target-Independent AST-level IR (e.g. ANDF, UNCOL) is not very feasible Every analysis/xform must know about ‘all’ languages One IR for analysis and optimization IR must be able to support aggressive IPO, loop opts, scalar opts, … high- and low-level optimization! Optimize as much as early as possible Can’t postpone everything until link or runtime No lowering in the IR! Chris Lattner – LLVM Instruction Set Overview #1 Low-level and target-independent semantics RISC-like three address code Infinite virtual register set in SSA form Simple, low-level control flow constructs Load/store instructions with typed-pointers IR has text, binary, and in-memory forms loop: %i.1 = phi int [ 0, %bb0 ], [ %i.2, %loop ] %AiAddr = getelementptr float* %A, int %i.1 for (i = 0; i < N; call void %Sum(float %AiAddr, %pair* %P) ++i) %i.2 = add int %i.1, 1 Sum(&A[i], &P); %tmp.4 = setlt int %i.1, %N br bool %tmp.4, label %loop,Lattner – %outloop Chris label LLVM Instruction Set Overview #2 High-level information exposed in the code Explicit dataflow through SSA form Explicit control-flow graph (even for exceptions) Explicit language-independent type-information Explicit typed pointer arithmetic Preserve array subscript and structure indexing loop: %i.1 = phi int [ 0, %bb0 ], [ %i.2, %loop ] %AiAddr = getelementptr float* %A, int %i.1 for (i = 0; i < N; call void %Sum(float %AiAddr, %pair* %P) ++i) %i.2 = add int %i.1, 1 Sum(&A[i], &P); %tmp.4 = setlt int %i.1, %N br bool %tmp.4, label %loop,Lattner – %outloop Chris label LLVM Type System Details The entire type system consists of: Primitives: void, bool, float, ushort, opaque, … Derived: pointer, array, structure, function No high-level types: type-system is language neutral! Type system allows arbitrary casts: Allows expressing weakly-typed languages, like C Front-ends can implement safe languages Also easy to define a type-safe subset of LLVM See also: docs/LangRef.html Chris Lattner – Lowering source-level types to LLVM Source language types are lowered: Rich type systems expanded to simple type system Implicit & abstract types are made explicit & concrete Examples of lowering: References turn into pointers: T& T* Complex numbers: complex float { float, float } Bitfields: struct X { int Y:4; int Z:2; } { int } Inheritance: class T : S { int X; } { S, int } Methods: class T { void foo(); } void foo(T*) Same idea as lowering to machine code Chris Lattner – LLVM Program Structure Module contains Functions/GlobalVariables Module is unit of compilation/analysis/optimization Function contains BasicBlocks/Arguments Functions roughly correspond to functions in C BasicBlock contains list of instructions Each block ends in a control flow instruction Instruction is opcode + vector of operands All operands have types Instruction result is typed Chris Lattner – Our example, compiled to LLVM int callee(const int *X) { return *X+1; // load } int caller() { int T; // on stack T = 4; // store return callee(&T); } internal int %callee(int* %X) { %tmp.1 = load int* %X %tmp.2 = add int %tmp.1, 1 ret int %tmp.2 } int %caller() { %T = alloca int store int 4, int* %T %tmp.3 = call int %callee(int* %T) ret int %tmp.3 } Linker “internalizes” All loads/stores are Stack allocation is most functions in most explicit in the LLVM explicit in LLVM representation cases Chris Lattner – Our example, desired transformation internal int %callee(int* %X) { %tmp.1 = load int* %X %tmp.2 = add int %tmp.1, 1 ret int %tmp.2 } int %caller() { %T = alloca int store int 4, int* %T %tmp.3 = call int %callee(int* %T) ret int %tmp.3 } Other transformation Update all instructions Insert load call sites of Change the prototype (-mem2reg) cleans up for the function into‘callee’ all callers the rest internal int %callee(int %X.val) { %tmp.2 = add int %X.val, 1 ret int %tmp.2 } int %caller() { %T = alloca int store int 4, int* %T %tmp.1 = load int* %T %tmp.3 = call int %callee(%tmp.1) ret int %tmp.3 } int %caller() { %tmp.3 = call int %callee(int 4) ret int %tmp.3 } Chris Lattner – Tutorial Overview Introduction to the running example LLVM C/C++ Compiler Overview High-level view of an example LLVM compiler The LLVM Virtual Instruction Set IR overview and type-system LLVM C++ IR and important API’s Basics, PassManager, dataflow, ArgPromotion Important LLVM Tools opt, code generator, JIT, test suite, bugpoint Example applications of LLVM Chris Lattner – LLVM Coding Basics Written in modern C++, uses the STL: Particularly the vector, set, and map classes LLVM IR is almost all doubly-linked lists: Module contains lists of Functions & GlobalVariables Function contains lists of BasicBlocks & Arguments BasicBlock contains list of Instructions Linked lists are traversed with iterators: Function *M = … for (Function::iterator I = M->begin(); I != M->end(); ++I) { BasicBlock &BB = *I; ... See also: docs/ProgrammersManual.html Chris Lattner – LLVM Pass Manager Compiler is organized as a series of ‘passes’: Each pass is one analysis or transformation Four types of Pass: ModulePass: general interprocedural pass CallGraphSCCPass: bottom-up on the call graph FunctionPass: process a function at a time BasicBlockPass: process a basic block at a time Constraints imposed (e.g. FunctionPass): FunctionPass can only look at “current function” Cannot maintain state across functions See also: docs/WritingAnLLVMPass.html Chris Lattner – Services provided by PassManager Optimization of pass execution: Process a function at a time instead of a pass at a time Example: If F, G, H are three functions in input pgm: “FFFFGGGGHHHH” not “FGHFGHFGHFGH” Process functions in parallel on an SMP (future work) Declarative dependency management: Automatically fulfill and manage analysis pass lifetimes Share analyses between passes when safe: e.g. “DominatorSet live unless pass modifies CFG” Avoid boilerplate for traversal of program See also: docs/WritingAnLLVMPass.html Chris Lattner – Pass Manager + Arg Promotion #1/2 Arg Promotion is a CallGraphSCCPass: Naturally operates bottom-up on the CallGraph Bubble pointers from callees out to callers 24: #include "llvm/CallGraphSCCPass.h" 47: struct SimpleArgPromotion : public CallGraphSCCPass { Arg Promotion requires AliasAnalysis info To prove safety of transformation Works with any alias analysis algorithm though 48: virtual void getAnalysisUsage(AnalysisUsage &AU) AU.addRequired<AliasAnalysis>(); // Get AU.addRequired<TargetData>(); // Get CallGraphSCCPass::getAnalysisUsage(AU); // Get } const { aliases data layout CallGraph Chris Lattner – Pass Manager + Arg Promotion #2/2 Finally, implement runOnSCC (line 65): bool SimpleArgPromotion:: runOnSCC(const std::vector<CallGraphNode*> &SCC) { bool Changed = false, LocalChange; do { // Iterate until we stop promoting from this SCC. LocalChange = false; // Attempt to promote arguments from all functions in this SCC. for (unsigned i = 0, e = SCC.size(); i != e; ++i) LocalChange |= PromoteArguments(SCC[i]); Changed |= LocalChange; // Remember that we changed something. } while (LocalChange); return Changed; // Passes return true if something changed. } static int foo(int ***P) { return ***P; } static int foo(int P_val_val_val) { return P_val_val_val; } Chris Lattner – LLVM Dataflow Analysis LLVM IR is in SSA form: use-def and def-use chains are always available All objects have user/use info, even functions Control Flow Graph is always available: Exposed as BasicBlock predecessor/successor lists Many generic graph algorithms usable with the CFG Higher-level info implemented as passes: Dominators, CallGraph, induction vars, aliasing, GVN, … See also: docs/ProgrammersManual.html Chris Lattner – Arg Promotion: safety check #1/4 #1: Function must be “internal” (aka “static”) 88: if (!F || !F->hasInternalLinkage()) return false; #2: Make sure address of F is not taken In LLVM, check that there are only direct calls using F 99: for (Value::use_iterator UI = F->use_begin(); UI != F->use_end(); ++UI) { CallSite CS = CallSite::get(*UI); if (!CS.getInstruction()) // "Taking the address" of F. return false; #3: Check to see if any args are promotable: 114: for (unsigned i = 0; i != PointerArgs.size(); ++i) if (!isSafeToPromoteArgument(PointerArgs[i])) PointerArgs.erase(PointerArgs.begin()+i); if (PointerArgs.empty()) return false; // no args promotable Chris Lattner – Arg Promotion: safety check #2/4 #4: Argument pointer can only be loaded from: No stores through argument pointer allowed! // Loop over all uses of the argument (use-def chains). 138: for (Value::use_iterator UI = Arg->use_begin(); UI != Arg->use_end(); ++UI) { // If the user is a load: if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) { // Don't modify volatile loads. if (LI->isVolatile()) return false; Loads.push_back(LI); } else { return false; // Not a load. } } Chris Lattner – Arg Promotion: safety check #3/4 #5: Value of “*P” must not change in the BB We move load out to the caller, value cannot change! … … load P … Modifie s “*P”? // Get AliasAnalysis implementation from the pass manager. 156: AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); // Ensure *P is not modified from start of block to load 169: if (AA.canInstructionRangeModify(BB->front(), *Load, Arg, LoadSize)) return false; // Pointer is invalidated! See also: docs/AliasAnalysis.html Chris Lattner – Arg Promotion: safety check #4/4 #6: “*P” cannot change from Fn entry to BB Entry Modifie s “*P”? Modifie s “*P”? Entry load P load P 175: for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) // Loop over predecessors of BB. // Check each block from BB to entry (DF search on inverse graph). for (idf_iterator<BasicBlock*> I = idf_begin(*PI); I != idf_end(*PI); ++I) // Might *P be modified in this basic block? if (AA.canBasicBlockModify(**I, Arg, LoadSize)) return false; Chris Lattner – Arg Promotion: xform outline #1/4 #1: Make prototype with new arg types: #197 Basically just replaces ‘int*’ with ‘int’ in prototype #2: Create function with new prototype: 214: Function *NF = new Function(NFTy, F->getLinkage(), F->getName()); F->getParent()->getFunctionList().insert(F, NF); #3: Change all callers of F to call NF: // If there are uses of F, then calls to it remain. 221: while (!F->use_empty()) { // Get a caller of F. CallSite CS = CallSite::get(F->use_back()); Chris Lattner – Arg Promotion: xform outline #2/4 #4: For each caller, add loads, determine args Loop over the args, inserting the loads in the caller 220: std::vector<Value*> Args; 226: CallSite::arg_iterator AI = CS.arg_begin(); for (Function::aiterator I = F->abegin(); I != F->aend(); ++I, ++AI) if (!ArgsToPromote.count(I)) // Unmodified argument. Args.push_back(*AI); else { // Insert the load before the call. LoadInst *LI = new LoadInst(*AI, (*AI)->getName()+".val", Call); // Insertion point Args.push_back(LI); } Chris Lattner – Arg Promotion: xform outline #3/4 #5: Replace the call site of F with call of NF // Create the call to NF with the adjusted arguments. 242: Instruction *New = new CallInst(NF, Args, "", Call); // If the return value of the old call was used, use the retval of the new call. if (!Call->use_empty()) Call->replaceAllUsesWith(New); // Finally, remove the old call from the program, reducing the use-count of F. Call->getParent()->getInstList().erase(Call); #6: Move code from old function to new Fn 259: NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); Chris Lattner – Arg Promotion: xform outline #4/4 #7: Change users of F’s arguments to use NF’s 264: for (Function::aiterator I = F->abegin(), I2 = NF->abegin(); I != F->aend(); ++I, ++I2) if (!ArgsToPromote.count(I)) { // Not promoting this arg? I->replaceAllUsesWith(I2); // Use new arg, not old arg. } else { while (!I->use_empty()) { // Only users can be loads. LoadInst *LI = cast<LoadInst>(I->use_back()); LI->replaceAllUsesWith(I2); LI->getParent()->getInstList().erase(LI); } } #8: Delete old function: 286: F->getParent()->getFunctionList().erase(F); Chris Lattner – Tutorial Overview Introduction to the running example LLVM C/C++ Compiler Overview High-level view of an example LLVM compiler The LLVM Virtual Instruction Set IR overview and type-system LLVM C++ IR and important API’s Basics, PassManager, dataflow, ArgPromotion Important LLVM Tools opt, code generator, JIT, test suite, bugpoint Example applications of LLVM Chris Lattner – LLVM tools: two flavors “Primitive” tools: do a single job llvm-as: Convert from .ll (text) to .bc (binary) llvm-dis: Convert from .bc (binary) to .ll (text) llvm-link: Link multiple .bc files together llvm-prof: Print profile output to human readers llvmc: Configurable compiler driver Aggregate tools: pull in multiple features gccas/gccld: Compile/link-time optimizers for C/C++ FE bugpoint: automatic compiler debugger llvm-gcc/llvm-g++: C/C++ compilers See also: docs/CommandGuide/ Chris Lattner – opt tool: 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: 61: RegisterOpt<SimpleArgPromotion> X("simpleargpromotion", "Promote 'by reference' arguments to 'by value'"); From this, they are exposed through opt: > opt -load libsimpleargpromote.so –help ... -sccp - Sparse Conditional Constant Propagation -simpleargpromotion - Promote 'by reference' arguments to 'by -simplifycfg - Simplify the CFG ... Chris Lattner – Running Arg Promotion with opt Basic execution with ‘opt’: opt -simpleargpromotion in.bc -o out.bc Load .bc file, run pass, write out results Use “-load filename.so” if compiled into a library P...
View Full Document

  • Fall '15
  • Cindy Rubio
  • Software engineering, Compiler optimization, code generation, LLVM, Chris Lattner

{[ snackBarMessage ]}

What students are saying

  • Left Quote Icon

    As a current student on this bumpy collegiate pathway, I stumbled upon Course Hero, where I can find study resources for nearly all my courses, get online help from tutors 24/7, and even share my old projects, papers, and lecture notes with other students.

    Student Picture

    Kiran Temple University Fox School of Business ‘17, Course Hero Intern

  • Left Quote Icon

    I cannot even describe how much Course Hero helped me this summer. It’s truly become something I can always rely on and help me. In the end, I was not only able to survive summer classes, but I was able to thrive thanks to Course Hero.

    Student Picture

    Dana University of Pennsylvania ‘17, Course Hero Intern

  • Left Quote Icon

    The ability to access any university’s resources through Course Hero proved invaluable in my case. I was behind on Tulane coursework and actually used UCLA’s materials to help me move forward and get everything together on time.

    Student Picture

    Jill Tulane University ‘16, Course Hero Intern