LLVM学习笔记(27)

3.4.3.3. Match对象序列的优化

回到DAGISelEmitter::run()。注意PatternMatchers中每个项都是一条Matcher对象链,对应一条指令。在160行生成一个ScopeMatcher对象,把这些项设为自己的孩子。在下面生成的MatcherTable里,它产生的内容将使得SelectCommon()方法在匹配一个孩子(即一条指令)失败时,继续进行下一个孩子(即下一条指令)的匹配。

DAGISelEmitter::run(续)

160       std::unique_ptr<Matcher> TheMatcher =

161         llvm::make_unique<ScopeMatcher>(PatternMatchers);

162    

163       OptimizeMatcher(TheMatcher, CGP);

164       //Matcher->dump();

165       EmitMatcherTable(TheMatcher.get(), CGP, OS);

166     }

在输出MatcherTable之前,TableGen需要执行一个优化步骤。优化包括几方面。一方面在Matcher对象链里,可能存在若干Matcher对象序列,它们可以被更短的等效的Matcher对象序列所替代。另一方面,有些的Matcher对象可以作为公共因子提取出来,以形成更短的Matcher序列。

514     void

515     llvm::OptimizeMatcher(std::unique_ptr<Matcher> &MatcherPtr,

516                         const CodeGenDAGPatterns &CGP) {

517       ContractNodes(MatcherPtr, CGP);

518       SinkPatternPredicates(MatcherPtr);                                      <-- v7.0删除

519       FactorNodes(MatcherPtr);

520     }

3.4.3.3.1. ​​​​​​​合并Matcher对象

在Matcher对象序列里,有些Matcher对象是可以合并的,比如一个MoveChildMatcher与一个RecordMatcher就可以合并为一个RecordChildMatcher。这样不仅缩短了Matcher对象的序列,而且用一个更具体的Matcher对象来代替两个Matcher对象也简化了后续对Matcher对象序列的处理。

26       static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr,

27                                 const CodeGenDAGPatterns &CGP) {

28         // If we reached the end of the chain, we're done.

29         Matcher *N = MatcherPtr.get();

30         if (!N) return;

31      

32         // If we have a scope node, walk down all of the children.

33         if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) {

34           for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {

35             std::unique_ptr<Matcher> Child(Scope->takeChild(i));

36             ContractNodes(Child, CGP);

37             Scope->resetChild(i, Child.release());

38           }

39           return;

40         }

41        

42         // If we found a movechild node with a node that comes in a 'foochild' form,

43         // transform it.

44         if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) {

45           Matcher *New = nullptr;

46           if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext()))

47             if (MC->getChildNo() < 8)  // Only have RecordChild0...7

48               New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(),

49                                            RM->getResultNo());

50      

51           if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext()))

52             if (MC->getChildNo() < 8 &&  // Only have CheckChildType0...7

53                 CT->getResNo() == 0)     // CheckChildType checks res #0

54               New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType());

55      

56           if (CheckSameMatcher *CS = dyn_cast<CheckSameMatcher>(MC->getNext()))

57             if (MC->getChildNo() < 4)  // Only have CheckChildSame0...3

58               New = new CheckChildSameMatcher(MC->getChildNo(), CS->getMatchNumber());

59      

60           if (CheckIntegerMatcher *CS = dyn_cast<CheckIntegerMatcher>(MC->getNext()))

61             if (MC->getChildNo() < 5)  // Only have CheckChildInteger0...4

62               New = new CheckChildIntegerMatcher(MC->getChildNo(), CS->getValue());

63      

64           if (New) {

65             // Insert the new node.

66             New->setNext(MatcherPtr.release());

67             MatcherPtr.reset(New);

68             // Remove the old one.

69             MC->setNext(MC->getNext()->takeNext());

70             return ContractNodes(MatcherPtr, CGP);

71           }

72         }

73        

74         // Zap movechild -> moveparent.

75         if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N))

76           if (MoveParentMatcher *MP =

77               dyn_cast<MoveParentMatcher>(MC->getNext())) {

78             MatcherPtr.reset(MP->takeNext());

79             return ContractNodes(MatcherPtr, CGP);

80           }

81      

82         // Turn EmitNode->MarkFlagResults->CompleteMatch into

83         // MarkFlagResults->EmitNode->CompleteMatch when we can to encourage

84         // MorphNodeTo formation.  This is safe because MarkFlagResults never refers

85         // to the root of the pattern.

86         if (isa<EmitNodeMatcher>(N) && isa<MarkGlueResultsMatcher>(N->getNext()) &&   <-- v7.0删除

87             isa<CompleteMatchMatcher>(N->getNext()->getNext())) {

88           // Unlink the two nodes from the list.

89           Matcher *EmitNode = MatcherPtr.release();

90           Matcher *MFR = EmitNode->takeNext();

91           Matcher *Tail = MFR->takeNext();

92              

93           // Relink them.

94           MatcherPtr.reset(MFR);

95           MFR->setNext(EmitNode);

96           EmitNode->setNext(Tail);

97           return ContractNodes(MatcherPtr, CGP);

98         }

99      

100       // Turn EmitNode->CompleteMatch into MorphNodeTo if we can.

101       if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N))

102         if (CompleteMatchMatcher *CM =

103               dyn_cast<CompleteMatchMatcher>(EN->getNext())) {

104           // We can only use MorphNodeTo if the result values match up.

105           unsigned RootResultFirst = EN->getFirstResultSlot();

106           bool ResultsMatch = true;

107         for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)

108             if (CM->getResult(i) != RootResultFirst+i)

109               ResultsMatch = false;

110          

111           // If the selected node defines a subset of the glue/chain results, we

112           // can't use MorphNodeTo.  For example, we can't use MorphNodeTo if the

113           // matched pattern has a chain but the root node doesn't.

114           const PatternToMatch &Pattern = CM->getPattern();

115          

116           if (!EN->hasChain() &&

117               Pattern.getSrcPattern()->NodeHasProperty(SDNPHasChain, CGP))

118             ResultsMatch = false;

119    

120           // If the matched node has glue and the output root doesn't, we can't

121           // use MorphNodeTo.

122           //

123           // NOTE: Strictly speaking, we don't have to check for glue here

124           // because the code in the pattern generator doesn't handle it right.  We

125           // do it anyway for thoroughness.

126           if (!EN->hasOutFlag() &&

127               Pattern.getSrcPattern()->NodeHasProperty(SDNPOutGlue, CGP))

128             ResultsMatch = false;

129          

130          

131           // If the root result node defines more results than the source root node

132           // *and* has a chain or glue input, then we can't match it because it

133           // would end up replacing the extra result with the chain/glue.

134     #if 0

135           if ((EN->hasGlue() || EN->hasChain()) &&

136               EN->getNumNonChainGlueVTs() > ... need to get no results reliably ...)

137             ResultMatch = false;

138     #endif

139              

140           if (ResultsMatch) {

141             const SmallVectorImpl<MVT::SimpleValueType> &VTs = EN->getVTList();

142             const SmallVectorImpl<unsigned> &Operands = EN->getOperandList();

143             MatcherPtr.reset(new MorphNodeToMatcher(EN->getOpcodeName(),

144                                                     VTs, Operands,

145                                                     EN->hasChain(), EN->hasInFlag(),

146                                                     EN->hasOutFlag(),

147                                                     EN->hasMemRefs(),

148                                                     EN->getNumFixedArityOperands(),

149                                                     Pattern));

150             return;

151           }

152    

153           // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode

154           // variants.

155         }

156      

157       ContractNodes(N->getNextPtr(), CGP);

158      

159      

160       // If we have a CheckType/CheckChildType/Record node followed by a

161       // CheckOpcode, invert the two nodes.  We prefer to do structural checks

162       // before type checks, as this opens opportunities for factoring on targets

163       // like X86 where many operations are valid on multiple types.

164       if ((isa<CheckTypeMatcher>(N) || isa<CheckChildTypeMatcher>(N) ||

165            isa<RecordMatcher>(N)) &&

166           isa<CheckOpcodeMatcher>(N->getNext())) {

167         // Unlink the two nodes from the list.

168         Matcher *CheckType = MatcherPtr.release();

169         Matcher *CheckOpcode = CheckType->takeNext();

170         Matcher *Tail = CheckOpcode->takeNext();

171        

172         // Relink them.

173         MatcherPtr.reset(CheckOpcode);

174         CheckOpcode->setNext(CheckType);

175         CheckType->setNext(Tail);

176         return ContractNodes(MatcherPtr, CGP);

177       }

178     }

ContractNodes()是一个递归函数。因为Matcher对象的序列以ScopeMatcher实开始,因此最上层的ContractNodes()调用必然进入33~39行的分支。以后的递归调用则依据所见的Matcher实例分别进入不同的分支。有效的合并操作计有:

MoveChildMatcher + RecordMatcher à RecordChildMatcher(仅对第1~8的子节点)

MoveChildMatcher + CheckTypeMatcher à CheckChildTypeMatcher(仅对第1~8的子节点)

MoveChildMatcher + CheckSameMatcher à CheckChildSameMatcher(仅对第1~4的子节点)

MoveChildMatcher + CheckIntegerMatcher à CheckChildIntegerMatcher(仅对第1~5的子节点)

MoveChildMatcher + MoveParentMatcher à 0

EmitNodeMatcher + MarkGlueResultsMatcher + CompleteMatchMatcher à       ß v7.0删除

                    MarkGlueResultsMatcher + EmitNodeMatcher + CompleteMatchMatcher

EmitNodeMatcher + CompleteMatchMatcher à MorphNodeToMatcher(在两者的结果都相同时)

CheckTypeMatcher | CheckChildTypeMatcher | RecordMatcher + CheckOpcodeMatcher à

                   CheckOpcodeMatcher + CheckTypeMatcher | CheckChildTypeMatcher | RecordMatcher

3.4.3.3.2. ​​​​​​​下调谓词(v7.0删除

前面生成PatternToMatch实例时,模板谓词(Predicate)都被移到了模板的最上层。因此,在生成的Matcher实例里,CheckPredicateMatcher也是在最前面的,这会妨碍后面的因子提取看到它们。因此SinkPatternPredicates()会尽量将这些CheckPredicateMatcher实例往下移,但不会越过需要判断谓词才执行的Matcher实例。

191     static void SinkPatternPredicates(std::unique_ptr<Matcher> &MatcherPtr) {

192       // Recursively scan for a PatternPredicate.

193       // If we reached the end of the chain, we're done.

194       Matcher *N = MatcherPtr.get();

195       if (!N) return;

196      

197       // Walk down all members of a scope node.

198       if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) {

199         for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {

200           std::unique_ptr<Matcher> Child(Scope->takeChild(i));

201           SinkPatternPredicates(Child);

202           Scope->resetChild(i, Child.release());

203         }

204         return;

205       }

206      

207       // If this node isn't a CheckPatternPredicateMatcher we keep scanning until

208       // we find one.

209       CheckPatternPredicateMatcher *CPPM =dyn_cast<CheckPatternPredicateMatcher>(N);

210       if (!CPPM)

211         return SinkPatternPredicates(N->getNextPtr());

212      

213       // Ok, we found one, lets try to sink it. Check if we can sink it past the

214       // next node in the chain.  If not, we won't be able to change anything and

215       // might as well bail.

216       if (!CPPM->getNext()->isSafeToReorderWithPatternPredicate())

217         return;

218      

219       // Okay, we know we can sink it past at least one node.  Unlink it from the

220       // chain and scan for the new insertion point.

221       MatcherPtr.release();  // Don't delete CPPM.

222       MatcherPtr.reset(CPPM->takeNext());

223      

224       N = MatcherPtr.get();

225       while (N->getNext()->isSafeToReorderWithPatternPredicate())

226         N = N->getNext();

227      

228       // At this point, we want to insert CPPM after N.

229       CPPM->setNext(N->takeNext());

230       N->setNext(CPPM);

231     }

上面216与225行的isSafeToReorderWithPatternPredicate()是虚函数,不同的Matcher派生定义依自己的需要进行改写。它如果返回true,表示可以将PatternPredicate下沉到它之下。

基类Matcher的isSafeToReorderWithPatternPredicate()返回false。

而返回true的派生类有:RecordMatcher,RecordChildMatcher,RecordMemRefMatcher,CaptureGlueInputMatcher,MoveChildMatcher,MoveParentMatcher,CheckSameMatcher,CheckChildSameMatcher,CheckPatternPredicateMatcher,CheckOpcodeMatcher,CheckTypeMatcher,CheckChildTypeMatcher,CheckIntegerMatcher,CheckChildIntegerMatcher,CheckCondCodeMatcher,CheckValueTypeMatcher,CheckAndImmMatcher,CheckOrImmMatcher,CheckFoldableChainNodeMatcher。

返回false的派生类有:CheckComplexPatMatcher,CheckPredicateMatcher,ScopeMatcher,SwitchOpcodeMatcher,SwitchTypeMatcher,以及生成结果代码的Matcher对象(即EmitStringIntegerMatcher,EmitRegisterMatcher,EmitConvertToTargetMatcher,EmitMergeInputChainsMatcher,EmitCopyToRegMatcher,EmitNodeXFormMatcher,EmitNodeMatcher,MorphNodeToMatcher,MarkGlueResultsMatcher,CompleteMatchMatcher)。

3.4.3.3.3. ​​​​​​​提取等价对象

完成了上述的优化后,FactorNodes()将进行公共因子的提取,比如将如下的Matcher树:

   Scope +--> OPC_CheckType i32 --> ABC

               |

               +--> OPC_CheckType i32 --> XYZ

转换为:

   OPC_CheckType i32 --> Scope +--> ABC

                                                       |

                                                       +--> XYZ

ScopeMatcher是单一的Matcher节点,本身不指向下一个Matcher对象,但它有多个子节点,这些子节点都构成一条链(ScopeMatcher类型的子节点除外,它们是子树的根节点)。公共因子从这些子节点链上提取。

在263行,对非ScopeMatcher对象则不做处理,只是对它指向的下一个Matcher对象进行尾递归调用。因此到271行,当前节点就是一个ScopeMatcher对象,对其子节点进行递归调用。这是个深度优先的过程,保证在链最后的ScopeMatcher对象先得到处理,然后经由返回到递归调用点逐步向Matcher树中的前一个ScopeMatcher对象回溯。最后将处理后的子序列保存在OptionsToMatch中(v7.0使用了等价的循环,应该是为了提高代码效率)。

在OptimizeMatcher()调用FactorNodes()时,Matcher序列只有一个ScopeMatcher对象,274行调用的FactorNodes()实际上什么也不做,递归到序列尾返回。因此OptimizeMatcher()调用的FactorNodes()在271行的循环向容器OptionsToMatch插入了开头这个ScopeMatcher对象所有子节点。

256     static void   std::unique_ptr<Matcher> &MatcherPtr) {

257       // If we reached the end of the chain, we're done.

258       Matcher *N = MatcherPtr.get();

259       if (!N) return;

260      

261       // If this is not a push node, just scan for one.

262       ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N);

263       if (!Scope)

264         return FactorNodes(N->getNextPtr());

265      

266       // Okay, pull together the children of the scope node into a vector so we can

267       // inspect it more easily.  While we're at it, bucket them up by the hash

268       // code of their first predicate.

269       SmallVector<Matcher*, 32> OptionsToMatch;

270      

271       for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {

272         // Factor the subexpression.

273         std::unique_ptr<Matcher> Child(Scope->takeChild(i));

274         FactorNodes(Child);

275        

276         if (Matcher *N = Child.release())                                                                        <-- v7.0删除

277           OptionsToMatch.push_back(N);

    if (Child) {                                                                                                                <-- v7.0增加

      // If the child is a ScopeMatcher we can just merge its contents.

      if (auto *SM = dyn_cast<ScopeMatcher>(Child.get())) {

        for (unsigned j = 0, e = SM->getNumChildren(); j != e; ++j)

          OptionsToMatch.push_back(SM->takeChild(j));

      } else {

        OptionsToMatch.push_back(Child.release());

      }

    }

278       }

279      

280       SmallVector<Matcher*, 32> NewOptionsToMatch;

281      

282       // Loop over options to match, merging neighboring patterns with identical

283       // starting nodes into a shared matcher.

284       for (unsigned OptionIdx = 0, e = OptionsToMatch.size(); OptionIdx != e;) {

285         // Find the set of matchers that start with this node.

286         Matcher *Optn = OptionsToMatch[OptionIdx++];

287    

288         if (OptionIdx == e) {

289           NewOptionsToMatch.push_back(Optn);

290           continue;

291         }

292        

293         // See if the next option starts with the same matcher.  If the two

294         // neighbors *do* start with the same matcher, we can factor the matcher out

295         // of at least these two patterns.  See what the maximal set we can merge

296         // together is.

297         SmallVector<Matcher*, 8> EqualMatchers;

298         EqualMatchers.push_back(Optn);

299        

300         // Factor all of the known-equal matchers after this one into the same

301         // group.

302         while (OptionIdx != e && OptionsToMatch[OptionIdx]->isEqual(Optn))

303           EqualMatchers.push_back(OptionsToMatch[OptionIdx++]);

304

305         // If we found a non-equal matcher, see if it is contradictory with the

306         // current node.  If so, we know that the ordering relation between the

307         // current sets of nodes and this node don't matter.  Look past it to see if

308         // we can merge anything else into this matching group.

309         unsigned Scan = OptionIdx;

310         while (1) {

311           // If we ran out of stuff to scan, we're done.

312           if (Scan == e) break;

313          

314           Matcher *ScanMatcher = OptionsToMatch[Scan];

315          

316           // If we found an entry that matches out matcher, merge it into the set to

317           // handle.

318           if (Optn->isEqual(ScanMatcher)) {

319             // If is equal after all, add the option to EqualMatchers and remove it

320             // from OptionsToMatch.

321             EqualMatchers.push_back(ScanMatcher);

322             OptionsToMatch.erase(OptionsToMatch.begin()+Scan);

323             --e;

324             continue;

325           }

326          

327           // If the option we're checking for contradicts the start of the list,

328           // skip over it.

329           if (Optn->isContradictory(ScanMatcher)) {

330             ++Scan;

331             continue;

332           }

333    

334           // If we're scanning for a simple node, see if it occurs later in the

335           // sequence.  If so, and if we can move it up, it might be contradictory

336           // or the same as what we're looking for.  If so, reorder it.

337           if (Optn->isSimplePredicateOrRecordNode()) {

338             Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind());

339             if (M2 && M2 != ScanMatcher &&

340                 M2->canMoveBefore(ScanMatcher) &&

341                 (M2->isEqual(Optn) || M2->isContradictory(Optn))) {

342               Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2);

343               M2->setNext(MatcherWithoutM2);

344               OptionsToMatch[Scan] = M2;

345               continue;

346             }

347           }

348          

349           // Otherwise, we don't know how to handle this entry, we have to bail.

350           break;

351         }

352          

353         if (Scan != e &&

354             // Don't print it's obvious nothing extra could be merged anyway.

355             Scan+1 != e) {

356           DEBUG(errs() << "Couldn't merge this:\n";

357                 Optn->print(errs(), 4);

358                 errs() << "into this:\n";

359                 OptionsToMatch[Scan]->print(errs(), 4);

360                 if (Scan+1 != e)

361                   OptionsToMatch[Scan+1]->printOne(errs());

362                 if (Scan+2 < e)

363                   OptionsToMatch[Scan+2]->printOne(errs());

364                 errs() << "\n");

365         }

366        

367         // If we only found one option starting with this matcher, no factoring is

368         // possible.

369         if (EqualMatchers.size() == 1) {

370           NewOptionsToMatch.push_back(EqualMatchers[0]);

371           continue;

372         }

373        

374         // Factor these checks by pulling the first node off each entry and

375         // discarding it.  Take the first one off the first entry to reuse.

376         Matcher *Shared = Optn;

377         Optn = Optn->takeNext();

378         EqualMatchers[0] = Optn;

379    

380         // Remove and delete the first node from the other matchers we're factoring.

381         for (unsigned i = 1, e = EqualMatchers.size(); i != e; ++i) {

382           Matcher *Tmp = EqualMatchers[i]->takeNext();

383           delete EqualMatchers[i];

384           EqualMatchers[i] = Tmp;

385         }

386        

387         Shared->setNext(new ScopeMatcher(EqualMatchers));

388    

389         // Recursively factor the newly created node.

390         FactorNodes(Shared->getNextPtr());

391        

392         NewOptionsToMatch.push_back(Shared);

393       }

OptionsToMatch的每一项都代表一个等价类(但在一开始每一项代表一条指令,但在后面387与390行处理里,将逐步细化为等价类)。284行开始的循环执行等价类的合并。

首先在302行循环检查OptionsToMatch中紧邻的项是否等价,将等价类合并起来。而存在不等价情形时,310行循环确定这些对象是与当前等价类冲突或等价或者满足337~341行条件的相邻Matcher序列。容器EqualMatchers用于保存与当前处理Matcher对象(Optn)等价的Matcher对象(这里冲突的含义是不会匹配到相同的DAG,这样可以将不同DAG匹配路径里等价的Matcher对象提取出来,让这些匹配过程共享这个Matcher对象。即我们可以将分支推迟到尽可能晚。记住我们是在一个ScopeMatcher的孩子中,这些孩子代表对不同DAG的匹配)。

如果后续Matcher对象都不满足上述条件,它将属于另一个等价类。注意,因为生成Matcher时,PatternToMatch对象是经过排序的,因此等价Matcher对象通常会聚集在一起。等价意味着作用相同,因此在369行以下,如果EqualMatchers中有多个Matcher序列,可以将这些序列中的第一个元素提取出来,构造出一个ScopeMatcher对象,让FactorNodes()递归处理后续的元素。最后将序列的处理结果记录在NewOptionsToMatch容器里,继续284行循环的处理。

用于判定等价关系的Matcher对象的isEqual()方法是一个虚函数。其在基类Matcher的定义是:

105       bool isEqual(const Matcher *M) const {

106         if (getKind() != M->getKind()) return false;

107         return isEqualImpl(M);

108       }

不同类型间的Matcher对象总是不等价的。相同类型的Matcher对象由虚函数isEqualImpl()来判别。其中ScopeMatcher、SwitchOpcodeMatcher、SwitchTypeMatcher不同实例间总是不等价;而RecordMemRefMatcher、CheckFoldableChainNodeMatcher、RecordMatcher、MoveParentMatcher、CaptureGlueInputMatcher不同实例间则总是等价的。

另外,等价的RecordChildMatcher对象必须具有相同的子节点编号(MoveChildMatcher类似):

292       bool isEqualImpl(const Matcher *M) const override {

293         return cast<RecordChildMatcher>(M)->getChildNo() == getChildNo();

294       }

等价的CheckSameMatcher对象必须具有相同的匹配值:

394       bool isEqualImpl(const Matcher *M) const override {

395         return cast<CheckSameMatcher>(M)->getMatchNumber() == getMatchNumber();

396       }

等价的CheckPatternPredicateMatcher对象则具有相同的名称谓词(CheckPredicateMatcher对象与之类似,但要求具有相同的谓词对象):

447       bool isEqualImpl(const Matcher *M) const override {

448         return cast<CheckPatternPredicateMatcher>(M)->getPredicate() == Predicate;

449       }

等价的CheckOpcodeMatcher对象则必须援引相同的SDNode节点(但不一定同一个)。

326     bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const {

327       // Note: pointer equality isn't enough here, we have to check the enum names

328       // to ensure that the nodes are for the same opcode.

329       return cast<CheckOpcodeMatcher>(M)->Opcode.getEnumName() ==

330               Opcode.getEnumName();

331     }

等价的CheckTypeMatcher对象则要求援引相同的类型:

548       bool isEqualImpl(const Matcher *M) const override {

549         return cast<CheckTypeMatcher>(M)->Type == Type;

550       }

等价的CheckChildTypeMatcher对象则同时要求援引相同的类型及相同的子节点:

603       bool isEqualImpl(const Matcher *M) const override {

604         return cast<CheckChildTypeMatcher>(M)->ChildNo == ChildNo &&

605                cast<CheckChildTypeMatcher>(M)->Type == Type;

606       }

等价CheckIntegerMatcher对象要求整数值相同(CheckAndImmMatcher、CheckOrImmMatcher有类似的要求):

630       bool isEqualImpl(const Matcher *M) const override {

631         return cast<CheckIntegerMatcher>(M)->Value == Value;

632       }

等价的CheckCondCodeMatcher对象则要求有相同的条件代码:

683       bool isEqualImpl(const Matcher *M) const override {

684         return cast<CheckCondCodeMatcher>(M)->CondCodeName == CondCodeName;

685       }

等价的CheckValueTypeMatcher对象要求援引相同名称的类型:

707       bool isEqualImpl(const Matcher *M) const override {

708         return cast<CheckValueTypeMatcher>(M)->TypeName == TypeName;

709       }

等价的CheckComplexPatMatcher对象要求具有相同的匹配节点编号:

752       bool isEqualImpl(const Matcher *M) const override {

753         return &cast<CheckComplexPatMatcher>(M)->Pattern == &Pattern &&

754                cast<CheckComplexPatMatcher>(M)->MatchNumber == MatchNumber;

755       }

等价的EmitIntegerMatcher对象要求值和类型都要相同(EmitStringIntegerMatcher有类似要求):

845     ol isEqualImpl(const Matcher *M) const override {

846         return cast<EmitIntegerMatcher>(M)->Val == Val &&

847                cast<EmitIntegerMatcher>(M)->VT == VT;

848       }

等价的EmitRegisterMatcher对象则要求相同的寄存器对象及类型:

896       bool isEqualImpl(const Matcher *M) const override {

897         return cast<EmitRegisterMatcher>(M)->Reg == Reg &&

898                cast<EmitRegisterMatcher>(M)->VT == VT;

899       }

等价的EmitConvertToTargetMatcher要求具有援引相同的对象:

922       bool isEqualImpl(const Matcher *M) const override {

923         return cast<EmitConvertToTargetMatcher>(M)->Slot == Slot;

924       }

等价的EmitMergeInputChainsMatcher对象要求具有相同的输入链:

951       bool isEqualImpl(const Matcher *M) const override {

952         return cast<EmitMergeInputChainsMatcher>(M)->ChainNodes == ChainNodes;

953       }

等价的EmitCopyToRegMatcher对象要求援引相同的源数据与目标寄存器:

976       bool isEqualImpl(const Matcher *M) const override {

977         return cast<EmitCopyToRegMatcher>(M)->SrcSlot == SrcSlot &&

978                cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg;

979       }

等价的EmitNodeXFormMatcher对象要求援引相同的对象及转换方法:

1005    bool isEqualImpl(const Matcher *M) const override {

1006      return cast<EmitNodeXFormMatcher>(M)->Slot == Slot &&

1007             cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm;

1008    }

等价的EmitNodeMatcherCommon对象要在各方面完全一致:

333     bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {

334       const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m);

335       return M->OpcodeName == OpcodeName && M->VTs == VTs &&

336              M->Operands == Operands && M->HasChain == HasChain &&

337              M->HasInGlue == HasInGlue && M->HasOutGlue == HasOutGlue &&

338              M->HasMemRefs == HasMemRefs &&

339              M->NumFixedArityOperands == NumFixedArityOperands;

340     }

等价的MarkGlueResultsMatcher对象要求写相同的标记寄存器(v7.0删除):

1141    bool isEqualImpl(const Matcher *M) const override {

1142      return cast<MarkGlueResultsMatcher>(M)->GlueResultNodes == GlueResultNodes;

1143    }

等价的CompleteMatchMatcher对象要求有相同的结果与模式:

1169    bool isEqualImpl(const Matcher *M) const override {

1170      return cast<CompleteMatchMatcher>(M)->Results == Results &&

1171            &cast<CompleteMatchMatcher>(M)->Pattern == &Pattern;

1172    }

类似的,相违关系则是由另一个虚函数isContradictory()来判定。如果两个Matcher对象不可能匹配到同一个DAG,该方法会返回true。反过来,如果返回false,只是表明不确定是否能匹配到同一个DAG。

168       bool isContradictory(const Matcher *Other) const {

169         // Since this predicate is reflexive, we canonicalize the ordering so that

170         // we always match a node against nodes with kinds that are greater or equal

171         // to them.  For example, we'll pass in a CheckType node as an argument to

172         // the CheckOpcode method, not the other way around.

173         if (getKind() < Other->getKind())

174           return isContradictoryImpl(Other);

175         return Other->isContradictoryImpl(this);

176       }

同样,isContradictoryImpl()是由各个派生类定义的虚函数,基类Matcher提供的版本则总是返回false。定义了isContradictoryImpl()的派生类有这些:

410     bool CheckChildTypeMatcher::isContradictoryImpl(const Matcher *M) const {

411       if (const CheckChildTypeMatcher *CC = dyn_cast<CheckChildTypeMatcher>(M)) {

412         // If the two checks are about different nodes, we don't know if they

413         // conflict!

414         if (CC->getChildNo() != getChildNo())

415           return false;

416    

417       return TypesAreContradictory(getType(), CC->getType());

418       }

419       return false;

420     }

如果这两个CheckChildTypeMatcher对象援引不同的节点,就无法确定这些对象是否不能匹配到同一个节点,因此返回false;否则通过TypesAreContradictory()方法继续检查类型相容性。

362     static bool TypesAreContradictory(MVT::SimpleValueType T1,

363                                       MVT::SimpleValueType T2) {

364       // If the two types are the same, then they are the same, so they don't

365       // contradict.

366       if (T1 == T2) return false;

367    

368       // If either type is about iPtr, then they don't conflict unless the other

369       // one is not a scalar integer type.

370       if (T1 == MVT::iPTR)

371         return !MVT(T2).isInteger() || MVT(T2).isVector();

372    

373       if (T2 == MVT::iPTR)

374         return !MVT(T1).isInteger() || MVT(T1).isVector();

375    

376       // Otherwise, they are two different non-iPTR types, they conflict.

377       return true;

378     }

如果类型不相兼容,就可断定不能匹配到同一个节点。

对CheckOpcodeMatcher而言,如果操作码不同,两个CheckOpcodeMatcher就不能匹配到同一节点(正好是isEqualImpl()的相反条件)。另外,它也可能与一个CheckTypeMatcher不起冲突。前提是这两个Matcher实例的类型是兼容的。

380     bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const {

381       if (const CheckOpcodeMatcher *COM = dyn_cast<CheckOpcodeMatcher>(M)) {

382         // One node can't have two different opcodes!

383         // Note: pointer equality isn't enough here, we have to check the enum names

384         // to ensure that the nodes are for the same opcode.

385         return COM->getOpcode().getEnumName() != getOpcode().getEnumName();

386       }

387    

388       // If the node has a known type, and if the type we're checking for is

389       // different, then we know they contradict.  For example, a check for

390       // ISD::STORE will never be true at the same time a check for Type i32 is.

391       if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M)) {

392         // If checking for a result the opcode doesn't have, it can't match.

393         if (CT->getResNo() >= getOpcode().getNumResults())

394           return true;

395    

396         MVT::SimpleValueType NodeType = getOpcode().getKnownType(CT->getResNo());

397         if (NodeType != MVT::Other)

398           return TypesAreContradictory(NodeType, CT->getType());

399       }

400    

401       return false;

402     }

兼容的CheckOpcodeMatcher与CheckTypeMatcher正好给出了进入FactorNode() 337行的一个例子。在337行的isSimplePredicateOrRecordNode()方法检查下列条件:

147       bool isSimplePredicateOrRecordNode() const {

148         return isSimplePredicateNode() ||

149                getKind() == RecordNode || getKind() == RecordChild;

150       }

满足isSimplePredicateNode()方法的Matcher对象有:

124       bool isSimplePredicateNode() const {

125         switch (getKind()) {

126         default: return false;

127         case CheckSame:

128         case CheckChildSame:

129         case CheckPatternPredicate:

130         case CheckPredicate:

131         case CheckOpcode:

132         case CheckType:

133         case CheckChildType:

134         case CheckInteger:

135         case CheckChildInteger:

136         case CheckCondCode:

137         case CheckValueType:

138         case CheckAndImm:

139         case CheckOrImm:

140         case CheckFoldableChainNode:

141           return true;

142         }

143       }

CheckOpcodeMatcher与CheckTypeMatcher都满足isSimplePredicateNode()方法。接下来338行的FindNodeWithKind()查找ScanMatcher后续Matcher对象中第一个与Optn类型相同的对象,如果这个对象可以移到ScanMatcher前面,就交换它们(M2存在与Optn等价的可能性),并由310行循环重新处理。

55       bool Matcher::canMoveBefore(const Matcher *Other) const {

56         for (;; Other = Other->getNext()) {

57           assert(Other && "Other didn't come before 'this'?");

58           if (this == Other) return true;

59      

60           // We have to be able to move this node across the Other node.

61           if (!canMoveBeforeNode(Other))

62             return false;

63         }

64       }

在上面的方法中,this必须在Other后面。而只有满足下列条件,this才能移到Other前。

68       bool Matcher::canMoveBeforeNode(const Matcher *Other) const {

69         // We can move simple predicates before record nodes.

70         if (isSimplePredicateNode())

71           return Other->isSimplePredicateOrRecordNode();

72      

73         // We can move record nodes across simple predicates.

74         if (isSimplePredicateOrRecordNode())

75           return isSimplePredicateNode();

76      

77         // We can't move record nodes across each other etc.

78         return false;

79       }

不过反过来CheckTypeMatcher的isContradictoryImpl()并没有考虑CheckOpcodeMatcher,这是因为CheckTypeMatcher的类型标识值要小于CheckOpcodeMatcher,Matcher::isContradictory()保证不会对CheckOpcodeMatcher调用CheckTypeMatcher的isContradictoryImpl()方法。

404     bool CheckTypeMatcher::isContradictoryImpl(const Matcher *M) const {

405       if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M))

406       return TypesAreContradictory(getType(), CT->getType());

407       return false;

408     }

至于CheckIntegerMatcher对象,只要援引的值不一样,就是不兼容的(与isEqualImpl()相反)。

422     bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const {

423       if (const CheckIntegerMatcher *CIM = dyn_cast<CheckIntegerMatcher>(M))

424         return CIM->getValue() != getValue();

425       return false;

426     }

同样对于CheckValueTypeMatcher对象,只要援引的类型的名称不同,就不可能兼容(与isEqualImpl()相反)。

440     bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const {

441       if (const CheckValueTypeMatcher *CVT = dyn_cast<CheckValueTypeMatcher>(M))

442         return CVT->getTypeName() != getTypeName();

443       return false;

444     }

回到FactorNodes()。现在处理后的Matcher序列保存在容器NewOptionsToMatch中。接着,415行的分支检查指定的Matcher链是否以CheckOpcodeMatcher开始。427行分支接着检查该Matcher链中最靠近的CheckTypeMatcher对象是否能移到Matcher序列的前面。如果所有的Matcher子序列都是CheckOpcodeMatcher对象可以使用一个SwitchOpcodeMatcher对象封装它们。而如果都是CheckTypeMatcher对象,且避开了431~439行条件C,它们可以一个SwitchTypeMatcher对象或CheckTypeMatcher对象代替(只存在CheckTypeMatcher多个相同的实例)。

在467行分支,容器TypeEntry用来记录这些CheckTypeMatcher对象所进行的检查类型,如果不存在相同的CheckTypeMatcher对象,在Cases容器里记录检查类型与去掉这个CheckTypeMatcher对象后的Matcher链(494行)。如果存在相同的CheckTypeMatcher对象,满足479行条件。如果前一个相同的CheckTypeMatcher对象所在链的当前对象不是ScopeMatcher,创建一个ScopeMatcher对象,以前一个Matcher链及当前Matcher链(都去掉相关CheckTypeMatcher对象)作为孩子。而如果前一个相同的CheckTypeMatcher对象所在链的当前对象是ScopeMatcher,它必定是前一个情形创建的,只需把当前的Matcher链添加为这个ScopeMatcher对象的新孩子即可。进而在501行,一个新的等效的CheckTypeMatcher对象被添加到这个ScopeMatcher对象的前面。

FactorNodes(续)

395       // If we're down to a single pattern to match, then we don't need this scope

396       // anymore.

397       if (NewOptionsToMatch.size() == 1) {

398         MatcherPtr.reset(NewOptionsToMatch[0]);

399         return;

400       }

401      

402       if (NewOptionsToMatch.empty()) {

403         MatcherPtr.reset();

404         return;

405       }

406      

407       // If our factoring failed (didn't achieve anything) see if we can simplify in

408       // other ways.

409      

410       // Check to see if all of the leading entries are now opcode checks.  If so,

411       // we can convert this Scope to be a OpcodeSwitch instead.

412       bool AllOpcodeChecks = true, AllTypeChecks = true;

413       for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {

414         // Check to see if this breaks a series of CheckOpcodeMatchers.

415         if (AllOpcodeChecks &&

416               !isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) {

417     #if 0

418           if (i > 3) {

419             errs() << "FAILING OPC #" << i << "\n";

420             NewOptionsToMatch[i]->dump();

421           }

422     #endif

423           AllOpcodeChecks = false;

424         }

425    

426         // Check to see if this breaks a series of CheckTypeMatcher's.

427         if (AllTypeChecks) {

428           CheckTypeMatcher *CTM =

429             cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],

430                                                             Matcher::CheckType));

431           if (!CTM ||

432               // iPTR checks could alias any other case without us knowing, don't

433               // bother with them.

434               CTM->getType() == MVT::iPTR ||

435               // SwitchType only works for result #0.

436               CTM->getResNo() != 0 ||

437               // If the CheckType isn't at the start of the list, see if we can move

438               // it there.

439               !CTM->canMoveBefore(NewOptionsToMatch[i])) {

440     #if 0

441             if (i > 3 && AllTypeChecks) {

442               errs() << "FAILING TYPE #" << i << "\n";

443               NewOptionsToMatch[i]->dump();

444             }

445     #endif

446             AllTypeChecks = false;

447           }

448         }

449       }

450      

451       // If all the options are CheckOpcode's, we can form the SwitchOpcode, woot.

452       if (AllOpcodeChecks) {

453         StringSet<> Opcodes;

454      SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;

455         for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {

456           CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]);

457           assert(Opcodes.insert(COM->getOpcode().getEnumName()).second &&

458                  "Duplicate opcodes not factored?");

459           Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext()));

460         }

461        

462         MatcherPtr.reset(new SwitchOpcodeMatcher(Cases));

463         return;

464       }

465      

466       // If all the options are CheckType's, we can form the SwitchType, woot.

467       if (AllTypeChecks) {

468         DenseMap<unsigned, unsigned> TypeEntry;

469         SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;

470         for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {

471           CheckTypeMatcher *CTM =

472             cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],

473                                                             Matcher::CheckType));

474           Matcher *MatcherWithoutCTM = NewOptionsToMatch[i]->unlinkNode(CTM);

475           MVT::SimpleValueType CTMTy = CTM->getType();

476           delete CTM;

477          

478           unsigned &Entry = TypeEntry[CTMTy];

479           if (Entry != 0) {

480             // If we have unfactored duplicate types, then we should factor them.

481             Matcher *PrevMatcher = Cases[Entry-1].second;

482             if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) {

483              SM->setNumChildren(SM->getNumChildren()+1);

484               SM->resetChild(SM->getNumChildren()-1, MatcherWithoutCTM);

485               continue;

486             }

487            

488             Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM };

489             Cases[Entry-1].second = new ScopeMatcher(Entries);

490             continue;

491           }

492          

493           Entry = Cases.size()+1;

494           Cases.push_back(std::make_pair(CTMTy, MatcherWithoutCTM));

495         }

 

    // Make sure we recursively factor any scopes we may have created.

    for (auto &M : Cases) {                                                                                        ß v7.0增加

      if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M.second)) {

        std::unique_ptr<Matcher> Scope(SM);

        FactorNodes(Scope);

        M.second = Scope.release();

        assert(M.second && "null matcher");

      }

    }

496        

497         if (Cases.size() != 1) {

498           MatcherPtr.reset(new SwitchTypeMatcher(Cases));

499         } else {

500           // If we factored and ended up with one case, create it now.

501           MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first, 0));

502           MatcherPtr->setNext(Cases[0].second);

503         }

504         return;

505       }

506      

507    

508       // Reassemble the Scope node with the adjusted children.

509       Scope->setNumChildren(NewOptionsToMatch.size());

510       for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i)

511         Scope->resetChild(i, NewOptionsToMatch[i]);

512     }

如果上述两种情形都不存在,那么只能将NewOptionsToMatch(即新的等价对象)替换为原来ScopeMatcher对象的孩子(509行以下)。注意V7.0会对新创建的ScopeMatcher进行一次递归提取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值