SplitFunctions (BOLT) - 优化阅读笔记

将函数拆分成更小的代码片段,从而执行更激进的代码段重排的优化

在文件 bolt/lib/Passes/SplitFunctions.cpp

相关选项释义默认
-split-all-cold尽可能多的分离冷的基本块false
-split-align-threshold对齐参数2
-split-functions主要功能选项, 分离函数到代码片段false
-split-threshold控制分离的片段的大小0
-split-strategy分离策略:
profile2: 依据采样文件
random2:随机?
randomN:随机分离成N个片段
all: 将函数分离成单独的BB块
profile2

–split-functions --split-strategy=all

1. 分割的逻辑

下面是一个并行执行的一个函数

void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) {if (BF.empty())return;// 在 RunOnFunctios, 已根据 opts::SplitStrategy 对 Strategy 初始化了// 主要判断是否有采样文件等if (!S.canSplit(BF))return;// 先拷贝一份 BB 块FunctionLayout &Layout = BF.getLayout();BinaryFunction::BasicBlockOrderType PreSplitLayout(Layout.block_begin(),Layout.block_end());// ...BinaryFunction::BasicBlockOrderType NewLayout(Layout.block_begin(),Layout.block_end());// 接下来,遍历以检查哪些BB块不能被移动// Never outline the first basic block.NewLayout.front()->setCanOutline(false);for (BinaryBasicBlock *const BB : NewLayout) {if (!BB->canOutline())continue;// 在 aarch64 中不要拆分额外的入口点。它们可以通过使用 ADRs 进行引用,当发生这种情况时,由于 ADR 指令的有限范围,这些块不能被放置得太远if (BC.isAArch64() && BB->isEntryPoint()) {BB->setCanOutline(false);continue;}if (BF.hasEHRanges() && !opts::SplitEH) {// 我们不能移动异常处理块(或者说异常处理块的入口点)if (BB->isLandingPad()) {BB->setCanOutline(false);continue;}// 由于异常处理运行时无法处理拆分的函数,我们不能移动可能引发异常的块。// 但是,如果我们可以保证该块永远不会引发异常,那么将该块移动以减小函数大小是安全的for (MCInst &Instr : *BB) {if (BC.MIB->isInvoke(Instr)) {BB->setCanOutline(false);break;}}}}// 参考 1.1 更新 Layout 的索引BF.getLayout().updateLayoutIndices();// 根据不同的 split 算法设置BB所属的代码片段// profile2: FragmentNum::cold() --> 1// random2: 随机设置某个范围的 BB 为 cold// randomN: 随机分配BB到某个片段// all: 所有BB属于单独的片段S.fragment(NewLayout.begin(), NewLayout.end());// Make sure all non-outlineable blocks are in the main-fragment.for (BinaryBasicBlock *const BB : NewLayout) {if (!BB->canOutline())BB->setFragmentNum(FragmentNum::main());}// 按顺序排一下基本块if (opts::AggressiveSplitting) {// 我们可以移动的所有计数为 0 的区块都将进入函数的末尾。// 即使它们是自然形成的集群,并且出现在热门基本区块之间llvm::stable_sort(NewLayout, [&](const BinaryBasicBlock *const A,const BinaryBasicBlock *const B) {return A->getFragmentNum() < B->getFragmentNum();});} else if (BF.hasEHRanges() && !opts::SplitEH) {// 通常情况下,带有异常处理功能的函数在末尾都有异常处理块。// 我们无法移动起始位置,但可以将包含起始位置的 0 计数值块移动到末尾,从而方便拆分auto FirstLP = NewLayout.begin();while ((*FirstLP)->isLandingPad())++FirstLP;std::stable_sort(FirstLP, NewLayout.end(),[&](BinaryBasicBlock *A, BinaryBasicBlock *B) {return A->getFragmentNum() < B->getFragmentNum();});}// 让 BB 所属的代码片段编号递增FragmentNum CurrentFragment = NewLayout.back()->getFragmentNum();for (BinaryBasicBlock *const BB : reverse(NewLayout)) {if (BB->getFragmentNum() > CurrentFragment)BB->setFragmentNum(CurrentFragment);CurrentFragment = BB->getFragmentNum();}// 让代码片段编号保持连续if (!S.keepEmpty()) {FragmentNum CurrentFragment = FragmentNum::main();FragmentNum NewFragment = FragmentNum::main();for (BinaryBasicBlock *const BB : NewLayout) {if (BB->getFragmentNum() > CurrentFragment) {CurrentFragment = BB->getFragmentNum();NewFragment = FragmentNum(NewFragment.get() + 1);}BB->setFragmentNum(NewFragment);}}// 参考 1.2 BF.getLayout().update(NewLayout);// 对于共享对象,调用指令和相应的异常处理块必须放置在同一片段中。// 当我们拆分它们时,创建跳板异常处理块,它将重定向执行到真正的异常处理块......SplitBytesHot += HotSize;SplitBytesCold += ColdSize;

1.1 更新 Layout 的索引

通常用法,如在 bolt/lib/Passes/SplitFunctions.cpp 中:

BF.getLayout().updateLayoutIndices();
S.fragment(NewLayout.begin(), NewLayout.end());
// 这看起来是按顺序给BB的 LayoutIndex 按顺序赋值一个 index
// 并且初始化所有的BB所属的代码片段为0
void FunctionLayout::updateLayoutIndices() {unsigned BlockIndex = 0;for (FunctionFragment &FF : fragments()) {for (BinaryBasicBlock *const BB : FF) {BB->setLayoutIndex(BlockIndex++);BB->setFragmentNum(FF.getFragmentNum());}}
}

1.2 更新内存布局

通常用法,如在 bolt/lib/Passes/SplitFunctions.cpp 中:

BF.getLayout().update(NewLayout);
bool FunctionLayout::update(const ArrayRef<BinaryBasicBlock *> NewLayout) {// 检查要更新的 Layout 的 BB 块是否一样 以及 他们所属的代码片段是否一样const bool EqualBlockOrder = llvm::equal(Blocks, NewLayout);if (EqualBlockOrder) {const bool EqualPartitioning =llvm::all_of(fragments(), [](const FunctionFragment &FF) {return llvm::all_of(FF, [&](const BinaryBasicBlock *const BB) {return FF.Num == BB->getFragmentNum();});});if (EqualPartitioning)return false;}// 删除除main()代码片段外的其他片段clear();// 根据 NewLayout 里 BB 设置的代码片段编号新增对应的代码片段for (BinaryBasicBlock *const BB : NewLayout) {FragmentNum Num = BB->getFragmentNum();assert(Num >= Fragments.back()->getFragmentNum() &&"Blocks must be arranged such that fragments are monotonically ""increasing.");// Add empty fragments if necessarywhile (Fragments.back()->getFragmentNum() < Num)addFragment();// Set the next fragment to point one past the current BBaddBasicBlock(BB);}return true;
}

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

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

相关文章

Codeql复现CVE-2018-11776学习笔记

基本使用 1、首先下载struts2漏洞版本源码&#xff1a; https://codeload.github.com/apache/struts/zip/refs/tags/STRUTS_2_3_20 2、构建codeql数据库&#xff08;构建失败文末有解决办法&#xff09;&#xff1a; codeql database create ~/CodeQL/databases/struts2-2.3.…

C#与WPF通用类库

个人集成封装&#xff0c;仓库已公开 NetHelper 集成了一些常用的方法&#xff1b; 如通用的缓存静态操作类、常用的Wpf的ValueConverters、内置的委托类型、通用的反射加载dll操作类、Wpf的ViewModel、Command、Navigation、Messenger、部分常用UserControls(可绑定的Passwo…

通信总线协议之CAN-FD协议详解

文章目录 通信总线之CAN-FD总线协议详解1. CAN-FD 简介1.1 什么是CAN FD1.2 CAN FD的特点 2. CAN-FD总线协议2.1 帧起始2.2 仲裁段2.3 控制段2.4 数据段2.5 CRC段2.6 ACK段2.7 帧结束 3. 如何从传统的CAN升级到CAN FD 通信总线之CAN-FD总线协议详解 1. CAN-FD 简介 1.1 什么是…

selenium高级应用

常见控件应用 复杂的控件操作1.操作Ajax选项2.滑动滑块操作 WebDriver的特殊操作元素class值包含空格property、attribute、text的区别定位动态id 截图功能页面截图页面截图&#xff0c;返回截图的二进制数据页面截图&#xff0c;返回base64的字符串截取指定元素。先定位元素&a…

Vue3:toRef和toRefs的用法

一、情景说明 我们知道&#xff0c;Vue3中想要定义对象类型的响应式数据 可以通过reactive函数实现 如果&#xff0c;后端返回的对象&#xff0c;有很多的字段&#xff0c;我们想进行结构化赋值 但是&#xff0c;又想保证赋值后的变量也是响应式数据 那么&#xff0c;这个时候…

算法进阶之路:十大经典排序算法详解与实践

算法进阶之路&#xff1a;十大经典排序算法详解与实践 在计算机科学的世界里&#xff0c;排序算法是基础且至关重要的一环。无论是数据库查询、数据分析还是日常的编程任务&#xff0c;高效的排序算法都能显著提升程序的性能。本文将带你深入了解十大经典排序算法&#xff0c;…

BeyondCompared4提示“缺少评估信息或损坏”修复

BeyondCompared4提示“缺少评估信息或损坏”修复 使用 beyond compare4&#xff0c;在安装的30天后&#xff0c;出现“缺少评估信息”、“评估信息损坏”的提示 解决方法如下&#xff08;Win11下亲测可行&#xff09; 按 WinR 进入 打开Windows命令运行框&#xff0c;输入cmd …

Redis常见数据类型下

目录 Hash 哈希 常用指令 HSET HGET HEXISTS HDEL HKEYS HVALS HGETALL HMGET 内部编码 Hash类型和关系型数据库 缓存方式对比 List 列表 特点 常用命令 LPUSH LPUSHX RPUSH RPUSHX LRANGE LPOP / RPOP LINDEX LINSERT 阻塞(BLOCK)版…

无人机避障技术

无人机避障技术是现代无人机系统发展的重要组成部分&#xff0c;其核心目标是提升无人机的自主飞行能力&#xff0c;确保其在复杂环境中的安全性。本文将详细介绍无人机避障项目的背景、技术原理、实现过程、应用前景以及面临的挑战&#xff0c;以期为读者提供全面而深入的了解…

【Linux】文件缓冲区|理解文件系统

目录 预备知识 观察现象 第一&#xff1a;携带\n&#xff0c;不使用fork()&#xff0c;打印到显示器 第二&#xff1a;携带\n&#xff0c;使用fork()&#xff0c;打印到显示器 第三&#xff1a;携带\n&#xff0c;使用fork()&#xff0c;打印到文件里 第四&#xff1a;不携…

Android Studio

深入探索集成开发环境的魅力 在数字化和移动化的浪潮下&#xff0c;Android系统凭借其广泛的覆盖范围和深度的定制性&#xff0c;已在全球范围内占据显著的市场份额。为了支撑这一庞大的生态系统&#xff0c;一个强大且灵活的集成开发环境&#xff08;IDE&#xff09;应运而生…

如何选择适合的G口大流量服务器?

G口大流量服务器是指接入互联网的带宽达到1Gbps及以上&#xff0c;并且能够提供大量数据传输服务的服务器。那么如何选择适合的G口大流量服务器&#xff0c;RAK部落小编为您整理发布选择适合的G口大流量服务器需要考虑哪些关键点。 选择适合的G口大流量服务器时&#xff0c;应该…

JavaSec 基础之 CC1 链

文章目录 背景环境以及配置分析0x1 终点(利用点分析)0x20x30x310x320x33 0x040x05 背景 Apache Commons Collections是Apache提供的一个Java库&#xff0c;它扩展了Java自带的集合框架。通过这个库&#xff0c;咱们可以使用更多种类的集合类型&#xff0c;以及各种实用的集合操…

星星魔方

星星魔方 1&#xff0c;魔方三要素 &#xff08;1&#xff09;组成部件 6个中心块和8个角块和三阶魔方同构&#xff0c;另外每个面还有构成五角星的十个块。 &#xff08;2&#xff09;可执行操作 一共12种操作&#xff0c;其中6种是每个层顺时针旋转90度&#xff0c;另外6…

HTML静态网页成品作业(HTML+CSS)——家乡漳州介绍设计制作(1个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有1个页面。 二、作品演示 三、代…

Python的特性——跟老吕学Python编程

Python的特性——跟老吕学Python编程 Python的特性1.Python易学易用2.Python是解释型语言3.Python是交互式的4.Python是一种多范式语言5.Python的标准库6.Python是开源的7.Python是跨平台的8.用于GUI应用程序的Python9.Python的数据库连接10.Python是可扩展的11.Python拥有活跃…

【golang】28、用 httptest 做 web server 的 controller 的单测

文章目录 一、构建 HTTP server1.1 model.go1.2 server.go1.3 curl 验证 server 功能1.3.1 新建1.3.2 查询1.3.3 更新1.3.4 删除 二、httptest 测试2.1 完整示例2.2 实现逻辑2.3 其他示例2.4 用 TestMain 避免重复的测试代码2.5 gin 框架的 httptest 一、构建 HTTP server 1.1…

ElementUI两个小坑

1.form表单绑定的是一个对象&#xff0c;表单里的一个输入项是对象的一个属性之一&#xff0c;修改输入项&#xff0c;表单没刷新的问题&#xff0c; <el-form :model"formData" :rules"rules" ref"editForm" class"demo-ruleForm"…

蓝牙耳机链接电脑莫名奇妙关机问题(QQ浏览器)

蓝牙耳机连接电脑听歌的时候&#xff0c;如果听歌软件是暴风影音&#xff0c;或者其它播放器&#xff0c;蓝牙不会自动关机&#xff0c;但如果是QQ浏览器&#xff0c;蓝牙耳机经常莫名其妙的关机&#xff0c;时间间隔忽长忽短&#xff0c;没有规律&#xff0c;解决办法就是重启…

翻硬币..

0翻硬币 - 蓝桥云课 (lanqiao.cn) 题目描述 小明正在玩一个"翻硬币”的游戏 桌上放着排成一排的若干硬币。我们用”表示正面&#xff0c;用o表示反面(是小写字母&#xff0c;不是零) 比如&#xff0c;可能情形是:**oo***o00 如果同时翻转左边的两个硬币&#xff0c;则变为…