首页
社区
课程
招聘
LLVM入门篇剧场版
发表于: 2019-5-13 21:48 13730

LLVM入门篇剧场版

2019-5-13 21:48
13730

LLVM入门篇剧场版

LLVM的官方入门

这个PPT是位于 llvm.org/docs/LLVM Design & Overview/Introduction to the LLVM Compiler目录下,地址在这里,PPT为LLVM作者Chris LattnerACAT大会上发表的演讲PPT,Chris Lattner在本讲座上简要介绍了LLVM,讨论了使用LLVM的好处,包括更强悍的编译时和运行时性能。这个讲座虽然很高级,但是其实也适合没有深度编译器基础背景的人。当然,这篇文档是2008年的了,内容稍微有点过时,但仍不失为一篇官方版本的LLVM介绍文档。

 

 

整个PPT有55页,当然如果大家有时间,最好可以全文阅读一遍,因为真的不难,全文主要分为四个部分。

  • Intro and Motivation(LLVM介绍和动机)
  • LLVM as a C and C++ Compiler(LLVM作为C/C++的编译器)
  • Other LLVM Capabilities(LLVM还能做什么)
  • LLVM Going Forward(LLVM未来展望)

LLVM项目是什么?

  • 现代编译器技术集大成者

    • 优化器和代码生成器
    • llvm-gccclang前端
    • MSIL.NET虚拟机
  • 由众多贡献者参与的开源项目

众多行业、研究团体、个人

 

为何要造一个新的编译器?

因为现有的开源C编译器已停滞不前!(说的就是gcc!)

  • gcc的“顽疾”
    • 基于数十年前的代码生成技术
    • 没有跨文件优化和JIT等现代技术
    • 老化代码库:难以学习,难以调优,重构困难
    • 难以复用
    • 新版本越来越慢

我们想要的编译器是什么样子的?

  • 一组具有产品级质量的可复用的库:
    • 能实施各种paper里描述的最新技术
    • 能专注于编译过程
    • 能生成高性能的代码
  • 支持许多不同的语言和应用程序

LLVM的愿景和实现方法

  • 主要任务:构建一组模块化编译器组件:

    • 减少构建特定编译器的时间和成本
    • 组件在不同的编译器之间共享
    • 允许为具体任务选择正确的组件
  • 次要任务:使用这些组件构建编译器

    • 例如,一个真正优秀的C编译器
    • 例如,一个运行时特化引擎

llvm优化器的潜力

  • 生成的代码:代码运行的速度有多快?
  • 编译时间:编译过程可以提速多少?
  • 新功能:链接时优化

  • 编译时间快了四成左右!

  • 执行时间快了两成左右!

  • 新功能:链接时优化
    • 使用-O4选项优化文件(例如内联,常数折叠等)
    • 跨语言边界能力的深度优化!

针对编译器研究员

  • LLVM是写新语言的理想工具

    • 定义明确,编程简单
    • 易于重新定位现有编译器以使用LLVM后端
  • LLVM支持现代的即时优化和编译

    • 根据动态信息在运行时优化代码
    • 易于将现有字节码解释器重新定位到LLVM JIT
    • 功能非常强大,绝不仅仅是传统的“编译器”

LLVM的周边项目

lldb

lldb项目是一个使用LLVM基础架构构建的新一代的高性能调试器,在Mac OS X上作为Xcode 5的内置调试器进行发布。安装好XcodeCommand Line Tools的话,命令行是可以直接访问lldb工具的。如下所示:

$ which lldb
/usr/bin/lldb

lldb项目属于全新的基础架构,该架构支持现代的多线程程序,并且以更加高效的方式处理调试符号,模块化的组件为功能的扩展打下良好的基础。另外,由于lldb更加开放的特性(其licsence并不是GPL。GPL要求使用GPL授权的产品都必须开源),lldb几乎可以集成到任何想要集成的产品中去,而不用担心法律问题。

 

lldb会将调试信息转换为clang类型,以便它可以利用clang编译器的基础架构。这使得lldb可以在表达式中支持最新的cc++Objective-CObjective-C++语言的所有功能和运行时,而无需重新实现这些功能。此外它还利用编译器来处理函数调用表达式时的所有ABI接口,反汇编指令和提取指令细节等流程,把llvmclang的基础架构运用到了极致。

御用调试器

作为clang的“御用”调试器,lldb有以下几个优点:

  • 最新的CC++Objective-C语言支持
  • 可以声明局部变量和类型的多行表达式
  • 当需要时可以直接使用clang的JIT表达式
  • JIT不可用的时候,会直接对中间表示(IR)进行还原
基本使用方法

我们以一个案例,来粗略说明使用lldb的基本使用方法。lldbiOS的开发和逆向的工作中,已经被使用得非常广泛了,关于正向开发和逆向分析的场景中使用lldb,网络上都可以找到许多文章与教程,这里假定读者已经初步了解过lldb的基本使用方法。或者,如果您已经对gdb非常熟悉,而没有使用过lldb的话,可以在lldb-gdb命令关联页面,找到gdb下对应的命令在lldb下应当如何使用的操作说明。这样可以快速的从gdb的使用经验上,找到lldb的使用技巧。如图所示:

 

 

与GDB一样,我们可以通过命令行的方式传递参数给lldb调试器:

$ lldb mybuilder/bin/clang
Current executable set to 'mybuilder/bin/clang' (x86_64).
(lldb) break main
Breakpoint 1: where = clang`main + 48 at driver.cpp:293, address = 0x000000001000109e0

动态调试时,我们为clang二进制文件提供命令行参数。例如使用-v参数,它应该打印clang版本:

(lldb) run -v

LLDB到达我们的断点后,使用next命令逐步执行每行c++代码。与gdb一样,lldb接受任何命令的缩写,缩写可以是单个字母,也可以是命令单词的前几个字符。例如next可以用n来代替,finish可以使用finifinis代替。

 

lldb中提供的p命令还可以打印c++对象的内容。如下所示,执行下一步后,使用p命令打印ArgAllocator参数的内容:

(lldb) n
(lldb) p ArgAllocator (llvm::SpecificBumpPtrAllocator<char>) $0 = {
Allocator = { SlabSize = 4096
SizeThreshld = 4096
DefaultSlabAllocator = (Allocator = llvm::MallocAllocator @ 0x00007f85f1497f68)
Allocator = 0x0000007fffbff200 CurSlab = 0x0000000000000000
CurPtr = 0x0000000000000000 End = 0x0000000000000000
BytesAllocated = 0
}
}

动态调试完毕后,可通过q命令来退出调试:

(lldb) q
Quitting LLDB will kill one or more processes. Do you really want to proceed: [Y/n] y

lld

lldllvm项目的链接器,可以作为系统默认链接器的直接替代品,运行速度相比系统的链接器要快的多,另外还提供了针对编译器开发人员的其他有用功能。

 

lld目前按照兼容程度排序的话,最完美的是ELF(Unix),其次是PE / COFF(Windows),然后是Mach-O(macOS),最后是WebAssemblylld在不同平台上的链接实现都不一样,本文将会详述ELF(Unix)平台的实现,针对PE/COFF(windows)平台上实现的也很好,兼容Windows debug info (PDB),针对WebAssembly的实现还在开发中(大家可以看WebAssembly lld port),另外针对Mach-O平台的实现则采用了一套ATOM-based lld的架构,详情可以阅读官方文档

特点
  1. LLDGNU链接器的直接替代品,它接受与GNU相同的命令行参数和脚本文件。lld团队在与FreeBSD紧密合作的过程中,非常重视解决兼容性问题,因为希望能在未来版本的操作系统中,希望能选择LLD作为系统的默认链接器。因此,截至2017年2月,LLD已经能够链接整个FreeBSD / amd64基础系统,包括内核。通过一些团队正在制作中的补丁,它可以链接基于AMDx64架构的95%的freeBSD各种发行版。

  2. LLD运行速度非常快,在多核计算机上链接大型程序时,LLD的运行速度可以达到GNU gold链接器的两倍多。

  3. LLD支持各种CPU / ABI,包括x86-64x86x32AArch64ARMMIPS 32/64大/小端,PowerPCPowerPC 64AMDGPU。其中,x86-64的支持最为完美,完全可以用在生产环境,AArch64MIPS也不错。 x86只能说应该没问题,但尚未经过完美的测试,还有对ARM的支持,正在积极开发中。

  4. 不管lld被如何编译出来,它始终是一个交叉链接器,始终支持上述所有目标架构。lld甚至都不提供编译时的选项来启用/禁用任何一个目标架构,所以,把lld集成到你的编译工具里应该可以很放心。

  5. 可以将LLD嵌入到程序中去,以消除程序对外部链接器的依赖性。只需要构造目标文件和命令行参数,就像调用外部链接器一样,然后从代码中调用链接器的主函数lld :: elf :: link

  6. LLD很小。使用LLVM libObject库来读取目标文件,虽然这样比较显得不是很公平,但截至2017年2月,LLD / ELF仅包含21kC ++代码,而GNU gold包含198kC ++代码。这数据也足以说明LLD真的很小。

  7. LLD默认支持链接时优化(LTO)。想要使用LTO的话只需要将-flto选项传递给clang,然后clang则不会创建的本机的native对象格式,而是LLVM bitcode格式。然后LLD读取bitcode目标文件,使用LLVM编译并产生输出文件。在开启LTO时,LLD参与编译的全部过程,对整个程序进行优化。

  8. 古老的Unix系统(90年代之前甚至之前)的一些非常古老的功能已被删除。一些默认设置也已经进行了调整。例如,默认情况下,堆栈被标记为不可执行,来加强安全性。

性能表现

测试环境为一台双路E5-2680 2.8Ghz主频、20核40线程的CPU,硬盘为SSD
分别运行GNUgloder链接器和llvmlld链接器,比较项目里也包含了带不带多线程支持。

 

PS:默认是开启多线程的,如果要禁用多线程,可以在命令行里添加-no-threads 选项。

 

 

如图可见,从编译时间上来看,lld明显快于GNU链接器。

 

PS:这只是基于单个环境下的基准测试结果,根据可用内核的数量,可用内存量或磁盘延迟/吞吐量,可能会存在误差。

使用

LLD安装为ld.lld。 在Unix上,链接器由编译器程序调用,所以不能直接使用该命令,有几种方法可以强制编译器使用ld.lld而不是默认链接器。

  • 首先,最简单的方法是覆盖默认链接器。 将LLD安装到磁盘上的某个位置后,可以通过执行ln -s /path/to/ld.lld /usr/bin/ld创建符号链接,以便将/usr/bin/ld解析为LLD

  • 如果您不想更改系统设置,可以使用clang-fuse-ld选项。这样,会在构建程序时将-fuse-ld = lld设置为LDFLAGS

LLD会将其名称和版本号留在输出中的.comment部分。如果不确定是否成功使用LLD,运行readelf --string-dump .comment <output-file>并检查输出。 如果输出中包含字符串“Linker:LLD”,则表示已经成功使用LLD啦。

LLVM优化入门

llvm现在作为一个完整的编译工具链,包含了clang/clang++的前端,可优化和配置的中间代码,针对不同架构生成机器码的后端,可以作为完整的成套工具(toolchain)而使用。而且,在中间层上对代码执行的平台无关的优化,是llvm的杀手锏,也是基于llvm进行二次开发的过程中,最为关键和重要的地方。

 

opt命令详解

语法

opt [options] [filename]

简介

optoptimizer的缩写,是llvm系统的分析器和优化器,该命令接受llvm字节码作为输入,对其进行指定的分析和优化,并且输出分析或优化的结果。

 

如果命令行中没有指定输入文件,则opt命令会从标准输入中读取输入,输入可以是llvm汇编语言.ll或者llvm的字节码.bc。同理如果没有指定输出文件名的话,opt也会输出到标注输出中去。

 

opt的执行过程取决于有没有加上-analyze分析的选项:

  • 如果有-analyze分析的选项,opt会对输入文件进行各种各样的分析,并且将分析结果输出到标准输出,当然也会有一些情况下输出到标准错误输出,或者使用重定位输出到文件中。
  • 如果没有-analyze分析选项的话,opt会默认对输入文件进行优化,优化的结果取决于采用了哪个pass,可以使用-load选项来加载这些pass,也可以使用-help来查看可用的pass一览。可以看到可供选择的优化选项是非常多的。
$ ./opt -help
OVERVIEW: llvm .bc -> .bc modular optimizer and analysis printer

USAGE: opt [options] <input bitcode file>

OPTIONS:

General options:

  -O0                                               - Optimization level 0. Similar to clang -O0
  -O1                                               - Optimization level 1. Similar to clang -O1
  -O2                                               - Optimization level 2. Similar to clang -O2
  -O3                                               - Optimization level 3. Similar to clang -O3
  -Os                                               - Like -O2 with extra optimizations for size. Similar to clang -Os
  -Oz                                               - Like -Os but reduces code size further. Similar to clang -Oz
  -S                                                - Write output as LLVM assembly
  -aarch64-neon-syntax                              - Choose style of NEON code to emit from AArch64 backend:
    =generic                                        -   Emit generic NEON assembly
    =apple                                          -   Emit Apple-style NEON assembly
  -addrsig                                          - Emit an address-significance table
  -amdgpu-dump-hsa-metadata                         - Dump AMDGPU HSA Metadata
  -amdgpu-enable-merge-m0                           - Merge and hoist M0 initializations
  -amdgpu-sdwa-peephole                             - Enable SDWA peepholer
  -amdgpu-spill-sgpr-to-smem                        - Use scalar stores to spill SGPRs if supported by subtarget
  -amdgpu-verify-hsa-metadata                       - Verify AMDGPU HSA Metadata
  -amdgpu-vgpr-index-mode                           - Use GPR indexing mode instead of movrel for vector indexing
  -analyze                                          - Only perform analysis, no optimization
  -arm-add-build-attributes                         -
  -arm-implicit-it                                  - Allow conditional instructions outdside of an IT block
    =always                                         -   Accept in both ISAs, emit implicit ITs in Thumb
    =never                                          -   Warn in ARM, reject in Thumb
    =arm                                            -   Accept in ARM, reject in Thumb
    =thumb                                          -   Warn in ARM, emit implicit ITs in Thumb
  -asm-instrumentation                              - Instrumentation of inline assembly and assembly source files
    =none                                           -   no instrumentation at all
    =address                                        -   instrument instructions with memory arguments
  -asm-show-inst                                    - Emit internal instruction representation to assembly file
  -atomic-counter-update-promoted                   - Do counter update using atomic fetch add  for promoted counters only
  Optimizations available:
    -aa                                             - Function Alias Analysis Results
    -aa-eval                                        - Exhaustive Alias Analysis Precision Evaluator
    -aarch64-a57-fp-load-balancing                  - AArch64 A57 FP Load-Balancing
    -aarch64-ccmp                                   - AArch64 CCMP Pass
    -aarch64-collect-loh                            - AArch64 Collect Linker Optimization Hint (LOH)
    -aarch64-condopt                                - AArch64 CondOpt Pass
    -aarch64-copyelim                               - AArch64 redundant copy elimination pass
    -aarch64-dead-defs                              - AArch64 Dead register definitions
    -aarch64-expand-pseudo                          - AArch64 pseudo instruction expansion pass
    ...
    ...

Generic Options:

      -help                                             - Display available options (-help-hidden for more)
      -help-list                                        - Display list of available options (-help-list-hidden for more)
      -version                                          - Display the version of this program

Polly Options:
    Configure the polly loop optimizer

      -polly                                            - Enable the polly optimizer (only at -O3)
      -polly-2nd-level-tiling                           - Enable a 2nd level loop of loop tiling
      -polly-ast-print-accesses                         - Print memory access functions
      -polly-context=<isl parameter set>                - Provide additional constraints on the context parameters
      -polly-dce-precise-steps=<int>                    - The number of precise steps between two approximating iterations. (A value of -1 schedules another approximation stage before the actual dead code elimination.
      -polly-delicm-max-ops=<int>                       - Maximum number of isl operations to invest for lifetime analysis; 0=no limit
      -polly-detect-full-functions                      - Allow the detection of full functions
      -polly-dump-after                                 - Dump module after Polly transformations into a file suffixed with "-after"
      -polly-dump-after-file=<string>                   - Dump module after Polly transformations to the given file
      -polly-dump-before                                - Dump module before Polly transformations into a file suffixed with "-before"
      -polly-dump-before-file=<string>                  - Dump module before Polly transformations to the given file
      -polly-enable-simplify                            - Simplify SCoP after optimizations
      ...
      ...
选项
选项 含义
-f 启动输出二进制到命令行界面。一般情况下,opt不会将二进制直接输出来,加了-f选项之后,可将二进制输出到任意输出
-help 打印opt命令的所有选项
-o<filename> 指定输出文件
-S 输出模式从输出字节码切换为输出llvm中间代码表示(IR)
-{passname} opt命令接受多个pass参数,并且会按照pass传进来的顺序,来执行这些pass。可以使用help命令查看所有可用的pass参数
-disable-inlining 该选项可以移除pass中的内联pass
-disable-opt 只有给定-std-link-opts选项的时候,该选项才有效,并且禁用大部分pass
-strip-debug 在运行其他pass之前,优先剔除调试信息。虽然这个选项的作用跟strip是相同的,但是-strip-debug可以保证剔除在最前面运行
-verify-each 单个验证,在每个pass的后面加一个用于验证的pass。这样可以确认每个pass究竟干了什么。
-stats 打印统计信息
-time-passes 记录下每个pass执行的时间,并且输出到标准错误输出
-debug 调试输出,编译为调试模式,该选项会启用所有pass里的调试输出,也就是由宏LLVM_DEBUG()定义的输出内容,可以查看LLVM Programmer’s Manual,看#DEBUG一节来查看更多内容。
-load=<plugin> 加载动态插件。该插件需要注册新的优化或者分析选项,一旦加载成功之后,可以使用插件自己的优化或者分析选项,使用opt -load=plugin.so -help命令来查看该插件自己的选项。
-p 在每个转换之后打印模块
返回值

opt成功返回时,返回值为0。如果过程发生了错误,会输出错误,并且返回一个非零值。

llvm内置的众多Passes

Passes主要分为三类

llvm内置的pass特别多,基本上分为三类,Analysis PassesTransform PassesUtility PassesAnalysis Passes类别的Pass主要用于计算分析和输出一些IR信息,用于调试用途、可视化用途等等。Transform Passes类别的Pass就是我们的重点,可以彻底将现有的IR“更改成”另外一种形式的IR,具体如何更改,全看代码怎么写。可以在Transform Passes里调用Analysis PassesUtility Passes则完全就是因为有些Pass既不是Analysis类型,也不是Transform类型,比如某些Pass的作用就是将函数释放成字节码,或者将某个模块生成字节码本质上既不是分析也不是转化,所以就归类成Utility Passes

    Analysis Passes
        -aa-eval: Exhaustive Alias Analysis Precision Evaluator
        -basicaa: Basic Alias Analysis (stateless AA impl)
        -basiccg: Basic CallGraph Construction
        -count-aa: Count Alias Analysis Query Responses
        -da: Dependence Analysis
        -debug-aa: AA use debugger
        -domfrontier: Dominance Frontier Construction
        -domtree: Dominator Tree Construction
        -dot-callgraph: Print Call Graph to “dot” file
        -dot-cfg: Print CFG of function to “dot” file
        -dot-cfg-only: Print CFG of function to “dot” file (with no function bodies)
        -dot-dom: Print dominance tree of function to “dot” file
        -dot-dom-only: Print dominance tree of function to “dot” file (with no function bodies)
        -dot-postdom: Print postdominance tree of function to “dot” file
        -dot-postdom-only: Print postdominance tree of function to “dot” file (with no function bodies)
        -globalsmodref-aa: Simple mod/ref analysis for globals
        -instcount: Counts the various types of Instructions
        -intervals: Interval Partition Construction
        -iv-users: Induction Variable Users
        -lazy-value-info: Lazy Value Information Analysis
        -libcall-aa: LibCall Alias Analysis
        -lint: Statically lint-checks LLVM IR
        -loops: Natural Loop Information
        -memdep: Memory Dependence Analysis
        -module-debuginfo: Decodes module-level debug info
        -postdomfrontier: Post-Dominance Frontier Construction
        -postdomtree: Post-Dominator Tree Construction
        -print-alias-sets: Alias Set Printer
        -print-callgraph: Print a call graph
        -print-callgraph-sccs: Print SCCs of the Call Graph
        -print-cfg-sccs: Print SCCs of each function CFG
        -print-dom-info: Dominator Info Printer
        -print-externalfnconstants: Print external fn callsites passed constants
        -print-function: Print function to stderr
        -print-module: Print module to stderr
        -print-used-types: Find Used Types
        -regions: Detect single entry single exit regions
        -scalar-evolution: Scalar Evolution Analysis
        -scev-aa: ScalarEvolution-based Alias Analysis
        -stack-safety: Stack Safety Analysis
        -targetdata: Target Data Layout
    Transform Passes
        -adce: Aggressive Dead Code Elimination
        -always-inline: Inliner for always_inline functions
        -argpromotion: Promote ‘by reference’ arguments to scalars
        -bb-vectorize: Basic-Block Vectorization
        -block-placement: Profile Guided Basic Block Placement
        -break-crit-edges: Break critical edges in CFG
        -codegenprepare: Optimize for code generation
        -constmerge: Merge Duplicate Global Constants
        -constprop: Simple constant propagation
        -dce: Dead Code Elimination
        -deadargelim: Dead Argument Elimination
        -deadtypeelim: Dead Type Elimination
        -die: Dead Instruction Elimination
        -dse: Dead Store Elimination
        -functionattrs: Deduce function attributes
        -globaldce: Dead Global Elimination
        -globalopt: Global Variable Optimizer
        -gvn: Global Value Numbering
        -indvars: Canonicalize Induction Variables
        -inline: Function Integration/Inlining
        -instcombine: Combine redundant instructions
        -aggressive-instcombine: Combine expression patterns
        -internalize: Internalize Global Symbols
        -ipconstprop: Interprocedural constant propagation
        -ipsccp: Interprocedural Sparse Conditional Constant Propagation
        -jump-threading: Jump Threading
        -lcssa: Loop-Closed SSA Form Pass
        -licm: Loop Invariant Code Motion
        -loop-deletion: Delete dead loops
        -loop-extract: Extract loops into new functions
        -loop-extract-single: Extract at most one loop into a new function
        -loop-reduce: Loop Strength Reduction
        -loop-rotate: Rotate Loops
        -loop-simplify: Canonicalize natural loops
        -loop-unroll: Unroll loops
        -loop-unroll-and-jam: Unroll and Jam loops
        -loop-unswitch: Unswitch loops
        -loweratomic: Lower atomic intrinsics to non-atomic form
        -lowerinvoke: Lower invokes to calls, for unwindless code generators
        -lowerswitch: Lower SwitchInsts to branches
        -mem2reg: Promote Memory to Register
        -memcpyopt: MemCpy Optimization
        -mergefunc: Merge Functions
        -mergereturn: Unify function exit nodes
        -partial-inliner: Partial Inliner
        -prune-eh: Remove unused exception handling info
        -reassociate: Reassociate expressions
        -reg2mem: Demote all values to stack slots
        -sroa: Scalar Replacement of Aggregates
        -sccp: Sparse Conditional Constant Propagation
        -simplifycfg: Simplify the CFG
        -sink: Code sinking
        -strip: Strip all symbols from a module
        -strip-dead-debug-info: Strip debug info for unused symbols
        -strip-dead-prototypes: Strip Unused Function Prototypes
        -strip-debug-declare: Strip all llvm.dbg.declare intrinsics
        -strip-nondebug: Strip all symbols, except dbg symbols, from a module
        -tailcallelim: Tail Call Elimination
    Utility Passes
        -deadarghaX0r: Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)
        -extract-blocks: Extract Basic Blocks From Module (for bugpoint use)
        -instnamer: Assign names to anonymous instructions
        -verify: Module Verifier
        -view-cfg: View CFG of function
        -view-cfg-only: View CFG of function (with no function bodies)
        -view-dom: View dominance tree of function
        -view-dom-only: View dominance tree of function (with no function bodies)
        -view-postdom: View postdominance tree of function
        -view-postdom-only: View postdominance tree of function (with no function bodies)
        -transform-warning: Report missed forced transformations
Passes的源码位置

下面的目录展示了AnalysisTransformUtility的主要Passes,我们将在下一节中详细阐述。这些Passes的源代码位于llvm-8.0.0.src/lib目录下:

:~/llvm-8.0.0.src/lib$ ls
Analysis      Bitcode         DebugInfo        Fuzzer      IRReader    LLVMBuild.txt  MCA         Option      ProfileData  Target   ToolDrivers      XRay
AsmParser     CMakeLists.txt  Demangle         FuzzMutate  LineEditor  LTO            Object      OptRemarks  Support      Testing  Transforms
BinaryFormat  CodeGen         ExecutionEngine  IR          Linker      MC             ObjectYAML  Passes      TableGen     TextAPI  WindowsManifest

:~/llvm-8.0.0.src/lib$ tree -NCfhl |grep -i instcount
│   ├── [2.4K]  ./Analysis/InstCount.cpp
优化级别使用的内置Passes

上一节中我们还提到了,可以通过运行以下命令来查看每个优化水平启用的Passes的开关:

 

$ llvm-as < /dev/null | opt -O3 -disable-output -debug-pass=Arguments

PS: llvm-asllvm的编译器,它的输入端是可读的llvm汇编语言,输出llvm字节码,并将其写到文件或者标准输出中去。

 

在我的机器上,-O1跑出来的结果是:

$ ./llvm-as < /dev/null | ./opt -O1 -disable-output -debug-pass=Arguments
...
...
-targetlibinfo -tti -tbaa -scoped-noalias -assumption-cache-tracker -profile-summary-info -forceattrs -inferattrs -ipsccp -called-value-propagation -globalopt -domtree -mem2reg -deadargelim -domtree -basicaa -aa -loops -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -instcombine -simplifycfg -basiccg -globals-aa -prune-eh -always-inline -functionattrs -domtree -sroa -basicaa -aa -memoryssa -early-cse-memssa -speculative-execution -basicaa -aa -lazy-value-info -jump-threading -correlated-propagation -simplifycfg -domtree -basicaa -aa -loops -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -instcombine -libcalls-shrinkwrap -loops -branch-prob -block-freq -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -pgo-memop-opt -basicaa -aa -loops -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -tailcallelim -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa-verification -lcssa -basicaa -aa -scalar-evolution -loop-rotate -licm -loop-unswitch -simplifycfg -domtree -basicaa -aa -loops -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -instcombine -loop-simplify -lcssa-verification -lcssa -scalar-evolution -indvars -loop-idiom -loop-deletion -loop-unroll -phi-values -memdep -memcpyopt -sccp -demanded-bits -bdce -basicaa -aa -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -instcombine -lazy-value-info -jump-threading -correlated-propagation -basicaa -aa -phi-values -memdep -dse -loops -loop-simplify -lcssa-verification -lcssa -basicaa -aa -scalar-evolution -licm -postdomtree -adce -simplifycfg -domtree -basicaa -aa -loops -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -instcombine -barrier -basiccg -rpo-functionattrs -globalopt -globaldce -basiccg -globals-aa -float2int -domtree -loops -loop-simplify -lcssa-verification -lcssa -basicaa -aa -scalar-evolution -loop-rotate -loop-accesses -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -loop-distribute -branch-prob -block-freq -scalar-evolution -basicaa -aa -loop-accesses -demanded-bits -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -loop-vectorize -loop-simplify -scalar-evolution -aa -loop-accesses -loop-load-elim -basicaa -aa -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -instcombine -simplifycfg -domtree -basicaa -aa -loops -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -instcombine -loop-simplify -lcssa-verification -lcssa -scalar-evolution -loop-unroll -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -instcombine -loop-simplify -lcssa-verification -lcssa -scalar-evolution -licm -alignment-from-assumptions -strip-dead-prototypes -domtree -loops -branch-prob -block-freq -loop-simplify -lcssa-verification -lcssa -basicaa -aa -scalar-evolution -branch-prob -block-freq -loop-sink -lazy-branch-prob -lazy-block-freq -opt-remark-emitter -instsimplify -div-rem-pairs -simplifycfg -verify
...
...

 

这里面有个有趣的现象,比如像-instcombile这个优化,在命令行中出现了多次(准确来讲是八次),它是用来干嘛的呢?-instcombileinstruction combining的简称,字面意思就是指令绑定,是指将一系列指令用更加精简的效率更高的指令来代替,结果却保持相同。这个就有点俄罗斯方块的感觉,有时候这一轮优化的结果,就是下一轮优化的前提,所以可以进行多次优化。

 

这些Passes,都是llvm内置的Passes

完整版目录介绍

 

 

 

 

 

更多内容,尽在feicong@llvm知识星球!

 

 

或者欢迎加我的微信(ID:fe1c0ng)或微博(id:非虫)


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 2
支持
分享
最新回复 (10)
雪    币: 9348
活跃值: (1825)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
到此一游
2019-5-13 21:52
0
雪    币: 231
活跃值: (2631)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
中文书本 PDF或者PPT有吗?哪里买
2019-5-13 22:12
0
雪    币: 3997
活跃值: (382)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
4
火前留名
2019-5-14 00:24
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
路过留名
2019-5-14 02:00
0
雪    币: 26399
活跃值: (63262)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
6
顶一下
2019-5-14 09:09
0
雪    币: 158
活跃值: (1162)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
星球显示,9月21号就到期了,现在上车是不是有点晚
2019-5-14 09:59
0
雪    币: 120
活跃值: (1597)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
mark,大佬的好文章
2019-5-14 12:30
0
雪    币: 7324
活跃值: (4522)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
有没有小学生都能看得懂的编译原理?中国没有自己的CPU、编译器、操作系统,一切都是外国货。。。
最后于 2019-5-14 12:58 被nekaxi编辑 ,原因:
2019-5-14 12:55
0
雪    币: 73
活跃值: (923)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
舍不得花钱听课,虫哥就放出来了,太好了
2019-5-15 22:05
0
雪    币: 111
活跃值: (100)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
到期了 。。。 
2019-11-22 15:02
0
游客
登录 | 注册 方可回帖
返回
//