LLVM学习笔记(20)

3.4.2.5.3. ApplyTypeConstraints对Instruction的处理

前面看TreePatternNode::ApplyTypeConstraints()方法时,我们跳过了模式操作符是Instruction部分,现在是时候看一下,它到底对作为操作符的Instruction做了什么(v7.0在这部分的处理也是相同的)。

TreePatternNode::ApplyTypeConstraints(续)     

1775    if (getOperator()->isSubClassOf("Instruction")) {

1776      const DAGInstruction &Inst = CDP.getInstruction(getOperator());

1777      CodeGenInstruction &InstInfo =

1778        CDP.getTargetInfo().getInstruction(getOperator());

1779 

1780      bool MadeChange = false;

1781 

1782      // Apply the result types to the node, these come from the things in the

1783      // (outs) list of the instruction.

1784      unsigned NumResultsToAdd = std::min(InstInfo.Operands.NumDefs,

1785                                          Inst.getNumResults());

1786      for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo)

1787        MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP);

1788 

1789      // If the instruction has implicit defs, we apply the first one as a result.

1790      // FIXME: This sucks, it should apply all implicit defs.

1791      if (!InstInfo.ImplicitDefs.empty()) {

1792        unsigned ResNo = NumResultsToAdd;

1793 

1794        // FIXME: Generalize to multiple possible types and multiple possible

1795        // ImplicitDefs.

1796        MVT::SimpleValueType VT =

1797          InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo());

1798 

1799        if (VT != MVT::Other)

1800          MadeChange |= UpdateNodeType(ResNo, VT, TP);

1801      }

1802 

1803      // If this is an INSERT_SUBREG, constrain the source and destination VTs to

1804      // be the same.

1805      if (getOperator()->getName() == "INSERT_SUBREG") {

1806        assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled");

1807        MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP);

1808        MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP);

1809     } else if (getOperator()->getName() == "REG_SEQUENCE") {

1810        // We need to do extra, custom typechecking for REG_SEQUENCE since it is

1811        // variadic.

1812 

1813        unsigned NChild = getNumChildren();

1814        if (NChild < 3) {

1815          TP.error("REG_SEQUENCE requires at least 3 operands!");

1816          return false;

1817        }

1818 

1819        if (NChild % 2 == 0) {

1820          TP.error("REG_SEQUENCE requires an odd number of operands!");

1821          return false;

1822        }

1823 

1824        if (!isOperandClass(getChild(0), "RegisterClass")) {

1825          TP.error("REG_SEQUENCE requires a RegisterClass for first operand!");

1826          return false;

1827        }

1828 

1829        for (unsigned I = 1; I < NChild; I += 2) {

1830          TreePatternNode *SubIdxChild = getChild(I + 1);

1831          if (!isOperandClass(SubIdxChild, "SubRegIndex")) {

1832            TP.error("REG_SEQUENCE requires a SubRegIndex for operand " +

1833                     itostr(I + 1) + "!");

1834            return false;

1835          }

1836        }

1837      }

在1784行,InstInfo.Operands.NumDefs是输出操作数的个数,而1785行的Inst.getNumResults()则是set的目标操作数个数。对于输出操作数,需要下面的方法来更新其类型信息(下面看到对于输入操作数也是一样的)。

1051  bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo,

1052                                               Record *Operand,

1053                                               TreePattern &TP) {

1054    // The 'unknown' operand indicates that types should be inferred from the

1055    // context.

1056    if (Operand->isSubClassOf("unknown_class"))

1057      return false;

1058 

1059    // The Operand class specifies a type directly.

1060    if (Operand->isSubClassOf("Operand"))

1061      return UpdateNodeType(ResNo, getValueType(Operand->getValueAsDef("Type")),

1062                            TP);                                                                           <-- v7.0删除

    Record *R = Operand->getValueAsDef("Type");                                     <-- v7.0增加

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

    return UpdateNodeType(ResNo, getValueTypeByHwMode(R, T.getHwModes()), TP);

1063 

1064    // PointerLikeRegClass has a type that is determined at runtime.

1065    if (Operand->isSubClassOf("PointerLikeRegClass"))

1066      return UpdateNodeType(ResNo, MVT::iPTR, TP);

1067 

1068    // Both RegisterClass and RegisterOperand operands derive their types from a

1069    // register class def.

1070    Record *RC = nullptr;

1071    if (Operand->isSubClassOf("RegisterClass"))

1072      RC = Operand;

1073    else if (Operand->isSubClassOf("RegisterOperand"))

1074      RC = Operand->getValueAsDef("RegClass");

1075 

1076    assert(RC && "Unknown operand type");

1077    CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo();

1078    return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP);

1079  }

1791行的ImplicitDefs来自Instruction定义的Defs域,即被修改的非参数寄存器(对X86,比如EFLAG)。如果指令有隐含结果,通过下面的方法,尝试通过目标机器的信息,获取隐含结果寄存器的类型信息。

365     MVT::SimpleValueType CodeGenInstruction::

366     HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const {

367       if (ImplicitDefs.empty()) return MVT::Other;

368    

369       // Check to see if the first implicit def has a resolvable type.

370       Record *FirstImplicitDef = ImplicitDefs[0];

371       assert(FirstImplicitDef->isSubClassOf("Register"));

372       const std::vector<MVT::SimpleValueType> &RegVTs =

373         TargetInfo.getRegisterVTs(FirstImplicitDef);

374       if (RegVTs.size() == 1 && RegVTs[0].isSimple())               <-- v7.0增加

375         return RegVTs[0].getSimple().SimpleTy;                          <-- v7.0增加

376       return MVT::Other;

377     }

参考GetNumNodeResults()的1196行分支,对Instruction类型操作符结果个数的计算。因此,在1784行的NumResultsToAdd就是放置隐含结果的起始索引。

1805行的INSERT_SUBREG与1809行的REG_SEQUENCE在TargetOpcode.h中有对应的枚举值,对这些枚举值的注释可以帮助我们理解上面的代码(v7.0中这些枚举值定义在TargetOpcode.h里,它们的定义在TargetOpcodes.def中通过HANDLE_TARGET_OPCODE宏自动生成)。

43         /// INSERT_SUBREG - This instruction takes three operands: a register that

44         /// has subregisters, a register providing an insert value, and a

45         /// subregister index. It returns the value of the first register with the

46         /// value of the second register inserted. The first register is often

47         /// defined by an IMPLICIT_DEF, because it is commonly used to implement

48         /// anyext operations on target architectures which support it.

49         INSERT_SUBREG = 7,

注释是这样说的:这条指令有3个操作数:一个有子寄存器的寄存器,一个提供插入值的寄存器,以及一个子寄存器索引。它返回插入第二个寄存器值的第一个寄存器。第一个寄存器通常由IMPLICIT_DEF定义,因为它通常用于在支持anyext操作的目标架构上实现anyext。

71         /// REG_SEQUENCE - This variadic instruction is used to form a register that

72         /// represents a consecutive sequence of sub-registers. It's used as a

73         /// register coalescing / allocation aid and must be eliminated before code

74         /// emission.

75         // In SDNode form, the first operand encodes the register class created by

76         // the REG_SEQUENCE, while each subsequent pair names a vreg + subreg index

77         // pair.  Once it has been lowered to a MachineInstr, the regclass operand

78         // is no longer present.

79         /// e.g. v1027 = REG_SEQUENCE v1024, 3, v1025, 4, v1026, 5

80         /// After register coalescing references of v1024 should be replace with

81         /// v1027:3, v1025 with v1027:4, etc.

82         REG_SEQUENCE = 12,

注释是这样说的:这是用于构成表示一个连续子寄存器序列的寄存器的可变数目参数指令。它用作寄存器合并/分配的一个辅助,并且在代码发布前必须消除。在SDNode形式里,第一个操作数编码了由REG_SEQUENCE创建的寄存器类,后续是命名了一个虚拟寄存器+子寄存器索引的各个对。一旦被降级到MachineInstr,regclass操作数就不再出现了。比如v1027 = REG_SEQUENCE v1024, 3, v1025, 4, v1026, 5。在寄存器合并后,v1024的引用由v1027:3替换,v1025由v1027:4替换,等等。

接下来1840行循环处理所有的输入、输出操作数。注意1857行的ChildResNo永远是0。1839行的ChildNo用于统计已经处理的子节点(树)的个数。

TreePatternNode::ApplyTypeConstraints(续)

1839      unsigned ChildNo = 0;

1840      for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {

1841        Record *OperandNode = Inst.getOperand(i);

1842 

1843        // If the instruction expects a predicate or optional def operand, we

1844        // codegen this by setting the operand to it's default value if it has a

1845        // non-empty DefaultOps field.

1846        if (OperandNode->isSubClassOf("OperandWithDefaultOps") &&

1847           !CDP.getDefaultOperand(OperandNode).DefaultOps.empty())

1848          continue;

1849 

1850        // Verify that we didn't run out of provided operands.

1851        if (ChildNo >= getNumChildren()) {

1852          emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren());

1853          return false;

1854        }

1855 

1856        TreePatternNode *Child = getChild(ChildNo++);

1857        unsigned ChildResNo = 0;  // Instructions always use res #0 of their op.

1858 

1859        // If the operand has sub-operands, they may be provided by distinct

1860        // child patterns, so attempt to match each sub-operand separately.

1861        if (OperandNode->isSubClassOf("Operand")) {

1862          DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo");

1863          if (unsigned NumArgs = MIOpInfo->getNumArgs()) {

1864            // But don't do that if the whole operand is being provided by

1865            // a single ComplexPattern-related Operand.

1866 

1867            if (Child->getNumMIResults(CDP) < NumArgs) {

1868              // Match first sub-operand against the child we already have.

1869              Record *SubRec = cast<DefInit>(MIOpInfo->getArg(0))->getDef();

1870              MadeChange |=

1871                Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP);

1872 

1873              // And the remaining sub-operands against subsequent children.

1874              for (unsigned Arg = 1; Arg < NumArgs; ++Arg) {

1875                if (ChildNo >= getNumChildren()) {

1876                  emitTooFewOperandsError(TP, getOperator()->getName(),

1877                                          getNumChildren());

1878                  return false;

1879                }

1880                Child = getChild(ChildNo++);

1881 

1882                SubRec = cast<DefInit>(MIOpInfo->getArg(Arg))->getDef();

1883                MadeChange |=

1884                  Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP);

1885              }

1886              continue;

1887            }

1888          }

1889        }

1890 

1891        // If we didn't match by pieces above, attempt to match the whole

1892        // operand now.

1893        MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP);

1894      }

1895 

1896      if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) {

1897        emitTooManyOperandsError(TP, getOperator()->getName(),

1898                                 ChildNo, getNumChildren());

1899        return false;

1900      }

1901 

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

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

1904      return MadeChange;

1905    }

1874行的循环处理Operand类型操作数所包含的子操作数。显而易见,如果具有子操作数,在模式里也必须有描述它们的部分,除非操作数是可变数目的(实际上,对于非常复杂的输入、输出操作数,在模式的描述中通常使用ComplexPattern定义来对应,通过特定的函数来处理,就像前面的例子bmi_andn)。

3.4.2.5.4. 构建PatternToMatch实例

在解析完所有的Instruction定义后,在下面的3111行循环遍历所产生的DAGInstruction实例,为它们生成PatternToMatch实例。这些PatternToMatch实例将是下面生成Matcher对象的依据。

TreePatternNode::ParseInstructions(续)

3110    // If we can, convert the instructions to be patterns that are matched!

3111    for (std::map<Record*, DAGInstruction, LessRecordByID>::iterator II =

3112          Instructions.begin(),

3113         E = Instructions.end(); II != E; ++II) {

3114      DAGInstruction &TheInst = II->second;

3115      TreePattern *I = TheInst.getPattern();

3116      if (!I) continue// No pattern.

3117 

3118      // FIXME: Assume only the first tree is the pattern. The others are clobber

3119      // nodes.

3120      TreePatternNode *Pattern = I->getTree(0);

3121      TreePatternNode *SrcPattern;

3122      if (Pattern->getOperator()->getName() == "set") {

3123        SrcPattern = Pattern->getChild(Pattern->getNumChildren()-1)->clone();

3124      } else{

3125        // Not a set (store or something?)

3126        SrcPattern = Pattern;

3127      }

3128 

3129      Record *Instr = II->first;

3130      AddPatternToMatch(I,

3131                        PatternToMatch(Instr,

3132                                      Instr->getValueAsListInit("Predicates"),

3133                                       SrcPattern,

3134                                       TheInst.getResultPattern(),

3135                                       TheInst.getImpResults(),

3136                                       Instr->getValueAsInt("AddedComplexity"),

3137                                       Instr->getID()));

3138    }

3139  }

PatternToMatch的相关定义在文件CodeGenDAGPatterns.h,它包含了这些数据成员:

679     class PatternToMatch {

680     public:

681       PatternToMatch(Record *srcrecord, ListInit *preds,

682                      TreePatternNode *src, TreePatternNode *dst,

683                      const std::vector<Record*> &dstregs,

684                      int complexity, unsigned uid, unsigned setmode = 0)           <-- v7.0增加

685         : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst),

686           Dstregs(dstregs), AddedComplexity(complexity), ID(uid), ForceMode(setmode) {}   <-- v7.0增加

687    

688       Record          *SrcRecord;   // Originating Record for the pattern.

689       ListInit        *Predicates;  // Top level predicate conditions to match.

690     TreePatternNode *SrcPattern;  // Source pattern to match.

691       TreePatternNode *DstPattern;  // Resulting pattern.

692       std::vector<Record*> Dstregs; // Physical register defs being matched.

693       int              AddedComplexity; // Add to matching pattern complexity.

694       unsigned         ID;          // Unique ID for the record.

  unsigned         ForceMode;   // Force this mode in type inference when set.            <-- v7.0增加

注意3133行的SrcPattern,如果匹配模式的操作数的set,SrcPattern就是代表其目标操作数的模式树,否则就是匹配模式本身。然后,这个PatternToMatch实例由AddPatternToMatch方法进行有效性检查,并最终加入容器PatternsToMatch里(类型std::vector<PatternToMatch>)。

3163  void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern,

3164                                             const PatternToMatch &PTM) {

3165    // Do some sanity checking on the pattern we're about to match.

3166    std::string Reason;

3167    if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this)) {

3168      PrintWarning(Pattern->getRecord()->getLoc(),

3169        Twine("Pattern can never match: ") + Reason);

3170      return;

3171    }

3172 

3173    // If the source pattern's root is a complex pattern, that complex pattern

3174    // must specify the nodes it can potentially match.

3175    if (const ComplexPattern *CP =

3176          PTM.getSrcPattern()->getComplexPatternInfo(*this))

3177      if (CP->getRootNodes().empty())

3178        Pattern->error("ComplexPattern at root must specify list of opcodes it"

3179                       " could match");

3180 

3181 

3182    // Find all of the named values in the input and output, ensure they have the

3183    // same type.

3184    std::map<std::string, NameRecord> SrcNames, DstNames;

3185    FindNames(PTM.getSrcPattern(), SrcNames, Pattern);

3186    FindNames(PTM.getDstPattern(), DstNames, Pattern);

3187 

3188    // Scan all of the named values in the destination pattern, rejecting them if

3189    // they don't exist in the input pattern.

3190    for (std::map<std::string, NameRecord>::iterator

3191         I = DstNames.begin(), E = DstNames.end(); I != E; ++I) {

3192      if (SrcNames[I->first].first == nullptr)

3193        Pattern->error("Pattern has input without matching name in output: $" +

3194                       I->first);

3195    }

3196 

3197    // Scan all of the named values in the source pattern, rejecting them if the

3198    // name isn't used in the dest, and isn't used to tie two values together.

3199    for (std::map<std::string, NameRecord>::iterator

3200         I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I)

3201      if (DstNames[I->first].first == nullptr && SrcNames[I->first].second == 1)

3202        Pattern->error("Pattern has dead named input: $" + I->first);

3203 

3204    PatternsToMatch.push_back(PTM);

3205  }

首先检查SrcPattern是否符合目标机器的要求。实际上,canPatternMatch()基本上的工作就是检查符合交换律的操作符是否将立即数放在了左手侧(LHS),这是SelectionDAG要求的规范形式。

1957 bool TreePatternNode::canPatternMatch(std::string &Reason,

1958                                        const CodeGenDAGPatterns &CDP) {

1959    if (isLeaf()) return true;

1960 

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

1962      if (!getChild(i)->canPatternMatch(Reason, CDP))

1963        return false;

1964 

1965    // If this is an intrinsic, handle cases that would make it not match.  For

1966    // example, if an operand is required to be an immediate.

1967    if (getOperator()->isSubClassOf("Intrinsic")) {

1968      // TODO:

1969      return true;

1970    }

1971 

1972    if (getOperator()->isSubClassOf("ComplexPattern"))

1973      return true;

1974 

1975    // If this node is a commutative operator, check that the LHS isn't an

1976    // immediate.

1977    const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator());

1978    bool isCommIntrinsic = isCommutativeIntrinsic(CDP);

1979    if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) {

1980      // Scan all of the operands of the node and make sure that only the last one

1981      // is a constant node, unless the RHS also is.

1982      if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) {

1983        bool Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id.

1984        for (unsigned i = Skip, e = getNumChildren()-1; i != e; ++i)

1985          if (OnlyOnRHSOfCommutative(getChild(i))) {

1986            Reason="Immediate value must be on the RHS of commutative operators!";

1987            return false;

1988          }

1989      }

1990    }

1991 

1992    return true;

1993  }

接下来检查ComplexPattern类型节点是否指定了匹配的目标对象。而源模板与目标模板是否具有相同的具名操作数(注意这里的源模板与目标模板只是PatternsToMatch里的命名而已,实际上它们都来自该Instruction定义的Pattern部分)。

通过检查的PatternToMatch对象被放入PatternsToMatch容器,表示这个对象应该能匹配得上。

V7.0的处理

V7.0 TreePatternNode::ParseInstructions()最后部分改动颇大的。不过目的都是遍历已有的DAGInstruction对象,构建PatternToMatch实例。

3694    // If we can, convert the instructions to be patterns that are matched!

3695    for (auto &Entry : Instructions) {

3696      Record *Instr = Entry.first;

3697      DAGInstruction &TheInst = Entry.second;

3698      TreePatternNodePtr SrcPattern = TheInst.getSrcPattern();

3699      TreePatternNodePtr ResultPattern = TheInst.getResultPattern();

3700 

3701      if (SrcPattern && ResultPattern) {

3702        TreePattern Pattern(Instr, SrcPattern, true, *this);

3703        TreePattern Result(Instr, ResultPattern, false, *this);

3704        ParseOnePattern(Instr, Pattern, Result, TheInst.getImpResults());

3705      }

3706    }

3707  }

首先,将指令的匹配模式与结果模式构建为TreePattern实例。接着,在下面的方法中内联片段并进行类型推导。4041行的PatternRewriter是在构造CodeGenDAGPatterns时传入的,当前为null

3967  void CodeGenDAGPatterns::ParseOnePattern(Record *TheDef,

3968         TreePattern &Pattern, TreePattern &Result,

3969         const std::vector<Record *> &InstImpResults) {

3970 

3971    // Inline pattern fragments and expand multiple alternatives.

3972    Pattern.InlinePatternFragments();

3973    Result.InlinePatternFragments();

3974 

3975    if (Result.getNumTrees() != 1)

3976      Result.error("Cannot use multi-alternative fragments in result pattern!");

3977 

3978    // Infer types.

3979    bool IterateInference;

3980    bool InferredAllPatternTypes, InferredAllResultTypes;

3981    do {

3982      // Infer as many types as possible.  If we cannot infer all of them, we

3983      // can never do anything with this pattern: report it to the user.

3984      InferredAllPatternTypes =

3985          Pattern.InferAllTypes(&Pattern.getNamedNodesMap());

3986 

3987      // Infer as many types as possible.  If we cannot infer all of them, we

3988      // can never do anything with this pattern: report it to the user.

3989      InferredAllResultTypes =

3990          Result.InferAllTypes(&Pattern.getNamedNodesMap());

3991 

3992      IterateInference = false;

3993 

3994      // Apply the type of the result to the source pattern.  This helps us

3995      // resolve cases where the input type is known to be a pointer type (which

3996      // is considered resolved), but the result knows it needs to be 32- or

3997      // 64-bits.  Infer the other way for good measure.

3998      for (auto T : Pattern.getTrees())

3999        for (unsigned i = 0, e = std::min(Result.getOnlyTree()->getNumTypes(),

4000                                          T->getNumTypes());

4001           i != e; ++i) {

4002          IterateInference |= T->UpdateNodeType(

4003              i, Result.getOnlyTree()->getExtType(i), Result);

4004          IterateInference |= Result.getOnlyTree()->UpdateNodeType(

4005              i, T->getExtType(i), Result);

4006        }

4007 

4008      // If our iteration has converged and the input pattern's types are fully

4009      // resolved but the result pattern is not fully resolved, we may have a

4010      // situation where we have two instructions in the result pattern and

4011      // the instructions require a common register class, but don't care about

4012      // what actual MVT is used.  This is actually a bug in our modelling:

4013      // output patterns should have register classes, not MVTs.

4014      //

4015      // In any case, to handle this, we just go through and disambiguate some

4016      // arbitrary types to the result pattern's nodes.

4017      if (!IterateInference && InferredAllPatternTypes &&

4018          !InferredAllResultTypes)

4019        IterateInference =

4020            ForceArbitraryInstResultType(Result.getTree(0).get(), Result);

4021    } while (IterateInference);

4022 

4023    // Verify that we inferred enough types that we can do something with the

4024    // pattern and result.  If these fire the user has to add type casts.

4025    if (!InferredAllPatternTypes)

4026      Pattern.error("Could not infer all types in pattern!");

4027    if (!InferredAllResultTypes) {

4028      Pattern.dump();

4029      Result.error("Could not infer all types in pattern result!");

4030    }

4031 

4032    // Promote xform function to be an explicit node wherever set.

4033    TreePatternNodePtr DstShared = PromoteXForms(Result.getOnlyTree());

4034 

4035    TreePattern Temp(Result.getRecord(), DstShared, false, *this);

4036    Temp.InferAllTypes();

4037 

4038    ListInit *Preds = TheDef->getValueAsListInit("Predicates");

4039    int Complexity = TheDef->getValueAsInt("AddedComplexity");

4040 

4041    if (PatternRewriter)

4042      PatternRewriter(&Pattern);

4043 

4044    // A pattern may end up with an "impossible" type, i.e. a situation

4045    // where all types have been eliminated for some node in this pattern.

4046    // This could occur for intrinsics that only make sense for a specific

4047    // value type, and use a specific register class. If, for some mode,

4048    // that register class does not accept that type, the type inference

4049    // will lead to a contradiction, which is not an error however, but

4050    // a sign that this pattern will simply never match.

4051    if (Temp.getOnlyTree()->hasPossibleType())

4052      for (auto T : Pattern.getTrees())

4053        if (T->hasPossibleType())

4054          AddPatternToMatch(&Pattern,

4055                            PatternToMatch(TheDef, makePredList(Preds),

4056                                           T, Temp.getOnlyTree(),

4057                                           InstImpResults, Complexity,

4058                                           TheDef->getID()));

4059  }

上面4008行注释谈到:如果我们的迭代收敛并且输入模式里的类型被完全解析,但结果模式的类型没有完全解析,在我们在结果模式及输入模式里有两条要求同一个寄存器类,但不关心实际使用的MVT时,会出现这种情形。这是我们模型里的一个bug:输出模式应该使用寄存器类,不是MVT

在这种情形里,通过下面的方法随机选择一个类型。

3922  static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) {

3923    if (N->isLeaf())

3924      return false;

3925 

3926    // Analyze children.

3927    for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)

3928      if (ForceArbitraryInstResultType(N->getChild(i), TP))

3929        return true;

3930 

3931    if (!N->getOperator()->isSubClassOf("Instruction"))

3932      return false;

3933 

3934    // If this type is already concrete or completely unknown we can't do

3935    // anything.

3936    TypeInfer &TI = TP.getInfer();

3937    for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) {

3938      if (N->getExtType(i).empty() || TI.isConcrete(N->getExtType(i), false))

3939        continue;

3940 

3941      // Otherwise, force its type to an arbitrary choice.

3942      if (TI.forceArbitrary(N->getExtType(i)))

3943        return true;

3944    }

3945 

3946    return false;

3947  }

3938行的isConcrete()如果返回true,表示指定的类型在每个硬件模式下都有唯一明确的MVT。如果在某个模式下有多于一个类型,在3942行通过forceArbitrary()方法任意选取一个类型

344     bool TypeInfer::forceArbitrary(TypeSetByHwMode &Out) {

345       ValidateOnExit _1(Out, *this);

346       if (TP.hasError())

347         return false;

348       assert(!Out.empty() && "cannot pick from an empty set");

349    

350       bool Changed = false;

351       for (auto &I : Out) {

352         TypeSetByHwMode::SetType &S = I.second;

353         if (S.size() <= 1)

354           continue;

355         MVT T = *S.begin(); // Pick the first element.

356         S.clear();

357         S.insert(T);

358         Changed = true;

359       }

360       return Changed;

361     }

最后在4055行,构建PatternToMatch实例时,谓词由makePredList()进行排序后交给构造函数。排序的目的是规范化不同次序的相同谓词,最终得到相同的谓词字符串。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值