summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/FileCheck/FileCheck.cpp66
-rw-r--r--utils/KillTheDoctor/KillTheDoctor.cpp1
-rw-r--r--utils/Makefile2
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp53
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp33
-rw-r--r--utils/TableGen/AsmWriterInst.cpp11
-rw-r--r--utils/TableGen/AsmWriterInst.h10
-rw-r--r--utils/TableGen/CallingConvEmitter.cpp11
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp2
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp518
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h16
-rw-r--r--utils/TableGen/CodeGenIntrinsics.h3
-rw-r--r--utils/TableGen/CodeGenMapTable.cpp6
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp202
-rw-r--r--utils/TableGen/CodeGenRegisters.h73
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp4
-rw-r--r--utils/TableGen/CodeGenTarget.cpp11
-rw-r--r--utils/TableGen/DAGISelMatcher.h6
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp4
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp8
-rw-r--r--utils/TableGen/DFAPacketizerEmitter.cpp2
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp28
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp34
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp36
-rw-r--r--utils/TableGen/PseudoLoweringEmitter.cpp4
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp63
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp93
-rw-r--r--utils/TableGen/X86DisassemblerShared.h2
-rw-r--r--utils/TableGen/X86DisassemblerTables.cpp59
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp131
-rw-r--r--utils/create_ladder_graph.py43
-rw-r--r--utils/emacs/emacs.el24
-rw-r--r--utils/emacs/llvm-mode.el35
-rwxr-xr-xutils/git-svn/git-svnrevert7
-rw-r--r--utils/lit/lit/LitConfig.py2
-rw-r--r--utils/lit/lit/Test.py3
-rw-r--r--utils/lit/lit/TestRunner.py52
-rw-r--r--utils/lit/lit/formats/googletest.py20
-rwxr-xr-xutils/lit/lit/main.py2
-rwxr-xr-xutils/lit/utils/check-coverage2
-rw-r--r--utils/lldbDataFormatters.py10
-rwxr-xr-xutils/release/export.sh5
-rwxr-xr-xutils/release/test-release.sh127
-rwxr-xr-xutils/shuffle_fuzz.py5
-rwxr-xr-xutils/sort_includes.py20
-rw-r--r--utils/unittest/CMakeLists.txt17
-rw-r--r--utils/unittest/UnitTestMain/TestMain.cpp2
-rw-r--r--utils/unittest/googletest/include/gtest/gtest-spi.h5
-rw-r--r--utils/unittest/googletest/include/gtest/gtest-test-part.h4
-rw-r--r--utils/unittest/googletest/include/gtest/gtest.h33
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h4
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-internal.h2
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h3
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-param-util.h28
-rw-r--r--utils/unittest/googletest/include/gtest/internal/gtest-port.h6
-rw-r--r--utils/unittest/googletest/src/gtest-death-test.cc13
-rw-r--r--utils/unittest/googletest/src/gtest-internal-inl.h8
-rw-r--r--utils/unittest/googletest/src/gtest.cc78
-rwxr-xr-xutils/update_llc_test_checks.py8
-rw-r--r--utils/vim/README33
-rw-r--r--utils/vim/ftdetect/llvm-lit.vim1
-rw-r--r--utils/vim/ftdetect/llvm.vim1
-rw-r--r--utils/vim/ftdetect/tablegen.vim1
-rw-r--r--utils/vim/ftplugin/llvm.vim11
-rw-r--r--utils/vim/ftplugin/tablegen.vim12
-rw-r--r--utils/vim/indent/llvm.vim72
-rw-r--r--utils/vim/syntax/llvm.vim (renamed from utils/vim/llvm.vim)8
-rw-r--r--utils/vim/syntax/tablegen.vim (renamed from utils/vim/tablegen.vim)2
-rw-r--r--utils/yaml-bench/YAMLBench.cpp18
69 files changed, 1264 insertions, 955 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp
index 59affa1ada1ba..8fe2f88a3e70e 100644
--- a/utils/FileCheck/FileCheck.cpp
+++ b/utils/FileCheck/FileCheck.cpp
@@ -73,6 +73,7 @@ namespace Check {
CheckNone = 0,
CheckPlain,
CheckNext,
+ CheckSame,
CheckNot,
CheckDAG,
CheckLabel,
@@ -620,6 +621,9 @@ struct CheckString {
/// CheckNext - Verify there is a single line in the given buffer.
bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
+ /// CheckSame - Verify there is no newline in the given buffer.
+ bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
+
/// CheckNot - Verify there's no "not strings" in the given buffer.
bool CheckNot(const SourceMgr &SM, StringRef Buffer,
const std::vector<const Pattern *> &NotStrings,
@@ -683,6 +687,9 @@ static size_t CheckTypeSize(Check::CheckType Ty) {
case Check::CheckNext:
return sizeof("-NEXT:") - 1;
+ case Check::CheckSame:
+ return sizeof("-SAME:") - 1;
+
case Check::CheckNot:
return sizeof("-NOT:") - 1;
@@ -713,6 +720,9 @@ static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
if (Rest.startswith("NEXT:"))
return Check::CheckNext;
+ if (Rest.startswith("SAME:"))
+ return Check::CheckSame;
+
if (Rest.startswith("NOT:"))
return Check::CheckNot;
@@ -919,10 +929,12 @@ static bool ReadCheckFile(SourceMgr &SM,
Buffer = Buffer.substr(EOL);
// Verify that CHECK-NEXT lines have at least one CHECK line before them.
- if ((CheckTy == Check::CheckNext) && CheckStrings.empty()) {
+ if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) &&
+ CheckStrings.empty()) {
+ StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME";
SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
SourceMgr::DK_Error,
- "found '" + UsedPrefix + "-NEXT:' without previous '"
+ "found '" + UsedPrefix + "-" + Type + "' without previous '"
+ UsedPrefix + ": line");
return true;
}
@@ -946,7 +958,7 @@ static bool ReadCheckFile(SourceMgr &SM,
// prefix as a filler for the error message.
if (!DagNotMatches.empty()) {
CheckStrings.push_back(CheckString(Pattern(Check::CheckEOF),
- CheckPrefixes[0],
+ *CheckPrefixes.begin(),
SMLoc::getFromPointer(Buffer.data()),
Check::CheckEOF));
std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
@@ -955,12 +967,14 @@ static bool ReadCheckFile(SourceMgr &SM,
if (CheckStrings.empty()) {
errs() << "error: no check strings found with prefix"
<< (CheckPrefixes.size() > 1 ? "es " : " ");
- for (size_t I = 0, N = CheckPrefixes.size(); I != N; ++I) {
- StringRef Prefix(CheckPrefixes[I]);
- errs() << '\'' << Prefix << ":'";
- if (I != N - 1)
- errs() << ", ";
+ prefix_iterator I = CheckPrefixes.begin();
+ prefix_iterator E = CheckPrefixes.end();
+ if (I != E) {
+ errs() << "\'" << *I << ":'";
+ ++I;
}
+ for (; I != E; ++I)
+ errs() << ", \'" << *I << ":'";
errs() << '\n';
return true;
@@ -1041,7 +1055,6 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
return StringRef::npos;
}
- MatchPos += LastPos;
// Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
// or CHECK-NOT
@@ -1053,13 +1066,18 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
if (CheckNext(SM, SkippedRegion))
return StringRef::npos;
+ // If this check is a "CHECK-SAME", verify that the previous match was on
+ // the same line (i.e. that there is no newline between them).
+ if (CheckSame(SM, SkippedRegion))
+ return StringRef::npos;
+
// If this match had "not strings", verify that they don't exist in the
// skipped region.
if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
return StringRef::npos;
}
- return MatchPos;
+ return LastPos + MatchPos;
}
bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
@@ -1101,6 +1119,34 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
return false;
}
+bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
+ if (CheckTy != Check::CheckSame)
+ return false;
+
+ // Count the number of newlines between the previous match and this one.
+ assert(Buffer.data() !=
+ SM.getMemoryBuffer(SM.FindBufferContainingLoc(
+ SMLoc::getFromPointer(Buffer.data())))
+ ->getBufferStart() &&
+ "CHECK-SAME can't be the first check in a file");
+
+ const char *FirstNewLine = nullptr;
+ unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
+
+ if (NumNewLines != 0) {
+ SM.PrintMessage(Loc, SourceMgr::DK_Error,
+ Prefix +
+ "-SAME: is not on the same line as the previous match");
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
+ "'next' match was here");
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
+ "previous match ended here");
+ return true;
+ }
+
+ return false;
+}
+
bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
const std::vector<const Pattern *> &NotStrings,
StringMap<StringRef> &VariableTable) const {
diff --git a/utils/KillTheDoctor/KillTheDoctor.cpp b/utils/KillTheDoctor/KillTheDoctor.cpp
index 111bad209584f..fae3b1a8b9d84 100644
--- a/utils/KillTheDoctor/KillTheDoctor.cpp
+++ b/utils/KillTheDoctor/KillTheDoctor.cpp
@@ -38,6 +38,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/WindowsError.h"
diff --git a/utils/Makefile b/utils/Makefile
index 04261923e1b5f..a59318de4834e 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -9,7 +9,7 @@
LEVEL = ..
PARALLEL_DIRS := FileCheck TableGen PerfectShuffle count fpcmp llvm-lit not \
- unittest
+ unittest yaml-bench
EXTRA_DIST := check-each-file codegen-diff countloc.sh \
DSAclean.py DSAextract.py emacs findsym.pl GenLibDeps.pl \
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 5ee20dda02616..d8f261939540f 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -264,6 +264,11 @@ public:
}
/// operator< - Compare two classes.
+ // FIXME: This ordering seems to be broken. For example:
+ // u64 < i64, i64 < s8, s8 < u64, forming a cycle
+ // u64 is a subset of i64
+ // i64 and s8 are not subsets of each other, so are ordered by name
+ // s8 and u64 are not subsets of each other, so are ordered by name
bool operator<(const ClassInfo &RHS) const {
if (this == &RHS)
return false;
@@ -433,12 +438,21 @@ struct MatchableInfo {
/// If this instruction is deprecated in some form.
bool HasDeprecation;
+ /// If this is an alias, this is use to determine whether or not to using
+ /// the conversion function defined by the instruction's AsmMatchConverter
+ /// or to use the function generated by the alias.
+ bool UseInstAsmMatchConverter;
+
MatchableInfo(const CodeGenInstruction &CGI)
- : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI) {
+ : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI),
+ UseInstAsmMatchConverter(true) {
}
MatchableInfo(std::unique_ptr<const CodeGenInstAlias> Alias)
- : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), DefRec(Alias.release()) {
+ : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef),
+ DefRec(Alias.release()),
+ UseInstAsmMatchConverter(
+ TheDef->getValueAsBit("UseInstAsmMatchConverter")) {
}
~MatchableInfo() {
@@ -979,6 +993,7 @@ static std::string getEnumNameForToken(StringRef Str) {
case '.': Res += "_DOT_"; break;
case '<': Res += "_LT_"; break;
case '>': Res += "_GT_"; break;
+ case '-': Res += "_MINUS_"; break;
default:
if ((*it >= 'A' && *it <= 'Z') ||
(*it >= 'a' && *it <= 'z') ||
@@ -1446,8 +1461,9 @@ void AsmMatcherInfo::buildInfo() {
II->buildAliasResultOperands();
}
if (!NewMatchables.empty())
- std::move(NewMatchables.begin(), NewMatchables.end(),
- std::back_inserter(Matchables));
+ Matchables.insert(Matchables.end(),
+ std::make_move_iterator(NewMatchables.begin()),
+ std::make_move_iterator(NewMatchables.end()));
// Process token alias definitions and set up the associated superclass
// information.
@@ -1742,7 +1758,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Check if we have a custom match function.
std::string AsmMatchConverter =
II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter");
- if (!AsmMatchConverter.empty()) {
+ if (!AsmMatchConverter.empty() && II->UseInstAsmMatchConverter) {
std::string Signature = "ConvertCustom_" + AsmMatchConverter;
II->ConversionFnKind = Signature;
@@ -1848,6 +1864,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
case MatchableInfo::ResOperand::ImmOperand: {
int64_t Val = OpInfo.ImmVal;
std::string Ty = "imm_" + itostr(Val);
+ Ty = getEnumNameForToken(Ty);
Signature += "__" + Ty;
std::string Name = "CVT_" + Ty;
@@ -1862,7 +1879,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
break;
CvtOS << " case " << Name << ":\n"
- << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n"
+ << " Inst.addOperand(MCOperand::createImm(" << Val << "));\n"
<< " break;\n";
OpOS << " case " << Name << ":\n"
@@ -1893,7 +1910,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
if (!IsNewConverter)
break;
CvtOS << " case " << Name << ":\n"
- << " Inst.addOperand(MCOperand::CreateReg(" << Reg << "));\n"
+ << " Inst.addOperand(MCOperand::createReg(" << Reg << "));\n"
<< " break;\n";
OpOS << " case " << Name << ":\n"
@@ -2240,7 +2257,7 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
Info.AsmParser->getValueAsString("AsmParserClassName");
OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n"
- << "ComputeAvailableFeatures(uint64_t FB) const {\n";
+ << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n";
OS << " uint64_t Features = 0;\n";
for (const auto &SF : Info.SubtargetFeatures) {
const SubtargetFeatureInfo &SFI = SF.second;
@@ -2262,12 +2279,10 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
Cond = Cond.substr(1);
}
- OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")";
+ OS << "(";
if (Neg)
- OS << " == 0";
- else
- OS << " != 0";
- OS << ")";
+ OS << "!";
+ OS << "FB[" << Info.Target.getName() << "::" << Cond << "])";
if (Comma.second.empty())
break;
@@ -2637,7 +2652,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "#undef GET_ASSEMBLER_HEADER\n";
OS << " // This should be included into the middle of the declaration of\n";
OS << " // your subclasses implementation of MCTargetAsmParser.\n";
- OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
+ OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n";
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const OperandVector "
@@ -2651,7 +2666,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< " bool matchingInlineAsm,\n"
<< " unsigned VariantID = 0);\n";
- if (Info.OperandMatchInfo.size()) {
+ if (!Info.OperandMatchInfo.empty()) {
OS << "\n enum OperandMatchResultTy {\n";
OS << " MatchOperand_Success, // operand matched successfully\n";
OS << " MatchOperand_NoMatch, // operand did not match\n";
@@ -2879,7 +2894,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " uint64_t MissingFeatures = ~0ULL;\n";
OS << " // Set ErrorInfo to the operand that mismatches if it is\n";
OS << " // wrong for all instances of the instruction.\n";
- OS << " ErrorInfo = ~0U;\n";
+ OS << " ErrorInfo = ~0ULL;\n";
// Emit code to search the table.
OS << " // Find the appropriate table for this asm variant.\n";
@@ -2954,8 +2969,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " HadMatchOtherThanFeatures = true;\n";
OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & "
"~AvailableFeatures;\n";
- OS << " if (CountPopulation_64(NewMissingFeatures) <=\n"
- " CountPopulation_64(MissingFeatures))\n";
+ OS << " if (countPopulation(NewMissingFeatures) <=\n"
+ " countPopulation(MissingFeatures))\n";
OS << " MissingFeatures = NewMissingFeatures;\n";
OS << " continue;\n";
OS << " }\n";
@@ -3009,7 +3024,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " return Match_MissingFeature;\n";
OS << "}\n\n";
- if (Info.OperandMatchInfo.size())
+ if (!Info.OperandMatchInfo.empty())
emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable,
MaxMnemonicIndex);
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index 5924d5f48dc46..389889ab80f0a 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -278,12 +278,15 @@ static void UnescapeString(std::string &Str) {
void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
Record *AsmWriter = Target.getAsmWriter();
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+ unsigned PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
O <<
"/// printInstruction - This method is automatically generated by tablegen\n"
"/// from the instruction set description.\n"
"void " << Target.getName() << ClassName
- << "::printInstruction(const MCInst *MI, raw_ostream &O) {\n";
+ << "::printInstruction(const MCInst *MI, "
+ << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
+ << "raw_ostream &O) {\n";
// Build an aggregate string, and build a table of offsets into it.
SequenceToOffsetTable<std::string> StringTable;
@@ -727,7 +730,7 @@ public:
OS.flush();
// Emit the string.
- O.indent(6) << "AsmString = \"" << OutString.str() << "\";\n";
+ O.indent(6) << "AsmString = \"" << OutString << "\";\n";
O.indent(6) << "break;\n";
O.indent(4) << '}';
@@ -787,6 +790,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
// Emit the method that prints the alias instruction.
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
unsigned Variant = AsmWriter->getValueAsInt("Variant");
+ unsigned PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
std::vector<Record*> AllInstAliases =
Records.getAllDerivedDefinitions("InstAlias");
@@ -949,7 +953,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
HeaderO << "bool " << Target.getName() << ClassName
<< "::printAliasInstr(const MCInst"
- << " *MI, raw_ostream &OS) {\n";
+ << " *MI, " << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
+ << "raw_ostream &OS) {\n";
std::string Cases;
raw_string_ostream CasesO(Cases);
@@ -998,7 +1003,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
return;
}
- if (MCOpPredicates.size())
+ if (!MCOpPredicates.empty())
O << "static bool " << Target.getName() << ClassName
<< "ValidateMCOperand(\n"
<< " const MCOperand &MCOp, unsigned PredicateIndex);\n";
@@ -1027,9 +1032,13 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << " ++I;\n";
O << " int OpIdx = AsmString[I++] - 1;\n";
O << " int PrintMethodIdx = AsmString[I++] - 1;\n";
- O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, OS);\n";
+ O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, ";
+ O << (PassSubtarget ? "STI, " : "");
+ O << "OS);\n";
O << " } else\n";
- O << " printOperand(MI, unsigned(AsmString[I++]) - 1, OS);\n";
+ O << " printOperand(MI, unsigned(AsmString[I++]) - 1, ";
+ O << (PassSubtarget ? "STI, " : "");
+ O << "OS);\n";
O << " } else {\n";
O << " OS << AsmString[I++];\n";
O << " }\n";
@@ -1046,7 +1055,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << "void " << Target.getName() << ClassName << "::"
<< "printCustomAliasOperand(\n"
<< " const MCInst *MI, unsigned OpIdx,\n"
- << " unsigned PrintMethodIdx, raw_ostream &OS) {\n";
+ << " unsigned PrintMethodIdx,\n"
+ << (PassSubtarget ? " const MCSubtargetInfo &STI,\n" : "")
+ << " raw_ostream &OS) {\n";
if (PrintMethods.empty())
O << " llvm_unreachable(\"Unknown PrintMethod kind\");\n";
else {
@@ -1057,14 +1068,15 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
for (unsigned i = 0; i < PrintMethods.size(); ++i) {
O << " case " << i << ":\n"
- << " " << PrintMethods[i] << "(MI, OpIdx, OS);\n"
+ << " " << PrintMethods[i] << "(MI, OpIdx, "
+ << (PassSubtarget ? "STI, " : "") << "OS);\n"
<< " break;\n";
}
O << " }\n";
}
O << "}\n\n";
- if (MCOpPredicates.size()) {
+ if (!MCOpPredicates.empty()) {
O << "static bool " << Target.getName() << ClassName
<< "ValidateMCOperand(\n"
<< " const MCOperand &MCOp, unsigned PredicateIndex) {\n"
@@ -1094,7 +1106,8 @@ AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) {
for (const CodeGenInstruction *I : Target.instructions())
if (!I->AsmString.empty() && I->TheDef->getName() != "PHI")
Instructions.push_back(
- AsmWriterInst(*I, AsmWriter->getValueAsInt("Variant")));
+ AsmWriterInst(*I, AsmWriter->getValueAsInt("Variant"),
+ AsmWriter->getValueAsInt("PassSubtarget")));
// Get the instruction numbering.
NumberedInstructions = &Target.getInstructionsByEnumValue();
diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp
index 6ddc510473ed5..a66b1a01cae45 100644
--- a/utils/TableGen/AsmWriterInst.cpp
+++ b/utils/TableGen/AsmWriterInst.cpp
@@ -39,6 +39,8 @@ std::string AsmWriterOperand::getCode() const {
std::string Result = Str + "(MI";
if (MIOpNo != ~0U)
Result += ", " + utostr(MIOpNo);
+ if (PassSubtarget)
+ Result += ", STI";
Result += ", O";
if (!MiModifier.empty())
Result += ", \"" + MiModifier + '"';
@@ -48,7 +50,8 @@ std::string AsmWriterOperand::getCode() const {
/// ParseAsmString - Parse the specified Instruction's AsmString into this
/// AsmWriterInst.
///
-AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
+AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant,
+ unsigned PassSubtarget) {
this->CGI = &CGI;
// NOTE: Any extensions to this code need to be mirrored in the
@@ -163,7 +166,8 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
Operands.push_back(AsmWriterOperand("PrintSpecial",
~0U,
~0U,
- Modifier));
+ Modifier,
+ PassSubtarget));
} else {
// Otherwise, normal operand.
unsigned OpNo = CGI.Operands.getOperandNamed(VarName);
@@ -171,7 +175,8 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
unsigned MIOp = OpInfo.MIOperandNo;
Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName,
- OpNo, MIOp, Modifier));
+ OpNo, MIOp, Modifier,
+ PassSubtarget));
}
LastEmitted = VarEnd;
}
diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h
index 6a900b7997011..a597e6ba1a558 100644
--- a/utils/TableGen/AsmWriterInst.h
+++ b/utils/TableGen/AsmWriterInst.h
@@ -53,6 +53,11 @@ namespace llvm {
/// an operand, specified with syntax like ${opname:modifier}.
std::string MiModifier;
+ // PassSubtarget - Pass MCSubtargetInfo to the print method if this is
+ // equal to 1.
+ // FIXME: Remove after all ports are updated.
+ unsigned PassSubtarget;
+
// To make VS STL happy
AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
@@ -64,9 +69,10 @@ namespace llvm {
unsigned _CGIOpNo,
unsigned _MIOpNo,
const std::string &Modifier,
+ unsigned PassSubtarget,
OpType op = isMachineInstrOperand)
: OperandType(op), Str(Printer), CGIOpNo(_CGIOpNo), MIOpNo(_MIOpNo),
- MiModifier(Modifier) {}
+ MiModifier(Modifier), PassSubtarget(PassSubtarget) {}
bool operator!=(const AsmWriterOperand &Other) const {
if (OperandType != Other.OperandType || Str != Other.Str) return true;
@@ -88,7 +94,7 @@ namespace llvm {
const CodeGenInstruction *CGI;
AsmWriterInst(const CodeGenInstruction &CGI,
- unsigned Variant);
+ unsigned Variant, unsigned PassSubtarget);
/// MatchesAllButOneOp - If this instruction is exactly identical to the
/// specified instruction except for one differing operand, return the
diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp
index 6a65e5e97821b..051a7e9814140 100644
--- a/utils/TableGen/CallingConvEmitter.cpp
+++ b/utils/TableGen/CallingConvEmitter.cpp
@@ -124,7 +124,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
}
O << "\n" << IndentStr << "};\n";
O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
- << Counter << ", " << RegList->getSize() << ")) {\n";
+ << Counter << ")) {\n";
}
O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
<< "Reg, LocVT, LocInfo));\n";
@@ -166,7 +166,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
<< RegListNumber << ", " << "RegList" << ShadowRegListNumber
- << ", " << RegList->getSize() << ")) {\n";
+ << ")) {\n";
}
O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
<< "Reg, LocVT, LocInfo));\n";
@@ -182,14 +182,14 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << Size << ", ";
else
O << "\n" << IndentStr
- << " State.getMachineFunction().getSubtarget().getDataLayout()"
+ << " State.getMachineFunction().getTarget().getDataLayout()"
"->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
" ";
if (Align)
O << Align;
else
O << "\n" << IndentStr
- << " State.getMachineFunction().getSubtarget().getDataLayout()"
+ << " State.getMachineFunction().getTarget().getDataLayout()"
"->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()"
"))";
O << ");\n" << IndentStr
@@ -215,8 +215,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << IndentStr << "unsigned Offset" << ++Counter
<< " = State.AllocateStack("
<< Size << ", " << Align << ", "
- << "ShadowRegList" << ShadowRegListNumber << ", "
- << ShadowRegList->getSize() << ");\n";
+ << "ShadowRegList" << ShadowRegListNumber << ");\n";
O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
<< Counter << ", LocVT, LocInfo));\n";
O << IndentStr << "return false;\n";
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 11911b63b7bd5..46fcdf5e96ffd 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -96,7 +96,7 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
/// generated emitter, skip it.
while (NumberedOp < NumberOps &&
(CGI.Operands.isFlatOperandNotEmitted(NumberedOp) ||
- (NamedOpIndices.size() && NamedOpIndices.count(
+ (!NamedOpIndices.empty() && NamedOpIndices.count(
CGI.Operands.getSubOperandNumber(NumberedOp).first)))) {
++NumberedOp;
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index c3de37e94533d..fd02bbdc6b488 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -53,7 +53,7 @@ EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) {
EnforceVector(TP);
else {
assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR ||
- VT == MVT::iPTRAny) && "Not a concrete type!");
+ VT == MVT::iPTRAny || VT == MVT::Any) && "Not a concrete type!");
TypeVec.push_back(VT);
}
}
@@ -389,52 +389,6 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
else if (!Other.hasScalarTypes())
MadeChange |= EnforceVector(TP);
- // For vectors we need to ensure that smaller size doesn't produce larger
- // vector and vice versa.
- if (isConcrete() && isVector(getConcrete())) {
- MVT IVT = getConcrete();
- unsigned Size = IVT.getSizeInBits();
-
- // Only keep types that have at least as many bits.
- TypeSet InputSet(Other);
-
- for (unsigned i = 0; i != Other.TypeVec.size(); ++i) {
- assert(isVector(Other.TypeVec[i]) && "EnforceVector didn't work");
- if (MVT(Other.TypeVec[i]).getSizeInBits() < Size) {
- Other.TypeVec.erase(Other.TypeVec.begin()+i--);
- MadeChange = true;
- }
- }
-
- if (Other.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
- TP.error("Type inference contradiction found, forcing '" +
- InputSet.getName() + "' to have at least as many bits as " +
- getName() + "'");
- return false;
- }
- } else if (Other.isConcrete() && isVector(Other.getConcrete())) {
- MVT IVT = Other.getConcrete();
- unsigned Size = IVT.getSizeInBits();
-
- // Only keep types with the same or fewer total bits
- TypeSet InputSet(*this);
-
- for (unsigned i = 0; i != TypeVec.size(); ++i) {
- assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
- if (MVT(TypeVec[i]).getSizeInBits() > Size) {
- TypeVec.erase(TypeVec.begin()+i--);
- MadeChange = true;
- }
- }
-
- if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
- TP.error("Type inference contradiction found, forcing '" +
- InputSet.getName() + "' to have the same or fewer bits than " +
- Other.getName() + "'");
- return false;
- }
- }
-
// This code does not currently handle nodes which have multiple types,
// where some types are integer, and some are fp. Assert that this is not
// the case.
@@ -445,12 +399,22 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
if (TP.hasError())
return false;
- // Okay, find the smallest scalar type from the other set and remove
- // anything the same or smaller from the current set.
+ // Okay, find the smallest type from current set and remove anything the
+ // same or smaller from the other set. We need to ensure that the scalar
+ // type size is smaller than the scalar size of the smallest type. For
+ // vectors, we also need to make sure that the total size is no larger than
+ // the size of the smallest type.
TypeSet InputSet(Other);
- MVT::SimpleValueType Smallest = TypeVec[0];
+ MVT Smallest = TypeVec[0];
for (unsigned i = 0; i != Other.TypeVec.size(); ++i) {
- if (Other.TypeVec[i] <= Smallest) {
+ MVT OtherVT = Other.TypeVec[i];
+ // Don't compare vector and non-vector types.
+ if (OtherVT.isVector() != Smallest.isVector())
+ continue;
+ // The getSizeInBits() check here is only needed for vectors, but is
+ // a subset of the scalar check for scalars so no need to qualify.
+ if (OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits() ||
+ OtherVT.getSizeInBits() < Smallest.getSizeInBits()) {
Other.TypeVec.erase(Other.TypeVec.begin()+i--);
MadeChange = true;
}
@@ -462,12 +426,22 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
return false;
}
- // Okay, find the largest scalar type from the other set and remove
- // anything the same or larger from the current set.
+ // Okay, find the largest type from the other set and remove anything the
+ // same or smaller from the current set. We need to ensure that the scalar
+ // type size is larger than the scalar size of the largest type. For
+ // vectors, we also need to make sure that the total size is no smaller than
+ // the size of the largest type.
InputSet = TypeSet(*this);
- MVT::SimpleValueType Largest = Other.TypeVec[Other.TypeVec.size()-1];
+ MVT Largest = Other.TypeVec[Other.TypeVec.size()-1];
for (unsigned i = 0; i != TypeVec.size(); ++i) {
- if (TypeVec[i] >= Largest) {
+ MVT OtherVT = TypeVec[i];
+ // Don't compare vector and non-vector types.
+ if (OtherVT.isVector() != Largest.isVector())
+ continue;
+ // The getSizeInBits() check here is only needed for vectors, but is
+ // a subset of the scalar check for scalars so no need to qualify.
+ if (OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() ||
+ OtherVT.getSizeInBits() > Largest.getSizeInBits()) {
TypeVec.erase(TypeVec.begin()+i--);
MadeChange = true;
}
@@ -484,6 +458,34 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
/// whose element is specified by VTOperand.
+bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT,
+ TreePattern &TP) {
+ bool MadeChange = false;
+
+ MadeChange |= EnforceVector(TP);
+
+ TypeSet InputSet(*this);
+
+ // Filter out all the types which don't have the right element type.
+ for (unsigned i = 0; i != TypeVec.size(); ++i) {
+ assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
+ if (MVT(TypeVec[i]).getVectorElementType().SimpleTy != VT) {
+ TypeVec.erase(TypeVec.begin()+i--);
+ MadeChange = true;
+ }
+ }
+
+ if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have a vector element");
+ return false;
+ }
+
+ return MadeChange;
+}
+
+/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
+/// whose element is specified by VTOperand.
bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
TreePattern &TP) {
if (TP.hasError())
@@ -609,6 +611,64 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
return MadeChange;
}
+/// EnforceVectorSameNumElts - 'this' is now constrainted to
+/// be a vector with same num elements as VTOperand.
+bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand,
+ TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
+ // "This" must be a vector and "VTOperand" must be a vector.
+ bool MadeChange = false;
+ MadeChange |= EnforceVector(TP);
+ MadeChange |= VTOperand.EnforceVector(TP);
+
+ // If we know one of the vector types, it forces the other type to agree.
+ if (isConcrete()) {
+ MVT IVT = getConcrete();
+ unsigned NumElems = IVT.getVectorNumElements();
+
+ // Only keep types that have same elements as VTOperand.
+ TypeSet InputSet(VTOperand);
+
+ for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) {
+ assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work");
+ if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() != NumElems) {
+ VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--);
+ MadeChange = true;
+ }
+ }
+ if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have same number elements as '" +
+ getName() + "'");
+ return false;
+ }
+ } else if (VTOperand.isConcrete()) {
+ MVT IVT = VTOperand.getConcrete();
+ unsigned NumElems = IVT.getVectorNumElements();
+
+ // Only keep types that have same elements as 'this'.
+ TypeSet InputSet(*this);
+
+ for (unsigned i = 0; i != TypeVec.size(); ++i) {
+ assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
+ if (MVT(TypeVec[i]).getVectorNumElements() != NumElems) {
+ TypeVec.erase(TypeVec.begin()+i--);
+ MadeChange = true;
+ }
+ }
+ if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have same number elements than '" +
+ VTOperand.getName() + "'");
+ return false;
+ }
+ }
+
+ return MadeChange;
+}
+
//===----------------------------------------------------------------------===//
// Helpers for working with extended types.
@@ -839,9 +899,21 @@ SDTypeConstraint::SDTypeConstraint(Record *R) {
ConstraintType = SDTCisSubVecOfVec;
x.SDTCisSubVecOfVec_Info.OtherOperandNum =
R->getValueAsInt("OtherOpNum");
+ } else if (R->isSubClassOf("SDTCVecEltisVT")) {
+ ConstraintType = SDTCVecEltisVT;
+ x.SDTCVecEltisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
+ if (MVT(x.SDTCVecEltisVT_Info.VT).isVector())
+ PrintFatalError(R->getLoc(), "Cannot use vector type as SDTCVecEltisVT");
+ if (!MVT(x.SDTCVecEltisVT_Info.VT).isInteger() &&
+ !MVT(x.SDTCVecEltisVT_Info.VT).isFloatingPoint())
+ PrintFatalError(R->getLoc(), "Must use integer or floating point type "
+ "as SDTCVecEltisVT");
+ } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) {
+ ConstraintType = SDTCisSameNumEltsAs;
+ x.SDTCisSameNumEltsAs_Info.OtherOperandNum =
+ R->getValueAsInt("OtherOperandNum");
} else {
- errs() << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n";
- exit(1);
+ PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
}
}
@@ -859,11 +931,12 @@ static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N,
OpNo -= NumResults;
if (OpNo >= N->getNumChildren()) {
- errs() << "Invalid operand number in type constraint "
+ std::string S;
+ raw_string_ostream OS(S);
+ OS << "Invalid operand number in type constraint "
<< (OpNo+NumResults) << " ";
- N->dump();
- errs() << '\n';
- exit(1);
+ N->print(OS);
+ PrintFatalError(OS.str());
}
return N->getChild(OpNo);
@@ -901,8 +974,8 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
unsigned OResNo = 0;
TreePatternNode *OtherNode =
getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo);
- return NodeToApply->UpdateNodeType(OResNo, OtherNode->getExtType(ResNo),TP)|
- OtherNode->UpdateNodeType(ResNo,NodeToApply->getExtType(OResNo),TP);
+ return NodeToApply->UpdateNodeType(ResNo, OtherNode->getExtType(OResNo),TP)|
+ OtherNode->UpdateNodeType(OResNo,NodeToApply->getExtType(ResNo),TP);
}
case SDTCisVTSmallerThanOp: {
// The NodeToApply must be a leaf node that is a VT. OtherOperandNum must
@@ -956,6 +1029,18 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
return BigVecOperand->getExtType(VResNo).
EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP);
}
+ case SDTCVecEltisVT: {
+ return NodeToApply->getExtType(ResNo).
+ EnforceVectorEltTypeIs(x.SDTCVecEltisVT_Info.VT, TP);
+ }
+ case SDTCisSameNumEltsAs: {
+ unsigned OResNo = 0;
+ TreePatternNode *OtherNode =
+ getOperandNum(x.SDTCisSameNumEltsAs_Info.OtherOperandNum,
+ N, NodeInfo, OResNo);
+ return OtherNode->getExtType(OResNo).
+ EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP);
+ }
}
llvm_unreachable("Invalid ConstraintType!");
}
@@ -1031,9 +1116,9 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
} else if (PropList[i]->getName() == "SDNPVariadic") {
Properties |= 1 << SDNPVariadic;
} else {
- errs() << "Unknown SD Node property '" << PropList[i]->getName()
- << "' on node '" << R->getName() << "'!\n";
- exit(1);
+ PrintFatalError("Unknown SD Node property '" +
+ PropList[i]->getName() + "' on node '" +
+ R->getName() + "'!");
}
}
@@ -1111,8 +1196,16 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
if (Operator->isSubClassOf("Instruction")) {
CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator);
- // FIXME: Should allow access to all the results here.
- unsigned NumDefsToAdd = InstInfo.Operands.NumDefs ? 1 : 0;
+ unsigned NumDefsToAdd = InstInfo.Operands.NumDefs;
+
+ // Subtract any defaulted outputs.
+ for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) {
+ Record *OperandNode = InstInfo.Operands[i].Rec;
+
+ if (OperandNode->isSubClassOf("OperandWithDefaultOps") &&
+ !CDP.getDefaultOperand(OperandNode).DefaultOps.empty())
+ --NumDefsToAdd;
+ }
// Add on one implicit def if it has a resolvable type.
if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other)
@@ -1130,8 +1223,7 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
return 1;
Operator->dump();
- errs() << "Unhandled node in GetNumNodeResults\n";
- exit(1);
+ PrintFatalError("Unhandled node in GetNumNodeResults");
}
void TreePatternNode::print(raw_ostream &OS) const {
@@ -1689,8 +1781,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
// Apply the result types to the node, these come from the things in the
// (outs) list of the instruction.
- // FIXME: Cap at one result so far.
- unsigned NumResultsToAdd = InstInfo.Operands.NumDefs ? 1 : 0;
+ unsigned NumResultsToAdd = std::min(InstInfo.Operands.NumDefs,
+ Inst.getNumResults());
for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo)
MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP);
@@ -1971,7 +2063,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
}
// ?:$name or just $name.
- if (TheInit == UnsetInit::get()) {
+ if (isa<UnsetInit>(TheInit)) {
if (OpName.empty())
error("'?' argument requires a name to match with operand list");
TreePatternNode *Res = new TreePatternNode(TheInit, 1);
@@ -2280,10 +2372,9 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const {
Record *N = Records.getDef(Name);
- if (!N || !N->isSubClassOf("SDNode")) {
- errs() << "Error getting SDNode '" << Name << "'!\n";
- exit(1);
- }
+ if (!N || !N->isSubClassOf("SDNode"))
+ PrintFatalError("Error getting SDNode '" + Name + "'!");
+
return N;
}
@@ -2811,159 +2902,161 @@ static bool checkOperandClass(CGIOperandList::OperandInfo &OI,
const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) {
- assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!");
+ assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!");
- // Parse the instruction.
- TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this);
- // Inline pattern fragments into it.
- I->InlinePatternFragments();
+ // Parse the instruction.
+ TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this);
+ // Inline pattern fragments into it.
+ I->InlinePatternFragments();
- // Infer as many types as possible. If we cannot infer all of them, we can
- // never do anything with this instruction pattern: report it to the user.
- if (!I->InferAllTypes())
- I->error("Could not infer all types in pattern!");
+ // Infer as many types as possible. If we cannot infer all of them, we can
+ // never do anything with this instruction pattern: report it to the user.
+ if (!I->InferAllTypes())
+ I->error("Could not infer all types in pattern!");
- // InstInputs - Keep track of all of the inputs of the instruction, along
- // with the record they are declared as.
- std::map<std::string, TreePatternNode*> InstInputs;
+ // InstInputs - Keep track of all of the inputs of the instruction, along
+ // with the record they are declared as.
+ std::map<std::string, TreePatternNode*> InstInputs;
- // InstResults - Keep track of all the virtual registers that are 'set'
- // in the instruction, including what reg class they are.
- std::map<std::string, TreePatternNode*> InstResults;
+ // InstResults - Keep track of all the virtual registers that are 'set'
+ // in the instruction, including what reg class they are.
+ std::map<std::string, TreePatternNode*> InstResults;
- std::vector<Record*> InstImpResults;
+ std::vector<Record*> InstImpResults;
- // Verify that the top-level forms in the instruction are of void type, and
- // fill in the InstResults map.
- for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
- TreePatternNode *Pat = I->getTree(j);
- if (Pat->getNumTypes() != 0)
- I->error("Top-level forms in instruction pattern should have"
- " void types");
+ // Verify that the top-level forms in the instruction are of void type, and
+ // fill in the InstResults map.
+ for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
+ TreePatternNode *Pat = I->getTree(j);
+ if (Pat->getNumTypes() != 0)
+ I->error("Top-level forms in instruction pattern should have"
+ " void types");
- // Find inputs and outputs, and verify the structure of the uses/defs.
- FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,
- InstImpResults);
- }
+ // Find inputs and outputs, and verify the structure of the uses/defs.
+ FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,
+ InstImpResults);
+ }
- // Now that we have inputs and outputs of the pattern, inspect the operands
- // list for the instruction. This determines the order that operands are
- // added to the machine instruction the node corresponds to.
- unsigned NumResults = InstResults.size();
+ // Now that we have inputs and outputs of the pattern, inspect the operands
+ // list for the instruction. This determines the order that operands are
+ // added to the machine instruction the node corresponds to.
+ unsigned NumResults = InstResults.size();
- // Parse the operands list from the (ops) list, validating it.
- assert(I->getArgList().empty() && "Args list should still be empty here!");
+ // Parse the operands list from the (ops) list, validating it.
+ assert(I->getArgList().empty() && "Args list should still be empty here!");
- // Check that all of the results occur first in the list.
- std::vector<Record*> Results;
- TreePatternNode *Res0Node = nullptr;
- for (unsigned i = 0; i != NumResults; ++i) {
- if (i == CGI.Operands.size())
- I->error("'" + InstResults.begin()->first +
- "' set but does not appear in operand list!");
- const std::string &OpName = CGI.Operands[i].Name;
+ // Check that all of the results occur first in the list.
+ std::vector<Record*> Results;
+ SmallVector<TreePatternNode *, 2> ResNodes;
+ for (unsigned i = 0; i != NumResults; ++i) {
+ if (i == CGI.Operands.size())
+ I->error("'" + InstResults.begin()->first +
+ "' set but does not appear in operand list!");
+ const std::string &OpName = CGI.Operands[i].Name;
- // Check that it exists in InstResults.
- TreePatternNode *RNode = InstResults[OpName];
- if (!RNode)
- I->error("Operand $" + OpName + " does not exist in operand list!");
+ // Check that it exists in InstResults.
+ TreePatternNode *RNode = InstResults[OpName];
+ if (!RNode)
+ I->error("Operand $" + OpName + " does not exist in operand list!");
- if (i == 0)
- Res0Node = RNode;
- Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();
- if (!R)
- I->error("Operand $" + OpName + " should be a set destination: all "
- "outputs must occur before inputs in operand list!");
+ ResNodes.push_back(RNode);
- if (!checkOperandClass(CGI.Operands[i], R))
- I->error("Operand $" + OpName + " class mismatch!");
+ Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();
+ if (!R)
+ I->error("Operand $" + OpName + " should be a set destination: all "
+ "outputs must occur before inputs in operand list!");
- // Remember the return type.
- Results.push_back(CGI.Operands[i].Rec);
+ if (!checkOperandClass(CGI.Operands[i], R))
+ I->error("Operand $" + OpName + " class mismatch!");
- // Okay, this one checks out.
- InstResults.erase(OpName);
- }
+ // Remember the return type.
+ Results.push_back(CGI.Operands[i].Rec);
- // Loop over the inputs next. Make a copy of InstInputs so we can destroy
- // the copy while we're checking the inputs.
- std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs);
+ // Okay, this one checks out.
+ InstResults.erase(OpName);
+ }
- std::vector<TreePatternNode*> ResultNodeOperands;
- std::vector<Record*> Operands;
- for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) {
- CGIOperandList::OperandInfo &Op = CGI.Operands[i];
- const std::string &OpName = Op.Name;
- if (OpName.empty())
- I->error("Operand #" + utostr(i) + " in operands list has no name!");
-
- if (!InstInputsCheck.count(OpName)) {
- // If this is an operand with a DefaultOps set filled in, we can ignore
- // this. When we codegen it, we will do so as always executed.
- if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) {
- // Does it have a non-empty DefaultOps field? If so, ignore this
- // operand.
- if (!getDefaultOperand(Op.Rec).DefaultOps.empty())
- continue;
- }
- I->error("Operand $" + OpName +
- " does not appear in the instruction pattern");
- }
- TreePatternNode *InVal = InstInputsCheck[OpName];
- InstInputsCheck.erase(OpName); // It occurred, remove from map.
-
- if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) {
- Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
- if (!checkOperandClass(Op, InRec))
- I->error("Operand $" + OpName + "'s register class disagrees"
- " between the operand and pattern");
+ // Loop over the inputs next. Make a copy of InstInputs so we can destroy
+ // the copy while we're checking the inputs.
+ std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs);
+
+ std::vector<TreePatternNode*> ResultNodeOperands;
+ std::vector<Record*> Operands;
+ for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) {
+ CGIOperandList::OperandInfo &Op = CGI.Operands[i];
+ const std::string &OpName = Op.Name;
+ if (OpName.empty())
+ I->error("Operand #" + utostr(i) + " in operands list has no name!");
+
+ if (!InstInputsCheck.count(OpName)) {
+ // If this is an operand with a DefaultOps set filled in, we can ignore
+ // this. When we codegen it, we will do so as always executed.
+ if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) {
+ // Does it have a non-empty DefaultOps field? If so, ignore this
+ // operand.
+ if (!getDefaultOperand(Op.Rec).DefaultOps.empty())
+ continue;
}
- Operands.push_back(Op.Rec);
+ I->error("Operand $" + OpName +
+ " does not appear in the instruction pattern");
+ }
+ TreePatternNode *InVal = InstInputsCheck[OpName];
+ InstInputsCheck.erase(OpName); // It occurred, remove from map.
- // Construct the result for the dest-pattern operand list.
- TreePatternNode *OpNode = InVal->clone();
+ if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) {
+ Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
+ if (!checkOperandClass(Op, InRec))
+ I->error("Operand $" + OpName + "'s register class disagrees"
+ " between the operand and pattern");
+ }
+ Operands.push_back(Op.Rec);
- // No predicate is useful on the result.
- OpNode->clearPredicateFns();
+ // Construct the result for the dest-pattern operand list.
+ TreePatternNode *OpNode = InVal->clone();
- // Promote the xform function to be an explicit node if set.
- if (Record *Xform = OpNode->getTransformFn()) {
- OpNode->setTransformFn(nullptr);
- std::vector<TreePatternNode*> Children;
- Children.push_back(OpNode);
- OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
- }
+ // No predicate is useful on the result.
+ OpNode->clearPredicateFns();
- ResultNodeOperands.push_back(OpNode);
+ // Promote the xform function to be an explicit node if set.
+ if (Record *Xform = OpNode->getTransformFn()) {
+ OpNode->setTransformFn(nullptr);
+ std::vector<TreePatternNode*> Children;
+ Children.push_back(OpNode);
+ OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
}
- if (!InstInputsCheck.empty())
- I->error("Input operand $" + InstInputsCheck.begin()->first +
- " occurs in pattern but not in operands list!");
+ ResultNodeOperands.push_back(OpNode);
+ }
- TreePatternNode *ResultPattern =
- new TreePatternNode(I->getRecord(), ResultNodeOperands,
- GetNumNodeResults(I->getRecord(), *this));
- // Copy fully inferred output node type to instruction result pattern.
- for (unsigned i = 0; i != NumResults; ++i)
- ResultPattern->setType(i, Res0Node->getExtType(i));
+ if (!InstInputsCheck.empty())
+ I->error("Input operand $" + InstInputsCheck.begin()->first +
+ " occurs in pattern but not in operands list!");
- // Create and insert the instruction.
- // FIXME: InstImpResults should not be part of DAGInstruction.
- DAGInstruction TheInst(I, Results, Operands, InstImpResults);
- DAGInsts.insert(std::make_pair(I->getRecord(), TheInst));
+ TreePatternNode *ResultPattern =
+ new TreePatternNode(I->getRecord(), ResultNodeOperands,
+ GetNumNodeResults(I->getRecord(), *this));
+ // Copy fully inferred output node types to instruction result pattern.
+ for (unsigned i = 0; i != NumResults; ++i) {
+ assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled");
+ ResultPattern->setType(i, ResNodes[i]->getExtType(0));
+ }
- // Use a temporary tree pattern to infer all types and make sure that the
- // constructed result is correct. This depends on the instruction already
- // being inserted into the DAGInsts map.
- TreePattern Temp(I->getRecord(), ResultPattern, false, *this);
- Temp.InferAllTypes(&I->getNamedNodesMap());
+ // Create and insert the instruction.
+ // FIXME: InstImpResults should not be part of DAGInstruction.
+ DAGInstruction TheInst(I, Results, Operands, InstImpResults);
+ DAGInsts.insert(std::make_pair(I->getRecord(), TheInst));
- DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second;
- TheInsertedInst.setResultPattern(Temp.getOnlyTree());
+ // Use a temporary tree pattern to infer all types and make sure that the
+ // constructed result is correct. This depends on the instruction already
+ // being inserted into the DAGInsts map.
+ TreePattern Temp(I->getRecord(), ResultPattern, false, *this);
+ Temp.InferAllTypes(&I->getNamedNodesMap());
- return TheInsertedInst;
- }
+ DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second;
+ TheInsertedInst.setResultPattern(Temp.getOnlyTree());
+
+ return TheInsertedInst;
+}
/// ParseInstructions - Parse all of the instructions, inlining and resolving
/// any fragments involved. This populates the Instructions list with fully
@@ -2983,25 +3076,20 @@ void CodeGenDAGPatterns::ParseInstructions() {
// null_frag operator is as-if no pattern were specified. Normally this
// is from a multiclass expansion w/ a SDPatternOperator passed in as
// null_frag.
- if (!LI || LI->getSize() == 0 || hasNullFragReference(LI)) {
+ if (!LI || LI->empty() || hasNullFragReference(LI)) {
std::vector<Record*> Results;
std::vector<Record*> Operands;
CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]);
if (InstInfo.Operands.size() != 0) {
- if (InstInfo.Operands.NumDefs == 0) {
- // These produce no results
- for (unsigned j = 0, e = InstInfo.Operands.size(); j < e; ++j)
- Operands.push_back(InstInfo.Operands[j].Rec);
- } else {
- // Assume the first operand is the result.
- Results.push_back(InstInfo.Operands[0].Rec);
-
- // The rest are inputs.
- for (unsigned j = 1, e = InstInfo.Operands.size(); j < e; ++j)
- Operands.push_back(InstInfo.Operands[j].Rec);
- }
+ for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j)
+ Results.push_back(InstInfo.Operands[j].Rec);
+
+ // The rest are inputs.
+ for (unsigned j = InstInfo.Operands.NumDefs,
+ e = InstInfo.Operands.size(); j < e; ++j)
+ Operands.push_back(InstInfo.Operands[j].Rec);
}
// Create and insert the instruction.
@@ -3311,7 +3399,7 @@ void CodeGenDAGPatterns::ParsePatterns() {
Pattern->InlinePatternFragments();
ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs");
- if (LI->getSize() == 0) continue; // no pattern.
+ if (LI->empty()) continue; // no pattern.
// Parse the instruction.
TreePattern Result(CurPattern, LI, false, *this);
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index c0812cf055364..9ce3cdfd7bc15 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -136,10 +136,18 @@ namespace EEVT {
/// whose element is VT.
bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
+ /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
+ /// whose element is VT.
+ bool EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TreePattern &TP);
+
/// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to
/// be a vector type VT.
bool EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
+ /// EnforceVectorSameNumElts - 'this' is now constrainted to
+ /// be a vector with same num elements as VT.
+ bool EnforceVectorSameNumElts(EEVT::TypeSet &VT, TreePattern &TP);
+
bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; }
bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; }
@@ -165,7 +173,7 @@ struct SDTypeConstraint {
enum {
SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec,
- SDTCisSubVecOfVec
+ SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs
} ConstraintType;
union { // The discriminated union.
@@ -187,6 +195,12 @@ struct SDTypeConstraint {
struct {
unsigned OtherOperandNum;
} SDTCisSubVecOfVec_Info;
+ struct {
+ MVT::SimpleValueType VT;
+ } SDTCVecEltisVT_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisSameNumEltsAs_Info;
} x;
/// ApplyTypeConstraint - Given a node in a pattern, apply this type
diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h
index 1f1adf11fb3b0..f4055571b1c7b 100644
--- a/utils/TableGen/CodeGenIntrinsics.h
+++ b/utils/TableGen/CodeGenIntrinsics.h
@@ -80,6 +80,9 @@ namespace llvm {
/// isNoReturn - True if the intrinsic is no-return.
bool isNoReturn;
+ /// isConvergent - True if the intrinsic is marked as convergent.
+ bool isConvergent;
+
enum ArgAttribute {
NoCapture,
ReadOnly,
diff --git a/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp
index 7e5aa9c161b48..b52a91d0177b5 100644
--- a/utils/TableGen/CodeGenMapTable.cpp
+++ b/utils/TableGen/CodeGenMapTable.cpp
@@ -128,7 +128,7 @@ public:
ListInit *ColValList = MapRec->getValueAsListInit("ValueCols");
// Each instruction map must specify at least one column for it to be valid.
- if (ColValList->getSize() == 0)
+ if (ColValList->empty())
PrintFatalError(MapRec->getLoc(), "InstrMapping record `" +
MapRec->getName() + "' has empty " + "`ValueCols' field!");
@@ -376,7 +376,7 @@ unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) {
std::vector<Record*> ColInstrs = MapTable[CurInstr];
std::string OutStr("");
unsigned RelExists = 0;
- if (ColInstrs.size()) {
+ if (!ColInstrs.empty()) {
for (unsigned j = 0; j < NumCol; j++) {
if (ColInstrs[j] != nullptr) {
RelExists = 1;
@@ -567,7 +567,7 @@ void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) {
std::vector<Record*> InstrMapVec;
InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping");
- if (!InstrMapVec.size())
+ if (InstrMapVec.empty())
return;
OS << "#ifdef GET_INSTRMAP_INFO\n";
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp
index bef8a4b8fa12a..c6940e9fe5176 100644
--- a/utils/TableGen/CodeGenRegisters.cpp
+++ b/utils/TableGen/CodeGenRegisters.cpp
@@ -108,7 +108,7 @@ CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum)
EnumValue(Enum),
CostPerUse(R->getValueAsInt("CostPerUse")),
CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
- NumNativeRegUnits(0),
+ HasDisjunctSubRegs(false),
SubRegsComplete(false),
SuperRegsComplete(false),
TopoSig(~0u)
@@ -153,11 +153,11 @@ const std::string &CodeGenRegister::getName() const {
namespace {
// Iterate over all register units in a set of registers.
class RegUnitIterator {
- CodeGenRegister::Set::const_iterator RegI, RegE;
- CodeGenRegister::RegUnitList::const_iterator UnitI, UnitE;
+ CodeGenRegister::Vec::const_iterator RegI, RegE;
+ CodeGenRegister::RegUnitList::iterator UnitI, UnitE;
public:
- RegUnitIterator(const CodeGenRegister::Set &Regs):
+ RegUnitIterator(const CodeGenRegister::Vec &Regs):
RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() {
if (RegI != RegE) {
@@ -192,32 +192,23 @@ protected:
};
} // namespace
-// Merge two RegUnitLists maintaining the order and removing duplicates.
-// Overwrites MergedRU in the process.
-static void mergeRegUnits(CodeGenRegister::RegUnitList &MergedRU,
- const CodeGenRegister::RegUnitList &RRU) {
- CodeGenRegister::RegUnitList LRU = MergedRU;
- MergedRU.clear();
- std::set_union(LRU.begin(), LRU.end(), RRU.begin(), RRU.end(),
- std::back_inserter(MergedRU));
-}
-
// Return true of this unit appears in RegUnits.
static bool hasRegUnit(CodeGenRegister::RegUnitList &RegUnits, unsigned Unit) {
- return std::count(RegUnits.begin(), RegUnits.end(), Unit);
+ return RegUnits.test(Unit);
}
// Inherit register units from subregisters.
// Return true if the RegUnits changed.
bool CodeGenRegister::inheritRegUnits(CodeGenRegBank &RegBank) {
- unsigned OldNumUnits = RegUnits.size();
+ bool changed = false;
for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
I != E; ++I) {
CodeGenRegister *SR = I->second;
// Merge the subregister's units into this register's RegUnits.
- mergeRegUnits(RegUnits, SR->RegUnits);
+ changed |= (RegUnits |= SR->RegUnits);
}
- return OldNumUnits != RegUnits.size();
+
+ return changed;
}
const CodeGenRegister::SubRegMap &
@@ -227,6 +218,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
return SubRegs;
SubRegsComplete = true;
+ HasDisjunctSubRegs = ExplicitSubRegs.size() > 1;
+
// First insert the explicit subregs and make sure they are fully indexed.
for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
CodeGenRegister *SR = ExplicitSubRegs[i];
@@ -247,6 +240,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
CodeGenRegister *SR = ExplicitSubRegs[i];
const SubRegMap &Map = SR->computeSubRegs(RegBank);
+ HasDisjunctSubRegs |= SR->HasDisjunctSubRegs;
for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE;
++SI) {
@@ -363,14 +357,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
// sub-registers, the other registers won't contribute any more units.
for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
CodeGenRegister *SR = ExplicitSubRegs[i];
- // Explicit sub-registers are usually disjoint, so this is a good way of
- // computing the union. We may pick up a few duplicates that will be
- // eliminated below.
- unsigned N = RegUnits.size();
- RegUnits.append(SR->RegUnits.begin(), SR->RegUnits.end());
- std::inplace_merge(RegUnits.begin(), RegUnits.begin() + N, RegUnits.end());
+ RegUnits |= SR->RegUnits;
}
- RegUnits.erase(std::unique(RegUnits.begin(), RegUnits.end()), RegUnits.end());
// Absent any ad hoc aliasing, we create one register unit per leaf register.
// These units correspond to the maximal cliques in the register overlap
@@ -389,19 +377,19 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
// Create a RegUnit representing this alias edge, and add it to both
// registers.
unsigned Unit = RegBank.newRegUnit(this, AR);
- RegUnits.push_back(Unit);
- AR->RegUnits.push_back(Unit);
+ RegUnits.set(Unit);
+ AR->RegUnits.set(Unit);
}
// Finally, create units for leaf registers without ad hoc aliases. Note that
// a leaf register with ad hoc aliases doesn't get its own unit - it isn't
// necessary. This means the aliasing leaf registers can share a single unit.
if (RegUnits.empty())
- RegUnits.push_back(RegBank.newRegUnit(this));
+ RegUnits.set(RegBank.newRegUnit(this));
// We have now computed the native register units. More may be adopted later
// for balancing purposes.
- NumNativeRegUnits = RegUnits.size();
+ NativeRegUnits = RegUnits;
return SubRegs;
}
@@ -535,7 +523,7 @@ CodeGenRegister::addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet,
// Get the sum of this register's unit weights.
unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const {
unsigned Weight = 0;
- for (RegUnitList::const_iterator I = RegUnits.begin(), E = RegUnits.end();
+ for (RegUnitList::iterator I = RegUnits.begin(), E = RegUnits.end();
I != E; ++I) {
Weight += RegBank.getRegUnit(*I).Weight;
}
@@ -658,6 +646,11 @@ struct TupleExpander : SetTheory::Expander {
// CodeGenRegisterClass
//===----------------------------------------------------------------------===//
+static void sortAndUniqueRegisters(CodeGenRegister::Vec &M) {
+ std::sort(M.begin(), M.end(), deref<llvm::less>());
+ M.erase(std::unique(M.begin(), M.end(), deref<llvm::equal>()), M.end());
+}
+
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
: TheDef(R),
Name(R->getName()),
@@ -667,9 +660,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
// Rename anonymous register classes.
if (R->getName().size() > 9 && R->getName()[9] == '.') {
static unsigned AnonCounter = 0;
- R->setName("AnonRegClass_" + utostr(AnonCounter));
- // MSVC2012 ICEs if AnonCounter++ is directly passed to utostr.
- ++AnonCounter;
+ R->setName("AnonRegClass_" + utostr(AnonCounter++));
}
std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes");
@@ -685,19 +676,20 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
// Allocation order 0 is the full set. AltOrders provides others.
const SetTheory::RecVec *Elements = RegBank.getSets().expand(R);
ListInit *AltOrders = R->getValueAsListInit("AltOrders");
- Orders.resize(1 + AltOrders->size());
+ Orders.resize(1 + AltOrders->getSize());
// Default allocation order always contains all registers.
for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
Orders[0].push_back((*Elements)[i]);
const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]);
- Members.insert(Reg);
+ Members.push_back(Reg);
TopoSigs.set(Reg->getTopoSig());
}
+ sortAndUniqueRegisters(Members);
// Alternative allocation orders may be subsets.
SetTheory::RecSet Order;
- for (unsigned i = 0, e = AltOrders->size(); i != e; ++i) {
+ for (unsigned i = 0, e = AltOrders->getSize(); i != e; ++i) {
RegBank.getSets().evaluate(AltOrders->getElement(i), Order, R->getLoc());
Orders[1 + i].append(Order.begin(), Order.end());
// Verify that all altorder members are regclass members.
@@ -719,6 +711,10 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
CopyCost = R->getValueAsInt("CopyCost");
Allocatable = R->getValueAsBit("isAllocatable");
AltOrderSelect = R->getValueAsString("AltOrderSelect");
+ int AllocationPriority = R->getValueAsInt("AllocationPriority");
+ if (AllocationPriority < 0 || AllocationPriority > 63)
+ PrintFatalError(R->getLoc(), "AllocationPriority out of range [0,63]");
+ this->AllocationPriority = AllocationPriority;
}
// Create an inferred register class that was missing from the .td files.
@@ -734,10 +730,10 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
SpillSize(Props.SpillSize),
SpillAlignment(Props.SpillAlignment),
CopyCost(0),
- Allocatable(true) {
- for (CodeGenRegister::Set::iterator I = Members.begin(), E = Members.end();
- I != E; ++I)
- TopoSigs.set((*I)->getTopoSig());
+ Allocatable(true),
+ AllocationPriority(0) {
+ for (const auto R : Members)
+ TopoSigs.set(R->getTopoSig());
}
// Compute inherited propertied for a synthesized register class.
@@ -755,6 +751,7 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
CopyCost = Super.CopyCost;
Allocatable = Super.Allocatable;
AltOrderSelect = Super.AltOrderSelect;
+ AllocationPriority = Super.AllocationPriority;
// Copy all allocation orders, filter out foreign registers from the larger
// super-class.
@@ -766,15 +763,15 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
}
bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
- return Members.count(Reg);
+ return std::binary_search(Members.begin(), Members.end(), Reg,
+ deref<llvm::less>());
}
namespace llvm {
raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
- for (CodeGenRegister::Set::const_iterator I = K.Members->begin(),
- E = K.Members->end(); I != E; ++I)
- OS << ", " << (*I)->getName();
+ for (const auto R : *K.Members)
+ OS << ", " << R->getName();
return OS << " }";
}
}
@@ -800,10 +797,10 @@ operator<(const CodeGenRegisterClass::Key &B) const {
static bool testSubClass(const CodeGenRegisterClass *A,
const CodeGenRegisterClass *B) {
return A->SpillAlignment && B->SpillAlignment % A->SpillAlignment == 0 &&
- A->SpillSize <= B->SpillSize &&
- std::includes(A->getMembers().begin(), A->getMembers().end(),
- B->getMembers().begin(), B->getMembers().end(),
- CodeGenRegister::Less());
+ A->SpillSize <= B->SpillSize &&
+ std::includes(A->getMembers().begin(), A->getMembers().end(),
+ B->getMembers().begin(), B->getMembers().end(),
+ deref<llvm::less>());
}
/// Sorting predicate for register classes. This provides a topological
@@ -927,7 +924,7 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) {
// Configure register Sets to understand register classes and tuples.
Sets.addFieldExpander("RegisterClass", "MemberList");
Sets.addFieldExpander("CalleeSavedRegs", "SaveList");
- Sets.addExpander("RegisterTuples", new TupleExpander());
+ Sets.addExpander("RegisterTuples", llvm::make_unique<TupleExpander>());
// Read in the user-defined (named) sub-register indices.
// More indices will be synthesized later.
@@ -1050,7 +1047,7 @@ void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
// Create a synthetic sub-class if it is missing.
CodeGenRegisterClass*
CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
- const CodeGenRegister::Set *Members,
+ const CodeGenRegister::Vec *Members,
StringRef Name) {
// Synthetic sub-class has the same size and alignment as RC.
CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment);
@@ -1273,7 +1270,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
for (auto &RegClass : RegClasses) {
unsigned LaneMask = 0;
for (const auto &SubRegIndex : SubRegIndices) {
- if (RegClass.getSubClassWithSubReg(&SubRegIndex) != &RegClass)
+ if (RegClass.getSubClassWithSubReg(&SubRegIndex) == nullptr)
continue;
LaneMask |= SubRegIndex.LaneMask;
}
@@ -1299,7 +1296,7 @@ namespace {
// for which the unit weight equals the set weight. These units should not have
// their weight increased.
struct UberRegSet {
- CodeGenRegister::Set Regs;
+ CodeGenRegister::Vec Regs;
unsigned Weight;
CodeGenRegister::RegUnitList SingularDeterminants;
@@ -1328,7 +1325,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
if (!RegClass.Allocatable)
continue;
- const CodeGenRegister::Set &Regs = RegClass.getMembers();
+ const CodeGenRegister::Vec &Regs = RegClass.getMembers();
if (Regs.empty())
continue;
@@ -1336,8 +1333,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
assert(USetID && "register number 0 is invalid");
AllocatableRegs.insert((*Regs.begin())->EnumValue);
- for (CodeGenRegister::Set::const_iterator I = std::next(Regs.begin()),
- E = Regs.end(); I != E; ++I) {
+ for (auto I = std::next(Regs.begin()), E = Regs.end(); I != E; ++I) {
AllocatableRegs.insert((*I)->EnumValue);
UberSetIDs.join(USetID, (*I)->EnumValue);
}
@@ -1367,7 +1363,8 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
USetID = 0;
UberRegSet *USet = &UberSets[USetID];
- USet->Regs.insert(&Reg);
+ USet->Regs.push_back(&Reg);
+ sortAndUniqueRegisters(USet->Regs);
RegSets[i++] = USet;
}
}
@@ -1409,11 +1406,10 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets,
}
// Find singular determinants.
- for (CodeGenRegister::Set::iterator RegI = I->Regs.begin(),
- RegE = I->Regs.end(); RegI != RegE; ++RegI) {
- if ((*RegI)->getRegUnits().size() == 1
- && (*RegI)->getWeight(RegBank) == I->Weight)
- mergeRegUnits(I->SingularDeterminants, (*RegI)->getRegUnits());
+ for (const auto R : I->Regs) {
+ if (R->getRegUnits().count() == 1 && R->getWeight(RegBank) == I->Weight) {
+ I->SingularDeterminants |= R->getRegUnits();
+ }
}
}
}
@@ -1431,13 +1427,14 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets,
static bool normalizeWeight(CodeGenRegister *Reg,
std::vector<UberRegSet> &UberSets,
std::vector<UberRegSet*> &RegSets,
- std::set<unsigned> &NormalRegs,
+ SparseBitVector<> &NormalRegs,
CodeGenRegister::RegUnitList &NormalUnits,
CodeGenRegBank &RegBank) {
- bool Changed = false;
- if (!NormalRegs.insert(Reg->EnumValue).second)
- return Changed;
+ if (NormalRegs.test(Reg->EnumValue))
+ return false;
+ NormalRegs.set(Reg->EnumValue);
+ bool Changed = false;
const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs();
for (CodeGenRegister::SubRegMap::const_iterator SRI = SRM.begin(),
SRE = SRM.end(); SRI != SRE; ++SRI) {
@@ -1461,8 +1458,8 @@ static bool normalizeWeight(CodeGenRegister *Reg,
// A register unit's weight can be adjusted only if it is the singular unit
// for this register, has not been used to normalize a subregister's set,
// and has not already been used to singularly determine this UberRegSet.
- unsigned AdjustUnit = Reg->getRegUnits().front();
- if (Reg->getRegUnits().size() != 1
+ unsigned AdjustUnit = *Reg->getRegUnits().begin();
+ if (Reg->getRegUnits().count() != 1
|| hasRegUnit(NormalUnits, AdjustUnit)
|| hasRegUnit(UberSet->SingularDeterminants, AdjustUnit)) {
// We don't have an adjustable unit, so adopt a new one.
@@ -1480,7 +1477,7 @@ static bool normalizeWeight(CodeGenRegister *Reg,
}
// Mark these units normalized so superregisters can't change their weights.
- mergeRegUnits(NormalUnits, Reg->getRegUnits());
+ NormalUnits |= Reg->getRegUnits();
return Changed;
}
@@ -1505,7 +1502,7 @@ void CodeGenRegBank::computeRegUnitWeights() {
Changed = false;
for (auto &Reg : Registers) {
CodeGenRegister::RegUnitList NormalUnits;
- std::set<unsigned> NormalRegs;
+ SparseBitVector<> NormalRegs;
Changed |= normalizeWeight(&Reg, UberSets, RegSets, NormalRegs,
NormalUnits, *this);
}
@@ -1768,7 +1765,7 @@ void CodeGenRegBank::computeRegUnitLaneMasks() {
for (auto &Register : Registers) {
// Create an initial lane mask for all register units.
const auto &RegUnits = Register.getRegUnits();
- CodeGenRegister::RegUnitLaneMaskList RegUnitLaneMasks(RegUnits.size(), 0);
+ CodeGenRegister::RegUnitLaneMaskList RegUnitLaneMasks(RegUnits.count(), 0);
// Iterate through SubRegisters.
typedef CodeGenRegister::SubRegMap SubRegMap;
const SubRegMap &SubRegs = Register.getSubRegs();
@@ -1783,15 +1780,18 @@ void CodeGenRegBank::computeRegUnitLaneMasks() {
const CodeGenRegister *SubRegister = S->second;
unsigned LaneMask = SubRegIndex->LaneMask;
// Distribute LaneMask to Register Units touched.
- for (const auto &SUI : SubRegister->getRegUnits()) {
+ for (unsigned SUI : SubRegister->getRegUnits()) {
bool Found = false;
- for (size_t u = 0, ue = RegUnits.size(); u < ue; ++u) {
- if (SUI == RegUnits[u]) {
+ unsigned u = 0;
+ for (unsigned RU : RegUnits) {
+ if (SUI == RU) {
RegUnitLaneMasks[u] |= LaneMask;
assert(!Found);
Found = true;
}
+ ++u;
}
+ (void)Found;
assert(Found);
}
}
@@ -1813,6 +1813,13 @@ void CodeGenRegBank::computeDerivedInfo() {
computeRegUnitLaneMasks();
+ // Compute register class HasDisjunctSubRegs flag.
+ for (CodeGenRegisterClass &RC : RegClasses) {
+ RC.HasDisjunctSubRegs = false;
+ for (const CodeGenRegister *Reg : RC.getMembers())
+ RC.HasDisjunctSubRegs |= Reg->HasDisjunctSubRegs;
+ }
+
// Get the weight of each set.
for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx)
RegUnitSets[Idx].Weight = getRegUnitSetWeight(RegUnitSets[Idx].Units);
@@ -1850,13 +1857,12 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
continue;
// Compute the set intersection of RC1 and RC2.
- const CodeGenRegister::Set &Memb1 = RC1->getMembers();
- const CodeGenRegister::Set &Memb2 = RC2->getMembers();
- CodeGenRegister::Set Intersection;
- std::set_intersection(Memb1.begin(), Memb1.end(),
- Memb2.begin(), Memb2.end(),
- std::inserter(Intersection, Intersection.begin()),
- CodeGenRegister::Less());
+ const CodeGenRegister::Vec &Memb1 = RC1->getMembers();
+ const CodeGenRegister::Vec &Memb2 = RC2->getMembers();
+ CodeGenRegister::Vec Intersection;
+ std::set_intersection(
+ Memb1.begin(), Memb1.end(), Memb2.begin(), Memb2.end(),
+ std::inserter(Intersection, Intersection.begin()), deref<llvm::less>());
// Skip disjoint class pairs.
if (Intersection.empty())
@@ -1882,19 +1888,21 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
//
void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
// Map SubRegIndex to set of registers in RC supporting that SubRegIndex.
- typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Set,
- CodeGenSubRegIndex::Less> SubReg2SetMap;
+ typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Vec,
+ deref<llvm::less>> SubReg2SetMap;
// Compute the set of registers supporting each SubRegIndex.
SubReg2SetMap SRSets;
- for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(),
- RE = RC->getMembers().end(); RI != RE; ++RI) {
- const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs();
+ for (const auto R : RC->getMembers()) {
+ const CodeGenRegister::SubRegMap &SRM = R->getSubRegs();
for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
E = SRM.end(); I != E; ++I)
- SRSets[I->first].insert(*RI);
+ SRSets[I->first].push_back(R);
}
+ for (auto I : SRSets)
+ sortAndUniqueRegisters(I.second);
+
// Find matching classes for all SRSets entries. Iterate in SubRegIndex
// numerical order to visit synthetic indices last.
for (const auto &SubIdx : SubRegIndices) {
@@ -1939,9 +1947,7 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
// Build list of (Super, Sub) pairs for this SubIdx.
SSPairs.clear();
TopoSigs.reset();
- for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(),
- RE = RC->getMembers().end(); RI != RE; ++RI) {
- const CodeGenRegister *Super = *RI;
+ for (const auto Super : RC->getMembers()) {
const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second;
assert(Sub && "Missing sub-register");
SSPairs.push_back(std::make_pair(Super, Sub));
@@ -1960,22 +1966,26 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
if (!TopoSigs.anyCommon(SubRC.getTopoSigs()))
continue;
// Compute the subset of RC that maps into SubRC.
- CodeGenRegister::Set SubSet;
+ CodeGenRegister::Vec SubSetVec;
for (unsigned i = 0, e = SSPairs.size(); i != e; ++i)
if (SubRC.contains(SSPairs[i].second))
- SubSet.insert(SSPairs[i].first);
- if (SubSet.empty())
+ SubSetVec.push_back(SSPairs[i].first);
+
+ if (SubSetVec.empty())
continue;
+
// RC injects completely into SubRC.
- if (SubSet.size() == SSPairs.size()) {
+ sortAndUniqueRegisters(SubSetVec);
+ if (SubSetVec.size() == SSPairs.size()) {
SubRC.addSuperRegClass(&SubIdx, RC);
continue;
}
+
// Only a subset of RC maps into SubRC. Make sure it is represented by a
// class.
- getOrCreateSubClass(RC, &SubSet, RC->getName() + "_with_" +
- SubIdx.getName() + "_in_" +
- SubRC.getName());
+ getOrCreateSubClass(RC, &SubSetVec, RC->getName() + "_with_" +
+ SubIdx.getName() + "_in_" +
+ SubRC.getName());
}
}
}
diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h
index 87a0dcf7af3d8..dc441436537db 100644
--- a/utils/TableGen/CodeGenRegisters.h
+++ b/utils/TableGen/CodeGenRegisters.h
@@ -18,7 +18,9 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SparseBitVector.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/TableGen/Record.h"
@@ -40,10 +42,10 @@ namespace llvm {
struct MaskRolPair {
unsigned Mask;
uint8_t RotateLeft;
- bool operator==(const MaskRolPair Other) {
+ bool operator==(const MaskRolPair Other) const {
return Mask == Other.Mask && RotateLeft == Other.RotateLeft;
}
- bool operator!=(const MaskRolPair Other) {
+ bool operator!=(const MaskRolPair Other) const {
return Mask != Other.Mask || RotateLeft != Other.RotateLeft;
}
};
@@ -72,17 +74,9 @@ namespace llvm {
const std::string &getNamespace() const { return Namespace; }
std::string getQualifiedName() const;
- // Order CodeGenSubRegIndex pointers by EnumValue.
- struct Less {
- bool operator()(const CodeGenSubRegIndex *A,
- const CodeGenSubRegIndex *B) const {
- assert(A && B);
- return A->EnumValue < B->EnumValue;
- }
- };
-
// Map of composite subreg indices.
- typedef std::map<CodeGenSubRegIndex*, CodeGenSubRegIndex*, Less> CompMap;
+ typedef std::map<CodeGenSubRegIndex *, CodeGenSubRegIndex *,
+ deref<llvm::less>> CompMap;
// Returns the subreg index that results from composing this with Idx.
// Returns NULL if this and Idx don't compose.
@@ -124,16 +118,22 @@ namespace llvm {
CompMap Composed;
};
+ inline bool operator<(const CodeGenSubRegIndex &A,
+ const CodeGenSubRegIndex &B) {
+ return A.EnumValue < B.EnumValue;
+ }
+
/// CodeGenRegister - Represents a register definition.
struct CodeGenRegister {
Record *TheDef;
unsigned EnumValue;
unsigned CostPerUse;
bool CoveredBySubRegs;
+ bool HasDisjunctSubRegs;
// Map SubRegIndex -> Register.
- typedef std::map<CodeGenSubRegIndex*, CodeGenRegister*,
- CodeGenSubRegIndex::Less> SubRegMap;
+ typedef std::map<CodeGenSubRegIndex *, CodeGenRegister *, deref<llvm::less>>
+ SubRegMap;
CodeGenRegister(Record *R, unsigned Enum);
@@ -197,23 +197,23 @@ namespace llvm {
}
// List of register units in ascending order.
- typedef SmallVector<unsigned, 16> RegUnitList;
+ typedef SparseBitVector<> RegUnitList;
typedef SmallVector<unsigned, 16> RegUnitLaneMaskList;
// How many entries in RegUnitList are native?
- unsigned NumNativeRegUnits;
+ RegUnitList NativeRegUnits;
// Get the list of register units.
// This is only valid after computeSubRegs() completes.
const RegUnitList &getRegUnits() const { return RegUnits; }
ArrayRef<unsigned> getRegUnitLaneMasks() const {
- return makeArrayRef(RegUnitLaneMasks).slice(0, NumNativeRegUnits);
+ return makeArrayRef(RegUnitLaneMasks).slice(0, NativeRegUnits.count());
}
// Get the native register units. This is a prefix of getRegUnits().
- ArrayRef<unsigned> getNativeRegUnits() const {
- return makeArrayRef(RegUnits).slice(0, NumNativeRegUnits);
+ RegUnitList getNativeRegUnits() const {
+ return NativeRegUnits;
}
void setRegUnitLaneMasks(const RegUnitLaneMaskList &LaneMasks) {
@@ -225,23 +225,14 @@ namespace llvm {
bool inheritRegUnits(CodeGenRegBank &RegBank);
// Adopt a register unit for pressure tracking.
- // A unit is adopted iff its unit number is >= NumNativeRegUnits.
- void adoptRegUnit(unsigned RUID) { RegUnits.push_back(RUID); }
+ // A unit is adopted iff its unit number is >= NativeRegUnits.count().
+ void adoptRegUnit(unsigned RUID) { RegUnits.set(RUID); }
// Get the sum of this register's register unit weights.
unsigned getWeight(const CodeGenRegBank &RegBank) const;
- // Order CodeGenRegister pointers by EnumValue.
- struct Less {
- bool operator()(const CodeGenRegister *A,
- const CodeGenRegister *B) const {
- assert(A && B);
- return A->EnumValue < B->EnumValue;
- }
- };
-
// Canonically ordered set.
- typedef std::set<const CodeGenRegister*, Less> Set;
+ typedef std::vector<const CodeGenRegister*> Vec;
private:
bool SubRegsComplete;
@@ -265,9 +256,16 @@ namespace llvm {
RegUnitLaneMaskList RegUnitLaneMasks;
};
+ inline bool operator<(const CodeGenRegister &A, const CodeGenRegister &B) {
+ return A.EnumValue < B.EnumValue;
+ }
+
+ inline bool operator==(const CodeGenRegister &A, const CodeGenRegister &B) {
+ return A.EnumValue == B.EnumValue;
+ }
class CodeGenRegisterClass {
- CodeGenRegister::Set Members;
+ CodeGenRegister::Vec Members;
// Allocation orders. Order[0] always contains all registers in Members.
std::vector<SmallVector<Record*, 16> > Orders;
// Bit mask of sub-classes including this, indexed by their EnumValue.
@@ -308,8 +306,11 @@ namespace llvm {
int CopyCost;
bool Allocatable;
std::string AltOrderSelect;
+ uint8_t AllocationPriority;
/// Contains the combination of the lane masks of all subregisters.
unsigned LaneMask;
+ /// True if there are at least 2 subregisters which do not interfere.
+ bool HasDisjunctSubRegs;
// Return the Record that defined this class, or NULL if the class was
// created by TableGen.
@@ -388,7 +389,7 @@ namespace llvm {
// Get the set of registers. This set contains the same registers as
// getOrder(0).
- const CodeGenRegister::Set &getMembers() const { return Members; }
+ const CodeGenRegister::Vec &getMembers() const { return Members; }
// Get a bit vector of TopoSigs present in this register class.
const BitVector &getTopoSigs() const { return TopoSigs; }
@@ -402,11 +403,11 @@ namespace llvm {
// sub-classes. Note the ordering provided by this key is not the same as
// the topological order used for the EnumValues.
struct Key {
- const CodeGenRegister::Set *Members;
+ const CodeGenRegister::Vec *Members;
unsigned SpillSize;
unsigned SpillAlignment;
- Key(const CodeGenRegister::Set *M, unsigned S = 0, unsigned A = 0)
+ Key(const CodeGenRegister::Vec *M, unsigned S = 0, unsigned A = 0)
: Members(M), SpillSize(S), SpillAlignment(A) {}
Key(const CodeGenRegisterClass &RC)
@@ -524,7 +525,7 @@ namespace llvm {
// Create a synthetic sub-class if it is missing.
CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC,
- const CodeGenRegister::Set *Membs,
+ const CodeGenRegister::Vec *Membs,
StringRef Name);
// Infer missing register classes.
diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp
index bfdf8dcc89e09..58363e85c5449 100644
--- a/utils/TableGen/CodeGenSchedule.cpp
+++ b/utils/TableGen/CodeGenSchedule.cpp
@@ -93,8 +93,8 @@ CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
// Allow Set evaluation to recognize the dags used in InstRW records:
// (instrs Op1, Op1...)
- Sets.addOperator("instrs", new InstrsOp);
- Sets.addOperator("instregex", new InstRegexOp(Target));
+ Sets.addOperator("instrs", llvm::make_unique<InstrsOp>());
+ Sets.addOperator("instregex", llvm::make_unique<InstRegexOp>(Target));
// Instantiate a CodeGenProcModel for each SchedMachineModel with the values
// that are explicitly referenced in tablegen records. Resources associated
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index e727a0e3f7ac5..076537002a6f0 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -57,6 +57,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::i32: return "MVT::i32";
case MVT::i64: return "MVT::i64";
case MVT::i128: return "MVT::i128";
+ case MVT::Any: return "MVT::Any";
case MVT::iAny: return "MVT::iAny";
case MVT::fAny: return "MVT::fAny";
case MVT::vAny: return "MVT::vAny";
@@ -98,6 +99,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v4i64: return "MVT::v4i64";
case MVT::v8i64: return "MVT::v8i64";
case MVT::v16i64: return "MVT::v16i64";
+ case MVT::v1i128: return "MVT::v1i128";
case MVT::v2f16: return "MVT::v2f16";
case MVT::v4f16: return "MVT::v4f16";
case MVT::v8f16: return "MVT::v8f16";
@@ -409,9 +411,9 @@ ComplexPattern::ComplexPattern(Record *R) {
} else if (PropList[i]->getName() == "SDNPWantParent") {
Properties |= 1 << SDNPWantParent;
} else {
- errs() << "Unsupported SD Node property '" << PropList[i]->getName()
- << "' on ComplexPattern '" << R->getName() << "'!\n";
- exit(1);
+ PrintFatalError("Unsupported SD Node property '" +
+ PropList[i]->getName() + "' on ComplexPattern '" +
+ R->getName() + "'!");
}
}
@@ -442,6 +444,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
canThrow = false;
isNoReturn = false;
isNoDuplicate = false;
+ isConvergent = false;
if (DefName.size() <= 4 ||
std::string(DefName.begin(), DefName.begin() + 4) != "int_")
@@ -572,6 +575,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
canThrow = true;
else if (Property->getName() == "IntrNoDuplicate")
isNoDuplicate = true;
+ else if (Property->getName() == "IntrConvergent")
+ isConvergent = true;
else if (Property->getName() == "IntrNoReturn")
isNoReturn = true;
else if (Property->isSubClassOf("NoCapture")) {
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
index 9df3b410ff268..a8a6ba5c32e15 100644
--- a/utils/TableGen/DAGISelMatcher.h
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -194,7 +194,7 @@ public:
ScopeMatcher(ArrayRef<Matcher *> children)
: Matcher(Scope), Children(children.begin(), children.end()) {
}
- virtual ~ScopeMatcher();
+ ~ScopeMatcher() override;
unsigned getNumChildren() const { return Children.size(); }
@@ -507,7 +507,7 @@ class SwitchOpcodeMatcher : public Matcher {
public:
SwitchOpcodeMatcher(ArrayRef<std::pair<const SDNodeInfo*, Matcher*> > cases)
: Matcher(SwitchOpcode), Cases(cases.begin(), cases.end()) {}
- virtual ~SwitchOpcodeMatcher();
+ ~SwitchOpcodeMatcher() override;
static inline bool classof(const Matcher *N) {
return N->getKind() == SwitchOpcode;
@@ -561,7 +561,7 @@ class SwitchTypeMatcher : public Matcher {
public:
SwitchTypeMatcher(ArrayRef<std::pair<MVT::SimpleValueType, Matcher*> > cases)
: Matcher(SwitchType), Cases(cases.begin(), cases.end()) {}
- virtual ~SwitchTypeMatcher();
+ ~SwitchTypeMatcher() override;
static inline bool classof(const Matcher *N) {
return N->getKind() == SwitchType;
diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
index 302f27bd0ecb4..4659dc157338b 100644
--- a/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -188,7 +188,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
<< " children in Scope";
}
- OS << '\n' << TmpBuf.str();
+ OS << '\n' << TmpBuf;
CurrentIdx += ChildSize;
}
@@ -342,7 +342,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
if (!OmitComments)
OS << "// ->" << CurrentIdx+ChildSize;
OS << '\n';
- OS << TmpBuf.str();
+ OS << TmpBuf;
CurrentIdx += ChildSize;
}
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index eb806192bdc39..9663b71d6620d 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -220,7 +220,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
}
// An UnsetInit represents a named node without any constraints.
- if (N->getLeafValue() == UnsetInit::get()) {
+ if (isa<UnsetInit>(N->getLeafValue())) {
assert(N->hasName() && "Unnamed ? leaf");
return;
}
@@ -268,8 +268,10 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
// We can't model ComplexPattern uses that don't have their name taken yet.
// The OPC_CheckComplexPattern operation implicitly records the results.
if (N->getName().empty()) {
- errs() << "We expect complex pattern uses to have names: " << *N << "\n";
- exit(1);
+ std::string S;
+ raw_string_ostream OS(S);
+ OS << "We expect complex pattern uses to have names: " << *N;
+ PrintFatalError(OS.str());
}
// Remember this ComplexPattern so that we can emit it after all the other
diff --git a/utils/TableGen/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp
index ea14cb973ebcd..5060b6e9ce7c0 100644
--- a/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -472,7 +472,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
current->canAddInsnClass(InsnClass)) {
const State *NewState;
current->AddInsnClass(InsnClass, NewStateResources);
- assert(NewStateResources.size() && "New states must be generated");
+ assert(!NewStateResources.empty() && "New states must be generated");
//
// If we have seen this state before, then do not create a new state.
diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
index 7c29422ec1b90..7905b1a6268e2 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -333,8 +333,8 @@ protected:
// Parent emitter
const FixedLenDecoderEmitter *Emitter;
- FilterChooser(const FilterChooser &) LLVM_DELETED_FUNCTION;
- void operator=(const FilterChooser &) LLVM_DELETED_FUNCTION;
+ FilterChooser(const FilterChooser &) = delete;
+ void operator=(const FilterChooser &) = delete;
public:
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
@@ -540,7 +540,7 @@ void Filter::recurse() {
// Starts by inheriting our parent filter chooser's filter bit values.
std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues);
- if (VariableInstructions.size()) {
+ if (!VariableInstructions.empty()) {
// Conservatively marks each segment position as BIT_UNSET.
for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex)
BitValueArray[StartBit + bitIndex] = BIT_UNSET;
@@ -676,7 +676,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
// Returns the number of fanout produced by the filter. More fanout implies
// the filter distinguishes more categories of instructions.
unsigned Filter::usefulness() const {
- if (VariableInstructions.size())
+ if (!VariableInstructions.empty())
return FilteredInstructions.size();
else
return FilteredInstructions.size() + 1;
@@ -848,7 +848,7 @@ emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
// The predicate function is just a big switch statement based on the
// input predicate index.
OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
- << "uint64_t Bits) {\n";
+ << "const FeatureBitset& Bits) {\n";
Indentation += 2;
if (!Predicates.empty()) {
OS.indent(Indentation) << "switch (Idx) {\n";
@@ -1054,7 +1054,7 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
<< "(MI, tmp, Address, Decoder)"
<< Emitter->GuardPostfix << "\n";
else
- o.indent(Indentation) << "MI.addOperand(MCOperand::CreateImm(tmp));\n";
+ o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n";
}
@@ -1091,7 +1091,7 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
// overkill for now, though.
// Make sure the predicate is in the table.
- Decoders.insert(Decoder.str());
+ Decoders.insert(StringRef(Decoder));
// Now figure out the index for when we write out the table.
DecoderSet::const_iterator P = std::find(Decoders.begin(),
Decoders.end(),
@@ -1102,16 +1102,17 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
const std::string &PredicateNamespace) {
if (str[0] == '!')
- o << "!(Bits & " << PredicateNamespace << "::"
- << str.slice(1,str.size()) << ")";
+ o << "!Bits[" << PredicateNamespace << "::"
+ << str.slice(1,str.size()) << "]";
else
- o << "(Bits & " << PredicateNamespace << "::" << str << ")";
+ o << "Bits[" << PredicateNamespace << "::" << str << "]";
}
bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
unsigned Opc) const {
ListInit *Predicates =
AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates");
+ bool IsFirstEmission = true;
for (unsigned i = 0; i < Predicates->getSize(); ++i) {
Record *Pred = Predicates->getElementAsRecord(i);
if (!Pred->getValue("AssemblerMatcherPredicate"))
@@ -1122,7 +1123,7 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
if (!P.length())
continue;
- if (i != 0)
+ if (!IsFirstEmission)
o << " && ";
StringRef SR(P);
@@ -1133,6 +1134,7 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
pairs = pairs.second.split(',');
}
emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
+ IsFirstEmission = false;
}
return Predicates->getSize() > 0;
}
@@ -1780,7 +1782,7 @@ static bool populateInstruction(CodeGenTarget &Target,
unsigned NumberOps = CGI.Operands.size();
while (NumberedOp < NumberOps &&
(CGI.Operands.isFlatOperandNotEmitted(NumberedOp) ||
- (NamedOpIndices.size() && NamedOpIndices.count(
+ (!NamedOpIndices.empty() && NamedOpIndices.count(
CGI.Operands.getSubOperandNumber(NumberedOp).first))))
++NumberedOp;
@@ -2010,7 +2012,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " InsnType insn, uint64_t Address,\n"
<< " const void *DisAsm,\n"
<< " const MCSubtargetInfo &STI) {\n"
- << " uint64_t Bits = STI.getFeatureBits();\n"
+ << " const FeatureBitset& Bits = STI.getFeatureBits();\n"
<< "\n"
<< " const uint8_t *Ptr = DecodeTable;\n"
<< " uint32_t CurFieldValue = 0;\n"
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index fe30d60fd4ce7..7b69de56f9f74 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -248,7 +248,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n";
OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n";
- OS << "namespace llvm {";
+ OS << "namespace llvm {\n";
OS << "namespace " << Namespace << " {\n";
OS << "namespace " << OpNameNS << " { \n";
OS << "enum {\n";
@@ -264,7 +264,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n";
OS << "#undef GET_INSTRINFO_NAMED_OPS\n";
- OS << "namespace llvm {";
+ OS << "namespace llvm {\n";
OS << "namespace " << Namespace << " {\n";
OS << "LLVM_READONLY\n";
OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n";
@@ -315,7 +315,7 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
OS << "\n#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
OS << "#undef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
- OS << "namespace llvm {";
+ OS << "namespace llvm {\n";
OS << "namespace " << Namespace << " {\n";
OS << "namespace OpTypes { \n";
OS << "enum OperandType {\n";
@@ -430,7 +430,8 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
std::string ClassName = TargetName + "GenInstrInfo";
OS << "namespace llvm {\n";
OS << "struct " << ClassName << " : public TargetInstrInfo {\n"
- << " explicit " << ClassName << "(int SO = -1, int DO = -1);\n"
+ << " explicit " << ClassName
+ << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1);\n"
<< " virtual ~" << ClassName << "();\n"
<< "};\n";
OS << "} // End llvm namespace \n";
@@ -444,10 +445,11 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n";
OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n";
OS << "extern const char " << TargetName << "InstrNameData[];\n";
- OS << ClassName << "::" << ClassName << "(int SO, int DO)\n"
- << " : TargetInstrInfo(SO, DO) {\n"
- << " InitMCInstrInfo(" << TargetName << "Insts, "
- << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "
+ OS << ClassName << "::" << ClassName
+ << "(int CFSetupOpcode, int CFDestroyOpcode)\n"
+ << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode) {\n"
+ << " InitMCInstrInfo(" << TargetName << "Insts, " << TargetName
+ << "InstrNameIndices, " << TargetName << "InstrNameData, "
<< NumberedInstructions.size() << ");\n}\n"
<< ClassName << "::~" << ClassName << "() {}\n";
OS << "} // End llvm namespace \n";
@@ -476,7 +478,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
<< SchedModels.getSchedClassIdx(Inst) << ",\t"
<< Inst.TheDef->getValueAsInt("Size") << ",\t0";
- // Emit all of the target indepedent flags...
+ // Emit all of the target independent flags...
if (Inst.isPseudo) OS << "|(1<<MCID::Pseudo)";
if (Inst.isReturn) OS << "|(1<<MCID::Return)";
if (Inst.isBranch) OS << "|(1<<MCID::Branch)";
@@ -547,15 +549,15 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
CodeGenTarget &Target = CDP.getTargetInfo();
if (Inst.HasComplexDeprecationPredicate)
// Emit a function pointer to the complex predicate method.
- OS << ",0"
+ OS << ", -1 "
<< ",&get" << Inst.DeprecatedReason << "DeprecationInfo";
else if (!Inst.DeprecatedReason.empty())
// Emit the Subtarget feature.
- OS << "," << Target.getInstNamespace() << "::" << Inst.DeprecatedReason
- << ",nullptr";
+ OS << ", " << Target.getInstNamespace() << "::" << Inst.DeprecatedReason
+ << " ,nullptr";
else
// Instruction isn't deprecated.
- OS << ",0,nullptr";
+ OS << ", -1 ,nullptr";
OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}
@@ -573,10 +575,8 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
// We must emit the PHI opcode first...
std::string Namespace = Target.getInstNamespace();
- if (Namespace.empty()) {
- fprintf(stderr, "No instructions defined!\n");
- exit(1);
- }
+ if (Namespace.empty())
+ PrintFatalError("No instructions defined!");
const std::vector<const CodeGenInstruction*> &NumberedInstructions =
Target.getInstructionsByEnumValue();
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index c0cf92d761873..3f62f205fe557 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -259,7 +259,9 @@ enum IIT_Info {
IIT_VARARG = 28,
IIT_HALF_VEC_ARG = 29,
IIT_SAME_VEC_WIDTH_ARG = 30,
- IIT_PTR_TO_ARG = 31
+ IIT_PTR_TO_ARG = 31,
+ IIT_VEC_OF_PTRS_TO_ELT = 32,
+ IIT_I128 = 33
};
@@ -274,6 +276,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
case 16: return Sig.push_back(IIT_I16);
case 32: return Sig.push_back(IIT_I32);
case 64: return Sig.push_back(IIT_I64);
+ case 128: return Sig.push_back(IIT_I128);
}
}
@@ -291,7 +294,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
}
}
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(__clang__)
#pragma optimize("",off) // MSVC 2010 optimizer can't deal with this function.
#endif
@@ -309,17 +312,18 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
Sig.push_back(IIT_HALF_VEC_ARG);
else if (R->isSubClassOf("LLVMVectorSameWidth")) {
Sig.push_back(IIT_SAME_VEC_WIDTH_ARG);
- Sig.push_back((Number << 2) | ArgCodes[Number]);
+ Sig.push_back((Number << 3) | ArgCodes[Number]);
MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy"));
EncodeFixedValueType(VT, Sig);
return;
}
- else if (R->isSubClassOf("LLVMPointerTo")) {
+ else if (R->isSubClassOf("LLVMPointerTo"))
Sig.push_back(IIT_PTR_TO_ARG);
- }
+ else if (R->isSubClassOf("LLVMVectorOfPointersToElt"))
+ Sig.push_back(IIT_VEC_OF_PTRS_TO_ELT);
else
Sig.push_back(IIT_ARG);
- return Sig.push_back((Number << 2) | ArgCodes[Number]);
+ return Sig.push_back((Number << 3) | ArgCodes[Number]);
}
MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
@@ -330,7 +334,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
case MVT::iPTRAny: ++Tmp; // FALL THROUGH.
case MVT::vAny: ++Tmp; // FALL THROUGH.
case MVT::fAny: ++Tmp; // FALL THROUGH.
- case MVT::iAny: {
+ case MVT::iAny: ++Tmp; // FALL THROUGH.
+ case MVT::Any: {
// If this is an "any" valuetype, then the type is the type of the next
// type in the list specified to getIntrinsic().
Sig.push_back(IIT_ARG);
@@ -339,8 +344,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
unsigned ArgNo = ArgCodes.size();
ArgCodes.push_back(Tmp);
- // Encode what sort of argument it must be in the low 2 bits of the ArgNo.
- return Sig.push_back((ArgNo << 2) | Tmp);
+ // Encode what sort of argument it must be in the low 3 bits of the ArgNo.
+ return Sig.push_back((ArgNo << 3) | Tmp);
}
case MVT::iPTR: {
@@ -378,7 +383,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
EncodeFixedValueType(VT, Sig);
}
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(__clang__)
#pragma optimize("",on)
#endif
@@ -532,6 +537,9 @@ struct AttributeComparator {
if (L->isNoReturn != R->isNoReturn)
return R->isNoReturn;
+ if (L->isConvergent != R->isConvergent)
+ return R->isConvergent;
+
// Try to order by readonly/readnone attribute.
ModRefKind LK = getModRefKind(*L);
ModRefKind RK = getModRefKind(*R);
@@ -644,7 +652,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
ModRefKind modRef = getModRefKind(intrinsic);
if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn ||
- intrinsic.isNoDuplicate) {
+ intrinsic.isNoDuplicate || intrinsic.isConvergent) {
OS << " const Attribute::AttrKind Atts[] = {";
bool addComma = false;
if (!intrinsic.canThrow) {
@@ -663,6 +671,12 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << "Attribute::NoDuplicate";
addComma = true;
}
+ if (intrinsic.isConvergent) {
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::Convergent";
+ addComma = true;
+ }
switch (modRef) {
case MRK_none: break;
diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp
index ebb43f0652620..01e41d1060e0d 100644
--- a/utils/TableGen/PseudoLoweringEmitter.cpp
+++ b/utils/TableGen/PseudoLoweringEmitter.cpp
@@ -232,12 +232,12 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
<< " TmpInst.addOperand(MCOp);\n";
break;
case OpData::Imm:
- o << " TmpInst.addOperand(MCOperand::CreateImm("
+ o << " TmpInst.addOperand(MCOperand::createImm("
<< Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n";
break;
case OpData::Reg: {
Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg;
- o << " TmpInst.addOperand(MCOperand::CreateReg(";
+ o << " TmpInst.addOperand(MCOperand::createReg(";
// "zero_reg" is special.
if (Reg->getName() == "zero_reg")
o << "0";
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index 1c3de4a2c2b85..a8423a98ae855 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -180,7 +180,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< "getRegClassWeight(const TargetRegisterClass *RC) const {\n"
<< " static const RegClassWeight RCWeightTable[] = {\n";
for (const auto &RC : RegBank.getRegClasses()) {
- const CodeGenRegister::Set &Regs = RC.getMembers();
+ const CodeGenRegister::Vec &Regs = RC.getMembers();
if (Regs.empty())
OS << " {0, 0";
else {
@@ -233,7 +233,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
OS << "// Get the name of this register unit pressure set.\n"
<< "const char *" << ClassName << "::\n"
<< "getRegPressureSetName(unsigned Idx) const {\n"
- << " static const char *PressureNameTable[] = {\n";
+ << " static const char *const PressureNameTable[] = {\n";
unsigned MaxRegUnitWeight = 0;
for (unsigned i = 0; i < NumSets; ++i ) {
const RegUnitSet &RegUnits = RegBank.getRegSetAt(i);
@@ -247,7 +247,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
OS << "// Get the register unit pressure limit for this dimension.\n"
<< "// This limit must be adjusted dynamically for reserved registers.\n"
<< "unsigned " << ClassName << "::\n"
- << "getRegPressureSetLimit(unsigned Idx) const {\n"
+ << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const {\n"
<< " static const " << getMinimalTypeForRange(MaxRegUnitWeight)
<< " PressureLimitTable[] = {\n";
for (unsigned i = 0; i < NumSets; ++i ) {
@@ -573,11 +573,11 @@ typedef SmallVector<unsigned, 4> MaskVec;
// Differentially encode a sequence of numbers into V. The starting value and
// terminating 0 are not added to V, so it will have the same size as List.
static
-DiffVec &diffEncode(DiffVec &V, unsigned InitVal, ArrayRef<unsigned> List) {
+DiffVec &diffEncode(DiffVec &V, unsigned InitVal, SparseBitVector<> List) {
assert(V.empty() && "Clear DiffVec before diffEncode.");
uint16_t Val = uint16_t(InitVal);
- for (unsigned i = 0; i != List.size(); ++i) {
- uint16_t Cur = List[i];
+
+ for (uint16_t Cur : List) {
V.push_back(Cur - Val);
Val = Cur;
}
@@ -610,17 +610,19 @@ static void printMask(raw_ostream &OS, unsigned Val) {
static bool combine(const CodeGenSubRegIndex *Idx,
SmallVectorImpl<CodeGenSubRegIndex*> &Vec) {
const CodeGenSubRegIndex::CompMap &Map = Idx->getComposites();
- for (CodeGenSubRegIndex::CompMap::const_iterator
- I = Map.begin(), E = Map.end(); I != E; ++I) {
- CodeGenSubRegIndex *&Entry = Vec[I->first->EnumValue - 1];
- if (Entry && Entry != I->second)
+ for (const auto &I : Map) {
+ CodeGenSubRegIndex *&Entry = Vec[I.first->EnumValue - 1];
+ if (Entry && Entry != I.second)
return false;
}
// All entries are compatible. Make it so.
- for (CodeGenSubRegIndex::CompMap::const_iterator
- I = Map.begin(), E = Map.end(); I != E; ++I)
- Vec[I->first->EnumValue - 1] = I->second;
+ for (const auto &I : Map) {
+ auto *&Entry = Vec[I.first->EnumValue - 1];
+ assert((!Entry || Entry == I.second) &&
+ "Expected EnumValue to be unique");
+ Entry = I.second;
+ }
return true;
}
@@ -714,16 +716,7 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
for (size_t s = 0, se = Sequences.size(); s != se; ++s, SIdx = NextSIdx) {
SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s];
NextSIdx = SIdx + Sequence.size() + 1;
- if (Sequence.size() != IdxSequence.size())
- continue;
- bool Identical = true;
- for (size_t o = 0, oe = Sequence.size(); o != oe; ++o) {
- if (Sequence[o] != IdxSequence[o]) {
- Identical = false;
- break;
- }
- }
- if (Identical) {
+ if (Sequence == IdxSequence) {
Found = SIdx;
break;
}
@@ -759,7 +752,7 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
Idx += Sequence.size() + 1;
}
OS << " };\n"
- " static const MaskRolOp *CompositeSequences[] = {\n";
+ " static const MaskRolOp *const CompositeSequences[] = {\n";
for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) {
OS << " ";
unsigned Idx = SubReg2SequenceIndexMap[i];
@@ -815,7 +808,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
// Keep track of sub-register names as well. These are not differentially
// encoded.
typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec;
- SequenceToOffsetTable<SubRegIdxVec, CodeGenSubRegIndex::Less> SubRegIdxSeqs;
+ SequenceToOffsetTable<SubRegIdxVec, deref<llvm::less>> SubRegIdxSeqs;
SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size());
SequenceToOffsetTable<std::string> RegStrings;
@@ -856,13 +849,13 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
//
// Check the neighboring registers for arithmetic progressions.
unsigned ScaleA = ~0u, ScaleB = ~0u;
- ArrayRef<unsigned> RUs = Reg.getNativeRegUnits();
+ SparseBitVector<> RUs = Reg.getNativeRegUnits();
if (I != Regs.begin() &&
- std::prev(I)->getNativeRegUnits().size() == RUs.size())
- ScaleB = RUs.front() - std::prev(I)->getNativeRegUnits().front();
+ std::prev(I)->getNativeRegUnits().count() == RUs.count())
+ ScaleB = *RUs.begin() - *std::prev(I)->getNativeRegUnits().begin();
if (std::next(I) != Regs.end() &&
- std::next(I)->getNativeRegUnits().size() == RUs.size())
- ScaleA = std::next(I)->getNativeRegUnits().front() - RUs.front();
+ std::next(I)->getNativeRegUnits().count() == RUs.count())
+ ScaleA = *std::next(I)->getNativeRegUnits().begin() - *RUs.begin();
unsigned Scale = std::min(ScaleB, ScaleA);
// Default the scale to 0 if it can't be encoded in 4 bits.
if (Scale >= 16)
@@ -1095,7 +1088,8 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
<< " unsigned getRegUnitWeight(unsigned RegUnit) const override;\n"
<< " unsigned getNumRegPressureSets() const override;\n"
<< " const char *getRegPressureSetName(unsigned Idx) const override;\n"
- << " unsigned getRegPressureSetLimit(unsigned Idx) const override;\n"
+ << " unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned "
+ "Idx) const override;\n"
<< " const int *getRegClassPressureSets("
<< "const TargetRegisterClass *RC) const override;\n"
<< " const int *getRegUnitPressureSets("
@@ -1205,7 +1199,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Compress the sub-reg index lists.
typedef std::vector<const CodeGenSubRegIndex*> IdxList;
SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size());
- SequenceToOffsetTable<IdxList, CodeGenSubRegIndex::Less> SuperRegIdxSeqs;
+ SequenceToOffsetTable<IdxList, deref<llvm::less>> SuperRegIdxSeqs;
BitVector MaskBV(RegisterClasses.size());
for (const auto &RC : RegisterClasses) {
@@ -1292,7 +1286,10 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName()
<< "SubClassMask,\n SuperRegIdxSeqs + "
<< SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n "
- << format("0x%08x,\n ", RC.LaneMask);
+ << format("0x%08x,\n ", RC.LaneMask)
+ << (unsigned)RC.AllocationPriority << ",\n "
+ << (RC.HasDisjunctSubRegs?"true":"false")
+ << ", /* HasDisjunctSubRegs */\n ";
if (RC.getSuperClasses().empty())
OS << "NullRegClasses,\n ";
else
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 9f2fc929d96a0..de9c7a656a0d4 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCInstrItineraries.h"
+#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/TableGen/Error.h"
@@ -62,7 +63,7 @@ class SubtargetEmitter {
CodeGenSchedModels &SchedModels;
std::string Target;
- void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
+ void Enumeration(raw_ostream &OS, const char *ClassName);
unsigned FeatureKeyValues(raw_ostream &OS);
unsigned CPUKeyValues(raw_ostream &OS);
void FormItineraryStageString(const std::string &Names,
@@ -112,8 +113,7 @@ public:
// Enumeration - Emit the specified class as an enumeration.
//
void SubtargetEmitter::Enumeration(raw_ostream &OS,
- const char *ClassName,
- bool isBits) {
+ const char *ClassName) {
// Get all records of class and sort
std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
std::sort(DefList.begin(), DefList.end(), LessRecord());
@@ -121,50 +121,28 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS,
unsigned N = DefList.size();
if (N == 0)
return;
- if (N > 64) {
- errs() << "Too many (> 64) subtarget features!\n";
- exit(1);
- }
+ if (N > MAX_SUBTARGET_FEATURES)
+ PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
OS << "namespace " << Target << " {\n";
- // For bit flag enumerations with more than 32 items, emit constants.
- // Emit an enum for everything else.
- if (isBits && N > 32) {
- // For each record
- for (unsigned i = 0; i < N; i++) {
- // Next record
- Record *Def = DefList[i];
-
- // Get and emit name and expression (1 << i)
- OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
- }
- } else {
- // Open enumeration
- OS << "enum {\n";
-
- // For each record
- for (unsigned i = 0; i < N;) {
- // Next record
- Record *Def = DefList[i];
+ // Open enumeration. Use a 64-bit underlying type.
+ OS << "enum : uint64_t {\n";
- // Get and emit name
- OS << " " << Def->getName();
-
- // If bit flags then emit expression (1 << i)
- if (isBits) OS << " = " << " 1ULL << " << i;
-
- // Depending on 'if more in the list' emit comma
- if (++i < N) OS << ",";
+ // For each record
+ for (unsigned i = 0; i < N;) {
+ // Next record
+ Record *Def = DefList[i];
- OS << "\n";
- }
+ // Get and emit name
+ OS << " " << Def->getName() << " = " << i;
+ if (++i < N) OS << ",";
- // Close enumeration
- OS << "};\n";
+ OS << "\n";
}
- OS << "}\n";
+ // Close enumeration and namespace
+ OS << "};\n}\n";
}
//
@@ -198,22 +176,24 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
if (CommandLineName.empty()) continue;
- // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
+ // Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in } }
OS << " { "
<< "\"" << CommandLineName << "\", "
<< "\"" << Desc << "\", "
- << Target << "::" << Name << ", ";
+ << "{ " << Target << "::" << Name << " }, ";
const std::vector<Record*> &ImpliesList =
Feature->getValueAsListOfDefs("Implies");
if (ImpliesList.empty()) {
- OS << "0ULL";
+ OS << "{ }";
} else {
+ OS << "{ ";
for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
OS << Target << "::" << ImpliesList[j]->getName();
- if (++j < M) OS << " | ";
+ if (++j < M) OS << ", ";
}
+ OS << " }";
}
OS << " }";
@@ -255,22 +235,24 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
const std::vector<Record*> &FeatureList =
Processor->getValueAsListOfDefs("Features");
- // Emit as { "cpu", "description", f1 | f2 | ... fn },
+ // Emit as { "cpu", "description", { f1 , f2 , ... fn } },
OS << " { "
<< "\"" << Name << "\", "
<< "\"Select the " << Name << " processor\", ";
if (FeatureList.empty()) {
- OS << "0ULL";
+ OS << "{ }";
} else {
+ OS << "{ ";
for (unsigned j = 0, M = FeatureList.size(); j < M;) {
OS << Target << "::" << FeatureList[j]->getName();
- if (++j < M) OS << " | ";
+ if (++j < M) OS << ", ";
}
+ OS << " }";
}
- // The "0" is for the "implies" section of this data structure.
- OS << ", 0ULL }";
+ // The { } is for the "implies" section of this data structure.
+ OS << ", { } }";
// Depending on 'if more in the list' emit comma
if (++i < N) OS << ",";
@@ -404,7 +386,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
OS << "}\n";
std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
- if (BPs.size()) {
+ if (!BPs.empty()) {
OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
<< "\"\n" << "namespace " << Name << "Bypass {\n";
@@ -1398,7 +1380,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
}
OS << " InitMCProcessorInfo(CPU, FS);\n"
- << " uint64_t Bits = getFeatureBits();\n";
+ << " const FeatureBitset& Bits = getFeatureBits();\n";
for (unsigned i = 0; i < Features.size(); i++) {
// Next record
@@ -1408,12 +1390,12 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
const std::string &Attribute = R->getValueAsString("Attribute");
if (Value=="true" || Value=="false")
- OS << " if ((Bits & " << Target << "::"
- << Instance << ") != 0) "
+ OS << " if (Bits[" << Target << "::"
+ << Instance << "]) "
<< Attribute << " = " << Value << ";\n";
else
- OS << " if ((Bits & " << Target << "::"
- << Instance << ") != 0 && "
+ OS << " if (Bits[" << Target << "::"
+ << Instance << "] && "
<< Attribute << " < " << Value << ") "
<< Attribute << " = " << Value << ";\n";
}
@@ -1431,7 +1413,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "#undef GET_SUBTARGETINFO_ENUM\n";
OS << "namespace llvm {\n";
- Enumeration(OS, "SubtargetFeature", true);
+ Enumeration(OS, "SubtargetFeature");
OS << "} // End llvm namespace \n";
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
@@ -1487,6 +1469,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
OS << "#include \"llvm/Support/Debug.h\"\n";
+ OS << "#include \"llvm/Support/raw_ostream.h\"\n";
ParseFeaturesFunction(OS, NumFeatures, NumProcs);
OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
diff --git a/utils/TableGen/X86DisassemblerShared.h b/utils/TableGen/X86DisassemblerShared.h
index 58952776b7568..e5889e92415df 100644
--- a/utils/TableGen/X86DisassemblerShared.h
+++ b/utils/TableGen/X86DisassemblerShared.h
@@ -10,7 +10,7 @@
#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H
#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H
-#include <string.h>
+#include <cstring>
#include <string>
#include "../../lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h"
diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp
index fbe5502bc90e8..f59652c79e748 100644
--- a/utils/TableGen/X86DisassemblerTables.cpp
+++ b/utils/TableGen/X86DisassemblerTables.cpp
@@ -215,11 +215,17 @@ static inline bool inheritsFrom(InstructionContext child,
return inheritsFrom(child, IC_EVEX_W_K) ||
inheritsFrom(child, IC_EVEX_L_W_K);
case IC_EVEX_XS_K:
+ case IC_EVEX_XS_K_B:
+ case IC_EVEX_XS_KZ_B:
return inheritsFrom(child, IC_EVEX_W_XS_K) ||
inheritsFrom(child, IC_EVEX_L_W_XS_K);
case IC_EVEX_XD_K:
+ case IC_EVEX_XD_K_B:
+ case IC_EVEX_XD_KZ_B:
return inheritsFrom(child, IC_EVEX_W_XD_K) ||
inheritsFrom(child, IC_EVEX_L_W_XD_K);
+ case IC_EVEX_XS_B:
+ case IC_EVEX_XD_B:
case IC_EVEX_K_B:
case IC_EVEX_KZ:
return false;
@@ -253,17 +259,27 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_EVEX_W_KZ:
case IC_EVEX_W_XS_KZ:
case IC_EVEX_W_XD_KZ:
+ case IC_EVEX_W_XS_B:
+ case IC_EVEX_W_XD_B:
+ case IC_EVEX_W_XS_K_B:
+ case IC_EVEX_W_XD_K_B:
+ case IC_EVEX_W_XS_KZ_B:
+ case IC_EVEX_W_XD_KZ_B:
case IC_EVEX_W_OPSIZE_KZ:
case IC_EVEX_W_OPSIZE_KZ_B:
return false;
case IC_EVEX_L_KZ:
case IC_EVEX_L_XS_KZ:
+ case IC_EVEX_L_XS_B:
+ case IC_EVEX_L_XS_K_B:
case IC_EVEX_L_XD_KZ:
case IC_EVEX_L_OPSIZE_KZ:
case IC_EVEX_L_OPSIZE_KZ_B:
return false;
case IC_EVEX_L_W_K:
case IC_EVEX_L_W_XS_K:
+ case IC_EVEX_L_W_XS_B:
+ case IC_EVEX_L_W_XS_K_B:
case IC_EVEX_L_W_XD_K:
case IC_EVEX_L_W_OPSIZE_K:
case IC_EVEX_L_W_OPSIZE_B:
@@ -279,6 +295,7 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_EVEX_L2_K_B:
case IC_EVEX_L2_KZ_B:
case IC_EVEX_L2_XS_K:
+ case IC_EVEX_L2_XS_K_B:
case IC_EVEX_L2_XS_B:
case IC_EVEX_L2_XD_B:
case IC_EVEX_L2_XD_K:
@@ -294,6 +311,8 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_EVEX_L2_W_K:
case IC_EVEX_L2_W_B:
case IC_EVEX_L2_W_XS_K:
+ case IC_EVEX_L2_W_XS_B:
+ case IC_EVEX_L2_W_XS_K_B:
case IC_EVEX_L2_W_XD_K:
case IC_EVEX_L2_W_XD_B:
case IC_EVEX_L2_W_OPSIZE_K:
@@ -585,7 +604,8 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
o << "static const struct OperandSpecifier x86OperandSets[]["
<< X86_MAX_OPERANDS << "] = {\n";
- typedef std::vector<std::pair<const char *, const char *> > OperandListTy;
+ typedef SmallVector<std::pair<OperandEncoding, OperandType>,
+ X86_MAX_OPERANDS> OperandListTy;
std::map<OperandListTy, unsigned> OperandSets;
unsigned OperandSetNum = 0;
@@ -594,12 +614,10 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
++OperandIndex) {
- const char *Encoding =
- stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[Index]
- .operands[OperandIndex].encoding);
- const char *Type =
- stringForOperandType((OperandType)InstructionSpecifiers[Index]
- .operands[OperandIndex].type);
+ OperandEncoding Encoding = (OperandEncoding)InstructionSpecifiers[Index]
+ .operands[OperandIndex].encoding;
+ OperandType Type = (OperandType)InstructionSpecifiers[Index]
+ .operands[OperandIndex].type;
OperandList.push_back(std::make_pair(Encoding, Type));
}
unsigned &N = OperandSets[OperandList];
@@ -609,8 +627,9 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
o << " { /* " << (OperandSetNum - 1) << " */\n";
for (unsigned i = 0, e = OperandList.size(); i != e; ++i) {
- o << " { " << OperandList[i].first << ", "
- << OperandList[i].second << " },\n";
+ const char *Encoding = stringForOperandEncoding(OperandList[i].first);
+ const char *Type = stringForOperandType(OperandList[i].second);
+ o << " { " << Encoding << ", " << Type << " },\n";
}
o << " },\n";
}
@@ -622,32 +641,24 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
i++;
for (unsigned index = 0; index < NumInstructions; ++index) {
- o.indent(i * 2) << "{ /* " << index << " */" << "\n";
+ o.indent(i * 2) << "{ /* " << index << " */\n";
i++;
OperandListTy OperandList;
for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
++OperandIndex) {
- const char *Encoding =
- stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index]
- .operands[OperandIndex].encoding);
- const char *Type =
- stringForOperandType((OperandType)InstructionSpecifiers[index]
- .operands[OperandIndex].type);
+ OperandEncoding Encoding = (OperandEncoding)InstructionSpecifiers[index]
+ .operands[OperandIndex].encoding;
+ OperandType Type = (OperandType)InstructionSpecifiers[index]
+ .operands[OperandIndex].type;
OperandList.push_back(std::make_pair(Encoding, Type));
}
o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";
- o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */";
- o << "\n";
+ o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */\n";
i--;
- o.indent(i * 2) << "}";
-
- if (index + 1 < NumInstructions)
- o << ",";
-
- o << "\n";
+ o.indent(i * 2) << "},\n";
}
i--;
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index 198ad1090493b..ae461bcfbc880 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -28,54 +28,65 @@ using namespace llvm;
MAP(C2, 34) \
MAP(C3, 35) \
MAP(C4, 36) \
- MAP(C8, 37) \
- MAP(C9, 38) \
- MAP(CA, 39) \
- MAP(CB, 40) \
- MAP(CF, 41) \
- MAP(D0, 42) \
- MAP(D1, 43) \
- MAP(D4, 44) \
- MAP(D5, 45) \
- MAP(D6, 46) \
- MAP(D7, 47) \
- MAP(D8, 48) \
- MAP(D9, 49) \
- MAP(DA, 50) \
- MAP(DB, 51) \
- MAP(DC, 52) \
- MAP(DD, 53) \
- MAP(DE, 54) \
- MAP(DF, 55) \
- MAP(E0, 56) \
- MAP(E1, 57) \
- MAP(E2, 58) \
- MAP(E3, 59) \
- MAP(E4, 60) \
- MAP(E5, 61) \
- MAP(E8, 62) \
- MAP(E9, 63) \
- MAP(EA, 64) \
- MAP(EB, 65) \
- MAP(EC, 66) \
- MAP(ED, 67) \
- MAP(EE, 68) \
- MAP(F0, 69) \
- MAP(F1, 70) \
- MAP(F2, 71) \
- MAP(F3, 72) \
- MAP(F4, 73) \
- MAP(F5, 74) \
- MAP(F6, 75) \
- MAP(F7, 76) \
- MAP(F8, 77) \
- MAP(F9, 78) \
- MAP(FA, 79) \
- MAP(FB, 80) \
- MAP(FC, 81) \
- MAP(FD, 82) \
- MAP(FE, 83) \
- MAP(FF, 84)
+ MAP(C5, 37) \
+ MAP(C6, 38) \
+ MAP(C7, 39) \
+ MAP(C8, 40) \
+ MAP(C9, 41) \
+ MAP(CA, 42) \
+ MAP(CB, 43) \
+ MAP(CC, 44) \
+ MAP(CD, 45) \
+ MAP(CE, 46) \
+ MAP(CF, 47) \
+ MAP(D0, 48) \
+ MAP(D1, 49) \
+ MAP(D2, 50) \
+ MAP(D3, 51) \
+ MAP(D4, 52) \
+ MAP(D5, 53) \
+ MAP(D6, 54) \
+ MAP(D7, 55) \
+ MAP(D8, 56) \
+ MAP(D9, 57) \
+ MAP(DA, 58) \
+ MAP(DB, 59) \
+ MAP(DC, 60) \
+ MAP(DD, 61) \
+ MAP(DE, 62) \
+ MAP(DF, 63) \
+ MAP(E0, 64) \
+ MAP(E1, 65) \
+ MAP(E2, 66) \
+ MAP(E3, 67) \
+ MAP(E4, 68) \
+ MAP(E5, 69) \
+ MAP(E6, 70) \
+ MAP(E7, 71) \
+ MAP(E8, 72) \
+ MAP(E9, 73) \
+ MAP(EA, 74) \
+ MAP(EB, 75) \
+ MAP(EC, 76) \
+ MAP(ED, 77) \
+ MAP(EE, 78) \
+ MAP(EF, 79) \
+ MAP(F0, 80) \
+ MAP(F1, 81) \
+ MAP(F2, 82) \
+ MAP(F3, 83) \
+ MAP(F4, 84) \
+ MAP(F5, 85) \
+ MAP(F6, 86) \
+ MAP(F7, 87) \
+ MAP(F8, 88) \
+ MAP(F9, 89) \
+ MAP(FA, 90) \
+ MAP(FB, 91) \
+ MAP(FC, 92) \
+ MAP(FD, 93) \
+ MAP(FE, 94) \
+ MAP(FF, 95)
// A clone of X86 since we can't depend on something that is generated.
namespace X86Local {
@@ -514,7 +525,7 @@ void RecognizableInstr::emitInstructionSpecifier() {
assert(numOperands <= X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough");
for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
- if (OperandList[operandIndex].Constraints.size()) {
+ if (!OperandList[operandIndex].Constraints.empty()) {
const CGIOperandList::ConstraintInfo &Constraint =
OperandList[operandIndex].Constraints[0];
if (Constraint.isTied()) {
@@ -803,9 +814,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
// Special cases where the LLVM tables are not complete
#define MAP(from, to) \
- case X86Local::MRM_##from: \
- filter = new ExactFilter(0x##from); \
- break;
+ case X86Local::MRM_##from:
OpcodeType opcodeType = (OpcodeType)-1;
@@ -854,6 +863,8 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
break;
MRM_MAPPING
+ filter = new ExactFilter(0xC0 + Form - X86Local::MRM_C0); \
+ break;
} // switch (Form)
opcodeToSet = Opcode;
@@ -932,6 +943,8 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("GR64", TYPE_R64)
TYPE("i8mem", TYPE_M8)
TYPE("i8imm", TYPE_IMM8)
+ TYPE("u8imm", TYPE_UIMM8)
+ TYPE("i32u8imm", TYPE_UIMM8)
TYPE("GR8", TYPE_R8)
TYPE("VR128", TYPE_XMM128)
TYPE("VR128X", TYPE_XMM128)
@@ -954,7 +967,9 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("i16imm_pcrel", TYPE_REL16)
TYPE("i32imm_pcrel", TYPE_REL32)
TYPE("SSECC", TYPE_IMM3)
+ TYPE("XOPCC", TYPE_IMM3)
TYPE("AVXCC", TYPE_IMM5)
+ TYPE("AVX512ICC", TYPE_AVX512ICC)
TYPE("AVX512RC", TYPE_IMM32)
TYPE("brtarget32", TYPE_RELv)
TYPE("brtarget16", TYPE_RELv)
@@ -1034,7 +1049,9 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s,
}
ENCODING("i32i8imm", ENCODING_IB)
ENCODING("SSECC", ENCODING_IB)
+ ENCODING("XOPCC", ENCODING_IB)
ENCODING("AVXCC", ENCODING_IB)
+ ENCODING("AVX512ICC", ENCODING_IB)
ENCODING("AVX512RC", ENCODING_IB)
ENCODING("i16imm", ENCODING_Iv)
ENCODING("i16i8imm", ENCODING_IB)
@@ -1042,6 +1059,8 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s,
ENCODING("i64i32imm", ENCODING_ID)
ENCODING("i64i8imm", ENCODING_IB)
ENCODING("i8imm", ENCODING_IB)
+ ENCODING("u8imm", ENCODING_IB)
+ ENCODING("i32u8imm", ENCODING_IB)
// This is not a typo. Instructions like BLENDVPD put
// register IDs in 8-bit immediates nowadays.
ENCODING("FR32", ENCODING_IB)
@@ -1077,6 +1096,8 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s,
ENCODING("VR256X", ENCODING_RM)
ENCODING("VR512", ENCODING_RM)
ENCODING("VK1", ENCODING_RM)
+ ENCODING("VK2", ENCODING_RM)
+ ENCODING("VK4", ENCODING_RM)
ENCODING("VK8", ENCODING_RM)
ENCODING("VK16", ENCODING_RM)
ENCODING("VK32", ENCODING_RM)
@@ -1114,8 +1135,12 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s,
ENCODING("VK32", ENCODING_REG)
ENCODING("VK64", ENCODING_REG)
ENCODING("VK1WM", ENCODING_REG)
+ ENCODING("VK2WM", ENCODING_REG)
+ ENCODING("VK4WM", ENCODING_REG)
ENCODING("VK8WM", ENCODING_REG)
ENCODING("VK16WM", ENCODING_REG)
+ ENCODING("VK32WM", ENCODING_REG)
+ ENCODING("VK64WM", ENCODING_REG)
errs() << "Unhandled reg/opcode register encoding " << s << "\n";
llvm_unreachable("Unhandled reg/opcode register encoding");
}
@@ -1210,6 +1235,8 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s,
ENCODING("i64i32imm", ENCODING_ID)
ENCODING("i64i8imm", ENCODING_IB)
ENCODING("i8imm", ENCODING_IB)
+ ENCODING("u8imm", ENCODING_IB)
+ ENCODING("i32u8imm", ENCODING_IB)
ENCODING("i64i32imm_pcrel", ENCODING_ID)
ENCODING("i16imm_pcrel", ENCODING_IW)
ENCODING("i32imm_pcrel", ENCODING_ID)
diff --git a/utils/create_ladder_graph.py b/utils/create_ladder_graph.py
new file mode 100644
index 0000000000000..d29e3ad3a10d1
--- /dev/null
+++ b/utils/create_ladder_graph.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+"""A ladder graph creation program.
+
+This is a python program that creates c source code that will generate
+CFGs that are ladder graphs. Ladder graphs are generally the worst case
+for a lot of dominance related algorithms (Dominance frontiers, etc),
+and often generate N^2 or worse behavior.
+
+One good use of this program is to test whether your linear time algorithm is
+really behaving linearly.
+"""
+
+import argparse
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('rungs', type=int,
+ help="Number of ladder rungs. Must be a multiple of 2")
+ args = parser.parse_args()
+ if (args.rungs % 2) != 0:
+ print "Rungs must be a multiple of 2"
+ return
+ print "int ladder(int *foo, int *bar, int x) {"
+ rung1 = xrange(0, args.rungs, 2)
+ rung2 = xrange(1, args.rungs, 2)
+ for i in rung1:
+ print "rung1%d:" % i
+ print "*foo = x++;"
+ if i != rung1[-1]:
+ print "if (*bar) goto rung1%d;" % (i+2)
+ print "else goto rung2%d;" % (i+1)
+ else:
+ print "goto rung2%d;" % (i+1)
+ for i in rung2:
+ print "rung2%d:" % i
+ print "*foo = x++;"
+ if i != rung2[-1]:
+ print "goto rung2%d;" % (i+2)
+ else:
+ print "return *foo;"
+ print "}"
+
+if __name__ == '__main__':
+ main()
diff --git a/utils/emacs/emacs.el b/utils/emacs/emacs.el
index 2ebc3c677cef7..4a3a5031026a1 100644
--- a/utils/emacs/emacs.el
+++ b/utils/emacs/emacs.el
@@ -1,34 +1,22 @@
;; LLVM coding style guidelines in emacs
;; Maintainer: LLVM Team, http://llvm.org/
-;; Add a cc-mode style for editing LLVM C++ code
+;; Add a cc-mode style for editing LLVM C and C++ code
(c-add-style "llvm.org"
- '((fill-column . 80)
+ '("gnu"
+ (fill-column . 80)
(c++-indent-level . 2)
(c-basic-offset . 2)
(indent-tabs-mode . nil)
(c-offsets-alist . ((arglist-intro . ++)
(innamespace . 0)
- (member-init-intro . ++)
- ))
- ))
+ (member-init-intro . ++)))))
;; Files with "llvm" in their names will automatically be set to the
;; llvm.org coding style.
-(add-hook 'c-mode-hook
+(add-hook 'c-mode-common-hook
(function
(lambda nil
(if (string-match "llvm" buffer-file-name)
(progn
- (c-set-style "llvm.org")
- )
- ))))
-
-(add-hook 'c++-mode-hook
- (function
- (lambda nil
- (if (string-match "llvm" buffer-file-name)
- (progn
- (c-set-style "llvm.org")
- )
- ))))
+ (c-set-style "llvm.org"))))))
diff --git a/utils/emacs/llvm-mode.el b/utils/emacs/llvm-mode.el
index 6d8395cc111b8..5fb1eb38cc62d 100644
--- a/utils/emacs/llvm-mode.el
+++ b/utils/emacs/llvm-mode.el
@@ -23,7 +23,7 @@
;; Unnamed variable slots
'("%[-]?[0-9]+" . font-lock-variable-name-face)
;; Types
- `(,(regexp-opt '("void" "i[0-9]+" "float" "double" "type" "label" "opaque") 'words) . font-lock-type-face)
+ `(,(regexp-opt '("void" "i1" "i8" "i16" "i32" "i64" "i128" "float" "double" "type" "label" "opaque") 'symbol) . font-lock-type-face)
;; Integer literals
'("\\b[-]?[0-9]+\\b" . font-lock-preprocessor-face)
;; Floating point constants
@@ -35,28 +35,28 @@
"define" "global" "constant" "const" "internal" "linkonce" "linkonce_odr"
"weak" "weak_odr" "appending" "uninitialized" "implementation" "..."
"null" "undef" "to" "except" "not" "target" "endian" "little" "big"
- "pointersize" "volatile" "fastcc" "coldcc" "cc") 'words) . font-lock-keyword-face)
+ "pointersize" "volatile" "fastcc" "coldcc" "cc" "personality") 'symbols) . font-lock-keyword-face)
;; Arithmetic and Logical Operators
`(,(regexp-opt '("add" "sub" "mul" "sdiv" "udiv" "urem" "srem" "and" "or" "xor"
- "setne" "seteq" "setlt" "setgt" "setle" "setge") 'words) . font-lock-keyword-face)
+ "setne" "seteq" "setlt" "setgt" "setle" "setge") 'symbols) . font-lock-keyword-face)
;; Floating-point operators
- `(,(regexp-opt '("fadd" "fsub" "fmul" "fdiv" "frem") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("fadd" "fsub" "fmul" "fdiv" "frem") 'symbols) . font-lock-keyword-face)
;; Special instructions
- `(,(regexp-opt '("phi" "tail" "call" "select" "to" "shl" "lshr" "ashr" "fcmp" "icmp" "va_arg" "landingpad") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("phi" "tail" "call" "select" "to" "shl" "lshr" "ashr" "fcmp" "icmp" "va_arg" "landingpad") 'symbols) . font-lock-keyword-face)
;; Control instructions
- `(,(regexp-opt '("ret" "br" "switch" "invoke" "resume" "unwind" "unreachable" "indirectbr") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("ret" "br" "switch" "invoke" "resume" "unwind" "unreachable" "indirectbr") 'symbols) . font-lock-keyword-face)
;; Memory operators
- `(,(regexp-opt '("malloc" "alloca" "free" "load" "store" "getelementptr" "fence" "cmpxchg" "atomicrmw") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("malloc" "alloca" "free" "load" "store" "getelementptr" "fence" "cmpxchg" "atomicrmw") 'symbols) . font-lock-keyword-face)
;; Casts
- `(,(regexp-opt '("bitcast" "inttoptr" "ptrtoint" "trunc" "zext" "sext" "fptrunc" "fpext" "fptoui" "fptosi" "uitofp" "sitofp" "addrspacecast") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("bitcast" "inttoptr" "ptrtoint" "trunc" "zext" "sext" "fptrunc" "fpext" "fptoui" "fptosi" "uitofp" "sitofp" "addrspacecast") 'symbols) . font-lock-keyword-face)
;; Vector ops
- `(,(regexp-opt '("extractelement" "insertelement" "shufflevector") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("extractelement" "insertelement" "shufflevector") 'symbols) . font-lock-keyword-face)
;; Aggregate ops
- `(,(regexp-opt '("extractvalue" "insertvalue") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("extractvalue" "insertvalue") 'symbols) . font-lock-keyword-face)
;; Metadata types
- `(,(regexp-opt '("distinct") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("distinct") 'symbols) . font-lock-keyword-face)
;; Use-list order directives
- `(,(regexp-opt '("uselistorder" "uselistorder_bb") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("uselistorder" "uselistorder_bb") 'symbols) . font-lock-keyword-face)
)
"Syntax highlighting for LLVM."
@@ -83,7 +83,7 @@
;; word constituents (`w')
;;[?< "w"]
;;[?> "w"]
- [?\% "w"]
+ [?% "w"]
;;[?_ "w "]
;; comments
[?\; "< "]
@@ -93,16 +93,9 @@
;; symbol constituents (`_')
;; punctuation (`.')
;; open paren (`(')
- [?\( "("]
- [?\[ "("]
- [?\{ "("]
;; close paren (`)')
- [?\) ")"]
- [?\] ")"]
- [?\} ")"]
;; string quote ('"')
- [?\" "\""]
- ))))
+ [?\" "\""]))))
;; --------------------- Abbrev table -----------------------------
diff --git a/utils/git-svn/git-svnrevert b/utils/git-svn/git-svnrevert
index f15e7abfb3f10..4185ee7ae87af 100755
--- a/utils/git-svn/git-svnrevert
+++ b/utils/git-svn/git-svnrevert
@@ -14,8 +14,13 @@ fi
COMMIT=$1
OTHER=$(git svn find-rev "$COMMIT")
-if [ $? -ne 0 ]; then
+if [ $? -ne 0 ] || [ "$OTHER" = "" ]; then
echo "Error! Could not find an svn/git revision for commit $COMMIT!"
+ echo
+ echo "Possible problems are:"
+ echo " * Your revision number ($COMMIT) is wrong"
+ echo " * This tree is not up to date (before that commit)"
+ echo " * This commit in in another three (llvm, clang, compiler-rt, etc)"
exit 1
fi
diff --git a/utils/lit/lit/LitConfig.py b/utils/lit/lit/LitConfig.py
index b0dde5db86868..b8183801bfca7 100644
--- a/utils/lit/lit/LitConfig.py
+++ b/utils/lit/lit/LitConfig.py
@@ -76,7 +76,6 @@ class LitConfig:
self.bashPath = lit.util.which('bash')
if self.bashPath is None:
- self.warning("Unable to find 'bash'.")
self.bashPath = ''
return self.bashPath
@@ -91,7 +90,6 @@ class LitConfig:
# bash
self.bashPath = lit.util.which('bash', dir)
if self.bashPath is None:
- self.note("Unable to find 'bash.exe'.")
self.bashPath = ''
return dir
diff --git a/utils/lit/lit/Test.py b/utils/lit/lit/Test.py
index b81023010d70a..38bb41b0252d5 100644
--- a/utils/lit/lit/Test.py
+++ b/utils/lit/lit/Test.py
@@ -91,7 +91,8 @@ class JSONMetricValue(MetricValue):
self.value = value
def format(self):
- return str(self.value)
+ e = JSONEncoder(indent=2, sort_keys=True)
+ return e.encode(self.value)
def todata(self):
return self.value
diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py
index 268e46c38f744..f1734eca37263 100644
--- a/utils/lit/lit/TestRunner.py
+++ b/utils/lit/lit/TestRunner.py
@@ -22,33 +22,56 @@ kUseCloseFDs = not kIsWindows
# Use temporary files to replace /dev/null on Windows.
kAvoidDevNull = kIsWindows
-def executeShCmd(cmd, cfg, cwd, results):
+class ShellEnvironment(object):
+
+ """Mutable shell environment containing things like CWD and env vars.
+
+ Environment variables are not implemented, but cwd tracking is.
+ """
+
+ def __init__(self, cwd, env):
+ self.cwd = cwd
+ self.env = env
+
+def executeShCmd(cmd, shenv, results):
if isinstance(cmd, ShUtil.Seq):
if cmd.op == ';':
- res = executeShCmd(cmd.lhs, cfg, cwd, results)
- return executeShCmd(cmd.rhs, cfg, cwd, results)
+ res = executeShCmd(cmd.lhs, shenv, results)
+ return executeShCmd(cmd.rhs, shenv, results)
if cmd.op == '&':
raise InternalShellError(cmd,"unsupported shell operator: '&'")
if cmd.op == '||':
- res = executeShCmd(cmd.lhs, cfg, cwd, results)
+ res = executeShCmd(cmd.lhs, shenv, results)
if res != 0:
- res = executeShCmd(cmd.rhs, cfg, cwd, results)
+ res = executeShCmd(cmd.rhs, shenv, results)
return res
if cmd.op == '&&':
- res = executeShCmd(cmd.lhs, cfg, cwd, results)
+ res = executeShCmd(cmd.lhs, shenv, results)
if res is None:
return res
if res == 0:
- res = executeShCmd(cmd.rhs, cfg, cwd, results)
+ res = executeShCmd(cmd.rhs, shenv, results)
return res
raise ValueError('Unknown shell command: %r' % cmd.op)
-
assert isinstance(cmd, ShUtil.Pipeline)
+
+ # Handle shell builtins first.
+ if cmd.commands[0].args[0] == 'cd':
+ # Update the cwd in the environment.
+ if len(cmd.commands[0].args) != 2:
+ raise ValueError('cd supports only one argument')
+ newdir = cmd.commands[0].args[1]
+ if os.path.isabs(newdir):
+ shenv.cwd = newdir
+ else:
+ shenv.cwd = os.path.join(shenv.cwd, newdir)
+ return 0
+
procs = []
input = subprocess.PIPE
stderrTempFiles = []
@@ -102,7 +125,9 @@ def executeShCmd(cmd, cfg, cwd, results):
if kAvoidDevNull and r[0] == '/dev/null':
r[2] = tempfile.TemporaryFile(mode=r[1])
else:
- r[2] = open(r[0], r[1])
+ # Make sure relative paths are relative to the cwd.
+ redir_filename = os.path.join(shenv.cwd, r[0])
+ r[2] = open(redir_filename, r[1])
# Workaround a Win32 and/or subprocess bug when appending.
#
# FIXME: Actually, this is probably an instance of PR6753.
@@ -132,7 +157,7 @@ def executeShCmd(cmd, cfg, cwd, results):
# Resolve the executable path ourselves.
args = list(j.args)
- executable = lit.util.which(args[0], cfg.environment['PATH'])
+ executable = lit.util.which(args[0], shenv.env['PATH'])
if not executable:
raise InternalShellError(j, '%r: command not found' % j.args[0])
@@ -146,12 +171,12 @@ def executeShCmd(cmd, cfg, cwd, results):
args[i] = f.name
try:
- procs.append(subprocess.Popen(args, cwd=cwd,
+ procs.append(subprocess.Popen(args, cwd=shenv.cwd,
executable = executable,
stdin = stdin,
stdout = stdout,
stderr = stderr,
- env = cfg.environment,
+ env = shenv.env,
close_fds = kUseCloseFDs))
except OSError as e:
raise InternalShellError(j, 'Could not create process due to {}'.format(e))
@@ -257,7 +282,8 @@ def executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
results = []
try:
- exitCode = executeShCmd(cmd, test.config, cwd, results)
+ shenv = ShellEnvironment(cwd, test.config.environment)
+ exitCode = executeShCmd(cmd, shenv, results)
except InternalShellError:
e = sys.exc_info()[1]
exitCode = 127
diff --git a/utils/lit/lit/formats/googletest.py b/utils/lit/lit/formats/googletest.py
index 59ac3c5cb3700..3ce57917113aa 100644
--- a/utils/lit/lit/formats/googletest.py
+++ b/utils/lit/lit/formats/googletest.py
@@ -53,6 +53,11 @@ class GoogleTest(TestFormat):
ln = ln[index*2:]
if ln.endswith('.'):
nested_tests.append(ln)
+ elif any([name.startswith('DISABLED_')
+ for name in nested_tests + [ln]]):
+ # Gtest will internally skip these tests. No need to launch a
+ # child process for it.
+ continue
else:
yield ''.join(nested_tests) + ln
@@ -95,7 +100,7 @@ class GoogleTest(TestFormat):
# Handle GTest parametrized and typed tests, whose name includes
# some '/'s.
testPath, namePrefix = os.path.split(testPath)
- testName = os.path.join(namePrefix, testName)
+ testName = namePrefix + '/' + testName
cmd = [testPath, '--gtest_filter=' + testName]
if litConfig.useValgrind:
@@ -107,7 +112,14 @@ class GoogleTest(TestFormat):
out, err, exitCode = lit.util.executeCommand(
cmd, env=test.config.environment)
- if not exitCode:
- return lit.Test.PASS,''
+ if exitCode:
+ return lit.Test.FAIL, out + err
+
+ passing_test_line = '[ PASSED ] 1 test.'
+ if passing_test_line not in out:
+ msg = ('Unable to find %r in gtest output:\n\n%s%s' %
+ (passing_test_line, out, err))
+ return lit.Test.UNRESOLVED, msg
+
+ return lit.Test.PASS,''
- return lit.Test.FAIL, out + err
diff --git a/utils/lit/lit/main.py b/utils/lit/lit/main.py
index f2aedc906bb15..e3722674f63f2 100755
--- a/utils/lit/lit/main.py
+++ b/utils/lit/lit/main.py
@@ -146,7 +146,7 @@ def main(builtinParameters = {}):
parser.add_option("", "--config-prefix", dest="configPrefix",
metavar="NAME", help="Prefix for 'lit' config files",
action="store", default=None)
- parser.add_option("", "--param", dest="userParameters",
+ parser.add_option("-D", "--param", dest="userParameters",
metavar="NAME=VAL",
help="Add 'NAME' = 'VAL' to the user defined parameters",
type=str, action="append", default=[])
diff --git a/utils/lit/utils/check-coverage b/utils/lit/utils/check-coverage
index 128e827f22dcb..cded7a2921c55 100755
--- a/utils/lit/utils/check-coverage
+++ b/utils/lit/utils/check-coverage
@@ -23,7 +23,7 @@ fi
# sitecustomize.
if ! python -c \
'import sitecustomize, sys; sys.exit("coverage" not in dir(sitecustomize))' \
- &> /dev/null; then
+ >/dev/null 2>&1; then
printf 1>&2 "error: active python does not appear to enable coverage in its 'sitecustomize.py'\n"
exit 1
fi
diff --git a/utils/lldbDataFormatters.py b/utils/lldbDataFormatters.py
index f570fb49f3473..687729f61eddd 100644
--- a/utils/lldbDataFormatters.py
+++ b/utils/lldbDataFormatters.py
@@ -15,6 +15,9 @@ def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand('type synthetic add -w llvm '
'-l lldbDataFormatters.ArrayRefSynthProvider '
'-x "^llvm::ArrayRef<.+>$"')
+ debugger.HandleCommand('type summary add -w llvm '
+ '-F lldbDataFormatters.OptionalSummaryProvider '
+ '-x "^llvm::Optional<.+>$"')
# Pretty printer for llvm::SmallVector/llvm::SmallVectorImpl
class SmallVectorSynthProvider:
@@ -86,3 +89,10 @@ class ArrayRefSynthProvider:
self.data_type = self.data.GetType().GetPointeeType()
self.type_size = self.data_type.GetByteSize()
assert self.type_size != 0
+
+def OptionalSummaryProvider(valobj, internal_dict):
+ if not valobj.GetChildMemberWithName('hasVal').GetValueAsUnsigned(0):
+ return 'None'
+ underlying_type = valobj.GetType().GetTemplateArgumentType(0)
+ storage = valobj.GetChildMemberWithName('storage')
+ return str(storage.Cast(underlying_type))
diff --git a/utils/release/export.sh b/utils/release/export.sh
index 38e5a819c01d0..9aee306f96645 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 libcxxabi clang-tools-extra polly lldb lld openmp"
+projects="llvm cfe test-suite compiler-rt libcxx libcxxabi clang-tools-extra polly lldb lld openmp"
base_url="https://llvm.org/svn/llvm-project"
release=""
@@ -79,5 +79,8 @@ if [ "x$release" = "x" ]; then
exit 1
fi
+# Make sure umask is not overly restrictive.
+umask 0022
+
export_sources
exit 0
diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh
index 20f8d97ebc0d7..89519c47e35b6 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 libcxxabi test-suite clang-tools-extra"
+projects="llvm cfe compiler-rt libcxx libcxxabi test-suite clang-tools-extra"
# Base SVN URL for the sources.
Base_url="http://llvm.org/svn/llvm-project"
@@ -29,11 +29,7 @@ RC=""
Triple=""
use_gzip="no"
do_checkout="yes"
-do_ada="no"
do_clang="yes"
-do_dragonegg="no"
-do_fortran="no"
-do_objc="yes"
do_64bit="yes"
do_debug="no"
do_asserts="no"
@@ -54,7 +50,6 @@ function usage() {
echo " -no-64bit Don't test the 64-bit version. [default: yes]"
echo " -enable-ada Build Ada. [default: disable]"
echo " -disable-clang Do not test clang. [default: enable]"
- echo " -enable-dragonegg Test dragonegg. [default: disable]"
echo " -enable-fortran Enable Fortran build. [default: disable]"
echo " -disable-objc Disable ObjC build. [default: enable]"
echo " -test-debug Test the debug build. [default: no]"
@@ -104,21 +99,9 @@ while [ $# -gt 0 ]; do
-no-64bit | --no-64bit )
do_64bit="no"
;;
- -enable-ada | --enable-ada )
- do_ada="yes"
- ;;
-disable-clang | --disable-clang )
do_clang="no"
;;
- -enable-dragonegg | --enable-dragonegg )
- do_dragonegg="yes"
- ;;
- -enable-fortran | --enable-fortran )
- do_fortran="yes"
- ;;
- -disable-objc | --disable-objc )
- do_objc="no"
- ;;
-test-debug | --test-debug )
do_debug="yes"
;;
@@ -188,27 +171,6 @@ if [ $RC != "final" ]; then
fi
Package=$Package-$Triple
-# Find compilers.
-if [ "$do_dragonegg" = "yes" ]; then
- gcc_compiler="$GCC"
- if [ -z "$gcc_compiler" ]; then
- gcc_compiler="`which gcc`"
- if [ -z "$gcc_compiler" ]; then
- echo "error: cannot find gcc to use with dragonegg"
- exit 1
- fi
- fi
-
- gxx_compiler="$GXX"
- if [ -z "$gxx_compiler" ]; then
- gxx_compiler="`which g++`"
- if [ -z "$gxx_compiler" ]; then
- echo "error: cannot find g++ to use with dragonegg"
- exit 1
- fi
- fi
-fi
-
# Make sure that a required program is available
function check_program_exists() {
local program="$1"
@@ -344,28 +306,6 @@ function build_llvmCore() {
cd $BuildDir
}
-function build_dragonegg() {
- Phase="$1"
- Flavor="$2"
- LLVMInstallDir="$3"
- DragonEggObjDir="$4"
- LLVM_CONFIG=$LLVMInstallDir/bin/llvm-config
- TOP_DIR=$BuildDir/dragonegg.src
-
- echo "# Targeted compiler: $gcc_compiler"
-
- cd $DragonEggObjDir
- echo "# Compiling phase $Phase dragonegg $Release-$RC $Flavor"
- echo -n "# CXX=$cxx_compiler TOP_DIR=$TOP_DIR GCC=$gcc_compiler "
- echo -n "LLVM_CONFIG=$LLVM_CONFIG ${MAKE} -f $TOP_DIR/Makefile "
- echo "-j $NumJobs VERBOSE=1"
- CXX="$cxx_compiler" TOP_DIR="$TOP_DIR" GCC="$gcc_compiler" \
- LLVM_CONFIG="$LLVM_CONFIG" ${MAKE} -f $TOP_DIR/Makefile \
- -j $NumJobs VERBOSE=1 \
- 2>&1 | tee $LogDir/dragonegg-Phase$Phase-$Flavor.log
- cd $BuildDir
-}
-
function test_llvmCore() {
Phase="$1"
Flavor="$2"
@@ -445,51 +385,42 @@ for Flavor in $Flavors ; do
llvmCore_phase1_objdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.obj
llvmCore_phase1_installdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.install
- dragonegg_phase1_objdir=$BuildDir/Phase1/$Flavor/DragonEgg-$Release-$RC.obj
llvmCore_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.obj
llvmCore_phase2_installdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.install
llvmCore_de_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmCore-DragonEgg-$Release-$RC.obj
llvmCore_de_phase2_installdir=$BuildDir/Phase2/$Flavor/llvmCore-DragonEgg-$Release-$RC.install
- dragonegg_phase2_objdir=$BuildDir/Phase2/$Flavor/DragonEgg-$Release-$RC.obj
llvmCore_phase3_objdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.obj
llvmCore_phase3_installdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.install
llvmCore_de_phase3_objdir=$BuildDir/Phase3/$Flavor/llvmCore-DragonEgg-$Release-$RC.obj
llvmCore_de_phase3_installdir=$BuildDir/Phase3/$Flavor/llvmCore-DragonEgg-$Release-$RC.install
- dragonegg_phase3_objdir=$BuildDir/Phase3/$Flavor/DragonEgg-$Release-$RC.obj
rm -rf $llvmCore_phase1_objdir
rm -rf $llvmCore_phase1_installdir
- rm -rf $dragonegg_phase1_objdir
rm -rf $llvmCore_phase2_objdir
rm -rf $llvmCore_phase2_installdir
rm -rf $llvmCore_de_phase2_objdir
rm -rf $llvmCore_de_phase2_installdir
- rm -rf $dragonegg_phase2_objdir
rm -rf $llvmCore_phase3_objdir
rm -rf $llvmCore_phase3_installdir
rm -rf $llvmCore_de_phase3_objdir
rm -rf $llvmCore_de_phase3_installdir
- rm -rf $dragonegg_phase3_objdir
mkdir -p $llvmCore_phase1_objdir
mkdir -p $llvmCore_phase1_installdir
- mkdir -p $dragonegg_phase1_objdir
mkdir -p $llvmCore_phase2_objdir
mkdir -p $llvmCore_phase2_installdir
mkdir -p $llvmCore_de_phase2_objdir
mkdir -p $llvmCore_de_phase2_installdir
- mkdir -p $dragonegg_phase2_objdir
mkdir -p $llvmCore_phase3_objdir
mkdir -p $llvmCore_phase3_installdir
mkdir -p $llvmCore_de_phase3_objdir
mkdir -p $llvmCore_de_phase3_installdir
- mkdir -p $dragonegg_phase3_objdir
############################################################################
# Phase 1: Build llvmCore and clang
@@ -544,62 +475,8 @@ for Flavor in $Flavors ; do
fi
fi
- # Test dragonegg
- if [ "$do_dragonegg" = "yes" ]; then
- # Build dragonegg using the targeted gcc. This isn't necessary, but
- # helps avoid using broken versions of gcc (which are legion), tests
- # that the targeted gcc is basically sane and is consistent with the
- # later phases in which the targeted gcc + dragonegg are used.
- c_compiler="$gcc_compiler"
- cxx_compiler="$gxx_compiler"
- build_dragonegg 1 $Flavor $llvmCore_phase1_installdir $dragonegg_phase1_objdir
-
- ########################################################################
- # Phase 2: Build llvmCore with newly built dragonegg from phase 1.
- c_compiler="$gcc_compiler -fplugin=$dragonegg_phase1_objdir/dragonegg.so"
- cxx_compiler="$gxx_compiler -fplugin=$dragonegg_phase1_objdir/dragonegg.so"
- echo "# Phase 2: Building llvmCore with dragonegg"
- configure_llvmCore 2 $Flavor \
- $llvmCore_de_phase2_objdir $llvmCore_de_phase2_installdir
- build_llvmCore 2 $Flavor \
- $llvmCore_de_phase2_objdir
- build_dragonegg 2 $Flavor $llvmCore_de_phase2_installdir $dragonegg_phase2_objdir
- clean_RPATH $llvmCore_de_phase2_installdir
-
- ########################################################################
- # Phase 3: Build llvmCore with newly built dragonegg from phase 2.
- c_compiler="$gcc_compiler -fplugin=$dragonegg_phase2_objdir/dragonegg.so"
- cxx_compiler="$gxx_compiler -fplugin=$dragonegg_phase2_objdir/dragonegg.so"
- echo "# Phase 3: Building llvmCore with dragonegg"
- configure_llvmCore 3 $Flavor \
- $llvmCore_de_phase3_objdir $llvmCore_de_phase3_installdir
- build_llvmCore 3 $Flavor \
- $llvmCore_de_phase3_objdir
- build_dragonegg 3 $Flavor $llvmCore_de_phase3_installdir $dragonegg_phase3_objdir
- clean_RPATH $llvmCore_de_phase3_installdir
-
- ########################################################################
- # Testing: Test phase 3
- c_compiler="$gcc_compiler -fplugin=$dragonegg_phase3_objdir/dragonegg.so"
- cxx_compiler="$gxx_compiler -fplugin=$dragonegg_phase3_objdir/dragonegg.so"
- echo "# Testing - built with dragonegg"
- test_llvmCore 3 $Flavor $llvmCore_de_phase3_objdir
-
- ########################################################################
- # Compare .o files between Phase2 and Phase3 and report which ones differ.
- echo
- echo "# Comparing Phase 2 and Phase 3 files"
- for o in `find $llvmCore_de_phase2_objdir -name '*.o'` \
- `find $dragonegg_phase2_objdir -name '*.o'` ; do
- p3=`echo $o | sed -e 's,Phase2,Phase3,'`
- if ! cmp --ignore-initial=16 $o $p3 > /dev/null 2>&1 ; then
- echo "file `basename $o` differs between dragonegg phase 2 and phase 3"
- fi
- done
- fi
-
# Otherwise just test the core.
- if [ "$do_clang" != "yes" -a "$do_dragonegg" != "yes" ]; then
+ if [ "$do_clang" != "yes" ]; then
echo "# Testing - built with system compiler"
test_llvmCore 1 $Flavor $llvmCore_phase1_objdir
fi
diff --git a/utils/shuffle_fuzz.py b/utils/shuffle_fuzz.py
index 384a93aa98848..985d1dab9e23e 100755
--- a/utils/shuffle_fuzz.py
+++ b/utils/shuffle_fuzz.py
@@ -173,7 +173,7 @@ entry:""" % dict(subst,
# Generate some string constants that we can use to report errors.
for i, r in enumerate(result):
if r != -1:
- s = ('FAIL(%(seed)s): lane %(lane)d, expected %(result)d, found %%d\\0A' %
+ s = ('FAIL(%(seed)s): lane %(lane)d, expected %(result)d, found %%d\n\\0A' %
{'seed': args.seed, 'lane': i, 'result': r})
s += ''.join(['\\00' for _ in itertools.repeat(None, 128 - len(s) + 2)])
print """
@@ -235,8 +235,7 @@ die.%(i)d:
%%bad.%(i)d = trunc i2048 %%tmp.%(i)d to i32
call i32 (i8*, i8*, ...)* @sprintf(i8* %%str.ptr, i8* getelementptr inbounds ([128 x i8]* @error.%(i)d, i32 0, i32 0), i32 %%bad.%(i)d)
%%length.%(i)d = call i32 @strlen(i8* %%str.ptr)
- %%size.%(i)d = add i32 %%length.%(i)d, 1
- call i32 @write(i32 2, i8* %%str.ptr, i32 %%size.%(i)d)
+ call i32 @write(i32 2, i8* %%str.ptr, i32 %%length.%(i)d)
call void @llvm.trap()
unreachable
""" % dict(subst, i=i, next_i=i + 1, r=r)
diff --git a/utils/sort_includes.py b/utils/sort_includes.py
index fef97550db8d8..70bfdedfc6d32 100755
--- a/utils/sort_includes.py
+++ b/utils/sort_includes.py
@@ -29,7 +29,8 @@ def sort_includes(f):
headers_end = 0
api_headers = []
local_headers = []
- project_headers = []
+ subproject_headers = []
+ llvm_headers = []
system_headers = []
for (i, l) in enumerate(lines):
if l.strip() == '':
@@ -44,12 +45,16 @@ def sort_includes(f):
api_headers.append(header)
look_for_api_header = False
continue
- if header.startswith('<') or header.startswith('"gtest/'):
+ if (header.startswith('<') or header.startswith('"gtest/') or
+ header.startswith('"isl/') or header.startswith('"json/')):
system_headers.append(header)
continue
- if (header.startswith('"llvm/') or header.startswith('"llvm-c/') or
- header.startswith('"clang/') or header.startswith('"clang-c/')):
- project_headers.append(header)
+ if (header.startswith('"clang/') or header.startswith('"clang-c/') or
+ header.startswith('"polly/')):
+ subproject_headers.append(header)
+ continue
+ if (header.startswith('"llvm/') or header.startswith('"llvm-c/')):
+ llvm_headers.append(header)
continue
local_headers.append(header)
continue
@@ -65,9 +70,10 @@ def sort_includes(f):
return
local_headers = sorted(set(local_headers))
- project_headers = sorted(set(project_headers))
+ subproject_headers = sorted(set(subproject_headers))
+ llvm_headers = sorted(set(llvm_headers))
system_headers = sorted(set(system_headers))
- headers = api_headers + local_headers + project_headers + system_headers
+ headers = api_headers + local_headers + subproject_headers + llvm_headers + system_headers
header_lines = ['#include ' + h for h in headers]
lines = lines[:headers_begin] + header_lines + lines[headers_end + 1:]
diff --git a/utils/unittest/CMakeLists.txt b/utils/unittest/CMakeLists.txt
index b6d2d6d9e0e99..b34e22ae0cb42 100644
--- a/utils/unittest/CMakeLists.txt
+++ b/utils/unittest/CMakeLists.txt
@@ -32,17 +32,20 @@ if (NOT LLVM_ENABLE_THREADS)
add_definitions( -DGTEST_HAS_PTHREAD=0 )
endif()
-# Visual Studio 2012 only supports up to 8 template parameters in
-# std::tr1::tuple by default, but gtest requires 10
-if(MSVC AND MSVC_VERSION EQUAL 1700)
- add_definitions(-D_VARIADIC_MAX=10)
-endif ()
+set(LIBS
+ LLVMSupport # Depends on llvm::raw_ostream
+)
+
+find_library(PTHREAD_LIBRARY_PATH pthread)
+if (PTHREAD_LIBRARY_PATH)
+ list(APPEND LIBS pthread)
+endif()
add_llvm_library(gtest
googletest/src/gtest-all.cc
LINK_LIBS
- LLVMSupport # Depends on llvm::raw_ostream
- )
+ ${LIBS}
+)
add_subdirectory(UnitTestMain)
diff --git a/utils/unittest/UnitTestMain/TestMain.cpp b/utils/unittest/UnitTestMain/TestMain.cpp
index 5387512e6fb54..f5b09a5cf6735 100644
--- a/utils/unittest/UnitTestMain/TestMain.cpp
+++ b/utils/unittest/UnitTestMain/TestMain.cpp
@@ -23,7 +23,7 @@
const char *TestMainArgv0;
int main(int argc, char **argv) {
- llvm::sys::PrintStackTraceOnErrorSignal();
+ llvm::sys::PrintStackTraceOnErrorSignal(true /* Disable crash reporting */);
testing::InitGoogleTest(&argc, argv);
llvm::cl::ParseCommandLineOptions(argc, argv);
diff --git a/utils/unittest/googletest/include/gtest/gtest-spi.h b/utils/unittest/googletest/include/gtest/gtest-spi.h
index b226e55048959..736f692e48f75 100644
--- a/utils/unittest/googletest/include/gtest/gtest-spi.h
+++ b/utils/unittest/googletest/include/gtest/gtest-spi.h
@@ -68,14 +68,15 @@ class GTEST_API_ ScopedFakeTestPartResultReporter
TestPartResultArray* result);
// The d'tor restores the previous test part result reporter.
- virtual ~ScopedFakeTestPartResultReporter();
+ ~ScopedFakeTestPartResultReporter() override;
// Appends the TestPartResult object to the TestPartResultArray
// received in the constructor.
//
// This method is from the TestPartResultReporterInterface
// interface.
- virtual void ReportTestPartResult(const TestPartResult& result);
+ void ReportTestPartResult(const TestPartResult &result) override;
+
private:
void Init();
diff --git a/utils/unittest/googletest/include/gtest/gtest-test-part.h b/utils/unittest/googletest/include/gtest/gtest-test-part.h
index 98e8b844915d1..d2410c00a3ffb 100644
--- a/utils/unittest/googletest/include/gtest/gtest-test-part.h
+++ b/utils/unittest/googletest/include/gtest/gtest-test-part.h
@@ -159,8 +159,8 @@ class GTEST_API_ HasNewFatalFailureHelper
: public TestPartResultReporterInterface {
public:
HasNewFatalFailureHelper();
- virtual ~HasNewFatalFailureHelper();
- virtual void ReportTestPartResult(const TestPartResult& result);
+ ~HasNewFatalFailureHelper() override;
+ void ReportTestPartResult(const TestPartResult &result) override;
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
private:
bool has_new_fatal_failure_;
diff --git a/utils/unittest/googletest/include/gtest/gtest.h b/utils/unittest/googletest/include/gtest/gtest.h
index 07ed92b57c0dc..92ca5cc91c82b 100644
--- a/utils/unittest/googletest/include/gtest/gtest.h
+++ b/utils/unittest/googletest/include/gtest/gtest.h
@@ -74,7 +74,7 @@
// define it to 0 to indicate otherwise.
//
// If the user's ::std::string and ::string are the same class due to
-// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0.
+// aliasing, they should define GTEST_HAS_GLOBAL_STRING to 0.
//
// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined
// heuristically.
@@ -982,21 +982,22 @@ class TestEventListener {
class EmptyTestEventListener : public TestEventListener {
virtual void anchor();
public:
- virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
- virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
- int /*iteration*/) {}
- virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {}
- virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
- virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
- virtual void OnTestStart(const TestInfo& /*test_info*/) {}
- virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {}
- virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
- virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
- virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {}
- virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
- virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
- int /*iteration*/) {}
- virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+ void OnTestProgramStart(const UnitTest & /*unit_test*/) override {}
+ void OnTestIterationStart(const UnitTest & /*unit_test*/,
+ int /*iteration*/) override {}
+ void OnEnvironmentsSetUpStart(const UnitTest & /*unit_test*/) override {}
+ void OnEnvironmentsSetUpEnd(const UnitTest & /*unit_test*/) override {}
+ void OnTestCaseStart(const TestCase & /*test_case*/) override {}
+ void OnTestStart(const TestInfo & /*test_info*/) override {}
+ void OnTestPartResult(const TestPartResult & /*test_part_result*/) override {
+ }
+ void OnTestEnd(const TestInfo & /*test_info*/) override {}
+ void OnTestCaseEnd(const TestCase & /*test_case*/) override {}
+ void OnEnvironmentsTearDownStart(const UnitTest & /*unit_test*/) override {}
+ void OnEnvironmentsTearDownEnd(const UnitTest & /*unit_test*/) override {}
+ void OnTestIterationEnd(const UnitTest & /*unit_test*/,
+ int /*iteration*/) override {}
+ void OnTestProgramEnd(const UnitTest & /*unit_test*/) override {}
};
// TestEventListeners lets users add listeners to track events in Google Test.
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h b/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
index 8d53c4528078b..04c676ce5ff7b 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
@@ -147,8 +147,8 @@ class DeathTestFactory {
// A concrete DeathTestFactory implementation for normal use.
class DefaultDeathTestFactory : public DeathTestFactory {
public:
- virtual bool Create(const char* statement, const RE* regex,
- const char* file, int line, DeathTest** test);
+ bool Create(const char *statement, const RE *regex, const char *file,
+ int line, DeathTest **test) override;
};
// Returns true if exit_status describes a process that was terminated
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-internal.h b/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
index 63f72acdfb572..3c7eee81b1d91 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
@@ -555,7 +555,7 @@ class TestFactoryBase {
template <class TestClass>
class TestFactoryImpl : public TestFactoryBase {
public:
- virtual Test* CreateTest() { return new TestClass; }
+ Test *CreateTest() override { return new TestClass; }
};
#if GTEST_OS_WINDOWS
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h b/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
index 258267500ec18..e32c762f75ada 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
@@ -100,9 +100,6 @@ class ValueArray2 {
}
private:
- // No implementation - assignment is unsupported.
- void operator=(const ValueArray2& other);
-
const T1 v1_;
const T2 v2_;
};
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h b/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
index 3bb2ffb355666..dea4d5cc6bcb1 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
@@ -270,12 +270,12 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
template <typename ForwardIterator>
ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
: container_(begin, end) {}
- virtual ~ValuesInIteratorRangeGenerator() {}
+ ~ValuesInIteratorRangeGenerator() override {}
- virtual ParamIteratorInterface<T>* Begin() const {
+ ParamIteratorInterface<T> *Begin() const override {
return new Iterator(this, container_.begin());
}
- virtual ParamIteratorInterface<T>* End() const {
+ ParamIteratorInterface<T> *End() const override {
return new Iterator(this, container_.end());
}
@@ -287,16 +287,16 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
Iterator(const ParamGeneratorInterface<T>* base,
typename ContainerType::const_iterator iterator)
: base_(base), iterator_(iterator) {}
- virtual ~Iterator() {}
+ ~Iterator() override {}
- virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+ const ParamGeneratorInterface<T> *BaseGenerator() const override {
return base_;
}
- virtual void Advance() {
+ void Advance() override {
++iterator_;
value_.reset();
}
- virtual ParamIteratorInterface<T>* Clone() const {
+ ParamIteratorInterface<T> *Clone() const override {
return new Iterator(*this);
}
// We need to use cached value referenced by iterator_ because *iterator_
@@ -306,12 +306,12 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
// can advance iterator_ beyond the end of the range, and we cannot
// detect that fact. The client code, on the other hand, is
// responsible for not calling Current() on an out-of-range iterator.
- virtual const T* Current() const {
+ const T *Current() const override {
if (value_.get() == NULL)
value_.reset(new T(*iterator_));
return value_.get();
}
- virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+ bool Equals(const ParamIteratorInterface<T> &other) const override {
// Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
@@ -355,7 +355,7 @@ class ParameterizedTestFactory : public TestFactoryBase {
typedef typename TestClass::ParamType ParamType;
explicit ParameterizedTestFactory(ParamType parameter) :
parameter_(parameter) {}
- virtual Test* CreateTest() {
+ Test *CreateTest() override {
TestClass::SetParam(&parameter_);
return new TestClass();
}
@@ -394,7 +394,7 @@ class TestMetaFactory
TestMetaFactory() {}
- virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
+ TestFactoryBase *CreateTestFactory(ParamType parameter) override {
return new ParameterizedTestFactory<TestCase>(parameter);
}
@@ -454,9 +454,9 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
: test_case_name_(name) {}
// Test case base name for display purposes.
- virtual const string& GetTestCaseName() const { return test_case_name_; }
+ const string &GetTestCaseName() const override { return test_case_name_; }
// Test case id to verify identity.
- virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
+ TypeId GetTestCaseTypeId() const override { return GetTypeId<TestCase>(); }
// TEST_P macro uses AddTestPattern() to record information
// about a single test in a LocalTestInfo structure.
// test_case_name is the base name of the test case (without invocation
@@ -484,7 +484,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
// This method should not be called more then once on any single
// instance of a ParameterizedTestCaseInfoBase derived class.
// UnitTest has a guard to prevent from calling this method more then once.
- virtual void RegisterTests() {
+ void RegisterTests() override {
for (typename TestInfoContainer::iterator test_it = tests_.begin();
test_it != tests_.end(); ++test_it) {
linked_ptr<TestInfo> test_info = *test_it;
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-port.h b/utils/unittest/googletest/include/gtest/internal/gtest-port.h
index f5bfd4e1d2eec..6b942e9f9d9e7 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-port.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-port.h
@@ -503,7 +503,7 @@
# define _TR1_FUNCTIONAL 1
# include <tr1/tuple>
# undef _TR1_FUNCTIONAL // Allows the user to #include
- // <tr1/functional> if he chooses to.
+ // <tr1/functional> if they choose to.
# else
# include <tr1/tuple> // NOLINT
# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
@@ -1165,7 +1165,7 @@ class ThreadWithParam : public ThreadWithParamBase {
GTEST_CHECK_POSIX_SUCCESS_(
pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base));
}
- ~ThreadWithParam() { Join(); }
+ ~ThreadWithParam() override { Join(); }
void Join() {
if (!finished_) {
@@ -1174,7 +1174,7 @@ class ThreadWithParam : public ThreadWithParamBase {
}
}
- virtual void Run() {
+ void Run() override {
if (thread_can_start_ != NULL)
thread_can_start_->WaitForNotification();
func_(param_);
diff --git a/utils/unittest/googletest/src/gtest-death-test.cc b/utils/unittest/googletest/src/gtest-death-test.cc
index 314dba2116e97..47c1a15b820cd 100644
--- a/utils/unittest/googletest/src/gtest-death-test.cc
+++ b/utils/unittest/googletest/src/gtest-death-test.cc
@@ -334,10 +334,10 @@ class DeathTestImpl : public DeathTest {
write_fd_(-1) {}
// read_fd_ is expected to be closed and cleared by a derived class.
- ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+ ~DeathTestImpl() override { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
- void Abort(AbortReason reason);
- virtual bool Passed(bool status_ok);
+ void Abort(AbortReason reason) override;
+ bool Passed(bool status_ok) override;
const char* statement() const { return statement_; }
const RE* regex() const { return regex_; }
@@ -744,7 +744,7 @@ class ForkingDeathTest : public DeathTestImpl {
ForkingDeathTest(const char* statement, const RE* regex);
// All of these virtual functions are inherited from DeathTest.
- virtual int Wait();
+ int Wait() override;
protected:
void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
@@ -780,7 +780,7 @@ class NoExecDeathTest : public ForkingDeathTest {
public:
NoExecDeathTest(const char* a_statement, const RE* a_regex) :
ForkingDeathTest(a_statement, a_regex) { }
- virtual TestRole AssumeRole();
+ TestRole AssumeRole() override;
};
// The AssumeRole process for a fork-and-run death test. It implements a
@@ -835,7 +835,8 @@ class ExecDeathTest : public ForkingDeathTest {
ExecDeathTest(const char* a_statement, const RE* a_regex,
const char* file, int line) :
ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
- virtual TestRole AssumeRole();
+ TestRole AssumeRole() override;
+
private:
// The name of the file in which the death test is located.
const char* const file_;
diff --git a/utils/unittest/googletest/src/gtest-internal-inl.h b/utils/unittest/googletest/src/gtest-internal-inl.h
index 1bae630127b52..35e865ff07fe9 100644
--- a/utils/unittest/googletest/src/gtest-internal-inl.h
+++ b/utils/unittest/googletest/src/gtest-internal-inl.h
@@ -431,8 +431,8 @@ class OsStackTraceGetterInterface {
class OsStackTraceGetter : public OsStackTraceGetterInterface {
public:
OsStackTraceGetter() : caller_frame_(NULL) {}
- virtual String CurrentStackTrace(int max_depth, int skip_count);
- virtual void UponLeavingGTest();
+ String CurrentStackTrace(int max_depth, int skip_count) override;
+ void UponLeavingGTest() override;
// This string is inserted in place of stack frames that are part of
// Google Test's implementation.
@@ -465,7 +465,7 @@ class DefaultGlobalTestPartResultReporter
explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
// Implements the TestPartResultReporterInterface. Reports the test part
// result in the current test.
- virtual void ReportTestPartResult(const TestPartResult& result);
+ void ReportTestPartResult(const TestPartResult &result) override;
private:
UnitTestImpl* const unit_test_;
@@ -481,7 +481,7 @@ class DefaultPerThreadTestPartResultReporter
explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
// Implements the TestPartResultReporterInterface. The implementation just
// delegates to the current global test part result reporter of *unit_test_.
- virtual void ReportTestPartResult(const TestPartResult& result);
+ void ReportTestPartResult(const TestPartResult &result) override;
private:
UnitTestImpl* const unit_test_;
diff --git a/utils/unittest/googletest/src/gtest.cc b/utils/unittest/googletest/src/gtest.cc
index bf850c6cd9774..57807646ea173 100644
--- a/utils/unittest/googletest/src/gtest.cc
+++ b/utils/unittest/googletest/src/gtest.cc
@@ -2663,19 +2663,19 @@ class PrettyUnitTestResultPrinter : public TestEventListener {
}
// The following methods override what's in the TestEventListener class.
- virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
- virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
- virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
- virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
- virtual void OnTestCaseStart(const TestCase& test_case);
- virtual void OnTestStart(const TestInfo& test_info);
- virtual void OnTestPartResult(const TestPartResult& result);
- virtual void OnTestEnd(const TestInfo& test_info);
- virtual void OnTestCaseEnd(const TestCase& test_case);
- virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
- virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
- virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
- virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+ void OnTestProgramStart(const UnitTest & /*unit_test*/) override {}
+ void OnTestIterationStart(const UnitTest &unit_test, int iteration) override;
+ void OnEnvironmentsSetUpStart(const UnitTest &unit_test) override;
+ void OnEnvironmentsSetUpEnd(const UnitTest & /*unit_test*/) override {}
+ void OnTestCaseStart(const TestCase &test_case) override;
+ void OnTestStart(const TestInfo &test_info) override;
+ void OnTestPartResult(const TestPartResult &result) override;
+ void OnTestEnd(const TestInfo &test_info) override;
+ void OnTestCaseEnd(const TestCase &test_case) override;
+ void OnEnvironmentsTearDownStart(const UnitTest &unit_test) override;
+ void OnEnvironmentsTearDownEnd(const UnitTest & /*unit_test*/) override {}
+ void OnTestIterationEnd(const UnitTest &unit_test, int iteration) override;
+ void OnTestProgramEnd(const UnitTest & /*unit_test*/) override {}
private:
static void PrintFailedTests(const UnitTest& unit_test);
@@ -2869,7 +2869,7 @@ void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
class TestEventRepeater : public TestEventListener {
public:
TestEventRepeater() : forwarding_enabled_(true) {}
- virtual ~TestEventRepeater();
+ ~TestEventRepeater() override;
void Append(TestEventListener *listener);
TestEventListener* Release(TestEventListener* listener);
@@ -2878,19 +2878,19 @@ class TestEventRepeater : public TestEventListener {
bool forwarding_enabled() const { return forwarding_enabled_; }
void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
- virtual void OnTestProgramStart(const UnitTest& unit_test);
- virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
- virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
- virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test);
- virtual void OnTestCaseStart(const TestCase& test_case);
- virtual void OnTestStart(const TestInfo& test_info);
- virtual void OnTestPartResult(const TestPartResult& result);
- virtual void OnTestEnd(const TestInfo& test_info);
- virtual void OnTestCaseEnd(const TestCase& test_case);
- virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
- virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test);
- virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
- virtual void OnTestProgramEnd(const UnitTest& unit_test);
+ void OnTestProgramStart(const UnitTest &unit_test) override;
+ void OnTestIterationStart(const UnitTest &unit_test, int iteration) override;
+ void OnEnvironmentsSetUpStart(const UnitTest &unit_test) override;
+ void OnEnvironmentsSetUpEnd(const UnitTest &unit_test) override;
+ void OnTestCaseStart(const TestCase &test_case) override;
+ void OnTestStart(const TestInfo &test_info) override;
+ void OnTestPartResult(const TestPartResult &result) override;
+ void OnTestEnd(const TestInfo &test_info) override;
+ void OnTestCaseEnd(const TestCase &test_case) override;
+ void OnEnvironmentsTearDownStart(const UnitTest &unit_test) override;
+ void OnEnvironmentsTearDownEnd(const UnitTest &unit_test) override;
+ void OnTestIterationEnd(const UnitTest &unit_test, int iteration) override;
+ void OnTestProgramEnd(const UnitTest &unit_test) override;
private:
// Controls whether events will be forwarded to listeners_. Set to false
@@ -2983,7 +2983,7 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
public:
explicit XmlUnitTestResultPrinter(const char* output_file);
- virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+ void OnTestIterationEnd(const UnitTest &unit_test, int iteration) override;
private:
// Is c a whitespace character that is normalized to a space character
@@ -3310,16 +3310,16 @@ class StreamingListener : public EmptyTestEventListener {
Send("gtest_streaming_protocol_version=1.0\n");
}
- virtual ~StreamingListener() {
+ ~StreamingListener() override {
if (sockfd_ != -1)
CloseConnection();
}
- void OnTestProgramStart(const UnitTest& /* unit_test */) {
+ void OnTestProgramStart(const UnitTest & /* unit_test */) override {
Send("event=TestProgramStart\n");
}
- void OnTestProgramEnd(const UnitTest& unit_test) {
+ void OnTestProgramEnd(const UnitTest &unit_test) override {
// Note that Google Test current only report elapsed time for each
// test iteration, not for the entire test program.
Send(String::Format("event=TestProgramEnd&passed=%d\n",
@@ -3329,39 +3329,41 @@ class StreamingListener : public EmptyTestEventListener {
CloseConnection();
}
- void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+ void OnTestIterationStart(const UnitTest & /* unit_test */,
+ int iteration) override {
Send(String::Format("event=TestIterationStart&iteration=%d\n",
iteration));
}
- void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+ void OnTestIterationEnd(const UnitTest &unit_test,
+ int /* iteration */) override {
Send(String::Format("event=TestIterationEnd&passed=%d&elapsed_time=%sms\n",
unit_test.Passed(),
StreamableToString(unit_test.elapsed_time()).c_str()));
}
- void OnTestCaseStart(const TestCase& test_case) {
+ void OnTestCaseStart(const TestCase &test_case) override {
Send(String::Format("event=TestCaseStart&name=%s\n", test_case.name()));
}
- void OnTestCaseEnd(const TestCase& test_case) {
+ void OnTestCaseEnd(const TestCase &test_case) override {
Send(String::Format("event=TestCaseEnd&passed=%d&elapsed_time=%sms\n",
test_case.Passed(),
StreamableToString(test_case.elapsed_time()).c_str()));
}
- void OnTestStart(const TestInfo& test_info) {
+ void OnTestStart(const TestInfo &test_info) override {
Send(String::Format("event=TestStart&name=%s\n", test_info.name()));
}
- void OnTestEnd(const TestInfo& test_info) {
+ void OnTestEnd(const TestInfo &test_info) override {
Send(String::Format(
"event=TestEnd&passed=%d&elapsed_time=%sms\n",
(test_info.result())->Passed(),
StreamableToString((test_info.result())->elapsed_time()).c_str()));
}
- void OnTestPartResult(const TestPartResult& test_part_result) {
+ void OnTestPartResult(const TestPartResult &test_part_result) override {
const char* file_name = test_part_result.file_name();
if (file_name == NULL)
file_name = "";
diff --git a/utils/update_llc_test_checks.py b/utils/update_llc_test_checks.py
index 4125ea981ec15..df01d8973c464 100755
--- a/utils/update_llc_test_checks.py
+++ b/utils/update_llc_test_checks.py
@@ -24,6 +24,7 @@ def llc(args, cmd_args, ir):
ASM_SCRUB_WHITESPACE_RE = re.compile(r'(?!^(| \w))[ \t]+', flags=re.M)
+ASM_SCRUB_TRAILING_WHITESPACE_RE = re.compile(r'[ \t]+$', flags=re.M)
ASM_SCRUB_SHUFFLES_RE = (
re.compile(
r'^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem) = .*)$',
@@ -47,6 +48,8 @@ def scrub_asm(asm):
asm = ASM_SCRUB_RIP_RE.sub(r'{{.*}}(%rip)', asm)
# Strip kill operands inserted into the asm.
asm = ASM_SCRUB_KILL_COMMENT_RE.sub('', asm)
+ # Strip trailing whitespace.
+ asm = ASM_SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
return asm
@@ -66,7 +69,7 @@ def main():
asm_function_re = re.compile(
r'^_?(?P<f>[^:]+):[ \t]*#+[ \t]*@(?P=f)\n[^:]*?'
r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
- r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.(?:sub)?section)',
+ r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section)',
flags=(re.M | re.S))
check_prefix_re = re.compile('--check-prefix=(\S+)')
check_re = re.compile(r'^\s*;\s*([^:]+?)(?:-NEXT|-NOT|-DAG|-LABEL)?:')
@@ -122,6 +125,9 @@ def main():
continue
f = m.group('f')
f_asm = scrub_asm(m.group('body'))
+ if f.startswith('stress'):
+ # We only use the last line of the asm for stress tests.
+ f_asm = '\n'.join(f_asm.splitlines()[-1:])
if args.verbose:
print >>sys.stderr, 'Processing asm for function: ' + f
for l in f_asm.splitlines():
diff --git a/utils/vim/README b/utils/vim/README
index bca25bfe61272..1fe00992b0ab1 100644
--- a/utils/vim/README
+++ b/utils/vim/README
@@ -1,33 +1,12 @@
-*- llvm/utils/vim/README -*-
-These are syntax highlighting files for the VIM editor. Included are:
+This directory contains settings for the vim editor to work on llvm *.ll and
+tablegen *.td files. It comes with filetype detection rules in the (ftdetect),
+syntax highlighting (syntax), some minimal sensible default settings (ftplugin)
+and indentation plugins (indent).
-* llvm.vim
-
- Syntax highlighting mode for LLVM assembly files. To use, copy `llvm.vim' to
- ~/.vim/syntax and add this code to your ~/.vimrc :
-
- augroup filetype
- au! BufRead,BufNewFile *.ll set filetype=llvm
- augroup END
-
-* tablegen.vim
-
- Syntax highlighting mode for TableGen description files. To use, copy
- `tablegen.vim' to ~/.vim/syntax and add this code to your ~/.vimrc :
-
- augroup filetype
- au! BufRead,BufNewFile *.td set filetype=tablegen
- augroup END
-
-
-If you prefer, instead of making copies you can make symlinks from
-~/.vim/syntax/... to the syntax files in your LLVM source tree. Apparently
-this did not work with older versions of vim however, so if this doesn't
-work you may need to make actual copies of the files.
-
-Another option, if you do not already have a ~/.vim/syntax directory, is
-to symlink ~/.vim/syntax itself to llvm/utils/vim .
+To install copy all subdirectories to your $HOME/.vim or if you prefer create
+symlinks to the files here. Do not copy the vimrc file here it is only meant as an inspiration and starting point for those working on llvm c++ code.
Note: If you notice missing or incorrect syntax highlighting, please contact
<llvmbugs [at] cs.uiuc.edu>; if you wish to provide a patch to improve the
diff --git a/utils/vim/ftdetect/llvm-lit.vim b/utils/vim/ftdetect/llvm-lit.vim
new file mode 100644
index 0000000000000..fa651e1268cb5
--- /dev/null
+++ b/utils/vim/ftdetect/llvm-lit.vim
@@ -0,0 +1 @@
+au BufRead,BufNewFile lit.*cfg set filetype=python
diff --git a/utils/vim/ftdetect/llvm.vim b/utils/vim/ftdetect/llvm.vim
new file mode 100644
index 0000000000000..161ceb2bd5595
--- /dev/null
+++ b/utils/vim/ftdetect/llvm.vim
@@ -0,0 +1 @@
+au BufRead,BufNewFile *.ll set filetype=llvm
diff --git a/utils/vim/ftdetect/tablegen.vim b/utils/vim/ftdetect/tablegen.vim
new file mode 100644
index 0000000000000..95efa6efdd0aa
--- /dev/null
+++ b/utils/vim/ftdetect/tablegen.vim
@@ -0,0 +1 @@
+au BufRead,BufNewFile *.td set filetype=tablegen
diff --git a/utils/vim/ftplugin/llvm.vim b/utils/vim/ftplugin/llvm.vim
new file mode 100644
index 0000000000000..04bb9e0016966
--- /dev/null
+++ b/utils/vim/ftplugin/llvm.vim
@@ -0,0 +1,11 @@
+" Vim filetype plugin file
+" Language: LLVM Assembly
+" Maintainer: The LLVM team, http://llvm.org/
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+setlocal softtabstop=2 shiftwidth=2
+setlocal expandtab
diff --git a/utils/vim/ftplugin/tablegen.vim b/utils/vim/ftplugin/tablegen.vim
new file mode 100644
index 0000000000000..cfae846c818b8
--- /dev/null
+++ b/utils/vim/ftplugin/tablegen.vim
@@ -0,0 +1,12 @@
+" Vim filetype plugin file
+" Language: LLVM TableGen
+" Maintainer: The LLVM team, http://llvm.org/
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+setlocal matchpairs+=<:>
+setlocal softtabstop=2 shiftwidth=2
+setlocal expandtab
diff --git a/utils/vim/indent/llvm.vim b/utils/vim/indent/llvm.vim
new file mode 100644
index 0000000000000..d1d8c83d11861
--- /dev/null
+++ b/utils/vim/indent/llvm.vim
@@ -0,0 +1,72 @@
+" Vim indent file
+" Language: llvm
+" Maintainer: The LLVM team, http://llvm.org/
+" What this indent plugin currently does:
+" - If no other rule matches copy indent from previous non-empty,
+" non-commented line
+" - On '}' align the same as the line containing the matching '{'
+" - If previous line ends with ':' increase indentation
+" - If the current line ends with ':' indent at the same level as the
+" enclosing '{'/'}' block
+" Stuff that would be nice to add:
+" - Continue comments on next line
+" - If there is an opening+unclosed parenthesis on previous line indent to that
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal shiftwidth=2 expandtab
+
+setlocal indentkeys=0{,0},<:>,!^F,o,O,e
+setlocal indentexpr=GetLLVMIndent()
+
+if exists("*GetLLVMIndent")
+ finish
+endif
+
+function! FindOpenBrace(lnum)
+ call cursor(a:lnum, 1)
+ return searchpair('{', '', '}', 'bW')
+endfun
+
+function! GetLLVMIndent()
+ " On '}' align the same as the line containing the matching '{'
+ let thisline = getline(v:lnum)
+ if thisline =~ '^\s*}'
+ call cursor(v:lnum, 1)
+ silent normal %
+ let opening_lnum = line('.')
+ if opening_lnum != v:lnum
+ return indent(opening_lnum)
+ endif
+ endif
+
+ " Indent labels the same as the current opening block
+ if thisline =~ ':\s*$'
+ let blockbegin = FindOpenBrace(v:lnum)
+ if blockbegin > 0
+ return indent(blockbegin)
+ endif
+ endif
+
+ " Find a non-blank not-completely commented line above the current line.
+ let prev_lnum = prevnonblank(v:lnum - 1)
+ while prev_lnum > 0 && synIDattr(synID(prev_lnum, indent(prev_lnum)+1, 0), "name") =? "string\|comment"
+ let prev_lnum = prevnonblank(prev_lnum-1)
+ endwhile
+ " Hit the start of the file, use zero indent.
+ if prev_lnum == 0
+ return 0
+ endif
+
+ let ind = indent(prev_lnum)
+ let prevline = getline(prev_lnum)
+
+ " Add a 'shiftwidth' after lines that start a block or labels
+ if prevline =~ '{\s*$' || prevline =~ ':\s*$'
+ let ind = ind + &shiftwidth
+ endif
+
+ return ind
+endfunction
diff --git a/utils/vim/llvm.vim b/utils/vim/syntax/llvm.vim
index f767fda16f873..c8e73cd94a57d 100644
--- a/utils/vim/llvm.vim
+++ b/utils/vim/syntax/llvm.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: llvm
" Maintainer: The LLVM team, http://llvm.org/
-" Version: $Revision: 225830 $
+" Version: $Revision: 235369 $
if version < 600
syntax clear
@@ -77,6 +77,12 @@ syn match llvmIdentifier /[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*/
syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*$/
syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*[=!]/
syn match llvmType /!\zs\a\+\ze\s*(/
+syn match llvmConstant /\<DW_TAG_[a-z_]\+\>/
+syn match llvmConstant /\<DW_ATE_[a-zA-Z_]\+\>/
+syn match llvmConstant /\<DW_OP_[a-zA-Z0-9_]\+\>/
+syn match llvmConstant /\<DW_LANG_[a-zA-Z0-9_]\+\>/
+syn match llvmConstant /\<DW_VIRTUALITY_[a-z_]\+\>/
+syn match llvmConstant /\<DIFlag[A-Za-z]\+\>/
" Syntax-highlight dejagnu test commands.
syn match llvmSpecialComment /;\s*RUN:.*$/
diff --git a/utils/vim/tablegen.vim b/utils/vim/syntax/tablegen.vim
index 40d8d78bba128..21f4848933537 100644
--- a/utils/vim/tablegen.vim
+++ b/utils/vim/syntax/tablegen.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: TableGen
" Maintainer: The LLVM team, http://llvm.org/
-" Version: $Revision: 151164 $
+" Version: $Revision: 235369 $
if version < 600
syntax clear
diff --git a/utils/yaml-bench/YAMLBench.cpp b/utils/yaml-bench/YAMLBench.cpp
index 8bd1ea17ea8e2..634622a710c80 100644
--- a/utils/yaml-bench/YAMLBench.cpp
+++ b/utils/yaml-bench/YAMLBench.cpp
@@ -19,6 +19,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/Timer.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/YAMLParser.h"
#include "llvm/Support/raw_ostream.h"
#include <system_error>
@@ -52,6 +53,10 @@ static cl::opt<unsigned>
"Do not use more megabytes of memory"),
cl::init(1000));
+cl::opt<cl::boolOrDefault>
+ UseColor("use-color", cl::desc("Emit colored output (default=autodetect)"),
+ cl::init(cl::BOU_UNSET));
+
struct indent {
unsigned distance;
indent(unsigned d) : distance(d) {}
@@ -69,7 +74,7 @@ static std::string prettyTag(yaml::Node *N) {
if (StringRef(Tag).startswith("tag:yaml.org,2002:")) {
std::string Ret = "!!";
Ret += StringRef(Tag).substr(18);
- return std::move(Ret);
+ return Ret;
}
std::string Ret = "!<";
Ret += Tag;
@@ -91,6 +96,8 @@ static void dumpNode( yaml::Node *n
SmallString<32> Storage;
StringRef Val = sn->getValue(Storage);
outs() << prettyTag(n) << " \"" << yaml::escape(Val) << "\"";
+ } else if (yaml::BlockScalarNode *BN = dyn_cast<yaml::BlockScalarNode>(n)) {
+ outs() << prettyTag(n) << " \"" << yaml::escape(BN->getValue()) << "\"";
} else if (yaml::SequenceNode *sn = dyn_cast<yaml::SequenceNode>(n)) {
outs() << prettyTag(n) << " [\n";
++Indent;
@@ -117,7 +124,7 @@ static void dumpNode( yaml::Node *n
outs() << indent(Indent) << "}";
} else if (yaml::AliasNode *an = dyn_cast<yaml::AliasNode>(n)){
outs() << "*" << an->getName();
- } else if (dyn_cast<yaml::NullNode>(n)) {
+ } else if (isa<yaml::NullNode>(n)) {
outs() << prettyTag(n) << " null";
}
}
@@ -187,6 +194,9 @@ static std::string createJSONText(size_t MemoryMB, unsigned ValueSize) {
int main(int argc, char **argv) {
llvm::cl::ParseCommandLineOptions(argc, argv);
+ bool ShowColors = UseColor == cl::BOU_UNSET
+ ? sys::Process::StandardOutHasColors()
+ : UseColor == cl::BOU_TRUE;
if (Input.getNumOccurrences()) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
MemoryBuffer::getFileOrSTDIN(Input);
@@ -200,8 +210,10 @@ int main(int argc, char **argv) {
}
if (DumpCanonical) {
- yaml::Stream stream(Buf.getBuffer(), sm);
+ yaml::Stream stream(Buf.getBuffer(), sm, ShowColors);
dumpStream(stream);
+ if (stream.failed())
+ return 1;
}
}