diff options
author | Chris Lattner <sabre@nondot.org> | 2005-01-22 18:38:13 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2005-01-22 18:38:13 +0000 |
commit | 870c016934bacf43995d89531b166ae095ee3675 (patch) | |
tree | 70105d4b18d4446b27e5b42f4095a6dca0edee25 /utils/TableGen/AsmWriterEmitter.cpp | |
parent | f11ad9ef46d67b5f52f7c410d5c4451e81d154e4 (diff) | |
download | llvm-870c016934bacf43995d89531b166ae095ee3675.tar.gz llvm-870c016934bacf43995d89531b166ae095ee3675.tar.bz2 llvm-870c016934bacf43995d89531b166ae095ee3675.tar.xz |
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
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19755 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen/AsmWriterEmitter.cpp')
-rw-r--r-- | utils/TableGen/AsmWriterEmitter.cpp | 107 |
1 files changed, 97 insertions, 10 deletions
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 5563061ba2..821032df95 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -48,6 +48,12 @@ namespace { MVT::ValueType VT) : OperandType(isMachineInstrOperand), 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; }; @@ -56,10 +62,12 @@ namespace { const CodeGenInstruction *CGI; AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant); - void EmitCode(std::ostream &OS) const { - for (unsigned i = 0, e = Operands.size(); i != e; ++i) - Operands[i].EmitCode(OS); - } + + /// 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 MatchesAllButOneString(const AsmWriterInst &Other) const; + private: void AddLiteralString(const std::string &Str) { // 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"); } +/// 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) { EmitSourceFileHeader("Assembly Writer Source Fragment", O); @@ -202,13 +289,13 @@ void AsmWriterEmitter::run(std::ostream &O) { if (!I->second.AsmString.empty()) Instructions.push_back(AsmWriterInst(I->second, Variant)); - for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { - O << " case " << Namespace << "::" - << Instructions[i].CGI->TheDef->getName() << ": "; - Instructions[i].EmitCode(O); - O << " break;\n"; - } + // Because this is a vector we want to emit from the end. Reverse all of the + // elements in the vector. + std::reverse(Instructions.begin(), Instructions.end()); + while (!Instructions.empty()) + EmitInstructions(Instructions, O); + O << " }\n" " return true;\n" "}\n"; |