add (and document) the ability for alias results to have
authorChris Lattner <sabre@nondot.org>
Sat, 6 Nov 2010 19:57:21 +0000 (19:57 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 6 Nov 2010 19:57:21 +0000 (19:57 +0000)
fixed physical registers.  Start moving fp comparison
aliases to the .td file (which default to using %st1 if
nothing is specified).

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

docs/CodeGenerator.html
lib/Target/X86/AsmParser/X86AsmParser.cpp
lib/Target/X86/X86InstrInfo.td
utils/TableGen/AsmMatcherEmitter.cpp
utils/TableGen/CodeGenInstruction.cpp
utils/TableGen/CodeGenInstruction.h
utils/TableGen/CodeGenRegisters.h

index 376b91c8f1a621d8054b3a6cee4fb56ced081184..8eb43d58ba32d4553898ae4cf377604b2d727337 100644 (file)
@@ -1998,12 +1998,20 @@ def : InstAlias&lt;"clrq $reg", (XOR64rr GR64:$reg, GR64:$reg)&gt;;
 <p>This example also shows that tied operands are only listed once.  In the X86
 backend, XOR8rr has two input GR8's and one output GR8 (where an input is tied
 to the output).  InstAliases take a flattened operand list without duplicates
-for tied operands.  The result of an instruction alias can also use immediates,
-which are added as simple immediate operands in the result, for example:</p>
+for tied operands.  The result of an instruction alias can also use immediates
+and fixed physical registers which are added as simple immediate operands in the
+result, for example:</p>
 
 <div class="doc_code">
 <pre>
+// Fixed Immediate operand.
 def : InstAlias&lt;"aad", (AAD8i8 10)&gt;;
+
+// Fixed register operand.
+def : InstAlias&lt;"fcomi", (COM_FIr ST1)&gt;;
+
+// Simple alias.
+def : InstAlias&lt;"fcomi $reg", (COM_FIr RST:$reg)&gt;;
 </pre>
 </div>
 
index 9ab6b56c8f01b27b74635ccd7c3a0d910c505702..eaa69f1708dfe3ec1404ab9c838bfdfda05ffe51 100644 (file)
@@ -821,7 +821,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
 
   // The assembler accepts these instructions with no operand as a synonym for
   // an instruction acting on st(1).  e.g. "fxch" -> "fxch %st(1)".
-  if ((Name == "fxch" || Name == "fucom" || Name == "fucomp" ||
+  if ((Name == "fxch" ||
        Name == "faddp" || Name == "fsubp" || Name == "fsubrp" ||
        Name == "fmulp" || Name == "fdivp" || Name == "fdivrp") &&
       Operands.size() == 1) {
@@ -829,18 +829,6 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
                                              NameLoc, NameLoc));
   }
 
-  // The assembler accepts these instructions with two few operands as a synonym
-  // for taking %st(1),%st(0) or X, %st(0).
-  if ((Name == "fcomi" || Name == "fucomi" || Name == "fucompi" ||
-       Name == "fcompi" ) &&
-      Operands.size() < 3) {
-    if (Operands.size() == 1)
-      Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
-                                               NameLoc, NameLoc));
-    Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(0)"),
-                                             NameLoc, NameLoc));
-  }
-
   return false;
 }
 
@@ -854,6 +842,8 @@ MatchAndEmitInstruction(SMLoc IDLoc,
 
   // First, handle aliases that expand to multiple instructions.
   // FIXME: This should be replaced with a real .td file alias mechanism.
+  // Also, MatchInstructionImpl should do actually *do* the EmitInstruction
+  // call.
   if (Op->getToken() == "fstsw" || Op->getToken() == "fstcw" ||
       Op->getToken() == "fstsww" || Op->getToken() == "fstcww" ||
       Op->getToken() == "finit" || Op->getToken() == "fsave" ||
index 7fec0141ce41bd3a3241d4458032162eba52a866..fdb29837fd79502652de35b695e0055ce3d6ff3a 100644 (file)
@@ -1377,6 +1377,19 @@ def : InstAlias<"clrw $reg", (XOR16rr GR16:$reg, GR16:$reg)>;
 def : InstAlias<"clrl $reg", (XOR32rr GR32:$reg, GR32:$reg)>;
 def : InstAlias<"clrq $reg", (XOR64rr GR64:$reg, GR64:$reg)>;
 
+// Default arguments for various fp stack instructions.
+def : InstAlias<"fucom",        (UCOM_Fr   ST1)>;
+def : InstAlias<"fucomp",       (UCOM_FPr  ST1)>;
+def : InstAlias<"fcomi",        (COM_FIr   ST1)>;
+def : InstAlias<"fcomi   $reg", (COM_FIr   RST:$reg)>;
+def : InstAlias<"fcomip",       (COM_FIPr  ST1)>;
+def : InstAlias<"fcomip  $reg", (COM_FIPr  RST:$reg)>;
+def : InstAlias<"fucomi",       (UCOM_FIr  ST1)>;
+def : InstAlias<"fucomi  $reg", (UCOM_FIr  RST:$reg)>;
+def : InstAlias<"fucomip",      (UCOM_FIPr ST1)>;
+def : InstAlias<"fucomip $reg", (UCOM_FIPr RST:$reg)>;
+
+
 // We accepts "fnstsw %eax" even though it only writes %ax.
 def : InstAlias<"fnstsw %eax", (FNSTSW8r)>;
 def : InstAlias<"fnstsw %al" , (FNSTSW8r)>;
index 46866140eb48a00572aa828964e076c78bde0eb0..151c1b2f4b174901e38947cab0358cb7b46d43af 100644 (file)
@@ -274,7 +274,10 @@ struct MatchableInfo {
       
       /// ImmOperand - This represents an immediate value that is dumped into
       /// the operand.
-      ImmOperand
+      ImmOperand,
+      
+      /// RegOperand - This represents a fixed register that is dumped in.
+      RegOperand
     } Kind;
     
     union {
@@ -288,6 +291,9 @@ struct MatchableInfo {
       
       /// ImmVal - This is the immediate value added to the instruction.
       int64_t ImmVal;
+      
+      /// Register - This is the register record.
+      Record *Register;
     };
     
     /// OpInfo - This is the information about the instruction operand that is
@@ -320,6 +326,16 @@ struct MatchableInfo {
       X.OpInfo = Op;
       return X;
     }
+    
+    static ResOperand getRegOp(Record *Reg,
+                               const CGIOperandList::OperandInfo *Op) {
+      ResOperand X;
+      X.Kind = RegOperand;
+      X.Register = Reg;
+      X.OpInfo = Op;
+      return X;
+    }
+    
   };
 
   /// TheDef - This is the definition of the instruction or InstAlias that this
@@ -1243,7 +1259,8 @@ void MatchableInfo::BuildAliasResultOperands() {
     
     // Find out what operand from the asmparser that this MCInst operand comes
     // from.
-    if (CGA.ResultOperands[AliasOpNo].isRecord()) {
+    switch (CGA.ResultOperands[AliasOpNo].Kind) {
+    case CodeGenInstAlias::ResultOperand::K_Record: {
       StringRef Name = CGA.ResultOperands[AliasOpNo++].getName();
       int SrcOperand = FindAsmOperandNamed(Name);
       if (SrcOperand != -1) {
@@ -1255,10 +1272,18 @@ void MatchableInfo::BuildAliasResultOperands() {
                     TheDef->getName() + "' has operand '" + OpInfo.Name +
                     "' that doesn't appear in asm string!");
     }
-    
-    int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm();
-    ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo));
-    continue;
+    case CodeGenInstAlias::ResultOperand::K_Imm: {
+      int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm();
+      ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo));
+      continue;
+    }
+
+    case CodeGenInstAlias::ResultOperand::K_Reg: {
+      Record *Reg = CGA.ResultOperands[AliasOpNo++].getRegister();
+      ResOperands.push_back(ResOperand::getRegOp(Reg, &OpInfo));
+      continue;
+    }
+    }
   }
 }
 
@@ -1341,6 +1366,11 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
         Signature += "__imm" + itostr(Val);
         break;
       }
+      case MatchableInfo::ResOperand::RegOperand: {
+        std::string N = getQualifiedName(OpInfo.Register);
+        CaseOS << "    Inst.addOperand(MCOperand::CreateReg(" << N << "));\n";
+        Signature += "__reg" + OpInfo.Register->getName();
+      }  
       }
     }
     
index 924608cbf0fec6f74c83539ab390f85221c02337..84a8b9137e1784ad8beaebcaeea1103e3db2db8d 100644 (file)
@@ -419,6 +419,30 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
     
     
     Init *Arg = Result->getArg(AliasOpNo);
+    Record *ResultOpRec = ResultInst->Operands[i].Rec;
+
+    // Handle explicit registers.
+    if (DefInit *ADI = dynamic_cast<DefInit*>(Arg)) {
+      if (ADI->getDef()->isSubClassOf("Register")) {
+        if (!Result->getArgName(AliasOpNo).empty())
+          throw TGError(R->getLoc(), "result fixed register argument must "
+                        "not have a name!");
+        
+        if (!ResultOpRec->isSubClassOf("RegisterClass"))
+          throw TGError(R->getLoc(), "result fixed register argument is not "
+                        "passed to a RegisterClass operand!");
+        
+        if (!T.getRegisterClass(ResultOpRec).containsRegister(ADI->getDef()))
+          throw TGError(R->getLoc(), "fixed register " +ADI->getDef()->getName()
+                        + " is not a member of the " + ResultOpRec->getName() +
+                        " register class!");
+                                                                              
+        // Now that it is validated, add it.
+        ResultOperands.push_back(ResultOperand(ADI->getDef()));
+        ++AliasOpNo;
+        continue;
+      }
+    }
     
     // If the operand is a record, it must have a name, and the record type must
     // match up with the instruction's argument type.
@@ -427,11 +451,11 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
         throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
                       " must have a name!");
 
-      if (ADI->getDef() != ResultInst->Operands[i].Rec)
+      if (ADI->getDef() != ResultOpRec)
         throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
                       " declared with class " + ADI->getDef()->getName() +
                       ", instruction operand is class " + 
-                      ResultInst->Operands[i].Rec->getName());
+                      ResultOpRec->getName());
       
       // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo)
       // $foo can exist multiple times in the result list, but it must have the
@@ -456,9 +480,9 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
         throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
                       " must not have a name!");
       if (ResultInst->Operands[i].MINumOperands != 1 ||
-          !ResultInst->Operands[i].Rec->isSubClassOf("Operand"))
+          !ResultOpRec->isSubClassOf("Operand"))
         throw TGError(R->getLoc(), "invalid argument class " + 
-                      ResultInst->Operands[i].Rec->getName() +
+                      ResultOpRec->getName() +
                       " for integer result operand!");
       ResultOperands.push_back(ResultOperand(II->getValue()));
       ++AliasOpNo;
index ac593dfb17dcdbc51e57bcfdc905c6a5b9bf7585..9cd23e6fa82c91eec733d004bf87cc6d9b25b55d 100644 (file)
@@ -275,18 +275,22 @@ namespace llvm {
     public:      
       enum {
         K_Record,
-        K_Imm
+        K_Imm,
+        K_Reg
       } Kind;
       
       ResultOperand(StringRef N, Record *r) : Name(N), R(r), Kind(K_Record) {}
       ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
+      ResultOperand(Record *r) : R(r), Kind(K_Reg) {}
 
       bool isRecord() const { return Kind == K_Record; }
       bool isImm() const { return Kind == K_Imm; }
+      bool isReg() const { return Kind == K_Reg; }
       
       StringRef getName() const { assert(isRecord()); return Name; }
       Record *getRecord() const { assert(isRecord()); return R; }
       int64_t getImm() const { assert(isImm()); return Imm; }
+      Record *getRegister() const { assert(isReg()); return R; }
     };
     
     /// ResultOperands - The decoded operands for the result instruction.
index ccd3d222bbad092823dd581a539302892c752b90..bbd0cefa58047fc3a3b27fc5ec05dbea68a9e647 100644 (file)
@@ -57,6 +57,12 @@ namespace llvm {
       abort();
     }
     
+    bool containsRegister(Record *R) const {
+      for (unsigned i = 0, e = Elements.size(); i != e; ++i)
+        if (Elements[i] == R) return true;
+      return false;
+    }
+    
     // Returns true if RC is a strict subclass.
     // RC is a sub-class of this class if it is a valid replacement for any
     // instruction operand where a register of this classis required. It must