LLVM 编译器学习笔记之三十六-- 指令调度Instruction scheduling

📅 2026/7/5 21:35:08 👁️ 阅读次数 📝 编程学习
LLVM 编译器学习笔记之三十六-- 指令调度Instruction scheduling

1、参考Instruction scheduling in LLVM - 知乎,在中、后端均存在指令调度

     https://www.youtube.com/watch?v=cWLW0aQwFg0&t=922s

GenericScheduler:: 做寄存器压力感知的指令调度

PostGenericScheduler:: 寄存器分配后的指令调度,基于BB的指令调度

 2、在llvm12->llvm14 中Machine Instruction Scheduler有个patch af342f7240增强了load/store指令的合并,也就是指令调度不仅仅只是改变指令的顺序,该优化类似gcc中的store-merge优化

注意:后端isPairableLdStInst接口可以指示是否允许寄存器对的优化,一般来说这个合并是有利的,也不能排除个别硬件存在bug

3、指令调度*.P指Pend, *.A为ready的指令,调度时从Bot和Top两端选取,最后将在某个中间位置相遇时结束调度;另外BotQ.A中的指令会被优先考虑发射(P 代表Pending, A 代表Available, 参考SchedBoundary::pickOnlyChoice)

4、指令中隐式的定义需要被列在let Defs = []中,参考⚙ D123578 [RISCV] Add sched to pseudo function call instructions

let isCall = 1, Defs = [LR, X0, X1], hasSideEffects = 1, Size = 16, isCodeGenOnly = 1 in def TLSDESC_CALLSEQ : Pseudo<(outs), (ins i64imm:$sym), [(AArch64tlsdesc_callseq tglobaltlsaddr:$sym)]>, Sched<[WriteI, WriteLD, WriteI, WriteBrReg]>;

AArch64::TLSDESC_CALLSEQ lower to

adrp  x0, :tlsdesc:var

ldr  x1, [x0, #:tlsdesc_lo12:var]

add   x0, x0, #:tlsdesc_lo12:var

blr   x1 # bl 指令会将程序的返回地址放到LR寄存器中 

5、 乱序执行OOO也需要进行指令调度优化,不是任意顺序性能都一样的

硬件有一个instruction window, 假如这个window无限大,compiler不管怎么写指令都无所谓。但实际上这个window只有80-100个指令,所以当有很深的parallel loop时,compiler如何写指令就会对性能有影响了

6、实现指令调度,确保stp指令按照升序排列输出(寄存器分配后的指令调度简单从ReadyQueue队列中获取一个指令,然后和当前Cand进行比较,如果需要调整即更新Cand, 因此pickNodeFromQueue函数返回后Cand值即为最优先需要发射的指令)

⚙ D125377 [AArch64] Order STP Q's by ascending address (llvm.org)

注意:指令调度的模型SchedModel=mf.getSubtarget()和后端架构配置相关

7、 在-mattr=+slow-paired-128选项说明128位的loadstore不好可能是一个共性问题,commit 7784cacd9,涉及AArch64InstrInfo::isCandidateToMergeOrPair函数

 203 def FeatureSlowPaired128 : SubtargetFeature<"slow-paired-128",
 204     "Paired128IsSlow", "true", "Paired 128 bit loads and stores are slow">;

usage:clang  -Xclang -target-feature -Xclang+slow-paired-128 或者llc -mattr=+slow-paired-128

代码中选项使用方法,参考MF.getSubtarget<AArch64Subtarget>().hardenSlsBlr() (注:需要头文件#include "AArch64Subtarget.h")

8、指令调度模型在 llvm/lib/Target/AArch64/AArch64.td中设置,参考D89972 (之后在D120906中进行了重构),也就是当前指定使用ProcTSV110对应的模型配置

当仅仅使用 -march=armv8.2-a 未指定tsv110时