LLVM学习笔记(21)

来源:互联网 发布:推广平台源码 编辑:程序博客网 时间:2024/06/02 02:23

3.4.2.6.       Pattern的处理

我们已经知道Pattern定义可以将通用的IR的指令表示映射为特定于目标机器的指令(对目标机器不同的型号,可以映射到这些型号特有的、更高效的指令)。因此,对指令选择,Pattern定义是有益的补充。因为Pattern定义会援引指令,因此需要在解析完所有的指令定义后才开始。

3386   void CodeGenDAGPatterns::ParsePatterns(){

3387     std::vector<Record*> Patterns =Records.getAllDerivedDefinitions("Pattern");

3388  

3389     for (unsignedi = 0, e = Patterns.size(); i != e; ++i) {

3390       Record *CurPattern = Patterns[i];

3391       DagInit *Tree =CurPattern->getValueAsDag("PatternToMatch");

3392  

3393       // If thepattern 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       // Inlinepattern fragments into it.

3400       Pattern->InlinePatternFragments();

3401  

3402       ListInit *LI =CurPattern->getValueAsListInit("ResultInstrs");

3403       if (LI->empty()) continue// no pattern.

3404  

3405       // Parse theinstruction.

3406       TreePattern Result(CurPattern, LI, false, *this);

3407  

3408       // Inlinepattern fragments into it.

3409       Result.InlinePatternFragments();

3410  

3411       if (Result.getNumTrees() != 1)

3412         Result.error("Cannot handleinstructions producing instructions "

3413                      "with temporaries yet!");

3414  

3415       bool IterateInference;

3416       bool InferredAllPatternTypes,InferredAllResultTypes;

3417       do {

3418         // Infer asmany types as possible.  If we cannotinfer all of them, we

3419        // can neverdo anything with this pattern: report it to the user.

3420         InferredAllPatternTypes =

3421           Pattern->InferAllTypes(&Pattern->getNamedNodesMap());

3422  

3423         // Infer asmany types as possible.  If we cannotinfer all of them, we

3424        // can neverdo anything with this pattern: report it to the user.

3425         InferredAllResultTypes =

3426             Result.InferAllTypes(&Pattern->getNamedNodesMap());

3427  

3428         IterateInference = false;

3429  

3430         // Apply thetype of the result to the source pattern. This helps us

3431        // resolvecases where the input type is known to be a pointer type (which

3432        // isconsidered resolved), but the result knows it needs to be 32- or

3433        //64-bits.  Infer the other way for goodmeasure.

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 ouriteration has converged and the input pattern's types are fully

3444        // resolvedbut the result pattern is not fully resolved, we may have a

3445        // situationwhere we have two instructions in the result pattern and

3446        // theinstructions require a common register class, but don't care about

3447        // whatactual MVT is used.  This is actually abug in our modelling:

3448        // outputpatterns should have register classes, not MVTs.

3449        //

3450        // In anycase, to handle this, we just go through and disambiguate some

3451        // arbitrarytypes 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 thatwe inferred enough types that we can do something with the

3459      // pattern andresult.  If these fire the user has toadd type casts.

3460       if (!InferredAllPatternTypes)

3461         Pattern->error("Could not inferall types in pattern!");

3462       if (!InferredAllResultTypes) {

3463         Pattern->dump();

3464         Result.error("Could not infer alltypes in pattern result!");

3465       }

3466  

3467       // Validatethat 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 thexform 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 = newTreePatternNode(Xform, Children, OpNode->getNumTypes());

3486         }

3487         ResultNodeOperands.push_back(OpNode);

3488       }

3489       DstPattern = Result.getOnlyTree();

3490       if (!DstPattern->isLeaf())

3491         DstPattern = newTreePatternNode(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 boolForceArbitraryInstResultType(TreePatternNode*N, TreePattern &TP) {

3361     if (N->isLeaf())

3362       return false;

3363  

3364     // Analyzechildren.

3365     for (unsignedi = 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 typeis already concrete or completely unknown we can't do

3373    // anything.

3374     for (unsignedi = 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的处理类似。