aboutsummaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/FileCheck/FileCheck.cpp49
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp429
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp84
-rw-r--r--utils/TableGen/AsmWriterInst.cpp4
-rw-r--r--utils/TableGen/AsmWriterInst.h3
-rw-r--r--utils/TableGen/CallingConvEmitter.cpp11
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp2
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp60
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp14
-rw-r--r--utils/TableGen/CodeGenInstruction.h2
-rw-r--r--utils/TableGen/CodeGenMapTable.cpp4
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp618
-rw-r--r--utils/TableGen/CodeGenRegisters.h143
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp44
-rw-r--r--utils/TableGen/CodeGenTarget.cpp52
-rw-r--r--utils/TableGen/CodeGenTarget.h13
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp8
-rw-r--r--utils/TableGen/DAGISelMatcher.h3
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp4
-rw-r--r--utils/TableGen/DAGISelMatcherOpt.cpp7
-rw-r--r--utils/TableGen/DFAPacketizerEmitter.cpp2
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp97
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp10
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp29
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp553
-rw-r--r--utils/TableGen/SequenceToOffsetTable.h5
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp2
-rw-r--r--utils/TableGen/TableGen.cpp16
-rw-r--r--utils/TableGen/X86DisassemblerTables.cpp49
-rw-r--r--utils/TableGen/X86DisassemblerTables.h4
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp195
-rw-r--r--utils/TableGen/X86RecognizableInstr.h4
-rw-r--r--utils/emacs/emacs.el37
-rw-r--r--utils/emacs/llvm-mode.el111
-rw-r--r--utils/emacs/tablegen-mode.el20
-rw-r--r--utils/lit/lit/LitConfig.py2
-rw-r--r--utils/lit/lit/Test.py5
-rw-r--r--utils/lit/lit/TestingConfig.py6
-rw-r--r--utils/lit/lit/formats/googletest.py1
-rw-r--r--utils/lit/lit/util.py18
-rwxr-xr-xutils/lit/utils/check-coverage2
-rw-r--r--utils/lldbDataFormatters.py10
-rw-r--r--utils/not/not.cpp5
-rwxr-xr-xutils/release/merge.sh10
-rwxr-xr-xutils/release/tag.sh39
-rwxr-xr-xutils/release/test-release.sh48
-rwxr-xr-xutils/shuffle_fuzz.py5
-rw-r--r--utils/unittest/CMakeLists.txt17
-rwxr-xr-xutils/update_llc_test_checks.py213
-rw-r--r--utils/vim/llvm.vim46
50 files changed, 1841 insertions, 1274 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp
index 59affa1..146b512 100644
--- a/utils/FileCheck/FileCheck.cpp
+++ b/utils/FileCheck/FileCheck.cpp
@@ -73,6 +73,7 @@ namespace Check {
CheckNone = 0,
CheckPlain,
CheckNext,
+ CheckSame,
CheckNot,
CheckDAG,
CheckLabel,
@@ -620,6 +621,9 @@ struct CheckString {
/// CheckNext - Verify there is a single line in the given buffer.
bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
+ /// CheckSame - Verify there is no newline in the given buffer.
+ bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
+
/// CheckNot - Verify there's no "not strings" in the given buffer.
bool CheckNot(const SourceMgr &SM, StringRef Buffer,
const std::vector<const Pattern *> &NotStrings,
@@ -683,6 +687,9 @@ static size_t CheckTypeSize(Check::CheckType Ty) {
case Check::CheckNext:
return sizeof("-NEXT:") - 1;
+ case Check::CheckSame:
+ return sizeof("-SAME:") - 1;
+
case Check::CheckNot:
return sizeof("-NOT:") - 1;
@@ -713,6 +720,9 @@ static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
if (Rest.startswith("NEXT:"))
return Check::CheckNext;
+ if (Rest.startswith("SAME:"))
+ return Check::CheckSame;
+
if (Rest.startswith("NOT:"))
return Check::CheckNot;
@@ -919,10 +929,12 @@ static bool ReadCheckFile(SourceMgr &SM,
Buffer = Buffer.substr(EOL);
// Verify that CHECK-NEXT lines have at least one CHECK line before them.
- if ((CheckTy == Check::CheckNext) && CheckStrings.empty()) {
+ if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) &&
+ CheckStrings.empty()) {
+ StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME";
SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
SourceMgr::DK_Error,
- "found '" + UsedPrefix + "-NEXT:' without previous '"
+ "found '" + UsedPrefix + "-" + Type + "' without previous '"
+ UsedPrefix + ": line");
return true;
}
@@ -1053,6 +1065,11 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
if (CheckNext(SM, SkippedRegion))
return StringRef::npos;
+ // If this check is a "CHECK-SAME", verify that the previous match was on
+ // the same line (i.e. that there is no newline between them).
+ if (CheckSame(SM, SkippedRegion))
+ return StringRef::npos;
+
// If this match had "not strings", verify that they don't exist in the
// skipped region.
if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
@@ -1101,6 +1118,34 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
return false;
}
+bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
+ if (CheckTy != Check::CheckSame)
+ return false;
+
+ // Count the number of newlines between the previous match and this one.
+ assert(Buffer.data() !=
+ SM.getMemoryBuffer(SM.FindBufferContainingLoc(
+ SMLoc::getFromPointer(Buffer.data())))
+ ->getBufferStart() &&
+ "CHECK-SAME can't be the first check in a file");
+
+ const char *FirstNewLine = nullptr;
+ unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
+
+ if (NumNewLines != 0) {
+ SM.PrintMessage(Loc, SourceMgr::DK_Error,
+ Prefix +
+ "-SAME: is not on the same line as the previous match");
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
+ "'next' match was here");
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
+ "previous match ended here");
+ return true;
+ }
+
+ return false;
+}
+
bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
const std::vector<const Pattern *> &NotStrings,
StringMap<StringRef> &VariableTable) const {
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 891328f..65a34d3 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -115,6 +115,7 @@
#include <map>
#include <set>
#include <sstream>
+#include <forward_list>
using namespace llvm;
#define DEBUG_TYPE "asm-matcher-emitter"
@@ -255,9 +256,8 @@ public:
return true;
// ... or if any of its super classes are a subset of RHS.
- for (std::vector<ClassInfo*>::const_iterator it = SuperClasses.begin(),
- ie = SuperClasses.end(); it != ie; ++it)
- if ((*it)->isSubsetOf(RHS))
+ for (const ClassInfo *CI : SuperClasses)
+ if (CI->isSubsetOf(RHS))
return true;
return false;
@@ -391,6 +391,10 @@ struct MatchableInfo {
/// AsmVariantID - Target's assembly syntax variant no.
int AsmVariantID;
+ /// AsmString - The assembly string for this instruction (with variants
+ /// removed), e.g. "movsx $src, $dst".
+ std::string AsmString;
+
/// TheDef - This is the definition of the instruction or InstAlias that this
/// matchable came from.
Record *const TheDef;
@@ -408,10 +412,6 @@ struct MatchableInfo {
/// MCInst.
SmallVector<ResOperand, 8> ResOperands;
- /// AsmString - The assembly string for this instruction (with variants
- /// removed), e.g. "movsx $src, $dst".
- std::string AsmString;
-
/// Mnemonic - This is the first token of the matched instruction, its
/// mnemonic.
StringRef Mnemonic;
@@ -423,7 +423,7 @@ struct MatchableInfo {
SmallVector<AsmOperand, 8> AsmOperands;
/// Predicates - The required subtarget features to match this instruction.
- SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures;
+ SmallVector<const SubtargetFeatureInfo *, 4> RequiredFeatures;
/// ConversionFnKind - The enum value which is passed to the generated
/// convertToMCInst to convert parsed operands into an MCInst for this
@@ -434,13 +434,15 @@ struct MatchableInfo {
bool HasDeprecation;
MatchableInfo(const CodeGenInstruction &CGI)
- : AsmVariantID(0), TheDef(CGI.TheDef), DefRec(&CGI),
- AsmString(CGI.AsmString) {
+ : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI) {
}
- MatchableInfo(const CodeGenInstAlias *Alias)
- : AsmVariantID(0), TheDef(Alias->TheDef), DefRec(Alias),
- AsmString(Alias->AsmString) {
+ MatchableInfo(std::unique_ptr<const CodeGenInstAlias> Alias)
+ : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), DefRec(Alias.release()) {
+ }
+
+ ~MatchableInfo() {
+ delete DefRec.dyn_cast<const CodeGenInstAlias*>();
}
// Two-operand aliases clone from the main matchable, but mark the second
@@ -516,7 +518,7 @@ struct MatchableInfo {
/// couldMatchAmbiguouslyWith - Check whether this matchable could
/// ambiguously match the same set of operands as \p RHS (without being a
/// strictly superior match).
- bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) {
+ bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) const {
// The primary comparator is the instruction mnemonic.
if (Mnemonic != RHS.Mnemonic)
return false;
@@ -552,7 +554,7 @@ struct MatchableInfo {
return !(HasLT ^ HasGT);
}
- void dump();
+ void dump() const;
private:
void tokenizeAsmString(const AsmMatcherInfo &Info);
@@ -574,7 +576,7 @@ struct SubtargetFeatureInfo {
return "Feature_" + TheDef->getName();
}
- void dump() {
+ void dump() const {
errs() << getEnumName() << " " << Index << "\n";
TheDef->dump();
}
@@ -582,10 +584,10 @@ struct SubtargetFeatureInfo {
struct OperandMatchEntry {
unsigned OperandMask;
- MatchableInfo* MI;
+ const MatchableInfo* MI;
ClassInfo *CI;
- static OperandMatchEntry create(MatchableInfo* mi, ClassInfo *ci,
+ static OperandMatchEntry create(const MatchableInfo *mi, ClassInfo *ci,
unsigned opMask) {
OperandMatchEntry X;
X.OperandMask = opMask;
@@ -608,10 +610,10 @@ public:
CodeGenTarget &Target;
/// The classes which are needed for matching.
- std::vector<ClassInfo*> Classes;
+ std::forward_list<ClassInfo> Classes;
/// The information on the matchables to match.
- std::vector<MatchableInfo*> Matchables;
+ std::vector<std::unique_ptr<MatchableInfo>> Matchables;
/// Info for custom matching operands by user defined methods.
std::vector<OperandMatchEntry> OperandMatchInfo;
@@ -621,7 +623,7 @@ public:
RegisterClassesTy RegisterClasses;
/// Map of Predicate records to their subtarget information.
- std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> SubtargetFeatures;
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
/// Map of AsmOperandClass records to their class information.
std::map<Record*, ClassInfo*> AsmOperandClasses;
@@ -669,11 +671,10 @@ public:
/// getSubtargetFeature - Lookup or create the subtarget feature info for the
/// given operand.
- SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {
+ const SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {
assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
- std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator I =
- SubtargetFeatures.find(Def);
- return I == SubtargetFeatures.end() ? nullptr : I->second;
+ const auto &I = SubtargetFeatures.find(Def);
+ return I == SubtargetFeatures.end() ? nullptr : &I->second;
}
RecordKeeper &getRecords() const {
@@ -683,11 +684,11 @@ public:
} // End anonymous namespace
-void MatchableInfo::dump() {
+void MatchableInfo::dump() const {
errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n";
for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
- AsmOperand &Op = AsmOperands[i];
+ const AsmOperand &Op = AsmOperands[i];
errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";
errs() << '\"' << Op.Token << "\"\n";
}
@@ -777,8 +778,8 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info,
// Compute the require features.
std::vector<Record*> Predicates =TheDef->getValueAsListOfDefs("Predicates");
for (unsigned i = 0, e = Predicates.size(); i != e; ++i)
- if (SubtargetFeatureInfo *Feature =
- Info.getSubtargetFeature(Predicates[i]))
+ if (const SubtargetFeatureInfo *Feature =
+ Info.getSubtargetFeature(Predicates[i]))
RequiredFeatures.push_back(Feature);
// Collect singleton registers, if used.
@@ -978,6 +979,7 @@ static std::string getEnumNameForToken(StringRef Str) {
case '.': Res += "_DOT_"; break;
case '<': Res += "_LT_"; break;
case '>': Res += "_GT_"; break;
+ case '-': Res += "_MINUS_"; break;
default:
if ((*it >= 'A' && *it <= 'Z') ||
(*it >= 'a' && *it <= 'z') ||
@@ -995,7 +997,8 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
ClassInfo *&Entry = TokenClasses[Token];
if (!Entry) {
- Entry = new ClassInfo();
+ Classes.emplace_front();
+ Entry = &Classes.front();
Entry->Kind = ClassInfo::Token;
Entry->ClassName = "Token";
Entry->Name = "MCK_" + getEnumNameForToken(Token);
@@ -1004,7 +1007,6 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
Entry->RenderMethod = "<invalid>";
Entry->ParserMethod = "";
Entry->DiagnosticType = "";
- Classes.push_back(Entry);
}
return Entry;
@@ -1076,10 +1078,8 @@ struct LessRegisterSet {
void AsmMatcherInfo::
buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
- const std::vector<CodeGenRegister*> &Registers =
- Target.getRegBank().getRegisters();
- ArrayRef<CodeGenRegisterClass*> RegClassList =
- Target.getRegBank().getRegClasses();
+ const auto &Registers = Target.getRegBank().getRegisters();
+ auto &RegClassList = Target.getRegBank().getRegClasses();
typedef std::set<RegisterSet, LessRegisterSet> RegisterSetSet;
@@ -1087,15 +1087,12 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
RegisterSetSet RegisterSets;
// Gather the defined sets.
- for (ArrayRef<CodeGenRegisterClass*>::const_iterator it =
- RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it)
- RegisterSets.insert(RegisterSet(
- (*it)->getOrder().begin(), (*it)->getOrder().end()));
+ for (const CodeGenRegisterClass &RC : RegClassList)
+ RegisterSets.insert(
+ RegisterSet(RC.getOrder().begin(), RC.getOrder().end()));
// Add any required singleton sets.
- for (SmallPtrSetImpl<Record*>::iterator it = SingletonRegisters.begin(),
- ie = SingletonRegisters.end(); it != ie; ++it) {
- Record *Rec = *it;
+ for (Record *Rec : SingletonRegisters) {
RegisterSets.insert(RegisterSet(&Rec, &Rec + 1));
}
@@ -1103,19 +1100,16 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
// a unique register set class), and build the mapping of registers to the set
// they should classify to.
std::map<Record*, RegisterSet> RegisterMap;
- for (std::vector<CodeGenRegister*>::const_iterator it = Registers.begin(),
- ie = Registers.end(); it != ie; ++it) {
- const CodeGenRegister &CGR = **it;
+ for (const CodeGenRegister &CGR : Registers) {
// Compute the intersection of all sets containing this register.
RegisterSet ContainingSet;
- for (RegisterSetSet::iterator it = RegisterSets.begin(),
- ie = RegisterSets.end(); it != ie; ++it) {
- if (!it->count(CGR.TheDef))
+ for (const RegisterSet &RS : RegisterSets) {
+ if (!RS.count(CGR.TheDef))
continue;
if (ContainingSet.empty()) {
- ContainingSet = *it;
+ ContainingSet = RS;
continue;
}
@@ -1123,7 +1117,7 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
std::swap(Tmp, ContainingSet);
std::insert_iterator<RegisterSet> II(ContainingSet,
ContainingSet.begin());
- std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II,
+ std::set_intersection(Tmp.begin(), Tmp.end(), RS.begin(), RS.end(), II,
LessRecordByID());
}
@@ -1136,39 +1130,35 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
// Construct the register classes.
std::map<RegisterSet, ClassInfo*, LessRegisterSet> RegisterSetClasses;
unsigned Index = 0;
- for (RegisterSetSet::iterator it = RegisterSets.begin(),
- ie = RegisterSets.end(); it != ie; ++it, ++Index) {
- ClassInfo *CI = new ClassInfo();
+ for (const RegisterSet &RS : RegisterSets) {
+ Classes.emplace_front();
+ ClassInfo *CI = &Classes.front();
CI->Kind = ClassInfo::RegisterClass0 + Index;
CI->ClassName = "Reg" + utostr(Index);
CI->Name = "MCK_Reg" + utostr(Index);
CI->ValueName = "";
CI->PredicateMethod = ""; // unused
CI->RenderMethod = "addRegOperands";
- CI->Registers = *it;
+ CI->Registers = RS;
// FIXME: diagnostic type.
CI->DiagnosticType = "";
- Classes.push_back(CI);
- RegisterSetClasses.insert(std::make_pair(*it, CI));
+ RegisterSetClasses.insert(std::make_pair(RS, CI));
+ ++Index;
}
// Find the superclasses; we could compute only the subgroup lattice edges,
// but there isn't really a point.
- for (RegisterSetSet::iterator it = RegisterSets.begin(),
- ie = RegisterSets.end(); it != ie; ++it) {
- ClassInfo *CI = RegisterSetClasses[*it];
- for (RegisterSetSet::iterator it2 = RegisterSets.begin(),
- ie2 = RegisterSets.end(); it2 != ie2; ++it2)
- if (*it != *it2 &&
- std::includes(it2->begin(), it2->end(), it->begin(), it->end(),
+ for (const RegisterSet &RS : RegisterSets) {
+ ClassInfo *CI = RegisterSetClasses[RS];
+ for (const RegisterSet &RS2 : RegisterSets)
+ if (RS != RS2 &&
+ std::includes(RS2.begin(), RS2.end(), RS.begin(), RS.end(),
LessRecordByID()))
- CI->SuperClasses.push_back(RegisterSetClasses[*it2]);
+ CI->SuperClasses.push_back(RegisterSetClasses[RS2]);
}
// Name the register classes which correspond to a user defined RegisterClass.
- for (ArrayRef<CodeGenRegisterClass*>::const_iterator
- it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) {
- const CodeGenRegisterClass &RC = **it;
+ for (const CodeGenRegisterClass &RC : RegClassList) {
// Def will be NULL for non-user defined register classes.
Record *Def = RC.getDef();
if (!Def)
@@ -1191,9 +1181,7 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
RegisterClasses[it->first] = RegisterSetClasses[it->second];
// Name the register classes which correspond to singleton registers.
- for (SmallPtrSetImpl<Record*>::iterator it = SingletonRegisters.begin(),
- ie = SingletonRegisters.end(); it != ie; ++it) {
- Record *Rec = *it;
+ for (Record *Rec : SingletonRegisters) {
ClassInfo *CI = RegisterClasses[Rec];
assert(CI && "Missing singleton register class info!");
@@ -1211,36 +1199,36 @@ void AsmMatcherInfo::buildOperandClasses() {
Records.getAllDerivedDefinitions("AsmOperandClass");
// Pre-populate AsmOperandClasses map.
- for (std::vector<Record*>::iterator it = AsmOperands.begin(),
- ie = AsmOperands.end(); it != ie; ++it)
- AsmOperandClasses[*it] = new ClassInfo();
+ for (Record *Rec : AsmOperands) {
+ Classes.emplace_front();
+ AsmOperandClasses[Rec] = &Classes.front();
+ }
unsigned Index = 0;
- for (std::vector<Record*>::iterator it = AsmOperands.begin(),
- ie = AsmOperands.end(); it != ie; ++it, ++Index) {
- ClassInfo *CI = AsmOperandClasses[*it];
+ for (Record *Rec : AsmOperands) {
+ ClassInfo *CI = AsmOperandClasses[Rec];
CI->Kind = ClassInfo::UserClass0 + Index;
- ListInit *Supers = (*it)->getValueAsListInit("SuperClasses");
+ ListInit *Supers = Rec->getValueAsListInit("SuperClasses");
for (unsigned i = 0, e = Supers->getSize(); i != e; ++i) {
DefInit *DI = dyn_cast<DefInit>(Supers->getElement(i));
if (!DI) {
- PrintError((*it)->getLoc(), "Invalid super class reference!");
+ PrintError(Rec->getLoc(), "Invalid super class reference!");
continue;
}
ClassInfo *SC = AsmOperandClasses[DI->getDef()];
if (!SC)
- PrintError((*it)->getLoc(), "Invalid super class reference!");
+ PrintError(Rec->getLoc(), "Invalid super class reference!");
else
CI->SuperClasses.push_back(SC);
}
- CI->ClassName = (*it)->getValueAsString("Name");
+ CI->ClassName = Rec->getValueAsString("Name");
CI->Name = "MCK_" + CI->ClassName;
- CI->ValueName = (*it)->getName();
+ CI->ValueName = Rec->getName();
// Get or construct the predicate method name.
- Init *PMName = (*it)->getValueInit("PredicateMethod");
+ Init *PMName = Rec->getValueInit("PredicateMethod");
if (StringInit *SI = dyn_cast<StringInit>(PMName)) {
CI->PredicateMethod = SI->getValue();
} else {
@@ -1249,7 +1237,7 @@ void AsmMatcherInfo::buildOperandClasses() {
}
// Get or construct the render method name.
- Init *RMName = (*it)->getValueInit("RenderMethod");
+ Init *RMName = Rec->getValueInit("RenderMethod");
if (StringInit *SI = dyn_cast<StringInit>(RMName)) {
CI->RenderMethod = SI->getValue();
} else {
@@ -1258,18 +1246,17 @@ void AsmMatcherInfo::buildOperandClasses() {
}
// Get the parse method name or leave it as empty.
- Init *PRMName = (*it)->getValueInit("ParserMethod");
+ Init *PRMName = Rec->getValueInit("ParserMethod");
if (StringInit *SI = dyn_cast<StringInit>(PRMName))
CI->ParserMethod = SI->getValue();
// Get the diagnostic type or leave it as empty.
// Get the parse method name or leave it as empty.
- Init *DiagnosticType = (*it)->getValueInit("DiagnosticType");
+ Init *DiagnosticType = Rec->getValueInit("DiagnosticType");
if (StringInit *SI = dyn_cast<StringInit>(DiagnosticType))
CI->DiagnosticType = SI->getValue();
- AsmOperandClasses[*it] = CI;
- Classes.push_back(CI);
+ ++Index;
}
}
@@ -1288,16 +1275,13 @@ void AsmMatcherInfo::buildOperandMatchInfo() {
typedef std::map<ClassInfo *, unsigned, less_ptr<ClassInfo>> OpClassMaskTy;
OpClassMaskTy OpClassMask;
- for (std::vector<MatchableInfo*>::const_iterator it =
- Matchables.begin(), ie = Matchables.end();
- it != ie; ++it) {
- MatchableInfo &II = **it;
+ for (const auto &MI : Matchables) {
OpClassMask.clear();
// Keep track of all operands of this instructions which belong to the
// same class.
- for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) {
- MatchableInfo::AsmOperand &Op = II.AsmOperands[i];
+ for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) {
+ const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i];
if (Op.Class->ParserMethod.empty())
continue;
unsigned &OperandMask = OpClassMask[Op.Class];
@@ -1305,11 +1289,11 @@ void AsmMatcherInfo::buildOperandMatchInfo() {
}
// Generate operand match info for each mnemonic/operand class pair.
- for (OpClassMaskTy::iterator iit = OpClassMask.begin(),
- iie = OpClassMask.end(); iit != iie; ++iit) {
- unsigned OpMask = iit->second;
- ClassInfo *CI = iit->first;
- OperandMatchInfo.push_back(OperandMatchEntry::create(&II, CI, OpMask));
+ for (const auto &OCM : OpClassMask) {
+ unsigned OpMask = OCM.second;
+ ClassInfo *CI = OCM.first;
+ OperandMatchInfo.push_back(OperandMatchEntry::create(MI.get(), CI,
+ OpMask));
}
}
}
@@ -1327,10 +1311,10 @@ void AsmMatcherInfo::buildInfo() {
if (Pred->getName().empty())
PrintFatalError(Pred->getLoc(), "Predicate has no name!");
- uint64_t FeatureNo = SubtargetFeatures.size();
- SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo);
- DEBUG(SubtargetFeatures[Pred]->dump());
- assert(FeatureNo < 64 && "Too many subtarget features!");
+ SubtargetFeatures.insert(std::make_pair(
+ Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size())));
+ DEBUG(SubtargetFeatures.find(Pred)->second.dump());
+ assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!");
}
// Parse the instructions; we need to do this first so that we can gather the
@@ -1344,20 +1328,18 @@ void AsmMatcherInfo::buildInfo() {
std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");
int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I) {
- const CodeGenInstruction &CGI = **I;
+ for (const CodeGenInstruction *CGI : Target.instructions()) {
// If the tblgen -match-prefix option is specified (for tblgen hackers),
// filter the set of instructions we consider.
- if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix))
+ if (!StringRef(CGI->TheDef->getName()).startswith(MatchPrefix))
continue;
// Ignore "codegen only" instructions.
- if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
+ if (CGI->TheDef->getValueAsBit("isCodeGenOnly"))
continue;
- std::unique_ptr<MatchableInfo> II(new MatchableInfo(CGI));
+ std::unique_ptr<MatchableInfo> II(new MatchableInfo(*CGI));
II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
@@ -1366,14 +1348,7 @@ void AsmMatcherInfo::buildInfo() {
if (!II->validate(CommentDelimiter, true))
continue;
- // Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
- //
- // FIXME: This is a total hack.
- if (StringRef(II->TheDef->getName()).startswith("Int_") ||
- StringRef(II->TheDef->getName()).endswith("_Int"))
- continue;
-
- Matchables.push_back(II.release());
+ Matchables.push_back(std::move(II));
}
// Parse all of the InstAlias definitions and stick them in the list of
@@ -1381,8 +1356,8 @@ void AsmMatcherInfo::buildInfo() {
std::vector<Record*> AllInstAliases =
Records.getAllDerivedDefinitions("InstAlias");
for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) {
- CodeGenInstAlias *Alias =
- new CodeGenInstAlias(AllInstAliases[i], AsmVariantNo, Target);
+ auto Alias = llvm::make_unique<CodeGenInstAlias>(AllInstAliases[i],
+ AsmVariantNo, Target);
// If the tblgen -match-prefix option is specified (for tblgen hackers),
// filter the set of instruction aliases we consider, based on the target
@@ -1391,14 +1366,14 @@ void AsmMatcherInfo::buildInfo() {
.startswith( MatchPrefix))
continue;
- std::unique_ptr<MatchableInfo> II(new MatchableInfo(Alias));
+ std::unique_ptr<MatchableInfo> II(new MatchableInfo(std::move(Alias)));
II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
// Validate the alias definitions.
II->validate(CommentDelimiter, false);
- Matchables.push_back(II.release());
+ Matchables.push_back(std::move(II));
}
}
@@ -1410,11 +1385,8 @@ void AsmMatcherInfo::buildInfo() {
// Build the information about matchables, now that we have fully formed
// classes.
- std::vector<MatchableInfo*> NewMatchables;
- for (std::vector<MatchableInfo*>::iterator it = Matchables.begin(),
- ie = Matchables.end(); it != ie; ++it) {
- MatchableInfo *II = *it;
-
+ std::vector<std::unique_ptr<MatchableInfo>> NewMatchables;
+ for (auto &II : Matchables) {
// Parse the tokens after the mnemonic.
// Note: buildInstructionOperandReference may insert new AsmOperands, so
// don't precompute the loop bound.
@@ -1449,9 +1421,9 @@ void AsmMatcherInfo::buildInfo() {
OperandName = Token.substr(1);
if (II->DefRec.is<const CodeGenInstruction*>())
- buildInstructionOperandReference(II, OperandName, i);
+ buildInstructionOperandReference(II.get(), OperandName, i);
else
- buildAliasOperandReference(II, OperandName, Op);
+ buildAliasOperandReference(II.get(), OperandName, Op);
}
if (II->DefRec.is<const CodeGenInstruction*>()) {
@@ -1469,14 +1441,14 @@ void AsmMatcherInfo::buildInfo() {
AliasII->formTwoOperandAlias(Constraint);
// Add the alias to the matchables list.
- NewMatchables.push_back(AliasII.release());
+ NewMatchables.push_back(std::move(AliasII));
}
} else
II->buildAliasResultOperands();
}
if (!NewMatchables.empty())
- Matchables.insert(Matchables.end(), NewMatchables.begin(),
- NewMatchables.end());
+ std::move(NewMatchables.begin(), NewMatchables.end(),
+ std::back_inserter(Matchables));
// Process token alias definitions and set up the associated superclass
// information.
@@ -1493,7 +1465,7 @@ void AsmMatcherInfo::buildInfo() {
}
// Reorder classes so that classes precede super classes.
- std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
+ Classes.sort();
}
/// buildInstructionOperandReference - The specified operand is a reference to a
@@ -1703,7 +1675,7 @@ static unsigned getConverterOperandID(const std::string &Name,
static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
- std::vector<MatchableInfo*> &Infos,
+ std::vector<std::unique_ptr<MatchableInfo>> &Infos,
raw_ostream &OS) {
SetVector<std::string> OperandConversionKinds;
SetVector<std::string> InstructionConversionKinds;
@@ -1767,16 +1739,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
OperandConversionKinds.insert("CVT_Tied");
enum { CVT_Done, CVT_Reg, CVT_Tied };
- for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(),
- ie = Infos.end(); it != ie; ++it) {
- MatchableInfo &II = **it;
-
+ for (auto &II : Infos) {
// Check if we have a custom match function.
std::string AsmMatchConverter =
- II.getResultInst()->TheDef->getValueAsString("AsmMatchConverter");
+ II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter");
if (!AsmMatchConverter.empty()) {
std::string Signature = "ConvertCustom_" + AsmMatchConverter;
- II.ConversionFnKind = Signature;
+ II->ConversionFnKind = Signature;
// Check if we have already generated this signature.
if (!InstructionConversionKinds.insert(Signature))
@@ -1808,16 +1777,17 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
std::vector<uint8_t> ConversionRow;
// Compute the convert enum and the case body.
- MaxRowLength = std::max(MaxRowLength, II.ResOperands.size()*2 + 1 );
+ MaxRowLength = std::max(MaxRowLength, II->ResOperands.size()*2 + 1 );
- for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) {
- const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i];
+ for (unsigned i = 0, e = II->ResOperands.size(); i != e; ++i) {
+ const MatchableInfo::ResOperand &OpInfo = II->ResOperands[i];
// Generate code to populate each result operand.
switch (OpInfo.Kind) {
case MatchableInfo::ResOperand::RenderAsmOperand: {
// This comes from something we parsed.
- MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum];
+ const MatchableInfo::AsmOperand &Op =
+ II->AsmOperands[OpInfo.AsmOperandNum];
// Registers are always converted the same, don't duplicate the
// conversion function based on them.
@@ -1879,6 +1849,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
case MatchableInfo::ResOperand::ImmOperand: {
int64_t Val = OpInfo.ImmVal;
std::string Ty = "imm_" + itostr(Val);
+ Ty = getEnumNameForToken(Ty);
Signature += "__" + Ty;
std::string Name = "CVT_" + Ty;
@@ -1940,7 +1911,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
if (Signature == "Convert")
Signature += "_NoOperands";
- II.ConversionFnKind = Signature;
+ II->ConversionFnKind = Signature;
// Save the signature. If we already have it, don't add a new row
// to the table.
@@ -2003,7 +1974,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
/// emitMatchClassEnumeration - Emit the enumeration for match class kinds.
static void emitMatchClassEnumeration(CodeGenTarget &Target,
- std::vector<ClassInfo*> &Infos,
+ std::forward_list<ClassInfo> &Infos,
raw_ostream &OS) {
OS << "namespace {\n\n";
@@ -2011,9 +1982,7 @@ static void emitMatchClassEnumeration(CodeGenTarget &Target,
<< "/// instruction matching.\n";
OS << "enum MatchClassKind {\n";
OS << " InvalidMatchClass = 0,\n";
- for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
- ie = Infos.end(); it != ie; ++it) {
- ClassInfo &CI = **it;
+ for (const auto &CI : Infos) {
OS << " " << CI.Name << ", // ";
if (CI.Kind == ClassInfo::Token) {
OS << "'" << CI.ValueName << "'\n";
@@ -2053,10 +2022,7 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info,
// Check the user classes. We don't care what order since we're only
// actually matching against one of them.
- for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(),
- ie = Info.Classes.end(); it != ie; ++it) {
- ClassInfo &CI = **it;
-
+ for (const auto &CI : Info.Classes) {
if (!CI.isUserClass())
continue;
@@ -2075,11 +2041,9 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info,
OS << " MatchClassKind OpKind;\n";
OS << " switch (Operand.getReg()) {\n";
OS << " default: OpKind = InvalidMatchClass; break;\n";
- for (AsmMatcherInfo::RegisterClassesTy::iterator
- it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
- it != ie; ++it)
+ for (const auto &RC : Info.RegisterClasses)
OS << " case " << Info.Target.getName() << "::"
- << it->first->getName() << ": OpKind = " << it->second->Name
+ << RC.first->getName() << ": OpKind = " << RC.second->Name
<< "; break;\n";
OS << " }\n";
OS << " return isSubclass(OpKind, Kind) ? "
@@ -2094,7 +2058,7 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info,
/// emitIsSubclass - Emit the subclass predicate function.
static void emitIsSubclass(CodeGenTarget &Target,
- std::vector<ClassInfo*> &Infos,
+ std::forward_list<ClassInfo> &Infos,
raw_ostream &OS) {
OS << "/// isSubclass - Compute whether \\p A is a subclass of \\p B.\n";
OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n";
@@ -2107,15 +2071,9 @@ static void emitIsSubclass(CodeGenTarget &Target,
SS << " switch (A) {\n";
SS << " default:\n";
SS << " return false;\n";
- for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
- ie = Infos.end(); it != ie; ++it) {
- ClassInfo &A = **it;
-
+ for (const auto &A : Infos) {
std::vector<StringRef> SuperClasses;
- for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
- ie = Infos.end(); it != ie; ++it) {
- ClassInfo &B = **it;
-
+ for (const auto &B : Infos) {
if (&A != &B && A.isSubsetOf(B))
SuperClasses.push_back(B.Name);
}
@@ -2157,17 +2115,14 @@ static void emitIsSubclass(CodeGenTarget &Target,
/// emitMatchTokenString - Emit the function to match a token string to the
/// appropriate match class value.
static void emitMatchTokenString(CodeGenTarget &Target,
- std::vector<ClassInfo*> &Infos,
+ std::forward_list<ClassInfo> &Infos,
raw_ostream &OS) {
// Construct the match list.
std::vector<StringMatcher::StringPair> Matches;
- for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
- ie = Infos.end(); it != ie; ++it) {
- ClassInfo &CI = **it;
-
+ for (const auto &CI : Infos) {
if (CI.Kind == ClassInfo::Token)
- Matches.push_back(StringMatcher::StringPair(CI.ValueName,
- "return " + CI.Name + ";"));
+ Matches.push_back(
+ StringMatcher::StringPair(CI.ValueName, "return " + CI.Name + ";"));
}
OS << "static MatchClassKind matchTokenString(StringRef Name) {\n";
@@ -2184,16 +2139,14 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
raw_ostream &OS) {
// Construct the match list.
std::vector<StringMatcher::StringPair> Matches;
- const std::vector<CodeGenRegister*> &Regs =
- Target.getRegBank().getRegisters();
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- const CodeGenRegister *Reg = Regs[i];
- if (Reg->TheDef->getValueAsString("AsmName").empty())
+ const auto &Regs = Target.getRegBank().getRegisters();
+ for (const CodeGenRegister &Reg : Regs) {
+ if (Reg.TheDef->getValueAsString("AsmName").empty())
continue;
- Matches.push_back(StringMatcher::StringPair(
- Reg->TheDef->getValueAsString("AsmName"),
- "return " + utostr(Reg->EnumValue) + ";"));
+ Matches.push_back(
+ StringMatcher::StringPair(Reg.TheDef->getValueAsString("AsmName"),
+ "return " + utostr(Reg.EnumValue) + ";"));
}
OS << "static unsigned MatchRegisterName(StringRef Name) {\n";
@@ -2230,10 +2183,8 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info,
<< "instruction matching.\n";
OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info)
<< " {\n";
- for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator
- it = Info.SubtargetFeatures.begin(),
- ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
- SubtargetFeatureInfo &SFI = *it->second;
+ for (const auto &SF : Info.SubtargetFeatures) {
+ const SubtargetFeatureInfo &SFI = SF.second;
OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n";
}
OS << " Feature_None = 0\n";
@@ -2268,10 +2219,8 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
<< "static const char *getSubtargetFeatureName(uint64_t Val) {\n";
if (!Info.SubtargetFeatures.empty()) {
OS << " switch(Val) {\n";
- typedef std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> RecFeatMap;
- for (RecFeatMap::const_iterator it = Info.SubtargetFeatures.begin(),
- ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
- SubtargetFeatureInfo &SFI = *it->second;
+ for (const auto &SF : Info.SubtargetFeatures) {
+ const SubtargetFeatureInfo &SFI = SF.second;
// FIXME: Totally just a placeholder name to get the algorithm working.
OS << " case " << SFI.getEnumName() << ": return \""
<< SFI.TheDef->getValueAsString("PredicateName") << "\";\n";
@@ -2295,10 +2244,8 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n"
<< "ComputeAvailableFeatures(uint64_t FB) const {\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) {
- SubtargetFeatureInfo &SFI = *it->second;
+ for (const auto &SF : Info.SubtargetFeatures) {
+ const SubtargetFeatureInfo &SFI = SF.second;
OS << " if (";
std::string CondStorage =
@@ -2344,7 +2291,7 @@ static std::string GetAliasRequiredFeatures(Record *R,
std::string Result;
unsigned NumFeatures = 0;
for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {
- SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
+ const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
if (!F)
PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() +
@@ -2488,8 +2435,8 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
<< " RequiredFeatures;\n";
OS << " " << getMinimalTypeForRange(MaxMnemonicIndex)
<< " Mnemonic;\n";
- OS << " " << getMinimalTypeForRange(Info.Classes.size())
- << " Class;\n";
+ OS << " " << getMinimalTypeForRange(std::distance(
+ Info.Classes.begin(), Info.Classes.end())) << " Class;\n";
OS << " " << getMinimalTypeForRange(MaxMask)
<< " OperandMask;\n\n";
OS << " StringRef getMnemonic() const {\n";
@@ -2566,13 +2513,11 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
<< " &Operands,\n unsigned MCK) {\n\n"
<< " switch(MCK) {\n";
- for (std::vector<ClassInfo*>::const_iterator it = Info.Classes.begin(),
- ie = Info.Classes.end(); it != ie; ++it) {
- ClassInfo *CI = *it;
- if (CI->ParserMethod.empty())
+ for (const auto &CI : Info.Classes) {
+ if (CI.ParserMethod.empty())
continue;
- OS << " case " << CI->Name << ":\n"
- << " return " << CI->ParserMethod << "(Operands);\n";
+ OS << " case " << CI.Name << ":\n"
+ << " return " << CI.ParserMethod << "(Operands);\n";
}
OS << " default:\n";
@@ -2651,22 +2596,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// stable_sort to ensure that ambiguous instructions are still
// deterministically ordered.
std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(),
- less_ptr<MatchableInfo>());
+ [](const std::unique_ptr<MatchableInfo> &a,
+ const std::unique_ptr<MatchableInfo> &b){
+ return *a < *b;});
DEBUG_WITH_TYPE("instruction_info", {
- for (std::vector<MatchableInfo*>::iterator
- it = Info.Matchables.begin(), ie = Info.Matchables.end();
- it != ie; ++it)
- (*it)->dump();
+ for (const auto &MI : Info.Matchables)
+ MI->dump();
});
// Check for ambiguous matchables.
DEBUG_WITH_TYPE("ambiguous_instrs", {
unsigned NumAmbiguous = 0;
- for (unsigned i = 0, e = Info.Matchables.size(); i != e; ++i) {
- for (unsigned j = i + 1; j != e; ++j) {
- MatchableInfo &A = *Info.Matchables[i];
- MatchableInfo &B = *Info.Matchables[j];
+ for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;
+ ++I) {
+ for (auto J = std::next(I); J != E; ++J) {
+ const MatchableInfo &A = **I;
+ const MatchableInfo &B = **J;
if (A.couldMatchAmbiguouslyWith(B)) {
errs() << "warning: ambiguous matchables:\n";
@@ -2701,15 +2647,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " void convertToMapAndConstraints(unsigned Kind,\n ";
OS << " const OperandVector &Operands) override;\n";
OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) override;\n";
- OS << " unsigned MatchInstructionImpl(\n";
- OS.indent(27);
- OS << "const OperandVector &Operands,\n"
+ OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n"
<< " MCInst &Inst,\n"
<< " uint64_t &ErrorInfo,"
<< " bool matchingInlineAsm,\n"
<< " unsigned VariantID = 0);\n";
- if (Info.OperandMatchInfo.size()) {
+ if (!Info.OperandMatchInfo.empty()) {
OS << "\n enum OperandMatchResultTy {\n";
OS << " MatchOperand_Success, // operand matched successfully\n";
OS << " MatchOperand_NoMatch, // operand did not match\n";
@@ -2786,15 +2730,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
size_t MaxNumOperands = 0;
unsigned MaxMnemonicIndex = 0;
bool HasDeprecation = false;
- for (std::vector<MatchableInfo*>::const_iterator it =
- Info.Matchables.begin(), ie = Info.Matchables.end();
- it != ie; ++it) {
- MatchableInfo &II = **it;
- MaxNumOperands = std::max(MaxNumOperands, II.AsmOperands.size());
- HasDeprecation |= II.HasDeprecation;
+ for (const auto &MI : Info.Matchables) {
+ MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());
+ HasDeprecation |= MI->HasDeprecation;
// Store a pascal-style length byte in the mnemonic.
- std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str();
+ std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str();
MaxMnemonicIndex = std::max(MaxMnemonicIndex,
StringTable.GetOrAddStringOffset(LenMnemonic, false));
}
@@ -2822,8 +2763,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< " ConvertFn;\n";
OS << " " << getMinimalRequiredFeaturesType(Info)
<< " RequiredFeatures;\n";
- OS << " " << getMinimalTypeForRange(Info.Classes.size())
- << " Classes[" << MaxNumOperands << "];\n";
+ OS << " " << getMinimalTypeForRange(
+ std::distance(Info.Classes.begin(), Info.Classes.end()))
+ << " Classes[" << MaxNumOperands << "];\n";
OS << " StringRef getMnemonic() const {\n";
OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n";
OS << " MnemonicTable[Mnemonic]);\n";
@@ -2852,33 +2794,30 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "static const MatchEntry MatchTable" << VC << "[] = {\n";
- for (std::vector<MatchableInfo*>::const_iterator it =
- Info.Matchables.begin(), ie = Info.Matchables.end();
- it != ie; ++it) {
- MatchableInfo &II = **it;
- if (II.AsmVariantID != AsmVariantNo)
+ for (const auto &MI : Info.Matchables) {
+ if (MI->AsmVariantID != AsmVariantNo)
continue;
// Store a pascal-style length byte in the mnemonic.
- std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str();
+ std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str();
OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false)
- << " /* " << II.Mnemonic << " */, "
+ << " /* " << MI->Mnemonic << " */, "
<< Target.getName() << "::"
- << II.getResultInst()->TheDef->getName() << ", "
- << II.ConversionFnKind << ", ";
+ << MI->getResultInst()->TheDef->getName() << ", "
+ << MI->ConversionFnKind << ", ";
// Write the required features mask.
- if (!II.RequiredFeatures.empty()) {
- for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) {
+ if (!MI->RequiredFeatures.empty()) {
+ for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i) {
if (i) OS << "|";
- OS << II.RequiredFeatures[i]->getEnumName();
+ OS << MI->RequiredFeatures[i]->getEnumName();
}
} else
OS << "0";
OS << ", { ";
- for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) {
- MatchableInfo::AsmOperand &Op = II.AsmOperands[i];
+ for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) {
+ const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i];
if (i) OS << ", ";
OS << Op.Class->Name;
@@ -2895,7 +2834,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " // Find the appropriate table for this asm variant.\n";
OS << " const MatchEntry *Start, *End;\n";
OS << " switch (VariantID) {\n";
- OS << " default: // unreachable\n";
+ OS << " default: llvm_unreachable(\"invalid variant!\");\n";
for (unsigned VC = 0; VC != VariantCount; ++VC) {
Record *AsmVariant = Target.getAsmParserVariant(VC);
int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
@@ -2911,10 +2850,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Finally, build the match function.
OS << "unsigned " << Target.getName() << ClassName << "::\n"
- << "MatchInstructionImpl(const OperandVector"
- << " &Operands,\n";
- OS << " MCInst &Inst,\n"
- << "uint64_t &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n";
+ << "MatchInstructionImpl(const OperandVector &Operands,\n";
+ OS << " MCInst &Inst, uint64_t &ErrorInfo,\n"
+ << " bool matchingInlineAsm, unsigned VariantID) {\n";
OS << " // Eliminate obvious mismatches.\n";
OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n";
@@ -2949,7 +2887,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " // Find the appropriate table for this asm variant.\n";
OS << " const MatchEntry *Start, *End;\n";
OS << " switch (VariantID) {\n";
- OS << " default: // unreachable\n";
+ OS << " default: llvm_unreachable(\"invalid variant!\");\n";
for (unsigned VC = 0; VC != VariantCount; ++VC) {
Record *AsmVariant = Target.getAsmParserVariant(VC);
int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
@@ -3018,12 +2956,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " HadMatchOtherThanFeatures = true;\n";
OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & "
"~AvailableFeatures;\n";
- OS << " if (CountPopulation_64(NewMissingFeatures) <=\n"
- " CountPopulation_64(MissingFeatures))\n";
+ OS << " if (countPopulation(NewMissingFeatures) <=\n"
+ " countPopulation(MissingFeatures))\n";
OS << " MissingFeatures = NewMissingFeatures;\n";
OS << " continue;\n";
OS << " }\n";
OS << "\n";
+ OS << " Inst.clear();\n\n";
OS << " if (matchingInlineAsm) {\n";
OS << " Inst.setOpcode(it->Opcode);\n";
OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";
@@ -3072,7 +3011,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " return Match_MissingFeature;\n";
OS << "}\n\n";
- if (Info.OperandMatchInfo.size())
+ if (!Info.OperandMatchInfo.empty())
emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable,
MaxMnemonicIndex);
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index 7ef70d3..587de26 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -208,9 +208,6 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
// Otherwise, scan to see if all of the other instructions in this command
// set share the operand.
bool AllSame = true;
- // Keep track of the maximum, number of operands or any
- // instruction we see in the group.
- size_t MaxSize = FirstInst->Operands.size();
for (NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx);
NIT != InstIdxs.end();
@@ -220,10 +217,6 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
const AsmWriterInst *OtherInst =
getAsmWriterInstByID(NIT-InstIdxs.begin());
- if (OtherInst &&
- OtherInst->Operands.size() > FirstInst->Operands.size())
- MaxSize = std::max(MaxSize, OtherInst->Operands.size());
-
if (!OtherInst || OtherInst->Operands.size() == Op ||
OtherInst->Operands[Op] != FirstInst->Operands[Op]) {
AllSame = false;
@@ -350,7 +343,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
// in the opcode-indexed table.
unsigned BitsLeft = 64-AsmStrBits;
- std::vector<std::vector<std::string> > TableDrivenOperandPrinters;
+ std::vector<std::vector<std::string>> TableDrivenOperandPrinters;
while (1) {
std::vector<std::string> UniqueOperandCommands;
@@ -393,7 +386,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
}
// Remember the handlers for this set of operands.
- TableDrivenOperandPrinters.push_back(UniqueOperandCommands);
+ TableDrivenOperandPrinters.push_back(std::move(UniqueOperandCommands));
}
@@ -474,7 +467,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
O << " switch ((Bits >> "
<< (64-BitsLeft) << ") & "
<< ((1 << NumBits)-1) << ") {\n"
- << " default: // unreachable.\n";
+ << " default: llvm_unreachable(\"Invalid command number.\");\n";
// Print out all the cases.
for (unsigned i = 0, e = Commands.size(); i != e; ++i) {
@@ -520,14 +513,23 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
O << "}\n";
}
+static const char *getMinimalTypeForRange(uint64_t Range) {
+ assert(Range < 0xFFFFFFFFULL && "Enum too large");
+ if (Range > 0xFFFF)
+ return "uint32_t";
+ if (Range > 0xFF)
+ return "uint16_t";
+ return "uint8_t";
+}
+
static void
emitRegisterNameString(raw_ostream &O, StringRef AltName,
- const std::vector<CodeGenRegister*> &Registers) {
+ const std::deque<CodeGenRegister> &Registers) {
SequenceToOffsetTable<std::string> StringTable;
SmallVector<std::string, 4> AsmNames(Registers.size());
- for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
- const CodeGenRegister &Reg = *Registers[i];
- std::string &AsmName = AsmNames[i];
+ unsigned i = 0;
+ for (const auto &Reg : Registers) {
+ std::string &AsmName = AsmNames[i++];
// "NoRegAltName" is special. We don't need to do a lookup for that,
// as it's just a reference to the default register name.
@@ -564,7 +566,8 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
StringTable.emit(O, printChar);
O << " };\n\n";
- O << " static const uint32_t RegAsmOffset" << AltName << "[] = {";
+ O << " static const " << getMinimalTypeForRange(StringTable.size()-1)
+ << " RegAsmOffset" << AltName << "[] = {";
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
if ((i % 14) == 0)
O << "\n ";
@@ -577,8 +580,7 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
Record *AsmWriter = Target.getAsmWriter();
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
- const std::vector<CodeGenRegister*> &Registers =
- Target.getRegBank().getRegisters();
+ const auto &Registers = Target.getRegBank().getRegisters();
std::vector<Record*> AltNameIndices = Target.getRegAltNameIndices();
bool hasAltNames = AltNameIndices.size() > 1;
@@ -602,26 +604,25 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
emitRegisterNameString(O, "", Registers);
if (hasAltNames) {
- O << " const uint32_t *RegAsmOffset;\n"
- << " const char *AsmStrs;\n"
- << " switch(AltIdx) {\n"
+ O << " switch(AltIdx) {\n"
<< " default: llvm_unreachable(\"Invalid register alt name index!\");\n";
for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) {
std::string Namespace = AltNameIndices[1]->getValueAsString("Namespace");
std::string AltName(AltNameIndices[i]->getName());
- O << " case " << Namespace << "::" << AltName
- << ":\n"
- << " AsmStrs = AsmStrs" << AltName << ";\n"
- << " RegAsmOffset = RegAsmOffset" << AltName << ";\n"
- << " break;\n";
+ O << " case " << Namespace << "::" << AltName << ":\n"
+ << " assert(*(AsmStrs" << AltName << "+RegAsmOffset"
+ << AltName << "[RegNo-1]) &&\n"
+ << " \"Invalid alt name index for register!\");\n"
+ << " return AsmStrs" << AltName << "+RegAsmOffset"
+ << AltName << "[RegNo-1];\n";
}
- O << "}\n";
+ O << " }\n";
+ } else {
+ O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
+ << " \"Invalid alt name index for register!\");\n"
+ << " return AsmStrs+RegAsmOffset[RegNo-1];\n";
}
-
- O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
- << " \"Invalid alt name index for register!\");\n"
- << " return AsmStrs+RegAsmOffset[RegNo-1];\n"
- << "}\n";
+ O << "}\n";
}
namespace {
@@ -654,20 +655,26 @@ public:
std::pair<StringRef, StringRef::iterator> parseName(StringRef::iterator Start,
StringRef::iterator End) {
StringRef::iterator I = Start;
+ StringRef::iterator Next;
if (*I == '{') {
// ${some_name}
Start = ++I;
while (I != End && *I != '}')
++I;
+ Next = I;
+ // eat the final '}'
+ if (Next != End)
+ ++Next;
} else {
// $name, just eat the usual suspects.
while (I != End &&
((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') ||
(*I >= '0' && *I <= '9') || *I == '_'))
++I;
+ Next = I;
}
- return std::make_pair(StringRef(Start, I - Start), I);
+ return std::make_pair(StringRef(Start, I - Start), Next);
}
void print(raw_ostream &O) {
@@ -991,7 +998,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
return;
}
- if (MCOpPredicates.size())
+ if (!MCOpPredicates.empty())
O << "static bool " << Target.getName() << ClassName
<< "ValidateMCOperand(\n"
<< " const MCOperand &MCOp, unsigned PredicateIndex);\n";
@@ -1057,7 +1064,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
}
O << "}\n\n";
- if (MCOpPredicates.size()) {
+ if (!MCOpPredicates.empty()) {
O << "static bool " << Target.getName() << ClassName
<< "ValidateMCOperand(\n"
<< " const MCOperand &MCOp, unsigned PredicateIndex) {\n"
@@ -1084,13 +1091,10 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) {
Record *AsmWriter = Target.getAsmWriter();
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end();
- I != E; ++I)
- if (!(*I)->AsmString.empty() && (*I)->TheDef->getName() != "PHI")
+ for (const CodeGenInstruction *I : Target.instructions())
+ if (!I->AsmString.empty() && I->TheDef->getName() != "PHI")
Instructions.push_back(
- AsmWriterInst(**I, AsmWriter->getValueAsInt("Variant"),
- AsmWriter->getValueAsInt("OperandSpacing")));
+ AsmWriterInst(*I, AsmWriter->getValueAsInt("Variant")));
// Get the instruction numbering.
NumberedInstructions = &Target.getInstructionsByEnumValue();
diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp
index 5d9ead1..6ddc510 100644
--- a/utils/TableGen/AsmWriterInst.cpp
+++ b/utils/TableGen/AsmWriterInst.cpp
@@ -48,9 +48,7 @@ std::string AsmWriterOperand::getCode() const {
/// ParseAsmString - Parse the specified Instruction's AsmString into this
/// AsmWriterInst.
///
-AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
- unsigned Variant,
- int OperandSpacing) {
+AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
this->CGI = &CGI;
// NOTE: Any extensions to this code need to be mirrored in the
diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h
index fd77982..6a900b7 100644
--- a/utils/TableGen/AsmWriterInst.h
+++ b/utils/TableGen/AsmWriterInst.h
@@ -88,8 +88,7 @@ namespace llvm {
const CodeGenInstruction *CGI;
AsmWriterInst(const CodeGenInstruction &CGI,
- unsigned Variant,
- int OperandSpacing);
+ unsigned Variant);
/// MatchesAllButOneOp - If this instruction is exactly identical to the
/// specified instruction except for one differing operand, return the
diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp
index 6a65e5e..051a7e9 100644
--- a/utils/TableGen/CallingConvEmitter.cpp
+++ b/utils/TableGen/CallingConvEmitter.cpp
@@ -124,7 +124,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
}
O << "\n" << IndentStr << "};\n";
O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
- << Counter << ", " << RegList->getSize() << ")) {\n";
+ << Counter << ")) {\n";
}
O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
<< "Reg, LocVT, LocInfo));\n";
@@ -166,7 +166,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
<< RegListNumber << ", " << "RegList" << ShadowRegListNumber
- << ", " << RegList->getSize() << ")) {\n";
+ << ")) {\n";
}
O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
<< "Reg, LocVT, LocInfo));\n";
@@ -182,14 +182,14 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << Size << ", ";
else
O << "\n" << IndentStr
- << " State.getMachineFunction().getSubtarget().getDataLayout()"
+ << " State.getMachineFunction().getTarget().getDataLayout()"
"->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
" ";
if (Align)
O << Align;
else
O << "\n" << IndentStr
- << " State.getMachineFunction().getSubtarget().getDataLayout()"
+ << " State.getMachineFunction().getTarget().getDataLayout()"
"->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()"
"))";
O << ");\n" << IndentStr
@@ -215,8 +215,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << IndentStr << "unsigned Offset" << ++Counter
<< " = State.AllocateStack("
<< Size << ", " << Align << ", "
- << "ShadowRegList" << ShadowRegListNumber << ", "
- << ShadowRegList->getSize() << ");\n";
+ << "ShadowRegList" << ShadowRegListNumber << ");\n";
O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
<< Counter << ", LocVT, LocInfo));\n";
O << IndentStr << "return false;\n";
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 11911b6..46fcdf5 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -96,7 +96,7 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
/// generated emitter, skip it.
while (NumberedOp < NumberOps &&
(CGI.Operands.isFlatOperandNotEmitted(NumberedOp) ||
- (NamedOpIndices.size() && NamedOpIndices.count(
+ (!NamedOpIndices.empty() && NamedOpIndices.count(
CGI.Operands.getSubOperandNumber(NumberedOp).first)))) {
++NumberedOp;
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index a750aa9..4e3e588 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -53,7 +53,7 @@ EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) {
EnforceVector(TP);
else {
assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR ||
- VT == MVT::iPTRAny) && "Not a concrete type!");
+ VT == MVT::iPTRAny || VT == MVT::Any) && "Not a concrete type!");
TypeVec.push_back(VT);
}
}
@@ -1113,6 +1113,8 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
// FIXME: Should allow access to all the results here.
unsigned NumDefsToAdd = InstInfo.Operands.NumDefs ? 1 : 0;
+ if (InstInfo.hasTwoExplicitDefs)
+ ++NumDefsToAdd;
// Add on one implicit def if it has a resolvable type.
if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other)
@@ -1539,6 +1541,22 @@ static bool isOperandClass(const TreePatternNode *N, StringRef Class) {
return false;
}
+
+static void emitTooManyOperandsError(TreePattern &TP,
+ StringRef InstName,
+ unsigned Expected,
+ unsigned Actual) {
+ TP.error("Instruction '" + InstName + "' was provided " + Twine(Actual) +
+ " operands but expected only " + Twine(Expected) + "!");
+}
+
+static void emitTooFewOperandsError(TreePattern &TP,
+ StringRef InstName,
+ unsigned Actual) {
+ TP.error("Instruction '" + InstName +
+ "' expects more than the provided " + Twine(Actual) + " operands!");
+}
+
/// 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.
@@ -1593,11 +1611,20 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
assert(getNumTypes() == 0 && "Set doesn't produce a value");
assert(getNumChildren() >= 2 && "Missing RHS of a set?");
unsigned NC = getNumChildren();
+ unsigned NumOfSrcs = NC-1;
+ // destination
TreePatternNode *SetVal = getChild(NC-1);
bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters);
- for (unsigned i = 0; i < NC-1; ++i) {
+ // second explicit destination
+ if (TP.getRecord()->getValueAsBit("hasTwoExplicitDefs")) {
+ TreePatternNode *Set2Val = getChild(NC-2);
+ MadeChange = Set2Val->ApplyTypeConstraints(TP, NotRegisters);
+ NumOfSrcs --;
+ }
+
+ for (unsigned i = 0; i < NumOfSrcs; ++i) {
TreePatternNode *Child = getChild(i);
MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
@@ -1741,8 +1768,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
// Verify that we didn't run out of provided operands.
if (ChildNo >= getNumChildren()) {
- TP.error("Instruction '" + getOperator()->getName() +
- "' expects more operands than were provided.");
+ emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren());
return false;
}
@@ -1766,8 +1792,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
// And the remaining sub-operands against subsequent children.
for (unsigned Arg = 1; Arg < NumArgs; ++Arg) {
if (ChildNo >= getNumChildren()) {
- TP.error("Instruction '" + getOperator()->getName() +
- "' expects more operands than were provided.");
+ emitTooFewOperandsError(TP, getOperator()->getName(),
+ getNumChildren());
return false;
}
Child = getChild(ChildNo++);
@@ -1787,8 +1813,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
}
if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) {
- TP.error("Instruction '" + getOperator()->getName() +
- "' was provided too many operands!");
+ emitTooManyOperandsError(TP, getOperator()->getName(),
+ ChildNo, getNumChildren());
return false;
}
@@ -2554,8 +2580,10 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
I->error("set destination should be a register!");
DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue());
- if (!Val)
+ if (!Val) {
I->error("set destination should be a register!");
+ continue;
+ }
if (Val->getDef()->isSubClassOf("RegisterClass") ||
Val->getDef()->isSubClassOf("ValueType") ||
@@ -2839,7 +2867,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
// Check that all of the results occur first in the list.
std::vector<Record*> Results;
- TreePatternNode *Res0Node = nullptr;
+ SmallVector<TreePatternNode *, 2> ResNode;
for (unsigned i = 0; i != NumResults; ++i) {
if (i == CGI.Operands.size())
I->error("'" + InstResults.begin()->first +
@@ -2851,8 +2879,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
if (!RNode)
I->error("Operand $" + OpName + " does not exist in operand list!");
- if (i == 0)
- Res0Node = RNode;
+ ResNode.push_back(RNode);
Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();
if (!R)
I->error("Operand $" + OpName + " should be a set destination: all "
@@ -2929,7 +2956,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
GetNumNodeResults(I->getRecord(), *this));
// Copy fully inferred output node type to instruction result pattern.
for (unsigned i = 0; i != NumResults; ++i)
- ResultPattern->setType(i, Res0Node->getExtType(i));
+ ResultPattern->setType(i, ResNode[i]->getExtType(0));
// Create and insert the instruction.
// FIXME: InstImpResults should not be part of DAGInstruction.
@@ -3111,13 +3138,6 @@ void CodeGenDAGPatterns::InferInstructionFlags() {
CodeGenInstruction &InstInfo =
const_cast<CodeGenInstruction &>(*Instructions[i]);
- // Treat neverHasSideEffects = 1 as the equivalent of hasSideEffects = 0.
- // This flag is obsolete and will be removed.
- if (InstInfo.neverHasSideEffects) {
- assert(!InstInfo.hasSideEffects);
- InstInfo.hasSideEffects_Unset = false;
- }
-
// Get the primary instruction pattern.
const TreePattern *Pattern = getInstruction(InstInfo.TheDef).getPattern();
if (!Pattern) {
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index d567dde..b1e4318 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -68,10 +68,13 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
std::string PrintMethod = "printOperand";
std::string EncoderMethod;
std::string OperandType = "OPERAND_UNKNOWN";
+ std::string OperandNamespace = "MCOI";
unsigned NumOps = 1;
DagInit *MIOpInfo = nullptr;
if (Rec->isSubClassOf("RegisterOperand")) {
PrintMethod = Rec->getValueAsString("PrintMethod");
+ OperandType = Rec->getValueAsString("OperandType");
+ OperandNamespace = Rec->getValueAsString("OperandNamespace");
} else if (Rec->isSubClassOf("Operand")) {
PrintMethod = Rec->getValueAsString("PrintMethod");
OperandType = Rec->getValueAsString("OperandType");
@@ -113,8 +116,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
Twine(i) + " has the same name as a previous operand!");
OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod,
- OperandType, MIOperandNo, NumOps,
- MIOpInfo));
+ OperandNamespace + "::" + OperandType,
+ MIOperandNo, NumOps, MIOpInfo));
MIOperandNo += NumOps;
}
@@ -317,6 +320,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
isRegSequence = R->getValueAsBit("isRegSequence");
isExtractSubreg = R->getValueAsBit("isExtractSubreg");
isInsertSubreg = R->getValueAsBit("isInsertSubreg");
+ hasTwoExplicitDefs = R->getValueAsBit("hasTwoExplicitDefs");
bool Unset;
mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);
@@ -325,7 +329,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
mayStore_Unset = Unset;
hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset);
hasSideEffects_Unset = Unset;
- neverHasSideEffects = R->getValueAsBit("neverHasSideEffects");
isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
@@ -335,9 +338,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
ImplicitDefs = R->getValueAsListOfDefs("Defs");
ImplicitUses = R->getValueAsListOfDefs("Uses");
- if (neverHasSideEffects + hasSideEffects > 1)
- PrintFatalError(R->getName() + ": multiple conflicting side-effect flags set!");
-
// Parse Constraints.
ParseConstraints(R->getValueAsString("Constraints"), Operands);
@@ -541,7 +541,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
// 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.
- if (InstOpRec->isSubClassOf("Operand") &&
+ if (InstOpRec->isSubClassOf("Operand") && ADI &&
ADI->getDef()->isSubClassOf("Operand")) {
// FIXME: What other attributes should we check here? Identical
// MIOperandInfo perhaps?
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index 92aac5f..82b23f4 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -247,7 +247,6 @@ namespace llvm {
bool isNotDuplicable : 1;
bool hasSideEffects : 1;
bool hasSideEffects_Unset : 1;
- bool neverHasSideEffects : 1;
bool isAsCheapAsAMove : 1;
bool hasExtraSrcRegAllocReq : 1;
bool hasExtraDefRegAllocReq : 1;
@@ -256,6 +255,7 @@ namespace llvm {
bool isRegSequence : 1;
bool isExtractSubreg : 1;
bool isInsertSubreg : 1;
+ bool hasTwoExplicitDefs : 1;
std::string DeprecatedReason;
bool HasComplexDeprecationPredicate;
diff --git a/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp
index 7e5aa9c..8abea48 100644
--- a/utils/TableGen/CodeGenMapTable.cpp
+++ b/utils/TableGen/CodeGenMapTable.cpp
@@ -376,7 +376,7 @@ unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) {
std::vector<Record*> ColInstrs = MapTable[CurInstr];
std::string OutStr("");
unsigned RelExists = 0;
- if (ColInstrs.size()) {
+ if (!ColInstrs.empty()) {
for (unsigned j = 0; j < NumCol; j++) {
if (ColInstrs[j] != nullptr) {
RelExists = 1;
@@ -567,7 +567,7 @@ void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) {
std::vector<Record*> InstrMapVec;
InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping");
- if (!InstrMapVec.size())
+ if (InstrMapVec.empty())
return;
OS << "#ifdef GET_INSTRMAP_INFO\n";
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp
index 678222f..37f8905 100644
--- a/utils/TableGen/CodeGenRegisters.cpp
+++ b/utils/TableGen/CodeGenRegisters.cpp
@@ -82,7 +82,7 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
}
}
-unsigned CodeGenSubRegIndex::computeLaneMask() {
+unsigned CodeGenSubRegIndex::computeLaneMask() const {
// Already computed?
if (LaneMask)
return LaneMask;
@@ -92,8 +92,8 @@ unsigned CodeGenSubRegIndex::computeLaneMask() {
// The lane mask is simply the union of all sub-indices.
unsigned M = 0;
- for (CompMap::iterator I = Composed.begin(), E = Composed.end(); I != E; ++I)
- M |= I->second->computeLaneMask();
+ for (const auto &C : Composed)
+ M |= C.second->computeLaneMask();
assert(M && "Missing lane mask, sub-register cycle?");
LaneMask = M;
return LaneMask;
@@ -108,7 +108,6 @@ CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum)
EnumValue(Enum),
CostPerUse(R->getValueAsInt("CostPerUse")),
CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
- NumNativeRegUnits(0),
SubRegsComplete(false),
SuperRegsComplete(false),
TopoSig(~0u)
@@ -146,17 +145,18 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
}
const std::string &CodeGenRegister::getName() const {
+ assert(TheDef && "no def");
return TheDef->getName();
}
namespace {
// Iterate over all register units in a set of registers.
class RegUnitIterator {
- CodeGenRegister::Set::const_iterator RegI, RegE;
- CodeGenRegister::RegUnitList::const_iterator UnitI, UnitE;
+ CodeGenRegister::Vec::const_iterator RegI, RegE;
+ CodeGenRegister::RegUnitList::iterator UnitI, UnitE;
public:
- RegUnitIterator(const CodeGenRegister::Set &Regs):
+ RegUnitIterator(const CodeGenRegister::Vec &Regs):
RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() {
if (RegI != RegE) {
@@ -191,32 +191,23 @@ protected:
};
} // namespace
-// Merge two RegUnitLists maintaining the order and removing duplicates.
-// Overwrites MergedRU in the process.
-static void mergeRegUnits(CodeGenRegister::RegUnitList &MergedRU,
- const CodeGenRegister::RegUnitList &RRU) {
- CodeGenRegister::RegUnitList LRU = MergedRU;
- MergedRU.clear();
- std::set_union(LRU.begin(), LRU.end(), RRU.begin(), RRU.end(),
- std::back_inserter(MergedRU));
-}
-
// Return true of this unit appears in RegUnits.
static bool hasRegUnit(CodeGenRegister::RegUnitList &RegUnits, unsigned Unit) {
- return std::count(RegUnits.begin(), RegUnits.end(), Unit);
+ return RegUnits.test(Unit);
}
// Inherit register units from subregisters.
// Return true if the RegUnits changed.
bool CodeGenRegister::inheritRegUnits(CodeGenRegBank &RegBank) {
- unsigned OldNumUnits = RegUnits.size();
+ bool changed = false;
for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
I != E; ++I) {
CodeGenRegister *SR = I->second;
// Merge the subregister's units into this register's RegUnits.
- mergeRegUnits(RegUnits, SR->RegUnits);
+ changed |= (RegUnits |= SR->RegUnits);
}
- return OldNumUnits != RegUnits.size();
+
+ return changed;
}
const CodeGenRegister::SubRegMap &
@@ -362,14 +353,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
// sub-registers, the other registers won't contribute any more units.
for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
CodeGenRegister *SR = ExplicitSubRegs[i];
- // Explicit sub-registers are usually disjoint, so this is a good way of
- // computing the union. We may pick up a few duplicates that will be
- // eliminated below.
- unsigned N = RegUnits.size();
- RegUnits.append(SR->RegUnits.begin(), SR->RegUnits.end());
- std::inplace_merge(RegUnits.begin(), RegUnits.begin() + N, RegUnits.end());
+ RegUnits |= SR->RegUnits;
}
- RegUnits.erase(std::unique(RegUnits.begin(), RegUnits.end()), RegUnits.end());
// Absent any ad hoc aliasing, we create one register unit per leaf register.
// These units correspond to the maximal cliques in the register overlap
@@ -388,19 +373,19 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
// Create a RegUnit representing this alias edge, and add it to both
// registers.
unsigned Unit = RegBank.newRegUnit(this, AR);
- RegUnits.push_back(Unit);
- AR->RegUnits.push_back(Unit);
+ RegUnits.set(Unit);
+ AR->RegUnits.set(Unit);
}
// Finally, create units for leaf registers without ad hoc aliases. Note that
// a leaf register with ad hoc aliases doesn't get its own unit - it isn't
// necessary. This means the aliasing leaf registers can share a single unit.
if (RegUnits.empty())
- RegUnits.push_back(RegBank.newRegUnit(this));
+ RegUnits.set(RegBank.newRegUnit(this));
// We have now computed the native register units. More may be adopted later
// for balancing purposes.
- NumNativeRegUnits = RegUnits.size();
+ NativeRegUnits = RegUnits;
return SubRegs;
}
@@ -534,7 +519,7 @@ CodeGenRegister::addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet,
// Get the sum of this register's unit weights.
unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const {
unsigned Weight = 0;
- for (RegUnitList::const_iterator I = RegUnits.begin(), E = RegUnits.end();
+ for (RegUnitList::iterator I = RegUnits.begin(), E = RegUnits.end();
I != E; ++I) {
Weight += RegBank.getRegUnit(*I).Weight;
}
@@ -657,17 +642,21 @@ struct TupleExpander : SetTheory::Expander {
// CodeGenRegisterClass
//===----------------------------------------------------------------------===//
+static void sortAndUniqueRegisters(CodeGenRegister::Vec &M) {
+ std::sort(M.begin(), M.end(), deref<llvm::less>());
+ M.erase(std::unique(M.begin(), M.end(), deref<llvm::equal>()), M.end());
+}
+
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
: TheDef(R),
Name(R->getName()),
TopoSigs(RegBank.getNumTopoSigs()),
- EnumValue(-1) {
+ EnumValue(-1),
+ LaneMask(0) {
// Rename anonymous register classes.
if (R->getName().size() > 9 && R->getName()[9] == '.') {
static unsigned AnonCounter = 0;
- R->setName("AnonRegClass_" + utostr(AnonCounter));
- // MSVC2012 ICEs if AnonCounter++ is directly passed to utostr.
- ++AnonCounter;
+ R->setName("AnonRegClass_" + utostr(AnonCounter++));
}
std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes");
@@ -689,9 +678,10 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
Orders[0].push_back((*Elements)[i]);
const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]);
- Members.insert(Reg);
+ Members.push_back(Reg);
TopoSigs.set(Reg->getTopoSig());
}
+ sortAndUniqueRegisters(Members);
// Alternative allocation orders may be subsets.
SetTheory::RecSet Order;
@@ -733,9 +723,8 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
SpillAlignment(Props.SpillAlignment),
CopyCost(0),
Allocatable(true) {
- for (CodeGenRegister::Set::iterator I = Members.begin(), E = Members.end();
- I != E; ++I)
- TopoSigs.set((*I)->getTopoSig());
+ for (const auto R : Members)
+ TopoSigs.set(R->getTopoSig());
}
// Compute inherited propertied for a synthesized register class.
@@ -764,15 +753,15 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
}
bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
- return Members.count(Reg);
+ return std::binary_search(Members.begin(), Members.end(), Reg,
+ deref<llvm::less>());
}
namespace llvm {
raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
- for (CodeGenRegister::Set::const_iterator I = K.Members->begin(),
- E = K.Members->end(); I != E; ++I)
- OS << ", " << (*I)->getName();
+ for (const auto R : *K.Members)
+ OS << ", " << R->getName();
return OS << " }";
}
}
@@ -798,10 +787,10 @@ operator<(const CodeGenRegisterClass::Key &B) const {
static bool testSubClass(const CodeGenRegisterClass *A,
const CodeGenRegisterClass *B) {
return A->SpillAlignment && B->SpillAlignment % A->SpillAlignment == 0 &&
- A->SpillSize <= B->SpillSize &&
- std::includes(A->getMembers().begin(), A->getMembers().end(),
- B->getMembers().begin(), B->getMembers().end(),
- CodeGenRegister::Less());
+ A->SpillSize <= B->SpillSize &&
+ std::includes(A->getMembers().begin(), A->getMembers().end(),
+ B->getMembers().begin(), B->getMembers().end(),
+ deref<llvm::less>());
}
/// Sorting predicate for register classes. This provides a topological
@@ -810,34 +799,34 @@ static bool testSubClass(const CodeGenRegisterClass *A,
/// Register classes with the same registers, spill size, and alignment form a
/// clique. They will be ordered alphabetically.
///
-static int TopoOrderRC(CodeGenRegisterClass *const *PA,
- CodeGenRegisterClass *const *PB) {
- const CodeGenRegisterClass *A = *PA;
- const CodeGenRegisterClass *B = *PB;
+static bool TopoOrderRC(const CodeGenRegisterClass &PA,
+ const CodeGenRegisterClass &PB) {
+ auto *A = &PA;
+ auto *B = &PB;
if (A == B)
return 0;
// Order by ascending spill size.
if (A->SpillSize < B->SpillSize)
- return -1;
+ return true;
if (A->SpillSize > B->SpillSize)
- return 1;
+ return false;
// Order by ascending spill alignment.
if (A->SpillAlignment < B->SpillAlignment)
- return -1;
+ return true;
if (A->SpillAlignment > B->SpillAlignment)
- return 1;
+ return false;
// Order by descending set size. Note that the classes' allocation order may
// not have been computed yet. The Members set is always vaild.
if (A->getMembers().size() > B->getMembers().size())
- return -1;
+ return true;
if (A->getMembers().size() < B->getMembers().size())
- return 1;
+ return false;
// Finally order by name as a tie breaker.
- return StringRef(A->getName()).compare(B->getName());
+ return StringRef(A->getName()) < B->getName();
}
std::string CodeGenRegisterClass::getQualifiedName() const {
@@ -850,55 +839,56 @@ std::string CodeGenRegisterClass::getQualifiedName() const {
// Compute sub-classes of all register classes.
// Assume the classes are ordered topologically.
void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
- ArrayRef<CodeGenRegisterClass*> RegClasses = RegBank.getRegClasses();
+ auto &RegClasses = RegBank.getRegClasses();
// Visit backwards so sub-classes are seen first.
- for (unsigned rci = RegClasses.size(); rci; --rci) {
- CodeGenRegisterClass &RC = *RegClasses[rci - 1];
+ for (auto I = RegClasses.rbegin(), E = RegClasses.rend(); I != E; ++I) {
+ CodeGenRegisterClass &RC = *I;
RC.SubClasses.resize(RegClasses.size());
RC.SubClasses.set(RC.EnumValue);
// Normally, all subclasses have IDs >= rci, unless RC is part of a clique.
- for (unsigned s = rci; s != RegClasses.size(); ++s) {
- if (RC.SubClasses.test(s))
+ for (auto I2 = I.base(), E2 = RegClasses.end(); I2 != E2; ++I2) {
+ CodeGenRegisterClass &SubRC = *I2;
+ if (RC.SubClasses.test(SubRC.EnumValue))
continue;
- CodeGenRegisterClass *SubRC = RegClasses[s];
- if (!testSubClass(&RC, SubRC))
+ if (!testSubClass(&RC, &SubRC))
continue;
// SubRC is a sub-class. Grap all its sub-classes so we won't have to
// check them again.
- RC.SubClasses |= SubRC->SubClasses;
+ RC.SubClasses |= SubRC.SubClasses;
}
// Sweep up missed clique members. They will be immediately preceding RC.
- for (unsigned s = rci - 1; s && testSubClass(&RC, RegClasses[s - 1]); --s)
- RC.SubClasses.set(s - 1);
+ for (auto I2 = std::next(I); I2 != E && testSubClass(&RC, &*I2); ++I2)
+ RC.SubClasses.set(I2->EnumValue);
}
// Compute the SuperClasses lists from the SubClasses vectors.
- for (unsigned rci = 0; rci != RegClasses.size(); ++rci) {
- const BitVector &SC = RegClasses[rci]->getSubClasses();
- for (int s = SC.find_first(); s >= 0; s = SC.find_next(s)) {
- if (unsigned(s) == rci)
+ for (auto &RC : RegClasses) {
+ const BitVector &SC = RC.getSubClasses();
+ auto I = RegClasses.begin();
+ for (int s = 0, next_s = SC.find_first(); next_s != -1;
+ next_s = SC.find_next(s)) {
+ std::advance(I, next_s - s);
+ s = next_s;
+ if (&*I == &RC)
continue;
- RegClasses[s]->SuperClasses.push_back(RegClasses[rci]);
+ I->SuperClasses.push_back(&RC);
}
}
// With the class hierarchy in place, let synthesized register classes inherit
// properties from their closest super-class. The iteration order here can
// propagate properties down multiple levels.
- for (unsigned rci = 0; rci != RegClasses.size(); ++rci)
- if (!RegClasses[rci]->getDef())
- RegClasses[rci]->inheritProperties(RegBank);
+ for (auto &RC : RegClasses)
+ if (!RC.getDef())
+ RC.inheritProperties(RegBank);
}
-void
-CodeGenRegisterClass::getSuperRegClasses(CodeGenSubRegIndex *SubIdx,
- BitVector &Out) const {
- DenseMap<CodeGenSubRegIndex*,
- SmallPtrSet<CodeGenRegisterClass*, 8> >::const_iterator
- FindI = SuperRegClasses.find(SubIdx);
+void CodeGenRegisterClass::getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
+ BitVector &Out) const {
+ auto FindI = SuperRegClasses.find(SubIdx);
if (FindI == SuperRegClasses.end())
return;
for (CodeGenRegisterClass *RC : FindI->second)
@@ -933,13 +923,12 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) {
for (unsigned i = 0, e = SRIs.size(); i != e; ++i)
getSubRegIdx(SRIs[i]);
// Build composite maps from ComposedOf fields.
- for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i)
- SubRegIndices[i]->updateComponents(*this);
+ for (auto &Idx : SubRegIndices)
+ Idx.updateComponents(*this);
// Read in the register definitions.
std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register");
std::sort(Regs.begin(), Regs.end(), LessRecordRegister());
- Registers.reserve(Regs.size());
// Assign the enumeration values.
for (unsigned i = 0, e = Regs.size(); i != e; ++i)
getReg(Regs[i]);
@@ -948,45 +937,41 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) {
std::vector<Record*> Tups =
Records.getAllDerivedDefinitions("RegisterTuples");
- std::vector<Record*> TupRegsCopy;
- for (unsigned i = 0, e = Tups.size(); i != e; ++i) {
- const std::vector<Record*> *TupRegs = Sets.expand(Tups[i]);
- TupRegsCopy.reserve(TupRegs->size());
- TupRegsCopy.assign(TupRegs->begin(), TupRegs->end());
- std::sort(TupRegsCopy.begin(), TupRegsCopy.end(), LessRecordRegister());
- for (unsigned j = 0, je = TupRegsCopy.size(); j != je; ++j)
- getReg((TupRegsCopy)[j]);
- TupRegsCopy.clear();
+ for (Record *R : Tups) {
+ std::vector<Record *> TupRegs = *Sets.expand(R);
+ std::sort(TupRegs.begin(), TupRegs.end(), LessRecordRegister());
+ for (Record *RC : TupRegs)
+ getReg(RC);
}
// Now all the registers are known. Build the object graph of explicit
// register-register references.
- for (unsigned i = 0, e = Registers.size(); i != e; ++i)
- Registers[i]->buildObjectGraph(*this);
+ for (auto &Reg : Registers)
+ Reg.buildObjectGraph(*this);
// Compute register name map.
- for (unsigned i = 0, e = Registers.size(); i != e; ++i)
+ for (auto &Reg : Registers)
// 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]));
+ RegistersByName.insert(
+ std::make_pair(Reg.TheDef->getValueAsString("AsmName"), &Reg));
// Precompute all sub-register maps.
// This will create Composite entries for all inferred sub-register indices.
- for (unsigned i = 0, e = Registers.size(); i != e; ++i)
- Registers[i]->computeSubRegs(*this);
+ for (auto &Reg : Registers)
+ Reg.computeSubRegs(*this);
// Infer even more sub-registers by combining leading super-registers.
- for (unsigned i = 0, e = Registers.size(); i != e; ++i)
- if (Registers[i]->CoveredBySubRegs)
- Registers[i]->computeSecondarySubRegs(*this);
+ for (auto &Reg : Registers)
+ if (Reg.CoveredBySubRegs)
+ Reg.computeSecondarySubRegs(*this);
// After the sub-register graph is complete, compute the topologically
// ordered SuperRegs list.
- for (unsigned i = 0, e = Registers.size(); i != e; ++i)
- Registers[i]->computeSuperRegs(*this);
+ for (auto &Reg : Registers)
+ Reg.computeSuperRegs(*this);
// Native register units are associated with a leaf register. They've all been
// discovered now.
@@ -998,35 +983,35 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) {
PrintFatalError("No 'RegisterClass' subclasses defined!");
// Allocate user-defined register classes.
- RegClasses.reserve(RCs.size());
- for (unsigned i = 0, e = RCs.size(); i != e; ++i)
- addToMaps(new CodeGenRegisterClass(*this, RCs[i]));
+ for (auto *RC : RCs) {
+ RegClasses.push_back(CodeGenRegisterClass(*this, RC));
+ addToMaps(&RegClasses.back());
+ }
// Infer missing classes to create a full algebra.
computeInferredRegisterClasses();
// Order register classes topologically and assign enum values.
- array_pod_sort(RegClasses.begin(), RegClasses.end(), TopoOrderRC);
- for (unsigned i = 0, e = RegClasses.size(); i != e; ++i)
- RegClasses[i]->EnumValue = i;
+ RegClasses.sort(TopoOrderRC);
+ unsigned i = 0;
+ for (auto &RC : RegClasses)
+ RC.EnumValue = i++;
CodeGenRegisterClass::computeSubClasses(*this);
}
// Create a synthetic CodeGenSubRegIndex without a corresponding Record.
CodeGenSubRegIndex*
CodeGenRegBank::createSubRegIndex(StringRef Name, StringRef Namespace) {
- CodeGenSubRegIndex *Idx = new CodeGenSubRegIndex(Name, Namespace,
- SubRegIndices.size() + 1);
- SubRegIndices.push_back(Idx);
- return Idx;
+ SubRegIndices.emplace_back(Name, Namespace, SubRegIndices.size() + 1);
+ return &SubRegIndices.back();
}
CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) {
CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def];
if (Idx)
return Idx;
- Idx = new CodeGenSubRegIndex(Def, SubRegIndices.size() + 1);
- SubRegIndices.push_back(Idx);
+ SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1);
+ Idx = &SubRegIndices.back();
return Idx;
}
@@ -1034,14 +1019,12 @@ CodeGenRegister *CodeGenRegBank::getReg(Record *Def) {
CodeGenRegister *&Reg = Def2Reg[Def];
if (Reg)
return Reg;
- Reg = new CodeGenRegister(Def, Registers.size() + 1);
- Registers.push_back(Reg);
+ Registers.emplace_back(Def, Registers.size() + 1);
+ Reg = &Registers.back();
return Reg;
}
void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
- RegClasses.push_back(RC);
-
if (Record *Def = RC->getDef())
Def2RC.insert(std::make_pair(Def, RC));
@@ -1054,7 +1037,7 @@ void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
// Create a synthetic sub-class if it is missing.
CodeGenRegisterClass*
CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
- const CodeGenRegister::Set *Members,
+ const CodeGenRegister::Vec *Members,
StringRef Name) {
// Synthetic sub-class has the same size and alignment as RC.
CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment);
@@ -1063,9 +1046,9 @@ CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
return FoundI->second;
// Sub-class doesn't exist, create a new one.
- CodeGenRegisterClass *NewRC = new CodeGenRegisterClass(*this, Name, K);
- addToMaps(NewRC);
- return NewRC;
+ RegClasses.push_back(CodeGenRegisterClass(*this, Name, K));
+ addToMaps(&RegClasses.back());
+ return &RegClasses.back();
}
CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) {
@@ -1126,21 +1109,19 @@ void CodeGenRegBank::computeComposites() {
// and many registers will share TopoSigs on regular architectures.
BitVector TopoSigs(getNumTopoSigs());
- for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
- CodeGenRegister *Reg1 = Registers[i];
-
+ for (const auto &Reg1 : Registers) {
// Skip identical subreg structures already processed.
- if (TopoSigs.test(Reg1->getTopoSig()))
+ if (TopoSigs.test(Reg1.getTopoSig()))
continue;
- TopoSigs.set(Reg1->getTopoSig());
+ TopoSigs.set(Reg1.getTopoSig());
- const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs();
+ const CodeGenRegister::SubRegMap &SRM1 = Reg1.getSubRegs();
for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(),
e1 = SRM1.end(); i1 != e1; ++i1) {
CodeGenSubRegIndex *Idx1 = i1->first;
CodeGenRegister *Reg2 = i1->second;
// Ignore identity compositions.
- if (Reg1 == Reg2)
+ if (&Reg1 == Reg2)
continue;
const CodeGenRegister::SubRegMap &SRM2 = Reg2->getSubRegs();
// Try composing Idx1 with another SubRegIndex.
@@ -1152,7 +1133,7 @@ void CodeGenRegBank::computeComposites() {
if (Reg2 == Reg3)
continue;
// OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3.
- CodeGenSubRegIndex *Idx3 = Reg1->getSubRegIndex(Reg3);
+ CodeGenSubRegIndex *Idx3 = Reg1.getSubRegIndex(Reg3);
assert(Idx3 && "Sub-register doesn't have an index");
// Conflicting composition? Emit a warning but allow it.
@@ -1173,15 +1154,14 @@ void CodeGenRegBank::computeComposites() {
//
// Conservatively share a lane mask bit if two sub-register indices overlap in
// some registers, but not in others. That shouldn't happen a lot.
-void CodeGenRegBank::computeSubRegIndexLaneMasks() {
+void CodeGenRegBank::computeSubRegLaneMasks() {
// First assign individual bits to all the leaf indices.
unsigned Bit = 0;
// Determine mask of lanes that cover their registers.
CoveringLanes = ~0u;
- for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
- CodeGenSubRegIndex *Idx = SubRegIndices[i];
- if (Idx->getComposites().empty()) {
- Idx->LaneMask = 1u << Bit;
+ for (auto &Idx : SubRegIndices) {
+ if (Idx.getComposites().empty()) {
+ Idx.LaneMask = 1u << Bit;
// Share bit 31 in the unlikely case there are more than 32 leafs.
//
// Sharing bits is harmless; it allows graceful degradation in targets
@@ -1196,7 +1176,71 @@ void CodeGenRegBank::computeSubRegIndexLaneMasks() {
// is no longer covering its registers.
CoveringLanes &= ~(1u << Bit);
} else {
- Idx->LaneMask = 0;
+ Idx.LaneMask = 0;
+ }
+ }
+
+ // Compute transformation sequences for composeSubRegIndexLaneMask. The idea
+ // here is that for each possible target subregister we look at the leafs
+ // in the subregister graph that compose for this target and create
+ // transformation sequences for the lanemasks. Each step in the sequence
+ // consists of a bitmask and a bitrotate operation. As the rotation amounts
+ // are usually the same for many subregisters we can easily combine the steps
+ // by combining the masks.
+ for (const auto &Idx : SubRegIndices) {
+ const auto &Composites = Idx.getComposites();
+ auto &LaneTransforms = Idx.CompositionLaneMaskTransform;
+ // Go through all leaf subregisters and find the ones that compose with Idx.
+ // These make out all possible valid bits in the lane mask we want to
+ // transform. Looking only at the leafs ensure that only a single bit in
+ // the mask is set.
+ unsigned NextBit = 0;
+ for (auto &Idx2 : SubRegIndices) {
+ // Skip non-leaf subregisters.
+ if (!Idx2.getComposites().empty())
+ continue;
+ // Replicate the behaviour from the lane mask generation loop above.
+ unsigned SrcBit = NextBit;
+ unsigned SrcMask = 1u << SrcBit;
+ if (NextBit < 31)
+ ++NextBit;
+ assert(Idx2.LaneMask == SrcMask);
+
+ // Get the composed subregister if there is any.
+ auto C = Composites.find(&Idx2);
+ if (C == Composites.end())
+ continue;
+ const CodeGenSubRegIndex *Composite = C->second;
+ // The Composed subreg should be a leaf subreg too
+ assert(Composite->getComposites().empty());
+
+ // Create Mask+Rotate operation and merge with existing ops if possible.
+ unsigned DstBit = Log2_32(Composite->LaneMask);
+ int Shift = DstBit - SrcBit;
+ uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift : 32+Shift;
+ for (auto &I : LaneTransforms) {
+ if (I.RotateLeft == RotateLeft) {
+ I.Mask |= SrcMask;
+ SrcMask = 0;
+ }
+ }
+ if (SrcMask != 0) {
+ MaskRolPair MaskRol = { SrcMask, RotateLeft };
+ LaneTransforms.push_back(MaskRol);
+ }
+ }
+ // Optimize if the transformation consists of one step only: Set mask to
+ // 0xffffffff (including some irrelevant invalid bits) so that it should
+ // merge with more entries later while compressing the table.
+ if (LaneTransforms.size() == 1)
+ LaneTransforms[0].Mask = ~0u;
+
+ // Further compression optimization: For invalid compositions resulting
+ // in a sequence with 0 entries we can just pick any other. Choose
+ // Mask 0xffffffff with Rotation 0.
+ if (LaneTransforms.size() == 0) {
+ MaskRolPair P = { ~0u, 0 };
+ LaneTransforms.push_back(P);
}
}
@@ -1204,13 +1248,24 @@ void CodeGenRegBank::computeSubRegIndexLaneMasks() {
// by the sub-register graph? This doesn't occur in any known targets.
// Inherit lanes from composites.
- for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
- unsigned Mask = SubRegIndices[i]->computeLaneMask();
+ for (const auto &Idx : SubRegIndices) {
+ unsigned Mask = Idx.computeLaneMask();
// If some super-registers without CoveredBySubRegs use this index, we can
// no longer assume that the lanes are covering their registers.
- if (!SubRegIndices[i]->AllSuperRegsCovered)
+ if (!Idx.AllSuperRegsCovered)
CoveringLanes &= ~Mask;
}
+
+ // Compute lane mask combinations for register classes.
+ for (auto &RegClass : RegClasses) {
+ unsigned LaneMask = 0;
+ for (const auto &SubRegIndex : SubRegIndices) {
+ if (RegClass.getSubClassWithSubReg(&SubRegIndex) != &RegClass)
+ continue;
+ LaneMask |= SubRegIndex.LaneMask;
+ }
+ RegClass.LaneMask = LaneMask;
+ }
}
namespace {
@@ -1231,7 +1286,7 @@ namespace {
// for which the unit weight equals the set weight. These units should not have
// their weight increased.
struct UberRegSet {
- CodeGenRegister::Set Regs;
+ CodeGenRegister::Vec Regs;
unsigned Weight;
CodeGenRegister::RegUnitList SingularDeterminants;
@@ -1247,22 +1302,20 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
std::vector<UberRegSet*> &RegSets,
CodeGenRegBank &RegBank) {
- const std::vector<CodeGenRegister*> &Registers = RegBank.getRegisters();
+ const auto &Registers = RegBank.getRegisters();
// The Register EnumValue is one greater than its index into Registers.
- assert(Registers.size() == Registers[Registers.size()-1]->EnumValue &&
+ assert(Registers.size() == Registers.back().EnumValue &&
"register enum value mismatch");
// For simplicitly make the SetID the same as EnumValue.
IntEqClasses UberSetIDs(Registers.size()+1);
std::set<unsigned> AllocatableRegs;
- for (unsigned i = 0, e = RegBank.getRegClasses().size(); i != e; ++i) {
-
- CodeGenRegisterClass *RegClass = RegBank.getRegClasses()[i];
- if (!RegClass->Allocatable)
+ for (auto &RegClass : RegBank.getRegClasses()) {
+ if (!RegClass.Allocatable)
continue;
- const CodeGenRegister::Set &Regs = RegClass->getMembers();
+ const CodeGenRegister::Vec &Regs = RegClass.getMembers();
if (Regs.empty())
continue;
@@ -1270,15 +1323,14 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
assert(USetID && "register number 0 is invalid");
AllocatableRegs.insert((*Regs.begin())->EnumValue);
- for (CodeGenRegister::Set::const_iterator I = std::next(Regs.begin()),
- E = Regs.end(); I != E; ++I) {
+ for (auto I = std::next(Regs.begin()), E = Regs.end(); I != E; ++I) {
AllocatableRegs.insert((*I)->EnumValue);
UberSetIDs.join(USetID, (*I)->EnumValue);
}
}
// Combine non-allocatable regs.
- for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
- unsigned RegNum = Registers[i]->EnumValue;
+ for (const auto &Reg : Registers) {
+ unsigned RegNum = Reg.EnumValue;
if (AllocatableRegs.count(RegNum))
continue;
@@ -1292,17 +1344,18 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
// Insert Registers into the UberSets formed by union-find.
// Do not resize after this.
UberSets.resize(UberSetIDs.getNumClasses());
- for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
- const CodeGenRegister *Reg = Registers[i];
- unsigned USetID = UberSetIDs[Reg->EnumValue];
+ unsigned i = 0;
+ for (const CodeGenRegister &Reg : Registers) {
+ unsigned USetID = UberSetIDs[Reg.EnumValue];
if (!USetID)
USetID = ZeroID;
else if (USetID == ZeroID)
USetID = 0;
UberRegSet *USet = &UberSets[USetID];
- USet->Regs.insert(Reg);
- RegSets[i] = USet;
+ USet->Regs.push_back(&Reg);
+ sortAndUniqueRegisters(USet->Regs);
+ RegSets[i++] = USet;
}
}
@@ -1335,22 +1388,18 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets,
if (I->Weight != MaxWeight) {
DEBUG(
dbgs() << "UberSet " << I - UberSets.begin() << " Weight " << MaxWeight;
- for (CodeGenRegister::Set::iterator
- UnitI = I->Regs.begin(), UnitE = I->Regs.end();
- UnitI != UnitE; ++UnitI) {
- dbgs() << " " << (*UnitI)->getName();
- }
+ for (auto &Unit : I->Regs)
+ dbgs() << " " << Unit->getName();
dbgs() << "\n");
// Update the set weight.
I->Weight = MaxWeight;
}
// Find singular determinants.
- for (CodeGenRegister::Set::iterator RegI = I->Regs.begin(),
- RegE = I->Regs.end(); RegI != RegE; ++RegI) {
- if ((*RegI)->getRegUnits().size() == 1
- && (*RegI)->getWeight(RegBank) == I->Weight)
- mergeRegUnits(I->SingularDeterminants, (*RegI)->getRegUnits());
+ for (const auto R : I->Regs) {
+ if (R->getRegUnits().count() == 1 && R->getWeight(RegBank) == I->Weight) {
+ I->SingularDeterminants |= R->getRegUnits();
+ }
}
}
}
@@ -1368,13 +1417,14 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets,
static bool normalizeWeight(CodeGenRegister *Reg,
std::vector<UberRegSet> &UberSets,
std::vector<UberRegSet*> &RegSets,
- std::set<unsigned> &NormalRegs,
+ SparseBitVector<> &NormalRegs,
CodeGenRegister::RegUnitList &NormalUnits,
CodeGenRegBank &RegBank) {
- bool Changed = false;
- if (!NormalRegs.insert(Reg->EnumValue).second)
- return Changed;
+ if (NormalRegs.test(Reg->EnumValue))
+ return false;
+ NormalRegs.set(Reg->EnumValue);
+ bool Changed = false;
const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs();
for (CodeGenRegister::SubRegMap::const_iterator SRI = SRM.begin(),
SRE = SRM.end(); SRI != SRE; ++SRI) {
@@ -1398,8 +1448,8 @@ static bool normalizeWeight(CodeGenRegister *Reg,
// A register unit's weight can be adjusted only if it is the singular unit
// for this register, has not been used to normalize a subregister's set,
// and has not already been used to singularly determine this UberRegSet.
- unsigned AdjustUnit = Reg->getRegUnits().front();
- if (Reg->getRegUnits().size() != 1
+ unsigned AdjustUnit = *Reg->getRegUnits().begin();
+ if (Reg->getRegUnits().count() != 1
|| hasRegUnit(NormalUnits, AdjustUnit)
|| hasRegUnit(UberSet->SingularDeterminants, AdjustUnit)) {
// We don't have an adjustable unit, so adopt a new one.
@@ -1417,7 +1467,7 @@ static bool normalizeWeight(CodeGenRegister *Reg,
}
// Mark these units normalized so superregisters can't change their weights.
- mergeRegUnits(NormalUnits, Reg->getRegUnits());
+ NormalUnits |= Reg->getRegUnits();
return Changed;
}
@@ -1440,11 +1490,11 @@ void CodeGenRegBank::computeRegUnitWeights() {
for (bool Changed = true; Changed; ++NumIters) {
assert(NumIters <= NumNativeRegUnits && "Runaway register unit weights");
Changed = false;
- for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
+ for (auto &Reg : Registers) {
CodeGenRegister::RegUnitList NormalUnits;
- std::set<unsigned> NormalRegs;
- Changed |= normalizeWeight(Registers[i], UberSets, RegSets,
- NormalRegs, NormalUnits, *this);
+ SparseBitVector<> NormalRegs;
+ Changed |= normalizeWeight(&Reg, UberSets, RegSets, NormalRegs,
+ NormalUnits, *this);
}
}
}
@@ -1535,18 +1585,17 @@ void CodeGenRegBank::computeRegUnitSets() {
assert(RegUnitSets.empty() && "dirty RegUnitSets");
// Compute a unique RegUnitSet for each RegClass.
- ArrayRef<CodeGenRegisterClass*> RegClasses = getRegClasses();
- unsigned NumRegClasses = RegClasses.size();
- for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) {
- if (!RegClasses[RCIdx]->Allocatable)
+ auto &RegClasses = getRegClasses();
+ for (auto &RC : RegClasses) {
+ if (!RC.Allocatable)
continue;
// Speculatively grow the RegUnitSets to hold the new set.
RegUnitSets.resize(RegUnitSets.size() + 1);
- RegUnitSets.back().Name = RegClasses[RCIdx]->getName();
+ RegUnitSets.back().Name = RC.getName();
// Compute a sorted list of units in this class.
- RegClasses[RCIdx]->buildRegUnitSet(RegUnitSets.back().Units);
+ RC.buildRegUnitSet(RegUnitSets.back().Units);
// Find an existing RegUnitSet.
std::vector<RegUnitSet>::const_iterator SetI =
@@ -1560,9 +1609,8 @@ void CodeGenRegBank::computeRegUnitSets() {
USIdx < USEnd; ++USIdx) {
dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name
<< ":";
- ArrayRef<unsigned> Units = RegUnitSets[USIdx].Units;
- for (unsigned i = 0, e = Units.size(); i < e; ++i)
- dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName();
+ for (auto &U : RegUnitSets[USIdx].Units)
+ dbgs() << " " << RegUnits[U].Roots[0]->getName();
dbgs() << "\n";
});
@@ -1574,9 +1622,8 @@ void CodeGenRegBank::computeRegUnitSets() {
USIdx < USEnd; ++USIdx) {
dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name
<< ":";
- ArrayRef<unsigned> Units = RegUnitSets[USIdx].Units;
- for (unsigned i = 0, e = Units.size(); i < e; ++i)
- dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName();
+ for (auto &U : RegUnitSets[USIdx].Units)
+ dbgs() << " " << RegUnits[U].Roots[0]->getName();
dbgs() << "\n";
}
dbgs() << "\nUnion sets:\n");
@@ -1621,9 +1668,8 @@ void CodeGenRegBank::computeRegUnitSets() {
else {
DEBUG(dbgs() << "UnitSet " << RegUnitSets.size()-1
<< " " << RegUnitSets.back().Name << ":";
- ArrayRef<unsigned> Units = RegUnitSets.back().Units;
- for (unsigned i = 0, e = Units.size(); i < e; ++i)
- dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName();
+ for (auto &U : RegUnitSets.back().Units)
+ dbgs() << " " << RegUnits[U].Roots[0]->getName();
dbgs() << "\n";);
}
}
@@ -1637,29 +1683,30 @@ void CodeGenRegBank::computeRegUnitSets() {
USIdx < USEnd; ++USIdx) {
dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name
<< ":";
- ArrayRef<unsigned> Units = RegUnitSets[USIdx].Units;
- for (unsigned i = 0, e = Units.size(); i < e; ++i)
- dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName();
+ for (auto &U : RegUnitSets[USIdx].Units)
+ dbgs() << " " << RegUnits[U].Roots[0]->getName();
dbgs() << "\n";
});
// For each register class, list the UnitSets that are supersets.
- RegClassUnitSets.resize(NumRegClasses);
- for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) {
- if (!RegClasses[RCIdx]->Allocatable)
+ RegClassUnitSets.resize(RegClasses.size());
+ int RCIdx = -1;
+ for (auto &RC : RegClasses) {
+ ++RCIdx;
+ if (!RC.Allocatable)
continue;
// Recompute the sorted list of units in this class.
std::vector<unsigned> RCRegUnits;
- RegClasses[RCIdx]->buildRegUnitSet(RCRegUnits);
+ RC.buildRegUnitSet(RCRegUnits);
// Don't increase pressure for unallocatable regclasses.
if (RCRegUnits.empty())
continue;
- DEBUG(dbgs() << "RC " << RegClasses[RCIdx]->getName() << " Units: \n";
- for (unsigned i = 0, e = RCRegUnits.size(); i < e; ++i)
- dbgs() << RegUnits[RCRegUnits[i]].getRoots()[0]->getName() << " ";
+ DEBUG(dbgs() << "RC " << RC.getName() << " Units: \n";
+ for (auto &U : RCRegUnits)
+ dbgs() << RegUnits[U].getRoots()[0]->getName() << " ";
dbgs() << "\n UnitSetIDs:");
// Find all supersets.
@@ -1704,9 +1751,46 @@ void CodeGenRegBank::computeRegUnitSets() {
}
}
+void CodeGenRegBank::computeRegUnitLaneMasks() {
+ for (auto &Register : Registers) {
+ // Create an initial lane mask for all register units.
+ const auto &RegUnits = Register.getRegUnits();
+ CodeGenRegister::RegUnitLaneMaskList RegUnitLaneMasks(RegUnits.count(), 0);
+ // Iterate through SubRegisters.
+ typedef CodeGenRegister::SubRegMap SubRegMap;
+ const SubRegMap &SubRegs = Register.getSubRegs();
+ for (SubRegMap::const_iterator S = SubRegs.begin(),
+ SE = SubRegs.end(); S != SE; ++S) {
+ CodeGenRegister *SubReg = S->second;
+ // Ignore non-leaf subregisters, their lane masks are fully covered by
+ // the leaf subregisters anyway.
+ if (SubReg->getSubRegs().size() != 0)
+ continue;
+ CodeGenSubRegIndex *SubRegIndex = S->first;
+ const CodeGenRegister *SubRegister = S->second;
+ unsigned LaneMask = SubRegIndex->LaneMask;
+ // Distribute LaneMask to Register Units touched.
+ for (const auto &SUI : SubRegister->getRegUnits()) {
+ bool Found = false;
+ unsigned u = 0;
+ for (unsigned RU : RegUnits) {
+ if (SUI == RU) {
+ RegUnitLaneMasks[u] |= LaneMask;
+ assert(!Found);
+ Found = true;
+ }
+ ++u;
+ }
+ assert(Found);
+ }
+ }
+ Register.setRegUnitLaneMasks(RegUnitLaneMasks);
+ }
+}
+
void CodeGenRegBank::computeDerivedInfo() {
computeComposites();
- computeSubRegIndexLaneMasks();
+ computeSubRegLaneMasks();
// Compute a weight for each register unit created during getSubRegs.
// This may create adopted register units (with unit # >= NumNativeRegUnits).
@@ -1716,6 +1800,8 @@ void CodeGenRegBank::computeDerivedInfo() {
// supersets for the union of overlapping sets.
computeRegUnitSets();
+ computeRegUnitLaneMasks();
+
// Get the weight of each set.
for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx)
RegUnitSets[Idx].Weight = getRegUnitSetWeight(RegUnitSets[Idx].Units);
@@ -1742,20 +1828,23 @@ void CodeGenRegBank::computeDerivedInfo() {
// returns a maximal register class for all X.
//
void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
- for (unsigned rci = 0, rce = RegClasses.size(); rci != rce; ++rci) {
+ assert(!RegClasses.empty());
+ // Stash the iterator to the last element so that this loop doesn't visit
+ // elements added by the getOrCreateSubClass call within it.
+ for (auto I = RegClasses.begin(), E = std::prev(RegClasses.end());
+ I != std::next(E); ++I) {
CodeGenRegisterClass *RC1 = RC;
- CodeGenRegisterClass *RC2 = RegClasses[rci];
+ CodeGenRegisterClass *RC2 = &*I;
if (RC1 == RC2)
continue;
// Compute the set intersection of RC1 and RC2.
- const CodeGenRegister::Set &Memb1 = RC1->getMembers();
- const CodeGenRegister::Set &Memb2 = RC2->getMembers();
- CodeGenRegister::Set Intersection;
- std::set_intersection(Memb1.begin(), Memb1.end(),
- Memb2.begin(), Memb2.end(),
- std::inserter(Intersection, Intersection.begin()),
- CodeGenRegister::Less());
+ const CodeGenRegister::Vec &Memb1 = RC1->getMembers();
+ const CodeGenRegister::Vec &Memb2 = RC2->getMembers();
+ CodeGenRegister::Vec Intersection;
+ std::set_intersection(
+ Memb1.begin(), Memb1.end(), Memb2.begin(), Memb2.end(),
+ std::inserter(Intersection, Intersection.begin()), deref<llvm::less>());
// Skip disjoint class pairs.
if (Intersection.empty())
@@ -1781,37 +1870,38 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
//
void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
// Map SubRegIndex to set of registers in RC supporting that SubRegIndex.
- typedef std::map<CodeGenSubRegIndex*, CodeGenRegister::Set,
- CodeGenSubRegIndex::Less> SubReg2SetMap;
+ typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Vec,
+ deref<llvm::less>> SubReg2SetMap;
// Compute the set of registers supporting each SubRegIndex.
SubReg2SetMap SRSets;
- for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(),
- RE = RC->getMembers().end(); RI != RE; ++RI) {
- const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs();
+ for (const auto R : RC->getMembers()) {
+ const CodeGenRegister::SubRegMap &SRM = R->getSubRegs();
for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
E = SRM.end(); I != E; ++I)
- SRSets[I->first].insert(*RI);
+ SRSets[I->first].push_back(R);
}
+ for (auto I : SRSets)
+ sortAndUniqueRegisters(I.second);
+
// Find matching classes for all SRSets entries. Iterate in SubRegIndex
// numerical order to visit synthetic indices last.
- for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
- CodeGenSubRegIndex *SubIdx = SubRegIndices[sri];
- SubReg2SetMap::const_iterator I = SRSets.find(SubIdx);
+ for (const auto &SubIdx : SubRegIndices) {
+ SubReg2SetMap::const_iterator I = SRSets.find(&SubIdx);
// Unsupported SubRegIndex. Skip it.
if (I == SRSets.end())
continue;
// In most cases, all RC registers support the SubRegIndex.
if (I->second.size() == RC->getMembers().size()) {
- RC->setSubClassWithSubReg(SubIdx, RC);
+ RC->setSubClassWithSubReg(&SubIdx, RC);
continue;
}
// This is a real subset. See if we have a matching class.
CodeGenRegisterClass *SubRC =
getOrCreateSubClass(RC, &I->second,
RC->getName() + "_with_" + I->first->getName());
- RC->setSubClassWithSubReg(SubIdx, SubRC);
+ RC->setSubClassWithSubReg(&SubIdx, SubRC);
}
}
@@ -1823,27 +1913,24 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
//
void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
- unsigned FirstSubRegRC) {
+ std::list<CodeGenRegisterClass>::iterator FirstSubRegRC) {
SmallVector<std::pair<const CodeGenRegister*,
const CodeGenRegister*>, 16> SSPairs;
BitVector TopoSigs(getNumTopoSigs());
// Iterate in SubRegIndex numerical order to visit synthetic indices last.
- for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
- CodeGenSubRegIndex *SubIdx = SubRegIndices[sri];
+ for (auto &SubIdx : SubRegIndices) {
// Skip indexes that aren't fully supported by RC's registers. This was
// computed by inferSubClassWithSubReg() above which should have been
// called first.
- if (RC->getSubClassWithSubReg(SubIdx) != RC)
+ if (RC->getSubClassWithSubReg(&SubIdx) != RC)
continue;
// Build list of (Super, Sub) pairs for this SubIdx.
SSPairs.clear();
TopoSigs.reset();
- for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(),
- RE = RC->getMembers().end(); RI != RE; ++RI) {
- const CodeGenRegister *Super = *RI;
- const CodeGenRegister *Sub = Super->getSubRegs().find(SubIdx)->second;
+ for (const auto Super : RC->getMembers()) {
+ const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second;
assert(Sub && "Missing sub-register");
SSPairs.push_back(std::make_pair(Super, Sub));
TopoSigs.set(Sub->getTopoSig());
@@ -1851,29 +1938,36 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
// Iterate over sub-register class candidates. Ignore classes created by
// this loop. They will never be useful.
- for (unsigned rci = FirstSubRegRC, rce = RegClasses.size(); rci != rce;
- ++rci) {
- CodeGenRegisterClass *SubRC = RegClasses[rci];
+ // Store an iterator to the last element (not end) so that this loop doesn't
+ // visit newly inserted elements.
+ assert(!RegClasses.empty());
+ for (auto I = FirstSubRegRC, E = std::prev(RegClasses.end());
+ I != std::next(E); ++I) {
+ CodeGenRegisterClass &SubRC = *I;
// Topological shortcut: SubRC members have the wrong shape.
- if (!TopoSigs.anyCommon(SubRC->getTopoSigs()))
+ if (!TopoSigs.anyCommon(SubRC.getTopoSigs()))
continue;
// Compute the subset of RC that maps into SubRC.
- CodeGenRegister::Set SubSet;
+ CodeGenRegister::Vec SubSetVec;
for (unsigned i = 0, e = SSPairs.size(); i != e; ++i)
- if (SubRC->contains(SSPairs[i].second))
- SubSet.insert(SSPairs[i].first);
- if (SubSet.empty())
+ if (SubRC.contains(SSPairs[i].second))
+ SubSetVec.push_back(SSPairs[i].first);
+
+ if (SubSetVec.empty())
continue;
+
// RC injects completely into SubRC.
- if (SubSet.size() == SSPairs.size()) {
- SubRC->addSuperRegClass(SubIdx, RC);
+ sortAndUniqueRegisters(SubSetVec);
+ if (SubSetVec.size() == SSPairs.size()) {
+ SubRC.addSuperRegClass(&SubIdx, RC);
continue;
}
+
// Only a subset of RC maps into SubRC. Make sure it is represented by a
// class.
- getOrCreateSubClass(RC, &SubSet, RC->getName() +
- "_with_" + SubIdx->getName() +
- "_in_" + SubRC->getName());
+ getOrCreateSubClass(RC, &SubSetVec, RC->getName() + "_with_" +
+ SubIdx.getName() + "_in_" +
+ SubRC.getName());
}
}
}
@@ -1883,14 +1977,19 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
// Infer missing register classes.
//
void CodeGenRegBank::computeInferredRegisterClasses() {
+ assert(!RegClasses.empty());
// When this function is called, the register classes have not been sorted
// and assigned EnumValues yet. That means getSubClasses(),
// getSuperClasses(), and hasSubClass() functions are defunct.
- unsigned FirstNewRC = RegClasses.size();
+
+ // Use one-before-the-end so it doesn't move forward when new elements are
+ // added.
+ auto FirstNewRC = std::prev(RegClasses.end());
// Visit all register classes, including the ones being added by the loop.
- for (unsigned rci = 0; rci != RegClasses.size(); ++rci) {
- CodeGenRegisterClass *RC = RegClasses[rci];
+ // Watch out for iterator invalidation here.
+ for (auto I = RegClasses.begin(), E = RegClasses.end(); I != E; ++I) {
+ CodeGenRegisterClass *RC = &*I;
// Synthesize answers for getSubClassWithSubReg().
inferSubClassWithSubReg(RC);
@@ -1907,10 +2006,11 @@ void CodeGenRegBank::computeInferredRegisterClasses() {
// after inferMatchingSuperRegClass was called. At this point,
// inferMatchingSuperRegClass has checked SuperRC = [0..rci] with SubRC =
// [0..FirstNewRC). We need to cover SubRC = [FirstNewRC..rci].
- if (rci + 1 == FirstNewRC) {
- unsigned NextNewRC = RegClasses.size();
- for (unsigned rci2 = 0; rci2 != FirstNewRC; ++rci2)
- inferMatchingSuperRegClass(RegClasses[rci2], FirstNewRC);
+ if (I == FirstNewRC) {
+ auto NextNewRC = std::prev(RegClasses.end());
+ for (auto I2 = RegClasses.begin(), E2 = std::next(FirstNewRC); I2 != E2;
+ ++I2)
+ inferMatchingSuperRegClass(&*I2, E2);
FirstNewRC = NextNewRC;
}
}
@@ -1924,10 +2024,8 @@ void CodeGenRegBank::computeInferredRegisterClasses() {
const CodeGenRegisterClass*
CodeGenRegBank::getRegClassForRegister(Record *R) {
const CodeGenRegister *Reg = getReg(R);
- ArrayRef<CodeGenRegisterClass*> RCs = getRegClasses();
const CodeGenRegisterClass *FoundRC = nullptr;
- for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = *RCs[i];
+ for (const auto &RC : getRegClasses()) {
if (!RC.contains(Reg))
continue;
diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h
index c1e37fa..7c723d9 100644
--- a/utils/TableGen/CodeGenRegisters.h
+++ b/utils/TableGen/CodeGenRegisters.h
@@ -19,19 +19,36 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SparseBitVector.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/SetTheory.h"
#include <cstdlib>
+#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
+#include <deque>
namespace llvm {
class CodeGenRegBank;
+ /// Used to encode a step in a register lane mask transformation.
+ /// Mask the bits specified in Mask, then rotate them Rol bits to the left
+ /// assuming a wraparound at 32bits.
+ struct MaskRolPair {
+ unsigned Mask;
+ uint8_t RotateLeft;
+ bool operator==(const MaskRolPair Other) {
+ return Mask == Other.Mask && RotateLeft == Other.RotateLeft;
+ }
+ bool operator!=(const MaskRolPair Other) {
+ return Mask != Other.Mask || RotateLeft != Other.RotateLeft;
+ }
+ };
+
/// CodeGenSubRegIndex - Represents a sub-register index.
class CodeGenSubRegIndex {
Record *const TheDef;
@@ -42,7 +59,8 @@ namespace llvm {
uint16_t Size;
uint16_t Offset;
const unsigned EnumValue;
- unsigned LaneMask;
+ mutable unsigned LaneMask;
+ mutable SmallVector<MaskRolPair,1> CompositionLaneMaskTransform;
// Are all super-registers containing this SubRegIndex covered by their
// sub-registers?
@@ -55,17 +73,9 @@ namespace llvm {
const std::string &getNamespace() const { return Namespace; }
std::string getQualifiedName() const;
- // Order CodeGenSubRegIndex pointers by EnumValue.
- struct Less {
- bool operator()(const CodeGenSubRegIndex *A,
- const CodeGenSubRegIndex *B) const {
- assert(A && B);
- return A->EnumValue < B->EnumValue;
- }
- };
-
// Map of composite subreg indices.
- typedef std::map<CodeGenSubRegIndex*, CodeGenSubRegIndex*, Less> CompMap;
+ typedef std::map<CodeGenSubRegIndex *, CodeGenSubRegIndex *,
+ deref<llvm::less>> CompMap;
// Returns the subreg index that results from composing this with Idx.
// Returns NULL if this and Idx don't compose.
@@ -101,12 +111,17 @@ namespace llvm {
const CompMap &getComposites() const { return Composed; }
// Compute LaneMask from Composed. Return LaneMask.
- unsigned computeLaneMask();
+ unsigned computeLaneMask() const;
private:
CompMap Composed;
};
+ inline bool operator<(const CodeGenSubRegIndex &A,
+ const CodeGenSubRegIndex &B) {
+ return A.EnumValue < B.EnumValue;
+ }
+
/// CodeGenRegister - Represents a register definition.
struct CodeGenRegister {
Record *TheDef;
@@ -115,8 +130,8 @@ namespace llvm {
bool CoveredBySubRegs;
// Map SubRegIndex -> Register.
- typedef std::map<CodeGenSubRegIndex*, CodeGenRegister*,
- CodeGenSubRegIndex::Less> SubRegMap;
+ typedef std::map<CodeGenSubRegIndex *, CodeGenRegister *, deref<llvm::less>>
+ SubRegMap;
CodeGenRegister(Record *R, unsigned Enum);
@@ -180,18 +195,27 @@ namespace llvm {
}
// List of register units in ascending order.
- typedef SmallVector<unsigned, 16> RegUnitList;
+ typedef SparseBitVector<> RegUnitList;
+ typedef SmallVector<unsigned, 16> RegUnitLaneMaskList;
// How many entries in RegUnitList are native?
- unsigned NumNativeRegUnits;
+ RegUnitList NativeRegUnits;
// Get the list of register units.
// This is only valid after computeSubRegs() completes.
const RegUnitList &getRegUnits() const { return RegUnits; }
+ ArrayRef<unsigned> getRegUnitLaneMasks() const {
+ return makeArrayRef(RegUnitLaneMasks).slice(0, NativeRegUnits.count());
+ }
+
// Get the native register units. This is a prefix of getRegUnits().
- ArrayRef<unsigned> getNativeRegUnits() const {
- return makeArrayRef(RegUnits).slice(0, NumNativeRegUnits);
+ RegUnitList getNativeRegUnits() const {
+ return NativeRegUnits;
+ }
+
+ void setRegUnitLaneMasks(const RegUnitLaneMaskList &LaneMasks) {
+ RegUnitLaneMasks = LaneMasks;
}
// Inherit register units from subregisters.
@@ -199,23 +223,14 @@ namespace llvm {
bool inheritRegUnits(CodeGenRegBank &RegBank);
// Adopt a register unit for pressure tracking.
- // A unit is adopted iff its unit number is >= NumNativeRegUnits.
- void adoptRegUnit(unsigned RUID) { RegUnits.push_back(RUID); }
+ // A unit is adopted iff its unit number is >= NativeRegUnits.count().
+ void adoptRegUnit(unsigned RUID) { RegUnits.set(RUID); }
// Get the sum of this register's register unit weights.
unsigned getWeight(const CodeGenRegBank &RegBank) const;
- // Order CodeGenRegister pointers by EnumValue.
- struct Less {
- bool operator()(const CodeGenRegister *A,
- const CodeGenRegister *B) const {
- assert(A && B);
- return A->EnumValue < B->EnumValue;
- }
- };
-
// Canonically ordered set.
- typedef std::set<const CodeGenRegister*, Less> Set;
+ typedef std::vector<const CodeGenRegister*> Vec;
private:
bool SubRegsComplete;
@@ -236,11 +251,19 @@ namespace llvm {
SuperRegList SuperRegs;
DenseMap<const CodeGenRegister*, CodeGenSubRegIndex*> SubReg2Idx;
RegUnitList RegUnits;
+ RegUnitLaneMaskList RegUnitLaneMasks;
};
+ inline bool operator<(const CodeGenRegister &A, const CodeGenRegister &B) {
+ return A.EnumValue < B.EnumValue;
+ }
+
+ inline bool operator==(const CodeGenRegister &A, const CodeGenRegister &B) {
+ return A.EnumValue == B.EnumValue;
+ }
class CodeGenRegisterClass {
- CodeGenRegister::Set Members;
+ CodeGenRegister::Vec Members;
// Allocation orders. Order[0] always contains all registers in Members.
std::vector<SmallVector<Record*, 16> > Orders;
// Bit mask of sub-classes including this, indexed by their EnumValue.
@@ -257,15 +280,16 @@ namespace llvm {
// Map SubRegIndex -> sub-class. This is the largest sub-class where all
// registers have a SubRegIndex sub-register.
- DenseMap<CodeGenSubRegIndex*, CodeGenRegisterClass*> SubClassWithSubReg;
+ DenseMap<const CodeGenSubRegIndex *, CodeGenRegisterClass *>
+ SubClassWithSubReg;
// Map SubRegIndex -> set of super-reg classes. This is all register
// classes SuperRC such that:
//
// R:SubRegIndex in this RC for all R in SuperRC.
//
- DenseMap<CodeGenSubRegIndex*,
- SmallPtrSet<CodeGenRegisterClass*, 8> > SuperRegClasses;
+ DenseMap<const CodeGenSubRegIndex *, SmallPtrSet<CodeGenRegisterClass *, 8>>
+ SuperRegClasses;
// Bit vector of TopoSigs for the registers in this class. This will be
// very sparse on regular architectures.
@@ -280,6 +304,8 @@ namespace llvm {
int CopyCost;
bool Allocatable;
std::string AltOrderSelect;
+ /// Contains the combination of the lane masks of all subregisters.
+ unsigned LaneMask;
// Return the Record that defined this class, or NULL if the class was
// created by TableGen.
@@ -314,19 +340,20 @@ namespace llvm {
// getSubClassWithSubReg - Returns the largest sub-class where all
// registers have a SubIdx sub-register.
- CodeGenRegisterClass*
- getSubClassWithSubReg(CodeGenSubRegIndex *SubIdx) const {
+ CodeGenRegisterClass *
+ getSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx) const {
return SubClassWithSubReg.lookup(SubIdx);
}
- void setSubClassWithSubReg(CodeGenSubRegIndex *SubIdx,
+ void setSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx,
CodeGenRegisterClass *SubRC) {
SubClassWithSubReg[SubIdx] = SubRC;
}
// getSuperRegClasses - Returns a bit vector of all register classes
// containing only SubIdx super-registers of this class.
- void getSuperRegClasses(CodeGenSubRegIndex *SubIdx, BitVector &Out) const;
+ void getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
+ BitVector &Out) const;
// addSuperRegClass - Add a class containing only SudIdx super-registers.
void addSuperRegClass(CodeGenSubRegIndex *SubIdx,
@@ -357,7 +384,7 @@ namespace llvm {
// Get the set of registers. This set contains the same registers as
// getOrder(0).
- const CodeGenRegister::Set &getMembers() const { return Members; }
+ const CodeGenRegister::Vec &getMembers() const { return Members; }
// Get a bit vector of TopoSigs present in this register class.
const BitVector &getTopoSigs() const { return TopoSigs; }
@@ -371,11 +398,11 @@ namespace llvm {
// sub-classes. Note the ordering provided by this key is not the same as
// the topological order used for the EnumValues.
struct Key {
- const CodeGenRegister::Set *Members;
+ const CodeGenRegister::Vec *Members;
unsigned SpillSize;
unsigned SpillAlignment;
- Key(const CodeGenRegister::Set *M, unsigned S = 0, unsigned A = 0)
+ Key(const CodeGenRegister::Vec *M, unsigned S = 0, unsigned A = 0)
: Members(M), SpillSize(S), SpillAlignment(A) {}
Key(const CodeGenRegisterClass &RC)
@@ -446,8 +473,7 @@ namespace llvm {
class CodeGenRegBank {
SetTheory Sets;
- // SubRegIndices.
- std::vector<CodeGenSubRegIndex*> SubRegIndices;
+ std::deque<CodeGenSubRegIndex> SubRegIndices;
DenseMap<Record*, CodeGenSubRegIndex*> Def2SubRegIdx;
CodeGenSubRegIndex *createSubRegIndex(StringRef Name, StringRef NameSpace);
@@ -457,7 +483,7 @@ namespace llvm {
ConcatIdxMap ConcatIdx;
// Registers.
- std::vector<CodeGenRegister*> Registers;
+ std::deque<CodeGenRegister> Registers;
StringMap<CodeGenRegister*> RegistersByName;
DenseMap<Record*, CodeGenRegister*> Def2Reg;
unsigned NumNativeRegUnits;
@@ -468,7 +494,7 @@ namespace llvm {
SmallVector<RegUnit, 8> RegUnits;
// Register classes.
- std::vector<CodeGenRegisterClass*> RegClasses;
+ std::list<CodeGenRegisterClass> RegClasses;
DenseMap<Record*, CodeGenRegisterClass*> Def2RC;
typedef std::map<CodeGenRegisterClass::Key, CodeGenRegisterClass*> RCKeyMap;
RCKeyMap Key2RC;
@@ -494,15 +520,20 @@ namespace llvm {
// Create a synthetic sub-class if it is missing.
CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC,
- const CodeGenRegister::Set *Membs,
+ const CodeGenRegister::Vec *Membs,
StringRef Name);
// Infer missing register classes.
void computeInferredRegisterClasses();
void inferCommonSubClass(CodeGenRegisterClass *RC);
void inferSubClassWithSubReg(CodeGenRegisterClass *RC);
- void inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
- unsigned FirstSubRegRC = 0);
+ void inferMatchingSuperRegClass(CodeGenRegisterClass *RC) {
+ inferMatchingSuperRegClass(RC, RegClasses.begin());
+ }
+
+ void inferMatchingSuperRegClass(
+ CodeGenRegisterClass *RC,
+ std::list<CodeGenRegisterClass>::iterator FirstSubRegRC);
// Iteratively prune unit sets.
void pruneUnitSets();
@@ -517,7 +548,11 @@ namespace llvm {
void computeComposites();
// Compute a lane mask for each sub-register index.
- void computeSubRegIndexLaneMasks();
+ void computeSubRegLaneMasks();
+
+ /// Computes a lane mask for each register unit enumerated by a physical
+ /// register.
+ void computeRegUnitLaneMasks();
public:
CodeGenRegBank(RecordKeeper&);
@@ -527,7 +562,9 @@ namespace llvm {
// Sub-register indices. The first NumNamedIndices are defined by the user
// in the .td files. The rest are synthesized such that all sub-registers
// have a unique name.
- ArrayRef<CodeGenSubRegIndex*> getSubRegIndices() { return SubRegIndices; }
+ const std::deque<CodeGenSubRegIndex> &getSubRegIndices() const {
+ return SubRegIndices;
+ }
// Find a SubRegIndex form its Record def.
CodeGenSubRegIndex *getSubRegIdx(Record*);
@@ -547,7 +584,7 @@ namespace llvm {
ConcatIdx.insert(std::make_pair(Parts, Idx));
}
- const std::vector<CodeGenRegister*> &getRegisters() { return Registers; }
+ const std::deque<CodeGenRegister> &getRegisters() { return Registers; }
const StringMap<CodeGenRegister*> &getRegistersByName() {
return RegistersByName;
}
@@ -604,7 +641,9 @@ namespace llvm {
RegUnit &getRegUnit(unsigned RUID) { return RegUnits[RUID]; }
const RegUnit &getRegUnit(unsigned RUID) const { return RegUnits[RUID]; }
- ArrayRef<CodeGenRegisterClass*> getRegClasses() const {
+ std::list<CodeGenRegisterClass> &getRegClasses() { return RegClasses; }
+
+ const std::list<CodeGenRegisterClass> &getRegClasses() const {
return RegClasses;
}
diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp
index 4cf7b5f..bfdf8dc 100644
--- a/utils/TableGen/CodeGenSchedule.cpp
+++ b/utils/TableGen/CodeGenSchedule.cpp
@@ -74,11 +74,10 @@ struct InstRegexOp : public SetTheory::Operator {
}
RegexList.push_back(Regex(pat));
}
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I) {
+ for (const CodeGenInstruction *Inst : Target.instructions()) {
for (auto &R : RegexList) {
- if (R.match((*I)->TheDef->getName()))
- Elts.insert((*I)->TheDef);
+ if (R.match(Inst->TheDef->getName()))
+ Elts.insert(Inst->TheDef);
}
}
}
@@ -214,9 +213,8 @@ void CodeGenSchedModels::collectSchedRW() {
// Find all SchedReadWrites referenced by instruction defs.
RecVec SWDefs, SRDefs;
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I) {
- Record *SchedDef = (*I)->TheDef;
+ for (const CodeGenInstruction *Inst : Target.instructions()) {
+ Record *SchedDef = Inst->TheDef;
if (SchedDef->isValueUnset("SchedRW"))
continue;
RecVec RWs = SchedDef->getValueAsListOfDefs("SchedRW");
@@ -509,18 +507,17 @@ void CodeGenSchedModels::collectSchedClasses() {
// Create a SchedClass for each unique combination of itinerary class and
// SchedRW list.
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I) {
- Record *ItinDef = (*I)->TheDef->getValueAsDef("Itinerary");
+ for (const CodeGenInstruction *Inst : Target.instructions()) {
+ Record *ItinDef = Inst->TheDef->getValueAsDef("Itinerary");
IdxVec Writes, Reads;
- if (!(*I)->TheDef->isValueUnset("SchedRW"))
- findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads);
+ if (!Inst->TheDef->isValueUnset("SchedRW"))
+ findRWs(Inst->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads);
// ProcIdx == 0 indicates the class applies to all processors.
IdxVec ProcIndices(1, 0);
unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, ProcIndices);
- InstrClassMap[(*I)->TheDef] = SCIdx;
+ InstrClassMap[Inst->TheDef] = SCIdx;
}
// Create classes for InstRW defs.
RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
@@ -535,18 +532,16 @@ void CodeGenSchedModels::collectSchedClasses() {
if (!EnableDump)
return;
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I) {
-
- std::string InstName = (*I)->TheDef->getName();
- unsigned SCIdx = InstrClassMap.lookup((*I)->TheDef);
+ for (const CodeGenInstruction *Inst : Target.instructions()) {
+ std::string InstName = Inst->TheDef->getName();
+ unsigned SCIdx = InstrClassMap.lookup(Inst->TheDef);
if (!SCIdx) {
- dbgs() << "No machine model for " << (*I)->TheDef->getName() << '\n';
+ dbgs() << "No machine model for " << Inst->TheDef->getName() << '\n';
continue;
}
CodeGenSchedClass &SC = getSchedClass(SCIdx);
if (SC.ProcIndices[0] != 0)
- PrintFatalError((*I)->TheDef->getLoc(), "Instruction's sched class "
+ PrintFatalError(Inst->TheDef->getLoc(), "Instruction's sched class "
"must not be subtarget specific.");
IdxVec ProcIndices;
@@ -584,7 +579,7 @@ void CodeGenSchedModels::collectSchedClasses() {
for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(),
PE = ProcModels.end(); PI != PE; ++PI) {
if (!std::count(ProcIndices.begin(), ProcIndices.end(), PI->Index))
- dbgs() << "No machine model for " << (*I)->TheDef->getName()
+ dbgs() << "No machine model for " << Inst->TheDef->getName()
<< " on processor " << PI->ModelName << '\n';
}
}
@@ -781,9 +776,7 @@ bool CodeGenSchedModels::hasItineraries() const {
// Gather the processor itineraries.
void CodeGenSchedModels::collectProcItins() {
- for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(),
- PE = ProcModels.end(); PI != PE; ++PI) {
- CodeGenProcModel &ProcModel = *PI;
+ for (CodeGenProcModel &ProcModel : ProcModels) {
if (!ProcModel.hasItineraries())
continue;
@@ -1502,8 +1495,7 @@ void CodeGenSchedModels::collectProcResources() {
PM.ProcResourceDefs.push_back(*RI);
}
// Finalize each ProcModel by sorting the record arrays.
- for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) {
- CodeGenProcModel &PM = ProcModels[PIdx];
+ for (CodeGenProcModel &PM : ProcModels) {
std::sort(PM.WriteResDefs.begin(), PM.WriteResDefs.end(),
LessRecord());
std::sort(PM.ReadAdvanceDefs.begin(), PM.ReadAdvanceDefs.end(),
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index 597da68..47c8e0b 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -57,6 +57,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::i32: return "MVT::i32";
case MVT::i64: return "MVT::i64";
case MVT::i128: return "MVT::i128";
+ case MVT::Any: return "MVT::Any";
case MVT::iAny: return "MVT::iAny";
case MVT::fAny: return "MVT::fAny";
case MVT::vAny: return "MVT::vAny";
@@ -133,7 +134,7 @@ std::string llvm::getQualifiedName(const Record *R) {
/// getTarget - Return the current instance of the Target class.
///
CodeGenTarget::CodeGenTarget(RecordKeeper &records)
- : Records(records), RegBank(nullptr), SchedModels(nullptr) {
+ : Records(records) {
std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
if (Targets.size() == 0)
PrintFatalError("ERROR: No 'Target' subclasses defined!");
@@ -143,9 +144,6 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records)
}
CodeGenTarget::~CodeGenTarget() {
- DeleteContainerSeconds(Instructions);
- delete RegBank;
- delete SchedModels;
}
const std::string &CodeGenTarget::getName() const {
@@ -153,11 +151,11 @@ const std::string &CodeGenTarget::getName() const {
}
std::string CodeGenTarget::getInstNamespace() const {
- for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) {
+ for (const CodeGenInstruction *Inst : instructions()) {
// Make sure not to pick up "TargetOpcode" by accidentally getting
// the namespace off the PHI instruction or something.
- if ((*i)->Namespace != "TargetOpcode")
- return (*i)->Namespace;
+ if (Inst->Namespace != "TargetOpcode")
+ return Inst->Namespace;
}
return "";
@@ -211,7 +209,7 @@ Record *CodeGenTarget::getAsmWriter() const {
CodeGenRegBank &CodeGenTarget::getRegBank() const {
if (!RegBank)
- RegBank = new CodeGenRegBank(Records);
+ RegBank = llvm::make_unique<CodeGenRegBank>(Records);
return *RegBank;
}
@@ -234,9 +232,7 @@ std::vector<MVT::SimpleValueType> CodeGenTarget::
getRegisterVTs(Record *R) const {
const CodeGenRegister *Reg = getRegBank().getReg(R);
std::vector<MVT::SimpleValueType> Result;
- ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses();
- for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = *RCs[i];
+ for (const auto &RC : getRegBank().getRegClasses()) {
if (RC.contains(Reg)) {
ArrayRef<MVT::SimpleValueType> InVTs = RC.getValueTypes();
Result.insert(Result.end(), InVTs.begin(), InVTs.end());
@@ -251,10 +247,8 @@ getRegisterVTs(Record *R) const {
void CodeGenTarget::ReadLegalValueTypes() const {
- ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses();
- for (unsigned i = 0, e = RCs.size(); i != e; ++i)
- for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri)
- LegalValueTypes.push_back(RCs[i]->VTs[ri]);
+ for (const auto &RC : getRegBank().getRegClasses())
+ LegalValueTypes.insert(LegalValueTypes.end(), RC.VTs.begin(), RC.VTs.end());
// Remove duplicates.
std::sort(LegalValueTypes.begin(), LegalValueTypes.end());
@@ -265,7 +259,7 @@ void CodeGenTarget::ReadLegalValueTypes() const {
CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
if (!SchedModels)
- SchedModels = new CodeGenSchedModels(Records, *this);
+ SchedModels = llvm::make_unique<CodeGenSchedModels>(Records, *this);
return *SchedModels;
}
@@ -276,20 +270,20 @@ void CodeGenTarget::ReadInstructions() const {
// Parse the instructions defined in the .td file.
for (unsigned i = 0, e = Insts.size(); i != e; ++i)
- Instructions[Insts[i]] = new CodeGenInstruction(Insts[i]);
+ Instructions[Insts[i]] = llvm::make_unique<CodeGenInstruction>(Insts[i]);
}
static const CodeGenInstruction *
GetInstByName(const char *Name,
- const DenseMap<const Record*, CodeGenInstruction*> &Insts,
+ const DenseMap<const Record*,
+ std::unique_ptr<CodeGenInstruction>> &Insts,
RecordKeeper &Records) {
const Record *Rec = Records.getDef(Name);
- DenseMap<const Record*, CodeGenInstruction*>::const_iterator
- I = Insts.find(Rec);
+ const auto I = Insts.find(Rec);
if (!Rec || I == Insts.end())
PrintFatalError(Twine("Could not find '") + Name + "' instruction!");
- return I->second;
+ return I->second.get();
}
/// \brief Return all of the instructions defined by the target, ordered by
@@ -302,8 +296,9 @@ void CodeGenTarget::ComputeInstrsByEnum() const {
"IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE",
"REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START",
"LIFETIME_END", "STACKMAP", "PATCHPOINT", "LOAD_STACK_GUARD",
+ "STATEPOINT", "FRAME_ALLOC",
nullptr};
- const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions();
+ const auto &Insts = getInstructions();
for (const char *const *p = FixedInstrs; *p; ++p) {
const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
assert(Instr && "Missing target independent instruction");
@@ -312,9 +307,8 @@ void CodeGenTarget::ComputeInstrsByEnum() const {
}
unsigned EndOfPredefines = InstrsByEnum.size();
- for (DenseMap<const Record*, CodeGenInstruction*>::const_iterator
- I = Insts.begin(), E = Insts.end(); I != E; ++I) {
- const CodeGenInstruction *CGI = I->second;
+ for (const auto &I : Insts) {
+ const CodeGenInstruction *CGI = I.second.get();
if (CGI->Namespace != "TargetOpcode")
InstrsByEnum.push_back(CGI);
}
@@ -344,9 +338,7 @@ void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
return;
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
- for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
- I != E; ++I) {
- Record *R = *I;
+ for (Record *R : Insts) {
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
R->getValueAsBit("isPseudo"))
continue;
@@ -539,7 +531,9 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// variants with iAny types; otherwise, if the intrinsic is not
// overloaded, all the types can be specified directly.
assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
- !TyEl->isSubClassOf("LLVMTruncatedType")) ||
+ !TyEl->isSubClassOf("LLVMTruncatedType") &&
+ !TyEl->isSubClassOf("LLVMVectorSameWidth") &&
+ !TyEl->isSubClassOf("LLVMPointerToElt")) ||
VT == MVT::iAny || VT == MVT::vAny) &&
"Expected iAny or vAny type");
} else
diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h
index f4e1b6a..24b3851 100644
--- a/utils/TableGen/CodeGenTarget.h
+++ b/utils/TableGen/CodeGenTarget.h
@@ -65,15 +65,16 @@ class CodeGenTarget {
RecordKeeper &Records;
Record *TargetRec;
- mutable DenseMap<const Record*, CodeGenInstruction*> Instructions;
- mutable CodeGenRegBank *RegBank;
+ mutable DenseMap<const Record*,
+ std::unique_ptr<CodeGenInstruction>> Instructions;
+ mutable std::unique_ptr<CodeGenRegBank> RegBank;
mutable std::vector<Record*> RegAltNameIndices;
mutable SmallVector<MVT::SimpleValueType, 8> LegalValueTypes;
void ReadRegAltNameIndices() const;
void ReadInstructions() const;
void ReadLegalValueTypes() const;
- mutable CodeGenSchedModels *SchedModels;
+ mutable std::unique_ptr<CodeGenSchedModels> SchedModels;
mutable std::vector<const CodeGenInstruction*> InstrsByEnum;
public:
@@ -146,7 +147,8 @@ public:
CodeGenSchedModels &getSchedModels() const;
private:
- DenseMap<const Record*, CodeGenInstruction*> &getInstructions() const {
+ DenseMap<const Record*, std::unique_ptr<CodeGenInstruction>> &
+ getInstructions() const {
if (Instructions.empty()) ReadInstructions();
return Instructions;
}
@@ -154,8 +156,7 @@ public:
CodeGenInstruction &getInstruction(const Record *InstRec) const {
if (Instructions.empty()) ReadInstructions();
- DenseMap<const Record*, CodeGenInstruction*>::iterator I =
- Instructions.find(InstRec);
+ auto I = Instructions.find(InstRec);
assert(I != Instructions.end() && "Not an instruction");
return *I->second;
}
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index e2e6ab1..0fe3bbd 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -157,12 +157,12 @@ void DAGISelEmitter::run(raw_ostream &OS) {
}
}
- Matcher *TheMatcher = new ScopeMatcher(PatternMatchers);
+ std::unique_ptr<Matcher> TheMatcher =
+ llvm::make_unique<ScopeMatcher>(PatternMatchers);
- TheMatcher = OptimizeMatcher(TheMatcher, CGP);
+ OptimizeMatcher(TheMatcher, CGP);
//Matcher->dump();
- EmitMatcherTable(TheMatcher, CGP, OS);
- delete TheMatcher;
+ EmitMatcherTable(TheMatcher.get(), CGP, OS);
}
namespace llvm {
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
index b9cb267..9df3b41 100644
--- a/utils/TableGen/DAGISelMatcher.h
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -30,7 +30,8 @@ namespace llvm {
Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant,
const CodeGenDAGPatterns &CGP);
-Matcher *OptimizeMatcher(Matcher *Matcher, const CodeGenDAGPatterns &CGP);
+void OptimizeMatcher(std::unique_ptr<Matcher> &Matcher,
+ const CodeGenDAGPatterns &CGP);
void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP,
raw_ostream &OS);
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index 4a73b00..eb80619 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -27,10 +27,8 @@ static MVT::SimpleValueType getRegisterValueType(Record *R,
bool FoundRC = false;
MVT::SimpleValueType VT = MVT::Other;
const CodeGenRegister *Reg = T.getRegBank().getReg(R);
- ArrayRef<CodeGenRegisterClass*> RCs = T.getRegBank().getRegClasses();
- for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = *RCs[rc];
+ for (const auto &RC : T.getRegBank().getRegClasses()) {
if (!RC.contains(Reg))
continue;
diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp
index 7a22764..c9ee371 100644
--- a/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -511,11 +511,10 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) {
Scope->resetChild(i, NewOptionsToMatch[i]);
}
-Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher,
- const CodeGenDAGPatterns &CGP) {
- std::unique_ptr<Matcher> MatcherPtr(TheMatcher);
+void
+llvm::OptimizeMatcher(std::unique_ptr<Matcher> &MatcherPtr,
+ const CodeGenDAGPatterns &CGP) {
ContractNodes(MatcherPtr, CGP);
SinkPatternPredicates(MatcherPtr);
FactorNodes(MatcherPtr);
- return MatcherPtr.release();
}
diff --git a/utils/TableGen/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp
index ea14cb9..5060b6e 100644
--- a/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -472,7 +472,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
current->canAddInsnClass(InsnClass)) {
const State *NewState;
current->AddInsnClass(InsnClass, NewStateResources);
- assert(NewStateResources.size() && "New states must be generated");
+ assert(!NewStateResources.empty() && "New states must be generated");
//
// If we have seen this state before, then do not create a new state.
diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
index bd83b6c..292a2b1 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -333,8 +333,8 @@ protected:
// Parent emitter
const FixedLenDecoderEmitter *Emitter;
- FilterChooser(const FilterChooser &) LLVM_DELETED_FUNCTION;
- void operator=(const FilterChooser &) LLVM_DELETED_FUNCTION;
+ FilterChooser(const FilterChooser &) = delete;
+ void operator=(const FilterChooser &) = delete;
public:
FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
@@ -537,12 +537,10 @@ Filter::~Filter() {
// instructions. In order to unambiguously decode the singleton, we need to
// match the remaining undecoded encoding bits against the singleton.
void Filter::recurse() {
- std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator;
-
// Starts by inheriting our parent filter chooser's filter bit values.
std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues);
- if (VariableInstructions.size()) {
+ if (!VariableInstructions.empty()) {
// Conservatively marks each segment position as BIT_UNSET.
for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex)
BitValueArray[StartBit + bitIndex] = BIT_UNSET;
@@ -564,13 +562,11 @@ void Filter::recurse() {
}
// Otherwise, create sub choosers.
- for (mapIterator = FilteredInstructions.begin();
- mapIterator != FilteredInstructions.end();
- mapIterator++) {
+ for (const auto &Inst : FilteredInstructions) {
// Marks all the segment positions with either BIT_TRUE or BIT_FALSE.
for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) {
- if (mapIterator->first & (1ULL << bitIndex))
+ if (Inst.first & (1ULL << bitIndex))
BitValueArray[StartBit + bitIndex] = BIT_TRUE;
else
BitValueArray[StartBit + bitIndex] = BIT_FALSE;
@@ -579,8 +575,8 @@ void Filter::recurse() {
// Delegates to an inferior filter chooser for further processing on this
// category of instructions.
FilterChooserMap.insert(std::make_pair(
- mapIterator->first, llvm::make_unique<FilterChooser>(
- Owner->AllInstructions, mapIterator->second,
+ Inst.first, llvm::make_unique<FilterChooser>(
+ Owner->AllInstructions, Inst.second,
Owner->Operands, BitValueArray, *Owner)));
}
}
@@ -616,19 +612,14 @@ 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,
- std::unique_ptr<const FilterChooser>>::const_iterator filterIterator;
-
DecoderTable &Table = TableInfo.Table;
size_t PrevFilter = 0;
bool HasFallthrough = false;
- for (filterIterator = FilterChooserMap.begin();
- filterIterator != FilterChooserMap.end();
- filterIterator++) {
+ for (auto &Filter : FilterChooserMap) {
// Field value -1 implies a non-empty set of variable instructions.
// See also recurse().
- if (filterIterator->first == (unsigned)-1) {
+ if (Filter.first == (unsigned)-1) {
HasFallthrough = true;
// Each scope should always have at least one filter value to check
@@ -643,7 +634,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
Table.push_back(MCD::OPC_FilterValue);
// Encode and emit the value to filter against.
uint8_t Buffer[8];
- unsigned Len = encodeULEB128(filterIterator->first, Buffer);
+ unsigned Len = encodeULEB128(Filter.first, Buffer);
Table.insert(Table.end(), Buffer, Buffer + Len);
// Reserve space for the NumToSkip entry. We'll backpatch the value
// later.
@@ -656,7 +647,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
// Now delegate to the sub filter chooser for further decodings.
// The case may fallthrough, which happens if the remaining well-known
// encoding bits do not match exactly.
- filterIterator->second->emitTableEntries(TableInfo);
+ Filter.second->emitTableEntries(TableInfo);
// Now that we've emitted the body of the handler, update the NumToSkip
// of the filter itself to be able to skip forward when false. Subtract
@@ -685,7 +676,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
// Returns the number of fanout produced by the filter. More fanout implies
// the filter distinguishes more categories of instructions.
unsigned Filter::usefulness() const {
- if (VariableInstructions.size())
+ if (!VariableInstructions.empty())
return FilteredInstructions.size();
else
return FilteredInstructions.size() + 1;
@@ -863,10 +854,9 @@ emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
OS.indent(Indentation) << "switch (Idx) {\n";
OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
unsigned Index = 0;
- for (PredicateSet::const_iterator I = Predicates.begin(), E = Predicates.end();
- I != E; ++I, ++Index) {
- OS.indent(Indentation) << "case " << Index << ":\n";
- OS.indent(Indentation+2) << "return (" << *I << ");\n";
+ for (const auto &Predicate : Predicates) {
+ OS.indent(Indentation) << "case " << Index++ << ":\n";
+ OS.indent(Indentation+2) << "return (" << Predicate << ");\n";
}
OS.indent(Indentation) << "}\n";
} else {
@@ -892,10 +882,9 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
OS.indent(Indentation) << "switch (Idx) {\n";
OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
unsigned Index = 0;
- for (DecoderSet::const_iterator I = Decoders.begin(), E = Decoders.end();
- I != E; ++I, ++Index) {
- OS.indent(Indentation) << "case " << Index << ":\n";
- OS << *I;
+ for (const auto &Decoder : Decoders) {
+ OS.indent(Indentation) << "case " << Index++ << ":\n";
+ OS << Decoder;
OS.indent(Indentation+2) << "return S;\n";
}
OS.indent(Indentation) << "}\n";
@@ -1071,20 +1060,16 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation,
unsigned Opc) const {
- std::map<unsigned, std::vector<OperandInfo> >::const_iterator OpIter =
- Operands.find(Opc);
- const std::vector<OperandInfo>& InsnOperands = OpIter->second;
- for (std::vector<OperandInfo>::const_iterator
- I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
+ for (const auto &Op : Operands.find(Opc)->second) {
// If a custom instruction decoder was specified, use that.
- if (I->numFields() == 0 && I->Decoder.size()) {
- OS.indent(Indentation) << Emitter->GuardPrefix << I->Decoder
+ if (Op.numFields() == 0 && Op.Decoder.size()) {
+ OS.indent(Indentation) << Emitter->GuardPrefix << Op.Decoder
<< "(MI, insn, Address, Decoder)"
<< Emitter->GuardPostfix << "\n";
break;
}
- emitBinaryParser(OS, Indentation, *I);
+ emitBinaryParser(OS, Indentation, Op);
}
}
@@ -1795,7 +1780,7 @@ static bool populateInstruction(CodeGenTarget &Target,
unsigned NumberOps = CGI.Operands.size();
while (NumberedOp < NumberOps &&
(CGI.Operands.isFlatOperandNotEmitted(NumberedOp) ||
- (NamedOpIndices.size() && NamedOpIndices.count(
+ (!NamedOpIndices.empty() && NamedOpIndices.count(
CGI.Operands.getSubOperandNumber(NumberedOp).first))))
++NumberedOp;
@@ -1864,20 +1849,20 @@ static bool populateInstruction(CodeGenTarget &Target,
}
// For each operand, see if we can figure out where it is encoded.
- for (std::vector<std::pair<Init*, std::string> >::const_iterator
- NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) {
- if (!NumberedInsnOperands[NI->second].empty()) {
+ for (const auto &Op : InOutOperands) {
+ if (!NumberedInsnOperands[Op.second].empty()) {
InsnOperands.insert(InsnOperands.end(),
- NumberedInsnOperands[NI->second].begin(),
- NumberedInsnOperands[NI->second].end());
+ NumberedInsnOperands[Op.second].begin(),
+ NumberedInsnOperands[Op.second].end());
continue;
- } else if (!NumberedInsnOperands[TiedNames[NI->second]].empty()) {
- if (!NumberedInsnOperandsNoTie.count(TiedNames[NI->second])) {
+ }
+ if (!NumberedInsnOperands[TiedNames[Op.second]].empty()) {
+ if (!NumberedInsnOperandsNoTie.count(TiedNames[Op.second])) {
// Figure out to which (sub)operand we're tied.
- unsigned i = CGI.Operands.getOperandNamed(TiedNames[NI->second]);
+ unsigned i = CGI.Operands.getOperandNamed(TiedNames[Op.second]);
int tiedTo = CGI.Operands[i].getTiedRegister();
if (tiedTo == -1) {
- i = CGI.Operands.getOperandNamed(NI->second);
+ i = CGI.Operands.getOperandNamed(Op.second);
tiedTo = CGI.Operands[i].getTiedRegister();
}
@@ -1885,7 +1870,7 @@ static bool populateInstruction(CodeGenTarget &Target,
std::pair<unsigned, unsigned> SO =
CGI.Operands.getSubOperandNumber(tiedTo);
- InsnOperands.push_back(NumberedInsnOperands[TiedNames[NI->second]]
+ InsnOperands.push_back(NumberedInsnOperands[TiedNames[Op.second]]
[SO.second]);
}
}
@@ -1899,7 +1884,7 @@ static bool populateInstruction(CodeGenTarget &Target,
// for decoding register classes.
// FIXME: This need to be extended to handle instructions with custom
// decoder methods, and operands with (simple) MIOperandInfo's.
- TypedInit *TI = cast<TypedInit>(NI->first);
+ TypedInit *TI = cast<TypedInit>(Op.first);
RecordRecTy *Type = cast<RecordRecTy>(TI->getType());
Record *TypeRecord = Type->getRecord();
bool isReg = false;
@@ -1943,8 +1928,8 @@ static bool populateInstruction(CodeGenTarget &Target,
continue;
}
- if (Var->getName() != NI->second &&
- Var->getName() != TiedNames[NI->second]) {
+ if (Var->getName() != Op.second &&
+ Var->getName() != TiedNames[Op.second]) {
if (Base != ~0U) {
OpInfo.addField(Base, Width, Offset);
Base = ~0U;
@@ -2181,12 +2166,10 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
}
DecoderTableInfo TableInfo;
- for (std::map<std::pair<std::string, unsigned>,
- std::vector<unsigned> >::const_iterator
- I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) {
+ for (const auto &Opc : OpcMap) {
// Emit the decoder for this namespace+width combination.
- FilterChooser FC(*NumberedInstructions, I->second, Operands,
- 8*I->first.second, this);
+ FilterChooser FC(*NumberedInstructions, Opc.second, Operands,
+ 8*Opc.first.second, this);
// The decode table is cleared for each top level decoder function. The
// predicates and decoders themselves, however, are shared across all
@@ -2207,7 +2190,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
TableInfo.Table.push_back(MCD::OPC_Fail);
// Print the table to the output stream.
- emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), I->first.first);
+ emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), Opc.first.first);
OS.flush();
}
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 6fdf22d..c5999de 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -143,7 +143,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
Res += "|(1<<MCOI::OptionalDef)";
// Fill in operand type.
- Res += ", MCOI::";
+ Res += ", ";
assert(!Op.OperandType.empty() && "Invalid operand type.");
Res += Op.OperandType;
@@ -476,7 +476,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
<< SchedModels.getSchedClassIdx(Inst) << ",\t"
<< Inst.TheDef->getValueAsInt("Size") << ",\t0";
- // Emit all of the target indepedent flags...
+ // Emit all of the target independent flags...
if (Inst.isPseudo) OS << "|(1<<MCID::Pseudo)";
if (Inst.isReturn) OS << "|(1<<MCID::Return)";
if (Inst.isBranch) OS << "|(1<<MCID::Branch)";
@@ -587,14 +587,16 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
for (const CodeGenInstruction *Inst : NumberedInstructions)
OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n";
OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n";
- OS << " };\n";
+ OS << " };\n\n";
OS << "namespace Sched {\n";
OS << " enum {\n";
Num = 0;
for (const auto &Class : SchedModels.explicit_classes())
OS << " " << Class.Name << "\t= " << Num++ << ",\n";
OS << " SCHED_LIST_END = " << SchedModels.numInstrSchedClasses() << "\n";
- OS << " };\n}\n}\n";
+ OS << " };\n";
+ OS << "} // End Sched namespace\n";
+ OS << "} // End " << Namespace << " namespace\n";
OS << "} // End llvm namespace \n";
OS << "#endif // GET_INSTRINFO_ENUM\n\n";
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index 37f6de0..e71c695 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -257,7 +257,10 @@ enum IIT_Info {
IIT_ANYPTR = 26,
IIT_V1 = 27,
IIT_VARARG = 28,
- IIT_HALF_VEC_ARG = 29
+ IIT_HALF_VEC_ARG = 29,
+ IIT_SAME_VEC_WIDTH_ARG = 30,
+ IIT_PTR_TO_ARG = 31,
+ IIT_VEC_OF_PTRS_TO_ELT = 32
};
@@ -289,7 +292,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
}
}
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(__clang__)
#pragma optimize("",off) // MSVC 2010 optimizer can't deal with this function.
#endif
@@ -305,9 +308,20 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
Sig.push_back(IIT_TRUNC_ARG);
else if (R->isSubClassOf("LLVMHalfElementsVectorType"))
Sig.push_back(IIT_HALF_VEC_ARG);
+ else if (R->isSubClassOf("LLVMVectorSameWidth")) {
+ Sig.push_back(IIT_SAME_VEC_WIDTH_ARG);
+ Sig.push_back((Number << 3) | ArgCodes[Number]);
+ MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy"));
+ EncodeFixedValueType(VT, Sig);
+ return;
+ }
+ else if (R->isSubClassOf("LLVMPointerTo"))
+ Sig.push_back(IIT_PTR_TO_ARG);
+ else if (R->isSubClassOf("LLVMVectorOfPointersToElt"))
+ Sig.push_back(IIT_VEC_OF_PTRS_TO_ELT);
else
Sig.push_back(IIT_ARG);
- return Sig.push_back((Number << 2) | ArgCodes[Number]);
+ return Sig.push_back((Number << 3) | ArgCodes[Number]);
}
MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
@@ -318,7 +332,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
case MVT::iPTRAny: ++Tmp; // FALL THROUGH.
case MVT::vAny: ++Tmp; // FALL THROUGH.
case MVT::fAny: ++Tmp; // FALL THROUGH.
- case MVT::iAny: {
+ case MVT::iAny: ++Tmp; // FALL THROUGH.
+ case MVT::Any: {
// If this is an "any" valuetype, then the type is the type of the next
// type in the list specified to getIntrinsic().
Sig.push_back(IIT_ARG);
@@ -327,8 +342,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
unsigned ArgNo = ArgCodes.size();
ArgCodes.push_back(Tmp);
- // Encode what sort of argument it must be in the low 2 bits of the ArgNo.
- return Sig.push_back((ArgNo << 2) | Tmp);
+ // Encode what sort of argument it must be in the low 3 bits of the ArgNo.
+ return Sig.push_back((ArgNo << 3) | Tmp);
}
case MVT::iPTR: {
@@ -366,7 +381,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
EncodeFixedValueType(VT, Sig);
}
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(__clang__)
#pragma optimize("",on)
#endif
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index 79d08a9..5a6694e 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -53,27 +53,30 @@ public:
void run(raw_ostream &o);
private:
- void EmitRegMapping(raw_ostream &o,
- const std::vector<CodeGenRegister*> &Regs, bool isCtor);
+ void EmitRegMapping(raw_ostream &o, const std::deque<CodeGenRegister> &Regs,
+ bool isCtor);
void EmitRegMappingTables(raw_ostream &o,
- const std::vector<CodeGenRegister*> &Regs,
+ const std::deque<CodeGenRegister> &Regs,
bool isCtor);
void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
const std::string &ClassName);
void emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank,
const std::string &ClassName);
+ void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank,
+ const std::string &ClassName);
};
} // End anonymous namespace
// runEnums - Print out enum values for all of the registers.
void RegisterInfoEmitter::runEnums(raw_ostream &OS,
CodeGenTarget &Target, CodeGenRegBank &Bank) {
- const std::vector<CodeGenRegister*> &Registers = Bank.getRegisters();
+ const auto &Registers = Bank.getRegisters();
// Register enums are stored as uint16_t in the tables. Make sure we'll fit.
assert(Registers.size() <= 0xffff && "Too many regs to fit in tables");
- std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace");
+ std::string Namespace =
+ Registers.front().TheDef->getValueAsString("Namespace");
emitSourceFileHeader("Target Register Enum Values", OS);
@@ -90,17 +93,16 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "namespace " << Namespace << " {\n";
OS << "enum {\n NoRegister,\n";
- for (unsigned i = 0, e = Registers.size(); i != e; ++i)
- OS << " " << Registers[i]->getName() << " = " <<
- Registers[i]->EnumValue << ",\n";
- assert(Registers.size() == Registers[Registers.size()-1]->EnumValue &&
+ for (const auto &Reg : Registers)
+ OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n";
+ assert(Registers.size() == Registers.back().EnumValue &&
"Register enum value mismatch!");
OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
OS << "};\n";
if (!Namespace.empty())
OS << "}\n";
- ArrayRef<CodeGenRegisterClass*> RegisterClasses = Bank.getRegClasses();
+ const auto &RegisterClasses = Bank.getRegClasses();
if (!RegisterClasses.empty()) {
// RegisterClass enums are stored as uint16_t in the tables.
@@ -111,11 +113,9 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
OS << "enum {\n";
- for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- if (i) OS << ",\n";
- OS << " " << RegisterClasses[i]->getName() << "RegClassID";
- OS << " = " << i;
- }
+ for (const auto &RC : RegisterClasses)
+ OS << " " << RC.getName() << "RegClassID"
+ << " = " << RC.EnumValue << ",\n";
OS << "\n };\n";
if (!Namespace.empty())
OS << "}\n";
@@ -137,25 +137,38 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "}\n";
}
- ArrayRef<CodeGenSubRegIndex*> SubRegIndices = Bank.getSubRegIndices();
+ auto &SubRegIndices = Bank.getSubRegIndices();
if (!SubRegIndices.empty()) {
OS << "\n// Subregister indices\n";
- std::string Namespace =
- SubRegIndices[0]->getNamespace();
+ std::string Namespace = SubRegIndices.front().getNamespace();
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
OS << "enum {\n NoSubRegister,\n";
- for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i)
- OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n";
+ unsigned i = 0;
+ for (const auto &Idx : SubRegIndices)
+ OS << " " << Idx.getName() << ",\t// " << ++i << "\n";
OS << " NUM_TARGET_SUBREGS\n};\n";
if (!Namespace.empty())
OS << "}\n";
}
- OS << "} // End llvm namespace \n";
+ OS << "} // End llvm namespace\n";
OS << "#endif // GET_REGINFO_ENUM\n\n";
}
+static void printInt(raw_ostream &OS, int Val) {
+ OS << Val;
+}
+
+static const char *getMinimalTypeForRange(uint64_t Range) {
+ assert(Range < 0xFFFFFFFFULL && "Enum too large");
+ if (Range > 0xFFFF)
+ return "uint32_t";
+ if (Range > 0xFF)
+ return "uint16_t";
+ return "uint8_t";
+}
+
void RegisterInfoEmitter::
EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
const std::string &ClassName) {
@@ -166,9 +179,8 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< "const RegClassWeight &" << ClassName << "::\n"
<< "getRegClassWeight(const TargetRegisterClass *RC) const {\n"
<< " static const RegClassWeight RCWeightTable[] = {\n";
- for (unsigned i = 0, e = NumRCs; i != e; ++i) {
- const CodeGenRegisterClass &RC = *RegBank.getRegClasses()[i];
- const CodeGenRegister::Set &Regs = RC.getMembers();
+ for (const auto &RC : RegBank.getRegClasses()) {
+ const CodeGenRegister::Vec &Regs = RC.getMembers();
if (Regs.empty())
OS << " {0, 0";
else {
@@ -179,7 +191,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
}
OS << "}, \t// " << RC.getName() << "\n";
}
- OS << " {0, 0} };\n"
+ OS << " };\n"
<< " return RCWeightTable[RC->getID()];\n"
<< "}\n\n";
@@ -204,7 +216,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
assert(RU.Weight < 256 && "RegUnit too heavy");
OS << RU.Weight << ", ";
}
- OS << "0 };\n"
+ OS << "};\n"
<< " return RUWeightTable[RegUnit];\n";
}
else {
@@ -222,8 +234,11 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< "const char *" << ClassName << "::\n"
<< "getRegPressureSetName(unsigned Idx) const {\n"
<< " static const char *PressureNameTable[] = {\n";
+ unsigned MaxRegUnitWeight = 0;
for (unsigned i = 0; i < NumSets; ++i ) {
- OS << " \"" << RegBank.getRegSetAt(i).Name << "\",\n";
+ const RegUnitSet &RegUnits = RegBank.getRegSetAt(i);
+ MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight);
+ OS << " \"" << RegUnits.Name << "\",\n";
}
OS << " nullptr };\n"
<< " return PressureNameTable[Idx];\n"
@@ -233,63 +248,54 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< "// This limit must be adjusted dynamically for reserved registers.\n"
<< "unsigned " << ClassName << "::\n"
<< "getRegPressureSetLimit(unsigned Idx) const {\n"
- << " static const unsigned PressureLimitTable[] = {\n";
+ << " static const " << getMinimalTypeForRange(MaxRegUnitWeight)
+ << " PressureLimitTable[] = {\n";
for (unsigned i = 0; i < NumSets; ++i ) {
const RegUnitSet &RegUnits = RegBank.getRegSetAt(i);
OS << " " << RegUnits.Weight << ", \t// " << i << ": "
<< RegUnits.Name << "\n";
}
- OS << " 0 };\n"
+ OS << " };\n"
<< " return PressureLimitTable[Idx];\n"
<< "}\n\n";
+ SequenceToOffsetTable<std::vector<int>> PSetsSeqs;
+
// This table may be larger than NumRCs if some register units needed a list
// of unit sets that did not correspond to a register class.
unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists();
- OS << "/// Table of pressure sets per register class or unit.\n"
- << "static const int RCSetsTable[] = {\n ";
- std::vector<unsigned> RCSetStarts(NumRCUnitSets);
- for (unsigned i = 0, StartIdx = 0, e = NumRCUnitSets; i != e; ++i) {
- RCSetStarts[i] = StartIdx;
+ std::vector<std::vector<int>> PSets(NumRCUnitSets);
+
+ for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) {
ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(i);
- std::vector<unsigned> PSets;
- PSets.reserve(PSetIDs.size());
+ PSets[i].reserve(PSetIDs.size());
for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(),
PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) {
- PSets.push_back(RegBank.getRegPressureSet(*PSetI).Order);
- }
- std::sort(PSets.begin(), PSets.end());
- for (unsigned j = 0, e = PSets.size(); j < e; ++j) {
- OS << PSets[j] << ", ";
- ++StartIdx;
+ PSets[i].push_back(RegBank.getRegPressureSet(*PSetI).Order);
}
- OS << "-1, \t// #" << RCSetStarts[i] << " ";
- if (i < NumRCs)
- OS << RegBank.getRegClasses()[i]->getName();
- else {
- OS << "inferred";
- for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(),
- PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) {
- OS << "~" << RegBank.getRegSetAt(*PSetI).Name;
- }
- }
- OS << "\n ";
- ++StartIdx;
+ std::sort(PSets[i].begin(), PSets[i].end());
+ PSetsSeqs.add(PSets[i]);
}
- OS << "-1 };\n\n";
+
+ PSetsSeqs.layout();
+
+ OS << "/// Table of pressure sets per register class or unit.\n"
+ << "static const int RCSetsTable[] = {\n";
+ PSetsSeqs.emit(OS, printInt, "-1");
+ OS << "};\n\n";
OS << "/// Get the dimensions of register pressure impacted by this "
<< "register class.\n"
<< "/// Returns a -1 terminated array of pressure set IDs\n"
<< "const int* " << ClassName << "::\n"
<< "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n";
- OS << " static const unsigned RCSetStartTable[] = {\n ";
+ OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1)
+ << " RCSetStartTable[] = {\n ";
for (unsigned i = 0, e = NumRCs; i != e; ++i) {
- OS << RCSetStarts[i] << ",";
+ OS << PSetsSeqs.get(PSets[i]) << ",";
}
- OS << "0 };\n"
- << " unsigned SetListStart = RCSetStartTable[RC->getID()];\n"
- << " return &RCSetsTable[SetListStart];\n"
+ OS << "};\n"
+ << " return &RCSetsTable[RCSetStartTable[RC->getID()]];\n"
<< "}\n\n";
OS << "/// Get the dimensions of register pressure impacted by this "
@@ -299,29 +305,28 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< "getRegUnitPressureSets(unsigned RegUnit) const {\n"
<< " assert(RegUnit < " << RegBank.getNumNativeRegUnits()
<< " && \"invalid register unit\");\n";
- OS << " static const unsigned RUSetStartTable[] = {\n ";
+ OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1)
+ << " RUSetStartTable[] = {\n ";
for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();
UnitIdx < UnitEnd; ++UnitIdx) {
- OS << RCSetStarts[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx] << ",";
+ OS << PSetsSeqs.get(PSets[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx])
+ << ",";
}
- OS << "0 };\n"
- << " unsigned SetListStart = RUSetStartTable[RegUnit];\n"
- << " return &RCSetsTable[SetListStart];\n"
+ OS << "};\n"
+ << " return &RCSetsTable[RUSetStartTable[RegUnit]];\n"
<< "}\n\n";
}
-void
-RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS,
- const std::vector<CodeGenRegister*> &Regs,
- bool isCtor) {
+void RegisterInfoEmitter::EmitRegMappingTables(
+ raw_ostream &OS, const std::deque<CodeGenRegister> &Regs, bool isCtor) {
// Collect all information about dwarf register numbers
typedef std::map<Record*, std::vector<int64_t>, LessRecordRegister> DwarfRegNumsMapTy;
DwarfRegNumsMapTy DwarfRegNums;
// First, just pull all provided information to the map
unsigned maxLength = 0;
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *Reg = Regs[i]->TheDef;
+ for (auto &RE : Regs) {
+ Record *Reg = RE.TheDef;
std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
maxLength = std::max((size_t)maxLength, RegNums.size());
if (DwarfRegNums.count(Reg))
@@ -339,7 +344,7 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS,
for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
I->second.push_back(-1);
- std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace");
+ std::string Namespace = Regs.front().TheDef->getValueAsString("Namespace");
OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n";
@@ -387,8 +392,8 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS,
}
}
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *Reg = Regs[i]->TheDef;
+ for (auto &RE : Regs) {
+ Record *Reg = RE.TheDef;
const RecordVal *V = Reg->getValue("DwarfAlias");
if (!V || !V->getValue())
continue;
@@ -435,15 +440,13 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS,
}
}
-void
-RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
- const std::vector<CodeGenRegister*> &Regs,
- bool isCtor) {
+void RegisterInfoEmitter::EmitRegMapping(
+ raw_ostream &OS, const std::deque<CodeGenRegister> &Regs, bool isCtor) {
// Emit the initializer so the tables from EmitRegMappingTables get wired up
// to the MCRegisterInfo object.
unsigned maxLength = 0;
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *Reg = Regs[i]->TheDef;
+ for (auto &RE : Regs) {
+ Record *Reg = RE.TheDef;
maxLength = std::max((size_t)maxLength,
Reg->getValueAsListOfInts("DwarfNumbers").size());
}
@@ -451,7 +454,7 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
if (!maxLength)
return;
- std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace");
+ std::string Namespace = Regs.front().TheDef->getValueAsString("Namespace");
// Emit reverse information about the dwarf register numbers.
for (unsigned j = 0; j < 2; ++j) {
@@ -565,15 +568,16 @@ static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) {
// 0 differential which means we can't encode repeated elements.
typedef SmallVector<uint16_t, 4> DiffVec;
+typedef SmallVector<unsigned, 4> MaskVec;
// Differentially encode a sequence of numbers into V. The starting value and
// terminating 0 are not added to V, so it will have the same size as List.
static
-DiffVec &diffEncode(DiffVec &V, unsigned InitVal, ArrayRef<unsigned> List) {
+DiffVec &diffEncode(DiffVec &V, unsigned InitVal, SparseBitVector<> List) {
assert(V.empty() && "Clear DiffVec before diffEncode.");
uint16_t Val = uint16_t(InitVal);
- for (unsigned i = 0; i != List.size(); ++i) {
- uint16_t Cur = List[i];
+
+ for (uint16_t Cur : List) {
V.push_back(Cur - Val);
Val = Cur;
}
@@ -597,6 +601,10 @@ static void printDiff16(raw_ostream &OS, uint16_t Val) {
OS << Val;
}
+static void printMask(raw_ostream &OS, unsigned Val) {
+ OS << format("0x%08X", Val);
+}
+
// Try to combine Idx's compose map into Vec if it is compatible.
// Return false if it's not possible.
static bool combine(const CodeGenSubRegIndex *Idx,
@@ -616,20 +624,11 @@ static bool combine(const CodeGenSubRegIndex *Idx,
return true;
}
-static const char *getMinimalTypeForRange(uint64_t Range) {
- assert(Range < 0xFFFFFFFFULL && "Enum too large");
- if (Range > 0xFFFF)
- return "uint32_t";
- if (Range > 0xFF)
- return "uint16_t";
- return "uint8_t";
-}
-
void
RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
CodeGenRegBank &RegBank,
const std::string &ClName) {
- ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices();
+ const auto &SubRegIndices = RegBank.getSubRegIndices();
OS << "unsigned " << ClName
<< "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n";
@@ -644,10 +643,12 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
SmallVector<unsigned, 4> RowMap;
SmallVector<SmallVector<CodeGenSubRegIndex*, 4>, 4> Rows;
- for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
+ auto SubRegIndicesSize =
+ std::distance(SubRegIndices.begin(), SubRegIndices.end());
+ for (const auto &Idx : SubRegIndices) {
unsigned Found = ~0u;
for (unsigned r = 0, re = Rows.size(); r != re; ++r) {
- if (combine(SubRegIndices[i], Rows[r])) {
+ if (combine(&Idx, Rows[r])) {
Found = r;
break;
}
@@ -655,27 +656,27 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
if (Found == ~0u) {
Found = Rows.size();
Rows.resize(Found + 1);
- Rows.back().resize(SubRegIndices.size());
- combine(SubRegIndices[i], Rows.back());
+ Rows.back().resize(SubRegIndicesSize);
+ combine(&Idx, Rows.back());
}
RowMap.push_back(Found);
}
// Output the row map if there is multiple rows.
if (Rows.size() > 1) {
- OS << " static const " << getMinimalTypeForRange(Rows.size())
- << " RowMap[" << SubRegIndices.size() << "] = {\n ";
- for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i)
+ OS << " static const " << getMinimalTypeForRange(Rows.size()) << " RowMap["
+ << SubRegIndicesSize << "] = {\n ";
+ for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i)
OS << RowMap[i] << ", ";
OS << "\n };\n";
}
// Output the rows.
- OS << " static const " << getMinimalTypeForRange(SubRegIndices.size()+1)
- << " Rows[" << Rows.size() << "][" << SubRegIndices.size() << "] = {\n";
+ OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1)
+ << " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n";
for (unsigned r = 0, re = Rows.size(); r != re; ++r) {
OS << " { ";
- for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i)
+ for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i)
if (Rows[r][i])
OS << Rows[r][i]->EnumValue << ", ";
else
@@ -684,8 +685,8 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
}
OS << " };\n\n";
- OS << " --IdxA; assert(IdxA < " << SubRegIndices.size() << ");\n"
- << " --IdxB; assert(IdxB < " << SubRegIndices.size() << ");\n";
+ OS << " --IdxA; assert(IdxA < " << SubRegIndicesSize << ");\n"
+ << " --IdxB; assert(IdxB < " << SubRegIndicesSize << ");\n";
if (Rows.size() > 1)
OS << " return Rows[RowMap[IdxA]][IdxB];\n";
else
@@ -693,6 +694,95 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
OS << "}\n\n";
}
+void
+RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
+ CodeGenRegBank &RegBank,
+ const std::string &ClName) {
+ // See the comments in computeSubRegLaneMasks() for our goal here.
+ const auto &SubRegIndices = RegBank.getSubRegIndices();
+
+ // Create a list of Mask+Rotate operations, with equivalent entries merged.
+ SmallVector<unsigned, 4> SubReg2SequenceIndexMap;
+ SmallVector<SmallVector<MaskRolPair, 1>, 4> Sequences;
+ for (const auto &Idx : SubRegIndices) {
+ const SmallVector<MaskRolPair, 1> &IdxSequence
+ = Idx.CompositionLaneMaskTransform;
+
+ unsigned Found = ~0u;
+ unsigned SIdx = 0;
+ unsigned NextSIdx;
+ for (size_t s = 0, se = Sequences.size(); s != se; ++s, SIdx = NextSIdx) {
+ SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s];
+ NextSIdx = SIdx + Sequence.size() + 1;
+ if (Sequence.size() != IdxSequence.size())
+ continue;
+ bool Identical = true;
+ for (size_t o = 0, oe = Sequence.size(); o != oe; ++o) {
+ if (Sequence[o] != IdxSequence[o]) {
+ Identical = false;
+ break;
+ }
+ }
+ if (Identical) {
+ Found = SIdx;
+ break;
+ }
+ }
+ if (Found == ~0u) {
+ Sequences.push_back(IdxSequence);
+ Found = SIdx;
+ }
+ SubReg2SequenceIndexMap.push_back(Found);
+ }
+
+ OS << "unsigned " << ClName
+ << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, unsigned LaneMask)"
+ " const {\n";
+
+ OS << " struct MaskRolOp {\n"
+ " unsigned Mask;\n"
+ " uint8_t RotateLeft;\n"
+ " };\n"
+ " static const MaskRolOp Seqs[] = {\n";
+ unsigned Idx = 0;
+ for (size_t s = 0, se = Sequences.size(); s != se; ++s) {
+ OS << " ";
+ const SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s];
+ for (size_t p = 0, pe = Sequence.size(); p != pe; ++p) {
+ const MaskRolPair &P = Sequence[p];
+ OS << format("{ 0x%08X, %2u }, ", P.Mask, P.RotateLeft);
+ }
+ OS << "{ 0, 0 }";
+ if (s+1 != se)
+ OS << ", ";
+ OS << " // Sequence " << Idx << "\n";
+ Idx += Sequence.size() + 1;
+ }
+ OS << " };\n"
+ " static const MaskRolOp *CompositeSequences[] = {\n";
+ for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) {
+ OS << " ";
+ unsigned Idx = SubReg2SequenceIndexMap[i];
+ OS << format("&Seqs[%u]", Idx);
+ if (i+1 != e)
+ OS << ",";
+ OS << " // to " << SubRegIndices[i].getName() << "\n";
+ }
+ OS << " };\n\n";
+
+ OS << " --IdxA; assert(IdxA < " << SubRegIndices.size()
+ << " && \"Subregister index out of bounds\");\n"
+ " unsigned Result = 0;\n"
+ " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)"
+ " {\n"
+ " unsigned Masked = LaneMask & Ops->Mask;\n"
+ " Result |= (Masked << Ops->RotateLeft) & 0xFFFFFFFF;\n"
+ " Result |= (Masked >> ((32 - Ops->RotateLeft) & 0x1F));\n"
+ " }\n"
+ " return Result;\n"
+ "}\n";
+}
+
//
// runMCDesc - Print out MC register descriptions.
//
@@ -704,9 +794,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "\n#ifdef GET_REGINFO_MC_DESC\n";
OS << "#undef GET_REGINFO_MC_DESC\n";
- const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters();
+ const auto &Regs = RegBank.getRegisters();
- ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices();
+ auto &SubRegIndices = RegBank.getSubRegIndices();
// The lists of sub-registers and super-registers go in the same array. That
// allows us to share suffixes.
typedef std::vector<const CodeGenRegister*> RegVec;
@@ -718,36 +808,40 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
SmallVector<DiffVec, 4> RegUnitLists(Regs.size());
SmallVector<unsigned, 4> RegUnitInitScale(Regs.size());
+ // List of lane masks accompanying register unit sequences.
+ SequenceToOffsetTable<MaskVec> LaneMaskSeqs;
+ SmallVector<MaskVec, 4> RegUnitLaneMasks(Regs.size());
+
// Keep track of sub-register names as well. These are not differentially
// encoded.
typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec;
- SequenceToOffsetTable<SubRegIdxVec, CodeGenSubRegIndex::Less> SubRegIdxSeqs;
+ SequenceToOffsetTable<SubRegIdxVec, deref<llvm::less>> SubRegIdxSeqs;
SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size());
SequenceToOffsetTable<std::string> RegStrings;
// Precompute register lists for the SequenceToOffsetTable.
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- const CodeGenRegister *Reg = Regs[i];
-
- RegStrings.add(Reg->getName());
+ unsigned i = 0;
+ for (auto I = Regs.begin(), E = Regs.end(); I != E; ++I, ++i) {
+ const auto &Reg = *I;
+ RegStrings.add(Reg.getName());
// Compute the ordered sub-register list.
SetVector<const CodeGenRegister*> SR;
- Reg->addSubRegsPreOrder(SR, RegBank);
- diffEncode(SubRegLists[i], Reg->EnumValue, SR.begin(), SR.end());
+ Reg.addSubRegsPreOrder(SR, RegBank);
+ diffEncode(SubRegLists[i], Reg.EnumValue, SR.begin(), SR.end());
DiffSeqs.add(SubRegLists[i]);
// Compute the corresponding sub-register indexes.
SubRegIdxVec &SRIs = SubRegIdxLists[i];
for (unsigned j = 0, je = SR.size(); j != je; ++j)
- SRIs.push_back(Reg->getSubRegIndex(SR[j]));
+ SRIs.push_back(Reg.getSubRegIndex(SR[j]));
SubRegIdxSeqs.add(SRIs);
// Super-registers are already computed.
- const RegVec &SuperRegList = Reg->getSuperRegs();
- diffEncode(SuperRegLists[i], Reg->EnumValue,
- SuperRegList.begin(), SuperRegList.end());
+ const RegVec &SuperRegList = Reg.getSuperRegs();
+ diffEncode(SuperRegLists[i], Reg.EnumValue, SuperRegList.begin(),
+ SuperRegList.end());
DiffSeqs.add(SuperRegLists[i]);
// Differentially encode the register unit list, seeded by register number.
@@ -762,22 +856,36 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
//
// Check the neighboring registers for arithmetic progressions.
unsigned ScaleA = ~0u, ScaleB = ~0u;
- ArrayRef<unsigned> RUs = Reg->getNativeRegUnits();
- if (i > 0 && Regs[i-1]->getNativeRegUnits().size() == RUs.size())
- ScaleB = RUs.front() - Regs[i-1]->getNativeRegUnits().front();
- if (i+1 != Regs.size() &&
- Regs[i+1]->getNativeRegUnits().size() == RUs.size())
- ScaleA = Regs[i+1]->getNativeRegUnits().front() - RUs.front();
+ SparseBitVector<> RUs = Reg.getNativeRegUnits();
+ if (I != Regs.begin() &&
+ std::prev(I)->getNativeRegUnits().count() == RUs.count())
+ ScaleB = *RUs.begin() - *std::prev(I)->getNativeRegUnits().begin();
+ if (std::next(I) != Regs.end() &&
+ std::next(I)->getNativeRegUnits().count() == RUs.count())
+ ScaleA = *std::next(I)->getNativeRegUnits().begin() - *RUs.begin();
unsigned Scale = std::min(ScaleB, ScaleA);
// Default the scale to 0 if it can't be encoded in 4 bits.
if (Scale >= 16)
Scale = 0;
RegUnitInitScale[i] = Scale;
- DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg->EnumValue, RUs));
+ DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg.EnumValue, RUs));
+
+ const auto &RUMasks = Reg.getRegUnitLaneMasks();
+ MaskVec &LaneMaskVec = RegUnitLaneMasks[i];
+ assert(LaneMaskVec.empty());
+ LaneMaskVec.insert(LaneMaskVec.begin(), RUMasks.begin(), RUMasks.end());
+ // Terminator mask should not be used inside of the list.
+#ifndef NDEBUG
+ for (unsigned M : LaneMaskVec) {
+ assert(M != ~0u && "terminator mask should not be part of the list");
+ }
+#endif
+ LaneMaskSeqs.add(LaneMaskVec);
}
// Compute the final layout of the sequence table.
DiffSeqs.layout();
+ LaneMaskSeqs.layout();
SubRegIdxSeqs.layout();
OS << "namespace llvm {\n\n";
@@ -789,6 +897,11 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
DiffSeqs.emit(OS, printDiff16);
OS << "};\n\n";
+ // Emit the shared table of regunit lane mask sequences.
+ OS << "extern const unsigned " << TargetName << "LaneMaskLists[] = {\n";
+ LaneMaskSeqs.emit(OS, printMask, "~0u");
+ OS << "};\n\n";
+
// Emit the table of sub-register indexes.
OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n";
SubRegIdxSeqs.emit(OS, printSubRegIndex);
@@ -798,12 +911,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "extern const MCRegisterInfo::SubRegCoveredBits "
<< TargetName << "SubRegIdxRanges[] = {\n";
OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n";
- for (ArrayRef<CodeGenSubRegIndex*>::const_iterator
- SRI = SubRegIndices.begin(), SRE = SubRegIndices.end();
- SRI != SRE; ++SRI) {
- OS << " { " << (*SRI)->Offset << ", "
- << (*SRI)->Size
- << " },\t// " << (*SRI)->getName() << "\n";
+ for (const auto &Idx : SubRegIndices) {
+ OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// "
+ << Idx.getName() << "\n";
}
OS << "};\n\n";
@@ -815,16 +925,17 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "extern const MCRegisterDesc " << TargetName
<< "RegDesc[] = { // Descriptors\n";
- OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0 },\n";
+ OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n";
// Emit the register descriptors now.
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- const CodeGenRegister *Reg = Regs[i];
- OS << " { " << RegStrings.get(Reg->getName()) << ", "
- << DiffSeqs.get(SubRegLists[i]) << ", "
- << DiffSeqs.get(SuperRegLists[i]) << ", "
- << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", "
- << (DiffSeqs.get(RegUnitLists[i])*16 + RegUnitInitScale[i]) << " },\n";
+ i = 0;
+ for (const auto &Reg : Regs) {
+ OS << " { " << RegStrings.get(Reg.getName()) << ", "
+ << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i])
+ << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", "
+ << (DiffSeqs.get(RegUnitLists[i]) * 16 + RegUnitInitScale[i]) << ", "
+ << LaneMaskSeqs.get(RegUnitLaneMasks[i]) << " },\n";
+ ++i;
}
OS << "};\n\n"; // End of register descriptors...
@@ -842,7 +953,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "};\n\n";
- ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
+ const auto &RegisterClasses = RegBank.getRegClasses();
// Loop over all of the register classes... emitting each one.
OS << "namespace { // Register classes...\n";
@@ -850,8 +961,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
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];
+ for (const auto &RC : RegisterClasses) {
ArrayRef<Record*> Order = RC.getOrder();
// Give the register class a legal C name if it's anonymous.
@@ -891,9 +1001,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "extern const MCRegisterClass " << TargetName
<< "MCRegisterClasses[] = {\n";
- for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = *RegisterClasses[rc];
-
+ for (const auto &RC : RegisterClasses) {
// Asserts to make sure values will fit in table assuming types from
// MCRegisterInfo.h
assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large.");
@@ -919,8 +1027,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "RegEncodingTable[] = {\n";
// Add entry for NoRegister
OS << " 0,\n";
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *Reg = Regs[i]->TheDef;
+ for (const auto &RE : Regs) {
+ Record *Reg = RE.TheDef;
BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding");
uint64_t Value = 0;
for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) {
@@ -934,25 +1042,23 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
// MCRegisterInfo initialization routine.
OS << "static inline void Init" << TargetName
<< "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, "
- << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) {\n"
+ << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) "
+ "{\n"
<< " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, "
- << Regs.size()+1 << ", RA, PC, " << TargetName << "MCRegisterClasses, "
- << RegisterClasses.size() << ", "
- << TargetName << "RegUnitRoots, "
- << RegBank.getNumNativeRegUnits() << ", "
- << TargetName << "RegDiffLists, "
- << TargetName << "RegStrings, "
- << TargetName << "RegClassStrings, "
- << TargetName << "SubRegIdxLists, "
- << (SubRegIndices.size() + 1) << ",\n"
- << TargetName << "SubRegIdxRanges, "
- << TargetName << "RegEncodingTable);\n\n";
+ << Regs.size() + 1 << ", RA, PC, " << TargetName << "MCRegisterClasses, "
+ << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, "
+ << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, "
+ << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, "
+ << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, "
+ << (std::distance(SubRegIndices.begin(), SubRegIndices.end()) + 1) << ",\n"
+ << TargetName << "SubRegIdxRanges, " << TargetName
+ << "RegEncodingTable);\n\n";
EmitRegMapping(OS, Regs, false);
OS << "}\n\n";
- OS << "} // End llvm namespace \n";
+ OS << "} // End llvm namespace\n";
OS << "#endif // GET_REGINFO_MC_DESC\n\n";
}
@@ -979,6 +1085,8 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
if (!RegBank.getSubRegIndices().empty()) {
OS << " unsigned composeSubRegIndicesImpl"
<< "(unsigned, unsigned) const override;\n"
+ << " unsigned composeSubRegIndexLaneMaskImpl"
+ << "(unsigned, unsigned) const override;\n"
<< " const TargetRegisterClass *getSubClassWithSubReg"
<< "(const TargetRegisterClass*, unsigned) const override;\n";
}
@@ -994,14 +1102,13 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
<< "unsigned RegUnit) const override;\n"
<< "};\n\n";
- ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
+ const auto &RegisterClasses = RegBank.getRegClasses();
if (!RegisterClasses.empty()) {
- OS << "namespace " << RegisterClasses[0]->Namespace
+ OS << "namespace " << RegisterClasses.front().Namespace
<< " { // Register classes\n";
- for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = *RegisterClasses[i];
+ for (const auto &RC : RegisterClasses) {
const std::string &Name = RC.getName();
// Output the extern for the instance.
@@ -1009,7 +1116,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "} // end of namespace " << TargetName << "\n\n";
}
- OS << "} // End llvm namespace \n";
+ OS << "} // End llvm namespace\n";
OS << "#endif // GET_REGINFO_HEADER\n\n";
}
@@ -1031,15 +1138,14 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< "MCRegisterClasses[];\n";
// Start out by emitting each of the register classes.
- ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
- ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices();
+ const auto &RegisterClasses = RegBank.getRegClasses();
+ const auto &SubRegIndices = RegBank.getSubRegIndices();
// Collect all registers belonging to any allocatable class.
std::set<Record*> AllocatableRegs;
// Collect allocatable registers.
- for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ for (const auto &RC : RegisterClasses) {
ArrayRef<Record*> Order = RC.getOrder();
if (RC.Allocatable)
@@ -1048,8 +1154,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Build a shared array of value types.
SequenceToOffsetTable<SmallVector<MVT::SimpleValueType, 4> > VTSeqs;
- for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc)
- VTSeqs.add(RegisterClasses[rc]->VTs);
+ for (const auto &RC : RegisterClasses)
+ VTSeqs.add(RC.VTs);
VTSeqs.layout();
OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n";
VTSeqs.emit(OS, printSimpleValueType, "MVT::Other");
@@ -1057,18 +1163,17 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Emit SubRegIndex names, skipping 0.
OS << "\nstatic const char *const SubRegIndexNameTable[] = { \"";
- for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
- OS << SubRegIndices[i]->getName();
- if (i + 1 != e)
- OS << "\", \"";
+
+ for (const auto &Idx : SubRegIndices) {
+ OS << Idx.getName();
+ OS << "\", \"";
}
OS << "\" };\n\n";
// Emit SubRegIndex lane masks, including 0.
OS << "\nstatic const unsigned SubRegIndexLaneMaskTable[] = {\n ~0u,\n";
- for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
- OS << format(" 0x%08x, // ", SubRegIndices[i]->LaneMask)
- << SubRegIndices[i]->getName() << '\n';
+ for (const auto &Idx : SubRegIndices) {
+ OS << format(" 0x%08x, // ", Idx.LaneMask) << Idx.getName() << '\n';
}
OS << " };\n\n";
@@ -1100,27 +1205,25 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Compress the sub-reg index lists.
typedef std::vector<const CodeGenSubRegIndex*> IdxList;
SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size());
- SequenceToOffsetTable<IdxList, CodeGenSubRegIndex::Less> SuperRegIdxSeqs;
+ SequenceToOffsetTable<IdxList, deref<llvm::less>> SuperRegIdxSeqs;
BitVector MaskBV(RegisterClasses.size());
- for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ for (const auto &RC : RegisterClasses) {
OS << "static const uint32_t " << RC.getName() << "SubClassMask[] = {\n ";
printBitVectorAsHex(OS, RC.getSubClasses(), 32);
// Emit super-reg class masks for any relevant SubRegIndices that can
// project into RC.
- IdxList &SRIList = SuperRegIdxLists[rc];
- for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
- CodeGenSubRegIndex *Idx = SubRegIndices[sri];
+ IdxList &SRIList = SuperRegIdxLists[RC.EnumValue];
+ for (auto &Idx : SubRegIndices) {
MaskBV.reset();
- RC.getSuperRegClasses(Idx, MaskBV);
+ RC.getSuperRegClasses(&Idx, MaskBV);
if (MaskBV.none())
continue;
- SRIList.push_back(Idx);
+ SRIList.push_back(&Idx);
OS << "\n ";
printBitVectorAsHex(OS, MaskBV, 32);
- OS << "// " << Idx->getName();
+ OS << "// " << Idx.getName();
}
SuperRegIdxSeqs.add(SRIList);
OS << "\n};\n\n";
@@ -1132,8 +1235,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "};\n\n";
// Emit NULL terminated super-class lists.
- for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ for (const auto &RC : RegisterClasses) {
ArrayRef<CodeGenRegisterClass*> Supers = RC.getSuperClasses();
// Skip classes without supers. We can reuse NullRegClasses.
@@ -1142,14 +1244,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "static const TargetRegisterClass *const "
<< RC.getName() << "Superclasses[] = {\n";
- for (unsigned i = 0; i != Supers.size(); ++i)
- OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n";
+ for (const auto *Super : Supers)
+ OS << " &" << Super->getQualifiedName() << "RegClass,\n";
OS << " nullptr\n};\n\n";
}
// Emit methods.
- for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = *RegisterClasses[i];
+ for (const auto &RC : RegisterClasses) {
if (!RC.AltOrderSelect.empty()) {
OS << "\nstatic inline unsigned " << RC.getName()
<< "AltOrderSelect(const MachineFunction &MF) {"
@@ -1177,22 +1278,21 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << ")\n };\n const unsigned Select = " << RC.getName()
<< "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders()
<< ");\n return Order[Select];\n}\n";
- }
+ }
}
// Now emit the actual value-initialized register class instances.
- OS << "namespace " << RegisterClasses[0]->Namespace
+ OS << "\nnamespace " << RegisterClasses.front().Namespace
<< " { // Register class instances\n";
- for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = *RegisterClasses[i];
- OS << " extern const TargetRegisterClass "
- << RegisterClasses[i]->getName() << "RegClass = {\n "
- << '&' << Target.getName() << "MCRegisterClasses[" << RC.getName()
- << "RegClassID],\n "
- << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n "
- << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + "
- << SuperRegIdxSeqs.get(SuperRegIdxLists[i]) << ",\n ";
+ for (const auto &RC : RegisterClasses) {
+ OS << " extern const TargetRegisterClass " << RC.getName()
+ << "RegClass = {\n " << '&' << Target.getName()
+ << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n "
+ << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName()
+ << "SubClassMask,\n SuperRegIdxSeqs + "
+ << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n "
+ << format("0x%08x,\n ", RC.LaneMask);
if (RC.getSuperClasses().empty())
OS << "NullRegClasses,\n ";
else
@@ -1209,9 +1309,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "\nnamespace {\n";
OS << " const TargetRegisterClass* const RegisterClasses[] = {\n";
- for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
- OS << " &" << RegisterClasses[i]->getQualifiedName()
- << "RegClass,\n";
+ for (const auto &RC : RegisterClasses)
+ OS << " &" << RC.getQualifiedName() << "RegClass,\n";
OS << " };\n";
OS << "}\n"; // End of anonymous namespace...
@@ -1221,9 +1320,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< TargetName << "RegInfoDesc[] = { // Extra Descriptors\n";
OS << " { 0, 0 },\n";
- const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters();
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- const CodeGenRegister &Reg = *Regs[i];
+ const auto &Regs = RegBank.getRegisters();
+ for (const auto &Reg : Regs) {
OS << " { ";
OS << Reg.CostPerUse << ", "
<< int(AllocatableRegs.count(Reg.TheDef)) << " },\n";
@@ -1233,8 +1331,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
std::string ClassName = Target.getName() + "GenRegisterInfo";
- if (!SubRegIndices.empty())
+ auto SubRegIndicesSize =
+ std::distance(SubRegIndices.begin(), SubRegIndices.end());
+
+ if (!SubRegIndices.empty()) {
emitComposeSubRegIndices(OS, RegBank, ClassName);
+ emitComposeSubRegIndexLaneMask(OS, RegBank, ClassName);
+ }
// Emit getSubClassWithSubReg.
if (!SubRegIndices.empty()) {
@@ -1249,23 +1352,21 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << " static const uint16_t Table[";
else
PrintFatalError("Too many register classes.");
- OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n";
- for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) {
- const CodeGenRegisterClass &RC = *RegisterClasses[rci];
+ OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n";
+ for (const auto &RC : RegisterClasses) {
OS << " {\t// " << RC.getName() << "\n";
- for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
- CodeGenSubRegIndex *Idx = SubRegIndices[sri];
- if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx))
- OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName()
+ for (auto &Idx : SubRegIndices) {
+ if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(&Idx))
+ OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName()
<< " -> " << SRC->getName() << "\n";
else
- OS << " 0,\t// " << Idx->getName() << "\n";
+ OS << " 0,\t// " << Idx.getName() << "\n";
}
OS << " },\n";
}
OS << " };\n assert(RC && \"Missing regclass\");\n"
<< " if (!Idx) return RC;\n --Idx;\n"
- << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n"
+ << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n"
<< " unsigned TV = Table[RC->getID()][Idx];\n"
<< " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n";
}
@@ -1275,6 +1376,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Emit the constructor of the class...
OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n";
OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n";
+ OS << "extern const unsigned " << TargetName << "LaneMaskLists[];\n";
OS << "extern const char " << TargetName << "RegStrings[];\n";
OS << "extern const char " << TargetName << "RegClassStrings[];\n";
OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n";
@@ -1292,16 +1394,17 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< " SubRegIndexNameTable, SubRegIndexLaneMaskTable, 0x";
OS.write_hex(RegBank.CoveringLanes);
OS << ") {\n"
- << " InitMCRegisterInfo(" << TargetName << "RegDesc, "
- << Regs.size()+1 << ", RA, PC,\n " << TargetName
+ << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1
+ << ", RA, PC,\n " << TargetName
<< "MCRegisterClasses, " << RegisterClasses.size() << ",\n"
<< " " << TargetName << "RegUnitRoots,\n"
<< " " << RegBank.getNumNativeRegUnits() << ",\n"
<< " " << TargetName << "RegDiffLists,\n"
+ << " " << TargetName << "LaneMaskLists,\n"
<< " " << TargetName << "RegStrings,\n"
<< " " << TargetName << "RegClassStrings,\n"
<< " " << TargetName << "SubRegIdxLists,\n"
- << " " << SubRegIndices.size() + 1 << ",\n"
+ << " " << SubRegIndicesSize + 1 << ",\n"
<< " " << TargetName << "SubRegIdxRanges,\n"
<< " " << TargetName << "RegEncodingTable);\n\n";
@@ -1345,7 +1448,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "\n\n";
- OS << "} // End llvm namespace \n";
+ OS << "} // End llvm namespace\n";
OS << "#endif // GET_REGINFO_TARGET_DESC\n\n";
}
diff --git a/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h
index b58de4c..66506ea 100644
--- a/utils/TableGen/SequenceToOffsetTable.h
+++ b/utils/TableGen/SequenceToOffsetTable.h
@@ -84,6 +84,11 @@ public:
bool empty() const { return Seqs.empty(); }
+ unsigned size() const {
+ assert(Entries && "Call layout() before size()");
+ return Entries;
+ }
+
/// layout - Computes the final table layout.
void layout() {
assert(Entries == 0 && "Can only call layout() once");
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 9f2fc92..d8cf0d1 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -404,7 +404,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
OS << "}\n";
std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
- if (BPs.size()) {
+ if (!BPs.empty()) {
OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
<< "\"\n" << "namespace " << Name << "Bypass {\n";
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index bbd61f5..02fe4dc 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -143,9 +143,8 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
break;
case PrintEnums:
{
- std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
- for (unsigned i = 0, e = Recs.size(); i != e; ++i)
- OS << Recs[i]->getName() << ", ";
+ for (Record *Rec : Records.getAllDerivedDefinitions(Class))
+ OS << Rec->getName() << ", ";
OS << "\n";
break;
}
@@ -153,13 +152,12 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
{
SetTheory Sets;
Sets.addFieldExpander("Set", "Elements");
- std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set");
- for (unsigned i = 0, e = Recs.size(); i != e; ++i) {
- OS << Recs[i]->getName() << " = [";
- const std::vector<Record*> *Elts = Sets.expand(Recs[i]);
+ for (Record *Rec : Records.getAllDerivedDefinitions("Set")) {
+ OS << Rec->getName() << " = [";
+ const std::vector<Record*> *Elts = Sets.expand(Rec);
assert(Elts && "Couldn't expand Set instance");
- for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei)
- OS << ' ' << (*Elts)[ei]->getName();
+ for (Record *Elt : *Elts)
+ OS << ' ' << Elt->getName();
OS << " ]\n";
}
break;
diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp
index d7e981c..fbe5502 100644
--- a/utils/TableGen/X86DisassemblerTables.cpp
+++ b/utils/TableGen/X86DisassemblerTables.cpp
@@ -75,13 +75,13 @@ static inline const char* stringForOperandEncoding(OperandEncoding encoding) {
/// @return - True if child is a subset of parent, false otherwise.
static inline bool inheritsFrom(InstructionContext child,
InstructionContext parent,
- bool VEX_LIG = false) {
+ bool VEX_LIG = false, bool AdSize64 = false) {
if (child == parent)
return true;
switch (parent) {
case IC:
- return(inheritsFrom(child, IC_64BIT) ||
+ return(inheritsFrom(child, IC_64BIT, AdSize64) ||
inheritsFrom(child, IC_OPSIZE) ||
inheritsFrom(child, IC_ADSIZE) ||
inheritsFrom(child, IC_XD) ||
@@ -89,13 +89,19 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_64BIT:
return(inheritsFrom(child, IC_64BIT_REXW) ||
inheritsFrom(child, IC_64BIT_OPSIZE) ||
- inheritsFrom(child, IC_64BIT_ADSIZE) ||
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_ADSIZE)) ||
inheritsFrom(child, IC_64BIT_XD) ||
inheritsFrom(child, IC_64BIT_XS));
case IC_OPSIZE:
- return inheritsFrom(child, IC_64BIT_OPSIZE);
+ return inheritsFrom(child, IC_64BIT_OPSIZE) ||
+ inheritsFrom(child, IC_OPSIZE_ADSIZE);
case IC_ADSIZE:
+ return inheritsFrom(child, IC_OPSIZE_ADSIZE);
+ case IC_OPSIZE_ADSIZE:
+ return false;
case IC_64BIT_ADSIZE:
+ return inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE);
+ case IC_64BIT_OPSIZE_ADSIZE:
return false;
case IC_XD:
return inheritsFrom(child, IC_64BIT_XD);
@@ -108,9 +114,12 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_64BIT_REXW:
return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
inheritsFrom(child, IC_64BIT_REXW_XD) ||
- inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
+ inheritsFrom(child, IC_64BIT_REXW_OPSIZE) ||
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE)));
case IC_64BIT_OPSIZE:
- return(inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
+ return inheritsFrom(child, IC_64BIT_REXW_OPSIZE) ||
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE)) ||
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE));
case IC_64BIT_XD:
return(inheritsFrom(child, IC_64BIT_REXW_XD));
case IC_64BIT_XS:
@@ -121,6 +130,7 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_64BIT_REXW_XD:
case IC_64BIT_REXW_XS:
case IC_64BIT_REXW_OPSIZE:
+ case IC_64BIT_REXW_ADSIZE:
return false;
case IC_VEX:
return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W)) ||
@@ -713,6 +723,9 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
(index & ATTR_OPSIZE))
o << "IC_64BIT_REXW_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
+ (index & ATTR_ADSIZE))
+ o << "IC_64BIT_REXW_ADSIZE";
else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE))
o << "IC_64BIT_XD_OPSIZE";
else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE))
@@ -721,6 +734,9 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
o << "IC_64BIT_XS";
else if ((index & ATTR_64BIT) && (index & ATTR_XD))
o << "IC_64BIT_XD";
+ else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE) &&
+ (index & ATTR_ADSIZE))
+ o << "IC_64BIT_OPSIZE_ADSIZE";
else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE))
o << "IC_64BIT_OPSIZE";
else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE))
@@ -737,6 +753,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
o << "IC_XS";
else if (index & ATTR_XD)
o << "IC_XD";
+ else if ((index & ATTR_OPSIZE) && (index & ATTR_ADSIZE))
+ o << "IC_OPSIZE_ADSIZE";
else if (index & ATTR_OPSIZE)
o << "IC_OPSIZE";
else if (index & ATTR_ADSIZE)
@@ -822,15 +840,6 @@ void DisassemblerTables::setTableFields(ModRMDecision &decision,
InstructionSpecifier &previousInfo =
InstructionSpecifiers[decision.instructionIDs[index]];
- // Instructions such as MOV8ao8 and MOV8ao8_16 differ only in the
- // presence of the AdSize prefix. However, the disassembler doesn't
- // care about that difference in the instruction definition; it
- // handles 16-bit vs. 32-bit addressing for itself based purely
- // on the 0x67 prefix and the CPU mode. So there's no need to
- // disambiguate between them; just let them conflict/coexist.
- if (previousInfo.name + "_16" == newInfo.name)
- continue;
-
if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
newInfo.name == "XCHG32ar" ||
newInfo.name == "XCHG32ar64" ||
@@ -862,15 +871,19 @@ void DisassemblerTables::setTableFields(OpcodeType type,
const ModRMFilter &filter,
InstrUID uid,
bool is32bit,
- bool ignoresVEX_L) {
+ bool ignoresVEX_L,
+ unsigned addressSize) {
ContextDecision &decision = *Tables[type];
for (unsigned index = 0; index < IC_max; ++index) {
- if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT))
+ if ((is32bit || addressSize == 16) &&
+ inheritsFrom((InstructionContext)index, IC_64BIT))
continue;
+ bool adSize64 = addressSize == 64;
if (inheritsFrom((InstructionContext)index,
- InstructionSpecifiers[uid].insnContext, ignoresVEX_L))
+ InstructionSpecifiers[uid].insnContext, ignoresVEX_L,
+ adSize64))
setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
filter,
uid,
diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h
index d86b926..5a8688b 100644
--- a/utils/TableGen/X86DisassemblerTables.h
+++ b/utils/TableGen/X86DisassemblerTables.h
@@ -245,13 +245,15 @@ public:
/// @param uid - The unique ID of the instruction.
/// @param is32bit - Instructon is only 32-bit
/// @param ignoresVEX_L - Instruction ignores VEX.L
+ /// @param AddrSize - Instructions address size 16/32/64. 0 is unspecified
void setTableFields(OpcodeType type,
InstructionContext insnContext,
uint8_t opcode,
const ModRMFilter &filter,
InstrUID uid,
bool is32bit,
- bool ignoresVEX_L);
+ bool ignoresVEX_L,
+ unsigned AddrSize);
/// specForUID - Returns the instruction specifier for a given unique
/// instruction ID. Used when resolving collisions.
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index 9b8092f..5f12965 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -28,54 +28,65 @@ using namespace llvm;
MAP(C2, 34) \
MAP(C3, 35) \
MAP(C4, 36) \
- MAP(C8, 37) \
- MAP(C9, 38) \
- MAP(CA, 39) \
- MAP(CB, 40) \
- MAP(CF, 41) \
- MAP(D0, 42) \
- MAP(D1, 43) \
- MAP(D4, 44) \
- MAP(D5, 45) \
- MAP(D6, 46) \
- MAP(D7, 47) \
- MAP(D8, 48) \
- MAP(D9, 49) \
- MAP(DA, 50) \
- MAP(DB, 51) \
- MAP(DC, 52) \
- MAP(DD, 53) \
- MAP(DE, 54) \
- MAP(DF, 55) \
- MAP(E0, 56) \
- MAP(E1, 57) \
- MAP(E2, 58) \
- MAP(E3, 59) \
- MAP(E4, 60) \
- MAP(E5, 61) \
- MAP(E8, 62) \
- MAP(E9, 63) \
- MAP(EA, 64) \
- MAP(EB, 65) \
- MAP(EC, 66) \
- MAP(ED, 67) \
- MAP(EE, 68) \
- MAP(F0, 69) \
- MAP(F1, 70) \
- MAP(F2, 71) \
- MAP(F3, 72) \
- MAP(F4, 73) \
- MAP(F5, 74) \
- MAP(F6, 75) \
- MAP(F7, 76) \
- MAP(F8, 77) \
- MAP(F9, 78) \
- MAP(FA, 79) \
- MAP(FB, 80) \
- MAP(FC, 81) \
- MAP(FD, 82) \
- MAP(FE, 83) \
- MAP(FF, 84)
+ MAP(C5, 37) \
+ MAP(C6, 38) \
+ MAP(C7, 39) \
+ MAP(C8, 40) \
+ MAP(C9, 41) \
+ MAP(CA, 42) \
+ MAP(CB, 43) \
+ MAP(CC, 44) \
+ MAP(CD, 45) \
+ MAP(CE, 46) \
+ MAP(CF, 47) \
+ MAP(D0, 48) \
+ MAP(D1, 49) \
+ MAP(D2, 50) \
+ MAP(D3, 51) \
+ MAP(D4, 52) \
+ MAP(D5, 53) \
+ MAP(D6, 54) \
+ MAP(D7, 55) \
+ MAP(D8, 56) \
+ MAP(D9, 57) \
+ MAP(DA, 58) \
+ MAP(DB, 59) \
+ MAP(DC, 60) \
+ MAP(DD, 61) \
+ MAP(DE, 62) \
+ MAP(DF, 63) \
+ MAP(E0, 64) \
+ MAP(E1, 65) \
+ MAP(E2, 66) \
+ MAP(E3, 67) \
+ MAP(E4, 68) \
+ MAP(E5, 69) \
+ MAP(E6, 70) \
+ MAP(E7, 71) \
+ MAP(E8, 72) \
+ MAP(E9, 73) \
+ MAP(EA, 74) \
+ MAP(EB, 75) \
+ MAP(EC, 76) \
+ MAP(ED, 77) \
+ MAP(EE, 78) \
+ MAP(EF, 79) \
+ MAP(F0, 80) \
+ MAP(F1, 81) \
+ MAP(F2, 82) \
+ MAP(F3, 83) \
+ MAP(F4, 84) \
+ MAP(F5, 85) \
+ MAP(F6, 86) \
+ MAP(F7, 87) \
+ MAP(F8, 88) \
+ MAP(F9, 89) \
+ MAP(FA, 90) \
+ MAP(FB, 91) \
+ MAP(FC, 92) \
+ MAP(FD, 93) \
+ MAP(FE, 94) \
+ MAP(FF, 95)
// A clone of X86 since we can't depend on something that is generated.
namespace X86Local {
@@ -119,6 +130,10 @@ namespace X86Local {
enum {
OpSize16 = 1, OpSize32 = 2
};
+
+ enum {
+ AdSize16 = 1, AdSize32 = 2, AdSize64 = 3
+ };
}
using namespace X86Disassembler;
@@ -194,7 +209,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
Encoding = byteFromRec(Rec, "OpEncBits");
OpSize = byteFromRec(Rec, "OpSizeBits");
- HasAdSizePrefix = Rec->getValueAsBit("hasAdSizePrefix");
+ AdSize = byteFromRec(Rec, "AdSizeBits");
HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
HasVEX_4V = Rec->getValueAsBit("hasVEX_4V");
HasVEX_4VOp3 = Rec->getValueAsBit("hasVEX_4VOp3");
@@ -401,16 +416,20 @@ InstructionContext RecognizableInstr::insnContext() const {
errs() << "Instruction does not use a prefix: " << Name << "\n";
llvm_unreachable("Invalid prefix");
}
- } else if (Is64Bit || HasREX_WPrefix) {
+ } else if (Is64Bit || HasREX_WPrefix || AdSize == X86Local::AdSize64) {
if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD))
insnContext = IC_64BIT_REXW_OPSIZE;
+ else if (HasREX_WPrefix && AdSize == X86Local::AdSize32)
+ insnContext = IC_64BIT_REXW_ADSIZE;
else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD)
insnContext = IC_64BIT_XD_OPSIZE;
else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS)
insnContext = IC_64BIT_XS_OPSIZE;
+ else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize32)
+ insnContext = IC_64BIT_OPSIZE_ADSIZE;
else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)
insnContext = IC_64BIT_OPSIZE;
- else if (HasAdSizePrefix)
+ else if (AdSize == X86Local::AdSize32)
insnContext = IC_64BIT_ADSIZE;
else if (HasREX_WPrefix && OpPrefix == X86Local::XS)
insnContext = IC_64BIT_REXW_XS;
@@ -429,9 +448,11 @@ InstructionContext RecognizableInstr::insnContext() const {
insnContext = IC_XD_OPSIZE;
else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS)
insnContext = IC_XS_OPSIZE;
+ else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize16)
+ insnContext = IC_OPSIZE_ADSIZE;
else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)
insnContext = IC_OPSIZE;
- else if (HasAdSizePrefix)
+ else if (AdSize == X86Local::AdSize16)
insnContext = IC_ADSIZE;
else if (OpPrefix == X86Local::XD)
insnContext = IC_XD;
@@ -504,7 +525,7 @@ void RecognizableInstr::emitInstructionSpecifier() {
assert(numOperands <= X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough");
for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
- if (OperandList[operandIndex].Constraints.size()) {
+ if (!OperandList[operandIndex].Constraints.empty()) {
const CGIOperandList::ConstraintInfo &Constraint =
OperandList[operandIndex].Constraints[0];
if (Constraint.isTied()) {
@@ -793,9 +814,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
// Special cases where the LLVM tables are not complete
#define MAP(from, to) \
- case X86Local::MRM_##from: \
- filter = new ExactFilter(0x##from); \
- break;
+ case X86Local::MRM_##from:
OpcodeType opcodeType = (OpcodeType)-1;
@@ -844,12 +863,21 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
break;
MRM_MAPPING
+ filter = new ExactFilter(0xC0 + Form - X86Local::MRM_C0); \
+ break;
} // switch (Form)
opcodeToSet = Opcode;
break;
} // switch (OpMap)
+ unsigned AddressSize = 0;
+ switch (AdSize) {
+ case X86Local::AdSize16: AddressSize = 16; break;
+ case X86Local::AdSize32: AddressSize = 32; break;
+ case X86Local::AdSize64: AddressSize = 64; break;
+ }
+
assert(opcodeType != (OpcodeType)-1 &&
"Opcode type not set");
assert(filter && "Filter not set");
@@ -867,13 +895,13 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
insnContext(),
currentOpcode,
*filter,
- UID, Is32Bit, IgnoresVEX_L);
+ UID, Is32Bit, IgnoresVEX_L, AddressSize);
} else {
tables.setTableFields(opcodeType,
insnContext(),
opcodeToSet,
*filter,
- UID, Is32Bit, IgnoresVEX_L);
+ UID, Is32Bit, IgnoresVEX_L, AddressSize);
}
delete filter;
@@ -915,6 +943,8 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("GR64", TYPE_R64)
TYPE("i8mem", TYPE_M8)
TYPE("i8imm", TYPE_IMM8)
+ TYPE("u8imm", TYPE_UIMM8)
+ TYPE("i32u8imm", TYPE_UIMM8)
TYPE("GR8", TYPE_R8)
TYPE("VR128", TYPE_XMM128)
TYPE("VR128X", TYPE_XMM128)
@@ -937,17 +967,19 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("i16imm_pcrel", TYPE_REL16)
TYPE("i32imm_pcrel", TYPE_REL32)
TYPE("SSECC", TYPE_IMM3)
+ TYPE("XOPCC", TYPE_IMM3)
TYPE("AVXCC", TYPE_IMM5)
+ TYPE("AVX512ICC", TYPE_AVX512ICC)
TYPE("AVX512RC", TYPE_IMM32)
- TYPE("brtarget", TYPE_RELv)
- TYPE("uncondbrtarget", TYPE_RELv)
+ TYPE("brtarget32", TYPE_RELv)
+ TYPE("brtarget16", TYPE_RELv)
TYPE("brtarget8", TYPE_REL8)
TYPE("f80mem", TYPE_M80FP)
- TYPE("lea32mem", TYPE_LEA)
TYPE("lea64_32mem", TYPE_LEA)
TYPE("lea64mem", TYPE_LEA)
TYPE("VR64", TYPE_MM64)
TYPE("i64imm", TYPE_IMMv)
+ TYPE("anymem", TYPE_M)
TYPE("opaque32mem", TYPE_M1616)
TYPE("opaque48mem", TYPE_M1632)
TYPE("opaque80mem", TYPE_M1664)
@@ -963,10 +995,17 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("dstidx16", TYPE_DSTIDX16)
TYPE("dstidx32", TYPE_DSTIDX32)
TYPE("dstidx64", TYPE_DSTIDX64)
- TYPE("offset8", TYPE_MOFFS8)
- TYPE("offset16", TYPE_MOFFS16)
- TYPE("offset32", TYPE_MOFFS32)
- TYPE("offset64", TYPE_MOFFS64)
+ TYPE("offset16_8", TYPE_MOFFS8)
+ TYPE("offset16_16", TYPE_MOFFS16)
+ TYPE("offset16_32", TYPE_MOFFS32)
+ TYPE("offset32_8", TYPE_MOFFS8)
+ TYPE("offset32_16", TYPE_MOFFS16)
+ TYPE("offset32_32", TYPE_MOFFS32)
+ TYPE("offset32_64", TYPE_MOFFS64)
+ TYPE("offset64_8", TYPE_MOFFS8)
+ TYPE("offset64_16", TYPE_MOFFS16)
+ TYPE("offset64_32", TYPE_MOFFS32)
+ TYPE("offset64_64", TYPE_MOFFS64)
TYPE("VR256", TYPE_XMM256)
TYPE("VR256X", TYPE_XMM256)
TYPE("VR512", TYPE_XMM512)
@@ -1010,7 +1049,9 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s,
}
ENCODING("i32i8imm", ENCODING_IB)
ENCODING("SSECC", ENCODING_IB)
+ ENCODING("XOPCC", ENCODING_IB)
ENCODING("AVXCC", ENCODING_IB)
+ ENCODING("AVX512ICC", ENCODING_IB)
ENCODING("AVX512RC", ENCODING_IB)
ENCODING("i16imm", ENCODING_Iv)
ENCODING("i16i8imm", ENCODING_IB)
@@ -1018,6 +1059,8 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s,
ENCODING("i64i32imm", ENCODING_ID)
ENCODING("i64i8imm", ENCODING_IB)
ENCODING("i8imm", ENCODING_IB)
+ ENCODING("u8imm", ENCODING_IB)
+ ENCODING("i32u8imm", ENCODING_IB)
// This is not a typo. Instructions like BLENDVPD put
// register IDs in 8-bit immediates nowadays.
ENCODING("FR32", ENCODING_IB)
@@ -1153,9 +1196,9 @@ RecognizableInstr::memoryEncodingFromString(const std::string &s,
ENCODING("i256mem", ENCODING_RM)
ENCODING("i512mem", ENCODING_RM)
ENCODING("f80mem", ENCODING_RM)
- ENCODING("lea32mem", ENCODING_RM)
ENCODING("lea64_32mem", ENCODING_RM)
ENCODING("lea64mem", ENCODING_RM)
+ ENCODING("anymem", ENCODING_RM)
ENCODING("opaque32mem", ENCODING_RM)
ENCODING("opaque48mem", ENCODING_RM)
ENCODING("opaque80mem", ENCODING_RM)
@@ -1186,16 +1229,26 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s,
ENCODING("i64i32imm", ENCODING_ID)
ENCODING("i64i8imm", ENCODING_IB)
ENCODING("i8imm", ENCODING_IB)
+ ENCODING("u8imm", ENCODING_IB)
+ ENCODING("i32u8imm", ENCODING_IB)
ENCODING("i64i32imm_pcrel", ENCODING_ID)
ENCODING("i16imm_pcrel", ENCODING_IW)
ENCODING("i32imm_pcrel", ENCODING_ID)
- ENCODING("brtarget", ENCODING_Iv)
+ ENCODING("brtarget32", ENCODING_Iv)
+ ENCODING("brtarget16", ENCODING_Iv)
ENCODING("brtarget8", ENCODING_IB)
ENCODING("i64imm", ENCODING_IO)
- ENCODING("offset8", ENCODING_Ia)
- ENCODING("offset16", ENCODING_Ia)
- ENCODING("offset32", ENCODING_Ia)
- ENCODING("offset64", ENCODING_Ia)
+ ENCODING("offset16_8", ENCODING_Ia)
+ ENCODING("offset16_16", ENCODING_Ia)
+ ENCODING("offset16_32", ENCODING_Ia)
+ ENCODING("offset32_8", ENCODING_Ia)
+ ENCODING("offset32_16", ENCODING_Ia)
+ ENCODING("offset32_32", ENCODING_Ia)
+ ENCODING("offset32_64", ENCODING_Ia)
+ ENCODING("offset64_8", ENCODING_Ia)
+ ENCODING("offset64_16", ENCODING_Ia)
+ ENCODING("offset64_32", ENCODING_Ia)
+ ENCODING("offset64_64", ENCODING_Ia)
ENCODING("srcidx8", ENCODING_SI)
ENCODING("srcidx16", ENCODING_SI)
ENCODING("srcidx32", ENCODING_SI)
diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h
index 95d7a40..28e1053 100644
--- a/utils/TableGen/X86RecognizableInstr.h
+++ b/utils/TableGen/X86RecognizableInstr.h
@@ -50,8 +50,8 @@ private:
uint8_t Encoding;
/// The OpSize field from the record
uint8_t OpSize;
- /// The hasAdSizePrefix field from the record
- bool HasAdSizePrefix;
+ /// The AdSize field from the record
+ uint8_t AdSize;
/// The hasREX_WPrefix field from the record
bool HasREX_WPrefix;
/// The hasVEX_4V field from the record
diff --git a/utils/emacs/emacs.el b/utils/emacs/emacs.el
index 969f538..4a3a503 100644
--- a/utils/emacs/emacs.el
+++ b/utils/emacs/emacs.el
@@ -1,39 +1,22 @@
;; LLVM coding style guidelines in emacs
;; Maintainer: LLVM Team, http://llvm.org/
-;; Modified: 2009-07-28
-;; Max 80 cols per line, indent by two spaces, no tabs.
-;; Apparently, this does not affect tabs in Makefiles.
-(custom-set-variables
- '(fill-column 80)
- '(c++-indent-level 2)
- '(c-basic-offset 2)
- '(indent-tabs-mode nil))
-
-
-;; Alternative to setting the global style. Only files with "llvm" in
-;; their names will automatically set to the llvm.org coding style.
+;; Add a cc-mode style for editing LLVM C and C++ code
(c-add-style "llvm.org"
- '((fill-column . 80)
+ '("gnu"
+ (fill-column . 80)
(c++-indent-level . 2)
(c-basic-offset . 2)
(indent-tabs-mode . nil)
- (c-offsets-alist . ((innamespace 0)))))
-
-(add-hook 'c-mode-hook
- (function
- (lambda nil
- (if (string-match "llvm" buffer-file-name)
- (progn
- (c-set-style "llvm.org")
- )
- ))))
+ (c-offsets-alist . ((arglist-intro . ++)
+ (innamespace . 0)
+ (member-init-intro . ++)))))
-(add-hook 'c++-mode-hook
+;; Files with "llvm" in their names will automatically be set to the
+;; llvm.org coding style.
+(add-hook 'c-mode-common-hook
(function
(lambda nil
(if (string-match "llvm" buffer-file-name)
(progn
- (c-set-style "llvm.org")
- )
- ))))
+ (c-set-style "llvm.org"))))))
diff --git a/utils/emacs/llvm-mode.el b/utils/emacs/llvm-mode.el
index 61127b6..5fb1eb3 100644
--- a/utils/emacs/llvm-mode.el
+++ b/utils/emacs/llvm-mode.el
@@ -1,8 +1,13 @@
+;;; llvm-mode.el --- Major mode for the LLVM assembler language.
+
;; Maintainer: The LLVM team, http://llvm.org/
-;; Description: Major mode for the LLVM assembler language.
-;; Updated: 2007-09-19
-;; Create mode-specific tables.
+;;; Commentary:
+
+;; Major mode for editing LLVM IR files.
+
+;;; Code:
+
(defvar llvm-mode-syntax-table nil
"Syntax table used while in LLVM mode.")
(defvar llvm-font-lock-keywords
@@ -18,7 +23,7 @@
;; Unnamed variable slots
'("%[-]?[0-9]+" . font-lock-variable-name-face)
;; Types
- `(,(regexp-opt '("void" "i[0-9]+" "float" "double" "type" "label" "opaque") 'words) . font-lock-type-face)
+ `(,(regexp-opt '("void" "i1" "i8" "i16" "i32" "i64" "i128" "float" "double" "type" "label" "opaque") 'symbol) . font-lock-type-face)
;; Integer literals
'("\\b[-]?[0-9]+\\b" . font-lock-preprocessor-face)
;; Floating point constants
@@ -30,29 +35,31 @@
"define" "global" "constant" "const" "internal" "linkonce" "linkonce_odr"
"weak" "weak_odr" "appending" "uninitialized" "implementation" "..."
"null" "undef" "to" "except" "not" "target" "endian" "little" "big"
- "pointersize" "volatile" "fastcc" "coldcc" "cc") 'words) . font-lock-keyword-face)
+ "pointersize" "volatile" "fastcc" "coldcc" "cc" "personality") 'symbols) . font-lock-keyword-face)
;; Arithmetic and Logical Operators
`(,(regexp-opt '("add" "sub" "mul" "sdiv" "udiv" "urem" "srem" "and" "or" "xor"
- "setne" "seteq" "setlt" "setgt" "setle" "setge") 'words) . font-lock-keyword-face)
+ "setne" "seteq" "setlt" "setgt" "setle" "setge") 'symbols) . font-lock-keyword-face)
;; Floating-point operators
- `(,(regexp-opt '("fadd" "fsub" "fmul" "fdiv" "frem") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("fadd" "fsub" "fmul" "fdiv" "frem") 'symbols) . font-lock-keyword-face)
;; Special instructions
- `(,(regexp-opt '("phi" "tail" "call" "select" "to" "shl" "lshr" "ashr" "fcmp" "icmp" "va_arg" "landingpad") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("phi" "tail" "call" "select" "to" "shl" "lshr" "ashr" "fcmp" "icmp" "va_arg" "landingpad") 'symbols) . font-lock-keyword-face)
;; Control instructions
- `(,(regexp-opt '("ret" "br" "switch" "invoke" "resume" "unwind" "unreachable" "indirectbr") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("ret" "br" "switch" "invoke" "resume" "unwind" "unreachable" "indirectbr") 'symbols) . font-lock-keyword-face)
;; Memory operators
- `(,(regexp-opt '("malloc" "alloca" "free" "load" "store" "getelementptr" "fence" "cmpxchg" "atomicrmw") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("malloc" "alloca" "free" "load" "store" "getelementptr" "fence" "cmpxchg" "atomicrmw") 'symbols) . font-lock-keyword-face)
;; Casts
- `(,(regexp-opt '("bitcast" "inttoptr" "ptrtoint" "trunc" "zext" "sext" "fptrunc" "fpext" "fptoui" "fptosi" "uitofp" "sitofp" "addrspacecast") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("bitcast" "inttoptr" "ptrtoint" "trunc" "zext" "sext" "fptrunc" "fpext" "fptoui" "fptosi" "uitofp" "sitofp" "addrspacecast") 'symbols) . font-lock-keyword-face)
;; Vector ops
- `(,(regexp-opt '("extractelement" "insertelement" "shufflevector") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("extractelement" "insertelement" "shufflevector") 'symbols) . font-lock-keyword-face)
;; Aggregate ops
- `(,(regexp-opt '("extractvalue" "insertvalue") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("extractvalue" "insertvalue") 'symbols) . font-lock-keyword-face)
+ ;; Metadata types
+ `(,(regexp-opt '("distinct") 'symbols) . font-lock-keyword-face)
;; Use-list order directives
- `(,(regexp-opt '("uselistorder" "uselistorder_bb") 'words) . font-lock-keyword-face)
+ `(,(regexp-opt '("uselistorder" "uselistorder_bb") 'symbols) . font-lock-keyword-face)
)
- "Syntax highlighting for LLVM"
+ "Syntax highlighting for LLVM."
)
;; ---------------------- Syntax table ---------------------------
@@ -62,40 +69,33 @@
(if (not llvm-mode-syntax-table)
(progn
(setq llvm-mode-syntax-table (make-syntax-table))
- (mapcar (function (lambda (n)
- (modify-syntax-entry (aref n 0)
- (aref n 1)
- llvm-mode-syntax-table)))
- '(
- ;; whitespace (` ')
- [?\^m " "]
- [?\f " "]
- [?\n " "]
- [?\t " "]
- [?\ " "]
- ;; word constituents (`w')
- ;;[?< "w"]
- ;;[?> "w"]
- [?\% "w"]
- ;;[?_ "w "]
- ;; comments
- [?\; "< "]
- [?\n "> "]
- ;;[?\r "> "]
- ;;[?\^m "> "]
- ;; symbol constituents (`_')
- ;; punctuation (`.')
- ;; open paren (`(')
- [?\( "("]
- [?\[ "("]
- [?\{ "("]
- ;; close paren (`)')
- [?\) ")"]
- [?\] ")"]
- [?\} ")"]
- ;; string quote ('"')
- [?\" "\""]
- ))))
+ (mapc (function (lambda (n)
+ (modify-syntax-entry (aref n 0)
+ (aref n 1)
+ llvm-mode-syntax-table)))
+ '(
+ ;; whitespace (` ')
+ [?\^m " "]
+ [?\f " "]
+ [?\n " "]
+ [?\t " "]
+ [?\ " "]
+ ;; word constituents (`w')
+ ;;[?< "w"]
+ ;;[?> "w"]
+ [?% "w"]
+ ;;[?_ "w "]
+ ;; comments
+ [?\; "< "]
+ [?\n "> "]
+ ;;[?\r "> "]
+ ;;[?\^m "> "]
+ ;; symbol constituents (`_')
+ ;; punctuation (`.')
+ ;; open paren (`(')
+ ;; close paren (`)')
+ ;; string quote ('"')
+ [?\" "\""]))))
;; --------------------- Abbrev table -----------------------------
@@ -113,11 +113,11 @@
(define-key llvm-mode-map "\es" 'center-line)
(define-key llvm-mode-map "\eS" 'center-paragraph))
-
+;;;###autoload
(defun llvm-mode ()
"Major mode for editing LLVM source files.
- \\{llvm-mode-map}
- Runs llvm-mode-hook on startup."
+\\{llvm-mode-map}
+ Runs `llvm-mode-hook' on startup."
(interactive)
(kill-all-local-variables)
(use-local-map llvm-mode-map) ; Provides the local keymap.
@@ -136,8 +136,9 @@
; customize the mode with a hook.
;; Associate .ll files with llvm-mode
-(setq auto-mode-alist
- (append '(("\\.ll$" . llvm-mode)) auto-mode-alist))
+;;;###autoload
+(add-to-list 'auto-mode-alist (cons (purecopy "\\.ll\\'") 'llvm-mode))
(provide 'llvm-mode)
-;; end of llvm-mode.el
+
+;;; llvm-mode.el ends here
diff --git a/utils/emacs/tablegen-mode.el b/utils/emacs/tablegen-mode.el
index c0ae751..035455d 100644
--- a/utils/emacs/tablegen-mode.el
+++ b/utils/emacs/tablegen-mode.el
@@ -1,12 +1,17 @@
+;;; tablegen-mode.el --- Major mode for TableGen description files (part of LLVM project)
+
;; Maintainer: The LLVM team, http://llvm.org/
-;; Description: Major mode for TableGen description files (part of LLVM project)
-;; Updated: 2007-12-18
+
+;;; Commentary:
+;; A major mode for TableGen description files in LLVM.
(require 'comint)
(require 'custom)
(require 'ansi-color)
;; Create mode-specific tables.
+;;; Code:
+
(defvar td-decorators-face 'td-decorators-face
"Face method decorators.")
(make-face 'td-decorators-face)
@@ -93,10 +98,11 @@
(define-key tablegen-mode-map "\es" 'center-line)
(define-key tablegen-mode-map "\eS" 'center-paragraph))
+;;;###autoload
(defun tablegen-mode ()
"Major mode for editing TableGen description files.
- \\{tablegen-mode-map}
- Runs tablegen-mode-hook on startup."
+\\{tablegen-mode-map}
+ Runs `tablegen-mode-hook' on startup."
(interactive)
(kill-all-local-variables)
(use-local-map tablegen-mode-map) ; Provides the local keymap.
@@ -117,7 +123,9 @@
; customize the mode with a hook.
;; Associate .td files with tablegen-mode
-(setq auto-mode-alist (append '(("\\.td$" . tablegen-mode)) auto-mode-alist))
+;;;###autoload
+(add-to-list 'auto-mode-alist (cons (purecopy "\\.td\\'") 'tablegen-mode))
(provide 'tablegen-mode)
-;; end of tablegen-mode.el
+
+;;; tablegen-mode.el ends here
diff --git a/utils/lit/lit/LitConfig.py b/utils/lit/lit/LitConfig.py
index b0dde5d..b818380 100644
--- a/utils/lit/lit/LitConfig.py
+++ b/utils/lit/lit/LitConfig.py
@@ -76,7 +76,6 @@ class LitConfig:
self.bashPath = lit.util.which('bash')
if self.bashPath is None:
- self.warning("Unable to find 'bash'.")
self.bashPath = ''
return self.bashPath
@@ -91,7 +90,6 @@ class LitConfig:
# bash
self.bashPath = lit.util.which('bash', dir)
if self.bashPath is None:
- self.note("Unable to find 'bash.exe'.")
self.bashPath = ''
return dir
diff --git a/utils/lit/lit/Test.py b/utils/lit/lit/Test.py
index b810230..682d04f 100644
--- a/utils/lit/lit/Test.py
+++ b/utils/lit/lit/Test.py
@@ -91,7 +91,8 @@ class JSONMetricValue(MetricValue):
self.value = value
def format(self):
- return str(self.value)
+ e = JSONEncoder(indent=2, sort_keys=True)
+ return e.encode(self.value)
def todata(self):
return self.value
@@ -252,4 +253,4 @@ class Test:
xml += "\n\t</failure>\n</testcase>"
else:
xml += "/>"
- return xml \ No newline at end of file
+ return xml
diff --git a/utils/lit/lit/TestingConfig.py b/utils/lit/lit/TestingConfig.py
index 52cebbf..c7ef94d 100644
--- a/utils/lit/lit/TestingConfig.py
+++ b/utils/lit/lit/TestingConfig.py
@@ -26,7 +26,11 @@ class TestingConfig:
'LD_PRELOAD', 'ASAN_OPTIONS', 'UBSAN_OPTIONS',
'LSAN_OPTIONS']
for var in pass_vars:
- environment[var] = os.environ.get(var, '')
+ val = os.environ.get(var, '')
+ # Check for empty string as some variables such as LD_PRELOAD cannot be empty
+ # ('') for OS's such as OpenBSD.
+ if val:
+ environment[var] = val
if sys.platform == 'win32':
environment.update({
diff --git a/utils/lit/lit/formats/googletest.py b/utils/lit/lit/formats/googletest.py
index 1b5b785..59ac3c5 100644
--- a/utils/lit/lit/formats/googletest.py
+++ b/utils/lit/lit/formats/googletest.py
@@ -31,7 +31,6 @@ class GoogleTest(TestFormat):
try:
lines = lit.util.capture([path, '--gtest_list_tests'],
env=localConfig.environment)
- lines = lines.decode('utf-8')
if kIsWindows:
lines = lines.replace('\r', '')
lines = lines.split('\n')
diff --git a/utils/lit/lit/util.py b/utils/lit/lit/util.py
index ca1aeb6..08f7b71 100644
--- a/utils/lit/lit/util.py
+++ b/utils/lit/lit/util.py
@@ -16,6 +16,12 @@ def to_string(bytes):
return bytes
return to_bytes(bytes)
+def convert_string(bytes):
+ try:
+ return to_string(bytes.decode('utf-8'))
+ except UnicodeError:
+ return str(bytes)
+
def detectCPUs():
"""
Detects the number of CPUs on a system. Cribbed from pp.
@@ -60,7 +66,7 @@ def capture(args, env=None):
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=env)
out,_ = p.communicate()
- return out
+ return convert_string(out)
def which(command, paths = None):
"""which(command, [paths]) - Look up the given command in the paths string
@@ -166,14 +172,8 @@ def executeCommand(command, cwd=None, env=None):
raise KeyboardInterrupt
# Ensure the resulting output is always of string type.
- try:
- out = to_string(out.decode('utf-8'))
- except:
- out = str(out)
- try:
- err = to_string(err.decode('utf-8'))
- except:
- err = str(err)
+ out = convert_string(out)
+ err = convert_string(err)
return out, err, exitCode
diff --git a/utils/lit/utils/check-coverage b/utils/lit/utils/check-coverage
index 128e827..cded7a2 100755
--- a/utils/lit/utils/check-coverage
+++ b/utils/lit/utils/check-coverage
@@ -23,7 +23,7 @@ fi
# sitecustomize.
if ! python -c \
'import sitecustomize, sys; sys.exit("coverage" not in dir(sitecustomize))' \
- &> /dev/null; then
+ >/dev/null 2>&1; then
printf 1>&2 "error: active python does not appear to enable coverage in its 'sitecustomize.py'\n"
exit 1
fi
diff --git a/utils/lldbDataFormatters.py b/utils/lldbDataFormatters.py
index f570fb4..687729f 100644
--- a/utils/lldbDataFormatters.py
+++ b/utils/lldbDataFormatters.py
@@ -15,6 +15,9 @@ def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand('type synthetic add -w llvm '
'-l lldbDataFormatters.ArrayRefSynthProvider '
'-x "^llvm::ArrayRef<.+>$"')
+ debugger.HandleCommand('type summary add -w llvm '
+ '-F lldbDataFormatters.OptionalSummaryProvider '
+ '-x "^llvm::Optional<.+>$"')
# Pretty printer for llvm::SmallVector/llvm::SmallVectorImpl
class SmallVectorSynthProvider:
@@ -86,3 +89,10 @@ class ArrayRefSynthProvider:
self.data_type = self.data.GetType().GetPointeeType()
self.type_size = self.data_type.GetByteSize()
assert self.type_size != 0
+
+def OptionalSummaryProvider(valobj, internal_dict):
+ if not valobj.GetChildMemberWithName('hasVal').GetValueAsUnsigned(0):
+ return 'None'
+ underlying_type = valobj.GetType().GetTemplateArgumentType(0)
+ storage = valobj.GetChildMemberWithName('storage')
+ return str(storage.Cast(underlying_type))
diff --git a/utils/not/not.cpp b/utils/not/not.cpp
index 2adeded..23062fb 100644
--- a/utils/not/not.cpp
+++ b/utils/not/not.cpp
@@ -6,6 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+// Usage:
+// not cmd
+// Will return true if cmd doesn't crash and returns false.
+// not --crash cmd
+// Will return true if cmd crashes (e.g. for testing crash reporting).
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
diff --git a/utils/release/merge.sh b/utils/release/merge.sh
index 2cf39b2..949c298 100755
--- a/utils/release/merge.sh
+++ b/utils/release/merge.sh
@@ -66,9 +66,11 @@ svn log -c $rev http://llvm.org/svn/llvm-project/$proj/trunk >> $tempfile 2>&1
cd $proj.src
echo "# Updating tree"
svn up
-echo "# Merging r$rev into $proj"
+echo "# Merging r$rev into $proj locally"
svn merge -c $rev https://llvm.org/svn/llvm-project/$proj/trunk . || exit 1
-echo "# Committing changes"
-svn commit -F $tempfile || exit 1
-rm -f $tempfile
+
+echo
+echo "# To commit the merge, run the following in $proj.src/:"
+echo svn commit -F $tempfile
+
exit 0
diff --git a/utils/release/tag.sh b/utils/release/tag.sh
index 390acaf..503413b 100755
--- a/utils/release/tag.sh
+++ b/utils/release/tag.sh
@@ -18,17 +18,21 @@ release=""
rc=""
rebranch="no"
projects="llvm cfe dragonegg test-suite compiler-rt libcxx libcxxabi clang-tools-extra polly lldb lld openmp"
+dryrun=""
+revision="HEAD"
base_url="https://llvm.org/svn/llvm-project"
function usage() {
- echo "usage: `basename $0` -release <num> [-rebranch]"
- echo "usage: `basename $0` -release <num> -rc <num>"
+ echo "usage: `basename $0` -release <num> [-rebranch] [-revision <num>] [-dry-run]"
+ echo "usage: `basename $0` -release <num> -rc <num> [-dry-run]"
echo " "
- echo " -release <num> The version number of the release"
- echo " -rc <num> The release candidate number"
- echo " -rebranch Remove existing branch, if present, before branching"
- echo " -final Tag final release candidate"
+ echo " -release <num> The version number of the release"
+ echo " -rc <num> The release candidate number"
+ echo " -rebranch Remove existing branch, if present, before branching"
+ echo " -final Tag final release candidate"
+ echo " -revision <num> Revision to branch off (default: HEAD)"
+ echo " -dry-run Make no changes to the repository, just print the commands"
}
function tag_version() {
@@ -38,10 +42,11 @@ function tag_version() {
if [ $rebranch = "no" ]; then
continue
fi
- svn remove -m "Removing old release_$branch_release branch for rebranching." \
+ ${dryrun} svn remove -m "Removing old release_$branch_release branch for rebranching." \
$base_url/$proj/branches/release_$branch_release
fi
- svn copy -m "Creating release_$branch_release branch" \
+ ${dryrun} svn copy -m "Creating release_$branch_release branch off revision ${revision}" \
+ -r ${revision} \
$base_url/$proj/trunk \
$base_url/$proj/branches/release_$branch_release
done
@@ -52,10 +57,10 @@ function tag_release_candidate() {
set -x
for proj in $projects ; do
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
+ ${dryrun} 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_$tag_release/$rc > /dev/null 2>&1 ; then
- svn copy -m "Creating release candidate $rc from release_$tag_release branch" \
+ ${dryrun} 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
@@ -79,6 +84,13 @@ while [ $# -gt 0 ]; do
-final | --final )
rc="final"
;;
+ -revision | --revision )
+ shift
+ revision="$1"
+ ;;
+ -dry-run | --dry-run )
+ dryrun="echo"
+ ;;
-h | --help | -help )
usage
exit 0
@@ -105,6 +117,13 @@ tag_release=`echo $release | sed -e 's,\.,,g'`
if [ "x$rc" = "x" ]; then
tag_version
else
+ if [ "$revision" != "HEAD" ]; then
+ echo "error: cannot use -revision with -rc"
+ echo
+ usage
+ exit 1
+ fi
+
tag_release_candidate
fi
diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh
index b028924..20f8d97 100755
--- a/utils/release/test-release.sh
+++ b/utils/release/test-release.sh
@@ -39,27 +39,30 @@ do_debug="no"
do_asserts="no"
do_compare="yes"
BuildDir="`pwd`"
+BuildTriple=""
function usage() {
echo "usage: `basename $0` -release X.Y -rc NUM [OPTIONS]"
echo ""
- echo " -release X.Y The release number to test."
- echo " -rc NUM The pre-release candidate number."
- echo " -final The final release candidate."
- echo " -triple TRIPLE The target triple for this machine."
- echo " -j NUM Number of compile jobs to run. [default: 3]"
- echo " -build-dir DIR Directory to perform testing in. [default: pwd]"
- echo " -no-checkout Don't checkout the sources from SVN."
- echo " -no-64bit Don't test the 64-bit version. [default: yes]"
- echo " -enable-ada Build Ada. [default: disable]"
- echo " -disable-clang Do not test clang. [default: enable]"
- echo " -enable-dragonegg Test dragonegg. [default: disable]"
- echo " -enable-fortran Enable Fortran build. [default: disable]"
- echo " -disable-objc Disable ObjC build. [default: enable]"
- echo " -test-debug Test the debug build. [default: no]"
- echo " -test-asserts Test with asserts on. [default: no]"
- echo " -no-compare-files Don't test that phase 2 and 3 files are identical."
- echo " -use-gzip Use gzip instead of xz."
+ echo " -release X.Y The release number to test."
+ echo " -rc NUM The pre-release candidate number."
+ echo " -final The final release candidate."
+ echo " -triple TRIPLE The target triple for this machine."
+ echo " -j NUM Number of compile jobs to run. [default: 3]"
+ echo " -build-dir DIR Directory to perform testing in. [default: pwd]"
+ echo " -no-checkout Don't checkout the sources from SVN."
+ echo " -no-64bit Don't test the 64-bit version. [default: yes]"
+ echo " -enable-ada Build Ada. [default: disable]"
+ echo " -disable-clang Do not test clang. [default: enable]"
+ echo " -enable-dragonegg Test dragonegg. [default: disable]"
+ echo " -enable-fortran Enable Fortran build. [default: disable]"
+ echo " -disable-objc Disable ObjC build. [default: enable]"
+ echo " -test-debug Test the debug build. [default: no]"
+ echo " -test-asserts Test with asserts on. [default: no]"
+ echo " -no-compare-files Don't test that phase 2 and 3 files are identical."
+ echo " -use-gzip Use gzip instead of xz."
+ echo " -build-triple TRIPLE The build triple for this machine"
+ echo " [default: use config.guess]"
}
while [ $# -gt 0 ]; do
@@ -80,6 +83,10 @@ while [ $# -gt 0 ]; do
shift
Triple="$1"
;;
+ -build-triple | --build-triple )
+ shift
+ BuildTriple="$1"
+ ;;
-j* )
NumJobs="`echo $1 | sed -e 's,-j\([0-9]*\),\1,g'`"
if [ -z "$NumJobs" ]; then
@@ -295,16 +302,21 @@ function configure_llvmCore() {
echo "# Using C compiler: $c_compiler"
echo "# Using C++ compiler: $cxx_compiler"
+ build_triple_option="${BuildTriple:+--build=$BuildTriple}"
+
cd $ObjDir
echo "# Configuring llvm $Release-$RC $Flavor"
echo "# $BuildDir/llvm.src/configure --prefix=$InstallDir \
--enable-optimized=$Optimized \
- --enable-assertions=$Assertions"
+ --enable-assertions=$Assertions \
+ --disable-timestamps \
+ $build_triple_option"
env CC="$c_compiler" CXX="$cxx_compiler" \
$BuildDir/llvm.src/configure --prefix=$InstallDir \
--enable-optimized=$Optimized \
--enable-assertions=$Assertions \
--disable-timestamps \
+ $build_triple_option \
2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log
cd $BuildDir
}
diff --git a/utils/shuffle_fuzz.py b/utils/shuffle_fuzz.py
index 384a93a..985d1da 100755
--- a/utils/shuffle_fuzz.py
+++ b/utils/shuffle_fuzz.py
@@ -173,7 +173,7 @@ entry:""" % dict(subst,
# Generate some string constants that we can use to report errors.
for i, r in enumerate(result):
if r != -1:
- s = ('FAIL(%(seed)s): lane %(lane)d, expected %(result)d, found %%d\\0A' %
+ s = ('FAIL(%(seed)s): lane %(lane)d, expected %(result)d, found %%d\n\\0A' %
{'seed': args.seed, 'lane': i, 'result': r})
s += ''.join(['\\00' for _ in itertools.repeat(None, 128 - len(s) + 2)])
print """
@@ -235,8 +235,7 @@ die.%(i)d:
%%bad.%(i)d = trunc i2048 %%tmp.%(i)d to i32
call i32 (i8*, i8*, ...)* @sprintf(i8* %%str.ptr, i8* getelementptr inbounds ([128 x i8]* @error.%(i)d, i32 0, i32 0), i32 %%bad.%(i)d)
%%length.%(i)d = call i32 @strlen(i8* %%str.ptr)
- %%size.%(i)d = add i32 %%length.%(i)d, 1
- call i32 @write(i32 2, i8* %%str.ptr, i32 %%size.%(i)d)
+ call i32 @write(i32 2, i8* %%str.ptr, i32 %%length.%(i)d)
call void @llvm.trap()
unreachable
""" % dict(subst, i=i, next_i=i + 1, r=r)
diff --git a/utils/unittest/CMakeLists.txt b/utils/unittest/CMakeLists.txt
index b6d2d6d..b34e22a 100644
--- a/utils/unittest/CMakeLists.txt
+++ b/utils/unittest/CMakeLists.txt
@@ -32,17 +32,20 @@ if (NOT LLVM_ENABLE_THREADS)
add_definitions( -DGTEST_HAS_PTHREAD=0 )
endif()
-# Visual Studio 2012 only supports up to 8 template parameters in
-# std::tr1::tuple by default, but gtest requires 10
-if(MSVC AND MSVC_VERSION EQUAL 1700)
- add_definitions(-D_VARIADIC_MAX=10)
-endif ()
+set(LIBS
+ LLVMSupport # Depends on llvm::raw_ostream
+)
+
+find_library(PTHREAD_LIBRARY_PATH pthread)
+if (PTHREAD_LIBRARY_PATH)
+ list(APPEND LIBS pthread)
+endif()
add_llvm_library(gtest
googletest/src/gtest-all.cc
LINK_LIBS
- LLVMSupport # Depends on llvm::raw_ostream
- )
+ ${LIBS}
+)
add_subdirectory(UnitTestMain)
diff --git a/utils/update_llc_test_checks.py b/utils/update_llc_test_checks.py
new file mode 100755
index 0000000..df01d89
--- /dev/null
+++ b/utils/update_llc_test_checks.py
@@ -0,0 +1,213 @@
+#!/usr/bin/env python2.7
+
+"""A test case update script.
+
+This script is a utility to update LLVM X86 'llc' based test cases with new
+FileCheck patterns. It can either update all of the tests in the file or
+a single test function.
+"""
+
+import argparse
+import itertools
+import string
+import subprocess
+import sys
+import tempfile
+import re
+
+
+def llc(args, cmd_args, ir):
+ with open(ir) as ir_file:
+ stdout = subprocess.check_output(args.llc_binary + ' ' + cmd_args,
+ shell=True, stdin=ir_file)
+ return stdout
+
+
+ASM_SCRUB_WHITESPACE_RE = re.compile(r'(?!^(| \w))[ \t]+', flags=re.M)
+ASM_SCRUB_TRAILING_WHITESPACE_RE = re.compile(r'[ \t]+$', flags=re.M)
+ASM_SCRUB_SHUFFLES_RE = (
+ re.compile(
+ r'^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem) = .*)$',
+ flags=re.M))
+ASM_SCRUB_SP_RE = re.compile(r'\d+\(%(esp|rsp)\)')
+ASM_SCRUB_RIP_RE = re.compile(r'[.\w]+\(%rip\)')
+ASM_SCRUB_KILL_COMMENT_RE = re.compile(r'^ *#+ +kill:.*\n')
+
+
+def scrub_asm(asm):
+ # Scrub runs of whitespace out of the assembly, but leave the leading
+ # whitespace in place.
+ asm = ASM_SCRUB_WHITESPACE_RE.sub(r' ', asm)
+ # Expand the tabs used for indentation.
+ asm = string.expandtabs(asm, 2)
+ # Detect shuffle asm comments and hide the operands in favor of the comments.
+ asm = ASM_SCRUB_SHUFFLES_RE.sub(r'\1 {{.*#+}} \2', asm)
+ # Generically match the stack offset of a memory operand.
+ asm = ASM_SCRUB_SP_RE.sub(r'{{[0-9]+}}(%\1)', asm)
+ # Generically match a RIP-relative memory operand.
+ asm = ASM_SCRUB_RIP_RE.sub(r'{{.*}}(%rip)', asm)
+ # Strip kill operands inserted into the asm.
+ asm = ASM_SCRUB_KILL_COMMENT_RE.sub('', asm)
+ # Strip trailing whitespace.
+ asm = ASM_SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
+ return asm
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('-v', '--verbose', action='store_true',
+ help='Show verbose output')
+ parser.add_argument('--llc-binary', default='llc',
+ help='The "llc" binary to use to generate the test case')
+ parser.add_argument(
+ '--function', help='The function in the test file to update')
+ parser.add_argument('tests', nargs='+')
+ args = parser.parse_args()
+
+ run_line_re = re.compile('^\s*;\s*RUN:\s*(.*)$')
+ ir_function_re = re.compile('^\s*define\s+(?:internal\s+)?[^@]*@(\w+)\s*\(')
+ asm_function_re = re.compile(
+ r'^_?(?P<f>[^:]+):[ \t]*#+[ \t]*@(?P=f)\n[^:]*?'
+ r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
+ r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section)',
+ flags=(re.M | re.S))
+ check_prefix_re = re.compile('--check-prefix=(\S+)')
+ check_re = re.compile(r'^\s*;\s*([^:]+?)(?:-NEXT|-NOT|-DAG|-LABEL)?:')
+
+ for test in args.tests:
+ if args.verbose:
+ print >>sys.stderr, 'Scanning for RUN lines in test file: %s' % (test,)
+ with open(test) as f:
+ test_lines = [l.rstrip() for l in f]
+
+ run_lines = [m.group(1)
+ for m in [run_line_re.match(l) for l in test_lines] if m]
+ if args.verbose:
+ print >>sys.stderr, 'Found %d RUN lines:' % (len(run_lines),)
+ for l in run_lines:
+ print >>sys.stderr, ' RUN: ' + l
+
+ checks = []
+ for l in run_lines:
+ (llc_cmd, filecheck_cmd) = tuple([cmd.strip() for cmd in l.split('|', 1)])
+ if not llc_cmd.startswith('llc '):
+ print >>sys.stderr, 'WARNING: Skipping non-llc RUN line: ' + l
+ continue
+
+ if not filecheck_cmd.startswith('FileCheck '):
+ print >>sys.stderr, 'WARNING: Skipping non-FileChecked RUN line: ' + l
+ continue
+
+ llc_cmd_args = llc_cmd[len('llc'):].strip()
+ llc_cmd_args = llc_cmd_args.replace('< %s', '').replace('%s', '').strip()
+
+ check_prefixes = [m.group(1)
+ for m in check_prefix_re.finditer(filecheck_cmd)]
+ if not check_prefixes:
+ check_prefixes = ['CHECK']
+
+ # FIXME: We should use multiple check prefixes to common check lines. For
+ # now, we just ignore all but the last.
+ checks.append((check_prefixes, llc_cmd_args))
+
+ asm = {}
+ for prefixes, _ in checks:
+ for prefix in prefixes:
+ asm.update({prefix: dict()})
+ for prefixes, llc_args in checks:
+ if args.verbose:
+ print >>sys.stderr, 'Extracted LLC cmd: llc ' + llc_args
+ print >>sys.stderr, 'Extracted FileCheck prefixes: ' + str(prefixes)
+ raw_asm = llc(args, llc_args, test)
+ # Build up a dictionary of all the function bodies.
+ for m in asm_function_re.finditer(raw_asm):
+ if not m:
+ continue
+ f = m.group('f')
+ f_asm = scrub_asm(m.group('body'))
+ if f.startswith('stress'):
+ # We only use the last line of the asm for stress tests.
+ f_asm = '\n'.join(f_asm.splitlines()[-1:])
+ if args.verbose:
+ print >>sys.stderr, 'Processing asm for function: ' + f
+ for l in f_asm.splitlines():
+ print >>sys.stderr, ' ' + l
+ for prefix in prefixes:
+ if f in asm[prefix] and asm[prefix][f] != f_asm:
+ if prefix == prefixes[-1]:
+ print >>sys.stderr, ('WARNING: Found conflicting asm under the '
+ 'same prefix!')
+ else:
+ asm[prefix][f] = None
+ continue
+
+ asm[prefix][f] = f_asm
+
+ is_in_function = False
+ is_in_function_start = False
+ prefix_set = set([prefix for prefixes, _ in checks for prefix in prefixes])
+ if args.verbose:
+ print >>sys.stderr, 'Rewriting FileCheck prefixes: %s' % (prefix_set,)
+ fixed_lines = []
+ for l in test_lines:
+ if is_in_function_start:
+ if l.lstrip().startswith(';'):
+ m = check_re.match(l)
+ if not m or m.group(1) not in prefix_set:
+ fixed_lines.append(l)
+ continue
+
+ # Print out the various check lines here
+ printed_prefixes = []
+ for prefixes, _ in checks:
+ for prefix in prefixes:
+ if prefix in printed_prefixes:
+ break
+ if not asm[prefix][name]:
+ continue
+ if len(printed_prefixes) != 0:
+ fixed_lines.append(';')
+ printed_prefixes.append(prefix)
+ fixed_lines.append('; %s-LABEL: %s:' % (prefix, name))
+ asm_lines = asm[prefix][name].splitlines()
+ fixed_lines.append('; %s: %s' % (prefix, asm_lines[0]))
+ for asm_line in asm_lines[1:]:
+ fixed_lines.append('; %s-NEXT: %s' % (prefix, asm_line))
+ break
+ is_in_function_start = False
+
+ if is_in_function:
+ # Skip any blank comment lines in the IR.
+ if l.strip() == ';':
+ continue
+ # And skip any CHECK lines. We'll build our own.
+ m = check_re.match(l)
+ if m and m.group(1) in prefix_set:
+ continue
+ # Collect the remaining lines in the function body and look for the end
+ # of the function.
+ fixed_lines.append(l)
+ if l.strip() == '}':
+ is_in_function = False
+ continue
+
+ fixed_lines.append(l)
+
+ m = ir_function_re.match(l)
+ if not m:
+ continue
+ name = m.group(1)
+ if args.function is not None and name != args.function:
+ # When filtering on a specific function, skip all others.
+ continue
+ is_in_function = is_in_function_start = True
+
+ if args.verbose:
+ print>>sys.stderr, 'Writing %d fixed lines to %s...' % (
+ len(fixed_lines), test)
+ with open(test, 'w') as f:
+ f.writelines([l + '\n' for l in fixed_lines])
+
+
+if __name__ == '__main__':
+ main()
diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim
index e8273dd..913d0f5 100644
--- a/utils/vim/llvm.vim
+++ b/utils/vim/llvm.vim
@@ -41,29 +41,28 @@ syn keyword llvmKeyword alignstack alwaysinline appending arm_aapcs_vfpcc
syn keyword llvmKeyword arm_aapcscc arm_apcscc asm atomic available_externally
syn keyword llvmKeyword blockaddress byval c catch cc ccc cleanup coldcc common
syn keyword llvmKeyword constant datalayout declare default define deplibs
-syn keyword llvmKeyword dllexport dllimport except extern_weak external fastcc
-syn keyword llvmKeyword filter gc global hidden initialexec inlinehint inreg
-syn keyword llvmKeyword intel_ocl_bicc inteldialect internal
-syn keyword llvmKeyword linkonce linkonce_odr
-syn keyword llvmKeyword localdynamic localexec minsize module monotonic
-syn keyword llvmKeyword msp430_intrcc naked nest noalias nocapture
-syn keyword llvmKeyword noimplicitfloat noinline nonlazybind noredzone noreturn
-syn keyword llvmKeyword nounwind optnone optsize personality private protected
-syn keyword llvmKeyword ptx_device ptx_kernel readnone readonly release
-syn keyword llvmKeyword returns_twice sanitize_thread sanitize_memory
-syn keyword llvmKeyword section seq_cst sideeffect signext singlethread
-syn keyword llvmKeyword spir_func spir_kernel sret ssp sspreq sspstrong
-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
+syn keyword llvmKeyword distinct dllexport dllimport except extern_weak external
+syn keyword llvmKeyword externally_initialized fastcc filter gc global hidden
+syn keyword llvmKeyword initialexec inlinehint inreg intel_ocl_bicc inteldialect
+syn keyword llvmKeyword internal linkonce linkonce_odr localdynamic localexec
+syn keyword llvmKeyword minsize module monotonic msp430_intrcc naked nest
+syn keyword llvmKeyword noalias nocapture noimplicitfloat noinline nonlazybind
+syn keyword llvmKeyword noredzone noreturn nounwind optnone optsize personality
+syn keyword llvmKeyword private protected ptx_device ptx_kernel readnone
+syn keyword llvmKeyword readonly release returns_twice sanitize_thread
+syn keyword llvmKeyword sanitize_memory section seq_cst sideeffect signext
+syn keyword llvmKeyword singlethread spir_func spir_kernel sret ssp sspreq
+syn keyword llvmKeyword sspstrong tail target thread_local to triple
+syn keyword llvmKeyword unnamed_addr unordered uwtable volatile weak weak_odr
+syn keyword llvmKeyword x86_fastcallcc x86_stdcallcc x86_thiscallcc
+syn keyword llvmKeyword x86_64_sysvcc x86_64_win64cc zeroext uselistorder
+syn keyword llvmKeyword uselistorder_bb
" Obsolete keywords.
syn keyword llvmError getresult begin end
" Misc syntax.
-syn match llvmNoName /[%@]\d\+\>/
+syn match llvmNoName /[%@!]\d\+\>/
syn match llvmNumber /-\?\<\d\+\>/
syn match llvmFloat /-\?\<\d\+\.\d*\(e[+-]\d\+\)\?\>/
syn match llvmFloat /\<0x\x\+\>/
@@ -74,6 +73,17 @@ syn region llvmString start=/"/ skip=/\\"/ end=/"/
syn match llvmLabel /[-a-zA-Z$._][-a-zA-Z$._0-9]*:/
syn match llvmIdentifier /[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*/
+" Named metadata and specialized metadata keywords.
+syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*$/
+syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*[=!]/
+syn match llvmType /!\zs\a\+\ze\s*(/
+syn match llvmConstant /\<DW_TAG_[a-z_]\+\>/
+syn match llvmConstant /\<DW_ATE_[a-zA-Z_]\+\>/
+syn match llvmConstant /\<DW_OP_[a-zA-Z0-9_]\+\>/
+syn match llvmConstant /\<DW_LANG_[a-zA-Z0-9_]\+\>/
+syn match llvmConstant /\<DW_VIRTUALITY_[a-z_]\+\>/
+syn match llvmConstant /\<DIFlag[A-Za-z]\+\>/
+
" Syntax-highlight dejagnu test commands.
syn match llvmSpecialComment /;\s*RUN:.*$/
syn match llvmSpecialComment /;\s*PR\d*\s*$/