LLVM学习笔记(17)

3.4.2.4.3. 类型推导

3.4.2.4.3.1. 应用类型限定

在展开PatFrag模式之后,对展开结果要进行类型推导,采纳其中类型限定的约束,以尽早检查是否有类型错误。这由下面的TreePattern:: InferAllTypes()方法来完成(v7.0InferAllTypes()版本逻辑上与v3.6.1的是一致的,因此不再列出)。

2246  bool TreePattern::

2247  InferAllTypes(const StringMap<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 are constraints 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 have input named node types, propagate their types to the named

2265        // values here.

2266        if (InNamedTypes) {

2267          if (!InNamedTypes->count(I->getKey())) {

2268            error("Node '" + std::string(I->getKey()) +

2269                  "' in output pattern but not input pattern");

2270            return true;

2271          }

2272 

2273          const SmallVectorImpl<TreePatternNode*> &InNodes =

2274            InNamedTypes->find(I->getKey())->second;

2275 

2276          // The input types should be fully resolved by now.

2277          for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {

2278            // If this node is a register class, and it is the root of the pattern

2279            // then we're mapping something onto an input register.  We allow

2280            // changing the type of the input register in this case.  This allows

2281            // us to match things like:

2282           //  def : Pat<(v1i64 (bitconvert(v2i32 DPR:$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 name multiple result nodes yet");

2293            MadeChange |= Nodes[i]->UpdateNodeType(0, InNodes[0]->getExtType(0),

2294                                                   *this);

2295          }

2296        }

2297 

2298        // If there are 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 name multiple 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 (unsigned i = 0, e = Trees.size(); i != e; ++i)

2315      HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType();

2316    return !HasUnresolvedTypes;

2317  }

2248行的NamedNodes是TreePattern的StringMap<SmallVector<TreePatternNode*,1>>类型容器,它用于记录模式树中的具名节点。因此,首先调用下面的函数保存具名节点的名字。

2026  void TreePattern::ComputeNamedNodes() {

2027    for (unsigned i = 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 (unsigned i = 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      return false;

1656 

1657    CodeGenDAGPatterns &CDP = TP.getDAGPatterns();

1658    if (isLeaf()) {

1659      if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) {

1660        // If it's a regclass 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        return MadeChange;

1667      }

1668 

1669      if (IntInit *II = dyn_cast<IntInit>(getLeafValue())) {

1670        assert(Types.size() == 1 && "Invalid IntInit");

1671 

1672        // Int inits are always integers. :)

1673        bool MadeChange = Types[0].EnforceInteger(TP);

1674 

1675        if (!Types[0].isConcrete())

1676          return MadeChange;

1677 

1678        MVT::SimpleValueType VT = getType(0);

1679        if (VT == MVT::iPTR || VT == MVT::iPTRAny)

1680          return MadeChange;

1681 

1682        unsigned Size = MVT(VT).getSizeInBits();

1683        // Make sure that the value is representable for this type.

1684        if (Size >= 32) return MadeChange;

1685 

1686        // Check that the 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          return MadeChange;

1691 

1692        TP.error("Integer value '" + itostr(II->getValue()) +

1693                 "' is out of range for type '" + getEnumName(getType(0)) + "'!");

1694        return false;

1695      }

1696      return false;

1697    }

ApplyTypeConstraints()将对子树递归。因此在方法的开头首先处理叶子节点。对于DefInit,这有可能是寄存器,它们可能具有隐含的类型,通过下面的方法来推导这些类型(DefInit代表任意一个def定义)。

1436  static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,

1437                                       bool NotRegisters,

1438                                       bool Unnamed,

1439                                       TreePattern &TP) {

1440    // Check to see if this is a register operand.

1441    if (R->isSubClassOf("RegisterOperand")) {

1442      assert(ResNo == 0 && "Regoperand ref only has one result!");

1443      if (NotRegisters)

1444        return EEVT::TypeSet(); // Unknown.

1445      Record *RegClass = R->getValueAsDef("RegClass");

1446      const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();

1447      return EEVT::TypeSet(T.getRegisterClass(RegClass).getValueTypes());

1448    }

1449 

1450    // Check to see if 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 unnamed register class represents itself as an i32 immediate, for

1454      // example on a COPY_TO_REGCLASS instruction.

1455      if (Unnamed)

1456        return EEVT::TypeSet(MVT::i32, TP);

1457 

1458      // In a named operand, the register class provides the possible set of

1459      // types.

1460      if (NotRegisters)

1461        return EEVT::TypeSet(); // Unknown.

1462      const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();

1463      return EEVT::TypeSet(T.getRegisterClass(R).getValueTypes());

1464    }

1465 

1466    if (R->isSubClassOf("PatFrag")) {

1467      assert(ResNo == 0 && "FIXME: PatFrag with multiple results?");

1468      // Pattern fragment types will be resolved when they are inlined.

1469      return EEVT::TypeSet(); // Unknown.

1470    }

1471 

1472    if (R->isSubClassOf("Register")) {

1473      assert(ResNo == 0 && "Registers only produce one result!");

1474      if (NotRegisters)

1475        return EEVT::TypeSet(); // Unknown.

1476      const CodeGenTarget &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      return EEVT::TypeSet(MVT::i32, TP);

1483    }

1484 

1485    if (R->isSubClassOf("ValueType")) {

1486      assert(ResNo == 0 && "This node only has one result!");

1487      // An unnamed VTSDNode represents itself as an MVT::Other immediate.

1488      //

1489      //   (sext_inreg GPR:$src, i16)

1490      //                         ~~~

1491      if (Unnamed)

1492        return EEVT::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        return EEVT::TypeSet(); // Unknown.

1500      return EEVT::TypeSet(getValueType(R), TP);

1501    }

1502 

1503    if (R->isSubClassOf("CondCode")) {

1504      assert(ResNo == 0 && "This node only has one result!");

1505      // Using a CondCodeSDNode.

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     return EEVT::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      return EEVT::TypeSet(MVT::iPTR, TP);

1519    }

1520 

1521    if (R->getName() == "node" || R->getName() == "srcvalue" ||

1522        R->getName() == "zero_reg") {

1523      // Placeholder.

1524      return EEVT::TypeSet(); // Unknown.

1525    }

1526 

1527    if (R->isSubClassOf("Operand"))

1528      return EEVT::TypeSet(getValueType(R->getValueAsDef("Type")));

1529 

1530    TP.error("Unknown node flavor used in pattern: " + R->getName());

1531    return EEVT::TypeSet(MVT::Other, TP);

1532  }

名字空间EEVT内的类TypeSet用于表示节点可能具有的类型。它有三个状态:1)空,类型完全未知,可以是任意有效的目标机器类型;2)多个受限类型(比如v4i32 + v4f32),实际类型仅是其中之一;3)只有一个具体类型(具体类型的定义参考SimpleValueType的定义),类型完全已知。

这个方法返回一个封装了可能类型的EEVT::TypeSet对象,并由ApplyTypeConstraints() 1663行处的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 no duplicates.

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't really 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 of operands must match.

1713        MadeChange |= Child->UpdateNodeType(0, SetVal->getExtType(i), TP);

1714        MadeChange |= SetVal->UpdateNodeType(i, Child->getExtType(0), TP);

1715      }

1716      return MadeChange;

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      return MadeChange;

1726    }

1727 

1728    if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {

1729      bool MadeChange = false;

1730 

1731      // Apply the result 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        return false;

1743      }

1744 

1745      // Apply type info 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      return MadeChange;

1756    }

1757 

1758    if (getOperator()->isSubClassOf("SDNode")) {

1759      const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator());

1760 

1761      // Check that the number of operands is sane.  Negative operands -> 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        return false;

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      return MadeChange;

1773    }

1700行的set可以带若干个操作数(不少于2),其中最后的操作数是要设置的值,其余都是设置的目标。因此1708行的循环将设置值与每个设置目标进行融合,任意一个发生变化就返回true。

操作符implicit用于代表其操作数是隐含的,对X86来说,最常见的结构是:(implicit EFLAGS)。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         return MadeChange;

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         return false;

953    

954       unsigned ResNo = 0; // The result number being referenced.

955       TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo);

956    

957       switch (ConstraintType) {

958       case SDTCisVT:

959         // Operand must be a particular type.

960         return NodeToApply->UpdateNodeType(ResNo, x.SDTCisVT_Info.VT, TP);

961       case SDTCisPtrTy:

962         // Operand must be same as target pointer type.

963         return NodeToApply->UpdateNodeType(ResNo, MVT::iPTR, TP);

964       case SDTCisInt:

965         // Require it to be one of the legal integer VTs.

966         return NodeToApply->getExtType(ResNo).EnforceInteger(TP);

967       case SDTCisFP:

968         // Require it to be one of the legal fp VTs.

969         return NodeToApply->getExtType(ResNo).EnforceFloatingPoint(TP);

970       case SDTCisVec:

971         // Require it to be one of the legal vector VTs.

972         return NodeToApply->getExtType(ResNo).EnforceVector(TP);

973       case SDTCisSameAs: {

974         unsigned OResNo = 0;

975         TreePatternNode *OtherNode =

976           getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo);

977         return NodeToApply->UpdateNodeType(ResNo, OtherNode->getExtType(OResNo),TP)|

978                OtherNode->UpdateNodeType(OResNo,NodeToApply->getExtType(ResNo),TP);

979       }

980       case SDTCisVTSmallerThanOp: {

981         // The NodeToApply must be a leaf node that is a VT.  OtherOperandNum must

982         // have an integer 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 VT operand!");

988           return false;

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      return TypeListTmp.EnforceSmallerThan(OtherNode->getExtType(OResNo), TP);

1001    }

1002    case SDTCisOpSmallerThanOp: {

1003      unsigned BResNo = 0;

1004      TreePatternNode *BigOperand =

1005        getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NodeInfo,

1006                      BResNo);

1007      return NodeToApply->getExtType(ResNo).

1008                    EnforceSmallerThan(BigOperand->getExtType(BResNo), TP);

1009    }

1010    case SDTCisEltOfVec: {

1011      unsigned VResNo = 0;

1012      TreePatternNode *VecOperand =

1013        getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo,

1014                      VResNo);

1015 

1016      // Filter vector types out of VecOperand that don't have the right element

1017      // type.

1018      return VecOperand->getExtType(VResNo).

1019        EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), TP);

1020    }

1021    case SDTCisSubVecOfVec: {

1022      unsigned VResNo = 0;

1023      TreePatternNode *BigVecOperand =

1024        getOperandNum(x.SDTCisSubVecOfVec_Info.OtherOperandNum, N, NodeInfo,

1025                      VResNo);

1026 

1027      // Filter vector types out of BigVecOperand that don't have the

1028      // right subvector type.

1029      return BigVecOperand->getExtType(VResNo).

1030        EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP);

1031    }

1032    case SDTCVecEltisVT: {

1033      return NodeToApply->getExtType(ResNo).

1034       EnforceVectorEltTypeIs(x.SDTCVecEltisVT_Info.VT, TP);

1035    }

1036    case SDTCisSameNumEltsAs: {

1037      unsigned OResNo = 0;

1038      TreePatternNode *OtherNode =

1039        getOperandNum(x.SDTCisSameNumEltsAs_Info.OtherOperandNum,

1040                      N, NodeInfo, OResNo);

1041      return OtherNode->getExtType(OResNo).

1042        EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP);

1043    }

1044    }

1045    llvm_unreachable("Invalid ConstraintType!");

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    // Node transforms always take one operand.

1919    if (getNumChildren() != 1) {

1920      TP.error("Node transform '" + getOperator()->getName() +

1921               "' requires one operand!");

1922      return false;

1923    }

1924 

1925    bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters);

1926 

1927 

1928    // If either the output or input of the xform does not have exact

1929    // type info. We assume they must be the same. Otherwise, it is perfectly

1930    // legal to transform 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      return MadeChange;

1936    }

1937  #endif

1938    return MadeChange;

1939  }

对ComplexPattern与SDNodeXForm定义的处理都很简单,分别对它们的操作数应用类型限定。

V7.0的处理

V7.0版本的TreePatternNode::ApplyTypeConstraints()方法是这样处理的:

2224  bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {

2225    if (TP.hasError())

2226      return false;

2227 

2228    CodeGenDAGPatterns &CDP = TP.getDAGPatterns();

2229    if (isLeaf()) {

2230      if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) {

2231        // If it's a regclass or something else known, include the type.

2232        bool MadeChange = false;

2233        for (unsigned i = 0, e = Types.size(); i != e; ++i)

2234          MadeChange |= UpdateNodeType(i, getImplicitType(DI->getDef(), i,

2235                                                          NotRegisters,

2236                                                                   !hasName(), TP), TP);

2237        return MadeChange;

2238      }

2239 

2240      if (IntInit *II = dyn_cast<IntInit>(getLeafValue())) {

2241        assert(Types.size() == 1 && "Invalid IntInit");

2242 

2243        // Int inits are always integers. :)

2244        bool MadeChange = TP.getInfer().EnforceInteger(Types[0]);

2245 

2246        if (!TP.getInfer().isConcrete(Types[0], false))

2247          return MadeChange;

2248 

2249        ValueTypeByHwMode VVT = TP.getInfer().getConcrete(Types[0], false);

2250        for (auto &P : VVT) {

2251          MVT::SimpleValueType VT = P.second.SimpleTy;

2252          if (VT == MVT::iPTR || VT == MVT::iPTRAny)

2253            continue;

2254          unsigned Size = MVT(VT).getSizeInBits();

2255          // Make sure that the value is representable for this type.

2256          if (Size >= 32)

2257            continue;

2258          // Check that the value doesn't use more bits than we have. It must

2259          // either be a sign- or zero-extended equivalent of the original.

2260          int64_t SignBitAndAbove = II->getValue() >> (Size - 1);

2261          if (SignBitAndAbove == -1 || SignBitAndAbove == 0 ||

2262              SignBitAndAbove == 1)

2263            continue;

2264 

2265          TP.error("Integer value '" + Twine(II->getValue()) +

2266                   "' is out of range for type '" + getEnumName(VT) + "'!");

2267          break;

2268        }

2269        return MadeChange;

2270      }

2271 

2272      return false;

2273    }

TreePatternNode::ApplyTypeConstraints()根据TreePatternNode实例的定义采取不同的处理。首先是叶子节点,它是从下面对dag定义处理的过程中递归进来的。这主要考虑两种情况,其他情形都不处理(2272行返回false)。第一种是def定义的情形。那么会根据该定义的Record对象,由getImplicitType()来确定这个定义是否有要应用的隐含类型(这是getImplicitType()唯一使用的地方)。

TreePatternNode::ApplyTypeConstraints() 2033行的循环是将getImplicitType()返回的类型作为约束应用到这个TreePatternNode的(多个)结果类型上。

参数NotRegisters如果是true,表示不考虑寄存器约束条件。在当前上下文里,NotRegistersfalse,只有后面在MatcherGen的上下文里它才是true

参数Unnamed用于在类似(COPY_TO_REGCLASS GPR:$src, F8RC)这样的定义中选择类型,当它为true时,getImplicitType()返回匿名dag操作数(即F8RC)的类型;否则返回具名dag操作数(即GPR:$src)的类型。

1991  static TypeSetByHwMode getImplicitType(Record *R, unsigned ResNo,

1992                                         bool NotRegisters,

1993                                         bool Unnamed,

1994                                         TreePattern &TP) {

1995    CodeGenDAGPatterns &CDP = TP.getDAGPatterns();

1996 

1997    // Check to see if this is a register operand.

1998    if (R->isSubClassOf("RegisterOperand")) {

1999      assert(ResNo == 0 && "Regoperand ref only has one result!");

2000      if (NotRegisters)

2001        return TypeSetByHwMode(); // Unknown.

2002      Record *RegClass = R->getValueAsDef("RegClass");

2003      const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();

2004      return TypeSetByHwMode(T.getRegisterClass(RegClass).getValueTypes());

2005    }

2006 

2007    // Check to see if this is a register or a register class.

2008    if (R->isSubClassOf("RegisterClass")) {

2009      assert(ResNo == 0 && "Regclass ref only has one result!");

2010      // An unnamed register class represents itself as an i32 immediate, for

2011      // example on a COPY_TO_REGCLASS instruction.

2012      if (Unnamed)

2013        return TypeSetByHwMode(MVT::i32);

2014 

2015      // In a named operand, the register class provides the possible set of

2016      // types.

2017      if (NotRegisters)

2018        return TypeSetByHwMode(); // Unknown.

2019      const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();

2020      return TypeSetByHwMode(T.getRegisterClass(R).getValueTypes());

2021    }

2022 

2023    if (R->isSubClassOf("PatFrags")) {

2024      assert(ResNo == 0 && "FIXME: PatFrag with multiple results?");

2025      // Pattern fragment types will be resolved when they are inlined.

2026      return TypeSetByHwMode(); // Unknown.

2027    }

2028 

2029    if (R->isSubClassOf("Register")) {

2030      assert(ResNo == 0 && "Registers only produce one result!");

2031      if (NotRegisters)

2032        return TypeSetByHwMode(); // Unknown.

2033      const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();

2034      return TypeSetByHwMode(T.getRegisterVTs(R));

2035    }

2036 

2037    if (R->isSubClassOf("SubRegIndex")) {

2038      assert(ResNo == 0 && "SubRegisterIndices only produce one result!");

2039      return TypeSetByHwMode(MVT::i32);

2040    }

2041 

2042    if (R->isSubClassOf("ValueType")) {

2043      assert(ResNo == 0 && "This node only has one result!");

2044      // An unnamed VTSDNode represents itself as an MVT::Other immediate.

2045      //

2046      //   (sext_inreg GPR:$src, i16)

2047      //                         ~~~

2048      if (Unnamed)

2049        return TypeSetByHwMode(MVT::Other);

2050      // With a name, the ValueType simply provides the type of the named

2051      // variable.

2052      //

2053      //   (sext_inreg i32:$src, i16)

2054      //               ~~~~~~~~

2055      if (NotRegisters)

2056        return TypeSetByHwMode(); // Unknown.

2057      const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes();

2058      return TypeSetByHwMode(getValueTypeByHwMode(R, CGH));

2059    }

2060 

2061    if (R->isSubClassOf("CondCode")) {

2062      assert(ResNo == 0 && "This node only has one result!");

2063      // Using a CondCodeSDNode.

2064      return TypeSetByHwMode(MVT::Other);

2065    }

2066 

2067    if (R->isSubClassOf("ComplexPattern")) {

2068      assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?");

2069      if (NotRegisters)

2070        return TypeSetByHwMode(); // Unknown.

2071      return TypeSetByHwMode(CDP.getComplexPattern(R).getValueType());

2072    }

2073    if (R->isSubClassOf("PointerLikeRegClass")) {

2074      assert(ResNo == 0 && "Regclass can only have one result!");

2075      TypeSetByHwMode VTS(MVT::iPTR);

2076      TP.getInfer().expandOverloads(VTS);

2077      return VTS;

2078    }

2079 

2080    if (R->getName() == "node" || R->getName() == "srcvalue" ||

2081        R->getName() == "zero_reg") {

2082      // Placeholder.

2083      return TypeSetByHwMode(); // Unknown.

2084    }

2085 

2086    if (R->isSubClassOf("Operand")) {

2087      const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes();

2088      Record *T = R->getValueAsDef("Type");

2089      return TypeSetByHwMode(getValueTypeByHwMode(T, CGH));

2090    }

2091 

2092    TP.error("Unknown node flavor used in pattern: " + R->getName());

2093    return TypeSetByHwMode(MVT::Other);

2094  }

getImplicitType()的逻辑并不复杂。比如,对涉及寄存器的定义与ComplexPattern定义,如果NotRegisterstrue,返回空的TypeSetByHwMode类型。UpdateNodeType()将忽略它,返回false。其他定义的处理不再解释。

第二种情形就是整数字面量(IntInit),这个定义生成的TreePatternNode实例总是只有一个返回类型。在2244行首先通过TypeInfer::EnforceInteger()获取其中的整数类型:

363     bool TypeInfer::EnforceInteger(TypeSetByHwMode &Out) {

364       ValidateOnExit _1(Out, *this);

365       if (TP.hasError())

366         return false;

367       if (!Out.empty())

368         return Out.constrain(isIntegerOrPtr);

369    

370       return Out.assign_if(getLegalTypes(), isIntegerOrPtr);

371     }

368行的constrain()是另一个模板版本。连同assign_if(),它们的定义如下:

147     template <typename Predicate>

148     bool TypeSetByHwMode::constrain(Predicate P) {

149       bool Changed = false;

150       for (auto &I : *this)

151         Changed |= berase_if(I.second, [&P](MVT VT) { return !P(VT); });

152       return Changed;

153     }

154    

155     template <typename Predicate>

156     bool TypeSetByHwMode::assign_if(const TypeSetByHwMode &VTS, Predicate P) {

157       assert(empty());

158       for (const auto &I : VTS) {

159         SetType &S = getOrCreate(I.first);

160         for (auto J : I.second)

161           if (P(J))

162             S.insert(J);

163       }

164       return !empty();

165     }

TreePatternNode::ApplyTypeConstraints() 2246行的TypeInfer::isConcrete()检查每个硬件模式是否都只有一个关联类型(如果第二个参数是true,允许有硬件模式没有关联类型,这里是false)。如果不满足条件,提前退出。否则,继续在2249行获取这些类型到VVT。在2250行循环检查这个IntInit值的有效性(是否对类型溢出)。

2275~2302行处理固有函数,我们跳过。

TreePatternNode::ApplyTypeConstraints(续)

2275    if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {

2276      bool MadeChange = false;

2277 

2278      // Apply the result type to the node.

2279      unsigned NumRetVTs = Int->IS.RetVTs.size();

2280      unsigned NumParamVTs = Int->IS.ParamVTs.size();

2281 

2282      for (unsigned i = 0, e = NumRetVTs; i != e; ++i)

2283        MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP);

2284 

2285      if (getNumChildren() != NumParamVTs + 1) {

2286        TP.error("Intrinsic '" + Int->Name + "' expects " + Twine(NumParamVTs) +

2287                 " operands, not " + Twine(getNumChildren() - 1) + " operands!");

2288        return false;

2289      }

2290 

2291      // Apply type info to the intrinsic ID.

2292      MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP);

2293 

2294      for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i) {

2295        MadeChange |= getChild(i+1)->ApplyTypeConstraints(TP, NotRegisters);

2296 

2297        MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i];

2298        assert(getChild(i+1)->getNumTypes() == 1 && "Unhandled case");

2299        MadeChange |= getChild(i+1)->UpdateNodeType(0, OpVT, TP);

2300      }

2301      return MadeChange;

2302    }

2303 

2304    if (getOperator()->isSubClassOf("SDNode")) {

2305      const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator());

2306 

2307      // Check that the number of operands is sane.  Negative operands -> varargs.

2308      if (NI.getNumOperands() >= 0 &&

2309          getNumChildren() != (unsigned)NI.getNumOperands()) {

2310        TP.error(getOperator()->getName() + " node requires exactly " +

2311                 Twine(NI.getNumOperands()) + " operands!");

2312        return false;

2313      }

2314 

2315      bool MadeChange = false;

2316      for (unsigned i = 0, e = getNumChildren(); i != e; ++i)

2317        MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);

2318      MadeChange |= NI.ApplyTypeConstraints(this, TP);

2319      return MadeChange;

2320    }

对于SDNode来说,2308~2313行检查TreePatternNode(使用处)的子节点数与SDNodeInfo(定义处)中操作数个数一致。在2316行循环中,2318行的SDNodeInfo::ApplyTypeConstraints()是对TreePatternNode实例应用SDNode定义里的类型限定。具体细节与v3.6.1版本的基本相同。

同样,这里先跳过对Instruction定义的处理。

TreePatternNode::ApplyTypeConstraints(续)

2454    if (getOperator()->isSubClassOf("ComplexPattern")) {

2455      bool MadeChange = false;

2456 

2457      for (unsigned i = 0; i < getNumChildren(); ++i)

2458        MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);

2459 

2460      return MadeChange;

2461    }

2462 

2463    assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");

2464 

2465    // Node transforms always take one operand.

2466    if (getNumChildren() != 1) {

2467      TP.error("Node transform '" + getOperator()->getName() +

2468               "' requires one operand!");

2469      return false;

2470    }

2471 

2472    bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters);

2473    return MadeChange;

2474  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值