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()的4256行GlobalISelEmitter::gatherOpcodeValues()收集指令操作码的值。
3081 void GlobalISelEmitter::gatherOpcodeValues()
3082 InstructionOpcodeMatcher::initOpcodeValuesMap(Target);
3083
InstructionOpcodeMatcher的OpcodeValues是DenseMap<const CodeGenInstruction*, unsigned>类型的静态容器。在1554行getInstructionsByEnumValue()以这个次序返回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名字中的LLT是Low 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用于映射SDNode到GINodeEquiv,维护SDNode与指令间的等价性。它的类型是DenseMap<Record *, Record *>。
容器ComplexPatternEquivs用于维护ComplexPattern与GIComplexOperandMatcher间的等价性。它的类型也是 DenseMap<const Record *, const Record *>。
同理,容器SDNodeXFormEquivs用于维护SDNodeXForm与GICustomOperandRenderer间的等价性,类型仍然是DenseMap<const Record *, const Record *>。
它们都使用相应的SelectionDAG定义的Record对象作为键值。
以上是关于LLVM学习笔记(53)的主要内容,如果未能解决你的问题,请参考以下文章