aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/utils/TableGen
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/utils/TableGen')
-rw-r--r--llvm/utils/TableGen/AsmMatcherEmitter.cpp59
-rw-r--r--llvm/utils/TableGen/AsmWriterEmitter.cpp3
-rw-r--r--llvm/utils/TableGen/AsmWriterInst.h3
-rw-r--r--llvm/utils/TableGen/Attributes.cpp33
-rw-r--r--llvm/utils/TableGen/CallingConvEmitter.cpp28
-rw-r--r--llvm/utils/TableGen/CodeBeadsGen.cpp137
-rw-r--r--llvm/utils/TableGen/CodeEmitterGen.cpp12
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.cpp336
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.h86
-rw-r--r--llvm/utils/TableGen/CodeGenInstruction.cpp60
-rw-r--r--llvm/utils/TableGen/CodeGenInstruction.h4
-rw-r--r--llvm/utils/TableGen/CodeGenIntrinsics.h3
-rw-r--r--llvm/utils/TableGen/CodeGenMapTable.cpp10
-rw-r--r--llvm/utils/TableGen/CodeGenRegisters.cpp124
-rw-r--r--llvm/utils/TableGen/CodeGenRegisters.h7
-rw-r--r--llvm/utils/TableGen/CodeGenSchedule.cpp166
-rw-r--r--llvm/utils/TableGen/CodeGenTarget.cpp21
-rw-r--r--llvm/utils/TableGen/DAGISelEmitter.cpp11
-rw-r--r--llvm/utils/TableGen/DAGISelMatcher.cpp12
-rw-r--r--llvm/utils/TableGen/DAGISelMatcher.h2
-rw-r--r--llvm/utils/TableGen/DAGISelMatcherEmitter.cpp53
-rw-r--r--llvm/utils/TableGen/DAGISelMatcherGen.cpp4
-rw-r--r--llvm/utils/TableGen/DFAEmitter.cpp9
-rw-r--r--llvm/utils/TableGen/DFAPacketizerEmitter.cpp8
-rw-r--r--llvm/utils/TableGen/DirectiveEmitter.cpp89
-rw-r--r--llvm/utils/TableGen/ExegesisEmitter.cpp4
-rw-r--r--llvm/utils/TableGen/FastISelEmitter.cpp75
-rw-r--r--llvm/utils/TableGen/FixedLenDecoderEmitter.cpp109
-rw-r--r--llvm/utils/TableGen/GICombinerEmitter.cpp12
-rw-r--r--llvm/utils/TableGen/GlobalISelEmitter.cpp179
-rw-r--r--llvm/utils/TableGen/InfoByHwMode.cpp20
-rw-r--r--llvm/utils/TableGen/InfoByHwMode.h20
-rw-r--r--llvm/utils/TableGen/InstrDocsEmitter.cpp40
-rw-r--r--llvm/utils/TableGen/InstrInfoEmitter.cpp191
-rw-r--r--llvm/utils/TableGen/IntrinsicEmitter.cpp240
-rw-r--r--llvm/utils/TableGen/OptParserEmitter.cpp2
-rw-r--r--llvm/utils/TableGen/PseudoLoweringEmitter.cpp5
-rw-r--r--llvm/utils/TableGen/RISCVCompressInstEmitter.cpp4
-rw-r--r--llvm/utils/TableGen/RegisterInfoEmitter.cpp122
-rw-r--r--llvm/utils/TableGen/SearchableTableEmitter.cpp39
-rw-r--r--llvm/utils/TableGen/SubtargetEmitter.cpp33
-rw-r--r--llvm/utils/TableGen/SubtargetFeatureInfo.cpp11
-rw-r--r--llvm/utils/TableGen/TableGen.cpp14
-rw-r--r--llvm/utils/TableGen/TableGenBackends.h2
-rw-r--r--llvm/utils/TableGen/X86DisassemblerTables.cpp61
-rw-r--r--llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp38
-rw-r--r--llvm/utils/TableGen/X86RecognizableInstr.cpp13
47 files changed, 1444 insertions, 1070 deletions
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 9d304910ba4e..00bdd127e3c2 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -612,7 +612,7 @@ struct MatchableInfo {
/// operator< - Compare two matchables.
bool operator<(const MatchableInfo &RHS) const {
// The primary comparator is the instruction mnemonic.
- if (int Cmp = Mnemonic.compare_lower(RHS.Mnemonic))
+ if (int Cmp = Mnemonic.compare_insensitive(RHS.Mnemonic))
return Cmp == -1;
if (AsmOperands.size() != RHS.AsmOperands.size())
@@ -1100,8 +1100,8 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool IsAlias) const {
static std::string getEnumNameForToken(StringRef Str) {
std::string Res;
- for (StringRef::iterator it = Str.begin(), ie = Str.end(); it != ie; ++it) {
- switch (*it) {
+ for (char C : Str) {
+ switch (C) {
case '*': Res += "_STAR_"; break;
case '%': Res += "_PCT_"; break;
case ':': Res += "_COLON_"; break;
@@ -1112,10 +1112,10 @@ static std::string getEnumNameForToken(StringRef Str) {
case '-': Res += "_MINUS_"; break;
case '#': Res += "_HASH_"; break;
default:
- if (isAlnum(*it))
- Res += *it;
+ if (isAlnum(C))
+ Res += C;
else
- Res += "_" + utostr((unsigned) *it) + "_";
+ Res += "_" + utostr((unsigned)C) + "_";
}
}
@@ -1322,9 +1322,8 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
}
// Populate the map for individual registers.
- for (std::map<Record*, RegisterSet>::iterator it = RegisterMap.begin(),
- ie = RegisterMap.end(); it != ie; ++it)
- RegisterClasses[it->first] = RegisterSetClasses[it->second];
+ for (auto &It : RegisterMap)
+ RegisterClasses[It.first] = RegisterSetClasses[It.second];
// Name the register classes which correspond to singleton registers.
for (Record *Rec : SingletonRegisters) {
@@ -1529,9 +1528,8 @@ void AsmMatcherInfo::buildInfo() {
// matchables.
std::vector<Record*> AllInstAliases =
Records.getAllDerivedDefinitions("InstAlias");
- for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) {
- auto Alias = std::make_unique<CodeGenInstAlias>(AllInstAliases[i],
- Target);
+ for (Record *InstAlias : AllInstAliases) {
+ auto Alias = std::make_unique<CodeGenInstAlias>(InstAlias, Target);
// If the tblgen -match-prefix option is specified (for tblgen hackers),
// filter the set of instruction aliases we consider, based on the target
@@ -2726,7 +2724,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
StringRef AsmVariantName = R->getValueAsString("AsmVariantName");
if (AsmVariantName != AsmParserVariantName)
continue;
- AliasesFromMnemonic[std::string(R->getValueAsString("FromMnemonic"))]
+ AliasesFromMnemonic[R->getValueAsString("FromMnemonic").lower()]
.push_back(R);
}
if (AliasesFromMnemonic.empty())
@@ -2751,10 +2749,14 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
// If this unconditionally matches, remember it for later and diagnose
// duplicates.
if (FeatureMask.empty()) {
- if (AliasWithNoPredicate != -1) {
- // We can't have two aliases from the same mnemonic with no predicate.
- PrintError(ToVec[AliasWithNoPredicate]->getLoc(),
- "two MnemonicAliases with the same 'from' mnemonic!");
+ if (AliasWithNoPredicate != -1 &&
+ R->getValueAsString("ToMnemonic") !=
+ ToVec[AliasWithNoPredicate]->getValueAsString("ToMnemonic")) {
+ // We can't have two different aliases from the same mnemonic with no
+ // predicate.
+ PrintError(
+ ToVec[AliasWithNoPredicate]->getLoc(),
+ "two different MnemonicAliases with the same 'from' mnemonic!");
PrintFatalError(R->getLoc(), "this is the other MnemonicAlias.");
}
@@ -2768,7 +2770,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
MatchCode += "else ";
MatchCode += "if (" + FeatureMask + ")\n";
MatchCode += " Mnemonic = \"";
- MatchCode += R->getValueAsString("ToMnemonic");
+ MatchCode += R->getValueAsString("ToMnemonic").lower();
MatchCode += "\";\n";
}
@@ -2777,7 +2779,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
if (!MatchCode.empty())
MatchCode += "else\n ";
MatchCode += "Mnemonic = \"";
- MatchCode += R->getValueAsString("ToMnemonic");
+ MatchCode += R->getValueAsString("ToMnemonic").lower();
MatchCode += "\";\n";
}
@@ -2883,14 +2885,10 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
OS << OMI.OperandMask;
OS << " /* ";
- bool printComma = false;
+ ListSeparator LS;
for (int i = 0, e = 31; i !=e; ++i)
- if (OMI.OperandMask & (1 << i)) {
- if (printComma)
- OS << ", ";
- OS << i;
- printComma = true;
- }
+ if (OMI.OperandMask & (1 << i))
+ OS << LS << i;
OS << " */, ";
OS << OMI.CI->Name;
@@ -3513,12 +3511,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << '_' << MI->RequiredFeatures[i]->TheDef->getName();
OS << ", { ";
- for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) {
- const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i];
-
- if (i) OS << ", ";
- OS << Op.Class->Name;
- }
+ ListSeparator LS;
+ for (const MatchableInfo::AsmOperand &Op : MI->AsmOperands)
+ OS << LS << Op.Class->Name;
OS << " }, },\n";
}
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index 92df204475b9..94fd8f7e92b4 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -994,8 +994,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
});
}
- for (auto I = ReqFeatures.cbegin(); I != ReqFeatures.cend(); I++) {
- Record *R = *I;
+ for (Record *const R : ReqFeatures) {
const DagInit *D = R->getValueAsDag("AssemblerCondDag");
std::string CombineType = D->getOperator()->getAsString();
if (CombineType != "any_of" && CombineType != "all_of")
diff --git a/llvm/utils/TableGen/AsmWriterInst.h b/llvm/utils/TableGen/AsmWriterInst.h
index 366c9eca664f..fe2b934e266f 100644
--- a/llvm/utils/TableGen/AsmWriterInst.h
+++ b/llvm/utils/TableGen/AsmWriterInst.h
@@ -66,7 +66,8 @@ namespace llvm {
bool operator!=(const AsmWriterOperand &Other) const {
if (OperandType != Other.OperandType || Str != Other.Str) return true;
if (OperandType == isMachineInstrOperand)
- return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier;
+ return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier ||
+ PCRel != Other.PCRel;
return false;
}
bool operator==(const AsmWriterOperand &Other) const {
diff --git a/llvm/utils/TableGen/Attributes.cpp b/llvm/utils/TableGen/Attributes.cpp
index f3f875e8ce0b..5deac4b34bf2 100644
--- a/llvm/utils/TableGen/Attributes.cpp
+++ b/llvm/utils/TableGen/Attributes.cpp
@@ -25,6 +25,7 @@ public:
private:
void emitTargetIndependentNames(raw_ostream &OS);
void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
+ void emitAttributeProperties(raw_ostream &OF);
RecordKeeper &Records;
};
@@ -58,7 +59,20 @@ void Attributes::emitTargetIndependentNames(raw_ostream &OS) {
Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL");
OS << "#undef ATTRIBUTE_ALL\n";
- OS << "#endif\n";
+ OS << "#endif\n\n";
+
+ OS << "#ifdef GET_ATTR_ENUM\n";
+ OS << "#undef GET_ATTR_ENUM\n";
+ unsigned Value = 1; // Leave zero for AttrKind::None.
+ for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) {
+ OS << "First" << KindName << " = " << Value << ",\n";
+ for (auto A : Records.getAllDerivedDefinitions(KindName)) {
+ OS << A->getName() << " = " << Value << ",\n";
+ Value++;
+ }
+ OS << "Last" << KindName << " = " << (Value - 1) << ",\n";
+ }
+ OS << "#endif\n\n";
}
void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
@@ -96,9 +110,26 @@ void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
OS << "#endif\n";
}
+void Attributes::emitAttributeProperties(raw_ostream &OS) {
+ OS << "#ifdef GET_ATTR_PROP_TABLE\n";
+ OS << "#undef GET_ATTR_PROP_TABLE\n";
+ OS << "static const uint8_t AttrPropTable[] = {\n";
+ for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) {
+ for (auto A : Records.getAllDerivedDefinitions(KindName)) {
+ OS << "0";
+ for (Init *P : *A->getValueAsListInit("Properties"))
+ OS << " | AttributeProperty::" << cast<DefInit>(P)->getDef()->getName();
+ OS << ",\n";
+ }
+ }
+ OS << "};\n";
+ OS << "#endif\n";
+}
+
void Attributes::emit(raw_ostream &OS) {
emitTargetIndependentNames(OS);
emitFnAttrCompatCheck(OS, false);
+ emitAttributeProperties(OS);
}
namespace llvm {
diff --git a/llvm/utils/TableGen/CallingConvEmitter.cpp b/llvm/utils/TableGen/CallingConvEmitter.cpp
index 9e997483d21d..127ae6247bd9 100644
--- a/llvm/utils/TableGen/CallingConvEmitter.cpp
+++ b/llvm/utils/TableGen/CallingConvEmitter.cpp
@@ -131,10 +131,9 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << IndentStr << "static const MCPhysReg RegList" << ++Counter
<< "[] = {\n";
O << IndentStr << " ";
- for (unsigned i = 0, e = RegList->size(); i != e; ++i) {
- if (i != 0) O << ", ";
- O << getQualifiedName(RegList->getElementAsRecord(i));
- }
+ ListSeparator LS;
+ for (unsigned i = 0, e = RegList->size(); i != e; ++i)
+ O << LS << getQualifiedName(RegList->getElementAsRecord(i));
O << "\n" << IndentStr << "};\n";
O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
<< Counter << ")) {\n";
@@ -162,19 +161,17 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << IndentStr << "static const MCPhysReg RegList" << RegListNumber
<< "[] = {\n";
O << IndentStr << " ";
- for (unsigned i = 0, e = RegList->size(); i != e; ++i) {
- if (i != 0) O << ", ";
- O << getQualifiedName(RegList->getElementAsRecord(i));
- }
+ ListSeparator LS;
+ for (unsigned i = 0, e = RegList->size(); i != e; ++i)
+ O << LS << getQualifiedName(RegList->getElementAsRecord(i));
O << "\n" << IndentStr << "};\n";
O << IndentStr << "static const MCPhysReg RegList"
<< ShadowRegListNumber << "[] = {\n";
O << IndentStr << " ";
- for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) {
- if (i != 0) O << ", ";
- O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
- }
+ ListSeparator LSS;
+ for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i)
+ O << LSS << getQualifiedName(ShadowRegList->getElementAsRecord(i));
O << "\n" << IndentStr << "};\n";
O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
@@ -220,10 +217,9 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << IndentStr << "static const MCPhysReg ShadowRegList"
<< ShadowRegListNumber << "[] = {\n";
O << IndentStr << " ";
- for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) {
- if (i != 0) O << ", ";
- O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
- }
+ ListSeparator LS;
+ for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i)
+ O << LS << getQualifiedName(ShadowRegList->getElementAsRecord(i));
O << "\n" << IndentStr << "};\n";
O << IndentStr << "unsigned Offset" << ++Counter
diff --git a/llvm/utils/TableGen/CodeBeadsGen.cpp b/llvm/utils/TableGen/CodeBeadsGen.cpp
new file mode 100644
index 000000000000..18a6d6d19eb2
--- /dev/null
+++ b/llvm/utils/TableGen/CodeBeadsGen.cpp
@@ -0,0 +1,137 @@
+//===---------- CodeBeadsGen.cpp - Code Beads Generator -------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// CodeBeads are data fields carrying auxiliary information for instructions.
+//
+// Under the hood it's simply implemented by a `bits` field (with arbitrary
+// length) in each TG instruction description, where this TG backend will
+// generate a helper function to access it.
+//
+// This is especially useful for expressing variable length encoding
+// instructions and complex addressing modes. Since in those cases each
+// instruction is usually associated with large amount of information like
+// addressing mode details used on a specific operand. Instead of retreating to
+// ad-hoc methods to figure out these information when encoding an instruction,
+// CodeBeads provide a clean table for the instruction encoder to lookup.
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTarget.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <map>
+#include <string>
+#include <vector>
+using namespace llvm;
+
+namespace {
+
+class CodeBeadsGen {
+ RecordKeeper &Records;
+
+public:
+ CodeBeadsGen(RecordKeeper &R) : Records(R) {}
+ void run(raw_ostream &OS);
+};
+
+void CodeBeadsGen::run(raw_ostream &OS) {
+ CodeGenTarget Target(Records);
+ std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
+
+ // For little-endian instruction bit encodings, reverse the bit order
+ Target.reverseBitsForLittleEndianEncoding();
+
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ // Emit function declaration
+ OS << "const uint8_t *llvm::" << Target.getInstNamespace();
+ OS << "::getMCInstrBeads(unsigned Opcode) {\n";
+
+ // First, get the maximum bit length among all beads. And do some
+ // simple validation
+ unsigned MaxBitLength = 0;
+
+ for (const CodeGenInstruction *CGI : NumberedInstructions) {
+ Record *R = CGI->TheDef;
+ if (!R->getValue("Beads"))
+ continue;
+
+ BitsInit *BI = R->getValueAsBitsInit("Beads");
+ if (!BI->isComplete()) {
+ PrintFatalError(R->getLoc(), "Record `" + R->getName() +
+ "', bit field 'Beads' is not complete");
+ }
+
+ MaxBitLength = std::max(MaxBitLength, BI->getNumBits());
+ }
+
+ // Number of bytes
+ unsigned Parts = MaxBitLength / 8;
+
+ // Emit instruction base values
+ OS << " static const uint8_t InstBits[][" << Parts << "] = {\n";
+ for (const CodeGenInstruction *CGI : NumberedInstructions) {
+ Record *R = CGI->TheDef;
+
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ !R->getValue("Beads")) {
+ OS << "\t{ 0x0 },\t// ";
+ if (R->getValueAsBit("isPseudo"))
+ OS << "(Pseudo) ";
+ OS << R->getName() << "\n";
+ continue;
+ }
+
+ BitsInit *BI = R->getValueAsBitsInit("Beads");
+
+ // Convert to byte array:
+ // [dcba] -> [a][b][c][d]
+ OS << "\t{";
+ for (unsigned p = 0; p < Parts; ++p) {
+ unsigned Right = 8 * p;
+ unsigned Left = Right + 8;
+
+ uint8_t Value = 0;
+ for (unsigned i = Right; i != Left; ++i) {
+ unsigned Shift = i % 8;
+ if (auto *B = dyn_cast<BitInit>(BI->getBit(i))) {
+ Value |= (static_cast<uint8_t>(B->getValue()) << Shift);
+ } else {
+ PrintFatalError(R->getLoc(), "Record `" + R->getName() +
+ "', bit 'Beads[" + Twine(i) +
+ "]' is not defined");
+ }
+ }
+
+ if (p)
+ OS << ',';
+ OS << " 0x";
+ OS.write_hex(Value);
+ OS << "";
+ }
+ OS << " }," << '\t' << "// " << R->getName() << "\n";
+ }
+ OS << "\t{ 0x0 }\n };\n";
+
+ // Emit initial function code
+ OS << " return InstBits[Opcode];\n"
+ << "}\n\n";
+}
+
+} // End anonymous namespace
+
+namespace llvm {
+
+void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS) {
+ emitSourceFileHeader("Machine Code Beads", OS);
+ CodeBeadsGen(RK).run(OS);
+}
+
+} // namespace llvm
diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp
index 53bf953b13cf..ffc2878d3508 100644
--- a/llvm/utils/TableGen/CodeEmitterGen.cpp
+++ b/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -272,7 +272,7 @@ std::string CodeEmitterGen::getInstructionCase(Record *R,
EncodingInfoByHwMode EBM(DI->getDef(), HWM);
Case += " switch (HwMode) {\n";
Case += " default: llvm_unreachable(\"Unhandled HwMode\");\n";
- for (auto &KV : EBM.Map) {
+ for (auto &KV : EBM) {
Case += " case " + itostr(KV.first) + ": {\n";
Case += getInstructionCaseForEncoding(R, KV.second, Target);
Case += " break;\n";
@@ -409,7 +409,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
if (const RecordVal *RV = R->getValue("EncodingInfos")) {
if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
EncodingInfoByHwMode EBM(DI->getDef(), HWM);
- for (auto &KV : EBM.Map) {
+ for (auto &KV : EBM) {
BitsInit *BI = KV.second->getValueAsBitsInit("Inst");
BitWidth = std::max(BitWidth, BI->getNumBits());
HwModes.insert(KV.first);
@@ -461,9 +461,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
std::map<std::string, std::vector<std::string>> CaseMap;
// Construct all cases statement for each opcode
- for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
- IC != EC; ++IC) {
- Record *R = *IC;
+ for (Record *R : Insts) {
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
R->getValueAsBit("isPseudo"))
continue;
@@ -483,8 +481,8 @@ void CodeEmitterGen::run(raw_ostream &o) {
<< " Inst = Inst.zext(" << BitWidth << ");\n"
<< " if (Scratch.getBitWidth() != " << BitWidth << ")\n"
<< " Scratch = Scratch.zext(" << BitWidth << ");\n"
- << " LoadIntFromMemory(Inst, (uint8_t *)&InstBits[opcode * " << NumWords
- << "], " << NumBytes << ");\n"
+ << " LoadIntFromMemory(Inst, (const uint8_t *)&InstBits[opcode * "
+ << NumWords << "], " << NumBytes << ");\n"
<< " APInt &Value = Inst;\n"
<< " APInt &op = Scratch;\n"
<< " switch (opcode) {\n";
diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index 1ca4a68eb155..c1a3a34d928b 100644
--- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "CodeGenDAGPatterns.h"
-#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
@@ -111,10 +110,8 @@ bool TypeSetByHwMode::insert(const ValueTypeByHwMode &VVT) {
bool ContainsDefault = false;
MVT DT = MVT::Other;
- SmallDenseSet<unsigned, 4> Modes;
for (const auto &P : VVT) {
unsigned M = P.first;
- Modes.insert(M);
// Make sure there exists a set for each specific mode from VVT.
Changed |= getOrCreate(M).insert(P.second).second;
// Cache VVT's default mode.
@@ -128,7 +125,7 @@ bool TypeSetByHwMode::insert(const ValueTypeByHwMode &VVT) {
// modes in "this" that do not exist in VVT.
if (ContainsDefault)
for (auto &I : *this)
- if (!Modes.count(I.first))
+ if (!VVT.hasMode(I.first))
Changed |= I.second.insert(DT).second;
return Changed;
@@ -205,11 +202,9 @@ void TypeSetByHwMode::writeToStream(const SetType &S, raw_ostream &OS) {
array_pod_sort(Types.begin(), Types.end());
OS << '[';
- for (unsigned i = 0, e = Types.size(); i != e; ++i) {
- OS << ValueTypeByHwMode::getMVTName(Types[i]);
- if (i != e-1)
- OS << ' ';
- }
+ ListSeparator LS(" ");
+ for (const MVT &T : Types)
+ OS << LS << ValueTypeByHwMode::getMVTName(T);
OS << ']';
}
@@ -226,7 +221,7 @@ bool TypeSetByHwMode::operator==(const TypeSetByHwMode &VTS) const {
if (HaveDefault != VTSHaveDefault)
return false;
- SmallDenseSet<unsigned, 4> Modes;
+ SmallSet<unsigned, 4> Modes;
for (auto &I : *this)
Modes.insert(I.first);
for (const auto &I : VTS)
@@ -470,7 +465,8 @@ bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small,
assert(Small.hasDefault() && Big.hasDefault());
- std::vector<unsigned> Modes = union_modes(Small, Big);
+ SmallVector<unsigned, 4> Modes;
+ union_modes(Small, Big, Modes);
// 1. Only allow integer or floating point types and make sure that
// both sides are both integer or both floating point.
@@ -577,7 +573,9 @@ bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec,
if (Elem.empty())
Changed |= EnforceScalar(Elem);
- for (unsigned M : union_modes(Vec, Elem)) {
+ SmallVector<unsigned, 4> Modes;
+ union_modes(Vec, Elem, Modes);
+ for (unsigned M : Modes) {
TypeSetByHwMode::SetType &V = Vec.get(M);
TypeSetByHwMode::SetType &E = Elem.get(M);
@@ -585,7 +583,7 @@ bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec,
Changed |= berase_if(E, isVector); // Vector = !scalar
assert(!V.empty() && !E.empty());
- SmallSet<MVT,4> VT, ST;
+ MachineValueTypeSet VT, ST;
// Collect element types from the "vector" set.
for (MVT T : V)
VT.insert(T.getVectorElementType());
@@ -632,7 +630,7 @@ bool TypeInfer::EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec,
return false;
if (B.getVectorElementType() != P.getVectorElementType())
return false;
- return B.getVectorNumElements() < P.getVectorNumElements();
+ return B.getVectorMinNumElements() < P.getVectorMinNumElements();
};
/// Return true if S has no element (vector type) that T is a sub-vector of,
@@ -660,7 +658,9 @@ bool TypeInfer::EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec,
if (Sub.empty())
Changed |= EnforceVector(Sub);
- for (unsigned M : union_modes(Vec, Sub)) {
+ SmallVector<unsigned, 4> Modes;
+ union_modes(Vec, Sub, Modes);
+ for (unsigned M : Modes) {
TypeSetByHwMode::SetType &S = Sub.get(M);
TypeSetByHwMode::SetType &V = Vec.get(M);
@@ -696,19 +696,25 @@ bool TypeInfer::EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W) {
// An actual vector type cannot have 0 elements, so we can treat scalars
// as zero-length vectors. This way both vectors and scalars can be
// processed identically.
- auto NoLength = [](const SmallSet<unsigned,2> &Lengths, MVT T) -> bool {
- return !Lengths.count(T.isVector() ? T.getVectorNumElements() : 0);
+ auto NoLength = [](const SmallDenseSet<ElementCount> &Lengths,
+ MVT T) -> bool {
+ return !Lengths.count(T.isVector() ? T.getVectorElementCount()
+ : ElementCount::getNull());
};
- for (unsigned M : union_modes(V, W)) {
+ SmallVector<unsigned, 4> Modes;
+ union_modes(V, W, Modes);
+ for (unsigned M : Modes) {
TypeSetByHwMode::SetType &VS = V.get(M);
TypeSetByHwMode::SetType &WS = W.get(M);
- SmallSet<unsigned,2> VN, WN;
+ SmallDenseSet<ElementCount> VN, WN;
for (MVT T : VS)
- VN.insert(T.isVector() ? T.getVectorNumElements() : 0);
+ VN.insert(T.isVector() ? T.getVectorElementCount()
+ : ElementCount::getNull());
for (MVT T : WS)
- WN.insert(T.isVector() ? T.getVectorNumElements() : 0);
+ WN.insert(T.isVector() ? T.getVectorElementCount()
+ : ElementCount::getNull());
Changed |= berase_if(VS, std::bind(NoLength, WN, std::placeholders::_1));
Changed |= berase_if(WS, std::bind(NoLength, VN, std::placeholders::_1));
@@ -716,6 +722,15 @@ bool TypeInfer::EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W) {
return Changed;
}
+namespace {
+struct TypeSizeComparator {
+ bool operator()(const TypeSize &LHS, const TypeSize &RHS) const {
+ return std::make_tuple(LHS.isScalable(), LHS.getKnownMinValue()) <
+ std::make_tuple(RHS.isScalable(), RHS.getKnownMinValue());
+ }
+};
+} // end anonymous namespace
+
/// 1. Ensure that for each type T in A, there exists a type U in B,
/// such that T and U have equal size in bits.
/// 2. Ensure that for each type U in B, there exists a type T in A
@@ -730,14 +745,18 @@ bool TypeInfer::EnforceSameSize(TypeSetByHwMode &A, TypeSetByHwMode &B) {
if (B.empty())
Changed |= EnforceAny(B);
- auto NoSize = [](const SmallSet<TypeSize, 2> &Sizes, MVT T) -> bool {
+ typedef SmallSet<TypeSize, 2, TypeSizeComparator> TypeSizeSet;
+
+ auto NoSize = [](const TypeSizeSet &Sizes, MVT T) -> bool {
return !Sizes.count(T.getSizeInBits());
};
- for (unsigned M : union_modes(A, B)) {
+ SmallVector<unsigned, 4> Modes;
+ union_modes(A, B, Modes);
+ for (unsigned M : Modes) {
TypeSetByHwMode::SetType &AS = A.get(M);
TypeSetByHwMode::SetType &BS = B.get(M);
- SmallSet<TypeSize, 2> AN, BN;
+ TypeSizeSet AN, BN;
for (MVT T : AS)
AN.insert(T.getSizeInBits());
@@ -837,7 +856,11 @@ TypeInfer::ValidateOnExit::~ValidateOnExit() {
"(use -print-records with llvm-tblgen to see all "
"expanded records).\n";
Infer.TP.dump();
- llvm_unreachable(nullptr);
+ dbgs() << "Generated from record:\n";
+ Infer.TP.getRecord()->dump();
+ PrintFatalError(Infer.TP.getRecord()->getLoc(),
+ "Type set is empty for each HW mode in '" +
+ Infer.TP.getRecord()->getName() + "'");
}
}
#endif
@@ -980,12 +1003,9 @@ std::string TreePredicateFn::getPredCode() const {
Code += "unsigned AddrSpace = cast<MemSDNode>(N)->getAddressSpace();\n"
" if (";
- bool First = true;
+ ListSeparator LS(" && ");
for (Init *Val : AddressSpaces->getValues()) {
- if (First)
- First = false;
- else
- Code += " && ";
+ Code += LS;
IntInit *IntVal = dyn_cast<IntInit>(Val);
if (!IntVal) {
@@ -1015,33 +1035,33 @@ std::string TreePredicateFn::getPredCode() const {
}
if (isAtomic() && isAtomicOrderingMonotonic())
- Code += "if (cast<AtomicSDNode>(N)->getOrdering() != "
+ Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != "
"AtomicOrdering::Monotonic) return false;\n";
if (isAtomic() && isAtomicOrderingAcquire())
- Code += "if (cast<AtomicSDNode>(N)->getOrdering() != "
+ Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != "
"AtomicOrdering::Acquire) return false;\n";
if (isAtomic() && isAtomicOrderingRelease())
- Code += "if (cast<AtomicSDNode>(N)->getOrdering() != "
+ Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != "
"AtomicOrdering::Release) return false;\n";
if (isAtomic() && isAtomicOrderingAcquireRelease())
- Code += "if (cast<AtomicSDNode>(N)->getOrdering() != "
+ Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != "
"AtomicOrdering::AcquireRelease) return false;\n";
if (isAtomic() && isAtomicOrderingSequentiallyConsistent())
- Code += "if (cast<AtomicSDNode>(N)->getOrdering() != "
+ Code += "if (cast<AtomicSDNode>(N)->getMergedOrdering() != "
"AtomicOrdering::SequentiallyConsistent) return false;\n";
if (isAtomic() && isAtomicOrderingAcquireOrStronger())
- Code += "if (!isAcquireOrStronger(cast<AtomicSDNode>(N)->getOrdering())) "
+ Code += "if (!isAcquireOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) "
"return false;\n";
if (isAtomic() && isAtomicOrderingWeakerThanAcquire())
- Code += "if (isAcquireOrStronger(cast<AtomicSDNode>(N)->getOrdering())) "
+ Code += "if (isAcquireOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) "
"return false;\n";
if (isAtomic() && isAtomicOrderingReleaseOrStronger())
- Code += "if (!isReleaseOrStronger(cast<AtomicSDNode>(N)->getOrdering())) "
+ Code += "if (!isReleaseOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) "
"return false;\n";
if (isAtomic() && isAtomicOrderingWeakerThanRelease())
- Code += "if (isReleaseOrStronger(cast<AtomicSDNode>(N)->getOrdering())) "
+ Code += "if (isReleaseOrStronger(cast<AtomicSDNode>(N)->getMergedOrdering())) "
"return false;\n";
if (isLoad() || isStore()) {
@@ -1242,7 +1262,7 @@ StringRef TreePredicateFn::getImmType() const {
StringRef TreePredicateFn::getImmTypeIdentifier() const {
if (immCodeUsesAPInt())
return "APInt";
- else if (immCodeUsesAPFloat())
+ if (immCodeUsesAPFloat())
return "APFloat";
return "I64";
}
@@ -1423,24 +1443,50 @@ getPatternComplexity(const CodeGenDAGPatterns &CGP) const {
return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity();
}
+void PatternToMatch::getPredicateRecords(
+ SmallVectorImpl<Record *> &PredicateRecs) const {
+ for (Init *I : Predicates->getValues()) {
+ if (DefInit *Pred = dyn_cast<DefInit>(I)) {
+ Record *Def = Pred->getDef();
+ if (!Def->isSubClassOf("Predicate")) {
+#ifndef NDEBUG
+ Def->dump();
+#endif
+ llvm_unreachable("Unknown predicate type!");
+ }
+ PredicateRecs.push_back(Def);
+ }
+ }
+ // Sort so that different orders get canonicalized to the same string.
+ llvm::sort(PredicateRecs, LessRecord());
+}
+
/// getPredicateCheck - Return a single string containing all of this
/// pattern's predicates concatenated with "&&" operators.
///
std::string PatternToMatch::getPredicateCheck() const {
- SmallVector<const Predicate*,4> PredList;
- for (const Predicate &P : Predicates) {
- if (!P.getCondString().empty())
- PredList.push_back(&P);
+ SmallVector<Record *, 4> PredicateRecs;
+ getPredicateRecords(PredicateRecs);
+
+ SmallString<128> PredicateCheck;
+ for (Record *Pred : PredicateRecs) {
+ StringRef CondString = Pred->getValueAsString("CondString");
+ if (CondString.empty())
+ continue;
+ if (!PredicateCheck.empty())
+ PredicateCheck += " && ";
+ PredicateCheck += "(";
+ PredicateCheck += CondString;
+ PredicateCheck += ")";
}
- llvm::sort(PredList, deref<std::less<>>());
- std::string Check;
- for (unsigned i = 0, e = PredList.size(); i != e; ++i) {
- if (i != 0)
- Check += " && ";
- Check += '(' + PredList[i]->getCondString() + ')';
+ if (!HwModeFeatures.empty()) {
+ if (!PredicateCheck.empty())
+ PredicateCheck += " && ";
+ PredicateCheck += HwModeFeatures;
}
- return Check;
+
+ return std::string(PredicateCheck);
}
//===----------------------------------------------------------------------===//
@@ -1791,7 +1837,7 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
// The number of results of a fragment with alternative records is the
// maximum number of results across all alternatives.
unsigned NumResults = 0;
- for (auto T : PFRec->getTrees())
+ for (const auto &T : PFRec->getTrees())
NumResults = std::max(NumResults, T->getNumTypes());
return NumResults;
}
@@ -1857,9 +1903,9 @@ void TreePatternNode::print(raw_ostream &OS) const {
if (!isLeaf()) {
if (getNumChildren() != 0) {
OS << " ";
- getChild(0)->print(OS);
- for (unsigned i = 1, e = getNumChildren(); i != e; ++i) {
- OS << ", ";
+ ListSeparator LS;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+ OS << LS;
getChild(i)->print(OS);
}
}
@@ -2013,10 +2059,13 @@ void TreePatternNode::InlinePatternFragments(
if (ChildAlternatives[i].empty())
return;
- for (auto NewChild : ChildAlternatives[i])
- assert((Child->getPredicateCalls().empty() ||
- NewChild->getPredicateCalls() == Child->getPredicateCalls()) &&
- "Non-empty child predicate clobbered!");
+ assert((Child->getPredicateCalls().empty() ||
+ llvm::all_of(ChildAlternatives[i],
+ [&](const TreePatternNodePtr &NewChild) {
+ return NewChild->getPredicateCalls() ==
+ Child->getPredicateCalls();
+ })) &&
+ "Non-empty child predicate clobbered!");
}
// The end result is an all-pairs construction of the resultant pattern.
@@ -2088,7 +2137,7 @@ void TreePatternNode::InlinePatternFragments(
}
// Loop over all fragment alternatives.
- for (auto Alternative : Frag->getTrees()) {
+ for (const auto &Alternative : Frag->getTrees()) {
TreePatternNodePtr FragTree = Alternative->clone();
if (!PredFn.isAlwaysTrue())
@@ -2637,6 +2686,8 @@ static bool OnlyOnRHSOfCommutative(TreePatternNode *N) {
return true;
if (N->isLeaf() && isa<IntInit>(N->getLeafValue()))
return true;
+ if (isImmAllOnesAllZerosMatch(N))
+ return true;
return false;
}
@@ -2802,7 +2853,8 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
// Apply the type cast.
- assert(New->getNumTypes() == 1 && "FIXME: Unhandled");
+ if (New->getNumTypes() != 1)
+ error("Type cast can only have one type!");
const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this);
@@ -3030,9 +3082,10 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
void TreePattern::print(raw_ostream &OS) const {
OS << getRecord()->getName();
if (!Args.empty()) {
- OS << "(" << Args[0];
- for (unsigned i = 1, e = Args.size(); i != e; ++i)
- OS << ", " << Args[i];
+ OS << "(";
+ ListSeparator LS;
+ for (const std::string &Arg : Args)
+ OS << LS << Arg;
OS << ")";
}
OS << ": ";
@@ -3070,15 +3123,15 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R,
ParsePatternFragments(/*OutFrags*/true);
ParsePatterns();
+ // Generate variants. For example, commutative patterns can match
+ // multiple ways. Add them to PatternsToMatch as well.
+ GenerateVariants();
+
// Break patterns with parameterized types into a series of patterns,
// where each one has a fixed type and is predicated on the conditions
// of the associated HW mode.
ExpandHwModeBasedTypes();
- // Generate variants. For example, commutative patterns can match
- // multiple ways. Add them to PatternsToMatch as well.
- GenerateVariants();
-
// Infer instruction flags. For example, we can detect loads,
// stores, and side effects in many cases by examining an
// instruction's pattern.
@@ -3201,7 +3254,7 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
// it.
Record *Transform = Frag->getValueAsDef("OperandTransform");
if (!getSDNodeTransform(Transform).second.empty()) // not noop xform?
- for (auto T : P->getTrees())
+ for (const auto &T : P->getTrees())
T->setTransformFn(Transform);
}
@@ -3470,6 +3523,9 @@ private:
if (N->getNumChildren() != 1 || !N->getChild(0)->isLeaf())
return false;
+ if (N->getOperator()->isSubClassOf("ComplexPattern"))
+ return false;
+
const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator());
if (OpInfo.getNumResults() != 1 || OpInfo.getNumOperands() != 1)
return false;
@@ -3671,9 +3727,9 @@ void CodeGenDAGPatterns::parseInstructionPattern(
TreePatternNodePtr Pat = I.getTree(j);
if (Pat->getNumTypes() != 0) {
raw_svector_ostream OS(TypesString);
+ ListSeparator LS;
for (unsigned k = 0, ke = Pat->getNumTypes(); k != ke; ++k) {
- if (k > 0)
- OS << ", ";
+ OS << LS;
Pat->getExtType(k).writeToStream(OS);
}
I.error("Top-level forms in instruction pattern should have"
@@ -3904,20 +3960,6 @@ static void FindNames(TreePatternNode *P,
}
}
-std::vector<Predicate> CodeGenDAGPatterns::makePredList(ListInit *L) {
- std::vector<Predicate> Preds;
- for (Init *I : L->getValues()) {
- if (DefInit *Pred = dyn_cast<DefInit>(I))
- Preds.push_back(Pred->getDef());
- else
- llvm_unreachable("Non-def on the list");
- }
-
- // Sort so that different orders get canonicalized to the same string.
- llvm::sort(Preds);
- return Preds;
-}
-
void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern,
PatternToMatch &&PTM) {
// Do some sanity checking on the pattern we're about to match.
@@ -3958,7 +4000,7 @@ void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern,
SrcNames[Entry.first].second == 1)
Pattern->error("Pattern has dead named input: $" + Entry.first);
- PatternsToMatch.push_back(PTM);
+ PatternsToMatch.push_back(std::move(PTM));
}
void CodeGenDAGPatterns::InferInstructionFlags() {
@@ -4030,8 +4072,7 @@ void CodeGenDAGPatterns::InferInstructionFlags() {
/// Verify instruction flags against pattern node properties.
void CodeGenDAGPatterns::VerifyInstructionFlags() {
unsigned Errors = 0;
- for (ptm_iterator I = ptm_begin(), E = ptm_end(); I != E; ++I) {
- const PatternToMatch &PTM = *I;
+ for (const PatternToMatch &PTM : ptms()) {
SmallVector<Record*, 8> Instrs;
getInstructionsInTree(PTM.getDstPattern(), Instrs);
if (Instrs.empty())
@@ -4172,7 +4213,7 @@ void CodeGenDAGPatterns::ParseOnePattern(Record *TheDef,
// resolve cases where the input type is known to be a pointer type (which
// is considered resolved), but the result knows it needs to be 32- or
// 64-bits. Infer the other way for good measure.
- for (auto T : Pattern.getTrees())
+ for (const auto &T : Pattern.getTrees())
for (unsigned i = 0, e = std::min(Result.getOnlyTree()->getNumTypes(),
T->getNumTypes());
i != e; ++i) {
@@ -4226,11 +4267,10 @@ void CodeGenDAGPatterns::ParseOnePattern(Record *TheDef,
// will lead to a contradiction, which is not an error however, but
// a sign that this pattern will simply never match.
if (Temp.getOnlyTree()->hasPossibleType())
- for (auto T : Pattern.getTrees())
+ for (const auto &T : Pattern.getTrees())
if (T->hasPossibleType())
AddPatternToMatch(&Pattern,
- PatternToMatch(TheDef, makePredList(Preds),
- T, Temp.getOnlyTree(),
+ PatternToMatch(TheDef, Preds, T, Temp.getOnlyTree(),
InstImpResults, Complexity,
TheDef->getID()));
}
@@ -4281,32 +4321,29 @@ static void collectModes(std::set<unsigned> &Modes, const TreePatternNode *N) {
void CodeGenDAGPatterns::ExpandHwModeBasedTypes() {
const CodeGenHwModes &CGH = getTargetInfo().getHwModes();
- std::map<unsigned,std::vector<Predicate>> ModeChecks;
- std::vector<PatternToMatch> Copy = PatternsToMatch;
- PatternsToMatch.clear();
+ std::vector<PatternToMatch> Copy;
+ PatternsToMatch.swap(Copy);
- auto AppendPattern = [this, &ModeChecks](PatternToMatch &P, unsigned Mode) {
- TreePatternNodePtr NewSrc = P.SrcPattern->clone();
- TreePatternNodePtr NewDst = P.DstPattern->clone();
+ auto AppendPattern = [this](PatternToMatch &P, unsigned Mode,
+ StringRef Check) {
+ TreePatternNodePtr NewSrc = P.getSrcPattern()->clone();
+ TreePatternNodePtr NewDst = P.getDstPattern()->clone();
if (!NewSrc->setDefaultMode(Mode) || !NewDst->setDefaultMode(Mode)) {
return;
}
- std::vector<Predicate> Preds = P.Predicates;
- const std::vector<Predicate> &MC = ModeChecks[Mode];
- llvm::append_range(Preds, MC);
- PatternsToMatch.emplace_back(P.getSrcRecord(), Preds, std::move(NewSrc),
- std::move(NewDst), P.getDstRegs(),
- P.getAddedComplexity(), Record::getNewUID(),
- Mode);
+ PatternsToMatch.emplace_back(P.getSrcRecord(), P.getPredicates(),
+ std::move(NewSrc), std::move(NewDst),
+ P.getDstRegs(), P.getAddedComplexity(),
+ Record::getNewUID(), Mode, Check);
};
for (PatternToMatch &P : Copy) {
TreePatternNodePtr SrcP = nullptr, DstP = nullptr;
- if (P.SrcPattern->hasProperTypeByHwMode())
- SrcP = P.SrcPattern;
- if (P.DstPattern->hasProperTypeByHwMode())
- DstP = P.DstPattern;
+ if (P.getSrcPattern()->hasProperTypeByHwMode())
+ SrcP = P.getSrcPatternShared();
+ if (P.getDstPattern()->hasProperTypeByHwMode())
+ DstP = P.getDstPatternShared();
if (!SrcP && !DstP) {
PatternsToMatch.push_back(P);
continue;
@@ -4329,31 +4366,27 @@ void CodeGenDAGPatterns::ExpandHwModeBasedTypes() {
// duplicated patterns with different predicate checks, construct the
// default check as a negation of all predicates that are actually present
// in the source/destination patterns.
- std::vector<Predicate> DefaultPred;
+ SmallString<128> DefaultCheck;
for (unsigned M : Modes) {
if (M == DefaultMode)
continue;
- if (ModeChecks.find(M) != ModeChecks.end())
- continue;
// Fill the map entry for this mode.
const HwMode &HM = CGH.getMode(M);
- ModeChecks[M].emplace_back(Predicate(HM.Features, true));
+ AppendPattern(P, M, "(MF->getSubtarget().checkFeatures(\"" + HM.Features + "\"))");
// Add negations of the HM's predicates to the default predicate.
- DefaultPred.emplace_back(Predicate(HM.Features, false));
- }
-
- for (unsigned M : Modes) {
- if (M == DefaultMode)
- continue;
- AppendPattern(P, M);
+ if (!DefaultCheck.empty())
+ DefaultCheck += " && ";
+ DefaultCheck += "(!(MF->getSubtarget().checkFeatures(\"";
+ DefaultCheck += HM.Features;
+ DefaultCheck += "\")))";
}
bool HasDefault = Modes.count(DefaultMode);
if (HasDefault)
- AppendPattern(P, DefaultMode);
+ AppendPattern(P, DefaultMode, DefaultCheck);
}
}
@@ -4635,17 +4668,7 @@ void CodeGenDAGPatterns::GenerateVariants() {
// intentionally do not reconsider these. Any variants of added patterns have
// already been added.
//
- const unsigned NumOriginalPatterns = PatternsToMatch.size();
- BitVector MatchedPatterns(NumOriginalPatterns);
- std::vector<BitVector> MatchedPredicates(NumOriginalPatterns,
- BitVector(NumOriginalPatterns));
-
- typedef std::pair<MultipleUseVarSet, std::vector<TreePatternNodePtr>>
- DepsAndVariants;
- std::map<unsigned, DepsAndVariants> PatternsWithVariants;
-
- // Collect patterns with more than one variant.
- for (unsigned i = 0; i != NumOriginalPatterns; ++i) {
+ for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
MultipleUseVarSet DepVars;
std::vector<TreePatternNodePtr> Variants;
FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars);
@@ -4655,6 +4678,9 @@ void CodeGenDAGPatterns::GenerateVariants() {
GenerateVariantsOf(PatternsToMatch[i].getSrcPatternShared(), Variants,
*this, DepVars);
+ assert(PatternsToMatch[i].getHwModeFeatures().empty() &&
+ "HwModes should not have been expanded yet!");
+
assert(!Variants.empty() && "Must create at least original variant!");
if (Variants.size() == 1) // No additional variants for this pattern.
continue;
@@ -4662,40 +4688,8 @@ void CodeGenDAGPatterns::GenerateVariants() {
LLVM_DEBUG(errs() << "FOUND VARIANTS OF: ";
PatternsToMatch[i].getSrcPattern()->dump(); errs() << "\n");
- PatternsWithVariants[i] = std::make_pair(DepVars, Variants);
-
- // Cache matching predicates.
- if (MatchedPatterns[i])
- continue;
-
- const std::vector<Predicate> &Predicates =
- PatternsToMatch[i].getPredicates();
-
- BitVector &Matches = MatchedPredicates[i];
- MatchedPatterns.set(i);
- Matches.set(i);
-
- // Don't test patterns that have already been cached - it won't match.
- for (unsigned p = 0; p != NumOriginalPatterns; ++p)
- if (!MatchedPatterns[p])
- Matches[p] = (Predicates == PatternsToMatch[p].getPredicates());
-
- // Copy this to all the matching patterns.
- for (int p = Matches.find_first(); p != -1; p = Matches.find_next(p))
- if (p != (int)i) {
- MatchedPatterns.set(p);
- MatchedPredicates[p] = Matches;
- }
- }
-
- for (auto it : PatternsWithVariants) {
- unsigned i = it.first;
- const MultipleUseVarSet &DepVars = it.second.first;
- const std::vector<TreePatternNodePtr> &Variants = it.second.second;
-
for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
TreePatternNodePtr Variant = Variants[v];
- BitVector &Matches = MatchedPredicates[i];
LLVM_DEBUG(errs() << " VAR#" << v << ": "; Variant->dump();
errs() << "\n");
@@ -4704,7 +4698,8 @@ void CodeGenDAGPatterns::GenerateVariants() {
bool AlreadyExists = false;
for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
// Skip if the top level predicates do not match.
- if (!Matches[p])
+ if ((i != p) && (PatternsToMatch[i].getPredicates() !=
+ PatternsToMatch[p].getPredicates()))
continue;
// Check to see if this variant already exists.
if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(),
@@ -4718,16 +4713,13 @@ void CodeGenDAGPatterns::GenerateVariants() {
if (AlreadyExists) continue;
// Otherwise, add it to the list of patterns we have.
- PatternsToMatch.push_back(PatternToMatch(
+ PatternsToMatch.emplace_back(
PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(),
Variant, PatternsToMatch[i].getDstPatternShared(),
PatternsToMatch[i].getDstRegs(),
- PatternsToMatch[i].getAddedComplexity(), Record::getNewUID()));
- MatchedPredicates.push_back(Matches);
-
- // Add a new match the same as this pattern.
- for (auto &P : MatchedPredicates)
- P.push_back(P[i]);
+ PatternsToMatch[i].getAddedComplexity(), Record::getNewUID(),
+ PatternsToMatch[i].getForceMode(),
+ PatternsToMatch[i].getHwModeFeatures());
}
LLVM_DEBUG(errs() << "\n");
diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.h b/llvm/utils/TableGen/CodeGenDAGPatterns.h
index bc939fe9acc1..a69f1e2e3030 100644
--- a/llvm/utils/TableGen/CodeGenDAGPatterns.h
+++ b/llvm/utils/TableGen/CodeGenDAGPatterns.h
@@ -200,9 +200,7 @@ struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> {
TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList);
SetType &getOrCreate(unsigned Mode) {
- if (hasMode(Mode))
- return get(Mode);
- return Map.insert({Mode,SetType()}).first->second;
+ return Map[Mode];
}
bool isValueTypeByHwMode(bool AllowEmpty) const;
@@ -1049,89 +1047,43 @@ public:
TreePatternNodePtr getResultPattern() const { return ResultPattern; }
};
-/// This class represents a condition that has to be satisfied for a pattern
-/// to be tried. It is a generalization of a class "Pattern" from Target.td:
-/// in addition to the Target.td's predicates, this class can also represent
-/// conditions associated with HW modes. Both types will eventually become
-/// strings containing C++ code to be executed, the difference is in how
-/// these strings are generated.
-class Predicate {
-public:
- Predicate(Record *R, bool C = true) : Def(R), IfCond(C), IsHwMode(false) {
- assert(R->isSubClassOf("Predicate") &&
- "Predicate objects should only be created for records derived"
- "from Predicate class");
- }
- Predicate(StringRef FS, bool C = true) : Def(nullptr), Features(FS.str()),
- IfCond(C), IsHwMode(true) {}
-
- /// Return a string which contains the C++ condition code that will serve
- /// as a predicate during instruction selection.
- std::string getCondString() const {
- // The string will excute in a subclass of SelectionDAGISel.
- // Cast to std::string explicitly to avoid ambiguity with StringRef.
- std::string C = IsHwMode
- ? std::string("MF->getSubtarget().checkFeatures(\"" +
- Features + "\")")
- : std::string(Def->getValueAsString("CondString"));
- if (C.empty())
- return "";
- return IfCond ? C : "!("+C+')';
- }
-
- bool operator==(const Predicate &P) const {
- return IfCond == P.IfCond && IsHwMode == P.IsHwMode && Def == P.Def;
- }
- bool operator<(const Predicate &P) const {
- if (IsHwMode != P.IsHwMode)
- return IsHwMode < P.IsHwMode;
- assert(!Def == !P.Def && "Inconsistency between Def and IsHwMode");
- if (IfCond != P.IfCond)
- return IfCond < P.IfCond;
- if (Def)
- return LessRecord()(Def, P.Def);
- return Features < P.Features;
- }
- Record *Def; ///< Predicate definition from .td file, null for
- ///< HW modes.
- std::string Features; ///< Feature string for HW mode.
- bool IfCond; ///< The boolean value that the condition has to
- ///< evaluate to for this predicate to be true.
- bool IsHwMode; ///< Does this predicate correspond to a HW mode?
-};
-
/// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns
/// processed to produce isel.
class PatternToMatch {
-public:
- PatternToMatch(Record *srcrecord, std::vector<Predicate> preds,
- TreePatternNodePtr src, TreePatternNodePtr dst,
- std::vector<Record *> dstregs, int complexity,
- unsigned uid, unsigned setmode = 0)
- : SrcRecord(srcrecord), SrcPattern(src), DstPattern(dst),
- Predicates(std::move(preds)), Dstregs(std::move(dstregs)),
- AddedComplexity(complexity), ID(uid), ForceMode(setmode) {}
-
Record *SrcRecord; // Originating Record for the pattern.
+ ListInit *Predicates; // Top level predicate conditions to match.
TreePatternNodePtr SrcPattern; // Source pattern to match.
TreePatternNodePtr DstPattern; // Resulting pattern.
- std::vector<Predicate> Predicates; // Top level predicate conditions
- // to match.
std::vector<Record*> Dstregs; // Physical register defs being matched.
+ std::string HwModeFeatures;
int AddedComplexity; // Add to matching pattern complexity.
unsigned ID; // Unique ID for the record.
unsigned ForceMode; // Force this mode in type inference when set.
+public:
+ PatternToMatch(Record *srcrecord, ListInit *preds, TreePatternNodePtr src,
+ TreePatternNodePtr dst, std::vector<Record *> dstregs,
+ int complexity, unsigned uid, unsigned setmode = 0,
+ const Twine &hwmodefeatures = "")
+ : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src),
+ DstPattern(dst), Dstregs(std::move(dstregs)),
+ HwModeFeatures(hwmodefeatures.str()), AddedComplexity(complexity),
+ ID(uid), ForceMode(setmode) {}
+
Record *getSrcRecord() const { return SrcRecord; }
+ ListInit *getPredicates() const { return Predicates; }
TreePatternNode *getSrcPattern() const { return SrcPattern.get(); }
TreePatternNodePtr getSrcPatternShared() const { return SrcPattern; }
TreePatternNode *getDstPattern() const { return DstPattern.get(); }
TreePatternNodePtr getDstPatternShared() const { return DstPattern; }
const std::vector<Record*> &getDstRegs() const { return Dstregs; }
+ StringRef getHwModeFeatures() const { return HwModeFeatures; }
int getAddedComplexity() const { return AddedComplexity; }
- const std::vector<Predicate> &getPredicates() const { return Predicates; }
+ unsigned getID() const { return ID; }
+ unsigned getForceMode() const { return ForceMode; }
std::string getPredicateCheck() const;
+ void getPredicateRecords(SmallVectorImpl<Record *> &PredicateRecs) const;
/// Compute the complexity metric for the input pattern. This roughly
/// corresponds to the number of nodes that are covered.
@@ -1289,8 +1241,6 @@ private:
void GenerateVariants();
void VerifyInstructionFlags();
- std::vector<Predicate> makePredList(ListInit *L);
-
void ParseOnePattern(Record *TheDef,
TreePattern &Pattern, TreePattern &Result,
const std::vector<Record *> &InstImpResults);
diff --git a/llvm/utils/TableGen/CodeGenInstruction.cpp b/llvm/utils/TableGen/CodeGenInstruction.cpp
index 960fe08677f7..3933ce6e1106 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -177,17 +177,17 @@ bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const {
}
std::pair<unsigned,unsigned>
-CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
+CGIOperandList::ParseOperandName(StringRef Op, bool AllowWholeOp) {
if (Op.empty() || Op[0] != '$')
PrintFatalError(TheDef->getLoc(),
TheDef->getName() + ": Illegal operand name: '" + Op + "'");
- std::string OpName = Op.substr(1);
- std::string SubOpName;
+ StringRef OpName = Op.substr(1);
+ StringRef SubOpName;
// Check to see if this is $foo.bar.
- std::string::size_type DotIdx = OpName.find_first_of('.');
- if (DotIdx != std::string::npos) {
+ StringRef::size_type DotIdx = OpName.find_first_of('.');
+ if (DotIdx != StringRef::npos) {
SubOpName = OpName.substr(DotIdx+1);
if (SubOpName.empty())
PrintFatalError(TheDef->getLoc(),
@@ -231,16 +231,16 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
return std::make_pair(0U, 0U);
}
-static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops,
+static void ParseConstraint(StringRef CStr, CGIOperandList &Ops,
Record *Rec) {
// EARLY_CLOBBER: @early $reg
- std::string::size_type wpos = CStr.find_first_of(" \t");
- std::string::size_type start = CStr.find_first_not_of(" \t");
- std::string Tok = CStr.substr(start, wpos - start);
+ StringRef::size_type wpos = CStr.find_first_of(" \t");
+ StringRef::size_type start = CStr.find_first_not_of(" \t");
+ StringRef Tok = CStr.substr(start, wpos - start);
if (Tok == "@earlyclobber") {
- std::string Name = CStr.substr(wpos+1);
+ StringRef Name = CStr.substr(wpos+1);
wpos = Name.find_first_not_of(" \t");
- if (wpos == std::string::npos)
+ if (wpos == StringRef::npos)
PrintFatalError(
Rec->getLoc(), "Illegal format for @earlyclobber constraint in '" +
Rec->getName() + "': '" + CStr + "'");
@@ -258,8 +258,8 @@ static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops,
}
// Only other constraint is "TIED_TO" for now.
- std::string::size_type pos = CStr.find_first_of('=');
- if (pos == std::string::npos)
+ StringRef::size_type pos = CStr.find_first_of('=');
+ if (pos == StringRef::npos)
PrintFatalError(
Rec->getLoc(), "Unrecognized constraint '" + CStr +
"' in '" + Rec->getName() + "'");
@@ -267,20 +267,19 @@ static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops,
// TIED_TO: $src1 = $dst
wpos = CStr.find_first_of(" \t", start);
- if (wpos == std::string::npos || wpos > pos)
+ if (wpos == StringRef::npos || wpos > pos)
PrintFatalError(
Rec->getLoc(), "Illegal format for tied-to constraint in '" +
Rec->getName() + "': '" + CStr + "'");
- std::string LHSOpName =
- std::string(StringRef(CStr).substr(start, wpos - start));
+ StringRef LHSOpName = CStr.substr(start, wpos - start);
std::pair<unsigned,unsigned> LHSOp = Ops.ParseOperandName(LHSOpName, false);
wpos = CStr.find_first_not_of(" \t", pos + 1);
- if (wpos == std::string::npos)
+ if (wpos == StringRef::npos)
PrintFatalError(
Rec->getLoc(), "Illegal format for tied-to constraint: '" + CStr + "'");
- std::string RHSOpName = std::string(StringRef(CStr).substr(wpos));
+ StringRef RHSOpName = CStr.substr(wpos);
std::pair<unsigned,unsigned> RHSOp = Ops.ParseOperandName(RHSOpName, false);
// Sort the operands into order, which should put the output one
@@ -325,29 +324,27 @@ static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops,
Ops[SrcOp.first].Constraints[SrcOp.second] = NewConstraint;
}
-static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops,
- Record *Rec) {
+static void ParseConstraints(StringRef CStr, CGIOperandList &Ops, Record *Rec) {
if (CStr.empty()) return;
- const std::string delims(",");
- std::string::size_type bidx, eidx;
+ StringRef delims(",");
+ StringRef::size_type bidx, eidx;
bidx = CStr.find_first_not_of(delims);
- while (bidx != std::string::npos) {
+ while (bidx != StringRef::npos) {
eidx = CStr.find_first_of(delims, bidx);
- if (eidx == std::string::npos)
- eidx = CStr.length();
+ if (eidx == StringRef::npos)
+ eidx = CStr.size();
ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops, Rec);
bidx = CStr.find_first_not_of(delims, eidx);
}
}
-void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) {
+void CGIOperandList::ProcessDisableEncoding(StringRef DisableEncoding) {
while (1) {
- std::pair<StringRef, StringRef> P = getToken(DisableEncoding, " ,\t");
- std::string OpName = std::string(P.first);
- DisableEncoding = std::string(P.second);
+ StringRef OpName;
+ std::tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t");
if (OpName.empty()) break;
// Figure out which operand this is.
@@ -427,12 +424,11 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
hasChain_Inferred = false;
// Parse Constraints.
- ParseConstraints(std::string(R->getValueAsString("Constraints")), Operands,
- R);
+ ParseConstraints(R->getValueAsString("Constraints"), Operands, R);
// Parse the DisableEncoding field.
Operands.ProcessDisableEncoding(
- std::string(R->getValueAsString("DisableEncoding")));
+ R->getValueAsString("DisableEncoding"));
// First check for a ComplexDeprecationPredicate.
if (R->getValue("ComplexDeprecationPredicate")) {
diff --git a/llvm/utils/TableGen/CodeGenInstruction.h b/llvm/utils/TableGen/CodeGenInstruction.h
index af851a11676b..e35d2191ea45 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.h
+++ b/llvm/utils/TableGen/CodeGenInstruction.h
@@ -182,7 +182,7 @@ template <typename T> class ArrayRef;
/// where $foo is a whole operand and $foo.bar refers to a suboperand.
/// This aborts if the name is invalid. If AllowWholeOp is true, references
/// to operands with suboperands are allowed, otherwise not.
- std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op,
+ std::pair<unsigned,unsigned> ParseOperandName(StringRef Op,
bool AllowWholeOp = true);
/// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
@@ -211,7 +211,7 @@ template <typename T> class ArrayRef;
return false;
}
- void ProcessDisableEncoding(std::string Value);
+ void ProcessDisableEncoding(StringRef Value);
};
diff --git a/llvm/utils/TableGen/CodeGenIntrinsics.h b/llvm/utils/TableGen/CodeGenIntrinsics.h
index c469f662a42d..dbfad3bf6b17 100644
--- a/llvm/utils/TableGen/CodeGenIntrinsics.h
+++ b/llvm/utils/TableGen/CodeGenIntrinsics.h
@@ -120,6 +120,9 @@ struct CodeGenIntrinsic {
/// True if the intrinsic is marked as noduplicate.
bool isNoDuplicate;
+ /// True if the intrinsic is marked as nomerge.
+ bool isNoMerge;
+
/// True if the intrinsic is no-return.
bool isNoReturn;
diff --git a/llvm/utils/TableGen/CodeGenMapTable.cpp b/llvm/utils/TableGen/CodeGenMapTable.cpp
index 289a20a96f02..6f718acbac3e 100644
--- a/llvm/utils/TableGen/CodeGenMapTable.cpp
+++ b/llvm/utils/TableGen/CodeGenMapTable.cpp
@@ -318,11 +318,10 @@ Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
ListInit *ColFields = InstrMapDesc.getColFields();
Record *MatchInstr = nullptr;
- for (unsigned i = 0, e = RelatedInstrVec.size(); i < e; i++) {
+ for (llvm::Record *CurInstr : RelatedInstrVec) {
bool MatchFound = true;
- Record *CurInstr = RelatedInstrVec[i];
for (unsigned j = 0, endCF = ColFields->size();
- (j < endCF) && MatchFound; j++) {
+ (j < endCF) && MatchFound; j++) {
Init *ColFieldJ = ColFields->getElement(j);
Init *CurInstrInit = CurInstr->getValue(ColFieldJ)->getValue();
std::string CurInstrVal = CurInstrInit->getAsUnquotedString();
@@ -342,8 +341,9 @@ Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
}
PrintFatalError("Multiple matches found for `" + KeyInstr->getName() +
- "', for the relation `" + InstrMapDesc.getName() + "', row fields [" +
- KeyValueStr + "], column `" + CurValueCol->getAsString() + "'");
+ "', for the relation `" + InstrMapDesc.getName() +
+ "', row fields [" + KeyValueStr + "], column `" +
+ CurValueCol->getAsString() + "'");
}
MatchInstr = CurInstr;
}
diff --git a/llvm/utils/TableGen/CodeGenRegisters.cpp b/llvm/utils/TableGen/CodeGenRegisters.cpp
index f9a7ba6bba80..930b7742103e 100644
--- a/llvm/utils/TableGen/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/CodeGenRegisters.cpp
@@ -154,14 +154,11 @@ void CodeGenSubRegIndex::computeConcatTransitiveClosure() {
//===----------------------------------------------------------------------===//
CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum)
- : TheDef(R),
- EnumValue(Enum),
- CostPerUse(R->getValueAsInt("CostPerUse")),
- CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
- HasDisjunctSubRegs(false),
- SubRegsComplete(false),
- SuperRegsComplete(false),
- TopoSig(~0u) {
+ : TheDef(R), EnumValue(Enum),
+ CostPerUse(R->getValueAsListOfInts("CostPerUse")),
+ CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
+ HasDisjunctSubRegs(false), SubRegsComplete(false),
+ SuperRegsComplete(false), TopoSig(~0u) {
Artificial = R->getValueAsBit("isArtificial");
}
@@ -314,18 +311,17 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
// Look at the possible compositions of Idx.
// They may not all be supported by SR.
- for (CodeGenSubRegIndex::CompMap::const_iterator I = Comps.begin(),
- E = Comps.end(); I != E; ++I) {
- SubRegMap::const_iterator SRI = Map.find(I->first);
+ for (auto Comp : Comps) {
+ SubRegMap::const_iterator SRI = Map.find(Comp.first);
if (SRI == Map.end())
continue; // Idx + I->first doesn't exist in SR.
// Add I->second as a name for the subreg SRI->second, assuming it is
// orphaned, and the name isn't already used for something else.
- if (SubRegs.count(I->second) || !Orphans.erase(SRI->second))
+ if (SubRegs.count(Comp.second) || !Orphans.erase(SRI->second))
continue;
// We found a new name for the orphaned sub-register.
- SubRegs.insert(std::make_pair(I->second, SRI->second));
- Indices.push_back(I->second);
+ SubRegs.insert(std::make_pair(Comp.second, SRI->second));
+ Indices.push_back(Comp.second);
}
}
@@ -531,13 +527,13 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
for (unsigned i = 0, e = NewSubRegs.size(); i != e; ++i) {
CodeGenSubRegIndex *NewIdx = NewSubRegs[i].first;
CodeGenRegister *NewSubReg = NewSubRegs[i].second;
- for (SubRegMap::const_iterator SI = NewSubReg->SubRegs.begin(),
- SE = NewSubReg->SubRegs.end(); SI != SE; ++SI) {
- CodeGenSubRegIndex *SubIdx = getSubRegIndex(SI->second);
+ for (auto SubReg : NewSubReg->SubRegs) {
+ CodeGenSubRegIndex *SubIdx = getSubRegIndex(SubReg.second);
if (!SubIdx)
PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " +
- SI->second->getName() + " in " + getName());
- NewIdx->addComposite(SI->first, SubIdx);
+ SubReg.second->getName() +
+ " in " + getName());
+ NewIdx->addComposite(SubReg.first, SubIdx);
}
}
}
@@ -550,24 +546,23 @@ void CodeGenRegister::computeSuperRegs(CodeGenRegBank &RegBank) {
// Make sure all sub-registers have been visited first, so the super-reg
// lists will be topologically ordered.
- for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
- I != E; ++I)
- I->second->computeSuperRegs(RegBank);
+ for (auto SubReg : SubRegs)
+ SubReg.second->computeSuperRegs(RegBank);
// Now add this as a super-register on all sub-registers.
// Also compute the TopoSigId in post-order.
TopoSigId Id;
- for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
- I != E; ++I) {
+ for (auto SubReg : SubRegs) {
// Topological signature computed from SubIdx, TopoId(SubReg).
// Loops and idempotent indices have TopoSig = ~0u.
- Id.push_back(I->first->EnumValue);
- Id.push_back(I->second->TopoSig);
+ Id.push_back(SubReg.first->EnumValue);
+ Id.push_back(SubReg.second->TopoSig);
// Don't add duplicate entries.
- if (!I->second->SuperRegs.empty() && I->second->SuperRegs.back() == this)
+ if (!SubReg.second->SuperRegs.empty() &&
+ SubReg.second->SuperRegs.back() == this)
continue;
- I->second->SuperRegs.push_back(this);
+ SubReg.second->SuperRegs.push_back(this);
}
TopoSig = RegBank.getTopoSig(Id);
}
@@ -582,17 +577,15 @@ CodeGenRegister::addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet,
SR->addSubRegsPreOrder(OSet, RegBank);
}
// Add any secondary sub-registers that weren't part of the explicit tree.
- for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
- I != E; ++I)
- OSet.insert(I->second);
+ for (auto SubReg : SubRegs)
+ OSet.insert(SubReg.second);
}
// Get the sum of this register's unit weights.
unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const {
unsigned Weight = 0;
- for (RegUnitList::iterator I = RegUnits.begin(), E = RegUnits.end();
- I != E; ++I) {
- Weight += RegBank.getRegUnit(*I).Weight;
+ for (unsigned RegUnit : RegUnits) {
+ Weight += RegBank.getRegUnit(RegUnit).Weight;
}
return Weight;
}
@@ -646,16 +639,18 @@ struct TupleExpander : SetTheory::Expander {
std::string Name;
Record *Proto = Lists[0][n];
std::vector<Init*> Tuple;
- unsigned CostPerUse = 0;
for (unsigned i = 0; i != Dim; ++i) {
Record *Reg = Lists[i][n];
if (i) Name += '_';
Name += Reg->getName();
Tuple.push_back(DefInit::get(Reg));
- CostPerUse = std::max(CostPerUse,
- unsigned(Reg->getValueAsInt("CostPerUse")));
}
+ // Take the cost list of the first register in the tuple.
+ ListInit *CostList = Proto->getValueAsListInit("CostPerUse");
+ SmallVector<Init *, 2> CostPerUse;
+ CostPerUse.insert(CostPerUse.end(), CostList->begin(), CostList->end());
+
StringInit *AsmName = StringInit::get("");
if (!RegNames.empty()) {
if (RegNames.size() <= n)
@@ -697,7 +692,7 @@ struct TupleExpander : SetTheory::Expander {
// CostPerUse is aggregated from all Tuple members.
if (Field == "CostPerUse")
- RV.setValue(IntInit::get(CostPerUse));
+ RV.setValue(ListInit::get(CostPerUse, CostList->getElementType()));
// Composite registers are always covered by sub-registers.
if (Field == "CoveredBySubRegs")
@@ -797,7 +792,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
RI.RegSize = RI.SpillSize = Size ? Size
: VTs[0].getSimple().getSizeInBits();
RI.SpillAlignment = R->getValueAsInt("Alignment");
- RSI.Map.insert({DefaultMode, RI});
+ RSI.insertRegSizeForMode(DefaultMode, RI);
}
CopyCost = R->getValueAsInt("CopyCost");
@@ -838,7 +833,10 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
Namespace = Super.Namespace;
VTs = Super.VTs;
CopyCost = Super.CopyCost;
- Allocatable = Super.Allocatable;
+ // Check for allocatable superclasses.
+ Allocatable = any_of(SuperClasses, [&](const CodeGenRegisterClass *S) {
+ return S->Allocatable;
+ });
AltOrderSelect = Super.AltOrderSelect;
AllocationPriority = Super.AllocationPriority;
GeneratePressureSet |= Super.GeneratePressureSet;
@@ -1396,19 +1394,17 @@ void CodeGenRegBank::computeComposites() {
TopoSigs.set(Reg1.getTopoSig());
const CodeGenRegister::SubRegMap &SRM1 = Reg1.getSubRegs();
- for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(),
- e1 = SRM1.end(); i1 != e1; ++i1) {
- CodeGenSubRegIndex *Idx1 = i1->first;
- CodeGenRegister *Reg2 = i1->second;
+ for (auto I1 : SRM1) {
+ CodeGenSubRegIndex *Idx1 = I1.first;
+ CodeGenRegister *Reg2 = I1.second;
// Ignore identity compositions.
if (&Reg1 == Reg2)
continue;
const CodeGenRegister::SubRegMap &SRM2 = Reg2->getSubRegs();
// Try composing Idx1 with another SubRegIndex.
- for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM2.begin(),
- e2 = SRM2.end(); i2 != e2; ++i2) {
- CodeGenSubRegIndex *Idx2 = i2->first;
- CodeGenRegister *Reg3 = i2->second;
+ for (auto I2 : SRM2) {
+ CodeGenSubRegIndex *Idx2 = I2.first;
+ CodeGenRegister *Reg3 = I2.second;
// Ignore identity compositions.
if (Reg2 == Reg3)
continue;
@@ -1425,7 +1421,7 @@ void CodeGenRegBank::computeComposites() {
" and " + Idx2->getQualifiedName() +
" compose ambiguously as " + Prev->getQualifiedName() +
" or " + Idx3->getQualifiedName());
- }
+ }
}
}
}
@@ -1728,13 +1724,12 @@ static bool normalizeWeight(CodeGenRegister *Reg,
bool Changed = false;
const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs();
- for (CodeGenRegister::SubRegMap::const_iterator SRI = SRM.begin(),
- SRE = SRM.end(); SRI != SRE; ++SRI) {
- if (SRI->second == Reg)
+ for (auto SRI : SRM) {
+ if (SRI.second == Reg)
continue; // self-cycles happen
- Changed |= normalizeWeight(SRI->second, UberSets, RegSets,
- NormalRegs, NormalUnits, RegBank);
+ Changed |= normalizeWeight(SRI.second, UberSets, RegSets, NormalRegs,
+ NormalUnits, RegBank);
}
// Postorder register normalization.
@@ -2064,15 +2059,14 @@ void CodeGenRegBank::computeRegUnitLaneMasks() {
// Iterate through SubRegisters.
typedef CodeGenRegister::SubRegMap SubRegMap;
const SubRegMap &SubRegs = Register.getSubRegs();
- for (SubRegMap::const_iterator S = SubRegs.begin(),
- SE = SubRegs.end(); S != SE; ++S) {
- CodeGenRegister *SubReg = S->second;
+ for (auto S : SubRegs) {
+ CodeGenRegister *SubReg = S.second;
// Ignore non-leaf subregisters, their lane masks are fully covered by
// the leaf subregisters anyway.
if (!SubReg->getSubRegs().empty())
continue;
- CodeGenSubRegIndex *SubRegIndex = S->first;
- const CodeGenRegister *SubRegister = S->second;
+ CodeGenSubRegIndex *SubRegIndex = S.first;
+ const CodeGenRegister *SubRegister = S.second;
LaneBitmask LaneMask = SubRegIndex->LaneMask;
// Distribute LaneMask to Register Units touched.
for (unsigned SUI : SubRegister->getRegUnits()) {
@@ -2194,10 +2188,9 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
if (R->Artificial)
continue;
const CodeGenRegister::SubRegMap &SRM = R->getSubRegs();
- for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
- E = SRM.end(); I != E; ++I) {
- if (!I->first->Artificial)
- SRSets[I->first].push_back(R);
+ for (auto I : SRM) {
+ if (!I.first->Artificial)
+ SRSets[I.first].push_back(R);
}
}
@@ -2422,9 +2415,8 @@ BitVector CodeGenRegBank::computeCoveredRegisters(ArrayRef<Record*> Regs) {
// This new super-register is covered by its sub-registers.
bool AllSubsInSet = true;
const CodeGenRegister::SubRegMap &SRM = Super->getSubRegs();
- for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
- E = SRM.end(); I != E; ++I)
- if (!Set.count(I->second)) {
+ for (auto I : SRM)
+ if (!Set.count(I.second)) {
AllSubsInSet = false;
break;
}
diff --git a/llvm/utils/TableGen/CodeGenRegisters.h b/llvm/utils/TableGen/CodeGenRegisters.h
index 5228e6518fe5..6a0696011a40 100644
--- a/llvm/utils/TableGen/CodeGenRegisters.h
+++ b/llvm/utils/TableGen/CodeGenRegisters.h
@@ -151,7 +151,7 @@ namespace llvm {
struct CodeGenRegister {
Record *TheDef;
unsigned EnumValue;
- unsigned CostPerUse;
+ std::vector<int64_t> CostPerUse;
bool CoveredBySubRegs;
bool HasDisjunctSubRegs;
bool Artificial;
@@ -738,9 +738,8 @@ namespace llvm {
// Get the sum of unit weights.
unsigned getRegUnitSetWeight(const std::vector<unsigned> &Units) const {
unsigned Weight = 0;
- for (std::vector<unsigned>::const_iterator
- I = Units.begin(), E = Units.end(); I != E; ++I)
- Weight += getRegUnit(*I).Weight;
+ for (unsigned Unit : Units)
+ Weight += getRegUnit(Unit).Weight;
return Weight;
}
diff --git a/llvm/utils/TableGen/CodeGenSchedule.cpp b/llvm/utils/TableGen/CodeGenSchedule.cpp
index b20eb6eff422..ee52b2e7ab9f 100644
--- a/llvm/utils/TableGen/CodeGenSchedule.cpp
+++ b/llvm/utils/TableGen/CodeGenSchedule.cpp
@@ -708,10 +708,10 @@ void CodeGenSchedModels::collectSchedRW() {
/// Compute a SchedWrite name from a sequence of writes.
std::string CodeGenSchedModels::genRWName(ArrayRef<unsigned> Seq, bool IsRead) {
std::string Name("(");
- for (auto I = Seq.begin(), E = Seq.end(); I != E; ++I) {
- if (I != Seq.begin())
- Name += '_';
- Name += getSchedRW(*I, IsRead).Name;
+ ListSeparator LS("_");
+ for (unsigned I : Seq) {
+ Name += LS;
+ Name += getSchedRW(I, IsRead).Name;
}
Name += ')';
return Name;
@@ -921,11 +921,10 @@ void CodeGenSchedModels::collectSchedClasses() {
ProcIndices.push_back(0);
LLVM_DEBUG({
dbgs() << "SchedRW machine model for " << InstName;
- for (IdxIter WI = SC.Writes.begin(), WE = SC.Writes.end(); WI != WE;
- ++WI)
- dbgs() << " " << SchedWrites[*WI].Name;
- for (IdxIter RI = SC.Reads.begin(), RE = SC.Reads.end(); RI != RE; ++RI)
- dbgs() << " " << SchedReads[*RI].Name;
+ for (unsigned int Write : SC.Writes)
+ dbgs() << " " << SchedWrites[Write].Name;
+ for (unsigned int Read : SC.Reads)
+ dbgs() << " " << SchedReads[Read].Name;
dbgs() << '\n';
});
}
@@ -990,10 +989,10 @@ CodeGenSchedModels::createSchedClassName(Record *ItinClassDef,
std::string CodeGenSchedModels::createSchedClassName(const RecVec &InstDefs) {
std::string Name;
- for (RecIter I = InstDefs.begin(), E = InstDefs.end(); I != E; ++I) {
- if (I != InstDefs.begin())
- Name += '_';
- Name += (*I)->getName();
+ ListSeparator LS("_");
+ for (const Record *InstDef : InstDefs) {
+ Name += LS;
+ Name += InstDef->getName();
}
return Name;
}
@@ -1557,12 +1556,11 @@ pushVariant(const TransVariant &VInfo, bool IsRead) {
// sequence (add to the current operand's sequence).
SmallVectorImpl<unsigned> &Seq = RWSequences.back();
IdxVec ExpandedRWs;
- for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end();
- RWI != RWE; ++RWI) {
+ for (unsigned int SelectedRW : SelectedRWs) {
if (IsRead)
- ExpandedRWs.push_back(*RWI);
+ ExpandedRWs.push_back(SelectedRW);
else
- SchedModels.expandRWSequence(*RWI, ExpandedRWs, IsRead);
+ SchedModels.expandRWSequence(SelectedRW, ExpandedRWs, IsRead);
}
llvm::append_range(Seq, ExpandedRWs);
}
@@ -1576,9 +1574,8 @@ bool PredTransitions::substituteVariantOperand(
const SmallVectorImpl<unsigned> &RWSeq, bool IsRead, unsigned StartIdx) {
bool Subst = false;
// Visit each original RW within the current sequence.
- for (SmallVectorImpl<unsigned>::const_iterator
- RWI = RWSeq.begin(), RWE = RWSeq.end(); RWI != RWE; ++RWI) {
- const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(*RWI, IsRead);
+ for (unsigned int RWI : RWSeq) {
+ const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(RWI, IsRead);
// Push this RW on all partial PredTransitions or distribute variants.
// New PredTransitions may be pushed within this loop which should not be
// revisited (TransEnd must be loop invariant).
@@ -1593,9 +1590,9 @@ bool PredTransitions::substituteVariantOperand(
pushVariant(IV, IsRead);
if (IntersectingVariants.empty()) {
if (IsRead)
- TransVec[TransIdx].ReadSequences.back().push_back(*RWI);
+ TransVec[TransIdx].ReadSequences.back().push_back(RWI);
else
- TransVec[TransIdx].WriteSequences.back().push_back(*RWI);
+ TransVec[TransIdx].WriteSequences.back().push_back(RWI);
continue;
} else {
Subst = true;
@@ -1620,26 +1617,23 @@ bool PredTransitions::substituteVariants(const PredTransition &Trans) {
TransVec.emplace_back(Trans.PredTerm, Trans.ProcIndex);
// Visit each original write sequence.
- for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
- WSI = Trans.WriteSequences.begin(), WSE = Trans.WriteSequences.end();
- WSI != WSE; ++WSI) {
+ for (const auto &WriteSequence : Trans.WriteSequences) {
// Push a new (empty) write sequence onto all partial Transitions.
for (std::vector<PredTransition>::iterator I =
TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) {
I->WriteSequences.emplace_back();
}
- Subst |= substituteVariantOperand(*WSI, /*IsRead=*/false, StartIdx);
+ Subst |=
+ substituteVariantOperand(WriteSequence, /*IsRead=*/false, StartIdx);
}
// Visit each original read sequence.
- for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
- RSI = Trans.ReadSequences.begin(), RSE = Trans.ReadSequences.end();
- RSI != RSE; ++RSI) {
+ for (const auto &ReadSequence : Trans.ReadSequences) {
// Push a new (empty) read sequence onto all partial Transitions.
for (std::vector<PredTransition>::iterator I =
TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) {
I->ReadSequences.emplace_back();
}
- Subst |= substituteVariantOperand(*RSI, /*IsRead=*/true, StartIdx);
+ Subst |= substituteVariantOperand(ReadSequence, /*IsRead=*/true, StartIdx);
}
return Subst;
}
@@ -1676,33 +1670,32 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
CodeGenSchedModels &SchedModels) {
// For each PredTransition, create a new CodeGenSchedTransition, which usually
// requires creating a new SchedClass.
- for (ArrayRef<PredTransition>::iterator
- I = LastTransitions.begin(), E = LastTransitions.end(); I != E; ++I) {
+ for (const auto &LastTransition : LastTransitions) {
// Variant expansion (substituteVariants) may create unconditional
// transitions. We don't need to build sched classes for them.
- if (I->PredTerm.empty())
+ if (LastTransition.PredTerm.empty())
continue;
IdxVec OperWritesVariant, OperReadsVariant;
- addSequences(SchedModels, I->WriteSequences, OperWritesVariant, false);
- addSequences(SchedModels, I->ReadSequences, OperReadsVariant, true);
+ addSequences(SchedModels, LastTransition.WriteSequences, OperWritesVariant,
+ false);
+ addSequences(SchedModels, LastTransition.ReadSequences, OperReadsVariant,
+ true);
CodeGenSchedTransition SCTrans;
// Transition should not contain processor indices already assigned to
// InstRWs in this scheduling class.
const CodeGenSchedClass &FromSC = SchedModels.getSchedClass(FromClassIdx);
- if (FromSC.InstRWProcIndices.count(I->ProcIndex))
+ if (FromSC.InstRWProcIndices.count(LastTransition.ProcIndex))
continue;
- SCTrans.ProcIndex = I->ProcIndex;
+ SCTrans.ProcIndex = LastTransition.ProcIndex;
SCTrans.ToClassIdx =
SchedModels.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant,
- OperReadsVariant, I->ProcIndex);
+ OperReadsVariant, LastTransition.ProcIndex);
// The final PredTerm is unique set of predicates guarding the transition.
RecVec Preds;
- transform(I->PredTerm, std::back_inserter(Preds),
- [](const PredCheck &P) {
- return P.Predicate;
- });
+ transform(LastTransition.PredTerm, std::back_inserter(Preds),
+ [](const PredCheck &P) { return P.Predicate; });
Preds.erase(std::unique(Preds.begin(), Preds.end()), Preds.end());
dumpTransition(SchedModels, FromSC, SCTrans, Preds);
SCTrans.PredTerm = std::move(Preds);
@@ -1791,11 +1784,10 @@ void CodeGenSchedModels::inferFromRW(ArrayRef<unsigned> OperWrites,
// Check if any processor resource group contains all resource records in
// SubUnits.
bool CodeGenSchedModels::hasSuperGroup(RecVec &SubUnits, CodeGenProcModel &PM) {
- for (unsigned i = 0, e = PM.ProcResourceDefs.size(); i < e; ++i) {
- if (!PM.ProcResourceDefs[i]->isSubClassOf("ProcResGroup"))
+ for (Record *ProcResourceDef : PM.ProcResourceDefs) {
+ if (!ProcResourceDef->isSubClassOf("ProcResGroup"))
continue;
- RecVec SuperUnits =
- PM.ProcResourceDefs[i]->getValueAsListOfDefs("Resources");
+ RecVec SuperUnits = ProcResourceDef->getValueAsListOfDefs("Resources");
RecIter RI = SubUnits.begin(), RE = SubUnits.end();
for ( ; RI != RE; ++RI) {
if (!is_contained(SuperUnits, *RI)) {
@@ -1951,27 +1943,26 @@ void CodeGenSchedModels::collectProcResources() {
llvm::sort(PM.ReadAdvanceDefs, LessRecord());
llvm::sort(PM.ProcResourceDefs, LessRecord());
LLVM_DEBUG(
- PM.dump();
- dbgs() << "WriteResDefs: "; for (RecIter RI = PM.WriteResDefs.begin(),
- RE = PM.WriteResDefs.end();
- RI != RE; ++RI) {
- if ((*RI)->isSubClassOf("WriteRes"))
- dbgs() << (*RI)->getValueAsDef("WriteType")->getName() << " ";
+ PM.dump(); dbgs() << "WriteResDefs: "; for (auto WriteResDef
+ : PM.WriteResDefs) {
+ if (WriteResDef->isSubClassOf("WriteRes"))
+ dbgs() << WriteResDef->getValueAsDef("WriteType")->getName() << " ";
else
- dbgs() << (*RI)->getName() << " ";
+ dbgs() << WriteResDef->getName() << " ";
} dbgs() << "\nReadAdvanceDefs: ";
- for (RecIter RI = PM.ReadAdvanceDefs.begin(),
- RE = PM.ReadAdvanceDefs.end();
- RI != RE; ++RI) {
- if ((*RI)->isSubClassOf("ReadAdvance"))
- dbgs() << (*RI)->getValueAsDef("ReadType")->getName() << " ";
+ for (Record *ReadAdvanceDef
+ : PM.ReadAdvanceDefs) {
+ if (ReadAdvanceDef->isSubClassOf("ReadAdvance"))
+ dbgs() << ReadAdvanceDef->getValueAsDef("ReadType")->getName()
+ << " ";
else
- dbgs() << (*RI)->getName() << " ";
+ dbgs() << ReadAdvanceDef->getName() << " ";
} dbgs()
<< "\nProcResourceDefs: ";
- for (RecIter RI = PM.ProcResourceDefs.begin(),
- RE = PM.ProcResourceDefs.end();
- RI != RE; ++RI) { dbgs() << (*RI)->getName() << " "; } dbgs()
+ for (Record *ProcResourceDef
+ : PM.ProcResourceDefs) {
+ dbgs() << ProcResourceDef->getName() << " ";
+ } dbgs()
<< '\n');
verifyProcResourceGroups(PM);
}
@@ -2073,23 +2064,20 @@ void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead,
addReadAdvance(SchedRW.TheDef, Idx);
}
}
- for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
- AI != AE; ++AI) {
+ for (auto *Alias : SchedRW.Aliases) {
IdxVec AliasProcIndices;
- if ((*AI)->getValueInit("SchedModel")->isComplete()) {
+ if (Alias->getValueInit("SchedModel")->isComplete()) {
AliasProcIndices.push_back(
- getProcModel((*AI)->getValueAsDef("SchedModel")).Index);
- }
- else
+ getProcModel(Alias->getValueAsDef("SchedModel")).Index);
+ } else
AliasProcIndices = ProcIndices;
- const CodeGenSchedRW &AliasRW = getSchedRW((*AI)->getValueAsDef("AliasRW"));
+ const CodeGenSchedRW &AliasRW = getSchedRW(Alias->getValueAsDef("AliasRW"));
assert(AliasRW.IsRead == IsRead && "cannot alias reads to writes");
IdxVec ExpandedRWs;
expandRWSequence(AliasRW.Index, ExpandedRWs, IsRead);
- for (IdxIter SI = ExpandedRWs.begin(), SE = ExpandedRWs.end();
- SI != SE; ++SI) {
- collectRWResources(*SI, IsRead, AliasProcIndices);
+ for (unsigned int ExpandedRW : ExpandedRWs) {
+ collectRWResources(ExpandedRW, IsRead, AliasProcIndices);
}
}
}
@@ -2179,9 +2167,8 @@ void CodeGenSchedModels::addWriteRes(Record *ProcWriteResDef, unsigned PIdx) {
// Visit ProcResourceKinds referenced by the newly discovered WriteRes.
RecVec ProcResDefs = ProcWriteResDef->getValueAsListOfDefs("ProcResources");
- for (RecIter WritePRI = ProcResDefs.begin(), WritePRE = ProcResDefs.end();
- WritePRI != WritePRE; ++WritePRI) {
- addProcResource(*WritePRI, ProcModels[PIdx], ProcWriteResDef->getLoc());
+ for (auto *ProcResDef : ProcResDefs) {
+ addProcResource(ProcResDef, ProcModels[PIdx], ProcWriteResDef->getLoc());
}
}
@@ -2259,28 +2246,21 @@ void CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const {
void PredTransitions::dump() const {
dbgs() << "Expanded Variants:\n";
- for (std::vector<PredTransition>::const_iterator
- TI = TransVec.begin(), TE = TransVec.end(); TI != TE; ++TI) {
+ for (const auto &TI : TransVec) {
dbgs() << "{";
- for (SmallVectorImpl<PredCheck>::const_iterator
- PCI = TI->PredTerm.begin(), PCE = TI->PredTerm.end();
- PCI != PCE; ++PCI) {
- if (PCI != TI->PredTerm.begin())
- dbgs() << ", ";
- dbgs() << SchedModels.getSchedRW(PCI->RWIdx, PCI->IsRead).Name
- << ":" << PCI->Predicate->getName();
- }
+ ListSeparator LS;
+ for (const PredCheck &PC : TI.PredTerm)
+ dbgs() << LS << SchedModels.getSchedRW(PC.RWIdx, PC.IsRead).Name << ":"
+ << PC.Predicate->getName();
dbgs() << "},\n => {";
- for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
- WSI = TI->WriteSequences.begin(), WSE = TI->WriteSequences.end();
+ for (SmallVectorImpl<SmallVector<unsigned, 4>>::const_iterator
+ WSI = TI.WriteSequences.begin(),
+ WSE = TI.WriteSequences.end();
WSI != WSE; ++WSI) {
dbgs() << "(";
- for (SmallVectorImpl<unsigned>::const_iterator
- WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) {
- if (WI != WSI->begin())
- dbgs() << ", ";
- dbgs() << SchedModels.getSchedWrite(*WI).Name;
- }
+ ListSeparator LS;
+ for (unsigned N : *WSI)
+ dbgs() << LS << SchedModels.getSchedWrite(N).Name;
dbgs() << "),";
}
dbgs() << "}\n";
diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp
index 8f6d212df5ec..7311819f77ff 100644
--- a/llvm/utils/TableGen/CodeGenTarget.cpp
+++ b/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -99,6 +99,8 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v64i8: return "MVT::v64i8";
case MVT::v128i8: return "MVT::v128i8";
case MVT::v256i8: return "MVT::v256i8";
+ case MVT::v512i8: return "MVT::v512i8";
+ case MVT::v1024i8: return "MVT::v1024i8";
case MVT::v1i16: return "MVT::v1i16";
case MVT::v2i16: return "MVT::v2i16";
case MVT::v3i16: return "MVT::v3i16";
@@ -108,11 +110,15 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v32i16: return "MVT::v32i16";
case MVT::v64i16: return "MVT::v64i16";
case MVT::v128i16: return "MVT::v128i16";
+ case MVT::v256i16: return "MVT::v256i16";
+ case MVT::v512i16: return "MVT::v512i16";
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::v6i32: return "MVT::v6i32";
+ case MVT::v7i32: return "MVT::v7i32";
case MVT::v8i32: return "MVT::v8i32";
case MVT::v16i32: return "MVT::v16i32";
case MVT::v32i32: return "MVT::v32i32";
@@ -124,6 +130,7 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v2048i32: return "MVT::v2048i32";
case MVT::v1i64: return "MVT::v1i64";
case MVT::v2i64: return "MVT::v2i64";
+ case MVT::v3i64: return "MVT::v3i64";
case MVT::v4i64: return "MVT::v4i64";
case MVT::v8i64: return "MVT::v8i64";
case MVT::v16i64: return "MVT::v16i64";
@@ -132,6 +139,7 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v128i64: return "MVT::v128i64";
case MVT::v256i64: return "MVT::v256i64";
case MVT::v1i128: return "MVT::v1i128";
+ case MVT::v1f16: return "MVT::v1f16";
case MVT::v2f16: return "MVT::v2f16";
case MVT::v3f16: return "MVT::v3f16";
case MVT::v4f16: return "MVT::v4f16";
@@ -140,6 +148,8 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v32f16: return "MVT::v32f16";
case MVT::v64f16: return "MVT::v64f16";
case MVT::v128f16: return "MVT::v128f16";
+ case MVT::v256f16: return "MVT::v256f16";
+ case MVT::v512f16: return "MVT::v512f16";
case MVT::v2bf16: return "MVT::v2bf16";
case MVT::v3bf16: return "MVT::v3bf16";
case MVT::v4bf16: return "MVT::v4bf16";
@@ -153,6 +163,8 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v3f32: return "MVT::v3f32";
case MVT::v4f32: return "MVT::v4f32";
case MVT::v5f32: return "MVT::v5f32";
+ case MVT::v6f32: return "MVT::v6f32";
+ case MVT::v7f32: return "MVT::v7f32";
case MVT::v8f32: return "MVT::v8f32";
case MVT::v16f32: return "MVT::v16f32";
case MVT::v32f32: return "MVT::v32f32";
@@ -164,6 +176,7 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v2048f32: return "MVT::v2048f32";
case MVT::v1f64: return "MVT::v1f64";
case MVT::v2f64: return "MVT::v2f64";
+ case MVT::v3f64: return "MVT::v3f64";
case MVT::v4f64: return "MVT::v4f64";
case MVT::v8f64: return "MVT::v8f64";
case MVT::v16f64: return "MVT::v16f64";
@@ -209,6 +222,7 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::nxv8f16: return "MVT::nxv8f16";
case MVT::nxv16f16: return "MVT::nxv16f16";
case MVT::nxv32f16: return "MVT::nxv32f16";
+ case MVT::nxv1bf16: return "MVT::nxv1bf16";
case MVT::nxv2bf16: return "MVT::nxv2bf16";
case MVT::nxv4bf16: return "MVT::nxv4bf16";
case MVT::nxv8bf16: return "MVT::nxv8bf16";
@@ -251,9 +265,9 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records)
: Records(records), CGH(records) {
std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
if (Targets.size() == 0)
- PrintFatalError("ERROR: No 'Target' subclasses defined!");
+ PrintFatalError("No 'Target' subclasses defined!");
if (Targets.size() != 1)
- PrintFatalError("ERROR: Multiple subclasses of Target defined!");
+ PrintFatalError("Multiple subclasses of Target defined!");
TargetRec = Targets[0];
}
@@ -656,6 +670,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R,
isWillReturn = false;
isCold = false;
isNoDuplicate = false;
+ isNoMerge = false;
isConvergent = false;
isSpeculatable = false;
hasSideEffects = false;
@@ -845,6 +860,8 @@ void CodeGenIntrinsic::setProperty(Record *R) {
canThrow = true;
else if (R->getName() == "IntrNoDuplicate")
isNoDuplicate = true;
+ else if (R->getName() == "IntrNoMerge")
+ isNoMerge = true;
else if (R->getName() == "IntrConvergent")
isConvergent = true;
else if (R->getName() == "IntrNoReturn")
diff --git a/llvm/utils/TableGen/DAGISelEmitter.cpp b/llvm/utils/TableGen/DAGISelEmitter.cpp
index 32ed0bf98743..2f211e2958fa 100644
--- a/llvm/utils/TableGen/DAGISelEmitter.cpp
+++ b/llvm/utils/TableGen/DAGISelEmitter.cpp
@@ -115,7 +115,7 @@ struct PatternSortingPredicate {
// pattern may have been resolved into multiple match patterns due to
// alternative fragments. To ensure deterministic output, always use
// std::stable_sort with this predicate.
- return LHS->ID < RHS->ID;
+ return LHS->getID() < RHS->getID();
}
};
} // End anonymous namespace
@@ -153,9 +153,8 @@ void DAGISelEmitter::run(raw_ostream &OS) {
// Add all the patterns to a temporary list so we can sort them.
Records.startTimer("Sort patterns");
std::vector<const PatternToMatch*> Patterns;
- for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();
- I != E; ++I)
- Patterns.push_back(&*I);
+ for (const PatternToMatch &PTM : CGP.ptms())
+ Patterns.push_back(&PTM);
// We want to process the matches in order of minimal cost. Sort the patterns
// so the least cost one is at the start.
@@ -164,9 +163,9 @@ void DAGISelEmitter::run(raw_ostream &OS) {
// Convert each variant of each pattern into a Matcher.
Records.startTimer("Convert to matchers");
std::vector<Matcher*> PatternMatchers;
- for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
+ for (const PatternToMatch *PTM : Patterns) {
for (unsigned Variant = 0; ; ++Variant) {
- if (Matcher *M = ConvertPatternToMatcher(*Patterns[i], Variant, CGP))
+ if (Matcher *M = ConvertPatternToMatcher(*PTM, Variant, CGP))
PatternMatchers.push_back(M);
else
break;
diff --git a/llvm/utils/TableGen/DAGISelMatcher.cpp b/llvm/utils/TableGen/DAGISelMatcher.cpp
index bebd205ad58f..e436a931a9f5 100644
--- a/llvm/utils/TableGen/DAGISelMatcher.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcher.cpp
@@ -421,3 +421,15 @@ bool CheckImmAllZerosVMatcher::isContradictoryImpl(const Matcher *M) const {
// AllOnes is contradictory.
return isa<CheckImmAllOnesVMatcher>(M);
}
+
+bool CheckCondCodeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const auto *CCCM = dyn_cast<CheckCondCodeMatcher>(M))
+ return CCCM->getCondCodeName() != getCondCodeName();
+ return false;
+}
+
+bool CheckChild2CondCodeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const auto *CCCCM = dyn_cast<CheckChild2CondCodeMatcher>(M))
+ return CCCCM->getCondCodeName() != getCondCodeName();
+ return false;
+}
diff --git a/llvm/utils/TableGen/DAGISelMatcher.h b/llvm/utils/TableGen/DAGISelMatcher.h
index ff9a0cb335d1..77280acaf4ca 100644
--- a/llvm/utils/TableGen/DAGISelMatcher.h
+++ b/llvm/utils/TableGen/DAGISelMatcher.h
@@ -635,6 +635,7 @@ private:
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckCondCodeMatcher>(M)->CondCodeName == CondCodeName;
}
+ bool isContradictoryImpl(const Matcher *M) const override;
};
/// CheckChild2CondCodeMatcher - This checks to see if child 2 node is a
@@ -656,6 +657,7 @@ private:
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckChild2CondCodeMatcher>(M)->CondCodeName == CondCodeName;
}
+ bool isContradictoryImpl(const Matcher *M) const override;
};
/// CheckValueTypeMatcher - This checks to see if the current node is a
diff --git a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
index 03528a46aea7..a552998e4eee 100644
--- a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -173,7 +173,7 @@ static std::string GetPatFromTreePatternNode(const TreePatternNode *N) {
return str;
}
-static size_t GetVBRSize(unsigned Val) {
+static unsigned GetVBRSize(unsigned Val) {
if (Val <= 127) return 1;
unsigned NumBytes = 0;
@@ -186,7 +186,7 @@ static size_t GetVBRSize(unsigned Val) {
/// EmitVBRValue - Emit the specified value as a VBR, returning the number of
/// bytes emitted.
-static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) {
+static unsigned EmitVBRValue(uint64_t Val, raw_ostream &OS) {
if (Val <= 127) {
OS << Val << ", ";
return 1;
@@ -206,6 +206,18 @@ static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) {
return NumBytes+1;
}
+/// Emit the specified signed value as a VBR. To improve compression we encode
+/// positive numbers shifted left by 1 and negative numbers negated and shifted
+/// left by 1 with bit 0 set.
+static unsigned EmitSignedVBRValue(uint64_t Val, raw_ostream &OS) {
+ if ((int64_t)Val >= 0)
+ Val = Val << 1;
+ else
+ Val = (-Val << 1) | 1;
+
+ return EmitVBRValue(Val, OS);
+}
+
// This is expensive and slow.
static std::string getIncludePath(const Record *R) {
std::string str;
@@ -255,7 +267,7 @@ SizeMatcher(Matcher *N, raw_ostream &OS) {
assert(SM->getNext() == nullptr && "Scope matcher should not have next");
unsigned Size = 1; // Count the kind.
for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) {
- const size_t ChildSize = SizeMatcherList(SM->getChild(i), OS);
+ const unsigned ChildSize = SizeMatcherList(SM->getChild(i), OS);
assert(ChildSize != 0 && "Matcher cannot have child of size 0");
SM->getChild(i)->setSize(ChildSize);
Size += GetVBRSize(ChildSize) + ChildSize; // Count VBR and child size.
@@ -283,7 +295,7 @@ SizeMatcher(Matcher *N, raw_ostream &OS) {
Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
++Size; // Count the child's type.
}
- const size_t ChildSize = SizeMatcherList(Child, OS);
+ const unsigned ChildSize = SizeMatcherList(Child, OS);
assert(ChildSize != 0 && "Matcher cannot have child of size 0");
Child->setSize(ChildSize);
Size += GetVBRSize(ChildSize) + ChildSize; // Count VBR and child size.
@@ -381,9 +393,8 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
OS.indent(Indent);
}
- size_t ChildSize = SM->getChild(i)->getSize();
- size_t VBRSize = GetVBRSize(ChildSize);
- EmitVBRValue(ChildSize, OS);
+ unsigned ChildSize = SM->getChild(i)->getSize();
+ unsigned VBRSize = EmitVBRValue(ChildSize, OS);
if (!OmitComments) {
OS << "/*->" << CurrentIdx + VBRSize + ChildSize << "*/";
if (i == 0)
@@ -534,7 +545,7 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
"/*SwitchOpcode*/ " : "/*SwitchType*/ ");
}
- size_t ChildSize = Child->getSize();
+ unsigned ChildSize = Child->getSize();
CurrentIdx += EmitVBRValue(ChildSize, OS) + IdxSize;
if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),";
@@ -580,15 +591,16 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
case Matcher::CheckInteger: {
OS << "OPC_CheckInteger, ";
- unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);
+ unsigned Bytes =
+ 1 + EmitSignedVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);
OS << '\n';
return Bytes;
}
case Matcher::CheckChildInteger: {
OS << "OPC_CheckChild" << cast<CheckChildIntegerMatcher>(N)->getChildNo()
<< "Integer, ";
- unsigned Bytes=1+EmitVBRValue(cast<CheckChildIntegerMatcher>(N)->getValue(),
- OS);
+ unsigned Bytes = 1 + EmitSignedVBRValue(
+ cast<CheckChildIntegerMatcher>(N)->getValue(), OS);
OS << '\n';
return Bytes;
}
@@ -656,16 +668,16 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
int64_t Val = cast<EmitIntegerMatcher>(N)->getValue();
OS << "OPC_EmitInteger, "
<< getEnumName(cast<EmitIntegerMatcher>(N)->getVT()) << ", ";
- unsigned Bytes = 2+EmitVBRValue(Val, OS);
+ unsigned Bytes = 2 + EmitSignedVBRValue(Val, OS);
OS << '\n';
return Bytes;
}
case Matcher::EmitStringInteger: {
const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue();
// These should always fit into 7 bits.
- OS << "OPC_EmitInteger, "
- << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", "
- << Val << ",\n";
+ OS << "OPC_EmitStringInteger, "
+ << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", " << Val
+ << ",\n";
return 3;
}
@@ -886,14 +898,13 @@ void MatcherTableEmitter::EmitNodePredicatesFunction(
for (unsigned i = 0, e = Preds.size(); i != e; ++i) {
// Emit the predicate code corresponding to this pattern.
const TreePredicateFn PredFn = Preds[i];
-
assert(!PredFn.isAlwaysTrue() && "No code in this predicate");
- OS << " case " << i << ": {\n";
- for (auto *SimilarPred :
- NodePredicatesByCodeToRun[PredFn.getCodeToRunOnSDNode()])
- OS << " // " << TreePredicateFn(SimilarPred).getFnName() <<'\n';
+ std::string PredFnCodeStr = PredFn.getCodeToRunOnSDNode();
- OS << PredFn.getCodeToRunOnSDNode() << "\n }\n";
+ OS << " case " << i << ": {\n";
+ for (auto *SimilarPred : NodePredicatesByCodeToRun[PredFnCodeStr])
+ OS << " // " << TreePredicateFn(SimilarPred).getFnName() << '\n';
+ OS << PredFnCodeStr << "\n }\n";
}
OS << " }\n";
OS << "}\n";
diff --git a/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/llvm/utils/TableGen/DAGISelMatcherGen.cpp
index f7415b87e1c0..2625595cf9d5 100644
--- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherGen.cpp
@@ -163,7 +163,7 @@ MatcherGen::MatcherGen(const PatternToMatch &pattern,
PatWithNoTypes->RemoveAllTypes();
// If there are types that are manifestly known, infer them.
- InferPossibleTypes(Pattern.ForceMode);
+ InferPossibleTypes(Pattern.getForceMode());
}
/// InferPossibleTypes - As we emit the pattern, we end up generating type
@@ -576,7 +576,7 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) {
// Emit the matcher for the pattern structure and types.
EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes.get(),
- Pattern.ForceMode);
+ Pattern.getForceMode());
// If the pattern has a predicate on it (e.g. only enabled when a subtarget
// feature is around, do the check).
diff --git a/llvm/utils/TableGen/DFAEmitter.cpp b/llvm/utils/TableGen/DFAEmitter.cpp
index 781cb0636fa1..27161d261e85 100644
--- a/llvm/utils/TableGen/DFAEmitter.cpp
+++ b/llvm/utils/TableGen/DFAEmitter.cpp
@@ -19,7 +19,6 @@
// to the NFA.
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "dfa-emitter"
#include "DFAEmitter.h"
#include "CodeGenTarget.h"
@@ -39,6 +38,8 @@
#include <string>
#include <vector>
+#define DEBUG_TYPE "dfa-emitter"
+
using namespace llvm;
//===----------------------------------------------------------------------===//
@@ -376,11 +377,9 @@ void CustomDfaEmitter::printActionValue(action_type A, raw_ostream &OS) {
const ActionTuple &AT = Actions[A];
if (AT.size() > 1)
OS << "std::make_tuple(";
- bool First = true;
+ ListSeparator LS;
for (const auto &SingleAction : AT) {
- if (!First)
- OS << ", ";
- First = false;
+ OS << LS;
SingleAction.print(OS);
}
if (AT.size() > 1)
diff --git a/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
index 40d9385e5e9e..9cbdbc19c206 100644
--- a/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -14,8 +14,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "dfa-emitter"
-
#include "CodeGenSchedule.h"
#include "CodeGenTarget.h"
#include "DFAEmitter.h"
@@ -34,6 +32,8 @@
#include <unordered_map>
#include <vector>
+#define DEBUG_TYPE "dfa-emitter"
+
using namespace llvm;
// We use a uint64_t to represent a resource bitmask.
@@ -157,8 +157,8 @@ int DFAPacketizerEmitter::collectAllComboFuncs(ArrayRef<Record *> ComboFuncList)
uint64_t ComboResources = ComboBit;
LLVM_DEBUG(dbgs() << " combo: " << ComboFuncName << ":0x"
<< Twine::utohexstr(ComboResources) << "\n");
- for (unsigned k = 0, M = FuncList.size(); k < M; ++k) {
- std::string FuncName = std::string(FuncList[k]->getName());
+ for (auto *K : FuncList) {
+ std::string FuncName = std::string(K->getName());
uint64_t FuncResources = FUNameToBitsMap[FuncName];
LLVM_DEBUG(dbgs() << " " << FuncName << ":0x"
<< Twine::utohexstr(FuncResources) << "\n");
diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp
index c9daa9b24155..b21bf369d18e 100644
--- a/llvm/utils/TableGen/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/DirectiveEmitter.cpp
@@ -633,6 +633,43 @@ void GenerateFlangClauseUnparse(const DirectiveLanguage &DirLang,
}
}
+// Generate check in the Enter functions for clauses classes.
+void GenerateFlangClauseCheckPrototypes(const DirectiveLanguage &DirLang,
+ raw_ostream &OS) {
+
+ IfDefScope Scope("GEN_FLANG_CLAUSE_CHECK_ENTER", OS);
+
+ OS << "\n";
+ for (const auto &C : DirLang.getClauses()) {
+ Clause Clause{C};
+ OS << "void Enter(const parser::" << DirLang.getFlangClauseBaseClass()
+ << "::" << Clause.getFormattedParserClassName() << " &);\n";
+ }
+}
+
+// Generate the mapping for clauses between the parser class and the
+// corresponding clause Kind
+void GenerateFlangClauseParserKindMap(const DirectiveLanguage &DirLang,
+ raw_ostream &OS) {
+
+ IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_KIND_MAP", OS);
+
+ OS << "\n";
+ for (const auto &C : DirLang.getClauses()) {
+ Clause Clause{C};
+ OS << "if constexpr (std::is_same_v<A, parser::"
+ << DirLang.getFlangClauseBaseClass()
+ << "::" << Clause.getFormattedParserClassName();
+ OS << ">)\n";
+ OS << " return llvm::" << DirLang.getCppNamespace()
+ << "::Clause::" << DirLang.getClausePrefix() << Clause.getFormattedName()
+ << ";\n";
+ }
+
+ OS << "llvm_unreachable(\"Invalid " << DirLang.getName()
+ << " Parser clause\");\n";
+}
+
// Generate the implementation section for the enumeration in the directive
// language
void EmitDirectivesFlangImpl(const DirectiveLanguage &DirLang,
@@ -649,6 +686,10 @@ void EmitDirectivesFlangImpl(const DirectiveLanguage &DirLang,
GenerateFlangClauseDump(DirLang, OS);
GenerateFlangClauseUnparse(DirLang, OS);
+
+ GenerateFlangClauseCheckPrototypes(DirLang, OS);
+
+ GenerateFlangClauseParserKindMap(DirLang, OS);
}
void GenerateClauseClassMacro(const DirectiveLanguage &DirLang,
@@ -717,37 +758,11 @@ void GenerateClauseClassMacro(const DirectiveLanguage &DirLang,
OS << "#undef CLAUSE\n";
}
-// Generate the implementation section for the enumeration in the directive
-// language.
-void EmitDirectivesGen(RecordKeeper &Records, raw_ostream &OS) {
- const auto DirLang = DirectiveLanguage{Records};
- if (DirLang.HasValidityErrors())
- return;
-
- EmitDirectivesFlangImpl(DirLang, OS);
-
- GenerateClauseClassMacro(DirLang, OS);
-}
-
-// Generate the implementation for the enumeration in the directive
+// Generate the implemenation for the enumeration in the directive
// language. This code can be included in library.
-void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) {
- const auto DirLang = DirectiveLanguage{Records};
- if (DirLang.HasValidityErrors())
- return;
-
- if (!DirLang.getIncludeHeader().empty())
- OS << "#include \"" << DirLang.getIncludeHeader() << "\"\n\n";
-
- OS << "#include \"llvm/ADT/StringRef.h\"\n";
- OS << "#include \"llvm/ADT/StringSwitch.h\"\n";
- OS << "#include \"llvm/Support/ErrorHandling.h\"\n";
- OS << "\n";
- OS << "using namespace llvm;\n";
- llvm::SmallVector<StringRef, 2> Namespaces;
- llvm::SplitString(DirLang.getCppNamespace(), Namespaces, "::");
- for (auto Ns : Namespaces)
- OS << "using namespace " << Ns << ";\n";
+void EmitDirectivesBasicImpl(const DirectiveLanguage &DirLang,
+ raw_ostream &OS) {
+ IfDefScope Scope("GEN_DIRECTIVES_IMPL", OS);
// getDirectiveKind(StringRef Str)
GenerateGetKind(DirLang.getDirectives(), OS, "Directive", DirLang,
@@ -773,4 +788,18 @@ void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) {
GenerateIsAllowedClause(DirLang, OS);
}
+// Generate the implemenation section for the enumeration in the directive
+// language.
+void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) {
+ const auto DirLang = DirectiveLanguage{Records};
+ if (DirLang.HasValidityErrors())
+ return;
+
+ EmitDirectivesFlangImpl(DirLang, OS);
+
+ GenerateClauseClassMacro(DirLang, OS);
+
+ EmitDirectivesBasicImpl(DirLang, OS);
+}
+
} // namespace llvm
diff --git a/llvm/utils/TableGen/ExegesisEmitter.cpp b/llvm/utils/TableGen/ExegesisEmitter.cpp
index 4e532c371691..77654cbc92fd 100644
--- a/llvm/utils/TableGen/ExegesisEmitter.cpp
+++ b/llvm/utils/TableGen/ExegesisEmitter.cpp
@@ -98,9 +98,9 @@ ExegesisEmitter::ExegesisEmitter(RecordKeeper &RK)
: Records(RK), PfmCounterNameTable(collectPfmCounters(RK)) {
std::vector<Record *> Targets = Records.getAllDerivedDefinitions("Target");
if (Targets.size() == 0)
- PrintFatalError("ERROR: No 'Target' subclasses defined!");
+ PrintFatalError("No 'Target' subclasses defined!");
if (Targets.size() != 1)
- PrintFatalError("ERROR: Multiple subclasses of Target defined!");
+ PrintFatalError("Multiple subclasses of Target defined!");
Target = std::string(Targets[0]->getName());
}
diff --git a/llvm/utils/TableGen/FastISelEmitter.cpp b/llvm/utils/TableGen/FastISelEmitter.cpp
index 0729ab70d696..d64262124308 100644
--- a/llvm/utils/TableGen/FastISelEmitter.cpp
+++ b/llvm/utils/TableGen/FastISelEmitter.cpp
@@ -290,9 +290,11 @@ struct OperandsSignature {
}
void PrintParameters(raw_ostream &OS) const {
+ ListSeparator LS;
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ OS << LS;
if (Operands[i].isReg()) {
- OS << "unsigned Op" << i << ", bool Op" << i << "IsKill";
+ OS << "unsigned Op" << i;
} else if (Operands[i].isImm()) {
OS << "uint64_t imm" << i;
} else if (Operands[i].isFP()) {
@@ -300,31 +302,25 @@ struct OperandsSignature {
} else {
llvm_unreachable("Unknown operand kind!");
}
- if (i + 1 != e)
- OS << ", ";
}
}
void PrintArguments(raw_ostream &OS,
const std::vector<std::string> &PR) const {
assert(PR.size() == Operands.size());
- bool PrintedArg = false;
+ ListSeparator LS;
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (PR[i] != "")
// Implicit physical register operand.
continue;
- if (PrintedArg)
- OS << ", ";
+ OS << LS;
if (Operands[i].isReg()) {
- OS << "Op" << i << ", Op" << i << "IsKill";
- PrintedArg = true;
+ OS << "Op" << i;
} else if (Operands[i].isImm()) {
OS << "imm" << i;
- PrintedArg = true;
} else if (Operands[i].isFP()) {
OS << "f" << i;
- PrintedArg = true;
} else {
llvm_unreachable("Unknown operand kind!");
}
@@ -332,9 +328,11 @@ struct OperandsSignature {
}
void PrintArguments(raw_ostream &OS) const {
+ ListSeparator LS;
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ OS << LS;
if (Operands[i].isReg()) {
- OS << "Op" << i << ", Op" << i << "IsKill";
+ OS << "Op" << i;
} else if (Operands[i].isImm()) {
OS << "imm" << i;
} else if (Operands[i].isFP()) {
@@ -342,8 +340,6 @@ struct OperandsSignature {
} else {
llvm_unreachable("Unknown operand kind!");
}
- if (i + 1 != e)
- OS << ", ";
}
}
@@ -620,10 +616,10 @@ void FastISelMap::printImmediatePredicates(raw_ostream &OS) {
return;
OS << "\n// FastEmit Immediate Predicate functions.\n";
- for (ImmPredicateSet::iterator I = ImmediatePredicates.begin(),
- E = ImmediatePredicates.end(); I != E; ++I) {
- OS << "static bool " << I->getFnName() << "(int64_t Imm) {\n";
- OS << I->getImmediatePredicateCode() << "\n}\n";
+ for (auto ImmediatePredicate : ImmediatePredicates) {
+ OS << "static bool " << ImmediatePredicate.getFnName()
+ << "(int64_t Imm) {\n";
+ OS << ImmediatePredicate.getImmediatePredicateCode() << "\n}\n";
}
OS << "\n\n";
@@ -677,7 +673,7 @@ void FastISelMap::emitInstructionCode(raw_ostream &OS,
OS << ");\n";
} else {
OS << "extractsubreg(" << RetVTName
- << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n";
+ << ", Op0, " << Memo.SubRegNo << ");\n";
}
if (!PredicateCheck.empty()) {
@@ -695,29 +691,25 @@ void FastISelMap::emitInstructionCode(raw_ostream &OS,
void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
// Now emit code for all the patterns that we collected.
- for (OperandsOpcodeTypeRetPredMap::const_iterator OI = SimplePatterns.begin(),
- OE = SimplePatterns.end(); OI != OE; ++OI) {
- const OperandsSignature &Operands = OI->first;
- const OpcodeTypeRetPredMap &OTM = OI->second;
+ for (const auto &SimplePattern : SimplePatterns) {
+ const OperandsSignature &Operands = SimplePattern.first;
+ const OpcodeTypeRetPredMap &OTM = SimplePattern.second;
- for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end();
- I != E; ++I) {
- const std::string &Opcode = I->first;
- const TypeRetPredMap &TM = I->second;
+ for (const auto &I : OTM) {
+ const std::string &Opcode = I.first;
+ const TypeRetPredMap &TM = I.second;
OS << "// FastEmit functions for " << Opcode << ".\n";
OS << "\n";
// Emit one function for each opcode,type pair.
- for (TypeRetPredMap::const_iterator TI = TM.begin(), TE = TM.end();
- TI != TE; ++TI) {
- MVT::SimpleValueType VT = TI->first;
- const RetPredMap &RM = TI->second;
+ for (const auto &TI : TM) {
+ MVT::SimpleValueType VT = TI.first;
+ const RetPredMap &RM = TI.second;
if (RM.size() != 1) {
- for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end();
- RI != RE; ++RI) {
- MVT::SimpleValueType RetVT = RI->first;
- const PredMap &PM = RI->second;
+ for (const auto &RI : RM) {
+ MVT::SimpleValueType RetVT = RI.first;
+ const PredMap &PM = RI.second;
OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"
<< getLegalCName(std::string(getName(VT))) << "_"
@@ -739,9 +731,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
OS << ", ";
Operands.PrintParameters(OS);
OS << ") {\nswitch (RetVT.SimpleTy) {\n";
- for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end();
- RI != RE; ++RI) {
- MVT::SimpleValueType RetVT = RI->first;
+ for (const auto &RI : RM) {
+ MVT::SimpleValueType RetVT = RI.first;
OS << " case " << getName(RetVT) << ": return fastEmit_"
<< getLegalCName(Opcode) << "_"
<< getLegalCName(std::string(getName(VT))) << "_"
@@ -783,9 +774,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
Operands.PrintParameters(OS);
OS << ") {\n";
OS << " switch (VT.SimpleTy) {\n";
- for (TypeRetPredMap::const_iterator TI = TM.begin(), TE = TM.end();
- TI != TE; ++TI) {
- MVT::SimpleValueType VT = TI->first;
+ for (const auto &TI : TM) {
+ MVT::SimpleValueType VT = TI.first;
std::string TypeName = std::string(getName(VT));
OS << " case " << TypeName << ": return fastEmit_"
<< getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";
@@ -850,9 +840,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
}
OS << " switch (Opcode) {\n";
- for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end();
- I != E; ++I) {
- const std::string &Opcode = I->first;
+ for (const auto &I : OTM) {
+ const std::string &Opcode = I.first;
OS << " case " << Opcode << ": return fastEmit_"
<< getLegalCName(Opcode) << "_";
diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
index 01b39df055ad..c5dd1e626696 100644
--- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -973,7 +973,13 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
<< "Address, const void *Decoder, bool &DecodeComplete) {\n";
Indentation += 2;
OS.indent(Indentation) << "DecodeComplete = true;\n";
- OS.indent(Indentation) << "InsnType tmp;\n";
+ // TODO: When InsnType is large, using uint64_t limits all fields to 64 bits
+ // It would be better for emitBinaryParser to use a 64-bit tmp whenever
+ // possible but fall back to an InsnType-sized tmp for truly large fields.
+ OS.indent(Indentation) << "using TmpType = "
+ "std::conditional_t<std::is_integral<InsnType>::"
+ "value, InsnType, uint64_t>;\n";
+ OS.indent(Indentation) << "TmpType tmp;\n";
OS.indent(Indentation) << "switch (Idx) {\n";
OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
unsigned Index = 0;
@@ -1107,18 +1113,24 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
bool &OpHasCompleteDecoder) const {
const std::string &Decoder = OpInfo.Decoder;
- if (OpInfo.numFields() != 1 || OpInfo.InitValue != 0) {
+ bool UseInsertBits = OpInfo.numFields() != 1 || OpInfo.InitValue != 0;
+
+ if (UseInsertBits) {
o.indent(Indentation) << "tmp = 0x";
o.write_hex(OpInfo.InitValue);
o << ";\n";
}
for (const EncodingField &EF : OpInfo) {
- o.indent(Indentation) << "tmp ";
- if (OpInfo.numFields() != 1 || OpInfo.InitValue != 0) o << '|';
- o << "= fieldFromInstruction"
- << "(insn, " << EF.Base << ", " << EF.Width << ')';
- if (OpInfo.numFields() != 1 || EF.Offset != 0)
+ o.indent(Indentation);
+ if (UseInsertBits)
+ o << "insertBits(tmp, ";
+ else
+ o << "tmp = ";
+ o << "fieldFromInstruction(insn, " << EF.Base << ", " << EF.Width << ')';
+ if (UseInsertBits)
+ o << ", " << EF.Offset << ", " << EF.Width << ')';
+ else if (EF.Offset != 0)
o << " << " << EF.Offset;
o << ";\n";
}
@@ -1210,14 +1222,9 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
if (IsOr)
o << "(";
- bool First = true;
+ ListSeparator LS(IsOr ? " || " : " && ");
for (auto *Arg : D->getArgs()) {
- if (!First) {
- if (IsOr)
- o << " || ";
- else
- o << " && ";
- }
+ o << LS;
if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
if (NotArg->getOperator()->getAsString() != "not" ||
NotArg->getNumArgs() != 1)
@@ -1230,8 +1237,6 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
PrintFatalError(Pred->getLoc(), "Invalid AssemblerCondDag!");
o << "Bits[" << Emitter->PredicateNamespace << "::" << Arg->getAsString()
<< "]";
-
- First = false;
}
if (IsOr)
@@ -1250,7 +1255,7 @@ bool FilterChooser::doesOpcodeNeedPredicate(unsigned Opc) const {
if (!Pred->getValue("AssemblerMatcherPredicate"))
continue;
- if (dyn_cast<DagInit>(Pred->getValue("AssemblerCondDag")->getValue()))
+ if (isa<DagInit>(Pred->getValue("AssemblerCondDag")->getValue()))
return true;
}
return false;
@@ -1501,13 +1506,13 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
if (AllowMixed && !Greedy) {
assert(numInstructions == 3);
- for (unsigned i = 0; i < Opcodes.size(); ++i) {
+ for (auto Opcode : Opcodes) {
std::vector<unsigned> StartBits;
std::vector<unsigned> EndBits;
std::vector<uint64_t> FieldVals;
insn_t Insn;
- insnWithID(Insn, Opcodes[i].EncodingID);
+ insnWithID(Insn, Opcode.EncodingID);
// Look for islands of undecoded bits of any instruction.
if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) {
@@ -1769,13 +1774,13 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
dumpStack(errs(), "\t\t");
- for (unsigned i = 0; i < Opcodes.size(); ++i) {
+ for (auto Opcode : Opcodes) {
errs() << '\t';
- emitNameWithID(errs(), Opcodes[i].EncodingID);
+ emitNameWithID(errs(), Opcode.EncodingID);
errs() << " ";
dumpBits(
errs(),
- getBitsField(*AllInstructions[Opcodes[i].EncodingID].EncodingDef, "Inst"));
+ getBitsField(*AllInstructions[Opcode.EncodingID].EncodingDef, "Inst"));
errs() << '\n';
}
}
@@ -2149,27 +2154,22 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
OS << "// Helper functions for extracting fields from encoded instructions.\n"
<< "// InsnType must either be integral or an APInt-like object that "
"must:\n"
- << "// * Have a static const max_size_in_bits equal to the number of bits "
- "in the\n"
- << "// encoding.\n"
<< "// * be default-constructible and copy-constructible\n"
<< "// * be constructible from a uint64_t\n"
<< "// * be constructible from an APInt (this can be private)\n"
- << "// * Support getBitsSet(loBit, hiBit)\n"
- << "// * be convertible to uint64_t\n"
- << "// * Support the ~, &, ==, !=, and |= operators with other objects of "
+ << "// * Support insertBits(bits, startBit, numBits)\n"
+ << "// * Support extractBitsAsZExtValue(numBits, startBit)\n"
+ << "// * be convertible to bool\n"
+ << "// * Support the ~, &, ==, and != operators with other objects of "
"the same type\n"
- << "// * Support shift (<<, >>) with signed and unsigned integers on the "
- "RHS\n"
<< "// * Support put (<<) to raw_ostream&\n"
<< "template <typename InsnType>\n"
<< "#if defined(_MSC_VER) && !defined(__clang__)\n"
<< "__declspec(noinline)\n"
<< "#endif\n"
- << "static InsnType fieldFromInstruction(InsnType insn, unsigned "
- "startBit,\n"
- << " unsigned numBits, "
- "std::true_type) {\n"
+ << "static std::enable_if_t<std::is_integral<InsnType>::value, InsnType>\n"
+ << "fieldFromInstruction(const InsnType &insn, unsigned startBit,\n"
+ << " unsigned numBits) {\n"
<< " assert(startBit + numBits <= 64 && \"Cannot support >64-bit "
"extractions!\");\n"
<< " assert(startBit + numBits <= (sizeof(InsnType) * 8) &&\n"
@@ -2183,22 +2183,32 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
<< "}\n"
<< "\n"
<< "template <typename InsnType>\n"
- << "static InsnType fieldFromInstruction(InsnType insn, unsigned "
- "startBit,\n"
- << " unsigned numBits, "
- "std::false_type) {\n"
- << " assert(startBit + numBits <= InsnType::max_size_in_bits && "
- "\"Instruction field out of bounds!\");\n"
- << " InsnType fieldMask = InsnType::getBitsSet(0, numBits);\n"
- << " return (insn >> startBit) & fieldMask;\n"
+ << "static std::enable_if_t<!std::is_integral<InsnType>::value, "
+ "uint64_t>\n"
+ << "fieldFromInstruction(const InsnType &insn, unsigned startBit,\n"
+ << " unsigned numBits) {\n"
+ << " return insn.extractBitsAsZExtValue(numBits, startBit);\n"
+ << "}\n\n";
+}
+
+// emitInsertBits - Emit the templated helper function insertBits().
+static void emitInsertBits(formatted_raw_ostream &OS) {
+ OS << "// Helper function for inserting bits extracted from an encoded "
+ "instruction into\n"
+ << "// a field.\n"
+ << "template <typename InsnType>\n"
+ << "static std::enable_if_t<std::is_integral<InsnType>::value>\n"
+ << "insertBits(InsnType &field, InsnType bits, unsigned startBit, "
+ "unsigned numBits) {\n"
+ << " assert(startBit + numBits <= sizeof field * 8);\n"
+ << " field |= (InsnType)bits << startBit;\n"
<< "}\n"
<< "\n"
<< "template <typename InsnType>\n"
- << "static InsnType fieldFromInstruction(InsnType insn, unsigned "
- "startBit,\n"
- << " unsigned numBits) {\n"
- << " return fieldFromInstruction(insn, startBit, numBits, "
- "std::is_integral<InsnType>());\n"
+ << "static std::enable_if_t<!std::is_integral<InsnType>::value>\n"
+ << "insertBits(InsnType &field, uint64_t bits, unsigned startBit, "
+ "unsigned numBits) {\n"
+ << " field.insertBits(bits, startBit, numBits);\n"
<< "}\n\n";
}
@@ -2401,6 +2411,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
OS << "namespace llvm {\n\n";
emitFieldFromInstruction(OS);
+ emitInsertBits(OS);
Target.reverseBitsForLittleEndianEncoding();
@@ -2418,7 +2429,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
const CodeGenHwModes &HWM = Target.getHwModes();
EncodingInfoByHwMode EBM(DI->getDef(), HWM);
- for (auto &KV : EBM.Map)
+ for (auto &KV : EBM)
HwModeNames.insert(HWM.getMode(KV.first).Name);
}
}
@@ -2436,7 +2447,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
const CodeGenHwModes &HWM = Target.getHwModes();
EncodingInfoByHwMode EBM(DI->getDef(), HWM);
- for (auto &KV : EBM.Map) {
+ for (auto &KV : EBM) {
NumberedEncodings.emplace_back(KV.second, NumberedInstruction,
HWM.getMode(KV.first).Name);
HwModeNames.insert(HWM.getMode(KV.first).Name);
diff --git a/llvm/utils/TableGen/GICombinerEmitter.cpp b/llvm/utils/TableGen/GICombinerEmitter.cpp
index ab00cff63998..c03cd371ef9d 100644
--- a/llvm/utils/TableGen/GICombinerEmitter.cpp
+++ b/llvm/utils/TableGen/GICombinerEmitter.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/Timer.h"
#include "llvm/TableGen/Error.h"
@@ -241,13 +242,12 @@ public:
bool Progressed = false;
SmallSet<GIMatchDagEdge *, 20> EdgesToRemove;
while (!EdgesRemaining.empty()) {
- for (auto EI = EdgesRemaining.begin(), EE = EdgesRemaining.end();
- EI != EE; ++EI) {
- if (Visited.count((*EI)->getFromMI())) {
- if (Roots.count((*EI)->getToMI()))
+ for (auto *EI : EdgesRemaining) {
+ if (Visited.count(EI->getFromMI())) {
+ if (Roots.count(EI->getToMI()))
PrintError(TheDef.getLoc(), "One or more roots are unnecessary");
- Visited.insert((*EI)->getToMI());
- EdgesToRemove.insert(*EI);
+ Visited.insert(EI->getToMI());
+ EdgesToRemove.insert(EI);
Progressed = true;
}
}
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index 0a6985a3eac2..693073672fc1 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -90,7 +90,7 @@ std::string getEnumNameForPredicate(const TreePredicateFn &Predicate) {
}
/// Get the opcode used to check this predicate.
-std::string getMatchOpcodeForPredicate(const TreePredicateFn &Predicate) {
+std::string getMatchOpcodeForImmPredicate(const TreePredicateFn &Predicate) {
return "GIM_Check" + Predicate.getImmTypeIdentifier().str() + "ImmPredicate";
}
@@ -118,7 +118,9 @@ public:
return;
}
if (Ty.isVector()) {
- OS << "GILLT_v" << Ty.getNumElements() << "s" << Ty.getScalarSizeInBits();
+ OS << (Ty.isScalable() ? "GILLT_nxv" : "GILLT_v")
+ << Ty.getElementCount().getKnownMinValue() << "s"
+ << Ty.getScalarSizeInBits();
return;
}
if (Ty.isPointer()) {
@@ -136,7 +138,10 @@ public:
return;
}
if (Ty.isVector()) {
- OS << "LLT::vector(" << Ty.getNumElements() << ", "
+ OS << "LLT::vector("
+ << (Ty.isScalable() ? "ElementCount::getScalable("
+ : "ElementCount::getFixed(")
+ << Ty.getElementCount().getKnownMinValue() << "), "
<< Ty.getScalarSizeInBits() << ")";
return;
}
@@ -169,10 +174,21 @@ public:
if (Ty.isPointer() && Ty.getAddressSpace() != Other.Ty.getAddressSpace())
return Ty.getAddressSpace() < Other.Ty.getAddressSpace();
- if (Ty.isVector() && Ty.getNumElements() != Other.Ty.getNumElements())
- return Ty.getNumElements() < Other.Ty.getNumElements();
+ if (Ty.isVector() && Ty.getElementCount() != Other.Ty.getElementCount())
+ return std::make_tuple(Ty.isScalable(),
+ Ty.getElementCount().getKnownMinValue()) <
+ std::make_tuple(Other.Ty.isScalable(),
+ Other.Ty.getElementCount().getKnownMinValue());
- return Ty.getSizeInBits() < Other.Ty.getSizeInBits();
+ assert((!Ty.isVector() || Ty.isScalable() == Other.Ty.isScalable()) &&
+ "Unexpected mismatch of scalable property");
+ return Ty.isVector()
+ ? std::make_tuple(Ty.isScalable(),
+ Ty.getSizeInBits().getKnownMinSize()) <
+ std::make_tuple(Other.Ty.isScalable(),
+ Other.Ty.getSizeInBits().getKnownMinSize())
+ : Ty.getSizeInBits().getFixedSize() <
+ Other.Ty.getSizeInBits().getFixedSize();
}
bool operator==(const LLTCodeGen &B) const { return Ty == B.Ty; }
@@ -187,12 +203,9 @@ class InstructionMatcher;
static Optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT) {
MVT VT(SVT);
- if (VT.isScalableVector())
- return None;
-
- if (VT.isFixedLengthVector() && VT.getVectorNumElements() != 1)
+ if (VT.isVector() && !VT.getVectorElementCount().isScalar())
return LLTCodeGen(
- LLT::vector(VT.getVectorNumElements(), VT.getScalarSizeInBits()));
+ LLT::vector(VT.getVectorElementCount(), VT.getScalarSizeInBits()));
if (VT.isInteger() || VT.isFloatingPoint())
return LLTCodeGen(LLT::scalar(VT.getSizeInBits()));
@@ -1562,6 +1575,40 @@ public:
}
};
+/// Generates code to check that this operand is an immediate whose value meets
+/// an immediate predicate.
+class OperandImmPredicateMatcher : public OperandPredicateMatcher {
+protected:
+ TreePredicateFn Predicate;
+
+public:
+ OperandImmPredicateMatcher(unsigned InsnVarID, unsigned OpIdx,
+ const TreePredicateFn &Predicate)
+ : OperandPredicateMatcher(IPM_ImmPredicate, InsnVarID, OpIdx),
+ Predicate(Predicate) {}
+
+ bool isIdentical(const PredicateMatcher &B) const override {
+ return OperandPredicateMatcher::isIdentical(B) &&
+ Predicate.getOrigPatFragRecord() ==
+ cast<OperandImmPredicateMatcher>(&B)
+ ->Predicate.getOrigPatFragRecord();
+ }
+
+ static bool classof(const PredicateMatcher *P) {
+ return P->getKind() == IPM_ImmPredicate;
+ }
+
+ void emitPredicateOpcodes(MatchTable &Table,
+ RuleMatcher &Rule) const override {
+ Table << MatchTable::Opcode("GIM_CheckImmOperandPredicate")
+ << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
+ << MatchTable::Comment("MO") << MatchTable::IntValue(OpIdx)
+ << MatchTable::Comment("Predicate")
+ << MatchTable::NamedValue(getEnumNameForPredicate(Predicate))
+ << MatchTable::LineBreak;
+ }
+};
+
/// Generates code to check that a set of predicates match for a particular
/// operand.
class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> {
@@ -1924,7 +1971,7 @@ public:
void emitPredicateOpcodes(MatchTable &Table,
RuleMatcher &Rule) const override {
- Table << MatchTable::Opcode(getMatchOpcodeForPredicate(Predicate))
+ Table << MatchTable::Opcode(getMatchOpcodeForImmPredicate(Predicate))
<< MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
<< MatchTable::Comment("Predicate")
<< MatchTable::NamedValue(getEnumNameForPredicate(Predicate))
@@ -3536,7 +3583,7 @@ private:
const CodeGenInstruction *getEquivNode(Record &Equiv,
const TreePatternNode *N) const;
- Error importRulePredicates(RuleMatcher &M, ArrayRef<Predicate> Predicates);
+ Error importRulePredicates(RuleMatcher &M, ArrayRef<Record *> Predicates);
Expected<InstructionMatcher &>
createAndImportSelDAGMatcher(RuleMatcher &Rule,
InstructionMatcher &InsnMatcher,
@@ -3623,6 +3670,10 @@ private:
Optional<const CodeGenRegisterClass *>
inferRegClassFromPattern(TreePatternNode *N);
+ /// Return the size of the MemoryVT in this predicate, if possible.
+ Optional<unsigned>
+ getMemSizeBitsFromPredicate(const TreePredicateFn &Predicate);
+
// Add builtin predicates.
Expected<InstructionMatcher &>
addBuiltinPredicates(const Record *SrcGIEquivOrNull,
@@ -3723,19 +3774,30 @@ GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)
//===- Emitter ------------------------------------------------------------===//
-Error
-GlobalISelEmitter::importRulePredicates(RuleMatcher &M,
- ArrayRef<Predicate> Predicates) {
- for (const Predicate &P : Predicates) {
- if (!P.Def || P.getCondString().empty())
+Error GlobalISelEmitter::importRulePredicates(RuleMatcher &M,
+ ArrayRef<Record *> Predicates) {
+ for (Record *Pred : Predicates) {
+ if (Pred->getValueAsString("CondString").empty())
continue;
- declareSubtargetFeature(P.Def);
- M.addRequiredFeature(P.Def);
+ declareSubtargetFeature(Pred);
+ M.addRequiredFeature(Pred);
}
return Error::success();
}
+Optional<unsigned> GlobalISelEmitter::getMemSizeBitsFromPredicate(const TreePredicateFn &Predicate) {
+ Optional<LLTCodeGen> MemTyOrNone =
+ MVTToLLT(getValueType(Predicate.getMemoryVT()));
+
+ if (!MemTyOrNone)
+ return None;
+
+ // Align so unusual types like i1 don't get rounded down.
+ return llvm::alignTo(
+ static_cast<unsigned>(MemTyOrNone->get().getSizeInBits()), 8);
+}
+
Expected<InstructionMatcher &> GlobalISelEmitter::addBuiltinPredicates(
const Record *SrcGIEquivOrNull, const TreePredicateFn &Predicate,
InstructionMatcher &InsnMatcher, bool &HasAddedMatcher) {
@@ -3775,9 +3837,18 @@ Expected<InstructionMatcher &> GlobalISelEmitter::addBuiltinPredicates(
if (Predicate.isStore()) {
if (Predicate.isTruncStore()) {
- // FIXME: If MemoryVT is set, we end up with 2 checks for the MMO size.
- InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>(
- 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0);
+ if (Predicate.getMemoryVT() != nullptr) {
+ // FIXME: If MemoryVT is set, we end up with 2 checks for the MMO size.
+ auto MemSizeInBits = getMemSizeBitsFromPredicate(Predicate);
+ if (!MemSizeInBits)
+ return failedImport("MemVT could not be converted to LLT");
+
+ InsnMatcher.addPredicate<MemorySizePredicateMatcher>(0, *MemSizeInBits /
+ 8);
+ } else {
+ InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>(
+ 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0);
+ }
return InsnMatcher;
}
if (Predicate.isNonTruncStore()) {
@@ -3804,19 +3875,12 @@ Expected<InstructionMatcher &> GlobalISelEmitter::addBuiltinPredicates(
if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) {
if (Predicate.getMemoryVT() != nullptr) {
- Optional<LLTCodeGen> MemTyOrNone =
- MVTToLLT(getValueType(Predicate.getMemoryVT()));
-
- if (!MemTyOrNone)
+ auto MemSizeInBits = getMemSizeBitsFromPredicate(Predicate);
+ if (!MemSizeInBits)
return failedImport("MemVT could not be converted to LLT");
- // MMO's work in bytes so we must take care of unusual types like i1
- // don't round down.
- unsigned MemSizeInBits =
- llvm::alignTo(MemTyOrNone->get().getSizeInBits(), 8);
-
InsnMatcher.addPredicate<MemorySizePredicateMatcher>(0,
- MemSizeInBits / 8);
+ *MemSizeInBits / 8);
return InsnMatcher;
}
}
@@ -4153,6 +4217,17 @@ Error GlobalISelEmitter::importChildMatcher(
}
if (SrcChild->getOperator()->getName() == "timm") {
OM.addPredicate<ImmOperandMatcher>();
+
+ // Add predicates, if any
+ for (const TreePredicateCall &Call : SrcChild->getPredicateCalls()) {
+ const TreePredicateFn &Predicate = Call.Fn;
+
+ // Only handle immediate patterns for now
+ if (Predicate.isImmediatePattern()) {
+ OM.addPredicate<OperandImmPredicateMatcher>(Predicate);
+ }
+ }
+
return Error::success();
}
}
@@ -4464,7 +4539,6 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
return failedImport(
"Dst pattern child def is an unsupported tablegen class");
}
-
return failedImport("Dst pattern child is an unsupported kind");
}
@@ -5043,7 +5117,9 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
" => " +
llvm::to_string(*P.getDstPattern()));
- if (auto Error = importRulePredicates(M, P.getPredicates()))
+ SmallVector<Record *, 4> Predicates;
+ P.getPredicateRecords(Predicates);
+ if (auto Error = importRulePredicates(M, Predicates))
return std::move(Error);
// Next, analyze the pattern operators.
@@ -5351,7 +5427,7 @@ void GlobalISelEmitter::emitCxxPredicateFns(
StringRef AdditionalDeclarations,
std::function<bool(const Record *R)> Filter) {
std::vector<const Record *> MatchedRecords;
- const auto &Defs = RK.getAllDerivedDefinitions("PatFrag");
+ const auto &Defs = RK.getAllDerivedDefinitions("PatFrags");
std::copy_if(Defs.begin(), Defs.end(), std::back_inserter(MatchedRecords),
[&](Record *Record) {
return !Record->getValueAsString(CodeFieldName).empty() &&
@@ -5595,9 +5671,17 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
RK.getAllDerivedDefinitions("GIComplexOperandMatcher");
llvm::sort(ComplexPredicates, orderByName);
- std::vector<Record *> CustomRendererFns =
- RK.getAllDerivedDefinitions("GICustomOperandRenderer");
- llvm::sort(CustomRendererFns, orderByName);
+ std::vector<StringRef> CustomRendererFns;
+ transform(RK.getAllDerivedDefinitions("GICustomOperandRenderer"),
+ std::back_inserter(CustomRendererFns), [](const auto &Record) {
+ return Record->getValueAsString("RendererFn");
+ });
+ // Sort and remove duplicates to get a list of unique renderer functions, in
+ // case some were mentioned more than once.
+ llvm::sort(CustomRendererFns);
+ CustomRendererFns.erase(
+ std::unique(CustomRendererFns.begin(), CustomRendererFns.end()),
+ CustomRendererFns.end());
unsigned MaxTemporaries = 0;
for (const auto &Rule : Rules)
@@ -5675,13 +5759,6 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
"(const " << Target.getName() << "Subtarget *)&MF.getSubtarget(), &MF);\n"
"}\n";
- if (Target.getName() == "X86" || Target.getName() == "AArch64") {
- // TODO: Implement PGSO.
- OS << "static bool shouldOptForSize(const MachineFunction *MF) {\n";
- OS << " return MF->getFunction().hasOptSize();\n";
- OS << "}\n\n";
- }
-
SubtargetFeatureInfo::emitComputeAvailableFeatures(
Target.getName(), "InstructionSelector",
"computeAvailableFunctionFeatures", FunctionFeatures, OS,
@@ -5791,17 +5868,15 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
OS << "// Custom renderers.\n"
<< "enum {\n"
<< " GICR_Invalid,\n";
- for (const auto &Record : CustomRendererFns)
- OS << " GICR_" << Record->getValueAsString("RendererFn") << ",\n";
+ for (const auto &Fn : CustomRendererFns)
+ OS << " GICR_" << Fn << ",\n";
OS << "};\n";
OS << Target.getName() << "InstructionSelector::CustomRendererFn\n"
<< Target.getName() << "InstructionSelector::CustomRenderers[] = {\n"
<< " nullptr, // GICR_Invalid\n";
- for (const auto &Record : CustomRendererFns)
- OS << " &" << Target.getName()
- << "InstructionSelector::" << Record->getValueAsString("RendererFn")
- << ", // " << Record->getName() << "\n";
+ for (const auto &Fn : CustomRendererFns)
+ OS << " &" << Target.getName() << "InstructionSelector::" << Fn << ",\n";
OS << "};\n\n";
llvm::stable_sort(Rules, [&](const RuleMatcher &A, const RuleMatcher &B) {
diff --git a/llvm/utils/TableGen/InfoByHwMode.cpp b/llvm/utils/TableGen/InfoByHwMode.cpp
index 7cd1b0f08132..3d236b828032 100644
--- a/llvm/utils/TableGen/InfoByHwMode.cpp
+++ b/llvm/utils/TableGen/InfoByHwMode.cpp
@@ -91,13 +91,10 @@ void ValueTypeByHwMode::writeToStream(raw_ostream &OS) const {
llvm::sort(Pairs, deref<std::less<PairType>>());
OS << '{';
- for (unsigned i = 0, e = Pairs.size(); i != e; ++i) {
- const PairType *P = Pairs[i];
- OS << '(' << getModeName(P->first)
- << ':' << getMVTName(P->second).str() << ')';
- if (i != e-1)
- OS << ',';
- }
+ ListSeparator LS(",");
+ for (const PairType *P : Pairs)
+ OS << LS << '(' << getModeName(P->first) << ':'
+ << getMVTName(P->second).str() << ')';
OS << '}';
}
@@ -183,12 +180,9 @@ void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const {
llvm::sort(Pairs, deref<std::less<PairType>>());
OS << '{';
- for (unsigned i = 0, e = Pairs.size(); i != e; ++i) {
- const PairType *P = Pairs[i];
- OS << '(' << getModeName(P->first) << ':' << P->second << ')';
- if (i != e-1)
- OS << ',';
- }
+ ListSeparator LS(",");
+ for (const PairType *P : Pairs)
+ OS << LS << '(' << getModeName(P->first) << ':' << P->second << ')';
OS << '}';
}
diff --git a/llvm/utils/TableGen/InfoByHwMode.h b/llvm/utils/TableGen/InfoByHwMode.h
index d92e5901a7f3..c97add687ca2 100644
--- a/llvm/utils/TableGen/InfoByHwMode.h
+++ b/llvm/utils/TableGen/InfoByHwMode.h
@@ -15,10 +15,10 @@
#define LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H
#include "CodeGenHwModes.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/MachineValueType.h"
#include <map>
-#include <set>
#include <string>
#include <vector>
@@ -37,10 +37,10 @@ enum : unsigned {
};
template <typename InfoT>
-std::vector<unsigned> union_modes(const InfoByHwMode<InfoT> &A,
- const InfoByHwMode<InfoT> &B) {
- std::vector<unsigned> V;
- std::set<unsigned> U;
+void union_modes(const InfoByHwMode<InfoT> &A,
+ const InfoByHwMode<InfoT> &B,
+ SmallVectorImpl<unsigned> &Modes) {
+ SmallSet<unsigned, 4> U;
for (const auto &P : A)
U.insert(P.first);
for (const auto &P : B)
@@ -49,12 +49,11 @@ std::vector<unsigned> union_modes(const InfoByHwMode<InfoT> &A,
bool HasDefault = false;
for (unsigned M : U)
if (M != DefaultMode)
- V.push_back(M);
+ Modes.push_back(M);
else
HasDefault = true;
if (HasDefault)
- V.push_back(DefaultMode);
- return V;
+ Modes.push_back(DefaultMode);
}
template <typename InfoT>
@@ -114,6 +113,7 @@ struct InfoByHwMode {
Map.insert(std::make_pair(DefaultMode, I));
}
+protected:
MapType Map;
};
@@ -178,6 +178,10 @@ struct RegSizeInfoByHwMode : public InfoByHwMode<RegSizeInfo> {
bool hasStricterSpillThan(const RegSizeInfoByHwMode &I) const;
void writeToStream(raw_ostream &OS) const;
+
+ void insertRegSizeForMode(unsigned Mode, RegSizeInfo Info) {
+ Map.insert(std::make_pair(Mode, Info));
+ }
};
raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T);
diff --git a/llvm/utils/TableGen/InstrDocsEmitter.cpp b/llvm/utils/TableGen/InstrDocsEmitter.cpp
index 66744bf9ecef..bc391227edd1 100644
--- a/llvm/utils/TableGen/InstrDocsEmitter.cpp
+++ b/llvm/utils/TableGen/InstrDocsEmitter.cpp
@@ -141,13 +141,9 @@ void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
FLAG(isAuthenticated)
if (!FlagStrings.empty()) {
OS << "Flags: ";
- bool IsFirst = true;
- for (auto FlagString : FlagStrings) {
- if (!IsFirst)
- OS << ", ";
- OS << "``" << FlagString << "``";
- IsFirst = false;
- }
+ ListSeparator LS;
+ for (auto FlagString : FlagStrings)
+ OS << LS << "``" << FlagString << "``";
OS << "\n\n";
}
@@ -192,26 +188,18 @@ void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
// Implicit definitions.
if (!II->ImplicitDefs.empty()) {
OS << "Implicit defs: ";
- bool IsFirst = true;
- for (Record *Def : II->ImplicitDefs) {
- if (!IsFirst)
- OS << ", ";
- OS << "``" << Def->getName() << "``";
- IsFirst = false;
- }
+ ListSeparator LS;
+ for (Record *Def : II->ImplicitDefs)
+ OS << LS << "``" << Def->getName() << "``";
OS << "\n\n";
}
// Implicit uses.
if (!II->ImplicitUses.empty()) {
OS << "Implicit uses: ";
- bool IsFirst = true;
- for (Record *Use : II->ImplicitUses) {
- if (!IsFirst)
- OS << ", ";
- OS << "``" << Use->getName() << "``";
- IsFirst = false;
- }
+ ListSeparator LS;
+ for (Record *Use : II->ImplicitUses)
+ OS << LS << "``" << Use->getName() << "``";
OS << "\n\n";
}
@@ -220,13 +208,9 @@ void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
II->TheDef->getValueAsListOfDefs("Predicates");
if (!Predicates.empty()) {
OS << "Predicates: ";
- bool IsFirst = true;
- for (Record *P : Predicates) {
- if (!IsFirst)
- OS << ", ";
- OS << "``" << P->getName() << "``";
- IsFirst = false;
- }
+ ListSeparator LS;
+ for (Record *P : Predicates)
+ OS << LS << "``" << P->getName() << "``";
OS << "\n\n";
}
}
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index 9ff385faec56..aee887a906e5 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -19,6 +19,7 @@
#include "SequenceToOffsetTable.h"
#include "TableGenBackends.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
@@ -27,6 +28,7 @@
#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
#include <cstdint>
+#include <iterator>
#include <map>
#include <string>
#include <utility>
@@ -87,6 +89,13 @@ private:
void emitOperandNameMappings(raw_ostream &OS, const CodeGenTarget &Target,
ArrayRef<const CodeGenInstruction*> NumberedInstructions);
+ void emitLogicalOperandSizeMappings(
+ raw_ostream &OS, StringRef Namespace,
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions);
+ void emitLogicalOperandTypeMappings(
+ raw_ostream &OS, StringRef Namespace,
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions);
+
// Operand information.
void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst);
@@ -442,6 +451,182 @@ void InstrInfoEmitter::emitOperandTypeMappings(
OS << "#endif // GET_INSTRINFO_OPERAND_TYPE\n\n";
}
+void InstrInfoEmitter::emitLogicalOperandSizeMappings(
+ raw_ostream &OS, StringRef Namespace,
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
+ std::map<std::vector<unsigned>, unsigned> LogicalOpSizeMap;
+
+ std::map<unsigned, std::vector<std::string>> InstMap;
+
+ size_t LogicalOpListSize = 0U;
+ std::vector<unsigned> LogicalOpList;
+ for (const auto *Inst : NumberedInstructions) {
+ if (!Inst->TheDef->getValueAsBit("UseLogicalOperandMappings"))
+ continue;
+
+ LogicalOpList.clear();
+ llvm::transform(Inst->Operands, std::back_inserter(LogicalOpList),
+ [](const CGIOperandList::OperandInfo &Op) -> unsigned {
+ auto *MIOI = Op.MIOperandInfo;
+ if (!MIOI || MIOI->getNumArgs() == 0)
+ return 1;
+ return MIOI->getNumArgs();
+ });
+ LogicalOpListSize = std::max(LogicalOpList.size(), LogicalOpListSize);
+
+ auto I =
+ LogicalOpSizeMap.insert({LogicalOpList, LogicalOpSizeMap.size()}).first;
+ InstMap[I->second].push_back(
+ (Namespace + "::" + Inst->TheDef->getName()).str());
+ }
+
+ OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n";
+ OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n";
+ OS << "namespace llvm {\n";
+ OS << "namespace " << Namespace << " {\n";
+ OS << "LLVM_READONLY static unsigned\n";
+ OS << "getLogicalOperandSize(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";
+ if (!InstMap.empty()) {
+ std::vector<const std::vector<unsigned> *> LogicalOpSizeList(
+ LogicalOpSizeMap.size());
+ for (auto &P : LogicalOpSizeMap) {
+ LogicalOpSizeList[P.second] = &P.first;
+ }
+ OS << " static const unsigned SizeMap[][" << LogicalOpListSize
+ << "] = {\n";
+ for (auto &R : LogicalOpSizeList) {
+ const auto &Row = *R;
+ OS << " {";
+ int i;
+ for (i = 0; i < static_cast<int>(Row.size()); ++i) {
+ OS << Row[i] << ", ";
+ }
+ for (; i < static_cast<int>(LogicalOpListSize); ++i) {
+ OS << "0, ";
+ }
+ OS << "}, ";
+ OS << "\n";
+ }
+ OS << " };\n";
+
+ OS << " switch (Opcode) {\n";
+ OS << " default: return LogicalOpIdx;\n";
+ for (auto &P : InstMap) {
+ auto OpMapIdx = P.first;
+ const auto &Insts = P.second;
+ for (const auto &Inst : Insts) {
+ OS << " case " << Inst << ":\n";
+ }
+ OS << " return SizeMap[" << OpMapIdx << "][LogicalOpIdx];\n";
+ }
+ OS << " }\n";
+ } else {
+ OS << " return LogicalOpIdx;\n";
+ }
+ OS << "}\n";
+
+ OS << "LLVM_READONLY static inline unsigned\n";
+ OS << "getLogicalOperandIdx(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";
+ OS << " auto S = 0U;\n";
+ OS << " for (auto i = 0U; i < LogicalOpIdx; ++i)\n";
+ OS << " S += getLogicalOperandSize(Opcode, i);\n";
+ OS << " return S;\n";
+ OS << "}\n";
+
+ OS << "} // end namespace " << Namespace << "\n";
+ OS << "} // end namespace llvm\n";
+ OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n\n";
+}
+
+void InstrInfoEmitter::emitLogicalOperandTypeMappings(
+ raw_ostream &OS, StringRef Namespace,
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
+ std::map<std::vector<std::string>, unsigned> LogicalOpTypeMap;
+
+ std::map<unsigned, std::vector<std::string>> InstMap;
+
+ size_t OpTypeListSize = 0U;
+ std::vector<std::string> LogicalOpTypeList;
+ for (const auto *Inst : NumberedInstructions) {
+ if (!Inst->TheDef->getValueAsBit("UseLogicalOperandMappings"))
+ continue;
+
+ LogicalOpTypeList.clear();
+ for (const auto &Op : Inst->Operands) {
+ auto *OpR = Op.Rec;
+ if ((OpR->isSubClassOf("Operand") ||
+ OpR->isSubClassOf("RegisterOperand") ||
+ OpR->isSubClassOf("RegisterClass")) &&
+ !OpR->isAnonymous()) {
+ LogicalOpTypeList.push_back(
+ (Namespace + "::OpTypes::" + Op.Rec->getName()).str());
+ } else {
+ LogicalOpTypeList.push_back("-1");
+ }
+ }
+ OpTypeListSize = std::max(LogicalOpTypeList.size(), OpTypeListSize);
+
+ auto I =
+ LogicalOpTypeMap.insert({LogicalOpTypeList, LogicalOpTypeMap.size()})
+ .first;
+ InstMap[I->second].push_back(
+ (Namespace + "::" + Inst->TheDef->getName()).str());
+ }
+
+ OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n";
+ OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n";
+ OS << "namespace llvm {\n";
+ OS << "namespace " << Namespace << " {\n";
+ OS << "LLVM_READONLY static int\n";
+ OS << "getLogicalOperandType(uint16_t Opcode, uint16_t LogicalOpIdx) {\n";
+ if (!InstMap.empty()) {
+ std::vector<const std::vector<std::string> *> LogicalOpTypeList(
+ LogicalOpTypeMap.size());
+ for (auto &P : LogicalOpTypeMap) {
+ LogicalOpTypeList[P.second] = &P.first;
+ }
+ OS << " static const int TypeMap[][" << OpTypeListSize << "] = {\n";
+ for (int r = 0, rs = LogicalOpTypeList.size(); r < rs; ++r) {
+ const auto &Row = *LogicalOpTypeList[r];
+ OS << " {";
+ int i, s = Row.size();
+ for (i = 0; i < s; ++i) {
+ if (i > 0)
+ OS << ", ";
+ OS << Row[i];
+ }
+ for (; i < static_cast<int>(OpTypeListSize); ++i) {
+ if (i > 0)
+ OS << ", ";
+ OS << "-1";
+ }
+ OS << "}";
+ if (r != rs - 1)
+ OS << ",";
+ OS << "\n";
+ }
+ OS << " };\n";
+
+ OS << " switch (Opcode) {\n";
+ OS << " default: return -1;\n";
+ for (auto &P : InstMap) {
+ auto OpMapIdx = P.first;
+ const auto &Insts = P.second;
+ for (const auto &Inst : Insts) {
+ OS << " case " << Inst << ":\n";
+ }
+ OS << " return TypeMap[" << OpMapIdx << "][LogicalOpIdx];\n";
+ }
+ OS << " }\n";
+ } else {
+ OS << " return -1;\n";
+ }
+ OS << "}\n";
+ OS << "} // end namespace " << Namespace << "\n";
+ OS << "} // end namespace llvm\n";
+ OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n\n";
+}
+
void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS,
StringRef TargetName) {
RecVec TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate");
@@ -726,6 +911,12 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
Records.startTimer("Emit operand type mappings");
emitOperandTypeMappings(OS, Target, NumberedInstructions);
+ Records.startTimer("Emit logical operand size mappings");
+ emitLogicalOperandSizeMappings(OS, TargetName, NumberedInstructions);
+
+ Records.startTimer("Emit logical operand type mappings");
+ emitLogicalOperandTypeMappings(OS, TargetName, NumberedInstructions);
+
Records.startTimer("Emit helper methods");
emitMCIIHelperMethods(OS, TargetName);
}
diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp
index 4be0d90a45d2..3d1d258e342e 100644
--- a/llvm/utils/TableGen/IntrinsicEmitter.cpp
+++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -378,7 +378,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
MVT VVT = VT;
if (VVT.isScalableVector())
Sig.push_back(IIT_SCALABLE_VEC);
- switch (VVT.getVectorNumElements()) {
+ switch (VVT.getVectorMinNumElements()) {
default: PrintFatalError("unhandled vector type width in intrinsic!");
case 1: Sig.push_back(IIT_V1); break;
case 2: Sig.push_back(IIT_V2); break;
@@ -584,6 +584,9 @@ struct AttributeComparator {
if (L->isNoDuplicate != R->isNoDuplicate)
return R->isNoDuplicate;
+ if (L->isNoMerge != R->isNoMerge)
+ return R->isNoMerge;
+
if (L->isNoReturn != R->isNoReturn)
return R->isNoReturn;
@@ -638,13 +641,13 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size()));
unsigned &N = UniqAttributes[&intrinsic];
if (N) continue;
- assert(AttrNum < 256 && "Too many unique attributes for table!");
N = ++AttrNum;
+ assert(N < 65536 && "Too many unique attributes for table!");
}
// Emit an array of AttributeList. Most intrinsics will have at least one
// entry, for the function itself (index ~1), which is usually nounwind.
- OS << " static const uint8_t IntrinsicsToAttributesMap[] = {\n";
+ OS << " static const uint16_t IntrinsicsToAttributesMap[] = {\n";
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
const CodeGenIntrinsic &intrinsic = Ints[i];
@@ -659,240 +662,165 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
OS << " if (id != 0) {\n";
OS << " switch(IntrinsicsToAttributesMap[id - 1]) {\n";
OS << " default: llvm_unreachable(\"Invalid attribute number\");\n";
- for (UniqAttrMapTy::const_iterator I = UniqAttributes.begin(),
- E = UniqAttributes.end(); I != E; ++I) {
- OS << " case " << I->second << ": {\n";
+ for (auto UniqAttribute : UniqAttributes) {
+ OS << " case " << UniqAttribute.second << ": {\n";
- const CodeGenIntrinsic &intrinsic = *(I->first);
+ const CodeGenIntrinsic &Intrinsic = *(UniqAttribute.first);
// Keep track of the number of attributes we're writing out.
unsigned numAttrs = 0;
// The argument attributes are alreadys sorted by argument index.
- unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size();
- if (ae) {
- while (ai != ae) {
- unsigned attrIdx = intrinsic.ArgumentAttributes[ai].Index;
+ unsigned Ai = 0, Ae = Intrinsic.ArgumentAttributes.size();
+ if (Ae) {
+ while (Ai != Ae) {
+ unsigned AttrIdx = Intrinsic.ArgumentAttributes[Ai].Index;
- OS << " const Attribute::AttrKind AttrParam" << attrIdx << "[]= {";
- bool addComma = false;
+ OS << " const Attribute::AttrKind AttrParam" << AttrIdx << "[]= {";
+ ListSeparator LS(",");
bool AllValuesAreZero = true;
SmallVector<uint64_t, 8> Values;
do {
- switch (intrinsic.ArgumentAttributes[ai].Kind) {
+ switch (Intrinsic.ArgumentAttributes[Ai].Kind) {
case CodeGenIntrinsic::NoCapture:
- if (addComma)
- OS << ",";
- OS << "Attribute::NoCapture";
- addComma = true;
+ OS << LS << "Attribute::NoCapture";
break;
case CodeGenIntrinsic::NoAlias:
- if (addComma)
- OS << ",";
- OS << "Attribute::NoAlias";
- addComma = true;
+ OS << LS << "Attribute::NoAlias";
break;
case CodeGenIntrinsic::NoUndef:
- if (addComma)
- OS << ",";
- OS << "Attribute::NoUndef";
- addComma = true;
+ OS << LS << "Attribute::NoUndef";
break;
case CodeGenIntrinsic::Returned:
- if (addComma)
- OS << ",";
- OS << "Attribute::Returned";
- addComma = true;
+ OS << LS << "Attribute::Returned";
break;
case CodeGenIntrinsic::ReadOnly:
- if (addComma)
- OS << ",";
- OS << "Attribute::ReadOnly";
- addComma = true;
+ OS << LS << "Attribute::ReadOnly";
break;
case CodeGenIntrinsic::WriteOnly:
- if (addComma)
- OS << ",";
- OS << "Attribute::WriteOnly";
- addComma = true;
+ OS << LS << "Attribute::WriteOnly";
break;
case CodeGenIntrinsic::ReadNone:
- if (addComma)
- OS << ",";
- OS << "Attribute::ReadNone";
- addComma = true;
+ OS << LS << "Attribute::ReadNone";
break;
case CodeGenIntrinsic::ImmArg:
- if (addComma)
- OS << ',';
- OS << "Attribute::ImmArg";
- addComma = true;
+ OS << LS << "Attribute::ImmArg";
break;
case CodeGenIntrinsic::Alignment:
- if (addComma)
- OS << ',';
- OS << "Attribute::Alignment";
- addComma = true;
+ OS << LS << "Attribute::Alignment";
break;
}
- uint64_t V = intrinsic.ArgumentAttributes[ai].Value;
+ uint64_t V = Intrinsic.ArgumentAttributes[Ai].Value;
Values.push_back(V);
AllValuesAreZero &= (V == 0);
- ++ai;
- } while (ai != ae && intrinsic.ArgumentAttributes[ai].Index == attrIdx);
+ ++Ai;
+ } while (Ai != Ae && Intrinsic.ArgumentAttributes[Ai].Index == AttrIdx);
OS << "};\n";
// Generate attribute value array if not all attribute values are zero.
if (!AllValuesAreZero) {
- OS << " const uint64_t AttrValParam" << attrIdx << "[]= {";
- addComma = false;
- for (const auto V : Values) {
- if (addComma)
- OS << ',';
- OS << V;
- addComma = true;
- }
+ OS << " const uint64_t AttrValParam" << AttrIdx << "[]= {";
+ ListSeparator LSV(",");
+ for (const auto V : Values)
+ OS << LSV << V;
OS << "};\n";
}
OS << " AS[" << numAttrs++ << "] = AttributeList::get(C, "
- << attrIdx << ", AttrParam" << attrIdx;
+ << AttrIdx << ", AttrParam" << AttrIdx;
if (!AllValuesAreZero)
- OS << ", AttrValParam" << attrIdx;
+ OS << ", AttrValParam" << AttrIdx;
OS << ");\n";
}
}
- if (!intrinsic.canThrow ||
- (intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem &&
- !intrinsic.hasSideEffects) ||
- intrinsic.isNoReturn || intrinsic.isNoSync || intrinsic.isNoFree ||
- intrinsic.isWillReturn || intrinsic.isCold || intrinsic.isNoDuplicate ||
- intrinsic.isConvergent || intrinsic.isSpeculatable) {
+ if (!Intrinsic.canThrow ||
+ (Intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem &&
+ !Intrinsic.hasSideEffects) ||
+ Intrinsic.isNoReturn || Intrinsic.isNoSync || Intrinsic.isNoFree ||
+ Intrinsic.isWillReturn || Intrinsic.isCold || Intrinsic.isNoDuplicate ||
+ Intrinsic.isNoMerge || Intrinsic.isConvergent ||
+ Intrinsic.isSpeculatable) {
OS << " const Attribute::AttrKind Atts[] = {";
- bool addComma = false;
- if (!intrinsic.canThrow) {
- OS << "Attribute::NoUnwind";
- addComma = true;
- }
- if (intrinsic.isNoReturn) {
- if (addComma)
- OS << ",";
- OS << "Attribute::NoReturn";
- addComma = true;
- }
- if (intrinsic.isNoSync) {
- if (addComma)
- OS << ",";
- OS << "Attribute::NoSync";
- addComma = true;
- }
- if (intrinsic.isNoFree) {
- if (addComma)
- OS << ",";
- OS << "Attribute::NoFree";
- addComma = true;
- }
- if (intrinsic.isWillReturn) {
- if (addComma)
- OS << ",";
- OS << "Attribute::WillReturn";
- addComma = true;
- }
- if (intrinsic.isCold) {
- if (addComma)
- OS << ",";
- OS << "Attribute::Cold";
- addComma = true;
- }
- if (intrinsic.isNoDuplicate) {
- if (addComma)
- OS << ",";
- OS << "Attribute::NoDuplicate";
- addComma = true;
- }
- if (intrinsic.isConvergent) {
- if (addComma)
- OS << ",";
- OS << "Attribute::Convergent";
- addComma = true;
- }
- if (intrinsic.isSpeculatable) {
- if (addComma)
- OS << ",";
- OS << "Attribute::Speculatable";
- addComma = true;
- }
+ ListSeparator LS(",");
+ if (!Intrinsic.canThrow)
+ OS << LS << "Attribute::NoUnwind";
+ if (Intrinsic.isNoReturn)
+ OS << LS << "Attribute::NoReturn";
+ if (Intrinsic.isNoSync)
+ OS << LS << "Attribute::NoSync";
+ if (Intrinsic.isNoFree)
+ OS << LS << "Attribute::NoFree";
+ if (Intrinsic.isWillReturn)
+ OS << LS << "Attribute::WillReturn";
+ if (Intrinsic.isCold)
+ OS << LS << "Attribute::Cold";
+ if (Intrinsic.isNoDuplicate)
+ OS << LS << "Attribute::NoDuplicate";
+ if (Intrinsic.isNoMerge)
+ OS << LS << "Attribute::NoMerge";
+ if (Intrinsic.isConvergent)
+ OS << LS << "Attribute::Convergent";
+ if (Intrinsic.isSpeculatable)
+ OS << LS << "Attribute::Speculatable";
- switch (intrinsic.ModRef) {
+ switch (Intrinsic.ModRef) {
case CodeGenIntrinsic::NoMem:
- if (intrinsic.hasSideEffects)
+ if (Intrinsic.hasSideEffects)
break;
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::ReadNone";
break;
case CodeGenIntrinsic::ReadArgMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::ReadOnly,";
OS << "Attribute::ArgMemOnly";
break;
case CodeGenIntrinsic::ReadMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::ReadOnly";
break;
case CodeGenIntrinsic::ReadInaccessibleMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::ReadOnly,";
OS << "Attribute::InaccessibleMemOnly";
break;
case CodeGenIntrinsic::ReadInaccessibleMemOrArgMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::ReadOnly,";
OS << "Attribute::InaccessibleMemOrArgMemOnly";
break;
case CodeGenIntrinsic::WriteArgMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::WriteOnly,";
OS << "Attribute::ArgMemOnly";
break;
case CodeGenIntrinsic::WriteMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::WriteOnly";
break;
case CodeGenIntrinsic::WriteInaccessibleMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::WriteOnly,";
OS << "Attribute::InaccessibleMemOnly";
break;
case CodeGenIntrinsic::WriteInaccessibleMemOrArgMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::WriteOnly,";
OS << "Attribute::InaccessibleMemOrArgMemOnly";
break;
case CodeGenIntrinsic::ReadWriteArgMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::ArgMemOnly";
break;
case CodeGenIntrinsic::ReadWriteInaccessibleMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::InaccessibleMemOnly";
break;
case CodeGenIntrinsic::ReadWriteInaccessibleMemOrArgMem:
- if (addComma)
- OS << ",";
+ OS << LS;
OS << "Attribute::InaccessibleMemOrArgMemOnly";
break;
case CodeGenIntrinsic::ReadWriteMem:
@@ -977,25 +905,25 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n";
// Note: this could emit significantly better code if we cared.
- for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
+ for (auto &I : BuiltinMap) {
OS << " ";
- if (!I->first.empty())
- OS << "if (TargetPrefix == \"" << I->first << "\") ";
+ if (!I.first.empty())
+ OS << "if (TargetPrefix == \"" << I.first << "\") ";
else
OS << "/* Target Independent Builtins */ ";
OS << "{\n";
// Emit the comparisons for this target prefix.
- OS << " static const BuiltinEntry " << I->first << "Names[] = {\n";
- for (const auto &P : I->second) {
+ OS << " static const BuiltinEntry " << I.first << "Names[] = {\n";
+ for (const auto &P : I.second) {
OS << " {Intrinsic::" << P.second << ", "
<< Table.GetOrAddStringOffset(P.first) << "}, // " << P.first << "\n";
}
OS << " };\n";
- OS << " auto I = std::lower_bound(std::begin(" << I->first << "Names),\n";
- OS << " std::end(" << I->first << "Names),\n";
+ OS << " auto I = std::lower_bound(std::begin(" << I.first << "Names),\n";
+ OS << " std::end(" << I.first << "Names),\n";
OS << " BuiltinNameStr);\n";
- OS << " if (I != std::end(" << I->first << "Names) &&\n";
+ OS << " if (I != std::end(" << I.first << "Names) &&\n";
OS << " I->getName() == BuiltinNameStr)\n";
OS << " return I->IntrinID;\n";
OS << " }\n";
diff --git a/llvm/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp
index 8e6c05885e5b..0809432dfd0d 100644
--- a/llvm/utils/TableGen/OptParserEmitter.cpp
+++ b/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -251,7 +251,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
// Prefix values.
OS << ", {";
- for (StringRef PrefixKey : Prefix.first)
+ for (const auto &PrefixKey : Prefix.first)
OS << "\"" << PrefixKey << "\" COMMA ";
OS << "nullptr})\n";
}
diff --git a/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
index e05409db67d0..6acb630299c1 100644
--- a/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
+++ b/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
@@ -108,6 +108,11 @@ addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
OperandMap[BaseIdx + i].Kind = OpData::Imm;
OperandMap[BaseIdx + i].Data.Imm = II->getValue();
++OpsAdded;
+ } else if (auto *BI = dyn_cast<BitsInit>(Dag->getArg(i))) {
+ auto *II = cast<IntInit>(BI->convertInitializerTo(IntRecTy::get()));
+ OperandMap[BaseIdx + i].Kind = OpData::Imm;
+ OperandMap[BaseIdx + i].Data.Imm = II->getValue();
+ ++OpsAdded;
} else if (DagInit *SubDag = dyn_cast<DagInit>(Dag->getArg(i))) {
// Just add the operands recursively. This is almost certainly
// a constant value for a complex operand (> 1 MI operand).
diff --git a/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp b/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp
index 183c8f9494db..e931801f82a4 100644
--- a/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp
+++ b/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp
@@ -273,8 +273,8 @@ static bool verifyDagOpCount(CodeGenInstruction &Inst, DagInit *Dag,
// The Instruction might have tied operands so the Dag might have
// a fewer operand count.
unsigned RealCount = Inst.Operands.size();
- for (unsigned i = 0; i < Inst.Operands.size(); i++)
- if (Inst.Operands[i].getTiedRegister() != -1)
+ for (const auto &Operand : Inst.Operands)
+ if (Operand.getTiedRegister() != -1)
--RealCount;
if (Dag->getNumArgs() != RealCount)
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index dce7594dec2f..037fad207ac7 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -305,9 +305,8 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) {
ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(i);
PSets[i].reserve(PSetIDs.size());
- for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(),
- PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) {
- PSets[i].push_back(RegBank.getRegPressureSet(*PSetI).Order);
+ for (unsigned PSetID : PSetIDs) {
+ PSets[i].push_back(RegBank.getRegPressureSet(PSetID).Order);
}
llvm::sort(PSets[i]);
PSetsSeqs.add(PSets[i]);
@@ -399,11 +398,9 @@ void RegisterInfoEmitter::EmitRegMappingTables(
return;
// Now we know maximal length of number list. Append -1's, where needed
- for (DwarfRegNumsVecTy::iterator I = DwarfRegNums.begin(),
- E = DwarfRegNums.end();
- I != E; ++I)
- for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
- I->second.push_back(-1);
+ for (auto &DwarfRegNum : DwarfRegNums)
+ for (unsigned I = DwarfRegNum.second.size(), E = maxLength; I != E; ++I)
+ DwarfRegNum.second.push_back(-1);
StringRef Namespace = Regs.front().TheDef->getValueAsString("Namespace");
@@ -411,10 +408,10 @@ void RegisterInfoEmitter::EmitRegMappingTables(
// Emit reverse information about the dwarf register numbers.
for (unsigned j = 0; j < 2; ++j) {
- for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ for (unsigned I = 0, E = maxLength; I != E; ++I) {
OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace;
OS << (j == 0 ? "DwarfFlavour" : "EHFlavour");
- OS << i << "Dwarf2L[]";
+ OS << I << "Dwarf2L[]";
if (!isCtor) {
OS << " = {\n";
@@ -422,17 +419,15 @@ void RegisterInfoEmitter::EmitRegMappingTables(
// Store the mapping sorted by the LLVM reg num so lookup can be done
// with a binary search.
std::map<uint64_t, Record*> Dwarf2LMap;
- for (DwarfRegNumsVecTy::iterator
- I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
- int DwarfRegNo = I->second[i];
+ for (auto &DwarfRegNum : DwarfRegNums) {
+ int DwarfRegNo = DwarfRegNum.second[I];
if (DwarfRegNo < 0)
continue;
- Dwarf2LMap[DwarfRegNo] = I->first;
+ Dwarf2LMap[DwarfRegNo] = DwarfRegNum.first;
}
- for (std::map<uint64_t, Record*>::iterator
- I = Dwarf2LMap.begin(), E = Dwarf2LMap.end(); I != E; ++I)
- OS << " { " << I->first << "U, " << getQualifiedName(I->second)
+ for (auto &I : Dwarf2LMap)
+ OS << " { " << I.first << "U, " << getQualifiedName(I.second)
<< " },\n";
OS << "};\n";
@@ -443,11 +438,10 @@ void RegisterInfoEmitter::EmitRegMappingTables(
// We have to store the size in a const global, it's used in multiple
// places.
OS << "extern const unsigned " << Namespace
- << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize";
+ << (j == 0 ? "DwarfFlavour" : "EHFlavour") << I << "Dwarf2LSize";
if (!isCtor)
OS << " = array_lengthof(" << Namespace
- << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
- << "Dwarf2L);\n\n";
+ << (j == 0 ? "DwarfFlavour" : "EHFlavour") << I << "Dwarf2L);\n\n";
else
OS << ";\n\n";
}
@@ -486,13 +480,12 @@ void RegisterInfoEmitter::EmitRegMappingTables(
OS << " = {\n";
// Store the mapping sorted by the Dwarf reg num so lookup can be done
// with a binary search.
- for (DwarfRegNumsVecTy::iterator
- I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
- int RegNo = I->second[i];
+ for (auto &DwarfRegNum : DwarfRegNums) {
+ int RegNo = DwarfRegNum.second[i];
if (RegNo == -1) // -1 is the default value, don't emit a mapping.
continue;
- OS << " { " << getQualifiedName(I->first) << ", " << RegNo
+ OS << " { " << getQualifiedName(DwarfRegNum.first) << ", " << RegNo
<< "U },\n";
}
OS << "};\n";
@@ -1029,9 +1022,10 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
ArrayRef<const CodeGenRegister*> Roots = RegBank.getRegUnit(i).getRoots();
assert(!Roots.empty() && "All regunits must have a root register.");
assert(Roots.size() <= 2 && "More than two roots not supported yet.");
- OS << " { " << getQualifiedName(Roots.front()->TheDef);
- for (unsigned r = 1; r != Roots.size(); ++r)
- OS << ", " << getQualifiedName(Roots[r]->TheDef);
+ OS << " { ";
+ ListSeparator LS;
+ for (const CodeGenRegister *R : Roots)
+ OS << LS << getQualifiedName(R->TheDef);
OS << " },\n";
}
OS << "};\n\n";
@@ -1083,12 +1077,15 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
for (const auto &RC : RegisterClasses) {
assert(isInt<8>(RC.CopyCost) && "Copy cost too large.");
+ uint32_t RegSize = 0;
+ if (RC.RSI.isSimple())
+ RegSize = RC.RSI.getSimple().RegSize;
OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, "
- << RegClassStrings.get(RC.getName()) << ", "
- << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), "
- << RC.getQualifiedName() + "RegClassID" << ", "
- << RC.CopyCost << ", "
- << ( RC.Allocatable ? "true" : "false" ) << " },\n";
+ << RegClassStrings.get(RC.getName()) << ", " << RC.getOrder().size()
+ << ", sizeof(" << RC.getName() << "Bits), "
+ << RC.getQualifiedName() + "RegClassID"
+ << ", " << RegSize << ", " << RC.CopyCost << ", "
+ << (RC.Allocatable ? "true" : "false") << " },\n";
}
OS << "};\n\n";
@@ -1441,19 +1438,52 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Emit extra information about registers.
const std::string &TargetName = std::string(Target.getName());
- OS << "\nstatic const TargetRegisterInfoDesc "
- << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n";
- OS << " { 0, false },\n";
-
const auto &Regs = RegBank.getRegisters();
+ unsigned NumRegCosts = 1;
+ for (const auto &Reg : Regs)
+ NumRegCosts = std::max((size_t)NumRegCosts, Reg.CostPerUse.size());
+
+ std::vector<unsigned> AllRegCostPerUse;
+ llvm::BitVector InAllocClass(Regs.size() + 1, false);
+ AllRegCostPerUse.insert(AllRegCostPerUse.end(), NumRegCosts, 0);
+
+ // Populate the vector RegCosts with the CostPerUse list of the registers
+ // in the order they are read. Have at most NumRegCosts entries for
+ // each register. Fill with zero for values which are not explicitly given.
for (const auto &Reg : Regs) {
- OS << " { ";
- OS << Reg.CostPerUse << ", "
- << ( AllocatableRegs.count(Reg.TheDef) != 0 ? "true" : "false" )
- << " },\n";
+ auto Costs = Reg.CostPerUse;
+ AllRegCostPerUse.insert(AllRegCostPerUse.end(), Costs.begin(), Costs.end());
+ if (NumRegCosts > Costs.size())
+ AllRegCostPerUse.insert(AllRegCostPerUse.end(),
+ NumRegCosts - Costs.size(), 0);
+
+ if (AllocatableRegs.count(Reg.TheDef))
+ InAllocClass.set(Reg.EnumValue);
}
- OS << "};\n"; // End of register descriptors...
+ // Emit the cost values as a 1D-array after grouping them by their indices,
+ // i.e. the costs for all registers corresponds to index 0, 1, 2, etc.
+ // Size of the emitted array should be NumRegCosts * (Regs.size() + 1).
+ OS << "\nstatic const uint8_t "
+ << "CostPerUseTable[] = { \n";
+ for (unsigned int I = 0; I < NumRegCosts; ++I) {
+ for (unsigned J = I, E = AllRegCostPerUse.size(); J < E; J += NumRegCosts)
+ OS << AllRegCostPerUse[J] << ", ";
+ }
+ OS << "};\n\n";
+
+ OS << "\nstatic const bool "
+ << "InAllocatableClassTable[] = { \n";
+ for (unsigned I = 0, E = InAllocClass.size(); I < E; ++I) {
+ OS << (InAllocClass[I] ? "true" : "false") << ", ";
+ }
+ OS << "};\n\n";
+
+ OS << "\nstatic const TargetRegisterInfoDesc " << TargetName
+ << "RegInfoDesc = { // Extra Descriptors\n";
+ OS << "CostPerUseTable, " << NumRegCosts << ", "
+ << "InAllocatableClassTable";
+ OS << "};\n\n"; // End of register descriptors...
std::string ClassName = Target.getName().str() + "GenRegisterInfo";
@@ -1513,10 +1543,11 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
EmitRegMappingTables(OS, Regs, true);
- OS << ClassName << "::\n" << ClassName
+ OS << ClassName << "::\n"
+ << ClassName
<< "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour,\n"
" unsigned PC, unsigned HwMode)\n"
- << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc"
+ << " : TargetRegisterInfo(&" << TargetName << "RegInfoDesc"
<< ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() << ",\n"
<< " SubRegIndexNameTable, SubRegIndexLaneMaskTable,\n"
<< " ";
@@ -1679,7 +1710,10 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) {
for (const CodeGenRegister &R : RegBank.getRegisters()) {
OS << "Register " << R.getName() << ":\n";
- OS << "\tCostPerUse: " << R.CostPerUse << '\n';
+ OS << "\tCostPerUse: ";
+ for (const auto &Cost : R.CostPerUse)
+ OS << Cost << " ";
+ OS << '\n';
OS << "\tCoveredBySubregs: " << R.CoveredBySubRegs << '\n';
OS << "\tHasDisjunctSubRegs: " << R.HasDisjunctSubRegs << '\n';
for (std::pair<CodeGenSubRegIndex*,CodeGenRegister*> P : R.getSubRegs()) {
diff --git a/llvm/utils/TableGen/SearchableTableEmitter.cpp b/llvm/utils/TableGen/SearchableTableEmitter.cpp
index 912d43b2caa1..7803848aafc4 100644
--- a/llvm/utils/TableGen/SearchableTableEmitter.cpp
+++ b/llvm/utils/TableGen/SearchableTableEmitter.cpp
@@ -348,17 +348,13 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
IndexRowsStorage.push_back(Entry.first);
OS << " { ";
- bool NeedComma = false;
+ ListSeparator LS;
for (const auto &Field : Index.Fields) {
- if (NeedComma)
- OS << ", ";
- NeedComma = true;
-
std::string Repr = primaryRepresentation(
Index.Loc, Field, Entry.first->getValueInit(Field.Name));
if (isa<StringRecTy>(Field.RecType))
Repr = StringRef(Repr).upper();
- OS << Repr;
+ OS << LS << Repr;
}
OS << ", " << Entry.second << " },\n";
}
@@ -414,13 +410,9 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
}
OS << " };\n";
OS << " KeyType Key = {";
- bool NeedComma = false;
+ ListSeparator LS;
for (const auto &Field : Index.Fields) {
- if (NeedComma)
- OS << ", ";
- NeedComma = true;
-
- OS << Field.Name;
+ OS << LS << Field.Name;
if (isa<StringRecTy>(Field.RecType)) {
OS << ".upper()";
if (IsPrimary)
@@ -482,15 +474,10 @@ void SearchableTableEmitter::emitLookupDeclaration(const GenericTable &Table,
raw_ostream &OS) {
OS << "const " << Table.CppTypeName << " *" << Index.Name << "(";
- bool NeedComma = false;
- for (const auto &Field : Index.Fields) {
- if (NeedComma)
- OS << ", ";
- NeedComma = true;
-
- OS << searchableFieldType(Table, Index, Field, TypeInArgument) << " "
+ ListSeparator LS;
+ for (const auto &Field : Index.Fields)
+ OS << LS << searchableFieldType(Table, Index, Field, TypeInArgument) << " "
<< Field.Name;
- }
OS << ")";
}
@@ -518,15 +505,11 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
Record *Entry = Table.Entries[i];
OS << " { ";
- bool NeedComma = false;
- for (const auto &Field : Table.Fields) {
- if (NeedComma)
- OS << ", ";
- NeedComma = true;
-
- OS << primaryRepresentation(Table.Locs[0], Field,
+ ListSeparator LS;
+ for (const auto &Field : Table.Fields)
+ OS << LS
+ << primaryRepresentation(Table.Locs[0], Field,
Entry->getValueInit(Field.Name));
- }
OS << " }, // " << i << "\n";
}
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index 7d2b4b929df3..c88fe949c25c 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -179,8 +179,8 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS,
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]);
+ for (const Record *Feature : FeatureList) {
+ unsigned Bit = FeatureMap.lookup(Feature);
Mask[Bit / 64] |= 1ULL << (Bit % 64);
}
@@ -215,10 +215,8 @@ unsigned SubtargetEmitter::FeatureKeyValues(
// For each feature
unsigned NumFeatures = 0;
- for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
+ for (const Record *Feature : FeatureList) {
// Next feature
- Record *Feature = FeatureList[i];
-
StringRef Name = Feature->getName();
StringRef CommandLineName = Feature->getValueAsString("Name");
StringRef Desc = Feature->getValueAsString("Desc");
@@ -344,13 +342,12 @@ void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
ItinData->getValueAsListOfInts("OperandCycles");
// For each operand cycle
- unsigned N = NOperandCycles = OperandCycleList.size();
- for (unsigned i = 0; i < N;) {
+ NOperandCycles = OperandCycleList.size();
+ ListSeparator LS;
+ for (int OCycle : OperandCycleList) {
// Next operand cycle
- const int OCycle = OperandCycleList[i];
-
+ ItinString += LS;
ItinString += " " + itostr(OCycle);
- if (++i < N) ItinString += ", ";
}
}
@@ -361,13 +358,14 @@ void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
RecVec BypassList = ItinData->getValueAsListOfDefs("Bypasses");
unsigned N = BypassList.size();
unsigned i = 0;
- for (; i < N;) {
+ ListSeparator LS;
+ for (; i < N; ++i) {
+ ItinString += LS;
ItinString += Name + "Bypass::" + BypassList[i]->getName().str();
- if (++i < NOperandCycles) ItinString += ", ";
}
- for (; i < NOperandCycles;) {
+ for (; i < NOperandCycles; ++i) {
+ ItinString += LS;
ItinString += " 0";
- if (++i < NOperandCycles) ItinString += ", ";
}
}
@@ -995,6 +993,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
SCDesc.NumMicroOps = 0;
SCDesc.BeginGroup = false;
SCDesc.EndGroup = false;
+ SCDesc.RetireOOO = false;
SCDesc.WriteProcResIdx = 0;
SCDesc.WriteLatencyIdx = 0;
SCDesc.ReadAdvanceIdx = 0;
@@ -1097,6 +1096,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup");
SCDesc.BeginGroup |= WriteRes->getValueAsBit("SingleIssue");
SCDesc.EndGroup |= WriteRes->getValueAsBit("SingleIssue");
+ SCDesc.RetireOOO |= WriteRes->getValueAsBit("RetireOOO");
// Create an entry for each ProcResource listed in WriteRes.
RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
@@ -1295,7 +1295,7 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
std::vector<MCSchedClassDesc> &SCTab =
SchedTables.ProcSchedClasses[1 + (PI - SchedModels.procModelBegin())];
- OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup,"
+ OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup, RetireOOO,"
<< " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
OS << "static const llvm::MCSchedClassDesc "
<< PI->ModelName << "SchedClasses[] = {\n";
@@ -1306,7 +1306,7 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
&& "invalid class not first");
OS << " {DBGFIELD(\"InvalidSchedClass\") "
<< MCSchedClassDesc::InvalidNumMicroOps
- << ", false, false, 0, 0, 0, 0, 0, 0},\n";
+ << ", false, false, false, 0, 0, 0, 0, 0, 0},\n";
for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
MCSchedClassDesc &MCDesc = SCTab[SCIdx];
@@ -1317,6 +1317,7 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
OS << MCDesc.NumMicroOps
<< ", " << ( MCDesc.BeginGroup ? "true" : "false" )
<< ", " << ( MCDesc.EndGroup ? "true" : "false" )
+ << ", " << ( MCDesc.RetireOOO ? "true" : "false" )
<< ", " << format("%2d", MCDesc.WriteProcResIdx)
<< ", " << MCDesc.NumWriteProcResEntries
<< ", " << format("%2d", MCDesc.WriteLatencyIdx)
diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
index 105ed82c9d02..33a22776f2df 100644
--- a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
+++ b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
@@ -130,14 +130,9 @@ void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
if (IsOr)
OS << "(";
- bool First = true;
+ ListSeparator LS(IsOr ? " || " : " && ");
for (auto *Arg : D->getArgs()) {
- if (!First) {
- if (IsOr)
- OS << " || ";
- else
- OS << " && ";
- }
+ OS << LS;
if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
if (NotArg->getOperator()->getAsString() != "not" ||
NotArg->getNumArgs() != 1)
@@ -149,8 +144,6 @@ void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
!cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
PrintFatalError(SFI.TheDef->getLoc(), "Invalid AssemblerCondDag!");
OS << "FB[" << TargetName << "::" << Arg->getAsString() << "]";
-
- First = false;
}
if (IsOr)
diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp
index 6d851da34731..24c11c8bc831 100644
--- a/llvm/utils/TableGen/TableGen.cpp
+++ b/llvm/utils/TableGen/TableGen.cpp
@@ -25,6 +25,7 @@ enum ActionType {
NullBackend,
DumpJSON,
GenEmitter,
+ GenCodeBeads,
GenRegisterInfo,
GenInstrInfo,
GenInstrDocs,
@@ -56,7 +57,6 @@ enum ActionType {
GenAutomata,
GenDirectivesEnumDecl,
GenDirectivesEnumImpl,
- GenDirectivesEnumGen,
};
namespace llvm {
@@ -81,6 +81,8 @@ cl::opt<ActionType> Action(
clEnumValN(DumpJSON, "dump-json",
"Dump all records as machine-readable JSON"),
clEnumValN(GenEmitter, "gen-emitter", "Generate machine code emitter"),
+ clEnumValN(GenCodeBeads, "gen-code-beads",
+ "Generate machine code beads"),
clEnumValN(GenRegisterInfo, "gen-register-info",
"Generate registers and register classes info"),
clEnumValN(GenInstrInfo, "gen-instr-info",
@@ -136,9 +138,7 @@ cl::opt<ActionType> Action(
clEnumValN(GenDirectivesEnumDecl, "gen-directive-decl",
"Generate directive related declaration code (header file)"),
clEnumValN(GenDirectivesEnumImpl, "gen-directive-impl",
- "Generate directive related implementation code"),
- clEnumValN(GenDirectivesEnumGen, "gen-directive-gen",
- "Generate directive related implementation code part")));
+ "Generate directive related implementation code")));
cl::OptionCategory PrintEnumsCat("Options for -print-enums");
cl::opt<std::string> Class("class", cl::desc("Print Enum list for this class"),
@@ -161,6 +161,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenEmitter:
EmitCodeEmitter(Records, OS);
break;
+ case GenCodeBeads:
+ EmitCodeBeads(Records, OS);
+ break;
case GenRegisterInfo:
EmitRegisterInfo(Records, OS);
break;
@@ -269,9 +272,6 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenDirectivesEnumImpl:
EmitDirectivesImpl(Records, OS);
break;
- case GenDirectivesEnumGen:
- EmitDirectivesGen(Records, OS);
- break;
}
return false;
diff --git a/llvm/utils/TableGen/TableGenBackends.h b/llvm/utils/TableGen/TableGenBackends.h
index 92204f39f8fa..71db8dc77b05 100644
--- a/llvm/utils/TableGen/TableGenBackends.h
+++ b/llvm/utils/TableGen/TableGenBackends.h
@@ -67,6 +67,7 @@ void EmitAsmMatcher(RecordKeeper &RK, raw_ostream &OS);
void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS);
void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS);
void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS);
+void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS);
void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS);
void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS);
void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);
@@ -92,7 +93,6 @@ void EmitExegesis(RecordKeeper &RK, raw_ostream &OS);
void EmitAutomata(RecordKeeper &RK, raw_ostream &OS);
void EmitDirectivesDecl(RecordKeeper &RK, raw_ostream &OS);
void EmitDirectivesImpl(RecordKeeper &RK, raw_ostream &OS);
-void EmitDirectivesGen(RecordKeeper &RK, raw_ostream &OS);
} // End llvm namespace
diff --git a/llvm/utils/TableGen/X86DisassemblerTables.cpp b/llvm/utils/TableGen/X86DisassemblerTables.cpp
index 331664f875b7..89069ec3e4ff 100644
--- a/llvm/utils/TableGen/X86DisassemblerTables.cpp
+++ b/llvm/utils/TableGen/X86DisassemblerTables.cpp
@@ -102,7 +102,8 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_64BIT_ADSIZE:
return (noPrefix && inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE, noPrefix));
case IC_64BIT_OPSIZE_ADSIZE:
- return false;
+ return (noPrefix &&
+ inheritsFrom(child, IC_64BIT_VEX_OPSIZE_ADSIZE, noPrefix));
case IC_XD:
return inheritsFrom(child, IC_64BIT_XD);
case IC_XS:
@@ -123,10 +124,11 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_64BIT_OPSIZE:
return inheritsFrom(child, IC_64BIT_REXW_OPSIZE) ||
(!AdSize64 && inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE)) ||
- (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE));
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE)) ||
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_VEX_OPSIZE_ADSIZE));
case IC_64BIT_XD:
- return(inheritsFrom(child, IC_64BIT_REXW_XD) ||
- (!AdSize64 && inheritsFrom(child, IC_64BIT_XD_ADSIZE)));
+ return (inheritsFrom(child, IC_64BIT_REXW_XD) ||
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_XD_ADSIZE)));
case IC_64BIT_XS:
return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
(!AdSize64 && inheritsFrom(child, IC_64BIT_XS_ADSIZE)));
@@ -156,7 +158,12 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_VEX_OPSIZE:
return (VEX_LIG && VEX_WIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE)) ||
(VEX_WIG && inheritsFrom(child, IC_VEX_W_OPSIZE)) ||
- (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE));
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE)) ||
+ inheritsFrom(child, IC_64BIT_VEX_OPSIZE);
+ case IC_64BIT_VEX_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_VEX_OPSIZE_ADSIZE);
+ case IC_64BIT_VEX_OPSIZE_ADSIZE:
+ return false;
case IC_VEX_W:
return VEX_LIG && inheritsFrom(child, IC_VEX_L_W);
case IC_VEX_W_XS:
@@ -698,8 +705,8 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
ModRMDecision.push_back(decision.instructionIDs[index]);
break;
case MODRM_FULL:
- for (unsigned index = 0; index < 256; ++index)
- ModRMDecision.push_back(decision.instructionIDs[index]);
+ for (unsigned short InstructionID : decision.instructionIDs)
+ ModRMDecision.push_back(InstructionID);
break;
}
@@ -710,10 +717,9 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
ModRMTableNum += ModRMDecision.size();
o1 << "/*Table" << EntryNumber << "*/\n";
i1++;
- for (std::vector<unsigned>::const_iterator I = ModRMDecision.begin(),
- E = ModRMDecision.end(); I != E; ++I) {
- o1.indent(i1 * 2) << format("0x%hx", *I) << ", /*"
- << InstructionSpecifiers[*I].name << "*/\n";
+ for (unsigned I : ModRMDecision) {
+ o1.indent(i1 * 2) << format("0x%hx", I) << ", /*"
+ << InstructionSpecifiers[I].name << "*/\n";
}
i1--;
}
@@ -743,6 +749,7 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
// We assume that the index can fit into uint16_t.
assert(sEntryNumber < 65536U &&
"Index into ModRMDecision is too large for uint16_t!");
+ (void)sEntryNumber;
++sTableNumber;
}
@@ -823,12 +830,9 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
for (unsigned Index = 0; Index < NumInstructions; ++Index) {
OperandListTy OperandList;
- for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
- ++OperandIndex) {
- OperandEncoding Encoding = (OperandEncoding)InstructionSpecifiers[Index]
- .operands[OperandIndex].encoding;
- OperandType Type = (OperandType)InstructionSpecifiers[Index]
- .operands[OperandIndex].type;
+ for (auto Operand : InstructionSpecifiers[Index].operands) {
+ OperandEncoding Encoding = (OperandEncoding)Operand.encoding;
+ OperandType Type = (OperandType)Operand.type;
OperandList.push_back(std::make_pair(Encoding, Type));
}
unsigned &N = OperandSets[OperandList];
@@ -856,12 +860,9 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
i++;
OperandListTy OperandList;
- for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
- ++OperandIndex) {
- OperandEncoding Encoding = (OperandEncoding)InstructionSpecifiers[index]
- .operands[OperandIndex].encoding;
- OperandType Type = (OperandType)InstructionSpecifiers[index]
- .operands[OperandIndex].type;
+ for (auto Operand : InstructionSpecifiers[index].operands) {
+ OperandEncoding Encoding = (OperandEncoding)Operand.encoding;
+ OperandType Type = (OperandType)Operand.type;
OperandList.push_back(std::make_pair(Encoding, Type));
}
o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";
@@ -887,6 +888,9 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
if ((index & ATTR_EVEX) || (index & ATTR_VEX) || (index & ATTR_VEXL)) {
if (index & ATTR_EVEX)
o << "IC_EVEX";
+ else if ((index & (ATTR_64BIT | ATTR_VEXL | ATTR_REXW | ATTR_OPSIZE)) ==
+ (ATTR_64BIT | ATTR_OPSIZE))
+ o << "IC_64BIT_VEX";
else
o << "IC_VEX";
@@ -898,9 +902,13 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
if (index & ATTR_REXW)
o << "_W";
- if (index & ATTR_OPSIZE)
+ if (index & ATTR_OPSIZE) {
o << "_OPSIZE";
- else if (index & ATTR_XD)
+ if ((index & (ATTR_64BIT | ATTR_EVEX | ATTR_VEX | ATTR_VEXL |
+ ATTR_REXW | ATTR_ADSIZE)) ==
+ (ATTR_64BIT | ATTR_VEX | ATTR_ADSIZE))
+ o << "_ADSIZE";
+ } else if (index & ATTR_XD)
o << "_XD";
else if (index & ATTR_XS)
o << "_XS";
@@ -914,8 +922,7 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
if (index & ATTR_EVEXB)
o << "_B";
}
- }
- else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
+ } 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))
o << "IC_64BIT_REXW_XD";
diff --git a/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp b/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp
index 6dc7e31e0dab..009dc036cf97 100644
--- a/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp
+++ b/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp
@@ -30,10 +30,13 @@ class X86EVEX2VEXTablesEmitter {
std::map<uint64_t, std::vector<const CodeGenInstruction *>> VEXInsts;
typedef std::pair<const CodeGenInstruction *, const CodeGenInstruction *> Entry;
+ typedef std::pair<StringRef, StringRef> Predicate;
// Represent both compress tables
std::vector<Entry> EVEX2VEX128;
std::vector<Entry> EVEX2VEX256;
+ // Represent predicates of VEX instructions.
+ std::vector<Predicate> EVEX2VEXPredicates;
public:
X86EVEX2VEXTablesEmitter(RecordKeeper &R) : Records(R), Target(R) {}
@@ -45,6 +48,9 @@ private:
// Prints the given table as a C++ array of type
// X86EvexToVexCompressTableEntry
void printTable(const std::vector<Entry> &Table, raw_ostream &OS);
+ // Prints function which checks target feature specific predicate.
+ void printCheckPredicate(const std::vector<Predicate> &Predicates,
+ raw_ostream &OS);
};
void X86EVEX2VEXTablesEmitter::printTable(const std::vector<Entry> &Table,
@@ -67,6 +73,19 @@ void X86EVEX2VEXTablesEmitter::printTable(const std::vector<Entry> &Table,
OS << "};\n\n";
}
+void X86EVEX2VEXTablesEmitter::printCheckPredicate(
+ const std::vector<Predicate> &Predicates, raw_ostream &OS) {
+ OS << "static bool CheckVEXInstPredicate"
+ << "(MachineInstr &MI, const X86Subtarget *Subtarget) {\n"
+ << " unsigned Opc = MI.getOpcode();\n"
+ << " switch (Opc) {\n"
+ << " default: return true;\n";
+ for (auto Pair : Predicates)
+ OS << " case X86::" << Pair.first << ": return " << Pair.second << ";\n";
+ OS << " }\n"
+ << "}\n\n";
+}
+
// Return true if the 2 BitsInits are equal
// Calculates the integer value residing BitsInit object
static inline uint64_t getValueFromBitsInit(const BitsInit *B) {
@@ -169,6 +188,18 @@ private:
};
void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) {
+ auto getPredicates = [&](const CodeGenInstruction *Inst) {
+ std::vector<Record *> PredicatesRecords =
+ Inst->TheDef->getValueAsListOfDefs("Predicates");
+ // Currently we only do AVX related checks and assume each instruction
+ // has one and only one AVX related predicates.
+ for (unsigned i = 0, e = PredicatesRecords.size(); i != e; ++i)
+ if (PredicatesRecords[i]->getName().startswith("HasAVX"))
+ return PredicatesRecords[i]->getValueAsString("CondString");
+ llvm_unreachable(
+ "Instruction with checkPredicate set must have one predicate!");
+ };
+
emitSourceFileHeader("X86 EVEX2VEX tables", OS);
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
@@ -222,11 +253,18 @@ void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) {
EVEX2VEX256.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,1}
else
EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0}
+
+ // Adding predicate check to EVEX2VEXPredicates table when needed.
+ if (VEXInst->TheDef->getValueAsBit("checkVEXPredicate"))
+ EVEX2VEXPredicates.push_back(
+ std::make_pair(EVEXInst->TheDef->getName(), getPredicates(VEXInst)));
}
// Print both tables
printTable(EVEX2VEX128, OS);
printTable(EVEX2VEX256, OS);
+ // Print CheckVEXInstPredicate function.
+ printCheckPredicate(EVEX2VEXPredicates, OS);
}
}
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp
index e4b7c05cfb88..c2ca3791ac36 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -125,13 +125,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
return;
}
- // Special case since there is no attribute class for 64-bit and VEX
- if (Name == "VMASKMOVDQU64") {
- ShouldBeEmitted = false;
- return;
- }
-
- ShouldBeEmitted = true;
+ ShouldBeEmitted = true;
}
void RecognizableInstr::processInstr(DisassemblerTables &tables,
@@ -267,6 +261,11 @@ InstructionContext RecognizableInstr::insnContext() const {
insnContext = IC_VEX_L_OPSIZE;
else if (OpPrefix == X86Local::PD && HasVEX_W)
insnContext = IC_VEX_W_OPSIZE;
+ else if (OpPrefix == X86Local::PD && Is64Bit &&
+ AdSize == X86Local::AdSize32)
+ insnContext = IC_64BIT_VEX_OPSIZE_ADSIZE;
+ else if (OpPrefix == X86Local::PD && Is64Bit)
+ insnContext = IC_64BIT_VEX_OPSIZE;
else if (OpPrefix == X86Local::PD)
insnContext = IC_VEX_OPSIZE;
else if (HasVEX_LPrefix && OpPrefix == X86Local::XS)