llvm.org GIT mirror llvm / dcbac18
[TableGen] Use range-based for loops. NFC git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@260809 91177308-0d34-0410-b5e6-96231b3b80d8 Craig Topper 4 years ago
2 changed file(s) with 107 addition(s) and 132 deletion(s). Raw diff Collapse all Expand all
299299 typedef std::vector::const_iterator ProcIter;
300300 ProcIter procModelBegin() const { return ProcModels.begin(); }
301301 ProcIter procModelEnd() const { return ProcModels.end(); }
302 ArrayRef procModels() const { return ProcModels; }
302303
303304 // Return true if any processors have itineraries.
304305 bool hasItineraries() const;
352353 typedef std::vector::const_iterator SchedClassIter;
353354 SchedClassIter schedClassBegin() const { return SchedClasses.begin(); }
354355 SchedClassIter schedClassEnd() const { return SchedClasses.end(); }
356 ArrayRef schedClasses() const { return SchedClasses; }
355357
356358 unsigned numInstrSchedClasses() const { return NumInstrSchedClasses; }
357359
356356 SmallPtrSet ItinsDefSet;
357357
358358 // Emit functional units for all the itineraries.
359 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
360 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
361
362 if (!ItinsDefSet.insert(PI->ItinsDef).second)
359 for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
360
361 if (!ItinsDefSet.insert(ProcModel.ItinsDef).second)
363362 continue;
364363
365 std::vector FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
364 std::vector FUs = ProcModel.ItinsDef->getValueAsListOfDefs("FU");
366365 if (FUs.empty())
367366 continue;
368367
369 const std::string &Name = PI->ItinsDef->getName();
368 const std::string &Name = ProcModel.ItinsDef->getName();
370369 OS << "\n// Functional units for \"" << Name << "\"\n"
371370 << "namespace " << Name << "FU {\n";
372371
376375
377376 OS << "}\n";
378377
379 std::vector BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
378 std::vector BPs = ProcModel.ItinsDef->getValueAsListOfDefs("BP");
380379 if (!BPs.empty()) {
381380 OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
382381 << "\"\n" << "namespace " << Name << "Bypass {\n";
410409 // object with computed offsets to the ProcItinLists result.
411410 unsigned StageCount = 1, OperandCycleCount = 1;
412411 std::map ItinStageMap, ItinOperandMap;
413 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
414 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
415 const CodeGenProcModel &ProcModel = *PI;
416
412 for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
417413 // Add process itinerary to the list.
418414 ProcItinLists.resize(ProcItinLists.size()+1);
419415
611607 int BufferSize = PRDef->getValueAsInt("BufferSize");
612608 if (PRDef->isSubClassOf("ProcResGroup")) {
613609 RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources");
614 for (RecIter RUI = ResUnits.begin(), RUE = ResUnits.end();
615 RUI != RUE; ++RUI) {
616 NumUnits += (*RUI)->getValueAsInt("NumUnits");
610 for (Record *RU : ResUnits) {
611 NumUnits += RU->getValueAsInt("NumUnits");
617612 }
618613 }
619614 else {
651646 return SchedWrite.TheDef;
652647
653648 Record *AliasDef = nullptr;
654 for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
655 AI != AE; ++AI) {
649 for (Record *A : SchedWrite.Aliases) {
656650 const CodeGenSchedRW &AliasRW =
657 SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
651 SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
658652 if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
659653 Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
660654 if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
671665
672666 // Check this processor's list of write resources.
673667 Record *ResDef = nullptr;
674 for (RecIter WRI = ProcModel.WriteResDefs.begin(),
675 WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
676 if (!(*WRI)->isSubClassOf("WriteRes"))
668 for (Record *WR : ProcModel.WriteResDefs) {
669 if (!WR->isSubClassOf("WriteRes"))
677670 continue;
678 if (AliasDef == (*WRI)->getValueAsDef("WriteType")
679 || SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) {
671 if (AliasDef == WR->getValueAsDef("WriteType")
672 || SchedWrite.TheDef == WR->getValueAsDef("WriteType")) {
680673 if (ResDef) {
681 PrintFatalError((*WRI)->getLoc(), "Resources are defined for both "
674 PrintFatalError(WR->getLoc(), "Resources are defined for both "
682675 "SchedWrite and its alias on processor " +
683676 ProcModel.ModelName);
684677 }
685 ResDef = *WRI;
678 ResDef = WR;
686679 }
687680 }
688681 // TODO: If ProcModel has a base model (previous generation processor),
705698
706699 // Check this processor's list of aliases for SchedRead.
707700 Record *AliasDef = nullptr;
708 for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end();
709 AI != AE; ++AI) {
701 for (Record *A : SchedRead.Aliases) {
710702 const CodeGenSchedRW &AliasRW =
711 SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
703 SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
712704 if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
713705 Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
714706 if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
725717
726718 // Check this processor's ReadAdvanceList.
727719 Record *ResDef = nullptr;
728 for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
729 RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
730 if (!(*RAI)->isSubClassOf("ReadAdvance"))
720 for (Record *RA : ProcModel.ReadAdvanceDefs) {
721 if (!RA->isSubClassOf("ReadAdvance"))
731722 continue;
732 if (AliasDef == (*RAI)->getValueAsDef("ReadType")
733 || SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) {
723 if (AliasDef == RA->getValueAsDef("ReadType")
724 || SchedRead.TheDef == RA->getValueAsDef("ReadType")) {
734725 if (ResDef) {
735 PrintFatalError((*RAI)->getLoc(), "Resources are defined for both "
726 PrintFatalError(RA->getLoc(), "Resources are defined for both "
736727 "SchedRead and its alias on processor " +
737728 ProcModel.ModelName);
738729 }
739 ResDef = *RAI;
730 ResDef = RA;
740731 }
741732 }
742733 // TODO: If ProcModel has a base model (previous generation processor),
778769 SubDef = SuperDef;
779770 }
780771 }
781 for (RecIter PRI = PM.ProcResourceDefs.begin(),
782 PRE = PM.ProcResourceDefs.end();
783 PRI != PRE; ++PRI) {
784 if (*PRI == PRDef || !(*PRI)->isSubClassOf("ProcResGroup"))
772 for (Record *PR : PM.ProcResourceDefs) {
773 if (PR == PRDef || !PR->isSubClassOf("ProcResGroup"))
785774 continue;
786 RecVec SuperResources = (*PRI)->getValueAsListOfDefs("Resources");
775 RecVec SuperResources = PR->getValueAsListOfDefs("Resources");
787776 RecIter SubI = SubResources.begin(), SubE = SubResources.end();
788777 for( ; SubI != SubE; ++SubI) {
789778 if (std::find(SuperResources.begin(), SuperResources.end(), *SubI)
792781 }
793782 }
794783 if (SubI == SubE) {
795 PRVec.push_back(*PRI);
784 PRVec.push_back(PR);
796785 Cycles.push_back(Cycles[i]);
797786 }
798787 }
808797 return;
809798
810799 std::vector &SCTab = SchedTables.ProcSchedClasses.back();
811 for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
812 SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
813 DEBUG(SCI->dump(&SchedModels));
800 for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
801 DEBUG(SC.dump(&SchedModels));
814802
815803 SCTab.resize(SCTab.size() + 1);
816804 MCSchedClassDesc &SCDesc = SCTab.back();
825813 // A Variant SchedClass has no resources of its own.
826814 bool HasVariants = false;
827815 for (std::vector::const_iterator
828 TI = SCI->Transitions.begin(), TE = SCI->Transitions.end();
816 TI = SC.Transitions.begin(), TE = SC.Transitions.end();
829817 TI != TE; ++TI) {
830818 if (TI->ProcIndices[0] == 0) {
831819 HasVariants = true;
846834 // Determine if the SchedClass is actually reachable on this processor. If
847835 // not don't try to locate the processor resources, it will fail.
848836 // If ProcIndices contains 0, this class applies to all processors.
849 assert(!SCI->ProcIndices.empty() && "expect at least one procidx");
850 if (SCI->ProcIndices[0] != 0) {
851 IdxIter PIPos = std::find(SCI->ProcIndices.begin(),
852 SCI->ProcIndices.end(), ProcModel.Index);
853 if (PIPos == SCI->ProcIndices.end())
837 assert(!SC.ProcIndices.empty() && "expect at least one procidx");
838 if (SC.ProcIndices[0] != 0) {
839 IdxIter PIPos = std::find(SC.ProcIndices.begin(),
840 SC.ProcIndices.end(), ProcModel.Index);
841 if (PIPos == SC.ProcIndices.end())
854842 continue;
855843 }
856 IdxVec Writes = SCI->Writes;
857 IdxVec Reads = SCI->Reads;
858 if (!SCI->InstRWs.empty()) {
844 IdxVec Writes = SC.Writes;
845 IdxVec Reads = SC.Reads;
846 if (!SC.InstRWs.empty()) {
859847 // This class has a default ReadWrite list which can be overriden by
860848 // InstRW definitions.
861849 Record *RWDef = nullptr;
862 for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
863 RWI != RWE; ++RWI) {
864 Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
850 for (Record *RW : SC.InstRWs) {
851 Record *RWModelDef = RW->getValueAsDef("SchedModel");
865852 if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
866 RWDef = *RWI;
853 RWDef = RW;
867854 break;
868855 }
869856 }
876863 }
877864 if (Writes.empty()) {
878865 // Check this processor's itinerary class resources.
879 for (RecIter II = ProcModel.ItinRWDefs.begin(),
880 IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) {
881 RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
882 if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef)
866 for (Record *I : ProcModel.ItinRWDefs) {
867 RecVec Matched = I->getValueAsListOfDefs("MatchedItinClasses");
868 if (std::find(Matched.begin(), Matched.end(), SC.ItinClassDef)
883869 != Matched.end()) {
884 SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"),
870 SchedModels.findRWs(I->getValueAsListOfDefs("OperandReadWrites"),
885871 Writes, Reads);
886872 break;
887873 }
888874 }
889875 if (Writes.empty()) {
890876 DEBUG(dbgs() << ProcModel.ModelName
891 << " does not have resources for class " << SCI->Name << '\n');
877 << " does not have resources for class " << SC.Name << '\n');
892878 }
893879 }
894880 // Sum resources across all operand writes.
896882 std::vector WriteLatencies;
897883 std::vector WriterNames;
898884 std::vector ReadAdvanceEntries;
899 for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
885 for (unsigned W : Writes) {
900886 IdxVec WriteSeq;
901 SchedModels.expandRWSeqForProc(*WI, WriteSeq, /*IsRead=*/false,
887 SchedModels.expandRWSeqForProc(W, WriteSeq, /*IsRead=*/false,
902888 ProcModel);
903889
904890 // For each operand, create a latency entry.
914900 }
915901 WLEntry.WriteResourceID = WriteID;
916902
917 for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
918 WSI != WSE; ++WSI) {
903 for (unsigned WS : WriteSeq) {
919904
920905 Record *WriteRes =
921 FindWriteResources(SchedModels.getSchedWrite(*WSI), ProcModel);
906 FindWriteResources(SchedModels.getSchedWrite(WS), ProcModel);
922907
923908 // Mark the parent class as invalid for unsupported write types.
924909 if (WriteRes->getValueAsBit("Unsupported")) {
980965 if (ValidWrites.empty())
981966 WriteIDs.push_back(0);
982967 else {
983 for (RecIter VWI = ValidWrites.begin(), VWE = ValidWrites.end();
984 VWI != VWE; ++VWI) {
985 WriteIDs.push_back(SchedModels.getSchedRWIdx(*VWI, /*IsRead=*/false));
968 for (Record *VW : ValidWrites) {
969 WriteIDs.push_back(SchedModels.getSchedRWIdx(VW, /*IsRead=*/false));
986970 }
987971 }
988972 std::sort(WriteIDs.begin(), WriteIDs.end());
989 for(IdxIter WI = WriteIDs.begin(), WE = WriteIDs.end(); WI != WE; ++WI) {
973 for(unsigned W : WriteIDs) {
990974 MCReadAdvanceEntry RAEntry;
991975 RAEntry.UseIdx = UseIdx;
992 RAEntry.WriteResourceID = *WI;
976 RAEntry.WriteResourceID = W;
993977 RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
994978 ReadAdvanceEntries.push_back(RAEntry);
995979 }
11551139
11561140 void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
11571141 // For each processor model.
1158 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
1159 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
1142 for (const CodeGenProcModel &PM : SchedModels.procModels()) {
11601143 // Emit processor resource table.
1161 if (PI->hasInstrSchedModel())
1162 EmitProcessorResources(*PI, OS);
1163 else if(!PI->ProcResourceDefs.empty())
1164 PrintFatalError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
1144 if (PM.hasInstrSchedModel())
1145 EmitProcessorResources(PM, OS);
1146 else if(!PM.ProcResourceDefs.empty())
1147 PrintFatalError(PM.ModelDef->getLoc(), "SchedMachineModel defines "
11651148 "ProcResources without defining WriteRes SchedWriteRes");
11661149
11671150 // Begin processor itinerary properties
11681151 OS << "\n";
1169 OS << "static const llvm::MCSchedModel " << PI->ModelName << " = {\n";
1170 EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
1171 EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ',');
1172 EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ',');
1173 EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
1174 EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
1175 EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
1176
1177 OS << " " << (bool)(PI->ModelDef ?
1178 PI->ModelDef->getValueAsBit("PostRAScheduler") : 0)
1152 OS << "static const llvm::MCSchedModel " << PM.ModelName << " = {\n";
1153 EmitProcessorProp(OS, PM.ModelDef, "IssueWidth", ',');
1154 EmitProcessorProp(OS, PM.ModelDef, "MicroOpBufferSize", ',');
1155 EmitProcessorProp(OS, PM.ModelDef, "LoopMicroOpBufferSize", ',');
1156 EmitProcessorProp(OS, PM.ModelDef, "LoadLatency", ',');
1157 EmitProcessorProp(OS, PM.ModelDef, "HighLatency", ',');
1158 EmitProcessorProp(OS, PM.ModelDef, "MispredictPenalty", ',');
1159
1160 OS << " " << (bool)(PM.ModelDef ?
1161 PM.ModelDef->getValueAsBit("PostRAScheduler") : 0)
11791162 << ", // " << "PostRAScheduler\n";
11801163
1181 OS << " " << (bool)(PI->ModelDef ?
1182 PI->ModelDef->getValueAsBit("CompleteModel") : 0)
1164 OS << " " << (bool)(PM.ModelDef ?
1165 PM.ModelDef->getValueAsBit("CompleteModel") : 0)
11831166 << ", // " << "CompleteModel\n";
11841167
1185 OS << " " << PI->Index << ", // Processor ID\n";
1186 if (PI->hasInstrSchedModel())
1187 OS << " " << PI->ModelName << "ProcResources" << ",\n"
1188 << " " << PI->ModelName << "SchedClasses" << ",\n"
1189 << " " << PI->ProcResourceDefs.size()+1 << ",\n"
1168 OS << " " << PM.Index << ", // Processor ID\n";
1169 if (PM.hasInstrSchedModel())
1170 OS << " " << PM.ModelName << "ProcResources" << ",\n"
1171 << " " << PM.ModelName << "SchedClasses" << ",\n"
1172 << " " << PM.ProcResourceDefs.size()+1 << ",\n"
11901173 << " " << (SchedModels.schedClassEnd()
11911174 - SchedModels.schedClassBegin()) << ",\n";
11921175 else
11931176 OS << " nullptr, nullptr, 0, 0,"
11941177 << " // No instruction-level machine model.\n";
1195 if (PI->hasItineraries())
1196 OS << " " << PI->ItinsDef->getName() << "};\n";
1178 if (PM.hasItineraries())
1179 OS << " " << PM.ItinsDef->getName() << "};\n";
11971180 else
11981181 OS << " nullptr}; // No Itinerary\n";
11991182 }
12591242 << "// Data tables for the new per-operand machine model.\n";
12601243
12611244 SchedClassTables SchedTables;
1262 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
1263 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
1264 GenSchedClassTables(*PI, SchedTables);
1245 for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
1246 GenSchedClassTables(ProcModel, SchedTables);
12651247 }
12661248 EmitSchedClassTables(SchedTables, OS);
12671249
12811263
12821264 std::vector Prologs = Records.getAllDerivedDefinitions("PredicateProlog");
12831265 std::sort(Prologs.begin(), Prologs.end(), LessRecord());
1284 for (std::vector::const_iterator
1285 PI = Prologs.begin(), PE = Prologs.end(); PI != PE; ++PI) {
1286 OS << (*PI)->getValueAsString("Code") << '\n';
1266 for (Record *P : Prologs) {
1267 OS << P->getValueAsString("Code") << '\n';
12871268 }
12881269 IdxVec VariantClasses;
1289 for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
1290 SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
1291 if (SCI->Transitions.empty())
1270 for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
1271 if (SC.Transitions.empty())
12921272 continue;
1293 VariantClasses.push_back(SCI->Index);
1273 VariantClasses.push_back(SC.Index);
12941274 }
12951275 if (!VariantClasses.empty()) {
12961276 OS << " switch (SchedClass) {\n";
1297 for (IdxIter VCI = VariantClasses.begin(), VCE = VariantClasses.end();
1298 VCI != VCE; ++VCI) {
1299 const CodeGenSchedClass &SC = SchedModels.getSchedClass(*VCI);
1300 OS << " case " << *VCI << ": // " << SC.Name << '\n';
1277 for (unsigned VC : VariantClasses) {
1278 const CodeGenSchedClass &SC = SchedModels.getSchedClass(VC);
1279 OS << " case " << VC << ": // " << SC.Name << '\n';
13011280 IdxVec ProcIndices;
1302 for (std::vector::const_iterator
1303 TI = SC.Transitions.begin(), TE = SC.Transitions.end();
1304 TI != TE; ++TI) {
1281 for (const CodeGenSchedTransition &T : SC.Transitions) {
13051282 IdxVec PI;
1306 std::set_union(TI->ProcIndices.begin(), TI->ProcIndices.end(),
1283 std::set_union(T.ProcIndices.begin(), T.ProcIndices.end(),
13071284 ProcIndices.begin(), ProcIndices.end(),
13081285 std::back_inserter(PI));
13091286 ProcIndices.swap(PI);
13101287 }
1311 for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
1312 PI != PE; ++PI) {
1288 for (unsigned PI : ProcIndices) {
13131289 OS << " ";
1314 if (*PI != 0)
1315 OS << "if (SchedModel->getProcessorID() == " << *PI << ") ";
1316 OS << "{ // " << (SchedModels.procModelBegin() + *PI)->ModelName
1290 if (PI != 0)
1291 OS << "if (SchedModel->getProcessorID() == " << PI << ") ";
1292 OS << "{ // " << (SchedModels.procModelBegin() + PI)->ModelName
13171293 << '\n';
1318 for (std::vector::const_iterator
1319 TI = SC.Transitions.begin(), TE = SC.Transitions.end();
1320 TI != TE; ++TI) {
1321 if (*PI != 0 && !std::count(TI->ProcIndices.begin(),
1322 TI->ProcIndices.end(), *PI)) {
1294 for (const CodeGenSchedTransition &T : SC.Transitions) {
1295 if (PI != 0 && !std::count(T.ProcIndices.begin(),
1296 T.ProcIndices.end(), PI)) {
13231297 continue;
13241298 }
13251299 OS << " if (";
1326 for (RecIter RI = TI->PredTerm.begin(), RE = TI->PredTerm.end();
1300 for (RecIter RI = T.PredTerm.begin(), RE = T.PredTerm.end();
13271301 RI != RE; ++RI) {
1328 if (RI != TI->PredTerm.begin())
1302 if (RI != T.PredTerm.begin())
13291303 OS << "\n && ";
13301304 OS << "(" << (*RI)->getValueAsString("Predicate") << ")";
13311305 }
13321306 OS << ")\n"
1333 << " return " << TI->ToClassIdx << "; // "
1334 << SchedModels.getSchedClass(TI->ToClassIdx).Name << '\n';
1307 << " return " << T.ToClassIdx << "; // "
1308 << SchedModels.getSchedClass(T.ToClassIdx).Name << '\n';
13351309 }
13361310 OS << " }\n";
1337 if (*PI == 0)
1311 if (PI == 0)
13381312 break;
13391313 }
13401314 if (SC.isInferred())
13741348 OS << " InitMCProcessorInfo(CPU, FS);\n"
13751349 << " const FeatureBitset& Bits = getFeatureBits();\n";
13761350
1377 for (unsigned i = 0; i < Features.size(); i++) {
1351 for (Record *R : Features) {
13781352 // Next record
1379 Record *R = Features[i];
13801353 const std::string &Instance = R->getName();
13811354 const std::string &Value = R->getValueAsString("Value");
13821355 const std::string &Attribute = R->getValueAsString("Attribute");