内容简介:3.4.2.4.3.2.回到TreePattern::InferAllTypes,既然现在类型有可能已经具体化了,那么通过下面的方法尝试简化这棵TreePattern树。
3.4.2.4.3.2. 简化
回到TreePattern::InferAllTypes,既然现在类型有可能已经具体化了,那么通过下面的方法尝试简化这棵TreePattern树。
2216 static bool SimplifyTree (TreePatternNode *&N) {
2217 if (N->isLeaf())
2218 return false;
2219
2220 // If we have a bitconvert with a resolved type and if the source and
2221 // destination types are the same, then the bitconvert is useless, remove it.
2222 if (N->getOperator()->getName() == "bitconvert" &&
2223 N->getExtType(0).isConcrete() &&
2224 N->getExtType(0) == N->getChild(0)->getExtType(0) &&
2225 N->getName().empty()) {
2226 N = N->getChild(0);
2227 SimplifyTree(N);
2228 return true;
2229 }
2230
2231 // Walk all children.
2232 bool MadeChange = false;
2233 for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
2234 TreePatternNode *Child = N->getChild(i);
2235 MadeChange |= SimplifyTree(Child);
2236 N->setChild(i, Child);
2237 }
2238 return MadeChange;
2239 }
可以看到,目前只有bitconvert子树才可能简化。Bitconvert代表了整数、浮点及向量值之间的转换,源与目标值都有相同的大小。如果源与目标值类型相同,这个转换可以丢弃。
3.4.2.4.3.3. 类型的最后确定
在TreePattern::InferAllTypes()函数的入口,当前树的具名节点(即node:$ name 的名字 name )被保存在NamedNodes容器。現在2260行遍历这些名字。首先,如果InferAllTypes()传入了非空的参数InNamedTypes,需要确保名字出现在InNamedTypes里。并使用InNamedTypes中对应节点的类型信息来更新当前节点的类型。这个用法出现在Instruction与Pattern定义的处理中,后面会看到。
在此之后,如果NamedNodes容器里存在多个节点对应同一个名字的情形,它们的类型必须一致(2300~2310行)。
而在上述过程里,一旦有节点的类型发生变化,就要回到2252行重新进行处理,直达没有节点的类型在一次处理过程中改变为止。这时,这棵(些)TreePattern树所有节点的类型都应该确定了,这由下面的方法来判定。
498 bool ContainsUnresolvedType () const {
499 for (unsigned i = 0, e = Types.size(); i != e; ++i)
500 if (!Types[i].isConcrete()) return true;
501
502 for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
503 if (getChild(i)->ContainsUnresolvedType()) return true;
504 return false;
505 }
从TreePattern::InferAllTypes()回到CodeGenDAGPatterns::ParsePatternFragments(),对PatFrag定义的处理就此完成。
对 v7.0 , ContainsUnresolvedType() 的定义是:
1561 bool TreePatternNode::ContainsUnresolvedType(TreePattern &TP) const {
1562 for (unsigned i = 0, e = Types.size(); i != e; ++i)
1563 if (!TP.getInfer().isConcrete(Types[i], true))
1564 return true;
1565 for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
1566 if (getChild(i)->ContainsUnresolvedType(TP))
1567 return true;
1568 return false;
1569 }
1563 行 TypeInfo 的 isConcrete() 方法通过 TypeSetByHwMode 的 sValueTypeByHwMode() 来执行:
253 bool isConcrete( const TypeSetByHwMode &VTS, bool AllowEmpty) const {
254 return VTS.isValueTypeByHwMode(AllowEmpty);
255 }
下面
73
行遍历
TypeSetByHwMode
实例中的
Map
容器(
std::map
72 bool TypeSetByHwMode::isValueTypeByHwMode (bool AllowEmpty) const {
73 for ( const auto &I : * this ) {
74 if (I.second.size() > 1)
75 return false;
76 if (!AllowEmpty && I.second.empty())
77 return false;
78 }
79 return true;
80 }
在 AllowEmpty 是 false 的情形下, Map 容器里每个 MachineValueTypeSet 容器中只设置了一个比特位, TypeSetByHwMode 的 sValueTypeByHwMode() 才返回 true 。
3.4.2.4.4. OperandWithDefaultOps
接下来,CodeGenDAGPatterns构造函数处理OperandWithDefaultOps派生定义。这个定义在文件Target.td里。
664
class
OperandWithDefaultOps
665
: Operand
666 dag DefaultOps = defaultops;
667 }
TableGen使用这个定义用于代表缺省值。它典型的用法有(摘自AMDGPUInstructions.td):
def
InstFlag : OperandWithDefaultOps
在这个定义里,缺省值是0。InstFlag可以用在dag中作为操作数,表示自己所代表的缺省值。
CodeGenDAGPatterns对OperandWithDefaultOps定义的处理相当简单。
2507 void CodeGenDAGPatterns::ParseDefaultOperands () {
2508
std::vector
2509 DefaultOps = Records.getAllDerivedDefinitions("OperandWithDefaultOps");
2510
2511 // Find some SDNode.
2512 assert (!SDNodes.empty() && "No SDNodes parsed?");
2513 Init *SomeSDNode = DefInit::get(SDNodes.begin()->first);
2514
2515 for (unsigned i = 0, e = DefaultOps.size(); i != e; ++i) {
2516 DagInit *DefaultInfo = DefaultOps[i]->getValueAsDag("DefaultOps");
2517
2518 // Clone the DefaultInfo dag node, changing the operator from 'ops' to
2519 // SomeSDnode so that we can parse this.
2520
std::vector
2521 for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
2522 Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
2523 DefaultInfo->getArgName(op)));
2524 DagInit *DI = DagInit::get(SomeSDNode, "", Ops);
2525
2526 // Create a TreePattern to parse this.
2527 TreePattern P(DefaultOps[i], DI, false, * this );
2528 assert (P.getNumTrees() == 1 && "This ctor can only produce one tree!");
2529
2530 // Copy the operands over into a DAGDefaultOperand.
2531 DAGDefaultOperand DefaultOpInfo;
2532
2533 TreePatternNode *T = P.getTree(0);
2534 for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
2535 TreePatternNode *TPN = T->getChild(op);
2536 while (TPN->(P, false))
2537 /* Resolve all types */ ;
2538
2539 if (TPN-> ContainsUnresolvedType ()) {
2540 PrintFatalError("Value #" + Twine(i) + " of OperandWithDefaultOps '" +
2541 DefaultOps[i]->getName() +
2542 "' doesn't have a concrete type!");
2543 }
2544 DefaultOpInfo.DefaultOps.push_back(TPN);
2545 }
2546
2547 // Insert it into the DefaultOperands map so we can find it later.
2548 DefaultOperands[DefaultOps[i]] = DefaultOpInfo;
2549 }
2550 }
SDNodes是CodeGenDAGPatterns的std::map
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【每日笔记】【Go学习笔记】2019-01-04 Codis笔记
- 【每日笔记】【Go学习笔记】2019-01-02 Codis笔记
- 【每日笔记】【Go学习笔记】2019-01-07 Codis笔记
- Golang学习笔记-调度器学习
- Vue学习笔记(二)------axios学习
- 算法/NLP/深度学习/机器学习面试笔记
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First PHP & MySQL
Lynn Beighley、Michael Morrison / O'Reilly Media / 2008-12-29 / USD 44.99
If you're ready to create web pages more complex than those you can build with HTML and CSS, Head First PHP & MySQL is the ultimate learning guide to building dynamic, database-driven websites using P......一起来看看 《Head First PHP & MySQL》 这本书的介绍吧!