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>)保存这些生成的模式树。


原创粉丝点击