当前位置: 首页 > news >正文

LLVM学习笔记(50)

4.1.4. DAG合并与合法化

来自SelectionDAGBuilder的SelectionDAG输出还不能进行指令选择,必须通过额外的转换——显示在上图。在指令选择前应用的遍序列如下:

  • 匹配一组节点,在有利时使用更简单的构造来替换它们,DAG合并遍优化SelectionDAG的结构。例如,(add (Register X), (constant 0))可以折叠为(Register X)。类似的,目标机器的合并方法可以识别节点模式,决定是否合并以及折叠它们,提升目标机器指令选择的质量。方法setTargetDAGCombine标记目标机器希望合并的节点。例如,MIPS后端尝试合并加法——参考lib/Target/Mips/MipsISelLowering.cpp的setTargetDAGCombine(ISD::ADD)与performADDCombine()。

(注:在每个合法化阶段后运行DAG合并以尽量减少SelectionDAG冗余。另外,DAG合并知道运行到遍链(pass chain)的何处(例如,在合法化或向量合法化之后),并且可以更精确地使用这个信息。)

  • 类型合法化遍确保指令选择仅需要处理合法的类型。合法类型是目标机器原生支持的类型。例如,在仅支持i32类型的目标机器上带有i64操作数的加法是非法的。在这个情形里,类型合法器执行整数扩展,将一个i64操作数分解为两个i32操作数,同时生成处理它们的合适的代码。目标机器定义每个类型与哪些寄存器类相关,明确声明支持的类型。因此,必须相应地检测与处理非法类型:标量类型可以被提升、扩展或者弱化,而向量类型可以被分裂、标量化或者加宽。同样,目标机器也可以定制类型合法化的方法。类型合法器运行两次,在第一次DAG合并后,以及向量合法化后。
  • 存在后端直接支持一个向量类型的情形,这意味着对此有一个寄存器类,但在一个给定向量类型上的一个特定操作不一定。例如,有SSE2的X86支持v4i32向量类型。不过,在ISD::OR上没有支持v4i32类型的X86指令,仅支持v2i64。因此,向量合法化器使用指令的合法类型提升或扩展来处理这些情形。在上述ISD::OR情形里,操作被提升为使用v2i64类型。

(注:对某些类型,扩展将消除向量类型,使用标量类型。这会导致目标机器不支持的标量类型。不过,后续的类型合法化器将清除之。)

  • DAG合法化器具有与向量合法化器相同的任务,但处理任何带有不支持类型(标量或向量)的遗留操作。它支持相同的操作:提升,扩展,处理定制节点。例如,x86节点不支持以下三个中的任意一个:i8类型有符号整数到浮点数的操作(ISD::SINT_TO_FP),要求合法化器提升该操作;i32操作数上的有符号除法,要求一个扩展,发布一个库调用来处理该除法;f32操作数上浮点绝对值(ISD::FABS),使用一个定制句柄来生成具有相同效果的代码。X86以下列方式来发布这样的行为(参考lib/Target/X86/X86ISelLowering.cpp):

setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);

setOperationAction(ISD::SDIV, MVT::i32, Expand);

setOperationAction(ISD::FABS, MVT::f32, Custom); 

4.1.5. DAG到DAG的指令选择

 DAG到DAG指令选择的目的是通过模式匹配,将目标机器无关的节点翻译为目标机器特定的节点。指令选择算法是局部的,一次作用在一个SelectionDAG(基本块)实例上。

作为一个例子,在指令选择后,我们的SelectionDAG结构展示如下。CopyToReg,CopyFromReg及Register节点没有触及,并一直维持到寄存器分配。事实上,指令选择阶段甚至可能生成额外的节点。在指令选择后, ISD::ADD节点被翻译为X86指令ADD32ri8,而X86ISD::RET_FLAG被翻译为RET。

(注:在同一个DAG中可能有3种指令表示共存:通用LLVM ISD节点,比如ISD::ADD;目标机器特定的<Target>ISD节点,比如X86ISD::RET_FLAG;以及目标机器的物理指令,比如X86::ADD32ri8。)

4.1.6. 模式匹配

每个目标机器通过在名为<Target_Name>DAGToDAGISel的SelectionDAGISel子类中实现Select()方法来处理指令选择,例如,SPARC中的SparcDAGToDAGISel::Select()。这个方法接受一个要匹配的SDNode参数,返回代表一条物理指令的一个SDNode值;否则出错。

Select()方法允许两个方式来匹配物理指令。最直接的方式是通过调用从TableGen模式生成的匹配代码,就像下面列表中的第一步。不过,模式表达能力可能不足以处理某些指令的古怪行为。在这种情形下,必须在这个方法里编写定制的C++匹配逻辑的实现,就像下面列表的第二步。这个做法的细节如下:

1. Select()方法调用SelectCode。TableGen为每个目标机器生成SelectCode()方法,在这个代码里,TableGen还生成了MatcherTable,将ISD及<Target>ISD节点映射到物理指令节点。这个匹配者表从.td文件(通常是<Target>InstrInfo.td)里的指令定义生成。SelectCode()方法以调用使用该目标机器匹配者表来匹配节点的目标机器无关方法SelectCodeCommon()结束。TableGen有一个专用的指令选择后端来生成这些方法即这个表

$ cd <llvm_source>/lib/Target/Sparc

$ llvm-tblgen -gen-dag-isel Sparc.td -I ../../../include

对每个目标机器,在C++生成文件<build_dir>/lib/Target/<Target>/<Target>GenDAGISel.inc中有相同的输出;例如,SPARC的方法与表在<build_dir>/lib/Target/Sparc/SparcGenDAGISel.inc文件里。

2. 在调用SelectCode()之前提供定制的匹配代码。例如,i32节点ISD::MULHU执行两个i32的乘法,产生一个i64结果,并返回高i32部分。在32位SPARC里,乘法指令SP::UMULrr在特殊寄存器Y中返回高部分,这要求使用SP::RDY指令读出。TableGen不能体现这个逻辑,我们使用下述代码来解决之:

case ISD::MULHU: {

   SDValue MulLHS = N->getOperand(0);

   SDValue MulRHS = N->getOperand(1);

   SDNode *Mul = CurDAG->getMachineNode(SP::UMULrr, dl,

            MVT::i32, MVT::Glue, MulLHS, MulRHS);

   return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32,

            SDValue(Mul, 1));

}
这里,在这个上下文中,N是要匹配的SDNode实参,它等于ISD::MULHU。因为在这个case语句之前已经执行过完备性检查,我们着手生成SPARC特定的操作码来替换ISD::MULHU。为此,我们调用CurDAG->getMachineNode()创建一个带有物理指令SP::UMULrr的节点。其次,通过使用CurDAG- >SelectNodeTo(),我们创建一个SP::RDY指令节点,然后将所有使用ISD::MULHU节点的地方改为指向SP::RDY的结果。下图展示了这个例子指令选择前后SelectionDAG结构。上述的C++代码片段是lib/Target/Sparc/SparcISelDAGToDAG.cpp代码的简化版。

 

4.1.7. 指令选择过程的可视化

有几个llc选项允许在指令选择的不同阶段可视化SelectionDAG。如果你使用这些选项,llc将生成一个类似于之前展示图的.dot图,不过你需要使用dot程序来显示它,或使用dotty来编辑它,两者都能在www.graphviz.org的Graphviz包里找到。下表以执行序展示了各个选项:

Llc选项

阶段

-view-dag-combine1-dags

在DAG合并1之前

-view-legalize-types-dags

在类型合法化之前

-view-dag-combine-lt-dags

类型合法化2之后,DAG合并之前

-view-legalize-dags

合法化之前

-view-dag-combine2-dags

DAG合并2之前

-view-isel-dags

在指令选择之前

-view-sched-dags

指令选择之后,调度之前

44.1.8. 快速指令选择

LLVM还支持另一个称为快速指令选择的实现。快速指令选择的目的是,以代码质量为代价,提供快速的代码生成,它适合于-O0级别优化过程的哲学。速度提升归因于避免复杂的折叠与降级逻辑。TableGen描述也用于简单的操作,但指令更复杂的匹配要求目标机器特定的处理代码。

-O0过程还使用快速的次优寄存器分配器及调度器,以代码质量换取编译速度。)

相关文章:

LLVM学习笔记(50)

4.1.4. DAG合并与合法化 来自SelectionDAGBuilder的SelectionDAG输出还不能进行指令选择&#xff0c;必须通过额外的转换——显示在上图。在指令选择前应用的遍序列如下&#xff1a; 匹配一组节点&#xff0c;在有利时使用更简单的构造来替换它们&#xff0c;DAG合并遍优化Se…...

rpc入门笔记0x01

syntax "proto3"; // 这是个proto3的文件message HelloRequest{ // 创建数据对象string name 1; // name表示名称&#xff0c;编号是1 }生成python文件 安装grpcio和grpcio-tools库 pip install grpcio #安装grpc pip install grpcio-tools #安装grpc tools生成…...

web - Tomcat服务器

文章目录 目录 文章目录 前言 一 . CS和BS的异同 二 . 什么是Tomcat 二 . Tomcat安装 四 . Tomcat目录结构 bin目录: 用于存放二进制的可执行文件 config目录 server.xml&#xff1a;配置整个服务器信息。例如修改端口号。默认HTTP请求的端口号是&#xff1a;8080 lib目录 log…...

后端接口返回常见的状态码

2开头 &#xff08;请求成功&#xff09;表示成功处理了请求的状态代码 200 &#xff08;成功&#xff09; 服务器已成功处理了请求。 通常&#xff0c;这表示服务器提供了请求的网页。 201 &#xff08;已创建&#xff09; 请求成功并且服务器创建了新的资源。 202 &#xf…...

50.MongoDB快速入门实战

MongoDB概念 MongoDB是一个文档数据库&#xff08;以 JSON 为数据模型&#xff09;&#xff0c;由C语言编写&#xff0c;旨在为WEB应用提供可扩展的高性能数据存储解决方案。 原则上 Oracle 和 MySQL 能做的事情&#xff0c;MongoDB 都能做&#xff08;包括 ACID 事务&#x…...

一款功能强大的音乐曲谱软件Guitar Pro 8 .1.1for Mac 中文破解版

Guitar Pro 8 .1.1for Mac 中文破解版是一款功能强大的音乐曲谱软件&#xff0c;非常适合学习如何玩&#xff0c;改进技巧&#xff0c;重现喜爱的歌曲或陪伴自己。可以帮助我们进行吉他的学习、绘谱与创作&#xff0c;它包含了几乎所有的吉他现有指法及音色&#xff0c;在做弹拨…...

图论基础和表示

一、概念及其介绍 图论(Graph Theory)是离散数学的一个分支&#xff0c;是一门研究图(Graph)的学问。 图是用来对对象之间的成对关系建模的数学结构&#xff0c;由"节点"或"顶点"(Vertex&#xff09;以及连接这些顶点的"边"&#xff08;Edge&a…...

STM32 音频ADC转wav格式

STM32 音频ADC DAC测试方法_stm32 adc 音频-CSDN博客 STM32--vs1053 WAV录音实现&#xff08;保存在SD卡&#xff09;_vs1053 多字节读取-CSDN博客 单片机内部AD实现录音wav文件_adc语音信号采样_天外飞仙CUG的博客-CSDN博客 PCM编码格式_pcm格式-CSDN博客 用ADC编码PCM数据…...

面试中经常问道的问题二

深入理解前端跨域方法和原理 前言 受浏览器同源策略的限制&#xff0c;本域的js不能操作其他域的页面对象&#xff08;比如DOM&#xff09;。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。所以我们要通过一些方法使本域的js能够操作其他域的页面对象或者使…...

SQL UPDATE 语句(更新表中的记录)

SQL UPDATE 语句 UPDATE 语句用于更新表中已存在的记录。 还可以使用AND或OR运算符组合多个条件。 SQL UPDATE 语法 具有WHERE子句的UPDATE查询的基本语法如下所示&#xff1a; UPDATE table_name SET column1 value1, column2 value2, ... WHERE conditi…...

js节流和防抖

节流&#xff08;throttle&#xff09;和防抖&#xff08;debounce&#xff09;是为了解决函数频繁触发而引发性能问题的两种优化方法。 节流&#xff1a; 指定一个时间间隔&#xff0c;在时间间隔内只执行一次函数&#xff0c;即在一段时间内&#xff0c;多次触发函数只执行一…...

权限系统设计(转载)

1 为什么需要权限管理 2 权限模型 2.1 权限设计 2.2 为什么需要角色 2.3 权限模型的演进 2.4 用户划分 2.5 理想的RBAC模型 3 权限系统表设计 3.1 标准RBAC模型表设计 3.2 理想RBAC模型表设计 4 结语 1 为什么需要权限管理 日常工作中权限的问题时时刻刻伴随着我们&a…...

【机器学习合集】标准化与池化合集 ->(个人学习记录笔记)

文章目录 标准化与池化1. 标准化/归一化1.1 归一化归一化的作用 1.2 标准化批标准化方法 Batch Normailzation标准化方法的对比自动学习标准化方法 2. 池化2.1 池化的作用2.2 常见的池化方法2.3 池化方法的差异2.4 池化的必要性 标准化与池化 1. 标准化/归一化 1.1 归一化 归…...

Dockerfile文件自动化生成R4L镜像

Dockerfile文件自动化生成R4L镜像的步骤 1、安装Docker&#xff1a;2、使用Dockerfile一键生成镜像&#xff1a;3、查看生成的Docker镜像&#xff1a;4、删除Docker镜像&#xff1a;5、生成Docker容器&#xff1a;6、查看容器7、删除容器 1、安装Docker&#xff1a; curl -fsS…...

基于SSM的居家养老系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…...

[C#基础训练]FoodRobot食品管理部分代码-2

参考代码&#xff1a; using System; using System.Collections.Generic;namespace FoodRobotDemo {public class FoodInfo{ public string Name { get; set; } public int Id { get; set; } public int Count { get; set; }}public class FoodRobot{private …...

docker部署rabbitmq的坑

背景 今天用docker部署rabbitmq&#xff0c;启动都一起正常&#xff0c;但是当访问15672端口时&#xff0c;不能加载出页面。 排查 1.防火墙是否开启 ufw status2.ip是否能ping通 ping 192.168.x.x3.检查docker日志 docker psdocker logs -f 容器id4.进入容器&#xff0c…...

【python VS vba(系列2)】 python和vba读写EXCEL文件的方式比较 (建设ing)

目录 1 用VBA读写EXCEL文件 1.1 用VBA读写&#xff0c;本工作簿workbook里的特定sheet的特定内容 1.1.1 EXCEL表内内容访问 1.1.2 注意点 1.1.3 代码 1.2 用VBA读写本工作簿workbook里的所有sheet的内容 1.2.1 麻烦之处 1.2.2 方法&#xff0c;如何指定EXCEL里的内容…...

小程序 swiper滑动 层叠滑动效果

整个红色区域为可滑动区域&#xff0c;数字1区域为展示区域&#xff0c;数字2为下一个展示模块 <scroll-view class"h_scroll_horizontal" enhanced"ture" bind:touchend"touchEnd" bind:touchstart"touchStart"><view clas…...

【20年VIO梳理】

19-20年VIO 梳理 1. 开源代码介绍&#xff1a; DSM2. FMD Stereo SLAM&#xff1a;融合MVG和直接方法&#xff0c;实现准确&#xff0c;快速的双目SLAM3. 基于VINS-Mono开发的SPVIS4. 改进&#xff1a;一种基于光流的动态环境移动机器人定位方案5. PVIO:基于先验平面约束的高效…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...