summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/utils
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2017-04-02 17:24:58 +0000
committerdim <dim@FreeBSD.org>2017-04-02 17:24:58 +0000
commit60b571e49a90d38697b3aca23020d9da42fc7d7f (patch)
tree99351324c24d6cb146b6285b6caffa4d26fce188 /contrib/llvm/utils
parentbea1b22c7a9bce1dfdd73e6e5b65bc4752215180 (diff)
downloadFreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.zip
FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.tar.gz
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release:
MFC r309142 (by emaste): Add WITH_LLD_AS_LD build knob If set it installs LLD as /usr/bin/ld. LLD (as of version 3.9) is not capable of linking the world and kernel, but can self-host and link many substantial applications. GNU ld continues to be used for the world and kernel build, regardless of how this knob is set. It is on by default for arm64, and off for all other CPU architectures. Sponsored by: The FreeBSD Foundation MFC r310840: Reapply 310775, now it also builds correctly if lldb is disabled: Move llvm-objdump from CLANG_EXTRAS to installed by default We currently install three tools from binutils 2.17.50: as, ld, and objdump. Work is underway to migrate to a permissively-licensed tool-chain, with one goal being the retirement of binutils 2.17.50. LLVM's llvm-objdump is intended to be compatible with GNU objdump although it is currently missing some options and may have formatting differences. Enable it by default for testing and further investigation. It may later be changed to install as /usr/bin/objdump, it becomes a fully viable replacement. Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D8879 MFC r312855 (by emaste): Rename LLD_AS_LD to LLD_IS_LD, for consistency with CLANG_IS_CC Reported by: Dan McGregor <dan.mcgregor usask.ca> MFC r313559 | glebius | 2017-02-10 18:34:48 +0100 (Fri, 10 Feb 2017) | 5 lines Don't check struct rtentry on FreeBSD, it is an internal kernel structure. On other systems it may be API structure for SIOCADDRT/SIOCDELRT. Reviewed by: emaste, dim MFC r314152 (by jkim): Remove an assembler flag, which is redundant since r309124. The upstream took care of it by introducing a macro NO_EXEC_STACK_DIRECTIVE. http://llvm.org/viewvc/llvm-project?rev=273500&view=rev Reviewed by: dim MFC r314564: Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 (branches/release_40 296509). The release will follow soon. Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11 support to build; see UPDATING for more information. Also note that as of 4.0.0, lld should be able to link the base system on amd64 and aarch64. See the WITH_LLD_IS_LLD setting in src.conf(5). Though please be aware that this is work in progress. Release notes for llvm, clang and lld will be available here: <http://releases.llvm.org/4.0.0/docs/ReleaseNotes.html> <http://releases.llvm.org/4.0.0/tools/clang/docs/ReleaseNotes.html> <http://releases.llvm.org/4.0.0/tools/lld/docs/ReleaseNotes.html> Thanks to Ed Maste, Jan Beich, Antoine Brodin and Eric Fiselier for their help. Relnotes: yes Exp-run: antoine PR: 215969, 216008 MFC r314708: For now, revert r287232 from upstream llvm trunk (by Daniil Fukalov): [SCEV] limit recursion depth of CompareSCEVComplexity Summary: CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled loop) and runs almost infinite time. Added cache of "equal" SCEV pairs to earlier cutoff of further estimation. Recursion depth limit was also introduced as a parameter. Reviewers: sanjoy Subscribers: mzolotukhin, tstellarAMD, llvm-commits Differential Revision: https://reviews.llvm.org/D26389 This commit is the cause of excessive compile times on skein_block.c (and possibly other files) during kernel builds on amd64. We never saw the problematic behavior described in this upstream commit, so for now it is better to revert it. An upstream bug has been filed here: https://bugs.llvm.org/show_bug.cgi?id=32142 Reported by: mjg MFC r314795: Reapply r287232 from upstream llvm trunk (by Daniil Fukalov): [SCEV] limit recursion depth of CompareSCEVComplexity Summary: CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled loop) and runs almost infinite time. Added cache of "equal" SCEV pairs to earlier cutoff of further estimation. Recursion depth limit was also introduced as a parameter. Reviewers: sanjoy Subscribers: mzolotukhin, tstellarAMD, llvm-commits Differential Revision: https://reviews.llvm.org/D26389 Pull in r296992 from upstream llvm trunk (by Sanjoy Das): [SCEV] Decrease the recursion threshold for CompareValueComplexity Fixes PR32142. r287232 accidentally increased the recursion threshold for CompareValueComplexity from 2 to 32. This change reverses that change by introducing a separate flag for CompareValueComplexity's threshold. The latter revision fixes the excessive compile times for skein_block.c. MFC r314907 | mmel | 2017-03-08 12:40:27 +0100 (Wed, 08 Mar 2017) | 7 lines Unbreak ARMv6 world. The new compiler_rt library imported with clang 4.0.0 have several fatal issues (non-functional __udivsi3 for example) with ARM specific instrict functions. As temporary workaround, until upstream solve these problems, disable all thumb[1][2] related feature. MFC r315016: Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release. We were already very close to the last release candidate, so this is a pretty minor update. Relnotes: yes MFC r316005: Revert r314907, and pull in r298713 from upstream compiler-rt trunk (by Weiming Zhao): builtins: Select correct code fragments when compiling for Thumb1/Thum2/ARM ISA. Summary: Value of __ARM_ARCH_ISA_THUMB isn't based on the actual compilation mode (-mthumb, -marm), it reflect's capability of given CPU. Due to this: - use __tbumb__ and __thumb2__ insteand of __ARM_ARCH_ISA_THUMB - use '.thumb' directive consistently in all affected files - decorate all thumb functions using DEFINE_COMPILERRT_THUMB_FUNCTION() --------- Note: This patch doesn't fix broken Thumb1 variant of __udivsi3 ! Reviewers: weimingz, rengolin, compnerd Subscribers: aemerson, dim Differential Revision: https://reviews.llvm.org/D30938 Discussed with: mmel
Diffstat (limited to 'contrib/llvm/utils')
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp264
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp95
-rw-r--r--contrib/llvm/utils/TableGen/Attributes.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/CTagsEmitter.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/CodeEmitterGen.cpp87
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp147
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h5
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.cpp35
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.h1
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenIntrinsics.h27
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenMapTable.cpp1
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenRegisters.cpp119
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenRegisters.h48
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenSchedule.cpp90
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.cpp26
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.h7
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelEmitter.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp8
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp25
-rw-r--r--contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp45
-rw-r--r--contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/FastISelEmitter.cpp5
-rw-r--r--contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp192
-rw-r--r--contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp388
-rw-r--r--contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp28
-rw-r--r--contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp66
-rw-r--r--contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp4
-rw-r--r--contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp93
-rw-r--r--contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp4
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetEmitter.cpp49
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp119
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h72
-rw-r--r--contrib/llvm/utils/TableGen/TableGen.cpp7
-rw-r--r--contrib/llvm/utils/TableGen/TableGenBackends.h1
-rw-r--r--contrib/llvm/utils/TableGen/Types.cpp44
-rw-r--r--contrib/llvm/utils/TableGen/Types.h25
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp267
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.h4
38 files changed, 1599 insertions, 807 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 76228e0..1272d2b 100644
--- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -97,6 +97,9 @@
//===----------------------------------------------------------------------===//
#include "CodeGenTarget.h"
+#include "SubtargetFeatureInfo.h"
+#include "Types.h"
+#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -126,7 +129,6 @@ MatchPrefix("match-prefix", cl::init(""),
namespace {
class AsmMatcherInfo;
-struct SubtargetFeatureInfo;
// Register sets are used as keys in some second-order sets TableGen creates
// when generating its data structures. This means that the order of two
@@ -353,6 +355,7 @@ public:
std::string TokenizingCharacters;
std::string SeparatorCharacters;
std::string BreakCharacters;
+ std::string Name;
int AsmVariantNo;
};
@@ -556,20 +559,17 @@ struct MatchableInfo {
/// findAsmOperand - Find the AsmOperand with the specified name and
/// suboperand index.
int findAsmOperand(StringRef N, int SubOpIdx) const {
- auto I = std::find_if(AsmOperands.begin(), AsmOperands.end(),
- [&](const AsmOperand &Op) {
- return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx;
- });
+ auto I = find_if(AsmOperands, [&](const AsmOperand &Op) {
+ return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx;
+ });
return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
}
/// findAsmOperandNamed - Find the first AsmOperand with the specified name.
/// This does not check the suboperand index.
int findAsmOperandNamed(StringRef N) const {
- auto I = std::find_if(AsmOperands.begin(), AsmOperands.end(),
- [&](const AsmOperand &Op) {
- return Op.SrcOpName == N;
- });
+ auto I = find_if(AsmOperands,
+ [&](const AsmOperand &Op) { return Op.SrcOpName == N; });
return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
}
@@ -653,28 +653,6 @@ private:
void addAsmOperand(StringRef Token, bool IsIsolatedToken = false);
};
-/// SubtargetFeatureInfo - Helper class for storing information on a subtarget
-/// feature which participates in instruction matching.
-struct SubtargetFeatureInfo {
- /// \brief The predicate record for this feature.
- Record *TheDef;
-
- /// \brief An unique index assigned to represent this feature.
- uint64_t Index;
-
- SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {}
-
- /// \brief The name of the enumerated constant identifying this feature.
- std::string getEnumName() const {
- return "Feature_" + TheDef->getName();
- }
-
- void dump() const {
- errs() << getEnumName() << " " << Index << "\n";
- TheDef->dump();
- }
-};
-
struct OperandMatchEntry {
unsigned OperandMask;
const MatchableInfo* MI;
@@ -754,7 +732,7 @@ public:
CodeGenTarget &Target,
RecordKeeper &Records);
- /// buildInfo - Construct the various tables used during matching.
+ /// Construct the various tables used during matching.
void buildInfo();
/// buildOperandMatchInfo - Build the necessary information to handle user
@@ -774,9 +752,9 @@ public:
}
bool hasOptionalOperands() const {
- return std::find_if(Classes.begin(), Classes.end(),
- [](const ClassInfo& Class){ return Class.IsOptional; })
- != Classes.end();
+ return find_if(Classes, [](const ClassInfo &Class) {
+ return Class.IsOptional;
+ }) != Classes.end();
}
};
@@ -1311,10 +1289,10 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
if (CI->ValueName.empty()) {
CI->ClassName = Rec->getName();
- CI->Name = "MCK_" + Rec->getName();
+ CI->Name = "MCK_" + Rec->getName().str();
CI->ValueName = Rec->getName();
} else
- CI->ValueName = CI->ValueName + "," + Rec->getName();
+ CI->ValueName = CI->ValueName + "," + Rec->getName().str();
}
}
@@ -1437,21 +1415,15 @@ void AsmMatcherInfo::buildOperandMatchInfo() {
void AsmMatcherInfo::buildInfo() {
// Build information about all of the AssemblerPredicates.
- std::vector<Record*> AllPredicates =
- Records.getAllDerivedDefinitions("Predicate");
- for (Record *Pred : AllPredicates) {
- // Ignore predicates that are not intended for the assembler.
- if (!Pred->getValueAsBit("AssemblerMatcherPredicate"))
- continue;
-
- if (Pred->getName().empty())
- PrintFatalError(Pred->getLoc(), "Predicate has no name!");
-
- SubtargetFeatures.insert(std::make_pair(
- Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size())));
- DEBUG(SubtargetFeatures.find(Pred)->second.dump());
- assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!");
- }
+ const std::vector<std::pair<Record *, SubtargetFeatureInfo>>
+ &SubtargetFeaturePairs = SubtargetFeatureInfo::getAll(Records);
+ SubtargetFeatures.insert(SubtargetFeaturePairs.begin(),
+ SubtargetFeaturePairs.end());
+#ifndef NDEBUG
+ for (const auto &Pair : SubtargetFeatures)
+ DEBUG(Pair.second.dump());
+#endif // NDEBUG
+ assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!");
bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");
@@ -1471,6 +1443,7 @@ void AsmMatcherInfo::buildInfo() {
AsmVariant->getValueAsString("SeparatorCharacters");
Variant.BreakCharacters =
AsmVariant->getValueAsString("BreakCharacters");
+ Variant.Name = AsmVariant->getValueAsString("Name");
Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant");
for (const CodeGenInstruction *CGI : Target.getInstructionsByEnumValue()) {
@@ -1484,6 +1457,11 @@ void AsmMatcherInfo::buildInfo() {
if (CGI->TheDef->getValueAsBit("isCodeGenOnly"))
continue;
+ // Ignore instructions for different instructions
+ const std::string V = CGI->TheDef->getValueAsString("AsmVariantName");
+ if (!V.empty() && V != Variant.Name)
+ continue;
+
auto II = llvm::make_unique<MatchableInfo>(*CGI);
II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);
@@ -1512,6 +1490,10 @@ void AsmMatcherInfo::buildInfo() {
.startswith( MatchPrefix))
continue;
+ const std::string V = Alias->TheDef->getValueAsString("AsmVariantName");
+ if (!V.empty() && V != Variant.Name)
+ continue;
+
auto II = llvm::make_unique<MatchableInfo>(std::move(Alias));
II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);
@@ -1613,15 +1595,15 @@ void AsmMatcherInfo::buildInfo() {
// Reorder classes so that classes precede super classes.
Classes.sort();
-#ifndef NDEBUG
- // Verify that the table is now sorted
+#ifdef EXPENSIVE_CHECKS
+ // Verify that the table is sorted and operator < works transitively.
for (auto I = Classes.begin(), E = Classes.end(); I != E; ++I) {
for (auto J = I; J != E; ++J) {
assert(!(*J < *I));
assert(I == J || !J->isSubsetOf(*I));
}
}
-#endif // NDEBUG
+#endif
}
/// buildInstructionOperandReference - The specified operand is a reference to a
@@ -1814,13 +1796,13 @@ void MatchableInfo::buildAliasResultOperands() {
}
}
-static unsigned getConverterOperandID(const std::string &Name,
- SmallSetVector<std::string, 16> &Table,
- bool &IsNew) {
- IsNew = Table.insert(Name);
+static unsigned
+getConverterOperandID(const std::string &Name,
+ SmallSetVector<CachedHashString, 16> &Table,
+ bool &IsNew) {
+ IsNew = Table.insert(CachedHashString(Name));
- unsigned ID = IsNew ? Table.size() - 1 :
- std::find(Table.begin(), Table.end(), Name) - Table.begin();
+ unsigned ID = IsNew ? Table.size() - 1 : find(Table, Name) - Table.begin();
assert(ID < Table.size());
@@ -1831,13 +1813,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
std::vector<std::unique_ptr<MatchableInfo>> &Infos,
bool HasMnemonicFirst, bool HasOptionalOperands,
raw_ostream &OS) {
- SmallSetVector<std::string, 16> OperandConversionKinds;
- SmallSetVector<std::string, 16> InstructionConversionKinds;
+ SmallSetVector<CachedHashString, 16> OperandConversionKinds;
+ SmallSetVector<CachedHashString, 16> InstructionConversionKinds;
std::vector<std::vector<uint8_t> > ConversionTable;
size_t MaxRowLength = 2; // minimum is custom converter plus terminator.
// TargetOperandClass - This is the target's operand class, like X86Operand.
- std::string TargetOperandClass = Target.getName() + "Operand";
+ std::string TargetOperandClass = Target.getName().str() + "Operand";
// Write the convert function to a separate stream, so we can drop it after
// the enum. We'll build up the conversion handlers for the individual
@@ -1904,9 +1886,9 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Pre-populate the operand conversion kinds with the standard always
// available entries.
- OperandConversionKinds.insert("CVT_Done");
- OperandConversionKinds.insert("CVT_Reg");
- OperandConversionKinds.insert("CVT_Tied");
+ OperandConversionKinds.insert(CachedHashString("CVT_Done"));
+ OperandConversionKinds.insert(CachedHashString("CVT_Reg"));
+ OperandConversionKinds.insert(CachedHashString("CVT_Tied"));
enum { CVT_Done, CVT_Reg, CVT_Tied };
for (auto &II : Infos) {
@@ -1918,13 +1900,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
II->ConversionFnKind = Signature;
// Check if we have already generated this signature.
- if (!InstructionConversionKinds.insert(Signature))
+ if (!InstructionConversionKinds.insert(CachedHashString(Signature)))
continue;
// Remember this converter for the kind enum.
unsigned KindID = OperandConversionKinds.size();
- OperandConversionKinds.insert("CVT_" +
- getEnumNameForToken(AsmMatchConverter));
+ OperandConversionKinds.insert(
+ CachedHashString("CVT_" + getEnumNameForToken(AsmMatchConverter)));
// Add the converter row for this instruction.
ConversionTable.emplace_back();
@@ -2072,7 +2054,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
Reg = "0";
} else {
Reg = getQualifiedName(OpInfo.Register);
- Name = "reg" + OpInfo.Register->getName();
+ Name = "reg" + OpInfo.Register->getName().str();
}
Signature += "__" + Name;
Name = "CVT_" + Name;
@@ -2106,7 +2088,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Save the signature. If we already have it, don't add a new row
// to the table.
- if (!InstructionConversionKinds.insert(Signature))
+ if (!InstructionConversionKinds.insert(CachedHashString(Signature)))
continue;
// Add the row to the table.
@@ -2123,14 +2105,14 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Output the operand conversion kind enum.
OS << "enum OperatorConversionKind {\n";
- for (const std::string &Converter : OperandConversionKinds)
+ for (const auto &Converter : OperandConversionKinds)
OS << " " << Converter << ",\n";
OS << " CVT_NUM_CONVERTERS\n";
OS << "};\n\n";
// Output the instruction conversion kind enum.
OS << "enum InstructionConversionKind {\n";
- for (const std::string &Signature : InstructionConversionKinds)
+ for (const auto &Signature : InstructionConversionKinds)
OS << " " << Signature << ",\n";
OS << " CVT_NUM_SIGNATURES\n";
OS << "};\n\n";
@@ -2382,40 +2364,6 @@ static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser,
OS << "}\n\n";
}
-static const char *getMinimalTypeForRange(uint64_t Range) {
- assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large");
- if (Range > 0xFFFFFFFFULL)
- return "uint64_t";
- if (Range > 0xFFFF)
- return "uint32_t";
- if (Range > 0xFF)
- return "uint16_t";
- return "uint8_t";
-}
-
-static const char *getMinimalRequiredFeaturesType(const AsmMatcherInfo &Info) {
- uint64_t MaxIndex = Info.SubtargetFeatures.size();
- if (MaxIndex > 0)
- MaxIndex--;
- return getMinimalTypeForRange(1ULL << MaxIndex);
-}
-
-/// emitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag
-/// definitions.
-static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info,
- raw_ostream &OS) {
- OS << "// Flags for subtarget features that participate in "
- << "instruction matching.\n";
- OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info)
- << " {\n";
- for (const auto &SF : Info.SubtargetFeatures) {
- const SubtargetFeatureInfo &SFI = SF.second;
- OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n";
- }
- OS << " Feature_None = 0\n";
- OS << "};\n\n";
-}
-
/// emitOperandDiagnosticTypes - Emit the operand matching diagnostic types.
static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) {
// Get the set of diagnostic types from all of the operand classes.
@@ -2456,55 +2404,6 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
OS << "}\n\n";
}
-/// emitComputeAvailableFeatures - Emit the function to compute the list of
-/// available features given a subtarget.
-static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
- raw_ostream &OS) {
- std::string ClassName =
- Info.AsmParser->getValueAsString("AsmParserClassName");
-
- OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n"
- << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n";
- OS << " uint64_t Features = 0;\n";
- for (const auto &SF : Info.SubtargetFeatures) {
- const SubtargetFeatureInfo &SFI = SF.second;
-
- OS << " if (";
- std::string CondStorage =
- SFI.TheDef->getValueAsString("AssemblerCondString");
- StringRef Conds = CondStorage;
- std::pair<StringRef,StringRef> Comma = Conds.split(',');
- bool First = true;
- do {
- if (!First)
- OS << " && ";
-
- bool Neg = false;
- StringRef Cond = Comma.first;
- if (Cond[0] == '!') {
- Neg = true;
- Cond = Cond.substr(1);
- }
-
- OS << "(";
- if (Neg)
- OS << "!";
- OS << "FB[" << Info.Target.getName() << "::" << Cond << "])";
-
- if (Comma.second.empty())
- break;
-
- First = false;
- Comma = Comma.second.split(',');
- } while (true);
-
- OS << ")\n";
- OS << " Features |= " << SFI.getEnumName() << ";\n";
- }
- OS << " return Features;\n";
- OS << "}\n\n";
-}
-
static std::string GetAliasRequiredFeatures(Record *R,
const AsmMatcherInfo &Info) {
std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates");
@@ -2646,7 +2545,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit the static custom operand parsing table;
OS << "namespace {\n";
OS << " struct OperandMatchEntry {\n";
- OS << " " << getMinimalRequiredFeaturesType(Info)
+ OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size())
<< " RequiredFeatures;\n";
OS << " " << getMinimalTypeForRange(MaxMnemonicIndex)
<< " Mnemonic;\n";
@@ -2719,8 +2618,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit the operand class switch to call the correct custom parser for
// the found operand class.
- OS << Target.getName() << ClassName << "::OperandMatchResultTy "
- << Target.getName() << ClassName << "::\n"
+ OS << "OperandMatchResultTy " << Target.getName() << ClassName << "::\n"
<< "tryCustomParseOperand(OperandVector"
<< " &Operands,\n unsigned MCK) {\n\n"
<< " switch(MCK) {\n";
@@ -2741,8 +2639,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit the static custom operand parser. This code is very similar with
// the other matcher. Also use MatchResultTy here just in case we go for
// a better error handling.
- OS << Target.getName() << ClassName << "::OperandMatchResultTy "
- << Target.getName() << ClassName << "::\n"
+ OS << "OperandMatchResultTy " << Target.getName() << ClassName << "::\n"
<< "MatchOperandParserImpl(OperandVector"
<< " &Operands,\n StringRef Mnemonic) {\n";
@@ -2822,15 +2719,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
const std::unique_ptr<MatchableInfo> &b){
return *a < *b;});
-#ifndef NDEBUG
- // Verify that the table is now sorted
+#ifdef EXPENSIVE_CHECKS
+ // Verify that the table is sorted and operator < works transitively.
for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;
++I) {
for (auto J = I; J != E; ++J) {
assert(!(**J < **I));
}
}
-#endif // NDEBUG
+#endif
DEBUG_WITH_TYPE("instruction_info", {
for (const auto &MI : Info.Matchables)
@@ -2896,11 +2793,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< " unsigned VariantID = 0);\n";
if (!Info.OperandMatchInfo.empty()) {
- OS << "\n enum OperandMatchResultTy {\n";
- OS << " MatchOperand_Success, // operand matched successfully\n";
- OS << " MatchOperand_NoMatch, // operand did not match\n";
- OS << " MatchOperand_ParseFail // operand matched but had errors\n";
- OS << " };\n";
OS << " OperandMatchResultTy MatchOperandParserImpl(\n";
OS << " OperandVector &Operands,\n";
OS << " StringRef Mnemonic);\n";
@@ -2922,7 +2814,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "#undef GET_REGISTER_MATCHER\n\n";
// Emit the subtarget feature enumeration.
- emitSubtargetFeatureFlagEnumeration(Info, OS);
+ SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
+ Info.SubtargetFeatures, OS);
// Emit the function to match a register name to number.
// This should be omitted for Mips target
@@ -2967,7 +2860,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
emitValidateOperandClass(Info, OS);
// Emit the available features compute function.
- emitComputeAvailableFeatures(Info, OS);
+ SubtargetFeatureInfo::emitComputeAvailableFeatures(
+ Info.Target.getName(), ClassName, "ComputeAvailableFeatures",
+ Info.SubtargetFeatures, OS);
StringToOffsetTable StringTable;
@@ -3005,7 +2900,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " uint16_t Opcode;\n";
OS << " " << getMinimalTypeForRange(Info.Matchables.size())
<< " ConvertFn;\n";
- OS << " " << getMinimalRequiredFeaturesType(Info)
+ OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size())
<< " RequiredFeatures;\n";
OS << " " << getMinimalTypeForRange(
std::distance(Info.Classes.begin(), Info.Classes.end()))
@@ -3254,8 +3149,24 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " }\n";
OS << "\n";
OS << " Inst.clear();\n\n";
+ OS << " Inst.setOpcode(it->Opcode);\n";
+ // Verify the instruction with the target-specific match predicate function.
+ OS << " // We have a potential match but have not rendered the operands.\n"
+ << " // Check the target predicate to handle any context sensitive\n"
+ " // constraints.\n"
+ << " // For example, Ties that are referenced multiple times must be\n"
+ " // checked here to ensure the input is the same for each match\n"
+ " // constraints. If we leave it any later the ties will have been\n"
+ " // canonicalized\n"
+ << " unsigned MatchResult;\n"
+ << " if ((MatchResult = checkEarlyTargetMatchPredicate(Inst, "
+ "Operands)) != Match_Success) {\n"
+ << " Inst.clear();\n"
+ << " RetCode = MatchResult;\n"
+ << " HadMatchOtherThanPredicate = true;\n"
+ << " continue;\n"
+ << " }\n\n";
OS << " if (matchingInlineAsm) {\n";
- OS << " Inst.setOpcode(it->Opcode);\n";
OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";
OS << " return Match_Success;\n";
OS << " }\n\n";
@@ -3272,7 +3183,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Verify the instruction with the target-specific match predicate function.
OS << " // We have a potential match. Check the target predicate to\n"
<< " // handle any context sensitive constraints.\n"
- << " unsigned MatchResult;\n"
<< " if ((MatchResult = checkTargetMatchPredicate(Inst)) !="
<< " Match_Success) {\n"
<< " Inst.clear();\n"
@@ -3289,7 +3199,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (HasDeprecation) {
OS << " std::string Info;\n";
- OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n";
+ OS << " if (!getParser().getTargetParser().\n";
+ OS << " getTargetOptions().MCNoDeprecatedWarn &&\n";
+ OS << " MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n";
OS << " SMLoc Loc = ((" << Target.getName()
<< "Operand&)*Operands[0]).getStartLoc();\n";
OS << " getParser().Warning(Loc, Info, None);\n";
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
index fc2138f..a7c6104 100644
--- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -13,32 +13,53 @@
//===----------------------------------------------------------------------===//
#include "AsmWriterInst.h"
+#include "CodeGenInstruction.h"
+#include "CodeGenRegisters.h"
#include "CodeGenTarget.h"
#include "SequenceToOffsetTable.h"
+#include "Types.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <algorithm>
#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <deque>
+#include <iterator>
#include <map>
+#include <set>
+#include <string>
+#include <tuple>
#include <utility>
#include <vector>
+
using namespace llvm;
#define DEBUG_TYPE "asm-writer-emitter"
namespace {
+
class AsmWriterEmitter {
RecordKeeper &Records;
CodeGenTarget Target;
ArrayRef<const CodeGenInstruction *> NumberedInstructions;
std::vector<AsmWriterInst> Instructions;
+
public:
AsmWriterEmitter(RecordKeeper &R);
@@ -54,10 +75,11 @@ private:
std::vector<unsigned> &InstOpsUsed,
bool PassSubtarget) const;
};
+
} // end anonymous namespace
static void PrintCases(std::vector<std::pair<std::string,
- AsmWriterOperand> > &OpsToPrint, raw_ostream &O,
+ AsmWriterOperand>> &OpsToPrint, raw_ostream &O,
bool PassSubtarget) {
O << " case " << OpsToPrint.back().first << ":";
AsmWriterOperand TheOp = OpsToPrint.back().second;
@@ -76,7 +98,6 @@ static void PrintCases(std::vector<std::pair<std::string,
O << "\n break;\n";
}
-
/// EmitInstructions - Emit the last instruction in the vector and any other
/// instructions that are suitably similar to it.
static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
@@ -115,14 +136,14 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
// emit a switch for just this operand now.
O << " switch (MI->getOpcode()) {\n";
O << " default: llvm_unreachable(\"Unexpected opcode.\");\n";
- std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint;
+ std::vector<std::pair<std::string, AsmWriterOperand>> OpsToPrint;
OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace + "::" +
- FirstInst.CGI->TheDef->getName(),
+ FirstInst.CGI->TheDef->getName().str(),
FirstInst.Operands[i]));
for (const AsmWriterInst &AWI : SimilarInsts) {
- OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::"+
- AWI.CGI->TheDef->getName(),
+ OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::" +
+ AWI.CGI->TheDef->getName().str(),
AWI.Operands[i]));
}
std::reverse(OpsToPrint.begin(), OpsToPrint.end());
@@ -140,7 +161,6 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
std::vector<std::vector<unsigned>> &InstIdxs,
std::vector<unsigned> &InstOpsUsed,
bool PassSubtarget) const {
-
// This vector parallels UniqueOperandCommands, keeping track of which
// instructions each case are used for. It is a comma separated string of
// enums.
@@ -157,8 +177,7 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
// Check to see if we already have 'Command' in UniqueOperandCommands.
// If not, add it.
- auto I = std::find(UniqueOperandCommands.begin(),
- UniqueOperandCommands.end(), Command);
+ auto I = llvm::find(UniqueOperandCommands, Command);
if (I != UniqueOperandCommands.end()) {
size_t idx = I - UniqueOperandCommands.begin();
InstrsForCase[idx] += ", ";
@@ -225,7 +244,6 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
}
}
-
static void UnescapeString(std::string &Str) {
for (unsigned i = 0; i != Str.size(); ++i) {
if (Str[i] == '\\' && i != Str.size()-1) {
@@ -317,7 +335,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
std::vector<std::vector<std::string>> TableDrivenOperandPrinters;
- while (1) {
+ while (true) {
std::vector<std::string> UniqueOperandCommands;
std::vector<std::vector<unsigned>> InstIdxs;
std::vector<unsigned> NumInstOpsHandled;
@@ -451,10 +469,8 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
}
// Okay, delete instructions with no operand info left.
- auto I = std::remove_if(Instructions.begin(), Instructions.end(),
- [](AsmWriterInst &Inst) {
- return Inst.Operands.empty();
- });
+ auto I = llvm::remove_if(Instructions,
+ [](AsmWriterInst &Inst) { return Inst.Operands.empty(); });
Instructions.erase(I, Instructions.end());
@@ -480,15 +496,6 @@ 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::deque<CodeGenRegister> &Registers) {
@@ -533,7 +540,7 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
StringTable.emit(O, printChar);
O << " };\n\n";
- O << " static const " << getMinimalTypeForRange(StringTable.size()-1)
+ O << " static const " << getMinimalTypeForRange(StringTable.size() - 1, 32)
<< " RegAsmOffset" << AltName << "[] = {";
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
if ((i % 14) == 0)
@@ -595,6 +602,7 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
}
namespace {
+
// IAPrinter - Holds information about an InstAlias. Two InstAliases match if
// they both have the same conditionals. In which case, we cannot print out the
// alias for that pattern.
@@ -604,6 +612,7 @@ class IAPrinter {
std::string Result;
std::string AsmString;
+
public:
IAPrinter(std::string R, std::string AS)
: Result(std::move(R)), AsmString(std::move(AS)) {}
@@ -725,9 +734,10 @@ static unsigned CountNumOperands(StringRef AsmString, unsigned Variant) {
}
namespace {
+
struct AliasPriorityComparator {
typedef std::pair<CodeGenInstAlias, int> ValueType;
- bool operator()(const ValueType &LHS, const ValueType &RHS) {
+ bool operator()(const ValueType &LHS, const ValueType &RHS) const {
if (LHS.second == RHS.second) {
// We don't actually care about the order, but for consistency it
// shouldn't depend on pointer comparisons.
@@ -738,8 +748,8 @@ struct AliasPriorityComparator {
return LHS.second > RHS.second;
}
};
-}
+} // end anonymous namespace
void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
Record *AsmWriter = Target.getAsmWriter();
@@ -814,14 +824,14 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
NumMIOps += Operand.getMINumOperands();
std::string Cond;
- Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(NumMIOps);
+ Cond = std::string("MI->getNumOperands() == ") + utostr(NumMIOps);
IAP.addCond(Cond);
bool CantHandle = false;
unsigned MIOpNum = 0;
for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
- std::string Op = "MI->getOperand(" + llvm::utostr(MIOpNum) + ")";
+ std::string Op = "MI->getOperand(" + utostr(MIOpNum) + ")";
const CodeGenInstAlias::ResultOperand &RO = CGA.ResultOperands[i];
@@ -838,9 +848,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
Rec->isSubClassOf("Operand")) {
std::string PrintMethod = Rec->getValueAsString("PrintMethod");
if (PrintMethod != "" && PrintMethod != "printOperand") {
- PrintMethodIdx = std::find(PrintMethods.begin(),
- PrintMethods.end(), PrintMethod) -
- PrintMethods.begin();
+ PrintMethodIdx =
+ llvm::find(PrintMethods, PrintMethod) - PrintMethods.begin();
if (static_cast<unsigned>(PrintMethodIdx) == PrintMethods.size())
PrintMethods.push_back(PrintMethod);
}
@@ -856,12 +865,12 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
Record *R = CGA.ResultOperands[i].getRecord();
if (R->isSubClassOf("RegisterOperand"))
R = R->getValueAsDef("RegClass");
- Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" +
- R->getName() + "RegClassID)"
- ".contains(" + Op + ".getReg())";
+ Cond = std::string("MRI.getRegClass(") + Target.getName().str() +
+ "::" + R->getName().str() + "RegClassID).contains(" + Op +
+ ".getReg())";
} else {
Cond = Op + ".getReg() == MI->getOperand(" +
- llvm::utostr(IAP.getOpIndex(ROName)) + ").getReg()";
+ utostr(IAP.getOpIndex(ROName)) + ").getReg()";
}
} else {
// Assume all printable operands are desired for now. This can be
@@ -878,8 +887,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
} else
break; // No conditions on this operand at all
}
- Cond = Target.getName() + ClassName + "ValidateMCOperand(" +
- Op + ", STI, " + llvm::utostr(Entry) + ")";
+ Cond = Target.getName().str() + ClassName + "ValidateMCOperand(" +
+ Op + ", STI, " + utostr(Entry) + ")";
}
// for all subcases of ResultOperand::K_Record:
IAP.addCond(Cond);
@@ -890,8 +899,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
// MCInst will. An MCExpr could be present, for example.
IAP.addCond(Op + ".isImm()");
- Cond = Op + ".getImm() == " +
- llvm::utostr(CGA.ResultOperands[i].getImm());
+ Cond = Op + ".getImm() == " + itostr(CGA.ResultOperands[i].getImm());
IAP.addCond(Cond);
break;
}
@@ -903,8 +911,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
break;
}
- Cond = Op + ".getReg() == " + Target.getName() + "::" +
- CGA.ResultOperands[i].getRegister()->getName();
+ Cond = Op + ".getReg() == " + Target.getName().str() + "::" +
+ CGA.ResultOperands[i].getRegister()->getName().str();
IAP.addCond(Cond);
break;
}
@@ -1112,7 +1120,6 @@ void AsmWriterEmitter::run(raw_ostream &O) {
EmitPrintAliasInstruction(O);
}
-
namespace llvm {
void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS) {
@@ -1120,4 +1127,4 @@ void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS) {
AsmWriterEmitter(RK).run(OS);
}
-} // End llvm namespace
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/Attributes.cpp b/contrib/llvm/utils/TableGen/Attributes.cpp
index 58dbe57..927f6e0 100644
--- a/contrib/llvm/utils/TableGen/Attributes.cpp
+++ b/contrib/llvm/utils/TableGen/Attributes.cpp
@@ -156,7 +156,7 @@ void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
OS << "// StrBoolAttr classes\n";
for (const auto *R : Records) {
OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n";
- OS << " static const char *getKind() {\n";
+ OS << " static StringRef getKind() {\n";
OS << " return \"" << R->getValueAsString("AttrString") << "\";\n";
OS << " }\n";
OS << "};\n";
diff --git a/contrib/llvm/utils/TableGen/CTagsEmitter.cpp b/contrib/llvm/utils/TableGen/CTagsEmitter.cpp
index 35f4ad6..5213cd9 100644
--- a/contrib/llvm/utils/TableGen/CTagsEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/CTagsEmitter.cpp
@@ -37,7 +37,7 @@ public:
void emit(raw_ostream &OS) const {
const MemoryBuffer *CurMB =
SrcMgr.getMemoryBuffer(SrcMgr.FindBufferContainingLoc(Loc));
- const char *BufferName = CurMB->getBufferIdentifier();
+ auto BufferName = CurMB->getBufferIdentifier();
std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc);
OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n";
}
diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
index 400913e..f34c0de 100644
--- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
+++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -13,24 +13,35 @@
//
//===----------------------------------------------------------------------===//
+#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
+#include "SubtargetFeatureInfo.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
+#include <cassert>
+#include <cstdint>
#include <map>
+#include <set>
#include <string>
+#include <utility>
#include <vector>
+
using namespace llvm;
namespace {
class CodeEmitterGen {
RecordKeeper &Records;
+
public:
CodeEmitterGen(RecordKeeper &R) : Records(R) {}
void run(raw_ostream &o);
+
private:
int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
std::string getInstructionCase(Record *R, CodeGenTarget &Target);
@@ -173,7 +184,6 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
}
}
-
std::string CodeEmitterGen::getInstructionCase(Record *R,
CodeGenTarget &Target) {
std::string Case;
@@ -259,7 +269,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
o << " UINT64_C(0)\n };\n";
// Map to accumulate all the cases.
- std::map<std::string, std::vector<std::string> > CaseMap;
+ std::map<std::string, std::vector<std::string>> CaseMap;
// Construct all cases statement for each opcode
for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
@@ -269,7 +279,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
R->getValueAsBit("isPseudo"))
continue;
const std::string &InstName = R->getValueAsString("Namespace") + "::"
- + R->getName();
+ + R->getName().str();
std::string Case = getInstructionCase(R, Target);
CaseMap[Case].push_back(InstName);
@@ -283,7 +293,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
<< " switch (opcode) {\n";
// Emit each case statement
- std::map<std::string, std::vector<std::string> >::iterator IE, EE;
+ std::map<std::string, std::vector<std::string>>::iterator IE, EE;
for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
const std::string &Case = IE->first;
std::vector<std::string> &InstList = IE->second;
@@ -307,9 +317,72 @@ void CodeEmitterGen::run(raw_ostream &o) {
<< " }\n"
<< " return Value;\n"
<< "}\n\n";
+
+ const auto &All = SubtargetFeatureInfo::getAll(Records);
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
+ SubtargetFeatures.insert(All.begin(), All.end());
+
+ o << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n"
+ << "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n"
+ << "#include <sstream>\n\n";
+
+ // Emit the subtarget feature enumeration.
+ SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(SubtargetFeatures,
+ o);
+
+ // Emit the name table for error messages.
+ o << "#ifndef NDEBUG\n";
+ SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, o);
+ o << "#endif // NDEBUG\n";
+
+ // Emit the available features compute function.
+ SubtargetFeatureInfo::emitComputeAvailableFeatures(
+ Target.getName(), "MCCodeEmitter", "computeAvailableFeatures",
+ SubtargetFeatures, o);
+
+ // Emit the predicate verifier.
+ o << "void " << Target.getName()
+ << "MCCodeEmitter::verifyInstructionPredicates(\n"
+ << " const MCInst &Inst, uint64_t AvailableFeatures) const {\n"
+ << "#ifndef NDEBUG\n"
+ << " static uint64_t RequiredFeatures[] = {\n";
+ unsigned InstIdx = 0;
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ o << " ";
+ for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {
+ const auto &I = SubtargetFeatures.find(Predicate);
+ if (I != SubtargetFeatures.end())
+ o << I->second.getEnumName() << " | ";
+ }
+ o << "0, // " << Inst->TheDef->getName() << " = " << InstIdx << "\n";
+ InstIdx++;
+ }
+ o << " };\n\n";
+ o << " assert(Inst.getOpcode() < " << InstIdx << ");\n";
+ o << " uint64_t MissingFeatures =\n"
+ << " (AvailableFeatures & RequiredFeatures[Inst.getOpcode()]) ^\n"
+ << " RequiredFeatures[Inst.getOpcode()];\n"
+ << " if (MissingFeatures) {\n"
+ << " std::ostringstream Msg;\n"
+ << " Msg << \"Attempting to emit \" << "
+ "MCII.getName(Inst.getOpcode()).str()\n"
+ << " << \" instruction but the \";\n"
+ << " for (unsigned i = 0; i < 8 * sizeof(MissingFeatures); ++i)\n"
+ << " if (MissingFeatures & (1ULL << i))\n"
+ << " Msg << SubtargetFeatureNames[i] << \" \";\n"
+ << " Msg << \"predicate(s) are not met\";\n"
+ << " report_fatal_error(Msg.str());\n"
+ << " }\n"
+ << "#else\n"
+ << "// Silence unused variable warning on targets that don't use MCII for "
+ "other purposes (e.g. BPF).\n"
+ << "(void)MCII;\n"
+ << "#endif // NDEBUG\n";
+ o << "}\n";
+ o << "#endif\n";
}
-} // End anonymous namespace
+} // end anonymous namespace
namespace llvm {
@@ -318,4 +391,4 @@ void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS) {
CodeEmitterGen(RK).run(OS);
}
-} // End llvm namespace
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index 307a953..b82a76b 100644
--- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -108,24 +108,24 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP,
/// hasIntegerTypes - Return true if this TypeSet contains iAny or an
/// integer value type.
bool EEVT::TypeSet::hasIntegerTypes() const {
- return std::any_of(TypeVec.begin(), TypeVec.end(), isInteger);
+ return any_of(TypeVec, isInteger);
}
/// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
/// a floating point value type.
bool EEVT::TypeSet::hasFloatingPointTypes() const {
- return std::any_of(TypeVec.begin(), TypeVec.end(), isFloatingPoint);
+ return any_of(TypeVec, isFloatingPoint);
}
/// hasScalarTypes - Return true if this TypeSet contains a scalar value type.
bool EEVT::TypeSet::hasScalarTypes() const {
- return std::any_of(TypeVec.begin(), TypeVec.end(), isScalar);
+ return any_of(TypeVec, isScalar);
}
/// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector
/// value type.
bool EEVT::TypeSet::hasVectorTypes() const {
- return std::any_of(TypeVec.begin(), TypeVec.end(), isVector);
+ return any_of(TypeVec, isVector);
}
@@ -239,8 +239,7 @@ bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) {
TypeSet InputSet(*this);
// Filter out all the fp types.
- TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(),
- std::not1(std::ptr_fun(isInteger))),
+ TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isInteger))),
TypeVec.end());
if (TypeVec.empty()) {
@@ -265,8 +264,7 @@ bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) {
TypeSet InputSet(*this);
// Filter out all the integer types.
- TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(),
- std::not1(std::ptr_fun(isFloatingPoint))),
+ TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isFloatingPoint))),
TypeVec.end());
if (TypeVec.empty()) {
@@ -292,8 +290,7 @@ bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) {
TypeSet InputSet(*this);
// Filter out all the vector types.
- TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(),
- std::not1(std::ptr_fun(isScalar))),
+ TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isScalar))),
TypeVec.end());
if (TypeVec.empty()) {
@@ -317,8 +314,7 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) {
bool MadeChange = false;
// Filter out all the scalar types.
- TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(),
- std::not1(std::ptr_fun(isVector))),
+ TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isVector))),
TypeVec.end());
if (TypeVec.empty()) {
@@ -395,16 +391,15 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
A.getSizeInBits() < B.getSizeInBits());
});
- auto I = std::remove_if(Other.TypeVec.begin(), Other.TypeVec.end(),
- [Smallest](MVT OtherVT) {
- // Don't compare vector and non-vector types.
- if (OtherVT.isVector() != Smallest.isVector())
- return false;
- // The getSizeInBits() check here is only needed for vectors, but is
- // a subset of the scalar check for scalars so no need to qualify.
- return OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits()||
- OtherVT.getSizeInBits() < Smallest.getSizeInBits();
- });
+ auto I = remove_if(Other.TypeVec, [Smallest](MVT OtherVT) {
+ // Don't compare vector and non-vector types.
+ if (OtherVT.isVector() != Smallest.isVector())
+ return false;
+ // The getSizeInBits() check here is only needed for vectors, but is
+ // a subset of the scalar check for scalars so no need to qualify.
+ return OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits() ||
+ OtherVT.getSizeInBits() < Smallest.getSizeInBits();
+ });
MadeChange |= I != Other.TypeVec.end(); // If we're about to remove types.
Other.TypeVec.erase(I, Other.TypeVec.end());
@@ -428,14 +423,13 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
(A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
A.getSizeInBits() < B.getSizeInBits());
});
- auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
- [Largest](MVT OtherVT) {
- // Don't compare vector and non-vector types.
- if (OtherVT.isVector() != Largest.isVector())
- return false;
- return OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() ||
- OtherVT.getSizeInBits() > Largest.getSizeInBits();
- });
+ auto I = remove_if(TypeVec, [Largest](MVT OtherVT) {
+ // Don't compare vector and non-vector types.
+ if (OtherVT.isVector() != Largest.isVector())
+ return false;
+ return OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() ||
+ OtherVT.getSizeInBits() > Largest.getSizeInBits();
+ });
MadeChange |= I != TypeVec.end(); // If we're about to remove types.
TypeVec.erase(I, TypeVec.end());
@@ -460,10 +454,9 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT,
TypeSet InputSet(*this);
// Filter out all the types which don't have the right element type.
- auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
- [VT](MVT VVT) {
- return VVT.getVectorElementType().SimpleTy != VT;
- });
+ auto I = remove_if(TypeVec, [VT](MVT VVT) {
+ return VVT.getVectorElementType().SimpleTy != VT;
+ });
MadeChange |= I != TypeVec.end();
TypeVec.erase(I, TypeVec.end());
@@ -547,10 +540,9 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
// Only keep types that have less elements than VTOperand.
TypeSet InputSet(VTOperand);
- auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(),
- [NumElems](MVT VVT) {
- return VVT.getVectorNumElements() >= NumElems;
- });
+ auto I = remove_if(VTOperand.TypeVec, [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() >= NumElems;
+ });
MadeChange |= I != VTOperand.TypeVec.end();
VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
@@ -571,10 +563,9 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
// Only keep types that have more elements than 'this'.
TypeSet InputSet(*this);
- auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
- [NumElems](MVT VVT) {
- return VVT.getVectorNumElements() <= NumElems;
- });
+ auto I = remove_if(TypeVec, [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() <= NumElems;
+ });
MadeChange |= I != TypeVec.end();
TypeVec.erase(I, TypeVec.end());
@@ -609,10 +600,9 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand,
// Only keep types that have same elements as 'this'.
TypeSet InputSet(VTOperand);
- auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(),
- [NumElems](MVT VVT) {
- return VVT.getVectorNumElements() != NumElems;
- });
+ auto I = remove_if(VTOperand.TypeVec, [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() != NumElems;
+ });
MadeChange |= I != VTOperand.TypeVec.end();
VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
@@ -629,10 +619,9 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand,
// Only keep types that have same elements as VTOperand.
TypeSet InputSet(*this);
- auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
- [NumElems](MVT VVT) {
- return VVT.getVectorNumElements() != NumElems;
- });
+ auto I = remove_if(TypeVec, [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() != NumElems;
+ });
MadeChange |= I != TypeVec.end();
TypeVec.erase(I, TypeVec.end());
@@ -663,10 +652,8 @@ bool EEVT::TypeSet::EnforceSameSize(EEVT::TypeSet &VTOperand,
// Only keep types that have the same size as 'this'.
TypeSet InputSet(VTOperand);
- auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(),
- [&](MVT VT) {
- return VT.getSizeInBits() != Size;
- });
+ auto I = remove_if(VTOperand.TypeVec,
+ [&](MVT VT) { return VT.getSizeInBits() != Size; });
MadeChange |= I != VTOperand.TypeVec.end();
VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
@@ -683,10 +670,8 @@ bool EEVT::TypeSet::EnforceSameSize(EEVT::TypeSet &VTOperand,
// Only keep types that have the same size as VTOperand.
TypeSet InputSet(*this);
- auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
- [&](MVT VT) {
- return VT.getSizeInBits() != Size;
- });
+ auto I =
+ remove_if(TypeVec, [&](MVT VT) { return VT.getSizeInBits() != Size; });
MadeChange |= I != TypeVec.end();
TypeVec.erase(I, TypeVec.end());
@@ -770,7 +755,7 @@ bool TreePredicateFn::isAlwaysTrue() const {
/// Return the name to use in the generated code to reference this, this is
/// "Predicate_foo" if from a pattern fragment "foo".
std::string TreePredicateFn::getFnName() const {
- return "Predicate_" + PatFragRec->getRecord()->getName();
+ return "Predicate_" + PatFragRec->getRecord()->getName().str();
}
/// getCodeToRunOnSDNode - Return the code for the function body that
@@ -820,14 +805,9 @@ static unsigned getPatternSize(const TreePatternNode *P,
if (P->isLeaf() && isa<IntInit>(P->getLeafValue()))
Size += 2;
- // FIXME: This is a hack to statically increase the priority of patterns
- // which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD.
- // Later we can allow complexity / cost for each pattern to be (optionally)
- // specified. To get best possible pattern match we'll need to dynamically
- // calculate the complexity of all patterns a dag can potentially map to.
const ComplexPattern *AM = P->getComplexPatternInfo(CGP);
if (AM) {
- Size += AM->getNumOperands() * 3;
+ Size += AM->getComplexity();
// We don't want to count any children twice, so return early.
return Size;
@@ -2026,7 +2006,7 @@ bool TreePatternNode::canPatternMatch(std::string &Reason,
// Scan all of the operands of the node and make sure that only the last one
// is a constant node, unless the RHS also is.
if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) {
- bool Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id.
+ unsigned Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id.
for (unsigned i = Skip, e = getNumChildren()-1; i != e; ++i)
if (OnlyOnRHSOfCommutative(getChild(i))) {
Reason="Immediate value must be on the RHS of commutative operators!";
@@ -2092,8 +2072,8 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
/// (foo GPR, imm) -> (foo GPR, (imm))
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag"))
return ParseTreePattern(
- DagInit::get(DI, "",
- std::vector<std::pair<Init*, std::string> >()),
+ DagInit::get(DI, nullptr,
+ std::vector<std::pair<Init*, StringInit*> >()),
OpName);
// Input argument?
@@ -2147,7 +2127,8 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
if (Dag->getNumArgs() != 1)
error("Type cast only takes one operand!");
- TreePatternNode *New = ParseTreePattern(Dag->getArg(0), Dag->getArgName(0));
+ TreePatternNode *New = ParseTreePattern(Dag->getArg(0),
+ Dag->getArgNameStr(0));
// Apply the type cast.
assert(New->getNumTypes() == 1 && "FIXME: Unhandled");
@@ -2198,7 +2179,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
// Parse all the operands.
for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i)
- Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgName(i)));
+ Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgNameStr(i)));
// If the operator is an intrinsic, then this is just syntactic sugar for for
// (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and
@@ -2246,9 +2227,9 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults);
Result->setName(OpName);
- if (!Dag->getName().empty()) {
+ if (Dag->getName()) {
assert(Result->getName().empty());
- Result->setName(Dag->getName());
+ Result->setName(Dag->getNameStr());
}
return Result;
}
@@ -2504,13 +2485,14 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
if (!isa<DefInit>(OpsList->getArg(j)) ||
cast<DefInit>(OpsList->getArg(j))->getDef()->getName() != "node")
P->error("Operands list should all be 'node' values.");
- if (OpsList->getArgName(j).empty())
+ if (!OpsList->getArgName(j))
P->error("Operands list should have names for each operand!");
- if (!OperandsSet.count(OpsList->getArgName(j)))
- P->error("'" + OpsList->getArgName(j) +
+ StringRef ArgNameStr = OpsList->getArgNameStr(j);
+ if (!OperandsSet.count(ArgNameStr))
+ P->error("'" + ArgNameStr +
"' does not occur in pattern or was multiply specified!");
- OperandsSet.erase(OpsList->getArgName(j));
- Args.push_back(OpsList->getArgName(j));
+ OperandsSet.erase(ArgNameStr);
+ Args.push_back(ArgNameStr);
}
if (!OperandsSet.empty())
@@ -2562,11 +2544,11 @@ void CodeGenDAGPatterns::ParseDefaultOperands() {
// Clone the DefaultInfo dag node, changing the operator from 'ops' to
// SomeSDnode so that we can parse this.
- std::vector<std::pair<Init*, std::string> > Ops;
+ std::vector<std::pair<Init*, StringInit*> > Ops;
for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
DefaultInfo->getArgName(op)));
- DagInit *DI = DagInit::get(SomeSDNode, "", Ops);
+ DagInit *DI = DagInit::get(SomeSDNode, nullptr, Ops);
// Create a TreePattern to parse this.
TreePattern P(DefaultOps[i], DI, false, *this);
@@ -3602,10 +3584,9 @@ static void CombineChildVariants(TreePatternNode *Orig,
// (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
// which are the same pattern. Ignore the dups.
if (R->canPatternMatch(ErrString, CDP) &&
- std::none_of(OutVariants.begin(), OutVariants.end(),
- [&](TreePatternNode *Variant) {
- return R->isIsomorphicTo(Variant, DepVars);
- }))
+ none_of(OutVariants, [&](TreePatternNode *Variant) {
+ return R->isIsomorphicTo(Variant, DepVars);
+ }))
OutVariants.push_back(R.release());
// Increment indices to the next permutation by incrementing the
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
index 819c4b8..97401cd 100644
--- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
@@ -412,8 +412,7 @@ public:
}
void addPredicateFn(const TreePredicateFn &Fn) {
assert(!Fn.isAlwaysTrue() && "Empty predicate string!");
- if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) ==
- PredicateFns.end())
+ if (!is_contained(PredicateFns, Fn))
PredicateFns.push_back(Fn);
}
@@ -810,11 +809,13 @@ public:
LessRecordByID>::const_iterator pf_iterator;
pf_iterator pf_begin() const { return PatternFragments.begin(); }
pf_iterator pf_end() const { return PatternFragments.end(); }
+ iterator_range<pf_iterator> ptfs() const { return PatternFragments; }
// Patterns to match information.
typedef std::vector<PatternToMatch>::const_iterator ptm_iterator;
ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); }
ptm_iterator ptm_end() const { return PatternsToMatch.end(); }
+ iterator_range<ptm_iterator> ptms() const { return PatternsToMatch; }
/// Parse the Pattern for an instruction, and insert the result in DAGInsts.
typedef std::map<Record*, DAGInstruction, LessRecordByID> DAGInstMap;
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
index ec80236..bb2ec2a 100644
--- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -53,13 +53,13 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
OperandList.reserve(e);
for (unsigned i = 0; i != e; ++i){
Init *ArgInit;
- std::string ArgName;
+ StringRef ArgName;
if (i < NumDefs) {
ArgInit = OutDI->getArg(i);
- ArgName = OutDI->getArgName(i);
+ ArgName = OutDI->getArgNameStr(i);
} else {
ArgInit = InDI->getArg(i-NumDefs);
- ArgName = InDI->getArgName(i-NumDefs);
+ ArgName = InDI->getArgNameStr(i-NumDefs);
}
DefInit *Arg = dyn_cast<DefInit>(ArgInit);
@@ -165,7 +165,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
std::string SubOpName;
// Check to see if this is $foo.bar.
- std::string::size_type DotIdx = OpName.find_first_of(".");
+ std::string::size_type DotIdx = OpName.find_first_of('.');
if (DotIdx != std::string::npos) {
SubOpName = OpName.substr(DotIdx+1);
if (SubOpName.empty())
@@ -193,7 +193,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
// Find the operand with the right name.
for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
- if (MIOpInfo->getArgName(i) == SubOpName)
+ if (MIOpInfo->getArgNameStr(i) == SubOpName)
return std::make_pair(OpIdx, i);
// Otherwise, didn't find it!
@@ -309,6 +309,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
isSelect = R->getValueAsBit("isSelect");
isBarrier = R->getValueAsBit("isBarrier");
isCall = R->getValueAsBit("isCall");
+ isAdd = R->getValueAsBit("isAdd");
canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable");
isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
@@ -448,10 +449,10 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
if (ADI && ADI->getDef() == InstOpRec) {
// If the operand is a record, it must have a name, and the record type
// must match up with the instruction's argument type.
- if (Result->getArgName(AliasOpNo).empty())
+ if (!Result->getArgName(AliasOpNo))
PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
" must have a name!");
- ResOp = ResultOperand(Result->getArgName(AliasOpNo), ResultRecord);
+ ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ResultRecord);
return true;
}
@@ -469,7 +470,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
if (!T.getRegisterClass(InstOpRec)
.hasSubClass(&T.getRegisterClass(ADI->getDef())))
return false;
- ResOp = ResultOperand(Result->getArgName(AliasOpNo), ResultRecord);
+ ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ResultRecord);
return true;
}
@@ -491,7 +492,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
" is not a member of the " + InstOpRec->getName() +
" register class!");
- if (!Result->getArgName(AliasOpNo).empty())
+ if (Result->getArgName(AliasOpNo))
PrintFatalError(Loc, "result fixed register argument must "
"not have a name!");
@@ -520,7 +521,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
return false;
// Integer arguments can't have names.
- if (!Result->getArgName(AliasOpNo).empty())
+ if (Result->getArgName(AliasOpNo))
PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
" must not have a name!");
ResOp = ResultOperand(II->getValue());
@@ -551,7 +552,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
// MIOperandInfo perhaps?
if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type"))
return false;
- ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef());
+ ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ADI->getDef());
return true;
}
@@ -596,14 +597,14 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, unsigned Variant,
StringMap<Record*> NameClass;
for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
DefInit *ADI = dyn_cast<DefInit>(Result->getArg(i));
- if (!ADI || Result->getArgName(i).empty())
+ if (!ADI || !Result->getArgName(i))
continue;
// Verify we don't have something like: (someinst GR16:$foo, GR32:$foo)
// $foo can exist multiple times in the result list, but it must have the
// same type.
- Record *&Entry = NameClass[Result->getArgName(i)];
+ Record *&Entry = NameClass[Result->getArgNameStr(i)];
if (Entry && Entry != ADI->getDef())
- PrintFatalError(R->getLoc(), "result value $" + Result->getArgName(i) +
+ PrintFatalError(R->getLoc(), "result value $" + Result->getArgNameStr(i) +
" is both " + Entry->getName() + " and " +
ADI->getDef()->getName() + "!");
Entry = ADI->getDef();
@@ -646,9 +647,9 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, unsigned Variant,
// Take care to instantiate each of the suboperands with the correct
// nomenclature: $foo.bar
- ResultOperands.emplace_back(Result->getArgName(AliasOpNo) + "." +
- MIOI->getArgName(SubOp),
- SubRec);
+ ResultOperands.emplace_back(
+ Result->getArgName(AliasOpNo)->getAsUnquotedString() + "." +
+ MIOI->getArgName(SubOp)->getAsUnquotedString(), SubRec);
ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
}
++AliasOpNo;
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.h b/contrib/llvm/utils/TableGen/CodeGenInstruction.h
index 8e5a03d..75db17b 100644
--- a/contrib/llvm/utils/TableGen/CodeGenInstruction.h
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.h
@@ -230,6 +230,7 @@ template <typename T> class ArrayRef;
bool isSelect : 1;
bool isBarrier : 1;
bool isCall : 1;
+ bool isAdd : 1;
bool canFoldAsLoad : 1;
bool mayLoad : 1;
bool mayLoad_Unset : 1;
diff --git a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
index ea3ec67..6df0e6a 100644
--- a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
+++ b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
@@ -62,15 +62,23 @@ struct CodeGenIntrinsic {
/// accesses that may be performed by the intrinsics. Analogous to
/// \c FunctionModRefBehaviour.
enum ModRefBits {
+ /// The intrinsic may access memory that is otherwise inaccessible via
+ /// LLVM IR.
+ MR_InaccessibleMem = 1,
+
+ /// The intrinsic may access memory through pointer arguments.
+ /// LLVM IR.
+ MR_ArgMem = 2,
+
/// The intrinsic may access memory anywhere, i.e. it is not restricted
/// to access through pointer arguments.
- MR_Anywhere = 1,
+ MR_Anywhere = 4 | MR_ArgMem | MR_InaccessibleMem,
/// The intrinsic may read memory.
- MR_Ref = 2,
+ MR_Ref = 8,
/// The intrinsic may write memory.
- MR_Mod = 4,
+ MR_Mod = 16,
/// The intrinsic may both read and write memory.
MR_ModRef = MR_Ref | MR_Mod,
@@ -80,11 +88,18 @@ struct CodeGenIntrinsic {
/// properties (IntrReadMem, IntrArgMemOnly, etc.).
enum ModRefBehavior {
NoMem = 0,
- ReadArgMem = MR_Ref,
+ ReadArgMem = MR_Ref | MR_ArgMem,
+ ReadInaccessibleMem = MR_Ref | MR_InaccessibleMem,
+ ReadInaccessibleMemOrArgMem = MR_Ref | MR_ArgMem | MR_InaccessibleMem,
ReadMem = MR_Ref | MR_Anywhere,
- WriteArgMem = MR_Mod,
+ WriteArgMem = MR_Mod | MR_ArgMem,
+ WriteInaccessibleMem = MR_Mod | MR_InaccessibleMem,
+ WriteInaccessibleMemOrArgMem = MR_Mod | MR_ArgMem | MR_InaccessibleMem,
WriteMem = MR_Mod | MR_Anywhere,
- ReadWriteArgMem = MR_ModRef,
+ ReadWriteArgMem = MR_ModRef | MR_ArgMem,
+ ReadWriteInaccessibleMem = MR_ModRef | MR_InaccessibleMem,
+ ReadWriteInaccessibleMemOrArgMem = MR_ModRef | MR_ArgMem |
+ MR_InaccessibleMem,
ReadWriteMem = MR_ModRef | MR_Anywhere,
};
ModRefBehavior ModRef;
diff --git a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp
index 527f530..8032d7b 100644
--- a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp
@@ -542,6 +542,7 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {
for (unsigned j = i+1; j < FieldValues.size(); j++) {
if (CurVal == FieldValues[j]) {
FieldValues.erase(FieldValues.begin()+j);
+ --j;
}
}
}
diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
index 626144f..c03e0d1 100644
--- a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
@@ -14,13 +14,33 @@
#include "CodeGenRegisters.h"
#include "CodeGenTarget.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntEqClasses.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SparseBitVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <map>
+#include <set>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
using namespace llvm;
@@ -31,7 +51,7 @@ using namespace llvm;
//===----------------------------------------------------------------------===//
CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum)
- : TheDef(R), EnumValue(Enum), LaneMask(0), AllSuperRegsCovered(true) {
+ : TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true) {
Name = R->getName();
if (R->getValue("Namespace"))
Namespace = R->getValueAsString("Namespace");
@@ -42,7 +62,7 @@ CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum)
CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace,
unsigned Enum)
: TheDef(nullptr), Name(N), Namespace(Nspace), Size(-1), Offset(-1),
- EnumValue(Enum), LaneMask(0), AllSuperRegsCovered(true) {
+ EnumValue(Enum), AllSuperRegsCovered(true) {
}
std::string CodeGenSubRegIndex::getQualifiedName() const {
@@ -82,19 +102,19 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
}
}
-unsigned CodeGenSubRegIndex::computeLaneMask() const {
+LaneBitmask CodeGenSubRegIndex::computeLaneMask() const {
// Already computed?
- if (LaneMask)
+ if (LaneMask.any())
return LaneMask;
// Recursion guard, shouldn't be required.
- LaneMask = ~0u;
+ LaneMask = LaneBitmask::getAll();
// The lane mask is simply the union of all sub-indices.
- unsigned M = 0;
+ LaneBitmask M;
for (const auto &C : Composed)
M |= C.second->computeLaneMask();
- assert(M && "Missing lane mask, sub-register cycle?");
+ assert(M.any() && "Missing lane mask, sub-register cycle?");
LaneMask = M;
return LaneMask;
}
@@ -145,12 +165,13 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
}
}
-const std::string &CodeGenRegister::getName() const {
+const StringRef CodeGenRegister::getName() const {
assert(TheDef && "no def");
return TheDef->getName();
}
namespace {
+
// Iterate over all register units in a set of registers.
class RegUnitIterator {
CodeGenRegister::Vec::const_iterator RegI, RegE;
@@ -158,7 +179,7 @@ class RegUnitIterator {
public:
RegUnitIterator(const CodeGenRegister::Vec &Regs):
- RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() {
+ RegI(Regs.begin()), RegE(Regs.end()) {
if (RegI != RegE) {
UnitI = (*RegI)->getRegUnits().begin();
@@ -190,7 +211,8 @@ protected:
}
}
};
-} // namespace
+
+} // end anonymous namespace
// Return true of this unit appears in RegUnits.
static bool hasRegUnit(CodeGenRegister::RegUnitList &RegUnits, unsigned Unit) {
@@ -538,6 +560,7 @@ unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const {
// sub-registers. We provide a SetTheory expander class that returns the new
// registers.
namespace {
+
struct TupleExpander : SetTheory::Expander {
void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) override {
std::vector<Record*> Indices = Def->getValueAsListOfDefs("SubRegIndices");
@@ -639,7 +662,8 @@ struct TupleExpander : SetTheory::Expander {
}
}
};
-}
+
+} // end anonymous namespace
//===----------------------------------------------------------------------===//
// CodeGenRegisterClass
@@ -654,8 +678,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
: TheDef(R),
Name(R->getName()),
TopoSigs(RegBank.getNumTopoSigs()),
- EnumValue(-1),
- LaneMask(0) {
+ EnumValue(-1) {
// Rename anonymous register classes.
if (R->getName().size() > 9 && R->getName()[9] == '.') {
static unsigned AnonCounter = 0;
@@ -767,13 +790,15 @@ bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
}
namespace llvm {
+
raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
for (const auto R : *K.Members)
OS << ", " << R->getName();
return OS << " }";
}
-}
+
+} // end namespace llvm
// This is a simple lexicographical order that can be used to search for sets.
// It is not the same as the topological order provided by TopoOrderRC.
@@ -813,7 +838,7 @@ static bool TopoOrderRC(const CodeGenRegisterClass &PA,
auto *A = &PA;
auto *B = &PB;
if (A == B)
- return 0;
+ return false;
// Order by ascending spill size.
if (A->SpillSize < B->SpillSize)
@@ -1167,7 +1192,7 @@ 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;
+ CoveringLanes = LaneBitmask::getAll();
for (auto &Idx : SubRegIndices) {
if (Idx.getComposites().empty()) {
if (Bit > 32) {
@@ -1175,10 +1200,10 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
Twine("Ran out of lanemask bits to represent subregister ")
+ Idx.getName());
}
- Idx.LaneMask = 1u << Bit;
+ Idx.LaneMask = LaneBitmask(1 << Bit);
++Bit;
} else {
- Idx.LaneMask = 0;
+ Idx.LaneMask = LaneBitmask::getNone();
}
}
@@ -1197,9 +1222,12 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
// Moving from a class with no subregisters we just had a single lane:
// The subregister must be a leaf subregister and only occupies 1 bit.
// Move the bit from the class without subregisters into that position.
- unsigned DstBit = Log2_32(Idx.LaneMask);
- assert(Idx.LaneMask == 1u << DstBit && "Must be a leaf subregister");
- MaskRolPair MaskRol = { 1, (uint8_t)DstBit };
+ static_assert(sizeof(Idx.LaneMask.getAsInteger()) == 4,
+ "Change Log2_32 to a proper one");
+ unsigned DstBit = Log2_32(Idx.LaneMask.getAsInteger());
+ assert(Idx.LaneMask == LaneBitmask(1 << DstBit) &&
+ "Must be a leaf subregister");
+ MaskRolPair MaskRol = { LaneBitmask(1), (uint8_t)DstBit };
LaneTransforms.push_back(MaskRol);
} else {
// Go through all leaf subregisters and find the ones that compose with
@@ -1213,8 +1241,8 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
continue;
// Replicate the behaviour from the lane mask generation loop above.
unsigned SrcBit = NextBit;
- unsigned SrcMask = 1u << SrcBit;
- if (NextBit < 31)
+ LaneBitmask SrcMask = LaneBitmask(1 << SrcBit);
+ if (NextBit < LaneBitmask::BitWidth-1)
++NextBit;
assert(Idx2.LaneMask == SrcMask);
@@ -1227,16 +1255,19 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
assert(Composite->getComposites().empty());
// Create Mask+Rotate operation and merge with existing ops if possible.
- unsigned DstBit = Log2_32(Composite->LaneMask);
+ static_assert(sizeof(Composite->LaneMask.getAsInteger()) == 4,
+ "Change Log2_32 to a proper one");
+ unsigned DstBit = Log2_32(Composite->LaneMask.getAsInteger());
int Shift = DstBit - SrcBit;
- uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift : 32+Shift;
+ uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift
+ : LaneBitmask::BitWidth + Shift;
for (auto &I : LaneTransforms) {
if (I.RotateLeft == RotateLeft) {
I.Mask |= SrcMask;
- SrcMask = 0;
+ SrcMask = LaneBitmask::getNone();
}
}
- if (SrcMask != 0) {
+ if (SrcMask.any()) {
MaskRolPair MaskRol = { SrcMask, RotateLeft };
LaneTransforms.push_back(MaskRol);
}
@@ -1247,13 +1278,13 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
// 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;
+ LaneTransforms[0].Mask = LaneBitmask::getAll();
// 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 };
+ MaskRolPair P = { LaneBitmask::getAll(), 0 };
LaneTransforms.push_back(P);
}
}
@@ -1263,7 +1294,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
// Inherit lanes from composites.
for (const auto &Idx : SubRegIndices) {
- unsigned Mask = Idx.computeLaneMask();
+ LaneBitmask 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 (!Idx.AllSuperRegsCovered)
@@ -1272,7 +1303,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
// Compute lane mask combinations for register classes.
for (auto &RegClass : RegClasses) {
- unsigned LaneMask = 0;
+ LaneBitmask LaneMask;
for (const auto &SubRegIndex : SubRegIndices) {
if (RegClass.getSubClassWithSubReg(&SubRegIndex) == nullptr)
continue;
@@ -1281,14 +1312,15 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
// For classes without any subregisters set LaneMask to 1 instead of 0.
// This makes it easier for client code to handle classes uniformly.
- if (LaneMask == 0)
- LaneMask = 1;
+ if (LaneMask.none())
+ LaneMask = LaneBitmask(1);
RegClass.LaneMask = LaneMask;
}
}
namespace {
+
// UberRegSet is a helper class for computeRegUnitWeights. Each UberRegSet is
// the transitive closure of the union of overlapping register
// classes. Together, the UberRegSets form a partition of the registers. If we
@@ -1307,12 +1339,13 @@ namespace {
// their weight increased.
struct UberRegSet {
CodeGenRegister::Vec Regs;
- unsigned Weight;
+ unsigned Weight = 0;
CodeGenRegister::RegUnitList SingularDeterminants;
- UberRegSet(): Weight(0) {}
+ UberRegSet() = default;
};
-} // namespace
+
+} // end anonymous namespace
// Partition registers into UberRegSets, where each set is the transitive
// closure of the union of overlapping register classes.
@@ -1321,7 +1354,6 @@ struct UberRegSet {
static void computeUberSets(std::vector<UberRegSet> &UberSets,
std::vector<UberRegSet*> &RegSets,
CodeGenRegBank &RegBank) {
-
const auto &Registers = RegBank.getRegisters();
// The Register EnumValue is one greater than its index into Registers.
@@ -1756,8 +1788,7 @@ void CodeGenRegBank::computeRegUnitSets() {
std::vector<unsigned> RUSets;
for (unsigned i = 0, e = RegUnitSets.size(); i != e; ++i) {
RegUnitSet &RUSet = RegUnitSets[i];
- if (std::find(RUSet.Units.begin(), RUSet.Units.end(), UnitIdx)
- == RUSet.Units.end())
+ if (!is_contained(RUSet.Units, UnitIdx))
continue;
RUSets.push_back(i);
}
@@ -1781,7 +1812,8 @@ 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);
+ CodeGenRegister::RegUnitLaneMaskList
+ RegUnitLaneMasks(RegUnits.count(), LaneBitmask::getNone());
// Iterate through SubRegisters.
typedef CodeGenRegister::SubRegMap SubRegMap;
const SubRegMap &SubRegs = Register.getSubRegs();
@@ -1790,11 +1822,11 @@ void CodeGenRegBank::computeRegUnitLaneMasks() {
CodeGenRegister *SubReg = S->second;
// Ignore non-leaf subregisters, their lane masks are fully covered by
// the leaf subregisters anyway.
- if (SubReg->getSubRegs().size() != 0)
+ if (!SubReg->getSubRegs().empty())
continue;
CodeGenSubRegIndex *SubRegIndex = S->first;
const CodeGenRegister *SubRegister = S->second;
- unsigned LaneMask = SubRegIndex->LaneMask;
+ LaneBitmask LaneMask = SubRegIndex->LaneMask;
// Distribute LaneMask to Register Units touched.
for (unsigned SUI : SubRegister->getRegUnits()) {
bool Found = false;
@@ -2009,7 +2041,6 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
}
}
-
//
// Infer missing register classes.
//
diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h
index b8d47aa..3ed26fa 100644
--- a/contrib/llvm/utils/TableGen/CodeGenRegisters.h
+++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h
@@ -18,20 +18,29 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SparseBitVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/MC/LaneBitmask.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/SetTheory.h"
-#include <cstdlib>
+#include <cassert>
+#include <cstdint>
#include <deque>
#include <list>
#include <map>
#include <string>
+#include <utility>
#include <vector>
namespace llvm {
+
class CodeGenRegBank;
template <typename T, typename Vector, typename Set> class SetVector;
@@ -39,8 +48,9 @@ namespace llvm {
/// Mask the bits specified in Mask, then rotate them Rol bits to the left
/// assuming a wraparound at 32bits.
struct MaskRolPair {
- unsigned Mask;
+ LaneBitmask Mask;
uint8_t RotateLeft;
+
bool operator==(const MaskRolPair Other) const {
return Mask == Other.Mask && RotateLeft == Other.RotateLeft;
}
@@ -59,7 +69,7 @@ namespace llvm {
uint16_t Size;
uint16_t Offset;
const unsigned EnumValue;
- mutable unsigned LaneMask;
+ mutable LaneBitmask LaneMask;
mutable SmallVector<MaskRolPair,1> CompositionLaneMaskTransform;
// Are all super-registers containing this SubRegIndex covered by their
@@ -111,7 +121,7 @@ namespace llvm {
const CompMap &getComposites() const { return Composed; }
// Compute LaneMask from Composed. Return LaneMask.
- unsigned computeLaneMask() const;
+ LaneBitmask computeLaneMask() const;
private:
CompMap Composed;
@@ -136,7 +146,7 @@ namespace llvm {
CodeGenRegister(Record *R, unsigned Enum);
- const std::string &getName() const;
+ const StringRef getName() const;
// Extract more information from TheDef. This is used to build an object
// graph after all CodeGenRegister objects have been created.
@@ -197,7 +207,7 @@ namespace llvm {
// List of register units in ascending order.
typedef SparseBitVector<> RegUnitList;
- typedef SmallVector<unsigned, 16> RegUnitLaneMaskList;
+ typedef SmallVector<LaneBitmask, 16> RegUnitLaneMaskList;
// How many entries in RegUnitList are native?
RegUnitList NativeRegUnits;
@@ -206,7 +216,7 @@ namespace llvm {
// This is only valid after computeSubRegs() completes.
const RegUnitList &getRegUnits() const { return RegUnits; }
- ArrayRef<unsigned> getRegUnitLaneMasks() const {
+ ArrayRef<LaneBitmask> getRegUnitLaneMasks() const {
return makeArrayRef(RegUnitLaneMasks).slice(0, NativeRegUnits.count());
}
@@ -266,7 +276,7 @@ namespace llvm {
class CodeGenRegisterClass {
CodeGenRegister::Vec Members;
// Allocation orders. Order[0] always contains all registers in Members.
- std::vector<SmallVector<Record*, 16> > Orders;
+ std::vector<SmallVector<Record*, 16>> Orders;
// Bit mask of sub-classes including this, indexed by their EnumValue.
BitVector SubClasses;
// List of super-classes, topologocally ordered to have the larger classes
@@ -307,7 +317,7 @@ namespace llvm {
std::string AltOrderSelect;
uint8_t AllocationPriority;
/// Contains the combination of the lane masks of all subregisters.
- unsigned LaneMask;
+ LaneBitmask LaneMask;
/// True if there are at least 2 subregisters which do not interfere.
bool HasDisjunctSubRegs;
bool CoveredBySubRegs;
@@ -463,10 +473,10 @@ namespace llvm {
std::string Name;
std::vector<unsigned> Units;
- unsigned Weight; // Cache the sum of all unit weights.
- unsigned Order; // Cache the sort key.
+ unsigned Weight = 0; // Cache the sum of all unit weights.
+ unsigned Order = 0; // Cache the sort key.
- RegUnitSet() : Weight(0), Order(0) {}
+ RegUnitSet() = default;
};
// Base vector for identifying TopoSigs. The contents uniquely identify a
@@ -515,7 +525,7 @@ namespace llvm {
// NOTE: This could grow beyond the number of register classes when we map
// register units to lists of unit sets. If the list of unit sets does not
// already exist for a register class, we create a new entry in this vector.
- std::vector<std::vector<unsigned> > RegClassUnitSets;
+ std::vector<std::vector<unsigned>> RegClassUnitSets;
// Give each register unit set an order based on sorting criteria.
std::vector<unsigned> RegUnitSetOrder;
@@ -532,6 +542,7 @@ namespace llvm {
void computeInferredRegisterClasses();
void inferCommonSubClass(CodeGenRegisterClass *RC);
void inferSubClassWithSubReg(CodeGenRegisterClass *RC);
+
void inferMatchingSuperRegClass(CodeGenRegisterClass *RC) {
inferMatchingSuperRegClass(RC, RegClasses.begin());
}
@@ -590,6 +601,7 @@ namespace llvm {
}
const std::deque<CodeGenRegister> &getRegisters() { return Registers; }
+
const StringMap<CodeGenRegister*> &getRegistersByName() {
return RegistersByName;
}
@@ -674,6 +686,7 @@ namespace llvm {
unsigned getRegSetIDAt(unsigned Order) const {
return RegUnitSetOrder[Order];
}
+
const RegUnitSet &getRegSetAt(unsigned Order) const {
return RegUnitSets[RegUnitSetOrder[Order]];
}
@@ -721,8 +734,9 @@ namespace llvm {
// Bit mask of lanes that cover their registers. A sub-register index whose
// LaneMask is contained in CoveringLanes will be completely covered by
// another sub-register with the same or larger lane mask.
- unsigned CoveringLanes;
+ LaneBitmask CoveringLanes;
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H
diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
index d1b141e..cae1cf4 100644
--- a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
@@ -12,12 +12,21 @@
//
//===----------------------------------------------------------------------===//
+#include "CodeGenInstruction.h"
#include "CodeGenSchedule.h"
#include "CodeGenTarget.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Regex.h"
#include "llvm/TableGen/Error.h"
+#include <algorithm>
+#include <iterator>
+#include <utility>
using namespace llvm;
@@ -31,6 +40,7 @@ static void dumpIdxVec(ArrayRef<unsigned> V) {
#endif
namespace {
+
// (instrs a, b, ...) Evaluate and union all arguments. Identical to AddOp.
struct InstrsOp : public SetTheory::Operator {
void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
@@ -76,6 +86,7 @@ struct InstRegexOp : public SetTheory::Operator {
}
}
};
+
} // end anonymous namespace
/// CodeGenModels ctor interprets machine model records and populates maps.
@@ -356,8 +367,7 @@ bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const {
continue;
RecVec ValidWrites = ReadDef->getValueAsListOfDefs("ValidWrites");
- if (std::find(ValidWrites.begin(), ValidWrites.end(), WriteDef)
- != ValidWrites.end()) {
+ if (is_contained(ValidWrites, WriteDef)) {
return true;
}
}
@@ -365,6 +375,7 @@ bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const {
}
namespace llvm {
+
void splitSchedReadWrites(const RecVec &RWDefs,
RecVec &WriteDefs, RecVec &ReadDefs) {
for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); RWI != RWE; ++RWI) {
@@ -376,7 +387,8 @@ void splitSchedReadWrites(const RecVec &RWDefs,
}
}
}
-} // namespace llvm
+
+} // end namespace llvm
// Split the SchedReadWrites defs and call findRWs for each list.
void CodeGenSchedModels::findRWs(const RecVec &RWDefs,
@@ -574,11 +586,14 @@ void CodeGenSchedModels::collectSchedClasses() {
dbgs() << " " << SchedReads[*RI].Name;
dbgs() << '\n';
}
- 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 " << Inst->TheDef->getName()
- << " on processor " << PI->ModelName << '\n';
+ // If ProcIndices contains zero, the class applies to all processors.
+ if (!std::count(ProcIndices.begin(), ProcIndices.end(), 0)) {
+ 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 " << Inst->TheDef->getName()
+ << " on processor " << PI->ModelName << '\n';
+ }
}
}
}
@@ -674,7 +689,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
// intersects with an existing class via a previous InstRWDef. Instrs that do
// not intersect with an existing class refer back to their former class as
// determined from ItinDef or SchedRW.
- SmallVector<std::pair<unsigned, SmallVector<Record *, 8> >, 4> ClassInstrs;
+ SmallVector<std::pair<unsigned, SmallVector<Record *, 8>>, 4> ClassInstrs;
// Sort Instrs into sets.
const RecVec *InstDefs = Sets.expand(InstRWDef);
if (InstDefs->empty())
@@ -913,6 +928,7 @@ void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) {
}
namespace {
+
// Helper for substituteVariantOperand.
struct TransVariant {
Record *VarOrSeqDef; // Variant or sequence.
@@ -969,7 +985,8 @@ private:
std::vector<TransVariant> &IntersectingVariants);
void pushVariant(const TransVariant &VInfo, bool IsRead);
};
-} // anonymous
+
+} // end anonymous namespace
// Return true if this predicate is mutually exclusive with a PredTerm. This
// degenerates into checking if the predicate is mutually exclusive with any
@@ -982,7 +999,6 @@ private:
// conditions implicitly negate any prior condition.
bool PredTransitions::mutuallyExclusive(Record *PredDef,
ArrayRef<PredCheck> Term) {
-
for (ArrayRef<PredCheck>::iterator I = Term.begin(), E = Term.end();
I != E; ++I) {
if (I->Predicate == PredDef)
@@ -1029,7 +1045,7 @@ static bool hasVariant(ArrayRef<PredTransition> Transitions,
for (ArrayRef<PredTransition>::iterator
PTI = Transitions.begin(), PTE = Transitions.end();
PTI != PTE; ++PTI) {
- for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
WSI = PTI->WriteSequences.begin(), WSE = PTI->WriteSequences.end();
WSI != WSE; ++WSI) {
for (SmallVectorImpl<unsigned>::const_iterator
@@ -1038,7 +1054,7 @@ static bool hasVariant(ArrayRef<PredTransition> Transitions,
return true;
}
}
- for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
RSI = PTI->ReadSequences.begin(), RSE = PTI->ReadSequences.end();
RSI != RSE; ++RSI) {
for (SmallVectorImpl<unsigned>::const_iterator
@@ -1145,7 +1161,6 @@ void PredTransitions::getIntersectingVariants(
// specified by VInfo.
void PredTransitions::
pushVariant(const TransVariant &VInfo, bool IsRead) {
-
PredTransition &Trans = TransVec[VInfo.TransVecIdx];
// If this operand transition is reached through a processor-specific alias,
@@ -1168,7 +1183,7 @@ pushVariant(const TransVariant &VInfo, bool IsRead) {
const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(VInfo.RWIdx, IsRead);
- SmallVectorImpl<SmallVector<unsigned,4> > &RWSequences = IsRead
+ SmallVectorImpl<SmallVector<unsigned,4>> &RWSequences = IsRead
? Trans.ReadSequences : Trans.WriteSequences;
if (SchedRW.IsVariadic) {
unsigned OperIdx = RWSequences.size()-1;
@@ -1264,7 +1279,7 @@ void PredTransitions::substituteVariants(const PredTransition &Trans) {
TransVec.back().ProcIndices = Trans.ProcIndices;
// Visit each original write sequence.
- for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
WSI = Trans.WriteSequences.begin(), WSE = Trans.WriteSequences.end();
WSI != WSE; ++WSI) {
// Push a new (empty) write sequence onto all partial Transitions.
@@ -1275,7 +1290,7 @@ void PredTransitions::substituteVariants(const PredTransition &Trans) {
substituteVariantOperand(*WSI, /*IsRead=*/false, StartIdx);
}
// Visit each original read sequence.
- for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
RSI = Trans.ReadSequences.begin(), RSE = Trans.ReadSequences.end();
RSI != RSE; ++RSI) {
// Push a new (empty) read sequence onto all partial Transitions.
@@ -1296,7 +1311,7 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
for (ArrayRef<PredTransition>::iterator
I = LastTransitions.begin(), E = LastTransitions.end(); I != E; ++I) {
IdxVec OperWritesVariant;
- for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
WSI = I->WriteSequences.begin(), WSE = I->WriteSequences.end();
WSI != WSE; ++WSI) {
// Create a new write representing the expanded sequence.
@@ -1304,7 +1319,7 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
SchedModels.findOrInsertRW(*WSI, /*IsRead=*/false));
}
IdxVec OperReadsVariant;
- for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
RSI = I->ReadSequences.begin(), RSE = I->ReadSequences.end();
RSI != RSE; ++RSI) {
// Create a new read representing the expanded sequence.
@@ -1400,8 +1415,7 @@ bool CodeGenSchedModels::hasSuperGroup(RecVec &SubUnits, CodeGenProcModel &PM) {
PM.ProcResourceDefs[i]->getValueAsListOfDefs("Resources");
RecIter RI = SubUnits.begin(), RE = SubUnits.end();
for ( ; RI != RE; ++RI) {
- if (std::find(SuperUnits.begin(), SuperUnits.end(), *RI)
- == SuperUnits.end()) {
+ if (!is_contained(SuperUnits, *RI)) {
break;
}
}
@@ -1500,9 +1514,7 @@ void CodeGenSchedModels::collectProcResources() {
if (!(*RI)->getValueInit("SchedModel")->isComplete())
continue;
CodeGenProcModel &PM = getProcModel((*RI)->getValueAsDef("SchedModel"));
- RecIter I = std::find(PM.ProcResourceDefs.begin(),
- PM.ProcResourceDefs.end(), *RI);
- if (I == PM.ProcResourceDefs.end())
+ if (!is_contained(PM.ProcResourceDefs, *RI))
PM.ProcResourceDefs.push_back(*RI);
}
// Finalize each ProcModel by sorting the record arrays.
@@ -1568,15 +1580,14 @@ void CodeGenSchedModels::checkCompleteness() {
const CodeGenSchedClass &SC = getSchedClass(SCIdx);
if (!SC.Writes.empty())
continue;
- if (SC.ItinClassDef != nullptr)
+ if (SC.ItinClassDef != nullptr &&
+ SC.ItinClassDef->getName() != "NoItinerary")
continue;
const RecVec &InstRWs = SC.InstRWs;
- auto I = std::find_if(InstRWs.begin(), InstRWs.end(),
- [&ProcModel] (const Record *R) {
- return R->getValueAsDef("SchedModel") ==
- ProcModel.ModelDef;
- });
+ auto I = find_if(InstRWs, [&ProcModel](const Record *R) {
+ return R->getValueAsDef("SchedModel") == ProcModel.ModelDef;
+ });
if (I == InstRWs.end()) {
PrintError("'" + ProcModel.ModelName + "' lacks information for '" +
Inst->TheDef->getName() + "'");
@@ -1660,7 +1671,6 @@ void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead,
void CodeGenSchedModels::collectRWResources(ArrayRef<unsigned> Writes,
ArrayRef<unsigned> Reads,
ArrayRef<unsigned> ProcIndices) {
-
for (unsigned Idx : Writes)
collectRWResources(Idx, /*IsRead=*/false, ProcIndices);
@@ -1668,7 +1678,6 @@ void CodeGenSchedModels::collectRWResources(ArrayRef<unsigned> Writes,
collectRWResources(Idx, /*IsRead=*/true, ProcIndices);
}
-
// Find the processor's resource units for this kind of resource.
Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
const CodeGenProcModel &PM) const {
@@ -1716,13 +1725,11 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
// Iteratively add a resource and its super resources.
void CodeGenSchedModels::addProcResource(Record *ProcResKind,
CodeGenProcModel &PM) {
- for (;;) {
+ while (true) {
Record *ProcResUnits = findProcResUnits(ProcResKind, PM);
// See if this ProcResource is already associated with this processor.
- RecIter I = std::find(PM.ProcResourceDefs.begin(),
- PM.ProcResourceDefs.end(), ProcResUnits);
- if (I != PM.ProcResourceDefs.end())
+ if (is_contained(PM.ProcResourceDefs, ProcResUnits))
return;
PM.ProcResourceDefs.push_back(ProcResUnits);
@@ -1741,8 +1748,7 @@ void CodeGenSchedModels::addWriteRes(Record *ProcWriteResDef, unsigned PIdx) {
assert(PIdx && "don't add resources to an invalid Processor model");
RecVec &WRDefs = ProcModels[PIdx].WriteResDefs;
- RecIter WRI = std::find(WRDefs.begin(), WRDefs.end(), ProcWriteResDef);
- if (WRI != WRDefs.end())
+ if (is_contained(WRDefs, ProcWriteResDef))
return;
WRDefs.push_back(ProcWriteResDef);
@@ -1758,15 +1764,13 @@ void CodeGenSchedModels::addWriteRes(Record *ProcWriteResDef, unsigned PIdx) {
void CodeGenSchedModels::addReadAdvance(Record *ProcReadAdvanceDef,
unsigned PIdx) {
RecVec &RADefs = ProcModels[PIdx].ReadAdvanceDefs;
- RecIter I = std::find(RADefs.begin(), RADefs.end(), ProcReadAdvanceDef);
- if (I != RADefs.end())
+ if (is_contained(RADefs, ProcReadAdvanceDef))
return;
RADefs.push_back(ProcReadAdvanceDef);
}
unsigned CodeGenProcModel::getProcResourceIdx(Record *PRDef) const {
- RecIter PRPos = std::find(ProcResourceDefs.begin(), ProcResourceDefs.end(),
- PRDef);
+ RecIter PRPos = find(ProcResourceDefs, PRDef);
if (PRPos == ProcResourceDefs.end())
PrintFatalError(PRDef->getLoc(), "ProcResource def is not included in "
"the ProcResources list for " + ModelName);
@@ -1842,7 +1846,7 @@ void PredTransitions::dump() const {
<< ":" << PCI->Predicate->getName();
}
dbgs() << "},\n => {";
- for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
WSI = TI->WriteSequences.begin(), WSE = TI->WriteSequences.end();
WSI != WSE; ++WSI) {
dbgs() << "(";
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
index 245b9ee..6503d5a 100644
--- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -138,7 +138,7 @@ std::string llvm::getQualifiedName(const Record *R) {
if (R->getValue("Namespace"))
Namespace = R->getValueAsString("Namespace");
if (Namespace.empty()) return R->getName();
- return Namespace + "::" + R->getName();
+ return Namespace + "::" + R->getName().str();
}
@@ -157,7 +157,7 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records)
CodeGenTarget::~CodeGenTarget() {
}
-const std::string &CodeGenTarget::getName() const {
+const StringRef CodeGenTarget::getName() const {
return TargetRec->getName();
}
@@ -301,7 +301,7 @@ GetInstByName(const char *Name,
/// their enum value.
void CodeGenTarget::ComputeInstrsByEnum() const {
static const char *const FixedInstrs[] = {
-#define HANDLE_TARGET_OPCODE(OPC, NUM) #OPC,
+#define HANDLE_TARGET_OPCODE(OPC) #OPC,
#include "llvm/Target/TargetOpcodes.def"
nullptr};
const auto &Insts = getInstructions();
@@ -393,6 +393,16 @@ ComplexPattern::ComplexPattern(Record *R) {
SelectFunc = R->getValueAsString("SelectFunc");
RootNodes = R->getValueAsListOfDefs("RootNodes");
+ // FIXME: This is a hack to statically increase the priority of patterns which
+ // maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
+ // possible pattern match we'll need to dynamically calculate the complexity
+ // of all patterns a dag can potentially map to.
+ int64_t RawComplexity = R->getValueAsInt("Complexity");
+ if (RawComplexity == -1)
+ Complexity = NumOperands * 3;
+ else
+ Complexity = RawComplexity;
+
// Parse the properties.
Properties = 0;
std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
@@ -550,8 +560,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// overloaded, all the types can be specified directly.
assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
!TyEl->isSubClassOf("LLVMTruncatedType") &&
- !TyEl->isSubClassOf("LLVMVectorSameWidth") &&
- !TyEl->isSubClassOf("LLVMPointerToElt")) ||
+ !TyEl->isSubClassOf("LLVMVectorSameWidth")) ||
VT == MVT::iAny || VT == MVT::vAny) &&
"Expected iAny or vAny type");
} else
@@ -584,7 +593,12 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
else if (Property->getName() == "IntrWriteMem")
ModRef = ModRefBehavior(ModRef & ~MR_Ref);
else if (Property->getName() == "IntrArgMemOnly")
- ModRef = ModRefBehavior(ModRef & ~MR_Anywhere);
+ ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem);
+ else if (Property->getName() == "IntrInaccessibleMemOnly")
+ ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_InaccessibleMem);
+ else if (Property->getName() == "IntrInaccessibleMemOrArgMemOnly")
+ ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem |
+ MR_InaccessibleMem);
else if (Property->getName() == "Commutative")
isCommutative = true;
else if (Property->getName() == "Throws")
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h
index 85a8c1b..c822e94 100644
--- a/contrib/llvm/utils/TableGen/CodeGenTarget.h
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h
@@ -82,7 +82,7 @@ public:
~CodeGenTarget();
Record *getTargetRecord() const { return TargetRec; }
- const std::string &getName() const;
+ const StringRef getName() const;
/// getInstNamespace - Return the target-specific instruction namespace.
///
@@ -139,7 +139,7 @@ public:
/// supported by the target (i.e. there are registers that directly hold it).
bool isLegalValueType(MVT::SimpleValueType VT) const {
ArrayRef<MVT::SimpleValueType> LegalVTs = getLegalValueTypes();
- return std::find(LegalVTs.begin(), LegalVTs.end(), VT) != LegalVTs.end();
+ return is_contained(LegalVTs, VT);
}
CodeGenSchedModels &getSchedModels() const;
@@ -196,8 +196,8 @@ class ComplexPattern {
std::string SelectFunc;
std::vector<Record*> RootNodes;
unsigned Properties; // Node properties
+ unsigned Complexity;
public:
- ComplexPattern() : NumOperands(0) {}
ComplexPattern(Record *R);
MVT::SimpleValueType getValueType() const { return Ty; }
@@ -207,6 +207,7 @@ public:
return RootNodes;
}
bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
+ unsigned getComplexity() const { return Complexity; }
};
} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp
index 0fe3bbd..60fe866 100644
--- a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp
@@ -121,7 +121,7 @@ struct PatternSortingPredicate {
void DAGISelEmitter::run(raw_ostream &OS) {
emitSourceFileHeader("DAG Instruction Selector for the " +
- CGP.getTargetInfo().getName() + " target", OS);
+ CGP.getTargetInfo().getName().str() + " target", OS);
OS << "// *** NOTE: This file is #included into the middle of the target\n"
<< "// *** instruction selector class. These functions are really "
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
index 4110e97..aafc115 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
@@ -250,7 +250,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
// If we have a physreg reference like (mul gpr:$src, EAX) then we need to
// record the register
if (LeafRec->isSubClassOf("Register")) {
- AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName(),
+ AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName().str(),
NextRecordedOperandNo));
PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++));
return;
@@ -354,7 +354,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
unsigned OpNo = 0;
if (N->NodeHasProperty(SDNPHasChain, CGP)) {
// Record the node and remember it in our chained nodes list.
- AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +
+ AddMatcher(new RecordMatcher("'" + N->getOperator()->getName().str() +
"' chained node",
NextRecordedOperandNo));
// Remember all of the input chains our pattern will match.
@@ -418,7 +418,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
// TODO: This redundantly records nodes with both glues and chains.
// Record the node and remember it in our chained nodes list.
- AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +
+ AddMatcher(new RecordMatcher("'" + N->getOperator()->getName().str() +
"' glue output node",
NextRecordedOperandNo));
}
@@ -887,7 +887,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
assert((!ResultVTs.empty() || TreeHasOutGlue || NodeHasChain) &&
"Node has no result");
- AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(),
+ AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName().str(),
ResultVTs, InstOps,
NodeHasChain, TreeHasInGlue, TreeHasOutGlue,
NodeHasMemRefs, NumFixedArityOperands,
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
index ad385fa..783b35e 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -200,8 +200,15 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) {
std::unique_ptr<Matcher> Child(Scope->takeChild(i));
FactorNodes(Child);
- if (Matcher *N = Child.release())
- OptionsToMatch.push_back(N);
+ if (Child) {
+ // If the child is a ScopeMatcher we can just merge its contents.
+ if (auto *SM = dyn_cast<ScopeMatcher>(Child.get())) {
+ for (unsigned j = 0, e = SM->getNumChildren(); j != e; ++j)
+ OptionsToMatch.push_back(SM->takeChild(j));
+ } else {
+ OptionsToMatch.push_back(Child.release());
+ }
+ }
}
SmallVector<Matcher*, 32> NewOptionsToMatch;
@@ -414,9 +421,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) {
}
Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM };
- std::unique_ptr<Matcher> Case(new ScopeMatcher(Entries));
- FactorNodes(Case);
- Cases[Entry-1].second = Case.release();
+ Cases[Entry-1].second = new ScopeMatcher(Entries);
continue;
}
@@ -424,6 +429,16 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) {
Cases.push_back(std::make_pair(CTMTy, MatcherWithoutCTM));
}
+ // Make sure we recursively factor any scopes we may have created.
+ for (auto &M : Cases) {
+ if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M.second)) {
+ std::unique_ptr<Matcher> Scope(SM);
+ FactorNodes(Scope);
+ M.second = Scope.release();
+ assert(M.second && "null matcher");
+ }
+ }
+
if (Cases.size() != 1) {
MatcherPtr.reset(new SwitchTypeMatcher(Cases));
} else {
diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
index e31caaf..f879a5b 100644
--- a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -19,14 +19,18 @@
#include "CodeGenTarget.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdint>
#include <map>
+#include <set>
#include <string>
-#include <queue>
+#include <vector>
using namespace llvm;
@@ -58,6 +62,7 @@ typedef int64_t DFAStateInput;
#define DFA_TBLTYPE "int64_t" // For generating DFAStateInputTable.
namespace {
+
DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) {
return (Inp << DFA_MAX_RESOURCES) | FuncUnits;
}
@@ -67,12 +72,13 @@ namespace {
/// DFAPacketizerEmitter.cpp.
DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) {
DFAInput InsnInput = 0;
- assert ((InsnClass.size() <= DFA_MAX_RESTERMS) &&
- "Exceeded maximum number of DFA terms");
+ assert((InsnClass.size() <= DFA_MAX_RESTERMS) &&
+ "Exceeded maximum number of DFA terms");
for (auto U : InsnClass)
InsnInput = addDFAFuncUnits(InsnInput, U);
return InsnInput;
}
+
} // end anonymous namespace
// --------------------------------------------------------------------
@@ -98,6 +104,7 @@ void dbgsIndent(unsigned indent);
// for resource tracking.
//
namespace {
+
class DFAPacketizerEmitter {
private:
std::string TargetName;
@@ -150,10 +157,8 @@ public:
void run(raw_ostream &OS);
};
-} // end anonymous namespace
//
-//
// State represents the usage of machine resources if the packet contains
// a set of instruction classes.
//
@@ -174,7 +179,6 @@ public:
// A State instance also contains a collection of transitions from that state:
// a map from inputs to new states.
//
-namespace {
class State {
public:
static int currentStateNum;
@@ -204,6 +208,7 @@ class State {
//
bool canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
std::map<unsigned, unsigned> &ComboBitToBitsMap) const;
+
//
// AddInsnClass - Return all combinations of resource reservation
// which are possible from this state (PossibleStates).
@@ -214,6 +219,7 @@ class State {
void AddInsnClass(std::vector<unsigned> &InsnClass,
std::map<unsigned, unsigned> &ComboBitToBitsMap,
std::set<unsigned> &PossibleStates) const;
+
//
// AddInsnClassStages - Return all combinations of resource reservation
// resulting from the cross product of all stages for this InsnClass
@@ -225,31 +231,31 @@ class State {
unsigned prevState, unsigned origState,
DenseSet<unsigned> &VisitedResourceStates,
std::set<unsigned> &PossibleStates) const;
+
//
// addTransition - Add a transition from this state given the input InsnClass
//
void addTransition(std::vector<unsigned> InsnClass, const State *To) const;
+
//
// hasTransition - Returns true if there is a transition from this state
// given the input InsnClass
//
bool hasTransition(std::vector<unsigned> InsnClass) const;
};
-} // end anonymous namespace
//
// class DFA: deterministic finite automaton for processor resource tracking.
//
-namespace {
class DFA {
public:
- DFA();
+ DFA() = default;
// Set of states. Need to keep this sorted to emit the transition table.
typedef std::set<State> StateSet;
StateSet states;
- State *currentState;
+ State *currentState = nullptr;
//
// Modify the DFA.
@@ -263,6 +269,7 @@ public:
int numInsnClasses = 0,
int maxResources = 0, int numCombos = 0, int maxStages = 0);
};
+
} // end anonymous namespace
#ifndef NDEBUG
@@ -314,8 +321,6 @@ void dbgsIndent(unsigned indent) {
State::State() :
stateNum(currentStateNum++), isInitial(false) {}
-DFA::DFA(): currentState(nullptr) {}
-
//
// addTransition - Add a transition from this state given the input InsnClass
//
@@ -370,7 +375,6 @@ void State::AddInsnClassStages(std::vector<unsigned> &InsnClass,
unsigned prevState, unsigned origState,
DenseSet<unsigned> &VisitedResourceStates,
std::set<unsigned> &PossibleStates) const {
-
assert((chkstage < numstages) && "AddInsnClassStages: stage out of range");
unsigned thisStage = InsnClass[chkstage];
@@ -469,7 +473,6 @@ bool State::canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
std::map<unsigned, unsigned> &ComboBitToBitsMap) const {
for (std::set<unsigned>::const_iterator SI = stateInfo.begin();
SI != stateInfo.end(); ++SI) {
-
// Check to see if all required resources are available.
bool available = true;
@@ -514,8 +517,7 @@ const State &DFA::newState() {
int State::currentStateNum = 0;
DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):
- TargetName(CodeGenTarget(R).getName()),
- allInsnClasses(), Records(R) {}
+ TargetName(CodeGenTarget(R).getName()), Records(R) {}
//
// writeTableAndAPI - Print out a table representing the DFA and the
@@ -531,7 +533,6 @@ DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):
void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,
int numInsnClasses,
int maxResources, int numCombos, int maxStages) {
-
unsigned numStates = states.size();
DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");
@@ -783,7 +784,7 @@ int DFAPacketizerEmitter::collectOneInsnClass(const std::string &ProcName,
DEBUG(dbgs() << " (bits: 0x" << utohexstr(UnitBitValue) << ")\n");
}
- if (UnitBits.size() > 0)
+ if (!UnitBits.empty())
allInsnClasses.push_back(UnitBits);
DEBUG({
@@ -831,7 +832,6 @@ int DFAPacketizerEmitter::collectAllInsnClasses(const std::string &ProcName,
// Run the worklist algorithm to generate the DFA.
//
void DFAPacketizerEmitter::run(raw_ostream &OS) {
-
// Collect processor iteraries.
std::vector<Record*> ProcItinList =
Records.getAllDerivedDefinitions("ProcessorItineraries");
@@ -890,7 +890,6 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
Initial->isInitial = true;
Initial->stateInfo.insert(0x0);
SmallVector<const State*, 32> WorkList;
-// std::queue<State*> WorkList;
std::map<std::set<unsigned>, const State*> Visited;
WorkList.push_back(Initial);
@@ -937,7 +936,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
current->canMaybeAddInsnClass(InsnClass, ComboBitToBitsMap)) {
const State *NewState = nullptr;
current->AddInsnClass(InsnClass, ComboBitToBitsMap, NewStateResources);
- if (NewStateResources.size() == 0) {
+ if (NewStateResources.empty()) {
DEBUG(dbgs() << " Skipped - no new states generated\n");
continue;
}
@@ -989,4 +988,4 @@ void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS) {
DFAPacketizerEmitter(RK).run(OS);
}
-} // end namespaec llvm
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
index 44815b0..6e1d8dd 100644
--- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
@@ -104,7 +104,7 @@ extern void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
CodeGenTarget Target(Records);
- emitSourceFileHeader(" * " + Target.getName() + " Disassembler", OS);
+ emitSourceFileHeader(" * " + Target.getName().str() + " Disassembler", OS);
// X86 uses a custom disassembler.
if (Target.getName() == "X86") {
diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
index debb12c..43c6a98 100644
--- a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
@@ -564,8 +564,7 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true);
SuffixOS.flush();
if (!StringSwitch<bool>(ManglingSuffix)
- .Cases("", "r", "rr", "ri", "rf", true)
- .Cases("rri", "i", "f", true)
+ .Cases("", "r", "rr", "ri", "i", "f", true)
.Default(false))
continue;
@@ -874,7 +873,7 @@ void EmitFastISel(RecordKeeper &RK, raw_ostream &OS) {
CodeGenDAGPatterns CGP(RK);
const CodeGenTarget &Target = CGP.getTargetInfo();
emitSourceFileHeader("\"Fast\" Instruction Selector for the " +
- Target.getName() + " target", OS);
+ Target.getName().str() + " target", OS);
// Determine the target's namespace name.
std::string InstNS = Target.getInstNamespace() + "::";
diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
index 0506400..e1aaecc 100644
--- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -12,21 +12,32 @@
//
//===----------------------------------------------------------------------===//
+#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCFixedLenDisassembler.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <map>
+#include <memory>
+#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -36,6 +47,7 @@ using namespace llvm;
#define DEBUG_TYPE "decoder-emitter"
namespace {
+
struct EncodingField {
unsigned Base, Width, Offset;
EncodingField(unsigned B, unsigned W, unsigned O)
@@ -66,8 +78,8 @@ typedef std::vector<uint8_t> DecoderTable;
typedef uint32_t DecoderFixup;
typedef std::vector<DecoderFixup> FixupList;
typedef std::vector<FixupList> FixupScopeList;
-typedef SmallSetVector<std::string, 16> PredicateSet;
-typedef SmallSetVector<std::string, 16> DecoderSet;
+typedef SmallSetVector<CachedHashString, 16> PredicateSet;
+typedef SmallSetVector<CachedHashString, 16> DecoderSet;
struct DecoderTableInfo {
DecoderTable Table;
FixupScopeList FixupStack;
@@ -75,13 +87,10 @@ struct DecoderTableInfo {
DecoderSet Decoders;
};
-} // End anonymous namespace
-
-namespace {
class FixedLenDecoderEmitter {
ArrayRef<const CodeGenInstruction *> NumberedInstructions;
-public:
+public:
// Defaults preserved here for documentation, even though they aren't
// strictly necessary given the way that this is currently being called.
FixedLenDecoderEmitter(RecordKeeper &R, std::string PredicateNamespace,
@@ -111,13 +120,15 @@ public:
private:
CodeGenTarget Target;
+
public:
std::string PredicateNamespace;
std::string GuardPrefix, GuardPostfix;
std::string ReturnOK, ReturnFail;
std::string Locals;
};
-} // End anonymous namespace
+
+} // end anonymous namespace
// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system
// for a bit value.
@@ -134,12 +145,15 @@ typedef enum {
static bool ValueSet(bit_value_t V) {
return (V == BIT_TRUE || V == BIT_FALSE);
}
+
static bool ValueNotSet(bit_value_t V) {
return (V == BIT_UNSET);
}
+
static int Value(bit_value_t V) {
return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1);
}
+
static bit_value_t bitFromBits(const BitsInit &bits, unsigned index) {
if (BitInit *bit = dyn_cast<BitInit>(bits.getBit(index)))
return bit->getValue() ? BIT_TRUE : BIT_FALSE;
@@ -147,6 +161,7 @@ static bit_value_t bitFromBits(const BitsInit &bits, unsigned index) {
// The bit is uninitialized.
return BIT_UNSET;
}
+
// Prints the bit value for each position.
static void dumpBits(raw_ostream &o, const BitsInit &bits) {
for (unsigned index = bits.getNumBits(); index > 0; --index) {
@@ -166,19 +181,18 @@ static void dumpBits(raw_ostream &o, const BitsInit &bits) {
}
}
-static BitsInit &getBitsField(const Record &def, const char *str) {
+static BitsInit &getBitsField(const Record &def, StringRef str) {
BitsInit *bits = def.getValueAsBitsInit(str);
return *bits;
}
-// Forward declaration.
-namespace {
-class FilterChooser;
-} // End anonymous namespace
-
// Representation of the instruction to work on.
typedef std::vector<bit_value_t> insn_t;
+namespace {
+
+class FilterChooser;
+
/// Filter - Filter works with FilterChooser to produce the decoding tree for
/// the ISA.
///
@@ -215,7 +229,6 @@ typedef std::vector<bit_value_t> insn_t;
/// decoder could try to decode the even/odd register numbering and assign to
/// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a"
/// version and return the Opcode since the two have the same Asm format string.
-namespace {
class Filter {
protected:
const FilterChooser *Owner;// points to the FilterChooser who owns this filter
@@ -224,7 +237,7 @@ protected:
bool Mixed; // a mixed region contains both set and unset bits
// Map of well-known segment value to the set of uid's with that value.
- std::map<uint64_t, std::vector<unsigned> > FilteredInstructions;
+ std::map<uint64_t, std::vector<unsigned>> FilteredInstructions;
// Set of uid's with non-constant segment values.
std::vector<unsigned> VariableInstructions;
@@ -239,11 +252,18 @@ protected:
unsigned LastOpcFiltered;
public:
+ Filter(Filter &&f);
+ Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed);
+
+ ~Filter() = default;
+
unsigned getNumFiltered() const { return NumFiltered; }
+
unsigned getSingletonOpc() const {
assert(NumFiltered == 1);
return LastOpcFiltered;
}
+
// Return the filter chooser for the group of instructions without constant
// segment values.
const FilterChooser &getVariableFC() const {
@@ -252,11 +272,6 @@ public:
return *(FilterChooserMap.find((unsigned)-1)->second);
}
- Filter(Filter &&f);
- Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed);
-
- ~Filter();
-
// Divides the decoding task into sub tasks and delegates them to the
// inferior FilterChooser's.
//
@@ -272,8 +287,9 @@ public:
// Returns the number of fanout produced by the filter. More fanout implies
// the filter distinguishes more categories of instructions.
unsigned usefulness() const;
-}; // End of class Filter
-} // End anonymous namespace
+}; // end class Filter
+
+} // end anonymous namespace
// These are states of our finite state machines used in FilterChooser's
// filterProcessor() which produces the filter candidates to use.
@@ -301,6 +317,7 @@ typedef enum {
/// decoding tree. And each case is delegated to an inferior FilterChooser to
/// decide what further remaining bits to look at.
namespace {
+
class FilterChooser {
protected:
friend class Filter;
@@ -312,7 +329,7 @@ protected:
const std::vector<unsigned> &Opcodes;
// Lookup table for the operand decoding of instructions.
- const std::map<unsigned, std::vector<OperandInfo> > &Operands;
+ const std::map<unsigned, std::vector<OperandInfo>> &Operands;
// Vector of candidate filters.
std::vector<Filter> Filters;
@@ -333,16 +350,13 @@ protected:
// Parent emitter
const FixedLenDecoderEmitter *Emitter;
- FilterChooser(const FilterChooser &) = delete;
- void operator=(const FilterChooser &) = delete;
public:
-
FilterChooser(ArrayRef<const CodeGenInstruction *> Insts,
const std::vector<unsigned> &IDs,
- const std::map<unsigned, std::vector<OperandInfo> > &Ops,
+ const std::map<unsigned, std::vector<OperandInfo>> &Ops,
unsigned BW,
const FixedLenDecoderEmitter *E)
- : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(),
+ : AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1),
BitWidth(BW), Emitter(E) {
doFilter();
@@ -350,16 +364,18 @@ public:
FilterChooser(ArrayRef<const CodeGenInstruction *> Insts,
const std::vector<unsigned> &IDs,
- const std::map<unsigned, std::vector<OperandInfo> > &Ops,
+ const std::map<unsigned, std::vector<OperandInfo>> &Ops,
const std::vector<bit_value_t> &ParentFilterBitValues,
const FilterChooser &parent)
: AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
- Filters(), FilterBitValues(ParentFilterBitValues),
- Parent(&parent), BestIndex(-1), BitWidth(parent.BitWidth),
- Emitter(parent.Emitter) {
+ FilterBitValues(ParentFilterBitValues), Parent(&parent), BestIndex(-1),
+ BitWidth(parent.BitWidth), Emitter(parent.Emitter) {
doFilter();
}
+ FilterChooser(const FilterChooser &) = delete;
+ void operator=(const FilterChooser &) = delete;
+
unsigned getBitWidth() const { return BitWidth; }
protected:
@@ -384,7 +400,7 @@ protected:
}
// Returns the record name.
- const std::string &nameWithID(unsigned Opcode) const {
+ const StringRef nameWithID(unsigned Opcode) const {
return AllInstructions[Opcode]->TheDef->getName();
}
@@ -476,7 +492,8 @@ public:
// instructions.
void emitTableEntries(DecoderTableInfo &TableInfo) const;
};
-} // End anonymous namespace
+
+} // end anonymous namespace
///////////////////////////
// //
@@ -527,9 +544,6 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
&& "Filter returns no instruction categories");
}
-Filter::~Filter() {
-}
-
// Divides the decoding task into sub tasks and delegates them to the
// inferior FilterChooser's.
//
@@ -1071,7 +1085,7 @@ void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation,
for (const auto &Op : Operands.find(Opc)->second) {
// If a custom instruction decoder was specified, use that.
- if (Op.numFields() == 0 && Op.Decoder.size()) {
+ if (Op.numFields() == 0 && !Op.Decoder.empty()) {
HasCompleteDecoder = Op.HasCompleteDecoder;
OS.indent(Indentation) << Emitter->GuardPrefix << Op.Decoder
<< "(MI, insn, Address, Decoder)"
@@ -1106,11 +1120,9 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
// overkill for now, though.
// Make sure the predicate is in the table.
- Decoders.insert(StringRef(Decoder));
+ Decoders.insert(CachedHashString(Decoder));
// Now figure out the index for when we write out the table.
- DecoderSet::const_iterator P = std::find(Decoders.begin(),
- Decoders.end(),
- Decoder.str());
+ DecoderSet::const_iterator P = find(Decoders, Decoder.str());
return (unsigned)(P - Decoders.begin());
}
@@ -1143,7 +1155,7 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
StringRef SR(P);
std::pair<StringRef, StringRef> pairs = SR.split(',');
- while (pairs.second.size()) {
+ while (!pairs.second.empty()) {
emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
o << " && ";
pairs = pairs.second.split(',');
@@ -1181,11 +1193,9 @@ unsigned FilterChooser::getPredicateIndex(DecoderTableInfo &TableInfo,
// overkill for now, though.
// Make sure the predicate is in the table.
- TableInfo.Predicates.insert(Predicate.str());
+ TableInfo.Predicates.insert(CachedHashString(Predicate));
// Now figure out the index for when we write out the table.
- PredicateSet::const_iterator P = std::find(TableInfo.Predicates.begin(),
- TableInfo.Predicates.end(),
- Predicate.str());
+ PredicateSet::const_iterator P = find(TableInfo.Predicates, Predicate);
return (unsigned)(P - TableInfo.Predicates.begin());
}
@@ -1374,7 +1384,6 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
Best.getVariableFC().emitTableEntries(TableInfo);
}
-
// Assign a single filter and run with it. Top level API client can initialize
// with a single filter to start the filtering process.
void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit,
@@ -1692,9 +1701,37 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
}
}
+static std::string findOperandDecoderMethod(TypedInit *TI) {
+ std::string Decoder;
+
+ RecordRecTy *Type = cast<RecordRecTy>(TI->getType());
+ Record *TypeRecord = Type->getRecord();
+
+ RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod");
+ StringInit *String = DecoderString ?
+ dyn_cast<StringInit>(DecoderString->getValue()) : nullptr;
+ if (String) {
+ Decoder = String->getValue();
+ if (!Decoder.empty())
+ return Decoder;
+ }
+
+ if (TypeRecord->isSubClassOf("RegisterOperand"))
+ TypeRecord = TypeRecord->getValueAsDef("RegClass");
+
+ if (TypeRecord->isSubClassOf("RegisterClass")) {
+ Decoder = "Decode" + TypeRecord->getName().str() + "RegisterClass";
+ } else if (TypeRecord->isSubClassOf("PointerLikeRegClass")) {
+ Decoder = "DecodePointerLikeRegClass" +
+ utostr(TypeRecord->getValueAsInt("RegClassKind"));
+ }
+
+ return Decoder;
+}
+
static bool populateInstruction(CodeGenTarget &Target,
const CodeGenInstruction &CGI, unsigned Opc,
- std::map<unsigned, std::vector<OperandInfo> > &Operands){
+ std::map<unsigned, std::vector<OperandInfo>> &Operands){
const Record &Def = *CGI.TheDef;
// If all the bit positions are not specified; do not decode this instruction.
// We are bound to fail! For proper disassembly, the well-known encoding bits
@@ -1722,13 +1759,15 @@ static bool populateInstruction(CodeGenTarget &Target,
// Gather the outputs/inputs of the instruction, so we can find their
// positions in the encoding. This assumes for now that they appear in the
// MCInst in the order that they're listed.
- std::vector<std::pair<Init*, std::string> > InOutOperands;
+ std::vector<std::pair<Init*, StringRef>> InOutOperands;
DagInit *Out = Def.getValueAsDag("OutOperandList");
DagInit *In = Def.getValueAsDag("InOperandList");
for (unsigned i = 0; i < Out->getNumArgs(); ++i)
- InOutOperands.push_back(std::make_pair(Out->getArg(i), Out->getArgName(i)));
+ InOutOperands.push_back(std::make_pair(Out->getArg(i),
+ Out->getArgNameStr(i)));
for (unsigned i = 0; i < In->getNumArgs(); ++i)
- InOutOperands.push_back(std::make_pair(In->getArg(i), In->getArgName(i)));
+ InOutOperands.push_back(std::make_pair(In->getArg(i),
+ In->getArgNameStr(i)));
// Search for tied operands, so that we can correctly instantiate
// operands that are not explicitly represented in the encoding.
@@ -1743,7 +1782,7 @@ static bool populateInstruction(CodeGenTarget &Target,
}
}
- std::map<std::string, std::vector<OperandInfo> > NumberedInsnOperands;
+ std::map<std::string, std::vector<OperandInfo>> NumberedInsnOperands;
std::set<std::string> NumberedInsnOperandsNoTie;
if (Target.getInstructionSet()->
getValueAsBit("decodePositionallyEncodedOperands")) {
@@ -1828,7 +1867,7 @@ static bool populateInstruction(CodeGenTarget &Target,
Name << "(" << SO.first << ", " << SO.second << ") => " <<
Vals[i].getName() << "\n");
- std::string Decoder = "";
+ std::string Decoder;
Record *TypeRecord = CGI.Operands[SO.first].Rec;
RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod");
@@ -1852,7 +1891,7 @@ static bool populateInstruction(CodeGenTarget &Target,
if (TypeRecord->isSubClassOf("RegisterOperand"))
TypeRecord = TypeRecord->getValueAsDef("RegClass");
if (TypeRecord->isSubClassOf("RegisterClass")) {
- Decoder = "Decode" + TypeRecord->getName() + "RegisterClass";
+ Decoder = "Decode" + TypeRecord->getName().str() + "RegisterClass";
isReg = true;
} else if (TypeRecord->isSubClassOf("PointerLikeRegClass")) {
Decoder = "DecodePointerLikeRegClass" +
@@ -1917,33 +1956,13 @@ static bool populateInstruction(CodeGenTarget &Target,
continue;
}
- std::string Decoder = "";
-
- // At this point, we can locate the field, but we need to know how to
- // interpret it. As a first step, require the target to provide callbacks
- // 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>(Op.first);
- RecordRecTy *Type = cast<RecordRecTy>(TI->getType());
- Record *TypeRecord = Type->getRecord();
- bool isReg = false;
- if (TypeRecord->isSubClassOf("RegisterOperand"))
- TypeRecord = TypeRecord->getValueAsDef("RegClass");
- if (TypeRecord->isSubClassOf("RegisterClass")) {
- Decoder = "Decode" + TypeRecord->getName() + "RegisterClass";
- isReg = true;
- } else if (TypeRecord->isSubClassOf("PointerLikeRegClass")) {
- Decoder = "DecodePointerLikeRegClass" +
- utostr(TypeRecord->getValueAsInt("RegClassKind"));
- isReg = true;
- }
- RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod");
- StringInit *String = DecoderString ?
- dyn_cast<StringInit>(DecoderString->getValue()) : nullptr;
- if (!isReg && String && String->getValue() != "")
- Decoder = String->getValue();
+ // At this point, we can locate the decoder field, but we need to know how
+ // to interpret it. As a first step, require the target to provide
+ // callbacks for decoding register classes.
+ std::string Decoder = findOperandDecoderMethod(TI);
+ Record *TypeRecord = cast<RecordRecTy>(TI->getType())->getRecord();
RecordVal *HasCompleteDecoderVal =
TypeRecord->getValue("hasCompleteDecoder");
@@ -2009,7 +2028,6 @@ static bool populateInstruction(CodeGenTarget &Target,
Operands[Opc] = InsnOperands;
-
#if 0
DEBUG({
// Dumps the instruction encoding bits.
@@ -2062,7 +2080,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " const uint8_t *Ptr = DecodeTable;\n"
<< " uint32_t CurFieldValue = 0;\n"
<< " DecodeStatus S = MCDisassembler::Success;\n"
- << " for (;;) {\n"
+ << " while (true) {\n"
<< " ptrdiff_t Loc = Ptr - DecodeTable;\n"
<< " switch (*Ptr) {\n"
<< " default:\n"
@@ -2230,8 +2248,8 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
// Parameterize the decoders based on namespace and instruction width.
NumberedInstructions = Target.getInstructionsByEnumValue();
std::map<std::pair<std::string, unsigned>,
- std::vector<unsigned> > OpcMap;
- std::map<unsigned, std::vector<OperandInfo> > Operands;
+ std::vector<unsigned>> OpcMap;
+ std::map<unsigned, std::vector<OperandInfo>> Operands;
for (unsigned i = 0; i < NumberedInstructions.size(); ++i) {
const CodeGenInstruction *Inst = NumberedInstructions[i];
@@ -2304,4 +2322,4 @@ void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
ROK, RFail, L).run(OS);
}
-} // End llvm namespace
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp b/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp
new file mode 100644
index 0000000..2bc6181
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -0,0 +1,388 @@
+//===- GlobalISelEmitter.cpp - Generate an instruction selector -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// This tablegen backend emits code for use by the GlobalISel instruction
+/// selector. See include/llvm/CodeGen/TargetGlobalISel.td.
+///
+/// This file analyzes the patterns recognized by the SelectionDAGISel tablegen
+/// backend, filters out the ones that are unsupported, maps
+/// SelectionDAG-specific constructs to their GlobalISel counterpart
+/// (when applicable: MVT to LLT; SDNode to generic Instruction).
+///
+/// Not all patterns are supported: pass the tablegen invocation
+/// "-warn-on-skipped-patterns" to emit a warning when a pattern is skipped,
+/// as well as why.
+///
+/// The generated file defines a single method:
+/// bool <Target>InstructionSelector::selectImpl(MachineInstr &I) const;
+/// intended to be used in InstructionSelector::select as the first-step
+/// selector for the patterns that don't require complex C++.
+///
+/// FIXME: We'll probably want to eventually define a base
+/// "TargetGenInstructionSelector" class.
+///
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenDAGPatterns.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <string>
+using namespace llvm;
+
+#define DEBUG_TYPE "gisel-emitter"
+
+STATISTIC(NumPatternTotal, "Total number of patterns");
+STATISTIC(NumPatternSkipped, "Number of patterns skipped");
+STATISTIC(NumPatternEmitted, "Number of patterns emitted");
+
+static cl::opt<bool> WarnOnSkippedPatterns(
+ "warn-on-skipped-patterns",
+ cl::desc("Explain why a pattern was skipped for inclusion "
+ "in the GlobalISel selector"),
+ cl::init(false));
+
+namespace {
+
+class GlobalISelEmitter {
+public:
+ explicit GlobalISelEmitter(RecordKeeper &RK);
+ void run(raw_ostream &OS);
+
+private:
+ const RecordKeeper &RK;
+ const CodeGenDAGPatterns CGP;
+ const CodeGenTarget &Target;
+
+ /// Keep track of the equivalence between SDNodes and Instruction.
+ /// This is defined using 'GINodeEquiv' in the target description.
+ DenseMap<Record *, const CodeGenInstruction *> NodeEquivs;
+
+ void gatherNodeEquivs();
+ const CodeGenInstruction *findNodeEquiv(Record *N);
+
+ struct SkipReason {
+ std::string Reason;
+ };
+
+ /// Analyze pattern \p P, possibly emitting matching code for it to \p OS.
+ /// Otherwise, return a reason why this pattern was skipped for emission.
+ Optional<SkipReason> runOnPattern(const PatternToMatch &P,
+ raw_ostream &OS);
+};
+
+} // end anonymous namespace
+
+//===- Helper functions ---------------------------------------------------===//
+
+/// Convert an MVT to an equivalent LLT if possible, or the invalid LLT() for
+/// MVTs that don't map cleanly to an LLT (e.g., iPTR, *any, ...).
+static Optional<std::string> MVTToLLT(MVT::SimpleValueType SVT) {
+ std::string TyStr;
+ raw_string_ostream OS(TyStr);
+ MVT VT(SVT);
+ if (VT.isVector() && VT.getVectorNumElements() != 1) {
+ OS << "LLT::vector(" << VT.getVectorNumElements() << ", "
+ << VT.getScalarSizeInBits() << ")";
+ } else if (VT.isInteger() || VT.isFloatingPoint()) {
+ OS << "LLT::scalar(" << VT.getSizeInBits() << ")";
+ } else {
+ return None;
+ }
+ OS.flush();
+ return TyStr;
+}
+
+static bool isTrivialOperatorNode(const TreePatternNode *N) {
+ return !N->isLeaf() && !N->hasAnyPredicate() && !N->getTransformFn();
+}
+
+//===- Matchers -----------------------------------------------------------===//
+
+struct Matcher {
+ virtual ~Matcher() {}
+ virtual void emit(raw_ostream &OS) const = 0;
+};
+
+raw_ostream &operator<<(raw_ostream &S, const Matcher &M) {
+ M.emit(S);
+ return S;
+}
+
+struct MatchAction {
+ virtual ~MatchAction() {}
+ virtual void emit(raw_ostream &OS) const = 0;
+};
+
+raw_ostream &operator<<(raw_ostream &S, const MatchAction &A) {
+ A.emit(S);
+ return S;
+}
+
+struct MatchOpcode : public Matcher {
+ MatchOpcode(const CodeGenInstruction *I) : I(I) {}
+ const CodeGenInstruction *I;
+
+ virtual void emit(raw_ostream &OS) const {
+ OS << "I.getOpcode() == " << I->Namespace << "::" << I->TheDef->getName();
+ }
+};
+
+struct MatchRegOpType : public Matcher {
+ MatchRegOpType(unsigned OpIdx, std::string Ty)
+ : OpIdx(OpIdx), Ty(Ty) {}
+ unsigned OpIdx;
+ std::string Ty;
+
+ virtual void emit(raw_ostream &OS) const {
+ OS << "MRI.getType(I.getOperand(" << OpIdx << ").getReg()) == (" << Ty
+ << ")";
+ }
+};
+
+struct MatchRegOpBank : public Matcher {
+ MatchRegOpBank(unsigned OpIdx, const CodeGenRegisterClass &RC)
+ : OpIdx(OpIdx), RC(RC) {}
+ unsigned OpIdx;
+ const CodeGenRegisterClass &RC;
+
+ virtual void emit(raw_ostream &OS) const {
+ OS << "(&RBI.getRegBankFromRegClass(" << RC.getQualifiedName()
+ << "RegClass) == RBI.getRegBank(I.getOperand(" << OpIdx
+ << ").getReg(), MRI, TRI))";
+ }
+};
+
+struct MatchMBBOp : public Matcher {
+ MatchMBBOp(unsigned OpIdx) : OpIdx(OpIdx) {}
+ unsigned OpIdx;
+
+ virtual void emit(raw_ostream &OS) const {
+ OS << "I.getOperand(" << OpIdx << ").isMBB()";
+ }
+};
+
+struct MutateOpcode : public MatchAction {
+ MutateOpcode(const CodeGenInstruction *I) : I(I) {}
+ const CodeGenInstruction *I;
+
+ virtual void emit(raw_ostream &OS) const {
+ OS << "I.setDesc(TII.get(" << I->Namespace << "::" << I->TheDef->getName()
+ << "));";
+ }
+};
+
+class MatcherEmitter {
+ const PatternToMatch &P;
+
+public:
+ std::vector<std::unique_ptr<Matcher>> Matchers;
+ std::vector<std::unique_ptr<MatchAction>> Actions;
+
+ MatcherEmitter(const PatternToMatch &P) : P(P) {}
+
+ void emit(raw_ostream &OS) {
+ if (Matchers.empty())
+ llvm_unreachable("Unexpected empty matcher!");
+
+ OS << " // Src: " << *P.getSrcPattern() << "\n"
+ << " // Dst: " << *P.getDstPattern() << "\n";
+
+ OS << " if ((" << *Matchers.front() << ")";
+ for (auto &MA : makeArrayRef(Matchers).drop_front())
+ OS << " &&\n (" << *MA << ")";
+ OS << ") {\n";
+
+ for (auto &MA : Actions)
+ OS << " " << *MA << "\n";
+
+ OS << " constrainSelectedInstRegOperands(I, TII, TRI, RBI);\n";
+ OS << " return true;\n";
+ OS << " }\n";
+ }
+};
+
+//===- GlobalISelEmitter class --------------------------------------------===//
+
+void GlobalISelEmitter::gatherNodeEquivs() {
+ assert(NodeEquivs.empty());
+ for (Record *Equiv : RK.getAllDerivedDefinitions("GINodeEquiv"))
+ NodeEquivs[Equiv->getValueAsDef("Node")] =
+ &Target.getInstruction(Equiv->getValueAsDef("I"));
+}
+
+const CodeGenInstruction *GlobalISelEmitter::findNodeEquiv(Record *N) {
+ return NodeEquivs.lookup(N);
+}
+
+GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)
+ : RK(RK), CGP(RK), Target(CGP.getTargetInfo()) {}
+
+//===- Emitter ------------------------------------------------------------===//
+
+Optional<GlobalISelEmitter::SkipReason>
+GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) {
+
+ // Keep track of the matchers and actions to emit.
+ MatcherEmitter M(P);
+
+ // First, analyze the whole pattern.
+ // If the entire pattern has a predicate (e.g., target features), ignore it.
+ if (!P.getPredicates()->getValues().empty())
+ return SkipReason{"Pattern has a predicate"};
+
+ // Physreg imp-defs require additional logic. Ignore the pattern.
+ if (!P.getDstRegs().empty())
+ return SkipReason{"Pattern defines a physical register"};
+
+ // Next, analyze the pattern operators.
+ TreePatternNode *Src = P.getSrcPattern();
+ TreePatternNode *Dst = P.getDstPattern();
+
+ // If the root of either pattern isn't a simple operator, ignore it.
+ if (!isTrivialOperatorNode(Dst))
+ return SkipReason{"Dst pattern root isn't a trivial operator"};
+ if (!isTrivialOperatorNode(Src))
+ return SkipReason{"Src pattern root isn't a trivial operator"};
+
+ Record *DstOp = Dst->getOperator();
+ if (!DstOp->isSubClassOf("Instruction"))
+ return SkipReason{"Pattern operator isn't an instruction"};
+
+ auto &DstI = Target.getInstruction(DstOp);
+
+ auto SrcGIOrNull = findNodeEquiv(Src->getOperator());
+ if (!SrcGIOrNull)
+ return SkipReason{"Pattern operator lacks an equivalent Instruction"};
+ auto &SrcGI = *SrcGIOrNull;
+
+ // The operators look good: match the opcode and mutate it to the new one.
+ M.Matchers.emplace_back(new MatchOpcode(&SrcGI));
+ M.Actions.emplace_back(new MutateOpcode(&DstI));
+
+ // Next, analyze the children, only accepting patterns that don't require
+ // any change to operands.
+ if (Src->getNumChildren() != Dst->getNumChildren())
+ return SkipReason{"Src/dst patterns have a different # of children"};
+
+ unsigned OpIdx = 0;
+
+ // Start with the defined operands (i.e., the results of the root operator).
+ if (DstI.Operands.NumDefs != Src->getExtTypes().size())
+ return SkipReason{"Src pattern results and dst MI defs are different"};
+
+ for (const EEVT::TypeSet &Ty : Src->getExtTypes()) {
+ Record *DstIOpRec = DstI.Operands[OpIdx].Rec;
+ if (!DstIOpRec->isSubClassOf("RegisterClass"))
+ return SkipReason{"Dst MI def isn't a register class"};
+
+ auto OpTyOrNone = MVTToLLT(Ty.getConcrete());
+ if (!OpTyOrNone)
+ return SkipReason{"Dst operand has an unsupported type"};
+
+ M.Matchers.emplace_back(new MatchRegOpType(OpIdx, *OpTyOrNone));
+ M.Matchers.emplace_back(
+ new MatchRegOpBank(OpIdx, Target.getRegisterClass(DstIOpRec)));
+ ++OpIdx;
+ }
+
+ // Finally match the used operands (i.e., the children of the root operator).
+ for (unsigned i = 0, e = Src->getNumChildren(); i != e; ++i) {
+ auto *SrcChild = Src->getChild(i);
+ auto *DstChild = Dst->getChild(i);
+
+ // Patterns can reorder operands. Ignore those for now.
+ if (SrcChild->getName() != DstChild->getName())
+ return SkipReason{"Src/dst pattern children not in same order"};
+
+ // The only non-leaf child we accept is 'bb': it's an operator because
+ // BasicBlockSDNode isn't inline, but in MI it's just another operand.
+ if (!SrcChild->isLeaf()) {
+ if (DstChild->isLeaf() ||
+ SrcChild->getOperator() != DstChild->getOperator())
+ return SkipReason{"Src/dst pattern child operator mismatch"};
+
+ if (SrcChild->getOperator()->isSubClassOf("SDNode")) {
+ auto &ChildSDNI = CGP.getSDNodeInfo(SrcChild->getOperator());
+ if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") {
+ M.Matchers.emplace_back(new MatchMBBOp(OpIdx++));
+ continue;
+ }
+ }
+ return SkipReason{"Src pattern child isn't a leaf node"};
+ }
+
+ if (SrcChild->getLeafValue() != DstChild->getLeafValue())
+ return SkipReason{"Src/dst pattern child leaf mismatch"};
+
+ // Otherwise, we're looking for a bog-standard RegisterClass operand.
+ if (SrcChild->hasAnyPredicate())
+ return SkipReason{"Src pattern child has predicate"};
+ auto *ChildRec = cast<DefInit>(SrcChild->getLeafValue())->getDef();
+ if (!ChildRec->isSubClassOf("RegisterClass"))
+ return SkipReason{"Src pattern child isn't a RegisterClass"};
+
+ ArrayRef<EEVT::TypeSet> ChildTypes = SrcChild->getExtTypes();
+ if (ChildTypes.size() != 1)
+ return SkipReason{"Src pattern child has multiple results"};
+
+ auto OpTyOrNone = MVTToLLT(ChildTypes.front().getConcrete());
+ if (!OpTyOrNone)
+ return SkipReason{"Src operand has an unsupported type"};
+
+ M.Matchers.emplace_back(new MatchRegOpType(OpIdx, *OpTyOrNone));
+ M.Matchers.emplace_back(
+ new MatchRegOpBank(OpIdx, Target.getRegisterClass(ChildRec)));
+ ++OpIdx;
+ }
+
+ // We're done with this pattern! Emit the processed result.
+ M.emit(OS);
+ ++NumPatternEmitted;
+ return None;
+}
+
+void GlobalISelEmitter::run(raw_ostream &OS) {
+ // Track the GINodeEquiv definitions.
+ gatherNodeEquivs();
+
+ emitSourceFileHeader(("Global Instruction Selector for the " +
+ Target.getName() + " target").str(), OS);
+ OS << "bool " << Target.getName()
+ << "InstructionSelector::selectImpl"
+ "(MachineInstr &I) const {\n const MachineRegisterInfo &MRI = "
+ "I.getParent()->getParent()->getRegInfo();\n";
+
+ // Look through the SelectionDAG patterns we found, possibly emitting some.
+ for (const PatternToMatch &Pat : CGP.ptms()) {
+ ++NumPatternTotal;
+ if (auto SkipReason = runOnPattern(Pat, OS)) {
+ if (WarnOnSkippedPatterns) {
+ PrintWarning(Pat.getSrcRecord()->getLoc(),
+ "Skipped pattern: " + SkipReason->Reason);
+ }
+ ++NumPatternSkipped;
+ }
+ }
+
+ OS << " return false;\n}\n";
+}
+
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+void EmitGlobalISel(RecordKeeper &RK, raw_ostream &OS) {
+ GlobalISelEmitter(RK).run(OS);
+}
+} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
index 02461cc..ab7d964 100644
--- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -13,22 +13,29 @@
//===----------------------------------------------------------------------===//
#include "CodeGenDAGPatterns.h"
+#include "CodeGenInstruction.h"
#include "CodeGenSchedule.h"
#include "CodeGenTarget.h"
#include "SequenceToOffsetTable.h"
#include "TableGenBackends.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
-#include <algorithm>
-#include <cstdio>
+#include <cassert>
+#include <cstdint>
#include <map>
+#include <string>
+#include <utility>
#include <vector>
using namespace llvm;
namespace {
+
class InstrInfoEmitter {
RecordKeeper &Records;
CodeGenDAGPatterns CDP;
@@ -50,7 +57,7 @@ private:
/// and instruction operand indices as their values. The values of this map
/// are lists of instruction names.
typedef std::map<std::map<unsigned, unsigned>,
- std::vector<std::string> > OpNameMapTy;
+ std::vector<std::string>> OpNameMapTy;
typedef std::map<std::string, unsigned>::iterator StrUintMapIter;
void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
Record *InstrInfo,
@@ -70,6 +77,7 @@ private:
void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst);
};
+
} // end anonymous namespace
static void PrintDefList(const std::vector<Record*> &Uses,
@@ -106,7 +114,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) {
OperandList.push_back(Op);
- Record *OpR = cast<DefInit>(MIOI->getArg(j))->getDef();
+ auto *OpR = cast<DefInit>(MIOI->getArg(j))->getDef();
OperandList.back().Rec = OpR;
}
}
@@ -202,7 +210,6 @@ void InstrInfoEmitter::initOperandMapData(
const std::string &Namespace,
std::map<std::string, unsigned> &Operands,
OpNameMapTy &OperandMap) {
-
unsigned NumOperands = 0;
for (const CodeGenInstruction *Inst : NumberedInstructions) {
if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable"))
@@ -217,7 +224,8 @@ void InstrInfoEmitter::initOperandMapData(
}
OpList[I->second] = Info.MIOperandNo;
}
- OperandMap[OpList].push_back(Namespace + "::" + Inst->TheDef->getName());
+ OperandMap[OpList].push_back(Namespace + "::" +
+ Inst->TheDef->getName().str());
}
}
@@ -235,7 +243,6 @@ void InstrInfoEmitter::initOperandMapData(
void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
const CodeGenTarget &Target,
ArrayRef<const CodeGenInstruction*> NumberedInstructions) {
-
const std::string &Namespace = Target.getInstNamespace();
std::string OpNameNS = "OpName";
// Map of operand names to their enumeration value. This will be used to
@@ -300,7 +307,6 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
OS << "} // end namespace " << Namespace << "\n";
OS << "} // end namespace llvm\n";
OS << "#endif //GET_INSTRINFO_NAMED_OPS\n\n";
-
}
/// Generate an enum for all the operand types for this target, under the
@@ -429,7 +435,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
OS << "struct " << ClassName << " : public TargetInstrInfo {\n"
<< " explicit " << ClassName
<< "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1, int ReturnOpcode = -1);\n"
- << " ~" << ClassName << "() override {}\n"
+ << " ~" << ClassName << "() override = default;\n"
<< "};\n";
OS << "} // end llvm namespace\n";
@@ -482,6 +488,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
if (Inst.isCompare) OS << "|(1ULL<<MCID::Compare)";
if (Inst.isMoveImm) OS << "|(1ULL<<MCID::MoveImm)";
if (Inst.isBitcast) OS << "|(1ULL<<MCID::Bitcast)";
+ if (Inst.isAdd) OS << "|(1ULL<<MCID::Add)";
if (Inst.isSelect) OS << "|(1ULL<<MCID::Select)";
if (Inst.isBarrier) OS << "|(1ULL<<MCID::Barrier)";
if (Inst.hasDelaySlot) OS << "|(1ULL<<MCID::DelaySlot)";
@@ -514,7 +521,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
PrintFatalError("no TSFlags?");
uint64_t Value = 0;
for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) {
- if (BitInit *Bit = dyn_cast<BitInit>(TSF->getBit(i)))
+ if (const auto *Bit = dyn_cast<BitInit>(TSF->getBit(i)))
Value |= uint64_t(Bit->getValue()) << i;
else
PrintFatalError("Invalid TSFlags bit in " + Inst.TheDef->getName());
@@ -561,7 +568,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
// emitEnums - Print out enum values for all of the instructions.
void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
-
OS << "#ifdef GET_INSTRINFO_ENUM\n";
OS << "#undef GET_INSTRINFO_ENUM\n";
diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
index a676159..33256cc 100644
--- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -213,10 +213,11 @@ enum IIT_Info {
IIT_HALF_VEC_ARG = 30,
IIT_SAME_VEC_WIDTH_ARG = 31,
IIT_PTR_TO_ARG = 32,
- IIT_VEC_OF_PTRS_TO_ELT = 33,
- IIT_I128 = 34,
- IIT_V512 = 35,
- IIT_V1024 = 36
+ IIT_PTR_TO_ELT = 33,
+ IIT_VEC_OF_PTRS_TO_ELT = 34,
+ IIT_I128 = 35,
+ IIT_V512 = 36,
+ IIT_V1024 = 37
};
@@ -251,7 +252,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
}
#if defined(_MSC_VER) && !defined(__clang__)
-#pragma optimize("",off) // MSVC 2010 optimizer can't deal with this function.
+#pragma optimize("",off) // MSVC 2015 optimizer can't deal with this function.
#endif
static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
@@ -277,6 +278,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
Sig.push_back(IIT_PTR_TO_ARG);
else if (R->isSubClassOf("LLVMVectorOfPointersToElt"))
Sig.push_back(IIT_VEC_OF_PTRS_TO_ELT);
+ else if (R->isSubClassOf("LLVMPointerToElt"))
+ Sig.push_back(IIT_PTR_TO_ELT);
else
Sig.push_back(IIT_ARG);
return Sig.push_back((Number << 3) | ArgCodes[Number]);
@@ -287,10 +290,10 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
unsigned Tmp = 0;
switch (VT) {
default: break;
- case MVT::iPTRAny: ++Tmp; // FALL THROUGH.
- case MVT::vAny: ++Tmp; // FALL THROUGH.
- case MVT::fAny: ++Tmp; // FALL THROUGH.
- case MVT::iAny: ++Tmp; // FALL THROUGH.
+ case MVT::iPTRAny: ++Tmp; LLVM_FALLTHROUGH;
+ case MVT::vAny: ++Tmp; LLVM_FALLTHROUGH;
+ case MVT::fAny: ++Tmp; LLVM_FALLTHROUGH;
+ case MVT::iAny: ++Tmp; LLVM_FALLTHROUGH;
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().
@@ -643,6 +646,18 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
OS << ",";
OS << "Attribute::ReadOnly";
break;
+ case CodeGenIntrinsic::ReadInaccessibleMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly,";
+ OS << "Attribute::InaccessibleMemOnly";
+ break;
+ case CodeGenIntrinsic::ReadInaccessibleMemOrArgMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly,";
+ OS << "Attribute::InaccessibleMemOrArgMemOnly";
+ break;
case CodeGenIntrinsic::WriteArgMem:
if (addComma)
OS << ",";
@@ -654,11 +669,32 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
OS << ",";
OS << "Attribute::WriteOnly";
break;
+ case CodeGenIntrinsic::WriteInaccessibleMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::WriteOnly,";
+ OS << "Attribute::InaccessibleMemOnly";
+ break;
+ case CodeGenIntrinsic::WriteInaccessibleMemOrArgMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::WriteOnly,";
+ OS << "Attribute::InaccessibleMemOrArgOnly";
+ break;
case CodeGenIntrinsic::ReadWriteArgMem:
if (addComma)
OS << ",";
OS << "Attribute::ArgMemOnly";
break;
+ case CodeGenIntrinsic::ReadWriteInaccessibleMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::InaccessibleMemOnly";
+ break;
+ case CodeGenIntrinsic::ReadWriteInaccessibleMemOrArgMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::InaccessibleMemOrArgMemOnly";
case CodeGenIntrinsic::ReadWriteMem:
break;
}
@@ -714,11 +750,11 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
if (TargetOnly) {
OS << "static " << TargetPrefix << "Intrinsic::ID "
<< "getIntrinsicFor" << CompilerName << "Builtin(const char "
- << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
+ << "*TargetPrefixStr, StringRef BuiltinNameStr) {\n";
} else {
OS << "Intrinsic::ID Intrinsic::getIntrinsicFor" << CompilerName
<< "Builtin(const char "
- << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
+ << "*TargetPrefixStr, StringRef BuiltinNameStr) {\n";
}
OS << " static const char BuiltinNames[] = {\n";
Table.EmitCharArray(OS);
@@ -730,13 +766,11 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
OS << " const char *getName() const {\n";
OS << " return &BuiltinNames[StrTabOffset];\n";
OS << " }\n";
- OS << " bool operator<(const char *RHS) const {\n";
- OS << " return strcmp(getName(), RHS) < 0;\n";
+ OS << " bool operator<(StringRef RHS) const {\n";
+ OS << " return strncmp(getName(), RHS.data(), RHS.size()) < 0;\n";
OS << " }\n";
OS << " };\n";
-
- OS << " StringRef BuiltinName(BuiltinNameStr);\n";
OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n";
// Note: this could emit significantly better code if we cared.
@@ -759,7 +793,7 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
OS << " std::end(" << I->first << "Names),\n";
OS << " BuiltinNameStr);\n";
OS << " if (I != std::end(" << I->first << "Names) &&\n";
- OS << " strcmp(I->getName(), BuiltinNameStr) == 0)\n";
+ OS << " I->getName() == BuiltinNameStr)\n";
OS << " return I->IntrinID;\n";
OS << " }\n";
}
diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
index 01e41d1..63bdd36 100644
--- a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
@@ -177,10 +177,10 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand)
continue;
StringMap<unsigned>::iterator SourceOp =
- SourceOperands.find(Dag->getArgName(i));
+ SourceOperands.find(Dag->getArgNameStr(i));
if (SourceOp == SourceOperands.end())
PrintFatalError(Rec->getLoc(),
- "Pseudo output operand '" + Dag->getArgName(i) +
+ "Pseudo output operand '" + Dag->getArgNameStr(i) +
"' has no matching source operand.");
// Map the source operand to the destination operand index for each
// MachineInstr operand.
diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index 9bb988f..b75be13 100644
--- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -15,6 +15,7 @@
#include "CodeGenRegisters.h"
#include "CodeGenTarget.h"
+#include "Types.h"
#include "SequenceToOffsetTable.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
@@ -103,7 +104,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "namespace llvm {\n\n";
OS << "class MCRegisterClass;\n"
- << "extern const MCRegisterClass " << Namespace
+ << "extern const MCRegisterClass " << Target.getName()
<< "MCRegisterClasses[];\n\n";
if (!Namespace.empty())
@@ -177,15 +178,6 @@ 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) {
@@ -264,8 +256,9 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
OS << "// Get the register unit pressure limit for this dimension.\n"
<< "// This limit must be adjusted dynamically for reserved registers.\n"
<< "unsigned " << ClassName << "::\n"
- << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const {\n"
- << " static const " << getMinimalTypeForRange(MaxRegUnitWeight)
+ << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const "
+ "{\n"
+ << " static const " << getMinimalTypeForRange(MaxRegUnitWeight, 32)
<< " PressureLimitTable[] = {\n";
for (unsigned i = 0; i < NumSets; ++i ) {
const RegUnitSet &RegUnits = RegBank.getRegSetAt(i);
@@ -306,7 +299,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< "/// Returns a -1 terminated array of pressure set IDs\n"
<< "const int* " << ClassName << "::\n"
<< "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n";
- OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1)
+ OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32)
<< " RCSetStartTable[] = {\n ";
for (unsigned i = 0, e = NumRCs; i != e; ++i) {
OS << PSetsSeqs.get(PSets[i]) << ",";
@@ -322,7 +315,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< "getRegUnitPressureSets(unsigned RegUnit) const {\n"
<< " assert(RegUnit < " << RegBank.getNumNativeRegUnits()
<< " && \"invalid register unit\");\n";
- OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1)
+ OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32)
<< " RUSetStartTable[] = {\n ";
for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();
UnitIdx < UnitEnd; ++UnitIdx) {
@@ -585,7 +578,7 @@ 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;
+typedef SmallVector<LaneBitmask, 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.
@@ -618,8 +611,8 @@ static void printDiff16(raw_ostream &OS, uint16_t Val) {
OS << Val;
}
-static void printMask(raw_ostream &OS, unsigned Val) {
- OS << format("0x%08X", Val);
+static void printMask(raw_ostream &OS, LaneBitmask Val) {
+ OS << "LaneBitmask(0x" << PrintLaneMask(Val) << ')';
}
// Try to combine Idx's compose map into Vec if it is compatible.
@@ -683,15 +676,15 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
// Output the row map if there is multiple rows.
if (Rows.size() > 1) {
- OS << " static const " << getMinimalTypeForRange(Rows.size()) << " RowMap["
- << SubRegIndicesSize << "] = {\n ";
+ OS << " static const " << getMinimalTypeForRange(Rows.size(), 32)
+ << " 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(SubRegIndicesSize + 1)
+ OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1, 32)
<< " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n";
for (unsigned r = 0, re = Rows.size(); r != re; ++r) {
OS << " { ";
@@ -746,7 +739,7 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
}
OS << " struct MaskRolOp {\n"
- " unsigned Mask;\n"
+ " LaneBitmask Mask;\n"
" uint8_t RotateLeft;\n"
" };\n"
" static const MaskRolOp LaneMaskComposeSequences[] = {\n";
@@ -756,9 +749,10 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &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);
+ printMask(OS << "{ ", P.Mask);
+ OS << format(", %2u }, ", P.RotateLeft);
}
- OS << "{ 0, 0 }";
+ OS << "{ LaneBitmask::getNone(), 0 }";
if (s+1 != se)
OS << ", ";
OS << " // Sequence " << Idx << "\n";
@@ -781,12 +775,13 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
" const {\n"
" --IdxA; assert(IdxA < " << SubRegIndices.size()
<< " && \"Subregister index out of bounds\");\n"
- " LaneBitmask Result = 0;\n"
- " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)"
- " {\n"
- " LaneBitmask Masked = LaneMask & Ops->Mask;\n"
- " Result |= (Masked << Ops->RotateLeft) & 0xFFFFFFFF;\n"
- " Result |= (Masked >> ((32 - Ops->RotateLeft) & 0x1F));\n"
+ " LaneBitmask Result;\n"
+ " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask.any(); ++Ops) {\n"
+ " LaneBitmask::Type M = LaneMask.getAsInteger() & Ops->Mask.getAsInteger();\n"
+ " if (unsigned S = Ops->RotateLeft)\n"
+ " Result |= LaneBitmask((M << S) | (M >> (LaneBitmask::BitWidth - S)));\n"
+ " else\n"
+ " Result |= LaneBitmask(M);\n"
" }\n"
" return Result;\n"
"}\n\n";
@@ -797,12 +792,13 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
" LaneMask &= getSubRegIndexLaneMask(IdxA);\n"
" --IdxA; assert(IdxA < " << SubRegIndices.size()
<< " && \"Subregister index out of bounds\");\n"
- " LaneBitmask Result = 0;\n"
- " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)"
- " {\n"
- " LaneBitmask Rotated = (LaneMask >> Ops->RotateLeft) |\n"
- " ((LaneMask << ((32 - Ops->RotateLeft) & 0x1F)) & 0xFFFFFFFF);\n"
- " Result |= Rotated & Ops->Mask;\n"
+ " LaneBitmask Result;\n"
+ " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask.any(); ++Ops) {\n"
+ " LaneBitmask::Type M = LaneMask.getAsInteger();\n"
+ " if (unsigned S = Ops->RotateLeft)\n"
+ " Result |= LaneBitmask((M >> S) | (M << (LaneBitmask::BitWidth - S)));\n"
+ " else\n"
+ " Result |= LaneBitmask(M);\n"
" }\n"
" return Result;\n"
"}\n\n";
@@ -901,8 +897,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
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");
+ for (LaneBitmask M : LaneMaskVec) {
+ assert(!M.all() && "terminator mask should not be part of the list");
}
#endif
LaneMaskSeqs.add(LaneMaskVec);
@@ -923,8 +919,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
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 << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n";
+ LaneMaskSeqs.emit(OS, printMask, "LaneBitmask::getAll()");
OS << "};\n\n";
// Emit the table of sub-register indexes.
@@ -1204,9 +1200,10 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "\" };\n\n";
// Emit SubRegIndex lane masks, including 0.
- OS << "\nstatic const unsigned SubRegIndexLaneMaskTable[] = {\n ~0u,\n";
+ OS << "\nstatic const LaneBitmask SubRegIndexLaneMaskTable[] = {\n LaneBitmask::getAll(),\n";
for (const auto &Idx : SubRegIndices) {
- OS << format(" 0x%08x, // ", Idx.LaneMask) << Idx.getName() << '\n';
+ printMask(OS << " ", Idx.LaneMask);
+ OS << ", // " << Idx.getName() << '\n';
}
OS << " };\n\n";
@@ -1324,9 +1321,9 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< "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)
- << (unsigned)RC.AllocationPriority << ",\n "
+ << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n ";
+ printMask(OS, RC.LaneMask);
+ OS << ",\n " << (unsigned)RC.AllocationPriority << ",\n "
<< (RC.HasDisjunctSubRegs?"true":"false")
<< ", /* HasDisjunctSubRegs */\n "
<< (RC.CoveredBySubRegs?"true":"false")
@@ -1368,7 +1365,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "};\n"; // End of register descriptors...
- std::string ClassName = Target.getName() + "GenRegisterInfo";
+ std::string ClassName = Target.getName().str() + "GenRegisterInfo";
auto SubRegIndicesSize =
std::distance(SubRegIndices.begin(), SubRegIndices.end());
@@ -1415,7 +1412,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 LaneBitmask " << 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";
@@ -1430,8 +1427,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour, unsigned PC)\n"
<< " : TargetRegisterInfo(" << TargetName << "RegInfoDesc"
<< ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
- << " SubRegIndexNameTable, SubRegIndexLaneMaskTable, 0x";
- OS.write_hex(RegBank.CoveringLanes);
+ << " SubRegIndexNameTable, SubRegIndexLaneMaskTable, ";
+ printMask(OS, RegBank.CoveringLanes);
OS << ") {\n"
<< " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1
<< ", RA, PC,\n " << TargetName
diff --git a/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp b/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp
index 8c1b880..80f0b0d 100644
--- a/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp
@@ -193,7 +193,7 @@ void SearchableTableEmitter::emitLookupFunction(StringRef Name, StringRef Field,
} else {
// Make sure the result is null terminated because it's going via "char *".
OS << " std::string CanonicalVal = " << Field << ".upper();\n";
- OS << " " << PairType << " Val = {CanonicalVal.data(), 0};\n";
+ OS << " " << PairType << " Val = {CanonicalVal.c_str(), 0};\n";
}
OS << " ArrayRef<" << PairType << "> Table(" << Name << "sBy" << Field
@@ -206,7 +206,7 @@ void SearchableTableEmitter::emitLookupFunction(StringRef Name, StringRef Field,
OS << ",\n ";
OS << "[](const " << PairType << " &LHS, const " << PairType
<< " &RHS) {\n";
- OS << " return StringRef(LHS.first) < StringRef(RHS.first);\n";
+ OS << " return std::strcmp(LHS.first, RHS.first) < 0;\n";
OS << " });\n\n";
}
diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
index 2288821..bf7b392 100644
--- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -14,7 +14,9 @@
#include "CodeGenTarget.h"
#include "CodeGenSchedule.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/MCSchedule.h"
#include "llvm/MC/SubtargetFeature.h"
@@ -27,6 +29,7 @@
#include <algorithm>
#include <cassert>
#include <cstdint>
+#include <iterator>
#include <map>
#include <string>
#include <vector>
@@ -42,7 +45,7 @@ class SubtargetEmitter {
// The SchedClassDesc table indexes into a global write resource table, write
// latency table, and read advance table.
struct SchedClassTables {
- std::vector<std::vector<MCSchedClassDesc> > ProcSchedClasses;
+ std::vector<std::vector<MCSchedClassDesc>> ProcSchedClasses;
std::vector<MCWriteProcResEntry> WriteProcResources;
std::vector<MCWriteLatencyEntry> WriteLatencies;
std::vector<std::string> WriterNames;
@@ -81,12 +84,12 @@ class SubtargetEmitter {
Record *ItinData,
std::string &ItinString, unsigned NOperandCycles);
void EmitStageAndOperandCycleData(raw_ostream &OS,
- std::vector<std::vector<InstrItinerary> >
+ std::vector<std::vector<InstrItinerary>>
&ProcItinLists);
void EmitItineraries(raw_ostream &OS,
- std::vector<std::vector<InstrItinerary> >
+ std::vector<std::vector<InstrItinerary>>
&ProcItinLists);
- void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
+ void EmitProcessorProp(raw_ostream &OS, const Record *R, StringRef Name,
char Separator);
void EmitProcessorResources(const CodeGenProcModel &ProcModel,
raw_ostream &OS);
@@ -294,7 +297,7 @@ void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
// For each unit
for (unsigned j = 0, M = UnitList.size(); j < M;) {
// Add name and bitwise or
- ItinString += Name + "FU::" + UnitList[j]->getName();
+ ItinString += Name + "FU::" + UnitList[j]->getName().str();
if (++j < M) ItinString += " | ";
}
@@ -341,7 +344,7 @@ void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
unsigned N = BypassList.size();
unsigned i = 0;
for (; i < N;) {
- ItinString += Name + "Bypass::" + BypassList[i]->getName();
+ ItinString += Name + "Bypass::" + BypassList[i]->getName().str();
if (++i < NOperandCycles) ItinString += ", ";
}
for (; i < NOperandCycles;) {
@@ -357,9 +360,8 @@ void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
//
void SubtargetEmitter::
EmitStageAndOperandCycleData(raw_ostream &OS,
- std::vector<std::vector<InstrItinerary> >
+ std::vector<std::vector<InstrItinerary>>
&ProcItinLists) {
-
// Multiple processor models may share an itinerary record. Emit it once.
SmallPtrSet<Record*, 8> ItinsDefSet;
@@ -498,7 +500,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
FindOperandCycle,
- FindOperandCycle + NOperandCycles};
+ FindOperandCycle + NOperandCycles };
// Inject - empty slots will be 0, 0
ItinList[SchedClassIdx] = Intinerary;
@@ -530,13 +532,12 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
//
void SubtargetEmitter::
EmitItineraries(raw_ostream &OS,
- std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
-
+ std::vector<std::vector<InstrItinerary>> &ProcItinLists) {
// Multiple processor models may share an itinerary record. Emit it once.
SmallPtrSet<Record*, 8> ItinsDefSet;
// For each processor's machine model
- std::vector<std::vector<InstrItinerary> >::iterator
+ std::vector<std::vector<InstrItinerary>>::iterator
ProcItinListsIter = ProcItinLists.begin();
for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
@@ -587,7 +588,7 @@ EmitItineraries(raw_ostream &OS,
// value defined in the C++ header. The Record is null if the processor does not
// define a model.
void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
- const char *Name, char Separator) {
+ StringRef Name, char Separator) {
OS << " ";
int V = R ? R->getValueAsInt(Name) : -1;
if (V >= 0)
@@ -783,8 +784,7 @@ void SubtargetEmitter::ExpandProcResources(RecVec &PRVec,
RecVec SuperResources = PR->getValueAsListOfDefs("Resources");
RecIter SubI = SubResources.begin(), SubE = SubResources.end();
for( ; SubI != SubE; ++SubI) {
- if (std::find(SuperResources.begin(), SuperResources.end(), *SubI)
- == SuperResources.end()) {
+ if (!is_contained(SuperResources, *SubI)) {
break;
}
}
@@ -827,9 +827,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
HasVariants = true;
break;
}
- IdxIter PIPos = std::find(TI->ProcIndices.begin(),
- TI->ProcIndices.end(), ProcModel.Index);
- if (PIPos != TI->ProcIndices.end()) {
+ if (is_contained(TI->ProcIndices, ProcModel.Index)) {
HasVariants = true;
break;
}
@@ -844,9 +842,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
// If ProcIndices contains 0, this class applies to all processors.
assert(!SC.ProcIndices.empty() && "expect at least one procidx");
if (SC.ProcIndices[0] != 0) {
- IdxIter PIPos = std::find(SC.ProcIndices.begin(),
- SC.ProcIndices.end(), ProcModel.Index);
- if (PIPos == SC.ProcIndices.end())
+ if (!is_contained(SC.ProcIndices, ProcModel.Index))
continue;
}
IdxVec Writes = SC.Writes;
@@ -873,8 +869,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
// Check this processor's itinerary class resources.
for (Record *I : ProcModel.ItinRWDefs) {
RecVec Matched = I->getValueAsListOfDefs("MatchedItinClasses");
- if (std::find(Matched.begin(), Matched.end(), SC.ItinClassDef)
- != Matched.end()) {
+ if (is_contained(Matched, SC.ItinClassDef)) {
SchedModels.findRWs(I->getValueAsListOfDefs("OperandReadWrites"),
Writes, Reads);
break;
@@ -1246,7 +1241,7 @@ void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
<< "#endif\n";
if (SchedModels.hasItineraries()) {
- std::vector<std::vector<InstrItinerary> > ProcItinLists;
+ std::vector<std::vector<InstrItinerary>> ProcItinLists;
// Emit the stage data
EmitStageAndOperandCycleData(OS, ProcItinLists);
EmitItineraries(OS, ProcItinLists);
@@ -1430,13 +1425,13 @@ void SubtargetEmitter::run(raw_ostream &OS) {
<< Target << "WriteProcResTable, "
<< Target << "WriteLatencyTable, "
<< Target << "ReadAdvanceTable, ";
+ OS << '\n'; OS.indent(22);
if (SchedModels.hasItineraries()) {
- OS << '\n'; OS.indent(22);
OS << Target << "Stages, "
<< Target << "OperandCycles, "
<< Target << "ForwardingPaths";
} else
- OS << "0, 0, 0";
+ OS << "nullptr, nullptr, nullptr";
OS << ");\n}\n\n";
OS << "} // end namespace llvm\n\n";
@@ -1516,7 +1511,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
<< Target << "OperandCycles, "
<< Target << "ForwardingPaths";
} else
- OS << "0, 0, 0";
+ OS << "nullptr, nullptr, nullptr";
OS << ") {}\n\n";
EmitSchedModelHelpers(ClassName, OS);
diff --git a/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
new file mode 100644
index 0000000..7db8813
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
@@ -0,0 +1,119 @@
+//===- SubtargetFeatureInfo.cpp - Helpers for subtarget features ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SubtargetFeatureInfo.h"
+
+#include "Types.h"
+#include "llvm/TableGen/Record.h"
+
+#include <map>
+
+using namespace llvm;
+
+void SubtargetFeatureInfo::dump() const {
+ errs() << getEnumName() << " " << Index << "\n";
+ TheDef->dump();
+}
+
+std::vector<std::pair<Record *, SubtargetFeatureInfo>>
+SubtargetFeatureInfo::getAll(const RecordKeeper &Records) {
+ std::vector<std::pair<Record *, SubtargetFeatureInfo>> SubtargetFeatures;
+ std::vector<Record *> AllPredicates =
+ Records.getAllDerivedDefinitions("Predicate");
+ for (Record *Pred : AllPredicates) {
+ // Ignore predicates that are not intended for the assembler.
+ //
+ // The "AssemblerMatcherPredicate" string should be promoted to an argument
+ // if we re-use the machinery for non-assembler purposes in future.
+ if (!Pred->getValueAsBit("AssemblerMatcherPredicate"))
+ continue;
+
+ if (Pred->getName().empty())
+ PrintFatalError(Pred->getLoc(), "Predicate has no name!");
+
+ SubtargetFeatures.emplace_back(
+ Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size()));
+ }
+ return SubtargetFeatures;
+}
+
+void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
+ raw_ostream &OS) {
+ OS << "// Flags for subtarget features that participate in "
+ << "instruction matching.\n";
+ OS << "enum SubtargetFeatureFlag : "
+ << getMinimalTypeForEnumBitfield(SubtargetFeatures.size()) << " {\n";
+ for (const auto &SF : SubtargetFeatures) {
+ const SubtargetFeatureInfo &SFI = SF.second;
+ OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n";
+ }
+ OS << " Feature_None = 0\n";
+ OS << "};\n\n";
+}
+
+void SubtargetFeatureInfo::emitNameTable(
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
+ raw_ostream &OS) {
+ OS << "static const char *SubtargetFeatureNames[] = {\n";
+ for (const auto &SF : SubtargetFeatures) {
+ const SubtargetFeatureInfo &SFI = SF.second;
+ OS << " \"" << SFI.getEnumName() << "\",\n";
+ }
+ // A small number of targets have no predicates. Null terminate the array to
+ // avoid a zero-length array.
+ OS << " nullptr\n"
+ << "};\n\n";
+}
+
+void SubtargetFeatureInfo::emitComputeAvailableFeatures(
+ StringRef TargetName, StringRef ClassName, StringRef FuncName,
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
+ raw_ostream &OS) {
+ OS << "uint64_t " << TargetName << ClassName << "::\n"
+ << FuncName << "(const FeatureBitset& FB) const {\n";
+ OS << " uint64_t Features = 0;\n";
+ for (const auto &SF : SubtargetFeatures) {
+ const SubtargetFeatureInfo &SFI = SF.second;
+
+ OS << " if (";
+ std::string CondStorage =
+ SFI.TheDef->getValueAsString("AssemblerCondString");
+ StringRef Conds = CondStorage;
+ std::pair<StringRef, StringRef> Comma = Conds.split(',');
+ bool First = true;
+ do {
+ if (!First)
+ OS << " && ";
+
+ bool Neg = false;
+ StringRef Cond = Comma.first;
+ if (Cond[0] == '!') {
+ Neg = true;
+ Cond = Cond.substr(1);
+ }
+
+ OS << "(";
+ if (Neg)
+ OS << "!";
+ OS << "FB[" << TargetName << "::" << Cond << "])";
+
+ if (Comma.second.empty())
+ break;
+
+ First = false;
+ Comma = Comma.second.split(',');
+ } while (true);
+
+ OS << ")\n";
+ OS << " Features |= " << SFI.getEnumName() << ";\n";
+ }
+ OS << " return Features;\n";
+ OS << "}\n\n";
+}
diff --git a/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h
new file mode 100644
index 0000000..99f380f
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h
@@ -0,0 +1,72 @@
+//===- SubtargetFeatureInfo.h - Helpers for subtarget features ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H
+#define LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H
+
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace llvm {
+class Record;
+class RecordKeeper;
+
+/// Helper class for storing information on a subtarget feature which
+/// participates in instruction matching.
+struct SubtargetFeatureInfo {
+ /// \brief The predicate record for this feature.
+ Record *TheDef;
+
+ /// \brief An unique index assigned to represent this feature.
+ uint64_t Index;
+
+ SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {}
+
+ /// \brief The name of the enumerated constant identifying this feature.
+ std::string getEnumName() const {
+ return "Feature_" + TheDef->getName().str();
+ }
+
+ void dump() const;
+ static std::vector<std::pair<Record *, SubtargetFeatureInfo>>
+ getAll(const RecordKeeper &Records);
+
+ /// Emit the subtarget feature flag definitions.
+ static void emitSubtargetFeatureFlagEnumeration(
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
+ &SubtargetFeatures,
+ raw_ostream &OS);
+
+ static void emitNameTable(std::map<Record *, SubtargetFeatureInfo,
+ LessRecordByID> &SubtargetFeatures,
+ raw_ostream &OS);
+
+ /// Emit the function to compute the list of available features given a
+ /// subtarget.
+ ///
+ /// \param TargetName The name of the target as used in class prefixes (e.g.
+ /// <TargetName>Subtarget)
+ /// \param ClassName The name of the class (without the <Target> prefix)
+ /// that will contain the generated functions.
+ /// \param FuncName The name of the function to emit.
+ /// \param SubtargetFeatures A map of TableGen records to the
+ /// SubtargetFeatureInfo equivalent.
+ static void emitComputeAvailableFeatures(
+ StringRef TargetName, StringRef ClassName, StringRef FuncName,
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
+ &SubtargetFeatures,
+ raw_ostream &OS);
+};
+} // end namespace llvm
+
+#endif // LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H
diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp
index 24dbe5d..79a7731 100644
--- a/contrib/llvm/utils/TableGen/TableGen.cpp
+++ b/contrib/llvm/utils/TableGen/TableGen.cpp
@@ -45,6 +45,7 @@ enum ActionType {
GenCTags,
GenAttributes,
GenSearchableTables,
+ GenGlobalISel,
};
namespace {
@@ -92,7 +93,8 @@ namespace {
"Generate attributes"),
clEnumValN(GenSearchableTables, "gen-searchable-tables",
"Generate generic binary-searchable table"),
- clEnumValEnd));
+ clEnumValN(GenGlobalISel, "gen-global-isel",
+ "Generate GlobalISel selector")));
cl::opt<std::string>
Class("class", cl::desc("Print Enum list for this class"),
@@ -178,6 +180,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenSearchableTables:
EmitSearchableTables(Records, OS);
break;
+ case GenGlobalISel:
+ EmitGlobalISel(Records, OS);
+ break;
}
return false;
diff --git a/contrib/llvm/utils/TableGen/TableGenBackends.h b/contrib/llvm/utils/TableGen/TableGenBackends.h
index 51e017f..eb306d2 100644
--- a/contrib/llvm/utils/TableGen/TableGenBackends.h
+++ b/contrib/llvm/utils/TableGen/TableGenBackends.h
@@ -80,6 +80,7 @@ void EmitOptParser(RecordKeeper &RK, raw_ostream &OS);
void EmitCTags(RecordKeeper &RK, raw_ostream &OS);
void EmitAttributes(RecordKeeper &RK, raw_ostream &OS);
void EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS);
+void EmitGlobalISel(RecordKeeper &RK, raw_ostream &OS);
} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/Types.cpp b/contrib/llvm/utils/TableGen/Types.cpp
new file mode 100644
index 0000000..3545829
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/Types.cpp
@@ -0,0 +1,44 @@
+//===- Types.cpp - Helper for the selection of C++ data types. ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Types.h"
+
+// For LLVM_ATTRIBUTE_UNUSED
+#include "llvm/Support/Compiler.h"
+
+#include <cassert>
+
+using namespace llvm;
+
+const char *llvm::getMinimalTypeForRange(uint64_t Range, unsigned MaxSize LLVM_ATTRIBUTE_UNUSED) {
+ // TODO: The original callers only used 32 and 64 so these are the only
+ // values permitted. Rather than widen the supported values we should
+ // allow 64 for the callers that currently use 32 and remove the
+ // argument altogether.
+ assert((MaxSize == 32 || MaxSize == 64) && "Unexpected size");
+ assert(MaxSize <= 64 && "Unexpected size");
+ assert(((MaxSize > 32) ? Range <= 0xFFFFFFFFFFFFFFFFULL
+ : Range <= 0xFFFFFFFFULL) &&
+ "Enum too large");
+
+ if (Range > 0xFFFFFFFFULL)
+ return "uint64_t";
+ if (Range > 0xFFFF)
+ return "uint32_t";
+ if (Range > 0xFF)
+ return "uint16_t";
+ return "uint8_t";
+}
+
+const char *llvm::getMinimalTypeForEnumBitfield(uint64_t Size) {
+ uint64_t MaxIndex = Size;
+ if (MaxIndex > 0)
+ MaxIndex--;
+ return getMinimalTypeForRange(1ULL << MaxIndex);
+}
diff --git a/contrib/llvm/utils/TableGen/Types.h b/contrib/llvm/utils/TableGen/Types.h
new file mode 100644
index 0000000..d511b7e
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/Types.h
@@ -0,0 +1,25 @@
+//===- Types.h - Helper for the selection of C++ types. ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_TYPES_H
+#define LLVM_UTILS_TABLEGEN_TYPES_H
+
+#include <cstdint>
+
+namespace llvm {
+/// Returns the smallest unsigned integer type that can hold the given range.
+/// MaxSize indicates the largest size of integer to consider (in bits) and only
+/// supports values of at least 32.
+const char *getMinimalTypeForRange(uint64_t Range, unsigned MaxSize = 64);
+
+/// Returns the smallest unsigned integer type that can hold the given bitfield.
+const char *getMinimalTypeForEnumBitfield(uint64_t Size);
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
index ca937d0..4736c4e 100644
--- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -23,96 +23,100 @@
using namespace llvm;
#define MRM_MAPPING \
- MAP(C0, 32) \
- MAP(C1, 33) \
- MAP(C2, 34) \
- MAP(C3, 35) \
- MAP(C4, 36) \
- 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)
+ MAP(C0, 64) \
+ MAP(C1, 65) \
+ MAP(C2, 66) \
+ MAP(C3, 67) \
+ MAP(C4, 68) \
+ MAP(C5, 69) \
+ MAP(C6, 70) \
+ MAP(C7, 71) \
+ MAP(C8, 72) \
+ MAP(C9, 73) \
+ MAP(CA, 74) \
+ MAP(CB, 75) \
+ MAP(CC, 76) \
+ MAP(CD, 77) \
+ MAP(CE, 78) \
+ MAP(CF, 79) \
+ MAP(D0, 80) \
+ MAP(D1, 81) \
+ MAP(D2, 82) \
+ MAP(D3, 83) \
+ MAP(D4, 84) \
+ MAP(D5, 85) \
+ MAP(D6, 86) \
+ MAP(D7, 87) \
+ MAP(D8, 88) \
+ MAP(D9, 89) \
+ MAP(DA, 90) \
+ MAP(DB, 91) \
+ MAP(DC, 92) \
+ MAP(DD, 93) \
+ MAP(DE, 94) \
+ MAP(DF, 95) \
+ MAP(E0, 96) \
+ MAP(E1, 97) \
+ MAP(E2, 98) \
+ MAP(E3, 99) \
+ MAP(E4, 100) \
+ MAP(E5, 101) \
+ MAP(E6, 102) \
+ MAP(E7, 103) \
+ MAP(E8, 104) \
+ MAP(E9, 105) \
+ MAP(EA, 106) \
+ MAP(EB, 107) \
+ MAP(EC, 108) \
+ MAP(ED, 109) \
+ MAP(EE, 110) \
+ MAP(EF, 111) \
+ MAP(F0, 112) \
+ MAP(F1, 113) \
+ MAP(F2, 114) \
+ MAP(F3, 115) \
+ MAP(F4, 116) \
+ MAP(F5, 117) \
+ MAP(F6, 118) \
+ MAP(F7, 119) \
+ MAP(F8, 120) \
+ MAP(F9, 121) \
+ MAP(FA, 122) \
+ MAP(FB, 123) \
+ MAP(FC, 124) \
+ MAP(FD, 125) \
+ MAP(FE, 126) \
+ MAP(FF, 127)
// A clone of X86 since we can't depend on something that is generated.
namespace X86Local {
enum {
- Pseudo = 0,
- RawFrm = 1,
- AddRegFrm = 2,
- MRMDestReg = 3,
- MRMDestMem = 4,
- MRMSrcReg = 5,
- MRMSrcMem = 6,
- RawFrmMemOffs = 7,
- RawFrmSrc = 8,
- RawFrmDst = 9,
- RawFrmDstSrc = 10,
- RawFrmImm8 = 11,
- RawFrmImm16 = 12,
- MRMXr = 14, MRMXm = 15,
- MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19,
- MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23,
- MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27,
- MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31,
+ Pseudo = 0,
+ RawFrm = 1,
+ AddRegFrm = 2,
+ RawFrmMemOffs = 3,
+ RawFrmSrc = 4,
+ RawFrmDst = 5,
+ RawFrmDstSrc = 6,
+ RawFrmImm8 = 7,
+ RawFrmImm16 = 8,
+ MRMDestMem = 32,
+ MRMSrcMem = 33,
+ MRMSrcMem4VOp3 = 34,
+ MRMSrcMemOp4 = 35,
+ MRMXm = 39,
+ MRM0m = 40, MRM1m = 41, MRM2m = 42, MRM3m = 43,
+ MRM4m = 44, MRM5m = 45, MRM6m = 46, MRM7m = 47,
+ MRMDestReg = 48,
+ MRMSrcReg = 49,
+ MRMSrcReg4VOp3 = 50,
+ MRMSrcRegOp4 = 51,
+ MRMXr = 55,
+ MRM0r = 56, MRM1r = 57, MRM2r = 58, MRM3r = 59,
+ MRM4r = 60, MRM5r = 61, MRM6r = 62, MRM7r = 63,
#define MAP(from, to) MRM_##from = to,
MRM_MAPPING
#undef MAP
- lastMRM
};
enum {
@@ -138,19 +142,6 @@ namespace X86Local {
using namespace X86Disassembler;
-/// isRegFormat - Indicates whether a particular form requires the Mod field of
-/// the ModR/M byte to be 0b11.
-///
-/// @param form - The form of the instruction.
-/// @return - true if the form implies that Mod must be 0b11, false
-/// otherwise.
-static bool isRegFormat(uint8_t form) {
- return (form == X86Local::MRMDestReg ||
- form == X86Local::MRMSrcReg ||
- form == X86Local::MRMXr ||
- (form >= X86Local::MRM0r && form <= X86Local::MRM7r));
-}
-
/// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit.
/// Useful for switch statements and the like.
///
@@ -212,9 +203,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
AdSize = byteFromRec(Rec, "AdSizeBits");
HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
HasVEX_4V = Rec->getValueAsBit("hasVEX_4V");
- HasVEX_4VOp3 = Rec->getValueAsBit("hasVEX_4VOp3");
HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix");
- HasMemOp4Prefix = Rec->getValueAsBit("hasMemOp4Prefix");
IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2");
HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
@@ -565,7 +554,7 @@ void RecognizableInstr::emitInstructionSpecifier() {
// Given the set of prefix bits, how many additional operands does the
// instruction have?
unsigned additionalOperands = 0;
- if (HasVEX_4V || HasVEX_4VOp3)
+ if (HasVEX_4V)
++additionalOperands;
if (HasEVEX_K)
++additionalOperands;
@@ -666,19 +655,27 @@ void RecognizableInstr::emitInstructionSpecifier() {
// in ModRMVEX and the one above the one in the VEX.VVVV field
HANDLE_OPERAND(vvvvRegister)
- if (HasMemOp4Prefix)
- HANDLE_OPERAND(immediate)
-
HANDLE_OPERAND(rmRegister)
-
- if (HasVEX_4VOp3)
- HANDLE_OPERAND(vvvvRegister)
-
- if (!HasMemOp4Prefix)
- HANDLE_OPTIONAL(immediate)
+ HANDLE_OPTIONAL(immediate)
HANDLE_OPTIONAL(immediate) // above might be a register in 7:4
HANDLE_OPTIONAL(immediate)
break;
+ case X86Local::MRMSrcReg4VOp3:
+ assert(numPhysicalOperands == 3 &&
+ "Unexpected number of operands for MRMSrcRegFrm");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(rmRegister)
+ HANDLE_OPERAND(vvvvRegister)
+ break;
+ case X86Local::MRMSrcRegOp4:
+ assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 &&
+ "Unexpected number of operands for MRMSrcRegOp4Frm");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(vvvvRegister)
+ HANDLE_OPERAND(immediate) // Register in imm[7:4]
+ HANDLE_OPERAND(rmRegister)
+ HANDLE_OPTIONAL(immediate)
+ break;
case X86Local::MRMSrcMem:
// Operand 1 is a register operand in the Reg/Opcode field.
// Operand 2 is a memory operand (possibly SIB-extended)
@@ -699,18 +696,26 @@ void RecognizableInstr::emitInstructionSpecifier() {
// in ModRMVEX and the one above the one in the VEX.VVVV field
HANDLE_OPERAND(vvvvRegister)
- if (HasMemOp4Prefix)
- HANDLE_OPERAND(immediate)
-
HANDLE_OPERAND(memory)
-
- if (HasVEX_4VOp3)
- HANDLE_OPERAND(vvvvRegister)
-
- if (!HasMemOp4Prefix)
- HANDLE_OPTIONAL(immediate)
+ HANDLE_OPTIONAL(immediate)
HANDLE_OPTIONAL(immediate) // above might be a register in 7:4
break;
+ case X86Local::MRMSrcMem4VOp3:
+ assert(numPhysicalOperands == 3 &&
+ "Unexpected number of operands for MRMSrcMemFrm");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(memory)
+ HANDLE_OPERAND(vvvvRegister)
+ break;
+ case X86Local::MRMSrcMemOp4:
+ assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 &&
+ "Unexpected number of operands for MRMSrcMemOp4Frm");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(vvvvRegister)
+ HANDLE_OPERAND(immediate) // Register in imm[7:4]
+ HANDLE_OPERAND(memory)
+ HANDLE_OPTIONAL(immediate)
+ break;
case X86Local::MRMXr:
case X86Local::MRM0r:
case X86Local::MRM1r:
@@ -841,13 +846,31 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
}
switch (Form) {
- default:
+ default: llvm_unreachable("Invalid form!");
+ case X86Local::Pseudo: llvm_unreachable("Pseudo should not be emitted!");
+ case X86Local::RawFrm:
+ case X86Local::AddRegFrm:
+ case X86Local::RawFrmMemOffs:
+ case X86Local::RawFrmSrc:
+ case X86Local::RawFrmDst:
+ case X86Local::RawFrmDstSrc:
+ case X86Local::RawFrmImm8:
+ case X86Local::RawFrmImm16:
filter = new DumbFilter();
break;
- case X86Local::MRMDestReg: case X86Local::MRMDestMem:
- case X86Local::MRMSrcReg: case X86Local::MRMSrcMem:
- case X86Local::MRMXr: case X86Local::MRMXm:
- filter = new ModFilter(isRegFormat(Form));
+ case X86Local::MRMDestReg:
+ case X86Local::MRMSrcReg:
+ case X86Local::MRMSrcReg4VOp3:
+ case X86Local::MRMSrcRegOp4:
+ case X86Local::MRMXr:
+ filter = new ModFilter(true);
+ break;
+ case X86Local::MRMDestMem:
+ case X86Local::MRMSrcMem:
+ case X86Local::MRMSrcMem4VOp3:
+ case X86Local::MRMSrcMemOp4:
+ case X86Local::MRMXm:
+ filter = new ModFilter(false);
break;
case X86Local::MRM0r: case X86Local::MRM1r:
case X86Local::MRM2r: case X86Local::MRM3r:
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
index f6f5006..2e61158 100644
--- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
@@ -55,14 +55,10 @@ private:
bool HasREX_WPrefix;
/// The hasVEX_4V field from the record
bool HasVEX_4V;
- /// The hasVEX_4VOp3 field from the record
- bool HasVEX_4VOp3;
/// The hasVEX_WPrefix field from the record
bool HasVEX_WPrefix;
/// Inferred from the operands; indicates whether the L bit in the VEX prefix is set
bool HasVEX_LPrefix;
- /// The hasMemOp4Prefix field from the record
- bool HasMemOp4Prefix;
/// The ignoreVEX_L field from the record
bool IgnoresVEX_L;
/// The hasEVEX_L2Prefix field from the record
OpenPOWER on IntegriCloud