LLVM学习笔记(22)

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 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 &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 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 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 ABVariants;

3664        std::vector BAVariants;

3665        std::vector ACVariants;

3666        std::vector CAVariants;

3667        std::vector BCVariants;

3668        std::vector 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 &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 &LHS,

3593                                   const std::vector &RHS,

3594                                   std::vector &OutVariants,

3595                                   CodeGenDAGPatterns &CDP,

3596                                   const MultipleUseVarSet &DepVars) {

3597    std::vector > 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 > &ChildVariants,

3516                                   std::vector &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 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 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(                                 <-- 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(getLeafValue())) {

1279        if (DefInit *NDI = dyn_cast(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 > 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(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 > 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> 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对象同构。

你可能感兴趣的:(LLVM学习笔记,编译器,llvm,compiler)