forked from OSchip/llvm-project
Implement factoring of instruction pattern strings. In particular, instead of
emitting code like this: case PPC::ADD: O << "add "; printOperand(MI, 0, MVT::i64); O << ", "; prin tOperand(MI, 1, MVT::i64); O << ", "; printOperand(MI, 2, MVT::i64); O << '\n '; break; case PPC::ADDC: O << "addc "; printOperand(MI, 0, MVT::i64); O << ", "; pr intOperand(MI, 1, MVT::i64); O << ", "; printOperand(MI, 2, MVT::i64); O << ' \n'; break; case PPC::ADDE: O << "adde "; printOperand(MI, 0, MVT::i64); O << ", "; pr intOperand(MI, 1, MVT::i64); O << ", "; printOperand(MI, 2, MVT::i64); O << ' \n'; break; ... Emit code like this: case PPC::ADD: case PPC::ADDC: case PPC::ADDE: ... switch (MI->getOpcode()) { case PPC::ADD: O << "add "; break; case PPC::ADDC: O << "addc "; break; case PPC::ADDE: O << "adde "; break; ... } printOperand(MI, 0, MVT::i64); O << ", "; printOperand(MI, 1, MVT::i64); O << ", "; printOperand(MI, 2, MVT::i64); O << "\n"; break; This shrinks the PPC asm writer from 24785->15205 bytes (even though the new asmwriter has much more whitespace than the old one), and the X86 printers shrink quite a bit too. The important implication of this is that GCC no longer hits swap when building the PPC backend in optimized mode. Thus this fixes PR448. -Chris llvm-svn: 19755
This commit is contained in:
parent
b6f5d9a82a
commit
9ceb7c8f23
|
@ -48,6 +48,12 @@ namespace {
|
||||||
MVT::ValueType VT) : OperandType(isMachineInstrOperand),
|
MVT::ValueType VT) : OperandType(isMachineInstrOperand),
|
||||||
Str(Printer), MIOpNo(OpNo), OpVT(VT){}
|
Str(Printer), MIOpNo(OpNo), OpVT(VT){}
|
||||||
|
|
||||||
|
bool operator!=(const AsmWriterOperand &Other) const {
|
||||||
|
if (OperandType != Other.OperandType || Str != Other.Str) return true;
|
||||||
|
if (OperandType == isMachineInstrOperand)
|
||||||
|
return MIOpNo != Other.MIOpNo || OpVT != Other.OpVT;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
void EmitCode(std::ostream &OS) const;
|
void EmitCode(std::ostream &OS) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,10 +62,12 @@ namespace {
|
||||||
const CodeGenInstruction *CGI;
|
const CodeGenInstruction *CGI;
|
||||||
|
|
||||||
AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant);
|
AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant);
|
||||||
void EmitCode(std::ostream &OS) const {
|
|
||||||
for (unsigned i = 0, e = Operands.size(); i != e; ++i)
|
/// MatchesAllButOneString - If this instruction is exactly identical to the
|
||||||
Operands[i].EmitCode(OS);
|
/// specified instruction except for one differing literal string, return
|
||||||
}
|
/// the operand number of the literal string. Otherwise return ~0.
|
||||||
|
unsigned MatchesAllButOneString(const AsmWriterInst &Other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddLiteralString(const std::string &Str) {
|
void AddLiteralString(const std::string &Str) {
|
||||||
// If the last operand was already a literal text string, append this to
|
// If the last operand was already a literal text string, append this to
|
||||||
|
@ -174,6 +182,85 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
|
||||||
AddLiteralString("\\n");
|
AddLiteralString("\\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// MatchesAllButOneString - If this instruction is exactly identical to the
|
||||||
|
/// specified instruction except for one differing literal string, return
|
||||||
|
/// the operand number of the literal string. Otherwise return ~0.
|
||||||
|
unsigned AsmWriterInst::MatchesAllButOneString(const AsmWriterInst &Other)const{
|
||||||
|
if (Operands.size() != Other.Operands.size()) return ~0;
|
||||||
|
|
||||||
|
unsigned MismatchOperand = ~0U;
|
||||||
|
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
|
||||||
|
if (Operands[i].OperandType != Other.Operands[i].OperandType)
|
||||||
|
return ~0U;
|
||||||
|
|
||||||
|
if (Operands[i] != Other.Operands[i])
|
||||||
|
if (Operands[i].OperandType == AsmWriterOperand::isMachineInstrOperand ||
|
||||||
|
MismatchOperand != ~0U)
|
||||||
|
return ~0U;
|
||||||
|
else
|
||||||
|
MismatchOperand = i;
|
||||||
|
}
|
||||||
|
return MismatchOperand;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
std::ostream &O) {
|
||||||
|
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].MatchesAllButOneString(FirstInst);
|
||||||
|
if (DiffOp != ~0U) {
|
||||||
|
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) {
|
||||||
|
SimilarInsts.push_back(Insts[i-1]);
|
||||||
|
Insts.erase(Insts.begin()+i-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Namespace = FirstInst.CGI->Namespace;
|
||||||
|
|
||||||
|
O << " case " << Namespace << "::"
|
||||||
|
<< FirstInst.CGI->TheDef->getName() << ":\n";
|
||||||
|
for (unsigned i = 0, e = SimilarInsts.size(); i != e; ++i)
|
||||||
|
O << " case " << Namespace << "::"
|
||||||
|
<< SimilarInsts[i].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.
|
||||||
|
O << " ";
|
||||||
|
FirstInst.Operands[i].EmitCode(O);
|
||||||
|
} else {
|
||||||
|
// If this is the operand that varies between all of the instructions,
|
||||||
|
// emit a switch for just this operand now.
|
||||||
|
O << " switch (MI->getOpcode()) {\n";
|
||||||
|
O << " case " << Namespace << "::"
|
||||||
|
<< FirstInst.CGI->TheDef->getName() << ": ";
|
||||||
|
FirstInst.Operands[i].EmitCode(O);
|
||||||
|
O << "break;\n";
|
||||||
|
for (unsigned si = 0, e = SimilarInsts.size(); si != e; ++si) {
|
||||||
|
O << " case " << Namespace << "::"
|
||||||
|
<< SimilarInsts[si].CGI->TheDef->getName() << ": ";
|
||||||
|
SimilarInsts[si].Operands[i].EmitCode(O);
|
||||||
|
O << "break;\n";
|
||||||
|
}
|
||||||
|
O << " }";
|
||||||
|
}
|
||||||
|
O << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
O << " break;\n";
|
||||||
|
}
|
||||||
|
|
||||||
void AsmWriterEmitter::run(std::ostream &O) {
|
void AsmWriterEmitter::run(std::ostream &O) {
|
||||||
EmitSourceFileHeader("Assembly Writer Source Fragment", O);
|
EmitSourceFileHeader("Assembly Writer Source Fragment", O);
|
||||||
|
@ -202,13 +289,13 @@ void AsmWriterEmitter::run(std::ostream &O) {
|
||||||
if (!I->second.AsmString.empty())
|
if (!I->second.AsmString.empty())
|
||||||
Instructions.push_back(AsmWriterInst(I->second, Variant));
|
Instructions.push_back(AsmWriterInst(I->second, Variant));
|
||||||
|
|
||||||
for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
|
// Because this is a vector we want to emit from the end. Reverse all of the
|
||||||
O << " case " << Namespace << "::"
|
// elements in the vector.
|
||||||
<< Instructions[i].CGI->TheDef->getName() << ": ";
|
std::reverse(Instructions.begin(), Instructions.end());
|
||||||
Instructions[i].EmitCode(O);
|
|
||||||
O << " break;\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
while (!Instructions.empty())
|
||||||
|
EmitInstructions(Instructions, O);
|
||||||
|
|
||||||
O << " }\n"
|
O << " }\n"
|
||||||
" return true;\n"
|
" return true;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
Loading…
Reference in New Issue