LLVM学习笔记(28)

3.4.3.4. 生成MatcherTable

一切就绪之后,在DAGISelEmitter::run()的末尾,调用EmitMatcherTable()方法生成MatcherTable。参数O是TableGenMain()方法(TableGen的入口)传入的代表输出文件的流。对X86,这个输出文件就是X86GenDAGISel.inc。

806     void llvm::EmitMatcherTable(const Matcher *TheMatcher,

807                                 const CodeGenDAGPatterns &CGP,

808                                 raw_ostream &O) {                                                                                       <-- v7.0删除

                            raw_ostream &OS) {                                                                                     <-- v7.0增加

809       formatted_raw_ostream OS(O);                                                                                           <-- v7.0删除

810    

811       OS << "// The main instruction selector code.\n";

812       OS << "SDNode *SelectCode(SDNode *N) {\n";

813    

  OS << "#if defined(GET_DAGISEL_DECL) && defined(GET_DAGISEL_BODY)\n";          <-- v7.0增加

  OS << "#error GET_DAGISEL_DECL and GET_DAGISEL_BODY cannot be both defined, ";

  OS << "undef both for inline definitions\n";

  OS << "#endif\n\n";

 

  // Emit a check for omitted class name.

  OS << "#ifdef GET_DAGISEL_BODY\n";

  OS << "#define LOCAL_DAGISEL_STRINGIZE(X) LOCAL_DAGISEL_STRINGIZE_(X)\n";

  OS << "#define LOCAL_DAGISEL_STRINGIZE_(X) #X\n";

  OS << "static_assert(sizeof(LOCAL_DAGISEL_STRINGIZE(GET_DAGISEL_BODY)) > 1,"

        "\n";

  OS << "   \"GET_DAGISEL_BODY is empty: it should be defined with the class "

        "name\");\n";

  OS << "#undef LOCAL_DAGISEL_STRINGIZE_\n";

  OS << "#undef LOCAL_DAGISEL_STRINGIZE\n";

  OS << "#endif\n\n";

 

  OS << "#if !defined(GET_DAGISEL_DECL) && !defined(GET_DAGISEL_BODY)\n";

  OS << "#define DAGISEL_INLINE 1\n";

  OS << "#else\n";

  OS << "#define DAGISEL_INLINE 0\n";

  OS << "#endif\n\n";

 

  OS << "#if !DAGISEL_INLINE\n";

  OS << "#define DAGISEL_CLASS_COLONCOLON GET_DAGISEL_BODY ::\n";

  OS << "#else\n";

  OS << "#define DAGISEL_CLASS_COLONCOLON\n";

  OS << "#endif\n\n";

 

  BeginEmitFunction(OS, "void", "SelectCode(SDNode *N)", false/*AddOverride*/);

 

814       MatcherTableEmitter MatcherEmitter(CGP);

815    

816       OS << "  // Some target values are emitted as 2 bytes, TARGET_VAL handles\n";

817       OS << "  // this.\n";

818       OS << "  #define TARGET_VAL(X) X & 255, unsigned(X) >> 8\n";

819       OS << "  static const unsigned char MatcherTable[] = {\n";

820       unsigned TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 6, 0, OS);

821       OS << "    0\n  }; // Total Array size is " << (TotalSize+1) << " bytes\n\n";

822    

823       MatcherEmitter.EmitHistogram(TheMatcher, OS);

824    

825       OS << "  #undef TARGET_VAL\n";

826       OS << "  return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n";

827       OS << '\n';

  EndEmitFunction(OS);                                                                                                             <-- v7.0增加

828    

829       // Next up, emit the function for node and pattern predicates:

830       MatcherEmitter.EmitPredicateFunctions(OS);

  if (InstrumentCoverage)                                                                                                          <-- v7.0增加

    MatcherEmitter.EmitPatternMatchTable(OS);

 

  // Clean up the preprocessor macros.

  OS << "\n";

  OS << "#ifdef DAGISEL_INLINE\n";

  OS << "#undef DAGISEL_INLINE\n";

  OS << "#endif\n";

  OS << "#ifdef DAGISEL_CLASS_COLONCOLON\n";

  OS << "#undef DAGISEL_CLASS_COLONCOLON\n";

  OS << "#endif\n";

  OS << "#ifdef GET_DAGISEL_DECL\n";

  OS << "#undef GET_DAGISEL_DECL\n";

  OS << "#endif\n";

  OS << "#ifdef GET_DAGISEL_BODY\n";

  OS << "#undef GET_DAGISEL_BODY\n";

  OS << "#endif\n";

831     }

一直到819行,这些代码向输出文件输出如下的内容:

// The main instruction selector code.

SDNode *SelectCode(SDNode *N) {

  // Some target values are emitted as 2 bytes, TARGET_VAL handles

  // this.

  #define TARGET_VAL(X) X & 255, unsigned(X) >> 8

  static const unsigned char MatcherTable[] = {

到等价部分,V7.0的输出则是如下:

#if defined(GET_DAGISEL_DECL) && defined(GET_DAGISEL_BODY)

#error GET_DAGISEL_DECL and GET_DAGISEL_BODY cannot be both defined, undef both for inline definitions

#endif

 

#ifdef GET_DAGISEL_BODY

#define LOCAL_DAGISEL_STRINGIZE(X) LOCAL_DAGISEL_STRINGIZE_(X)

#define LOCAL_DAGISEL_STRINGIZE_(X) #X

static_assert(sizeof(LOCAL_DAGISEL_STRINGIZE(GET_DAGISEL_BODY)) > 1,

   "GET_DAGISEL_BODY is empty: it should be defined with the class name");

#undef LOCAL_DAGISEL_STRINGIZE_

#undef LOCAL_DAGISEL_STRINGIZE

#endif

 

#if !defined(GET_DAGISEL_DECL) && !defined(GET_DAGISEL_BODY)

#define DAGISEL_INLINE 1

#else

#define DAGISEL_INLINE 0

#endif

 

#if !DAGISEL_INLINE

#define DAGISEL_CLASS_COLONCOLON GET_DAGISEL_BODY ::

#else

#define DAGISEL_CLASS_COLONCOLON

#endif

 

#ifdef GET_DAGISEL_DECL

void SelectCode(SDNode *N);

#endif

#if defined(GET_DAGISEL_BODY) || DAGISEL_INLINE

void DAGISEL_CLASS_COLONCOLON SelectCode(SDNode *N)

{

  // Some target values are emitted as 2 bytes, TARGET_VAL handles

  // this.

  #define TARGET_VAL(X) X & 255, unsigned(X) >> 8

  static const unsigned char MatcherTable[] = {

上面这些宏的作用是这样:

如果定义了GET_DAGISEL_DECL,在包含这个文件时,仅包含函数上面。

如果定义了GET_DAGISEL_BODY,其值应该是指令选择器类的名字。将发布函数体,并且每个函数名由类名修饰。

在没有定义任何GET_DAGISEL*宏时,函数被发布为内联。

数组MatcherTable就是这里所说的MatcherTable表,由下面的方法输出。参数CurrentIdx表示在输出文件中当前的位置,Indent表示缩进的空格数。因为EmitMatcherList()将在EmitMatcher()中被递归调用,这些参数都必须实时传入。

597     unsigned MatcherTableEmitter::

598     EmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx,

599                     formatted_raw_ostream &OS) {

600       unsigned Size = 0;

601       while (N) {

602         if (!OmitComments)

603           OS << "/*" << CurrentIdx << "*/";

604         unsigned MatcherSize = EmitMatcher(N, Indent, CurrentIdx, OS);

605         Size += MatcherSize;

606         CurrentIdx += MatcherSize;

607    

608         // If there are other nodes in this list, iterate to them, otherwise we're

609         // done.

610         N = N->getNext();

611       }

612       return Size;

613     }

前面看到所有指令的Matcher链都是一个ScopeMatcher实例或SwitchOpcodeMatcher实例的孩子(整个指令集都由这个实例来表示),但不管是简单的Matcher对象,还是这个庞大复杂的Matcher实例,总是由EmitMatcher()为它们输出MatcherTable的内容。这个函数的返回值表示这次输出的字节数。而EmitMatcherList()返回的则是总的字节数。

137     unsigned MatcherTableEmitter::

138     EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,

139                 formatted_raw_ostream &OS) {

140       OS.PadToColumn(Indent*2);

141    

142       switch (N->getKind()) {

143       case Matcher::Scope: {

144         const ScopeMatcher *SM = cast<ScopeMatcher>(N);

145         assert(SM->getNext() == nullptr && "Shouldn't have next after scope");

146    

147         unsigned StartIdx = CurrentIdx;

148    

149         // Emit all of the children.

150         for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) {

151           if (i == 0) {

152             OS << "OPC_Scope, ";

153             ++CurrentIdx;

154           } else  {

155             if (!OmitComments) {

156               OS << "/*" << CurrentIdx << "*/";

157               OS.PadToColumn(Indent*2) << "/*Scope*/ ";

158             } else

159               OS.PadToColumn(Indent*2);

160           }

161    

162           // We need to encode the child and the offset of the failure code before

163           // emitting either of them.  Handle this by buffering the output into a

164           // string while we get the size.  Unfortunately, the offset of the

165           // children depends on the VBR size of the child, so for large children we

166           // have to iterate a bit.

167           SmallString<128> TmpBuf;

168           unsigned ChildSize = 0;

169           unsigned VBRSize = 0;

170           do {

171             VBRSize = GetVBRSize(ChildSize);

172    

173             TmpBuf.clear();

174             raw_svector_ostream OS(TmpBuf);

175             formatted_raw_ostream FOS(OS);

176             ChildSize = EmitMatcherList(SM->getChild(i), Indent+1,

177                                         CurrentIdx+VBRSize, FOS);

178           } while (GetVBRSize(ChildSize) != VBRSize);

179    

180           assert(ChildSize != 0 && "Should not have a zero-sized child!");

181    

182           CurrentIdx += EmitVBRValue(ChildSize, OS);

183           if (!OmitComments) {

184             OS << "/*->" << CurrentIdx+ChildSize << "*/";

185    

186             if (i == 0)

187               OS.PadToColumn(CommentIndent) << "// " << SM->getNumChildren()

188                 << " children in Scope";

189           }

190    

191           OS << '\n' << TmpBuf;

192           CurrentIdx += ChildSize;

193         }

194    

195         // Emit a zero as a sentinel indicating end of 'Scope'.

196         if (!OmitComments)

197           OS << "/*" << CurrentIdx << "*/";

198         OS.PadToColumn(Indent*2) << "0, ";

199         if (!OmitComments)

200           OS << "/*End of Scope*/";

201         OS << '\n';

202         return CurrentIdx - StartIdx + 1;

203       }

X86GenDAGISel.inc当前版本(llvm-3.6)MatcherTable开头部分是这样子的(让我们稍微看多一点,看一个完整的复杂ScopeMatcher实例的输出。而X86GenDAGISel.inc一共有183518行!v7.0一共有387case,它的X86GenDAGISel.inc一共有304822行。不过,它的输出内容是相似的):

/*0*/       OPC_SwitchOpcode /*284 cases */, 41|128,120/*15401*/, TARGET_VAL(ISD::STORE),// ->15406

/*5*/         OPC_RecordMemRef,

/*6*/         OPC_RecordNode, // #0 = 'st' chained node

/*7*/         OPC_Scope, 20|128,5/*660*/, /*->670*/ // 10 children in Scope

/*10*/          OPC_RecordChild1, // #1 = $src

/*11*/          OPC_Scope, 64, /*->77*/ // 17 children in Scope

/*13*/            OPC_CheckChild1Type, MVT::v4f32,

/*15*/            OPC_RecordChild2, // #2 = $dst

/*16*/            OPC_CheckPredicate, 0, // Predicate_alignednontemporalstore

/*18*/            OPC_Scope, 18, /*->38*/ // 3 children in Scope

/*20*/              OPC_CheckPatternPredicate, 0, // (Subtarget->hasAVX()) && (!Subtarget->hasVLX())

/*22*/              OPC_CheckComplexPat, /*CP*/0, /*#*/2, // SelectAddr:$dst #3 #4 #5 #6 #7

/*25*/              OPC_EmitMergeInputChains1_0,

/*26*/              OPC_MorphNodeTo, TARGET_VAL(X86::VMOVNTPSmr), 0|OPFL_Chain|OPFL_MemRefs,

                                  0/*#VTs*/, 6/*#Ops*/, 3, 4, 5, 6, 7, 1,

                          // Src: (st VR128:v4f32:$src, addr:iPTR:$dst)<<P:Predicate_alignednontemporalstore>> - Complexity = 422

                          // Dst: (VMOVNTPSmr addr:iPTR:$dst, VR128:v4f32:$src)

/*38*/            /*Scope*/ 18, /*->57*/

/*39*/              OPC_CheckPatternPredicate, 1, // (Subtarget->hasSSE1() && !Subtarget->hasAVX())

/*41*/              OPC_CheckComplexPat, /*CP*/0, /*#*/2, // SelectAddr:$dst #3 #4 #5 #6 #7

/*44*/              OPC_EmitMergeInputChains1_0,

/*45*/              OPC_MorphNodeTo, TARGET_VAL(X86::MOVNTPSmr), 0|OPFL_Chain|OPFL_MemRefs,

                        0/*#VTs*/, 6/*#Ops*/, 3, 4, 5, 6, 7, 1,

                    // Src: (st VR128:v4f32:$src, addr:iPTR:$dst)<<P:Predicate_alignednontemporalstore>> - Complexity = 422

                    // Dst: (MOVNTPSmr addr:iPTR:$dst, VR128:v4f32:$src)

/*57*/            /*Scope*/ 18, /*->76*/

/*58*/              OPC_CheckPatternPredicate, 2, // (Subtarget->hasAVX512()) && (Subtarget->hasVLX())

/*60*/              OPC_CheckComplexPat, /*CP*/0, /*#*/2, // SelectAddr:$dst #3 #4 #5 #6 #7

/*63*/              OPC_EmitMergeInputChains1_0,

/*64*/              OPC_MorphNodeTo, TARGET_VAL(X86::VMOVNTPSZ128mr), 0|OPFL_Chain|OPFL_MemRefs,

                        0/*#VTs*/, 6/*#Ops*/, 3, 4, 5, 6, 7, 1,

                    // Src: (st VR128X:v4f32:$src, addr:iPTR:$dst)<<P:Predicate_alignednontemporalstore>> - Complexity = 422

                    // Dst: (VMOVNTPSZ128mr addr:iPTR:$dst, VR128X:v4f32:$src)

/*76*/            0, /*End of Scope*/

第一列是当前在输出文件里的偏移,第二列通常就是当前Matcher对象所对应的枚举值(类型BuiltinOpcodes,这些值不能超过127,原因参见下面说明)。之后的内容则取决于具体的Matcher对象。对于ScopeMatcher对象,OPC_Scope后的是这个对象输出的字节数,之后的注释则描述跟在这个对象后的Matcher对象输出内容所在的文件偏移。在这个注释后,跟着的就是这个对象包含的孩子的输出。EmitMatcher()的170~178行代码用于确定这些孩子的输出与字节大小。

在171行与178行,ChildSize要经过GetVBRSize()处理为VBRSize。

102     static unsigned GetVBRSize(unsigned Val) {

103       if (Val <= 127) return 1;

104    

105       unsigned NumBytes = 0;

106       while (Val >= 128) {

107         Val >>= 7;

108         ++NumBytes;

109       }

110       return NumBytes+1;

111     }

GetVBRSize()以127为单位为Val分配字节,因为子节点的大小是未知的,以170~178行循环迭代来计算这个大小。为什么要这样呢?这是因为MatcherTable是一个const unsigned char类型的数组,而ScopeMatcher类型的对象理论上可以无限嵌套,它的输出可能会很大,因此需要特别的编码方式来编码这个可能很大的输出大小。这里使用的是变长整数值的编码。

计算出这个大小后,EmitVBRValue()方法将它输出到文件中。看到除了最后一个字节,其他字节的高位都是1,这就是为什么每个字节保存的值不能超过127的原因。

115   static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) {

116       if (Val <= 127) {

117         OS << Val << ", ";

118         return 1;

119       }

120    

121       uint64_t InVal = Val;

122       unsigned NumBytes = 0;

123       while (Val >= 128) {

124         OS << (Val&127) << "|128,";

125         Val >>= 7;

126         ++NumBytes;

127       }

128       OS << Val;

129       if (!OmitComments)

130         OS << "/*" << InVal << "*/";

131       OS << ", ";

132       return NumBytes+1;

133     }

ScopeMatcher实例的内容也是由递归的EmitMatcherList()方法输出的。因此,实际的输出取决于子节点的类型,亦即下面的处理。

V7.0改进了下面对MoveChildMatcher的处理。对前8个孩子,将输出这样的代码:

/* 40402*/      OPC_MoveChild7,

8以后的孩子,将输出这样的代码:

/* 40409*/      OPC_MoveChild, 8,

v7.0同时改进了SelectionDAGISel::SelectCodeCommon(),让它能支持超过8个孩子的MoveChildMatcherv3.6.1限制孩子数为8个)。

下面261行的EmitMatcher::getNodePredicate(),在v7.0里定义为:

98         unsigned getNodePredicate(TreePredicateFn Pred) {

99           TreePattern *TP = Pred.getOrigPatFragRecord();

100         unsigned &Entry = NodePredicateMap[TP];

101         if (Entry == 0) {

102           TinyPtrVector<TreePattern *> &SameCodePreds =

103               NodePredicatesByCodeToRun[Pred.getCodeToRunOnSDNode()];

104           if (SameCodePreds.empty()) {

105             // We've never seen a predicate with the same code: allocate an entry.

106             NodePredicates.push_back(Pred);

107             Entry = NodePredicates.size();

108           } else {

109             // We did see an identical predicate: re-use it.

110             Entry = NodePredicateMap[SameCodePreds.front()];

111             assert(Entry != 0);

112           }

113           // In both cases, we've never seen this particular predicate before, so

114           // mark it in the list of predicates sharing the same code.

115           SameCodePreds.push_back(TP);

116         }

117         return Entry-1;

118       }

这个方法获取谓词代码字符串的序号(这些字符串将生成在一个表中,通过序号去援引。在这里输出序号,远比输出字符串要高效和方便)。

为此,要使用这些容器:

100行的NodePredicateMapDenseMap<TreePattern *, unsigned>类型的容器,用于将指定的TreePattern对象绑定到谓词代码字符串。如果该TreePattern对象尚未绑定字符串,进入101if语句块进行绑定。

103行的NodePredicatesByCodeToRunStringMap<TinyPtrVector<TreePattern *>>类型容器,其中TinyPtrVector是针对只有01的向量优化的容器。它使用谓词代码字符串作为键值。谓词代码字符串由103行的TreePredicateFn::getCodeToRunOnSDNode()生成,它在v7.0里定义为:

1177  std::string TreePredicateFn::getCodeToRunOnSDNode() const {

1178    // Handle immediate predicates first.

1179    std::string ImmCode = getImmCode();

1180    if (!ImmCode.empty()) {

1181      if (isLoad())

1182        PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),

1183                        "IsLoad cannot be used with ImmLeaf or its subclasses");

1184     if (isStore())

1185        PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),

1186                        "IsStore cannot be used with ImmLeaf or its subclasses");

1187      if (isUnindexed())

1188        PrintFatalError(

1189            getOrigPatFragRecord()->getRecord()->getLoc(),

1190            "IsUnindexed cannot be used with ImmLeaf or its subclasses");

1191      if (isNonExtLoad())

1192        PrintFatalError(

1193            getOrigPatFragRecord()->getRecord()->getLoc(),

1194            "IsNonExtLoad cannot be used with ImmLeaf or its subclasses");

1195      if (isAnyExtLoad())

1196        PrintFatalError(

1197            getOrigPatFragRecord()->getRecord()->getLoc(),

1198            "IsAnyExtLoad cannot be used with ImmLeaf or its subclasses");

1199      if (isSignExtLoad())

1200        PrintFatalError(

1201            getOrigPatFragRecord()->getRecord()->getLoc(),

1202            "IsSignExtLoad cannot be used with ImmLeaf or its subclasses");

1203      if (isZeroExtLoad())

1204        PrintFatalError(

1205            getOrigPatFragRecord()->getRecord()->getLoc(),

1206            "IsZeroExtLoad cannot be used with ImmLeaf or its subclasses");

1207      if (isNonTruncStore())

1208        PrintFatalError(

1209            getOrigPatFragRecord()->getRecord()->getLoc(),

1210            "IsNonTruncStore cannot be used with ImmLeaf or its subclasses");

1211      if (isTruncStore())

1212        PrintFatalError(

1213            getOrigPatFragRecord()->getRecord()->getLoc(),

1214            "IsTruncStore cannot be used with ImmLeaf or its subclasses");

1215      if (getMemoryVT())

1216        PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),

1217                        "MemoryVT cannot be used with ImmLeaf or its subclasses");

1218      if (getScalarMemoryVT())

1219        PrintFatalError(

1220            getOrigPatFragRecord()->getRecord()->getLoc(),

1221            "ScalarMemoryVT cannot be used with ImmLeaf or its subclasses");

1222 

1223      std::string Result = ("    " + getImmType() + " Imm = ").str();

1224      if (immCodeUsesAPFloat())

1225        Result += "cast<ConstantFPSDNode>(Node)->getValueAPF();\n";

1226      else if (immCodeUsesAPInt())

1227        Result += "cast<ConstantSDNode>(Node)->getAPIntValue();\n";

1228      else

1229        Result += "cast<ConstantSDNode>(Node)->getSExtValue();\n";

1230      return Result + ImmCode;

1231    }

1232 

1233    // Handle arbitrary node predicates.

1234    assert(hasPredCode() && "Don't have any predicate code!");

1235    StringRef ClassName;

1236    if (PatFragRec->getOnlyTree()->isLeaf())

1237      ClassName = "SDNode";

1238    else {

1239      Record *Op = PatFragRec->getOnlyTree()->getOperator();

1240      ClassName = PatFragRec->getDAGPatterns().getSDNodeInfo(Op).getSDClassName();

1241    }

1242    std::string Result;

1243    if (ClassName == "SDNode")

1244      Result = "    SDNode *N = Node;\n";

1245    else

1246      Result = "    auto *N = cast<" + ClassName.str() + ">(Node);\n";

1247 

1248    return Result + getPredCode();

1249  }

V7.0定义了PatFrag的基类PatFrags,其中ImmediateCode是派生定义ImmLeaf使用的用于判断立即数的谓词代码片段,IsLoadIsStoreIsUnindexed等则是与LoadSDNodeStoreSDNode相关的。这  两者是矛盾的。12241226行的immCodeUsesAPFloat()immCodeUsesAPInt()分别判断ImmLeaf是否封装了IsAPFloatIsAPInt

如果谓词代码字符串在NodePredicatesByCodeToRun里没有关联的TreePattern对象,即该字符串是第一次出现(不同的TreePattern对象共享相同的字符串),将该TreePredicateFn对象(Pred)保存在容器NodePredicates中(类型std::vector<TreePredicateFn>),把它在该容器的索引作为要求的序号。

MatcherTableEmitter::EmitMatcher(续)

205       case Matcher::RecordNode:

206         OS << "OPC_RecordNode,";

207         if (!OmitComments)

208           OS.PadToColumn(CommentIndent) << "// #"

209             << cast<RecordMatcher>(N)->getResultNo() << " = "

210             << cast<RecordMatcher>(N)->getWhatFor();

211         OS << '\n';

212         return 1;

213    

214       case Matcher::RecordChild:

215         OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo()

216            << ',';

217         if (!OmitComments)

218           OS.PadToColumn(CommentIndent) << "// #"

219             << cast<RecordChildMatcher>(N)->getResultNo() << " = "

220             << cast<RecordChildMatcher>(N)->getWhatFor();

221         OS << '\n';

222         return 1;

223    

224       case Matcher::RecordMemRef:

225         OS << "OPC_RecordMemRef,\n";

226         return 1;

227    

228       case Matcher::CaptureGlueInput:

229         OS << "OPC_CaptureGlueInput,\n";

230         return 1;

231    

232       case Matcher::MoveChild:                                                                                <-- v7.0删除

233         OS << "OPC_MoveChild, " << cast<MoveChildMatcher>(N)->getChildNo() << ",\n";

234         return 2;

 

  case Matcher::MoveChild: {                                                                              <-- v7.0增加

    const auto *MCM = cast<MoveChildMatcher>(N);

 

    OS << "OPC_MoveChild";

    // Handle the specialized forms.

    if (MCM->getChildNo() >= 8)

      OS << ", ";

    OS << MCM->getChildNo() << ",\n";

    return (MCM->getChildNo() >= 8) ? 2 : 1;

  }

235    

236       case Matcher::MoveParent:

237         OS << "OPC_MoveParent,\n";

238         return 1;

239    

240       case Matcher::CheckSame:

241         OS << "OPC_CheckSame, "

242            << cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n";

243         return 2;

244    

245       case Matcher::CheckChildSame:

246         OS << "OPC_CheckChild"

247            << cast<CheckChildSameMatcher>(N)->getChildNo() << "Same, "

248            << cast<CheckChildSameMatcher>(N)->getMatchNumber() << ",\n";

249         return 2;

250    

251       case Matcher::CheckPatternPredicate: {

252         StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate();

253         OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ',';

254         if (!OmitComments)

255           OS.PadToColumn(CommentIndent) << "// " << Pred;

256         OS << '\n';

257         return 2;

258       }

259       case Matcher::CheckPredicate: {

260         TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate();

261         OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ',';

262         if (!OmitComments)

263           OS.PadToColumn(CommentIndent) << "// " << Pred.getFnName();

264         OS << '\n';

265         return 2;

266       }

267    

268       case Matcher::CheckOpcode:

269         OS << "OPC_CheckOpcode, TARGET_VAL("

270            << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n";

271         return 3;

272    

273       case Matcher::SwitchOpcode:

274       case Matcher::SwitchType: {

275         unsigned StartIdx = CurrentIdx;

276    

277         unsigned NumCases;

278         if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {

279           OS << "OPC_SwitchOpcode ";

280           NumCases = SOM->getNumCases();

281         } else {

282           OS << "OPC_SwitchType ";

283           NumCases = cast<SwitchTypeMatcher>(N)->getNumCases();

284         }

285    

286         if (!OmitComments)

287           OS << "/*" << NumCases << " cases */";

288         OS << ", ";

289         ++CurrentIdx;

290    

291         // For each case we emit the size, then the opcode, then the matcher.

292         for (unsigned i = 0, e = NumCases; i != e; ++i) {

293           const Matcher *Child;

294           unsigned IdxSize;

295           if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {

296             Child = SOM->getCaseMatcher(i);

297             IdxSize = 2;  // size of opcode in table is 2 bytes.

298           } else {

299             Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);

300             IdxSize = 1;  // size of type in table is 1 byte.

301           }

302    

303           // We need to encode the opcode and the offset of the case code before

304           // emitting the case code.  Handle this by buffering the output into a

305           // string while we get the size.  Unfortunately, the offset of the

306           // children depends on the VBR size of the child, so for large children we

307           // have to iterate a bit.

308           SmallString<128> TmpBuf;

309           unsigned ChildSize = 0;

310           unsigned VBRSize = 0;

311           do {

312             VBRSize = GetVBRSize(ChildSize);

313    

314             TmpBuf.clear();

315             raw_svector_ostream OS(TmpBuf);

316             formatted_raw_ostream FOS(OS);

317             ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize,

318                                         FOS);

319           } while (GetVBRSize(ChildSize) != VBRSize);

320    

321           assert(ChildSize != 0 && "Should not have a zero-sized child!");

322    

323           if (i != 0) {

324             if (!OmitComments)

325               OS << "/*" << CurrentIdx << "*/";

326             OS.PadToColumn(Indent*2);

327             if (!OmitComments)

328               OS << (isa<SwitchOpcodeMatcher>(N) ?

329                          "/*SwitchOpcode*/ " : "/*SwitchType*/ ");

330           }

331    

332           // Emit the VBR.

333           CurrentIdx += EmitVBRValue(ChildSize, OS);

334    

335           if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))

336             OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),";

337           else

338             OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ',';

339    

340           CurrentIdx += IdxSize;

341    

342           if (!OmitComments)

343             OS << "// ->" << CurrentIdx+ChildSize;

344           OS << '\n';

345           OS << TmpBuf;

346           CurrentIdx += ChildSize;

347         }

348    

349         // Emit the final zero to terminate the switch.

350         if (!OmitComments)

351           OS << "/*" << CurrentIdx << "*/";

352         OS.PadToColumn(Indent*2) << "0, ";

353         if (!OmitComments)

354           OS << (isa<SwitchOpcodeMatcher>(N) ?

355                  "// EndSwitchOpcode" : "// EndSwitchType");

356    

357         OS << '\n';

358         ++CurrentIdx;

359         return CurrentIdx-StartIdx;

360       }

这里输出的OPC_*是定义在SelectionDAGISel(执行指令选择的类)中类型为BuiltinOpcodes的枚举值,SelectionDAGISel::SelectCodeCommon()将根据这些值执行相应的操作。方法getEnumName()将类型枚举值的字符串返回。对SwitchOpcodeMatcher,SwitchTypeMatcher的处理与ScopeMatcher十分类似。因为操作码的数目超过了127,因此SwitchOpcodeMatcher的输出需要TARGET_VAL宏(输出这两个字节:val & 255, unsigned(val) >> 8)。

V7.0增加了对多个结果类型的支持,因此将会有这样的输出(针对mgather指令):

/*561207*/      OPC_CheckType, MVT::v4i32,

/*561209*/      OPC_CheckTypeRes, 1, MVT::v4i32,

MatcherTableEmitter::EmitMatcher(续)

362     case Matcher::CheckType:

363         assert(cast<CheckTypeMatcher>(N)->getResNo() == 0 &&                                   <-- v7.0删除

364                "FIXME: Add support for CheckType of resno != 0");

365         OS << "OPC_CheckType, "

366            << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n";

367         return 2;

 

    if (cast<CheckTypeMatcher>(N)->getResNo() == 0) {                                             <-- v7.0增加

      OS << "OPC_CheckType, "

         << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n";

      return 2;

    }

    OS << "OPC_CheckTypeRes, " << cast<CheckTypeMatcher>(N)->getResNo()

       << ", " << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n";

    return 3;

368    

369       case Matcher::CheckChildType:

370         OS << "OPC_CheckChild"

371            << cast<CheckChildTypeMatcher>(N)->getChildNo() << "Type, "

372            << getEnumName(cast<CheckChildTypeMatcher>(N)->getType()) << ",\n";

373         return 2;

374    

375       case Matcher::CheckInteger: {

376         OS << "OPC_CheckInteger, ";

377         unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);

378         OS << '\n';

379         return Bytes;

380       }

381       case Matcher::CheckChildInteger: {

382         OS << "OPC_CheckChild" << cast<CheckChildIntegerMatcher>(N)->getChildNo()

383            << "Integer, ";

384         unsigned Bytes=1+EmitVBRValue(cast<CheckChildIntegerMatcher>(N)->getValue(),

385                                       OS);

386         OS << '\n';

387         return Bytes;

388       }

389       case Matcher::CheckCondCode:

390         OS << "OPC_CheckCondCode, ISD::"

391            << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n";

392         return 2;

393    

394       case Matcher::CheckValueType:

395         OS << "OPC_CheckValueType, MVT::"

396            << cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n";

397         return 2;

398    

399       case Matcher::CheckComplexPat: {

400         const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N);

401         const ComplexPattern &Pattern = CCPM->getPattern();

402         OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/"

403            << CCPM->getMatchNumber() << ',';

404    

405         if (!OmitComments) {

406           OS.PadToColumn(CommentIndent) << "// " << Pattern.getSelectFunc();

407           OS << ":$" << CCPM->getName();

408           for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i)

409             OS << " #" << CCPM->getFirstResult()+i;

410    

411           if (Pattern.hasProperty(SDNPHasChain))

412             OS << " + chain result";

413         }

414         OS << '\n';

415         return 3;

416       }

417    

418       case Matcher::CheckAndImm: {

419         OS << "OPC_CheckAndImm, ";

420         unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS);

421         OS << '\n';

422         return Bytes;

423       }

424    

425       case Matcher::CheckOrImm: {

426         OS << "OPC_CheckOrImm, ";

427         unsigned Bytes = 1+EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS);

428         OS << '\n';

429         return Bytes;

430       }

431    

432       case Matcher::CheckFoldableChainNode:

433         OS << "OPC_CheckFoldableChainNode,\n";

434         return 1;

435    

436       case Matcher::EmitInteger: {

437         int64_t Val = cast<EmitIntegerMatcher>(N)->getValue();

438         OS << "OPC_EmitInteger, "

439            << getEnumName(cast<EmitIntegerMatcher>(N)->getVT()) << ", ";

440         unsigned Bytes = 2+EmitVBRValue(Val, OS);

441         OS << '\n';

442         return Bytes;

443       }

444       case Matcher::EmitStringInteger: {

445         const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue();

446         // These should always fit into one byte.

447         OS << "OPC_EmitInteger, "

448           << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", "

449           << Val << ",\n";

450         return 3;

451       }

452    

453       case Matcher::EmitRegister: {

454         const EmitRegisterMatcher *Matcher = cast<EmitRegisterMatcher>(N);

455         const CodeGenRegister *Reg = Matcher->getReg();

456         // If the enum value of the register is larger than one byte can handle,

457         // use EmitRegister2.

458         if (Reg && Reg->EnumValue > 255) {

459           OS << "OPC_EmitRegister2, " << getEnumName(Matcher->getVT()) << ", ";

460           OS << "TARGET_VAL(" << getQualifiedName(Reg->TheDef) << "),\n";

461           return 4;

462         } else {

463           OS << "OPC_EmitRegister, " << getEnumName(Matcher->getVT()) << ", ";

464           if (Reg) {

465             OS << getQualifiedName(Reg->TheDef) << ",\n";

466           } else {

467             OS << "0 ";

468             if (!OmitComments)

469               OS << "/*zero_reg*/";

470             OS << ",\n";

471           }

472           return 3;

473         }

474       }

475    

476       case Matcher::EmitConvertToTarget:

477         OS << "OPC_EmitConvertToTarget, "

478            << cast<EmitConvertToTargetMatcher>(N)->getSlot() << ",\n";

479         return 2;

480    

481       case Matcher::EmitMergeInputChains: {

482         const EmitMergeInputChainsMatcher *MN =

483           cast<EmitMergeInputChainsMatcher>(N);

484    

485         // Handle the specialized forms OPC_EmitMergeInputChains1_0 and 1_1.

486         if (MN->getNumNodes() == 1 && MN->getNode(0) < 2) {

487           OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n";

488           return 1;

489         }

490    

491         OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", ";

492         for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i)

493           OS << MN->getNode(i) << ", ";

494         OS << '\n';

495         return 2+MN->getNumNodes();

496       }

497       case Matcher::EmitCopyToReg:

498         OS << "OPC_EmitCopyToReg, "

499            << cast<EmitCopyToRegMatcher>(N)->getSrcSlot() << ", "

500            << getQualifiedName(cast<EmitCopyToRegMatcher>(N)->getDestPhysReg())

501            << ",\n";

502         return 3;

503       case Matcher::EmitNodeXForm: {

504         const EmitNodeXFormMatcher *XF = cast<EmitNodeXFormMatcher>(N);

505         OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", "

506            << XF->getSlot() << ',';

507         if (!OmitComments)

508           OS.PadToColumn(CommentIndent) << "// "<<XF->getNodeXForm()->getName();

509         OS <<'\n';

510         return 3;

511       }

这里面要注意EmitStringInteger实际输出的是OPC_EmitInteger,因为它的内容是字符串形式的整数。

V7.0引入了一个新选项“instrument-coverage”(变量InstrumentCoverage,缺省为false)来生成辅助识别匹配模式的表。GetPatFromTreePatternNode()得到的字符串内容与下面556行输出的源目标内容是类似的,是这个样子:

Src: (X86masked_gather:{ *:[v4i64] }:{ *:[v4i64] } VR256:{ *:[v4i64] }:$src1, VR256:{ *:[v4i64] }:$mask, vectoraddr:{ *:[iPTR] }:$src2)<<P:Predicate_mgatherv4i64>>

另外,对具有3个类型以下的MorphNodeToMatcherEmitNodeMatcher为了节省编码大小(少一个字节),输出形如OPC_MorphNodeTo1的编码。

MatcherTableEmitter::EmitMatcher(续)

513       case Matcher::EmitNode:

514       case Matcher::MorphNodeTo: {

    auto NumCoveredBytes = 0;                                                                                           <-- v7.0增加

    if (InstrumentCoverage) {

      if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {

        NumCoveredBytes = 3;

        OS << "OPC_Coverage, ";

        std::string src =

            GetPatFromTreePatternNode(SNT->getPattern().getSrcPattern());

        std::string dst =

            GetPatFromTreePatternNode(SNT->getPattern().getDstPattern());

        Record *PatRecord = SNT->getPattern().getSrcRecord();

        std::string include_src = getIncludePath(PatRecord);

        unsigned Offset =

            getPatternIdxFromTable(src + " -> " + dst, std::move(include_src));

        OS << "TARGET_VAL(" << Offset << "),\n";

        OS.indent(FullIndexWidth + Indent * 2);

      }

    }

515         const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N);

516         OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo");

    bool CompressVTs = EN->getNumVTs() < 3;                                                          <-- v7.0增加

    if (CompressVTs)

      OS << EN->getNumVTs();

517         OS << ", TARGET_VAL(" << EN->getOpcodeName() << "), 0";

518    

519         if (EN->hasChain())   OS << "|OPFL_Chain";

520         if (EN->hasInFlag())  OS << "|OPFL_GlueInput";

521         if (EN->hasOutFlag()) OS << "|OPFL_GlueOutput";

522         if (EN->hasMemRefs()) OS << "|OPFL_MemRefs";

523         if (EN->getNumFixedArityOperands() != -1)

524           OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();

525         OS << ",\n";

526    

527         OS.PadToColumn(Indent*2+4) << EN->getNumVTs();

528         if (!OmitComments)                                                                                               <-- v7.0删除

529           OS << "/*#VTs*/";

530         OS << ", ";

    if (!CompressVTs) {                                                                                                 <-- v7.0增加

      OS << EN->getNumVTs();

      if (!OmitComments)

        OS << "/*#VTs*/";

      OS << ", ";

    }

531         for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i)

532           OS << getEnumName(EN->getVT(i)) << ", ";

533    

534         OS << EN->getNumOperands();

535         if (!OmitComments)

536           OS << "/*#Ops*/";

537         OS << ", ";

538         unsigned NumOperandBytes = 0;

539         for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i)

540           NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS);

541    

542         if (!OmitComments) {

543           // Print the result #'s for EmitNode.

544           if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) {

545             if (unsigned NumResults = EN->getNumVTs()) {

546               OS.PadToColumn(CommentIndent) << "// Results =";

547               unsigned First = E->getFirstResultSlot();

548               for (unsigned i = 0; i != NumResults; ++i)

549                 OS << " #" << First+i;

550             }

551           }

552           OS << '\n';

553    

554           if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {

555             OS.PadToColumn(Indent*2) << "// Src: "

556               << *SNT->getPattern().getSrcPattern() << " - Complexity = "

557               << SNT->getPattern().getPatternComplexity(CGP) << '\n';

558             OS.PadToColumn(Indent*2) << "// Dst: "

559               << *SNT->getPattern().getDstPattern() << '\n';

560           }

561         } else

562           OS << '\n';

563    

564         return 6+EN->getNumVTs()+NumOperandBytes;                                               <-- v7.0删除

    return 5 + !CompressVTs + EN->getNumVTs() + NumOperandBytes +           <-- v7.0增加

           NumCoveredBytes;

565       }

566       case Matcher::MarkGlueResults: {                                                                             <-- v7.0删除

567         const MarkGlueResultsMatcher *CFR = cast<MarkGlueResultsMatcher>(N);

568         OS << "OPC_MarkGlueResults, " << CFR->getNumNodes() << ", ";

569         unsigned NumOperandBytes = 0;

570         for (unsigned i = 0, e = CFR->getNumNodes(); i != e; ++i)

571          NumOperandBytes += EmitVBRValue(CFR->getNode(i), OS);

572         OS << '\n';

573         return 2+NumOperandBytes;

574       }

575       case Matcher::CompleteMatch: {

576         const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N);

    auto NumCoveredBytes = 0;                                                                                      <-- v7.0增加

    if (InstrumentCoverage) {

      NumCoveredBytes = 3;

      OS << "OPC_Coverage, ";

      std::string src =

          GetPatFromTreePatternNode(CM->getPattern().getSrcPattern());

      std::string dst =

          GetPatFromTreePatternNode(CM->getPattern().getDstPattern());

      Record *PatRecord = CM->getPattern().getSrcRecord();

      std::string include_src = getIncludePath(PatRecord);

      unsigned Offset =

          getPatternIdxFromTable(src + " -> " + dst, std::move(include_src));

      OS << "TARGET_VAL(" << Offset << "),\n";

      OS.indent(FullIndexWidth + Indent * 2);

}

577         OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", ";

578         unsigned NumResultBytes = 0;

579         for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)

580           NumResultBytes += EmitVBRValue(CM->getResult(i), OS);

581         OS << '\n';

582         if (!OmitComments) {

583           OS.PadToColumn(Indent*2) << "// Src: "

584             << *CM->getPattern().getSrcPattern() << " - Complexity = "

585             << CM->getPattern().getPatternComplexity(CGP) << '\n';

586           OS.PadToColumn(Indent*2) << "// Dst: "

587             << *CM->getPattern().getDstPattern();

588         }

589         OS << '\n';

590         return 2 + NumResultBytes;                                                                              <-- v7.0删除

    return 2 + NumResultBytes + NumCoveredBytes;                                        <-- v7.0增加

591       }

592       }

593       llvm_unreachable("Unreachable");

594     }

MorphNodeToMatcher对象是EmitNodeMatcher对象及紧接的CompleteMatchMatcher对象优化的结果(EmitNodeMatcher后面一般都跟着CompleteMatchMatcher,不过也有例外。而且这样的序列也不总是能优化的)。MorphNodeToMatcher与EmitNodeMatcher+CompleteMatchMatcher都表示匹配成功,并且输出结果。

这里要做的只是把这些对象的内容按顺序输出,在后面SelectionDAGISel::SelectCodeCommon()将照管这一切。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值