LLVM代码研读(3) --- LLVM后端(1): 概述

来源:互联网 发布:网络叫车 编辑:程序博客网 时间:2024/05/28 15:26

前言LLVM后端主要涉及IR语言的优化及优化算法和平台相关代码的生成;主要涉及从IR代码到系统代码的主要部分;这部分预计会分以下几个章节:

  • LLVM后端概述:LLVM后端的一些基本理论知识
  • 后端文件组织形式:相关源文件和目标文件构成
  • 后端相关知识:主要讲解PassTableGen,因为IR过于庞大,暂时先省略
  • LLVM平台无关代码生成器:
  • 编写完整后端代码的大致过程:
  • MCJIT的设计与实现:
  • 交叉平台编译:

因为本人能力有限,很多东西也还在学习中。虽然还算努力,但无奈头脑愚钝,错误之处在所难免。如果有错误之处,务必指正,小弟必会虚心学习。

参考文档:http://llvm.org/docs/WritingAnLLVMBackend.html

http://llvm.org/docs/TableGen/index.html

LLVM涉及的其他方面:PassTableGen文件、IR

  1. LLVM后端概述

编译器前端产生IR指令(如clang),优化器通过在IR指令上完成必要的优化。后端必须将这些与平台无关的IR指令转换成具体设备相关的指令。

(该图截自《Getting Started with LLVM Core Libraries P134)其中:

  • 白色框表示外部的用于改善转换效果的优化Pass(趟)
  • 灰色框称之为超级趟(Superpasses),不同于白色盒子,他是由一些列的小趟(Pass)构成

有以上图示,参考编译原理,后端分为以下几个过程:

  • 指令选择(InstructionSelection):

指令选择将内存中的设备无关的IR指令转换成设备相关的DAGDirected Acycle GraphSelectionDAG)节点。在内部,这一阶段转换三地址结构的IRDAG。每个BasicBlock对应一个DAG,即所有的BasicBlock对应不同的DAG。使用DAG算法是对允许代码生成器使用树模式匹配(tree-based pattern-matching)的指令选择很重要,并不仅仅是基于树。在这个阶段完成后,所有的LLVM IRDAG节点全部转换成目标节点,也就是,代表及其指令的节点而不是LLVM IR指令。即输出为:SelectionDAG,以下是指令选择主要过程:

指令选择主要包括以下过程:

    • Build initial DAG:该过程只是将LLVM IR指令简单的转换成不合法的SelectionDAG
    • Optimize SelectionDAG:优化SelectionDAG,识别目标平台支持的元指令
    • Legalize SelectionDAG Types:类型合法化,消除不支持的类型
    • Optimize SelectionDAG:清楚类型合法化后的冗余
    • Legalize SelectionDAG Ops:操作合法化
    • Optimize SelectionDAG:消除效率低下的操作数
    • 转换设备无关的DAG到目标DAG

指令选择将编译器的IR指令映射到目标的ISA指令,实际就是模式匹配问题(Pattern-matching)。指令选择有两种不同的算法:基于树模式匹配基于窥孔优化。前一种方法依赖于编译器IR和目标ISA的一种高层次的树表示方法,后一种将IR转换成底层线性IR并对后者进行系统的优化。

  • 指令调度(InstructionScheduling):

为了尽可能的利用指令级的并行操作,即多数情况下,指令的执行顺序会影响程序的执行效率,所有有指令调度。因为,IR指令是假定寄存器个数不受限制(即拥有无穷多的虚拟寄存器),因此指令调度在寄存器分配前后会被分成两个部分:前寄存器申请调度(Pre-register Allocation Scheduling)和后寄存器申请调度(Post-registerAllocation(RA) Scheduling);

指令调度主流技术使用的是一种贪婪启发式算法,称之为表调度。

  • 寄存器分配(Registerallocation):

寄存器分配将输入的任意数目的寄存器重新分配为符合硬件要求的有限个数寄存器。多数编译器寄存器分配的主要算法有图着色算法。

LLVM根据不同的选项有4种不同的寄存器分配算法:

    • Pbqp
    • Greedy:贪心算法。
    • Basic
    • Fast
  • 代码发行(Codeemission

MachineInstr描述的指令转换成MCInst,并生成:汇编代码或二进制代码

         后端使用的工具:

  • llcllcLLVM输入(汇编格式的LL代码或二进制的BC代码)自动转换成特定架构的编译代码,如果没有指定任何架构,则转换成默认本地汇编。可以使用-march指定要转换成的平台。llc同时可以使用-reg alloc指定可以使用的寄存器分配算法;可以使用-version获得后端所支持的CPU种类:

具体可以支持的CPU是在创建LLVM时指定的。

  • opt:代码优化,对IR代码进行优化

(稍后再更新。。。)