LLVM Spiller 关键代码剖析

本文深入剖析LLVM Spiller的关键函数,包括spill、spillAll和spillAroundUses。详细解释了如何处理虚拟寄存器的溢出、栈槽分配、重定义点以及插入spill代码的过程,涉及LiveRangeEdit类、rematerialization和snippet的处理。
摘要由CSDN通过智能技术生成

LLVM Spiller
spill 函数

void InlineSpiller::spill(LiveRangeEdit &edit) {
   
  ++NumSpilledRanges;
  Edit = &edit;
  assert(!TargetRegisterInfo::isStackSlot(edit.getReg()) && "Trying to spill a stack slot.");
  // Share a stack slot among all descendants of Original.
  Original = VRM.getOriginal(edit.getReg());
  StackSlot = VRM.getStackSlot(Original);
  StackInt = nullptr;

  DEBUG(dbgs() << "Inline spilling "
               << TRI.getRegClassName(MRI.getRegClass(edit.getReg()))
               << ':' << edit.getParent()
               << "\nFrom original " << PrintReg(Original) << '\n');
  assert(edit.getParent().isSpillable() &&
         "Attempting to spill already spilled value.");
  assert(DeadDefs.empty() && "Previous spill didn't remove dead defs");

  collectRegsToSpill();
  analyzeSiblingValues();
  reMaterializeAll();

  // Remat may handle everything.
  if (!RegsToSpill.empty())
    spillAll();

  Edit->calculateRegClassAndHint(MF, Loops, MBFI);
}

分析:
函数参数:LiveRangeEdit 类用于表示对虚拟寄存器进行 spill 或是 split 时发生的改变。LiveRangeEdit 类有两个成员对象要说明一下:1. LiveInterval *Parent,这个对象表示原始的父虚拟寄存器所在的活跃区间;2. SmallVectorImpl< unsigned > &NewRegs,当父虚拟寄存器的生命期发生 split 时会产生新的子生命期,也就是新的子虚拟寄存器。
第 2 行:NumSpilledRanges 表示溢出的生命期数目,不管后面是否实际插入了 spill 代码,还是通过别的手段避免插入 spill 代码,该生命期都已经溢出了,要加1。
第 4 行:edit.getReg() 获得的是此 LiveRangeEdit 对象的父虚拟寄存器,如果判断出它本身就是栈槽,显然不需要再进行spill,直接报错。
第 6 行:获得初始的虚拟寄存器。如果该父虚拟寄存器没有被 split 过,Original 就是它本身。如果该父虚拟寄存器被 split 过,那么 Original 则是它被 split 前的虚拟寄存器。
第 7 行:返回本 LiveRangeEdit 类对象的虚拟寄存器所在的栈槽。由于 Original 始终是最开始的虚拟寄存器,显然对于所有从 Original 分割出去的虚拟寄存器而言,都映射到了同一个栈槽里。
第 8 行:StackInt 表示当前栈槽对应的活跃区间(StackSlot Interval)。
第 18 行:本函数用于处理 snippet,snippet 是仅仅只有一次实际 use 的生命期。
第 19、20 行:处理可以通过 rematerialization 过程避免 spill 的情况。
第 23 行:RegsToSpill 在 collectRegsToSpill 中收集了数据(snippets + 本身),如果没有snippets,RegsToSpill 仅有一个数据,即父虚拟寄存器。
spillAll 函数

/// spillAll - Spill all registers remaining after rematerialization.
void InlineSpiller::spillAll() {
   
  // Update LiveStacks now that we are committed to spilling.
  if (StackSlot == VirtR
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值