aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/utils/TableGen')
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp372
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp109
-rw-r--r--contrib/llvm/utils/TableGen/Attributes.cpp156
-rw-r--r--contrib/llvm/utils/TableGen/CallingConvEmitter.cpp8
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp613
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h16
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.cpp1
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenIntrinsics.h5
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenMapTable.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenRegisters.cpp31
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenSchedule.cpp91
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenSchedule.h49
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.cpp12
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.h2
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp36
-rw-r--r--contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp704
-rw-r--r--contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp5
-rw-r--r--contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp189
-rw-r--r--contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp50
-rw-r--r--contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp136
-rw-r--r--contrib/llvm/utils/TableGen/OptParserEmitter.cpp20
-rw-r--r--contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp41
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetEmitter.cpp17
-rw-r--r--contrib/llvm/utils/TableGen/TableGen.cpp8
-rw-r--r--contrib/llvm/utils/TableGen/TableGenBackends.h1
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp17
26 files changed, 1741 insertions, 950 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 0d7c5ffbea1c..4177388840be 100644
--- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -294,6 +294,15 @@ public:
}
};
+class AsmVariantInfo {
+public:
+ std::string RegisterPrefix;
+ std::string TokenizingCharacters;
+ std::string SeparatorCharacters;
+ std::string BreakCharacters;
+ int AsmVariantNo;
+};
+
/// MatchableInfo - Helper class for storing the necessary information for an
/// instruction or alias which is capable of being matched.
struct MatchableInfo {
@@ -460,6 +469,20 @@ struct MatchableInfo {
TheDef->getValueAsBit("UseInstAsmMatchConverter")) {
}
+ // Could remove this and the dtor if PointerUnion supported unique_ptr
+ // elements with a dynamic failure/assertion (like the one below) in the case
+ // where it was copied while being in an owning state.
+ MatchableInfo(const MatchableInfo &RHS)
+ : AsmVariantID(RHS.AsmVariantID), AsmString(RHS.AsmString),
+ TheDef(RHS.TheDef), DefRec(RHS.DefRec), ResOperands(RHS.ResOperands),
+ Mnemonic(RHS.Mnemonic), AsmOperands(RHS.AsmOperands),
+ RequiredFeatures(RHS.RequiredFeatures),
+ ConversionFnKind(RHS.ConversionFnKind),
+ HasDeprecation(RHS.HasDeprecation),
+ UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) {
+ assert(!DefRec.is<const CodeGenInstAlias *>());
+ }
+
~MatchableInfo() {
delete DefRec.dyn_cast<const CodeGenInstAlias*>();
}
@@ -470,18 +493,12 @@ struct MatchableInfo {
void initialize(const AsmMatcherInfo &Info,
SmallPtrSetImpl<Record*> &SingletonRegisters,
- int AsmVariantNo, std::string &RegisterPrefix);
+ AsmVariantInfo const &Variant);
/// validate - Return true if this matchable is a valid thing to match against
/// and perform a bunch of validity checking.
bool validate(StringRef CommentDelimiter, bool Hack) const;
- /// extractSingletonRegisterForAsmOperand - Extract singleton register,
- /// if present, from specified token.
- void
- extractSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info,
- std::string &RegisterPrefix);
-
/// findAsmOperand - Find the AsmOperand with the specified name and
/// suboperand index.
int findAsmOperand(StringRef N, int SubOpIdx) const {
@@ -576,8 +593,10 @@ struct MatchableInfo {
void dump() const;
private:
- void tokenizeAsmString(const AsmMatcherInfo &Info);
- void addAsmOperand(size_t Start, size_t End);
+ void tokenizeAsmString(AsmMatcherInfo const &Info,
+ AsmVariantInfo const &Variant);
+ void addAsmOperand(size_t Start, size_t End,
+ std::string const &SeparatorCharacters);
};
/// SubtargetFeatureInfo - Helper class for storing information on a subtarget
@@ -756,8 +775,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) {
// Find the ResOperand that refers to the operand we're aliasing away
// and update it to refer to the combined operand instead.
- for (unsigned i = 0, e = ResOperands.size(); i != e; ++i) {
- ResOperand &Op = ResOperands[i];
+ for (ResOperand &Op : ResOperands) {
if (Op.Kind == ResOperand::RenderAsmOperand &&
Op.AsmOperandNum == (unsigned)SrcAsmOperand) {
Op.AsmOperandNum = DstAsmOperand;
@@ -768,8 +786,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) {
AsmOperands.erase(AsmOperands.begin() + SrcAsmOperand);
// Adjust the ResOperand references to any AsmOperands that followed
// the one we just deleted.
- for (unsigned i = 0, e = ResOperands.size(); i != e; ++i) {
- ResOperand &Op = ResOperands[i];
+ for (ResOperand &Op : ResOperands) {
switch(Op.Kind) {
default:
// Nothing to do for operands that don't reference AsmOperands.
@@ -786,26 +803,58 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) {
}
}
+/// extractSingletonRegisterForAsmOperand - Extract singleton register,
+/// if present, from specified token.
+static void
+extractSingletonRegisterForAsmOperand(MatchableInfo::AsmOperand &Op,
+ const AsmMatcherInfo &Info,
+ StringRef RegisterPrefix) {
+ StringRef Tok = Op.Token;
+
+ // If this token is not an isolated token, i.e., it isn't separated from
+ // other tokens (e.g. with whitespace), don't interpret it as a register name.
+ if (!Op.IsIsolatedToken)
+ return;
+
+ if (RegisterPrefix.empty()) {
+ std::string LoweredTok = Tok.lower();
+ if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok))
+ Op.SingletonReg = Reg->TheDef;
+ return;
+ }
+
+ if (!Tok.startswith(RegisterPrefix))
+ return;
+
+ StringRef RegName = Tok.substr(RegisterPrefix.size());
+ if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName))
+ Op.SingletonReg = Reg->TheDef;
+
+ // If there is no register prefix (i.e. "%" in "%eax"), then this may
+ // be some random non-register token, just ignore it.
+ return;
+}
+
void MatchableInfo::initialize(const AsmMatcherInfo &Info,
SmallPtrSetImpl<Record*> &SingletonRegisters,
- int AsmVariantNo, std::string &RegisterPrefix) {
- AsmVariantID = AsmVariantNo;
+ AsmVariantInfo const &Variant) {
+ AsmVariantID = Variant.AsmVariantNo;
AsmString =
- CodeGenInstruction::FlattenAsmStringVariants(AsmString, AsmVariantNo);
+ CodeGenInstruction::FlattenAsmStringVariants(AsmString,
+ Variant.AsmVariantNo);
- tokenizeAsmString(Info);
+ tokenizeAsmString(Info, Variant);
// Compute the require features.
- std::vector<Record*> Predicates =TheDef->getValueAsListOfDefs("Predicates");
- for (unsigned i = 0, e = Predicates.size(); i != e; ++i)
+ for (Record *Predicate : TheDef->getValueAsListOfDefs("Predicates"))
if (const SubtargetFeatureInfo *Feature =
- Info.getSubtargetFeature(Predicates[i]))
+ Info.getSubtargetFeature(Predicate))
RequiredFeatures.push_back(Feature);
// Collect singleton registers, if used.
- for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
- extractSingletonRegisterForAsmOperand(i, Info, RegisterPrefix);
- if (Record *Reg = AsmOperands[i].SingletonReg)
+ for (MatchableInfo::AsmOperand &Op : AsmOperands) {
+ extractSingletonRegisterForAsmOperand(Op, Info, Variant.RegisterPrefix);
+ if (Record *Reg = Op.SingletonReg)
SingletonRegisters.insert(Reg);
}
@@ -818,9 +867,9 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info,
}
/// Append an AsmOperand for the given substring of AsmString.
-void MatchableInfo::addAsmOperand(size_t Start, size_t End) {
+void MatchableInfo::addAsmOperand(size_t Start, size_t End,
+ std::string const &Separators) {
StringRef String = AsmString;
- StringRef Separators = "[]*! \t,";
// Look for separators before and after to figure out is this token is
// isolated. Accept '$$' as that's how we escape '$'.
bool IsIsolatedToken =
@@ -831,92 +880,86 @@ void MatchableInfo::addAsmOperand(size_t Start, size_t End) {
}
/// tokenizeAsmString - Tokenize a simplified assembly string.
-void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) {
+void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info,
+ AsmVariantInfo const &Variant) {
StringRef String = AsmString;
- unsigned Prev = 0;
- bool InTok = true;
- for (unsigned i = 0, e = String.size(); i != e; ++i) {
- switch (String[i]) {
- case '[':
- case ']':
- case '*':
- case '!':
- case ' ':
- case '\t':
- case ',':
- if (InTok) {
- addAsmOperand(Prev, i);
+ size_t Prev = 0;
+ bool InTok = false;
+ std::string Separators = Variant.TokenizingCharacters +
+ Variant.SeparatorCharacters;
+ for (size_t i = 0, e = String.size(); i != e; ++i) {
+ if(Variant.BreakCharacters.find(String[i]) != std::string::npos) {
+ if(InTok) {
+ addAsmOperand(Prev, i, Separators);
+ Prev = i;
+ }
+ InTok = true;
+ continue;
+ }
+ if(Variant.TokenizingCharacters.find(String[i]) != std::string::npos) {
+ if(InTok) {
+ addAsmOperand(Prev, i, Separators);
InTok = false;
}
- if (!isspace(String[i]) && String[i] != ',')
- addAsmOperand(i, i + 1);
+ addAsmOperand(i, i + 1, Separators);
Prev = i + 1;
- break;
-
+ continue;
+ }
+ if(Variant.SeparatorCharacters.find(String[i]) != std::string::npos) {
+ if(InTok) {
+ addAsmOperand(Prev, i, Separators);
+ InTok = false;
+ }
+ Prev = i + 1;
+ continue;
+ }
+ switch (String[i]) {
case '\\':
if (InTok) {
- addAsmOperand(Prev, i);
+ addAsmOperand(Prev, i, Separators);
InTok = false;
}
++i;
assert(i != String.size() && "Invalid quoted character");
- addAsmOperand(i, i + 1);
+ addAsmOperand(i, i + 1, Separators);
Prev = i + 1;
break;
case '$': {
- if (InTok) {
- addAsmOperand(Prev, i);
+ if (InTok && Prev != i) {
+ addAsmOperand(Prev, i, Separators);
InTok = false;
}
- // If this isn't "${", treat like a normal token.
+ // If this isn't "${", start new identifier looking like "$xxx"
if (i + 1 == String.size() || String[i + 1] != '{') {
Prev = i;
break;
}
- StringRef::iterator End = std::find(String.begin() + i, String.end(),'}');
- assert(End != String.end() && "Missing brace in operand reference!");
- size_t EndPos = End - String.begin();
- addAsmOperand(i, EndPos+1);
+ size_t EndPos = String.find('}', i);
+ assert(EndPos != StringRef::npos &&
+ "Missing brace in operand reference!");
+ addAsmOperand(i, EndPos+1, Separators);
Prev = EndPos + 1;
i = EndPos;
break;
}
-
- case '.':
- if (!Info.AsmParser->getValueAsBit("MnemonicContainsDot")) {
- if (InTok)
- addAsmOperand(Prev, i);
- Prev = i;
- }
- InTok = true;
- break;
-
default:
InTok = true;
}
}
if (InTok && Prev != String.size())
- addAsmOperand(Prev, StringRef::npos);
+ addAsmOperand(Prev, StringRef::npos, Separators);
// The first token of the instruction is the mnemonic, which must be a
// simple string, not a $foo variable or a singleton register.
if (AsmOperands.empty())
PrintFatalError(TheDef->getLoc(),
"Instruction '" + TheDef->getName() + "' has no tokens");
- Mnemonic = AsmOperands[0].Token;
- if (Mnemonic.empty())
- PrintFatalError(TheDef->getLoc(),
- "Missing instruction mnemonic");
- // FIXME : Check and raise an error if it is a register.
- if (Mnemonic[0] == '$')
- PrintFatalError(TheDef->getLoc(),
- "Invalid instruction mnemonic '" + Mnemonic + "'!");
-
- // Remove the first operand, it is tracked in the mnemonic field.
- AsmOperands.erase(AsmOperands.begin());
+ assert(!AsmOperands[0].Token.empty());
+ if (AsmOperands[0].Token[0] != '$')
+ Mnemonic = AsmOperands[0].Token;
}
bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const {
@@ -946,8 +989,8 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const {
// Also, check for instructions which reference the operand multiple times;
// this implies a constraint we would not honor.
std::set<std::string> OperandNames;
- for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
- StringRef Tok = AsmOperands[i].Token;
+ for (const AsmOperand &Op : AsmOperands) {
+ StringRef Tok = Op.Token;
if (Tok[0] == '$' && Tok.find(':') != StringRef::npos)
PrintFatalError(TheDef->getLoc(),
"matchable with operand modifier '" + Tok +
@@ -974,38 +1017,6 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const {
return true;
}
-/// extractSingletonRegisterForAsmOperand - Extract singleton register,
-/// if present, from specified token.
-void MatchableInfo::
-extractSingletonRegisterForAsmOperand(unsigned OperandNo,
- const AsmMatcherInfo &Info,
- std::string &RegisterPrefix) {
- StringRef Tok = AsmOperands[OperandNo].Token;
-
- // If this token is not an isolated token, i.e., it isn't separated from
- // other tokens (e.g. with whitespace), don't interpret it as a register name.
- if (!AsmOperands[OperandNo].IsIsolatedToken)
- return;
-
- if (RegisterPrefix.empty()) {
- std::string LoweredTok = Tok.lower();
- if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok))
- AsmOperands[OperandNo].SingletonReg = Reg->TheDef;
- return;
- }
-
- if (!Tok.startswith(RegisterPrefix))
- return;
-
- StringRef RegName = Tok.substr(RegisterPrefix.size());
- if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName))
- AsmOperands[OperandNo].SingletonReg = Reg->TheDef;
-
- // If there is no register prefix (i.e. "%" in "%eax"), then this may
- // be some random non-register token, just ignore it.
- return;
-}
-
static std::string getEnumNameForToken(StringRef Str) {
std::string Res;
@@ -1364,8 +1375,15 @@ void AsmMatcherInfo::buildInfo() {
Record *AsmVariant = Target.getAsmParserVariant(VC);
std::string CommentDelimiter =
AsmVariant->getValueAsString("CommentDelimiter");
- std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");
- int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
+ AsmVariantInfo Variant;
+ Variant.RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");
+ Variant.TokenizingCharacters =
+ AsmVariant->getValueAsString("TokenizingCharacters");
+ Variant.SeparatorCharacters =
+ AsmVariant->getValueAsString("SeparatorCharacters");
+ Variant.BreakCharacters =
+ AsmVariant->getValueAsString("BreakCharacters");
+ Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant");
for (const CodeGenInstruction *CGI : Target.instructions()) {
@@ -1378,9 +1396,9 @@ void AsmMatcherInfo::buildInfo() {
if (CGI->TheDef->getValueAsBit("isCodeGenOnly"))
continue;
- std::unique_ptr<MatchableInfo> II(new MatchableInfo(*CGI));
+ auto II = llvm::make_unique<MatchableInfo>(*CGI);
- II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
+ II->initialize(*this, SingletonRegisters, Variant);
// Ignore instructions which shouldn't be matched and diagnose invalid
// instruction definitions with an error.
@@ -1396,7 +1414,8 @@ void AsmMatcherInfo::buildInfo() {
Records.getAllDerivedDefinitions("InstAlias");
for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) {
auto Alias = llvm::make_unique<CodeGenInstAlias>(AllInstAliases[i],
- AsmVariantNo, Target);
+ Variant.AsmVariantNo,
+ Target);
// If the tblgen -match-prefix option is specified (for tblgen hackers),
// filter the set of instruction aliases we consider, based on the target
@@ -1405,9 +1424,9 @@ void AsmMatcherInfo::buildInfo() {
.startswith( MatchPrefix))
continue;
- std::unique_ptr<MatchableInfo> II(new MatchableInfo(std::move(Alias)));
+ auto II = llvm::make_unique<MatchableInfo>(std::move(Alias));
- II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
+ II->initialize(*this, SingletonRegisters, Variant);
// Validate the alias definitions.
II->validate(CommentDelimiter, false);
@@ -1434,7 +1453,7 @@ void AsmMatcherInfo::buildInfo() {
StringRef Token = Op.Token;
// Check for singleton registers.
- if (Record *RegRecord = II->AsmOperands[i].SingletonReg) {
+ if (Record *RegRecord = Op.SingletonReg) {
Op.Class = RegisterClasses[RegRecord];
assert(Op.Class && Op.Class->Registers.size() == 1 &&
"Unexpected class for singleton register");
@@ -1474,7 +1493,7 @@ void AsmMatcherInfo::buildInfo() {
II->TheDef->getValueAsString("TwoOperandAliasConstraint");
if (Constraint != "") {
// Start by making a copy of the original matchable.
- std::unique_ptr<MatchableInfo> AliasII(new MatchableInfo(*II));
+ auto AliasII = llvm::make_unique<MatchableInfo>(*II);
// Adjust it to be a two-operand alias.
AliasII->formTwoOperandAlias(Constraint);
@@ -1494,8 +1513,7 @@ void AsmMatcherInfo::buildInfo() {
// information.
std::vector<Record*> AllTokenAliases =
Records.getAllDerivedDefinitions("TokenAlias");
- for (unsigned i = 0, e = AllTokenAliases.size(); i != e; ++i) {
- Record *Rec = AllTokenAliases[i];
+ for (Record *Rec : AllTokenAliases) {
ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken"));
ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken"));
if (FromClass == ToClass)
@@ -1603,9 +1621,7 @@ void MatchableInfo::buildInstructionResultOperands() {
// Loop over all operands of the result instruction, determining how to
// populate them.
- for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
- const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i];
-
+ for (const CGIOperandList::OperandInfo &OpInfo : ResultInst->Operands) {
// If this is a tied operand, just copy from the previously handled operand.
int TiedOp = -1;
if (OpInfo.MINumOperands == 1)
@@ -1701,7 +1717,7 @@ void MatchableInfo::buildAliasResultOperands() {
}
static unsigned getConverterOperandID(const std::string &Name,
- SetVector<std::string> &Table,
+ SmallSetVector<std::string, 16> &Table,
bool &IsNew) {
IsNew = Table.insert(Name);
@@ -1717,8 +1733,8 @@ static unsigned getConverterOperandID(const std::string &Name,
static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
std::vector<std::unique_ptr<MatchableInfo>> &Infos,
raw_ostream &OS) {
- SetVector<std::string> OperandConversionKinds;
- SetVector<std::string> InstructionConversionKinds;
+ SmallSetVector<std::string, 16> OperandConversionKinds;
+ SmallSetVector<std::string, 16> InstructionConversionKinds;
std::vector<std::vector<uint8_t> > ConversionTable;
size_t MaxRowLength = 2; // minimum is custom converter plus terminator.
@@ -1850,7 +1866,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Add the operand entry to the instruction kind conversion row.
ConversionRow.push_back(ID);
- ConversionRow.push_back(OpInfo.AsmOperandNum + 1);
+ ConversionRow.push_back(OpInfo.AsmOperandNum);
if (!IsNewConverter)
break;
@@ -1959,7 +1975,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
continue;
// Add the row to the table.
- ConversionTable.push_back(ConversionRow);
+ ConversionTable.push_back(std::move(ConversionRow));
}
// Finish up the converter driver function.
@@ -1979,10 +1995,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Output the instruction conversion kind enum.
OS << "enum InstructionConversionKind {\n";
- for (SetVector<std::string>::const_iterator
- i = InstructionConversionKinds.begin(),
- e = InstructionConversionKinds.end(); i != e; ++i)
- OS << " " << *i << ",\n";
+ for (const std::string &Signature : InstructionConversionKinds)
+ OS << " " << Signature << ",\n";
OS << " CVT_NUM_SIGNATURES\n";
OS << "};\n\n";
@@ -2105,12 +2119,7 @@ static void emitIsSubclass(CodeGenTarget &Target,
OS << " if (A == B)\n";
OS << " return true;\n\n";
- std::string OStr;
- raw_string_ostream SS(OStr);
- unsigned Count = 0;
- SS << " switch (A) {\n";
- SS << " default:\n";
- SS << " return false;\n";
+ bool EmittedSwitch = false;
for (const auto &A : Infos) {
std::vector<StringRef> SuperClasses;
for (const auto &B : Infos) {
@@ -2120,33 +2129,38 @@ static void emitIsSubclass(CodeGenTarget &Target,
if (SuperClasses.empty())
continue;
- ++Count;
- SS << "\n case " << A.Name << ":\n";
+ // If this is the first SuperClass, emit the switch header.
+ if (!EmittedSwitch) {
+ OS << " switch (A) {\n";
+ OS << " default:\n";
+ OS << " return false;\n";
+ EmittedSwitch = true;
+ }
+
+ OS << "\n case " << A.Name << ":\n";
if (SuperClasses.size() == 1) {
- SS << " return B == " << SuperClasses.back().str() << ";\n";
+ OS << " return B == " << SuperClasses.back() << ";\n";
continue;
}
if (!SuperClasses.empty()) {
- SS << " switch (B) {\n";
- SS << " default: return false;\n";
- for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
- SS << " case " << SuperClasses[i].str() << ": return true;\n";
- SS << " }\n";
+ OS << " switch (B) {\n";
+ OS << " default: return false;\n";
+ for (StringRef SC : SuperClasses)
+ OS << " case " << SC << ": return true;\n";
+ OS << " }\n";
} else {
// No case statement to emit
- SS << " return false;\n";
+ OS << " return false;\n";
}
}
- SS << " }\n";
+ OS << " }\n";
- // If there were case statements emitted into the string stream, write them
- // to the output stream, otherwise write the default.
- if (Count)
- OS << SS.str();
- else
+ // If there were case statements emitted into the string stream write the
+ // default.
+ if (!EmittedSwitch)
OS << " return false;\n";
OS << "}\n\n";
@@ -2575,13 +2589,17 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n";
OS << " // Get the next operand index.\n";
- OS << " unsigned NextOpNum = Operands.size()-1;\n";
+ OS << " unsigned NextOpNum = Operands.size();\n";
// Emit code to search the table.
OS << " // Search the table.\n";
OS << " std::pair<const OperandMatchEntry*, const OperandMatchEntry*>";
- OS << " MnemonicRange =\n";
- OS << " std::equal_range(OperandMatchTable, OperandMatchTable+"
+ OS << " MnemonicRange\n";
+ OS << " (OperandMatchTable, OperandMatchTable+";
+ OS << Info.OperandMatchInfo.size() << ");\n";
+ OS << " if(!Mnemonic.empty())\n";
+ OS << " MnemonicRange = std::equal_range(OperandMatchTable,";
+ OS << " OperandMatchTable+"
<< Info.OperandMatchInfo.size() << ", Mnemonic,\n"
<< " LessOpcodeOperand());\n\n";
@@ -2682,7 +2700,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< "&Operands);\n";
OS << " void convertToMapAndConstraints(unsigned Kind,\n ";
OS << " const OperandVector &Operands) override;\n";
- OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) override;\n";
+ OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n";
OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n"
<< " MCInst &Inst,\n"
<< " uint64_t &ErrorInfo,"
@@ -2891,8 +2909,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< " bool matchingInlineAsm, unsigned VariantID) {\n";
OS << " // Eliminate obvious mismatches.\n";
- OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n";
- OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n";
+ OS << " if (Operands.size() > " << MaxNumOperands << ") {\n";
+ OS << " ErrorInfo = " << MaxNumOperands << ";\n";
OS << " return Match_InvalidOperand;\n";
OS << " }\n\n";
@@ -2901,7 +2919,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n";
OS << " // Get the instruction mnemonic, which is the first token.\n";
- OS << " StringRef Mnemonic = ((" << Target.getName()
+ OS << " StringRef Mnemonic;\n";
+ OS << " if (Operands[0]->isToken())\n";
+ OS << " Mnemonic = ((" << Target.getName()
<< "Operand&)*Operands[0]).getToken();\n\n";
if (HasMnemonicAliases) {
@@ -2932,8 +2952,11 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
}
OS << " }\n";
OS << " // Search the table.\n";
- OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n";
- OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n";
+ OS << " std::pair<const MatchEntry*, const MatchEntry*> "
+ "MnemonicRange(Start, End);\n";
+ OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n";
+ OS << " if (!Mnemonic.empty())\n";
+ OS << " MnemonicRange = std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n";
OS << " // Return a more specific error code if no mnemonics match.\n";
OS << " if (MnemonicRange.first == MnemonicRange.second)\n";
@@ -2943,28 +2966,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< "*ie = MnemonicRange.second;\n";
OS << " it != ie; ++it) {\n";
- OS << " // equal_range guarantees that instruction mnemonic matches.\n";
- OS << " assert(Mnemonic == it->getMnemonic());\n";
-
// Emit check that the subclasses match.
OS << " bool OperandsValid = true;\n";
- OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n";
- OS << " if (i + 1 >= Operands.size()) {\n";
- OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n";
- OS << " if (!OperandsValid) ErrorInfo = i + 1;\n";
+ OS << " for (unsigned i = SIndex; i != " << MaxNumOperands << "; ++i) {\n";
+ OS << " auto Formal = static_cast<MatchClassKind>(it->Classes[i]);\n";
+ OS << " if (i >= Operands.size()) {\n";
+ OS << " OperandsValid = (Formal == " <<"InvalidMatchClass);\n";
+ OS << " if (!OperandsValid) ErrorInfo = i;\n";
OS << " break;\n";
OS << " }\n";
- OS << " unsigned Diag = validateOperandClass(*Operands[i+1],\n";
- OS.indent(43);
- OS << "(MatchClassKind)it->Classes[i]);\n";
+ OS << " MCParsedAsmOperand &Actual = *Operands[i];\n";
+ OS << " unsigned Diag = validateOperandClass(Actual, Formal);\n";
OS << " if (Diag == Match_Success)\n";
OS << " continue;\n";
OS << " // If the generic handler indicates an invalid operand\n";
OS << " // failure, check for a special case.\n";
OS << " if (Diag == Match_InvalidOperand) {\n";
- OS << " Diag = validateTargetOperandClass(*Operands[i+1],\n";
- OS.indent(43);
- OS << "(MatchClassKind)it->Classes[i]);\n";
+ OS << " Diag = validateTargetOperandClass(Actual, Formal);\n";
OS << " if (Diag == Match_Success)\n";
OS << " continue;\n";
OS << " }\n";
@@ -2973,8 +2991,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " // If we already had a match that only failed due to a\n";
OS << " // target predicate, that diagnostic is preferred.\n";
OS << " if (!HadMatchOtherThanPredicate &&\n";
- OS << " (it == MnemonicRange.first || ErrorInfo <= i+1)) {\n";
- OS << " ErrorInfo = i+1;\n";
+ OS << " (it == MnemonicRange.first || ErrorInfo <= i)) {\n";
+ OS << " ErrorInfo = i;\n";
OS << " // InvalidOperand is the default. Prefer specificity.\n";
OS << " if (Diag != Match_InvalidOperand)\n";
OS << " RetCode = Diag;\n";
@@ -3029,7 +3047,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (HasDeprecation) {
OS << " std::string Info;\n";
- OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n";
+ OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n";
OS << " SMLoc Loc = ((" << Target.getName()
<< "Operand&)*Operands[0]).getStartLoc();\n";
OS << " getParser().Warning(Loc, Info, None);\n";
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
index 8163f681d88d..cc74f9ebcece 100644
--- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -586,6 +586,8 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
const auto &Registers = Target.getRegBank().getRegisters();
std::vector<Record*> AltNameIndices = Target.getRegAltNameIndices();
bool hasAltNames = AltNameIndices.size() > 1;
+ std::string Namespace =
+ Registers.front().TheDef->getValueAsString("Namespace");
O <<
"\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
@@ -610,9 +612,9 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
O << " switch(AltIdx) {\n"
<< " default: llvm_unreachable(\"Invalid register alt name index!\");\n";
for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) {
- std::string Namespace = AltNameIndices[1]->getValueAsString("Namespace");
std::string AltName(AltNameIndices[i]->getName());
- O << " case " << Namespace << "::" << AltName << ":\n"
+ std::string Prefix = !Namespace.empty() ? Namespace + "::" : "";
+ O << " case " << Prefix << AltName << ":\n"
<< " assert(*(AsmStrs" << AltName << "+RegAsmOffset"
<< AltName << "[RegNo-1]) &&\n"
<< " \"Invalid alt name index for register!\");\n"
@@ -727,7 +729,6 @@ public:
++I;
}
}
- OS.flush();
// Emit the string.
O.indent(6) << "AsmString = \"" << OutString << "\";\n";
@@ -736,14 +737,13 @@ public:
O.indent(4) << '}';
}
- bool operator==(const IAPrinter &RHS) {
+ bool operator==(const IAPrinter &RHS) const {
if (Conds.size() != RHS.Conds.size())
return false;
unsigned Idx = 0;
- for (std::vector<std::string>::iterator
- I = Conds.begin(), E = Conds.end(); I != E; ++I)
- if (*I != RHS.Conds[Idx++])
+ for (const auto &str : Conds)
+ if (str != RHS.Conds[Idx++])
return false;
return true;
@@ -762,12 +762,12 @@ static unsigned CountNumOperands(StringRef AsmString, unsigned Variant) {
namespace {
struct AliasPriorityComparator {
- typedef std::pair<CodeGenInstAlias *, int> ValueType;
+ typedef std::pair<CodeGenInstAlias, int> ValueType;
bool operator()(const ValueType &LHS, const ValueType &RHS) {
if (LHS.second == RHS.second) {
// We don't actually care about the order, but for consistency it
// shouldn't depend on pointer comparisons.
- return LHS.first->TheDef->getName() < RHS.first->TheDef->getName();
+ return LHS.first.TheDef->getName() < RHS.first.TheDef->getName();
}
// Aliases with larger priorities should be considered first.
@@ -796,12 +796,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
Records.getAllDerivedDefinitions("InstAlias");
// Create a map from the qualified name to a list of potential matches.
- typedef std::set<std::pair<CodeGenInstAlias*, int>, AliasPriorityComparator>
+ typedef std::set<std::pair<CodeGenInstAlias, int>, AliasPriorityComparator>
AliasWithPriority;
std::map<std::string, AliasWithPriority> AliasMap;
for (std::vector<Record*>::iterator
I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) {
- CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Variant, Target);
const Record *R = *I;
int Priority = R->getValueAsInt("EmitPriority");
if (Priority < 1)
@@ -809,13 +808,13 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
const DagInit *DI = R->getValueAsDag("ResultInst");
const DefInit *Op = cast<DefInit>(DI->getOperator());
- AliasMap[getQualifiedName(Op->getDef())].insert(std::make_pair(Alias,
- Priority));
+ AliasMap[getQualifiedName(Op->getDef())].insert(
+ std::make_pair(CodeGenInstAlias(*I, Variant, Target), Priority));
}
// A map of which conditions need to be met for each instruction operand
// before it can be matched to the mnemonic.
- std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap;
+ std::map<std::string, std::vector<IAPrinter>> IAPrinterMap;
// A list of MCOperandPredicates for all operands in use, and the reverse map
std::vector<const Record*> MCOpPredicates;
@@ -823,25 +822,24 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
for (auto &Aliases : AliasMap) {
for (auto &Alias : Aliases.second) {
- const CodeGenInstAlias *CGA = Alias.first;
- unsigned LastOpNo = CGA->ResultInstOperandIndex.size();
+ const CodeGenInstAlias &CGA = Alias.first;
+ unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
unsigned NumResultOps =
- CountNumOperands(CGA->ResultInst->AsmString, Variant);
+ CountNumOperands(CGA.ResultInst->AsmString, Variant);
// Don't emit the alias if it has more operands than what it's aliasing.
- if (NumResultOps < CountNumOperands(CGA->AsmString, Variant))
+ if (NumResultOps < CountNumOperands(CGA.AsmString, Variant))
continue;
- IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(),
- CGA->AsmString);
+ IAPrinter IAP(CGA.Result->getAsString(), CGA.AsmString);
unsigned NumMIOps = 0;
- for (auto &Operand : CGA->ResultOperands)
+ for (auto &Operand : CGA.ResultOperands)
NumMIOps += Operand.getMINumOperands();
std::string Cond;
Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(NumMIOps);
- IAP->addCond(Cond);
+ IAP.addCond(Cond);
bool CantHandle = false;
@@ -849,7 +847,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
std::string Op = "MI->getOperand(" + llvm::utostr(MIOpNum) + ")";
- const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i];
+ const CodeGenInstAlias::ResultOperand &RO = CGA.ResultOperands[i];
switch (RO.Kind) {
case CodeGenInstAlias::ResultOperand::K_Record: {
@@ -875,11 +873,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (Rec->isSubClassOf("RegisterOperand"))
Rec = Rec->getValueAsDef("RegClass");
if (Rec->isSubClassOf("RegisterClass")) {
- IAP->addCond(Op + ".isReg()");
+ IAP.addCond(Op + ".isReg()");
- if (!IAP->isOpMapped(ROName)) {
- IAP->addOperand(ROName, MIOpNum, PrintMethodIdx);
- Record *R = CGA->ResultOperands[i].getRecord();
+ if (!IAP.isOpMapped(ROName)) {
+ IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
+ Record *R = CGA.ResultOperands[i].getRecord();
if (R->isSubClassOf("RegisterOperand"))
R = R->getValueAsDef("RegClass");
Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" +
@@ -887,12 +885,12 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
".contains(" + Op + ".getReg())";
} else {
Cond = Op + ".getReg() == MI->getOperand(" +
- llvm::utostr(IAP->getOpIndex(ROName)) + ").getReg()";
+ llvm::utostr(IAP.getOpIndex(ROName)) + ").getReg()";
}
} else {
// Assume all printable operands are desired for now. This can be
// overridden in the InstAlias instantiation if necessary.
- IAP->addOperand(ROName, MIOpNum, PrintMethodIdx);
+ IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
// There might be an additional predicate on the MCOperand
unsigned Entry = MCOpPredicateMap[Rec];
@@ -905,42 +903,41 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
break; // No conditions on this operand at all
}
Cond = Target.getName() + ClassName + "ValidateMCOperand(" +
- Op + ", " + llvm::utostr(Entry) + ")";
+ Op + ", STI, " + llvm::utostr(Entry) + ")";
}
// for all subcases of ResultOperand::K_Record:
- IAP->addCond(Cond);
+ IAP.addCond(Cond);
break;
}
case CodeGenInstAlias::ResultOperand::K_Imm: {
// Just because the alias has an immediate result, doesn't mean the
// MCInst will. An MCExpr could be present, for example.
- IAP->addCond(Op + ".isImm()");
+ IAP.addCond(Op + ".isImm()");
- Cond = Op + ".getImm() == "
- + llvm::utostr(CGA->ResultOperands[i].getImm());
- IAP->addCond(Cond);
+ Cond = Op + ".getImm() == " +
+ llvm::utostr(CGA.ResultOperands[i].getImm());
+ IAP.addCond(Cond);
break;
}
case CodeGenInstAlias::ResultOperand::K_Reg:
// If this is zero_reg, something's playing tricks we're not
// equipped to handle.
- if (!CGA->ResultOperands[i].getRegister()) {
+ if (!CGA.ResultOperands[i].getRegister()) {
CantHandle = true;
break;
}
- Cond = Op + ".getReg() == " + Target.getName() +
- "::" + CGA->ResultOperands[i].getRegister()->getName();
- IAP->addCond(Cond);
+ Cond = Op + ".getReg() == " + Target.getName() + "::" +
+ CGA.ResultOperands[i].getRegister()->getName();
+ IAP.addCond(Cond);
break;
}
- if (!IAP) break;
MIOpNum += RO.getMINumOperands();
}
if (CantHandle) continue;
- IAPrinterMap[Aliases.first].push_back(IAP);
+ IAPrinterMap[Aliases.first].push_back(std::move(IAP));
}
}
@@ -959,30 +956,26 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
std::string Cases;
raw_string_ostream CasesO(Cases);
- for (std::map<std::string, std::vector<IAPrinter*> >::iterator
- I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) {
- std::vector<IAPrinter*> &IAPs = I->second;
+ for (auto &Entry : IAPrinterMap) {
+ std::vector<IAPrinter> &IAPs = Entry.second;
std::vector<IAPrinter*> UniqueIAPs;
- for (std::vector<IAPrinter*>::iterator
- II = IAPs.begin(), IE = IAPs.end(); II != IE; ++II) {
- IAPrinter *LHS = *II;
+ for (auto &LHS : IAPs) {
bool IsDup = false;
- for (std::vector<IAPrinter*>::iterator
- III = IAPs.begin(), IIE = IAPs.end(); III != IIE; ++III) {
- IAPrinter *RHS = *III;
- if (LHS != RHS && *LHS == *RHS) {
+ for (const auto &RHS : IAPs) {
+ if (&LHS != &RHS && LHS == RHS) {
IsDup = true;
break;
}
}
- if (!IsDup) UniqueIAPs.push_back(LHS);
+ if (!IsDup)
+ UniqueIAPs.push_back(&LHS);
}
if (UniqueIAPs.empty()) continue;
- CasesO.indent(2) << "case " << I->first << ":\n";
+ CasesO.indent(2) << "case " << Entry.first << ":\n";
for (std::vector<IAPrinter*>::iterator
II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) {
@@ -1005,8 +998,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (!MCOpPredicates.empty())
O << "static bool " << Target.getName() << ClassName
- << "ValidateMCOperand(\n"
- << " const MCOperand &MCOp, unsigned PredicateIndex);\n";
+ << "ValidateMCOperand(const MCOperand &MCOp,\n"
+ << " const MCSubtargetInfo &STI,\n"
+ << " unsigned PredicateIndex);\n";
O << HeaderO.str();
O.indent(2) << "const char *AsmString;\n";
@@ -1078,8 +1072,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (!MCOpPredicates.empty()) {
O << "static bool " << Target.getName() << ClassName
- << "ValidateMCOperand(\n"
- << " const MCOperand &MCOp, unsigned PredicateIndex) {\n"
+ << "ValidateMCOperand(const MCOperand &MCOp,\n"
+ << " const MCSubtargetInfo &STI,\n"
+ << " unsigned PredicateIndex) {\n"
<< " switch (PredicateIndex) {\n"
<< " default:\n"
<< " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
diff --git a/contrib/llvm/utils/TableGen/Attributes.cpp b/contrib/llvm/utils/TableGen/Attributes.cpp
new file mode 100644
index 000000000000..7b001bf14de5
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/Attributes.cpp
@@ -0,0 +1,156 @@
+//===- Attributes.cpp - Generate attributes -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+using namespace llvm;
+
+#define DEBUG_TYPE "attr-enum"
+
+namespace {
+
+class Attributes {
+public:
+ Attributes(RecordKeeper &R) : Records(R) {}
+ void emit(raw_ostream &OS);
+
+private:
+ void emitTargetIndependentEnums(raw_ostream &OS);
+ void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
+
+ void printEnumAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records);
+ void printStrBoolAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records);
+
+ RecordKeeper &Records;
+};
+
+} // End anonymous namespace.
+
+void Attributes::emitTargetIndependentEnums(raw_ostream &OS) {
+ OS << "#ifdef GET_ATTR_ENUM\n";
+ OS << "#undef GET_ATTR_ENUM\n";
+
+ std::vector<Record*> Attrs =
+ Records.getAllDerivedDefinitions("EnumAttr");
+
+ for (auto A : Attrs)
+ OS << A->getName() << ",\n";
+
+ OS << "#endif\n";
+}
+
+void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
+ OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
+ OS << "#undef GET_ATTR_COMPAT_FUNC\n";
+
+ OS << "struct EnumAttr {\n";
+ OS << " static bool isSet(const Function &Fn,\n";
+ OS << " Attribute::AttrKind Kind) {\n";
+ OS << " return Fn.hasFnAttribute(Kind);\n";
+ OS << " }\n\n";
+ OS << " static void set(Function &Fn,\n";
+ OS << " Attribute::AttrKind Kind, bool Val) {\n";
+ OS << " if (Val)\n";
+ OS << " Fn.addFnAttr(Kind);\n";
+ OS << " else\n";
+ OS << " Fn.removeFnAttr(Kind);\n";
+ OS << " }\n";
+ OS << "};\n\n";
+
+ OS << "struct StrBoolAttr {\n";
+ OS << " static bool isSet(const Function &Fn,\n";
+ OS << " StringRef Kind) {\n";
+ OS << " auto A = Fn.getFnAttribute(Kind);\n";
+ OS << " return A.getValueAsString().equals(\"true\");\n";
+ OS << " }\n\n";
+ OS << " static void set(Function &Fn,\n";
+ OS << " StringRef Kind, bool Val) {\n";
+ OS << " Fn.addFnAttr(Kind, Val ? \"true\" : \"false\");\n";
+ OS << " }\n";
+ OS << "};\n\n";
+
+ printEnumAttrClasses(OS ,Records.getAllDerivedDefinitions("EnumAttr"));
+ printStrBoolAttrClasses(OS , Records.getAllDerivedDefinitions("StrBoolAttr"));
+
+ OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
+ << " const Function &Callee) {\n";
+ OS << " bool Ret = true;\n\n";
+
+ std::vector<Record *> CompatRules =
+ Records.getAllDerivedDefinitions("CompatRule");
+
+ for (auto *Rule : CompatRules) {
+ std::string FuncName = Rule->getValueAsString("CompatFunc");
+ OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
+ }
+
+ OS << "\n";
+ OS << " return Ret;\n";
+ OS << "}\n\n";
+
+ std::vector<Record *> MergeRules =
+ Records.getAllDerivedDefinitions("MergeRule");
+ OS << "static inline void mergeFnAttrs(Function &Caller,\n"
+ << " const Function &Callee) {\n";
+
+ for (auto *Rule : MergeRules) {
+ std::string FuncName = Rule->getValueAsString("MergeFunc");
+ OS << " " << FuncName << "(Caller, Callee);\n";
+ }
+
+ OS << "}\n\n";
+
+ OS << "#endif\n";
+}
+
+void Attributes::printEnumAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records) {
+ OS << "// EnumAttr classes\n";
+ for (const auto *R : Records) {
+ OS << "struct " << R->getName() << "Attr : EnumAttr {\n";
+ OS << " static enum Attribute::AttrKind getKind() {\n";
+ OS << " return llvm::Attribute::" << R->getName() << ";\n";
+ OS << " }\n";
+ OS << "};\n";
+ }
+ OS << "\n";
+}
+
+void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records) {
+ OS << "// StrBoolAttr classes\n";
+ for (const auto *R : Records) {
+ OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n";
+ OS << " static const char *getKind() {\n";
+ OS << " return \"" << R->getValueAsString("AttrString") << "\";\n";
+ OS << " }\n";
+ OS << "};\n";
+ }
+ OS << "\n";
+}
+
+void Attributes::emit(raw_ostream &OS) {
+ emitTargetIndependentEnums(OS);
+ emitFnAttrCompatCheck(OS, false);
+}
+
+namespace llvm {
+
+void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) {
+ Attributes(RK).emit(OS);
+}
+
+} // End llvm namespace.
diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp
index c7519b3e1528..a47662b28558 100644
--- a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp
@@ -181,15 +181,15 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << Size << ", ";
else
O << "\n" << IndentStr
- << " State.getMachineFunction().getTarget().getDataLayout()"
- "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
+ << " State.getMachineFunction().getDataLayout()."
+ "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
" ";
if (Align)
O << Align;
else
O << "\n" << IndentStr
- << " State.getMachineFunction().getTarget().getDataLayout()"
- "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()"
+ << " State.getMachineFunction().getDataLayout()."
+ "getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()"
"))";
O << ");\n" << IndentStr
<< "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index ae1cc0cfb5fd..3ebe51e05121 100644
--- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -14,6 +14,7 @@
#include "CodeGenDAGPatterns.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
@@ -84,9 +85,9 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP,
if (TP.hasError())
return false;
- for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i)
- if (!Pred || Pred(LegalTypes[i]))
- TypeVec.push_back(LegalTypes[i]);
+ for (MVT::SimpleValueType VT : LegalTypes)
+ if (!Pred || Pred(VT))
+ TypeVec.push_back(VT);
// If we have nothing that matches the predicate, bail out.
if (TypeVec.empty()) {
@@ -107,36 +108,24 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP,
/// hasIntegerTypes - Return true if this TypeSet contains iAny or an
/// integer value type.
bool EEVT::TypeSet::hasIntegerTypes() const {
- for (unsigned i = 0, e = TypeVec.size(); i != e; ++i)
- if (isInteger(TypeVec[i]))
- return true;
- return false;
+ return std::any_of(TypeVec.begin(), TypeVec.end(), isInteger);
}
/// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
/// a floating point value type.
bool EEVT::TypeSet::hasFloatingPointTypes() const {
- for (unsigned i = 0, e = TypeVec.size(); i != e; ++i)
- if (isFloatingPoint(TypeVec[i]))
- return true;
- return false;
+ return std::any_of(TypeVec.begin(), TypeVec.end(), isFloatingPoint);
}
/// hasScalarTypes - Return true if this TypeSet contains a scalar value type.
bool EEVT::TypeSet::hasScalarTypes() const {
- for (unsigned i = 0, e = TypeVec.size(); i != e; ++i)
- if (isScalar(TypeVec[i]))
- return true;
- return false;
+ return std::any_of(TypeVec.begin(), TypeVec.end(), isScalar);
}
/// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector
/// value type.
bool EEVT::TypeSet::hasVectorTypes() const {
- for (unsigned i = 0, e = TypeVec.size(); i != e; ++i)
- if (isVector(TypeVec[i]))
- return true;
- return false;
+ return std::any_of(TypeVec.begin(), TypeVec.end(), isVector);
}
@@ -171,7 +160,7 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){
return true;
}
- assert(TypeVec.size() >= 1 && InVT.TypeVec.size() >= 1 && "No unknowns");
+ assert(!TypeVec.empty() && !InVT.TypeVec.empty() && "No unknowns");
// Handle the abstract cases, seeing if we can resolve them better.
switch (TypeVec[0]) {
@@ -206,8 +195,7 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){
// multiple different integer types, replace them with a single iPTR.
if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) &&
TypeVec.size() != 1) {
- TypeVec.resize(1);
- TypeVec[0] = InVT.TypeVec[0];
+ TypeVec.assign(1, InVT.TypeVec[0]);
MadeChange = true;
}
@@ -216,25 +204,20 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){
// If this is a type list and the RHS is a typelist as well, eliminate entries
// from this list that aren't in the other one.
- bool MadeChange = false;
TypeSet InputSet(*this);
- for (unsigned i = 0; i != TypeVec.size(); ++i) {
- bool InInVT = false;
- for (unsigned j = 0, e = InVT.TypeVec.size(); j != e; ++j)
- if (TypeVec[i] == InVT.TypeVec[j]) {
- InInVT = true;
- break;
- }
+ TypeVec.clear();
+ std::set_intersection(InputSet.TypeVec.begin(), InputSet.TypeVec.end(),
+ InVT.TypeVec.begin(), InVT.TypeVec.end(),
+ std::back_inserter(TypeVec));
- if (InInVT) continue;
- TypeVec.erase(TypeVec.begin()+i--);
- MadeChange = true;
- }
+ // If the intersection is the same size as the original set then we're done.
+ if (TypeVec.size() == InputSet.TypeVec.size())
+ return false;
// If we removed all of our types, we have a type contradiction.
if (!TypeVec.empty())
- return MadeChange;
+ return true;
// FIXME: Really want an SMLoc here!
TP.error("Type inference contradiction found, merging '" +
@@ -249,15 +232,16 @@ bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) {
// If we know nothing, then get the full set.
if (TypeVec.empty())
return FillWithPossibleTypes(TP, isInteger, "integer");
+
if (!hasFloatingPointTypes())
return false;
TypeSet InputSet(*this);
// Filter out all the fp types.
- for (unsigned i = 0; i != TypeVec.size(); ++i)
- if (!isInteger(TypeVec[i]))
- TypeVec.erase(TypeVec.begin()+i--);
+ TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(),
+ std::not1(std::ptr_fun(isInteger))),
+ TypeVec.end());
if (TypeVec.empty()) {
TP.error("Type inference contradiction found, '" +
@@ -280,10 +264,10 @@ bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) {
TypeSet InputSet(*this);
- // Filter out all the fp types.
- for (unsigned i = 0; i != TypeVec.size(); ++i)
- if (!isFloatingPoint(TypeVec[i]))
- TypeVec.erase(TypeVec.begin()+i--);
+ // Filter out all the integer types.
+ TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(),
+ std::not1(std::ptr_fun(isFloatingPoint))),
+ TypeVec.end());
if (TypeVec.empty()) {
TP.error("Type inference contradiction found, '" +
@@ -308,9 +292,9 @@ bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) {
TypeSet InputSet(*this);
// Filter out all the vector types.
- for (unsigned i = 0; i != TypeVec.size(); ++i)
- if (!isScalar(TypeVec[i]))
- TypeVec.erase(TypeVec.begin()+i--);
+ TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(),
+ std::not1(std::ptr_fun(isScalar))),
+ TypeVec.end());
if (TypeVec.empty()) {
TP.error("Type inference contradiction found, '" +
@@ -333,11 +317,9 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) {
bool MadeChange = false;
// Filter out all the scalar types.
- for (unsigned i = 0; i != TypeVec.size(); ++i)
- if (!isVector(TypeVec[i])) {
- TypeVec.erase(TypeVec.begin()+i--);
- MadeChange = true;
- }
+ TypeVec.erase(std::remove_if(TypeVec.begin(), TypeVec.end(),
+ std::not1(std::ptr_fun(isVector))),
+ TypeVec.end());
if (TypeVec.empty()) {
TP.error("Type inference contradiction found, '" +
@@ -350,7 +332,7 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) {
/// EnforceSmallerThan - 'this' must be a smaller VT than Other. For vectors
-/// this shoud be based on the element type. Update this and other based on
+/// this should be based on the element type. Update this and other based on
/// this information.
bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
if (TP.hasError())
@@ -404,59 +386,70 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
// type size is smaller than the scalar size of the smallest type. For
// vectors, we also need to make sure that the total size is no larger than
// the size of the smallest type.
- TypeSet InputSet(Other);
- MVT Smallest = TypeVec[0];
- for (unsigned i = 0; i != Other.TypeVec.size(); ++i) {
- MVT OtherVT = Other.TypeVec[i];
- // Don't compare vector and non-vector types.
- if (OtherVT.isVector() != Smallest.isVector())
- continue;
- // The getSizeInBits() check here is only needed for vectors, but is
- // a subset of the scalar check for scalars so no need to qualify.
- if (OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits() ||
- OtherVT.getSizeInBits() < Smallest.getSizeInBits()) {
- Other.TypeVec.erase(Other.TypeVec.begin()+i--);
- MadeChange = true;
+ {
+ TypeSet InputSet(Other);
+ MVT Smallest = *std::min_element(TypeVec.begin(), TypeVec.end(),
+ [](MVT A, MVT B) {
+ return A.getScalarSizeInBits() < B.getScalarSizeInBits() ||
+ (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
+ A.getSizeInBits() < B.getSizeInBits());
+ });
+
+ auto I = std::remove_if(Other.TypeVec.begin(), Other.TypeVec.end(),
+ [Smallest](MVT OtherVT) {
+ // Don't compare vector and non-vector types.
+ if (OtherVT.isVector() != Smallest.isVector())
+ return false;
+ // The getSizeInBits() check here is only needed for vectors, but is
+ // a subset of the scalar check for scalars so no need to qualify.
+ return OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits()||
+ OtherVT.getSizeInBits() < Smallest.getSizeInBits();
+ });
+ MadeChange |= I != Other.TypeVec.end(); // If we're about to remove types.
+ Other.TypeVec.erase(I, Other.TypeVec.end());
+
+ if (Other.TypeVec.empty()) {
+ TP.error("Type inference contradiction found, '" + InputSet.getName() +
+ "' has nothing larger than '" + getName() +"'!");
+ return false;
}
}
- if (Other.TypeVec.empty()) {
- TP.error("Type inference contradiction found, '" + InputSet.getName() +
- "' has nothing larger than '" + getName() +"'!");
- return false;
- }
-
// Okay, find the largest type from the other set and remove anything the
// same or smaller from the current set. We need to ensure that the scalar
// type size is larger than the scalar size of the largest type. For
// vectors, we also need to make sure that the total size is no smaller than
// the size of the largest type.
- InputSet = TypeSet(*this);
- MVT Largest = Other.TypeVec[Other.TypeVec.size()-1];
- for (unsigned i = 0; i != TypeVec.size(); ++i) {
- MVT OtherVT = TypeVec[i];
- // Don't compare vector and non-vector types.
- if (OtherVT.isVector() != Largest.isVector())
- continue;
- // The getSizeInBits() check here is only needed for vectors, but is
- // a subset of the scalar check for scalars so no need to qualify.
- if (OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() ||
- OtherVT.getSizeInBits() > Largest.getSizeInBits()) {
- TypeVec.erase(TypeVec.begin()+i--);
- MadeChange = true;
+ {
+ TypeSet InputSet(*this);
+ MVT Largest = *std::max_element(Other.TypeVec.begin(), Other.TypeVec.end(),
+ [](MVT A, MVT B) {
+ return A.getScalarSizeInBits() < B.getScalarSizeInBits() ||
+ (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
+ A.getSizeInBits() < B.getSizeInBits());
+ });
+ auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
+ [Largest](MVT OtherVT) {
+ // Don't compare vector and non-vector types.
+ if (OtherVT.isVector() != Largest.isVector())
+ return false;
+ return OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() ||
+ OtherVT.getSizeInBits() > Largest.getSizeInBits();
+ });
+ MadeChange |= I != TypeVec.end(); // If we're about to remove types.
+ TypeVec.erase(I, TypeVec.end());
+
+ if (TypeVec.empty()) {
+ TP.error("Type inference contradiction found, '" + InputSet.getName() +
+ "' has nothing smaller than '" + Other.getName() +"'!");
+ return false;
}
}
- if (TypeVec.empty()) {
- TP.error("Type inference contradiction found, '" + InputSet.getName() +
- "' has nothing smaller than '" + Other.getName() +"'!");
- return false;
- }
-
return MadeChange;
}
-/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
+/// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
/// whose element is specified by VTOperand.
bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT,
TreePattern &TP) {
@@ -467,24 +460,24 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT,
TypeSet InputSet(*this);
// Filter out all the types which don't have the right element type.
- for (unsigned i = 0; i != TypeVec.size(); ++i) {
- assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
- if (MVT(TypeVec[i]).getVectorElementType().SimpleTy != VT) {
- TypeVec.erase(TypeVec.begin()+i--);
- MadeChange = true;
- }
- }
+ auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
+ [VT](MVT VVT) {
+ return VVT.getVectorElementType().SimpleTy != VT;
+ });
+ MadeChange |= I != TypeVec.end();
+ TypeVec.erase(I, TypeVec.end());
if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
TP.error("Type inference contradiction found, forcing '" +
- InputSet.getName() + "' to have a vector element");
+ InputSet.getName() + "' to have a vector element of type " +
+ getEnumName(VT));
return false;
}
return MadeChange;
}
-/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
+/// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
/// whose element is specified by VTOperand.
bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
TreePattern &TP) {
@@ -500,8 +493,7 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
if (isConcrete()) {
MVT IVT = getConcrete();
IVT = IVT.getVectorElementType();
- return MadeChange |
- VTOperand.MergeInTypeInfo(IVT.SimpleTy, TP);
+ return MadeChange || VTOperand.MergeInTypeInfo(IVT.SimpleTy, TP);
}
// If the scalar type is known, filter out vector types whose element types
@@ -511,26 +503,12 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
MVT::SimpleValueType VT = VTOperand.getConcrete();
- TypeSet InputSet(*this);
-
- // Filter out all the types which don't have the right element type.
- for (unsigned i = 0; i != TypeVec.size(); ++i) {
- assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
- if (MVT(TypeVec[i]).getVectorElementType().SimpleTy != VT) {
- TypeVec.erase(TypeVec.begin()+i--);
- MadeChange = true;
- }
- }
+ MadeChange |= EnforceVectorEltTypeIs(VT, TP);
- if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
- TP.error("Type inference contradiction found, forcing '" +
- InputSet.getName() + "' to have a vector element");
- return false;
- }
return MadeChange;
}
-/// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to be a
+/// EnforceVectorSubVectorTypeIs - 'this' is now constrained to be a
/// vector type specified by VTOperand.
bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
TreePattern &TP) {
@@ -569,13 +547,13 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
// Only keep types that have less elements than VTOperand.
TypeSet InputSet(VTOperand);
- for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) {
- assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work");
- if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() >= NumElems) {
- VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--);
- MadeChange = true;
- }
- }
+ auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(),
+ [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() >= NumElems;
+ });
+ MadeChange |= I != VTOperand.TypeVec.end();
+ VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
+
if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
TP.error("Type inference contradiction found, forcing '" +
InputSet.getName() + "' to have less vector elements than '" +
@@ -593,13 +571,13 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
// Only keep types that have more elements than 'this'.
TypeSet InputSet(*this);
- for (unsigned i = 0; i != TypeVec.size(); ++i) {
- assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
- if (MVT(TypeVec[i]).getVectorNumElements() <= NumElems) {
- TypeVec.erase(TypeVec.begin()+i--);
- MadeChange = true;
- }
- }
+ auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
+ [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() <= NumElems;
+ });
+ MadeChange |= I != TypeVec.end();
+ TypeVec.erase(I, TypeVec.end());
+
if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
TP.error("Type inference contradiction found, forcing '" +
InputSet.getName() + "' to have more vector elements than '" +
@@ -611,7 +589,7 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
return MadeChange;
}
-/// EnforceVectorSameNumElts - 'this' is now constrainted to
+/// EnforceVectorSameNumElts - 'this' is now constrained to
/// be a vector with same num elements as VTOperand.
bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand,
TreePattern &TP) {
@@ -628,16 +606,16 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand,
MVT IVT = getConcrete();
unsigned NumElems = IVT.getVectorNumElements();
- // Only keep types that have same elements as VTOperand.
+ // Only keep types that have same elements as 'this'.
TypeSet InputSet(VTOperand);
- for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) {
- assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work");
- if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() != NumElems) {
- VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--);
- MadeChange = true;
- }
- }
+ auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(),
+ [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() != NumElems;
+ });
+ MadeChange |= I != VTOperand.TypeVec.end();
+ VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
+
if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
TP.error("Type inference contradiction found, forcing '" +
InputSet.getName() + "' to have same number elements as '" +
@@ -648,16 +626,16 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand,
MVT IVT = VTOperand.getConcrete();
unsigned NumElems = IVT.getVectorNumElements();
- // Only keep types that have same elements as 'this'.
+ // Only keep types that have same elements as VTOperand.
TypeSet InputSet(*this);
- for (unsigned i = 0; i != TypeVec.size(); ++i) {
- assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
- if (MVT(TypeVec[i]).getVectorNumElements() != NumElems) {
- TypeVec.erase(TypeVec.begin()+i--);
- MadeChange = true;
- }
- }
+ auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
+ [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() != NumElems;
+ });
+ MadeChange |= I != TypeVec.end();
+ TypeVec.erase(I, TypeVec.end());
+
if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
TP.error("Type inference contradiction found, forcing '" +
InputSet.getName() + "' to have same number elements than '" +
@@ -669,15 +647,66 @@ bool EEVT::TypeSet::EnforceVectorSameNumElts(EEVT::TypeSet &VTOperand,
return MadeChange;
}
+/// EnforceSameSize - 'this' is now constrained to be same size as VTOperand.
+bool EEVT::TypeSet::EnforceSameSize(EEVT::TypeSet &VTOperand,
+ TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
+ bool MadeChange = false;
+
+ // If we know one of the types, it forces the other type agree.
+ if (isConcrete()) {
+ MVT IVT = getConcrete();
+ unsigned Size = IVT.getSizeInBits();
+
+ // Only keep types that have the same size as 'this'.
+ TypeSet InputSet(VTOperand);
+
+ auto I = std::remove_if(VTOperand.TypeVec.begin(), VTOperand.TypeVec.end(),
+ [&](MVT VT) {
+ return VT.getSizeInBits() != Size;
+ });
+ MadeChange |= I != VTOperand.TypeVec.end();
+ VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
+
+ if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have same size as '" +
+ getName() + "'");
+ return false;
+ }
+ } else if (VTOperand.isConcrete()) {
+ MVT IVT = VTOperand.getConcrete();
+ unsigned Size = IVT.getSizeInBits();
+
+ // Only keep types that have the same size as VTOperand.
+ TypeSet InputSet(*this);
+
+ auto I = std::remove_if(TypeVec.begin(), TypeVec.end(),
+ [&](MVT VT) {
+ return VT.getSizeInBits() != Size;
+ });
+ MadeChange |= I != TypeVec.end();
+ TypeVec.erase(I, TypeVec.end());
+
+ if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have same size as '" +
+ VTOperand.getName() + "'");
+ return false;
+ }
+ }
+
+ return MadeChange;
+}
+
//===----------------------------------------------------------------------===//
// Helpers for working with extended types.
/// Dependent variable map for CodeGenDAGPattern variant generation
typedef std::map<std::string, int> DepVarMap;
-/// Const iterator shorthand for DepVarMap
-typedef DepVarMap::const_iterator DepVarMap_citer;
-
static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) {
if (N->isLeaf()) {
if (isa<DefInit>(N->getLeafValue()))
@@ -692,9 +721,9 @@ static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) {
static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) {
DepVarMap depcounts;
FindDepVarsOf(N, depcounts);
- for (DepVarMap_citer i = depcounts.begin(); i != depcounts.end(); ++i) {
- if (i->second > 1) // std::pair<std::string, int>
- DepVars.insert(i->first);
+ for (const std::pair<std::string, int> &Pair : depcounts) {
+ if (Pair.second > 1)
+ DepVars.insert(Pair.first);
}
}
@@ -705,9 +734,8 @@ static void DumpDepVars(MultipleUseVarSet &DepVars) {
DEBUG(errs() << "<empty set>");
} else {
DEBUG(errs() << "[ ");
- for (MultipleUseVarSet::const_iterator i = DepVars.begin(),
- e = DepVars.end(); i != e; ++i) {
- DEBUG(errs() << (*i) << " ");
+ for (const std::string &DepVar : DepVars) {
+ DEBUG(errs() << DepVar << " ");
}
DEBUG(errs() << "]");
}
@@ -771,7 +799,7 @@ std::string TreePredicateFn::getCodeToRunOnSDNode() const {
if (ClassName == "SDNode")
Result = " SDNode *N = Node;\n";
else
- Result = " " + ClassName + "*N = cast<" + ClassName + ">(Node);\n";
+ Result = " auto *N = cast<" + ClassName + ">(Node);\n";
return Result + getPredCode();
}
@@ -841,7 +869,7 @@ getPatternComplexity(const CodeGenDAGPatterns &CGP) const {
/// pattern's predicates concatenated with "&&" operators.
///
std::string PatternToMatch::getPredicateCheck() const {
- std::string PredicateCheck;
+ SmallVector<Record *, 4> PredicateRecs;
for (Init *I : Predicates->getValues()) {
if (DefInit *Pred = dyn_cast<DefInit>(I)) {
Record *Def = Pred->getDef();
@@ -851,13 +879,20 @@ std::string PatternToMatch::getPredicateCheck() const {
#endif
llvm_unreachable("Unknown predicate type!");
}
- if (!PredicateCheck.empty())
- PredicateCheck += " && ";
- PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";
+ PredicateRecs.push_back(Def);
}
}
+ // Sort so that different orders get canonicalized to the same string.
+ std::sort(PredicateRecs.begin(), PredicateRecs.end(), LessRecord());
+
+ SmallString<128> PredicateCheck;
+ for (Record *Pred : PredicateRecs) {
+ if (!PredicateCheck.empty())
+ PredicateCheck += " && ";
+ PredicateCheck += "(" + Pred->getValueAsString("CondString") + ")";
+ }
- return PredicateCheck;
+ return PredicateCheck.str();
}
//===----------------------------------------------------------------------===//
@@ -912,6 +947,10 @@ SDTypeConstraint::SDTypeConstraint(Record *R) {
ConstraintType = SDTCisSameNumEltsAs;
x.SDTCisSameNumEltsAs_Info.OtherOperandNum =
R->getValueAsInt("OtherOperandNum");
+ } else if (R->isSubClassOf("SDTCisSameSizeAs")) {
+ ConstraintType = SDTCisSameSizeAs;
+ x.SDTCisSameSizeAs_Info.OtherOperandNum =
+ R->getValueAsInt("OtherOperandNum");
} else {
PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
}
@@ -1041,6 +1080,14 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
return OtherNode->getExtType(OResNo).
EnforceVectorSameNumElts(NodeToApply->getExtType(ResNo), TP);
}
+ case SDTCisSameSizeAs: {
+ unsigned OResNo = 0;
+ TreePatternNode *OtherNode =
+ getOperandNum(x.SDTCisSameSizeAs_Info.OtherOperandNum,
+ N, NodeInfo, OResNo);
+ return OtherNode->getExtType(OResNo).
+ EnforceSameSize(NodeToApply->getExtType(ResNo), TP);
+ }
}
llvm_unreachable("Invalid ConstraintType!");
}
@@ -1091,33 +1138,32 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
// Parse the properties.
Properties = 0;
- std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
- for (unsigned i = 0, e = PropList.size(); i != e; ++i) {
- if (PropList[i]->getName() == "SDNPCommutative") {
+ for (Record *Property : R->getValueAsListOfDefs("Properties")) {
+ if (Property->getName() == "SDNPCommutative") {
Properties |= 1 << SDNPCommutative;
- } else if (PropList[i]->getName() == "SDNPAssociative") {
+ } else if (Property->getName() == "SDNPAssociative") {
Properties |= 1 << SDNPAssociative;
- } else if (PropList[i]->getName() == "SDNPHasChain") {
+ } else if (Property->getName() == "SDNPHasChain") {
Properties |= 1 << SDNPHasChain;
- } else if (PropList[i]->getName() == "SDNPOutGlue") {
+ } else if (Property->getName() == "SDNPOutGlue") {
Properties |= 1 << SDNPOutGlue;
- } else if (PropList[i]->getName() == "SDNPInGlue") {
+ } else if (Property->getName() == "SDNPInGlue") {
Properties |= 1 << SDNPInGlue;
- } else if (PropList[i]->getName() == "SDNPOptInGlue") {
+ } else if (Property->getName() == "SDNPOptInGlue") {
Properties |= 1 << SDNPOptInGlue;
- } else if (PropList[i]->getName() == "SDNPMayStore") {
+ } else if (Property->getName() == "SDNPMayStore") {
Properties |= 1 << SDNPMayStore;
- } else if (PropList[i]->getName() == "SDNPMayLoad") {
+ } else if (Property->getName() == "SDNPMayLoad") {
Properties |= 1 << SDNPMayLoad;
- } else if (PropList[i]->getName() == "SDNPSideEffect") {
+ } else if (Property->getName() == "SDNPSideEffect") {
Properties |= 1 << SDNPSideEffect;
- } else if (PropList[i]->getName() == "SDNPMemOperand") {
+ } else if (Property->getName() == "SDNPMemOperand") {
Properties |= 1 << SDNPMemOperand;
- } else if (PropList[i]->getName() == "SDNPVariadic") {
+ } else if (Property->getName() == "SDNPVariadic") {
Properties |= 1 << SDNPVariadic;
} else {
PrintFatalError("Unknown SD Node property '" +
- PropList[i]->getName() + "' on node '" +
+ Property->getName() + "' on node '" +
R->getName() + "'!");
}
}
@@ -1138,15 +1184,15 @@ MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const {
"We only work with nodes with zero or one result so far!");
assert(ResNo == 0 && "Only handles single result nodes so far");
- for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) {
+ for (const SDTypeConstraint &Constraint : TypeConstraints) {
// Make sure that this applies to the correct node result.
- if (TypeConstraints[i].OperandNo >= NumResults) // FIXME: need value #
+ if (Constraint.OperandNo >= NumResults) // FIXME: need value #
continue;
- switch (TypeConstraints[i].ConstraintType) {
+ switch (Constraint.ConstraintType) {
default: break;
case SDTypeConstraint::SDTCisVT:
- return TypeConstraints[i].x.SDTCisVT_Info.VT;
+ return Constraint.x.SDTCisVT_Info.VT;
case SDTypeConstraint::SDTCisPtrTy:
return MVT::iPTR;
}
@@ -1247,8 +1293,8 @@ void TreePatternNode::print(raw_ostream &OS) const {
OS << ")";
}
- for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i)
- OS << "<<P:" << PredicateFns[i].getFnName() << ">>";
+ for (const TreePredicateFn &Pred : PredicateFns)
+ OS << "<<P:" << Pred.getFnName() << ">>";
if (TransformFn)
OS << "<<X:" << TransformFn->getName() << ">>";
if (!getName().empty())
@@ -1315,8 +1361,8 @@ TreePatternNode *TreePatternNode::clone() const {
/// RemoveAllTypes - Recursively strip all the types of this tree.
void TreePatternNode::RemoveAllTypes() {
- for (unsigned i = 0, e = Types.size(); i != e; ++i)
- Types[i] = EEVT::TypeSet(); // Reset to unknown type.
+ // Reset to unknown type.
+ std::fill(Types.begin(), Types.end(), EEVT::TypeSet());
if (isLeaf()) return;
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
getChild(i)->RemoveAllTypes();
@@ -1410,8 +1456,8 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
FragTree->UpdateNodeType(i, getExtType(i), TP);
// Transfer in the old predicates.
- for (unsigned i = 0, e = getPredicateFns().size(); i != e; ++i)
- FragTree->addPredicateFn(getPredicateFns()[i]);
+ for (const TreePredicateFn &Pred : getPredicateFns())
+ FragTree->addPredicateFn(Pred);
// Get a new copy of this fragment to stitch into here.
//delete this; // FIXME: implement refcounting!
@@ -2024,8 +2070,8 @@ void TreePattern::error(const Twine &Msg) {
}
void TreePattern::ComputeNamedNodes() {
- for (unsigned i = 0, e = Trees.size(); i != e; ++i)
- ComputeNamedNodes(Trees[i]);
+ for (TreePatternNode *Tree : Trees)
+ ComputeNamedNodes(Tree);
}
void TreePattern::ComputeNamedNodes(TreePatternNode *N) {
@@ -2251,53 +2297,52 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
bool MadeChange = true;
while (MadeChange) {
MadeChange = false;
- for (unsigned i = 0, e = Trees.size(); i != e; ++i) {
- MadeChange |= Trees[i]->ApplyTypeConstraints(*this, false);
- MadeChange |= SimplifyTree(Trees[i]);
+ for (TreePatternNode *Tree : Trees) {
+ MadeChange |= Tree->ApplyTypeConstraints(*this, false);
+ MadeChange |= SimplifyTree(Tree);
}
// If there are constraints on our named nodes, apply them.
- for (StringMap<SmallVector<TreePatternNode*,1> >::iterator
- I = NamedNodes.begin(), E = NamedNodes.end(); I != E; ++I) {
- SmallVectorImpl<TreePatternNode*> &Nodes = I->second;
+ for (auto &Entry : NamedNodes) {
+ SmallVectorImpl<TreePatternNode*> &Nodes = Entry.second;
// If we have input named node types, propagate their types to the named
// values here.
if (InNamedTypes) {
- if (!InNamedTypes->count(I->getKey())) {
- error("Node '" + std::string(I->getKey()) +
+ if (!InNamedTypes->count(Entry.getKey())) {
+ error("Node '" + std::string(Entry.getKey()) +
"' in output pattern but not input pattern");
return true;
}
const SmallVectorImpl<TreePatternNode*> &InNodes =
- InNamedTypes->find(I->getKey())->second;
+ InNamedTypes->find(Entry.getKey())->second;
// The input types should be fully resolved by now.
- for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
+ for (TreePatternNode *Node : Nodes) {
// If this node is a register class, and it is the root of the pattern
// then we're mapping something onto an input register. We allow
// changing the type of the input register in this case. This allows
// us to match things like:
// def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>;
- if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) {
- DefInit *DI = dyn_cast<DefInit>(Nodes[i]->getLeafValue());
+ if (Node == Trees[0] && Node->isLeaf()) {
+ DefInit *DI = dyn_cast<DefInit>(Node->getLeafValue());
if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
DI->getDef()->isSubClassOf("RegisterOperand")))
continue;
}
- assert(Nodes[i]->getNumTypes() == 1 &&
+ assert(Node->getNumTypes() == 1 &&
InNodes[0]->getNumTypes() == 1 &&
"FIXME: cannot name multiple result nodes yet");
- MadeChange |= Nodes[i]->UpdateNodeType(0, InNodes[0]->getExtType(0),
- *this);
+ MadeChange |= Node->UpdateNodeType(0, InNodes[0]->getExtType(0),
+ *this);
}
}
// If there are multiple nodes with the same name, they must all have the
// same type.
- if (I->second.size() > 1) {
+ if (Entry.second.size() > 1) {
for (unsigned i = 0, e = Nodes.size()-1; i != e; ++i) {
TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1];
assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 &&
@@ -2311,8 +2356,8 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
}
bool HasUnresolvedTypes = false;
- for (unsigned i = 0, e = Trees.size(); i != e; ++i)
- HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType();
+ for (const TreePatternNode *Tree : Trees)
+ HasUnresolvedTypes |= Tree->ContainsUnresolvedType();
return !HasUnresolvedTypes;
}
@@ -2328,9 +2373,9 @@ void TreePattern::print(raw_ostream &OS) const {
if (Trees.size() > 1)
OS << "[\n";
- for (unsigned i = 0, e = Trees.size(); i != e; ++i) {
+ for (const TreePatternNode *Tree : Trees) {
OS << "\t";
- Trees[i]->print(OS);
+ Tree->print(OS);
OS << "\n";
}
@@ -2425,14 +2470,14 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag");
// First step, parse all of the fragments.
- for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
- if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag"))
+ for (Record *Frag : Fragments) {
+ if (OutFrags != Frag->isSubClassOf("OutPatFrag"))
continue;
- DagInit *Tree = Fragments[i]->getValueAsDag("Fragment");
+ DagInit *Tree = Frag->getValueAsDag("Fragment");
TreePattern *P =
- (PatternFragments[Fragments[i]] = llvm::make_unique<TreePattern>(
- Fragments[i], Tree, !Fragments[i]->isSubClassOf("OutPatFrag"),
+ (PatternFragments[Frag] = llvm::make_unique<TreePattern>(
+ Frag, Tree, !Frag->isSubClassOf("OutPatFrag"),
*this)).get();
// Validate the argument list, converting it to set, to discard duplicates.
@@ -2443,7 +2488,7 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
P->error("Cannot have unnamed 'node' values in pattern fragment!");
// Parse the operands list.
- DagInit *OpsList = Fragments[i]->getValueAsDag("Operands");
+ DagInit *OpsList = Frag->getValueAsDag("Operands");
DefInit *OpsOp = dyn_cast<DefInit>(OpsList->getOperator());
// Special cases: ops == outs == ins. Different names are used to
// improve readability.
@@ -2480,18 +2525,18 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
// If there is a node transformation corresponding to this, keep track of
// it.
- Record *Transform = Fragments[i]->getValueAsDef("OperandTransform");
+ Record *Transform = Frag->getValueAsDef("OperandTransform");
if (!getSDNodeTransform(Transform).second.empty()) // not noop xform?
P->getOnlyTree()->setTransformFn(Transform);
}
// Now that we've parsed all of the tree fragments, do a closure on them so
// that there are not references to PatFrags left inside of them.
- for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
- if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag"))
+ for (Record *Frag : Fragments) {
+ if (OutFrags != Frag->isSubClassOf("OutPatFrag"))
continue;
- TreePattern &ThePat = *PatternFragments[Fragments[i]];
+ TreePattern &ThePat = *PatternFragments[Frag];
ThePat.InlinePatternFragments();
// Infer as many types as possible. Don't worry about it if we don't infer
@@ -2815,7 +2860,7 @@ static bool InferFromPattern(CodeGenInstruction &InstInfo,
if (InstInfo.mayLoad != PatInfo.mayLoad && !InstInfo.mayLoad_Unset) {
// Allow explicitly setting mayLoad = 1, even when the pattern has no loads.
- // Some targets translate imediates to loads.
+ // Some targets translate immediates to loads.
if (!InstInfo.mayLoad) {
Error = true;
PrintError(PatDef->getLoc(), "Pattern doesn't match mayLoad = " +
@@ -3065,11 +3110,11 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
void CodeGenDAGPatterns::ParseInstructions() {
std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction");
- for (unsigned i = 0, e = Instrs.size(); i != e; ++i) {
+ for (Record *Instr : Instrs) {
ListInit *LI = nullptr;
- if (isa<ListInit>(Instrs[i]->getValueInit("Pattern")))
- LI = Instrs[i]->getValueAsListInit("Pattern");
+ if (isa<ListInit>(Instr->getValueInit("Pattern")))
+ LI = Instr->getValueAsListInit("Pattern");
// If there is no pattern, only collect minimal information about the
// instruction for its operand list. We have to assume that there is one
@@ -3081,7 +3126,7 @@ void CodeGenDAGPatterns::ParseInstructions() {
std::vector<Record*> Results;
std::vector<Record*> Operands;
- CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]);
+ CodeGenInstruction &InstInfo = Target.getInstruction(Instr);
if (InstInfo.Operands.size() != 0) {
for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j)
@@ -3095,12 +3140,12 @@ void CodeGenDAGPatterns::ParseInstructions() {
// Create and insert the instruction.
std::vector<Record*> ImpResults;
- Instructions.insert(std::make_pair(Instrs[i],
+ Instructions.insert(std::make_pair(Instr,
DAGInstruction(nullptr, Results, Operands, ImpResults)));
continue; // no pattern.
}
- CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]);
+ CodeGenInstruction &CGI = Target.getInstruction(Instr);
const DAGInstruction &DI = parseInstructionPattern(CGI, LI, Instructions);
(void)DI;
@@ -3108,10 +3153,8 @@ void CodeGenDAGPatterns::ParseInstructions() {
}
// If we can, convert the instructions to be patterns that are matched!
- for (std::map<Record*, DAGInstruction, LessRecordByID>::iterator II =
- Instructions.begin(),
- E = Instructions.end(); II != E; ++II) {
- DAGInstruction &TheInst = II->second;
+ for (auto &Entry : Instructions) {
+ DAGInstruction &TheInst = Entry.second;
TreePattern *I = TheInst.getPattern();
if (!I) continue; // No pattern.
@@ -3126,7 +3169,7 @@ void CodeGenDAGPatterns::ParseInstructions() {
SrcPattern = Pattern;
}
- Record *Instr = II->first;
+ Record *Instr = Entry.first;
AddPatternToMatch(I,
PatternToMatch(Instr,
Instr->getValueAsListInit("Predicates"),
@@ -3187,19 +3230,18 @@ void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern,
// Scan all of the named values in the destination pattern, rejecting them if
// they don't exist in the input pattern.
- for (std::map<std::string, NameRecord>::iterator
- I = DstNames.begin(), E = DstNames.end(); I != E; ++I) {
- if (SrcNames[I->first].first == nullptr)
+ for (const auto &Entry : DstNames) {
+ if (SrcNames[Entry.first].first == nullptr)
Pattern->error("Pattern has input without matching name in output: $" +
- I->first);
+ Entry.first);
}
// Scan all of the named values in the source pattern, rejecting them if the
// name isn't used in the dest, and isn't used to tie two values together.
- for (std::map<std::string, NameRecord>::iterator
- I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I)
- if (DstNames[I->first].first == nullptr && SrcNames[I->first].second == 1)
- Pattern->error("Pattern has dead named input: $" + I->first);
+ for (const auto &Entry : SrcNames)
+ if (DstNames[Entry.first].first == nullptr &&
+ SrcNames[Entry.first].second == 1)
+ Pattern->error("Pattern has dead named input: $" + Entry.first);
PatternsToMatch.push_back(PTM);
}
@@ -3258,31 +3300,29 @@ void CodeGenDAGPatterns::InferInstructionFlags() {
// Revisit instructions with undefined flags and no pattern.
if (Target.guessInstructionProperties()) {
- for (unsigned i = 0, e = Revisit.size(); i != e; ++i) {
- CodeGenInstruction &InstInfo = *Revisit[i];
- if (InstInfo.InferredFrom)
+ for (CodeGenInstruction *InstInfo : Revisit) {
+ if (InstInfo->InferredFrom)
continue;
// The mayLoad and mayStore flags default to false.
// Conservatively assume hasSideEffects if it wasn't explicit.
- if (InstInfo.hasSideEffects_Unset)
- InstInfo.hasSideEffects = true;
+ if (InstInfo->hasSideEffects_Unset)
+ InstInfo->hasSideEffects = true;
}
return;
}
// Complain about any flags that are still undefined.
- for (unsigned i = 0, e = Revisit.size(); i != e; ++i) {
- CodeGenInstruction &InstInfo = *Revisit[i];
- if (InstInfo.InferredFrom)
+ for (CodeGenInstruction *InstInfo : Revisit) {
+ if (InstInfo->InferredFrom)
continue;
- if (InstInfo.hasSideEffects_Unset)
- PrintError(InstInfo.TheDef->getLoc(),
+ if (InstInfo->hasSideEffects_Unset)
+ PrintError(InstInfo->TheDef->getLoc(),
"Can't infer hasSideEffects from patterns");
- if (InstInfo.mayStore_Unset)
- PrintError(InstInfo.TheDef->getLoc(),
+ if (InstInfo->mayStore_Unset)
+ PrintError(InstInfo->TheDef->getLoc(),
"Can't infer mayStore from patterns");
- if (InstInfo.mayLoad_Unset)
- PrintError(InstInfo.TheDef->getLoc(),
+ if (InstInfo->mayLoad_Unset)
+ PrintError(InstInfo->TheDef->getLoc(),
"Can't infer mayLoad from patterns");
}
}
@@ -3302,8 +3342,8 @@ void CodeGenDAGPatterns::VerifyInstructionFlags() {
unsigned NumSideEffects = 0;
unsigned NumStores = 0;
unsigned NumLoads = 0;
- for (unsigned i = 0, e = Instrs.size(); i != e; ++i) {
- const CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]);
+ for (const Record *Instr : Instrs) {
+ const CodeGenInstruction &InstInfo = Target.getInstruction(Instr);
NumSideEffects += InstInfo.hasSideEffects;
NumStores += InstInfo.mayStore;
NumLoads += InstInfo.mayLoad;
@@ -3335,19 +3375,19 @@ void CodeGenDAGPatterns::VerifyInstructionFlags() {
continue;
++Errors;
- for (unsigned i = 0, e = Msgs.size(); i != e; ++i)
- PrintError(PTM.getSrcRecord()->getLoc(), Twine(Msgs[i]) + " on the " +
+ for (const std::string &Msg : Msgs)
+ PrintError(PTM.getSrcRecord()->getLoc(), Twine(Msg) + " on the " +
(Instrs.size() == 1 ?
"instruction" : "output instructions"));
// Provide the location of the relevant instruction definitions.
- for (unsigned i = 0, e = Instrs.size(); i != e; ++i) {
- if (Instrs[i] != PTM.getSrcRecord())
- PrintError(Instrs[i]->getLoc(), "defined here");
- const CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]);
+ for (const Record *Instr : Instrs) {
+ if (Instr != PTM.getSrcRecord())
+ PrintError(Instr->getLoc(), "defined here");
+ const CodeGenInstruction &InstInfo = Target.getInstruction(Instr);
if (InstInfo.InferredFrom &&
InstInfo.InferredFrom != InstInfo.TheDef &&
InstInfo.InferredFrom != PTM.getSrcRecord())
- PrintError(InstInfo.InferredFrom->getLoc(), "inferred from patttern");
+ PrintError(InstInfo.InferredFrom->getLoc(), "inferred from pattern");
}
}
if (Errors)
@@ -3386,8 +3426,7 @@ static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) {
void CodeGenDAGPatterns::ParsePatterns() {
std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern");
- for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
- Record *CurPattern = Patterns[i];
+ for (Record *CurPattern : Patterns) {
DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch");
// If the pattern references the null_frag, there's nothing to do.
@@ -3517,8 +3556,8 @@ static void CombineChildVariants(TreePatternNode *Orig,
CodeGenDAGPatterns &CDP,
const MultipleUseVarSet &DepVars) {
// Make sure that each operand has at least one variant to choose from.
- for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
- if (ChildVariants[i].empty())
+ for (const auto &Variants : ChildVariants)
+ if (Variants.empty())
return;
// The end result is an all-pairs construction of the resultant pattern.
@@ -3529,8 +3568,8 @@ static void CombineChildVariants(TreePatternNode *Orig,
#ifndef NDEBUG
DEBUG(if (!Idxs.empty()) {
errs() << Orig->getOperator()->getName() << ": Idxs = [ ";
- for (unsigned i = 0; i < Idxs.size(); ++i) {
- errs() << Idxs[i] << " ";
+ for (unsigned Idx : Idxs) {
+ errs() << Idx << " ";
}
errs() << "]\n";
});
@@ -3539,8 +3578,8 @@ static void CombineChildVariants(TreePatternNode *Orig,
std::vector<TreePatternNode*> NewChildren;
for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
NewChildren.push_back(ChildVariants[i][Idxs[i]]);
- TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren,
- Orig->getNumTypes());
+ auto R = llvm::make_unique<TreePatternNode>(
+ Orig->getOperator(), NewChildren, Orig->getNumTypes());
// Copy over properties.
R->setName(Orig->getName());
@@ -3551,29 +3590,19 @@ static void CombineChildVariants(TreePatternNode *Orig,
// If this pattern cannot match, do not include it as a variant.
std::string ErrString;
- if (!R->canPatternMatch(ErrString, CDP)) {
- delete R;
- } else {
- bool AlreadyExists = false;
-
- // Scan to see if this pattern has already been emitted. We can get
- // duplication due to things like commuting:
- // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
- // which are the same pattern. Ignore the dups.
- for (unsigned i = 0, e = OutVariants.size(); i != e; ++i)
- if (R->isIsomorphicTo(OutVariants[i], DepVars)) {
- AlreadyExists = true;
- break;
- }
-
- if (AlreadyExists)
- delete R;
- else
- OutVariants.push_back(R);
- }
+ // Scan to see if this pattern has already been emitted. We can get
+ // duplication due to things like commuting:
+ // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
+ // which are the same pattern. Ignore the dups.
+ if (R->canPatternMatch(ErrString, CDP) &&
+ std::none_of(OutVariants.begin(), OutVariants.end(),
+ [&](TreePatternNode *Variant) {
+ return R->isIsomorphicTo(Variant, DepVars);
+ }))
+ OutVariants.push_back(R.release());
// Increment indices to the next permutation by incrementing the
- // indicies from last index backward, e.g., generate the sequence
+ // indices from last index backward, e.g., generate the sequence
// [0, 0], [0, 1], [1, 0], [1, 1].
int IdxsIdx;
for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) {
@@ -3724,7 +3753,7 @@ static void GenerateVariantsOf(TreePatternNode *N,
// operands are the commutative operands, and there might be more operands
// after those.
assert(NC >= 3 &&
- "Commutative intrinsic should have at least 3 childrean!");
+ "Commutative intrinsic should have at least 3 children!");
std::vector<std::vector<TreePatternNode*> > Variants;
Variants.push_back(ChildVariants[0]); // Intrinsic id.
Variants.push_back(ChildVariants[2]);
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
index 9ce3cdfd7bc1..76c9cefea50f 100644
--- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
@@ -132,22 +132,25 @@ namespace EEVT {
/// this an other based on this information.
bool EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP);
- /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
+ /// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
/// whose element is VT.
bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
- /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
+ /// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
/// whose element is VT.
bool EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TreePattern &TP);
- /// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to
+ /// EnforceVectorSubVectorTypeIs - 'this' is now constrained to
/// be a vector type VT.
bool EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
- /// EnforceVectorSameNumElts - 'this' is now constrainted to
+ /// EnforceVectorSameNumElts - 'this' is now constrained to
/// be a vector with same num elements as VT.
bool EnforceVectorSameNumElts(EEVT::TypeSet &VT, TreePattern &TP);
+ /// EnforceSameSize - 'this' is now constrained to be the same size as VT.
+ bool EnforceSameSize(EEVT::TypeSet &VT, TreePattern &TP);
+
bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; }
bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; }
@@ -173,7 +176,7 @@ struct SDTypeConstraint {
enum {
SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec,
- SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs
+ SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs, SDTCisSameSizeAs
} ConstraintType;
union { // The discriminated union.
@@ -201,6 +204,9 @@ struct SDTypeConstraint {
struct {
unsigned OtherOperandNum;
} SDTCisSameNumEltsAs_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisSameSizeAs_Info;
} x;
/// ApplyTypeConstraint - Given a node in a pattern, apply this type
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
index e83d5033b182..366e8ec7fac1 100644
--- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -78,6 +78,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
} else if (Rec->isSubClassOf("Operand")) {
PrintMethod = Rec->getValueAsString("PrintMethod");
OperandType = Rec->getValueAsString("OperandType");
+ OperandNamespace = Rec->getValueAsString("OperandNamespace");
// If there is an explicit encoder method, use it.
EncoderMethod = Rec->getValueAsString("EncoderMethod");
MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
diff --git a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
index f4055571b1c7..7bdb7e1bc537 100644
--- a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
+++ b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
@@ -60,9 +60,10 @@ namespace llvm {
IntrinsicSignature IS;
// Memory mod/ref behavior of this intrinsic.
- enum {
+ enum ModRefKind {
NoMem, ReadArgMem, ReadMem, ReadWriteArgMem, ReadWriteMem
- } ModRef;
+ };
+ ModRefKind ModRef;
/// This is set to true if the intrinsic is overloaded by its argument
/// types.
diff --git a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp
index 48df4391fe16..f66dd082709b 100644
--- a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp
@@ -471,7 +471,7 @@ void MapTableEmitter::emitTablesWithFunc(raw_ostream &OS) {
ListInit *ColFields = InstrMapDesc.getColFields();
const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
- OS << "// "<< InstrMapDesc.getName() << "\n";
+ OS << "// "<< InstrMapDesc.getName() << "\nLLVM_READONLY\n";
OS << "int "<< InstrMapDesc.getName() << "(uint16_t Opcode";
if (ValueCols.size() > 1) {
for (Init *CF : ColFields->getValues()) {
diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
index c9e6d1d379de..ca316e96a21a 100644
--- a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
@@ -1171,20 +1171,13 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
CoveringLanes = ~0u;
for (auto &Idx : SubRegIndices) {
if (Idx.getComposites().empty()) {
+ if (Bit > 32) {
+ PrintFatalError(
+ Twine("Ran out of lanemask bits to represent subregister ")
+ + Idx.getName());
+ }
Idx.LaneMask = 1u << Bit;
- // Share bit 31 in the unlikely case there are more than 32 leafs.
- //
- // Sharing bits is harmless; it allows graceful degradation in targets
- // with more than 32 vector lanes. They simply get a limited resolution
- // view of lanes beyond the 32nd.
- //
- // See also the comment for getSubRegIndexLaneMask().
- if (Bit < 31)
- ++Bit;
- else
- // Once bit 31 is shared among multiple leafs, the 'lane' it represents
- // is no longer covering its registers.
- CoveringLanes &= ~(1u << Bit);
+ ++Bit;
} else {
Idx.LaneMask = 0;
}
@@ -1274,6 +1267,12 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
continue;
LaneMask |= SubRegIndex.LaneMask;
}
+
+ // For classes without any subregisters set LaneMask to ~0u instead of 0.
+ // This makes it easier for client code to handle classes uniformly.
+ if (LaneMask == 0)
+ LaneMask = ~0u;
+
RegClass.LaneMask = LaneMask;
}
}
@@ -1568,6 +1567,12 @@ void CodeGenRegBank::pruneUnitSets() {
&& UnitWeight == RegUnits[SuperSet.Units.back()].Weight) {
DEBUG(dbgs() << "UnitSet " << SubIdx << " subsumed by " << SuperIdx
<< "\n");
+ // We can pick any of the set names for the merged set. Go for the
+ // shortest one to avoid picking the name of one of the classes that are
+ // artificially created by tablegen. So "FPR128_lo" instead of
+ // "QQQQ_with_qsub3_in_FPR128_lo".
+ if (RegUnitSets[SubIdx].Name.size() < RegUnitSets[SuperIdx].Name.size())
+ RegUnitSets[SuperIdx].Name = RegUnitSets[SubIdx].Name;
break;
}
}
diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
index bc27481869fe..c98f62345342 100644
--- a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
@@ -24,15 +24,9 @@ using namespace llvm;
#define DEBUG_TYPE "subtarget-emitter"
#ifndef NDEBUG
-static void dumpIdxVec(const IdxVec &V) {
- for (unsigned i = 0, e = V.size(); i < e; ++i) {
- dbgs() << V[i] << ", ";
- }
-}
-static void dumpIdxVec(const SmallVectorImpl<unsigned> &V) {
- for (unsigned i = 0, e = V.size(); i < e; ++i) {
- dbgs() << V[i] << ", ";
- }
+static void dumpIdxVec(ArrayRef<unsigned> V) {
+ for (unsigned Idx : V)
+ dbgs() << Idx << ", ";
}
#endif
@@ -326,9 +320,9 @@ void CodeGenSchedModels::collectSchedRW() {
}
/// Compute a SchedWrite name from a sequence of writes.
-std::string CodeGenSchedModels::genRWName(const IdxVec& Seq, bool IsRead) {
+std::string CodeGenSchedModels::genRWName(ArrayRef<unsigned> Seq, bool IsRead) {
std::string Name("(");
- for (IdxIter I = Seq.begin(), E = Seq.end(); I != E; ++I) {
+ for (auto I = Seq.begin(), E = Seq.end(); I != E; ++I) {
if (I != Seq.begin())
Name += '_';
Name += getSchedRW(*I, IsRead).Name;
@@ -457,13 +451,13 @@ void CodeGenSchedModels::expandRWSeqForProc(
}
// Find the existing SchedWrite that models this sequence of writes.
-unsigned CodeGenSchedModels::findRWForSequence(const IdxVec &Seq,
+unsigned CodeGenSchedModels::findRWForSequence(ArrayRef<unsigned> Seq,
bool IsRead) {
std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;
for (std::vector<CodeGenSchedRW>::iterator I = RWVec.begin(), E = RWVec.end();
I != E; ++I) {
- if (I->Sequence == Seq)
+ if (makeArrayRef(I->Sequence) == Seq)
return I - RWVec.begin();
}
// Index zero reserved for invalid RW.
@@ -585,11 +579,11 @@ void CodeGenSchedModels::collectSchedClasses() {
/// Find an SchedClass that has been inferred from a per-operand list of
/// SchedWrites and SchedReads.
unsigned CodeGenSchedModels::findSchedClassIdx(Record *ItinClassDef,
- const IdxVec &Writes,
- const IdxVec &Reads) const {
+ ArrayRef<unsigned> Writes,
+ ArrayRef<unsigned> Reads) const {
for (SchedClassIter I = schedClassBegin(), E = schedClassEnd(); I != E; ++I) {
- if (I->ItinClassDef == ItinClassDef
- && I->Writes == Writes && I->Reads == Reads) {
+ if (I->ItinClassDef == ItinClassDef && makeArrayRef(I->Writes) == Writes &&
+ makeArrayRef(I->Reads) == Reads) {
return I - schedClassBegin();
}
}
@@ -603,20 +597,22 @@ unsigned CodeGenSchedModels::getSchedClassIdx(
return InstrClassMap.lookup(Inst.TheDef);
}
-std::string CodeGenSchedModels::createSchedClassName(
- Record *ItinClassDef, const IdxVec &OperWrites, const IdxVec &OperReads) {
+std::string
+CodeGenSchedModels::createSchedClassName(Record *ItinClassDef,
+ ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads) {
std::string Name;
if (ItinClassDef && ItinClassDef->getName() != "NoItinerary")
Name = ItinClassDef->getName();
- for (IdxIter WI = OperWrites.begin(), WE = OperWrites.end(); WI != WE; ++WI) {
+ for (unsigned Idx : OperWrites) {
if (!Name.empty())
Name += '_';
- Name += SchedWrites[*WI].Name;
+ Name += SchedWrites[Idx].Name;
}
- for (IdxIter RI = OperReads.begin(), RE = OperReads.end(); RI != RE; ++RI) {
+ for (unsigned Idx : OperReads) {
Name += '_';
- Name += SchedReads[*RI].Name;
+ Name += SchedReads[Idx].Name;
}
return Name;
}
@@ -636,10 +632,9 @@ std::string CodeGenSchedModels::createSchedClassName(const RecVec &InstDefs) {
/// SchedWrites and SchedReads. ProcIndices contains the set of IDs of
/// processors that may utilize this class.
unsigned CodeGenSchedModels::addSchedClass(Record *ItinClassDef,
- const IdxVec &OperWrites,
- const IdxVec &OperReads,
- const IdxVec &ProcIndices)
-{
+ ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads,
+ ArrayRef<unsigned> ProcIndices) {
assert(!ProcIndices.empty() && "expect at least one ProcIdx");
unsigned Idx = findSchedClassIdx(ItinClassDef, OperWrites, OperReads);
@@ -1322,10 +1317,10 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
// Create new SchedClasses for the given ReadWrite list. If any of the
// ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
// of the ReadWrite list, following Aliases if necessary.
-void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites,
- const IdxVec &OperReads,
+void CodeGenSchedModels::inferFromRW(ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads,
unsigned FromClassIdx,
- const IdxVec &ProcIndices) {
+ ArrayRef<unsigned> ProcIndices) {
DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices); dbgs() << ") ");
// Create a seed transition with an empty PredTerm and the expanded sequences
@@ -1335,9 +1330,9 @@ void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites,
LastTransitions.back().ProcIndices.append(ProcIndices.begin(),
ProcIndices.end());
- for (IdxIter I = OperWrites.begin(), E = OperWrites.end(); I != E; ++I) {
+ for (unsigned WriteIdx : OperWrites) {
IdxVec WriteSeq;
- expandRWSequence(*I, WriteSeq, /*IsRead=*/false);
+ expandRWSequence(WriteIdx, WriteSeq, /*IsRead=*/false);
unsigned Idx = LastTransitions[0].WriteSequences.size();
LastTransitions[0].WriteSequences.resize(Idx + 1);
SmallVectorImpl<unsigned> &Seq = LastTransitions[0].WriteSequences[Idx];
@@ -1346,9 +1341,9 @@ void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites,
DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") ");
}
DEBUG(dbgs() << " Reads: ");
- for (IdxIter I = OperReads.begin(), E = OperReads.end(); I != E; ++I) {
+ for (unsigned ReadIdx : OperReads) {
IdxVec ReadSeq;
- expandRWSequence(*I, ReadSeq, /*IsRead=*/true);
+ expandRWSequence(ReadIdx, ReadSeq, /*IsRead=*/true);
unsigned Idx = LastTransitions[0].ReadSequences.size();
LastTransitions[0].ReadSequences.resize(Idx + 1);
SmallVectorImpl<unsigned> &Seq = LastTransitions[0].ReadSequences[Idx];
@@ -1552,20 +1547,16 @@ void CodeGenSchedModels::collectItinProcResources(Record *ItinClassDef) {
}
void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead,
- const IdxVec &ProcIndices) {
+ ArrayRef<unsigned> ProcIndices) {
const CodeGenSchedRW &SchedRW = getSchedRW(RWIdx, IsRead);
if (SchedRW.TheDef) {
if (!IsRead && SchedRW.TheDef->isSubClassOf("SchedWriteRes")) {
- for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
- PI != PE; ++PI) {
- addWriteRes(SchedRW.TheDef, *PI);
- }
+ for (unsigned Idx : ProcIndices)
+ addWriteRes(SchedRW.TheDef, Idx);
}
else if (IsRead && SchedRW.TheDef->isSubClassOf("SchedReadAdvance")) {
- for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
- PI != PE; ++PI) {
- addReadAdvance(SchedRW.TheDef, *PI);
- }
+ for (unsigned Idx : ProcIndices)
+ addReadAdvance(SchedRW.TheDef, Idx);
}
}
for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
@@ -1590,15 +1581,15 @@ void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead,
}
// Collect resources for a set of read/write types and processor indices.
-void CodeGenSchedModels::collectRWResources(const IdxVec &Writes,
- const IdxVec &Reads,
- const IdxVec &ProcIndices) {
+void CodeGenSchedModels::collectRWResources(ArrayRef<unsigned> Writes,
+ ArrayRef<unsigned> Reads,
+ ArrayRef<unsigned> ProcIndices) {
- for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI)
- collectRWResources(*WI, /*IsRead=*/false, ProcIndices);
+ for (unsigned Idx : Writes)
+ collectRWResources(Idx, /*IsRead=*/false, ProcIndices);
- for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI)
- collectRWResources(*RI, /*IsRead=*/true, ProcIndices);
+ for (unsigned Idx : Reads)
+ collectRWResources(Idx, /*IsRead=*/true, ProcIndices);
}
diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.h b/contrib/llvm/utils/TableGen/CodeGenSchedule.h
index e5241b9d5fda..f5c50c992a92 100644
--- a/contrib/llvm/utils/TableGen/CodeGenSchedule.h
+++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.h
@@ -72,10 +72,10 @@ struct CodeGenSchedRW {
IsSequence = Def->isSubClassOf("WriteSequence");
}
- CodeGenSchedRW(unsigned Idx, bool Read, const IdxVec &Seq,
+ CodeGenSchedRW(unsigned Idx, bool Read, ArrayRef<unsigned> Seq,
const std::string &Name)
- : Index(Idx), Name(Name), TheDef(nullptr), IsRead(Read), IsAlias(false),
- HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) {
+ : Index(Idx), Name(Name), TheDef(nullptr), IsRead(Read), IsAlias(false),
+ HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) {
assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");
}
@@ -144,8 +144,9 @@ struct CodeGenSchedClass {
CodeGenSchedClass(): Index(0), ItinClassDef(nullptr) {}
- bool isKeyEqual(Record *IC, const IdxVec &W, const IdxVec &R) {
- return ItinClassDef == IC && Writes == W && Reads == R;
+ bool isKeyEqual(Record *IC, ArrayRef<unsigned> W, ArrayRef<unsigned> R) {
+ return ItinClassDef == IC && makeArrayRef(Writes) == W &&
+ makeArrayRef(Reads) == R;
}
// Is this class generated from a variants if existing classes? Instructions
@@ -256,18 +257,16 @@ public:
class_iterator classes_end() { return SchedClasses.end(); }
const_class_iterator classes_end() const { return SchedClasses.end(); }
iterator_range<class_iterator> classes() {
- return iterator_range<class_iterator>(classes_begin(), classes_end());
+ return make_range(classes_begin(), classes_end());
}
iterator_range<const_class_iterator> classes() const {
- return iterator_range<const_class_iterator>(classes_begin(), classes_end());
+ return make_range(classes_begin(), classes_end());
}
iterator_range<class_iterator> explicit_classes() {
- return iterator_range<class_iterator>(
- classes_begin(), classes_begin() + NumInstrSchedClasses);
+ return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses);
}
iterator_range<const_class_iterator> explicit_classes() const {
- return iterator_range<const_class_iterator>(
- classes_begin(), classes_begin() + NumInstrSchedClasses);
+ return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses);
}
Record *getModelOrItinDef(Record *ProcDef) const {
@@ -363,14 +362,14 @@ public:
void expandRWSeqForProc(unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
const CodeGenProcModel &ProcModel) const;
- unsigned addSchedClass(Record *ItinDef, const IdxVec &OperWrites,
- const IdxVec &OperReads, const IdxVec &ProcIndices);
+ unsigned addSchedClass(Record *ItinDef, ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads,
+ ArrayRef<unsigned> ProcIndices);
unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead);
- unsigned findSchedClassIdx(Record *ItinClassDef,
- const IdxVec &Writes,
- const IdxVec &Reads) const;
+ unsigned findSchedClassIdx(Record *ItinClassDef, ArrayRef<unsigned> Writes,
+ ArrayRef<unsigned> Reads) const;
Record *findProcResUnits(Record *ProcResKind,
const CodeGenProcModel &PM) const;
@@ -383,14 +382,14 @@ private:
void collectSchedRW();
- std::string genRWName(const IdxVec& Seq, bool IsRead);
- unsigned findRWForSequence(const IdxVec &Seq, bool IsRead);
+ std::string genRWName(ArrayRef<unsigned> Seq, bool IsRead);
+ unsigned findRWForSequence(ArrayRef<unsigned> Seq, bool IsRead);
void collectSchedClasses();
std::string createSchedClassName(Record *ItinClassDef,
- const IdxVec &OperWrites,
- const IdxVec &OperReads);
+ ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads);
std::string createSchedClassName(const RecVec &InstDefs);
void createInstRWClass(Record *InstRWDef);
@@ -400,8 +399,8 @@ private:
void inferSchedClasses();
- void inferFromRW(const IdxVec &OperWrites, const IdxVec &OperReads,
- unsigned FromClassIdx, const IdxVec &ProcIndices);
+ void inferFromRW(ArrayRef<unsigned> OperWrites, ArrayRef<unsigned> OperReads,
+ unsigned FromClassIdx, ArrayRef<unsigned> ProcIndices);
void inferFromItinClass(Record *ItinClassDef, unsigned FromClassIdx);
void inferFromInstRWs(unsigned SCIdx);
@@ -413,10 +412,10 @@ private:
void collectItinProcResources(Record *ItinClassDef);
void collectRWResources(unsigned RWIdx, bool IsRead,
- const IdxVec &ProcIndices);
+ ArrayRef<unsigned> ProcIndices);
- void collectRWResources(const IdxVec &Writes, const IdxVec &Reads,
- const IdxVec &ProcIndices);
+ void collectRWResources(ArrayRef<unsigned> Writes, ArrayRef<unsigned> Reads,
+ ArrayRef<unsigned> ProcIndices);
void addProcResource(Record *ProcResourceKind, CodeGenProcModel &PM);
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
index 661975ecb202..aaad4225ace8 100644
--- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -76,6 +76,8 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v16i1: return "MVT::v16i1";
case MVT::v32i1: return "MVT::v32i1";
case MVT::v64i1: return "MVT::v64i1";
+ case MVT::v512i1: return "MVT::v512i1";
+ case MVT::v1024i1: return "MVT::v1024i1";
case MVT::v1i8: return "MVT::v1i8";
case MVT::v2i8: return "MVT::v2i8";
case MVT::v4i8: return "MVT::v4i8";
@@ -83,22 +85,29 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v16i8: return "MVT::v16i8";
case MVT::v32i8: return "MVT::v32i8";
case MVT::v64i8: return "MVT::v64i8";
+ case MVT::v128i8: return "MVT::v128i8";
+ case MVT::v256i8: return "MVT::v256i8";
case MVT::v1i16: return "MVT::v1i16";
case MVT::v2i16: return "MVT::v2i16";
case MVT::v4i16: return "MVT::v4i16";
case MVT::v8i16: return "MVT::v8i16";
case MVT::v16i16: return "MVT::v16i16";
case MVT::v32i16: return "MVT::v32i16";
+ case MVT::v64i16: return "MVT::v64i16";
+ case MVT::v128i16: return "MVT::v128i16";
case MVT::v1i32: return "MVT::v1i32";
case MVT::v2i32: return "MVT::v2i32";
case MVT::v4i32: return "MVT::v4i32";
case MVT::v8i32: return "MVT::v8i32";
case MVT::v16i32: return "MVT::v16i32";
+ case MVT::v32i32: return "MVT::v32i32";
+ case MVT::v64i32: return "MVT::v64i32";
case MVT::v1i64: return "MVT::v1i64";
case MVT::v2i64: return "MVT::v2i64";
case MVT::v4i64: return "MVT::v4i64";
case MVT::v8i64: return "MVT::v8i64";
case MVT::v16i64: return "MVT::v16i64";
+ case MVT::v32i64: return "MVT::v32i64";
case MVT::v1i128: return "MVT::v1i128";
case MVT::v2f16: return "MVT::v2f16";
case MVT::v4f16: return "MVT::v4f16";
@@ -112,6 +121,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v2f64: return "MVT::v2f64";
case MVT::v4f64: return "MVT::v4f64";
case MVT::v8f64: return "MVT::v8f64";
+ case MVT::token: return "MVT::token";
case MVT::Metadata: return "MVT::Metadata";
case MVT::iPTR: return "MVT::iPTR";
case MVT::iPTRAny: return "MVT::iPTRAny";
@@ -252,7 +262,7 @@ void CodeGenTarget::ReadLegalValueTypes() const {
LegalValueTypes.insert(LegalValueTypes.end(), RC.VTs.begin(), RC.VTs.end());
// Remove duplicates.
- std::sort(LegalValueTypes.begin(), LegalValueTypes.end());
+ array_pod_sort(LegalValueTypes.begin(), LegalValueTypes.end());
LegalValueTypes.erase(std::unique(LegalValueTypes.begin(),
LegalValueTypes.end()),
LegalValueTypes.end());
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h
index 24b38514260c..cf4a0bbe5bd9 100644
--- a/contrib/llvm/utils/TableGen/CodeGenTarget.h
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h
@@ -173,7 +173,7 @@ public:
inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();}
inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); }
iterator_range<inst_iterator> instructions() const {
- return iterator_range<inst_iterator>(inst_begin(), inst_end());
+ return make_range(inst_begin(), inst_end());
}
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
index 4659dc157338..26f53dca6361 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/TableGen/Record.h"
@@ -36,6 +37,10 @@ class MatcherTableEmitter {
DenseMap<TreePattern *, unsigned> NodePredicateMap;
std::vector<TreePredicateFn> NodePredicates;
+
+ // We de-duplicate the predicates by code string, and use this map to track
+ // all the patterns with "identical" predicates.
+ StringMap<TinyPtrVector<TreePattern *>> NodePredicatesByCodeToRun;
StringMap<unsigned> PatternPredicateMap;
std::vector<std::string> PatternPredicates;
@@ -62,10 +67,23 @@ private:
formatted_raw_ostream &OS);
unsigned getNodePredicate(TreePredicateFn Pred) {
- unsigned &Entry = NodePredicateMap[Pred.getOrigPatFragRecord()];
+ TreePattern *TP = Pred.getOrigPatFragRecord();
+ unsigned &Entry = NodePredicateMap[TP];
if (Entry == 0) {
- NodePredicates.push_back(Pred);
- Entry = NodePredicates.size();
+ TinyPtrVector<TreePattern *> &SameCodePreds =
+ NodePredicatesByCodeToRun[Pred.getCodeToRunOnSDNode()];
+ if (SameCodePreds.empty()) {
+ // We've never seen a predicate with the same code: allocate an entry.
+ NodePredicates.push_back(Pred);
+ Entry = NodePredicates.size();
+ } else {
+ // We did see an identical predicate: re-use it.
+ Entry = NodePredicateMap[SameCodePreds.front()];
+ assert(Entry != 0);
+ }
+ // In both cases, we've never seen this particular predicate before, so
+ // mark it in the list of predicates sharing the same code.
+ SameCodePreds.push_back(TP);
}
return Entry-1;
}
@@ -625,13 +643,6 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
}
// Emit Node predicates.
- // FIXME: Annoyingly, these are stored by name, which we never even emit. Yay?
- StringMap<TreePattern*> PFsByName;
-
- for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end();
- I != E; ++I)
- PFsByName[I->first->getName()] = I->second.get();
-
if (!NodePredicates.empty()) {
OS << "bool CheckNodePredicate(SDNode *Node,\n";
OS << " unsigned PredNo) const override {\n";
@@ -642,7 +653,10 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
TreePredicateFn PredFn = NodePredicates[i];
assert(!PredFn.isAlwaysTrue() && "No code in this predicate");
- OS << " case " << i << ": { // " << NodePredicates[i].getFnName() <<'\n';
+ OS << " case " << i << ": { \n";
+ for (auto *SimilarPred :
+ NodePredicatesByCodeToRun[PredFn.getCodeToRunOnSDNode()])
+ OS << " // " << TreePredicateFn(SimilarPred).getFnName() <<'\n';
OS << PredFn.getCodeToRunOnSDNode() << "\n }\n";
}
diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
index 5060b6e9ce7c..77afff7ab5c2 100644
--- a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -15,16 +15,83 @@
//
//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "dfa-emitter"
+
#include "CodeGenTarget.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/Support/Debug.h"
#include <list>
#include <map>
#include <string>
+#include <queue>
using namespace llvm;
+// --------------------------------------------------------------------
+// Definitions shared between DFAPacketizer.cpp and DFAPacketizerEmitter.cpp
+
+// DFA_MAX_RESTERMS * DFA_MAX_RESOURCES must fit within sizeof DFAInput.
+// This is verified in DFAPacketizer.cpp:DFAPacketizer::DFAPacketizer.
+//
+// e.g. terms x resource bit combinations that fit in uint32_t:
+// 4 terms x 8 bits = 32 bits
+// 3 terms x 10 bits = 30 bits
+// 2 terms x 16 bits = 32 bits
+//
+// e.g. terms x resource bit combinations that fit in uint64_t:
+// 8 terms x 8 bits = 64 bits
+// 7 terms x 9 bits = 63 bits
+// 6 terms x 10 bits = 60 bits
+// 5 terms x 12 bits = 60 bits
+// 4 terms x 16 bits = 64 bits <--- current
+// 3 terms x 21 bits = 63 bits
+// 2 terms x 32 bits = 64 bits
+//
+#define DFA_MAX_RESTERMS 4 // The max # of AND'ed resource terms.
+#define DFA_MAX_RESOURCES 16 // The max # of resource bits in one term.
+
+typedef uint64_t DFAInput;
+typedef int64_t DFAStateInput;
+#define DFA_TBLTYPE "int64_t" // For generating DFAStateInputTable.
+
+namespace {
+ DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) {
+ return (Inp << DFA_MAX_RESOURCES) | FuncUnits;
+ }
+
+ /// Return the DFAInput for an instruction class input vector.
+ /// This function is used in both DFAPacketizer.cpp and in
+ /// DFAPacketizerEmitter.cpp.
+ DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) {
+ DFAInput InsnInput = 0;
+ assert ((InsnClass.size() <= DFA_MAX_RESTERMS) &&
+ "Exceeded maximum number of DFA terms");
+ for (auto U : InsnClass)
+ InsnInput = addDFAFuncUnits(InsnInput, U);
+ return InsnInput;
+ }
+}
+// --------------------------------------------------------------------
+
+#ifndef NDEBUG
+// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
+//
+// dbgsInsnClass - When debugging, print instruction class stages.
+//
+void dbgsInsnClass(const std::vector<unsigned> &InsnClass);
+//
+// dbgsStateInfo - When debugging, print the set of state info.
+//
+void dbgsStateInfo(const std::set<unsigned> &stateInfo);
+//
+// dbgsIndent - When debugging, indent by the specified amount.
+//
+void dbgsIndent(unsigned indent);
+#endif
+
//
// class DFAPacketizerEmitter: class that generates and prints out the DFA
// for resource tracking.
@@ -37,20 +104,48 @@ private:
// allInsnClasses is the set of all possible resources consumed by an
// InstrStage.
//
- DenseSet<unsigned> allInsnClasses;
+ std::vector<std::vector<unsigned>> allInsnClasses;
RecordKeeper &Records;
public:
DFAPacketizerEmitter(RecordKeeper &R);
//
- // collectAllInsnClasses: Populate allInsnClasses which is a set of units
+ // collectAllFuncUnits - Construct a map of function unit names to bits.
+ //
+ int collectAllFuncUnits(std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ int &maxResources,
+ raw_ostream &OS);
+
+ //
+ // collectAllComboFuncs - Construct a map from a combo function unit bit to
+ // the bits of all included functional units.
+ //
+ int collectAllComboFuncs(std::vector<Record*> &ComboFuncList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ raw_ostream &OS);
+
+ //
+ // collectOneInsnClass - Populate allInsnClasses with one instruction class.
+ //
+ int collectOneInsnClass(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ Record *ItinData,
+ raw_ostream &OS);
+
+ //
+ // collectAllInsnClasses - Populate allInsnClasses which is a set of units
// used in each stage.
//
- void collectAllInsnClasses(const std::string &Name,
- Record *ItinData,
- unsigned &NStages,
- raw_ostream &OS);
+ int collectAllInsnClasses(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::vector<Record*> &ItinDataList,
+ int &maxStages,
+ raw_ostream &OS);
void run(raw_ostream &OS);
};
@@ -87,7 +182,7 @@ class State {
const int stateNum;
mutable bool isInitial;
mutable std::set<unsigned> stateInfo;
- typedef std::map<unsigned, const State *> TransitionMap;
+ typedef std::map<std::vector<unsigned>, const State *> TransitionMap;
mutable TransitionMap Transitions;
State();
@@ -97,28 +192,47 @@ class State {
}
//
- // canAddInsnClass - Returns true if an instruction of type InsnClass is a
- // valid transition from this state, i.e., can an instruction of type InsnClass
- // be added to the packet represented by this state.
+ // canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
+ // may be a valid transition from this state i.e., can an instruction of type
+ // InsnClass be added to the packet represented by this state.
+ //
+ // Note that for multiple stages, this quick check does not take into account
+ // any possible resource competition between the stages themselves. That is
+ // enforced in AddInsnClassStages which checks the cross product of all
+ // stages for resource availability (which is a more involved check).
+ //
+ bool canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap) const;
+ //
+ // AddInsnClass - Return all combinations of resource reservation
+ // which are possible from this state (PossibleStates).
//
// PossibleStates is the set of valid resource states that ensue from valid
// transitions.
//
- bool canAddInsnClass(unsigned InsnClass) const;
+ void AddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ std::set<unsigned> &PossibleStates) const;
//
- // AddInsnClass - Return all combinations of resource reservation
+ // AddInsnClassStages - Return all combinations of resource reservation
+ // resulting from the cross product of all stages for this InsnClass
// which are possible from this state (PossibleStates).
//
- void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates) const;
- //
+ void AddInsnClassStages(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ unsigned chkstage, unsigned numstages,
+ unsigned prevState, unsigned origState,
+ DenseSet<unsigned> &VisitedResourceStates,
+ std::set<unsigned> &PossibleStates) const;
+ //
// addTransition - Add a transition from this state given the input InsnClass
//
- void addTransition(unsigned InsnClass, const State *To) const;
+ void addTransition(std::vector<unsigned> InsnClass, const State *To) const;
//
// hasTransition - Returns true if there is a transition from this state
// given the input InsnClass
//
- bool hasTransition(unsigned InsnClass) const;
+ bool hasTransition(std::vector<unsigned> InsnClass) const;
};
} // End anonymous namespace.
@@ -144,10 +258,54 @@ public:
//
// writeTable: Print out a table representing the DFA.
//
- void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName);
+ void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName,
+ int numInsnClasses = 0,
+ int maxResources = 0, int numCombos = 0, int maxStages = 0);
};
} // End anonymous namespace.
+#ifndef NDEBUG
+// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
+//
+// dbgsInsnClass - When debugging, print instruction class stages.
+//
+void dbgsInsnClass(const std::vector<unsigned> &InsnClass) {
+ DEBUG(dbgs() << "InsnClass: ");
+ for (unsigned i = 0; i < InsnClass.size(); ++i) {
+ if (i > 0) {
+ DEBUG(dbgs() << ", ");
+ }
+ DEBUG(dbgs() << "0x" << utohexstr(InsnClass[i]));
+ }
+ DFAInput InsnInput = getDFAInsnInput(InsnClass);
+ DEBUG(dbgs() << " (input: 0x" << utohexstr(InsnInput) << ")");
+}
+
+//
+// dbgsStateInfo - When debugging, print the set of state info.
+//
+void dbgsStateInfo(const std::set<unsigned> &stateInfo) {
+ DEBUG(dbgs() << "StateInfo: ");
+ unsigned i = 0;
+ for (std::set<unsigned>::iterator SI = stateInfo.begin();
+ SI != stateInfo.end(); ++SI, ++i) {
+ unsigned thisState = *SI;
+ if (i > 0) {
+ DEBUG(dbgs() << ", ");
+ }
+ DEBUG(dbgs() << "0x" << utohexstr(thisState));
+ }
+}
+
+//
+// dbgsIndent - When debugging, indent by the specified amount.
+//
+void dbgsIndent(unsigned indent) {
+ for (unsigned i = 0; i < indent; ++i) {
+ DEBUG(dbgs() << " ");
+ }
+}
+#endif
//
// Constructors and destructors for State and DFA
@@ -157,10 +315,11 @@ State::State() :
DFA::DFA(): currentState(nullptr) {}
-//
+//
// addTransition - Add a transition from this state given the input InsnClass
//
-void State::addTransition(unsigned InsnClass, const State *To) const {
+void State::addTransition(std::vector<unsigned> InsnClass, const State *To)
+ const {
assert(!Transitions.count(InsnClass) &&
"Cannot have multiple transitions for the same input");
Transitions[InsnClass] = To;
@@ -170,7 +329,7 @@ void State::addTransition(unsigned InsnClass, const State *To) const {
// hasTransition - Returns true if there is a transition from this state
// given the input InsnClass
//
-bool State::hasTransition(unsigned InsnClass) const {
+bool State::hasTransition(std::vector<unsigned> InsnClass) const {
return Transitions.count(InsnClass) > 0;
}
@@ -178,61 +337,170 @@ bool State::hasTransition(unsigned InsnClass) const {
// AddInsnClass - Return all combinations of resource reservation
// which are possible from this state (PossibleStates).
//
-void State::AddInsnClass(unsigned InsnClass,
- std::set<unsigned> &PossibleStates) const {
+// PossibleStates is the set of valid resource states that ensue from valid
+// transitions.
+//
+void State::AddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ std::set<unsigned> &PossibleStates) const {
//
// Iterate over all resource states in currentState.
//
+ unsigned numstages = InsnClass.size();
+ assert((numstages > 0) && "InsnClass has no stages");
for (std::set<unsigned>::iterator SI = stateInfo.begin();
SI != stateInfo.end(); ++SI) {
unsigned thisState = *SI;
- //
- // Iterate over all possible resources used in InsnClass.
- // For ex: for InsnClass = 0x11, all resources = {0x01, 0x10}.
- //
-
DenseSet<unsigned> VisitedResourceStates;
- for (unsigned int j = 0; j < sizeof(InsnClass) * 8; ++j) {
- if ((0x1 << j) & InsnClass) {
- //
- // For each possible resource used in InsnClass, generate the
- // resource state if that resource was used.
- //
- unsigned ResultingResourceState = thisState | (0x1 << j);
+
+ DEBUG(dbgs() << " thisState: 0x" << utohexstr(thisState) << "\n");
+ AddInsnClassStages(InsnClass, ComboBitToBitsMap,
+ numstages - 1, numstages,
+ thisState, thisState,
+ VisitedResourceStates, PossibleStates);
+ }
+}
+
+void State::AddInsnClassStages(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ unsigned chkstage, unsigned numstages,
+ unsigned prevState, unsigned origState,
+ DenseSet<unsigned> &VisitedResourceStates,
+ std::set<unsigned> &PossibleStates) const {
+
+ assert((chkstage < numstages) && "AddInsnClassStages: stage out of range");
+ unsigned thisStage = InsnClass[chkstage];
+
+ DEBUG({
+ dbgsIndent((1 + numstages - chkstage) << 1);
+ dbgs() << "AddInsnClassStages " << chkstage << " (0x"
+ << utohexstr(thisStage) << ") from ";
+ dbgsInsnClass(InsnClass);
+ dbgs() << "\n";
+ });
+
+ //
+ // Iterate over all possible resources used in thisStage.
+ // For ex: for thisStage = 0x11, all resources = {0x01, 0x10}.
+ //
+ for (unsigned int j = 0; j < DFA_MAX_RESOURCES; ++j) {
+ unsigned resourceMask = (0x1 << j);
+ if (resourceMask & thisStage) {
+ unsigned combo = ComboBitToBitsMap[resourceMask];
+ if (combo && ((~prevState & combo) != combo)) {
+ DEBUG(dbgs() << "\tSkipped Add 0x" << utohexstr(prevState)
+ << " - combo op 0x" << utohexstr(resourceMask)
+ << " (0x" << utohexstr(combo) <<") cannot be scheduled\n");
+ continue;
+ }
+ //
+ // For each possible resource used in thisStage, generate the
+ // resource state if that resource was used.
+ //
+ unsigned ResultingResourceState = prevState | resourceMask | combo;
+ DEBUG({
+ dbgsIndent((2 + numstages - chkstage) << 1);
+ dbgs() << "0x" << utohexstr(prevState)
+ << " | 0x" << utohexstr(resourceMask);
+ if (combo)
+ dbgs() << " | 0x" << utohexstr(combo);
+ dbgs() << " = 0x" << utohexstr(ResultingResourceState) << " ";
+ });
+
+ //
+ // If this is the final stage for this class
+ //
+ if (chkstage == 0) {
//
// Check if the resulting resource state can be accommodated in this
// packet.
- // We compute ResultingResourceState OR thisState.
- // If the result of the OR is different than thisState, it implies
+ // We compute resource OR prevState (originally started as origState).
+ // If the result of the OR is different than origState, it implies
// that there is at least one resource that can be used to schedule
- // InsnClass in the current packet.
+ // thisStage in the current packet.
// Insert ResultingResourceState into PossibleStates only if we haven't
// processed ResultingResourceState before.
//
- if ((ResultingResourceState != thisState) &&
- (VisitedResourceStates.count(ResultingResourceState) == 0)) {
- VisitedResourceStates.insert(ResultingResourceState);
- PossibleStates.insert(ResultingResourceState);
+ if (ResultingResourceState != prevState) {
+ if (VisitedResourceStates.count(ResultingResourceState) == 0) {
+ VisitedResourceStates.insert(ResultingResourceState);
+ PossibleStates.insert(ResultingResourceState);
+ DEBUG(dbgs() << "\tResultingResourceState: 0x"
+ << utohexstr(ResultingResourceState) << "\n");
+ } else {
+ DEBUG(dbgs() << "\tSkipped Add - state already seen\n");
+ }
+ } else {
+ DEBUG(dbgs() << "\tSkipped Add - no final resources available\n");
+ }
+ } else {
+ //
+ // If the current resource can be accommodated, check the next
+ // stage in InsnClass for available resources.
+ //
+ if (ResultingResourceState != prevState) {
+ DEBUG(dbgs() << "\n");
+ AddInsnClassStages(InsnClass, ComboBitToBitsMap,
+ chkstage - 1, numstages,
+ ResultingResourceState, origState,
+ VisitedResourceStates, PossibleStates);
+ } else {
+ DEBUG(dbgs() << "\tSkipped Add - no resources available\n");
}
}
}
}
-
}
//
-// canAddInsnClass - Quickly verifies if an instruction of type InsnClass is a
-// valid transition from this state i.e., can an instruction of type InsnClass
-// be added to the packet represented by this state.
+// canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
+// may be a valid transition from this state i.e., can an instruction of type
+// InsnClass be added to the packet represented by this state.
+//
+// Note that this routine is performing conservative checks that can be
+// quickly executed acting as a filter before calling AddInsnClassStages.
+// Any cases allowed through here will be caught later in AddInsnClassStages
+// which performs the more expensive exact check.
//
-bool State::canAddInsnClass(unsigned InsnClass) const {
+bool State::canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap) const {
for (std::set<unsigned>::const_iterator SI = stateInfo.begin();
SI != stateInfo.end(); ++SI) {
- if (~*SI & InsnClass)
+
+ // Check to see if all required resources are available.
+ bool available = true;
+
+ // Inspect each stage independently.
+ // note: This is a conservative check as we aren't checking for
+ // possible resource competition between the stages themselves
+ // The full cross product is examined later in AddInsnClass.
+ for (unsigned i = 0; i < InsnClass.size(); ++i) {
+ unsigned resources = *SI;
+ if ((~resources & InsnClass[i]) == 0) {
+ available = false;
+ break;
+ }
+ // Make sure _all_ resources for a combo function are available.
+ // note: This is a quick conservative check as it won't catch an
+ // unscheduleable combo if this stage is an OR expression
+ // containing a combo.
+ // These cases are caught later in AddInsnClass.
+ unsigned combo = ComboBitToBitsMap[InsnClass[i]];
+ if (combo && ((~resources & combo) != combo)) {
+ DEBUG(dbgs() << "\tSkipped canMaybeAdd 0x" << utohexstr(resources)
+ << " - combo op 0x" << utohexstr(InsnClass[i])
+ << " (0x" << utohexstr(combo) <<") cannot be scheduled\n");
+ available = false;
+ break;
+ }
+ }
+
+ if (available) {
return true;
+ }
}
return false;
}
@@ -244,7 +512,6 @@ const State &DFA::newState() {
return *IterPair.first;
}
-
int State::currentStateNum = 0;
DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):
@@ -263,57 +530,100 @@ DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):
// the ith state.
//
//
-void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) {
- static const std::string SentinelEntry = "{-1, -1}";
- DFA::StateSet::iterator SI = states.begin();
+void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,
+ int numInsnClasses,
+ int maxResources, int numCombos, int maxStages) {
+
+ unsigned numStates = states.size();
+
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");
+ DEBUG(dbgs() << "writeTableAndAPI\n");
+ DEBUG(dbgs() << "Total states: " << numStates << "\n");
+
+ OS << "namespace llvm {\n";
+
+ OS << "\n// Input format:\n";
+ OS << "#define DFA_MAX_RESTERMS " << DFA_MAX_RESTERMS
+ << "\t// maximum AND'ed resource terms\n";
+ OS << "#define DFA_MAX_RESOURCES " << DFA_MAX_RESOURCES
+ << "\t// maximum resource bits in one term\n";
+
+ OS << "\n// " << TargetName << "DFAStateInputTable[][2] = "
+ << "pairs of <Input, NextState> for all valid\n";
+ OS << "// transitions.\n";
+ OS << "// " << numStates << "\tstates\n";
+ OS << "// " << numInsnClasses << "\tinstruction classes\n";
+ OS << "// " << maxResources << "\tresources max\n";
+ OS << "// " << numCombos << "\tcombo resources\n";
+ OS << "// " << maxStages << "\tstages max\n";
+ OS << "const " << DFA_TBLTYPE << " "
+ << TargetName << "DFAStateInputTable[][2] = {\n";
+
// This table provides a map to the beginning of the transitions for State s
// in DFAStateInputTable.
- std::vector<int> StateEntry(states.size());
-
- OS << "namespace llvm {\n\n";
- OS << "const int " << TargetName << "DFAStateInputTable[][2] = {\n";
+ std::vector<int> StateEntry(numStates+1);
+ static const std::string SentinelEntry = "{-1, -1}";
// Tracks the total valid transitions encountered so far. It is used
// to construct the StateEntry table.
int ValidTransitions = 0;
- for (unsigned i = 0; i < states.size(); ++i, ++SI) {
+ DFA::StateSet::iterator SI = states.begin();
+ for (unsigned i = 0; i < numStates; ++i, ++SI) {
assert ((SI->stateNum == (int) i) && "Mismatch in state numbers");
StateEntry[i] = ValidTransitions;
for (State::TransitionMap::iterator
II = SI->Transitions.begin(), IE = SI->Transitions.end();
II != IE; ++II) {
- OS << "{" << II->first << ", "
+ OS << "{0x" << utohexstr(getDFAInsnInput(II->first)) << ", "
<< II->second->stateNum
- << "}, ";
+ << "},\t";
}
ValidTransitions += SI->Transitions.size();
// If there are no valid transitions from this stage, we need a sentinel
// transition.
if (ValidTransitions == StateEntry[i]) {
- OS << SentinelEntry << ",";
+ OS << SentinelEntry << ",\t";
++ValidTransitions;
}
+ OS << " // state " << i << ": " << StateEntry[i];
+ if (StateEntry[i] != (ValidTransitions-1)) { // More than one transition.
+ OS << "-" << (ValidTransitions-1);
+ }
OS << "\n";
}
// Print out a sentinel entry at the end of the StateInputTable. This is
// needed to iterate over StateInputTable in DFAPacketizer::ReadTable()
- OS << SentinelEntry << "\n";
-
+ OS << SentinelEntry << "\t";
+ OS << " // state " << numStates << ": " << ValidTransitions;
+ OS << "\n";
+
OS << "};\n\n";
+ OS << "// " << TargetName << "DFAStateEntryTable[i] = "
+ << "Index of the first entry in DFAStateInputTable for\n";
+ OS << "// "
+ << "the ith state.\n";
+ OS << "// " << numStates << " states\n";
OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n";
// Multiply i by 2 since each entry in DFAStateInputTable is a set of
// two numbers.
- for (unsigned i = 0; i < states.size(); ++i)
+ unsigned lastState = 0;
+ for (unsigned i = 0; i < numStates; ++i) {
+ if (i && ((i % 10) == 0)) {
+ lastState = i-1;
+ OS << " // states " << (i-10) << ":" << lastState << "\n";
+ }
OS << StateEntry[i] << ", ";
+ }
// Print out the index to the sentinel entry in StateInputTable
OS << ValidTransitions << ", ";
+ OS << " // states " << (lastState+1) << ":" << numStates << "\n";
- OS << "\n};\n";
+ OS << "};\n";
OS << "} // namespace\n";
@@ -332,40 +642,118 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) {
//
-// collectAllInsnClasses - Populate allInsnClasses which is a set of units
-// used in each stage.
+// collectAllFuncUnits - Construct a map of function unit names to bits.
//
-void DFAPacketizerEmitter::collectAllInsnClasses(const std::string &Name,
- Record *ItinData,
- unsigned &NStages,
- raw_ostream &OS) {
- // Collect processor itineraries.
- std::vector<Record*> ProcItinList =
- Records.getAllDerivedDefinitions("ProcessorItineraries");
-
- // If just no itinerary then don't bother.
- if (ProcItinList.size() < 2)
- return;
- std::map<std::string, unsigned> NameToBitsMap;
+int DFAPacketizerEmitter::collectAllFuncUnits(
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ int &maxFUs,
+ raw_ostream &OS) {
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");
+ DEBUG(dbgs() << "collectAllFuncUnits");
+ DEBUG(dbgs() << " (" << ProcItinList.size() << " itineraries)\n");
+ int totalFUs = 0;
// Parse functional units for all the itineraries.
for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) {
Record *Proc = ProcItinList[i];
std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU");
+ DEBUG(dbgs() << " FU:" << i
+ << " (" << FUs.size() << " FUs) "
+ << Proc->getName());
+
+
// Convert macros to bits for each stage.
- for (unsigned i = 0, N = FUs.size(); i < N; ++i)
- NameToBitsMap[FUs[i]->getName()] = (unsigned) (1U << i);
+ unsigned numFUs = FUs.size();
+ for (unsigned j = 0; j < numFUs; ++j) {
+ assert ((j < DFA_MAX_RESOURCES) &&
+ "Exceeded maximum number of representable resources");
+ unsigned FuncResources = (unsigned) (1U << j);
+ FUNameToBitsMap[FUs[j]->getName()] = FuncResources;
+ DEBUG(dbgs() << " " << FUs[j]->getName()
+ << ":0x" << utohexstr(FuncResources));
+ }
+ if (((int) numFUs) > maxFUs) {
+ maxFUs = numFUs;
+ }
+ totalFUs += numFUs;
+ DEBUG(dbgs() << "\n");
}
+ return totalFUs;
+}
+
+//
+// collectAllComboFuncs - Construct a map from a combo function unit bit to
+// the bits of all included functional units.
+//
+int DFAPacketizerEmitter::collectAllComboFuncs(
+ std::vector<Record*> &ComboFuncList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ raw_ostream &OS) {
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");
+ DEBUG(dbgs() << "collectAllComboFuncs");
+ DEBUG(dbgs() << " (" << ComboFuncList.size() << " sets)\n");
+ int numCombos = 0;
+ for (unsigned i = 0, N = ComboFuncList.size(); i < N; ++i) {
+ Record *Func = ComboFuncList[i];
+ std::vector<Record*> FUs = Func->getValueAsListOfDefs("CFD");
+
+ DEBUG(dbgs() << " CFD:" << i
+ << " (" << FUs.size() << " combo FUs) "
+ << Func->getName() << "\n");
+
+ // Convert macros to bits for each stage.
+ for (unsigned j = 0, N = FUs.size(); j < N; ++j) {
+ assert ((j < DFA_MAX_RESOURCES) &&
+ "Exceeded maximum number of DFA resources");
+ Record *FuncData = FUs[j];
+ Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc");
+ const std::vector<Record*> &FuncList =
+ FuncData->getValueAsListOfDefs("FuncList");
+ std::string ComboFuncName = ComboFunc->getName();
+ unsigned ComboBit = FUNameToBitsMap[ComboFuncName];
+ unsigned ComboResources = ComboBit;
+ DEBUG(dbgs() << " combo: " << ComboFuncName
+ << ":0x" << utohexstr(ComboResources) << "\n");
+ for (unsigned k = 0, M = FuncList.size(); k < M; ++k) {
+ std::string FuncName = FuncList[k]->getName();
+ unsigned FuncResources = FUNameToBitsMap[FuncName];
+ DEBUG(dbgs() << " " << FuncName
+ << ":0x" << utohexstr(FuncResources) << "\n");
+ ComboResources |= FuncResources;
+ }
+ ComboBitToBitsMap[ComboBit] = ComboResources;
+ numCombos++;
+ DEBUG(dbgs() << " => combo bits: " << ComboFuncName << ":0x"
+ << utohexstr(ComboBit) << " = 0x"
+ << utohexstr(ComboResources) << "\n");
+ }
+ }
+ return numCombos;
+}
+
+
+//
+// collectOneInsnClass - Populate allInsnClasses with one instruction class
+//
+int DFAPacketizerEmitter::collectOneInsnClass(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ Record *ItinData,
+ raw_ostream &OS) {
const std::vector<Record*> &StageList =
ItinData->getValueAsListOfDefs("Stages");
// The number of stages.
- NStages = StageList.size();
+ unsigned NStages = StageList.size();
+
+ DEBUG(dbgs() << " " << ItinData->getValueAsDef("TheClass")->getName()
+ << "\n");
- // For each unit.
- unsigned UnitBitValue = 0;
+ std::vector<unsigned> UnitBits;
// Compute the bitwise or of each unit used in this stage.
for (unsigned i = 0; i < NStages; ++i) {
@@ -375,18 +763,74 @@ void DFAPacketizerEmitter::collectAllInsnClasses(const std::string &Name,
const std::vector<Record*> &UnitList =
Stage->getValueAsListOfDefs("Units");
+ DEBUG(dbgs() << " stage:" << i
+ << " [" << UnitList.size() << " units]:");
+ unsigned dbglen = 26; // cursor after stage dbgs
+
+ // Compute the bitwise or of each unit used in this stage.
+ unsigned UnitBitValue = 0;
for (unsigned j = 0, M = UnitList.size(); j < M; ++j) {
// Conduct bitwise or.
std::string UnitName = UnitList[j]->getName();
- assert(NameToBitsMap.count(UnitName));
- UnitBitValue |= NameToBitsMap[UnitName];
+ DEBUG(dbgs() << " " << j << ":" << UnitName);
+ dbglen += 3 + UnitName.length();
+ assert(FUNameToBitsMap.count(UnitName));
+ UnitBitValue |= FUNameToBitsMap[UnitName];
}
if (UnitBitValue != 0)
- allInsnClasses.insert(UnitBitValue);
+ UnitBits.push_back(UnitBitValue);
+
+ while (dbglen <= 64) { // line up bits dbgs
+ dbglen += 8;
+ DEBUG(dbgs() << "\t");
+ }
+ DEBUG(dbgs() << " (bits: 0x" << utohexstr(UnitBitValue) << ")\n");
}
+
+ if (UnitBits.size() > 0)
+ allInsnClasses.push_back(UnitBits);
+
+ DEBUG({
+ dbgs() << " ";
+ dbgsInsnClass(UnitBits);
+ dbgs() << "\n";
+ });
+
+ return NStages;
}
+//
+// collectAllInsnClasses - Populate allInsnClasses which is a set of units
+// used in each stage.
+//
+int DFAPacketizerEmitter::collectAllInsnClasses(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::vector<Record*> &ItinDataList,
+ int &maxStages,
+ raw_ostream &OS) {
+ // Collect all instruction classes.
+ unsigned M = ItinDataList.size();
+
+ int numInsnClasses = 0;
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n"
+ << "collectAllInsnClasses "
+ << ProcName
+ << " (" << M << " classes)\n");
+
+ // Collect stages for each instruction class for all itinerary data
+ for (unsigned j = 0; j < M; j++) {
+ Record *ItinData = ItinDataList[j];
+ int NStages = collectOneInsnClass(ProcName, ProcItinList,
+ FUNameToBitsMap, ItinData, OS);
+ if (NStages > maxStages) {
+ maxStages = NStages;
+ }
+ numInsnClasses++;
+ }
+ return numInsnClasses;
+}
//
// Run the worklist algorithm to generate the DFA.
@@ -398,16 +842,35 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
Records.getAllDerivedDefinitions("ProcessorItineraries");
//
- // Collect the instruction classes.
+ // Collect the Functional units.
+ //
+ std::map<std::string, unsigned> FUNameToBitsMap;
+ int maxResources = 0;
+ collectAllFuncUnits(ProcItinList,
+ FUNameToBitsMap, maxResources, OS);
+
+ //
+ // Collect the Combo Functional units.
//
+ std::map<unsigned, unsigned> ComboBitToBitsMap;
+ std::vector<Record*> ComboFuncList =
+ Records.getAllDerivedDefinitions("ComboFuncUnits");
+ int numCombos = collectAllComboFuncs(ComboFuncList,
+ FUNameToBitsMap, ComboBitToBitsMap, OS);
+
+ //
+ // Collect the itineraries.
+ //
+ int maxStages = 0;
+ int numInsnClasses = 0;
for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
Record *Proc = ProcItinList[i];
// Get processor itinerary name.
- const std::string &Name = Proc->getName();
+ const std::string &ProcName = Proc->getName();
// Skip default.
- if (Name == "NoItineraries")
+ if (ProcName == "NoItineraries")
continue;
// Sanity check for at least one instruction itinerary class.
@@ -419,15 +882,11 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
// Get itinerary data list.
std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
- // Collect instruction classes for all itinerary data.
- for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) {
- Record *ItinData = ItinDataList[j];
- unsigned NStages;
- collectAllInsnClasses(Name, ItinData, NStages, OS);
- }
+ // Collect all instruction classes
+ numInsnClasses += collectAllInsnClasses(ProcName, ProcItinList,
+ FUNameToBitsMap, ItinDataList, maxStages, OS);
}
-
//
// Run a worklist algorithm to generate the DFA.
//
@@ -436,6 +895,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
Initial->isInitial = true;
Initial->stateInfo.insert(0x0);
SmallVector<const State*, 32> WorkList;
+// std::queue<State*> WorkList;
std::map<std::set<unsigned>, const State*> Visited;
WorkList.push_back(Initial);
@@ -459,9 +919,19 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
//
while (!WorkList.empty()) {
const State *current = WorkList.pop_back_val();
- for (DenseSet<unsigned>::iterator CI = allInsnClasses.begin(),
- CE = allInsnClasses.end(); CI != CE; ++CI) {
- unsigned InsnClass = *CI;
+ DEBUG({
+ dbgs() << "---------------------\n";
+ dbgs() << "Processing state: " << current->stateNum << " - ";
+ dbgsStateInfo(current->stateInfo);
+ dbgs() << "\n";
+ });
+ for (unsigned i = 0; i < allInsnClasses.size(); i++) {
+ std::vector<unsigned> InsnClass = allInsnClasses[i];
+ DEBUG({
+ dbgs() << i << " ";
+ dbgsInsnClass(InsnClass);
+ dbgs() << "\n";
+ });
std::set<unsigned> NewStateResources;
//
@@ -469,32 +939,52 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
// and the state can accommodate this InsnClass, create a transition.
//
if (!current->hasTransition(InsnClass) &&
- current->canAddInsnClass(InsnClass)) {
- const State *NewState;
- current->AddInsnClass(InsnClass, NewStateResources);
- assert(!NewStateResources.empty() && "New states must be generated");
+ current->canMaybeAddInsnClass(InsnClass, ComboBitToBitsMap)) {
+ const State *NewState = NULL;
+ current->AddInsnClass(InsnClass, ComboBitToBitsMap, NewStateResources);
+ if (NewStateResources.size() == 0) {
+ DEBUG(dbgs() << " Skipped - no new states generated\n");
+ continue;
+ }
+
+ DEBUG({
+ dbgs() << "\t";
+ dbgsStateInfo(NewStateResources);
+ dbgs() << "\n";
+ });
//
// If we have seen this state before, then do not create a new state.
//
- //
auto VI = Visited.find(NewStateResources);
- if (VI != Visited.end())
+ if (VI != Visited.end()) {
NewState = VI->second;
- else {
+ DEBUG({
+ dbgs() << "\tFound existing state: " << NewState->stateNum
+ << " - ";
+ dbgsStateInfo(NewState->stateInfo);
+ dbgs() << "\n";
+ });
+ } else {
NewState = &D.newState();
NewState->stateInfo = NewStateResources;
Visited[NewStateResources] = NewState;
WorkList.push_back(NewState);
+ DEBUG({
+ dbgs() << "\tAccepted new state: " << NewState->stateNum << " - ";
+ dbgsStateInfo(NewState->stateInfo);
+ dbgs() << "\n";
+ });
}
-
+
current->addTransition(InsnClass, NewState);
}
}
}
// Print out the table.
- D.writeTableAndAPI(OS, TargetName);
+ D.writeTableAndAPI(OS, TargetName,
+ numInsnClasses, maxResources, numCombos, maxStages);
}
namespace llvm {
diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
index f02051a2cd6c..e8595271bcce 100644
--- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
@@ -134,7 +134,7 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
PredicateNamespace = "ARM";
EmitFixedLenDecoder(Records, OS, PredicateNamespace,
- "if (!Check(S, ", ")) return MCDisassembler::Fail;",
+ "if (!Check(S, ", "))",
"S", "MCDisassembler::Fail",
" MCDisassembler::DecodeStatus S = "
"MCDisassembler::Success;\n(void)S;");
@@ -142,8 +142,7 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
}
EmitFixedLenDecoder(Records, OS, Target.getName(),
- "if (", " == MCDisassembler::Fail)"
- " return MCDisassembler::Fail;",
+ "if (", " == MCDisassembler::Fail)",
"MCDisassembler::Success", "MCDisassembler::Fail", "");
}
diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
index c4df2833885a..8ca4a1bf5404 100644
--- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -44,9 +44,10 @@ struct EncodingField {
struct OperandInfo {
std::vector<EncodingField> Fields;
std::string Decoder;
+ bool HasCompleteDecoder;
- OperandInfo(std::string D)
- : Decoder(D) { }
+ OperandInfo(std::string D, bool HCD)
+ : Decoder(D), HasCompleteDecoder(HCD) { }
void addField(unsigned Base, unsigned Width, unsigned Offset) {
Fields.push_back(EncodingField(Base, Width, Offset));
@@ -64,8 +65,8 @@ typedef std::vector<uint8_t> DecoderTable;
typedef uint32_t DecoderFixup;
typedef std::vector<DecoderFixup> FixupList;
typedef std::vector<FixupList> FixupScopeList;
-typedef SetVector<std::string> PredicateSet;
-typedef SetVector<std::string> DecoderSet;
+typedef SmallSetVector<std::string, 16> PredicateSet;
+typedef SmallSetVector<std::string, 16> DecoderSet;
struct DecoderTableInfo {
DecoderTable Table;
FixupScopeList FixupStack;
@@ -85,8 +86,7 @@ public:
FixedLenDecoderEmitter(RecordKeeper &R,
std::string PredicateNamespace,
std::string GPrefix = "if (",
- std::string GPostfix = " == MCDisassembler::Fail)"
- " return MCDisassembler::Fail;",
+ std::string GPostfix = " == MCDisassembler::Fail)",
std::string ROK = "MCDisassembler::Success",
std::string RFail = "MCDisassembler::Fail",
std::string L = "") :
@@ -448,10 +448,13 @@ protected:
const Filter &Best) const;
void emitBinaryParser(raw_ostream &o, unsigned &Indentation,
- const OperandInfo &OpInfo) const;
+ const OperandInfo &OpInfo,
+ bool &OpHasCompleteDecoder) const;
- void emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc) const;
- unsigned getDecoderIndex(DecoderSet &Decoders, unsigned Opc) const;
+ void emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc,
+ bool &HasCompleteDecoder) const;
+ unsigned getDecoderIndex(DecoderSet &Decoders, unsigned Opc,
+ bool &HasCompleteDecoder) const;
// Assign a single filter and run with it.
void runSingleFilter(unsigned startBit, unsigned numBit, bool mixed);
@@ -779,7 +782,9 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
}
- case MCD::OPC_Decode: {
+ case MCD::OPC_Decode:
+ case MCD::OPC_TryDecode: {
+ bool IsTry = *I == MCD::OPC_TryDecode;
++I;
// Extract the ULEB128 encoded Opcode to a buffer.
uint8_t Buffer[8], *p = Buffer;
@@ -788,7 +793,8 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
&& "ULEB128 value too large!");
// Decode the Opcode value.
unsigned Opc = decodeULEB128(Buffer);
- OS.indent(Indentation) << "MCD::OPC_Decode, ";
+ OS.indent(Indentation) << "MCD::OPC_" << (IsTry ? "Try" : "")
+ << "Decode, ";
for (p = Buffer; *p >= 128; ++p)
OS << utostr(*p) << ", ";
OS << utostr(*p) << ", ";
@@ -798,8 +804,25 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
OS << utostr(*I) << ", ";
OS << utostr(*I++) << ", ";
+ if (!IsTry) {
+ OS << "// Opcode: "
+ << NumberedInstructions->at(Opc)->TheDef->getName() << "\n";
+ break;
+ }
+
+ // Fallthrough for OPC_TryDecode.
+
+ // 16-bit numtoskip value.
+ uint8_t Byte = *I++;
+ uint32_t NumToSkip = Byte;
+ OS << utostr(Byte) << ", ";
+ Byte = *I++;
+ OS << utostr(Byte) << ", ";
+ NumToSkip |= Byte << 8;
+
OS << "// Opcode: "
- << NumberedInstructions->at(Opc)->TheDef->getName() << "\n";
+ << NumberedInstructions->at(Opc)->TheDef->getName()
+ << ", skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
}
case MCD::OPC_SoftFail: {
@@ -876,8 +899,9 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
OS.indent(Indentation) << "static DecodeStatus decodeToMCInst(DecodeStatus S,"
<< " unsigned Idx, InsnType insn, MCInst &MI,\n";
OS.indent(Indentation) << " uint64_t "
- << "Address, const void *Decoder) {\n";
+ << "Address, const void *Decoder, bool &DecodeComplete) {\n";
Indentation += 2;
+ OS.indent(Indentation) << "DecodeComplete = true;\n";
OS.indent(Indentation) << "InsnType tmp;\n";
OS.indent(Indentation) << "switch (Idx) {\n";
OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
@@ -1033,7 +1057,8 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
}
void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
- const OperandInfo &OpInfo) const {
+ const OperandInfo &OpInfo,
+ bool &OpHasCompleteDecoder) const {
const std::string &Decoder = OpInfo.Decoder;
if (OpInfo.numFields() != 1)
@@ -1049,45 +1074,57 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
o << ";\n";
}
- if (Decoder != "")
+ if (Decoder != "") {
+ OpHasCompleteDecoder = OpInfo.HasCompleteDecoder;
o.indent(Indentation) << Emitter->GuardPrefix << Decoder
- << "(MI, tmp, Address, Decoder)"
- << Emitter->GuardPostfix << "\n";
- else
+ << "(MI, tmp, Address, Decoder)"
+ << Emitter->GuardPostfix
+ << " { " << (OpHasCompleteDecoder ? "" : "DecodeComplete = false; ")
+ << "return MCDisassembler::Fail; }\n";
+ } else {
+ OpHasCompleteDecoder = true;
o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n";
-
+ }
}
void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation,
- unsigned Opc) const {
+ unsigned Opc, bool &HasCompleteDecoder) const {
+ HasCompleteDecoder = true;
+
for (const auto &Op : Operands.find(Opc)->second) {
// If a custom instruction decoder was specified, use that.
if (Op.numFields() == 0 && Op.Decoder.size()) {
+ HasCompleteDecoder = Op.HasCompleteDecoder;
OS.indent(Indentation) << Emitter->GuardPrefix << Op.Decoder
<< "(MI, insn, Address, Decoder)"
- << Emitter->GuardPostfix << "\n";
+ << Emitter->GuardPostfix
+ << " { " << (HasCompleteDecoder ? "" : "DecodeComplete = false; ")
+ << "return MCDisassembler::Fail; }\n";
break;
}
- emitBinaryParser(OS, Indentation, Op);
+ bool OpHasCompleteDecoder;
+ emitBinaryParser(OS, Indentation, Op, OpHasCompleteDecoder);
+ if (!OpHasCompleteDecoder)
+ HasCompleteDecoder = false;
}
}
unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
- unsigned Opc) const {
+ unsigned Opc,
+ bool &HasCompleteDecoder) const {
// Build up the predicate string.
SmallString<256> Decoder;
// FIXME: emitDecoder() function can take a buffer directly rather than
// a stream.
raw_svector_ostream S(Decoder);
unsigned I = 4;
- emitDecoder(S, I, Opc);
- S.flush();
+ emitDecoder(S, I, Opc, HasCompleteDecoder);
// Using the full decoder string as the key value here is a bit
// heavyweight, but is effective. If the string comparisons become a
// performance concern, we can implement a mangling of the predicate
- // data easilly enough with a map back to the actual string. That's
+ // data easily enough with a map back to the actual string. That's
// overkill for now, though.
// Make sure the predicate is in the table.
@@ -1162,7 +1199,7 @@ unsigned FilterChooser::getPredicateIndex(DecoderTableInfo &TableInfo,
// Using the full predicate string as the key value here is a bit
// heavyweight, but is effective. If the string comparisons become a
// performance concern, we can implement a mangling of the predicate
- // data easilly enough with a map back to the actual string. That's
+ // data easily enough with a map back to the actual string. That's
// overkill for now, though.
// Make sure the predicate is in the table.
@@ -1193,7 +1230,6 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo,
SmallString<16> PBytes;
raw_svector_ostream S(PBytes);
encodeULEB128(PIdx, S);
- S.flush();
TableInfo.Table.push_back(MCD::OPC_CheckPredicate);
// Predicate index
@@ -1252,16 +1288,13 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
raw_svector_ostream S(MaskBytes);
if (NeedPositiveMask) {
encodeULEB128(PositiveMask.getZExtValue(), S);
- S.flush();
for (unsigned i = 0, e = MaskBytes.size(); i != e; ++i)
TableInfo.Table.push_back(MaskBytes[i]);
} else
TableInfo.Table.push_back(0);
if (NeedNegativeMask) {
MaskBytes.clear();
- S.resync();
encodeULEB128(NegativeMask.getZExtValue(), S);
- S.flush();
for (unsigned i = 0, e = MaskBytes.size(); i != e; ++i)
TableInfo.Table.push_back(MaskBytes[i]);
} else
@@ -1308,22 +1341,41 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
// Check for soft failure of the match.
emitSoftFailTableEntry(TableInfo, Opc);
- TableInfo.Table.push_back(MCD::OPC_Decode);
+ bool HasCompleteDecoder;
+ unsigned DIdx = getDecoderIndex(TableInfo.Decoders, Opc, HasCompleteDecoder);
+
+ // Produce OPC_Decode or OPC_TryDecode opcode based on the information
+ // whether the instruction decoder is complete or not. If it is complete
+ // then it handles all possible values of remaining variable/unfiltered bits
+ // and for any value can determine if the bitpattern is a valid instruction
+ // or not. This means OPC_Decode will be the final step in the decoding
+ // process. If it is not complete, then the Fail return code from the
+ // decoder method indicates that additional processing should be done to see
+ // if there is any other instruction that also matches the bitpattern and
+ // can decode it.
+ TableInfo.Table.push_back(HasCompleteDecoder ? MCD::OPC_Decode :
+ MCD::OPC_TryDecode);
uint8_t Buffer[8], *p;
encodeULEB128(Opc, Buffer);
for (p = Buffer; *p >= 128 ; ++p)
TableInfo.Table.push_back(*p);
TableInfo.Table.push_back(*p);
- unsigned DIdx = getDecoderIndex(TableInfo.Decoders, Opc);
SmallString<16> Bytes;
raw_svector_ostream S(Bytes);
encodeULEB128(DIdx, S);
- S.flush();
// Decoder index
for (unsigned i = 0, e = Bytes.size(); i != e; ++i)
TableInfo.Table.push_back(Bytes[i]);
+
+ if (!HasCompleteDecoder) {
+ // Push location for NumToSkip backpatching.
+ TableInfo.FixupStack.back().push_back(TableInfo.Table.size());
+ // Allocate the space for the fixup.
+ TableInfo.Table.push_back(0);
+ TableInfo.Table.push_back(0);
+ }
}
// Emits table entries to decode the singleton, and then to decode the rest.
@@ -1679,7 +1731,8 @@ static bool populateInstruction(CodeGenTarget &Target,
// of trying to auto-generate the decoder.
std::string InstDecoder = Def.getValueAsString("DecoderMethod");
if (InstDecoder != "") {
- InsnOperands.push_back(OperandInfo(InstDecoder));
+ bool HasCompleteInstDecoder = Def.getValueAsBit("hasCompleteDecoder");
+ InsnOperands.push_back(OperandInfo(InstDecoder, HasCompleteInstDecoder));
Operands[Opc] = InsnOperands;
return true;
}
@@ -1835,7 +1888,14 @@ static bool populateInstruction(CodeGenTarget &Target,
if (!isReg && String && String->getValue() != "")
Decoder = String->getValue();
- OperandInfo OpInfo(Decoder);
+ RecordVal *HasCompleteDecoderVal =
+ TypeRecord->getValue("hasCompleteDecoder");
+ BitInit *HasCompleteDecoderBit = HasCompleteDecoderVal ?
+ dyn_cast<BitInit>(HasCompleteDecoderVal->getValue()) : nullptr;
+ bool HasCompleteDecoder = HasCompleteDecoderBit ?
+ HasCompleteDecoderBit->getValue() : true;
+
+ OperandInfo OpInfo(Decoder, HasCompleteDecoder);
OpInfo.addField(bitStart, bitWidth, 0);
NumberedInsnOperands[Name].push_back(OpInfo);
@@ -1907,7 +1967,14 @@ static bool populateInstruction(CodeGenTarget &Target,
if (!isReg && String && String->getValue() != "")
Decoder = String->getValue();
- OperandInfo OpInfo(Decoder);
+ RecordVal *HasCompleteDecoderVal =
+ TypeRecord->getValue("hasCompleteDecoder");
+ BitInit *HasCompleteDecoderBit = HasCompleteDecoderVal ?
+ dyn_cast<BitInit>(HasCompleteDecoderVal->getValue()) : nullptr;
+ bool HasCompleteDecoder = HasCompleteDecoderBit ?
+ HasCompleteDecoderBit->getValue() : true;
+
+ OperandInfo OpInfo(Decoder, HasCompleteDecoder);
unsigned Base = ~0U;
unsigned Width = 0;
unsigned Offset = 0;
@@ -2096,12 +2163,52 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
<< " Ptr += Len;\n"
<< " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n"
<< " Ptr += Len;\n"
- << " DEBUG(dbgs() << Loc << \": OPC_Decode: opcode \" << Opc\n"
- << " << \", using decoder \" << DecodeIdx << \"\\n\" );\n"
- << " DEBUG(dbgs() << \"----- DECODE SUCCESSFUL -----\\n\");\n"
<< "\n"
+ << " MI.clear();\n"
<< " MI.setOpcode(Opc);\n"
- << " return decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm);\n"
+ << " bool DecodeComplete;\n"
+ << " S = decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm, DecodeComplete);\n"
+ << " assert(DecodeComplete);\n"
+ << "\n"
+ << " DEBUG(dbgs() << Loc << \": OPC_Decode: opcode \" << Opc\n"
+ << " << \", using decoder \" << DecodeIdx << \": \"\n"
+ << " << (S != MCDisassembler::Fail ? \"PASS\" : \"FAIL\") << \"\\n\");\n"
+ << " return S;\n"
+ << " }\n"
+ << " case MCD::OPC_TryDecode: {\n"
+ << " unsigned Len;\n"
+ << " // Decode the Opcode value.\n"
+ << " unsigned Opc = decodeULEB128(++Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << " // NumToSkip is a plain 16-bit integer.\n"
+ << " unsigned NumToSkip = *Ptr++;\n"
+ << " NumToSkip |= (*Ptr++) << 8;\n"
+ << "\n"
+ << " // Perform the decode operation.\n"
+ << " MCInst TmpMI;\n"
+ << " TmpMI.setOpcode(Opc);\n"
+ << " bool DecodeComplete;\n"
+ << " S = decodeToMCInst(S, DecodeIdx, insn, TmpMI, Address, DisAsm, DecodeComplete);\n"
+ << " DEBUG(dbgs() << Loc << \": OPC_TryDecode: opcode \" << Opc\n"
+ << " << \", using decoder \" << DecodeIdx << \": \");\n"
+ << "\n"
+ << " if (DecodeComplete) {\n"
+ << " // Decoding complete.\n"
+ << " DEBUG(dbgs() << (S != MCDisassembler::Fail ? \"PASS\" : \"FAIL\") << \"\\n\");\n"
+ << " MI = TmpMI;\n"
+ << " return S;\n"
+ << " } else {\n"
+ << " assert(S == MCDisassembler::Fail);\n"
+ << " // If the decoding was incomplete, skip.\n"
+ << " Ptr += NumToSkip;\n"
+ << " DEBUG(dbgs() << \"FAIL: continuing at \" << (Ptr - DecodeTable) << \"\\n\");\n"
+ << " // Reset decode status. This also drops a SoftFail status that could be\n"
+ << " // set before the decode attempt.\n"
+ << " S = MCDisassembler::Success;\n"
+ << " }\n"
+ << " break;\n"
<< " }\n"
<< " case MCD::OPC_SoftFail: {\n"
<< " // Decode the mask values.\n"
diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
index e242a965ff93..a6583399fa20 100644
--- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -1,4 +1,4 @@
-//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
+//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,7 +12,6 @@
//
//===----------------------------------------------------------------------===//
-
#include "CodeGenDAGPatterns.h"
#include "CodeGenSchedule.h"
#include "CodeGenTarget.h"
@@ -26,6 +25,7 @@
#include <cstdio>
#include <map>
#include <vector>
+
using namespace llvm;
namespace {
@@ -70,11 +70,11 @@ private:
void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst);
};
-} // End anonymous namespace
+} // end anonymous namespace
static void PrintDefList(const std::vector<Record*> &Uses,
unsigned Num, raw_ostream &OS) {
- OS << "static const uint16_t ImplicitList" << Num << "[] = { ";
+ OS << "static const MCPhysReg ImplicitList" << Num << "[] = { ";
for (unsigned i = 0, e = Uses.size(); i != e; ++i)
OS << getQualifiedName(Uses[i]) << ", ";
OS << "0 };\n";
@@ -190,7 +190,6 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
}
}
-
/// Initialize data structures for generating operand name mappings.
///
/// \param Operands [out] A map used to generate the OpName enum with operand
@@ -257,9 +256,9 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
OS << "OPERAND_LAST";
OS << "\n};\n";
- OS << "} // End namespace OpName\n";
- OS << "} // End namespace " << Namespace << "\n";
- OS << "} // End namespace llvm\n";
+ OS << "} // end namespace OpName\n";
+ OS << "} // end namespace " << Namespace << "\n";
+ OS << "} // end namespace llvm\n";
OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n";
OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n";
@@ -298,8 +297,8 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
OS << " return -1;\n";
}
OS << "}\n";
- OS << "} // End namespace " << Namespace << "\n";
- OS << "} // End namespace llvm\n";
+ OS << "} // end namespace " << Namespace << "\n";
+ OS << "} // end namespace llvm\n";
OS << "#endif //GET_INSTRINFO_NAMED_OPS\n";
}
@@ -328,9 +327,9 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
}
OS << " OPERAND_TYPE_LIST_END" << "\n};\n";
- OS << "} // End namespace OpTypes\n";
- OS << "} // End namespace " << Namespace << "\n";
- OS << "} // End namespace llvm\n";
+ OS << "} // end namespace OpTypes\n";
+ OS << "} // end namespace " << Namespace << "\n";
+ OS << "} // end namespace llvm\n";
OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
}
@@ -419,7 +418,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
<< TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "
<< NumberedInstructions.size() << ");\n}\n\n";
- OS << "} // End llvm namespace \n";
+ OS << "} // end llvm namespace \n";
OS << "#endif // GET_INSTRINFO_MC_DESC\n\n";
@@ -431,10 +430,10 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
OS << "namespace llvm {\n";
OS << "struct " << ClassName << " : public TargetInstrInfo {\n"
<< " explicit " << ClassName
- << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1);\n"
- << " virtual ~" << ClassName << "();\n"
+ << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1);\n"
+ << " ~" << ClassName << "() override {}\n"
<< "};\n";
- OS << "} // End llvm namespace \n";
+ OS << "} // end llvm namespace \n";
OS << "#endif // GET_INSTRINFO_HEADER\n\n";
@@ -446,13 +445,12 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n";
OS << "extern const char " << TargetName << "InstrNameData[];\n";
OS << ClassName << "::" << ClassName
- << "(int CFSetupOpcode, int CFDestroyOpcode)\n"
- << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode) {\n"
+ << "(int CFSetupOpcode, int CFDestroyOpcode, int CatchRetOpcode)\n"
+ << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode) {\n"
<< " InitMCInstrInfo(" << TargetName << "Insts, " << TargetName
<< "InstrNameIndices, " << TargetName << "InstrNameData, "
- << NumberedInstructions.size() << ");\n}\n"
- << ClassName << "::~" << ClassName << "() {}\n";
- OS << "} // End llvm namespace \n";
+ << NumberedInstructions.size() << ");\n}\n";
+ OS << "} // end llvm namespace \n";
OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n";
@@ -596,9 +594,9 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
OS << " " << Class.Name << "\t= " << Num++ << ",\n";
OS << " SCHED_LIST_END = " << SchedModels.numInstrSchedClasses() << "\n";
OS << " };\n";
- OS << "} // End Sched namespace\n";
- OS << "} // End " << Namespace << " namespace\n";
- OS << "} // End llvm namespace \n";
+ OS << "} // end Sched namespace\n";
+ OS << "} // end " << Namespace << " namespace\n";
+ OS << "} // end llvm namespace \n";
OS << "#endif // GET_INSTRINFO_ENUM\n\n";
}
@@ -610,4 +608,4 @@ void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
EmitMapTable(RK, OS);
}
-} // End llvm namespace
+} // end llvm namespace
diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
index 2b59ee69d16a..42a6a152f55e 100644
--- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -50,8 +50,6 @@ public:
raw_ostream &OS);
void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS);
- void EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS);
void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS);
void EmitIntrinsicToMSBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
@@ -92,9 +90,6 @@ void IntrinsicEmitter::run(raw_ostream &OS) {
// Emit the intrinsic parameter attributes.
EmitAttributes(Ints, OS);
- // Emit intrinsic alias analysis mod/ref behavior.
- EmitModRefBehavior(Ints, OS);
-
// Emit code to translate GCC builtins into LLVM intrinsics.
EmitIntrinsicToGCCBuiltinMap(Ints, OS);
@@ -246,22 +241,25 @@ enum IIT_Info {
// Values from 16+ are only encodable with the inefficient encoding.
IIT_V64 = 16,
IIT_MMX = 17,
- IIT_METADATA = 18,
- IIT_EMPTYSTRUCT = 19,
- IIT_STRUCT2 = 20,
- IIT_STRUCT3 = 21,
- IIT_STRUCT4 = 22,
- IIT_STRUCT5 = 23,
- IIT_EXTEND_ARG = 24,
- IIT_TRUNC_ARG = 25,
- IIT_ANYPTR = 26,
- IIT_V1 = 27,
- IIT_VARARG = 28,
- IIT_HALF_VEC_ARG = 29,
- IIT_SAME_VEC_WIDTH_ARG = 30,
- IIT_PTR_TO_ARG = 31,
- IIT_VEC_OF_PTRS_TO_ELT = 32,
- IIT_I128 = 33
+ IIT_TOKEN = 18,
+ IIT_METADATA = 19,
+ IIT_EMPTYSTRUCT = 20,
+ IIT_STRUCT2 = 21,
+ IIT_STRUCT3 = 22,
+ IIT_STRUCT4 = 23,
+ IIT_STRUCT5 = 24,
+ IIT_EXTEND_ARG = 25,
+ IIT_TRUNC_ARG = 26,
+ IIT_ANYPTR = 27,
+ IIT_V1 = 28,
+ IIT_VARARG = 29,
+ IIT_HALF_VEC_ARG = 30,
+ IIT_SAME_VEC_WIDTH_ARG = 31,
+ IIT_PTR_TO_ARG = 32,
+ IIT_VEC_OF_PTRS_TO_ELT = 33,
+ IIT_I128 = 34,
+ IIT_V512 = 35,
+ IIT_V1024 = 36
};
@@ -285,6 +283,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
case MVT::f16: return Sig.push_back(IIT_F16);
case MVT::f32: return Sig.push_back(IIT_F32);
case MVT::f64: return Sig.push_back(IIT_F64);
+ case MVT::token: return Sig.push_back(IIT_TOKEN);
case MVT::Metadata: return Sig.push_back(IIT_METADATA);
case MVT::x86mmx: return Sig.push_back(IIT_MMX);
// MVT::OtherVT is used to mean the empty struct type here.
@@ -375,6 +374,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
case 16: Sig.push_back(IIT_V16); break;
case 32: Sig.push_back(IIT_V32); break;
case 64: Sig.push_back(IIT_V64); break;
+ case 512: Sig.push_back(IIT_V512); break;
+ case 1024: Sig.push_back(IIT_V1024); break;
}
return EncodeFixedValueType(VVT.getVectorElementType().SimpleTy, Sig);
@@ -503,28 +504,6 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
}
namespace {
-enum ModRefKind {
- MRK_none,
- MRK_readonly,
- MRK_readnone
-};
-}
-
-static ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) {
- switch (intrinsic.ModRef) {
- case CodeGenIntrinsic::NoMem:
- return MRK_readnone;
- case CodeGenIntrinsic::ReadArgMem:
- case CodeGenIntrinsic::ReadMem:
- return MRK_readonly;
- case CodeGenIntrinsic::ReadWriteArgMem:
- case CodeGenIntrinsic::ReadWriteMem:
- return MRK_none;
- }
- llvm_unreachable("bad mod-ref kind");
-}
-
-namespace {
struct AttributeComparator {
bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
// Sort throwing intrinsics after non-throwing intrinsics.
@@ -541,8 +520,8 @@ struct AttributeComparator {
return R->isConvergent;
// Try to order by readonly/readnone attribute.
- ModRefKind LK = getModRefKind(*L);
- ModRefKind RK = getModRefKind(*R);
+ CodeGenIntrinsic::ModRefKind LK = L->ModRef;
+ CodeGenIntrinsic::ModRefKind RK = R->ModRef;
if (LK != RK) return (LK > RK);
// Order by argument attributes.
@@ -636,7 +615,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
case CodeGenIntrinsic::ReadNone:
if (addComma)
OS << ",";
- OS << "Attributes::ReadNone";
+ OS << "Attribute::ReadNone";
addComma = true;
break;
}
@@ -649,10 +628,10 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
}
}
- ModRefKind modRef = getModRefKind(intrinsic);
-
- if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn ||
- intrinsic.isNoDuplicate || intrinsic.isConvergent) {
+ if (!intrinsic.canThrow ||
+ intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem ||
+ intrinsic.isNoReturn || intrinsic.isNoDuplicate ||
+ intrinsic.isConvergent) {
OS << " const Attribute::AttrKind Atts[] = {";
bool addComma = false;
if (!intrinsic.canThrow) {
@@ -678,17 +657,29 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
addComma = true;
}
- switch (modRef) {
- case MRK_none: break;
- case MRK_readonly:
+ switch (intrinsic.ModRef) {
+ case CodeGenIntrinsic::NoMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadNone";
+ break;
+ case CodeGenIntrinsic::ReadArgMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly,";
+ OS << "Attribute::ArgMemOnly";
+ break;
+ case CodeGenIntrinsic::ReadMem:
if (addComma)
OS << ",";
OS << "Attribute::ReadOnly";
break;
- case MRK_readnone:
+ case CodeGenIntrinsic::ReadWriteArgMem:
if (addComma)
OS << ",";
- OS << "Attribute::ReadNone";
+ OS << "Attribute::ArgMemOnly";
+ break;
+ case CodeGenIntrinsic::ReadWriteMem:
break;
}
OS << "};\n";
@@ -713,41 +704,6 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
}
-/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior.
-void IntrinsicEmitter::
-EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
- OS << "// Determine intrinsic alias analysis mod/ref behavior.\n"
- << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n"
- << "assert(iid <= Intrinsic::" << Ints.back().EnumName << " && "
- << "\"Unknown intrinsic.\");\n\n";
-
- OS << "static const uint8_t IntrinsicModRefBehavior[] = {\n"
- << " /* invalid */ UnknownModRefBehavior,\n";
- for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
- OS << " /* " << TargetPrefix << Ints[i].EnumName << " */ ";
- switch (Ints[i].ModRef) {
- case CodeGenIntrinsic::NoMem:
- OS << "DoesNotAccessMemory,\n";
- break;
- case CodeGenIntrinsic::ReadArgMem:
- OS << "OnlyReadsArgumentPointees,\n";
- break;
- case CodeGenIntrinsic::ReadMem:
- OS << "OnlyReadsMemory,\n";
- break;
- case CodeGenIntrinsic::ReadWriteArgMem:
- OS << "OnlyAccessesArgumentPointees,\n";
- break;
- case CodeGenIntrinsic::ReadWriteMem:
- OS << "UnknownModRefBehavior,\n";
- break;
- }
- }
- OS << "};\n\n"
- << "return static_cast<ModRefBehavior>(IntrinsicModRefBehavior[iid]);\n"
- << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n";
-}
-
/// EmitTargetBuiltins - All of the builtins in the specified map are for the
/// same target, and we already checked it.
static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
diff --git a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp
index 9262d7c8a02c..c1b5e6510325 100644
--- a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -149,10 +149,10 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
PE = I->first.end(); PI != PE; ++PI) {
OS << "\"" << *PI << "\" COMMA ";
}
- OS << "0})\n";
+ OS << "nullptr})\n";
}
OS << "#undef COMMA\n";
- OS << "#endif\n\n";
+ OS << "#endif // PREFIX\n\n";
OS << "/////////\n";
OS << "// Groups\n\n";
@@ -164,7 +164,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
OS << "OPTION(";
// The option prefix;
- OS << "0";
+ OS << "nullptr";
// The option string.
OS << ", \"" << R.getValueAsString("Name") << '"';
@@ -183,7 +183,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
OS << "INVALID";
// The other option arguments (unused for groups).
- OS << ", INVALID, 0, 0, 0";
+ OS << ", INVALID, nullptr, 0, 0";
// The option help text.
if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
@@ -191,10 +191,10 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
OS << " ";
write_cstring(OS, R.getValueAsString("HelpText"));
} else
- OS << ", 0";
+ OS << ", nullptr";
// The option meta-variable name (unused).
- OS << ", 0)\n";
+ OS << ", nullptr)\n";
}
OS << "\n";
@@ -242,7 +242,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
OS << ", ";
std::vector<std::string> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
if (AliasArgs.size() == 0) {
- OS << "0";
+ OS << "nullptr";
} else {
OS << "\"";
for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
@@ -274,17 +274,17 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
OS << " ";
write_cstring(OS, R.getValueAsString("HelpText"));
} else
- OS << ", 0";
+ OS << ", nullptr";
// The option meta-variable name.
OS << ", ";
if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
write_cstring(OS, R.getValueAsString("MetaVarName"));
else
- OS << "0";
+ OS << "nullptr";
OS << ")\n";
}
- OS << "#endif\n";
+ OS << "#endif // OPTION\n";
}
} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index 9619fb9e356e..b727df75626f 100644
--- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -240,7 +240,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight);
OS << " \"" << RegUnits.Name << "\",\n";
}
- OS << " nullptr };\n"
+ OS << " };\n"
<< " return PressureNameTable[Idx];\n"
<< "}\n\n";
@@ -1074,9 +1074,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
OS << "struct " << ClassName << " : public TargetRegisterInfo {\n"
<< " explicit " << ClassName
- << "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n"
- << " bool needsStackRealignment(const MachineFunction &) const override\n"
- << " { return false; }\n";
+ << "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n";
if (!RegBank.getSubRegIndices().empty()) {
OS << " unsigned composeSubRegIndicesImpl"
<< "(unsigned, unsigned) const override;\n"
@@ -1454,27 +1452,32 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "ArrayRef<const uint32_t *> " << ClassName
<< "::getRegMasks() const {\n";
- OS << " static const uint32_t *Masks[] = {\n";
- for (Record *CSRSet : CSRSets)
- OS << " " << CSRSet->getName() << "_RegMask, \n";
- OS << " nullptr\n };\n";
- OS << " return ArrayRef<const uint32_t *>(Masks, (size_t)" << CSRSets.size()
- << ");\n";
+ if (!CSRSets.empty()) {
+ OS << " static const uint32_t *const Masks[] = {\n";
+ for (Record *CSRSet : CSRSets)
+ OS << " " << CSRSet->getName() << "_RegMask,\n";
+ OS << " };\n";
+ OS << " return makeArrayRef(Masks);\n";
+ } else {
+ OS << " return None;\n";
+ }
OS << "}\n\n";
OS << "ArrayRef<const char *> " << ClassName
<< "::getRegMaskNames() const {\n";
- OS << " static const char *Names[] = {\n";
- for (Record *CSRSet : CSRSets)
- OS << " " << '"' << CSRSet->getName() << '"' << ",\n";
- OS << " nullptr\n };\n";
- OS << " return ArrayRef<const char *>(Names, (size_t)" << CSRSets.size()
- << ");\n";
+ if (!CSRSets.empty()) {
+ OS << " static const char *const Names[] = {\n";
+ for (Record *CSRSet : CSRSets)
+ OS << " " << '"' << CSRSet->getName() << '"' << ",\n";
+ OS << " };\n";
+ OS << " return makeArrayRef(Names);\n";
+ } else {
+ OS << " return None;\n";
+ }
OS << "}\n\n";
- OS << "const " << TargetName << "FrameLowering *"
- << TargetName << "GenRegisterInfo::\n"
- << " getFrameLowering(const MachineFunction &MF) {\n"
+ OS << "const " << TargetName << "FrameLowering *\n" << TargetName
+ << "GenRegisterInfo::getFrameLowering(const MachineFunction &MF) {\n"
<< " return static_cast<const " << TargetName << "FrameLowering *>(\n"
<< " MF.getSubtarget().getFrameLowering());\n"
<< "}\n\n";
diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
index 03d7f4e868e7..6246d811123d 100644
--- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -26,6 +26,7 @@
#include <map>
#include <string>
#include <vector>
+
using namespace llvm;
#define DEBUG_TYPE "subtarget-emitter"
@@ -105,9 +106,8 @@ public:
Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
void run(raw_ostream &o);
-
};
-} // End anonymous namespace
+} // end anonymous namespace
//
// Enumeration - Emit the specified class as an enumeration.
@@ -1199,7 +1199,8 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
<< " " << (SchedModels.schedClassEnd()
- SchedModels.schedClassBegin()) << ",\n";
else
- OS << " 0, 0, 0, 0, // No instruction-level machine model.\n";
+ OS << " nullptr, nullptr, 0, 0,"
+ << " // No instruction-level machine model.\n";
if (PI->hasItineraries())
OS << " " << PI->ItinsDef->getName() << "};\n";
else
@@ -1414,7 +1415,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "namespace llvm {\n";
Enumeration(OS, "SubtargetFeature");
- OS << "} // End llvm namespace \n";
+ OS << "} // end llvm namespace\n";
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
@@ -1461,7 +1462,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "0, 0, 0";
OS << ");\n}\n\n";
- OS << "} // End llvm namespace \n";
+ OS << "} // end llvm namespace\n";
OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
@@ -1491,7 +1492,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
<< " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
<< " const;\n"
<< "};\n";
- OS << "} // End llvm namespace \n";
+ OS << "} // end llvm namespace\n";
OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
@@ -1543,7 +1544,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
EmitSchedModelHelpers(ClassName, OS);
- OS << "} // End llvm namespace \n";
+ OS << "} // end llvm namespace\n";
OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
}
@@ -1555,4 +1556,4 @@ void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
SubtargetEmitter(RK, CGTarget).run(OS);
}
-} // End llvm namespace
+} // end llvm namespace
diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp
index 02fe4dc98bea..c16a5583eb36 100644
--- a/contrib/llvm/utils/TableGen/TableGen.cpp
+++ b/contrib/llvm/utils/TableGen/TableGen.cpp
@@ -41,7 +41,8 @@ enum ActionType {
PrintEnums,
PrintSets,
GenOptParserDefs,
- GenCTags
+ GenCTags,
+ GenAttributes
};
namespace {
@@ -85,6 +86,8 @@ namespace {
"Generate option definitions"),
clEnumValN(GenCTags, "gen-ctags",
"Generate ctags-compatible index"),
+ clEnumValN(GenAttributes, "gen-attrs",
+ "Generate attributes"),
clEnumValEnd));
cl::opt<std::string>
@@ -165,6 +168,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenCTags:
EmitCTags(Records, OS);
break;
+ case GenAttributes:
+ EmitAttributes(Records, OS);
+ break;
}
return false;
diff --git a/contrib/llvm/utils/TableGen/TableGenBackends.h b/contrib/llvm/utils/TableGen/TableGenBackends.h
index 2dc03ce1e71e..d9dd3d157697 100644
--- a/contrib/llvm/utils/TableGen/TableGenBackends.h
+++ b/contrib/llvm/utils/TableGen/TableGenBackends.h
@@ -78,6 +78,7 @@ void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS);
void EmitMapTable(RecordKeeper &RK, raw_ostream &OS);
void EmitOptParser(RecordKeeper &RK, raw_ostream &OS);
void EmitCTags(RecordKeeper &RK, raw_ostream &OS);
+void EmitAttributes(RecordKeeper &RK, raw_ostream &OS);
} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
index efcb0c81e1ca..8a5ae12f67fb 100644
--- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -796,12 +796,12 @@ void RecognizableInstr::emitInstructionSpecifier() {
case X86Local::MRM_E3: case X86Local::MRM_E4: case X86Local::MRM_E5:
case X86Local::MRM_E8: case X86Local::MRM_E9: case X86Local::MRM_EA:
case X86Local::MRM_EB: case X86Local::MRM_EC: case X86Local::MRM_ED:
- case X86Local::MRM_EE: case X86Local::MRM_F0: case X86Local::MRM_F1:
- case X86Local::MRM_F2: case X86Local::MRM_F3: case X86Local::MRM_F4:
- case X86Local::MRM_F5: case X86Local::MRM_F6: case X86Local::MRM_F7:
- case X86Local::MRM_F9: case X86Local::MRM_FA: case X86Local::MRM_FB:
- case X86Local::MRM_FC: case X86Local::MRM_FD: case X86Local::MRM_FE:
- case X86Local::MRM_FF:
+ case X86Local::MRM_EE: case X86Local::MRM_EF: case X86Local::MRM_F0:
+ case X86Local::MRM_F1: case X86Local::MRM_F2: case X86Local::MRM_F3:
+ case X86Local::MRM_F4: case X86Local::MRM_F5: case X86Local::MRM_F6:
+ case X86Local::MRM_F7: case X86Local::MRM_F9: case X86Local::MRM_FA:
+ case X86Local::MRM_FB: case X86Local::MRM_FC: case X86Local::MRM_FD:
+ case X86Local::MRM_FE: case X86Local::MRM_FF:
// Ignored.
break;
}
@@ -951,6 +951,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("f128mem", TYPE_M128)
TYPE("f256mem", TYPE_M256)
TYPE("f512mem", TYPE_M512)
+ TYPE("FR128", TYPE_XMM128)
TYPE("FR64", TYPE_XMM64)
TYPE("FR64X", TYPE_XMM64)
TYPE("f64mem", TYPE_M64FP)
@@ -1069,6 +1070,7 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s,
// register IDs in 8-bit immediates nowadays.
ENCODING("FR32", ENCODING_IB)
ENCODING("FR64", ENCODING_IB)
+ ENCODING("FR128", ENCODING_IB)
ENCODING("VR128", ENCODING_IB)
ENCODING("VR256", ENCODING_IB)
ENCODING("FR32X", ENCODING_IB)
@@ -1091,6 +1093,7 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s,
ENCODING("GR8", ENCODING_RM)
ENCODING("VR128", ENCODING_RM)
ENCODING("VR128X", ENCODING_RM)
+ ENCODING("FR128", ENCODING_RM)
ENCODING("FR64", ENCODING_RM)
ENCODING("FR32", ENCODING_RM)
ENCODING("FR64X", ENCODING_RM)
@@ -1120,6 +1123,7 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s,
ENCODING("GR64", ENCODING_REG)
ENCODING("GR8", ENCODING_REG)
ENCODING("VR128", ENCODING_REG)
+ ENCODING("FR128", ENCODING_REG)
ENCODING("FR64", ENCODING_REG)
ENCODING("FR32", ENCODING_REG)
ENCODING("VR64", ENCODING_REG)
@@ -1157,6 +1161,7 @@ RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s,
ENCODING("GR32", ENCODING_VVVV)
ENCODING("GR64", ENCODING_VVVV)
ENCODING("FR32", ENCODING_VVVV)
+ ENCODING("FR128", ENCODING_VVVV)
ENCODING("FR64", ENCODING_VVVV)
ENCODING("VR128", ENCODING_VVVV)
ENCODING("VR256", ENCODING_VVVV)