diff options
Diffstat (limited to 'contrib/llvm/utils')
26 files changed, 1741 insertions, 950 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp index 0d7c5ffbea1c..4177388840be 100644 --- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -294,6 +294,15 @@ public: } }; +class AsmVariantInfo { +public: + std::string RegisterPrefix; + std::string TokenizingCharacters; + std::string SeparatorCharacters; + std::string BreakCharacters; + int AsmVariantNo; +}; + /// MatchableInfo - Helper class for storing the necessary information for an /// instruction or alias which is capable of being matched. struct MatchableInfo { @@ -460,6 +469,20 @@ struct MatchableInfo { TheDef->getValueAsBit("UseInstAsmMatchConverter")) { } + // Could remove this and the dtor if PointerUnion supported unique_ptr + // elements with a dynamic failure/assertion (like the one below) in the case + // where it was copied while being in an owning state. + MatchableInfo(const MatchableInfo &RHS) + : AsmVariantID(RHS.AsmVariantID), AsmString(RHS.AsmString), + TheDef(RHS.TheDef), DefRec(RHS.DefRec), ResOperands(RHS.ResOperands), + Mnemonic(RHS.Mnemonic), AsmOperands(RHS.AsmOperands), + RequiredFeatures(RHS.RequiredFeatures), + ConversionFnKind(RHS.ConversionFnKind), + HasDeprecation(RHS.HasDeprecation), + UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) { + assert(!DefRec.is<const CodeGenInstAlias *>()); + } + ~MatchableInfo() { delete DefRec.dyn_cast<const CodeGenInstAlias*>(); } @@ -470,18 +493,12 @@ struct MatchableInfo { void initialize(const AsmMatcherInfo &Info, SmallPtrSetImpl<Record*> &SingletonRegisters, - int AsmVariantNo, std::string &RegisterPrefix); + AsmVariantInfo const &Variant); /// validate - Return true if this matchable is a valid thing to match against /// and perform a bunch of validity checking. bool validate(StringRef CommentDelimiter, bool Hack) const; - /// extractSingletonRegisterForAsmOperand - Extract singleton register, - /// if present, from specified token. - void - extractSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info, - std::string &RegisterPrefix); - /// findAsmOperand - Find the AsmOperand with the specified name and /// suboperand index. int findAsmOperand(StringRef N, int SubOpIdx) const { @@ -576,8 +593,10 @@ struct MatchableInfo { void dump() const; private: - void tokenizeAsmString(const AsmMatcherInfo &Info); - void addAsmOperand(size_t Start, size_t End); + void tokenizeAsmString(AsmMatcherInfo const &Info, + AsmVariantInfo const &Variant); + void addAsmOperand(size_t Start, size_t End, + std::string const &SeparatorCharacters); }; /// SubtargetFeatureInfo - Helper class for storing information on a subtarget @@ -756,8 +775,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { // Find the ResOperand that refers to the operand we're aliasing away // and update it to refer to the combined operand instead. - for (unsigned i = 0, e = ResOperands.size(); i != e; ++i) { - ResOperand &Op = ResOperands[i]; + for (ResOperand &Op : ResOperands) { if (Op.Kind == ResOperand::RenderAsmOperand && Op.AsmOperandNum == (unsigned)SrcAsmOperand) { Op.AsmOperandNum = DstAsmOperand; @@ -768,8 +786,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { AsmOperands.erase(AsmOperands.begin() + SrcAsmOperand); // Adjust the ResOperand references to any AsmOperands that followed // the one we just deleted. - for (unsigned i = 0, e = ResOperands.size(); i != e; ++i) { - ResOperand &Op = ResOperands[i]; + for (ResOperand &Op : ResOperands) { switch(Op.Kind) { default: // Nothing to do for operands that don't reference AsmOperands. @@ -786,26 +803,58 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { } } +/// extractSingletonRegisterForAsmOperand - Extract singleton register, +/// if present, from specified token. +static void +extractSingletonRegisterForAsmOperand(MatchableInfo::AsmOperand &Op, + const AsmMatcherInfo &Info, + StringRef RegisterPrefix) { + StringRef Tok = Op.Token; + + // If this token is not an isolated token, i.e., it isn't separated from + // other tokens (e.g. with whitespace), don't interpret it as a register name. + if (!Op.IsIsolatedToken) + return; + + if (RegisterPrefix.empty()) { + std::string LoweredTok = Tok.lower(); + if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok)) + Op.SingletonReg = Reg->TheDef; + return; + } + + if (!Tok.startswith(RegisterPrefix)) + return; + + StringRef RegName = Tok.substr(RegisterPrefix.size()); + if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName)) + Op.SingletonReg = Reg->TheDef; + + // If there is no register prefix (i.e. "%" in "%eax"), then this may + // be some random non-register token, just ignore it. + return; +} + void MatchableInfo::initialize(const AsmMatcherInfo &Info, SmallPtrSetImpl<Record*> &SingletonRegisters, - int AsmVariantNo, std::string &RegisterPrefix) { - AsmVariantID = AsmVariantNo; + AsmVariantInfo const &Variant) { + AsmVariantID = Variant.AsmVariantNo; AsmString = - CodeGenInstruction::FlattenAsmStringVariants(AsmString, AsmVariantNo); + CodeGenInstruction::FlattenAsmStringVariants(AsmString, + Variant.AsmVariantNo); - tokenizeAsmString(Info); + tokenizeAsmString(Info, Variant); // Compute the require features. - std::vector<Record*> Predicates =TheDef->getValueAsListOfDefs("Predicates"); - for (unsigned i = 0, e = Predicates.size(); i != e; ++i) + for (Record *Predicate : TheDef->getValueAsListOfDefs("Predicates")) if (const SubtargetFeatureInfo *Feature = - Info.getSubtargetFeature(Predicates[i])) + Info.getSubtargetFeature(Predicate)) RequiredFeatures.push_back(Feature); // Collect singleton registers, if used. - for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { - extractSingletonRegisterForAsmOperand(i, Info, RegisterPrefix); - if (Record *Reg = AsmOperands[i].SingletonReg) + for (MatchableInfo::AsmOperand &Op : AsmOperands) { + extractSingletonRegisterForAsmOperand(Op, Info, Variant.RegisterPrefix); + if (Record *Reg = Op.SingletonReg) SingletonRegisters.insert(Reg); } @@ -818,9 +867,9 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info, } /// Append an AsmOperand for the given substring of AsmString. -void MatchableInfo::addAsmOperand(size_t Start, size_t End) { +void MatchableInfo::addAsmOperand(size_t Start, size_t End, + std::string const &Separators) { StringRef String = AsmString; - StringRef Separators = "[]*! \t,"; // Look for separators before and after to figure out is this token is // isolated. Accept '$$' as that's how we escape '$'. bool IsIsolatedToken = @@ -831,92 +880,86 @@ void MatchableInfo::addAsmOperand(size_t Start, size_t End) { } /// tokenizeAsmString - Tokenize a simplified assembly string. -void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { +void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info, + AsmVariantInfo const &Variant) { StringRef String = AsmString; - unsigned Prev = 0; - bool InTok = true; - for (unsigned i = 0, e = String.size(); i != e; ++i) { - switch (String[i]) { - case '[': - case ']': - case '*': - case '!': - case ' ': - case '\t': - case ',': - if (InTok) { - addAsmOperand(Prev, i); + size_t Prev = 0; + bool InTok = false; + std::string Separators = Variant.TokenizingCharacters + + Variant.SeparatorCharacters; + for (size_t i = 0, e = String.size(); i != e; ++i) { + if(Variant.BreakCharacters.find(String[i]) != std::string::npos) { + if(InTok) { + addAsmOperand(Prev, i, Separators); + Prev = i; + } + InTok = true; + continue; + } + if(Variant.TokenizingCharacters.find(String[i]) != std::string::npos) { + if(InTok) { + addAsmOperand(Prev, i, Separators); InTok = false; } - if (!isspace(String[i]) && String[i] != ',') - addAsmOperand(i, i + 1); + addAsmOperand(i, i + 1, Separators); Prev = i + 1; - break; - + continue; + } + if(Variant.SeparatorCharacters.find(String[i]) != std::string::npos) { + if(InTok) { + addAsmOperand(Prev, i, Separators); + InTok = false; + } + Prev = i + 1; + continue; + } + switch (String[i]) { case '\\': if (InTok) { - addAsmOperand(Prev, i); + addAsmOperand(Prev, i, Separators); InTok = false; } ++i; assert(i != String.size() && "Invalid quoted character"); - addAsmOperand(i, i + 1); + addAsmOperand(i, i + 1, Separators); Prev = i + 1; break; case '$': { - if (InTok) { - addAsmOperand(Prev, i); + if (InTok && Prev != i) { + addAsmOperand(Prev, i, Separators); InTok = false; } - // If this isn't "${", treat like a normal token. + // If this isn't "${", start new identifier looking like "$xxx" if (i + 1 == String.size() || String[i + 1] != '{') { Prev = i; break; } - StringRef::iterator End = std::find(String.begin() + i, String.end(),'}'); - assert(End != String.end() && "Missing brace in operand reference!"); - size_t EndPos = End - String.begin(); - addAsmOperand(i, EndPos+1); + size_t EndPos = String.find('}', i); + assert(EndPos != StringRef::npos && + "Missing brace in operand reference!"); + addAsmOperand(i, EndPos+1, Separators); Prev = EndPos + 1; i = EndPos; break; } - - case '.': - if (!Info.AsmParser->getValueAsBit("MnemonicContainsDot")) { - if (InTok) - addAsmOperand(Prev, i); - Prev = i; - } - InTok = true; - break; - default: InTok = true; } } if (InTok && Prev != String.size()) - addAsmOperand(Prev, StringRef::npos); + addAsmOperand(Prev, StringRef::npos, Separators); // The first token of the instruction is the mnemonic, which must be a // simple string, not a $foo variable or a singleton register. if (AsmOperands.empty()) PrintFatalError(TheDef->getLoc(), "Instruction '" + TheDef->getName() + "' has no tokens"); - Mnemonic = AsmOperands[0].Token; - if (Mnemonic.empty()) - PrintFatalError(TheDef->getLoc(), - "Missing instruction mnemonic"); - // FIXME : Check and raise an error if it is a register. - if (Mnemonic[0] == '$') - PrintFatalError(TheDef->getLoc(), - "Invalid instruction mnemonic '" + Mnemonic + "'!"); - - // Remove the first operand, it is tracked in the mnemonic field. - AsmOperands.erase(AsmOperands.begin()); + assert(!AsmOperands[0].Token.empty()); + if (AsmOperands[0].Token[0] != '$') + Mnemonic = AsmOperands[0].Token; } bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { @@ -946,8 +989,8 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { // Also, check for instructions which reference the operand multiple times; // this implies a constraint we would not honor. std::set<std::string> OperandNames; - for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { - StringRef Tok = AsmOperands[i].Token; + for (const AsmOperand &Op : AsmOperands) { + StringRef Tok = Op.Token; if (Tok[0] == '$' && Tok.find(':') != StringRef::npos) PrintFatalError(TheDef->getLoc(), "matchable with operand modifier '" + Tok + @@ -974,38 +1017,6 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { return true; } -/// extractSingletonRegisterForAsmOperand - Extract singleton register, -/// if present, from specified token. -void MatchableInfo:: -extractSingletonRegisterForAsmOperand(unsigned OperandNo, - const AsmMatcherInfo &Info, - std::string &RegisterPrefix) { - StringRef Tok = AsmOperands[OperandNo].Token; - - // If this token is not an isolated token, i.e., it isn't separated from - // other tokens (e.g. with whitespace), don't interpret it as a register name. - if (!AsmOperands[OperandNo].IsIsolatedToken) - return; - - if (RegisterPrefix.empty()) { - std::string LoweredTok = Tok.lower(); - if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok)) - AsmOperands[OperandNo].SingletonReg = Reg->TheDef; - return; - } - - if (!Tok.startswith(RegisterPrefix)) - return; - - StringRef RegName = Tok.substr(RegisterPrefix.size()); - if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName)) - AsmOperands[OperandNo].SingletonReg = Reg->TheDef; - - // If there is no register prefix (i.e. "%" in "%eax"), then this may - // be some random non-register token, just ignore it. - return; -} - static std::string getEnumNameForToken(StringRef Str) { std::string Res; @@ -1364,8 +1375,15 @@ void AsmMatcherInfo::buildInfo() { Record *AsmVariant = Target.getAsmParserVariant(VC); std::string CommentDelimiter = AsmVariant->getValueAsString("CommentDelimiter"); - std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix"); - int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); + AsmVariantInfo Variant; + Variant.RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix"); + Variant.TokenizingCharacters = + AsmVariant->getValueAsString("TokenizingCharacters"); + Variant.SeparatorCharacters = + AsmVariant->getValueAsString("SeparatorCharacters"); + Variant.BreakCharacters = + AsmVariant->getValueAsString("BreakCharacters"); + Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant"); for (const CodeGenInstruction *CGI : Target.instructions()) { @@ -1378,9 +1396,9 @@ void AsmMatcherInfo::buildInfo() { if (CGI->TheDef->getValueAsBit("isCodeGenOnly")) continue; - std::unique_ptr<MatchableInfo> II(new MatchableInfo(*CGI)); + auto II = llvm::make_unique<MatchableInfo>(*CGI); - II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); + II->initialize(*this, SingletonRegisters, Variant); // Ignore instructions which shouldn't be matched and diagnose invalid // instruction definitions with an error. @@ -1396,7 +1414,8 @@ void AsmMatcherInfo::buildInfo() { Records.getAllDerivedDefinitions("InstAlias"); for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { auto Alias = llvm::make_unique<CodeGenInstAlias>(AllInstAliases[i], - AsmVariantNo, Target); + Variant.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 @@ -1405,9 +1424,9 @@ void AsmMatcherInfo::buildInfo() { .startswith( MatchPrefix)) continue; - std::unique_ptr<MatchableInfo> II(new MatchableInfo(std::move(Alias))); + auto II = llvm::make_unique<MatchableInfo>(std::move(Alias)); - II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); + II->initialize(*this, SingletonRegisters, Variant); // Validate the alias definitions. II->validate(CommentDelimiter, false); @@ -1434,7 +1453,7 @@ void AsmMatcherInfo::buildInfo() { StringRef Token = Op.Token; // Check for singleton registers. - if (Record *RegRecord = II->AsmOperands[i].SingletonReg) { + if (Record *RegRecord = Op.SingletonReg) { Op.Class = RegisterClasses[RegRecord]; assert(Op.Class && Op.Class->Registers.size() == 1 && "Unexpected class for singleton register"); @@ -1474,7 +1493,7 @@ void AsmMatcherInfo::buildInfo() { II->TheDef->getValueAsString("TwoOperandAliasConstraint"); if (Constraint != "") { // Start by making a copy of the original matchable. - std::unique_ptr<MatchableInfo> AliasII(new MatchableInfo(*II)); + auto AliasII = llvm::make_unique<MatchableInfo>(*II); // Adjust it to be a two-operand alias. AliasII->formTwoOperandAlias(Constraint); @@ -1494,8 +1513,7 @@ void AsmMatcherInfo::buildInfo() { // information. std::vector<Record*> AllTokenAliases = Records.getAllDerivedDefinitions("TokenAlias"); - for (unsigned i = 0, e = AllTokenAliases.size(); i != e; ++i) { - Record *Rec = AllTokenAliases[i]; + for (Record *Rec : AllTokenAliases) { ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken")); ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken")); if (FromClass == ToClass) @@ -1603,9 +1621,7 @@ void MatchableInfo::buildInstructionResultOperands() { // Loop over all operands of the result instruction, determining how to // populate them. - for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { - const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i]; - + for (const CGIOperandList::OperandInfo &OpInfo : ResultInst->Operands) { // If this is a tied operand, just copy from the previously handled operand. int TiedOp = -1; if (OpInfo.MINumOperands == 1) @@ -1701,7 +1717,7 @@ void MatchableInfo::buildAliasResultOperands() { } static unsigned getConverterOperandID(const std::string &Name, - SetVector<std::string> &Table, + SmallSetVector<std::string, 16> &Table, bool &IsNew) { IsNew = Table.insert(Name); @@ -1717,8 +1733,8 @@ static unsigned getConverterOperandID(const std::string &Name, static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, std::vector<std::unique_ptr<MatchableInfo>> &Infos, raw_ostream &OS) { - SetVector<std::string> OperandConversionKinds; - SetVector<std::string> InstructionConversionKinds; + SmallSetVector<std::string, 16> OperandConversionKinds; + SmallSetVector<std::string, 16> InstructionConversionKinds; std::vector<std::vector<uint8_t> > ConversionTable; size_t MaxRowLength = 2; // minimum is custom converter plus terminator. @@ -1850,7 +1866,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Add the operand entry to the instruction kind conversion row. ConversionRow.push_back(ID); - ConversionRow.push_back(OpInfo.AsmOperandNum + 1); + ConversionRow.push_back(OpInfo.AsmOperandNum); if (!IsNewConverter) break; @@ -1959,7 +1975,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, continue; // Add the row to the table. - ConversionTable.push_back(ConversionRow); + ConversionTable.push_back(std::move(ConversionRow)); } // Finish up the converter driver function. @@ -1979,10 +1995,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Output the instruction conversion kind enum. OS << "enum InstructionConversionKind {\n"; - for (SetVector<std::string>::const_iterator - i = InstructionConversionKinds.begin(), - e = InstructionConversionKinds.end(); i != e; ++i) - OS << " " << *i << ",\n"; + for (const std::string &Signature : InstructionConversionKinds) + OS << " " << Signature << ",\n"; OS << " CVT_NUM_SIGNATURES\n"; OS << "};\n\n"; @@ -2105,12 +2119,7 @@ static void emitIsSubclass(CodeGenTarget &Target, OS << " if (A == B)\n"; OS << " return true;\n\n"; - std::string OStr; - raw_string_ostream SS(OStr); - unsigned Count = 0; - SS << " switch (A) {\n"; - SS << " default:\n"; - SS << " return false;\n"; + bool EmittedSwitch = false; for (const auto &A : Infos) { std::vector<StringRef> SuperClasses; for (const auto &B : Infos) { @@ -2120,33 +2129,38 @@ static void emitIsSubclass(CodeGenTarget &Target, if (SuperClasses.empty()) continue; - ++Count; - SS << "\n case " << A.Name << ":\n"; + // If this is the first SuperClass, emit the switch header. + if (!EmittedSwitch) { + OS << " switch (A) {\n"; + OS << " default:\n"; + OS << " return false;\n"; + EmittedSwitch = true; + } + + OS << "\n case " << A.Name << ":\n"; if (SuperClasses.size() == 1) { - SS << " return B == " << SuperClasses.back().str() << ";\n"; + OS << " return B == " << SuperClasses.back() << ";\n"; continue; } if (!SuperClasses.empty()) { - SS << " switch (B) {\n"; - SS << " default: return false;\n"; - for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) - SS << " case " << SuperClasses[i].str() << ": return true;\n"; - SS << " }\n"; + OS << " switch (B) {\n"; + OS << " default: return false;\n"; + for (StringRef SC : SuperClasses) + OS << " case " << SC << ": return true;\n"; + OS << " }\n"; } else { // No case statement to emit - SS << " return false;\n"; + OS << " return false;\n"; } } - SS << " }\n"; + OS << " }\n"; - // If there were case statements emitted into the string stream, write them - // to the output stream, otherwise write the default. - if (Count) - OS << SS.str(); - else + // If there were case statements emitted into the string stream write the + // default. + if (!EmittedSwitch) OS << " return false;\n"; OS << "}\n\n"; @@ -2575,13 +2589,17 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the next operand index.\n"; - OS << " unsigned NextOpNum = Operands.size()-1;\n"; + OS << " unsigned NextOpNum = Operands.size();\n"; // Emit code to search the table. OS << " // Search the table.\n"; OS << " std::pair<const OperandMatchEntry*, const OperandMatchEntry*>"; - OS << " MnemonicRange =\n"; - OS << " std::equal_range(OperandMatchTable, OperandMatchTable+" + OS << " MnemonicRange\n"; + OS << " (OperandMatchTable, OperandMatchTable+"; + OS << Info.OperandMatchInfo.size() << ");\n"; + OS << " if(!Mnemonic.empty())\n"; + OS << " MnemonicRange = std::equal_range(OperandMatchTable,"; + OS << " OperandMatchTable+" << Info.OperandMatchInfo.size() << ", Mnemonic,\n" << " LessOpcodeOperand());\n\n"; @@ -2682,7 +2700,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << "&Operands);\n"; OS << " void convertToMapAndConstraints(unsigned Kind,\n "; OS << " const OperandVector &Operands) override;\n"; - OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) override;\n"; + OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n"; OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n" << " MCInst &Inst,\n" << " uint64_t &ErrorInfo," @@ -2891,8 +2909,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " bool matchingInlineAsm, unsigned VariantID) {\n"; OS << " // Eliminate obvious mismatches.\n"; - OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; - OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n"; + OS << " if (Operands.size() > " << MaxNumOperands << ") {\n"; + OS << " ErrorInfo = " << MaxNumOperands << ";\n"; OS << " return Match_InvalidOperand;\n"; OS << " }\n\n"; @@ -2901,7 +2919,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the instruction mnemonic, which is the first token.\n"; - OS << " StringRef Mnemonic = ((" << Target.getName() + OS << " StringRef Mnemonic;\n"; + OS << " if (Operands[0]->isToken())\n"; + OS << " Mnemonic = ((" << Target.getName() << "Operand&)*Operands[0]).getToken();\n\n"; if (HasMnemonicAliases) { @@ -2932,8 +2952,11 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { } OS << " }\n"; OS << " // Search the table.\n"; - OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n"; - OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n"; + OS << " std::pair<const MatchEntry*, const MatchEntry*> " + "MnemonicRange(Start, End);\n"; + OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n"; + OS << " if (!Mnemonic.empty())\n"; + OS << " MnemonicRange = std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n"; OS << " // Return a more specific error code if no mnemonics match.\n"; OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; @@ -2943,28 +2966,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << "*ie = MnemonicRange.second;\n"; OS << " it != ie; ++it) {\n"; - OS << " // equal_range guarantees that instruction mnemonic matches.\n"; - OS << " assert(Mnemonic == it->getMnemonic());\n"; - // Emit check that the subclasses match. OS << " bool OperandsValid = true;\n"; - OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n"; - OS << " if (i + 1 >= Operands.size()) {\n"; - OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n"; - OS << " if (!OperandsValid) ErrorInfo = i + 1;\n"; + OS << " for (unsigned i = SIndex; i != " << MaxNumOperands << "; ++i) {\n"; + OS << " auto Formal = static_cast<MatchClassKind>(it->Classes[i]);\n"; + OS << " if (i >= Operands.size()) {\n"; + OS << " OperandsValid = (Formal == " <<"InvalidMatchClass);\n"; + OS << " if (!OperandsValid) ErrorInfo = i;\n"; OS << " break;\n"; OS << " }\n"; - OS << " unsigned Diag = validateOperandClass(*Operands[i+1],\n"; - OS.indent(43); - OS << "(MatchClassKind)it->Classes[i]);\n"; + OS << " MCParsedAsmOperand &Actual = *Operands[i];\n"; + OS << " unsigned Diag = validateOperandClass(Actual, Formal);\n"; OS << " if (Diag == Match_Success)\n"; OS << " continue;\n"; OS << " // If the generic handler indicates an invalid operand\n"; OS << " // failure, check for a special case.\n"; OS << " if (Diag == Match_InvalidOperand) {\n"; - OS << " Diag = validateTargetOperandClass(*Operands[i+1],\n"; - OS.indent(43); - OS << "(MatchClassKind)it->Classes[i]);\n"; + OS << " Diag = validateTargetOperandClass(Actual, Formal);\n"; OS << " if (Diag == Match_Success)\n"; OS << " continue;\n"; OS << " }\n"; @@ -2973,8 +2991,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // If we already had a match that only failed due to a\n"; OS << " // target predicate, that diagnostic is preferred.\n"; OS << " if (!HadMatchOtherThanPredicate &&\n"; - OS << " (it == MnemonicRange.first || ErrorInfo <= i+1)) {\n"; - OS << " ErrorInfo = i+1;\n"; + OS << " (it == MnemonicRange.first || ErrorInfo <= i)) {\n"; + OS << " ErrorInfo = i;\n"; OS << " // InvalidOperand is the default. Prefer specificity.\n"; OS << " if (Diag != Match_InvalidOperand)\n"; OS << " RetCode = Diag;\n"; @@ -3029,7 +3047,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (HasDeprecation) { OS << " std::string Info;\n"; - OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n"; + OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n"; OS << " SMLoc Loc = ((" << Target.getName() << "Operand&)*Operands[0]).getStartLoc();\n"; OS << " getParser().Warning(Loc, Info, None);\n"; diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp index 8163f681d88d..cc74f9ebcece 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -586,6 +586,8 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { const auto &Registers = Target.getRegBank().getRegisters(); std::vector<Record*> AltNameIndices = Target.getRegAltNameIndices(); bool hasAltNames = AltNameIndices.size() > 1; + std::string Namespace = + Registers.front().TheDef->getValueAsString("Namespace"); O << "\n\n/// getRegisterName - This method is automatically generated by tblgen\n" @@ -610,9 +612,9 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { 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" + std::string Prefix = !Namespace.empty() ? Namespace + "::" : ""; + O << " case " << Prefix << AltName << ":\n" << " assert(*(AsmStrs" << AltName << "+RegAsmOffset" << AltName << "[RegNo-1]) &&\n" << " \"Invalid alt name index for register!\");\n" @@ -727,7 +729,6 @@ public: ++I; } } - OS.flush(); // Emit the string. O.indent(6) << "AsmString = \"" << OutString << "\";\n"; @@ -736,14 +737,13 @@ public: O.indent(4) << '}'; } - bool operator==(const IAPrinter &RHS) { + bool operator==(const IAPrinter &RHS) const { if (Conds.size() != RHS.Conds.size()) return false; unsigned Idx = 0; - for (std::vector<std::string>::iterator - I = Conds.begin(), E = Conds.end(); I != E; ++I) - if (*I != RHS.Conds[Idx++]) + for (const auto &str : Conds) + if (str != RHS.Conds[Idx++]) return false; return true; @@ -762,12 +762,12 @@ static unsigned CountNumOperands(StringRef AsmString, unsigned Variant) { namespace { struct AliasPriorityComparator { - typedef std::pair<CodeGenInstAlias *, int> ValueType; + typedef std::pair<CodeGenInstAlias, int> ValueType; bool operator()(const ValueType &LHS, const ValueType &RHS) { if (LHS.second == RHS.second) { // We don't actually care about the order, but for consistency it // shouldn't depend on pointer comparisons. - return LHS.first->TheDef->getName() < RHS.first->TheDef->getName(); + return LHS.first.TheDef->getName() < RHS.first.TheDef->getName(); } // Aliases with larger priorities should be considered first. @@ -796,12 +796,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { Records.getAllDerivedDefinitions("InstAlias"); // Create a map from the qualified name to a list of potential matches. - typedef std::set<std::pair<CodeGenInstAlias*, int>, AliasPriorityComparator> + typedef std::set<std::pair<CodeGenInstAlias, int>, AliasPriorityComparator> AliasWithPriority; std::map<std::string, AliasWithPriority> AliasMap; for (std::vector<Record*>::iterator I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) { - CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Variant, Target); const Record *R = *I; int Priority = R->getValueAsInt("EmitPriority"); if (Priority < 1) @@ -809,13 +808,13 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { const DagInit *DI = R->getValueAsDag("ResultInst"); const DefInit *Op = cast<DefInit>(DI->getOperator()); - AliasMap[getQualifiedName(Op->getDef())].insert(std::make_pair(Alias, - Priority)); + AliasMap[getQualifiedName(Op->getDef())].insert( + std::make_pair(CodeGenInstAlias(*I, Variant, Target), Priority)); } // A map of which conditions need to be met for each instruction operand // before it can be matched to the mnemonic. - std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap; + std::map<std::string, std::vector<IAPrinter>> IAPrinterMap; // A list of MCOperandPredicates for all operands in use, and the reverse map std::vector<const Record*> MCOpPredicates; @@ -823,25 +822,24 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { for (auto &Aliases : AliasMap) { for (auto &Alias : Aliases.second) { - const CodeGenInstAlias *CGA = Alias.first; - unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); + const CodeGenInstAlias &CGA = Alias.first; + unsigned LastOpNo = CGA.ResultInstOperandIndex.size(); unsigned NumResultOps = - CountNumOperands(CGA->ResultInst->AsmString, Variant); + CountNumOperands(CGA.ResultInst->AsmString, Variant); // Don't emit the alias if it has more operands than what it's aliasing. - if (NumResultOps < CountNumOperands(CGA->AsmString, Variant)) + if (NumResultOps < CountNumOperands(CGA.AsmString, Variant)) continue; - IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(), - CGA->AsmString); + IAPrinter IAP(CGA.Result->getAsString(), CGA.AsmString); unsigned NumMIOps = 0; - for (auto &Operand : CGA->ResultOperands) + for (auto &Operand : CGA.ResultOperands) NumMIOps += Operand.getMINumOperands(); std::string Cond; Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(NumMIOps); - IAP->addCond(Cond); + IAP.addCond(Cond); bool CantHandle = false; @@ -849,7 +847,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { for (unsigned i = 0, e = LastOpNo; i != e; ++i) { std::string Op = "MI->getOperand(" + llvm::utostr(MIOpNum) + ")"; - const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i]; + const CodeGenInstAlias::ResultOperand &RO = CGA.ResultOperands[i]; switch (RO.Kind) { case CodeGenInstAlias::ResultOperand::K_Record: { @@ -875,11 +873,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { if (Rec->isSubClassOf("RegisterOperand")) Rec = Rec->getValueAsDef("RegClass"); if (Rec->isSubClassOf("RegisterClass")) { - IAP->addCond(Op + ".isReg()"); + IAP.addCond(Op + ".isReg()"); - if (!IAP->isOpMapped(ROName)) { - IAP->addOperand(ROName, MIOpNum, PrintMethodIdx); - Record *R = CGA->ResultOperands[i].getRecord(); + if (!IAP.isOpMapped(ROName)) { + IAP.addOperand(ROName, MIOpNum, PrintMethodIdx); + Record *R = CGA.ResultOperands[i].getRecord(); if (R->isSubClassOf("RegisterOperand")) R = R->getValueAsDef("RegClass"); Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" + @@ -887,12 +885,12 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { ".contains(" + Op + ".getReg())"; } else { Cond = Op + ".getReg() == MI->getOperand(" + - llvm::utostr(IAP->getOpIndex(ROName)) + ").getReg()"; + llvm::utostr(IAP.getOpIndex(ROName)) + ").getReg()"; } } else { // Assume all printable operands are desired for now. This can be // overridden in the InstAlias instantiation if necessary. - IAP->addOperand(ROName, MIOpNum, PrintMethodIdx); + IAP.addOperand(ROName, MIOpNum, PrintMethodIdx); // There might be an additional predicate on the MCOperand unsigned Entry = MCOpPredicateMap[Rec]; @@ -905,42 +903,41 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { break; // No conditions on this operand at all } Cond = Target.getName() + ClassName + "ValidateMCOperand(" + - Op + ", " + llvm::utostr(Entry) + ")"; + Op + ", STI, " + llvm::utostr(Entry) + ")"; } // for all subcases of ResultOperand::K_Record: - IAP->addCond(Cond); + IAP.addCond(Cond); break; } case CodeGenInstAlias::ResultOperand::K_Imm: { // Just because the alias has an immediate result, doesn't mean the // MCInst will. An MCExpr could be present, for example. - IAP->addCond(Op + ".isImm()"); + IAP.addCond(Op + ".isImm()"); - Cond = Op + ".getImm() == " - + llvm::utostr(CGA->ResultOperands[i].getImm()); - IAP->addCond(Cond); + Cond = Op + ".getImm() == " + + llvm::utostr(CGA.ResultOperands[i].getImm()); + IAP.addCond(Cond); break; } case CodeGenInstAlias::ResultOperand::K_Reg: // If this is zero_reg, something's playing tricks we're not // equipped to handle. - if (!CGA->ResultOperands[i].getRegister()) { + if (!CGA.ResultOperands[i].getRegister()) { CantHandle = true; break; } - Cond = Op + ".getReg() == " + Target.getName() + - "::" + CGA->ResultOperands[i].getRegister()->getName(); - IAP->addCond(Cond); + Cond = Op + ".getReg() == " + Target.getName() + "::" + + CGA.ResultOperands[i].getRegister()->getName(); + IAP.addCond(Cond); break; } - if (!IAP) break; MIOpNum += RO.getMINumOperands(); } if (CantHandle) continue; - IAPrinterMap[Aliases.first].push_back(IAP); + IAPrinterMap[Aliases.first].push_back(std::move(IAP)); } } @@ -959,30 +956,26 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { std::string Cases; raw_string_ostream CasesO(Cases); - for (std::map<std::string, std::vector<IAPrinter*> >::iterator - I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) { - std::vector<IAPrinter*> &IAPs = I->second; + for (auto &Entry : IAPrinterMap) { + std::vector<IAPrinter> &IAPs = Entry.second; std::vector<IAPrinter*> UniqueIAPs; - for (std::vector<IAPrinter*>::iterator - II = IAPs.begin(), IE = IAPs.end(); II != IE; ++II) { - IAPrinter *LHS = *II; + for (auto &LHS : IAPs) { bool IsDup = false; - for (std::vector<IAPrinter*>::iterator - III = IAPs.begin(), IIE = IAPs.end(); III != IIE; ++III) { - IAPrinter *RHS = *III; - if (LHS != RHS && *LHS == *RHS) { + for (const auto &RHS : IAPs) { + if (&LHS != &RHS && LHS == RHS) { IsDup = true; break; } } - if (!IsDup) UniqueIAPs.push_back(LHS); + if (!IsDup) + UniqueIAPs.push_back(&LHS); } if (UniqueIAPs.empty()) continue; - CasesO.indent(2) << "case " << I->first << ":\n"; + CasesO.indent(2) << "case " << Entry.first << ":\n"; for (std::vector<IAPrinter*>::iterator II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) { @@ -1005,8 +998,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { if (!MCOpPredicates.empty()) O << "static bool " << Target.getName() << ClassName - << "ValidateMCOperand(\n" - << " const MCOperand &MCOp, unsigned PredicateIndex);\n"; + << "ValidateMCOperand(const MCOperand &MCOp,\n" + << " const MCSubtargetInfo &STI,\n" + << " unsigned PredicateIndex);\n"; O << HeaderO.str(); O.indent(2) << "const char *AsmString;\n"; @@ -1078,8 +1072,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { if (!MCOpPredicates.empty()) { O << "static bool " << Target.getName() << ClassName - << "ValidateMCOperand(\n" - << " const MCOperand &MCOp, unsigned PredicateIndex) {\n" + << "ValidateMCOperand(const MCOperand &MCOp,\n" + << " const MCSubtargetInfo &STI,\n" + << " unsigned PredicateIndex) {\n" << " switch (PredicateIndex) {\n" << " default:\n" << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n" diff --git a/contrib/llvm/utils/TableGen/Attributes.cpp b/contrib/llvm/utils/TableGen/Attributes.cpp new file mode 100644 index 000000000000..7b001bf14de5 --- /dev/null +++ b/contrib/llvm/utils/TableGen/Attributes.cpp @@ -0,0 +1,156 @@ +//===- Attributes.cpp - Generate attributes -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include <algorithm> +#include <string> +#include <vector> +using namespace llvm; + +#define DEBUG_TYPE "attr-enum" + +namespace { + +class Attributes { +public: + Attributes(RecordKeeper &R) : Records(R) {} + void emit(raw_ostream &OS); + +private: + void emitTargetIndependentEnums(raw_ostream &OS); + void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr); + + void printEnumAttrClasses(raw_ostream &OS, + const std::vector<Record *> &Records); + void printStrBoolAttrClasses(raw_ostream &OS, + const std::vector<Record *> &Records); + + RecordKeeper &Records; +}; + +} // End anonymous namespace. + +void Attributes::emitTargetIndependentEnums(raw_ostream &OS) { + OS << "#ifdef GET_ATTR_ENUM\n"; + OS << "#undef GET_ATTR_ENUM\n"; + + std::vector<Record*> Attrs = + Records.getAllDerivedDefinitions("EnumAttr"); + + for (auto A : Attrs) + OS << A->getName() << ",\n"; + + OS << "#endif\n"; +} + +void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) { + OS << "#ifdef GET_ATTR_COMPAT_FUNC\n"; + OS << "#undef GET_ATTR_COMPAT_FUNC\n"; + + OS << "struct EnumAttr {\n"; + OS << " static bool isSet(const Function &Fn,\n"; + OS << " Attribute::AttrKind Kind) {\n"; + OS << " return Fn.hasFnAttribute(Kind);\n"; + OS << " }\n\n"; + OS << " static void set(Function &Fn,\n"; + OS << " Attribute::AttrKind Kind, bool Val) {\n"; + OS << " if (Val)\n"; + OS << " Fn.addFnAttr(Kind);\n"; + OS << " else\n"; + OS << " Fn.removeFnAttr(Kind);\n"; + OS << " }\n"; + OS << "};\n\n"; + + OS << "struct StrBoolAttr {\n"; + OS << " static bool isSet(const Function &Fn,\n"; + OS << " StringRef Kind) {\n"; + OS << " auto A = Fn.getFnAttribute(Kind);\n"; + OS << " return A.getValueAsString().equals(\"true\");\n"; + OS << " }\n\n"; + OS << " static void set(Function &Fn,\n"; + OS << " StringRef Kind, bool Val) {\n"; + OS << " Fn.addFnAttr(Kind, Val ? \"true\" : \"false\");\n"; + OS << " }\n"; + OS << "};\n\n"; + + printEnumAttrClasses(OS ,Records.getAllDerivedDefinitions("EnumAttr")); + printStrBoolAttrClasses(OS , Records.getAllDerivedDefinitions("StrBoolAttr")); + + OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n" + << " const Function &Callee) {\n"; + OS << " bool Ret = true;\n\n"; + + std::vector<Record *> CompatRules = + Records.getAllDerivedDefinitions("CompatRule"); + + for (auto *Rule : CompatRules) { + std::string FuncName = Rule->getValueAsString("CompatFunc"); + OS << " Ret &= " << FuncName << "(Caller, Callee);\n"; + } + + OS << "\n"; + OS << " return Ret;\n"; + OS << "}\n\n"; + + std::vector<Record *> MergeRules = + Records.getAllDerivedDefinitions("MergeRule"); + OS << "static inline void mergeFnAttrs(Function &Caller,\n" + << " const Function &Callee) {\n"; + + for (auto *Rule : MergeRules) { + std::string FuncName = Rule->getValueAsString("MergeFunc"); + OS << " " << FuncName << "(Caller, Callee);\n"; + } + + OS << "}\n\n"; + + OS << "#endif\n"; +} + +void Attributes::printEnumAttrClasses(raw_ostream &OS, + const std::vector<Record *> &Records) { + OS << "// EnumAttr classes\n"; + for (const auto *R : Records) { + OS << "struct " << R->getName() << "Attr : EnumAttr {\n"; + OS << " static enum Attribute::AttrKind getKind() {\n"; + OS << " return llvm::Attribute::" << R->getName() << ";\n"; + OS << " }\n"; + OS << "};\n"; + } + OS << "\n"; +} + +void Attributes::printStrBoolAttrClasses(raw_ostream &OS, + const std::vector<Record *> &Records) { + OS << "// StrBoolAttr classes\n"; + for (const auto *R : Records) { + OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n"; + OS << " static const char *getKind() {\n"; + OS << " return \"" << R->getValueAsString("AttrString") << "\";\n"; + OS << " }\n"; + OS << "};\n"; + } + OS << "\n"; +} + +void Attributes::emit(raw_ostream &OS) { + emitTargetIndependentEnums(OS); + emitFnAttrCompatCheck(OS, false); +} + +namespace llvm { + +void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) { + Attributes(RK).emit(OS); +} + +} // End llvm namespace. diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp index c7519b3e1528..a47662b28558 100644 --- a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp +++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp @@ -181,15 +181,15 @@ void CallingConvEmitter::EmitAction(Record *Action, O << Size << ", "; else O << "\n" << IndentStr - << " State.getMachineFunction().getTarget().getDataLayout()" - "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," + << " State.getMachineFunction().getDataLayout()." + "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," " "; if (Align) O << Align; else O << "\n" << IndentStr - << " State.getMachineFunction().getTarget().getDataLayout()" - "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()" + << " State.getMachineFunction().getDataLayout()." + "getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()" "))"; O << ");\n" << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index ae1cc0cfb5fd..3ebe51e05121 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -14,6 +14,7 @@ #include "CodeGenDAGPatterns.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" @@ -84,9 +85,9 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, if (TP.hasError()) return false; - for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i) - if (!Pred || Pred(LegalTypes[i])) - TypeVec.push_back(LegalTypes[i]); + for (MVT::SimpleValueType VT : LegalTypes) + if (!Pred || Pred(VT)) + TypeVec.push_back(VT); // If we have nothing that matches the predicate, bail out. if (TypeVec.empty()) { @@ -107,36 +108,24 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, /// hasIntegerTypes - Return true if this TypeSet contains iAny or an /// integer value type. bool EEVT::TypeSet::hasIntegerTypes() const { - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isInteger(TypeVec[i])) - return true; - return false; + return std::any_of(TypeVec.begin(), TypeVec.end(), isInteger); } /// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or /// a floating point value type. bool EEVT::TypeSet::hasFloatingPointTypes() const { - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isFloatingPoint(TypeVec[i])) - return true; - return false; + return std::any_of(TypeVec.begin(), TypeVec.end(), isFloatingPoint); } /// hasScalarTypes - Return true if this TypeSet contains a scalar value type. bool EEVT::TypeSet::hasScalarTypes() const { - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isScalar(TypeVec[i])) - return true; - return false; + return std::any_of(TypeVec.begin(), TypeVec.end(), isScalar); } /// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector /// value type. bool EEVT::TypeSet::hasVectorTypes() const { - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isVector(TypeVec[i])) - return true; - return false; + return std::any_of(TypeVec.begin(), TypeVec.end(), isVector); } @@ -171,7 +160,7 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ return true; } - assert(TypeVec.size() >= 1 && InVT.TypeVec.size() >= 1 && "No unknowns"); + assert(!TypeVec.empty() && !InVT.TypeVec.empty() && "No unknowns"); // Handle the abstract cases, seeing if we can resolve them better. switch (TypeVec[0]) { @@ -206,8 +195,7 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ // multiple different integer types, replace them with a single iPTR. if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) && TypeVec.size() != 1) { - TypeVec.resize(1); - TypeVec[0] = InVT.TypeVec[0]; + TypeVec.assign(1, InVT.TypeVec[0]); MadeChange = true; } @@ -216,25 +204,20 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ // If this is a type list and the RHS is a typelist as well, eliminate entries // from this list that aren't in the other one. - bool MadeChange = false; TypeSet InputSet(*this); - for (unsigned i = 0; i != TypeVec.size(); ++i) { - bool InInVT = false; - for (unsigned j = 0, e = InVT.TypeVec.size(); j != e; ++j) - if (TypeVec[i] == InVT.TypeVec[j]) { - InInVT = true; - break; - } + TypeVec.clear(); + std::set_intersection(InputSet.TypeVec.begin(), InputSet.TypeVec.end(), + InVT.TypeVec.begin(), InVT.TypeVec.end(), + std::back_inserter(TypeVec)); - if (InInVT) continue; - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; - } + // If the intersection is the same size as the original set then we're done. + if (TypeVec.size() == InputSet.TypeVec.size()) + return false; // If we removed all of our types, we have a type contradiction. if (!TypeVec.empty()) - return MadeChange; + return true; // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, merging '" + @@ -249,15 +232,16 @@ bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) { // If we know nothing, then get the full set. if (TypeVec.empty()) return FillWithPossibleTypes(TP, isInteger, "integer"); + if (!hasFloatingPointTypes()) return false; TypeSet InputSet(*this); // Filter out all the fp types. - for (unsigned i = 0; i != TypeVec.size(); ++i) - if (!isInteger(TypeVec[i])) - TypeVec.erase(TypeVec.begin()+i--); + TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), + std::not1(std::ptr_fun(isInteger))), + TypeVec.end()); if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + @@ -280,10 +264,10 @@ bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) { TypeSet InputSet(*this); - // Filter out all the fp types. - for (unsigned i = 0; i != TypeVec.size(); ++i) - if (!isFloatingPoint(TypeVec[i])) - TypeVec.erase(TypeVec.begin()+i--); + // Filter out all the integer types. + TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), + std::not1(std::ptr_fun(isFloatingPoint))), + TypeVec.end()); if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + @@ -308,9 +292,9 @@ bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) { TypeSet InputSet(*this); // Filter out all the vector types. - for (unsigned i = 0; i != TypeVec.size(); ++i) - if (!isScalar(TypeVec[i])) - TypeVec.erase(TypeVec.begin()+i--); + TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), + std::not1(std::ptr_fun(isScalar))), + TypeVec.end()); if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + @@ -333,11 +317,9 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { bool MadeChange = false; // Filter out all the scalar types. - for (unsigned i = 0; i != TypeVec.size(); ++i) - if (!isVector(TypeVec[i])) { - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; - } + TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(), + std::not1(std::ptr_fun(isVector))), + TypeVec.end()); if (TypeVec.empty()) { TP.error("Type inference contradiction found, '" + @@ -350,7 +332,7 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { /// EnforceSmallerThan - 'this' must be a smaller VT than Other. For vectors -/// this shoud be based on the element type. Update this and other based on +/// this should be based on the element type. Update this and other based on /// this information. bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { if (TP.hasError()) @@ -404,59 +386,70 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { // type size is smaller than the scalar size of the smallest type. For // vectors, we also need to make sure that the total size is no larger than // the size of the smallest type. - TypeSet InputSet(Other); - MVT Smallest = TypeVec[0]; - for (unsigned i = 0; i != Other.TypeVec.size(); ++i) { - MVT OtherVT = Other.TypeVec[i]; - // Don't compare vector and non-vector types. - if (OtherVT.isVector() != Smallest.isVector()) - continue; - // The getSizeInBits() check here is only needed for vectors, but is - // a subset of the scalar check for scalars so no need to qualify. - if (OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits() || - OtherVT.getSizeInBits() < Smallest.getSizeInBits()) { - Other.TypeVec.erase(Other.TypeVec.begin()+i--); - MadeChange = true; + { + TypeSet InputSet(Other); + MVT Smallest = *std::min_element(TypeVec.begin(), TypeVec.end(), + [](MVT A, MVT B) { + return A.getScalarSizeInBits() < B.getScalarSizeInBits() || + (A.getScalarSizeInBits() == B.getScalarSizeInBits() && + A.getSizeInBits() < B.getSizeInBits()); + }); + + auto I = std::remove_if(Other.TypeVec.begin(), Other.TypeVec.end(), + [Smallest](MVT OtherVT) { + // Don't compare vector and non-vector types. + if (OtherVT.isVector() != Smallest.isVector()) + return false; + // The getSizeInBits() check here is only needed for vectors, but is + // a subset of the scalar check for scalars so no need to qualify. + return OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits()|| + OtherVT.getSizeInBits() < Smallest.getSizeInBits(); + }); + MadeChange |= I != Other.TypeVec.end(); // If we're about to remove types. + Other.TypeVec.erase(I, Other.TypeVec.end()); + + if (Other.TypeVec.empty()) { + TP.error("Type inference contradiction found, '" + InputSet.getName() + + "' has nothing larger than '" + getName() +"'!"); + return false; } } - if (Other.TypeVec.empty()) { - TP.error("Type inference contradiction found, '" + InputSet.getName() + - "' has nothing larger than '" + getName() +"'!"); - return false; - } - // Okay, find the largest type from the other set and remove anything the // same or smaller from the current set. We need to ensure that the scalar // type size is larger than the scalar size of the largest type. For // vectors, we also need to make sure that the total size is no smaller than // the size of the largest type. - InputSet = TypeSet(*this); - MVT Largest = Other.TypeVec[Other.TypeVec.size()-1]; - for (unsigned i = 0; i != TypeVec.size(); ++i) { - MVT OtherVT = TypeVec[i]; - // Don't compare vector and non-vector types. - if (OtherVT.isVector() != Largest.isVector()) - continue; - // The getSizeInBits() check here is only needed for vectors, but is - // a subset of the scalar check for scalars so no need to qualify. - if (OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() || - OtherVT.getSizeInBits() > Largest.getSizeInBits()) { - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; + { + TypeSet InputSet(*this); + MVT Largest = *std::max_element(Other.TypeVec.begin(), Other.TypeVec.end(), + [](MVT A, MVT B) { + return A.getScalarSizeInBits() < B.getScalarSizeInBits() || + (A.getScalarSizeInBits() == B.getScalarSizeInBits() && + A.getSizeInBits() < B.getSizeInBits()); + }); + auto I = std::remove_if(TypeVec.begin(), TypeVec.end(), + [Largest](MVT OtherVT) { + // Don't compare vector and non-vector types. + if (OtherVT.isVector() != Largest.isVector()) + return false; + return OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() || + OtherVT.getSizeInBits() > Largest.getSizeInBits(); + }); + MadeChange |= I != TypeVec.end(); // If we're about to remove types. + TypeVec.erase(I, TypeVec.end()); + + if (TypeVec.empty()) { + TP.error("Type inference contradiction found, '" + InputSet.getName() + + "' has nothing smaller than '" + Other.getName() +"'!"); + return false; } } - if (TypeVec.empty()) { - TP.error("Type inference contradiction found, '" + InputSet.getName() + - "' has nothing smaller than '" + Other.getName() +"'!"); - return false; - } - return MadeChange; } -/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type +/// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type /// whose element is specified by VTOperand. bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TreePattern &TP) { @@ -467,24 +460,24 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TypeSet InputSet(*this); // Filter out all the types which don't have the right element type. - for (unsigned i = 0; i != TypeVec.size(); ++i) { - assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); - if (MVT(TypeVec[i]).getVectorElementType().SimpleTy != VT) { - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; - } - } + auto I = std::remove_if(TypeVec.begin(), TypeVec.end(), + [VT](MVT VVT) { + return VVT.getVectorElementType().SimpleTy != VT; + }); + MadeChange |= I != TypeVec.end(); + TypeVec.erase(I, TypeVec.end()); if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, forcing '" + - InputSet.getName() + "' to have a vector element"); + InputSet.getName() + "' to have a vector element of type " + + getEnumName(VT)); return false; } return MadeChange; } -/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type +/// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type /// whose element is specified by VTOperand. bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, TreePattern &TP) { @@ -500,8 +493,7 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, if (isConcrete()) { MVT IVT = getConcrete(); IVT = IVT.getVectorElementType(); - return MadeChange | - VTOperand.MergeInTypeInfo(IVT.SimpleTy, TP); + return MadeChange || VTOperand.MergeInTypeInfo(IVT.SimpleTy, TP); } // If the scalar type is known, filter out vector types whose element types @@ -511,26 +503,12 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, MVT::SimpleValueType VT = VTOperand.getConcrete(); - TypeSet InputSet(*this); - - // Filter out all the types which don't have the right element type. - for (unsigned i = 0; i != TypeVec.size(); ++i) { - assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); - if (MVT(TypeVec[i]).getVectorElementType().SimpleTy != VT) { - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; - } - } + MadeChange |= EnforceVectorEltTypeIs(VT, TP); - if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! - TP.error("Type inference contradiction found, forcing '" + - InputSet.getName() + "' to have a vector element"); - return false; - } return MadeChange; } -/// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to be a +/// EnforceVectorSubVectorTypeIs - 'this' is now constrained to be a /// vector type specified by VTOperand. bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, TreePattern &TP) { @@ -569,13 +547,13 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, // Only keep types that have less elements than VTOperand. TypeSet InputSet(VTOperand); - for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) { - assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work"); - if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() >= NumElems) { - VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--); - MadeChange = true; - } - } + auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(), + [NumElems](MVT VVT) { + return VVT.getVectorNumElements() >= NumElems; + }); + MadeChange |= I != VTOperand.TypeVec.end(); + VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end()); + if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, forcing '" + InputSet.getName() + "' to have less vector elements than '" + @@ -593,13 +571,13 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, // Only keep types that have more elements than 'this'. TypeSet InputSet(*this); - for (unsigned i = 0; i != TypeVec.size(); ++i) { - assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); - if (MVT(TypeVec[i]).getVectorNumElements() <= NumElems) { - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; - } - } + auto I = std::remove_if(TypeVec.begin(), TypeVec.end(), + [NumElems](MVT VVT) { + return VVT.getVectorNumElements() <= NumElems; + }); + MadeChange |= I != TypeVec.end(); + TypeVec.erase(I, TypeVec.end()); + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, forcing '" + InputSet.getName() + "' to have more vector elements than '" + @@ -611,7 +589,7 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, return MadeChange; } -/// EnforceVectorSameNumElts - 'this' is now constrainted to +/// EnforceVectorSameNumElts - 'this' is now constrained to /// be a vector with same num elements as VTOperand. bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand, TreePattern &TP) { @@ -628,16 +606,16 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand, MVT IVT = getConcrete(); unsigned NumElems = IVT.getVectorNumElements(); - // Only keep types that have same elements as VTOperand. + // Only keep types that have same elements as 'this'. TypeSet InputSet(VTOperand); - for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) { - assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work"); - if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() != NumElems) { - VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--); - MadeChange = true; - } - } + auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(), + [NumElems](MVT VVT) { + return VVT.getVectorNumElements() != NumElems; + }); + MadeChange |= I != VTOperand.TypeVec.end(); + VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end()); + if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, forcing '" + InputSet.getName() + "' to have same number elements as '" + @@ -648,16 +626,16 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand, MVT IVT = VTOperand.getConcrete(); unsigned NumElems = IVT.getVectorNumElements(); - // Only keep types that have same elements as 'this'. + // Only keep types that have same elements as VTOperand. TypeSet InputSet(*this); - for (unsigned i = 0; i != TypeVec.size(); ++i) { - assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); - if (MVT(TypeVec[i]).getVectorNumElements() != NumElems) { - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; - } - } + auto I = std::remove_if(TypeVec.begin(), TypeVec.end(), + [NumElems](MVT VVT) { + return VVT.getVectorNumElements() != NumElems; + }); + MadeChange |= I != TypeVec.end(); + TypeVec.erase(I, TypeVec.end()); + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, forcing '" + InputSet.getName() + "' to have same number elements than '" + @@ -669,15 +647,66 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand, return MadeChange; } +/// EnforceSameSize - 'this' is now constrained to be same size as VTOperand. +bool EEVT::TypeSet::EnforceSameSize(EEVT::TypeSet &VTOperand, + TreePattern &TP) { + if (TP.hasError()) + return false; + + bool MadeChange = false; + + // If we know one of the types, it forces the other type agree. + if (isConcrete()) { + MVT IVT = getConcrete(); + unsigned Size = IVT.getSizeInBits(); + + // Only keep types that have the same size as 'this'. + TypeSet InputSet(VTOperand); + + auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(), + [&](MVT VT) { + return VT.getSizeInBits() != Size; + }); + MadeChange |= I != VTOperand.TypeVec.end(); + VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end()); + + if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have same size as '" + + getName() + "'"); + return false; + } + } else if (VTOperand.isConcrete()) { + MVT IVT = VTOperand.getConcrete(); + unsigned Size = IVT.getSizeInBits(); + + // Only keep types that have the same size as VTOperand. + TypeSet InputSet(*this); + + auto I = std::remove_if(TypeVec.begin(), TypeVec.end(), + [&](MVT VT) { + return VT.getSizeInBits() != Size; + }); + MadeChange |= I != TypeVec.end(); + TypeVec.erase(I, TypeVec.end()); + + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have same size as '" + + VTOperand.getName() + "'"); + return false; + } + } + + return MadeChange; +} + //===----------------------------------------------------------------------===// // Helpers for working with extended types. /// Dependent variable map for CodeGenDAGPattern variant generation typedef std::map<std::string, int> DepVarMap; -/// Const iterator shorthand for DepVarMap -typedef DepVarMap::const_iterator DepVarMap_citer; - static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { if (N->isLeaf()) { if (isa<DefInit>(N->getLeafValue())) @@ -692,9 +721,9 @@ static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) { DepVarMap depcounts; FindDepVarsOf(N, depcounts); - for (DepVarMap_citer i = depcounts.begin(); i != depcounts.end(); ++i) { - if (i->second > 1) // std::pair<std::string, int> - DepVars.insert(i->first); + for (const std::pair<std::string, int> &Pair : depcounts) { + if (Pair.second > 1) + DepVars.insert(Pair.first); } } @@ -705,9 +734,8 @@ static void DumpDepVars(MultipleUseVarSet &DepVars) { DEBUG(errs() << "<empty set>"); } else { DEBUG(errs() << "[ "); - for (MultipleUseVarSet::const_iterator i = DepVars.begin(), - e = DepVars.end(); i != e; ++i) { - DEBUG(errs() << (*i) << " "); + for (const std::string &DepVar : DepVars) { + DEBUG(errs() << DepVar << " "); } DEBUG(errs() << "]"); } @@ -771,7 +799,7 @@ std::string TreePredicateFn::getCodeToRunOnSDNode() const { if (ClassName == "SDNode") Result = " SDNode *N = Node;\n"; else - Result = " " + ClassName + "*N = cast<" + ClassName + ">(Node);\n"; + Result = " auto *N = cast<" + ClassName + ">(Node);\n"; return Result + getPredCode(); } @@ -841,7 +869,7 @@ getPatternComplexity(const CodeGenDAGPatterns &CGP) const { /// pattern's predicates concatenated with "&&" operators. /// std::string PatternToMatch::getPredicateCheck() const { - std::string PredicateCheck; + SmallVector<Record *, 4> PredicateRecs; for (Init *I : Predicates->getValues()) { if (DefInit *Pred = dyn_cast<DefInit>(I)) { Record *Def = Pred->getDef(); @@ -851,13 +879,20 @@ std::string PatternToMatch::getPredicateCheck() const { #endif llvm_unreachable("Unknown predicate type!"); } - if (!PredicateCheck.empty()) - PredicateCheck += " && "; - PredicateCheck += "(" + Def->getValueAsString("CondString") + ")"; + PredicateRecs.push_back(Def); } } + // Sort so that different orders get canonicalized to the same string. + std::sort(PredicateRecs.begin(), PredicateRecs.end(), LessRecord()); + + SmallString<128> PredicateCheck; + for (Record *Pred : PredicateRecs) { + if (!PredicateCheck.empty()) + PredicateCheck += " && "; + PredicateCheck += "(" + Pred->getValueAsString("CondString") + ")"; + } - return PredicateCheck; + return PredicateCheck.str(); } //===----------------------------------------------------------------------===// @@ -912,6 +947,10 @@ SDTypeConstraint::SDTypeConstraint(Record *R) { ConstraintType = SDTCisSameNumEltsAs; x.SDTCisSameNumEltsAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum"); + } else if (R->isSubClassOf("SDTCisSameSizeAs")) { + ConstraintType = SDTCisSameSizeAs; + x.SDTCisSameSizeAs_Info.OtherOperandNum = + R->getValueAsInt("OtherOperandNum"); } else { PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); } @@ -1041,6 +1080,14 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, return OtherNode->getExtType(OResNo). EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP); } + case SDTCisSameSizeAs: { + unsigned OResNo = 0; + TreePatternNode *OtherNode = + getOperandNum(x.SDTCisSameSizeAs_Info.OtherOperandNum, + N, NodeInfo, OResNo); + return OtherNode->getExtType(OResNo). + EnforceSameSize(NodeToApply->getExtType(ResNo), TP); + } } llvm_unreachable("Invalid ConstraintType!"); } @@ -1091,33 +1138,32 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { // Parse the properties. Properties = 0; - std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties"); - for (unsigned i = 0, e = PropList.size(); i != e; ++i) { - if (PropList[i]->getName() == "SDNPCommutative") { + for (Record *Property : R->getValueAsListOfDefs("Properties")) { + if (Property->getName() == "SDNPCommutative") { Properties |= 1 << SDNPCommutative; - } else if (PropList[i]->getName() == "SDNPAssociative") { + } else if (Property->getName() == "SDNPAssociative") { Properties |= 1 << SDNPAssociative; - } else if (PropList[i]->getName() == "SDNPHasChain") { + } else if (Property->getName() == "SDNPHasChain") { Properties |= 1 << SDNPHasChain; - } else if (PropList[i]->getName() == "SDNPOutGlue") { + } else if (Property->getName() == "SDNPOutGlue") { Properties |= 1 << SDNPOutGlue; - } else if (PropList[i]->getName() == "SDNPInGlue") { + } else if (Property->getName() == "SDNPInGlue") { Properties |= 1 << SDNPInGlue; - } else if (PropList[i]->getName() == "SDNPOptInGlue") { + } else if (Property->getName() == "SDNPOptInGlue") { Properties |= 1 << SDNPOptInGlue; - } else if (PropList[i]->getName() == "SDNPMayStore") { + } else if (Property->getName() == "SDNPMayStore") { Properties |= 1 << SDNPMayStore; - } else if (PropList[i]->getName() == "SDNPMayLoad") { + } else if (Property->getName() == "SDNPMayLoad") { Properties |= 1 << SDNPMayLoad; - } else if (PropList[i]->getName() == "SDNPSideEffect") { + } else if (Property->getName() == "SDNPSideEffect") { Properties |= 1 << SDNPSideEffect; - } else if (PropList[i]->getName() == "SDNPMemOperand") { + } else if (Property->getName() == "SDNPMemOperand") { Properties |= 1 << SDNPMemOperand; - } else if (PropList[i]->getName() == "SDNPVariadic") { + } else if (Property->getName() == "SDNPVariadic") { Properties |= 1 << SDNPVariadic; } else { PrintFatalError("Unknown SD Node property '" + - PropList[i]->getName() + "' on node '" + + Property->getName() + "' on node '" + R->getName() + "'!"); } } @@ -1138,15 +1184,15 @@ MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const { "We only work with nodes with zero or one result so far!"); assert(ResNo == 0 && "Only handles single result nodes so far"); - for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) { + for (const SDTypeConstraint &Constraint : TypeConstraints) { // Make sure that this applies to the correct node result. - if (TypeConstraints[i].OperandNo >= NumResults) // FIXME: need value # + if (Constraint.OperandNo >= NumResults) // FIXME: need value # continue; - switch (TypeConstraints[i].ConstraintType) { + switch (Constraint.ConstraintType) { default: break; case SDTypeConstraint::SDTCisVT: - return TypeConstraints[i].x.SDTCisVT_Info.VT; + return Constraint.x.SDTCisVT_Info.VT; case SDTypeConstraint::SDTCisPtrTy: return MVT::iPTR; } @@ -1247,8 +1293,8 @@ void TreePatternNode::print(raw_ostream &OS) const { OS << ")"; } - for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i) - OS << "<<P:" << PredicateFns[i].getFnName() << ">>"; + for (const TreePredicateFn &Pred : PredicateFns) + OS << "<<P:" << Pred.getFnName() << ">>"; if (TransformFn) OS << "<<X:" << TransformFn->getName() << ">>"; if (!getName().empty()) @@ -1315,8 +1361,8 @@ TreePatternNode *TreePatternNode::clone() const { /// RemoveAllTypes - Recursively strip all the types of this tree. void TreePatternNode::RemoveAllTypes() { - for (unsigned i = 0, e = Types.size(); i != e; ++i) - Types[i] = EEVT::TypeSet(); // Reset to unknown type. + // Reset to unknown type. + std::fill(Types.begin(), Types.end(), EEVT::TypeSet()); if (isLeaf()) return; for (unsigned i = 0, e = getNumChildren(); i != e; ++i) getChild(i)->RemoveAllTypes(); @@ -1410,8 +1456,8 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { FragTree->UpdateNodeType(i, getExtType(i), TP); // Transfer in the old predicates. - for (unsigned i = 0, e = getPredicateFns().size(); i != e; ++i) - FragTree->addPredicateFn(getPredicateFns()[i]); + for (const TreePredicateFn &Pred : getPredicateFns()) + FragTree->addPredicateFn(Pred); // Get a new copy of this fragment to stitch into here. //delete this; // FIXME: implement refcounting! @@ -2024,8 +2070,8 @@ void TreePattern::error(const Twine &Msg) { } void TreePattern::ComputeNamedNodes() { - for (unsigned i = 0, e = Trees.size(); i != e; ++i) - ComputeNamedNodes(Trees[i]); + for (TreePatternNode *Tree : Trees) + ComputeNamedNodes(Tree); } void TreePattern::ComputeNamedNodes(TreePatternNode *N) { @@ -2251,53 +2297,52 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { bool MadeChange = true; while (MadeChange) { MadeChange = false; - for (unsigned i = 0, e = Trees.size(); i != e; ++i) { - MadeChange |= Trees[i]->ApplyTypeConstraints(*this, false); - MadeChange |= SimplifyTree(Trees[i]); + for (TreePatternNode *Tree : Trees) { + MadeChange |= Tree->ApplyTypeConstraints(*this, false); + MadeChange |= SimplifyTree(Tree); } // If there are constraints on our named nodes, apply them. - for (StringMap<SmallVector<TreePatternNode*,1> >::iterator - I = NamedNodes.begin(), E = NamedNodes.end(); I != E; ++I) { - SmallVectorImpl<TreePatternNode*> &Nodes = I->second; + for (auto &Entry : NamedNodes) { + SmallVectorImpl<TreePatternNode*> &Nodes = Entry.second; // If we have input named node types, propagate their types to the named // values here. if (InNamedTypes) { - if (!InNamedTypes->count(I->getKey())) { - error("Node '" + std::string(I->getKey()) + + if (!InNamedTypes->count(Entry.getKey())) { + error("Node '" + std::string(Entry.getKey()) + "' in output pattern but not input pattern"); return true; } const SmallVectorImpl<TreePatternNode*> &InNodes = - InNamedTypes->find(I->getKey())->second; + InNamedTypes->find(Entry.getKey())->second; // The input types should be fully resolved by now. - for (unsigned i = 0, e = Nodes.size(); i != e; ++i) { + for (TreePatternNode *Node : Nodes) { // If this node is a register class, and it is the root of the pattern // then we're mapping something onto an input register. We allow // changing the type of the input register in this case. This allows // us to match things like: // def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>; - if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) { - DefInit *DI = dyn_cast<DefInit>(Nodes[i]->getLeafValue()); + if (Node == Trees[0] && Node->isLeaf()) { + DefInit *DI = dyn_cast<DefInit>(Node->getLeafValue()); if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || DI->getDef()->isSubClassOf("RegisterOperand"))) continue; } - assert(Nodes[i]->getNumTypes() == 1 && + assert(Node->getNumTypes() == 1 && InNodes[0]->getNumTypes() == 1 && "FIXME: cannot name multiple result nodes yet"); - MadeChange |= Nodes[i]->UpdateNodeType(0, InNodes[0]->getExtType(0), - *this); + MadeChange |= Node->UpdateNodeType(0, InNodes[0]->getExtType(0), + *this); } } // If there are multiple nodes with the same name, they must all have the // same type. - if (I->second.size() > 1) { + if (Entry.second.size() > 1) { for (unsigned i = 0, e = Nodes.size()-1; i != e; ++i) { TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1]; assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 && @@ -2311,8 +2356,8 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { } bool HasUnresolvedTypes = false; - for (unsigned i = 0, e = Trees.size(); i != e; ++i) - HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType(); + for (const TreePatternNode *Tree : Trees) + HasUnresolvedTypes |= Tree->ContainsUnresolvedType(); return !HasUnresolvedTypes; } @@ -2328,9 +2373,9 @@ void TreePattern::print(raw_ostream &OS) const { if (Trees.size() > 1) OS << "[\n"; - for (unsigned i = 0, e = Trees.size(); i != e; ++i) { + for (const TreePatternNode *Tree : Trees) { OS << "\t"; - Trees[i]->print(OS); + Tree->print(OS); OS << "\n"; } @@ -2425,14 +2470,14 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag"); // First step, parse all of the fragments. - for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { - if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag")) + for (Record *Frag : Fragments) { + if (OutFrags != Frag->isSubClassOf("OutPatFrag")) continue; - DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); + DagInit *Tree = Frag->getValueAsDag("Fragment"); TreePattern *P = - (PatternFragments[Fragments[i]] = llvm::make_unique<TreePattern>( - Fragments[i], Tree, !Fragments[i]->isSubClassOf("OutPatFrag"), + (PatternFragments[Frag] = llvm::make_unique<TreePattern>( + Frag, Tree, !Frag->isSubClassOf("OutPatFrag"), *this)).get(); // Validate the argument list, converting it to set, to discard duplicates. @@ -2443,7 +2488,7 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { P->error("Cannot have unnamed 'node' values in pattern fragment!"); // Parse the operands list. - DagInit *OpsList = Fragments[i]->getValueAsDag("Operands"); + DagInit *OpsList = Frag->getValueAsDag("Operands"); DefInit *OpsOp = dyn_cast<DefInit>(OpsList->getOperator()); // Special cases: ops == outs == ins. Different names are used to // improve readability. @@ -2480,18 +2525,18 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { // If there is a node transformation corresponding to this, keep track of // it. - Record *Transform = Fragments[i]->getValueAsDef("OperandTransform"); + Record *Transform = Frag->getValueAsDef("OperandTransform"); if (!getSDNodeTransform(Transform).second.empty()) // not noop xform? P->getOnlyTree()->setTransformFn(Transform); } // Now that we've parsed all of the tree fragments, do a closure on them so // that there are not references to PatFrags left inside of them. - for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { - if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag")) + for (Record *Frag : Fragments) { + if (OutFrags != Frag->isSubClassOf("OutPatFrag")) continue; - TreePattern &ThePat = *PatternFragments[Fragments[i]]; + TreePattern &ThePat = *PatternFragments[Frag]; ThePat.InlinePatternFragments(); // Infer as many types as possible. Don't worry about it if we don't infer @@ -2815,7 +2860,7 @@ static bool InferFromPattern(CodeGenInstruction &InstInfo, if (InstInfo.mayLoad != PatInfo.mayLoad && !InstInfo.mayLoad_Unset) { // Allow explicitly setting mayLoad = 1, even when the pattern has no loads. - // Some targets translate imediates to loads. + // Some targets translate immediates to loads. if (!InstInfo.mayLoad) { Error = true; PrintError(PatDef->getLoc(), "Pattern doesn't match mayLoad = " + @@ -3065,11 +3110,11 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( void CodeGenDAGPatterns::ParseInstructions() { std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction"); - for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { + for (Record *Instr : Instrs) { ListInit *LI = nullptr; - if (isa<ListInit>(Instrs[i]->getValueInit("Pattern"))) - LI = Instrs[i]->getValueAsListInit("Pattern"); + if (isa<ListInit>(Instr->getValueInit("Pattern"))) + LI = Instr->getValueAsListInit("Pattern"); // If there is no pattern, only collect minimal information about the // instruction for its operand list. We have to assume that there is one @@ -3081,7 +3126,7 @@ void CodeGenDAGPatterns::ParseInstructions() { std::vector<Record*> Results; std::vector<Record*> Operands; - CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); + CodeGenInstruction &InstInfo = Target.getInstruction(Instr); if (InstInfo.Operands.size() != 0) { for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j) @@ -3095,12 +3140,12 @@ void CodeGenDAGPatterns::ParseInstructions() { // Create and insert the instruction. std::vector<Record*> ImpResults; - Instructions.insert(std::make_pair(Instrs[i], + Instructions.insert(std::make_pair(Instr, DAGInstruction(nullptr, Results, Operands, ImpResults))); continue; // no pattern. } - CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]); + CodeGenInstruction &CGI = Target.getInstruction(Instr); const DAGInstruction &DI = parseInstructionPattern(CGI, LI, Instructions); (void)DI; @@ -3108,10 +3153,8 @@ void CodeGenDAGPatterns::ParseInstructions() { } // If we can, convert the instructions to be patterns that are matched! - for (std::map<Record*, DAGInstruction, LessRecordByID>::iterator II = - Instructions.begin(), - E = Instructions.end(); II != E; ++II) { - DAGInstruction &TheInst = II->second; + for (auto &Entry : Instructions) { + DAGInstruction &TheInst = Entry.second; TreePattern *I = TheInst.getPattern(); if (!I) continue; // No pattern. @@ -3126,7 +3169,7 @@ void CodeGenDAGPatterns::ParseInstructions() { SrcPattern = Pattern; } - Record *Instr = II->first; + Record *Instr = Entry.first; AddPatternToMatch(I, PatternToMatch(Instr, Instr->getValueAsListInit("Predicates"), @@ -3187,19 +3230,18 @@ void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, // Scan all of the named values in the destination pattern, rejecting them if // they don't exist in the input pattern. - for (std::map<std::string, NameRecord>::iterator - I = DstNames.begin(), E = DstNames.end(); I != E; ++I) { - if (SrcNames[I->first].first == nullptr) + for (const auto &Entry : DstNames) { + if (SrcNames[Entry.first].first == nullptr) Pattern->error("Pattern has input without matching name in output: $" + - I->first); + Entry.first); } // Scan all of the named values in the source pattern, rejecting them if the // name isn't used in the dest, and isn't used to tie two values together. - for (std::map<std::string, NameRecord>::iterator - I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I) - if (DstNames[I->first].first == nullptr && SrcNames[I->first].second == 1) - Pattern->error("Pattern has dead named input: $" + I->first); + for (const auto &Entry : SrcNames) + if (DstNames[Entry.first].first == nullptr && + SrcNames[Entry.first].second == 1) + Pattern->error("Pattern has dead named input: $" + Entry.first); PatternsToMatch.push_back(PTM); } @@ -3258,31 +3300,29 @@ void CodeGenDAGPatterns::InferInstructionFlags() { // Revisit instructions with undefined flags and no pattern. if (Target.guessInstructionProperties()) { - for (unsigned i = 0, e = Revisit.size(); i != e; ++i) { - CodeGenInstruction &InstInfo = *Revisit[i]; - if (InstInfo.InferredFrom) + for (CodeGenInstruction *InstInfo : Revisit) { + if (InstInfo->InferredFrom) continue; // The mayLoad and mayStore flags default to false. // Conservatively assume hasSideEffects if it wasn't explicit. - if (InstInfo.hasSideEffects_Unset) - InstInfo.hasSideEffects = true; + if (InstInfo->hasSideEffects_Unset) + InstInfo->hasSideEffects = true; } return; } // Complain about any flags that are still undefined. - for (unsigned i = 0, e = Revisit.size(); i != e; ++i) { - CodeGenInstruction &InstInfo = *Revisit[i]; - if (InstInfo.InferredFrom) + for (CodeGenInstruction *InstInfo : Revisit) { + if (InstInfo->InferredFrom) continue; - if (InstInfo.hasSideEffects_Unset) - PrintError(InstInfo.TheDef->getLoc(), + if (InstInfo->hasSideEffects_Unset) + PrintError(InstInfo->TheDef->getLoc(), "Can't infer hasSideEffects from patterns"); - if (InstInfo.mayStore_Unset) - PrintError(InstInfo.TheDef->getLoc(), + if (InstInfo->mayStore_Unset) + PrintError(InstInfo->TheDef->getLoc(), "Can't infer mayStore from patterns"); - if (InstInfo.mayLoad_Unset) - PrintError(InstInfo.TheDef->getLoc(), + if (InstInfo->mayLoad_Unset) + PrintError(InstInfo->TheDef->getLoc(), "Can't infer mayLoad from patterns"); } } @@ -3302,8 +3342,8 @@ void CodeGenDAGPatterns::VerifyInstructionFlags() { unsigned NumSideEffects = 0; unsigned NumStores = 0; unsigned NumLoads = 0; - for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { - const CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); + for (const Record *Instr : Instrs) { + const CodeGenInstruction &InstInfo = Target.getInstruction(Instr); NumSideEffects += InstInfo.hasSideEffects; NumStores += InstInfo.mayStore; NumLoads += InstInfo.mayLoad; @@ -3335,19 +3375,19 @@ void CodeGenDAGPatterns::VerifyInstructionFlags() { continue; ++Errors; - for (unsigned i = 0, e = Msgs.size(); i != e; ++i) - PrintError(PTM.getSrcRecord()->getLoc(), Twine(Msgs[i]) + " on the " + + for (const std::string &Msg : Msgs) + PrintError(PTM.getSrcRecord()->getLoc(), Twine(Msg) + " on the " + (Instrs.size() == 1 ? "instruction" : "output instructions")); // Provide the location of the relevant instruction definitions. - for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { - if (Instrs[i] != PTM.getSrcRecord()) - PrintError(Instrs[i]->getLoc(), "defined here"); - const CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); + for (const Record *Instr : Instrs) { + if (Instr != PTM.getSrcRecord()) + PrintError(Instr->getLoc(), "defined here"); + const CodeGenInstruction &InstInfo = Target.getInstruction(Instr); if (InstInfo.InferredFrom && InstInfo.InferredFrom != InstInfo.TheDef && InstInfo.InferredFrom != PTM.getSrcRecord()) - PrintError(InstInfo.InferredFrom->getLoc(), "inferred from patttern"); + PrintError(InstInfo.InferredFrom->getLoc(), "inferred from pattern"); } } if (Errors) @@ -3386,8 +3426,7 @@ static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) { void CodeGenDAGPatterns::ParsePatterns() { std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern"); - for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { - Record *CurPattern = Patterns[i]; + for (Record *CurPattern : Patterns) { DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch"); // If the pattern references the null_frag, there's nothing to do. @@ -3517,8 +3556,8 @@ static void CombineChildVariants(TreePatternNode *Orig, CodeGenDAGPatterns &CDP, const MultipleUseVarSet &DepVars) { // Make sure that each operand has at least one variant to choose from. - for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) - if (ChildVariants[i].empty()) + for (const auto &Variants : ChildVariants) + if (Variants.empty()) return; // The end result is an all-pairs construction of the resultant pattern. @@ -3529,8 +3568,8 @@ static void CombineChildVariants(TreePatternNode *Orig, #ifndef NDEBUG DEBUG(if (!Idxs.empty()) { errs() << Orig->getOperator()->getName() << ": Idxs = [ "; - for (unsigned i = 0; i < Idxs.size(); ++i) { - errs() << Idxs[i] << " "; + for (unsigned Idx : Idxs) { + errs() << Idx << " "; } errs() << "]\n"; }); @@ -3539,8 +3578,8 @@ static void CombineChildVariants(TreePatternNode *Orig, std::vector<TreePatternNode*> NewChildren; for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) NewChildren.push_back(ChildVariants[i][Idxs[i]]); - TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren, - Orig->getNumTypes()); + auto R = llvm::make_unique<TreePatternNode>( + Orig->getOperator(), NewChildren, Orig->getNumTypes()); // Copy over properties. R->setName(Orig->getName()); @@ -3551,29 +3590,19 @@ static void CombineChildVariants(TreePatternNode *Orig, // If this pattern cannot match, do not include it as a variant. std::string ErrString; - if (!R->canPatternMatch(ErrString, CDP)) { - delete R; - } else { - bool AlreadyExists = false; - - // Scan to see if this pattern has already been emitted. We can get - // duplication due to things like commuting: - // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a) - // which are the same pattern. Ignore the dups. - for (unsigned i = 0, e = OutVariants.size(); i != e; ++i) - if (R->isIsomorphicTo(OutVariants[i], DepVars)) { - AlreadyExists = true; - break; - } - - if (AlreadyExists) - delete R; - else - OutVariants.push_back(R); - } + // Scan to see if this pattern has already been emitted. We can get + // duplication due to things like commuting: + // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a) + // which are the same pattern. Ignore the dups. + if (R->canPatternMatch(ErrString, CDP) && + std::none_of(OutVariants.begin(), OutVariants.end(), + [&](TreePatternNode *Variant) { + return R->isIsomorphicTo(Variant, DepVars); + })) + OutVariants.push_back(R.release()); // Increment indices to the next permutation by incrementing the - // indicies from last index backward, e.g., generate the sequence + // indices from last index backward, e.g., generate the sequence // [0, 0], [0, 1], [1, 0], [1, 1]. int IdxsIdx; for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) { @@ -3724,7 +3753,7 @@ static void GenerateVariantsOf(TreePatternNode *N, // operands are the commutative operands, and there might be more operands // after those. assert(NC >= 3 && - "Commutative intrinsic should have at least 3 childrean!"); + "Commutative intrinsic should have at least 3 children!"); std::vector<std::vector<TreePatternNode*> > Variants; Variants.push_back(ChildVariants[0]); // Intrinsic id. Variants.push_back(ChildVariants[2]); diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h index 9ce3cdfd7bc1..76c9cefea50f 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -132,22 +132,25 @@ namespace EEVT { /// this an other based on this information. bool EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP); - /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type + /// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type /// whose element is VT. bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP); - /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type + /// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type /// whose element is VT. bool EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TreePattern &TP); - /// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to + /// EnforceVectorSubVectorTypeIs - 'this' is now constrained to /// be a vector type VT. bool EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VT, TreePattern &TP); - /// EnforceVectorSameNumElts - 'this' is now constrainted to + /// EnforceVectorSameNumElts - 'this' is now constrained to /// be a vector with same num elements as VT. bool EnforceVectorSameNumElts(EEVT::TypeSet &VT, TreePattern &TP); + /// EnforceSameSize - 'this' is now constrained to be the same size as VT. + bool EnforceSameSize(EEVT::TypeSet &VT, TreePattern &TP); + bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; } bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; } @@ -173,7 +176,7 @@ struct SDTypeConstraint { enum { SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs, SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec, - SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs + SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs, SDTCisSameSizeAs } ConstraintType; union { // The discriminated union. @@ -201,6 +204,9 @@ struct SDTypeConstraint { struct { unsigned OtherOperandNum; } SDTCisSameNumEltsAs_Info; + struct { + unsigned OtherOperandNum; + } SDTCisSameSizeAs_Info; } x; /// ApplyTypeConstraint - Given a node in a pattern, apply this type diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp index e83d5033b182..366e8ec7fac1 100644 --- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp @@ -78,6 +78,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { } else if (Rec->isSubClassOf("Operand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); OperandType = Rec->getValueAsString("OperandType"); + OperandNamespace = Rec->getValueAsString("OperandNamespace"); // If there is an explicit encoder method, use it. EncoderMethod = Rec->getValueAsString("EncoderMethod"); MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); diff --git a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h index f4055571b1c7..7bdb7e1bc537 100644 --- a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h +++ b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h @@ -60,9 +60,10 @@ namespace llvm { IntrinsicSignature IS; // Memory mod/ref behavior of this intrinsic. - enum { + enum ModRefKind { NoMem, ReadArgMem, ReadMem, ReadWriteArgMem, ReadWriteMem - } ModRef; + }; + ModRefKind ModRef; /// This is set to true if the intrinsic is overloaded by its argument /// types. diff --git a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp index 48df4391fe16..f66dd082709b 100644 --- a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp @@ -471,7 +471,7 @@ void MapTableEmitter::emitTablesWithFunc(raw_ostream &OS) { ListInit *ColFields = InstrMapDesc.getColFields(); const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols(); - OS << "// "<< InstrMapDesc.getName() << "\n"; + OS << "// "<< InstrMapDesc.getName() << "\nLLVM_READONLY\n"; OS << "int "<< InstrMapDesc.getName() << "(uint16_t Opcode"; if (ValueCols.size() > 1) { for (Init *CF : ColFields->getValues()) { diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp index c9e6d1d379de..ca316e96a21a 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp @@ -1171,20 +1171,13 @@ void CodeGenRegBank::computeSubRegLaneMasks() { CoveringLanes = ~0u; for (auto &Idx : SubRegIndices) { if (Idx.getComposites().empty()) { + if (Bit > 32) { + PrintFatalError( + Twine("Ran out of lanemask bits to represent subregister ") + + Idx.getName()); + } 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 - // with more than 32 vector lanes. They simply get a limited resolution - // view of lanes beyond the 32nd. - // - // See also the comment for getSubRegIndexLaneMask(). - if (Bit < 31) - ++Bit; - else - // Once bit 31 is shared among multiple leafs, the 'lane' it represents - // is no longer covering its registers. - CoveringLanes &= ~(1u << Bit); + ++Bit; } else { Idx.LaneMask = 0; } @@ -1274,6 +1267,12 @@ void CodeGenRegBank::computeSubRegLaneMasks() { continue; LaneMask |= SubRegIndex.LaneMask; } + + // For classes without any subregisters set LaneMask to ~0u instead of 0. + // This makes it easier for client code to handle classes uniformly. + if (LaneMask == 0) + LaneMask = ~0u; + RegClass.LaneMask = LaneMask; } } @@ -1568,6 +1567,12 @@ void CodeGenRegBank::pruneUnitSets() { && UnitWeight == RegUnits[SuperSet.Units.back()].Weight) { DEBUG(dbgs() << "UnitSet " << SubIdx << " subsumed by " << SuperIdx << "\n"); + // We can pick any of the set names for the merged set. Go for the + // shortest one to avoid picking the name of one of the classes that are + // artificially created by tablegen. So "FPR128_lo" instead of + // "QQQQ_with_qsub3_in_FPR128_lo". + if (RegUnitSets[SubIdx].Name.size() < RegUnitSets[SuperIdx].Name.size()) + RegUnitSets[SuperIdx].Name = RegUnitSets[SubIdx].Name; break; } } diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp index bc27481869fe..c98f62345342 100644 --- a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp @@ -24,15 +24,9 @@ using namespace llvm; #define DEBUG_TYPE "subtarget-emitter" #ifndef NDEBUG -static void dumpIdxVec(const IdxVec &V) { - for (unsigned i = 0, e = V.size(); i < e; ++i) { - dbgs() << V[i] << ", "; - } -} -static void dumpIdxVec(const SmallVectorImpl<unsigned> &V) { - for (unsigned i = 0, e = V.size(); i < e; ++i) { - dbgs() << V[i] << ", "; - } +static void dumpIdxVec(ArrayRef<unsigned> V) { + for (unsigned Idx : V) + dbgs() << Idx << ", "; } #endif @@ -326,9 +320,9 @@ void CodeGenSchedModels::collectSchedRW() { } /// Compute a SchedWrite name from a sequence of writes. -std::string CodeGenSchedModels::genRWName(const IdxVec& Seq, bool IsRead) { +std::string CodeGenSchedModels::genRWName(ArrayRef<unsigned> Seq, bool IsRead) { std::string Name("("); - for (IdxIter I = Seq.begin(), E = Seq.end(); I != E; ++I) { + for (auto I = Seq.begin(), E = Seq.end(); I != E; ++I) { if (I != Seq.begin()) Name += '_'; Name += getSchedRW(*I, IsRead).Name; @@ -457,13 +451,13 @@ void CodeGenSchedModels::expandRWSeqForProc( } // Find the existing SchedWrite that models this sequence of writes. -unsigned CodeGenSchedModels::findRWForSequence(const IdxVec &Seq, +unsigned CodeGenSchedModels::findRWForSequence(ArrayRef<unsigned> Seq, bool IsRead) { std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites; for (std::vector<CodeGenSchedRW>::iterator I = RWVec.begin(), E = RWVec.end(); I != E; ++I) { - if (I->Sequence == Seq) + if (makeArrayRef(I->Sequence) == Seq) return I - RWVec.begin(); } // Index zero reserved for invalid RW. @@ -585,11 +579,11 @@ void CodeGenSchedModels::collectSchedClasses() { /// Find an SchedClass that has been inferred from a per-operand list of /// SchedWrites and SchedReads. unsigned CodeGenSchedModels::findSchedClassIdx(Record *ItinClassDef, - const IdxVec &Writes, - const IdxVec &Reads) const { + ArrayRef<unsigned> Writes, + ArrayRef<unsigned> Reads) const { for (SchedClassIter I = schedClassBegin(), E = schedClassEnd(); I != E; ++I) { - if (I->ItinClassDef == ItinClassDef - && I->Writes == Writes && I->Reads == Reads) { + if (I->ItinClassDef == ItinClassDef && makeArrayRef(I->Writes) == Writes && + makeArrayRef(I->Reads) == Reads) { return I - schedClassBegin(); } } @@ -603,20 +597,22 @@ unsigned CodeGenSchedModels::getSchedClassIdx( return InstrClassMap.lookup(Inst.TheDef); } -std::string CodeGenSchedModels::createSchedClassName( - Record *ItinClassDef, const IdxVec &OperWrites, const IdxVec &OperReads) { +std::string +CodeGenSchedModels::createSchedClassName(Record *ItinClassDef, + ArrayRef<unsigned> OperWrites, + ArrayRef<unsigned> OperReads) { std::string Name; if (ItinClassDef && ItinClassDef->getName() != "NoItinerary") Name = ItinClassDef->getName(); - for (IdxIter WI = OperWrites.begin(), WE = OperWrites.end(); WI != WE; ++WI) { + for (unsigned Idx : OperWrites) { if (!Name.empty()) Name += '_'; - Name += SchedWrites[*WI].Name; + Name += SchedWrites[Idx].Name; } - for (IdxIter RI = OperReads.begin(), RE = OperReads.end(); RI != RE; ++RI) { + for (unsigned Idx : OperReads) { Name += '_'; - Name += SchedReads[*RI].Name; + Name += SchedReads[Idx].Name; } return Name; } @@ -636,10 +632,9 @@ std::string CodeGenSchedModels::createSchedClassName(const RecVec &InstDefs) { /// SchedWrites and SchedReads. ProcIndices contains the set of IDs of /// processors that may utilize this class. unsigned CodeGenSchedModels::addSchedClass(Record *ItinClassDef, - const IdxVec &OperWrites, - const IdxVec &OperReads, - const IdxVec &ProcIndices) -{ + ArrayRef<unsigned> OperWrites, + ArrayRef<unsigned> OperReads, + ArrayRef<unsigned> ProcIndices) { assert(!ProcIndices.empty() && "expect at least one ProcIdx"); unsigned Idx = findSchedClassIdx(ItinClassDef, OperWrites, OperReads); @@ -1322,10 +1317,10 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions, // Create new SchedClasses for the given ReadWrite list. If any of the // ReadWrites refers to a SchedVariant, create a new SchedClass for each variant // of the ReadWrite list, following Aliases if necessary. -void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites, - const IdxVec &OperReads, +void CodeGenSchedModels::inferFromRW(ArrayRef<unsigned> OperWrites, + ArrayRef<unsigned> OperReads, unsigned FromClassIdx, - const IdxVec &ProcIndices) { + ArrayRef<unsigned> ProcIndices) { DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices); dbgs() << ") "); // Create a seed transition with an empty PredTerm and the expanded sequences @@ -1335,9 +1330,9 @@ void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites, LastTransitions.back().ProcIndices.append(ProcIndices.begin(), ProcIndices.end()); - for (IdxIter I = OperWrites.begin(), E = OperWrites.end(); I != E; ++I) { + for (unsigned WriteIdx : OperWrites) { IdxVec WriteSeq; - expandRWSequence(*I, WriteSeq, /*IsRead=*/false); + expandRWSequence(WriteIdx, WriteSeq, /*IsRead=*/false); unsigned Idx = LastTransitions[0].WriteSequences.size(); LastTransitions[0].WriteSequences.resize(Idx + 1); SmallVectorImpl<unsigned> &Seq = LastTransitions[0].WriteSequences[Idx]; @@ -1346,9 +1341,9 @@ void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites, DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") "); } DEBUG(dbgs() << " Reads: "); - for (IdxIter I = OperReads.begin(), E = OperReads.end(); I != E; ++I) { + for (unsigned ReadIdx : OperReads) { IdxVec ReadSeq; - expandRWSequence(*I, ReadSeq, /*IsRead=*/true); + expandRWSequence(ReadIdx, ReadSeq, /*IsRead=*/true); unsigned Idx = LastTransitions[0].ReadSequences.size(); LastTransitions[0].ReadSequences.resize(Idx + 1); SmallVectorImpl<unsigned> &Seq = LastTransitions[0].ReadSequences[Idx]; @@ -1552,20 +1547,16 @@ void CodeGenSchedModels::collectItinProcResources(Record *ItinClassDef) { } void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead, - const IdxVec &ProcIndices) { + ArrayRef<unsigned> ProcIndices) { const CodeGenSchedRW &SchedRW = getSchedRW(RWIdx, IsRead); if (SchedRW.TheDef) { if (!IsRead && SchedRW.TheDef->isSubClassOf("SchedWriteRes")) { - for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end(); - PI != PE; ++PI) { - addWriteRes(SchedRW.TheDef, *PI); - } + for (unsigned Idx : ProcIndices) + addWriteRes(SchedRW.TheDef, Idx); } else if (IsRead && SchedRW.TheDef->isSubClassOf("SchedReadAdvance")) { - for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end(); - PI != PE; ++PI) { - addReadAdvance(SchedRW.TheDef, *PI); - } + for (unsigned Idx : ProcIndices) + addReadAdvance(SchedRW.TheDef, Idx); } } for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end(); @@ -1590,15 +1581,15 @@ void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead, } // Collect resources for a set of read/write types and processor indices. -void CodeGenSchedModels::collectRWResources(const IdxVec &Writes, - const IdxVec &Reads, - const IdxVec &ProcIndices) { +void CodeGenSchedModels::collectRWResources(ArrayRef<unsigned> Writes, + ArrayRef<unsigned> Reads, + ArrayRef<unsigned> ProcIndices) { - for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) - collectRWResources(*WI, /*IsRead=*/false, ProcIndices); + for (unsigned Idx : Writes) + collectRWResources(Idx, /*IsRead=*/false, ProcIndices); - for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI) - collectRWResources(*RI, /*IsRead=*/true, ProcIndices); + for (unsigned Idx : Reads) + collectRWResources(Idx, /*IsRead=*/true, ProcIndices); } diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.h b/contrib/llvm/utils/TableGen/CodeGenSchedule.h index e5241b9d5fda..f5c50c992a92 100644 --- a/contrib/llvm/utils/TableGen/CodeGenSchedule.h +++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.h @@ -72,10 +72,10 @@ struct CodeGenSchedRW { IsSequence = Def->isSubClassOf("WriteSequence"); } - CodeGenSchedRW(unsigned Idx, bool Read, const IdxVec &Seq, + CodeGenSchedRW(unsigned Idx, bool Read, ArrayRef<unsigned> Seq, const std::string &Name) - : Index(Idx), Name(Name), TheDef(nullptr), IsRead(Read), IsAlias(false), - HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) { + : Index(Idx), Name(Name), TheDef(nullptr), IsRead(Read), IsAlias(false), + HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) { assert(Sequence.size() > 1 && "implied sequence needs >1 RWs"); } @@ -144,8 +144,9 @@ struct CodeGenSchedClass { CodeGenSchedClass(): Index(0), ItinClassDef(nullptr) {} - bool isKeyEqual(Record *IC, const IdxVec &W, const IdxVec &R) { - return ItinClassDef == IC && Writes == W && Reads == R; + bool isKeyEqual(Record *IC, ArrayRef<unsigned> W, ArrayRef<unsigned> R) { + return ItinClassDef == IC && makeArrayRef(Writes) == W && + makeArrayRef(Reads) == R; } // Is this class generated from a variants if existing classes? Instructions @@ -256,18 +257,16 @@ public: class_iterator classes_end() { return SchedClasses.end(); } const_class_iterator classes_end() const { return SchedClasses.end(); } iterator_range<class_iterator> classes() { - return iterator_range<class_iterator>(classes_begin(), classes_end()); + return make_range(classes_begin(), classes_end()); } iterator_range<const_class_iterator> classes() const { - return iterator_range<const_class_iterator>(classes_begin(), classes_end()); + return make_range(classes_begin(), classes_end()); } iterator_range<class_iterator> explicit_classes() { - return iterator_range<class_iterator>( - classes_begin(), classes_begin() + NumInstrSchedClasses); + return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses); } iterator_range<const_class_iterator> explicit_classes() const { - return iterator_range<const_class_iterator>( - classes_begin(), classes_begin() + NumInstrSchedClasses); + return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses); } Record *getModelOrItinDef(Record *ProcDef) const { @@ -363,14 +362,14 @@ public: void expandRWSeqForProc(unsigned RWIdx, IdxVec &RWSeq, bool IsRead, const CodeGenProcModel &ProcModel) const; - unsigned addSchedClass(Record *ItinDef, const IdxVec &OperWrites, - const IdxVec &OperReads, const IdxVec &ProcIndices); + unsigned addSchedClass(Record *ItinDef, ArrayRef<unsigned> OperWrites, + ArrayRef<unsigned> OperReads, + ArrayRef<unsigned> ProcIndices); unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead); - unsigned findSchedClassIdx(Record *ItinClassDef, - const IdxVec &Writes, - const IdxVec &Reads) const; + unsigned findSchedClassIdx(Record *ItinClassDef, ArrayRef<unsigned> Writes, + ArrayRef<unsigned> Reads) const; Record *findProcResUnits(Record *ProcResKind, const CodeGenProcModel &PM) const; @@ -383,14 +382,14 @@ private: void collectSchedRW(); - std::string genRWName(const IdxVec& Seq, bool IsRead); - unsigned findRWForSequence(const IdxVec &Seq, bool IsRead); + std::string genRWName(ArrayRef<unsigned> Seq, bool IsRead); + unsigned findRWForSequence(ArrayRef<unsigned> Seq, bool IsRead); void collectSchedClasses(); std::string createSchedClassName(Record *ItinClassDef, - const IdxVec &OperWrites, - const IdxVec &OperReads); + ArrayRef<unsigned> OperWrites, + ArrayRef<unsigned> OperReads); std::string createSchedClassName(const RecVec &InstDefs); void createInstRWClass(Record *InstRWDef); @@ -400,8 +399,8 @@ private: void inferSchedClasses(); - void inferFromRW(const IdxVec &OperWrites, const IdxVec &OperReads, - unsigned FromClassIdx, const IdxVec &ProcIndices); + void inferFromRW(ArrayRef<unsigned> OperWrites, ArrayRef<unsigned> OperReads, + unsigned FromClassIdx, ArrayRef<unsigned> ProcIndices); void inferFromItinClass(Record *ItinClassDef, unsigned FromClassIdx); void inferFromInstRWs(unsigned SCIdx); @@ -413,10 +412,10 @@ private: void collectItinProcResources(Record *ItinClassDef); void collectRWResources(unsigned RWIdx, bool IsRead, - const IdxVec &ProcIndices); + ArrayRef<unsigned> ProcIndices); - void collectRWResources(const IdxVec &Writes, const IdxVec &Reads, - const IdxVec &ProcIndices); + void collectRWResources(ArrayRef<unsigned> Writes, ArrayRef<unsigned> Reads, + ArrayRef<unsigned> ProcIndices); void addProcResource(Record *ProcResourceKind, CodeGenProcModel &PM); diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp index 661975ecb202..aaad4225ace8 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp @@ -76,6 +76,8 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v16i1: return "MVT::v16i1"; case MVT::v32i1: return "MVT::v32i1"; case MVT::v64i1: return "MVT::v64i1"; + case MVT::v512i1: return "MVT::v512i1"; + case MVT::v1024i1: return "MVT::v1024i1"; case MVT::v1i8: return "MVT::v1i8"; case MVT::v2i8: return "MVT::v2i8"; case MVT::v4i8: return "MVT::v4i8"; @@ -83,22 +85,29 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v16i8: return "MVT::v16i8"; case MVT::v32i8: return "MVT::v32i8"; case MVT::v64i8: return "MVT::v64i8"; + case MVT::v128i8: return "MVT::v128i8"; + case MVT::v256i8: return "MVT::v256i8"; case MVT::v1i16: return "MVT::v1i16"; case MVT::v2i16: return "MVT::v2i16"; case MVT::v4i16: return "MVT::v4i16"; case MVT::v8i16: return "MVT::v8i16"; case MVT::v16i16: return "MVT::v16i16"; case MVT::v32i16: return "MVT::v32i16"; + case MVT::v64i16: return "MVT::v64i16"; + case MVT::v128i16: return "MVT::v128i16"; case MVT::v1i32: return "MVT::v1i32"; case MVT::v2i32: return "MVT::v2i32"; case MVT::v4i32: return "MVT::v4i32"; case MVT::v8i32: return "MVT::v8i32"; case MVT::v16i32: return "MVT::v16i32"; + case MVT::v32i32: return "MVT::v32i32"; + case MVT::v64i32: return "MVT::v64i32"; case MVT::v1i64: return "MVT::v1i64"; case MVT::v2i64: return "MVT::v2i64"; case MVT::v4i64: return "MVT::v4i64"; case MVT::v8i64: return "MVT::v8i64"; case MVT::v16i64: return "MVT::v16i64"; + case MVT::v32i64: return "MVT::v32i64"; case MVT::v1i128: return "MVT::v1i128"; case MVT::v2f16: return "MVT::v2f16"; case MVT::v4f16: return "MVT::v4f16"; @@ -112,6 +121,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v2f64: return "MVT::v2f64"; case MVT::v4f64: return "MVT::v4f64"; case MVT::v8f64: return "MVT::v8f64"; + case MVT::token: return "MVT::token"; case MVT::Metadata: return "MVT::Metadata"; case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; @@ -252,7 +262,7 @@ void CodeGenTarget::ReadLegalValueTypes() const { LegalValueTypes.insert(LegalValueTypes.end(), RC.VTs.begin(), RC.VTs.end()); // Remove duplicates. - std::sort(LegalValueTypes.begin(), LegalValueTypes.end()); + array_pod_sort(LegalValueTypes.begin(), LegalValueTypes.end()); LegalValueTypes.erase(std::unique(LegalValueTypes.begin(), LegalValueTypes.end()), LegalValueTypes.end()); diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h index 24b38514260c..cf4a0bbe5bd9 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.h +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h @@ -173,7 +173,7 @@ public: inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();} inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); } iterator_range<inst_iterator> instructions() const { - return iterator_range<inst_iterator>(inst_begin(), inst_end()); + return make_range(inst_begin(), inst_end()); } diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp index 4659dc157338..26f53dca6361 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/TableGen/Record.h" @@ -36,6 +37,10 @@ class MatcherTableEmitter { DenseMap<TreePattern *, unsigned> NodePredicateMap; std::vector<TreePredicateFn> NodePredicates; + + // We de-duplicate the predicates by code string, and use this map to track + // all the patterns with "identical" predicates. + StringMap<TinyPtrVector<TreePattern *>> NodePredicatesByCodeToRun; StringMap<unsigned> PatternPredicateMap; std::vector<std::string> PatternPredicates; @@ -62,10 +67,23 @@ private: formatted_raw_ostream &OS); unsigned getNodePredicate(TreePredicateFn Pred) { - unsigned &Entry = NodePredicateMap[Pred.getOrigPatFragRecord()]; + TreePattern *TP = Pred.getOrigPatFragRecord(); + unsigned &Entry = NodePredicateMap[TP]; if (Entry == 0) { - NodePredicates.push_back(Pred); - Entry = NodePredicates.size(); + TinyPtrVector<TreePattern *> &SameCodePreds = + NodePredicatesByCodeToRun[Pred.getCodeToRunOnSDNode()]; + if (SameCodePreds.empty()) { + // We've never seen a predicate with the same code: allocate an entry. + NodePredicates.push_back(Pred); + Entry = NodePredicates.size(); + } else { + // We did see an identical predicate: re-use it. + Entry = NodePredicateMap[SameCodePreds.front()]; + assert(Entry != 0); + } + // In both cases, we've never seen this particular predicate before, so + // mark it in the list of predicates sharing the same code. + SameCodePreds.push_back(TP); } return Entry-1; } @@ -625,13 +643,6 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { } // Emit Node predicates. - // FIXME: Annoyingly, these are stored by name, which we never even emit. Yay? - StringMap<TreePattern*> PFsByName; - - for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end(); - I != E; ++I) - PFsByName[I->first->getName()] = I->second.get(); - if (!NodePredicates.empty()) { OS << "bool CheckNodePredicate(SDNode *Node,\n"; OS << " unsigned PredNo) const override {\n"; @@ -642,7 +653,10 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { TreePredicateFn PredFn = NodePredicates[i]; assert(!PredFn.isAlwaysTrue() && "No code in this predicate"); - OS << " case " << i << ": { // " << NodePredicates[i].getFnName() <<'\n'; + OS << " case " << i << ": { \n"; + for (auto *SimilarPred : + NodePredicatesByCodeToRun[PredFn.getCodeToRunOnSDNode()]) + OS << " // " << TreePredicateFn(SimilarPred).getFnName() <<'\n'; OS << PredFn.getCodeToRunOnSDNode() << "\n }\n"; } diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp index 5060b6e9ce7c..77afff7ab5c2 100644 --- a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp @@ -15,16 +15,83 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "dfa-emitter" + #include "CodeGenTarget.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" +#include "llvm/Support/Debug.h" #include <list> #include <map> #include <string> +#include <queue> using namespace llvm; +// -------------------------------------------------------------------- +// Definitions shared between DFAPacketizer.cpp and DFAPacketizerEmitter.cpp + +// DFA_MAX_RESTERMS * DFA_MAX_RESOURCES must fit within sizeof DFAInput. +// This is verified in DFAPacketizer.cpp:DFAPacketizer::DFAPacketizer. +// +// e.g. terms x resource bit combinations that fit in uint32_t: +// 4 terms x 8 bits = 32 bits +// 3 terms x 10 bits = 30 bits +// 2 terms x 16 bits = 32 bits +// +// e.g. terms x resource bit combinations that fit in uint64_t: +// 8 terms x 8 bits = 64 bits +// 7 terms x 9 bits = 63 bits +// 6 terms x 10 bits = 60 bits +// 5 terms x 12 bits = 60 bits +// 4 terms x 16 bits = 64 bits <--- current +// 3 terms x 21 bits = 63 bits +// 2 terms x 32 bits = 64 bits +// +#define DFA_MAX_RESTERMS 4 // The max # of AND'ed resource terms. +#define DFA_MAX_RESOURCES 16 // The max # of resource bits in one term. + +typedef uint64_t DFAInput; +typedef int64_t DFAStateInput; +#define DFA_TBLTYPE "int64_t" // For generating DFAStateInputTable. + +namespace { + DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) { + return (Inp << DFA_MAX_RESOURCES) | FuncUnits; + } + + /// Return the DFAInput for an instruction class input vector. + /// This function is used in both DFAPacketizer.cpp and in + /// DFAPacketizerEmitter.cpp. + DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) { + DFAInput InsnInput = 0; + assert ((InsnClass.size() <= DFA_MAX_RESTERMS) && + "Exceeded maximum number of DFA terms"); + for (auto U : InsnClass) + InsnInput = addDFAFuncUnits(InsnInput, U); + return InsnInput; + } +} +// -------------------------------------------------------------------- + +#ifndef NDEBUG +// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter". +// +// dbgsInsnClass - When debugging, print instruction class stages. +// +void dbgsInsnClass(const std::vector<unsigned> &InsnClass); +// +// dbgsStateInfo - When debugging, print the set of state info. +// +void dbgsStateInfo(const std::set<unsigned> &stateInfo); +// +// dbgsIndent - When debugging, indent by the specified amount. +// +void dbgsIndent(unsigned indent); +#endif + // // class DFAPacketizerEmitter: class that generates and prints out the DFA // for resource tracking. @@ -37,20 +104,48 @@ private: // allInsnClasses is the set of all possible resources consumed by an // InstrStage. // - DenseSet<unsigned> allInsnClasses; + std::vector<std::vector<unsigned>> allInsnClasses; RecordKeeper &Records; public: DFAPacketizerEmitter(RecordKeeper &R); // - // collectAllInsnClasses: Populate allInsnClasses which is a set of units + // collectAllFuncUnits - Construct a map of function unit names to bits. + // + int collectAllFuncUnits(std::vector<Record*> &ProcItinList, + std::map<std::string, unsigned> &FUNameToBitsMap, + int &maxResources, + raw_ostream &OS); + + // + // collectAllComboFuncs - Construct a map from a combo function unit bit to + // the bits of all included functional units. + // + int collectAllComboFuncs(std::vector<Record*> &ComboFuncList, + std::map<std::string, unsigned> &FUNameToBitsMap, + std::map<unsigned, unsigned> &ComboBitToBitsMap, + raw_ostream &OS); + + // + // collectOneInsnClass - Populate allInsnClasses with one instruction class. + // + int collectOneInsnClass(const std::string &ProcName, + std::vector<Record*> &ProcItinList, + std::map<std::string, unsigned> &FUNameToBitsMap, + Record *ItinData, + raw_ostream &OS); + + // + // collectAllInsnClasses - Populate allInsnClasses which is a set of units // used in each stage. // - void collectAllInsnClasses(const std::string &Name, - Record *ItinData, - unsigned &NStages, - raw_ostream &OS); + int collectAllInsnClasses(const std::string &ProcName, + std::vector<Record*> &ProcItinList, + std::map<std::string, unsigned> &FUNameToBitsMap, + std::vector<Record*> &ItinDataList, + int &maxStages, + raw_ostream &OS); void run(raw_ostream &OS); }; @@ -87,7 +182,7 @@ class State { const int stateNum; mutable bool isInitial; mutable std::set<unsigned> stateInfo; - typedef std::map<unsigned, const State *> TransitionMap; + typedef std::map<std::vector<unsigned>, const State *> TransitionMap; mutable TransitionMap Transitions; State(); @@ -97,28 +192,47 @@ class State { } // - // canAddInsnClass - Returns true if an instruction of type InsnClass is a - // valid transition from this state, i.e., can an instruction of type InsnClass - // be added to the packet represented by this state. + // canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass + // may be a valid transition from this state i.e., can an instruction of type + // InsnClass be added to the packet represented by this state. + // + // Note that for multiple stages, this quick check does not take into account + // any possible resource competition between the stages themselves. That is + // enforced in AddInsnClassStages which checks the cross product of all + // stages for resource availability (which is a more involved check). + // + bool canMaybeAddInsnClass(std::vector<unsigned> &InsnClass, + std::map<unsigned, unsigned> &ComboBitToBitsMap) const; + // + // AddInsnClass - Return all combinations of resource reservation + // which are possible from this state (PossibleStates). // // PossibleStates is the set of valid resource states that ensue from valid // transitions. // - bool canAddInsnClass(unsigned InsnClass) const; + void AddInsnClass(std::vector<unsigned> &InsnClass, + std::map<unsigned, unsigned> &ComboBitToBitsMap, + std::set<unsigned> &PossibleStates) const; // - // AddInsnClass - Return all combinations of resource reservation + // AddInsnClassStages - Return all combinations of resource reservation + // resulting from the cross product of all stages for this InsnClass // which are possible from this state (PossibleStates). // - void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates) const; - // + void AddInsnClassStages(std::vector<unsigned> &InsnClass, + std::map<unsigned, unsigned> &ComboBitToBitsMap, + unsigned chkstage, unsigned numstages, + unsigned prevState, unsigned origState, + DenseSet<unsigned> &VisitedResourceStates, + std::set<unsigned> &PossibleStates) const; + // // addTransition - Add a transition from this state given the input InsnClass // - void addTransition(unsigned InsnClass, const State *To) const; + void addTransition(std::vector<unsigned> InsnClass, const State *To) const; // // hasTransition - Returns true if there is a transition from this state // given the input InsnClass // - bool hasTransition(unsigned InsnClass) const; + bool hasTransition(std::vector<unsigned> InsnClass) const; }; } // End anonymous namespace. @@ -144,10 +258,54 @@ public: // // writeTable: Print out a table representing the DFA. // - void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName); + void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName, + int numInsnClasses = 0, + int maxResources = 0, int numCombos = 0, int maxStages = 0); }; } // End anonymous namespace. +#ifndef NDEBUG +// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter". +// +// dbgsInsnClass - When debugging, print instruction class stages. +// +void dbgsInsnClass(const std::vector<unsigned> &InsnClass) { + DEBUG(dbgs() << "InsnClass: "); + for (unsigned i = 0; i < InsnClass.size(); ++i) { + if (i > 0) { + DEBUG(dbgs() << ", "); + } + DEBUG(dbgs() << "0x" << utohexstr(InsnClass[i])); + } + DFAInput InsnInput = getDFAInsnInput(InsnClass); + DEBUG(dbgs() << " (input: 0x" << utohexstr(InsnInput) << ")"); +} + +// +// dbgsStateInfo - When debugging, print the set of state info. +// +void dbgsStateInfo(const std::set<unsigned> &stateInfo) { + DEBUG(dbgs() << "StateInfo: "); + unsigned i = 0; + for (std::set<unsigned>::iterator SI = stateInfo.begin(); + SI != stateInfo.end(); ++SI, ++i) { + unsigned thisState = *SI; + if (i > 0) { + DEBUG(dbgs() << ", "); + } + DEBUG(dbgs() << "0x" << utohexstr(thisState)); + } +} + +// +// dbgsIndent - When debugging, indent by the specified amount. +// +void dbgsIndent(unsigned indent) { + for (unsigned i = 0; i < indent; ++i) { + DEBUG(dbgs() << " "); + } +} +#endif // // Constructors and destructors for State and DFA @@ -157,10 +315,11 @@ State::State() : DFA::DFA(): currentState(nullptr) {} -// +// // addTransition - Add a transition from this state given the input InsnClass // -void State::addTransition(unsigned InsnClass, const State *To) const { +void State::addTransition(std::vector<unsigned> InsnClass, const State *To) + const { assert(!Transitions.count(InsnClass) && "Cannot have multiple transitions for the same input"); Transitions[InsnClass] = To; @@ -170,7 +329,7 @@ void State::addTransition(unsigned InsnClass, const State *To) const { // hasTransition - Returns true if there is a transition from this state // given the input InsnClass // -bool State::hasTransition(unsigned InsnClass) const { +bool State::hasTransition(std::vector<unsigned> InsnClass) const { return Transitions.count(InsnClass) > 0; } @@ -178,61 +337,170 @@ bool State::hasTransition(unsigned InsnClass) const { // AddInsnClass - Return all combinations of resource reservation // which are possible from this state (PossibleStates). // -void State::AddInsnClass(unsigned InsnClass, - std::set<unsigned> &PossibleStates) const { +// PossibleStates is the set of valid resource states that ensue from valid +// transitions. +// +void State::AddInsnClass(std::vector<unsigned> &InsnClass, + std::map<unsigned, unsigned> &ComboBitToBitsMap, + std::set<unsigned> &PossibleStates) const { // // Iterate over all resource states in currentState. // + unsigned numstages = InsnClass.size(); + assert((numstages > 0) && "InsnClass has no stages"); for (std::set<unsigned>::iterator SI = stateInfo.begin(); SI != stateInfo.end(); ++SI) { unsigned thisState = *SI; - // - // Iterate over all possible resources used in InsnClass. - // For ex: for InsnClass = 0x11, all resources = {0x01, 0x10}. - // - DenseSet<unsigned> VisitedResourceStates; - for (unsigned int j = 0; j < sizeof(InsnClass) * 8; ++j) { - if ((0x1 << j) & InsnClass) { - // - // For each possible resource used in InsnClass, generate the - // resource state if that resource was used. - // - unsigned ResultingResourceState = thisState | (0x1 << j); + + DEBUG(dbgs() << " thisState: 0x" << utohexstr(thisState) << "\n"); + AddInsnClassStages(InsnClass, ComboBitToBitsMap, + numstages - 1, numstages, + thisState, thisState, + VisitedResourceStates, PossibleStates); + } +} + +void State::AddInsnClassStages(std::vector<unsigned> &InsnClass, + std::map<unsigned, unsigned> &ComboBitToBitsMap, + unsigned chkstage, unsigned numstages, + unsigned prevState, unsigned origState, + DenseSet<unsigned> &VisitedResourceStates, + std::set<unsigned> &PossibleStates) const { + + assert((chkstage < numstages) && "AddInsnClassStages: stage out of range"); + unsigned thisStage = InsnClass[chkstage]; + + DEBUG({ + dbgsIndent((1 + numstages - chkstage) << 1); + dbgs() << "AddInsnClassStages " << chkstage << " (0x" + << utohexstr(thisStage) << ") from "; + dbgsInsnClass(InsnClass); + dbgs() << "\n"; + }); + + // + // Iterate over all possible resources used in thisStage. + // For ex: for thisStage = 0x11, all resources = {0x01, 0x10}. + // + for (unsigned int j = 0; j < DFA_MAX_RESOURCES; ++j) { + unsigned resourceMask = (0x1 << j); + if (resourceMask & thisStage) { + unsigned combo = ComboBitToBitsMap[resourceMask]; + if (combo && ((~prevState & combo) != combo)) { + DEBUG(dbgs() << "\tSkipped Add 0x" << utohexstr(prevState) + << " - combo op 0x" << utohexstr(resourceMask) + << " (0x" << utohexstr(combo) <<") cannot be scheduled\n"); + continue; + } + // + // For each possible resource used in thisStage, generate the + // resource state if that resource was used. + // + unsigned ResultingResourceState = prevState | resourceMask | combo; + DEBUG({ + dbgsIndent((2 + numstages - chkstage) << 1); + dbgs() << "0x" << utohexstr(prevState) + << " | 0x" << utohexstr(resourceMask); + if (combo) + dbgs() << " | 0x" << utohexstr(combo); + dbgs() << " = 0x" << utohexstr(ResultingResourceState) << " "; + }); + + // + // If this is the final stage for this class + // + if (chkstage == 0) { // // Check if the resulting resource state can be accommodated in this // packet. - // We compute ResultingResourceState OR thisState. - // If the result of the OR is different than thisState, it implies + // We compute resource OR prevState (originally started as origState). + // If the result of the OR is different than origState, it implies // that there is at least one resource that can be used to schedule - // InsnClass in the current packet. + // thisStage in the current packet. // Insert ResultingResourceState into PossibleStates only if we haven't // processed ResultingResourceState before. // - if ((ResultingResourceState != thisState) && - (VisitedResourceStates.count(ResultingResourceState) == 0)) { - VisitedResourceStates.insert(ResultingResourceState); - PossibleStates.insert(ResultingResourceState); + if (ResultingResourceState != prevState) { + if (VisitedResourceStates.count(ResultingResourceState) == 0) { + VisitedResourceStates.insert(ResultingResourceState); + PossibleStates.insert(ResultingResourceState); + DEBUG(dbgs() << "\tResultingResourceState: 0x" + << utohexstr(ResultingResourceState) << "\n"); + } else { + DEBUG(dbgs() << "\tSkipped Add - state already seen\n"); + } + } else { + DEBUG(dbgs() << "\tSkipped Add - no final resources available\n"); + } + } else { + // + // If the current resource can be accommodated, check the next + // stage in InsnClass for available resources. + // + if (ResultingResourceState != prevState) { + DEBUG(dbgs() << "\n"); + AddInsnClassStages(InsnClass, ComboBitToBitsMap, + chkstage - 1, numstages, + ResultingResourceState, origState, + VisitedResourceStates, PossibleStates); + } else { + DEBUG(dbgs() << "\tSkipped Add - no resources available\n"); } } } } - } // -// canAddInsnClass - Quickly verifies if an instruction of type InsnClass is a -// valid transition from this state i.e., can an instruction of type InsnClass -// be added to the packet represented by this state. +// canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass +// may be a valid transition from this state i.e., can an instruction of type +// InsnClass be added to the packet represented by this state. +// +// Note that this routine is performing conservative checks that can be +// quickly executed acting as a filter before calling AddInsnClassStages. +// Any cases allowed through here will be caught later in AddInsnClassStages +// which performs the more expensive exact check. // -bool State::canAddInsnClass(unsigned InsnClass) const { +bool State::canMaybeAddInsnClass(std::vector<unsigned> &InsnClass, + std::map<unsigned, unsigned> &ComboBitToBitsMap) const { for (std::set<unsigned>::const_iterator SI = stateInfo.begin(); SI != stateInfo.end(); ++SI) { - if (~*SI & InsnClass) + + // Check to see if all required resources are available. + bool available = true; + + // Inspect each stage independently. + // note: This is a conservative check as we aren't checking for + // possible resource competition between the stages themselves + // The full cross product is examined later in AddInsnClass. + for (unsigned i = 0; i < InsnClass.size(); ++i) { + unsigned resources = *SI; + if ((~resources & InsnClass[i]) == 0) { + available = false; + break; + } + // Make sure _all_ resources for a combo function are available. + // note: This is a quick conservative check as it won't catch an + // unscheduleable combo if this stage is an OR expression + // containing a combo. + // These cases are caught later in AddInsnClass. + unsigned combo = ComboBitToBitsMap[InsnClass[i]]; + if (combo && ((~resources & combo) != combo)) { + DEBUG(dbgs() << "\tSkipped canMaybeAdd 0x" << utohexstr(resources) + << " - combo op 0x" << utohexstr(InsnClass[i]) + << " (0x" << utohexstr(combo) <<") cannot be scheduled\n"); + available = false; + break; + } + } + + if (available) { return true; + } } return false; } @@ -244,7 +512,6 @@ const State &DFA::newState() { return *IterPair.first; } - int State::currentStateNum = 0; DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R): @@ -263,57 +530,100 @@ DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R): // the ith state. // // -void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { - static const std::string SentinelEntry = "{-1, -1}"; - DFA::StateSet::iterator SI = states.begin(); +void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName, + int numInsnClasses, + int maxResources, int numCombos, int maxStages) { + + unsigned numStates = states.size(); + + DEBUG(dbgs() << "-----------------------------------------------------------------------------\n"); + DEBUG(dbgs() << "writeTableAndAPI\n"); + DEBUG(dbgs() << "Total states: " << numStates << "\n"); + + OS << "namespace llvm {\n"; + + OS << "\n// Input format:\n"; + OS << "#define DFA_MAX_RESTERMS " << DFA_MAX_RESTERMS + << "\t// maximum AND'ed resource terms\n"; + OS << "#define DFA_MAX_RESOURCES " << DFA_MAX_RESOURCES + << "\t// maximum resource bits in one term\n"; + + OS << "\n// " << TargetName << "DFAStateInputTable[][2] = " + << "pairs of <Input, NextState> for all valid\n"; + OS << "// transitions.\n"; + OS << "// " << numStates << "\tstates\n"; + OS << "// " << numInsnClasses << "\tinstruction classes\n"; + OS << "// " << maxResources << "\tresources max\n"; + OS << "// " << numCombos << "\tcombo resources\n"; + OS << "// " << maxStages << "\tstages max\n"; + OS << "const " << DFA_TBLTYPE << " " + << TargetName << "DFAStateInputTable[][2] = {\n"; + // This table provides a map to the beginning of the transitions for State s // in DFAStateInputTable. - std::vector<int> StateEntry(states.size()); - - OS << "namespace llvm {\n\n"; - OS << "const int " << TargetName << "DFAStateInputTable[][2] = {\n"; + std::vector<int> StateEntry(numStates+1); + static const std::string SentinelEntry = "{-1, -1}"; // Tracks the total valid transitions encountered so far. It is used // to construct the StateEntry table. int ValidTransitions = 0; - for (unsigned i = 0; i < states.size(); ++i, ++SI) { + DFA::StateSet::iterator SI = states.begin(); + for (unsigned i = 0; i < numStates; ++i, ++SI) { assert ((SI->stateNum == (int) i) && "Mismatch in state numbers"); StateEntry[i] = ValidTransitions; for (State::TransitionMap::iterator II = SI->Transitions.begin(), IE = SI->Transitions.end(); II != IE; ++II) { - OS << "{" << II->first << ", " + OS << "{0x" << utohexstr(getDFAInsnInput(II->first)) << ", " << II->second->stateNum - << "}, "; + << "},\t"; } ValidTransitions += SI->Transitions.size(); // If there are no valid transitions from this stage, we need a sentinel // transition. if (ValidTransitions == StateEntry[i]) { - OS << SentinelEntry << ","; + OS << SentinelEntry << ",\t"; ++ValidTransitions; } + OS << " // state " << i << ": " << StateEntry[i]; + if (StateEntry[i] != (ValidTransitions-1)) { // More than one transition. + OS << "-" << (ValidTransitions-1); + } OS << "\n"; } // Print out a sentinel entry at the end of the StateInputTable. This is // needed to iterate over StateInputTable in DFAPacketizer::ReadTable() - OS << SentinelEntry << "\n"; - + OS << SentinelEntry << "\t"; + OS << " // state " << numStates << ": " << ValidTransitions; + OS << "\n"; + OS << "};\n\n"; + OS << "// " << TargetName << "DFAStateEntryTable[i] = " + << "Index of the first entry in DFAStateInputTable for\n"; + OS << "// " + << "the ith state.\n"; + OS << "// " << numStates << " states\n"; OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n"; // Multiply i by 2 since each entry in DFAStateInputTable is a set of // two numbers. - for (unsigned i = 0; i < states.size(); ++i) + unsigned lastState = 0; + for (unsigned i = 0; i < numStates; ++i) { + if (i && ((i % 10) == 0)) { + lastState = i-1; + OS << " // states " << (i-10) << ":" << lastState << "\n"; + } OS << StateEntry[i] << ", "; + } // Print out the index to the sentinel entry in StateInputTable OS << ValidTransitions << ", "; + OS << " // states " << (lastState+1) << ":" << numStates << "\n"; - OS << "\n};\n"; + OS << "};\n"; OS << "} // namespace\n"; @@ -332,40 +642,118 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { // -// collectAllInsnClasses - Populate allInsnClasses which is a set of units -// used in each stage. +// collectAllFuncUnits - Construct a map of function unit names to bits. // -void DFAPacketizerEmitter::collectAllInsnClasses(const std::string &Name, - Record *ItinData, - unsigned &NStages, - raw_ostream &OS) { - // Collect processor itineraries. - std::vector<Record*> ProcItinList = - Records.getAllDerivedDefinitions("ProcessorItineraries"); - - // If just no itinerary then don't bother. - if (ProcItinList.size() < 2) - return; - std::map<std::string, unsigned> NameToBitsMap; +int DFAPacketizerEmitter::collectAllFuncUnits( + std::vector<Record*> &ProcItinList, + std::map<std::string, unsigned> &FUNameToBitsMap, + int &maxFUs, + raw_ostream &OS) { + DEBUG(dbgs() << "-----------------------------------------------------------------------------\n"); + DEBUG(dbgs() << "collectAllFuncUnits"); + DEBUG(dbgs() << " (" << ProcItinList.size() << " itineraries)\n"); + int totalFUs = 0; // Parse functional units for all the itineraries. for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) { Record *Proc = ProcItinList[i]; std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU"); + DEBUG(dbgs() << " FU:" << i + << " (" << FUs.size() << " FUs) " + << Proc->getName()); + + // Convert macros to bits for each stage. - for (unsigned i = 0, N = FUs.size(); i < N; ++i) - NameToBitsMap[FUs[i]->getName()] = (unsigned) (1U << i); + unsigned numFUs = FUs.size(); + for (unsigned j = 0; j < numFUs; ++j) { + assert ((j < DFA_MAX_RESOURCES) && + "Exceeded maximum number of representable resources"); + unsigned FuncResources = (unsigned) (1U << j); + FUNameToBitsMap[FUs[j]->getName()] = FuncResources; + DEBUG(dbgs() << " " << FUs[j]->getName() + << ":0x" << utohexstr(FuncResources)); + } + if (((int) numFUs) > maxFUs) { + maxFUs = numFUs; + } + totalFUs += numFUs; + DEBUG(dbgs() << "\n"); } + return totalFUs; +} + +// +// collectAllComboFuncs - Construct a map from a combo function unit bit to +// the bits of all included functional units. +// +int DFAPacketizerEmitter::collectAllComboFuncs( + std::vector<Record*> &ComboFuncList, + std::map<std::string, unsigned> &FUNameToBitsMap, + std::map<unsigned, unsigned> &ComboBitToBitsMap, + raw_ostream &OS) { + DEBUG(dbgs() << "-----------------------------------------------------------------------------\n"); + DEBUG(dbgs() << "collectAllComboFuncs"); + DEBUG(dbgs() << " (" << ComboFuncList.size() << " sets)\n"); + int numCombos = 0; + for (unsigned i = 0, N = ComboFuncList.size(); i < N; ++i) { + Record *Func = ComboFuncList[i]; + std::vector<Record*> FUs = Func->getValueAsListOfDefs("CFD"); + + DEBUG(dbgs() << " CFD:" << i + << " (" << FUs.size() << " combo FUs) " + << Func->getName() << "\n"); + + // Convert macros to bits for each stage. + for (unsigned j = 0, N = FUs.size(); j < N; ++j) { + assert ((j < DFA_MAX_RESOURCES) && + "Exceeded maximum number of DFA resources"); + Record *FuncData = FUs[j]; + Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc"); + const std::vector<Record*> &FuncList = + FuncData->getValueAsListOfDefs("FuncList"); + std::string ComboFuncName = ComboFunc->getName(); + unsigned ComboBit = FUNameToBitsMap[ComboFuncName]; + unsigned ComboResources = ComboBit; + DEBUG(dbgs() << " combo: " << ComboFuncName + << ":0x" << utohexstr(ComboResources) << "\n"); + for (unsigned k = 0, M = FuncList.size(); k < M; ++k) { + std::string FuncName = FuncList[k]->getName(); + unsigned FuncResources = FUNameToBitsMap[FuncName]; + DEBUG(dbgs() << " " << FuncName + << ":0x" << utohexstr(FuncResources) << "\n"); + ComboResources |= FuncResources; + } + ComboBitToBitsMap[ComboBit] = ComboResources; + numCombos++; + DEBUG(dbgs() << " => combo bits: " << ComboFuncName << ":0x" + << utohexstr(ComboBit) << " = 0x" + << utohexstr(ComboResources) << "\n"); + } + } + return numCombos; +} + + +// +// collectOneInsnClass - Populate allInsnClasses with one instruction class +// +int DFAPacketizerEmitter::collectOneInsnClass(const std::string &ProcName, + std::vector<Record*> &ProcItinList, + std::map<std::string, unsigned> &FUNameToBitsMap, + Record *ItinData, + raw_ostream &OS) { const std::vector<Record*> &StageList = ItinData->getValueAsListOfDefs("Stages"); // The number of stages. - NStages = StageList.size(); + unsigned NStages = StageList.size(); + + DEBUG(dbgs() << " " << ItinData->getValueAsDef("TheClass")->getName() + << "\n"); - // For each unit. - unsigned UnitBitValue = 0; + std::vector<unsigned> UnitBits; // Compute the bitwise or of each unit used in this stage. for (unsigned i = 0; i < NStages; ++i) { @@ -375,18 +763,74 @@ void DFAPacketizerEmitter::collectAllInsnClasses(const std::string &Name, const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units"); + DEBUG(dbgs() << " stage:" << i + << " [" << UnitList.size() << " units]:"); + unsigned dbglen = 26; // cursor after stage dbgs + + // Compute the bitwise or of each unit used in this stage. + unsigned UnitBitValue = 0; for (unsigned j = 0, M = UnitList.size(); j < M; ++j) { // Conduct bitwise or. std::string UnitName = UnitList[j]->getName(); - assert(NameToBitsMap.count(UnitName)); - UnitBitValue |= NameToBitsMap[UnitName]; + DEBUG(dbgs() << " " << j << ":" << UnitName); + dbglen += 3 + UnitName.length(); + assert(FUNameToBitsMap.count(UnitName)); + UnitBitValue |= FUNameToBitsMap[UnitName]; } if (UnitBitValue != 0) - allInsnClasses.insert(UnitBitValue); + UnitBits.push_back(UnitBitValue); + + while (dbglen <= 64) { // line up bits dbgs + dbglen += 8; + DEBUG(dbgs() << "\t"); + } + DEBUG(dbgs() << " (bits: 0x" << utohexstr(UnitBitValue) << ")\n"); } + + if (UnitBits.size() > 0) + allInsnClasses.push_back(UnitBits); + + DEBUG({ + dbgs() << " "; + dbgsInsnClass(UnitBits); + dbgs() << "\n"; + }); + + return NStages; } +// +// collectAllInsnClasses - Populate allInsnClasses which is a set of units +// used in each stage. +// +int DFAPacketizerEmitter::collectAllInsnClasses(const std::string &ProcName, + std::vector<Record*> &ProcItinList, + std::map<std::string, unsigned> &FUNameToBitsMap, + std::vector<Record*> &ItinDataList, + int &maxStages, + raw_ostream &OS) { + // Collect all instruction classes. + unsigned M = ItinDataList.size(); + + int numInsnClasses = 0; + DEBUG(dbgs() << "-----------------------------------------------------------------------------\n" + << "collectAllInsnClasses " + << ProcName + << " (" << M << " classes)\n"); + + // Collect stages for each instruction class for all itinerary data + for (unsigned j = 0; j < M; j++) { + Record *ItinData = ItinDataList[j]; + int NStages = collectOneInsnClass(ProcName, ProcItinList, + FUNameToBitsMap, ItinData, OS); + if (NStages > maxStages) { + maxStages = NStages; + } + numInsnClasses++; + } + return numInsnClasses; +} // // Run the worklist algorithm to generate the DFA. @@ -398,16 +842,35 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { Records.getAllDerivedDefinitions("ProcessorItineraries"); // - // Collect the instruction classes. + // Collect the Functional units. + // + std::map<std::string, unsigned> FUNameToBitsMap; + int maxResources = 0; + collectAllFuncUnits(ProcItinList, + FUNameToBitsMap, maxResources, OS); + + // + // Collect the Combo Functional units. // + std::map<unsigned, unsigned> ComboBitToBitsMap; + std::vector<Record*> ComboFuncList = + Records.getAllDerivedDefinitions("ComboFuncUnits"); + int numCombos = collectAllComboFuncs(ComboFuncList, + FUNameToBitsMap, ComboBitToBitsMap, OS); + + // + // Collect the itineraries. + // + int maxStages = 0; + int numInsnClasses = 0; for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { Record *Proc = ProcItinList[i]; // Get processor itinerary name. - const std::string &Name = Proc->getName(); + const std::string &ProcName = Proc->getName(); // Skip default. - if (Name == "NoItineraries") + if (ProcName == "NoItineraries") continue; // Sanity check for at least one instruction itinerary class. @@ -419,15 +882,11 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // Get itinerary data list. std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID"); - // Collect instruction classes for all itinerary data. - for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) { - Record *ItinData = ItinDataList[j]; - unsigned NStages; - collectAllInsnClasses(Name, ItinData, NStages, OS); - } + // Collect all instruction classes + numInsnClasses += collectAllInsnClasses(ProcName, ProcItinList, + FUNameToBitsMap, ItinDataList, maxStages, OS); } - // // Run a worklist algorithm to generate the DFA. // @@ -436,6 +895,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { Initial->isInitial = true; Initial->stateInfo.insert(0x0); SmallVector<const State*, 32> WorkList; +// std::queue<State*> WorkList; std::map<std::set<unsigned>, const State*> Visited; WorkList.push_back(Initial); @@ -459,9 +919,19 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // while (!WorkList.empty()) { const State *current = WorkList.pop_back_val(); - for (DenseSet<unsigned>::iterator CI = allInsnClasses.begin(), - CE = allInsnClasses.end(); CI != CE; ++CI) { - unsigned InsnClass = *CI; + DEBUG({ + dbgs() << "---------------------\n"; + dbgs() << "Processing state: " << current->stateNum << " - "; + dbgsStateInfo(current->stateInfo); + dbgs() << "\n"; + }); + for (unsigned i = 0; i < allInsnClasses.size(); i++) { + std::vector<unsigned> InsnClass = allInsnClasses[i]; + DEBUG({ + dbgs() << i << " "; + dbgsInsnClass(InsnClass); + dbgs() << "\n"; + }); std::set<unsigned> NewStateResources; // @@ -469,32 +939,52 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // and the state can accommodate this InsnClass, create a transition. // if (!current->hasTransition(InsnClass) && - current->canAddInsnClass(InsnClass)) { - const State *NewState; - current->AddInsnClass(InsnClass, NewStateResources); - assert(!NewStateResources.empty() && "New states must be generated"); + current->canMaybeAddInsnClass(InsnClass, ComboBitToBitsMap)) { + const State *NewState = NULL; + current->AddInsnClass(InsnClass, ComboBitToBitsMap, NewStateResources); + if (NewStateResources.size() == 0) { + DEBUG(dbgs() << " Skipped - no new states generated\n"); + continue; + } + + DEBUG({ + dbgs() << "\t"; + dbgsStateInfo(NewStateResources); + dbgs() << "\n"; + }); // // If we have seen this state before, then do not create a new state. // - // auto VI = Visited.find(NewStateResources); - if (VI != Visited.end()) + if (VI != Visited.end()) { NewState = VI->second; - else { + DEBUG({ + dbgs() << "\tFound existing state: " << NewState->stateNum + << " - "; + dbgsStateInfo(NewState->stateInfo); + dbgs() << "\n"; + }); + } else { NewState = &D.newState(); NewState->stateInfo = NewStateResources; Visited[NewStateResources] = NewState; WorkList.push_back(NewState); + DEBUG({ + dbgs() << "\tAccepted new state: " << NewState->stateNum << " - "; + dbgsStateInfo(NewState->stateInfo); + dbgs() << "\n"; + }); } - + current->addTransition(InsnClass, NewState); } } } // Print out the table. - D.writeTableAndAPI(OS, TargetName); + D.writeTableAndAPI(OS, TargetName, + numInsnClasses, maxResources, numCombos, maxStages); } namespace llvm { diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp index f02051a2cd6c..e8595271bcce 100644 --- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp @@ -134,7 +134,7 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) { PredicateNamespace = "ARM"; EmitFixedLenDecoder(Records, OS, PredicateNamespace, - "if (!Check(S, ", ")) return MCDisassembler::Fail;", + "if (!Check(S, ", "))", "S", "MCDisassembler::Fail", " MCDisassembler::DecodeStatus S = " "MCDisassembler::Success;\n(void)S;"); @@ -142,8 +142,7 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) { } EmitFixedLenDecoder(Records, OS, Target.getName(), - "if (", " == MCDisassembler::Fail)" - " return MCDisassembler::Fail;", + "if (", " == MCDisassembler::Fail)", "MCDisassembler::Success", "MCDisassembler::Fail", ""); } diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index c4df2833885a..8ca4a1bf5404 100644 --- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -44,9 +44,10 @@ struct EncodingField { struct OperandInfo { std::vector<EncodingField> Fields; std::string Decoder; + bool HasCompleteDecoder; - OperandInfo(std::string D) - : Decoder(D) { } + OperandInfo(std::string D, bool HCD) + : Decoder(D), HasCompleteDecoder(HCD) { } void addField(unsigned Base, unsigned Width, unsigned Offset) { Fields.push_back(EncodingField(Base, Width, Offset)); @@ -64,8 +65,8 @@ typedef std::vector<uint8_t> DecoderTable; typedef uint32_t DecoderFixup; typedef std::vector<DecoderFixup> FixupList; typedef std::vector<FixupList> FixupScopeList; -typedef SetVector<std::string> PredicateSet; -typedef SetVector<std::string> DecoderSet; +typedef SmallSetVector<std::string, 16> PredicateSet; +typedef SmallSetVector<std::string, 16> DecoderSet; struct DecoderTableInfo { DecoderTable Table; FixupScopeList FixupStack; @@ -85,8 +86,7 @@ public: FixedLenDecoderEmitter(RecordKeeper &R, std::string PredicateNamespace, std::string GPrefix = "if (", - std::string GPostfix = " == MCDisassembler::Fail)" - " return MCDisassembler::Fail;", + std::string GPostfix = " == MCDisassembler::Fail)", std::string ROK = "MCDisassembler::Success", std::string RFail = "MCDisassembler::Fail", std::string L = "") : @@ -448,10 +448,13 @@ protected: const Filter &Best) const; void emitBinaryParser(raw_ostream &o, unsigned &Indentation, - const OperandInfo &OpInfo) const; + const OperandInfo &OpInfo, + bool &OpHasCompleteDecoder) const; - void emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc) const; - unsigned getDecoderIndex(DecoderSet &Decoders, unsigned Opc) const; + void emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc, + bool &HasCompleteDecoder) const; + unsigned getDecoderIndex(DecoderSet &Decoders, unsigned Opc, + bool &HasCompleteDecoder) const; // Assign a single filter and run with it. void runSingleFilter(unsigned startBit, unsigned numBit, bool mixed); @@ -779,7 +782,9 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS, OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; break; } - case MCD::OPC_Decode: { + case MCD::OPC_Decode: + case MCD::OPC_TryDecode: { + bool IsTry = *I == MCD::OPC_TryDecode; ++I; // Extract the ULEB128 encoded Opcode to a buffer. uint8_t Buffer[8], *p = Buffer; @@ -788,7 +793,8 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS, && "ULEB128 value too large!"); // Decode the Opcode value. unsigned Opc = decodeULEB128(Buffer); - OS.indent(Indentation) << "MCD::OPC_Decode, "; + OS.indent(Indentation) << "MCD::OPC_" << (IsTry ? "Try" : "") + << "Decode, "; for (p = Buffer; *p >= 128; ++p) OS << utostr(*p) << ", "; OS << utostr(*p) << ", "; @@ -798,8 +804,25 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS, OS << utostr(*I) << ", "; OS << utostr(*I++) << ", "; + if (!IsTry) { + OS << "// Opcode: " + << NumberedInstructions->at(Opc)->TheDef->getName() << "\n"; + break; + } + + // Fallthrough for OPC_TryDecode. + + // 16-bit numtoskip value. + uint8_t Byte = *I++; + uint32_t NumToSkip = Byte; + OS << utostr(Byte) << ", "; + Byte = *I++; + OS << utostr(Byte) << ", "; + NumToSkip |= Byte << 8; + OS << "// Opcode: " - << NumberedInstructions->at(Opc)->TheDef->getName() << "\n"; + << NumberedInstructions->at(Opc)->TheDef->getName() + << ", skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; break; } case MCD::OPC_SoftFail: { @@ -876,8 +899,9 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders, OS.indent(Indentation) << "static DecodeStatus decodeToMCInst(DecodeStatus S," << " unsigned Idx, InsnType insn, MCInst &MI,\n"; OS.indent(Indentation) << " uint64_t " - << "Address, const void *Decoder) {\n"; + << "Address, const void *Decoder, bool &DecodeComplete) {\n"; Indentation += 2; + OS.indent(Indentation) << "DecodeComplete = true;\n"; OS.indent(Indentation) << "InsnType tmp;\n"; OS.indent(Indentation) << "switch (Idx) {\n"; OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n"; @@ -1033,7 +1057,8 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits, } void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, - const OperandInfo &OpInfo) const { + const OperandInfo &OpInfo, + bool &OpHasCompleteDecoder) const { const std::string &Decoder = OpInfo.Decoder; if (OpInfo.numFields() != 1) @@ -1049,45 +1074,57 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, o << ";\n"; } - if (Decoder != "") + if (Decoder != "") { + OpHasCompleteDecoder = OpInfo.HasCompleteDecoder; o.indent(Indentation) << Emitter->GuardPrefix << Decoder - << "(MI, tmp, Address, Decoder)" - << Emitter->GuardPostfix << "\n"; - else + << "(MI, tmp, Address, Decoder)" + << Emitter->GuardPostfix + << " { " << (OpHasCompleteDecoder ? "" : "DecodeComplete = false; ") + << "return MCDisassembler::Fail; }\n"; + } else { + OpHasCompleteDecoder = true; o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n"; - + } } void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation, - unsigned Opc) const { + unsigned Opc, bool &HasCompleteDecoder) const { + HasCompleteDecoder = true; + for (const auto &Op : Operands.find(Opc)->second) { // If a custom instruction decoder was specified, use that. if (Op.numFields() == 0 && Op.Decoder.size()) { + HasCompleteDecoder = Op.HasCompleteDecoder; OS.indent(Indentation) << Emitter->GuardPrefix << Op.Decoder << "(MI, insn, Address, Decoder)" - << Emitter->GuardPostfix << "\n"; + << Emitter->GuardPostfix + << " { " << (HasCompleteDecoder ? "" : "DecodeComplete = false; ") + << "return MCDisassembler::Fail; }\n"; break; } - emitBinaryParser(OS, Indentation, Op); + bool OpHasCompleteDecoder; + emitBinaryParser(OS, Indentation, Op, OpHasCompleteDecoder); + if (!OpHasCompleteDecoder) + HasCompleteDecoder = false; } } unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, - unsigned Opc) const { + unsigned Opc, + bool &HasCompleteDecoder) const { // Build up the predicate string. SmallString<256> Decoder; // FIXME: emitDecoder() function can take a buffer directly rather than // a stream. raw_svector_ostream S(Decoder); unsigned I = 4; - emitDecoder(S, I, Opc); - S.flush(); + emitDecoder(S, I, Opc, HasCompleteDecoder); // Using the full decoder string as the key value here is a bit // heavyweight, but is effective. If the string comparisons become a // performance concern, we can implement a mangling of the predicate - // data easilly enough with a map back to the actual string. That's + // data easily enough with a map back to the actual string. That's // overkill for now, though. // Make sure the predicate is in the table. @@ -1162,7 +1199,7 @@ unsigned FilterChooser::getPredicateIndex(DecoderTableInfo &TableInfo, // Using the full predicate string as the key value here is a bit // heavyweight, but is effective. If the string comparisons become a // performance concern, we can implement a mangling of the predicate - // data easilly enough with a map back to the actual string. That's + // data easily enough with a map back to the actual string. That's // overkill for now, though. // Make sure the predicate is in the table. @@ -1193,7 +1230,6 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo, SmallString<16> PBytes; raw_svector_ostream S(PBytes); encodeULEB128(PIdx, S); - S.flush(); TableInfo.Table.push_back(MCD::OPC_CheckPredicate); // Predicate index @@ -1252,16 +1288,13 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo, raw_svector_ostream S(MaskBytes); if (NeedPositiveMask) { encodeULEB128(PositiveMask.getZExtValue(), S); - S.flush(); for (unsigned i = 0, e = MaskBytes.size(); i != e; ++i) TableInfo.Table.push_back(MaskBytes[i]); } else TableInfo.Table.push_back(0); if (NeedNegativeMask) { MaskBytes.clear(); - S.resync(); encodeULEB128(NegativeMask.getZExtValue(), S); - S.flush(); for (unsigned i = 0, e = MaskBytes.size(); i != e; ++i) TableInfo.Table.push_back(MaskBytes[i]); } else @@ -1308,22 +1341,41 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, // Check for soft failure of the match. emitSoftFailTableEntry(TableInfo, Opc); - TableInfo.Table.push_back(MCD::OPC_Decode); + bool HasCompleteDecoder; + unsigned DIdx = getDecoderIndex(TableInfo.Decoders, Opc, HasCompleteDecoder); + + // Produce OPC_Decode or OPC_TryDecode opcode based on the information + // whether the instruction decoder is complete or not. If it is complete + // then it handles all possible values of remaining variable/unfiltered bits + // and for any value can determine if the bitpattern is a valid instruction + // or not. This means OPC_Decode will be the final step in the decoding + // process. If it is not complete, then the Fail return code from the + // decoder method indicates that additional processing should be done to see + // if there is any other instruction that also matches the bitpattern and + // can decode it. + TableInfo.Table.push_back(HasCompleteDecoder ? MCD::OPC_Decode : + MCD::OPC_TryDecode); uint8_t Buffer[8], *p; encodeULEB128(Opc, Buffer); for (p = Buffer; *p >= 128 ; ++p) TableInfo.Table.push_back(*p); TableInfo.Table.push_back(*p); - unsigned DIdx = getDecoderIndex(TableInfo.Decoders, Opc); SmallString<16> Bytes; raw_svector_ostream S(Bytes); encodeULEB128(DIdx, S); - S.flush(); // Decoder index for (unsigned i = 0, e = Bytes.size(); i != e; ++i) TableInfo.Table.push_back(Bytes[i]); + + if (!HasCompleteDecoder) { + // Push location for NumToSkip backpatching. + TableInfo.FixupStack.back().push_back(TableInfo.Table.size()); + // Allocate the space for the fixup. + TableInfo.Table.push_back(0); + TableInfo.Table.push_back(0); + } } // Emits table entries to decode the singleton, and then to decode the rest. @@ -1679,7 +1731,8 @@ static bool populateInstruction(CodeGenTarget &Target, // of trying to auto-generate the decoder. std::string InstDecoder = Def.getValueAsString("DecoderMethod"); if (InstDecoder != "") { - InsnOperands.push_back(OperandInfo(InstDecoder)); + bool HasCompleteInstDecoder = Def.getValueAsBit("hasCompleteDecoder"); + InsnOperands.push_back(OperandInfo(InstDecoder, HasCompleteInstDecoder)); Operands[Opc] = InsnOperands; return true; } @@ -1835,7 +1888,14 @@ static bool populateInstruction(CodeGenTarget &Target, if (!isReg && String && String->getValue() != "") Decoder = String->getValue(); - OperandInfo OpInfo(Decoder); + RecordVal *HasCompleteDecoderVal = + TypeRecord->getValue("hasCompleteDecoder"); + BitInit *HasCompleteDecoderBit = HasCompleteDecoderVal ? + dyn_cast<BitInit>(HasCompleteDecoderVal->getValue()) : nullptr; + bool HasCompleteDecoder = HasCompleteDecoderBit ? + HasCompleteDecoderBit->getValue() : true; + + OperandInfo OpInfo(Decoder, HasCompleteDecoder); OpInfo.addField(bitStart, bitWidth, 0); NumberedInsnOperands[Name].push_back(OpInfo); @@ -1907,7 +1967,14 @@ static bool populateInstruction(CodeGenTarget &Target, if (!isReg && String && String->getValue() != "") Decoder = String->getValue(); - OperandInfo OpInfo(Decoder); + RecordVal *HasCompleteDecoderVal = + TypeRecord->getValue("hasCompleteDecoder"); + BitInit *HasCompleteDecoderBit = HasCompleteDecoderVal ? + dyn_cast<BitInit>(HasCompleteDecoderVal->getValue()) : nullptr; + bool HasCompleteDecoder = HasCompleteDecoderBit ? + HasCompleteDecoderBit->getValue() : true; + + OperandInfo OpInfo(Decoder, HasCompleteDecoder); unsigned Base = ~0U; unsigned Width = 0; unsigned Offset = 0; @@ -2096,12 +2163,52 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) { << " Ptr += Len;\n" << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n" << " Ptr += Len;\n" - << " DEBUG(dbgs() << Loc << \": OPC_Decode: opcode \" << Opc\n" - << " << \", using decoder \" << DecodeIdx << \"\\n\" );\n" - << " DEBUG(dbgs() << \"----- DECODE SUCCESSFUL -----\\n\");\n" << "\n" + << " MI.clear();\n" << " MI.setOpcode(Opc);\n" - << " return decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm);\n" + << " bool DecodeComplete;\n" + << " S = decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm, DecodeComplete);\n" + << " assert(DecodeComplete);\n" + << "\n" + << " DEBUG(dbgs() << Loc << \": OPC_Decode: opcode \" << Opc\n" + << " << \", using decoder \" << DecodeIdx << \": \"\n" + << " << (S != MCDisassembler::Fail ? \"PASS\" : \"FAIL\") << \"\\n\");\n" + << " return S;\n" + << " }\n" + << " case MCD::OPC_TryDecode: {\n" + << " unsigned Len;\n" + << " // Decode the Opcode value.\n" + << " unsigned Opc = decodeULEB128(++Ptr, &Len);\n" + << " Ptr += Len;\n" + << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n" + << " Ptr += Len;\n" + << " // NumToSkip is a plain 16-bit integer.\n" + << " unsigned NumToSkip = *Ptr++;\n" + << " NumToSkip |= (*Ptr++) << 8;\n" + << "\n" + << " // Perform the decode operation.\n" + << " MCInst TmpMI;\n" + << " TmpMI.setOpcode(Opc);\n" + << " bool DecodeComplete;\n" + << " S = decodeToMCInst(S, DecodeIdx, insn, TmpMI, Address, DisAsm, DecodeComplete);\n" + << " DEBUG(dbgs() << Loc << \": OPC_TryDecode: opcode \" << Opc\n" + << " << \", using decoder \" << DecodeIdx << \": \");\n" + << "\n" + << " if (DecodeComplete) {\n" + << " // Decoding complete.\n" + << " DEBUG(dbgs() << (S != MCDisassembler::Fail ? \"PASS\" : \"FAIL\") << \"\\n\");\n" + << " MI = TmpMI;\n" + << " return S;\n" + << " } else {\n" + << " assert(S == MCDisassembler::Fail);\n" + << " // If the decoding was incomplete, skip.\n" + << " Ptr += NumToSkip;\n" + << " DEBUG(dbgs() << \"FAIL: continuing at \" << (Ptr - DecodeTable) << \"\\n\");\n" + << " // Reset decode status. This also drops a SoftFail status that could be\n" + << " // set before the decode attempt.\n" + << " S = MCDisassembler::Success;\n" + << " }\n" + << " break;\n" << " }\n" << " case MCD::OPC_SoftFail: {\n" << " // Decode the mask values.\n" diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp index e242a965ff93..a6583399fa20 100644 --- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -1,4 +1,4 @@ -//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===// +//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// - #include "CodeGenDAGPatterns.h" #include "CodeGenSchedule.h" #include "CodeGenTarget.h" @@ -26,6 +25,7 @@ #include <cstdio> #include <map> #include <vector> + using namespace llvm; namespace { @@ -70,11 +70,11 @@ private: void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs); std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst); }; -} // End anonymous namespace +} // end anonymous namespace static void PrintDefList(const std::vector<Record*> &Uses, unsigned Num, raw_ostream &OS) { - OS << "static const uint16_t ImplicitList" << Num << "[] = { "; + OS << "static const MCPhysReg ImplicitList" << Num << "[] = { "; for (unsigned i = 0, e = Uses.size(); i != e; ++i) OS << getQualifiedName(Uses[i]) << ", "; OS << "0 };\n"; @@ -190,7 +190,6 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, } } - /// Initialize data structures for generating operand name mappings. /// /// \param Operands [out] A map used to generate the OpName enum with operand @@ -257,9 +256,9 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << "OPERAND_LAST"; OS << "\n};\n"; - OS << "} // End namespace OpName\n"; - OS << "} // End namespace " << Namespace << "\n"; - OS << "} // End namespace llvm\n"; + OS << "} // end namespace OpName\n"; + OS << "} // end namespace " << Namespace << "\n"; + OS << "} // end namespace llvm\n"; OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n"; OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n"; @@ -298,8 +297,8 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << " return -1;\n"; } OS << "}\n"; - OS << "} // End namespace " << Namespace << "\n"; - OS << "} // End namespace llvm\n"; + OS << "} // end namespace " << Namespace << "\n"; + OS << "} // end namespace llvm\n"; OS << "#endif //GET_INSTRINFO_NAMED_OPS\n"; } @@ -328,9 +327,9 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS, } OS << " OPERAND_TYPE_LIST_END" << "\n};\n"; - OS << "} // End namespace OpTypes\n"; - OS << "} // End namespace " << Namespace << "\n"; - OS << "} // End namespace llvm\n"; + OS << "} // end namespace OpTypes\n"; + OS << "} // end namespace " << Namespace << "\n"; + OS << "} // end namespace llvm\n"; OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n"; } @@ -419,7 +418,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " << NumberedInstructions.size() << ");\n}\n\n"; - OS << "} // End llvm namespace \n"; + OS << "} // end llvm namespace \n"; OS << "#endif // GET_INSTRINFO_MC_DESC\n\n"; @@ -431,10 +430,10 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OS << "namespace llvm {\n"; OS << "struct " << ClassName << " : public TargetInstrInfo {\n" << " explicit " << ClassName - << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1);\n" - << " virtual ~" << ClassName << "();\n" + << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1);\n" + << " ~" << ClassName << "() override {}\n" << "};\n"; - OS << "} // End llvm namespace \n"; + OS << "} // end llvm namespace \n"; OS << "#endif // GET_INSTRINFO_HEADER\n\n"; @@ -446,13 +445,12 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; OS << "extern const char " << TargetName << "InstrNameData[];\n"; OS << ClassName << "::" << ClassName - << "(int CFSetupOpcode, int CFDestroyOpcode)\n" - << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode) {\n" + << "(int CFSetupOpcode, int CFDestroyOpcode, int CatchRetOpcode)\n" + << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode) {\n" << " InitMCInstrInfo(" << TargetName << "Insts, " << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " - << NumberedInstructions.size() << ");\n}\n" - << ClassName << "::~" << ClassName << "() {}\n"; - OS << "} // End llvm namespace \n"; + << NumberedInstructions.size() << ");\n}\n"; + OS << "} // end llvm namespace \n"; OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n"; @@ -596,9 +594,9 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) { OS << " " << Class.Name << "\t= " << Num++ << ",\n"; OS << " SCHED_LIST_END = " << SchedModels.numInstrSchedClasses() << "\n"; OS << " };\n"; - OS << "} // End Sched namespace\n"; - OS << "} // End " << Namespace << " namespace\n"; - OS << "} // End llvm namespace \n"; + OS << "} // end Sched namespace\n"; + OS << "} // end " << Namespace << " namespace\n"; + OS << "} // end llvm namespace \n"; OS << "#endif // GET_INSTRINFO_ENUM\n\n"; } @@ -610,4 +608,4 @@ void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) { EmitMapTable(RK, OS); } -} // End llvm namespace +} // end llvm namespace diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp index 2b59ee69d16a..42a6a152f55e 100644 --- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -50,8 +50,6 @@ public: raw_ostream &OS); void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS); - void EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, - raw_ostream &OS); void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS); void EmitIntrinsicToMSBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, @@ -92,9 +90,6 @@ void IntrinsicEmitter::run(raw_ostream &OS) { // Emit the intrinsic parameter attributes. EmitAttributes(Ints, OS); - // Emit intrinsic alias analysis mod/ref behavior. - EmitModRefBehavior(Ints, OS); - // Emit code to translate GCC builtins into LLVM intrinsics. EmitIntrinsicToGCCBuiltinMap(Ints, OS); @@ -246,22 +241,25 @@ enum IIT_Info { // Values from 16+ are only encodable with the inefficient encoding. 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, - IIT_VEC_OF_PTRS_TO_ELT = 32, - IIT_I128 = 33 + IIT_TOKEN = 18, + IIT_METADATA = 19, + IIT_EMPTYSTRUCT = 20, + IIT_STRUCT2 = 21, + IIT_STRUCT3 = 22, + IIT_STRUCT4 = 23, + IIT_STRUCT5 = 24, + IIT_EXTEND_ARG = 25, + IIT_TRUNC_ARG = 26, + IIT_ANYPTR = 27, + IIT_V1 = 28, + IIT_VARARG = 29, + IIT_HALF_VEC_ARG = 30, + IIT_SAME_VEC_WIDTH_ARG = 31, + IIT_PTR_TO_ARG = 32, + IIT_VEC_OF_PTRS_TO_ELT = 33, + IIT_I128 = 34, + IIT_V512 = 35, + IIT_V1024 = 36 }; @@ -285,6 +283,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, case MVT::f16: return Sig.push_back(IIT_F16); case MVT::f32: return Sig.push_back(IIT_F32); case MVT::f64: return Sig.push_back(IIT_F64); + case MVT::token: return Sig.push_back(IIT_TOKEN); case MVT::Metadata: return Sig.push_back(IIT_METADATA); case MVT::x86mmx: return Sig.push_back(IIT_MMX); // MVT::OtherVT is used to mean the empty struct type here. @@ -375,6 +374,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, case 16: Sig.push_back(IIT_V16); break; case 32: Sig.push_back(IIT_V32); break; case 64: Sig.push_back(IIT_V64); break; + case 512: Sig.push_back(IIT_V512); break; + case 1024: Sig.push_back(IIT_V1024); break; } return EncodeFixedValueType(VVT.getVectorElementType().SimpleTy, Sig); @@ -503,28 +504,6 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, } namespace { -enum ModRefKind { - MRK_none, - MRK_readonly, - MRK_readnone -}; -} - -static ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) { - switch (intrinsic.ModRef) { - case CodeGenIntrinsic::NoMem: - return MRK_readnone; - case CodeGenIntrinsic::ReadArgMem: - case CodeGenIntrinsic::ReadMem: - return MRK_readonly; - case CodeGenIntrinsic::ReadWriteArgMem: - case CodeGenIntrinsic::ReadWriteMem: - return MRK_none; - } - llvm_unreachable("bad mod-ref kind"); -} - -namespace { struct AttributeComparator { bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const { // Sort throwing intrinsics after non-throwing intrinsics. @@ -541,8 +520,8 @@ struct AttributeComparator { return R->isConvergent; // Try to order by readonly/readnone attribute. - ModRefKind LK = getModRefKind(*L); - ModRefKind RK = getModRefKind(*R); + CodeGenIntrinsic::ModRefKind LK = L->ModRef; + CodeGenIntrinsic::ModRefKind RK = R->ModRef; if (LK != RK) return (LK > RK); // Order by argument attributes. @@ -636,7 +615,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { case CodeGenIntrinsic::ReadNone: if (addComma) OS << ","; - OS << "Attributes::ReadNone"; + OS << "Attribute::ReadNone"; addComma = true; break; } @@ -649,10 +628,10 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { } } - ModRefKind modRef = getModRefKind(intrinsic); - - if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn || - intrinsic.isNoDuplicate || intrinsic.isConvergent) { + if (!intrinsic.canThrow || + intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem || + intrinsic.isNoReturn || intrinsic.isNoDuplicate || + intrinsic.isConvergent) { OS << " const Attribute::AttrKind Atts[] = {"; bool addComma = false; if (!intrinsic.canThrow) { @@ -678,17 +657,29 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { addComma = true; } - switch (modRef) { - case MRK_none: break; - case MRK_readonly: + switch (intrinsic.ModRef) { + case CodeGenIntrinsic::NoMem: + if (addComma) + OS << ","; + OS << "Attribute::ReadNone"; + break; + case CodeGenIntrinsic::ReadArgMem: + if (addComma) + OS << ","; + OS << "Attribute::ReadOnly,"; + OS << "Attribute::ArgMemOnly"; + break; + case CodeGenIntrinsic::ReadMem: if (addComma) OS << ","; OS << "Attribute::ReadOnly"; break; - case MRK_readnone: + case CodeGenIntrinsic::ReadWriteArgMem: if (addComma) OS << ","; - OS << "Attribute::ReadNone"; + OS << "Attribute::ArgMemOnly"; + break; + case CodeGenIntrinsic::ReadWriteMem: break; } OS << "};\n"; @@ -713,41 +704,6 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; } -/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior. -void IntrinsicEmitter:: -EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){ - OS << "// Determine intrinsic alias analysis mod/ref behavior.\n" - << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n" - << "assert(iid <= Intrinsic::" << Ints.back().EnumName << " && " - << "\"Unknown intrinsic.\");\n\n"; - - OS << "static const uint8_t IntrinsicModRefBehavior[] = {\n" - << " /* invalid */ UnknownModRefBehavior,\n"; - for (unsigned i = 0, e = Ints.size(); i != e; ++i) { - OS << " /* " << TargetPrefix << Ints[i].EnumName << " */ "; - switch (Ints[i].ModRef) { - case CodeGenIntrinsic::NoMem: - OS << "DoesNotAccessMemory,\n"; - break; - case CodeGenIntrinsic::ReadArgMem: - OS << "OnlyReadsArgumentPointees,\n"; - break; - case CodeGenIntrinsic::ReadMem: - OS << "OnlyReadsMemory,\n"; - break; - case CodeGenIntrinsic::ReadWriteArgMem: - OS << "OnlyAccessesArgumentPointees,\n"; - break; - case CodeGenIntrinsic::ReadWriteMem: - OS << "UnknownModRefBehavior,\n"; - break; - } - } - OS << "};\n\n" - << "return static_cast<ModRefBehavior>(IntrinsicModRefBehavior[iid]);\n" - << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; -} - /// EmitTargetBuiltins - All of the builtins in the specified map are for the /// same target, and we already checked it. static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM, diff --git a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp index 9262d7c8a02c..c1b5e6510325 100644 --- a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp +++ b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp @@ -149,10 +149,10 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { PE = I->first.end(); PI != PE; ++PI) { OS << "\"" << *PI << "\" COMMA "; } - OS << "0})\n"; + OS << "nullptr})\n"; } OS << "#undef COMMA\n"; - OS << "#endif\n\n"; + OS << "#endif // PREFIX\n\n"; OS << "/////////\n"; OS << "// Groups\n\n"; @@ -164,7 +164,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << "OPTION("; // The option prefix; - OS << "0"; + OS << "nullptr"; // The option string. OS << ", \"" << R.getValueAsString("Name") << '"'; @@ -183,7 +183,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << "INVALID"; // The other option arguments (unused for groups). - OS << ", INVALID, 0, 0, 0"; + OS << ", INVALID, nullptr, 0, 0"; // The option help text. if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { @@ -191,10 +191,10 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << " "; write_cstring(OS, R.getValueAsString("HelpText")); } else - OS << ", 0"; + OS << ", nullptr"; // The option meta-variable name (unused). - OS << ", 0)\n"; + OS << ", nullptr)\n"; } OS << "\n"; @@ -242,7 +242,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << ", "; std::vector<std::string> AliasArgs = R.getValueAsListOfStrings("AliasArgs"); if (AliasArgs.size() == 0) { - OS << "0"; + OS << "nullptr"; } else { OS << "\""; for (size_t i = 0, e = AliasArgs.size(); i != e; ++i) @@ -274,17 +274,17 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { OS << " "; write_cstring(OS, R.getValueAsString("HelpText")); } else - OS << ", 0"; + OS << ", nullptr"; // The option meta-variable name. OS << ", "; if (!isa<UnsetInit>(R.getValueInit("MetaVarName"))) write_cstring(OS, R.getValueAsString("MetaVarName")); else - OS << "0"; + OS << "nullptr"; OS << ")\n"; } - OS << "#endif\n"; + OS << "#endif // OPTION\n"; } } // end namespace llvm diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp index 9619fb9e356e..b727df75626f 100644 --- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -240,7 +240,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight); OS << " \"" << RegUnits.Name << "\",\n"; } - OS << " nullptr };\n" + OS << " };\n" << " return PressureNameTable[Idx];\n" << "}\n\n"; @@ -1074,9 +1074,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" << " explicit " << ClassName - << "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n" - << " bool needsStackRealignment(const MachineFunction &) const override\n" - << " { return false; }\n"; + << "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n"; if (!RegBank.getSubRegIndices().empty()) { OS << " unsigned composeSubRegIndicesImpl" << "(unsigned, unsigned) const override;\n" @@ -1454,27 +1452,32 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "ArrayRef<const uint32_t *> " << ClassName << "::getRegMasks() const {\n"; - OS << " static const uint32_t *Masks[] = {\n"; - for (Record *CSRSet : CSRSets) - OS << " " << CSRSet->getName() << "_RegMask, \n"; - OS << " nullptr\n };\n"; - OS << " return ArrayRef<const uint32_t *>(Masks, (size_t)" << CSRSets.size() - << ");\n"; + if (!CSRSets.empty()) { + OS << " static const uint32_t *const Masks[] = {\n"; + for (Record *CSRSet : CSRSets) + OS << " " << CSRSet->getName() << "_RegMask,\n"; + OS << " };\n"; + OS << " return makeArrayRef(Masks);\n"; + } else { + OS << " return None;\n"; + } OS << "}\n\n"; OS << "ArrayRef<const char *> " << ClassName << "::getRegMaskNames() const {\n"; - OS << " static const char *Names[] = {\n"; - for (Record *CSRSet : CSRSets) - OS << " " << '"' << CSRSet->getName() << '"' << ",\n"; - OS << " nullptr\n };\n"; - OS << " return ArrayRef<const char *>(Names, (size_t)" << CSRSets.size() - << ");\n"; + if (!CSRSets.empty()) { + OS << " static const char *const Names[] = {\n"; + for (Record *CSRSet : CSRSets) + OS << " " << '"' << CSRSet->getName() << '"' << ",\n"; + OS << " };\n"; + OS << " return makeArrayRef(Names);\n"; + } else { + OS << " return None;\n"; + } OS << "}\n\n"; - OS << "const " << TargetName << "FrameLowering *" - << TargetName << "GenRegisterInfo::\n" - << " getFrameLowering(const MachineFunction &MF) {\n" + OS << "const " << TargetName << "FrameLowering *\n" << TargetName + << "GenRegisterInfo::getFrameLowering(const MachineFunction &MF) {\n" << " return static_cast<const " << TargetName << "FrameLowering *>(\n" << " MF.getSubtarget().getFrameLowering());\n" << "}\n\n"; diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp index 03d7f4e868e7..6246d811123d 100644 --- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -26,6 +26,7 @@ #include <map> #include <string> #include <vector> + using namespace llvm; #define DEBUG_TYPE "subtarget-emitter" @@ -105,9 +106,8 @@ public: Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {} void run(raw_ostream &o); - }; -} // End anonymous namespace +} // end anonymous namespace // // Enumeration - Emit the specified class as an enumeration. @@ -1199,7 +1199,8 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { << " " << (SchedModels.schedClassEnd() - SchedModels.schedClassBegin()) << ",\n"; else - OS << " 0, 0, 0, 0, // No instruction-level machine model.\n"; + OS << " nullptr, nullptr, 0, 0," + << " // No instruction-level machine model.\n"; if (PI->hasItineraries()) OS << " " << PI->ItinsDef->getName() << "};\n"; else @@ -1414,7 +1415,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "namespace llvm {\n"; Enumeration(OS, "SubtargetFeature"); - OS << "} // End llvm namespace \n"; + OS << "} // end llvm namespace\n"; OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; @@ -1461,7 +1462,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "0, 0, 0"; OS << ");\n}\n\n"; - OS << "} // End llvm namespace \n"; + OS << "} // end llvm namespace\n"; OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n"; @@ -1491,7 +1492,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" << " const;\n" << "};\n"; - OS << "} // End llvm namespace \n"; + OS << "} // end llvm namespace\n"; OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; @@ -1543,7 +1544,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { EmitSchedModelHelpers(ClassName, OS); - OS << "} // End llvm namespace \n"; + OS << "} // end llvm namespace\n"; OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n"; } @@ -1555,4 +1556,4 @@ void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) { SubtargetEmitter(RK, CGTarget).run(OS); } -} // End llvm namespace +} // end llvm namespace diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp index 02fe4dc98bea..c16a5583eb36 100644 --- a/contrib/llvm/utils/TableGen/TableGen.cpp +++ b/contrib/llvm/utils/TableGen/TableGen.cpp @@ -41,7 +41,8 @@ enum ActionType { PrintEnums, PrintSets, GenOptParserDefs, - GenCTags + GenCTags, + GenAttributes }; namespace { @@ -85,6 +86,8 @@ namespace { "Generate option definitions"), clEnumValN(GenCTags, "gen-ctags", "Generate ctags-compatible index"), + clEnumValN(GenAttributes, "gen-attrs", + "Generate attributes"), clEnumValEnd)); cl::opt<std::string> @@ -165,6 +168,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenCTags: EmitCTags(Records, OS); break; + case GenAttributes: + EmitAttributes(Records, OS); + break; } return false; diff --git a/contrib/llvm/utils/TableGen/TableGenBackends.h b/contrib/llvm/utils/TableGen/TableGenBackends.h index 2dc03ce1e71e..d9dd3d157697 100644 --- a/contrib/llvm/utils/TableGen/TableGenBackends.h +++ b/contrib/llvm/utils/TableGen/TableGenBackends.h @@ -78,6 +78,7 @@ void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS); void EmitMapTable(RecordKeeper &RK, raw_ostream &OS); void EmitOptParser(RecordKeeper &RK, raw_ostream &OS); void EmitCTags(RecordKeeper &RK, raw_ostream &OS); +void EmitAttributes(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp index efcb0c81e1ca..8a5ae12f67fb 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -796,12 +796,12 @@ void RecognizableInstr::emitInstructionSpecifier() { 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_EE: case X86Local::MRM_EF: 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; } @@ -951,6 +951,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("f128mem", TYPE_M128) TYPE("f256mem", TYPE_M256) TYPE("f512mem", TYPE_M512) + TYPE("FR128", TYPE_XMM128) TYPE("FR64", TYPE_XMM64) TYPE("FR64X", TYPE_XMM64) TYPE("f64mem", TYPE_M64FP) @@ -1069,6 +1070,7 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, // register IDs in 8-bit immediates nowadays. ENCODING("FR32", ENCODING_IB) ENCODING("FR64", ENCODING_IB) + ENCODING("FR128", ENCODING_IB) ENCODING("VR128", ENCODING_IB) ENCODING("VR256", ENCODING_IB) ENCODING("FR32X", ENCODING_IB) @@ -1091,6 +1093,7 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s, ENCODING("GR8", ENCODING_RM) ENCODING("VR128", ENCODING_RM) ENCODING("VR128X", ENCODING_RM) + ENCODING("FR128", ENCODING_RM) ENCODING("FR64", ENCODING_RM) ENCODING("FR32", ENCODING_RM) ENCODING("FR64X", ENCODING_RM) @@ -1120,6 +1123,7 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s, ENCODING("GR64", ENCODING_REG) ENCODING("GR8", ENCODING_REG) ENCODING("VR128", ENCODING_REG) + ENCODING("FR128", ENCODING_REG) ENCODING("FR64", ENCODING_REG) ENCODING("FR32", ENCODING_REG) ENCODING("VR64", ENCODING_REG) @@ -1157,6 +1161,7 @@ RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s, ENCODING("GR32", ENCODING_VVVV) ENCODING("GR64", ENCODING_VVVV) ENCODING("FR32", ENCODING_VVVV) + ENCODING("FR128", ENCODING_VVVV) ENCODING("FR64", ENCODING_VVVV) ENCODING("VR128", ENCODING_VVVV) ENCODING("VR256", ENCODING_VVVV) |