LLVM学习笔记(16)

来源:互联网 发布:封天战神坐骑进阶数据 编辑:程序博客网 时间:2024/05/20 09:25

3.4.2.4.       PatFrag的处理

3.4.2.4.1. 模式树的构建

PatFrag是一个可重用的构件,TableGen会在PatFrag出现的地方展开其定义,有点像C/C++中的宏。为此,CodeGenDAGPatterns将每个可能嵌入PatFrag的定义——Instruction,Pattern,Pat以及PatFrag,构建为一棵TreePattern树,并在适当的时候将其中包含的PatFrag展开(这是个递归的过程,会一直进行到PatFrag不存在为止)。

函数CodeGenDAGPatterns::ParsePatternFragments处理、展开所有的PatFrag定义。首先在2428行循环为所有的PatFrag定义生成模式树,并进行一些有效性检查。

2424   void CodeGenDAGPatterns::ParsePatternFragments(boolOutFrags) {

2425     std::vector<Record*> Fragments =Records.getAllDerivedDefinitions("PatFrag");

2426  

2427     // First step,parse all of the fragments.

2428     for (unsignedi = 0, e = Fragments.size(); i != e; ++i) {

2429       if (OutFrags !=Fragments[i]->isSubClassOf("OutPatFrag"))

2430         continue;

2431  

2432       DagInit *Tree = Fragments[i]->getValueAsDag("Fragment");

2433       TreePattern *P =

2434           (PatternFragments[Fragments[i]] =llvm::make_unique<TreePattern>(

2435                Fragments[i], Tree,!Fragments[i]->isSubClassOf("OutPatFrag"),

2436                *this)).get();

2437  

2438       // Validate theargument list, converting it to set, to discard duplicates.

2439       std::vector<std::string> &Args =P->getArgList();

2440       std::set<std::string>OperandsSet(Args.begin(), Args.end());

2441  

2442       if (OperandsSet.count(""))

2443         P->error("Cannot have unnamed'node' values in pattern fragment!");

2444  

2445       // Parse theoperands list.

2446       DagInit *OpsList =Fragments[i]->getValueAsDag("Operands");

2447       DefInit *OpsOp = dyn_cast<DefInit>(OpsList->getOperator());

2448       // Specialcases: ops == outs == ins. Different names are used to

2449       // improvereadability.

2450       if (!OpsOp ||

2451           (OpsOp->getDef()->getName() !="ops" &&

2452            OpsOp->getDef()->getName() !="outs" &&

2453            OpsOp->getDef()->getName() !="ins"))

2454         P->error("Operands list shouldstart with '(ops ... '!");

2455  

2456       // Copy overthe arguments.

2457       Args.clear();

2458       for(unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) {

2459         if(!isa<DefInit>(OpsList->getArg(j)) ||

2460            cast<DefInit>(OpsList->getArg(j))->getDef()->getName() !="node")

2461           P->error("Operands list shouldall be 'node' values.");

2462         if (OpsList->getArgName(j).empty())

2463           P->error("Operands list shouldhave names for each operand!");

2464         if(!OperandsSet.count(OpsList->getArgName(j)))

2465           P->error("'" +OpsList->getArgName(j) +

2466                    "' does not occur inpattern or was multiply specified!");

2467        OperandsSet.erase(OpsList->getArgName(j));

2468        Args.push_back(OpsList->getArgName(j));

2469       }

2470  

2471       if (!OperandsSet.empty())

2472         P->error("Operands list does not containan entry for operand '" +

2473                  *OperandsSet.begin() +"'!");

2474  

2475      // If there isa code init for this fragment, keep track of the fact that

2476       // thisfragment uses it.

2477       TreePredicateFn PredFn(P);

2478       if (!PredFn.isAlwaysTrue())

2479        P->getOnlyTree()->addPredicateFn(PredFn);

2480  

2481       // If there isa node transformation corresponding to this, keep track of

2482       // it.

2483       Record *Transform =Fragments[i]->getValueAsDef("OperandTransform");

2484       if(!getSDNodeTransform(Transform).second.empty())   // not noopxform?

2485        P->getOnlyTree()->setTransformFn(Transform);

2486     }

2487  

2488     // Now that we'veparsed all of the tree fragments, do a closure on them so

2489     // that there arenot references to PatFrags left inside of them.

2490     for (unsignedi = 0, e = Fragments.size(); i != e; ++i) {

2491       if (OutFrags !=Fragments[i]->isSubClassOf("OutPatFrag"))

2492         continue;

2493  

2494       TreePattern &ThePat = *PatternFragments[Fragments[i]];

2495       ThePat.InlinePatternFragments();

2496  

2497       // Infer asmany types as possible.  Don't worryabout it if we don't infer

2498       // all of them,some may depend on the inputs of the pattern.

2499       ThePat.InferAllTypes();

2500       ThePat.resetError();

2501  

2502       // Ifdebugging, print out the pattern fragment result.

2503       DEBUG(ThePat.dump());

2504     }

2505   }

在CodeGenDAGPatterns构造函数里两次调用了ParsePatternFragments,第一次参数OutFrags是false,表示不考虑OutPatFrag类型的定义。2434行的llvm::make_unique(std::make_unique的实现)会调用new操作符构建一个TreePattern实例,并返回一个std::unique_ptr<TreePattern>对象。因此,成员PatternFragments是类型为std::map<Record*, std::unique_ptr<TreePattern>, LessRecordByID>的容器。调用到的TreePattern的构造函数定义在CodeGenDAGPatterns.cpp里:

2006   TreePattern::TreePattern(Record*TheRec, DagInit *Pat, bool isInput,

2007                            CodeGenDAGPatterns&cdp) : TheRecord(TheRec), CDP(cdp),

2008                           isInputPattern(isInput), HasError(false) {

2009     Trees.push_back(ParseTreePattern(Pat, ""));

2010   }

注意只要这个PatFrag不是OutPatFrag的派生定义,参数isInputPattern就是false。2009行的Trees是TreePattern中类型为std::vector<TreePatternNode*>的容器,显然TreePatternNode用作树的节点。PatFrag的具体解析由ParseTreePattern完成,参数TheInit是PatFrag定义中的Fragment(匹配片段):

2040   TreePatternNode *TreePattern::ParseTreePattern(Init*TheInit, StringRef OpName){

2041     if (DefInit *DI = dyn_cast<DefInit>(TheInit)){

2042       Record *R = DI->getDef();

2043  

2044      // Directreference to a leaf DagNode or PatFrag? Turn it into a

2045      //TreePatternNode of its own.  For example:

2046      ///   (foo GPR, imm) -> (foo GPR, (imm))

2047       if (R->isSubClassOf("SDNode")|| R->isSubClassOf("PatFrag"))

2048         returnParseTreePattern(

2049           DagInit::get(DI, "",

2050                       std::vector<std::pair<Init*, std::string> >()),

2051           OpName);

2052  

2053      // Inputargument?

2054       TreePatternNode *Res = new TreePatternNode(DI,1);

2055       if (R->getName() == "node"&& !OpName.empty()) {

2056         if (OpName.empty())

2057           error("'node' argument requires aname to match with operand list");

2058         Args.push_back(OpName);

2059       }

2060  

2061       Res->setName(OpName);

2062       return Res;

2063     }

2064  

2065    // ?:$name orjust $name.

2066     if (isa<UnsetInit>(TheInit)) {

2067       if (OpName.empty())

2068         error("'?' argument requires a nameto match with operand list");

2069       TreePatternNode *Res = new TreePatternNode(TheInit,1);

2070       Args.push_back(OpName);

2071       Res->setName(OpName);

2072       return Res;

2073     }

2074  

2075     if (IntInit *II =dyn_cast<IntInit>(TheInit)) {

2076       if (!OpName.empty())

2077         error("Constant int argument shouldnot have a name!");

2078       return new TreePatternNode(II,1);

2079     }

2080  

2081     if (BitsInit *BI =dyn_cast<BitsInit>(TheInit)) {

2082      // Turn thisinto an IntInit.

2083       Init *II =BI->convertInitializerTo(IntRecTy::get());

2084       if (!II || !isa<IntInit>(II))

2085         error("Bits value must beconstants!");

2086       returnParseTreePattern(II, OpName);

2087     }

2088  

2089     DagInit *Dag =dyn_cast<DagInit>(TheInit);

2090     if (!Dag) {

2091       TheInit->dump();

2092       error("Pattern has unexpected initkind!");

2093     }

2094     DefInit *OpDef =dyn_cast<DefInit>(Dag->getOperator());

2095     if (!OpDef) error("Pattern hasunexpected operator type!");

2096     Record *Operator = OpDef->getDef();

2097  

2098     if (Operator->isSubClassOf("ValueType")){

2099      // If theoperator is a ValueType, then this must be "type cast" of a leaf

2100      // node.

2101       if (Dag->getNumArgs() != 1)

2102         error("Type cast only takes oneoperand!");

2103  

2104       TreePatternNode *New =ParseTreePattern(Dag->getArg(0), Dag->getArgName(0));

2105  

2106      // Apply thetype cast.

2107       assert(New->getNumTypes()== 1 && "FIXME: Unhandled");

2108       New->UpdateNodeType(0,getValueType(Operator), *this);

2109  

2110       if (!OpName.empty())

2111         error("ValueType cast should nothave a name!");

2112       return New;

2113     }

2114  

2115    // Verify thatthis is something that makes sense for an operator.

2116     if(!Operator->isSubClassOf("PatFrag") &&

2117        !Operator->isSubClassOf("SDNode") &&

2118        !Operator->isSubClassOf("Instruction") &&

2119        !Operator->isSubClassOf("SDNodeXForm") &&

2120        !Operator->isSubClassOf("Intrinsic") &&

2121        !Operator->isSubClassOf("ComplexPattern") &&

2122         Operator->getName() != "set"&&

2123         Operator->getName() !="implicit")

2124       error("Unrecognized node '" +Operator->getName() + "'!");

2125  

2126    //  Check to see if this is something that isillegal in an input pattern.

2127     if (isInputPattern) {

2128       if(Operator->isSubClassOf("Instruction") ||

2129          Operator->isSubClassOf("SDNodeXForm"))

2130         error("Cannot use '" +Operator->getName() + "' in an input pattern!");

2131     } else {

2132       if(Operator->isSubClassOf("Intrinsic"))

2133         error("Cannot use '" +Operator->getName() + "' in an output pattern!");

2134  

2135       if(Operator->isSubClassOf("SDNode") &&

2136           Operator->getName() !="imm" &&

2137           Operator->getName() !="fpimm" &&

2138           Operator->getName() !="tglobaltlsaddr" &&

2139           Operator->getName() !="tconstpool" &&

2140           Operator->getName() !="tjumptable" &&

2141           Operator->getName() !="tframeindex" &&

2142           Operator->getName() !="texternalsym" &&

2143           Operator->getName() !="tblockaddress" &&

2144           Operator->getName() !="tglobaladdr" &&

2145           Operator->getName() !="bb" &&

2146           Operator->getName() !="vt" &&

2147           Operator->getName() !="mcsym")

2148         error("Cannot use '" +Operator->getName() + "' in an output pattern!");

2149    }

PatFrag的匹配片段(Fragment)通常是一个dag值,Fragment的操作数也可以包含PatFrag(当然要满足一定的条件),因此ParseTreePattern先递归处理Fragment的操作数。

如果要匹配的部分是一个SDNode或PatFrag,在2049行构建一个自己为操作符,没有操作数的匿名的dag值(DagInit实例),然后新调用ParseTreePattern。这个处理非常重要,DagInit生成的树节点不是叶子节点,即使它没有子节点,后面进行的内联、展开是不对叶子节点进行的。其他的DefInit(对应一个def定义)就可以直接生成TreePatternNode实例。但如果这是一个node(一个空def,参见TargetSelectionDAG.TD的310行),它必须具名(node:$name)。

类似的,UnsetInit(表示未初始化的值)、IntInit(TD整数常量)、BitsInit(TD比特值)都必须是具名的,而且BitsInit还必须是常量。不能匿名是因为TableGen需要通过名字将它们匹配到模式片段的操作数。它们都对应一个TreePatternNode实例。

349        TreePatternNode(Init *val,unsigned NumResults)    // leaf ctor

350          : Operator(nullptr), Val(val),TransformFn(nullptr) {

351          Types.resize(NumResults);

352        }

在这个调用里,NumResults为1,因为叶子节点只产生一个结果。

而如果要匹配的部分是一个dag。这个dag可以是一个PatFrag,还可能是上面2049行为SDNode与PatFrag生成的。

从这里的代码可以看出,Fragment所包含dag的操作符无外乎这些定义:ValueType,PatFrag,SDNode,Instruction,SDNodeXForm,Intrinsic,ComplexPattern,或者特殊节点set或implicit,其中Instruction,SDNodeXForm不允许用于输入模式。至于OutPatFrag,SDNode还被进一步限定为imm,fpimm,tglobaltlsaddr,tconstpool,tjumptable,tframeindex,texternalsym,tblockaddress,tglobaladdr,bb,vt,mcsym之一。

在这中间,ValueType类型的操作符代表一个类型转换,必须有且只有一个操作数。那么对它的操作数调用ParseTreePattern进行解析,在2108行把对应树节点的类型更新为这个ValueType代表类型。执行更新操作的TreePatternNode::UpdateNodeType定义如下(CodeGenDAGPatterns.h):

486        bool UpdateNodeType(unsigned ResNo,MVT::SimpleValueType InTy,

487                            TreePattern &TP) {

488          returnTypes[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy,TP), TP);

489        }

MVT::SimpleValueType是一个枚举类型,它与ValueType中Value域的值一一对应。EEVT::TypeSet表示类型的集合,它在内部维护一个SmallVector<MVT::SimpleValueType,4>类型的容器TypeVec。488行的Types是一个SmallVector<EEVT::TypeSet,1>容器,由其MergeInTypeInfo方法执行类型推导。

165      bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){

166        if (InVT.isCompletelyUnknown() || *this == InVT || TP.hasError())

167          returnfalse;

168     

169        if (isCompletelyUnknown()) {

170          *this =InVT;

171          returntrue;

172        }

173     

174        assert(TypeVec.size()>= 1 && InVT.TypeVec.size() >= 1 && "Nounknowns");

175     

176       // Handle theabstract cases, seeing if we can resolve them better.

177        switch(TypeVec[0]) {

178        default: break;

179        caseMVT::iPTR:

180        caseMVT::iPTRAny:

181          if (InVT.hasIntegerTypes()) {

182            EEVT::TypeSet InCopy(InVT);

183            InCopy.EnforceInteger(TP);

184            InCopy.EnforceScalar(TP);

185     

186            if (InCopy.isConcrete()) {

187             // If theRHS has one integer type, upgrade iPTR to i32.

188              TypeVec[0] = InVT.TypeVec[0];

189              returntrue;

190            }

191     

192           // If theinput has multiple scalar integers, this doesn't add any info.

193            if (!InCopy.isCompletelyUnknown())

194              returnfalse;

195          }

196          break;

197        }

198     

199        // If the inputconstraint is iAny/iPTR and this is an integer type list,

200        // removenon-integer types from the list.

201        if ((InVT.TypeVec[0] == MVT::iPTR ||InVT.TypeVec[0] == MVT::iPTRAny) &&

202            hasIntegerTypes()) {

203          bool MadeChange = EnforceInteger(TP);

204     

205         // If we'remerging in iPTR/iPTRAny and the node currently has a list of

206         // multipledifferent integer types, replace them with a single iPTR.

207          if ((InVT.TypeVec[0] == MVT::iPTR ||InVT.TypeVec[0] == MVT::iPTRAny) &&

208              TypeVec.size() != 1) {

209            TypeVec.resize(1);

210            TypeVec[0] = InVT.TypeVec[0];

211            MadeChange = true;

212          }

213     

214          returnMadeChange;

215        }

216     

217       // If this is atype list and the RHS is a typelist as well, eliminate entries

218       // from this listthat aren't in the other one.

219        bool MadeChange = false;

220        TypeSet InputSet(*this);

221     

222        for (unsignedi = 0; i != TypeVec.size(); ++i) {

223          bool InInVT = false;

224          for(unsigned j = 0, e = InVT.TypeVec.size(); j != e; ++j)

225            if (TypeVec[i] == InVT.TypeVec[j]) {

226              InInVT = true;

227              break;

228            }

229     

230          if (InInVT) continue;

231          TypeVec.erase(TypeVec.begin()+i--);

232          MadeChange = true;

233        }

234     

235       // If we removedall of our types, we have a type contradiction.

236        if (!TypeVec.empty())

237          returnMadeChange;

238     

239        // FIXME: Reallywant an SMLoc here!

240        TP.error("Type inference contradiction found,merging '" +

241                 InVT.getName() + "' into'" + InputSet.getName() + "'");

242        return false;

243      }

基本上MergeInTypeInfo只干这几件事:

如果原有的是指针类型,而新发现的类型包含了整数类型,183与184行的EnforceInteger与EnforceScalar会分别滤除新发现类型中包含的浮点类型与向量类型,如果此时还有整形,就以这个类型来替换原有的指针类型。

如果原有的是整形,而新发现的类型是指针类型,203行的EnforceInteger过滤掉浮点类型后,如果剩余的整形有多个,就替换为指针类型,否则维持原样。

如果不是上述情形,将原有类型集中不在新发现类型集里的类型删除,删除后的类型集不能是空,否则就代表类型冲突。

这段逻辑就是TableGen进行类型推导的依据。这样类型集将会越来越小,最终能确定一个具体的类型。枚举类型MVT::SimpleValueType的定义有助于理解这段代码:

31            enum SimpleValueType {

32             //INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are

33             // consideredextended value types.

34              INVALID_SIMPLE_VALUE_TYPE = -1,

35       

36             // If youchange this numbering, you must change the values in

37             // ValueTypes.tdas well!

38              Other          =  0,  //This is a non-standard value

39              i1             =  1,  //This is a 1 bit integer value

40              i8             =  2,  //This is an 8 bit integer value

41              i16            =  3,  //This is a 16 bit integer value

42              i32            =  4,  //This is a 32 bit integer value

43              i64            =  5,  //This is a 64 bit integer value

44              i128           =  6,  //This is a 128 bit integer value

45       

46              FIRST_INTEGER_VALUETYPE = i1, // ------+-------这个区间满足isInteger

47              LAST_INTEGER_VALUETYPE  = i128,// ----+

48       

49              f16            =  7,  //This is a 16 bit floating point value

50              f32            =  8,  //This is a 32 bit floating point value

51              f64            =  9,  //This is a 64 bit floating point value

52              f80            = 10,  //This is a 80 bit floating point value

53              f128           = 11,  //This is a 128 bit floating point value

54              ppcf128        = 12,  //This is a PPC 128-bit floating point value

55       

56              FIRST_FP_VALUETYPE = f16, // 这个区间还同时满足isFloatingPoint

57              LAST_FP_VALUETYPE  = ppcf128, // >= ppcf128 + iPTR + iPTRAny满足 isConcrete

58       

59              v2i1           = 13,  //  2 x i1

60              v4i1           = 14,  //  4 x i1

61              v8i1           = 15,  //  8 x i1

62              v16i1          = 16,  //16 x i1

63              v32i1          = 17,  //32 x i1

64              v64i1          = 18,  //64 x i1

65       

66              v1i8           = 19,  //  1 x i8

67              v2i8           = 20,  //  2 x i8

68              v4i8           = 21,  //  4 x i8

69              v8i8           = 22,  //  8 x i8

70              v16i8          = 23,  //16 x i8

71              v32i8          = 24,  //32 x i8

72             v64i8          = 25,  //64 x i8

73              v1i16          = 26,  //  1 x i16

74              v2i16          = 27,  //  2 x i16

75              v4i16          = 28,  //  4 x i16

76              v8i16          = 29,  //  8 x i16

77              v16i16         = 30,  //16 x i16

78              v32i16         = 31,  //32 x i16

79              v1i32          = 32,  //  1 x i32

80              v2i32          = 33,  //  2 x i32

81              v4i32          = 34,  //  4 x i32

82              v8i32          = 35,  //  8 x i32

83              v16i32         = 36,  //16 x i32

84              v1i64          = 37,  //  1 x i64

85              v2i64          = 38,  //  2 x i64

86              v4i64          = 39,  //  4 x i64

87              v8i64          = 40,  //  8 x i64

88              v16i64         = 41,  //16 x i64

89              v1i128         = 42,  //  1 x i128

90             

91              FIRST_INTEGER_VECTOR_VALUETYPE = v2i1,// --------+---- 这个区间满足isInteger

92              LAST_INTEGER_VECTOR_VALUETYPE = v1i128,// ------+

93       

94              v2f16          = 43,  //  2 x f16

95              v4f16          = 44,  //  4 x f16

96              v8f16          = 45,  //  8 x f16

97              v1f32          = 46,  //  1 x f32

98              v2f32          = 47,  //  2 x f32

99              v4f32          = 48,  //  4 x f32

100            v8f32          = 49,  //  8 x f32

101            v16f32         = 50,  //16 x f32

102            v1f64          = 51,  //  1 x f64

103            v2f64          = 52,  //  2 x f64

104            v4f64          = 53,  //  4 x f64

105            v8f64          = 54,  //  8 x f64

106     

107            FIRST_FP_VECTOR_VALUETYPE = v2f16,// --------+----这个区间满足isFloatingPoint

108            LAST_FP_VECTOR_VALUETYPE = v8f64,// ---------+

109     

110            FIRST_VECTOR_VALUETYPE = v2i1,// ---- -+---- 这个区间满足isVector

111            LAST_VECTOR_VALUETYPE  = v8f64,// ----+

112     

113            x86mmx         = 55,  //This is an X86 MMX value

114     

115            Glue           = 56,  //This glues nodes together during pre-RA sched

116     

117            isVoid         = 57,  //This has no value

118     

119            Untyped        = 58,  //This value takes a register, but has

120                                   // unspecifiedtype.  The register class

121                                   // will bedetermined by the opcode.

122     

123            FIRST_VALUETYPE = 0,   // This isalways the beginning of the list. ----+

124            LAST_VALUETYPE =  59, // This always remains at the end of the list.  +--这个区间满足isValid

125     

126           // This isthe current maximum for LAST_VALUETYPE.

127           //MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors

128           // This valuemust be a multiple of 32.

129            MAX_ALLOWED_VALUETYPE = 64,

130     

131           // Metadata -This is MDNode or MDString.

132            Metadata       = 250,

133     

134           // iPTRAny -An int value the size of the pointer of the current

135           // target toany address space. This must only be used internal to

136           // tblgen.Other than for overloading, we treat iPTRAny the same as iPTR.

137            iPTRAny        =251,

138     

139           // vAny - Avector with any length and element size. This is used

140           // forintrinsics that have overloadings based on vector types.

141           // This isonly for tblgen's consumption!

142            vAny           = 252,

143     

144           // fAny - Anyfloating-point or vector floating-point value. This is used

145           // forintrinsics that have overloadings based on floating-point types.

146           // This isonly for tblgen's consumption!

147            fAny           = 253,

148     

149           // iAny - Aninteger or vector integer value of any bit width. This is

150           // used forintrinsics that have overloadings based on integer bit widths.

151           // This isonly for tblgen's consumption!

152            iAny           = 254,

153     

154           // iPTR - An int value the size of thepointer of the current

155           //target.  This should only be usedinternal to tblgen!

156            iPTR           = 255,

157     

158           // Any - Anytype. This is used for intrinsics that have overloadings.

159           // This isonly for tblgen's consumption!

160            Any            = 256

161          };

2116~2149行进行有效性检查。对于输入模式的派生定义(除OutPatFrag派生定义,Pattern定义的ResultInstrs也视为输出模式),isInputPattern就是true。输入模式片段不允许使用Instruction和SDNodeXForm作为操作符(因为这两者分别代表结果和对结果的修改)。对于输出模式,限制就更多了,tglobaltlsaddr~tglobaladdr(2138~2144行)表示需要目标机器处理的特定于目标机器的地址,而bb与vt分别代表基本块与ValueType,它们都不能用作模式的操作符。

通过了检查后,在2155行对dag的每个操作数递归调用ParseTreePattern,生成的树节点(子树)保存在临时的Children容器内。

TreePattern::ParseTreePattern(续)

2151    std::vector<TreePatternNode*> Children;

2152  

2153    // Parse all theoperands.

2154     for (unsignedi = 0, e = Dag->getNumArgs(); i != e; ++i)

2155      Children.push_back(ParseTreePattern(Dag->getArg(i),Dag->getArgName(i)));

2156  

2157    // If the operatoris an intrinsic, then this is just syntactic sugar for for

2158    // (intrinsic_*<number>, ..children..).  Pick theright intrinsic node, and

2159    // convert theintrinsic name to a number.

2160     if(Operator->isSubClassOf("Intrinsic")) {

2161       const CodeGenIntrinsic &Int =getDAGPatterns().getIntrinsic(Operator);

2162       unsigned IID =getDAGPatterns().getIntrinsicID(Operator)+1;

2163  

2164      // If thisintrinsic returns void, it must have side-effects and thus a

2165      // chain.

2166       if (Int.IS.RetVTs.empty())

2167         Operator =getDAGPatterns().get_intrinsic_void_sdnode();

2168       else if (Int.ModRef !=CodeGenIntrinsic::NoMem)

2169        // Hasside-effects, requires chain.

2170         Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode();

2171       else //Otherwise, no chain.

2172         Operator =getDAGPatterns().get_intrinsic_wo_chain_sdnode();

2173  

2174       TreePatternNode *IIDNode =new TreePatternNode(IntInit::get(IID), 1);

2175       Children.insert(Children.begin(), IIDNode);

2176     }

2177  

2178     if(Operator->isSubClassOf("ComplexPattern")) {

2179       for(unsigned i = 0; i < Children.size(); ++i) {

2180         TreePatternNode *Child = Children[i];

2181  

2182         if (Child->getName().empty())

2183           error("All arguments to aComplexPattern must be named");

2184  

2185        // Check thatthe ComplexPattern uses are consistent: "(MY_PAT $a, $b)"

2186        // and"(MY_PAT $b, $a)" should not be allowed in the same pattern;

2187        // neither should"(MY_PAT_1 $a, $b)" and "(MY_PAT_2 $a, $b)".

2188         autoOperandId = std::make_pair(Operator, i);

2189         autoPrevOp = ComplexPatternOperands.find(Child->getName());

2190         if (PrevOp !=ComplexPatternOperands.end()) {

2191           if (PrevOp->getValue() != OperandId)

2192             error("All ComplexPatternoperands must appear consistently: "

2193                   "in the same order in justone ComplexPattern instance.");

2194         } else

2195           ComplexPatternOperands[Child->getName()]= OperandId;

2196       }

2197     }

2198  

2199     unsigned NumResults = GetNumNodeResults(Operator, CDP);

2200     TreePatternNode *Result =new TreePatternNode(Operator,Children, NumResults);

2201     Result->setName(OpName);

2202  

2203     if (!Dag->getName().empty()) {

2204       assert(Result->getName().empty());

2205       Result->setName(Dag->getName());

2206     }

2207     returnResult;

2208   }

另外,有两种操作符还需要额外的处理。

第一个是固有函数。前面在CodeGenDAGPatterns构造函数的一开始就通过LoadIntrinsics方法将TD文件里定义的固有函数翻译为了CodeGenIntrinsic对象,因此在2161与2162行分别获取指定固有函数的CodeGenIntrinsic对象与ID。接着根据这个固有函数的特点,使用intrinsic_void_sdnode,intrinsic_w_chain_sdnode或intrinsic_wo_chain_sdnode来封装它。注意,容器Children里已经保存了固有函数参数的模式树节点(2155行的深度优先递归),在2175行将ID插入为第一个操作数,构造成这三个类型所需的形式。

再一个就是ComplexPattern操作符。2189行的ComplexPatternOperands是TreePattern的容器,只由这个模式里的ComplexPattern对象共享。它的类型是StringMap<std::pair<Record*,unsigned>>,StringMap是LLVM将map对string的优化容器。在一个模式中对ComplexPattern的使用(它(们)作为dag值的操作符)有这些限制:1)援引同一个ComplexPattern时,操作数必须具名,且一致,2)援引不同的ComplexPattern时,操作数必须具名,且不相同。

最后为这个dag值的操作符创建它所表示的模式树的根节点。首先需要确定它所代表操作返回的结果数。

1168   static unsignedGetNumNodeResults(Record *Operator,CodeGenDAGPatterns &CDP) {

1169     if (Operator->getName() == "set"||

1170         Operator->getName() =="implicit")

1171       return0;  // Allreturn nothing.

1172  

1173     if(Operator->isSubClassOf("Intrinsic"))

1174       returnCDP.getIntrinsic(Operator).IS.RetVTs.size();

1175  

1176     if (Operator->isSubClassOf("SDNode"))

1177       returnCDP.getSDNodeInfo(Operator).getNumResults();

1178  

1179     if(Operator->isSubClassOf("PatFrag")) {

1180      // If we'vealready parsed this pattern fragment, get it. Otherwise, handle

1181      // the forwardreference case where one pattern fragment references another

1182      // before it isprocessed.

1183       if (TreePattern *PFRec =CDP.getPatternFragmentIfRead(Operator))

1184         returnPFRec->getOnlyTree()->getNumTypes();

1185  

1186      // Get theresult tree.

1187       DagInit *Tree =Operator->getValueAsDag("Fragment");

1188       Record *Op = nullptr;

1189       if (Tree)

1190         if (DefInit *DI =dyn_cast<DefInit>(Tree->getOperator()))

1191           Op = DI->getDef();

1192       assert(Op&& "Invalid Fragment");

1193       returnGetNumNodeResults(Op, CDP);

1194     }

1195  

1196     if(Operator->isSubClassOf("Instruction")) {

1197       CodeGenInstruction &InstInfo =CDP.getTargetInfo().getInstruction(Operator);

1198  

1199       unsigned NumDefsToAdd =InstInfo.Operands.NumDefs;

1200  

1201      // Subtract anydefaulted outputs.

1202       for(unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) {

1203         Record *OperandNode =InstInfo.Operands[i].Rec;

1204  

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

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

1207           --NumDefsToAdd;

1208       }

1209  

1210      // Add on oneimplicit def if it has a resolvable type.

1211       if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo())!=MVT::Other)

1212         ++NumDefsToAdd;

1213       returnNumDefsToAdd;

1214     }

1215  

1216     if(Operator->isSubClassOf("SDNodeXForm"))

1217       return1;  // FIXME:Generalize SDNodeXForm

1218  

1219     if(Operator->isSubClassOf("ValueType"))

1220       return1;  // Atype-cast of one result.

1221  

1222     if(Operator->isSubClassOf("ComplexPattern"))

1223       return 1;

1224  

1225     Operator->dump();

1226     PrintFatalError("Unhandled node inGetNumNodeResults");

1227   }

2200行的TreePatternNode构造函数创建了一个非叶子模式树节点:

344        TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch,

345                        unsigned NumResults)

346          : Operator(Op), Val(nullptr),TransformFn(nullptr), Children(Ch) {

347          Types.resize(NumResults);

348        }

这个生成的节点保存在TreePattern的容器Trees里。

在ParsePatternFragments的2433行,std::unique_ptr<TreePattern>的get方法得到TreePattern指针,TreePattern::getArgList返回PatFrag的输入参数。这些参数是在TreePattern::ParseTreePattern的2058行(node:$name)及2070行(UnsetInit)加入的。在2446行,获取PatFrag定义的Operands域,这是一个dag值。在2447行获取其操作符,操作符只能是ops,ins与outs。2458行循环遍历这个dag值的操作数(模式的参数操作数),确认对这个PatFrag而言,在其Operands与Fragment域中出现的参数是相同的。

接着,为这个PatFrag产生谓词对象TreePredicateFn,它可根据这个PatFrag定义的PredicateCode与ImmediateCode域给出判断代码。这两个域是不能同时为空的。如果两者之一为空,这个谓词就视为总是真的。最后处理PatFrag定义中对输出进行修改的OperandTransform域(SDNodeXForm派生定义)。

3.4.2.4.2. PatFrag的展开

在第一步完成后,2490行的for循环对模式进行展开。在第一次调用时(CodeGenDAGPatterns构造函数的2355行),展开输入模式。在第二次调用时(CodeGenDAGPatterns构造函数的2358行),展开输出模式(OutPatFrag定义)。TreePattern的InlinePatternFragments方法定义如下:

601        voidInlinePatternFragments(){

602          for(unsigned i = 0, e = Trees.size(); i != e; ++i)

603            Trees[i] = Trees[i]->InlinePatternFragments(*this);

604        }

实际上PatFrag都只包含一棵树。不过,其他结构,比如Pattern,Instruction都会调用这个函数,它们可能有多棵模式树。每棵树的展开由TreePatternNode::InlinePatternFragments方法来完成。

1358   TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern&TP) {

1359     if (TP.hasError())

1360       returnnullptr;

1361  

1362     if (isLeaf())

1363        return this// nothing to do.

1364     Record *Op = getOperator();

1365  

1366     if(!Op->isSubClassOf("PatFrag")) {

1367      // Justrecursively inline children nodes.

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

1369         TreePatternNode *Child = getChild(i);

1370         TreePatternNode *NewChild =Child->InlinePatternFragments(TP);

1371  

1372         assert((Child->getPredicateFns().empty()||

1373                 NewChild->getPredicateFns() ==Child->getPredicateFns()) &&

1374                "Non-empty child predicateclobbered!");

1375  

1376         setChild(i, NewChild);

1377       }

1378       return this;

1379     }

1380  

1381    // Otherwise, wefound a reference to a fragment.  First,look up its

1382    // TreePatternrecord.

1383     TreePattern *Frag =TP.getDAGPatterns().getPatternFragment(Op);

1384  

1385    // Verify that weare passing the right number of operands.

1386     if (Frag->getNumArgs() != Children.size()){

1387       TP.error("'" + Op->getName() +"' fragment requires " +

1388                utostr(Frag->getNumArgs()) +" operands!");

1389       returnnullptr;

1390     }

1391  

1392     TreePatternNode *FragTree =Frag->getOnlyTree()->clone();

1393  

1394     TreePredicateFn PredFn(Frag);

1395     if (!PredFn.isAlwaysTrue())

1396       FragTree->addPredicateFn(PredFn);

1397  

1398    // Resolve formalarguments to their actual value.

1399     if (Frag->getNumArgs()) {

1400      // Compute themap of formal to actual arguments.

1401       std::map<std::string,TreePatternNode*> ArgMap;

1402       for(unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i)

1403         ArgMap[Frag->getArgName(i)] =getChild(i)->InlinePatternFragments(TP);

1404  

1405       FragTree->SubstituteFormalArguments(ArgMap);

1406     }

1407  

1408     FragTree->setName(getName());

1409     for (unsignedi = 0, e = Types.size(); i != e; ++i)

1410       FragTree->UpdateNodeType(i, getExtType(i),TP);

1411  

1412    // Transfer inthe old predicates.

1413     for (unsignedi = 0, e = getPredicateFns().size(); i != e; ++i)

1414      FragTree->addPredicateFn(getPredicateFns()[i]);

1415  

1416    // Get a new copyof this fragment to stitch into here.

1417    //deletethis;    // FIXME: implement refcounting!

1418  

1419    // The fragmentwe inlined could have recursive inlining that is needed.  See

1420    // if there areany pattern fragments in it and inline them as needed.

1421     returnFragTree->InlinePatternFragments(TP);

1422   }

1362行的isLeaf方法首先筛选出模式树的叶子节点,它们不可能是展开的对象(因为SDNode与PatFrag都不产生叶子节点)。

非叶子节点总是由一个DagInit值生成的。

如果这个DagInit值的操作符不是一个PatFrag定义(比如一个SDNode定义),那么操作符本身不可展开,因此在1370行对其操作数进行展开,并替换为展开的结果。注意,这些展开可能没有执行任何操作,得到的结果与原来是一样的。

而如果操作符是一个PatFrag定义,首先确保操作数与子节点个数相同(正常情况下,这是可以保证的,因为子节点就是根据操作数生成的)。然后克隆这棵模式树(TreePatternNode),这样做是因为这个PatFrag可能有多处使用,我们必须保留一个未展开的形式,以备后续展开这个PatFrag的其他使用。

如果存在操作数,在1403行将展开的操作数子节点保存在ArgMap容器,然后对克隆树进行参数值的替换。

1328   void TreePatternNode::

1329   SubstituteFormalArguments(std::map<std::string,TreePatternNode*> &ArgMap) {

1330     if (isLeaf()) return;

1331  

1332     for (unsignedi = 0, e = getNumChildren(); i != e; ++i) {

1333       TreePatternNode *Child = getChild(i);

1334       if (Child->isLeaf()) {

1335         Init *Val = Child->getLeafValue();

1336        // Note that,when substituting into an output pattern, Val might be an

1337        // UnsetInit.

1338         if (isa<UnsetInit>(Val) ||(isa<DefInit>(Val) &&

1339             cast<DefInit>(Val)->getDef()->getName()== "node")) {

1340          // We founda use of a formal argument, replace it with its value.

1341           TreePatternNode *NewChild =ArgMap[Child->getName()];

1342           assert(NewChild&& "Couldn't find formal argument!");

1343           assert((Child->getPredicateFns().empty()||

1344                   NewChild->getPredicateFns()== Child->getPredicateFns()) &&

1345                  "Non-empty child predicateclobbered!");

1346           setChild(i, NewChild);

1347         }

1348       } else {

1349        getChild(i)->SubstituteFormalArguments(ArgMap);

1350       }

1351     }

1352   }

SubstituteFormalArguments只替换代表未初始化值(UnsetInit,对应(ops?:$name)或(ops $name)形式),以及(ops node:$name)形式的叶子节点。注意,1341行的Child->getName()返回的是name部分,比如(opsnode:$ptr),就是字符串”ptr”。

用一个例子能更容易理解这个过程。比如这些定义:

def P1:PatFrag<(node:$src, node:$dst), (P2 node:$src, node:$dst), [{…}]>;

def P2:PatFrag<(node:$src, node:$dst), (P3 node:$src, (P4 node:$dst)), [{…}]>;

def P3:PatFrag<(node:$src, node:$dst), (S1 node:$src, node:$dst), [{…}]>;

def P4:PatFrag<(node:$val), (S2 node:$val), [{…}]>;

def S1: SDNode;

def S2: SDNode;

对P1解析的结果是:一棵以P2为根,node:$src,node:$dst为叶子的树(称为P1树)。

对P2解析的结果是:一棵以P3为根,node:$src与(P4node:$dst)为子树的树(称为P2树)。

对P3解析的结果是:一棵以S1为根,node:$src,node:$dst为叶子的树(称为P3树)。

对P4解析的结果是:一棵以S2为根,node:$val为叶子的树(称为P4树)。

开始内联P2树时,InlinePatternFragments的1383行获取P1的克隆树(称为P1clone)。在1403行递归进入叶子节点node:$src,node:$dst,并在1363行返回。这时,ArgMap[dst]ànode:$dst,ArgMap[src]ànode:$src。然后对P1clone进行参数替换,这一步没有实质的变化。

接着在1421行,对P1clone的P2操作符进行内联。类似的,在1383行获取P2克隆树(称为P2clone),在1403行进入P2clone的子树node:$src与(P4node:$dst)。node:$src直接返回,得到P2clone的ArgMap[src]ànode:$src。(P4node:$dst)则再次调用InlinePatternFragments。在这个过程中,得到P4的克隆树(称为P4clone),因为P2clone的P4子树的叶子节点是node:$dst。因此P2cloneArgMap[val]ànode:$dstP4clone进行参数替换,得到(S2node:$dst)。然后在1421行,内联P4clone的S2操作符。S2是SDNode的定义,而且node:$dst是叶子节点,因此S2没有改变。自此,P4clone处理完成。

现在P2clone的ArgMap[dst]àP4clone,ArgMap[src]ànode:$src。接着在1421行对P2clone的S1操作符进行内联,也无改变。自此,P2clone内联展开完成。进而P1clone内联展开也完成,得到:(S1node:$src, (S2 node: $dst)))——同时也实现了node:$dst对node:$val的替换。

原创粉丝点击