3.4.2.6. Pattern的处理
我们已经知道Pattern定义可以将通用的IR指令表示映射为特定于目标机器的指令(对目标机器不同的型号,可以映射到这些型号特有的、更高效的指令)。因此对指令选择,Pattern定义是有益的补充。因为Pattern定义会援引指令,因此需要在解析完所有的指令定义后才开始处理。
3386 void CodeGenDAGPatterns::ParsePatterns() {
3387 std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern");
3388
3389 for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
3390 Record *CurPattern = Patterns[i];
3391 DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch");
3392
3393 // If the pattern references the null_frag, there's nothing to do.
3394 if (hasNullFragReference(Tree))
3395 continue;
3396
3397 TreePattern *Pattern = new TreePattern(CurPattern, Tree, true, *this);
3398
3399 // Inline pattern fragments into it.
3400 Pattern->InlinePatternFragments();
3401
3402 ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs");
3403 if (LI->empty()) continue; // no pattern.
3404
3405 // Parse the instruction.
3406 TreePattern Result(CurPattern, LI, false, *this);
3407
3408 // Inline pattern fragments into it.
3409 Result.InlinePatternFragments();
3410
3411 if (Result.getNumTrees() != 1)
3412 Result.error("Cannot handle instructions producing instructions "
3413 "with temporaries yet!");
3414
3415 bool IterateInference;
3416 bool InferredAllPatternTypes, InferredAllResultTypes;
3417 do {
3418 // Infer as many types as possible. If we cannot infer all of them, we
3419 // can never do anything with this pattern: report it to the user.
3420 InferredAllPatternTypes =
3421 Pattern->InferAllTypes(&Pattern->getNamedNodesMap());
3422
3423 // Infer as many types as possible. If we cannot infer all of them, we
3424 // can never do anything with this pattern: report it to the user.
3425 InferredAllResultTypes =
3426 Result.InferAllTypes(&Pattern->getNamedNodesMap());
3427
3428 IterateInference = false;
3429
3430 // Apply the type of the result to the source pattern. This helps us
3431 // resolve cases where the input type is known to be a pointer type (which
3432 // is considered resolved), but the result knows it needs to be 32- or
3433 // 64-bits. Infer the other way for good measure.
3434 for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(),
3435 Pattern->getTree(0)->getNumTypes());
3436 i != e; ++i) {
3437 IterateInference = Pattern->getTree(0)->UpdateNodeType(
3438 i, Result.getTree(0)->getExtType(i), Result);
3439 IterateInference |= Result.getTree(0)->UpdateNodeType(
3440 i, Pattern->getTree(0)->getExtType(i), Result);
3441 }
3442
3443 // If our iteration has converged and the input pattern's types are fully
3444 // resolved but the result pattern is not fully resolved, we may have a
3445 // situation where we have two instructions in the result pattern and
3446 // the instructions require a common register class, but don't care about
3447 // what actual MVT is used. This is actually a bug in our modelling:
3448 // output patterns should have register classes, not MVTs.
3449 //
3450 // In any case, to handle this, we just go through and disambiguate some
3451 // arbitrary types to the result pattern's nodes.
3452 if (!IterateInference && InferredAllPatternTypes &&
3453 !InferredAllResultTypes)
3454 IterateInference =
3455 ForceArbitraryInstResultType(Result.getTree(0), Result);
3456 } while (IterateInference);
3457
3458 // Verify that we inferred enough types that we can do something with the
3459 // pattern and result. If these fire the user has to add type casts.
3460 if (!InferredAllPatternTypes)
3461 Pattern->error("Could not infer all types in pattern!");
3462 if (!InferredAllResultTypes) {
3463 Pattern->dump();
3464 Result.error("Could not infer all types in pattern result!");
3465 }
3466
3467 // Validate that the input pattern is correct.
3468 std::map<std::string, TreePatternNode*> InstInputs;
3469 std::map<std::string, TreePatternNode*> InstResults;
3470 std::vector<Record*> InstImpResults;
3471 for (unsigned j = 0, ee = Pattern->getNumTrees(); j != ee; ++j)
3472 FindPatternInputsAndOutputs(Pattern, Pattern->getTree(j),
3473 InstInputs, InstResults,
3474 InstImpResults);
3475
3476 // Promote the xform function to be an explicit node if set.
3477 TreePatternNode *DstPattern = Result.getOnlyTree();
3478 std::vector<TreePatternNode*> ResultNodeOperands;
3479 for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) {
3480 TreePatternNode *OpNode = DstPattern->getChild(ii);
3481 if (Record *Xform = OpNode->getTransformFn()) {
3482 OpNode->setTransformFn(nullptr);
3483 std::vector<TreePatternNode*> Children;
3484 Children.push_back(OpNode);
3485 OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
3486 }
3487 ResultNodeOperands.push_back(OpNode);
3488 }
3489 DstPattern = Result.getOnlyTree();
3490 if (!DstPattern->isLeaf())
3491 DstPattern = new TreePatternNode(DstPattern->getOperator(),
3492 ResultNodeOperands,
3493 DstPattern->getNumTypes());
3494
3495 for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i)
3496 DstPattern->setType(i, Result.getOnlyTree()->getExtType(i));
3497
3498 TreePattern Temp(Result.getRecord(), DstPattern, false, *this);
3499 Temp.InferAllTypes();
3500
3501
3502 AddPatternToMatch(Pattern,
3503 PatternToMatch(CurPattern,
3504 CurPattern->getValueAsListInit("Predicates"),
3505 Pattern->getTree(0),
3506 Temp.getOnlyTree(), InstImpResults,
3507 CurPattern->getValueAsInt("AddedComplexity"),
3508 CurPattern->getID()));
3509 }
3510 }
上面根据Pattern定义的PatternToMatch与ResultInstrs,分别建立了两棵TreePattern树,Pattern与Result,注意Pattern被视为输入模板,Result则是输出目标,因此它们的处理与内联展开是有区别的。接着在3417行循环里不停地进行类型推导迭代,直到不再发生变化。
其中,3455行的ForceArbitraryInstResultType()尝试尽可能地确定Result包含的返回类型。
3360 static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) {
3361 if (N->isLeaf())
3362 return false;
3363
3364 // Analyze children.
3365 for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
3366 if (ForceArbitraryInstResultType(N->getChild(i), TP))
3367 return true;
3368
3369 if (!N->getOperator()->isSubClassOf("Instruction"))
3370 return false;
3371
3372 // If this type is already concrete or completely unknown we can't do
3373 // anything.
3374 for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) {
3375 if (N->getExtType(i).isCompletelyUnknown() || N->getExtType(i).isConcrete())
3376 continue;
3377
3378 // Otherwise, force its type to the first possibility (an arbitrary choice).
3379 if (N->getExtType(i).MergeInTypeInfo(N->getExtType(i).getTypeList()[0], TP))
3380 return true;
3381 }
3382
3383 return false;
3384 }
在3379行,如果指定的返回类型既不是确定,又不是完全未知,就将它尽可能向第一个类型靠拢。因为只有所有的类型都能推导出来时InferAllTypes()才返回true,因此在3468行以下类型都是已知的。接下来在Pattern中确定输入操作数、结果及隐含结果。而Result则用于表示指令的结果。最后生成PatternToMatch实例。这些操作都与对Instruction的处理类似。
V7.0的处理
V7.0版本的CodeGenDAGPatterns::ParsePatterns()定义如下: 4061 void CodeGenDAGPatterns::ParsePatterns() { 4062 std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern"); 4063 4064 for (Record *CurPattern : Patterns) { 4065 DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch"); 4066 4067 // If the pattern references the null_frag, there's nothing to do. 4068 if (hasNullFragReference(Tree)) 4069 continue; 4070 4071 TreePattern Pattern(CurPattern, Tree, true, *this); 4072 4073 ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); 4074 if (LI->empty()) continue; // no pattern. 4075 4076 // Parse the instruction. 4077 TreePattern Result(CurPattern, LI, false, *this); 4078 4079 if (Result.getNumTrees() != 1) 4080 Result.error("Cannot handle instructions producing instructions " 4081 "with temporaries yet!"); 4082 4083 // Validate that the input pattern is correct. 4084 std::map<std::string, TreePatternNodePtr> InstInputs; 4085 std::map<std::string, TreePatternNodePtr> InstResults; 4086 std::vector<Record*> InstImpResults; 4087 for (unsigned j = 0, ee = Pattern.getNumTrees(); j != ee; ++j) 4088 FindPatternInputsAndOutputs(Pattern, Pattern.getTree(j), InstInputs, 4089 InstResults, InstImpResults); 4090 4091 ParseOnePattern(CurPattern, Pattern, Result, InstImpResults); 4092 } 4093 } 重构后结构清晰了很多。 |
3.4.2.7. 展开基于硬件模式的类型(v7.0)
前面我们已经对指令生成了PatternToMatch对象,但是我们没有考虑指令的结果类型可能与硬件模式相关。我们需要为每个相关硬件模式构建一个PatternToMatch实例,以及对应的选择谓词。这就是下面的CodeGenDAGPatterns::ExpandHwModeBasedTypes()方法要做的事情。
4104 void CodeGenDAGPatterns::ExpandHwModeBasedTypes() {
4105 const CodeGenHwModes &CGH = getTargetInfo().getHwModes();
4106 std::map<unsigned,std::vector<Predicate>> ModeChecks;
4107 std::vector<PatternToMatch> Copy = PatternsToMatch;
4108 PatternsToMatch.clear();
4109
4110 auto AppendPattern = [this, &ModeChecks](PatternToMatch &P, unsigned Mode) {
4111 TreePatternNodePtr NewSrc = P.SrcPattern->clone();
4112 TreePatternNodePtr NewDst = P.DstPattern->clone();
4113 if (!NewSrc->setDefaultMode(Mode) || !NewDst->setDefaultMode(Mode)) {
4114 return;
4115 }
4116
4117 std::vector<Predicate> Preds = P.Predicates;
4118 const std::vector<Predicate> &MC = ModeChecks[Mode];
4119 Preds.insert(Preds.end(), MC.begin(), MC.end());
4120 PatternsToMatch.emplace_back(P.getSrcRecord(), Preds, std::move(NewSrc),
4121 std::move(NewDst), P.getDstRegs(),
4122 P.getAddedComplexity(), Record::getNewUID(),
4123 Mode);
4124 };
4125
4126 for (PatternToMatch &P : Copy) {
4127 TreePatternNodePtr SrcP = nullptr, DstP = nullptr;
4128 if (P.SrcPattern->hasProperTypeByHwMode())
4129 SrcP = P.SrcPattern;
4130 if (P.DstPattern->hasProperTypeByHwMode())
4131 DstP = P.DstPattern;
4132 if (!SrcP && !DstP) {
4133 PatternsToMatch.push_back(P);
4134 continue;
4135 }
4136
4137 std::set<unsigned> Modes;
4138 if (SrcP)
4139 collectModes(Modes, SrcP.get());
4140 if (DstP)
4141 collectModes(Modes, DstP.get());
4142
4143 // The predicate for the default mode needs to be constructed for each
4144 // pattern separately.
4145 // Since not all modes must be present in each pattern, if a mode m is
4146 // absent, then there is no point in constructing a check for m. If such
4147 // a check was created, it would be equivalent to checking the default
4148 // mode, except not all modes' predicates would be a part of the checking
4149 // code. The subsequently generated check for the default mode would then
4150 // have the exact same patterns, but a different predicate code. To avoid
4151 // duplicated patterns with different predicate checks, construct the
4152 // default check as a negation of all predicates that are actually present
4153 // in the source/destination patterns.
4154 std::vector<Predicate> DefaultPred;
4155
4156 for (unsigned M : Modes) {
4157 if (M == DefaultMode)
4158 continue;
4159 if (ModeChecks.find(M) != ModeChecks.end())
4160 continue;
4161
4162 // Fill the map entry for this mode.
4163 const HwMode &HM = CGH.getMode(M);
4164 ModeChecks[M].emplace_back(Predicate(HM.Features, true));
4165
4166 // Add negations of the HM's predicates to the default predicate.
4167 DefaultPred.emplace_back(Predicate(HM.Features, false));
4168 }
4169
4170 for (unsigned M : Modes) {
4171 if (M == DefaultMode)
4172 continue;
4173 AppendPattern(P, M);
4174 }
4175
4176 bool HasDefault = Modes.count(DefaultMode);
4177 if (HasDefault)
4178 AppendPattern(P, DefaultMode);
4179 }
4180 }
4128与4130行的TreePatternNode::hasProperTypeByHwMode()方法分别检查匹配模式与结果模式是否有缺省模式以外的硬件模式。如果有,进入4139行以下,通过collectModes()方法收集这些模式。在4156行循环根据非缺省模式构造Predicate实例保存在ModeChecks容器,构造条件相反的Predicate实例保存在DefaultPred容器。
接着在4170行循环,通过4110~4124行定义的AppendPattern兰布达表达式,在PatternsToMatch容器中添加各个模式对应的PatternToMatch实例。注意在4123行向PatternToMatch构造函数插入参数ForceMode。