Replace the old algorithm that emitted the "print the alias for an instruction"
authorBill Wendling <isanbard@gmail.com>
Thu, 7 Apr 2011 21:20:06 +0000 (21:20 +0000)
committerBill Wendling <isanbard@gmail.com>
Thu, 7 Apr 2011 21:20:06 +0000 (21:20 +0000)
with the newer, cleaner model. It uses the IAPrinter class to hold the
information that is needed to match an instruction with its alias. This also
takes into account the available features of the platform.

There is one bit of ugliness. The way the logic determines if a pattern is
unique is O(N**2), which is gross. But in reality, the number of items it's
checking against isn't large. So while it's N**2, it shouldn't be a massive time
sink.

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

include/llvm/MC/MCInstPrinter.h
lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp
lib/Target/X86/InstPrinter/X86ATTInstPrinter.h
lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp
lib/Target/X86/InstPrinter/X86IntelInstPrinter.h
utils/TableGen/AsmWriterEmitter.cpp

index 92f06ed09c6bbcee93f115116851182fc64933c5..066955867c5910005e5370d830aa5f2f4e7cd392 100644 (file)
@@ -25,9 +25,12 @@ protected:
   /// assembly emission is disable.
   raw_ostream *CommentStream;
   const MCAsmInfo &MAI;
+
+  /// The current set of available features.
+  unsigned AvailableFeatures;
 public:
   MCInstPrinter(const MCAsmInfo &mai)
-    : CommentStream(0), MAI(mai) {}
+    : CommentStream(0), MAI(mai), AvailableFeatures(0) {}
 
   virtual ~MCInstPrinter();
 
@@ -44,6 +47,9 @@ public:
 
   /// getRegName - Return the assembler register name.
   virtual StringRef getRegName(unsigned RegNo) const;
+
+  unsigned getAvailableFeatures() const { return AvailableFeatures; }
+  void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; }
 };
 
 } // namespace llvm
index d6950f49f824bcafa2624b85fa66a59775a11967..d006eca3449253b34d1f47a4c9cde2919b3ce594 100644 (file)
@@ -15,6 +15,7 @@
 #define DEBUG_TYPE "asm-printer"
 #include "X86ATTInstPrinter.h"
 #include "X86InstComments.h"
+#include "X86Subtarget.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormattedStream.h"
 #include "X86GenInstrNames.inc"
+#include <map>
 using namespace llvm;
 
 // Include the auto-generated portion of the assembly writer.
 #define GET_INSTRUCTION_NAME
+#define PRINT_ALIAS_INSTR
+#include "X86GenRegisterNames.inc"
 #include "X86GenAsmWriter.inc"
+#undef PRINT_ALIAS_INSTR
+#undef GET_INSTRUCTION_NAME
+
+X86ATTInstPrinter::X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI)
+  : MCInstPrinter(MAI) {
+  // Initialize the set of available features.
+  setAvailableFeatures(ComputeAvailableFeatures(
+            &TM.getSubtarget<X86Subtarget>()));
+}
 
 void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) {
   printInstruction(MI, OS);
@@ -35,11 +48,11 @@ void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) {
   if (CommentStream)
     EmitAnyX86InstComments(MI, *CommentStream, getRegisterName);
 }
+
 StringRef X86ATTInstPrinter::getOpcodeName(unsigned Opcode) const {
   return getInstructionName(Opcode);
 }
 
-
 void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op,
                                    raw_ostream &O) {
   switch (MI->getOperand(Op).getImm()) {
index 0a10c6c1a6b39495782ec7ab8516cffb92604de0..f24674f68e3ad35f99e58a3f5f0f628811704014 100644 (file)
 namespace llvm {
 
 class MCOperand;
+class X86Subtarget;
 class TargetMachine;
   
 class X86ATTInstPrinter : public MCInstPrinter {
 public:
-  X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI)
-    : MCInstPrinter(MAI) {}
+  X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI);
   
   virtual void printInst(const MCInst *MI, raw_ostream &OS);
   virtual StringRef getOpcodeName(unsigned Opcode) const;
 
+  // Methods used to print the alias of an instruction.
+  unsigned ComputeAvailableFeatures(const X86Subtarget *Subtarget) const;
+  bool printAliasInstr(const MCInst *MI, raw_ostream &OS);
+
   // Autogenerated by tblgen.
   void printInstruction(const MCInst *MI, raw_ostream &OS);
   static const char *getRegisterName(unsigned RegNo);
index 048452985089d10ffcd41d1a5d352b555e94cc32..47253ebd202ef643efa938b796200a64ef147e4d 100644 (file)
@@ -15,6 +15,7 @@
 #define DEBUG_TYPE "asm-printer"
 #include "X86IntelInstPrinter.h"
 #include "X86InstComments.h"
+#include "X86Subtarget.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCExpr.h"
index b1dc3f46941415c5515a58cdf8fd29fe06737e7b..ca99dc09b8a41c5687736ca41e3ca6259ec1b4d9 100644 (file)
@@ -26,7 +26,7 @@ class X86IntelInstPrinter : public MCInstPrinter {
 public:
   X86IntelInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI)
     : MCInstPrinter(MAI) {}
-  
+
   virtual void printInst(const MCInst *MI, raw_ostream &OS);
   virtual StringRef getOpcodeName(unsigned Opcode) const;
   
@@ -35,7 +35,6 @@ public:
   static const char *getRegisterName(unsigned RegNo);
   static const char *getInstructionName(unsigned Opcode);
 
-
   void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printMemReference(const MCInst *MI, unsigned Op, raw_ostream &O);
   void printSSECC(const MCInst *MI, unsigned Op, raw_ostream &O);
index 7c5c9e45ef60b3d8641a205fdc28d532c54dc585..534f20f1eb47b273395279f528d0eb0cffee5068 100644 (file)
@@ -626,26 +626,30 @@ public:
   bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); }
 
   void print(raw_ostream &O) {
-    unsigned Indent = 8;
+    if (Conds.empty() && ReqFeatures.empty()) {
+      O.indent(6) << "return true;\n";
+      return;
+    }
 
-    if (!Conds.empty())
-      O << "if (";
+    O << "if (";
 
     for (std::vector<std::string>::iterator
            I = Conds.begin(), E = Conds.end(); I != E; ++I) {
       if (I != Conds.begin()) {
         O << " &&\n";
-        O.indent(Indent);
+        O.indent(8);
       }
 
       O << *I;
     }
 
     if (!ReqFeatures.empty()) {
-      if (Conds.begin() != Conds.end())
+      if (Conds.begin() != Conds.end()) {
         O << " &&\n";
-      else
+        O.indent(8);
+      } else {
         O << "if (";
+      }
 
       std::string Req;
       raw_string_ostream ReqO(Req);
@@ -656,28 +660,21 @@ public:
         ReqO << AWI.getFeatureInfo(*I)->getEnumName();
       }
 
-      if (Conds.begin() != Conds.end()) O.indent(Indent);
       O << "(AvailableFeatures & (" << ReqO.str() << ")) == ("
         << ReqO.str() << ')';
     }
 
-    if (!Conds.empty() || !ReqFeatures.empty()) {
-      O << ") {\n";
-      Indent = 6;
-    } else {
-      Indent = 4;
-    }
-
-    O.indent(Indent) << "// " << Result << "\n";
-    O.indent(Indent) << "AsmString = \"" << AsmString << "\";\n";
+    O << ") {\n";
+    O.indent(6) << "// " << Result << "\n";
+    O.indent(6) << "AsmString = \"" << AsmString << "\";\n";
 
     for (std::map<StringRef, unsigned>::iterator
            I = OpMap.begin(), E = OpMap.end(); I != E; ++I)
-      O.indent(Indent) << "OpMap[\"" << I->first << "\"] = "
-                       << I->second << ";\n";
+      O.indent(6) << "OpMap[\"" << I->first << "\"] = "
+                  << I->second << ";\n";
 
-    if (!Conds.empty() || !ReqFeatures.empty())
-      O.indent(4) << '}';
+    O.indent(6) << "break;\n";
+    O.indent(4) << '}';
   }
 
   bool operator==(const IAPrinter &RHS) {
@@ -727,7 +724,7 @@ static void EmitSubtargetFeatureFlagEnumeration(AsmWriterInfo &Info,
 
   O << "  Feature_None = 0\n";
   O << "};\n\n";
-  O << "} // end anonymous namespace\n";
+  O << "} // end anonymous namespace\n\n";
 }
 
 /// EmitComputeAvailableFeatures - Emit the function to compute the list of
@@ -928,156 +925,72 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
 
       if (CantHandle) continue;
       IAPrinterMap[I->first].push_back(IAP);
-
-#if 0
-      O.indent(4) << "// " << I->first << '\n';
-      O.indent(4);
-      IAP->print(O);
-#endif
     }
   }
 
-  O << "#if 0\n";
   EmitSubtargetFeatureFlagEnumeration(AWI, O);
   EmitComputeAvailableFeatures(AWI, AsmWriter, Target, O);
-  O << "#endif\n\n";
 
   O << "bool " << Target.getName() << ClassName
     << "::printAliasInstr(const " << MachineInstrClassName
     << " *MI, raw_ostream &OS) {\n";
 
-  if (AliasMap.empty() || !isMC) {
-    // FIXME: Support MachineInstr InstAliases?
-    O << "  return true;\n";
-    O << "}\n\n";
-    O << "#endif // PRINT_ALIAS_INSTR\n";
-    return;
-  }
-
-  O << "  StringRef AsmString;\n";
-  O << "  std::map<StringRef, unsigned> OpMap;\n";
-  O << "  switch (MI->getOpcode()) {\n";
-  O << "  default: return true;\n";
-
-  for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator
-         I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) {
-    std::vector<CodeGenInstAlias*> &Aliases = I->second;
-
-    std::map<std::string, unsigned> CondCount;
-    std::map<std::string, std::string> BodyMap;
-
-    std::string AsmString = "";
-
-    for (std::vector<CodeGenInstAlias*>::iterator
-           II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) {
-      const CodeGenInstAlias *CGA = *II;
-      AsmString = CGA->AsmString;
-      unsigned Indent = 8;
-      unsigned LastOpNo = CGA->ResultInstOperandIndex.size();
-
-      std::string Cond;
-      raw_string_ostream CondO(Cond);
-
-      CondO << "if (MI->getNumOperands() == " << LastOpNo;
-
-      std::map<StringRef, unsigned> OpMap;
-      bool CantHandle = false;
-
-      for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
-        const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i];
-
-        switch (RO.Kind) {
-        default: assert(0 && "unexpected InstAlias operand kind");
-        case CodeGenInstAlias::ResultOperand::K_Record: {
-          const Record *Rec = RO.getRecord();
-          StringRef ROName = RO.getName();
-
-          if (Rec->isSubClassOf("RegisterClass")) {
-            CondO << " &&\n";
-            CondO.indent(Indent) << "MI->getOperand(" << i << ").isReg() &&\n";
-            if (OpMap.find(ROName) == OpMap.end()) {
-              OpMap[ROName] = i;
-              CondO.indent(Indent)
-                << "regIsInRegisterClass(RC_"
-                << CGA->ResultOperands[i].getRecord()->getName()
-                << ", MI->getOperand(" << i << ").getReg())";
-            } else {
-              CondO.indent(Indent)
-                << "MI->getOperand(" << i
-                << ").getReg() == MI->getOperand("
-                << OpMap[ROName] << ").getReg()";
-            }
-          } else {
-            assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
-            // FIXME: We need to handle these situations.
-            CantHandle = true;
-            break;
-          }
-
-          break;
-        }
-        case CodeGenInstAlias::ResultOperand::K_Imm:
-          CondO << " &&\n";
-          CondO.indent(Indent) << "MI->getOperand(" << i << ").getImm() == ";
-          CondO << CGA->ResultOperands[i].getImm();
-          break;
-        case CodeGenInstAlias::ResultOperand::K_Reg:
-          CondO << " &&\n";
-          CondO.indent(Indent) << "MI->getOperand(" << i << ").getReg() == ";
-          CondO << Target.getName() << "::"
-                << CGA->ResultOperands[i].getRegister()->getName();
+  std::string Cases;
+  raw_string_ostream CasesO(Cases);
+
+  for (std::map<std::string, std::vector<IAPrinter*> >::iterator
+         I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) {
+    std::vector<IAPrinter*> &IAPs = I->second;
+    std::vector<IAPrinter*> UniqueIAPs;
+
+    for (std::vector<IAPrinter*>::iterator
+           II = IAPs.begin(), IE = IAPs.end(); II != IE; ++II) {
+      IAPrinter *LHS = *II;
+      bool IsDup = false;
+      for (std::vector<IAPrinter*>::iterator
+             III = IAPs.begin(), IIE = IAPs.end(); III != IIE; ++III) {
+        IAPrinter *RHS = *III;
+        if (LHS != RHS && *LHS == *RHS) {
+          IsDup = true;
           break;
         }
-
-        if (CantHandle) break;
       }
 
-      if (CantHandle) continue;
-
-      CondO << ")";
-
-      std::string Body;
-      raw_string_ostream BodyO(Body);
+      if (!IsDup) UniqueIAPs.push_back(LHS);
+    }
 
-      BodyO << "      // " << CGA->Result->getAsString() << "\n";
-      BodyO << "      AsmString = \"" << AsmString << "\";\n";
+    if (UniqueIAPs.empty()) continue;
 
-      for (std::map<StringRef, unsigned>::iterator
-             III = OpMap.begin(), IIE = OpMap.end(); III != IIE; ++III)
-        BodyO << "      OpMap[\"" << III->first << "\"] = "
-              << III->second << ";\n";
+    CasesO.indent(2) << "case " << I->first << ":\n";
 
-      ++CondCount[CondO.str()];
-      BodyMap[CondO.str()] = BodyO.str();
+    for (std::vector<IAPrinter*>::iterator
+           II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) {
+      IAPrinter *IAP = *II;
+      CasesO.indent(4);
+      IAP->print(CasesO);
+      CasesO << '\n';
     }
 
-    std::string Code;
-    raw_string_ostream CodeO(Code);
-
-    bool EmitElse = false;
-    for (std::map<std::string, unsigned>::iterator
-           II = CondCount.begin(), IE = CondCount.end(); II != IE; ++II) {
-      if (II->second != 1) continue;
-      CodeO << "    ";
-      if (EmitElse) CodeO << "} else ";
-      CodeO << II->first << " {\n";
-      CodeO << BodyMap[II->first];
-      EmitElse = true;
-    }
-
-    if (CodeO.str().empty()) continue;
+    CasesO.indent(4) << "return true;\n";
+  }
 
-    O << "  case " << I->first << ":\n";
-    O << CodeO.str();
-    O << "    }\n";
-    O << "    break;\n";
+  if (CasesO.str().empty() || !isMC) {
+    O << "  return true;\n";
+    O << "}\n\n";
+    O << "#endif // PRINT_ALIAS_INSTR\n";
+    return;
   }
 
-  O << "  }\n\n";
+  O.indent(2) << "StringRef AsmString;\n";
+  O.indent(2) << "std::map<StringRef, unsigned> OpMap;\n";
+  O.indent(2) << "unsigned AvailableFeatures = getAvailableFeatures();\n\n";
+  O.indent(2) << "switch (MI->getOpcode()) {\n";
+  O.indent(2) << "default: return true;\n";
+  O << CasesO.str();
+  O.indent(2) << "}\n\n";
 
   // Code that prints the alias, replacing the operands with the ones from the
   // MCInst.
-  O << "  if (AsmString.empty()) return true;\n";
   O << "  std::pair<StringRef, StringRef> ASM = AsmString.split(' ');\n";
   O << "  OS << '\\t' << ASM.first;\n";