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