[TableGen] In AsmWriterEmitter unique command search, rather than storing a mapping from instruction to unique command, instead store a list of which instructions each unique command corresponds to.

This simplifies the complexity of the code that tries to find further operands to merge into the unique command.

llvm-svn: 258656
This commit is contained in:
Craig Topper 2016-01-24 07:13:28 +00:00
parent dcd6c79d55
commit 5dd7a2cc24
1 changed files with 32 additions and 43 deletions

View File

@ -49,7 +49,7 @@ private:
void EmitPrintAliasInstruction(raw_ostream &O);
void FindUniqueOperandCommands(std::vector<std::string> &UOC,
std::vector<unsigned> &InstIdxs,
std::vector<std::vector<unsigned>> &InstIdxs,
std::vector<unsigned> &InstOpsUsed,
bool PassSubtarget) const;
};
@ -136,10 +136,9 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
void AsmWriterEmitter::
FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
std::vector<unsigned> &InstIdxs,
std::vector<std::vector<unsigned>> &InstIdxs,
std::vector<unsigned> &InstOpsUsed,
bool PassSubtarget) const {
InstIdxs.assign(Instructions.size(), ~0U);
// This vector parallels UniqueOperandCommands, keeping track of which
// instructions each case are used for. It is a comma separated string of
@ -161,13 +160,14 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
UniqueOperandCommands.end(), Command);
if (I != UniqueOperandCommands.end()) {
size_t idx = I - UniqueOperandCommands.begin();
InstIdxs[i] = idx;
InstrsForCase[idx] += ", ";
InstrsForCase[idx] += Inst.CGI->TheDef->getName();
InstIdxs[idx].push_back(i);
} else {
InstIdxs[i] = UniqueOperandCommands.size();
UniqueOperandCommands.push_back(std::move(Command));
InstrsForCase.push_back(Inst.CGI->TheDef->getName());
InstIdxs.emplace_back();
InstIdxs.back().push_back(i);
// This command matches one operand so far.
InstOpsUsed.push_back(1);
@ -177,38 +177,28 @@ 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 (unsigned CommandIdx = 0, e = UniqueOperandCommands.size();
for (size_t CommandIdx = 0, e = UniqueOperandCommands.size();
CommandIdx != e; ++CommandIdx) {
for (unsigned Op = 1; ; ++Op) {
// Scan for the first instruction in the set.
auto NIT = std::find(InstIdxs.begin(), InstIdxs.end(), CommandIdx);
if (NIT == InstIdxs.end()) break; // No commonality.
const auto &Idxs = InstIdxs[CommandIdx];
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
// into this command.
const AsmWriterInst &FirstInst = Instructions[NIT-InstIdxs.begin()];
if (FirstInst.Operands.size() == Op)
break;
// Otherwise, scan to see if all of the other instructions in this command
// set share the operand.
bool AllSame = true;
for (NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx);
NIT != InstIdxs.end();
NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx)) {
// Okay, found another instruction in this command set. If the operand
// matches, we're ok, otherwise bail out.
const AsmWriterInst &OtherInst = Instructions[NIT-InstIdxs.begin()];
if (OtherInst.Operands.size() == Op ||
OtherInst.Operands[Op] != FirstInst.Operands[Op]) {
AllSame = false;
break;
}
}
if (!AllSame) break;
if (std::any_of(Idxs.begin()+1, Idxs.end(),
[&](unsigned Idx) {
const AsmWriterInst &OtherInst = Instructions[Idx];
return OtherInst.Operands.size() == Op ||
OtherInst.Operands[Op] != FirstInst.Operands[Op];
}))
break;
// Okay, everything in this command set has the same next operand. Add it
// to UniqueOperandCommands and remember that it was consumed.
@ -328,7 +318,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
while (1) {
std::vector<std::string> UniqueOperandCommands;
std::vector<unsigned> InstIdxs;
std::vector<std::vector<unsigned>> InstIdxs;
std::vector<unsigned> NumInstOpsHandled;
FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs,
NumInstOpsHandled, PassSubtarget);
@ -348,23 +338,22 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
}
// Otherwise, we can include this in the initial lookup table. Add it in.
for (size_t i = 0, e = Instructions.size(); i != e; ++i)
if (InstIdxs[i] != ~0U)
OpcodeInfo[Instructions[i].CGIIndex] |=
(uint64_t)InstIdxs[i] << (OpcodeInfoBits-BitsLeft);
BitsLeft -= NumBits;
// Remove the info about this operand.
for (size_t i = 0, e = Instructions.size(); i != e; ++i) {
AsmWriterInst &Inst = Instructions[i];
if (!Inst.Operands.empty()) {
unsigned NumOps = NumInstOpsHandled[InstIdxs[i]];
assert(NumOps <= Inst.Operands.size() &&
"Can't remove this many ops!");
Inst.Operands.erase(Inst.Operands.begin(),
Inst.Operands.begin()+NumOps);
for (size_t i = 0, e = InstIdxs.size(); i != e; ++i) {
unsigned NumOps = NumInstOpsHandled[i];
for (unsigned Idx : InstIdxs[i]) {
OpcodeInfo[Instructions[Idx].CGIIndex] |=
(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);
}
}
}
BitsLeft -= NumBits;
// Remember the handlers for this set of operands.
TableDrivenOperandPrinters.push_back(std::move(UniqueOperandCommands));