From f876668518097413a904537ce9d249953987508c Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 22 Jan 2005 19:22:23 +0000 Subject: Implement *even more* factoring. In particular, if all of the instruction strings starts out with a constant string, we emit the string first, using a table lookup (instead of a switch statement). Because this is usually the opcode portion of the asm string, the differences between the instructions have now been greatly reduced. This allows many more case statements to be grouped together. This patch also allows instruction cases to be grouped together when the instruction patterns are exactly identical (common after the opcode string has been ripped off), and when the differing operand is a MachineInstr operand that needs to be formatted. The end result of this is a mean and lean generated AsmPrinter! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19759 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/AsmWriterEmitter.cpp | 82 ++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 20 deletions(-) (limited to 'utils/TableGen/AsmWriterEmitter.cpp') diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index ecd09630e1..327776b329 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -64,10 +64,10 @@ namespace { AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant); - /// 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; + /// 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) { @@ -183,21 +183,18 @@ 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; +/// MatchesAllButOneOp - If this instruction is exactly identical to the +/// 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 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; + if (MismatchOperand != ~0U) // Already have one mismatch? + return ~1U; else MismatchOperand = i; } @@ -215,14 +212,14 @@ static void EmitInstructions(std::vector &Insts, std::vector SimilarInsts; unsigned DifferingOperand = ~0; for (unsigned i = Insts.size(); i != 0; --i) { - unsigned DiffOp = Insts[i-1].MatchesAllButOneString(FirstInst); - if (DiffOp != ~0U) { + unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst); + if (DiffOp != ~1U) { 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) { + if (DifferingOperand == DiffOp || DiffOp == ~0U) { SimilarInsts.push_back(Insts[i-1]); Insts.erase(Insts.begin()+i-1); } @@ -278,8 +275,6 @@ void AsmWriterEmitter::run(std::ostream &O) { "/// it returns false.\n" "bool " << Target.getName() << ClassName << "::printInstruction(const MachineInstr *MI) {\n"; - O << " switch (MI->getOpcode()) {\n" - " default: return false;\n"; std::string Namespace = Target.inst_begin()->second.Namespace; @@ -290,9 +285,56 @@ void AsmWriterEmitter::run(std::ostream &O) { if (!I->second.AsmString.empty()) Instructions.push_back(AsmWriterInst(I->second, Variant)); + // If all of the instructions start with a constant string (a very very common + // occurance), emit all of the constant strings as a big table lookup instead + // of requiring a switch for them. + bool AllStartWithString = true; + + for (unsigned i = 0, e = Instructions.size(); i != e; ++i) + if (Instructions[i].Operands.empty() || + Instructions[i].Operands[0].OperandType != + AsmWriterOperand::isLiteralTextOperand) { + AllStartWithString = false; + break; + } + + if (AllStartWithString) { + // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not + // all machine instructions are necessarily being printed, so there may be + // target instructions not in this map. + std::map CGIAWIMap; + for (unsigned i = 0, e = Instructions.size(); i != e; ++i) + CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i])); + + // Emit a table of constant strings. + std::vector NumberedInstructions; + Target.getInstructionsByEnumValue(NumberedInstructions); + + O << " static const char * const OpStrs[] = {\n"; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; + if (AWI == 0) { + // Something not handled by the asmwriter printer. + O << " 0,\t// "; + } else { + O << " \"" << AWI->Operands[0].Str << "\",\t// "; + // Nuke the string from the operand list. It is now handled! + AWI->Operands.erase(AWI->Operands.begin()); + } + O << NumberedInstructions[i]->TheDef->getName() << "\n"; + } + O << " };\n\n" + << " // Emit the opcode for the instruction.\n" + << " if (const char *AsmStr = OpStrs[MI->getOpcode()])\n" + << " O << AsmStr;\n\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()); + + O << " switch (MI->getOpcode()) {\n" + " default: return false;\n"; while (!Instructions.empty()) EmitInstructions(Instructions, O); -- cgit v1.2.3