3.4.2.4. PatFrag的处理
3.4.2.4.1. 模式树的构建
PatFrag是一个可重用的构件,TableGen会在PatFrag出现的地方展开其定义,有点像C/C++中的宏。为此,CodeGenDAGPatterns将每个可能嵌入PatFrag的定义——Instruction,Pattern,Pat以及PatFrag,构建为一棵TreePattern树,并在适当的时候将其中包含的PatFrag展开(这是个递归的过程,会一直进行到PatFrag不存在为止)。
在v7.0里,PatFrag是PatFrags的派生定义(或者说是PatFrags单匹配片段的特例),PatFrags支持多个匹配片段,只要其中一个匹配,就可视为匹配成功,因此在v7.0里是对PatFrags展开处理。
函数CodeGenDAGPatterns::ParsePatternFragments()处理、展开所有的PatFrag定义。
它会生成这样的结构:对一个PatFrag定义(v7.0是PatFrags下同)生成一个TreePattern实例;从定义里的Fragment(v7.0是Fragments)生成一个保存在TreePattern的Trees容器里的TreePatternNode实例(v7.0是Fragments里每成员一个TreePatternNode实例);定义里Operands中的操作数名则保存在Args容器里。如果Fragment的dag值仍然是一个PatFrag派生定义,那么其TreePatternNode实例的Operator记录这个PatFrag的Record对象,Children容器则保存由该dag操作数生成的TreePatternNode实例。以此类推,直到该定义中涉及的所有PatFrag定义都被处理。这分为两大步进行。
首先在2428行循环为所有的PatFrag定义生成模式树,并进行一些有效性检查。
2424 void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
2425 std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag"); <- v7.0删除
std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrags"); <- v7.0增加
2426
2427 // First step, parse all of the fragments.
2428 for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
2429 if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag"))
2430 continue;
2431
2432 DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); <- v7.0删除
ListInit *LI = Frag->getValueAsListInit("Fragments"); <- v7.0增加
2433 TreePattern *P =
2434 (PatternFragments[Fragments[i]] = llvm::make_unique<TreePattern>(
2435 Fragments[i], Tree LI, !Fragments[i]->isSubClassOf("OutPatFrag"),
2436 *this)).get();
2437
2438 // Validate the argument list, converting it to set, to discard duplicates.
2439 std::vector<std::string> &Args = P->getArgList();
// Copy the args so we can take StringRefs to them.
auto ArgsCopy = Args; <- v7.0增加
SmallDenseSet<StringRef, 4> OperandsSet;
OperandsSet.insert(ArgsCopy.begin(), ArgsCopy.end());
2440 std::set<std::string> OperandsSet(Args.begin(), Args.end()); <- v7.0删除
2441
2442 if (OperandsSet.count(""))
2443 P->error("Cannot have unnamed 'node' values in pattern fragment!");
2444
2445 // Parse the operands list.
2446 DagInit *OpsList = Fragments[i]->getValueAsDag("Operands");
2447 DefInit *OpsOp = dyn_cast<DefInit>(OpsList->getOperator());
2448 // Special cases: ops == outs == ins. Different names are used to
2449 // improve readability.
2450 if (!OpsOp ||
2451 (OpsOp->getDef()->getName() != "ops" &&
2452 OpsOp->getDef()->getName() != "outs" &&
2453 OpsOp->getDef()->getName() != "ins"))
2454 P->error("Operands list should start with '(ops ... '!");
2455
2456 // Copy over the 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 should all be 'node' values.");
2462 if (OpsList->getArgName(j).empty())
2463 P->error("Operands list should have names for each operand!");
2464 if (!OperandsSet.count(OpsList->getArgName(j)))
2465 P->error("'" + OpsList->getArgName(j) +
2466 "' does not occur in pattern 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 contain an entry for operand '" +
2473 *OperandsSet.begin() + "'!");
2474
2475 // If there is a code init for this fragment, keep track of the fact that
2476 // this fragment uses it.
2477 TreePredicateFn PredFn(P);
2478 if (!PredFn.isAlwaysTrue())
2479 P->getOnlyTree()->addPredicateFn(PredFn);
2480
2481 // If there is a node transformation corresponding to this, keep track of
2482 // it.
2483 Record *Transform = Fragments[i]->getValueAsDef("OperandTransform");
2484 if (!getSDNodeTransform(Transform).second.empty()) // not noop xform?
for (auto T : P->getTrees()) <- v7.0增加
2485 P->getOnlyTree()->setTransformFn(Transform);
2486 }
2487
2488 // Now that we've parsed all of the tree fragments, do a closure on them so
2489 // that there are not references to PatFrags left inside of them.
2490 for (unsigned i = 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 as many types as possible. Don't worry about it if we don't infer
2498 // all of them, some may depend on the inputs of the pattern. Also, don't <- v7.0增加
// validate type sets; validation may cause spurious failures e.g. if a
// fragment needs floating-point types but the current target does not have
// any (this is only an error if that fragment is ever used!).
{
TypeInfer::SuppressValidation SV(ThePat.getInfer());
2499 ThePat.InferAllTypes();
2500 ThePat.resetError();
}
2501
2502 // If debugging, print out the pattern fragment result.
2503 DEBUG(ThePat.dump());
2504 }
2505 }
在CodeGenDAGPatterns构造函数里两次调用了ParsePatternFragments(),第一次参数OutFrags是false(缺省值),表示不考虑OutPatFrag类型的定义。2434行的llvm::make_unique调用new操作符构建一个TreePattern实例,并返回一个std::unique_ptr<TreePattern>实例。因此,2434行的成员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 }
V7.0中调用这个版本,因为PatFrags里现在是Fragments(类型为list<dag>): 2534 TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, 2535 CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp), 2536 isInputPattern(isInput), HasError(false), 2537 Infer(*this) { 2538 for (Init *I : RawPat->getValues()) 2539 Trees.push_back(ParseTreePattern(I, "")); 2540 } 其中2537行的Infer是类型为TypeInfer的成员,用于辅助类型推导。 |
注意只要这个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 // Direct reference 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 return ParseTreePattern(
2049 DagInit::get(DI, "",
2050 std::vector<std::pair<Init*, std::string> >()),
2051 OpName);
2052
2053 // Input argument?
2054 TreePatternNode *Res = new TreePatternNode(DI, 1); <- v7.0删除
TreePatternNodePtr Res = std::make_shared<TreePatternNode>(DI, 1); <- v7.0增加
2055 if (R->getName() == "node" && !OpName.empty()) {
2056 if (OpName.empty())
2057 error("'node' argument requires a name to match with operand list");
2058 Args.push_back(OpName);
2059 }
2060
2061 Res->setName(OpName);
2062 return Res;
2063 }
2064
2065 // ?:$name or just $name.
2066 if (isa<UnsetInit>(TheInit)) {
2067 if (OpName.empty())
2068 error("'?' argument requires a name to match with operand list");
2069 TreePatternNode *Res = new TreePatternNode(TheInit, 1); <- v7.0删除
TreePatternNodePtr Res = std::make_shared<TreePatternNode>(TheInit, 1); <- v7.0增加
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 should not have a name!");
2078 return new TreePatternNode(II, 1); <- v7.0删除
return std::make_shared<TreePatternNode>(TheInit, 1); <- v7.0增加
2079 }
2080
2081 if (BitsInit *BI = dyn_cast<BitsInit>(TheInit)) {
2082 // Turn this into an IntInit.
2083 Init *II = BI->convertInitializerTo(IntRecTy::get());
2084 if (!II || !isa<IntInit>(II))
2085 error("Bits value must be constants!");
2086 return ParseTreePattern(II, OpName);
2087 }
2088
2089 DagInit *Dag = dyn_cast<DagInit>(TheInit);
2090 if (!Dag) {
2091 TheInit->dump();
2092 error("Pattern has unexpected init kind!");
2093 }
2094 DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator());
2095 if (!OpDef) error("Pattern has unexpected operator type!");
2096 Record *Operator = OpDef->getDef();
2097
2098 if (Operator->isSubClassOf("ValueType")) {
2099 // If the operator 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 one operand!");
2103
2104 TreePatternNode *New = ParseTreePattern(Dag->getArg(0), Dag->getArgName(0));
2105
2106 // Apply the type cast.
2107 assert(New->getNumTypes() == 1 && "FIXME: Unhandled");
2108 New->UpdateNodeType(0, getValueType(Operator), *this); <- v7.0删除
const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes(); <- v7.0增加
New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this);
2109
2110 if (!OpName.empty())
2111 error("ValueType cast should not have a name!");
2112 return New;
2113 }
2114
2115 // Verify that this is something that makes sense for an operator.
2116 if (!Operator->isSubClassOf("PatFrag") && <- v7.0删除
if (!Operator->isSubClassOf("PatFrags") && <- v7.0增加
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 is illegal 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的操作数。(v7.0补充: PatFrags派生定义对应TreePattern实例,其中的每个Fragments片段对应TreePatternNode实例,保存在对应TreePattern实例的Trees容器中。Fragments片段通常是dag,合法dag的操作数也将生成TreePatternNode实例,保存在父TreePatternNode的Children容器里。具体细节参见下面的描述)
如果要匹配的部分是一个SDNode或PatFrag(v7.0是PatFrags),在2049行构建一个自己为操作符,没有操作数的匿名dag值(DagInit实例),然后新调用ParseTreePattern()。这个处理非常重要。DagInit生成的树节点不是叶子节点,即使它没有子节点。后面进行的内联与展开是不对叶子节点进行的。其他的DefInit(对应一个def定义)可以直接生成TreePatternNode叶子节点。但如果这是一个node(一个空def,参见TargetSelectionDAG.TD的310行),它必须具名(node:$name)。
类似的,UnsetInit(表示未初始化的值)、IntInit(TD整数常量)、BitsInit(TD比特值)都必须是具名的,而且BitsInit还必须是常量。不能匿名是因为TableGen需要通过名字将它们匹配到模式片段的操作数。它们都对应一个叶子TreePatternNode节点(v7.0使用std::make_shared< TreePatternNode>()来创建TreePatternNode实例,这是对原来TreePatternNode对象内存泄露的一个修正)。下面的构造函数用于创建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 return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP);
489 }
V7.0则是调用了下面的函数。其中第二个参数是通过llvm::getValueTypeByHwMode()方法生成的,在这个上下文里,这个方法的实参Operator一定是ValueTypes的派生定义,生成的ValueTypeByHwMode实例会将Operator的类型关联到缺省硬件模式。 915 inline bool TreePatternNode::UpdateNodeType(unsigned ResNo, 916 ValueTypeByHwMode InTy, 917 TreePattern &TP) { 918 TypeSetByHwMode VTS(InTy); 919 TP.getInfer().expandOverloads(VTS); 920 return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS); 921 } 919行的getInfer()方法返回TreePattern的成员Infer,它是一个struct TypeInfer的实例。这个结构显然是用于类型推导的,其成员函数expandOverloads()将所谓的重载类型替换为对应的类型集合,并通过参数VTS返回。 732 void TypeInfer::expandOverloads(TypeSetByHwMode &VTS) { 733 ValidateOnExit _1(VTS, *this); 734 TypeSetByHwMode Legal = getLegalTypes(); 735 bool HaveLegalDef = Legal.hasDefault(); 736 737 for (auto &I : VTS) { 738 unsigned M = I.first; 739 if (!Legal.hasMode(M) && !HaveLegalDef) { 740 TP.error("Invalid mode " + Twine(M)); 741 return; 742 } 743 expandOverloads(I.second, Legal.get(M)); 744 } 745 } 734行的成员函数getLegalTypes()获取所有合法类型,并关联到缺省硬件模式下: 796 TypeSetByHwMode TypeInfer::getLegalTypes() { 797 if (!LegalTypesCached) { 798 // Stuff all types from all modes into the default mode. 799 const TypeSetByHwMode <S = TP.getDAGPatterns().getLegalTypes(); 800 for (const auto &I : LTS) 801 LegalCache.insert(I.second); 802 LegalTypesCached = true; 803 } 804 TypeSetByHwMode VTS; 805 VTS.getOrCreate(DefaultMode) = LegalCache; 806 return VTS; 807 } 799行CodeGenDAGPatterns的getLegalTypes()方法返回其成员LegalVTS(TypeSetByHwMode实例)。LegalCache是TypeInfer类型为TypeSetByHwMode::SetType(即MachineValueTypeSet)的成员。800行的循环遍历LegalVTS底下类型为std::map<unsigned, MachineValueTypeSet>的容器,获取所有合法的类型(合法类型来自TD文件的定义,如ValueTypeByHwMode及其派生定义)。在801行调用MachineValueTypeSet这个版本的insert()方法: 97 MachineValueTypeSet &insert(const MachineValueTypeSet &S) { 98 for (unsigned i = 0; i != NumWords; ++i) 99 Words[i] |= S.Words[i]; 101 return *this; 102 } MachineValueTypeSet使用数组的比特位来记录类型。在805行将这些类型与缺省模式绑定。 在TypeInfer::expandOverloads()的743行调用的expandOverloads()是这个版本: 747 void TypeInfer::expandOverloads(TypeSetByHwMode::SetType &Out, 748 const TypeSetByHwMode::SetType &Legal) { 749 std::set<MVT> Ovs; 750 for (MVT T : Out) { 751 if (!T.isOverloaded()) 752 continue; 753 754 Ovs.insert(T); 755 // MachineValueTypeSet allows iteration and erasing. 756 Out.erase(T); 757 } 758 759 for (MVT Ov : Ovs) { 760 switch (Ov.SimpleTy) { 761 case MVT::iPTRAny: 762 Out.insert(MVT::iPTR); 763 return; 764 case MVT::iAny: 765 for (MVT T : MVT::integer_valuetypes()) 766 if (Legal.count(T)) 767 Out.insert(T); 768 for (MVT T : MVT::integer_vector_valuetypes()) 769 if (Legal.count(T)) 770 Out.insert(T); 771 return; 772 case MVT::fAny: 773 for (MVT T : MVT::fp_valuetypes()) 774 if (Legal.count(T)) 775 Out.insert(T); 776 for (MVT T : MVT::fp_vector_valuetypes()) 777 if (Legal.count(T)) 778 Out.insert(T); 779 return; 780 case MVT::vAny: 781 for (MVT T : MVT::vector_valuetypes()) 782 if (Legal.count(T)) 783 Out.insert(T); 784 return; 785 case MVT::Any: 786 for (MVT T : MVT::all_valuetypes()) 787 if (Legal.count(T)) 788 Out.insert(T); 789 return; 790 default: 791 break; 792 } 793 } 794 } 750行循环查找所谓的重载类型: 388 bool isOverloaded() const { 389 return (SimpleTy==MVT::Any || 390 SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || 391 SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny); 392 } 759行的大循环就是将Legal中存在的对应合法类型替换掉重载类型。765、768、773、781及786行循环的含义参考下面对SimpleValueType的说明。 在UpdateNodeType()的920行,MergeInTypeInfo()方法现在是TypeInfer的成员。参数Out是该TreePatternNode的结果类型,In就是指定硬件模式下可用的类型,MergeInTypeInfo()就是获取两者间的交集。 326 bool TypeInfer::MergeInTypeInfo(TypeSetByHwMode &Out, 327 const TypeSetByHwMode &In) { 328 ValidateOnExit _1(Out, *this); 329 In.validate(); 330 if (In.empty() || Out == In || TP.hasError()) 331 return false; 332 if (Out.empty()) { 333 Out = In; 334 return true; 335 } 336 337 bool Changed = Out.constrain(In); 338 if (Changed && Out.empty()) 339 TP.error("Type contradiction"); 340 341 return Changed; 342 } 329行TypeSetByHwMode的validate()方法在不打开调试时是空函数。如果Out不是空,那么要取Out与In的交集,即337行的Constrain()方法: 112 bool TypeSetByHwMode::constrain(const TypeSetByHwMode &VTS) { 113 bool Changed = false; 114 if (hasDefault()) { 115 for (const auto &I : VTS) { 116 unsigned M = I.first; 117 if (M == DefaultMode || hasMode(M)) 118 continue; 119 Map.insert({M, Map.at(DefaultMode)}); 120 Changed = true; 121 } 122 } 123 124 for (auto &I : *this) { 125 unsigned M = I.first; 126 SetType &S = I.second; 127 if (VTS.hasMode(M) || VTS.hasDefault()) { 128 Changed |= intersect(I.second, VTS.get(M)); 129 } else if (!S.empty()) { 130 S.clear(); 131 Changed = true; 132 } 133 } 134 return Changed; 135 } 如果Out里有缺省硬件模式,115行循环将VTS中所没有的Out硬件模式都关联到缺省模式对应的合法类型。124行循环对OUT的合法类型与VTS对应模式或缺省模式的合法类型求交集。求交集的方法是下面的TypeSetByHwMode::intersect()。 253 bool TypeSetByHwMode::intersect(SetType &Out, const SetType &In) { 254 bool OutP = Out.count(MVT::iPTR), InP = In.count(MVT::iPTR); 255 auto Int = [&In](MVT T) -> bool { return !In.count(T); }; 256 257 if (OutP == InP) 258 return berase_if(Out, Int); 259 260 // Compute the intersection of scalars separately to account for only 261 // one set containing iPTR. 262 // The itersection of iPTR with a set of integer scalar types that does not 263 // include iPTR will result in the most specific scalar type: 264 // - iPTR is more specific than any set with two elements or more 265 // - iPTR is less specific than any single integer scalar type. 266 // For example 267 // { iPTR } * { i32 } -> { i32 } 268 // { iPTR } * { i32 i64 } -> { iPTR } 269 // and 270 // { iPTR i32 } * { i32 } -> { i32 } 271 // { iPTR i32 } * { i32 i64 } -> { i32 i64 } 272 // { iPTR i32 } * { i32 i64 i128 } -> { iPTR i32 } 273 274 // Compute the difference between the two sets in such a way that the 275 // iPTR is in the set that is being subtracted. This is to see if there 276 // are any extra scalars in the set without iPTR that are not in the 277 // set containing iPTR. Then the iPTR could be considered a "wildcard" 278 // matching these scalars. If there is only one such scalar, it would 279 // replace the iPTR, if there are more, the iPTR would be retained. 280 SetType Diff; 281 if (InP) { 282 Diff = Out; 283 berase_if(Diff, [&In](MVT T) { return In.count(T); }); 284 // Pre-remove these elements and rely only on InP/OutP to determine 285 // whether a change has been made. 286 berase_if(Out, [&Diff](MVT T) { return Diff.count(T); }); 287 } else { 288 Diff = In; 289 berase_if(Diff, [&Out](MVT T) { return Out.count(T); }); 290 Out.erase(MVT::iPTR); 291 } 292 293 // The actual intersection. 294 bool Changed = berase_if(Out, Int); 295 unsigned NumD = Diff.size(); 296 if (NumD == 0) 297 return Changed; 298 299 if (NumD == 1) { 300 Out.insert(*Diff.begin()); 301 // This is a change only if Out was the one with iPTR (which is now 302 // being replaced). 303 Changed |= OutP; 304 } else { 305 // Multiple elements from Out are now replaced with iPTR. 306 Out.insert(MVT::iPTR); 307 Changed |= !OutP; 308 } 309 return Changed; 310 } TypeSetByHwMode的SetType是MachineValueTypeSet,因此254行的count()方法就是在MachineValueTypeSet里查找MVT::iPTR是否存在。如果在OUT与VTS中都有MVT::iPTR,255行的兰布达表达式将用作方法berase_if()的第二个参数Predicate。因此这时berase_if()的作用就是,如果OUT指定模式中的合法类型没有出现在VTS的对应模式里,从OUT中把这些类型删除。 47 template <typename Predicate> 48 static bool berase_if(MachineValueTypeSet &S, Predicate P) { 49 bool Erased = false; 50 // It is ok to iterate over MachineValueTypeSet and remove elements from it 51 // at the same time. 52 for (MVT T : S) { 53 if (!P(T)) 54 continue; 55 Erased = true; 56 S.erase(T); 57 } 58 return Erased; 59 } 如果只有一方有MVT::iPTR,260行的注释谈到了如何处理。如果除了iPTR之外,两个集合间只相差一个标量,那么该标量作为iPTR的替代;如果两个集合间相差多个标量,那么iPTR作为这些标量的通配。具体参考266~279行的注释。 与下面3.6.0的实现比较,通过引入硬件模式的概念,v7.0这部分的实现干净利落不少,LLVM的重构确实是不遗余力的。 |
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 return false;
168
169 if (isCompletelyUnknown()) {
170 *this = InVT;
171 return true;
172 }
173
174 assert(TypeVec.size() >= 1 && InVT.TypeVec.size() >= 1 && "No unknowns");
175
176 // Handle the abstract cases, seeing if we can resolve them better.
177 switch (TypeVec[0]) {
178 default: break;
179 case MVT::iPTR:
180 case MVT::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 the RHS has one integer type, upgrade iPTR to i32.
188 TypeVec[0] = InVT.TypeVec[0];
189 return true;
190 }
191
192 // If the input has multiple scalar integers, this doesn't add any info.
193 if (!InCopy.isCompletelyUnknown())
194 return false;
195 }
196 break;
197 }
198
199 // If the input constraint is iAny/iPTR and this is an integer type list,
200 // remove non-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're merging in iPTR/iPTRAny and the node currently has a list of
206 // multiple different 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 return MadeChange;
215 }
216
217 // If this is a type list and the RHS is a typelist as well, eliminate entries
218 // from this list that aren't in the other one.
219 bool MadeChange = false;
220 TypeSet InputSet(*this);
221
222 for (unsigned i = 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 removed all of our types, we have a type contradiction.
236 if (!TypeVec.empty())
237 return MadeChange;
238
239 // FIXME: Really want 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 // considered extended value types.
34 INVALID_SIMPLE_VALUE_TYPE = -1,
35
36 // If you change this numbering, you must change the values in
37 // ValueTypes.td as 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 // unspecified type. The register class
121 // will be determined by the opcode.
122
123 FIRST_VALUETYPE = 0, // This is always the beginning of the list. ----+
124 LAST_VALUETYPE = 59, // This always remains at the end of the list. +--这个区间满足isValid
125
126 // This is the current maximum for LAST_VALUETYPE.
127 // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors
128 // This value must 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 to any 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 - A vector with any length and element size. This is used
140 // for intrinsics that have overloadings based on vector types.
141 // This is only for tblgen's consumption!
142 vAny = 252,
143
144 // fAny - Any floating-point or vector floating-point value. This is used
145 // for intrinsics that have overloadings based on floating-point types.
146 // This is only for tblgen's consumption!
147 fAny = 253,
148
149 // iAny - An integer or vector integer value of any bit width. This is
150 // used for intrinsics that have overloadings based on integer bit widths.
151 // This is only for tblgen's consumption!
152 iAny = 254,
153
154 // iPTR - An int value the size of the pointer of the current
155 // target. This should only be used internal to tblgen!
156 iPTR = 255,
157
158 // Any - Any type. This is used for intrinsics that have overloadings.
159 // This is only 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容器内。这个容器里的内容会在后面调用TreePatternNode非叶子节点构造函数时,保存在父TreePatternNode节点的Children容器内。
TreePattern::ParseTreePattern(续)
2151 std::vector<TreePatternNode*> Children;
2152
2153 // Parse all the operands.
2154 for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i)
2155 Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgName(i)));
// Get the actual number of results before Operator is converted to an intrinsic <- v7.0增加
// node (which is hard-coded to have either zero or one result).
unsigned NumResults = GetNumNodeResults(Operator, CDP);
2157 // If the operator is an intrinsic, then this is just syntactic sugar for for
2158 // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and
2159 // convert the intrinsic 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 this intrinsic 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 // Has side-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); <- v7.0删除
2175 Children.insert(Children.begin(), IIDNode);
Children.insert(Children.begin(), <- v7.0增加
std::make_shared<TreePatternNode>(IntInit::get(IID), 1));
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 a ComplexPattern must be named");
2184
2185 // Check that the 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 auto OperandId = std::make_pair(Operator, i);
2189 auto PrevOp = ComplexPatternOperands.find(Child->getName());
2190 if (PrevOp != ComplexPatternOperands.end()) {
2191 if (PrevOp->getValue() != OperandId)
2192 error("All ComplexPattern operands must appear consistently: "
2193 "in the same order in just one ComplexPattern instance.");
2194 } else
2195 ComplexPatternOperands[Child->getName()] = OperandId;
2196 }
2197 }
2198
2199 unsigned NumResults = GetNumNodeResults(Operator, CDP); <- v7.0删除
2200 TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults);
TreePatternNodePtr Result = <- v7.0增加
std::make_shared<TreePatternNode>(Operator, std::move(Children),
NumResults);
2201 Result->setName(OpName);
2202
2203 if (!Dag->getName().empty()) {
2204 assert(Result->getName().empty());
2205 Result->setName(Dag->getName());
2206 }
2207 return Result;
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值的操作符创建它所表示的模式树的根节点。首先需要确定它所代表操作返回的结果数(v7.0将GetNumNodeResults()提前了,原因在2156行后的注释提及)。
1168 static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
1169 if (Operator->getName() == "set" ||
1170 Operator->getName() == "implicit")
1171 return 0; // All return nothing.
1172
1173 if (Operator->isSubClassOf("Intrinsic"))
1174 return CDP.getIntrinsic(Operator).IS.RetVTs.size();
1175
1176 if (Operator->isSubClassOf("SDNode"))
1177 return CDP.getSDNodeInfo(Operator).getNumResults();
1178
1179 if (Operator->isSubClassOf("PatFrag")) { <- v7.0删除
1180 // If we've already parsed this pattern fragment, get it. Otherwise, handle
1181 // the forward reference case where one pattern fragment references another
1182 // before it is processed.
1183 if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator))
1184 return PFRec->getOnlyTree()->getNumTypes();
1185
1186 // Get the result 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 return GetNumNodeResults(Op, CDP);
1194 }
if (Operator->isSubClassOf("PatFrags")) { <- v7.0增加
// If we've already parsed this pattern fragment, get it. Otherwise, handle
// the forward reference case where one pattern fragment references another
// before it is processed.
if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator)) {
// The number of results of a fragment with alternative records is the
// maximum number of results across all alternatives.
unsigned NumResults = 0;
for (auto T : PFRec->getTrees())
NumResults = std::max(NumResults, T->getNumTypes());
return NumResults;
}
ListInit *LI = Operator->getValueAsListInit("Fragments");
assert(LI && "Invalid Fragment");
unsigned NumResults = 0;
for (Init *I : LI->getValues()) {
Record *Op = nullptr;
if (DagInit *Dag = dyn_cast<DagInit>(I))
if (DefInit *DI = dyn_cast<DefInit>(Dag->getOperator()))
Op = DI->getDef();
assert(Op && "Invalid Fragment");
NumResults = std::max(NumResults, GetNumNodeResults(Op, CDP));
}
return NumResults;
}
1196 if (Operator->isSubClassOf("Instruction")) {
1197 CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator);
1198
1199 unsigned NumDefsToAdd = InstInfo.Operands.NumDefs;
1200
1201 // Subtract any defaulted 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 one implicit def if it has a resolvable type.
1211 if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other)
1212 ++NumDefsToAdd;
1213 return NumDefsToAdd;
1214 }
1215
1216 if (Operator->isSubClassOf("SDNodeXForm"))
1217 return 1; // FIXME: Generalize SDNodeXForm
1218
1219 if (Operator->isSubClassOf("ValueType"))
1220 return 1; // A type-cast of one result.
1221
1222 if (Operator->isSubClassOf("ComplexPattern"))
1223 return 1;
1224
1225 Operator->dump();
1226 PrintFatalError("Unhandled node in GetNumNodeResults");
1227 }
因为v7.0增加了PatFrags作为PatFrag的基类,因此GetNumNodeResults做了相应的调整,但基本原则是相同的。
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()的2995行,TreePattern::getArgList()返回PatFrag(v7.0是PatFrags,下同)的输入参数。这些参数是在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派生定义)。