LLVM学习笔记(22)

来源:互联网 发布:域名如何别名解析 编辑:程序博客网 时间:2024/06/05 01:54

3.4.2.7.       PatternToMatch的变体

因为符合交换律的模式可以有多种匹配形式,还需要从相应的PatternToMatch实例生成符合这些匹配形式的PatternToMatch变体,来覆盖这些情形。

3744   void CodeGenDAGPatterns::GenerateVariants(){

3745     DEBUG(errs() << "Generatinginstruction variants.\n");

3746  

3747     // Loop over allof the patterns we've collected, checking to see if we can

3748    // generatevariants of the instruction, through the exploitation of

3749    //identities.  This permits the target toprovide aggressive matching without

3750    // the .td filehaving to contain tons of variants of instructions.

3751    //

3752    // Note that thisloop adds new patterns to the PatternsToMatch list, but we

3753    // intentionallydo not reconsider these.  Any variants ofadded patterns have

3754    // already beenadded.

3755    //

3756     for (unsignedi = 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 theoriginal pattern.

3768  

3769       if (Variants.empty())  // No variantsfor this pattern.

3770         continue;

3771  

3772       DEBUG(errs() << "FOUND VARIANTSOF: ";

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 tosee 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 ifthe top level predicates do not match.

3787           if (PatternsToMatch[i].getPredicates()!=

3788               PatternsToMatch[p].getPredicates())

3789             continue;

3790           // Check tosee if this variant already exists.

3791           if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(),

3792                                       DepVars)) {

3793             DEBUG(errs() << "  *** ALREADY EXISTS, ignoringvariant.\n");

3794             AlreadyExists = true;

3795             break;

3796           }

3797         }

3798         // If wealready 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容器导出。注意,原始版本总是容器里的第一个项。

3630   static voidGenerateVariantsOf(TreePatternNode *N,

3631                                 std::vector<TreePatternNode*> &OutVariants,

3632                                 CodeGenDAGPatterns &CDP,

3633                                  constMultipleUseVarSet &DepVars) {

3634     // We cannotpermute leaves or ComplexPattern uses.

3635     if (N->isLeaf() ||N->getOperator()->isSubClassOf("ComplexPattern")) {

3636       OutVariants.push_back(N);

3637       return;

3638     }

3639  

3640     // Look upinteresting info about the node.

3641     constSDNodeInfo &NodeInfo = CDP.getSDNodeInfo(N->getOperator());

3642  

3643     // If this nodeis associative, re-associate.

3644     if (NodeInfo.hasProperty(SDNPAssociative)) {

3645       // Re-associateby pulling together all of the linked operators

3646       std::vector<TreePatternNode*>MaximalChildren;

3647       GatherChildrenOfAssociativeOpcode(N,MaximalChildren);

3648  

3649       // Only handlechild sizes of 3.  Otherwise we'll end uptrying too many

3650      // permutations.

3651       if (MaximalChildren.size() == 3) {

3652         // Find thevariants 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 areonly two ways we can permute the tree:

3659        //   (A op B) op C    and   A op (B op C)

3660        // Withinthese forms, we can also permute A/B/C.

3661  

3662        // Generatelegal 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         // Combinethose 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         // Combinethose 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行的操作出问题(触发断言),就说明描述出错了。

如果满足3644行条件,说明这个SDNode还代表一个满足结合律的操作。首先,需要查明它有几个操作数。

3604   static voidGatherChildrenOfAssociativeOpcode(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 permitraw 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形式的,如果子树的操作符与当前操作符一致,就说明这些操作符是连续的,就像Aop B op C;否则就是被子树操作符隔开的(因而无需考虑)。

满足结合律的操作符如果涉及的操作数太多(即太多操作符串联在一起),其组合数将会太大,因此这里限定操作数为3(如果是2就跟满交换律的操作符一样)。在3654~3657行递归求出每个子树可能的变体,并保存在对应的容器里。然后对每种组合(集合)调用下面的方法。

3591   static voidCombineChildVariants(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 voidCombineChildVariants(TreePatternNode *Orig,

3515                  conststd::vector<std::vector<TreePatternNode*> > &ChildVariants,

3516                                   std::vector<TreePatternNode*> &OutVariants,

3517                                   CodeGenDAGPatterns &CDP,

3518                                   const MultipleUseVarSet &DepVars) {

3519     // Make sure thateach operand has at least one variant to choose from.

3520     for (unsignedi = 0, e = ChildVariants.size(); i != e; ++i)

3521       if (ChildVariants[i].empty())

3522         return;

3523  

3524     // The end resultis an all-pairs construction of the resultant pattern.

3525     std::vector<unsigned> Idxs;

3526     Idxs.resize(ChildVariants.size());

3527     bool NotDone;

3528     do {

3529   #ifndefNDEBUG

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 thevariant 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,

3543                                               Orig->getNumTypes());

3544  

3545       // Copy overproperties.

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 thispattern cannot match, do not include it as a variant.

3553       std::string ErrString;

3554       if (!R->canPatternMatch(ErrString, CDP)){

3555         delete R;

3556       } else {

3557         bool AlreadyExists = false;

3558  

3559         // Scan tosee 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 arethe 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           deleteR;

3571         else

3572           OutVariants.push_back(R);

3573       }

3574  

3575       // Incrementindices to the next permutation by incrementing the

3576      // indiciesfrom 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 (unsignedi = 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 (unsignedi = 0, e = N->getNumChildren(); i != e; ++i)

3699       GenerateVariantsOf(N->getChild(i),ChildVariants[i], CDP, DepVars);

3700  

3701     // Build allpermutations based on how the children were formed.

3702     CombineChildVariants(N, ChildVariants,OutVariants, CDP, DepVars);

3703  

3704     // If this nodeis 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 2children!");

3709       // Don't countchildren 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 thecommuted order.

3722       if (isCommIntrinsic) {

3723         //Commutative intrinsic. First operand is the intrinsic id, 2nd and 3rd

3724        // operandsare the commutative operands, and there might be more operands

3725        // afterthose.

3726         assert(NC>= 3 &&

3727                "Commutative intrinsic shouldhave 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)

3736         CombineChildVariants(N, ChildVariants[1],ChildVariants[0],

3737                              OutVariants, CDP,DepVars);

3738     }

3739   }

看到对于符合交换律的操作符,需要进一步做的是交换这两棵子树,生成对应的版本。

在产生出所有的变体后,在GenerateVariants的3776行循环遍历这些变体,在3785行循环检查确保它们不与原有的PatternToMatch对象同构。

原创粉丝点击