LLVM笔记1

参考:https://www.bilibili.com/video/BV1D84y1y73v/?share_source=copy_web&vd_source=fc187607fc6ec6bbd2c74a3d0d7484cf

文章目录

  • 零、入门名词解释
    • 1. Compiler & Interpreter
    • 2. AOT静态编译和JIT动态解释的编译方式
    • 3. Pass
    • 4. Intermediate Representations中间表达
    • 5. 编译器基本构成
  • 一、GCC编译流程
  • 二、LLVM编译技术
    • 1. LLVM设计架构
    • 2. LLVM IR
      • 2.1 IR语法
      • 2.2 IR三种表达形式
      • 2.3 IR内存模型
    • 3. LLVM前端
      • 3.1 词法分析
      • 3.2 语法分析
      • 3.3 语义分析
    • 4. LLVM优化
      • 4.1 发现Pass
      • 4.2 Pass依赖
      • 4.3 Pass API
    • 5. LLVM后端
    • 5.1 指令选择
    • 5.2 指令调度
    • 5.3 寄存器分配
    • 5.4 指令调度
    • 5.5 代码输出
  • 发展


零、入门名词解释

1. Compiler & Interpreter

将程序从高级语言翻译到机器语言,得到一个可运行的文件。
在这里插入图片描述
在这里插入图片描述

2. AOT静态编译和JIT动态解释的编译方式

在这里插入图片描述

3. Pass

对源程序的一次完整扫描或处理。从高级语言到低级语言或者IR会经过几次Pass。比如下图第一个Pass是词法分析、语法分析、语义分析(图片里中间代码生成拼错了)。
在这里插入图片描述

4. Intermediate Representations中间表达

可以是数据结构或者定义好的代码,能让编译器或者虚拟机表达源码就行。

5. 编译器基本构成

  • 前端:词法语法分析,将源代码转化为抽象语法树。
  • 优化:对前端得到的IR优化,使得更高效。
  • 后端:将优化的IR转化为针对各自平台的机器代码。比如X86、ARM、GPU上执行的机器码是不同的。
    在这里插入图片描述

一、GCC编译流程

  • 预处理(前端):读入源代码,响应预处理指令和替换宏定义,删除程序中的注释和多余空白符。会把引用的头文件和自己写的hello.c文件都放在hello.i文件中。
  • 编译(优化):语法分析和词法分析,以及大量优化。hello.s中都是汇编指令。
  • 汇编(后端):则是将汇编指令转为机器语言。
  • 链接(后端):链接程序用到的目标文件、各种依赖的库文件,生成可执行文件,以二进制形式存储在磁盘中。
    在这里插入图片描述

二、LLVM编译技术

1. LLVM设计架构

利用IR做中转,将前端和优化和后端分离开。不同于GCC的前后端没有解耦,LLVM增加一种新的语言时只用实现一个新的编译前端,优化和后端都能复用。

clang -E -c hello.c -o hello.i
clang -emit-llvm hello.c -S -o hello.ll #这里是导出为IR模式
llc hello.ll -o hello.s #这里导出的是汇编语言了
clang hello.s -o hello #这里得到可执行的二进制文件

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2. LLVM IR

2.1 IR语法

;表示注释
@全局变量开头
%局部变量开头
alloca在函数栈中分配内存
store写入
load读取
i32 32位4字节
align字节对齐(计算机中内存大小的基本单位是字节(byte),理论上来讲,可以从任意地址访问某种基本数据类型,但是实际上,计算机并非逐字节大小读写内存,而是以2,4,或8的 倍数的字节块来读写内存,如此一来就会对基本数据类型的合法地址作出一些限制,即它的地址必须是2,4或8的倍数。那么就要求各种数据类型按照一定的规则在空间上排列,这就是对齐。)
在这里插入图片描述

  • IR假设寄存器数量无限。
  • 指令都是三地址形式,操作码OP 第一操作数地址A1 第二操作数地址A2 结果地址A3
  • 不使用固定的命名寄存器,都是用%字符命名临时寄存器。

2.2 IR三种表达形式

这三种中间格式是完全等价的:

  • 在内存中的编译中间语言(无法通过文件的形式得到的指令类等)
  • 在硬盘上存储的二进制中间语言( 格式为.bc )
  • 人类可读的代码语言(格式为.Il )

2.3 IR内存模型

如果在编译器的优化层对LLVM的IR进行操作,写一个定制的优化pass,就需要了解LLVM IR内存模型。

● LLVM IR文件的基本单位称为module;
● 一个module中可以拥有多个顶层实体,比如function和global variable;
● 一个function define中至少有一个basicblock(就是花括号);
● 每个basicblock中有若干instruction ,并且都以terminator instruction(写作ret,就是return的意思)结尾。

void test( int a, int b){int c=a*b + 100;
}
1 ; Function Attrs: noinline nounwind optnone ssp uwtable
2 define void @test(i32, i32) #2 { ;有个全局函数@test (a,b)
3 %3 = alloca 132,align 4 ;局部变量C
4 %4 = alloca i32,align 4 ;局部变量d
5 %5 = alloca i32, align 4 ;局部变量e
6 store i32 %0, i32*%3,align 4 ;%0赋值给3C=a
7 store i32%1,i32*%4,align 4 ;%1赋值给%4d=b
8 %6=load i32, i32*%3, align 4 ;读取%3 ,赋值给%6就是函数参数a
9 %7=load i32, i32* %4 , align 4 ;读取%4 ,赋值给%7就是函数参数b
10 %8=mul nsw i32%6, %7 ;a*b
11 %9=add nsw i32%8, 100 ;a*b+100
12 store i32%9, i32*%5, align 4 ;参数%9赋值给%5 e ===>就是转换前函数写的int c变量
ret void

3. LLVM前端

3.1 词法分析

前端的第一个步骤处理源代码的文本输入,将语言结构分解为一组单词和标记,去除注释、空白、制表符等。每个单词或者标记必须属于语言子集,语言的保留字被变换为编译器内部表示

3.2 语法分析

分组标记以形成表达式、语句、函数体等。检查-组标记是否有意义 ,考虑代码物理布局,未分析代码的意思,就像英语中的语法分析,不关心你说了什么,只考虑句子是否正确,并输出语法树( AST )。
在这里插入图片描述

3.3 语义分析

借助符号表检验代码没有违背语言类型系统。符号表存储标识符和其各自的类型之间的映射,以及其它内容。类型检查的一-种直觉的方法是,在解析之后,遍历AST的同时从符号表收集关于类型的信息。

4. LLVM优化

4.1 发现Pass

优化通常由分析Pass和转换Pass组成:

  • 分析Pass :负责发掘性质和优化机会;
  • 转换Pass :生成必需的数据结构,后续为后者所用;

4.2 Pass依赖

在转换Pass和分析Pass之间,有两种主要的依赖类型:

  • 显式依赖:转换Pass需要一种分析,则Pass管理器自动地安排它所依赖的分析Pass在它之前运行;
DominatorTree &DT = getAnalysis<DominatorTree>(Func);
  • 隐式依赖:转换或者分析Pass要求IR代码运用特定表达式。需要手动地以正确的顺序把这个Pass加到Pass队列中,通过命令行工具( clang或者opt )或者Pass管理器。

4.3 Pass API

Pass类是实现优化的主要资源。然而,我们从不直接使用它,而是通过清楚的子类使用它。当实现一个Pass时,你应该选择适合你的Pass的最佳粒度,适合此粒度的最佳子类,例如基于函数、模块、循环、强联通区域,等等。常见的这些子类如下:
● ModulePass (一个模块)
● FunctionPass(一个函数)
● BasicBlockPass (某几条指令)

5. LLVM后端

也是由多个Pass链接,分为必要Pass和非必要Pass,下面介绍一些必要Pass

5.1 指令选择

  • 内存中LLVM IR变换为目标特定SelectionDAG节点;
  • DAG有向无环图,IR变成图后表示单一的一个计算节点,图的节点是具体执行的指令,边是数据流依赖关系。。每个DAG能够表示单一基本块的计算。

5.2 指令调度

第1次指令调度( Instruction Scheduling ) ,也称为前寄存器分配(RA)调度。
●对指令排序,同时尝试发现尽可能多的指令层次的并行;
●然后指令被变换为MachineInstr三地址表示。

5.3 寄存器分配

LLVM IR寄存器集是无限的,这个性质一直保持着,直到寄存器分配( Register Allocation )
●寄存器分配将无限的虚拟寄存器引用转换为有限的目标特定的寄存器集;
●寄存器不够时挤出( spill )到内存。

5.4 指令调度

第2次指令调度,也称为后寄存器分配(RA)调度。
●此时可获得真实的寄存器信息,某些类型寄存器存在延迟,它们可被用以改进指令顺序。

5.5 代码输出

  • 代码输出阶段将指令从MachineInstr表示变换为MCInst实例;
  • 新的表示更适合汇编器和链接器,可以输出汇编代码或者输出二进制块特定目标代码格式。

发展

XLA (加速线性代数)是一种针对特定领域的线性代数编译器。

Julia面向科学计算的高性能动态编程语言,使用LLVM JIT编译。LLVM JIT编译器通常不断地分析正在执行的代码,并且识别代码的一部分 ,使得从编译中获得的性能加速超过编译该代码的性能开销。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/53135.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AirLink 101 Wireless N 150 PCI Adapter驱动和管理软件

从光盘里拷出来的&#xff0c;界面比较复古&#xff0c;实际功能聊胜于无 链接&#xff1a;https://pan.baidu.com/s/1clUcp7QsF8QMWdGoZkc_dQ?pwdmkra 提取码&#xff1a;mkra

开放式耳机怎么样?值得入手的开放式耳机推荐

​蓝牙耳机是现代音乐爱好者不可或缺的装备&#xff0c;近几年热门的开放式耳机似乎更受大家热爱&#xff0c;它们能够带来更加清晰、自然的声音体验&#xff0c;同时还能让你在听音乐时保持一定的舒适度。那么&#xff0c;都有哪些好用的开放式耳机呢&#xff1f;希望通过今天…

记录--基于css3写出的流光登录(注释超详细!)

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 完整效果 对基本的表单样式进行设置 这里设置了基本的表单样式&#xff0c;外层用了div进行包裹&#xff0c;重点是运用了两个i元素在后期通过css样式勾画出一条线没在聚焦文本框的时候线会过度成一个…

【前端】对前端小白极为友好的JS DOM入门文章

在现代web开发中&#xff0c;JavaScript (JS) 是不可或缺的一部分&#xff0c;它使我们能够为网页赋予交互性和动态性。其中&#xff0c;DOM&#xff08;文档对象模型&#xff09;技术在前端开发中起着至关重要的作用。本篇博客将带领前端初学者深入理解JavaScript DOM技术&…

【数据结构】快速排序

快速排序是一种高效的排序算法&#xff0c;其基本思想是分治法。它将一个大问题分解成若干个小问题进行解决&#xff0c;最后将这些解合并得到最终结果。 快速排序的主要思路如下&#xff1a; 选择一个基准元素&#xff1a;从待排序的数组中选择一个元素作为基准&#xff08;…

PAT 1002 A+B for Polynomials

个人学习记录&#xff0c;代码难免不尽人意 Output Specification: For each test case you should output the sum of A and B in one line, with the same format as the input. Notice that there must be NO extra space at the end of each line. Please be accurate to 1…

炼钢工艺流程(2)

1. 轧制单元 更换前后两个工作辊之间的轧制对象称为轧制单元&#xff0c;对应一个轧制计划。两个 支撑辊之间的轧制对象是由多个轧制单元组成&#xff0c;称为轧制单元组&#xff0c;对应多个轧制计 划。 轧制单元的结构 每个计划开始的部分板坯按照宽度非减的方向排列来加热轧…

RISC-V - 小记

文章目录 关于 RISC-V安装 关于 RISC-V RISC : Reduced Instruction Set Computing RISC-V(“RISC five”)的目标是成为一个通用的指令集架构(ISA) 官网&#xff1a;https://riscv.orggithub : https://github.com/riscv 教程 [完结] 循序渐进&#xff0c;学习开发一个RISC-…

35岁体能断崖,裁员热潮,焦虑倍增,你当如何应对?

小明是一个35岁的研发工程师&#xff0c;最近正面临工作压力和身体状况的双重挑战。他在一家大厂工作多年&#xff0c;但由于公司裁员的原因&#xff0c;他也成为了其中的一员。 小明虽然年龄已经不再年轻&#xff0c;但他一直以来都非常注重自己的体能状况。每天早上&#xf…

SpringBoot+AOP+Redission实战分布式锁

文章目录 前言一、Redission是什么&#xff1f;二、使用场景三、代码实战1.项目结构2.类图3.maven依赖4.yml5.config6.annotation7.aop8.model9.service 四、单元测试总结 前言 在集群环境下非单体应用存在的问题&#xff1a;JVM锁只能控制本地资源的访问&#xff0c;无法控制…

elasticSearch常见的面试题

常见的面试问题 描述使用场景 es集群架构3个节点&#xff0c;根据不同的服务创建不同的索引&#xff0c;根据日期和环境&#xff0c;平均每天递增60*2&#xff0c;大约60Gb的数据。 调优技巧 原文参考&#xff1a;干货 | BAT等一线大厂 Elasticsearch面试题解读 - 掘金 设计阶…

Linux中的firewall-cmd

2023年8月4日&#xff0c;周五上午 目录 打开端口关闭端口查看某个端口是否打开查看当前防火墙设置firewall-cmd中的服务在防火墙中什么是服务&#xff1f;为什么会有服务&#xff1f;打开或关闭服务查看某个服务是否打开firewall-cmd中的 zones查看所有可用的zones&#xff0…