diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 |
commit | 67c32a98315f785a9ec9d531c1f571a0196c7463 (patch) | |
tree | 4abb9cbeecc7901726dd0b4a37369596c852e9ef /utils/TableGen | |
parent | 9f61947910e6ab40de38e6b4034751ef1513200f (diff) |
Diffstat (limited to 'utils/TableGen')
39 files changed, 1681 insertions, 1355 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 1277086ba823..5ee20dda0261 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -115,6 +115,7 @@ #include <map> #include <set> #include <sstream> +#include <forward_list> 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<ClassInfo*>::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<ResOperand, 8> 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<AsmOperand, 8> AsmOperands; /// Predicates - The required subtarget features to match this instruction. - SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures; + SmallVector<const SubtargetFeatureInfo *, 4> 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<const CodeGenInstAlias> Alias) + : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), DefRec(Alias.release()) { + } + + ~MatchableInfo() { + delete DefRec.dyn_cast<const CodeGenInstAlias*>(); } // Two-operand aliases clone from the main matchable, but mark the second @@ -448,7 +450,7 @@ struct MatchableInfo { void formTwoOperandAlias(StringRef Constraint); void initialize(const AsmMatcherInfo &Info, - SmallPtrSet<Record*, 16> &SingletonRegisters, + SmallPtrSetImpl<Record*> &SingletonRegisters, int AsmVariantNo, std::string &RegisterPrefix); /// validate - Return true if this matchable is a valid thing to match against @@ -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); @@ -565,16 +567,16 @@ struct SubtargetFeatureInfo { Record *TheDef; /// \brief An unique index assigned to represent this feature. - unsigned Index; + uint64_t Index; - SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} + SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {} /// \brief The name of the enumerated constant identifying this feature. std::string getEnumName() const { 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<ClassInfo*> Classes; + std::forward_list<ClassInfo> Classes; /// The information on the matchables to match. - std::vector<MatchableInfo*> Matchables; + std::vector<std::unique_ptr<MatchableInfo>> Matchables; /// Info for custom matching operands by user defined methods. std::vector<OperandMatchEntry> OperandMatchInfo; @@ -621,7 +623,7 @@ public: RegisterClassesTy RegisterClasses; /// Map of Predicate records to their subtarget information. - std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> SubtargetFeatures; + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures; /// Map of AsmOperandClass records to their class information. std::map<Record*, ClassInfo*> AsmOperandClasses; @@ -644,7 +646,7 @@ private: /// buildRegisterClasses - Build the ClassInfo* instances for register /// classes. - void buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters); + void buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters); /// buildOperandClasses - Build the ClassInfo* instances for user defined /// operand classes. @@ -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<Record*, SubtargetFeatureInfo*, LessRecordByID>::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"; } @@ -766,7 +767,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { } void MatchableInfo::initialize(const AsmMatcherInfo &Info, - SmallPtrSet<Record*, 16> &SingletonRegisters, + SmallPtrSetImpl<Record*> &SingletonRegisters, int AsmVariantNo, std::string &RegisterPrefix) { AsmVariantID = AsmVariantNo; AsmString = @@ -777,8 +778,8 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info, // Compute the require features. std::vector<Record*> 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. @@ -995,7 +996,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 +1006,6 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { Entry->RenderMethod = "<invalid>"; Entry->ParserMethod = ""; Entry->DiagnosticType = ""; - Classes.push_back(Entry); } return Entry; @@ -1075,11 +1076,9 @@ struct LessRegisterSet { }; void AsmMatcherInfo:: -buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { - const std::vector<CodeGenRegister*> &Registers = - Target.getRegBank().getRegisters(); - ArrayRef<CodeGenRegisterClass*> RegClassList = - Target.getRegBank().getRegClasses(); +buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) { + const auto &Registers = Target.getRegBank().getRegisters(); + auto &RegClassList = Target.getRegBank().getRegClasses(); typedef std::set<RegisterSet, LessRegisterSet> RegisterSetSet; @@ -1087,15 +1086,12 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { RegisterSetSet RegisterSets; // Gather the defined sets. - for (ArrayRef<CodeGenRegisterClass*>::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 (SmallPtrSet<Record*, 16>::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 +1099,16 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { // a unique register set class), and build the mapping of registers to the set // they should classify to. std::map<Record*, RegisterSet> RegisterMap; - for (std::vector<CodeGenRegister*>::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 +1116,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { std::swap(Tmp, ContainingSet); std::insert_iterator<RegisterSet> 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 +1129,35 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { // Construct the register classes. std::map<RegisterSet, ClassInfo*, LessRegisterSet> 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<CodeGenRegisterClass*>::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 +1180,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { RegisterClasses[it->first] = RegisterSetClasses[it->second]; // Name the register classes which correspond to singleton registers. - for (SmallPtrSet<Record*, 16>::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 +1198,36 @@ void AsmMatcherInfo::buildOperandClasses() { Records.getAllDerivedDefinitions("AsmOperandClass"); // Pre-populate AsmOperandClasses map. - for (std::vector<Record*>::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<Record*>::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<DefInit>(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<StringInit>(PMName)) { CI->PredicateMethod = SI->getValue(); } else { @@ -1249,7 +1236,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<StringInit>(RMName)) { CI->RenderMethod = SI->getValue(); } else { @@ -1258,18 +1245,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<StringInit>(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<StringInit>(DiagnosticType)) CI->DiagnosticType = SI->getValue(); - AsmOperandClasses[*it] = CI; - Classes.push_back(CI); + ++Index; } } @@ -1288,16 +1274,13 @@ void AsmMatcherInfo::buildOperandMatchInfo() { typedef std::map<ClassInfo *, unsigned, less_ptr<ClassInfo>> OpClassMaskTy; OpClassMaskTy OpClassMask; - for (std::vector<MatchableInfo*>::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 +1288,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 +1310,10 @@ void AsmMatcherInfo::buildInfo() { if (Pred->getName().empty()) PrintFatalError(Pred->getLoc(), "Predicate has no name!"); - unsigned FeatureNo = SubtargetFeatures.size(); - SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); - DEBUG(SubtargetFeatures[Pred]->dump()); - assert(FeatureNo < 32 && "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 +1327,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<MatchableInfo> II(new MatchableInfo(CGI)); + std::unique_ptr<MatchableInfo> II(new MatchableInfo(*CGI)); II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); @@ -1366,14 +1347,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 +1355,8 @@ void AsmMatcherInfo::buildInfo() { std::vector<Record*> 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<CodeGenInstAlias>(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 +1365,14 @@ void AsmMatcherInfo::buildInfo() { .startswith( MatchPrefix)) continue; - std::unique_ptr<MatchableInfo> II(new MatchableInfo(Alias)); + std::unique_ptr<MatchableInfo> 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 +1384,8 @@ void AsmMatcherInfo::buildInfo() { // Build the information about matchables, now that we have fully formed // classes. - std::vector<MatchableInfo*> NewMatchables; - for (std::vector<MatchableInfo*>::iterator it = Matchables.begin(), - ie = Matchables.end(); it != ie; ++it) { - MatchableInfo *II = *it; - + std::vector<std::unique_ptr<MatchableInfo>> 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 +1420,9 @@ void AsmMatcherInfo::buildInfo() { OperandName = Token.substr(1); if (II->DefRec.is<const CodeGenInstruction*>()) - buildInstructionOperandReference(II, OperandName, i); + buildInstructionOperandReference(II.get(), OperandName, i); else - buildAliasOperandReference(II, OperandName, Op); + buildAliasOperandReference(II.get(), OperandName, Op); } if (II->DefRec.is<const CodeGenInstruction*>()) { @@ -1469,14 +1440,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 +1464,7 @@ void AsmMatcherInfo::buildInfo() { } // Reorder classes so that classes precede super classes. - std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>()); + Classes.sort(); } /// buildInstructionOperandReference - The specified operand is a reference to a @@ -1703,7 +1674,7 @@ static unsigned getConverterOperandID(const std::string &Name, static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, - std::vector<MatchableInfo*> &Infos, + std::vector<std::unique_ptr<MatchableInfo>> &Infos, raw_ostream &OS) { SetVector<std::string> OperandConversionKinds; SetVector<std::string> InstructionConversionKinds; @@ -1767,16 +1738,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, OperandConversionKinds.insert("CVT_Tied"); enum { CVT_Done, CVT_Reg, CVT_Tied }; - for (std::vector<MatchableInfo*>::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 +1776,17 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, std::vector<uint8_t> 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. @@ -1940,7 +1909,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 +1972,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, /// emitMatchClassEnumeration - Emit the enumeration for match class kinds. static void emitMatchClassEnumeration(CodeGenTarget &Target, - std::vector<ClassInfo*> &Infos, + std::forward_list<ClassInfo> &Infos, raw_ostream &OS) { OS << "namespace {\n\n"; @@ -2011,9 +1980,7 @@ static void emitMatchClassEnumeration(CodeGenTarget &Target, << "/// instruction matching.\n"; OS << "enum MatchClassKind {\n"; OS << " InvalidMatchClass = 0,\n"; - for (std::vector<ClassInfo*>::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 +2020,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<ClassInfo*>::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 +2039,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 +2056,7 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, /// emitIsSubclass - Emit the subclass predicate function. static void emitIsSubclass(CodeGenTarget &Target, - std::vector<ClassInfo*> &Infos, + std::forward_list<ClassInfo> &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 +2069,9 @@ static void emitIsSubclass(CodeGenTarget &Target, SS << " switch (A) {\n"; SS << " default:\n"; SS << " return false;\n"; - for (std::vector<ClassInfo*>::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &A = **it; - + for (const auto &A : Infos) { std::vector<StringRef> SuperClasses; - for (std::vector<ClassInfo*>::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 +2113,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<ClassInfo*> &Infos, + std::forward_list<ClassInfo> &Infos, raw_ostream &OS) { // Construct the match list. std::vector<StringMatcher::StringPair> Matches; - for (std::vector<ClassInfo*>::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 +2137,14 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, raw_ostream &OS) { // Construct the match list. std::vector<StringMatcher::StringPair> Matches; - const std::vector<CodeGenRegister*> &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"; @@ -2205,7 +2156,9 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, } static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range <= 0xFFFFFFFFULL && "Enum too large"); + assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFFFFFFULL) + return "uint64_t"; if (Range > 0xFFFF) return "uint32_t"; if (Range > 0xFF) @@ -2228,11 +2181,9 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, << "instruction matching.\n"; OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info) << " {\n"; - for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator - it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; - OS << " " << SFI.getEnumName() << " = (1U << " << SFI.Index << "),\n"; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; } OS << " Feature_None = 0\n"; OS << "};\n\n"; @@ -2263,13 +2214,11 @@ static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "// User-level names for subtarget features that participate in\n" << "// instruction matching.\n" - << "static const char *getSubtargetFeatureName(unsigned Val) {\n"; + << "static const char *getSubtargetFeatureName(uint64_t Val) {\n"; if (!Info.SubtargetFeatures.empty()) { OS << " switch(Val) {\n"; - typedef std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> 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"; @@ -2290,13 +2239,11 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, std::string ClassName = Info.AsmParser->getValueAsString("AsmParserClassName"); - OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" + OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" << "ComputeAvailableFeatures(uint64_t FB) const {\n"; - OS << " unsigned Features = 0;\n"; - for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator - it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; + OS << " uint64_t Features = 0;\n"; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; OS << " if ("; std::string CondStorage = @@ -2342,7 +2289,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() + @@ -2446,7 +2393,7 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, if (Aliases.empty()) return false; OS << "static void applyMnemonicAliases(StringRef &Mnemonic, " - "unsigned Features, unsigned VariantID) {\n"; + "uint64_t Features, unsigned VariantID) {\n"; OS << " switch (VariantID) {\n"; unsigned VariantCount = Target.getAsmParserVariantCount(); for (unsigned VC = 0; VC != VariantCount; ++VC) { @@ -2486,8 +2433,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"; @@ -2564,13 +2511,11 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, << " &Operands,\n unsigned MCK) {\n\n" << " switch(MCK) {\n"; - for (std::vector<ClassInfo*>::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"; @@ -2589,7 +2534,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the next operand index.\n"; OS << " unsigned NextOpNum = Operands.size()-1;\n"; @@ -2649,22 +2594,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<MatchableInfo>()); + [](const std::unique_ptr<MatchableInfo> &a, + const std::unique_ptr<MatchableInfo> &b){ + return *a < *b;}); DEBUG_WITH_TYPE("instruction_info", { - for (std::vector<MatchableInfo*>::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"; @@ -2691,7 +2637,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of MCTargetAsmParser.\n"; - OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; + OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" << " const OperandVector " @@ -2699,11 +2645,9 @@ 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" - << " unsigned &ErrorInfo," + << " uint64_t &ErrorInfo," << " bool matchingInlineAsm,\n" << " unsigned VariantID = 0);\n"; @@ -2784,15 +2728,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { size_t MaxNumOperands = 0; unsigned MaxMnemonicIndex = 0; bool HasDeprecation = false; - for (std::vector<MatchableInfo*>::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)); } @@ -2820,8 +2761,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"; @@ -2850,33 +2792,30 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "static const MatchEntry MatchTable" << VC << "[] = {\n"; - for (std::vector<MatchableInfo*>::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; @@ -2893,7 +2832,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"); @@ -2909,10 +2848,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" - << "unsigned &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"; @@ -2922,7 +2860,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the instruction mnemonic, which is the first token.\n"; OS << " StringRef Mnemonic = ((" << Target.getName() @@ -2938,7 +2876,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " bool HadMatchOtherThanFeatures = false;\n"; OS << " bool HadMatchOtherThanPredicate = false;\n"; OS << " unsigned RetCode = Match_InvalidOperand;\n"; - OS << " unsigned MissingFeatures = ~0U;\n"; + OS << " uint64_t MissingFeatures = ~0ULL;\n"; OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; OS << " // wrong for all instances of the instruction.\n"; OS << " ErrorInfo = ~0U;\n"; @@ -2947,7 +2885,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"); @@ -3014,14 +2952,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if ((AvailableFeatures & it->RequiredFeatures) " << "!= it->RequiredFeatures) {\n"; OS << " HadMatchOtherThanFeatures = true;\n"; - OS << " unsigned NewMissingFeatures = it->RequiredFeatures & " + OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " if (CountPopulation_32(NewMissingFeatures) <=\n" - " CountPopulation_32(MissingFeatures))\n"; + OS << " if (CountPopulation_64(NewMissingFeatures) <=\n" + " CountPopulation_64(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"; @@ -3055,7 +2994,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n"; OS << " SMLoc Loc = ((" << Target.getName() << "Operand&)*Operands[0]).getStartLoc();\n"; - OS << " Parser.Warning(Loc, Info, None);\n"; + OS << " getParser().Warning(Loc, Info, None);\n"; OS << " }\n"; } diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 7ef70d31b693..5924d5f48dc4 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -208,9 +208,6 @@ FindUniqueOperandCommands(std::vector<std::string> &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<std::string> &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<std::vector<std::string> > TableDrivenOperandPrinters; + std::vector<std::vector<std::string>> TableDrivenOperandPrinters; while (1) { std::vector<std::string> 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<CodeGenRegister*> &Registers) { + const std::deque<CodeGenRegister> &Registers) { SequenceToOffsetTable<std::string> StringTable; SmallVector<std::string, 4> 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<CodeGenRegister*> &Registers = - Target.getRegBank().getRegisters(); + const auto &Registers = Target.getRegBank().getRegisters(); std::vector<Record*> 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<StringRef, StringRef::iterator> 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) { @@ -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 5d9ead10b361..6ddc510473ed 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 4cee35289f12..6a900b799701 100644 --- a/utils/TableGen/AsmWriterInst.h +++ b/utils/TableGen/AsmWriterInst.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef ASMWRITER_INST_H -#define ASMWRITER_INST_H +#ifndef LLVM_UTILS_TABLEGEN_ASMWRITERINST_H +#define LLVM_UTILS_TABLEGEN_ASMWRITERINST_H #include <string> #include <vector> @@ -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/CTagsEmitter.cpp b/utils/TableGen/CTagsEmitter.cpp index 5d6d6da9cf25..bbed92a13852 100644 --- a/utils/TableGen/CTagsEmitter.cpp +++ b/utils/TableGen/CTagsEmitter.cpp @@ -69,19 +69,15 @@ SMLoc CTagsEmitter::locate(const Record *R) { } void CTagsEmitter::run(raw_ostream &OS) { - const std::map<std::string, Record *> &Classes = Records.getClasses(); - const std::map<std::string, Record *> &Defs = Records.getDefs(); + const auto &Classes = Records.getClasses(); + const auto &Defs = Records.getDefs(); std::vector<Tag> Tags; // Collect tags. Tags.reserve(Classes.size() + Defs.size()); - for (std::map<std::string, Record *>::const_iterator I = Classes.begin(), - E = Classes.end(); - I != E; ++I) - Tags.push_back(Tag(I->first, locate(I->second))); - for (std::map<std::string, Record *>::const_iterator I = Defs.begin(), - E = Defs.end(); - I != E; ++I) - Tags.push_back(Tag(I->first, locate(I->second))); + for (const auto &C : Classes) + Tags.push_back(Tag(C.first, locate(C.second.get()))); + for (const auto &D : Defs) + Tags.push_back(Tag(D.first, locate(D.second.get()))); // Emit tags. std::sort(Tags.begin(), Tags.end()); OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n"; diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index ec2251d934c0..6a65e5e97821 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -181,13 +181,17 @@ void CallingConvEmitter::EmitAction(Record *Action, if (Size) O << Size << ", "; else - O << "\n" << IndentStr << " State.getTarget().getDataLayout()" - "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())), "; + O << "\n" << IndentStr + << " State.getMachineFunction().getSubtarget().getDataLayout()" + "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," + " "; if (Align) O << Align; else - O << "\n" << IndentStr << " State.getTarget().getDataLayout()" - "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()))"; + O << "\n" << IndentStr + << " State.getMachineFunction().getSubtarget().getDataLayout()" + "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()" + "))"; O << ");\n" << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" << Counter << ", LocVT, LocInfo));\n"; diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 4d0c0ca8e701..11911b63b7bd 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -24,14 +24,6 @@ #include <vector> using namespace llvm; -// FIXME: Somewhat hackish to use a command line option for this. There should -// be a CodeEmitter class in the Target.td that controls this sort of thing -// instead. -static cl::opt<bool> -MCEmitter("mc-emitter", - cl::desc("Generate CodeEmitter for use with the MC library."), - cl::init(false)); - namespace { class CodeEmitterGen { @@ -134,15 +126,13 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, if (SO.second == 0) { Case += " // op: " + VarName + "\n" + " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx); - if (MCEmitter) - Case += ", Fixups, STI"; + Case += ", Fixups, STI"; Case += ");\n"; } } else { Case += " // op: " + VarName + "\n" + " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")"; - if (MCEmitter) - Case += ", Fixups, STI"; + Case += ", Fixups, STI"; Case += ");\n"; } @@ -223,8 +213,7 @@ std::string CodeEmitterGen::getInstructionCase(Record *R, std::string PostEmitter = R->getValueAsString("PostEncoderMethod"); if (!PostEmitter.empty()) { Case += " Value = " + PostEmitter + "(MI, Value"; - if (MCEmitter) - Case += ", STI"; + Case += ", STI"; Case += ");\n"; } @@ -243,12 +232,9 @@ void CodeEmitterGen::run(raw_ostream &o) { // Emit function declaration o << "uint64_t " << Target.getName(); - if (MCEmitter) - o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" - << " SmallVectorImpl<MCFixup> &Fixups,\n" - << " const MCSubtargetInfo &STI) const {\n"; - else - o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n"; + o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" + << " SmallVectorImpl<MCFixup> &Fixups,\n" + << " const MCSubtargetInfo &STI) const {\n"; // Emit instruction base values o << " static const uint64_t InstBits[] = {\n"; diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 2602bbcf6f61..c3de37e94533 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -771,7 +771,7 @@ static unsigned getPatternSize(const TreePatternNode *P, /// Compute the complexity metric for the input pattern. This roughly /// corresponds to the number of nodes that are covered. -unsigned PatternToMatch:: +int PatternToMatch:: getPatternComplexity(const CodeGenDAGPatterns &CGP) const { return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity(); } @@ -1387,7 +1387,7 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, if (R->isSubClassOf("SubRegIndex")) { assert(ResNo == 0 && "SubRegisterIndices only produce one result!"); - return EEVT::TypeSet(); + return EEVT::TypeSet(MVT::i32, TP); } if (R->isSubClassOf("ValueType")) { @@ -1529,6 +1529,31 @@ TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const { return false; } +static bool isOperandClass(const TreePatternNode *N, StringRef Class) { + if (!N->isLeaf()) + return N->getOperator()->isSubClassOf(Class); + + DefInit *DI = dyn_cast<DefInit>(N->getLeafValue()); + if (DI && DI->getDef()->isSubClassOf(Class)) + return true; + + 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 @@ -1689,6 +1714,34 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled"); MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP); MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP); + } else if (getOperator()->getName() == "REG_SEQUENCE") { + // We need to do extra, custom typechecking for REG_SEQUENCE since it is + // variadic. + + unsigned NChild = getNumChildren(); + if (NChild < 3) { + TP.error("REG_SEQUENCE requires at least 3 operands!"); + return false; + } + + if (NChild % 2 == 0) { + TP.error("REG_SEQUENCE requires an odd number of operands!"); + return false; + } + + if (!isOperandClass(getChild(0), "RegisterClass")) { + TP.error("REG_SEQUENCE requires a RegisterClass for first operand!"); + return false; + } + + for (unsigned I = 1; I < NChild; I += 2) { + TreePatternNode *SubIdxChild = getChild(I + 1); + if (!isOperandClass(SubIdxChild, "SubRegIndex")) { + TP.error("REG_SEQUENCE requires a SubRegIndex for operand " + + itostr(I + 1) + "!"); + return false; + } + } } unsigned ChildNo = 0; @@ -1704,8 +1757,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; } @@ -1729,8 +1781,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++); @@ -1749,9 +1801,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP); } - if (ChildNo != getNumChildren()) { - TP.error("Instruction '" + getOperator()->getName() + - "' was provided too many operands!"); + if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) { + emitTooManyOperandsError(TP, getOperator()->getName(), + ChildNo, getNumChildren()); return false; } @@ -1871,7 +1923,7 @@ TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, Trees.push_back(Pat); } -void TreePattern::error(const std::string &Msg) { +void TreePattern::error(const Twine &Msg) { if (HasError) return; dump(); @@ -2226,13 +2278,6 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : VerifyInstructionFlags(); } -CodeGenDAGPatterns::~CodeGenDAGPatterns() { - for (pf_iterator I = PatternFragments.begin(), - E = PatternFragments.end(); I != E; ++I) - delete I->second; -} - - Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const { Record *N = Records.getDef(Name); if (!N || !N->isSubClassOf("SDNode")) { @@ -2294,9 +2339,9 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); TreePattern *P = - new TreePattern(Fragments[i], Tree, - !Fragments[i]->isSubClassOf("OutPatFrag"), *this); - PatternFragments[Fragments[i]] = P; + (PatternFragments[Fragments[i]] = llvm::make_unique<TreePattern>( + Fragments[i], Tree, !Fragments[i]->isSubClassOf("OutPatFrag"), + *this)).get(); // Validate the argument list, converting it to set, to discard duplicates. std::vector<std::string> &Args = P->getArgList(); @@ -2354,16 +2399,16 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag")) continue; - TreePattern *ThePat = PatternFragments[Fragments[i]]; - ThePat->InlinePatternFragments(); + TreePattern &ThePat = *PatternFragments[Fragments[i]]; + ThePat.InlinePatternFragments(); // Infer as many types as possible. Don't worry about it if we don't infer // all of them, some may depend on the inputs of the pattern. - ThePat->InferAllTypes(); - ThePat->resetError(); + ThePat.InferAllTypes(); + ThePat.resetError(); // If debugging, print out the pattern fragment result. - DEBUG(ThePat->dump()); + DEBUG(ThePat.dump()); } } @@ -2524,8 +2569,10 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, I->error("set destination should be a register!"); DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue()); - if (!Val) + if (!Val) { I->error("set destination should be a register!"); + continue; + } if (Val->getDef()->isSubClassOf("RegisterClass") || Val->getDef()->isSubClassOf("ValueType") || @@ -3081,13 +3128,6 @@ void CodeGenDAGPatterns::InferInstructionFlags() { CodeGenInstruction &InstInfo = const_cast<CodeGenInstruction &>(*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) { @@ -3274,14 +3314,14 @@ void CodeGenDAGPatterns::ParsePatterns() { if (LI->getSize() == 0) continue; // no pattern. // Parse the instruction. - TreePattern *Result = new TreePattern(CurPattern, LI, false, *this); + TreePattern Result(CurPattern, LI, false, *this); // Inline pattern fragments into it. - Result->InlinePatternFragments(); + Result.InlinePatternFragments(); - if (Result->getNumTrees() != 1) - Result->error("Cannot handle instructions producing instructions " - "with temporaries yet!"); + if (Result.getNumTrees() != 1) + Result.error("Cannot handle instructions producing instructions " + "with temporaries yet!"); bool IterateInference; bool InferredAllPatternTypes, InferredAllResultTypes; @@ -3294,7 +3334,7 @@ void CodeGenDAGPatterns::ParsePatterns() { // Infer as many types as possible. If we cannot infer all of them, we // can never do anything with this pattern: report it to the user. InferredAllResultTypes = - Result->InferAllTypes(&Pattern->getNamedNodesMap()); + Result.InferAllTypes(&Pattern->getNamedNodesMap()); IterateInference = false; @@ -3302,13 +3342,13 @@ void CodeGenDAGPatterns::ParsePatterns() { // resolve cases where the input type is known to be a pointer type (which // is considered resolved), but the result knows it needs to be 32- or // 64-bits. Infer the other way for good measure. - for (unsigned i = 0, e = std::min(Result->getTree(0)->getNumTypes(), + for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(), Pattern->getTree(0)->getNumTypes()); i != e; ++i) { - IterateInference = Pattern->getTree(0)-> - UpdateNodeType(i, Result->getTree(0)->getExtType(i), *Result); - IterateInference |= Result->getTree(0)-> - UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result); + IterateInference = Pattern->getTree(0)->UpdateNodeType( + i, Result.getTree(0)->getExtType(i), Result); + IterateInference |= Result.getTree(0)->UpdateNodeType( + i, Pattern->getTree(0)->getExtType(i), Result); } // If our iteration has converged and the input pattern's types are fully @@ -3322,8 +3362,8 @@ void CodeGenDAGPatterns::ParsePatterns() { // arbitrary types to the result pattern's nodes. if (!IterateInference && InferredAllPatternTypes && !InferredAllResultTypes) - IterateInference = ForceArbitraryInstResultType(Result->getTree(0), - *Result); + IterateInference = + ForceArbitraryInstResultType(Result.getTree(0), Result); } while (IterateInference); // Verify that we inferred enough types that we can do something with the @@ -3332,7 +3372,7 @@ void CodeGenDAGPatterns::ParsePatterns() { Pattern->error("Could not infer all types in pattern!"); if (!InferredAllResultTypes) { Pattern->dump(); - Result->error("Could not infer all types in pattern result!"); + Result.error("Could not infer all types in pattern result!"); } // Validate that the input pattern is correct. @@ -3345,7 +3385,7 @@ void CodeGenDAGPatterns::ParsePatterns() { InstImpResults); // Promote the xform function to be an explicit node if set. - TreePatternNode *DstPattern = Result->getOnlyTree(); + TreePatternNode *DstPattern = Result.getOnlyTree(); std::vector<TreePatternNode*> ResultNodeOperands; for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) { TreePatternNode *OpNode = DstPattern->getChild(ii); @@ -3357,16 +3397,16 @@ void CodeGenDAGPatterns::ParsePatterns() { } ResultNodeOperands.push_back(OpNode); } - DstPattern = Result->getOnlyTree(); + DstPattern = Result.getOnlyTree(); if (!DstPattern->isLeaf()) DstPattern = new TreePatternNode(DstPattern->getOperator(), ResultNodeOperands, DstPattern->getNumTypes()); - for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i) - DstPattern->setType(i, Result->getOnlyTree()->getExtType(i)); + for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i) + DstPattern->setType(i, Result.getOnlyTree()->getExtType(i)); - TreePattern Temp(Result->getRecord(), DstPattern, false, *this); + TreePattern Temp(Result.getRecord(), DstPattern, false, *this); Temp.InferAllTypes(); diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index fb30cdd94853..c0812cf05536 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_DAGPATTERNS_H -#define CODEGEN_DAGPATTERNS_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H +#define LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H #include "CodeGenIntrinsics.h" #include "CodeGenTarget.h" @@ -597,7 +597,7 @@ public: /// error - If this is the first error in the current resolution step, /// print it and set the error flag. Otherwise, continue silently. - void error(const std::string &Msg); + void error(const Twine &Msg); bool hasError() const { return HasError; } @@ -667,7 +667,7 @@ public: PatternToMatch(Record *srcrecord, ListInit *preds, TreePatternNode *src, TreePatternNode *dst, const std::vector<Record*> &dstregs, - unsigned complexity, unsigned uid) + int complexity, unsigned uid) : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst), Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {} @@ -676,7 +676,7 @@ public: TreePatternNode *SrcPattern; // Source pattern to match. TreePatternNode *DstPattern; // Resulting pattern. std::vector<Record*> Dstregs; // Physical register defs being matched. - unsigned AddedComplexity; // Add to matching pattern complexity. + int AddedComplexity; // Add to matching pattern complexity. unsigned ID; // Unique ID for the record. Record *getSrcRecord() const { return SrcRecord; } @@ -684,13 +684,13 @@ public: TreePatternNode *getSrcPattern() const { return SrcPattern; } TreePatternNode *getDstPattern() const { return DstPattern; } const std::vector<Record*> &getDstRegs() const { return Dstregs; } - unsigned getAddedComplexity() const { return AddedComplexity; } + int getAddedComplexity() const { return AddedComplexity; } std::string getPredicateCheck() const; /// Compute the complexity metric for the input pattern. This roughly /// corresponds to the number of nodes that are covered. - unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const; + int getPatternComplexity(const CodeGenDAGPatterns &CGP) const; }; class CodeGenDAGPatterns { @@ -702,7 +702,8 @@ class CodeGenDAGPatterns { std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes; std::map<Record*, std::pair<Record*, std::string>, LessRecordByID> SDNodeXForms; std::map<Record*, ComplexPattern, LessRecordByID> ComplexPatterns; - std::map<Record*, TreePattern*, LessRecordByID> PatternFragments; + std::map<Record *, std::unique_ptr<TreePattern>, LessRecordByID> + PatternFragments; std::map<Record*, DAGDefaultOperand, LessRecordByID> DefaultOperands; std::map<Record*, DAGInstruction, LessRecordByID> Instructions; @@ -716,7 +717,6 @@ class CodeGenDAGPatterns { std::vector<PatternToMatch> PatternsToMatch; public: CodeGenDAGPatterns(RecordKeeper &R); - ~CodeGenDAGPatterns(); CodeGenTarget &getTargetInfo() { return Target; } const CodeGenTarget &getTargetInfo() const { return Target; } @@ -778,15 +778,16 @@ public: // Pattern Fragment information. TreePattern *getPatternFragment(Record *R) const { assert(PatternFragments.count(R) && "Invalid pattern fragment request!"); - return PatternFragments.find(R)->second; + return PatternFragments.find(R)->second.get(); } TreePattern *getPatternFragmentIfRead(Record *R) const { - if (!PatternFragments.count(R)) return nullptr; - return PatternFragments.find(R)->second; + if (!PatternFragments.count(R)) + return nullptr; + return PatternFragments.find(R)->second.get(); } - typedef std::map<Record*, TreePattern*, LessRecordByID>::const_iterator - pf_iterator; + typedef std::map<Record *, std::unique_ptr<TreePattern>, + LessRecordByID>::const_iterator pf_iterator; pf_iterator pf_begin() const { return PatternFragments.begin(); } pf_iterator pf_end() const { return PatternFragments.end(); } diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 2577ad4d919d..10602964e485 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; } @@ -314,6 +317,9 @@ CodeGenInstruction::CodeGenInstruction(Record *R) hasPostISelHook = R->getValueAsBit("hasPostISelHook"); hasCtrlDep = R->getValueAsBit("hasCtrlDep"); isNotDuplicable = R->getValueAsBit("isNotDuplicable"); + isRegSequence = R->getValueAsBit("isRegSequence"); + isExtractSubreg = R->getValueAsBit("isExtractSubreg"); + isInsertSubreg = R->getValueAsBit("isInsertSubreg"); bool Unset; mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset); @@ -322,7 +328,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"); @@ -332,9 +337,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); @@ -520,10 +522,25 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return true; } + // Bits<n> (also used for 0bxx literals) + if (BitsInit *BI = dyn_cast<BitsInit>(Arg)) { + if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) + return false; + if (!BI->isComplete()) + return false; + // Convert the bits init to an integer and use that for the result. + IntInit *II = + dyn_cast_or_null<IntInit>(BI->convertInitializerTo(IntRecTy::get())); + if (!II) + return false; + ResOp = ResultOperand(II->getValue()); + return true; + } + // 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 f143875131b4..bdbe546ec97e 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_INSTRUCTION_H -#define CODEGEN_INSTRUCTION_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H +#define LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineValueType.h" @@ -247,12 +247,14 @@ namespace llvm { bool isNotDuplicable : 1; bool hasSideEffects : 1; bool hasSideEffects_Unset : 1; - bool neverHasSideEffects : 1; bool isAsCheapAsAMove : 1; bool hasExtraSrcRegAllocReq : 1; bool hasExtraDefRegAllocReq : 1; bool isCodeGenOnly : 1; bool isPseudo : 1; + bool isRegSequence : 1; + bool isExtractSubreg : 1; + bool isInsertSubreg : 1; std::string DeprecatedReason; bool HasComplexDeprecationPredicate; diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index a9ece01c904b..1f1adf11fb3b 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_INTRINSIC_H -#define CODEGEN_INTRINSIC_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H +#define LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H #include "llvm/CodeGen/MachineValueType.h" #include <string> diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 8099f134fd0e..bef8a4b8fa12 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; @@ -146,6 +146,7 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) { } const std::string &CodeGenRegister::getName() const { + assert(TheDef && "no def"); return TheDef->getName(); } @@ -661,7 +662,8 @@ 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; @@ -810,34 +812,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,60 +852,60 @@ std::string CodeGenRegisterClass::getQualifiedName() const { // Compute sub-classes of all register classes. // Assume the classes are ordered topologically. void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) { - ArrayRef<CodeGenRegisterClass*> 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<CodeGenSubRegIndex*, - SmallPtrSet<CodeGenRegisterClass*, 8> >::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 (SmallPtrSet<CodeGenRegisterClass*, 8>::const_iterator I = - FindI->second.begin(), E = FindI->second.end(); I != E; ++I) - Out.set((*I)->EnumValue); + for (CodeGenRegisterClass *RC : FindI->second) + Out.set(RC->EnumValue); } // Populate a unique sorted list of units from a register set. @@ -934,13 +936,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<Record*> 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]); @@ -949,42 +950,41 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { std::vector<Record*> Tups = Records.getAllDerivedDefinitions("RegisterTuples"); - std::vector<Record*> TupRegsCopy; - for (unsigned i = 0, e = Tups.size(); i != e; ++i) { - const std::vector<Record*> *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<Record *> 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) - RegistersByName.GetOrCreateValue( - Registers[i]->TheDef->getValueAsString("AsmName"), - Registers[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(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. @@ -996,35 +996,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; } @@ -1032,14 +1032,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)); @@ -1061,9 +1059,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) { @@ -1124,21 +1122,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. @@ -1150,7 +1146,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. @@ -1171,15 +1167,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 @@ -1194,7 +1189,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); } } @@ -1202,13 +1261,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 { @@ -1245,22 +1315,20 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets, std::vector<UberRegSet*> &RegSets, CodeGenRegBank &RegBank) { - const std::vector<CodeGenRegister*> &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<unsigned> 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::Set &Regs = RegClass.getMembers(); if (Regs.empty()) continue; @@ -1275,8 +1343,8 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets, } } // 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; @@ -1290,17 +1358,17 @@ static void computeUberSets(std::vector<UberRegSet> &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.insert(&Reg); + RegSets[i++] = USet; } } @@ -1333,11 +1401,8 @@ static void computeUberWeights(std::vector<UberRegSet> &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; @@ -1438,11 +1503,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<unsigned> NormalRegs; - Changed |= normalizeWeight(Registers[i], UberSets, RegSets, - NormalRegs, NormalUnits, *this); + Changed |= normalizeWeight(&Reg, UberSets, RegSets, NormalRegs, + NormalUnits, *this); } } } @@ -1533,18 +1598,17 @@ void CodeGenRegBank::computeRegUnitSets() { assert(RegUnitSets.empty() && "dirty RegUnitSets"); // Compute a unique RegUnitSet for each RegClass. - const ArrayRef<CodeGenRegisterClass*> &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<RegUnitSet>::const_iterator SetI = @@ -1558,9 +1622,8 @@ void CodeGenRegBank::computeRegUnitSets() { USIdx < USEnd; ++USIdx) { dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name << ":"; - ArrayRef<unsigned> 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"; }); @@ -1572,9 +1635,8 @@ void CodeGenRegBank::computeRegUnitSets() { USIdx < USEnd; ++USIdx) { dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name << ":"; - ArrayRef<unsigned> 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"); @@ -1619,9 +1681,8 @@ void CodeGenRegBank::computeRegUnitSets() { else { DEBUG(dbgs() << "UnitSet " << RegUnitSets.size()-1 << " " << RegUnitSets.back().Name << ":"; - ArrayRef<unsigned> 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";); } } @@ -1635,29 +1696,30 @@ void CodeGenRegBank::computeRegUnitSets() { USIdx < USEnd; ++USIdx) { dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name << ":"; - ArrayRef<unsigned> 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<unsigned> 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. @@ -1702,9 +1764,44 @@ 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.size(), 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; + for (size_t u = 0, ue = RegUnits.size(); u < ue; ++u) { + if (SUI == RegUnits[u]) { + RegUnitLaneMasks[u] |= LaneMask; + assert(!Found); + Found = true; + } + } + 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). @@ -1714,6 +1811,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); @@ -1740,9 +1839,13 @@ 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; @@ -1779,7 +1882,7 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) { // void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { // Map SubRegIndex to set of registers in RC supporting that SubRegIndex. - typedef std::map<CodeGenSubRegIndex*, CodeGenRegister::Set, + typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Set, CodeGenSubRegIndex::Less> SubReg2SetMap; // Compute the set of registers supporting each SubRegIndex. @@ -1794,22 +1897,21 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { // 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); } } @@ -1821,18 +1923,17 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { // void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, - unsigned FirstSubRegRC) { + std::list<CodeGenRegisterClass>::iterator FirstSubRegRC) { SmallVector<std::pair<const CodeGenRegister*, const CodeGenRegister*>, 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. @@ -1841,7 +1942,7 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, 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; + 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()); @@ -1849,29 +1950,32 @@ 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; for (unsigned i = 0, e = SSPairs.size(); i != e; ++i) - if (SubRC->contains(SSPairs[i].second)) + if (SubRC.contains(SSPairs[i].second)) SubSet.insert(SSPairs[i].first); if (SubSet.empty()) continue; // RC injects completely into SubRC. if (SubSet.size() == SSPairs.size()) { - SubRC->addSuperRegClass(SubIdx, RC); + 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, &SubSet, RC->getName() + "_with_" + + SubIdx.getName() + "_in_" + + SubRC.getName()); } } } @@ -1881,14 +1985,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); @@ -1905,10 +2014,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; } } @@ -1922,10 +2032,8 @@ void CodeGenRegBank::computeInferredRegisterClasses() { const CodeGenRegisterClass* CodeGenRegBank::getRegClassForRegister(Record *R) { const CodeGenRegister *Reg = getReg(R); - ArrayRef<CodeGenRegisterClass*> 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 278315ba47b3..87a0dcf7af3d 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_REGISTERS_H -#define CODEGEN_REGISTERS_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H +#define LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" @@ -24,14 +24,30 @@ #include "llvm/TableGen/Record.h" #include "llvm/TableGen/SetTheory.h" #include <cstdlib> +#include <list> #include <map> #include <set> #include <string> #include <vector> +#include <deque> 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 +58,8 @@ namespace llvm { uint16_t Size; uint16_t Offset; const unsigned EnumValue; - unsigned LaneMask; + mutable unsigned LaneMask; + mutable SmallVector<MaskRolPair,1> CompositionLaneMaskTransform; // Are all super-registers containing this SubRegIndex covered by their // sub-registers? @@ -101,7 +118,7 @@ namespace llvm { const CompMap &getComposites() const { return Composed; } // Compute LaneMask from Composed. Return LaneMask. - unsigned computeLaneMask(); + unsigned computeLaneMask() const; private: CompMap Composed; @@ -181,6 +198,7 @@ namespace llvm { // List of register units in ascending order. typedef SmallVector<unsigned, 16> RegUnitList; + typedef SmallVector<unsigned, 16> RegUnitLaneMaskList; // How many entries in RegUnitList are native? unsigned NumNativeRegUnits; @@ -189,11 +207,19 @@ namespace llvm { // This is only valid after computeSubRegs() completes. const RegUnitList &getRegUnits() const { return RegUnits; } + ArrayRef<unsigned> getRegUnitLaneMasks() const { + return makeArrayRef(RegUnitLaneMasks).slice(0, NumNativeRegUnits); + } + // Get the native register units. This is a prefix of getRegUnits(). ArrayRef<unsigned> getNativeRegUnits() const { return makeArrayRef(RegUnits).slice(0, NumNativeRegUnits); } + void setRegUnitLaneMasks(const RegUnitLaneMaskList &LaneMasks) { + RegUnitLaneMasks = LaneMasks; + } + // Inherit register units from subregisters. // Return true if the RegUnits changed. bool inheritRegUnits(CodeGenRegBank &RegBank); @@ -236,6 +262,7 @@ namespace llvm { SuperRegList SuperRegs; DenseMap<const CodeGenRegister*, CodeGenSubRegIndex*> SubReg2Idx; RegUnitList RegUnits; + RegUnitLaneMaskList RegUnitLaneMasks; }; @@ -257,15 +284,16 @@ namespace llvm { // Map SubRegIndex -> sub-class. This is the largest sub-class where all // registers have a SubRegIndex sub-register. - DenseMap<CodeGenSubRegIndex*, CodeGenRegisterClass*> SubClassWithSubReg; + DenseMap<const CodeGenSubRegIndex *, CodeGenRegisterClass *> + 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<CodeGenSubRegIndex*, - SmallPtrSet<CodeGenRegisterClass*, 8> > SuperRegClasses; + DenseMap<const CodeGenSubRegIndex *, SmallPtrSet<CodeGenRegisterClass *, 8>> + SuperRegClasses; // Bit vector of TopoSigs for the registers in this class. This will be // very sparse on regular architectures. @@ -280,6 +308,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 +344,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, @@ -446,8 +477,7 @@ namespace llvm { class CodeGenRegBank { SetTheory Sets; - // SubRegIndices. - std::vector<CodeGenSubRegIndex*> SubRegIndices; + std::deque<CodeGenSubRegIndex> SubRegIndices; DenseMap<Record*, CodeGenSubRegIndex*> Def2SubRegIdx; CodeGenSubRegIndex *createSubRegIndex(StringRef Name, StringRef NameSpace); @@ -457,7 +487,7 @@ namespace llvm { ConcatIdxMap ConcatIdx; // Registers. - std::vector<CodeGenRegister*> Registers; + std::deque<CodeGenRegister> Registers; StringMap<CodeGenRegister*> RegistersByName; DenseMap<Record*, CodeGenRegister*> Def2Reg; unsigned NumNativeRegUnits; @@ -468,7 +498,7 @@ namespace llvm { SmallVector<RegUnit, 8> RegUnits; // Register classes. - std::vector<CodeGenRegisterClass*> RegClasses; + std::list<CodeGenRegisterClass> RegClasses; DenseMap<Record*, CodeGenRegisterClass*> Def2RC; typedef std::map<CodeGenRegisterClass::Key, CodeGenRegisterClass*> RCKeyMap; RCKeyMap Key2RC; @@ -501,8 +531,13 @@ namespace llvm { 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<CodeGenRegisterClass>::iterator FirstSubRegRC); // Iteratively prune unit sets. void pruneUnitSets(); @@ -517,7 +552,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 +566,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<CodeGenSubRegIndex*> getSubRegIndices() { return SubRegIndices; } + const std::deque<CodeGenSubRegIndex> &getSubRegIndices() const { + return SubRegIndices; + } // Find a SubRegIndex form its Record def. CodeGenSubRegIndex *getSubRegIdx(Record*); @@ -547,7 +588,7 @@ namespace llvm { ConcatIdx.insert(std::make_pair(Parts, Idx)); } - const std::vector<CodeGenRegister*> &getRegisters() { return Registers; } + const std::deque<CodeGenRegister> &getRegisters() { return Registers; } const StringMap<CodeGenRegister*> &getRegistersByName() { return RegistersByName; } @@ -604,7 +645,9 @@ namespace llvm { RegUnit &getRegUnit(unsigned RUID) { return RegUnits[RUID]; } const RegUnit &getRegUnit(unsigned RUID) const { return RegUnits[RUID]; } - ArrayRef<CodeGenRegisterClass*> getRegClasses() const { + std::list<CodeGenRegisterClass> &getRegClasses() { return RegClasses; } + + const std::list<CodeGenRegisterClass> &getRegClasses() const { return RegClasses; } diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index 79d60ac171b8..bfdf8dcc89e0 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); } } } @@ -182,7 +181,7 @@ void CodeGenSchedModels::addProcModel(Record *ProcDef) { // Recursively find all reachable SchedReadWrite records. static void scanSchedRW(Record *RWDef, RecVec &RWDefs, SmallPtrSet<Record*, 16> &RWSet) { - if (!RWSet.insert(RWDef)) + if (!RWSet.insert(RWDef).second) return; RWDefs.push_back(RWDef); // Reads don't current have sequence records, but it can be added later. @@ -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<CodeGenProcModel>::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'; } } @@ -751,7 +746,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { for (ArrayRef<Record*>::const_iterator II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) { unsigned OldSCIdx = InstrClassMap[*II]; - if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx)) { + if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx).second) { for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(), RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) { if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) { @@ -781,9 +776,7 @@ bool CodeGenSchedModels::hasItineraries() const { // Gather the processor itineraries. void CodeGenSchedModels::collectProcItins() { - for (std::vector<CodeGenProcModel>::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/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index 3fef8adf91e5..e5241b9d5fda 100644 --- a/utils/TableGen/CodeGenSchedule.h +++ b/utils/TableGen/CodeGenSchedule.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_SCHEDULE_H -#define CODEGEN_SCHEDULE_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H +#define LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index d1b57118e0ee..e727a0e3f7ac 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -133,7 +133,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<Record*> Targets = Records.getAllDerivedDefinitions("Target"); if (Targets.size() == 0) PrintFatalError("ERROR: No 'Target' subclasses defined!"); @@ -143,9 +143,6 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records) } CodeGenTarget::~CodeGenTarget() { - DeleteContainerSeconds(Instructions); - delete RegBank; - delete SchedModels; } const std::string &CodeGenTarget::getName() const { @@ -153,11 +150,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 +208,7 @@ Record *CodeGenTarget::getAsmWriter() const { CodeGenRegBank &CodeGenTarget::getRegBank() const { if (!RegBank) - RegBank = new CodeGenRegBank(Records); + RegBank = llvm::make_unique<CodeGenRegBank>(Records); return *RegBank; } @@ -234,9 +231,7 @@ std::vector<MVT::SimpleValueType> CodeGenTarget:: getRegisterVTs(Record *R) const { const CodeGenRegister *Reg = getRegBank().getReg(R); std::vector<MVT::SimpleValueType> Result; - ArrayRef<CodeGenRegisterClass*> 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<MVT::SimpleValueType> InVTs = RC.getValueTypes(); Result.insert(Result.end(), InVTs.begin(), InVTs.end()); @@ -251,10 +246,8 @@ getRegisterVTs(Record *R) const { void CodeGenTarget::ReadLegalValueTypes() const { - ArrayRef<CodeGenRegisterClass*> 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 +258,7 @@ void CodeGenTarget::ReadLegalValueTypes() const { CodeGenSchedModels &CodeGenTarget::getSchedModels() const { if (!SchedModels) - SchedModels = new CodeGenSchedModels(Records, *this); + SchedModels = llvm::make_unique<CodeGenSchedModels>(Records, *this); return *SchedModels; } @@ -276,20 +269,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<CodeGenInstruction>(Insts[i]); } static const CodeGenInstruction * GetInstByName(const char *Name, - const DenseMap<const Record*, CodeGenInstruction*> &Insts, + const DenseMap<const Record*, + std::unique_ptr<CodeGenInstruction>> &Insts, RecordKeeper &Records) { const Record *Rec = Records.getDef(Name); - DenseMap<const Record*, CodeGenInstruction*>::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 @@ -301,8 +294,10 @@ void CodeGenTarget::ComputeInstrsByEnum() const { "GC_LABEL", "KILL", "EXTRACT_SUBREG", "INSERT_SUBREG", "IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE", "REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START", - "LIFETIME_END", "STACKMAP", "PATCHPOINT", nullptr}; - const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); + "LIFETIME_END", "STACKMAP", "PATCHPOINT", "LOAD_STACK_GUARD", + "STATEPOINT", "FRAME_ALLOC", + nullptr}; + 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"); @@ -311,9 +306,8 @@ void CodeGenTarget::ComputeInstrsByEnum() const { } unsigned EndOfPredefines = InstrsByEnum.size(); - for (DenseMap<const Record*, CodeGenInstruction*>::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); } @@ -343,9 +337,7 @@ void CodeGenTarget::reverseBitsForLittleEndianEncoding() { return; std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); - for (std::vector<Record*>::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; @@ -538,7 +530,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 54143103dc18..24b38514260c 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_TARGET_H -#define CODEGEN_TARGET_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENTARGET_H +#define LLVM_UTILS_TABLEGEN_CODEGENTARGET_H #include "CodeGenInstruction.h" #include "CodeGenRegisters.h" @@ -65,15 +65,16 @@ class CodeGenTarget { RecordKeeper &Records; Record *TargetRec; - mutable DenseMap<const Record*, CodeGenInstruction*> Instructions; - mutable CodeGenRegBank *RegBank; + mutable DenseMap<const Record*, + std::unique_ptr<CodeGenInstruction>> Instructions; + mutable std::unique_ptr<CodeGenRegBank> RegBank; mutable std::vector<Record*> RegAltNameIndices; mutable SmallVector<MVT::SimpleValueType, 8> LegalValueTypes; void ReadRegAltNameIndices() const; void ReadInstructions() const; void ReadLegalValueTypes() const; - mutable CodeGenSchedModels *SchedModels; + mutable std::unique_ptr<CodeGenSchedModels> SchedModels; mutable std::vector<const CodeGenInstruction*> InstrsByEnum; public: @@ -146,7 +147,8 @@ public: CodeGenSchedModels &getSchedModels() const; private: - DenseMap<const Record*, CodeGenInstruction*> &getInstructions() const { + DenseMap<const Record*, std::unique_ptr<CodeGenInstruction>> & + getInstructions() const { if (Instructions.empty()) ReadInstructions(); return Instructions; } @@ -154,8 +156,7 @@ public: CodeGenInstruction &getInstruction(const Record *InstRec) const { if (Instructions.empty()) ReadInstructions(); - DenseMap<const Record*, CodeGenInstruction*>::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 82682cd5a5ad..0fe3bbd8d788 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -94,8 +94,8 @@ struct PatternSortingPredicate { // Otherwise, if the patterns might both match, sort based on complexity, // which means that we prefer to match patterns that cover more nodes in the // input over nodes that cover fewer. - unsigned LHSSize = LHS->getPatternComplexity(CGP); - unsigned RHSSize = RHS->getPatternComplexity(CGP); + int LHSSize = LHS->getPatternComplexity(CGP); + int RHSSize = RHS->getPatternComplexity(CGP); if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost if (LHSSize < RHSSize) return false; @@ -157,12 +157,12 @@ void DAGISelEmitter::run(raw_ostream &OS) { } } - Matcher *TheMatcher = new ScopeMatcher(PatternMatchers); + std::unique_ptr<Matcher> TheMatcher = + llvm::make_unique<ScopeMatcher>(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 f8f6c546e11d..9df3b410ff26 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -1,4 +1,4 @@ -//===- DAGISelMatcher.h - Representation of DAG pattern matcher -----------===// +//===- DAGISelMatcher.h - Representation of DAG pattern matcher -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TBLGEN_DAGISELMATCHER_H -#define TBLGEN_DAGISELMATCHER_H +#ifndef LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H +#define LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.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> &Matcher, + const CodeGenDAGPatterns &CGP); void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP, raw_ostream &OS); diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 00595703839c..302f27bd0ecb 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -630,7 +630,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end(); I != E; ++I) - PFsByName[I->first->getName()] = I->second; + PFsByName[I->first->getName()] = I->second.get(); if (!NodePredicates.empty()) { OS << "bool CheckNodePredicate(SDNode *Node,\n"; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 97e37ba68952..eb806192bdc3 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<CodeGenRegisterClass*> 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; @@ -718,7 +716,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, CodeGenInstruction &II = CGT.getInstruction(Op); const DAGInstruction &Inst = CGP.getInstruction(Op); - // If we can, get the pattern for the instruction we're generating. We derive + // If we can, get the pattern for the instruction we're generating. We derive // a variety of information from this pattern, such as whether it has a chain. // // FIXME2: This is extremely dubious for several reasons, not the least of @@ -755,16 +753,21 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // the "outs" list. unsigned NumResults = Inst.getNumResults(); - // Loop over all of the operands of the instruction pattern, emitting code - // to fill them all in. The node 'N' usually has number children equal to - // the number of input operands of the instruction. However, in cases - // where there are predicate operands for an instruction, we need to fill - // in the 'execute always' values. Match up the node operands to the - // instruction operands to do this. + // Number of operands we know the output instruction must have. If it is + // variadic, we could have more operands. + unsigned NumFixedOperands = II.Operands.size(); + SmallVector<unsigned, 8> InstOps; - for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.Operands.size(); - InstOpNo != e; ++InstOpNo) { + // Loop over all of the fixed operands of the instruction pattern, emitting + // code to fill them all in. The node 'N' usually has number children equal to + // the number of input operands of the instruction. However, in cases where + // there are predicate operands for an instruction, we need to fill in the + // 'execute always' values. Match up the node operands to the instruction + // operands to do this. + unsigned ChildNo = 0; + for (unsigned InstOpNo = NumResults, e = NumFixedOperands; + InstOpNo != e; ++InstOpNo) { // Determine what to emit for this operand. Record *OperandNode = II.Operands[InstOpNo].Rec; if (OperandNode->isSubClassOf("OperandWithDefaultOps") && @@ -807,6 +810,16 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, } } + // If this is a variadic output instruction (i.e. REG_SEQUENCE), we can't + // expand suboperands, use default operands, or other features determined from + // the CodeGenInstruction after the fixed operands, which were handled + // above. Emit the remaining instructions implicitly added by the use for + // variable_ops. + if (II.Operands.isVariadic) { + for (unsigned I = ChildNo, E = N->getNumChildren(); I < E; ++I) + EmitResultOperand(N->getChild(I), InstOps); + } + // If this node has input glue or explicitly specified input physregs, we // need to add chained and glued copyfromreg nodes and materialize the glue // input. @@ -852,7 +865,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // gets the excess operands from the input DAG. int NumFixedArityOperands = -1; if (isRoot && - (Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))) + Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP)) NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren(); // If this is the root node and multiple matched nodes in the input pattern diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index da6a9577a770..c9ee371e3e2f 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -185,7 +185,7 @@ static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr, /// Conceptually, we'd like to sink these predicates all the way to the last /// matcher predicate in the series. However, it turns out that some /// ComplexPatterns have side effects on the graph, so we really don't want to -/// run a the complex pattern if the pattern predicate will fail. For this +/// run a complex pattern if the pattern predicate will fail. For this /// reason, we refuse to sink the pattern predicate past a ComplexPattern. /// static void SinkPatternPredicates(std::unique_ptr<Matcher> &MatcherPtr) { @@ -454,7 +454,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases; for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]); - assert(Opcodes.insert(COM->getOpcode().getEnumName()) && + assert(Opcodes.insert(COM->getOpcode().getEnumName()).second && "Duplicate opcodes not factored?"); Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext())); } @@ -511,11 +511,10 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { Scope->resetChild(i, NewOptionsToMatch[i]); } -Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher, - const CodeGenDAGPatterns &CGP) { - std::unique_ptr<Matcher> MatcherPtr(TheMatcher); +void +llvm::OptimizeMatcher(std::unique_ptr<Matcher> &MatcherPtr, + const CodeGenDAGPatterns &CGP) { ContractNodes(MatcherPtr, CGP); SinkPatternPredicates(MatcherPtr); FactorNodes(MatcherPtr); - return MatcherPtr.release(); } diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 154f96d3d023..748c92347783 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -19,6 +19,7 @@ #include "CodeGenDAGPatterns.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Error.h" @@ -36,6 +37,7 @@ struct InstructionMemo { const CodeGenRegisterClass *RC; std::string SubRegNo; std::vector<std::string>* PhysRegs; + std::string PredicateCheck; }; } // End anonymous namespace @@ -347,7 +349,7 @@ struct OperandsSignature { // Implicit physical register operand. e.g. Instruction::Mul expect to // select to a binary op. On x86, mul may take a single operand with // the other operand being implicit. We must emit something that looks - // like a binary instruction except for the very inner FastEmitInst_* + // like a binary instruction except for the very inner fastEmitInst_* // call. continue; Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes); @@ -364,7 +366,9 @@ struct OperandsSignature { namespace { class FastISelMap { - typedef std::map<std::string, InstructionMemo> PredMap; + // A multimap is needed instead of a "plain" map because the key is + // the instruction's complexity (an int) and they are not unique. + typedef std::multimap<int, InstructionMemo> PredMap; typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap; typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap; typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap; @@ -373,6 +377,16 @@ class FastISelMap { OperandsOpcodeTypeRetPredMap SimplePatterns; + // This is used to check that there are no duplicate predicates + typedef std::multimap<std::string, bool> PredCheckMap; + typedef std::map<MVT::SimpleValueType, PredCheckMap> RetPredCheckMap; + typedef std::map<MVT::SimpleValueType, RetPredCheckMap> TypeRetPredCheckMap; + typedef std::map<std::string, TypeRetPredCheckMap> OpcodeTypeRetPredCheckMap; + typedef std::map<OperandsSignature, OpcodeTypeRetPredCheckMap> + OperandsOpcodeTypeRetPredCheckMap; + + OperandsOpcodeTypeRetPredCheckMap SimplePatternsCheck; + std::map<OperandsSignature, std::vector<OperandsSignature> > SignaturesWithConstantForms; @@ -384,6 +398,11 @@ public: void collectPatterns(CodeGenDAGPatterns &CGP); void printImmediatePredicates(raw_ostream &OS); void printFunctionDefinitions(raw_ostream &OS); +private: + void emitInstructionCode(raw_ostream &OS, + const OperandsSignature &Operands, + const PredMap &PM, + const std::string &RetVTName); }; } // End anonymous namespace @@ -541,6 +560,17 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { continue; } + // Check if the operands match one of the patterns handled by FastISel. + std::string ManglingSuffix; + raw_string_ostream SuffixOS(ManglingSuffix); + Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true); + SuffixOS.flush(); + if (!StringSwitch<bool>(ManglingSuffix) + .Cases("", "r", "rr", "ri", "rf", true) + .Cases("rri", "i", "f", true) + .Default(false)) + continue; + // Get the predicate that guards this pattern. std::string PredicateCheck = Pattern.getPredicateCheck(); @@ -549,14 +579,24 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { Pattern.getDstPattern()->getOperator()->getName(), DstRC, SubRegNo, - PhysRegInputs + PhysRegInputs, + PredicateCheck }; + + int complexity = Pattern.getPatternComplexity(CGP); - if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck)) + if (SimplePatternsCheck[Operands][OpcodeName][VT] + [RetVT].count(PredicateCheck)) { PrintFatalError(Pattern.getSrcRecord()->getLoc(), - "Duplicate record in FastISel table!"); + "Duplicate predicate in FastISel table!"); + } + SimplePatternsCheck[Operands][OpcodeName][VT][RetVT].insert( + std::make_pair(PredicateCheck, true)); - SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo; + // Note: Instructions with the same complexity will appear in the order + // that they are encountered. + SimplePatterns[Operands][OpcodeName][VT][RetVT].insert( + std::make_pair(complexity, Memo)); // If any of the operands were immediates with predicates on them, strip // them down to a signature that doesn't have predicates so that we can @@ -582,6 +622,72 @@ void FastISelMap::printImmediatePredicates(raw_ostream &OS) { OS << "\n\n"; } +void FastISelMap::emitInstructionCode(raw_ostream &OS, + const OperandsSignature &Operands, + const PredMap &PM, + const std::string &RetVTName) { + // Emit code for each possible instruction. There may be + // multiple if there are subtarget concerns. A reverse iterator + // is used to produce the ones with highest complexity first. + + bool OneHadNoPredicate = false; + for (PredMap::const_reverse_iterator PI = PM.rbegin(), PE = PM.rend(); + PI != PE; ++PI) { + const InstructionMemo &Memo = PI->second; + std::string PredicateCheck = Memo.PredicateCheck; + + if (PredicateCheck.empty()) { + assert(!OneHadNoPredicate && + "Multiple instructions match and more than one had " + "no predicate!"); + OneHadNoPredicate = true; + } else { + if (OneHadNoPredicate) { + // FIXME: This should be a PrintError once the x86 target + // fixes PR21575. + PrintWarning("Multiple instructions match and one with no " + "predicate came before one with a predicate! " + "name:" + Memo.Name + " predicate: " + + PredicateCheck); + } + OS << " if (" + PredicateCheck + ") {\n"; + OS << " "; + } + + for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { + if ((*Memo.PhysRegs)[i] != "") + OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " + << "TII.get(TargetOpcode::COPY), " + << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; + } + + OS << " return fastEmitInst_"; + if (Memo.SubRegNo.empty()) { + Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, + ImmediatePredicates, true); + OS << "(" << InstNS << Memo.Name << ", "; + OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintArguments(OS, *Memo.PhysRegs); + OS << ");\n"; + } else { + OS << "extractsubreg(" << RetVTName + << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; + } + + if (!PredicateCheck.empty()) { + OS << " }\n"; + } + } + // Return 0 if all of the possibilities had predicates but none + // were satisfied. + if (!OneHadNoPredicate) + OS << " return 0;\n"; + OS << "}\n"; + OS << "\n"; +} + void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { // Now emit code for all the patterns that we collected. @@ -608,9 +714,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { RI != RE; ++RI) { MVT::SimpleValueType RetVT = RI->first; const PredMap &PM = RI->second; - bool HasPred = false; - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; @@ -619,58 +724,11 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { Operands.PrintParameters(OS); OS << ") {\n"; - // Emit code for each possible instruction. There may be - // multiple if there are subtarget concerns. - for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); - PI != PE; ++PI) { - std::string PredicateCheck = PI->first; - const InstructionMemo &Memo = PI->second; - - if (PredicateCheck.empty()) { - assert(!HasPred && - "Multiple instructions match, at least one has " - "a predicate and at least one doesn't!"); - } else { - OS << " if (" + PredicateCheck + ") {\n"; - OS << " "; - HasPred = true; - } - - for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { - if ((*Memo.PhysRegs)[i] != "") - OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " - << "TII.get(TargetOpcode::COPY), " - << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; - } - - OS << " return FastEmitInst_"; - if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, - ImmediatePredicates, true); - OS << "(" << InstNS << Memo.Name << ", "; - OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; - if (!Operands.empty()) - OS << ", "; - Operands.PrintArguments(OS, *Memo.PhysRegs); - OS << ");\n"; - } else { - OS << "extractsubreg(" << getName(RetVT); - OS << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; - } - - if (HasPred) - OS << " }\n"; - - } - // Return 0 if none of the predicates were satisfied. - if (HasPred) - OS << " return 0;\n"; - OS << "}\n"; - OS << "\n"; + emitInstructionCode(OS, Operands, PM, getName(RetVT)); } // Emit one function for the type that demultiplexes on return type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -682,7 +740,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end(); RI != RE; ++RI) { MVT::SimpleValueType RetVT = RI->first; - OS << " case " << getName(RetVT) << ": return FastEmit_" + OS << " case " << getName(RetVT) << ": return fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -694,7 +752,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { } else { // Non-variadic return type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -708,63 +766,13 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { << ")\n return 0;\n"; const PredMap &PM = RM.begin()->second; - bool HasPred = false; - - // Emit code for each possible instruction. There may be - // multiple if there are subtarget concerns. - for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); PI != PE; - ++PI) { - std::string PredicateCheck = PI->first; - const InstructionMemo &Memo = PI->second; - - if (PredicateCheck.empty()) { - assert(!HasPred && - "Multiple instructions match, at least one has " - "a predicate and at least one doesn't!"); - } else { - OS << " if (" + PredicateCheck + ") {\n"; - OS << " "; - HasPred = true; - } - - for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { - if ((*Memo.PhysRegs)[i] != "") - OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " - << "TII.get(TargetOpcode::COPY), " - << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; - } - - OS << " return FastEmitInst_"; - - if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, - ImmediatePredicates, true); - OS << "(" << InstNS << Memo.Name << ", "; - OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; - if (!Operands.empty()) - OS << ", "; - Operands.PrintArguments(OS, *Memo.PhysRegs); - OS << ");\n"; - } else { - OS << "extractsubreg(RetVT, Op0, Op0IsKill, "; - OS << Memo.SubRegNo; - OS << ");\n"; - } - - if (HasPred) - OS << " }\n"; - } - // Return 0 if none of the predicates were satisfied. - if (HasPred) - OS << " return 0;\n"; - OS << "}\n"; - OS << "\n"; + emitInstructionCode(OS, Operands, PM, "RetVT"); } } // Emit one function for the opcode that demultiplexes based on the type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT"; @@ -777,7 +785,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { TI != TE; ++TI) { MVT::SimpleValueType VT = TI->first; std::string TypeName = getName(VT); - OS << " case " << TypeName << ": return FastEmit_" + OS << " case " << TypeName << ": return fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(RetVT"; @@ -797,13 +805,16 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { // Emit one function for the operand signature that demultiplexes based // on opcode and type. - OS << "unsigned FastEmit_"; + OS << "unsigned fastEmit_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT, unsigned Opcode"; if (!Operands.empty()) OS << ", "; Operands.PrintParameters(OS); - OS << ") {\n"; + OS << ") "; + if (!Operands.hasAnyImmediateCodes()) + OS << "override "; + OS << "{\n"; // If there are any forms of this signature available that operate on // constrained forms of the immediate (e.g., 32-bit sext immediate in a @@ -823,7 +834,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { for (unsigned i = 0, e = MI->second.size(); i != e; ++i) { OS << " if ("; MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates); - OS << ")\n if (unsigned Reg = FastEmit_"; + OS << ")\n if (unsigned Reg = fastEmit_"; MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates); OS << "(VT, RetVT, Opcode"; if (!MI->second[i].empty()) @@ -841,7 +852,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { I != E; ++I) { const std::string &Opcode = I->first; - OS << " case " << Opcode << ": return FastEmit_" + OS << " case " << Opcode << ": return fastEmit_" << getLegalCName(Opcode) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(VT, RetVT"; diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index 42639cc4cf95..7c29422ec1b9 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -230,7 +230,7 @@ protected: std::vector<unsigned> VariableInstructions; // Map of well-known segment value to its delegate. - std::map<unsigned, const FilterChooser*> FilterChooserMap; + std::map<unsigned, std::unique_ptr<const FilterChooser>> FilterChooserMap; // Number of instructions which fall under FilteredInstructions category. unsigned NumFiltered; @@ -252,7 +252,7 @@ public: return *(FilterChooserMap.find((unsigned)-1)->second); } - Filter(const Filter &f); + Filter(Filter &&f); Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed); ~Filter(); @@ -333,13 +333,9 @@ protected: // Parent emitter const FixedLenDecoderEmitter *Emitter; + FilterChooser(const FilterChooser &) LLVM_DELETED_FUNCTION; + void operator=(const FilterChooser &) LLVM_DELETED_FUNCTION; public: - FilterChooser(const FilterChooser &FC) - : AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), - Operands(FC.Operands), Filters(FC.Filters), - FilterBitValues(FC.FilterBitValues), Parent(FC.Parent), - BestIndex(FC.BestIndex), BitWidth(FC.BitWidth), - Emitter(FC.Emitter) { } FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, const std::vector<unsigned> &IDs, @@ -347,10 +343,8 @@ public: unsigned BW, const FixedLenDecoderEmitter *E) : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), - Parent(nullptr), BestIndex(-1), BitWidth(BW), Emitter(E) { - for (unsigned i = 0; i < BitWidth; ++i) - FilterBitValues.push_back(BIT_UNFILTERED); - + FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1), + BitWidth(BW), Emitter(E) { doFilter(); } @@ -490,11 +484,11 @@ public: // // /////////////////////////// -Filter::Filter(const Filter &f) +Filter::Filter(Filter &&f) : Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), - FilteredInstructions(f.FilteredInstructions), - VariableInstructions(f.VariableInstructions), - FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered), + FilteredInstructions(std::move(f.FilteredInstructions)), + VariableInstructions(std::move(f.VariableInstructions)), + FilterChooserMap(std::move(f.FilterChooserMap)), NumFiltered(f.NumFiltered), LastOpcFiltered(f.LastOpcFiltered) { } @@ -534,12 +528,6 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, } Filter::~Filter() { - std::map<unsigned, const FilterChooser*>::iterator filterIterator; - for (filterIterator = FilterChooserMap.begin(); - filterIterator != FilterChooserMap.end(); - filterIterator++) { - delete filterIterator->second; - } } // Divides the decoding task into sub tasks and delegates them to the @@ -549,8 +537,6 @@ 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<uint64_t, std::vector<unsigned> >::const_iterator mapIterator; - // Starts by inheriting our parent filter chooser's filter bit values. std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues); @@ -561,14 +547,10 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // group of instructions whose segment values are variable. - FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>( - (unsigned)-1, - new FilterChooser(Owner->AllInstructions, - VariableInstructions, - Owner->Operands, - BitValueArray, - *Owner) - )); + FilterChooserMap.insert( + std::make_pair(-1U, llvm::make_unique<FilterChooser>( + Owner->AllInstructions, VariableInstructions, + Owner->Operands, BitValueArray, *Owner))); } // No need to recurse for a singleton filtered instruction. @@ -580,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; @@ -594,14 +574,10 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // category of instructions. - FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>( - mapIterator->first, - new FilterChooser(Owner->AllInstructions, - mapIterator->second, - Owner->Operands, - BitValueArray, - *Owner) - )); + FilterChooserMap.insert(std::make_pair( + Inst.first, llvm::make_unique<FilterChooser>( + Owner->AllInstructions, Inst.second, + Owner->Operands, BitValueArray, *Owner))); } } @@ -636,18 +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<unsigned, const FilterChooser*>::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 @@ -662,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. @@ -675,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 @@ -882,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 { @@ -911,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"; @@ -1066,19 +1036,17 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, const OperandInfo &OpInfo) const { const std::string &Decoder = OpInfo.Decoder; - if (OpInfo.numFields() == 1) { - OperandInfo::const_iterator OI = OpInfo.begin(); - o.indent(Indentation) << "tmp = fieldFromInstruction" - << "(insn, " << OI->Base << ", " << OI->Width - << ");\n"; - } else { + if (OpInfo.numFields() != 1) o.indent(Indentation) << "tmp = 0;\n"; - for (OperandInfo::const_iterator OI = OpInfo.begin(), OE = OpInfo.end(); - OI != OE; ++OI) { - o.indent(Indentation) << "tmp |= (fieldFromInstruction" - << "(insn, " << OI->Base << ", " << OI->Width - << ") << " << OI->Offset << ");\n"; - } + + for (const EncodingField &EF : OpInfo) { + o.indent(Indentation) << "tmp "; + if (OpInfo.numFields() != 1) o << '|'; + o << "= fieldFromInstruction" + << "(insn, " << EF.Base << ", " << EF.Width << ')'; + if (OpInfo.numFields() != 1 || EF.Offset != 0) + o << " << " << EF.Offset; + o << ";\n"; } if (Decoder != "") @@ -1092,20 +1060,16 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc) const { - std::map<unsigned, std::vector<OperandInfo> >::const_iterator OpIter = - Operands.find(Opc); - const std::vector<OperandInfo>& InsnOperands = OpIter->second; - for (std::vector<OperandInfo>::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); } } @@ -1384,8 +1348,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit, bool mixed) { Filters.clear(); - Filter F(*this, startBit, numBit, true); - Filters.push_back(F); + Filters.push_back(Filter(*this, startBit, numBit, true)); BestIndex = 0; // Sole Filter instance to choose from. bestFilter().recurse(); } @@ -1886,20 +1849,20 @@ static bool populateInstruction(CodeGenTarget &Target, } // For each operand, see if we can figure out where it is encoded. - for (std::vector<std::pair<Init*, std::string> >::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(); } @@ -1907,7 +1870,7 @@ static bool populateInstruction(CodeGenTarget &Target, std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(tiedTo); - InsnOperands.push_back(NumberedInsnOperands[TiedNames[NI->second]] + InsnOperands.push_back(NumberedInsnOperands[TiedNames[Op.second]] [SO.second]); } } @@ -1921,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<TypedInit>(NI->first); + TypedInit *TI = cast<TypedInit>(Op.first); RecordRecTy *Type = cast<RecordRecTy>(TI->getType()); Record *TypeRecord = Type->getRecord(); bool isReg = false; @@ -1965,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; @@ -2203,12 +2166,10 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { } DecoderTableInfo TableInfo; - for (std::map<std::pair<std::string, unsigned>, - std::vector<unsigned> >::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 @@ -2229,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 76f05cea3f7e..fe30d60fd4ce 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -143,7 +143,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { Res += "|(1<<MCOI::OptionalDef)"; // Fill in operand type. - Res += ", MCOI::"; + Res += ", "; assert(!Op.OperandType.empty() && "Invalid operand type."); Res += Op.OperandType; @@ -266,6 +266,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << "#undef GET_INSTRINFO_NAMED_OPS\n"; OS << "namespace llvm {"; OS << "namespace " << Namespace << " {\n"; + OS << "LLVM_READONLY\n"; OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n"; if (!Operands.empty()) { OS << " static const int16_t OperandMap [][" << Operands.size() @@ -504,6 +505,9 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)"; if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<MCID::ExtraSrcRegAllocReq)"; if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<MCID::ExtraDefRegAllocReq)"; + if (Inst.isRegSequence) OS << "|(1<<MCID::RegSequence)"; + if (Inst.isExtractSubreg) OS << "|(1<<MCID::ExtractSubreg)"; + if (Inst.isInsertSubreg) OS << "|(1<<MCID::InsertSubreg)"; // Emit all of the target-specific flags... BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); @@ -583,14 +587,16 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) { for (const CodeGenInstruction *Inst : NumberedInstructions) OS << " " << Inst->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 34358c41a742..c0cf92d76187 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -244,19 +244,22 @@ enum IIT_Info { IIT_ARG = 15, // Values from 16+ are only encodable with the inefficient encoding. - IIT_MMX = 16, - IIT_METADATA = 17, - IIT_EMPTYSTRUCT = 18, - IIT_STRUCT2 = 19, - IIT_STRUCT3 = 20, - IIT_STRUCT4 = 21, - IIT_STRUCT5 = 22, - IIT_EXTEND_ARG = 23, - IIT_TRUNC_ARG = 24, - IIT_ANYPTR = 25, - IIT_V1 = 26, - IIT_VARARG = 27, - IIT_HALF_VEC_ARG = 28 + IIT_V64 = 16, + IIT_MMX = 17, + IIT_METADATA = 18, + IIT_EMPTYSTRUCT = 19, + IIT_STRUCT2 = 20, + IIT_STRUCT3 = 21, + IIT_STRUCT4 = 22, + IIT_STRUCT5 = 23, + IIT_EXTEND_ARG = 24, + IIT_TRUNC_ARG = 25, + IIT_ANYPTR = 26, + IIT_V1 = 27, + IIT_VARARG = 28, + IIT_HALF_VEC_ARG = 29, + IIT_SAME_VEC_WIDTH_ARG = 30, + IIT_PTR_TO_ARG = 31 }; @@ -304,6 +307,16 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &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 << 2) | 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 Sig.push_back(IIT_ARG); return Sig.push_back((Number << 2) | ArgCodes[Number]); @@ -356,6 +369,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, case 8: Sig.push_back(IIT_V8); break; case 16: Sig.push_back(IIT_V16); break; case 32: Sig.push_back(IIT_V32); break; + case 64: Sig.push_back(IIT_V64); break; } return EncodeFixedValueType(VVT.getVectorElementType().SimpleTy, Sig); @@ -680,8 +694,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << " }\n"; OS << " }\n"; - OS << " return AttributeSet::get(C, ArrayRef<AttributeSet>(AS, " - "NumAttrs));\n"; + OS << " return AttributeSet::get(C, makeArrayRef(AS, NumAttrs));\n"; OS << "}\n"; OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; } diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index 3b74ac41e9b3..ebb43f065262 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -277,11 +277,10 @@ void PseudoLoweringEmitter::run(raw_ostream &o) { assert(InstructionClass && "Instruction class definition missing!"); std::vector<Record*> Insts; - for (std::map<std::string, Record*>::const_iterator I = - Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) { - if (I->second->isSubClassOf(ExpansionClass) && - I->second->isSubClassOf(InstructionClass)) - Insts.push_back(I->second); + for (const auto &D : Records.getDefs()) { + if (D.second->isSubClassOf(ExpansionClass) && + D.second->isSubClassOf(InstructionClass)) + Insts.push_back(D.second.get()); } // Process the pseudo expansion definitions, validating them as we do so. diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 573c37f4eef4..1c3de4a2c2b8 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<CodeGenRegister*> &Regs, bool isCtor); + void EmitRegMapping(raw_ostream &o, const std::deque<CodeGenRegister> &Regs, + bool isCtor); void EmitRegMappingTables(raw_ostream &o, - const std::vector<CodeGenRegister*> &Regs, + const std::deque<CodeGenRegister> &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<CodeGenRegister*> &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<CodeGenRegisterClass*> 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<CodeGenSubRegIndex*> 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,8 +179,7 @@ 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]; + for (const auto &RC : RegBank.getRegClasses()) { const CodeGenRegister::Set &Regs = RC.getMembers(); if (Regs.empty()) OS << " {0, 0"; @@ -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<std::vector<int>> 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<unsigned> RCSetStarts(NumRCUnitSets); - for (unsigned i = 0, StartIdx = 0, e = NumRCUnitSets; i != e; ++i) { - RCSetStarts[i] = StartIdx; + std::vector<std::vector<int>> PSets(NumRCUnitSets); + + for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) { ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(i); - std::vector<unsigned> PSets; - PSets.reserve(PSetIDs.size()); + PSets[i].reserve(PSetIDs.size()); for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(), PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { - PSets.push_back(RegBank.getRegPressureSet(*PSetI).Order); + PSets[i].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; - } - OS << "-1, \t// #" << RCSetStarts[i] << " "; - if (i < NumRCs) - OS << RegBank.getRegClasses()[i]->getName(); - else { - OS << "inferred"; - for (ArrayRef<unsigned>::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<CodeGenRegister*> &Regs, - bool isCtor) { +void RegisterInfoEmitter::EmitRegMappingTables( + raw_ostream &OS, const std::deque<CodeGenRegister> &Regs, bool isCtor) { // Collect all information about dwarf register numbers typedef std::map<Record*, std::vector<int64_t>, 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<int64_t> 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"; @@ -379,16 +384,16 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, OS << "extern const unsigned " << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize"; if (!isCtor) - OS << " = sizeof(" << Namespace + OS << " = array_lengthof(" << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + << "Dwarf2L);\n\n"; else OS << ";\n\n"; } } - 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; @@ -427,24 +432,21 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, OS << "extern const unsigned " << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize"; if (!isCtor) - OS << " = sizeof(" << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "L2Dwarf)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + OS << " = array_lengthof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2Dwarf);\n\n"; else OS << ";\n\n"; } } } -void -RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, - const std::vector<CodeGenRegister*> &Regs, - bool isCtor) { +void RegisterInfoEmitter::EmitRegMapping( + raw_ostream &OS, const std::deque<CodeGenRegister> &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()); } @@ -452,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) { @@ -566,6 +568,7 @@ static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) { // 0 differential which means we can't encode repeated elements. typedef SmallVector<uint16_t, 4> DiffVec; +typedef SmallVector<unsigned, 4> 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. @@ -598,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, @@ -617,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<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); + const auto &SubRegIndices = RegBank.getSubRegIndices(); OS << "unsigned " << ClName << "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n"; @@ -645,10 +643,12 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, SmallVector<unsigned, 4> RowMap; SmallVector<SmallVector<CodeGenSubRegIndex*, 4>, 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; } @@ -656,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 @@ -685,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 @@ -694,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<unsigned, 4> SubReg2SequenceIndexMap; + SmallVector<SmallVector<MaskRolPair, 1>, 4> Sequences; + for (const auto &Idx : SubRegIndices) { + const SmallVector<MaskRolPair, 1> &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<MaskRolPair> &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<MaskRolPair> &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. // @@ -705,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<CodeGenRegister*> &Regs = RegBank.getRegisters(); + const auto &Regs = RegBank.getRegisters(); - ArrayRef<CodeGenSubRegIndex*> 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<const CodeGenRegister*> RegVec; @@ -719,6 +808,10 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, SmallVector<DiffVec, 4> RegUnitLists(Regs.size()); SmallVector<unsigned, 4> RegUnitInitScale(Regs.size()); + // List of lane masks accompanying register unit sequences. + SequenceToOffsetTable<MaskVec> LaneMaskSeqs; + SmallVector<MaskVec, 4> RegUnitLaneMasks(Regs.size()); + // Keep track of sub-register names as well. These are not differentially // encoded. typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec; @@ -728,27 +821,27 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, SequenceToOffsetTable<std::string> 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<const CodeGenRegister*> 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. @@ -763,22 +856,36 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // // Check the neighboring registers for arithmetic progressions. unsigned ScaleA = ~0u, ScaleB = ~0u; - ArrayRef<unsigned> 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(); + ArrayRef<unsigned> RUs = Reg.getNativeRegUnits(); + if (I != Regs.begin() && + std::prev(I)->getNativeRegUnits().size() == RUs.size()) + ScaleB = RUs.front() - std::prev(I)->getNativeRegUnits().front(); + if (std::next(I) != Regs.end() && + std::next(I)->getNativeRegUnits().size() == RUs.size()) + ScaleA = std::next(I)->getNativeRegUnits().front() - RUs.front(); 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"; @@ -790,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); @@ -799,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<CodeGenSubRegIndex*>::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"; @@ -816,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... @@ -843,19 +953,22 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "};\n\n"; - ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); + const auto &RegisterClasses = RegBank.getRegClasses(); // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; + SequenceToOffsetTable<std::string> 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<Record*> Order = RC.getOrder(); // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); + RegClassStrings.add(Name); + // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " const MCPhysReg " << Name @@ -880,20 +993,23 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "}\n\n"; + RegClassStrings.layout(); + OS << "extern const char " << TargetName << "RegClassStrings[] = {\n"; + RegClassStrings.emit(OS, printChar); + OS << "};\n\n"; + 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."); assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); - OS << " { " << '\"' << RC.getName() << "\", " - << RC.getName() << ", " << RC.getName() << "Bits, " + OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, " + << RegClassStrings.get(RC.getName()) << ", " << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " @@ -911,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) { @@ -926,24 +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 << "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"; } @@ -970,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"; } @@ -985,14 +1102,13 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, << "unsigned RegUnit) const override;\n" << "};\n\n"; - ArrayRef<CodeGenRegisterClass*> 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. @@ -1000,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"; } @@ -1022,15 +1138,14 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << "MCRegisterClasses[];\n"; // Start out by emitting each of the register classes. - ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); - ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); + const auto &RegisterClasses = RegBank.getRegClasses(); + const auto &SubRegIndices = RegBank.getSubRegIndices(); // Collect all registers belonging to any allocatable class. std::set<Record*> 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<Record*> Order = RC.getOrder(); if (RC.Allocatable) @@ -1039,8 +1154,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Build a shared array of value types. SequenceToOffsetTable<SmallVector<MVT::SimpleValueType, 4> > 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"); @@ -1048,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"; @@ -1094,24 +1208,22 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, SequenceToOffsetTable<IdxList, CodeGenSubRegIndex::Less> 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"; @@ -1123,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<CodeGenRegisterClass*> Supers = RC.getSuperClasses(); // Skip classes without supers. We can reuse NullRegClasses. @@ -1133,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) {" @@ -1168,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 @@ -1200,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... @@ -1212,9 +1320,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n"; OS << " { 0, 0 },\n"; - const std::vector<CodeGenRegister*> &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"; @@ -1224,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()) { @@ -1240,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"; } @@ -1266,7 +1376,9 @@ 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"; OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; OS << "extern const MCRegisterInfo::SubRegCoveredBits " @@ -1282,15 +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"; @@ -1334,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 e6ab66426fb1..66506ea0638f 100644 --- a/utils/TableGen/SequenceToOffsetTable.h +++ b/utils/TableGen/SequenceToOffsetTable.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H -#define TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H +#ifndef LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H +#define LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -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 a59eead6d0df..9f2fc929d96a 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -386,7 +386,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS, for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), PE = SchedModels.procModelEnd(); PI != PE; ++PI) { - if (!ItinsDefSet.insert(PI->ItinsDef)) + if (!ItinsDefSet.insert(PI->ItinsDef).second) continue; std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU"); @@ -565,7 +565,7 @@ EmitItineraries(raw_ostream &OS, PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) { Record *ItinsDef = PI->ItinsDef; - if (!ItinsDefSet.insert(ItinsDef)) + if (!ItinsDefSet.insert(ItinsDef).second) continue; // Get processor itinerary name @@ -575,12 +575,13 @@ EmitItineraries(raw_ostream &OS, assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator"); std::vector<InstrItinerary> &ItinList = *ProcItinListsIter; + // Empty itineraries aren't referenced anywhere in the tablegen output + // so don't emit them. + if (ItinList.empty()) + continue; + OS << "\n"; OS << "static const llvm::InstrItinerary "; - if (ItinList.empty()) { - OS << '*' << Name << " = nullptr;\n"; - continue; - } // Begin processor itinerary table OS << Name << "[] = {\n"; @@ -1192,7 +1193,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { // Begin processor itinerary properties OS << "\n"; - OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n"; + OS << "static const llvm::MCSchedModel " << PI->ModelName << " = {\n"; EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ','); EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ','); EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ','); @@ -1217,10 +1218,10 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { - SchedModels.schedClassBegin()) << ",\n"; else OS << " 0, 0, 0, 0, // No instruction-level machine model.\n"; - if (SchedModels.hasItineraries()) - OS << " " << PI->ItinsDef->getName() << ");\n"; + if (PI->hasItineraries()) + OS << " " << PI->ItinsDef->getName() << "};\n"; else - OS << " 0); // No Itinerary\n"; + OS << " nullptr}; // No Itinerary\n"; } } diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index bbd61f5fb112..02fe4dc98bea 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<Record*> 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<Record*> Recs = Records.getAllDerivedDefinitions("Set"); - for (unsigned i = 0, e = Recs.size(); i != e; ++i) { - OS << Recs[i]->getName() << " = ["; - const std::vector<Record*> *Elts = Sets.expand(Recs[i]); + for (Record *Rec : Records.getAllDerivedDefinitions("Set")) { + OS << Rec->getName() << " = ["; + const std::vector<Record*> *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/TableGenBackends.h b/utils/TableGen/TableGenBackends.h index 28b626e17e89..2dc03ce1e71e 100644 --- a/utils/TableGen/TableGenBackends.h +++ b/utils/TableGen/TableGenBackends.h @@ -13,6 +13,8 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H +#define LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H // A TableGen backend is a function that looks like // @@ -78,3 +80,5 @@ void EmitOptParser(RecordKeeper &RK, raw_ostream &OS); void EmitCTags(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace + +#endif diff --git a/utils/TableGen/X86DisassemblerShared.h b/utils/TableGen/X86DisassemblerShared.h index 9e79b9c553a7..58952776b756 100644 --- a/utils/TableGen/X86DisassemblerShared.h +++ b/utils/TableGen/X86DisassemblerShared.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86DISASSEMBLERSHARED_H -#define X86DISASSEMBLERSHARED_H +#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H +#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H #include <string.h> #include <string> diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index fbcc6f228ca0..fbe5502bc90e 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)) || @@ -171,12 +181,17 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_OPSIZE: return inheritsFrom(child, IC_EVEX_W_OPSIZE) || inheritsFrom(child, IC_EVEX_L_W_OPSIZE); + case IC_EVEX_B: + return false; case IC_EVEX_W: case IC_EVEX_W_XS: case IC_EVEX_W_XD: case IC_EVEX_W_OPSIZE: return false; case IC_EVEX_L: + case IC_EVEX_L_K_B: + case IC_EVEX_L_KZ_B: + case IC_EVEX_L_B: case IC_EVEX_L_XS: case IC_EVEX_L_XD: case IC_EVEX_L_OPSIZE: @@ -205,38 +220,59 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_XD_K: return inheritsFrom(child, IC_EVEX_W_XD_K) || inheritsFrom(child, IC_EVEX_L_W_XD_K); + case IC_EVEX_K_B: + case IC_EVEX_KZ: + return false; + case IC_EVEX_XS_KZ: + return inheritsFrom(child, IC_EVEX_W_XS_KZ) || + inheritsFrom(child, IC_EVEX_L_W_XS_KZ); + case IC_EVEX_XD_KZ: + return inheritsFrom(child, IC_EVEX_W_XD_KZ) || + inheritsFrom(child, IC_EVEX_L_W_XD_KZ); + case IC_EVEX_KZ_B: case IC_EVEX_OPSIZE_K: case IC_EVEX_OPSIZE_B: + case IC_EVEX_OPSIZE_K_B: + case IC_EVEX_OPSIZE_KZ: + case IC_EVEX_OPSIZE_KZ_B: return false; case IC_EVEX_W_K: case IC_EVEX_W_XS_K: case IC_EVEX_W_XD_K: case IC_EVEX_W_OPSIZE_K: case IC_EVEX_W_OPSIZE_B: + case IC_EVEX_W_OPSIZE_K_B: return false; case IC_EVEX_L_K: case IC_EVEX_L_XS_K: case IC_EVEX_L_XD_K: case IC_EVEX_L_OPSIZE_K: + case IC_EVEX_L_OPSIZE_B: + case IC_EVEX_L_OPSIZE_K_B: return false; case IC_EVEX_W_KZ: case IC_EVEX_W_XS_KZ: case IC_EVEX_W_XD_KZ: case IC_EVEX_W_OPSIZE_KZ: + case IC_EVEX_W_OPSIZE_KZ_B: return false; case IC_EVEX_L_KZ: case IC_EVEX_L_XS_KZ: case IC_EVEX_L_XD_KZ: case IC_EVEX_L_OPSIZE_KZ: + case IC_EVEX_L_OPSIZE_KZ_B: return false; case IC_EVEX_L_W_K: case IC_EVEX_L_W_XS_K: case IC_EVEX_L_W_XD_K: case IC_EVEX_L_W_OPSIZE_K: + case IC_EVEX_L_W_OPSIZE_B: + case IC_EVEX_L_W_OPSIZE_K_B: case IC_EVEX_L_W_KZ: case IC_EVEX_L_W_XS_KZ: case IC_EVEX_L_W_XD_KZ: case IC_EVEX_L_W_OPSIZE_KZ: + case IC_EVEX_L_W_OPSIZE_KZ_B: return false; case IC_EVEX_L2_K: case IC_EVEX_L2_B: @@ -687,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)) @@ -695,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)) @@ -711,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) @@ -796,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" || @@ -836,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 1327375f7957..5a8688be0819 100644 --- a/utils/TableGen/X86DisassemblerTables.h +++ b/utils/TableGen/X86DisassemblerTables.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86DISASSEMBLERTABLES_H -#define X86DISASSEMBLERTABLES_H +#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H +#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H #include "X86DisassemblerShared.h" #include "X86ModRMFilters.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/X86ModRMFilters.h b/utils/TableGen/X86ModRMFilters.h index fac38389eadd..d919c588c644 100644 --- a/utils/TableGen/X86ModRMFilters.h +++ b/utils/TableGen/X86ModRMFilters.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86MODRMFILTERS_H -#define X86MODRMFILTERS_H +#ifndef LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H +#define LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H #include "llvm/Support/DataTypes.h" diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index b7bd822d31d6..198ad1090493 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -32,48 +32,50 @@ using namespace llvm; MAP(C9, 38) \ MAP(CA, 39) \ MAP(CB, 40) \ - MAP(D0, 41) \ - MAP(D1, 42) \ - MAP(D4, 43) \ - MAP(D5, 44) \ - MAP(D6, 45) \ - MAP(D8, 46) \ - MAP(D9, 47) \ - MAP(DA, 48) \ - MAP(DB, 49) \ - MAP(DC, 50) \ - MAP(DD, 51) \ - MAP(DE, 52) \ - MAP(DF, 53) \ - MAP(E0, 54) \ - MAP(E1, 55) \ - MAP(E2, 56) \ - MAP(E3, 57) \ - MAP(E4, 58) \ - MAP(E5, 59) \ - MAP(E8, 60) \ - MAP(E9, 61) \ - MAP(EA, 62) \ - MAP(EB, 63) \ - MAP(EC, 64) \ - MAP(ED, 65) \ - MAP(EE, 66) \ - MAP(F0, 67) \ - MAP(F1, 68) \ - MAP(F2, 69) \ - MAP(F3, 70) \ - MAP(F4, 71) \ - MAP(F5, 72) \ - MAP(F6, 73) \ - MAP(F7, 74) \ - MAP(F8, 75) \ - MAP(F9, 76) \ - MAP(FA, 77) \ - MAP(FB, 78) \ - MAP(FC, 79) \ - MAP(FD, 80) \ - MAP(FE, 81) \ - MAP(FF, 82) + 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) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { @@ -117,6 +119,10 @@ namespace X86Local { enum { OpSize16 = 1, OpSize32 = 2 }; + + enum { + AdSize16 = 1, AdSize32 = 2, AdSize64 = 3 + }; } using namespace X86Disassembler; @@ -192,7 +198,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"); @@ -399,16 +405,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; @@ -427,9 +437,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; @@ -539,6 +551,14 @@ void RecognizableInstr::emitInstructionSpecifier() { // physicalOperandIndex should always be < numPhysicalOperands unsigned physicalOperandIndex = 0; + // Given the set of prefix bits, how many additional operands does the + // instruction have? + unsigned additionalOperands = 0; + if (HasVEX_4V || HasVEX_4VOp3) + ++additionalOperands; + if (HasEVEX_K) + ++additionalOperands; + switch (Form) { default: llvm_unreachable("Unhandled form"); case X86Local::RawFrmSrc: @@ -573,17 +593,17 @@ void RecognizableInstr::emitInstructionSpecifier() { break; case X86Local::MRMDestReg: // Operand 1 is a register operand in the R/M field. + // - In AVX512 there may be a mask operand here - // Operand 2 is a register operand in the Reg/Opcode field. // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMDestRegFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMDestRegFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMDestRegFrm"); HANDLE_OPERAND(rmRegister) + if (HasEVEX_K) + HANDLE_OPERAND(writemaskRegister) if (HasVEX_4V) // FIXME: In AVX, the register below becomes the one encoded @@ -598,12 +618,10 @@ void RecognizableInstr::emitInstructionSpecifier() { // Operand 2 is a register operand in the Reg/Opcode field. // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMDestMemFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMDestMemFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMDestMemFrm with VEX_4V"); + HANDLE_OPERAND(memory) if (HasEVEX_K) @@ -624,12 +642,9 @@ void RecognizableInstr::emitInstructionSpecifier() { // Operand 3 (optional) is an immediate. // Operand 4 (optional) is an immediate. - if (HasVEX_4V || HasVEX_4VOp3) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && - "Unexpected number of operands for MRMSrcRegFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMSrcRegFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 4 + additionalOperands && + "Unexpected number of operands for MRMSrcRegFrm"); HANDLE_OPERAND(roRegister) @@ -660,12 +675,9 @@ void RecognizableInstr::emitInstructionSpecifier() { // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V || HasVEX_4VOp3) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && - "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMSrcMemFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 4 + additionalOperands && + "Unexpected number of operands for MRMSrcMemFrm"); HANDLE_OPERAND(roRegister) @@ -698,15 +710,13 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM5r: case X86Local::MRM6r: case X86Local::MRM7r: - { - // Operand 1 is a register operand in the R/M field. - // Operand 2 (optional) is an immediate or relocation. - // Operand 3 (optional) is an immediate. - unsigned kOp = (HasEVEX_K) ? 1:0; - unsigned Op4v = (HasVEX_4V) ? 1:0; - if (numPhysicalOperands > 3 + kOp + Op4v) - llvm_unreachable("Unexpected number of operands for MRMnr"); - } + // Operand 1 is a register operand in the R/M field. + // Operand 2 (optional) is an immediate or relocation. + // Operand 3 (optional) is an immediate. + assert(numPhysicalOperands >= 0 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMnr"); + if (HasVEX_4V) HANDLE_OPERAND(vvvvRegister) @@ -725,15 +735,12 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM5m: case X86Local::MRM6m: case X86Local::MRM7m: - { - // Operand 1 is a memory operand (possibly SIB-extended) - // Operand 2 (optional) is an immediate or relocation. - unsigned kOp = (HasEVEX_K) ? 1:0; - unsigned Op4v = (HasVEX_4V) ? 1:0; - if (numPhysicalOperands < 1 + kOp + Op4v || - numPhysicalOperands > 2 + kOp + Op4v) - llvm_unreachable("Unexpected number of operands for MRMnm"); - } + // Operand 1 is a memory operand (possibly SIB-extended) + // Operand 2 (optional) is an immediate or relocation. + assert(numPhysicalOperands >= 1 + additionalOperands && + numPhysicalOperands <= 2 + additionalOperands && + "Unexpected number of operands for MRMnm"); + if (HasVEX_4V) HANDLE_OPERAND(vvvvRegister) if (HasEVEX_K) @@ -769,20 +776,21 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM_C0: case X86Local::MRM_C1: case X86Local::MRM_C2: case X86Local::MRM_C3: case X86Local::MRM_C4: case X86Local::MRM_C8: case X86Local::MRM_C9: case X86Local::MRM_CA: case X86Local::MRM_CB: - case X86Local::MRM_D0: case X86Local::MRM_D1: case X86Local::MRM_D4: - case X86Local::MRM_D5: case X86Local::MRM_D6: case X86Local::MRM_D8: - case X86Local::MRM_D9: case X86Local::MRM_DA: case X86Local::MRM_DB: - case X86Local::MRM_DC: case X86Local::MRM_DD: case X86Local::MRM_DE: - case X86Local::MRM_DF: case X86Local::MRM_E0: case X86Local::MRM_E1: - case X86Local::MRM_E2: case X86Local::MRM_E3: case X86Local::MRM_E4: - case X86Local::MRM_E5: case X86Local::MRM_E8: case X86Local::MRM_E9: - case X86Local::MRM_EA: case X86Local::MRM_EB: case X86Local::MRM_EC: - case X86Local::MRM_ED: case X86Local::MRM_EE: case X86Local::MRM_F0: - case X86Local::MRM_F1: case X86Local::MRM_F2: case X86Local::MRM_F3: - case X86Local::MRM_F4: case X86Local::MRM_F5: case X86Local::MRM_F6: - case X86Local::MRM_F7: case X86Local::MRM_F9: case X86Local::MRM_FA: - case X86Local::MRM_FB: case X86Local::MRM_FC: case X86Local::MRM_FD: - case X86Local::MRM_FE: case X86Local::MRM_FF: + case X86Local::MRM_CF: case X86Local::MRM_D0: case X86Local::MRM_D1: + case X86Local::MRM_D4: case X86Local::MRM_D5: case X86Local::MRM_D6: + case X86Local::MRM_D7: case X86Local::MRM_D8: case X86Local::MRM_D9: + case X86Local::MRM_DA: case X86Local::MRM_DB: case X86Local::MRM_DC: + case X86Local::MRM_DD: case X86Local::MRM_DE: case X86Local::MRM_DF: + case X86Local::MRM_E0: case X86Local::MRM_E1: case X86Local::MRM_E2: + case X86Local::MRM_E3: case X86Local::MRM_E4: case X86Local::MRM_E5: + case X86Local::MRM_E8: case X86Local::MRM_E9: case X86Local::MRM_EA: + case X86Local::MRM_EB: case X86Local::MRM_EC: case X86Local::MRM_ED: + case X86Local::MRM_EE: case X86Local::MRM_F0: case X86Local::MRM_F1: + case X86Local::MRM_F2: case X86Local::MRM_F3: case X86Local::MRM_F4: + case X86Local::MRM_F5: case X86Local::MRM_F6: case X86Local::MRM_F7: + case X86Local::MRM_F9: case X86Local::MRM_FA: case X86Local::MRM_FB: + case X86Local::MRM_FC: case X86Local::MRM_FD: case X86Local::MRM_FE: + case X86Local::MRM_FF: // Ignored. break; } @@ -852,6 +860,13 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { 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"); @@ -869,13 +884,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; @@ -909,7 +924,6 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i32mem", TYPE_Mv) TYPE("i32imm", TYPE_IMMv) TYPE("i32i8imm", TYPE_IMM32) - TYPE("u32u8imm", TYPE_IMM32) TYPE("GR32", TYPE_R32) TYPE("GR32orGR64", TYPE_R32) TYPE("i64mem", TYPE_Mv) @@ -942,15 +956,15 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("SSECC", TYPE_IMM3) TYPE("AVXCC", TYPE_IMM5) 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) @@ -966,10 +980,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) @@ -1012,7 +1033,6 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, ENCODING("i16imm", ENCODING_IW) } ENCODING("i32i8imm", ENCODING_IB) - ENCODING("u32u8imm", ENCODING_IB) ENCODING("SSECC", ENCODING_IB) ENCODING("AVXCC", ENCODING_IB) ENCODING("AVX512RC", ENCODING_IB) @@ -1059,6 +1079,8 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s, ENCODING("VK1", ENCODING_RM) ENCODING("VK8", ENCODING_RM) ENCODING("VK16", ENCODING_RM) + ENCODING("VK32", ENCODING_RM) + ENCODING("VK64", ENCODING_RM) errs() << "Unhandled R/M register encoding " << s << "\n"; llvm_unreachable("Unhandled R/M register encoding"); } @@ -1085,8 +1107,12 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s, ENCODING("FR32X", ENCODING_REG) ENCODING("VR512", ENCODING_REG) ENCODING("VK1", ENCODING_REG) + ENCODING("VK2", ENCODING_REG) + ENCODING("VK4", ENCODING_REG) ENCODING("VK8", ENCODING_REG) ENCODING("VK16", ENCODING_REG) + ENCODING("VK32", ENCODING_REG) + ENCODING("VK64", ENCODING_REG) ENCODING("VK1WM", ENCODING_REG) ENCODING("VK8WM", ENCODING_REG) ENCODING("VK16WM", ENCODING_REG) @@ -1113,6 +1139,8 @@ RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s, ENCODING("VK4", ENCODING_VVVV) ENCODING("VK8", ENCODING_VVVV) ENCODING("VK16", ENCODING_VVVV) + ENCODING("VK32", ENCODING_VVVV) + ENCODING("VK64", ENCODING_VVVV) errs() << "Unhandled VEX.vvvv register encoding " << s << "\n"; llvm_unreachable("Unhandled VEX.vvvv register encoding"); } @@ -1149,9 +1177,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) @@ -1185,13 +1213,21 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s, 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 4bc52ebd849e..28e10535508d 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86RECOGNIZABLEINSTR_H -#define X86RECOGNIZABLEINSTR_H +#ifndef LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H +#define LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H #include "CodeGenTarget.h" #include "X86DisassemblerTables.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 |