LLVM学习笔记(25)

3.4.3.2. 从PatternToMatch到Matcher

3.4.3.2.1. MatcherGen对象

完成了排序后,接着在151行遍历这些排好序的PatternToMatch对象,为它们生成Matcher对象(实际上是一系列DAGISelMatcher派生类)。

DAGISelEmitter::run(续)

149       // Convert each variant of each pattern into a Matcher.

150       std::vector<Matcher*> PatternMatchers;

151       for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {

152         for (unsigned Variant = 0; ; ++Variant) {

153           if (Matcher *M = ConvertPatternToMatcher(*Patterns[i], Variant, CGP))

154             PatternMatchers.push_back(M);

155           else

156             break;

157         }

158       }

151行的外层遍历使用的排序PatternToMatch对象,152行的内层则无限循环,直到153行的ConvertPatternToMatcher()返回0为止(即遍历完匹配模式中ComplexPattern对象的RootNodes)。这是通过参数Variant每次加1传入ConvertPatternToMatcher()来遍历RootNodes实现的。

1003  Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern,

1004                                         unsigned Variant,

1005                                         const CodeGenDAGPatterns &CGP) {

1006    MatcherGen Gen(Pattern, CGP);

1007 

1008    // Generate the code for the matcher.

1009    if (Gen.EmitMatcherCode(Variant))

1010      return nullptr;

1011 

1012    // FIXME2: Kill extra MoveParent commands at the end of the matcher sequence.

1013    // FIXME2: Split result code out to another table, and make the matcher end

1014    // with an "Emit <index>" command.  This allows result generation stuff to be

1015    // shared and factored?

1016 

1017    // If the match succeeds, then we generate Pattern.

1018    Gen.EmitResultCode();

1019 

1020    // Unconditional match.

1021    return Gen.GetMatcher();

1022  }

Matcher实例由MatcherGen对象辅助产生,因此先在1006行如下构造MatcherGen实例。注意,是每个PatternToMatch对象分配一个实例。因此MatcherGen的变量NextRecordedOperandNo及容器VariableMap、MatchedChainNodes、MatchedGlueResultNodes、MatchedComplexPatterns、PhysRegInputs都有专用的PatternToMatch对象。

152     MatcherGen::MatcherGen(const PatternToMatch &pattern,

153                            const CodeGenDAGPatterns &cgp)

154     : Pattern(pattern), CGP(cgp), NextRecordedOperandNo(0),

155       TheMatcher(nullptr), CurPredicate(nullptr) {

156       // We need to produce the matcher tree for the patterns source pattern.  To do

157       // this we need to match the structure as well as the types.  To do the type

158       // matching, we want to figure out the fewest number of type checks we need to

159       // emit.  For example, if there is only one integer type supported by a

160       // target, there should be no type comparisons at all for integer patterns!

161       //

162       // To figure out the fewest number of type checks needed, clone the pattern,

163       // remove the types, then perform type inference on the pattern as a whole.

164       // If there are unresolved types, emit an explicit check for those types,

165       // apply the type to the tree, then rerun type inference.  Iterate until all

166       // types are resolved.

167       //

168       PatWithNoTypes = Pattern.getSrcPattern()->clone();

169       PatWithNoTypes->RemoveAllTypes();

170    

171       // If there are types that are manifestly known, infer them.

172       InferPossibleTypes(Pattern.ForceMode);                                               <-- v7.0增加参数

173     }

156行开始的注释谈到,匹配结构时类型也要匹配,但希望尽可能少地进行类型检查。为了找出最少的类型检查数,首先克隆源模板,以下面的方法删除所有的类型。

1317  void TreePatternNode::RemoveAllTypes() {

1318    for (unsigned i = 0, e = Types.size(); i != e; ++i)

1319      Types[i] = EEVT::TypeSet();  // Reset to unknown type.                   <-- v7.0删除

  std::fill(Types.begin(), Types.end(), TypeSetByHwMode());               <-- v7.0增加

1320    if (isLeaf()) return;

1321    for (unsigned i = 0, e = getNumChildren(); i != e; ++i)

1322      getChild(i)->RemoveAllTypes();

1323  }

因为在1319行将所有的类型都设置为未知,那么下面的ApplyTypeConstraints(),在其内部调用的UpdateNodeType(),进而MergeInTypeInfo()时会直接利用目标系统给出的类型。当然,这个过程不保证所有的类型都能确定,因此上面的注释谈到类型未知的节点才需要生成类型检查代码。

179     void MatcherGen::InferPossibleTypes(unsigned ForceMode) {          <-- v7.0增加

180       // TP - Get *SOME* tree pattern, we don't care which.  It is only used for

181       // diagnostics, which we know are impossible at this point.

182       TreePattern &TP = *CGP.pf_begin()->second;

  TP.getInfer().CodeGen = true;                                                                 <-- v7.0增加

  TP.getInfer().ForceMode = ForceMode;

183    

184       bool MadeChange = true;

185       while (MadeChange)

186         MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP,

187                                                   true/*Ignore reg constraints*/);

188     }

v7.0中,MatcherGen::InferPossibleTypes()的参数ForceMode来自PatternToMatch实例的ForceMode成员,用于表明该匹配适用的硬件模式。设置了这个域后,将影响在186行调用的ApplyTypeConstraints()的行为(细节参考前面章节)。

3.4.3.2.2. ​​​​​​​生成匹配代码的Matcher对象

MatcherGen::EmitMatcherCode()方法生成一系列Matcher对象。这些对象将用于生成匹配输入模式的代码。所有Matcher对象都通过自身的Next域链接在一起。AddMatcher()提供了相应的接口。

192     void MatcherGen::AddMatcher(Matcher *NewNode) {

193       if (CurPredicate)

194         CurPredicate->setNext(NewNode);

195       else

196         TheMatcher = NewNode;

197       CurPredicate = NewNode;

198     }

其中,MatcherGen的TheMatcher指向最顶层的Matcher对象,CurPredicate则指向最后生成的Matcher对象。

502     bool MatcherGen::EmitMatcherCode(unsigned Variant) {

503       // If the root of the pattern is a ComplexPattern and if it is specified to

504       // match some number of root opcodes, these are considered to be our variants.

505       // Depending on which variant we're generating code for, emit the root opcode

506       // check.

507       if (const ComplexPattern *CP =

508                        Pattern.getSrcPattern()->getComplexPatternInfo(CGP)) {

509         const std::vector<Record*> &OpNodes = CP->getRootNodes();

510         assert(!OpNodes.empty() &&"Complex Pattern must specify what it can match");

511         if (Variant >= OpNodes.size()) return true;

512    

513         AddMatcher(new CheckOpcodeMatcher(CGP.getSDNodeInfo(OpNodes[Variant])));

514       } else {

515         if (Variant != 0) return true;

516       }

517    

518       // Emit the matcher for the pattern structure and types.

519       EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes, Pattern.ForceMode);  <-- v7.0增加

在508行,方法getComplexPatternInfo()获取匹配模板中的ComplexPattern定义(如果没有,返回null)。ComplexPattern定义可以指定一个RootNodes列表,这是它的SelectFunc要匹配的节点。因此,在513行为这些节点分别生成一个CheckOpcodeMatcher对象(匹配OpCode的Matcher),参数Variant来自DAGISelEmitter::run() 152行的循环变量,用于顺序遍历ComplexPattern操作数,一旦穷尽就返回true(这表示Variant是无效的),进而ConvertPatternToMatcher()返回0,最后在DAGISelEmitter::run() 156行跳出152行循环。对于非ComplexPattern,Variant有效值只能是0。

ComplexPattern定义之外,对匹配模式的结构与类型进行匹配的Matcher对象由下面的方法产生。其中参数NodeNoTypes是参数N的去除类型版本。472行遍历两者的类型,将不一致的类型记录在容器ResultsToTypeCheck里,用于稍后生成类型匹配的Matcher实例。

465     void MatcherGen::EmitMatchCode(const TreePatternNode *N,

466                                    TreePatternNode *NodeNoTypes,

                                           unsigned ForceMode) {                                             <-- v7.0增加

467       // If N and NodeNoTypes don't agree on a type, then this is a case where we

468       // need to do a type check.  Emit the check, apply the type to NodeNoTypes and

469       // reinfer any correlated types.

470       SmallVector<unsigned, 2> ResultsToTypeCheck;

471    

472       for (unsigned i = 0, e = NodeNoTypes->getNumTypes(); i != e; ++i) {

473         if (NodeNoTypes->getExtType(i) == N->getExtType(i)) continue;

474         NodeNoTypes->setType(i, N->getExtType(i));

475         InferPossibleTypes(ForceMode);                                                        <-- v7.0增加

476         ResultsToTypeCheck.push_back(i);

477       }

478    

479       // If this node has a name associated with it, capture it in VariableMap. If

480       // we already saw this in the pattern, emit code to verify dagness.

481       if (!N->getName().empty())

482         if (!recordUniqueNode(N->getName()))

483           return;

484    

485       if (N->isLeaf())

486         EmitLeafMatchCode(N);

487       else

488       EmitOperatorMatchCode(N, NodeNoTypes, ForceMode);             <-- v7.0增加

489    

490       // If there are node predicates for this node, generate their checks.

491     for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)

492         AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i]));

493    

494       for (unsigned i = 0, e = ResultsToTypeCheck.size(); i != e; ++i)

495         AddMatcher(new CheckTypeMatcher(N->getType(ResultsToTypeCheck[i]),

496                                         ResultsToTypeCheck[i]));

497     }

如果节点是具名的,我们需要生成对这个具名节点进行名字检查的Matcher。

448     bool MatcherGen::recordUniqueNode(std::string Name) {

449       unsigned &VarMapEntry = VariableMap[Name];

450       if (VarMapEntry == 0) {

451         // If it is a named node, we must emit a 'Record' opcode.

452         AddMatcher(new RecordMatcher("$" + Name, NextRecordedOperandNo));

453         VarMapEntry = ++NextRecordedOperandNo;

454         return true;

455       }

456    

457       // If we get here, this is a second reference to a specific name.  Since

458       // we already have checked that the first reference is valid, we don't

459       // have to recursively match it, just check that it's the same as the

460       // previously named thing.

461       AddMatcher(new CheckSameMatcher(VarMapEntry-1));

462       return false;

463     }

在这里VariableMap是MatcherGen的StringMap<unsigned>类型容器,NextRecordedOperandNo用作SelectionDAGISel::SelectCodeCommon()函数里临时容器RecordedNodes里的序号,在指令选择时将会用选则产生SDValue节点填充这个容器,这些节点的序号就是NextRecordedOperandNo的对应值。这些是可能会用于选中指令的节点。

对第一次出现的具名节点,要生成一个RecordMatcher对象,在指令选择时将会记录对应的SDNode对象。如果是再次出现,就需要一个CheckSameMatcher对象来检查同名的RecordMatcher对象是否一致。注意449行的VarMapEntry是一个引用,对第一次出现的具名节点,它所记录的序号实际上比真实序号大1,这是为了方便450行的判定(因为0序号是不使用的)。

除了recordUniqueNode()里会生成RecordMatcher,还有这样几处:ComplexPattern定义(它也是具名的,也是通过recordUniqueNode()生成),Register定义,带有chain节点或glue节点的TreePatternNode。它们对应的SDNode对象有可能作为选择结果的操作数,

如果是叶子节点,生成其匹配代码的Matcher对象由下面的方法来产生。注意,dag不会产生模式树的叶子节点。

206     void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {

207       assert(N->isLeaf() && "Not a leaf?");

208    

209       // Direct match against an integer constant.

210       if (IntInit *II = dyn_cast<IntInit>(N->getLeafValue())) {

211         // If this is the root of the dag we're matching, we emit a redundant opcode

212         // check to ensure that this gets folded into the normal top-level

213         // OpcodeSwitch.

214         if (N == Pattern.getSrcPattern()) {

215           const SDNodeInfo &NI = CGP.getSDNodeInfo(CGP.getSDNodeNamed("imm"));

216           AddMatcher(new CheckOpcodeMatcher(NI));

217         }

218    

219         return AddMatcher(new CheckIntegerMatcher(II->getValue()));

220       }

221    

222       // An UnsetInit represents a named node without any constraints.

223       if (isa<UnsetInit>(N->getLeafValue())) {

224         assert(N->hasName() && "Unnamed ? leaf");

225         return;

226       }

227    

228       DefInit *DI = dyn_cast<DefInit>(N->getLeafValue());

229       if (!DI) {

230         errs() << "Unknown leaf kind: " << *N << "\n";

231         abort();

232       }

233    

234       Record *LeafRec = DI->getDef();

235    

236       // A ValueType leaf node can represent a register when named, or itself when

237       // unnamed.

238       if (LeafRec->isSubClassOf("ValueType")) {

239         // A named ValueType leaf always matches: (add i32:$a, i32:$b).

240         if (N->hasName())

241           return;

242         // An unnamed ValueType as in (sext_inreg GPR:$foo, i8).

243         return AddMatcher(new CheckValueTypeMatcher(LeafRec->getName()));

244       }

245    

246       if (// Handle register references.  Nothing to do here, they always match.

247           LeafRec->isSubClassOf("RegisterClass") ||

248           LeafRec->isSubClassOf("RegisterOperand") ||

249           LeafRec->isSubClassOf("PointerLikeRegClass") ||

250           LeafRec->isSubClassOf("SubRegIndex") ||

251           // Place holder for SRCVALUE nodes. Nothing to do here.

252           LeafRec->getName() == "srcvalue")

253         return;

254    

255       // If we have a physreg reference like (mul gpr:$src, EAX) then we need to

256       // record the register

257       if (LeafRec->isSubClassOf("Register")) {

258         AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName(),

259                                      NextRecordedOperandNo));

260         PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++));

261         return;

262       }

263    

264       if (LeafRec->isSubClassOf("CondCode"))

265         return AddMatcher(new CheckCondCodeMatcher(LeafRec->getName()));

266    

267       if (LeafRec->isSubClassOf("ComplexPattern")) {

268         // We can't model ComplexPattern uses that don't have their name taken yet.

269         // The OPC_CheckComplexPattern operation implicitly records the results.

270         if (N->getName().empty()) {

271           std::string S;

272           raw_string_ostream OS(S);

273         OS << "We expect complex pattern uses to have names: " << *N;

274           PrintFatalError(OS.str());

275         }

276    

277         // Remember this ComplexPattern so that we can emit it after all the other

278         // structural matches are done.

279         unsigned InputOperand = VariableMap[N->getName()] - 1;

280         MatchedComplexPatterns.push_back(std::make_pair(N, InputOperand));

281         return;

282       }

283    

284       errs() << "Unknown leaf kind: " << *N << "\n";

285       abort();

286     }

前面解析匹配模式时,我们看到能作为其叶子节点的类型无外乎:IntInit(整数,包括BitsInit)、UnsetInit(未初始化整数)、DefInit(任意Record定义)。对IntInit而言,如果它是唯一需要匹配的对象,我们需要确定它是(imm val)中的操作数(CheckOpcodeMatcher对象)。

至于Definit,需要区分这些情形:

  • ValueType:需要检查操作数是否具有指定类型(CheckValueTypeMatcher对象)。
  • Register:在这个阶段,通常只需要指定寄存器类,让寄存器分配器来分配适用的寄存器(因此这里无需特别处理RegisterClass,RegisterOperand,PointerLikeRegClass与SubRegIndex)。如果特别指定了物理寄存器,就需要一个RecordMatcher实例,并把相关的参数(Record对象及Matcher对象的序号)保存入寄存器专用容器PhysRegInputs里。
  • CondCode:需要生成判断条件代码(CheckCondCodeMatcher对象)。
  • ComplexPattern:RecordMatcher实例已经由recordUniqueNode()生成,容器 MatchedComplexPatterns保存了它的信息用于稍后统一创建Matcher对象。

如果是非叶子节点,我们知道它的操作符可以是ComplexPattern,SDNode(在这里源模板不能是set,也不会是只能出现在输入、输出操作数描述里的out、in、ops)。293行的注释提到了非叶子节点ComplexPattern的处理,这个节点连同其操作数合为一个RecordMatcher实例(叶子节点的ComplexPattern则不如是,下面我们会看到)。

288     void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,

289                                            TreePatternNode *NodeNoTypes,

                                                   unsigned ForceMode) {                                                    <-- v7.0增加

290       assert(!N->isLeaf() && "Not an operator?");

291    

292       if (N->getOperator()->isSubClassOf("ComplexPattern")) {

293         // The "name" of a non-leaf complex pattern (MY_PAT $op1, $op2) is

294         // "MY_PAT:op1:op2". We should already have validated that the uses are

295         // consistent.

296       std::string PatternName = N->getOperator()->getName();

297         for (unsigned i = 0; i < N->getNumChildren(); ++i) {

298           PatternName += ":";

299           PatternName += N->getChild(i)->getName();

300         }

301    

302         if (recordUniqueNode(PatternName)) {

303           auto NodeAndOpNum = std::make_pair(N, NextRecordedOperandNo - 1);

304           MatchedComplexPatterns.push_back(NodeAndOpNum);

305         }

306    

307         return;

308       }

309    

310       const SDNodeInfo &CInfo = CGP.getSDNodeInfo(N->getOperator());

311    

312       // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is

313       // a constant without a predicate fn that has more that one bit set, handle

314       // this as a special case.  This is usually for targets that have special

315       // handling of certain large constants (e.g. alpha with it's 8/16/32-bit

316       // handling stuff).  Using these instructions is often far more efficient

317       // than materializing the constant.  Unfortunately, both the instcombiner

318       // and the dag combiner can often infer that bits are dead, and thus drop

319       // them from the mask in the dag.  For example, it might turn 'AND X, 255'

320       // into 'AND X, 254' if it knows the low bit is set.  Emit code that checks

321       // to handle this.

322       if ((N->getOperator()->getName() == "and" ||

323            N->getOperator()->getName() == "or") &&

324           N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty() &&

325           N->getPredicateFns().empty()) {

326         if (IntInit *II = dyn_cast<IntInit>(N->getChild(1)->getLeafValue())) {

327           if (!isPowerOf2_32(II->getValue())) {  // Don't bother with single bits.

328             // If this is at the root of the pattern, we emit a redundant

329             // CheckOpcode so that the following checks get factored properly under

330             // a single opcode check.

331             if (N == Pattern.getSrcPattern())

332               AddMatcher(new CheckOpcodeMatcher(CInfo));

333    

334             // Emit the CheckAndImm/CheckOrImm node.

335             if (N->getOperator()->getName() == "and")

336               AddMatcher(new CheckAndImmMatcher(II->getValue()));

337             else

338               AddMatcher(new CheckOrImmMatcher(II->getValue()));

339    

340             // Match the LHS of the AND as appropriate.

341             AddMatcher(new MoveChildMatcher(0));

342             EmitMatchCode(N->getChild(0), NodeNoTypes->getChild(0), ForceMode);         <-- v7.0增加

343             AddMatcher(new MoveParentMatcher());

344             return;

345           }

346         }

347       }

348    

349       // Check that the current opcode lines up.

350       AddMatcher(new CheckOpcodeMatcher(CInfo));

351    

352     // If this node has memory references (i.e. is a load or store), tell the

353       // interpreter to capture them in the memref array.

354       if (N->NodeHasProperty(SDNPMemOperand, CGP))

355         AddMatcher(new RecordMemRefMatcher());

356    

357       // If this node has a chain, then the chain is operand #0 is the SDNode, and

358       // the child numbers of the node are all offset by one.

359       unsigned OpNo = 0;

360       if (N->NodeHasProperty(SDNPHasChain, CGP)) {

361         // Record the node and remember it in our chained nodes list.

362         AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +

363                                              "' chained node",

364                                      NextRecordedOperandNo));

365         // Remember all of the input chains our pattern will match.

366         MatchedChainNodes.push_back(NextRecordedOperandNo++);

367    

368         // Don't look at the input chain when matching the tree pattern to the

369         // SDNode.

370         OpNo = 1;

371    

372         // If this node is not the root and the subtree underneath it produces a

373         // chain, then the result of matching the node is also produce a chain.

374         // Beyond that, this means that we're also folding (at least) the root node

375         // into the node that produce the chain (for example, matching

376         // "(add reg, (load ptr))" as a add_with_memory on X86).  This is

377         // problematic, if the 'reg' node also uses the load (say, its chain).

378         // Graphically:

379         //

380         //         [LD]

381         //           ^  ^

382         //           |    \                              DAG's like cheese.

383         //          /      |

384         //        /     [YY]

385         //       |        ^

386         //      [XX]--/

387         //

388         // It would be invalid to fold XX and LD.  In this case, folding the two

389         // nodes together would induce a cycle in the DAG, making it a 'cyclic DAG'

390         // To prevent this, we emit a dynamic check for legality before allowing

391         // this to be folded.

392         //

393         const TreePatternNode *Root = Pattern.getSrcPattern();

394         if (N != Root) {                             // Not the root of the pattern.

395           // If there is a node between the root and this node, then we definitely

396           // need to emit the check.

397           bool NeedCheck = !Root->hasChild(N);

398    

399           // If it *is* an immediate child of the root, we can still need a check if

400           // the root SDNode has multiple inputs.  For us, this means that it is an

401           // intrinsic, has multiple operands, or has other inputs like chain or

402           // glue).

403           if (!NeedCheck) {

404             const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Root->getOperator());

405             NeedCheck =

406               Root->getOperator() == CGP.get_intrinsic_void_sdnode() ||

407               Root->getOperator() == CGP.get_intrinsic_w_chain_sdnode() ||

408               Root->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||

409               PInfo.getNumOperands() > 1 ||

410               PInfo.hasProperty(SDNPHasChain) ||

411               PInfo.hasProperty(SDNPInGlue) ||

412               PInfo.hasProperty(SDNPOptInGlue);

413           }

414    

415           if (NeedCheck)

416             AddMatcher(new CheckFoldableChainNodeMatcher());

417         }

418       }

419    

420       // If this node has an output glue and isn't the root, remember it.

421       if (N->NodeHasProperty(SDNPOutGlue, CGP) &&

422           N != Pattern.getSrcPattern()) {

423         // TODO: This redundantly records nodes with both glues and chains.

424    

425         // Record the node and remember it in our chained nodes list.

426         AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +

427                                              "' glue output node",

428                                      NextRecordedOperandNo));

429         // Remember all of the nodes with output glue our pattern will match.              <-- v7.0删除

430         MatchedGlueResultNodes.push_back(NextRecordedOperandNo++);

431       }

432    

433       // If this node is known to have an input glue or if it *might* have an input

434       // glue, capture it as the glue input of the pattern.

435       if (N->NodeHasProperty(SDNPOptInGlue, CGP) ||

436           N->NodeHasProperty(SDNPInGlue, CGP))

437         AddMatcher(new CaptureGlueInputMatcher());

438    

439       for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {

440         // Get the code suitable for matching this child.  Move to the child, check

441         // it then move back to the parent.

442         AddMatcher(new MoveChildMatcher(OpNo));

443         EmitMatchCode(N->getChild(i), NodeNoTypes->getChild(i), ForceMode);         ß v7.0增加

444         AddMatcher(new MoveParentMatcher());

445       }

446     }

312行提到了一个特殊的情况,即操作符是and或or,右手侧操作数是多个比特位是1的常量,且没有伴随的谓词,在这种情况下,目标机器通常有更高效的专用指令。注释里提到指令合并器与dag合并器会进行一些优化,比如“AND X, 255”,如果X的最低位为0(注释称为1,但似乎应该为0),它们将被优化为“AND X, 254”(这条指令可能更短),为此生成CheckAndImmMatcher或CheckOrImmMatcher来匹配这种情形。

这里的要匹配节点都是所谓的SelectionDAG节点。SelectionDAG包含两种类型的值:表示数据流的,以及表示控制流依赖性的。数据值是具有一个整数或浮点值类型的简单边。控制边被表示作“链(chain)”边,类型是MVT::Other。这些边在具有副作用的节点间(比如load,store,call,return等)提供了一个次序。所有具有副作用的节点接受一个符号链作为输入,并产生一个新的符号链作为输出。按照惯例,符号链输入总是操作数0,而一个操作产生的最后的值总是链结果(如果没有glue节点的话)。

360~418行处理具有链的节点。372行的注释谈到一点,就是一个模式里所有具有链的节点都可能会依据链的顺序折叠起来,这就需要避免380~386行所给出的DAG的形式,TableGen产生一个CheckFoldableChainNodeMatcher对象用于生成在指令选择时对这种情况进行检查的代码。

421行的SDNPOutGlue属性,表示该操作会写标记寄存器。435行的SDNPOptInGlue属性与436行的SDNPInGlue属性分别表示可能及确定读标记寄存器。因此,在指令调度时,属性为SDNPOutGlue的节点会与属性为SDNPInGlue的后续节点一起调度,中间不会插入别的节点。

另外,注意在439行循环里,在进入子节点生成Matcher对象之前与之后,需要分别产生一个特殊的对象MoveChildMatcher与MoveParentMatcher来表示作用域的切换。它们将产生在在指令选择时进出子SDNode节点的代码。

在MatcherGen::EmitMatchCode()的最后,为谓词及需要检查的类型生成Matcher对象(在472行的循环我们把这些类型缓存起来了)。

MatcherGen::EmitMatcherCode(续)

521       // If the pattern has a predicate on it (e.g. only enabled when a subtarget

522       // feature is around, do the check).

523       if (!Pattern.getPredicateCheck().empty())

524         AddMatcher(new CheckPatternPredicateMatcher(Pattern.getPredicateCheck()));

525    

526       // Now that we've completed the structural type match, emit any ComplexPattern

527       // checks (e.g. addrmode matches).  We emit this after the structural match

528       // because they are generally more expensive to evaluate and more difficult to

529       // factor.

530       for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) {

531         const TreePatternNode *N = MatchedComplexPatterns[i].first;

532    

533         // Remember where the results of this match get stuck.

534         if (N->isLeaf()) {

535           NamedComplexPatternOperands[N->getName()] = NextRecordedOperandNo + 1;

536         } else {

537           unsigned CurOp = NextRecordedOperandNo;

538           for (unsigned i = 0; i < N->getNumChildren(); ++i) {

539             NamedComplexPatternOperands[N->getChild(i)->getName()] = CurOp + 1;

540             CurOp += N->getChild(i)->getNumMIResults(CGP);

541           }

542         }

543    

544         // Get the slot we recorded the value in from the name on the node.

545         unsigned RecNodeEntry = MatchedComplexPatterns[i].second;

546    

547         const ComplexPattern &CP = *N->getComplexPatternInfo(CGP);

548    

549         // Emit a CheckComplexPat operation, which does the match (aborting if it

550         // fails) and pushes the matched operands onto the recorded nodes list.

551         AddMatcher(new CheckComplexPatMatcher(CP, RecNodeEntry,

552                                               N->getName(), NextRecordedOperandNo));

553    

554         // Record the right number of operands.

555         NextRecordedOperandNo += CP.getNumOperands();

556         if (CP.hasProperty(SDNPHasChain)) {

557           // If the complex pattern has a chain, then we need to keep track of the

558           // fact that we just recorded a chain input.  The chain input will be

559           // matched as the last operand of the predicate if it was successful.

560           ++NextRecordedOperandNo; // Chained node operand.

561    

562           // It is the last operand recorded.

563           assert(NextRecordedOperandNo > 1 &&

564                  "Should have recorded input/result chains at least!");

565           MatchedChainNodes.push_back(NextRecordedOperandNo-1);

566         }

567    

568         // TODO: Complex patterns can't have output glues, if they did, we'd want

569         // to record them.

570       }

571    

572       return false;

573     }

524行的getPredicateCheck()方法获取模式中包含的谓词方法的名字与参数CondString的字符串。

843     std::string PatternToMatch::getPredicateCheck() const {

844       std::string PredicateCheck;

845       for (Init *I : Predicates->getValues()) {

846         if (DefInit *Pred = dyn_cast<DefInit>(I)) {

847           Record *Def = Pred->getDef();

848           if (!Def->isSubClassOf("Predicate")) {

849     #ifndef NDEBUG

850             Def->dump();

851     #endif

852             llvm_unreachable("Unknown predicate type!");

853           }

854           if (!PredicateCheck.empty())

855             PredicateCheck += " && ";

856           PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";

857         }

858       }

859    

860       return PredicateCheck;

861     }

V7.0的版本如下:

1312  std::string PatternToMatch::getPredicateCheck() const {

1313    SmallVector<const Predicate*,4> PredList;

1314    for (const Predicate &P : Predicates)

1315      PredList.push_back(&P);

1316    llvm::sort(PredList.begin(), PredList.end(), deref<llvm::less>());

1317 

1318    std::string Check;

1319    for (unsigned i = 0, e = PredList.size(); i != e; ++i) {

1320      if (i != 0)

1321        Check += " && ";

1322      Check += '(' + PredList[i]->getCondString() + ')';

1323    }

1324    return Check;

1325  }

为了更高效地生成谓词代码,v7.0首先对Predicate进行排序,因此在Predicate里引入了“<”操作符。其中ifCondbool类型成员,Featuresstd::string类型成员。

999       bool operator<(const Predicate &P) const {

1000      if (IsHwMode != P.IsHwMode)

1001        return IsHwMode < P.IsHwMode;

1002      assert(!Def == !P.Def && "Inconsistency between Def and IsHwMode");

1003      if (IfCond != P.IfCond)

1004        return IfCond < P.IfCond;

1005      if (Def)

1006        return LessRecord()(Def, P.Def);

1007      return Features < P.Features;

1008    }

在原来PatternToMatch::getPredicateCheck()进行的检查,移到了上面1002行(更严格)。

前面将模式中所有ComplexPattern定义的信息保存在MatchedComplexPatterns容器里,现在可以为这些ComplexPattern对象生成CheckComplexPatMatcher实例了。NextRecordedOperandNo要计入ComplexPattern对象的结果个数。如果ComplexPattern对象有子节点,还要计入子节点里的ComplexPattern对象的结果个数。因为结果代码需要在这些位置输出结果值。因为ComplexPattern是具名的,因此535行的NamedComplexPatternOperands容器(StringMap<unsigned>类型)记录下相关SDValue对象在RecordedNodes里的索引。这将用于后面生成具名操作数的Matcher对象时(参见EmitResultOfNamedOperand())。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值