Engineering a Compiler: 5.1/5.2 Graphical IRs

业余民科学习者阅读笔记,垃圾内容

在《PLP: 4.2/4.3 Attribute Gramma阅读笔记3》中提到AST在整个编译过程中并不是必须的,同理IR也并不是必须的(AST本来就是IR的一种)。源码被compiler部分模块处理后得到IR,IR以另外一种形式保存了源码的内容,有时可能需要symbol table或者其它数据结构辅助。IR作为抽象出来的一个layer,主要目的是进行target无关的优化和分析。

As the compiler derives knowledge about the code it compiles, it must convey that information from one pass to another. Thus, the compiler needs a representation for all of the facts that it derives about the program. - 《Engineering a Compiler》

IR可以从结构上分为如下三种:

  • Graphical IRs,对应的算法主要用于处理nodes, edges, lists, trees。
  • Linear IRs,类似于一些抽象机器的伪码。对应的算法主要是迭代地处理这些线性表示。
  • Hybrid IRs,结合了前两者,使用Graphical IRs来表示基本块间的数据流,使用Linear IRs表示底层的基本块内部的细节。

其实比较经典的compiler都是Hybrid IRs,例如llvm。另外也通过抽象层次的高低来对IR进行分类。

图形IR

分类

  • Syntax-Related Trees
    - Parse Tree
    - AST
    - DAG
  • Graphs
    - CFG
    - Dependence Graph
    - Call Graph

我曾经做过的基于IR上的工作大致可以分为如下几个部分。

我曾经接触到的IR形式

从代码中学习API使用

这里我需要处理的IR是AST,遍历AST收集函数调用和if-then-else。如果某个API的调用很频繁,那我们就对这些数据进行聚类,得到一些常见的使用模式。例如文件打开操作和关闭,我们对内嵌着分支语句的序列进行聚类然后得到一些API的常见使用模式。
聚类

code intelligence

这里我处理的IR也是AST,这里只需要获取某个点的definition在哪个位置?或者遍历AST得到symbol信息从而能够提供代码文件的outline信息,或者是得到reference信息。

clang static analyzer

这里我处理的IR是一个Hybrid IR,只是这里hybrid的是CFG+AST+Call Graph。然后clang static analyzer作为一个executor,依次解释执行CFG基本块内部的AST语句。

Call Graph & Inheritance Graph

这里处理的IR依然是AST,同样是遍历AST收集相关信息。

moses

在moses中我要遍历AST生成线性IR,moses抄了llvm3.3,所以也是CFG+linear IR

对于DAG,可以用来揭示依赖关系,而moses只是生成了线性IR,并没有生成SSA,更没有后面的instruction select,所以并没有涉及到DAG的工作。

Parse Tree

Parse Tree可以看做parser生成的结果,parse tree“再现”了文法符号推导的过程,所以也=更贴近源码。但是现在的parser都是一步生成出AST,而将源码相关的内容嵌在AST中,因为保留parse tree并没有特别大的必要,除非一些使用场景需要parse tree中的内容。

AST

而更通用的Tree型IR是AST,再剥去了语言相关的一些细节后,AST更精简的展示了程序的结构。但是AST仍然是贴近源码的一种IR形式,所以更多的用在与源码相关的场景中,例如editor。

DAG

DAG通常不是主力IR,主要用做补充。我们可以用DAG来揭示,代码中可能的重复的计算,但是在构造DAG的时候,必须能够证明 a ∗ 2 a * 2 a2的值不会改变。
DAG
其实除此之外,DAG还有更重要的作用,也就是做指令重排。

CFG

CFG是compiler中间阶段最重要的结构之一。后端的许多操作都依赖与CFG,像是instruction scheduling,register allocation。

Compilers typically use a CFG in conjunction with another IR. The CFG represents the relationship among blocks, while the operations inside a block are represented with another IR, such as an expression-level AST, a DAG, or one of the linear IRS. The resulting combination is a hybrid IR.

Dependence Graph

Dependence Graph直观地展示IR中的依赖关系,具体细节可以参照PLP中的Depedence Analysis。

Call Graph

Call Graph主要用来做过程间的分析和优化,但是在构造call graph的过程中可能需要类型信息来减少callee candidates,例如C++中的虚函数调用。

Object-oriented programs with inheritance routinely create ambiguous procedure calls that can only be resolved with additional type information. - 《Engineering a Compiler》

但是有些type information只能在runtime中得到,此时构建call graph可能会有很大的开销。

在本节最后,作者说清楚了Graphical IRs的主要作用。

Graphical IRs encode relationship that may be difficult to represent in a linear IR. A graphical IR can provide the compiler with an efficient way to move between logically connected points in the program.

读书的重点在于思考和理解,否则无疑是向脑子里倾倒垃圾

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值