From ebe69fe11e48d322045d5949c83283927a0d790b Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Mon, 23 Mar 2015 12:10:34 -0700 Subject: Update aosp/master LLVM for rebase to r230699. Change-Id: I2b5be30509658cb8266be782de0ab24f9099f9b9 --- utils/FileCheck/FileCheck.cpp | 49 ++- utils/TableGen/AsmMatcherEmitter.cpp | 429 +++++++++------------ utils/TableGen/AsmWriterEmitter.cpp | 84 ++-- utils/TableGen/AsmWriterInst.cpp | 4 +- utils/TableGen/AsmWriterInst.h | 3 +- utils/TableGen/CallingConvEmitter.cpp | 11 +- utils/TableGen/CodeEmitterGen.cpp | 2 +- utils/TableGen/CodeGenDAGPatterns.cpp | 60 ++- utils/TableGen/CodeGenInstruction.cpp | 14 +- utils/TableGen/CodeGenInstruction.h | 2 +- utils/TableGen/CodeGenMapTable.cpp | 4 +- utils/TableGen/CodeGenRegisters.cpp | 618 +++++++++++++++++------------- utils/TableGen/CodeGenRegisters.h | 143 ++++--- utils/TableGen/CodeGenSchedule.cpp | 44 +-- utils/TableGen/CodeGenTarget.cpp | 52 ++- utils/TableGen/CodeGenTarget.h | 13 +- utils/TableGen/DAGISelEmitter.cpp | 8 +- utils/TableGen/DAGISelMatcher.h | 3 +- utils/TableGen/DAGISelMatcherGen.cpp | 4 +- utils/TableGen/DAGISelMatcherOpt.cpp | 7 +- utils/TableGen/DFAPacketizerEmitter.cpp | 2 +- utils/TableGen/FixedLenDecoderEmitter.cpp | 97 ++--- utils/TableGen/InstrInfoEmitter.cpp | 10 +- utils/TableGen/IntrinsicEmitter.cpp | 29 +- utils/TableGen/RegisterInfoEmitter.cpp | 553 +++++++++++++++----------- utils/TableGen/SequenceToOffsetTable.h | 5 + utils/TableGen/SubtargetEmitter.cpp | 2 +- utils/TableGen/TableGen.cpp | 16 +- utils/TableGen/X86DisassemblerTables.cpp | 49 ++- utils/TableGen/X86DisassemblerTables.h | 4 +- utils/TableGen/X86RecognizableInstr.cpp | 195 ++++++---- utils/TableGen/X86RecognizableInstr.h | 4 +- utils/emacs/emacs.el | 37 +- utils/emacs/llvm-mode.el | 111 +++--- utils/emacs/tablegen-mode.el | 20 +- utils/lit/lit/LitConfig.py | 2 - utils/lit/lit/Test.py | 5 +- utils/lit/lit/TestingConfig.py | 6 +- utils/lit/lit/formats/googletest.py | 1 - utils/lit/lit/util.py | 18 +- utils/lit/utils/check-coverage | 2 +- utils/lldbDataFormatters.py | 10 + utils/not/not.cpp | 5 + utils/release/merge.sh | 10 +- utils/release/tag.sh | 39 +- utils/release/test-release.sh | 48 ++- utils/shuffle_fuzz.py | 5 +- utils/unittest/CMakeLists.txt | 17 +- utils/update_llc_test_checks.py | 213 ++++++++++ utils/vim/llvm.vim | 46 ++- 50 files changed, 1841 insertions(+), 1274 deletions(-) create mode 100755 utils/update_llc_test_checks.py (limited to 'utils') diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 59affa1..146b512 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -73,6 +73,7 @@ namespace Check { CheckNone = 0, CheckPlain, CheckNext, + CheckSame, CheckNot, CheckDAG, CheckLabel, @@ -620,6 +621,9 @@ struct CheckString { /// CheckNext - Verify there is a single line in the given buffer. bool CheckNext(const SourceMgr &SM, StringRef Buffer) const; + /// CheckSame - Verify there is no newline in the given buffer. + bool CheckSame(const SourceMgr &SM, StringRef Buffer) const; + /// CheckNot - Verify there's no "not strings" in the given buffer. bool CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector &NotStrings, @@ -683,6 +687,9 @@ static size_t CheckTypeSize(Check::CheckType Ty) { case Check::CheckNext: return sizeof("-NEXT:") - 1; + case Check::CheckSame: + return sizeof("-SAME:") - 1; + case Check::CheckNot: return sizeof("-NOT:") - 1; @@ -713,6 +720,9 @@ static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) { if (Rest.startswith("NEXT:")) return Check::CheckNext; + if (Rest.startswith("SAME:")) + return Check::CheckSame; + if (Rest.startswith("NOT:")) return Check::CheckNot; @@ -919,10 +929,12 @@ static bool ReadCheckFile(SourceMgr &SM, Buffer = Buffer.substr(EOL); // Verify that CHECK-NEXT lines have at least one CHECK line before them. - if ((CheckTy == Check::CheckNext) && CheckStrings.empty()) { + if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) && + CheckStrings.empty()) { + StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME"; SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error, - "found '" + UsedPrefix + "-NEXT:' without previous '" + "found '" + UsedPrefix + "-" + Type + "' without previous '" + UsedPrefix + ": line"); return true; } @@ -1053,6 +1065,11 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer, if (CheckNext(SM, SkippedRegion)) return StringRef::npos; + // If this check is a "CHECK-SAME", verify that the previous match was on + // the same line (i.e. that there is no newline between them). + if (CheckSame(SM, SkippedRegion)) + return StringRef::npos; + // If this match had "not strings", verify that they don't exist in the // skipped region. if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable)) @@ -1101,6 +1118,34 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { return false; } +bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const { + if (CheckTy != Check::CheckSame) + return false; + + // Count the number of newlines between the previous match and this one. + assert(Buffer.data() != + SM.getMemoryBuffer(SM.FindBufferContainingLoc( + SMLoc::getFromPointer(Buffer.data()))) + ->getBufferStart() && + "CHECK-SAME can't be the first check in a file"); + + const char *FirstNewLine = nullptr; + unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); + + if (NumNewLines != 0) { + SM.PrintMessage(Loc, SourceMgr::DK_Error, + Prefix + + "-SAME: is not on the same line as the previous match"); + SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, + "'next' match was here"); + SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, + "previous match ended here"); + return true; + } + + return false; +} + bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector &NotStrings, StringMap &VariableTable) const { diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 891328f..65a34d3 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -115,6 +115,7 @@ #include #include #include +#include using namespace llvm; #define DEBUG_TYPE "asm-matcher-emitter" @@ -255,9 +256,8 @@ public: return true; // ... or if any of its super classes are a subset of RHS. - for (std::vector::const_iterator it = SuperClasses.begin(), - ie = SuperClasses.end(); it != ie; ++it) - if ((*it)->isSubsetOf(RHS)) + for (const ClassInfo *CI : SuperClasses) + if (CI->isSubsetOf(RHS)) return true; return false; @@ -391,6 +391,10 @@ struct MatchableInfo { /// AsmVariantID - Target's assembly syntax variant no. int AsmVariantID; + /// AsmString - The assembly string for this instruction (with variants + /// removed), e.g. "movsx $src, $dst". + std::string AsmString; + /// TheDef - This is the definition of the instruction or InstAlias that this /// matchable came from. Record *const TheDef; @@ -408,10 +412,6 @@ struct MatchableInfo { /// MCInst. SmallVector ResOperands; - /// AsmString - The assembly string for this instruction (with variants - /// removed), e.g. "movsx $src, $dst". - std::string AsmString; - /// Mnemonic - This is the first token of the matched instruction, its /// mnemonic. StringRef Mnemonic; @@ -423,7 +423,7 @@ struct MatchableInfo { SmallVector AsmOperands; /// Predicates - The required subtarget features to match this instruction. - SmallVector RequiredFeatures; + SmallVector RequiredFeatures; /// ConversionFnKind - The enum value which is passed to the generated /// convertToMCInst to convert parsed operands into an MCInst for this @@ -434,13 +434,15 @@ struct MatchableInfo { bool HasDeprecation; MatchableInfo(const CodeGenInstruction &CGI) - : AsmVariantID(0), TheDef(CGI.TheDef), DefRec(&CGI), - AsmString(CGI.AsmString) { + : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI) { } - MatchableInfo(const CodeGenInstAlias *Alias) - : AsmVariantID(0), TheDef(Alias->TheDef), DefRec(Alias), - AsmString(Alias->AsmString) { + MatchableInfo(std::unique_ptr Alias) + : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), DefRec(Alias.release()) { + } + + ~MatchableInfo() { + delete DefRec.dyn_cast(); } // Two-operand aliases clone from the main matchable, but mark the second @@ -516,7 +518,7 @@ struct MatchableInfo { /// couldMatchAmbiguouslyWith - Check whether this matchable could /// ambiguously match the same set of operands as \p RHS (without being a /// strictly superior match). - bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) { + bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) const { // The primary comparator is the instruction mnemonic. if (Mnemonic != RHS.Mnemonic) return false; @@ -552,7 +554,7 @@ struct MatchableInfo { return !(HasLT ^ HasGT); } - void dump(); + void dump() const; private: void tokenizeAsmString(const AsmMatcherInfo &Info); @@ -574,7 +576,7 @@ struct SubtargetFeatureInfo { return "Feature_" + TheDef->getName(); } - void dump() { + void dump() const { errs() << getEnumName() << " " << Index << "\n"; TheDef->dump(); } @@ -582,10 +584,10 @@ struct SubtargetFeatureInfo { struct OperandMatchEntry { unsigned OperandMask; - MatchableInfo* MI; + const MatchableInfo* MI; ClassInfo *CI; - static OperandMatchEntry create(MatchableInfo* mi, ClassInfo *ci, + static OperandMatchEntry create(const MatchableInfo *mi, ClassInfo *ci, unsigned opMask) { OperandMatchEntry X; X.OperandMask = opMask; @@ -608,10 +610,10 @@ public: CodeGenTarget &Target; /// The classes which are needed for matching. - std::vector Classes; + std::forward_list Classes; /// The information on the matchables to match. - std::vector Matchables; + std::vector> Matchables; /// Info for custom matching operands by user defined methods. std::vector OperandMatchInfo; @@ -621,7 +623,7 @@ public: RegisterClassesTy RegisterClasses; /// Map of Predicate records to their subtarget information. - std::map SubtargetFeatures; + std::map SubtargetFeatures; /// Map of AsmOperandClass records to their class information. std::map AsmOperandClasses; @@ -669,11 +671,10 @@ public: /// getSubtargetFeature - Lookup or create the subtarget feature info for the /// given operand. - SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const { + const SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const { assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); - std::map::const_iterator I = - SubtargetFeatures.find(Def); - return I == SubtargetFeatures.end() ? nullptr : I->second; + const auto &I = SubtargetFeatures.find(Def); + return I == SubtargetFeatures.end() ? nullptr : &I->second; } RecordKeeper &getRecords() const { @@ -683,11 +684,11 @@ public: } // End anonymous namespace -void MatchableInfo::dump() { +void MatchableInfo::dump() const { errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n"; for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { - AsmOperand &Op = AsmOperands[i]; + const AsmOperand &Op = AsmOperands[i]; errs() << " op[" << i << "] = " << Op.Class->ClassName << " - "; errs() << '\"' << Op.Token << "\"\n"; } @@ -777,8 +778,8 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info, // Compute the require features. std::vector Predicates =TheDef->getValueAsListOfDefs("Predicates"); for (unsigned i = 0, e = Predicates.size(); i != e; ++i) - if (SubtargetFeatureInfo *Feature = - Info.getSubtargetFeature(Predicates[i])) + if (const SubtargetFeatureInfo *Feature = + Info.getSubtargetFeature(Predicates[i])) RequiredFeatures.push_back(Feature); // Collect singleton registers, if used. @@ -978,6 +979,7 @@ static std::string getEnumNameForToken(StringRef Str) { case '.': Res += "_DOT_"; break; case '<': Res += "_LT_"; break; case '>': Res += "_GT_"; break; + case '-': Res += "_MINUS_"; break; default: if ((*it >= 'A' && *it <= 'Z') || (*it >= 'a' && *it <= 'z') || @@ -995,7 +997,8 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { ClassInfo *&Entry = TokenClasses[Token]; if (!Entry) { - Entry = new ClassInfo(); + Classes.emplace_front(); + Entry = &Classes.front(); Entry->Kind = ClassInfo::Token; Entry->ClassName = "Token"; Entry->Name = "MCK_" + getEnumNameForToken(Token); @@ -1004,7 +1007,6 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { Entry->RenderMethod = ""; Entry->ParserMethod = ""; Entry->DiagnosticType = ""; - Classes.push_back(Entry); } return Entry; @@ -1076,10 +1078,8 @@ struct LessRegisterSet { void AsmMatcherInfo:: buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { - const std::vector &Registers = - Target.getRegBank().getRegisters(); - ArrayRef RegClassList = - Target.getRegBank().getRegClasses(); + const auto &Registers = Target.getRegBank().getRegisters(); + auto &RegClassList = Target.getRegBank().getRegClasses(); typedef std::set RegisterSetSet; @@ -1087,15 +1087,12 @@ buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { RegisterSetSet RegisterSets; // Gather the defined sets. - for (ArrayRef::const_iterator it = - RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) - RegisterSets.insert(RegisterSet( - (*it)->getOrder().begin(), (*it)->getOrder().end())); + for (const CodeGenRegisterClass &RC : RegClassList) + RegisterSets.insert( + RegisterSet(RC.getOrder().begin(), RC.getOrder().end())); // Add any required singleton sets. - for (SmallPtrSetImpl::iterator it = SingletonRegisters.begin(), - ie = SingletonRegisters.end(); it != ie; ++it) { - Record *Rec = *it; + for (Record *Rec : SingletonRegisters) { RegisterSets.insert(RegisterSet(&Rec, &Rec + 1)); } @@ -1103,19 +1100,16 @@ buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { // a unique register set class), and build the mapping of registers to the set // they should classify to. std::map RegisterMap; - for (std::vector::const_iterator it = Registers.begin(), - ie = Registers.end(); it != ie; ++it) { - const CodeGenRegister &CGR = **it; + for (const CodeGenRegister &CGR : Registers) { // Compute the intersection of all sets containing this register. RegisterSet ContainingSet; - for (RegisterSetSet::iterator it = RegisterSets.begin(), - ie = RegisterSets.end(); it != ie; ++it) { - if (!it->count(CGR.TheDef)) + for (const RegisterSet &RS : RegisterSets) { + if (!RS.count(CGR.TheDef)) continue; if (ContainingSet.empty()) { - ContainingSet = *it; + ContainingSet = RS; continue; } @@ -1123,7 +1117,7 @@ buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { std::swap(Tmp, ContainingSet); std::insert_iterator II(ContainingSet, ContainingSet.begin()); - std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II, + std::set_intersection(Tmp.begin(), Tmp.end(), RS.begin(), RS.end(), II, LessRecordByID()); } @@ -1136,39 +1130,35 @@ buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { // Construct the register classes. std::map RegisterSetClasses; unsigned Index = 0; - for (RegisterSetSet::iterator it = RegisterSets.begin(), - ie = RegisterSets.end(); it != ie; ++it, ++Index) { - ClassInfo *CI = new ClassInfo(); + for (const RegisterSet &RS : RegisterSets) { + Classes.emplace_front(); + ClassInfo *CI = &Classes.front(); CI->Kind = ClassInfo::RegisterClass0 + Index; CI->ClassName = "Reg" + utostr(Index); CI->Name = "MCK_Reg" + utostr(Index); CI->ValueName = ""; CI->PredicateMethod = ""; // unused CI->RenderMethod = "addRegOperands"; - CI->Registers = *it; + CI->Registers = RS; // FIXME: diagnostic type. CI->DiagnosticType = ""; - Classes.push_back(CI); - RegisterSetClasses.insert(std::make_pair(*it, CI)); + RegisterSetClasses.insert(std::make_pair(RS, CI)); + ++Index; } // Find the superclasses; we could compute only the subgroup lattice edges, // but there isn't really a point. - for (RegisterSetSet::iterator it = RegisterSets.begin(), - ie = RegisterSets.end(); it != ie; ++it) { - ClassInfo *CI = RegisterSetClasses[*it]; - for (RegisterSetSet::iterator it2 = RegisterSets.begin(), - ie2 = RegisterSets.end(); it2 != ie2; ++it2) - if (*it != *it2 && - std::includes(it2->begin(), it2->end(), it->begin(), it->end(), + for (const RegisterSet &RS : RegisterSets) { + ClassInfo *CI = RegisterSetClasses[RS]; + for (const RegisterSet &RS2 : RegisterSets) + if (RS != RS2 && + std::includes(RS2.begin(), RS2.end(), RS.begin(), RS.end(), LessRecordByID())) - CI->SuperClasses.push_back(RegisterSetClasses[*it2]); + CI->SuperClasses.push_back(RegisterSetClasses[RS2]); } // Name the register classes which correspond to a user defined RegisterClass. - for (ArrayRef::const_iterator - it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) { - const CodeGenRegisterClass &RC = **it; + for (const CodeGenRegisterClass &RC : RegClassList) { // Def will be NULL for non-user defined register classes. Record *Def = RC.getDef(); if (!Def) @@ -1191,9 +1181,7 @@ buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { RegisterClasses[it->first] = RegisterSetClasses[it->second]; // Name the register classes which correspond to singleton registers. - for (SmallPtrSetImpl::iterator it = SingletonRegisters.begin(), - ie = SingletonRegisters.end(); it != ie; ++it) { - Record *Rec = *it; + for (Record *Rec : SingletonRegisters) { ClassInfo *CI = RegisterClasses[Rec]; assert(CI && "Missing singleton register class info!"); @@ -1211,36 +1199,36 @@ void AsmMatcherInfo::buildOperandClasses() { Records.getAllDerivedDefinitions("AsmOperandClass"); // Pre-populate AsmOperandClasses map. - for (std::vector::iterator it = AsmOperands.begin(), - ie = AsmOperands.end(); it != ie; ++it) - AsmOperandClasses[*it] = new ClassInfo(); + for (Record *Rec : AsmOperands) { + Classes.emplace_front(); + AsmOperandClasses[Rec] = &Classes.front(); + } unsigned Index = 0; - for (std::vector::iterator it = AsmOperands.begin(), - ie = AsmOperands.end(); it != ie; ++it, ++Index) { - ClassInfo *CI = AsmOperandClasses[*it]; + for (Record *Rec : AsmOperands) { + ClassInfo *CI = AsmOperandClasses[Rec]; CI->Kind = ClassInfo::UserClass0 + Index; - ListInit *Supers = (*it)->getValueAsListInit("SuperClasses"); + ListInit *Supers = Rec->getValueAsListInit("SuperClasses"); for (unsigned i = 0, e = Supers->getSize(); i != e; ++i) { DefInit *DI = dyn_cast(Supers->getElement(i)); if (!DI) { - PrintError((*it)->getLoc(), "Invalid super class reference!"); + PrintError(Rec->getLoc(), "Invalid super class reference!"); continue; } ClassInfo *SC = AsmOperandClasses[DI->getDef()]; if (!SC) - PrintError((*it)->getLoc(), "Invalid super class reference!"); + PrintError(Rec->getLoc(), "Invalid super class reference!"); else CI->SuperClasses.push_back(SC); } - CI->ClassName = (*it)->getValueAsString("Name"); + CI->ClassName = Rec->getValueAsString("Name"); CI->Name = "MCK_" + CI->ClassName; - CI->ValueName = (*it)->getName(); + CI->ValueName = Rec->getName(); // Get or construct the predicate method name. - Init *PMName = (*it)->getValueInit("PredicateMethod"); + Init *PMName = Rec->getValueInit("PredicateMethod"); if (StringInit *SI = dyn_cast(PMName)) { CI->PredicateMethod = SI->getValue(); } else { @@ -1249,7 +1237,7 @@ void AsmMatcherInfo::buildOperandClasses() { } // Get or construct the render method name. - Init *RMName = (*it)->getValueInit("RenderMethod"); + Init *RMName = Rec->getValueInit("RenderMethod"); if (StringInit *SI = dyn_cast(RMName)) { CI->RenderMethod = SI->getValue(); } else { @@ -1258,18 +1246,17 @@ void AsmMatcherInfo::buildOperandClasses() { } // Get the parse method name or leave it as empty. - Init *PRMName = (*it)->getValueInit("ParserMethod"); + Init *PRMName = Rec->getValueInit("ParserMethod"); if (StringInit *SI = dyn_cast(PRMName)) CI->ParserMethod = SI->getValue(); // Get the diagnostic type or leave it as empty. // Get the parse method name or leave it as empty. - Init *DiagnosticType = (*it)->getValueInit("DiagnosticType"); + Init *DiagnosticType = Rec->getValueInit("DiagnosticType"); if (StringInit *SI = dyn_cast(DiagnosticType)) CI->DiagnosticType = SI->getValue(); - AsmOperandClasses[*it] = CI; - Classes.push_back(CI); + ++Index; } } @@ -1288,16 +1275,13 @@ void AsmMatcherInfo::buildOperandMatchInfo() { typedef std::map> OpClassMaskTy; OpClassMaskTy OpClassMask; - for (std::vector::const_iterator it = - Matchables.begin(), ie = Matchables.end(); - it != ie; ++it) { - MatchableInfo &II = **it; + for (const auto &MI : Matchables) { OpClassMask.clear(); // Keep track of all operands of this instructions which belong to the // same class. - for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { - MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) { + const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i]; if (Op.Class->ParserMethod.empty()) continue; unsigned &OperandMask = OpClassMask[Op.Class]; @@ -1305,11 +1289,11 @@ void AsmMatcherInfo::buildOperandMatchInfo() { } // Generate operand match info for each mnemonic/operand class pair. - for (OpClassMaskTy::iterator iit = OpClassMask.begin(), - iie = OpClassMask.end(); iit != iie; ++iit) { - unsigned OpMask = iit->second; - ClassInfo *CI = iit->first; - OperandMatchInfo.push_back(OperandMatchEntry::create(&II, CI, OpMask)); + for (const auto &OCM : OpClassMask) { + unsigned OpMask = OCM.second; + ClassInfo *CI = OCM.first; + OperandMatchInfo.push_back(OperandMatchEntry::create(MI.get(), CI, + OpMask)); } } } @@ -1327,10 +1311,10 @@ void AsmMatcherInfo::buildInfo() { if (Pred->getName().empty()) PrintFatalError(Pred->getLoc(), "Predicate has no name!"); - uint64_t FeatureNo = SubtargetFeatures.size(); - SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); - DEBUG(SubtargetFeatures[Pred]->dump()); - assert(FeatureNo < 64 && "Too many subtarget features!"); + SubtargetFeatures.insert(std::make_pair( + Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size()))); + DEBUG(SubtargetFeatures.find(Pred)->second.dump()); + assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!"); } // Parse the instructions; we need to do this first so that we can gather the @@ -1344,20 +1328,18 @@ void AsmMatcherInfo::buildInfo() { std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix"); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - const CodeGenInstruction &CGI = **I; + for (const CodeGenInstruction *CGI : Target.instructions()) { // If the tblgen -match-prefix option is specified (for tblgen hackers), // filter the set of instructions we consider. - if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix)) + if (!StringRef(CGI->TheDef->getName()).startswith(MatchPrefix)) continue; // Ignore "codegen only" instructions. - if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) + if (CGI->TheDef->getValueAsBit("isCodeGenOnly")) continue; - std::unique_ptr II(new MatchableInfo(CGI)); + std::unique_ptr II(new MatchableInfo(*CGI)); II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); @@ -1366,14 +1348,7 @@ void AsmMatcherInfo::buildInfo() { if (!II->validate(CommentDelimiter, true)) continue; - // Ignore "Int_*" and "*_Int" instructions, which are internal aliases. - // - // FIXME: This is a total hack. - if (StringRef(II->TheDef->getName()).startswith("Int_") || - StringRef(II->TheDef->getName()).endswith("_Int")) - continue; - - Matchables.push_back(II.release()); + Matchables.push_back(std::move(II)); } // Parse all of the InstAlias definitions and stick them in the list of @@ -1381,8 +1356,8 @@ void AsmMatcherInfo::buildInfo() { std::vector AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { - CodeGenInstAlias *Alias = - new CodeGenInstAlias(AllInstAliases[i], AsmVariantNo, Target); + auto Alias = llvm::make_unique(AllInstAliases[i], + AsmVariantNo, Target); // If the tblgen -match-prefix option is specified (for tblgen hackers), // filter the set of instruction aliases we consider, based on the target @@ -1391,14 +1366,14 @@ void AsmMatcherInfo::buildInfo() { .startswith( MatchPrefix)) continue; - std::unique_ptr II(new MatchableInfo(Alias)); + std::unique_ptr II(new MatchableInfo(std::move(Alias))); II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); // Validate the alias definitions. II->validate(CommentDelimiter, false); - Matchables.push_back(II.release()); + Matchables.push_back(std::move(II)); } } @@ -1410,11 +1385,8 @@ void AsmMatcherInfo::buildInfo() { // Build the information about matchables, now that we have fully formed // classes. - std::vector NewMatchables; - for (std::vector::iterator it = Matchables.begin(), - ie = Matchables.end(); it != ie; ++it) { - MatchableInfo *II = *it; - + std::vector> NewMatchables; + for (auto &II : Matchables) { // Parse the tokens after the mnemonic. // Note: buildInstructionOperandReference may insert new AsmOperands, so // don't precompute the loop bound. @@ -1449,9 +1421,9 @@ void AsmMatcherInfo::buildInfo() { OperandName = Token.substr(1); if (II->DefRec.is()) - buildInstructionOperandReference(II, OperandName, i); + buildInstructionOperandReference(II.get(), OperandName, i); else - buildAliasOperandReference(II, OperandName, Op); + buildAliasOperandReference(II.get(), OperandName, Op); } if (II->DefRec.is()) { @@ -1469,14 +1441,14 @@ void AsmMatcherInfo::buildInfo() { AliasII->formTwoOperandAlias(Constraint); // Add the alias to the matchables list. - NewMatchables.push_back(AliasII.release()); + NewMatchables.push_back(std::move(AliasII)); } } else II->buildAliasResultOperands(); } if (!NewMatchables.empty()) - Matchables.insert(Matchables.end(), NewMatchables.begin(), - NewMatchables.end()); + std::move(NewMatchables.begin(), NewMatchables.end(), + std::back_inserter(Matchables)); // Process token alias definitions and set up the associated superclass // information. @@ -1493,7 +1465,7 @@ void AsmMatcherInfo::buildInfo() { } // Reorder classes so that classes precede super classes. - std::sort(Classes.begin(), Classes.end(), less_ptr()); + Classes.sort(); } /// buildInstructionOperandReference - The specified operand is a reference to a @@ -1703,7 +1675,7 @@ static unsigned getConverterOperandID(const std::string &Name, static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, - std::vector &Infos, + std::vector> &Infos, raw_ostream &OS) { SetVector OperandConversionKinds; SetVector InstructionConversionKinds; @@ -1767,16 +1739,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, OperandConversionKinds.insert("CVT_Tied"); enum { CVT_Done, CVT_Reg, CVT_Tied }; - for (std::vector::const_iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - MatchableInfo &II = **it; - + for (auto &II : Infos) { // Check if we have a custom match function. std::string AsmMatchConverter = - II.getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); + II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); if (!AsmMatchConverter.empty()) { std::string Signature = "ConvertCustom_" + AsmMatchConverter; - II.ConversionFnKind = Signature; + II->ConversionFnKind = Signature; // Check if we have already generated this signature. if (!InstructionConversionKinds.insert(Signature)) @@ -1808,16 +1777,17 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, std::vector ConversionRow; // Compute the convert enum and the case body. - MaxRowLength = std::max(MaxRowLength, II.ResOperands.size()*2 + 1 ); + MaxRowLength = std::max(MaxRowLength, II->ResOperands.size()*2 + 1 ); - for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) { - const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i]; + for (unsigned i = 0, e = II->ResOperands.size(); i != e; ++i) { + const MatchableInfo::ResOperand &OpInfo = II->ResOperands[i]; // Generate code to populate each result operand. switch (OpInfo.Kind) { case MatchableInfo::ResOperand::RenderAsmOperand: { // This comes from something we parsed. - MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum]; + const MatchableInfo::AsmOperand &Op = + II->AsmOperands[OpInfo.AsmOperandNum]; // Registers are always converted the same, don't duplicate the // conversion function based on them. @@ -1879,6 +1849,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, case MatchableInfo::ResOperand::ImmOperand: { int64_t Val = OpInfo.ImmVal; std::string Ty = "imm_" + itostr(Val); + Ty = getEnumNameForToken(Ty); Signature += "__" + Ty; std::string Name = "CVT_" + Ty; @@ -1940,7 +1911,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, if (Signature == "Convert") Signature += "_NoOperands"; - II.ConversionFnKind = Signature; + II->ConversionFnKind = Signature; // Save the signature. If we already have it, don't add a new row // to the table. @@ -2003,7 +1974,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, /// emitMatchClassEnumeration - Emit the enumeration for match class kinds. static void emitMatchClassEnumeration(CodeGenTarget &Target, - std::vector &Infos, + std::forward_list &Infos, raw_ostream &OS) { OS << "namespace {\n\n"; @@ -2011,9 +1982,7 @@ static void emitMatchClassEnumeration(CodeGenTarget &Target, << "/// instruction matching.\n"; OS << "enum MatchClassKind {\n"; OS << " InvalidMatchClass = 0,\n"; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &CI = **it; + for (const auto &CI : Infos) { OS << " " << CI.Name << ", // "; if (CI.Kind == ClassInfo::Token) { OS << "'" << CI.ValueName << "'\n"; @@ -2053,10 +2022,7 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, // Check the user classes. We don't care what order since we're only // actually matching against one of them. - for (std::vector::iterator it = Info.Classes.begin(), - ie = Info.Classes.end(); it != ie; ++it) { - ClassInfo &CI = **it; - + for (const auto &CI : Info.Classes) { if (!CI.isUserClass()) continue; @@ -2075,11 +2041,9 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, OS << " MatchClassKind OpKind;\n"; OS << " switch (Operand.getReg()) {\n"; OS << " default: OpKind = InvalidMatchClass; break;\n"; - for (AsmMatcherInfo::RegisterClassesTy::iterator - it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end(); - it != ie; ++it) + for (const auto &RC : Info.RegisterClasses) OS << " case " << Info.Target.getName() << "::" - << it->first->getName() << ": OpKind = " << it->second->Name + << RC.first->getName() << ": OpKind = " << RC.second->Name << "; break;\n"; OS << " }\n"; OS << " return isSubclass(OpKind, Kind) ? " @@ -2094,7 +2058,7 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, /// emitIsSubclass - Emit the subclass predicate function. static void emitIsSubclass(CodeGenTarget &Target, - std::vector &Infos, + std::forward_list &Infos, raw_ostream &OS) { OS << "/// isSubclass - Compute whether \\p A is a subclass of \\p B.\n"; OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n"; @@ -2107,15 +2071,9 @@ static void emitIsSubclass(CodeGenTarget &Target, SS << " switch (A) {\n"; SS << " default:\n"; SS << " return false;\n"; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &A = **it; - + for (const auto &A : Infos) { std::vector SuperClasses; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &B = **it; - + for (const auto &B : Infos) { if (&A != &B && A.isSubsetOf(B)) SuperClasses.push_back(B.Name); } @@ -2157,17 +2115,14 @@ static void emitIsSubclass(CodeGenTarget &Target, /// emitMatchTokenString - Emit the function to match a token string to the /// appropriate match class value. static void emitMatchTokenString(CodeGenTarget &Target, - std::vector &Infos, + std::forward_list &Infos, raw_ostream &OS) { // Construct the match list. std::vector Matches; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &CI = **it; - + for (const auto &CI : Infos) { if (CI.Kind == ClassInfo::Token) - Matches.push_back(StringMatcher::StringPair(CI.ValueName, - "return " + CI.Name + ";")); + Matches.push_back( + StringMatcher::StringPair(CI.ValueName, "return " + CI.Name + ";")); } OS << "static MatchClassKind matchTokenString(StringRef Name) {\n"; @@ -2184,16 +2139,14 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, raw_ostream &OS) { // Construct the match list. std::vector Matches; - const std::vector &Regs = - Target.getRegBank().getRegisters(); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - if (Reg->TheDef->getValueAsString("AsmName").empty()) + const auto &Regs = Target.getRegBank().getRegisters(); + for (const CodeGenRegister &Reg : Regs) { + if (Reg.TheDef->getValueAsString("AsmName").empty()) continue; - Matches.push_back(StringMatcher::StringPair( - Reg->TheDef->getValueAsString("AsmName"), - "return " + utostr(Reg->EnumValue) + ";")); + Matches.push_back( + StringMatcher::StringPair(Reg.TheDef->getValueAsString("AsmName"), + "return " + utostr(Reg.EnumValue) + ";")); } OS << "static unsigned MatchRegisterName(StringRef Name) {\n"; @@ -2230,10 +2183,8 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, << "instruction matching.\n"; OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info) << " {\n"; - for (std::map::const_iterator - it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; } OS << " Feature_None = 0\n"; @@ -2268,10 +2219,8 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { << "static const char *getSubtargetFeatureName(uint64_t Val) {\n"; if (!Info.SubtargetFeatures.empty()) { OS << " switch(Val) {\n"; - typedef std::map RecFeatMap; - for (RecFeatMap::const_iterator it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; // FIXME: Totally just a placeholder name to get the algorithm working. OS << " case " << SFI.getEnumName() << ": return \"" << SFI.TheDef->getValueAsString("PredicateName") << "\";\n"; @@ -2295,10 +2244,8 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" << "ComputeAvailableFeatures(uint64_t FB) const {\n"; OS << " uint64_t Features = 0;\n"; - for (std::map::const_iterator - it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; OS << " if ("; std::string CondStorage = @@ -2344,7 +2291,7 @@ static std::string GetAliasRequiredFeatures(Record *R, std::string Result; unsigned NumFeatures = 0; for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) { - SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); + const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); if (!F) PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + @@ -2488,8 +2435,8 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; - OS << " " << getMinimalTypeForRange(Info.Classes.size()) - << " Class;\n"; + OS << " " << getMinimalTypeForRange(std::distance( + Info.Classes.begin(), Info.Classes.end())) << " Class;\n"; OS << " " << getMinimalTypeForRange(MaxMask) << " OperandMask;\n\n"; OS << " StringRef getMnemonic() const {\n"; @@ -2566,13 +2513,11 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, << " &Operands,\n unsigned MCK) {\n\n" << " switch(MCK) {\n"; - for (std::vector::const_iterator it = Info.Classes.begin(), - ie = Info.Classes.end(); it != ie; ++it) { - ClassInfo *CI = *it; - if (CI->ParserMethod.empty()) + for (const auto &CI : Info.Classes) { + if (CI.ParserMethod.empty()) continue; - OS << " case " << CI->Name << ":\n" - << " return " << CI->ParserMethod << "(Operands);\n"; + OS << " case " << CI.Name << ":\n" + << " return " << CI.ParserMethod << "(Operands);\n"; } OS << " default:\n"; @@ -2651,22 +2596,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // stable_sort to ensure that ambiguous instructions are still // deterministically ordered. std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(), - less_ptr()); + [](const std::unique_ptr &a, + const std::unique_ptr &b){ + return *a < *b;}); DEBUG_WITH_TYPE("instruction_info", { - for (std::vector::iterator - it = Info.Matchables.begin(), ie = Info.Matchables.end(); - it != ie; ++it) - (*it)->dump(); + for (const auto &MI : Info.Matchables) + MI->dump(); }); // Check for ambiguous matchables. DEBUG_WITH_TYPE("ambiguous_instrs", { unsigned NumAmbiguous = 0; - for (unsigned i = 0, e = Info.Matchables.size(); i != e; ++i) { - for (unsigned j = i + 1; j != e; ++j) { - MatchableInfo &A = *Info.Matchables[i]; - MatchableInfo &B = *Info.Matchables[j]; + for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E; + ++I) { + for (auto J = std::next(I); J != E; ++J) { + const MatchableInfo &A = **I; + const MatchableInfo &B = **J; if (A.couldMatchAmbiguouslyWith(B)) { errs() << "warning: ambiguous matchables:\n"; @@ -2701,15 +2647,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " void convertToMapAndConstraints(unsigned Kind,\n "; OS << " const OperandVector &Operands) override;\n"; OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) override;\n"; - OS << " unsigned MatchInstructionImpl(\n"; - OS.indent(27); - OS << "const OperandVector &Operands,\n" + OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n" << " MCInst &Inst,\n" << " uint64_t &ErrorInfo," << " bool matchingInlineAsm,\n" << " unsigned VariantID = 0);\n"; - if (Info.OperandMatchInfo.size()) { + if (!Info.OperandMatchInfo.empty()) { OS << "\n enum OperandMatchResultTy {\n"; OS << " MatchOperand_Success, // operand matched successfully\n"; OS << " MatchOperand_NoMatch, // operand did not match\n"; @@ -2786,15 +2730,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { size_t MaxNumOperands = 0; unsigned MaxMnemonicIndex = 0; bool HasDeprecation = false; - for (std::vector::const_iterator it = - Info.Matchables.begin(), ie = Info.Matchables.end(); - it != ie; ++it) { - MatchableInfo &II = **it; - MaxNumOperands = std::max(MaxNumOperands, II.AsmOperands.size()); - HasDeprecation |= II.HasDeprecation; + for (const auto &MI : Info.Matchables) { + MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size()); + HasDeprecation |= MI->HasDeprecation; // Store a pascal-style length byte in the mnemonic. - std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str(); MaxMnemonicIndex = std::max(MaxMnemonicIndex, StringTable.GetOrAddStringOffset(LenMnemonic, false)); } @@ -2822,8 +2763,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " ConvertFn;\n"; OS << " " << getMinimalRequiredFeaturesType(Info) << " RequiredFeatures;\n"; - OS << " " << getMinimalTypeForRange(Info.Classes.size()) - << " Classes[" << MaxNumOperands << "];\n"; + OS << " " << getMinimalTypeForRange( + std::distance(Info.Classes.begin(), Info.Classes.end())) + << " Classes[" << MaxNumOperands << "];\n"; OS << " StringRef getMnemonic() const {\n"; OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; OS << " MnemonicTable[Mnemonic]);\n"; @@ -2852,33 +2794,30 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "static const MatchEntry MatchTable" << VC << "[] = {\n"; - for (std::vector::const_iterator it = - Info.Matchables.begin(), ie = Info.Matchables.end(); - it != ie; ++it) { - MatchableInfo &II = **it; - if (II.AsmVariantID != AsmVariantNo) + for (const auto &MI : Info.Matchables) { + if (MI->AsmVariantID != AsmVariantNo) continue; // Store a pascal-style length byte in the mnemonic. - std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str(); OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false) - << " /* " << II.Mnemonic << " */, " + << " /* " << MI->Mnemonic << " */, " << Target.getName() << "::" - << II.getResultInst()->TheDef->getName() << ", " - << II.ConversionFnKind << ", "; + << MI->getResultInst()->TheDef->getName() << ", " + << MI->ConversionFnKind << ", "; // Write the required features mask. - if (!II.RequiredFeatures.empty()) { - for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { + if (!MI->RequiredFeatures.empty()) { + for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i) { if (i) OS << "|"; - OS << II.RequiredFeatures[i]->getEnumName(); + OS << MI->RequiredFeatures[i]->getEnumName(); } } else OS << "0"; OS << ", { "; - for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { - MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) { + const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i]; if (i) OS << ", "; OS << Op.Class->Name; @@ -2895,7 +2834,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // Find the appropriate table for this asm variant.\n"; OS << " const MatchEntry *Start, *End;\n"; OS << " switch (VariantID) {\n"; - OS << " default: // unreachable\n"; + OS << " default: llvm_unreachable(\"invalid variant!\");\n"; for (unsigned VC = 0; VC != VariantCount; ++VC) { Record *AsmVariant = Target.getAsmParserVariant(VC); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); @@ -2911,10 +2850,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Finally, build the match function. OS << "unsigned " << Target.getName() << ClassName << "::\n" - << "MatchInstructionImpl(const OperandVector" - << " &Operands,\n"; - OS << " MCInst &Inst,\n" - << "uint64_t &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n"; + << "MatchInstructionImpl(const OperandVector &Operands,\n"; + OS << " MCInst &Inst, uint64_t &ErrorInfo,\n" + << " bool matchingInlineAsm, unsigned VariantID) {\n"; OS << " // Eliminate obvious mismatches.\n"; OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; @@ -2949,7 +2887,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // Find the appropriate table for this asm variant.\n"; OS << " const MatchEntry *Start, *End;\n"; OS << " switch (VariantID) {\n"; - OS << " default: // unreachable\n"; + OS << " default: llvm_unreachable(\"invalid variant!\");\n"; for (unsigned VC = 0; VC != VariantCount; ++VC) { Record *AsmVariant = Target.getAsmParserVariant(VC); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); @@ -3018,12 +2956,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " HadMatchOtherThanFeatures = true;\n"; OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " if (CountPopulation_64(NewMissingFeatures) <=\n" - " CountPopulation_64(MissingFeatures))\n"; + OS << " if (countPopulation(NewMissingFeatures) <=\n" + " countPopulation(MissingFeatures))\n"; OS << " MissingFeatures = NewMissingFeatures;\n"; OS << " continue;\n"; OS << " }\n"; OS << "\n"; + OS << " Inst.clear();\n\n"; OS << " if (matchingInlineAsm) {\n"; OS << " Inst.setOpcode(it->Opcode);\n"; OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n"; @@ -3072,7 +3011,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " return Match_MissingFeature;\n"; OS << "}\n\n"; - if (Info.OperandMatchInfo.size()) + if (!Info.OperandMatchInfo.empty()) emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable, MaxMnemonicIndex); diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 7ef70d3..587de26 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -208,9 +208,6 @@ FindUniqueOperandCommands(std::vector &UniqueOperandCommands, // Otherwise, scan to see if all of the other instructions in this command // set share the operand. bool AllSame = true; - // Keep track of the maximum, number of operands or any - // instruction we see in the group. - size_t MaxSize = FirstInst->Operands.size(); for (NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx); NIT != InstIdxs.end(); @@ -220,10 +217,6 @@ FindUniqueOperandCommands(std::vector &UniqueOperandCommands, const AsmWriterInst *OtherInst = getAsmWriterInstByID(NIT-InstIdxs.begin()); - if (OtherInst && - OtherInst->Operands.size() > FirstInst->Operands.size()) - MaxSize = std::max(MaxSize, OtherInst->Operands.size()); - if (!OtherInst || OtherInst->Operands.size() == Op || OtherInst->Operands[Op] != FirstInst->Operands[Op]) { AllSame = false; @@ -350,7 +343,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { // in the opcode-indexed table. unsigned BitsLeft = 64-AsmStrBits; - std::vector > TableDrivenOperandPrinters; + std::vector> TableDrivenOperandPrinters; while (1) { std::vector UniqueOperandCommands; @@ -393,7 +386,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { } // Remember the handlers for this set of operands. - TableDrivenOperandPrinters.push_back(UniqueOperandCommands); + TableDrivenOperandPrinters.push_back(std::move(UniqueOperandCommands)); } @@ -474,7 +467,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { O << " switch ((Bits >> " << (64-BitsLeft) << ") & " << ((1 << NumBits)-1) << ") {\n" - << " default: // unreachable.\n"; + << " default: llvm_unreachable(\"Invalid command number.\");\n"; // Print out all the cases. for (unsigned i = 0, e = Commands.size(); i != e; ++i) { @@ -520,14 +513,23 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { O << "}\n"; } +static const char *getMinimalTypeForRange(uint64_t Range) { + assert(Range < 0xFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFF) + return "uint32_t"; + if (Range > 0xFF) + return "uint16_t"; + return "uint8_t"; +} + static void emitRegisterNameString(raw_ostream &O, StringRef AltName, - const std::vector &Registers) { + const std::deque &Registers) { SequenceToOffsetTable StringTable; SmallVector AsmNames(Registers.size()); - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Registers[i]; - std::string &AsmName = AsmNames[i]; + unsigned i = 0; + for (const auto &Reg : Registers) { + std::string &AsmName = AsmNames[i++]; // "NoRegAltName" is special. We don't need to do a lookup for that, // as it's just a reference to the default register name. @@ -564,7 +566,8 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName, StringTable.emit(O, printChar); O << " };\n\n"; - O << " static const uint32_t RegAsmOffset" << AltName << "[] = {"; + O << " static const " << getMinimalTypeForRange(StringTable.size()-1) + << " RegAsmOffset" << AltName << "[] = {"; for (unsigned i = 0, e = Registers.size(); i != e; ++i) { if ((i % 14) == 0) O << "\n "; @@ -577,8 +580,7 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName, void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { Record *AsmWriter = Target.getAsmWriter(); std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - const std::vector &Registers = - Target.getRegBank().getRegisters(); + const auto &Registers = Target.getRegBank().getRegisters(); std::vector AltNameIndices = Target.getRegAltNameIndices(); bool hasAltNames = AltNameIndices.size() > 1; @@ -602,26 +604,25 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { emitRegisterNameString(O, "", Registers); if (hasAltNames) { - O << " const uint32_t *RegAsmOffset;\n" - << " const char *AsmStrs;\n" - << " switch(AltIdx) {\n" + O << " switch(AltIdx) {\n" << " default: llvm_unreachable(\"Invalid register alt name index!\");\n"; for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) { std::string Namespace = AltNameIndices[1]->getValueAsString("Namespace"); std::string AltName(AltNameIndices[i]->getName()); - O << " case " << Namespace << "::" << AltName - << ":\n" - << " AsmStrs = AsmStrs" << AltName << ";\n" - << " RegAsmOffset = RegAsmOffset" << AltName << ";\n" - << " break;\n"; + O << " case " << Namespace << "::" << AltName << ":\n" + << " assert(*(AsmStrs" << AltName << "+RegAsmOffset" + << AltName << "[RegNo-1]) &&\n" + << " \"Invalid alt name index for register!\");\n" + << " return AsmStrs" << AltName << "+RegAsmOffset" + << AltName << "[RegNo-1];\n"; } - O << "}\n"; + O << " }\n"; + } else { + O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n" + << " \"Invalid alt name index for register!\");\n" + << " return AsmStrs+RegAsmOffset[RegNo-1];\n"; } - - O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n" - << " \"Invalid alt name index for register!\");\n" - << " return AsmStrs+RegAsmOffset[RegNo-1];\n" - << "}\n"; + O << "}\n"; } namespace { @@ -654,20 +655,26 @@ public: std::pair parseName(StringRef::iterator Start, StringRef::iterator End) { StringRef::iterator I = Start; + StringRef::iterator Next; if (*I == '{') { // ${some_name} Start = ++I; while (I != End && *I != '}') ++I; + Next = I; + // eat the final '}' + if (Next != End) + ++Next; } else { // $name, just eat the usual suspects. while (I != End && ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') || (*I >= '0' && *I <= '9') || *I == '_')) ++I; + Next = I; } - return std::make_pair(StringRef(Start, I - Start), I); + return std::make_pair(StringRef(Start, I - Start), Next); } void print(raw_ostream &O) { @@ -991,7 +998,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { return; } - if (MCOpPredicates.size()) + if (!MCOpPredicates.empty()) O << "static bool " << Target.getName() << ClassName << "ValidateMCOperand(\n" << " const MCOperand &MCOp, unsigned PredicateIndex);\n"; @@ -1057,7 +1064,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { } O << "}\n\n"; - if (MCOpPredicates.size()) { + if (!MCOpPredicates.empty()) { O << "static bool " << Target.getName() << ClassName << "ValidateMCOperand(\n" << " const MCOperand &MCOp, unsigned PredicateIndex) {\n" @@ -1084,13 +1091,10 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) { Record *AsmWriter = Target.getAsmWriter(); - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); - I != E; ++I) - if (!(*I)->AsmString.empty() && (*I)->TheDef->getName() != "PHI") + for (const CodeGenInstruction *I : Target.instructions()) + if (!I->AsmString.empty() && I->TheDef->getName() != "PHI") Instructions.push_back( - AsmWriterInst(**I, AsmWriter->getValueAsInt("Variant"), - AsmWriter->getValueAsInt("OperandSpacing"))); + AsmWriterInst(*I, AsmWriter->getValueAsInt("Variant"))); // Get the instruction numbering. NumberedInstructions = &Target.getInstructionsByEnumValue(); diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp index 5d9ead1..6ddc510 100644 --- a/utils/TableGen/AsmWriterInst.cpp +++ b/utils/TableGen/AsmWriterInst.cpp @@ -48,9 +48,7 @@ std::string AsmWriterOperand::getCode() const { /// ParseAsmString - Parse the specified Instruction's AsmString into this /// AsmWriterInst. /// -AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, - unsigned Variant, - int OperandSpacing) { +AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { this->CGI = &CGI; // NOTE: Any extensions to this code need to be mirrored in the diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h index fd77982..6a900b7 100644 --- a/utils/TableGen/AsmWriterInst.h +++ b/utils/TableGen/AsmWriterInst.h @@ -88,8 +88,7 @@ namespace llvm { const CodeGenInstruction *CGI; AsmWriterInst(const CodeGenInstruction &CGI, - unsigned Variant, - int OperandSpacing); + unsigned Variant); /// MatchesAllButOneOp - If this instruction is exactly identical to the /// specified instruction except for one differing operand, return the diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index 6a65e5e..051a7e9 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -124,7 +124,7 @@ void CallingConvEmitter::EmitAction(Record *Action, } O << "\n" << IndentStr << "};\n"; O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" - << Counter << ", " << RegList->getSize() << ")) {\n"; + << Counter << ")) {\n"; } O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " << "Reg, LocVT, LocInfo));\n"; @@ -166,7 +166,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" << RegListNumber << ", " << "RegList" << ShadowRegListNumber - << ", " << RegList->getSize() << ")) {\n"; + << ")) {\n"; } O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " << "Reg, LocVT, LocInfo));\n"; @@ -182,14 +182,14 @@ void CallingConvEmitter::EmitAction(Record *Action, O << Size << ", "; else O << "\n" << IndentStr - << " State.getMachineFunction().getSubtarget().getDataLayout()" + << " State.getMachineFunction().getTarget().getDataLayout()" "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," " "; if (Align) O << Align; else O << "\n" << IndentStr - << " State.getMachineFunction().getSubtarget().getDataLayout()" + << " State.getMachineFunction().getTarget().getDataLayout()" "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()" "))"; O << ");\n" << IndentStr @@ -215,8 +215,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << IndentStr << "unsigned Offset" << ++Counter << " = State.AllocateStack(" << Size << ", " << Align << ", " - << "ShadowRegList" << ShadowRegListNumber << ", " - << ShadowRegList->getSize() << ");\n"; + << "ShadowRegList" << ShadowRegListNumber << ");\n"; O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" << Counter << ", LocVT, LocInfo));\n"; O << IndentStr << "return false;\n"; diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 11911b6..46fcdf5 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -96,7 +96,7 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, /// generated emitter, skip it. while (NumberedOp < NumberOps && (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) || - (NamedOpIndices.size() && NamedOpIndices.count( + (!NamedOpIndices.empty() && NamedOpIndices.count( CGI.Operands.getSubOperandNumber(NumberedOp).first)))) { ++NumberedOp; diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index a750aa9..4e3e588 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -53,7 +53,7 @@ EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) { EnforceVector(TP); else { assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR || - VT == MVT::iPTRAny) && "Not a concrete type!"); + VT == MVT::iPTRAny || VT == MVT::Any) && "Not a concrete type!"); TypeVec.push_back(VT); } } @@ -1113,6 +1113,8 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { // FIXME: Should allow access to all the results here. unsigned NumDefsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; + if (InstInfo.hasTwoExplicitDefs) + ++NumDefsToAdd; // Add on one implicit def if it has a resolvable type. if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) @@ -1539,6 +1541,22 @@ static bool isOperandClass(const TreePatternNode *N, StringRef Class) { return false; } + +static void emitTooManyOperandsError(TreePattern &TP, + StringRef InstName, + unsigned Expected, + unsigned Actual) { + TP.error("Instruction '" + InstName + "' was provided " + Twine(Actual) + + " operands but expected only " + Twine(Expected) + "!"); +} + +static void emitTooFewOperandsError(TreePattern &TP, + StringRef InstName, + unsigned Actual) { + TP.error("Instruction '" + InstName + + "' expects more than the provided " + Twine(Actual) + " operands!"); +} + /// ApplyTypeConstraints - Apply all of the type constraints relevant to /// this node and its children in the tree. This returns true if it makes a /// change, false otherwise. If a type contradiction is found, flag an error. @@ -1593,11 +1611,20 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { assert(getNumTypes() == 0 && "Set doesn't produce a value"); assert(getNumChildren() >= 2 && "Missing RHS of a set?"); unsigned NC = getNumChildren(); + unsigned NumOfSrcs = NC-1; + // destination TreePatternNode *SetVal = getChild(NC-1); bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters); - for (unsigned i = 0; i < NC-1; ++i) { + // second explicit destination + if (TP.getRecord()->getValueAsBit("hasTwoExplicitDefs")) { + TreePatternNode *Set2Val = getChild(NC-2); + MadeChange = Set2Val->ApplyTypeConstraints(TP, NotRegisters); + NumOfSrcs --; + } + + for (unsigned i = 0; i < NumOfSrcs; ++i) { TreePatternNode *Child = getChild(i); MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); @@ -1741,8 +1768,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Verify that we didn't run out of provided operands. if (ChildNo >= getNumChildren()) { - TP.error("Instruction '" + getOperator()->getName() + - "' expects more operands than were provided."); + emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren()); return false; } @@ -1766,8 +1792,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // And the remaining sub-operands against subsequent children. for (unsigned Arg = 1; Arg < NumArgs; ++Arg) { if (ChildNo >= getNumChildren()) { - TP.error("Instruction '" + getOperator()->getName() + - "' expects more operands than were provided."); + emitTooFewOperandsError(TP, getOperator()->getName(), + getNumChildren()); return false; } Child = getChild(ChildNo++); @@ -1787,8 +1813,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { } if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) { - TP.error("Instruction '" + getOperator()->getName() + - "' was provided too many operands!"); + emitTooManyOperandsError(TP, getOperator()->getName(), + ChildNo, getNumChildren()); return false; } @@ -2554,8 +2580,10 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, I->error("set destination should be a register!"); DefInit *Val = dyn_cast(Dest->getLeafValue()); - if (!Val) + if (!Val) { I->error("set destination should be a register!"); + continue; + } if (Val->getDef()->isSubClassOf("RegisterClass") || Val->getDef()->isSubClassOf("ValueType") || @@ -2839,7 +2867,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( // Check that all of the results occur first in the list. std::vector Results; - TreePatternNode *Res0Node = nullptr; + SmallVector ResNode; for (unsigned i = 0; i != NumResults; ++i) { if (i == CGI.Operands.size()) I->error("'" + InstResults.begin()->first + @@ -2851,8 +2879,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( if (!RNode) I->error("Operand $" + OpName + " does not exist in operand list!"); - if (i == 0) - Res0Node = RNode; + ResNode.push_back(RNode); Record *R = cast(RNode->getLeafValue())->getDef(); if (!R) I->error("Operand $" + OpName + " should be a set destination: all " @@ -2929,7 +2956,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( GetNumNodeResults(I->getRecord(), *this)); // Copy fully inferred output node type to instruction result pattern. for (unsigned i = 0; i != NumResults; ++i) - ResultPattern->setType(i, Res0Node->getExtType(i)); + ResultPattern->setType(i, ResNode[i]->getExtType(0)); // Create and insert the instruction. // FIXME: InstImpResults should not be part of DAGInstruction. @@ -3111,13 +3138,6 @@ void CodeGenDAGPatterns::InferInstructionFlags() { CodeGenInstruction &InstInfo = const_cast(*Instructions[i]); - // Treat neverHasSideEffects = 1 as the equivalent of hasSideEffects = 0. - // This flag is obsolete and will be removed. - if (InstInfo.neverHasSideEffects) { - assert(!InstInfo.hasSideEffects); - InstInfo.hasSideEffects_Unset = false; - } - // Get the primary instruction pattern. const TreePattern *Pattern = getInstruction(InstInfo.TheDef).getPattern(); if (!Pattern) { diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index d567dde..b1e4318 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -68,10 +68,13 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { std::string PrintMethod = "printOperand"; std::string EncoderMethod; std::string OperandType = "OPERAND_UNKNOWN"; + std::string OperandNamespace = "MCOI"; unsigned NumOps = 1; DagInit *MIOpInfo = nullptr; if (Rec->isSubClassOf("RegisterOperand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); + OperandType = Rec->getValueAsString("OperandType"); + OperandNamespace = Rec->getValueAsString("OperandNamespace"); } else if (Rec->isSubClassOf("Operand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); OperandType = Rec->getValueAsString("OperandType"); @@ -113,8 +116,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { Twine(i) + " has the same name as a previous operand!"); OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, - OperandType, MIOperandNo, NumOps, - MIOpInfo)); + OperandNamespace + "::" + OperandType, + MIOperandNo, NumOps, MIOpInfo)); MIOperandNo += NumOps; } @@ -317,6 +320,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) isRegSequence = R->getValueAsBit("isRegSequence"); isExtractSubreg = R->getValueAsBit("isExtractSubreg"); isInsertSubreg = R->getValueAsBit("isInsertSubreg"); + hasTwoExplicitDefs = R->getValueAsBit("hasTwoExplicitDefs"); bool Unset; mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset); @@ -325,7 +329,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R) mayStore_Unset = Unset; hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset); hasSideEffects_Unset = Unset; - neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); @@ -335,9 +338,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R) ImplicitDefs = R->getValueAsListOfDefs("Defs"); ImplicitUses = R->getValueAsListOfDefs("Uses"); - if (neverHasSideEffects + hasSideEffects > 1) - PrintFatalError(R->getName() + ": multiple conflicting side-effect flags set!"); - // Parse Constraints. ParseConstraints(R->getValueAsString("Constraints"), Operands); @@ -541,7 +541,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, // If both are Operands with the same MVT, allow the conversion. It's // up to the user to make sure the values are appropriate, just like // for isel Pat's. - if (InstOpRec->isSubClassOf("Operand") && + if (InstOpRec->isSubClassOf("Operand") && ADI && ADI->getDef()->isSubClassOf("Operand")) { // FIXME: What other attributes should we check here? Identical // MIOperandInfo perhaps? diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 92aac5f..82b23f4 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -247,7 +247,6 @@ namespace llvm { bool isNotDuplicable : 1; bool hasSideEffects : 1; bool hasSideEffects_Unset : 1; - bool neverHasSideEffects : 1; bool isAsCheapAsAMove : 1; bool hasExtraSrcRegAllocReq : 1; bool hasExtraDefRegAllocReq : 1; @@ -256,6 +255,7 @@ namespace llvm { bool isRegSequence : 1; bool isExtractSubreg : 1; bool isInsertSubreg : 1; + bool hasTwoExplicitDefs : 1; std::string DeprecatedReason; bool HasComplexDeprecationPredicate; diff --git a/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp index 7e5aa9c..8abea48 100644 --- a/utils/TableGen/CodeGenMapTable.cpp +++ b/utils/TableGen/CodeGenMapTable.cpp @@ -376,7 +376,7 @@ unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) { std::vector ColInstrs = MapTable[CurInstr]; std::string OutStr(""); unsigned RelExists = 0; - if (ColInstrs.size()) { + if (!ColInstrs.empty()) { for (unsigned j = 0; j < NumCol; j++) { if (ColInstrs[j] != nullptr) { RelExists = 1; @@ -567,7 +567,7 @@ void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) { std::vector InstrMapVec; InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); - if (!InstrMapVec.size()) + if (InstrMapVec.empty()) return; OS << "#ifdef GET_INSTRMAP_INFO\n"; diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 678222f..37f8905 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -82,7 +82,7 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { } } -unsigned CodeGenSubRegIndex::computeLaneMask() { +unsigned CodeGenSubRegIndex::computeLaneMask() const { // Already computed? if (LaneMask) return LaneMask; @@ -92,8 +92,8 @@ unsigned CodeGenSubRegIndex::computeLaneMask() { // The lane mask is simply the union of all sub-indices. unsigned M = 0; - for (CompMap::iterator I = Composed.begin(), E = Composed.end(); I != E; ++I) - M |= I->second->computeLaneMask(); + for (const auto &C : Composed) + M |= C.second->computeLaneMask(); assert(M && "Missing lane mask, sub-register cycle?"); LaneMask = M; return LaneMask; @@ -108,7 +108,6 @@ CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum) EnumValue(Enum), CostPerUse(R->getValueAsInt("CostPerUse")), CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")), - NumNativeRegUnits(0), SubRegsComplete(false), SuperRegsComplete(false), TopoSig(~0u) @@ -146,17 +145,18 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) { } const std::string &CodeGenRegister::getName() const { + assert(TheDef && "no def"); return TheDef->getName(); } namespace { // Iterate over all register units in a set of registers. class RegUnitIterator { - CodeGenRegister::Set::const_iterator RegI, RegE; - CodeGenRegister::RegUnitList::const_iterator UnitI, UnitE; + CodeGenRegister::Vec::const_iterator RegI, RegE; + CodeGenRegister::RegUnitList::iterator UnitI, UnitE; public: - RegUnitIterator(const CodeGenRegister::Set &Regs): + RegUnitIterator(const CodeGenRegister::Vec &Regs): RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() { if (RegI != RegE) { @@ -191,32 +191,23 @@ protected: }; } // namespace -// Merge two RegUnitLists maintaining the order and removing duplicates. -// Overwrites MergedRU in the process. -static void mergeRegUnits(CodeGenRegister::RegUnitList &MergedRU, - const CodeGenRegister::RegUnitList &RRU) { - CodeGenRegister::RegUnitList LRU = MergedRU; - MergedRU.clear(); - std::set_union(LRU.begin(), LRU.end(), RRU.begin(), RRU.end(), - std::back_inserter(MergedRU)); -} - // Return true of this unit appears in RegUnits. static bool hasRegUnit(CodeGenRegister::RegUnitList &RegUnits, unsigned Unit) { - return std::count(RegUnits.begin(), RegUnits.end(), Unit); + return RegUnits.test(Unit); } // Inherit register units from subregisters. // Return true if the RegUnits changed. bool CodeGenRegister::inheritRegUnits(CodeGenRegBank &RegBank) { - unsigned OldNumUnits = RegUnits.size(); + bool changed = false; for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end(); I != E; ++I) { CodeGenRegister *SR = I->second; // Merge the subregister's units into this register's RegUnits. - mergeRegUnits(RegUnits, SR->RegUnits); + changed |= (RegUnits |= SR->RegUnits); } - return OldNumUnits != RegUnits.size(); + + return changed; } const CodeGenRegister::SubRegMap & @@ -362,14 +353,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { // sub-registers, the other registers won't contribute any more units. for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) { CodeGenRegister *SR = ExplicitSubRegs[i]; - // Explicit sub-registers are usually disjoint, so this is a good way of - // computing the union. We may pick up a few duplicates that will be - // eliminated below. - unsigned N = RegUnits.size(); - RegUnits.append(SR->RegUnits.begin(), SR->RegUnits.end()); - std::inplace_merge(RegUnits.begin(), RegUnits.begin() + N, RegUnits.end()); + RegUnits |= SR->RegUnits; } - RegUnits.erase(std::unique(RegUnits.begin(), RegUnits.end()), RegUnits.end()); // Absent any ad hoc aliasing, we create one register unit per leaf register. // These units correspond to the maximal cliques in the register overlap @@ -388,19 +373,19 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { // Create a RegUnit representing this alias edge, and add it to both // registers. unsigned Unit = RegBank.newRegUnit(this, AR); - RegUnits.push_back(Unit); - AR->RegUnits.push_back(Unit); + RegUnits.set(Unit); + AR->RegUnits.set(Unit); } // Finally, create units for leaf registers without ad hoc aliases. Note that // a leaf register with ad hoc aliases doesn't get its own unit - it isn't // necessary. This means the aliasing leaf registers can share a single unit. if (RegUnits.empty()) - RegUnits.push_back(RegBank.newRegUnit(this)); + RegUnits.set(RegBank.newRegUnit(this)); // We have now computed the native register units. More may be adopted later // for balancing purposes. - NumNativeRegUnits = RegUnits.size(); + NativeRegUnits = RegUnits; return SubRegs; } @@ -534,7 +519,7 @@ CodeGenRegister::addSubRegsPreOrder(SetVector &OSet, // Get the sum of this register's unit weights. unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const { unsigned Weight = 0; - for (RegUnitList::const_iterator I = RegUnits.begin(), E = RegUnits.end(); + for (RegUnitList::iterator I = RegUnits.begin(), E = RegUnits.end(); I != E; ++I) { Weight += RegBank.getRegUnit(*I).Weight; } @@ -657,17 +642,21 @@ struct TupleExpander : SetTheory::Expander { // CodeGenRegisterClass //===----------------------------------------------------------------------===// +static void sortAndUniqueRegisters(CodeGenRegister::Vec &M) { + std::sort(M.begin(), M.end(), deref()); + M.erase(std::unique(M.begin(), M.end(), deref()), M.end()); +} + CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) : TheDef(R), Name(R->getName()), TopoSigs(RegBank.getNumTopoSigs()), - EnumValue(-1) { + EnumValue(-1), + LaneMask(0) { // Rename anonymous register classes. if (R->getName().size() > 9 && R->getName()[9] == '.') { static unsigned AnonCounter = 0; - R->setName("AnonRegClass_" + utostr(AnonCounter)); - // MSVC2012 ICEs if AnonCounter++ is directly passed to utostr. - ++AnonCounter; + R->setName("AnonRegClass_" + utostr(AnonCounter++)); } std::vector TypeList = R->getValueAsListOfDefs("RegTypes"); @@ -689,9 +678,10 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) for (unsigned i = 0, e = Elements->size(); i != e; ++i) { Orders[0].push_back((*Elements)[i]); const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]); - Members.insert(Reg); + Members.push_back(Reg); TopoSigs.set(Reg->getTopoSig()); } + sortAndUniqueRegisters(Members); // Alternative allocation orders may be subsets. SetTheory::RecSet Order; @@ -733,9 +723,8 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, SpillAlignment(Props.SpillAlignment), CopyCost(0), Allocatable(true) { - for (CodeGenRegister::Set::iterator I = Members.begin(), E = Members.end(); - I != E; ++I) - TopoSigs.set((*I)->getTopoSig()); + for (const auto R : Members) + TopoSigs.set(R->getTopoSig()); } // Compute inherited propertied for a synthesized register class. @@ -764,15 +753,15 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) { } bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const { - return Members.count(Reg); + return std::binary_search(Members.begin(), Members.end(), Reg, + deref()); } namespace llvm { raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) { OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment; - for (CodeGenRegister::Set::const_iterator I = K.Members->begin(), - E = K.Members->end(); I != E; ++I) - OS << ", " << (*I)->getName(); + for (const auto R : *K.Members) + OS << ", " << R->getName(); return OS << " }"; } } @@ -798,10 +787,10 @@ operator<(const CodeGenRegisterClass::Key &B) const { static bool testSubClass(const CodeGenRegisterClass *A, const CodeGenRegisterClass *B) { return A->SpillAlignment && B->SpillAlignment % A->SpillAlignment == 0 && - A->SpillSize <= B->SpillSize && - std::includes(A->getMembers().begin(), A->getMembers().end(), - B->getMembers().begin(), B->getMembers().end(), - CodeGenRegister::Less()); + A->SpillSize <= B->SpillSize && + std::includes(A->getMembers().begin(), A->getMembers().end(), + B->getMembers().begin(), B->getMembers().end(), + deref()); } /// Sorting predicate for register classes. This provides a topological @@ -810,34 +799,34 @@ static bool testSubClass(const CodeGenRegisterClass *A, /// Register classes with the same registers, spill size, and alignment form a /// clique. They will be ordered alphabetically. /// -static int TopoOrderRC(CodeGenRegisterClass *const *PA, - CodeGenRegisterClass *const *PB) { - const CodeGenRegisterClass *A = *PA; - const CodeGenRegisterClass *B = *PB; +static bool TopoOrderRC(const CodeGenRegisterClass &PA, + const CodeGenRegisterClass &PB) { + auto *A = &PA; + auto *B = &PB; if (A == B) return 0; // Order by ascending spill size. if (A->SpillSize < B->SpillSize) - return -1; + return true; if (A->SpillSize > B->SpillSize) - return 1; + return false; // Order by ascending spill alignment. if (A->SpillAlignment < B->SpillAlignment) - return -1; + return true; if (A->SpillAlignment > B->SpillAlignment) - return 1; + return false; // Order by descending set size. Note that the classes' allocation order may // not have been computed yet. The Members set is always vaild. if (A->getMembers().size() > B->getMembers().size()) - return -1; + return true; if (A->getMembers().size() < B->getMembers().size()) - return 1; + return false; // Finally order by name as a tie breaker. - return StringRef(A->getName()).compare(B->getName()); + return StringRef(A->getName()) < B->getName(); } std::string CodeGenRegisterClass::getQualifiedName() const { @@ -850,55 +839,56 @@ std::string CodeGenRegisterClass::getQualifiedName() const { // Compute sub-classes of all register classes. // Assume the classes are ordered topologically. void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) { - ArrayRef RegClasses = RegBank.getRegClasses(); + auto &RegClasses = RegBank.getRegClasses(); // Visit backwards so sub-classes are seen first. - for (unsigned rci = RegClasses.size(); rci; --rci) { - CodeGenRegisterClass &RC = *RegClasses[rci - 1]; + for (auto I = RegClasses.rbegin(), E = RegClasses.rend(); I != E; ++I) { + CodeGenRegisterClass &RC = *I; RC.SubClasses.resize(RegClasses.size()); RC.SubClasses.set(RC.EnumValue); // Normally, all subclasses have IDs >= rci, unless RC is part of a clique. - for (unsigned s = rci; s != RegClasses.size(); ++s) { - if (RC.SubClasses.test(s)) + for (auto I2 = I.base(), E2 = RegClasses.end(); I2 != E2; ++I2) { + CodeGenRegisterClass &SubRC = *I2; + if (RC.SubClasses.test(SubRC.EnumValue)) continue; - CodeGenRegisterClass *SubRC = RegClasses[s]; - if (!testSubClass(&RC, SubRC)) + if (!testSubClass(&RC, &SubRC)) continue; // SubRC is a sub-class. Grap all its sub-classes so we won't have to // check them again. - RC.SubClasses |= SubRC->SubClasses; + RC.SubClasses |= SubRC.SubClasses; } // Sweep up missed clique members. They will be immediately preceding RC. - for (unsigned s = rci - 1; s && testSubClass(&RC, RegClasses[s - 1]); --s) - RC.SubClasses.set(s - 1); + for (auto I2 = std::next(I); I2 != E && testSubClass(&RC, &*I2); ++I2) + RC.SubClasses.set(I2->EnumValue); } // Compute the SuperClasses lists from the SubClasses vectors. - for (unsigned rci = 0; rci != RegClasses.size(); ++rci) { - const BitVector &SC = RegClasses[rci]->getSubClasses(); - for (int s = SC.find_first(); s >= 0; s = SC.find_next(s)) { - if (unsigned(s) == rci) + for (auto &RC : RegClasses) { + const BitVector &SC = RC.getSubClasses(); + auto I = RegClasses.begin(); + for (int s = 0, next_s = SC.find_first(); next_s != -1; + next_s = SC.find_next(s)) { + std::advance(I, next_s - s); + s = next_s; + if (&*I == &RC) continue; - RegClasses[s]->SuperClasses.push_back(RegClasses[rci]); + I->SuperClasses.push_back(&RC); } } // With the class hierarchy in place, let synthesized register classes inherit // properties from their closest super-class. The iteration order here can // propagate properties down multiple levels. - for (unsigned rci = 0; rci != RegClasses.size(); ++rci) - if (!RegClasses[rci]->getDef()) - RegClasses[rci]->inheritProperties(RegBank); + for (auto &RC : RegClasses) + if (!RC.getDef()) + RC.inheritProperties(RegBank); } -void -CodeGenRegisterClass::getSuperRegClasses(CodeGenSubRegIndex *SubIdx, - BitVector &Out) const { - DenseMap >::const_iterator - FindI = SuperRegClasses.find(SubIdx); +void CodeGenRegisterClass::getSuperRegClasses(const CodeGenSubRegIndex *SubIdx, + BitVector &Out) const { + auto FindI = SuperRegClasses.find(SubIdx); if (FindI == SuperRegClasses.end()) return; for (CodeGenRegisterClass *RC : FindI->second) @@ -933,13 +923,12 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { for (unsigned i = 0, e = SRIs.size(); i != e; ++i) getSubRegIdx(SRIs[i]); // Build composite maps from ComposedOf fields. - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) - SubRegIndices[i]->updateComponents(*this); + for (auto &Idx : SubRegIndices) + Idx.updateComponents(*this); // Read in the register definitions. std::vector Regs = Records.getAllDerivedDefinitions("Register"); std::sort(Regs.begin(), Regs.end(), LessRecordRegister()); - Registers.reserve(Regs.size()); // Assign the enumeration values. for (unsigned i = 0, e = Regs.size(); i != e; ++i) getReg(Regs[i]); @@ -948,45 +937,41 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { std::vector Tups = Records.getAllDerivedDefinitions("RegisterTuples"); - std::vector TupRegsCopy; - for (unsigned i = 0, e = Tups.size(); i != e; ++i) { - const std::vector *TupRegs = Sets.expand(Tups[i]); - TupRegsCopy.reserve(TupRegs->size()); - TupRegsCopy.assign(TupRegs->begin(), TupRegs->end()); - std::sort(TupRegsCopy.begin(), TupRegsCopy.end(), LessRecordRegister()); - for (unsigned j = 0, je = TupRegsCopy.size(); j != je; ++j) - getReg((TupRegsCopy)[j]); - TupRegsCopy.clear(); + for (Record *R : Tups) { + std::vector TupRegs = *Sets.expand(R); + std::sort(TupRegs.begin(), TupRegs.end(), LessRecordRegister()); + for (Record *RC : TupRegs) + getReg(RC); } // Now all the registers are known. Build the object graph of explicit // register-register references. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - Registers[i]->buildObjectGraph(*this); + for (auto &Reg : Registers) + Reg.buildObjectGraph(*this); // Compute register name map. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) + for (auto &Reg : Registers) // FIXME: This could just be RegistersByName[name] = register, except that // causes some failures in MIPS - perhaps they have duplicate register name // entries? (or maybe there's a reason for it - I don't know much about this // code, just drive-by refactoring) - RegistersByName.insert(std::make_pair( - Registers[i]->TheDef->getValueAsString("AsmName"), Registers[i])); + RegistersByName.insert( + std::make_pair(Reg.TheDef->getValueAsString("AsmName"), &Reg)); // Precompute all sub-register maps. // This will create Composite entries for all inferred sub-register indices. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - Registers[i]->computeSubRegs(*this); + for (auto &Reg : Registers) + Reg.computeSubRegs(*this); // Infer even more sub-registers by combining leading super-registers. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - if (Registers[i]->CoveredBySubRegs) - Registers[i]->computeSecondarySubRegs(*this); + for (auto &Reg : Registers) + if (Reg.CoveredBySubRegs) + Reg.computeSecondarySubRegs(*this); // After the sub-register graph is complete, compute the topologically // ordered SuperRegs list. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - Registers[i]->computeSuperRegs(*this); + for (auto &Reg : Registers) + Reg.computeSuperRegs(*this); // Native register units are associated with a leaf register. They've all been // discovered now. @@ -998,35 +983,35 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { PrintFatalError("No 'RegisterClass' subclasses defined!"); // Allocate user-defined register classes. - RegClasses.reserve(RCs.size()); - for (unsigned i = 0, e = RCs.size(); i != e; ++i) - addToMaps(new CodeGenRegisterClass(*this, RCs[i])); + for (auto *RC : RCs) { + RegClasses.push_back(CodeGenRegisterClass(*this, RC)); + addToMaps(&RegClasses.back()); + } // Infer missing classes to create a full algebra. computeInferredRegisterClasses(); // Order register classes topologically and assign enum values. - array_pod_sort(RegClasses.begin(), RegClasses.end(), TopoOrderRC); - for (unsigned i = 0, e = RegClasses.size(); i != e; ++i) - RegClasses[i]->EnumValue = i; + RegClasses.sort(TopoOrderRC); + unsigned i = 0; + for (auto &RC : RegClasses) + RC.EnumValue = i++; CodeGenRegisterClass::computeSubClasses(*this); } // Create a synthetic CodeGenSubRegIndex without a corresponding Record. CodeGenSubRegIndex* CodeGenRegBank::createSubRegIndex(StringRef Name, StringRef Namespace) { - CodeGenSubRegIndex *Idx = new CodeGenSubRegIndex(Name, Namespace, - SubRegIndices.size() + 1); - SubRegIndices.push_back(Idx); - return Idx; + SubRegIndices.emplace_back(Name, Namespace, SubRegIndices.size() + 1); + return &SubRegIndices.back(); } CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) { CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def]; if (Idx) return Idx; - Idx = new CodeGenSubRegIndex(Def, SubRegIndices.size() + 1); - SubRegIndices.push_back(Idx); + SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1); + Idx = &SubRegIndices.back(); return Idx; } @@ -1034,14 +1019,12 @@ CodeGenRegister *CodeGenRegBank::getReg(Record *Def) { CodeGenRegister *&Reg = Def2Reg[Def]; if (Reg) return Reg; - Reg = new CodeGenRegister(Def, Registers.size() + 1); - Registers.push_back(Reg); + Registers.emplace_back(Def, Registers.size() + 1); + Reg = &Registers.back(); return Reg; } void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) { - RegClasses.push_back(RC); - if (Record *Def = RC->getDef()) Def2RC.insert(std::make_pair(Def, RC)); @@ -1054,7 +1037,7 @@ void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) { // Create a synthetic sub-class if it is missing. CodeGenRegisterClass* CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC, - const CodeGenRegister::Set *Members, + const CodeGenRegister::Vec *Members, StringRef Name) { // Synthetic sub-class has the same size and alignment as RC. CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment); @@ -1063,9 +1046,9 @@ CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC, return FoundI->second; // Sub-class doesn't exist, create a new one. - CodeGenRegisterClass *NewRC = new CodeGenRegisterClass(*this, Name, K); - addToMaps(NewRC); - return NewRC; + RegClasses.push_back(CodeGenRegisterClass(*this, Name, K)); + addToMaps(&RegClasses.back()); + return &RegClasses.back(); } CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) { @@ -1126,21 +1109,19 @@ void CodeGenRegBank::computeComposites() { // and many registers will share TopoSigs on regular architectures. BitVector TopoSigs(getNumTopoSigs()); - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - CodeGenRegister *Reg1 = Registers[i]; - + for (const auto &Reg1 : Registers) { // Skip identical subreg structures already processed. - if (TopoSigs.test(Reg1->getTopoSig())) + if (TopoSigs.test(Reg1.getTopoSig())) continue; - TopoSigs.set(Reg1->getTopoSig()); + TopoSigs.set(Reg1.getTopoSig()); - const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs(); + const CodeGenRegister::SubRegMap &SRM1 = Reg1.getSubRegs(); for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(), e1 = SRM1.end(); i1 != e1; ++i1) { CodeGenSubRegIndex *Idx1 = i1->first; CodeGenRegister *Reg2 = i1->second; // Ignore identity compositions. - if (Reg1 == Reg2) + if (&Reg1 == Reg2) continue; const CodeGenRegister::SubRegMap &SRM2 = Reg2->getSubRegs(); // Try composing Idx1 with another SubRegIndex. @@ -1152,7 +1133,7 @@ void CodeGenRegBank::computeComposites() { if (Reg2 == Reg3) continue; // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3. - CodeGenSubRegIndex *Idx3 = Reg1->getSubRegIndex(Reg3); + CodeGenSubRegIndex *Idx3 = Reg1.getSubRegIndex(Reg3); assert(Idx3 && "Sub-register doesn't have an index"); // Conflicting composition? Emit a warning but allow it. @@ -1173,15 +1154,14 @@ void CodeGenRegBank::computeComposites() { // // Conservatively share a lane mask bit if two sub-register indices overlap in // some registers, but not in others. That shouldn't happen a lot. -void CodeGenRegBank::computeSubRegIndexLaneMasks() { +void CodeGenRegBank::computeSubRegLaneMasks() { // First assign individual bits to all the leaf indices. unsigned Bit = 0; // Determine mask of lanes that cover their registers. CoveringLanes = ~0u; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - CodeGenSubRegIndex *Idx = SubRegIndices[i]; - if (Idx->getComposites().empty()) { - Idx->LaneMask = 1u << Bit; + for (auto &Idx : SubRegIndices) { + if (Idx.getComposites().empty()) { + Idx.LaneMask = 1u << Bit; // Share bit 31 in the unlikely case there are more than 32 leafs. // // Sharing bits is harmless; it allows graceful degradation in targets @@ -1196,7 +1176,71 @@ void CodeGenRegBank::computeSubRegIndexLaneMasks() { // is no longer covering its registers. CoveringLanes &= ~(1u << Bit); } else { - Idx->LaneMask = 0; + Idx.LaneMask = 0; + } + } + + // Compute transformation sequences for composeSubRegIndexLaneMask. The idea + // here is that for each possible target subregister we look at the leafs + // in the subregister graph that compose for this target and create + // transformation sequences for the lanemasks. Each step in the sequence + // consists of a bitmask and a bitrotate operation. As the rotation amounts + // are usually the same for many subregisters we can easily combine the steps + // by combining the masks. + for (const auto &Idx : SubRegIndices) { + const auto &Composites = Idx.getComposites(); + auto &LaneTransforms = Idx.CompositionLaneMaskTransform; + // Go through all leaf subregisters and find the ones that compose with Idx. + // These make out all possible valid bits in the lane mask we want to + // transform. Looking only at the leafs ensure that only a single bit in + // the mask is set. + unsigned NextBit = 0; + for (auto &Idx2 : SubRegIndices) { + // Skip non-leaf subregisters. + if (!Idx2.getComposites().empty()) + continue; + // Replicate the behaviour from the lane mask generation loop above. + unsigned SrcBit = NextBit; + unsigned SrcMask = 1u << SrcBit; + if (NextBit < 31) + ++NextBit; + assert(Idx2.LaneMask == SrcMask); + + // Get the composed subregister if there is any. + auto C = Composites.find(&Idx2); + if (C == Composites.end()) + continue; + const CodeGenSubRegIndex *Composite = C->second; + // The Composed subreg should be a leaf subreg too + assert(Composite->getComposites().empty()); + + // Create Mask+Rotate operation and merge with existing ops if possible. + unsigned DstBit = Log2_32(Composite->LaneMask); + int Shift = DstBit - SrcBit; + uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift : 32+Shift; + for (auto &I : LaneTransforms) { + if (I.RotateLeft == RotateLeft) { + I.Mask |= SrcMask; + SrcMask = 0; + } + } + if (SrcMask != 0) { + MaskRolPair MaskRol = { SrcMask, RotateLeft }; + LaneTransforms.push_back(MaskRol); + } + } + // Optimize if the transformation consists of one step only: Set mask to + // 0xffffffff (including some irrelevant invalid bits) so that it should + // merge with more entries later while compressing the table. + if (LaneTransforms.size() == 1) + LaneTransforms[0].Mask = ~0u; + + // Further compression optimization: For invalid compositions resulting + // in a sequence with 0 entries we can just pick any other. Choose + // Mask 0xffffffff with Rotation 0. + if (LaneTransforms.size() == 0) { + MaskRolPair P = { ~0u, 0 }; + LaneTransforms.push_back(P); } } @@ -1204,13 +1248,24 @@ void CodeGenRegBank::computeSubRegIndexLaneMasks() { // by the sub-register graph? This doesn't occur in any known targets. // Inherit lanes from composites. - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - unsigned Mask = SubRegIndices[i]->computeLaneMask(); + for (const auto &Idx : SubRegIndices) { + unsigned Mask = Idx.computeLaneMask(); // If some super-registers without CoveredBySubRegs use this index, we can // no longer assume that the lanes are covering their registers. - if (!SubRegIndices[i]->AllSuperRegsCovered) + if (!Idx.AllSuperRegsCovered) CoveringLanes &= ~Mask; } + + // Compute lane mask combinations for register classes. + for (auto &RegClass : RegClasses) { + unsigned LaneMask = 0; + for (const auto &SubRegIndex : SubRegIndices) { + if (RegClass.getSubClassWithSubReg(&SubRegIndex) != &RegClass) + continue; + LaneMask |= SubRegIndex.LaneMask; + } + RegClass.LaneMask = LaneMask; + } } namespace { @@ -1231,7 +1286,7 @@ namespace { // for which the unit weight equals the set weight. These units should not have // their weight increased. struct UberRegSet { - CodeGenRegister::Set Regs; + CodeGenRegister::Vec Regs; unsigned Weight; CodeGenRegister::RegUnitList SingularDeterminants; @@ -1247,22 +1302,20 @@ static void computeUberSets(std::vector &UberSets, std::vector &RegSets, CodeGenRegBank &RegBank) { - const std::vector &Registers = RegBank.getRegisters(); + const auto &Registers = RegBank.getRegisters(); // The Register EnumValue is one greater than its index into Registers. - assert(Registers.size() == Registers[Registers.size()-1]->EnumValue && + assert(Registers.size() == Registers.back().EnumValue && "register enum value mismatch"); // For simplicitly make the SetID the same as EnumValue. IntEqClasses UberSetIDs(Registers.size()+1); std::set AllocatableRegs; - for (unsigned i = 0, e = RegBank.getRegClasses().size(); i != e; ++i) { - - CodeGenRegisterClass *RegClass = RegBank.getRegClasses()[i]; - if (!RegClass->Allocatable) + for (auto &RegClass : RegBank.getRegClasses()) { + if (!RegClass.Allocatable) continue; - const CodeGenRegister::Set &Regs = RegClass->getMembers(); + const CodeGenRegister::Vec &Regs = RegClass.getMembers(); if (Regs.empty()) continue; @@ -1270,15 +1323,14 @@ static void computeUberSets(std::vector &UberSets, assert(USetID && "register number 0 is invalid"); AllocatableRegs.insert((*Regs.begin())->EnumValue); - for (CodeGenRegister::Set::const_iterator I = std::next(Regs.begin()), - E = Regs.end(); I != E; ++I) { + for (auto I = std::next(Regs.begin()), E = Regs.end(); I != E; ++I) { AllocatableRegs.insert((*I)->EnumValue); UberSetIDs.join(USetID, (*I)->EnumValue); } } // Combine non-allocatable regs. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - unsigned RegNum = Registers[i]->EnumValue; + for (const auto &Reg : Registers) { + unsigned RegNum = Reg.EnumValue; if (AllocatableRegs.count(RegNum)) continue; @@ -1292,17 +1344,18 @@ static void computeUberSets(std::vector &UberSets, // Insert Registers into the UberSets formed by union-find. // Do not resize after this. UberSets.resize(UberSetIDs.getNumClasses()); - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - const CodeGenRegister *Reg = Registers[i]; - unsigned USetID = UberSetIDs[Reg->EnumValue]; + unsigned i = 0; + for (const CodeGenRegister &Reg : Registers) { + unsigned USetID = UberSetIDs[Reg.EnumValue]; if (!USetID) USetID = ZeroID; else if (USetID == ZeroID) USetID = 0; UberRegSet *USet = &UberSets[USetID]; - USet->Regs.insert(Reg); - RegSets[i] = USet; + USet->Regs.push_back(&Reg); + sortAndUniqueRegisters(USet->Regs); + RegSets[i++] = USet; } } @@ -1335,22 +1388,18 @@ static void computeUberWeights(std::vector &UberSets, if (I->Weight != MaxWeight) { DEBUG( dbgs() << "UberSet " << I - UberSets.begin() << " Weight " << MaxWeight; - for (CodeGenRegister::Set::iterator - UnitI = I->Regs.begin(), UnitE = I->Regs.end(); - UnitI != UnitE; ++UnitI) { - dbgs() << " " << (*UnitI)->getName(); - } + for (auto &Unit : I->Regs) + dbgs() << " " << Unit->getName(); dbgs() << "\n"); // Update the set weight. I->Weight = MaxWeight; } // Find singular determinants. - for (CodeGenRegister::Set::iterator RegI = I->Regs.begin(), - RegE = I->Regs.end(); RegI != RegE; ++RegI) { - if ((*RegI)->getRegUnits().size() == 1 - && (*RegI)->getWeight(RegBank) == I->Weight) - mergeRegUnits(I->SingularDeterminants, (*RegI)->getRegUnits()); + for (const auto R : I->Regs) { + if (R->getRegUnits().count() == 1 && R->getWeight(RegBank) == I->Weight) { + I->SingularDeterminants |= R->getRegUnits(); + } } } } @@ -1368,13 +1417,14 @@ static void computeUberWeights(std::vector &UberSets, static bool normalizeWeight(CodeGenRegister *Reg, std::vector &UberSets, std::vector &RegSets, - std::set &NormalRegs, + SparseBitVector<> &NormalRegs, CodeGenRegister::RegUnitList &NormalUnits, CodeGenRegBank &RegBank) { - bool Changed = false; - if (!NormalRegs.insert(Reg->EnumValue).second) - return Changed; + if (NormalRegs.test(Reg->EnumValue)) + return false; + NormalRegs.set(Reg->EnumValue); + bool Changed = false; const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs(); for (CodeGenRegister::SubRegMap::const_iterator SRI = SRM.begin(), SRE = SRM.end(); SRI != SRE; ++SRI) { @@ -1398,8 +1448,8 @@ static bool normalizeWeight(CodeGenRegister *Reg, // A register unit's weight can be adjusted only if it is the singular unit // for this register, has not been used to normalize a subregister's set, // and has not already been used to singularly determine this UberRegSet. - unsigned AdjustUnit = Reg->getRegUnits().front(); - if (Reg->getRegUnits().size() != 1 + unsigned AdjustUnit = *Reg->getRegUnits().begin(); + if (Reg->getRegUnits().count() != 1 || hasRegUnit(NormalUnits, AdjustUnit) || hasRegUnit(UberSet->SingularDeterminants, AdjustUnit)) { // We don't have an adjustable unit, so adopt a new one. @@ -1417,7 +1467,7 @@ static bool normalizeWeight(CodeGenRegister *Reg, } // Mark these units normalized so superregisters can't change their weights. - mergeRegUnits(NormalUnits, Reg->getRegUnits()); + NormalUnits |= Reg->getRegUnits(); return Changed; } @@ -1440,11 +1490,11 @@ void CodeGenRegBank::computeRegUnitWeights() { for (bool Changed = true; Changed; ++NumIters) { assert(NumIters <= NumNativeRegUnits && "Runaway register unit weights"); Changed = false; - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + for (auto &Reg : Registers) { CodeGenRegister::RegUnitList NormalUnits; - std::set NormalRegs; - Changed |= normalizeWeight(Registers[i], UberSets, RegSets, - NormalRegs, NormalUnits, *this); + SparseBitVector<> NormalRegs; + Changed |= normalizeWeight(&Reg, UberSets, RegSets, NormalRegs, + NormalUnits, *this); } } } @@ -1535,18 +1585,17 @@ void CodeGenRegBank::computeRegUnitSets() { assert(RegUnitSets.empty() && "dirty RegUnitSets"); // Compute a unique RegUnitSet for each RegClass. - ArrayRef RegClasses = getRegClasses(); - unsigned NumRegClasses = RegClasses.size(); - for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { - if (!RegClasses[RCIdx]->Allocatable) + auto &RegClasses = getRegClasses(); + for (auto &RC : RegClasses) { + if (!RC.Allocatable) continue; // Speculatively grow the RegUnitSets to hold the new set. RegUnitSets.resize(RegUnitSets.size() + 1); - RegUnitSets.back().Name = RegClasses[RCIdx]->getName(); + RegUnitSets.back().Name = RC.getName(); // Compute a sorted list of units in this class. - RegClasses[RCIdx]->buildRegUnitSet(RegUnitSets.back().Units); + RC.buildRegUnitSet(RegUnitSets.back().Units); // Find an existing RegUnitSet. std::vector::const_iterator SetI = @@ -1560,9 +1609,8 @@ void CodeGenRegBank::computeRegUnitSets() { USIdx < USEnd; ++USIdx) { dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name << ":"; - ArrayRef Units = RegUnitSets[USIdx].Units; - for (unsigned i = 0, e = Units.size(); i < e; ++i) - dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName(); + for (auto &U : RegUnitSets[USIdx].Units) + dbgs() << " " << RegUnits[U].Roots[0]->getName(); dbgs() << "\n"; }); @@ -1574,9 +1622,8 @@ void CodeGenRegBank::computeRegUnitSets() { USIdx < USEnd; ++USIdx) { dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name << ":"; - ArrayRef Units = RegUnitSets[USIdx].Units; - for (unsigned i = 0, e = Units.size(); i < e; ++i) - dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName(); + for (auto &U : RegUnitSets[USIdx].Units) + dbgs() << " " << RegUnits[U].Roots[0]->getName(); dbgs() << "\n"; } dbgs() << "\nUnion sets:\n"); @@ -1621,9 +1668,8 @@ void CodeGenRegBank::computeRegUnitSets() { else { DEBUG(dbgs() << "UnitSet " << RegUnitSets.size()-1 << " " << RegUnitSets.back().Name << ":"; - ArrayRef Units = RegUnitSets.back().Units; - for (unsigned i = 0, e = Units.size(); i < e; ++i) - dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName(); + for (auto &U : RegUnitSets.back().Units) + dbgs() << " " << RegUnits[U].Roots[0]->getName(); dbgs() << "\n";); } } @@ -1637,29 +1683,30 @@ void CodeGenRegBank::computeRegUnitSets() { USIdx < USEnd; ++USIdx) { dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name << ":"; - ArrayRef Units = RegUnitSets[USIdx].Units; - for (unsigned i = 0, e = Units.size(); i < e; ++i) - dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName(); + for (auto &U : RegUnitSets[USIdx].Units) + dbgs() << " " << RegUnits[U].Roots[0]->getName(); dbgs() << "\n"; }); // For each register class, list the UnitSets that are supersets. - RegClassUnitSets.resize(NumRegClasses); - for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { - if (!RegClasses[RCIdx]->Allocatable) + RegClassUnitSets.resize(RegClasses.size()); + int RCIdx = -1; + for (auto &RC : RegClasses) { + ++RCIdx; + if (!RC.Allocatable) continue; // Recompute the sorted list of units in this class. std::vector RCRegUnits; - RegClasses[RCIdx]->buildRegUnitSet(RCRegUnits); + RC.buildRegUnitSet(RCRegUnits); // Don't increase pressure for unallocatable regclasses. if (RCRegUnits.empty()) continue; - DEBUG(dbgs() << "RC " << RegClasses[RCIdx]->getName() << " Units: \n"; - for (unsigned i = 0, e = RCRegUnits.size(); i < e; ++i) - dbgs() << RegUnits[RCRegUnits[i]].getRoots()[0]->getName() << " "; + DEBUG(dbgs() << "RC " << RC.getName() << " Units: \n"; + for (auto &U : RCRegUnits) + dbgs() << RegUnits[U].getRoots()[0]->getName() << " "; dbgs() << "\n UnitSetIDs:"); // Find all supersets. @@ -1704,9 +1751,46 @@ void CodeGenRegBank::computeRegUnitSets() { } } +void CodeGenRegBank::computeRegUnitLaneMasks() { + for (auto &Register : Registers) { + // Create an initial lane mask for all register units. + const auto &RegUnits = Register.getRegUnits(); + CodeGenRegister::RegUnitLaneMaskList RegUnitLaneMasks(RegUnits.count(), 0); + // Iterate through SubRegisters. + typedef CodeGenRegister::SubRegMap SubRegMap; + const SubRegMap &SubRegs = Register.getSubRegs(); + for (SubRegMap::const_iterator S = SubRegs.begin(), + SE = SubRegs.end(); S != SE; ++S) { + CodeGenRegister *SubReg = S->second; + // Ignore non-leaf subregisters, their lane masks are fully covered by + // the leaf subregisters anyway. + if (SubReg->getSubRegs().size() != 0) + continue; + CodeGenSubRegIndex *SubRegIndex = S->first; + const CodeGenRegister *SubRegister = S->second; + unsigned LaneMask = SubRegIndex->LaneMask; + // Distribute LaneMask to Register Units touched. + for (const auto &SUI : SubRegister->getRegUnits()) { + bool Found = false; + unsigned u = 0; + for (unsigned RU : RegUnits) { + if (SUI == RU) { + RegUnitLaneMasks[u] |= LaneMask; + assert(!Found); + Found = true; + } + ++u; + } + assert(Found); + } + } + Register.setRegUnitLaneMasks(RegUnitLaneMasks); + } +} + void CodeGenRegBank::computeDerivedInfo() { computeComposites(); - computeSubRegIndexLaneMasks(); + computeSubRegLaneMasks(); // Compute a weight for each register unit created during getSubRegs. // This may create adopted register units (with unit # >= NumNativeRegUnits). @@ -1716,6 +1800,8 @@ void CodeGenRegBank::computeDerivedInfo() { // supersets for the union of overlapping sets. computeRegUnitSets(); + computeRegUnitLaneMasks(); + // Get the weight of each set. for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx) RegUnitSets[Idx].Weight = getRegUnitSetWeight(RegUnitSets[Idx].Units); @@ -1742,20 +1828,23 @@ void CodeGenRegBank::computeDerivedInfo() { // returns a maximal register class for all X. // void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) { - for (unsigned rci = 0, rce = RegClasses.size(); rci != rce; ++rci) { + assert(!RegClasses.empty()); + // Stash the iterator to the last element so that this loop doesn't visit + // elements added by the getOrCreateSubClass call within it. + for (auto I = RegClasses.begin(), E = std::prev(RegClasses.end()); + I != std::next(E); ++I) { CodeGenRegisterClass *RC1 = RC; - CodeGenRegisterClass *RC2 = RegClasses[rci]; + CodeGenRegisterClass *RC2 = &*I; if (RC1 == RC2) continue; // Compute the set intersection of RC1 and RC2. - const CodeGenRegister::Set &Memb1 = RC1->getMembers(); - const CodeGenRegister::Set &Memb2 = RC2->getMembers(); - CodeGenRegister::Set Intersection; - std::set_intersection(Memb1.begin(), Memb1.end(), - Memb2.begin(), Memb2.end(), - std::inserter(Intersection, Intersection.begin()), - CodeGenRegister::Less()); + const CodeGenRegister::Vec &Memb1 = RC1->getMembers(); + const CodeGenRegister::Vec &Memb2 = RC2->getMembers(); + CodeGenRegister::Vec Intersection; + std::set_intersection( + Memb1.begin(), Memb1.end(), Memb2.begin(), Memb2.end(), + std::inserter(Intersection, Intersection.begin()), deref()); // Skip disjoint class pairs. if (Intersection.empty()) @@ -1781,37 +1870,38 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) { // void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { // Map SubRegIndex to set of registers in RC supporting that SubRegIndex. - typedef std::map SubReg2SetMap; + typedef std::map> SubReg2SetMap; // Compute the set of registers supporting each SubRegIndex. SubReg2SetMap SRSets; - for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(), - RE = RC->getMembers().end(); RI != RE; ++RI) { - const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs(); + for (const auto R : RC->getMembers()) { + const CodeGenRegister::SubRegMap &SRM = R->getSubRegs(); for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(), E = SRM.end(); I != E; ++I) - SRSets[I->first].insert(*RI); + SRSets[I->first].push_back(R); } + for (auto I : SRSets) + sortAndUniqueRegisters(I.second); + // Find matching classes for all SRSets entries. Iterate in SubRegIndex // numerical order to visit synthetic indices last. - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - CodeGenSubRegIndex *SubIdx = SubRegIndices[sri]; - SubReg2SetMap::const_iterator I = SRSets.find(SubIdx); + for (const auto &SubIdx : SubRegIndices) { + SubReg2SetMap::const_iterator I = SRSets.find(&SubIdx); // Unsupported SubRegIndex. Skip it. if (I == SRSets.end()) continue; // In most cases, all RC registers support the SubRegIndex. if (I->second.size() == RC->getMembers().size()) { - RC->setSubClassWithSubReg(SubIdx, RC); + RC->setSubClassWithSubReg(&SubIdx, RC); continue; } // This is a real subset. See if we have a matching class. CodeGenRegisterClass *SubRC = getOrCreateSubClass(RC, &I->second, RC->getName() + "_with_" + I->first->getName()); - RC->setSubClassWithSubReg(SubIdx, SubRC); + RC->setSubClassWithSubReg(&SubIdx, SubRC); } } @@ -1823,27 +1913,24 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { // void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, - unsigned FirstSubRegRC) { + std::list::iterator FirstSubRegRC) { SmallVector, 16> SSPairs; BitVector TopoSigs(getNumTopoSigs()); // Iterate in SubRegIndex numerical order to visit synthetic indices last. - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - CodeGenSubRegIndex *SubIdx = SubRegIndices[sri]; + for (auto &SubIdx : SubRegIndices) { // Skip indexes that aren't fully supported by RC's registers. This was // computed by inferSubClassWithSubReg() above which should have been // called first. - if (RC->getSubClassWithSubReg(SubIdx) != RC) + if (RC->getSubClassWithSubReg(&SubIdx) != RC) continue; // Build list of (Super, Sub) pairs for this SubIdx. SSPairs.clear(); TopoSigs.reset(); - for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(), - RE = RC->getMembers().end(); RI != RE; ++RI) { - const CodeGenRegister *Super = *RI; - const CodeGenRegister *Sub = Super->getSubRegs().find(SubIdx)->second; + for (const auto Super : RC->getMembers()) { + const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second; assert(Sub && "Missing sub-register"); SSPairs.push_back(std::make_pair(Super, Sub)); TopoSigs.set(Sub->getTopoSig()); @@ -1851,29 +1938,36 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, // Iterate over sub-register class candidates. Ignore classes created by // this loop. They will never be useful. - for (unsigned rci = FirstSubRegRC, rce = RegClasses.size(); rci != rce; - ++rci) { - CodeGenRegisterClass *SubRC = RegClasses[rci]; + // Store an iterator to the last element (not end) so that this loop doesn't + // visit newly inserted elements. + assert(!RegClasses.empty()); + for (auto I = FirstSubRegRC, E = std::prev(RegClasses.end()); + I != std::next(E); ++I) { + CodeGenRegisterClass &SubRC = *I; // Topological shortcut: SubRC members have the wrong shape. - if (!TopoSigs.anyCommon(SubRC->getTopoSigs())) + if (!TopoSigs.anyCommon(SubRC.getTopoSigs())) continue; // Compute the subset of RC that maps into SubRC. - CodeGenRegister::Set SubSet; + CodeGenRegister::Vec SubSetVec; for (unsigned i = 0, e = SSPairs.size(); i != e; ++i) - if (SubRC->contains(SSPairs[i].second)) - SubSet.insert(SSPairs[i].first); - if (SubSet.empty()) + if (SubRC.contains(SSPairs[i].second)) + SubSetVec.push_back(SSPairs[i].first); + + if (SubSetVec.empty()) continue; + // RC injects completely into SubRC. - if (SubSet.size() == SSPairs.size()) { - SubRC->addSuperRegClass(SubIdx, RC); + sortAndUniqueRegisters(SubSetVec); + if (SubSetVec.size() == SSPairs.size()) { + SubRC.addSuperRegClass(&SubIdx, RC); continue; } + // Only a subset of RC maps into SubRC. Make sure it is represented by a // class. - getOrCreateSubClass(RC, &SubSet, RC->getName() + - "_with_" + SubIdx->getName() + - "_in_" + SubRC->getName()); + getOrCreateSubClass(RC, &SubSetVec, RC->getName() + "_with_" + + SubIdx.getName() + "_in_" + + SubRC.getName()); } } } @@ -1883,14 +1977,19 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, // Infer missing register classes. // void CodeGenRegBank::computeInferredRegisterClasses() { + assert(!RegClasses.empty()); // When this function is called, the register classes have not been sorted // and assigned EnumValues yet. That means getSubClasses(), // getSuperClasses(), and hasSubClass() functions are defunct. - unsigned FirstNewRC = RegClasses.size(); + + // Use one-before-the-end so it doesn't move forward when new elements are + // added. + auto FirstNewRC = std::prev(RegClasses.end()); // Visit all register classes, including the ones being added by the loop. - for (unsigned rci = 0; rci != RegClasses.size(); ++rci) { - CodeGenRegisterClass *RC = RegClasses[rci]; + // Watch out for iterator invalidation here. + for (auto I = RegClasses.begin(), E = RegClasses.end(); I != E; ++I) { + CodeGenRegisterClass *RC = &*I; // Synthesize answers for getSubClassWithSubReg(). inferSubClassWithSubReg(RC); @@ -1907,10 +2006,11 @@ void CodeGenRegBank::computeInferredRegisterClasses() { // after inferMatchingSuperRegClass was called. At this point, // inferMatchingSuperRegClass has checked SuperRC = [0..rci] with SubRC = // [0..FirstNewRC). We need to cover SubRC = [FirstNewRC..rci]. - if (rci + 1 == FirstNewRC) { - unsigned NextNewRC = RegClasses.size(); - for (unsigned rci2 = 0; rci2 != FirstNewRC; ++rci2) - inferMatchingSuperRegClass(RegClasses[rci2], FirstNewRC); + if (I == FirstNewRC) { + auto NextNewRC = std::prev(RegClasses.end()); + for (auto I2 = RegClasses.begin(), E2 = std::next(FirstNewRC); I2 != E2; + ++I2) + inferMatchingSuperRegClass(&*I2, E2); FirstNewRC = NextNewRC; } } @@ -1924,10 +2024,8 @@ void CodeGenRegBank::computeInferredRegisterClasses() { const CodeGenRegisterClass* CodeGenRegBank::getRegClassForRegister(Record *R) { const CodeGenRegister *Reg = getReg(R); - ArrayRef RCs = getRegClasses(); const CodeGenRegisterClass *FoundRC = nullptr; - for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RCs[i]; + for (const auto &RC : getRegClasses()) { if (!RC.contains(Reg)) continue; diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index c1e37fa..7c723d9 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -19,19 +19,36 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SparseBitVector.h" #include "llvm/CodeGen/MachineValueType.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/SetTheory.h" #include +#include #include #include #include #include +#include namespace llvm { class CodeGenRegBank; + /// Used to encode a step in a register lane mask transformation. + /// Mask the bits specified in Mask, then rotate them Rol bits to the left + /// assuming a wraparound at 32bits. + struct MaskRolPair { + unsigned Mask; + uint8_t RotateLeft; + bool operator==(const MaskRolPair Other) { + return Mask == Other.Mask && RotateLeft == Other.RotateLeft; + } + bool operator!=(const MaskRolPair Other) { + return Mask != Other.Mask || RotateLeft != Other.RotateLeft; + } + }; + /// CodeGenSubRegIndex - Represents a sub-register index. class CodeGenSubRegIndex { Record *const TheDef; @@ -42,7 +59,8 @@ namespace llvm { uint16_t Size; uint16_t Offset; const unsigned EnumValue; - unsigned LaneMask; + mutable unsigned LaneMask; + mutable SmallVector CompositionLaneMaskTransform; // Are all super-registers containing this SubRegIndex covered by their // sub-registers? @@ -55,17 +73,9 @@ namespace llvm { const std::string &getNamespace() const { return Namespace; } std::string getQualifiedName() const; - // Order CodeGenSubRegIndex pointers by EnumValue. - struct Less { - bool operator()(const CodeGenSubRegIndex *A, - const CodeGenSubRegIndex *B) const { - assert(A && B); - return A->EnumValue < B->EnumValue; - } - }; - // Map of composite subreg indices. - typedef std::map CompMap; + typedef std::map> CompMap; // Returns the subreg index that results from composing this with Idx. // Returns NULL if this and Idx don't compose. @@ -101,12 +111,17 @@ namespace llvm { const CompMap &getComposites() const { return Composed; } // Compute LaneMask from Composed. Return LaneMask. - unsigned computeLaneMask(); + unsigned computeLaneMask() const; private: CompMap Composed; }; + inline bool operator<(const CodeGenSubRegIndex &A, + const CodeGenSubRegIndex &B) { + return A.EnumValue < B.EnumValue; + } + /// CodeGenRegister - Represents a register definition. struct CodeGenRegister { Record *TheDef; @@ -115,8 +130,8 @@ namespace llvm { bool CoveredBySubRegs; // Map SubRegIndex -> Register. - typedef std::map SubRegMap; + typedef std::map> + SubRegMap; CodeGenRegister(Record *R, unsigned Enum); @@ -180,18 +195,27 @@ namespace llvm { } // List of register units in ascending order. - typedef SmallVector RegUnitList; + typedef SparseBitVector<> RegUnitList; + typedef SmallVector RegUnitLaneMaskList; // How many entries in RegUnitList are native? - unsigned NumNativeRegUnits; + RegUnitList NativeRegUnits; // Get the list of register units. // This is only valid after computeSubRegs() completes. const RegUnitList &getRegUnits() const { return RegUnits; } + ArrayRef getRegUnitLaneMasks() const { + return makeArrayRef(RegUnitLaneMasks).slice(0, NativeRegUnits.count()); + } + // Get the native register units. This is a prefix of getRegUnits(). - ArrayRef getNativeRegUnits() const { - return makeArrayRef(RegUnits).slice(0, NumNativeRegUnits); + RegUnitList getNativeRegUnits() const { + return NativeRegUnits; + } + + void setRegUnitLaneMasks(const RegUnitLaneMaskList &LaneMasks) { + RegUnitLaneMasks = LaneMasks; } // Inherit register units from subregisters. @@ -199,23 +223,14 @@ namespace llvm { bool inheritRegUnits(CodeGenRegBank &RegBank); // Adopt a register unit for pressure tracking. - // A unit is adopted iff its unit number is >= NumNativeRegUnits. - void adoptRegUnit(unsigned RUID) { RegUnits.push_back(RUID); } + // A unit is adopted iff its unit number is >= NativeRegUnits.count(). + void adoptRegUnit(unsigned RUID) { RegUnits.set(RUID); } // Get the sum of this register's register unit weights. unsigned getWeight(const CodeGenRegBank &RegBank) const; - // Order CodeGenRegister pointers by EnumValue. - struct Less { - bool operator()(const CodeGenRegister *A, - const CodeGenRegister *B) const { - assert(A && B); - return A->EnumValue < B->EnumValue; - } - }; - // Canonically ordered set. - typedef std::set Set; + typedef std::vector Vec; private: bool SubRegsComplete; @@ -236,11 +251,19 @@ namespace llvm { SuperRegList SuperRegs; DenseMap SubReg2Idx; RegUnitList RegUnits; + RegUnitLaneMaskList RegUnitLaneMasks; }; + inline bool operator<(const CodeGenRegister &A, const CodeGenRegister &B) { + return A.EnumValue < B.EnumValue; + } + + inline bool operator==(const CodeGenRegister &A, const CodeGenRegister &B) { + return A.EnumValue == B.EnumValue; + } class CodeGenRegisterClass { - CodeGenRegister::Set Members; + CodeGenRegister::Vec Members; // Allocation orders. Order[0] always contains all registers in Members. std::vector > Orders; // Bit mask of sub-classes including this, indexed by their EnumValue. @@ -257,15 +280,16 @@ namespace llvm { // Map SubRegIndex -> sub-class. This is the largest sub-class where all // registers have a SubRegIndex sub-register. - DenseMap SubClassWithSubReg; + DenseMap + SubClassWithSubReg; // Map SubRegIndex -> set of super-reg classes. This is all register // classes SuperRC such that: // // R:SubRegIndex in this RC for all R in SuperRC. // - DenseMap > SuperRegClasses; + DenseMap> + SuperRegClasses; // Bit vector of TopoSigs for the registers in this class. This will be // very sparse on regular architectures. @@ -280,6 +304,8 @@ namespace llvm { int CopyCost; bool Allocatable; std::string AltOrderSelect; + /// Contains the combination of the lane masks of all subregisters. + unsigned LaneMask; // Return the Record that defined this class, or NULL if the class was // created by TableGen. @@ -314,19 +340,20 @@ namespace llvm { // getSubClassWithSubReg - Returns the largest sub-class where all // registers have a SubIdx sub-register. - CodeGenRegisterClass* - getSubClassWithSubReg(CodeGenSubRegIndex *SubIdx) const { + CodeGenRegisterClass * + getSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx) const { return SubClassWithSubReg.lookup(SubIdx); } - void setSubClassWithSubReg(CodeGenSubRegIndex *SubIdx, + void setSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx, CodeGenRegisterClass *SubRC) { SubClassWithSubReg[SubIdx] = SubRC; } // getSuperRegClasses - Returns a bit vector of all register classes // containing only SubIdx super-registers of this class. - void getSuperRegClasses(CodeGenSubRegIndex *SubIdx, BitVector &Out) const; + void getSuperRegClasses(const CodeGenSubRegIndex *SubIdx, + BitVector &Out) const; // addSuperRegClass - Add a class containing only SudIdx super-registers. void addSuperRegClass(CodeGenSubRegIndex *SubIdx, @@ -357,7 +384,7 @@ namespace llvm { // Get the set of registers. This set contains the same registers as // getOrder(0). - const CodeGenRegister::Set &getMembers() const { return Members; } + const CodeGenRegister::Vec &getMembers() const { return Members; } // Get a bit vector of TopoSigs present in this register class. const BitVector &getTopoSigs() const { return TopoSigs; } @@ -371,11 +398,11 @@ namespace llvm { // sub-classes. Note the ordering provided by this key is not the same as // the topological order used for the EnumValues. struct Key { - const CodeGenRegister::Set *Members; + const CodeGenRegister::Vec *Members; unsigned SpillSize; unsigned SpillAlignment; - Key(const CodeGenRegister::Set *M, unsigned S = 0, unsigned A = 0) + Key(const CodeGenRegister::Vec *M, unsigned S = 0, unsigned A = 0) : Members(M), SpillSize(S), SpillAlignment(A) {} Key(const CodeGenRegisterClass &RC) @@ -446,8 +473,7 @@ namespace llvm { class CodeGenRegBank { SetTheory Sets; - // SubRegIndices. - std::vector SubRegIndices; + std::deque SubRegIndices; DenseMap Def2SubRegIdx; CodeGenSubRegIndex *createSubRegIndex(StringRef Name, StringRef NameSpace); @@ -457,7 +483,7 @@ namespace llvm { ConcatIdxMap ConcatIdx; // Registers. - std::vector Registers; + std::deque Registers; StringMap RegistersByName; DenseMap Def2Reg; unsigned NumNativeRegUnits; @@ -468,7 +494,7 @@ namespace llvm { SmallVector RegUnits; // Register classes. - std::vector RegClasses; + std::list RegClasses; DenseMap Def2RC; typedef std::map RCKeyMap; RCKeyMap Key2RC; @@ -494,15 +520,20 @@ namespace llvm { // Create a synthetic sub-class if it is missing. CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC, - const CodeGenRegister::Set *Membs, + const CodeGenRegister::Vec *Membs, StringRef Name); // Infer missing register classes. void computeInferredRegisterClasses(); void inferCommonSubClass(CodeGenRegisterClass *RC); void inferSubClassWithSubReg(CodeGenRegisterClass *RC); - void inferMatchingSuperRegClass(CodeGenRegisterClass *RC, - unsigned FirstSubRegRC = 0); + void inferMatchingSuperRegClass(CodeGenRegisterClass *RC) { + inferMatchingSuperRegClass(RC, RegClasses.begin()); + } + + void inferMatchingSuperRegClass( + CodeGenRegisterClass *RC, + std::list::iterator FirstSubRegRC); // Iteratively prune unit sets. void pruneUnitSets(); @@ -517,7 +548,11 @@ namespace llvm { void computeComposites(); // Compute a lane mask for each sub-register index. - void computeSubRegIndexLaneMasks(); + void computeSubRegLaneMasks(); + + /// Computes a lane mask for each register unit enumerated by a physical + /// register. + void computeRegUnitLaneMasks(); public: CodeGenRegBank(RecordKeeper&); @@ -527,7 +562,9 @@ namespace llvm { // Sub-register indices. The first NumNamedIndices are defined by the user // in the .td files. The rest are synthesized such that all sub-registers // have a unique name. - ArrayRef getSubRegIndices() { return SubRegIndices; } + const std::deque &getSubRegIndices() const { + return SubRegIndices; + } // Find a SubRegIndex form its Record def. CodeGenSubRegIndex *getSubRegIdx(Record*); @@ -547,7 +584,7 @@ namespace llvm { ConcatIdx.insert(std::make_pair(Parts, Idx)); } - const std::vector &getRegisters() { return Registers; } + const std::deque &getRegisters() { return Registers; } const StringMap &getRegistersByName() { return RegistersByName; } @@ -604,7 +641,9 @@ namespace llvm { RegUnit &getRegUnit(unsigned RUID) { return RegUnits[RUID]; } const RegUnit &getRegUnit(unsigned RUID) const { return RegUnits[RUID]; } - ArrayRef getRegClasses() const { + std::list &getRegClasses() { return RegClasses; } + + const std::list &getRegClasses() const { return RegClasses; } diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index 4cf7b5f..bfdf8dc 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -74,11 +74,10 @@ struct InstRegexOp : public SetTheory::Operator { } RegexList.push_back(Regex(pat)); } - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { + for (const CodeGenInstruction *Inst : Target.instructions()) { for (auto &R : RegexList) { - if (R.match((*I)->TheDef->getName())) - Elts.insert((*I)->TheDef); + if (R.match(Inst->TheDef->getName())) + Elts.insert(Inst->TheDef); } } } @@ -214,9 +213,8 @@ void CodeGenSchedModels::collectSchedRW() { // Find all SchedReadWrites referenced by instruction defs. RecVec SWDefs, SRDefs; - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - Record *SchedDef = (*I)->TheDef; + for (const CodeGenInstruction *Inst : Target.instructions()) { + Record *SchedDef = Inst->TheDef; if (SchedDef->isValueUnset("SchedRW")) continue; RecVec RWs = SchedDef->getValueAsListOfDefs("SchedRW"); @@ -509,18 +507,17 @@ void CodeGenSchedModels::collectSchedClasses() { // Create a SchedClass for each unique combination of itinerary class and // SchedRW list. - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - Record *ItinDef = (*I)->TheDef->getValueAsDef("Itinerary"); + for (const CodeGenInstruction *Inst : Target.instructions()) { + Record *ItinDef = Inst->TheDef->getValueAsDef("Itinerary"); IdxVec Writes, Reads; - if (!(*I)->TheDef->isValueUnset("SchedRW")) - findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads); + if (!Inst->TheDef->isValueUnset("SchedRW")) + findRWs(Inst->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads); // ProcIdx == 0 indicates the class applies to all processors. IdxVec ProcIndices(1, 0); unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, ProcIndices); - InstrClassMap[(*I)->TheDef] = SCIdx; + InstrClassMap[Inst->TheDef] = SCIdx; } // Create classes for InstRW defs. RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW"); @@ -535,18 +532,16 @@ void CodeGenSchedModels::collectSchedClasses() { if (!EnableDump) return; - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - - std::string InstName = (*I)->TheDef->getName(); - unsigned SCIdx = InstrClassMap.lookup((*I)->TheDef); + for (const CodeGenInstruction *Inst : Target.instructions()) { + std::string InstName = Inst->TheDef->getName(); + unsigned SCIdx = InstrClassMap.lookup(Inst->TheDef); if (!SCIdx) { - dbgs() << "No machine model for " << (*I)->TheDef->getName() << '\n'; + dbgs() << "No machine model for " << Inst->TheDef->getName() << '\n'; continue; } CodeGenSchedClass &SC = getSchedClass(SCIdx); if (SC.ProcIndices[0] != 0) - PrintFatalError((*I)->TheDef->getLoc(), "Instruction's sched class " + PrintFatalError(Inst->TheDef->getLoc(), "Instruction's sched class " "must not be subtarget specific."); IdxVec ProcIndices; @@ -584,7 +579,7 @@ void CodeGenSchedModels::collectSchedClasses() { for (std::vector::iterator PI = ProcModels.begin(), PE = ProcModels.end(); PI != PE; ++PI) { if (!std::count(ProcIndices.begin(), ProcIndices.end(), PI->Index)) - dbgs() << "No machine model for " << (*I)->TheDef->getName() + dbgs() << "No machine model for " << Inst->TheDef->getName() << " on processor " << PI->ModelName << '\n'; } } @@ -781,9 +776,7 @@ bool CodeGenSchedModels::hasItineraries() const { // Gather the processor itineraries. void CodeGenSchedModels::collectProcItins() { - for (std::vector::iterator PI = ProcModels.begin(), - PE = ProcModels.end(); PI != PE; ++PI) { - CodeGenProcModel &ProcModel = *PI; + for (CodeGenProcModel &ProcModel : ProcModels) { if (!ProcModel.hasItineraries()) continue; @@ -1502,8 +1495,7 @@ void CodeGenSchedModels::collectProcResources() { PM.ProcResourceDefs.push_back(*RI); } // Finalize each ProcModel by sorting the record arrays. - for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) { - CodeGenProcModel &PM = ProcModels[PIdx]; + for (CodeGenProcModel &PM : ProcModels) { std::sort(PM.WriteResDefs.begin(), PM.WriteResDefs.end(), LessRecord()); std::sort(PM.ReadAdvanceDefs.begin(), PM.ReadAdvanceDefs.end(), diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 597da68..47c8e0b 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -57,6 +57,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::i32: return "MVT::i32"; case MVT::i64: return "MVT::i64"; case MVT::i128: return "MVT::i128"; + case MVT::Any: return "MVT::Any"; case MVT::iAny: return "MVT::iAny"; case MVT::fAny: return "MVT::fAny"; case MVT::vAny: return "MVT::vAny"; @@ -133,7 +134,7 @@ std::string llvm::getQualifiedName(const Record *R) { /// getTarget - Return the current instance of the Target class. /// CodeGenTarget::CodeGenTarget(RecordKeeper &records) - : Records(records), RegBank(nullptr), SchedModels(nullptr) { + : Records(records) { std::vector Targets = Records.getAllDerivedDefinitions("Target"); if (Targets.size() == 0) PrintFatalError("ERROR: No 'Target' subclasses defined!"); @@ -143,9 +144,6 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records) } CodeGenTarget::~CodeGenTarget() { - DeleteContainerSeconds(Instructions); - delete RegBank; - delete SchedModels; } const std::string &CodeGenTarget::getName() const { @@ -153,11 +151,11 @@ const std::string &CodeGenTarget::getName() const { } std::string CodeGenTarget::getInstNamespace() const { - for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) { + for (const CodeGenInstruction *Inst : instructions()) { // Make sure not to pick up "TargetOpcode" by accidentally getting // the namespace off the PHI instruction or something. - if ((*i)->Namespace != "TargetOpcode") - return (*i)->Namespace; + if (Inst->Namespace != "TargetOpcode") + return Inst->Namespace; } return ""; @@ -211,7 +209,7 @@ Record *CodeGenTarget::getAsmWriter() const { CodeGenRegBank &CodeGenTarget::getRegBank() const { if (!RegBank) - RegBank = new CodeGenRegBank(Records); + RegBank = llvm::make_unique(Records); return *RegBank; } @@ -234,9 +232,7 @@ std::vector CodeGenTarget:: getRegisterVTs(Record *R) const { const CodeGenRegister *Reg = getRegBank().getReg(R); std::vector Result; - ArrayRef RCs = getRegBank().getRegClasses(); - for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RCs[i]; + for (const auto &RC : getRegBank().getRegClasses()) { if (RC.contains(Reg)) { ArrayRef InVTs = RC.getValueTypes(); Result.insert(Result.end(), InVTs.begin(), InVTs.end()); @@ -251,10 +247,8 @@ getRegisterVTs(Record *R) const { void CodeGenTarget::ReadLegalValueTypes() const { - ArrayRef RCs = getRegBank().getRegClasses(); - for (unsigned i = 0, e = RCs.size(); i != e; ++i) - for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri) - LegalValueTypes.push_back(RCs[i]->VTs[ri]); + for (const auto &RC : getRegBank().getRegClasses()) + LegalValueTypes.insert(LegalValueTypes.end(), RC.VTs.begin(), RC.VTs.end()); // Remove duplicates. std::sort(LegalValueTypes.begin(), LegalValueTypes.end()); @@ -265,7 +259,7 @@ void CodeGenTarget::ReadLegalValueTypes() const { CodeGenSchedModels &CodeGenTarget::getSchedModels() const { if (!SchedModels) - SchedModels = new CodeGenSchedModels(Records, *this); + SchedModels = llvm::make_unique(Records, *this); return *SchedModels; } @@ -276,20 +270,20 @@ void CodeGenTarget::ReadInstructions() const { // Parse the instructions defined in the .td file. for (unsigned i = 0, e = Insts.size(); i != e; ++i) - Instructions[Insts[i]] = new CodeGenInstruction(Insts[i]); + Instructions[Insts[i]] = llvm::make_unique(Insts[i]); } static const CodeGenInstruction * GetInstByName(const char *Name, - const DenseMap &Insts, + const DenseMap> &Insts, RecordKeeper &Records) { const Record *Rec = Records.getDef(Name); - DenseMap::const_iterator - I = Insts.find(Rec); + const auto I = Insts.find(Rec); if (!Rec || I == Insts.end()) PrintFatalError(Twine("Could not find '") + Name + "' instruction!"); - return I->second; + return I->second.get(); } /// \brief Return all of the instructions defined by the target, ordered by @@ -302,8 +296,9 @@ void CodeGenTarget::ComputeInstrsByEnum() const { "IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE", "REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START", "LIFETIME_END", "STACKMAP", "PATCHPOINT", "LOAD_STACK_GUARD", + "STATEPOINT", "FRAME_ALLOC", nullptr}; - const DenseMap &Insts = getInstructions(); + const auto &Insts = getInstructions(); for (const char *const *p = FixedInstrs; *p; ++p) { const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); assert(Instr && "Missing target independent instruction"); @@ -312,9 +307,8 @@ void CodeGenTarget::ComputeInstrsByEnum() const { } unsigned EndOfPredefines = InstrsByEnum.size(); - for (DenseMap::const_iterator - I = Insts.begin(), E = Insts.end(); I != E; ++I) { - const CodeGenInstruction *CGI = I->second; + for (const auto &I : Insts) { + const CodeGenInstruction *CGI = I.second.get(); if (CGI->Namespace != "TargetOpcode") InstrsByEnum.push_back(CGI); } @@ -344,9 +338,7 @@ void CodeGenTarget::reverseBitsForLittleEndianEncoding() { return; std::vector Insts = Records.getAllDerivedDefinitions("Instruction"); - for (std::vector::iterator I = Insts.begin(), E = Insts.end(); - I != E; ++I) { - Record *R = *I; + for (Record *R : Insts) { if (R->getValueAsString("Namespace") == "TargetOpcode" || R->getValueAsBit("isPseudo")) continue; @@ -539,7 +531,9 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // variants with iAny types; otherwise, if the intrinsic is not // overloaded, all the types can be specified directly. assert(((!TyEl->isSubClassOf("LLVMExtendedType") && - !TyEl->isSubClassOf("LLVMTruncatedType")) || + !TyEl->isSubClassOf("LLVMTruncatedType") && + !TyEl->isSubClassOf("LLVMVectorSameWidth") && + !TyEl->isSubClassOf("LLVMPointerToElt")) || VT == MVT::iAny || VT == MVT::vAny) && "Expected iAny or vAny type"); } else diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index f4e1b6a..24b3851 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -65,15 +65,16 @@ class CodeGenTarget { RecordKeeper &Records; Record *TargetRec; - mutable DenseMap Instructions; - mutable CodeGenRegBank *RegBank; + mutable DenseMap> Instructions; + mutable std::unique_ptr RegBank; mutable std::vector RegAltNameIndices; mutable SmallVector LegalValueTypes; void ReadRegAltNameIndices() const; void ReadInstructions() const; void ReadLegalValueTypes() const; - mutable CodeGenSchedModels *SchedModels; + mutable std::unique_ptr SchedModels; mutable std::vector InstrsByEnum; public: @@ -146,7 +147,8 @@ public: CodeGenSchedModels &getSchedModels() const; private: - DenseMap &getInstructions() const { + DenseMap> & + getInstructions() const { if (Instructions.empty()) ReadInstructions(); return Instructions; } @@ -154,8 +156,7 @@ public: CodeGenInstruction &getInstruction(const Record *InstRec) const { if (Instructions.empty()) ReadInstructions(); - DenseMap::iterator I = - Instructions.find(InstRec); + auto I = Instructions.find(InstRec); assert(I != Instructions.end() && "Not an instruction"); return *I->second; } diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index e2e6ab1..0fe3bbd 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -157,12 +157,12 @@ void DAGISelEmitter::run(raw_ostream &OS) { } } - Matcher *TheMatcher = new ScopeMatcher(PatternMatchers); + std::unique_ptr TheMatcher = + llvm::make_unique(PatternMatchers); - TheMatcher = OptimizeMatcher(TheMatcher, CGP); + OptimizeMatcher(TheMatcher, CGP); //Matcher->dump(); - EmitMatcherTable(TheMatcher, CGP, OS); - delete TheMatcher; + EmitMatcherTable(TheMatcher.get(), CGP, OS); } namespace llvm { diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index b9cb267..9df3b41 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -30,7 +30,8 @@ namespace llvm { Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant, const CodeGenDAGPatterns &CGP); -Matcher *OptimizeMatcher(Matcher *Matcher, const CodeGenDAGPatterns &CGP); +void OptimizeMatcher(std::unique_ptr &Matcher, + const CodeGenDAGPatterns &CGP); void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP, raw_ostream &OS); diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 4a73b00..eb80619 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -27,10 +27,8 @@ static MVT::SimpleValueType getRegisterValueType(Record *R, bool FoundRC = false; MVT::SimpleValueType VT = MVT::Other; const CodeGenRegister *Reg = T.getRegBank().getReg(R); - ArrayRef RCs = T.getRegBank().getRegClasses(); - for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RCs[rc]; + for (const auto &RC : T.getRegBank().getRegClasses()) { if (!RC.contains(Reg)) continue; diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index 7a22764..c9ee371 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -511,11 +511,10 @@ static void FactorNodes(std::unique_ptr &MatcherPtr) { Scope->resetChild(i, NewOptionsToMatch[i]); } -Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher, - const CodeGenDAGPatterns &CGP) { - std::unique_ptr MatcherPtr(TheMatcher); +void +llvm::OptimizeMatcher(std::unique_ptr &MatcherPtr, + const CodeGenDAGPatterns &CGP) { ContractNodes(MatcherPtr, CGP); SinkPatternPredicates(MatcherPtr); FactorNodes(MatcherPtr); - return MatcherPtr.release(); } diff --git a/utils/TableGen/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp index ea14cb9..5060b6e 100644 --- a/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/utils/TableGen/DFAPacketizerEmitter.cpp @@ -472,7 +472,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { current->canAddInsnClass(InsnClass)) { const State *NewState; current->AddInsnClass(InsnClass, NewStateResources); - assert(NewStateResources.size() && "New states must be generated"); + assert(!NewStateResources.empty() && "New states must be generated"); // // If we have seen this state before, then do not create a new state. diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index bd83b6c..292a2b1 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -333,8 +333,8 @@ protected: // Parent emitter const FixedLenDecoderEmitter *Emitter; - FilterChooser(const FilterChooser &) LLVM_DELETED_FUNCTION; - void operator=(const FilterChooser &) LLVM_DELETED_FUNCTION; + FilterChooser(const FilterChooser &) = delete; + void operator=(const FilterChooser &) = delete; public: FilterChooser(const std::vector &Insts, @@ -537,12 +537,10 @@ Filter::~Filter() { // instructions. In order to unambiguously decode the singleton, we need to // match the remaining undecoded encoding bits against the singleton. void Filter::recurse() { - std::map >::const_iterator mapIterator; - // Starts by inheriting our parent filter chooser's filter bit values. std::vector BitValueArray(Owner->FilterBitValues); - if (VariableInstructions.size()) { + if (!VariableInstructions.empty()) { // Conservatively marks each segment position as BIT_UNSET. for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) BitValueArray[StartBit + bitIndex] = BIT_UNSET; @@ -564,13 +562,11 @@ void Filter::recurse() { } // Otherwise, create sub choosers. - for (mapIterator = FilteredInstructions.begin(); - mapIterator != FilteredInstructions.end(); - mapIterator++) { + for (const auto &Inst : FilteredInstructions) { // Marks all the segment positions with either BIT_TRUE or BIT_FALSE. for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) { - if (mapIterator->first & (1ULL << bitIndex)) + if (Inst.first & (1ULL << bitIndex)) BitValueArray[StartBit + bitIndex] = BIT_TRUE; else BitValueArray[StartBit + bitIndex] = BIT_FALSE; @@ -579,8 +575,8 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // category of instructions. FilterChooserMap.insert(std::make_pair( - mapIterator->first, llvm::make_unique( - Owner->AllInstructions, mapIterator->second, + Inst.first, llvm::make_unique( + Owner->AllInstructions, Inst.second, Owner->Operands, BitValueArray, *Owner))); } } @@ -616,19 +612,14 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { // A new filter entry begins a new scope for fixup resolution. TableInfo.FixupStack.push_back(FixupList()); - std::map>::const_iterator filterIterator; - DecoderTable &Table = TableInfo.Table; size_t PrevFilter = 0; bool HasFallthrough = false; - for (filterIterator = FilterChooserMap.begin(); - filterIterator != FilterChooserMap.end(); - filterIterator++) { + for (auto &Filter : FilterChooserMap) { // Field value -1 implies a non-empty set of variable instructions. // See also recurse(). - if (filterIterator->first == (unsigned)-1) { + if (Filter.first == (unsigned)-1) { HasFallthrough = true; // Each scope should always have at least one filter value to check @@ -643,7 +634,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { Table.push_back(MCD::OPC_FilterValue); // Encode and emit the value to filter against. uint8_t Buffer[8]; - unsigned Len = encodeULEB128(filterIterator->first, Buffer); + unsigned Len = encodeULEB128(Filter.first, Buffer); Table.insert(Table.end(), Buffer, Buffer + Len); // Reserve space for the NumToSkip entry. We'll backpatch the value // later. @@ -656,7 +647,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { // Now delegate to the sub filter chooser for further decodings. // The case may fallthrough, which happens if the remaining well-known // encoding bits do not match exactly. - filterIterator->second->emitTableEntries(TableInfo); + Filter.second->emitTableEntries(TableInfo); // Now that we've emitted the body of the handler, update the NumToSkip // of the filter itself to be able to skip forward when false. Subtract @@ -685,7 +676,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { // Returns the number of fanout produced by the filter. More fanout implies // the filter distinguishes more categories of instructions. unsigned Filter::usefulness() const { - if (VariableInstructions.size()) + if (!VariableInstructions.empty()) return FilteredInstructions.size(); else return FilteredInstructions.size() + 1; @@ -863,10 +854,9 @@ emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates, OS.indent(Indentation) << "switch (Idx) {\n"; OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n"; unsigned Index = 0; - for (PredicateSet::const_iterator I = Predicates.begin(), E = Predicates.end(); - I != E; ++I, ++Index) { - OS.indent(Indentation) << "case " << Index << ":\n"; - OS.indent(Indentation+2) << "return (" << *I << ");\n"; + for (const auto &Predicate : Predicates) { + OS.indent(Indentation) << "case " << Index++ << ":\n"; + OS.indent(Indentation+2) << "return (" << Predicate << ");\n"; } OS.indent(Indentation) << "}\n"; } else { @@ -892,10 +882,9 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders, OS.indent(Indentation) << "switch (Idx) {\n"; OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n"; unsigned Index = 0; - for (DecoderSet::const_iterator I = Decoders.begin(), E = Decoders.end(); - I != E; ++I, ++Index) { - OS.indent(Indentation) << "case " << Index << ":\n"; - OS << *I; + for (const auto &Decoder : Decoders) { + OS.indent(Indentation) << "case " << Index++ << ":\n"; + OS << Decoder; OS.indent(Indentation+2) << "return S;\n"; } OS.indent(Indentation) << "}\n"; @@ -1071,20 +1060,16 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc) const { - std::map >::const_iterator OpIter = - Operands.find(Opc); - const std::vector& InsnOperands = OpIter->second; - for (std::vector::const_iterator - I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { + for (const auto &Op : Operands.find(Opc)->second) { // If a custom instruction decoder was specified, use that. - if (I->numFields() == 0 && I->Decoder.size()) { - OS.indent(Indentation) << Emitter->GuardPrefix << I->Decoder + if (Op.numFields() == 0 && Op.Decoder.size()) { + OS.indent(Indentation) << Emitter->GuardPrefix << Op.Decoder << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n"; break; } - emitBinaryParser(OS, Indentation, *I); + emitBinaryParser(OS, Indentation, Op); } } @@ -1795,7 +1780,7 @@ static bool populateInstruction(CodeGenTarget &Target, unsigned NumberOps = CGI.Operands.size(); while (NumberedOp < NumberOps && (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) || - (NamedOpIndices.size() && NamedOpIndices.count( + (!NamedOpIndices.empty() && NamedOpIndices.count( CGI.Operands.getSubOperandNumber(NumberedOp).first)))) ++NumberedOp; @@ -1864,20 +1849,20 @@ static bool populateInstruction(CodeGenTarget &Target, } // For each operand, see if we can figure out where it is encoded. - for (std::vector >::const_iterator - NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) { - if (!NumberedInsnOperands[NI->second].empty()) { + for (const auto &Op : InOutOperands) { + if (!NumberedInsnOperands[Op.second].empty()) { InsnOperands.insert(InsnOperands.end(), - NumberedInsnOperands[NI->second].begin(), - NumberedInsnOperands[NI->second].end()); + NumberedInsnOperands[Op.second].begin(), + NumberedInsnOperands[Op.second].end()); continue; - } else if (!NumberedInsnOperands[TiedNames[NI->second]].empty()) { - if (!NumberedInsnOperandsNoTie.count(TiedNames[NI->second])) { + } + if (!NumberedInsnOperands[TiedNames[Op.second]].empty()) { + if (!NumberedInsnOperandsNoTie.count(TiedNames[Op.second])) { // Figure out to which (sub)operand we're tied. - unsigned i = CGI.Operands.getOperandNamed(TiedNames[NI->second]); + unsigned i = CGI.Operands.getOperandNamed(TiedNames[Op.second]); int tiedTo = CGI.Operands[i].getTiedRegister(); if (tiedTo == -1) { - i = CGI.Operands.getOperandNamed(NI->second); + i = CGI.Operands.getOperandNamed(Op.second); tiedTo = CGI.Operands[i].getTiedRegister(); } @@ -1885,7 +1870,7 @@ static bool populateInstruction(CodeGenTarget &Target, std::pair SO = CGI.Operands.getSubOperandNumber(tiedTo); - InsnOperands.push_back(NumberedInsnOperands[TiedNames[NI->second]] + InsnOperands.push_back(NumberedInsnOperands[TiedNames[Op.second]] [SO.second]); } } @@ -1899,7 +1884,7 @@ static bool populateInstruction(CodeGenTarget &Target, // for decoding register classes. // FIXME: This need to be extended to handle instructions with custom // decoder methods, and operands with (simple) MIOperandInfo's. - TypedInit *TI = cast(NI->first); + TypedInit *TI = cast(Op.first); RecordRecTy *Type = cast(TI->getType()); Record *TypeRecord = Type->getRecord(); bool isReg = false; @@ -1943,8 +1928,8 @@ static bool populateInstruction(CodeGenTarget &Target, continue; } - if (Var->getName() != NI->second && - Var->getName() != TiedNames[NI->second]) { + if (Var->getName() != Op.second && + Var->getName() != TiedNames[Op.second]) { if (Base != ~0U) { OpInfo.addField(Base, Width, Offset); Base = ~0U; @@ -2181,12 +2166,10 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { } DecoderTableInfo TableInfo; - for (std::map, - std::vector >::const_iterator - I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) { + for (const auto &Opc : OpcMap) { // Emit the decoder for this namespace+width combination. - FilterChooser FC(*NumberedInstructions, I->second, Operands, - 8*I->first.second, this); + FilterChooser FC(*NumberedInstructions, Opc.second, Operands, + 8*Opc.first.second, this); // The decode table is cleared for each top level decoder function. The // predicates and decoders themselves, however, are shared across all @@ -2207,7 +2190,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { TableInfo.Table.push_back(MCD::OPC_Fail); // Print the table to the output stream. - emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), I->first.first); + emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), Opc.first.first); OS.flush(); } diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 6fdf22d..c5999de 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -143,7 +143,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { Res += "|(1<getValueAsInt("Size") << ",\t0"; - // Emit all of the target indepedent flags... + // Emit all of the target independent flags... if (Inst.isPseudo) OS << "|(1<TheDef->getName() << "\t= " << Num++ << ",\n"; OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; - OS << " };\n"; + OS << " };\n\n"; OS << "namespace Sched {\n"; OS << " enum {\n"; Num = 0; for (const auto &Class : SchedModels.explicit_classes()) OS << " " << Class.Name << "\t= " << Num++ << ",\n"; OS << " SCHED_LIST_END = " << SchedModels.numInstrSchedClasses() << "\n"; - OS << " };\n}\n}\n"; + OS << " };\n"; + OS << "} // End Sched namespace\n"; + OS << "} // End " << Namespace << " namespace\n"; OS << "} // End llvm namespace \n"; OS << "#endif // GET_INSTRINFO_ENUM\n\n"; diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 37f6de0..e71c695 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -257,7 +257,10 @@ enum IIT_Info { IIT_ANYPTR = 26, IIT_V1 = 27, IIT_VARARG = 28, - IIT_HALF_VEC_ARG = 29 + IIT_HALF_VEC_ARG = 29, + IIT_SAME_VEC_WIDTH_ARG = 30, + IIT_PTR_TO_ARG = 31, + IIT_VEC_OF_PTRS_TO_ELT = 32 }; @@ -289,7 +292,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, } } -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) #pragma optimize("",off) // MSVC 2010 optimizer can't deal with this function. #endif @@ -305,9 +308,20 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, Sig.push_back(IIT_TRUNC_ARG); else if (R->isSubClassOf("LLVMHalfElementsVectorType")) Sig.push_back(IIT_HALF_VEC_ARG); + else if (R->isSubClassOf("LLVMVectorSameWidth")) { + Sig.push_back(IIT_SAME_VEC_WIDTH_ARG); + Sig.push_back((Number << 3) | ArgCodes[Number]); + MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy")); + EncodeFixedValueType(VT, Sig); + return; + } + else if (R->isSubClassOf("LLVMPointerTo")) + Sig.push_back(IIT_PTR_TO_ARG); + else if (R->isSubClassOf("LLVMVectorOfPointersToElt")) + Sig.push_back(IIT_VEC_OF_PTRS_TO_ELT); else Sig.push_back(IIT_ARG); - return Sig.push_back((Number << 2) | ArgCodes[Number]); + return Sig.push_back((Number << 3) | ArgCodes[Number]); } MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT")); @@ -318,7 +332,8 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, case MVT::iPTRAny: ++Tmp; // FALL THROUGH. case MVT::vAny: ++Tmp; // FALL THROUGH. case MVT::fAny: ++Tmp; // FALL THROUGH. - case MVT::iAny: { + case MVT::iAny: ++Tmp; // FALL THROUGH. + case MVT::Any: { // If this is an "any" valuetype, then the type is the type of the next // type in the list specified to getIntrinsic(). Sig.push_back(IIT_ARG); @@ -327,8 +342,8 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, unsigned ArgNo = ArgCodes.size(); ArgCodes.push_back(Tmp); - // Encode what sort of argument it must be in the low 2 bits of the ArgNo. - return Sig.push_back((ArgNo << 2) | Tmp); + // Encode what sort of argument it must be in the low 3 bits of the ArgNo. + return Sig.push_back((ArgNo << 3) | Tmp); } case MVT::iPTR: { @@ -366,7 +381,7 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, EncodeFixedValueType(VT, Sig); } -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) #pragma optimize("",on) #endif diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 79d08a9..5a6694e 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -53,27 +53,30 @@ public: void run(raw_ostream &o); private: - void EmitRegMapping(raw_ostream &o, - const std::vector &Regs, bool isCtor); + void EmitRegMapping(raw_ostream &o, const std::deque &Regs, + bool isCtor); void EmitRegMappingTables(raw_ostream &o, - const std::vector &Regs, + const std::deque &Regs, bool isCtor); void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, const std::string &ClassName); void emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank, const std::string &ClassName); + void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank, + const std::string &ClassName); }; } // End anonymous namespace // runEnums - Print out enum values for all of the registers. void RegisterInfoEmitter::runEnums(raw_ostream &OS, CodeGenTarget &Target, CodeGenRegBank &Bank) { - const std::vector &Registers = Bank.getRegisters(); + const auto &Registers = Bank.getRegisters(); // Register enums are stored as uint16_t in the tables. Make sure we'll fit. assert(Registers.size() <= 0xffff && "Too many regs to fit in tables"); - std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace"); + std::string Namespace = + Registers.front().TheDef->getValueAsString("Namespace"); emitSourceFileHeader("Target Register Enum Values", OS); @@ -90,17 +93,16 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "namespace " << Namespace << " {\n"; OS << "enum {\n NoRegister,\n"; - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - OS << " " << Registers[i]->getName() << " = " << - Registers[i]->EnumValue << ",\n"; - assert(Registers.size() == Registers[Registers.size()-1]->EnumValue && + for (const auto &Reg : Registers) + OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n"; + assert(Registers.size() == Registers.back().EnumValue && "Register enum value mismatch!"); OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n"; OS << "};\n"; if (!Namespace.empty()) OS << "}\n"; - ArrayRef RegisterClasses = Bank.getRegClasses(); + const auto &RegisterClasses = Bank.getRegClasses(); if (!RegisterClasses.empty()) { // RegisterClass enums are stored as uint16_t in the tables. @@ -111,11 +113,9 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; OS << "enum {\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - if (i) OS << ",\n"; - OS << " " << RegisterClasses[i]->getName() << "RegClassID"; - OS << " = " << i; - } + for (const auto &RC : RegisterClasses) + OS << " " << RC.getName() << "RegClassID" + << " = " << RC.EnumValue << ",\n"; OS << "\n };\n"; if (!Namespace.empty()) OS << "}\n"; @@ -137,25 +137,38 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "}\n"; } - ArrayRef SubRegIndices = Bank.getSubRegIndices(); + auto &SubRegIndices = Bank.getSubRegIndices(); if (!SubRegIndices.empty()) { OS << "\n// Subregister indices\n"; - std::string Namespace = - SubRegIndices[0]->getNamespace(); + std::string Namespace = SubRegIndices.front().getNamespace(); if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; OS << "enum {\n NoSubRegister,\n"; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) - OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; + unsigned i = 0; + for (const auto &Idx : SubRegIndices) + OS << " " << Idx.getName() << ",\t// " << ++i << "\n"; OS << " NUM_TARGET_SUBREGS\n};\n"; if (!Namespace.empty()) OS << "}\n"; } - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_ENUM\n\n"; } +static void printInt(raw_ostream &OS, int Val) { + OS << Val; +} + +static const char *getMinimalTypeForRange(uint64_t Range) { + assert(Range < 0xFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFF) + return "uint32_t"; + if (Range > 0xFF) + return "uint16_t"; + return "uint8_t"; +} + void RegisterInfoEmitter:: EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, const std::string &ClassName) { @@ -166,9 +179,8 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "const RegClassWeight &" << ClassName << "::\n" << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" << " static const RegClassWeight RCWeightTable[] = {\n"; - for (unsigned i = 0, e = NumRCs; i != e; ++i) { - const CodeGenRegisterClass &RC = *RegBank.getRegClasses()[i]; - const CodeGenRegister::Set &Regs = RC.getMembers(); + for (const auto &RC : RegBank.getRegClasses()) { + const CodeGenRegister::Vec &Regs = RC.getMembers(); if (Regs.empty()) OS << " {0, 0"; else { @@ -179,7 +191,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, } OS << "}, \t// " << RC.getName() << "\n"; } - OS << " {0, 0} };\n" + OS << " };\n" << " return RCWeightTable[RC->getID()];\n" << "}\n\n"; @@ -204,7 +216,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, assert(RU.Weight < 256 && "RegUnit too heavy"); OS << RU.Weight << ", "; } - OS << "0 };\n" + OS << "};\n" << " return RUWeightTable[RegUnit];\n"; } else { @@ -222,8 +234,11 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "const char *" << ClassName << "::\n" << "getRegPressureSetName(unsigned Idx) const {\n" << " static const char *PressureNameTable[] = {\n"; + unsigned MaxRegUnitWeight = 0; for (unsigned i = 0; i < NumSets; ++i ) { - OS << " \"" << RegBank.getRegSetAt(i).Name << "\",\n"; + const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); + MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight); + OS << " \"" << RegUnits.Name << "\",\n"; } OS << " nullptr };\n" << " return PressureNameTable[Idx];\n" @@ -233,63 +248,54 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "// This limit must be adjusted dynamically for reserved registers.\n" << "unsigned " << ClassName << "::\n" << "getRegPressureSetLimit(unsigned Idx) const {\n" - << " static const unsigned PressureLimitTable[] = {\n"; + << " static const " << getMinimalTypeForRange(MaxRegUnitWeight) + << " PressureLimitTable[] = {\n"; for (unsigned i = 0; i < NumSets; ++i ) { const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); OS << " " << RegUnits.Weight << ", \t// " << i << ": " << RegUnits.Name << "\n"; } - OS << " 0 };\n" + OS << " };\n" << " return PressureLimitTable[Idx];\n" << "}\n\n"; + SequenceToOffsetTable> PSetsSeqs; + // This table may be larger than NumRCs if some register units needed a list // of unit sets that did not correspond to a register class. unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists(); - OS << "/// Table of pressure sets per register class or unit.\n" - << "static const int RCSetsTable[] = {\n "; - std::vector RCSetStarts(NumRCUnitSets); - for (unsigned i = 0, StartIdx = 0, e = NumRCUnitSets; i != e; ++i) { - RCSetStarts[i] = StartIdx; + std::vector> PSets(NumRCUnitSets); + + for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) { ArrayRef PSetIDs = RegBank.getRCPressureSetIDs(i); - std::vector PSets; - PSets.reserve(PSetIDs.size()); + PSets[i].reserve(PSetIDs.size()); for (ArrayRef::iterator PSetI = PSetIDs.begin(), PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { - PSets.push_back(RegBank.getRegPressureSet(*PSetI).Order); - } - std::sort(PSets.begin(), PSets.end()); - for (unsigned j = 0, e = PSets.size(); j < e; ++j) { - OS << PSets[j] << ", "; - ++StartIdx; + PSets[i].push_back(RegBank.getRegPressureSet(*PSetI).Order); } - OS << "-1, \t// #" << RCSetStarts[i] << " "; - if (i < NumRCs) - OS << RegBank.getRegClasses()[i]->getName(); - else { - OS << "inferred"; - for (ArrayRef::iterator PSetI = PSetIDs.begin(), - PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { - OS << "~" << RegBank.getRegSetAt(*PSetI).Name; - } - } - OS << "\n "; - ++StartIdx; + std::sort(PSets[i].begin(), PSets[i].end()); + PSetsSeqs.add(PSets[i]); } - OS << "-1 };\n\n"; + + PSetsSeqs.layout(); + + OS << "/// Table of pressure sets per register class or unit.\n" + << "static const int RCSetsTable[] = {\n"; + PSetsSeqs.emit(OS, printInt, "-1"); + OS << "};\n\n"; OS << "/// Get the dimensions of register pressure impacted by this " << "register class.\n" << "/// Returns a -1 terminated array of pressure set IDs\n" << "const int* " << ClassName << "::\n" << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n"; - OS << " static const unsigned RCSetStartTable[] = {\n "; + OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1) + << " RCSetStartTable[] = {\n "; for (unsigned i = 0, e = NumRCs; i != e; ++i) { - OS << RCSetStarts[i] << ","; + OS << PSetsSeqs.get(PSets[i]) << ","; } - OS << "0 };\n" - << " unsigned SetListStart = RCSetStartTable[RC->getID()];\n" - << " return &RCSetsTable[SetListStart];\n" + OS << "};\n" + << " return &RCSetsTable[RCSetStartTable[RC->getID()]];\n" << "}\n\n"; OS << "/// Get the dimensions of register pressure impacted by this " @@ -299,29 +305,28 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "getRegUnitPressureSets(unsigned RegUnit) const {\n" << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() << " && \"invalid register unit\");\n"; - OS << " static const unsigned RUSetStartTable[] = {\n "; + OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1) + << " RUSetStartTable[] = {\n "; for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); UnitIdx < UnitEnd; ++UnitIdx) { - OS << RCSetStarts[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx] << ","; + OS << PSetsSeqs.get(PSets[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx]) + << ","; } - OS << "0 };\n" - << " unsigned SetListStart = RUSetStartTable[RegUnit];\n" - << " return &RCSetsTable[SetListStart];\n" + OS << "};\n" + << " return &RCSetsTable[RUSetStartTable[RegUnit]];\n" << "}\n\n"; } -void -RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, - const std::vector &Regs, - bool isCtor) { +void RegisterInfoEmitter::EmitRegMappingTables( + raw_ostream &OS, const std::deque &Regs, bool isCtor) { // Collect all information about dwarf register numbers typedef std::map, LessRecordRegister> DwarfRegNumsMapTy; DwarfRegNumsMapTy DwarfRegNums; // First, just pull all provided information to the map unsigned maxLength = 0; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (auto &RE : Regs) { + Record *Reg = RE.TheDef; std::vector RegNums = Reg->getValueAsListOfInts("DwarfNumbers"); maxLength = std::max((size_t)maxLength, RegNums.size()); if (DwarfRegNums.count(Reg)) @@ -339,7 +344,7 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, for (unsigned i = I->second.size(), e = maxLength; i != e; ++i) I->second.push_back(-1); - std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + std::string Namespace = Regs.front().TheDef->getValueAsString("Namespace"); OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n"; @@ -387,8 +392,8 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, } } - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (auto &RE : Regs) { + Record *Reg = RE.TheDef; const RecordVal *V = Reg->getValue("DwarfAlias"); if (!V || !V->getValue()) continue; @@ -435,15 +440,13 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, } } -void -RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, - const std::vector &Regs, - bool isCtor) { +void RegisterInfoEmitter::EmitRegMapping( + raw_ostream &OS, const std::deque &Regs, bool isCtor) { // Emit the initializer so the tables from EmitRegMappingTables get wired up // to the MCRegisterInfo object. unsigned maxLength = 0; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (auto &RE : Regs) { + Record *Reg = RE.TheDef; maxLength = std::max((size_t)maxLength, Reg->getValueAsListOfInts("DwarfNumbers").size()); } @@ -451,7 +454,7 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, if (!maxLength) return; - std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + std::string Namespace = Regs.front().TheDef->getValueAsString("Namespace"); // Emit reverse information about the dwarf register numbers. for (unsigned j = 0; j < 2; ++j) { @@ -565,15 +568,16 @@ static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) { // 0 differential which means we can't encode repeated elements. typedef SmallVector DiffVec; +typedef SmallVector MaskVec; // Differentially encode a sequence of numbers into V. The starting value and // terminating 0 are not added to V, so it will have the same size as List. static -DiffVec &diffEncode(DiffVec &V, unsigned InitVal, ArrayRef List) { +DiffVec &diffEncode(DiffVec &V, unsigned InitVal, SparseBitVector<> List) { assert(V.empty() && "Clear DiffVec before diffEncode."); uint16_t Val = uint16_t(InitVal); - for (unsigned i = 0; i != List.size(); ++i) { - uint16_t Cur = List[i]; + + for (uint16_t Cur : List) { V.push_back(Cur - Val); Val = Cur; } @@ -597,6 +601,10 @@ static void printDiff16(raw_ostream &OS, uint16_t Val) { OS << Val; } +static void printMask(raw_ostream &OS, unsigned Val) { + OS << format("0x%08X", Val); +} + // Try to combine Idx's compose map into Vec if it is compatible. // Return false if it's not possible. static bool combine(const CodeGenSubRegIndex *Idx, @@ -616,20 +624,11 @@ static bool combine(const CodeGenSubRegIndex *Idx, return true; } -static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range < 0xFFFFFFFFULL && "Enum too large"); - if (Range > 0xFFFF) - return "uint32_t"; - if (Range > 0xFF) - return "uint16_t"; - return "uint8_t"; -} - void RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank, const std::string &ClName) { - ArrayRef SubRegIndices = RegBank.getSubRegIndices(); + const auto &SubRegIndices = RegBank.getSubRegIndices(); OS << "unsigned " << ClName << "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n"; @@ -644,10 +643,12 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, SmallVector RowMap; SmallVector, 4> Rows; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { + auto SubRegIndicesSize = + std::distance(SubRegIndices.begin(), SubRegIndices.end()); + for (const auto &Idx : SubRegIndices) { unsigned Found = ~0u; for (unsigned r = 0, re = Rows.size(); r != re; ++r) { - if (combine(SubRegIndices[i], Rows[r])) { + if (combine(&Idx, Rows[r])) { Found = r; break; } @@ -655,27 +656,27 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, if (Found == ~0u) { Found = Rows.size(); Rows.resize(Found + 1); - Rows.back().resize(SubRegIndices.size()); - combine(SubRegIndices[i], Rows.back()); + Rows.back().resize(SubRegIndicesSize); + combine(&Idx, Rows.back()); } RowMap.push_back(Found); } // Output the row map if there is multiple rows. if (Rows.size() > 1) { - OS << " static const " << getMinimalTypeForRange(Rows.size()) - << " RowMap[" << SubRegIndices.size() << "] = {\n "; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + OS << " static const " << getMinimalTypeForRange(Rows.size()) << " RowMap[" + << SubRegIndicesSize << "] = {\n "; + for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) OS << RowMap[i] << ", "; OS << "\n };\n"; } // Output the rows. - OS << " static const " << getMinimalTypeForRange(SubRegIndices.size()+1) - << " Rows[" << Rows.size() << "][" << SubRegIndices.size() << "] = {\n"; + OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1) + << " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n"; for (unsigned r = 0, re = Rows.size(); r != re; ++r) { OS << " { "; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) if (Rows[r][i]) OS << Rows[r][i]->EnumValue << ", "; else @@ -684,8 +685,8 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, } OS << " };\n\n"; - OS << " --IdxA; assert(IdxA < " << SubRegIndices.size() << ");\n" - << " --IdxB; assert(IdxB < " << SubRegIndices.size() << ");\n"; + OS << " --IdxA; assert(IdxA < " << SubRegIndicesSize << ");\n" + << " --IdxB; assert(IdxB < " << SubRegIndicesSize << ");\n"; if (Rows.size() > 1) OS << " return Rows[RowMap[IdxA]][IdxB];\n"; else @@ -693,6 +694,95 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, OS << "}\n\n"; } +void +RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, + CodeGenRegBank &RegBank, + const std::string &ClName) { + // See the comments in computeSubRegLaneMasks() for our goal here. + const auto &SubRegIndices = RegBank.getSubRegIndices(); + + // Create a list of Mask+Rotate operations, with equivalent entries merged. + SmallVector SubReg2SequenceIndexMap; + SmallVector, 4> Sequences; + for (const auto &Idx : SubRegIndices) { + const SmallVector &IdxSequence + = Idx.CompositionLaneMaskTransform; + + unsigned Found = ~0u; + unsigned SIdx = 0; + unsigned NextSIdx; + for (size_t s = 0, se = Sequences.size(); s != se; ++s, SIdx = NextSIdx) { + SmallVectorImpl &Sequence = Sequences[s]; + NextSIdx = SIdx + Sequence.size() + 1; + if (Sequence.size() != IdxSequence.size()) + continue; + bool Identical = true; + for (size_t o = 0, oe = Sequence.size(); o != oe; ++o) { + if (Sequence[o] != IdxSequence[o]) { + Identical = false; + break; + } + } + if (Identical) { + Found = SIdx; + break; + } + } + if (Found == ~0u) { + Sequences.push_back(IdxSequence); + Found = SIdx; + } + SubReg2SequenceIndexMap.push_back(Found); + } + + OS << "unsigned " << ClName + << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, unsigned LaneMask)" + " const {\n"; + + OS << " struct MaskRolOp {\n" + " unsigned Mask;\n" + " uint8_t RotateLeft;\n" + " };\n" + " static const MaskRolOp Seqs[] = {\n"; + unsigned Idx = 0; + for (size_t s = 0, se = Sequences.size(); s != se; ++s) { + OS << " "; + const SmallVectorImpl &Sequence = Sequences[s]; + for (size_t p = 0, pe = Sequence.size(); p != pe; ++p) { + const MaskRolPair &P = Sequence[p]; + OS << format("{ 0x%08X, %2u }, ", P.Mask, P.RotateLeft); + } + OS << "{ 0, 0 }"; + if (s+1 != se) + OS << ", "; + OS << " // Sequence " << Idx << "\n"; + Idx += Sequence.size() + 1; + } + OS << " };\n" + " static const MaskRolOp *CompositeSequences[] = {\n"; + for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) { + OS << " "; + unsigned Idx = SubReg2SequenceIndexMap[i]; + OS << format("&Seqs[%u]", Idx); + if (i+1 != e) + OS << ","; + OS << " // to " << SubRegIndices[i].getName() << "\n"; + } + OS << " };\n\n"; + + OS << " --IdxA; assert(IdxA < " << SubRegIndices.size() + << " && \"Subregister index out of bounds\");\n" + " unsigned Result = 0;\n" + " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)" + " {\n" + " unsigned Masked = LaneMask & Ops->Mask;\n" + " Result |= (Masked << Ops->RotateLeft) & 0xFFFFFFFF;\n" + " Result |= (Masked >> ((32 - Ops->RotateLeft) & 0x1F));\n" + " }\n" + " return Result;\n" + "}\n"; +} + // // runMCDesc - Print out MC register descriptions. // @@ -704,9 +794,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; OS << "#undef GET_REGINFO_MC_DESC\n"; - const std::vector &Regs = RegBank.getRegisters(); + const auto &Regs = RegBank.getRegisters(); - ArrayRef SubRegIndices = RegBank.getSubRegIndices(); + auto &SubRegIndices = RegBank.getSubRegIndices(); // The lists of sub-registers and super-registers go in the same array. That // allows us to share suffixes. typedef std::vector RegVec; @@ -718,36 +808,40 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, SmallVector RegUnitLists(Regs.size()); SmallVector RegUnitInitScale(Regs.size()); + // List of lane masks accompanying register unit sequences. + SequenceToOffsetTable LaneMaskSeqs; + SmallVector RegUnitLaneMasks(Regs.size()); + // Keep track of sub-register names as well. These are not differentially // encoded. typedef SmallVector SubRegIdxVec; - SequenceToOffsetTable SubRegIdxSeqs; + SequenceToOffsetTable> SubRegIdxSeqs; SmallVector SubRegIdxLists(Regs.size()); SequenceToOffsetTable RegStrings; // Precompute register lists for the SequenceToOffsetTable. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - - RegStrings.add(Reg->getName()); + unsigned i = 0; + for (auto I = Regs.begin(), E = Regs.end(); I != E; ++I, ++i) { + const auto &Reg = *I; + RegStrings.add(Reg.getName()); // Compute the ordered sub-register list. SetVector SR; - Reg->addSubRegsPreOrder(SR, RegBank); - diffEncode(SubRegLists[i], Reg->EnumValue, SR.begin(), SR.end()); + Reg.addSubRegsPreOrder(SR, RegBank); + diffEncode(SubRegLists[i], Reg.EnumValue, SR.begin(), SR.end()); DiffSeqs.add(SubRegLists[i]); // Compute the corresponding sub-register indexes. SubRegIdxVec &SRIs = SubRegIdxLists[i]; for (unsigned j = 0, je = SR.size(); j != je; ++j) - SRIs.push_back(Reg->getSubRegIndex(SR[j])); + SRIs.push_back(Reg.getSubRegIndex(SR[j])); SubRegIdxSeqs.add(SRIs); // Super-registers are already computed. - const RegVec &SuperRegList = Reg->getSuperRegs(); - diffEncode(SuperRegLists[i], Reg->EnumValue, - SuperRegList.begin(), SuperRegList.end()); + const RegVec &SuperRegList = Reg.getSuperRegs(); + diffEncode(SuperRegLists[i], Reg.EnumValue, SuperRegList.begin(), + SuperRegList.end()); DiffSeqs.add(SuperRegLists[i]); // Differentially encode the register unit list, seeded by register number. @@ -762,22 +856,36 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // // Check the neighboring registers for arithmetic progressions. unsigned ScaleA = ~0u, ScaleB = ~0u; - ArrayRef RUs = Reg->getNativeRegUnits(); - if (i > 0 && Regs[i-1]->getNativeRegUnits().size() == RUs.size()) - ScaleB = RUs.front() - Regs[i-1]->getNativeRegUnits().front(); - if (i+1 != Regs.size() && - Regs[i+1]->getNativeRegUnits().size() == RUs.size()) - ScaleA = Regs[i+1]->getNativeRegUnits().front() - RUs.front(); + SparseBitVector<> RUs = Reg.getNativeRegUnits(); + if (I != Regs.begin() && + std::prev(I)->getNativeRegUnits().count() == RUs.count()) + ScaleB = *RUs.begin() - *std::prev(I)->getNativeRegUnits().begin(); + if (std::next(I) != Regs.end() && + std::next(I)->getNativeRegUnits().count() == RUs.count()) + ScaleA = *std::next(I)->getNativeRegUnits().begin() - *RUs.begin(); unsigned Scale = std::min(ScaleB, ScaleA); // Default the scale to 0 if it can't be encoded in 4 bits. if (Scale >= 16) Scale = 0; RegUnitInitScale[i] = Scale; - DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg->EnumValue, RUs)); + DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg.EnumValue, RUs)); + + const auto &RUMasks = Reg.getRegUnitLaneMasks(); + MaskVec &LaneMaskVec = RegUnitLaneMasks[i]; + assert(LaneMaskVec.empty()); + LaneMaskVec.insert(LaneMaskVec.begin(), RUMasks.begin(), RUMasks.end()); + // Terminator mask should not be used inside of the list. +#ifndef NDEBUG + for (unsigned M : LaneMaskVec) { + assert(M != ~0u && "terminator mask should not be part of the list"); + } +#endif + LaneMaskSeqs.add(LaneMaskVec); } // Compute the final layout of the sequence table. DiffSeqs.layout(); + LaneMaskSeqs.layout(); SubRegIdxSeqs.layout(); OS << "namespace llvm {\n\n"; @@ -789,6 +897,11 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, DiffSeqs.emit(OS, printDiff16); OS << "};\n\n"; + // Emit the shared table of regunit lane mask sequences. + OS << "extern const unsigned " << TargetName << "LaneMaskLists[] = {\n"; + LaneMaskSeqs.emit(OS, printMask, "~0u"); + OS << "};\n\n"; + // Emit the table of sub-register indexes. OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n"; SubRegIdxSeqs.emit(OS, printSubRegIndex); @@ -798,12 +911,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName << "SubRegIdxRanges[] = {\n"; OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; - for (ArrayRef::const_iterator - SRI = SubRegIndices.begin(), SRE = SubRegIndices.end(); - SRI != SRE; ++SRI) { - OS << " { " << (*SRI)->Offset << ", " - << (*SRI)->Size - << " },\t// " << (*SRI)->getName() << "\n"; + for (const auto &Idx : SubRegIndices) { + OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// " + << Idx.getName() << "\n"; } OS << "};\n\n"; @@ -815,16 +925,17 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[] = { // Descriptors\n"; - OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0 },\n"; + OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n"; // Emit the register descriptors now. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - OS << " { " << RegStrings.get(Reg->getName()) << ", " - << DiffSeqs.get(SubRegLists[i]) << ", " - << DiffSeqs.get(SuperRegLists[i]) << ", " - << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " - << (DiffSeqs.get(RegUnitLists[i])*16 + RegUnitInitScale[i]) << " },\n"; + i = 0; + for (const auto &Reg : Regs) { + OS << " { " << RegStrings.get(Reg.getName()) << ", " + << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i]) + << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " + << (DiffSeqs.get(RegUnitLists[i]) * 16 + RegUnitInitScale[i]) << ", " + << LaneMaskSeqs.get(RegUnitLaneMasks[i]) << " },\n"; + ++i; } OS << "};\n\n"; // End of register descriptors... @@ -842,7 +953,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "};\n\n"; - ArrayRef RegisterClasses = RegBank.getRegClasses(); + const auto &RegisterClasses = RegBank.getRegClasses(); // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; @@ -850,8 +961,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, SequenceToOffsetTable RegClassStrings; // Emit the register enum value arrays for each RegisterClass - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { ArrayRef Order = RC.getOrder(); // Give the register class a legal C name if it's anonymous. @@ -891,9 +1001,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; - + for (const auto &RC : RegisterClasses) { // Asserts to make sure values will fit in table assuming types from // MCRegisterInfo.h assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large."); @@ -919,8 +1027,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "RegEncodingTable[] = {\n"; // Add entry for NoRegister OS << " 0,\n"; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (const auto &RE : Regs) { + Record *Reg = RE.TheDef; BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding"); uint64_t Value = 0; for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { @@ -934,25 +1042,23 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " - << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) {\n" + << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) " + "{\n" << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " - << RegisterClasses.size() << ", " - << TargetName << "RegUnitRoots, " - << RegBank.getNumNativeRegUnits() << ", " - << TargetName << "RegDiffLists, " - << TargetName << "RegStrings, " - << TargetName << "RegClassStrings, " - << TargetName << "SubRegIdxLists, " - << (SubRegIndices.size() + 1) << ",\n" - << TargetName << "SubRegIdxRanges, " - << TargetName << "RegEncodingTable);\n\n"; + << Regs.size() + 1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " + << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " + << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " + << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, " + << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, " + << (std::distance(SubRegIndices.begin(), SubRegIndices.end()) + 1) << ",\n" + << TargetName << "SubRegIdxRanges, " << TargetName + << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); OS << "}\n\n"; - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_MC_DESC\n\n"; } @@ -979,6 +1085,8 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, if (!RegBank.getSubRegIndices().empty()) { OS << " unsigned composeSubRegIndicesImpl" << "(unsigned, unsigned) const override;\n" + << " unsigned composeSubRegIndexLaneMaskImpl" + << "(unsigned, unsigned) const override;\n" << " const TargetRegisterClass *getSubClassWithSubReg" << "(const TargetRegisterClass*, unsigned) const override;\n"; } @@ -994,14 +1102,13 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, << "unsigned RegUnit) const override;\n" << "};\n\n"; - ArrayRef RegisterClasses = RegBank.getRegClasses(); + const auto &RegisterClasses = RegBank.getRegClasses(); if (!RegisterClasses.empty()) { - OS << "namespace " << RegisterClasses[0]->Namespace + OS << "namespace " << RegisterClasses.front().Namespace << " { // Register classes\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RegisterClasses[i]; + for (const auto &RC : RegisterClasses) { const std::string &Name = RC.getName(); // Output the extern for the instance. @@ -1009,7 +1116,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, } OS << "} // end of namespace " << TargetName << "\n\n"; } - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_HEADER\n\n"; } @@ -1031,15 +1138,14 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << "MCRegisterClasses[];\n"; // Start out by emitting each of the register classes. - ArrayRef RegisterClasses = RegBank.getRegClasses(); - ArrayRef SubRegIndices = RegBank.getSubRegIndices(); + const auto &RegisterClasses = RegBank.getRegClasses(); + const auto &SubRegIndices = RegBank.getSubRegIndices(); // Collect all registers belonging to any allocatable class. std::set AllocatableRegs; // Collect allocatable registers. - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { ArrayRef Order = RC.getOrder(); if (RC.Allocatable) @@ -1048,8 +1154,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Build a shared array of value types. SequenceToOffsetTable > VTSeqs; - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) - VTSeqs.add(RegisterClasses[rc]->VTs); + for (const auto &RC : RegisterClasses) + VTSeqs.add(RC.VTs); VTSeqs.layout(); OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n"; VTSeqs.emit(OS, printSimpleValueType, "MVT::Other"); @@ -1057,18 +1163,17 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit SubRegIndex names, skipping 0. OS << "\nstatic const char *const SubRegIndexNameTable[] = { \""; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - OS << SubRegIndices[i]->getName(); - if (i + 1 != e) - OS << "\", \""; + + for (const auto &Idx : SubRegIndices) { + OS << Idx.getName(); + OS << "\", \""; } OS << "\" };\n\n"; // Emit SubRegIndex lane masks, including 0. OS << "\nstatic const unsigned SubRegIndexLaneMaskTable[] = {\n ~0u,\n"; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - OS << format(" 0x%08x, // ", SubRegIndices[i]->LaneMask) - << SubRegIndices[i]->getName() << '\n'; + for (const auto &Idx : SubRegIndices) { + OS << format(" 0x%08x, // ", Idx.LaneMask) << Idx.getName() << '\n'; } OS << " };\n\n"; @@ -1100,27 +1205,25 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Compress the sub-reg index lists. typedef std::vector IdxList; SmallVector SuperRegIdxLists(RegisterClasses.size()); - SequenceToOffsetTable SuperRegIdxSeqs; + SequenceToOffsetTable> SuperRegIdxSeqs; BitVector MaskBV(RegisterClasses.size()); - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { OS << "static const uint32_t " << RC.getName() << "SubClassMask[] = {\n "; printBitVectorAsHex(OS, RC.getSubClasses(), 32); // Emit super-reg class masks for any relevant SubRegIndices that can // project into RC. - IdxList &SRIList = SuperRegIdxLists[rc]; - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - CodeGenSubRegIndex *Idx = SubRegIndices[sri]; + IdxList &SRIList = SuperRegIdxLists[RC.EnumValue]; + for (auto &Idx : SubRegIndices) { MaskBV.reset(); - RC.getSuperRegClasses(Idx, MaskBV); + RC.getSuperRegClasses(&Idx, MaskBV); if (MaskBV.none()) continue; - SRIList.push_back(Idx); + SRIList.push_back(&Idx); OS << "\n "; printBitVectorAsHex(OS, MaskBV, 32); - OS << "// " << Idx->getName(); + OS << "// " << Idx.getName(); } SuperRegIdxSeqs.add(SRIList); OS << "\n};\n\n"; @@ -1132,8 +1235,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "};\n\n"; // Emit NULL terminated super-class lists. - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { ArrayRef Supers = RC.getSuperClasses(); // Skip classes without supers. We can reuse NullRegClasses. @@ -1142,14 +1244,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "static const TargetRegisterClass *const " << RC.getName() << "Superclasses[] = {\n"; - for (unsigned i = 0; i != Supers.size(); ++i) - OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n"; + for (const auto *Super : Supers) + OS << " &" << Super->getQualifiedName() << "RegClass,\n"; OS << " nullptr\n};\n\n"; } // Emit methods. - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RegisterClasses[i]; + for (const auto &RC : RegisterClasses) { if (!RC.AltOrderSelect.empty()) { OS << "\nstatic inline unsigned " << RC.getName() << "AltOrderSelect(const MachineFunction &MF) {" @@ -1177,22 +1278,21 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << ")\n };\n const unsigned Select = " << RC.getName() << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() << ");\n return Order[Select];\n}\n"; - } + } } // Now emit the actual value-initialized register class instances. - OS << "namespace " << RegisterClasses[0]->Namespace + OS << "\nnamespace " << RegisterClasses.front().Namespace << " { // Register class instances\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RegisterClasses[i]; - OS << " extern const TargetRegisterClass " - << RegisterClasses[i]->getName() << "RegClass = {\n " - << '&' << Target.getName() << "MCRegisterClasses[" << RC.getName() - << "RegClassID],\n " - << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " - << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + " - << SuperRegIdxSeqs.get(SuperRegIdxLists[i]) << ",\n "; + for (const auto &RC : RegisterClasses) { + OS << " extern const TargetRegisterClass " << RC.getName() + << "RegClass = {\n " << '&' << Target.getName() + << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n " + << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName() + << "SubClassMask,\n SuperRegIdxSeqs + " + << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n " + << format("0x%08x,\n ", RC.LaneMask); if (RC.getSuperClasses().empty()) OS << "NullRegClasses,\n "; else @@ -1209,9 +1309,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "\nnamespace {\n"; OS << " const TargetRegisterClass* const RegisterClasses[] = {\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) - OS << " &" << RegisterClasses[i]->getQualifiedName() - << "RegClass,\n"; + for (const auto &RC : RegisterClasses) + OS << " &" << RC.getQualifiedName() << "RegClass,\n"; OS << " };\n"; OS << "}\n"; // End of anonymous namespace... @@ -1221,9 +1320,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n"; OS << " { 0, 0 },\n"; - const std::vector &Regs = RegBank.getRegisters(); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; + const auto &Regs = RegBank.getRegisters(); + for (const auto &Reg : Regs) { OS << " { "; OS << Reg.CostPerUse << ", " << int(AllocatableRegs.count(Reg.TheDef)) << " },\n"; @@ -1233,8 +1331,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, std::string ClassName = Target.getName() + "GenRegisterInfo"; - if (!SubRegIndices.empty()) + auto SubRegIndicesSize = + std::distance(SubRegIndices.begin(), SubRegIndices.end()); + + if (!SubRegIndices.empty()) { emitComposeSubRegIndices(OS, RegBank, ClassName); + emitComposeSubRegIndexLaneMask(OS, RegBank, ClassName); + } // Emit getSubClassWithSubReg. if (!SubRegIndices.empty()) { @@ -1249,23 +1352,21 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << " static const uint16_t Table["; else PrintFatalError("Too many register classes."); - OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n"; - for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { - const CodeGenRegisterClass &RC = *RegisterClasses[rci]; + OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n"; + for (const auto &RC : RegisterClasses) { OS << " {\t// " << RC.getName() << "\n"; - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - CodeGenSubRegIndex *Idx = SubRegIndices[sri]; - if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx)) - OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName() + for (auto &Idx : SubRegIndices) { + if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(&Idx)) + OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName() << " -> " << SRC->getName() << "\n"; else - OS << " 0,\t// " << Idx->getName() << "\n"; + OS << " 0,\t// " << Idx.getName() << "\n"; } OS << " },\n"; } OS << " };\n assert(RC && \"Missing regclass\");\n" << " if (!Idx) return RC;\n --Idx;\n" - << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" + << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" << " unsigned TV = Table[RC->getID()][Idx];\n" << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; } @@ -1275,6 +1376,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the constructor of the class... OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; + OS << "extern const unsigned " << TargetName << "LaneMaskLists[];\n"; OS << "extern const char " << TargetName << "RegStrings[];\n"; OS << "extern const char " << TargetName << "RegClassStrings[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; @@ -1292,16 +1394,17 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << " SubRegIndexNameTable, SubRegIndexLaneMaskTable, 0x"; OS.write_hex(RegBank.CoveringLanes); OS << ") {\n" - << " InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA, PC,\n " << TargetName + << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1 + << ", RA, PC,\n " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" << " " << TargetName << "RegUnitRoots,\n" << " " << RegBank.getNumNativeRegUnits() << ",\n" << " " << TargetName << "RegDiffLists,\n" + << " " << TargetName << "LaneMaskLists,\n" << " " << TargetName << "RegStrings,\n" << " " << TargetName << "RegClassStrings,\n" << " " << TargetName << "SubRegIdxLists,\n" - << " " << SubRegIndices.size() + 1 << ",\n" + << " " << SubRegIndicesSize + 1 << ",\n" << " " << TargetName << "SubRegIdxRanges,\n" << " " << TargetName << "RegEncodingTable);\n\n"; @@ -1345,7 +1448,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "\n\n"; - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; } diff --git a/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h index b58de4c..66506ea 100644 --- a/utils/TableGen/SequenceToOffsetTable.h +++ b/utils/TableGen/SequenceToOffsetTable.h @@ -84,6 +84,11 @@ public: bool empty() const { return Seqs.empty(); } + unsigned size() const { + assert(Entries && "Call layout() before size()"); + return Entries; + } + /// layout - Computes the final table layout. void layout() { assert(Entries == 0 && "Can only call layout() once"); diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 9f2fc92..d8cf0d1 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -404,7 +404,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS, OS << "}\n"; std::vector BPs = PI->ItinsDef->getValueAsListOfDefs("BP"); - if (BPs.size()) { + if (!BPs.empty()) { OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name << "\"\n" << "namespace " << Name << "Bypass {\n"; diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index bbd61f5..02fe4dc 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -143,9 +143,8 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { break; case PrintEnums: { - std::vector Recs = Records.getAllDerivedDefinitions(Class); - for (unsigned i = 0, e = Recs.size(); i != e; ++i) - OS << Recs[i]->getName() << ", "; + for (Record *Rec : Records.getAllDerivedDefinitions(Class)) + OS << Rec->getName() << ", "; OS << "\n"; break; } @@ -153,13 +152,12 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { { SetTheory Sets; Sets.addFieldExpander("Set", "Elements"); - std::vector Recs = Records.getAllDerivedDefinitions("Set"); - for (unsigned i = 0, e = Recs.size(); i != e; ++i) { - OS << Recs[i]->getName() << " = ["; - const std::vector *Elts = Sets.expand(Recs[i]); + for (Record *Rec : Records.getAllDerivedDefinitions("Set")) { + OS << Rec->getName() << " = ["; + const std::vector *Elts = Sets.expand(Rec); assert(Elts && "Couldn't expand Set instance"); - for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei) - OS << ' ' << (*Elts)[ei]->getName(); + for (Record *Elt : *Elts) + OS << ' ' << Elt->getName(); OS << " ]\n"; } break; diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index d7e981c..fbe5502 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -75,13 +75,13 @@ static inline const char* stringForOperandEncoding(OperandEncoding encoding) { /// @return - True if child is a subset of parent, false otherwise. static inline bool inheritsFrom(InstructionContext child, InstructionContext parent, - bool VEX_LIG = false) { + bool VEX_LIG = false, bool AdSize64 = false) { if (child == parent) return true; switch (parent) { case IC: - return(inheritsFrom(child, IC_64BIT) || + return(inheritsFrom(child, IC_64BIT, AdSize64) || inheritsFrom(child, IC_OPSIZE) || inheritsFrom(child, IC_ADSIZE) || inheritsFrom(child, IC_XD) || @@ -89,13 +89,19 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT: return(inheritsFrom(child, IC_64BIT_REXW) || inheritsFrom(child, IC_64BIT_OPSIZE) || - inheritsFrom(child, IC_64BIT_ADSIZE) || + (!AdSize64 && inheritsFrom(child, IC_64BIT_ADSIZE)) || inheritsFrom(child, IC_64BIT_XD) || inheritsFrom(child, IC_64BIT_XS)); case IC_OPSIZE: - return inheritsFrom(child, IC_64BIT_OPSIZE); + return inheritsFrom(child, IC_64BIT_OPSIZE) || + inheritsFrom(child, IC_OPSIZE_ADSIZE); case IC_ADSIZE: + return inheritsFrom(child, IC_OPSIZE_ADSIZE); + case IC_OPSIZE_ADSIZE: + return false; case IC_64BIT_ADSIZE: + return inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE); + case IC_64BIT_OPSIZE_ADSIZE: return false; case IC_XD: return inheritsFrom(child, IC_64BIT_XD); @@ -108,9 +114,12 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT_REXW: return(inheritsFrom(child, IC_64BIT_REXW_XS) || inheritsFrom(child, IC_64BIT_REXW_XD) || - inheritsFrom(child, IC_64BIT_REXW_OPSIZE)); + inheritsFrom(child, IC_64BIT_REXW_OPSIZE) || + (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE))); case IC_64BIT_OPSIZE: - return(inheritsFrom(child, IC_64BIT_REXW_OPSIZE)); + return inheritsFrom(child, IC_64BIT_REXW_OPSIZE) || + (!AdSize64 && inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE)) || + (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE)); case IC_64BIT_XD: return(inheritsFrom(child, IC_64BIT_REXW_XD)); case IC_64BIT_XS: @@ -121,6 +130,7 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT_REXW_XD: case IC_64BIT_REXW_XS: case IC_64BIT_REXW_OPSIZE: + case IC_64BIT_REXW_ADSIZE: return false; case IC_VEX: return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W)) || @@ -713,6 +723,9 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) o << "IC_64BIT_REXW_OPSIZE"; + else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && + (index & ATTR_ADSIZE)) + o << "IC_64BIT_REXW_ADSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE)) o << "IC_64BIT_XD_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE)) @@ -721,6 +734,9 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { o << "IC_64BIT_XS"; else if ((index & ATTR_64BIT) && (index & ATTR_XD)) o << "IC_64BIT_XD"; + else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE) && + (index & ATTR_ADSIZE)) + o << "IC_64BIT_OPSIZE_ADSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE)) o << "IC_64BIT_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE)) @@ -737,6 +753,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { o << "IC_XS"; else if (index & ATTR_XD) o << "IC_XD"; + else if ((index & ATTR_OPSIZE) && (index & ATTR_ADSIZE)) + o << "IC_OPSIZE_ADSIZE"; else if (index & ATTR_OPSIZE) o << "IC_OPSIZE"; else if (index & ATTR_ADSIZE) @@ -822,15 +840,6 @@ void DisassemblerTables::setTableFields(ModRMDecision &decision, InstructionSpecifier &previousInfo = InstructionSpecifiers[decision.instructionIDs[index]]; - // Instructions such as MOV8ao8 and MOV8ao8_16 differ only in the - // presence of the AdSize prefix. However, the disassembler doesn't - // care about that difference in the instruction definition; it - // handles 16-bit vs. 32-bit addressing for itself based purely - // on the 0x67 prefix and the CPU mode. So there's no need to - // disambiguate between them; just let them conflict/coexist. - if (previousInfo.name + "_16" == newInfo.name) - continue; - if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" || newInfo.name == "XCHG32ar" || newInfo.name == "XCHG32ar64" || @@ -862,15 +871,19 @@ void DisassemblerTables::setTableFields(OpcodeType type, const ModRMFilter &filter, InstrUID uid, bool is32bit, - bool ignoresVEX_L) { + bool ignoresVEX_L, + unsigned addressSize) { ContextDecision &decision = *Tables[type]; for (unsigned index = 0; index < IC_max; ++index) { - if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT)) + if ((is32bit || addressSize == 16) && + inheritsFrom((InstructionContext)index, IC_64BIT)) continue; + bool adSize64 = addressSize == 64; if (inheritsFrom((InstructionContext)index, - InstructionSpecifiers[uid].insnContext, ignoresVEX_L)) + InstructionSpecifiers[uid].insnContext, ignoresVEX_L, + adSize64)) setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode], filter, uid, diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h index d86b926..5a8688b 100644 --- a/utils/TableGen/X86DisassemblerTables.h +++ b/utils/TableGen/X86DisassemblerTables.h @@ -245,13 +245,15 @@ public: /// @param uid - The unique ID of the instruction. /// @param is32bit - Instructon is only 32-bit /// @param ignoresVEX_L - Instruction ignores VEX.L + /// @param AddrSize - Instructions address size 16/32/64. 0 is unspecified void setTableFields(OpcodeType type, InstructionContext insnContext, uint8_t opcode, const ModRMFilter &filter, InstrUID uid, bool is32bit, - bool ignoresVEX_L); + bool ignoresVEX_L, + unsigned AddrSize); /// specForUID - Returns the instruction specifier for a given unique /// instruction ID. Used when resolving collisions. diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 9b8092f..5f12965 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -28,54 +28,65 @@ using namespace llvm; MAP(C2, 34) \ MAP(C3, 35) \ MAP(C4, 36) \ - MAP(C8, 37) \ - MAP(C9, 38) \ - MAP(CA, 39) \ - MAP(CB, 40) \ - MAP(CF, 41) \ - MAP(D0, 42) \ - MAP(D1, 43) \ - MAP(D4, 44) \ - MAP(D5, 45) \ - MAP(D6, 46) \ - MAP(D7, 47) \ - MAP(D8, 48) \ - MAP(D9, 49) \ - MAP(DA, 50) \ - MAP(DB, 51) \ - MAP(DC, 52) \ - MAP(DD, 53) \ - MAP(DE, 54) \ - MAP(DF, 55) \ - MAP(E0, 56) \ - MAP(E1, 57) \ - MAP(E2, 58) \ - MAP(E3, 59) \ - MAP(E4, 60) \ - MAP(E5, 61) \ - MAP(E8, 62) \ - MAP(E9, 63) \ - MAP(EA, 64) \ - MAP(EB, 65) \ - MAP(EC, 66) \ - MAP(ED, 67) \ - MAP(EE, 68) \ - MAP(F0, 69) \ - MAP(F1, 70) \ - MAP(F2, 71) \ - MAP(F3, 72) \ - MAP(F4, 73) \ - MAP(F5, 74) \ - MAP(F6, 75) \ - MAP(F7, 76) \ - MAP(F8, 77) \ - MAP(F9, 78) \ - MAP(FA, 79) \ - MAP(FB, 80) \ - MAP(FC, 81) \ - MAP(FD, 82) \ - MAP(FE, 83) \ - MAP(FF, 84) + MAP(C5, 37) \ + MAP(C6, 38) \ + MAP(C7, 39) \ + MAP(C8, 40) \ + MAP(C9, 41) \ + MAP(CA, 42) \ + MAP(CB, 43) \ + MAP(CC, 44) \ + MAP(CD, 45) \ + MAP(CE, 46) \ + MAP(CF, 47) \ + MAP(D0, 48) \ + MAP(D1, 49) \ + MAP(D2, 50) \ + MAP(D3, 51) \ + MAP(D4, 52) \ + MAP(D5, 53) \ + MAP(D6, 54) \ + MAP(D7, 55) \ + MAP(D8, 56) \ + MAP(D9, 57) \ + MAP(DA, 58) \ + MAP(DB, 59) \ + MAP(DC, 60) \ + MAP(DD, 61) \ + MAP(DE, 62) \ + MAP(DF, 63) \ + MAP(E0, 64) \ + MAP(E1, 65) \ + MAP(E2, 66) \ + MAP(E3, 67) \ + MAP(E4, 68) \ + MAP(E5, 69) \ + MAP(E6, 70) \ + MAP(E7, 71) \ + MAP(E8, 72) \ + MAP(E9, 73) \ + MAP(EA, 74) \ + MAP(EB, 75) \ + MAP(EC, 76) \ + MAP(ED, 77) \ + MAP(EE, 78) \ + MAP(EF, 79) \ + MAP(F0, 80) \ + MAP(F1, 81) \ + MAP(F2, 82) \ + MAP(F3, 83) \ + MAP(F4, 84) \ + MAP(F5, 85) \ + MAP(F6, 86) \ + MAP(F7, 87) \ + MAP(F8, 88) \ + MAP(F9, 89) \ + MAP(FA, 90) \ + MAP(FB, 91) \ + MAP(FC, 92) \ + MAP(FD, 93) \ + MAP(FE, 94) \ + MAP(FF, 95) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { @@ -119,6 +130,10 @@ namespace X86Local { enum { OpSize16 = 1, OpSize32 = 2 }; + + enum { + AdSize16 = 1, AdSize32 = 2, AdSize64 = 3 + }; } using namespace X86Disassembler; @@ -194,7 +209,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, Encoding = byteFromRec(Rec, "OpEncBits"); OpSize = byteFromRec(Rec, "OpSizeBits"); - HasAdSizePrefix = Rec->getValueAsBit("hasAdSizePrefix"); + AdSize = byteFromRec(Rec, "AdSizeBits"); HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); HasVEX_4V = Rec->getValueAsBit("hasVEX_4V"); HasVEX_4VOp3 = Rec->getValueAsBit("hasVEX_4VOp3"); @@ -401,16 +416,20 @@ InstructionContext RecognizableInstr::insnContext() const { errs() << "Instruction does not use a prefix: " << Name << "\n"; llvm_unreachable("Invalid prefix"); } - } else if (Is64Bit || HasREX_WPrefix) { + } else if (Is64Bit || HasREX_WPrefix || AdSize == X86Local::AdSize64) { if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)) insnContext = IC_64BIT_REXW_OPSIZE; + else if (HasREX_WPrefix && AdSize == X86Local::AdSize32) + insnContext = IC_64BIT_REXW_ADSIZE; else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD) insnContext = IC_64BIT_XD_OPSIZE; else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS) insnContext = IC_64BIT_XS_OPSIZE; + else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize32) + insnContext = IC_64BIT_OPSIZE_ADSIZE; else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD) insnContext = IC_64BIT_OPSIZE; - else if (HasAdSizePrefix) + else if (AdSize == X86Local::AdSize32) insnContext = IC_64BIT_ADSIZE; else if (HasREX_WPrefix && OpPrefix == X86Local::XS) insnContext = IC_64BIT_REXW_XS; @@ -429,9 +448,11 @@ InstructionContext RecognizableInstr::insnContext() const { insnContext = IC_XD_OPSIZE; else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS) insnContext = IC_XS_OPSIZE; + else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize16) + insnContext = IC_OPSIZE_ADSIZE; else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD) insnContext = IC_OPSIZE; - else if (HasAdSizePrefix) + else if (AdSize == X86Local::AdSize16) insnContext = IC_ADSIZE; else if (OpPrefix == X86Local::XD) insnContext = IC_XD; @@ -504,7 +525,7 @@ void RecognizableInstr::emitInstructionSpecifier() { assert(numOperands <= X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough"); for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) { - if (OperandList[operandIndex].Constraints.size()) { + if (!OperandList[operandIndex].Constraints.empty()) { const CGIOperandList::ConstraintInfo &Constraint = OperandList[operandIndex].Constraints[0]; if (Constraint.isTied()) { @@ -793,9 +814,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { // Special cases where the LLVM tables are not complete #define MAP(from, to) \ - case X86Local::MRM_##from: \ - filter = new ExactFilter(0x##from); \ - break; + case X86Local::MRM_##from: OpcodeType opcodeType = (OpcodeType)-1; @@ -844,12 +863,21 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { filter = new ExtendedFilter(false, Form - X86Local::MRM0m); break; MRM_MAPPING + filter = new ExactFilter(0xC0 + Form - X86Local::MRM_C0); \ + break; } // switch (Form) opcodeToSet = Opcode; break; } // switch (OpMap) + unsigned AddressSize = 0; + switch (AdSize) { + case X86Local::AdSize16: AddressSize = 16; break; + case X86Local::AdSize32: AddressSize = 32; break; + case X86Local::AdSize64: AddressSize = 64; break; + } + assert(opcodeType != (OpcodeType)-1 && "Opcode type not set"); assert(filter && "Filter not set"); @@ -867,13 +895,13 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { insnContext(), currentOpcode, *filter, - UID, Is32Bit, IgnoresVEX_L); + UID, Is32Bit, IgnoresVEX_L, AddressSize); } else { tables.setTableFields(opcodeType, insnContext(), opcodeToSet, *filter, - UID, Is32Bit, IgnoresVEX_L); + UID, Is32Bit, IgnoresVEX_L, AddressSize); } delete filter; @@ -915,6 +943,8 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("GR64", TYPE_R64) TYPE("i8mem", TYPE_M8) TYPE("i8imm", TYPE_IMM8) + TYPE("u8imm", TYPE_UIMM8) + TYPE("i32u8imm", TYPE_UIMM8) TYPE("GR8", TYPE_R8) TYPE("VR128", TYPE_XMM128) TYPE("VR128X", TYPE_XMM128) @@ -937,17 +967,19 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i16imm_pcrel", TYPE_REL16) TYPE("i32imm_pcrel", TYPE_REL32) TYPE("SSECC", TYPE_IMM3) + TYPE("XOPCC", TYPE_IMM3) TYPE("AVXCC", TYPE_IMM5) + TYPE("AVX512ICC", TYPE_AVX512ICC) TYPE("AVX512RC", TYPE_IMM32) - TYPE("brtarget", TYPE_RELv) - TYPE("uncondbrtarget", TYPE_RELv) + TYPE("brtarget32", TYPE_RELv) + TYPE("brtarget16", TYPE_RELv) TYPE("brtarget8", TYPE_REL8) TYPE("f80mem", TYPE_M80FP) - TYPE("lea32mem", TYPE_LEA) TYPE("lea64_32mem", TYPE_LEA) TYPE("lea64mem", TYPE_LEA) TYPE("VR64", TYPE_MM64) TYPE("i64imm", TYPE_IMMv) + TYPE("anymem", TYPE_M) TYPE("opaque32mem", TYPE_M1616) TYPE("opaque48mem", TYPE_M1632) TYPE("opaque80mem", TYPE_M1664) @@ -963,10 +995,17 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("dstidx16", TYPE_DSTIDX16) TYPE("dstidx32", TYPE_DSTIDX32) TYPE("dstidx64", TYPE_DSTIDX64) - TYPE("offset8", TYPE_MOFFS8) - TYPE("offset16", TYPE_MOFFS16) - TYPE("offset32", TYPE_MOFFS32) - TYPE("offset64", TYPE_MOFFS64) + TYPE("offset16_8", TYPE_MOFFS8) + TYPE("offset16_16", TYPE_MOFFS16) + TYPE("offset16_32", TYPE_MOFFS32) + TYPE("offset32_8", TYPE_MOFFS8) + TYPE("offset32_16", TYPE_MOFFS16) + TYPE("offset32_32", TYPE_MOFFS32) + TYPE("offset32_64", TYPE_MOFFS64) + TYPE("offset64_8", TYPE_MOFFS8) + TYPE("offset64_16", TYPE_MOFFS16) + TYPE("offset64_32", TYPE_MOFFS32) + TYPE("offset64_64", TYPE_MOFFS64) TYPE("VR256", TYPE_XMM256) TYPE("VR256X", TYPE_XMM256) TYPE("VR512", TYPE_XMM512) @@ -1010,7 +1049,9 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, } ENCODING("i32i8imm", ENCODING_IB) ENCODING("SSECC", ENCODING_IB) + ENCODING("XOPCC", ENCODING_IB) ENCODING("AVXCC", ENCODING_IB) + ENCODING("AVX512ICC", ENCODING_IB) ENCODING("AVX512RC", ENCODING_IB) ENCODING("i16imm", ENCODING_Iv) ENCODING("i16i8imm", ENCODING_IB) @@ -1018,6 +1059,8 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, ENCODING("i64i32imm", ENCODING_ID) ENCODING("i64i8imm", ENCODING_IB) ENCODING("i8imm", ENCODING_IB) + ENCODING("u8imm", ENCODING_IB) + ENCODING("i32u8imm", ENCODING_IB) // This is not a typo. Instructions like BLENDVPD put // register IDs in 8-bit immediates nowadays. ENCODING("FR32", ENCODING_IB) @@ -1153,9 +1196,9 @@ RecognizableInstr::memoryEncodingFromString(const std::string &s, ENCODING("i256mem", ENCODING_RM) ENCODING("i512mem", ENCODING_RM) ENCODING("f80mem", ENCODING_RM) - ENCODING("lea32mem", ENCODING_RM) ENCODING("lea64_32mem", ENCODING_RM) ENCODING("lea64mem", ENCODING_RM) + ENCODING("anymem", ENCODING_RM) ENCODING("opaque32mem", ENCODING_RM) ENCODING("opaque48mem", ENCODING_RM) ENCODING("opaque80mem", ENCODING_RM) @@ -1186,16 +1229,26 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s, ENCODING("i64i32imm", ENCODING_ID) ENCODING("i64i8imm", ENCODING_IB) ENCODING("i8imm", ENCODING_IB) + ENCODING("u8imm", ENCODING_IB) + ENCODING("i32u8imm", ENCODING_IB) ENCODING("i64i32imm_pcrel", ENCODING_ID) ENCODING("i16imm_pcrel", ENCODING_IW) ENCODING("i32imm_pcrel", ENCODING_ID) - ENCODING("brtarget", ENCODING_Iv) + ENCODING("brtarget32", ENCODING_Iv) + ENCODING("brtarget16", ENCODING_Iv) ENCODING("brtarget8", ENCODING_IB) ENCODING("i64imm", ENCODING_IO) - ENCODING("offset8", ENCODING_Ia) - ENCODING("offset16", ENCODING_Ia) - ENCODING("offset32", ENCODING_Ia) - ENCODING("offset64", ENCODING_Ia) + ENCODING("offset16_8", ENCODING_Ia) + ENCODING("offset16_16", ENCODING_Ia) + ENCODING("offset16_32", ENCODING_Ia) + ENCODING("offset32_8", ENCODING_Ia) + ENCODING("offset32_16", ENCODING_Ia) + ENCODING("offset32_32", ENCODING_Ia) + ENCODING("offset32_64", ENCODING_Ia) + ENCODING("offset64_8", ENCODING_Ia) + ENCODING("offset64_16", ENCODING_Ia) + ENCODING("offset64_32", ENCODING_Ia) + ENCODING("offset64_64", ENCODING_Ia) ENCODING("srcidx8", ENCODING_SI) ENCODING("srcidx16", ENCODING_SI) ENCODING("srcidx32", ENCODING_SI) diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index 95d7a40..28e1053 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -50,8 +50,8 @@ private: uint8_t Encoding; /// The OpSize field from the record uint8_t OpSize; - /// The hasAdSizePrefix field from the record - bool HasAdSizePrefix; + /// The AdSize field from the record + uint8_t AdSize; /// The hasREX_WPrefix field from the record bool HasREX_WPrefix; /// The hasVEX_4V field from the record diff --git a/utils/emacs/emacs.el b/utils/emacs/emacs.el index 969f538..4a3a503 100644 --- a/utils/emacs/emacs.el +++ b/utils/emacs/emacs.el @@ -1,39 +1,22 @@ ;; LLVM coding style guidelines in emacs ;; Maintainer: LLVM Team, http://llvm.org/ -;; Modified: 2009-07-28 -;; Max 80 cols per line, indent by two spaces, no tabs. -;; Apparently, this does not affect tabs in Makefiles. -(custom-set-variables - '(fill-column 80) - '(c++-indent-level 2) - '(c-basic-offset 2) - '(indent-tabs-mode nil)) - - -;; Alternative to setting the global style. Only files with "llvm" in -;; their names will automatically set to the llvm.org coding style. +;; Add a cc-mode style for editing LLVM C and C++ code (c-add-style "llvm.org" - '((fill-column . 80) + '("gnu" + (fill-column . 80) (c++-indent-level . 2) (c-basic-offset . 2) (indent-tabs-mode . nil) - (c-offsets-alist . ((innamespace 0))))) - -(add-hook 'c-mode-hook - (function - (lambda nil - (if (string-match "llvm" buffer-file-name) - (progn - (c-set-style "llvm.org") - ) - )))) + (c-offsets-alist . ((arglist-intro . ++) + (innamespace . 0) + (member-init-intro . ++))))) -(add-hook 'c++-mode-hook +;; Files with "llvm" in their names will automatically be set to the +;; llvm.org coding style. +(add-hook 'c-mode-common-hook (function (lambda nil (if (string-match "llvm" buffer-file-name) (progn - (c-set-style "llvm.org") - ) - )))) + (c-set-style "llvm.org")))))) diff --git a/utils/emacs/llvm-mode.el b/utils/emacs/llvm-mode.el index 61127b6..5fb1eb3 100644 --- a/utils/emacs/llvm-mode.el +++ b/utils/emacs/llvm-mode.el @@ -1,8 +1,13 @@ +;;; llvm-mode.el --- Major mode for the LLVM assembler language. + ;; Maintainer: The LLVM team, http://llvm.org/ -;; Description: Major mode for the LLVM assembler language. -;; Updated: 2007-09-19 -;; Create mode-specific tables. +;;; Commentary: + +;; Major mode for editing LLVM IR files. + +;;; Code: + (defvar llvm-mode-syntax-table nil "Syntax table used while in LLVM mode.") (defvar llvm-font-lock-keywords @@ -18,7 +23,7 @@ ;; Unnamed variable slots '("%[-]?[0-9]+" . font-lock-variable-name-face) ;; Types - `(,(regexp-opt '("void" "i[0-9]+" "float" "double" "type" "label" "opaque") 'words) . font-lock-type-face) + `(,(regexp-opt '("void" "i1" "i8" "i16" "i32" "i64" "i128" "float" "double" "type" "label" "opaque") 'symbol) . font-lock-type-face) ;; Integer literals '("\\b[-]?[0-9]+\\b" . font-lock-preprocessor-face) ;; Floating point constants @@ -30,29 +35,31 @@ "define" "global" "constant" "const" "internal" "linkonce" "linkonce_odr" "weak" "weak_odr" "appending" "uninitialized" "implementation" "..." "null" "undef" "to" "except" "not" "target" "endian" "little" "big" - "pointersize" "volatile" "fastcc" "coldcc" "cc") 'words) . font-lock-keyword-face) + "pointersize" "volatile" "fastcc" "coldcc" "cc" "personality") 'symbols) . font-lock-keyword-face) ;; Arithmetic and Logical Operators `(,(regexp-opt '("add" "sub" "mul" "sdiv" "udiv" "urem" "srem" "and" "or" "xor" - "setne" "seteq" "setlt" "setgt" "setle" "setge") 'words) . font-lock-keyword-face) + "setne" "seteq" "setlt" "setgt" "setle" "setge") 'symbols) . font-lock-keyword-face) ;; Floating-point operators - `(,(regexp-opt '("fadd" "fsub" "fmul" "fdiv" "frem") 'words) . font-lock-keyword-face) + `(,(regexp-opt '("fadd" "fsub" "fmul" "fdiv" "frem") 'symbols) . font-lock-keyword-face) ;; Special instructions - `(,(regexp-opt '("phi" "tail" "call" "select" "to" "shl" "lshr" "ashr" "fcmp" "icmp" "va_arg" "landingpad") 'words) . font-lock-keyword-face) + `(,(regexp-opt '("phi" "tail" "call" "select" "to" "shl" "lshr" "ashr" "fcmp" "icmp" "va_arg" "landingpad") 'symbols) . font-lock-keyword-face) ;; Control instructions - `(,(regexp-opt '("ret" "br" "switch" "invoke" "resume" "unwind" "unreachable" "indirectbr") 'words) . font-lock-keyword-face) + `(,(regexp-opt '("ret" "br" "switch" "invoke" "resume" "unwind" "unreachable" "indirectbr") 'symbols) . font-lock-keyword-face) ;; Memory operators - `(,(regexp-opt '("malloc" "alloca" "free" "load" "store" "getelementptr" "fence" "cmpxchg" "atomicrmw") 'words) . font-lock-keyword-face) + `(,(regexp-opt '("malloc" "alloca" "free" "load" "store" "getelementptr" "fence" "cmpxchg" "atomicrmw") 'symbols) . font-lock-keyword-face) ;; Casts - `(,(regexp-opt '("bitcast" "inttoptr" "ptrtoint" "trunc" "zext" "sext" "fptrunc" "fpext" "fptoui" "fptosi" "uitofp" "sitofp" "addrspacecast") 'words) . font-lock-keyword-face) + `(,(regexp-opt '("bitcast" "inttoptr" "ptrtoint" "trunc" "zext" "sext" "fptrunc" "fpext" "fptoui" "fptosi" "uitofp" "sitofp" "addrspacecast") 'symbols) . font-lock-keyword-face) ;; Vector ops - `(,(regexp-opt '("extractelement" "insertelement" "shufflevector") 'words) . font-lock-keyword-face) + `(,(regexp-opt '("extractelement" "insertelement" "shufflevector") 'symbols) . font-lock-keyword-face) ;; Aggregate ops - `(,(regexp-opt '("extractvalue" "insertvalue") 'words) . font-lock-keyword-face) + `(,(regexp-opt '("extractvalue" "insertvalue") 'symbols) . font-lock-keyword-face) + ;; Metadata types + `(,(regexp-opt '("distinct") 'symbols) . font-lock-keyword-face) ;; Use-list order directives - `(,(regexp-opt '("uselistorder" "uselistorder_bb") 'words) . font-lock-keyword-face) + `(,(regexp-opt '("uselistorder" "uselistorder_bb") 'symbols) . font-lock-keyword-face) ) - "Syntax highlighting for LLVM" + "Syntax highlighting for LLVM." ) ;; ---------------------- Syntax table --------------------------- @@ -62,40 +69,33 @@ (if (not llvm-mode-syntax-table) (progn (setq llvm-mode-syntax-table (make-syntax-table)) - (mapcar (function (lambda (n) - (modify-syntax-entry (aref n 0) - (aref n 1) - llvm-mode-syntax-table))) - '( - ;; whitespace (` ') - [?\^m " "] - [?\f " "] - [?\n " "] - [?\t " "] - [?\ " "] - ;; word constituents (`w') - ;;[?< "w"] - ;;[?> "w"] - [?\% "w"] - ;;[?_ "w "] - ;; comments - [?\; "< "] - [?\n "> "] - ;;[?\r "> "] - ;;[?\^m "> "] - ;; symbol constituents (`_') - ;; punctuation (`.') - ;; open paren (`(') - [?\( "("] - [?\[ "("] - [?\{ "("] - ;; close paren (`)') - [?\) ")"] - [?\] ")"] - [?\} ")"] - ;; string quote ('"') - [?\" "\""] - )))) + (mapc (function (lambda (n) + (modify-syntax-entry (aref n 0) + (aref n 1) + llvm-mode-syntax-table))) + '( + ;; whitespace (` ') + [?\^m " "] + [?\f " "] + [?\n " "] + [?\t " "] + [?\ " "] + ;; word constituents (`w') + ;;[?< "w"] + ;;[?> "w"] + [?% "w"] + ;;[?_ "w "] + ;; comments + [?\; "< "] + [?\n "> "] + ;;[?\r "> "] + ;;[?\^m "> "] + ;; symbol constituents (`_') + ;; punctuation (`.') + ;; open paren (`(') + ;; close paren (`)') + ;; string quote ('"') + [?\" "\""])))) ;; --------------------- Abbrev table ----------------------------- @@ -113,11 +113,11 @@ (define-key llvm-mode-map "\es" 'center-line) (define-key llvm-mode-map "\eS" 'center-paragraph)) - +;;;###autoload (defun llvm-mode () "Major mode for editing LLVM source files. - \\{llvm-mode-map} - Runs llvm-mode-hook on startup." +\\{llvm-mode-map} + Runs `llvm-mode-hook' on startup." (interactive) (kill-all-local-variables) (use-local-map llvm-mode-map) ; Provides the local keymap. @@ -136,8 +136,9 @@ ; customize the mode with a hook. ;; Associate .ll files with llvm-mode -(setq auto-mode-alist - (append '(("\\.ll$" . llvm-mode)) auto-mode-alist)) +;;;###autoload +(add-to-list 'auto-mode-alist (cons (purecopy "\\.ll\\'") 'llvm-mode)) (provide 'llvm-mode) -;; end of llvm-mode.el + +;;; llvm-mode.el ends here diff --git a/utils/emacs/tablegen-mode.el b/utils/emacs/tablegen-mode.el index c0ae751..035455d 100644 --- a/utils/emacs/tablegen-mode.el +++ b/utils/emacs/tablegen-mode.el @@ -1,12 +1,17 @@ +;;; tablegen-mode.el --- Major mode for TableGen description files (part of LLVM project) + ;; Maintainer: The LLVM team, http://llvm.org/ -;; Description: Major mode for TableGen description files (part of LLVM project) -;; Updated: 2007-12-18 + +;;; Commentary: +;; A major mode for TableGen description files in LLVM. (require 'comint) (require 'custom) (require 'ansi-color) ;; Create mode-specific tables. +;;; Code: + (defvar td-decorators-face 'td-decorators-face "Face method decorators.") (make-face 'td-decorators-face) @@ -93,10 +98,11 @@ (define-key tablegen-mode-map "\es" 'center-line) (define-key tablegen-mode-map "\eS" 'center-paragraph)) +;;;###autoload (defun tablegen-mode () "Major mode for editing TableGen description files. - \\{tablegen-mode-map} - Runs tablegen-mode-hook on startup." +\\{tablegen-mode-map} + Runs `tablegen-mode-hook' on startup." (interactive) (kill-all-local-variables) (use-local-map tablegen-mode-map) ; Provides the local keymap. @@ -117,7 +123,9 @@ ; customize the mode with a hook. ;; Associate .td files with tablegen-mode -(setq auto-mode-alist (append '(("\\.td$" . tablegen-mode)) auto-mode-alist)) +;;;###autoload +(add-to-list 'auto-mode-alist (cons (purecopy "\\.td\\'") 'tablegen-mode)) (provide 'tablegen-mode) -;; end of tablegen-mode.el + +;;; tablegen-mode.el ends here diff --git a/utils/lit/lit/LitConfig.py b/utils/lit/lit/LitConfig.py index b0dde5d..b818380 100644 --- a/utils/lit/lit/LitConfig.py +++ b/utils/lit/lit/LitConfig.py @@ -76,7 +76,6 @@ class LitConfig: self.bashPath = lit.util.which('bash') if self.bashPath is None: - self.warning("Unable to find 'bash'.") self.bashPath = '' return self.bashPath @@ -91,7 +90,6 @@ class LitConfig: # bash self.bashPath = lit.util.which('bash', dir) if self.bashPath is None: - self.note("Unable to find 'bash.exe'.") self.bashPath = '' return dir diff --git a/utils/lit/lit/Test.py b/utils/lit/lit/Test.py index b810230..682d04f 100644 --- a/utils/lit/lit/Test.py +++ b/utils/lit/lit/Test.py @@ -91,7 +91,8 @@ class JSONMetricValue(MetricValue): self.value = value def format(self): - return str(self.value) + e = JSONEncoder(indent=2, sort_keys=True) + return e.encode(self.value) def todata(self): return self.value @@ -252,4 +253,4 @@ class Test: xml += "\n\t\n" else: xml += "/>" - return xml \ No newline at end of file + return xml diff --git a/utils/lit/lit/TestingConfig.py b/utils/lit/lit/TestingConfig.py index 52cebbf..c7ef94d 100644 --- a/utils/lit/lit/TestingConfig.py +++ b/utils/lit/lit/TestingConfig.py @@ -26,7 +26,11 @@ class TestingConfig: 'LD_PRELOAD', 'ASAN_OPTIONS', 'UBSAN_OPTIONS', 'LSAN_OPTIONS'] for var in pass_vars: - environment[var] = os.environ.get(var, '') + val = os.environ.get(var, '') + # Check for empty string as some variables such as LD_PRELOAD cannot be empty + # ('') for OS's such as OpenBSD. + if val: + environment[var] = val if sys.platform == 'win32': environment.update({ diff --git a/utils/lit/lit/formats/googletest.py b/utils/lit/lit/formats/googletest.py index 1b5b785..59ac3c5 100644 --- a/utils/lit/lit/formats/googletest.py +++ b/utils/lit/lit/formats/googletest.py @@ -31,7 +31,6 @@ class GoogleTest(TestFormat): try: lines = lit.util.capture([path, '--gtest_list_tests'], env=localConfig.environment) - lines = lines.decode('utf-8') if kIsWindows: lines = lines.replace('\r', '') lines = lines.split('\n') diff --git a/utils/lit/lit/util.py b/utils/lit/lit/util.py index ca1aeb6..08f7b71 100644 --- a/utils/lit/lit/util.py +++ b/utils/lit/lit/util.py @@ -16,6 +16,12 @@ def to_string(bytes): return bytes return to_bytes(bytes) +def convert_string(bytes): + try: + return to_string(bytes.decode('utf-8')) + except UnicodeError: + return str(bytes) + def detectCPUs(): """ Detects the number of CPUs on a system. Cribbed from pp. @@ -60,7 +66,7 @@ def capture(args, env=None): p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) out,_ = p.communicate() - return out + return convert_string(out) def which(command, paths = None): """which(command, [paths]) - Look up the given command in the paths string @@ -166,14 +172,8 @@ def executeCommand(command, cwd=None, env=None): raise KeyboardInterrupt # Ensure the resulting output is always of string type. - try: - out = to_string(out.decode('utf-8')) - except: - out = str(out) - try: - err = to_string(err.decode('utf-8')) - except: - err = str(err) + out = convert_string(out) + err = convert_string(err) return out, err, exitCode diff --git a/utils/lit/utils/check-coverage b/utils/lit/utils/check-coverage index 128e827..cded7a2 100755 --- a/utils/lit/utils/check-coverage +++ b/utils/lit/utils/check-coverage @@ -23,7 +23,7 @@ fi # sitecustomize. if ! python -c \ 'import sitecustomize, sys; sys.exit("coverage" not in dir(sitecustomize))' \ - &> /dev/null; then + >/dev/null 2>&1; then printf 1>&2 "error: active python does not appear to enable coverage in its 'sitecustomize.py'\n" exit 1 fi diff --git a/utils/lldbDataFormatters.py b/utils/lldbDataFormatters.py index f570fb4..687729f 100644 --- a/utils/lldbDataFormatters.py +++ b/utils/lldbDataFormatters.py @@ -15,6 +15,9 @@ def __lldb_init_module(debugger, internal_dict): debugger.HandleCommand('type synthetic add -w llvm ' '-l lldbDataFormatters.ArrayRefSynthProvider ' '-x "^llvm::ArrayRef<.+>$"') + debugger.HandleCommand('type summary add -w llvm ' + '-F lldbDataFormatters.OptionalSummaryProvider ' + '-x "^llvm::Optional<.+>$"') # Pretty printer for llvm::SmallVector/llvm::SmallVectorImpl class SmallVectorSynthProvider: @@ -86,3 +89,10 @@ class ArrayRefSynthProvider: self.data_type = self.data.GetType().GetPointeeType() self.type_size = self.data_type.GetByteSize() assert self.type_size != 0 + +def OptionalSummaryProvider(valobj, internal_dict): + if not valobj.GetChildMemberWithName('hasVal').GetValueAsUnsigned(0): + return 'None' + underlying_type = valobj.GetType().GetTemplateArgumentType(0) + storage = valobj.GetChildMemberWithName('storage') + return str(storage.Cast(underlying_type)) diff --git a/utils/not/not.cpp b/utils/not/not.cpp index 2adeded..23062fb 100644 --- a/utils/not/not.cpp +++ b/utils/not/not.cpp @@ -6,6 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// Usage: +// not cmd +// Will return true if cmd doesn't crash and returns false. +// not --crash cmd +// Will return true if cmd crashes (e.g. for testing crash reporting). #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" diff --git a/utils/release/merge.sh b/utils/release/merge.sh index 2cf39b2..949c298 100755 --- a/utils/release/merge.sh +++ b/utils/release/merge.sh @@ -66,9 +66,11 @@ svn log -c $rev http://llvm.org/svn/llvm-project/$proj/trunk >> $tempfile 2>&1 cd $proj.src echo "# Updating tree" svn up -echo "# Merging r$rev into $proj" +echo "# Merging r$rev into $proj locally" svn merge -c $rev https://llvm.org/svn/llvm-project/$proj/trunk . || exit 1 -echo "# Committing changes" -svn commit -F $tempfile || exit 1 -rm -f $tempfile + +echo +echo "# To commit the merge, run the following in $proj.src/:" +echo svn commit -F $tempfile + exit 0 diff --git a/utils/release/tag.sh b/utils/release/tag.sh index 390acaf..503413b 100755 --- a/utils/release/tag.sh +++ b/utils/release/tag.sh @@ -18,17 +18,21 @@ release="" rc="" rebranch="no" projects="llvm cfe dragonegg test-suite compiler-rt libcxx libcxxabi clang-tools-extra polly lldb lld openmp" +dryrun="" +revision="HEAD" base_url="https://llvm.org/svn/llvm-project" function usage() { - echo "usage: `basename $0` -release [-rebranch]" - echo "usage: `basename $0` -release -rc " + echo "usage: `basename $0` -release [-rebranch] [-revision ] [-dry-run]" + echo "usage: `basename $0` -release -rc [-dry-run]" echo " " - echo " -release The version number of the release" - echo " -rc The release candidate number" - echo " -rebranch Remove existing branch, if present, before branching" - echo " -final Tag final release candidate" + echo " -release The version number of the release" + echo " -rc The release candidate number" + echo " -rebranch Remove existing branch, if present, before branching" + echo " -final Tag final release candidate" + echo " -revision Revision to branch off (default: HEAD)" + echo " -dry-run Make no changes to the repository, just print the commands" } function tag_version() { @@ -38,10 +42,11 @@ function tag_version() { if [ $rebranch = "no" ]; then continue fi - svn remove -m "Removing old release_$branch_release branch for rebranching." \ + ${dryrun} svn remove -m "Removing old release_$branch_release branch for rebranching." \ $base_url/$proj/branches/release_$branch_release fi - svn copy -m "Creating release_$branch_release branch" \ + ${dryrun} svn copy -m "Creating release_$branch_release branch off revision ${revision}" \ + -r ${revision} \ $base_url/$proj/trunk \ $base_url/$proj/branches/release_$branch_release done @@ -52,10 +57,10 @@ function tag_release_candidate() { set -x for proj in $projects ; do if ! svn ls $base_url/$proj/tags/RELEASE_$tag_release > /dev/null 2>&1 ; then - svn mkdir -m "Creating release directory for release_$tag_release." $base_url/$proj/tags/RELEASE_$tag_release + ${dryrun} svn mkdir -m "Creating release directory for release_$tag_release." $base_url/$proj/tags/RELEASE_$tag_release fi if ! svn ls $base_url/$proj/tags/RELEASE_$tag_release/$rc > /dev/null 2>&1 ; then - svn copy -m "Creating release candidate $rc from release_$tag_release branch" \ + ${dryrun} svn copy -m "Creating release candidate $rc from release_$tag_release branch" \ $base_url/$proj/branches/release_$branch_release \ $base_url/$proj/tags/RELEASE_$tag_release/$rc fi @@ -79,6 +84,13 @@ while [ $# -gt 0 ]; do -final | --final ) rc="final" ;; + -revision | --revision ) + shift + revision="$1" + ;; + -dry-run | --dry-run ) + dryrun="echo" + ;; -h | --help | -help ) usage exit 0 @@ -105,6 +117,13 @@ tag_release=`echo $release | sed -e 's,\.,,g'` if [ "x$rc" = "x" ]; then tag_version else + if [ "$revision" != "HEAD" ]; then + echo "error: cannot use -revision with -rc" + echo + usage + exit 1 + fi + tag_release_candidate fi diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh index b028924..20f8d97 100755 --- a/utils/release/test-release.sh +++ b/utils/release/test-release.sh @@ -39,27 +39,30 @@ do_debug="no" do_asserts="no" do_compare="yes" BuildDir="`pwd`" +BuildTriple="" function usage() { echo "usage: `basename $0` -release X.Y -rc NUM [OPTIONS]" echo "" - echo " -release X.Y The release number to test." - echo " -rc NUM The pre-release candidate number." - echo " -final The final release candidate." - echo " -triple TRIPLE The target triple for this machine." - echo " -j NUM Number of compile jobs to run. [default: 3]" - echo " -build-dir DIR Directory to perform testing in. [default: pwd]" - echo " -no-checkout Don't checkout the sources from SVN." - echo " -no-64bit Don't test the 64-bit version. [default: yes]" - echo " -enable-ada Build Ada. [default: disable]" - echo " -disable-clang Do not test clang. [default: enable]" - echo " -enable-dragonegg Test dragonegg. [default: disable]" - echo " -enable-fortran Enable Fortran build. [default: disable]" - echo " -disable-objc Disable ObjC build. [default: enable]" - echo " -test-debug Test the debug build. [default: no]" - echo " -test-asserts Test with asserts on. [default: no]" - echo " -no-compare-files Don't test that phase 2 and 3 files are identical." - echo " -use-gzip Use gzip instead of xz." + echo " -release X.Y The release number to test." + echo " -rc NUM The pre-release candidate number." + echo " -final The final release candidate." + echo " -triple TRIPLE The target triple for this machine." + echo " -j NUM Number of compile jobs to run. [default: 3]" + echo " -build-dir DIR Directory to perform testing in. [default: pwd]" + echo " -no-checkout Don't checkout the sources from SVN." + echo " -no-64bit Don't test the 64-bit version. [default: yes]" + echo " -enable-ada Build Ada. [default: disable]" + echo " -disable-clang Do not test clang. [default: enable]" + echo " -enable-dragonegg Test dragonegg. [default: disable]" + echo " -enable-fortran Enable Fortran build. [default: disable]" + echo " -disable-objc Disable ObjC build. [default: enable]" + echo " -test-debug Test the debug build. [default: no]" + echo " -test-asserts Test with asserts on. [default: no]" + echo " -no-compare-files Don't test that phase 2 and 3 files are identical." + echo " -use-gzip Use gzip instead of xz." + echo " -build-triple TRIPLE The build triple for this machine" + echo " [default: use config.guess]" } while [ $# -gt 0 ]; do @@ -80,6 +83,10 @@ while [ $# -gt 0 ]; do shift Triple="$1" ;; + -build-triple | --build-triple ) + shift + BuildTriple="$1" + ;; -j* ) NumJobs="`echo $1 | sed -e 's,-j\([0-9]*\),\1,g'`" if [ -z "$NumJobs" ]; then @@ -295,16 +302,21 @@ function configure_llvmCore() { echo "# Using C compiler: $c_compiler" echo "# Using C++ compiler: $cxx_compiler" + build_triple_option="${BuildTriple:+--build=$BuildTriple}" + cd $ObjDir echo "# Configuring llvm $Release-$RC $Flavor" echo "# $BuildDir/llvm.src/configure --prefix=$InstallDir \ --enable-optimized=$Optimized \ - --enable-assertions=$Assertions" + --enable-assertions=$Assertions \ + --disable-timestamps \ + $build_triple_option" env CC="$c_compiler" CXX="$cxx_compiler" \ $BuildDir/llvm.src/configure --prefix=$InstallDir \ --enable-optimized=$Optimized \ --enable-assertions=$Assertions \ --disable-timestamps \ + $build_triple_option \ 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log cd $BuildDir } diff --git a/utils/shuffle_fuzz.py b/utils/shuffle_fuzz.py index 384a93a..985d1da 100755 --- a/utils/shuffle_fuzz.py +++ b/utils/shuffle_fuzz.py @@ -173,7 +173,7 @@ entry:""" % dict(subst, # Generate some string constants that we can use to report errors. for i, r in enumerate(result): if r != -1: - s = ('FAIL(%(seed)s): lane %(lane)d, expected %(result)d, found %%d\\0A' % + s = ('FAIL(%(seed)s): lane %(lane)d, expected %(result)d, found %%d\n\\0A' % {'seed': args.seed, 'lane': i, 'result': r}) s += ''.join(['\\00' for _ in itertools.repeat(None, 128 - len(s) + 2)]) print """ @@ -235,8 +235,7 @@ die.%(i)d: %%bad.%(i)d = trunc i2048 %%tmp.%(i)d to i32 call i32 (i8*, i8*, ...)* @sprintf(i8* %%str.ptr, i8* getelementptr inbounds ([128 x i8]* @error.%(i)d, i32 0, i32 0), i32 %%bad.%(i)d) %%length.%(i)d = call i32 @strlen(i8* %%str.ptr) - %%size.%(i)d = add i32 %%length.%(i)d, 1 - call i32 @write(i32 2, i8* %%str.ptr, i32 %%size.%(i)d) + call i32 @write(i32 2, i8* %%str.ptr, i32 %%length.%(i)d) call void @llvm.trap() unreachable """ % dict(subst, i=i, next_i=i + 1, r=r) diff --git a/utils/unittest/CMakeLists.txt b/utils/unittest/CMakeLists.txt index b6d2d6d..b34e22a 100644 --- a/utils/unittest/CMakeLists.txt +++ b/utils/unittest/CMakeLists.txt @@ -32,17 +32,20 @@ if (NOT LLVM_ENABLE_THREADS) add_definitions( -DGTEST_HAS_PTHREAD=0 ) endif() -# Visual Studio 2012 only supports up to 8 template parameters in -# std::tr1::tuple by default, but gtest requires 10 -if(MSVC AND MSVC_VERSION EQUAL 1700) - add_definitions(-D_VARIADIC_MAX=10) -endif () +set(LIBS + LLVMSupport # Depends on llvm::raw_ostream +) + +find_library(PTHREAD_LIBRARY_PATH pthread) +if (PTHREAD_LIBRARY_PATH) + list(APPEND LIBS pthread) +endif() add_llvm_library(gtest googletest/src/gtest-all.cc LINK_LIBS - LLVMSupport # Depends on llvm::raw_ostream - ) + ${LIBS} +) add_subdirectory(UnitTestMain) diff --git a/utils/update_llc_test_checks.py b/utils/update_llc_test_checks.py new file mode 100755 index 0000000..df01d89 --- /dev/null +++ b/utils/update_llc_test_checks.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python2.7 + +"""A test case update script. + +This script is a utility to update LLVM X86 'llc' based test cases with new +FileCheck patterns. It can either update all of the tests in the file or +a single test function. +""" + +import argparse +import itertools +import string +import subprocess +import sys +import tempfile +import re + + +def llc(args, cmd_args, ir): + with open(ir) as ir_file: + stdout = subprocess.check_output(args.llc_binary + ' ' + cmd_args, + shell=True, stdin=ir_file) + return stdout + + +ASM_SCRUB_WHITESPACE_RE = re.compile(r'(?!^(| \w))[ \t]+', flags=re.M) +ASM_SCRUB_TRAILING_WHITESPACE_RE = re.compile(r'[ \t]+$', flags=re.M) +ASM_SCRUB_SHUFFLES_RE = ( + re.compile( + r'^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem) = .*)$', + flags=re.M)) +ASM_SCRUB_SP_RE = re.compile(r'\d+\(%(esp|rsp)\)') +ASM_SCRUB_RIP_RE = re.compile(r'[.\w]+\(%rip\)') +ASM_SCRUB_KILL_COMMENT_RE = re.compile(r'^ *#+ +kill:.*\n') + + +def scrub_asm(asm): + # Scrub runs of whitespace out of the assembly, but leave the leading + # whitespace in place. + asm = ASM_SCRUB_WHITESPACE_RE.sub(r' ', asm) + # Expand the tabs used for indentation. + asm = string.expandtabs(asm, 2) + # Detect shuffle asm comments and hide the operands in favor of the comments. + asm = ASM_SCRUB_SHUFFLES_RE.sub(r'\1 {{.*#+}} \2', asm) + # Generically match the stack offset of a memory operand. + asm = ASM_SCRUB_SP_RE.sub(r'{{[0-9]+}}(%\1)', asm) + # Generically match a RIP-relative memory operand. + asm = ASM_SCRUB_RIP_RE.sub(r'{{.*}}(%rip)', asm) + # Strip kill operands inserted into the asm. + asm = ASM_SCRUB_KILL_COMMENT_RE.sub('', asm) + # Strip trailing whitespace. + asm = ASM_SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm) + return asm + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('-v', '--verbose', action='store_true', + help='Show verbose output') + parser.add_argument('--llc-binary', default='llc', + help='The "llc" binary to use to generate the test case') + parser.add_argument( + '--function', help='The function in the test file to update') + parser.add_argument('tests', nargs='+') + args = parser.parse_args() + + run_line_re = re.compile('^\s*;\s*RUN:\s*(.*)$') + ir_function_re = re.compile('^\s*define\s+(?:internal\s+)?[^@]*@(\w+)\s*\(') + asm_function_re = re.compile( + r'^_?(?P[^:]+):[ \t]*#+[ \t]*@(?P=f)\n[^:]*?' + r'(?P^##?[ \t]+[^:]+:.*?)\s*' + r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section)', + flags=(re.M | re.S)) + check_prefix_re = re.compile('--check-prefix=(\S+)') + check_re = re.compile(r'^\s*;\s*([^:]+?)(?:-NEXT|-NOT|-DAG|-LABEL)?:') + + for test in args.tests: + if args.verbose: + print >>sys.stderr, 'Scanning for RUN lines in test file: %s' % (test,) + with open(test) as f: + test_lines = [l.rstrip() for l in f] + + run_lines = [m.group(1) + for m in [run_line_re.match(l) for l in test_lines] if m] + if args.verbose: + print >>sys.stderr, 'Found %d RUN lines:' % (len(run_lines),) + for l in run_lines: + print >>sys.stderr, ' RUN: ' + l + + checks = [] + for l in run_lines: + (llc_cmd, filecheck_cmd) = tuple([cmd.strip() for cmd in l.split('|', 1)]) + if not llc_cmd.startswith('llc '): + print >>sys.stderr, 'WARNING: Skipping non-llc RUN line: ' + l + continue + + if not filecheck_cmd.startswith('FileCheck '): + print >>sys.stderr, 'WARNING: Skipping non-FileChecked RUN line: ' + l + continue + + llc_cmd_args = llc_cmd[len('llc'):].strip() + llc_cmd_args = llc_cmd_args.replace('< %s', '').replace('%s', '').strip() + + check_prefixes = [m.group(1) + for m in check_prefix_re.finditer(filecheck_cmd)] + if not check_prefixes: + check_prefixes = ['CHECK'] + + # FIXME: We should use multiple check prefixes to common check lines. For + # now, we just ignore all but the last. + checks.append((check_prefixes, llc_cmd_args)) + + asm = {} + for prefixes, _ in checks: + for prefix in prefixes: + asm.update({prefix: dict()}) + for prefixes, llc_args in checks: + if args.verbose: + print >>sys.stderr, 'Extracted LLC cmd: llc ' + llc_args + print >>sys.stderr, 'Extracted FileCheck prefixes: ' + str(prefixes) + raw_asm = llc(args, llc_args, test) + # Build up a dictionary of all the function bodies. + for m in asm_function_re.finditer(raw_asm): + if not m: + continue + f = m.group('f') + f_asm = scrub_asm(m.group('body')) + if f.startswith('stress'): + # We only use the last line of the asm for stress tests. + f_asm = '\n'.join(f_asm.splitlines()[-1:]) + if args.verbose: + print >>sys.stderr, 'Processing asm for function: ' + f + for l in f_asm.splitlines(): + print >>sys.stderr, ' ' + l + for prefix in prefixes: + if f in asm[prefix] and asm[prefix][f] != f_asm: + if prefix == prefixes[-1]: + print >>sys.stderr, ('WARNING: Found conflicting asm under the ' + 'same prefix!') + else: + asm[prefix][f] = None + continue + + asm[prefix][f] = f_asm + + is_in_function = False + is_in_function_start = False + prefix_set = set([prefix for prefixes, _ in checks for prefix in prefixes]) + if args.verbose: + print >>sys.stderr, 'Rewriting FileCheck prefixes: %s' % (prefix_set,) + fixed_lines = [] + for l in test_lines: + if is_in_function_start: + if l.lstrip().startswith(';'): + m = check_re.match(l) + if not m or m.group(1) not in prefix_set: + fixed_lines.append(l) + continue + + # Print out the various check lines here + printed_prefixes = [] + for prefixes, _ in checks: + for prefix in prefixes: + if prefix in printed_prefixes: + break + if not asm[prefix][name]: + continue + if len(printed_prefixes) != 0: + fixed_lines.append(';') + printed_prefixes.append(prefix) + fixed_lines.append('; %s-LABEL: %s:' % (prefix, name)) + asm_lines = asm[prefix][name].splitlines() + fixed_lines.append('; %s: %s' % (prefix, asm_lines[0])) + for asm_line in asm_lines[1:]: + fixed_lines.append('; %s-NEXT: %s' % (prefix, asm_line)) + break + is_in_function_start = False + + if is_in_function: + # Skip any blank comment lines in the IR. + if l.strip() == ';': + continue + # And skip any CHECK lines. We'll build our own. + m = check_re.match(l) + if m and m.group(1) in prefix_set: + continue + # Collect the remaining lines in the function body and look for the end + # of the function. + fixed_lines.append(l) + if l.strip() == '}': + is_in_function = False + continue + + fixed_lines.append(l) + + m = ir_function_re.match(l) + if not m: + continue + name = m.group(1) + if args.function is not None and name != args.function: + # When filtering on a specific function, skip all others. + continue + is_in_function = is_in_function_start = True + + if args.verbose: + print>>sys.stderr, 'Writing %d fixed lines to %s...' % ( + len(fixed_lines), test) + with open(test, 'w') as f: + f.writelines([l + '\n' for l in fixed_lines]) + + +if __name__ == '__main__': + main() diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim index e8273dd..913d0f5 100644 --- a/utils/vim/llvm.vim +++ b/utils/vim/llvm.vim @@ -41,29 +41,28 @@ syn keyword llvmKeyword alignstack alwaysinline appending arm_aapcs_vfpcc syn keyword llvmKeyword arm_aapcscc arm_apcscc asm atomic available_externally syn keyword llvmKeyword blockaddress byval c catch cc ccc cleanup coldcc common syn keyword llvmKeyword constant datalayout declare default define deplibs -syn keyword llvmKeyword dllexport dllimport except extern_weak external fastcc -syn keyword llvmKeyword filter gc global hidden initialexec inlinehint inreg -syn keyword llvmKeyword intel_ocl_bicc inteldialect internal -syn keyword llvmKeyword linkonce linkonce_odr -syn keyword llvmKeyword localdynamic localexec minsize module monotonic -syn keyword llvmKeyword msp430_intrcc naked nest noalias nocapture -syn keyword llvmKeyword noimplicitfloat noinline nonlazybind noredzone noreturn -syn keyword llvmKeyword nounwind optnone optsize personality private protected -syn keyword llvmKeyword ptx_device ptx_kernel readnone readonly release -syn keyword llvmKeyword returns_twice sanitize_thread sanitize_memory -syn keyword llvmKeyword section seq_cst sideeffect signext singlethread -syn keyword llvmKeyword spir_func spir_kernel sret ssp sspreq sspstrong -syn keyword llvmKeyword tail target thread_local to triple unnamed_addr -syn keyword llvmKeyword unordered uwtable volatile weak weak_odr -syn keyword llvmKeyword x86_fastcallcc x86_stdcallcc x86_thiscallcc x86_64_sysvcc -syn keyword llvmKeyword x86_64_win64cc zeroext -syn keyword llvmKeyword uselistorder uselistorder_bb +syn keyword llvmKeyword distinct dllexport dllimport except extern_weak external +syn keyword llvmKeyword externally_initialized fastcc filter gc global hidden +syn keyword llvmKeyword initialexec inlinehint inreg intel_ocl_bicc inteldialect +syn keyword llvmKeyword internal linkonce linkonce_odr localdynamic localexec +syn keyword llvmKeyword minsize module monotonic msp430_intrcc naked nest +syn keyword llvmKeyword noalias nocapture noimplicitfloat noinline nonlazybind +syn keyword llvmKeyword noredzone noreturn nounwind optnone optsize personality +syn keyword llvmKeyword private protected ptx_device ptx_kernel readnone +syn keyword llvmKeyword readonly release returns_twice sanitize_thread +syn keyword llvmKeyword sanitize_memory section seq_cst sideeffect signext +syn keyword llvmKeyword singlethread spir_func spir_kernel sret ssp sspreq +syn keyword llvmKeyword sspstrong tail target thread_local to triple +syn keyword llvmKeyword unnamed_addr unordered uwtable volatile weak weak_odr +syn keyword llvmKeyword x86_fastcallcc x86_stdcallcc x86_thiscallcc +syn keyword llvmKeyword x86_64_sysvcc x86_64_win64cc zeroext uselistorder +syn keyword llvmKeyword uselistorder_bb " Obsolete keywords. syn keyword llvmError getresult begin end " Misc syntax. -syn match llvmNoName /[%@]\d\+\>/ +syn match llvmNoName /[%@!]\d\+\>/ syn match llvmNumber /-\?\<\d\+\>/ syn match llvmFloat /-\?\<\d\+\.\d*\(e[+-]\d\+\)\?\>/ syn match llvmFloat /\<0x\x\+\>/ @@ -74,6 +73,17 @@ syn region llvmString start=/"/ skip=/\\"/ end=/"/ syn match llvmLabel /[-a-zA-Z$._][-a-zA-Z$._0-9]*:/ syn match llvmIdentifier /[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*/ +" Named metadata and specialized metadata keywords. +syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*$/ +syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*[=!]/ +syn match llvmType /!\zs\a\+\ze\s*(/ +syn match llvmConstant /\/ +syn match llvmConstant /\/ +syn match llvmConstant /\/ +syn match llvmConstant /\/ +syn match llvmConstant /\/ +syn match llvmConstant /\/ + " Syntax-highlight dejagnu test commands. syn match llvmSpecialComment /;\s*RUN:.*$/ syn match llvmSpecialComment /;\s*PR\d*\s*$/ -- cgit v1.1