深度学习AI编译器-LLVM简介

2023-11-05

1、什么是LLVM

LLVM的命名最早来源于底层语言虚拟机(Low Level Virtual Machine)的缩写。它是一个用于建立编译器的基础框架,以C++编写。创建此工程的目的是对于任意的编程语言,利用该基础框架,构建一个包括编译时、链接时、执行时等的语言执行器。目前官方的LLVM只支持处理C/C++,Objective-C三种语言,当然也有一些非官方的扩展,使其支持ActionScript、Ada、D语言、Fortran、GLSL、Haskell、Java bytecode、Objective-C、Python、Ruby、Rust、Scala以及C#。

LLVM是一个编译器框架。LLVM作为编译器框架,是需要各种功能模块支撑起来的,你可以将clang和lld都看做是LLVM的组成部分,框架的意思是,你可以基于LLVM提供的功能开发自己的模块,并集成在LLVM系统上,增加它的功能,或者就单纯自己开发软件工具,而利用LLVM来支撑底层实现。LLVM由一些库和工具组成,正因为它的这种设计思想,使它可以很容易和IDE集成(因为IDE软件可以直接调用库来实现一些如静态检查这些功能),也很容易构建生成各种功能的工具(因为新的工具只需要调用需要的库就行)。在这里插入图片描述
常见的结构如下图
在这里插入图片描述

主要由三个部分组成。

前端:将高级语言例如C或者其他语言转换成LLVM定义的中间表达方式 LLVM IR。例如非常有名的clang, 就是一个转换C/C++的前端。

中端:中端主要是对LLVM IR本身进行一下优化,输入是LLVM, 输出还是LLVM, 主要是消除无用代码等工作,一般来讲这个部分是不需要动的,可以不管他。

后端:后端输入是LLVM IR, 输出是我们的机器码。我们通常说的编译器应该主要是指这个部分。大部分优化都从这个地方实现。

至此,LLVM架构的模块化应该说的比较清楚了。很大的一个特点是隔离了前后端。

如果你想支持一个新语言,就重新实现一个前端,例如华为“仓颉”就有自己的前端来替换clang。

如果你想支持一个新硬件,那你就重行实现一个后端,让它可以正确的把LLVM IR映射到自己的芯片。

前端

在这里插入图片描述

经过词法分析、语法分析、语义分析、LLVM IR生产,最终将C++转化成后端认可的LLVM IR。

词法分析:将编程语言取出一个个词,遇到不认识的字符就报错。例如将a=b+c 拆成a,= ,b ,+, c

语法分析:将语法提取出来,例如你写了个a+b=c, 明显不符合语法,直接报错

语义分析:分析一下你写的代码实际含义是不是对,例如a=b+c, a,b,c有没有定义,类型是不是对的

LLVM IR生产:经过上述三步,将你写的代码转化成树状描述(抽象语法树),然后再转化成IR定义的IR即可。

举个直观的栗子,你写的C++

// add.cpp
int add(int a, int b) {
return a + b;
}

生产的LLVM IR

(这个地方你不需要看懂每个细节,知道大概想类汇编的语言就行了, 专业的形式叫SSA, Static Single Assignment (SSA)

; ModuleID = 'add.cpp'
source_filename = "add.cpp"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.15.0"


; Function Attrs: noinline nounwind optnone ssp uwtable
define i32 @_Z3addii(i32, i32) #0 {
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 %0, i32* %3, align 4
store i32 %1, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = add nsw i32 %5, %6
ret i32 %7
}

后端

后端把你的LLVM转换成真正的汇编(或者机器码)。主要的流程如下。这个我们要重点讲讲,因为后续我们就是要实现一个这个东西支持一个新的芯片。
在这里插入图片描述

DAG Lowering

这个主要负责将你的LLVM IR转换为有向无环图,便于后续利用图算法优化。

例如将下面的LLVM IR 转换成图,每个节点是一个指令。

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

DAG Legalization

DAG图合法化,3.1中的DAG图都是LLVM IR指令,但实际上LLVM IR指令不可能被芯片全部支持,这个步骤就是替换这些不合法的指令。

Instruction Selection

这个步骤其实和3.2算是一起的功能,都是为了将LLVM IR转换成机器支持的Machine DAG.
在这里插入图片描述

如上图,将store换成机器仍可的st, 将16位的寄存器转向32位。一切向机器指令靠拢。

Scheduling

这个步骤主要是调整指令顺序的,从有向无环图再展开成顺序的指令。

例如把下面的指令调成这样的。

在这里插入图片描述

把%C的store提前一些,因为下一条ld要用C啦。

SSA-based Machine Code Optimization

这一步骤主要是做一些公共表达式合并啊去除的操作。

Register Allocation

这一步就要分配寄存器了。在3.5之前我们认为寄存器其实是可以无限用的,但实际硬件的寄存器有限的。所以我们得考虑寄存器数量与寄存器值的生命周期,将虚拟的寄存器替换成实际的寄存器。这个一般会用到图着色等等算法,贼复杂,好在LLVM都实现好了,不用在重复造轮子。

例如一个芯片,有32个可用的寄存器,如果函数使用到了64个,多的就只能压如堆栈或者等着了。

具体怎么分配的,知乎有专家研究,见下面的文章。Frank Wang:LLVM寄存器分配(一)

Prologue/Epilogue Code Insertion

这个主要是加上函数调用前的指令和函数结束后的指令。主要是调用前把参数存下来,调用后把结果写到固定的寄存器里。

Peephole optimizations

这个步骤主要是对代码再最后抢救一番。比如把x*2换成x<1

再比如下面这样
在这里插入图片描述

将两个32bit的存储换成一个64bit的存储

Code Emission

最后一步显然,将上述优化好的中间格式转换成我们真正需要的汇编,由汇编器翻译成机器码,大功告成。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深度学习AI编译器-LLVM简介 的相关文章

随机推荐

  • 安卓移动应用开发之从零开始写程序5

    实验5 多界面程序的创建 案例1 QQ登陆界面的跳转 实现最终效果图如下 当我们点击登陆按钮 界面跳转到登陆成功界面 账号密码的判断暂时不写 并显示我们输入的账号和密码 如图 当我们点击返回按钮则返回初始界面 实验知识点 1 基本控件和布局
  • unity-Fatal Error GC-GetThreadContext Failed

    这几次在使用unity5 3打windows包后 运行x exe不久总是会弹出 fatal error GC GetThreadContext Failed 的错误 到网上查了 各种说法都有 我干脆换了unity5 6版本 但是问题依然存在
  • java.lang.NumberFormatException: Invalid int: “0 “

    关于 今天在接手前人模块开发的时候 测试一个数据列表点击跳转详细页面的时候奔溃了 控制台 主要出现的错误提示是这句 java lang NumberFormatException Invalid int 0 问题原因转换了特殊字符 空格 等
  • 常用的python 命令

    安装依赖的命令 venv虚拟环境 下载依赖包 创建虚拟环境 python m venv lt 虚拟环境名称 gt python m venv venv 创建名为venv的虚拟环境 激活虚拟环境 source venv bin activat
  • IPO向上,大模型向下:中国企服寻找新「出口」

    2023年 资本市场给企服行业带来的动荡 无疑是一次洗牌机会 只有当SaaS企业深耕产业侧 才能找到实现标准化的解法 才能在一波又一波的浪潮下抓住机遇 作者 思杭 编辑 皮爷 出品 产业家 2023上半年 企服行业在二级市场表现得尤为热闹
  • Mac latex vscode配置外部PDF阅读器并配置对应跳转

    1 下载并安装Skim 下载链接 https sourceforge net projects skim app 2 配置skim touch displayfile txt open displayfile txt 在文本中写入 bin
  • Unity Animation从UAS获取动画资产到编制状态机控制简单的人物动画

    Animation 动画 0 前言 这个笔记用于讨论在Unity中开发游戏时使用动画的相关知识 这个笔记最终期望能够达到 在Unity的Demo中展现一个人物 其能够进行类似挥拳 开门的具体动作 我将这个任务进一步的划分 第一阶段 获得动画
  • 环形内存circular_buffer

    boost中支持环形内存 该内存在一些地方还是蛮实用的 简单看下具体使用及部分源码 使用和源码相对来说都还是比较简单 易于理解的 与STL接口基本一致 void CCircularBufferTest TestCircularBuffer
  • 双向链表和循环双向链表的基本操作

    双向链表和循环双向链表的基本操作 include
  • Libevent库的介绍与应用

    Libevent库 Libevent概述 Libevent使用模型 Libevent库使用示例 Libevent事件类型和框架结构 使用Libevent完成tcp服务端 Libevent概述 Libevent是开源社区的一款高性能的I O框
  • VS远程连接调试Linux程序 ,vs找不到Linux头文件的解决办法

    使用VS编写Linux程序 可以将VS连接到Linux上 却出现了VS IDE中找不到 include
  • 小程序逆向工程:这个开源的小程序逆向工具真不错,2023年亲测成功

    前言 安全部门的大哥又双叒叕报了一个小程序的高危漏洞 他使用逆向工程破解了加密信心 用抓包修改了请求参数 又是头疼的一天 想成为一名微信小程序的开发者 前端思路的学习和安全意识是非常有必要的 故务必掌握小程序反编译技能 这里用到了2个工具
  • 虚拟化KVM

    什么是虚拟化 在计算机技术中 虚拟化是一种资源管理技术 是将计算机的各种实体资源 CPU 内存 磁盘空间 网络适配器等 予以抽象 转换后呈现出来并可供分割 组合为一个或多个计算机配置环境 并重新分割 重新组合 已达到最大化合理利用物理资源的
  • 程序的运行结构

    一 程序的运行结构有三种 1 顺序结构 2 分支结构 3 循环结构 二 分支结构 根据代码的成立与否 选择执行方向 包括 if 判断条件 代码块 if else语句 一定会执行一个语句或者是if里面的 或者是else里面的 switch 整
  • Leetcode每日一题:589. N 叉树的前序遍历

    前序遍历二叉树的要点就是根左右 在这里遍历的是n叉树 因此先访问根节点 然后再遍历根节点的每个孩子就可以了 递归解法 Definition for a Node class Node def init self val None child
  • Qt学习笔记:2018年8月记录

    1 Qt 设置背景图片注意事项 使用stylesheet设置背景图片还是有一些要注意的 如果是在mainwindow和dialog中 直接右键change style sheet在add resource中选择background imag
  • The method getContextPath() from the type HttpServletRequest refers to the missing type

    问题描述 每个JSP页面中的 request getContextPath 下方出现了红色的波浪线 提示的错误信息是 The method getContextPath from the type HttpServletRequest re
  • 微信小程序页面监听右上角退出,判断小程序进入后台时就实现页面跳转

    功能需求 在小程序中某一个页面没有进入后台的功能 如果点击右上角退出按钮 默认小程序进入后台 点击再次进入本页面 但是因为功能需要 在小程序进入后台时 再次进入需要跳转到首页 实现方法 在app js onHide 生命周期中监听进入后台的
  • 项目启动报错: This is very likely to create a memory leak. Stack trace of thread 解决方案

    问题发现 The web application ROOT appears to have started a thread named UIC STATISTIC THREAD but has failed to stop it This
  • 深度学习AI编译器-LLVM简介

    1 什么是LLVM LLVM的命名最早来源于底层语言虚拟机 Low Level Virtual Machine 的缩写 它是一个用于建立编译器的基础框架 以C 编写 创建此工程的目的是对于任意的编程语言 利用该基础框架 构建一个包括编译时