LLVM学习笔记(34)

3.5. 指令信息的生成

选项-gen-instr-info使得TableGen根据TD文件的描述,生成目标机器的指令描述代码。比如,前面指令选择成功时生成的MachineSDNode的操作码就是在这一步生成的。

3.5.1. CodeGenSchedModels对象

一如既往,TableGen对这个选项的入口函数看起来很简单。参数RK就是保存了所有class与def定义的Record实例的容器。

608     void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {

609       InstrInfoEmitter(RK).run(OS);

610       EmitMapTable(RK, OS);

611     }

609行的InstrInfoEmitter是用于生成相关代码的外覆类,它的构造函数定义如下:

38         InstrInfoEmitter(RecordKeeper &R):

39           Records(R), CDP(R), SchedModels(CDP.getTargetInfo().getSchedModels()) {}

CDP是一个CodeGenDAGPatterns实例,因此CDP(R)所引发的一系列处理正是前面一节所看过的过程,即从指令定义生成指令的DAG,但不涉及指令选择代码的生成。

InstrInfoEmitter的成员SchedModels是CodeGenSchedModels类型的引用,这个类定义了以下的数据成员。它用作目标机器模型数据的顶层容器的封装类。所有从.td文件里相关定义解析出来的对象都将保存在相应的容器中。其他协作类将使用这些对象在容器里的索引进行工作。

219     class CodeGenSchedModels {

220       RecordKeeper &Records;

221       const CodeGenTarget &Target;

222    

223       // Map dag expressions to Instruction lists.

224       SetTheory Sets;

225    

226       // List of unique processor models.

227       std::vector<CodeGenProcModel> ProcModels;

228    

229       // Map Processor's MachineModel or ProcItin to a CodeGenProcModel index.

230       typedef DenseMap<Record*, unsigned> ProcModelMapTy;

231       ProcModelMapTy ProcModelMap;

232    

233       // Per-operand SchedReadWrite types.

234       std::vector<CodeGenSchedRW> SchedWrites;

235       std::vector<CodeGenSchedRW> SchedReads;

236    

237       // List of unique SchedClasses.

238       std::vector<CodeGenSchedClass> SchedClasses;

239    

240       // Any inferred SchedClass has an index greater than NumInstrSchedClassses.

241       unsigned NumInstrSchedClasses;

  RecVec ProcResourceDefs;                                                                                                  <- v7.0增加

  RecVec ProcResGroups;

242    

243       // Map each instruction to its unique SchedClass index considering the

244       // combination of it's itinerary class, SchedRW list, and InstRW records.

245       typedef DenseMap<Record*, unsigned> InstClassMapTy;

246       InstClassMapTy InstrClassMap;

CodeGenTarget::getSchedModels()调用CodeGenSchedModels构造函数创建CodeGenSchedModels对象,参数RK也就是EmitInstrInfo()的参数RK。

88           CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,

89                                              const CodeGenTarget &TGT):

90         Records(RK), Target(TGT) {

91      

92         Sets.addFieldExpander("InstRW", "Instrs");

93      

94         // Allow Set evaluation to recognize the dags used in InstRW records:

95         // (instrs Op1, Op1...)

96         Sets.addOperator("instrs", llvm::make_unique<InstrsOp>());

97         Sets.addOperator("instregex", llvm::make_unique<InstRegexOp>(Target));

98      

99         // Instantiate a CodeGenProcModel for each SchedMachineModel with the values

100       // that are explicitly referenced in tablegen records. Resources associated

101       // with each processor will be derived later. Populate ProcModelMap with the

102       // CodeGenProcModel instances.

103       collectProcModels();

104    

105       // Instantiate a CodeGenSchedRW for each SchedReadWrite record explicitly

106       // defined, and populate SchedReads and SchedWrites vectors. Implicit

107       // SchedReadWrites that represent sequences derived from expanded variant will

108       // be inferred later.

109       collectSchedRW();

110    

111       // Instantiate a CodeGenSchedClass for each unique SchedRW signature directly

112       // required by an instruction definition, and populate SchedClassIdxMap. Set

113       // NumItineraryClasses to the number of explicit itinerary classes referenced

114       // by instructions. Set NumInstrSchedClasses to the number of itinerary

115       // classes plus any classes implied by instructions that derive from class

116       // Sched and provide SchedRW list. This does not infer any new classes from

117       // SchedVariant.

118       collectSchedClasses();

119    

120       // Find instruction itineraries for each processor. Sort and populate

121       // CodeGenProcModel::ItinDefList. (Cycle-to-cycle itineraries). This requires

122       // all itinerary classes to be discovered.

123       collectProcItins();

124    

125     // Find ItinRW records for each processor and itinerary class.

126       // (For per-operand resources mapped to itinerary classes).

127       collectProcItinRW();

 

  // Find UnsupportedFeatures records for each processor.                                                <- v7.0增加

  // (For per-operand resources mapped to itinerary classes).

  collectProcUnsupportedFeatures();

128    

129       // Infer new SchedClasses from SchedVariant.

130       inferSchedClasses();

131    

132       // Populate each CodeGenProcModel's WriteResDefs, ReadAdvanceDefs, and

133       // ProcResourceDefs.

134       collectProcResources();

  // Collect optional processor description.                                                                             <- v7.0增加

  collectOptionalProcessorInfo();

  checkCompleteness();

135     }

首先,InstRW具有一个dag的成员Instrs,这是需要特别处理的。其次,还有两个特殊的dag操作符需要注意。一个是instrs,表示它的操作数应该解释为指令定义。另一个是instregex,表示它的操作数是用于匹配指令操作码名字的正则模式。

​​​​​​​3.5.1.1. SchedMachineModel定义

CodeGenSchedModels构造函数首先处理SchedMachineModel定义。前面看到对Atom这样依赖Itinerary来描述指令执行的处理器,从SchedMachineModel派生的定义是这个描述最重要的部分(v7.0里,Atom已经不用Itinerary来描述了)。而对SandyBridge这样通过资源占用来描述指令执行的处理器,SchedMachineModel派生定义则通常给出处理器的全局信息。处理器在自己的Processor定义中指出所需的SchedMachineModel。因此,通过Processor定义找出所有使用的SchedMachineModel是很自然的的方式。140行首先通过方法LessRecordFieldName()以字母序对所有的Processor定义排序。

138     void CodeGenSchedModels::collectProcModels() {

139       RecVec ProcRecords = Records.getAllDerivedDefinitions("Processor");

140       std::sort(ProcRecords.begin(), ProcRecords.end(), LessRecordFieldName());

141    

142       // Reserve space because we can. Reallocation would be ok.

143       ProcModels.reserve(ProcRecords.size()+1);

144    

145       // Use idx=0 for NoModel/NoItineraries.

146       Record *NoModelDef = Records.getDef("NoSchedModel");

147       Record *NoItinsDef = Records.getDef("NoItineraries");

148       ProcModels.emplace_back(0, "NoSchedModel", NoModelDef, NoItinsDef);

149       ProcModelMap[NoModelDef] = 0;

150    

151       // For each processor, find a unique machine model.

152       for (unsigned i = 0, N = ProcRecords.size(); i < N; ++i)

153         addProcModel(ProcRecords[i]);

154     }

CodeGenSchedModels容器ProcModels的类型是std::vector<CodeGenProcModel>。其中的类型CodeGenProcModel用于描述处理器的调度模型,它近似于TD文件的SchedMachineModel定义,有如下的数据成员与构造函数。其中175行的Index是该CodeGenProcModel实例在ProcModels容器中的索引。

174     struct CodeGenProcModel {

175       unsigned Index;

176       std::string ModelName;

177       Record *ModelDef;

178       Record *ItinsDef;

179    

180       // Derived members...

181    

182       // Array of InstrItinData records indexed by a CodeGenSchedClass index.

183       // This list is empty if the Processor has no value for Itineraries.

184       // Initialized by collectProcItins().

185       RecVec ItinDefList;

186    

187       // Map itinerary classes to per-operand resources.

188       // This list is empty if no ItinRW refers to this Processor.

189       RecVec ItinRWDefs;

  // List of unsupported feature.                                                                                               <- v7.0增加

  // This list is empty if the Processor has no UnsupportedFeatures.

  RecVec UnsupportedFeaturesDefs;

190    

191       // All read/write resources associated with this processor.

192       RecVec WriteResDefs;

193       RecVec ReadAdvanceDefs;

194    

195       // Per-operand machine model resources associated with this processor.

196       RecVec ProcResourceDefs;

197       RecVec ProcResGroupDefs;

  // List of Register Files.                                                                                                             <- v7.0增加

  std::vector<CodeGenRegisterFile> RegisterFiles;

 

  // Optional Retire Control Unit definition.

  Record *RetireControlUnit;

 

  // List of PfmCounters.

  RecVec PfmIssueCounterDefs;

  Record *PfmCycleCounterDef = nullptr;

198    

199       CodeGenProcModel(unsigned Idx, const std::string &Name, Record *MDef,

200                        Record *IDef) :

201         Index(Idx), ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {}

collectProcModels() 149行的ProcModelMap是DenseMap<Record*, unsigned>的typedef,用于将CodeGenProcModel对象在ProcModels容器的序号与对应调度模型的Record对象关联起来。第一个调度模型是缺省模型,它的地位相当于空指针。

这些CodeGenSchedModels实例由CodeGenSchedModels::addProcModel()方法来获取。

158   void CodeGenSchedModels::addProcModel(Record *ProcDef) {

159       Record *ModelKey = getModelOrItinDef(ProcDef);

160       if (!ProcModelMap.insert(std::make_pair(ModelKey, ProcModels.size())).second)

161         return;

162    

163       std::string Name = ModelKey->getName();

164       if (ModelKey->isSubClassOf("SchedMachineModel")) {

165         Record *ItinsDef = ModelKey->getValueAsDef("Itineraries");

166         ProcModels.emplace_back(ProcModels.size(), Name, ModelKey, ItinsDef);

167       }

168       else {

169         // An itinerary is defined without a machine model. Infer a new model.

170         if (!ModelKey->getValueAsListOfDefs("IID").empty())

171           Name = Name + "Model";

172         ProcModels.emplace_back(ProcModels.size(), Name,

173                                 ProcDef->getValueAsDef("SchedModel"), ModelKey);

174       }

175       DEBUG(ProcModels.back().dump());

176     }

方法getModelOrItinDef()返回以下数据:Processor->SchedModel(类型SchedMachineModel)以及Processor->ProcItin(类型ProcessorItineraries)->IID(类型list<InstrItinData>)。

273       Record *getModelOrItinDef(Record *ProcDef) const {

274         Record *ModelDef = ProcDef->getValueAsDef("SchedModel");

275         Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");

276         if (!ItinsDef->getValueAsListOfDefs("IID").empty()) {

277           assert(ModelDef->getValueAsBit("NoModel")

278                  && "Itineraries must be defined within SchedMachineModel");

279           return ItinsDef;

280         }

281         return ModelDef;

282       }

从getModelOrItinDef()定义可以看出,如果同时出现,后者的优先程度高于前者。它们可生成这些CodeGenProcModel对象:(ModelDef: Processor->SchedModel, ItinsDef: Processor->SchedModel-> Itineraries),(ModelDef: Processor->ProcItin->IID, ItinsDef: Processor->ProcItin)。

245       CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef,

246                        Record *IDef) :

247         Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),

248         RetireControlUnit(nullptr) {}

其中Itineraries与Procltin的类型都是ProcessorItineraries的定义(ItinsDef)。

​​​​​​​3.5.1.2. SchedReadWrite的处理

接下来由CodeGenSchedModels::collectSchedRW()方法为TD文件中的SchedReadWrite定义生成CodeGenSchedRW对象。TD文件中SchedReadWrite有复杂的派生体系与来源,需要一个一个处理。v7.0里比较大的改动是用getInstructionsByEnumValue()替代了instructions()方法,前者将以操作码的大小序返回指令的CodeGenInstruction实例。

204     void CodeGenSchedModels::collectSchedRW() {

205       // Reserve idx=0 for invalid writes/reads.

206       SchedWrites.resize(1);

207       SchedReads.resize(1);

208    

209       SmallPtrSet<Record*, 16> RWSet;

210    

211       // Find all SchedReadWrites referenced by instruction defs.

212       RecVec SWDefs, SRDefs;

213       for (const CodeGenInstruction *Inst : Target.instructions()) {                                        <- v7.0删除

  for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {                       <- v7.0增加

214         Record *SchedDef = Inst->TheDef;

215         if (SchedDef->isValueUnset("SchedRW"))

216           continue;

217         RecVec RWs = SchedDef->getValueAsListOfDefs("SchedRW");

218         for (RecIter RWI = RWs.begin(), RWE = RWs.end(); RWI != RWE; ++RWI) {

219           if ((*RWI)->isSubClassOf("SchedWrite"))

220             scanSchedRW(*RWI, SWDefs, RWSet);

221           else {

222             assert((*RWI)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");

223             scanSchedRW(*RWI, SRDefs, RWSet);

224           }

225         }

226       }

227       // Find all ReadWrites referenced by InstRW.

228       RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");

229     for (RecIter OI = InstRWDefs.begin(), OE = InstRWDefs.end(); OI != OE; ++OI) {

230         // For all OperandReadWrites.

231         RecVec RWDefs = (*OI)->getValueAsListOfDefs("OperandReadWrites");

232         for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end();

233              RWI != RWE; ++RWI) {

234           if ((*RWI)->isSubClassOf("SchedWrite"))

235             scanSchedRW(*RWI, SWDefs, RWSet);

236           else {

237             assert((*RWI)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");

238             scanSchedRW(*RWI, SRDefs, RWSet);

239           }

240         }

241       }

242       // Find all ReadWrites referenced by ItinRW.

243       RecVec ItinRWDefs = Records.getAllDerivedDefinitions("ItinRW");

244       for (RecIter II = ItinRWDefs.begin(), IE = ItinRWDefs.end(); II != IE; ++II) {

245         // For all OperandReadWrites.

246         RecVec RWDefs = (*II)->getValueAsListOfDefs("OperandReadWrites");

247         for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end();

248              RWI != RWE; ++RWI) {

249           if ((*RWI)->isSubClassOf("SchedWrite"))

250             scanSchedRW(*RWI, SWDefs, RWSet);

251           else {

252             assert((*RWI)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");

253             scanSchedRW(*RWI, SRDefs, RWSet);

254           }

255         }

256       }

257       // Find all ReadWrites referenced by SchedAlias. AliasDefs needs to be sorted

258       // for the loop below that initializes Alias vectors.

259       RecVec AliasDefs = Records.getAllDerivedDefinitions("SchedAlias");

260       std::sort(AliasDefs.begin(), AliasDefs.end(), LessRecord());

261       for (RecIter AI = AliasDefs.begin(), AE = AliasDefs.end(); AI != AE; ++AI) {

262         Record *MatchDef = (*AI)->getValueAsDef("MatchRW");

263         Record *AliasDef = (*AI)->getValueAsDef("AliasRW");

264         if (MatchDef->isSubClassOf("SchedWrite")) {

265           if (!AliasDef->isSubClassOf("SchedWrite"))

266             PrintFatalError((*AI)->getLoc(), "SchedWrite Alias must be SchedWrite");

267           scanSchedRW(AliasDef, SWDefs, RWSet);

268         }

269         else {

270           assert(MatchDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");

271           if (!AliasDef->isSubClassOf("SchedRead"))

272             PrintFatalError((*AI)->getLoc(), "SchedRead Alias must be SchedRead");

273           scanSchedRW(AliasDef, SRDefs, RWSet);

274         }

275       }

276       // Sort and add the SchedReadWrites directly referenced by instructions or

277       // itinerary resources. Index reads and writes in separate domains.

278       std::sort(SWDefs.begin(), SWDefs.end(), LessRecord());

279       for (RecIter SWI = SWDefs.begin(), SWE = SWDefs.end(); SWI != SWE; ++SWI) {

280         assert(!getSchedRWIdx(*SWI, /*IsRead=*/false) && "duplicate SchedWrite");

281         SchedWrites.emplace_back(SchedWrites.size(), *SWI);

282       }

283       std::sort(SRDefs.begin(), SRDefs.end(), LessRecord());

284       for (RecIter SRI = SRDefs.begin(), SRE = SRDefs.end(); SRI != SRE; ++SRI) {

285         assert(!getSchedRWIdx(*SRI, /*IsRead-*/true) && "duplicate SchedWrite");

286         SchedReads.emplace_back(SchedReads.size(), *SRI);

287       }

288       // Initialize WriteSequence vectors.

289       for (std::vector<CodeGenSchedRW>::iterator WI = SchedWrites.begin(),

290              WE = SchedWrites.end(); WI != WE; ++WI) {

291         if (!WI->IsSequence)

292           continue;

293         findRWs(WI->TheDef->getValueAsListOfDefs("Writes"), WI->Sequence,

294                 /*IsRead=*/false);

295       }

296       // Initialize Aliases vectors.

297       for (RecIter AI = AliasDefs.begin(), AE = AliasDefs.end(); AI != AE; ++AI) {

298         Record *AliasDef = (*AI)->getValueAsDef("AliasRW");

299         getSchedRW(AliasDef).IsAlias = true;

300         Record *MatchDef = (*AI)->getValueAsDef("MatchRW");

301         CodeGenSchedRW &RW = getSchedRW(MatchDef);

302         if (RW.IsAlias)

303           PrintFatalError((*AI)->getLoc(), "Cannot Alias an Alias");

304         RW.Aliases.push_back(*AI);

305       }

306       DEBUG(

307         for (unsigned WIdx = 0, WEnd = SchedWrites.size(); WIdx != WEnd; ++WIdx) {

308           dbgs() << WIdx << ": ";

309           SchedWrites[WIdx].dump();

310           dbgs() << '\n';

311         }

312         for (unsigned RIdx = 0, REnd = SchedReads.size(); RIdx != REnd; ++RIdx) {

313           dbgs() << RIdx << ": ";

314           SchedReads[RIdx].dump();

315           dbgs() << '\n';

316         }

317         RecVec RWDefs = Records.getAllDerivedDefinitions("SchedReadWrite");

318         for (RecIter RI = RWDefs.begin(), RE = RWDefs.end();

319              RI != RE; ++RI) {

320           if (!getSchedRWIdx(*RI, (*RI)->isSubClassOf("SchedRead"))) {

321             const std::string &Name = (*RI)->getName();

322             if (Name != "NoWrite" && Name != "ReadDefault")

323               dbgs() << "Unused SchedReadWrite " << (*RI)->getName() << '\n';

324           }

325         });

326     }

SchedReadWrite各派生类型所对应的对象都是CodeGenSchedRW实例,它是这样的一个定义:

46       struct CodeGenSchedRW {

47         unsigned Index;

48         std::string Name;

49         Record *TheDef;

50         bool IsRead;

51         bool IsAlias;

52         bool HasVariants;

53         bool IsVariadic;

54         bool IsSequence;

55         IdxVec Sequence;

56         RecVec Aliases;

57      

58         CodeGenSchedRW()

59           : Index(0), TheDef(nullptr), IsRead(false), IsAlias(false),

60             HasVariants(false), IsVariadic(false), IsSequence(false) {}

61         CodeGenSchedRW(unsigned Idx, Record *Def)

62           : Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) {

63           Name = Def->getName();

64           IsRead = Def->isSubClassOf("SchedRead");

65           HasVariants = Def->isSubClassOf("SchedVariant");

66           if (HasVariants)

67             IsVariadic = Def->getValueAsBit("Variadic");

68      

69           // Read records don't currently have sequences, but it can be easily

70           // added. Note that implicit Reads (from ReadVariant) may have a Sequence

71           // (but no record).

72           IsSequence = Def->isSubClassOf("WriteSequence");

73         }

74      

75         CodeGenSchedRW(unsigned Idx, bool Read, const IdxVec &Seq,

76                        const std::string &Name)

77          : Index(Idx), Name(Name), TheDef(nullptr), IsRead(Read), IsAlias(false),

78             HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) {

79           assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");

80         }

81      

82         bool isValid() const {

83           assert((!HasVariants || TheDef) && "Variant write needs record def");

84           assert((!IsVariadic || HasVariants) && "Variadic write needs variants");

85           assert((!IsSequence || !HasVariants) && "Sequence can't have variant");

86           assert((!IsSequence || !Sequence.empty()) && "Sequence should be nonempty");

87           assert((!IsAlias || Aliases.empty()) && "Alias cannot have aliases");

88           return TheDef || !Sequence.empty();

89         }

90      

91       #ifndef NDEBUG

92         void dump() const;

93       #endif

94       };

其中类型IdxVec是std::vector<unsigned>的typdef,类型RecVec是std::vector<Record*>的typedef。

CodeGenSchedModels的容器SchedWrites与SchedReads用于保存CodeGenSchedRW对象,47行的成员Index是CodeGenSchedRW对象在这些容器里的索引。

collectSchedRW()首先调用scanSchedRW()方法将SchedRead或SchedWrites定义记录在临时容器RWSet里。SchedRead或SchedWrites用在以下各处:Instruction->SchedRW,SchedAlias->AliasRW,InstRW->OperandReadWrites,以及ItinRW->OperandReadWrites。

179     static void scanSchedRW(Record *RWDef, RecVec &RWDefs,

180                             SmallPtrSet<Record*, 16> &RWSet) {

181       if (!RWSet.insert(RWDef).second)

182         return;

183       RWDefs.push_back(RWDef);

184       // Reads don't current have sequence records, but it can be added later.

185       if (RWDef->isSubClassOf("WriteSequence")) {

186         RecVec Seq = RWDef->getValueAsListOfDefs("Writes");

187         for (RecIter I = Seq.begin(), E = Seq.end(); I != E; ++I)

188           scanSchedRW(*I, RWDefs, RWSet);

189       }

190       else if (RWDef->isSubClassOf("SchedVariant")) {

191         // Visit each variant (guarded by a different predicate).

192       RecVec Vars = RWDef->getValueAsListOfDefs("Variants");

193         for (RecIter VI = Vars.begin(), VE = Vars.end(); VI != VE; ++VI) {

194           // Visit each RW in the sequence selected by the current variant.

195           RecVec Selected = (*VI)->getValueAsListOfDefs("Selected");

196           for (RecIter I = Selected.begin(), E = Selected.end(); I != E; ++I)

197             scanSchedRW(*I, RWDefs, RWSet);

198         }

199       }

200     }

因为WriteSequence与SchedVariant还包含list<SchedWrite>类型的成员(即Writes与Variants),这些SchedWrite定义也需要包括进来。临时容器SWDefs保存的是这些SchedWrite定义的Record对象。类似的,SchedRead定义的Record对象则记录在SRDefs中。

在获得所有使用的SchedRead与SchedWrite定义后,在collectSchedRW()的278与283行将这些Record对象按名字排序。然后在279与284行循环对这些的Record对象构建对应的CodeGenSchedRW对象,并保存在SchedWrites与SchedReads容器中。

只有从WriteSequence定义产生的CodeGenSchedRW对象的IsSequence是true,它援引一组重复指定次数的SchedWrite定义。我们需要知道这些SchedWrite定义对应的CodeGenSchedRW对象。这里通过CodeGenSchedModels::findRWs()方法将这些CodeGenSchedRW对象在容器中的索引记录在这些WriteSequence的CodeGenSchedRW对象的Sequence容器里。

392   void CodeGenSchedModels::findRWs(const RecVec &RWDefs, IdxVec &RWs,

393                                      bool IsRead) const {

394       for (RecIter RI = RWDefs.begin(), RE = RWDefs.end(); RI != RE; ++RI) {

395         unsigned Idx = getSchedRWIdx(*RI, IsRead);

396         assert(Idx && "failed to collect SchedReadWrite");

397         RWs.push_back(Idx);

398       }

399     }

getSchedRWIdx()的参数After缺省为0,指定SchedReads或SchedWrites容器开始查找的位置。它返回参数Def对应的CodeGenSchedRW对象在SchedReads或SchedWrites容器中的索引。

340     unsigned CodeGenSchedModels::getSchedRWIdx(Record *Def, bool IsRead,

341                                                unsigned After) const {

342       const std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;

343       assert(After < RWVec.size() && "start position out of bounds");

344       for (std::vector<CodeGenSchedRW>::const_iterator I = RWVec.begin() + After,

345              E = RWVec.end(); I != E; ++I) {

346         if (I->TheDef == Def)

347           return I - RWVec.begin();

348       }

349       return 0;

350     }

V7.0版本的CodeGenSchedModels::getSchedRWIdx()得到了比较大的简化,而且不再从指定位置开始搜索:

458     unsigned CodeGenSchedModels::getSchedRWIdx(const Record *Def,

459                                                bool IsRead) const {

460       const std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;

461       const auto I = find_if(

462           RWVec, [Def](const CodeGenSchedRW &RW) { return RW.TheDef == Def; });

463       return I == RWVec.end() ? 0 : std::distance(RWVec.begin(), I);

464     }

SchedAlias使用AliasRW记录MatchRW的别名(参见SchedAlias的定义),因此从MatchRW构建的CodeGenSchedRW对象的Aliases容器将记录下AliasRW的CodeGenSchedRW对象(297行循环)。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值