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。因此P2clone有ArgMap[val]ànode:$dst,P4clone进行参数替换,得到(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的替换。
- LLVM学习笔记(16)
- llvm学习笔记(1)
- llvm学习笔记(2)
- llvm学习笔记(3)
- llvm学习笔记(4)
- llvm学习笔记(5)
- LLVM学习笔记(6)
- LLVM学习笔记(7)
- LLVM学习笔记(8)
- LLVM学习笔记(9)
- LLVM学习笔记(10)
- LLVM学习笔记(11)
- LLVM学习笔记(12)
- LLVM学习笔记(13)
- LLVM学习笔记(14)
- LLVM学习笔记(15)
- LLVM学习笔记(20)
- LLVM学习笔记(17)
- 强叔侃墙_NAT_nopat示例
- tomcat运行报错Failed to start component [StandardEngine[Catalina].StandardHost[localhost].
- 强叔侃墙_NAT_NAPT示例
- ssh登录 The authenticity of host 192.168.0.xxx can't be established. 的问题
- 异步群英会-线下技术沙龙-参与送书!
- LLVM学习笔记(16)
- weico.cc微博链接
- 强叔侃墙_NAT_easyip示例
- 强叔侃墙_NAT_smart NAT示例
- 强叔侃墙_三无组NAT
- 强叔侃墙_出口选路_策略路由_基于目的地址的IP策略路由
- 九度OJ
- python世界上最全的文件操作教程
- 使用WebView简单嵌套页面