Early if-conversion - 优化阅读笔记

news/2024/6/29 11:51:39 标签: 编译器

Early if-conversion 用于对于没有很多可预测指令的乱序CPU。目标是消除可能误预测的条件分支。

来自分支两侧的指令都会被推测性地执行,并使用 cmov 指令选择结果。

// SSAIfConv 类在确定可能的情况下,对SSA形式的机器码执行if-conversion。该类不包含任何启发式方法;
// 外部代码应该用于确定何时进行 if-conversion 是个好主意。
//
// SSAIfConv 可以转换三角形和菱形:
//
//   三角形:    Head              菱形:    Head
//              | \                       /  \_
//              |  \                     /    |
//              |  [TF]BB              FBB    TBB
//              |  /                     \    /
//              | /                       \  /
//             Tail                       Tail
//
// 条件块TBB和/或FBB中的指令被插入到Head块中,Tail块中的phi指令被转换为select指令。

按支配树的后序遍历访问块。后序遍历允许在单次遍历中进行嵌套的if转换。tryConvertIf() 函数可能会擦除块,但仅擦除由头块支配的块。这使得在后序遍历迭代器仍然活动时更新支配树是安全的。

./BiShengKernel/build3/bin/llc -debugify-and-strip-all-safe < ./BiShengKernel/llvm/test/CodeGen/AArch64/arm64-early-ifcvt.ll -stress-early-ifcvt -aarch64-enable-atomic-cfg-tidy=0 -stop-before=early-ifcvt -o 1.mir
./BiShengKernel/build3/bin/llc -debugify-and-strip-all-safe < ./BiShengKernel/llvm/test/CodeGen/AArch64/arm64-early-ifcvt.ll -stress-early-ifcvt -aarch64-enable-atomic-cfg-tidy=0 -stop-after=early-ifcvt -o 2.mir

./build3/bin/llc -run-pass=dot-machine-cfg 1.mir
dot .mm2.dot -T svg -o 1.mm2.dot.svg
./build3/bin/llc -run-pass=dot-machine-cfg 2.mir
dot .mm2.dot -T svg -o 2.mm2.dot.svg

在这里插入图片描述

; Function Attrs: nounwind ssp memory(read) uwtable
define i32 @mm2(ptr nocapture %p, i32 %n) #0 {
entry:
  br label %do.body

do.body:                          ; preds = %do.cond, %entry
  ...
  br i1 %cmp, label %do.cond, label %if.else

if.else:                          ; preds = %do.body
  ...
  br label %do.cond

do.cond:                          ; preds = %if.else, %do.body
  ...
  br i1 %tobool, label %do.end, label %do.body

do.end:                           ; preds = %do.cond
  %sub = sub nsw i32 %max.1, %min.1
  ret i32 %sub
}

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

类似C语言:

int32_t mm2(int32_t *p, int32_t n) {
  for(max=0,min=0; n != 0; n--) {
    p = p + 1;
    int32_t p0 = *p;
    if (p0 > max) {
      max = p0;
    } else {
      min = (p0 < min) ? p0 : min;
    }
  }
  return max - min;
}
// 转换为: 
int32_t mm2(int32_t *p, int32_t n) {
  for(max=0,min=0; n != 0; n--) {
    p = p + 1;
    int32_t p0 = *p;
    int32_t tmp = p0 < min ? p0 : min;
    max = p0 > max ? p0 : max;
    min = p0 > max ? min : tmp;
  }
  return max - min;
}

在 MIR 的表示:
在这里插入图片描述

几个重要的接口:

SSAIfConv::canConvertIf(..) {
  // ...
  TII->analyzeBranch(*Head, TBB, FBB, Cond); // llvm/lib/Target/AArch64/AArch64InstrInfo.cpp:266
  // ...
  if (!TII->canInsertSelect(*Head, Cond, PI.PHI->getOperand(0).getReg(),
                              PI.TReg, PI.FReg, PI.CondCycles, PI.TCycles,
                              PI.FCycles)) {}

    // canPredicateInstrs - 如果 MBB 中的所有指令都可以安全地作为谓词,则返回true。不考虑终结指令。
    /// 如果指令使用了在头基本块中定义的任何值,则将定义这些值的指令添加到InsertAfter中。
    //
    // 任何被破坏的寄存器单元都将添加到 ClobberedRegUnits 中。
    SSAIfConv::canPredicateInstrs(MachineBasicBlock *MBB);
    // canSpeculateInstrs - 如果MBB中的所有指令都可以安全地进行推测,则返回true。不考虑终结指令。
    // 如果指令使用了在头基本块中定义的任何值,则将定义这些值的指令添加到InsertAfter中。
    //
    // 任何被破坏的寄存器单元都将添加到 ClobberedRegUnits 中。
    SSAIfConv::canSpeculateInstrs(MachineBasicBlock *MBB);


}

http://www.niftyadmin.cn/n/5423977.html

相关文章

辽宁政采网供应商招募时间?

辽宁政采网上商城招募的供应商的时间并不固定&#xff0c;而是根据辽宁省财政厅的具体政策进行招募的。基本上是每年招募一批&#xff0c;但具体的招募时间会根据年度政策有所调整。 以2023年为例&#xff0c;辽宁省财政厅曾在2023年2月27日至3月17日公开征集辽宁省政府采购网…

HDOJ2031

进制转换 Problem Description 输入一个十进制数N&#xff0c;将它转换成R进制数输出。 Input 输入数据包含多个测试实例&#xff0c;每个测试实例包含两个整数N(32位整数)和R&#xff08;2<R<16, R<>10&#xff09;。 Output 为每个测试实例输出转换后的数&…

动态加载类LoadClass 打包后资源缺失 的解决方案

一.出现错误 献上代码&#xff0c;在我自己的PlayerController里。加载继承了我C类的Widget void AMyPlayerController::BeginPlay() {Super::BeginPlay();FString WidgetClassLoadPath FString(TEXT("/Script/UMGEditor.WidgetBlueprint/Game/GameUI/UMG_Widget.UMG_W…

实时查询银行卡归属地的API接口,快速获取卡片发卡地信息

快速查询银行卡发卡地信息是一项非常实用的功能&#xff0c;对于进行业务合作、风险评估等方面都有很大的帮助。在本文中&#xff0c;我们将介绍一个实时查询银行卡归属地的API接口&#xff0c;并提供相应的代码示例。 该API接口可以通过输入银行卡号&#xff0c;查询该卡片的…

C++11 std::thread

std::thread std::thread是一个用于创建和管理线程的类。它可以让程序在多个并发执行的线程中执行不同的任务。下面是std::thread的一些常用用法介绍&#xff1a; 创建线程&#xff1a; void myFunction(int arg1, double arg2) {// 线程执行的代码 } std::thread t(myFunct…

【学习笔记】VMware vSphere 6.7虚拟化入门

VMware vSphere 6.7虚拟化入门课程介绍 课程内容 1、VMware vSphere 6.7虚拟化入门课程介绍 2、ESXi6.7控制台设置 3、使用vSpkere Host client管理虚拟机 4、VMware EsXi基础操作 5、VMware Esxi存储管理 6、管理ESXi主机网络与虚拟机网络 7、安装配置vCenter Server Applia…

面试官让我讲讲Mybatis-Plus有哪些牛逼功能

文章目录 日志主键生成策略自动填充创建时间与更新时间是否添加乐观锁字段分页插件逻辑删除性能分析插件 Mybatis-Plus是一款插件&#xff0c;用于增强Mybais框架&#xff0c;logo类似于魂斗罗中的两兄弟。所以在 Mybatis与Mybatis-Plus是可以共存的。Mybatis-Plus中的每个Map…

git撤回代码提交commit或者修改commit提交注释

执行commit后&#xff0c;还没执行push时&#xff0c;想要撤销之前的提交commit 撤销提交 使用命令&#xff1a; git reset --soft HEAD^命令详解&#xff1a; HEAD^ 表示上一个版本&#xff0c;即上一次的commit&#xff0c;也可以写成HEAD~1 如果进行两次的commit&#xf…