LLVM学习笔记(17)
来源:互联网 发布:网络语氮素是什么意思 编辑:程序博客网 时间:2024/06/05 05:18
3.4.2.4.3. 类型推导
3.4.2.4.3.1. 应用类型限定
在展开PatFrag模式之后,对展开结果要进行类型推导,采纳其中类型限定的约束,以尽早检查是否有类型错误。这由下面的TreePattern::InferAllTypes方法来完成。
2246 bool TreePattern::
2247 InferAllTypes(constStringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
2248 if (NamedNodes.empty())
2249 ComputeNamedNodes();
2250
2251 bool MadeChange = true;
2252 while(MadeChange) {
2253 MadeChange = false;
2254 for(unsigned i = 0, e = Trees.size(); i != e; ++i) {
2255 MadeChange |= Trees[i]->ApplyTypeConstraints(*this, false);
2256 MadeChange |= SimplifyTree(Trees[i]);
2257 }
2258
2259 // If there areconstraints on our named nodes, apply them.
2260 for(StringMap<SmallVector<TreePatternNode*,1> >::iterator
2261 I = NamedNodes.begin(), E =NamedNodes.end(); I != E; ++I) {
2262 SmallVectorImpl<TreePatternNode*>&Nodes = I->second;
2263
2264 // If we haveinput named node types, propagate their types to the named
2265 // valueshere.
2266 if (InNamedTypes) {
2267 if(!InNamedTypes->count(I->getKey())) {
2268 error("Node '" +std::string(I->getKey()) +
2269 "' in output pattern butnot input pattern");
2270 returntrue;
2271 }
2272
2273 constSmallVectorImpl<TreePatternNode*> &InNodes =
2274 InNamedTypes->find(I->getKey())->second;
2275
2276 // Theinput types should be fully resolved by now.
2277 for(unsigned i = 0, e = Nodes.size(); i != e; ++i) {
2278 // Ifthis node is a register class, and it is the root of the pattern
2279 // thenwe're mapping something onto an input register. We allow
2280 //changing the type of the input register in this case. This allows
2281 // us tomatch things like:
2282 // def : Pat<(v1i64 (bitconvert(v2i32DPR:$src))), (v1i64 DPR:$src)>;
2283 if (Nodes[i] == Trees[0] &&Nodes[i]->isLeaf()) {
2284 DefInit *DI =dyn_cast<DefInit>(Nodes[i]->getLeafValue());
2285 if (DI &&(DI->getDef()->isSubClassOf("RegisterClass") ||
2286 DI->getDef()->isSubClassOf("RegisterOperand")))
2287 continue;
2288 }
2289
2290 assert(Nodes[i]->getNumTypes()== 1 &&
2291 InNodes[0]->getNumTypes()== 1 &&
2292 "FIXME: cannot namemultiple result nodes yet");
2293 MadeChange |= Nodes[i]->UpdateNodeType(0,InNodes[0]->getExtType(0),
2294 *this);
2295 }
2296 }
2297
2298 // If thereare multiple nodes with the same name, they must all have the
2299 // same type.
2300 if (I->second.size() > 1) {
2301 for(unsigned i = 0, e = Nodes.size()-1; i != e; ++i) {
2302 TreePatternNode *N1 = Nodes[i], *N2 =Nodes[i+1];
2303 assert(N1->getNumTypes()== 1 && N2->getNumTypes() == 1 &&
2304 "FIXME: cannot namemultiple result nodes yet");
2305
2306 MadeChange |= N1->UpdateNodeType(0,N2->getExtType(0), *this);
2307 MadeChange |= N2->UpdateNodeType(0,N1->getExtType(0), *this);
2308 }
2309 }
2310 }
2311 }
2312
2313 bool HasUnresolvedTypes = false;
2314 for (unsignedi = 0, e = Trees.size(); i != e; ++i)
2315 HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType();
2316 return!HasUnresolvedTypes;
2317 }
2248行的NamedNodes是TreePattern的StringMap<SmallVector<TreePatternNode*,1>>类型容器,它用于记录模式树中的具名节点。注意因为这个容器是TreePattern的类成员,因此子树的具名节点保存自己的NamedNodes容器里。
2026 void TreePattern::ComputeNamedNodes(){
2027 for (unsignedi = 0, e = Trees.size(); i != e; ++i)
2028 ComputeNamedNodes(Trees[i]);
2029 }
2030
2031 void TreePattern::ComputeNamedNodes(TreePatternNode*N) {
2032 if (!N->getName().empty())
2033 NamedNodes[N->getName()].push_back(N);
2034
2035 for (unsignedi = 0, e = N->getNumChildren(); i != e; ++i)
2036 ComputeNamedNodes(N->getChild(i));
2037 }
2033行的N->getName()所返回的Name(类型std::string),是通过setName方法设置的。实际上这些名字都对应形入模式变量node:$name的名字,即name(参考TreePattern::ParseTreePattern,在最顶层调用中参数OpName是””,最上层的节点是没有名字的)。
2254行循环逐个调用TreePattern树的TreePatternNode::ApplyTypeConstraints方法,应用相关的类型限定,以期能确定具体的类型。如果该TreePattern树(包括各级节点)类型发生了改变,就返回true,否则返回false。
1653 bool TreePatternNode::ApplyTypeConstraints(TreePattern&TP, bool NotRegisters) {
1654 if (TP.hasError())
1655 returnfalse;
1656
1657 CodeGenDAGPatterns &CDP =TP.getDAGPatterns();
1658 if (isLeaf()) {
1659 if (DefInit *DI =dyn_cast<DefInit>(getLeafValue())) {
1660 // If it's aregclass or something else known, include the type.
1661 bool MadeChange = false;
1662 for(unsigned i = 0, e = Types.size(); i != e; ++i)
1663 MadeChange |= UpdateNodeType(i,getImplicitType(DI->getDef(), i,
1664 NotRegisters,
1665 !hasName(), TP), TP);
1666 returnMadeChange;
1667 }
1668
1669 if (IntInit *II =dyn_cast<IntInit>(getLeafValue())) {
1670 assert(Types.size()== 1 && "Invalid IntInit");
1671
1672 // Int initsare always integers. :)
1673 bool MadeChange =Types[0].EnforceInteger(TP);
1674
1675 if (!Types[0].isConcrete())
1676 returnMadeChange;
1677
1678 MVT::SimpleValueType VT = getType(0);
1679 if (VT == MVT::iPTR || VT ==MVT::iPTRAny)
1680 returnMadeChange;
1681
1682 unsigned Size = MVT(VT).getSizeInBits();
1683 // Make surethat the value is representable for this type.
1684 if (Size >= 32) return MadeChange;
1685
1686 // Check thatthe value doesn't use more bits than we have. It must either
1687 // be a sign-or zero-extended equivalent of the original.
1688 int64_t SignBitAndAbove =II->getValue() >> (Size - 1);
1689 if (SignBitAndAbove == -1 ||SignBitAndAbove == 0 || SignBitAndAbove == 1)
1690 returnMadeChange;
1691
1692 TP.error("Integer value '" +itostr(II->getValue()) +
1693 "' is out of range for type'" + getEnumName(getType(0)) + "'!");
1694 returnfalse;
1695 }
1696 returnfalse;
1697 }
ApplyTypeConstraints将对子树递归。因此在方法的开头首先处理叶子节点。对于DefInit,这有可能是寄存器,它们可能具有隐含的类型,通过下面的方法来推导这些类型(DefInit代表任意一个def定义)。
1436 staticEEVT::TypeSet getImplicitType(Record *R, unsignedResNo,
1437 boolNotRegisters,
1438 bool Unnamed,
1439 TreePattern &TP) {
1440 // Check to seeif this is a register operand.
1441 if(R->isSubClassOf("RegisterOperand")) {
1442 assert(ResNo== 0 && "Regoperand ref only has one result!");
1443 if (NotRegisters)
1444 returnEEVT::TypeSet();//Unknown.
1445 Record *RegClass =R->getValueAsDef("RegClass");
1446 constCodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
1447 returnEEVT::TypeSet(T.getRegisterClass(RegClass).getValueTypes());
1448 }
1449
1450 // Check to seeif this is a register or a register class.
1451 if(R->isSubClassOf("RegisterClass")) {
1452 assert(ResNo== 0 && "Regclass ref only has one result!");
1453 // An unnamedregister class represents itself as an i32 immediate, for
1454 // example on aCOPY_TO_REGCLASS instruction.
1455 if (Unnamed)
1456 returnEEVT::TypeSet(MVT::i32, TP);
1457
1458 // In a namedoperand, the register class provides the possible set of
1459 // types.
1460 if (NotRegisters)
1461 returnEEVT::TypeSet();//Unknown.
1462 constCodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
1463 returnEEVT::TypeSet(T.getRegisterClass(R).getValueTypes());
1464 }
1465
1466 if (R->isSubClassOf("PatFrag")){
1467 assert(ResNo== 0 && "FIXME: PatFrag with multiple results?");
1468 // Patternfragment types will be resolved when they are inlined.
1469 returnEEVT::TypeSet();//Unknown.
1470 }
1471
1472 if (R->isSubClassOf("Register")){
1473 assert(ResNo== 0 && "Registers only produce one result!");
1474 if (NotRegisters)
1475 returnEEVT::TypeSet();//Unknown.
1476 constCodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
1477 return EEVT::TypeSet(T.getRegisterVTs(R));
1478 }
1479
1480 if(R->isSubClassOf("SubRegIndex")) {
1481 assert(ResNo== 0 && "SubRegisterIndices only produce one result!");
1482 returnEEVT::TypeSet(MVT::i32, TP);
1483 }
1484
1485 if(R->isSubClassOf("ValueType")) {
1486 assert(ResNo== 0 && "This node only has one result!");
1487 // An unnamedVTSDNode represents itself as an MVT::Other immediate.
1488 //
1489 // (sext_inreg GPR:$src, i16)
1490 // ~~~
1491 if (Unnamed)
1492 returnEEVT::TypeSet(MVT::Other, TP);
1493 // With a name,the ValueType simply provides the type of the named
1494 // variable.
1495 //
1496 // (sext_inreg i32:$src, i16)
1497 // ~~~~~~~~
1498 if (NotRegisters)
1499 returnEEVT::TypeSet();//Unknown.
1500 returnEEVT::TypeSet(getValueType(R), TP);
1501 }
1502
1503 if (R->isSubClassOf("CondCode")){
1504 assert(ResNo== 0 && "This node only has one result!");
1505 // Using aCondCodeSDNode.
1506 return EEVT::TypeSet(MVT::Other, TP);
1507 }
1508
1509 if(R->isSubClassOf("ComplexPattern")) {
1510 assert(ResNo== 0 && "FIXME: ComplexPattern with multiple results?");
1511 if (NotRegisters)
1512 return EEVT::TypeSet();// Unknown.
1513 returnEEVT::TypeSet(TP.getDAGPatterns().getComplexPattern(R).getValueType(),
1514 TP);
1515 }
1516 if (R->isSubClassOf("PointerLikeRegClass")){
1517 assert(ResNo== 0 && "Regclass can only have one result!");
1518 returnEEVT::TypeSet(MVT::iPTR, TP);
1519 }
1520
1521 if (R->getName() == "node" ||R->getName() == "srcvalue" ||
1522 R->getName() == "zero_reg"){
1523 // Placeholder.
1524 returnEEVT::TypeSet();//Unknown.
1525 }
1526
1527 if (R->isSubClassOf("Operand"))
1528 returnEEVT::TypeSet(getValueType(R->getValueAsDef("Type")));
1529
1530 TP.error("Unknown node flavor used inpattern: " + R->getName());
1531 return EEVT::TypeSet(MVT::Other, TP);
1532 }
名字空间EEVT内的类TypeSet用于表示节点可能具有的类型。它有三个状态:1)空,类型完全未知,可以是任意有效的目标机器类型;2)多个受限类型(比如v4i32+ v4f32),实际类型仅是其中之一;3)只有一个具体类型(具体类型的定义参考SimpleValueType的定义),类型完全已知。
这个方法返回一个封装了可能类型的EEVT::TypeSet对象,并由ApplyTypeConstraints1663行处的UpdateNodeType整合入模式树的类型。这里分别调用了EEVT::TypeSet的三种构造函数:
60 TypeSet() {}
47 EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP){
48 if (VT == MVT::iAny)
49 EnforceInteger(TP);
50 else if (VT == MVT::fAny)
51 EnforceFloatingPoint(TP);
52 else if (VT == MVT::vAny)
53 EnforceVector(TP);
54 else {
55 assert((VT< MVT::LAST_VALUETYPE || VT == MVT::iPTR ||
56 VT == MVT::iPTRAny || VT ==MVT::Any) && "Not a concrete type!");
57 TypeVec.push_back(VT);
58 }
59 }
62 EEVT::TypeSet::TypeSet(ArrayRef<MVT::SimpleValueType>VTList) {
63 assert(!VTList.empty()&& "empty list?");
64 TypeVec.append(VTList.begin(), VTList.end());
65
66 if (!VTList.empty())
67 assert(VTList[0]!= MVT::iAny && VTList[0] != MVT::vAny &&
68 VTList[0] != MVT::fAny);
69
70 // Verify noduplicates.
71 array_pod_sort(TypeVec.begin(),TypeVec.end());
72 assert(std::unique(TypeVec.begin(),TypeVec.end()) == TypeVec.end());
73 }
所谓的隐含类型,实际上都在别处给出了。其中1441行的RegisterOperand类型节点代表存放在寄存器里的操作数,1451行的RegisterClass类型节点代表寄存器的类型(寄存器按可存放值的类型进行分类),1472行的Register类型节点则代表寄存器,1480行的SubRegIndex类型节点则是寄存器索引,1503行的CondCode类型节点代表条件表达式(如SETEQ,SETGT等),而1509与1527行的ComplexPattern与Operand(表示一般操作数)类型节点在定义时必须指定其类型,1516行的PointerLikeRegClass类型节点用于列举可保存指针的寄存器。
回到TreePatternNode::ApplyTypeConstraints,另一种能推断类型的叶子节点就是IntInit,1673行的EnforceInteger在有已知类型的情况下,滤除非整形类型(如果滤除了某些类型,该方法返回true),而在没有已知类型的情况下,通过目标机器的描述载入整形,如果成功载入,返回true,否则返回false。
TreePatternNode::ApplyTypeConstraints(续)
1699 // special handling for set, which isn'treally an SDNode.
1700 if (getOperator()->getName() =="set") {
1701 assert(getNumTypes()== 0 && "Set doesn't produce a value");
1702 assert(getNumChildren()>= 2 && "Missing RHS of a set?");
1703 unsigned NC = getNumChildren();
1704
1705 TreePatternNode *SetVal = getChild(NC-1);
1706 bool MadeChange =SetVal->ApplyTypeConstraints(TP, NotRegisters);
1707
1708 for(unsigned i = 0; i < NC-1; ++i) {
1709 TreePatternNode *Child = getChild(i);
1710 MadeChange |=Child->ApplyTypeConstraints(TP, NotRegisters);
1711
1712 // Types ofoperands must match.
1713 MadeChange |= Child->UpdateNodeType(0,SetVal->getExtType(i), TP);
1714 MadeChange |=SetVal->UpdateNodeType(i, Child->getExtType(0), TP);
1715 }
1716 returnMadeChange;
1717 }
1718
1719 if (getOperator()->getName() =="implicit") {
1720 assert(getNumTypes()== 0 && "Node doesn't produce a value");
1721
1722 bool MadeChange = false;
1723 for(unsigned i = 0; i < getNumChildren(); ++i)
1724 MadeChange = getChild(i)->ApplyTypeConstraints(TP,NotRegisters);
1725 returnMadeChange;
1726 }
1727
1728 if (constCodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
1729 bool MadeChange = false;
1730
1731 // Apply theresult type to the node.
1732 unsigned NumRetVTs =Int->IS.RetVTs.size();
1733 unsigned NumParamVTs =Int->IS.ParamVTs.size();
1734
1735 for(unsigned i = 0, e = NumRetVTs; i != e; ++i)
1736 MadeChange |= UpdateNodeType(i,Int->IS.RetVTs[i], TP);
1737
1738 if (getNumChildren() != NumParamVTs + 1) {
1739 TP.error("Intrinsic '" +Int->Name + "' expects " +
1740 utostr(NumParamVTs) + "operands, not " +
1741 utostr(getNumChildren() - 1) +" operands!");
1742 returnfalse;
1743 }
1744
1745 // Apply typeinfo to the intrinsic ID.
1746 MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP);
1747
1748 for(unsigned i = 0, e = getNumChildren()-1; i != e; ++i) {
1749 MadeChange |=getChild(i+1)->ApplyTypeConstraints(TP, NotRegisters);
1750
1751 MVT::SimpleValueType OpVT =Int->IS.ParamVTs[i];
1752 assert(getChild(i+1)->getNumTypes()== 1 && "Unhandled case");
1753 MadeChange |=getChild(i+1)->UpdateNodeType(0, OpVT, TP);
1754 }
1755 returnMadeChange;
1756 }
1757
1758 if(getOperator()->isSubClassOf("SDNode")) {
1759 constSDNodeInfo &NI = CDP.getSDNodeInfo(getOperator());
1760
1761 // Check thatthe number of operands is sane. Negativeoperands -> varargs.
1762 if (NI.getNumOperands() >= 0 &&
1763 getNumChildren() !=(unsigned)NI.getNumOperands()) {
1764 TP.error(getOperator()->getName() +" node requires exactly " +
1765 itostr(NI.getNumOperands()) +" operands!");
1766 returnfalse;
1767 }
1768
1769 bool MadeChange = NI.ApplyTypeConstraints(this, TP);
1770 for(unsigned i = 0, e = getNumChildren(); i != e; ++i)
1771 MadeChange |=getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
1772 returnMadeChange;
1773 }
1700行的set可以带若干个操作数(不少于2),其中最后的操作数是要设置的值,其余都是设置的目标。因此1708行的循环将设置值与每个设置目标进行融合,任意一个发生变化就返回true。
操作符implicit用于代表其操作数是隐含的,对X86来说,最常见的结构是:(implicitEFLAGS)。Implicit本身不产生值,是没有类型的,因此只需考虑操作数(子树)。
至于固有函数,在TreePattern::ParseTreePattern的2175行将其ID插入为第一个操作数(但没设置类型),因此在1746行将它设为MVT::iPTR类型。而CodeGenIntrinsic的IS.RetVTs与IS.ParamVTs容器分别保存了该固有函数的返回类型与参数类型。因此,在1735行的循环使用返回类型更新该固有函数的类型(固有函数的类型由返回类型确定)。而1748行的循环实际上是将固有函数声明中对参数类型的描述更新到这棵TreePattern树里。其中1749行调用的ApplyTypeConstraints方法的定义如下:
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 returnMadeChange;
259 }
下一个考虑的类型是SDNode定义。在SDNode定义里我们可以通过SDTypeProfile指定类型。这些类型限定的描述(在SDNodeInfo构造函数里生成SDTypeConstraint实例)保存在对应SDNodeInfo对象的TypeConstraints容器里,通过下面的方法应用它们。
948 bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode*N,
949 const SDNodeInfo &NodeInfo,
950 TreePattern&TP)const {
951 if (TP.hasError())
952 returnfalse;
953
954 unsigned ResNo = 0; //The result number being referenced.
955 TreePatternNode *NodeToApply =getOperandNum(OperandNo, N, NodeInfo, ResNo);
956
957 switch(ConstraintType) {
958 caseSDTCisVT:
959 // Operand mustbe a particular type.
960 returnNodeToApply->UpdateNodeType(ResNo,x.SDTCisVT_Info.VT, TP);
961 caseSDTCisPtrTy:
962 // Operand mustbe same as target pointer type.
963 returnNodeToApply->UpdateNodeType(ResNo, MVT::iPTR, TP);
964 caseSDTCisInt:
965 // Require itto be one of the legal integer VTs.
966 returnNodeToApply->getExtType(ResNo).EnforceInteger(TP);
967 caseSDTCisFP:
968 // Require itto be one of the legal fp VTs.
969 returnNodeToApply->getExtType(ResNo).EnforceFloatingPoint(TP);
970 caseSDTCisVec:
971 // Require itto be one of the legal vector VTs.
972 returnNodeToApply->getExtType(ResNo).EnforceVector(TP);
973 caseSDTCisSameAs: {
974 unsigned OResNo = 0;
975 TreePatternNode *OtherNode =
976 getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo);
977 returnNodeToApply->UpdateNodeType(ResNo, OtherNode->getExtType(OResNo),TP)|
978 OtherNode->UpdateNodeType(OResNo,NodeToApply->getExtType(ResNo),TP);
979 }
980 caseSDTCisVTSmallerThanOp: {
981 // TheNodeToApply must be a leaf node that is a VT. OtherOperandNum must
982 // have aninteger type that is smaller than the VT.
983 if (!NodeToApply->isLeaf() ||
984 !isa<DefInit>(NodeToApply->getLeafValue()) ||
985 !static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()
986 ->isSubClassOf("ValueType")) {
987 TP.error(N->getOperator()->getName() + " expects a VToperand!");
988 returnfalse;
989 }
990 MVT::SimpleValueType VT =
991 getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef());
992
993 EEVT::TypeSet TypeListTmp(VT, TP);
994
995 unsigned OResNo = 0;
996 TreePatternNode *OtherNode =
997 getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo,
998 OResNo);
999
1000 returnTypeListTmp.EnforceSmallerThan(OtherNode->getExtType(OResNo), TP);
1001 }
1002 caseSDTCisOpSmallerThanOp: {
1003 unsigned BResNo = 0;
1004 TreePatternNode *BigOperand =
1005 getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum,N, NodeInfo,
1006 BResNo);
1007 returnNodeToApply->getExtType(ResNo).
1008 EnforceSmallerThan(BigOperand->getExtType(BResNo), TP);
1009 }
1010 caseSDTCisEltOfVec: {
1011 unsigned VResNo = 0;
1012 TreePatternNode *VecOperand =
1013 getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo,
1014 VResNo);
1015
1016 // Filtervector types out of VecOperand that don't have the right element
1017 // type.
1018 returnVecOperand->getExtType(VResNo).
1019 EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), TP);
1020 }
1021 caseSDTCisSubVecOfVec: {
1022 unsigned VResNo = 0;
1023 TreePatternNode *BigVecOperand =
1024 getOperandNum(x.SDTCisSubVecOfVec_Info.OtherOperandNum, N, NodeInfo,
1025 VResNo);
1026
1027 // Filtervector types out of BigVecOperand that don't have the
1028 // rightsubvector type.
1029 returnBigVecOperand->getExtType(VResNo).
1030 EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP);
1031 }
1032 caseSDTCVecEltisVT: {
1033 returnNodeToApply->getExtType(ResNo).
1034 EnforceVectorEltTypeIs(x.SDTCVecEltisVT_Info.VT, TP);
1035 }
1036 caseSDTCisSameNumEltsAs: {
1037 unsigned OResNo = 0;
1038 TreePatternNode *OtherNode =
1039 getOperandNum(x.SDTCisSameNumEltsAs_Info.OtherOperandNum,
1040 N, NodeInfo, OResNo);
1041 returnOtherNode->getExtType(OResNo).
1042 EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP);
1043 }
1044 }
1045 llvm_unreachable("InvalidConstraintType!");
1046 }
955行的OperandNo是SDTypeConstraint的成员,来自SDTypeConstraint定义中的OperandNum域,表示该限定应用于第几个参数,而960行及以下出现的x是SDTypeConstraint中的一个union成员,用于保存各种限定的数据。如果指定节点的类型信息发生改变,这个方法返回true,否则返回false(类型冲突将报错)。
回到TreePatternNode::ApplyTypeConstraints,接下来处理Instruction定义。但我们暂时还没解析Instruction,因此这里不会有这个需求。
TreePatternNode::ApplyTypeConstraints(续)
1907 if(getOperator()->isSubClassOf("ComplexPattern")) {
1908 bool MadeChange = false;
1909
1910 for(unsigned i = 0; i < getNumChildren(); ++i)
1911 MadeChange |=getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
1912
1913 return MadeChange;
1914 }
1915
1916 assert(getOperator()->isSubClassOf("SDNodeXForm")&& "Unknown node type!");
1917
1918 // Nodetransforms always take one operand.
1919 if (getNumChildren() != 1) {
1920 TP.error("Node transform '" +getOperator()->getName() +
1921 "' requires oneoperand!");
1922 return false;
1923 }
1924
1925 bool MadeChange =getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
1926
1927
1928 // If either theoutput or input of the xform does not have exact
1929 // type info. Weassume they must be the same. Otherwise, it is perfectly
1930 // legal totransform from one type to a completely different type.
1931 #if 0
1932 if (!hasTypeSet() ||!getChild(0)->hasTypeSet()) {
1933 bool MadeChange =UpdateNodeType(getChild(0)->getExtType(), TP);
1934 MadeChange |=getChild(0)->UpdateNodeType(getExtType(), TP);
1935 returnMadeChange;
1936 }
1937 #endif
1938 return MadeChange;
1939 }
对ComplexPattern与SDNodeXForm定义的处理都很简单,分别对它们的操作数应用类型限定。
3.4.2.4.3.2. 简化
回到TreePattern::InferAllTypes,既然现在类型有可能已经具体化了,那么通过下面的方法尝试简化这棵TreePattern树。
2216 static boolSimplifyTree(TreePatternNode *&N) {
2217 if (N->isLeaf())
2218 return false;
2219
2220 // If we have abitconvert with a resolved type and if the source and
2221 // destinationtypes are the same, then the bitconvert is useless, remove it.
2222 if (N->getOperator()->getName() =="bitconvert" &&
2223 N->getExtType(0).isConcrete()&&
2224 N->getExtType(0) ==N->getChild(0)->getExtType(0) &&
2225 N->getName().empty()) {
2226 N = N->getChild(0);
2227 SimplifyTree(N);
2228 return true;
2229 }
2230
2231 // Walk allchildren.
2232 bool MadeChange = false;
2233 for (unsignedi = 0, e = N->getNumChildren(); i != e; ++i) {
2234 TreePatternNode *Child = N->getChild(i);
2235 MadeChange |= SimplifyTree(Child);
2236 N->setChild(i, Child);
2237 }
2238 return MadeChange;
2239 }
可以看到,目前只有bitconvert子树才可能简化。Bitconvert代表了整数、浮点及向量值之间的转换,源与目标值都有相同的大小。如果源与目标值类型相同,这个转换可以丢弃。
3.4.2.4.3.3. 类型的最后确定
在TreePattern::InferAllTypes函数的入口,当前树的具名节点(即node:$name的名字name)被保存在NamedNodes容器。現在2260行遍历这些名字。首先,如果InferAllTypes传入了非空的参数InNamedTypes,需要确保名字出现在InNamedTypes里。并使用InNamedTypes中对应节点的类型信息来更新当前节点的类型。这个用法出现在Instruction与Pattern定义的处理中,后面会看到。
在此之后,如果NamedNodes容器里存在多个节点对应同一个名字的情形,它们的类型必须兼容(2300~2310行)。
而在上述过程里,一旦有节点的类型发生变化,就要回到2252行重新进行处理,直达没有节点的类型在一次处理过程中改变为止。这时,这棵(些)TreePattern树所有节点的类型都应该确定了,这由下面的方法来判定。
498 bool ContainsUnresolvedType() const {
499 for(unsigned i = 0, e = Types.size(); i != e; ++i)
500 if (!Types[i].isConcrete())return true;
501
502 for(unsigned i = 0, e = getNumChildren(); i != e; ++i)
503 if(getChild(i)->ContainsUnresolvedType())return true;
504 return false;
505 }
从TreePattern::InferAllTypes回到CodeGenDAGPatterns::ParsePatternFragments,对PatFrag定义的处理就此完成。
3.4.2.4.4. OperandWithDefaultOps
接下来,CodeGenDAGPatterns构造函数处理OperandWithDefaultOps派生定义。这个定义在文件Target.td里。
664 classOperandWithDefaultOps<ValueType ty,dag defaultops>
665 : Operand<ty> {
666 dagDefaultOps = defaultops;
667 }
TableGen使用这个定义用于代表缺省值。它典型的用法有(摘自AMDGPUInstructions.td):
def InstFlag :OperandWithDefaultOps <i32, (ops (i320))>;
在这个定义里,缺省值是0。InstFlag可以用在dag中作为操作数,表示自己所代表的缺省值。
CodeGenDAGPatterns对OperandWithDefaultOps定义的处理相当简单。
2507 void CodeGenDAGPatterns::ParseDefaultOperands(){
2508 std::vector<Record*> DefaultOps;
2509 DefaultOps =Records.getAllDerivedDefinitions("OperandWithDefaultOps");
2510
2511 // Find some SDNode.
2512 assert(!SDNodes.empty()&& "No SDNodes parsed?");
2513 Init *SomeSDNode =DefInit::get(SDNodes.begin()->first);
2514
2515 for (unsignedi = 0, e = DefaultOps.size(); i != e; ++i) {
2516 DagInit *DefaultInfo =DefaultOps[i]->getValueAsDag("DefaultOps");
2517
2518 // Clone theDefaultInfo dag node, changing the operator from 'ops' to
2519 // SomeSDnodeso that we can parse this.
2520 std::vector<std::pair<Init*,std::string> > Ops;
2521 for(unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
2522 Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
2523 DefaultInfo->getArgName(op)));
2524 DagInit *DI = DagInit::get(SomeSDNode,"", Ops);
2525
2526 // Create a TreePatternto parse this.
2527 TreePattern P(DefaultOps[i], DI, false, *this);
2528 assert(P.getNumTrees()== 1 && "This ctor can only produce one tree!");
2529
2530 // Copy theoperands over into a DAGDefaultOperand.
2531 DAGDefaultOperand DefaultOpInfo;
2532
2533 TreePatternNode *T = P.getTree(0);
2534 for(unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
2535 TreePatternNode *TPN =T->getChild(op);
2536 while(TPN->ApplyTypeConstraints(P,false))
2537 /* Resolveall types */;
2538
2539 if (TPN->ContainsUnresolvedType()) {
2540 PrintFatalError("Value #" +Twine(i) + " of OperandWithDefaultOps '" +
2541 DefaultOps[i]->getName() +
2542 "' doesn't have aconcrete type!");
2543 }
2544 DefaultOpInfo.DefaultOps.push_back(TPN);
2545 }
2546
2547 // Insert itinto the DefaultOperands map so we can find it later.
2548 DefaultOperands[DefaultOps[i]] =DefaultOpInfo;
2549 }
2550 }
SDNodes是CodeGenDAGPatterns的std::map<Record*,SDNodeInfo, LessRecordByID>类型容器,LessRecordByID以Record的ID来排序。因此2513行获取第一个出现的SDNode定义,这是imm。因此,2521~2524行将指定的缺省值(DefaultOps)封装为一个DagInit:(imm DefaultOps),由TreePattern构造函数构造该DagInit的模式树。由容器DefaultOperands(std::map<Record*,DAGDefaultOperand, LessRecordByID>)保存这些生成的模式树。
- LLVM学习笔记(17)
- llvm学习笔记(1)
- llvm学习笔记(2)
- llvm学习笔记(3)
- llvm学习笔记(4)
- llvm学习笔记(5)
- LLVM学习笔记(6)
- LLVM学习笔记(7)
- LLVM学习笔记(8)
- LLVM学习笔记(9)
- LLVM学习笔记(10)
- LLVM学习笔记(11)
- LLVM学习笔记(12)
- LLVM学习笔记(13)
- LLVM学习笔记(14)
- LLVM学习笔记(15)
- LLVM学习笔记(20)
- LLVM学习笔记(16)
- python文件录入编码的问题
- frams中子页面刷新另一个子页面
- 一个循环删除数组里的多个元素
- 新手容易混乱的String+和StringBuffer,以及Java的方法参数传递方式
- Gson
- LLVM学习笔记(17)
- 小程序的注册及页面的编写
- STL_vector<>
- C++count算法(STL)
- jar导入maven本地库
- MQ客户端链接失败:Failed to verify URI nio://hostname:61616 already known: java.net.UnknownHostExcept
- Canvas&Paint[]Paint:drawText位置
- 解决遗留问题:@PostConstruct注入不成功
- Java并发编程:Callable、Future和FutureTask