[NFC] clang-format utils/TableGen (#80973)

```
find llvm/utils/TableGen -iname "*.h" -o -iname "*.cpp" | xargs clang-format-16 -i
```

Split from #80847
This commit is contained in:
Pierre van Houtryve
2024-02-09 09:27:04 +01:00
committed by GitHub
parent 173e674ba5
commit b9079baadd
61 changed files with 3953 additions and 3871 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -64,6 +64,7 @@ public:
AsmWriterEmitter(RecordKeeper &R);
void run(raw_ostream &o);
private:
void EmitGetMnemonic(
raw_ostream &o,
@@ -84,9 +85,9 @@ private:
} // end anonymous namespace
static void PrintCases(std::vector<std::pair<std::string,
AsmWriterOperand>> &OpsToPrint, raw_ostream &O,
bool PassSubtarget) {
static void
PrintCases(std::vector<std::pair<std::string, AsmWriterOperand>> &OpsToPrint,
raw_ostream &O, bool PassSubtarget) {
O << " case " << OpsToPrint.back().first << ":";
AsmWriterOperand TheOp = OpsToPrint.back().second;
OpsToPrint.pop_back();
@@ -94,9 +95,9 @@ static void PrintCases(std::vector<std::pair<std::string,
// Check to see if any other operands are identical in this list, and if so,
// emit a case label for them.
for (unsigned i = OpsToPrint.size(); i != 0; --i)
if (OpsToPrint[i-1].second == TheOp) {
O << "\n case " << OpsToPrint[i-1].first << ":";
OpsToPrint.erase(OpsToPrint.begin()+i-1);
if (OpsToPrint[i - 1].second == TheOp) {
O << "\n case " << OpsToPrint[i - 1].first << ":";
OpsToPrint.erase(OpsToPrint.begin() + i - 1);
}
// Finally, emit the code.
@@ -106,33 +107,33 @@ static void PrintCases(std::vector<std::pair<std::string,
/// EmitInstructions - Emit the last instruction in the vector and any other
/// instructions that are suitably similar to it.
static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
raw_ostream &O, bool PassSubtarget) {
static void EmitInstructions(std::vector<AsmWriterInst> &Insts, raw_ostream &O,
bool PassSubtarget) {
AsmWriterInst FirstInst = Insts.back();
Insts.pop_back();
std::vector<AsmWriterInst> SimilarInsts;
unsigned DifferingOperand = ~0;
for (unsigned i = Insts.size(); i != 0; --i) {
unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst);
unsigned DiffOp = Insts[i - 1].MatchesAllButOneOp(FirstInst);
if (DiffOp != ~1U) {
if (DifferingOperand == ~0U) // First match!
if (DifferingOperand == ~0U) // First match!
DifferingOperand = DiffOp;
// If this differs in the same operand as the rest of the instructions in
// this class, move it to the SimilarInsts list.
if (DifferingOperand == DiffOp || DiffOp == ~0U) {
SimilarInsts.push_back(Insts[i-1]);
Insts.erase(Insts.begin()+i-1);
SimilarInsts.push_back(Insts[i - 1]);
Insts.erase(Insts.begin() + i - 1);
}
}
}
O << " case " << FirstInst.CGI->Namespace << "::"
<< FirstInst.CGI->TheDef->getName() << ":\n";
O << " case " << FirstInst.CGI->Namespace
<< "::" << FirstInst.CGI->TheDef->getName() << ":\n";
for (const AsmWriterInst &AWI : SimilarInsts)
O << " case " << AWI.CGI->Namespace << "::"
<< AWI.CGI->TheDef->getName() << ":\n";
O << " case " << AWI.CGI->Namespace << "::" << AWI.CGI->TheDef->getName()
<< ":\n";
for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) {
if (i != DifferingOperand) {
// If the operand is the same for all instructions, just print it.
@@ -143,14 +144,15 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
O << " switch (MI->getOpcode()) {\n";
O << " default: llvm_unreachable(\"Unexpected opcode.\");\n";
std::vector<std::pair<std::string, AsmWriterOperand>> OpsToPrint;
OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace.str() + "::" +
FirstInst.CGI->TheDef->getName().str(),
FirstInst.Operands[i]));
OpsToPrint.push_back(
std::make_pair(FirstInst.CGI->Namespace.str() +
"::" + FirstInst.CGI->TheDef->getName().str(),
FirstInst.Operands[i]));
for (const AsmWriterInst &AWI : SimilarInsts) {
OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace.str()+"::" +
AWI.CGI->TheDef->getName().str(),
AWI.Operands[i]));
OpsToPrint.push_back(std::make_pair(
AWI.CGI->Namespace.str() + "::" + AWI.CGI->TheDef->getName().str(),
AWI.Operands[i]));
}
std::reverse(OpsToPrint.begin(), OpsToPrint.end());
while (!OpsToPrint.empty())
@@ -162,11 +164,10 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
O << " break;\n";
}
void AsmWriterEmitter::
FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
std::vector<std::vector<unsigned>> &InstIdxs,
std::vector<unsigned> &InstOpsUsed,
bool PassSubtarget) const {
void AsmWriterEmitter::FindUniqueOperandCommands(
std::vector<std::string> &UniqueOperandCommands,
std::vector<std::vector<unsigned>> &InstIdxs,
std::vector<unsigned> &InstOpsUsed, bool PassSubtarget) const {
// This vector parallels UniqueOperandCommands, keeping track of which
// instructions each case are used for. It is a comma separated string of
// enums.
@@ -177,9 +178,10 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
for (size_t i = 0, e = Instructions.size(); i != e; ++i) {
const AsmWriterInst &Inst = Instructions[i];
if (Inst.Operands.empty())
continue; // Instruction already done.
continue; // Instruction already done.
std::string Command = " "+Inst.Operands[0].getCode(PassSubtarget)+"\n";
std::string Command =
" " + Inst.Operands[0].getCode(PassSubtarget) + "\n";
// Check to see if we already have 'Command' in UniqueOperandCommands.
// If not, add it.
@@ -203,12 +205,12 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
// For each entry of UniqueOperandCommands, there is a set of instructions
// that uses it. If the next command of all instructions in the set are
// identical, fold it into the command.
for (size_t CommandIdx = 0, e = UniqueOperandCommands.size();
CommandIdx != e; ++CommandIdx) {
for (size_t CommandIdx = 0, e = UniqueOperandCommands.size(); CommandIdx != e;
++CommandIdx) {
const auto &Idxs = InstIdxs[CommandIdx];
for (unsigned Op = 1; ; ++Op) {
for (unsigned Op = 1;; ++Op) {
// Find the first instruction in the set.
const AsmWriterInst &FirstInst = Instructions[Idxs.front()];
// If this instruction has no more operands, we isn't anything to merge
@@ -227,8 +229,8 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
// Okay, everything in this command set has the same next operand. Add it
// to UniqueOperandCommands and remember that it was consumed.
std::string Command = " " +
FirstInst.Operands[Op].getCode(PassSubtarget) + "\n";
std::string Command =
" " + FirstInst.Operands[Op].getCode(PassSubtarget) + "\n";
UniqueOperandCommands[CommandIdx] += Command;
InstOpsUsed[CommandIdx]++;
@@ -239,35 +241,58 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) {
std::string Instrs = InstrsForCase[i];
if (Instrs.size() > 70) {
Instrs.erase(Instrs.begin()+70, Instrs.end());
Instrs.erase(Instrs.begin() + 70, Instrs.end());
Instrs += "...";
}
if (!Instrs.empty())
UniqueOperandCommands[i] = " // " + Instrs + "\n" +
UniqueOperandCommands[i];
UniqueOperandCommands[i] =
" // " + Instrs + "\n" + UniqueOperandCommands[i];
}
}
static void UnescapeString(std::string &Str) {
for (unsigned i = 0; i != Str.size(); ++i) {
if (Str[i] == '\\' && i != Str.size()-1) {
switch (Str[i+1]) {
default: continue; // Don't execute the code after the switch.
case 'a': Str[i] = '\a'; break;
case 'b': Str[i] = '\b'; break;
case 'e': Str[i] = 27; break;
case 'f': Str[i] = '\f'; break;
case 'n': Str[i] = '\n'; break;
case 'r': Str[i] = '\r'; break;
case 't': Str[i] = '\t'; break;
case 'v': Str[i] = '\v'; break;
case '"': Str[i] = '\"'; break;
case '\'': Str[i] = '\''; break;
case '\\': Str[i] = '\\'; break;
if (Str[i] == '\\' && i != Str.size() - 1) {
switch (Str[i + 1]) {
default:
continue; // Don't execute the code after the switch.
case 'a':
Str[i] = '\a';
break;
case 'b':
Str[i] = '\b';
break;
case 'e':
Str[i] = 27;
break;
case 'f':
Str[i] = '\f';
break;
case 'n':
Str[i] = '\n';
break;
case 'r':
Str[i] = '\r';
break;
case 't':
Str[i] = '\t';
break;
case 'v':
Str[i] = '\v';
break;
case '"':
Str[i] = '\"';
break;
case '\'':
Str[i] = '\'';
break;
case '\\':
Str[i] = '\\';
break;
}
// Nuke the second character.
Str.erase(Str.begin()+i+1);
Str.erase(Str.begin() + i + 1);
}
}
}
@@ -281,14 +306,19 @@ static void UnescapeString(std::string &Str) {
/// causes non-standard escape character warnings.
static void UnescapeAliasString(std::string &Str) {
for (unsigned i = 0; i != Str.size(); ++i) {
if (Str[i] == '\\' && i != Str.size()-1) {
switch (Str[i+1]) {
default: continue; // Don't execute the code after the switch.
case '{': Str[i] = '{'; break;
case '}': Str[i] = '}'; break;
if (Str[i] == '\\' && i != Str.size() - 1) {
switch (Str[i + 1]) {
default:
continue; // Don't execute the code after the switch.
case '{':
Str[i] = '{';
break;
case '}':
Str[i] = '}';
break;
}
// Nuke the second character.
Str.erase(Str.begin()+i+1);
Str.erase(Str.begin() + i + 1);
}
}
}
@@ -318,8 +348,7 @@ void AsmWriterEmitter::EmitGetMnemonic(
// Add all strings to the string table upfront so it can generate an optimized
// representation.
for (AsmWriterInst &AWI : Instructions) {
if (AWI.Operands[0].OperandType ==
AsmWriterOperand::isLiteralTextOperand &&
if (AWI.Operands[0].OperandType == AsmWriterOperand::isLiteralTextOperand &&
!AWI.Operands[0].Str.empty()) {
std::string Str = AWI.Operands[0].Str;
UnescapeString(Str);
@@ -347,7 +376,7 @@ void AsmWriterEmitter::EmitGetMnemonic(
}
// Bias offset by one since we want 0 as a sentinel.
OpcodeInfo[AWI.CGIIndex] = Idx+1;
OpcodeInfo[AWI.CGIIndex] = Idx + 1;
}
// Figure out how many bits we used for the string index.
@@ -365,7 +394,8 @@ void AsmWriterEmitter::EmitGetMnemonic(
NumInstOpsHandled, PassSubtarget);
// If we ran out of operands to print, we're done.
if (UniqueOperandCommands.empty()) break;
if (UniqueOperandCommands.empty())
break;
// Compute the number of bits we need to represent these cases, this is
// ceil(log2(numentries)).
@@ -383,14 +413,14 @@ void AsmWriterEmitter::EmitGetMnemonic(
unsigned NumOps = NumInstOpsHandled[i];
for (unsigned Idx : InstIdxs[i]) {
OpcodeInfo[Instructions[Idx].CGIIndex] |=
(uint64_t)i << (OpcodeInfoBits-BitsLeft);
(uint64_t)i << (OpcodeInfoBits - BitsLeft);
// Remove the info about this operand from the instruction.
AsmWriterInst &Inst = Instructions[Idx];
if (!Inst.Operands.empty()) {
assert(NumOps <= Inst.Operands.size() &&
"Can't remove this many ops!");
Inst.Operands.erase(Inst.Operands.begin(),
Inst.Operands.begin()+NumOps);
Inst.Operands.begin() + NumOps);
}
}
}
@@ -487,7 +517,7 @@ void AsmWriterEmitter::EmitPrintInstruction(
<< " assert(Bits != 0 && \"Cannot print this instruction.\");\n";
// Output the table driven operand information.
BitsLeft = OpcodeInfoBits-AsmStrBits;
BitsLeft = OpcodeInfoBits - AsmStrBits;
for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) {
std::vector<std::string> &Commands = TableDrivenOperandPrinters[i];
@@ -497,25 +527,21 @@ void AsmWriterEmitter::EmitPrintInstruction(
assert(NumBits <= BitsLeft && "consistency error");
// Emit code to extract this field from Bits.
O << "\n // Fragment " << i << " encoded into " << NumBits
<< " bits for " << Commands.size() << " unique commands.\n";
O << "\n // Fragment " << i << " encoded into " << NumBits << " bits for "
<< Commands.size() << " unique commands.\n";
if (Commands.size() == 2) {
// Emit two possibilitys with if/else.
O << " if ((Bits >> "
<< (OpcodeInfoBits-BitsLeft) << ") & "
<< ((1 << NumBits)-1) << ") {\n"
<< Commands[1]
<< " } else {\n"
<< Commands[0]
<< " }\n\n";
O << " if ((Bits >> " << (OpcodeInfoBits - BitsLeft) << ") & "
<< ((1 << NumBits) - 1) << ") {\n"
<< Commands[1] << " } else {\n"
<< Commands[0] << " }\n\n";
} else if (Commands.size() == 1) {
// Emit a single possibility.
O << Commands[0] << "\n\n";
} else {
O << " switch ((Bits >> "
<< (OpcodeInfoBits-BitsLeft) << ") & "
<< ((1 << NumBits)-1) << ") {\n"
O << " switch ((Bits >> " << (OpcodeInfoBits - BitsLeft) << ") & "
<< ((1 << NumBits) - 1) << ") {\n"
<< " default: llvm_unreachable(\"Invalid command number.\");\n";
// Print out all the cases.
@@ -537,7 +563,6 @@ void AsmWriterEmitter::EmitPrintInstruction(
// elements in the vector.
std::reverse(Instructions.begin(), Instructions.end());
// Now that we've emitted all of the operand info that fit into 64 bits, emit
// information for those instructions that are left. This is a less dense
// encoding, but we expect the main 64-bit table to handle the majority of
@@ -572,22 +597,21 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
AsmName = std::string(Reg.getName());
} else {
// Make sure the register has an alternate name for this index.
std::vector<Record*> AltNameList =
Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices");
std::vector<Record *> AltNameList =
Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices");
unsigned Idx = 0, e;
for (e = AltNameList.size();
Idx < e && (AltNameList[Idx]->getName() != AltName);
++Idx)
Idx < e && (AltNameList[Idx]->getName() != AltName); ++Idx)
;
// If the register has an alternate name for this index, use it.
// Otherwise, leave it empty as an error flag.
if (Idx < e) {
std::vector<StringRef> AltNames =
Reg.TheDef->getValueAsListOfStrings("AltNames");
Reg.TheDef->getValueAsListOfStrings("AltNames");
if (AltNames.size() <= Idx)
PrintFatalError(Reg.TheDef->getLoc(),
"Register definition missing alt name for '" +
AltName + "'.");
AltName + "'.");
AsmName = std::string(AltNames[Idx]);
}
}
@@ -613,15 +637,17 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
Record *AsmWriter = Target.getAsmWriter();
StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
const auto &Registers = Target.getRegBank().getRegisters();
const std::vector<Record*> &AltNameIndices = Target.getRegAltNameIndices();
const std::vector<Record *> &AltNameIndices = Target.getRegAltNameIndices();
bool hasAltNames = AltNameIndices.size() > 1;
StringRef Namespace = Registers.front().TheDef->getValueAsString("Namespace");
O <<
"\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
"/// from the register set description. This returns the assembler name\n"
"/// for the specified register.\n"
"const char *" << Target.getName() << ClassName << "::";
O << "\n\n/// getRegisterName - This method is automatically generated by "
"tblgen\n"
"/// from the register set description. This returns the assembler "
"name\n"
"/// for the specified register.\n"
"const char *"
<< Target.getName() << ClassName << "::";
if (hasAltNames)
O << "\ngetRegisterName(MCRegister Reg, unsigned AltIdx) {\n";
else
@@ -695,8 +721,7 @@ public:
void addOperand(StringRef Op, int OpIdx, int PrintMethodIdx = -1) {
assert(OpIdx >= 0 && OpIdx < 0xFE && "Idx out of range");
assert(PrintMethodIdx >= -1 && PrintMethodIdx < 0xFF &&
"Idx out of range");
assert(PrintMethodIdx >= -1 && PrintMethodIdx < 0xFF && "Idx out of range");
OpMap[Op] = std::make_pair(OpIdx, PrintMethodIdx);
}
@@ -791,7 +816,7 @@ namespace {
struct AliasPriorityComparator {
typedef std::pair<CodeGenInstAlias, int> ValueType;
bool operator()(const ValueType &LHS, const ValueType &RHS) const {
if (LHS.second == RHS.second) {
if (LHS.second == RHS.second) {
// We don't actually care about the order, but for consistency it
// shouldn't depend on pointer comparisons.
return LessRecordByID()(LHS.first.TheDef, RHS.first.TheDef);
@@ -819,8 +844,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
unsigned Variant = AsmWriter->getValueAsInt("Variant");
bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
std::vector<Record*> AllInstAliases =
Records.getAllDerivedDefinitions("InstAlias");
std::vector<Record *> AllInstAliases =
Records.getAllDerivedDefinitions("InstAlias");
// Create a map from the qualified name to a list of potential matches.
typedef std::set<std::pair<CodeGenInstAlias, int>, AliasPriorityComparator>
@@ -843,8 +868,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
std::vector<std::pair<std::string, bool>> PrintMethods;
// A list of MCOperandPredicates for all operands in use, and the reverse map
std::vector<const Record*> MCOpPredicates;
DenseMap<const Record*, unsigned> MCOpPredicateMap;
std::vector<const Record *> MCOpPredicates;
DenseMap<const Record *, unsigned> MCOpPredicateMap;
for (auto &Aliases : AliasMap) {
// Collection of instruction alias rules. May contain ambiguous rules.
@@ -854,8 +879,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
const CodeGenInstAlias &CGA = Alias.first;
unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
std::string FlatInstAsmString =
CodeGenInstruction::FlattenAsmStringVariants(CGA.ResultInst->AsmString,
Variant);
CodeGenInstruction::FlattenAsmStringVariants(
CGA.ResultInst->AsmString, Variant);
unsigned NumResultOps = CountNumOperands(FlatInstAsmString, Variant);
std::string FlatAliasAsmString =
@@ -881,8 +906,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
unsigned OpNum = Operands.getSubOperandNumber(MIOpNum).first;
if (Operands[OpNum].MINumOperands == 1 &&
Operands[OpNum].getTiedRegister() != -1) {
// Tied operands of different RegisterClass should be explicit within
// an instruction's syntax and so cannot be skipped.
// Tied operands of different RegisterClass should be explicit
// within an instruction's syntax and so cannot be skipped.
int TiedOpNum = Operands[OpNum].getTiedRegister();
if (Operands[OpNum].Rec->getName() ==
Operands[TiedOpNum].Rec->getName()) {
@@ -1083,7 +1108,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (It == IAPrinterMap.end())
continue;
std::vector<IAPrinter> &IAPs = It->second;
std::vector<IAPrinter*> UniqueIAPs;
std::vector<IAPrinter *> UniqueIAPs;
// Remove any ambiguous alias rules.
for (auto &LHS : IAPs) {
@@ -1099,7 +1124,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
UniqueIAPs.push_back(&LHS);
}
if (UniqueIAPs.empty()) continue;
if (UniqueIAPs.empty())
continue;
unsigned PatternStart = PatternCount;
@@ -1193,7 +1219,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (MCOpPredicates.empty())
O.indent(2) << " nullptr,\n";
else
O.indent(2) << " &" << Target.getName() << ClassName << "ValidateMCOperand,\n";
O.indent(2) << " &" << Target.getName() << ClassName
<< "ValidateMCOperand,\n";
O.indent(2) << "};\n";
O.indent(2) << "const char *AsmString = matchAliasPatterns(MI, "
@@ -1262,21 +1289,22 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
<< " break;\n";
}
O << " }\n";
}
}
O << "}\n\n";
if (!MCOpPredicates.empty()) {
O << "static bool " << Target.getName() << ClassName
<< "ValidateMCOperand(const MCOperand &MCOp,\n"
<< " const MCSubtargetInfo &STI,\n"
<< " unsigned PredicateIndex) {\n"
<< " unsigned PredicateIndex) {\n"
<< " switch (PredicateIndex) {\n"
<< " default:\n"
<< " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
<< " break;\n";
for (unsigned i = 0; i < MCOpPredicates.size(); ++i) {
StringRef MCOpPred = MCOpPredicates[i]->getValueAsString("MCOperandPredicate");
StringRef MCOpPred =
MCOpPredicates[i]->getValueAsString("MCOperandPredicate");
O << " case " << i + 1 << ": {\n"
<< MCOpPred.data() << "\n"
<< " }\n";

View File

@@ -57,54 +57,55 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
std::string::size_type LastEmitted = 0;
while (LastEmitted != AsmString.size()) {
std::string::size_type DollarPos =
AsmString.find_first_of("$\\", LastEmitted);
if (DollarPos == std::string::npos) DollarPos = AsmString.size();
AsmString.find_first_of("$\\", LastEmitted);
if (DollarPos == std::string::npos)
DollarPos = AsmString.size();
// Emit a constant string fragment.
if (DollarPos != LastEmitted) {
for (; LastEmitted != DollarPos; ++LastEmitted)
switch (AsmString[LastEmitted]) {
case '\n':
AddLiteralString("\\n");
break;
case '\t':
AddLiteralString("\\t");
break;
case '"':
AddLiteralString("\\\"");
break;
case '\\':
AddLiteralString("\\\\");
break;
default:
AddLiteralString(std::string(1, AsmString[LastEmitted]));
break;
case '\n':
AddLiteralString("\\n");
break;
case '\t':
AddLiteralString("\\t");
break;
case '"':
AddLiteralString("\\\"");
break;
case '\\':
AddLiteralString("\\\\");
break;
default:
AddLiteralString(std::string(1, AsmString[LastEmitted]));
break;
}
} else if (AsmString[DollarPos] == '\\') {
if (DollarPos+1 != AsmString.size()) {
if (AsmString[DollarPos+1] == 'n') {
if (DollarPos + 1 != AsmString.size()) {
if (AsmString[DollarPos + 1] == 'n') {
AddLiteralString("\\n");
} else if (AsmString[DollarPos+1] == 't') {
} else if (AsmString[DollarPos + 1] == 't') {
AddLiteralString("\\t");
} else if (std::string("${|}\\").find(AsmString[DollarPos+1])
!= std::string::npos) {
AddLiteralString(std::string(1, AsmString[DollarPos+1]));
} else if (std::string("${|}\\").find(AsmString[DollarPos + 1]) !=
std::string::npos) {
AddLiteralString(std::string(1, AsmString[DollarPos + 1]));
} else {
PrintFatalError(
CGI.TheDef->getLoc(),
"Non-supported escaped character found in instruction '" +
CGI.TheDef->getName() + "'!");
}
LastEmitted = DollarPos+2;
LastEmitted = DollarPos + 2;
continue;
}
} else if (DollarPos+1 != AsmString.size() &&
AsmString[DollarPos+1] == '$') {
AddLiteralString("$"); // "$$" -> $
LastEmitted = DollarPos+2;
} else if (DollarPos + 1 != AsmString.size() &&
AsmString[DollarPos + 1] == '$') {
AddLiteralString("$"); // "$$" -> $
LastEmitted = DollarPos + 2;
} else {
// Get the name of the variable.
std::string::size_type VarEnd = DollarPos+1;
std::string::size_type VarEnd = DollarPos + 1;
// handle ${foo}bar as $foo by detecting whether the character following
// the dollar sign is a curly brace. If so, advance VarEnd and DollarPos
@@ -118,7 +119,8 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
++VarEnd;
StringRef VarName(AsmString.data()+DollarPos+1, VarEnd-DollarPos-1);
StringRef VarName(AsmString.data() + DollarPos + 1,
VarEnd - DollarPos - 1);
// Modifier - Support ${foo:modifier} syntax, where "modifier" is passed
// into printOperand. Also support ${:feature}, which is passed into
@@ -190,13 +192,14 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
/// specified instruction except for one differing operand, return the differing
/// operand number. If more than one operand mismatches, return ~1, otherwise
/// if the instructions are identical return ~0.
unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
if (Operands.size() != Other.Operands.size()) return ~1;
unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other) const {
if (Operands.size() != Other.Operands.size())
return ~1;
unsigned MismatchOperand = ~0U;
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (Operands[i] != Other.Operands[i]) {
if (MismatchOperand != ~0U) // Already have one mismatch?
if (MismatchOperand != ~0U) // Already have one mismatch?
return ~1U;
MismatchOperand = i;
}

View File

@@ -20,88 +20,88 @@
#include <vector>
namespace llvm {
class CodeGenInstruction;
class CodeGenInstruction;
struct AsmWriterOperand {
enum OpType {
// Output this text surrounded by quotes to the asm.
isLiteralTextOperand,
// This is the name of a routine to call to print the operand.
isMachineInstrOperand,
// Output this text verbatim to the asm writer. It is code that
// will output some text to the asm.
isLiteralStatementOperand
} OperandType;
struct AsmWriterOperand {
enum OpType {
// Output this text surrounded by quotes to the asm.
isLiteralTextOperand,
// This is the name of a routine to call to print the operand.
isMachineInstrOperand,
// Output this text verbatim to the asm writer. It is code that
// will output some text to the asm.
isLiteralStatementOperand
} OperandType;
/// MiOpNo - For isMachineInstrOperand, this is the operand number of the
/// machine instruction.
unsigned MIOpNo = 0;
/// MiOpNo - For isMachineInstrOperand, this is the operand number of the
/// machine instruction.
unsigned MIOpNo = 0;
/// Str - For isLiteralTextOperand, this IS the literal text. For
/// isMachineInstrOperand, this is the PrinterMethodName for the operand..
/// For isLiteralStatementOperand, this is the code to insert verbatim
/// into the asm writer.
std::string Str;
/// Str - For isLiteralTextOperand, this IS the literal text. For
/// isMachineInstrOperand, this is the PrinterMethodName for the operand..
/// For isLiteralStatementOperand, this is the code to insert verbatim
/// into the asm writer.
std::string Str;
/// MiModifier - For isMachineInstrOperand, this is the modifier string for
/// an operand, specified with syntax like ${opname:modifier}.
std::string MiModifier;
/// MiModifier - For isMachineInstrOperand, this is the modifier string for
/// an operand, specified with syntax like ${opname:modifier}.
std::string MiModifier;
bool PCRel = false;
bool PCRel = false;
// To make VS STL happy
AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
// To make VS STL happy
AsmWriterOperand(OpType op = isLiteralTextOperand) : OperandType(op) {}
AsmWriterOperand(const std::string &LitStr,
OpType op = isLiteralTextOperand)
: OperandType(op), Str(LitStr) {}
AsmWriterOperand(const std::string &LitStr, OpType op = isLiteralTextOperand)
: OperandType(op), Str(LitStr) {}
AsmWriterOperand(const std::string &Printer, unsigned _MIOpNo,
const std::string &Modifier,
OpType op = isMachineInstrOperand, bool PCRel = false)
: OperandType(op), MIOpNo(_MIOpNo), Str(Printer), MiModifier(Modifier),
PCRel(PCRel) {}
AsmWriterOperand(const std::string &Printer, unsigned _MIOpNo,
const std::string &Modifier,
OpType op = isMachineInstrOperand, bool PCRel = false)
: OperandType(op), MIOpNo(_MIOpNo), Str(Printer), MiModifier(Modifier),
PCRel(PCRel) {}
bool operator!=(const AsmWriterOperand &Other) const {
if (OperandType != Other.OperandType || Str != Other.Str) return true;
if (OperandType == isMachineInstrOperand)
return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier ||
PCRel != Other.PCRel;
return false;
}
bool operator==(const AsmWriterOperand &Other) const {
return !operator!=(Other);
}
bool operator!=(const AsmWriterOperand &Other) const {
if (OperandType != Other.OperandType || Str != Other.Str)
return true;
if (OperandType == isMachineInstrOperand)
return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier ||
PCRel != Other.PCRel;
return false;
}
bool operator==(const AsmWriterOperand &Other) const {
return !operator!=(Other);
}
/// getCode - Return the code that prints this operand.
std::string getCode(bool PassSubtarget) const;
};
/// getCode - Return the code that prints this operand.
std::string getCode(bool PassSubtarget) const;
};
class AsmWriterInst {
public:
std::vector<AsmWriterOperand> Operands;
const CodeGenInstruction *CGI;
unsigned CGIIndex;
class AsmWriterInst {
public:
std::vector<AsmWriterOperand> Operands;
const CodeGenInstruction *CGI;
unsigned CGIIndex;
AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
unsigned Variant);
AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
unsigned Variant);
/// MatchesAllButOneOp - If this instruction is exactly identical to the
/// specified instruction except for one differing operand, return the
/// differing operand number. Otherwise return ~0.
unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;
/// MatchesAllButOneOp - If this instruction is exactly identical to the
/// specified instruction except for one differing operand, return the
/// differing operand number. Otherwise return ~0.
unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;
private:
void AddLiteralString(const std::string &Str) {
// If the last operand was already a literal text string, append this to
// it, otherwise add a new operand.
if (!Operands.empty() &&
Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
Operands.back().Str.append(Str);
else
Operands.push_back(AsmWriterOperand(Str));
}
};
}
private:
void AddLiteralString(const std::string &Str) {
// If the last operand was already a literal text string, append this to
// it, otherwise add a new operand.
if (!Operands.empty() &&
Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
Operands.back().Str.append(Str);
else
Operands.push_back(AsmWriterOperand(Str));
}
};
} // namespace llvm
#endif

View File

@@ -1,4 +1,4 @@
//===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===//
//===- CTagsEmitter.cpp - Generate ctags-compatible index -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -30,6 +30,7 @@ private:
StringRef Id;
StringRef BufferIdentifier;
unsigned Line;
public:
Tag(StringRef Name, const SMLoc Location) : Id(Name) {
const MemoryBuffer *CurMB =
@@ -39,7 +40,8 @@ public:
Line = LineAndColumn.first;
}
int operator<(const Tag &B) const {
return std::make_tuple(Id, BufferIdentifier, Line) < std::make_tuple(B.Id, B.BufferIdentifier, B.Line);
return std::make_tuple(Id, BufferIdentifier, Line) <
std::make_tuple(B.Id, B.BufferIdentifier, B.Line);
}
void emit(raw_ostream &OS) const {
OS << Id << "\t" << BufferIdentifier << "\t" << Line << "\n";
@@ -49,6 +51,7 @@ public:
class CTagsEmitter {
private:
RecordKeeper &Records;
public:
CTagsEmitter(RecordKeeper &R) : Records(R) {}

View File

@@ -117,23 +117,24 @@ void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
O << "\n";
EmitAction(Action, 2, O);
}
O << "\n return true; // CC didn't match.\n";
O << "}\n";
}
void CallingConvEmitter::EmitAction(Record *Action,
unsigned Indent, raw_ostream &O) {
void CallingConvEmitter::EmitAction(Record *Action, unsigned Indent,
raw_ostream &O) {
std::string IndentStr = std::string(Indent, ' ');
if (Action->isSubClassOf("CCPredicateAction")) {
O << IndentStr << "if (";
if (Action->isSubClassOf("CCIfType")) {
ListInit *VTs = Action->getValueAsListInit("VTs");
for (unsigned i = 0, e = VTs->size(); i != e; ++i) {
Record *VT = VTs->getElementAsRecord(i);
if (i != 0) O << " ||\n " << IndentStr;
if (i != 0)
O << " ||\n " << IndentStr;
O << "LocVT == " << getEnumName(getValueType(VT));
}
@@ -143,9 +144,9 @@ void CallingConvEmitter::EmitAction(Record *Action,
errs() << *Action;
PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!");
}
O << ") {\n";
EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);
EmitAction(Action->getValueAsDef("SubAction"), Indent + 2, O);
O << IndentStr << "}\n";
} else {
if (Action->isSubClassOf("CCDelegateTo")) {
@@ -241,8 +242,8 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << "\n" << IndentStr << "};\n";
O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
<< RegListNumber << ", " << "RegList" << ShadowRegListNumber
<< ")) {\n";
<< RegListNumber << ", "
<< "RegList" << ShadowRegListNumber << ")) {\n";
}
O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
<< "Reg, LocVT, LocInfo));\n";
@@ -257,7 +258,8 @@ void CallingConvEmitter::EmitAction(Record *Action,
if (Size)
O << Size << ", ";
else
O << "\n" << IndentStr
O << "\n"
<< IndentStr
<< " State.getMachineFunction().getDataLayout()."
"getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
" ";
@@ -269,8 +271,8 @@ void CallingConvEmitter::EmitAction(Record *Action,
<< " State.getMachineFunction().getDataLayout()."
"getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()"
"))";
O << ");\n" << IndentStr
<< "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
O << ");\n"
<< IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
<< Counter << ", LocVT, LocInfo));\n";
O << IndentStr << "return false;\n";
} else if (Action->isSubClassOf("CCAssignToStackWithShadow")) {
@@ -281,7 +283,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
unsigned ShadowRegListNumber = ++Counter;
O << IndentStr << "static const MCPhysReg ShadowRegList"
<< ShadowRegListNumber << "[] = {\n";
<< ShadowRegListNumber << "[] = {\n";
O << IndentStr << " ";
ListSeparator LS;
for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i)
@@ -297,7 +299,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
} else if (Action->isSubClassOf("CCPromoteToType")) {
Record *DestTy = Action->getValueAsDef("DestTy");
MVT::SimpleValueType DestVT = getValueType(DestTy);
O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n";
O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
if (MVT(DestVT).isFloatingPoint()) {
O << IndentStr << "LocInfo = CCValAssign::FPExt;\n";
} else {
@@ -326,15 +328,18 @@ void CallingConvEmitter::EmitAction(Record *Action,
}
} else if (Action->isSubClassOf("CCBitConvertToType")) {
Record *DestTy = Action->getValueAsDef("DestTy");
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy))
<< ";\n";
O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
} else if (Action->isSubClassOf("CCTruncToType")) {
Record *DestTy = Action->getValueAsDef("DestTy");
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy))
<< ";\n";
O << IndentStr << "LocInfo = CCValAssign::Trunc;\n";
} else if (Action->isSubClassOf("CCPassIndirect")) {
Record *DestTy = Action->getValueAsDef("DestTy");
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy))
<< ";\n";
O << IndentStr << "LocInfo = CCValAssign::Indirect;\n";
} else if (Action->isSubClassOf("CCPassByVal")) {
int Size = Action->getValueAsInt("Size");
@@ -343,8 +348,8 @@ void CallingConvEmitter::EmitAction(Record *Action,
<< Size << ", Align(" << Align << "), ArgFlags);\n";
O << IndentStr << "return false;\n";
} else if (Action->isSubClassOf("CCCustom")) {
O << IndentStr
<< "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "
O << IndentStr << "if (" << Action->getValueAsString("FuncName")
<< "(ValNo, ValVT, "
<< "LocVT, LocInfo, ArgFlags, State))\n";
O << IndentStr << " return false;\n";
} else {
@@ -376,9 +381,8 @@ void CallingConvEmitter::EmitArgRegisterLists(raw_ostream &O) {
std::set<std::string> &InnerRegisters = InnerEntry.second;
if (InnerRegisters.find(CCName) != InnerRegisters.end()) {
AssignedRegsMap[InnerCCName].insert(
AssignedRegsMap[CCName].begin(),
AssignedRegsMap[CCName].end());
AssignedRegsMap[InnerCCName].insert(AssignedRegsMap[CCName].begin(),
AssignedRegsMap[CCName].end());
InnerRegisters.erase(CCName);
}
}

View File

@@ -78,8 +78,8 @@ private:
// If the VarBitInit at position 'bit' matches the specified variable then
// return the variable bit position. Otherwise return -1.
int CodeEmitterGen::getVariableBit(const std::string &VarName,
BitsInit *BI, int bit) {
int CodeEmitterGen::getVariableBit(const std::string &VarName, BitsInit *BI,
int bit) {
if (VarBitInit *VBI = dyn_cast<VarBitInit>(BI->getBit(bit))) {
if (VarInit *VI = dyn_cast<VarInit>(VBI->getBitVar()))
if (VI->getName() == VarName)
@@ -101,16 +101,16 @@ bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI,
CodeGenInstruction &CGI = Target.getInstruction(R);
// Determine if VarName actually contributes to the Inst encoding.
int bit = BI->getNumBits()-1;
int bit = BI->getNumBits() - 1;
// Scan for a bit that this contributed to.
for (; bit >= 0; ) {
for (; bit >= 0;) {
if (getVariableBit(VarName, BI, bit) != -1)
break;
--bit;
}
// If we found no bits, ignore this value, otherwise emit the call to get the
// operand encoding.
if (bit < 0)
@@ -127,12 +127,14 @@ bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI,
// Get the machine operand number for the indicated operand.
OpIdx = CGI.Operands[OpIdx].MIOperandNo;
} else {
PrintError(R, Twine("No operand named ") + VarName + " in record " + R->getName());
PrintError(R, Twine("No operand named ") + VarName + " in record " +
R->getName());
return false;
}
if (CGI.Operands.isFlatOperandNotEmitted(OpIdx)) {
PrintError(R, "Operand " + VarName + " used but also marked as not emitted!");
PrintError(R,
"Operand " + VarName + " used but also marked as not emitted!");
return false;
}
@@ -156,10 +158,12 @@ bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI,
Case += ", Fixups, STI);\n";
} else {
if (UseAPInt) {
Case += " getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
Case +=
" getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
Case += ", op, Fixups, STI";
} else {
Case += " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
Case += " op = getMachineOpValue(MI, MI.getOperand(" +
utostr(OpIdx) + ")";
Case += ", Fixups, STI";
}
Case += ");\n";
@@ -193,9 +197,9 @@ bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI,
}
unsigned BitOffset = -1;
for (; bit >= 0; ) {
for (; bit >= 0;) {
int varBit = getVariableBit(VarName, BI, bit);
// If this bit isn't from a variable, skip it.
if (varBit == -1) {
--bit;
@@ -209,7 +213,8 @@ bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI,
int N = 1;
for (--bit; bit >= 0;) {
varBit = getVariableBit(VarName, BI, bit);
if (varBit == -1 || varBit != (beginVarBit - N)) break;
if (varBit == -1 || varBit != (beginVarBit - N))
break;
++N;
--bit;
}
@@ -368,7 +373,9 @@ void CodeEmitterGen::emitInstructionBaseValues(
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
R->getValueAsBit("isPseudo")) {
o << " "; emitInstBits(o, APInt(BitWidth, 0)); o << ",\n";
o << " ";
emitInstBits(o, APInt(BitWidth, 0));
o << ",\n";
continue;
}
@@ -419,13 +426,13 @@ void CodeEmitterGen::run(raw_ostream &o) {
emitSourceFileHeader("Machine Code Emitter", o);
CodeGenTarget Target(Records);
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
// For little-endian instruction bit encodings, reverse the bit order
Target.reverseBitsForLittleEndianEncoding();
ArrayRef<const CodeGenInstruction*> NumberedInstructions =
Target.getInstructionsByEnumValue();
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
Target.getInstructionsByEnumValue();
if (any_of(NumberedInstructions, [](const CodeGenInstruction *CGI) {
Record *R = CGI->TheDef;

File diff suppressed because it is too large Load Diff

View File

@@ -56,17 +56,15 @@ struct MachineValueTypeSet {
static_assert(std::is_same<std::underlying_type_t<MVT::SimpleValueType>,
uint8_t>::value,
"Change uint8_t here to the SimpleValueType's type");
static unsigned constexpr Capacity = std::numeric_limits<uint8_t>::max()+1;
static unsigned constexpr Capacity = std::numeric_limits<uint8_t>::max() + 1;
using WordType = uint64_t;
static unsigned constexpr WordWidth = CHAR_BIT*sizeof(WordType);
static unsigned constexpr NumWords = Capacity/WordWidth;
static_assert(NumWords*WordWidth == Capacity,
static unsigned constexpr WordWidth = CHAR_BIT * sizeof(WordType);
static unsigned constexpr NumWords = Capacity / WordWidth;
static_assert(NumWords * WordWidth == Capacity,
"Capacity should be a multiple of WordWidth");
LLVM_ATTRIBUTE_ALWAYS_INLINE
MachineValueTypeSet() {
clear();
}
MachineValueTypeSet() { clear(); }
LLVM_ATTRIBUTE_ALWAYS_INLINE
unsigned size() const {
@@ -76,9 +74,7 @@ struct MachineValueTypeSet {
return Count;
}
LLVM_ATTRIBUTE_ALWAYS_INLINE
void clear() {
std::memset(Words.data(), 0, NumWords*sizeof(WordType));
}
void clear() { std::memset(Words.data(), 0, NumWords * sizeof(WordType)); }
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool empty() const {
for (WordType W : Words)
@@ -90,7 +86,7 @@ struct MachineValueTypeSet {
unsigned count(MVT T) const {
return (Words[T.SimpleTy / WordWidth] >> (T.SimpleTy % WordWidth)) & 1;
}
std::pair<MachineValueTypeSet&,bool> insert(MVT T) {
std::pair<MachineValueTypeSet &, bool> insert(MVT T) {
bool V = count(T.SimpleTy);
Words[T.SimpleTy / WordWidth] |= WordType(1) << (T.SimpleTy % WordWidth);
return {*this, V};
@@ -113,8 +109,8 @@ struct MachineValueTypeSet {
using iterator_category = std::forward_iterator_tag;
using value_type = MVT;
using difference_type = ptrdiff_t;
using pointer = const MVT*;
using reference = const MVT&;
using pointer = const MVT *;
using reference = const MVT &;
LLVM_ATTRIBUTE_ALWAYS_INLINE
MVT operator*() const {
@@ -128,7 +124,7 @@ struct MachineValueTypeSet {
LLVM_ATTRIBUTE_ALWAYS_INLINE
const_iterator &operator++() {
assert(Pos != Capacity);
Pos = find_from_pos(Pos+1);
Pos = find_from_pos(Pos + 1);
return *this;
}
@@ -137,9 +133,7 @@ struct MachineValueTypeSet {
return Set == It.Set && Pos == It.Pos;
}
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool operator!=(const const_iterator &It) const {
return !operator==(It);
}
bool operator!=(const const_iterator &It) const { return !operator==(It); }
private:
unsigned find_from_pos(unsigned P) const {
@@ -151,7 +145,7 @@ struct MachineValueTypeSet {
// the trailing bits need to be masked off to use findFirstSet.
if (SkipBits != 0) {
WordType W = Set->Words[SkipWords];
W &= maskLeadingOnes<WordType>(WordWidth-SkipBits);
W &= maskLeadingOnes<WordType>(WordWidth - SkipBits);
if (W != 0)
return Count + llvm::countr_zero(W);
Count += WordWidth;
@@ -174,20 +168,18 @@ struct MachineValueTypeSet {
LLVM_ATTRIBUTE_ALWAYS_INLINE
const_iterator begin() const { return const_iterator(this, false); }
LLVM_ATTRIBUTE_ALWAYS_INLINE
const_iterator end() const { return const_iterator(this, true); }
const_iterator end() const { return const_iterator(this, true); }
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool operator==(const MachineValueTypeSet &S) const {
return Words == S.Words;
}
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool operator!=(const MachineValueTypeSet &S) const {
return !operator==(S);
}
bool operator!=(const MachineValueTypeSet &S) const { return !operator==(S); }
private:
friend struct const_iterator;
std::array<WordType,NumWords> Words;
std::array<WordType, NumWords> Words;
};
raw_ostream &operator<<(raw_ostream &OS, const MachineValueTypeSet &T);
@@ -200,14 +192,12 @@ struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> {
TypeSetByHwMode(const TypeSetByHwMode &VTS) = default;
TypeSetByHwMode &operator=(const TypeSetByHwMode &) = default;
TypeSetByHwMode(MVT::SimpleValueType VT)
: TypeSetByHwMode(ValueTypeByHwMode(VT)) {}
: TypeSetByHwMode(ValueTypeByHwMode(VT)) {}
TypeSetByHwMode(ValueTypeByHwMode VT)
: TypeSetByHwMode(ArrayRef<ValueTypeByHwMode>(&VT, 1)) {}
: TypeSetByHwMode(ArrayRef<ValueTypeByHwMode>(&VT, 1)) {}
TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList);
SetType &getOrCreate(unsigned Mode) {
return Map[Mode];
}
SetType &getOrCreate(unsigned Mode) { return Map[Mode]; }
bool isValueTypeByHwMode(bool AllowEmpty) const;
ValueTypeByHwMode getValueTypeByHwMode() const;
@@ -225,9 +215,7 @@ struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> {
bool isPossible() const;
bool isPointer() const {
return getValueTypeByHwMode().isPointer();
}
bool isPointer() const { return getValueTypeByHwMode().isPointer(); }
unsigned getPtrAddrSpace() const {
assert(isPointer());
@@ -313,8 +301,7 @@ struct TypeInfer {
/// Ensure that for each type T in \p Sub, T is a vector type, and there
/// exists a type U in \p Vec such that U is a vector type with the same
/// element type as T and at least as many elements as T.
bool EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec,
TypeSetByHwMode &Sub);
bool EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec, TypeSetByHwMode &Sub);
/// 1. Ensure that \p V has a scalar type iff \p W has a scalar type.
/// 2. Ensure that for each vector type T in \p V, there exists a vector
/// type U in \p W, such that T and U have the same number of elements.
@@ -346,15 +333,13 @@ struct TypeInfer {
SuppressValidation(TypeInfer &TI) : Infer(TI), SavedValidate(TI.Validate) {
Infer.Validate = false;
}
~SuppressValidation() {
Infer.Validate = SavedValidate;
}
~SuppressValidation() { Infer.Validate = SavedValidate; }
TypeInfer &Infer;
bool SavedValidate;
};
TreePattern &TP;
bool Validate = true; // Indicate whether to validate types.
bool Validate = true; // Indicate whether to validate types.
private:
const TypeSetByHwMode &getLegalTypes() const;
@@ -372,14 +357,24 @@ typedef StringSet<> MultipleUseVarSet;
struct SDTypeConstraint {
SDTypeConstraint(Record *R, const CodeGenHwModes &CGH);
unsigned OperandNo; // The operand # this constraint applies to.
unsigned OperandNo; // The operand # this constraint applies to.
enum {
SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec,
SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs, SDTCisSameSizeAs
SDTCisVT,
SDTCisPtrTy,
SDTCisInt,
SDTCisFP,
SDTCisVec,
SDTCisSameAs,
SDTCisVTSmallerThanOp,
SDTCisOpSmallerThanOp,
SDTCisEltOfVec,
SDTCisSubVecOfVec,
SDTCVecEltisVT,
SDTCisSameNumEltsAs,
SDTCisSameSizeAs
} ConstraintType;
union { // The discriminated union.
union { // The discriminated union.
struct {
unsigned OtherOperandNum;
} SDTCisSameAs_Info;
@@ -422,6 +417,7 @@ struct SDTypeConstraint {
class ScopedName {
unsigned Scope;
std::string Identifier;
public:
ScopedName(unsigned Scope, StringRef Identifier)
: Scope(Scope), Identifier(std::string(Identifier)) {
@@ -447,6 +443,7 @@ class SDNodeInfo {
unsigned NumResults;
int NumOperands;
std::vector<SDTypeConstraint> TypeConstraints;
public:
// Parse the specified record.
SDNodeInfo(Record *R, const CodeGenHwModes &CGH);
@@ -487,11 +484,11 @@ class TreePredicateFn {
/// PatFragRec - This is the TreePattern for the PatFrag that we
/// originally came from.
TreePattern *PatFragRec;
public:
/// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag.
TreePredicateFn(TreePattern *N);
TreePattern *getOrigPatFragRecord() const { return PatFragRec; }
/// isAlwaysTrue - Return true if this is a noop predicate.
@@ -582,7 +579,8 @@ public:
bool isAtomicOrderingWeakerThanRelease() const;
/// If non-null, indicates that this predicate is a predefined memory VT
/// predicate for a load/store and returns the ValueType record for the memory VT.
/// predicate for a load/store and returns the ValueType record for the memory
/// VT.
Record *getMemoryVT() const;
/// If non-null, indicates that this predicate is a predefined memory VT
/// predicate (checking only the scalar type) for load/store and returns the
@@ -615,14 +613,12 @@ struct TreePredicateCall {
unsigned Scope;
TreePredicateCall(const TreePredicateFn &Fn, unsigned Scope)
: Fn(Fn), Scope(Scope) {}
: Fn(Fn), Scope(Scope) {}
bool operator==(const TreePredicateCall &o) const {
return Fn == o.Fn && Scope == o.Scope;
}
bool operator!=(const TreePredicateCall &o) const {
return !(*this == o);
}
bool operator!=(const TreePredicateCall &o) const { return !(*this == o); }
};
class TreePatternNode : public RefCountedBase<TreePatternNode> {
@@ -681,7 +677,7 @@ public:
const std::vector<ScopedName> &getNamesAsPredicateArg() const {
return NamesAsPredicateArg;
}
void setNamesAsPredicateArg(const std::vector<ScopedName>& Names) {
void setNamesAsPredicateArg(const std::vector<ScopedName> &Names) {
NamesAsPredicateArg = Names;
}
void addNameAsPredicateArg(const ScopedName &N) {
@@ -733,9 +729,7 @@ public:
const TreePatternNodePtr &getChildShared(unsigned N) const {
return Children[N];
}
TreePatternNodePtr &getChildSharedPtr(unsigned N) {
return Children[N];
}
TreePatternNodePtr &getChildSharedPtr(unsigned N) { return Children[N]; }
void setChild(unsigned i, TreePatternNodePtr N) { Children[i] = N; }
/// hasChild - Return true if N is any of our children.
@@ -762,7 +756,8 @@ public:
}
void addPredicateCall(const TreePredicateCall &Call) {
assert(!Call.Fn.isAlwaysTrue() && "Empty predicate string!");
assert(!is_contained(PredicateCalls, Call) && "predicate applied recursively");
assert(!is_contained(PredicateCalls, Call) &&
"predicate applied recursively");
PredicateCalls.push_back(Call);
}
void addPredicateCall(const TreePredicateFn &Fn, unsigned Scope) {
@@ -805,8 +800,7 @@ public:
void print(raw_ostream &OS) const;
void dump() const;
public: // Higher level manipulation routines.
public: // Higher level manipulation routines.
/// clone - Return a new copy of this tree.
///
TreePatternNodePtr clone() const;
@@ -845,8 +839,7 @@ public: // Higher level manipulation routines.
TreePattern &TP);
bool UpdateNodeType(unsigned ResNo, MVT::SimpleValueType InTy,
TreePattern &TP);
bool UpdateNodeType(unsigned ResNo, ValueTypeByHwMode InTy,
TreePattern &TP);
bool UpdateNodeType(unsigned ResNo, ValueTypeByHwMode InTy, TreePattern &TP);
// Update node type with types inferred from an instruction operand or result
// def from the ins/outs lists.
@@ -910,7 +903,6 @@ class TreePattern {
TypeInfer Infer;
public:
/// TreePattern constructor - Parse the specified DagInits into the
/// current record.
TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
@@ -971,12 +963,8 @@ public:
/// error - If this is the first error in the current resolution step,
/// print it and set the error flag. Otherwise, continue silently.
void error(const Twine &Msg);
bool hasError() const {
return HasError;
}
void resetError() {
HasError = false;
}
bool hasError() const { return HasError; }
void resetError() { HasError = false; }
TypeInfer &getInfer() { return Infer; }
@@ -989,7 +977,6 @@ private:
void ComputeNamedNodes(TreePatternNode *N);
};
inline bool TreePatternNode::UpdateNodeType(unsigned ResNo,
const TypeSetByHwMode &InTy,
TreePattern &TP) {
@@ -1014,7 +1001,6 @@ inline bool TreePatternNode::UpdateNodeType(unsigned ResNo,
return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS);
}
/// DAGDefaultOperand - One of these is created for each OperandWithDefaultOps
/// that has a set ExecuteAlways / DefaultOps field.
struct DAGDefaultOperand {
@@ -1022,9 +1008,9 @@ struct DAGDefaultOperand {
};
class DAGInstruction {
std::vector<Record*> Results;
std::vector<Record*> Operands;
std::vector<Record*> ImpResults;
std::vector<Record *> Results;
std::vector<Record *> Operands;
std::vector<Record *> ImpResults;
TreePatternNodePtr SrcPattern;
TreePatternNodePtr ResultPattern;
@@ -1041,7 +1027,7 @@ public:
unsigned getNumResults() const { return Results.size(); }
unsigned getNumOperands() const { return Operands.size(); }
unsigned getNumImpResults() const { return ImpResults.size(); }
const std::vector<Record*>& getImpResults() const { return ImpResults; }
const std::vector<Record *> &getImpResults() const { return ImpResults; }
Record *getResult(unsigned RN) const {
assert(RN < Results.size());
@@ -1065,34 +1051,33 @@ public:
/// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns
/// processed to produce isel.
class PatternToMatch {
Record *SrcRecord; // Originating Record for the pattern.
ListInit *Predicates; // Top level predicate conditions to match.
TreePatternNodePtr SrcPattern; // Source pattern to match.
TreePatternNodePtr DstPattern; // Resulting pattern.
std::vector<Record*> Dstregs; // Physical register defs being matched.
std::string HwModeFeatures;
int AddedComplexity; // Add to matching pattern complexity.
unsigned ID; // Unique ID for the record.
Record *SrcRecord; // Originating Record for the pattern.
ListInit *Predicates; // Top level predicate conditions to match.
TreePatternNodePtr SrcPattern; // Source pattern to match.
TreePatternNodePtr DstPattern; // Resulting pattern.
std::vector<Record *> Dstregs; // Physical register defs being matched.
std::string HwModeFeatures;
int AddedComplexity; // Add to matching pattern complexity.
unsigned ID; // Unique ID for the record.
public:
PatternToMatch(Record *srcrecord, ListInit *preds, TreePatternNodePtr src,
TreePatternNodePtr dst, std::vector<Record *> dstregs,
int complexity, unsigned uid,
const Twine &hwmodefeatures = "")
int complexity, unsigned uid, const Twine &hwmodefeatures = "")
: SrcRecord(srcrecord), Predicates(preds), SrcPattern(src),
DstPattern(dst), Dstregs(std::move(dstregs)),
HwModeFeatures(hwmodefeatures.str()), AddedComplexity(complexity),
ID(uid) {}
Record *getSrcRecord() const { return SrcRecord; }
ListInit *getPredicates() const { return Predicates; }
Record *getSrcRecord() const { return SrcRecord; }
ListInit *getPredicates() const { return Predicates; }
TreePatternNode *getSrcPattern() const { return SrcPattern.get(); }
TreePatternNodePtr getSrcPatternShared() const { return SrcPattern; }
TreePatternNode *getDstPattern() const { return DstPattern.get(); }
TreePatternNodePtr getDstPatternShared() const { return DstPattern; }
const std::vector<Record*> &getDstRegs() const { return Dstregs; }
StringRef getHwModeFeatures() const { return HwModeFeatures; }
int getAddedComplexity() const { return AddedComplexity; }
const std::vector<Record *> &getDstRegs() const { return Dstregs; }
StringRef getHwModeFeatures() const { return HwModeFeatures; }
int getAddedComplexity() const { return AddedComplexity; }
unsigned getID() const { return ID; }
std::string getPredicateCheck() const;
@@ -1108,14 +1093,14 @@ class CodeGenDAGPatterns {
CodeGenTarget Target;
CodeGenIntrinsicTable Intrinsics;
std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes;
std::map<Record*, std::pair<Record*, std::string>, LessRecordByID>
std::map<Record *, SDNodeInfo, LessRecordByID> SDNodes;
std::map<Record *, std::pair<Record *, std::string>, LessRecordByID>
SDNodeXForms;
std::map<Record*, ComplexPattern, LessRecordByID> ComplexPatterns;
std::map<Record *, ComplexPattern, LessRecordByID> ComplexPatterns;
std::map<Record *, std::unique_ptr<TreePattern>, LessRecordByID>
PatternFragments;
std::map<Record*, DAGDefaultOperand, LessRecordByID> DefaultOperands;
std::map<Record*, DAGInstruction, LessRecordByID> Instructions;
std::map<Record *, DAGDefaultOperand, LessRecordByID> DefaultOperands;
std::map<Record *, DAGInstruction, LessRecordByID> Instructions;
// Specific SDNode definitions:
Record *intrinsic_void_sdnode;
@@ -1128,7 +1113,7 @@ class CodeGenDAGPatterns {
TypeSetByHwMode LegalVTS;
using PatternRewriterFn = std::function<void (TreePattern *)>;
using PatternRewriterFn = std::function<void(TreePattern *)>;
PatternRewriterFn PatternRewriter;
unsigned NumScopes = 0;
@@ -1150,7 +1135,7 @@ public:
}
// Node transformation lookups.
typedef std::pair<Record*, std::string> NodeXForm;
typedef std::pair<Record *, std::string> NodeXForm;
const NodeXForm &getSDNodeTransform(Record *R) const {
auto F = SDNodeXForms.find(R);
assert(F != SDNodeXForms.end() && "Invalid transform!");
@@ -1165,25 +1150,27 @@ public:
const CodeGenIntrinsic &getIntrinsic(Record *R) const {
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
if (Intrinsics[i].TheDef == R) return Intrinsics[i];
if (Intrinsics[i].TheDef == R)
return Intrinsics[i];
llvm_unreachable("Unknown intrinsic!");
}
const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const {
if (IID-1 < Intrinsics.size())
return Intrinsics[IID-1];
if (IID - 1 < Intrinsics.size())
return Intrinsics[IID - 1];
llvm_unreachable("Bad intrinsic ID!");
}
unsigned getIntrinsicID(Record *R) const {
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
if (Intrinsics[i].TheDef == R) return i;
if (Intrinsics[i].TheDef == R)
return i;
llvm_unreachable("Unknown intrinsic!");
}
const DAGDefaultOperand &getDefaultOperand(Record *R) const {
auto F = DefaultOperands.find(R);
assert(F != DefaultOperands.end() &&"Isn't an analyzed default operand!");
assert(F != DefaultOperands.end() && "Isn't an analyzed default operand!");
return F->second;
}
@@ -1213,10 +1200,9 @@ public:
iterator_range<ptm_iterator> ptms() const { return PatternsToMatch; }
/// Parse the Pattern for an instruction, and insert the result in DAGInsts.
typedef std::map<Record*, DAGInstruction, LessRecordByID> DAGInstMap;
void parseInstructionPattern(
CodeGenInstruction &CGI, ListInit *Pattern,
DAGInstMap &DAGInsts);
typedef std::map<Record *, DAGInstruction, LessRecordByID> DAGInstMap;
void parseInstructionPattern(CodeGenInstruction &CGI, ListInit *Pattern,
DAGInstMap &DAGInsts);
const DAGInstruction &getInstruction(Record *R) const {
auto F = Instructions.find(R);
@@ -1224,9 +1210,7 @@ public:
return F->second;
}
Record *get_intrinsic_void_sdnode() const {
return intrinsic_void_sdnode;
}
Record *get_intrinsic_void_sdnode() const { return intrinsic_void_sdnode; }
Record *get_intrinsic_w_chain_sdnode() const {
return intrinsic_w_chain_sdnode;
}
@@ -1238,7 +1222,7 @@ public:
bool operandHasDefault(Record *Op) const {
return Op->isSubClassOf("OperandWithDefaultOps") &&
!getDefaultOperand(Op).DefaultOps.empty();
!getDefaultOperand(Op).DefaultOps.empty();
}
private:
@@ -1254,8 +1238,8 @@ private:
void GenerateVariants();
void VerifyInstructionFlags();
void ParseOnePattern(Record *TheDef,
TreePattern &Pattern, TreePattern &Result,
void ParseOnePattern(Record *TheDef, TreePattern &Pattern,
TreePattern &Result,
const std::vector<Record *> &InstImpResults);
void AddPatternToMatch(TreePattern *Pattern, PatternToMatch &&PTM);
void FindPatternInputsAndOutputs(
@@ -1266,14 +1250,13 @@ private:
std::vector<Record *> &InstImpResults);
};
inline bool SDNodeInfo::ApplyTypeConstraints(TreePatternNode *N,
TreePattern &TP) const {
bool MadeChange = false;
for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i)
MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP);
return MadeChange;
}
bool MadeChange = false;
for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i)
MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP);
return MadeChange;
}
} // end namespace llvm

View File

@@ -37,17 +37,17 @@ HwMode::HwMode(Record *R) {
}
LLVM_DUMP_METHOD
void HwMode::dump() const {
dbgs() << Name << ": " << Features << '\n';
}
void HwMode::dump() const { dbgs() << Name << ": " << Features << '\n'; }
HwModeSelect::HwModeSelect(Record *R, CodeGenHwModes &CGH) {
std::vector<Record*> Modes = R->getValueAsListOfDefs("Modes");
std::vector<Record*> Objects = R->getValueAsListOfDefs("Objects");
std::vector<Record *> Modes = R->getValueAsListOfDefs("Modes");
std::vector<Record *> Objects = R->getValueAsListOfDefs("Objects");
if (Modes.size() != Objects.size()) {
PrintError(R->getLoc(), "in record " + R->getName() +
" derived from HwModeSelect: the lists Modes and Objects should "
"have the same size");
PrintError(
R->getLoc(),
"in record " + R->getName() +
" derived from HwModeSelect: the lists Modes and Objects should "
"have the same size");
report_fatal_error("error in target description.");
}
for (unsigned i = 0, e = Modes.size(); i != e; ++i) {

View File

@@ -22,46 +22,46 @@
// HwModeId -> list of predicates (definition)
namespace llvm {
class Record;
class RecordKeeper;
class Record;
class RecordKeeper;
struct CodeGenHwModes;
struct CodeGenHwModes;
struct HwMode {
HwMode(Record *R);
StringRef Name;
std::string Features;
std::string Predicates;
void dump() const;
};
struct HwMode {
HwMode(Record *R);
StringRef Name;
std::string Features;
std::string Predicates;
void dump() const;
};
struct HwModeSelect {
HwModeSelect(Record *R, CodeGenHwModes &CGH);
typedef std::pair<unsigned, Record*> PairType;
std::vector<PairType> Items;
void dump() const;
};
struct HwModeSelect {
HwModeSelect(Record *R, CodeGenHwModes &CGH);
typedef std::pair<unsigned, Record *> PairType;
std::vector<PairType> Items;
void dump() const;
};
struct CodeGenHwModes {
enum : unsigned { DefaultMode = 0 };
static StringRef DefaultModeName;
struct CodeGenHwModes {
enum : unsigned { DefaultMode = 0 };
static StringRef DefaultModeName;
CodeGenHwModes(RecordKeeper &R);
unsigned getHwModeId(Record *R) const;
const HwMode &getMode(unsigned Id) const {
assert(Id != 0 && "Mode id of 0 is reserved for the default mode");
return Modes[Id-1];
}
const HwModeSelect &getHwModeSelect(Record *R) const;
unsigned getNumModeIds() const { return Modes.size()+1; }
void dump() const;
CodeGenHwModes(RecordKeeper &R);
unsigned getHwModeId(Record *R) const;
const HwMode &getMode(unsigned Id) const {
assert(Id != 0 && "Mode id of 0 is reserved for the default mode");
return Modes[Id - 1];
}
const HwModeSelect &getHwModeSelect(Record *R) const;
unsigned getNumModeIds() const { return Modes.size() + 1; }
void dump() const;
private:
RecordKeeper &Records;
DenseMap<Record *, unsigned> ModeIds; // HwMode Record -> HwModeId
std::vector<HwMode> Modes;
std::map<Record*,HwModeSelect> ModeSelects;
};
}
private:
RecordKeeper &Records;
DenseMap<Record *, unsigned> ModeIds; // HwMode Record -> HwModeId
std::vector<HwMode> Modes;
std::map<Record *, HwModeSelect> ModeSelects;
};
} // namespace llvm
#endif // LLVM_UTILS_TABLEGEN_CODEGENHWMODES_H

View File

@@ -55,15 +55,15 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
unsigned e = InDI->getNumArgs() + OutDI->getNumArgs();
OperandList.reserve(e);
bool VariadicOuts = false;
for (unsigned i = 0; i != e; ++i){
for (unsigned i = 0; i != e; ++i) {
Init *ArgInit;
StringRef ArgName;
if (i < NumDefs) {
ArgInit = OutDI->getArg(i);
ArgName = OutDI->getArgNameStr(i);
} else {
ArgInit = InDI->getArg(i-NumDefs);
ArgName = InDI->getArgNameStr(i-NumDefs);
ArgInit = InDI->getArg(i - NumDefs);
ArgName = InDI->getArgNameStr(i - NumDefs);
}
DagInit *SubArgDag = dyn_cast<DagInit>(ArgInit);
@@ -192,7 +192,6 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
--NumDefs;
}
/// getOperandNamed - Return the index of the operand with the specified
/// non-empty name. If the instruction does not have an operand with the
/// specified name, abort.
@@ -230,7 +229,7 @@ bool CGIOperandList::hasSubOperandAlias(
return false;
}
std::pair<unsigned,unsigned>
std::pair<unsigned, unsigned>
CGIOperandList::ParseOperandName(StringRef Op, bool AllowWholeOp) {
if (!Op.starts_with("$"))
PrintFatalError(TheDef->getLoc(),
@@ -242,7 +241,7 @@ CGIOperandList::ParseOperandName(StringRef Op, bool AllowWholeOp) {
// Check to see if this is $foo.bar.
StringRef::size_type DotIdx = OpName.find_first_of('.');
if (DotIdx != StringRef::npos) {
SubOpName = OpName.substr(DotIdx+1);
SubOpName = OpName.substr(DotIdx + 1);
if (SubOpName.empty())
PrintFatalError(TheDef->getLoc(),
TheDef->getName() +
@@ -266,7 +265,7 @@ CGIOperandList::ParseOperandName(StringRef Op, bool AllowWholeOp) {
OpIdx = getOperandNamed(OpName);
if (SubOpName.empty()) { // If no suboperand name was specified:
if (SubOpName.empty()) { // If no suboperand name was specified:
// If one was needed, throw.
if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
SubOpName.empty())
@@ -299,82 +298,80 @@ CGIOperandList::ParseOperandName(StringRef Op, bool AllowWholeOp) {
return std::make_pair(0U, 0U);
}
static void ParseConstraint(StringRef CStr, CGIOperandList &Ops,
Record *Rec) {
static void ParseConstraint(StringRef CStr, CGIOperandList &Ops, Record *Rec) {
// EARLY_CLOBBER: @early $reg
StringRef::size_type wpos = CStr.find_first_of(" \t");
StringRef::size_type start = CStr.find_first_not_of(" \t");
StringRef Tok = CStr.substr(start, wpos - start);
if (Tok == "@earlyclobber") {
StringRef Name = CStr.substr(wpos+1);
StringRef Name = CStr.substr(wpos + 1);
wpos = Name.find_first_not_of(" \t");
if (wpos == StringRef::npos)
PrintFatalError(
Rec->getLoc(), "Illegal format for @earlyclobber constraint in '" +
Rec->getName() + "': '" + CStr + "'");
PrintFatalError(Rec->getLoc(),
"Illegal format for @earlyclobber constraint in '" +
Rec->getName() + "': '" + CStr + "'");
Name = Name.substr(wpos);
std::pair<unsigned,unsigned> Op = Ops.ParseOperandName(Name, false);
std::pair<unsigned, unsigned> Op = Ops.ParseOperandName(Name, false);
// Build the string for the operand
if (!Ops[Op.first].Constraints[Op.second].isNone())
PrintFatalError(
Rec->getLoc(), "Operand '" + Name + "' of '" + Rec->getName() +
"' cannot have multiple constraints!");
PrintFatalError(Rec->getLoc(), "Operand '" + Name + "' of '" +
Rec->getName() +
"' cannot have multiple constraints!");
Ops[Op.first].Constraints[Op.second] =
CGIOperandList::ConstraintInfo::getEarlyClobber();
CGIOperandList::ConstraintInfo::getEarlyClobber();
return;
}
// Only other constraint is "TIED_TO" for now.
StringRef::size_type pos = CStr.find_first_of('=');
if (pos == StringRef::npos)
PrintFatalError(
Rec->getLoc(), "Unrecognized constraint '" + CStr +
"' in '" + Rec->getName() + "'");
PrintFatalError(Rec->getLoc(), "Unrecognized constraint '" + CStr +
"' in '" + Rec->getName() + "'");
start = CStr.find_first_not_of(" \t");
// TIED_TO: $src1 = $dst
wpos = CStr.find_first_of(" \t", start);
if (wpos == StringRef::npos || wpos > pos)
PrintFatalError(
Rec->getLoc(), "Illegal format for tied-to constraint in '" +
Rec->getName() + "': '" + CStr + "'");
PrintFatalError(Rec->getLoc(),
"Illegal format for tied-to constraint in '" +
Rec->getName() + "': '" + CStr + "'");
StringRef LHSOpName = CStr.substr(start, wpos - start);
std::pair<unsigned,unsigned> LHSOp = Ops.ParseOperandName(LHSOpName, false);
std::pair<unsigned, unsigned> LHSOp = Ops.ParseOperandName(LHSOpName, false);
wpos = CStr.find_first_not_of(" \t", pos + 1);
if (wpos == StringRef::npos)
PrintFatalError(
Rec->getLoc(), "Illegal format for tied-to constraint: '" + CStr + "'");
PrintFatalError(Rec->getLoc(),
"Illegal format for tied-to constraint: '" + CStr + "'");
StringRef RHSOpName = CStr.substr(wpos);
std::pair<unsigned,unsigned> RHSOp = Ops.ParseOperandName(RHSOpName, false);
std::pair<unsigned, unsigned> RHSOp = Ops.ParseOperandName(RHSOpName, false);
// Sort the operands into order, which should put the output one
// first. But keep the original order, for use in diagnostics.
bool FirstIsDest = (LHSOp < RHSOp);
std::pair<unsigned,unsigned> DestOp = (FirstIsDest ? LHSOp : RHSOp);
std::pair<unsigned, unsigned> DestOp = (FirstIsDest ? LHSOp : RHSOp);
StringRef DestOpName = (FirstIsDest ? LHSOpName : RHSOpName);
std::pair<unsigned,unsigned> SrcOp = (FirstIsDest ? RHSOp : LHSOp);
std::pair<unsigned, unsigned> SrcOp = (FirstIsDest ? RHSOp : LHSOp);
StringRef SrcOpName = (FirstIsDest ? RHSOpName : LHSOpName);
// Ensure one operand is a def and the other is a use.
if (DestOp.first >= Ops.NumDefs)
PrintFatalError(
Rec->getLoc(), "Input operands '" + LHSOpName + "' and '" + RHSOpName +
"' of '" + Rec->getName() + "' cannot be tied!");
PrintFatalError(Rec->getLoc(), "Input operands '" + LHSOpName + "' and '" +
RHSOpName + "' of '" + Rec->getName() +
"' cannot be tied!");
if (SrcOp.first < Ops.NumDefs)
PrintFatalError(
Rec->getLoc(), "Output operands '" + LHSOpName + "' and '" + RHSOpName +
"' of '" + Rec->getName() + "' cannot be tied!");
PrintFatalError(Rec->getLoc(), "Output operands '" + LHSOpName + "' and '" +
RHSOpName + "' of '" + Rec->getName() +
"' cannot be tied!");
// The constraint has to go on the operand with higher index, i.e.
// the source one. Check there isn't another constraint there
// already.
if (!Ops[SrcOp.first].Constraints[SrcOp.second].isNone())
PrintFatalError(
Rec->getLoc(), "Operand '" + SrcOpName + "' of '" + Rec->getName() +
"' cannot have multiple constraints!");
PrintFatalError(Rec->getLoc(), "Operand '" + SrcOpName + "' of '" +
Rec->getName() +
"' cannot have multiple constraints!");
unsigned DestFlatOpNo = Ops.getFlattenedOperandNumber(DestOp);
auto NewConstraint = CGIOperandList::ConstraintInfo::getTied(DestFlatOpNo);
@@ -384,16 +381,17 @@ static void ParseConstraint(StringRef CStr, CGIOperandList &Ops,
for (const CGIOperandList::OperandInfo &Op : Ops) {
for (unsigned i = 0; i < Op.MINumOperands; i++)
if (Op.Constraints[i] == NewConstraint)
PrintFatalError(
Rec->getLoc(), "Operand '" + DestOpName + "' of '" + Rec->getName() +
"' cannot have multiple operands tied to it!");
PrintFatalError(Rec->getLoc(),
"Operand '" + DestOpName + "' of '" + Rec->getName() +
"' cannot have multiple operands tied to it!");
}
Ops[SrcOp.first].Constraints[SrcOp.second] = NewConstraint;
}
static void ParseConstraints(StringRef CStr, CGIOperandList &Ops, Record *Rec) {
if (CStr.empty()) return;
if (CStr.empty())
return;
StringRef delims(",");
StringRef::size_type bidx, eidx;
@@ -413,15 +411,15 @@ void CGIOperandList::ProcessDisableEncoding(StringRef DisableEncoding) {
while (true) {
StringRef OpName;
std::tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t");
if (OpName.empty()) break;
if (OpName.empty())
break;
// Figure out which operand this is.
std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false);
std::pair<unsigned, unsigned> Op = ParseOperandName(OpName, false);
// Mark the operand as not-to-be encoded.
OperandList[Op.first].DoNotEncode[Op.second] = true;
}
}
//===----------------------------------------------------------------------===//
@@ -429,27 +427,27 @@ void CGIOperandList::ProcessDisableEncoding(StringRef DisableEncoding) {
//===----------------------------------------------------------------------===//
CodeGenInstruction::CodeGenInstruction(Record *R)
: TheDef(R), Operands(R), InferredFrom(nullptr) {
: TheDef(R), Operands(R), InferredFrom(nullptr) {
Namespace = R->getValueAsString("Namespace");
AsmString = std::string(R->getValueAsString("AsmString"));
isPreISelOpcode = R->getValueAsBit("isPreISelOpcode");
isReturn = R->getValueAsBit("isReturn");
isReturn = R->getValueAsBit("isReturn");
isEHScopeReturn = R->getValueAsBit("isEHScopeReturn");
isBranch = R->getValueAsBit("isBranch");
isBranch = R->getValueAsBit("isBranch");
isIndirectBranch = R->getValueAsBit("isIndirectBranch");
isCompare = R->getValueAsBit("isCompare");
isMoveImm = R->getValueAsBit("isMoveImm");
isMoveReg = R->getValueAsBit("isMoveReg");
isBitcast = R->getValueAsBit("isBitcast");
isSelect = R->getValueAsBit("isSelect");
isBarrier = R->getValueAsBit("isBarrier");
isCall = R->getValueAsBit("isCall");
isAdd = R->getValueAsBit("isAdd");
isTrap = R->getValueAsBit("isTrap");
isCompare = R->getValueAsBit("isCompare");
isMoveImm = R->getValueAsBit("isMoveImm");
isMoveReg = R->getValueAsBit("isMoveReg");
isBitcast = R->getValueAsBit("isBitcast");
isSelect = R->getValueAsBit("isSelect");
isBarrier = R->getValueAsBit("isBarrier");
isCall = R->getValueAsBit("isCall");
isAdd = R->getValueAsBit("isAdd");
isTrap = R->getValueAsBit("isTrap");
canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
isPredicable = !R->getValueAsBit("isUnpredicable") && (
Operands.isPredicable || R->getValueAsBit("isPredicable"));
isPredicable = !R->getValueAsBit("isUnpredicable") &&
(Operands.isPredicable || R->getValueAsBit("isPredicable"));
isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
isCommutable = R->getValueAsBit("isCommutable");
isTerminator = R->getValueAsBit("isTerminator");
@@ -457,7 +455,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
hasDelaySlot = R->getValueAsBit("hasDelaySlot");
usesCustomInserter = R->getValueAsBit("usesCustomInserter");
hasPostISelHook = R->getValueAsBit("hasPostISelHook");
hasCtrlDep = R->getValueAsBit("hasCtrlDep");
hasCtrlDep = R->getValueAsBit("hasCtrlDep");
isNotDuplicable = R->getValueAsBit("isNotDuplicable");
isRegSequence = R->getValueAsBit("isRegSequence");
isExtractSubreg = R->getValueAsBit("isExtractSubreg");
@@ -469,9 +467,9 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
isAuthenticated = R->getValueAsBit("isAuthenticated");
bool Unset;
mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);
mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);
mayLoad_Unset = Unset;
mayStore = R->getValueAsBitOrUnset("mayStore", Unset);
mayStore = R->getValueAsBitOrUnset("mayStore", Unset);
mayStore_Unset = Unset;
mayRaiseFPException = R->getValueAsBit("mayRaiseFPException");
hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset);
@@ -494,8 +492,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
ParseConstraints(R->getValueAsString("Constraints"), Operands, R);
// Parse the DisableEncoding field.
Operands.ProcessDisableEncoding(
R->getValueAsString("DisableEncoding"));
Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding"));
// First check for a ComplexDeprecationPredicate.
if (R->getValue("ComplexDeprecationPredicate")) {
@@ -516,25 +513,25 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
/// implicit def and it has a known VT, return the VT, otherwise return
/// MVT::Other.
MVT::SimpleValueType CodeGenInstruction::
HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const {
if (ImplicitDefs.empty()) return MVT::Other;
MVT::SimpleValueType CodeGenInstruction::HasOneImplicitDefWithKnownVT(
const CodeGenTarget &TargetInfo) const {
if (ImplicitDefs.empty())
return MVT::Other;
// Check to see if the first implicit def has a resolvable type.
Record *FirstImplicitDef = ImplicitDefs[0];
assert(FirstImplicitDef->isSubClassOf("Register"));
const std::vector<ValueTypeByHwMode> &RegVTs =
TargetInfo.getRegisterVTs(FirstImplicitDef);
TargetInfo.getRegisterVTs(FirstImplicitDef);
if (RegVTs.size() == 1 && RegVTs[0].isSimple())
return RegVTs[0].getSimple().SimpleTy;
return MVT::Other;
}
/// FlattenAsmStringVariants - Flatten the specified AsmString to only
/// include text from the specified variant, returning the new string.
std::string CodeGenInstruction::
FlattenAsmStringVariants(StringRef Cur, unsigned Variant) {
std::string CodeGenInstruction::FlattenAsmStringVariants(StringRef Cur,
unsigned Variant) {
std::string Res;
for (;;) {
@@ -542,8 +539,8 @@ FlattenAsmStringVariants(StringRef Cur, unsigned Variant) {
size_t VariantsStart = 0;
for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart)
if (Cur[VariantsStart] == '{' &&
(VariantsStart == 0 || (Cur[VariantsStart-1] != '$' &&
Cur[VariantsStart-1] != '\\')))
(VariantsStart == 0 ||
(Cur[VariantsStart - 1] != '$' && Cur[VariantsStart - 1] != '\\')))
break;
// Add the prefix to the result.
@@ -557,7 +554,7 @@ FlattenAsmStringVariants(StringRef Cur, unsigned Variant) {
size_t VariantsEnd = VariantsStart;
unsigned NestedBraces = 1;
for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) {
if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') {
if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd - 1] != '\\') {
if (--NestedBraces == 0)
break;
} else if (Cur[VariantsEnd] == '{')

View File

@@ -23,324 +23,320 @@
#include <vector>
namespace llvm {
class Record;
class DagInit;
class CodeGenTarget;
class Record;
class DagInit;
class CodeGenTarget;
class CGIOperandList {
public:
class ConstraintInfo {
enum { None, EarlyClobber, Tied } Kind = None;
unsigned OtherTiedOperand = 0;
class CGIOperandList {
public:
class ConstraintInfo {
enum { None, EarlyClobber, Tied } Kind = None;
unsigned OtherTiedOperand = 0;
ConstraintInfo() = default;
public:
ConstraintInfo() = default;
static ConstraintInfo getEarlyClobber() {
ConstraintInfo I;
I.Kind = EarlyClobber;
I.OtherTiedOperand = 0;
return I;
}
static ConstraintInfo getEarlyClobber() {
ConstraintInfo I;
I.Kind = EarlyClobber;
I.OtherTiedOperand = 0;
return I;
}
static ConstraintInfo getTied(unsigned Op) {
ConstraintInfo I;
I.Kind = Tied;
I.OtherTiedOperand = Op;
return I;
}
static ConstraintInfo getTied(unsigned Op) {
ConstraintInfo I;
I.Kind = Tied;
I.OtherTiedOperand = Op;
return I;
}
bool isNone() const { return Kind == None; }
bool isEarlyClobber() const { return Kind == EarlyClobber; }
bool isTied() const { return Kind == Tied; }
bool isNone() const { return Kind == None; }
bool isEarlyClobber() const { return Kind == EarlyClobber; }
bool isTied() const { return Kind == Tied; }
unsigned getTiedOperand() const {
assert(isTied());
return OtherTiedOperand;
}
unsigned getTiedOperand() const {
assert(isTied());
return OtherTiedOperand;
}
bool operator==(const ConstraintInfo &RHS) const {
if (Kind != RHS.Kind)
return false;
if (Kind == Tied && OtherTiedOperand != RHS.OtherTiedOperand)
return false;
return true;
}
bool operator!=(const ConstraintInfo &RHS) const { return !(*this == RHS); }
};
bool operator==(const ConstraintInfo &RHS) const {
if (Kind != RHS.Kind)
return false;
if (Kind == Tied && OtherTiedOperand != RHS.OtherTiedOperand)
return false;
return true;
}
bool operator!=(const ConstraintInfo &RHS) const {
return !(*this == RHS);
}
};
/// OperandInfo - The information we keep track of for each operand in the
/// operand list for a tablegen instruction.
struct OperandInfo {
/// Rec - The definition this operand is declared as.
///
Record *Rec;
/// Name - If this operand was assigned a symbolic name, this is it,
/// otherwise, it's empty.
std::string Name;
/// The names of sub-operands, if given, otherwise empty.
std::vector<std::string> SubOpNames;
/// PrinterMethodName - The method used to print operands of this type in
/// the asmprinter.
std::string PrinterMethodName;
/// The method used to get the machine operand value for binary
/// encoding, per sub-operand. If empty, uses "getMachineOpValue".
std::vector<std::string> EncoderMethodNames;
/// OperandType - A value from MCOI::OperandType representing the type of
/// the operand.
std::string OperandType;
/// MIOperandNo - Currently (this is meant to be phased out), some logical
/// operands correspond to multiple MachineInstr operands. In the X86
/// target for example, one address operand is represented as 4
/// MachineOperands. Because of this, the operand number in the
/// OperandList may not match the MachineInstr operand num. Until it
/// does, this contains the MI operand index of this operand.
unsigned MIOperandNo;
unsigned MINumOperands; // The number of operands.
/// DoNotEncode - Bools are set to true in this vector for each operand in
/// the DisableEncoding list. These should not be emitted by the code
/// emitter.
BitVector DoNotEncode;
/// MIOperandInfo - Default MI operand type. Note an operand may be made
/// up of multiple MI operands.
DagInit *MIOperandInfo;
/// Constraint info for this operand. This operand can have pieces, so we
/// track constraint info for each.
std::vector<ConstraintInfo> Constraints;
OperandInfo(Record *R, const std::string &N, const std::string &PMN,
const std::string &OT, unsigned MION, unsigned MINO,
DagInit *MIOI)
: Rec(R), Name(N), SubOpNames(MINO), PrinterMethodName(PMN),
EncoderMethodNames(MINO), OperandType(OT), MIOperandNo(MION),
MINumOperands(MINO), DoNotEncode(MINO), MIOperandInfo(MIOI),
Constraints(MINO) {}
/// getTiedOperand - If this operand is tied to another one, return the
/// other operand number. Otherwise, return -1.
int getTiedRegister() const {
for (unsigned j = 0, e = Constraints.size(); j != e; ++j) {
const CGIOperandList::ConstraintInfo &CI = Constraints[j];
if (CI.isTied()) return CI.getTiedOperand();
}
return -1;
}
};
CGIOperandList(Record *D);
Record *TheDef; // The actual record containing this OperandList.
/// NumDefs - Number of def operands declared, this is the number of
/// elements in the instruction's (outs) list.
/// OperandInfo - The information we keep track of for each operand in the
/// operand list for a tablegen instruction.
struct OperandInfo {
/// Rec - The definition this operand is declared as.
///
unsigned NumDefs;
Record *Rec;
/// OperandList - The list of declared operands, along with their declared
/// type (which is a record).
std::vector<OperandInfo> OperandList;
/// Name - If this operand was assigned a symbolic name, this is it,
/// otherwise, it's empty.
std::string Name;
/// SubOpAliases - List of alias names for suboperands.
StringMap<std::pair<unsigned, unsigned>> SubOpAliases;
/// The names of sub-operands, if given, otherwise empty.
std::vector<std::string> SubOpNames;
// Information gleaned from the operand list.
bool isPredicable;
bool hasOptionalDef;
bool isVariadic;
/// PrinterMethodName - The method used to print operands of this type in
/// the asmprinter.
std::string PrinterMethodName;
// Provide transparent accessors to the operand list.
bool empty() const { return OperandList.empty(); }
unsigned size() const { return OperandList.size(); }
const OperandInfo &operator[](unsigned i) const { return OperandList[i]; }
OperandInfo &operator[](unsigned i) { return OperandList[i]; }
OperandInfo &back() { return OperandList.back(); }
const OperandInfo &back() const { return OperandList.back(); }
/// The method used to get the machine operand value for binary
/// encoding, per sub-operand. If empty, uses "getMachineOpValue".
std::vector<std::string> EncoderMethodNames;
typedef std::vector<OperandInfo>::iterator iterator;
typedef std::vector<OperandInfo>::const_iterator const_iterator;
iterator begin() { return OperandList.begin(); }
const_iterator begin() const { return OperandList.begin(); }
iterator end() { return OperandList.end(); }
const_iterator end() const { return OperandList.end(); }
/// OperandType - A value from MCOI::OperandType representing the type of
/// the operand.
std::string OperandType;
/// getOperandNamed - Return the index of the operand with the specified
/// non-empty name. If the instruction does not have an operand with the
/// specified name, abort.
unsigned getOperandNamed(StringRef Name) const;
/// MIOperandNo - Currently (this is meant to be phased out), some logical
/// operands correspond to multiple MachineInstr operands. In the X86
/// target for example, one address operand is represented as 4
/// MachineOperands. Because of this, the operand number in the
/// OperandList may not match the MachineInstr operand num. Until it
/// does, this contains the MI operand index of this operand.
unsigned MIOperandNo;
unsigned MINumOperands; // The number of operands.
/// hasOperandNamed - Query whether the instruction has an operand of the
/// given name. If so, return true and set OpIdx to the index of the
/// operand. Otherwise, return false.
bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const;
/// DoNotEncode - Bools are set to true in this vector for each operand in
/// the DisableEncoding list. These should not be emitted by the code
/// emitter.
BitVector DoNotEncode;
bool hasSubOperandAlias(StringRef Name,
std::pair<unsigned, unsigned> &SubOp) const;
/// MIOperandInfo - Default MI operand type. Note an operand may be made
/// up of multiple MI operands.
DagInit *MIOperandInfo;
/// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
/// where $foo is a whole operand and $foo.bar refers to a suboperand.
/// This aborts if the name is invalid. If AllowWholeOp is true, references
/// to operands with suboperands are allowed, otherwise not.
std::pair<unsigned,unsigned> ParseOperandName(StringRef Op,
bool AllowWholeOp = true);
/// Constraint info for this operand. This operand can have pieces, so we
/// track constraint info for each.
std::vector<ConstraintInfo> Constraints;
/// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
/// flat machineinstr operand #.
unsigned getFlattenedOperandNumber(std::pair<unsigned,unsigned> Op) const {
return OperandList[Op.first].MIOperandNo + Op.second;
}
OperandInfo(Record *R, const std::string &N, const std::string &PMN,
const std::string &OT, unsigned MION, unsigned MINO,
DagInit *MIOI)
: Rec(R), Name(N), SubOpNames(MINO), PrinterMethodName(PMN),
EncoderMethodNames(MINO), OperandType(OT), MIOperandNo(MION),
MINumOperands(MINO), DoNotEncode(MINO), MIOperandInfo(MIOI),
Constraints(MINO) {}
/// getSubOperandNumber - Unflatten a operand number into an
/// operand/suboperand pair.
std::pair<unsigned,unsigned> getSubOperandNumber(unsigned Op) const {
for (unsigned i = 0; ; ++i) {
assert(i < OperandList.size() && "Invalid flat operand #");
if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op)
return std::make_pair(i, Op-OperandList[i].MIOperandNo);
/// getTiedOperand - If this operand is tied to another one, return the
/// other operand number. Otherwise, return -1.
int getTiedRegister() const {
for (unsigned j = 0, e = Constraints.size(); j != e; ++j) {
const CGIOperandList::ConstraintInfo &CI = Constraints[j];
if (CI.isTied())
return CI.getTiedOperand();
}
return -1;
}
/// isFlatOperandNotEmitted - Return true if the specified flat operand #
/// should not be emitted with the code emitter.
bool isFlatOperandNotEmitted(unsigned FlatOpNo) const {
std::pair<unsigned,unsigned> Op = getSubOperandNumber(FlatOpNo);
if (OperandList[Op.first].DoNotEncode.size() > Op.second)
return OperandList[Op.first].DoNotEncode[Op.second];
return false;
}
void ProcessDisableEncoding(StringRef Value);
};
CGIOperandList(Record *D);
class CodeGenInstruction {
public:
Record *TheDef; // The actual record defining this instruction.
StringRef Namespace; // The namespace the instruction is in.
Record *TheDef; // The actual record containing this OperandList.
/// AsmString - The format string used to emit a .s file for the
/// instruction.
std::string AsmString;
/// NumDefs - Number of def operands declared, this is the number of
/// elements in the instruction's (outs) list.
///
unsigned NumDefs;
/// Operands - This is information about the (ins) and (outs) list specified
/// to the instruction.
CGIOperandList Operands;
/// OperandList - The list of declared operands, along with their declared
/// type (which is a record).
std::vector<OperandInfo> OperandList;
/// ImplicitDefs/ImplicitUses - These are lists of registers that are
/// implicitly defined and used by the instruction.
std::vector<Record*> ImplicitDefs, ImplicitUses;
/// SubOpAliases - List of alias names for suboperands.
StringMap<std::pair<unsigned, unsigned>> SubOpAliases;
// Various boolean values we track for the instruction.
bool isPreISelOpcode : 1;
bool isReturn : 1;
bool isEHScopeReturn : 1;
bool isBranch : 1;
bool isIndirectBranch : 1;
bool isCompare : 1;
bool isMoveImm : 1;
bool isMoveReg : 1;
bool isBitcast : 1;
bool isSelect : 1;
bool isBarrier : 1;
bool isCall : 1;
bool isAdd : 1;
bool isTrap : 1;
bool canFoldAsLoad : 1;
bool mayLoad : 1;
bool mayLoad_Unset : 1;
bool mayStore : 1;
bool mayStore_Unset : 1;
bool mayRaiseFPException : 1;
bool isPredicable : 1;
bool isConvertibleToThreeAddress : 1;
bool isCommutable : 1;
bool isTerminator : 1;
bool isReMaterializable : 1;
bool hasDelaySlot : 1;
bool usesCustomInserter : 1;
bool hasPostISelHook : 1;
bool hasCtrlDep : 1;
bool isNotDuplicable : 1;
bool hasSideEffects : 1;
bool hasSideEffects_Unset : 1;
bool isAsCheapAsAMove : 1;
bool hasExtraSrcRegAllocReq : 1;
bool hasExtraDefRegAllocReq : 1;
bool isCodeGenOnly : 1;
bool isPseudo : 1;
bool isMeta : 1;
bool isRegSequence : 1;
bool isExtractSubreg : 1;
bool isInsertSubreg : 1;
bool isConvergent : 1;
bool hasNoSchedulingInfo : 1;
bool FastISelShouldIgnore : 1;
bool hasChain : 1;
bool hasChain_Inferred : 1;
bool variadicOpsAreDefs : 1;
bool isAuthenticated : 1;
// Information gleaned from the operand list.
bool isPredicable;
bool hasOptionalDef;
bool isVariadic;
std::string DeprecatedReason;
bool HasComplexDeprecationPredicate;
// Provide transparent accessors to the operand list.
bool empty() const { return OperandList.empty(); }
unsigned size() const { return OperandList.size(); }
const OperandInfo &operator[](unsigned i) const { return OperandList[i]; }
OperandInfo &operator[](unsigned i) { return OperandList[i]; }
OperandInfo &back() { return OperandList.back(); }
const OperandInfo &back() const { return OperandList.back(); }
/// Are there any undefined flags?
bool hasUndefFlags() const {
return mayLoad_Unset || mayStore_Unset || hasSideEffects_Unset;
typedef std::vector<OperandInfo>::iterator iterator;
typedef std::vector<OperandInfo>::const_iterator const_iterator;
iterator begin() { return OperandList.begin(); }
const_iterator begin() const { return OperandList.begin(); }
iterator end() { return OperandList.end(); }
const_iterator end() const { return OperandList.end(); }
/// getOperandNamed - Return the index of the operand with the specified
/// non-empty name. If the instruction does not have an operand with the
/// specified name, abort.
unsigned getOperandNamed(StringRef Name) const;
/// hasOperandNamed - Query whether the instruction has an operand of the
/// given name. If so, return true and set OpIdx to the index of the
/// operand. Otherwise, return false.
bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const;
bool hasSubOperandAlias(StringRef Name,
std::pair<unsigned, unsigned> &SubOp) const;
/// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
/// where $foo is a whole operand and $foo.bar refers to a suboperand.
/// This aborts if the name is invalid. If AllowWholeOp is true, references
/// to operands with suboperands are allowed, otherwise not.
std::pair<unsigned, unsigned> ParseOperandName(StringRef Op,
bool AllowWholeOp = true);
/// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
/// flat machineinstr operand #.
unsigned getFlattenedOperandNumber(std::pair<unsigned, unsigned> Op) const {
return OperandList[Op.first].MIOperandNo + Op.second;
}
/// getSubOperandNumber - Unflatten a operand number into an
/// operand/suboperand pair.
std::pair<unsigned, unsigned> getSubOperandNumber(unsigned Op) const {
for (unsigned i = 0;; ++i) {
assert(i < OperandList.size() && "Invalid flat operand #");
if (OperandList[i].MIOperandNo + OperandList[i].MINumOperands > Op)
return std::make_pair(i, Op - OperandList[i].MIOperandNo);
}
}
// The record used to infer instruction flags, or NULL if no flag values
// have been inferred.
Record *InferredFrom;
/// isFlatOperandNotEmitted - Return true if the specified flat operand #
/// should not be emitted with the code emitter.
bool isFlatOperandNotEmitted(unsigned FlatOpNo) const {
std::pair<unsigned, unsigned> Op = getSubOperandNumber(FlatOpNo);
if (OperandList[Op.first].DoNotEncode.size() > Op.second)
return OperandList[Op.first].DoNotEncode[Op.second];
return false;
}
// The enum value assigned by CodeGenTarget::computeInstrsByEnum.
mutable unsigned EnumVal;
void ProcessDisableEncoding(StringRef Value);
};
CodeGenInstruction(Record *R);
class CodeGenInstruction {
public:
Record *TheDef; // The actual record defining this instruction.
StringRef Namespace; // The namespace the instruction is in.
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
/// implicit def and it has a known VT, return the VT, otherwise return
/// MVT::Other.
MVT::SimpleValueType
HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const;
/// AsmString - The format string used to emit a .s file for the
/// instruction.
std::string AsmString;
/// Operands - This is information about the (ins) and (outs) list specified
/// to the instruction.
CGIOperandList Operands;
/// FlattenAsmStringVariants - Flatten the specified AsmString to only
/// include text from the specified variant, returning the new string.
static std::string FlattenAsmStringVariants(StringRef AsmString,
unsigned Variant);
/// ImplicitDefs/ImplicitUses - These are lists of registers that are
/// implicitly defined and used by the instruction.
std::vector<Record *> ImplicitDefs, ImplicitUses;
// Is the specified operand in a generic instruction implicitly a pointer.
// This can be used on intructions that use typeN or ptypeN to identify
// operands that should be considered as pointers even though SelectionDAG
// didn't make a distinction between integer and pointers.
bool isInOperandAPointer(unsigned i) const {
return isOperandImpl("InOperandList", i, "IsPointer");
}
// Various boolean values we track for the instruction.
bool isPreISelOpcode : 1;
bool isReturn : 1;
bool isEHScopeReturn : 1;
bool isBranch : 1;
bool isIndirectBranch : 1;
bool isCompare : 1;
bool isMoveImm : 1;
bool isMoveReg : 1;
bool isBitcast : 1;
bool isSelect : 1;
bool isBarrier : 1;
bool isCall : 1;
bool isAdd : 1;
bool isTrap : 1;
bool canFoldAsLoad : 1;
bool mayLoad : 1;
bool mayLoad_Unset : 1;
bool mayStore : 1;
bool mayStore_Unset : 1;
bool mayRaiseFPException : 1;
bool isPredicable : 1;
bool isConvertibleToThreeAddress : 1;
bool isCommutable : 1;
bool isTerminator : 1;
bool isReMaterializable : 1;
bool hasDelaySlot : 1;
bool usesCustomInserter : 1;
bool hasPostISelHook : 1;
bool hasCtrlDep : 1;
bool isNotDuplicable : 1;
bool hasSideEffects : 1;
bool hasSideEffects_Unset : 1;
bool isAsCheapAsAMove : 1;
bool hasExtraSrcRegAllocReq : 1;
bool hasExtraDefRegAllocReq : 1;
bool isCodeGenOnly : 1;
bool isPseudo : 1;
bool isMeta : 1;
bool isRegSequence : 1;
bool isExtractSubreg : 1;
bool isInsertSubreg : 1;
bool isConvergent : 1;
bool hasNoSchedulingInfo : 1;
bool FastISelShouldIgnore : 1;
bool hasChain : 1;
bool hasChain_Inferred : 1;
bool variadicOpsAreDefs : 1;
bool isAuthenticated : 1;
bool isOutOperandAPointer(unsigned i) const {
return isOperandImpl("OutOperandList", i, "IsPointer");
}
std::string DeprecatedReason;
bool HasComplexDeprecationPredicate;
/// Check if the operand is required to be an immediate.
bool isInOperandImmArg(unsigned i) const {
return isOperandImpl("InOperandList", i, "IsImmediate");
}
/// Are there any undefined flags?
bool hasUndefFlags() const {
return mayLoad_Unset || mayStore_Unset || hasSideEffects_Unset;
}
private:
bool isOperandImpl(StringRef OpListName, unsigned i,
StringRef PropertyName) const;
};
// The record used to infer instruction flags, or NULL if no flag values
// have been inferred.
Record *InferredFrom;
// The enum value assigned by CodeGenTarget::computeInstrsByEnum.
mutable unsigned EnumVal;
CodeGenInstruction(Record *R);
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
/// implicit def and it has a known VT, return the VT, otherwise return
/// MVT::Other.
MVT::SimpleValueType
HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const;
/// FlattenAsmStringVariants - Flatten the specified AsmString to only
/// include text from the specified variant, returning the new string.
static std::string FlattenAsmStringVariants(StringRef AsmString,
unsigned Variant);
// Is the specified operand in a generic instruction implicitly a pointer.
// This can be used on intructions that use typeN or ptypeN to identify
// operands that should be considered as pointers even though SelectionDAG
// didn't make a distinction between integer and pointers.
bool isInOperandAPointer(unsigned i) const {
return isOperandImpl("InOperandList", i, "IsPointer");
}
bool isOutOperandAPointer(unsigned i) const {
return isOperandImpl("OutOperandList", i, "IsPointer");
}
/// Check if the operand is required to be an immediate.
bool isInOperandImmArg(unsigned i) const {
return isOperandImpl("InOperandList", i, "IsImmediate");
}
private:
bool isOperandImpl(StringRef OpListName, unsigned i,
StringRef PropertyName) const;
};
} // namespace llvm
#endif

View File

@@ -25,12 +25,12 @@ class Record;
class RecordKeeper;
struct CodeGenIntrinsic {
Record *TheDef; // The actual record defining this intrinsic.
std::string Name; // The name of the LLVM function "llvm.bswap.i32"
std::string EnumName; // The name of the enum "bswap_i32"
Record *TheDef; // The actual record defining this intrinsic.
std::string Name; // The name of the LLVM function "llvm.bswap.i32"
std::string EnumName; // The name of the enum "bswap_i32"
std::string ClangBuiltinName; // Name of the corresponding GCC builtin, or "".
std::string MSBuiltinName; // Name of the corresponding MS builtin, or "".
std::string TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics.
std::string MSBuiltinName; // Name of the corresponding MS builtin, or "".
std::string TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics.
/// This structure holds the return values and parameter values of an
/// intrinsic. If the number of return values is > 1, then the intrinsic
@@ -136,9 +136,7 @@ struct CodeGenIntrinsic {
void addArgAttribute(unsigned Idx, ArgAttrKind AK, uint64_t V = 0);
bool hasProperty(enum SDNP Prop) const {
return Properties & (1 << Prop);
}
bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
/// Goes through all IntrProperties that have IsDefault
/// value set and sets the property.
@@ -182,6 +180,6 @@ public:
return Intrinsics[Pos];
}
};
}
} // namespace llvm
#endif

View File

@@ -80,9 +80,9 @@
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
using namespace llvm;
typedef std::map<std::string, std::vector<Record*> > InstrRelMapTy;
typedef std::map<std::string, std::vector<Record *>> InstrRelMapTy;
typedef std::map<std::vector<Init*>, std::vector<Record*> > RowInstrMapTy;
typedef std::map<std::vector<Init *>, std::vector<Record *>> RowInstrMapTy;
namespace {
@@ -95,10 +95,10 @@ private:
ListInit *RowFields;
ListInit *ColFields;
ListInit *KeyCol;
std::vector<ListInit*> ValueCols;
std::vector<ListInit *> ValueCols;
public:
InstrMap(Record* MapRec) {
InstrMap(Record *MapRec) {
Name = std::string(MapRec->getName());
// FilterClass - It's used to reduce the search space only to the
@@ -130,7 +130,8 @@ public:
// Each instruction map must specify at least one column for it to be valid.
if (ColValList->empty())
PrintFatalError(MapRec->getLoc(), "InstrMapping record `" +
MapRec->getName() + "' has empty " + "`ValueCols' field!");
MapRec->getName() + "' has empty " +
"`ValueCols' field!");
for (Init *I : ColValList->getValues()) {
auto *ColI = cast<ListInit>(I);
@@ -138,9 +139,10 @@ public:
// Make sure that all the sub-lists in 'ValueCols' have same number of
// elements as the fields in 'ColFields'.
if (ColI->size() != ColFields->size())
PrintFatalError(MapRec->getLoc(), "Record `" + MapRec->getName() +
"', field `ValueCols' entries don't match with " +
" the entries in 'ColFields'!");
PrintFatalError(MapRec->getLoc(),
"Record `" + MapRec->getName() +
"', field `ValueCols' entries don't match with " +
" the entries in 'ColFields'!");
ValueCols.push_back(ColI);
}
}
@@ -155,13 +157,10 @@ public:
ListInit *getKeyCol() const { return KeyCol; }
const std::vector<ListInit*> &getValueCols() const {
return ValueCols;
}
const std::vector<ListInit *> &getValueCols() const { return ValueCols; }
};
} // end anonymous namespace
//===----------------------------------------------------------------------===//
// class MapTableEmitter : It builds the instruction relation maps using
// the information provided in InstrMapping records. It outputs these
@@ -171,26 +170,26 @@ public:
namespace {
class MapTableEmitter {
private:
// std::string TargetName;
// std::string TargetName;
const CodeGenTarget &Target;
// InstrMapDesc - InstrMapping record to be processed.
InstrMap InstrMapDesc;
// InstrDefs - list of instructions filtered using FilterClass defined
// in InstrMapDesc.
std::vector<Record*> InstrDefs;
std::vector<Record *> InstrDefs;
// RowInstrMap - maps RowFields values to the instructions. It's keyed by the
// values of the row fields and contains vector of records as values.
RowInstrMapTy RowInstrMap;
// KeyInstrVec - list of key instructions.
std::vector<Record*> KeyInstrVec;
DenseMap<Record*, std::vector<Record*> > MapTable;
std::vector<Record *> KeyInstrVec;
DenseMap<Record *, std::vector<Record *>> MapTable;
public:
MapTableEmitter(CodeGenTarget &Target, RecordKeeper &Records, Record *IMRec):
Target(Target), InstrMapDesc(IMRec) {
MapTableEmitter(CodeGenTarget &Target, RecordKeeper &Records, Record *IMRec)
: Target(Target), InstrMapDesc(IMRec) {
const std::string &FilterClass = InstrMapDesc.getFilterClass();
InstrDefs = Records.getAllDerivedDefinitions(FilterClass);
}
@@ -199,7 +198,7 @@ public:
// Returns true if an instruction is a key instruction, i.e., its ColFields
// have same values as KeyCol.
bool isKeyColInstr(Record* CurInstr);
bool isKeyColInstr(Record *CurInstr);
// Find column instruction corresponding to a key instruction based on the
// constraints for that column.
@@ -215,11 +214,9 @@ public:
// Lookup functions to query binary search tables.
void emitMapFuncBody(raw_ostream &OS, unsigned TableSize);
};
} // end anonymous namespace
//===----------------------------------------------------------------------===//
// Process all the instructions that model this relation (alreday present in
// InstrDefs) and insert them into RowInstrMap which is keyed by the values of
@@ -230,14 +227,15 @@ public:
void MapTableEmitter::buildRowInstrMap() {
for (Record *CurInstr : InstrDefs) {
std::vector<Init*> KeyValue;
std::vector<Init *> KeyValue;
ListInit *RowFields = InstrMapDesc.getRowFields();
for (Init *RowField : RowFields->getValues()) {
RecordVal *RecVal = CurInstr->getValue(RowField);
if (RecVal == nullptr)
PrintFatalError(CurInstr->getLoc(), "No value " +
RowField->getAsString() + " found in \"" +
CurInstr->getName() + "\" instruction description.");
PrintFatalError(CurInstr->getLoc(),
"No value " + RowField->getAsString() + " found in \"" +
CurInstr->getName() +
"\" instruction description.");
Init *CurInstrVal = RecVal->getValue();
KeyValue.push_back(CurInstrVal);
}
@@ -256,14 +254,14 @@ void MapTableEmitter::buildRowInstrMap() {
// Return true if an instruction is a KeyCol instruction.
//===----------------------------------------------------------------------===//
bool MapTableEmitter::isKeyColInstr(Record* CurInstr) {
bool MapTableEmitter::isKeyColInstr(Record *CurInstr) {
ListInit *ColFields = InstrMapDesc.getColFields();
ListInit *KeyCol = InstrMapDesc.getKeyCol();
// Check if the instruction is a KeyCol instruction.
bool MatchFound = true;
for (unsigned j = 0, endCF = ColFields->size();
(j < endCF) && MatchFound; j++) {
for (unsigned j = 0, endCF = ColFields->size(); (j < endCF) && MatchFound;
j++) {
RecordVal *ColFieldName = CurInstr->getValue(ColFields->getElement(j));
std::string CurInstrVal = ColFieldName->getValue()->getAsUnquotedString();
std::string KeyColValue = KeyCol->getElement(j)->getAsUnquotedString();
@@ -280,10 +278,10 @@ bool MapTableEmitter::isKeyColInstr(Record* CurInstr) {
void MapTableEmitter::buildMapTable() {
// Find column instructions for a given key based on the ColField
// constraints.
const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
const std::vector<ListInit *> &ValueCols = InstrMapDesc.getValueCols();
unsigned NumOfCols = ValueCols.size();
for (Record *CurKeyInstr : KeyInstrVec) {
std::vector<Record*> ColInstrVec(NumOfCols);
std::vector<Record *> ColInstrVec(NumOfCols);
// Find the column instruction based on the constraints for the column.
for (unsigned ColIdx = 0; ColIdx < NumOfCols; ColIdx++) {
@@ -302,7 +300,7 @@ void MapTableEmitter::buildMapTable() {
Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
ListInit *CurValueCol) {
ListInit *RowFields = InstrMapDesc.getRowFields();
std::vector<Init*> KeyValue;
std::vector<Init *> KeyValue;
// Construct KeyValue using KeyInstr's values for RowFields.
for (Init *RowField : RowFields->getValues()) {
@@ -314,15 +312,15 @@ Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
// in RowInstrMap. We search through these instructions to find a match
// for the current column, i.e., the instruction which has the same values
// as CurValueCol for all the fields in ColFields.
const std::vector<Record*> &RelatedInstrVec = RowInstrMap[KeyValue];
const std::vector<Record *> &RelatedInstrVec = RowInstrMap[KeyValue];
ListInit *ColFields = InstrMapDesc.getColFields();
Record *MatchInstr = nullptr;
for (llvm::Record *CurInstr : RelatedInstrVec) {
bool MatchFound = true;
for (unsigned j = 0, endCF = ColFields->size();
(j < endCF) && MatchFound; j++) {
for (unsigned j = 0, endCF = ColFields->size(); (j < endCF) && MatchFound;
j++) {
Init *ColFieldJ = ColFields->getElement(j);
Init *CurInstrInit = CurInstr->getValue(ColFieldJ)->getValue();
std::string CurInstrVal = CurInstrInit->getAsUnquotedString();
@@ -360,21 +358,21 @@ Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) {
ArrayRef<const CodeGenInstruction*> NumberedInstructions =
Target.getInstructionsByEnumValue();
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
Target.getInstructionsByEnumValue();
StringRef Namespace = Target.getInstNamespace();
const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
const std::vector<ListInit *> &ValueCols = InstrMapDesc.getValueCols();
unsigned NumCol = ValueCols.size();
unsigned TotalNumInstr = NumberedInstructions.size();
unsigned TableSize = 0;
OS << "static const uint16_t "<<InstrMapDesc.getName();
OS << "static const uint16_t " << InstrMapDesc.getName();
// Number of columns in the table are NumCol+1 because key instructions are
// emitted as first column.
OS << "Table[]["<< NumCol+1 << "] = {\n";
OS << "Table[][" << NumCol + 1 << "] = {\n";
for (unsigned i = 0; i < TotalNumInstr; i++) {
Record *CurInstr = NumberedInstructions[i]->TheDef;
std::vector<Record*> ColInstrs = MapTable[CurInstr];
std::vector<Record *> ColInstrs = MapTable[CurInstr];
std::string OutStr;
unsigned RelExists = 0;
if (!ColInstrs.empty()) {
@@ -385,19 +383,23 @@ unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) {
OutStr += Namespace;
OutStr += "::";
OutStr += ColInstrs[j]->getName();
} else { OutStr += ", (uint16_t)-1U";}
} else {
OutStr += ", (uint16_t)-1U";
}
}
if (RelExists) {
OS << " { " << Namespace << "::" << CurInstr->getName();
OS << OutStr <<" },\n";
OS << OutStr << " },\n";
TableSize++;
}
}
}
if (!TableSize) {
OS << " { " << Namespace << "::" << "INSTRUCTION_LIST_END, ";
OS << Namespace << "::" << "INSTRUCTION_LIST_END }";
OS << " { " << Namespace << "::"
<< "INSTRUCTION_LIST_END, ";
OS << Namespace << "::"
<< "INSTRUCTION_LIST_END }";
}
OS << "}; // End of " << InstrMapDesc.getName() << "Table\n\n";
return TableSize;
@@ -430,11 +432,10 @@ void MapTableEmitter::emitBinSearch(raw_ostream &OS, unsigned TableSize) {
// Emit functions to query relation tables.
//===----------------------------------------------------------------------===//
void MapTableEmitter::emitMapFuncBody(raw_ostream &OS,
unsigned TableSize) {
void MapTableEmitter::emitMapFuncBody(raw_ostream &OS, unsigned TableSize) {
ListInit *ColFields = InstrMapDesc.getColFields();
const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
const std::vector<ListInit *> &ValueCols = InstrMapDesc.getValueCols();
// Emit binary search algorithm to locate instructions in the
// relation table. If found, return opcode value from the appropriate column
@@ -455,14 +456,13 @@ void MapTableEmitter::emitMapFuncBody(raw_ostream &OS,
}
OS << ")\n";
OS << " return " << InstrMapDesc.getName();
OS << "Table[mid]["<<i+1<<"];\n";
OS << "Table[mid][" << i + 1 << "];\n";
}
OS << " return -1;";
}
else
} else
OS << " return " << InstrMapDesc.getName() << "Table[mid][1];\n";
OS <<"}\n\n";
OS << "}\n\n";
}
//===----------------------------------------------------------------------===//
@@ -477,9 +477,9 @@ void MapTableEmitter::emitTablesWithFunc(raw_ostream &OS) {
// to pass another input to indicate the column to be selected.
ListInit *ColFields = InstrMapDesc.getColFields();
const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
OS << "// "<< InstrMapDesc.getName() << "\nLLVM_READONLY\n";
OS << "int "<< InstrMapDesc.getName() << "(uint16_t Opcode";
const std::vector<ListInit *> &ValueCols = InstrMapDesc.getValueCols();
OS << "// " << InstrMapDesc.getName() << "\nLLVM_READONLY\n";
OS << "int " << InstrMapDesc.getName() << "(uint16_t Opcode";
if (ValueCols.size() > 1) {
for (Init *CF : ColFields->getValues()) {
std::string ColName = CF->getAsUnquotedString();
@@ -501,9 +501,9 @@ void MapTableEmitter::emitTablesWithFunc(raw_ostream &OS) {
static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {
std::vector<Record*> InstrMapVec;
std::vector<Record *> InstrMapVec;
InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping");
std::map<std::string, std::vector<Init*> > ColFieldValueMap;
std::map<std::string, std::vector<Init *>> ColFieldValueMap;
// Iterate over all InstrMapping records and create a map between column
// fields and their possible values across all records.
@@ -511,20 +511,22 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {
ListInit *ColFields;
ColFields = CurMap->getValueAsListInit("ColFields");
ListInit *List = CurMap->getValueAsListInit("ValueCols");
std::vector<ListInit*> ValueCols;
std::vector<ListInit *> ValueCols;
unsigned ListSize = List->size();
for (unsigned j = 0; j < ListSize; j++) {
auto *ListJ = cast<ListInit>(List->getElement(j));
if (ListJ->size() != ColFields->size())
PrintFatalError("Record `" + CurMap->getName() + "', field "
"`ValueCols' entries don't match with the entries in 'ColFields' !");
PrintFatalError("Record `" + CurMap->getName() +
"', field "
"`ValueCols' entries don't match with the entries in "
"'ColFields' !");
ValueCols.push_back(ListJ);
}
for (unsigned j = 0, endCF = ColFields->size(); j < endCF; j++) {
for (unsigned k = 0; k < ListSize; k++){
for (unsigned k = 0; k < ListSize; k++) {
std::string ColName = ColFields->getElement(j)->getAsUnquotedString();
ColFieldValueMap[ColName].push_back((ValueCols[k])->getElement(j));
}
@@ -532,14 +534,14 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {
}
for (auto &Entry : ColFieldValueMap) {
std::vector<Init*> FieldValues = Entry.second;
std::vector<Init *> FieldValues = Entry.second;
// Delete duplicate entries from ColFieldValueMap
for (unsigned i = 0; i < FieldValues.size() - 1; i++) {
Init *CurVal = FieldValues[i];
for (unsigned j = i+1; j < FieldValues.size(); j++) {
for (unsigned j = i + 1; j < FieldValues.size(); j++) {
if (CurVal == FieldValues[j]) {
FieldValues.erase(FieldValues.begin()+j);
FieldValues.erase(FieldValues.begin() + j);
--j;
}
}
@@ -566,7 +568,7 @@ namespace llvm {
void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) {
CodeGenTarget Target(Records);
StringRef NameSpace = Target.getInstNamespace();
std::vector<Record*> InstrMapVec;
std::vector<Record *> InstrMapVec;
InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping");
if (InstrMapVec.empty())
@@ -603,4 +605,4 @@ void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) {
OS << "#endif // GET_INSTRMAP_INFO\n\n";
}
} // End llvm namespace
} // namespace llvm

View File

@@ -48,7 +48,7 @@ using namespace llvm;
//===----------------------------------------------------------------------===//
CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum)
: TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) {
: TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) {
Name = std::string(R->getName());
if (R->getValue("Namespace"))
Namespace = std::string(R->getValueAsString("Namespace"));
@@ -74,7 +74,7 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
if (!TheDef)
return;
std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf");
std::vector<Record *> Comps = TheDef->getValueAsListOfDefs("ComposedOf");
if (!Comps.empty()) {
if (Comps.size() != 2)
PrintFatalError(TheDef->getLoc(),
@@ -86,13 +86,13 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries");
}
std::vector<Record*> Parts =
TheDef->getValueAsListOfDefs("CoveringSubRegIndices");
std::vector<Record *> Parts =
TheDef->getValueAsListOfDefs("CoveringSubRegIndices");
if (!Parts.empty()) {
if (Parts.size() < 2)
PrintFatalError(TheDef->getLoc(),
"CoveredBySubRegs must have two or more entries");
SmallVector<CodeGenSubRegIndex*, 8> IdxParts;
SmallVector<CodeGenSubRegIndex *, 8> IdxParts;
for (Record *Part : Parts)
IdxParts.push_back(RegBank.getSubRegIdx(Part));
setConcatenationOf(IdxParts);
@@ -117,17 +117,19 @@ LaneBitmask CodeGenSubRegIndex::computeLaneMask() const {
}
void CodeGenSubRegIndex::setConcatenationOf(
ArrayRef<CodeGenSubRegIndex*> Parts) {
ArrayRef<CodeGenSubRegIndex *> Parts) {
if (ConcatenationOf.empty())
ConcatenationOf.assign(Parts.begin(), Parts.end());
else
assert(std::equal(Parts.begin(), Parts.end(),
ConcatenationOf.begin()) && "parts consistent");
assert(std::equal(Parts.begin(), Parts.end(), ConcatenationOf.begin()) &&
"parts consistent");
}
void CodeGenSubRegIndex::computeConcatTransitiveClosure() {
for (SmallVectorImpl<CodeGenSubRegIndex*>::iterator
I = ConcatenationOf.begin(); I != ConcatenationOf.end(); /*empty*/) {
for (SmallVectorImpl<CodeGenSubRegIndex *>::iterator I =
ConcatenationOf.begin();
I != ConcatenationOf.end();
/*empty*/) {
CodeGenSubRegIndex *SubIdx = *I;
SubIdx->computeConcatTransitiveClosure();
#ifndef NDEBUG
@@ -160,8 +162,8 @@ CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum)
}
void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
std::vector<Record*> SRIs = TheDef->getValueAsListOfDefs("SubRegIndices");
std::vector<Record*> SRs = TheDef->getValueAsListOfDefs("SubRegs");
std::vector<Record *> SRIs = TheDef->getValueAsListOfDefs("SubRegIndices");
std::vector<Record *> SRs = TheDef->getValueAsListOfDefs("SubRegs");
if (SRIs.size() != SRs.size())
PrintFatalError(TheDef->getLoc(),
@@ -182,7 +184,7 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
// Add ad hoc alias links. This is a symmetric relationship between two
// registers, so build a symmetric graph by adding links in both ends.
std::vector<Record*> Aliases = TheDef->getValueAsListOfDefs("Aliases");
std::vector<Record *> Aliases = TheDef->getValueAsListOfDefs("Aliases");
for (Record *Alias : Aliases) {
CodeGenRegister *Reg = RegBank.getReg(Alias);
ExplicitAliases.push_back(Reg);
@@ -204,8 +206,8 @@ class RegUnitIterator {
static CodeGenRegister::RegUnitList Sentinel;
public:
RegUnitIterator(const CodeGenRegister::Vec &Regs):
RegI(Regs.begin()), RegE(Regs.end()) {
RegUnitIterator(const CodeGenRegister::Vec &Regs)
: RegI(Regs.begin()), RegE(Regs.end()) {
if (RegI == RegE) {
UnitI = Sentinel.end();
@@ -219,9 +221,15 @@ public:
bool isValid() const { return UnitI != UnitE; }
unsigned operator* () const { assert(isValid()); return *UnitI; }
unsigned operator*() const {
assert(isValid());
return *UnitI;
}
const CodeGenRegister *getReg() const { assert(isValid()); return *RegI; }
const CodeGenRegister *getReg() const {
assert(isValid());
return *RegI;
}
/// Preincrement. Move to the next unit.
void operator++() {
@@ -280,14 +288,15 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
Idx->Artificial = false;
if (!SubRegs.insert(std::make_pair(Idx, SR)).second)
PrintFatalError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() +
" appears twice in Register " + getName());
" appears twice in Register " +
getName());
// Map explicit sub-registers first, so the names take precedence.
// The inherited sub-registers are mapped below.
SubReg2Idx.insert(std::make_pair(SR, Idx));
}
// Keep track of inherited subregs and how they can be reached.
SmallPtrSet<CodeGenRegister*, 8> Orphans;
SmallPtrSet<CodeGenRegister *, 8> Orphans;
// Clone inherited subregs and place duplicate entries in Orphans.
// Here the order is important - earlier subregs take precedence.
@@ -305,7 +314,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
// If dsub_2 has ComposedOf = [qsub_1, dsub_0], and this register has a
// qsub_1 subreg, add a dsub_2 subreg. Keep growing Indices and process
// expanded subreg indices recursively.
SmallVector<CodeGenSubRegIndex*, 8> Indices = ExplicitSubRegIndices;
SmallVector<CodeGenSubRegIndex *, 8> Indices = ExplicitSubRegIndices;
for (unsigned i = 0; i != Indices.size(); ++i) {
CodeGenSubRegIndex *Idx = Indices[i];
const CodeGenSubRegIndex::CompMap &Comps = Idx->getComposites();
@@ -350,7 +359,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
const SubRegMap &Map = SR->computeSubRegs(RegBank);
for (const auto &SubReg : Map)
if (Orphans.erase(SubReg.second))
SubRegs[RegBank.getCompositeSubRegIndex(Idx, SubReg.first)] = SubReg.second;
SubRegs[RegBank.getCompositeSubRegIndex(Idx, SubReg.first)] =
SubReg.second;
}
// Compute the inverse SubReg -> Idx map.
@@ -360,7 +370,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
if (TheDef)
Loc = TheDef->getLoc();
PrintFatalError(Loc, "Register " + getName() +
" has itself as a sub-register");
" has itself as a sub-register");
}
// Compute AllSuperRegsCovered.
@@ -368,17 +378,18 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
SubReg.first->AllSuperRegsCovered = false;
// Ensure that every sub-register has a unique name.
DenseMap<const CodeGenRegister*, CodeGenSubRegIndex*>::iterator Ins =
SubReg2Idx.insert(std::make_pair(SubReg.second, SubReg.first)).first;
DenseMap<const CodeGenRegister *, CodeGenSubRegIndex *>::iterator Ins =
SubReg2Idx.insert(std::make_pair(SubReg.second, SubReg.first)).first;
if (Ins->second == SubReg.first)
continue;
// Trouble: Two different names for SubReg.second.
ArrayRef<SMLoc> Loc;
if (TheDef)
Loc = TheDef->getLoc();
PrintFatalError(Loc, "Sub-register can't have two names: " +
SubReg.second->getName() + " available as " +
SubReg.first->getName() + " and " + Ins->second->getName());
PrintFatalError(
Loc, "Sub-register can't have two names: " + SubReg.second->getName() +
" available as " + SubReg.first->getName() + " and " +
Ins->second->getName());
}
// Derive possible names for sub-register concatenations from any explicit
@@ -392,7 +403,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
continue;
// SR is composed of multiple sub-regs. Find their names in this register.
SmallVector<CodeGenSubRegIndex*, 8> Parts;
SmallVector<CodeGenSubRegIndex *, 8> Parts;
for (unsigned j = 0, e = SR->ExplicitSubRegs.size(); j != e; ++j) {
CodeGenSubRegIndex &I = *SR->ExplicitSubRegIndices[j];
if (!I.Artificial)
@@ -464,8 +475,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
SmallVector<SubRegMap::value_type, 8> NewSubRegs;
std::queue<std::pair<CodeGenSubRegIndex*,CodeGenRegister*>> SubRegQueue;
for (std::pair<CodeGenSubRegIndex*,CodeGenRegister*> P : SubRegs)
std::queue<std::pair<CodeGenSubRegIndex *, CodeGenRegister *>> SubRegQueue;
for (std::pair<CodeGenSubRegIndex *, CodeGenRegister *> P : SubRegs)
SubRegQueue.push(P);
// Look at the leading super-registers of each sub-register. Those are the
@@ -479,7 +490,7 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
const CodeGenRegister::SuperRegList &Leads = SubReg->LeadingSuperRegs;
for (unsigned i = 0, e = Leads.size(); i != e; ++i) {
CodeGenRegister *Cand = const_cast<CodeGenRegister*>(Leads[i]);
CodeGenRegister *Cand = const_cast<CodeGenRegister *>(Leads[i]);
// Already got this sub-register?
if (Cand == this || getSubRegIndex(Cand))
continue;
@@ -488,7 +499,7 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
"Super-register has no sub-registers");
if (Cand->ExplicitSubRegs.size() == 1)
continue;
SmallVector<CodeGenSubRegIndex*, 8> Parts;
SmallVector<CodeGenSubRegIndex *, 8> Parts;
// We know that the first component is (SubRegIdx,SubReg). However we
// may still need to split it into smaller subregister parts.
assert(Cand->ExplicitSubRegs[0] == SubReg && "LeadingSuperRegs correct");
@@ -513,7 +524,7 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
// Each part of Cand is a sub-register of this. Make the full Cand also
// a sub-register with a concatenated sub-register index.
CodeGenSubRegIndex *Concat = RegBank.getConcatSubRegIndex(Parts);
std::pair<CodeGenSubRegIndex*,CodeGenRegister*> NewSubReg =
std::pair<CodeGenSubRegIndex *, CodeGenRegister *> NewSubReg =
std::make_pair(Concat, Cand);
if (!SubRegs.insert(NewSubReg).second)
@@ -570,9 +581,8 @@ void CodeGenRegister::computeSuperRegs(CodeGenRegBank &RegBank) {
TopoSig = RegBank.getTopoSig(Id);
}
void
CodeGenRegister::addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet,
CodeGenRegBank &RegBank) const {
void CodeGenRegister::addSubRegsPreOrder(
SetVector<const CodeGenRegister *> &OSet, CodeGenRegBank &RegBank) const {
assert(SubRegsComplete && "Must precompute sub-registers");
for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
CodeGenRegister *SR = ExplicitSubRegs[i];
@@ -611,7 +621,7 @@ struct TupleExpander : SetTheory::Expander {
: SynthDefs(SynthDefs) {}
void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) override {
std::vector<Record*> Indices = Def->getValueAsListOfDefs("SubRegIndices");
std::vector<Record *> Indices = Def->getValueAsListOfDefs("SubRegIndices");
unsigned Dim = Indices.size();
ListInit *SubRegs = Def->getValueAsListInit("SubRegs");
if (Dim != SubRegs->size())
@@ -635,17 +645,18 @@ struct TupleExpander : SetTheory::Expander {
Record *RegisterCl = Def->getRecords().getClass("Register");
RecTy *RegisterRecTy = RecordRecTy::get(RegisterCl);
std::vector<StringRef> RegNames =
Def->getValueAsListOfStrings("RegAsmNames");
Def->getValueAsListOfStrings("RegAsmNames");
// Zip them up.
RecordKeeper &RK = Def->getRecords();
for (unsigned n = 0; n != Length; ++n) {
std::string Name;
Record *Proto = Lists[0][n];
std::vector<Init*> Tuple;
std::vector<Init *> Tuple;
for (unsigned i = 0; i != Dim; ++i) {
Record *Reg = Lists[i][n];
if (i) Name += '_';
if (i)
Name += '_';
Name += Reg->getName();
Tuple.push_back(DefInit::get(Reg));
}
@@ -660,7 +671,7 @@ struct TupleExpander : SetTheory::Expander {
if (RegNames.size() <= n)
PrintFatalError(Def->getLoc(),
"Register tuple definition missing name for '" +
Name + "'.");
Name + "'.");
AsmName = StringInit::get(RK, RegNames[n]);
}
@@ -703,15 +714,13 @@ struct TupleExpander : SetTheory::Expander {
RV.setValue(BitInit::get(RK, true));
// Copy fields from the RegisterTuples def.
if (Field == "SubRegIndices" ||
Field == "CompositeIndices") {
if (Field == "SubRegIndices" || Field == "CompositeIndices") {
NewReg->addValue(*Def->getValue(Field));
continue;
}
// Some fields get their default uninitialized value.
if (Field == "DwarfNumbers" ||
Field == "DwarfAlias" ||
if (Field == "DwarfNumbers" || Field == "DwarfAlias" ||
Field == "Aliases") {
if (const RecordVal *DefRV = RegisterCl->getValue(Field))
NewReg->addValue(*DefRV);
@@ -740,7 +749,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
: TheDef(R), Name(std::string(R->getName())),
TopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1), TSFlags(0) {
GeneratePressureSet = R->getValueAsBit("GeneratePressureSet");
std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes");
std::vector<Record *> TypeList = R->getValueAsListOfDefs("RegTypes");
if (TypeList.empty())
PrintFatalError(R->getLoc(), "RegTypes list must not be empty!");
for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
@@ -779,7 +788,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
Order.pop_back();
if (!contains(Reg))
PrintFatalError(R->getLoc(), " AltOrder register " + Reg->getName() +
" is not a class member");
" is not a class member");
}
}
@@ -793,8 +802,8 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
"Impossible to determine register size");
if (!RSI.hasDefault()) {
RegSizeInfo RI;
RI.RegSize = RI.SpillSize = Size ? Size
: VTs[0].getSimple().getSizeInBits();
RI.RegSize = RI.SpillSize =
Size ? Size : VTs[0].getSimple().getSizeInBits();
RI.SpillAlignment = R->getValueAsInt("Alignment");
RSI.insertRegSizeForMode(DefaultMode, RI);
}
@@ -890,7 +899,7 @@ bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
deref<std::less<>>());
}
unsigned CodeGenRegisterClass::getWeight(const CodeGenRegBank& RegBank) const {
unsigned CodeGenRegisterClass::getWeight(const CodeGenRegBank &RegBank) const {
if (TheDef && !TheDef->isValueUnset("Weight"))
return TheDef->getValueAsInt("Weight");
@@ -902,19 +911,19 @@ unsigned CodeGenRegisterClass::getWeight(const CodeGenRegBank& RegBank) const {
namespace llvm {
raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
OS << "{ " << K.RSI;
for (const auto R : *K.Members)
OS << ", " << R->getName();
return OS << " }";
}
raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
OS << "{ " << K.RSI;
for (const auto R : *K.Members)
OS << ", " << R->getName();
return OS << " }";
}
} // end namespace llvm
// This is a simple lexicographical order that can be used to search for sets.
// It is not the same as the topological order provided by TopoOrderRC.
bool CodeGenRegisterClass::Key::
operator<(const CodeGenRegisterClass::Key &B) const {
bool CodeGenRegisterClass::Key::operator<(
const CodeGenRegisterClass::Key &B) const {
assert(Members && B.Members);
return std::tie(*Members, RSI) < std::tie(*B.Members, B.RSI);
}
@@ -1066,7 +1075,7 @@ CodeGenRegisterClass::getMatchingSubClassWithSubRegs(
// Find all the subreg classes and order them by size too.
std::vector<std::pair<CodeGenRegisterClass *, BitVector>> SuperRegClasses;
for (auto &RC: RegClasses) {
for (auto &RC : RegClasses) {
BitVector SuperRegClassesBV(RegClasses.size());
RC.getSuperRegClasses(SubIdx, SuperRegClassesBV);
if (SuperRegClassesBV.any())
@@ -1129,8 +1138,8 @@ void CodeGenRegisterClass::getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
}
// Populate a unique sorted list of units from a register set.
void CodeGenRegisterClass::buildRegUnitSet(const CodeGenRegBank &RegBank,
std::vector<unsigned> &RegUnits) const {
void CodeGenRegisterClass::buildRegUnitSet(
const CodeGenRegBank &RegBank, std::vector<unsigned> &RegUnits) const {
std::vector<unsigned> TmpUnits;
for (RegUnitIterator UnitI(Members); UnitI.isValid(); ++UnitI) {
const RegUnit &RU = RegBank.getRegUnit(*UnitI);
@@ -1158,7 +1167,8 @@ CodeGenRegisterCategory::CodeGenRegisterCategory(CodeGenRegBank &RegBank,
//===----------------------------------------------------------------------===//
CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records,
const CodeGenHwModes &Modes) : CGH(Modes) {
const CodeGenHwModes &Modes)
: CGH(Modes) {
// Configure register Sets to understand register classes and tuples.
Sets.addFieldExpander("RegisterClass", "MemberList");
Sets.addFieldExpander("CalleeSavedRegs", "SaveList");
@@ -1167,7 +1177,7 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records,
// Read in the user-defined (named) sub-register indices.
// More indices will be synthesized later.
std::vector<Record*> SRIs = Records.getAllDerivedDefinitions("SubRegIndex");
std::vector<Record *> SRIs = Records.getAllDerivedDefinitions("SubRegIndex");
llvm::sort(SRIs, LessRecord());
for (unsigned i = 0, e = SRIs.size(); i != e; ++i)
getSubRegIdx(SRIs[i]);
@@ -1238,8 +1248,9 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records,
SRI.computeConcatTransitiveClosure();
if (!SRI.ConcatenationOf.empty())
ConcatIdx.insert(std::make_pair(
SmallVector<CodeGenSubRegIndex*,8>(SRI.ConcatenationOf.begin(),
SRI.ConcatenationOf.end()), &SRI));
SmallVector<CodeGenSubRegIndex *, 8>(SRI.ConcatenationOf.begin(),
SRI.ConcatenationOf.end()),
&SRI));
}
// Infer even more sub-registers by combining leading super-registers.
@@ -1269,7 +1280,7 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records,
NumNativeRegUnits = RegUnits.size();
// Read in register class definitions.
std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass");
std::vector<Record *> RCs = Records.getAllDerivedDefinitions("RegisterClass");
if (RCs.empty())
PrintFatalError("No 'RegisterClass' subclasses defined!");
@@ -1299,8 +1310,8 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records,
}
// Create a synthetic CodeGenSubRegIndex without a corresponding Record.
CodeGenSubRegIndex*
CodeGenRegBank::createSubRegIndex(StringRef Name, StringRef Namespace) {
CodeGenSubRegIndex *CodeGenRegBank::createSubRegIndex(StringRef Name,
StringRef Namespace) {
SubRegIndices.emplace_back(Name, Namespace, SubRegIndices.size() + 1);
return &SubRegIndices.back();
}
@@ -1315,7 +1326,7 @@ CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) {
}
const CodeGenSubRegIndex *
CodeGenRegBank::findSubRegIdx(const Record* Def) const {
CodeGenRegBank::findSubRegIdx(const Record *Def) const {
return Def2SubRegIdx.lookup(Def);
}
@@ -1339,7 +1350,7 @@ void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
}
// Create a synthetic sub-class if it is missing.
CodeGenRegisterClass*
CodeGenRegisterClass *
CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
const CodeGenRegister::Vec *Members,
StringRef Name) {
@@ -1362,7 +1373,7 @@ CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def) const {
PrintFatalError(Def->getLoc(), "Not a known RegisterClass!");
}
CodeGenSubRegIndex*
CodeGenSubRegIndex *
CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A,
CodeGenSubRegIndex *B) {
// Look for an existing entry.
@@ -1377,8 +1388,8 @@ CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A,
return Comp;
}
CodeGenSubRegIndex *CodeGenRegBank::
getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &Parts) {
CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex(
const SmallVector<CodeGenSubRegIndex *, 8> &Parts) {
assert(Parts.size() > 1 && "Need two parts to concatenate");
#ifndef NDEBUG
for (CodeGenSubRegIndex *Idx : Parts) {
@@ -1419,26 +1430,26 @@ getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &Parts) {
}
void CodeGenRegBank::computeComposites() {
using RegMap = std::map<const CodeGenRegister*, const CodeGenRegister*>;
using RegMap = std::map<const CodeGenRegister *, const CodeGenRegister *>;
// Subreg -> { Reg->Reg }, where the right-hand side is the mapping from
// register to (sub)register associated with the action of the left-hand
// side subregister.
std::map<const CodeGenSubRegIndex*, RegMap> SubRegAction;
std::map<const CodeGenSubRegIndex *, RegMap> SubRegAction;
for (const CodeGenRegister &R : Registers) {
const CodeGenRegister::SubRegMap &SM = R.getSubRegs();
for (std::pair<const CodeGenSubRegIndex*, const CodeGenRegister*> P : SM)
for (std::pair<const CodeGenSubRegIndex *, const CodeGenRegister *> P : SM)
SubRegAction[P.first].insert({&R, P.second});
}
// Calculate the composition of two subregisters as compositions of their
// associated actions.
auto compose = [&SubRegAction] (const CodeGenSubRegIndex *Sub1,
const CodeGenSubRegIndex *Sub2) {
auto compose = [&SubRegAction](const CodeGenSubRegIndex *Sub1,
const CodeGenSubRegIndex *Sub2) {
RegMap C;
const RegMap &Img1 = SubRegAction.at(Sub1);
const RegMap &Img2 = SubRegAction.at(Sub2);
for (std::pair<const CodeGenRegister*, const CodeGenRegister*> P : Img1) {
for (std::pair<const CodeGenRegister *, const CodeGenRegister *> P : Img1) {
auto F = Img2.find(P.second);
if (F != Img2.end())
C.insert({P.first, F->second});
@@ -1447,13 +1458,13 @@ void CodeGenRegBank::computeComposites() {
};
// Check if the two maps agree on the intersection of their domains.
auto agree = [] (const RegMap &Map1, const RegMap &Map2) {
auto agree = [](const RegMap &Map1, const RegMap &Map2) {
// Technically speaking, an empty map agrees with any other map, but
// this could flag false positives. We're interested in non-vacuous
// agreements.
if (Map1.empty() || Map2.empty())
return false;
for (std::pair<const CodeGenRegister*, const CodeGenRegister*> P : Map1) {
for (std::pair<const CodeGenRegister *, const CodeGenRegister *> P : Map1) {
auto F = Map2.find(P.first);
if (F == Map2.end() || P.second != F->second)
return false;
@@ -1461,9 +1472,9 @@ void CodeGenRegBank::computeComposites() {
return true;
};
using CompositePair = std::pair<const CodeGenSubRegIndex*,
const CodeGenSubRegIndex*>;
SmallSet<CompositePair,4> UserDefined;
using CompositePair =
std::pair<const CodeGenSubRegIndex *, const CodeGenSubRegIndex *>;
SmallSet<CompositePair, 4> UserDefined;
for (const CodeGenSubRegIndex &Idx : SubRegIndices)
for (auto P : Idx.getComposites())
UserDefined.insert(std::make_pair(&Idx, P.first));
@@ -1528,8 +1539,8 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
if (Idx.getComposites().empty()) {
if (Bit > LaneBitmask::BitWidth) {
PrintFatalError(
Twine("Ran out of lanemask bits to represent subregister ")
+ Idx.getName());
Twine("Ran out of lanemask bits to represent subregister ") +
Idx.getName());
}
Idx.LaneMask = LaneBitmask::getLane(Bit);
++Bit;
@@ -1556,7 +1567,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
unsigned DstBit = Idx.LaneMask.getHighestLane();
assert(Idx.LaneMask == LaneBitmask::getLane(DstBit) &&
"Must be a leaf subregister");
MaskRolPair MaskRol = { LaneBitmask::getLane(0), (uint8_t)DstBit };
MaskRolPair MaskRol = {LaneBitmask::getLane(0), (uint8_t)DstBit};
LaneTransforms.push_back(MaskRol);
} else {
// Go through all leaf subregisters and find the ones that compose with
@@ -1571,7 +1582,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
// Replicate the behaviour from the lane mask generation loop above.
unsigned SrcBit = NextBit;
LaneBitmask SrcMask = LaneBitmask::getLane(SrcBit);
if (NextBit < LaneBitmask::BitWidth-1)
if (NextBit < LaneBitmask::BitWidth - 1)
++NextBit;
assert(Idx2.LaneMask == SrcMask);
@@ -1586,8 +1597,8 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
// Create Mask+Rotate operation and merge with existing ops if possible.
unsigned DstBit = Composite->LaneMask.getHighestLane();
int Shift = DstBit - SrcBit;
uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift
: LaneBitmask::BitWidth + Shift;
uint8_t RotateLeft =
Shift >= 0 ? (uint8_t)Shift : LaneBitmask::BitWidth + Shift;
for (auto &I : LaneTransforms) {
if (I.RotateLeft == RotateLeft) {
I.Mask |= SrcMask;
@@ -1595,7 +1606,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
}
}
if (SrcMask.any()) {
MaskRolPair MaskRol = { SrcMask, RotateLeft };
MaskRolPair MaskRol = {SrcMask, RotateLeft};
LaneTransforms.push_back(MaskRol);
}
}
@@ -1611,7 +1622,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
// in a sequence with 0 entries we can just pick any other. Choose
// Mask 0xffffffff with Rotation 0.
if (LaneTransforms.size() == 0) {
MaskRolPair P = { LaneBitmask::getAll(), 0 };
MaskRolPair P = {LaneBitmask::getAll(), 0};
LaneTransforms.push_back(P);
}
}
@@ -1679,7 +1690,7 @@ struct UberRegSet {
//
// UberRegSets[0] is a special non-allocatable set.
static void computeUberSets(std::vector<UberRegSet> &UberSets,
std::vector<UberRegSet*> &RegSets,
std::vector<UberRegSet *> &RegSets,
CodeGenRegBank &RegBank) {
const auto &Registers = RegBank.getRegisters();
@@ -1742,7 +1753,8 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets,
CodeGenRegBank &RegBank) {
// Skip the first unallocatable set.
for (std::vector<UberRegSet>::iterator I = std::next(UberSets.begin()),
E = UberSets.end(); I != E; ++I) {
E = UberSets.end();
I != E; ++I) {
// Initialize all unit weights in this set, and remember the max units/reg.
const CodeGenRegister *Reg = nullptr;
@@ -1797,7 +1809,7 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets,
// - induces recomputation of UberWeights.
static bool normalizeWeight(CodeGenRegister *Reg,
std::vector<UberRegSet> &UberSets,
std::vector<UberRegSet*> &RegSets,
std::vector<UberRegSet *> &RegSets,
BitVector &NormalRegs,
CodeGenRegister::RegUnitList &NormalUnits,
CodeGenRegBank &RegBank) {
@@ -1830,15 +1842,14 @@ static bool normalizeWeight(CodeGenRegister *Reg,
// for this register, has not been used to normalize a subregister's set,
// and has not already been used to singularly determine this UberRegSet.
unsigned AdjustUnit = *Reg->getRegUnits().begin();
if (Reg->getRegUnits().count() != 1
|| hasRegUnit(NormalUnits, AdjustUnit)
|| hasRegUnit(UberSet->SingularDeterminants, AdjustUnit)) {
if (Reg->getRegUnits().count() != 1 ||
hasRegUnit(NormalUnits, AdjustUnit) ||
hasRegUnit(UberSet->SingularDeterminants, AdjustUnit)) {
// We don't have an adjustable unit, so adopt a new one.
AdjustUnit = RegBank.newRegUnit(UberSet->Weight - RegWeight);
Reg->adoptRegUnit(AdjustUnit);
// Adopting a unit does not immediately require recomputing set weights.
}
else {
} else {
// Adjust the existing single unit.
if (!RegBank.getRegUnit(AdjustUnit).Artificial)
RegBank.increaseRegUnitWeight(AdjustUnit, UberSet->Weight - RegWeight);
@@ -1860,7 +1871,7 @@ static bool normalizeWeight(CodeGenRegister *Reg,
// where each register's weight is defined as sum of its units' weights.
void CodeGenRegBank::computeRegUnitWeights() {
std::vector<UberRegSet> UberSets;
std::vector<UberRegSet*> RegSets(Registers.size());
std::vector<UberRegSet *> RegSets(Registers.size());
computeUberSets(UberSets, RegSets, *this);
// UberSets and RegSets are now immutable.
@@ -1871,7 +1882,7 @@ void CodeGenRegBank::computeRegUnitWeights() {
unsigned NumIters = 0;
for (bool Changed = true; Changed; ++NumIters) {
assert(NumIters <= NumNativeRegUnits && "Runaway register unit weights");
(void) NumIters;
(void)NumIters;
Changed = false;
for (auto &Reg : Registers) {
CodeGenRegister::RegUnitList NormalUnits;
@@ -1887,9 +1898,9 @@ void CodeGenRegBank::computeRegUnitWeights() {
static std::vector<RegUnitSet>::const_iterator
findRegUnitSet(const std::vector<RegUnitSet> &UniqueSets,
const RegUnitSet &Set) {
std::vector<RegUnitSet>::const_iterator
I = UniqueSets.begin(), E = UniqueSets.end();
for(;I != E; ++I) {
std::vector<RegUnitSet>::const_iterator I = UniqueSets.begin(),
E = UniqueSets.end();
for (; I != E; ++I) {
if (I->Units == Set.Units)
break;
}
@@ -1899,8 +1910,8 @@ findRegUnitSet(const std::vector<RegUnitSet> &UniqueSets,
// Return true if the RUSubSet is a subset of RUSuperSet.
static bool isRegUnitSubSet(const std::vector<unsigned> &RUSubSet,
const std::vector<unsigned> &RUSuperSet) {
return std::includes(RUSuperSet.begin(), RUSuperSet.end(),
RUSubSet.begin(), RUSubSet.end());
return std::includes(RUSuperSet.begin(), RUSuperSet.end(), RUSubSet.begin(),
RUSubSet.end());
}
/// Iteratively prune unit sets. Prune subsets that are close to the superset,
@@ -1925,8 +1936,8 @@ void CodeGenRegBank::pruneUnitSets() {
// Form an equivalence class of UnitSets with no significant difference.
std::vector<unsigned> SuperSetIDs;
for (unsigned SubIdx = 0, EndIdx = RegUnitSets.size();
SubIdx != EndIdx; ++SubIdx) {
for (unsigned SubIdx = 0, EndIdx = RegUnitSets.size(); SubIdx != EndIdx;
++SubIdx) {
const RegUnitSet &SubSet = RegUnitSets[SubIdx];
unsigned SuperIdx = 0;
for (; SuperIdx != EndIdx; ++SuperIdx) {
@@ -1935,10 +1946,10 @@ void CodeGenRegBank::pruneUnitSets() {
unsigned UnitWeight = RegUnits[SubSet.Units[0]].Weight;
const RegUnitSet &SuperSet = RegUnitSets[SuperIdx];
if (isRegUnitSubSet(SubSet.Units, SuperSet.Units)
&& (SubSet.Units.size() + 3 > SuperSet.Units.size())
&& UnitWeight == RegUnits[SuperSet.Units[0]].Weight
&& UnitWeight == RegUnits[SuperSet.Units.back()].Weight) {
if (isRegUnitSubSet(SubSet.Units, SuperSet.Units) &&
(SubSet.Units.size() + 3 > SuperSet.Units.size()) &&
UnitWeight == RegUnits[SuperSet.Units[0]].Weight &&
UnitWeight == RegUnits[SuperSet.Units.back()].Weight) {
LLVM_DEBUG(dbgs() << "UnitSet " << SubIdx << " subsumed by " << SuperIdx
<< "\n");
// We can pick any of the set names for the merged set. Go for the
@@ -1988,7 +1999,7 @@ void CodeGenRegBank::computeRegUnitSets() {
// Find an existing RegUnitSet.
std::vector<RegUnitSet>::const_iterator SetI =
findRegUnitSet(RegUnitSets, RegUnitSets.back());
findRegUnitSet(RegUnitSets, RegUnitSets.back());
if (SetI != std::prev(RegUnitSets.end()))
RegUnitSets.pop_back();
}
@@ -2023,10 +2034,10 @@ void CodeGenRegBank::computeRegUnitSets() {
// In theory, this is combinatorial. In practice, it needs to be bounded
// by a small number of sets for regpressure to be efficient.
// If the assert is hit, we need to implement pruning.
assert(Idx < (2*NumRegUnitSubSets) && "runaway unit set inference");
assert(Idx < (2 * NumRegUnitSubSets) && "runaway unit set inference");
// Compare new sets with all original classes.
for (unsigned SearchIdx = (Idx >= NumRegUnitSubSets) ? 0 : Idx+1;
for (unsigned SearchIdx = (Idx >= NumRegUnitSubSets) ? 0 : Idx + 1;
SearchIdx != EndIdx; ++SearchIdx) {
std::set<unsigned> Intersection;
std::set_intersection(RegUnitSets[Idx].Units.begin(),
@@ -2040,7 +2051,7 @@ void CodeGenRegBank::computeRegUnitSets() {
// Speculatively grow the RegUnitSets to hold the new set.
RegUnitSets.resize(RegUnitSets.size() + 1);
RegUnitSets.back().Name =
RegUnitSets[Idx].Name + "_with_" + RegUnitSets[SearchIdx].Name;
RegUnitSets[Idx].Name + "_with_" + RegUnitSets[SearchIdx].Name;
std::set_union(RegUnitSets[Idx].Units.begin(),
RegUnitSets[Idx].Units.end(),
@@ -2051,7 +2062,7 @@ void CodeGenRegBank::computeRegUnitSets() {
// Find an existing RegUnitSet, or add the union to the unique sets.
std::vector<RegUnitSet>::const_iterator SetI =
findRegUnitSet(RegUnitSets, RegUnitSets.back());
findRegUnitSet(RegUnitSets, RegUnitSets.back());
if (SetI != std::prev(RegUnitSets.end()))
RegUnitSets.pop_back();
else {
@@ -2098,8 +2109,8 @@ void CodeGenRegBank::computeRegUnitSets() {
dbgs() << "\n UnitSetIDs:");
// Find all supersets.
for (unsigned USIdx = 0, USEnd = RegUnitSets.size();
USIdx != USEnd; ++USIdx) {
for (unsigned USIdx = 0, USEnd = RegUnitSets.size(); USIdx != USEnd;
++USIdx) {
if (isRegUnitSubSet(RCRegUnits, RegUnitSets[USIdx].Units)) {
LLVM_DEBUG(dbgs() << " " << USIdx);
RegClassUnitSets[RCIdx].push_back(USIdx);
@@ -2114,8 +2125,8 @@ void CodeGenRegBank::computeRegUnitSets() {
// contain the unit. Normally, this matches an existing list of UnitSets for a
// register class. If not, we create a new entry in RegClassUnitSets as a
// "fake" register class.
for (unsigned UnitIdx = 0, UnitEnd = NumNativeRegUnits;
UnitIdx < UnitEnd; ++UnitIdx) {
for (unsigned UnitIdx = 0, UnitEnd = NumNativeRegUnits; UnitIdx < UnitEnd;
++UnitIdx) {
std::vector<unsigned> RUSets;
for (unsigned i = 0, e = RegUnitSets.size(); i != e; ++i) {
RegUnitSet &RUSet = RegUnitSets[i];
@@ -2124,8 +2135,8 @@ void CodeGenRegBank::computeRegUnitSets() {
RUSets.push_back(i);
}
unsigned RCUnitSetsIdx = 0;
for (unsigned e = RegClassUnitSets.size();
RCUnitSetsIdx != e; ++RCUnitSetsIdx) {
for (unsigned e = RegClassUnitSets.size(); RCUnitSetsIdx != e;
++RCUnitSetsIdx) {
if (RegClassUnitSets[RCUnitSetsIdx] == RUSets) {
break;
}
@@ -2301,9 +2312,8 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
continue;
}
// This is a real subset. See if we have a matching class.
CodeGenRegisterClass *SubRC =
getOrCreateSubClass(RC, &I->second,
RC->getName() + "_with_" + I->first->getName());
CodeGenRegisterClass *SubRC = getOrCreateSubClass(
RC, &I->second, RC->getName() + "_with_" + I->first->getName());
RC->setSubClassWithSubReg(&SubIdx, SubRC);
}
}
@@ -2315,8 +2325,9 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
// has a maximal result for any SubIdx and any X >= FirstSubRegRC.
//
void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
std::list<CodeGenRegisterClass>::iterator FirstSubRegRC) {
void CodeGenRegBank::inferMatchingSuperRegClass(
CodeGenRegisterClass *RC,
std::list<CodeGenRegisterClass>::iterator FirstSubRegRC) {
DenseMap<const CodeGenRegister *, std::vector<const CodeGenRegister *>>
SubToSuperRegs;
BitVector TopoSigs(getNumTopoSigs());
@@ -2374,9 +2385,9 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
// Only a subset of RC maps into SubRC. Make sure it is represented by a
// class.
getOrCreateSubClass(RC, &SubSetVec, RC->getName() + "_with_" +
SubIdx.getName() + "_in_" +
SubRC.getName());
getOrCreateSubClass(RC, &SubSetVec,
RC->getName() + "_with_" + SubIdx.getName() + "_in_" +
SubRC.getName());
}
}
}
@@ -2431,8 +2442,7 @@ void CodeGenRegBank::computeInferredRegisterClasses() {
/// return null. If the register is in multiple classes, and the classes have a
/// superset-subset relationship and the same set of types, return the
/// superclass. Otherwise return null.
const CodeGenRegisterClass*
CodeGenRegBank::getRegClassForRegister(Record *R) {
const CodeGenRegisterClass *CodeGenRegBank::getRegClassForRegister(Record *R) {
const CodeGenRegister *Reg = getReg(R);
const CodeGenRegisterClass *FoundRC = nullptr;
for (const auto &RC : getRegClasses()) {
@@ -2477,8 +2487,8 @@ CodeGenRegBank::getMinimalPhysRegClass(Record *RegRecord,
const CodeGenRegister *Reg = getReg(RegRecord);
const CodeGenRegisterClass *BestRC = nullptr;
for (const auto &RC : getRegClasses()) {
if ((!VT || RC.hasType(*VT)) &&
RC.contains(Reg) && (!BestRC || BestRC->hasSubClass(&RC)))
if ((!VT || RC.hasType(*VT)) && RC.contains(Reg) &&
(!BestRC || BestRC->hasSubClass(&RC)))
BestRC = &RC;
}
@@ -2486,8 +2496,8 @@ CodeGenRegBank::getMinimalPhysRegClass(Record *RegRecord,
return BestRC;
}
BitVector CodeGenRegBank::computeCoveredRegisters(ArrayRef<Record*> Regs) {
SetVector<const CodeGenRegister*> Set;
BitVector CodeGenRegBank::computeCoveredRegisters(ArrayRef<Record *> Regs) {
SetVector<const CodeGenRegister *> Set;
// First add Regs with all sub-registers.
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {

File diff suppressed because it is too large Load Diff

View File

@@ -51,7 +51,7 @@ struct InstrsOp : public SetTheory::Operator {
// (instregex "OpcPat",...) Find all instructions matching an opcode pattern.
struct InstRegexOp : public SetTheory::Operator {
const CodeGenTarget &Target;
InstRegexOp(const CodeGenTarget &t): Target(t) {}
InstRegexOp(const CodeGenTarget &t) : Target(t) {}
/// Remove any text inside of parentheses from S.
static std::string removeParens(llvm::StringRef S) {
@@ -182,8 +182,8 @@ struct InstRegexOp : public SetTheory::Operator {
/// CodeGenModels ctor interprets machine model records and populates maps.
CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
const CodeGenTarget &TGT):
Records(RK), Target(TGT) {
const CodeGenTarget &TGT)
: Records(RK), Target(TGT) {
Sets.addFieldExpander("InstRW", "Instrs");
@@ -298,9 +298,8 @@ static APInt constructOperandMask(ArrayRef<int64_t> Indices) {
return OperandMask;
}
static void
processSTIPredicate(STIPredicateFunction &Fn,
const ProcModelMapTy &ProcModelMap) {
static void processSTIPredicate(STIPredicateFunction &Fn,
const ProcModelMapTy &ProcModelMap) {
DenseMap<const Record *, unsigned> Opcode2Index;
using OpcodeMapPair = std::pair<const Record *, OpcodeInfo>;
std::vector<OpcodeMapPair> OpcodeMappings;
@@ -380,30 +379,29 @@ processSTIPredicate(STIPredicateFunction &Fn,
// Sort OpcodeMappings elements based on their CPU and predicate masks.
// As a last resort, order elements by opcode identifier.
llvm::sort(OpcodeMappings,
[&](const OpcodeMapPair &Lhs, const OpcodeMapPair &Rhs) {
unsigned LhsIdx = Opcode2Index[Lhs.first];
unsigned RhsIdx = Opcode2Index[Rhs.first];
const std::pair<APInt, APInt> &LhsMasks = OpcodeMasks[LhsIdx];
const std::pair<APInt, APInt> &RhsMasks = OpcodeMasks[RhsIdx];
llvm::sort(
OpcodeMappings, [&](const OpcodeMapPair &Lhs, const OpcodeMapPair &Rhs) {
unsigned LhsIdx = Opcode2Index[Lhs.first];
unsigned RhsIdx = Opcode2Index[Rhs.first];
const std::pair<APInt, APInt> &LhsMasks = OpcodeMasks[LhsIdx];
const std::pair<APInt, APInt> &RhsMasks = OpcodeMasks[RhsIdx];
auto PopulationCountAndLeftBit =
[](const APInt &Other) -> std::pair<int, int> {
return std::pair<int, int>(Other.popcount(),
-Other.countl_zero());
};
auto lhsmask_first = PopulationCountAndLeftBit(LhsMasks.first);
auto rhsmask_first = PopulationCountAndLeftBit(RhsMasks.first);
if (lhsmask_first != rhsmask_first)
return lhsmask_first < rhsmask_first;
auto PopulationCountAndLeftBit =
[](const APInt &Other) -> std::pair<int, int> {
return std::pair<int, int>(Other.popcount(), -Other.countl_zero());
};
auto lhsmask_first = PopulationCountAndLeftBit(LhsMasks.first);
auto rhsmask_first = PopulationCountAndLeftBit(RhsMasks.first);
if (lhsmask_first != rhsmask_first)
return lhsmask_first < rhsmask_first;
auto lhsmask_second = PopulationCountAndLeftBit(LhsMasks.second);
auto rhsmask_second = PopulationCountAndLeftBit(RhsMasks.second);
if (lhsmask_second != rhsmask_second)
return lhsmask_second < rhsmask_second;
auto lhsmask_second = PopulationCountAndLeftBit(LhsMasks.second);
auto rhsmask_second = PopulationCountAndLeftBit(RhsMasks.second);
if (lhsmask_second != rhsmask_second)
return lhsmask_second < rhsmask_second;
return LhsIdx < RhsIdx;
});
return LhsIdx < RhsIdx;
});
// Now construct opcode groups. Groups are used by the SubtargetEmitter when
// expanding the body of a STIPredicate function. In particular, each opcode
@@ -498,8 +496,7 @@ void CodeGenSchedModels::collectLoadStoreQueueInfo() {
CodeGenProcModel &PM = getProcModel(Queue->getValueAsDef("SchedModel"));
if (Queue->isSubClassOf("LoadQueue")) {
if (PM.LoadQueue) {
PrintError(Queue->getLoc(),
"Expected a single LoadQueue definition");
PrintError(Queue->getLoc(), "Expected a single LoadQueue definition");
PrintNote(PM.LoadQueue->getLoc(),
"Previous definition of LoadQueue was here");
}
@@ -509,8 +506,7 @@ void CodeGenSchedModels::collectLoadStoreQueueInfo() {
if (Queue->isSubClassOf("StoreQueue")) {
if (PM.StoreQueue) {
PrintError(Queue->getLoc(),
"Expected a single StoreQueue definition");
PrintError(Queue->getLoc(), "Expected a single StoreQueue definition");
PrintNote(PM.StoreQueue->getLoc(),
"Previous definition of StoreQueue was here");
}
@@ -542,14 +538,15 @@ void CodeGenSchedModels::collectProcModels() {
// Check for duplicated names.
auto I = std::adjacent_find(ProcRecords.begin(), ProcRecords.end(),
[](const Record *Rec1, const Record *Rec2) {
return Rec1->getValueAsString("Name") == Rec2->getValueAsString("Name");
});
return Rec1->getValueAsString("Name") ==
Rec2->getValueAsString("Name");
});
if (I != ProcRecords.end())
PrintFatalError((*I)->getLoc(), "Duplicate processor name " +
(*I)->getValueAsString("Name"));
(*I)->getValueAsString("Name"));
// Reserve space because we can. Reallocation would be ok.
ProcModels.reserve(ProcRecords.size()+1);
ProcModels.reserve(ProcRecords.size() + 1);
// Use idx=0 for NoModel/NoItineraries.
Record *NoModelDef = Records.getDef("NoSchedModel");
@@ -574,8 +571,7 @@ void CodeGenSchedModels::addProcModel(Record *ProcDef) {
if (ModelKey->isSubClassOf("SchedMachineModel")) {
Record *ItinsDef = ModelKey->getValueAsDef("Itineraries");
ProcModels.emplace_back(ProcModels.size(), Name, ModelKey, ItinsDef);
}
else {
} else {
// An itinerary is defined without a machine model. Infer a new model.
if (!ModelKey->getValueAsListOfDefs("IID").empty())
Name = Name + "Model";
@@ -587,7 +583,7 @@ void CodeGenSchedModels::addProcModel(Record *ProcDef) {
// Recursively find all reachable SchedReadWrite records.
static void scanSchedRW(Record *RWDef, RecVec &RWDefs,
SmallPtrSet<Record*, 16> &RWSet) {
SmallPtrSet<Record *, 16> &RWSet) {
if (!RWSet.insert(RWDef).second)
return;
RWDefs.push_back(RWDef);
@@ -596,8 +592,7 @@ static void scanSchedRW(Record *RWDef, RecVec &RWDefs,
RecVec Seq = RWDef->getValueAsListOfDefs("Writes");
for (Record *WSRec : Seq)
scanSchedRW(WSRec, RWDefs, RWSet);
}
else if (RWDef->isSubClassOf("SchedVariant")) {
} else if (RWDef->isSubClassOf("SchedVariant")) {
// Visit each variant (guarded by a different predicate).
RecVec Vars = RWDef->getValueAsListOfDefs("Variants");
for (Record *Variant : Vars) {
@@ -616,7 +611,7 @@ void CodeGenSchedModels::collectSchedRW() {
SchedWrites.resize(1);
SchedReads.resize(1);
SmallPtrSet<Record*, 16> RWSet;
SmallPtrSet<Record *, 16> RWSet;
// Find all SchedReadWrites referenced by instruction defs.
RecVec SWDefs, SRDefs;
@@ -673,8 +668,7 @@ void CodeGenSchedModels::collectSchedRW() {
if (!AliasDef->isSubClassOf("SchedWrite"))
PrintFatalError(ADef->getLoc(), "SchedWrite Alias must be SchedWrite");
scanSchedRW(AliasDef, SWDefs, RWSet);
}
else {
} else {
assert(MatchDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
if (!AliasDef->isSubClassOf("SchedRead"))
PrintFatalError(ADef->getLoc(), "SchedRead Alias must be SchedRead");
@@ -690,7 +684,7 @@ void CodeGenSchedModels::collectSchedRW() {
}
llvm::sort(SRDefs, LessRecord());
for (Record *SRDef : SRDefs) {
assert(!getSchedRWIdx(SRDef, /*IsRead-*/true) && "duplicate SchedWrite");
assert(!getSchedRWIdx(SRDef, /*IsRead-*/ true) && "duplicate SchedWrite");
SchedReads.emplace_back(SchedReads.size(), SRDef);
}
// Initialize WriteSequence vectors.
@@ -753,9 +747,9 @@ unsigned CodeGenSchedModels::getSchedRWIdx(const Record *Def,
}
bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const {
for (auto& ProcModel : ProcModels) {
for (auto &ProcModel : ProcModels) {
const RecVec &RADefs = ProcModel.ReadAdvanceDefs;
for (auto& RADef : RADefs) {
for (auto &RADef : RADefs) {
RecVec ValidWrites = RADef->getValueAsListOfDefs("ValidWrites");
if (is_contained(ValidWrites, WriteDef))
return true;
@@ -764,8 +758,8 @@ bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const {
return false;
}
static void splitSchedReadWrites(const RecVec &RWDefs,
RecVec &WriteDefs, RecVec &ReadDefs) {
static void splitSchedReadWrites(const RecVec &RWDefs, RecVec &WriteDefs,
RecVec &ReadDefs) {
for (Record *RWDef : RWDefs) {
if (RWDef->isSubClassOf("SchedWrite"))
WriteDefs.push_back(RWDef);
@@ -777,8 +771,8 @@ static void splitSchedReadWrites(const RecVec &RWDefs,
}
// Split the SchedReadWrites defs and call findRWs for each list.
void CodeGenSchedModels::findRWs(const RecVec &RWDefs,
IdxVec &Writes, IdxVec &Reads) const {
void CodeGenSchedModels::findRWs(const RecVec &RWDefs, IdxVec &Writes,
IdxVec &Reads) const {
RecVec WriteDefs;
RecVec ReadDefs;
splitSchedReadWrites(RWDefs, WriteDefs, ReadDefs);
@@ -803,8 +797,7 @@ void CodeGenSchedModels::expandRWSequence(unsigned RWIdx, IdxVec &RWSeq,
RWSeq.push_back(RWIdx);
return;
}
int Repeat =
SchedRW.TheDef ? SchedRW.TheDef->getValueAsInt("Repeat") : 1;
int Repeat = SchedRW.TheDef ? SchedRW.TheDef->getValueAsInt("Repeat") : 1;
for (int i = 0; i < Repeat; ++i) {
for (unsigned I : SchedRW.Sequence) {
expandRWSequence(I, RWSeq, IsRead);
@@ -815,8 +808,8 @@ void CodeGenSchedModels::expandRWSequence(unsigned RWIdx, IdxVec &RWSeq,
// Expand a SchedWrite as a sequence following any aliases that coincide with
// the given processor model.
void CodeGenSchedModels::expandRWSeqForProc(
unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
const CodeGenProcModel &ProcModel) const {
unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
const CodeGenProcModel &ProcModel) const {
const CodeGenSchedRW &SchedWrite = getSchedRW(RWIdx, IsRead);
Record *AliasDef = nullptr;
@@ -828,14 +821,16 @@ void CodeGenSchedModels::expandRWSeqForProc(
continue;
}
if (AliasDef)
PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
"defined for processor " + ProcModel.ModelName +
" Ensure only one SchedAlias exists per RW.");
PrintFatalError(AliasRW.TheDef->getLoc(),
"Multiple aliases "
"defined for processor " +
ProcModel.ModelName +
" Ensure only one SchedAlias exists per RW.");
AliasDef = AliasRW.TheDef;
}
if (AliasDef) {
expandRWSeqForProc(getSchedRWIdx(AliasDef, IsRead),
RWSeq, IsRead,ProcModel);
expandRWSeqForProc(getSchedRWIdx(AliasDef, IsRead), RWSeq, IsRead,
ProcModel);
return;
}
if (!SchedWrite.IsSequence) {
@@ -843,7 +838,7 @@ void CodeGenSchedModels::expandRWSeqForProc(
return;
}
int Repeat =
SchedWrite.TheDef ? SchedWrite.TheDef->getValueAsInt("Repeat") : 1;
SchedWrite.TheDef ? SchedWrite.TheDef->getValueAsInt("Repeat") : 1;
for (int I = 0, E = Repeat; I < E; ++I) {
for (unsigned Idx : SchedWrite.Sequence) {
expandRWSeqForProc(Idx, RWSeq, IsRead, ProcModel);
@@ -888,8 +883,7 @@ void CodeGenSchedModels::collectSchedClasses() {
// NoItinerary is always the first class at Idx=0
assert(SchedClasses.empty() && "Expected empty sched class");
SchedClasses.emplace_back(0, "NoInstrModel",
Records.getDef("NoItinerary"));
SchedClasses.emplace_back(0, "NoInstrModel", Records.getDef("NoItinerary"));
SchedClasses.back().ProcIndices.push_back(0);
// Create a SchedClass for each unique combination of itinerary class and
@@ -901,7 +895,7 @@ void CodeGenSchedModels::collectSchedClasses() {
findRWs(Inst->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads);
// ProcIdx == 0 indicates the class applies to all processors.
unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, /*ProcIndices*/{0});
unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, /*ProcIndices*/ {0});
InstrClassMap[Inst->TheDef] = SCIdx;
}
// Create classes for InstRW defs.
@@ -933,7 +927,8 @@ void CodeGenSchedModels::collectSchedClasses() {
}
CodeGenSchedClass &SC = getSchedClass(SCIdx);
if (SC.ProcIndices[0] != 0)
PrintFatalError(Inst->TheDef->getLoc(), "Instruction's sched class "
PrintFatalError(Inst->TheDef->getLoc(),
"Instruction's sched class "
"must not be subtarget specific.");
IdxVec ProcIndices;
@@ -962,8 +957,7 @@ void CodeGenSchedModels::collectSchedClasses() {
<< InstName);
IdxVec Writes;
IdxVec Reads;
findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
Writes, Reads);
findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
LLVM_DEBUG({
for (unsigned WIdx : Writes)
dbgs() << " " << SchedWrites[WIdx].Name;
@@ -1032,25 +1026,23 @@ unsigned CodeGenSchedModels::addSchedClass(Record *ItinClassDef,
assert(!ProcIndices.empty() && "expect at least one ProcIdx");
auto IsKeyEqual = [=](const CodeGenSchedClass &SC) {
return SC.isKeyEqual(ItinClassDef, OperWrites, OperReads);
};
return SC.isKeyEqual(ItinClassDef, OperWrites, OperReads);
};
auto I = find_if(make_range(schedClassBegin(), schedClassEnd()), IsKeyEqual);
unsigned Idx = I == schedClassEnd() ? 0 : std::distance(schedClassBegin(), I);
if (Idx || SchedClasses[0].isKeyEqual(ItinClassDef, OperWrites, OperReads)) {
IdxVec PI;
std::set_union(SchedClasses[Idx].ProcIndices.begin(),
SchedClasses[Idx].ProcIndices.end(),
ProcIndices.begin(), ProcIndices.end(),
std::back_inserter(PI));
SchedClasses[Idx].ProcIndices.end(), ProcIndices.begin(),
ProcIndices.end(), std::back_inserter(PI));
SchedClasses[Idx].ProcIndices = std::move(PI);
return Idx;
}
Idx = SchedClasses.size();
SchedClasses.emplace_back(Idx,
createSchedClassName(ItinClassDef, OperWrites,
OperReads),
ItinClassDef);
SchedClasses.emplace_back(
Idx, createSchedClassName(ItinClassDef, OperWrites, OperReads),
ItinClassDef);
CodeGenSchedClass &SC = SchedClasses.back();
SC.Writes = OperWrites;
SC.Reads = OperReads;
@@ -1083,17 +1075,16 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
// the Instrs to it.
for (auto &Entry : ClassInstrs) {
unsigned OldSCIdx = Entry.first;
ArrayRef<Record*> InstDefs = Entry.second;
ArrayRef<Record *> InstDefs = Entry.second;
// If the all instrs in the current class are accounted for, then leave
// them mapped to their old class.
if (OldSCIdx) {
const RecVec &RWDefs = SchedClasses[OldSCIdx].InstRWs;
if (!RWDefs.empty()) {
const RecVec *OrigInstDefs = Sets.expand(RWDefs[0]);
unsigned OrigNumInstrs =
count_if(*OrigInstDefs, [&](Record *OIDef) {
return InstrClassMap[OIDef] == OldSCIdx;
});
unsigned OrigNumInstrs = count_if(*OrigInstDefs, [&](Record *OIDef) {
return InstrClassMap[OIDef] == OldSCIdx;
});
if (OrigNumInstrs == InstDefs.size()) {
assert(SchedClasses[OldSCIdx].ProcIndices[0] == 0 &&
"expected a generic SchedClass");
@@ -1148,8 +1139,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
"\".");
PrintFatalNote(OldRWDef->getLoc(), "Previous match was here.");
}
assert(OldRWDef != InstRWDef &&
"SchedClass has duplicate InstRW def");
assert(OldRWDef != InstRWDef && "SchedClass has duplicate InstRW def");
SC.InstRWs.push_back(OldRWDef);
}
}
@@ -1162,7 +1152,8 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
// True if collectProcItins found anything.
bool CodeGenSchedModels::hasItineraries() const {
for (const CodeGenProcModel &PM : make_range(procModelBegin(),procModelEnd()))
for (const CodeGenProcModel &PM :
make_range(procModelBegin(), procModelEnd()))
if (PM.hasItineraries())
return true;
return false;
@@ -1217,14 +1208,14 @@ void CodeGenSchedModels::collectProcItins() {
void CodeGenSchedModels::collectProcItinRW() {
RecVec ItinRWDefs = Records.getAllDerivedDefinitions("ItinRW");
llvm::sort(ItinRWDefs, LessRecord());
for (Record *RWDef : ItinRWDefs) {
for (Record *RWDef : ItinRWDefs) {
if (!RWDef->getValueInit("SchedModel")->isComplete())
PrintFatalError(RWDef->getLoc(), "SchedModel is undefined");
Record *ModelDef = RWDef->getValueAsDef("SchedModel");
ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
if (I == ProcModelMap.end()) {
PrintFatalError(RWDef->getLoc(), "Undefined SchedMachineModel "
+ ModelDef->getName());
PrintFatalError(RWDef->getLoc(),
"Undefined SchedMachineModel " + ModelDef->getName());
}
ProcModels[I->second].ItinRWDefs.push_back(RWDef);
}
@@ -1254,10 +1245,10 @@ void CodeGenSchedModels::inferSchedClasses() {
if (!SchedClasses[Idx].InstRWs.empty())
inferFromInstRWs(Idx);
if (!SchedClasses[Idx].Writes.empty()) {
inferFromRW(SchedClasses[Idx].Writes, SchedClasses[Idx].Reads,
Idx, SchedClasses[Idx].ProcIndices);
inferFromRW(SchedClasses[Idx].Writes, SchedClasses[Idx].Reads, Idx,
SchedClasses[Idx].ProcIndices);
}
assert(SchedClasses.size() < (NumInstrSchedClasses*6) &&
assert(SchedClasses.size() < (NumInstrSchedClasses * 6) &&
"too many SchedVariants");
}
}
@@ -1274,9 +1265,9 @@ void CodeGenSchedModels::inferFromItinClass(Record *ItinClassDef,
if (!llvm::is_contained(Matched, ItinClassDef))
continue;
if (HasMatch)
PrintFatalError(Rec->getLoc(), "Duplicate itinerary class "
+ ItinClassDef->getName()
+ " in ItinResources for " + PM.ModelName);
PrintFatalError(Rec->getLoc(),
"Duplicate itinerary class " + ItinClassDef->getName() +
" in ItinResources for " + PM.ModelName);
HasMatch = true;
IdxVec Writes, Reads;
findRWs(Rec->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
@@ -1317,8 +1308,8 @@ struct TransVariant {
unsigned ProcIdx; // Processor model index or zero for any.
unsigned TransVecIdx; // Index into PredTransitions::TransVec.
TransVariant(Record *def, unsigned rwi, unsigned pi, unsigned ti):
VarOrSeqDef(def), RWIdx(rwi), ProcIdx(pi), TransVecIdx(ti) {}
TransVariant(Record *def, unsigned rwi, unsigned pi, unsigned ti)
: VarOrSeqDef(def), RWIdx(rwi), ProcIdx(pi), TransVecIdx(ti) {}
};
// Associate a predicate with the SchedReadWrite that it guards.
@@ -1328,15 +1319,16 @@ struct PredCheck {
unsigned RWIdx;
Record *Predicate;
PredCheck(bool r, unsigned w, Record *p): IsRead(r), RWIdx(w), Predicate(p) {}
PredCheck(bool r, unsigned w, Record *p)
: IsRead(r), RWIdx(w), Predicate(p) {}
};
// A Predicate transition is a list of RW sequences guarded by a PredTerm.
struct PredTransition {
// A predicate term is a conjunction of PredChecks.
SmallVector<PredCheck, 4> PredTerm;
SmallVector<SmallVector<unsigned,4>, 16> WriteSequences;
SmallVector<SmallVector<unsigned,4>, 16> ReadSequences;
SmallVector<SmallVector<unsigned, 4>, 16> WriteSequences;
SmallVector<SmallVector<unsigned, 4>, 16> ReadSequences;
unsigned ProcIndex = 0;
PredTransition() = default;
@@ -1354,7 +1346,7 @@ class PredTransitions {
public:
std::vector<PredTransition> TransVec;
PredTransitions(CodeGenSchedModels &sm): SchedModels(sm) {}
PredTransitions(CodeGenSchedModels &sm) : SchedModels(sm) {}
bool substituteVariantOperand(const SmallVectorImpl<unsigned> &RWSeq,
bool IsRead, unsigned StartIdx);
@@ -1368,9 +1360,8 @@ public:
private:
bool mutuallyExclusive(Record *PredDef, ArrayRef<Record *> Preds,
ArrayRef<PredCheck> Term);
void getIntersectingVariants(
const CodeGenSchedRW &SchedRW, unsigned TransIdx,
std::vector<TransVariant> &IntersectingVariants);
void getIntersectingVariants(const CodeGenSchedRW &SchedRW, unsigned TransIdx,
std::vector<TransVariant> &IntersectingVariants);
void pushVariant(const TransVariant &VInfo, bool IsRead);
};
@@ -1388,7 +1379,7 @@ private:
bool PredTransitions::mutuallyExclusive(Record *PredDef,
ArrayRef<Record *> Preds,
ArrayRef<PredCheck> Term) {
for (const PredCheck &PC: Term) {
for (const PredCheck &PC : Term) {
if (PC.Predicate == PredDef)
return false;
@@ -1446,8 +1437,8 @@ static std::vector<Record *> getAllPredicates(ArrayRef<TransVariant> Variants,
// given SchedRW whose processor indices and predicates are not mutually
// exclusive with the given transition.
void PredTransitions::getIntersectingVariants(
const CodeGenSchedRW &SchedRW, unsigned TransIdx,
std::vector<TransVariant> &IntersectingVariants) {
const CodeGenSchedRW &SchedRW, unsigned TransIdx,
std::vector<TransVariant> &IntersectingVariants) {
bool GenericRW = false;
@@ -1489,7 +1480,7 @@ void PredTransitions::getIntersectingVariants(
}
const CodeGenSchedRW &AliasRW =
SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
if (AliasRW.HasVariants) {
const RecVec VarDefs = AliasRW.TheDef->getValueAsListOfDefs("Variants");
@@ -1516,8 +1507,7 @@ void PredTransitions::getIntersectingVariants(
// The first variant builds on the existing transition.
Variant.TransVecIdx = TransIdx;
IntersectingVariants.push_back(Variant);
}
else {
} else {
// Push another copy of the current transition for more variants.
Variant.TransVecIdx = TransVec.size();
IntersectingVariants.push_back(Variant);
@@ -1525,15 +1515,15 @@ void PredTransitions::getIntersectingVariants(
}
}
if (GenericRW && IntersectingVariants.empty()) {
PrintFatalError(SchedRW.TheDef->getLoc(), "No variant of this type has "
PrintFatalError(SchedRW.TheDef->getLoc(),
"No variant of this type has "
"a matching predicate on any processor");
}
}
// Push the Reads/Writes selected by this variant onto the PredTransition
// specified by VInfo.
void PredTransitions::
pushVariant(const TransVariant &VInfo, bool IsRead) {
void PredTransitions::pushVariant(const TransVariant &VInfo, bool IsRead) {
PredTransition &Trans = TransVec[VInfo.TransVecIdx];
// If this operand transition is reached through a processor-specific alias,
@@ -1541,11 +1531,10 @@ pushVariant(const TransVariant &VInfo, bool IsRead) {
IdxVec SelectedRWs;
if (VInfo.VarOrSeqDef->isSubClassOf("SchedVar")) {
Record *PredDef = VInfo.VarOrSeqDef->getValueAsDef("Predicate");
Trans.PredTerm.emplace_back(IsRead, VInfo.RWIdx,PredDef);
Trans.PredTerm.emplace_back(IsRead, VInfo.RWIdx, PredDef);
RecVec SelectedDefs = VInfo.VarOrSeqDef->getValueAsListOfDefs("Selected");
SchedModels.findRWs(SelectedDefs, SelectedRWs, IsRead);
}
else {
} else {
assert(VInfo.VarOrSeqDef->isSubClassOf("WriteSequence") &&
"variant must be a SchedVariant or aliased WriteSequence");
SelectedRWs.push_back(SchedModels.getSchedRWIdx(VInfo.VarOrSeqDef, IsRead));
@@ -1553,10 +1542,10 @@ pushVariant(const TransVariant &VInfo, bool IsRead) {
const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(VInfo.RWIdx, IsRead);
SmallVectorImpl<SmallVector<unsigned,4>> &RWSequences = IsRead
? Trans.ReadSequences : Trans.WriteSequences;
SmallVectorImpl<SmallVector<unsigned, 4>> &RWSequences =
IsRead ? Trans.ReadSequences : Trans.WriteSequences;
if (SchedRW.IsVariadic) {
unsigned OperIdx = RWSequences.size()-1;
unsigned OperIdx = RWSequences.size() - 1;
// Make N-1 copies of this transition's last sequence.
RWSequences.reserve(RWSequences.size() + SelectedRWs.size() - 1);
RWSequences.insert(RWSequences.end(), SelectedRWs.size() - 1,
@@ -1565,8 +1554,8 @@ pushVariant(const TransVariant &VInfo, bool IsRead) {
// sequence (split the current operand into N operands).
// Note that write sequences should be expanded within this loop--the entire
// sequence belongs to a single operand.
for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end();
RWI != RWE; ++RWI, ++OperIdx) {
for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end(); RWI != RWE;
++RWI, ++OperIdx) {
IdxVec ExpandedRWs;
if (IsRead)
ExpandedRWs.push_back(*RWI);
@@ -1575,8 +1564,7 @@ pushVariant(const TransVariant &VInfo, bool IsRead) {
llvm::append_range(RWSequences[OperIdx], ExpandedRWs);
}
assert(OperIdx == RWSequences.size() && "missed a sequence");
}
else {
} else {
// Push this transition's expanded sequence onto this transition's last
// sequence (add to the current operand's sequence).
SmallVectorImpl<unsigned> &Seq = RWSequences.back();
@@ -1644,8 +1632,9 @@ bool PredTransitions::substituteVariants(const PredTransition &Trans) {
// Visit each original write sequence.
for (const auto &WriteSequence : Trans.WriteSequences) {
// Push a new (empty) write sequence onto all partial Transitions.
for (std::vector<PredTransition>::iterator I =
TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) {
for (std::vector<PredTransition>::iterator I = TransVec.begin() + StartIdx,
E = TransVec.end();
I != E; ++I) {
I->WriteSequences.emplace_back();
}
Subst |=
@@ -1654,8 +1643,9 @@ bool PredTransitions::substituteVariants(const PredTransition &Trans) {
// Visit each original read sequence.
for (const auto &ReadSequence : Trans.ReadSequences) {
// Push a new (empty) read sequence onto all partial Transitions.
for (std::vector<PredTransition>::iterator I =
TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) {
for (std::vector<PredTransition>::iterator I = TransVec.begin() + StartIdx,
E = TransVec.end();
I != E; ++I) {
I->ReadSequences.emplace_back();
}
Subst |= substituteVariantOperand(ReadSequence, /*IsRead=*/true, StartIdx);
@@ -1814,7 +1804,7 @@ bool CodeGenSchedModels::hasSuperGroup(RecVec &SubUnits, CodeGenProcModel &PM) {
continue;
RecVec SuperUnits = ProcResourceDef->getValueAsListOfDefs("Resources");
RecIter RI = SubUnits.begin(), RE = SubUnits.end();
for ( ; RI != RE; ++RI) {
for (; RI != RE; ++RI) {
if (!is_contained(SuperUnits, *RI)) {
break;
}
@@ -1831,22 +1821,22 @@ void CodeGenSchedModels::verifyProcResourceGroups(CodeGenProcModel &PM) {
if (!PM.ProcResourceDefs[i]->isSubClassOf("ProcResGroup"))
continue;
RecVec CheckUnits =
PM.ProcResourceDefs[i]->getValueAsListOfDefs("Resources");
for (unsigned j = i+1; j < e; ++j) {
PM.ProcResourceDefs[i]->getValueAsListOfDefs("Resources");
for (unsigned j = i + 1; j < e; ++j) {
if (!PM.ProcResourceDefs[j]->isSubClassOf("ProcResGroup"))
continue;
RecVec OtherUnits =
PM.ProcResourceDefs[j]->getValueAsListOfDefs("Resources");
PM.ProcResourceDefs[j]->getValueAsListOfDefs("Resources");
if (std::find_first_of(CheckUnits.begin(), CheckUnits.end(),
OtherUnits.begin(), OtherUnits.end())
!= CheckUnits.end()) {
OtherUnits.begin(),
OtherUnits.end()) != CheckUnits.end()) {
// CheckUnits and OtherUnits overlap
llvm::append_range(OtherUnits, CheckUnits);
if (!hasSuperGroup(OtherUnits, PM)) {
PrintFatalError((PM.ProcResourceDefs[i])->getLoc(),
"proc resource group overlaps with "
+ PM.ProcResourceDefs[j]->getName()
+ " but no supergroup contains both.");
"proc resource group overlaps with " +
PM.ProcResourceDefs[j]->getName() +
" but no supergroup contains both.");
}
}
}
@@ -1862,7 +1852,7 @@ void CodeGenSchedModels::collectRegisterFiles() {
// For each register file definition, construct a CodeGenRegisterFile object
// and add it to the appropriate scheduling model.
CodeGenProcModel &PM = getProcModel(RF->getValueAsDef("SchedModel"));
PM.RegisterFiles.emplace_back(CodeGenRegisterFile(RF->getName(),RF));
PM.RegisterFiles.emplace_back(CodeGenRegisterFile(RF->getName(), RF));
CodeGenRegisterFile &CGRF = PM.RegisterFiles.back();
CGRF.MaxMovesEliminatedPerCycle =
RF->getValueAsInt("MaxMovesEliminatedPerCycle");
@@ -2013,7 +2003,7 @@ void CodeGenSchedModels::checkCompleteness() {
PrintError(Inst->TheDef->getLoc(),
"No schedule information for instruction '" +
Inst->TheDef->getName() + "' in SchedMachineModel '" +
ProcModel.ModelDef->getName() + "'");
ProcModel.ModelDef->getName() + "'");
Complete = false;
}
continue;
@@ -2039,14 +2029,18 @@ void CodeGenSchedModels::checkCompleteness() {
}
}
if (!Complete) {
errs() << "\n\nIncomplete schedule models found.\n"
<< "- Consider setting 'CompleteModel = 0' while developing new models.\n"
<< "- Pseudo instructions can be marked with 'hasNoSchedulingInfo = 1'.\n"
<< "- Instructions should usually have Sched<[...]> as a superclass, "
"you may temporarily use an empty list.\n"
<< "- Instructions related to unsupported features can be excluded with "
"list<Predicate> UnsupportedFeatures = [HasA,..,HasY]; in the "
"processor model.\n\n";
errs()
<< "\n\nIncomplete schedule models found.\n"
<< "- Consider setting 'CompleteModel = 0' while developing new "
"models.\n"
<< "- Pseudo instructions can be marked with 'hasNoSchedulingInfo = "
"1'.\n"
<< "- Instructions should usually have Sched<[...]> as a superclass, "
"you may temporarily use an empty list.\n"
<< "- Instructions related to unsupported features can be excluded "
"with "
"list<Predicate> UnsupportedFeatures = [HasA,..,HasY]; in the "
"processor model.\n\n";
PrintFatalError("Incomplete schedule model");
}
}
@@ -2057,15 +2051,15 @@ void CodeGenSchedModels::collectItinProcResources(Record *ItinClassDef) {
const CodeGenProcModel &PM = ProcModels[PIdx];
// For all ItinRW entries.
bool HasMatch = false;
for (RecIter II = PM.ItinRWDefs.begin(), IE = PM.ItinRWDefs.end();
II != IE; ++II) {
for (RecIter II = PM.ItinRWDefs.begin(), IE = PM.ItinRWDefs.end(); II != IE;
++II) {
RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
if (!llvm::is_contained(Matched, ItinClassDef))
continue;
if (HasMatch)
PrintFatalError((*II)->getLoc(), "Duplicate itinerary class "
+ ItinClassDef->getName()
+ " in ItinResources for " + PM.ModelName);
PrintFatalError((*II)->getLoc(),
"Duplicate itinerary class " + ItinClassDef->getName() +
" in ItinResources for " + PM.ModelName);
HasMatch = true;
IdxVec Writes, Reads;
findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
@@ -2081,8 +2075,7 @@ void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead,
if (!IsRead && SchedRW.TheDef->isSubClassOf("SchedWriteRes")) {
for (unsigned Idx : ProcIndices)
addWriteRes(SchedRW.TheDef, Idx);
}
else if (IsRead && SchedRW.TheDef->isSubClassOf("SchedReadAdvance")) {
} else if (IsRead && SchedRW.TheDef->isSubClassOf("SchedReadAdvance")) {
for (unsigned Idx : ProcIndices)
addReadAdvance(SchedRW.TheDef, Idx);
}
@@ -2128,31 +2121,30 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
assert(!ProcResGroups.empty());
for (Record *ProcResDef : ProcResourceDefs) {
if (ProcResDef->getValueAsDef("Kind") == ProcResKind
&& ProcResDef->getValueAsDef("SchedModel") == PM.ModelDef) {
if (ProcResDef->getValueAsDef("Kind") == ProcResKind &&
ProcResDef->getValueAsDef("SchedModel") == PM.ModelDef) {
if (ProcUnitDef) {
PrintFatalError(Loc,
"Multiple ProcessorResourceUnits associated with "
+ ProcResKind->getName());
"Multiple ProcessorResourceUnits associated with " +
ProcResKind->getName());
}
ProcUnitDef = ProcResDef;
}
}
for (Record *ProcResGroup : ProcResGroups) {
if (ProcResGroup == ProcResKind
&& ProcResGroup->getValueAsDef("SchedModel") == PM.ModelDef) {
if (ProcResGroup == ProcResKind &&
ProcResGroup->getValueAsDef("SchedModel") == PM.ModelDef) {
if (ProcUnitDef) {
PrintFatalError(Loc,
"Multiple ProcessorResourceUnits associated with "
+ ProcResKind->getName());
"Multiple ProcessorResourceUnits associated with " +
ProcResKind->getName());
}
ProcUnitDef = ProcResGroup;
}
}
if (!ProcUnitDef) {
PrintFatalError(Loc,
"No ProcessorResources associated with "
+ ProcResKind->getName());
PrintFatalError(Loc, "No ProcessorResources associated with " +
ProcResKind->getName());
}
return ProcUnitDef;
}
@@ -2208,14 +2200,16 @@ unsigned CodeGenProcModel::getProcResourceIdx(Record *PRDef) const {
RecIter PRPos = find(ProcResourceDefs, PRDef);
if (PRPos == ProcResourceDefs.end())
PrintFatalError(PRDef->getLoc(), "ProcResource def is not included in "
"the ProcResources list for " + ModelName);
"the ProcResources list for " +
ModelName);
// Idx=0 is reserved for invalid.
return 1 + (PRPos - ProcResourceDefs.begin());
}
bool CodeGenProcModel::isUnsupported(const CodeGenInstruction &Inst) const {
for (const Record *TheDef : UnsupportedFeaturesDefs) {
for (const Record *PredDef : Inst.TheDef->getValueAsListOfDefs("Predicates")) {
for (const Record *PredDef :
Inst.TheDef->getValueAsListOfDefs("Predicates")) {
if (TheDef->getName() == PredDef->getName())
return true;
}
@@ -2239,12 +2233,11 @@ void CodeGenSchedRW::dump() const {
}
}
void CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const {
dbgs() << "SCHEDCLASS " << Index << ":" << Name << '\n'
<< " Writes: ";
void CodeGenSchedClass::dump(const CodeGenSchedModels *SchedModels) const {
dbgs() << "SCHEDCLASS " << Index << ":" << Name << '\n' << " Writes: ";
for (unsigned i = 0, N = Writes.size(); i < N; ++i) {
SchedModels->getSchedWrite(Writes[i]).dump();
if (i < N-1) {
if (i < N - 1) {
dbgs() << '\n';
dbgs().indent(10);
}
@@ -2252,12 +2245,13 @@ void CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const {
dbgs() << "\n Reads: ";
for (unsigned i = 0, N = Reads.size(); i < N; ++i) {
SchedModels->getSchedRead(Reads[i]).dump();
if (i < N-1) {
if (i < N - 1) {
dbgs() << '\n';
dbgs().indent(10);
}
}
dbgs() << "\n ProcIdx: "; dumpIdxVec(ProcIndices);
dbgs() << "\n ProcIdx: ";
dumpIdxVec(ProcIndices);
if (!Transitions.empty()) {
dbgs() << "\n Transitions for Proc ";
for (const CodeGenSchedTransition &Transition : Transitions) {

View File

@@ -33,8 +33,8 @@ class CodeGenTarget;
class CodeGenSchedModels;
class CodeGenInstruction;
using RecVec = std::vector<Record*>;
using RecIter = std::vector<Record*>::const_iterator;
using RecVec = std::vector<Record *>;
using RecIter = std::vector<Record *>::const_iterator;
using IdxVec = std::vector<unsigned>;
using IdxIter = std::vector<unsigned>::const_iterator;
@@ -59,10 +59,10 @@ struct CodeGenSchedRW {
RecVec Aliases;
CodeGenSchedRW()
: Index(0), TheDef(nullptr), IsRead(false), IsAlias(false),
HasVariants(false), IsVariadic(false), IsSequence(false) {}
: Index(0), TheDef(nullptr), IsRead(false), IsAlias(false),
HasVariants(false), IsVariadic(false), IsSequence(false) {}
CodeGenSchedRW(unsigned Idx, Record *Def)
: Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) {
: Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) {
Name = std::string(Def->getName());
IsRead = Def->isSubClassOf("SchedRead");
HasVariants = Def->isSubClassOf("SchedVariant");
@@ -148,7 +148,7 @@ struct CodeGenSchedClass {
DenseSet<unsigned> InstRWProcIndices;
CodeGenSchedClass(unsigned Index, std::string Name, Record *ItinClassDef)
: Index(Index), Name(std::move(Name)), ItinClassDef(ItinClassDef) {}
: Index(Index), Name(std::move(Name)), ItinClassDef(ItinClassDef) {}
bool isKeyEqual(Record *IC, ArrayRef<unsigned> W,
ArrayRef<unsigned> R) const {
@@ -173,7 +173,8 @@ struct CodeGenRegisterCost {
Record *RCDef;
unsigned Cost;
bool AllowMoveElimination;
CodeGenRegisterCost(Record *RC, unsigned RegisterCost, bool AllowMoveElim = false)
CodeGenRegisterCost(Record *RC, unsigned RegisterCost,
bool AllowMoveElim = false)
: RCDef(RC), Cost(RegisterCost), AllowMoveElimination(AllowMoveElim) {}
CodeGenRegisterCost(const CodeGenRegisterCost &) = default;
CodeGenRegisterCost &operator=(const CodeGenRegisterCost &) = delete;
@@ -193,12 +194,12 @@ struct CodeGenRegisterFile {
unsigned NumPhysRegs;
std::vector<CodeGenRegisterCost> Costs;
CodeGenRegisterFile(StringRef name, Record *def, unsigned MaxMoveElimPerCy = 0,
CodeGenRegisterFile(StringRef name, Record *def,
unsigned MaxMoveElimPerCy = 0,
bool AllowZeroMoveElimOnly = false)
: Name(name), RegisterFileDef(def),
MaxMovesEliminatedPerCycle(MaxMoveElimPerCy),
AllowZeroMoveEliminationOnly(AllowZeroMoveElimOnly),
NumPhysRegs(0) {}
AllowZeroMoveEliminationOnly(AllowZeroMoveElimOnly), NumPhysRegs(0) {}
bool hasDefaultCosts() const { return Costs.empty(); }
};
@@ -255,10 +256,9 @@ struct CodeGenProcModel {
Record *LoadQueue;
Record *StoreQueue;
CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef,
Record *IDef) :
Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),
RetireControlUnit(nullptr), LoadQueue(nullptr), StoreQueue(nullptr) {}
CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef, Record *IDef)
: Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),
RetireControlUnit(nullptr), LoadQueue(nullptr), StoreQueue(nullptr) {}
bool hasItineraries() const {
return !ItinsDef->getValueAsListOfDefs("IID").empty();
@@ -443,14 +443,14 @@ class CodeGenSchedModels {
// Map each instruction to its unique SchedClass index considering the
// combination of it's itinerary class, SchedRW list, and InstRW records.
using InstClassMapTy = DenseMap<Record*, unsigned>;
using InstClassMapTy = DenseMap<Record *, unsigned>;
InstClassMapTy InstrClassMap;
std::vector<STIPredicateFunction> STIPredicates;
std::vector<unsigned> getAllProcIndices() const;
public:
CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT);
CodeGenSchedModels(RecordKeeper &RK, const CodeGenTarget &TGT);
// iterator access to the scheduling classes.
using class_iterator = std::vector<CodeGenSchedClass>::iterator;
@@ -460,10 +460,10 @@ public:
class_iterator classes_end() { return SchedClasses.end(); }
const_class_iterator classes_end() const { return SchedClasses.end(); }
iterator_range<class_iterator> classes() {
return make_range(classes_begin(), classes_end());
return make_range(classes_begin(), classes_end());
}
iterator_range<const_class_iterator> classes() const {
return make_range(classes_begin(), classes_end());
return make_range(classes_begin(), classes_end());
}
iterator_range<class_iterator> explicit_classes() {
return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses);
@@ -476,8 +476,8 @@ public:
Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");
if (!ItinsDef->getValueAsListOfDefs("IID").empty()) {
assert(ModelDef->getValueAsBit("NoModel")
&& "Itineraries must be defined within SchedMachineModel");
assert(ModelDef->getValueAsBit("NoModel") &&
"Itineraries must be defined within SchedMachineModel");
return ItinsDef;
}
return ModelDef;
@@ -496,7 +496,7 @@ public:
return ProcModels[I->second];
}
const CodeGenProcModel &getProcModel(Record *ModelDef) const {
return const_cast<CodeGenSchedModels*>(this)->getProcModel(ModelDef);
return const_cast<CodeGenSchedModels *>(this)->getProcModel(ModelDef);
}
// Iterate over the unique processor models.
@@ -527,11 +527,11 @@ public:
CodeGenSchedRW &getSchedRW(Record *Def) {
bool IsRead = Def->isSubClassOf("SchedRead");
unsigned Idx = getSchedRWIdx(Def, IsRead);
return const_cast<CodeGenSchedRW&>(
IsRead ? getSchedRead(Idx) : getSchedWrite(Idx));
return const_cast<CodeGenSchedRW &>(IsRead ? getSchedRead(Idx)
: getSchedWrite(Idx));
}
const CodeGenSchedRW &getSchedRW(Record *Def) const {
return const_cast<CodeGenSchedModels&>(*this).getSchedRW(Def);
return const_cast<CodeGenSchedModels &>(*this).getSchedRW(Def);
}
unsigned getSchedRWIdx(const Record *Def, bool IsRead) const;
@@ -579,6 +579,7 @@ public:
ArrayRef<STIPredicateFunction> getSTIPredicates() const {
return STIPredicates;
}
private:
void collectProcModels();

View File

@@ -49,10 +49,14 @@ MVT::SimpleValueType llvm::getValueType(const Record *Rec) {
StringRef llvm::getName(MVT::SimpleValueType T) {
switch (T) {
case MVT::Other: return "UNKNOWN";
case MVT::iPTR: return "TLI.getPointerTy()";
case MVT::iPTRAny: return "TLI.getPointerTy()";
default: return getEnumName(T);
case MVT::Other:
return "UNKNOWN";
case MVT::iPTR:
return "TLI.getPointerTy()";
case MVT::iPTRAny:
return "TLI.getPointerTy()";
default:
return getEnumName(T);
}
}
@@ -280,12 +284,11 @@ std::string llvm::getQualifiedName(const Record *R) {
return Namespace + "::" + R->getName().str();
}
/// getTarget - Return the current instance of the Target class.
///
CodeGenTarget::CodeGenTarget(RecordKeeper &records)
: Records(records), CGH(records) {
std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
: Records(records), CGH(records) {
std::vector<Record *> Targets = Records.getAllDerivedDefinitions("Target");
if (Targets.size() == 0)
PrintFatalError("No 'Target' subclasses defined!");
if (Targets.size() != 1)
@@ -294,8 +297,7 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records)
MacroFusions = Records.getAllDerivedDefinitions("Fusion");
}
CodeGenTarget::~CodeGenTarget() {
}
CodeGenTarget::~CodeGenTarget() {}
StringRef CodeGenTarget::getName() const { return TargetRec->getName(); }
@@ -331,7 +333,7 @@ bool CodeGenTarget::getAllowRegisterRenaming() const {
/// getAsmParser - Return the AssemblyParser definition for this target.
///
Record *CodeGenTarget::getAsmParser() const {
std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
std::vector<Record *> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
if (AsmParserNum >= LI.size())
PrintFatalError("Target does not have an AsmParser #" +
Twine(AsmParserNum) + "!");
@@ -342,8 +344,8 @@ Record *CodeGenTarget::getAsmParser() const {
/// this target.
///
Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
std::vector<Record*> LI =
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
std::vector<Record *> LI =
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
if (i >= LI.size())
PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) +
"!");
@@ -354,15 +356,15 @@ Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
/// available for this target.
///
unsigned CodeGenTarget::getAsmParserVariantCount() const {
std::vector<Record*> LI =
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
std::vector<Record *> LI =
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
return LI.size();
}
/// getAsmWriter - Return the AssemblyWriter definition for this target.
///
Record *CodeGenTarget::getAsmWriter() const {
std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
std::vector<Record *> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
if (AsmWriterNum >= LI.size())
PrintFatalError("Target does not have an AsmWriter #" +
Twine(AsmWriterNum) + "!");
@@ -437,8 +439,7 @@ const CodeGenRegisterClass &CodeGenTarget::getRegisterClass(Record *R) const {
return *getRegBank().getRegClass(R);
}
std::vector<ValueTypeByHwMode> CodeGenTarget::getRegisterVTs(Record *R)
const {
std::vector<ValueTypeByHwMode> CodeGenTarget::getRegisterVTs(Record *R) const {
const CodeGenRegister *Reg = getRegBank().getReg(R);
std::vector<ValueTypeByHwMode> Result;
for (const auto &RC : getRegBank().getRegClasses()) {
@@ -454,16 +455,15 @@ std::vector<ValueTypeByHwMode> CodeGenTarget::getRegisterVTs(Record *R)
return Result;
}
void CodeGenTarget::ReadLegalValueTypes() const {
for (const auto &RC : getRegBank().getRegClasses())
llvm::append_range(LegalValueTypes, RC.VTs);
// Remove duplicates.
llvm::sort(LegalValueTypes);
LegalValueTypes.erase(std::unique(LegalValueTypes.begin(),
LegalValueTypes.end()),
LegalValueTypes.end());
LegalValueTypes.erase(
std::unique(LegalValueTypes.begin(), LegalValueTypes.end()),
LegalValueTypes.end());
}
CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
@@ -473,7 +473,7 @@ CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
}
void CodeGenTarget::ReadInstructions() const {
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
if (Insts.size() <= 2)
PrintFatalError("No 'Instruction' subclasses defined!");
@@ -482,11 +482,10 @@ void CodeGenTarget::ReadInstructions() const {
Instructions[Insts[i]] = std::make_unique<CodeGenInstruction>(Insts[i]);
}
static const CodeGenInstruction *
GetInstByName(const char *Name,
const DenseMap<const Record*,
std::unique_ptr<CodeGenInstruction>> &Insts,
RecordKeeper &Records) {
static const CodeGenInstruction *GetInstByName(
const char *Name,
const DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> &Insts,
RecordKeeper &Records) {
const Record *Rec = Records.getDef(Name);
const auto I = Insts.find(Rec);
@@ -545,7 +544,6 @@ void CodeGenTarget::ComputeInstrsByEnum() const {
Inst->EnumVal = Num++;
}
/// isLittleEndianEncoding - Return whether this target encodes its instruction
/// in little-endian format, i.e. bits laid out in the order [0..n]
///
@@ -576,7 +574,7 @@ void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
unsigned bitSwapIdx = numBits - bit - 1;
Init *OrigBit = BI->getBit(bit);
Init *BitSwap = BI->getBit(bitSwapIdx);
NewBits[bit] = BitSwap;
NewBits[bit] = BitSwap;
NewBits[bitSwapIdx] = OrigBit;
}
if (numBits % 2) {
@@ -605,10 +603,10 @@ bool CodeGenTarget::guessInstructionProperties() const {
// ComplexPattern implementation
//
ComplexPattern::ComplexPattern(Record *R) {
Ty = R->getValueAsDef("Ty");
Ty = R->getValueAsDef("Ty");
NumOperands = R->getValueAsInt("NumOperands");
SelectFunc = std::string(R->getValueAsString("SelectFunc"));
RootNodes = R->getValueAsListOfDefs("RootNodes");
RootNodes = R->getValueAsListOfDefs("RootNodes");
// FIXME: This is a hack to statically increase the priority of patterns which
// maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
@@ -623,7 +621,7 @@ ComplexPattern::ComplexPattern(Record *R) {
// FIXME: Why is this different from parseSDPatternOperatorProperties?
// Parse the properties.
Properties = 0;
std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
std::vector<Record *> PropList = R->getValueAsListOfDefs("Properties");
for (unsigned i = 0, e = PropList.size(); i != e; ++i)
if (PropList[i]->getName() == "SDNPHasChain") {
Properties |= 1 << SDNPHasChain;

View File

@@ -58,10 +58,10 @@ class CodeGenTarget {
RecordKeeper &Records;
Record *TargetRec;
mutable DenseMap<const Record*,
std::unique_ptr<CodeGenInstruction>> Instructions;
mutable DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>>
Instructions;
mutable std::unique_ptr<CodeGenRegBank> RegBank;
mutable std::vector<Record*> RegAltNameIndices;
mutable std::vector<Record *> RegAltNameIndices;
mutable SmallVector<ValueTypeByHwMode, 8> LegalValueTypes;
CodeGenHwModes CGH;
std::vector<Record *> MacroFusions;
@@ -75,6 +75,7 @@ class CodeGenTarget {
mutable StringRef InstNamespace;
mutable std::vector<const CodeGenInstruction *> InstrsByEnum;
mutable unsigned NumPseudoInstructions = 0;
public:
CodeGenTarget(RecordKeeper &Records);
~CodeGenTarget();
@@ -130,8 +131,9 @@ public:
/// return it.
const CodeGenRegister *getRegisterByName(StringRef Name) const;
const std::vector<Record*> &getRegAltNameIndices() const {
if (RegAltNameIndices.empty()) ReadRegAltNameIndices();
const std::vector<Record *> &getRegAltNameIndices() const {
if (RegAltNameIndices.empty())
ReadRegAltNameIndices();
return RegAltNameIndices;
}
@@ -156,15 +158,17 @@ public:
const std::vector<Record *> getMacroFusions() const { return MacroFusions; }
private:
DenseMap<const Record*, std::unique_ptr<CodeGenInstruction>> &
DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> &
getInstructions() const {
if (Instructions.empty()) ReadInstructions();
if (Instructions.empty())
ReadInstructions();
return Instructions;
}
public:
public:
CodeGenInstruction &getInstruction(const Record *InstRec) const {
if (Instructions.empty()) ReadInstructions();
if (Instructions.empty())
ReadInstructions();
auto I = Instructions.find(InstRec);
assert(I != Instructions.end() && "Not an instruction");
return *I->second;
@@ -200,10 +204,11 @@ public:
}
typedef ArrayRef<const CodeGenInstruction *>::const_iterator inst_iterator;
inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();}
inst_iterator inst_begin() const {
return getInstructionsByEnumValue().begin();
}
inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); }
/// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]?
///
bool isLittleEndianEncoding() const;
@@ -226,22 +231,21 @@ class ComplexPattern {
Record *Ty;
unsigned NumOperands;
std::string SelectFunc;
std::vector<Record*> RootNodes;
std::vector<Record *> RootNodes;
unsigned Properties; // Node properties
unsigned Complexity;
public:
ComplexPattern(Record *R);
Record *getValueType() const { return Ty; }
unsigned getNumOperands() const { return NumOperands; }
const std::string &getSelectFunc() const { return SelectFunc; }
const std::vector<Record*> &getRootNodes() const {
return RootNodes;
}
const std::vector<Record *> &getRootNodes() const { return RootNodes; }
bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
unsigned getComplexity() const { return Complexity; }
};
} // End llvm namespace
} // namespace llvm
#endif

View File

@@ -27,6 +27,7 @@ namespace {
class DAGISelEmitter {
RecordKeeper &Records; // Just so we can get at the timing functions.
CodeGenDAGPatterns CGP;
public:
explicit DAGISelEmitter(RecordKeeper &R) : Records(R), CGP(R) {}
void run(raw_ostream &OS);
@@ -42,7 +43,8 @@ public:
/// latencies in this calculation.
static unsigned getResultPatternCost(TreePatternNode *P,
CodeGenDAGPatterns &CGP) {
if (P->isLeaf()) return 0;
if (P->isLeaf())
return 0;
unsigned Cost = 0;
Record *Op = P->getOperator();
@@ -61,7 +63,8 @@ static unsigned getResultPatternCost(TreePatternNode *P,
/// pattern.
static unsigned getResultPatternSize(TreePatternNode *P,
CodeGenDAGPatterns &CGP) {
if (P->isLeaf()) return 0;
if (P->isLeaf())
return 0;
unsigned Cost = 0;
Record *Op = P->getOperator();
@@ -98,19 +101,25 @@ struct PatternSortingPredicate {
// input over nodes that cover fewer.
int LHSSize = LHS->getPatternComplexity(CGP);
int RHSSize = RHS->getPatternComplexity(CGP);
if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
if (LHSSize < RHSSize) return false;
if (LHSSize > RHSSize)
return true; // LHS -> bigger -> less cost
if (LHSSize < RHSSize)
return false;
// If the patterns have equal complexity, compare generated instruction cost
unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP);
unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP);
if (LHSCost < RHSCost) return true;
if (LHSCost > RHSCost) return false;
if (LHSCost < RHSCost)
return true;
if (LHSCost > RHSCost)
return false;
unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP);
unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP);
if (LHSPatSize < RHSPatSize) return true;
if (LHSPatSize > RHSPatSize) return false;
if (LHSPatSize < RHSPatSize)
return true;
if (LHSPatSize > RHSPatSize)
return false;
// Sort based on the UID of the pattern, to reflect source order.
// Note that this is not guaranteed to be unique, since a single source
@@ -122,11 +131,11 @@ struct PatternSortingPredicate {
};
} // End anonymous namespace
void DAGISelEmitter::run(raw_ostream &OS) {
Records.startTimer("Parse patterns");
emitSourceFileHeader("DAG Instruction Selector for the " +
CGP.getTargetInfo().getName().str() + " target", OS);
CGP.getTargetInfo().getName().str() + " target",
OS);
OS << "// *** NOTE: This file is #included into the middle of the target\n"
<< "// *** instruction selector class. These functions are really "
@@ -155,7 +164,7 @@ void DAGISelEmitter::run(raw_ostream &OS) {
// Add all the patterns to a temporary list so we can sort them.
Records.startTimer("Sort patterns");
std::vector<const PatternToMatch*> Patterns;
std::vector<const PatternToMatch *> Patterns;
for (const PatternToMatch &PTM : CGP.ptms())
Patterns.push_back(&PTM);
@@ -167,7 +176,7 @@ void DAGISelEmitter::run(raw_ostream &OS) {
Records.startTimer("Convert to matchers");
SmallVector<Matcher *, 0> PatternMatchers;
for (const PatternToMatch *PTM : Patterns) {
for (unsigned Variant = 0; ; ++Variant) {
for (unsigned Variant = 0;; ++Variant) {
if (Matcher *M = ConvertPatternToMatcher(*PTM, Variant, CGP))
PatternMatchers.push_back(M);
else
@@ -181,7 +190,7 @@ void DAGISelEmitter::run(raw_ostream &OS) {
Records.startTimer("Optimize matchers");
OptimizeMatcher(TheMatcher, CGP);
//Matcher->dump();
// Matcher->dump();
Records.startTimer("Emit matcher table");
EmitMatcherTable(TheMatcher.get(), CGP, OS);

View File

@@ -15,11 +15,9 @@
#include "llvm/TableGen/Record.h"
using namespace llvm;
void Matcher::anchor() { }
void Matcher::anchor() {}
void Matcher::dump() const {
print(errs(), 0);
}
void Matcher::dump() const { print(errs(), 0); }
void Matcher::print(raw_ostream &OS, unsigned indent) const {
printImpl(OS, indent);
@@ -27,9 +25,7 @@ void Matcher::print(raw_ostream &OS, unsigned indent) const {
return Next->print(OS, indent);
}
void Matcher::printOne(raw_ostream &OS) const {
printImpl(OS, 0);
}
void Matcher::printOne(raw_ostream &OS) const { printImpl(OS, 0); }
/// unlinkNode - Unlink the specified node from this chain. If Other == this,
/// we unlink the next pointer and return it. Otherwise we unlink Other from
@@ -43,7 +39,8 @@ Matcher *Matcher::unlinkNode(Matcher *Other) {
for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext())
/*empty*/;
if (!Cur) return nullptr;
if (!Cur)
return nullptr;
Cur->takeNext();
Cur->setNext(Other->takeNext());
return this;
@@ -55,7 +52,8 @@ Matcher *Matcher::unlinkNode(Matcher *Other) {
bool Matcher::canMoveBefore(const Matcher *Other) const {
for (;; Other = Other->getNext()) {
assert(Other && "Other didn't come before 'this'?");
if (this == Other) return true;
if (this == Other)
return true;
// We have to be able to move this node across the Other node.
if (!canMoveBeforeNode(Other))
@@ -78,7 +76,6 @@ bool Matcher::canMoveBeforeNode(const Matcher *Other) const {
return false;
}
ScopeMatcher::~ScopeMatcher() {
for (Matcher *C : Children)
delete C;
@@ -96,8 +93,8 @@ SwitchTypeMatcher::~SwitchTypeMatcher() {
CheckPredicateMatcher::CheckPredicateMatcher(
const TreePredicateFn &pred, const SmallVectorImpl<unsigned> &Ops)
: Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()),
Operands(Ops.begin(), Ops.end()) {}
: Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()),
Operands(Ops.begin(), Ops.end()) {}
TreePredicateFn CheckPredicateMatcher::getPredicate() const {
return TreePredicateFn(Pred);
@@ -112,16 +109,15 @@ unsigned CheckPredicateMatcher::getOperandNo(unsigned i) const {
return Operands[i];
}
// printImpl methods.
void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "Scope\n";
for (const Matcher *C : Children) {
if (!C)
OS.indent(indent+1) << "NULL POINTER\n";
OS.indent(indent + 1) << "NULL POINTER\n";
else
C->print(OS, indent+2);
C->print(OS, indent + 2);
}
}
@@ -137,7 +133,8 @@ void RecordMemRefMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "RecordMemRef\n";
}
void CaptureGlueInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{
void CaptureGlueInputMatcher::printImpl(raw_ostream &OS,
unsigned indent) const {
OS.indent(indent) << "CaptureGlueInput\n";
}
@@ -161,8 +158,8 @@ void CheckChildSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "CheckChild" << ChildNo << "Same\n";
}
void CheckPatternPredicateMatcher::
printImpl(raw_ostream &OS, unsigned indent) const {
void CheckPatternPredicateMatcher::printImpl(raw_ostream &OS,
unsigned indent) const {
OS.indent(indent) << "CheckPatternPredicate " << Predicate << '\n';
}
@@ -178,32 +175,30 @@ void SwitchOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "SwitchOpcode: {\n";
for (const auto &C : Cases) {
OS.indent(indent) << "case " << C.first->getEnumName() << ":\n";
C.second->print(OS, indent+2);
C.second->print(OS, indent + 2);
}
OS.indent(indent) << "}\n";
}
void CheckTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "CheckType " << getEnumName(Type) << ", ResNo="
<< ResNo << '\n';
OS.indent(indent) << "CheckType " << getEnumName(Type) << ", ResNo=" << ResNo
<< '\n';
}
void SwitchTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "SwitchType: {\n";
for (const auto &C : Cases) {
OS.indent(indent) << "case " << getEnumName(C.first) << ":\n";
C.second->print(OS, indent+2);
C.second->print(OS, indent + 2);
}
OS.indent(indent) << "}\n";
}
void CheckChildTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "CheckChildType " << ChildNo << " "
<< getEnumName(Type) << '\n';
OS.indent(indent) << "CheckChildType " << ChildNo << " " << getEnumName(Type)
<< '\n';
}
void CheckIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "CheckInteger " << Value << '\n';
}
@@ -258,8 +253,8 @@ void EmitIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
<< '\n';
}
void EmitStringIntegerMatcher::
printImpl(raw_ostream &OS, unsigned indent) const {
void EmitStringIntegerMatcher::printImpl(raw_ostream &OS,
unsigned indent) const {
OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << getEnumName(VT)
<< '\n';
}
@@ -273,13 +268,13 @@ void EmitRegisterMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS << " VT=" << getEnumName(VT) << '\n';
}
void EmitConvertToTargetMatcher::
printImpl(raw_ostream &OS, unsigned indent) const {
void EmitConvertToTargetMatcher::printImpl(raw_ostream &OS,
unsigned indent) const {
OS.indent(indent) << "EmitConvertToTarget " << Slot << '\n';
}
void EmitMergeInputChainsMatcher::
printImpl(raw_ostream &OS, unsigned indent) const {
void EmitMergeInputChainsMatcher::printImpl(raw_ostream &OS,
unsigned indent) const {
OS.indent(indent) << "EmitMergeInputChains <todo: args>\n";
}
@@ -289,10 +284,9 @@ void EmitCopyToRegMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
void EmitNodeXFormMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "EmitNodeXForm " << NodeXForm->getName()
<< " Slot=" << Slot << '\n';
<< " Slot=" << Slot << '\n';
}
void EmitNodeMatcherCommon::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent);
OS << (isa<MorphNodeToMatcher>(this) ? "MorphNodeTo: " : "EmitNode: ")
@@ -316,7 +310,7 @@ bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const {
// Note: pointer equality isn't enough here, we have to check the enum names
// to ensure that the nodes are for the same opcode.
return cast<CheckOpcodeMatcher>(M)->Opcode.getEnumName() ==
Opcode.getEnumName();
Opcode.getEnumName();
}
bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {
@@ -327,9 +321,9 @@ bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {
M->NumFixedArityOperands == NumFixedArityOperands;
}
void EmitNodeMatcher::anchor() { }
void EmitNodeMatcher::anchor() {}
void MorphNodeToMatcher::anchor() { }
void MorphNodeToMatcher::anchor() {}
// isContradictoryImpl Implementations.
@@ -337,7 +331,8 @@ static bool TypesAreContradictory(MVT::SimpleValueType T1,
MVT::SimpleValueType T2) {
// If the two types are the same, then they are the same, so they don't
// contradict.
if (T1 == T2) return false;
if (T1 == T2)
return false;
// If either type is about iPtr, then they don't conflict unless the other
// one is not a scalar integer type.
@@ -400,7 +395,8 @@ bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const {
}
bool CheckChildIntegerMatcher::isContradictoryImpl(const Matcher *M) const {
if (const CheckChildIntegerMatcher *CCIM = dyn_cast<CheckChildIntegerMatcher>(M)) {
if (const CheckChildIntegerMatcher *CCIM =
dyn_cast<CheckChildIntegerMatcher>(M)) {
// If the two checks are about different nodes, we don't know if they
// conflict!
if (CCIM->getChildNo() != getChildNo())

View File

@@ -21,185 +21,186 @@
#include <utility>
namespace llvm {
class CodeGenRegister;
class CodeGenDAGPatterns;
class CodeGenInstruction;
class Matcher;
class PatternToMatch;
class raw_ostream;
class ComplexPattern;
class Record;
class SDNodeInfo;
class TreePredicateFn;
class TreePattern;
class CodeGenRegister;
class CodeGenDAGPatterns;
class CodeGenInstruction;
class Matcher;
class PatternToMatch;
class raw_ostream;
class ComplexPattern;
class Record;
class SDNodeInfo;
class TreePredicateFn;
class TreePattern;
Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,
unsigned Variant,
const CodeGenDAGPatterns &CGP);
void OptimizeMatcher(std::unique_ptr<Matcher> &Matcher,
const CodeGenDAGPatterns &CGP);
void EmitMatcherTable(Matcher *Matcher, const CodeGenDAGPatterns &CGP,
raw_ostream &OS);
Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,
unsigned Variant,
const CodeGenDAGPatterns &CGP);
void OptimizeMatcher(std::unique_ptr<Matcher> &Matcher,
const CodeGenDAGPatterns &CGP);
void EmitMatcherTable(Matcher *Matcher, const CodeGenDAGPatterns &CGP,
raw_ostream &OS);
/// Matcher - Base class for all the DAG ISel Matcher representation
/// nodes.
class Matcher {
// The next matcher node that is executed after this one. Null if this is
// the last stage of a match.
std::unique_ptr<Matcher> Next;
size_t Size = 0; // Size in bytes of matcher and all its children (if any).
virtual void anchor();
/// Matcher - Base class for all the DAG ISel Matcher representation
/// nodes.
class Matcher {
// The next matcher node that is executed after this one. Null if this is
// the last stage of a match.
std::unique_ptr<Matcher> Next;
size_t Size = 0; // Size in bytes of matcher and all its children (if any).
virtual void anchor();
public:
enum KindTy {
// Matcher state manipulation.
Scope, // Push a checking scope.
RecordNode, // Record the current node.
RecordChild, // Record a child of the current node.
RecordMemRef, // Record the memref in the current node.
CaptureGlueInput, // If the current node has an input glue, save it.
MoveChild, // Move current node to specified child.
MoveSibling, // Move current node to specified sibling.
MoveParent, // Move current node to parent.
public:
enum KindTy {
// Matcher state manipulation.
Scope, // Push a checking scope.
RecordNode, // Record the current node.
RecordChild, // Record a child of the current node.
RecordMemRef, // Record the memref in the current node.
CaptureGlueInput, // If the current node has an input glue, save it.
MoveChild, // Move current node to specified child.
MoveSibling, // Move current node to specified sibling.
MoveParent, // Move current node to parent.
// Predicate checking.
CheckSame, // Fail if not same as prev match.
CheckChildSame, // Fail if child not same as prev match.
CheckPatternPredicate,
CheckPredicate, // Fail if node predicate fails.
CheckOpcode, // Fail if not opcode.
SwitchOpcode, // Dispatch based on opcode.
CheckType, // Fail if not correct type.
SwitchType, // Dispatch based on type.
CheckChildType, // Fail if child has wrong type.
CheckInteger, // Fail if wrong val.
CheckChildInteger, // Fail if child is wrong val.
CheckCondCode, // Fail if not condcode.
CheckChild2CondCode, // Fail if child is wrong condcode.
CheckValueType,
CheckComplexPat,
CheckAndImm,
CheckOrImm,
CheckImmAllOnesV,
CheckImmAllZerosV,
CheckFoldableChainNode,
// Predicate checking.
CheckSame, // Fail if not same as prev match.
CheckChildSame, // Fail if child not same as prev match.
CheckPatternPredicate,
CheckPredicate, // Fail if node predicate fails.
CheckOpcode, // Fail if not opcode.
SwitchOpcode, // Dispatch based on opcode.
CheckType, // Fail if not correct type.
SwitchType, // Dispatch based on type.
CheckChildType, // Fail if child has wrong type.
CheckInteger, // Fail if wrong val.
CheckChildInteger, // Fail if child is wrong val.
CheckCondCode, // Fail if not condcode.
CheckChild2CondCode, // Fail if child is wrong condcode.
CheckValueType,
CheckComplexPat,
CheckAndImm,
CheckOrImm,
CheckImmAllOnesV,
CheckImmAllZerosV,
CheckFoldableChainNode,
// Node creation/emisssion.
EmitInteger, // Create a TargetConstant
EmitStringInteger, // Create a TargetConstant from a string.
EmitRegister, // Create a register.
EmitConvertToTarget, // Convert a imm/fpimm to target imm/fpimm
EmitMergeInputChains, // Merge together a chains for an input.
EmitCopyToReg, // Emit a copytoreg into a physreg.
EmitNode, // Create a DAG node
EmitNodeXForm, // Run a SDNodeXForm
CompleteMatch, // Finish a match and update the results.
MorphNodeTo, // Build a node, finish a match and update results.
// Node creation/emisssion.
EmitInteger, // Create a TargetConstant
EmitStringInteger, // Create a TargetConstant from a string.
EmitRegister, // Create a register.
EmitConvertToTarget, // Convert a imm/fpimm to target imm/fpimm
EmitMergeInputChains, // Merge together a chains for an input.
EmitCopyToReg, // Emit a copytoreg into a physreg.
EmitNode, // Create a DAG node
EmitNodeXForm, // Run a SDNodeXForm
CompleteMatch, // Finish a match and update the results.
MorphNodeTo, // Build a node, finish a match and update results.
// Highest enum value; watch out when adding more.
HighestKind = MorphNodeTo
};
const KindTy Kind;
protected:
Matcher(KindTy K) : Kind(K) {}
public:
virtual ~Matcher() {}
unsigned getSize() const { return Size; }
void setSize(unsigned sz) { Size = sz; }
KindTy getKind() const { return Kind; }
Matcher *getNext() { return Next.get(); }
const Matcher *getNext() const { return Next.get(); }
void setNext(Matcher *C) { Next.reset(C); }
Matcher *takeNext() { return Next.release(); }
std::unique_ptr<Matcher> &getNextPtr() { return Next; }
bool isEqual(const Matcher *M) const {
if (getKind() != M->getKind())
return false;
return isEqualImpl(M);
}
/// isSimplePredicateNode - Return true if this is a simple predicate that
/// operates on the node or its children without potential side effects or a
/// change of the current node.
bool isSimplePredicateNode() const {
switch (getKind()) {
default:
return false;
case CheckSame:
case CheckChildSame:
case CheckPatternPredicate:
case CheckPredicate:
case CheckOpcode:
case CheckType:
case CheckChildType:
case CheckInteger:
case CheckChildInteger:
case CheckCondCode:
case CheckChild2CondCode:
case CheckValueType:
case CheckAndImm:
case CheckOrImm:
case CheckImmAllOnesV:
case CheckImmAllZerosV:
case CheckFoldableChainNode:
return true;
}
}
/// isSimplePredicateOrRecordNode - Return true if this is a record node or
/// a simple predicate.
bool isSimplePredicateOrRecordNode() const {
return isSimplePredicateNode() || getKind() == RecordNode ||
getKind() == RecordChild;
}
/// unlinkNode - Unlink the specified node from this chain. If Other ==
/// this, we unlink the next pointer and return it. Otherwise we unlink
/// Other from the list and return this.
Matcher *unlinkNode(Matcher *Other);
/// canMoveBefore - Return true if this matcher is the same as Other, or if
/// we can move this matcher past all of the nodes in-between Other and this
/// node. Other must be equal to or before this.
bool canMoveBefore(const Matcher *Other) const;
/// canMoveBeforeNode - Return true if it is safe to move the current
/// matcher across the specified one.
bool canMoveBeforeNode(const Matcher *Other) const;
/// isContradictory - Return true of these two matchers could never match on
/// the same node.
bool isContradictory(const Matcher *Other) const {
// Since this predicate is reflexive, we canonicalize the ordering so that
// we always match a node against nodes with kinds that are greater or
// equal to them. For example, we'll pass in a CheckType node as an
// argument to the CheckOpcode method, not the other way around.
if (getKind() < Other->getKind())
return isContradictoryImpl(Other);
return Other->isContradictoryImpl(this);
}
void print(raw_ostream &OS, unsigned indent = 0) const;
void printOne(raw_ostream &OS) const;
void dump() const;
protected:
virtual void printImpl(raw_ostream &OS, unsigned indent) const = 0;
virtual bool isEqualImpl(const Matcher *M) const = 0;
virtual bool isContradictoryImpl(const Matcher *M) const { return false; }
// Highest enum value; watch out when adding more.
HighestKind = MorphNodeTo
};
const KindTy Kind;
protected:
Matcher(KindTy K) : Kind(K) {}
public:
virtual ~Matcher() {}
unsigned getSize() const { return Size; }
void setSize(unsigned sz) { Size = sz; }
KindTy getKind() const { return Kind; }
Matcher *getNext() { return Next.get(); }
const Matcher *getNext() const { return Next.get(); }
void setNext(Matcher *C) { Next.reset(C); }
Matcher *takeNext() { return Next.release(); }
std::unique_ptr<Matcher> &getNextPtr() { return Next; }
bool isEqual(const Matcher *M) const {
if (getKind() != M->getKind())
return false;
return isEqualImpl(M);
}
/// isSimplePredicateNode - Return true if this is a simple predicate that
/// operates on the node or its children without potential side effects or a
/// change of the current node.
bool isSimplePredicateNode() const {
switch (getKind()) {
default:
return false;
case CheckSame:
case CheckChildSame:
case CheckPatternPredicate:
case CheckPredicate:
case CheckOpcode:
case CheckType:
case CheckChildType:
case CheckInteger:
case CheckChildInteger:
case CheckCondCode:
case CheckChild2CondCode:
case CheckValueType:
case CheckAndImm:
case CheckOrImm:
case CheckImmAllOnesV:
case CheckImmAllZerosV:
case CheckFoldableChainNode:
return true;
}
}
/// isSimplePredicateOrRecordNode - Return true if this is a record node or
/// a simple predicate.
bool isSimplePredicateOrRecordNode() const {
return isSimplePredicateNode() || getKind() == RecordNode ||
getKind() == RecordChild;
}
/// unlinkNode - Unlink the specified node from this chain. If Other ==
/// this, we unlink the next pointer and return it. Otherwise we unlink
/// Other from the list and return this.
Matcher *unlinkNode(Matcher *Other);
/// canMoveBefore - Return true if this matcher is the same as Other, or if
/// we can move this matcher past all of the nodes in-between Other and this
/// node. Other must be equal to or before this.
bool canMoveBefore(const Matcher *Other) const;
/// canMoveBeforeNode - Return true if it is safe to move the current
/// matcher across the specified one.
bool canMoveBeforeNode(const Matcher *Other) const;
/// isContradictory - Return true of these two matchers could never match on
/// the same node.
bool isContradictory(const Matcher *Other) const {
// Since this predicate is reflexive, we canonicalize the ordering so that
// we always match a node against nodes with kinds that are greater or
// equal to them. For example, we'll pass in a CheckType node as an
// argument to the CheckOpcode method, not the other way around.
if (getKind() < Other->getKind())
return isContradictoryImpl(Other);
return Other->isContradictoryImpl(this);
}
void print(raw_ostream &OS, unsigned indent = 0) const;
void printOne(raw_ostream &OS) const;
void dump() const;
protected:
virtual void printImpl(raw_ostream &OS, unsigned indent) const = 0;
virtual bool isEqualImpl(const Matcher *M) const = 0;
virtual bool isContradictoryImpl(const Matcher *M) const { return false; }
};
/// ScopeMatcher - This attempts to match each of its children to find the first
/// one that successfully matches. If one child fails, it tries the next child.
/// If none of the children match then this check fails. It never has a 'next'.
class ScopeMatcher : public Matcher {
SmallVector<Matcher*, 4> Children;
SmallVector<Matcher *, 4> Children;
public:
ScopeMatcher(SmallVectorImpl<Matcher *> &&children)
: Matcher(Scope), Children(std::move(children)) {}
@@ -230,9 +231,7 @@ public:
Children.resize(NC);
}
static bool classof(const Matcher *N) {
return N->getKind() == Scope;
}
static bool classof(const Matcher *N) { return N->getKind() == Scope; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -248,16 +247,15 @@ class RecordMatcher : public Matcher {
/// ResultNo - The slot number in the RecordedNodes vector that this will be,
/// just printed as a comment.
unsigned ResultNo;
public:
RecordMatcher(const std::string &whatfor, unsigned resultNo)
: Matcher(RecordNode), WhatFor(whatfor), ResultNo(resultNo) {}
: Matcher(RecordNode), WhatFor(whatfor), ResultNo(resultNo) {}
const std::string &getWhatFor() const { return WhatFor; }
unsigned getResultNo() const { return ResultNo; }
static bool classof(const Matcher *N) {
return N->getKind() == RecordNode;
}
static bool classof(const Matcher *N) { return N->getKind() == RecordNode; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -277,19 +275,18 @@ class RecordChildMatcher : public Matcher {
/// ResultNo - The slot number in the RecordedNodes vector that this will be,
/// just printed as a comment.
unsigned ResultNo;
public:
RecordChildMatcher(unsigned childno, const std::string &whatfor,
unsigned resultNo)
: Matcher(RecordChild), ChildNo(childno), WhatFor(whatfor),
ResultNo(resultNo) {}
: Matcher(RecordChild), ChildNo(childno), WhatFor(whatfor),
ResultNo(resultNo) {}
unsigned getChildNo() const { return ChildNo; }
const std::string &getWhatFor() const { return WhatFor; }
unsigned getResultNo() const { return ResultNo; }
static bool classof(const Matcher *N) {
return N->getKind() == RecordChild;
}
static bool classof(const Matcher *N) { return N->getKind() == RecordChild; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -303,16 +300,13 @@ class RecordMemRefMatcher : public Matcher {
public:
RecordMemRefMatcher() : Matcher(RecordMemRef) {}
static bool classof(const Matcher *N) {
return N->getKind() == RecordMemRef;
}
static bool classof(const Matcher *N) { return N->getKind() == RecordMemRef; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override { return true; }
};
/// CaptureGlueInputMatcher - If the current record has a glue input, record
/// it so that it is used as an input to the generated code.
class CaptureGlueInputMatcher : public Matcher {
@@ -332,14 +326,13 @@ private:
/// specified child node.
class MoveChildMatcher : public Matcher {
unsigned ChildNo;
public:
MoveChildMatcher(unsigned childNo) : Matcher(MoveChild), ChildNo(childNo) {}
unsigned getChildNo() const { return ChildNo; }
static bool classof(const Matcher *N) {
return N->getKind() == MoveChild;
}
static bool classof(const Matcher *N) { return N->getKind() == MoveChild; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -374,9 +367,7 @@ class MoveParentMatcher : public Matcher {
public:
MoveParentMatcher() : Matcher(MoveParent) {}
static bool classof(const Matcher *N) {
return N->getKind() == MoveParent;
}
static bool classof(const Matcher *N) { return N->getKind() == MoveParent; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -388,15 +379,14 @@ private:
/// when patterns have the same name in them, like '(mul GPR:$in, GPR:$in)'.
class CheckSameMatcher : public Matcher {
unsigned MatchNumber;
public:
CheckSameMatcher(unsigned matchnumber)
: Matcher(CheckSame), MatchNumber(matchnumber) {}
: Matcher(CheckSame), MatchNumber(matchnumber) {}
unsigned getMatchNumber() const { return MatchNumber; }
static bool classof(const Matcher *N) {
return N->getKind() == CheckSame;
}
static bool classof(const Matcher *N) { return N->getKind() == CheckSame; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -411,9 +401,10 @@ private:
class CheckChildSameMatcher : public Matcher {
unsigned ChildNo;
unsigned MatchNumber;
public:
CheckChildSameMatcher(unsigned childno, unsigned matchnumber)
: Matcher(CheckChildSame), ChildNo(childno), MatchNumber(matchnumber) {}
: Matcher(CheckChildSame), ChildNo(childno), MatchNumber(matchnumber) {}
unsigned getChildNo() const { return ChildNo; }
unsigned getMatchNumber() const { return MatchNumber; }
@@ -435,9 +426,10 @@ private:
/// not take a node as input. This is used for subtarget feature checks etc.
class CheckPatternPredicateMatcher : public Matcher {
std::string Predicate;
public:
CheckPatternPredicateMatcher(StringRef predicate)
: Matcher(CheckPatternPredicate), Predicate(predicate) {}
: Matcher(CheckPatternPredicate), Predicate(predicate) {}
StringRef getPredicate() const { return Predicate; }
@@ -457,6 +449,7 @@ private:
class CheckPredicateMatcher : public Matcher {
TreePattern *Pred;
const SmallVector<unsigned, 4> Operands;
public:
CheckPredicateMatcher(const TreePredicateFn &pred,
const SmallVectorImpl<unsigned> &Operands);
@@ -476,20 +469,18 @@ private:
}
};
/// CheckOpcodeMatcher - This checks to see if the current node has the
/// specified opcode, if not it fails to match.
class CheckOpcodeMatcher : public Matcher {
const SDNodeInfo &Opcode;
public:
CheckOpcodeMatcher(const SDNodeInfo &opcode)
: Matcher(CheckOpcode), Opcode(opcode) {}
: Matcher(CheckOpcode), Opcode(opcode) {}
const SDNodeInfo &getOpcode() const { return Opcode; }
static bool classof(const Matcher *N) {
return N->getKind() == CheckOpcode;
}
static bool classof(const Matcher *N) { return N->getKind() == CheckOpcode; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -502,16 +493,15 @@ private:
/// then the match fails. This is semantically equivalent to a Scope node where
/// every child does a CheckOpcode, but is much faster.
class SwitchOpcodeMatcher : public Matcher {
SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;
SmallVector<std::pair<const SDNodeInfo *, Matcher *>, 8> Cases;
public:
SwitchOpcodeMatcher(
SmallVectorImpl<std::pair<const SDNodeInfo *, Matcher *>> &&cases)
: Matcher(SwitchOpcode), Cases(std::move(cases)) {}
~SwitchOpcodeMatcher() override;
static bool classof(const Matcher *N) {
return N->getKind() == SwitchOpcode;
}
static bool classof(const Matcher *N) { return N->getKind() == SwitchOpcode; }
unsigned getNumCases() const { return Cases.size(); }
@@ -529,16 +519,15 @@ private:
class CheckTypeMatcher : public Matcher {
MVT::SimpleValueType Type;
unsigned ResNo;
public:
CheckTypeMatcher(MVT::SimpleValueType type, unsigned resno)
: Matcher(CheckType), Type(type), ResNo(resno) {}
: Matcher(CheckType), Type(type), ResNo(resno) {}
MVT::SimpleValueType getType() const { return Type; }
unsigned getResNo() const { return ResNo; }
static bool classof(const Matcher *N) {
return N->getKind() == CheckType;
}
static bool classof(const Matcher *N) { return N->getKind() == CheckType; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -553,16 +542,15 @@ private:
/// then the match fails. This is semantically equivalent to a Scope node where
/// every child does a CheckType, but is much faster.
class SwitchTypeMatcher : public Matcher {
SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;
SmallVector<std::pair<MVT::SimpleValueType, Matcher *>, 8> Cases;
public:
SwitchTypeMatcher(
SmallVectorImpl<std::pair<MVT::SimpleValueType, Matcher *>> &&cases)
: Matcher(SwitchType), Cases(std::move(cases)) {}
~SwitchTypeMatcher() override;
static bool classof(const Matcher *N) {
return N->getKind() == SwitchType;
}
static bool classof(const Matcher *N) { return N->getKind() == SwitchType; }
unsigned getNumCases() const { return Cases.size(); }
@@ -575,15 +563,15 @@ private:
bool isEqualImpl(const Matcher *M) const override { return false; }
};
/// CheckChildTypeMatcher - This checks to see if a child node has the
/// specified type, if not it fails to match.
class CheckChildTypeMatcher : public Matcher {
unsigned ChildNo;
MVT::SimpleValueType Type;
public:
CheckChildTypeMatcher(unsigned childno, MVT::SimpleValueType type)
: Matcher(CheckChildType), ChildNo(childno), Type(type) {}
: Matcher(CheckChildType), ChildNo(childno), Type(type) {}
unsigned getChildNo() const { return ChildNo; }
MVT::SimpleValueType getType() const { return Type; }
@@ -601,20 +589,17 @@ private:
bool isContradictoryImpl(const Matcher *M) const override;
};
/// CheckIntegerMatcher - This checks to see if the current node is a
/// ConstantSDNode with the specified integer value, if not it fails to match.
class CheckIntegerMatcher : public Matcher {
int64_t Value;
public:
CheckIntegerMatcher(int64_t value)
: Matcher(CheckInteger), Value(value) {}
CheckIntegerMatcher(int64_t value) : Matcher(CheckInteger), Value(value) {}
int64_t getValue() const { return Value; }
static bool classof(const Matcher *N) {
return N->getKind() == CheckInteger;
}
static bool classof(const Matcher *N) { return N->getKind() == CheckInteger; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -629,9 +614,10 @@ private:
class CheckChildIntegerMatcher : public Matcher {
unsigned ChildNo;
int64_t Value;
public:
CheckChildIntegerMatcher(unsigned childno, int64_t value)
: Matcher(CheckChildInteger), ChildNo(childno), Value(value) {}
: Matcher(CheckChildInteger), ChildNo(childno), Value(value) {}
unsigned getChildNo() const { return ChildNo; }
int64_t getValue() const { return Value; }
@@ -653,9 +639,10 @@ private:
/// CondCodeSDNode with the specified condition, if not it fails to match.
class CheckCondCodeMatcher : public Matcher {
StringRef CondCodeName;
public:
CheckCondCodeMatcher(StringRef condcodename)
: Matcher(CheckCondCode), CondCodeName(condcodename) {}
: Matcher(CheckCondCode), CondCodeName(condcodename) {}
StringRef getCondCodeName() const { return CondCodeName; }
@@ -675,9 +662,10 @@ private:
/// CondCodeSDNode with the specified condition, if not it fails to match.
class CheckChild2CondCodeMatcher : public Matcher {
StringRef CondCodeName;
public:
CheckChild2CondCodeMatcher(StringRef condcodename)
: Matcher(CheckChild2CondCode), CondCodeName(condcodename) {}
: Matcher(CheckChild2CondCode), CondCodeName(condcodename) {}
StringRef getCondCodeName() const { return CondCodeName; }
@@ -697,9 +685,10 @@ private:
/// VTSDNode with the specified type, if not it fails to match.
class CheckValueTypeMatcher : public Matcher {
StringRef TypeName;
public:
CheckValueTypeMatcher(StringRef type_name)
: Matcher(CheckValueType), TypeName(type_name) {}
: Matcher(CheckValueType), TypeName(type_name) {}
StringRef getTypeName() const { return TypeName; }
@@ -715,8 +704,6 @@ private:
bool isContradictoryImpl(const Matcher *M) const override;
};
/// CheckComplexPatMatcher - This node runs the specified ComplexPattern on
/// the current node.
class CheckComplexPatMatcher : public Matcher {
@@ -732,11 +719,12 @@ class CheckComplexPatMatcher : public Matcher {
/// FirstResult - This is the first slot in the RecordedNodes list that the
/// result of the match populates.
unsigned FirstResult;
public:
CheckComplexPatMatcher(const ComplexPattern &pattern, unsigned matchnumber,
const std::string &name, unsigned firstresult)
: Matcher(CheckComplexPat), Pattern(pattern), MatchNumber(matchnumber),
Name(name), FirstResult(firstresult) {}
: Matcher(CheckComplexPat), Pattern(pattern), MatchNumber(matchnumber),
Name(name), FirstResult(firstresult) {}
const ComplexPattern &getPattern() const { return Pattern; }
unsigned getMatchNumber() const { return MatchNumber; }
@@ -760,15 +748,13 @@ private:
/// with something equivalent to the specified immediate.
class CheckAndImmMatcher : public Matcher {
int64_t Value;
public:
CheckAndImmMatcher(int64_t value)
: Matcher(CheckAndImm), Value(value) {}
CheckAndImmMatcher(int64_t value) : Matcher(CheckAndImm), Value(value) {}
int64_t getValue() const { return Value; }
static bool classof(const Matcher *N) {
return N->getKind() == CheckAndImm;
}
static bool classof(const Matcher *N) { return N->getKind() == CheckAndImm; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -781,15 +767,13 @@ private:
/// with something equivalent to the specified immediate.
class CheckOrImmMatcher : public Matcher {
int64_t Value;
public:
CheckOrImmMatcher(int64_t value)
: Matcher(CheckOrImm), Value(value) {}
CheckOrImmMatcher(int64_t value) : Matcher(CheckOrImm), Value(value) {}
int64_t getValue() const { return Value; }
static bool classof(const Matcher *N) {
return N->getKind() == CheckOrImm;
}
static bool classof(const Matcher *N) { return N->getKind() == CheckOrImm; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -834,8 +818,7 @@ private:
/// (which defines a chain operand) is safe to fold into a larger pattern.
class CheckFoldableChainNodeMatcher : public Matcher {
public:
CheckFoldableChainNodeMatcher()
: Matcher(CheckFoldableChainNode) {}
CheckFoldableChainNodeMatcher() : Matcher(CheckFoldableChainNode) {}
static bool classof(const Matcher *N) {
return N->getKind() == CheckFoldableChainNode;
@@ -850,16 +833,15 @@ private:
class EmitIntegerMatcher : public Matcher {
int64_t Val;
MVT::SimpleValueType VT;
public:
EmitIntegerMatcher(int64_t val, MVT::SimpleValueType vt)
: Matcher(EmitInteger), Val(val), VT(vt) {}
: Matcher(EmitInteger), Val(val), VT(vt) {}
int64_t getValue() const { return Val; }
MVT::SimpleValueType getVT() const { return VT; }
static bool classof(const Matcher *N) {
return N->getKind() == EmitInteger;
}
static bool classof(const Matcher *N) { return N->getKind() == EmitInteger; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -874,9 +856,10 @@ private:
class EmitStringIntegerMatcher : public Matcher {
std::string Val;
MVT::SimpleValueType VT;
public:
EmitStringIntegerMatcher(const std::string &val, MVT::SimpleValueType vt)
: Matcher(EmitStringInteger), Val(val), VT(vt) {}
: Matcher(EmitStringInteger), Val(val), VT(vt) {}
const std::string &getValue() const { return Val; }
MVT::SimpleValueType getVT() const { return VT; }
@@ -899,16 +882,15 @@ class EmitRegisterMatcher : public Matcher {
/// this is a reference to zero_reg.
const CodeGenRegister *Reg;
MVT::SimpleValueType VT;
public:
EmitRegisterMatcher(const CodeGenRegister *reg, MVT::SimpleValueType vt)
: Matcher(EmitRegister), Reg(reg), VT(vt) {}
: Matcher(EmitRegister), Reg(reg), VT(vt) {}
const CodeGenRegister *getReg() const { return Reg; }
MVT::SimpleValueType getVT() const { return VT; }
static bool classof(const Matcher *N) {
return N->getKind() == EmitRegister;
}
static bool classof(const Matcher *N) { return N->getKind() == EmitRegister; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
@@ -923,9 +905,10 @@ private:
/// ISD::TargetConstant, likewise for ConstantFP.
class EmitConvertToTargetMatcher : public Matcher {
unsigned Slot;
public:
EmitConvertToTargetMatcher(unsigned slot)
: Matcher(EmitConvertToTarget), Slot(slot) {}
: Matcher(EmitConvertToTarget), Slot(slot) {}
unsigned getSlot() const { return Slot; }
@@ -946,9 +929,10 @@ private:
/// chains of these nodes if they are not themselves a node in the pattern.
class EmitMergeInputChainsMatcher : public Matcher {
SmallVector<unsigned, 3> ChainNodes;
public:
EmitMergeInputChainsMatcher(ArrayRef<unsigned> nodes)
: Matcher(EmitMergeInputChains), ChainNodes(nodes.begin(), nodes.end()) {}
: Matcher(EmitMergeInputChains), ChainNodes(nodes.begin(), nodes.end()) {}
unsigned getNumNodes() const { return ChainNodes.size(); }
@@ -976,9 +960,8 @@ class EmitCopyToRegMatcher : public Matcher {
const CodeGenRegister *DestPhysReg;
public:
EmitCopyToRegMatcher(unsigned srcSlot,
const CodeGenRegister *destPhysReg)
: Matcher(EmitCopyToReg), SrcSlot(srcSlot), DestPhysReg(destPhysReg) {}
EmitCopyToRegMatcher(unsigned srcSlot, const CodeGenRegister *destPhysReg)
: Matcher(EmitCopyToReg), SrcSlot(srcSlot), DestPhysReg(destPhysReg) {}
unsigned getSrcSlot() const { return SrcSlot; }
const CodeGenRegister *getDestPhysReg() const { return DestPhysReg; }
@@ -995,16 +978,15 @@ private:
}
};
/// EmitNodeXFormMatcher - Emit an operation that runs an SDNodeXForm on a
/// recorded node and records the result.
class EmitNodeXFormMatcher : public Matcher {
unsigned Slot;
Record *NodeXForm;
public:
EmitNodeXFormMatcher(unsigned slot, Record *nodeXForm)
: Matcher(EmitNodeXForm), Slot(slot), NodeXForm(nodeXForm) {}
: Matcher(EmitNodeXForm), Slot(slot), NodeXForm(nodeXForm) {}
unsigned getSlot() const { return Slot; }
Record *getNodeXForm() const { return NodeXForm; }
@@ -1033,6 +1015,7 @@ class EmitNodeMatcherCommon : public Matcher {
/// If this is a varidic node, this is set to the number of fixed arity
/// operands in the root of the pattern. The rest are appended to this node.
int NumFixedArityOperands;
public:
EmitNodeMatcherCommon(const CodeGenInstruction &cgi,
ArrayRef<MVT::SimpleValueType> vts,
@@ -1061,7 +1044,6 @@ public:
const SmallVectorImpl<MVT::SimpleValueType> &getVTList() const { return VTs; }
const SmallVectorImpl<unsigned> &getOperandList() const { return Operands; }
bool hasChain() const { return HasChain; }
bool hasInGlue() const { return HasInGlue; }
bool hasOutGlue() const { return HasOutGlue; }
@@ -1081,6 +1063,7 @@ private:
class EmitNodeMatcher : public EmitNodeMatcherCommon {
void anchor() override;
unsigned FirstResultSlot;
public:
EmitNodeMatcher(const CodeGenInstruction &cgi,
ArrayRef<MVT::SimpleValueType> vts,
@@ -1094,15 +1077,13 @@ public:
unsigned getFirstResultSlot() const { return FirstResultSlot; }
static bool classof(const Matcher *N) {
return N->getKind() == EmitNode;
}
static bool classof(const Matcher *N) { return N->getKind() == EmitNode; }
};
class MorphNodeToMatcher : public EmitNodeMatcherCommon {
void anchor() override;
const PatternToMatch &Pattern;
public:
MorphNodeToMatcher(const CodeGenInstruction &cgi,
ArrayRef<MVT::SimpleValueType> vts,
@@ -1116,9 +1097,7 @@ public:
const PatternToMatch &getPattern() const { return Pattern; }
static bool classof(const Matcher *N) {
return N->getKind() == MorphNodeTo;
}
static bool classof(const Matcher *N) { return N->getKind() == MorphNodeTo; }
};
/// CompleteMatchMatcher - Complete a match by replacing the results of the
@@ -1127,11 +1106,12 @@ public:
class CompleteMatchMatcher : public Matcher {
SmallVector<unsigned, 2> Results;
const PatternToMatch &Pattern;
public:
CompleteMatchMatcher(ArrayRef<unsigned> results,
const PatternToMatch &pattern)
: Matcher(CompleteMatch), Results(results.begin(), results.end()),
Pattern(pattern) {}
: Matcher(CompleteMatch), Results(results.begin(), results.end()),
Pattern(pattern) {}
unsigned getNumResults() const { return Results.size(); }
unsigned getResult(unsigned R) const { return Results[R]; }
@@ -1145,7 +1125,7 @@ private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<CompleteMatchMatcher>(M)->Results == Results &&
&cast<CompleteMatchMatcher>(M)->Pattern == &Pattern;
&cast<CompleteMatchMatcher>(M)->Pattern == &Pattern;
}
};

View File

@@ -50,7 +50,7 @@ namespace {
class MatcherTableEmitter {
const CodeGenDAGPatterns &CGP;
SmallVector<unsigned, Matcher::HighestKind+1> OpcodeCounts;
SmallVector<unsigned, Matcher::HighestKind + 1> OpcodeCounts;
std::vector<TreePattern *> NodePredicates;
std::vector<TreePattern *> NodePredicatesWithOperands;
@@ -62,14 +62,13 @@ class MatcherTableEmitter {
std::vector<std::string> PatternPredicates;
std::vector<const ComplexPattern*> ComplexPatterns;
std::vector<const ComplexPattern *> ComplexPatterns;
DenseMap<Record*, unsigned> NodeXFormMap;
std::vector<Record*> NodeXForms;
DenseMap<Record *, unsigned> NodeXFormMap;
std::vector<Record *> NodeXForms;
std::vector<std::string> VecIncludeStrings;
MapVector<std::string, unsigned, StringMap<unsigned> > VecPatterns;
MapVector<std::string, unsigned, StringMap<unsigned>> VecPatterns;
unsigned getPatternIdxFromTable(std::string &&P, std::string &&include_loc) {
const auto It = VecPatterns.find(P);
@@ -184,8 +183,8 @@ private:
unsigned SizeMatcher(Matcher *N, raw_ostream &OS);
unsigned EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
raw_ostream &OS);
unsigned EmitMatcher(const Matcher *N, const unsigned Indent,
unsigned CurrentIdx, raw_ostream &OS);
unsigned getNodePredicate(TreePredicateFn Pred) {
// We use the first predicate.
@@ -210,9 +209,8 @@ private:
NodeXForms.push_back(Rec);
Entry = NodeXForms.size();
}
return Entry-1;
return Entry - 1;
}
};
} // end anonymous namespace.
@@ -224,14 +222,15 @@ static std::string GetPatFromTreePatternNode(const TreePatternNode *N) {
}
static unsigned GetVBRSize(unsigned Val) {
if (Val <= 127) return 1;
if (Val <= 127)
return 1;
unsigned NumBytes = 0;
while (Val >= 128) {
Val >>= 7;
++NumBytes;
}
return NumBytes+1;
return NumBytes + 1;
}
/// EmitVBRValue - Emit the specified value as a VBR, returning the number of
@@ -245,7 +244,7 @@ static unsigned EmitVBRValue(uint64_t Val, raw_ostream &OS) {
uint64_t InVal = Val;
unsigned NumBytes = 0;
while (Val >= 128) {
OS << (Val&127) << "|128,";
OS << (Val & 127) << "|128,";
Val >>= 7;
++NumBytes;
}
@@ -253,7 +252,7 @@ static unsigned EmitVBRValue(uint64_t Val, raw_ostream &OS) {
if (!OmitComments)
OS << "/*" << InVal << "*/";
OS << ", ";
return NumBytes+1;
return NumBytes + 1;
}
/// Emit the specified signed value as a VBR. To improve compression we encode
@@ -290,8 +289,7 @@ static std::string getIncludePath(const Record *R) {
/// This function traverses the matcher tree and sizes all the nodes
/// that are children of the three kinds of nodes that have them.
unsigned MatcherTableEmitter::
SizeMatcherList(Matcher *N, raw_ostream &OS) {
unsigned MatcherTableEmitter::SizeMatcherList(Matcher *N, raw_ostream &OS) {
unsigned Size = 0;
while (N) {
Size += SizeMatcher(N, OS);
@@ -303,8 +301,7 @@ SizeMatcherList(Matcher *N, raw_ostream &OS) {
/// This function sizes the children of the three kinds of nodes that
/// have them. It does so by using special cases for those three
/// nodes, but sharing the code in EmitMatcher() for the other kinds.
unsigned MatcherTableEmitter::
SizeMatcher(Matcher *N, raw_ostream &OS) {
unsigned MatcherTableEmitter::SizeMatcher(Matcher *N, raw_ostream &OS) {
unsigned Idx = 0;
++OpcodeCounts[N->getKind()];
@@ -389,7 +386,7 @@ void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) {
"The sizes of Pattern and include vectors should be the same");
BeginEmitFunction(OS, "StringRef", "getPatternForIndex(unsigned Index)",
true/*AddOverride*/);
true /*AddOverride*/);
OS << "{\n";
OS << "static const char *PATTERN_MATCH_TABLE[] = {\n";
@@ -403,7 +400,7 @@ void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) {
EndEmitFunction(OS);
BeginEmitFunction(OS, "StringRef", "getIncludePathForIndex(unsigned Index)",
true/*AddOverride*/);
true /*AddOverride*/);
OS << "{\n";
OS << "static const char *INCLUDE_PATH_TABLE[] = {\n";
@@ -419,9 +416,10 @@ void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) {
/// EmitMatcher - Emit bytes for the specified matcher and return
/// the number of bytes emitted.
unsigned MatcherTableEmitter::
EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
raw_ostream &OS) {
unsigned MatcherTableEmitter::EmitMatcher(const Matcher *N,
const unsigned Indent,
unsigned CurrentIdx,
raw_ostream &OS) {
OS.indent(Indent);
switch (N->getKind()) {
@@ -434,7 +432,7 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
if (i == 0) {
OS << "OPC_Scope, ";
++CurrentIdx;
} else {
} else {
if (!OmitComments) {
OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/";
OS.indent(Indent) << "/*Scope*/ ";
@@ -451,7 +449,7 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
}
OS << '\n';
ChildSize = EmitMatcherList(SM->getChild(i), Indent+1,
ChildSize = EmitMatcherList(SM->getChild(i), Indent + 1,
CurrentIdx + VBRSize, OS);
assert(ChildSize == SM->getChild(i)->getSize() &&
"Emitted child size does not match calculated size");
@@ -471,18 +469,15 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
case Matcher::RecordNode:
OS << "OPC_RecordNode,";
if (!OmitComments)
OS << " // #"
<< cast<RecordMatcher>(N)->getResultNo() << " = "
OS << " // #" << cast<RecordMatcher>(N)->getResultNo() << " = "
<< cast<RecordMatcher>(N)->getWhatFor();
OS << '\n';
return 1;
case Matcher::RecordChild:
OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo()
<< ',';
OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo() << ',';
if (!OmitComments)
OS << " // #"
<< cast<RecordChildMatcher>(N)->getResultNo() << " = "
OS << " // #" << cast<RecordChildMatcher>(N)->getResultNo() << " = "
<< cast<RecordChildMatcher>(N)->getWhatFor();
OS << '\n';
return 1;
@@ -522,14 +517,13 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
return 1;
case Matcher::CheckSame:
OS << "OPC_CheckSame, "
<< cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n";
OS << "OPC_CheckSame, " << cast<CheckSameMatcher>(N)->getMatchNumber()
<< ",\n";
return 2;
case Matcher::CheckChildSame:
OS << "OPC_CheckChild"
<< cast<CheckChildSameMatcher>(N)->getChildNo() << "Same, "
<< cast<CheckChildSameMatcher>(N)->getMatchNumber() << ",\n";
OS << "OPC_CheckChild" << cast<CheckChildSameMatcher>(N)->getChildNo()
<< "Same, " << cast<CheckChildSameMatcher>(N)->getMatchNumber() << ",\n";
return 2;
case Matcher::CheckPatternPredicate: {
@@ -602,10 +596,10 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
unsigned IdxSize;
if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
Child = SOM->getCaseMatcher(i);
IdxSize = 2; // size of opcode in table is 2 bytes.
IdxSize = 2; // size of opcode in table is 2 bytes.
} else {
Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
IdxSize = 1; // size of type in table is 1 byte.
IdxSize = 1; // size of type in table is 1 byte.
}
if (i != 0) {
@@ -613,8 +607,8 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/";
OS.indent(Indent);
if (!OmitComments)
OS << (isa<SwitchOpcodeMatcher>(N) ?
"/*SwitchOpcode*/ " : "/*SwitchType*/ ");
OS << (isa<SwitchOpcodeMatcher>(N) ? "/*SwitchOpcode*/ "
: "/*SwitchType*/ ");
}
unsigned ChildSize = Child->getSize();
@@ -627,7 +621,7 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
OS << "// ->" << CurrentIdx + ChildSize;
OS << '\n';
ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx, OS);
ChildSize = EmitMatcherList(Child, Indent + 1, CurrentIdx, OS);
assert(ChildSize == Child->getSize() &&
"Emitted child size does not match calculated size");
CurrentIdx += ChildSize;
@@ -638,8 +632,8 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/";
OS.indent(Indent) << "0,";
if (!OmitComments)
OS << (isa<SwitchOpcodeMatcher>(N) ?
" // EndSwitchOpcode" : " // EndSwitchType");
OS << (isa<SwitchOpcodeMatcher>(N) ? " // EndSwitchOpcode"
: " // EndSwitchType");
OS << '\n';
return CurrentIdx - StartIdx + 1;
@@ -722,7 +716,7 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
OS << " // " << Pattern.getSelectFunc();
OS << ":$" << CCPM->getName();
for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i)
OS << " #" << CCPM->getFirstResult()+i;
OS << " #" << CCPM->getFirstResult() + i;
if (Pattern.hasProperty(SDNPHasChain))
OS << " + chain result";
@@ -733,14 +727,16 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
case Matcher::CheckAndImm: {
OS << "OPC_CheckAndImm, ";
unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS);
unsigned Bytes =
1 + EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS);
OS << '\n';
return Bytes;
}
case Matcher::CheckOrImm: {
OS << "OPC_CheckOrImm, ";
unsigned Bytes = 1+EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS);
unsigned Bytes =
1 + EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS);
OS << '\n';
return Bytes;
}
@@ -843,7 +839,7 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
case Matcher::EmitMergeInputChains: {
const EmitMergeInputChainsMatcher *MN =
cast<EmitMergeInputChainsMatcher>(N);
cast<EmitMergeInputChainsMatcher>(N);
// Handle the specialized forms OPC_EmitMergeInputChains1_0, 1_1, and 1_2.
if (MN->getNumNodes() == 1 && MN->getNode(0) < 3) {
@@ -855,7 +851,7 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i)
OS << MN->getNode(i) << ", ";
OS << '\n';
return 2+MN->getNumNodes();
return 2 + MN->getNumNodes();
}
case Matcher::EmitCopyToReg: {
const auto *C2RMatcher = cast<EmitCopyToRegMatcher>(N);
@@ -884,8 +880,8 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", "
<< XF->getSlot() << ',';
if (!OmitComments)
OS << " // "<<XF->getNodeXForm()->getName();
OS <<'\n';
OS << " // " << XF->getNodeXForm()->getName();
OS << '\n';
return 3;
}
@@ -955,7 +951,7 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
}
OS << ",\n";
OS.indent(FullIndexWidth + Indent+4);
OS.indent(FullIndexWidth + Indent + 4);
if (!CompressVTs) {
OS << EN->getNumVTs();
if (!OmitComments)
@@ -980,17 +976,18 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
OS << " // Results =";
unsigned First = E->getFirstResultSlot();
for (unsigned i = 0; i != NumResults; ++i)
OS << " #" << First+i;
OS << " #" << First + i;
}
}
OS << '\n';
if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
OS.indent(FullIndexWidth + Indent) << "// Src: "
<< *SNT->getPattern().getSrcPattern() << " - Complexity = "
<< SNT->getPattern().getPatternComplexity(CGP) << '\n';
OS.indent(FullIndexWidth + Indent) << "// Dst: "
<< *SNT->getPattern().getDstPattern() << '\n';
OS.indent(FullIndexWidth + Indent)
<< "// Src: " << *SNT->getPattern().getSrcPattern()
<< " - Complexity = " << SNT->getPattern().getPatternComplexity(CGP)
<< '\n';
OS.indent(FullIndexWidth + Indent)
<< "// Dst: " << *SNT->getPattern().getDstPattern() << '\n';
}
} else
OS << '\n';
@@ -1021,11 +1018,12 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
NumResultBytes += EmitVBRValue(CM->getResult(i), OS);
OS << '\n';
if (!OmitComments) {
OS.indent(FullIndexWidth + Indent) << " // Src: "
<< *CM->getPattern().getSrcPattern() << " - Complexity = "
<< CM->getPattern().getPatternComplexity(CGP) << '\n';
OS.indent(FullIndexWidth + Indent) << " // Dst: "
<< *CM->getPattern().getDstPattern();
OS.indent(FullIndexWidth + Indent)
<< " // Src: " << *CM->getPattern().getSrcPattern()
<< " - Complexity = " << CM->getPattern().getPatternComplexity(CGP)
<< '\n';
OS.indent(FullIndexWidth + Indent)
<< " // Dst: " << *CM->getPattern().getDstPattern();
}
OS << '\n';
return 2 + NumResultBytes + NumCoveredBytes;
@@ -1036,9 +1034,10 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
/// This function traverses the matcher tree and emits all the nodes.
/// The nodes have already been sized.
unsigned MatcherTableEmitter::
EmitMatcherList(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
raw_ostream &OS) {
unsigned MatcherTableEmitter::EmitMatcherList(const Matcher *N,
const unsigned Indent,
unsigned CurrentIdx,
raw_ostream &OS) {
unsigned Size = 0;
while (N) {
if (!OmitComments)
@@ -1059,7 +1058,7 @@ void MatcherTableEmitter::EmitNodePredicatesFunction(
if (Preds.empty())
return;
BeginEmitFunction(OS, "bool", Decl, true/*AddOverride*/);
BeginEmitFunction(OS, "bool", Decl, true /*AddOverride*/);
OS << "{\n";
OS << " switch (PredNo) {\n";
OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n";
@@ -1083,12 +1082,13 @@ void MatcherTableEmitter::EmitPredicateFunctions(raw_ostream &OS) {
// Emit pattern predicates.
if (!PatternPredicates.empty()) {
BeginEmitFunction(OS, "bool",
"CheckPatternPredicate(unsigned PredNo) const", true/*AddOverride*/);
"CheckPatternPredicate(unsigned PredNo) const",
true /*AddOverride*/);
OS << "{\n";
OS << " switch (PredNo) {\n";
OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n";
for (unsigned i = 0, e = PatternPredicates.size(); i != e; ++i)
OS << " case " << i << ": return " << PatternPredicates[i] << ";\n";
OS << " case " << i << ": return " << PatternPredicates[i] << ";\n";
OS << " }\n";
OS << "}\n";
EndEmitFunction(OS);
@@ -1107,11 +1107,12 @@ void MatcherTableEmitter::EmitPredicateFunctions(raw_ostream &OS) {
// Emit CompletePattern matchers.
// FIXME: This should be const.
if (!ComplexPatterns.empty()) {
BeginEmitFunction(OS, "bool",
"CheckComplexPattern(SDNode *Root, SDNode *Parent,\n"
" SDValue N, unsigned PatternNo,\n"
" SmallVectorImpl<std::pair<SDValue, SDNode *>> &Result)",
true/*AddOverride*/);
BeginEmitFunction(
OS, "bool",
"CheckComplexPattern(SDNode *Root, SDNode *Parent,\n"
" SDValue N, unsigned PatternNo,\n"
" SmallVectorImpl<std::pair<SDValue, SDNode *>> &Result)",
true /*AddOverride*/);
OS << "{\n";
OS << " unsigned NextRes = Result.size();\n";
OS << " switch (PatternNo) {\n";
@@ -1121,7 +1122,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(raw_ostream &OS) {
unsigned NumOps = P.getNumOperands();
if (P.hasProperty(SDNPHasChain))
++NumOps; // Get the chained node too.
++NumOps; // Get the chained node too.
OS << " case " << i << ":\n";
if (InstrumentCoverage)
@@ -1160,12 +1161,12 @@ void MatcherTableEmitter::EmitPredicateFunctions(raw_ostream &OS) {
EndEmitFunction(OS);
}
// Emit SDNodeXForm handlers.
// FIXME: This should be const.
if (!NodeXForms.empty()) {
BeginEmitFunction(OS, "SDValue",
"RunSDNodeXForm(SDValue V, unsigned XFormNo)", true/*AddOverride*/);
"RunSDNodeXForm(SDValue V, unsigned XFormNo)",
true /*AddOverride*/);
OS << "{\n";
OS << " switch (XFormNo) {\n";
OS << " default: llvm_unreachable(\"Invalid xform # in table?\");\n";
@@ -1173,7 +1174,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(raw_ostream &OS) {
// FIXME: The node xform could take SDValue's instead of SDNode*'s.
for (unsigned i = 0, e = NodeXForms.size(); i != e; ++i) {
const CodeGenDAGPatterns::NodeXForm &Entry =
CGP.getSDNodeTransform(NodeXForms[i]);
CGP.getSDNodeTransform(NodeXForms[i]);
Record *SDNode = Entry.first;
const std::string &Code = Entry.second;
@@ -1281,8 +1282,7 @@ static StringRef getOpcodeString(Matcher::KindTy Kind) {
llvm_unreachable("Unhandled opcode?");
}
void MatcherTableEmitter::EmitHistogram(const Matcher *M,
raw_ostream &OS) {
void MatcherTableEmitter::EmitHistogram(const Matcher *M, raw_ostream &OS) {
if (OmitComments)
return;
@@ -1295,9 +1295,7 @@ void MatcherTableEmitter::EmitHistogram(const Matcher *M,
OS << '\n';
}
void llvm::EmitMatcherTable(Matcher *TheMatcher,
const CodeGenDAGPatterns &CGP,
void llvm::EmitMatcherTable(Matcher *TheMatcher, const CodeGenDAGPatterns &CGP,
raw_ostream &OS) {
OS << "#if defined(GET_DAGISEL_DECL) && defined(GET_DAGISEL_BODY)\n";
OS << "#error GET_DAGISEL_DECL and GET_DAGISEL_BODY cannot be both defined, ";
@@ -1328,7 +1326,7 @@ void llvm::EmitMatcherTable(Matcher *TheMatcher,
OS << "#define DAGISEL_CLASS_COLONCOLON\n";
OS << "#endif\n\n";
BeginEmitFunction(OS, "void", "SelectCode(SDNode *N)", false/*AddOverride*/);
BeginEmitFunction(OS, "void", "SelectCode(SDNode *N)", false /*AddOverride*/);
MatcherTableEmitter MatcherEmitter(TheMatcher, CGP);
// First we size all the children of the three kinds of matchers that have
@@ -1348,7 +1346,8 @@ void llvm::EmitMatcherTable(Matcher *TheMatcher,
OS << " #define TARGET_VAL(X) X & 255, unsigned(X) >> 8\n";
OS << " static const unsigned char MatcherTable[] = {\n";
TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 1, 0, OS);
OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n";
OS << " 0\n }; // Total Array size is " << (TotalSize + 1)
<< " bytes\n\n";
MatcherEmitter.EmitHistogram(TheMatcher, OS);

View File

@@ -20,7 +20,6 @@
#include <utility>
using namespace llvm;
/// getRegisterValueType - Look up and return the ValueType of the specified
/// register. If the register is a member of multiple register classes, they
/// must all have the same type.
@@ -52,96 +51,97 @@ static MVT::SimpleValueType getRegisterValueType(Record *R,
return VT;
}
namespace {
class MatcherGen {
const PatternToMatch &Pattern;
const CodeGenDAGPatterns &CGP;
class MatcherGen {
const PatternToMatch &Pattern;
const CodeGenDAGPatterns &CGP;
/// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts
/// out with all of the types removed. This allows us to insert type checks
/// as we scan the tree.
TreePatternNodePtr PatWithNoTypes;
/// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts
/// out with all of the types removed. This allows us to insert type checks
/// as we scan the tree.
TreePatternNodePtr PatWithNoTypes;
/// VariableMap - A map from variable names ('$dst') to the recorded operand
/// number that they were captured as. These are biased by 1 to make
/// insertion easier.
StringMap<unsigned> VariableMap;
/// VariableMap - A map from variable names ('$dst') to the recorded operand
/// number that they were captured as. These are biased by 1 to make
/// insertion easier.
StringMap<unsigned> VariableMap;
/// This maintains the recorded operand number that OPC_CheckComplexPattern
/// drops each sub-operand into. We don't want to insert these into
/// VariableMap because that leads to identity checking if they are
/// encountered multiple times. Biased by 1 like VariableMap for
/// consistency.
StringMap<unsigned> NamedComplexPatternOperands;
/// This maintains the recorded operand number that OPC_CheckComplexPattern
/// drops each sub-operand into. We don't want to insert these into
/// VariableMap because that leads to identity checking if they are
/// encountered multiple times. Biased by 1 like VariableMap for
/// consistency.
StringMap<unsigned> NamedComplexPatternOperands;
/// NextRecordedOperandNo - As we emit opcodes to record matched values in
/// the RecordedNodes array, this keeps track of which slot will be next to
/// record into.
unsigned NextRecordedOperandNo;
/// NextRecordedOperandNo - As we emit opcodes to record matched values in
/// the RecordedNodes array, this keeps track of which slot will be next to
/// record into.
unsigned NextRecordedOperandNo;
/// MatchedChainNodes - This maintains the position in the recorded nodes
/// array of all of the recorded input nodes that have chains.
SmallVector<unsigned, 2> MatchedChainNodes;
/// MatchedChainNodes - This maintains the position in the recorded nodes
/// array of all of the recorded input nodes that have chains.
SmallVector<unsigned, 2> MatchedChainNodes;
/// MatchedComplexPatterns - This maintains a list of all of the
/// ComplexPatterns that we need to check. The second element of each pair
/// is the recorded operand number of the input node.
SmallVector<std::pair<const TreePatternNode*,
unsigned>, 2> MatchedComplexPatterns;
/// MatchedComplexPatterns - This maintains a list of all of the
/// ComplexPatterns that we need to check. The second element of each pair
/// is the recorded operand number of the input node.
SmallVector<std::pair<const TreePatternNode *, unsigned>, 2>
MatchedComplexPatterns;
/// PhysRegInputs - List list has an entry for each explicitly specified
/// physreg input to the pattern. The first elt is the Register node, the
/// second is the recorded slot number the input pattern match saved it in.
SmallVector<std::pair<Record*, unsigned>, 2> PhysRegInputs;
/// PhysRegInputs - List list has an entry for each explicitly specified
/// physreg input to the pattern. The first elt is the Register node, the
/// second is the recorded slot number the input pattern match saved it in.
SmallVector<std::pair<Record *, unsigned>, 2> PhysRegInputs;
/// Matcher - This is the top level of the generated matcher, the result.
Matcher *TheMatcher;
/// Matcher - This is the top level of the generated matcher, the result.
Matcher *TheMatcher;
/// CurPredicate - As we emit matcher nodes, this points to the latest check
/// which should have future checks stuck into its Next position.
Matcher *CurPredicate;
public:
MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp);
/// CurPredicate - As we emit matcher nodes, this points to the latest check
/// which should have future checks stuck into its Next position.
Matcher *CurPredicate;
bool EmitMatcherCode(unsigned Variant);
void EmitResultCode();
public:
MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp);
Matcher *GetMatcher() const { return TheMatcher; }
private:
void AddMatcher(Matcher *NewNode);
void InferPossibleTypes();
bool EmitMatcherCode(unsigned Variant);
void EmitResultCode();
// Matcher Generation.
void EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes);
void EmitLeafMatchCode(const TreePatternNode *N);
void EmitOperatorMatchCode(const TreePatternNode *N,
TreePatternNode *NodeNoTypes);
Matcher *GetMatcher() const { return TheMatcher; }
/// If this is the first time a node with unique identifier Name has been
/// seen, record it. Otherwise, emit a check to make sure this is the same
/// node. Returns true if this is the first encounter.
bool recordUniqueNode(ArrayRef<std::string> Names);
private:
void AddMatcher(Matcher *NewNode);
void InferPossibleTypes();
// Result Code Generation.
unsigned getNamedArgumentSlot(StringRef Name) {
unsigned VarMapEntry = VariableMap[Name];
assert(VarMapEntry != 0 &&
"Variable referenced but not defined and not caught earlier!");
return VarMapEntry-1;
}
// Matcher Generation.
void EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes);
void EmitLeafMatchCode(const TreePatternNode *N);
void EmitOperatorMatchCode(const TreePatternNode *N,
TreePatternNode *NodeNoTypes);
void EmitResultOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
void EmitResultOfNamedOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
void EmitResultLeafAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
void EmitResultInstructionAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
void EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
};
/// If this is the first time a node with unique identifier Name has been
/// seen, record it. Otherwise, emit a check to make sure this is the same
/// node. Returns true if this is the first encounter.
bool recordUniqueNode(ArrayRef<std::string> Names);
// Result Code Generation.
unsigned getNamedArgumentSlot(StringRef Name) {
unsigned VarMapEntry = VariableMap[Name];
assert(VarMapEntry != 0 &&
"Variable referenced but not defined and not caught earlier!");
return VarMapEntry - 1;
}
void EmitResultOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
void EmitResultOfNamedOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
void EmitResultLeafAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
void EmitResultInstructionAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
void EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
};
} // end anonymous namespace
@@ -180,11 +180,10 @@ void MatcherGen::InferPossibleTypes() {
bool MadeChange = true;
while (MadeChange)
MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP,
true/*Ignore reg constraints*/);
MadeChange = PatWithNoTypes->ApplyTypeConstraints(
TP, true /*Ignore reg constraints*/);
}
/// AddMatcher - Add a matcher node to the current graph we're building.
void MatcherGen::AddMatcher(Matcher *NewNode) {
if (CurPredicate)
@@ -194,7 +193,6 @@ void MatcherGen::AddMatcher(Matcher *NewNode) {
CurPredicate = NewNode;
}
//===----------------------------------------------------------------------===//
// Pattern Match Generation
//===----------------------------------------------------------------------===//
@@ -240,7 +238,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
return AddMatcher(new CheckValueTypeMatcher(LeafRec->getName()));
}
if (// Handle register references. Nothing to do here, they always match.
if ( // Handle register references. Nothing to do here, they always match.
LeafRec->isSubClassOf("RegisterClass") ||
LeafRec->isSubClassOf("RegisterOperand") ||
LeafRec->isSubClassOf("PointerLikeRegClass") ||
@@ -252,7 +250,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
// If we have a physreg reference like (mul gpr:$src, EAX) then we need to
// record the register
if (LeafRec->isSubClassOf("Register")) {
AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName().str(),
AddMatcher(new RecordMatcher("physreg input " + LeafRec->getName().str(),
NextRecordedOperandNo));
PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++));
return;
@@ -376,7 +374,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
if (N->NodeHasProperty(SDNPHasChain, CGP)) {
// Record the node and remember it in our chained nodes list.
AddMatcher(new RecordMatcher("'" + N->getOperator()->getName().str() +
"' chained node",
"' chained node",
NextRecordedOperandNo));
// Remember all of the input chains our pattern will match.
MatchedChainNodes.push_back(NextRecordedOperandNo++);
@@ -407,7 +405,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
// this to be folded.
//
const TreePatternNode *Root = Pattern.getSrcPattern();
if (N != Root) { // Not the root of the pattern.
if (N != Root) { // Not the root of the pattern.
// If there is a node between the root and this node, then we definitely
// need to emit the check.
bool NeedCheck = !Root->hasChild(N);
@@ -419,13 +417,11 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
if (!NeedCheck) {
const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Root->getOperator());
NeedCheck =
Root->getOperator() == CGP.get_intrinsic_void_sdnode() ||
Root->getOperator() == CGP.get_intrinsic_w_chain_sdnode() ||
Root->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||
PInfo.getNumOperands() > 1 ||
PInfo.hasProperty(SDNPHasChain) ||
PInfo.hasProperty(SDNPInGlue) ||
PInfo.hasProperty(SDNPOptInGlue);
Root->getOperator() == CGP.get_intrinsic_void_sdnode() ||
Root->getOperator() == CGP.get_intrinsic_w_chain_sdnode() ||
Root->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||
PInfo.getNumOperands() > 1 || PInfo.hasProperty(SDNPHasChain) ||
PInfo.hasProperty(SDNPInGlue) || PInfo.hasProperty(SDNPOptInGlue);
}
if (NeedCheck)
@@ -434,13 +430,12 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
}
// If this node has an output glue and isn't the root, remember it.
if (N->NodeHasProperty(SDNPOutGlue, CGP) &&
N != Pattern.getSrcPattern()) {
if (N->NodeHasProperty(SDNPOutGlue, CGP) && N != Pattern.getSrcPattern()) {
// TODO: This redundantly records nodes with both glues and chains.
// Record the node and remember it in our chained nodes list.
AddMatcher(new RecordMatcher("'" + N->getOperator()->getName().str() +
"' glue output node",
"' glue output node",
NextRecordedOperandNo));
}
@@ -485,7 +480,7 @@ bool MatcherGen::recordUniqueNode(ArrayRef<std::string> Names) {
// we already have checked that the first reference is valid, we don't
// have to recursively match it, just check that it's the same as the
// previously named thing.
AddMatcher(new CheckSameMatcher(Entry-1));
AddMatcher(new CheckSameMatcher(Entry - 1));
}
for (const std::string &Name : Names)
@@ -502,7 +497,8 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N,
SmallVector<unsigned, 2> ResultsToTypeCheck;
for (unsigned i = 0, e = NodeNoTypes->getNumTypes(); i != e; ++i) {
if (NodeNoTypes->getExtType(i) == N->getExtType(i)) continue;
if (NodeNoTypes->getExtType(i) == N->getExtType(i))
continue;
NodeNoTypes->setType(i, N->getExtType(i));
InferPossibleTypes();
ResultsToTypeCheck.push_back(i);
@@ -515,7 +511,8 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N,
Names.push_back(N->getName());
for (const ScopedName &Name : N->getNamesAsPredicateArg()) {
Names.push_back(("pred:" + Twine(Name.getScope()) + ":" + Name.getIdentifier()).str());
Names.push_back(
("pred:" + Twine(Name.getScope()) + ":" + Name.getIdentifier()).str());
}
if (!Names.empty()) {
@@ -557,14 +554,17 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) {
// Depending on which variant we're generating code for, emit the root opcode
// check.
if (const ComplexPattern *CP =
Pattern.getSrcPattern()->getComplexPatternInfo(CGP)) {
const std::vector<Record*> &OpNodes = CP->getRootNodes();
assert(!OpNodes.empty() &&"Complex Pattern must specify what it can match");
if (Variant >= OpNodes.size()) return true;
Pattern.getSrcPattern()->getComplexPatternInfo(CGP)) {
const std::vector<Record *> &OpNodes = CP->getRootNodes();
assert(!OpNodes.empty() &&
"Complex Pattern must specify what it can match");
if (Variant >= OpNodes.size())
return true;
AddMatcher(new CheckOpcodeMatcher(CGP.getSDNodeInfo(OpNodes[Variant])));
} else {
if (Variant != 0) return true;
if (Variant != 0)
return true;
}
// Emit the matcher for the pattern structure and types.
@@ -616,7 +616,7 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) {
// It is the last operand recorded.
assert(NextRecordedOperandNo > 1 &&
"Should have recorded input/result chains at least!");
MatchedChainNodes.push_back(NextRecordedOperandNo-1);
MatchedChainNodes.push_back(NextRecordedOperandNo - 1);
}
// TODO: Complex patterns can't have output glues, if they did, we'd want
@@ -626,13 +626,12 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) {
return false;
}
//===----------------------------------------------------------------------===//
// Node Result Generation
//===----------------------------------------------------------------------===//
void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps){
void MatcherGen::EmitResultOfNamedOperand(
const TreePatternNode *N, SmallVectorImpl<unsigned> &ResultOps) {
assert(!N->getName().empty() && "Operand not named!");
if (unsigned SlotNo = NamedComplexPatternOperands[N->getName()]) {
@@ -676,8 +675,7 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
if (DefInit *DI = dyn_cast<DefInit>(N->getLeafValue())) {
Record *Def = DI->getDef();
if (Def->isSubClassOf("Register")) {
const CodeGenRegister *Reg =
CGP.getTargetInfo().getRegBank().getReg(Def);
const CodeGenRegister *Reg = CGP.getTargetInfo().getRegBank().getReg(Def);
AddMatcher(new EmitRegisterMatcher(Reg, N->getSimpleType(0)));
ResultOps.push_back(NextRecordedOperandNo++);
return;
@@ -746,18 +744,16 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
N->dump();
}
static bool
mayInstNodeLoadOrStore(const TreePatternNode *N,
const CodeGenDAGPatterns &CGP) {
static bool mayInstNodeLoadOrStore(const TreePatternNode *N,
const CodeGenDAGPatterns &CGP) {
Record *Op = N->getOperator();
const CodeGenTarget &CGT = CGP.getTargetInfo();
CodeGenInstruction &II = CGT.getInstruction(Op);
return II.mayLoad || II.mayStore;
}
static unsigned
numNodesThatMayLoadOrStore(const TreePatternNode *N,
const CodeGenDAGPatterns &CGP) {
static unsigned numNodesThatMayLoadOrStore(const TreePatternNode *N,
const CodeGenDAGPatterns &CGP) {
if (N->isLeaf())
return 0;
@@ -775,9 +771,8 @@ numNodesThatMayLoadOrStore(const TreePatternNode *N,
return Count;
}
void MatcherGen::
EmitResultInstructionAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &OutputOps) {
void MatcherGen::EmitResultInstructionAsOperand(
const TreePatternNode *N, SmallVectorImpl<unsigned> &OutputOps) {
Record *Op = N->getOperator();
const CodeGenTarget &CGT = CGP.getTargetInfo();
CodeGenInstruction &II = CGT.getInstruction(Op);
@@ -823,11 +818,11 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// filled in with their defaults unconditionally.
unsigned NonOverridableOperands = NumFixedOperands;
while (NonOverridableOperands > NumResults &&
CGP.operandHasDefault(II.Operands[NonOverridableOperands-1].Rec))
CGP.operandHasDefault(II.Operands[NonOverridableOperands - 1].Rec))
--NonOverridableOperands;
for (unsigned InstOpNo = NumResults, e = NumFixedOperands;
InstOpNo != e; ++InstOpNo) {
for (unsigned InstOpNo = NumResults, e = NumFixedOperands; InstOpNo != e;
++InstOpNo) {
// Determine what to emit for this operand.
Record *OperandNode = II.Operands[InstOpNo].Rec;
if (CGP.operandHasDefault(OperandNode) &&
@@ -835,8 +830,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// This is a predicate or optional def operand which the pattern has not
// overridden, or which we aren't letting it override; emit the 'default
// ops' operands.
const DAGDefaultOperand &DefaultOp
= CGP.getDefaultOperand(OperandNode);
const DAGDefaultOperand &DefaultOp = CGP.getDefaultOperand(OperandNode);
for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i)
EmitResultOperand(DefaultOp.DefaultOps[i].get(), InstOps);
continue;
@@ -865,7 +859,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// If the operand is an instruction and it produced multiple results, just
// take the first one.
if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction"))
InstOps.resize(BeforeAddingNumOps+1);
InstOps.resize(BeforeAddingNumOps + 1);
++ChildNo;
}
@@ -889,9 +883,8 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// occur in patterns like (mul:i8 AL:i8, GR8:i8:$src).
for (unsigned i = 0, e = PhysRegInputs.size(); i != e; ++i) {
const CodeGenRegister *Reg =
CGP.getTargetInfo().getRegBank().getReg(PhysRegInputs[i].first);
AddMatcher(new EmitCopyToRegMatcher(PhysRegInputs[i].second,
Reg));
CGP.getTargetInfo().getRegBank().getReg(PhysRegInputs[i].first);
AddMatcher(new EmitCopyToRegMatcher(PhysRegInputs[i].second, Reg));
}
// Even if the node has no other glue inputs, the resultant node must be
@@ -919,7 +912,8 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
HandledReg = II.ImplicitDefs[0];
for (Record *Reg : Pattern.getDstRegs()) {
if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
if (!Reg->isSubClassOf("Register") || Reg == HandledReg)
continue;
ResultVTs.push_back(getRegisterValueType(Reg, CGT));
}
}
@@ -928,8 +922,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// a node that is variadic, mark the generated node as variadic so that it
// gets the excess operands from the input DAG.
int NumFixedArityOperands = -1;
if (isRoot &&
Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))
if (isRoot && Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))
NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren();
// If this is the root node and multiple matched nodes in the input pattern
@@ -940,17 +933,17 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// FIXME3: This is actively incorrect for result patterns with multiple
// memory-referencing instructions.
bool PatternHasMemOperands =
Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP);
Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP);
bool NodeHasMemRefs = false;
if (PatternHasMemOperands) {
unsigned NumNodesThatLoadOrStore =
numNodesThatMayLoadOrStore(Pattern.getDstPattern(), CGP);
bool NodeIsUniqueLoadOrStore = mayInstNodeLoadOrStore(N, CGP) &&
NumNodesThatLoadOrStore == 1;
numNodesThatMayLoadOrStore(Pattern.getDstPattern(), CGP);
bool NodeIsUniqueLoadOrStore =
mayInstNodeLoadOrStore(N, CGP) && NumNodesThatLoadOrStore == 1;
NodeHasMemRefs =
NodeIsUniqueLoadOrStore || (isRoot && (mayInstNodeLoadOrStore(N, CGP) ||
NumNodesThatLoadOrStore != 1));
NodeIsUniqueLoadOrStore || (isRoot && (mayInstNodeLoadOrStore(N, CGP) ||
NumNodesThatLoadOrStore != 1));
}
// Determine whether we need to attach a chain to this node.
@@ -982,14 +975,14 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
// The non-chain and non-glue results of the newly emitted node get recorded.
for (unsigned i = 0, e = ResultVTs.size(); i != e; ++i) {
if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Glue) break;
if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Glue)
break;
OutputOps.push_back(NextRecordedOperandNo++);
}
}
void MatcherGen::
EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps) {
void MatcherGen::EmitResultSDNodeXFormAsOperand(
const TreePatternNode *N, SmallVectorImpl<unsigned> &ResultOps) {
assert(N->getOperator()->isSubClassOf("SDNodeXForm") && "Not SDNodeXForm?");
// Emit the operand.
@@ -1051,7 +1044,8 @@ void MatcherGen::EmitResultCode() {
// don't re-add it.
Record *HandledReg = nullptr;
const TreePatternNode *DstPat = Pattern.getDstPattern();
if (!DstPat->isLeaf() &&DstPat->getOperator()->isSubClassOf("Instruction")){
if (!DstPat->isLeaf() &&
DstPat->getOperator()->isSubClassOf("Instruction")) {
const CodeGenTarget &CGT = CGP.getTargetInfo();
CodeGenInstruction &II = CGT.getInstruction(DstPat->getOperator());
@@ -1060,7 +1054,8 @@ void MatcherGen::EmitResultCode() {
}
for (Record *Reg : Pattern.getDstRegs()) {
if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
if (!Reg->isSubClassOf("Register") || Reg == HandledReg)
continue;
++NumSrcResults;
}
}
@@ -1077,7 +1072,6 @@ void MatcherGen::EmitResultCode() {
AddMatcher(new CompleteMatchMatcher(Results, Pattern));
}
/// ConvertPatternToMatcher - Create the matcher for the specified pattern with
/// the specified variant. If the variant number is invalid, this returns null.
Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern,

View File

@@ -311,10 +311,9 @@ static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
// Don't print if it's obvious nothing extract could be merged anyway.
std::next(J) != E) {
LLVM_DEBUG(errs() << "Couldn't merge this:\n"; Optn->print(errs(), 4);
errs() << "into this:\n";
(*J)->print(errs(), 4);
errs() << "into this:\n"; (*J)->print(errs(), 4);
(*std::next(J))->printOne(errs());
if (std::next(J, 2) != E) (*std::next(J, 2))->printOne(errs());
if (std::next(J, 2) != E)(*std::next(J, 2))->printOne(errs());
errs() << "\n");
}

View File

@@ -147,8 +147,8 @@ void DfaEmitter::emit(StringRef Name, raw_ostream &OS) {
OS << "// A table of DFA transitions, ordered by {FromDfaState, Action}.\n";
OS << "// The initial state is 1, not zero.\n";
OS << "const std::array<" << Name << "Transition, "
<< DfaTransitions.size() << "> " << Name << "Transitions = {{\n";
OS << "const std::array<" << Name << "Transition, " << DfaTransitions.size()
<< "> " << Name << "Transitions = {{\n";
for (auto &KV : DfaTransitions) {
dfa_state_type From = KV.first.first;
dfa_state_type To = KV.second.first;
@@ -284,7 +284,7 @@ void Automaton::emit(raw_ostream &OS) {
}
LLVM_DEBUG(dbgs() << " NFA automaton has " << SeenStates.size()
<< " states with " << NumTransitions << " transitions.\n");
(void) NumTransitions;
(void)NumTransitions;
const auto &ActionTypes = Transitions.back().getTypes();
OS << "// The type of an action in the " << Name << " automaton.\n";
@@ -346,9 +346,7 @@ bool Transition::canTransitionFrom(uint64_t State) {
return false;
}
uint64_t Transition::transitionFrom(uint64_t State) {
return State | NewState;
}
uint64_t Transition::transitionFrom(uint64_t State) { return State | NewState; }
void CustomDfaEmitter::printActionType(raw_ostream &OS) { OS << TypeName; }

View File

@@ -72,8 +72,7 @@ public:
DFAPacketizerEmitter(RecordKeeper &R);
// Construct a map of function unit names to bits.
int collectAllFuncUnits(
ArrayRef<const CodeGenProcModel *> ProcModels);
int collectAllFuncUnits(ArrayRef<const CodeGenProcModel *> ProcModels);
// Construct a map from a combo function unit bit to the bits of all included
// functional units.
@@ -129,7 +128,8 @@ int DFAPacketizerEmitter::collectAllFuncUnits(
return totalFUs;
}
int DFAPacketizerEmitter::collectAllComboFuncs(ArrayRef<Record *> ComboFuncList) {
int DFAPacketizerEmitter::collectAllComboFuncs(
ArrayRef<Record *> ComboFuncList) {
LLVM_DEBUG(dbgs() << "-------------------------------------------------------"
"----------------------\n");
LLVM_DEBUG(dbgs() << "collectAllComboFuncs");

View File

@@ -42,22 +42,23 @@ struct DXILParameter {
};
struct DXILOperationDesc {
StringRef OpName; // name of DXIL operation
int OpCode; // ID of DXIL operation
StringRef OpClass; // name of the opcode class
StringRef Category; // classification for this instruction
StringRef Doc; // the documentation description of this instruction
StringRef OpName; // name of DXIL operation
int OpCode; // ID of DXIL operation
StringRef OpClass; // name of the opcode class
StringRef Category; // classification for this instruction
StringRef Doc; // the documentation description of this instruction
SmallVector<DXILParameter> Params; // the operands that this instruction takes
StringRef OverloadTypes; // overload types if applicable
StringRef FnAttr; // attribute shorthands: rn=does not access
// memory,ro=only reads from memory
StringRef Intrinsic; // The llvm intrinsic map to OpName. Default is "" which
// means no map exist
bool IsDeriv = false; // whether this is some kind of derivative
StringRef OverloadTypes; // overload types if applicable
StringRef FnAttr; // attribute shorthands: rn=does not access
// memory,ro=only reads from memory
StringRef Intrinsic; // The llvm intrinsic map to OpName. Default is "" which
// means no map exist
bool IsDeriv = false; // whether this is some kind of derivative
bool IsGradient = false; // whether this requires a gradient calculation
bool IsFeedback = false; // whether this is a sampler feedback op
bool IsWave = false; // whether this requires in-wave, cross-lane functionality
bool IsWave =
false; // whether this requires in-wave, cross-lane functionality
bool RequiresUniformInputs = false; // whether this operation requires that
// all of its inputs are uniform across
// the wave

View File

@@ -53,7 +53,8 @@ using namespace llvm;
namespace {
STATISTIC(NumEncodings, "Number of encodings considered");
STATISTIC(NumEncodingsLackingDisasm, "Number of encodings without disassembler info");
STATISTIC(NumEncodingsLackingDisasm,
"Number of encodings without disassembler info");
STATISTIC(NumInstructions, "Number of instructions considered");
STATISTIC(NumEncodingsSupported, "Number of encodings supported");
STATISTIC(NumEncodingsOmitted, "Number of encodings omitted");
@@ -61,7 +62,7 @@ STATISTIC(NumEncodingsOmitted, "Number of encodings omitted");
struct EncodingField {
unsigned Base, Width, Offset;
EncodingField(unsigned B, unsigned W, unsigned O)
: Base(B), Width(W), Offset(O) { }
: Base(B), Width(W), Offset(O) {}
};
struct OperandInfo {
@@ -82,7 +83,7 @@ struct OperandInfo {
typedef std::vector<EncodingField>::const_iterator const_iterator;
const_iterator begin() const { return Fields.begin(); }
const_iterator end() const { return Fields.end(); }
const_iterator end() const { return Fields.end(); }
};
typedef std::vector<uint8_t> DecoderTable;
@@ -141,8 +142,7 @@ public:
void emitPredicateFunction(formatted_raw_ostream &OS,
PredicateSet &Predicates,
unsigned Indentation) const;
void emitDecoderFunction(formatted_raw_ostream &OS,
DecoderSet &Decoders,
void emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
unsigned Indentation) const;
// run - Output the code emitter
@@ -173,9 +173,7 @@ static bool ValueSet(bit_value_t V) {
return (V == BIT_TRUE || V == BIT_FALSE);
}
static bool ValueNotSet(bit_value_t V) {
return (V == BIT_UNSET);
}
static bool ValueNotSet(bit_value_t V) { return (V == BIT_UNSET); }
static int Value(bit_value_t V) {
return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1);
@@ -280,14 +278,14 @@ class FilterChooser;
/// version and return the Opcode since the two have the same Asm format string.
class Filter {
protected:
const FilterChooser *Owner;// points to the FilterChooser who owns this filter
const FilterChooser
*Owner; // points to the FilterChooser who owns this filter
unsigned StartBit; // the starting bit position
unsigned NumBits; // number of bits to filter
bool Mixed; // a mixed region contains both set and unset bits
unsigned NumBits; // number of bits to filter
bool Mixed; // a mixed region contains both set and unset bits
// Map of well-known segment value to the set of uid's with that value.
std::map<uint64_t, std::vector<EncodingIDAndOpcode>>
FilteredInstructions;
std::map<uint64_t, std::vector<EncodingIDAndOpcode>> FilteredInstructions;
// Set of uid's with non-constant segment values.
std::vector<EncodingIDAndOpcode> VariableInstructions;
@@ -471,7 +469,7 @@ protected:
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars.
void dumpFilterArray(raw_ostream &o,
const std::vector<bit_value_t> & filter) const;
const std::vector<bit_value_t> &filter) const;
/// dumpStack - dumpStack traverses the filter chooser chain and calls
/// dumpFilterArray on each filter chooser up to the top level one.
@@ -504,11 +502,9 @@ protected:
bool doesOpcodeNeedPredicate(unsigned Opc) const;
unsigned getPredicateIndex(DecoderTableInfo &TableInfo, StringRef P) const;
void emitPredicateTableEntry(DecoderTableInfo &TableInfo,
unsigned Opc) const;
void emitPredicateTableEntry(DecoderTableInfo &TableInfo, unsigned Opc) const;
void emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
unsigned Opc) const;
void emitSoftFailTableEntry(DecoderTableInfo &TableInfo, unsigned Opc) const;
// Emits table entries to decode the singleton.
void emitSingletonTableEntry(DecoderTableInfo &TableInfo,
@@ -560,16 +556,15 @@ public:
///////////////////////////
Filter::Filter(Filter &&f)
: Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed),
FilteredInstructions(std::move(f.FilteredInstructions)),
VariableInstructions(std::move(f.VariableInstructions)),
FilterChooserMap(std::move(f.FilterChooserMap)), NumFiltered(f.NumFiltered),
LastOpcFiltered(f.LastOpcFiltered) {
}
: Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed),
FilteredInstructions(std::move(f.FilteredInstructions)),
VariableInstructions(std::move(f.VariableInstructions)),
FilterChooserMap(std::move(f.FilterChooserMap)),
NumFiltered(f.NumFiltered), LastOpcFiltered(f.LastOpcFiltered) {}
Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
bool mixed)
: Owner(&owner), StartBit(startBit), NumBits(numBits), Mixed(mixed) {
: Owner(&owner), StartBit(startBit), NumBits(numBits), Mixed(mixed) {
assert(StartBit + NumBits - 1 < Owner->BitWidth);
NumFiltered = 0;
@@ -598,8 +593,8 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
}
}
assert((FilteredInstructions.size() + VariableInstructions.size() > 0)
&& "Filter returns no instruction categories");
assert((FilteredInstructions.size() + VariableInstructions.size() > 0) &&
"Filter returns no instruction categories");
}
// Divides the decoding task into sub tasks and delegates them to the
@@ -619,9 +614,11 @@ void Filter::recurse() {
// Delegates to an inferior filter chooser for further processing on this
// group of instructions whose segment values are variable.
FilterChooserMap.insert(std::make_pair(NO_FIXED_SEGMENTS_SENTINEL,
FilterChooserMap.insert(std::make_pair(
NO_FIXED_SEGMENTS_SENTINEL,
std::make_unique<FilterChooser>(Owner->AllInstructions,
VariableInstructions, Owner->Operands, BitValueArray, *Owner)));
VariableInstructions, Owner->Operands,
BitValueArray, *Owner)));
}
// No need to recurse for a singleton filtered instruction.
@@ -646,8 +643,8 @@ void Filter::recurse() {
// category of instructions.
FilterChooserMap.insert(std::make_pair(
Inst.first, std::make_unique<FilterChooser>(
Owner->AllInstructions, Inst.second,
Owner->Operands, BitValueArray, *Owner)));
Owner->AllInstructions, Inst.second, Owner->Operands,
BitValueArray, *Owner)));
}
}
@@ -655,8 +652,7 @@ static void resolveTableFixups(DecoderTable &Table, const FixupList &Fixups,
uint32_t DestIdx) {
// Any NumToSkip fixups in the current scope can resolve to the
// current location.
for (FixupList::const_reverse_iterator I = Fixups.rbegin(),
E = Fixups.rend();
for (FixupList::const_reverse_iterator I = Fixups.rbegin(), E = Fixups.rend();
I != E; ++I) {
// Calculate the distance from the byte following the fixup entry byte
// to the destination. The Target is calculated from after the 16-bit
@@ -705,7 +701,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
// Resolve any NumToSkip fixups in the current scope.
resolveTableFixups(Table, CurScope, Table.size());
CurScope.clear();
PrevFilter = 0; // Don't re-process the filter's fallthrough.
PrevFilter = 0; // Don't re-process the filter's fallthrough.
} else {
Table.push_back(MCD::OPC_FilterValue);
// Encode and emit the value to filter against.
@@ -731,7 +727,8 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
// two as to account for the width of the NumToSkip field itself.
if (PrevFilter) {
uint32_t NumToSkip = Table.size() - PrevFilter - 3;
assert(NumToSkip < (1u << 24) && "disassembler decoding table too large!");
assert(NumToSkip < (1u << 24) &&
"disassembler decoding table too large!");
Table[PrevFilter] = (uint8_t)NumToSkip;
Table[PrevFilter + 1] = (uint8_t)(NumToSkip >> 8);
Table[PrevFilter + 2] = (uint8_t)(NumToSkip >> 16);
@@ -771,7 +768,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
unsigned Indentation, unsigned BitWidth,
StringRef Namespace) const {
OS.indent(Indentation) << "static const uint8_t DecoderTable" << Namespace
<< BitWidth << "[] = {\n";
<< BitWidth << "[] = {\n";
Indentation += 2;
@@ -807,7 +804,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
DecoderTable::const_iterator I = Table.begin();
DecoderTable::const_iterator E = Table.end();
while (I != E) {
assert (I < E && "incomplete decode table entry!");
assert(I < E && "incomplete decode table entry!");
uint64_t Pos = I - Table.begin();
OS << "/* " << Pos << " */";
@@ -884,8 +881,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
Table.data() + Table.size(), &ErrMsg);
assert(ErrMsg == nullptr && "ULEB128 value too large!");
OS.indent(Indentation) << "MCD::OPC_" << (IsTry ? "Try" : "")
<< "Decode, ";
OS.indent(Indentation)
<< "MCD::OPC_" << (IsTry ? "Try" : "") << "Decode, ";
I += emitULEB128(I, OS);
// Decoder index.
@@ -967,15 +964,16 @@ void DecoderEmitter::emitPredicateFunction(formatted_raw_ostream &OS,
// The predicate function is just a big switch statement based on the
// input predicate index.
OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
<< "const FeatureBitset &Bits) {\n";
<< "const FeatureBitset &Bits) {\n";
Indentation += 2;
if (!Predicates.empty()) {
OS.indent(Indentation) << "switch (Idx) {\n";
OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
OS.indent(Indentation)
<< "default: llvm_unreachable(\"Invalid index!\");\n";
unsigned Index = 0;
for (const auto &Predicate : Predicates) {
OS.indent(Indentation) << "case " << Index++ << ":\n";
OS.indent(Indentation+2) << "return (" << Predicate << ");\n";
OS.indent(Indentation + 2) << "return (" << Predicate << ");\n";
}
OS.indent(Indentation) << "}\n";
} else {
@@ -993,7 +991,7 @@ void DecoderEmitter::emitDecoderFunction(formatted_raw_ostream &OS,
// input decoder index.
OS.indent(Indentation) << "template <typename InsnType>\n";
OS.indent(Indentation) << "static DecodeStatus decodeToMCInst(DecodeStatus S,"
<< " unsigned Idx, InsnType insn, MCInst &MI,\n";
<< " unsigned Idx, InsnType insn, MCInst &MI,\n";
OS.indent(Indentation)
<< " uint64_t "
<< "Address, const MCDisassembler *Decoder, bool &DecodeComplete) {\n";
@@ -1012,7 +1010,7 @@ void DecoderEmitter::emitDecoderFunction(formatted_raw_ostream &OS,
for (const auto &Decoder : Decoders) {
OS.indent(Indentation) << "case " << Index++ << ":\n";
OS << Decoder;
OS.indent(Indentation+2) << "return S;\n";
OS.indent(Indentation + 2) << "return S;\n";
}
OS.indent(Indentation) << "}\n";
Indentation -= 2;
@@ -1041,8 +1039,8 @@ bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars.
void FilterChooser::dumpFilterArray(raw_ostream &o,
const std::vector<bit_value_t> &filter) const {
void FilterChooser::dumpFilterArray(
raw_ostream &o, const std::vector<bit_value_t> &filter) const {
for (unsigned bitIndex = BitWidth; bitIndex > 0; bitIndex--) {
switch (filter[bitIndex - 1]) {
case BIT_UNFILTERED:
@@ -1096,7 +1094,8 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
int64_t Val = Value(Insn[i]);
bool Filtered = PositionFiltered(i);
switch (State) {
default: llvm_unreachable("Unreachable code!");
default:
llvm_unreachable("Unreachable code!");
case 0:
case 1:
if (Filtered || Val == -1)
@@ -1197,8 +1196,7 @@ void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation,
}
}
unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
unsigned Opc,
unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, unsigned Opc,
bool &HasCompleteDecoder) const {
// Build up the predicate string.
SmallString<256> Decoder;
@@ -1343,7 +1341,8 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
const RecordVal *RV = AllInstructions[Opc].EncodingDef->getValue("SoftFail");
BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr;
if (!SFBits) return;
if (!SFBits)
return;
BitsInit *InstBits =
AllInstructions[Opc].EncodingDef->getValueAsBitsInit("Inst");
@@ -1353,7 +1352,8 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
bit_value_t B = bitFromBits(*SFBits, i);
bit_value_t IB = bitFromBits(*InstBits, i);
if (B != BIT_TRUE) continue;
if (B != BIT_TRUE)
continue;
switch (IB) {
case BIT_FALSE:
@@ -1458,12 +1458,12 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
// 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);
TableInfo.Table.push_back(HasCompleteDecoder ? MCD::OPC_Decode
: MCD::OPC_TryDecode);
NumEncodingsSupported++;
uint8_t Buffer[16], *p;
encodeULEB128(Opc.Opcode, Buffer);
for (p = Buffer; *p >= 128 ; ++p)
for (p = Buffer; *p >= 128; ++p)
TableInfo.Table.push_back(*p);
TableInfo.Table.push_back(*p);
@@ -1825,8 +1825,8 @@ static std::string findOperandDecoderMethod(Record *Record) {
std::string Decoder;
RecordVal *DecoderString = Record->getValue("DecoderMethod");
StringInit *String = DecoderString ?
dyn_cast<StringInit>(DecoderString->getValue()) : nullptr;
StringInit *String =
DecoderString ? dyn_cast<StringInit>(DecoderString->getValue()) : nullptr;
if (String) {
Decoder = std::string(String->getValue());
if (!Decoder.empty())
@@ -1840,7 +1840,7 @@ static std::string findOperandDecoderMethod(Record *Record) {
Decoder = "Decode" + Record->getName().str() + "RegisterClass";
} else if (Record->isSubClassOf("PointerLikeRegClass")) {
Decoder = "DecodePointerLikeRegClass" +
utostr(Record->getValueAsInt("RegClassKind"));
utostr(Record->getValueAsInt("RegClassKind"));
}
return Decoder;
@@ -1986,7 +1986,8 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
// of trying to auto-generate the decoder.
StringRef InstDecoder = EncodingDef.getValueAsString("DecoderMethod");
if (InstDecoder != "") {
bool HasCompleteInstDecoder = EncodingDef.getValueAsBit("hasCompleteDecoder");
bool HasCompleteInstDecoder =
EncodingDef.getValueAsBit("hasCompleteDecoder");
InsnOperands.push_back(
OperandInfo(std::string(InstDecoder), HasCompleteInstDecoder));
Operands[Opc] = InsnOperands;
@@ -2000,9 +2001,9 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
// Gather the outputs/inputs of the instruction, so we can find their
// positions in the encoding. This assumes for now that they appear in the
// MCInst in the order that they're listed.
std::vector<std::pair<Init*, StringRef>> InOutOperands;
DagInit *Out = Def.getValueAsDag("OutOperandList");
DagInit *In = Def.getValueAsDag("InOperandList");
std::vector<std::pair<Init *, StringRef>> InOutOperands;
DagInit *Out = Def.getValueAsDag("OutOperandList");
DagInit *In = Def.getValueAsDag("InOperandList");
for (unsigned i = 0; i < Out->getNumArgs(); ++i)
InOutOperands.push_back(
std::make_pair(Out->getArg(i), Out->getArgNameStr(i)));
@@ -2042,7 +2043,8 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
Init *OpInit = Op.first;
StringRef OpName = Op.second;
// We're ready to find the instruction encoding locations for this operand.
// We're ready to find the instruction encoding locations for this
// operand.
// First, find the operand type ("OpInit"), and sub-op names
// ("SubArgDag") if present.
@@ -2056,7 +2058,8 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
? OpTypeRec->getValueAsDag("MIOperandInfo")
: nullptr;
// Lookup the decoder method and construct a new OperandInfo to hold our result.
// Lookup the decoder method and construct a new OperandInfo to hold our
// result.
OperandInfo OpInfo = getOpInfo(OpTypeRec);
// If we have named sub-operands...
@@ -2490,7 +2493,8 @@ void DecoderEmitter::run(raw_ostream &o) {
NumberedEncodings.emplace_back(NumberedInstruction->TheDef,
NumberedInstruction, HwModeName);
}
for (const auto &NumberedAlias : RK.getAllDerivedDefinitions("AdditionalEncoding"))
for (const auto &NumberedAlias :
RK.getAllDerivedDefinitions("AdditionalEncoding"))
NumberedEncodings.emplace_back(
NumberedAlias,
&Target.getInstruction(NumberedAlias->getValueAsDef("AliasOf")));
@@ -2551,8 +2555,8 @@ void DecoderEmitter::run(raw_ostream &o) {
DecoderTableInfo TableInfo;
for (const auto &Opc : OpcMap) {
// Emit the decoder for this namespace+width combination.
ArrayRef<EncodingAndInst> NumberedEncodingsRef(
NumberedEncodings.data(), NumberedEncodings.size());
ArrayRef<EncodingAndInst> NumberedEncodingsRef(NumberedEncodings.data(),
NumberedEncodings.size());
FilterChooser FC(NumberedEncodingsRef, Opc.second, Operands,
IsVarLenInst ? MaxInstLen : 8 * Opc.first.second, this);

View File

@@ -102,8 +102,8 @@ static void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
if (Target.getName() == "X86") {
DisassemblerTables Tables;
ArrayRef<const CodeGenInstruction*> numberedInstructions =
Target.getInstructionsByEnumValue();
ArrayRef<const CodeGenInstruction *> numberedInstructions =
Target.getInstructionsByEnumValue();
for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i)
RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i);

View File

@@ -1,4 +1,4 @@
///===- FastISelEmitter.cpp - Generate an instruction selector -------------===//
///===- FastISelEmitter.cpp - Generate an instruction selector ------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -30,7 +30,6 @@
#include <utility>
using namespace llvm;
/// InstructionMemo - This class holds additional information about an
/// instruction needed to emit code for it.
///
@@ -61,15 +60,15 @@ namespace {
class ImmPredicateSet {
DenseMap<TreePattern *, unsigned> ImmIDs;
std::vector<TreePredicateFn> PredsByName;
public:
public:
unsigned getIDFor(TreePredicateFn Pred) {
unsigned &Entry = ImmIDs[Pred.getOrigPatFragRecord()];
if (Entry == 0) {
PredsByName.push_back(Pred);
Entry = PredsByName.size();
}
return Entry-1;
return Entry - 1;
}
const TreePredicateFn &getPredicate(unsigned i) {
@@ -80,7 +79,6 @@ public:
typedef std::vector<TreePredicateFn>::const_iterator iterator;
iterator begin() const { return PredsByName.begin(); }
iterator end() const { return PredsByName.end(); }
};
} // End anonymous namespace
@@ -92,26 +90,39 @@ struct OperandsSignature {
class OpKind {
enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 };
char Repr;
public:
public:
OpKind() : Repr(OK_Invalid) {}
bool operator<(OpKind RHS) const { return Repr < RHS.Repr; }
bool operator==(OpKind RHS) const { return Repr == RHS.Repr; }
static OpKind getReg() { OpKind K; K.Repr = OK_Reg; return K; }
static OpKind getFP() { OpKind K; K.Repr = OK_FP; return K; }
static OpKind getReg() {
OpKind K;
K.Repr = OK_Reg;
return K;
}
static OpKind getFP() {
OpKind K;
K.Repr = OK_FP;
return K;
}
static OpKind getImm(unsigned V) {
assert((unsigned)OK_Imm+V < 128 &&
assert((unsigned)OK_Imm + V < 128 &&
"Too many integer predicates for the 'Repr' char");
OpKind K; K.Repr = OK_Imm+V; return K;
OpKind K;
K.Repr = OK_Imm + V;
return K;
}
bool isReg() const { return Repr == OK_Reg; }
bool isFP() const { return Repr == OK_FP; }
bool isFP() const { return Repr == OK_FP; }
bool isImm() const { return Repr >= OK_Imm; }
unsigned getImmCode() const { assert(isImm()); return Repr-OK_Imm; }
unsigned getImmCode() const {
assert(isImm());
return Repr - OK_Imm;
}
void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,
bool StripImmCodes) const {
@@ -123,12 +134,11 @@ struct OperandsSignature {
OS << 'i';
if (!StripImmCodes)
if (unsigned Code = getImmCode())
OS << "_" << ImmPredicates.getPredicate(Code-1).getFnName();
OS << "_" << ImmPredicates.getPredicate(Code - 1).getFnName();
}
}
};
SmallVector<OpKind, 3> Operands;
bool operator<(const OperandsSignature &O) const {
@@ -162,15 +172,17 @@ struct OperandsSignature {
void emitImmediatePredicate(raw_ostream &OS, ImmPredicateSet &ImmPredicates) {
bool EmittedAnything = false;
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (!Operands[i].isImm()) continue;
if (!Operands[i].isImm())
continue;
unsigned Code = Operands[i].getImmCode();
if (Code == 0) continue;
if (Code == 0)
continue;
if (EmittedAnything)
OS << " &&\n ";
TreePredicateFn PredFn = ImmPredicates.getPredicate(Code-1);
TreePredicateFn PredFn = ImmPredicates.getPredicate(Code - 1);
// Emit the type check.
TreePattern *TP = PredFn.getOrigPatFragRecord();
@@ -179,7 +191,7 @@ struct OperandsSignature {
"Cannot use variable value types with fast isel");
OS << "VT == " << getEnumName(VVT.getSimple().SimpleTy) << " && ";
OS << PredFn.getFnName() << "(imm" << i <<')';
OS << PredFn.getFnName() << "(imm" << i << ')';
EmittedAnything = true;
}
}
@@ -189,8 +201,7 @@ struct OperandsSignature {
/// are supported, false otherwise.
///
bool initialize(TreePatternNode *InstPatNode, const CodeGenTarget &Target,
MVT::SimpleValueType VT,
ImmPredicateSet &ImmediatePredicates,
MVT::SimpleValueType VT, ImmPredicateSet &ImmediatePredicates,
const CodeGenRegisterClass *OrigDstRC) {
if (InstPatNode->isLeaf())
return false;
@@ -229,21 +240,20 @@ struct OperandsSignature {
if (Rec->getValueAsBit("FastIselShouldIgnore"))
return false;
PredNo = ImmediatePredicates.getIDFor(PredFn)+1;
PredNo = ImmediatePredicates.getIDFor(PredFn) + 1;
}
Operands.push_back(OpKind::getImm(PredNo));
continue;
}
// For now, filter out any operand with a predicate.
// For now, filter out any operand with multiple values.
if (!Op->getPredicateCalls().empty() || Op->getNumTypes() != 1)
return false;
if (!Op->isLeaf()) {
if (Op->getOperator()->getName() == "fpimm") {
if (Op->getOperator()->getName() == "fpimm") {
Operands.push_back(OpKind::getFP());
continue;
}
@@ -347,7 +357,6 @@ struct OperandsSignature {
}
}
void PrintManglingSuffix(raw_ostream &OS, const std::vector<std::string> &PR,
ImmPredicateSet &ImmPredicates,
bool StripImmCodes = false) const {
@@ -380,7 +389,7 @@ class FastISelMap {
typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap;
typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap;
typedef std::map<OperandsSignature, OpcodeTypeRetPredMap>
OperandsOpcodeTypeRetPredMap;
OperandsOpcodeTypeRetPredMap;
OperandsOpcodeTypeRetPredMap SimplePatterns;
@@ -389,22 +398,22 @@ class FastISelMap {
MVT::SimpleValueType, std::string>>
SimplePatternsCheck;
std::map<OperandsSignature, std::vector<OperandsSignature> >
SignaturesWithConstantForms;
std::map<OperandsSignature, std::vector<OperandsSignature>>
SignaturesWithConstantForms;
StringRef InstNS;
ImmPredicateSet ImmediatePredicates;
public:
explicit FastISelMap(StringRef InstNS);
void collectPatterns(CodeGenDAGPatterns &CGP);
void printImmediatePredicates(raw_ostream &OS);
void printFunctionDefinitions(raw_ostream &OS);
private:
void emitInstructionCode(raw_ostream &OS,
const OperandsSignature &Operands,
const PredMap &PM,
const std::string &RetVTName);
void emitInstructionCode(raw_ostream &OS, const OperandsSignature &Operands,
const PredMap &PM, const std::string &RetVTName);
};
} // End anonymous namespace
@@ -433,7 +442,7 @@ static std::string PhyRegForNode(TreePatternNode *Op,
return PhysReg;
PhysReg += cast<StringInit>(OpLeafRec->getValue("Namespace")->getValue())
->getValue();
->getValue();
PhysReg += "::";
PhysReg += Target.getRegBank().getReg(OpLeafRec)->getName();
return PhysReg;
@@ -443,14 +452,15 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
const CodeGenTarget &Target = CGP.getTargetInfo();
// Scan through all the patterns and record the simple ones.
for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
E = CGP.ptm_end(); I != E; ++I) {
for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();
I != E; ++I) {
const PatternToMatch &Pattern = *I;
// For now, just look at Instructions, so that we don't have to worry
// about emitting multiple instructions for a pattern.
TreePatternNode *Dst = Pattern.getDstPattern();
if (Dst->isLeaf()) continue;
if (Dst->isLeaf())
continue;
Record *Op = Dst->getOperator();
if (!Op->isSubClassOf("Instruction"))
continue;
@@ -495,7 +505,8 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
} else {
// If this isn't a leaf, then continue since the register classes are
// a bit too complicated for now.
if (!Dst->getChild(1)->isLeaf()) continue;
if (!Dst->getChild(1)->isLeaf())
continue;
DefInit *SR = dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue());
if (SR)
@@ -506,16 +517,20 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
// Inspect the pattern.
TreePatternNode *InstPatNode = Pattern.getSrcPattern();
if (!InstPatNode) continue;
if (InstPatNode->isLeaf()) continue;
if (!InstPatNode)
continue;
if (InstPatNode->isLeaf())
continue;
// Ignore multiple result nodes for now.
if (InstPatNode->getNumTypes() > 1) continue;
if (InstPatNode->getNumTypes() > 1)
continue;
Record *InstPatOp = InstPatNode->getOperator();
std::string OpcodeName = getOpcodeName(InstPatOp, CGP);
MVT::SimpleValueType RetVT = MVT::isVoid;
if (InstPatNode->getNumTypes()) RetVT = InstPatNode->getSimpleType(0);
if (InstPatNode->getNumTypes())
RetVT = InstPatNode->getSimpleType(0);
MVT::SimpleValueType VT = RetVT;
if (InstPatNode->getNumChildren()) {
assert(InstPatNode->getChild(0)->getNumTypes() == 1);
@@ -546,7 +561,7 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
if (PhysReg.empty()) {
if (DstIndex >= Dst->getNumChildren() ||
Dst->getChild(DstIndex)->getName() !=
InstPatNode->getChild(i)->getName()) {
InstPatNode->getChild(i)->getName()) {
FoundNonSimplePattern = true;
break;
}
@@ -568,21 +583,16 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
raw_string_ostream SuffixOS(ManglingSuffix);
Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true);
if (!StringSwitch<bool>(ManglingSuffix)
.Cases("", "r", "rr", "ri", "i", "f", true)
.Default(false))
.Cases("", "r", "rr", "ri", "i", "f", true)
.Default(false))
continue;
// Get the predicate that guards this pattern.
std::string PredicateCheck = Pattern.getPredicateCheck();
// Ok, we found a pattern that we can handle. Remember it.
InstructionMemo Memo(
Pattern.getDstPattern()->getOperator()->getName(),
DstRC,
SubRegNo,
PhysRegInputs,
PredicateCheck
);
InstructionMemo Memo(Pattern.getDstPattern()->getOperator()->getName(),
DstRC, SubRegNo, PhysRegInputs, PredicateCheck);
int complexity = Pattern.getPatternComplexity(CGP);
@@ -590,7 +600,7 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
std::make_tuple(Operands, OpcodeName, VT, RetVT, PredicateCheck));
if (!inserted_simple_pattern.second) {
PrintFatalError(Pattern.getSrcRecord()->getLoc(),
"Duplicate predicate in FastISel table!");
"Duplicate predicate in FastISel table!");
}
// Note: Instructions with the same complexity will appear in the order
@@ -602,8 +612,8 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
// them down to a signature that doesn't have predicates so that we can
// associate them with the stripped predicate version.
if (Operands.hasAnyImmediateCodes()) {
SignaturesWithConstantForms[Operands.getWithoutImmCodes()]
.push_back(Operands);
SignaturesWithConstantForms[Operands.getWithoutImmCodes()].push_back(
Operands);
}
}
}
@@ -645,7 +655,8 @@ void FastISelMap::emitInstructionCode(raw_ostream &OS,
if (OneHadNoPredicate) {
PrintFatalError("Multiple instructions match and one with no "
"predicate came before one with a predicate! "
"name:" + Memo.Name + " predicate: " + PredicateCheck);
"name:" +
Memo.Name + " predicate: " + PredicateCheck);
}
OS << " if (" + PredicateCheck + ") {\n";
OS << " ";
@@ -669,8 +680,8 @@ void FastISelMap::emitInstructionCode(raw_ostream &OS,
Operands.PrintArguments(OS, Memo.PhysRegs);
OS << ");\n";
} else {
OS << "extractsubreg(" << RetVTName
<< ", Op0, " << Memo.SubRegNo << ");\n";
OS << "extractsubreg(" << RetVTName << ", Op0, " << Memo.SubRegNo
<< ");\n";
}
if (!PredicateCheck.empty()) {
@@ -685,7 +696,6 @@ void FastISelMap::emitInstructionCode(raw_ostream &OS,
OS << "\n";
}
void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
// Now emit code for all the patterns that we collected.
for (const auto &SimplePattern : SimplePatterns) {
@@ -762,8 +772,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
}
// Emit one function for the opcode that demultiplexes based on the type.
OS << "unsigned fastEmit_"
<< getLegalCName(Opcode) << "_";
OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(MVT VT, MVT RetVT";
if (!Operands.empty())
@@ -809,8 +818,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
// constrained forms of the immediate (e.g., 32-bit sext immediate in a
// 64-bit operand), check them first.
std::map<OperandsSignature, std::vector<OperandsSignature> >::iterator MI
= SignaturesWithConstantForms.find(Operands);
std::map<OperandsSignature, std::vector<OperandsSignature>>::iterator MI =
SignaturesWithConstantForms.find(Operands);
if (MI != SignaturesWithConstantForms.end()) {
// Unique any duplicates out of the list.
llvm::sort(MI->second);
@@ -840,8 +849,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
for (const auto &I : OTM) {
const std::string &Opcode = I.first;
OS << " case " << Opcode << ": return fastEmit_"
<< getLegalCName(Opcode) << "_";
OS << " case " << Opcode << ": return fastEmit_" << getLegalCName(Opcode)
<< "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(VT, RetVT";
if (!Operands.empty())
@@ -862,7 +871,8 @@ static void EmitFastISel(RecordKeeper &RK, raw_ostream &OS) {
CodeGenDAGPatterns CGP(RK);
const CodeGenTarget &Target = CGP.getTargetInfo();
emitSourceFileHeader("\"Fast\" Instruction Selector for the " +
Target.getName().str() + " target", OS);
Target.getName().str() + " target",
OS);
// Determine the target's namespace name.
StringRef InstNS = Target.getInstNamespace();

View File

@@ -11,8 +11,8 @@
// data).
//===----------------------------------------------------------------------===//
#include "CodeGenTarget.h"
#include "InfoByHwMode.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
@@ -44,7 +44,7 @@ ValueTypeByHwMode::ValueTypeByHwMode(Record *R, MVT T) : ValueTypeByHwMode(T) {
PtrAddrSpace = R->getValueAsInt("AddrSpace");
}
bool ValueTypeByHwMode::operator== (const ValueTypeByHwMode &T) const {
bool ValueTypeByHwMode::operator==(const ValueTypeByHwMode &T) const {
assert(isValid() && T.isValid() && "Invalid type in assignment");
bool Simple = isSimple();
if (Simple != T.isSimple())
@@ -55,7 +55,7 @@ bool ValueTypeByHwMode::operator== (const ValueTypeByHwMode &T) const {
return Map == T.Map;
}
bool ValueTypeByHwMode::operator< (const ValueTypeByHwMode &T) const {
bool ValueTypeByHwMode::operator<(const ValueTypeByHwMode &T) const {
assert(isValid() && T.isValid() && "Invalid type in comparison");
// Default order for maps.
return Map < T.Map;
@@ -86,7 +86,7 @@ void ValueTypeByHwMode::writeToStream(raw_ostream &OS) const {
return;
}
std::vector<const PairType*> Pairs;
std::vector<const PairType *> Pairs;
for (const auto &P : Map)
Pairs.push_back(&P);
llvm::sort(Pairs, deref<std::less<PairType>>());
@@ -100,9 +100,7 @@ void ValueTypeByHwMode::writeToStream(raw_ostream &OS) const {
}
LLVM_DUMP_METHOD
void ValueTypeByHwMode::dump() const {
dbgs() << *this << '\n';
}
void ValueTypeByHwMode::dump() const { dbgs() << *this << '\n'; }
ValueTypeByHwMode llvm::getValueTypeByHwMode(Record *Rec,
const CodeGenHwModes &CGH) {
@@ -123,24 +121,22 @@ RegSizeInfo::RegSizeInfo(Record *R, const CodeGenHwModes &CGH) {
SpillAlignment = R->getValueAsInt("SpillAlignment");
}
bool RegSizeInfo::operator< (const RegSizeInfo &I) const {
bool RegSizeInfo::operator<(const RegSizeInfo &I) const {
return std::tie(RegSize, SpillSize, SpillAlignment) <
std::tie(I.RegSize, I.SpillSize, I.SpillAlignment);
}
bool RegSizeInfo::isSubClassOf(const RegSizeInfo &I) const {
return RegSize <= I.RegSize &&
SpillAlignment && I.SpillAlignment % SpillAlignment == 0 &&
SpillSize <= I.SpillSize;
return RegSize <= I.RegSize && SpillAlignment &&
I.SpillAlignment % SpillAlignment == 0 && SpillSize <= I.SpillSize;
}
void RegSizeInfo::writeToStream(raw_ostream &OS) const {
OS << "[R=" << RegSize << ",S=" << SpillSize
<< ",A=" << SpillAlignment << ']';
OS << "[R=" << RegSize << ",S=" << SpillSize << ",A=" << SpillAlignment
<< ']';
}
RegSizeInfoByHwMode::RegSizeInfoByHwMode(Record *R,
const CodeGenHwModes &CGH) {
RegSizeInfoByHwMode::RegSizeInfoByHwMode(Record *R, const CodeGenHwModes &CGH) {
const HwModeSelect &MS = CGH.getHwModeSelect(R);
for (const HwModeSelect::PairType &P : MS.Items) {
auto I = Map.insert({P.first, RegSizeInfo(P.second, CGH)});
@@ -149,12 +145,12 @@ RegSizeInfoByHwMode::RegSizeInfoByHwMode(Record *R,
}
}
bool RegSizeInfoByHwMode::operator< (const RegSizeInfoByHwMode &I) const {
bool RegSizeInfoByHwMode::operator<(const RegSizeInfoByHwMode &I) const {
unsigned M0 = Map.begin()->first;
return get(M0) < I.get(M0);
}
bool RegSizeInfoByHwMode::operator== (const RegSizeInfoByHwMode &I) const {
bool RegSizeInfoByHwMode::operator==(const RegSizeInfoByHwMode &I) const {
unsigned M0 = Map.begin()->first;
return get(M0) == I.get(M0);
}
@@ -164,8 +160,8 @@ bool RegSizeInfoByHwMode::isSubClassOf(const RegSizeInfoByHwMode &I) const {
return get(M0).isSubClassOf(I.get(M0));
}
bool RegSizeInfoByHwMode::hasStricterSpillThan(const RegSizeInfoByHwMode &I)
const {
bool RegSizeInfoByHwMode::hasStricterSpillThan(
const RegSizeInfoByHwMode &I) const {
unsigned M0 = Map.begin()->first;
const RegSizeInfo &A0 = get(M0);
const RegSizeInfo &B0 = I.get(M0);
@@ -175,7 +171,7 @@ bool RegSizeInfoByHwMode::hasStricterSpillThan(const RegSizeInfoByHwMode &I)
void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const {
typedef typename decltype(Map)::value_type PairType;
std::vector<const PairType*> Pairs;
std::vector<const PairType *> Pairs;
for (const auto &P : Map)
Pairs.push_back(&P);
llvm::sort(Pairs, deref<std::less<PairType>>());
@@ -187,7 +183,8 @@ void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const {
OS << '}';
}
EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH) {
EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R,
const CodeGenHwModes &CGH) {
const HwModeSelect &MS = CGH.getHwModeSelect(R);
for (const HwModeSelect::PairType &P : MS.Items) {
assert(P.second && P.second->isSubClassOf("InstructionEncoding") &&
@@ -199,18 +196,18 @@ EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH)
}
namespace llvm {
raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T) {
T.writeToStream(OS);
return OS;
}
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T) {
T.writeToStream(OS);
return OS;
}
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T) {
T.writeToStream(OS);
return OS;
}
raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T) {
T.writeToStream(OS);
return OS;
}
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T) {
T.writeToStream(OS);
return OS;
}
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T) {
T.writeToStream(OS);
return OS;
}
} // namespace llvm

View File

@@ -40,8 +40,7 @@ enum : unsigned {
};
template <typename InfoT>
void union_modes(const InfoByHwMode<InfoT> &A,
const InfoByHwMode<InfoT> &B,
void union_modes(const InfoByHwMode<InfoT> &A, const InfoByHwMode<InfoT> &B,
SmallVectorImpl<unsigned> &Modes) {
auto AI = A.begin();
auto BI = B.begin();
@@ -85,9 +84,8 @@ void union_modes(const InfoByHwMode<InfoT> &A,
Modes.push_back(DefaultMode);
}
template <typename InfoT>
struct InfoByHwMode {
typedef std::map<unsigned,InfoT> MapType;
template <typename InfoT> struct InfoByHwMode {
typedef std::map<unsigned, InfoT> MapType;
typedef typename MapType::value_type PairType;
typedef typename MapType::iterator iterator;
typedef typename MapType::const_iterator const_iterator;
@@ -98,11 +96,11 @@ struct InfoByHwMode {
LLVM_ATTRIBUTE_ALWAYS_INLINE
iterator begin() { return Map.begin(); }
LLVM_ATTRIBUTE_ALWAYS_INLINE
iterator end() { return Map.end(); }
iterator end() { return Map.end(); }
LLVM_ATTRIBUTE_ALWAYS_INLINE
const_iterator begin() const { return Map.begin(); }
LLVM_ATTRIBUTE_ALWAYS_INLINE
const_iterator end() const { return Map.end(); }
const_iterator end() const { return Map.end(); }
LLVM_ATTRIBUTE_ALWAYS_INLINE
bool empty() const { return Map.empty(); }
@@ -156,15 +154,13 @@ protected:
struct ValueTypeByHwMode : public InfoByHwMode<MVT> {
ValueTypeByHwMode(Record *R, const CodeGenHwModes &CGH);
ValueTypeByHwMode(Record *R, MVT T);
ValueTypeByHwMode(MVT T) { Map.insert({DefaultMode,T}); }
ValueTypeByHwMode(MVT T) { Map.insert({DefaultMode, T}); }
ValueTypeByHwMode() = default;
bool operator== (const ValueTypeByHwMode &T) const;
bool operator< (const ValueTypeByHwMode &T) const;
bool operator==(const ValueTypeByHwMode &T) const;
bool operator<(const ValueTypeByHwMode &T) const;
bool isValid() const {
return !Map.empty();
}
bool isValid() const { return !Map.empty(); }
MVT getType(unsigned Mode) const { return get(Mode); }
MVT &getOrCreateTypeForMode(unsigned Mode, MVT Type);
@@ -178,8 +174,7 @@ struct ValueTypeByHwMode : public InfoByHwMode<MVT> {
}
};
ValueTypeByHwMode getValueTypeByHwMode(Record *Rec,
const CodeGenHwModes &CGH);
ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, const CodeGenHwModes &CGH);
struct RegSizeInfo {
unsigned RegSize;
@@ -188,14 +183,12 @@ struct RegSizeInfo {
RegSizeInfo(Record *R, const CodeGenHwModes &CGH);
RegSizeInfo() = default;
bool operator< (const RegSizeInfo &I) const;
bool operator== (const RegSizeInfo &I) const {
bool operator<(const RegSizeInfo &I) const;
bool operator==(const RegSizeInfo &I) const {
return std::tie(RegSize, SpillSize, SpillAlignment) ==
std::tie(I.RegSize, I.SpillSize, I.SpillAlignment);
}
bool operator!= (const RegSizeInfo &I) const {
return !(*this == I);
}
bool operator!=(const RegSizeInfo &I) const { return !(*this == I); }
bool isSubClassOf(const RegSizeInfo &I) const;
void writeToStream(raw_ostream &OS) const;
@@ -204,9 +197,9 @@ struct RegSizeInfo {
struct RegSizeInfoByHwMode : public InfoByHwMode<RegSizeInfo> {
RegSizeInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
RegSizeInfoByHwMode() = default;
bool operator< (const RegSizeInfoByHwMode &VI) const;
bool operator== (const RegSizeInfoByHwMode &VI) const;
bool operator!= (const RegSizeInfoByHwMode &VI) const {
bool operator<(const RegSizeInfoByHwMode &VI) const;
bool operator==(const RegSizeInfoByHwMode &VI) const;
bool operator!=(const RegSizeInfoByHwMode &VI) const {
return !(*this == VI);
}
@@ -224,7 +217,7 @@ raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T);
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T);
raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T);
struct EncodingInfoByHwMode : public InfoByHwMode<Record*> {
struct EncodingInfoByHwMode : public InfoByHwMode<Record *> {
EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH);
EncodingInfoByHwMode() = default;
};

View File

@@ -44,11 +44,18 @@ static std::string escapeForRST(StringRef Str) {
for (char C : Str) {
switch (C) {
// We want special characters to be shown as their C escape codes.
case '\n': Result += "\\n"; break;
case '\t': Result += "\\t"; break;
case '\n':
Result += "\\n";
break;
case '\t':
Result += "\\t";
break;
// Underscore at the end of a line has a special meaning in rst.
case '_': Result += "\\_"; break;
default: Result += C;
case '_':
Result += "\\_";
break;
default:
Result += C;
}
}
return Result;
@@ -96,7 +103,10 @@ static void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
std::vector<const char *> FlagStrings;
#define xstr(s) str(s)
#define str(s) #s
#define FLAG(f) if (II->f) { FlagStrings.push_back(str(f)); }
#define FLAG(f) \
if (II->f) { \
FlagStrings.push_back(str(f)); \
}
FLAG(isReturn)
FLAG(isEHScopeReturn)
FLAG(isBranch)
@@ -111,9 +121,9 @@ static void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
FLAG(isTrap)
FLAG(canFoldAsLoad)
FLAG(mayLoad)
//FLAG(mayLoad_Unset) // Deliberately omitted.
// FLAG(mayLoad_Unset) // Deliberately omitted.
FLAG(mayStore)
//FLAG(mayStore_Unset) // Deliberately omitted.
// FLAG(mayStore_Unset) // Deliberately omitted.
FLAG(isPredicable)
FLAG(isConvertibleToThreeAddress)
FLAG(isCommutable)
@@ -125,7 +135,7 @@ static void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
FLAG(hasCtrlDep)
FLAG(isNotDuplicable)
FLAG(hasSideEffects)
//FLAG(hasSideEffects_Unset) // Deliberately omitted.
// FLAG(hasSideEffects_Unset) // Deliberately omitted.
FLAG(isAsCheapAsAMove)
FLAG(hasExtraSrcRegAllocReq)
FLAG(hasExtraDefRegAllocReq)

View File

@@ -53,8 +53,8 @@ class InstrInfoEmitter {
const CodeGenSchedModels &SchedModels;
public:
InstrInfoEmitter(RecordKeeper &R):
Records(R), CDP(R), SchedModels(CDP.getTargetInfo().getSchedModels()) {}
InstrInfoEmitter(RecordKeeper &R)
: Records(R), CDP(R), SchedModels(CDP.getTargetInfo().getSchedModels()) {}
// run - Output the instruction set description.
void run(raw_ostream &OS);
@@ -69,8 +69,8 @@ private:
/// The keys of this map are maps which have OpName enum values as their keys
/// and instruction operand indices as their values. The values of this map
/// are lists of instruction names.
typedef std::map<std::map<unsigned, unsigned>,
std::vector<std::string>> OpNameMapTy;
typedef std::map<std::map<unsigned, unsigned>, std::vector<std::string>>
OpNameMapTy;
typedef std::map<std::string, unsigned>::iterator StrUintMapIter;
/// Generate member functions in the target-specific GenInstrInfo class.
@@ -94,13 +94,14 @@ private:
void emitOperandTypeMappings(
raw_ostream &OS, const CodeGenTarget &Target,
ArrayRef<const CodeGenInstruction *> NumberedInstructions);
void initOperandMapData(
ArrayRef<const CodeGenInstruction *> NumberedInstructions,
StringRef Namespace,
std::map<std::string, unsigned> &Operands,
OpNameMapTy &OperandMap);
void emitOperandNameMappings(raw_ostream &OS, const CodeGenTarget &Target,
ArrayRef<const CodeGenInstruction*> NumberedInstructions);
void
initOperandMapData(ArrayRef<const CodeGenInstruction *> NumberedInstructions,
StringRef Namespace,
std::map<std::string, unsigned> &Operands,
OpNameMapTy &OperandMap);
void emitOperandNameMappings(
raw_ostream &OS, const CodeGenTarget &Target,
ArrayRef<const CodeGenInstruction *> NumberedInstructions);
void emitLogicalOperandSizeMappings(
raw_ostream &OS, StringRef Namespace,
@@ -193,8 +194,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
// Fill in constraint info.
Res += ", ";
const CGIOperandList::ConstraintInfo &Constraint =
Op.Constraints[j];
const CGIOperandList::ConstraintInfo &Constraint = Op.Constraints[j];
if (Constraint.isNone())
Res += "0";
else if (Constraint.isEarlyClobber())
@@ -246,10 +246,9 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
/// each instructions. This is used to generate the OperandMap table as
/// well as the getNamedOperandIdx() function.
void InstrInfoEmitter::initOperandMapData(
ArrayRef<const CodeGenInstruction *> NumberedInstructions,
StringRef Namespace,
std::map<std::string, unsigned> &Operands,
OpNameMapTy &OperandMap) {
ArrayRef<const CodeGenInstruction *> NumberedInstructions,
StringRef Namespace, std::map<std::string, unsigned> &Operands,
OpNameMapTy &OperandMap) {
unsigned NumOperands = 0;
for (const CodeGenInstruction *Inst : NumberedInstructions) {
if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable"))
@@ -259,13 +258,13 @@ void InstrInfoEmitter::initOperandMapData(
StrUintMapIter I = Operands.find(Info.Name);
if (I == Operands.end()) {
I = Operands.insert(Operands.begin(),
std::pair<std::string, unsigned>(Info.Name, NumOperands++));
I = Operands.insert(Operands.begin(), std::pair<std::string, unsigned>(
Info.Name, NumOperands++));
}
OpList[I->second] = Info.MIOperandNo;
}
OperandMap[OpList].push_back(Namespace.str() + "::" +
Inst->TheDef->getName().str());
OperandMap[OpList].push_back(Namespace.str() +
"::" + Inst->TheDef->getName().str());
}
}
@@ -280,9 +279,9 @@ void InstrInfoEmitter::initOperandMapData(
/// - A function called getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
/// for looking up the operand index for an instruction, given a value from
/// OpName enum
void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
const CodeGenTarget &Target,
ArrayRef<const CodeGenInstruction*> NumberedInstructions) {
void InstrInfoEmitter::emitOperandNameMappings(
raw_ostream &OS, const CodeGenTarget &Target,
ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
StringRef Namespace = Target.getInstNamespace();
std::string OpNameNS = "OpName";
// Map of operand names to their enumeration value. This will be used to
@@ -380,7 +379,8 @@ void InstrInfoEmitter::emitOperandTypeMappings(
}
}
OS << " OPERAND_TYPE_LIST_END" << "\n};\n";
OS << " OPERAND_TYPE_LIST_END"
<< "\n};\n";
OS << "} // end namespace OpTypes\n";
OS << "} // end namespace " << Namespace << "\n";
OS << "} // end namespace llvm\n";
@@ -685,7 +685,7 @@ void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS,
for (const Record *Rec : TIIPredicates) {
OS << "bool " << Rec->getValueAsString("FunctionName")
<< "(const MCInst &MI);\n";
<< "(const MCInst &MI);\n";
}
OS << "void verifyInstructionPredicates(unsigned Opcode, const FeatureBitset "
@@ -939,7 +939,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
// Collect all of the instruction's implicit uses and defs.
Records.startTimer("Collect uses/defs");
std::map<std::vector<Record*>, unsigned> EmittedLists;
std::map<std::vector<Record *>, unsigned> EmittedLists;
std::vector<std::vector<Record *>> ImplicitLists;
unsigned ImplicitListSize = 0;
for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
@@ -1017,7 +1017,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
InstrNames.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName +
"InstrNameData[]");
OS << "extern const unsigned " << TargetName <<"InstrNameIndices[] = {";
OS << "extern const unsigned " << TargetName << "InstrNameIndices[] = {";
Num = 0;
for (const CodeGenInstruction *Inst : NumberedInstructions) {
// Newline every eight entries.
@@ -1104,7 +1104,6 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
"unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u);\n"
<< " ~" << ClassName << "() override = default;\n";
OS << "\n};\n} // end namespace llvm\n";
OS << "#endif // GET_INSTRINFO_HEADER\n\n";
@@ -1180,8 +1179,8 @@ void InstrInfoEmitter::emitRecord(
int MinOperands = 0;
if (!Inst.Operands.empty())
// Each logical operand can be multiple MI operands.
MinOperands = Inst.Operands.back().MIOperandNo +
Inst.Operands.back().MINumOperands;
MinOperands =
Inst.Operands.back().MIOperandNo + Inst.Operands.back().MINumOperands;
OS << " { ";
OS << Num << ",\t" << MinOperands << ",\t" << Inst.Operands.NumDefs << ",\t"
@@ -1202,49 +1201,88 @@ void InstrInfoEmitter::emitRecord(
OS << OperandInfoMap.find(OperandInfo)->second << ",\t0";
// Emit all of the target independent flags...
if (Inst.isPreISelOpcode) OS << "|(1ULL<<MCID::PreISelOpcode)";
if (Inst.isPseudo) OS << "|(1ULL<<MCID::Pseudo)";
if (Inst.isMeta) OS << "|(1ULL<<MCID::Meta)";
if (Inst.isReturn) OS << "|(1ULL<<MCID::Return)";
if (Inst.isEHScopeReturn) OS << "|(1ULL<<MCID::EHScopeReturn)";
if (Inst.isBranch) OS << "|(1ULL<<MCID::Branch)";
if (Inst.isIndirectBranch) OS << "|(1ULL<<MCID::IndirectBranch)";
if (Inst.isCompare) OS << "|(1ULL<<MCID::Compare)";
if (Inst.isMoveImm) OS << "|(1ULL<<MCID::MoveImm)";
if (Inst.isMoveReg) OS << "|(1ULL<<MCID::MoveReg)";
if (Inst.isBitcast) OS << "|(1ULL<<MCID::Bitcast)";
if (Inst.isAdd) OS << "|(1ULL<<MCID::Add)";
if (Inst.isTrap) OS << "|(1ULL<<MCID::Trap)";
if (Inst.isSelect) OS << "|(1ULL<<MCID::Select)";
if (Inst.isBarrier) OS << "|(1ULL<<MCID::Barrier)";
if (Inst.hasDelaySlot) OS << "|(1ULL<<MCID::DelaySlot)";
if (Inst.isCall) OS << "|(1ULL<<MCID::Call)";
if (Inst.canFoldAsLoad) OS << "|(1ULL<<MCID::FoldableAsLoad)";
if (Inst.mayLoad) OS << "|(1ULL<<MCID::MayLoad)";
if (Inst.mayStore) OS << "|(1ULL<<MCID::MayStore)";
if (Inst.mayRaiseFPException) OS << "|(1ULL<<MCID::MayRaiseFPException)";
if (Inst.isPredicable) OS << "|(1ULL<<MCID::Predicable)";
if (Inst.isConvertibleToThreeAddress) OS << "|(1ULL<<MCID::ConvertibleTo3Addr)";
if (Inst.isCommutable) OS << "|(1ULL<<MCID::Commutable)";
if (Inst.isTerminator) OS << "|(1ULL<<MCID::Terminator)";
if (Inst.isReMaterializable) OS << "|(1ULL<<MCID::Rematerializable)";
if (Inst.isNotDuplicable) OS << "|(1ULL<<MCID::NotDuplicable)";
if (Inst.Operands.hasOptionalDef) OS << "|(1ULL<<MCID::HasOptionalDef)";
if (Inst.usesCustomInserter) OS << "|(1ULL<<MCID::UsesCustomInserter)";
if (Inst.hasPostISelHook) OS << "|(1ULL<<MCID::HasPostISelHook)";
if (Inst.Operands.isVariadic)OS << "|(1ULL<<MCID::Variadic)";
if (Inst.hasSideEffects) OS << "|(1ULL<<MCID::UnmodeledSideEffects)";
if (Inst.isAsCheapAsAMove) OS << "|(1ULL<<MCID::CheapAsAMove)";
if (Inst.isPreISelOpcode)
OS << "|(1ULL<<MCID::PreISelOpcode)";
if (Inst.isPseudo)
OS << "|(1ULL<<MCID::Pseudo)";
if (Inst.isMeta)
OS << "|(1ULL<<MCID::Meta)";
if (Inst.isReturn)
OS << "|(1ULL<<MCID::Return)";
if (Inst.isEHScopeReturn)
OS << "|(1ULL<<MCID::EHScopeReturn)";
if (Inst.isBranch)
OS << "|(1ULL<<MCID::Branch)";
if (Inst.isIndirectBranch)
OS << "|(1ULL<<MCID::IndirectBranch)";
if (Inst.isCompare)
OS << "|(1ULL<<MCID::Compare)";
if (Inst.isMoveImm)
OS << "|(1ULL<<MCID::MoveImm)";
if (Inst.isMoveReg)
OS << "|(1ULL<<MCID::MoveReg)";
if (Inst.isBitcast)
OS << "|(1ULL<<MCID::Bitcast)";
if (Inst.isAdd)
OS << "|(1ULL<<MCID::Add)";
if (Inst.isTrap)
OS << "|(1ULL<<MCID::Trap)";
if (Inst.isSelect)
OS << "|(1ULL<<MCID::Select)";
if (Inst.isBarrier)
OS << "|(1ULL<<MCID::Barrier)";
if (Inst.hasDelaySlot)
OS << "|(1ULL<<MCID::DelaySlot)";
if (Inst.isCall)
OS << "|(1ULL<<MCID::Call)";
if (Inst.canFoldAsLoad)
OS << "|(1ULL<<MCID::FoldableAsLoad)";
if (Inst.mayLoad)
OS << "|(1ULL<<MCID::MayLoad)";
if (Inst.mayStore)
OS << "|(1ULL<<MCID::MayStore)";
if (Inst.mayRaiseFPException)
OS << "|(1ULL<<MCID::MayRaiseFPException)";
if (Inst.isPredicable)
OS << "|(1ULL<<MCID::Predicable)";
if (Inst.isConvertibleToThreeAddress)
OS << "|(1ULL<<MCID::ConvertibleTo3Addr)";
if (Inst.isCommutable)
OS << "|(1ULL<<MCID::Commutable)";
if (Inst.isTerminator)
OS << "|(1ULL<<MCID::Terminator)";
if (Inst.isReMaterializable)
OS << "|(1ULL<<MCID::Rematerializable)";
if (Inst.isNotDuplicable)
OS << "|(1ULL<<MCID::NotDuplicable)";
if (Inst.Operands.hasOptionalDef)
OS << "|(1ULL<<MCID::HasOptionalDef)";
if (Inst.usesCustomInserter)
OS << "|(1ULL<<MCID::UsesCustomInserter)";
if (Inst.hasPostISelHook)
OS << "|(1ULL<<MCID::HasPostISelHook)";
if (Inst.Operands.isVariadic)
OS << "|(1ULL<<MCID::Variadic)";
if (Inst.hasSideEffects)
OS << "|(1ULL<<MCID::UnmodeledSideEffects)";
if (Inst.isAsCheapAsAMove)
OS << "|(1ULL<<MCID::CheapAsAMove)";
if (!Target.getAllowRegisterRenaming() || Inst.hasExtraSrcRegAllocReq)
OS << "|(1ULL<<MCID::ExtraSrcRegAllocReq)";
if (!Target.getAllowRegisterRenaming() || Inst.hasExtraDefRegAllocReq)
OS << "|(1ULL<<MCID::ExtraDefRegAllocReq)";
if (Inst.isRegSequence) OS << "|(1ULL<<MCID::RegSequence)";
if (Inst.isExtractSubreg) OS << "|(1ULL<<MCID::ExtractSubreg)";
if (Inst.isInsertSubreg) OS << "|(1ULL<<MCID::InsertSubreg)";
if (Inst.isConvergent) OS << "|(1ULL<<MCID::Convergent)";
if (Inst.variadicOpsAreDefs) OS << "|(1ULL<<MCID::VariadicOpsAreDefs)";
if (Inst.isAuthenticated) OS << "|(1ULL<<MCID::Authenticated)";
if (Inst.isRegSequence)
OS << "|(1ULL<<MCID::RegSequence)";
if (Inst.isExtractSubreg)
OS << "|(1ULL<<MCID::ExtractSubreg)";
if (Inst.isInsertSubreg)
OS << "|(1ULL<<MCID::InsertSubreg)";
if (Inst.isConvergent)
OS << "|(1ULL<<MCID::Convergent)";
if (Inst.variadicOpsAreDefs)
OS << "|(1ULL<<MCID::VariadicOpsAreDefs)";
if (Inst.isAuthenticated)
OS << "|(1ULL<<MCID::Authenticated)";
// Emit all of the target-specific flags...
BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");

View File

@@ -60,8 +60,8 @@ public:
raw_ostream &OS);
void EmitGenerator(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
void EmitAttributes(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable &Ints, bool IsClang,
raw_ostream &OS);
void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable &Ints,
bool IsClang, raw_ostream &OS);
};
} // End anonymous namespace
@@ -204,7 +204,7 @@ void IntrinsicEmitter::EmitIITInfo(raw_ostream &OS) {
}
void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable &Ints,
raw_ostream &OS) {
raw_ostream &OS) {
OS << "// Target mapping\n";
OS << "#ifdef GET_INTRINSIC_TARGET_DATA\n";
OS << "struct IntrinsicTargetInfo {\n"
@@ -238,10 +238,10 @@ void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
OS << " 0";
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
// Add one to the index so we emit a null bit for the invalid #0 intrinsic.
if ((i+1)%8 == 0)
if ((i + 1) % 8 == 0)
OS << ",\n 0";
if (Ints[i].isOverloaded)
OS << " | (1<<" << (i+1)%8 << ')';
OS << " | (1<<" << (i + 1) % 8 << ')';
}
OS << "\n};\n\n";
// OTable contains a true bit at the position if the intrinsic is overloaded.
@@ -271,7 +271,7 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
// capture it in this vector, otherwise store a ~0U.
std::vector<unsigned> FixedEncodings;
SequenceToOffsetTable<std::vector<unsigned char> > LongEncodingTable;
SequenceToOffsetTable<std::vector<unsigned char>> LongEncodingTable;
std::vector<unsigned char> TypeSig;
@@ -292,7 +292,7 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
Failed = true;
break;
}
Result = (Result << 4) | TypeSig[e-i-1];
Result = (Result << 4) | TypeSig[e - i - 1];
}
// If this could be encoded into a 31-bit word, return it.
@@ -330,7 +330,6 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
TypeSig.clear();
ComputeFixedEncoding(Ints[i], TypeSig);
// Otherwise, emit the offset into the long encoding table. We emit it this
// way so that it is easier to read the offset in the .def file.
OS << "(1U<<31) | " << LongEncodingTable.get(TypeSig) << ", ";
@@ -344,7 +343,7 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
LongEncodingTable.emit(OS, printIITEntry);
OS << " 255\n};\n\n";
OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL
OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL
}
namespace {
@@ -393,7 +392,8 @@ std::optional<bool> compareFnAttributes(const CodeGenIntrinsic *L,
// Try to order by readonly/readnone attribute.
uint32_t LK = L->ME.toIntValue();
uint32_t RK = R->ME.toIntValue();
if (LK != RK) return (LK > RK);
if (LK != RK)
return (LK > RK);
return std::nullopt;
}
@@ -438,8 +438,7 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
if (!UniqArgAttributes.try_emplace(Attrs, ID).second)
continue;
assert(is_sorted(Attrs) &&
"Argument attributes are not sorted");
assert(is_sorted(Attrs) && "Argument attributes are not sorted");
OS << " case " << ID << ":\n";
OS << " return AttributeSet::get(C, {\n";
@@ -473,8 +472,8 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
OS << " Attribute::get(C, Attribute::ImmArg),\n";
break;
case CodeGenIntrinsic::Alignment:
OS << " Attribute::get(C, Attribute::Alignment, "
<< Attr.Value << "),\n";
OS << " Attribute::get(C, Attribute::Alignment, " << Attr.Value
<< "),\n";
break;
case CodeGenIntrinsic::Dereferenceable:
OS << " Attribute::get(C, Attribute::Dereferenceable, "
@@ -489,7 +488,7 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
OS << "}\n\n";
// Compute unique function attribute sets.
std::map<const CodeGenIntrinsic*, unsigned, FnAttributeComparator>
std::map<const CodeGenIntrinsic *, unsigned, FnAttributeComparator>
UniqFnAttributes;
OS << "static AttributeSet getIntrinsicFnAttributeSet("
<< "LLVMContext &C, unsigned ID) {\n"
@@ -542,17 +541,18 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
OS << "AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) {\n";
// Compute the maximum number of attribute arguments and the map
typedef std::map<const CodeGenIntrinsic*, unsigned,
AttributeComparator> UniqAttrMapTy;
typedef std::map<const CodeGenIntrinsic *, unsigned, AttributeComparator>
UniqAttrMapTy;
UniqAttrMapTy UniqAttributes;
unsigned maxArgAttrs = 0;
unsigned AttrNum = 0;
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
const CodeGenIntrinsic &intrinsic = Ints[i];
maxArgAttrs =
std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size()));
std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size()));
unsigned &N = UniqAttributes[&intrinsic];
if (N) continue;
if (N)
continue;
N = ++AttrNum;
assert(N < 65536 && "Too many unique attributes for table!");
}
@@ -564,8 +564,8 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
const CodeGenIntrinsic &intrinsic = Ints[i];
OS << " " << UniqAttributes[&intrinsic] << ", // "
<< intrinsic.Name << "\n";
OS << " " << UniqAttributes[&intrinsic] << ", // " << intrinsic.Name
<< "\n";
}
OS << " };\n\n";

View File

@@ -196,9 +196,9 @@ static MarshallingInfo createMarshallingInfo(const Record &R) {
/// working with those options when given an input command line.
static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
// Get the option groups and options.
const std::vector<Record*> &Groups =
Records.getAllDerivedDefinitions("OptionGroup");
std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
const std::vector<Record *> &Groups =
Records.getAllDerivedDefinitions("OptionGroup");
std::vector<Record *> Opts = Records.getAllDerivedDefinitions("Option");
emitSourceFileHeader("Option Parsing Definitions", OS);
@@ -423,8 +423,7 @@ static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
write_cstring(OS, R.getValueAsString("Values"));
else if (!isa<UnsetInit>(R.getValueInit("ValuesCode"))) {
OS << getOptionName(R) << "_Values";
}
else
} else
OS << "nullptr";
};

View File

@@ -101,7 +101,6 @@ void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
OS << Reg->getName();
}
void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
int OpIndex,
StringRef FunctionMapper) {
@@ -487,7 +486,8 @@ void STIPredicateExpander::expandPrologue(raw_ostream &OS,
OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
}
void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS,
const OpcodeGroup &Group,
bool ShouldUpdateOpcodeMask) {
const OpcodeInfo &OI = Group.getOpcodeInfo();
for (const PredicateInfo &PI : OI.getPredicates()) {

View File

@@ -27,19 +27,19 @@ class PseudoLoweringEmitter {
enum MapKind { Operand, Imm, Reg };
MapKind Kind;
union {
unsigned Operand; // Operand number mapped to.
uint64_t Imm; // Integer immedate value.
Record *Reg; // Physical register.
unsigned Operand; // Operand number mapped to.
uint64_t Imm; // Integer immedate value.
Record *Reg; // Physical register.
} Data;
};
struct PseudoExpansion {
CodeGenInstruction Source; // The source pseudo instruction definition.
CodeGenInstruction Dest; // The destination instruction to lower to.
CodeGenInstruction Source; // The source pseudo instruction definition.
CodeGenInstruction Dest; // The destination instruction to lower to.
IndexedMap<OpData> OperandMap;
PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d,
IndexedMap<OpData> &m) :
Source(s), Dest(d), OperandMap(m) {}
IndexedMap<OpData> &m)
: Source(s), Dest(d), OperandMap(m) {}
};
RecordKeeper &Records;
@@ -57,6 +57,7 @@ class PseudoLoweringEmitter {
unsigned BaseIdx);
void evaluateExpansion(Record *Pseudo);
void emitLoweringEmitter(raw_ostream &o);
public:
PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {}
@@ -69,9 +70,9 @@ public:
// The pseudo expansion really should take a list of dags, not just
// a single dag, so we can do fancier things.
unsigned PseudoLoweringEmitter::
addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
IndexedMap<OpData> &OperandMap, unsigned BaseIdx) {
unsigned PseudoLoweringEmitter::addDagOperandMapping(
Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
IndexedMap<OpData> &OperandMap, unsigned BaseIdx) {
unsigned OpsAdded = 0;
for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
if (DefInit *DI = dyn_cast<DefInit>(Dag->getArg(i))) {
@@ -92,9 +93,9 @@ addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
// FIXME: Are the message operand types backward?
if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec) {
PrintError(Rec, "In pseudo instruction '" + Rec->getName() +
"', operand type '" + DI->getDef()->getName() +
"' does not match expansion operand type '" +
Insn.Operands[BaseIdx + i].Rec->getName() + "'");
"', operand type '" + DI->getDef()->getName() +
"' does not match expansion operand type '" +
Insn.Operands[BaseIdx + i].Rec->getName() + "'");
PrintFatalNote(DI->getDef(),
"Value was assigned at the following location:");
}
@@ -118,7 +119,7 @@ addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
// Just add the operands recursively. This is almost certainly
// a constant value for a complex operand (> 1 MI operand).
unsigned NewOps =
addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i);
addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i);
OpsAdded += NewOps;
// Since we added more than one, we also need to adjust the base.
BaseIdx += NewOps - 1;
@@ -140,15 +141,15 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator());
if (!OpDef) {
PrintError(Rec, "In pseudo instruction '" + Rec->getName() +
"', result operator is not a record");
"', result operator is not a record");
PrintFatalNote(Rec->getValue("ResultInst"),
"Result was assigned at the following location:");
}
Record *Operator = OpDef->getDef();
if (!Operator->isSubClassOf("Instruction")) {
PrintError(Rec, "In pseudo instruction '" + Rec->getName() +
"', result operator '" + Operator->getName() +
"' is not an instruction");
"', result operator '" + Operator->getName() +
"' is not an instruction");
PrintFatalNote(Rec->getValue("ResultInst"),
"Result was assigned at the following location:");
}
@@ -157,16 +158,16 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
if (Insn.isCodeGenOnly || Insn.isPseudo) {
PrintError(Rec, "In pseudo instruction '" + Rec->getName() +
"', result operator '" + Operator->getName() +
"' cannot be a pseudo instruction");
"', result operator '" + Operator->getName() +
"' cannot be a pseudo instruction");
PrintFatalNote(Rec->getValue("ResultInst"),
"Result was assigned at the following location:");
}
if (Insn.Operands.size() != Dag->getNumArgs()) {
PrintError(Rec, "In pseudo instruction '" + Rec->getName() +
"', result operator '" + Operator->getName() +
"' has the wrong number of operands");
"', result operator '" + Operator->getName() +
"' has the wrong number of operands");
PrintFatalNote(Rec->getValue("ResultInst"),
"Result was assigned at the following location:");
}
@@ -201,11 +202,11 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand)
continue;
StringMap<unsigned>::iterator SourceOp =
SourceOperands.find(Dag->getArgNameStr(i));
SourceOperands.find(Dag->getArgNameStr(i));
if (SourceOp == SourceOperands.end()) {
PrintError(Rec, "In pseudo instruction '" + Rec->getName() +
"', output operand '" + Dag->getArgNameStr(i) +
"' has no matching source operand");
"', output operand '" + Dag->getArgNameStr(i) +
"' has no matching source operand");
PrintFatalNote(Rec->getValue("ResultInst"),
"Value was assigned at the following location:");
}
@@ -213,7 +214,7 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
// MachineInstr operand.
for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand =
SourceOp->getValue();
SourceOp->getValue();
LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << i
<< "\n");
@@ -226,7 +227,8 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
// Emit file header.
emitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o);
o << "bool " << Target.getName() + "AsmPrinter" << "::\n"
o << "bool " << Target.getName() + "AsmPrinter"
<< "::\n"
<< "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n"
<< " const MachineInstr *MI) {\n";
@@ -236,12 +238,12 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
for (auto &Expansion : Expansions) {
CodeGenInstruction &Source = Expansion.Source;
CodeGenInstruction &Dest = Expansion.Dest;
o << " case " << Source.Namespace << "::"
<< Source.TheDef->getName() << ": {\n"
o << " case " << Source.Namespace << "::" << Source.TheDef->getName()
<< ": {\n"
<< " MCInst TmpInst;\n"
<< " MCOperand MCOp;\n"
<< " TmpInst.setOpcode(" << Dest.Namespace << "::"
<< Dest.TheDef->getName() << ");\n";
<< " TmpInst.setOpcode(" << Dest.Namespace
<< "::" << Dest.TheDef->getName() << ");\n";
// Copy the operands from the source instruction.
// FIXME: Instruction operands with defaults values (predicates and cc_out
@@ -252,29 +254,29 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
o << " // Operand: " << DestOperand.Name << "\n";
for (unsigned i = 0, e = DestOperand.MINumOperands; i != e; ++i) {
switch (Expansion.OperandMap[MIOpNo + i].Kind) {
case OpData::Operand:
case OpData::Operand:
o << " lowerOperand(MI->getOperand("
<< Source.Operands[Expansion.OperandMap[MIOpNo].Data
.Operand].MIOperandNo + i
<< Source.Operands[Expansion.OperandMap[MIOpNo].Data.Operand]
.MIOperandNo +
i
<< "), MCOp);\n"
<< " TmpInst.addOperand(MCOp);\n";
break;
case OpData::Imm:
case OpData::Imm:
o << " TmpInst.addOperand(MCOperand::createImm("
<< Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n";
break;
case OpData::Reg: {
Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg;
o << " TmpInst.addOperand(MCOperand::createReg(";
// "zero_reg" is special.
if (Reg->getName() == "zero_reg")
o << "0";
else
o << Reg->getValueAsString("Namespace") << "::"
<< Reg->getName();
o << "));\n";
break;
}
case OpData::Reg: {
Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg;
o << " TmpInst.addOperand(MCOperand::createReg(";
// "zero_reg" is special.
if (Reg->getName() == "zero_reg")
o << "0";
else
o << Reg->getValueAsString("Namespace") << "::" << Reg->getName();
o << "));\n";
break;
}
}
}
MIOpNo += DestOperand.MINumOperands;

View File

@@ -46,7 +46,9 @@ public:
/// Get the human-readable name for the bank.
StringRef getName() const { return TheDef.getValueAsString("Name"); }
/// Get the name of the enumerator in the ID enumeration.
std::string getEnumeratorName() const { return (TheDef.getName() + "ID").str(); }
std::string getEnumeratorName() const {
return (TheDef.getName() + "ID").str();
}
/// Get the name of the array holding the register class coverage data;
std::string getCoverageArrayName() const {
@@ -212,8 +214,7 @@ static void visitRegisterBankClasses(
}
void RegisterBankEmitter::emitBaseClassImplementation(
raw_ostream &OS, StringRef TargetName,
std::vector<RegisterBank> &Banks) {
raw_ostream &OS, StringRef TargetName, std::vector<RegisterBank> &Banks) {
const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
const CodeGenHwModes &CGH = Target.getHwModes();
@@ -229,7 +230,8 @@ void RegisterBankEmitter::emitBaseClassImplementation(
OS << "const uint32_t " << Bank.getCoverageArrayName() << "[] = {\n";
unsigned LowestIdxInWord = 0;
for (const auto &RCs : RCsGroupedByWord) {
OS << " // " << LowestIdxInWord << "-" << (LowestIdxInWord + 31) << "\n";
OS << " // " << LowestIdxInWord << "-" << (LowestIdxInWord + 31)
<< "\n";
for (const auto &RC : RCs) {
OS << " (1u << (" << RC->getQualifiedIdName() << " - "
<< LowestIdxInWord << ")) |\n";

View File

@@ -101,8 +101,8 @@ private:
} // end anonymous namespace
// runEnums - Print out enum values for all of the registers.
void RegisterInfoEmitter::runEnums(raw_ostream &OS,
CodeGenTarget &Target, CodeGenRegBank &Bank) {
void RegisterInfoEmitter::runEnums(raw_ostream &OS, CodeGenTarget &Target,
CodeGenRegBank &Bank) {
const auto &Registers = Bank.getRegisters();
// Register enums are stored as uint16_t in the tables. Make sure we'll fit.
@@ -129,7 +129,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n";
assert(Registers.size() == Registers.back().EnumValue &&
"Register enum value mismatch!");
OS << " NUM_TARGET_REGS // " << Registers.size()+1 << "\n";
OS << " NUM_TARGET_REGS // " << Registers.size() + 1 << "\n";
OS << "};\n";
if (!Namespace.empty())
OS << "} // end namespace " << Namespace << "\n";
@@ -152,7 +152,8 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "} // end namespace " << Namespace << "\n\n";
}
const std::vector<Record*> &RegAltNameIndices = Target.getRegAltNameIndices();
const std::vector<Record *> &RegAltNameIndices =
Target.getRegAltNameIndices();
// If the only definition is the default NoRegAltName, we don't need to
// emit anything.
if (RegAltNameIndices.size() > 1) {
@@ -188,7 +189,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "namespace " << Namespace << " {\n";
OS << "enum RegisterPressureSets {\n";
unsigned NumSets = Bank.getNumRegPressureSets();
for (unsigned i = 0; i < NumSets; ++i ) {
for (unsigned i = 0; i < NumSets; ++i) {
const RegUnitSet &RegUnits = Bank.getRegSetAt(i);
OS << " " << RegUnits.Name << " = " << i << ",\n";
}
@@ -201,13 +202,11 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "#endif // GET_REGINFO_ENUM\n\n";
}
static void printInt(raw_ostream &OS, int Val) {
OS << Val;
}
static void printInt(raw_ostream &OS, int Val) { OS << Val; }
void RegisterInfoEmitter::
EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
const std::string &ClassName) {
void RegisterInfoEmitter::EmitRegUnitPressure(raw_ostream &OS,
const CodeGenRegBank &RegBank,
const std::string &ClassName) {
unsigned NumRCs = RegBank.getRegClasses().size();
unsigned NumSets = RegBank.getNumRegPressureSets();
@@ -254,8 +253,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
}
OS << "};\n"
<< " return RUWeightTable[RegUnit];\n";
}
else {
} else {
OS << " // All register units have unit weight.\n"
<< " return 1;\n";
}
@@ -271,7 +269,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< "getRegPressureSetName(unsigned Idx) const {\n"
<< " static const char *PressureNameTable[] = {\n";
unsigned MaxRegUnitWeight = 0;
for (unsigned i = 0; i < NumSets; ++i ) {
for (unsigned i = 0; i < NumSets; ++i) {
const RegUnitSet &RegUnits = RegBank.getRegSetAt(i);
MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight);
OS << " \"" << RegUnits.Name << "\",\n";
@@ -287,10 +285,10 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
"{\n"
<< " static const " << getMinimalTypeForRange(MaxRegUnitWeight, 32)
<< " PressureLimitTable[] = {\n";
for (unsigned i = 0; i < NumSets; ++i ) {
for (unsigned i = 0; i < NumSets; ++i) {
const RegUnitSet &RegUnits = RegBank.getRegSetAt(i);
OS << " " << RegUnits.Weight << ", \t// " << i << ": "
<< RegUnits.Name << "\n";
OS << " " << RegUnits.Weight << ", \t// " << i << ": " << RegUnits.Name
<< "\n";
}
OS << " };\n"
<< " return PressureLimitTable[Idx];\n"
@@ -353,7 +351,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< "}\n\n";
}
using DwarfRegNumsMapPair = std::pair<Record*, std::vector<int64_t>>;
using DwarfRegNumsMapPair = std::pair<Record *, std::vector<int64_t>>;
using DwarfRegNumsVecTy = std::vector<DwarfRegNumsMapPair>;
static void finalizeDwarfRegNumsKeys(DwarfRegNumsVecTy &DwarfRegNums) {
@@ -419,7 +417,7 @@ void RegisterInfoEmitter::EmitRegMappingTables(
// Store the mapping sorted by the LLVM reg num so lookup can be done
// with a binary search.
std::map<uint64_t, Record*> Dwarf2LMap;
std::map<uint64_t, Record *> Dwarf2LMap;
for (auto &DwarfRegNum : DwarfRegNums) {
int DwarfRegNo = DwarfRegNum.second[I];
if (DwarfRegNo < 0)
@@ -531,8 +529,8 @@ void RegisterInfoEmitter::EmitRegMapping(
else
OS << "EHFlavour";
OS << ") {\n"
<< " default:\n"
<< " llvm_unreachable(\"Unknown DWARF flavour\");\n";
<< " default:\n"
<< " llvm_unreachable(\"Unknown DWARF flavour\");\n";
for (unsigned i = 0, e = maxLength; i != e; ++i) {
OS << " case " << i << ":\n";
@@ -540,14 +538,14 @@ void RegisterInfoEmitter::EmitRegMapping(
if (!isCtor)
OS << "RI->";
std::string Tmp;
raw_string_ostream(Tmp) << Namespace
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
<< "Dwarf2L";
raw_string_ostream(Tmp)
<< Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
<< "Dwarf2L";
OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, ";
if (j == 0)
OS << "false";
else
OS << "true";
OS << "false";
else
OS << "true";
OS << ");\n";
OS << " break;\n";
}
@@ -571,14 +569,14 @@ void RegisterInfoEmitter::EmitRegMapping(
if (!isCtor)
OS << "RI->";
std::string Tmp;
raw_string_ostream(Tmp) << Namespace
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
<< "L2Dwarf";
raw_string_ostream(Tmp)
<< Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
<< "L2Dwarf";
OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, ";
if (j == 0)
OS << "false";
else
OS << "true";
OS << "false";
else
OS << "true";
OS << ");\n";
OS << " break;\n";
}
@@ -588,8 +586,7 @@ void RegisterInfoEmitter::EmitRegMapping(
// Print a BitVector as a sequence of hex numbers using a little-endian mapping.
// Width is the number of bits per hex number.
static void printBitVectorAsHex(raw_ostream &OS,
const BitVector &Bits,
static void printBitVectorAsHex(raw_ostream &OS, const BitVector &Bits,
unsigned Width) {
assert(Width <= 32 && "Width too large");
unsigned Digits = (Width + 3) / 4;
@@ -604,16 +601,15 @@ static void printBitVectorAsHex(raw_ostream &OS,
// Helper to emit a set of bits into a constant byte array.
class BitVectorEmitter {
BitVector Values;
public:
void add(unsigned v) {
if (v >= Values.size())
Values.resize(((v/8)+1)*8); // Round up to the next byte.
Values.resize(((v / 8) + 1) * 8); // Round up to the next byte.
Values[v] = true;
}
void print(raw_ostream &OS) {
printBitVectorAsHex(OS, Values, 8);
}
void print(raw_ostream &OS) { printBitVectorAsHex(OS, Values, 8); }
};
static void printSimpleValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
@@ -650,9 +646,8 @@ static DiffVec &diffEncode(DiffVec &V, SparseBitVector<> List) {
return V;
}
template<typename Iter>
static
DiffVec &diffEncode(DiffVec &V, unsigned InitVal, Iter Begin, Iter End) {
template <typename Iter>
static DiffVec &diffEncode(DiffVec &V, unsigned InitVal, Iter Begin, Iter End) {
assert(V.empty() && "Clear DiffVec before diffEncode.");
unsigned Val = InitVal;
for (Iter I = Begin; I != End; ++I) {
@@ -672,7 +667,7 @@ static void printMask(raw_ostream &OS, LaneBitmask Val) {
// Try to combine Idx's compose map into Vec if it is compatible.
// Return false if it's not possible.
static bool combine(const CodeGenSubRegIndex *Idx,
SmallVectorImpl<CodeGenSubRegIndex*> &Vec) {
SmallVectorImpl<CodeGenSubRegIndex *> &Vec) {
const CodeGenSubRegIndex::CompMap &Map = Idx->getComposites();
for (const auto &I : Map) {
CodeGenSubRegIndex *&Entry = Vec[I.first->EnumValue - 1];
@@ -683,17 +678,15 @@ static bool combine(const CodeGenSubRegIndex *Idx,
// All entries are compatible. Make it so.
for (const auto &I : Map) {
auto *&Entry = Vec[I.first->EnumValue - 1];
assert((!Entry || Entry == I.second) &&
"Expected EnumValue to be unique");
assert((!Entry || Entry == I.second) && "Expected EnumValue to be unique");
Entry = I.second;
}
return true;
}
void
RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
CodeGenRegBank &RegBank,
const std::string &ClName) {
void RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
CodeGenRegBank &RegBank,
const std::string &ClName) {
const auto &SubRegIndices = RegBank.getSubRegIndices();
OS << "unsigned " << ClName
<< "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n";
@@ -707,7 +700,7 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
// Map each Sub-register index to a compatible table row.
SmallVector<unsigned, 4> RowMap;
SmallVector<SmallVector<CodeGenSubRegIndex*, 4>, 4> Rows;
SmallVector<SmallVector<CodeGenSubRegIndex *, 4>, 4> Rows;
auto SubRegIndicesSize =
std::distance(SubRegIndices.begin(), SubRegIndices.end());
@@ -760,10 +753,8 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
OS << "}\n\n";
}
void
RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
CodeGenRegBank &RegBank,
const std::string &ClName) {
void RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(
raw_ostream &OS, CodeGenRegBank &RegBank, const std::string &ClName) {
// See the comments in computeSubRegLaneMasks() for our goal here.
const auto &SubRegIndices = RegBank.getSubRegIndices();
@@ -771,8 +762,8 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
SmallVector<unsigned, 4> SubReg2SequenceIndexMap;
SmallVector<SmallVector<MaskRolPair, 1>, 4> Sequences;
for (const auto &Idx : SubRegIndices) {
const SmallVector<MaskRolPair, 1> &IdxSequence
= Idx.CompositionLaneMaskTransform;
const SmallVector<MaskRolPair, 1> &IdxSequence =
Idx.CompositionLaneMaskTransform;
unsigned Found = ~0u;
unsigned SIdx = 0;
@@ -807,7 +798,7 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
OS << format(", %2u }, ", P.RotateLeft);
}
OS << "{ LaneBitmask::getNone(), 0 }";
if (s+1 != se)
if (s + 1 != se)
OS << ", ";
OS << " // Sequence " << Idx << "\n";
Idx += Sequence.size() + 1;
@@ -820,7 +811,7 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) {
OS << " ";
OS << SubReg2SequenceIndexMap[i];
if (i+1 != e)
if (i + 1 != e)
OS << ",";
OS << " // to " << SubRegIndices[i].getName() << "\n";
}
@@ -829,15 +820,18 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
OS << "LaneBitmask " << ClName
<< "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, LaneBitmask LaneMask)"
" const {\n"
" --IdxA; assert(IdxA < " << SubRegIndices.size()
" --IdxA; assert(IdxA < "
<< SubRegIndices.size()
<< " && \"Subregister index out of bounds\");\n"
" LaneBitmask Result;\n"
" for (const MaskRolOp *Ops =\n"
" &LaneMaskComposeSequences[CompositeSequences[IdxA]];\n"
" Ops->Mask.any(); ++Ops) {\n"
" LaneBitmask::Type M = LaneMask.getAsInteger() & Ops->Mask.getAsInteger();\n"
" LaneBitmask::Type M = LaneMask.getAsInteger() & "
"Ops->Mask.getAsInteger();\n"
" if (unsigned S = Ops->RotateLeft)\n"
" Result |= LaneBitmask((M << S) | (M >> (LaneBitmask::BitWidth - S)));\n"
" Result |= LaneBitmask((M << S) | (M >> (LaneBitmask::BitWidth - "
"S)));\n"
" else\n"
" Result |= LaneBitmask(M);\n"
" }\n"
@@ -848,7 +842,8 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
<< "::reverseComposeSubRegIndexLaneMaskImpl(unsigned IdxA, "
" LaneBitmask LaneMask) const {\n"
" LaneMask &= getSubRegIndexLaneMask(IdxA);\n"
" --IdxA; assert(IdxA < " << SubRegIndices.size()
" --IdxA; assert(IdxA < "
<< SubRegIndices.size()
<< " && \"Subregister index out of bounds\");\n"
" LaneBitmask Result;\n"
" for (const MaskRolOp *Ops =\n"
@@ -856,7 +851,8 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
" Ops->Mask.any(); ++Ops) {\n"
" LaneBitmask::Type M = LaneMask.getAsInteger();\n"
" if (unsigned S = Ops->RotateLeft)\n"
" Result |= LaneBitmask((M >> S) | (M << (LaneBitmask::BitWidth - S)));\n"
" Result |= LaneBitmask((M >> S) | (M << (LaneBitmask::BitWidth - "
"S)));\n"
" else\n"
" Result |= LaneBitmask(M);\n"
" }\n"
@@ -867,9 +863,8 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
//
// runMCDesc - Print out MC register descriptions.
//
void
RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
CodeGenRegBank &RegBank) {
void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
CodeGenRegBank &RegBank) {
emitSourceFileHeader("MC Register Information", OS);
OS << "\n#ifdef GET_REGINFO_MC_DESC\n";
@@ -880,7 +875,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
auto &SubRegIndices = RegBank.getSubRegIndices();
// The lists of sub-registers and super-registers go in the same array. That
// allows us to share suffixes.
typedef std::vector<const CodeGenRegister*> RegVec;
typedef std::vector<const CodeGenRegister *> RegVec;
// Differentially encoded lists.
SequenceToOffsetTable<DiffVec> DiffSeqs;
@@ -894,7 +889,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
// Keep track of sub-register names as well. These are not differentially
// encoded.
typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec;
typedef SmallVector<const CodeGenSubRegIndex *, 4> SubRegIdxVec;
SequenceToOffsetTable<SubRegIdxVec, deref<std::less<>>> SubRegIdxSeqs;
SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size());
@@ -907,7 +902,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
RegStrings.add(std::string(Reg.getName()));
// Compute the ordered sub-register list.
SetVector<const CodeGenRegister*> SR;
SetVector<const CodeGenRegister *> SR;
Reg.addSubRegsPreOrder(SR, RegBank);
diffEncode(SubRegLists[i], Reg.EnumValue, SR.begin(), SR.end());
DiffSeqs.add(SubRegLists[i]);
@@ -961,8 +956,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "};\n\n";
// Emit the table of sub-register index sizes.
OS << "extern const MCRegisterInfo::SubRegCoveredBits "
<< TargetName << "SubRegIdxRanges[] = {\n";
OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName
<< "SubRegIdxRanges[] = {\n";
OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n";
for (const auto &Idx : SubRegIndices) {
OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// "
@@ -995,13 +990,13 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
<< LaneMaskSeqs.get(RegUnitLaneMasks[i]) << " },\n";
++i;
}
OS << "};\n\n"; // End of register descriptors...
OS << "};\n\n"; // End of register descriptors...
// Emit the table of register unit roots. Each regunit has one or two root
// registers.
OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n";
for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) {
ArrayRef<const CodeGenRegister*> Roots = RegBank.getRegUnit(i).getRoots();
ArrayRef<const CodeGenRegister *> Roots = RegBank.getRegUnit(i).getRoots();
assert(!Roots.empty() && "All regunits must have a root register.");
assert(Roots.size() <= 2 && "More than two roots not supported yet.");
OS << " { ";
@@ -1021,7 +1016,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
// Emit the register enum value arrays for each RegisterClass
for (const auto &RC : RegisterClasses) {
ArrayRef<Record*> Order = RC.getOrder();
ArrayRef<Record *> Order = RC.getOrder();
// Give the register class a legal C name if it's anonymous.
const std::string &Name = RC.getName();
@@ -1092,7 +1087,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << " " << Value << ",\n";
}
OS << "};\n"; // End of HW encoding table
OS << "};\n"; // End of HW encoding table
// MCRegisterInfo initialization routine.
OS << "static inline void Init" << TargetName
@@ -1117,9 +1112,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "#endif // GET_REGINFO_MC_DESC\n\n";
}
void
RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
CodeGenRegBank &RegBank) {
void RegisterInfoEmitter::runTargetHeader(raw_ostream &OS,
CodeGenTarget &Target,
CodeGenRegBank &RegBank) {
emitSourceFileHeader("Register Information Header Fragment", OS);
OS << "\n#ifdef GET_REGINFO_HEADER\n";
@@ -1175,8 +1170,10 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
<< " const MachineFunction &MF);\n";
const auto &RegisterClasses = RegBank.getRegClasses();
if (llvm::any_of(RegisterClasses, [](const auto &RC) { return RC.getBaseClassOrder(); })) {
OS << " const TargetRegisterClass *getPhysRegBaseClass(MCRegister Reg) const override;\n";
if (llvm::any_of(RegisterClasses,
[](const auto &RC) { return RC.getBaseClassOrder(); })) {
OS << " const TargetRegisterClass *getPhysRegBaseClass(MCRegister Reg) "
"const override;\n";
}
OS << "};\n\n";
@@ -1200,9 +1197,8 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
//
// runTargetDesc - Output the target register and register file descriptions.
//
void
RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
CodeGenRegBank &RegBank){
void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
CodeGenRegBank &RegBank) {
emitSourceFileHeader("Target Register and Register Classes Information", OS);
OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n";
@@ -1219,11 +1215,11 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
const auto &SubRegIndices = RegBank.getSubRegIndices();
// Collect all registers belonging to any allocatable class.
std::set<Record*> AllocatableRegs;
std::set<Record *> AllocatableRegs;
// Collect allocatable registers.
for (const auto &RC : RegisterClasses) {
ArrayRef<Record*> Order = RC.getOrder();
ArrayRef<Record *> Order = RC.getOrder();
if (RC.Allocatable)
AllocatableRegs.insert(Order.begin(), Order.end());
@@ -1297,7 +1293,6 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "};\n";
OS << "\nstatic const TargetRegisterClass *const "
<< "NullRegClasses[] = { nullptr };\n\n";
@@ -1320,7 +1315,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Every bit mask present in the list has at least one bit set.
// Compress the sub-reg index lists.
typedef std::vector<const CodeGenSubRegIndex*> IdxList;
typedef std::vector<const CodeGenSubRegIndex *> IdxList;
SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size());
SequenceToOffsetTable<IdxList, deref<std::less<>>> SuperRegIdxSeqs;
BitVector MaskBV(RegisterClasses.size());
@@ -1354,14 +1349,14 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Emit NULL terminated super-class lists.
for (const auto &RC : RegisterClasses) {
ArrayRef<CodeGenRegisterClass*> Supers = RC.getSuperClasses();
ArrayRef<CodeGenRegisterClass *> Supers = RC.getSuperClasses();
// Skip classes without supers. We can reuse NullRegClasses.
if (Supers.empty())
continue;
OS << "static const TargetRegisterClass *const "
<< RC.getName() << "Superclasses[] = {\n";
OS << "static const TargetRegisterClass *const " << RC.getName()
<< "Superclasses[] = {\n";
for (const auto *Super : Supers)
OS << " &" << Super->getQualifiedName() << "RegClass,\n";
OS << " nullptr\n};\n\n";
@@ -1371,12 +1366,12 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
for (const auto &RC : RegisterClasses) {
if (!RC.AltOrderSelect.empty()) {
OS << "\nstatic inline unsigned " << RC.getName()
<< "AltOrderSelect(const MachineFunction &MF) {"
<< RC.AltOrderSelect << "}\n\n"
<< "AltOrderSelect(const MachineFunction &MF) {" << RC.AltOrderSelect
<< "}\n\n"
<< "static ArrayRef<MCPhysReg> " << RC.getName()
<< "GetRawAllocationOrder(const MachineFunction &MF) {\n";
for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) {
ArrayRef<Record*> Elems = RC.getOrder(oi);
for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) {
ArrayRef<Record *> Elems = RC.getOrder(oi);
if (!Elems.empty()) {
OS << " static const MCPhysReg AltOrder" << oi << "[] = {";
for (unsigned elem = 0; elem != Elems.size(); ++elem)
@@ -1556,8 +1551,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
EnumValue = SubRegClass->EnumValue + 1;
}
OS << " " << EnumValue << ",\t// "
<< RC.getName() << ':' << Idx.getName();
OS << " " << EnumValue << ",\t// " << RC.getName() << ':'
<< Idx.getName();
if (MatchingSubClass) {
CodeGenRegisterClass *SubRegClass = MatchingSubClass->second;
@@ -1581,7 +1576,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Emit register base class mapper
if (!RegisterClasses.empty()) {
// Collect base classes
SmallVector<const CodeGenRegisterClass*> BaseClasses;
SmallVector<const CodeGenRegisterClass *> BaseClasses;
for (const auto &RC : RegisterClasses) {
if (RC.getBaseClassOrder())
BaseClasses.push_back(&RC);
@@ -1592,9 +1587,10 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Apply order
struct BaseClassOrdering {
bool operator()(const CodeGenRegisterClass *LHS, const CodeGenRegisterClass *RHS) const {
return std::pair(*LHS->getBaseClassOrder(), LHS->EnumValue)
< std::pair(*RHS->getBaseClassOrder(), RHS->EnumValue);
bool operator()(const CodeGenRegisterClass *LHS,
const CodeGenRegisterClass *RHS) const {
return std::pair(*LHS->getBaseClassOrder(), LHS->EnumValue) <
std::pair(*RHS->getBaseClassOrder(), RHS->EnumValue);
}
};
llvm::stable_sort(BaseClasses, BaseClassOrdering());
@@ -1638,8 +1634,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "extern const char " << TargetName << "RegClassStrings[];\n";
OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n";
OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n";
OS << "extern const MCRegisterInfo::SubRegCoveredBits "
<< TargetName << "SubRegIdxRanges[];\n";
OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName
<< "SubRegIdxRanges[];\n";
OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n";
EmitRegMappingTables(OS, Regs, true);
@@ -1673,16 +1669,15 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "}\n\n";
// Emit CalleeSavedRegs information.
std::vector<Record*> CSRSets =
Records.getAllDerivedDefinitions("CalleeSavedRegs");
std::vector<Record *> CSRSets =
Records.getAllDerivedDefinitions("CalleeSavedRegs");
for (unsigned i = 0, e = CSRSets.size(); i != e; ++i) {
Record *CSRSet = CSRSets[i];
const SetTheory::RecVec *Regs = RegBank.getSets().expand(CSRSet);
assert(Regs && "Cannot expand CalleeSavedRegs instance");
// Emit the *_SaveList list of callee-saved registers.
OS << "static const MCPhysReg " << CSRSet->getName()
<< "_SaveList[] = { ";
OS << "static const MCPhysReg " << CSRSet->getName() << "_SaveList[] = { ";
for (unsigned r = 0, re = Regs->size(); r != re; ++r)
OS << getQualifiedName((*Regs)[r]) << ", ";
OS << "0 };\n";
@@ -1693,11 +1688,11 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Check for an optional OtherPreserved set.
// Add those registers to RegMask, but not to SaveList.
if (DagInit *OPDag =
dyn_cast<DagInit>(CSRSet->getValueInit("OtherPreserved"))) {
dyn_cast<DagInit>(CSRSet->getValueInit("OtherPreserved"))) {
SetTheory::RecSet OPSet;
RegBank.getSets().evaluate(OPDag, OPSet, CSRSet->getLoc());
Covered |= RegBank.computeCoveredRegisters(
ArrayRef<Record*>(OPSet.begin(), OPSet.end()));
ArrayRef<Record *>(OPSet.begin(), OPSet.end()));
}
// Add all constant physical registers to the preserved mask:
@@ -1709,8 +1704,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
Covered |= RegBank.computeCoveredRegisters(
ArrayRef<Record *>(ConstantSet.begin(), ConstantSet.end()));
OS << "static const uint32_t " << CSRSet->getName()
<< "_RegMask[] = { ";
OS << "static const uint32_t " << CSRSet->getName() << "_RegMask[] = { ";
printBitVectorAsHex(OS, Covered, 32);
OS << "};\n";
}
@@ -1795,7 +1789,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "}\n\n";
OS << "const " << TargetName << "FrameLowering *\n" << TargetName
OS << "const " << TargetName << "FrameLowering *\n"
<< TargetName
<< "GenRegisterInfo::getFrameLowering(const MachineFunction &MF) {\n"
<< " return static_cast<const " << TargetName << "FrameLowering *>(\n"
<< " MF.getSubtarget().getFrameLowering());\n"
@@ -1827,7 +1822,7 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) {
CodeGenRegBank &RegBank = Target.getRegBank();
const CodeGenHwModes &CGH = Target.getHwModes();
unsigned NumModes = CGH.getNumModeIds();
auto getModeName = [CGH] (unsigned M) -> StringRef {
auto getModeName = [CGH](unsigned M) -> StringRef {
if (M == 0)
return "Default";
return CGH.getMode(M).Name;
@@ -1883,9 +1878,10 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) {
OS << '\n';
OS << "\tCoveredBySubregs: " << R.CoveredBySubRegs << '\n';
OS << "\tHasDisjunctSubRegs: " << R.HasDisjunctSubRegs << '\n';
for (std::pair<CodeGenSubRegIndex*,CodeGenRegister*> P : R.getSubRegs()) {
OS << "\tSubReg " << P.first->getName()
<< " = " << P.second->getName() << '\n';
for (std::pair<CodeGenSubRegIndex *, CodeGenRegister *> P :
R.getSubRegs()) {
OS << "\tSubReg " << P.first->getName() << " = " << P.second->getName()
<< '\n';
}
}
}

View File

@@ -34,6 +34,6 @@ enum SDNP {
unsigned parseSDPatternOperatorProperties(Record *R);
}
} // namespace llvm
#endif

View File

@@ -134,7 +134,7 @@ private:
Twine("Entry for field '") + Field.Name + "' is null");
return std::string(Entry->first);
}
PrintFatalError(Loc, Twine("invalid field type for field '") + Field.Name +
PrintFatalError(Loc, Twine("invalid field type for field '") + Field.Name +
"'; expected: bit, bits, string, or code");
}
@@ -173,7 +173,7 @@ private:
return "uint32_t";
if (NumBits <= 64)
return "uint64_t";
PrintFatalError(Index.Loc, Twine("In table '") + Table.Name +
PrintFatalError(Index.Loc, Twine("In table '") + Table.Name +
"' lookup method '" + Index.Name +
"', key field '" + Field.Name +
"' of type bits is too large");
@@ -425,7 +425,7 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
OS << " struct KeyType {\n";
for (const auto &Field : Index.Fields) {
OS << " " << searchableFieldType(Table, Index, Field, TypeInTempStruct)
OS << " " << searchableFieldType(Table, Index, Field, TypeInTempStruct)
<< " " << Field.Name << ";\n";
}
OS << " };\n";
@@ -436,7 +436,7 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
if (isa<StringRecTy>(Field.RecType)) {
OS << ".upper()";
if (IsPrimary)
PrintFatalError(Index.Loc,
PrintFatalError(Index.Loc,
Twine("In table '") + Table.Name +
"', use a secondary lookup method for "
"case-insensitive comparison of field '" +
@@ -580,7 +580,7 @@ std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex(
Twine("In table '") + Table.Name +
"', 'PrimaryKey' or 'Key' refers to nonexistent field '" +
FieldName + "'");
Index->Fields.push_back(*Field);
}
@@ -643,11 +643,11 @@ void SearchableTableEmitter::collectTableEntries(
} else {
RecTy *Ty = resolveTypes(Field.RecType, TI->getType());
if (!Ty)
PrintFatalError(EntryRec->getValue(Field.Name),
PrintFatalError(EntryRec->getValue(Field.Name),
Twine("Field '") + Field.Name + "' of table '" +
Table.Name + "' entry has incompatible type: " +
TI->getType()->getAsString() + " vs. " +
Field.RecType->getAsString());
Table.Name + "' entry has incompatible type: " +
TI->getType()->getAsString() + " vs. " +
Field.RecType->getAsString());
Field.RecType = Ty;
}
}
@@ -702,7 +702,7 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
StringRef FilterClass = EnumRec->getValueAsString("FilterClass");
Enum->Class = Records.getClass(FilterClass);
if (!Enum->Class)
PrintFatalError(EnumRec->getValue("FilterClass"),
PrintFatalError(EnumRec->getValue("FilterClass"),
Twine("Enum FilterClass '") + FilterClass +
"' does not exist");
@@ -723,11 +723,13 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
for (const auto &FieldName : Fields) {
Table->Fields.emplace_back(FieldName); // Construct a GenericField.
if (auto TypeOfRecordVal = TableRec->getValue(("TypeOf_" + FieldName).str())) {
if (!parseFieldType(Table->Fields.back(), TypeOfRecordVal->getValue())) {
PrintError(TypeOfRecordVal,
Twine("Table '") + Table->Name +
"' has invalid 'TypeOf_" + FieldName +
if (auto TypeOfRecordVal =
TableRec->getValue(("TypeOf_" + FieldName).str())) {
if (!parseFieldType(Table->Fields.back(),
TypeOfRecordVal->getValue())) {
PrintError(TypeOfRecordVal,
Twine("Table '") + Table->Name + "' has invalid 'TypeOf_" +
FieldName +
"': " + TypeOfRecordVal->getValue()->getAsString());
PrintFatalNote("The 'TypeOf_xxx' field must be a string naming a "
"GenericEnum record, or \"code\"");
@@ -737,9 +739,9 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
StringRef FilterClass = TableRec->getValueAsString("FilterClass");
if (!Records.getClass(FilterClass))
PrintFatalError(TableRec->getValue("FilterClass"),
Twine("Table FilterClass '") +
FilterClass + "' does not exist");
PrintFatalError(TableRec->getValue("FilterClass"),
Twine("Table FilterClass '") + FilterClass +
"' does not exist");
RecordVal *FilterClassFieldVal = TableRec->getValue("FilterClassField");
std::vector<Record *> Definitions =
@@ -779,14 +781,14 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
Record *TableRec = IndexRec->getValueAsDef("Table");
auto It = TableMap.find(TableRec);
if (It == TableMap.end())
PrintFatalError(IndexRec->getValue("Table"),
PrintFatalError(IndexRec->getValue("Table"),
Twine("SearchIndex '") + IndexRec->getName() +
"' refers to nonexistent table '" +
TableRec->getName());
GenericTable &Table = *It->second;
Table.Indices.push_back(
parseSearchIndex(Table, IndexRec->getValue("Key"), IndexRec->getName(),
parseSearchIndex(Table, IndexRec->getValue("Key"), IndexRec->getName(),
IndexRec->getValueAsListOfStrings("Key"),
IndexRec->getValueAsBit("EarlyOut")));
}

View File

@@ -44,7 +44,7 @@ static inline void printChar(raw_ostream &OS, char C) {
///
/// @tparam SeqT The sequence container. (vector or string).
/// @tparam Less A stable comparator for SeqT elements.
template<typename SeqT, typename Less = std::less<typename SeqT::value_type> >
template <typename SeqT, typename Less = std::less<typename SeqT::value_type>>
class SequenceToOffsetTable {
typedef typename SeqT::value_type ElemT;
@@ -53,8 +53,8 @@ class SequenceToOffsetTable {
struct SeqLess {
Less L;
bool operator()(const SeqT &A, const SeqT &B) const {
return std::lexicographical_compare(A.rbegin(), A.rend(),
B.rbegin(), B.rend(), L);
return std::lexicographical_compare(A.rbegin(), A.rend(), B.rbegin(),
B.rend(), L);
}
};
@@ -153,15 +153,15 @@ public:
/// emit - Print out the table as the body of an array initializer.
/// Use the Print function to print elements.
void emit(raw_ostream &OS,
void (*Print)(raw_ostream&, ElemT),
void emit(raw_ostream &OS, void (*Print)(raw_ostream &, ElemT),
const char *Term = "0") const {
assert((empty() || Entries) && "Call layout() before emit()");
for (typename SeqMap::const_iterator I = Seqs.begin(), E = Seqs.end();
I != E; ++I) {
OS << " /* " << I->second << " */ ";
for (typename SeqT::const_iterator SI = I->first.begin(),
SE = I->first.end(); SI != SE; ++SI) {
SE = I->first.end();
SI != SE; ++SI) {
Print(OS, *SI);
OS << ", ";
}

View File

@@ -51,9 +51,9 @@ struct LessRecordFieldFieldName {
};
class SubtargetEmitter {
// Each processor has a SchedClassDesc table with an entry for each SchedClass.
// The SchedClassDesc table indexes into a global write resource table, write
// latency table, and read advance table.
// Each processor has a SchedClassDesc table with an entry for each
// SchedClass. The SchedClassDesc table indexes into a global write resource
// table, write latency table, and read advance table.
struct SchedClassTables {
std::vector<std::vector<MCSchedClassDesc>> ProcSchedClasses;
std::vector<MCWriteProcResEntry> WriteProcResources;
@@ -89,20 +89,18 @@ class SubtargetEmitter {
const DenseMap<Record *, unsigned> &FeatureMap);
unsigned CPUKeyValues(raw_ostream &OS,
const DenseMap<Record *, unsigned> &FeatureMap);
void FormItineraryStageString(const std::string &Names,
Record *ItinData, std::string &ItinString,
unsigned &NStages);
void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
void FormItineraryStageString(const std::string &Names, Record *ItinData,
std::string &ItinString, unsigned &NStages);
void FormItineraryOperandCycleString(Record *ItinData,
std::string &ItinString,
unsigned &NOperandCycles);
void FormItineraryBypassString(const std::string &Names,
Record *ItinData,
std::string &ItinString, unsigned NOperandCycles);
void EmitStageAndOperandCycleData(raw_ostream &OS,
std::vector<std::vector<InstrItinerary>>
&ProcItinLists);
void FormItineraryBypassString(const std::string &Names, Record *ItinData,
std::string &ItinString,
unsigned NOperandCycles);
void EmitStageAndOperandCycleData(
raw_ostream &OS, std::vector<std::vector<InstrItinerary>> &ProcItinLists);
void EmitItineraries(raw_ostream &OS,
std::vector<std::vector<InstrItinerary>>
&ProcItinLists);
std::vector<std::vector<InstrItinerary>> &ProcItinLists);
unsigned EmitRegisterFileTables(const CodeGenProcModel &ProcModel,
raw_ostream &OS);
void EmitLoadStoreQueueInfo(const CodeGenProcModel &ProcModel,
@@ -153,15 +151,16 @@ public:
void SubtargetEmitter::Enumeration(raw_ostream &OS,
DenseMap<Record *, unsigned> &FeatureMap) {
// Get all records of class and sort
std::vector<Record*> DefList =
Records.getAllDerivedDefinitions("SubtargetFeature");
std::vector<Record *> DefList =
Records.getAllDerivedDefinitions("SubtargetFeature");
llvm::sort(DefList, LessRecord());
unsigned N = DefList.size();
if (N == 0)
return;
if (N + 1 > MAX_SUBTARGET_FEATURES)
PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
PrintFatalError(
"Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
OS << "namespace " << Target << " {\n";
@@ -248,8 +247,8 @@ void SubtargetEmitter::EmitSubtargetInfoMacroCalls(raw_ostream &OS) {
unsigned SubtargetEmitter::FeatureKeyValues(
raw_ostream &OS, const DenseMap<Record *, unsigned> &FeatureMap) {
// Gather and sort all the features
std::vector<Record*> FeatureList =
Records.getAllDerivedDefinitions("SubtargetFeature");
std::vector<Record *> FeatureList =
Records.getAllDerivedDefinitions("SubtargetFeature");
if (FeatureList.empty())
return 0;
@@ -269,13 +268,14 @@ unsigned SubtargetEmitter::FeatureKeyValues(
StringRef CommandLineName = Feature->getValueAsString("Name");
StringRef Desc = Feature->getValueAsString("Desc");
if (CommandLineName.empty()) continue;
if (CommandLineName.empty())
continue;
// Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in } }
// Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in
// } }
OS << " { "
<< "\"" << CommandLineName << "\", "
<< "\"" << Desc << "\", "
<< Target << "::" << Name << ", ";
<< "\"" << Desc << "\", " << Target << "::" << Name << ", ";
RecVec ImpliesList = Feature->getValueAsListOfDefs("Implies");
@@ -299,8 +299,8 @@ unsigned
SubtargetEmitter::CPUKeyValues(raw_ostream &OS,
const DenseMap<Record *, unsigned> &FeatureMap) {
// Gather and sort processor information
std::vector<Record*> ProcessorList =
Records.getAllDerivedDefinitions("Processor");
std::vector<Record *> ProcessorList =
Records.getAllDerivedDefinitions("Processor");
llvm::sort(ProcessorList, LessRecordFieldName());
// Begin processor table
@@ -324,7 +324,7 @@ SubtargetEmitter::CPUKeyValues(raw_ostream &OS,
// Emit the scheduler model pointer.
const std::string &ProcModelName =
SchedModels.getModelForProc(Processor).ModelName;
SchedModels.getModelForProc(Processor).ModelName;
OS << ", &" << ProcModelName << " },\n";
}
@@ -363,7 +363,8 @@ void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
for (unsigned j = 0, M = UnitList.size(); j < M;) {
// Add name and bitwise or
ItinString += Name + "FU::" + UnitList[j]->getName().str();
if (++j < M) ItinString += " | ";
if (++j < M)
ItinString += " | ";
}
int TimeInc = Stage->getValueAsInt("TimeInc");
@@ -374,7 +375,8 @@ void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
// Close off stage
ItinString += " }";
if (++i < N) ItinString += ", ";
if (++i < N)
ItinString += ", ";
}
}
@@ -383,11 +385,11 @@ void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
// operand cycle initialization for the specified itinerary. N is the
// number of operands that has cycles specified.
//
void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
std::string &ItinString, unsigned &NOperandCycles) {
void SubtargetEmitter::FormItineraryOperandCycleString(
Record *ItinData, std::string &ItinString, unsigned &NOperandCycles) {
// Get operand cycle list
std::vector<int64_t> OperandCycleList =
ItinData->getValueAsListOfInts("OperandCycles");
ItinData->getValueAsListOfInts("OperandCycles");
// For each operand cycle
NOperandCycles = OperandCycleList.size();
@@ -422,12 +424,10 @@ void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
// by CodeGenSchedClass::Index.
//
void SubtargetEmitter::
EmitStageAndOperandCycleData(raw_ostream &OS,
std::vector<std::vector<InstrItinerary>>
&ProcItinLists) {
void SubtargetEmitter::EmitStageAndOperandCycleData(
raw_ostream &OS, std::vector<std::vector<InstrItinerary>> &ProcItinLists) {
// Multiple processor models may share an itinerary record. Emit it once.
SmallPtrSet<Record*, 8> ItinsDefSet;
SmallPtrSet<Record *, 8> ItinsDefSet;
// Emit functional units for all the itineraries.
for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
@@ -452,30 +452,31 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
RecVec BPs = ProcModel.ItinsDef->getValueAsListOfDefs("BP");
if (!BPs.empty()) {
OS << "\n// Pipeline forwarding paths for itineraries \"" << Name
<< "\"\n" << "namespace " << Name << "Bypass {\n";
<< "\"\n"
<< "namespace " << Name << "Bypass {\n";
OS << " const unsigned NoBypass = 0;\n";
for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
OS << " const unsigned " << BPs[j]->getName()
<< " = 1 << " << j << ";\n";
OS << " const unsigned " << BPs[j]->getName() << " = 1 << " << j
<< ";\n";
OS << "} // end namespace " << Name << "Bypass\n";
}
}
// Begin stages table
std::string StageTable = "\nextern const llvm::InstrStage " + Target +
"Stages[] = {\n";
std::string StageTable =
"\nextern const llvm::InstrStage " + Target + "Stages[] = {\n";
StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
// Begin operand cycle table
std::string OperandCycleTable = "extern const unsigned " + Target +
"OperandCycles[] = {\n";
std::string OperandCycleTable =
"extern const unsigned " + Target + "OperandCycles[] = {\n";
OperandCycleTable += " 0, // No itinerary\n";
// Begin pipeline bypass table
std::string BypassTable = "extern const unsigned " + Target +
"ForwardingPaths[] = {\n";
std::string BypassTable =
"extern const unsigned " + Target + "ForwardingPaths[] = {\n";
BypassTable += " 0, // No itinerary\n";
// For each Itinerary across all processors, add a unique entry to the stages,
@@ -485,7 +486,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
// Add process itinerary to the list.
ProcItinLists.resize(ProcItinLists.size()+1);
ProcItinLists.resize(ProcItinLists.size() + 1);
// If this processor defines no itineraries, then leave the itinerary list
// empty.
@@ -542,19 +543,20 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
// Check to see if operand cycle already exists and create if it doesn't
uint16_t FindOperandCycle = 0;
if (NOperandCycles > 0) {
std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
std::string ItinOperandString =
ItinOperandCycleString + ItinBypassString;
FindOperandCycle = ItinOperandMap[ItinOperandString];
if (FindOperandCycle == 0) {
// Emit as cycle, // index
OperandCycleTable += ItinOperandCycleString + ", // ";
std::string OperandIdxComment = itostr(OperandCycleCount);
if (NOperandCycles > 1)
OperandIdxComment += "-"
+ itostr(OperandCycleCount + NOperandCycles - 1);
OperandIdxComment +=
"-" + itostr(OperandCycleCount + NOperandCycles - 1);
OperandCycleTable += OperandIdxComment + "\n";
// Record Itin class number.
ItinOperandMap[ItinOperandCycleString] =
FindOperandCycle = OperandCycleCount;
ItinOperandMap[ItinOperandCycleString] = FindOperandCycle =
OperandCycleCount;
// Emit as bypass, // index
BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
OperandCycleCount += NOperandCycles;
@@ -599,17 +601,17 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
// Itineraries for each processor. The Itinerary lists are indexed on
// CodeGenSchedClass::Index.
//
void SubtargetEmitter::
EmitItineraries(raw_ostream &OS,
std::vector<std::vector<InstrItinerary>> &ProcItinLists) {
void SubtargetEmitter::EmitItineraries(
raw_ostream &OS, std::vector<std::vector<InstrItinerary>> &ProcItinLists) {
// Multiple processor models may share an itinerary record. Emit it once.
SmallPtrSet<Record*, 8> ItinsDefSet;
SmallPtrSet<Record *, 8> ItinsDefSet;
// For each processor's machine model
std::vector<std::vector<InstrItinerary>>::iterator
ProcItinListsIter = ProcItinLists.begin();
std::vector<std::vector<InstrItinerary>>::iterator ProcItinListsIter =
ProcItinLists.begin();
for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
PE = SchedModels.procModelEnd();
PI != PE; ++PI, ++ProcItinListsIter) {
Record *ItinsDef = PI->ItinsDef;
if (!ItinsDefSet.insert(ItinsDef).second)
@@ -636,13 +638,10 @@ EmitItineraries(raw_ostream &OS,
// Emit Itinerary in the form of
// { firstStage, lastStage, firstCycle, lastCycle } // index
OS << " { " <<
Intinerary.NumMicroOps << ", " <<
Intinerary.FirstStage << ", " <<
Intinerary.LastStage << ", " <<
Intinerary.FirstOperandCycle << ", " <<
Intinerary.LastOperandCycle << " }" <<
", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
OS << " { " << Intinerary.NumMicroOps << ", " << Intinerary.FirstStage
<< ", " << Intinerary.LastStage << ", " << Intinerary.FirstOperandCycle
<< ", " << Intinerary.LastOperandCycle << " }"
<< ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
}
// End processor itinerary table
OS << " { 0, uint16_t(~0U), uint16_t(~0U), uint16_t(~0U), uint16_t(~0U) }"
@@ -840,13 +839,11 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
NumUnits += RU->getValueAsInt("NumUnits");
SubUnitsOffset += RU->getValueAsInt("NumUnits");
}
}
else {
} else {
// Find the SuperIdx
if (PRDef->getValueInit("Super")->isComplete()) {
SuperDef =
SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"),
ProcModel, PRDef->getLoc());
SuperDef = SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"),
ProcModel, PRDef->getLoc());
SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
}
NumUnits = PRDef->getValueAsInt("NumUnits");
@@ -862,7 +859,7 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
} else {
OS << "nullptr";
}
OS << "}, // #" << i+1;
OS << "}, // #" << i + 1;
if (SuperDef)
OS << ", Super=" << SuperDef->getName();
OS << "\n";
@@ -872,8 +869,9 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
// Find the WriteRes Record that defines processor resources for this
// SchedWrite.
Record *SubtargetEmitter::FindWriteResources(
const CodeGenSchedRW &SchedWrite, const CodeGenProcModel &ProcModel) {
Record *
SubtargetEmitter::FindWriteResources(const CodeGenSchedRW &SchedWrite,
const CodeGenProcModel &ProcModel) {
// Check if the SchedWrite is already subtarget-specific and directly
// specifies a set of processor resources.
@@ -883,16 +881,18 @@ Record *SubtargetEmitter::FindWriteResources(
Record *AliasDef = nullptr;
for (Record *A : SchedWrite.Aliases) {
const CodeGenSchedRW &AliasRW =
SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
continue;
}
if (AliasDef)
PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
"defined for processor " + ProcModel.ModelName +
" Ensure only one SchedAlias exists per RW.");
PrintFatalError(AliasRW.TheDef->getLoc(),
"Multiple aliases "
"defined for processor " +
ProcModel.ModelName +
" Ensure only one SchedAlias exists per RW.");
AliasDef = AliasRW.TheDef;
}
if (AliasDef && AliasDef->isSubClassOf("SchedWriteRes"))
@@ -903,12 +903,12 @@ Record *SubtargetEmitter::FindWriteResources(
for (Record *WR : ProcModel.WriteResDefs) {
if (!WR->isSubClassOf("WriteRes"))
continue;
if (AliasDef == WR->getValueAsDef("WriteType")
|| SchedWrite.TheDef == WR->getValueAsDef("WriteType")) {
if (AliasDef == WR->getValueAsDef("WriteType") ||
SchedWrite.TheDef == WR->getValueAsDef("WriteType")) {
if (ResDef) {
PrintFatalError(WR->getLoc(), "Resources are defined for both "
"SchedWrite and its alias on processor " +
ProcModel.ModelName);
"SchedWrite and its alias on processor " +
ProcModel.ModelName);
}
ResDef = WR;
}
@@ -918,7 +918,7 @@ Record *SubtargetEmitter::FindWriteResources(
if (!ResDef) {
PrintFatalError(ProcModel.ModelDef->getLoc(),
Twine("Processor does not define resources for ") +
SchedWrite.TheDef->getName());
SchedWrite.TheDef->getName());
}
return ResDef;
}
@@ -935,16 +935,18 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
Record *AliasDef = nullptr;
for (Record *A : SchedRead.Aliases) {
const CodeGenSchedRW &AliasRW =
SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
continue;
}
if (AliasDef)
PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
"defined for processor " + ProcModel.ModelName +
" Ensure only one SchedAlias exists per RW.");
PrintFatalError(AliasRW.TheDef->getLoc(),
"Multiple aliases "
"defined for processor " +
ProcModel.ModelName +
" Ensure only one SchedAlias exists per RW.");
AliasDef = AliasRW.TheDef;
}
if (AliasDef && AliasDef->isSubClassOf("SchedReadAdvance"))
@@ -955,12 +957,12 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
for (Record *RA : ProcModel.ReadAdvanceDefs) {
if (!RA->isSubClassOf("ReadAdvance"))
continue;
if (AliasDef == RA->getValueAsDef("ReadType")
|| SchedRead.TheDef == RA->getValueAsDef("ReadType")) {
if (AliasDef == RA->getValueAsDef("ReadType") ||
SchedRead.TheDef == RA->getValueAsDef("ReadType")) {
if (ResDef) {
PrintFatalError(RA->getLoc(), "Resources are defined for both "
"SchedRead and its alias on processor " +
ProcModel.ModelName);
"SchedRead and its alias on processor " +
ProcModel.ModelName);
}
ResDef = RA;
}
@@ -970,7 +972,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") {
PrintFatalError(ProcModel.ModelDef->getLoc(),
Twine("Processor does not define resources for ") +
SchedRead.TheDef->getName());
SchedRead.TheDef->getName());
}
return ResDef;
}
@@ -994,11 +996,10 @@ void SubtargetEmitter::ExpandProcResources(
if (SubDef->isSubClassOf("ProcResGroup")) {
// Disallow this for simplicitly.
PrintFatalError(SubDef->getLoc(), "Processor resource group "
" cannot be a super resources.");
" cannot be a super resources.");
}
Record *SuperDef =
SchedModels.findProcResUnits(SubDef->getValueAsDef("Super"), PM,
SubDef->getLoc());
Record *SuperDef = SchedModels.findProcResUnits(
SubDef->getValueAsDef("Super"), PM, SubDef->getLoc());
PRVec.push_back(SuperDef);
ReleaseAtCycles.push_back(ReleaseAtCycles[i]);
AcquireAtCycles.push_back(AcquireAtCycles[i]);
@@ -1010,7 +1011,7 @@ void SubtargetEmitter::ExpandProcResources(
continue;
RecVec SuperResources = PR->getValueAsListOfDefs("Resources");
RecIter SubI = SubResources.begin(), SubE = SubResources.end();
for( ; SubI != SubE; ++SubI) {
for (; SubI != SubE; ++SubI) {
if (!is_contained(SuperResources, *SubI)) {
break;
}
@@ -1051,7 +1052,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
// A Variant SchedClass has no resources of its own.
bool HasVariants = false;
for (const CodeGenSchedTransition &CGT :
make_range(SC.Transitions.begin(), SC.Transitions.end())) {
make_range(SC.Transitions.begin(), SC.Transitions.end())) {
if (CGT.ProcIndex == ProcModel.Index) {
HasVariants = true;
break;
@@ -1114,8 +1115,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
for (unsigned W : Writes) {
IdxVec WriteSeq;
SchedModels.expandRWSeqForProc(W, WriteSeq, /*IsRead=*/false,
ProcModel);
SchedModels.expandRWSeqForProc(W, WriteSeq, /*IsRead=*/false, ProcModel);
// For each operand, create a latency entry.
MCWriteLatencyEntry WLEntry;
@@ -1125,7 +1125,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
// If this Write is not referenced by a ReadAdvance, don't distinguish it
// from other WriteLatency entries.
if (!SchedModels.hasReadOfWrite(
SchedModels.getSchedWrite(WriteID).TheDef)) {
SchedModels.getSchedWrite(WriteID).TheDef)) {
WriteID = 0;
}
WLEntry.WriteResourceID = WriteID;
@@ -1133,7 +1133,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
for (unsigned WS : WriteSeq) {
Record *WriteRes =
FindWriteResources(SchedModels.getSchedWrite(WS), ProcModel);
FindWriteResources(SchedModels.getSchedWrite(WS), ProcModel);
// Mark the parent class as invalid for unsupported write types.
if (WriteRes->getValueAsBit("Unsupported")) {
@@ -1170,7 +1170,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
.concat(Twine(ReleaseAtCycles.size())));
}
if (!AcquireAtCycles.empty() && AcquireAtCycles.size() != PRVec.size()) {
if (!AcquireAtCycles.empty() &&
AcquireAtCycles.size() != PRVec.size()) {
PrintFatalError(
WriteRes->getLoc(),
Twine("Inconsistent resource cycles: size(AcquireAtCycles) != "
@@ -1197,8 +1198,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
ExpandProcResources(PRVec, ReleaseAtCycles, AcquireAtCycles, ProcModel);
assert(AcquireAtCycles.size() == ReleaseAtCycles.size());
for (unsigned PRIdx = 0, PREnd = PRVec.size();
PRIdx != PREnd; ++PRIdx) {
for (unsigned PRIdx = 0, PREnd = PRVec.size(); PRIdx != PREnd;
++PRIdx) {
MCWriteProcResEntry WPREntry;
WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
@@ -1220,9 +1221,9 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
// serially, rather than multiple parallel uses. This is important for
// in-order machine where the resource consumption is a hazard.
unsigned WPRIdx = 0, WPREnd = WriteProcResources.size();
for( ; WPRIdx != WPREnd; ++WPRIdx) {
if (WriteProcResources[WPRIdx].ProcResourceIdx
== WPREntry.ProcResourceIdx) {
for (; WPRIdx != WPREnd; ++WPRIdx) {
if (WriteProcResources[WPRIdx].ProcResourceIdx ==
WPREntry.ProcResourceIdx) {
// TODO: multiple use of the same resources would
// require either 1. thinking of how to handle multiple
// intervals for the same resource in
@@ -1245,10 +1246,10 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
}
// Create an entry for each operand Read in this SchedClass.
// Entries must be sorted first by UseIdx then by WriteResourceID.
for (unsigned UseIdx = 0, EndIdx = Reads.size();
UseIdx != EndIdx; ++UseIdx) {
for (unsigned UseIdx = 0, EndIdx = Reads.size(); UseIdx != EndIdx;
++UseIdx) {
Record *ReadAdvance =
FindReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel);
FindReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel);
if (!ReadAdvance)
continue;
@@ -1267,7 +1268,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
}
}
llvm::sort(WriteIDs);
for(unsigned W : WriteIDs) {
for (unsigned W : WriteIDs) {
MCReadAdvanceEntry RAEntry;
RAEntry.UseIdx = UseIdx;
RAEntry.WriteResourceID = W;
@@ -1288,9 +1289,9 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
SCDesc.NumWriteProcResEntries = WriteProcResources.size();
std::vector<MCWriteProcResEntry>::iterator WPRPos =
std::search(SchedTables.WriteProcResources.begin(),
SchedTables.WriteProcResources.end(),
WriteProcResources.begin(), WriteProcResources.end());
std::search(SchedTables.WriteProcResources.begin(),
SchedTables.WriteProcResources.end(),
WriteProcResources.begin(), WriteProcResources.end());
if (WPRPos != SchedTables.WriteProcResources.end())
SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin();
else {
@@ -1300,10 +1301,9 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
}
// Latency entries must remain in operand order.
SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
std::vector<MCWriteLatencyEntry>::iterator WLPos =
std::search(SchedTables.WriteLatencies.begin(),
SchedTables.WriteLatencies.end(),
WriteLatencies.begin(), WriteLatencies.end());
std::vector<MCWriteLatencyEntry>::iterator WLPos = std::search(
SchedTables.WriteLatencies.begin(), SchedTables.WriteLatencies.end(),
WriteLatencies.begin(), WriteLatencies.end());
if (WLPos != SchedTables.WriteLatencies.end()) {
unsigned idx = WLPos - SchedTables.WriteLatencies.begin();
SCDesc.WriteLatencyIdx = idx;
@@ -1312,8 +1312,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
std::string::npos) {
SchedTables.WriterNames[idx + i] += std::string("_") + WriterNames[i];
}
}
else {
} else {
SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size();
llvm::append_range(SchedTables.WriteLatencies, WriteLatencies);
llvm::append_range(SchedTables.WriterNames, WriterNames);
@@ -1321,9 +1320,9 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
// ReadAdvanceEntries must remain in operand order.
SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size();
std::vector<MCReadAdvanceEntry>::iterator RAPos =
std::search(SchedTables.ReadAdvanceEntries.begin(),
SchedTables.ReadAdvanceEntries.end(),
ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
std::search(SchedTables.ReadAdvanceEntries.begin(),
SchedTables.ReadAdvanceEntries.end(),
ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
if (RAPos != SchedTables.ReadAdvanceEntries.end())
SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin();
else {
@@ -1355,8 +1354,8 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
// Emit global WriteLatencyTable.
OS << "\n// {Cycles, WriteResourceID}\n"
<< "extern const llvm::MCWriteLatencyEntry "
<< Target << "WriteLatencyTable[] = {\n"
<< "extern const llvm::MCWriteLatencyEntry " << Target
<< "WriteLatencyTable[] = {\n"
<< " { 0, 0}, // Invalid\n";
for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size();
WLIdx != WLEnd; ++WLIdx) {
@@ -1371,8 +1370,8 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
// Emit global ReadAdvanceTable.
OS << "\n// {UseIdx, WriteResourceID, Cycles}\n"
<< "extern const llvm::MCReadAdvanceEntry "
<< Target << "ReadAdvanceTable[] = {\n"
<< "extern const llvm::MCReadAdvanceEntry " << Target
<< "ReadAdvanceTable[] = {\n"
<< " {0, 0, 0}, // Invalid\n";
for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size();
RAIdx != RAEnd; ++RAIdx) {
@@ -1388,22 +1387,23 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
// Emit a SchedClass table for each processor.
for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
PE = SchedModels.procModelEnd();
PI != PE; ++PI) {
if (!PI->hasInstrSchedModel())
continue;
std::vector<MCSchedClassDesc> &SCTab =
SchedTables.ProcSchedClasses[1 + (PI - SchedModels.procModelBegin())];
SchedTables.ProcSchedClasses[1 + (PI - SchedModels.procModelBegin())];
OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup, RetireOOO,"
<< " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
OS << "static const llvm::MCSchedClassDesc "
<< PI->ModelName << "SchedClasses[] = {\n";
OS << "static const llvm::MCSchedClassDesc " << PI->ModelName
<< "SchedClasses[] = {\n";
// The first class is always invalid. We no way to distinguish it except by
// name and position.
assert(SchedModels.getSchedClass(0).Name == "NoInstrModel"
&& "invalid class not first");
assert(SchedModels.getSchedClass(0).Name == "NoInstrModel" &&
"invalid class not first");
OS << " {DBGFIELD(\"InvalidSchedClass\") "
<< MCSchedClassDesc::InvalidNumMicroOps
<< ", false, false, false, 0, 0, 0, 0, 0, 0},\n";
@@ -1414,17 +1414,15 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
OS << " {DBGFIELD(\"" << SchedClass.Name << "\") ";
if (SchedClass.Name.size() < 18)
OS.indent(18 - SchedClass.Name.size());
OS << MCDesc.NumMicroOps
<< ", " << ( MCDesc.BeginGroup ? "true" : "false" )
<< ", " << ( MCDesc.EndGroup ? "true" : "false" )
<< ", " << ( MCDesc.RetireOOO ? "true" : "false" )
<< ", " << format("%2d", MCDesc.WriteProcResIdx)
<< ", " << MCDesc.NumWriteProcResEntries
<< ", " << format("%2d", MCDesc.WriteLatencyIdx)
<< ", " << MCDesc.NumWriteLatencyEntries
<< ", " << format("%2d", MCDesc.ReadAdvanceIdx)
<< ", " << MCDesc.NumReadAdvanceEntries
<< "}, // #" << SCIdx << '\n';
OS << MCDesc.NumMicroOps << ", " << (MCDesc.BeginGroup ? "true" : "false")
<< ", " << (MCDesc.EndGroup ? "true" : "false") << ", "
<< (MCDesc.RetireOOO ? "true" : "false") << ", "
<< format("%2d", MCDesc.WriteProcResIdx) << ", "
<< MCDesc.NumWriteProcResEntries << ", "
<< format("%2d", MCDesc.WriteLatencyIdx) << ", "
<< MCDesc.NumWriteLatencyEntries << ", "
<< format("%2d", MCDesc.ReadAdvanceIdx) << ", "
<< MCDesc.NumReadAdvanceEntries << "}, // #" << SCIdx << '\n';
}
OS << "}; // " << PI->ModelName << "SchedClasses\n";
}
@@ -1439,9 +1437,10 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
// Emit processor resource table.
if (PM.hasInstrSchedModel())
EmitProcessorResources(PM, OS);
else if(!PM.ProcResourceDefs.empty())
PrintFatalError(PM.ModelDef->getLoc(), "SchedMachineModel defines "
"ProcResources without defining WriteRes SchedWriteRes");
else if (!PM.ProcResourceDefs.empty())
PrintFatalError(PM.ModelDef->getLoc(),
"SchedMachineModel defines "
"ProcResources without defining WriteRes SchedWriteRes");
// Begin processor itinerary properties
OS << "\n";
@@ -1454,13 +1453,13 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
EmitProcessorProp(OS, PM.ModelDef, "MispredictPenalty", ',');
bool PostRAScheduler =
(PM.ModelDef ? PM.ModelDef->getValueAsBit("PostRAScheduler") : false);
(PM.ModelDef ? PM.ModelDef->getValueAsBit("PostRAScheduler") : false);
OS << " " << (PostRAScheduler ? "true" : "false") << ", // "
OS << " " << (PostRAScheduler ? "true" : "false") << ", // "
<< "PostRAScheduler\n";
bool CompleteModel =
(PM.ModelDef ? PM.ModelDef->getValueAsBit("CompleteModel") : false);
(PM.ModelDef ? PM.ModelDef->getValueAsBit("CompleteModel") : false);
OS << " " << (CompleteModel ? "true" : "false") << ", // "
<< "CompleteModel\n";
@@ -1473,11 +1472,14 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
OS << " " << PM.Index << ", // Processor ID\n";
if (PM.hasInstrSchedModel())
OS << " " << PM.ModelName << "ProcResources" << ",\n"
<< " " << PM.ModelName << "SchedClasses" << ",\n"
<< " " << PM.ProcResourceDefs.size()+1 << ",\n"
<< " " << (SchedModels.schedClassEnd()
- SchedModels.schedClassBegin()) << ",\n";
OS << " " << PM.ModelName << "ProcResources"
<< ",\n"
<< " " << PM.ModelName << "SchedClasses"
<< ",\n"
<< " " << PM.ProcResourceDefs.size() + 1 << ",\n"
<< " "
<< (SchedModels.schedClassEnd() - SchedModels.schedClassBegin())
<< ",\n";
else
OS << " nullptr, nullptr, 0, 0,"
<< " // No instruction-level machine model.\n";
@@ -1669,8 +1671,8 @@ void SubtargetEmitter::emitSchedModelHelpersImpl(
// Construct a switch statement where the condition is a check on the
// scheduling class identifier. There is a `case` for every variant class
// defined by the processor models of this target.
// Each `case` implements a number of rules to resolve (i.e. to transition from)
// a variant scheduling class to another scheduling class. Rules are
// Each `case` implements a number of rules to resolve (i.e. to transition
// from) a variant scheduling class to another scheduling class. Rules are
// described by instances of CodeGenSchedTransition. Note that transitions may
// not be valid for all processors.
OS << " switch (SchedClass) {\n";
@@ -1781,8 +1783,8 @@ void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName,
OS << "unsigned " << ClassName << "::getHwMode() const {\n";
for (unsigned M = 1, NumModes = CGH.getNumModeIds(); M != NumModes; ++M) {
const HwMode &HM = CGH.getMode(M);
OS << " if (checkFeatures(\"" << HM.Features
<< "\")) return " << M << ";\n";
OS << " if (checkFeatures(\"" << HM.Features << "\")) return " << M
<< ";\n";
}
OS << " return 0;\n}\n";
}
@@ -1808,8 +1810,8 @@ void SubtargetEmitter::emitGetMacroFusions(const std::string &ClassName,
// Produces a subtarget specific function for parsing
// the subtarget features string.
void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) {
std::vector<Record*> Features =
Records.getAllDerivedDefinitions("SubtargetFeature");
std::vector<Record *> Features =
Records.getAllDerivedDefinitions("SubtargetFeature");
llvm::sort(Features, LessRecord());
OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
@@ -1836,15 +1838,12 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) {
StringRef Value = R->getValueAsString("Value");
StringRef FieldName = R->getValueAsString("FieldName");
if (Value=="true" || Value=="false")
OS << " if (Bits[" << Target << "::"
<< Instance << "]) "
<< FieldName << " = " << Value << ";\n";
if (Value == "true" || Value == "false")
OS << " if (Bits[" << Target << "::" << Instance << "]) " << FieldName
<< " = " << Value << ";\n";
else
OS << " if (Bits[" << Target << "::"
<< Instance << "] && "
<< FieldName << " < " << Value << ") "
<< FieldName << " = " << Value << ";\n";
OS << " if (Bits[" << Target << "::" << Instance << "] && " << FieldName
<< " < " << Value << ") " << FieldName << " = " << Value << ";\n";
}
OS << "}\n";
@@ -1955,15 +1954,15 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << Target << "SubTypeKV, ";
else
OS << "std::nullopt, ";
OS << '\n'; OS.indent(22);
OS << Target << "WriteProcResTable, "
<< Target << "WriteLatencyTable, "
OS << '\n';
OS.indent(22);
OS << Target << "WriteProcResTable, " << Target << "WriteLatencyTable, "
<< Target << "ReadAdvanceTable, ";
OS << '\n'; OS.indent(22);
OS << '\n';
OS.indent(22);
if (SchedModels.hasItineraries()) {
OS << Target << "Stages, "
<< Target << "OperandCycles, "
<< Target << "ForwardingPaths";
OS << Target << "Stages, " << Target << "OperandCycles, " << Target
<< "ForwardingPaths";
} else
OS << "nullptr, nullptr, nullptr";
OS << ");\n}\n\n";
@@ -2027,12 +2026,12 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "namespace llvm {\n";
OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
OS << "extern const llvm::SubtargetSubTypeKV " << Target << "SubTypeKV[];\n";
OS << "extern const llvm::MCWriteProcResEntry "
<< Target << "WriteProcResTable[];\n";
OS << "extern const llvm::MCWriteLatencyEntry "
<< Target << "WriteLatencyTable[];\n";
OS << "extern const llvm::MCReadAdvanceEntry "
<< Target << "ReadAdvanceTable[];\n";
OS << "extern const llvm::MCWriteProcResEntry " << Target
<< "WriteProcResTable[];\n";
OS << "extern const llvm::MCWriteLatencyEntry " << Target
<< "WriteLatencyTable[];\n";
OS << "extern const llvm::MCReadAdvanceEntry " << Target
<< "ReadAdvanceTable[];\n";
if (SchedModels.hasItineraries()) {
OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
@@ -2051,15 +2050,15 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "ArrayRef(" << Target << "SubTypeKV, " << NumProcs << "), ";
else
OS << "std::nullopt, ";
OS << '\n'; OS.indent(24);
OS << Target << "WriteProcResTable, "
<< Target << "WriteLatencyTable, "
OS << '\n';
OS.indent(24);
OS << Target << "WriteProcResTable, " << Target << "WriteLatencyTable, "
<< Target << "ReadAdvanceTable, ";
OS << '\n'; OS.indent(24);
OS << '\n';
OS.indent(24);
if (SchedModels.hasItineraries()) {
OS << Target << "Stages, "
<< Target << "OperandCycles, "
<< Target << "ForwardingPaths";
OS << Target << "Stages, " << Target << "OperandCycles, " << Target
<< "ForwardingPaths";
} else
OS << "nullptr, nullptr, nullptr";
OS << ") {}\n\n";

View File

@@ -81,7 +81,7 @@ void SubtargetFeatureInfo::emitNameTable(
uint64_t IndexUB = 0;
for (const auto &SF : SubtargetFeatures)
if (IndexUB <= SF.second.Index)
IndexUB = SF.second.Index+1;
IndexUB = SF.second.Index + 1;
std::vector<std::string> Names;
if (IndexUB > 0)

View File

@@ -18,7 +18,8 @@
namespace llvm {
struct SubtargetFeatureInfo;
using SubtargetFeatureInfoMap = std::map<Record *, SubtargetFeatureInfo, LessRecordByID>;
using SubtargetFeatureInfoMap =
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>;
/// Helper class for storing information on a subtarget feature which
/// participates in instruction matching.

View File

@@ -46,7 +46,6 @@
// backends, this means that the EmitFoo function is the only thing not in
// the anonymous namespace.
// FIXME: Reorganize TableGen so that build dependencies can be more
// accurately expressed. Currently, touching any of the emitters (or
// anything that they transitively depend on) causes everything dependent
@@ -57,7 +56,6 @@
// TableGen binary with as few dependencies as possible on the rest of
// LLVM.
namespace llvm {
class raw_ostream;

View File

@@ -15,7 +15,9 @@
using namespace llvm;
const char *llvm::getMinimalTypeForRange(uint64_t Range, unsigned MaxSize LLVM_ATTRIBUTE_UNUSED) {
const char *
llvm::getMinimalTypeForRange(uint64_t Range,
unsigned MaxSize LLVM_ATTRIBUTE_UNUSED) {
// TODO: The original callers only used 32 and 64 so these are the only
// values permitted. Rather than widen the supported values we should
// allow 64 for the callers that currently use 32 and remove the

View File

@@ -16,6 +16,6 @@ namespace llvm {
/// MaxSize indicates the largest size of integer to consider (in bits) and only
/// supports values of at least 32.
const char *getMinimalTypeForRange(uint64_t Range, unsigned MaxSize = 64);
}
} // namespace llvm
#endif

View File

@@ -63,7 +63,8 @@ void emitWebAssemblyDisassemblerTables(
// should be the canonical one. This determines which variant gets
// printed in a disassembly. We want e.g. "call" not "i32.call", and
// "end" when we don't know if its "end_loop" or "end_block" etc.
bool IsCanonicalExisting = CGIP.second->TheDef->getValueAsBit("IsCanonical");
bool IsCanonicalExisting =
CGIP.second->TheDef->getValueAsBit("IsCanonical");
// We already have one marked explicitly as canonical, so keep it.
if (IsCanonicalExisting)
continue;
@@ -126,7 +127,8 @@ void emitWebAssemblyDisassemblerTables(
++J) {
size_t K = 0;
for (; K < CurOperandList.size(); ++K) {
if (OperandTable[J + K] != CurOperandList[K]) break;
if (OperandTable[J + K] != CurOperandList[K])
break;
}
if (K == CurOperandList.size()) {
OperandStart = J;

View File

@@ -83,7 +83,8 @@ void X86CompressEVEXTablesEmitter::printTable(const std::vector<Entry> &Table,
void X86CompressEVEXTablesEmitter::printCheckPredicate(
const PredicateInstMap &PredicateInsts, raw_ostream &OS) {
OS << "static bool checkPredicate(unsigned Opc, const X86Subtarget *Subtarget) {\n"
OS << "static bool checkPredicate(unsigned Opc, const X86Subtarget "
"*Subtarget) {\n"
<< " switch (Opc) {\n"
<< " default: return true;\n";
for (const auto &[Key, Val] : PredicateInsts) {
@@ -207,9 +208,9 @@ void X86CompressEVEXTablesEmitter::run(raw_ostream &OS) {
NewInst = &TempInst;
}
} else {
// For each pre-compression instruction look for a match in the appropriate
// vector (instructions with the same opcode) using function object
// IsMatch.
// For each pre-compression instruction look for a match in the
// appropriate vector (instructions with the same opcode) using function
// object IsMatch.
auto Match = llvm::find_if(CompressedInsts[Opcode], IsMatch(Inst));
if (Match != CompressedInsts[Opcode].end())
NewInst = *Match;
@@ -225,7 +226,7 @@ void X86CompressEVEXTablesEmitter::run(raw_ostream &OS) {
return Name == "HasAVXNECONVERT" || Name == "HasAVXVNNI" ||
Name == "HasAVXIFMA";
});
if(It!= Predicates.end())
if (It != Predicates.end())
PredicateInsts[*It].push_back(NewInst);
}

View File

@@ -49,9 +49,7 @@ struct OpcodeDecision {
struct ContextDecision {
OpcodeDecision opcodeDecisions[llvm::X86Disassembler::IC_max];
ContextDecision() {
memset(opcodeDecisions, 0, sizeof(opcodeDecisions));
}
ContextDecision() { memset(opcodeDecisions, 0, sizeof(opcodeDecisions)); }
};
#endif

View File

@@ -41,8 +41,9 @@ static inline const char *stringForContext(InstructionContext insnContext) {
break;
#define ENUM_ENTRY_K_B(n, r, d) \
ENUM_ENTRY(n, r, d) \
ENUM_ENTRY(n##_K_B, r, d) ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) \
ENUM_ENTRY(n##_B, r, d) ENUM_ENTRY(n##_KZ_B, r, d)
ENUM_ENTRY(n##_K_B, r, d) \
ENUM_ENTRY(n##_KZ, r, d) \
ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d) ENUM_ENTRY(n##_KZ_B, r, d)
INSTRUCTION_CONTEXTS
#undef ENUM_ENTRY
#undef ENUM_ENTRY_K_B
@@ -595,8 +596,8 @@ static inline bool outranks(InstructionContext upper,
#define ENUM_ENTRY_K_B(n, r, d) \
ENUM_ENTRY(n, r, d) \
ENUM_ENTRY(n##_K_B, r, d) \
ENUM_ENTRY(n##_KZ_B, r, d) ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) \
ENUM_ENTRY(n##_B, r, d)
ENUM_ENTRY(n##_KZ_B, r, d) \
ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)
static int ranks[IC_max] = {INSTRUCTION_CONTEXTS};
#undef ENUM_ENTRY
#undef ENUM_ENTRY_K_B
@@ -822,7 +823,8 @@ void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
}
i2--;
o2.indent(i2) << "}};" << "\n";
o2.indent(i2) << "}};"
<< "\n";
}
void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
@@ -859,7 +861,8 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
}
o << " },\n";
}
o << "};" << "\n\n";
o << "};"
<< "\n\n";
o.indent(i * 2) << "static const struct InstructionSpecifier ";
o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n";
@@ -885,7 +888,8 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
}
i--;
o.indent(i * 2) << "};" << "\n";
o.indent(i * 2) << "};"
<< "\n";
}
void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
@@ -1004,7 +1008,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
}
i--;
o.indent(i * 2) << "};" << "\n";
o.indent(i * 2) << "};"
<< "\n";
}
void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2,

View File

@@ -91,8 +91,8 @@ private:
/// @param ModRMTableNum - next table number for adding to ModRMTable.
/// @param decision - The ModR/M decision to emit. This decision has 256
/// entries - emitModRMDecision decides how to compact it.
void emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
void emitModRMDecision(raw_ostream &o1, raw_ostream &o2, unsigned &i1,
unsigned &i2, unsigned &ModRMTableNum,
ModRMDecision &decision) const;
/// emitOpcodeDecision - Emits an OpcodeDecision and all its subsidiary ModR/M
@@ -119,8 +119,8 @@ private:
/// @param ModRMTableNum - next table number for adding to ModRMTable.
/// @param decision - The OpcodeDecision to emit along with its subsidiary
/// structures.
void emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
void emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2, unsigned &i1,
unsigned &i2, unsigned &ModRMTableNum,
OpcodeDecision &decision) const;
/// emitContextDecision - Emits a ContextDecision and all its subsidiary
@@ -153,9 +153,9 @@ private:
/// @param decision - The ContextDecision to emit along with its subsidiary
/// structures.
/// @param name - The name for the ContextDecision.
void emitContextDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
ContextDecision &decision, const char* name) const;
void emitContextDecision(raw_ostream &o1, raw_ostream &o2, unsigned &i1,
unsigned &i2, unsigned &ModRMTableNum,
ContextDecision &decision, const char *name) const;
/// emitInstructionInfo - Prints the instruction specifier table, which has
/// one entry for each instruction, and contains name and operand
@@ -200,7 +200,8 @@ private:
/// IC is the context corresponding to the mask 0x00, and there are 256
/// possible masks.
///
/// @param o - The output stream to which the context table should be written.
/// @param o - The output stream to which the context table should be
/// written.
/// @param i - The indent level for use with the stream.
void emitContextTable(raw_ostream &o, uint32_t &i) const;
@@ -213,9 +214,8 @@ private:
/// @param i1 - The indent level to use with stream o1.
/// @param i2 - The indent level to use with stream o2.
/// @param ModRMTableNum - next table number for adding to ModRMTable.
void emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2,
unsigned &ModRMTableNum) const;
void emitContextDecisions(raw_ostream &o1, raw_ostream &o2, unsigned &i1,
unsigned &i2, unsigned &ModRMTableNum) const;
/// setTableFields - Uses a ModRMFilter to set the appropriate entries in a
/// ModRMDecision to refer to a particular instruction ID.
@@ -224,10 +224,9 @@ private:
/// @param filter - The filter to use in deciding which entries to populate.
/// @param uid - The unique ID to set matching entries to.
/// @param opcode - The opcode of the instruction, for error reporting.
void setTableFields(ModRMDecision &decision,
const ModRMFilter &filter,
InstrUID uid,
uint8_t opcode);
void setTableFields(ModRMDecision &decision, const ModRMFilter &filter,
InstrUID uid, uint8_t opcode);
public:
/// Constructor - Allocates space for the class decisions and clears them.
DisassemblerTables();
@@ -247,7 +246,8 @@ public:
/// @param insnContext - The context to use (IC, IC_64BIT, etc.)
/// @param opcode - The last byte of the opcode (not counting any escape
/// or extended opcodes).
/// @param filter - The ModRMFilter that decides which ModR/M byte values
/// @param filter - The ModRMFilter that decides which ModR/M byte
/// values
/// correspond to the desired instruction.
/// @param uid - The unique ID of the instruction.
/// @param is32bit - Instructon is only 32-bit
@@ -255,23 +255,17 @@ public:
/// @param ignoresVEX_L - Instruction ignores VEX.L
/// @param ignoresVEX_W - Instruction ignores VEX.W
/// @param AddrSize - Instructions address size 16/32/64. 0 is unspecified
void setTableFields(OpcodeType type,
InstructionContext insnContext,
uint8_t opcode,
const ModRMFilter &filter,
InstrUID uid,
bool is32bit,
bool noPrefix,
bool ignoresVEX_L,
bool ignoresVEX_W,
unsigned AddrSize);
void setTableFields(OpcodeType type, InstructionContext insnContext,
uint8_t opcode, const ModRMFilter &filter, InstrUID uid,
bool is32bit, bool noPrefix, bool ignoresVEX_L,
bool ignoresVEX_W, unsigned AddrSize);
/// specForUID - Returns the instruction specifier for a given unique
/// instruction ID. Used when resolving collisions.
///
/// @param uid - The unique ID of the instruction.
/// @return - A reference to the instruction specifier.
InstructionSpecifier& specForUID(InstrUID uid) {
InstructionSpecifier &specForUID(InstrUID uid) {
if (uid >= InstructionSpecifiers.size())
InstructionSpecifiers.resize(uid + 1);
@@ -282,9 +276,7 @@ public:
// from any instructions added to the tables.
// @return - true if there were; false otherwise.
bool hasConflicts() {
return HasConflicts;
}
bool hasConflicts() { return HasConflicts; }
};
} // namespace X86Disassembler

View File

@@ -10,14 +10,14 @@
using namespace llvm::X86Disassembler;
void ModRMFilter::anchor() { }
void ModRMFilter::anchor() {}
void DumbFilter::anchor() { }
void DumbFilter::anchor() {}
void ModFilter::anchor() { }
void ModFilter::anchor() {}
void ExtendedFilter::anchor() { }
void ExtendedFilter::anchor() {}
void ExtendedRMFilter::anchor() { }
void ExtendedRMFilter::anchor() {}
void ExactFilter::anchor() { }
void ExactFilter::anchor() {}

View File

@@ -27,9 +27,10 @@ namespace X86Disassembler {
/// ModR/M bytes.
class ModRMFilter {
virtual void anchor();
public:
/// Destructor - Override as necessary.
virtual ~ModRMFilter() { }
virtual ~ModRMFilter() {}
/// isDumb - Indicates whether this filter returns the same value for
/// any value of the ModR/M byte.
@@ -50,14 +51,11 @@ public:
/// for operands.
class DumbFilter : public ModRMFilter {
void anchor() override;
public:
bool isDumb() const override {
return true;
}
bool accepts(uint8_t modRM) const override {
return true;
}
public:
bool isDumb() const override { return true; }
bool accepts(uint8_t modRM) const override { return true; }
};
/// ModFilter - Filters based on the mod bits [bits 7-6] of the ModR/M byte.
@@ -66,6 +64,7 @@ public:
class ModFilter : public ModRMFilter {
void anchor() override;
bool R;
public:
/// Constructor
///
@@ -86,6 +85,7 @@ class ExtendedFilter : public ModRMFilter {
void anchor() override;
bool R;
uint8_t NNN;
public:
/// Constructor
///
@@ -95,9 +95,9 @@ public:
ExtendedFilter(bool r, uint8_t nnn) : R(r), NNN(nnn) {}
bool accepts(uint8_t modRM) const override {
return (((R && ((modRM & 0xc0) == 0xc0)) ||
(!R && ((modRM & 0xc0) != 0xc0))) &&
(((modRM & 0x38) >> 3) == NNN));
return (
((R && ((modRM & 0xc0) == 0xc0)) || (!R && ((modRM & 0xc0) != 0xc0))) &&
(((modRM & 0x38) >> 3) == NNN));
}
};
@@ -107,6 +107,7 @@ class ExtendedRMFilter : public ModRMFilter {
void anchor() override;
bool R;
uint8_t NNN;
public:
/// Constructor
///
@@ -116,8 +117,7 @@ public:
ExtendedRMFilter(bool r, uint8_t nnn) : R(r), NNN(nnn) {}
bool accepts(uint8_t modRM) const override {
return ((R && ((modRM & 0xc0) == 0xc0)) &&
((modRM & 0x7) == NNN));
return ((R && ((modRM & 0xc0) == 0xc0)) && ((modRM & 0x7) == NNN));
}
};
/// ExactFilter - The occasional extended opcode (such as VMCALL or MONITOR)
@@ -125,15 +125,14 @@ public:
class ExactFilter : public ModRMFilter {
void anchor() override;
uint8_t ModRM;
public:
/// Constructor
///
/// \param modRM The required value of the full ModR/M byte.
ExactFilter(uint8_t modRM) : ModRM(modRM) {}
bool accepts(uint8_t modRM) const override {
return (ModRM == modRM);
}
bool accepts(uint8_t modRM) const override { return (ModRM == modRM); }
};
} // namespace X86Disassembler

View File

@@ -1,4 +1,4 @@
//===- X86RecognizableInstr.cpp - Disassembler instruction spec --*- C++ -*-===//
//===- X86RecognizableInstr.cpp - Disassembler instruction spec -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@@ -1,4 +1,4 @@
//===- X86RecognizableInstr.h - Disassembler instruction spec ----*- C++ -*-===//
//===- X86RecognizableInstr.h - Disassembler instruction spec ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.