diff options
Diffstat (limited to 'contrib/llvm/utils')
27 files changed, 809 insertions, 614 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp index 5ee20dd..d8f2619 100644 --- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -264,6 +264,11 @@ public: } /// operator< - Compare two classes. + // FIXME: This ordering seems to be broken. For example: + // u64 < i64, i64 < s8, s8 < u64, forming a cycle + // u64 is a subset of i64 + // i64 and s8 are not subsets of each other, so are ordered by name + // s8 and u64 are not subsets of each other, so are ordered by name bool operator<(const ClassInfo &RHS) const { if (this == &RHS) return false; @@ -433,12 +438,21 @@ struct MatchableInfo { /// If this instruction is deprecated in some form. bool HasDeprecation; + /// If this is an alias, this is use to determine whether or not to using + /// the conversion function defined by the instruction's AsmMatchConverter + /// or to use the function generated by the alias. + bool UseInstAsmMatchConverter; + MatchableInfo(const CodeGenInstruction &CGI) - : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI) { + : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI), + UseInstAsmMatchConverter(true) { } MatchableInfo(std::unique_ptr<const CodeGenInstAlias> Alias) - : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), DefRec(Alias.release()) { + : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), + DefRec(Alias.release()), + UseInstAsmMatchConverter( + TheDef->getValueAsBit("UseInstAsmMatchConverter")) { } ~MatchableInfo() { @@ -979,6 +993,7 @@ static std::string getEnumNameForToken(StringRef Str) { case '.': Res += "_DOT_"; break; case '<': Res += "_LT_"; break; case '>': Res += "_GT_"; break; + case '-': Res += "_MINUS_"; break; default: if ((*it >= 'A' && *it <= 'Z') || (*it >= 'a' && *it <= 'z') || @@ -1446,8 +1461,9 @@ void AsmMatcherInfo::buildInfo() { II->buildAliasResultOperands(); } if (!NewMatchables.empty()) - std::move(NewMatchables.begin(), NewMatchables.end(), - std::back_inserter(Matchables)); + Matchables.insert(Matchables.end(), + std::make_move_iterator(NewMatchables.begin()), + std::make_move_iterator(NewMatchables.end())); // Process token alias definitions and set up the associated superclass // information. @@ -1742,7 +1758,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Check if we have a custom match function. std::string AsmMatchConverter = II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); - if (!AsmMatchConverter.empty()) { + if (!AsmMatchConverter.empty() && II->UseInstAsmMatchConverter) { std::string Signature = "ConvertCustom_" + AsmMatchConverter; II->ConversionFnKind = Signature; @@ -1848,6 +1864,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, case MatchableInfo::ResOperand::ImmOperand: { int64_t Val = OpInfo.ImmVal; std::string Ty = "imm_" + itostr(Val); + Ty = getEnumNameForToken(Ty); Signature += "__" + Ty; std::string Name = "CVT_" + Ty; @@ -1862,7 +1879,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, break; CvtOS << " case " << Name << ":\n" - << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n" + << " Inst.addOperand(MCOperand::createImm(" << Val << "));\n" << " break;\n"; OpOS << " case " << Name << ":\n" @@ -1893,7 +1910,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, if (!IsNewConverter) break; CvtOS << " case " << Name << ":\n" - << " Inst.addOperand(MCOperand::CreateReg(" << Reg << "));\n" + << " Inst.addOperand(MCOperand::createReg(" << Reg << "));\n" << " break;\n"; OpOS << " case " << Name << ":\n" @@ -2240,7 +2257,7 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, Info.AsmParser->getValueAsString("AsmParserClassName"); OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" - << "ComputeAvailableFeatures(uint64_t FB) const {\n"; + << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n"; OS << " uint64_t Features = 0;\n"; for (const auto &SF : Info.SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; @@ -2262,12 +2279,10 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, Cond = Cond.substr(1); } - OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")"; + OS << "("; if (Neg) - OS << " == 0"; - else - OS << " != 0"; - OS << ")"; + OS << "!"; + OS << "FB[" << Info.Target.getName() << "::" << Cond << "])"; if (Comma.second.empty()) break; @@ -2637,7 +2652,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of MCTargetAsmParser.\n"; - OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; + OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n"; OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" << " const OperandVector " @@ -2651,7 +2666,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " bool matchingInlineAsm,\n" << " unsigned VariantID = 0);\n"; - if (Info.OperandMatchInfo.size()) { + if (!Info.OperandMatchInfo.empty()) { OS << "\n enum OperandMatchResultTy {\n"; OS << " MatchOperand_Success, // operand matched successfully\n"; OS << " MatchOperand_NoMatch, // operand did not match\n"; @@ -2879,7 +2894,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " uint64_t MissingFeatures = ~0ULL;\n"; OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; OS << " // wrong for all instances of the instruction.\n"; - OS << " ErrorInfo = ~0U;\n"; + OS << " ErrorInfo = ~0ULL;\n"; // Emit code to search the table. OS << " // Find the appropriate table for this asm variant.\n"; @@ -2954,8 +2969,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " HadMatchOtherThanFeatures = true;\n"; OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " if (CountPopulation_64(NewMissingFeatures) <=\n" - " CountPopulation_64(MissingFeatures))\n"; + OS << " if (countPopulation(NewMissingFeatures) <=\n" + " countPopulation(MissingFeatures))\n"; OS << " MissingFeatures = NewMissingFeatures;\n"; OS << " continue;\n"; OS << " }\n"; @@ -3009,7 +3024,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " return Match_MissingFeature;\n"; OS << "}\n\n"; - if (Info.OperandMatchInfo.size()) + if (!Info.OperandMatchInfo.empty()) emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable, MaxMnemonicIndex); diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp index 5924d5f..389889a 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -278,12 +278,15 @@ static void UnescapeString(std::string &Str) { void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { Record *AsmWriter = Target.getAsmWriter(); std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); + unsigned PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget"); O << "/// printInstruction - This method is automatically generated by tablegen\n" "/// from the instruction set description.\n" "void " << Target.getName() << ClassName - << "::printInstruction(const MCInst *MI, raw_ostream &O) {\n"; + << "::printInstruction(const MCInst *MI, " + << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "") + << "raw_ostream &O) {\n"; // Build an aggregate string, and build a table of offsets into it. SequenceToOffsetTable<std::string> StringTable; @@ -727,7 +730,7 @@ public: OS.flush(); // Emit the string. - O.indent(6) << "AsmString = \"" << OutString.str() << "\";\n"; + O.indent(6) << "AsmString = \"" << OutString << "\";\n"; O.indent(6) << "break;\n"; O.indent(4) << '}'; @@ -787,6 +790,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { // Emit the method that prints the alias instruction. std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); unsigned Variant = AsmWriter->getValueAsInt("Variant"); + unsigned PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget"); std::vector<Record*> AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); @@ -949,7 +953,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { HeaderO << "bool " << Target.getName() << ClassName << "::printAliasInstr(const MCInst" - << " *MI, raw_ostream &OS) {\n"; + << " *MI, " << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "") + << "raw_ostream &OS) {\n"; std::string Cases; raw_string_ostream CasesO(Cases); @@ -998,7 +1003,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { return; } - if (MCOpPredicates.size()) + if (!MCOpPredicates.empty()) O << "static bool " << Target.getName() << ClassName << "ValidateMCOperand(\n" << " const MCOperand &MCOp, unsigned PredicateIndex);\n"; @@ -1027,9 +1032,13 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << " ++I;\n"; O << " int OpIdx = AsmString[I++] - 1;\n"; O << " int PrintMethodIdx = AsmString[I++] - 1;\n"; - O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, OS);\n"; + O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, "; + O << (PassSubtarget ? "STI, " : ""); + O << "OS);\n"; O << " } else\n"; - O << " printOperand(MI, unsigned(AsmString[I++]) - 1, OS);\n"; + O << " printOperand(MI, unsigned(AsmString[I++]) - 1, "; + O << (PassSubtarget ? "STI, " : ""); + O << "OS);\n"; O << " } else {\n"; O << " OS << AsmString[I++];\n"; O << " }\n"; @@ -1046,7 +1055,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << "void " << Target.getName() << ClassName << "::" << "printCustomAliasOperand(\n" << " const MCInst *MI, unsigned OpIdx,\n" - << " unsigned PrintMethodIdx, raw_ostream &OS) {\n"; + << " unsigned PrintMethodIdx,\n" + << (PassSubtarget ? " const MCSubtargetInfo &STI,\n" : "") + << " raw_ostream &OS) {\n"; if (PrintMethods.empty()) O << " llvm_unreachable(\"Unknown PrintMethod kind\");\n"; else { @@ -1057,14 +1068,15 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { for (unsigned i = 0; i < PrintMethods.size(); ++i) { O << " case " << i << ":\n" - << " " << PrintMethods[i] << "(MI, OpIdx, OS);\n" + << " " << PrintMethods[i] << "(MI, OpIdx, " + << (PassSubtarget ? "STI, " : "") << "OS);\n" << " break;\n"; } O << " }\n"; } O << "}\n\n"; - if (MCOpPredicates.size()) { + if (!MCOpPredicates.empty()) { O << "static bool " << Target.getName() << ClassName << "ValidateMCOperand(\n" << " const MCOperand &MCOp, unsigned PredicateIndex) {\n" @@ -1094,7 +1106,8 @@ AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) { for (const CodeGenInstruction *I : Target.instructions()) if (!I->AsmString.empty() && I->TheDef->getName() != "PHI") Instructions.push_back( - AsmWriterInst(*I, AsmWriter->getValueAsInt("Variant"))); + AsmWriterInst(*I, AsmWriter->getValueAsInt("Variant"), + AsmWriter->getValueAsInt("PassSubtarget"))); // Get the instruction numbering. NumberedInstructions = &Target.getInstructionsByEnumValue(); diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.cpp b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp index 6ddc510..a66b1a0 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterInst.cpp +++ b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp @@ -39,6 +39,8 @@ std::string AsmWriterOperand::getCode() const { std::string Result = Str + "(MI"; if (MIOpNo != ~0U) Result += ", " + utostr(MIOpNo); + if (PassSubtarget) + Result += ", STI"; Result += ", O"; if (!MiModifier.empty()) Result += ", \"" + MiModifier + '"'; @@ -48,7 +50,8 @@ std::string AsmWriterOperand::getCode() const { /// ParseAsmString - Parse the specified Instruction's AsmString into this /// AsmWriterInst. /// -AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { +AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant, + unsigned PassSubtarget) { this->CGI = &CGI; // NOTE: Any extensions to this code need to be mirrored in the @@ -163,7 +166,8 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { Operands.push_back(AsmWriterOperand("PrintSpecial", ~0U, ~0U, - Modifier)); + Modifier, + PassSubtarget)); } else { // Otherwise, normal operand. unsigned OpNo = CGI.Operands.getOperandNamed(VarName); @@ -171,7 +175,8 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { unsigned MIOp = OpInfo.MIOperandNo; Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, - OpNo, MIOp, Modifier)); + OpNo, MIOp, Modifier, + PassSubtarget)); } LastEmitted = VarEnd; } diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.h b/contrib/llvm/utils/TableGen/AsmWriterInst.h index 6a900b7..a597e6b 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterInst.h +++ b/contrib/llvm/utils/TableGen/AsmWriterInst.h @@ -53,6 +53,11 @@ namespace llvm { /// an operand, specified with syntax like ${opname:modifier}. std::string MiModifier; + // PassSubtarget - Pass MCSubtargetInfo to the print method if this is + // equal to 1. + // FIXME: Remove after all ports are updated. + unsigned PassSubtarget; + // To make VS STL happy AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {} @@ -64,9 +69,10 @@ namespace llvm { unsigned _CGIOpNo, unsigned _MIOpNo, const std::string &Modifier, + unsigned PassSubtarget, OpType op = isMachineInstrOperand) : OperandType(op), Str(Printer), CGIOpNo(_CGIOpNo), MIOpNo(_MIOpNo), - MiModifier(Modifier) {} + MiModifier(Modifier), PassSubtarget(PassSubtarget) {} bool operator!=(const AsmWriterOperand &Other) const { if (OperandType != Other.OperandType || Str != Other.Str) return true; @@ -88,7 +94,7 @@ namespace llvm { const CodeGenInstruction *CGI; AsmWriterInst(const CodeGenInstruction &CGI, - unsigned Variant); + unsigned Variant, unsigned PassSubtarget); /// MatchesAllButOneOp - If this instruction is exactly identical to the /// specified instruction except for one differing operand, return the diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp index 6a65e5e..051a7e9 100644 --- a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp +++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp @@ -124,7 +124,7 @@ void CallingConvEmitter::EmitAction(Record *Action, } O << "\n" << IndentStr << "};\n"; O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" - << Counter << ", " << RegList->getSize() << ")) {\n"; + << Counter << ")) {\n"; } O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " << "Reg, LocVT, LocInfo));\n"; @@ -166,7 +166,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" << RegListNumber << ", " << "RegList" << ShadowRegListNumber - << ", " << RegList->getSize() << ")) {\n"; + << ")) {\n"; } O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " << "Reg, LocVT, LocInfo));\n"; @@ -182,14 +182,14 @@ void CallingConvEmitter::EmitAction(Record *Action, O << Size << ", "; else O << "\n" << IndentStr - << " State.getMachineFunction().getSubtarget().getDataLayout()" + << " State.getMachineFunction().getTarget().getDataLayout()" "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," " "; if (Align) O << Align; else O << "\n" << IndentStr - << " State.getMachineFunction().getSubtarget().getDataLayout()" + << " State.getMachineFunction().getTarget().getDataLayout()" "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()" "))"; O << ");\n" << IndentStr @@ -215,8 +215,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << IndentStr << "unsigned Offset" << ++Counter << " = State.AllocateStack(" << Size << ", " << Align << ", " - << "ShadowRegList" << ShadowRegListNumber << ", " - << ShadowRegList->getSize() << ");\n"; + << "ShadowRegList" << ShadowRegListNumber << ");\n"; O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" << Counter << ", LocVT, LocInfo));\n"; O << IndentStr << "return false;\n"; diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp index 11911b6..46fcdf5 100644 --- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -96,7 +96,7 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, /// generated emitter, skip it. while (NumberedOp < NumberOps && (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) || - (NamedOpIndices.size() && NamedOpIndices.count( + (!NamedOpIndices.empty() && NamedOpIndices.count( CGI.Operands.getSubOperandNumber(NumberedOp).first)))) { ++NumberedOp; diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index c3de37e..fd02bbd 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -53,7 +53,7 @@ EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) { EnforceVector(TP); else { assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR || - VT == MVT::iPTRAny) && "Not a concrete type!"); + VT == MVT::iPTRAny || VT == MVT::Any) && "Not a concrete type!"); TypeVec.push_back(VT); } } @@ -389,52 +389,6 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { else if (!Other.hasScalarTypes()) MadeChange |= EnforceVector(TP); - // For vectors we need to ensure that smaller size doesn't produce larger - // vector and vice versa. - if (isConcrete() && isVector(getConcrete())) { - MVT IVT = getConcrete(); - unsigned Size = IVT.getSizeInBits(); - - // Only keep types that have at least as many bits. - TypeSet InputSet(Other); - - for (unsigned i = 0; i != Other.TypeVec.size(); ++i) { - assert(isVector(Other.TypeVec[i]) && "EnforceVector didn't work"); - if (MVT(Other.TypeVec[i]).getSizeInBits() < Size) { - Other.TypeVec.erase(Other.TypeVec.begin()+i--); - MadeChange = true; - } - } - - if (Other.TypeVec.empty()) { // FIXME: Really want an SMLoc here! - TP.error("Type inference contradiction found, forcing '" + - InputSet.getName() + "' to have at least as many bits as " + - getName() + "'"); - return false; - } - } else if (Other.isConcrete() && isVector(Other.getConcrete())) { - MVT IVT = Other.getConcrete(); - unsigned Size = IVT.getSizeInBits(); - - // Only keep types with the same or fewer total bits - TypeSet InputSet(*this); - - for (unsigned i = 0; i != TypeVec.size(); ++i) { - assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); - if (MVT(TypeVec[i]).getSizeInBits() > Size) { - TypeVec.erase(TypeVec.begin()+i--); - MadeChange = true; - } - } - - if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! - TP.error("Type inference contradiction found, forcing '" + - InputSet.getName() + "' to have the same or fewer bits than " + - Other.getName() + "'"); - return false; - } - } - // This code does not currently handle nodes which have multiple types, // where some types are integer, and some are fp. Assert that this is not // the case. @@ -445,12 +399,22 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { if (TP.hasError()) return false; - // Okay, find the smallest scalar type from the other set and remove - // anything the same or smaller from the current set. + // Okay, find the smallest type from current set and remove anything the + // same or smaller from the other set. We need to ensure that the scalar + // 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::SimpleValueType Smallest = TypeVec[0]; + MVT Smallest = TypeVec[0]; for (unsigned i = 0; i != Other.TypeVec.size(); ++i) { - if (Other.TypeVec[i] <= Smallest) { + 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; } @@ -462,12 +426,22 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { return false; } - // Okay, find the largest scalar type from the other set and remove - // anything the same or larger from the current set. + // 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::SimpleValueType Largest = Other.TypeVec[Other.TypeVec.size()-1]; + MVT Largest = Other.TypeVec[Other.TypeVec.size()-1]; for (unsigned i = 0; i != TypeVec.size(); ++i) { - if (TypeVec[i] >= Largest) { + 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; } @@ -484,6 +458,34 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type /// whose element is specified by VTOperand. +bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT, + TreePattern &TP) { + bool MadeChange = false; + + MadeChange |= EnforceVector(TP); + + 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; + } + } + + 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; +} + +/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type +/// whose element is specified by VTOperand. bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, TreePattern &TP) { if (TP.hasError()) @@ -609,6 +611,64 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, return MadeChange; } +/// EnforceVectorSameNumElts - 'this' is now constrainted to +/// be a vector with same num elements as VTOperand. +bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand, + TreePattern &TP) { + if (TP.hasError()) + return false; + + // "This" must be a vector and "VTOperand" must be a vector. + bool MadeChange = false; + MadeChange |= EnforceVector(TP); + MadeChange |= VTOperand.EnforceVector(TP); + + // If we know one of the vector types, it forces the other type to agree. + if (isConcrete()) { + MVT IVT = getConcrete(); + unsigned NumElems = IVT.getVectorNumElements(); + + // Only keep types that have same elements as 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; + } + } + 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 '" + + getName() + "'"); + return false; + } + } else if (VTOperand.isConcrete()) { + MVT IVT = VTOperand.getConcrete(); + unsigned NumElems = IVT.getVectorNumElements(); + + // Only keep types that have same elements as '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; + } + } + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have same number elements than '" + + VTOperand.getName() + "'"); + return false; + } + } + + return MadeChange; +} + //===----------------------------------------------------------------------===// // Helpers for working with extended types. @@ -839,9 +899,21 @@ SDTypeConstraint::SDTypeConstraint(Record *R) { ConstraintType = SDTCisSubVecOfVec; x.SDTCisSubVecOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum"); + } else if (R->isSubClassOf("SDTCVecEltisVT")) { + ConstraintType = SDTCVecEltisVT; + x.SDTCVecEltisVT_Info.VT = getValueType(R->getValueAsDef("VT")); + if (MVT(x.SDTCVecEltisVT_Info.VT).isVector()) + PrintFatalError(R->getLoc(), "Cannot use vector type as SDTCVecEltisVT"); + if (!MVT(x.SDTCVecEltisVT_Info.VT).isInteger() && + !MVT(x.SDTCVecEltisVT_Info.VT).isFloatingPoint()) + PrintFatalError(R->getLoc(), "Must use integer or floating point type " + "as SDTCVecEltisVT"); + } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) { + ConstraintType = SDTCisSameNumEltsAs; + x.SDTCisSameNumEltsAs_Info.OtherOperandNum = + R->getValueAsInt("OtherOperandNum"); } else { - errs() << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n"; - exit(1); + PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); } } @@ -859,11 +931,12 @@ static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, OpNo -= NumResults; if (OpNo >= N->getNumChildren()) { - errs() << "Invalid operand number in type constraint " + std::string S; + raw_string_ostream OS(S); + OS << "Invalid operand number in type constraint " << (OpNo+NumResults) << " "; - N->dump(); - errs() << '\n'; - exit(1); + N->print(OS); + PrintFatalError(OS.str()); } return N->getChild(OpNo); @@ -901,8 +974,8 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, unsigned OResNo = 0; TreePatternNode *OtherNode = getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo); - return NodeToApply->UpdateNodeType(OResNo, OtherNode->getExtType(ResNo),TP)| - OtherNode->UpdateNodeType(ResNo,NodeToApply->getExtType(OResNo),TP); + return NodeToApply->UpdateNodeType(ResNo, OtherNode->getExtType(OResNo),TP)| + OtherNode->UpdateNodeType(OResNo,NodeToApply->getExtType(ResNo),TP); } case SDTCisVTSmallerThanOp: { // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must @@ -956,6 +1029,18 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, return BigVecOperand->getExtType(VResNo). EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP); } + case SDTCVecEltisVT: { + return NodeToApply->getExtType(ResNo). + EnforceVectorEltTypeIs(x.SDTCVecEltisVT_Info.VT, TP); + } + case SDTCisSameNumEltsAs: { + unsigned OResNo = 0; + TreePatternNode *OtherNode = + getOperandNum(x.SDTCisSameNumEltsAs_Info.OtherOperandNum, + N, NodeInfo, OResNo); + return OtherNode->getExtType(OResNo). + EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP); + } } llvm_unreachable("Invalid ConstraintType!"); } @@ -1031,9 +1116,9 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { } else if (PropList[i]->getName() == "SDNPVariadic") { Properties |= 1 << SDNPVariadic; } else { - errs() << "Unknown SD Node property '" << PropList[i]->getName() - << "' on node '" << R->getName() << "'!\n"; - exit(1); + PrintFatalError("Unknown SD Node property '" + + PropList[i]->getName() + "' on node '" + + R->getName() + "'!"); } } @@ -1111,8 +1196,16 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { if (Operator->isSubClassOf("Instruction")) { CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); - // FIXME: Should allow access to all the results here. - unsigned NumDefsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; + unsigned NumDefsToAdd = InstInfo.Operands.NumDefs; + + // Subtract any defaulted outputs. + for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) { + Record *OperandNode = InstInfo.Operands[i].Rec; + + if (OperandNode->isSubClassOf("OperandWithDefaultOps") && + !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) + --NumDefsToAdd; + } // Add on one implicit def if it has a resolvable type. if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) @@ -1130,8 +1223,7 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { return 1; Operator->dump(); - errs() << "Unhandled node in GetNumNodeResults\n"; - exit(1); + PrintFatalError("Unhandled node in GetNumNodeResults"); } void TreePatternNode::print(raw_ostream &OS) const { @@ -1689,8 +1781,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Apply the result types to the node, these come from the things in the // (outs) list of the instruction. - // FIXME: Cap at one result so far. - unsigned NumResultsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; + unsigned NumResultsToAdd = std::min(InstInfo.Operands.NumDefs, + Inst.getNumResults()); for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP); @@ -1971,7 +2063,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ } // ?:$name or just $name. - if (TheInit == UnsetInit::get()) { + if (isa<UnsetInit>(TheInit)) { if (OpName.empty()) error("'?' argument requires a name to match with operand list"); TreePatternNode *Res = new TreePatternNode(TheInit, 1); @@ -2280,10 +2372,9 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const { Record *N = Records.getDef(Name); - if (!N || !N->isSubClassOf("SDNode")) { - errs() << "Error getting SDNode '" << Name << "'!\n"; - exit(1); - } + if (!N || !N->isSubClassOf("SDNode")) + PrintFatalError("Error getting SDNode '" + Name + "'!"); + return N; } @@ -2811,159 +2902,161 @@ static bool checkOperandClass(CGIOperandList::OperandInfo &OI, const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) { - assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!"); + assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!"); - // Parse the instruction. - TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this); - // Inline pattern fragments into it. - I->InlinePatternFragments(); + // Parse the instruction. + TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this); + // Inline pattern fragments into it. + I->InlinePatternFragments(); - // Infer as many types as possible. If we cannot infer all of them, we can - // never do anything with this instruction pattern: report it to the user. - if (!I->InferAllTypes()) - I->error("Could not infer all types in pattern!"); + // Infer as many types as possible. If we cannot infer all of them, we can + // never do anything with this instruction pattern: report it to the user. + if (!I->InferAllTypes()) + I->error("Could not infer all types in pattern!"); - // InstInputs - Keep track of all of the inputs of the instruction, along - // with the record they are declared as. - std::map<std::string, TreePatternNode*> InstInputs; + // InstInputs - Keep track of all of the inputs of the instruction, along + // with the record they are declared as. + std::map<std::string, TreePatternNode*> InstInputs; - // InstResults - Keep track of all the virtual registers that are 'set' - // in the instruction, including what reg class they are. - std::map<std::string, TreePatternNode*> InstResults; + // InstResults - Keep track of all the virtual registers that are 'set' + // in the instruction, including what reg class they are. + std::map<std::string, TreePatternNode*> InstResults; - std::vector<Record*> InstImpResults; + std::vector<Record*> InstImpResults; - // Verify that the top-level forms in the instruction are of void type, and - // fill in the InstResults map. - for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { - TreePatternNode *Pat = I->getTree(j); - if (Pat->getNumTypes() != 0) - I->error("Top-level forms in instruction pattern should have" - " void types"); + // Verify that the top-level forms in the instruction are of void type, and + // fill in the InstResults map. + for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { + TreePatternNode *Pat = I->getTree(j); + if (Pat->getNumTypes() != 0) + I->error("Top-level forms in instruction pattern should have" + " void types"); - // Find inputs and outputs, and verify the structure of the uses/defs. - FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, - InstImpResults); - } + // Find inputs and outputs, and verify the structure of the uses/defs. + FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, + InstImpResults); + } - // Now that we have inputs and outputs of the pattern, inspect the operands - // list for the instruction. This determines the order that operands are - // added to the machine instruction the node corresponds to. - unsigned NumResults = InstResults.size(); + // Now that we have inputs and outputs of the pattern, inspect the operands + // list for the instruction. This determines the order that operands are + // added to the machine instruction the node corresponds to. + unsigned NumResults = InstResults.size(); - // Parse the operands list from the (ops) list, validating it. - assert(I->getArgList().empty() && "Args list should still be empty here!"); + // Parse the operands list from the (ops) list, validating it. + assert(I->getArgList().empty() && "Args list should still be empty here!"); - // Check that all of the results occur first in the list. - std::vector<Record*> Results; - TreePatternNode *Res0Node = nullptr; - for (unsigned i = 0; i != NumResults; ++i) { - if (i == CGI.Operands.size()) - I->error("'" + InstResults.begin()->first + - "' set but does not appear in operand list!"); - const std::string &OpName = CGI.Operands[i].Name; + // Check that all of the results occur first in the list. + std::vector<Record*> Results; + SmallVector<TreePatternNode *, 2> ResNodes; + for (unsigned i = 0; i != NumResults; ++i) { + if (i == CGI.Operands.size()) + I->error("'" + InstResults.begin()->first + + "' set but does not appear in operand list!"); + const std::string &OpName = CGI.Operands[i].Name; - // Check that it exists in InstResults. - TreePatternNode *RNode = InstResults[OpName]; - if (!RNode) - I->error("Operand $" + OpName + " does not exist in operand list!"); + // Check that it exists in InstResults. + TreePatternNode *RNode = InstResults[OpName]; + if (!RNode) + I->error("Operand $" + OpName + " does not exist in operand list!"); - if (i == 0) - Res0Node = RNode; - Record *R = cast<DefInit>(RNode->getLeafValue())->getDef(); - if (!R) - I->error("Operand $" + OpName + " should be a set destination: all " - "outputs must occur before inputs in operand list!"); + ResNodes.push_back(RNode); - if (!checkOperandClass(CGI.Operands[i], R)) - I->error("Operand $" + OpName + " class mismatch!"); + Record *R = cast<DefInit>(RNode->getLeafValue())->getDef(); + if (!R) + I->error("Operand $" + OpName + " should be a set destination: all " + "outputs must occur before inputs in operand list!"); - // Remember the return type. - Results.push_back(CGI.Operands[i].Rec); + if (!checkOperandClass(CGI.Operands[i], R)) + I->error("Operand $" + OpName + " class mismatch!"); - // Okay, this one checks out. - InstResults.erase(OpName); - } + // Remember the return type. + Results.push_back(CGI.Operands[i].Rec); - // Loop over the inputs next. Make a copy of InstInputs so we can destroy - // the copy while we're checking the inputs. - std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs); + // Okay, this one checks out. + InstResults.erase(OpName); + } - std::vector<TreePatternNode*> ResultNodeOperands; - std::vector<Record*> Operands; - for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { - CGIOperandList::OperandInfo &Op = CGI.Operands[i]; - const std::string &OpName = Op.Name; - if (OpName.empty()) - I->error("Operand #" + utostr(i) + " in operands list has no name!"); - - if (!InstInputsCheck.count(OpName)) { - // If this is an operand with a DefaultOps set filled in, we can ignore - // this. When we codegen it, we will do so as always executed. - if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) { - // Does it have a non-empty DefaultOps field? If so, ignore this - // operand. - if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) - continue; - } - I->error("Operand $" + OpName + - " does not appear in the instruction pattern"); - } - TreePatternNode *InVal = InstInputsCheck[OpName]; - InstInputsCheck.erase(OpName); // It occurred, remove from map. - - if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) { - Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef(); - if (!checkOperandClass(Op, InRec)) - I->error("Operand $" + OpName + "'s register class disagrees" - " between the operand and pattern"); + // Loop over the inputs next. Make a copy of InstInputs so we can destroy + // the copy while we're checking the inputs. + std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs); + + std::vector<TreePatternNode*> ResultNodeOperands; + std::vector<Record*> Operands; + for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { + CGIOperandList::OperandInfo &Op = CGI.Operands[i]; + const std::string &OpName = Op.Name; + if (OpName.empty()) + I->error("Operand #" + utostr(i) + " in operands list has no name!"); + + if (!InstInputsCheck.count(OpName)) { + // If this is an operand with a DefaultOps set filled in, we can ignore + // this. When we codegen it, we will do so as always executed. + if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) { + // Does it have a non-empty DefaultOps field? If so, ignore this + // operand. + if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) + continue; } - Operands.push_back(Op.Rec); + I->error("Operand $" + OpName + + " does not appear in the instruction pattern"); + } + TreePatternNode *InVal = InstInputsCheck[OpName]; + InstInputsCheck.erase(OpName); // It occurred, remove from map. - // Construct the result for the dest-pattern operand list. - TreePatternNode *OpNode = InVal->clone(); + if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) { + Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef(); + if (!checkOperandClass(Op, InRec)) + I->error("Operand $" + OpName + "'s register class disagrees" + " between the operand and pattern"); + } + Operands.push_back(Op.Rec); - // No predicate is useful on the result. - OpNode->clearPredicateFns(); + // Construct the result for the dest-pattern operand list. + TreePatternNode *OpNode = InVal->clone(); - // Promote the xform function to be an explicit node if set. - if (Record *Xform = OpNode->getTransformFn()) { - OpNode->setTransformFn(nullptr); - std::vector<TreePatternNode*> Children; - Children.push_back(OpNode); - OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); - } + // No predicate is useful on the result. + OpNode->clearPredicateFns(); - ResultNodeOperands.push_back(OpNode); + // Promote the xform function to be an explicit node if set. + if (Record *Xform = OpNode->getTransformFn()) { + OpNode->setTransformFn(nullptr); + std::vector<TreePatternNode*> Children; + Children.push_back(OpNode); + OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); } - if (!InstInputsCheck.empty()) - I->error("Input operand $" + InstInputsCheck.begin()->first + - " occurs in pattern but not in operands list!"); + ResultNodeOperands.push_back(OpNode); + } - TreePatternNode *ResultPattern = - new TreePatternNode(I->getRecord(), ResultNodeOperands, - GetNumNodeResults(I->getRecord(), *this)); - // Copy fully inferred output node type to instruction result pattern. - for (unsigned i = 0; i != NumResults; ++i) - ResultPattern->setType(i, Res0Node->getExtType(i)); + if (!InstInputsCheck.empty()) + I->error("Input operand $" + InstInputsCheck.begin()->first + + " occurs in pattern but not in operands list!"); - // Create and insert the instruction. - // FIXME: InstImpResults should not be part of DAGInstruction. - DAGInstruction TheInst(I, Results, Operands, InstImpResults); - DAGInsts.insert(std::make_pair(I->getRecord(), TheInst)); + TreePatternNode *ResultPattern = + new TreePatternNode(I->getRecord(), ResultNodeOperands, + GetNumNodeResults(I->getRecord(), *this)); + // Copy fully inferred output node types to instruction result pattern. + for (unsigned i = 0; i != NumResults; ++i) { + assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled"); + ResultPattern->setType(i, ResNodes[i]->getExtType(0)); + } - // Use a temporary tree pattern to infer all types and make sure that the - // constructed result is correct. This depends on the instruction already - // being inserted into the DAGInsts map. - TreePattern Temp(I->getRecord(), ResultPattern, false, *this); - Temp.InferAllTypes(&I->getNamedNodesMap()); + // Create and insert the instruction. + // FIXME: InstImpResults should not be part of DAGInstruction. + DAGInstruction TheInst(I, Results, Operands, InstImpResults); + DAGInsts.insert(std::make_pair(I->getRecord(), TheInst)); - DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second; - TheInsertedInst.setResultPattern(Temp.getOnlyTree()); + // Use a temporary tree pattern to infer all types and make sure that the + // constructed result is correct. This depends on the instruction already + // being inserted into the DAGInsts map. + TreePattern Temp(I->getRecord(), ResultPattern, false, *this); + Temp.InferAllTypes(&I->getNamedNodesMap()); - return TheInsertedInst; - } + DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second; + TheInsertedInst.setResultPattern(Temp.getOnlyTree()); + + return TheInsertedInst; +} /// ParseInstructions - Parse all of the instructions, inlining and resolving /// any fragments involved. This populates the Instructions list with fully @@ -2983,25 +3076,20 @@ void CodeGenDAGPatterns::ParseInstructions() { // null_frag operator is as-if no pattern were specified. Normally this // is from a multiclass expansion w/ a SDPatternOperator passed in as // null_frag. - if (!LI || LI->getSize() == 0 || hasNullFragReference(LI)) { + if (!LI || LI->empty() || hasNullFragReference(LI)) { std::vector<Record*> Results; std::vector<Record*> Operands; CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); if (InstInfo.Operands.size() != 0) { - if (InstInfo.Operands.NumDefs == 0) { - // These produce no results - for (unsigned j = 0, e = InstInfo.Operands.size(); j < e; ++j) - Operands.push_back(InstInfo.Operands[j].Rec); - } else { - // Assume the first operand is the result. - Results.push_back(InstInfo.Operands[0].Rec); - - // The rest are inputs. - for (unsigned j = 1, e = InstInfo.Operands.size(); j < e; ++j) - Operands.push_back(InstInfo.Operands[j].Rec); - } + for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j) + Results.push_back(InstInfo.Operands[j].Rec); + + // The rest are inputs. + for (unsigned j = InstInfo.Operands.NumDefs, + e = InstInfo.Operands.size(); j < e; ++j) + Operands.push_back(InstInfo.Operands[j].Rec); } // Create and insert the instruction. @@ -3311,7 +3399,7 @@ void CodeGenDAGPatterns::ParsePatterns() { Pattern->InlinePatternFragments(); ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); - if (LI->getSize() == 0) continue; // no pattern. + if (LI->empty()) continue; // no pattern. // Parse the instruction. TreePattern Result(CurPattern, LI, false, *this); diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h index c0812cf..9ce3cdf 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -136,10 +136,18 @@ namespace EEVT { /// whose element is VT. bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP); + /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type + /// whose element is VT. + bool EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TreePattern &TP); + /// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to /// be a vector type VT. bool EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VT, TreePattern &TP); + /// EnforceVectorSameNumElts - 'this' is now constrainted to + /// be a vector with same num elements as VT. + bool EnforceVectorSameNumElts(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; } @@ -165,7 +173,7 @@ struct SDTypeConstraint { enum { SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs, SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec, - SDTCisSubVecOfVec + SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs } ConstraintType; union { // The discriminated union. @@ -187,6 +195,12 @@ struct SDTypeConstraint { struct { unsigned OtherOperandNum; } SDTCisSubVecOfVec_Info; + struct { + MVT::SimpleValueType VT; + } SDTCVecEltisVT_Info; + struct { + unsigned OtherOperandNum; + } SDTCisSameNumEltsAs_Info; } x; /// ApplyTypeConstraint - Given a node in a pattern, apply this type diff --git a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h index 1f1adf1..f405557 100644 --- a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h +++ b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h @@ -80,6 +80,9 @@ namespace llvm { /// isNoReturn - True if the intrinsic is no-return. bool isNoReturn; + /// isConvergent - True if the intrinsic is marked as convergent. + bool isConvergent; + enum ArgAttribute { NoCapture, ReadOnly, diff --git a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp index 7e5aa9c..b52a91d 100644 --- a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp @@ -128,7 +128,7 @@ public: ListInit *ColValList = MapRec->getValueAsListInit("ValueCols"); // Each instruction map must specify at least one column for it to be valid. - if (ColValList->getSize() == 0) + if (ColValList->empty()) PrintFatalError(MapRec->getLoc(), "InstrMapping record `" + MapRec->getName() + "' has empty " + "`ValueCols' field!"); @@ -376,7 +376,7 @@ unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) { std::vector<Record*> ColInstrs = MapTable[CurInstr]; std::string OutStr(""); unsigned RelExists = 0; - if (ColInstrs.size()) { + if (!ColInstrs.empty()) { for (unsigned j = 0; j < NumCol; j++) { if (ColInstrs[j] != nullptr) { RelExists = 1; @@ -567,7 +567,7 @@ void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) { std::vector<Record*> InstrMapVec; InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); - if (!InstrMapVec.size()) + if (InstrMapVec.empty()) return; OS << "#ifdef GET_INSTRMAP_INFO\n"; diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp index bef8a4b..c6940e9 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp @@ -108,7 +108,7 @@ CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum) EnumValue(Enum), CostPerUse(R->getValueAsInt("CostPerUse")), CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")), - NumNativeRegUnits(0), + HasDisjunctSubRegs(false), SubRegsComplete(false), SuperRegsComplete(false), TopoSig(~0u) @@ -153,11 +153,11 @@ const std::string &CodeGenRegister::getName() const { namespace { // Iterate over all register units in a set of registers. class RegUnitIterator { - CodeGenRegister::Set::const_iterator RegI, RegE; - CodeGenRegister::RegUnitList::const_iterator UnitI, UnitE; + CodeGenRegister::Vec::const_iterator RegI, RegE; + CodeGenRegister::RegUnitList::iterator UnitI, UnitE; public: - RegUnitIterator(const CodeGenRegister::Set &Regs): + RegUnitIterator(const CodeGenRegister::Vec &Regs): RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() { if (RegI != RegE) { @@ -192,32 +192,23 @@ protected: }; } // namespace -// Merge two RegUnitLists maintaining the order and removing duplicates. -// Overwrites MergedRU in the process. -static void mergeRegUnits(CodeGenRegister::RegUnitList &MergedRU, - const CodeGenRegister::RegUnitList &RRU) { - CodeGenRegister::RegUnitList LRU = MergedRU; - MergedRU.clear(); - std::set_union(LRU.begin(), LRU.end(), RRU.begin(), RRU.end(), - std::back_inserter(MergedRU)); -} - // Return true of this unit appears in RegUnits. static bool hasRegUnit(CodeGenRegister::RegUnitList &RegUnits, unsigned Unit) { - return std::count(RegUnits.begin(), RegUnits.end(), Unit); + return RegUnits.test(Unit); } // Inherit register units from subregisters. // Return true if the RegUnits changed. bool CodeGenRegister::inheritRegUnits(CodeGenRegBank &RegBank) { - unsigned OldNumUnits = RegUnits.size(); + bool changed = false; for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end(); I != E; ++I) { CodeGenRegister *SR = I->second; // Merge the subregister's units into this register's RegUnits. - mergeRegUnits(RegUnits, SR->RegUnits); + changed |= (RegUnits |= SR->RegUnits); } - return OldNumUnits != RegUnits.size(); + + return changed; } const CodeGenRegister::SubRegMap & @@ -227,6 +218,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { return SubRegs; SubRegsComplete = true; + HasDisjunctSubRegs = ExplicitSubRegs.size() > 1; + // First insert the explicit subregs and make sure they are fully indexed. for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) { CodeGenRegister *SR = ExplicitSubRegs[i]; @@ -247,6 +240,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) { CodeGenRegister *SR = ExplicitSubRegs[i]; const SubRegMap &Map = SR->computeSubRegs(RegBank); + HasDisjunctSubRegs |= SR->HasDisjunctSubRegs; for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE; ++SI) { @@ -363,14 +357,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { // sub-registers, the other registers won't contribute any more units. for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) { CodeGenRegister *SR = ExplicitSubRegs[i]; - // Explicit sub-registers are usually disjoint, so this is a good way of - // computing the union. We may pick up a few duplicates that will be - // eliminated below. - unsigned N = RegUnits.size(); - RegUnits.append(SR->RegUnits.begin(), SR->RegUnits.end()); - std::inplace_merge(RegUnits.begin(), RegUnits.begin() + N, RegUnits.end()); + RegUnits |= SR->RegUnits; } - RegUnits.erase(std::unique(RegUnits.begin(), RegUnits.end()), RegUnits.end()); // Absent any ad hoc aliasing, we create one register unit per leaf register. // These units correspond to the maximal cliques in the register overlap @@ -389,19 +377,19 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { // Create a RegUnit representing this alias edge, and add it to both // registers. unsigned Unit = RegBank.newRegUnit(this, AR); - RegUnits.push_back(Unit); - AR->RegUnits.push_back(Unit); + RegUnits.set(Unit); + AR->RegUnits.set(Unit); } // Finally, create units for leaf registers without ad hoc aliases. Note that // a leaf register with ad hoc aliases doesn't get its own unit - it isn't // necessary. This means the aliasing leaf registers can share a single unit. if (RegUnits.empty()) - RegUnits.push_back(RegBank.newRegUnit(this)); + RegUnits.set(RegBank.newRegUnit(this)); // We have now computed the native register units. More may be adopted later // for balancing purposes. - NumNativeRegUnits = RegUnits.size(); + NativeRegUnits = RegUnits; return SubRegs; } @@ -535,7 +523,7 @@ CodeGenRegister::addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet, // Get the sum of this register's unit weights. unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const { unsigned Weight = 0; - for (RegUnitList::const_iterator I = RegUnits.begin(), E = RegUnits.end(); + for (RegUnitList::iterator I = RegUnits.begin(), E = RegUnits.end(); I != E; ++I) { Weight += RegBank.getRegUnit(*I).Weight; } @@ -658,6 +646,11 @@ struct TupleExpander : SetTheory::Expander { // CodeGenRegisterClass //===----------------------------------------------------------------------===// +static void sortAndUniqueRegisters(CodeGenRegister::Vec &M) { + std::sort(M.begin(), M.end(), deref<llvm::less>()); + M.erase(std::unique(M.begin(), M.end(), deref<llvm::equal>()), M.end()); +} + CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) : TheDef(R), Name(R->getName()), @@ -667,9 +660,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) // Rename anonymous register classes. if (R->getName().size() > 9 && R->getName()[9] == '.') { static unsigned AnonCounter = 0; - R->setName("AnonRegClass_" + utostr(AnonCounter)); - // MSVC2012 ICEs if AnonCounter++ is directly passed to utostr. - ++AnonCounter; + R->setName("AnonRegClass_" + utostr(AnonCounter++)); } std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes"); @@ -685,19 +676,20 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) // Allocation order 0 is the full set. AltOrders provides others. const SetTheory::RecVec *Elements = RegBank.getSets().expand(R); ListInit *AltOrders = R->getValueAsListInit("AltOrders"); - Orders.resize(1 + AltOrders->size()); + Orders.resize(1 + AltOrders->getSize()); // Default allocation order always contains all registers. for (unsigned i = 0, e = Elements->size(); i != e; ++i) { Orders[0].push_back((*Elements)[i]); const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]); - Members.insert(Reg); + Members.push_back(Reg); TopoSigs.set(Reg->getTopoSig()); } + sortAndUniqueRegisters(Members); // Alternative allocation orders may be subsets. SetTheory::RecSet Order; - for (unsigned i = 0, e = AltOrders->size(); i != e; ++i) { + for (unsigned i = 0, e = AltOrders->getSize(); i != e; ++i) { RegBank.getSets().evaluate(AltOrders->getElement(i), Order, R->getLoc()); Orders[1 + i].append(Order.begin(), Order.end()); // Verify that all altorder members are regclass members. @@ -719,6 +711,10 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) CopyCost = R->getValueAsInt("CopyCost"); Allocatable = R->getValueAsBit("isAllocatable"); AltOrderSelect = R->getValueAsString("AltOrderSelect"); + int AllocationPriority = R->getValueAsInt("AllocationPriority"); + if (AllocationPriority < 0 || AllocationPriority > 63) + PrintFatalError(R->getLoc(), "AllocationPriority out of range [0,63]"); + this->AllocationPriority = AllocationPriority; } // Create an inferred register class that was missing from the .td files. @@ -734,10 +730,10 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, SpillSize(Props.SpillSize), SpillAlignment(Props.SpillAlignment), CopyCost(0), - Allocatable(true) { - for (CodeGenRegister::Set::iterator I = Members.begin(), E = Members.end(); - I != E; ++I) - TopoSigs.set((*I)->getTopoSig()); + Allocatable(true), + AllocationPriority(0) { + for (const auto R : Members) + TopoSigs.set(R->getTopoSig()); } // Compute inherited propertied for a synthesized register class. @@ -755,6 +751,7 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) { CopyCost = Super.CopyCost; Allocatable = Super.Allocatable; AltOrderSelect = Super.AltOrderSelect; + AllocationPriority = Super.AllocationPriority; // Copy all allocation orders, filter out foreign registers from the larger // super-class. @@ -766,15 +763,15 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) { } bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const { - return Members.count(Reg); + return std::binary_search(Members.begin(), Members.end(), Reg, + deref<llvm::less>()); } namespace llvm { raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) { OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment; - for (CodeGenRegister::Set::const_iterator I = K.Members->begin(), - E = K.Members->end(); I != E; ++I) - OS << ", " << (*I)->getName(); + for (const auto R : *K.Members) + OS << ", " << R->getName(); return OS << " }"; } } @@ -800,10 +797,10 @@ operator<(const CodeGenRegisterClass::Key &B) const { static bool testSubClass(const CodeGenRegisterClass *A, const CodeGenRegisterClass *B) { return A->SpillAlignment && B->SpillAlignment % A->SpillAlignment == 0 && - A->SpillSize <= B->SpillSize && - std::includes(A->getMembers().begin(), A->getMembers().end(), - B->getMembers().begin(), B->getMembers().end(), - CodeGenRegister::Less()); + A->SpillSize <= B->SpillSize && + std::includes(A->getMembers().begin(), A->getMembers().end(), + B->getMembers().begin(), B->getMembers().end(), + deref<llvm::less>()); } /// Sorting predicate for register classes. This provides a topological @@ -927,7 +924,7 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { // Configure register Sets to understand register classes and tuples. Sets.addFieldExpander("RegisterClass", "MemberList"); Sets.addFieldExpander("CalleeSavedRegs", "SaveList"); - Sets.addExpander("RegisterTuples", new TupleExpander()); + Sets.addExpander("RegisterTuples", llvm::make_unique<TupleExpander>()); // Read in the user-defined (named) sub-register indices. // More indices will be synthesized later. @@ -1050,7 +1047,7 @@ void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) { // Create a synthetic sub-class if it is missing. CodeGenRegisterClass* CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC, - const CodeGenRegister::Set *Members, + const CodeGenRegister::Vec *Members, StringRef Name) { // Synthetic sub-class has the same size and alignment as RC. CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment); @@ -1273,7 +1270,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() { for (auto &RegClass : RegClasses) { unsigned LaneMask = 0; for (const auto &SubRegIndex : SubRegIndices) { - if (RegClass.getSubClassWithSubReg(&SubRegIndex) != &RegClass) + if (RegClass.getSubClassWithSubReg(&SubRegIndex) == nullptr) continue; LaneMask |= SubRegIndex.LaneMask; } @@ -1299,7 +1296,7 @@ namespace { // for which the unit weight equals the set weight. These units should not have // their weight increased. struct UberRegSet { - CodeGenRegister::Set Regs; + CodeGenRegister::Vec Regs; unsigned Weight; CodeGenRegister::RegUnitList SingularDeterminants; @@ -1328,7 +1325,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets, if (!RegClass.Allocatable) continue; - const CodeGenRegister::Set &Regs = RegClass.getMembers(); + const CodeGenRegister::Vec &Regs = RegClass.getMembers(); if (Regs.empty()) continue; @@ -1336,8 +1333,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets, assert(USetID && "register number 0 is invalid"); AllocatableRegs.insert((*Regs.begin())->EnumValue); - for (CodeGenRegister::Set::const_iterator I = std::next(Regs.begin()), - E = Regs.end(); I != E; ++I) { + for (auto I = std::next(Regs.begin()), E = Regs.end(); I != E; ++I) { AllocatableRegs.insert((*I)->EnumValue); UberSetIDs.join(USetID, (*I)->EnumValue); } @@ -1367,7 +1363,8 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets, USetID = 0; UberRegSet *USet = &UberSets[USetID]; - USet->Regs.insert(&Reg); + USet->Regs.push_back(&Reg); + sortAndUniqueRegisters(USet->Regs); RegSets[i++] = USet; } } @@ -1409,11 +1406,10 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets, } // Find singular determinants. - for (CodeGenRegister::Set::iterator RegI = I->Regs.begin(), - RegE = I->Regs.end(); RegI != RegE; ++RegI) { - if ((*RegI)->getRegUnits().size() == 1 - && (*RegI)->getWeight(RegBank) == I->Weight) - mergeRegUnits(I->SingularDeterminants, (*RegI)->getRegUnits()); + for (const auto R : I->Regs) { + if (R->getRegUnits().count() == 1 && R->getWeight(RegBank) == I->Weight) { + I->SingularDeterminants |= R->getRegUnits(); + } } } } @@ -1431,13 +1427,14 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets, static bool normalizeWeight(CodeGenRegister *Reg, std::vector<UberRegSet> &UberSets, std::vector<UberRegSet*> &RegSets, - std::set<unsigned> &NormalRegs, + SparseBitVector<> &NormalRegs, CodeGenRegister::RegUnitList &NormalUnits, CodeGenRegBank &RegBank) { - bool Changed = false; - if (!NormalRegs.insert(Reg->EnumValue).second) - return Changed; + if (NormalRegs.test(Reg->EnumValue)) + return false; + NormalRegs.set(Reg->EnumValue); + bool Changed = false; const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs(); for (CodeGenRegister::SubRegMap::const_iterator SRI = SRM.begin(), SRE = SRM.end(); SRI != SRE; ++SRI) { @@ -1461,8 +1458,8 @@ static bool normalizeWeight(CodeGenRegister *Reg, // A register unit's weight can be adjusted only if it is the singular unit // for this register, has not been used to normalize a subregister's set, // and has not already been used to singularly determine this UberRegSet. - unsigned AdjustUnit = Reg->getRegUnits().front(); - if (Reg->getRegUnits().size() != 1 + unsigned AdjustUnit = *Reg->getRegUnits().begin(); + if (Reg->getRegUnits().count() != 1 || hasRegUnit(NormalUnits, AdjustUnit) || hasRegUnit(UberSet->SingularDeterminants, AdjustUnit)) { // We don't have an adjustable unit, so adopt a new one. @@ -1480,7 +1477,7 @@ static bool normalizeWeight(CodeGenRegister *Reg, } // Mark these units normalized so superregisters can't change their weights. - mergeRegUnits(NormalUnits, Reg->getRegUnits()); + NormalUnits |= Reg->getRegUnits(); return Changed; } @@ -1505,7 +1502,7 @@ void CodeGenRegBank::computeRegUnitWeights() { Changed = false; for (auto &Reg : Registers) { CodeGenRegister::RegUnitList NormalUnits; - std::set<unsigned> NormalRegs; + SparseBitVector<> NormalRegs; Changed |= normalizeWeight(&Reg, UberSets, RegSets, NormalRegs, NormalUnits, *this); } @@ -1768,7 +1765,7 @@ void CodeGenRegBank::computeRegUnitLaneMasks() { for (auto &Register : Registers) { // Create an initial lane mask for all register units. const auto &RegUnits = Register.getRegUnits(); - CodeGenRegister::RegUnitLaneMaskList RegUnitLaneMasks(RegUnits.size(), 0); + CodeGenRegister::RegUnitLaneMaskList RegUnitLaneMasks(RegUnits.count(), 0); // Iterate through SubRegisters. typedef CodeGenRegister::SubRegMap SubRegMap; const SubRegMap &SubRegs = Register.getSubRegs(); @@ -1783,15 +1780,18 @@ void CodeGenRegBank::computeRegUnitLaneMasks() { const CodeGenRegister *SubRegister = S->second; unsigned LaneMask = SubRegIndex->LaneMask; // Distribute LaneMask to Register Units touched. - for (const auto &SUI : SubRegister->getRegUnits()) { + for (unsigned SUI : SubRegister->getRegUnits()) { bool Found = false; - for (size_t u = 0, ue = RegUnits.size(); u < ue; ++u) { - if (SUI == RegUnits[u]) { + unsigned u = 0; + for (unsigned RU : RegUnits) { + if (SUI == RU) { RegUnitLaneMasks[u] |= LaneMask; assert(!Found); Found = true; } + ++u; } + (void)Found; assert(Found); } } @@ -1813,6 +1813,13 @@ void CodeGenRegBank::computeDerivedInfo() { computeRegUnitLaneMasks(); + // Compute register class HasDisjunctSubRegs flag. + for (CodeGenRegisterClass &RC : RegClasses) { + RC.HasDisjunctSubRegs = false; + for (const CodeGenRegister *Reg : RC.getMembers()) + RC.HasDisjunctSubRegs |= Reg->HasDisjunctSubRegs; + } + // Get the weight of each set. for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx) RegUnitSets[Idx].Weight = getRegUnitSetWeight(RegUnitSets[Idx].Units); @@ -1850,13 +1857,12 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) { continue; // Compute the set intersection of RC1 and RC2. - const CodeGenRegister::Set &Memb1 = RC1->getMembers(); - const CodeGenRegister::Set &Memb2 = RC2->getMembers(); - CodeGenRegister::Set Intersection; - std::set_intersection(Memb1.begin(), Memb1.end(), - Memb2.begin(), Memb2.end(), - std::inserter(Intersection, Intersection.begin()), - CodeGenRegister::Less()); + const CodeGenRegister::Vec &Memb1 = RC1->getMembers(); + const CodeGenRegister::Vec &Memb2 = RC2->getMembers(); + CodeGenRegister::Vec Intersection; + std::set_intersection( + Memb1.begin(), Memb1.end(), Memb2.begin(), Memb2.end(), + std::inserter(Intersection, Intersection.begin()), deref<llvm::less>()); // Skip disjoint class pairs. if (Intersection.empty()) @@ -1882,19 +1888,21 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) { // void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { // Map SubRegIndex to set of registers in RC supporting that SubRegIndex. - typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Set, - CodeGenSubRegIndex::Less> SubReg2SetMap; + typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Vec, + deref<llvm::less>> SubReg2SetMap; // Compute the set of registers supporting each SubRegIndex. SubReg2SetMap SRSets; - for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(), - RE = RC->getMembers().end(); RI != RE; ++RI) { - const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs(); + for (const auto R : RC->getMembers()) { + const CodeGenRegister::SubRegMap &SRM = R->getSubRegs(); for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(), E = SRM.end(); I != E; ++I) - SRSets[I->first].insert(*RI); + SRSets[I->first].push_back(R); } + for (auto I : SRSets) + sortAndUniqueRegisters(I.second); + // Find matching classes for all SRSets entries. Iterate in SubRegIndex // numerical order to visit synthetic indices last. for (const auto &SubIdx : SubRegIndices) { @@ -1939,9 +1947,7 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, // Build list of (Super, Sub) pairs for this SubIdx. SSPairs.clear(); TopoSigs.reset(); - for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(), - RE = RC->getMembers().end(); RI != RE; ++RI) { - const CodeGenRegister *Super = *RI; + for (const auto Super : RC->getMembers()) { const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second; assert(Sub && "Missing sub-register"); SSPairs.push_back(std::make_pair(Super, Sub)); @@ -1960,22 +1966,26 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, if (!TopoSigs.anyCommon(SubRC.getTopoSigs())) continue; // Compute the subset of RC that maps into SubRC. - CodeGenRegister::Set SubSet; + CodeGenRegister::Vec SubSetVec; for (unsigned i = 0, e = SSPairs.size(); i != e; ++i) if (SubRC.contains(SSPairs[i].second)) - SubSet.insert(SSPairs[i].first); - if (SubSet.empty()) + SubSetVec.push_back(SSPairs[i].first); + + if (SubSetVec.empty()) continue; + // RC injects completely into SubRC. - if (SubSet.size() == SSPairs.size()) { + sortAndUniqueRegisters(SubSetVec); + if (SubSetVec.size() == SSPairs.size()) { SubRC.addSuperRegClass(&SubIdx, RC); continue; } + // Only a subset of RC maps into SubRC. Make sure it is represented by a // class. - getOrCreateSubClass(RC, &SubSet, RC->getName() + "_with_" + - SubIdx.getName() + "_in_" + - SubRC.getName()); + getOrCreateSubClass(RC, &SubSetVec, RC->getName() + "_with_" + + SubIdx.getName() + "_in_" + + SubRC.getName()); } } } diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h index 87a0dcf..dc44143 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.h +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h @@ -18,7 +18,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SparseBitVector.h" #include "llvm/CodeGen/MachineValueType.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Record.h" @@ -40,10 +42,10 @@ namespace llvm { struct MaskRolPair { unsigned Mask; uint8_t RotateLeft; - bool operator==(const MaskRolPair Other) { + bool operator==(const MaskRolPair Other) const { return Mask == Other.Mask && RotateLeft == Other.RotateLeft; } - bool operator!=(const MaskRolPair Other) { + bool operator!=(const MaskRolPair Other) const { return Mask != Other.Mask || RotateLeft != Other.RotateLeft; } }; @@ -72,17 +74,9 @@ namespace llvm { const std::string &getNamespace() const { return Namespace; } std::string getQualifiedName() const; - // Order CodeGenSubRegIndex pointers by EnumValue. - struct Less { - bool operator()(const CodeGenSubRegIndex *A, - const CodeGenSubRegIndex *B) const { - assert(A && B); - return A->EnumValue < B->EnumValue; - } - }; - // Map of composite subreg indices. - typedef std::map<CodeGenSubRegIndex*, CodeGenSubRegIndex*, Less> CompMap; + typedef std::map<CodeGenSubRegIndex *, CodeGenSubRegIndex *, + deref<llvm::less>> CompMap; // Returns the subreg index that results from composing this with Idx. // Returns NULL if this and Idx don't compose. @@ -124,16 +118,22 @@ namespace llvm { CompMap Composed; }; + inline bool operator<(const CodeGenSubRegIndex &A, + const CodeGenSubRegIndex &B) { + return A.EnumValue < B.EnumValue; + } + /// CodeGenRegister - Represents a register definition. struct CodeGenRegister { Record *TheDef; unsigned EnumValue; unsigned CostPerUse; bool CoveredBySubRegs; + bool HasDisjunctSubRegs; // Map SubRegIndex -> Register. - typedef std::map<CodeGenSubRegIndex*, CodeGenRegister*, - CodeGenSubRegIndex::Less> SubRegMap; + typedef std::map<CodeGenSubRegIndex *, CodeGenRegister *, deref<llvm::less>> + SubRegMap; CodeGenRegister(Record *R, unsigned Enum); @@ -197,23 +197,23 @@ namespace llvm { } // List of register units in ascending order. - typedef SmallVector<unsigned, 16> RegUnitList; + typedef SparseBitVector<> RegUnitList; typedef SmallVector<unsigned, 16> RegUnitLaneMaskList; // How many entries in RegUnitList are native? - unsigned NumNativeRegUnits; + RegUnitList NativeRegUnits; // Get the list of register units. // This is only valid after computeSubRegs() completes. const RegUnitList &getRegUnits() const { return RegUnits; } ArrayRef<unsigned> getRegUnitLaneMasks() const { - return makeArrayRef(RegUnitLaneMasks).slice(0, NumNativeRegUnits); + return makeArrayRef(RegUnitLaneMasks).slice(0, NativeRegUnits.count()); } // Get the native register units. This is a prefix of getRegUnits(). - ArrayRef<unsigned> getNativeRegUnits() const { - return makeArrayRef(RegUnits).slice(0, NumNativeRegUnits); + RegUnitList getNativeRegUnits() const { + return NativeRegUnits; } void setRegUnitLaneMasks(const RegUnitLaneMaskList &LaneMasks) { @@ -225,23 +225,14 @@ namespace llvm { bool inheritRegUnits(CodeGenRegBank &RegBank); // Adopt a register unit for pressure tracking. - // A unit is adopted iff its unit number is >= NumNativeRegUnits. - void adoptRegUnit(unsigned RUID) { RegUnits.push_back(RUID); } + // A unit is adopted iff its unit number is >= NativeRegUnits.count(). + void adoptRegUnit(unsigned RUID) { RegUnits.set(RUID); } // Get the sum of this register's register unit weights. unsigned getWeight(const CodeGenRegBank &RegBank) const; - // Order CodeGenRegister pointers by EnumValue. - struct Less { - bool operator()(const CodeGenRegister *A, - const CodeGenRegister *B) const { - assert(A && B); - return A->EnumValue < B->EnumValue; - } - }; - // Canonically ordered set. - typedef std::set<const CodeGenRegister*, Less> Set; + typedef std::vector<const CodeGenRegister*> Vec; private: bool SubRegsComplete; @@ -265,9 +256,16 @@ namespace llvm { RegUnitLaneMaskList RegUnitLaneMasks; }; + inline bool operator<(const CodeGenRegister &A, const CodeGenRegister &B) { + return A.EnumValue < B.EnumValue; + } + + inline bool operator==(const CodeGenRegister &A, const CodeGenRegister &B) { + return A.EnumValue == B.EnumValue; + } class CodeGenRegisterClass { - CodeGenRegister::Set Members; + CodeGenRegister::Vec Members; // Allocation orders. Order[0] always contains all registers in Members. std::vector<SmallVector<Record*, 16> > Orders; // Bit mask of sub-classes including this, indexed by their EnumValue. @@ -308,8 +306,11 @@ namespace llvm { int CopyCost; bool Allocatable; std::string AltOrderSelect; + uint8_t AllocationPriority; /// Contains the combination of the lane masks of all subregisters. unsigned LaneMask; + /// True if there are at least 2 subregisters which do not interfere. + bool HasDisjunctSubRegs; // Return the Record that defined this class, or NULL if the class was // created by TableGen. @@ -388,7 +389,7 @@ namespace llvm { // Get the set of registers. This set contains the same registers as // getOrder(0). - const CodeGenRegister::Set &getMembers() const { return Members; } + const CodeGenRegister::Vec &getMembers() const { return Members; } // Get a bit vector of TopoSigs present in this register class. const BitVector &getTopoSigs() const { return TopoSigs; } @@ -402,11 +403,11 @@ namespace llvm { // sub-classes. Note the ordering provided by this key is not the same as // the topological order used for the EnumValues. struct Key { - const CodeGenRegister::Set *Members; + const CodeGenRegister::Vec *Members; unsigned SpillSize; unsigned SpillAlignment; - Key(const CodeGenRegister::Set *M, unsigned S = 0, unsigned A = 0) + Key(const CodeGenRegister::Vec *M, unsigned S = 0, unsigned A = 0) : Members(M), SpillSize(S), SpillAlignment(A) {} Key(const CodeGenRegisterClass &RC) @@ -524,7 +525,7 @@ namespace llvm { // Create a synthetic sub-class if it is missing. CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC, - const CodeGenRegister::Set *Membs, + const CodeGenRegister::Vec *Membs, StringRef Name); // Infer missing register classes. diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp index bfdf8dc..58363e8 100644 --- a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp @@ -93,8 +93,8 @@ CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK, // Allow Set evaluation to recognize the dags used in InstRW records: // (instrs Op1, Op1...) - Sets.addOperator("instrs", new InstrsOp); - Sets.addOperator("instregex", new InstRegexOp(Target)); + Sets.addOperator("instrs", llvm::make_unique<InstrsOp>()); + Sets.addOperator("instregex", llvm::make_unique<InstRegexOp>(Target)); // Instantiate a CodeGenProcModel for each SchedMachineModel with the values // that are explicitly referenced in tablegen records. Resources associated diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp index e727a0e..0765370 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp @@ -57,6 +57,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::i32: return "MVT::i32"; case MVT::i64: return "MVT::i64"; case MVT::i128: return "MVT::i128"; + case MVT::Any: return "MVT::Any"; case MVT::iAny: return "MVT::iAny"; case MVT::fAny: return "MVT::fAny"; case MVT::vAny: return "MVT::vAny"; @@ -98,6 +99,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v4i64: return "MVT::v4i64"; case MVT::v8i64: return "MVT::v8i64"; case MVT::v16i64: return "MVT::v16i64"; + case MVT::v1i128: return "MVT::v1i128"; case MVT::v2f16: return "MVT::v2f16"; case MVT::v4f16: return "MVT::v4f16"; case MVT::v8f16: return "MVT::v8f16"; @@ -409,9 +411,9 @@ ComplexPattern::ComplexPattern(Record *R) { } else if (PropList[i]->getName() == "SDNPWantParent") { Properties |= 1 << SDNPWantParent; } else { - errs() << "Unsupported SD Node property '" << PropList[i]->getName() - << "' on ComplexPattern '" << R->getName() << "'!\n"; - exit(1); + PrintFatalError("Unsupported SD Node property '" + + PropList[i]->getName() + "' on ComplexPattern '" + + R->getName() + "'!"); } } @@ -442,6 +444,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { canThrow = false; isNoReturn = false; isNoDuplicate = false; + isConvergent = false; if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") @@ -572,6 +575,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { canThrow = true; else if (Property->getName() == "IntrNoDuplicate") isNoDuplicate = true; + else if (Property->getName() == "IntrConvergent") + isConvergent = true; else if (Property->getName() == "IntrNoReturn") isNoReturn = true; else if (Property->isSubClassOf("NoCapture")) { diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.h b/contrib/llvm/utils/TableGen/DAGISelMatcher.h index 9df3b41..a8a6ba5 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcher.h +++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.h @@ -194,7 +194,7 @@ public: ScopeMatcher(ArrayRef<Matcher *> children) : Matcher(Scope), Children(children.begin(), children.end()) { } - virtual ~ScopeMatcher(); + ~ScopeMatcher() override; unsigned getNumChildren() const { return Children.size(); } @@ -507,7 +507,7 @@ class SwitchOpcodeMatcher : public Matcher { public: SwitchOpcodeMatcher(ArrayRef<std::pair<const SDNodeInfo*, Matcher*> > cases) : Matcher(SwitchOpcode), Cases(cases.begin(), cases.end()) {} - virtual ~SwitchOpcodeMatcher(); + ~SwitchOpcodeMatcher() override; static inline bool classof(const Matcher *N) { return N->getKind() == SwitchOpcode; @@ -561,7 +561,7 @@ class SwitchTypeMatcher : public Matcher { public: SwitchTypeMatcher(ArrayRef<std::pair<MVT::SimpleValueType, Matcher*> > cases) : Matcher(SwitchType), Cases(cases.begin(), cases.end()) {} - virtual ~SwitchTypeMatcher(); + ~SwitchTypeMatcher() override; static inline bool classof(const Matcher *N) { return N->getKind() == SwitchType; diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp index 302f27b..4659dc1 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -188,7 +188,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, << " children in Scope"; } - OS << '\n' << TmpBuf.str(); + OS << '\n' << TmpBuf; CurrentIdx += ChildSize; } @@ -342,7 +342,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, if (!OmitComments) OS << "// ->" << CurrentIdx+ChildSize; OS << '\n'; - OS << TmpBuf.str(); + OS << TmpBuf; CurrentIdx += ChildSize; } diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp index eb80619..9663b71 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -220,7 +220,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { } // An UnsetInit represents a named node without any constraints. - if (N->getLeafValue() == UnsetInit::get()) { + if (isa<UnsetInit>(N->getLeafValue())) { assert(N->hasName() && "Unnamed ? leaf"); return; } @@ -268,8 +268,10 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { // We can't model ComplexPattern uses that don't have their name taken yet. // The OPC_CheckComplexPattern operation implicitly records the results. if (N->getName().empty()) { - errs() << "We expect complex pattern uses to have names: " << *N << "\n"; - exit(1); + std::string S; + raw_string_ostream OS(S); + OS << "We expect complex pattern uses to have names: " << *N; + PrintFatalError(OS.str()); } // Remember this ComplexPattern so that we can emit it after all the other diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp index ea14cb9..5060b6e 100644 --- a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp @@ -472,7 +472,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { current->canAddInsnClass(InsnClass)) { const State *NewState; current->AddInsnClass(InsnClass, NewStateResources); - assert(NewStateResources.size() && "New states must be generated"); + assert(!NewStateResources.empty() && "New states must be generated"); // // If we have seen this state before, then do not create a new state. diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index 7c29422..7905b1a 100644 --- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -333,8 +333,8 @@ protected: // Parent emitter const FixedLenDecoderEmitter *Emitter; - FilterChooser(const FilterChooser &) LLVM_DELETED_FUNCTION; - void operator=(const FilterChooser &) LLVM_DELETED_FUNCTION; + FilterChooser(const FilterChooser &) = delete; + void operator=(const FilterChooser &) = delete; public: FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, @@ -540,7 +540,7 @@ void Filter::recurse() { // Starts by inheriting our parent filter chooser's filter bit values. std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues); - if (VariableInstructions.size()) { + if (!VariableInstructions.empty()) { // Conservatively marks each segment position as BIT_UNSET. for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) BitValueArray[StartBit + bitIndex] = BIT_UNSET; @@ -676,7 +676,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { // Returns the number of fanout produced by the filter. More fanout implies // the filter distinguishes more categories of instructions. unsigned Filter::usefulness() const { - if (VariableInstructions.size()) + if (!VariableInstructions.empty()) return FilteredInstructions.size(); else return FilteredInstructions.size() + 1; @@ -848,7 +848,7 @@ emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates, // The predicate function is just a big switch statement based on the // input predicate index. OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, " - << "uint64_t Bits) {\n"; + << "const FeatureBitset& Bits) {\n"; Indentation += 2; if (!Predicates.empty()) { OS.indent(Indentation) << "switch (Idx) {\n"; @@ -1054,7 +1054,7 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, << "(MI, tmp, Address, Decoder)" << Emitter->GuardPostfix << "\n"; else - o.indent(Indentation) << "MI.addOperand(MCOperand::CreateImm(tmp));\n"; + o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n"; } @@ -1091,7 +1091,7 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, // overkill for now, though. // Make sure the predicate is in the table. - Decoders.insert(Decoder.str()); + Decoders.insert(StringRef(Decoder)); // Now figure out the index for when we write out the table. DecoderSet::const_iterator P = std::find(Decoders.begin(), Decoders.end(), @@ -1102,16 +1102,17 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, static void emitSinglePredicateMatch(raw_ostream &o, StringRef str, const std::string &PredicateNamespace) { if (str[0] == '!') - o << "!(Bits & " << PredicateNamespace << "::" - << str.slice(1,str.size()) << ")"; + o << "!Bits[" << PredicateNamespace << "::" + << str.slice(1,str.size()) << "]"; else - o << "(Bits & " << PredicateNamespace << "::" << str << ")"; + o << "Bits[" << PredicateNamespace << "::" << str << "]"; } bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, unsigned Opc) const { ListInit *Predicates = AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates"); + bool IsFirstEmission = true; for (unsigned i = 0; i < Predicates->getSize(); ++i) { Record *Pred = Predicates->getElementAsRecord(i); if (!Pred->getValue("AssemblerMatcherPredicate")) @@ -1122,7 +1123,7 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, if (!P.length()) continue; - if (i != 0) + if (!IsFirstEmission) o << " && "; StringRef SR(P); @@ -1133,6 +1134,7 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, pairs = pairs.second.split(','); } emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace); + IsFirstEmission = false; } return Predicates->getSize() > 0; } @@ -1780,7 +1782,7 @@ static bool populateInstruction(CodeGenTarget &Target, unsigned NumberOps = CGI.Operands.size(); while (NumberedOp < NumberOps && (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) || - (NamedOpIndices.size() && NamedOpIndices.count( + (!NamedOpIndices.empty() && NamedOpIndices.count( CGI.Operands.getSubOperandNumber(NumberedOp).first)))) ++NumberedOp; @@ -2010,7 +2012,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) { << " InsnType insn, uint64_t Address,\n" << " const void *DisAsm,\n" << " const MCSubtargetInfo &STI) {\n" - << " uint64_t Bits = STI.getFeatureBits();\n" + << " const FeatureBitset& Bits = STI.getFeatureBits();\n" << "\n" << " const uint8_t *Ptr = DecodeTable;\n" << " uint32_t CurFieldValue = 0;\n" diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp index fe30d60..7b69de5 100644 --- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -248,7 +248,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n"; OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n"; - OS << "namespace llvm {"; + OS << "namespace llvm {\n"; OS << "namespace " << Namespace << " {\n"; OS << "namespace " << OpNameNS << " { \n"; OS << "enum {\n"; @@ -264,7 +264,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n"; OS << "#undef GET_INSTRINFO_NAMED_OPS\n"; - OS << "namespace llvm {"; + OS << "namespace llvm {\n"; OS << "namespace " << Namespace << " {\n"; OS << "LLVM_READONLY\n"; OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n"; @@ -315,7 +315,7 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS, OS << "\n#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n"; OS << "#undef GET_INSTRINFO_OPERAND_TYPES_ENUM\n"; - OS << "namespace llvm {"; + OS << "namespace llvm {\n"; OS << "namespace " << Namespace << " {\n"; OS << "namespace OpTypes { \n"; OS << "enum OperandType {\n"; @@ -430,7 +430,8 @@ void InstrInfoEmitter::run(raw_ostream &OS) { std::string ClassName = TargetName + "GenInstrInfo"; OS << "namespace llvm {\n"; OS << "struct " << ClassName << " : public TargetInstrInfo {\n" - << " explicit " << ClassName << "(int SO = -1, int DO = -1);\n" + << " explicit " << ClassName + << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1);\n" << " virtual ~" << ClassName << "();\n" << "};\n"; OS << "} // End llvm namespace \n"; @@ -444,10 +445,11 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n"; OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; OS << "extern const char " << TargetName << "InstrNameData[];\n"; - OS << ClassName << "::" << ClassName << "(int SO, int DO)\n" - << " : TargetInstrInfo(SO, DO) {\n" - << " InitMCInstrInfo(" << TargetName << "Insts, " - << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " + OS << ClassName << "::" << ClassName + << "(int CFSetupOpcode, int CFDestroyOpcode)\n" + << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode) {\n" + << " InitMCInstrInfo(" << TargetName << "Insts, " << TargetName + << "InstrNameIndices, " << TargetName << "InstrNameData, " << NumberedInstructions.size() << ");\n}\n" << ClassName << "::~" << ClassName << "() {}\n"; OS << "} // End llvm namespace \n"; @@ -476,7 +478,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, << SchedModels.getSchedClassIdx(Inst) << ",\t" << Inst.TheDef->getValueAsInt("Size") << ",\t0"; - // Emit all of the target indepedent flags... + // Emit all of the target independent flags... if (Inst.isPseudo) OS << "|(1<<MCID::Pseudo)"; if (Inst.isReturn) OS << "|(1<<MCID::Return)"; if (Inst.isBranch) OS << "|(1<<MCID::Branch)"; @@ -547,15 +549,15 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, CodeGenTarget &Target = CDP.getTargetInfo(); if (Inst.HasComplexDeprecationPredicate) // Emit a function pointer to the complex predicate method. - OS << ",0" + OS << ", -1 " << ",&get" << Inst.DeprecatedReason << "DeprecationInfo"; else if (!Inst.DeprecatedReason.empty()) // Emit the Subtarget feature. - OS << "," << Target.getInstNamespace() << "::" << Inst.DeprecatedReason - << ",nullptr"; + OS << ", " << Target.getInstNamespace() << "::" << Inst.DeprecatedReason + << " ,nullptr"; else // Instruction isn't deprecated. - OS << ",0,nullptr"; + OS << ", -1 ,nullptr"; OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; } @@ -573,10 +575,8 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) { // We must emit the PHI opcode first... std::string Namespace = Target.getInstNamespace(); - if (Namespace.empty()) { - fprintf(stderr, "No instructions defined!\n"); - exit(1); - } + if (Namespace.empty()) + PrintFatalError("No instructions defined!"); const std::vector<const CodeGenInstruction*> &NumberedInstructions = Target.getInstructionsByEnumValue(); diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp index c0cf92d..3f62f20 100644 --- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -259,7 +259,9 @@ enum IIT_Info { IIT_VARARG = 28, IIT_HALF_VEC_ARG = 29, IIT_SAME_VEC_WIDTH_ARG = 30, - IIT_PTR_TO_ARG = 31 + IIT_PTR_TO_ARG = 31, + IIT_VEC_OF_PTRS_TO_ELT = 32, + IIT_I128 = 33 }; @@ -274,6 +276,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, case 16: return Sig.push_back(IIT_I16); case 32: return Sig.push_back(IIT_I32); case 64: return Sig.push_back(IIT_I64); + case 128: return Sig.push_back(IIT_I128); } } @@ -291,7 +294,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, } } -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) #pragma optimize("",off) // MSVC 2010 optimizer can't deal with this function. #endif @@ -309,17 +312,18 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, Sig.push_back(IIT_HALF_VEC_ARG); else if (R->isSubClassOf("LLVMVectorSameWidth")) { Sig.push_back(IIT_SAME_VEC_WIDTH_ARG); - Sig.push_back((Number << 2) | ArgCodes[Number]); + Sig.push_back((Number << 3) | ArgCodes[Number]); MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy")); EncodeFixedValueType(VT, Sig); return; } - else if (R->isSubClassOf("LLVMPointerTo")) { + else if (R->isSubClassOf("LLVMPointerTo")) Sig.push_back(IIT_PTR_TO_ARG); - } + else if (R->isSubClassOf("LLVMVectorOfPointersToElt")) + Sig.push_back(IIT_VEC_OF_PTRS_TO_ELT); else Sig.push_back(IIT_ARG); - return Sig.push_back((Number << 2) | ArgCodes[Number]); + return Sig.push_back((Number << 3) | ArgCodes[Number]); } MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT")); @@ -330,7 +334,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, case MVT::iPTRAny: ++Tmp; // FALL THROUGH. case MVT::vAny: ++Tmp; // FALL THROUGH. case MVT::fAny: ++Tmp; // FALL THROUGH. - case MVT::iAny: { + case MVT::iAny: ++Tmp; // FALL THROUGH. + case MVT::Any: { // If this is an "any" valuetype, then the type is the type of the next // type in the list specified to getIntrinsic(). Sig.push_back(IIT_ARG); @@ -339,8 +344,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, unsigned ArgNo = ArgCodes.size(); ArgCodes.push_back(Tmp); - // Encode what sort of argument it must be in the low 2 bits of the ArgNo. - return Sig.push_back((ArgNo << 2) | Tmp); + // Encode what sort of argument it must be in the low 3 bits of the ArgNo. + return Sig.push_back((ArgNo << 3) | Tmp); } case MVT::iPTR: { @@ -378,7 +383,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, EncodeFixedValueType(VT, Sig); } -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) #pragma optimize("",on) #endif @@ -532,6 +537,9 @@ struct AttributeComparator { if (L->isNoReturn != R->isNoReturn) return R->isNoReturn; + if (L->isConvergent != R->isConvergent) + return R->isConvergent; + // Try to order by readonly/readnone attribute. ModRefKind LK = getModRefKind(*L); ModRefKind RK = getModRefKind(*R); @@ -644,7 +652,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { ModRefKind modRef = getModRefKind(intrinsic); if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn || - intrinsic.isNoDuplicate) { + intrinsic.isNoDuplicate || intrinsic.isConvergent) { OS << " const Attribute::AttrKind Atts[] = {"; bool addComma = false; if (!intrinsic.canThrow) { @@ -663,6 +671,12 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << "Attribute::NoDuplicate"; addComma = true; } + if (intrinsic.isConvergent) { + if (addComma) + OS << ","; + OS << "Attribute::Convergent"; + addComma = true; + } switch (modRef) { case MRK_none: break; diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp index ebb43f0..01e41d1 100644 --- a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp @@ -232,12 +232,12 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { << " TmpInst.addOperand(MCOp);\n"; break; case OpData::Imm: - o << " TmpInst.addOperand(MCOperand::CreateImm(" + o << " TmpInst.addOperand(MCOperand::createImm(" << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n"; break; case OpData::Reg: { Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg; - o << " TmpInst.addOperand(MCOperand::CreateReg("; + o << " TmpInst.addOperand(MCOperand::createReg("; // "zero_reg" is special. if (Reg->getName() == "zero_reg") o << "0"; diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp index 1c3de4a..a8423a9 100644 --- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -180,7 +180,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" << " static const RegClassWeight RCWeightTable[] = {\n"; for (const auto &RC : RegBank.getRegClasses()) { - const CodeGenRegister::Set &Regs = RC.getMembers(); + const CodeGenRegister::Vec &Regs = RC.getMembers(); if (Regs.empty()) OS << " {0, 0"; else { @@ -233,7 +233,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, OS << "// Get the name of this register unit pressure set.\n" << "const char *" << ClassName << "::\n" << "getRegPressureSetName(unsigned Idx) const {\n" - << " static const char *PressureNameTable[] = {\n"; + << " static const char *const PressureNameTable[] = {\n"; unsigned MaxRegUnitWeight = 0; for (unsigned i = 0; i < NumSets; ++i ) { const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); @@ -247,7 +247,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, OS << "// Get the register unit pressure limit for this dimension.\n" << "// This limit must be adjusted dynamically for reserved registers.\n" << "unsigned " << ClassName << "::\n" - << "getRegPressureSetLimit(unsigned Idx) const {\n" + << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const {\n" << " static const " << getMinimalTypeForRange(MaxRegUnitWeight) << " PressureLimitTable[] = {\n"; for (unsigned i = 0; i < NumSets; ++i ) { @@ -573,11 +573,11 @@ typedef SmallVector<unsigned, 4> MaskVec; // Differentially encode a sequence of numbers into V. The starting value and // terminating 0 are not added to V, so it will have the same size as List. static -DiffVec &diffEncode(DiffVec &V, unsigned InitVal, ArrayRef<unsigned> List) { +DiffVec &diffEncode(DiffVec &V, unsigned InitVal, SparseBitVector<> List) { assert(V.empty() && "Clear DiffVec before diffEncode."); uint16_t Val = uint16_t(InitVal); - for (unsigned i = 0; i != List.size(); ++i) { - uint16_t Cur = List[i]; + + for (uint16_t Cur : List) { V.push_back(Cur - Val); Val = Cur; } @@ -610,17 +610,19 @@ static void printMask(raw_ostream &OS, unsigned Val) { static bool combine(const CodeGenSubRegIndex *Idx, SmallVectorImpl<CodeGenSubRegIndex*> &Vec) { const CodeGenSubRegIndex::CompMap &Map = Idx->getComposites(); - for (CodeGenSubRegIndex::CompMap::const_iterator - I = Map.begin(), E = Map.end(); I != E; ++I) { - CodeGenSubRegIndex *&Entry = Vec[I->first->EnumValue - 1]; - if (Entry && Entry != I->second) + for (const auto &I : Map) { + CodeGenSubRegIndex *&Entry = Vec[I.first->EnumValue - 1]; + if (Entry && Entry != I.second) return false; } // All entries are compatible. Make it so. - for (CodeGenSubRegIndex::CompMap::const_iterator - I = Map.begin(), E = Map.end(); I != E; ++I) - Vec[I->first->EnumValue - 1] = I->second; + for (const auto &I : Map) { + auto *&Entry = Vec[I.first->EnumValue - 1]; + assert((!Entry || Entry == I.second) && + "Expected EnumValue to be unique"); + Entry = I.second; + } return true; } @@ -714,16 +716,7 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, for (size_t s = 0, se = Sequences.size(); s != se; ++s, SIdx = NextSIdx) { SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s]; NextSIdx = SIdx + Sequence.size() + 1; - if (Sequence.size() != IdxSequence.size()) - continue; - bool Identical = true; - for (size_t o = 0, oe = Sequence.size(); o != oe; ++o) { - if (Sequence[o] != IdxSequence[o]) { - Identical = false; - break; - } - } - if (Identical) { + if (Sequence == IdxSequence) { Found = SIdx; break; } @@ -759,7 +752,7 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, Idx += Sequence.size() + 1; } OS << " };\n" - " static const MaskRolOp *CompositeSequences[] = {\n"; + " static const MaskRolOp *const CompositeSequences[] = {\n"; for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) { OS << " "; unsigned Idx = SubReg2SequenceIndexMap[i]; @@ -815,7 +808,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // Keep track of sub-register names as well. These are not differentially // encoded. typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec; - SequenceToOffsetTable<SubRegIdxVec, CodeGenSubRegIndex::Less> SubRegIdxSeqs; + SequenceToOffsetTable<SubRegIdxVec, deref<llvm::less>> SubRegIdxSeqs; SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size()); SequenceToOffsetTable<std::string> RegStrings; @@ -856,13 +849,13 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // // Check the neighboring registers for arithmetic progressions. unsigned ScaleA = ~0u, ScaleB = ~0u; - ArrayRef<unsigned> RUs = Reg.getNativeRegUnits(); + SparseBitVector<> RUs = Reg.getNativeRegUnits(); if (I != Regs.begin() && - std::prev(I)->getNativeRegUnits().size() == RUs.size()) - ScaleB = RUs.front() - std::prev(I)->getNativeRegUnits().front(); + std::prev(I)->getNativeRegUnits().count() == RUs.count()) + ScaleB = *RUs.begin() - *std::prev(I)->getNativeRegUnits().begin(); if (std::next(I) != Regs.end() && - std::next(I)->getNativeRegUnits().size() == RUs.size()) - ScaleA = std::next(I)->getNativeRegUnits().front() - RUs.front(); + std::next(I)->getNativeRegUnits().count() == RUs.count()) + ScaleA = *std::next(I)->getNativeRegUnits().begin() - *RUs.begin(); unsigned Scale = std::min(ScaleB, ScaleA); // Default the scale to 0 if it can't be encoded in 4 bits. if (Scale >= 16) @@ -1095,7 +1088,8 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, << " unsigned getRegUnitWeight(unsigned RegUnit) const override;\n" << " unsigned getNumRegPressureSets() const override;\n" << " const char *getRegPressureSetName(unsigned Idx) const override;\n" - << " unsigned getRegPressureSetLimit(unsigned Idx) const override;\n" + << " unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned " + "Idx) const override;\n" << " const int *getRegClassPressureSets(" << "const TargetRegisterClass *RC) const override;\n" << " const int *getRegUnitPressureSets(" @@ -1205,7 +1199,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Compress the sub-reg index lists. typedef std::vector<const CodeGenSubRegIndex*> IdxList; SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size()); - SequenceToOffsetTable<IdxList, CodeGenSubRegIndex::Less> SuperRegIdxSeqs; + SequenceToOffsetTable<IdxList, deref<llvm::less>> SuperRegIdxSeqs; BitVector MaskBV(RegisterClasses.size()); for (const auto &RC : RegisterClasses) { @@ -1292,7 +1286,10 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + " << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n " - << format("0x%08x,\n ", RC.LaneMask); + << format("0x%08x,\n ", RC.LaneMask) + << (unsigned)RC.AllocationPriority << ",\n " + << (RC.HasDisjunctSubRegs?"true":"false") + << ", /* HasDisjunctSubRegs */\n "; if (RC.getSuperClasses().empty()) OS << "NullRegClasses,\n "; else diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp index 9f2fc92..de9c7a6 100644 --- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCInstrItineraries.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/TableGen/Error.h" @@ -62,7 +63,7 @@ class SubtargetEmitter { CodeGenSchedModels &SchedModels; std::string Target; - void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits); + void Enumeration(raw_ostream &OS, const char *ClassName); unsigned FeatureKeyValues(raw_ostream &OS); unsigned CPUKeyValues(raw_ostream &OS); void FormItineraryStageString(const std::string &Names, @@ -112,8 +113,7 @@ public: // Enumeration - Emit the specified class as an enumeration. // void SubtargetEmitter::Enumeration(raw_ostream &OS, - const char *ClassName, - bool isBits) { + const char *ClassName) { // Get all records of class and sort std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName); std::sort(DefList.begin(), DefList.end(), LessRecord()); @@ -121,50 +121,28 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS, unsigned N = DefList.size(); if (N == 0) return; - if (N > 64) { - errs() << "Too many (> 64) subtarget features!\n"; - exit(1); - } + if (N > MAX_SUBTARGET_FEATURES) + PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES."); OS << "namespace " << Target << " {\n"; - // For bit flag enumerations with more than 32 items, emit constants. - // Emit an enum for everything else. - if (isBits && N > 32) { - // For each record - for (unsigned i = 0; i < N; i++) { - // Next record - Record *Def = DefList[i]; - - // Get and emit name and expression (1 << i) - OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n"; - } - } else { - // Open enumeration - OS << "enum {\n"; - - // For each record - for (unsigned i = 0; i < N;) { - // Next record - Record *Def = DefList[i]; + // Open enumeration. Use a 64-bit underlying type. + OS << "enum : uint64_t {\n"; - // Get and emit name - OS << " " << Def->getName(); - - // If bit flags then emit expression (1 << i) - if (isBits) OS << " = " << " 1ULL << " << i; - - // Depending on 'if more in the list' emit comma - if (++i < N) OS << ","; + // For each record + for (unsigned i = 0; i < N;) { + // Next record + Record *Def = DefList[i]; - OS << "\n"; - } + // Get and emit name + OS << " " << Def->getName() << " = " << i; + if (++i < N) OS << ","; - // Close enumeration - OS << "};\n"; + OS << "\n"; } - OS << "}\n"; + // Close enumeration and namespace + OS << "};\n}\n"; } // @@ -198,22 +176,24 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { if (CommandLineName.empty()) continue; - // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in } + // Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in } } OS << " { " << "\"" << CommandLineName << "\", " << "\"" << Desc << "\", " - << Target << "::" << Name << ", "; + << "{ " << Target << "::" << Name << " }, "; const std::vector<Record*> &ImpliesList = Feature->getValueAsListOfDefs("Implies"); if (ImpliesList.empty()) { - OS << "0ULL"; + OS << "{ }"; } else { + OS << "{ "; for (unsigned j = 0, M = ImpliesList.size(); j < M;) { OS << Target << "::" << ImpliesList[j]->getName(); - if (++j < M) OS << " | "; + if (++j < M) OS << ", "; } + OS << " }"; } OS << " }"; @@ -255,22 +235,24 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { const std::vector<Record*> &FeatureList = Processor->getValueAsListOfDefs("Features"); - // Emit as { "cpu", "description", f1 | f2 | ... fn }, + // Emit as { "cpu", "description", { f1 , f2 , ... fn } }, OS << " { " << "\"" << Name << "\", " << "\"Select the " << Name << " processor\", "; if (FeatureList.empty()) { - OS << "0ULL"; + OS << "{ }"; } else { + OS << "{ "; for (unsigned j = 0, M = FeatureList.size(); j < M;) { OS << Target << "::" << FeatureList[j]->getName(); - if (++j < M) OS << " | "; + if (++j < M) OS << ", "; } + OS << " }"; } - // The "0" is for the "implies" section of this data structure. - OS << ", 0ULL }"; + // The { } is for the "implies" section of this data structure. + OS << ", { } }"; // Depending on 'if more in the list' emit comma if (++i < N) OS << ","; @@ -404,7 +386,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS, OS << "}\n"; std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP"); - if (BPs.size()) { + if (!BPs.empty()) { OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name << "\"\n" << "namespace " << Name << "Bypass {\n"; @@ -1398,7 +1380,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, } OS << " InitMCProcessorInfo(CPU, FS);\n" - << " uint64_t Bits = getFeatureBits();\n"; + << " const FeatureBitset& Bits = getFeatureBits();\n"; for (unsigned i = 0; i < Features.size(); i++) { // Next record @@ -1408,12 +1390,12 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, const std::string &Attribute = R->getValueAsString("Attribute"); if (Value=="true" || Value=="false") - OS << " if ((Bits & " << Target << "::" - << Instance << ") != 0) " + OS << " if (Bits[" << Target << "::" + << Instance << "]) " << Attribute << " = " << Value << ";\n"; else - OS << " if ((Bits & " << Target << "::" - << Instance << ") != 0 && " + OS << " if (Bits[" << Target << "::" + << Instance << "] && " << Attribute << " < " << Value << ") " << Attribute << " = " << Value << ";\n"; } @@ -1431,7 +1413,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#undef GET_SUBTARGETINFO_ENUM\n"; OS << "namespace llvm {\n"; - Enumeration(OS, "SubtargetFeature", true); + Enumeration(OS, "SubtargetFeature"); OS << "} // End llvm namespace \n"; OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; @@ -1487,6 +1469,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n"; OS << "#include \"llvm/Support/Debug.h\"\n"; + OS << "#include \"llvm/Support/raw_ostream.h\"\n"; ParseFeaturesFunction(OS, NumFeatures, NumProcs); OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerShared.h b/contrib/llvm/utils/TableGen/X86DisassemblerShared.h index 5895277..e5889e9 100644 --- a/contrib/llvm/utils/TableGen/X86DisassemblerShared.h +++ b/contrib/llvm/utils/TableGen/X86DisassemblerShared.h @@ -10,7 +10,7 @@ #ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H #define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H -#include <string.h> +#include <cstring> #include <string> #include "../../lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h" diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp index fbe5502..f59652c 100644 --- a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp +++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp @@ -215,11 +215,17 @@ static inline bool inheritsFrom(InstructionContext child, return inheritsFrom(child, IC_EVEX_W_K) || inheritsFrom(child, IC_EVEX_L_W_K); case IC_EVEX_XS_K: + case IC_EVEX_XS_K_B: + case IC_EVEX_XS_KZ_B: return inheritsFrom(child, IC_EVEX_W_XS_K) || inheritsFrom(child, IC_EVEX_L_W_XS_K); case IC_EVEX_XD_K: + case IC_EVEX_XD_K_B: + case IC_EVEX_XD_KZ_B: return inheritsFrom(child, IC_EVEX_W_XD_K) || inheritsFrom(child, IC_EVEX_L_W_XD_K); + case IC_EVEX_XS_B: + case IC_EVEX_XD_B: case IC_EVEX_K_B: case IC_EVEX_KZ: return false; @@ -253,17 +259,27 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_W_KZ: case IC_EVEX_W_XS_KZ: case IC_EVEX_W_XD_KZ: + case IC_EVEX_W_XS_B: + case IC_EVEX_W_XD_B: + case IC_EVEX_W_XS_K_B: + case IC_EVEX_W_XD_K_B: + case IC_EVEX_W_XS_KZ_B: + case IC_EVEX_W_XD_KZ_B: case IC_EVEX_W_OPSIZE_KZ: case IC_EVEX_W_OPSIZE_KZ_B: return false; case IC_EVEX_L_KZ: case IC_EVEX_L_XS_KZ: + case IC_EVEX_L_XS_B: + case IC_EVEX_L_XS_K_B: case IC_EVEX_L_XD_KZ: case IC_EVEX_L_OPSIZE_KZ: case IC_EVEX_L_OPSIZE_KZ_B: return false; case IC_EVEX_L_W_K: case IC_EVEX_L_W_XS_K: + case IC_EVEX_L_W_XS_B: + case IC_EVEX_L_W_XS_K_B: case IC_EVEX_L_W_XD_K: case IC_EVEX_L_W_OPSIZE_K: case IC_EVEX_L_W_OPSIZE_B: @@ -279,6 +295,7 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_L2_K_B: case IC_EVEX_L2_KZ_B: case IC_EVEX_L2_XS_K: + case IC_EVEX_L2_XS_K_B: case IC_EVEX_L2_XS_B: case IC_EVEX_L2_XD_B: case IC_EVEX_L2_XD_K: @@ -294,6 +311,8 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_L2_W_K: case IC_EVEX_L2_W_B: case IC_EVEX_L2_W_XS_K: + case IC_EVEX_L2_W_XS_B: + case IC_EVEX_L2_W_XS_K_B: case IC_EVEX_L2_W_XD_K: case IC_EVEX_L2_W_XD_B: case IC_EVEX_L2_W_OPSIZE_K: @@ -585,7 +604,8 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, o << "static const struct OperandSpecifier x86OperandSets[][" << X86_MAX_OPERANDS << "] = {\n"; - typedef std::vector<std::pair<const char *, const char *> > OperandListTy; + typedef SmallVector<std::pair<OperandEncoding, OperandType>, + X86_MAX_OPERANDS> OperandListTy; std::map<OperandListTy, unsigned> OperandSets; unsigned OperandSetNum = 0; @@ -594,12 +614,10 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS; ++OperandIndex) { - const char *Encoding = - stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[Index] - .operands[OperandIndex].encoding); - const char *Type = - stringForOperandType((OperandType)InstructionSpecifiers[Index] - .operands[OperandIndex].type); + OperandEncoding Encoding = (OperandEncoding)InstructionSpecifiers[Index] + .operands[OperandIndex].encoding; + OperandType Type = (OperandType)InstructionSpecifiers[Index] + .operands[OperandIndex].type; OperandList.push_back(std::make_pair(Encoding, Type)); } unsigned &N = OperandSets[OperandList]; @@ -609,8 +627,9 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, o << " { /* " << (OperandSetNum - 1) << " */\n"; for (unsigned i = 0, e = OperandList.size(); i != e; ++i) { - o << " { " << OperandList[i].first << ", " - << OperandList[i].second << " },\n"; + const char *Encoding = stringForOperandEncoding(OperandList[i].first); + const char *Type = stringForOperandType(OperandList[i].second); + o << " { " << Encoding << ", " << Type << " },\n"; } o << " },\n"; } @@ -622,32 +641,24 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, i++; for (unsigned index = 0; index < NumInstructions; ++index) { - o.indent(i * 2) << "{ /* " << index << " */" << "\n"; + o.indent(i * 2) << "{ /* " << index << " */\n"; i++; OperandListTy OperandList; for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS; ++OperandIndex) { - const char *Encoding = - stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index] - .operands[OperandIndex].encoding); - const char *Type = - stringForOperandType((OperandType)InstructionSpecifiers[index] - .operands[OperandIndex].type); + OperandEncoding Encoding = (OperandEncoding)InstructionSpecifiers[index] + .operands[OperandIndex].encoding; + OperandType Type = (OperandType)InstructionSpecifiers[index] + .operands[OperandIndex].type; OperandList.push_back(std::make_pair(Encoding, Type)); } o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n"; - o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */"; - o << "\n"; + o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */\n"; i--; - o.indent(i * 2) << "}"; - - if (index + 1 < NumInstructions) - o << ","; - - o << "\n"; + o.indent(i * 2) << "},\n"; } i--; diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp index 198ad10..ae461bc 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -28,54 +28,65 @@ using namespace llvm; MAP(C2, 34) \ MAP(C3, 35) \ MAP(C4, 36) \ - MAP(C8, 37) \ - MAP(C9, 38) \ - MAP(CA, 39) \ - MAP(CB, 40) \ - MAP(CF, 41) \ - MAP(D0, 42) \ - MAP(D1, 43) \ - MAP(D4, 44) \ - MAP(D5, 45) \ - MAP(D6, 46) \ - MAP(D7, 47) \ - MAP(D8, 48) \ - MAP(D9, 49) \ - MAP(DA, 50) \ - MAP(DB, 51) \ - MAP(DC, 52) \ - MAP(DD, 53) \ - MAP(DE, 54) \ - MAP(DF, 55) \ - MAP(E0, 56) \ - MAP(E1, 57) \ - MAP(E2, 58) \ - MAP(E3, 59) \ - MAP(E4, 60) \ - MAP(E5, 61) \ - MAP(E8, 62) \ - MAP(E9, 63) \ - MAP(EA, 64) \ - MAP(EB, 65) \ - MAP(EC, 66) \ - MAP(ED, 67) \ - MAP(EE, 68) \ - MAP(F0, 69) \ - MAP(F1, 70) \ - MAP(F2, 71) \ - MAP(F3, 72) \ - MAP(F4, 73) \ - MAP(F5, 74) \ - MAP(F6, 75) \ - MAP(F7, 76) \ - MAP(F8, 77) \ - MAP(F9, 78) \ - MAP(FA, 79) \ - MAP(FB, 80) \ - MAP(FC, 81) \ - MAP(FD, 82) \ - MAP(FE, 83) \ - MAP(FF, 84) + MAP(C5, 37) \ + MAP(C6, 38) \ + MAP(C7, 39) \ + MAP(C8, 40) \ + MAP(C9, 41) \ + MAP(CA, 42) \ + MAP(CB, 43) \ + MAP(CC, 44) \ + MAP(CD, 45) \ + MAP(CE, 46) \ + MAP(CF, 47) \ + MAP(D0, 48) \ + MAP(D1, 49) \ + MAP(D2, 50) \ + MAP(D3, 51) \ + MAP(D4, 52) \ + MAP(D5, 53) \ + MAP(D6, 54) \ + MAP(D7, 55) \ + MAP(D8, 56) \ + MAP(D9, 57) \ + MAP(DA, 58) \ + MAP(DB, 59) \ + MAP(DC, 60) \ + MAP(DD, 61) \ + MAP(DE, 62) \ + MAP(DF, 63) \ + MAP(E0, 64) \ + MAP(E1, 65) \ + MAP(E2, 66) \ + MAP(E3, 67) \ + MAP(E4, 68) \ + MAP(E5, 69) \ + MAP(E6, 70) \ + MAP(E7, 71) \ + MAP(E8, 72) \ + MAP(E9, 73) \ + MAP(EA, 74) \ + MAP(EB, 75) \ + MAP(EC, 76) \ + MAP(ED, 77) \ + MAP(EE, 78) \ + MAP(EF, 79) \ + MAP(F0, 80) \ + MAP(F1, 81) \ + MAP(F2, 82) \ + MAP(F3, 83) \ + MAP(F4, 84) \ + MAP(F5, 85) \ + MAP(F6, 86) \ + MAP(F7, 87) \ + MAP(F8, 88) \ + MAP(F9, 89) \ + MAP(FA, 90) \ + MAP(FB, 91) \ + MAP(FC, 92) \ + MAP(FD, 93) \ + MAP(FE, 94) \ + MAP(FF, 95) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { @@ -514,7 +525,7 @@ void RecognizableInstr::emitInstructionSpecifier() { assert(numOperands <= X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough"); for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) { - if (OperandList[operandIndex].Constraints.size()) { + if (!OperandList[operandIndex].Constraints.empty()) { const CGIOperandList::ConstraintInfo &Constraint = OperandList[operandIndex].Constraints[0]; if (Constraint.isTied()) { @@ -803,9 +814,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { // Special cases where the LLVM tables are not complete #define MAP(from, to) \ - case X86Local::MRM_##from: \ - filter = new ExactFilter(0x##from); \ - break; + case X86Local::MRM_##from: OpcodeType opcodeType = (OpcodeType)-1; @@ -854,6 +863,8 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { filter = new ExtendedFilter(false, Form - X86Local::MRM0m); break; MRM_MAPPING + filter = new ExactFilter(0xC0 + Form - X86Local::MRM_C0); \ + break; } // switch (Form) opcodeToSet = Opcode; @@ -932,6 +943,8 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("GR64", TYPE_R64) TYPE("i8mem", TYPE_M8) TYPE("i8imm", TYPE_IMM8) + TYPE("u8imm", TYPE_UIMM8) + TYPE("i32u8imm", TYPE_UIMM8) TYPE("GR8", TYPE_R8) TYPE("VR128", TYPE_XMM128) TYPE("VR128X", TYPE_XMM128) @@ -954,7 +967,9 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i16imm_pcrel", TYPE_REL16) TYPE("i32imm_pcrel", TYPE_REL32) TYPE("SSECC", TYPE_IMM3) + TYPE("XOPCC", TYPE_IMM3) TYPE("AVXCC", TYPE_IMM5) + TYPE("AVX512ICC", TYPE_AVX512ICC) TYPE("AVX512RC", TYPE_IMM32) TYPE("brtarget32", TYPE_RELv) TYPE("brtarget16", TYPE_RELv) @@ -1034,7 +1049,9 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, } ENCODING("i32i8imm", ENCODING_IB) ENCODING("SSECC", ENCODING_IB) + ENCODING("XOPCC", ENCODING_IB) ENCODING("AVXCC", ENCODING_IB) + ENCODING("AVX512ICC", ENCODING_IB) ENCODING("AVX512RC", ENCODING_IB) ENCODING("i16imm", ENCODING_Iv) ENCODING("i16i8imm", ENCODING_IB) @@ -1042,6 +1059,8 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, ENCODING("i64i32imm", ENCODING_ID) ENCODING("i64i8imm", ENCODING_IB) ENCODING("i8imm", ENCODING_IB) + ENCODING("u8imm", ENCODING_IB) + ENCODING("i32u8imm", ENCODING_IB) // This is not a typo. Instructions like BLENDVPD put // register IDs in 8-bit immediates nowadays. ENCODING("FR32", ENCODING_IB) @@ -1077,6 +1096,8 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s, ENCODING("VR256X", ENCODING_RM) ENCODING("VR512", ENCODING_RM) ENCODING("VK1", ENCODING_RM) + ENCODING("VK2", ENCODING_RM) + ENCODING("VK4", ENCODING_RM) ENCODING("VK8", ENCODING_RM) ENCODING("VK16", ENCODING_RM) ENCODING("VK32", ENCODING_RM) @@ -1114,8 +1135,12 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s, ENCODING("VK32", ENCODING_REG) ENCODING("VK64", ENCODING_REG) ENCODING("VK1WM", ENCODING_REG) + ENCODING("VK2WM", ENCODING_REG) + ENCODING("VK4WM", ENCODING_REG) ENCODING("VK8WM", ENCODING_REG) ENCODING("VK16WM", ENCODING_REG) + ENCODING("VK32WM", ENCODING_REG) + ENCODING("VK64WM", ENCODING_REG) errs() << "Unhandled reg/opcode register encoding " << s << "\n"; llvm_unreachable("Unhandled reg/opcode register encoding"); } @@ -1210,6 +1235,8 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s, ENCODING("i64i32imm", ENCODING_ID) ENCODING("i64i8imm", ENCODING_IB) ENCODING("i8imm", ENCODING_IB) + ENCODING("u8imm", ENCODING_IB) + ENCODING("i32u8imm", ENCODING_IB) ENCODING("i64i32imm_pcrel", ENCODING_ID) ENCODING("i16imm_pcrel", ENCODING_IW) ENCODING("i32imm_pcrel", ENCODING_ID) |