LLVM 编译器学习笔记之二十七 -- EarlyCSE, PRE, LICM, hoist, Sink

1、在社区commit 2813acb7d1将m_Undef同时能识别undefs and poisons后,CSE 中SimplifyICmpInst就能对这些Undef比较的指令进行简化

注意:要求所有向量元素均是undefs 或者 poisons,详见上述patch中的undef_match

  // icmp X, X -> true/false
  // icmp X, undef -> true/false because undef could be X.
  if (LHS == RHS || Q.isUndefValue(RHS))
    return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred));

2、PRE 包括CSE和LICM, 基于GVN分析进行优化 .PRE is considered to be a powerful transformation because it subsumes a (full redundancy elimination) transformation like common subexpression elimination (CSE) and loop invariant code motion (LICM) [5].参考https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.96.4443&rep=rep1&type=pdf

3、PRE和向量化存在冲突,因为Pre创建了反向跨迭代依赖阻止了向量化 (向量化中循环结点不允许存在IV之外的PHI结点) 参考[loop vectorize] failure to vectorize after GVN load-pre · Issue #38583 · llvm/llvm-project · GitHub

4、在 commit bcdcf984cc 中切换默认的GVN方法,Use '-passes=newgvn' instead of '-basic-aa -newgvn'

5、不变量外提需要考虑寄存器压力,因此一些mov类指令会被认为增加寄存器压力而不外提,详见MachineLICM.cpp:IsProfitableToHoist. 但事实上,寄存器压力评估是不准确的,比如的寄存器压力实际并不大[optimization] use vector register to init const float value · Issue #53651 · llvm/llvm-project · GitHub

6、gvn-hoist需要阻止不同类型的loads (same source pointer)进行合并,参考D122521 

7、 MachineSinking::isProfitableToSinkTo 中决定指令是否需要sink?106268 – [suboptimal] Remove unnecessary loops releated to fortran compare to ifort

8、在LICM中,会根据MSSA、AAResult分析相关指令的alias信息,进而实现循环中store指令的外提, 参考collectPromotionCandidates

循环不变量外提需要依靠MemorySSA的分析结果,而MemorySSA分析也需要借助AliasAnalysis的结果

buildMemorySSA( ) -> 生成默认MemoryUse(value) -> optimizeUsesInBlock( ) (更新MemoryUse(value)的value值)-> ... -> instructionClobbersQuery( ) (调用AliasAnalysis获取信息查询指令的Clobber)
MemoryUse
(XX)对应的MemoryDef(XX)是初始默认的Def

9、增强不变量属性invariant的分析,commit 8d0383eb(非必须), 但并不意味着会外提?需要确保外提后没有寄存器压力的问题commit 645bdd4b69

SU(6): t62: nxv2f64,ch = LD1RD_IMM<Mem:(dereferenceable invariant load (s64)  

 注意:能外提的指令,显然是要求没有副作用hasUnmodeledSideEffects(),在isSafeToMove中判断(注:默认属性仅对signle pattern tablegen起效,参考D139637)

10、利用sink巧妙的解决vacale指令合并时跨BB不能优化的问题,钩子 shouldSinkOperands,参考PR70304;

11、在后端允许特定的指令hoist, 比如copy指令在寄存器分配时可能评估不合适,需要在寄存器分配后进行调整,参考PR71403

12、在https://github.com/llvm/llvm-project/pull/72187上有个启示,也就是对于循环不变量,并不一定能够自然外提。生成指令时需要插在合适的位置

13、一些类似指令合并的工作也可能在sink处理,因为可以额外考虑寄存器压力,参考D152828

    // add Xa, Xn, Wm, {s,u}xtw #N
    // ldr Xd, [Xa]   -- offset 使用1个寄存器
    // ->
    // ldr Xd, [Xn, Wm, {s,u}xtw #N]

14、找cse处理alias时, CallValue::canHandle 会处理read-only call

a) 通过isSameMemGeneration判断,如果和之前相同的访存操作是同一个CurrentGeneration则可以优化;

b) 通过AvailableCalls.insert(&Inst, std::make_pair(&Inst, CurrentGeneration))为指令标识合适的CurrentGeneration,从而实现流敏感的实现

c) fabs不涉及errno, 在EarlyCSE能优化重复的load; 但exp存在errno,即使增加tbaa信息(PR96025),也不会再此pass优化,而是在InstCombinePass中优化

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值