实验 3 基于 LLVM 的 JIT 实现
在本实验中,我们观察、学习、理解并使用 LLVM 的 OrcJIT 架构,了解分层模块化的 JIT 实现模式,从而对 JIT 的实现方式和处理方法有一个大致的概念。学习和理解过程中,将主要以阅读代码的形式进行;使用中,将基于 OrcJIT,修改上一次实验的代码,使其具备 Lazy Compilation 和可控程度精细到 Pass 的代码优化。
这里我们的 JIT 仅包括从 LLVM IR 到可执行程序的 Just-In-Time Compilation,并不包括 AST 的解析;这和 JVM(Java Virtual Machine)、CLR(Common Language Runtime)的模式是相同的。
LLVM OrcJIT
在较新版本的 LLVM 中,OrcJIT(On-Request-Compilation JIT)作为 MCJIT 的功能扩展被引入,成为推荐使用的 JIT Engine。
OrcJIT 基于分层(Layer)化的结构,每层执行一定的任务,通过多个层的分工协作来完成整体的 JIT 任务。整体结构和每一层的行为均由用户配置。
使用的例子可以参考 Kaleidoscope 的 JIT 部分 Tutorial,由于其文档尚未完成,需要同学们直接参考其源码,阅读并理解其行为。这部分代码当中包含了相当丰富的注释,将有助于你的理解。这些源代码在你本地的 LLVM 仓库副本中也存在,推荐使用代码编辑器进行阅读。好事(没什么不对)的同学也可以去看一看施工中的 Tutorial 本体,由于完成度太低,所以如果要参考其内容,需要同学们自行斟酌。
其中 JIT Engine 的实现主要位于ChapterN/KaleidoscopeJIT.h
,建议按章节顺序逐个浏览,渐次加深理解。其中的注释十分详细,将大大有助于你的代码阅读。Chapter4
和Chapter5
的内容脱离了本次实验的要求范围,可以忽略。
除此之外,JIT 的一个常见功能是通过在线的 Profiling(即性能统计),分析出热点代码,并对其进行深度优化。这一功能在当前的 LLVM 中尚不具备,但由于 OrcJIT 的存在,这一功能的实现是可能的。你可以思考如何在 OrcJIT 的架构下,通过新 Layer 的实现和组织,完成基于 Hot Profiling 的在线优化;如果有自己的想法,请进行描述。不强制要求回答。
基于 OrcJIT 的 C1 JIT Engine 实现
本次实验将在先前直接使用 MCJIT 的 c1interpreter 基础上修改,基于 OrcJIT 完成其 JIT Engine 的实现,替代先前的简单的 MCJIT 的调用。
基础版本已经在本次实验的仓库中给出。其中的src/execution_engine.cpp
中包含了初始的实现,可以看到,这份实现是仿照 Kaleidoscope JIT Tutorial 中的Chapter1/KaleidoscopeJIT.h
进行的。你的工作是在其上进行改进,在其中加入优化功能的 Layer,并使其具备 Lazy Compilation 特性。你可以仿照 Kaleidoscope JIT Tutorial 中的Chapter3/KaleidoscopeJIT.h
完成这些功能改进。
提交内容
- 分阶段阅读 Tutorial,回答以下问题,将回答置于
<your-repo>/lab-3-answer.md
中:- 阅读
Chapter1/KaleidoscopeJIT.h
,回答问题:CompileLayer
和ObjectLayer
的功能分别是什么?- 在这个文件中,为什么只调用了
CompileLayer
的方法,而从未接触ObjectLayer
? - 在这个文件中,由哪一方法完成了 LLVM IR 到内存中可执行二进制的 JIT 编译?
- 阅读
Chapter2/KaleidoscopeJIT.h
,回答问题:- 这一实现较上一实现增加了什么功能?是由哪一 layer 完成的新增功能?
OptimizeLayer
、CompileLayer
和ObjectLayer
间是如何组织和交互的?llvm::orc::IRTransformLayer
不止可以执行优化工作,还可以实现运行期间每个函数调用的次数和时间统计。思考并简要说明方法。- 列出
OptimizeLayer
所执行的优化种类。
- 阅读
Chapter3/KaleidoscopeJIT.h
,回答问题:- 这一实现较上一实现增加了什么功能?是由哪一 layer 完成的新增功能?
- 本次的四个 layer 间是如何组织的?
- (可选)
CODLayer
是如何达成其功能的?(简单介绍函数被初次调用的流程即可)
- 阅读
- (可选)OrcJIT 的可扩展性很好。思考如何在 OrcJIT 的架构下,通过新 Layer 的实现和组织,完成基于 Hot Profiling 的在线优化,简单描述思路,不需要陈述具体细节。将你的思考也置于
<your-repo>/lab-3-answer.md
中。 - 完成
c1interpreter_jit
。- 将公共仓库中的
c1interpreter_jit
复制进你的仓库,并将你在 lab 2 中实现的c1interpreter/src/assembly_builder.cpp
替换至其中对应文件。编译并执行项目。 - 测试并改进
c1interpreter_jit/src/execution_engine.*
。- 在其中加入优化功能的 Layer;你可以选择比 KaleidoscopeJIT 更多的 optmization pass 加入其中,但请保证这些优化的时间复杂度较低(低于平方级),JIT 时通常不会接受高时间复杂度的优化。
- 使其具备 Lazy Compilation(即Compile On Demand)特性。
- 在
c1interpreter_jit/doc/jit.md
中描述你的工作;如果你的 optimization pass 较 KaleidoscopeJIT 中有区别,请对新加入的 pass 简单说明其功能。
- 将公共仓库中的