7 LLVM-IR

7 LLVM-IR

在之前 LLVM 是 Low-Level Virtual Machine 的缩写,然后发展到现在,已经脱离的虚拟机的概念,因此 LLVM 不再是缩写,而是这个项目就叫 LLVM。

LLVM 不是一个编译器,而是编译器的基础设施,当写一个编译器时,可以在 LLVM 上进行开发,而不是从头开始。

image-20221222200155928

image-20221222200709146

广义的 LLVM 是包含前端的,如 Clang 就是 LLVM 的子项目,但最核心的 LLVM 是注重优化和后端的。

image-20221222201302601

中间表示是强类型的

例子——没有函数体,只有函数声明

image-20221222202516690

0 级优化

image-20221222202510842

@开头表示是全局变量/函数,%表示局部变量,align 是 4 字节对齐。

%8 的类型起始是 i1,因为布尔值一个 bit 就行,但返回值是 i32,因此要进行拓展。

LLVM 中要求 SSA 静态单赋值,即每个寄存器/变量只能被赋值一次,如上面的 %6 和 %7,再执行 %6 和 7 的操作后,不能把结果再存储到 %6 中

1 级优化

1 级优化-O1,其中 -g0 是指不输出调试信息,可以看到优化后 main 函数的参数被优化掉了,因为从来没有使用过;内存操作[上图的 store]被转换成虚拟寄存器操作[如%6,%7]:

image-20221222202958544

image-20221222203308753

SSA 在分支中会有点问题,左边的代码转换成中间的 IR 后,会出现不知道使用哪个 y 的情况:一个解决的办法是使用 Φ 函数,根据控制流来决定;也可以通过存到同一块内存来解决

例子——有函数体——分支结构

image-20221222204823614

图被称为 Control Flow Graph (CFG)

0 级优化

image-20221222204925688

通过把值都存储到 %2 来解决分支问题

1 级优化

image-20221222204939222

优化后就是使用寄存器,那么就不能用相同内存的方式来存储了,而是使用了 phi 函数来决定分支:如果是从 %3 的分支来的,那么就返回 %6 的值;如果是从 %1 的控制块来的,那就返回 1

例子——有函数体——循环结构

0 级优化

image-20221222210011904

这里是 %8 = icmp sle i32 %6,%7 是比较 i 是不是小于等于 val

1 级优化

image-20221222210059615

这里是 %2 = icmp slt i32 %0,2 是比较 val 是不是大于 i=2

其中 %6 是在选择 i 取哪个值,%7 是在选择 tmep 取哪个值,%8 %9 分别为修改后的 i 和 temp

?不能重复赋值

  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
  • Copyrights © 2022-2024 zzb
  • RZ
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信