diff options
author | Stephen Hines <srhines@google.com> | 2014-12-01 14:51:49 -0800 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-12-02 16:08:10 -0800 |
commit | 37ed9c199ca639565f6ce88105f9e39e898d82d0 (patch) | |
tree | 8fb36d3910e3ee4c4e1b7422f4f017108efc52f5 /utils | |
parent | d2327b22152ced7bc46dc629fc908959e8a52d03 (diff) | |
download | external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.zip external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.gz external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.bz2 |
Update aosp/master LLVM for rebase to r222494.
Change-Id: Ic787f5e0124df789bd26f3f24680f45e678eef2d
Diffstat (limited to 'utils')
62 files changed, 1208 insertions, 603 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index d88cf36..59affa1 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -50,6 +50,18 @@ static cl::opt<bool> NoCanonicalizeWhiteSpace("strict-whitespace", cl::desc("Do not treat all horizontal whitespace as equivalent")); +static cl::list<std::string> ImplicitCheckNot( + "implicit-check-not", + cl::desc("Add an implicit negative check with this pattern to every\n" + "positive check. This can be used to ensure that no instances of\n" + "this pattern occur which are not matched by a positive pattern"), + cl::value_desc("pattern")); + +static cl::opt<bool> AllowEmptyInput( + "allow-empty", cl::init(false), + cl::desc("Allow the input file to be empty. This is useful when making\n" + "checks that some error message does not occur, for example.")); + typedef cl::list<std::string>::const_iterator prefix_iterator; //===----------------------------------------------------------------------===// @@ -624,8 +636,9 @@ struct CheckString { /// /// \param PreserveHorizontal Don't squash consecutive horizontal whitespace /// characters to a single space. -static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB, - bool PreserveHorizontal) { +static std::unique_ptr<MemoryBuffer> +CanonicalizeInputFile(std::unique_ptr<MemoryBuffer> MB, + bool PreserveHorizontal) { SmallString<128> NewFile; NewFile.reserve(MB->getBufferSize()); @@ -650,12 +663,8 @@ static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB, ++Ptr; } - // Free the old buffer and return a new one. - MemoryBuffer *MB2 = - MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier()); - - delete MB; - return MB2; + return std::unique_ptr<MemoryBuffer>( + MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier())); } static bool IsPartOfWord(char c) { @@ -830,14 +839,34 @@ static bool ReadCheckFile(SourceMgr &SM, // If we want to canonicalize whitespace, strip excess whitespace from the // buffer containing the CHECK lines. Remove DOS style line endings. - MemoryBuffer *F = CanonicalizeInputFile(FileOrErr.get().release(), - NoCanonicalizeWhiteSpace); - - SM.AddNewSourceBuffer(F, SMLoc()); + std::unique_ptr<MemoryBuffer> F = CanonicalizeInputFile( + std::move(FileOrErr.get()), NoCanonicalizeWhiteSpace); // Find all instances of CheckPrefix followed by : in the file. StringRef Buffer = F->getBuffer(); - std::vector<Pattern> DagNotMatches; + + SM.AddNewSourceBuffer(std::move(F), SMLoc()); + + std::vector<Pattern> ImplicitNegativeChecks; + for (const auto &PatternString : ImplicitCheckNot) { + // Create a buffer with fake command line content in order to display the + // command line option responsible for the specific implicit CHECK-NOT. + std::string Prefix = std::string("-") + ImplicitCheckNot.ArgStr + "='"; + std::string Suffix = "'"; + std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy( + Prefix + PatternString + Suffix, "command line"); + + StringRef PatternInBuffer = + CmdLine->getBuffer().substr(Prefix.size(), PatternString.size()); + SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc()); + + ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot)); + ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer, + "IMPLICIT-CHECK", SM, 0); + } + + + std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks; // LineNumber keeps track of the line on which CheckPrefix instances are // found. @@ -910,6 +939,7 @@ static bool ReadCheckFile(SourceMgr &SM, PatternLoc, CheckTy)); std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); + DagNotMatches = ImplicitNegativeChecks; } // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first @@ -1185,7 +1215,11 @@ static bool ValidateCheckPrefixes() { I != E; ++I) { StringRef Prefix(*I); - if (!PrefixSet.insert(Prefix)) + // Reject empty prefixes. + if (Prefix == "") + return false; + + if (!PrefixSet.insert(Prefix).second) return false; if (!ValidateCheckPrefix(Prefix)) @@ -1231,27 +1265,27 @@ int main(int argc, char **argv) { << "': " << EC.message() << '\n'; return 2; } - std::unique_ptr<MemoryBuffer> File = std::move(FileOrErr.get()); + std::unique_ptr<MemoryBuffer> &File = FileOrErr.get(); - if (File->getBufferSize() == 0) { + if (File->getBufferSize() == 0 && !AllowEmptyInput) { errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; return 2; } // Remove duplicate spaces in the input file if requested. // Remove DOS style line endings. - MemoryBuffer *F = - CanonicalizeInputFile(File.release(), NoCanonicalizeWhiteSpace); - - SM.AddNewSourceBuffer(F, SMLoc()); - - /// VariableTable - This holds all the current filecheck variables. - StringMap<StringRef> VariableTable; + std::unique_ptr<MemoryBuffer> F = + CanonicalizeInputFile(std::move(File), NoCanonicalizeWhiteSpace); // Check that we have all of the expected strings, in order, in the input // file. StringRef Buffer = F->getBuffer(); + SM.AddNewSourceBuffer(std::move(F), SMLoc()); + + /// VariableTable - This holds all the current filecheck variables. + StringMap<StringRef> VariableTable; + bool hasError = false; unsigned i = 0, j = 0, e = CheckStrings.size(); diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 1277086..891328f 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -448,7 +448,7 @@ struct MatchableInfo { void formTwoOperandAlias(StringRef Constraint); void initialize(const AsmMatcherInfo &Info, - SmallPtrSet<Record*, 16> &SingletonRegisters, + SmallPtrSetImpl<Record*> &SingletonRegisters, int AsmVariantNo, std::string &RegisterPrefix); /// validate - Return true if this matchable is a valid thing to match against @@ -565,9 +565,9 @@ struct SubtargetFeatureInfo { Record *TheDef; /// \brief An unique index assigned to represent this feature. - unsigned Index; + uint64_t Index; - SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} + SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {} /// \brief The name of the enumerated constant identifying this feature. std::string getEnumName() const { @@ -644,7 +644,7 @@ private: /// buildRegisterClasses - Build the ClassInfo* instances for register /// classes. - void buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters); + void buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters); /// buildOperandClasses - Build the ClassInfo* instances for user defined /// operand classes. @@ -766,7 +766,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { } void MatchableInfo::initialize(const AsmMatcherInfo &Info, - SmallPtrSet<Record*, 16> &SingletonRegisters, + SmallPtrSetImpl<Record*> &SingletonRegisters, int AsmVariantNo, std::string &RegisterPrefix) { AsmVariantID = AsmVariantNo; AsmString = @@ -1075,7 +1075,7 @@ struct LessRegisterSet { }; void AsmMatcherInfo:: -buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { +buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) { const std::vector<CodeGenRegister*> &Registers = Target.getRegBank().getRegisters(); ArrayRef<CodeGenRegisterClass*> RegClassList = @@ -1093,7 +1093,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { (*it)->getOrder().begin(), (*it)->getOrder().end())); // Add any required singleton sets. - for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), + for (SmallPtrSetImpl<Record*>::iterator it = SingletonRegisters.begin(), ie = SingletonRegisters.end(); it != ie; ++it) { Record *Rec = *it; RegisterSets.insert(RegisterSet(&Rec, &Rec + 1)); @@ -1191,7 +1191,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { RegisterClasses[it->first] = RegisterSetClasses[it->second]; // Name the register classes which correspond to singleton registers. - for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), + for (SmallPtrSetImpl<Record*>::iterator it = SingletonRegisters.begin(), ie = SingletonRegisters.end(); it != ie; ++it) { Record *Rec = *it; ClassInfo *CI = RegisterClasses[Rec]; @@ -1327,10 +1327,10 @@ void AsmMatcherInfo::buildInfo() { if (Pred->getName().empty()) PrintFatalError(Pred->getLoc(), "Predicate has no name!"); - unsigned FeatureNo = SubtargetFeatures.size(); + uint64_t FeatureNo = SubtargetFeatures.size(); SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); DEBUG(SubtargetFeatures[Pred]->dump()); - assert(FeatureNo < 32 && "Too many subtarget features!"); + assert(FeatureNo < 64 && "Too many subtarget features!"); } // Parse the instructions; we need to do this first so that we can gather the @@ -2205,7 +2205,9 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, } static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range <= 0xFFFFFFFFULL && "Enum too large"); + assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFFFFFFULL) + return "uint64_t"; if (Range > 0xFFFF) return "uint32_t"; if (Range > 0xFF) @@ -2232,7 +2234,7 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { SubtargetFeatureInfo &SFI = *it->second; - OS << " " << SFI.getEnumName() << " = (1U << " << SFI.Index << "),\n"; + OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; } OS << " Feature_None = 0\n"; OS << "};\n\n"; @@ -2263,7 +2265,7 @@ static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "// User-level names for subtarget features that participate in\n" << "// instruction matching.\n" - << "static const char *getSubtargetFeatureName(unsigned Val) {\n"; + << "static const char *getSubtargetFeatureName(uint64_t Val) {\n"; if (!Info.SubtargetFeatures.empty()) { OS << " switch(Val) {\n"; typedef std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> RecFeatMap; @@ -2290,9 +2292,9 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, std::string ClassName = Info.AsmParser->getValueAsString("AsmParserClassName"); - OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" + OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" << "ComputeAvailableFeatures(uint64_t FB) const {\n"; - OS << " unsigned Features = 0;\n"; + OS << " uint64_t Features = 0;\n"; for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { @@ -2446,7 +2448,7 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, if (Aliases.empty()) return false; OS << "static void applyMnemonicAliases(StringRef &Mnemonic, " - "unsigned Features, unsigned VariantID) {\n"; + "uint64_t Features, unsigned VariantID) {\n"; OS << " switch (VariantID) {\n"; unsigned VariantCount = Target.getAsmParserVariantCount(); for (unsigned VC = 0; VC != VariantCount; ++VC) { @@ -2589,7 +2591,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the next operand index.\n"; OS << " unsigned NextOpNum = Operands.size()-1;\n"; @@ -2691,7 +2693,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of MCTargetAsmParser.\n"; - OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; + OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" << " const OperandVector " @@ -2703,7 +2705,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS.indent(27); OS << "const OperandVector &Operands,\n" << " MCInst &Inst,\n" - << " unsigned &ErrorInfo," + << " uint64_t &ErrorInfo," << " bool matchingInlineAsm,\n" << " unsigned VariantID = 0);\n"; @@ -2912,7 +2914,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << "MatchInstructionImpl(const OperandVector" << " &Operands,\n"; OS << " MCInst &Inst,\n" - << "unsigned &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n"; + << "uint64_t &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n"; OS << " // Eliminate obvious mismatches.\n"; OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; @@ -2922,7 +2924,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the instruction mnemonic, which is the first token.\n"; OS << " StringRef Mnemonic = ((" << Target.getName() @@ -2938,7 +2940,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " bool HadMatchOtherThanFeatures = false;\n"; OS << " bool HadMatchOtherThanPredicate = false;\n"; OS << " unsigned RetCode = Match_InvalidOperand;\n"; - OS << " unsigned MissingFeatures = ~0U;\n"; + OS << " uint64_t MissingFeatures = ~0ULL;\n"; OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; OS << " // wrong for all instances of the instruction.\n"; OS << " ErrorInfo = ~0U;\n"; @@ -3014,10 +3016,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if ((AvailableFeatures & it->RequiredFeatures) " << "!= it->RequiredFeatures) {\n"; OS << " HadMatchOtherThanFeatures = true;\n"; - OS << " unsigned NewMissingFeatures = it->RequiredFeatures & " + OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " if (CountPopulation_32(NewMissingFeatures) <=\n" - " CountPopulation_32(MissingFeatures))\n"; + OS << " if (CountPopulation_64(NewMissingFeatures) <=\n" + " CountPopulation_64(MissingFeatures))\n"; OS << " MissingFeatures = NewMissingFeatures;\n"; OS << " continue;\n"; OS << " }\n"; @@ -3055,7 +3057,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n"; OS << " SMLoc Loc = ((" << Target.getName() << "Operand&)*Operands[0]).getStartLoc();\n"; - OS << " Parser.Warning(Loc, Info, None);\n"; + OS << " getParser().Warning(Loc, Info, None);\n"; OS << " }\n"; } diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index c7fe9df..7ef70d3 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -424,7 +424,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { } // Emit the string itself. - O << " const char AsmStrs[] = {\n"; + O << " static const char AsmStrs[] = {\n"; StringTable.emit(O, printChar); O << " };\n\n"; diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h index 4cee352..fd77982 100644 --- a/utils/TableGen/AsmWriterInst.h +++ b/utils/TableGen/AsmWriterInst.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef ASMWRITER_INST_H -#define ASMWRITER_INST_H +#ifndef LLVM_UTILS_TABLEGEN_ASMWRITERINST_H +#define LLVM_UTILS_TABLEGEN_ASMWRITERINST_H #include <string> #include <vector> diff --git a/utils/TableGen/CTagsEmitter.cpp b/utils/TableGen/CTagsEmitter.cpp index 5d6d6da..bbed92a 100644 --- a/utils/TableGen/CTagsEmitter.cpp +++ b/utils/TableGen/CTagsEmitter.cpp @@ -69,19 +69,15 @@ SMLoc CTagsEmitter::locate(const Record *R) { } void CTagsEmitter::run(raw_ostream &OS) { - const std::map<std::string, Record *> &Classes = Records.getClasses(); - const std::map<std::string, Record *> &Defs = Records.getDefs(); + const auto &Classes = Records.getClasses(); + const auto &Defs = Records.getDefs(); std::vector<Tag> Tags; // Collect tags. Tags.reserve(Classes.size() + Defs.size()); - for (std::map<std::string, Record *>::const_iterator I = Classes.begin(), - E = Classes.end(); - I != E; ++I) - Tags.push_back(Tag(I->first, locate(I->second))); - for (std::map<std::string, Record *>::const_iterator I = Defs.begin(), - E = Defs.end(); - I != E; ++I) - Tags.push_back(Tag(I->first, locate(I->second))); + for (const auto &C : Classes) + Tags.push_back(Tag(C.first, locate(C.second.get()))); + for (const auto &D : Defs) + Tags.push_back(Tag(D.first, locate(D.second.get()))); // Emit tags. std::sort(Tags.begin(), Tags.end()); OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n"; diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index 6d43e8e..6a65e5e 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -35,23 +35,26 @@ private: } // End anonymous namespace void CallingConvEmitter::run(raw_ostream &O) { - std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv"); - - // Emit prototypes for all of the CC's so that they can forward ref each - // other. + + // Emit prototypes for all of the non-custom CC's so that they can forward ref + // each other. + for (unsigned i = 0, e = CCs.size(); i != e; ++i) { + if (!CCs[i]->getValueAsBit("Custom")) { + O << "static bool " << CCs[i]->getName() + << "(unsigned ValNo, MVT ValVT,\n" + << std::string(CCs[i]->getName().size() + 13, ' ') + << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" + << std::string(CCs[i]->getName().size() + 13, ' ') + << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; + } + } + + // Emit each non-custom calling convention description in full. for (unsigned i = 0, e = CCs.size(); i != e; ++i) { - O << "static bool " << CCs[i]->getName() - << "(unsigned ValNo, MVT ValVT,\n" - << std::string(CCs[i]->getName().size()+13, ' ') - << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" - << std::string(CCs[i]->getName().size()+13, ' ') - << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; + if (!CCs[i]->getValueAsBit("Custom")) + EmitCallingConv(CCs[i], O); } - - // Emit each calling convention description in full. - for (unsigned i = 0, e = CCs.size(); i != e; ++i) - EmitCallingConv(CCs[i], O); } @@ -178,13 +181,17 @@ void CallingConvEmitter::EmitAction(Record *Action, if (Size) O << Size << ", "; else - O << "\n" << IndentStr << " State.getTarget().getDataLayout()" - "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())), "; + O << "\n" << IndentStr + << " State.getMachineFunction().getSubtarget().getDataLayout()" + "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," + " "; if (Align) O << Align; else - O << "\n" << IndentStr << " State.getTarget().getDataLayout()" - "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()))"; + O << "\n" << IndentStr + << " State.getMachineFunction().getSubtarget().getDataLayout()" + "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()" + "))"; O << ");\n" << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" << Counter << ", LocVT, LocInfo));\n"; @@ -227,6 +234,21 @@ void CallingConvEmitter::EmitAction(Record *Action, << IndentStr << "else\n" << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n"; } + } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) { + Record *DestTy = Action->getValueAsDef("DestTy"); + MVT::SimpleValueType DestVT = getValueType(DestTy); + O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n"; + if (MVT(DestVT).isFloatingPoint()) { + PrintFatalError("CCPromoteToUpperBitsInType does not handle floating " + "point"); + } else { + O << IndentStr << "if (ArgFlags.isSExt())\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::SExtUpper;\n" + << IndentStr << "else if (ArgFlags.isZExt())\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExtUpper;\n" + << IndentStr << "else\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::AExtUpper;\n"; + } } else if (Action->isSubClassOf("CCBitConvertToType")) { Record *DestTy = Action->getValueAsDef("DestTy"); O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 4d0c0ca..11911b6 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -24,14 +24,6 @@ #include <vector> using namespace llvm; -// FIXME: Somewhat hackish to use a command line option for this. There should -// be a CodeEmitter class in the Target.td that controls this sort of thing -// instead. -static cl::opt<bool> -MCEmitter("mc-emitter", - cl::desc("Generate CodeEmitter for use with the MC library."), - cl::init(false)); - namespace { class CodeEmitterGen { @@ -134,15 +126,13 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, if (SO.second == 0) { Case += " // op: " + VarName + "\n" + " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx); - if (MCEmitter) - Case += ", Fixups, STI"; + Case += ", Fixups, STI"; Case += ");\n"; } } else { Case += " // op: " + VarName + "\n" + " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")"; - if (MCEmitter) - Case += ", Fixups, STI"; + Case += ", Fixups, STI"; Case += ");\n"; } @@ -223,8 +213,7 @@ std::string CodeEmitterGen::getInstructionCase(Record *R, std::string PostEmitter = R->getValueAsString("PostEncoderMethod"); if (!PostEmitter.empty()) { Case += " Value = " + PostEmitter + "(MI, Value"; - if (MCEmitter) - Case += ", STI"; + Case += ", STI"; Case += ");\n"; } @@ -243,12 +232,9 @@ void CodeEmitterGen::run(raw_ostream &o) { // Emit function declaration o << "uint64_t " << Target.getName(); - if (MCEmitter) - o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" - << " SmallVectorImpl<MCFixup> &Fixups,\n" - << " const MCSubtargetInfo &STI) const {\n"; - else - o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n"; + o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" + << " SmallVectorImpl<MCFixup> &Fixups,\n" + << " const MCSubtargetInfo &STI) const {\n"; // Emit instruction base values o << " static const uint64_t InstBits[] = {\n"; diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 2602bbc..a750aa9 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -771,7 +771,7 @@ static unsigned getPatternSize(const TreePatternNode *P, /// Compute the complexity metric for the input pattern. This roughly /// corresponds to the number of nodes that are covered. -unsigned PatternToMatch:: +int PatternToMatch:: getPatternComplexity(const CodeGenDAGPatterns &CGP) const { return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity(); } @@ -1387,7 +1387,7 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, if (R->isSubClassOf("SubRegIndex")) { assert(ResNo == 0 && "SubRegisterIndices only produce one result!"); - return EEVT::TypeSet(); + return EEVT::TypeSet(MVT::i32, TP); } if (R->isSubClassOf("ValueType")) { @@ -1529,7 +1529,16 @@ TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const { return false; } +static bool isOperandClass(const TreePatternNode *N, StringRef Class) { + if (!N->isLeaf()) + return N->getOperator()->isSubClassOf(Class); + DefInit *DI = dyn_cast<DefInit>(N->getLeafValue()); + if (DI && DI->getDef()->isSubClassOf(Class)) + return true; + + return false; +} /// ApplyTypeConstraints - Apply all of the type constraints relevant to /// this node and its children in the tree. This returns true if it makes a /// change, false otherwise. If a type contradiction is found, flag an error. @@ -1689,6 +1698,34 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled"); MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP); MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP); + } else if (getOperator()->getName() == "REG_SEQUENCE") { + // We need to do extra, custom typechecking for REG_SEQUENCE since it is + // variadic. + + unsigned NChild = getNumChildren(); + if (NChild < 3) { + TP.error("REG_SEQUENCE requires at least 3 operands!"); + return false; + } + + if (NChild % 2 == 0) { + TP.error("REG_SEQUENCE requires an odd number of operands!"); + return false; + } + + if (!isOperandClass(getChild(0), "RegisterClass")) { + TP.error("REG_SEQUENCE requires a RegisterClass for first operand!"); + return false; + } + + for (unsigned I = 1; I < NChild; I += 2) { + TreePatternNode *SubIdxChild = getChild(I + 1); + if (!isOperandClass(SubIdxChild, "SubRegIndex")) { + TP.error("REG_SEQUENCE requires a SubRegIndex for operand " + + itostr(I + 1) + "!"); + return false; + } + } } unsigned ChildNo = 0; @@ -1749,7 +1786,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP); } - if (ChildNo != getNumChildren()) { + if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) { TP.error("Instruction '" + getOperator()->getName() + "' was provided too many operands!"); return false; @@ -1871,7 +1908,7 @@ TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, Trees.push_back(Pat); } -void TreePattern::error(const std::string &Msg) { +void TreePattern::error(const Twine &Msg) { if (HasError) return; dump(); @@ -2226,13 +2263,6 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : VerifyInstructionFlags(); } -CodeGenDAGPatterns::~CodeGenDAGPatterns() { - for (pf_iterator I = PatternFragments.begin(), - E = PatternFragments.end(); I != E; ++I) - delete I->second; -} - - Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const { Record *N = Records.getDef(Name); if (!N || !N->isSubClassOf("SDNode")) { @@ -2294,9 +2324,9 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); TreePattern *P = - new TreePattern(Fragments[i], Tree, - !Fragments[i]->isSubClassOf("OutPatFrag"), *this); - PatternFragments[Fragments[i]] = P; + (PatternFragments[Fragments[i]] = llvm::make_unique<TreePattern>( + Fragments[i], Tree, !Fragments[i]->isSubClassOf("OutPatFrag"), + *this)).get(); // Validate the argument list, converting it to set, to discard duplicates. std::vector<std::string> &Args = P->getArgList(); @@ -2354,16 +2384,16 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag")) continue; - TreePattern *ThePat = PatternFragments[Fragments[i]]; - ThePat->InlinePatternFragments(); + TreePattern &ThePat = *PatternFragments[Fragments[i]]; + ThePat.InlinePatternFragments(); // Infer as many types as possible. Don't worry about it if we don't infer // all of them, some may depend on the inputs of the pattern. - ThePat->InferAllTypes(); - ThePat->resetError(); + ThePat.InferAllTypes(); + ThePat.resetError(); // If debugging, print out the pattern fragment result. - DEBUG(ThePat->dump()); + DEBUG(ThePat.dump()); } } @@ -3274,14 +3304,14 @@ void CodeGenDAGPatterns::ParsePatterns() { if (LI->getSize() == 0) continue; // no pattern. // Parse the instruction. - TreePattern *Result = new TreePattern(CurPattern, LI, false, *this); + TreePattern Result(CurPattern, LI, false, *this); // Inline pattern fragments into it. - Result->InlinePatternFragments(); + Result.InlinePatternFragments(); - if (Result->getNumTrees() != 1) - Result->error("Cannot handle instructions producing instructions " - "with temporaries yet!"); + if (Result.getNumTrees() != 1) + Result.error("Cannot handle instructions producing instructions " + "with temporaries yet!"); bool IterateInference; bool InferredAllPatternTypes, InferredAllResultTypes; @@ -3294,7 +3324,7 @@ void CodeGenDAGPatterns::ParsePatterns() { // Infer as many types as possible. If we cannot infer all of them, we // can never do anything with this pattern: report it to the user. InferredAllResultTypes = - Result->InferAllTypes(&Pattern->getNamedNodesMap()); + Result.InferAllTypes(&Pattern->getNamedNodesMap()); IterateInference = false; @@ -3302,13 +3332,13 @@ void CodeGenDAGPatterns::ParsePatterns() { // resolve cases where the input type is known to be a pointer type (which // is considered resolved), but the result knows it needs to be 32- or // 64-bits. Infer the other way for good measure. - for (unsigned i = 0, e = std::min(Result->getTree(0)->getNumTypes(), + for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(), Pattern->getTree(0)->getNumTypes()); i != e; ++i) { - IterateInference = Pattern->getTree(0)-> - UpdateNodeType(i, Result->getTree(0)->getExtType(i), *Result); - IterateInference |= Result->getTree(0)-> - UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result); + IterateInference = Pattern->getTree(0)->UpdateNodeType( + i, Result.getTree(0)->getExtType(i), Result); + IterateInference |= Result.getTree(0)->UpdateNodeType( + i, Pattern->getTree(0)->getExtType(i), Result); } // If our iteration has converged and the input pattern's types are fully @@ -3322,8 +3352,8 @@ void CodeGenDAGPatterns::ParsePatterns() { // arbitrary types to the result pattern's nodes. if (!IterateInference && InferredAllPatternTypes && !InferredAllResultTypes) - IterateInference = ForceArbitraryInstResultType(Result->getTree(0), - *Result); + IterateInference = + ForceArbitraryInstResultType(Result.getTree(0), Result); } while (IterateInference); // Verify that we inferred enough types that we can do something with the @@ -3332,7 +3362,7 @@ void CodeGenDAGPatterns::ParsePatterns() { Pattern->error("Could not infer all types in pattern!"); if (!InferredAllResultTypes) { Pattern->dump(); - Result->error("Could not infer all types in pattern result!"); + Result.error("Could not infer all types in pattern result!"); } // Validate that the input pattern is correct. @@ -3345,7 +3375,7 @@ void CodeGenDAGPatterns::ParsePatterns() { InstImpResults); // Promote the xform function to be an explicit node if set. - TreePatternNode *DstPattern = Result->getOnlyTree(); + TreePatternNode *DstPattern = Result.getOnlyTree(); std::vector<TreePatternNode*> ResultNodeOperands; for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) { TreePatternNode *OpNode = DstPattern->getChild(ii); @@ -3357,16 +3387,16 @@ void CodeGenDAGPatterns::ParsePatterns() { } ResultNodeOperands.push_back(OpNode); } - DstPattern = Result->getOnlyTree(); + DstPattern = Result.getOnlyTree(); if (!DstPattern->isLeaf()) DstPattern = new TreePatternNode(DstPattern->getOperator(), ResultNodeOperands, DstPattern->getNumTypes()); - for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i) - DstPattern->setType(i, Result->getOnlyTree()->getExtType(i)); + for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i) + DstPattern->setType(i, Result.getOnlyTree()->getExtType(i)); - TreePattern Temp(Result->getRecord(), DstPattern, false, *this); + TreePattern Temp(Result.getRecord(), DstPattern, false, *this); Temp.InferAllTypes(); diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index fb30cdd..c0812cf 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_DAGPATTERNS_H -#define CODEGEN_DAGPATTERNS_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H +#define LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H #include "CodeGenIntrinsics.h" #include "CodeGenTarget.h" @@ -597,7 +597,7 @@ public: /// error - If this is the first error in the current resolution step, /// print it and set the error flag. Otherwise, continue silently. - void error(const std::string &Msg); + void error(const Twine &Msg); bool hasError() const { return HasError; } @@ -667,7 +667,7 @@ public: PatternToMatch(Record *srcrecord, ListInit *preds, TreePatternNode *src, TreePatternNode *dst, const std::vector<Record*> &dstregs, - unsigned complexity, unsigned uid) + int complexity, unsigned uid) : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst), Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {} @@ -676,7 +676,7 @@ public: TreePatternNode *SrcPattern; // Source pattern to match. TreePatternNode *DstPattern; // Resulting pattern. std::vector<Record*> Dstregs; // Physical register defs being matched. - unsigned AddedComplexity; // Add to matching pattern complexity. + int AddedComplexity; // Add to matching pattern complexity. unsigned ID; // Unique ID for the record. Record *getSrcRecord() const { return SrcRecord; } @@ -684,13 +684,13 @@ public: TreePatternNode *getSrcPattern() const { return SrcPattern; } TreePatternNode *getDstPattern() const { return DstPattern; } const std::vector<Record*> &getDstRegs() const { return Dstregs; } - unsigned getAddedComplexity() const { return AddedComplexity; } + int getAddedComplexity() const { return AddedComplexity; } std::string getPredicateCheck() const; /// Compute the complexity metric for the input pattern. This roughly /// corresponds to the number of nodes that are covered. - unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const; + int getPatternComplexity(const CodeGenDAGPatterns &CGP) const; }; class CodeGenDAGPatterns { @@ -702,7 +702,8 @@ class CodeGenDAGPatterns { std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes; std::map<Record*, std::pair<Record*, std::string>, LessRecordByID> SDNodeXForms; std::map<Record*, ComplexPattern, LessRecordByID> ComplexPatterns; - std::map<Record*, TreePattern*, LessRecordByID> PatternFragments; + std::map<Record *, std::unique_ptr<TreePattern>, LessRecordByID> + PatternFragments; std::map<Record*, DAGDefaultOperand, LessRecordByID> DefaultOperands; std::map<Record*, DAGInstruction, LessRecordByID> Instructions; @@ -716,7 +717,6 @@ class CodeGenDAGPatterns { std::vector<PatternToMatch> PatternsToMatch; public: CodeGenDAGPatterns(RecordKeeper &R); - ~CodeGenDAGPatterns(); CodeGenTarget &getTargetInfo() { return Target; } const CodeGenTarget &getTargetInfo() const { return Target; } @@ -778,15 +778,16 @@ public: // Pattern Fragment information. TreePattern *getPatternFragment(Record *R) const { assert(PatternFragments.count(R) && "Invalid pattern fragment request!"); - return PatternFragments.find(R)->second; + return PatternFragments.find(R)->second.get(); } TreePattern *getPatternFragmentIfRead(Record *R) const { - if (!PatternFragments.count(R)) return nullptr; - return PatternFragments.find(R)->second; + if (!PatternFragments.count(R)) + return nullptr; + return PatternFragments.find(R)->second.get(); } - typedef std::map<Record*, TreePattern*, LessRecordByID>::const_iterator - pf_iterator; + typedef std::map<Record *, std::unique_ptr<TreePattern>, + LessRecordByID>::const_iterator pf_iterator; pf_iterator pf_begin() const { return PatternFragments.begin(); } pf_iterator pf_end() const { return PatternFragments.end(); } diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 2577ad4..d567dde 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -314,6 +314,9 @@ CodeGenInstruction::CodeGenInstruction(Record *R) hasPostISelHook = R->getValueAsBit("hasPostISelHook"); hasCtrlDep = R->getValueAsBit("hasCtrlDep"); isNotDuplicable = R->getValueAsBit("isNotDuplicable"); + isRegSequence = R->getValueAsBit("isRegSequence"); + isExtractSubreg = R->getValueAsBit("isExtractSubreg"); + isInsertSubreg = R->getValueAsBit("isInsertSubreg"); bool Unset; mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset); @@ -520,6 +523,21 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return true; } + // Bits<n> (also used for 0bxx literals) + if (BitsInit *BI = dyn_cast<BitsInit>(Arg)) { + if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) + return false; + if (!BI->isComplete()) + return false; + // Convert the bits init to an integer and use that for the result. + IntInit *II = + dyn_cast_or_null<IntInit>(BI->convertInitializerTo(IntRecTy::get())); + if (!II) + return false; + ResOp = ResultOperand(II->getValue()); + return true; + } + // If both are Operands with the same MVT, allow the conversion. It's // up to the user to make sure the values are appropriate, just like // for isel Pat's. diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index f143875..92aac5f 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_INSTRUCTION_H -#define CODEGEN_INSTRUCTION_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H +#define LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineValueType.h" @@ -253,6 +253,9 @@ namespace llvm { bool hasExtraDefRegAllocReq : 1; bool isCodeGenOnly : 1; bool isPseudo : 1; + bool isRegSequence : 1; + bool isExtractSubreg : 1; + bool isInsertSubreg : 1; std::string DeprecatedReason; bool HasComplexDeprecationPredicate; diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index a9ece01..1f1adf1 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_INTRINSIC_H -#define CODEGEN_INTRINSIC_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H +#define LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H #include "llvm/CodeGen/MachineValueType.h" #include <string> diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 8099f13..678222f 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -901,9 +901,8 @@ CodeGenRegisterClass::getSuperRegClasses(CodeGenSubRegIndex *SubIdx, FindI = SuperRegClasses.find(SubIdx); if (FindI == SuperRegClasses.end()) return; - for (SmallPtrSet<CodeGenRegisterClass*, 8>::const_iterator I = - FindI->second.begin(), E = FindI->second.end(); I != E; ++I) - Out.set((*I)->EnumValue); + for (CodeGenRegisterClass *RC : FindI->second) + Out.set(RC->EnumValue); } // Populate a unique sorted list of units from a register set. @@ -967,9 +966,12 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { // Compute register name map. for (unsigned i = 0, e = Registers.size(); i != e; ++i) - RegistersByName.GetOrCreateValue( - Registers[i]->TheDef->getValueAsString("AsmName"), - Registers[i]); + // FIXME: This could just be RegistersByName[name] = register, except that + // causes some failures in MIPS - perhaps they have duplicate register name + // entries? (or maybe there's a reason for it - I don't know much about this + // code, just drive-by refactoring) + RegistersByName.insert(std::make_pair( + Registers[i]->TheDef->getValueAsString("AsmName"), Registers[i])); // Precompute all sub-register maps. // This will create Composite entries for all inferred sub-register indices. @@ -1533,7 +1535,7 @@ void CodeGenRegBank::computeRegUnitSets() { assert(RegUnitSets.empty() && "dirty RegUnitSets"); // Compute a unique RegUnitSet for each RegClass. - const ArrayRef<CodeGenRegisterClass*> &RegClasses = getRegClasses(); + ArrayRef<CodeGenRegisterClass*> RegClasses = getRegClasses(); unsigned NumRegClasses = RegClasses.size(); for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { if (!RegClasses[RCIdx]->Allocatable) diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 278315b..c1e37fa 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_REGISTERS_H -#define CODEGEN_REGISTERS_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H +#define LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index 79d60ac..4cf7b5f 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -182,7 +182,7 @@ void CodeGenSchedModels::addProcModel(Record *ProcDef) { // Recursively find all reachable SchedReadWrite records. static void scanSchedRW(Record *RWDef, RecVec &RWDefs, SmallPtrSet<Record*, 16> &RWSet) { - if (!RWSet.insert(RWDef)) + if (!RWSet.insert(RWDef).second) return; RWDefs.push_back(RWDef); // Reads don't current have sequence records, but it can be added later. @@ -751,7 +751,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { for (ArrayRef<Record*>::const_iterator II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) { unsigned OldSCIdx = InstrClassMap[*II]; - if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx)) { + if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx).second) { for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(), RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) { if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) { diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index 3fef8ad..e5241b9 100644 --- a/utils/TableGen/CodeGenSchedule.h +++ b/utils/TableGen/CodeGenSchedule.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_SCHEDULE_H -#define CODEGEN_SCHEDULE_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H +#define LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index d1b5711..597da68 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -301,7 +301,8 @@ void CodeGenTarget::ComputeInstrsByEnum() const { "GC_LABEL", "KILL", "EXTRACT_SUBREG", "INSERT_SUBREG", "IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE", "REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START", - "LIFETIME_END", "STACKMAP", "PATCHPOINT", nullptr}; + "LIFETIME_END", "STACKMAP", "PATCHPOINT", "LOAD_STACK_GUARD", + nullptr}; const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); for (const char *const *p = FixedInstrs; *p; ++p) { const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 5414310..f4e1b6a 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_TARGET_H -#define CODEGEN_TARGET_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENTARGET_H +#define LLVM_UTILS_TABLEGEN_CODEGENTARGET_H #include "CodeGenInstruction.h" #include "CodeGenRegisters.h" diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 82682cd..e2e6ab1 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -94,8 +94,8 @@ struct PatternSortingPredicate { // Otherwise, if the patterns might both match, sort based on complexity, // which means that we prefer to match patterns that cover more nodes in the // input over nodes that cover fewer. - unsigned LHSSize = LHS->getPatternComplexity(CGP); - unsigned RHSSize = RHS->getPatternComplexity(CGP); + int LHSSize = LHS->getPatternComplexity(CGP); + int RHSSize = RHS->getPatternComplexity(CGP); if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost if (LHSSize < RHSSize) return false; diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index f8f6c54..b9cb267 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -1,4 +1,4 @@ -//===- DAGISelMatcher.h - Representation of DAG pattern matcher -----------===// +//===- DAGISelMatcher.h - Representation of DAG pattern matcher -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TBLGEN_DAGISELMATCHER_H -#define TBLGEN_DAGISELMATCHER_H +#ifndef LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H +#define LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 0059570..302f27b 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -630,7 +630,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end(); I != E; ++I) - PFsByName[I->first->getName()] = I->second; + PFsByName[I->first->getName()] = I->second.get(); if (!NodePredicates.empty()) { OS << "bool CheckNodePredicate(SDNode *Node,\n"; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 97e37ba..4a73b00 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -718,7 +718,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, CodeGenInstruction &II = CGT.getInstruction(Op); const DAGInstruction &Inst = CGP.getInstruction(Op); - // If we can, get the pattern for the instruction we're generating. We derive + // If we can, get the pattern for the instruction we're generating. We derive // a variety of information from this pattern, such as whether it has a chain. // // FIXME2: This is extremely dubious for several reasons, not the least of @@ -755,16 +755,21 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // the "outs" list. unsigned NumResults = Inst.getNumResults(); - // Loop over all of the operands of the instruction pattern, emitting code - // to fill them all in. The node 'N' usually has number children equal to - // the number of input operands of the instruction. However, in cases - // where there are predicate operands for an instruction, we need to fill - // in the 'execute always' values. Match up the node operands to the - // instruction operands to do this. + // Number of operands we know the output instruction must have. If it is + // variadic, we could have more operands. + unsigned NumFixedOperands = II.Operands.size(); + SmallVector<unsigned, 8> InstOps; - for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.Operands.size(); - InstOpNo != e; ++InstOpNo) { + // Loop over all of the fixed operands of the instruction pattern, emitting + // code to fill them all in. The node 'N' usually has number children equal to + // the number of input operands of the instruction. However, in cases where + // there are predicate operands for an instruction, we need to fill in the + // 'execute always' values. Match up the node operands to the instruction + // operands to do this. + unsigned ChildNo = 0; + for (unsigned InstOpNo = NumResults, e = NumFixedOperands; + InstOpNo != e; ++InstOpNo) { // Determine what to emit for this operand. Record *OperandNode = II.Operands[InstOpNo].Rec; if (OperandNode->isSubClassOf("OperandWithDefaultOps") && @@ -807,6 +812,16 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, } } + // If this is a variadic output instruction (i.e. REG_SEQUENCE), we can't + // expand suboperands, use default operands, or other features determined from + // the CodeGenInstruction after the fixed operands, which were handled + // above. Emit the remaining instructions implicitly added by the use for + // variable_ops. + if (II.Operands.isVariadic) { + for (unsigned I = ChildNo, E = N->getNumChildren(); I < E; ++I) + EmitResultOperand(N->getChild(I), InstOps); + } + // If this node has input glue or explicitly specified input physregs, we // need to add chained and glued copyfromreg nodes and materialize the glue // input. @@ -852,7 +867,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // gets the excess operands from the input DAG. int NumFixedArityOperands = -1; if (isRoot && - (Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))) + Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP)) NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren(); // If this is the root node and multiple matched nodes in the input pattern diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index 0b117eb..7a22764 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -185,7 +185,7 @@ static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr, /// Conceptually, we'd like to sink these predicates all the way to the last /// matcher predicate in the series. However, it turns out that some /// ComplexPatterns have side effects on the graph, so we really don't want to -/// run a the complex pattern if the pattern predicate will fail. For this +/// run a complex pattern if the pattern predicate will fail. For this /// reason, we refuse to sink the pattern predicate past a ComplexPattern. /// static void SinkPatternPredicates(std::unique_ptr<Matcher> &MatcherPtr) { @@ -400,7 +400,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { } if (NewOptionsToMatch.empty()) { - MatcherPtr.reset(nullptr); + MatcherPtr.reset(); return; } @@ -454,7 +454,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases; for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]); - assert(Opcodes.insert(COM->getOpcode().getEnumName()) && + assert(Opcodes.insert(COM->getOpcode().getEnumName()).second && "Duplicate opcodes not factored?"); Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext())); } diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 154f96d..748c923 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -19,6 +19,7 @@ #include "CodeGenDAGPatterns.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Error.h" @@ -36,6 +37,7 @@ struct InstructionMemo { const CodeGenRegisterClass *RC; std::string SubRegNo; std::vector<std::string>* PhysRegs; + std::string PredicateCheck; }; } // End anonymous namespace @@ -347,7 +349,7 @@ struct OperandsSignature { // Implicit physical register operand. e.g. Instruction::Mul expect to // select to a binary op. On x86, mul may take a single operand with // the other operand being implicit. We must emit something that looks - // like a binary instruction except for the very inner FastEmitInst_* + // like a binary instruction except for the very inner fastEmitInst_* // call. continue; Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes); @@ -364,7 +366,9 @@ struct OperandsSignature { namespace { class FastISelMap { - typedef std::map<std::string, InstructionMemo> PredMap; + // A multimap is needed instead of a "plain" map because the key is + // the instruction's complexity (an int) and they are not unique. + typedef std::multimap<int, InstructionMemo> PredMap; typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap; typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap; typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap; @@ -373,6 +377,16 @@ class FastISelMap { OperandsOpcodeTypeRetPredMap SimplePatterns; + // This is used to check that there are no duplicate predicates + typedef std::multimap<std::string, bool> PredCheckMap; + typedef std::map<MVT::SimpleValueType, PredCheckMap> RetPredCheckMap; + typedef std::map<MVT::SimpleValueType, RetPredCheckMap> TypeRetPredCheckMap; + typedef std::map<std::string, TypeRetPredCheckMap> OpcodeTypeRetPredCheckMap; + typedef std::map<OperandsSignature, OpcodeTypeRetPredCheckMap> + OperandsOpcodeTypeRetPredCheckMap; + + OperandsOpcodeTypeRetPredCheckMap SimplePatternsCheck; + std::map<OperandsSignature, std::vector<OperandsSignature> > SignaturesWithConstantForms; @@ -384,6 +398,11 @@ public: void collectPatterns(CodeGenDAGPatterns &CGP); void printImmediatePredicates(raw_ostream &OS); void printFunctionDefinitions(raw_ostream &OS); +private: + void emitInstructionCode(raw_ostream &OS, + const OperandsSignature &Operands, + const PredMap &PM, + const std::string &RetVTName); }; } // End anonymous namespace @@ -541,6 +560,17 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { continue; } + // Check if the operands match one of the patterns handled by FastISel. + std::string ManglingSuffix; + raw_string_ostream SuffixOS(ManglingSuffix); + Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true); + SuffixOS.flush(); + if (!StringSwitch<bool>(ManglingSuffix) + .Cases("", "r", "rr", "ri", "rf", true) + .Cases("rri", "i", "f", true) + .Default(false)) + continue; + // Get the predicate that guards this pattern. std::string PredicateCheck = Pattern.getPredicateCheck(); @@ -549,14 +579,24 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { Pattern.getDstPattern()->getOperator()->getName(), DstRC, SubRegNo, - PhysRegInputs + PhysRegInputs, + PredicateCheck }; + + int complexity = Pattern.getPatternComplexity(CGP); - if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck)) + if (SimplePatternsCheck[Operands][OpcodeName][VT] + [RetVT].count(PredicateCheck)) { PrintFatalError(Pattern.getSrcRecord()->getLoc(), - "Duplicate record in FastISel table!"); + "Duplicate predicate in FastISel table!"); + } + SimplePatternsCheck[Operands][OpcodeName][VT][RetVT].insert( + std::make_pair(PredicateCheck, true)); - SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo; + // Note: Instructions with the same complexity will appear in the order + // that they are encountered. + SimplePatterns[Operands][OpcodeName][VT][RetVT].insert( + std::make_pair(complexity, Memo)); // If any of the operands were immediates with predicates on them, strip // them down to a signature that doesn't have predicates so that we can @@ -582,6 +622,72 @@ void FastISelMap::printImmediatePredicates(raw_ostream &OS) { OS << "\n\n"; } +void FastISelMap::emitInstructionCode(raw_ostream &OS, + const OperandsSignature &Operands, + const PredMap &PM, + const std::string &RetVTName) { + // Emit code for each possible instruction. There may be + // multiple if there are subtarget concerns. A reverse iterator + // is used to produce the ones with highest complexity first. + + bool OneHadNoPredicate = false; + for (PredMap::const_reverse_iterator PI = PM.rbegin(), PE = PM.rend(); + PI != PE; ++PI) { + const InstructionMemo &Memo = PI->second; + std::string PredicateCheck = Memo.PredicateCheck; + + if (PredicateCheck.empty()) { + assert(!OneHadNoPredicate && + "Multiple instructions match and more than one had " + "no predicate!"); + OneHadNoPredicate = true; + } else { + if (OneHadNoPredicate) { + // FIXME: This should be a PrintError once the x86 target + // fixes PR21575. + PrintWarning("Multiple instructions match and one with no " + "predicate came before one with a predicate! " + "name:" + Memo.Name + " predicate: " + + PredicateCheck); + } + OS << " if (" + PredicateCheck + ") {\n"; + OS << " "; + } + + for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { + if ((*Memo.PhysRegs)[i] != "") + OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " + << "TII.get(TargetOpcode::COPY), " + << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; + } + + OS << " return fastEmitInst_"; + if (Memo.SubRegNo.empty()) { + Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, + ImmediatePredicates, true); + OS << "(" << InstNS << Memo.Name << ", "; + OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintArguments(OS, *Memo.PhysRegs); + OS << ");\n"; + } else { + OS << "extractsubreg(" << RetVTName + << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; + } + + if (!PredicateCheck.empty()) { + OS << " }\n"; + } + } + // Return 0 if all of the possibilities had predicates but none + // were satisfied. + if (!OneHadNoPredicate) + OS << " return 0;\n"; + OS << "}\n"; + OS << "\n"; +} + void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { // Now emit code for all the patterns that we collected. @@ -608,9 +714,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { RI != RE; ++RI) { MVT::SimpleValueType RetVT = RI->first; const PredMap &PM = RI->second; - bool HasPred = false; - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; @@ -619,58 +724,11 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { Operands.PrintParameters(OS); OS << ") {\n"; - // Emit code for each possible instruction. There may be - // multiple if there are subtarget concerns. - for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); - PI != PE; ++PI) { - std::string PredicateCheck = PI->first; - const InstructionMemo &Memo = PI->second; - - if (PredicateCheck.empty()) { - assert(!HasPred && - "Multiple instructions match, at least one has " - "a predicate and at least one doesn't!"); - } else { - OS << " if (" + PredicateCheck + ") {\n"; - OS << " "; - HasPred = true; - } - - for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { - if ((*Memo.PhysRegs)[i] != "") - OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " - << "TII.get(TargetOpcode::COPY), " - << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; - } - - OS << " return FastEmitInst_"; - if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, - ImmediatePredicates, true); - OS << "(" << InstNS << Memo.Name << ", "; - OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; - if (!Operands.empty()) - OS << ", "; - Operands.PrintArguments(OS, *Memo.PhysRegs); - OS << ");\n"; - } else { - OS << "extractsubreg(" << getName(RetVT); - OS << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; - } - - if (HasPred) - OS << " }\n"; - - } - // Return 0 if none of the predicates were satisfied. - if (HasPred) - OS << " return 0;\n"; - OS << "}\n"; - OS << "\n"; + emitInstructionCode(OS, Operands, PM, getName(RetVT)); } // Emit one function for the type that demultiplexes on return type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -682,7 +740,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end(); RI != RE; ++RI) { MVT::SimpleValueType RetVT = RI->first; - OS << " case " << getName(RetVT) << ": return FastEmit_" + OS << " case " << getName(RetVT) << ": return fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -694,7 +752,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { } else { // Non-variadic return type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -708,63 +766,13 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { << ")\n return 0;\n"; const PredMap &PM = RM.begin()->second; - bool HasPred = false; - - // Emit code for each possible instruction. There may be - // multiple if there are subtarget concerns. - for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); PI != PE; - ++PI) { - std::string PredicateCheck = PI->first; - const InstructionMemo &Memo = PI->second; - - if (PredicateCheck.empty()) { - assert(!HasPred && - "Multiple instructions match, at least one has " - "a predicate and at least one doesn't!"); - } else { - OS << " if (" + PredicateCheck + ") {\n"; - OS << " "; - HasPred = true; - } - - for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { - if ((*Memo.PhysRegs)[i] != "") - OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " - << "TII.get(TargetOpcode::COPY), " - << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; - } - - OS << " return FastEmitInst_"; - - if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, - ImmediatePredicates, true); - OS << "(" << InstNS << Memo.Name << ", "; - OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; - if (!Operands.empty()) - OS << ", "; - Operands.PrintArguments(OS, *Memo.PhysRegs); - OS << ");\n"; - } else { - OS << "extractsubreg(RetVT, Op0, Op0IsKill, "; - OS << Memo.SubRegNo; - OS << ");\n"; - } - - if (HasPred) - OS << " }\n"; - } - // Return 0 if none of the predicates were satisfied. - if (HasPred) - OS << " return 0;\n"; - OS << "}\n"; - OS << "\n"; + emitInstructionCode(OS, Operands, PM, "RetVT"); } } // Emit one function for the opcode that demultiplexes based on the type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT"; @@ -777,7 +785,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { TI != TE; ++TI) { MVT::SimpleValueType VT = TI->first; std::string TypeName = getName(VT); - OS << " case " << TypeName << ": return FastEmit_" + OS << " case " << TypeName << ": return fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(RetVT"; @@ -797,13 +805,16 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { // Emit one function for the operand signature that demultiplexes based // on opcode and type. - OS << "unsigned FastEmit_"; + OS << "unsigned fastEmit_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT, unsigned Opcode"; if (!Operands.empty()) OS << ", "; Operands.PrintParameters(OS); - OS << ") {\n"; + OS << ") "; + if (!Operands.hasAnyImmediateCodes()) + OS << "override "; + OS << "{\n"; // If there are any forms of this signature available that operate on // constrained forms of the immediate (e.g., 32-bit sext immediate in a @@ -823,7 +834,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { for (unsigned i = 0, e = MI->second.size(); i != e; ++i) { OS << " if ("; MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates); - OS << ")\n if (unsigned Reg = FastEmit_"; + OS << ")\n if (unsigned Reg = fastEmit_"; MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates); OS << "(VT, RetVT, Opcode"; if (!MI->second[i].empty()) @@ -841,7 +852,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { I != E; ++I) { const std::string &Opcode = I->first; - OS << " case " << Opcode << ": return FastEmit_" + OS << " case " << Opcode << ": return fastEmit_" << getLegalCName(Opcode) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(VT, RetVT"; diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index 42639cc..bd83b6c 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -230,7 +230,7 @@ protected: std::vector<unsigned> VariableInstructions; // Map of well-known segment value to its delegate. - std::map<unsigned, const FilterChooser*> FilterChooserMap; + std::map<unsigned, std::unique_ptr<const FilterChooser>> FilterChooserMap; // Number of instructions which fall under FilteredInstructions category. unsigned NumFiltered; @@ -252,7 +252,7 @@ public: return *(FilterChooserMap.find((unsigned)-1)->second); } - Filter(const Filter &f); + Filter(Filter &&f); Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed); ~Filter(); @@ -333,13 +333,9 @@ protected: // Parent emitter const FixedLenDecoderEmitter *Emitter; + FilterChooser(const FilterChooser &) LLVM_DELETED_FUNCTION; + void operator=(const FilterChooser &) LLVM_DELETED_FUNCTION; public: - FilterChooser(const FilterChooser &FC) - : AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), - Operands(FC.Operands), Filters(FC.Filters), - FilterBitValues(FC.FilterBitValues), Parent(FC.Parent), - BestIndex(FC.BestIndex), BitWidth(FC.BitWidth), - Emitter(FC.Emitter) { } FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, const std::vector<unsigned> &IDs, @@ -347,10 +343,8 @@ public: unsigned BW, const FixedLenDecoderEmitter *E) : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), - Parent(nullptr), BestIndex(-1), BitWidth(BW), Emitter(E) { - for (unsigned i = 0; i < BitWidth; ++i) - FilterBitValues.push_back(BIT_UNFILTERED); - + FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1), + BitWidth(BW), Emitter(E) { doFilter(); } @@ -490,11 +484,11 @@ public: // // /////////////////////////// -Filter::Filter(const Filter &f) +Filter::Filter(Filter &&f) : Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), - FilteredInstructions(f.FilteredInstructions), - VariableInstructions(f.VariableInstructions), - FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered), + FilteredInstructions(std::move(f.FilteredInstructions)), + VariableInstructions(std::move(f.VariableInstructions)), + FilterChooserMap(std::move(f.FilterChooserMap)), NumFiltered(f.NumFiltered), LastOpcFiltered(f.LastOpcFiltered) { } @@ -534,12 +528,6 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, } Filter::~Filter() { - std::map<unsigned, const FilterChooser*>::iterator filterIterator; - for (filterIterator = FilterChooserMap.begin(); - filterIterator != FilterChooserMap.end(); - filterIterator++) { - delete filterIterator->second; - } } // Divides the decoding task into sub tasks and delegates them to the @@ -561,14 +549,10 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // group of instructions whose segment values are variable. - FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>( - (unsigned)-1, - new FilterChooser(Owner->AllInstructions, - VariableInstructions, - Owner->Operands, - BitValueArray, - *Owner) - )); + FilterChooserMap.insert( + std::make_pair(-1U, llvm::make_unique<FilterChooser>( + Owner->AllInstructions, VariableInstructions, + Owner->Operands, BitValueArray, *Owner))); } // No need to recurse for a singleton filtered instruction. @@ -594,14 +578,10 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // category of instructions. - FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>( - mapIterator->first, - new FilterChooser(Owner->AllInstructions, - mapIterator->second, - Owner->Operands, - BitValueArray, - *Owner) - )); + FilterChooserMap.insert(std::make_pair( + mapIterator->first, llvm::make_unique<FilterChooser>( + Owner->AllInstructions, mapIterator->second, + Owner->Operands, BitValueArray, *Owner))); } } @@ -636,7 +616,8 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { // A new filter entry begins a new scope for fixup resolution. TableInfo.FixupStack.push_back(FixupList()); - std::map<unsigned, const FilterChooser*>::const_iterator filterIterator; + std::map<unsigned, + std::unique_ptr<const FilterChooser>>::const_iterator filterIterator; DecoderTable &Table = TableInfo.Table; @@ -1066,19 +1047,17 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, const OperandInfo &OpInfo) const { const std::string &Decoder = OpInfo.Decoder; - if (OpInfo.numFields() == 1) { - OperandInfo::const_iterator OI = OpInfo.begin(); - o.indent(Indentation) << "tmp = fieldFromInstruction" - << "(insn, " << OI->Base << ", " << OI->Width - << ");\n"; - } else { + if (OpInfo.numFields() != 1) o.indent(Indentation) << "tmp = 0;\n"; - for (OperandInfo::const_iterator OI = OpInfo.begin(), OE = OpInfo.end(); - OI != OE; ++OI) { - o.indent(Indentation) << "tmp |= (fieldFromInstruction" - << "(insn, " << OI->Base << ", " << OI->Width - << ") << " << OI->Offset << ");\n"; - } + + for (const EncodingField &EF : OpInfo) { + o.indent(Indentation) << "tmp "; + if (OpInfo.numFields() != 1) o << '|'; + o << "= fieldFromInstruction" + << "(insn, " << EF.Base << ", " << EF.Width << ')'; + if (OpInfo.numFields() != 1 || EF.Offset != 0) + o << " << " << EF.Offset; + o << ";\n"; } if (Decoder != "") @@ -1384,8 +1363,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit, bool mixed) { Filters.clear(); - Filter F(*this, startBit, numBit, true); - Filters.push_back(F); + Filters.push_back(Filter(*this, startBit, numBit, true)); BestIndex = 0; // Sole Filter instance to choose from. bestFilter().recurse(); } diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 76f05ce..6fdf22d 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -266,6 +266,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << "#undef GET_INSTRINFO_NAMED_OPS\n"; OS << "namespace llvm {"; OS << "namespace " << Namespace << " {\n"; + OS << "LLVM_READONLY\n"; OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n"; if (!Operands.empty()) { OS << " static const int16_t OperandMap [][" << Operands.size() @@ -504,6 +505,9 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)"; if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<MCID::ExtraSrcRegAllocReq)"; if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<MCID::ExtraDefRegAllocReq)"; + if (Inst.isRegSequence) OS << "|(1<<MCID::RegSequence)"; + if (Inst.isExtractSubreg) OS << "|(1<<MCID::ExtractSubreg)"; + if (Inst.isInsertSubreg) OS << "|(1<<MCID::InsertSubreg)"; // Emit all of the target-specific flags... BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 430ef32..37f6de0 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -129,8 +129,9 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, for (unsigned i = 0, e = Ints.size(); i != e; ++i) { OS << " " << Ints[i].EnumName; OS << ((i != e-1) ? ", " : " "); - OS << std::string(40-Ints[i].EnumName.size(), ' ') - << "// " << Ints[i].Name << "\n"; + if (Ints[i].EnumName.size() < 40) + OS << std::string(40-Ints[i].EnumName.size(), ' '); + OS << " // " << Ints[i].Name << "\n"; } OS << "#endif\n\n"; } @@ -243,19 +244,20 @@ enum IIT_Info { IIT_ARG = 15, // Values from 16+ are only encodable with the inefficient encoding. - IIT_MMX = 16, - IIT_METADATA = 17, - IIT_EMPTYSTRUCT = 18, - IIT_STRUCT2 = 19, - IIT_STRUCT3 = 20, - IIT_STRUCT4 = 21, - IIT_STRUCT5 = 22, - IIT_EXTEND_ARG = 23, - IIT_TRUNC_ARG = 24, - IIT_ANYPTR = 25, - IIT_V1 = 26, - IIT_VARARG = 27, - IIT_HALF_VEC_ARG = 28 + IIT_V64 = 16, + IIT_MMX = 17, + IIT_METADATA = 18, + IIT_EMPTYSTRUCT = 19, + IIT_STRUCT2 = 20, + IIT_STRUCT3 = 21, + IIT_STRUCT4 = 22, + IIT_STRUCT5 = 23, + IIT_EXTEND_ARG = 24, + IIT_TRUNC_ARG = 25, + IIT_ANYPTR = 26, + IIT_V1 = 27, + IIT_VARARG = 28, + IIT_HALF_VEC_ARG = 29 }; @@ -355,6 +357,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, case 8: Sig.push_back(IIT_V8); break; case 16: Sig.push_back(IIT_V16); break; case 32: Sig.push_back(IIT_V32); break; + case 64: Sig.push_back(IIT_V64); break; } return EncodeFixedValueType(VVT.getVectorElementType().SimpleTy, Sig); @@ -679,8 +682,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << " }\n"; OS << " }\n"; - OS << " return AttributeSet::get(C, ArrayRef<AttributeSet>(AS, " - "NumAttrs));\n"; + OS << " return AttributeSet::get(C, makeArrayRef(AS, NumAttrs));\n"; OS << "}\n"; OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; } diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index c5fd7ee..9262d7c 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -221,9 +221,11 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { // The containing option group (if any). OS << ", "; - if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) + const ListInit *GroupFlags = nullptr; + if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) { + GroupFlags = DI->getDef()->getValueAsListInit("Flags"); OS << getOptionName(*DI->getDef()); - else + } else OS << "INVALID"; // The option alias (if any). @@ -249,17 +251,19 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { } // The option flags. + OS << ", "; + int NumFlags = 0; const ListInit *LI = R.getValueAsListInit("Flags"); - if (LI->empty()) { - OS << ", 0"; - } else { - OS << ", "; - for (unsigned i = 0, e = LI->size(); i != e; ++i) { - if (i) - OS << " | "; - OS << cast<DefInit>(LI->getElement(i))->getDef()->getName(); - } + for (Init *I : *LI) + OS << (NumFlags++ ? " | " : "") + << cast<DefInit>(I)->getDef()->getName(); + if (GroupFlags) { + for (Init *I : *GroupFlags) + OS << (NumFlags++ ? " | " : "") + << cast<DefInit>(I)->getDef()->getName(); } + if (NumFlags == 0) + OS << '0'; // The option parameter field. OS << ", " << R.getValueAsInt("NumArgs"); diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index 3b74ac4..ebb43f0 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -277,11 +277,10 @@ void PseudoLoweringEmitter::run(raw_ostream &o) { assert(InstructionClass && "Instruction class definition missing!"); std::vector<Record*> Insts; - for (std::map<std::string, Record*>::const_iterator I = - Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) { - if (I->second->isSubClassOf(ExpansionClass) && - I->second->isSubClassOf(InstructionClass)) - Insts.push_back(I->second); + for (const auto &D : Records.getDefs()) { + if (D.second->isSubClassOf(ExpansionClass) && + D.second->isSubClassOf(InstructionClass)) + Insts.push_back(D.second.get()); } // Process the pseudo expansion definitions, validating them as we do so. diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 573c37f..79d08a9 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -379,9 +379,9 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, OS << "extern const unsigned " << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize"; if (!isCtor) - OS << " = sizeof(" << Namespace + OS << " = array_lengthof(" << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + << "Dwarf2L);\n\n"; else OS << ";\n\n"; } @@ -427,9 +427,8 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, OS << "extern const unsigned " << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize"; if (!isCtor) - OS << " = sizeof(" << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "L2Dwarf)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + OS << " = array_lengthof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2Dwarf);\n\n"; else OS << ";\n\n"; } @@ -848,6 +847,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; + SequenceToOffsetTable<std::string> RegClassStrings; + // Emit the register enum value arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = *RegisterClasses[rc]; @@ -856,6 +857,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); + RegClassStrings.add(Name); + // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " const MCPhysReg " << Name @@ -880,6 +883,11 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "}\n\n"; + RegClassStrings.layout(); + OS << "extern const char " << TargetName << "RegClassStrings[] = {\n"; + RegClassStrings.emit(OS, printChar); + OS << "};\n\n"; + OS << "extern const MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; @@ -892,8 +900,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); - OS << " { " << '\"' << RC.getName() << "\", " - << RC.getName() << ", " << RC.getName() << "Bits, " + OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, " + << RegClassStrings.get(RC.getName()) << ", " << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " @@ -934,10 +942,11 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " << TargetName << "RegStrings, " + << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, " << (SubRegIndices.size() + 1) << ",\n" << TargetName << "SubRegIdxRanges, " - << " " << TargetName << "RegEncodingTable);\n\n"; + << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); @@ -1267,6 +1276,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; OS << "extern const char " << TargetName << "RegStrings[];\n"; + OS << "extern const char " << TargetName << "RegClassStrings[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; OS << "extern const MCRegisterInfo::SubRegCoveredBits " @@ -1289,6 +1299,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << " " << RegBank.getNumNativeRegUnits() << ",\n" << " " << TargetName << "RegDiffLists,\n" << " " << TargetName << "RegStrings,\n" + << " " << TargetName << "RegClassStrings,\n" << " " << TargetName << "SubRegIdxLists,\n" << " " << SubRegIndices.size() + 1 << ",\n" << " " << TargetName << "SubRegIdxRanges,\n" diff --git a/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h index e6ab664..b58de4c 100644 --- a/utils/TableGen/SequenceToOffsetTable.h +++ b/utils/TableGen/SequenceToOffsetTable.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H -#define TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H +#ifndef LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H +#define LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H #include "llvm/Support/raw_ostream.h" #include <algorithm> diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 06f8694..9f2fc92 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -386,7 +386,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS, for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), PE = SchedModels.procModelEnd(); PI != PE; ++PI) { - if (!ItinsDefSet.insert(PI->ItinsDef)) + if (!ItinsDefSet.insert(PI->ItinsDef).second) continue; std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU"); @@ -565,7 +565,7 @@ EmitItineraries(raw_ostream &OS, PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) { Record *ItinsDef = PI->ItinsDef; - if (!ItinsDefSet.insert(ItinsDef)) + if (!ItinsDefSet.insert(ItinsDef).second) continue; // Get processor itinerary name @@ -575,12 +575,13 @@ EmitItineraries(raw_ostream &OS, assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator"); std::vector<InstrItinerary> &ItinList = *ProcItinListsIter; + // Empty itineraries aren't referenced anywhere in the tablegen output + // so don't emit them. + if (ItinList.empty()) + continue; + OS << "\n"; OS << "static const llvm::InstrItinerary "; - if (ItinList.empty()) { - OS << '*' << Name << " = nullptr;\n"; - continue; - } // Begin processor itinerary table OS << Name << "[] = {\n"; @@ -1192,7 +1193,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { // Begin processor itinerary properties OS << "\n"; - OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n"; + OS << "static const llvm::MCSchedModel " << PI->ModelName << " = {\n"; EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ','); EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ','); EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ','); @@ -1201,6 +1202,10 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ','); OS << " " << (bool)(PI->ModelDef ? + PI->ModelDef->getValueAsBit("PostRAScheduler") : 0) + << ", // " << "PostRAScheduler\n"; + + OS << " " << (bool)(PI->ModelDef ? PI->ModelDef->getValueAsBit("CompleteModel") : 0) << ", // " << "CompleteModel\n"; @@ -1213,10 +1218,10 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { - SchedModels.schedClassBegin()) << ",\n"; else OS << " 0, 0, 0, 0, // No instruction-level machine model.\n"; - if (SchedModels.hasItineraries()) - OS << " " << PI->ItinsDef->getName() << ");\n"; + if (PI->hasItineraries()) + OS << " " << PI->ItinsDef->getName() << "};\n"; else - OS << " 0); // No Itinerary\n"; + OS << " nullptr}; // No Itinerary\n"; } } diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h index 28b626e..2dc03ce 100644 --- a/utils/TableGen/TableGenBackends.h +++ b/utils/TableGen/TableGenBackends.h @@ -13,6 +13,8 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H +#define LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H // A TableGen backend is a function that looks like // @@ -78,3 +80,5 @@ void EmitOptParser(RecordKeeper &RK, raw_ostream &OS); void EmitCTags(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace + +#endif diff --git a/utils/TableGen/X86DisassemblerShared.h b/utils/TableGen/X86DisassemblerShared.h index 9e79b9c..5895277 100644 --- a/utils/TableGen/X86DisassemblerShared.h +++ b/utils/TableGen/X86DisassemblerShared.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86DISASSEMBLERSHARED_H -#define X86DISASSEMBLERSHARED_H +#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H +#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H #include <string.h> #include <string> diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index fbcc6f2..d7e981c 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -171,12 +171,17 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_OPSIZE: return inheritsFrom(child, IC_EVEX_W_OPSIZE) || inheritsFrom(child, IC_EVEX_L_W_OPSIZE); + case IC_EVEX_B: + return false; case IC_EVEX_W: case IC_EVEX_W_XS: case IC_EVEX_W_XD: case IC_EVEX_W_OPSIZE: return false; case IC_EVEX_L: + case IC_EVEX_L_K_B: + case IC_EVEX_L_KZ_B: + case IC_EVEX_L_B: case IC_EVEX_L_XS: case IC_EVEX_L_XD: case IC_EVEX_L_OPSIZE: @@ -205,38 +210,59 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_XD_K: return inheritsFrom(child, IC_EVEX_W_XD_K) || inheritsFrom(child, IC_EVEX_L_W_XD_K); + case IC_EVEX_K_B: + case IC_EVEX_KZ: + return false; + case IC_EVEX_XS_KZ: + return inheritsFrom(child, IC_EVEX_W_XS_KZ) || + inheritsFrom(child, IC_EVEX_L_W_XS_KZ); + case IC_EVEX_XD_KZ: + return inheritsFrom(child, IC_EVEX_W_XD_KZ) || + inheritsFrom(child, IC_EVEX_L_W_XD_KZ); + case IC_EVEX_KZ_B: case IC_EVEX_OPSIZE_K: case IC_EVEX_OPSIZE_B: + case IC_EVEX_OPSIZE_K_B: + case IC_EVEX_OPSIZE_KZ: + case IC_EVEX_OPSIZE_KZ_B: return false; case IC_EVEX_W_K: case IC_EVEX_W_XS_K: case IC_EVEX_W_XD_K: case IC_EVEX_W_OPSIZE_K: case IC_EVEX_W_OPSIZE_B: + case IC_EVEX_W_OPSIZE_K_B: return false; case IC_EVEX_L_K: case IC_EVEX_L_XS_K: case IC_EVEX_L_XD_K: case IC_EVEX_L_OPSIZE_K: + case IC_EVEX_L_OPSIZE_B: + case IC_EVEX_L_OPSIZE_K_B: return false; case IC_EVEX_W_KZ: case IC_EVEX_W_XS_KZ: case IC_EVEX_W_XD_KZ: case IC_EVEX_W_OPSIZE_KZ: + case IC_EVEX_W_OPSIZE_KZ_B: return false; case IC_EVEX_L_KZ: case IC_EVEX_L_XS_KZ: case IC_EVEX_L_XD_KZ: case IC_EVEX_L_OPSIZE_KZ: + case IC_EVEX_L_OPSIZE_KZ_B: return false; case IC_EVEX_L_W_K: case IC_EVEX_L_W_XS_K: case IC_EVEX_L_W_XD_K: case IC_EVEX_L_W_OPSIZE_K: + case IC_EVEX_L_W_OPSIZE_B: + case IC_EVEX_L_W_OPSIZE_K_B: case IC_EVEX_L_W_KZ: case IC_EVEX_L_W_XS_KZ: case IC_EVEX_L_W_XD_KZ: case IC_EVEX_L_W_OPSIZE_KZ: + case IC_EVEX_L_W_OPSIZE_KZ_B: return false; case IC_EVEX_L2_K: case IC_EVEX_L2_B: diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h index 1327375..d86b926 100644 --- a/utils/TableGen/X86DisassemblerTables.h +++ b/utils/TableGen/X86DisassemblerTables.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86DISASSEMBLERTABLES_H -#define X86DISASSEMBLERTABLES_H +#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H +#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H #include "X86DisassemblerShared.h" #include "X86ModRMFilters.h" diff --git a/utils/TableGen/X86ModRMFilters.h b/utils/TableGen/X86ModRMFilters.h index fac3838..d919c58 100644 --- a/utils/TableGen/X86ModRMFilters.h +++ b/utils/TableGen/X86ModRMFilters.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86MODRMFILTERS_H -#define X86MODRMFILTERS_H +#ifndef LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H +#define LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H #include "llvm/Support/DataTypes.h" diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index ead419e..9b8092f 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -32,48 +32,50 @@ using namespace llvm; MAP(C9, 38) \ MAP(CA, 39) \ MAP(CB, 40) \ - MAP(D0, 41) \ - MAP(D1, 42) \ - MAP(D4, 43) \ - MAP(D5, 44) \ - MAP(D6, 45) \ - MAP(D8, 46) \ - MAP(D9, 47) \ - MAP(DA, 48) \ - MAP(DB, 49) \ - MAP(DC, 50) \ - MAP(DD, 51) \ - MAP(DE, 52) \ - MAP(DF, 53) \ - MAP(E0, 54) \ - MAP(E1, 55) \ - MAP(E2, 56) \ - MAP(E3, 57) \ - MAP(E4, 58) \ - MAP(E5, 59) \ - MAP(E8, 60) \ - MAP(E9, 61) \ - MAP(EA, 62) \ - MAP(EB, 63) \ - MAP(EC, 64) \ - MAP(ED, 65) \ - MAP(EE, 66) \ - MAP(F0, 67) \ - MAP(F1, 68) \ - MAP(F2, 69) \ - MAP(F3, 70) \ - MAP(F4, 71) \ - MAP(F5, 72) \ - MAP(F6, 73) \ - MAP(F7, 74) \ - MAP(F8, 75) \ - MAP(F9, 76) \ - MAP(FA, 77) \ - MAP(FB, 78) \ - MAP(FC, 79) \ - MAP(FD, 80) \ - MAP(FE, 81) \ - MAP(FF, 82) + MAP(CF, 41) \ + MAP(D0, 42) \ + MAP(D1, 43) \ + MAP(D4, 44) \ + MAP(D5, 45) \ + MAP(D6, 46) \ + MAP(D7, 47) \ + MAP(D8, 48) \ + MAP(D9, 49) \ + MAP(DA, 50) \ + MAP(DB, 51) \ + MAP(DC, 52) \ + MAP(DD, 53) \ + MAP(DE, 54) \ + MAP(DF, 55) \ + MAP(E0, 56) \ + MAP(E1, 57) \ + MAP(E2, 58) \ + MAP(E3, 59) \ + MAP(E4, 60) \ + MAP(E5, 61) \ + MAP(E8, 62) \ + MAP(E9, 63) \ + MAP(EA, 64) \ + MAP(EB, 65) \ + MAP(EC, 66) \ + MAP(ED, 67) \ + MAP(EE, 68) \ + MAP(F0, 69) \ + MAP(F1, 70) \ + MAP(F2, 71) \ + MAP(F3, 72) \ + MAP(F4, 73) \ + MAP(F5, 74) \ + MAP(F6, 75) \ + MAP(F7, 76) \ + MAP(F8, 77) \ + MAP(F9, 78) \ + MAP(FA, 79) \ + MAP(FB, 80) \ + MAP(FC, 81) \ + MAP(FD, 82) \ + MAP(FE, 83) \ + MAP(FF, 84) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { @@ -205,6 +207,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, HasEVEX_B = Rec->getValueAsBit("hasEVEX_B"); IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly"); ForceDisassemble = Rec->getValueAsBit("ForceDisassemble"); + CD8_Scale = byteFromRec(Rec, "CD8_Scale"); Name = Rec->getName(); AsmString = Rec->getValueAsString("AsmString"); @@ -441,6 +444,16 @@ InstructionContext RecognizableInstr::insnContext() const { return insnContext; } +void RecognizableInstr::adjustOperandEncoding(OperandEncoding &encoding) { + // The scaling factor for AVX512 compressed displacement encoding is an + // instruction attribute. Adjust the ModRM encoding type to include the + // scale for compressed displacement. + if (encoding != ENCODING_RM || CD8_Scale == 0) + return; + encoding = (OperandEncoding)(encoding + Log2_32(CD8_Scale)); + assert(encoding <= ENCODING_RM_CD64 && "Invalid CDisp scaling"); +} + void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex, unsigned &physicalOperandIndex, unsigned &numPhysicalOperands, @@ -464,8 +477,10 @@ void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex, const std::string &typeName = (*Operands)[operandIndex].Rec->getName(); - Spec->operands[operandIndex].encoding = encodingFromString(typeName, - OpSize); + OperandEncoding encoding = encodingFromString(typeName, OpSize); + // Adjust the encoding type for an operand based on the instruction. + adjustOperandEncoding(encoding); + Spec->operands[operandIndex].encoding = encoding; Spec->operands[operandIndex].type = typeFromString(typeName, HasREX_WPrefix, OpSize); @@ -526,6 +541,14 @@ void RecognizableInstr::emitInstructionSpecifier() { // physicalOperandIndex should always be < numPhysicalOperands unsigned physicalOperandIndex = 0; + // Given the set of prefix bits, how many additional operands does the + // instruction have? + unsigned additionalOperands = 0; + if (HasVEX_4V || HasVEX_4VOp3) + ++additionalOperands; + if (HasEVEX_K) + ++additionalOperands; + switch (Form) { default: llvm_unreachable("Unhandled form"); case X86Local::RawFrmSrc: @@ -560,17 +583,17 @@ void RecognizableInstr::emitInstructionSpecifier() { break; case X86Local::MRMDestReg: // Operand 1 is a register operand in the R/M field. + // - In AVX512 there may be a mask operand here - // Operand 2 is a register operand in the Reg/Opcode field. // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMDestRegFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMDestRegFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMDestRegFrm"); HANDLE_OPERAND(rmRegister) + if (HasEVEX_K) + HANDLE_OPERAND(writemaskRegister) if (HasVEX_4V) // FIXME: In AVX, the register below becomes the one encoded @@ -585,12 +608,10 @@ void RecognizableInstr::emitInstructionSpecifier() { // Operand 2 is a register operand in the Reg/Opcode field. // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMDestMemFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMDestMemFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMDestMemFrm with VEX_4V"); + HANDLE_OPERAND(memory) if (HasEVEX_K) @@ -611,12 +632,9 @@ void RecognizableInstr::emitInstructionSpecifier() { // Operand 3 (optional) is an immediate. // Operand 4 (optional) is an immediate. - if (HasVEX_4V || HasVEX_4VOp3) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && - "Unexpected number of operands for MRMSrcRegFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMSrcRegFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 4 + additionalOperands && + "Unexpected number of operands for MRMSrcRegFrm"); HANDLE_OPERAND(roRegister) @@ -647,12 +665,9 @@ void RecognizableInstr::emitInstructionSpecifier() { // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V || HasVEX_4VOp3) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && - "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMSrcMemFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 4 + additionalOperands && + "Unexpected number of operands for MRMSrcMemFrm"); HANDLE_OPERAND(roRegister) @@ -685,15 +700,13 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM5r: case X86Local::MRM6r: case X86Local::MRM7r: - { - // Operand 1 is a register operand in the R/M field. - // Operand 2 (optional) is an immediate or relocation. - // Operand 3 (optional) is an immediate. - unsigned kOp = (HasEVEX_K) ? 1:0; - unsigned Op4v = (HasVEX_4V) ? 1:0; - if (numPhysicalOperands > 3 + kOp + Op4v) - llvm_unreachable("Unexpected number of operands for MRMnr"); - } + // Operand 1 is a register operand in the R/M field. + // Operand 2 (optional) is an immediate or relocation. + // Operand 3 (optional) is an immediate. + assert(numPhysicalOperands >= 0 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMnr"); + if (HasVEX_4V) HANDLE_OPERAND(vvvvRegister) @@ -712,15 +725,12 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM5m: case X86Local::MRM6m: case X86Local::MRM7m: - { - // Operand 1 is a memory operand (possibly SIB-extended) - // Operand 2 (optional) is an immediate or relocation. - unsigned kOp = (HasEVEX_K) ? 1:0; - unsigned Op4v = (HasVEX_4V) ? 1:0; - if (numPhysicalOperands < 1 + kOp + Op4v || - numPhysicalOperands > 2 + kOp + Op4v) - llvm_unreachable("Unexpected number of operands for MRMnm"); - } + // Operand 1 is a memory operand (possibly SIB-extended) + // Operand 2 (optional) is an immediate or relocation. + assert(numPhysicalOperands >= 1 + additionalOperands && + numPhysicalOperands <= 2 + additionalOperands && + "Unexpected number of operands for MRMnm"); + if (HasVEX_4V) HANDLE_OPERAND(vvvvRegister) if (HasEVEX_K) @@ -756,20 +766,21 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM_C0: case X86Local::MRM_C1: case X86Local::MRM_C2: case X86Local::MRM_C3: case X86Local::MRM_C4: case X86Local::MRM_C8: case X86Local::MRM_C9: case X86Local::MRM_CA: case X86Local::MRM_CB: - case X86Local::MRM_D0: case X86Local::MRM_D1: case X86Local::MRM_D4: - case X86Local::MRM_D5: case X86Local::MRM_D6: case X86Local::MRM_D8: - case X86Local::MRM_D9: case X86Local::MRM_DA: case X86Local::MRM_DB: - case X86Local::MRM_DC: case X86Local::MRM_DD: case X86Local::MRM_DE: - case X86Local::MRM_DF: case X86Local::MRM_E0: case X86Local::MRM_E1: - case X86Local::MRM_E2: case X86Local::MRM_E3: case X86Local::MRM_E4: - case X86Local::MRM_E5: case X86Local::MRM_E8: case X86Local::MRM_E9: - case X86Local::MRM_EA: case X86Local::MRM_EB: case X86Local::MRM_EC: - case X86Local::MRM_ED: case X86Local::MRM_EE: case X86Local::MRM_F0: - case X86Local::MRM_F1: case X86Local::MRM_F2: case X86Local::MRM_F3: - case X86Local::MRM_F4: case X86Local::MRM_F5: case X86Local::MRM_F6: - case X86Local::MRM_F7: case X86Local::MRM_F9: case X86Local::MRM_FA: - case X86Local::MRM_FB: case X86Local::MRM_FC: case X86Local::MRM_FD: - case X86Local::MRM_FE: case X86Local::MRM_FF: + case X86Local::MRM_CF: case X86Local::MRM_D0: case X86Local::MRM_D1: + case X86Local::MRM_D4: case X86Local::MRM_D5: case X86Local::MRM_D6: + case X86Local::MRM_D7: case X86Local::MRM_D8: case X86Local::MRM_D9: + case X86Local::MRM_DA: case X86Local::MRM_DB: case X86Local::MRM_DC: + case X86Local::MRM_DD: case X86Local::MRM_DE: case X86Local::MRM_DF: + case X86Local::MRM_E0: case X86Local::MRM_E1: case X86Local::MRM_E2: + case X86Local::MRM_E3: case X86Local::MRM_E4: case X86Local::MRM_E5: + case X86Local::MRM_E8: case X86Local::MRM_E9: case X86Local::MRM_EA: + case X86Local::MRM_EB: case X86Local::MRM_EC: case X86Local::MRM_ED: + case X86Local::MRM_EE: case X86Local::MRM_F0: case X86Local::MRM_F1: + case X86Local::MRM_F2: case X86Local::MRM_F3: case X86Local::MRM_F4: + case X86Local::MRM_F5: case X86Local::MRM_F6: case X86Local::MRM_F7: + case X86Local::MRM_F9: case X86Local::MRM_FA: case X86Local::MRM_FB: + case X86Local::MRM_FC: case X86Local::MRM_FD: case X86Local::MRM_FE: + case X86Local::MRM_FF: // Ignored. break; } @@ -896,7 +907,6 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i32mem", TYPE_Mv) TYPE("i32imm", TYPE_IMMv) TYPE("i32i8imm", TYPE_IMM32) - TYPE("u32u8imm", TYPE_IMM32) TYPE("GR32", TYPE_R32) TYPE("GR32orGR64", TYPE_R32) TYPE("i64mem", TYPE_Mv) @@ -962,10 +972,18 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("VR512", TYPE_XMM512) TYPE("VK1", TYPE_VK1) TYPE("VK1WM", TYPE_VK1) + TYPE("VK2", TYPE_VK2) + TYPE("VK2WM", TYPE_VK2) + TYPE("VK4", TYPE_VK4) + TYPE("VK4WM", TYPE_VK4) TYPE("VK8", TYPE_VK8) TYPE("VK8WM", TYPE_VK8) TYPE("VK16", TYPE_VK16) TYPE("VK16WM", TYPE_VK16) + TYPE("VK32", TYPE_VK32) + TYPE("VK32WM", TYPE_VK32) + TYPE("VK64", TYPE_VK64) + TYPE("VK64WM", TYPE_VK64) TYPE("GR16_NOAX", TYPE_Rv) TYPE("GR32_NOAX", TYPE_Rv) TYPE("GR64_NOAX", TYPE_R64) @@ -991,7 +1009,6 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, ENCODING("i16imm", ENCODING_IW) } ENCODING("i32i8imm", ENCODING_IB) - ENCODING("u32u8imm", ENCODING_IB) ENCODING("SSECC", ENCODING_IB) ENCODING("AVXCC", ENCODING_IB) ENCODING("AVX512RC", ENCODING_IB) @@ -1038,6 +1055,8 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s, ENCODING("VK1", ENCODING_RM) ENCODING("VK8", ENCODING_RM) ENCODING("VK16", ENCODING_RM) + ENCODING("VK32", ENCODING_RM) + ENCODING("VK64", ENCODING_RM) errs() << "Unhandled R/M register encoding " << s << "\n"; llvm_unreachable("Unhandled R/M register encoding"); } @@ -1064,8 +1083,12 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s, ENCODING("FR32X", ENCODING_REG) ENCODING("VR512", ENCODING_REG) ENCODING("VK1", ENCODING_REG) + ENCODING("VK2", ENCODING_REG) + ENCODING("VK4", ENCODING_REG) ENCODING("VK8", ENCODING_REG) ENCODING("VK16", ENCODING_REG) + ENCODING("VK32", ENCODING_REG) + ENCODING("VK64", ENCODING_REG) ENCODING("VK1WM", ENCODING_REG) ENCODING("VK8WM", ENCODING_REG) ENCODING("VK16WM", ENCODING_REG) @@ -1088,8 +1111,12 @@ RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s, ENCODING("VR256X", ENCODING_VVVV) ENCODING("VR512", ENCODING_VVVV) ENCODING("VK1", ENCODING_VVVV) + ENCODING("VK2", ENCODING_VVVV) + ENCODING("VK4", ENCODING_VVVV) ENCODING("VK8", ENCODING_VVVV) ENCODING("VK16", ENCODING_VVVV) + ENCODING("VK32", ENCODING_VVVV) + ENCODING("VK64", ENCODING_VVVV) errs() << "Unhandled VEX.vvvv register encoding " << s << "\n"; llvm_unreachable("Unhandled VEX.vvvv register encoding"); } @@ -1098,8 +1125,12 @@ OperandEncoding RecognizableInstr::writemaskRegisterEncodingFromString(const std::string &s, uint8_t OpSize) { ENCODING("VK1WM", ENCODING_WRITEMASK) + ENCODING("VK2WM", ENCODING_WRITEMASK) + ENCODING("VK4WM", ENCODING_WRITEMASK) ENCODING("VK8WM", ENCODING_WRITEMASK) ENCODING("VK16WM", ENCODING_WRITEMASK) + ENCODING("VK32WM", ENCODING_WRITEMASK) + ENCODING("VK64WM", ENCODING_WRITEMASK) errs() << "Unhandled mask register encoding " << s << "\n"; llvm_unreachable("Unhandled mask register encoding"); } diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index 77286bc..95d7a40 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86RECOGNIZABLEINSTR_H -#define X86RECOGNIZABLEINSTR_H +#ifndef LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H +#define LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H #include "CodeGenTarget.h" #include "X86DisassemblerTables.h" @@ -78,6 +78,8 @@ private: bool IsCodeGenOnly; /// The ForceDisassemble field from the record bool ForceDisassemble; + // The CD8_Scale field from the record + uint8_t CD8_Scale; // Whether the instruction has the predicate "In64BitMode" bool Is64Bit; // Whether the instruction has the predicate "In32BitMode" @@ -153,6 +155,9 @@ private: static OperandEncoding writemaskRegisterEncodingFromString(const std::string &s, uint8_t OpSize); + /// \brief Adjust the encoding type for an operand based on the instruction. + void adjustOperandEncoding(OperandEncoding &encoding); + /// handleOperand - Converts a single operand from the LLVM table format to /// the emitted table format, handling any duplicate operands it encounters /// and then one non-duplicate. diff --git a/utils/bisect b/utils/bisect new file mode 100755 index 0000000..d1b1257 --- /dev/null +++ b/utils/bisect @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import os +import sys +import argparse +import subprocess + +parser = argparse.ArgumentParser() + +parser.add_argument('--start', type=int, default=0) +parser.add_argument('--end', type=int, default=(1 << 32)) +parser.add_argument('command', nargs='+') + +args = parser.parse_args() + +start = args.start +end = args.end + +print("Bisect Starting!") +print("Start: %d" % start) +print("End: %d" % end) + +last = None +while start != end and start != end-1: + count = start + (end - start)/2 + print("Visiting Count: %d with (Start, End) = (%d,%d)" % (count, start, end)) + cmd = [x % {'count':count} for x in args.command] + print cmd + result = subprocess.call(cmd) + if result == 0: + print(" PASSES! Setting start to count") + start = count + else: + print(" FAILS! Setting end to count") + end = count + +print("Last good count: %d" % start) diff --git a/utils/emacs/llvm-mode.el b/utils/emacs/llvm-mode.el index 99d3294..61127b6 100644 --- a/utils/emacs/llvm-mode.el +++ b/utils/emacs/llvm-mode.el @@ -48,6 +48,8 @@ `(,(regexp-opt '("extractelement" "insertelement" "shufflevector") 'words) . font-lock-keyword-face) ;; Aggregate ops `(,(regexp-opt '("extractvalue" "insertvalue") 'words) . font-lock-keyword-face) + ;; Use-list order directives + `(,(regexp-opt '("uselistorder" "uselistorder_bb") 'words) . font-lock-keyword-face) ) "Syntax highlighting for LLVM" diff --git a/utils/findmisopt b/utils/findmisopt index 88f991a..2405220 100755 --- a/utils/findmisopt +++ b/utils/findmisopt @@ -74,8 +74,8 @@ echo "Unoptimized program: $prog" echo " Optimized program: $optprog" # Define the list of optimizations to run. This comprises the same set of -# optimizations that opt -std-compile-opts and gccld run, in the same order. -opt_switches=`llvm-as < /dev/null -o - | opt -std-compile-opts -disable-output -debug-pass=Arguments 2>&1 | sed 's/Pass Arguments: //'` +# optimizations that opt -O3 runs, in the same order. +opt_switches=`llvm-as < /dev/null -o - | opt -O3 -disable-output -debug-pass=Arguments 2>&1 | sed 's/Pass Arguments: //'` all_switches="$opt_switches" echo "Passes : $all_switches" diff --git a/utils/git-svn/git-svnrevert b/utils/git-svn/git-svnrevert index 06a9c44..f15e7ab 100755 --- a/utils/git-svn/git-svnrevert +++ b/utils/git-svn/git-svnrevert @@ -2,7 +2,7 @@ if [ $# -ne 1 ]; then echo "Invalid arguments!" - echo "$0 <commit to revert>" + echo "$0 <rNNNNNN | git-hash>" exit 1 fi @@ -13,20 +13,27 @@ if [ -n "$(git status -uno -s --porcelain)" ]; then fi COMMIT=$1 - -SVN_REVISION=$(git svn find-rev "$COMMIT") +OTHER=$(git svn find-rev "$COMMIT") if [ $? -ne 0 ]; then - echo "Error! Could not find an svn revision for commit $COMMIT!" + echo "Error! Could not find an svn/git revision for commit $COMMIT!" exit 1 fi +if [ -n "$(echo $COMMIT | grep '^r[0-9]\+')" ]; then + SVN=`echo $COMMIT | sed -e 's/^r//'` + GIT=$OTHER +else + SVN=$OTHER + GIT=$COMMIT +fi + # Grab the one line message for our revert commit message. -ONE_LINE_MSG=$(git log --oneline $COMMIT -1 | cut -f2- -d " ") +ONE_LINE_MSG=$(git log --oneline $GIT -1 | cut -f2- -d " ") # Revert the commit. -git revert --no-commit $COMMIT 2>/dev/null +git revert --no-commit $GIT 2>/dev/null if [ $? -ne 0 ]; then - echo "Error! Failed to revert commit $COMMIT. Resetting to head." + echo "Error! Failed to revert commit r$SVN. Resetting to head." git reset --hard HEAD exit 1 fi @@ -36,13 +43,13 @@ TEMPLATE="`git rev-parse --git-dir`/git-svn-revert-template" cat > $TEMPLATE <<EOF Revert "$ONE_LINE_MSG" -This reverts commit r$SVN_REVISION. +This reverts commit r$SVN. EOF # Begin the commit but give our user an opportunity to edit it. git commit --file="$TEMPLATE" --edit if [ $? -ne 0 ]; then - echo "Error! Failed to commit reverting commit for commit $COMMIT. Reverting to head." + echo "Error! Failed to commit reverting commit for commit r$SVN. Reverting to head." git reset --hard HEAD rm -rf $TEMPLATE exit 1 diff --git a/utils/lit/TODO b/utils/lit/TODO index c1a60c6..90da327 100644 --- a/utils/lit/TODO +++ b/utils/lit/TODO @@ -156,8 +156,6 @@ Miscellaneous * Move temp directory name into local test config. -* Add --show-unsupported, don't show by default? - * Support valgrind in all configs, and LLVM style valgrind. * Support a timeout / ulimit. diff --git a/utils/lit/lit/ProgressBar.py b/utils/lit/lit/ProgressBar.py index e3644f1..3ad704d 100644 --- a/utils/lit/lit/ProgressBar.py +++ b/utils/lit/lit/ProgressBar.py @@ -6,8 +6,8 @@ import sys, re, time def to_bytes(str): - # Encode to Latin1 to get binary data. - return str.encode('ISO-8859-1') + # Encode to UTF-8 to get binary data. + return str.encode('utf-8') class TerminalController: """ @@ -136,7 +136,7 @@ class TerminalController: def _tparm(self, arg, index): import curses - return curses.tparm(to_bytes(arg), index).decode('ascii') or '' + return curses.tparm(to_bytes(arg), index).decode('utf-8') or '' def _tigetstr(self, cap_name): # String capabilities can include "delays" of the form "$<2>". @@ -147,7 +147,7 @@ class TerminalController: if cap is None: cap = '' else: - cap = cap.decode('ascii') + cap = cap.decode('utf-8') return re.sub(r'\$<\d+>[/*]?', '', cap) def render(self, template): diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py index 9752417..1a2df20 100644 --- a/utils/lit/lit/TestRunner.py +++ b/utils/lit/lit/TestRunner.py @@ -144,13 +144,16 @@ def executeShCmd(cmd, cfg, cwd, results): named_temp_files.append(f.name) args[i] = f.name - procs.append(subprocess.Popen(args, cwd=cwd, - executable = executable, - stdin = stdin, - stdout = stdout, - stderr = stderr, - env = cfg.environment, - close_fds = kUseCloseFDs)) + try: + procs.append(subprocess.Popen(args, cwd=cwd, + executable = executable, + stdin = stdin, + stdout = stdout, + stderr = stderr, + env = cfg.environment, + close_fds = kUseCloseFDs)) + except OSError as e: + raise InternalShellError(j, 'Could not create process due to {}'.format(e)) # Immediately close stdin for any process taking stdin from us. if stdin == subprocess.PIPE: @@ -192,6 +195,11 @@ def executeShCmd(cmd, cfg, cwd, results): f.seek(0, 0) procData[i] = (procData[i][0], f.read()) + def to_string(bytes): + if isinstance(bytes, str): + return bytes + return bytes.encode('utf-8') + exitCode = None for i,(out,err) in enumerate(procData): res = procs[i].wait() @@ -201,11 +209,11 @@ def executeShCmd(cmd, cfg, cwd, results): # Ensure the resulting output is always of string type. try: - out = str(out.decode('ascii')) + out = to_string(out.decode('utf-8')) except: out = str(out) try: - err = str(err.decode('ascii')) + err = to_string(err.decode('utf-8')) except: err = str(err) @@ -314,13 +322,18 @@ def parseIntegratedTestScriptCommands(source_path): # Python2 and bytes in Python3. # # Once we find a match, we do require each script line to be decodable to - # ascii, so we convert the outputs to ascii before returning. This way the + # UTF-8, so we convert the outputs to UTF-8 before returning. This way the # remaining code can work with "strings" agnostic of the executing Python # version. def to_bytes(str): - # Encode to Latin1 to get binary data. - return str.encode('ISO-8859-1') + # Encode to UTF-8 to get binary data. + return str.encode('utf-8') + def to_string(bytes): + if isinstance(bytes, str): + return bytes + return to_bytes(bytes) + keywords = ('RUN:', 'XFAIL:', 'REQUIRES:', 'END.') keywords_re = re.compile( to_bytes("(%s)(.*)\n" % ("|".join(k for k in keywords),))) @@ -330,6 +343,10 @@ def parseIntegratedTestScriptCommands(source_path): # Read the entire file contents. data = f.read() + # Ensure the data ends with a newline. + if not data.endswith(to_bytes('\n')): + data = data + to_bytes('\n') + # Iterate over the matches. line_number = 1 last_match_position = 0 @@ -341,13 +358,13 @@ def parseIntegratedTestScriptCommands(source_path): match_position) last_match_position = match_position - # Convert the keyword and line to ascii strings and yield the + # Convert the keyword and line to UTF-8 strings and yield the # command. Note that we take care to return regular strings in # Python 2, to avoid other code having to differentiate between the # str and unicode types. keyword,ln = match.groups() - yield (line_number, str(keyword[:-1].decode('ascii')), - str(ln.decode('ascii'))) + yield (line_number, to_string(keyword[:-1].decode('utf-8')), + to_string(ln.decode('utf-8'))) finally: f.close() diff --git a/utils/lit/lit/TestingConfig.py b/utils/lit/lit/TestingConfig.py index eb89067..4cd9486 100644 --- a/utils/lit/lit/TestingConfig.py +++ b/utils/lit/lit/TestingConfig.py @@ -17,15 +17,16 @@ class TestingConfig: """ # Set the environment based on the command line arguments. environment = { - 'LIBRARY_PATH' : os.environ.get('LIBRARY_PATH',''), - 'LD_LIBRARY_PATH' : os.environ.get('LD_LIBRARY_PATH',''), 'PATH' : os.pathsep.join(litConfig.path + [os.environ.get('PATH','')]), - 'SYSTEMROOT' : os.environ.get('SYSTEMROOT',''), - 'TERM' : os.environ.get('TERM',''), 'LLVM_DISABLE_CRASH_REPORT' : '1', } + pass_vars = ['LIBRARY_PATH', 'LD_LIBRARY_PATH', 'SYSTEMROOT', 'TERM', + 'LD_PRELOAD', 'ASAN_OPTIONS', 'UBSAN_OPTIONS'] + for var in pass_vars: + environment[var] = os.environ.get(var, '') + if sys.platform == 'win32': environment.update({ 'INCLUDE' : os.environ.get('INCLUDE',''), diff --git a/utils/lit/lit/__init__.py b/utils/lit/lit/__init__.py index 46fa82d..c1bd76b 100644 --- a/utils/lit/lit/__init__.py +++ b/utils/lit/lit/__init__.py @@ -5,7 +5,7 @@ from .main import main __author__ = 'Daniel Dunbar' __email__ = 'daniel@zuster.org' -__versioninfo__ = (0, 4, 0) +__versioninfo__ = (0, 5, 0) __version__ = '.'.join(str(v) for v in __versioninfo__) + 'dev' __all__ = [] diff --git a/utils/lit/lit/discovery.py b/utils/lit/lit/discovery.py index 876d4f3..4befe58 100644 --- a/utils/lit/lit/discovery.py +++ b/utils/lit/lit/discovery.py @@ -91,7 +91,7 @@ def getLocalConfig(ts, path_in_suite, litConfig, cache): # Otherwise, copy the current config and load the local configuration # file into it. - config = copy.copy(parent) + config = copy.deepcopy(parent) if litConfig.debug: litConfig.note('loading local config %r' % cfgpath) config.load_from_path(cfgpath, litConfig) diff --git a/utils/lit/lit/formats/googletest.py b/utils/lit/lit/formats/googletest.py index 3d14b729..1b5b785 100644 --- a/utils/lit/lit/formats/googletest.py +++ b/utils/lit/lit/formats/googletest.py @@ -31,7 +31,7 @@ class GoogleTest(TestFormat): try: lines = lit.util.capture([path, '--gtest_list_tests'], env=localConfig.environment) - lines = lines.decode('ascii') + lines = lines.decode('utf-8') if kIsWindows: lines = lines.replace('\r', '') lines = lines.split('\n') diff --git a/utils/lit/lit/main.py b/utils/lit/lit/main.py index c59651a..7343d24 100755 --- a/utils/lit/lit/main.py +++ b/utils/lit/lit/main.py @@ -42,8 +42,9 @@ class TestingProgressDisplay(object): self.progressBar.update(float(self.completed)/self.numTests, test.getFullName()) - if not test.result.code.isFailure and \ - (self.opts.quiet or self.opts.succinct): + shouldShow = test.result.code.isFailure or \ + (not self.opts.quiet and not self.opts.succinct) + if not shouldShow: return if self.progressBar: @@ -168,6 +169,12 @@ def main(builtinParameters = {}): group.add_option("", "--no-progress-bar", dest="useProgressBar", help="Do not use curses based progress bar", action="store_false", default=True) + group.add_option("", "--show-unsupported", dest="show_unsupported", + help="Show unsupported tests", + action="store_true", default=False) + group.add_option("", "--show-xfail", dest="show_xfail", + help="Show tests that were expected to fail", + action="store_true", default=False) parser.add_option_group(group) group = OptionGroup(parser, "Test Execution") @@ -382,7 +389,12 @@ def main(builtinParameters = {}): # Print each test in any of the failing groups. for title,code in (('Unexpected Passing Tests', lit.Test.XPASS), ('Failing Tests', lit.Test.FAIL), - ('Unresolved Tests', lit.Test.UNRESOLVED)): + ('Unresolved Tests', lit.Test.UNRESOLVED), + ('Unsupported Tests', lit.Test.UNSUPPORTED), + ('Expected Failing Tests', lit.Test.XFAIL)): + if (lit.Test.XFAIL == code and not opts.show_xfail) or \ + (lit.Test.UNSUPPORTED == code and not opts.show_unsupported): + continue elts = byCode.get(code) if not elts: continue @@ -403,7 +415,7 @@ def main(builtinParameters = {}): ('Unsupported Tests ', lit.Test.UNSUPPORTED), ('Unresolved Tests ', lit.Test.UNRESOLVED), ('Unexpected Passes ', lit.Test.XPASS), - ('Unexpected Failures', lit.Test.FAIL),): + ('Unexpected Failures', lit.Test.FAIL)): if opts.quiet and not code.isFailure: continue N = len(byCode.get(code,[])) diff --git a/utils/lit/lit/util.py b/utils/lit/lit/util.py index 72a8b48..cce620c 100644 --- a/utils/lit/lit/util.py +++ b/utils/lit/lit/util.py @@ -156,13 +156,18 @@ def executeCommand(command, cwd=None, env=None): if exitCode == -signal.SIGINT: raise KeyboardInterrupt + def to_string(bytes): + if isinstance(bytes, str): + return bytes + return bytes.encode('utf-8') + # Ensure the resulting output is always of string type. try: - out = str(out.decode('ascii')) + out = to_string(out.decode('utf-8')) except: out = str(out) try: - err = str(err.decode('ascii')) + err = to_string(err.decode('utf-8')) except: err = str(err) diff --git a/utils/lldbDataFormatters.py b/utils/lldbDataFormatters.py index 352448d..f570fb4 100644 --- a/utils/lldbDataFormatters.py +++ b/utils/lldbDataFormatters.py @@ -12,6 +12,9 @@ def __lldb_init_module(debugger, internal_dict): debugger.HandleCommand('type synthetic add -w llvm ' '-l lldbDataFormatters.SmallVectorSynthProvider ' '-x "^llvm::SmallVector<.+,.+>$"') + debugger.HandleCommand('type synthetic add -w llvm ' + '-l lldbDataFormatters.ArrayRefSynthProvider ' + '-x "^llvm::ArrayRef<.+>$"') # Pretty printer for llvm::SmallVector/llvm::SmallVectorImpl class SmallVectorSynthProvider: @@ -53,3 +56,33 @@ class SmallVectorSynthProvider: self.data_type = the_type.GetTemplateArgumentType(0) self.type_size = self.data_type.GetByteSize() assert self.type_size != 0 + +class ArrayRefSynthProvider: + """ Provider for llvm::ArrayRef """ + def __init__(self, valobj, dict): + self.valobj = valobj; + self.update() # initialize this provider + + def num_children(self): + return self.length + + def get_child_index(self, name): + try: + return int(name.lstrip('[').rstrip(']')) + except: + return -1; + + def get_child_at_index(self, index): + if index < 0 or index >= self.num_children(): + return None; + offset = index * self.type_size + return self.data.CreateChildAtOffset('[' + str(index) + ']', + offset, self.data_type) + + def update(self): + self.data = self.valobj.GetChildMemberWithName('Data') + length_obj = self.valobj.GetChildMemberWithName('Length') + self.length = length_obj.GetValueAsUnsigned(0) + self.data_type = self.data.GetType().GetPointeeType() + self.type_size = self.data_type.GetByteSize() + assert self.type_size != 0 diff --git a/utils/llvm-build/llvmbuild/main.py b/utils/llvm-build/llvmbuild/main.py index 37aa5d8..353741f 100644 --- a/utils/llvm-build/llvmbuild/main.py +++ b/utils/llvm-build/llvmbuild/main.py @@ -1,4 +1,5 @@ from __future__ import absolute_import +import filecmp import os import sys @@ -41,7 +42,7 @@ def mk_quote_string_for_target(value): """ mk_quote_string_for_target(target_name) -> str - Return a quoted form of the given target_name suitable for including in a + Return a quoted form of the given target_name suitable for including in a Makefile as a target name. """ @@ -340,7 +341,7 @@ subdirectories = %s # Compute the llvm-config "component name". For historical reasons, # this is lowercased based on the library name. llvmconfig_component_name = c.get_llvmconfig_component_name() - + # Get the library name, or None for LibraryGroups. if c.type_name == 'Library' or c.type_name == 'OptionalLibrary': library_name = c.get_prefixed_library_name() @@ -382,7 +383,7 @@ subdirectories = %s # Write out the library table. make_install_dir(os.path.dirname(output_path)) - f = open(output_path, 'w') + f = open(output_path+'.new', 'w') f.write("""\ //===- llvm-build generated file --------------------------------*- C++ -*-===// // @@ -420,6 +421,14 @@ subdirectories = %s f.write('};\n') f.close() + if not os.path.isfile(output_path): + os.rename(output_path+'.new', output_path) + elif filecmp.cmp(output_path, output_path+'.new'): + os.remove(output_path+'.new') + else: + os.remove(output_path) + os.rename(output_path+'.new', output_path) + def get_required_libraries_for_component(self, ci, traverse_groups = False): """ get_required_libraries_for_component(component_info) -> iter @@ -430,14 +439,14 @@ subdirectories = %s traversed to include their required libraries. """ - assert ci.type_name in ('Library', 'LibraryGroup', 'TargetGroup') + assert ci.type_name in ('Library', 'OptionalLibrary', 'LibraryGroup', 'TargetGroup') for name in ci.required_libraries: # Get the dependency info. dep = self.component_info_map[name] # If it is a library, yield it. - if dep.type_name == 'Library': + if dep.type_name == 'Library' or dep.type_name == 'OptionalLibrary': yield dep continue @@ -492,7 +501,7 @@ subdirectories = %s if (path.startswith(self.source_root) and os.path.exists(path)): yield path - def write_cmake_fragment(self, output_path): + def write_cmake_fragment(self, output_path, enabled_optional_components): """ write_cmake_fragment(output_path) -> None @@ -561,8 +570,13 @@ configure_file(\"%s\" # names to required libraries, in a way that is easily accessed from CMake. """) for ci in self.ordered_component_infos: - # We only write the information for libraries currently. - if ci.type_name != 'Library': + # Skip optional components which are not enabled. + if ci.type_name == 'OptionalLibrary' \ + and ci.name not in enabled_optional_components: + continue + + # We only write the information for certain components currently. + if ci.type_name not in ('Library', 'OptionalLibrary'): continue f.write("""\ @@ -573,7 +587,7 @@ set_property(GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_%s %s)\n""" % ( f.close() - def write_cmake_exports_fragment(self, output_path): + def write_cmake_exports_fragment(self, output_path, enabled_optional_components): """ write_cmake_exports_fragment(output_path) -> None @@ -595,8 +609,13 @@ set_property(GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_%s %s)\n""" % ( # dependencies of libraries imported from LLVM. """) for ci in self.ordered_component_infos: + # Skip optional components which are not enabled. + if ci.type_name == 'OptionalLibrary' \ + and ci.name not in enabled_optional_components: + continue + # We only write the information for libraries currently. - if ci.type_name != 'Library': + if ci.type_name not in ('Library', 'OptionalLibrary'): continue # Skip disabled targets. @@ -783,7 +802,7 @@ def add_magic_target_components(parser, project, opts): # If we have a native target with a JIT, use that for the engine. Otherwise, # use the interpreter. if native_target and native_target.enabled and native_target.has_jit: - engine_group.required_libraries.append('JIT') + engine_group.required_libraries.append('MCJIT') engine_group.required_libraries.append(native_group.name) else: engine_group.required_libraries.append('Interpreter') @@ -905,9 +924,11 @@ given by --build-root) at the same SUBPATH""", # Write out the cmake fragment, if requested. if opts.write_cmake_fragment: - project_info.write_cmake_fragment(opts.write_cmake_fragment) + project_info.write_cmake_fragment(opts.write_cmake_fragment, + opts.optional_components) if opts.write_cmake_exports_fragment: - project_info.write_cmake_exports_fragment(opts.write_cmake_exports_fragment) + project_info.write_cmake_exports_fragment(opts.write_cmake_exports_fragment, + opts.optional_components) # Configure target definition files, if requested. if opts.configure_target_def_files: diff --git a/utils/not/not.cpp b/utils/not/not.cpp index a5c7183..2adeded 100644 --- a/utils/not/not.cpp +++ b/utils/not/not.cpp @@ -27,10 +27,15 @@ int main(int argc, const char **argv) { if (argc == 0) return 1; - std::string Program = sys::FindProgramByName(argv[0]); + auto Program = sys::findProgramByName(argv[0]); + if (!Program) { + errs() << "Error: Unable to find `" << argv[0] + << "' in PATH: " << Program.getError().message() << "\n"; + return 1; + } std::string ErrMsg; - int Result = sys::ExecuteAndWait(Program, argv, nullptr, nullptr, 0, 0, + int Result = sys::ExecuteAndWait(*Program, argv, nullptr, nullptr, 0, 0, &ErrMsg); #ifdef _WIN32 // Handle abort() in msvcrt -- It has exit code as 3. abort(), aka diff --git a/utils/release/export.sh b/utils/release/export.sh index f25a193..38e5a81 100755 --- a/utils/release/export.sh +++ b/utils/release/export.sh @@ -14,7 +14,7 @@ set -e -projects="llvm cfe dragonegg test-suite compiler-rt libcxx clang-tools-extra polly lldb" +projects="llvm cfe dragonegg test-suite compiler-rt libcxx libcxxabi clang-tools-extra polly lldb lld openmp" base_url="https://llvm.org/svn/llvm-project" release="" @@ -44,7 +44,7 @@ function export_sources() { $proj-$release$rc.src echo "Creating tarball ..." - tar cfz $proj-$release$rc.src.tar.gz $proj-$release$rc.src + tar cfJ $proj-$release$rc.src.tar.xz $proj-$release$rc.src done } diff --git a/utils/release/tag.sh b/utils/release/tag.sh index 6c5039d..390acaf 100755 --- a/utils/release/tag.sh +++ b/utils/release/tag.sh @@ -17,7 +17,7 @@ set -e release="" rc="" rebranch="no" -projects="llvm cfe dragonegg test-suite compiler-rt libcxx clang-tools-extra polly lldb lld" +projects="llvm cfe dragonegg test-suite compiler-rt libcxx libcxxabi clang-tools-extra polly lldb lld openmp" base_url="https://llvm.org/svn/llvm-project" @@ -34,16 +34,16 @@ function usage() { function tag_version() { set -x for proj in $projects; do - if svn ls $base_url/$proj/branches/release_$release > /dev/null 2>&1 ; then + if svn ls $base_url/$proj/branches/release_$branch_release > /dev/null 2>&1 ; then if [ $rebranch = "no" ]; then continue fi - svn remove -m "Removing old release_$release branch for rebranching." \ - $base_url/$proj/branches/release_$release + svn remove -m "Removing old release_$branch_release branch for rebranching." \ + $base_url/$proj/branches/release_$branch_release fi - svn copy -m "Creating release_$release branch" \ + svn copy -m "Creating release_$branch_release branch" \ $base_url/$proj/trunk \ - $base_url/$proj/branches/release_$release + $base_url/$proj/branches/release_$branch_release done set +x } @@ -51,13 +51,13 @@ function tag_version() { function tag_release_candidate() { set -x for proj in $projects ; do - if ! svn ls $base_url/$proj/tags/RELEASE_$release > /dev/null 2>&1 ; then - svn mkdir -m "Creating release directory for release_$release." $base_url/$proj/tags/RELEASE_$release + if ! svn ls $base_url/$proj/tags/RELEASE_$tag_release > /dev/null 2>&1 ; then + svn mkdir -m "Creating release directory for release_$tag_release." $base_url/$proj/tags/RELEASE_$tag_release fi - if ! svn ls $base_url/$proj/tags/RELEASE_$release/$rc > /dev/null 2>&1 ; then - svn copy -m "Creating release candidate $rc from release_$release branch" \ - $base_url/$proj/branches/release_$release \ - $base_url/$proj/tags/RELEASE_$release/$rc + if ! svn ls $base_url/$proj/tags/RELEASE_$tag_release/$rc > /dev/null 2>&1 ; then + svn copy -m "Creating release candidate $rc from release_$tag_release branch" \ + $base_url/$proj/branches/release_$branch_release \ + $base_url/$proj/tags/RELEASE_$tag_release/$rc fi done set +x @@ -99,7 +99,8 @@ if [ "x$release" = "x" ]; then exit 1 fi -release=`echo $release | sed -e 's,\.,,g'` +branch_release=`echo $release | sed -e 's,\([0-9]*\.[0-9]*\).*,\1,' | sed -e 's,\.,,g'` +tag_release=`echo $release | sed -e 's,\.,,g'` if [ "x$rc" = "x" ]; then tag_version diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh index b4d7689..b028924 100755 --- a/utils/release/test-release.sh +++ b/utils/release/test-release.sh @@ -18,7 +18,7 @@ else MAKE=make fi -projects="llvm cfe dragonegg compiler-rt libcxx test-suite clang-tools-extra" +projects="llvm cfe dragonegg compiler-rt libcxx libcxxabi test-suite clang-tools-extra" # Base SVN URL for the sources. Base_url="http://llvm.org/svn/llvm-project" @@ -67,7 +67,7 @@ while [ $# -gt 0 ]; do -release | --release ) shift Release="$1" - Release_no_dot="`echo $1 | sed -e 's,\.,,'`" + Release_no_dot="`echo $1 | sed -e 's,\.,,g'`" ;; -rc | --rc | -RC | --RC ) shift @@ -260,6 +260,9 @@ function export_sources() { if [ ! -h libcxx ]; then ln -s ../../libcxx.src libcxx fi + if [ ! -h libcxxabi ]; then + ln -s ../../libcxxabi.src libcxxabi + fi cd $BuildDir } diff --git a/utils/shuffle_fuzz.py b/utils/shuffle_fuzz.py new file mode 100755 index 0000000..384a93a --- /dev/null +++ b/utils/shuffle_fuzz.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python + +"""A shuffle vector fuzz tester. + +This is a python program to fuzz test the LLVM shufflevector instruction. It +generates a function with a random sequnece of shufflevectors, maintaining the +element mapping accumulated across the function. It then generates a main +function which calls it with a different value in each element and checks that +the result matches the expected mapping. + +Take the output IR printed to stdout, compile it to an executable using whatever +set of transforms you want to test, and run the program. If it crashes, it found +a bug. +""" + +import argparse +import itertools +import random +import sys +import uuid + +def main(): + element_types=['i8', 'i16', 'i32', 'i64', 'f32', 'f64'] + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('-v', '--verbose', action='store_true', + help='Show verbose output') + parser.add_argument('--seed', default=str(uuid.uuid4()), + help='A string used to seed the RNG') + parser.add_argument('--max-shuffle-height', type=int, default=16, + help='Specify a fixed height of shuffle tree to test') + parser.add_argument('--no-blends', dest='blends', action='store_false', + help='Include blends of two input vectors') + parser.add_argument('--fixed-bit-width', type=int, choices=[128, 256], + help='Specify a fixed bit width of vector to test') + parser.add_argument('--fixed-element-type', choices=element_types, + help='Specify a fixed element type to test') + parser.add_argument('--triple', + help='Specify a triple string to include in the IR') + args = parser.parse_args() + + random.seed(args.seed) + + if args.fixed_element_type is not None: + element_types=[args.fixed_element_type] + + if args.fixed_bit_width is not None: + if args.fixed_bit_width == 128: + width_map={'i64': 2, 'i32': 4, 'i16': 8, 'i8': 16, 'f64': 2, 'f32': 4} + (width, element_type) = random.choice( + [(width_map[t], t) for t in element_types]) + elif args.fixed_bit_width == 256: + width_map={'i64': 4, 'i32': 8, 'i16': 16, 'i8': 32, 'f64': 4, 'f32': 8} + (width, element_type) = random.choice( + [(width_map[t], t) for t in element_types]) + else: + sys.exit(1) # Checked above by argument parsing. + else: + width = random.choice([2, 4, 8, 16, 32, 64]) + element_type = random.choice(element_types) + + element_modulus = { + 'i8': 1 << 8, 'i16': 1 << 16, 'i32': 1 << 32, 'i64': 1 << 64, + 'f32': 1 << 32, 'f64': 1 << 64}[element_type] + + shuffle_range = (2 * width) if args.blends else width + + # Because undef (-1) saturates and is indistinguishable when testing the + # correctness of a shuffle, we want to bias our fuzz toward having a decent + # mixture of non-undef lanes in the end. With a deep shuffle tree, the + # probabilies aren't good so we need to bias things. The math here is that if + # we uniformly select between -1 and the other inputs, each element of the + # result will have the following probability of being undef: + # + # 1 - (shuffle_range/(shuffle_range+1))^max_shuffle_height + # + # More generally, for any probability P of selecting a defined element in + # a single shuffle, the end result is: + # + # 1 - P^max_shuffle_height + # + # The power of the shuffle height is the real problem, as we want: + # + # 1 - shuffle_range/(shuffle_range+1) + # + # So we bias the selection of undef at any given node based on the tree + # height. Below, let 'A' be 'len(shuffle_range)', 'C' be 'max_shuffle_height', + # and 'B' be the bias we use to compensate for + # C '((A+1)*A^(1/C))/(A*(A+1)^(1/C))': + # + # 1 - (B * A)/(A + 1)^C = 1 - A/(A + 1) + # + # So at each node we use: + # + # 1 - (B * A)/(A + 1) + # = 1 - ((A + 1) * A * A^(1/C))/(A * (A + 1) * (A + 1)^(1/C)) + # = 1 - ((A + 1) * A^((C + 1)/C))/(A * (A + 1)^((C + 1)/C)) + # + # This is the formula we use to select undef lanes in the shuffle. + A = float(shuffle_range) + C = float(args.max_shuffle_height) + undef_prob = 1.0 - (((A + 1.0) * pow(A, (C + 1.0)/C)) / + (A * pow(A + 1.0, (C + 1.0)/C))) + + shuffle_tree = [[[-1 if random.random() <= undef_prob + else random.choice(range(shuffle_range)) + for _ in itertools.repeat(None, width)] + for _ in itertools.repeat(None, args.max_shuffle_height - i)] + for i in xrange(args.max_shuffle_height)] + + if args.verbose: + # Print out the shuffle sequence in a compact form. + print >>sys.stderr, ('Testing shuffle sequence "%s" (v%d%s):' % + (args.seed, width, element_type)) + for i, shuffles in enumerate(shuffle_tree): + print >>sys.stderr, ' tree level %d:' % (i,) + for j, s in enumerate(shuffles): + print >>sys.stderr, ' shuffle %d: %s' % (j, s) + print >>sys.stderr, '' + + # Symbolically evaluate the shuffle tree. + inputs = [[int(j % element_modulus) + for j in xrange(i * width + 1, (i + 1) * width + 1)] + for i in xrange(args.max_shuffle_height + 1)] + results = inputs + for shuffles in shuffle_tree: + results = [[((results[i] if j < width else results[i + 1])[j % width] + if j != -1 else -1) + for j in s] + for i, s in enumerate(shuffles)] + if len(results) != 1: + print >>sys.stderr, 'ERROR: Bad results: %s' % (results,) + sys.exit(1) + result = results[0] + + if args.verbose: + print >>sys.stderr, 'Which transforms:' + print >>sys.stderr, ' from: %s' % (inputs,) + print >>sys.stderr, ' into: %s' % (result,) + print >>sys.stderr, '' + + # The IR uses silly names for floating point types. We also need a same-size + # integer type. + integral_element_type = element_type + if element_type == 'f32': + integral_element_type = 'i32' + element_type = 'float' + elif element_type == 'f64': + integral_element_type = 'i64' + element_type = 'double' + + # Now we need to generate IR for the shuffle function. + subst = {'N': width, 'T': element_type, 'IT': integral_element_type} + print """ +define internal fastcc <%(N)d x %(T)s> @test(%(arguments)s) noinline nounwind { +entry:""" % dict(subst, + arguments=', '.join( + ['<%(N)d x %(T)s> %%s.0.%(i)d' % dict(subst, i=i) + for i in xrange(args.max_shuffle_height + 1)])) + + for i, shuffles in enumerate(shuffle_tree): + for j, s in enumerate(shuffles): + print """ + %%s.%(next_i)d.%(j)d = shufflevector <%(N)d x %(T)s> %%s.%(i)d.%(j)d, <%(N)d x %(T)s> %%s.%(i)d.%(next_j)d, <%(N)d x i32> <%(S)s> +""".strip('\n') % dict(subst, i=i, next_i=i + 1, j=j, next_j=j + 1, + S=', '.join(['i32 ' + (str(si) if si != -1 else 'undef') + for si in s])) + + print """ + ret <%(N)d x %(T)s> %%s.%(i)d.0 +} +""" % dict(subst, i=len(shuffle_tree)) + + # Generate some string constants that we can use to report errors. + for i, r in enumerate(result): + if r != -1: + s = ('FAIL(%(seed)s): lane %(lane)d, expected %(result)d, found %%d\\0A' % + {'seed': args.seed, 'lane': i, 'result': r}) + s += ''.join(['\\00' for _ in itertools.repeat(None, 128 - len(s) + 2)]) + print """ +@error.%(i)d = private unnamed_addr global [128 x i8] c"%(s)s" +""".strip() % {'i': i, 's': s} + + # Define a wrapper function which is marked 'optnone' to prevent + # interprocedural optimizations from deleting the test. + print """ +define internal fastcc <%(N)d x %(T)s> @test_wrapper(%(arguments)s) optnone noinline { + %%result = call fastcc <%(N)d x %(T)s> @test(%(arguments)s) + ret <%(N)d x %(T)s> %%result +} +""" % dict(subst, + arguments=', '.join(['<%(N)d x %(T)s> %%s.%(i)d' % dict(subst, i=i) + for i in xrange(args.max_shuffle_height + 1)])) + + # Finally, generate a main function which will trap if any lanes are mapped + # incorrectly (in an observable way). + print """ +define i32 @main() { +entry: + ; Create a scratch space to print error messages. + %%str = alloca [128 x i8] + %%str.ptr = getelementptr inbounds [128 x i8]* %%str, i32 0, i32 0 + + ; Build the input vector and call the test function. + %%v = call fastcc <%(N)d x %(T)s> @test_wrapper(%(inputs)s) + ; We need to cast this back to an integer type vector to easily check the + ; result. + %%v.cast = bitcast <%(N)d x %(T)s> %%v to <%(N)d x %(IT)s> + br label %%test.0 +""" % dict(subst, + inputs=', '.join( + [('<%(N)d x %(T)s> bitcast ' + '(<%(N)d x %(IT)s> <%(input)s> to <%(N)d x %(T)s>)' % + dict(subst, input=', '.join(['%(IT)s %(i)d' % dict(subst, i=i) + for i in input]))) + for input in inputs])) + + # Test that each non-undef result lane contains the expected value. + for i, r in enumerate(result): + if r == -1: + print """ +test.%(i)d: + ; Skip this lane, its value is undef. + br label %%test.%(next_i)d +""" % dict(subst, i=i, next_i=i + 1) + else: + print """ +test.%(i)d: + %%v.%(i)d = extractelement <%(N)d x %(IT)s> %%v.cast, i32 %(i)d + %%cmp.%(i)d = icmp ne %(IT)s %%v.%(i)d, %(r)d + br i1 %%cmp.%(i)d, label %%die.%(i)d, label %%test.%(next_i)d + +die.%(i)d: + ; Capture the actual value and print an error message. + %%tmp.%(i)d = zext %(IT)s %%v.%(i)d to i2048 + %%bad.%(i)d = trunc i2048 %%tmp.%(i)d to i32 + call i32 (i8*, i8*, ...)* @sprintf(i8* %%str.ptr, i8* getelementptr inbounds ([128 x i8]* @error.%(i)d, i32 0, i32 0), i32 %%bad.%(i)d) + %%length.%(i)d = call i32 @strlen(i8* %%str.ptr) + %%size.%(i)d = add i32 %%length.%(i)d, 1 + call i32 @write(i32 2, i8* %%str.ptr, i32 %%size.%(i)d) + call void @llvm.trap() + unreachable +""" % dict(subst, i=i, next_i=i + 1, r=r) + + print """ +test.%d: + ret i32 0 +} + +declare i32 @strlen(i8*) +declare i32 @write(i32, i8*, i32) +declare i32 @sprintf(i8*, i8*, ...) +declare void @llvm.trap() noreturn nounwind +""" % (len(result),) + +if __name__ == '__main__': + main() diff --git a/utils/valgrind/x86_64-pc-linux-gnu.supp b/utils/valgrind/x86_64-pc-linux-gnu.supp index c8e5cd0..d6af2dd 100644 --- a/utils/valgrind/x86_64-pc-linux-gnu.supp +++ b/utils/valgrind/x86_64-pc-linux-gnu.supp @@ -33,6 +33,14 @@ } { + We don't care if bash leaks + Memcheck:Leak + fun:malloc + fun:xmalloc + obj:/bin/bash +} + +{ We don't care of cmp Memcheck:Cond obj:/usr/bin/cmp @@ -52,6 +60,14 @@ } { + We don't care if sed leaks + Memcheck:Leak + fun:calloc + fun:malloc + obj:/bin/sed +} + +{ We don't care about anything ld.so does. Memcheck:Cond obj:/lib/ld*.so diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim index 2b91823..e8273dd 100644 --- a/utils/vim/llvm.vim +++ b/utils/vim/llvm.vim @@ -57,6 +57,7 @@ syn keyword llvmKeyword tail target thread_local to triple unnamed_addr syn keyword llvmKeyword unordered uwtable volatile weak weak_odr syn keyword llvmKeyword x86_fastcallcc x86_stdcallcc x86_thiscallcc x86_64_sysvcc syn keyword llvmKeyword x86_64_win64cc zeroext +syn keyword llvmKeyword uselistorder uselistorder_bb " Obsolete keywords. syn keyword llvmError getresult begin end diff --git a/utils/yaml-bench/YAMLBench.cpp b/utils/yaml-bench/YAMLBench.cpp index e88ce5d..8bd1ea1 100644 --- a/utils/yaml-bench/YAMLBench.cpp +++ b/utils/yaml-bench/YAMLBench.cpp @@ -192,15 +192,15 @@ int main(int argc, char **argv) { MemoryBuffer::getFileOrSTDIN(Input); if (!BufOrErr) return 1; - std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get()); + MemoryBuffer &Buf = *BufOrErr.get(); llvm::SourceMgr sm; if (DumpTokens) { - yaml::dumpTokens(Buf->getBuffer(), outs()); + yaml::dumpTokens(Buf.getBuffer(), outs()); } if (DumpCanonical) { - yaml::Stream stream(Buf->getBuffer(), sm); + yaml::Stream stream(Buf.getBuffer(), sm); dumpStream(stream); } } |