LLVM Backend Compiler TheoryCompiler Laboratory EECE6083 Stephen Comarata
LLVM Backend Compiler Theory/Compiler Laboratory EECE-6083 Stephen Comarata & Giang Ta
Code. Generator ● The LLVM backend is comprised mostly of the Code. Generator ● The Code. Generator takes in the LLVM IR and outputs machine code either in assembly or binary code for a specific target platform ● The target platform is the specific chip architecture/design and instruction set ● The Code. Generator needs to be able to generate machine code for a wide array of chip architectures, like X 86, ARM, MIPS, etc. since each has different instruction sets, registers, etc.
Code. Generator
Code. Generator The code generator is made up of 7 main steps 1. Instruction Selection 2. Scheduling and Formation 3. SSA Based Machine Code Optimizations (optional) 4. Register Allocation 5. Prolog/Epilog Code Insertion 6. Late Machine Code Optimizations 7. Code Emission
Instruction Selection ● The process of instruction selection consists of taking the LLVM IR and translate to target specific machine instructions ● For this step, the Target Description Classes need to be populated ○ The Target Description Classes allow LLVM to gain an abstract description of the targeted machine, they allow LLVM to figure out what instruction sets and registers the target machine have
Instruction Selection Target Description Classes: ● Target. Machine. Class ○ Provides virtual methods to access various get. Info methods, like get. Instr. Info and get. Register. Info ○ Designed to be specialized by a concrete target implementation, such as the X 86 Target. Machine or the ARMTarget. Machine ● Data. Layout Class ○ Required and not extensible ○ Specifies how the target lays out memory for data structures, data types, and pointer size
Instruction Selection Target Description Classes: ● Target. Register. Info Class ○ Describes the register file of the target and how registers interface ○ Physical registers are represented by small number, whereas virtual registers are larger numbers ● Target. Instr. Info Class ○ Describes the machine instructions supported by the target ○ Basically a bunch of Target. Instr. Descriptors ■ Mnemonic of the opcode, operands, registers
Target Description Classes Example Code: ARMDatalayout Class
Target Description Classes Example Code: ARMDatalayout Class
Target Description Classes Example Code: ARMBase. Register. Info
Target Description Classes Example Code: ARMBase. Instr. Info
Machine Code description classes ● Group of classes in LLVM used for presenting Machine Instructions ● Machine. Function, Machine. Basic. Block, Machine. Instr ● They are in the form of an opcode(tied to target machine) and a series of operands ● Operands of a machine instruction can be of several different types: ● a register reference ● a constant integer ● a basic block reference Build. MI is the function used for generating these forms
MI Class Hierarchy ● ● ● Machine. Basic. Block - list of machine instructions (Machine. Instr) Machine. Function - list of machine blocks (Machine. Basic. Block) Machine. Instr Bundles - pack instructions into nested groups for VLIW parallelism
Instruction Selection. DAG Creation: ● The Code. Generator in LLVM uses a Selection. DAG to translate the IR to target specific machine code ● Illegal versus legal Selection. DAG ● ● An Illegal Selection. DAG has instructions or registers that are unsupported by the target The Code. Generator First builds an Illegal Selection. DAG by transforming the LLVM IR to instruction generic instruction codes ● The Selection. DAG is optimized and eventually legalized **DAG = Directed Acyclic Graph
Instruction Selection Arithmetic Representation Selection. DAG Representation LLVM IR Representation Simplified Selection. DAG Representation
Scheduling and Formation ● Occurs after selecting instructions phase ● CPU doesn’t execute DAG, only used for representation and optimization ● Selection. DAG goes through “linearization” ● Instructions from nodes are assigned order and the DAG is completely converted into a list of Machine. Instr (class) and then it is destroyed
Register Allocation ● LLVM usually assigned physical registers numbers from 1 to 1023 ● These physical registers are mapped to Register Classes where registers in the same class are functionally equivalent and can be interchanged as needed. ● The Register Classes are defined in the Target. Register. Info of the Target Description Classes ● Virtual Registers usually have integer numbers greater than 1023 and numbers can be reused ● Register Mapping: ● Direct Mapping - where the developer must define load/store instructions which is more error prone but offers more control ● Indirect Mapping - where the developer doesn't have to define load/store instructions and LLVM handles register mapping
Register Allocation LLVM Built in register Allocators ● Fast - allocates on a basic block level, attempting to keep values in registers and reusing registers as appropriate ● Basic - Live ranges are assigned to registers one at a time in an order that is driven by heuristics ● Greedy - This is a highly tuned implementation of the Basic allocator that incorporates global live range splitting. This allocator works hard to minimize the cost of spill code ● PBQP - (Partitioned Boolean Quadratic Programming) - Constructs a PBQP problem representing the register allocation problem under consideration, solving this using a PBQP solver, and mapping the solution back to a register assignment
Prolog/Epilog code insertion ● ● In compiler design, prolog code helps setting up the stack frame Epilog code helps restore the stack frame of the calling function after being used In this stage, these code are inserted and “abstract stack location references” can be eliminated This stage is responsible for implementing optimizations like frame-pointer elimination and stack packing
Late Machine Code Optimizations ● This stage is optional ● Optimization passes and other optimizations are present in the Code. Generator ● These optimizations are very similar to those that were talked about in a previous student lecture ● Live variable analysis, which is a future student lecture topic is also used here
Code Emission ● Takes the code generator abstractions and lowers them to abstractions used by the “MC” layer ● The MC Layer is the API responsible for output file writing ● The key class for output file streaming is the MCStreamer class which is effectively an assembler API ● The assembler API interacts directly with the Machine Code Description Classes that were defined earlier to determine which format and machine code needs to be written
Implementation of a custom backend Example of a custom implementation for CJG RISC (subset 32 -bit RISC CPU). ● ● 32 individual 32 -bit registers denoted as r 0 through r 31 R 0 -r 2 are designated as special purpose registers (status register, stack pointer, program counter) 2 hardware stacks in the CJG RISC design. One stack is used for storing the PC and SR throughout calls and returns (the call stack). The other stack is used for storing variables (the data stack) 2 separate physical datapaths for accessing data and instruction memory (Harvard) https: //scholarworks. rit. edu/cgi/viewcontent. cgi? article=10699&context=theses
Define abstract target description with Table. Gen Components of the CJG backend are register information, calling convention, special operands, instruction format and complete instruction definitions. Register Information (CJGRegister. Info. td): Defines the register set of the CJG RISC as well as different register classes. This makes it easy to separate registers that may only be able to hold a specific datatype (int vs float).
Calling convention - describe the part of the ABI which controls how data moves between function calls. Definitions are in CJGCalling. Conv. td
Instruction Selection Example of a function my. Double translating from C to IR and then DAG
Scheduling (after selection. DAG)
Code Emission (with assembly writer)
Making your own backend It is possible to write your own backend for LLVM if you are using very specific chip set, architecture or machine code output This link describes what is needed to write your own LLVM backend: https: //llvm. org/docs/Writing. An. LLVMBackend. html
In Conclusion ● The LLVM Code. Generator is the portion of LLVM responsible for translating the IR to meaningful machine code for a wide array of specified chip architectures, machine codes, and chip sets. ● These “Backends” use common APIs that work to describe the target machine and its support for opcodes, register, and datatypes. ● The IR is translated to a common Selection. DAG then optimized to the specified target architecture and instruction set ● The Selection. DAG is then massaged into a linear list of instructions then optimized and processed into the specified output file type.
Questions?
References: https: //llvm. org/docs/Writing. An. LLVMBackend. html https: //www. llvm. org/docs/Code. Generator. html https: //scholarworks. rit. edu/cgi/viewcontent. cgi? article=10699&context=theses https: //llvm. org/doxygen/ARMBase. Instr. Info_8 cpp_source. html https: //llvm. org/doxygen/ARMBase. Register. Info_8 cpp_source. html https: //llvm. org/doxygen/ARMTarget. Machine_8 cpp_source. html https: //llvm. org/doxygen/ARMMCTarget. Desc_8 cpp_source. html
- Slides: 34