3.4. DAG指令选择器的生成代码
3.4.1. 概述
选项-gen-dag-isel用于产生DAG指令选择器,处理这个选项的入口在EmitDAGISel()。TableGen首先根据对指令的描述,为指令定义中的匹配模板(亦称源模板,它指出长怎么样的IR代码片段能匹配这条指令)以及结果模板(它指出匹配成功后指令应该输出怎样的结果,这个结果包含隐含的寄存器的变化)构建DAG实例(下文的展开的TreePatternNode图)。然后根据这两个DAG的结构产生一系列Matcher对象。所有指令所生成的Matcher对象都被串接起来。之后遍历这些Matcher对象,TableGen将输出一张表。函数SelectCodeCommon()将根据这张表进行指令选择。
170 void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS) {
171 DAGISelEmitter(RK).run(OS);
172 }
参数RK就是保存了所有class与def定义的Record实例的容器。171行首先构造了一个临时的DAGISelEmitter实例。
29 explicit DAGISelEmitter(RecordKeeper &R) : CGP(R) {}
3.4.1. CodeGenDAGPatterns对象
CGP是一个CodeGenDAGPatterns对象,顾名思义这是生成DAG模式处理代码的对象,这个对象在构造函数里完成了输出代码前几乎所有的处理。
2347 CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R,
PatternRewriterFn PatternRewriter) : <-- v7.0增加,缺省为null
2348 Records(R), Target(R),
LegalVTS(Target.getLegalValueTypes()), PatternRewriter(PatternRewriter) { ß v7.0增加
2349
2350 Intrinsics = LoadIntrinsics(Records, false); <-- v7.0删除
2351 TgtIntrinsics = LoadIntrinsics(Records, true);
Intrinsics = CodeGenIntrinsicTable(Records, false); <-- v7.0增加
TgtIntrinsics = CodeGenIntrinsicTable(Records, true);
2352 ParseNodeInfo();
2353 ParseNodeTransforms();
2354 ParseComplexPatterns();
2355 ParsePatternFragments();
2356 ParseDefaultOperands();
2357 ParseInstructions();
2358 ParsePatternFragments(/*OutFrags*/true);
2359 ParsePatterns();
2360
2361 // Generate variants. For example, commutative patterns can match
2362 // multiple ways. Add them to PatternsToMatch as well.
2363 GenerateVariants();
2364
// Break patterns with parameterized types into a series of patterns,
// where each one has a fixed type and is predicated on the conditions
// of the associated HW mode.
ExpandHwModeBasedTypes(); <-- v7.0增加
2365 // Infer instruction flags. For example, we can detect loads,
2366 // stores, and side effects in many cases by examining an
2367 // instruction's pattern.
2368 InferInstructionFlags();
2369
2370 // Verify that instruction flags match the patterns.
2371 VerifyInstructionFlags();
2372 }
2350与2351行的LoadIntrinsics()(v7.0是CodeGenIntrinsicTable())从固有函数的Record实例生成对应的CodeGenIntrinsic对象。在这里我们不深入其中的细节。维基百科Intrinsic function条目下详细解释了固有函数,简单来说,编译器完全理解固有函数的语义,能更好地生成这些函数的优化代码。LLVM兼容GCC,提供了大量的固有函数(http://llvm.org/docs/LangRef.html#instruction-reference里给出了一个详细列表,但不完全)。
V7.0在初始化列表中调用了CodeGenTarget的getLegalValueTypes()方法来获取合法类型: 124 ArrayRef 125 if (LegalValueTypes.empty()) 126 ReadLegalValueTypes(); 127 return LegalValueTypes; 128 } 方法ReadLegalValueTypes()收集所有寄存器类支持的类型。其中成员容器LegalValueTypes的类型是mutable SmallVector 312 void CodeGenTarget::ReadLegalValueTypes() const { 313 for (const auto &RC : getRegBank().getRegClasses()) 314 LegalValueTypes.insert(LegalValueTypes.end(), RC.VTs.begin(), RC.VTs.end()); 315 316 // Remove duplicates. 317 llvm::sort(LegalValueTypes.begin(), LegalValueTypes.end()); 318 LegalValueTypes.erase(std::unique(LegalValueTypes.begin(), 319 LegalValueTypes.end()), 320 LegalValueTypes.end()); 321 } 得到的合法类型在CodeGenDAGPatterns实例里保存在LegalVTS成员中(TypeSetByHwMode类型),并调用下面的构造函数: 67 TypeSetByHwMode::TypeSetByHwMode(ArrayRef 68 for (const ValueTypeByHwMode &VVT : VTList) 69 insert(VVT); 70 } TypeSetByHwMode是InfoByHwMode 100 bool TypeSetByHwMode::insert(const ValueTypeByHwMode &VVT) { 101 bool Changed = false; 102 SmallDenseSet 103 for (const auto &P : VVT) { 104 unsigned M = P.first; 105 Modes.insert(M); 106 // Make sure there exists a set for each specific mode from VVT. 107 Changed |= getOrCreate(M).insert(P.second).second; 108 } 109 110 // If VVT has a default mode, add the corresponding type to all 111 // modes in "this" that do not exist in VVT. 112 if (Modes.count(DefaultMode)) { 113 MVT DT = VVT.getType(DefaultMode); 114 for (auto &I : *this) 115 if (!Modes.count(I.first)) 116 Changed |= I.second.insert(DT).second; 117 } 118 return Changed; 119 } 上面103行循环首先记录硬件模式,然后插入对应的类型。getOrCreate()方法是这样的: 201 SetType &getOrCreate(unsigned Mode) { 202 if (hasMode(Mode)) 203 return get(Mode); 204 return Map.insert({Mode,SetType()}).first->second; 205 } Map就是基类InfoByHwMode中的std::map 85 InfoT &get(unsigned Mode) { 86 if (!hasMode(Mode)) { 87 assert(hasMode(DefaultMode)); 88 Map.insert({Mode, Map.at(DefaultMode)}); 89 } 90 return Map.at(Mode); 91 } 回到TypeSetByHwMode::insert()的107行,方法getOrCreate()返回后调用的insert()方法来自MachineValueTypeSet: 92 std::pair 93 bool V = count(T.SimpleTy); 94 Words[T.SimpleTy / WordWidth] |= WordType(1) << (T.SimpleTy % WordWidth); 95 return {*this, V}; 96 } Words就是MachineValueTypeSet中记录MVT的256位。 |
3.4.2.1. SDNode的处理
在TD文件里SDNode表示SelectionDAG的节点,代表操作的类型。TableGen通过下面一系列的方法,根据SDNode的Record实例,获取对应的SDNodeInfo与SDTypeConstraint对象。这两个类型的定义如下:
169 struct SDTypeConstraint {
170 SDTypeConstraint(Record *R);
171
172 unsigned OperandNo; // The operand # this constraint applies to.
173 enum {
174 SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
175 SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec,
176 SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs
177 } ConstraintType;
178
179 union { // The discriminated union.
180 struct {
181 MVT::SimpleValueType VT;
182 } SDTCisVT_Info;
183 struct {
184 unsigned OtherOperandNum;
185 } SDTCisSameAs_Info;
186 struct {
187 unsigned OtherOperandNum;
188 } SDTCisVTSmallerThanOp_Info;
189 struct {
190 unsigned BigOperandNum;
191 } SDTCisOpSmallerThanOp_Info;
192 struct {
193 unsigned OtherOperandNum;
194 } SDTCisEltOfVec_Info;
195 struct {
196 unsigned OtherOperandNum;
197 } SDTCisSubVecOfVec_Info;
198 struct {
199 MVT::SimpleValueType VT;
200 } SDTCVecEltisVT_Info;
201 struct {
202 unsigned OtherOperandNum;
203 } SDTCisSameNumEltsAs_Info;
204 } x;
// The VT for SDTCisVT and SDTCVecEltisVT.
// Must not be in the union because it has a non-trivial destructor.
ValueTypeByHwMode VVT; <--v7.0增加
205
206 /// ApplyTypeConstraint - Given a node in a pattern, apply this type
207 /// constraint to the nodes operands. This returns true if it makes a
208 /// change, false otherwise. If a type contradiction is found, an error
209 /// is flagged.
210 bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo,
211 TreePattern &TP) const;
212 };
SDTypeConstraint对应TD文件中的SDTypeConstraint派生定义,它隐藏在SDNode的TypeProfile域中。而SDNodeInfo就是TableGen所使用的SDNode的对应类型。
217 class SDNodeInfo {
218 Record *Def;
219 std::string EnumName;
220 std::string SDClassName;
221 unsigned Properties;
222 unsigned NumResults;
223 int NumOperands;
224 std::vector
225 public:
226 SDNodeInfo(Record *R); // Parse the specified record.
227
228 unsigned getNumResults() const { return NumResults; }
229
230 /// getNumOperands - This is the number of operands required or -1 if
231 /// variadic.
232 int getNumOperands() const { return NumOperands; }
233 Record *getRecord() const { return Def; }
234 const std::string &getEnumName() const { return EnumName; }
235 const std::string &getSDClassName() const { return SDClassName; }
236
237 const std::vector
238 return TypeConstraints;
239 }
240
241 /// getKnownType - If the type constraints on this node imply a fixed type
242 /// (e.g. all stores return void, etc), then return it as an
243 /// MVT::SimpleValueType. Otherwise, return MVT::Other.
244 MVT::SimpleValueType getKnownType(unsigned ResNo) const;
245
246 /// hasProperty - Return true if this node has the specified property.
247 ///
248 bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
249
250 /// ApplyTypeConstraints - Given a node in a pattern, apply the type
251 /// constraints for this node to the operands of the node. This returns
252 /// true if it makes a change, false otherwise. If a type contradiction is
253 /// found, an error is flagged.
254 bool ApplyTypeConstraints(TreePatternNode *N, TreePattern &TP) const {
255 bool MadeChange = false;
256 for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i)
257 MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP);
258 return MadeChange;
259 }
260 };
处理方法CodeGenDAGPatterns::ParseNodeInfo()则是这样定义的:
2383 void CodeGenDAGPatterns::ParseNodeInfo() {
2384 std::vector
const CodeGenHwModes &CGH = getTargetInfo().getHwModes(); <-- v7.0增加
2385 while (!Nodes.empty()) {
2386 SDNodes.insert(std::make_pair(Nodes.back(), Nodes.back())); <-- v7.0删除
Record *R = Nodes.back(); <-- v7.0增加
SDNodes.insert(std::make_pair(R, SDNodeInfo(R, CGH)));
2387 Nodes.pop_back();
2388 }
2389
2390 // Get the builtin intrinsic nodes.
2391 intrinsic_void_sdnode = getSDNodeNamed("intrinsic_void");
2392 intrinsic_w_chain_sdnode = getSDNodeNamed("intrinsic_w_chain");
2393 intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain");
2394 }
2386行的SDNodes是CodeGenDAGPatterns类型为std::map
1085 SDNodeInfo::SDNodeInfo(Record *R , const CodeGenHwModes &CGH) : Def(R) { <-- v7.0增加
1086 EnumName = R->getValueAsString("Opcode");
1087 SDClassName = R->getValueAsString("SDClass");
1088 Record *TypeProfile = R->getValueAsDef("TypeProfile");
1089 NumResults = TypeProfile->getValueAsInt("NumResults");
1090 NumOperands = TypeProfile->getValueAsInt("NumOperands");
1091
1092 // Parse the properties.
1093 Properties = 0;
1094 std::vector
1095 for (unsigned i = 0, e = PropList.size(); i != e; ++i) {
1096 if (PropList[i]->getName() == "SDNPCommutative") {
1097 Properties |= 1 << SDNPCommutative;
1098 } else if (PropList[i]->getName() == "SDNPAssociative") {
1099 Properties |= 1 << SDNPAssociative;
1100 } else if (PropList[i]->getName() == "SDNPHasChain") {
1101 Properties |= 1 << SDNPHasChain;
1102 } else if (PropList[i]->getName() == "SDNPOutGlue") {
1103 Properties |= 1 << SDNPOutGlue;
1104 } else if (PropList[i]->getName() == "SDNPInGlue") {
1105 Properties |= 1 << SDNPInGlue;
1106 } else if (PropList[i]->getName() == "SDNPOptInGlue") {
1107 Properties |= 1 << SDNPOptInGlue;
1108 } else if (PropList[i]->getName() == "SDNPMayStore") {
1109 Properties |= 1 << SDNPMayStore;
1110 } else if (PropList[i]->getName() == "SDNPMayLoad") {
1111 Properties |= 1 << SDNPMayLoad;
1112 } else if (PropList[i]->getName() == "SDNPSideEffect") {
1113 Properties |= 1 << SDNPSideEffect;
1114 } else if (PropList[i]->getName() == "SDNPMemOperand") {
1115 Properties |= 1 << SDNPMemOperand;
1116 } else if (PropList[i]->getName() == "SDNPVariadic") {
1117 Properties |= 1 << SDNPVariadic;
1118 } else {
1119 PrintFatalError("Unknown SD Node property '" +
1120 PropList[i]->getName() + "' on node '" +
1121 R->getName() + "'!");
1122 }
1123 }
1124
1125
1126 // Parse the type constraints.
1127 std::vector
1128 TypeProfile->getValueAsListOfDefs("Constraints");
1129 TypeConstraints.assign(ConstraintList.begin(), ConstraintList.end()); <-- v7.0删除
for (Record *R : ConstraintList) <-- v7.0增加
TypeConstraints.emplace_back(R, CGH);
1130 }
SDNodeInfo将Properties用作位图,用比特位来表示特定的属性。而1129行为TD文件的SDNode定义里的Constraints每项调用SDTypeConstraint构造函数:
867 SDTypeConstraint::SDTypeConstraint(Record *R , const CodeGenHwModes &CGH) { <-- v7.0增加
868 OperandNo = R->getValueAsInt("OperandNum");
869
870 if (R->isSubClassOf("SDTCisVT")) {
871 ConstraintType = SDTCisVT;
872 x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT")); <-- v7.0删除
VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH); ß v7.0增加
for (const auto &P : VVT)
873 if (x.SDTCisVT_Info.VT == MVT::isVoid)
874 PrintFatalError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT");
875
876 } else if (R->isSubClassOf("SDTCisPtrTy")) {
877 ConstraintType = SDTCisPtrTy;
878 } else if (R->isSubClassOf("SDTCisInt")) {
879 ConstraintType = SDTCisInt;
880 } else if (R->isSubClassOf("SDTCisFP")) {
881 ConstraintType = SDTCisFP;
882 } else if (R->isSubClassOf("SDTCisVec")) {
883 ConstraintType = SDTCisVec;
884 } else if (R->isSubClassOf("SDTCisSameAs")) {
885 ConstraintType = SDTCisSameAs;
886 x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum");
887 } else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) {
888 ConstraintType = SDTCisVTSmallerThanOp;
889 x.SDTCisVTSmallerThanOp_Info.OtherOperandNum =
890 R->getValueAsInt("OtherOperandNum");
891 } else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) {
892 ConstraintType = SDTCisOpSmallerThanOp;
893 x.SDTCisOpSmallerThanOp_Info.BigOperandNum =
894 R->getValueAsInt("BigOperandNum");
895 } else if (R->isSubClassOf("SDTCisEltOfVec")) {
896 ConstraintType = SDTCisEltOfVec;
897 x.SDTCisEltOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum");
898 } else if (R->isSubClassOf("SDTCisSubVecOfVec")) {
899 ConstraintType = SDTCisSubVecOfVec;
900 x.SDTCisSubVecOfVec_Info.OtherOperandNum =
901 R->getValueAsInt("OtherOpNum");
902 } else if (R->isSubClassOf("SDTCVecEltisVT")) {
903 ConstraintType = SDTCVecEltisVT;
904 x.SDTCVecEltisVT_Info.VT = getValueType(R->getValueAsDef("VT")); ß v7.0删除
VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH); ß v7.0增加
for (const auto &P : VVT) {
MVT T = P.second;
905 if (MVT(x.SDTCVecEltisVT_Info.VT).isVector())
906 PrintFatalError(R->getLoc(), "Cannot use vector type as SDTCVecEltisVT");
907 if (!MVT(x.SDTCVecEltisVT_Info.VT).isInteger() &&
908 !MVT(x.SDTCVecEltisVT_Info.VT).isFloatingPoint())
909 PrintFatalError(R->getLoc(), "Must use integer or floating point type "
910 "as SDTCVecEltisVT");
}
911 } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) {
912 ConstraintType = SDTCisSameNumEltsAs;
913 x.SDTCisSameNumEltsAs_Info.OtherOperandNum =
914 R->getValueAsInt("OtherOperandNum");
915 } else {
916 PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
917 }
918 }
CodeGenDAGPatterns::ParseNodeInfo()的2391~2393行,类成员intrinsic_void,intrinsic_w_chain与intrinsic_wo_chain都是LLVM内部用来表示一类固有函数调用的。在LLVM源代码目录下的文件include/llvm/CodeGen/ISDOpcodes.h里可以找到下述的描述:
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...),表示没有副作用的目标机器固有函数。第一个操作数是来自llvm::Intrinsic名字空间的该固有函数的ID号,后跟该固有函数的操作数。该节点返回该固有函数的结果。
RESULT, OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...),表示返回一个结果的有副作用的目标机器固有函数。第一个操作数是链指针,第二个是来自llvm::Intrinsic名字空间的该固有函数的ID号,后跟该固有函数的操作数。该节点返回两个结果,该固有函数的结果与输出链。
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...),表示不返回值、有副作用的目标机器固有函数。第一个操作数是链指针,第二个是来自llvm::Intrinsic名字空间的该固有函数的ID号,后跟该固有函数的操作数。
使用上述三个类型封装固有函数调用,无疑将极大地简化对固有函数的处理,除非必要,我们都无需操心固有函数的语义。因此,这里我们无需它们生成对应的SDNodeInfo对象,而是要记住它们的Record对象,因为它们是什么,我们很清楚。
3.4.2.2. SDNodeXForm的处理
SDNodeXForm也可以作为dag值中的操作符,来表示对操作数的一个修改。执行修改代码片段保存在成员XFormFunction里,而操作数由成员Opcode保存。这里要做的处理,就是整理一下,使得SDNodeXForm定义的内容可以快速获取。
2398 void CodeGenDAGPatterns::ParseNodeTransforms() {
2399 std::vector
2400 while (!Xforms.empty()) {
2401 Record *XFormNode = Xforms.back();
2402 Record *SDNode = XFormNode->getValueAsDef("Opcode");
2403 std::string Code = XFormNode->getValueAsString("XFormFunction");
2404 SDNodeXForms.insert(std::make_pair(XFormNode, NodeXForm(SDNode, Code)));
2405
2406 Xforms.pop_back();
2407 }
2408 }
在代码中SDNodeXForms是std::map
3.4.2.3. ComplexPattern的处理
前面看到ComplexPattern用于描述复杂操作数。CodeGenDAGPatterns::ParseComplexPatterns()方法准备TableGen所需的ComplexPattern对象:
198 class ComplexPattern {
199 MVT::SimpleValueType Ty;
200 unsigned NumOperands;
201 std::string SelectFunc;
202 std::vector
203 unsigned Properties; // Node properties
unsigned Complexity; <-- v7.0增加
204 public:
205 ComplexPattern() : NumOperands(0) {}
206 ComplexPattern(Record *R);
207
208 MVT::SimpleValueType getValueType() const { return Ty; }
209 unsigned getNumOperands() const { return NumOperands; }
210 const std::string &getSelectFunc() const { return SelectFunc; }
211 const std::vector
212 return RootNodes;
213 }
214 bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
unsigned getComplexity() const { return Complexity; } <-- v7.0增加
215 };
TableGen的ComplexPattern几乎就是TD文件中ComplexPattern的定义的一对一翻译。生成它相当简单:
2410 void CodeGenDAGPatterns::ParseComplexPatterns() {
2411 std::vector
2412 while (!AMs.empty()) {
2413 ComplexPatterns.insert(std::make_pair(AMs.back(), AMs.back()));
2414 AMs.pop_back();
2415 }
2416 }
ComplexPatterns容器的类型是std::map
385 ComplexPattern::ComplexPattern(Record *R) {
386 Ty = ::getValueType(R->getValueAsDef("Ty"));
387 NumOperands = R->getValueAsInt("NumOperands");
388 SelectFunc = R->getValueAsString("SelectFunc");
389 RootNodes = R->getValueAsListOfDefs("RootNodes");
390 <-- v7.0增加
// FIXME: This is a hack to statically increase the priority of patterns which
// maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
// possible pattern match we'll need to dynamically calculate the complexity
// of all patterns a dag can potentially map to.
int64_t RawComplexity = R->getValueAsInt("Complexity");
if (RawComplexity == -1)
Complexity = NumOperands * 3;
else
Complexity = RawComplexity;
// FIXME: Why is this different from parseSDPatternOperatorProperties?
391 // Parse the properties.
392 Properties = 0;
393 std::vector
394 for (unsigned i = 0, e = PropList.size(); i != e; ++i)
395 if (PropList[i]->getName() == "SDNPHasChain") {
396 Properties |= 1 << SDNPHasChain;
397 } else if (PropList[i]->getName() == "SDNPOptInGlue") {
398 Properties |= 1 << SDNPOptInGlue;
399 } else if (PropList[i]->getName() == "SDNPMayStore") {
400 Properties |= 1 << SDNPMayStore;
401 } else if (PropList[i]->getName() == "SDNPMayLoad") {
402 Properties |= 1 << SDNPMayLoad;
403 } else if (PropList[i]->getName() == "SDNPSideEffect") {
404 Properties |= 1 << SDNPSideEffect;
405 } else if (PropList[i]->getName() == "SDNPMemOperand") {
406 Properties |= 1 << SDNPMemOperand;
407 } else if (PropList[i]->getName() == "SDNPVariadic") {
408 Properties |= 1 << SDNPVariadic;
409 } else if (PropList[i]->getName() == "SDNPWantRoot") {
410 Properties |= 1 << SDNPWantRoot;
411 } else if (PropList[i]->getName() == "SDNPWantParent") {
412 Properties |= 1 << SDNPWantParent;
413 } else {
414 PrintFatalError("Unsupported SD Node property '" +
415 PropList[i]->getName() + "' on ComplexPattern '" +
416 R->getName() + "'!");
417 }
418 }
NumOperands是SelectFunc将要返回的值个数。RootNodes则是list