方舟编译器分析十一——代码分析(九)

本文详细介绍了MapleME框架中MeCFG类的实现细节,包括其成员变量和函数,如BuildMirCFG、FixMirCFG等。MeCFG在MeFunction的Prepare阶段被创建和初始化,用于构建和分析控制流图,进行未到达代码分析、不会退出分析等优化。MeCFG的使用遵循了一套标准流程,对于理解MapleME的代码优化过程具有重要意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2021SC@SDUSC

历时好久的me_ir部分终于结束了,我也松了一口气,下面该换新内容了。

前文分析过,在MeFuncPhase类别的phase执行之前,要进行一系列的准备工作,其中有一部分工作就是和MeFunction的CFG有关。MeFunction的CFG实现,主要是通过MeCFG类来进行的实现,本文将对MeCFG的实现及使用进行一个简单的分析。

MeCFG的定义和实现是在文件src/maple_me/include/me_cfg.h 和 src/maple_me/src/me_cfg.cpp之中。

MeCFG只有两个成员变量:

private:
  MeFunction &func;
  bool hasDoWhile = false;

 func用于将MeCFG对应到一个具体的MeFunction。hasDoWhile用于表示是否有DoWhile,从目前已经公开的代码来看,属于冗余的成员变量,并没有被使用。

MeCFG的成员函数主要有:

void BuildMirCFG();
  void FixMirCFG();
  void ConvertPhis2IdentityAssigns(BB &meBB) const;
  void UnreachCodeAnalysis(bool updatePhi = false);
  void WontExitAnalysis();
  void Verify() const;
  void VerifyLabels() const;
  void Dump() const;
  void DumpToFile(const std::string &prefix, bool dumpInStrs = false) const;
  bool FindExprUse(const BaseNode &expr, StIdx stIdx) const;
  bool FindUse(const StmtNode &stmt, StIdx stIdx) const;
  bool FindDef(const StmtNode &stmt, StIdx stIdx) const;
  bool HasNoOccBetween(StmtNode &from, const StmtNode &to, StIdx stIdx) const;
  • BuildMirCFG构建MIR的控制流图;
  • FixMirCFG是修复MIR的控制流图;
  • ConvertPhis2IdentityAssigns将phi指令转化为明确的赋值(identify assignment);
  • UnreachCodeAnalysis未到达代码分析,主要分析从函数入口无法到达的BB,然后删除它们;
  • WontExitAnalysis分析查找不会到达函数退出位置的BB,然后为其添加不会退出标记,并为其创建可以到达comment_exit_bb的路径;
  • Verify检验MeFunction中的BB的属性和CFG属性都正常;
  • VerifyLabels检验Lable是否正确;
  • Dump和DumpToFile都是要dump出信息,只是方式不同;
  • FindExprUse查找表达式是否使用,具体来说就是stIdx(符号)是否在expr中使用;
  • FindUse查找stIdx(符号)是否在stmt之中使用;
  • FindDef查找stIdx(符号)是否在stmt之中定义;
  • HasNoOccBetween查找stIdx(符号)没有from到to中使用或者定义,没有的话返回true;这个成员函数要调用FindUse和FindDef来实现。

MeCFG在代码之中只在MeFunction之中使用。共有两个部分使用,第一个部分:

src/maple_me/include/me_function.h

MeCFG *GetTheCfg() {
    return theCFG;
  }

  void SetTheCfg(MeCFG *currTheCfg) {
    theCFG = currTheCfg;
  }

 获取或者设置MeFunction的MeCFG*类型的成员变量theCFG ,成员变量定义如下:

MeCFG *theCFG = nullptr;

MeCFG在MeFunction之中使用的第二个部分就是我们前面提到的为MeFunctionPhase运行做准备的过程之中,构建CFG:

src/maple_me/src/me_function.cpp

void MeFunction::Prepare(unsigned long rangeNum) {
  if (!MeOption::quiet) {
    LogInfo::MapleLogger() << "---Preparing Function  < " << CurFunction()->GetName() << " > [" << rangeNum
                           << "] ---\n";
  }
  /* lower first */
  MIRLower mirLowerer(mirModule, CurFunction());
  mirLowerer.Init();
  mirLowerer.SetLowerME();
  mirLowerer.SetLowerExpandArray();
  ASSERT(CurFunction() != nullptr, "nullptr check");
  mirLowerer.LowerFunc(*CurFunction());
  CreateBasicBlocks();
  if (NumBBs() == 0) {
    /* there's no basicblock generated */
    return;
  }
  RemoveEhEdgesInSyncRegion();
  theCFG = memPool->New<MeCFG>(*this);
  theCFG->BuildMirCFG();
  theCFG->FixMirCFG();
  theCFG->VerifyLabels();
  theCFG->UnreachCodeAnalysis();
  theCFG->WontExitAnalysis();
  theCFG->Verify();
}

 其中主要执行了这几步:

 theCFG = memPool->New<MeCFG>(*this);
  theCFG->BuildMirCFG();
  theCFG->FixMirCFG();
  theCFG->VerifyLabels();
  theCFG->UnreachCodeAnalysis();
  theCFG->WontExitAnalysis();
  theCFG->Verify();

其中第一条语句为theCFG 新建对象并申请空间,后续的操作我们在3中进行过介绍,主要是新建控制流图,然后各种分析和验证的过程。

值得注意的是,这个使用CFG的流程,就是方舟中CFG使用的标准流程。因为目前开源的地方,对于CFG的使用就此一处,我们就要以这个官方顺序为标准。后续源码全部开放,可以调试分析的时候可以再hack这里的验证顺序是否可以调整。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值