Index: llvm/include/llvm/TableGen/Record.h =================================================================== --- llvm/include/llvm/TableGen/Record.h +++ llvm/include/llvm/TableGen/Record.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -1704,6 +1705,7 @@ std::string InputFilename; RecordMap Classes, Defs; + mutable std::unordered_map> ClassRecordsMap; FoldingSet RecordTypePool; std::map> ExtraGlobals; unsigned AnonCounter = 0; @@ -1802,17 +1804,14 @@ //===--------------------------------------------------------------------===// // High-level helper methods, useful for tablegen backends. - /// Get all the concrete records that inherit from all the specified - /// classes. The classes must be defined. - std::vector getAllDerivedDefinitions( - const ArrayRef ClassNames) const; - /// Get all the concrete records that inherit from the one specified /// class. The class must be defined. - std::vector getAllDerivedDefinitions(StringRef ClassName) const { + std::vector getAllDerivedDefinitions(StringRef ClassName) const; - return getAllDerivedDefinitions(makeArrayRef(ClassName)); - } + /// Get all the concrete records that inherit from all the specified + /// classes. The classes must be defined. + std::vector getAllDerivedDefinitions( + ArrayRef ClassNames) const; void dump() const; }; Index: llvm/lib/TableGen/Record.cpp =================================================================== --- llvm/lib/TableGen/Record.cpp +++ llvm/lib/TableGen/Record.cpp @@ -2595,8 +2595,23 @@ } } +// We cache the record vectors for single classes. Many backends request +// the same vectors multiple times. std::vector RecordKeeper::getAllDerivedDefinitions( - const ArrayRef ClassNames) const { + StringRef ClassName) const { + std::string ClassNameString = std::string(ClassName); + auto It = ClassRecordsMap.find(ClassNameString); + if (It != ClassRecordsMap.end()) { + return It->second; + } + + auto Records = getAllDerivedDefinitions(makeArrayRef(ClassName)); + ClassRecordsMap.emplace(ClassNameString, std::move(Records)); + return ClassRecordsMap[ClassNameString]; +} + +std::vector RecordKeeper::getAllDerivedDefinitions( + ArrayRef ClassNames) const { SmallVector ClassRecs; std::vector Defs; Index: llvm/utils/TableGen/CodeGenDAGPatterns.cpp =================================================================== --- llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -3060,31 +3060,44 @@ : Records(R), Target(R), LegalVTS(Target.getLegalValueTypes()), PatternRewriter(PatternRewriter) { +Records.startTimer("CDP: instrinsic table"); Intrinsics = CodeGenIntrinsicTable(Records); +Records.startTimer("CDP: node info"); ParseNodeInfo(); +Records.startTimer("CDP: transforms"); ParseNodeTransforms(); +Records.startTimer("CDP: complex patterns"); ParseComplexPatterns(); +Records.startTimer("CDP: pattern fragments 1"); ParsePatternFragments(); +Records.startTimer("CDP: default operands"); ParseDefaultOperands(); +Records.startTimer("CDP: instructions"); ParseInstructions(); +Records.startTimer("CDP: pattern fragments 2"); ParsePatternFragments(/*OutFrags*/true); +Records.startTimer("CDP: patterns"); ParsePatterns(); // Break patterns with parameterized types into a series of patterns, // where each one has a fixed type and is predicated on the conditions // of the associated HW mode. +Records.startTimer("CDP: mode-based types"); ExpandHwModeBasedTypes(); // Generate variants. For example, commutative patterns can match // multiple ways. Add them to PatternsToMatch as well. +Records.startTimer("CDP: variants"); GenerateVariants(); // Infer instruction flags. For example, we can detect loads, // stores, and side effects in many cases by examining an // instruction's pattern. +Records.startTimer("CDP: infer flags"); InferInstructionFlags(); // Verify that instruction flags match the patterns. +Records.startTimer("CDP: verify flags"); VerifyInstructionFlags(); } Index: llvm/utils/TableGen/CodeGenMapTable.cpp =================================================================== --- llvm/utils/TableGen/CodeGenMapTable.cpp +++ llvm/utils/TableGen/CodeGenMapTable.cpp @@ -570,8 +570,11 @@ // functions to query them. //===----------------------------------------------------------------------===// void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) { +Records.startTimer("EMT: CodeGenTarget"); CodeGenTarget Target(Records); +Records.startTimer("EMT: Namespace"); StringRef NameSpace = Target.getInstNamespace(); +Records.startTimer("EMT: InstrMapping"); std::vector InstrMapVec; InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); @@ -584,11 +587,13 @@ OS << "namespace " << NameSpace << " {\n\n"; // Emit coulumn field names and their values as enums. +Records.startTimer("EMT: enums"); emitEnums(OS, Records); // Iterate over all instruction mapping records and construct relationship // maps based on the information specified there. // +Records.startTimer("EMT: relation maps"); for (Record *CurMap : InstrMapVec) { MapTableEmitter IMap(Target, Records, CurMap); Index: llvm/utils/TableGen/CodeGenTarget.h =================================================================== --- llvm/utils/TableGen/CodeGenTarget.h +++ llvm/utils/TableGen/CodeGenTarget.h @@ -60,6 +60,7 @@ mutable std::unique_ptr SchedModels; + mutable StringRef InstNamespace = StringRef(); mutable std::vector InstrsByEnum; mutable unsigned NumPseudoInstructions = 0; public: Index: llvm/utils/TableGen/CodeGenTarget.cpp =================================================================== --- llvm/utils/TableGen/CodeGenTarget.cpp +++ llvm/utils/TableGen/CodeGenTarget.cpp @@ -264,15 +264,20 @@ return TargetRec->getName(); } +/// getInstNamespace - Find and return the target machine's instruction +/// namespace. The namespace is cached because it is requested multiple times. StringRef CodeGenTarget::getInstNamespace() const { - for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) { - // Make sure not to pick up "TargetOpcode" by accidentally getting - // the namespace off the PHI instruction or something. - if (Inst->Namespace != "TargetOpcode") - return Inst->Namespace; + if (InstNamespace.empty()) { + for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) { + // We are not interested in the "TargetOpcode" namespace. + if (Inst->Namespace != "TargetOpcode") { + InstNamespace = Inst->Namespace; + break; + } + } } - return ""; + return InstNamespace; } StringRef CodeGenTarget::getRegNamespace() const { Index: llvm/utils/TableGen/InstrInfoEmitter.cpp =================================================================== --- llvm/utils/TableGen/InstrInfoEmitter.cpp +++ llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -532,6 +532,7 @@ unsigned ListNumber = 0; // Emit all of the instruction's implicit uses and defs. + Records.startTimer("Emit uses/defs"); for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) { Record *Inst = II->TheDef; std::vector Uses = Inst->getValueAsListOfDefs("Uses"); @@ -549,10 +550,12 @@ OperandInfoMapTy OperandInfoIDs; // Emit all of the operand info records. + Records.startTimer("Emit operand info"); EmitOperandInfo(OS, OperandInfoIDs); // Emit all of the MCInstrDesc records in their ENUM ordering. // + Records.startTimer("Emit InstrDesc records"); OS << "\nextern const MCInstrDesc " << TargetName << "Insts[] = {\n"; ArrayRef NumberedInstructions = Target.getInstructionsByEnumValue(); @@ -568,6 +571,7 @@ OS << "};\n\n"; // Emit the array of instruction names. + Records.startTimer("Emit instruction names"); InstrNames.layout(); InstrNames.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName + "InstrNameData[]"); @@ -628,6 +632,7 @@ } // MCInstrInfo initialization routine. + Records.startTimer("Emit initialization routine"); OS << "static inline void Init" << TargetName << "MCInstrInfo(MCInstrInfo *II) {\n"; OS << " II->InitMCInstrInfo(" << TargetName << "Insts, " << TargetName @@ -706,10 +711,13 @@ OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n"; + Records.startTimer("Emit operand name mappings"); emitOperandNameMappings(OS, Target, NumberedInstructions); + Records.startTimer("Emit operand type mappings"); emitOperandTypeMappings(OS, Target, NumberedInstructions); + Records.startTimer("Emit helper methods"); emitMCIIHelperMethods(OS, TargetName); } @@ -862,7 +870,9 @@ namespace llvm { void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) { + RK.startTimer("Analyze DAG patterns"); InstrInfoEmitter(RK).run(OS); + RK.startTimer("Emit map table"); EmitMapTable(RK, OS); }