方舟编译器分析十四——代码分析(十二)

2021SC@SDUSC

ssa是MeFuncPhase类的phase之一,是除了ssaTab之外,和ssa相关的第二个phase。它在phases.def中,排在ssaTab和aliasclass之后。前文已经分析过了ssaTab,本文将就ssa做一个简要的分析。

1、ssa对应的实现类是MeDoSSA,MeDoSSA继承自MeFuncPhase。其定义和实现的位置为src/maple_me/include/me_ssa.h和src/maple_me/src/me_ssa.cpp。

2、MeDoSSA的Run函数的实际返回值是MeSSA类型的指针。MeSSA和MeDoSSA定义在同个头文件之中,它继承自SSA和AnalysisResult 。

class MeSSA : public maple::SSA, public AnalysisResult {

其中,SSA的定义和实现位于src/maple_me/include/ssa.h和src/maple_me/src/ssa.cpp。

MeSSA之中也定义了一个PhaseName

std::string PhaseName() const {
    return "ssa";
  }

 

正常这个应该是不因该存在的。因为MeSSA并不是一个phase,它只是用来实现MeDoSSA的分析结果的。PhaseName应该是一个phase的必备,但不应该是一个返回类所需要的。所以此点需要持续关注。MeAliasClass也有这个情况。

MeDoSSA的所做的工作是构建MeFunction的SSA形式。在构建函数的SSA形式之前,需要已经获取了函数的支配树以及BB的支配边界。关于支配树和支配边界的相关背景知识,推荐文章:https://blog.csdn.net/dashuniuniu/article/details/52224882。而支配树以及支配边界相关的操作,实际上是在dominance这个phase里实现的相关操作。

dominance这个phase,主要是分析MeFunction的控制流图,采用 Keith Cooper的算法来生成支配树和支配边界,这都是为了插入phi节点做准备。(Keith Cooper就是《Engineering a Compiler》的作者)dominance对应的实现类是MeDoDominance,它的定义和实现是src/maple_me/include/me_dominance.h和src/maple_me/src/me_dominance.cpp。

需要注意的是,dominance这个phase虽然在源码之中定义并实现了,但是它并没有注册在phases.def之中。但是它又是ssa所必须的前提,所以phases.def里列的phase列表,并不足以构成一个完整的执行phase序列。

MeDoSSA的所做的工作是构建函数的SSA形式,其工作可以分为两步:

  • 插入phi节点;
  • 重命名先序遍历支配树所遇到的每个定义和使用的符号。

src/maple_me/src/me_ssa.cpp中有注释详细描述该过程:

 

 This phase builds the SSA form of a function. Before this we have got the dominator tree
   and each bb's dominance frontiers. Then the algorithm follows this outline:

   Step 1: Inserting phi-node.
   With dominance frontiers, we can determine more
   precisely where phi-node might be needed. The basic idea is simple.
   A definition of x in block b forces a phi-node at every node in b's
   dominance frontiers. Since that phi-node is a new definition of x,
   it may, in turn, force the insertion of additional phi-node.

   Step 2: Renaming.
   Renames both definitions and uses of each symbol in
   a preorder walk over the dominator tree. In each block, we first
   rename the values defined by phi-node at the head of the block, then
   visit each stmt in the block: we rewrite each uses of a symbol with current
   SSA names(top of the stack which holds the current SSA version of the corresponding symbol),
   then it creates a new SSA name for the result of the stmt.
   This latter act makes the new name current. After all the stmts in the
   block have been rewritten, we rewrite the appropriate phi-node's
   parameters in each cfg successor of the block, using the current SSA names.
   Finally, it recurs on any children of the block in the dominator tree. When it
   returns from those recursive calls, we restores the stack of current SSA names to
   the state that existed before the current block was visited.

MeDoSSA的Run函数使用了ssaTab phase。 

AnalysisResult *MeDoSSA::Run(MeFunction *func, MeFuncResultMgr *funcResMgr, ModuleResultMgr *moduleResMgr) {
  auto *dom = static_cast<Dominance*>(funcResMgr->GetAnalysisResult(MeFuncPhase_DOMINANCE, func));
  CHECK_FATAL(dom != nullptr, "dominance phase has problem");
  auto *ssaTab = static_cast<SSATab*>(funcResMgr->GetAnalysisResult(MeFuncPhase_SSATAB, func));
  CHECK_FATAL(ssaTab != nullptr, "ssaTab phase has problem");
  MemPool *ssaMp = NewMemPool();
  MeSSA *ssa = ssaMp->New<MeSSA>(func, dom, ssaMp);
  ssa->BuildSSA();
  ssa->VerifySSA();
  if (DEBUGFUNC(func)) {
    ssaTab->GetVersionStTable().Dump(&ssaTab->GetModule());
  }
  return ssa;
}

 ssa本身并不是十分复杂,主要是完成MeFunction的SSA插入phi节点和重命名的操作。但是,ssa依赖于ssaTab和dominance这两个phase,所以其实要将三个phase一起理解,这样就相对复杂了一些。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值