[llvm-commits] CVS: llvm/utils/TableGen/AsmWriterEmitter.cpp

Chris Lattner lattner at cs.uiuc.edu
Sat Jan 22 11:22:38 PST 2005



Changes in directory llvm/utils/TableGen:

AsmWriterEmitter.cpp updated: 1.15 -> 1.16
---
Log message:

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!



---
Diffs of the changes:  (+62 -20)

 AsmWriterEmitter.cpp |   82 ++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 62 insertions(+), 20 deletions(-)


Index: llvm/utils/TableGen/AsmWriterEmitter.cpp
diff -u llvm/utils/TableGen/AsmWriterEmitter.cpp:1.15 llvm/utils/TableGen/AsmWriterEmitter.cpp:1.16
--- llvm/utils/TableGen/AsmWriterEmitter.cpp:1.15	Sat Jan 22 12:50:10 2005
+++ llvm/utils/TableGen/AsmWriterEmitter.cpp	Sat Jan 22 13:22:23 2005
@@ -64,10 +64,10 @@
     
     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 @@
   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 @@
   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) {
+    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 @@
   "/// 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 @@
     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<const CodeGenInstruction*, AsmWriterInst*> 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<const CodeGenInstruction*> 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);






More information about the llvm-commits mailing list