Skip to content

LLVM编译器

LLVM IR

编译器的中间表示 串联起编译器内各层级和模块 (intermediate representation)

为什么需要中间表示

抽象与语义

需要进行抽象,抛弃掉细枝末节帮助着眼于主要矛盾

使用抽象而产生的问题秒速称为模型,模型能够带给我们清晰的语义,通过模型和语义我们才能够进行精确的严谨推理。编译器需要清晰的语义来证明代码转换的正确性。

正确与优化

首要任务是要保证转化的正确性,优化是次要的考虑。(不正确的良好优化没有意义) 生成中可能会违反语义,但是每次转换遍历应该保证原子性,也就说之内可能不完全遵守。每次转换后需要进行验证来保证正确性。

递降和递升

递降后边的转换更具有结构劣势,具有的信息过于散缺乏高层次信息。 本质性问题是强耦合,在解决复杂问题时应尝试解耦。

效率工具

进行高级抽象带来的开发效率是显而易见的,而且这种取舍是可以接受的。 高级抽象带来的不一定是最高的效率,最高效的代码可能是通过汇编语言操作寄存器而来的。 通过统一的语言描述任务,再通过执行引擎执行,再到具体的操作调度,也可以看成一种编译。 (可能这个地方有点像解释器) 编译器要对中间环节进行一系列变换来链接不同层次的抽象。

中间表示的形态和兼容性

主要有三种形态

用于高效分析和变换的内存表示 用于存储和交换的字节码 用于阅读和纠错的文本表示

不同的需求需要不同的表示,无关对错只是角度不同而已。

中间表示的设计概念

希望和要求:

中间表示的操作具有清晰明确的语义 操作能够正交,有助于定义标准形态以减少变换考虑的情况 避免出现重复信息 尽可能的保持高层次信息 其他

反例:

对特殊功能模块,破坏了中间表示的正交性 SPIR-V中编译单元声明了所需的硬件能力,但是通过分析其实可以得到,不过声明带来的好处就是能够加速了实际的运行 对已有的低层次语言,需要对其进行提升,例如自动向量化

很多目标是相互冲突的,如何进行特定的优化是困难的,对编译器解绑来针对特定领域进行优化是能够提升效率的。(顺便提一句这样是会增加工程量的)

三种抽象表示

LLVM IR

2003 编译器解绑与模块化的实践

控制流 基础块 静态单赋值

是一种完备的表示 通过库的形式进行组织