llvm中如何利用分支概率和基本块频率估计
1. 背景
llvm自2.9版以后,已经集成了对分支概率和基本块频率的静态分析。
分支概率(branch probability)是指在程序的控制流图中,从控制流从一个基本块A到其任意后继基本块Si的概率。控制流从基本块A到其所有后继基本块的概率之和为1. 基本块频率(block frequency)是指在程序的控制流图中,任意基本块的执行次数。这两种信息都可以通过静态分析得到。其原理如下【1】【2】:
An alternative is static profiling, in which a compiler estimates execution frequencies (not absolute counts) with static program analysis. A static profile eliminates the drawbacks of dynamic profiling— if it accurately captures a program’s dynamic behavior. Recent work suggests that static analysis can predict dynamic program behavior. Fisher and Freudenberger [Fisher-92] observed that many programs’ dynamic branching behavior is independent of their input data. Ball and Larus developed a simple algorithm that statically predicts the outcome of a conditional branch with good accuracy [Ball-93]. Wagner et al. usedl simple estimates of branch probabilities to compute static profiles [Wagner-94]. (见文献【2】)
2. llvm3.3中的相关文件
Support/BranchProbability.cpp(.h): 实现一个用来表示分支概率的数据结构
Analysis/BranchProbabilityInfo.cpp(.h): 实现一个在basic block级别进行分支概率估计的FunctionPass
CodeGen/MachineBranchProbabilityInfo.cpp(.h): 实现一个在machine basic block级别进行分支概率估计的ImmutablePass
Support/BlockFrequency.cpp(.h): 实现一个用来表示基本块频率的数据结构
Analysis/BlockFrequencyInfo.cpp(.h): 实现一个在basic block级别进行基本块频率估计的FunctionPass
CodeGen/MachineBlockFrequency.cpp(.h): 实现一个在machine basic block级别进行基本块频率估计的MachineFunctionPass
Analysis/BlockFrequencyImpl.h: 在basic block级别和machine basic block级别共用的基本块频率估计的实现
3. llvm3.3中的相关实现
3.1 分支概率分析
3.1.1 在basic block级别,分支概率分析的实现主要参考文献【2】的方法,利用几个基本启发式来给分支加权。
for (po_iterator<BasicBlock *> I = po_begin(&F.getEntryBlock()), E = po_end(&F.getEntryBlock()); I != E; ++I) {
DEBUG(dbgs() << "Computing probabilities for " << I->getName() << "\n");
if (calcUnreachableHeuristics(*I))
continue;
if (calcMetadataWeights(*I))
continue;
if (calcColdCallHeuristics(*I))
continue;
if (calcLoopBranchHeuristics(*I))
continue;
if (calcPointerHeuristics(*I))
continue;
if (calcZeroHeuristics(*I))
continue;
if (calcFloatingPointHeuristics(*I))
continue;
calcInvokeHeuristics(*I);
}
return false;
}
3.1.2 在machine basic block级别,分支概率的实现实际上依赖于basic block级别的分支概率分析结果,所以MachineBranchProbabilityInfo并不是一个独立的MachineFunctionPass.
3.2 基本块频率分析
3.2.1 在basic block级别和machine basic block级别共用基本块频率估计的实现
bool BlockFrequencyInfo::runOnFunction(Function &F) {
BranchProbabilityInfo &BPI = getAnalysis<BranchProbabilityInfo>();
BFI->doFunction(&F, &BPI);
return false;
}
bool MachineBlockFrequencyInfo::runOnMachineFunction(MachineFunction &F) {
MachineBranchProbabilityInfo &MBPI = getAnalysis<MachineBranchProbabilityInfo>();
MBFI->doFunction(&F, &MBPI);
return false;
}
3.2.2 上面的代码还可以看出,基本块频率分析依赖于分支概率分析。因此,如果要利用这两种分析结果,只需要在自己的FunctionPass或者MachineFunctionPass里面进行类似如下的修改(建议参考CodeGen/MachineBlockPlacement.cpp):
1)修改getAnalysisUsage函数如下:
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<MachineBranchProbabilityInfo>();
AU.addRequired<MachineBlockFrequencyInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
}
2)修改runOnMachineFunction函数如下
bool MachineBlockPlacement::runOnMachineFunction(MachineFunction &F) {
MBPI = &getAnalysis<MachineBranchProbabilityInfo>();
MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
...
//打印分支概率信息
std::string szInfo;
raw_fd_ostream S("machinBranchProbs.txt", szInfo, raw_fd_ostream::F_Append);
for (MachineFunction::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) {
MachineBasicBlock *MBB = BI;
for (MachineBasicBlock::const_succ_iterator SI =MBB->succ_begin(), EI = MBB->succ_end(); SI != EI; ++SI) {
MachineBasicBlock *mBlock = *SI;
MBPI->printEdgeProbability(S << " ", MBB, mBlock);
}
}
S.close();
//打印基本块频率信息
raw_fd_ostream S1("machinBlockFreq.txt", szInfo, raw_fd_ostream::F_Append);
if (MBFI) MBFI->print(S1);;
S1.close();
...
return false;
}
4. 参考文献:
llvm中如何利用分支概率和基本块频率估计的更多相关文章
- Git 分支-利用分支进行开发的工作流程
3.4 Git 分支 - 利用分支进行开发的工作流程 利用分支进行开发的工作流程 现在我们已经学会了新建分支和合并分支,可以(或应该)用它来做点什么呢?在本节,我们会介绍一些利用分支进行开发的工作流程 ...
- javascript基础入门之js中的结构分支与循环语句
javascript基础入门之js中的结构分支与循环语句 程序的结构①顺序结构:自上而下:②选择(分支)结构:多条路径,根据不同的条件,只执行其中一个:③循环结构:重复某些代码④配合特定的语句实现选择 ...
- git 操作 :从远程仓库gitLab上拉取指定分支到本地仓库;git如何利用分支进行多人开发 ;多人合作代码提交实践
例如:将gitLab 上的dev分支拉取到本地 git checkout -b dev origin/dev 在本地创建分支dev并切换到该分支 git pull origin dev 就可以把git ...
- Git中如何利用生成SSH个人公钥访问git仓库
Git中如何利用生成SSH个人公钥访问git仓库方法(这里以coding平台为例): 1. 获取 SSH 协议地址 在项目的代码页面点击 SSH 切换到 SSH 协议, 获得访问地址, 请使用这个地址 ...
- 开发与测试整体过程中的Git分支merge流程
开发与测试整体过程中的Git分支merge流程 Git分支merge之开发流程 首先在Gitlab上有个仓库存储着原始的项目代码,其中包含一个叫master的分支.然后可能按功能进行分配,由不同的开发 ...
- C/S模式开发中如何利用WebBrowser控件制作导航窗体
原文:C/S模式开发中如何利用WebBrowser控件制作导航窗体 转自: CSDN 相信不少同学们都做过MIS系统的开发,今天这里不讨论B/S模式开发的问题.来谈谈winform开发.用过市面上常见 ...
- CVE-2019-0797漏洞:Windows操作系统中的新零日在攻击中被利用
https://securelist.com/cve-2019-0797-zero-day-vulnerability/89885/ 前言 在2019年2月,卡巴实验室的自动漏洞防护(AEP)系统检测 ...
- Vuejs(14)——在v-for中,利用index来对第一项添加class
版权声明:出处http://blog.csdn.net/qq20004604 (1)在v-for中,利用index来对第一项添加class <a class="list-group-i ...
- Flex中如何利用FocusManager类的setFocus函数设置TextInput的焦点的例子
参考:https://blog.csdn.net/liruizhuang/article/details/5876455 <?xml version="1.0" encodi ...
随机推荐
- appium---【Mac】Appium-Doctor提示WARN:“ ios_webkit_debug_proxy cannot be found”解决方案
“ ios_webkit_debug_proxy cannot be found”报错截图如下: 解决方案: 打开terminal终端,分别输入执行结束,再次运行appium-doctor即可看到运行 ...
- day4装饰器
Python装饰器 1.必备 def foo(): print(foo) <function foo at 0x7f62db093f28> >>> foo <fun ...
- loadrunner 分用户日志
loadrunner 分用户日志 loadrunner在run脚本时,模拟多用户并发场景下,通常需要分别关注每个用户的脚本执行日志,可以按照以下操作进行: 在“Run Load Tests”中选择需要 ...
- Knockout介绍
Knockout.js是什么? Knockout是一款很优秀的JavaScript库,它可以帮助你仅使用一个清晰整洁的底层数据模型(data model)即可创建一个富文本且具有良好的显示和编辑功能的 ...
- 如何使用Bootstrap4显示和隐藏元素
如何使用Bootstrap4显示和隐藏元素 为了更快地进行移动设备开发,请使用响应式显示类来按设备显示和隐藏元素.避免创建相同站点的完全不同版本,而是相应地为每个屏幕大小隐藏元素. 要隐藏元素,只需使 ...
- DDL DML DCL DQL的区别
原文章出处:http://blog.csdn.net/tomatofly/article/details/5949070 SQL(Structure Query Language)语言是数据库的核心语 ...
- 爱奇艺全国高校算法大赛初赛C
区间$dp$. 倒着考虑这件事件,肯定有最后一个取走的数字,假设是$a[k]$,那么最后一次取走的价值肯定是$a[0]*a[k]*a[n+1]$,之前取走的价值和为$[1,k-1]$的价值加上$[k+ ...
- python3 爬虫之爬取安居客二手房资讯(第一版)
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author;Tsukasa import requests from bs4 import Beau ...
- Java synchronized的原理解析
开始 类有一个特性叫封装,如果一个类,所有的field都是private的,而且没有任何的method,那么这个类就像是四面围墙+天罗地网,没有门.看起来就是一个封闭的箱子,外面的进不来,里面的出不去 ...
- 使用JDBC连接数据库的一些BUG
题记:前几天用JDBC连接MYSQL数据库的时候,出现了一些BUG,有代码层次的,也有设置层次的, 下面的解决方法时我目前所遇到的,后期如果还有遇到的会进行补充. 一.出现:远程mysql_java. ...