aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp246
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp26
-rw-r--r--utils/TableGen/AsmWriterInst.cpp40
-rw-r--r--utils/TableGen/AsmWriterInst.h7
-rw-r--r--utils/TableGen/Attributes.cpp7
-rw-r--r--utils/TableGen/CTagsEmitter.cpp7
-rw-r--r--utils/TableGen/CallingConvEmitter.cpp51
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp106
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp110
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h25
-rw-r--r--utils/TableGen/CodeGenHwModes.cpp7
-rw-r--r--utils/TableGen/CodeGenHwModes.h7
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp79
-rw-r--r--utils/TableGen/CodeGenInstruction.h8
-rw-r--r--utils/TableGen/CodeGenIntrinsics.h20
-rw-r--r--utils/TableGen/CodeGenMapTable.cpp7
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp15
-rw-r--r--utils/TableGen/CodeGenRegisters.h7
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp52
-rw-r--r--utils/TableGen/CodeGenSchedule.h7
-rw-r--r--utils/TableGen/CodeGenTarget.cpp100
-rw-r--r--utils/TableGen/CodeGenTarget.h7
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp7
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp31
-rw-r--r--utils/TableGen/DAGISelMatcher.h66
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp27
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp60
-rw-r--r--utils/TableGen/DAGISelMatcherOpt.cpp15
-rw-r--r--utils/TableGen/DFAPacketizerEmitter.cpp7
-rw-r--r--utils/TableGen/DisassemblerEmitter.cpp7
-rw-r--r--utils/TableGen/ExegesisEmitter.cpp7
-rw-r--r--utils/TableGen/FastISelEmitter.cpp7
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp147
-rw-r--r--utils/TableGen/GlobalISelEmitter.cpp157
-rw-r--r--utils/TableGen/InfoByHwMode.cpp14
-rw-r--r--utils/TableGen/InfoByHwMode.h13
-rw-r--r--utils/TableGen/InstrDocsEmitter.cpp7
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp89
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp120
-rw-r--r--utils/TableGen/OptParserEmitter.cpp7
-rw-r--r--utils/TableGen/PredicateExpander.cpp7
-rw-r--r--utils/TableGen/PredicateExpander.h7
-rw-r--r--utils/TableGen/PseudoLoweringEmitter.cpp7
-rw-r--r--utils/TableGen/RISCVCompressInstEmitter.cpp59
-rw-r--r--utils/TableGen/RegisterBankEmitter.cpp7
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp7
-rw-r--r--utils/TableGen/SDNodeProperties.cpp13
-rw-r--r--utils/TableGen/SDNodeProperties.h7
-rw-r--r--utils/TableGen/SearchableTableEmitter.cpp35
-rw-r--r--utils/TableGen/SequenceToOffsetTable.h7
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp140
-rw-r--r--utils/TableGen/SubtargetFeatureInfo.cpp27
-rw-r--r--utils/TableGen/SubtargetFeatureInfo.h16
-rw-r--r--utils/TableGen/TableGen.cpp18
-rw-r--r--utils/TableGen/TableGenBackends.h7
-rw-r--r--utils/TableGen/Types.cpp7
-rw-r--r--utils/TableGen/Types.h7
-rw-r--r--utils/TableGen/WebAssemblyDisassemblerEmitter.cpp38
-rw-r--r--utils/TableGen/WebAssemblyDisassemblerEmitter.h7
-rw-r--r--utils/TableGen/X86DisassemblerShared.h7
-rw-r--r--utils/TableGen/X86DisassemblerTables.cpp81
-rw-r--r--utils/TableGen/X86DisassemblerTables.h7
-rw-r--r--utils/TableGen/X86EVEX2VEXTablesEmitter.cpp64
-rw-r--r--utils/TableGen/X86FoldTablesEmitter.cpp71
-rw-r--r--utils/TableGen/X86ModRMFilters.cpp7
-rw-r--r--utils/TableGen/X86ModRMFilters.h7
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp128
-rw-r--r--utils/TableGen/X86RecognizableInstr.h24
68 files changed, 1663 insertions, 885 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 5b4229e64682..146d10835b8d 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -1,9 +1,8 @@
//===- AsmMatcherEmitter.cpp - Generate an assembly matcher ---------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -1073,8 +1072,9 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool IsAlias) const {
// handle, the target should be refactored to use operands instead of
// modifiers.
//
- // Also, check for instructions which reference the operand multiple times;
- // this implies a constraint we would not honor.
+ // Also, check for instructions which reference the operand multiple times,
+ // if they don't define a custom AsmMatcher: this implies a constraint that
+ // the built-in matching code would not honor.
std::set<std::string> OperandNames;
for (const AsmOperand &Op : AsmOperands) {
StringRef Tok = Op.Token;
@@ -1084,7 +1084,8 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool IsAlias) const {
"' not supported by asm matcher. Mark isCodeGenOnly!");
// Verify that any operand is only mentioned once.
// We reject aliases and ignore instructions for now.
- if (!IsAlias && Tok[0] == '$' && !OperandNames.insert(Tok).second) {
+ if (!IsAlias && TheDef->getValueAsString("AsmMatchConverter").empty() &&
+ Tok[0] == '$' && !OperandNames.insert(Tok).second) {
LLVM_DEBUG({
errs() << "warning: '" << TheDef->getName() << "': "
<< "ignoring instruction with tied operand '"
@@ -1160,8 +1161,9 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {
// use it, else just fall back to the underlying register class.
const RecordVal *R = Rec->getValue("ParserMatchClass");
if (!R || !R->getValue())
- PrintFatalError("Record `" + Rec->getName() +
- "' does not have a ParserMatchClass!\n");
+ PrintFatalError(Rec->getLoc(),
+ "Record `" + Rec->getName() +
+ "' does not have a ParserMatchClass!\n");
if (DefInit *DI= dyn_cast<DefInit>(R->getValue())) {
Record *MatchClass = DI->getDef();
@@ -1473,7 +1475,6 @@ void AsmMatcherInfo::buildInfo() {
for (const auto &Pair : SubtargetFeatures)
LLVM_DEBUG(Pair.second.dump());
#endif // NDEBUG
- assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!");
bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");
bool ReportMultipleNearMisses =
@@ -1928,10 +1929,11 @@ getConverterOperandID(const std::string &Name,
return ID;
}
-static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
- std::vector<std::unique_ptr<MatchableInfo>> &Infos,
- bool HasMnemonicFirst, bool HasOptionalOperands,
- raw_ostream &OS) {
+static unsigned
+emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
+ std::vector<std::unique_ptr<MatchableInfo>> &Infos,
+ bool HasMnemonicFirst, bool HasOptionalOperands,
+ raw_ostream &OS) {
SmallSetVector<CachedHashString, 16> OperandConversionKinds;
SmallSetVector<CachedHashString, 16> InstructionConversionKinds;
std::vector<std::vector<uint8_t> > ConversionTable;
@@ -2337,6 +2339,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Spit out the operand number lookup function.
OS << OpOS.str();
+
+ return ConversionTable.size();
}
/// emitMatchClassEnumeration - Emit the enumeration for match class kinds.
@@ -2675,7 +2679,7 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
for (const auto &SF : Info.SubtargetFeatures) {
const SubtargetFeatureInfo &SFI = SF.second;
// FIXME: Totally just a placeholder name to get the algorithm working.
- OS << " case " << SFI.getEnumName() << ": return \""
+ OS << " case " << SFI.getEnumBitName() << ": return \""
<< SFI.TheDef->getValueAsString("PredicateName") << "\";\n";
}
OS << " default: return \"(unknown)\";\n";
@@ -2691,7 +2695,10 @@ static std::string GetAliasRequiredFeatures(Record *R,
const AsmMatcherInfo &Info) {
std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates");
std::string Result;
- unsigned NumFeatures = 0;
+
+ if (ReqFeatures.empty())
+ return Result;
+
for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {
const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
@@ -2699,15 +2706,12 @@ static std::string GetAliasRequiredFeatures(Record *R,
PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() +
"' is not marked as an AssemblerPredicate!");
- if (NumFeatures)
- Result += '|';
+ if (i)
+ Result += " && ";
- Result += F->getEnumName();
- ++NumFeatures;
+ Result += "Features.test(" + F->getEnumBitName() + ')';
}
- if (NumFeatures > 1)
- Result = '(' + Result + ')';
return Result;
}
@@ -2763,7 +2767,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
if (!MatchCode.empty())
MatchCode += "else ";
- MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n";
+ MatchCode += "if (" + FeatureMask + ")\n";
MatchCode += " Mnemonic = \"";
MatchCode += R->getValueAsString("ToMnemonic");
MatchCode += "\";\n";
@@ -2798,7 +2802,7 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info,
if (Aliases.empty()) return false;
OS << "static void applyMnemonicAliases(StringRef &Mnemonic, "
- "uint64_t Features, unsigned VariantID) {\n";
+ "const FeatureBitset &Features, unsigned VariantID) {\n";
OS << " switch (VariantID) {\n";
unsigned VariantCount = Target.getAsmParserVariantCount();
for (unsigned VC = 0; VC != VariantCount; ++VC) {
@@ -2823,7 +2827,9 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info,
static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
const AsmMatcherInfo &Info, StringRef ClassName,
StringToOffsetTable &StringTable,
- unsigned MaxMnemonicIndex, bool HasMnemonicFirst) {
+ unsigned MaxMnemonicIndex,
+ unsigned MaxFeaturesIndex,
+ bool HasMnemonicFirst) {
unsigned MaxMask = 0;
for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) {
MaxMask |= OMI.OperandMask;
@@ -2832,14 +2838,14 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit the static custom operand parsing table;
OS << "namespace {\n";
OS << " struct OperandMatchEntry {\n";
- OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size())
- << " RequiredFeatures;\n";
OS << " " << getMinimalTypeForRange(MaxMnemonicIndex)
<< " Mnemonic;\n";
+ OS << " " << getMinimalTypeForRange(MaxMask)
+ << " OperandMask;\n";
OS << " " << getMinimalTypeForRange(std::distance(
Info.Classes.begin(), Info.Classes.end())) << " Class;\n";
- OS << " " << getMinimalTypeForRange(MaxMask)
- << " OperandMask;\n\n";
+ OS << " " << getMinimalTypeForRange(MaxFeaturesIndex)
+ << " RequiredFeaturesIdx;\n\n";
OS << " StringRef getMnemonic() const {\n";
OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n";
OS << " MnemonicTable[Mnemonic]);\n";
@@ -2865,29 +2871,18 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
OS << "static const OperandMatchEntry OperandMatchTable["
<< Info.OperandMatchInfo.size() << "] = {\n";
- OS << " /* Operand List Mask, Mnemonic, Operand Class, Features */\n";
+ OS << " /* Operand List Mnemonic, Mask, Operand Class, Features */\n";
for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) {
const MatchableInfo &II = *OMI.MI;
OS << " { ";
- // Write the required features mask.
- if (!II.RequiredFeatures.empty()) {
- for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) {
- if (i) OS << "|";
- OS << II.RequiredFeatures[i]->getEnumName();
- }
- } else
- OS << "0";
-
// Store a pascal-style length byte in the mnemonic.
std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str();
- OS << ", " << StringTable.GetOrAddStringOffset(LenMnemonic, false)
+ OS << StringTable.GetOrAddStringOffset(LenMnemonic, false)
<< " /* " << II.Mnemonic << " */, ";
- OS << OMI.CI->Name;
-
- OS << ", " << OMI.OperandMask;
+ OS << OMI.OperandMask;
OS << " /* ";
bool printComma = false;
for (int i = 0, e = 31; i !=e; ++i)
@@ -2897,7 +2892,17 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
OS << i;
printComma = true;
}
- OS << " */";
+ OS << " */, ";
+
+ OS << OMI.CI->Name;
+
+ // Write the required features mask.
+ OS << ", AMFBS";
+ if (II.RequiredFeatures.empty())
+ OS << "_None";
+ else
+ for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i)
+ OS << '_' << II.RequiredFeatures[i]->TheDef->getName();
OS << " },\n";
}
@@ -2933,7 +2938,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit code to get the available features.
OS << " // Get the current feature set.\n";
- OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n";
+ OS << " const FeatureBitset &AvailableFeatures = getAvailableFeatures();\n\n";
OS << " // Get the next operand index.\n";
OS << " unsigned NextOpNum = Operands.size()"
@@ -2967,8 +2972,10 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit check that the required features are available.
OS << " // check if the available features match\n";
+ OS << " const FeatureBitset &RequiredFeatures = "
+ "FeatureBitsets[it->RequiredFeaturesIdx];\n";
OS << " if (!ParseForAllFeatures && (AvailableFeatures & "
- "it->RequiredFeatures) != it->RequiredFeatures)\n";
+ "RequiredFeatures) != RequiredFeatures)\n";
OS << " continue;\n\n";
// Emit check to ensure the operand number matches.
@@ -3034,7 +3041,8 @@ static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
static void emitMnemonicSpellChecker(raw_ostream &OS, CodeGenTarget &Target,
unsigned VariantCount) {
OS << "static std::string " << Target.getName()
- << "MnemonicSpellCheck(StringRef S, uint64_t FBS, unsigned VariantID) {\n";
+ << "MnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,"
+ << " unsigned VariantID) {\n";
if (!VariantCount)
OS << " return \"\";";
else {
@@ -3055,7 +3063,9 @@ static void emitMnemonicSpellChecker(raw_ostream &OS, CodeGenTarget &Target,
OS << " }\n\n";
OS << " for (auto I = Start; I < End; I++) {\n";
OS << " // Ignore unsupported instructions.\n";
- OS << " if ((FBS & I->RequiredFeatures) != I->RequiredFeatures)\n";
+ OS << " const FeatureBitset &RequiredFeatures = "
+ "FeatureBitsets[I->RequiredFeaturesIdx];\n";
+ OS << " if ((FBS & RequiredFeatures) != RequiredFeatures)\n";
OS << " continue;\n";
OS << "\n";
OS << " StringRef T = I->getMnemonic();\n";
@@ -3103,6 +3113,14 @@ static void emitMatchClassKindNames(std::forward_list<ClassInfo> &Infos,
OS << "#endif // NDEBUG\n";
}
+static std::string
+getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset) {
+ std::string Name = "AMFBS";
+ for (const auto &Feature : FeatureBitset)
+ Name += ("_" + Feature->getName()).str();
+ return Name;
+}
+
void AsmMatcherEmitter::run(raw_ostream &OS) {
CodeGenTarget Target(Records);
Record *AsmParser = Target.getAsmParser();
@@ -3115,10 +3133,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Sort the instruction table using the partial order on classes. We use
// stable_sort to ensure that ambiguous instructions are still
// deterministically ordered.
- std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(),
- [](const std::unique_ptr<MatchableInfo> &a,
- const std::unique_ptr<MatchableInfo> &b){
- return *a < *b;});
+ llvm::stable_sort(
+ Info.Matchables,
+ [](const std::unique_ptr<MatchableInfo> &a,
+ const std::unique_ptr<MatchableInfo> &b) { return *a < *b; });
#ifdef EXPENSIVE_CHECKS
// Verify that the table is sorted and operator < works transitively.
@@ -3174,7 +3192,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "#undef GET_ASSEMBLER_HEADER\n";
OS << " // This should be included into the middle of the declaration of\n";
OS << " // your subclasses implementation of MCTargetAsmParser.\n";
- OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n";
+ OS << " FeatureBitset ComputeAvailableFeatures(const FeatureBitset& FB) const;\n";
if (HasOptionalOperands) {
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
@@ -3192,9 +3210,21 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (ReportMultipleNearMisses)
OS << " SmallVectorImpl<NearMissInfo> *NearMisses,\n";
else
- OS << " uint64_t &ErrorInfo,\n";
+ OS << " uint64_t &ErrorInfo,\n"
+ << " FeatureBitset &MissingFeatures,\n";
OS << " bool matchingInlineAsm,\n"
<< " unsigned VariantID = 0);\n";
+ if (!ReportMultipleNearMisses)
+ OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n"
+ << " MCInst &Inst,\n"
+ << " uint64_t &ErrorInfo,\n"
+ << " bool matchingInlineAsm,\n"
+ << " unsigned VariantID = 0) {\n"
+ << " FeatureBitset MissingFeatures;\n"
+ << " return MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,\n"
+ << " matchingInlineAsm, VariantID);\n"
+ << " }\n\n";
+
if (!Info.OperandMatchInfo.empty()) {
OS << " OperandMatchResultTy MatchOperandParserImpl(\n";
@@ -3219,7 +3249,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "#undef GET_REGISTER_MATCHER\n\n";
// Emit the subtarget feature enumeration.
- SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
+ SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(
Info.SubtargetFeatures, OS);
// Emit the function to match a register name to number.
@@ -3249,8 +3279,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Generate the convertToMCInst function to convert operands into an MCInst.
// Also, generate the convertToMapAndConstraints function for MS-style inline
// assembly. The latter doesn't actually generate a MCInst.
- emitConvertFuncs(Target, ClassName, Info.Matchables, HasMnemonicFirst,
- HasOptionalOperands, OS);
+ unsigned NumConverters = emitConvertFuncs(Target, ClassName, Info.Matchables,
+ HasMnemonicFirst,
+ HasOptionalOperands, OS);
// Emit the enumeration for classes which participate in matching.
emitMatchClassEnumeration(Target, Info.Classes, OS);
@@ -3300,6 +3331,56 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
StringTable.EmitString(OS);
OS << ";\n\n";
+ std::vector<std::vector<Record *>> FeatureBitsets;
+ for (const auto &MI : Info.Matchables) {
+ if (MI->RequiredFeatures.empty())
+ continue;
+ FeatureBitsets.emplace_back();
+ for (unsigned I = 0, E = MI->RequiredFeatures.size(); I != E; ++I)
+ FeatureBitsets.back().push_back(MI->RequiredFeatures[I]->TheDef);
+ }
+
+ llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A,
+ const std::vector<Record *> &B) {
+ if (A.size() < B.size())
+ return true;
+ if (A.size() > B.size())
+ return false;
+ for (const auto &Pair : zip(A, B)) {
+ if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName())
+ return true;
+ if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName())
+ return false;
+ }
+ return false;
+ });
+ FeatureBitsets.erase(
+ std::unique(FeatureBitsets.begin(), FeatureBitsets.end()),
+ FeatureBitsets.end());
+ OS << "// Feature bitsets.\n"
+ << "enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n"
+ << " AMFBS_None,\n";
+ for (const auto &FeatureBitset : FeatureBitsets) {
+ if (FeatureBitset.empty())
+ continue;
+ OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
+ }
+ OS << "};\n\n"
+ << "const static FeatureBitset FeatureBitsets[] {\n"
+ << " {}, // AMFBS_None\n";
+ for (const auto &FeatureBitset : FeatureBitsets) {
+ if (FeatureBitset.empty())
+ continue;
+ OS << " {";
+ for (const auto &Feature : FeatureBitset) {
+ const auto &I = Info.SubtargetFeatures.find(Feature);
+ assert(I != Info.SubtargetFeatures.end() && "Didn't import predicate?");
+ OS << I->second.getEnumBitName() << ", ";
+ }
+ OS << "},\n";
+ }
+ OS << "};\n\n";
+
// Emit the static match table; unused classes get initialized to 0 which is
// guaranteed to be InvalidMatchClass.
//
@@ -3315,10 +3396,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " " << getMinimalTypeForRange(MaxMnemonicIndex)
<< " Mnemonic;\n";
OS << " uint16_t Opcode;\n";
- OS << " " << getMinimalTypeForRange(Info.Matchables.size())
+ OS << " " << getMinimalTypeForRange(NumConverters)
<< " ConvertFn;\n";
- OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size())
- << " RequiredFeatures;\n";
+ OS << " " << getMinimalTypeForRange(FeatureBitsets.size())
+ << " RequiredFeaturesIdx;\n";
OS << " " << getMinimalTypeForRange(
std::distance(Info.Classes.begin(), Info.Classes.end()))
<< " Classes[" << MaxNumOperands << "];\n";
@@ -3363,13 +3444,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< MI->ConversionFnKind << ", ";
// Write the required features mask.
- if (!MI->RequiredFeatures.empty()) {
- for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i) {
- if (i) OS << "|";
- OS << MI->RequiredFeatures[i]->getEnumName();
- }
- } else
- OS << "0";
+ OS << "AMFBS";
+ if (MI->RequiredFeatures.empty())
+ OS << "_None";
+ else
+ for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i)
+ OS << '_' << MI->RequiredFeatures[i]->TheDef->getName();
OS << ", { ";
for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) {
@@ -3394,7 +3474,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (ReportMultipleNearMisses)
OS << " SmallVectorImpl<NearMissInfo> *NearMisses,\n";
else
- OS << " uint64_t &ErrorInfo,\n";
+ OS << " uint64_t &ErrorInfo,\n"
+ << " FeatureBitset &MissingFeatures,\n";
OS << " bool matchingInlineAsm, unsigned VariantID) {\n";
if (!ReportMultipleNearMisses) {
@@ -3409,7 +3490,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Emit code to get the available features.
OS << " // Get the current feature set.\n";
- OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n";
+ OS << " const FeatureBitset &AvailableFeatures = getAvailableFeatures();\n\n";
OS << " // Get the instruction mnemonic, which is the first token.\n";
if (HasMnemonicFirst) {
@@ -3433,7 +3514,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " bool HadMatchOtherThanFeatures = false;\n";
OS << " bool HadMatchOtherThanPredicate = false;\n";
OS << " unsigned RetCode = Match_InvalidOperand;\n";
- OS << " uint64_t MissingFeatures = ~0ULL;\n";
+ OS << " MissingFeatures.set();\n";
OS << " // Set ErrorInfo to the operand that mismatches if it is\n";
OS << " // wrong for all instances of the instruction.\n";
OS << " ErrorInfo = ~0ULL;\n";
@@ -3479,9 +3560,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " for (const MatchEntry *it = MnemonicRange.first, "
<< "*ie = MnemonicRange.second;\n";
OS << " it != ie; ++it) {\n";
+ OS << " const FeatureBitset &RequiredFeatures = "
+ "FeatureBitsets[it->RequiredFeaturesIdx];\n";
OS << " bool HasRequiredFeatures =\n";
- OS << " (AvailableFeatures & it->RequiredFeatures) == "
- "it->RequiredFeatures;\n";
+ OS << " (AvailableFeatures & RequiredFeatures) == RequiredFeatures;\n";
OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Trying to match opcode \"\n";
OS << " << MII.getName(it->Opcode) << \"\\n\");\n";
@@ -3640,16 +3722,18 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " if (!HasRequiredFeatures) {\n";
if (!ReportMultipleNearMisses)
OS << " HadMatchOtherThanFeatures = true;\n";
- OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & "
+ OS << " FeatureBitset NewMissingFeatures = RequiredFeatures & "
"~AvailableFeatures;\n";
- OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Missing target features: \"\n";
- OS << " << format_hex(NewMissingFeatures, 18)\n";
- OS << " << \"\\n\");\n";
+ OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Missing target features:\";\n";
+ OS << " for (unsigned I = 0, E = NewMissingFeatures.size(); I != E; ++I)\n";
+ OS << " if (NewMissingFeatures[I])\n";
+ OS << " dbgs() << ' ' << I;\n";
+ OS << " dbgs() << \"\\n\");\n";
if (ReportMultipleNearMisses) {
OS << " FeaturesNearMiss = NearMissInfo::getMissedFeature(NewMissingFeatures);\n";
} else {
- OS << " if (countPopulation(NewMissingFeatures) <=\n"
- " countPopulation(MissingFeatures))\n";
+ OS << " if (NewMissingFeatures.count() <=\n"
+ " MissingFeatures.count())\n";
OS << " MissingFeatures = NewMissingFeatures;\n";
OS << " continue;\n";
}
@@ -3804,15 +3888,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " // Okay, we had no match. Try to return a useful error code.\n";
OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)\n";
OS << " return RetCode;\n\n";
- OS << " // Missing feature matches return which features were missing\n";
- OS << " ErrorInfo = MissingFeatures;\n";
+ OS << " ErrorInfo = 0;\n";
OS << " return Match_MissingFeature;\n";
}
OS << "}\n\n";
if (!Info.OperandMatchInfo.empty())
emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable,
- MaxMnemonicIndex, HasMnemonicFirst);
+ MaxMnemonicIndex, FeatureBitsets.size(),
+ HasMnemonicFirst);
OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n";
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index a8f191181766..05d81f133505 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -1,9 +1,8 @@
//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -586,11 +585,20 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
O << " case ";
if (!Namespace.empty())
O << Namespace << "::";
- O << AltName << ":\n"
- << " assert(*(AsmStrs" << AltName << "+RegAsmOffset" << AltName
- << "[RegNo-1]) &&\n"
- << " \"Invalid alt name index for register!\");\n"
- << " return AsmStrs" << AltName << "+RegAsmOffset" << AltName
+ O << AltName << ":\n";
+ if (R->isValueUnset("FallbackRegAltNameIndex"))
+ O << " assert(*(AsmStrs" << AltName << "+RegAsmOffset" << AltName
+ << "[RegNo-1]) &&\n"
+ << " \"Invalid alt name index for register!\");\n";
+ else {
+ O << " if (!*(AsmStrs" << AltName << "+RegAsmOffset" << AltName
+ << "[RegNo-1]))\n"
+ << " return getRegisterName(RegNo, ";
+ if (!Namespace.empty())
+ O << Namespace << "::";
+ O << R->getValueAsDef("FallbackRegAltNameIndex")->getName() << ");\n";
+ }
+ O << " return AsmStrs" << AltName << "+RegAsmOffset" << AltName
<< "[RegNo-1];\n";
}
O << " }\n";
diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp
index 2c19e5d663d6..c26e0e421183 100644
--- a/utils/TableGen/AsmWriterInst.cpp
+++ b/utils/TableGen/AsmWriterInst.cpp
@@ -1,9 +1,8 @@
//===- AsmWriterInst.h - Classes encapsulating a printable inst -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -94,8 +93,10 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
!= std::string::npos) {
AddLiteralString(std::string(1, AsmString[DollarPos+1]));
} else {
- PrintFatalError("Non-supported escaped character found in instruction '" +
- CGI.TheDef->getName() + "'!");
+ PrintFatalError(
+ CGI.TheDef->getLoc(),
+ "Non-supported escaped character found in instruction '" +
+ CGI.TheDef->getName() + "'!");
}
LastEmitted = DollarPos+2;
continue;
@@ -132,15 +133,19 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
// brace.
if (hasCurlyBraces) {
if (VarEnd >= AsmString.size())
- PrintFatalError("Reached end of string before terminating curly brace in '"
- + CGI.TheDef->getName() + "'");
+ PrintFatalError(
+ CGI.TheDef->getLoc(),
+ "Reached end of string before terminating curly brace in '" +
+ CGI.TheDef->getName() + "'");
// Look for a modifier string.
if (AsmString[VarEnd] == ':') {
++VarEnd;
if (VarEnd >= AsmString.size())
- PrintFatalError("Reached end of string before terminating curly brace in '"
- + CGI.TheDef->getName() + "'");
+ PrintFatalError(
+ CGI.TheDef->getLoc(),
+ "Reached end of string before terminating curly brace in '" +
+ CGI.TheDef->getName() + "'");
std::string::size_type ModifierStart = VarEnd;
while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
@@ -148,17 +153,22 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
Modifier = std::string(AsmString.begin()+ModifierStart,
AsmString.begin()+VarEnd);
if (Modifier.empty())
- PrintFatalError("Bad operand modifier name in '"+ CGI.TheDef->getName() + "'");
+ PrintFatalError(CGI.TheDef->getLoc(),
+ "Bad operand modifier name in '" +
+ CGI.TheDef->getName() + "'");
}
if (AsmString[VarEnd] != '}')
- PrintFatalError("Variable name beginning with '{' did not end with '}' in '"
- + CGI.TheDef->getName() + "'");
+ PrintFatalError(
+ CGI.TheDef->getLoc(),
+ "Variable name beginning with '{' did not end with '}' in '" +
+ CGI.TheDef->getName() + "'");
++VarEnd;
}
if (VarName.empty() && Modifier.empty())
- PrintFatalError("Stray '$' in '" + CGI.TheDef->getName() +
- "' asm string, maybe you want $$?");
+ PrintFatalError(CGI.TheDef->getLoc(),
+ "Stray '$' in '" + CGI.TheDef->getName() +
+ "' asm string, maybe you want $$?");
if (VarName.empty()) {
// Just a modifier, pass this into PrintSpecial.
diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h
index 708f23cb5b0e..7d88e5a9d037 100644
--- a/utils/TableGen/AsmWriterInst.h
+++ b/utils/TableGen/AsmWriterInst.h
@@ -1,9 +1,8 @@
//===- AsmWriterInst.h - Classes encapsulating a printable inst -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/Attributes.cpp b/utils/TableGen/Attributes.cpp
index 6bfc0ab896f9..6fbc595d7300 100644
--- a/utils/TableGen/Attributes.cpp
+++ b/utils/TableGen/Attributes.cpp
@@ -1,9 +1,8 @@
//===- Attributes.cpp - Generate attributes -------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/CTagsEmitter.cpp b/utils/TableGen/CTagsEmitter.cpp
index bd596bcb47a8..ccb7f3300dde 100644
--- a/utils/TableGen/CTagsEmitter.cpp
+++ b/utils/TableGen/CTagsEmitter.cpp
@@ -1,9 +1,8 @@
//===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp
index d452031f8850..de5044e24d49 100644
--- a/utils/TableGen/CallingConvEmitter.cpp
+++ b/utils/TableGen/CallingConvEmitter.cpp
@@ -1,9 +1,8 @@
//===- CallingConvEmitter.cpp - Generate calling conventions --------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -41,11 +40,17 @@ void CallingConvEmitter::run(raw_ostream &O) {
// each other.
for (Record *CC : CCs) {
if (!CC->getValueAsBit("Custom")) {
- O << "static bool " << CC->getName()
- << "(unsigned ValNo, MVT ValVT,\n"
- << std::string(CC->getName().size() + 13, ' ')
- << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
- << std::string(CC->getName().size() + 13, ' ')
+ unsigned Pad = CC->getName().size();
+ if (CC->getValueAsBit("Entry")) {
+ O << "bool llvm::";
+ Pad += 12;
+ } else {
+ O << "static bool ";
+ Pad += 13;
+ }
+ O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n"
+ << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << std::string(Pad, ' ')
<< "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
}
}
@@ -62,12 +67,18 @@ void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
ListInit *CCActions = CC->getValueAsListInit("Actions");
Counter = 0;
- O << "\n\nstatic bool " << CC->getName()
- << "(unsigned ValNo, MVT ValVT,\n"
- << std::string(CC->getName().size()+13, ' ')
- << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
- << std::string(CC->getName().size()+13, ' ')
- << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
+ O << "\n\n";
+ unsigned Pad = CC->getName().size();
+ if (CC->getValueAsBit("Entry")) {
+ O << "bool llvm::";
+ Pad += 12;
+ } else {
+ O << "static bool ";
+ Pad += 13;
+ }
+ O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n"
+ << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << std::string(Pad, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
// Emit all of the actions, in order.
for (unsigned i = 0, e = CCActions->size(); i != e; ++i) {
O << "\n";
@@ -97,7 +108,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << Action->getValueAsString("Predicate");
} else {
errs() << *Action;
- PrintFatalError("Unknown CCPredicateAction!");
+ PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!");
}
O << ") {\n";
@@ -134,7 +145,8 @@ void CallingConvEmitter::EmitAction(Record *Action,
ListInit *RegList = Action->getValueAsListInit("RegList");
ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size())
- PrintFatalError("Invalid length of list of shadowed registers");
+ PrintFatalError(Action->getLoc(),
+ "Invalid length of list of shadowed registers");
if (RegList->size() == 1) {
O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
@@ -237,7 +249,8 @@ void CallingConvEmitter::EmitAction(Record *Action,
MVT::SimpleValueType DestVT = getValueType(DestTy);
O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
if (MVT(DestVT).isFloatingPoint()) {
- PrintFatalError("CCPromoteToUpperBitsInType does not handle floating "
+ PrintFatalError(Action->getLoc(),
+ "CCPromoteToUpperBitsInType does not handle floating "
"point");
} else {
O << IndentStr << "if (ArgFlags.isSExt())\n"
@@ -269,7 +282,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << IndentStr << IndentStr << "return false;\n";
} else {
errs() << *Action;
- PrintFatalError("Unknown CCAction!");
+ PrintFatalError(Action->getLoc(), "Unknown CCAction!");
}
}
}
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 23751a2cbfba..da65763905a8 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -1,9 +1,8 @@
//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -16,6 +15,7 @@
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
#include "SubtargetFeatureInfo.h"
+#include "Types.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Casting.h"
@@ -229,6 +229,14 @@ std::string CodeEmitterGen::getInstructionCase(Record *R,
return Case;
}
+static std::string
+getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset) {
+ std::string Name = "CEFBS";
+ for (const auto &Feature : FeatureBitset)
+ Name += ("_" + Feature->getName()).str();
+ return Name;
+}
+
void CodeEmitterGen::run(raw_ostream &o) {
CodeGenTarget Target(Records);
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
@@ -327,8 +335,8 @@ void CodeEmitterGen::run(raw_ostream &o) {
<< "#include <sstream>\n\n";
// Emit the subtarget feature enumeration.
- SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(SubtargetFeatures,
- o);
+ SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,
+ o);
// Emit the name table for error messages.
o << "#ifndef NDEBUG\n";
@@ -340,35 +348,97 @@ void CodeEmitterGen::run(raw_ostream &o) {
Target.getName(), "MCCodeEmitter", "computeAvailableFeatures",
SubtargetFeatures, o);
+ std::vector<std::vector<Record *>> FeatureBitsets;
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ FeatureBitsets.emplace_back();
+ for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {
+ const auto &I = SubtargetFeatures.find(Predicate);
+ if (I != SubtargetFeatures.end())
+ FeatureBitsets.back().push_back(I->second.TheDef);
+ }
+ }
+
+ llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A,
+ const std::vector<Record *> &B) {
+ if (A.size() < B.size())
+ return true;
+ if (A.size() > B.size())
+ return false;
+ for (const auto &Pair : zip(A, B)) {
+ if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName())
+ return true;
+ if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName())
+ return false;
+ }
+ return false;
+ });
+ FeatureBitsets.erase(
+ std::unique(FeatureBitsets.begin(), FeatureBitsets.end()),
+ FeatureBitsets.end());
+ o << "#ifndef NDEBUG\n"
+ << "// Feature bitsets.\n"
+ << "enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n"
+ << " CEFBS_None,\n";
+ for (const auto &FeatureBitset : FeatureBitsets) {
+ if (FeatureBitset.empty())
+ continue;
+ o << " " << getNameForFeatureBitset(FeatureBitset) << ",\n";
+ }
+ o << "};\n\n"
+ << "const static FeatureBitset FeatureBitsets[] {\n"
+ << " {}, // CEFBS_None\n";
+ for (const auto &FeatureBitset : FeatureBitsets) {
+ if (FeatureBitset.empty())
+ continue;
+ o << " {";
+ for (const auto &Feature : FeatureBitset) {
+ const auto &I = SubtargetFeatures.find(Feature);
+ assert(I != SubtargetFeatures.end() && "Didn't import predicate?");
+ o << I->second.getEnumBitName() << ", ";
+ }
+ o << "},\n";
+ }
+ o << "};\n"
+ << "#endif // NDEBUG\n\n";
+
+
// Emit the predicate verifier.
o << "void " << Target.getName()
<< "MCCodeEmitter::verifyInstructionPredicates(\n"
- << " const MCInst &Inst, uint64_t AvailableFeatures) const {\n"
+ << " const MCInst &Inst, const FeatureBitset &AvailableFeatures) const {\n"
<< "#ifndef NDEBUG\n"
- << " static uint64_t RequiredFeatures[] = {\n";
+ << " static " << getMinimalTypeForRange(FeatureBitsets.size())
+ << " RequiredFeaturesRefs[] = {\n";
unsigned InstIdx = 0;
for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
- o << " ";
+ o << " CEFBS";
+ unsigned NumPredicates = 0;
for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {
const auto &I = SubtargetFeatures.find(Predicate);
- if (I != SubtargetFeatures.end())
- o << I->second.getEnumName() << " | ";
+ if (I != SubtargetFeatures.end()) {
+ o << '_' << I->second.TheDef->getName();
+ NumPredicates++;
+ }
}
- o << "0, // " << Inst->TheDef->getName() << " = " << InstIdx << "\n";
+ if (!NumPredicates)
+ o << "_None";
+ o << ", // " << 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"
+ o << " const FeatureBitset &RequiredFeatures = "
+ "FeatureBitsets[RequiredFeaturesRefs[Inst.getOpcode()]];\n";
+ o << " FeatureBitset MissingFeatures =\n"
+ << " (AvailableFeatures & RequiredFeatures) ^\n"
+ << " RequiredFeatures;\n"
+ << " if (MissingFeatures.any()) {\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"
+ << " for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)\n"
+ << " if (MissingFeatures.test(i))\n"
<< " Msg << SubtargetFeatureNames[i] << \" \";\n"
<< " Msg << \"predicate(s) are not met\";\n"
<< " report_fatal_error(Msg.str());\n"
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 96c90c9cf6bd..c8f710d66a03 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -1,9 +1,8 @@
//===- CodeGenDAGPatterns.cpp - Read DAG patterns from .td file -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -68,8 +67,10 @@ static bool berase_if(MachineValueTypeSet &S, Predicate P) {
// inference will apply to each mode separately.
TypeSetByHwMode::TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList) {
- for (const ValueTypeByHwMode &VVT : VTList)
+ for (const ValueTypeByHwMode &VVT : VTList) {
insert(VVT);
+ AddrSpaces.push_back(VVT.PtrAddrSpace);
+ }
}
bool TypeSetByHwMode::isValueTypeByHwMode(bool AllowEmpty) const {
@@ -86,9 +87,13 @@ ValueTypeByHwMode TypeSetByHwMode::getValueTypeByHwMode() const {
assert(isValueTypeByHwMode(true) &&
"The type set has multiple types for at least one HW mode");
ValueTypeByHwMode VVT;
+ auto ASI = AddrSpaces.begin();
+
for (const auto &I : *this) {
MVT T = I.second.empty() ? MVT::Other : *I.second.begin();
VVT.getOrCreateTypeForMode(I.first, T);
+ if (ASI != AddrSpaces.end())
+ VVT.PtrAddrSpace = *ASI++;
}
return VVT;
}
@@ -502,22 +507,14 @@ bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small,
(A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
A.getSizeInBits() < B.getSizeInBits());
};
- auto LE = [](MVT A, MVT B) -> bool {
+ auto LE = [&LT](MVT A, MVT B) -> bool {
// This function is used when removing elements: when a vector is compared
// to a non-vector, it should return false (to avoid removal).
if (A.isVector() != B.isVector())
return false;
- // Note on the < comparison below:
- // X86 has patterns like
- // (set VR128X:$dst, (v16i8 (X86vtrunc (v4i32 VR128X:$src1)))),
- // where the truncated vector is given a type v16i8, while the source
- // vector has type v4i32. They both have the same size in bits.
- // The minimal type in the result is obviously v16i8, and when we remove
- // all types from the source that are smaller-or-equal than v8i16, the
- // only source type would also be removed (since it's equal in size).
- return A.getScalarSizeInBits() <= B.getScalarSizeInBits() ||
- A.getSizeInBits() < B.getSizeInBits();
+ return LT(A, B) || (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
+ A.getSizeInBits() == B.getSizeInBits());
};
for (unsigned M : Modes) {
@@ -957,13 +954,33 @@ std::string TreePredicateFn::getPredCode() const {
}
if (isLoad() || isStore() || isAtomic()) {
- StringRef SDNodeName =
- isLoad() ? "LoadSDNode" : isStore() ? "StoreSDNode" : "AtomicSDNode";
+ if (ListInit *AddressSpaces = getAddressSpaces()) {
+ Code += "unsigned AddrSpace = cast<MemSDNode>(N)->getAddressSpace();\n"
+ " if (";
+
+ bool First = true;
+ for (Init *Val : AddressSpaces->getValues()) {
+ if (First)
+ First = false;
+ else
+ Code += " && ";
+
+ IntInit *IntVal = dyn_cast<IntInit>(Val);
+ if (!IntVal) {
+ PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
+ "AddressSpaces element must be integer");
+ }
+
+ Code += "AddrSpace != " + utostr(IntVal->getValue());
+ }
+
+ Code += ")\nreturn false;\n";
+ }
Record *MemoryVT = getMemoryVT();
if (MemoryVT)
- Code += ("if (cast<" + SDNodeName + ">(N)->getMemoryVT() != MVT::" +
+ Code += ("if (cast<MemSDNode>(N)->getMemoryVT() != MVT::" +
MemoryVT->getName() + ") return false;\n")
.str();
}
@@ -1152,6 +1169,14 @@ Record *TreePredicateFn::getMemoryVT() const {
return nullptr;
return R->getValueAsDef("MemoryVT");
}
+
+ListInit *TreePredicateFn::getAddressSpaces() const {
+ Record *R = getOrigPatFragRecord()->getRecord();
+ if (R->isValueUnset("AddressSpaces"))
+ return nullptr;
+ return R->getValueAsListInit("AddressSpaces");
+}
+
Record *TreePredicateFn::getScalarMemoryVT() const {
Record *R = getOrigPatFragRecord()->getRecord();
if (R->isValueUnset("ScalarMemoryVT"))
@@ -1276,6 +1301,17 @@ std::string TreePredicateFn::getCodeToRunOnSDNode() const {
// PatternToMatch implementation
//
+static bool isImmAllOnesAllZerosMatch(const TreePatternNode *P) {
+ if (!P->isLeaf())
+ return false;
+ DefInit *DI = dyn_cast<DefInit>(P->getLeafValue());
+ if (!DI)
+ return false;
+
+ Record *R = DI->getDef();
+ return R->getName() == "immAllOnesV" || R->getName() == "immAllZerosV";
+}
+
/// getPatternSize - Return the 'size' of this pattern. We want to match large
/// patterns before small ones. This is used to determine the size of a
/// pattern.
@@ -1315,6 +1351,8 @@ static unsigned getPatternSize(const TreePatternNode *P,
Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
else if (Child->getComplexPatternInfo(CGP))
Size += getPatternSize(Child, CGP);
+ else if (isImmAllOnesAllZerosMatch(Child))
+ Size += 4; // Matches a build_vector(+3) and a predicate (+1).
else if (!Child->getPredicateCalls().empty())
++Size;
}
@@ -1408,7 +1446,8 @@ SDTypeConstraint::SDTypeConstraint(Record *R, const CodeGenHwModes &CGH) {
x.SDTCisSameSizeAs_Info.OtherOperandNum =
R->getValueAsInt("OtherOperandNum");
} else {
- PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
+ PrintFatalError(R->getLoc(),
+ "Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
}
}
@@ -2120,7 +2159,8 @@ static TypeSetByHwMode getImplicitType(Record *R, unsigned ResNo,
}
if (R->getName() == "node" || R->getName() == "srcvalue" ||
- R->getName() == "zero_reg") {
+ R->getName() == "zero_reg" || R->getName() == "immAllOnesV" ||
+ R->getName() == "immAllZerosV" || R->getName() == "undef_tied_input") {
// Placeholder.
return TypeSetByHwMode(); // Unknown.
}
@@ -2425,18 +2465,32 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
}
}
+ // If one or more operands with a default value appear at the end of the
+ // formal operand list for an instruction, we allow them to be overridden
+ // by optional operands provided in the pattern.
+ //
+ // But if an operand B without a default appears at any point after an
+ // operand A with a default, then we don't allow A to be overridden,
+ // because there would be no way to specify whether the next operand in
+ // the pattern was intended to override A or skip it.
+ unsigned NonOverridableOperands = Inst.getNumOperands();
+ while (NonOverridableOperands > 0 &&
+ CDP.operandHasDefault(Inst.getOperand(NonOverridableOperands-1)))
+ --NonOverridableOperands;
+
unsigned ChildNo = 0;
for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
Record *OperandNode = Inst.getOperand(i);
- // If the instruction expects a predicate or optional def operand, we
- // codegen this by setting the operand to it's default value if it has a
- // non-empty DefaultOps field.
- if (OperandNode->isSubClassOf("OperandWithDefaultOps") &&
- !CDP.getDefaultOperand(OperandNode).DefaultOps.empty())
+ // If the operand has a default value, do we use it? We must use the
+ // default if we've run out of children of the pattern DAG to consume,
+ // or if the operand is followed by a non-defaulted one.
+ if (CDP.operandHasDefault(OperandNode) &&
+ (i < NonOverridableOperands || ChildNo >= getNumChildren()))
continue;
- // Verify that we didn't run out of provided operands.
+ // If we have run out of child nodes and there _isn't_ a default
+ // value we can use for the next operand, give an error.
if (ChildNo >= getNumChildren()) {
emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren());
return false;
@@ -2753,7 +2807,7 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
// chain.
if (Int.IS.RetVTs.empty())
Operator = getDAGPatterns().get_intrinsic_void_sdnode();
- else if (Int.ModRef != CodeGenIntrinsic::NoMem)
+ else if (Int.ModRef != CodeGenIntrinsic::NoMem || Int.hasSideEffects)
// Has side-effects, requires chain.
Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode();
else // Otherwise, no chain.
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index 4be9afdcacd2..2b49a64c3f1d 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -1,9 +1,8 @@
//===- CodeGenDAGPatterns.h - Read DAG patterns from .td file ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -191,6 +190,7 @@ private:
struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> {
using SetType = MachineValueTypeSet;
+ std::vector<unsigned> AddrSpaces;
TypeSetByHwMode() = default;
TypeSetByHwMode(const TypeSetByHwMode &VTS) = default;
@@ -227,6 +227,15 @@ struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> {
return Map.size() == 1 && Map.begin()->first == DefaultMode;
}
+ bool isPointer() const {
+ return getValueTypeByHwMode().isPointer();
+ }
+
+ unsigned getPtrAddrSpace() const {
+ assert(isPointer());
+ return getValueTypeByHwMode().PtrAddrSpace;
+ }
+
bool insert(const ValueTypeByHwMode &VVT);
bool constrain(const TypeSetByHwMode &VTS);
template <typename Predicate> bool constrain(Predicate P);
@@ -243,6 +252,7 @@ struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> {
bool validate() const;
private:
+ unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max();
/// Intersect two sets. Return true if anything has changed.
bool intersect(SetType &Out, const SetType &In);
};
@@ -583,6 +593,8 @@ public:
/// ValueType record for the memory VT.
Record *getScalarMemoryVT() const;
+ ListInit *getAddressSpaces() const;
+
// If true, indicates that GlobalISel-based C++ code was supplied.
bool hasGISelPredicateCode() const;
std::string getGISelPredicateCode() const;
@@ -1272,6 +1284,11 @@ public:
unsigned allocateScope() { return ++NumScopes; }
+ bool operandHasDefault(Record *Op) const {
+ return Op->isSubClassOf("OperandWithDefaultOps") &&
+ !getDefaultOperand(Op).DefaultOps.empty();
+ }
+
private:
void ParseNodeInfo();
void ParseNodeTransforms();
diff --git a/utils/TableGen/CodeGenHwModes.cpp b/utils/TableGen/CodeGenHwModes.cpp
index 9f88d95275b4..9052cdd2bd3e 100644
--- a/utils/TableGen/CodeGenHwModes.cpp
+++ b/utils/TableGen/CodeGenHwModes.cpp
@@ -1,9 +1,8 @@
//===--- CodeGenHwModes.cpp -----------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Classes to parse and store HW mode information for instruction selection
diff --git a/utils/TableGen/CodeGenHwModes.h b/utils/TableGen/CodeGenHwModes.h
index 36df835d1933..1ff2faaa0e52 100644
--- a/utils/TableGen/CodeGenHwModes.h
+++ b/utils/TableGen/CodeGenHwModes.h
@@ -1,9 +1,8 @@
//===--- CodeGenHwModes.h ---------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Classes to parse and store HW mode information for instruction selection.
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 6d06ba2c8b67..2463824469ab 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -1,9 +1,8 @@
//===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -34,18 +33,24 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) {
if (Init->getDef()->getName() != "outs")
- PrintFatalError(R->getName() + ": invalid def name for output list: use 'outs'");
+ PrintFatalError(R->getLoc(),
+ R->getName() +
+ ": invalid def name for output list: use 'outs'");
} else
- PrintFatalError(R->getName() + ": invalid output list: use 'outs'");
+ PrintFatalError(R->getLoc(),
+ R->getName() + ": invalid output list: use 'outs'");
NumDefs = OutDI->getNumArgs();
DagInit *InDI = R->getValueAsDag("InOperandList");
if (DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) {
if (Init->getDef()->getName() != "ins")
- PrintFatalError(R->getName() + ": invalid def name for input list: use 'ins'");
+ PrintFatalError(R->getLoc(),
+ R->getName() +
+ ": invalid def name for input list: use 'ins'");
} else
- PrintFatalError(R->getName() + ": invalid input list: use 'ins'");
+ PrintFatalError(R->getLoc(),
+ R->getName() + ": invalid input list: use 'ins'");
unsigned MIOperandNo = 0;
std::set<std::string> OperandNames;
@@ -64,7 +69,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
DefInit *Arg = dyn_cast<DefInit>(ArgInit);
if (!Arg)
- PrintFatalError("Illegal operand for the '" + R->getName() + "' instruction!");
+ PrintFatalError(R->getLoc(), "Illegal operand for the '" + R->getName() +
+ "' instruction!");
Record *Rec = Arg->getDef();
std::string PrintMethod = "printOperand";
@@ -89,8 +95,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
// Verify that MIOpInfo has an 'ops' root value.
if (!isa<DefInit>(MIOpInfo->getOperator()) ||
cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops")
- PrintFatalError("Bad value for MIOperandInfo in operand '" + Rec->getName() +
- "'\n");
+ PrintFatalError(R->getLoc(),
+ "Bad value for MIOperandInfo in operand '" +
+ Rec->getName() + "'\n");
// If we have MIOpInfo, then we have #operands equal to number of entries
// in MIOperandInfo.
@@ -108,16 +115,20 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
OperandType = "OPERAND_REGISTER";
} else if (!Rec->isSubClassOf("PointerLikeRegClass") &&
!Rec->isSubClassOf("unknown_class"))
- PrintFatalError("Unknown operand class '" + Rec->getName() +
- "' in '" + R->getName() + "' instruction!");
+ PrintFatalError(R->getLoc(), "Unknown operand class '" + Rec->getName() +
+ "' in '" + R->getName() +
+ "' instruction!");
// Check that the operand has a name and that it's unique.
if (ArgName.empty())
- PrintFatalError("In instruction '" + R->getName() + "', operand #" +
- Twine(i) + " has no name!");
+ PrintFatalError(R->getLoc(), "In instruction '" + R->getName() +
+ "', operand #" + Twine(i) +
+ " has no name!");
if (!OperandNames.insert(ArgName).second)
- PrintFatalError("In instruction '" + R->getName() + "', operand #" +
- Twine(i) + " has the same name as a previous operand!");
+ PrintFatalError(R->getLoc(),
+ "In instruction '" + R->getName() + "', operand #" +
+ Twine(i) +
+ " has the same name as a previous operand!");
OperandList.emplace_back(Rec, ArgName, PrintMethod, EncoderMethod,
OperandNamespace + "::" + OperandType, MIOperandNo,
@@ -139,9 +150,11 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
///
unsigned CGIOperandList::getOperandNamed(StringRef Name) const {
unsigned OpIdx;
- if (hasOperandNamed(Name, OpIdx)) return OpIdx;
- PrintFatalError("'" + TheDef->getName() +
- "' does not have an operand named '$" + Name + "'!");
+ if (hasOperandNamed(Name, OpIdx))
+ return OpIdx;
+ PrintFatalError(TheDef->getLoc(), "'" + TheDef->getName() +
+ "' does not have an operand named '$" +
+ Name + "'!");
}
/// hasOperandNamed - Query whether the instruction has an operand of the
@@ -160,7 +173,8 @@ bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const {
std::pair<unsigned,unsigned>
CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
if (Op.empty() || Op[0] != '$')
- PrintFatalError(TheDef->getName() + ": Illegal operand name: '" + Op + "'");
+ PrintFatalError(TheDef->getLoc(),
+ TheDef->getName() + ": Illegal operand name: '" + Op + "'");
std::string OpName = Op.substr(1);
std::string SubOpName;
@@ -170,7 +184,9 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
if (DotIdx != std::string::npos) {
SubOpName = OpName.substr(DotIdx+1);
if (SubOpName.empty())
- PrintFatalError(TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'");
+ PrintFatalError(TheDef->getLoc(),
+ TheDef->getName() +
+ ": illegal empty suboperand name in '" + Op + "'");
OpName = OpName.substr(0, DotIdx);
}
@@ -180,8 +196,11 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
// If one was needed, throw.
if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
SubOpName.empty())
- PrintFatalError(TheDef->getName() + ": Illegal to refer to"
- " whole operand part of complex operand '" + Op + "'");
+ PrintFatalError(TheDef->getLoc(),
+ TheDef->getName() +
+ ": Illegal to refer to"
+ " whole operand part of complex operand '" +
+ Op + "'");
// Otherwise, return the operand.
return std::make_pair(OpIdx, 0U);
@@ -190,7 +209,9 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
// Find the suboperand number involved.
DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
if (!MIOpInfo)
- PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'");
+ PrintFatalError(TheDef->getLoc(), TheDef->getName() +
+ ": unknown suboperand name in '" +
+ Op + "'");
// Find the operand with the right name.
for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
@@ -198,7 +219,9 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
return std::make_pair(OpIdx, i);
// Otherwise, didn't find it!
- PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'");
+ PrintFatalError(TheDef->getLoc(), TheDef->getName() +
+ ": unknown suboperand name in '" + Op +
+ "'");
return std::make_pair(0U, 0U);
}
@@ -354,7 +377,8 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
isAdd = R->getValueAsBit("isAdd");
isTrap = R->getValueAsBit("isTrap");
canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
- isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable");
+ isPredicable = !R->getValueAsBit("isUnpredicable") && (
+ Operands.isPredicable || R->getValueAsBit("isPredicable"));
isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
isCommutable = R->getValueAsBit("isCommutable");
isTerminator = R->getValueAsBit("isTerminator");
@@ -377,6 +401,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
mayLoad_Unset = Unset;
mayStore = R->getValueAsBitOrUnset("mayStore", Unset);
mayStore_Unset = Unset;
+ mayRaiseFPException = R->getValueAsBit("mayRaiseFPException");
hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset);
hasSideEffects_Unset = Unset;
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index 2e3d2f48a928..bb5b1369649f 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -1,9 +1,8 @@
//===- CodeGenInstruction.h - Instruction Class Wrapper ---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -250,6 +249,7 @@ template <typename T> class ArrayRef;
bool mayLoad_Unset : 1;
bool mayStore : 1;
bool mayStore_Unset : 1;
+ bool mayRaiseFPException : 1;
bool isPredicable : 1;
bool isConvertibleToThreeAddress : 1;
bool isCommutable : 1;
diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h
index 9487a79c1432..7b74bb07d6e0 100644
--- a/utils/TableGen/CodeGenIntrinsics.h
+++ b/utils/TableGen/CodeGenIntrinsics.h
@@ -1,9 +1,8 @@
//===- CodeGenIntrinsic.h - Intrinsic Class Wrapper ------------*- C++ -*--===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -124,6 +123,9 @@ struct CodeGenIntrinsic {
/// True if the intrinsic is no-return.
bool isNoReturn;
+ /// True if the intrinsic is will-return.
+ bool isWillReturn;
+
/// True if the intrinsic is cold.
bool isCold;
@@ -137,7 +139,15 @@ struct CodeGenIntrinsic {
// True if the intrinsic is marked as speculatable.
bool isSpeculatable;
- enum ArgAttribute { NoCapture, Returned, ReadOnly, WriteOnly, ReadNone };
+ enum ArgAttribute {
+ NoCapture,
+ Returned,
+ ReadOnly,
+ WriteOnly,
+ ReadNone,
+ ImmArg
+ };
+
std::vector<std::pair<unsigned, ArgAttribute>> ArgumentAttributes;
bool hasProperty(enum SDNP Prop) const {
diff --git a/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp
index e5b0426cdcc3..b1774b01ba8c 100644
--- a/utils/TableGen/CodeGenMapTable.cpp
+++ b/utils/TableGen/CodeGenMapTable.cpp
@@ -1,9 +1,8 @@
//===- CodeGenMapTable.cpp - Instruction Mapping Table Generator ----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// CodeGenMapTable provides functionality for the TabelGen to create
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp
index 74a2b078dfb3..f87c6d6c945a 100644
--- a/utils/TableGen/CodeGenRegisters.cpp
+++ b/utils/TableGen/CodeGenRegisters.cpp
@@ -1,9 +1,8 @@
//===- CodeGenRegisters.cpp - Register and RegisterClass Info -------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -740,8 +739,9 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
Record *Type = TypeList[i];
if (!Type->isSubClassOf("ValueType"))
- PrintFatalError("RegTypes list member '" + Type->getName() +
- "' does not derive from the ValueType class!");
+ PrintFatalError(R->getLoc(),
+ "RegTypes list member '" + Type->getName() +
+ "' does not derive from the ValueType class!");
VTs.push_back(getValueTypeByHwMode(Type, RegBank.getHwModes()));
}
assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!");
@@ -2101,8 +2101,7 @@ void CodeGenRegBank::computeDerivedInfo() {
for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx)
RegUnitSetOrder.push_back(Idx);
- std::stable_sort(RegUnitSetOrder.begin(), RegUnitSetOrder.end(),
- [this](unsigned ID1, unsigned ID2) {
+ llvm::stable_sort(RegUnitSetOrder, [this](unsigned ID1, unsigned ID2) {
return getRegPressureSet(ID1).Units.size() <
getRegPressureSet(ID2).Units.size();
});
diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h
index 0f7a025ded10..f04a90f8fde5 100644
--- a/utils/TableGen/CodeGenRegisters.h
+++ b/utils/TableGen/CodeGenRegisters.h
@@ -1,9 +1,8 @@
//===- CodeGenRegisters.h - Register and RegisterClass Info -----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp
index 6d259cbb33ee..fd007044a16e 100644
--- a/utils/TableGen/CodeGenSchedule.cpp
+++ b/utils/TableGen/CodeGenSchedule.cpp
@@ -1,9 +1,8 @@
//===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -369,24 +368,22 @@ processSTIPredicate(STIPredicateFunction &Fn,
[&](const OpcodeMapPair &Lhs, const OpcodeMapPair &Rhs) {
unsigned LhsIdx = Opcode2Index[Lhs.first];
unsigned RhsIdx = Opcode2Index[Rhs.first];
- std::pair<APInt, APInt> &LhsMasks = OpcodeMasks[LhsIdx];
- std::pair<APInt, APInt> &RhsMasks = OpcodeMasks[RhsIdx];
-
- if (LhsMasks.first != RhsMasks.first) {
- if (LhsMasks.first.countPopulation() <
- RhsMasks.first.countPopulation())
- return true;
- return LhsMasks.first.countLeadingZeros() >
- RhsMasks.first.countLeadingZeros();
- }
-
- if (LhsMasks.second != RhsMasks.second) {
- if (LhsMasks.second.countPopulation() <
- RhsMasks.second.countPopulation())
- return true;
- return LhsMasks.second.countLeadingZeros() >
- RhsMasks.second.countLeadingZeros();
- }
+ const std::pair<APInt, APInt> &LhsMasks = OpcodeMasks[LhsIdx];
+ const std::pair<APInt, APInt> &RhsMasks = OpcodeMasks[RhsIdx];
+
+ auto LessThan = [](const APInt &Lhs, const APInt &Rhs) {
+ unsigned LhsCountPopulation = Lhs.countPopulation();
+ unsigned RhsCountPopulation = Rhs.countPopulation();
+ return ((LhsCountPopulation < RhsCountPopulation) ||
+ ((LhsCountPopulation == RhsCountPopulation) &&
+ (Lhs.countLeadingZeros() > Rhs.countLeadingZeros())));
+ };
+
+ if (LhsMasks.first != RhsMasks.first)
+ return LessThan(LhsMasks.first, RhsMasks.first);
+
+ if (LhsMasks.second != RhsMasks.second)
+ return LessThan(LhsMasks.second, RhsMasks.second);
return LhsIdx < RhsIdx;
});
@@ -1936,8 +1933,10 @@ void CodeGenSchedModels::checkCompleteness() {
unsigned SCIdx = getSchedClassIdx(*Inst);
if (!SCIdx) {
if (Inst->TheDef->isValueUnset("SchedRW") && !HadCompleteModel) {
- PrintError("No schedule information for instruction '"
- + Inst->TheDef->getName() + "'");
+ PrintError(Inst->TheDef->getLoc(),
+ "No schedule information for instruction '" +
+ Inst->TheDef->getName() + "' in SchedMachineModel '" +
+ ProcModel.ModelDef->getName() + "'");
Complete = false;
}
continue;
@@ -1955,8 +1954,9 @@ void CodeGenSchedModels::checkCompleteness() {
return R->getValueAsDef("SchedModel") == ProcModel.ModelDef;
});
if (I == InstRWs.end()) {
- PrintError("'" + ProcModel.ModelName + "' lacks information for '" +
- Inst->TheDef->getName() + "'");
+ PrintError(Inst->TheDef->getLoc(), "'" + ProcModel.ModelName +
+ "' lacks information for '" +
+ Inst->TheDef->getName() + "'");
Complete = false;
}
}
diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h
index 87a051b0c05e..c26fb1f97807 100644
--- a/utils/TableGen/CodeGenSchedule.h
+++ b/utils/TableGen/CodeGenSchedule.h
@@ -1,9 +1,8 @@
//===- CodeGenSchedule.h - Scheduling Machine Models ------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index bcb653135551..b65e1b6af791 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -1,9 +1,8 @@
//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -21,8 +20,10 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Timer.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <algorithm>
using namespace llvm;
@@ -105,11 +106,18 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v128i16: return "MVT::v128i16";
case MVT::v1i32: return "MVT::v1i32";
case MVT::v2i32: return "MVT::v2i32";
+ case MVT::v3i32: return "MVT::v3i32";
case MVT::v4i32: return "MVT::v4i32";
+ case MVT::v5i32: return "MVT::v5i32";
case MVT::v8i32: return "MVT::v8i32";
case MVT::v16i32: return "MVT::v16i32";
case MVT::v32i32: return "MVT::v32i32";
case MVT::v64i32: return "MVT::v64i32";
+ case MVT::v128i32: return "MVT::v128i32";
+ case MVT::v256i32: return "MVT::v256i32";
+ case MVT::v512i32: return "MVT::v512i32";
+ case MVT::v1024i32: return "MVT::v1024i32";
+ case MVT::v2048i32: return "MVT::v2048i32";
case MVT::v1i64: return "MVT::v1i64";
case MVT::v2i64: return "MVT::v2i64";
case MVT::v4i64: return "MVT::v4i64";
@@ -122,9 +130,18 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v8f16: return "MVT::v8f16";
case MVT::v1f32: return "MVT::v1f32";
case MVT::v2f32: return "MVT::v2f32";
+ case MVT::v3f32: return "MVT::v3f32";
case MVT::v4f32: return "MVT::v4f32";
+ case MVT::v5f32: return "MVT::v5f32";
case MVT::v8f32: return "MVT::v8f32";
case MVT::v16f32: return "MVT::v16f32";
+ case MVT::v32f32: return "MVT::v32f32";
+ case MVT::v64f32: return "MVT::v64f32";
+ case MVT::v128f32: return "MVT::v128f32";
+ case MVT::v256f32: return "MVT::v256f32";
+ case MVT::v512f32: return "MVT::v512f32";
+ case MVT::v1024f32: return "MVT::v1024f32";
+ case MVT::v2048f32: return "MVT::v2048f32";
case MVT::v1f64: return "MVT::v1f64";
case MVT::v2f64: return "MVT::v2f64";
case MVT::v4f64: return "MVT::v4f64";
@@ -174,7 +191,7 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::iPTR: return "MVT::iPTR";
case MVT::iPTRAny: return "MVT::iPTRAny";
case MVT::Untyped: return "MVT::Untyped";
- case MVT::ExceptRef: return "MVT::ExceptRef";
+ case MVT::exnref: return "MVT::exnref";
default: llvm_unreachable("ILLEGAL VALUE TYPE!");
}
}
@@ -327,6 +344,8 @@ CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
}
void CodeGenTarget::ReadInstructions() const {
+ NamedRegionTimer T("Read Instructions", "Time spent reading instructions",
+ "CodeGenTarget", "CodeGenTarget", TimeRegions);
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
if (Insts.size() <= 2)
PrintFatalError("No 'Instruction' subclasses defined!");
@@ -492,9 +511,10 @@ ComplexPattern::ComplexPattern(Record *R) {
} else if (PropList[i]->getName() == "SDNPWantParent") {
Properties |= 1 << SDNPWantParent;
} else {
- PrintFatalError("Unsupported SD Node property '" +
- PropList[i]->getName() + "' on ComplexPattern '" +
- R->getName() + "'!");
+ PrintFatalError(R->getLoc(), "Unsupported SD Node property '" +
+ PropList[i]->getName() +
+ "' on ComplexPattern '" + R->getName() +
+ "'!");
}
}
@@ -530,12 +550,14 @@ CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC,
CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
TheDef = R;
std::string DefName = R->getName();
+ ArrayRef<SMLoc> DefLoc = R->getLoc();
ModRef = ReadWriteMem;
Properties = 0;
isOverloaded = false;
isCommutative = false;
canThrow = false;
isNoReturn = false;
+ isWillReturn = false;
isCold = false;
isNoDuplicate = false;
isConvergent = false;
@@ -544,7 +566,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
if (DefName.size() <= 4 ||
std::string(DefName.begin(), DefName.begin() + 4) != "int_")
- PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!");
+ PrintFatalError(DefLoc,
+ "Intrinsic '" + DefName + "' does not start with 'int_'!");
EnumName = std::string(DefName.begin()+4, DefName.end());
@@ -566,7 +589,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// Verify it starts with "llvm.".
if (Name.size() <= 5 ||
std::string(Name.begin(), Name.begin() + 5) != "llvm.")
- PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!");
+ PrintFatalError(DefLoc, "Intrinsic '" + DefName +
+ "'s name does not start with 'llvm.'!");
}
// If TargetPrefix is specified, make sure that Name starts with
@@ -575,13 +599,34 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
if (Name.size() < 6+TargetPrefix.size() ||
std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size())
!= (TargetPrefix + "."))
- PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." +
- TargetPrefix + ".'!");
+ PrintFatalError(DefLoc, "Intrinsic '" + DefName +
+ "' does not start with 'llvm." +
+ TargetPrefix + ".'!");
}
- // Parse the list of return types.
+ ListInit *RetTypes = R->getValueAsListInit("RetTypes");
+ ListInit *ParamTypes = R->getValueAsListInit("ParamTypes");
+
+ // First collate a list of overloaded types.
std::vector<MVT::SimpleValueType> OverloadedVTs;
- ListInit *TypeList = R->getValueAsListInit("RetTypes");
+ for (ListInit *TypeList : {RetTypes, ParamTypes}) {
+ for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
+ Record *TyEl = TypeList->getElementAsRecord(i);
+ assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
+
+ if (TyEl->isSubClassOf("LLVMMatchType"))
+ continue;
+
+ MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT"));
+ if (MVT(VT).isOverloaded()) {
+ OverloadedVTs.push_back(VT);
+ isOverloaded = true;
+ }
+ }
+ }
+
+ // Parse the list of return types.
+ ListInit *TypeList = RetTypes;
for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
Record *TyEl = TypeList->getElementAsRecord(i);
assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
@@ -601,21 +646,18 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
} else {
VT = getValueType(TyEl->getValueAsDef("VT"));
}
- if (MVT(VT).isOverloaded()) {
- OverloadedVTs.push_back(VT);
- isOverloaded = true;
- }
// Reject invalid types.
if (VT == MVT::isVoid)
- PrintFatalError("Intrinsic '" + DefName + " has void in result type list!");
+ PrintFatalError(DefLoc, "Intrinsic '" + DefName +
+ " has void in result type list!");
IS.RetVTs.push_back(VT);
IS.RetTypeDefs.push_back(TyEl);
}
// Parse the list of parameter types.
- TypeList = R->getValueAsListInit("ParamTypes");
+ TypeList = ParamTypes;
for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
Record *TyEl = TypeList->getElementAsRecord(i);
assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
@@ -626,7 +668,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
PrintError(R->getLoc(),
"Parameter #" + Twine(i) + " has out of bounds matching "
"number " + Twine(MatchTy));
- PrintFatalError(Twine("ParamTypes is ") + TypeList->getAsString());
+ PrintFatalError(DefLoc,
+ Twine("ParamTypes is ") + TypeList->getAsString());
}
VT = OverloadedVTs[MatchTy];
// It only makes sense to use the extended and truncated vector element
@@ -634,20 +677,16 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// overloaded, all the types can be specified directly.
assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
!TyEl->isSubClassOf("LLVMTruncatedType") &&
- !TyEl->isSubClassOf("LLVMVectorSameWidth")) ||
+ !TyEl->isSubClassOf("LLVMScalarOrSameVectorWidth")) ||
VT == MVT::iAny || VT == MVT::vAny) &&
"Expected iAny or vAny type");
} else
VT = getValueType(TyEl->getValueAsDef("VT"));
- if (MVT(VT).isOverloaded()) {
- OverloadedVTs.push_back(VT);
- isOverloaded = true;
- }
-
// Reject invalid types.
if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
- PrintFatalError("Intrinsic '" + DefName + " has void in result type list!");
+ PrintFatalError(DefLoc, "Intrinsic '" + DefName +
+ " has void in result type list!");
IS.ParamVTs.push_back(VT);
IS.ParamTypeDefs.push_back(TyEl);
@@ -683,6 +722,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
isConvergent = true;
else if (Property->getName() == "IntrNoReturn")
isNoReturn = true;
+ else if (Property->getName() == "IntrWillReturn")
+ isWillReturn = true;
else if (Property->getName() == "IntrCold")
isCold = true;
else if (Property->getName() == "IntrSpeculatable")
@@ -704,6 +745,9 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
} else if (Property->isSubClassOf("ReadNone")) {
unsigned ArgNo = Property->getValueAsInt("ArgNo");
ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone));
+ } else if (Property->isSubClassOf("ImmArg")) {
+ unsigned ArgNo = Property->getValueAsInt("ArgNo");
+ ArgumentAttributes.push_back(std::make_pair(ArgNo, ImmArg));
} else
llvm_unreachable("Unknown property!");
}
diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h
index d2833d5b6a92..1ab2de269c76 100644
--- a/utils/TableGen/CodeGenTarget.h
+++ b/utils/TableGen/CodeGenTarget.h
@@ -1,9 +1,8 @@
//===- CodeGenTarget.h - Target Class Wrapper -------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index 62a0ff700725..fb0c6faa5295 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -1,9 +1,8 @@
//===- DAGISelEmitter.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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp
index c8e005739460..bebd205ad58f 100644
--- a/utils/TableGen/DAGISelMatcher.cpp
+++ b/utils/TableGen/DAGISelMatcher.cpp
@@ -1,9 +1,8 @@
//===- DAGISelMatcher.cpp - Representation of DAG pattern matcher ---------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -212,6 +211,11 @@ void CheckCondCodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "CheckCondCode ISD::" << CondCodeName << '\n';
}
+void CheckChild2CondCodeMatcher::printImpl(raw_ostream &OS,
+ unsigned indent) const {
+ OS.indent(indent) << "CheckChild2CondCode ISD::" << CondCodeName << '\n';
+}
+
void CheckValueTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "CheckValueType MVT::" << TypeName << '\n';
}
@@ -233,6 +237,16 @@ void CheckFoldableChainNodeMatcher::printImpl(raw_ostream &OS,
OS.indent(indent) << "CheckFoldableChainNode\n";
}
+void CheckImmAllOnesVMatcher::printImpl(raw_ostream &OS,
+ unsigned indent) const {
+ OS.indent(indent) << "CheckAllOnesV\n";
+}
+
+void CheckImmAllZerosVMatcher::printImpl(raw_ostream &OS,
+ unsigned indent) const {
+ OS.indent(indent) << "CheckAllZerosV\n";
+}
+
void EmitIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "EmitInteger " << Val << " VT=" << getEnumName(VT)
<< '\n';
@@ -398,3 +412,12 @@ bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const {
return false;
}
+bool CheckImmAllOnesVMatcher::isContradictoryImpl(const Matcher *M) const {
+ // AllZeros is contradictory.
+ return isa<CheckImmAllZerosVMatcher>(M);
+}
+
+bool CheckImmAllZerosVMatcher::isContradictoryImpl(const Matcher *M) const {
+ // AllOnes is contradictory.
+ return isa<CheckImmAllOnesVMatcher>(M);
+}
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
index 9be7295c67d4..0a782e84a372 100644
--- a/utils/TableGen/DAGISelMatcher.h
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -1,9 +1,8 @@
//===- DAGISelMatcher.h - Representation of DAG pattern matcher -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -67,10 +66,13 @@ public:
CheckInteger, // Fail if wrong val.
CheckChildInteger, // Fail if child is wrong val.
CheckCondCode, // Fail if not condcode.
+ CheckChild2CondCode, // Fail if child is wrong condcode.
CheckValueType,
CheckComplexPat,
CheckAndImm,
CheckOrImm,
+ CheckImmAllOnesV,
+ CheckImmAllZerosV,
CheckFoldableChainNode,
// Node creation/emisssion.
@@ -122,9 +124,12 @@ public:
case CheckInteger:
case CheckChildInteger:
case CheckCondCode:
+ case CheckChild2CondCode:
case CheckValueType:
case CheckAndImm:
case CheckOrImm:
+ case CheckImmAllOnesV:
+ case CheckImmAllZerosV:
case CheckFoldableChainNode:
return true;
}
@@ -626,6 +631,27 @@ private:
}
};
+/// CheckChild2CondCodeMatcher - This checks to see if child 2 node is a
+/// CondCodeSDNode with the specified condition, if not it fails to match.
+class CheckChild2CondCodeMatcher : public Matcher {
+ StringRef CondCodeName;
+public:
+ CheckChild2CondCodeMatcher(StringRef condcodename)
+ : Matcher(CheckChild2CondCode), CondCodeName(condcodename) {}
+
+ StringRef getCondCodeName() const { return CondCodeName; }
+
+ static bool classof(const Matcher *N) {
+ return N->getKind() == CheckChild2CondCode;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckChild2CondCodeMatcher>(M)->CondCodeName == CondCodeName;
+ }
+};
+
/// CheckValueTypeMatcher - This checks to see if the current node is a
/// VTSDNode with the specified type, if not it fails to match.
class CheckValueTypeMatcher : public Matcher {
@@ -731,6 +757,38 @@ private:
}
};
+/// CheckImmAllOnesVMatcher - This check if the current node is an build vector
+/// of all ones.
+class CheckImmAllOnesVMatcher : public Matcher {
+public:
+ CheckImmAllOnesVMatcher() : Matcher(CheckImmAllOnesV) {}
+
+ static bool classof(const Matcher *N) {
+ return N->getKind() == CheckImmAllOnesV;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override { return true; }
+ bool isContradictoryImpl(const Matcher *M) const override;
+};
+
+/// CheckImmAllZerosVMatcher - This check if the current node is an build vector
+/// of all zeros.
+class CheckImmAllZerosVMatcher : public Matcher {
+public:
+ CheckImmAllZerosVMatcher() : Matcher(CheckImmAllZerosV) {}
+
+ static bool classof(const Matcher *N) {
+ return N->getKind() == CheckImmAllZerosV;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override { return true; }
+ bool isContradictoryImpl(const Matcher *M) const override;
+};
+
/// CheckFoldableChainNodeMatcher - This checks to see if the current node
/// (which defines a chain operand) is safe to fold into a larger pattern.
class CheckFoldableChainNodeMatcher : public Matcher {
diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
index 90ca1bff5344..cecbc6cccdff 100644
--- a/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -1,9 +1,8 @@
//===- DAGISelMatcherEmitter.cpp - Matcher Emitter ------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -259,7 +258,7 @@ void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) {
OS << "\n};";
OS << "\nreturn StringRef(PATTERN_MATCH_TABLE[Index]);";
- OS << "\n}";
+ OS << "\n}\n";
EndEmitFunction(OS);
BeginEmitFunction(OS, "StringRef", "getIncludePathForIndex(unsigned Index)",
@@ -273,7 +272,7 @@ void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) {
OS << "\n};";
OS << "\nreturn StringRef(INCLUDE_PATH_TABLE[Index]);";
- OS << "\n}";
+ OS << "\n}\n";
EndEmitFunction(OS);
}
@@ -555,6 +554,11 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
<< cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n";
return 2;
+ case Matcher::CheckChild2CondCode:
+ OS << "OPC_CheckChild2CondCode, ISD::"
+ << cast<CheckChild2CondCodeMatcher>(N)->getCondCodeName() << ",\n";
+ return 2;
+
case Matcher::CheckValueType:
OS << "OPC_CheckValueType, MVT::"
<< cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n";
@@ -597,6 +601,14 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
OS << "OPC_CheckFoldableChainNode,\n";
return 1;
+ case Matcher::CheckImmAllOnesV:
+ OS << "OPC_CheckImmAllOnesV,\n";
+ return 1;
+
+ case Matcher::CheckImmAllZerosV:
+ OS << "OPC_CheckImmAllZerosV,\n";
+ return 1;
+
case Matcher::EmitInteger: {
int64_t Val = cast<EmitIntegerMatcher>(N)->getValue();
OS << "OPC_EmitInteger, "
@@ -996,12 +1008,15 @@ static StringRef getOpcodeString(Matcher::KindTy Kind) {
case Matcher::CheckInteger: return "OPC_CheckInteger"; break;
case Matcher::CheckChildInteger: return "OPC_CheckChildInteger"; break;
case Matcher::CheckCondCode: return "OPC_CheckCondCode"; break;
+ case Matcher::CheckChild2CondCode: return "OPC_CheckChild2CondCode"; break;
case Matcher::CheckValueType: return "OPC_CheckValueType"; break;
case Matcher::CheckComplexPat: return "OPC_CheckComplexPat"; break;
case Matcher::CheckAndImm: return "OPC_CheckAndImm"; break;
case Matcher::CheckOrImm: return "OPC_CheckOrImm"; break;
case Matcher::CheckFoldableChainNode:
return "OPC_CheckFoldableChainNode"; break;
+ case Matcher::CheckImmAllOnesV: return "OPC_CheckImmAllOnesV"; break;
+ case Matcher::CheckImmAllZerosV: return "OPC_CheckImmAllZerosV"; break;
case Matcher::EmitInteger: return "OPC_EmitInteger"; break;
case Matcher::EmitStringInteger: return "OPC_EmitStringInteger"; break;
case Matcher::EmitRegister: return "OPC_EmitRegister"; break;
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index 612342ddcddf..8f54beeba65b 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -1,9 +1,8 @@
//===- DAGISelMatcherGen.cpp - Matcher generator --------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -278,6 +277,27 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
return;
}
+ if (LeafRec->getName() == "immAllOnesV") {
+ // If this is the root of the dag we're matching, we emit a redundant opcode
+ // check to ensure that this gets folded into the normal top-level
+ // OpcodeSwitch.
+ if (N == Pattern.getSrcPattern()) {
+ const SDNodeInfo &NI = CGP.getSDNodeInfo(CGP.getSDNodeNamed("build_vector"));
+ AddMatcher(new CheckOpcodeMatcher(NI));
+ }
+ return AddMatcher(new CheckImmAllOnesVMatcher());
+ }
+ if (LeafRec->getName() == "immAllZerosV") {
+ // If this is the root of the dag we're matching, we emit a redundant opcode
+ // check to ensure that this gets folded into the normal top-level
+ // OpcodeSwitch.
+ if (N == Pattern.getSrcPattern()) {
+ const SDNodeInfo &NI = CGP.getSDNodeInfo(CGP.getSDNodeNamed("build_vector"));
+ AddMatcher(new CheckOpcodeMatcher(NI));
+ }
+ return AddMatcher(new CheckImmAllZerosVMatcher());
+ }
+
errs() << "Unknown leaf kind: " << *N << "\n";
abort();
}
@@ -671,6 +691,17 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
return;
}
+ if (Def->getName() == "undef_tied_input") {
+ std::array<MVT::SimpleValueType, 1> ResultVTs = {{ N->getSimpleType(0) }};
+ std::array<unsigned, 0> InstOps;
+ auto IDOperandNo = NextRecordedOperandNo++;
+ AddMatcher(new EmitNodeMatcher("TargetOpcode::IMPLICIT_DEF",
+ ResultVTs, InstOps, false, false, false,
+ false, -1, IDOperandNo));
+ ResultOps.push_back(IDOperandNo);
+ return;
+ }
+
// Handle a reference to a register class. This is used
// in COPY_TO_SUBREG instructions.
if (Def->isSubClassOf("RegisterOperand"))
@@ -763,14 +794,27 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// 'execute always' values. Match up the node operands to the instruction
// operands to do this.
unsigned ChildNo = 0;
+
+ // Similarly to the code in TreePatternNode::ApplyTypeConstraints, count the
+ // number of operands at the end of the list which have default values.
+ // Those can come from the pattern if it provides enough arguments, or be
+ // filled in with the default if the pattern hasn't provided them. But any
+ // operand with a default value _before_ the last mandatory one will be
+ // filled in with their defaults unconditionally.
+ unsigned NonOverridableOperands = NumFixedOperands;
+ while (NonOverridableOperands > NumResults &&
+ CGP.operandHasDefault(II.Operands[NonOverridableOperands-1].Rec))
+ --NonOverridableOperands;
+
for (unsigned InstOpNo = NumResults, e = NumFixedOperands;
InstOpNo != e; ++InstOpNo) {
// Determine what to emit for this operand.
Record *OperandNode = II.Operands[InstOpNo].Rec;
- if (OperandNode->isSubClassOf("OperandWithDefaultOps") &&
- !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
- // This is a predicate or optional def operand; emit the
- // 'default ops' operands.
+ if (CGP.operandHasDefault(OperandNode) &&
+ (InstOpNo < NonOverridableOperands || ChildNo >= N->getNumChildren())) {
+ // This is a predicate or optional def operand which the pattern has not
+ // overridden, or which we aren't letting it override; emit the 'default
+ // ops' operands.
const DAGDefaultOperand &DefaultOp
= CGP.getDefaultOperand(OperandNode);
for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i)
diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp
index 554c7438ce3d..7d51b0769372 100644
--- a/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -1,9 +1,8 @@
//===- DAGISelMatcherOpt.cpp - Optimize a DAG Matcher ---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -56,9 +55,13 @@ static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr,
if (MC->getChildNo() < 4) // Only have CheckChildSame0...3
New = new CheckChildSameMatcher(MC->getChildNo(), CS->getMatchNumber());
- if (CheckIntegerMatcher *CS = dyn_cast<CheckIntegerMatcher>(MC->getNext()))
+ if (CheckIntegerMatcher *CI = dyn_cast<CheckIntegerMatcher>(MC->getNext()))
if (MC->getChildNo() < 5) // Only have CheckChildInteger0...4
- New = new CheckChildIntegerMatcher(MC->getChildNo(), CS->getValue());
+ New = new CheckChildIntegerMatcher(MC->getChildNo(), CI->getValue());
+
+ if (auto *CCC = dyn_cast<CheckCondCodeMatcher>(MC->getNext()))
+ if (MC->getChildNo() == 2) // Only have CheckChild2CondCode
+ New = new CheckChild2CondCodeMatcher(CCC->getCondCodeName());
if (New) {
// Insert the new node.
diff --git a/utils/TableGen/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp
index 0db0f55f5ed6..dabcc8f8ed55 100644
--- a/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -1,9 +1,8 @@
//===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine ----===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp
index b99a0a973a2c..9e75c7fba77b 100644
--- a/utils/TableGen/DisassemblerEmitter.cpp
+++ b/utils/TableGen/DisassemblerEmitter.cpp
@@ -1,9 +1,8 @@
//===- DisassemblerEmitter.cpp - Generate a disassembler ------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/ExegesisEmitter.cpp b/utils/TableGen/ExegesisEmitter.cpp
index 208237aca20c..976d5f51776f 100644
--- a/utils/TableGen/ExegesisEmitter.cpp
+++ b/utils/TableGen/ExegesisEmitter.cpp
@@ -1,9 +1,8 @@
//===- ExegesisEmitter.cpp - Generate exegesis target data ----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index 5134b684c6f9..b39956859fe8 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/utils/TableGen/FastISelEmitter.cpp
@@ -1,9 +1,8 @@
///===- FastISelEmitter.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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
index 5e621fc0efdd..f5e975d2e5ae 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -1,9 +1,8 @@
//===------------ FixedLenDecoderEmitter.cpp - Decoder Generator ----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -17,9 +16,10 @@
#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/SetVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCFixedLenDisassembler.h"
@@ -48,6 +48,12 @@ using namespace llvm;
namespace {
+STATISTIC(NumEncodings, "Number of encodings considered");
+STATISTIC(NumEncodingsLackingDisasm, "Number of encodings without disassembler info");
+STATISTIC(NumInstructions, "Number of instructions considered");
+STATISTIC(NumEncodingsSupported, "Number of encodings supported");
+STATISTIC(NumEncodingsOmitted, "Number of encodings omitted");
+
struct EncodingField {
unsigned Base, Width, Offset;
EncodingField(unsigned B, unsigned W, unsigned O)
@@ -95,6 +101,15 @@ struct EncodingAndInst {
: EncodingDef(EncodingDef), Inst(Inst) {}
};
+struct EncodingIDAndOpcode {
+ unsigned EncodingID;
+ unsigned Opcode;
+
+ EncodingIDAndOpcode() : EncodingID(0), Opcode(0) {}
+ EncodingIDAndOpcode(unsigned EncodingID, unsigned Opcode)
+ : EncodingID(EncodingID), Opcode(Opcode) {}
+};
+
raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) {
if (Value.EncodingDef != Value.Inst->TheDef)
OS << Value.EncodingDef->getName() << ":";
@@ -103,6 +118,7 @@ raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) {
}
class FixedLenDecoderEmitter {
+ RecordKeeper &RK;
std::vector<EncodingAndInst> NumberedEncodings;
public:
@@ -114,7 +130,7 @@ public:
std::string ROK = "MCDisassembler::Success",
std::string RFail = "MCDisassembler::Fail",
std::string L = "")
- : Target(R), PredicateNamespace(std::move(PredicateNamespace)),
+ : RK(R), Target(R), PredicateNamespace(std::move(PredicateNamespace)),
GuardPrefix(std::move(GPrefix)), GuardPostfix(std::move(GPostfix)),
ReturnOK(std::move(ROK)), ReturnFail(std::move(RFail)),
Locals(std::move(L)) {}
@@ -252,10 +268,11 @@ 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<EncodingIDAndOpcode>>
+ FilteredInstructions;
// Set of uid's with non-constant segment values.
- std::vector<unsigned> VariableInstructions;
+ std::vector<EncodingIDAndOpcode> VariableInstructions;
// Map of well-known segment value to its delegate.
std::map<unsigned, std::unique_ptr<const FilterChooser>> FilterChooserMap;
@@ -264,7 +281,7 @@ protected:
unsigned NumFiltered;
// Keeps track of the last opcode in the filtered bucket.
- unsigned LastOpcFiltered;
+ EncodingIDAndOpcode LastOpcFiltered;
public:
Filter(Filter &&f);
@@ -274,7 +291,7 @@ public:
unsigned getNumFiltered() const { return NumFiltered; }
- unsigned getSingletonOpc() const {
+ EncodingIDAndOpcode getSingletonOpc() const {
assert(NumFiltered == 1);
return LastOpcFiltered;
}
@@ -341,7 +358,9 @@ protected:
ArrayRef<EncodingAndInst> AllInstructions;
// Vector of uid's for this filter chooser to work on.
- const std::vector<unsigned> &Opcodes;
+ // The first member of the pair is the opcode id being decoded, the second is
+ // the opcode id that should be emitted.
+ const std::vector<EncodingIDAndOpcode> &Opcodes;
// Lookup table for the operand decoding of instructions.
const std::map<unsigned, std::vector<OperandInfo>> &Operands;
@@ -367,7 +386,7 @@ protected:
public:
FilterChooser(ArrayRef<EncodingAndInst> Insts,
- const std::vector<unsigned> &IDs,
+ const std::vector<EncodingIDAndOpcode> &IDs,
const std::map<unsigned, std::vector<OperandInfo>> &Ops,
unsigned BW, const FixedLenDecoderEmitter *E)
: AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
@@ -377,7 +396,7 @@ public:
}
FilterChooser(ArrayRef<EncodingAndInst> Insts,
- const std::vector<unsigned> &IDs,
+ const std::vector<EncodingIDAndOpcode> &IDs,
const std::map<unsigned, std::vector<OperandInfo>> &Ops,
const std::vector<bit_value_t> &ParentFilterBitValues,
const FilterChooser &parent)
@@ -413,6 +432,15 @@ protected:
}
}
+ // Emit the name of the encoding/instruction pair.
+ void emitNameWithID(raw_ostream &OS, unsigned Opcode) const {
+ const Record *EncodingDef = AllInstructions[Opcode].EncodingDef;
+ const Record *InstDef = AllInstructions[Opcode].Inst->TheDef;
+ if (EncodingDef != InstDef)
+ OS << EncodingDef->getName() << ":";
+ OS << InstDef->getName();
+ }
+
// Populates the field of the insn given the start position and the number of
// consecutive bits to scan for.
//
@@ -463,7 +491,7 @@ protected:
// Emits table entries to decode the singleton.
void emitSingletonTableEntry(DecoderTableInfo &TableInfo,
- unsigned Opc) const;
+ EncodingIDAndOpcode Opc) const;
// Emits code to decode the singleton, and then to decode the rest.
void emitSingletonTableEntry(DecoderTableInfo &TableInfo,
@@ -524,13 +552,13 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
assert(StartBit + NumBits - 1 < Owner->BitWidth);
NumFiltered = 0;
- LastOpcFiltered = 0;
+ LastOpcFiltered = {0, 0};
for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) {
insn_t Insn;
// Populates the insn given the uid.
- Owner->insnWithID(Insn, Owner->Opcodes[i]);
+ Owner->insnWithID(Insn, Owner->Opcodes[i].EncodingID);
uint64_t Field;
// Scans the segment for possibly well-specified encoding bits.
@@ -1026,7 +1054,7 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
// 1: Water (the bit value does not affect decoding)
// 2: Island (well-known bit value needed for decoding)
int State = 0;
- int Val = -1;
+ int64_t Val = -1;
for (unsigned i = 0; i < BitWidth; ++i) {
Val = Value(Insn[i]);
@@ -1314,12 +1342,12 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
// Emits table entries to decode the singleton.
void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
- unsigned Opc) const {
+ EncodingIDAndOpcode Opc) const {
std::vector<unsigned> StartBits;
std::vector<unsigned> EndBits;
std::vector<uint64_t> FieldVals;
insn_t Insn;
- insnWithID(Insn, Opc);
+ insnWithID(Insn, Opc.EncodingID);
// Look for islands of undecoded bits of the singleton.
getIslands(StartBits, EndBits, FieldVals, Insn);
@@ -1327,7 +1355,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
unsigned Size = StartBits.size();
// Emit the predicate table entry if one is needed.
- emitPredicateTableEntry(TableInfo, Opc);
+ emitPredicateTableEntry(TableInfo, Opc.EncodingID);
// Check any additional encoding fields needed.
for (unsigned I = Size; I != 0; --I) {
@@ -1351,10 +1379,11 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
}
// Check for soft failure of the match.
- emitSoftFailTableEntry(TableInfo, Opc);
+ emitSoftFailTableEntry(TableInfo, Opc.EncodingID);
bool HasCompleteDecoder;
- unsigned DIdx = getDecoderIndex(TableInfo.Decoders, Opc, HasCompleteDecoder);
+ unsigned DIdx =
+ getDecoderIndex(TableInfo.Decoders, Opc.EncodingID, HasCompleteDecoder);
// Produce OPC_Decode or OPC_TryDecode opcode based on the information
// whether the instruction decoder is complete or not. If it is complete
@@ -1367,8 +1396,9 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
// can decode it.
TableInfo.Table.push_back(HasCompleteDecoder ? MCD::OPC_Decode :
MCD::OPC_TryDecode);
+ NumEncodingsSupported++;
uint8_t Buffer[16], *p;
- encodeULEB128(Opc, Buffer);
+ encodeULEB128(Opc.Opcode, Buffer);
for (p = Buffer; *p >= 128 ; ++p)
TableInfo.Table.push_back(*p);
TableInfo.Table.push_back(*p);
@@ -1394,7 +1424,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
// Emits table entries to decode the singleton, and then to decode the rest.
void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
const Filter &Best) const {
- unsigned Opc = Best.getSingletonOpc();
+ EncodingIDAndOpcode Opc = Best.getSingletonOpc();
// complex singletons need predicate checks from the first singleton
// to refer forward to the variable filterchooser that follows.
@@ -1454,7 +1484,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
std::vector<uint64_t> FieldVals;
insn_t Insn;
- insnWithID(Insn, Opcodes[i]);
+ insnWithID(Insn, Opcodes[i].EncodingID);
// Look for islands of undecoded bits of any instruction.
if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) {
@@ -1498,7 +1528,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
for (unsigned InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) {
insn_t insn;
- insnWithID(insn, Opcodes[InsnIndex]);
+ insnWithID(insn, Opcodes[InsnIndex].EncodingID);
for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
switch (bitAttrs[BitIndex]) {
@@ -1717,9 +1747,12 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
dumpStack(errs(), "\t\t");
for (unsigned i = 0; i < Opcodes.size(); ++i) {
- errs() << '\t' << AllInstructions[Opcodes[i]] << " ";
- dumpBits(errs(),
- getBitsField(*AllInstructions[Opcodes[i]].EncodingDef, "Inst"));
+ errs() << '\t';
+ emitNameWithID(errs(), Opcodes[i].EncodingID);
+ errs() << " ";
+ dumpBits(
+ errs(),
+ getBitsField(*AllInstructions[Opcodes[i].EncodingID].EncodingDef, "Inst"));
errs() << '\n';
}
}
@@ -1751,24 +1784,25 @@ static std::string findOperandDecoderMethod(TypedInit *TI) {
return Decoder;
}
-static bool populateInstruction(CodeGenTarget &Target,
- const CodeGenInstruction &CGI, unsigned Opc,
- std::map<unsigned, std::vector<OperandInfo>> &Operands){
+static bool
+populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
+ const CodeGenInstruction &CGI, unsigned Opc,
+ 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
// of the instruction must be fully specified.
- BitsInit &Bits = getBitsField(Def, "Inst");
+ BitsInit &Bits = getBitsField(EncodingDef, "Inst");
if (Bits.allInComplete()) return false;
std::vector<OperandInfo> InsnOperands;
// If the instruction has specified a custom decoding hook, use that instead
// of trying to auto-generate the decoder.
- StringRef InstDecoder = Def.getValueAsString("DecoderMethod");
+ StringRef InstDecoder = EncodingDef.getValueAsString("DecoderMethod");
if (InstDecoder != "") {
- bool HasCompleteInstDecoder = Def.getValueAsBit("hasCompleteDecoder");
+ bool HasCompleteInstDecoder = EncodingDef.getValueAsBit("hasCompleteDecoder");
InsnOperands.push_back(OperandInfo(InstDecoder, HasCompleteInstDecoder));
Operands[Opc] = InsnOperands;
return true;
@@ -2144,7 +2178,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " const FeatureBitset& Bits = STI.getFeatureBits();\n"
<< "\n"
<< " const uint8_t *Ptr = DecodeTable;\n"
- << " uint32_t CurFieldValue = 0;\n"
+ << " InsnType CurFieldValue = 0;\n"
<< " DecodeStatus S = MCDisassembler::Success;\n"
<< " while (true) {\n"
<< " ptrdiff_t Loc = Ptr - DecodeTable;\n"
@@ -2189,7 +2223,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " unsigned Len = *++Ptr;\n"
<< " InsnType FieldValue = fieldFromInstruction(insn, Start, Len);\n"
<< " // Decode the field value.\n"
- << " uint32_t ExpectedValue = decodeULEB128(++Ptr, &Len);\n"
+ << " InsnType ExpectedValue = decodeULEB128(++Ptr, &Len);\n"
<< " Ptr += Len;\n"
<< " // NumToSkip is a plain 24-bit integer.\n"
<< " unsigned NumToSkip = *Ptr++;\n"
@@ -2336,37 +2370,52 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
// Parameterize the decoders based on namespace and instruction width.
const auto &NumberedInstructions = Target.getInstructionsByEnumValue();
NumberedEncodings.reserve(NumberedInstructions.size());
- for (const auto &NumberedInstruction : NumberedInstructions)
+ DenseMap<Record *, unsigned> IndexOfInstruction;
+ for (const auto &NumberedInstruction : NumberedInstructions) {
+ IndexOfInstruction[NumberedInstruction->TheDef] = NumberedEncodings.size();
NumberedEncodings.emplace_back(NumberedInstruction->TheDef, NumberedInstruction);
+ }
+ for (const auto &NumberedAlias : RK.getAllDerivedDefinitions("AdditionalEncoding"))
+ NumberedEncodings.emplace_back(
+ NumberedAlias,
+ &Target.getInstruction(NumberedAlias->getValueAsDef("AliasOf")));
- std::map<std::pair<std::string, unsigned>,
- std::vector<unsigned>> OpcMap;
+ std::map<std::pair<std::string, unsigned>, std::vector<EncodingIDAndOpcode>>
+ OpcMap;
std::map<unsigned, std::vector<OperandInfo>> Operands;
for (unsigned i = 0; i < NumberedEncodings.size(); ++i) {
+ const Record *EncodingDef = NumberedEncodings[i].EncodingDef;
const CodeGenInstruction *Inst = NumberedEncodings[i].Inst;
const Record *Def = Inst->TheDef;
- unsigned Size = Def->getValueAsInt("Size");
+ unsigned Size = EncodingDef->getValueAsInt("Size");
if (Def->getValueAsString("Namespace") == "TargetOpcode" ||
Def->getValueAsBit("isPseudo") ||
Def->getValueAsBit("isAsmParserOnly") ||
- Def->getValueAsBit("isCodeGenOnly"))
+ Def->getValueAsBit("isCodeGenOnly")) {
+ NumEncodingsLackingDisasm++;
continue;
+ }
- StringRef DecoderNamespace = Def->getValueAsString("DecoderNamespace");
+ if (i < NumberedInstructions.size())
+ NumInstructions++;
+ NumEncodings++;
+
+ StringRef DecoderNamespace = EncodingDef->getValueAsString("DecoderNamespace");
if (Size) {
- if (populateInstruction(Target, *Inst, i, Operands)) {
- OpcMap[std::make_pair(DecoderNamespace, Size)].push_back(i);
- }
+ if (populateInstruction(Target, *EncodingDef, *Inst, i, Operands)) {
+ OpcMap[std::make_pair(DecoderNamespace, Size)].emplace_back(i, IndexOfInstruction.find(Def)->second);
+ } else
+ NumEncodingsOmitted++;
}
}
DecoderTableInfo TableInfo;
for (const auto &Opc : OpcMap) {
// Emit the decoder for this namespace+width combination.
- ArrayRef<EncodingAndInst> NumberedEncodingsRef(NumberedEncodings.data(),
- NumberedEncodings.size());
+ ArrayRef<EncodingAndInst> NumberedEncodingsRef(
+ NumberedEncodings.data(), NumberedEncodings.size());
FilterChooser FC(NumberedEncodingsRef, Opc.second, Operands,
8 * Opc.first.second, this);
diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp
index 997ceb12becd..f1c02134198b 100644
--- a/utils/TableGen/GlobalISelEmitter.cpp
+++ b/utils/TableGen/GlobalISelEmitter.cpp
@@ -1,9 +1,8 @@
//===- 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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -233,6 +232,23 @@ static std::string explainPredicates(const TreePatternNode *N) {
if (Record *VT = P.getScalarMemoryVT())
Explanation += (" ScalarVT(MemVT)=" + VT->getName()).str();
+ if (ListInit *AddrSpaces = P.getAddressSpaces()) {
+ raw_string_ostream OS(Explanation);
+ OS << " AddressSpaces=[";
+
+ StringRef AddrSpaceSeparator;
+ for (Init *Val : AddrSpaces->getValues()) {
+ IntInit *IntVal = dyn_cast<IntInit>(Val);
+ if (!IntVal)
+ continue;
+
+ OS << AddrSpaceSeparator << IntVal->getValue();
+ AddrSpaceSeparator = ", ";
+ }
+
+ OS << ']';
+ }
+
if (P.isAtomicOrderingMonotonic())
Explanation += " monotonic";
if (P.isAtomicOrderingAcquire())
@@ -298,7 +314,7 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) {
Predicate.isSignExtLoad() || Predicate.isZeroExtLoad())
continue;
- if (Predicate.isNonTruncStore())
+ if (Predicate.isNonTruncStore() || Predicate.isTruncStore())
continue;
if (Predicate.isLoad() && Predicate.getMemoryVT())
@@ -309,6 +325,12 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) {
continue;
}
+ if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) {
+ const ListInit *AddrSpaces = Predicate.getAddressSpaces();
+ if (AddrSpaces && !AddrSpaces->empty())
+ continue;
+ }
+
if (Predicate.isAtomic() && Predicate.getMemoryVT())
continue;
@@ -882,12 +904,19 @@ public:
void defineOperand(StringRef SymbolicName, OperandMatcher &OM);
- void defineComplexSubOperand(StringRef SymbolicName, Record *ComplexPattern,
- unsigned RendererID, unsigned SubOperandID) {
- assert(ComplexSubOperands.count(SymbolicName) == 0 && "Already defined");
+ Error defineComplexSubOperand(StringRef SymbolicName, Record *ComplexPattern,
+ unsigned RendererID, unsigned SubOperandID) {
+ if (ComplexSubOperands.count(SymbolicName))
+ return failedImport(
+ "Complex suboperand referenced more than once (Operand: " +
+ SymbolicName + ")");
+
ComplexSubOperands[SymbolicName] =
std::make_tuple(ComplexPattern, RendererID, SubOperandID);
+
+ return Error::success();
}
+
Optional<DefinedComplexPatternSubOperand>
getComplexSubOperand(StringRef SymbolicName) const {
const auto &I = ComplexSubOperands.find(SymbolicName);
@@ -1022,6 +1051,7 @@ public:
IPM_AtomicOrderingMMO,
IPM_MemoryLLTSize,
IPM_MemoryVsLLTSize,
+ IPM_MemoryAddressSpace,
IPM_GenericPredicate,
OPM_SameOperand,
OPM_ComplexPattern,
@@ -1507,6 +1537,9 @@ Error OperandMatcher::addTypeCheckPredicate(const TypeSetByHwMode &VTy,
if (OperandIsAPointer)
addPredicate<PointerToAnyOperandMatcher>(OpTyOrNone->get().getSizeInBits());
+ else if (VTy.isPointer())
+ addPredicate<LLTOperandMatcher>(LLT::pointer(VTy.getPtrAddrSpace(),
+ OpTyOrNone->get().getSizeInBits()));
else
addPredicate<LLTOperandMatcher>(*OpTyOrNone);
return Error::success();
@@ -1780,6 +1813,42 @@ public:
}
};
+class MemoryAddressSpacePredicateMatcher : public InstructionPredicateMatcher {
+protected:
+ unsigned MMOIdx;
+ SmallVector<unsigned, 4> AddrSpaces;
+
+public:
+ MemoryAddressSpacePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx,
+ ArrayRef<unsigned> AddrSpaces)
+ : InstructionPredicateMatcher(IPM_MemoryAddressSpace, InsnVarID),
+ MMOIdx(MMOIdx), AddrSpaces(AddrSpaces.begin(), AddrSpaces.end()) {}
+
+ static bool classof(const PredicateMatcher *P) {
+ return P->getKind() == IPM_MemoryAddressSpace;
+ }
+ bool isIdentical(const PredicateMatcher &B) const override {
+ if (!InstructionPredicateMatcher::isIdentical(B))
+ return false;
+ auto *Other = cast<MemoryAddressSpacePredicateMatcher>(&B);
+ return MMOIdx == Other->MMOIdx && AddrSpaces == Other->AddrSpaces;
+ }
+
+ void emitPredicateOpcodes(MatchTable &Table,
+ RuleMatcher &Rule) const override {
+ Table << MatchTable::Opcode("GIM_CheckMemoryAddressSpace")
+ << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
+ << MatchTable::Comment("MMO") << MatchTable::IntValue(MMOIdx)
+ // Encode number of address spaces to expect.
+ << MatchTable::Comment("NumAddrSpace")
+ << MatchTable::IntValue(AddrSpaces.size());
+ for (unsigned AS : AddrSpaces)
+ Table << MatchTable::Comment("AddrSpace") << MatchTable::IntValue(AS);
+
+ Table << MatchTable::LineBreak;
+ }
+};
+
/// Generates code to check that the size of an MMO is less-than, equal-to, or
/// greater than a given LLT.
class MemoryVsLLTSizePredicateMatcher : public InstructionPredicateMatcher {
@@ -3028,7 +3097,8 @@ private:
importExplicitUseRenderer(action_iterator InsertPt, RuleMatcher &Rule,
BuildMIAction &DstMIBuilder,
TreePatternNode *DstChild);
- Error importDefaultOperandRenderers(BuildMIAction &DstMIBuilder,
+ Error importDefaultOperandRenderers(action_iterator InsertPt, RuleMatcher &M,
+ BuildMIAction &DstMIBuilder,
DagInit *DefaultOps) const;
Error
importImplicitDefRenderers(BuildMIAction &DstMIBuilder,
@@ -3200,7 +3270,26 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
continue;
}
- // G_LOAD is used for both non-extending and any-extending loads.
+ // An address space check is needed in all contexts if there is one.
+ if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) {
+ if (const ListInit *AddrSpaces = Predicate.getAddressSpaces()) {
+ SmallVector<unsigned, 4> ParsedAddrSpaces;
+
+ for (Init *Val : AddrSpaces->getValues()) {
+ IntInit *IntVal = dyn_cast<IntInit>(Val);
+ if (!IntVal)
+ return failedImport("Address space is not an integer");
+ ParsedAddrSpaces.push_back(IntVal->getValue());
+ }
+
+ if (!ParsedAddrSpaces.empty()) {
+ InsnMatcher.addPredicate<MemoryAddressSpacePredicateMatcher>(
+ 0, ParsedAddrSpaces);
+ }
+ }
+ }
+
+ // G_LOAD is used for both non-extending and any-extending loads.
if (Predicate.isLoad() && Predicate.isNonExtLoad()) {
InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>(
0, MemoryVsLLTSizePredicateMatcher::EqualTo, 0);
@@ -3212,6 +3301,13 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
continue;
}
+ if (Predicate.isStore() && Predicate.isTruncStore()) {
+ // FIXME: If MemoryVT is set, we end up with 2 checks for the MMO size.
+ InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>(
+ 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0);
+ continue;
+ }
+
// No check required. We already did it by swapping the opcode.
if (!SrcGIEquivOrNull->isValueUnset("IfSignExtend") &&
Predicate.isSignExtLoad())
@@ -3422,9 +3518,12 @@ Error GlobalISelEmitter::importChildMatcher(RuleMatcher &Rule,
for (unsigned i = 0, e = SrcChild->getNumChildren(); i != e; ++i) {
auto *SubOperand = SrcChild->getChild(i);
- if (!SubOperand->getName().empty())
- Rule.defineComplexSubOperand(SubOperand->getName(),
- SrcChild->getOperator(), RendererID, i);
+ if (!SubOperand->getName().empty()) {
+ if (auto Error = Rule.defineComplexSubOperand(SubOperand->getName(),
+ SrcChild->getOperator(),
+ RendererID, i))
+ return Error;
+ }
}
return Error::success();
@@ -3765,7 +3864,8 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
// end up with too many rendered operands.
if (DstIOperand.Rec->isSubClassOf("OperandWithDefaultOps")) {
DagInit *DefaultOps = DstIOperand.Rec->getValueAsDag("DefaultOps");
- if (auto Error = importDefaultOperandRenderers(DstMIBuilder, DefaultOps))
+ if (auto Error = importDefaultOperandRenderers(
+ InsertPt, M, DstMIBuilder, DefaultOps))
return std::move(Error);
++NumDefaultOps;
continue;
@@ -3790,19 +3890,39 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
}
Error GlobalISelEmitter::importDefaultOperandRenderers(
- BuildMIAction &DstMIBuilder, DagInit *DefaultOps) const {
+ action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
+ DagInit *DefaultOps) const {
for (const auto *DefaultOp : DefaultOps->getArgs()) {
+ Optional<LLTCodeGen> OpTyOrNone = None;
+
// Look through ValueType operators.
if (const DagInit *DefaultDagOp = dyn_cast<DagInit>(DefaultOp)) {
if (const DefInit *DefaultDagOperator =
dyn_cast<DefInit>(DefaultDagOp->getOperator())) {
- if (DefaultDagOperator->getDef()->isSubClassOf("ValueType"))
+ if (DefaultDagOperator->getDef()->isSubClassOf("ValueType")) {
+ OpTyOrNone = MVTToLLT(getValueType(
+ DefaultDagOperator->getDef()));
DefaultOp = DefaultDagOp->getArg(0);
+ }
}
}
if (const DefInit *DefaultDefOp = dyn_cast<DefInit>(DefaultOp)) {
- DstMIBuilder.addRenderer<AddRegisterRenderer>(DefaultDefOp->getDef());
+ auto Def = DefaultDefOp->getDef();
+ if (Def->getName() == "undef_tied_input") {
+ unsigned TempRegID = M.allocateTempRegID();
+ M.insertAction<MakeTempRegisterAction>(
+ InsertPt, OpTyOrNone.getValue(), TempRegID);
+ InsertPt = M.insertAction<BuildMIAction>(
+ InsertPt, M.allocateOutputInsnID(),
+ &Target.getInstruction(RK.getDef("IMPLICIT_DEF")));
+ BuildMIAction &IDMIBuilder = *static_cast<BuildMIAction *>(
+ InsertPt->get());
+ IDMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
+ DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
+ } else {
+ DstMIBuilder.addRenderer<AddRegisterRenderer>(Def);
+ }
continue;
}
@@ -4489,8 +4609,7 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
<< ", // " << Record->getName() << "\n";
OS << "};\n\n";
- std::stable_sort(Rules.begin(), Rules.end(), [&](const RuleMatcher &A,
- const RuleMatcher &B) {
+ llvm::stable_sort(Rules, [&](const RuleMatcher &A, const RuleMatcher &B) {
int ScoreA = RuleMatcherScores[A.getRuleID()];
int ScoreB = RuleMatcherScores[B.getRuleID()];
if (ScoreA > ScoreB)
diff --git a/utils/TableGen/InfoByHwMode.cpp b/utils/TableGen/InfoByHwMode.cpp
index 086e12dafd74..d9662889a5db 100644
--- a/utils/TableGen/InfoByHwMode.cpp
+++ b/utils/TableGen/InfoByHwMode.cpp
@@ -1,9 +1,8 @@
//===--- InfoByHwMode.cpp -------------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Classes that implement data parameterized by HW modes for instruction
@@ -39,6 +38,11 @@ ValueTypeByHwMode::ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH) {
}
}
+ValueTypeByHwMode::ValueTypeByHwMode(Record *R, MVT T) : ValueTypeByHwMode(T) {
+ if (R->isSubClassOf("PtrValueType"))
+ PtrAddrSpace = R->getValueAsInt("AddrSpace");
+}
+
bool ValueTypeByHwMode::operator== (const ValueTypeByHwMode &T) const {
assert(isValid() && T.isValid() && "Invalid type in assignment");
bool Simple = isSimple();
@@ -112,7 +116,7 @@ ValueTypeByHwMode llvm::getValueTypeByHwMode(Record *Rec,
"Record must be derived from ValueType");
if (Rec->isSubClassOf("HwModeSelect"))
return ValueTypeByHwMode(Rec, CGH);
- return ValueTypeByHwMode(llvm::getValueType(Rec));
+ return ValueTypeByHwMode(Rec, llvm::getValueType(Rec));
}
RegSizeInfo::RegSizeInfo(Record *R, const CodeGenHwModes &CGH) {
diff --git a/utils/TableGen/InfoByHwMode.h b/utils/TableGen/InfoByHwMode.h
index 7be4678f271b..9e5cc3d5f2a4 100644
--- a/utils/TableGen/InfoByHwMode.h
+++ b/utils/TableGen/InfoByHwMode.h
@@ -1,9 +1,8 @@
//===--- InfoByHwMode.h -----------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Classes that implement data parameterized by HW modes for instruction
@@ -120,6 +119,7 @@ struct InfoByHwMode {
struct ValueTypeByHwMode : public InfoByHwMode<MVT> {
ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH);
+ ValueTypeByHwMode(Record *R, MVT T);
ValueTypeByHwMode(MVT T) { Map.insert({DefaultMode,T}); }
ValueTypeByHwMode() = default;
@@ -135,6 +135,11 @@ struct ValueTypeByHwMode : public InfoByHwMode<MVT> {
static StringRef getMVTName(MVT T);
void writeToStream(raw_ostream &OS) const;
void dump() const;
+
+ unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max();
+ bool isPointer() const {
+ return PtrAddrSpace != std::numeric_limits<unsigned>::max();
+ }
};
ValueTypeByHwMode getValueTypeByHwMode(Record *Rec,
diff --git a/utils/TableGen/InstrDocsEmitter.cpp b/utils/TableGen/InstrDocsEmitter.cpp
index 9d50351854ec..91c457ba08fd 100644
--- a/utils/TableGen/InstrDocsEmitter.cpp
+++ b/utils/TableGen/InstrDocsEmitter.cpp
@@ -1,9 +1,8 @@
//===- InstrDocsEmitter.cpp - Opcode Documentation Generator --------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 39d9e8526386..2d367f538b71 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -1,9 +1,8 @@
//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. --*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -77,7 +76,9 @@ private:
std::map<std::vector<Record*>, unsigned> &EL,
const OperandInfoMapTy &OpInfo,
raw_ostream &OS);
- void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target);
+ void emitOperandTypeMappings(
+ raw_ostream &OS, const CodeGenTarget &Target,
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions);
void initOperandMapData(
ArrayRef<const CodeGenInstruction *> NumberedInstructions,
StringRef Namespace,
@@ -212,7 +213,7 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
}
/// Initialize data structures for generating operand name mappings.
-///
+///
/// \param Operands [out] A map used to generate the OpName enum with operand
/// names as its keys and operand enum values as its values.
/// \param OperandMap [out] A map for representing the operand name mappings for
@@ -325,8 +326,9 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
/// Generate an enum for all the operand types for this target, under the
/// llvm::TargetNamespace::OpTypes namespace.
/// Operand types are all definitions derived of the Operand Target.td class.
-void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
- const CodeGenTarget &Target) {
+void InstrInfoEmitter::emitOperandTypeMappings(
+ raw_ostream &OS, const CodeGenTarget &Target,
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
StringRef Namespace = Target.getInstNamespace();
std::vector<Record *> Operands = Records.getAllDerivedDefinitions("Operand");
@@ -350,6 +352,69 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
OS << "} // end namespace " << Namespace << "\n";
OS << "} // end namespace llvm\n";
OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n";
+
+ OS << "#ifdef GET_INSTRINFO_OPERAND_TYPE\n";
+ OS << "#undef GET_INSTRINFO_OPERAND_TYPE\n";
+ OS << "namespace llvm {\n";
+ OS << "namespace " << Namespace << " {\n";
+ OS << "LLVM_READONLY\n";
+ OS << "int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n";
+ if (!NumberedInstructions.empty()) {
+ std::vector<int> OperandOffsets;
+ std::vector<Record *> OperandRecords;
+ int CurrentOffset = 0;
+ for (const CodeGenInstruction *Inst : NumberedInstructions) {
+ OperandOffsets.push_back(CurrentOffset);
+ for (const auto &Op : Inst->Operands) {
+ const DagInit *MIOI = Op.MIOperandInfo;
+ if (!MIOI || MIOI->getNumArgs() == 0) {
+ // Single, anonymous, operand.
+ OperandRecords.push_back(Op.Rec);
+ ++CurrentOffset;
+ } else {
+ for (Init *Arg : make_range(MIOI->arg_begin(), MIOI->arg_end())) {
+ OperandRecords.push_back(cast<DefInit>(Arg)->getDef());
+ ++CurrentOffset;
+ }
+ }
+ }
+ }
+
+ // Emit the table of offsets for the opcode lookup.
+ OS << " const int Offsets[] = {\n";
+ for (int I = 0, E = OperandOffsets.size(); I != E; ++I)
+ OS << " " << OperandOffsets[I] << ",\n";
+ OS << " };\n";
+
+ // Add an entry for the end so that we don't need to special case it below.
+ OperandOffsets.push_back(OperandRecords.size());
+ // Emit the actual operand types in a flat table.
+ OS << " const int OpcodeOperandTypes[] = {\n ";
+ for (int I = 0, E = OperandRecords.size(), CurOffset = 1; I != E; ++I) {
+ // We print each Opcode's operands in its own row.
+ if (I == OperandOffsets[CurOffset]) {
+ OS << "\n ";
+ // If there are empty rows, mark them with an empty comment.
+ while (OperandOffsets[++CurOffset] == I)
+ OS << "/**/\n ";
+ }
+ Record *OpR = OperandRecords[I];
+ if (OpR->isSubClassOf("Operand") && !OpR->isAnonymous())
+ OS << "OpTypes::" << OpR->getName();
+ else
+ OS << -1;
+ OS << ", ";
+ }
+ OS << "\n };\n";
+
+ OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n";
+ } else {
+ OS << " llvm_unreachable(\"No instructions defined\");\n";
+ }
+ OS << "}\n";
+ OS << "} // end namespace " << Namespace << "\n";
+ OS << "} // end namespace llvm\n";
+ OS << "#endif //GET_INSTRINFO_OPERAND_TYPE\n\n";
}
void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS,
@@ -561,7 +626,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
emitOperandNameMappings(OS, Target, NumberedInstructions);
- emitOperandTypesEnum(OS, Target);
+ emitOperandTypeMappings(OS, Target, NumberedInstructions);
emitMCIIHelperMethods(OS, TargetName);
}
@@ -604,6 +669,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
if (Inst.canFoldAsLoad) OS << "|(1ULL<<MCID::FoldableAsLoad)";
if (Inst.mayLoad) OS << "|(1ULL<<MCID::MayLoad)";
if (Inst.mayStore) OS << "|(1ULL<<MCID::MayStore)";
+ if (Inst.mayRaiseFPException) OS << "|(1ULL<<MCID::MayRaiseFPException)";
if (Inst.isPredicable) OS << "|(1ULL<<MCID::Predicable)";
if (Inst.isConvertibleToThreeAddress) OS << "|(1ULL<<MCID::ConvertibleTo3Addr)";
if (Inst.isCommutable) OS << "|(1ULL<<MCID::Commutable)";
@@ -629,13 +695,14 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
// Emit all of the target-specific flags...
BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
if (!TSF)
- PrintFatalError("no TSFlags?");
+ PrintFatalError(Inst.TheDef->getLoc(), "no TSFlags?");
uint64_t Value = 0;
for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++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());
+ PrintFatalError(Inst.TheDef->getLoc(),
+ "Invalid TSFlags bit in " + Inst.TheDef->getName());
}
OS << ", 0x";
OS.write_hex(Value);
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index 049282e5ebfe..979af98f6768 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -1,9 +1,8 @@
//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -220,7 +219,8 @@ enum IIT_Info {
IIT_STRUCT6 = 38,
IIT_STRUCT7 = 39,
IIT_STRUCT8 = 40,
- IIT_F128 = 41
+ IIT_F128 = 41,
+ IIT_VEC_ELEMENT = 42
};
static void EncodeFixedValueType(MVT::SimpleValueType VT,
@@ -259,10 +259,12 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
#endif
static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
- std::vector<unsigned char> &Sig) {
+ unsigned &NextArgCode,
+ std::vector<unsigned char> &Sig,
+ ArrayRef<unsigned char> Mapping) {
if (R->isSubClassOf("LLVMMatchType")) {
- unsigned Number = R->getValueAsInt("Number");
+ unsigned Number = Mapping[R->getValueAsInt("Number")];
assert(Number < ArgCodes.size() && "Invalid matching number!");
if (R->isSubClassOf("LLVMExtendedType"))
Sig.push_back(IIT_EXTEND_ARG);
@@ -270,7 +272,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
Sig.push_back(IIT_TRUNC_ARG);
else if (R->isSubClassOf("LLVMHalfElementsVectorType"))
Sig.push_back(IIT_HALF_VEC_ARG);
- else if (R->isSubClassOf("LLVMVectorSameWidth")) {
+ else if (R->isSubClassOf("LLVMScalarOrSameVectorWidth")) {
Sig.push_back(IIT_SAME_VEC_WIDTH_ARG);
Sig.push_back((Number << 3) | ArgCodes[Number]);
MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy"));
@@ -281,18 +283,18 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
Sig.push_back(IIT_PTR_TO_ARG);
else if (R->isSubClassOf("LLVMVectorOfAnyPointersToElt")) {
Sig.push_back(IIT_VEC_OF_ANYPTRS_TO_ELT);
- unsigned ArgNo = ArgCodes.size();
- ArgCodes.push_back(3 /*vAny*/);
// Encode overloaded ArgNo
- Sig.push_back(ArgNo);
+ Sig.push_back(NextArgCode++);
// Encode LLVMMatchType<Number> ArgNo
Sig.push_back(Number);
return;
} else if (R->isSubClassOf("LLVMPointerToElt"))
Sig.push_back(IIT_PTR_TO_ELT);
+ else if (R->isSubClassOf("LLVMVectorElementType"))
+ Sig.push_back(IIT_VEC_ELEMENT);
else
Sig.push_back(IIT_ARG);
- return Sig.push_back((Number << 3) | ArgCodes[Number]);
+ return Sig.push_back((Number << 3) | 7 /*IITDescriptor::AK_MatchType*/);
}
MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
@@ -310,8 +312,9 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
Sig.push_back(IIT_ARG);
// Figure out what arg # this is consuming, and remember what kind it was.
- unsigned ArgNo = ArgCodes.size();
- ArgCodes.push_back(Tmp);
+ assert(NextArgCode < ArgCodes.size() && ArgCodes[NextArgCode] == Tmp &&
+ "Invalid or no ArgCode associated with overloaded VT!");
+ unsigned ArgNo = NextArgCode++;
// Encode what sort of argument it must be in the low 3 bits of the ArgNo.
return Sig.push_back((ArgNo << 3) | Tmp);
@@ -329,7 +332,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
} else {
Sig.push_back(IIT_PTR);
}
- return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, Sig);
+ return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, NextArgCode, Sig,
+ Mapping);
}
}
@@ -354,6 +358,45 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
EncodeFixedValueType(VT, Sig);
}
+static void UpdateArgCodes(Record *R, std::vector<unsigned char> &ArgCodes,
+ unsigned int &NumInserted,
+ SmallVectorImpl<unsigned char> &Mapping) {
+ if (R->isSubClassOf("LLVMMatchType")) {
+ if (R->isSubClassOf("LLVMVectorOfAnyPointersToElt")) {
+ ArgCodes.push_back(3 /*vAny*/);
+ ++NumInserted;
+ }
+ return;
+ }
+
+ unsigned Tmp = 0;
+ switch (getValueType(R->getValueAsDef("VT"))) {
+ default: break;
+ case MVT::iPTR:
+ UpdateArgCodes(R->getValueAsDef("ElTy"), ArgCodes, NumInserted, Mapping);
+ break;
+ 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:
+ unsigned OriginalIdx = ArgCodes.size() - NumInserted;
+ assert(OriginalIdx >= Mapping.size());
+ Mapping.resize(OriginalIdx+1);
+ Mapping[OriginalIdx] = ArgCodes.size();
+ ArgCodes.push_back(Tmp);
+ break;
+ }
+}
+
#if defined(_MSC_VER) && !defined(__clang__)
#pragma optimize("",on)
#endif
@@ -364,6 +407,17 @@ static void ComputeFixedEncoding(const CodeGenIntrinsic &Int,
std::vector<unsigned char> &TypeSig) {
std::vector<unsigned char> ArgCodes;
+ // Add codes for any overloaded result VTs.
+ unsigned int NumInserted = 0;
+ SmallVector<unsigned char, 8> ArgMapping;
+ for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i)
+ UpdateArgCodes(Int.IS.RetTypeDefs[i], ArgCodes, NumInserted, ArgMapping);
+
+ // Add codes for any overloaded operand VTs.
+ for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i)
+ UpdateArgCodes(Int.IS.ParamTypeDefs[i], ArgCodes, NumInserted, ArgMapping);
+
+ unsigned NextArgCode = 0;
if (Int.IS.RetVTs.empty())
TypeSig.push_back(IIT_Done);
else if (Int.IS.RetVTs.size() == 1 &&
@@ -383,11 +437,13 @@ static void ComputeFixedEncoding(const CodeGenIntrinsic &Int,
}
for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i)
- EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, TypeSig);
+ EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, NextArgCode, TypeSig,
+ ArgMapping);
}
for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i)
- EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, TypeSig);
+ EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, NextArgCode, TypeSig,
+ ArgMapping);
}
static void printIITEntry(raw_ostream &OS, unsigned char X) {
@@ -489,6 +545,9 @@ struct AttributeComparator {
if (L->isNoReturn != R->isNoReturn)
return R->isNoReturn;
+ if (L->isWillReturn != R->isWillReturn)
+ return R->isWillReturn;
+
if (L->isCold != R->isCold)
return R->isCold;
@@ -505,7 +564,6 @@ struct AttributeComparator {
CodeGenIntrinsic::ModRefBehavior LK = L->ModRef;
CodeGenIntrinsic::ModRefBehavior RK = R->ModRef;
if (LK != RK) return (LK > RK);
-
// Order by argument attributes.
// This is reliable because each side is already sorted internally.
return (L->ArgumentAttributes < R->ArgumentAttributes);
@@ -613,6 +671,12 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
OS << "Attribute::ReadNone";
addComma = true;
break;
+ case CodeGenIntrinsic::ImmArg:
+ if (addComma)
+ OS << ',';
+ OS << "Attribute::ImmArg";
+ addComma = true;
+ break;
}
++ai;
@@ -624,9 +688,10 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
}
if (!intrinsic.canThrow ||
- intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem ||
- intrinsic.isNoReturn || intrinsic.isCold || intrinsic.isNoDuplicate ||
- intrinsic.isConvergent || intrinsic.isSpeculatable) {
+ (intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem && !intrinsic.hasSideEffects) ||
+ intrinsic.isNoReturn || intrinsic.isWillReturn || intrinsic.isCold ||
+ intrinsic.isNoDuplicate || intrinsic.isConvergent ||
+ intrinsic.isSpeculatable) {
OS << " const Attribute::AttrKind Atts[] = {";
bool addComma = false;
if (!intrinsic.canThrow) {
@@ -639,6 +704,12 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
OS << "Attribute::NoReturn";
addComma = true;
}
+ if (intrinsic.isWillReturn) {
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::WillReturn";
+ addComma = true;
+ }
if (intrinsic.isCold) {
if (addComma)
OS << ",";
@@ -666,6 +737,8 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
switch (intrinsic.ModRef) {
case CodeGenIntrinsic::NoMem:
+ if (intrinsic.hasSideEffects)
+ break;
if (addComma)
OS << ",";
OS << "Attribute::ReadNone";
@@ -771,8 +844,9 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
BuiltinMap[Ints[i].TargetPrefix];
if (!BIM.insert(std::make_pair(BuiltinName, Ints[i].EnumName)).second)
- PrintFatalError("Intrinsic '" + Ints[i].TheDef->getName() +
- "': duplicate " + CompilerName + " builtin name!");
+ PrintFatalError(Ints[i].TheDef->getLoc(),
+ "Intrinsic '" + Ints[i].TheDef->getName() +
+ "': duplicate " + CompilerName + " builtin name!");
Table.GetOrAddStringOffset(BuiltinName);
}
}
diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp
index 0358cf26509b..51b1cb093b21 100644
--- a/utils/TableGen/OptParserEmitter.cpp
+++ b/utils/TableGen/OptParserEmitter.cpp
@@ -1,9 +1,8 @@
//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/PredicateExpander.cpp b/utils/TableGen/PredicateExpander.cpp
index 2e01b7c3138e..9f7f40db2626 100644
--- a/utils/TableGen/PredicateExpander.cpp
+++ b/utils/TableGen/PredicateExpander.cpp
@@ -1,9 +1,8 @@
//===--------------------- PredicateExpander.cpp --------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
diff --git a/utils/TableGen/PredicateExpander.h b/utils/TableGen/PredicateExpander.h
index 0f3ee6867e65..115a81cf123b 100644
--- a/utils/TableGen/PredicateExpander.h
+++ b/utils/TableGen/PredicateExpander.h
@@ -1,9 +1,8 @@
//===--------------------- PredicateExpander.h ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp
index a363015730f3..3a80d8e5d1c4 100644
--- a/utils/TableGen/PseudoLoweringEmitter.cpp
+++ b/utils/TableGen/PseudoLoweringEmitter.cpp
@@ -1,9 +1,8 @@
//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/RISCVCompressInstEmitter.cpp b/utils/TableGen/RISCVCompressInstEmitter.cpp
index e03663b40f8a..e62f528ebc2e 100644
--- a/utils/TableGen/RISCVCompressInstEmitter.cpp
+++ b/utils/TableGen/RISCVCompressInstEmitter.cpp
@@ -1,9 +1,8 @@
//===- RISCVCompressInstEmitter.cpp - Generator for RISCV Compression -===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// RISCVCompressInstEmitter implements a tablegen-driven CompressPat based
// RISCV Instruction Compression mechanism.
@@ -65,6 +64,7 @@
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
+#include <set>
#include <vector>
using namespace llvm;
@@ -253,12 +253,14 @@ static bool verifyDagOpCount(CodeGenInstruction &Inst, DagInit *Dag,
// Source instructions are non compressed instructions and don't have tied
// operands.
if (IsSource)
- PrintFatalError("Input operands for Inst '" + Inst.TheDef->getName() +
- "' and input Dag operand count mismatch");
+ PrintFatalError(Inst.TheDef->getLoc(),
+ "Input operands for Inst '" + Inst.TheDef->getName() +
+ "' and input Dag operand count mismatch");
// The Dag can't have more arguments than the Instruction.
if (Dag->getNumArgs() > Inst.Operands.size())
- PrintFatalError("Inst '" + Inst.TheDef->getName() +
- "' and Dag operand count mismatch");
+ PrintFatalError(Inst.TheDef->getLoc(),
+ "Inst '" + Inst.TheDef->getName() +
+ "' and Dag operand count mismatch");
// The Instruction might have tied operands so the Dag might have
// a fewer operand count.
@@ -268,8 +270,9 @@ static bool verifyDagOpCount(CodeGenInstruction &Inst, DagInit *Dag,
--RealCount;
if (Dag->getNumArgs() != RealCount)
- PrintFatalError("Inst '" + Inst.TheDef->getName() +
- "' and Dag operand count mismatch");
+ PrintFatalError(Inst.TheDef->getLoc(),
+ "Inst '" + Inst.TheDef->getName() +
+ "' and Dag operand count mismatch");
return true;
}
@@ -472,7 +475,7 @@ void RISCVCompressInstEmitter::evaluateCompressPat(Record *Rec) {
SourceOperandMap, DestOperandMap));
}
-static void getReqFeatures(std::map<StringRef, int> &FeaturesMap,
+static void getReqFeatures(std::set<StringRef> &FeaturesSet,
const std::vector<Record *> &ReqFeatures) {
for (auto &R : ReqFeatures) {
StringRef AsmCondString = R->getValueAsString("AssemblerCondString");
@@ -481,11 +484,9 @@ static void getReqFeatures(std::map<StringRef, int> &FeaturesMap,
SmallVector<StringRef, 4> Ops;
SplitString(AsmCondString, Ops, ",");
assert(!Ops.empty() && "AssemblerCondString cannot be empty");
-
for (auto &Op : Ops) {
assert(!Op.empty() && "Empty operator");
- if (FeaturesMap.find(Op) == FeaturesMap.end())
- FeaturesMap[Op] = FeaturesMap.size();
+ FeaturesSet.insert(Op);
}
}
}
@@ -530,7 +531,8 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o,
bool Compress) {
Record *AsmWriter = Target.getAsmWriter();
if (!AsmWriter->getValueAsInt("PassSubtarget"))
- PrintFatalError("'PassSubtarget' is false. SubTargetInfo object is needed "
+ PrintFatalError(AsmWriter->getLoc(),
+ "'PassSubtarget' is false. SubTargetInfo object is needed "
"for target features.\n");
std::string Namespace = Target.getName();
@@ -540,15 +542,15 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o,
// transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the
// source and destination are flipped and the sort key needs to change
// accordingly.
- std::stable_sort(CompressPatterns.begin(), CompressPatterns.end(),
- [Compress](const CompressPat &LHS, const CompressPat &RHS) {
- if (Compress)
- return (LHS.Source.TheDef->getName().str() <
- RHS.Source.TheDef->getName().str());
- else
- return (LHS.Dest.TheDef->getName().str() <
- RHS.Dest.TheDef->getName().str());
- });
+ llvm::stable_sort(CompressPatterns,
+ [Compress](const CompressPat &LHS, const CompressPat &RHS) {
+ if (Compress)
+ return (LHS.Source.TheDef->getName().str() <
+ RHS.Source.TheDef->getName().str());
+ else
+ return (LHS.Dest.TheDef->getName().str() <
+ RHS.Dest.TheDef->getName().str());
+ });
// A list of MCOperandPredicates for all operands in use, and the reverse map.
std::vector<const Record *> MCOpPredicates;
@@ -617,9 +619,9 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o,
CaseStream.indent(4) << "case " + Namespace + "::" + CurOp + ": {\n";
}
- std::map<StringRef, int> FeaturesMap;
+ std::set<StringRef> FeaturesSet;
// Add CompressPat required features.
- getReqFeatures(FeaturesMap, CompressPat.PatReqFeatures);
+ getReqFeatures(FeaturesSet, CompressPat.PatReqFeatures);
// Add Dest instruction required features.
std::vector<Record *> ReqFeatures;
@@ -627,11 +629,10 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o,
copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) {
return R->getValueAsBit("AssemblerMatcherPredicate");
});
- getReqFeatures(FeaturesMap, ReqFeatures);
+ getReqFeatures(FeaturesSet, ReqFeatures);
// Emit checks for all required features.
- for (auto &F : FeaturesMap) {
- StringRef Op = F.first;
+ for (auto &Op : FeaturesSet) {
if (Op[0] == '!')
CondStream.indent(6) << ("!STI.getFeatureBits()[" + Namespace +
"::" + Op.substr(1) + "]")
diff --git a/utils/TableGen/RegisterBankEmitter.cpp b/utils/TableGen/RegisterBankEmitter.cpp
index 879b4162d629..7f6b3931d3de 100644
--- a/utils/TableGen/RegisterBankEmitter.cpp
+++ b/utils/TableGen/RegisterBankEmitter.cpp
@@ -1,9 +1,8 @@
//===- RegisterBankEmitter.cpp - Generate a Register Bank Desc. -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index ded54c828bcd..1b619072c814 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -1,9 +1,8 @@
//===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/SDNodeProperties.cpp b/utils/TableGen/SDNodeProperties.cpp
index 343febc99d1e..1843a78aa3cf 100644
--- a/utils/TableGen/SDNodeProperties.cpp
+++ b/utils/TableGen/SDNodeProperties.cpp
@@ -1,9 +1,8 @@
//===- SDNodeProperties.cpp -----------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -39,9 +38,9 @@ unsigned llvm::parseSDPatternOperatorProperties(Record *R) {
} else if (Property->getName() == "SDNPVariadic") {
Properties |= 1 << SDNPVariadic;
} else {
- PrintFatalError("Unknown SD Node property '" +
- Property->getName() + "' on node '" +
- R->getName() + "'!");
+ PrintFatalError(R->getLoc(), "Unknown SD Node property '" +
+ Property->getName() + "' on node '" +
+ R->getName() + "'!");
}
}
diff --git a/utils/TableGen/SDNodeProperties.h b/utils/TableGen/SDNodeProperties.h
index a8d4efb5dab0..66a04e63150c 100644
--- a/utils/TableGen/SDNodeProperties.h
+++ b/utils/TableGen/SDNodeProperties.h
@@ -1,9 +1,8 @@
//===- SDNodeProperties.h ---------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/SearchableTableEmitter.cpp b/utils/TableGen/SearchableTableEmitter.cpp
index f98a7c74bf0c..954b63e7253c 100644
--- a/utils/TableGen/SearchableTableEmitter.cpp
+++ b/utils/TableGen/SearchableTableEmitter.cpp
@@ -1,9 +1,8 @@
//===- SearchableTableEmitter.cpp - Generate efficiently searchable tables -==//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -142,7 +141,7 @@ private:
bool compareBy(Record *LHS, Record *RHS, const SearchIndex &Index);
bool isIntegral(Init *I) {
- return isa<BitsInit>(I) || isIntrinsic(I);
+ return isa<BitsInit>(I) || isa<CodeInit>(I) || isIntrinsic(I);
}
std::string searchableFieldType(const GenericField &Field, TypeContext Ctx) {
@@ -600,9 +599,10 @@ void SearchableTableEmitter::collectTableEntries(
for (auto &Field : Table.Fields) {
auto TI = dyn_cast<TypedInit>(EntryRec->getValueInit(Field.Name));
if (!TI) {
- PrintFatalError(Twine("Record '") + EntryRec->getName() +
- "' in table '" + Table.Name + "' is missing field '" +
- Field.Name + "'");
+ PrintFatalError(EntryRec->getLoc(),
+ Twine("Record '") + EntryRec->getName() +
+ "' in table '" + Table.Name +
+ "' is missing field '" + Field.Name + "'");
}
if (!Field.RecType) {
Field.RecType = TI->getType();
@@ -611,7 +611,7 @@ void SearchableTableEmitter::collectTableEntries(
if (!Ty)
PrintFatalError(Twine("Field '") + Field.Name + "' of table '" +
Table.Name + "' has incompatible type: " +
- Ty->getAsString() + " vs. " +
+ Field.RecType->getAsString() + " vs. " +
TI->getType()->getAsString());
Field.RecType = Ty;
}
@@ -654,8 +654,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
StringRef FilterClass = EnumRec->getValueAsString("FilterClass");
Enum->Class = Records.getClass(FilterClass);
if (!Enum->Class)
- PrintFatalError(Twine("Enum FilterClass '") + FilterClass +
- "' does not exist");
+ PrintFatalError(EnumRec->getLoc(), Twine("Enum FilterClass '") +
+ FilterClass + "' does not exist");
collectEnumEntries(*Enum, NameField, ValueField,
Records.getAllDerivedDefinitions(FilterClass));
@@ -675,9 +675,10 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
if (auto TypeOfVal = TableRec->getValue(("TypeOf_" + FieldName).str())) {
if (!parseFieldType(Table->Fields.back(), TypeOfVal->getValue())) {
- PrintFatalError(Twine("Table '") + Table->Name +
- "' has bad 'TypeOf_" + FieldName + "': " +
- TypeOfVal->getValue()->getAsString());
+ PrintFatalError(TableRec->getLoc(),
+ Twine("Table '") + Table->Name +
+ "' has bad 'TypeOf_" + FieldName +
+ "': " + TypeOfVal->getValue()->getAsString());
}
}
}
@@ -705,8 +706,10 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
Record *TableRec = IndexRec->getValueAsDef("Table");
auto It = TableMap.find(TableRec);
if (It == TableMap.end())
- PrintFatalError(Twine("SearchIndex '") + IndexRec->getName() +
- "' refers to non-existing table '" + TableRec->getName());
+ PrintFatalError(IndexRec->getLoc(),
+ Twine("SearchIndex '") + IndexRec->getName() +
+ "' refers to non-existing table '" +
+ TableRec->getName());
GenericTable &Table = *It->second;
Table.Indices.push_back(parseSearchIndex(
diff --git a/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h
index 2b8f66a3bf3e..8a826eff311d 100644
--- a/utils/TableGen/SequenceToOffsetTable.h
+++ b/utils/TableGen/SequenceToOffsetTable.h
@@ -1,9 +1,8 @@
//===-- SequenceToOffsetTable.h - Compress similar sequences ----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 731c14bdb9a0..9ce2b3b275c8 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -1,9 +1,8 @@
//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -74,9 +73,11 @@ class SubtargetEmitter {
CodeGenSchedModels &SchedModels;
std::string Target;
- void Enumeration(raw_ostream &OS);
- unsigned FeatureKeyValues(raw_ostream &OS);
- unsigned CPUKeyValues(raw_ostream &OS);
+ void Enumeration(raw_ostream &OS, DenseMap<Record *, unsigned> &FeatureMap);
+ unsigned FeatureKeyValues(raw_ostream &OS,
+ const DenseMap<Record *, unsigned> &FeatureMap);
+ unsigned CPUKeyValues(raw_ostream &OS,
+ const DenseMap<Record *, unsigned> &FeatureMap);
void FormItineraryStageString(const std::string &Names,
Record *ItinData, std::string &ItinString,
unsigned &NStages);
@@ -138,7 +139,8 @@ public:
//
// Enumeration - Emit the specified class as an enumeration.
//
-void SubtargetEmitter::Enumeration(raw_ostream &OS) {
+void SubtargetEmitter::Enumeration(raw_ostream &OS,
+ DenseMap<Record *, unsigned> &FeatureMap) {
// Get all records of class and sort
std::vector<Record*> DefList =
Records.getAllDerivedDefinitions("SubtargetFeature");
@@ -147,7 +149,7 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) {
unsigned N = DefList.size();
if (N == 0)
return;
- if (N > MAX_SUBTARGET_FEATURES)
+ if (N + 1 > MAX_SUBTARGET_FEATURES)
PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
OS << "namespace " << Target << " {\n";
@@ -162,18 +164,42 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) {
// Get and emit name
OS << " " << Def->getName() << " = " << i << ",\n";
+
+ // Save the index for this feature.
+ FeatureMap[Def] = i;
}
+ OS << " "
+ << "NumSubtargetFeatures = " << N << "\n";
+
// Close enumeration and namespace
OS << "};\n";
OS << "} // end namespace " << Target << "\n";
}
+static void printFeatureMask(raw_ostream &OS, RecVec &FeatureList,
+ const DenseMap<Record *, unsigned> &FeatureMap) {
+ std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {};
+ for (unsigned j = 0, M = FeatureList.size(); j < M; ++j) {
+ unsigned Bit = FeatureMap.lookup(FeatureList[j]);
+ Mask[Bit / 64] |= 1ULL << (Bit % 64);
+ }
+
+ OS << "{ { { ";
+ for (unsigned i = 0; i != Mask.size(); ++i) {
+ OS << "0x";
+ OS.write_hex(Mask[i]);
+ OS << "ULL, ";
+ }
+ OS << "} } }";
+}
+
//
// FeatureKeyValues - Emit data of all the subtarget features. Used by the
// command line.
//
-unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
+unsigned SubtargetEmitter::FeatureKeyValues(
+ raw_ostream &OS, const DenseMap<Record *, unsigned> &FeatureMap) {
// Gather and sort all the features
std::vector<Record*> FeatureList =
Records.getAllDerivedDefinitions("SubtargetFeature");
@@ -204,16 +230,13 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
OS << " { "
<< "\"" << CommandLineName << "\", "
<< "\"" << Desc << "\", "
- << "{ " << Target << "::" << Name << " }, ";
+ << Target << "::" << Name << ", ";
RecVec ImpliesList = Feature->getValueAsListOfDefs("Implies");
- OS << "{";
- for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
- OS << " " << Target << "::" << ImpliesList[j]->getName();
- if (++j < M) OS << ",";
- }
- OS << " } },\n";
+ printFeatureMask(OS, ImpliesList, FeatureMap);
+
+ OS << " },\n";
++NumFeatures;
}
@@ -227,7 +250,9 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
// CPUKeyValues - Emit data of all the subtarget processors. Used by command
// line.
//
-unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
+unsigned
+SubtargetEmitter::CPUKeyValues(raw_ostream &OS,
+ const DenseMap<Record *, unsigned> &FeatureMap) {
// Gather and sort processor information
std::vector<Record*> ProcessorList =
Records.getAllDerivedDefinitions("Processor");
@@ -235,7 +260,7 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
// Begin processor table
OS << "// Sorted (by key) array of values for CPU subtype.\n"
- << "extern const llvm::SubtargetFeatureKV " << Target
+ << "extern const llvm::SubtargetSubTypeKV " << Target
<< "SubTypeKV[] = {\n";
// For each processor
@@ -243,18 +268,16 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
StringRef Name = Processor->getValueAsString("Name");
RecVec FeatureList = Processor->getValueAsListOfDefs("Features");
- // Emit as { "cpu", "description", { f1 , f2 , ... fn } },
- OS << " { "
- << "\"" << Name << "\", "
- << "\"Select the " << Name << " processor\", ";
+ // Emit as { "cpu", "description", 0, { f1 , f2 , ... fn } },
+ OS << " { "
+ << "\"" << Name << "\", ";
- OS << "{";
- for (unsigned j = 0, M = FeatureList.size(); j < M;) {
- OS << " " << Target << "::" << FeatureList[j]->getName();
- if (++j < M) OS << ",";
- }
- // The { } is for the "implies" section of this data structure.
- OS << " }, { } },\n";
+ printFeatureMask(OS, FeatureList, FeatureMap);
+
+ // Emit the scheduler model pointer.
+ const std::string &ProcModelName =
+ SchedModels.getModelForProc(Processor).ModelName;
+ OS << ", &" << ProcModelName << " },\n";
}
// End processor table
@@ -1369,33 +1392,6 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
}
//
-// EmitProcessorLookup - generate cpu name to sched model lookup tables.
-//
-void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
- // Gather and sort processor information
- std::vector<Record*> ProcessorList =
- Records.getAllDerivedDefinitions("Processor");
- llvm::sort(ProcessorList, LessRecordFieldName());
-
- // Begin processor->sched model table
- OS << "\n";
- OS << "// Sorted (by key) array of sched model for CPU subtype.\n"
- << "extern const llvm::SubtargetInfoKV " << Target
- << "ProcSchedKV[] = {\n";
- // For each processor
- for (Record *Processor : ProcessorList) {
- StringRef Name = Processor->getValueAsString("Name");
- const std::string &ProcModelName =
- SchedModels.getModelForProc(Processor).ModelName;
-
- // Emit as { "cpu", procinit },
- OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " },\n";
- }
- // End processor->sched model table
- OS << "};\n";
-}
-
-//
// EmitSchedModel - Emits all scheduling model tables, folding common patterns.
//
void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
@@ -1423,12 +1419,10 @@ void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
}
EmitSchedClassTables(SchedTables, OS);
+ OS << "\n#undef DBGFIELD\n";
+
// Emit the processor machine model
EmitProcessorModels(OS);
- // Emit the processor lookup data
- EmitProcessorLookup(OS);
-
- OS << "\n#undef DBGFIELD";
}
static void emitPredicateProlog(const RecordKeeper &Records, raw_ostream &OS) {
@@ -1740,13 +1734,12 @@ void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) {
<< "GenMCSubtargetInfo : public MCSubtargetInfo {\n";
OS << " " << Target << "GenMCSubtargetInfo(const Triple &TT, \n"
<< " StringRef CPU, StringRef FS, ArrayRef<SubtargetFeatureKV> PF,\n"
- << " ArrayRef<SubtargetFeatureKV> PD,\n"
- << " const SubtargetInfoKV *ProcSched,\n"
+ << " ArrayRef<SubtargetSubTypeKV> PD,\n"
<< " const MCWriteProcResEntry *WPR,\n"
<< " const MCWriteLatencyEntry *WL,\n"
<< " const MCReadAdvanceEntry *RA, const InstrStage *IS,\n"
<< " const unsigned *OC, const unsigned *FP) :\n"
- << " MCSubtargetInfo(TT, CPU, FS, PF, PD, ProcSched,\n"
+ << " MCSubtargetInfo(TT, CPU, FS, PF, PD,\n"
<< " WPR, WL, RA, IS, OC, FP) { }\n\n"
<< " unsigned resolveVariantSchedClass(unsigned SchedClass,\n"
<< " const MCInst *MI, unsigned CPUID) const override {\n"
@@ -1790,8 +1783,10 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
OS << "#undef GET_SUBTARGETINFO_ENUM\n\n";
+ DenseMap<Record *, unsigned> FeatureMap;
+
OS << "namespace llvm {\n";
- Enumeration(OS);
+ Enumeration(OS, FeatureMap);
OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
@@ -1802,12 +1797,12 @@ void SubtargetEmitter::run(raw_ostream &OS) {
#if 0
OS << "namespace {\n";
#endif
- unsigned NumFeatures = FeatureKeyValues(OS);
- OS << "\n";
- unsigned NumProcs = CPUKeyValues(OS);
+ unsigned NumFeatures = FeatureKeyValues(OS, FeatureMap);
OS << "\n";
EmitSchedModel(OS);
OS << "\n";
+ unsigned NumProcs = CPUKeyValues(OS, FeatureMap);
+ OS << "\n";
#if 0
OS << "} // end anonymous namespace\n\n";
#endif
@@ -1828,8 +1823,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
else
OS << "None, ";
OS << '\n'; OS.indent(22);
- OS << Target << "ProcSchedKV, "
- << Target << "WriteProcResTable, "
+ OS << Target << "WriteProcResTable, "
<< Target << "WriteLatencyTable, "
<< Target << "ReadAdvanceTable, ";
OS << '\n'; OS.indent(22);
@@ -1895,8 +1889,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n\n";
OS << "namespace llvm {\n";
OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
- OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
- OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
+ OS << "extern const llvm::SubtargetSubTypeKV " << Target << "SubTypeKV[];\n";
OS << "extern const llvm::MCWriteProcResEntry "
<< Target << "WriteProcResTable[];\n";
OS << "extern const llvm::MCWriteLatencyEntry "
@@ -1922,8 +1915,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
else
OS << "None, ";
OS << '\n'; OS.indent(24);
- OS << Target << "ProcSchedKV, "
- << Target << "WriteProcResTable, "
+ OS << Target << "WriteProcResTable, "
<< Target << "WriteLatencyTable, "
<< Target << "ReadAdvanceTable, ";
OS << '\n'; OS.indent(24);
diff --git a/utils/TableGen/SubtargetFeatureInfo.cpp b/utils/TableGen/SubtargetFeatureInfo.cpp
index f9b8853cc117..edf0b4a01c6d 100644
--- a/utils/TableGen/SubtargetFeatureInfo.cpp
+++ b/utils/TableGen/SubtargetFeatureInfo.cpp
@@ -1,9 +1,8 @@
//===- 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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -45,20 +44,6 @@ SubtargetFeatureInfo::getAll(const RecordKeeper &Records) {
return SubtargetFeatures;
}
-void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
- SubtargetFeatureInfoMap &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::emitSubtargetFeatureBitEnumeration(
SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) {
OS << "// Bits for subtarget features that participate in "
@@ -121,9 +106,9 @@ void SubtargetFeatureInfo::emitComputeAvailableFeatures(
void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
StringRef TargetName, StringRef ClassName, StringRef FuncName,
SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) {
- OS << "uint64_t " << TargetName << ClassName << "::\n"
+ OS << "FeatureBitset " << TargetName << ClassName << "::\n"
<< FuncName << "(const FeatureBitset& FB) const {\n";
- OS << " uint64_t Features = 0;\n";
+ OS << " FeatureBitset Features;\n";
for (const auto &SF : SubtargetFeatures) {
const SubtargetFeatureInfo &SFI = SF.second;
@@ -157,7 +142,7 @@ void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
} while (true);
OS << ")\n";
- OS << " Features |= " << SFI.getEnumName() << ";\n";
+ OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n";
}
OS << " return Features;\n";
OS << "}\n\n";
diff --git a/utils/TableGen/SubtargetFeatureInfo.h b/utils/TableGen/SubtargetFeatureInfo.h
index 71e6748c863f..d72f8b93461f 100644
--- a/utils/TableGen/SubtargetFeatureInfo.h
+++ b/utils/TableGen/SubtargetFeatureInfo.h
@@ -1,9 +1,8 @@
-//===- SubtargetFeatureInfo.h - Helpers for subtarget features ------------===//
+//===- SubtargetFeatureInfo.h - Helpers for subtarget features --*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -56,13 +55,6 @@ struct SubtargetFeatureInfo {
/// Emit the subtarget feature flag definitions.
///
- /// This version emits the bit value for the feature and is therefore limited
- /// to 64 feature bits.
- static void emitSubtargetFeatureFlagEnumeration(
- SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS);
-
- /// Emit the subtarget feature flag definitions.
- ///
/// This version emits the bit index for the feature and can therefore support
/// more than 64 feature bits.
static void
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index d5b6a3c12647..c485ed2feb7a 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -1,9 +1,8 @@
//===- TableGen.cpp - Top-Level TableGen implementation for LLVM ----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -56,6 +55,12 @@ enum ActionType {
GenExegesis,
};
+namespace llvm {
+/// Storage for TimeRegionsOpt as a global so that backends aren't required to
+/// include CommandLine.h
+bool TimeRegions = false;
+} // end namespace llvm
+
namespace {
cl::opt<ActionType>
Action(cl::desc("Action to perform:"),
@@ -127,6 +132,11 @@ namespace {
Class("class", cl::desc("Print Enum list for this class"),
cl::value_desc("class name"), cl::cat(PrintEnumsCat));
+cl::opt<bool, true>
+ TimeRegionsOpt("time-regions",
+ cl::desc("Time regions of tablegens execution"),
+ cl::location(TimeRegions));
+
bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
switch (Action) {
case PrintRecords:
diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index f4f2909f8e88..135ec65c0f95 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/utils/TableGen/TableGenBackends.h
@@ -1,9 +1,8 @@
//===- TableGenBackends.h - Declarations for LLVM TableGen Backends -------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/Types.cpp b/utils/TableGen/Types.cpp
index 04d9e40f6743..a6682da90e6b 100644
--- a/utils/TableGen/Types.cpp
+++ b/utils/TableGen/Types.cpp
@@ -1,9 +1,8 @@
//===- 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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/Types.h b/utils/TableGen/Types.h
index d511b7eae6e8..17c7742ccaac 100644
--- a/utils/TableGen/Types.h
+++ b/utils/TableGen/Types.h
@@ -1,9 +1,8 @@
//===- 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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp b/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp
index 788f142e125f..365cba5a60ca 100644
--- a/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp
+++ b/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp
@@ -1,9 +1,8 @@
//===- WebAssemblyDisassemblerEmitter.cpp - Disassembler tables -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -51,12 +50,33 @@ void emitWebAssemblyDisassemblerTables(
auto IsStackBased =
StackString &&
reinterpret_cast<const StringInit *>(StackString)->getValue() == "true";
- if (IsStackBased && !CGIP.second) {
- // this picks the first of many typed variants, which is
- // currently the except_ref one, though this shouldn't matter for
- // disassembly purposes.
- CGIP = std::make_pair(I, &CGI);
+ if (!IsStackBased)
+ continue;
+ if (CGIP.second) {
+ // We already have an instruction for this slot, so decide which one
+ // should be the canonical one. This determines which variant gets
+ // printed in a disassembly. We want e.g. "call" not "i32.call", and
+ // "end" when we don't know if its "end_loop" or "end_block" etc.
+ auto IsCanonicalExisting = CGIP.second->TheDef->getValue("IsCanonical")
+ ->getValue()
+ ->getAsString() == "1";
+ // We already have one marked explicitly as canonical, so keep it.
+ if (IsCanonicalExisting)
+ continue;
+ auto IsCanonicalNew =
+ Def.getValue("IsCanonical")->getValue()->getAsString() == "1";
+ // If the new one is explicitly marked as canonical, take it.
+ if (!IsCanonicalNew) {
+ // Neither the existing or new instruction is canonical.
+ // Pick the one with the shortest name as heuristic.
+ // Though ideally IsCanonical is always defined for at least one
+ // variant so this never has to apply.
+ if (CGIP.second->AsmString.size() <= CGI.AsmString.size())
+ continue;
+ }
}
+ // Set this instruction as the one to use.
+ CGIP = std::make_pair(I, &CGI);
}
OS << "#include \"MCTargetDesc/WebAssemblyMCTargetDesc.h\"\n";
OS << "\n";
diff --git a/utils/TableGen/WebAssemblyDisassemblerEmitter.h b/utils/TableGen/WebAssemblyDisassemblerEmitter.h
index 91f820f120a2..60d3d9433eca 100644
--- a/utils/TableGen/WebAssemblyDisassemblerEmitter.h
+++ b/utils/TableGen/WebAssemblyDisassemblerEmitter.h
@@ -1,9 +1,8 @@
//===- WebAssemblyDisassemblerEmitter.h - Disassembler tables ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/X86DisassemblerShared.h b/utils/TableGen/X86DisassemblerShared.h
index 220765f72410..093f220fda5e 100644
--- a/utils/TableGen/X86DisassemblerShared.h
+++ b/utils/TableGen/X86DisassemblerShared.h
@@ -1,9 +1,8 @@
//===- X86DisassemblerShared.h - Emitter shared header ----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp
index 2b5cc1279605..8036aecc4f4b 100644
--- a/utils/TableGen/X86DisassemblerTables.cpp
+++ b/utils/TableGen/X86DisassemblerTables.cpp
@@ -1,9 +1,8 @@
//===- X86DisassemblerTables.cpp - Disassembler tables ----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -889,67 +888,44 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
}
void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
- const unsigned int tableSize = 16384;
o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR
- "[" << tableSize << "] = {\n";
+ "[" << ATTR_max << "] = {\n";
i++;
- for (unsigned index = 0; index < tableSize; ++index) {
+ for (unsigned index = 0; index < ATTR_max; ++index) {
o.indent(i * 2);
- if (index & ATTR_EVEX) {
- o << "IC_EVEX";
- if (index & ATTR_EVEXL2)
+ if ((index & ATTR_EVEX) || (index & ATTR_VEX) || (index & ATTR_VEXL)) {
+ if (index & ATTR_EVEX)
+ o << "IC_EVEX";
+ else
+ o << "IC_VEX";
+
+ if ((index & ATTR_EVEX) && (index & ATTR_EVEXL2))
o << "_L2";
- else if (index & ATTR_EVEXL)
+ else if (index & ATTR_VEXL)
o << "_L";
+
if (index & ATTR_REXW)
o << "_W";
+
if (index & ATTR_OPSIZE)
o << "_OPSIZE";
else if (index & ATTR_XD)
o << "_XD";
else if (index & ATTR_XS)
o << "_XS";
- if (index & ATTR_EVEXKZ)
- o << "_KZ";
- else if (index & ATTR_EVEXK)
- o << "_K";
- if (index & ATTR_EVEXB)
- o << "_B";
+
+ if ((index & ATTR_EVEX)) {
+ if (index & ATTR_EVEXKZ)
+ o << "_KZ";
+ else if (index & ATTR_EVEXK)
+ o << "_K";
+
+ if (index & ATTR_EVEXB)
+ o << "_B";
+ }
}
- else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
- o << "IC_VEX_L_W_OPSIZE";
- else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD))
- o << "IC_VEX_L_W_XD";
- else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XS))
- o << "IC_VEX_L_W_XS";
- else if ((index & ATTR_VEXL) && (index & ATTR_REXW))
- o << "IC_VEX_L_W";
- else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE))
- o << "IC_VEX_L_OPSIZE";
- else if ((index & ATTR_VEXL) && (index & ATTR_XD))
- o << "IC_VEX_L_XD";
- else if ((index & ATTR_VEXL) && (index & ATTR_XS))
- o << "IC_VEX_L_XS";
- else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
- o << "IC_VEX_W_OPSIZE";
- else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD))
- o << "IC_VEX_W_XD";
- else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS))
- o << "IC_VEX_W_XS";
- else if (index & ATTR_VEXL)
- o << "IC_VEX_L";
- else if ((index & ATTR_VEX) && (index & ATTR_REXW))
- o << "IC_VEX_W";
- else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE))
- o << "IC_VEX_OPSIZE";
- else if ((index & ATTR_VEX) && (index & ATTR_XD))
- o << "IC_VEX_XD";
- else if ((index & ATTR_VEX) && (index & ATTR_XS))
- o << "IC_VEX_XS";
- else if (index & ATTR_VEX)
- o << "IC_VEX";
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
o << "IC_64BIT_REXW_XS";
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
@@ -1004,12 +980,7 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
else
o << "IC";
- if (index < tableSize - 1)
- o << ",";
- else
- o << " ";
-
- o << " /* " << index << " */";
+ o << ", /* " << index << " */";
o << "\n";
}
diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h
index b0ea9c2e8625..63af68b6fbfa 100644
--- a/utils/TableGen/X86DisassemblerTables.h
+++ b/utils/TableGen/X86DisassemblerTables.h
@@ -1,9 +1,8 @@
//===- X86DisassemblerTables.h - Disassembler tables ------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp b/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp
index d5dc10ecad25..3df14f40e4a9 100644
--- a/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp
+++ b/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp
@@ -1,9 +1,8 @@
//===- utils/TableGen/X86EVEX2VEXTablesEmitter.cpp - X86 backend-*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
@@ -69,23 +68,6 @@ void X86EVEX2VEXTablesEmitter::printTable(const std::vector<Entry> &Table,
}
// Return true if the 2 BitsInits are equal
-static inline bool equalBitsInits(const BitsInit *B1, const BitsInit *B2) {
- if (B1->getNumBits() != B2->getNumBits())
- PrintFatalError("Comparing two BitsInits with different sizes!");
-
- for (unsigned i = 0, e = B1->getNumBits(); i != e; ++i) {
- if (BitInit *Bit1 = dyn_cast<BitInit>(B1->getBit(i))) {
- if (BitInit *Bit2 = dyn_cast<BitInit>(B2->getBit(i))) {
- if (Bit1->getValue() != Bit2->getValue())
- return false;
- } else
- PrintFatalError("Invalid BitsInit bit");
- } else
- PrintFatalError("Invalid BitsInit bit");
- }
- return true;
-}
-
// Calculates the integer value residing BitsInit object
static inline uint64_t getValueFromBitsInit(const BitsInit *B) {
uint64_t Value = 0;
@@ -109,26 +91,25 @@ public:
bool operator()(const CodeGenInstruction *VEXInst) {
Record *RecE = EVEXInst->TheDef;
Record *RecV = VEXInst->TheDef;
- uint64_t EVEX_W =
- getValueFromBitsInit(RecE->getValueAsBitsInit("VEX_WPrefix"));
- uint64_t VEX_W =
- getValueFromBitsInit(RecV->getValueAsBitsInit("VEX_WPrefix"));
+ bool EVEX_W = RecE->getValueAsBit("HasVEX_W");
+ bool VEX_W = RecV->getValueAsBit("HasVEX_W");
+ bool VEX_WIG = RecV->getValueAsBit("IgnoresVEX_W");
+ bool EVEX_WIG = RecE->getValueAsBit("IgnoresVEX_W");
+ bool EVEX_W1_VEX_W0 = RecE->getValueAsBit("EVEX_W1_VEX_W0");
if (RecV->getValueAsDef("OpEnc")->getName().str() != "EncVEX" ||
// VEX/EVEX fields
RecV->getValueAsDef("OpPrefix") != RecE->getValueAsDef("OpPrefix") ||
RecV->getValueAsDef("OpMap") != RecE->getValueAsDef("OpMap") ||
RecV->getValueAsBit("hasVEX_4V") != RecE->getValueAsBit("hasVEX_4V") ||
- !equalBitsInits(RecV->getValueAsBitsInit("EVEX_LL"),
- RecE->getValueAsBitsInit("EVEX_LL")) ||
+ RecV->getValueAsBit("hasEVEX_L2") != RecE->getValueAsBit("hasEVEX_L2") ||
+ RecV->getValueAsBit("hasVEX_L") != RecE->getValueAsBit("hasVEX_L") ||
// Match is allowed if either is VEX_WIG, or they match, or EVEX
// is VEX_W1X and VEX is VEX_W0.
- (!(EVEX_W == 2 || VEX_W == 2 || EVEX_W == VEX_W ||
- (EVEX_W == 3 && VEX_W == 0))) ||
+ (!(VEX_WIG || (!EVEX_WIG && EVEX_W == VEX_W) ||
+ (EVEX_W1_VEX_W0 && EVEX_W && !VEX_W))) ||
// Instruction's format
- RecV->getValueAsDef("Form") != RecE->getValueAsDef("Form") ||
- RecV->getValueAsBit("isAsmParserOnly") !=
- RecE->getValueAsBit("isAsmParserOnly"))
+ RecV->getValueAsDef("Form") != RecE->getValueAsDef("Form"))
return false;
// This is needed for instructions with intrinsic version (_Int).
@@ -150,8 +131,9 @@ public:
} else if (isMemoryOperand(OpRec1) && isMemoryOperand(OpRec2)) {
return false;
} else if (isImmediateOperand(OpRec1) && isImmediateOperand(OpRec2)) {
- if (OpRec1->getValueAsDef("Type") != OpRec2->getValueAsDef("Type"))
+ if (OpRec1->getValueAsDef("Type") != OpRec2->getValueAsDef("Type")) {
return false;
+ }
} else
return false;
}
@@ -207,8 +189,7 @@ void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) {
else if (Inst->TheDef->getValueAsDef("OpEnc")->getName() == "EncEVEX" &&
!Inst->TheDef->getValueAsBit("hasEVEX_K") &&
!Inst->TheDef->getValueAsBit("hasEVEX_B") &&
- getValueFromBitsInit(Inst->TheDef->
- getValueAsBitsInit("EVEX_LL")) != 2 &&
+ !Inst->TheDef->getValueAsBit("hasEVEX_L2") &&
!Inst->TheDef->getValueAsBit("notEVEX2VEXConvertible"))
EVEXInsts.push_back(Inst);
}
@@ -236,17 +217,10 @@ void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) {
continue;
// In case a match is found add new entry to the appropriate table
- switch (getValueFromBitsInit(
- EVEXInst->TheDef->getValueAsBitsInit("EVEX_LL"))) {
- case 0:
- EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0}
- break;
- case 1:
+ if (EVEXInst->TheDef->getValueAsBit("hasVEX_L"))
EVEX2VEX256.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,1}
- break;
- default:
- llvm_unreachable("Instruction's size not fit for the mapping!");
- }
+ else
+ EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0}
}
// Print both tables
diff --git a/utils/TableGen/X86FoldTablesEmitter.cpp b/utils/TableGen/X86FoldTablesEmitter.cpp
index 1ea668643575..2c15e35f234d 100644
--- a/utils/TableGen/X86FoldTablesEmitter.cpp
+++ b/utils/TableGen/X86FoldTablesEmitter.cpp
@@ -1,9 +1,8 @@
//===- utils/TableGen/X86FoldTablesEmitter.cpp - X86 backend-*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -14,6 +13,7 @@
#include "CodeGenTarget.h"
#include "X86RecognizableInstr.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/TableGenBackend.h"
@@ -62,9 +62,12 @@ const ManualMapEntry ManualMapSet[] = {
{ "ADD64ri32_DB", "ADD64mi32", NO_UNFOLD },
{ "ADD64ri8_DB", "ADD64mi8", NO_UNFOLD },
{ "ADD64rr_DB", "ADD64mr", NO_UNFOLD },
+ { "ADD8ri_DB", "ADD8mi", NO_UNFOLD },
+ { "ADD8rr_DB", "ADD8mr", NO_UNFOLD },
{ "ADD16rr_DB", "ADD16rm", NO_UNFOLD },
{ "ADD32rr_DB", "ADD32rm", NO_UNFOLD },
{ "ADD64rr_DB", "ADD64rm", NO_UNFOLD },
+ { "ADD8rr_DB", "ADD8rm", NO_UNFOLD },
{ "PUSH16r", "PUSH16rmm", UNFOLD },
{ "PUSH32r", "PUSH32rmm", UNFOLD },
{ "PUSH64r", "PUSH64rmm", UNFOLD },
@@ -106,23 +109,23 @@ class X86FoldTablesEmitter {
const CodeGenInstruction *MemInst)
: RegInst(RegInst), MemInst(MemInst) {}
- friend raw_ostream &operator<<(raw_ostream &OS,
- const X86FoldTableEntry &E) {
- OS << "{ X86::" << E.RegInst->TheDef->getName()
- << ", X86::" << E.MemInst->TheDef->getName() << ", ";
+ void print(formatted_raw_ostream &OS) const {
+ OS.indent(2);
+ OS << "{ X86::" << RegInst->TheDef->getName() << ",";
+ OS.PadToColumn(40);
+ OS << "X86::" << MemInst->TheDef->getName() << ",";
+ OS.PadToColumn(75);
- if (E.IsLoad)
+ if (IsLoad)
OS << "TB_FOLDED_LOAD | ";
- if (E.IsStore)
+ if (IsStore)
OS << "TB_FOLDED_STORE | ";
- if (E.CannotUnfold)
+ if (CannotUnfold)
OS << "TB_NO_REVERSE | ";
- if (E.IsAligned)
- OS << "TB_ALIGN_" << E.Alignment << " | ";
+ if (IsAligned)
+ OS << "TB_ALIGN_" << Alignment << " | ";
OS << "0 },\n";
-
- return OS;
}
};
@@ -142,7 +145,7 @@ public:
X86FoldTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {}
// run - Generate the 6 X86 memory fold tables.
- void run(raw_ostream &OS);
+ void run(formatted_raw_ostream &OS);
private:
// Decides to which table to add the entry with the given instructions.
@@ -160,21 +163,21 @@ private:
// Print the given table as a static const C++ array of type
// X86MemoryFoldTableEntry.
void printTable(const FoldTable &Table, StringRef TableName,
- raw_ostream &OS) {
+ formatted_raw_ostream &OS) {
OS << "static const X86MemoryFoldTableEntry MemoryFold" << TableName
<< "[] = {\n";
for (const X86FoldTableEntry &E : Table)
- OS << E;
+ E.print(OS);
- OS << "};\n";
+ OS << "};\n\n";
}
};
// Return true if one of the instruction's operands is a RST register class
static bool hasRSTRegClass(const CodeGenInstruction *Inst) {
return any_of(Inst->Operands, [](const CGIOperandList::OperandInfo &OpIn) {
- return OpIn.Rec->getName() == "RST";
+ return OpIn.Rec->getName() == "RST" || OpIn.Rec->getName() == "RSTi";
});
}
@@ -345,10 +348,18 @@ public:
MemRec->getValueAsBit("hasLockPrefix") ||
RegRec->getValueAsBit("hasNoTrackPrefix") !=
MemRec->getValueAsBit("hasNoTrackPrefix") ||
- !equalBitsInits(RegRec->getValueAsBitsInit("EVEX_LL"),
- MemRec->getValueAsBitsInit("EVEX_LL")) ||
- !equalBitsInits(RegRec->getValueAsBitsInit("VEX_WPrefix"),
- MemRec->getValueAsBitsInit("VEX_WPrefix")) ||
+ RegRec->getValueAsBit("hasVEX_L") !=
+ MemRec->getValueAsBit("hasVEX_L") ||
+ RegRec->getValueAsBit("hasEVEX_L2") !=
+ MemRec->getValueAsBit("hasEVEX_L2") ||
+ RegRec->getValueAsBit("ignoresVEX_L") !=
+ MemRec->getValueAsBit("ignoresVEX_L") ||
+ RegRec->getValueAsBit("HasVEX_W") !=
+ MemRec->getValueAsBit("HasVEX_W") ||
+ RegRec->getValueAsBit("IgnoresVEX_W") !=
+ MemRec->getValueAsBit("IgnoresVEX_W") ||
+ RegRec->getValueAsBit("EVEX_W1_VEX_W0") !=
+ MemRec->getValueAsBit("EVEX_W1_VEX_W0") ||
// Instruction's format - The register form's "Form" field should be
// the opposite of the memory form's "Form" field.
!areOppositeForms(RegRec->getValueAsBitsInit("FormBits"),
@@ -421,6 +432,7 @@ private:
(MemFormNum == X86Local::MRM6m && RegFormNum == X86Local::MRM6r) ||
(MemFormNum == X86Local::MRM7m && RegFormNum == X86Local::MRM7r) ||
(MemFormNum == X86Local::MRMXm && RegFormNum == X86Local::MRMXr) ||
+ (MemFormNum == X86Local::MRMXmCC && RegFormNum == X86Local::MRMXrCC) ||
(MemFormNum == X86Local::MRMDestMem &&
RegFormNum == X86Local::MRMDestReg) ||
(MemFormNum == X86Local::MRMSrcMem &&
@@ -428,7 +440,9 @@ private:
(MemFormNum == X86Local::MRMSrcMem4VOp3 &&
RegFormNum == X86Local::MRMSrcReg4VOp3) ||
(MemFormNum == X86Local::MRMSrcMemOp4 &&
- RegFormNum == X86Local::MRMSrcRegOp4))
+ RegFormNum == X86Local::MRMSrcRegOp4) ||
+ (MemFormNum == X86Local::MRMSrcMemCC &&
+ RegFormNum == X86Local::MRMSrcRegCC))
return true;
return false;
@@ -558,7 +572,7 @@ void X86FoldTablesEmitter::updateTables(const CodeGenInstruction *RegInstr,
return;
}
-void X86FoldTablesEmitter::run(raw_ostream &OS) {
+void X86FoldTablesEmitter::run(formatted_raw_ostream &OS) {
emitSourceFileHeader("X86 fold tables", OS);
// Holds all memory instructions
@@ -639,7 +653,7 @@ void X86FoldTablesEmitter::run(raw_ostream &OS) {
&(Target.getInstruction(MemInstIter)), Entry.Strategy);
}
- // Print all tables to raw_ostream OS.
+ // Print all tables.
printTable(Table2Addr, "Table2Addr", OS);
printTable(Table0, "Table0", OS);
printTable(Table1, "Table1", OS);
@@ -650,7 +664,8 @@ void X86FoldTablesEmitter::run(raw_ostream &OS) {
namespace llvm {
-void EmitX86FoldTables(RecordKeeper &RK, raw_ostream &OS) {
+void EmitX86FoldTables(RecordKeeper &RK, raw_ostream &o) {
+ formatted_raw_ostream OS(o);
X86FoldTablesEmitter(RK).run(OS);
}
} // namespace llvm
diff --git a/utils/TableGen/X86ModRMFilters.cpp b/utils/TableGen/X86ModRMFilters.cpp
index 1641613aa32d..98e6fb6104d7 100644
--- a/utils/TableGen/X86ModRMFilters.cpp
+++ b/utils/TableGen/X86ModRMFilters.cpp
@@ -1,9 +1,8 @@
//===- X86ModRMFilters.cpp - Disassembler ModR/M filterss -------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/utils/TableGen/X86ModRMFilters.h b/utils/TableGen/X86ModRMFilters.h
index b0248e878d07..c77b4c21aec4 100644
--- a/utils/TableGen/X86ModRMFilters.h
+++ b/utils/TableGen/X86ModRMFilters.h
@@ -1,9 +1,8 @@
//===- X86ModRMFilters.h - Disassembler ModR/M filterss ---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index 2f9b428b8cfe..ab8a8855c478 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -1,9 +1,8 @@
//===- X86RecognizableInstr.cpp - Disassembler instruction spec --*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -84,7 +83,8 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
AdSize = byteFromRec(Rec, "AdSizeBits");
HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
HasVEX_4V = Rec->getValueAsBit("hasVEX_4V");
- VEX_WPrefix = byteFromRec(Rec,"VEX_WPrefix");
+ HasVEX_W = Rec->getValueAsBit("HasVEX_W");
+ IgnoresVEX_W = Rec->getValueAsBit("IgnoresVEX_W");
IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2");
HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
@@ -110,7 +110,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates");
for (unsigned i = 0, e = Predicates.size(); i != e; ++i) {
if (Predicates[i]->getName().find("Not64Bit") != Name.npos ||
- Predicates[i]->getName().find("In32Bit") != Name.npos) {
+ Predicates[i]->getName().find("In32Bit") != Name.npos) {
Is32Bit = true;
break;
}
@@ -164,8 +164,7 @@ InstructionContext RecognizableInstr::insnContext() const {
llvm_unreachable("Don't support VEX.L if EVEX_L2 is enabled");
}
// VEX_L & VEX_W
- if (!EncodeRC && HasVEX_LPrefix && (VEX_WPrefix == X86Local::VEX_W1 ||
- VEX_WPrefix == X86Local::VEX_W1X)) {
+ if (!EncodeRC && HasVEX_LPrefix && HasVEX_W) {
if (OpPrefix == X86Local::PD)
insnContext = EVEX_KB(IC_EVEX_L_W_OPSIZE);
else if (OpPrefix == X86Local::XS)
@@ -192,9 +191,7 @@ InstructionContext RecognizableInstr::insnContext() const {
errs() << "Instruction does not use a prefix: " << Name << "\n";
llvm_unreachable("Invalid prefix");
}
- } else if (!EncodeRC && HasEVEX_L2Prefix &&
- (VEX_WPrefix == X86Local::VEX_W1 ||
- VEX_WPrefix == X86Local::VEX_W1X)) {
+ } else if (!EncodeRC && HasEVEX_L2Prefix && HasVEX_W) {
// EVEX_L2 & VEX_W
if (OpPrefix == X86Local::PD)
insnContext = EVEX_KB(IC_EVEX_L2_W_OPSIZE);
@@ -223,8 +220,7 @@ InstructionContext RecognizableInstr::insnContext() const {
llvm_unreachable("Invalid prefix");
}
}
- else if (VEX_WPrefix == X86Local::VEX_W1 ||
- VEX_WPrefix == X86Local::VEX_W1X) {
+ else if (HasVEX_W) {
// VEX_W
if (OpPrefix == X86Local::PD)
insnContext = EVEX_KB(IC_EVEX_W_OPSIZE);
@@ -254,8 +250,7 @@ InstructionContext RecognizableInstr::insnContext() const {
}
/// eof EVEX
} else if (Encoding == X86Local::VEX || Encoding == X86Local::XOP) {
- if (HasVEX_LPrefix && (VEX_WPrefix == X86Local::VEX_W1 ||
- VEX_WPrefix == X86Local::VEX_W1X)) {
+ if (HasVEX_LPrefix && HasVEX_W) {
if (OpPrefix == X86Local::PD)
insnContext = IC_VEX_L_W_OPSIZE;
else if (OpPrefix == X86Local::XS)
@@ -270,8 +265,7 @@ InstructionContext RecognizableInstr::insnContext() const {
}
} else if (OpPrefix == X86Local::PD && HasVEX_LPrefix)
insnContext = IC_VEX_L_OPSIZE;
- else if (OpPrefix == X86Local::PD && (VEX_WPrefix == X86Local::VEX_W1 ||
- VEX_WPrefix == X86Local::VEX_W1X))
+ else if (OpPrefix == X86Local::PD && HasVEX_W)
insnContext = IC_VEX_W_OPSIZE;
else if (OpPrefix == X86Local::PD)
insnContext = IC_VEX_OPSIZE;
@@ -279,14 +273,11 @@ InstructionContext RecognizableInstr::insnContext() const {
insnContext = IC_VEX_L_XS;
else if (HasVEX_LPrefix && OpPrefix == X86Local::XD)
insnContext = IC_VEX_L_XD;
- else if ((VEX_WPrefix == X86Local::VEX_W1 ||
- VEX_WPrefix == X86Local::VEX_W1X) && OpPrefix == X86Local::XS)
+ else if (HasVEX_W && OpPrefix == X86Local::XS)
insnContext = IC_VEX_W_XS;
- else if ((VEX_WPrefix == X86Local::VEX_W1 ||
- VEX_WPrefix == X86Local::VEX_W1X) && OpPrefix == X86Local::XD)
+ else if (HasVEX_W && OpPrefix == X86Local::XD)
insnContext = IC_VEX_W_XD;
- else if ((VEX_WPrefix == X86Local::VEX_W1 ||
- VEX_WPrefix == X86Local::VEX_W1X) && OpPrefix == X86Local::PS)
+ else if (HasVEX_W && OpPrefix == X86Local::PS)
insnContext = IC_VEX_W;
else if (HasVEX_LPrefix && OpPrefix == X86Local::PS)
insnContext = IC_VEX_L;
@@ -496,6 +487,13 @@ void RecognizableInstr::emitInstructionSpecifier() {
HANDLE_OPERAND(opcodeModifier)
HANDLE_OPTIONAL(relocation)
break;
+ case X86Local::AddCCFrm:
+ // Operand 1 (optional) is an address or immediate.
+ assert(numPhysicalOperands == 2 &&
+ "Unexpected number of operands for AddCCFrm");
+ HANDLE_OPERAND(relocation)
+ HANDLE_OPERAND(opcodeModifier)
+ break;
case X86Local::MRMDestReg:
// Operand 1 is a register operand in the R/M field.
// - In AVX512 there may be a mask operand here -
@@ -581,6 +579,13 @@ void RecognizableInstr::emitInstructionSpecifier() {
HANDLE_OPERAND(rmRegister)
HANDLE_OPTIONAL(immediate)
break;
+ case X86Local::MRMSrcRegCC:
+ assert(numPhysicalOperands == 3 &&
+ "Unexpected number of operands for MRMSrcRegCC");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(rmRegister)
+ HANDLE_OPERAND(opcodeModifier)
+ break;
case X86Local::MRMSrcMem:
// Operand 1 is a register operand in the Reg/Opcode field.
// Operand 2 is a memory operand (possibly SIB-extended)
@@ -621,6 +626,19 @@ void RecognizableInstr::emitInstructionSpecifier() {
HANDLE_OPERAND(memory)
HANDLE_OPTIONAL(immediate)
break;
+ case X86Local::MRMSrcMemCC:
+ assert(numPhysicalOperands == 3 &&
+ "Unexpected number of operands for MRMSrcMemCC");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(memory)
+ HANDLE_OPERAND(opcodeModifier)
+ break;
+ case X86Local::MRMXrCC:
+ assert(numPhysicalOperands == 2 &&
+ "Unexpected number of operands for MRMXrCC");
+ HANDLE_OPERAND(rmRegister)
+ HANDLE_OPERAND(opcodeModifier)
+ break;
case X86Local::MRMXr:
case X86Local::MRM0r:
case X86Local::MRM1r:
@@ -646,6 +664,12 @@ void RecognizableInstr::emitInstructionSpecifier() {
HANDLE_OPTIONAL(relocation)
HANDLE_OPTIONAL(immediate)
break;
+ case X86Local::MRMXmCC:
+ assert(numPhysicalOperands == 2 &&
+ "Unexpected number of operands for MRMXm");
+ HANDLE_OPERAND(memory)
+ HANDLE_OPERAND(opcodeModifier)
+ break;
case X86Local::MRMXm:
case X86Local::MRM0m:
case X86Local::MRM1m:
@@ -724,12 +748,15 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
case X86Local::RawFrmDstSrc:
case X86Local::RawFrmImm8:
case X86Local::RawFrmImm16:
+ case X86Local::AddCCFrm:
filter = llvm::make_unique<DumbFilter>();
break;
case X86Local::MRMDestReg:
case X86Local::MRMSrcReg:
case X86Local::MRMSrcReg4VOp3:
case X86Local::MRMSrcRegOp4:
+ case X86Local::MRMSrcRegCC:
+ case X86Local::MRMXrCC:
case X86Local::MRMXr:
filter = llvm::make_unique<ModFilter>(true);
break;
@@ -737,6 +764,8 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
case X86Local::MRMSrcMem:
case X86Local::MRMSrcMem4VOp3:
case X86Local::MRMSrcMemOp4:
+ case X86Local::MRMSrcMemCC:
+ case X86Local::MRMXmCC:
case X86Local::MRMXm:
filter = llvm::make_unique<ModFilter>(false);
break;
@@ -769,23 +798,24 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
assert(opcodeType && "Opcode type not set");
assert(filter && "Filter not set");
- if (Form == X86Local::AddRegFrm) {
- assert(((opcodeToSet & 7) == 0) &&
- "ADDREG_FRM opcode not aligned");
+ if (Form == X86Local::AddRegFrm || Form == X86Local::MRMSrcRegCC ||
+ Form == X86Local::MRMSrcMemCC || Form == X86Local::MRMXrCC ||
+ Form == X86Local::MRMXmCC || Form == X86Local::AddCCFrm) {
+ unsigned Count = Form == X86Local::AddRegFrm ? 8 : 16;
+ assert(((opcodeToSet % Count) == 0) && "ADDREG_FRM opcode not aligned");
uint8_t currentOpcode;
- for (currentOpcode = opcodeToSet;
- currentOpcode < opcodeToSet + 8;
+ for (currentOpcode = opcodeToSet; currentOpcode < opcodeToSet + Count;
++currentOpcode)
tables.setTableFields(*opcodeType, insnContext(), currentOpcode, *filter,
UID, Is32Bit, OpPrefix == 0,
IgnoresVEX_L || EncodeRC,
- VEX_WPrefix == X86Local::VEX_WIG, AddressSize);
+ IgnoresVEX_W, AddressSize);
} else {
tables.setTableFields(*opcodeType, insnContext(), opcodeToSet, *filter, UID,
Is32Bit, OpPrefix == 0, IgnoresVEX_L || EncodeRC,
- VEX_WPrefix == X86Local::VEX_WIG, AddressSize);
+ IgnoresVEX_W, AddressSize);
}
#undef MAP
@@ -825,7 +855,9 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("i8mem", TYPE_M)
TYPE("i8imm", TYPE_IMM)
TYPE("u8imm", TYPE_UIMM8)
+ TYPE("i16u8imm", TYPE_UIMM8)
TYPE("i32u8imm", TYPE_UIMM8)
+ TYPE("i64u8imm", TYPE_UIMM8)
TYPE("GR8", TYPE_R8)
TYPE("VR128", TYPE_XMM)
TYPE("VR128X", TYPE_XMM)
@@ -842,16 +874,14 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("f32mem", TYPE_M)
TYPE("ssmem", TYPE_M)
TYPE("RST", TYPE_ST)
+ TYPE("RSTi", TYPE_ST)
TYPE("i128mem", TYPE_M)
TYPE("i256mem", TYPE_M)
TYPE("i512mem", TYPE_M)
TYPE("i64i32imm_pcrel", TYPE_REL)
TYPE("i16imm_pcrel", TYPE_REL)
TYPE("i32imm_pcrel", TYPE_REL)
- TYPE("SSECC", TYPE_IMM3)
- TYPE("XOPCC", TYPE_IMM3)
- TYPE("AVXCC", TYPE_IMM5)
- TYPE("AVX512ICC", TYPE_AVX512ICC)
+ TYPE("ccode", TYPE_IMM)
TYPE("AVX512RC", TYPE_IMM)
TYPE("brtarget32", TYPE_REL)
TYPE("brtarget16", TYPE_REL)
@@ -902,6 +932,11 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("VK32WM", TYPE_VK)
TYPE("VK64", TYPE_VK)
TYPE("VK64WM", TYPE_VK)
+ TYPE("VK1Pair", TYPE_VK_PAIR)
+ TYPE("VK2Pair", TYPE_VK_PAIR)
+ TYPE("VK4Pair", TYPE_VK_PAIR)
+ TYPE("VK8Pair", TYPE_VK_PAIR)
+ TYPE("VK16Pair", TYPE_VK_PAIR)
TYPE("vx64mem", TYPE_MVSIBX)
TYPE("vx128mem", TYPE_MVSIBX)
TYPE("vx256mem", TYPE_MVSIBX)
@@ -931,10 +966,6 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s,
ENCODING("i16imm", ENCODING_IW)
}
ENCODING("i32i8imm", ENCODING_IB)
- ENCODING("SSECC", ENCODING_IB)
- ENCODING("XOPCC", ENCODING_IB)
- ENCODING("AVXCC", ENCODING_IB)
- ENCODING("AVX512ICC", ENCODING_IB)
ENCODING("AVX512RC", ENCODING_IRC)
ENCODING("i16imm", ENCODING_Iv)
ENCODING("i16i8imm", ENCODING_IB)
@@ -943,7 +974,9 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s,
ENCODING("i64i8imm", ENCODING_IB)
ENCODING("i8imm", ENCODING_IB)
ENCODING("u8imm", ENCODING_IB)
+ ENCODING("i16u8imm", ENCODING_IB)
ENCODING("i32u8imm", ENCODING_IB)
+ ENCODING("i64u8imm", ENCODING_IB)
// This is not a typo. Instructions like BLENDVPD put
// register IDs in 8-bit immediates nowadays.
ENCODING("FR32", ENCODING_IB)
@@ -964,6 +997,7 @@ OperandEncoding
RecognizableInstr::rmRegisterEncodingFromString(const std::string &s,
uint8_t OpSize) {
ENCODING("RST", ENCODING_FP)
+ ENCODING("RSTi", ENCODING_FP)
ENCODING("GR16", ENCODING_RM)
ENCODING("GR32", ENCODING_RM)
ENCODING("GR32orGR64", ENCODING_RM)
@@ -987,6 +1021,11 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s,
ENCODING("VK16", ENCODING_RM)
ENCODING("VK32", ENCODING_RM)
ENCODING("VK64", ENCODING_RM)
+ ENCODING("VK1PAIR", ENCODING_RM)
+ ENCODING("VK2PAIR", ENCODING_RM)
+ ENCODING("VK4PAIR", ENCODING_RM)
+ ENCODING("VK8PAIR", ENCODING_RM)
+ ENCODING("VK16PAIR", ENCODING_RM)
ENCODING("BNDR", ENCODING_RM)
errs() << "Unhandled R/M register encoding " << s << "\n";
llvm_unreachable("Unhandled R/M register encoding");
@@ -1021,6 +1060,11 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s,
ENCODING("VK16", ENCODING_REG)
ENCODING("VK32", ENCODING_REG)
ENCODING("VK64", ENCODING_REG)
+ ENCODING("VK1Pair", ENCODING_REG)
+ ENCODING("VK2Pair", ENCODING_REG)
+ ENCODING("VK4Pair", ENCODING_REG)
+ ENCODING("VK8Pair", ENCODING_REG)
+ ENCODING("VK16Pair", ENCODING_REG)
ENCODING("VK1WM", ENCODING_REG)
ENCODING("VK2WM", ENCODING_REG)
ENCODING("VK4WM", ENCODING_REG)
@@ -1055,6 +1099,11 @@ RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s,
ENCODING("VK16", ENCODING_VVVV)
ENCODING("VK32", ENCODING_VVVV)
ENCODING("VK64", ENCODING_VVVV)
+ ENCODING("VK1PAIR", ENCODING_VVVV)
+ ENCODING("VK2PAIR", ENCODING_VVVV)
+ ENCODING("VK4PAIR", ENCODING_VVVV)
+ ENCODING("VK8PAIR", ENCODING_VVVV)
+ ENCODING("VK16PAIR", ENCODING_VVVV)
errs() << "Unhandled VEX.vvvv register encoding " << s << "\n";
llvm_unreachable("Unhandled VEX.vvvv register encoding");
}
@@ -1128,7 +1177,9 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s,
ENCODING("i64i8imm", ENCODING_IB)
ENCODING("i8imm", ENCODING_IB)
ENCODING("u8imm", ENCODING_IB)
+ ENCODING("i16u8imm", ENCODING_IB)
ENCODING("i32u8imm", ENCODING_IB)
+ ENCODING("i64u8imm", ENCODING_IB)
ENCODING("i64i32imm_pcrel", ENCODING_ID)
ENCODING("i16imm_pcrel", ENCODING_IW)
ENCODING("i32imm_pcrel", ENCODING_ID)
@@ -1166,6 +1217,7 @@ RecognizableInstr::opcodeModifierEncodingFromString(const std::string &s,
ENCODING("GR64", ENCODING_RO)
ENCODING("GR16", ENCODING_Rv)
ENCODING("GR8", ENCODING_RB)
+ ENCODING("ccode", ENCODING_CC)
errs() << "Unhandled opcode modifier encoding " << s << "\n";
llvm_unreachable("Unhandled opcode modifier encoding");
}
diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h
index c4d34ee6c80c..b15bef4e1931 100644
--- a/utils/TableGen/X86RecognizableInstr.h
+++ b/utils/TableGen/X86RecognizableInstr.h
@@ -1,9 +1,8 @@
//===- X86RecognizableInstr.h - Disassembler instruction spec ----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -102,18 +101,21 @@ namespace X86Local {
RawFrmDstSrc = 6,
RawFrmImm8 = 7,
RawFrmImm16 = 8,
+ AddCCFrm = 9,
MRMDestMem = 32,
MRMSrcMem = 33,
MRMSrcMem4VOp3 = 34,
MRMSrcMemOp4 = 35,
- MRMXm = 39,
+ MRMSrcMemCC = 36,
+ MRMXmCC = 38, 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,
+ MRMSrcRegCC = 52,
+ MRMXrCC = 54, 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,
@@ -140,10 +142,6 @@ namespace X86Local {
enum {
AdSize16 = 1, AdSize32 = 2, AdSize64 = 3
};
-
- enum {
- VEX_W0 = 0, VEX_W1 = 1, VEX_WIG = 2, VEX_W1X = 3
- };
}
namespace X86Disassembler {
@@ -177,8 +175,10 @@ private:
bool HasREX_WPrefix;
/// The hasVEX_4V field from the record
bool HasVEX_4V;
- /// The VEX_WPrefix field from the record
- uint8_t VEX_WPrefix;
+ /// The HasVEX_WPrefix field from the record
+ bool HasVEX_W;
+ /// The IgnoresVEX_W field from the record
+ bool IgnoresVEX_W;
/// Inferred from the operands; indicates whether the L bit in the VEX prefix is set
bool HasVEX_LPrefix;
/// The ignoreVEX_L field from the record