MachineSink - 优化阅读笔记

注:该优化与全局子表达式消除刚好是相反的过程,具体该不该做这个优化得看代价模型算出来的结果(有采样文件指导算得会更准确)

该优化过程将指令移动到后继基本块中,以便它们不会在不需要其结果的路径上执行。

该优化过程并非旨在替代或完全替代 LLVM IR 级别的下沉优化。它仅设计用于下沉简单的结构,这些结构在 lowering 和指令选择之前不会显现.

测试用例:

grep "machine-sink" llvm/test/* -Rnw|grep X86|grep -v debug
./build4/bin/llvm-lit llvm/test/DebugInfo/MIR/X86/machinesink.mir -a
./build4/bin/llc -run-pass=dot-machine-cfg llvm/test/DebugInfo/MIR/X86/machinesink.mir
dot .Process.dot -T svg -o Process.dot.svg
dot .test2.dot -T svg -o test2.dot.svg
dot .test3.dot -T svg -o test3.dot.svg./build4/bin/llc -mtriple=x86_64-unknown-unknown -run-pass=machine-sink -o - ./llvm/test/DebugInfo/MIR/X86/machinesink.mir &> dd
./build4/bin/llc -mtriple=x86_64-unknown-unknown -run-pass=removeredundantdebugvalues -o - ./llvm/test/DebugInfo/MIR/X86/machinesink.mir &> ddd

效果:
在这里插入图片描述在这里插入图片描述

几个重要的接口:

bool MachineSinking::runOnMachineFunction(MachineFunction &MF) {// 更新寄存器信息RegClassInfo.runOnMachineFunction(MF);// 遍历每个 BB, 寻找优化的场景for (auto &MBB: MF)MadeChange |= ProcessBlock(MBB);// 处理需要打破的临界边auto NewSucc = Pair.first->SplitCriticalEdge(Pair.second, *this);
void RegisterClassInfo::runOnMachineFunction(const MachineFunction &mf) {// 1. 检查 CSR 数组的每个元素是否与之前分析的相同const MCPhysReg *CSR = MRI.getCalleeSavedRegs();// 2. 如果有改变,记录每一个 CSR 及它的别名for (MCRegAliasIterator AI(*I, TRI, true); AI.isValid(); ++AI)CalleeSavedAliases[*AI] = *I;// 3. 更新每个 CSRs 的分配优先级if (IgnoreCSRForAllocOrder.size() != CSRHintsForAllocOrder.size() ||IgnoreCSRForAllocOrder != CSRHintsForAllocOrder) {// 4. 获取寄存器的成本RegCosts = TRI->getRegisterCosts(*MF);// 5. 更新保留寄存器const BitVector &RR = MF->getRegInfo().getReservedRegs();// 6. 更新寄存器压力unsigned NumPSets = TRI->getNumRegPressureSets();// build4/lib/Target/X86/X86GenRegisterInfo.inc:11902// build4/lib/Target/AArch64/AArch64GenRegisterInfo.inc:103840
}
bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) {// 待优化BB需要有多个后继,且不是死的基本块// 逆序遍历每条指令do {// 记录指令的 debug 信息// 执行琐碎的前向聚合, SRC=DRC的拷贝指令的替换bool Joined = PerformTrivialForwardCoalescing(MI, &MBB);// 尝试下沉指令if (SinkInstruction(MI, SawStore, AllSuccessors))} while (!ProcessedBegin);
}
bool MachineSinking::SinkInstruction(MachineInstr &MI, bool &SawStore,AllSuccsCache &AllSuccessors) {TII->shouldSink(MI); // X86 always trueMI.isSafeToMove(AA, SawStore); // MachineInstr.cpp:1259 !store !call !load !phi !inlineasm !positino ...MachineBasicBlock *SuccToSinkTo =FindSuccToSinkTo(MI, ParentBlock, BreakPHIEdge, AllSuccessors);// 不要破坏隐式空指针检查。这是一种性能启发,而非正确性所必需// 如果 MI 可能被隐式空指针检查优化用作内存操作,则返回 trueSinkingPreventsImplicitNullCheck(...);// llvm/test/CodeGen/X86/implicit-null-check.ll// br i1 %c, label %is_null, label %not_null, !make.implicit !0// 这应该包括支持在当前块内下沉指令,以缩短其寄存器活跃范围。我们经常将指令下沉到大块的顶部,但最好在它们在块中第一次使用之前也将其下沉。但是,此变换必须小心,不要增加寄存器压力,例如,如果下沉 "x = y + z",但它杀死了 y 和 z,那么会增加 y 和 z 的寄存器活跃范围,而只会减小 x 的寄存器活跃范围MachineBasicBlock *SuccToSinkTo = FindSuccToSinkTo(MI, ParentBlock, BreakPHIEdge, AllSuccessors);// 检查是否会引入僵尸寄存器if (SuccToSinkTo->isLiveIn(Reg))// 如果需要打破危险边界, // 或 会破坏 PHI 边界if (SuccToSinkTo->pred_size() > 1) if (blockPrologueInterferes(SuccToSinkTo, InsertPos, MI, TRI, TII, MRI)) || if (BreakPHIEdge)// 延后打破危险边界,就记录一下bool Status = PostponeSplitCriticalEdge(MI, ParentBlock, SuccToSinkTo, BreakPHIEdge);// ToSplit.insert(std::make_pair(FromBB, ToBB));// 查找插入点, 跳过 phi和序幕指令SuccToSinkTo->SkipPHIsAndLabels(SuccToSinkTo->begin());// 收集需要一并下沉的debug指令DbgUsersToSink.push_back({DbgMI, SmallVector<unsigned, 2>(1, MO.getReg())});// 下沉指令及其相关调试指令performSink(MI, *SuccToSinkTo, InsertPos, DbgUsersToSink);// 移动指令:SuccToSinkTo.splice(InsertPos, ParentBlock, MI, ++MachineBasicBlock::iterator(MI));// 处理debug信息:attemptDebugCopyProp(MI, *DbgMI, Reg)// 清除 kill 标记RegsToClearKillFlags.insert(MO.getReg());
}
MachineBasicBlock *
MachineSinking::FindSuccToSinkTo(MachineInstr &MI, MachineBasicBlock *MBB,bool &BreakPHIEdge,AllSuccsCache &AllSuccessors) {// 检查要下沉的指令的每个操作数for (const MachineOperand &MO : MI.operands()) {// 对于虚拟寄存器// 需要能安全移动if (!TII->isSafeToMoveRegClassDefs(MRI->getRegClass(Reg)))// llvm/lib/Target/X86/X86InstrInfo.cpp:7534// 否则,我们应该查看所有的后继块并决定应该下沉到哪一个。如果我们有可靠的块频率信息(frequency != 0),则将具有较小频率的后继块优先级更高,否则优先考虑较小的循环深度for (MachineBasicBlock *SuccBlock :GetAllSortedSuccessors(MI, MBB, AllSuccessors)) {// 除了MBB的直接后继, 被 MBB 作为直接支配者的 DomTree 子节点也会被遍历/// AllUsesDominatedByBlock - 如果指定寄存器的所有使用都在指定块支配的块中发生,则返回 true, 如果任何使用在定义块中,则返回 false,因为在使用之后移动定义是不合法的。if (AllUsesDominatedByBlock(Reg, SuccBlock, MBB,BreakPHIEdge, LocalUse)) {}// 检查收益if (!isProfitableToSinkTo(Reg, MI, MBB, SuccToSinkTo, AllSuccessors))}
}bool MachineSinking::isProfitableToSinkTo(Register Reg, MachineInstr &MI,MachineBasicBlock *MBB,MachineBasicBlock *SuccToSinkTo,AllSuccsCache &AllSuccessors) {// 1. 不 反向支配 Def BB!PDT->dominates(SuccToSinkTo, MBB)// 2. 循环嵌套更浅if (CI->getCycleDepth(MBB) > CI->getCycleDepth(SuccToSinkTo))// 3. 寄存器压力不超限if (isRegisterPressureSetExceedLimit(MRI->getRegClass(Reg)))
}

遗留问题:

  1. 与 llvm ir 中 sink 的区别
  2. split critical edge 具体是怎么做的

LLVM IR 中搜索到其他三个 Sink 相关的pass:

# find llvm/lib/ -name "*.cpp"|grep "sink" -i
llvm/lib/Transforms/Scalar/Sink.cpp
llvm/lib/Transforms/Scalar/LoopSink.cpp
llvm/lib/Transforms/Scalar/GVNSink.cpp
llvm/lib/CodeGen/MachineSink.cpp

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

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

相关文章

【大厂AI课学习笔记NO.80】深度学习行业人才能力图谱

深度学习领域的就业岗位及所需关键技术、工具、能力分析 深度学习作为人工智能领域的一个重要分支&#xff0c;近年来得到了飞速的发展。随着技术的不断进步和应用场景的不断拓展&#xff0c;深度学习领域的就业岗位也日益增多。本文将从领军人才、产业研发人才、应用开发人才…

Linux——信号

目录 什么是信号 Linux下的信号 信号的记录 信号处理的常见方式 产生信号 使用组合键产生信号&#xff08;包含core dump&#xff09; 使用系统调用向进程发送信号 由软件条件产生信号 由硬件异常产生信号 阻塞信号 内核表示 sigset_t 信号集操作函数 sigpendin…

jvm八股

文章目录 运行时数据区域Java堆对象创建对象的内存布局对象的访问定位句柄直接指针 GC判断对象是否已死引用计数算法可达性分析算法 引用的类别垃圾收集算法分代收集理论标记清除算法标记复制算法标记整理算法 实现细节并发的可达性分析 垃圾收集器serial收集器ParNew收集器Par…

如何保证 redis 的高并发和高可用?redis 的主从复制原理能介绍一下么?redis 的哨兵原理能介绍一下么?

目录 一、面试官心理分析 二、面试题剖析 1.Redis 主从架构 2.Redis replication 的核心机制 3.Redis 主从复制的核心原理 4.主从复制的断点续传 5.无磁盘化复制 6.过期 key 处理 7.复制的完整流程 8.全量复制 9.增量复制 10.heartbeat 11.异步复制 12.Redis 如何…

【三十】springboot项目上高并发解决示例

互相交流入口地址 整体目录&#xff1a; 【一】springboot整合swagger 【二】springboot整合自定义swagger 【三】springboot整合token 【四】springboot整合mybatis-plus 【五】springboot整合mybatis-plus 【六】springboot整合redis 【七】springboot整合AOP实现日志操作 【…

Java学习记录(十六):IO流(三)

缓冲流 缓冲流是一种高级流&#xff0c;可以理解为将基本流包装成了这种高级流&#xff0c;而这种高级流的特点就是将一个缓冲区放入到基本流当中&#xff0c;从而提高基本流的效率&#xff0c;但实际进行读写操作的还是基本流 下面为缓冲字节输出流和缓冲字节输入流的应用&am…

基于SpringBoot疫情打卡健康评测系统

基于SpringBoot疫情打卡健康评测系统~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 学生端功能效果展示 试卷表 在线考试 打卡管理 居家管理 学生返校申请管理 管理…

救命!我终于会写一份简单的产品说明书了

写一份简单的说明书其实也不简单&#xff0c;需要有前期的调研准备&#xff0c;撰写时的条框梳理&#xff0c;收尾的清晰明了。网络上有很多撰写产品说明书的方法&#xff0c;却也有一些模糊的地方&#xff0c;下面就来看看LookLook同学是怎么完成一份简单的产品说明书的。 一、…

【Python】一文详细介绍plt.rcParams 在 Matplotlib 中的原理、作用、注意事项

【Python】一文详细介绍plt.rcParams 在 Matplotlib 中的原理、作用、注意事项 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x…

c++ primer plus 笔记 第十六章 string类和标准模板库

string类 string自动调整大小的功能&#xff1a; string字符串是怎么占用内存空间的&#xff1f; 前景&#xff1a; 如果只给string字符串分配string字符串大小的空间&#xff0c;当一个string字符串附加到另一个string字符串上&#xff0c;这个string字符串是以占用…

css 用flex做成田字型

哈喽&#xff0c;各位小伙伴&#xff01;今天给大家来css控制div完成田字型样式&#xff0c;来&#xff0c;看看下面的效果图&#xff1a; 一看就知道你们想要代码了&#xff0c;不急。代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head>&…

JAVA全面基础知识(第七部分)

大家好我是程序员阿存&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款&#xff0c;项目源码以及部署相关请联系存哥&#xff0c;文末附上联系信息 。 这篇文章给大家分享的是JAVA的基础知识&#xff0c; &#x1f495;&#x1f495;作者&#xff1a;程序员阿存 &…

哪里下载短视频素材?推荐几个短视频素材下载网站

当短视频行业的迅速崛起&#xff0c;剪辑影视短片的魅力无法抗拒&#xff0c;越来越多朋友爱看短视频&#xff0c;但从哪里找到高清、无水印和无字幕的短视频素材呢&#xff1f;今天&#xff0c;我将为大家推荐几个可获取短视频素材的优秀网站&#xff0c;下面让我们一起去看看…

吴恩达机器学习-可选实验室:逻辑回归(Logistic Regression))

在这个不评分的实验中&#xff0c;你会探索sigmoid函数(也称为逻辑函数)探索逻辑回归;哪个用到了sigmoid函数 import numpy as np %matplotlib widget import matplotlib.pyplot as plt from plt_one_addpt_onclick import plt_one_addpt_onclick from lab_utils_common impor…

2024最新版使用PyCharm搭建Anaconda

2024最新版使用PyCharm搭建Anaconda 因为pycharm自带的包不全&#xff0c;或者下载的时候比较慢&#xff0c;所以我们直接用anaconda的包&#xff0c;毕竟我们以后还会学到很多的包&#xff0c;不多说&#xff0c;直接开干&#xff01; 一、下载Pycharm、Anacoda pycharm中文网…

信息系统三级等保安全解决方案(46页Word)

1、系统定级与安全域 2、实施方案设计 3、安全防护体系建设规划 软件开发全系资料分享下载&#xff1a;软件项目开发全套文档下载_软件开发文档下载-CSDN博客

安全防御第七次作业

拓扑图如图所示&#xff1a; 问题&#xff1a;在FW7和FW8之间建立一条IPSEC通道保证10.0.2.0/24网段 可以正常访问到192.168.1.0/24 注&#xff1a;基础配置我在此省略了 一、NAT配置 FW4&#xff1a; FW6&#xff1a; 二、在FW4上做服务器映射 三、配置IPSEC FW5&#xff…

MessAuto-让验证码提取更加丝滑

专注于web漏洞挖掘、内网渗透、免杀和代码审计&#xff0c;感谢各位师傅的关注&#xff01;网安之路漫长&#xff0c;与君共勉&#xff01; MessAuto MessAuto 是一款 macOS 平台自动提取短信和邮箱验证码到粘贴板的软件&#xff0c;由Rust开发&#xff0c;适用于任何APP 下面展…

这个简历你给几分?

求大家给给建议&#x1f62d;&#x1f62d; 自己算法几乎没刷过&#xff0c;项目也不咋好 打算21号开始投日常实习 好慌

MySQL将两条记录根据相同条件合并

知识点&#xff1a;在MySQL中&#xff0c;可以使用GROUP BY子句和聚合函数如CONCAT或CONCAT_WS来将多条记录基于相同条件合并为一条记录 【主要是GROUP_CONCAT这个函数的运用】 例如将员工信息表中相同门店的员工信息合并为一条记录 MySQL语句如下&#xff1a; SELECT dept_…