LLVM学习笔记(53)

Posted wuhui_gdnt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LLVM学习笔记(53)相关的知识,希望对你有一定的参考价值。

3.11.2. 模式分析

GlobalISel是以DAG指令选择的TD定义处理与分析为基础的。因此,GlobalISelEmitter包含了一个CodeGenDAGPatterns类型的const成员CGP(一旦创建完成,就是只读的),在GlobalISelEmitter构造函数中将完成DAG指令选择令人眼花缭乱的准备工作(参考DAG指令选择器的生成代码一节,直到Match对象序列的优化为止),为GlobalISelEmitter准备好指令的PatternToMatch实例。在此基础上,GlobalISel将生成自己的指令匹配表。

在完成GlobalISelEmitter对象的构造后,立即调用下面的方法进行GlobalISel代码生成的处理。

4240  void GlobalISelEmitter::run(raw_ostream &OS)

4241    if (!UseCoverageFile.empty())

4242      RuleCoverage = CodeGenCoverage();

4243      auto RuleCoverageBufOrErr = MemoryBuffer::getFile(UseCoverageFile);

4244      if (!RuleCoverageBufOrErr)

4245        PrintWarning(SMLoc(), "Missing rule coverage data");

4246        RuleCoverage = None;

4247      else

4248        if (!RuleCoverage->parse(*RuleCoverageBufOrErr.get(), Target.getName()))

4249          PrintWarning(SMLoc(), "Ignoring invalid or missing rule coverage data");

4250          RuleCoverage = None;

4251       

4252     

4253   

4254 

4255    // Track the run-time opcode values

4256    gatherOpcodeValues();

4257    // Track the run-time LLT ID values

4258    gatherTypeIDValues();

4259 

4260    // Track the GINodeEquiv definitions.

4261    gatherNodeEquivs();

4262 

4263    emitSourceFileHeader(("Global Instruction Selector for the " +

4264                         Target.getName() + " target").str(), OS);

4265    std::vector<RuleMatcher> Rules;

4266    // Look through the SelectionDAG patterns we found, possibly emitting some.

4267    for (const PatternToMatch &Pat : CGP.ptms())

4268      ++NumPatternTotal;

4269 

4270      auto MatcherOrErr = runOnPattern(Pat);

4271 

4272      // The pattern analysis can fail, indicating an unsupported pattern.

4273      // Report that if we've been asked to do so.

4274      if (auto Err = MatcherOrErr.takeError())

4275        if (WarnOnSkippedPatterns)

4276          PrintWarning(Pat.getSrcRecord()->getLoc(),

4277                       "Skipped pattern: " + toString(std::move(Err)));

4278        else

4279          consumeError(std::move(Err));

4280       

4281        ++NumPatternImportsSkipped;

4282        continue;

4283     

4284 

4285      if (RuleCoverage)

4286        if (RuleCoverage->isCovered(MatcherOrErr->getRuleID()))

4287          ++NumPatternsTested;

4288        else

4289          PrintWarning(Pat.getSrcRecord()->getLoc(),

4290                       "Pattern is not covered by a test");

4291     

4292      Rules.push_back(std::move(MatcherOrErr.get()));

4293   

​​​​​​​3.11.2.1. 准备工作

这实际上就是所谓的SelectionDAG定义的导入。

GlobalISelEmitter::run()4256GlobalISelEmitter::gatherOpcodeValues()收集指令操作码的值。

3081  void GlobalISelEmitter::gatherOpcodeValues()

3082   InstructionOpcodeMatcher::initOpcodeValuesMap(Target);

3083 

InstructionOpcodeMatcherOpcodeValuesDenseMap<const CodeGenInstruction*, unsigned>类型的静态容器。在1554getInstructionsByEnumValue()以这个次序返回CodeGenInstruction对象:

TargetOpcodes.def文件中声明的固定/通用指令

按名字字母序排序的伪指令

按名字字母序排序的其他指令

1550    static void initOpcodeValuesMap(const CodeGenTarget &Target)

1551      OpcodeValues.clear();

1552 

1553      unsigned OpcodeValue = 0;

1554      for (const CodeGenInstruction *I : Target.getInstructionsByEnumValue())

1555        OpcodeValues[I] = OpcodeValue++;

1556   

接着,调用GlobalISelEmitter::gatherTypeIDValues()收集相关的类型信息:

3085  void GlobalISelEmitter::gatherTypeIDValues()

3086    LLTOperandMatcher::initTypeIDValuesMap();

3087 

LLTOperandMatcher的静态容器TypeIDValues的类型是std::map<LLTCodeGen, unsigned> 而全局容器KnownTypes的类型是std::set<LLTCodeGen>KnownTypes是由LLTOperandMatcher构造函数填充的,目前尚未调用LLTOperandMatcher构造函数,因此下面1134行循环在这里不会执行。initTypeIDValuesMap()另外的调用机会在LLTOperandMatcher::hasValue()里:

1156    bool hasValue() const override

1157      if (TypeIDValues.size() != KnownTypes.size())

1158        initTypeIDValuesMap();

1159      return TypeIDValues.count(Ty);

1160   

这里才是保证TypeIDValues反映已知类型的所在。

LLTCodeGen名字中的LLTLow Level Type的缩写,这个类只有一个LLT类型的数据成员,它用于辅助输出GlobalISel生成代码中与LLT相关的代码。

1130    static void initTypeIDValuesMap()

1131      TypeIDValues.clear();

1132 

1133      unsigned ID = 0;

1134      for (const LLTCodeGen LLTy : KnownTypes)

1135        TypeIDValues[LLTy] = ID++;

1136   

接着,在GlobalISelEmitter::run()4261行调用GlobalISelEmitter::gatherNodeEquivs()SDNode节点与等价的GlobalISel节点关联起来:

3103  void GlobalISelEmitter::gatherNodeEquivs()

3104    assert(NodeEquivs.empty());

3105    for (Record *Equiv : RK.getAllDerivedDefinitions("GINodeEquiv"))

3106      NodeEquivs[Equiv->getValueAsDef("Node")] = Equiv;

3107 

3108    assert(ComplexPatternEquivs.empty());

3109    for (Record *Equiv : RK.getAllDerivedDefinitions("GIComplexPatternEquiv"))

3110      Record *SelDAGEquiv = Equiv->getValueAsDef("SelDAGEquivalent");

3111      if (!SelDAGEquiv)

3112        continue;

3113      ComplexPatternEquivs[SelDAGEquiv] = Equiv;

3114 

3115 

3116  assert(SDNodeXFormEquivs.empty());

3117  for (Record *Equiv : RK.getAllDerivedDefinitions("GISDNodeXFormEquiv"))

3118     Record *SelDAGEquiv = Equiv->getValueAsDef("SelDAGEquivalent");

3119     if (!SelDAGEquiv)

3120       continue;

3120     SDNodeXFormEquivs[SelDAGEquiv] = Equiv;

3120 

3120 

GlobalISelEmitter的容器NodeEquivs用于映射SDNodeGINodeEquiv,维护SDNode与指令间的等价性。它的类型是DenseMap<Record *, Record *>

容器ComplexPatternEquivs用于维护ComplexPatternGIComplexOperandMatcher间的等价性。它的类型也是  DenseMap<const Record *, const Record *>

同理,容器SDNodeXFormEquivs用于维护SDNodeXFormGICustomOperandRenderer间的等价性,类型仍然是DenseMap<const Record *, const Record *>

它们都使用相应的SelectionDAG定义的Record对象作为键值。

以上是关于LLVM学习笔记(53)的主要内容,如果未能解决你的问题,请参考以下文章

LLVM学习笔记(52)

LLVM学习笔记(52)

LLVM学习笔记(43-2)

LLVM学习笔记(54)

LLVM学习笔记(54)

LLVM学习笔记(44-2)