3.4.2.8. PatternToMatch的变体
因为符合交换律的模式可以有多种匹配形式,还需要从相应的PatternToMatch实例生成符合这些匹配形式的PatternToMatch变体来覆盖这些情形。
3744 void CodeGenDAGPatterns::GenerateVariants() {
3745 DEBUG(errs() << "Generating instruction variants.\n");
3746
3747 // Loop over all of the patterns we've collected, checking to see if we can
3748 // generate variants of the instruction, through the exploitation of
3749 // identities. This permits the target to provide aggressive matching without
3750 // the .td file having to contain tons of variants of instructions.
3751 //
3752 // Note that this loop adds new patterns to the PatternsToMatch list, but we
3753 // intentionally do not reconsider these. Any variants of added patterns have
3754 // already been added.
3755 //
3756 for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
3757 MultipleUseVarSet DepVars;
3758 std::vector<TreePatternNode*> Variants;
3759 FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars);
3760 DEBUG(errs() << "Dependent/multiply used variables: ");
3761 DEBUG(DumpDepVars(DepVars));
3762 DEBUG(errs() << "\n");
3763 GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this,
3764 DepVars);
3765
3766 assert(!Variants.empty() && "Must create at least original variant!");
3767 Variants.erase(Variants.begin()); // Remove the original pattern. <-- v7.0删除
3768
3769 if (Variants.empty()) // No variants for this pattern.
3770 continue;
if (Variants.size() == 1) // No additional variants for this pattern. <-- v7.0增加
continue;
3771
3772 DEBUG(errs() << "FOUND VARIANTS OF: ";
3773 PatternsToMatch[i].getSrcPattern()->dump();
3774 errs() << "\n");
3775
3776 for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
3777 TreePatternNode *Variant = Variants[v];
3778
3779 DEBUG(errs() << " VAR#" << v << ": ";
3780 Variant->dump();
3781 errs() << "\n");
3782
3783 // Scan to see if an instruction or explicit pattern already matches this.
3784 bool AlreadyExists = false;
3785 for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
3786 // Skip if the top level predicates do not match.
3787 if (PatternsToMatch[i].getPredicates() !=
3788 PatternsToMatch[p].getPredicates())
3789 continue;
3790 // Check to see if this variant already exists.
3791 if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(),
3792 DepVars)) {
3793 DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n");
3794 AlreadyExists = true;
3795 break;
3796 }
3797 }
3798 // If we already have it, ignore the variant.
3799 if (AlreadyExists) continue;
3800
3801 // Otherwise, add it to the list of patterns we have.
3802 PatternsToMatch.emplace_back(
3803 PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(),
3804 Variant, PatternsToMatch[i].getDstPattern(),
3805 PatternsToMatch[i].getDstRegs(),
3806 PatternsToMatch[i].getAddedComplexity(), Record::getNewUID());
3807 }
3808
3809 DEBUG(errs() << "\n");
3810 }
3811 }
在3756行开始的循环里,生成变体的具体工作由GenerateVariantsOf()方法负责,生成的变体(包括原始版本)由临时的Variants容器导出。注意,原始版本总是容器里的第一个项(在v7.0中,3802行调用的PatternToMatch构造函数时,使用缺省的ForceMode参数,即缺省硬件模式)。
3630 static void GenerateVariantsOf(TreePatternNode *N,
3631 std::vector<TreePatternNode*> &OutVariants,
3632 CodeGenDAGPatterns &CDP,
3633 const MultipleUseVarSet &DepVars) {
3634 // We cannot permute leaves or ComplexPattern uses.
3635 if (N->isLeaf() || N->getOperator()->isSubClassOf("ComplexPattern")) {
3636 OutVariants.push_back(N);
3637 return;
3638 }
3639
3640 // Look up interesting info about the node.
3641 const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(N->getOperator());
3642
3643 // If this node is associative, re-associate.
3644 if (NodeInfo.hasProperty(SDNPAssociative)) {
3645 // Re-associate by pulling together all of the linked operators
3646 std::vector<TreePatternNode*> MaximalChildren;
3647 GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
3648
3649 // Only handle child sizes of 3. Otherwise we'll end up trying too many
3650 // permutations.
3651 if (MaximalChildren.size() == 3) {
3652 // Find the variants of all of our maximal children.
3653 std::vector<TreePatternNode*> AVariants, BVariants, CVariants;
3654 GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars);
3655 GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars);
3656 GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars);
3657
3658 // There are only two ways we can permute the tree:
3659 // (A op B) op C and A op (B op C)
3660 // Within these forms, we can also permute A/B/C.
3661
3662 // Generate legal pair permutations of A/B/C.
3663 std::vector<TreePatternNode*> ABVariants;
3664 std::vector<TreePatternNode*> BAVariants;
3665 std::vector<TreePatternNode*> ACVariants;
3666 std::vector<TreePatternNode*> CAVariants;
3667 std::vector<TreePatternNode*> BCVariants;
3668 std::vector<TreePatternNode*> CBVariants;
3669 CombineChildVariants(N, AVariants, BVariants, ABVariants, CDP, DepVars);
3670 CombineChildVariants(N, BVariants, AVariants, BAVariants, CDP, DepVars);
3671 CombineChildVariants(N, AVariants, CVariants, ACVariants, CDP, DepVars);
3672 CombineChildVariants(N, CVariants, AVariants, CAVariants, CDP, DepVars);
3673 CombineChildVariants(N, BVariants, CVariants, BCVariants, CDP, DepVars);
3674 CombineChildVariants(N, CVariants, BVariants, CBVariants, CDP, DepVars);
3675
3676 // Combine those into the result: (x op x) op x
3677 CombineChildVariants(N, ABVariants, CVariants, OutVariants, CDP, DepVars);
3678 CombineChildVariants(N, BAVariants, CVariants, OutVariants, CDP, DepVars);
3679 CombineChildVariants(N, ACVariants, BVariants, OutVariants, CDP, DepVars);
3680 CombineChildVariants(N, CAVariants, BVariants, OutVariants, CDP, DepVars);
3681 CombineChildVariants(N, BCVariants, AVariants, OutVariants, CDP, DepVars);
3682 CombineChildVariants(N, CBVariants, AVariants, OutVariants, CDP, DepVars);
3683
3684 // Combine those into the result: x op (x op x)
3685 CombineChildVariants(N, CVariants, ABVariants, OutVariants, CDP, DepVars);
3686 CombineChildVariants(N, CVariants, BAVariants, OutVariants, CDP, DepVars);
3687 CombineChildVariants(N, BVariants, ACVariants, OutVariants, CDP, DepVars);
3688 CombineChildVariants(N, BVariants, CAVariants, OutVariants, CDP, DepVars);
3689 CombineChildVariants(N, AVariants, BCVariants, OutVariants, CDP, DepVars);
3690 CombineChildVariants(N, AVariants, CBVariants, OutVariants, CDP, DepVars);
3691 return;
3692 }
3693 }
我们已经知道在实际使用里,dag值的操作符是SDNode、ValueType或简单定义(outs,ins,ops等),但除了SDNode,其他的都不能作为模式描述的第一层dag值的操作符。因此如果3641行的操作出问题(在getSDNodeInfo()里触发断言),就说明描述出错了。
如果满足3644行条件,说明这个SDNode还代表一个满足结合律的操作。首先,需要查明它有几个操作数。
3604 static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N,
3605 std::vector<TreePatternNode *> &Children) {
3606 assert(N->getNumChildren()==2 &&"Associative but doesn't have 2 children!");
3607 Record *Operator = N->getOperator();
3608
3609 // Only permit raw nodes.
3610 if (!N->getName().empty() || !N->getPredicateFns().empty() ||
3611 N->getTransformFn()) {
3612 Children.push_back(N);
3613 return;
3614 }
3615
3616 if (N->getChild(0)->isLeaf() || N->getChild(0)->getOperator() != Operator)
3617 Children.push_back(N->getChild(0));
3618 else
3619 GatherChildrenOfAssociativeOpcode(N->getChild(0), Children);
3620
3621 if (N->getChild(1)->isLeaf() || N->getChild(1)->getOperator() != Operator)
3622 Children.push_back(N->getChild(1));
3623 else
3624 GatherChildrenOfAssociativeOpcode(N->getChild(1), Children);
3625 }
如果子树包含的操作符与当前操作符不一样,就不需要再考虑这棵子树了,否则就需要递归进入子树找出所有一样的操作符及其操作数。这是因为在中间表达形式里,表达式是Postfix形式的,如果子树的操作符与当前操作符一致,就说明这些操作符是连续的,就像A op B op C;否则就是被子树操作符隔开的(因而无需考虑)。
满足结合律的操作符如果涉及的操作数太多(即太多操作符串联在一起),其组合数将会太大,因此这里限定操作数为3(如果是2就跟满交换律的操作符一样)。在3654~3657行递归求出每个子树可能的变体,并保存在对应的容器里。然后对每种组合(集合)调用下面的方法。
3591 static void CombineChildVariants(TreePatternNode *Orig,
3592 const std::vector<TreePatternNode*> &LHS,
3593 const std::vector<TreePatternNode*> &RHS,
3594 std::vector<TreePatternNode*> &OutVariants,
3595 CodeGenDAGPatterns &CDP,
3596 const MultipleUseVarSet &DepVars) {
3597 std::vector<std::vector<TreePatternNode*> > ChildVariants;
3598 ChildVariants.push_back(LHS);
3599 ChildVariants.push_back(RHS);
3590 CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars);
3601 }
显然,在叶子一级,容器LHS与RHS最多只包含一个元素。但随着返回到更上层,这些容器包含的元素会越来越多(它们是下层子树的组合数)。这里要对其中包含的元素进行排列组合,因此3525行的临时容器Idxs用于辅助遍历这些组合。注意,容器ChildVariants是一个两层的容器,在这里第一层总是只有两个因数(左操作数与右操作数,不过在下面的GenerateVariantsOf()调用里,第一层可能包含超过2个元素),3579行的循环生成这些孩子的全排列组合。
3514 static void CombineChildVariants(TreePatternNode *Orig,
3515 const std::vector<std::vector<TreePatternNode*> > &ChildVariants,
3516 std::vector<TreePatternNode*> &OutVariants,
3517 CodeGenDAGPatterns &CDP,
3518 const MultipleUseVarSet &DepVars) {
3519 // Make sure that each operand has at least one variant to choose from.
3520 for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
3521 if (ChildVariants[i].empty())
3522 return;
3523
3524 // The end result is an all-pairs construction of the resultant pattern.
3525 std::vector<unsigned> Idxs;
3526 Idxs.resize(ChildVariants.size());
3527 bool NotDone;
3528 do {
3529 #ifndef NDEBUG
3530 DEBUG(if (!Idxs.empty()) {
3531 errs() << Orig->getOperator()->getName() << ": Idxs = [ ";
3532 for (unsigned i = 0; i < Idxs.size(); ++i) {
3533 errs() << Idxs[i] << " ";
3534 }
3535 errs() << "]\n";
3536 });
3537 #endif
3538 // Create the variant and add it to the output list.
3539 std::vector<TreePatternNode*> NewChildren;
3540 for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
3541 NewChildren.push_back(ChildVariants[i][Idxs[i]]);
3542 TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren, <-- v7.0删除
3543 Orig->getNumTypes());
TreePatternNodePtr R = std::make_shared<TreePatternNode>( <-- v7.0增加
Orig->getOperator(), std::move(NewChildren), Orig->getNumTypes());
3544
3545 // Copy over properties.
3546 R->setName(Orig->getName());
3547 R->setPredicateFns(Orig->getPredicateFns());
3548 R->setTransformFn(Orig->getTransformFn());
3549 for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i)
3550 R->setType(i, Orig->getExtType(i));
3551
3552 // If this pattern cannot match, do not include it as a variant.
3553 std::string ErrString;
3554 if (!R->canPatternMatch(ErrString, CDP)) { <-- v7.0删除
3555 delete R;
3556 } else {
3557 bool AlreadyExists = false;
3558
3559 // Scan to see if this pattern has already been emitted. We can get
3560 // duplication due to things like commuting:
3561 // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
3562 // which are the same pattern. Ignore the dups.
3563 for (unsigned i = 0, e = OutVariants.size(); i != e; ++i)
3564 if (R->isIsomorphicTo(OutVariants[i], DepVars)) {
3565 AlreadyExists = true;
3566 break;
3567 }
3568
3569 if (AlreadyExists)
3570 delete R;
3571 else
if (R->canPatternMatch(ErrString, CDP) && <-- v7.0增加
none_of(OutVariants, [&](TreePatternNodePtr Variant) {
return R->isIsomorphicTo(Variant.get(), DepVars);
}))
3572 OutVariants.push_back(R);
3573 }
3574
3575 // Increment indices to the next permutation by incrementing the
3576 // indicies from last index backward, e.g., generate the sequence
3577 // [0, 0], [0, 1], [1, 0], [1, 1].
3578 int IdxsIdx;
3579 for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) {
3580 if (++Idxs[IdxsIdx] == ChildVariants[IdxsIdx].size())
3581 Idxs[IdxsIdx] = 0;
3582 else
3583 break;
3584 }
3585 NotDone = (IdxsIdx >= 0);
3586 } while (NotDone);
3587 }
另外,在穷举所有排列可能的同时,我们要确保这些变体不是同构的,否则就只需要其中一个就可以了。
1269 bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N,
1270 const MultipleUseVarSet &DepVars) const {
1271 if (N == this) return true;
1272 if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() ||
1273 getPredicateFns() != N->getPredicateFns() ||
1274 getTransformFn() != N->getTransformFn())
1275 return false;
1276
1277 if (isLeaf()) {
1278 if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) {
1279 if (DefInit *NDI = dyn_cast<DefInit>(N->getLeafValue())) {
1280 return ((DI->getDef() == NDI->getDef())
1281 && (DepVars.find(getName()) == DepVars.end()
1282 || getName() == N->getName()));
1283 }
1284 }
1285 return getLeafValue() == N->getLeafValue();
1286 }
1287
1288 if (N->getOperator() != getOperator() ||
1289 N->getNumChildren() != getNumChildren()) return false;
1290 for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
1291 if (!getChild(i)->isIsomorphicTo(N->getChild(i), DepVars))
1292 return false;
1293 return true;
1294 }
对于符合交换律或只有两个操作数的符合交换律的操作符,进入下面的处理。
GenerateVariantsOf(续)
3695 // Compute permutations of all children.
3696 std::vector<std::vector<TreePatternNode*> > ChildVariants;
3697 ChildVariants.resize(N->getNumChildren());
3698 for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
3699 GenerateVariantsOf(N->getChild(i), ChildVariants[i], CDP, DepVars);
3700
3701 // Build all permutations based on how the children were formed.
3702 CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars);
3703
3704 // If this node is commutative, consider the commuted order.
3705 bool isCommIntrinsic = N->isCommutativeIntrinsic(CDP);
3706 if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) {
3707 assert((N->getNumChildren()==2 || isCommIntrinsic) &&
3708 "Commutative but doesn't have 2 children!");
3709 // Don't count children which are actually register references.
3710 unsigned NC = 0;
3711 for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
3712 TreePatternNode *Child = N->getChild(i);
3713 if (Child->isLeaf())
3714 if (DefInit *DI = dyn_cast<DefInit>(Child->getLeafValue())) {
3715 Record *RR = DI->getDef();
3716 if (RR->isSubClassOf("Register"))
3717 continue;
3718 }
3719 NC++;
3720 }
3721 // Consider the commuted order.
3722 if (isCommIntrinsic) {
3723 // Commutative intrinsic. First operand is the intrinsic id, 2nd and 3rd
3724 // operands are the commutative operands, and there might be more operands
3725 // after those.
3726 assert(NC >= 3 &&
3727 "Commutative intrinsic should have at least 3 childrean!");
3728 std::vector<std::vector<TreePatternNode*> > Variants;
3729 Variants.push_back(ChildVariants[0]); // Intrinsic id.
3730 Variants.push_back(ChildVariants[2]);
3731 Variants.push_back(ChildVariants[1]);
3732 for (unsigned i = 3; i != NC; ++i)
3733 Variants.push_back(ChildVariants[i]);
3734 CombineChildVariants(N, Variants, OutVariants, CDP, DepVars);
3735 } else if (NC == 2) <-- v7.0删除
3736 CombineChildVariants(N, ChildVariants[1], ChildVariants[0],
3737 OutVariants, CDP, DepVars);
} else if (NC == N->getNumChildren()) { <-- v7.0增加
std::vector<std::vector<TreePatternNodePtr>> Variants;
Variants.push_back(std::move(ChildVariants[1]));
Variants.push_back(std::move(ChildVariants[0]));
for (unsigned i = 2; i != NC; ++i)
Variants.push_back(std::move(ChildVariants[i]));
CombineChildVariants(N, Variants, OutVariants, CDP, DepVars);
}
3738 }
3739 }
看到对于符合交换律的操作符,需要进一步做的是交换这两棵子树,生成对应的版本(v7.0对非固有函数操作,只交换前两个操作数)。
在产生出所有的变体后,在GenerateVariants()的3776行循环遍历这些变体,在3785行循环检查确保它们不与原有的PatternToMatch对象同构。