This is the final big of factoring. This shares cases in suboperand
authorChris Lattner <sabre@nondot.org>
Sat, 22 Jan 2005 20:31:17 +0000 (20:31 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 22 Jan 2005 20:31:17 +0000 (20:31 +0000)
differences, which means that identical instructions (after stripping off
the first literal string) do not run any different code at all.  On the X86,
this turns this code:

    switch (MI->getOpcode()) {
    case X86::ADC32mi: printOperand(MI, 4, MVT::i32); break;
    case X86::ADC32mi8: printOperand(MI, 4, MVT::i8); break;
    case X86::ADC32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::ADD32mi: printOperand(MI, 4, MVT::i32); break;
    case X86::ADD32mi8: printOperand(MI, 4, MVT::i8); break;
    case X86::ADD32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::AND32mi: printOperand(MI, 4, MVT::i32); break;
    case X86::AND32mi8: printOperand(MI, 4, MVT::i8); break;
    case X86::AND32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::CMP32mi: printOperand(MI, 4, MVT::i32); break;
    case X86::CMP32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::MOV32mi: printOperand(MI, 4, MVT::i32); break;
    case X86::MOV32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::OR32mi: printOperand(MI, 4, MVT::i32); break;
    case X86::OR32mi8: printOperand(MI, 4, MVT::i8); break;
    case X86::OR32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::ROL32mi: printOperand(MI, 4, MVT::i8); break;
    case X86::ROR32mi: printOperand(MI, 4, MVT::i8); break;
    case X86::SAR32mi: printOperand(MI, 4, MVT::i8); break;
    case X86::SBB32mi: printOperand(MI, 4, MVT::i32); break;
    case X86::SBB32mi8: printOperand(MI, 4, MVT::i8); break;
    case X86::SBB32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::SHL32mi: printOperand(MI, 4, MVT::i8); break;
    case X86::SHLD32mrCL: printOperand(MI, 4, MVT::i32); break;
    case X86::SHR32mi: printOperand(MI, 4, MVT::i8); break;
    case X86::SHRD32mrCL: printOperand(MI, 4, MVT::i32); break;
    case X86::SUB32mi: printOperand(MI, 4, MVT::i32); break;
    case X86::SUB32mi8: printOperand(MI, 4, MVT::i8); break;
    case X86::SUB32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::TEST32mi: printOperand(MI, 4, MVT::i32); break;
    case X86::TEST32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::TEST8mi: printOperand(MI, 4, MVT::i8); break;
    case X86::XCHG32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::XOR32mi: printOperand(MI, 4, MVT::i32); break;
    case X86::XOR32mi8: printOperand(MI, 4, MVT::i8); break;
    case X86::XOR32mr: printOperand(MI, 4, MVT::i32); break;
    }

into this:

    switch (MI->getOpcode()) {
    case X86::ADC32mi:
    case X86::ADC32mr:
    case X86::ADD32mi:
    case X86::ADD32mr:
    case X86::AND32mi:
    case X86::AND32mr:
    case X86::CMP32mi:
    case X86::CMP32mr:
    case X86::MOV32mi:
    case X86::MOV32mr:
    case X86::OR32mi:
    case X86::OR32mr:
    case X86::SBB32mi:
    case X86::SBB32mr:
    case X86::SHLD32mrCL:
    case X86::SHRD32mrCL:
    case X86::SUB32mi:
    case X86::SUB32mr:
    case X86::TEST32mi:
    case X86::TEST32mr:
    case X86::XCHG32mr:
    case X86::XOR32mi:
    case X86::XOR32mr: printOperand(MI, 4, MVT::i32); break;
    case X86::ADC32mi8:
    case X86::ADD32mi8:
    case X86::AND32mi8:
    case X86::OR32mi8:
    case X86::ROL32mi:
    case X86::ROR32mi:
    case X86::SAR32mi:
    case X86::SBB32mi8:
    case X86::SHL32mi:
    case X86::SHR32mi:
    case X86::SUB32mi8:
    case X86::TEST8mi:
    case X86::XOR32mi8: printOperand(MI, 4, MVT::i8); break;
    }

After this, the generated asmwriters look pretty much as though they were
generated by hand.  This shrinks the X86 asmwriter.inc files from 55101->39669
and 55429->39551 bytes each, and PPC from 16766->12859 bytes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19760 91177308-0d34-0410-b5e6-96231b3b80d8

utils/TableGen/AsmWriterEmitter.cpp

index 327776b32937cd6fa6ad5791649d2e560f2a54b0..6fb322e2f290c849afccc9ff5fc29410ca79b359 100644 (file)
@@ -55,6 +55,9 @@ namespace {
         return MIOpNo != Other.MIOpNo || OpVT != Other.OpVT;
       return false;
     }
+    bool operator==(const AsmWriterOperand &Other) const {
+      return !operator!=(Other);
+    }
     void EmitCode(std::ostream &OS) const;
   };
 
@@ -201,6 +204,25 @@ unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
   return MismatchOperand;
 }
 
+static void PrintCases(std::vector<std::pair<std::string,
+                       AsmWriterOperand> > &OpsToPrint, std::ostream &O) {
+  O << "    case " << OpsToPrint.back().first << ": ";
+  AsmWriterOperand TheOp = OpsToPrint.back().second;
+  OpsToPrint.pop_back();
+
+  // Check to see if any other operands are identical in this list, and if so,
+  // emit a case label for them.
+  for (unsigned i = OpsToPrint.size(); i != 0; --i)
+    if (OpsToPrint[i-1].second == TheOp) {
+      O << "\n    case " << OpsToPrint[i-1].first << ": ";
+      OpsToPrint.erase(OpsToPrint.begin()+i-1);
+    }
+
+  // Finally, emit the code.
+  TheOp.EmitCode(O);
+  O << "break;\n";
+}
+
 
 /// EmitInstructions - Emit the last instruction in the vector and any other
 /// instructions that are suitably similar to it.
@@ -242,16 +264,20 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
       // 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";
+      std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint;
+      OpsToPrint.push_back(std::make_pair(Namespace+"::"+
+                                          FirstInst.CGI->TheDef->getName(),
+                                          FirstInst.Operands[i]));
+                                          
       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";
+        AsmWriterInst &AWI = SimilarInsts[si];
+        OpsToPrint.push_back(std::make_pair(Namespace+"::"+
+                                            AWI.CGI->TheDef->getName(),
+                                            AWI.Operands[i]));
       }
+      std::reverse(OpsToPrint.begin(), OpsToPrint.end());
+      while (!OpsToPrint.empty())
+        PrintCases(OpsToPrint, O);
       O << "    }";
     }
     O << "\n";