This patch implements the instruction constraint DestReg!=SrcReg. It
is needed by ARM backend.

A sample of use of this constraint is following:

class RegConstraint<string C> {
 string Constraints = C;
}

// AI_orr - Defines a (op r, r) pattern.
class AI_orr<string opc, SDNode opnode>
 : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
      !strconcat(opc, " $dst, $a, $b"),
      [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>,
       RegConstraint<"$dst != $a">;


Lauro
Index: include/llvm/Target/TargetInstrInfo.h
===================================================================
RCS file: /var/cvs/llvm/llvm/include/llvm/Target/TargetInstrInfo.h,v
retrieving revision 1.110
diff -u -r1.110 TargetInstrInfo.h
--- include/llvm/Target/TargetInstrInfo.h	15 Dec 2006 06:37:08 -0000	1.110
+++ include/llvm/Target/TargetInstrInfo.h	25 Jan 2007 21:20:32 -0000
@@ -94,9 +94,10 @@
 const unsigned M_PREDICATE_OPERAND = 1 << 1;
 
 namespace TOI {
-  // Operand constraints: only "tied_to" for now.
+  // Operand constraints: only "tied_to" and "not_tied_to" for now.
   enum OperandConstraint {
-    TIED_TO = 0  // Must be allocated the same register as.
+    TIED_TO = 0,  // Must be allocated the same register as.
+    NOT_TIED_TO = 1  // Must not be allocated the same register as.
   };
 }
 
@@ -142,9 +143,22 @@
     return -1;
   }
 
-  /// findTiedToSrcOperand - Returns the operand that is tied to the specified
+  /// findTiedToOperand - Returns the operand that is tied to the specified
   /// dest operand. Returns -1 if there isn't one.
-  int findTiedToSrcOperand(unsigned OpNum) const;
+  int findTiedToOperand(unsigned OpNum) const;
+
+  /// findTiedToOperand - Returns the operand that is "not tied" to the
+  /// specified operand. Returns -1 if there isn't one.
+  int findNotTiedToOperand(unsigned OpNum) const;
+
+  /// isNotTiedToAnyOperand - Returns true if the operand is "not tied" to any
+  /// operand.
+  bool isNotTiedToAnyOperand(unsigned OpNum) const {
+    if (findNotTiedToOperand(OpNum) != -1)
+      return true;
+    else
+      return false;
+  }
 };
 
 
Index: lib/CodeGen/LiveIntervalAnalysis.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp,v
retrieving revision 1.204
diff -u -r1.204 LiveIntervalAnalysis.cpp
--- lib/CodeGen/LiveIntervalAnalysis.cpp	19 Dec 2006 22:41:21 -0000	1.204
+++ lib/CodeGen/LiveIntervalAnalysis.cpp	25 Jan 2007 21:20:33 -0000
@@ -441,6 +441,20 @@
   DOUT << "\t\tregister: "; DEBUG(printRegName(interval.reg));
   LiveVariables::VarInfo& vi = lv_->getVarInfo(interval.reg);
 
+  std::vector<bool> IsKillAfterInstr(vi.Kills.size());
+
+  for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i){
+    const TargetInstrDescriptor *instrDescriptor =
+      vi.Kills[i]->getInstrDescriptor();
+    IsKillAfterInstr[i] = false;
+    for (unsigned j = 0, f = vi.Kills[i]->getNumOperands(); j != f; ++j){
+      MachineOperand op = vi.Kills[i]->getOperand(j);
+      if (op.isRegister() && op.isUse() && (op.getReg() == interval.reg) &&
+          instrDescriptor->isNotTiedToAnyOperand(j))
+        IsKillAfterInstr[i] = true;
+    }
+  }
+
   // Virtual registers may be defined multiple times (due to phi
   // elimination and 2-addr elimination).  Much of what we do only has to be
   // done once for the vreg.  We use an empty interval to detect the first
@@ -467,9 +481,10 @@
       // FIXME: what about dead vars?
       unsigned killIdx;
       if (vi.Kills[0] != mi)
-        killIdx = getUseIndex(getInstructionIndex(vi.Kills[0]))+1;
+        killIdx = getUseIndex(getInstructionIndex(vi.Kills[0])) +
+          (IsKillAfterInstr[0]?2:1);
       else
-        killIdx = defIndex+1;
+        killIdx = defIndex + (IsKillAfterInstr[0]?2:1);
 
       // If the kill happens after the definition, we have an intra-block
       // live range.
@@ -514,8 +529,8 @@
     for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) {
       MachineInstr *Kill = vi.Kills[i];
       LiveRange LR(getMBBStartIdx(Kill->getParent()),
-                   getUseIndex(getInstructionIndex(Kill))+1,
-                   ValNum);
+                   getUseIndex(getInstructionIndex(Kill)) +
+                   (IsKillAfterInstr[i]?2:1), ValNum);
       interval.addRange(LR);
       DOUT << " +" << LR;
     }
@@ -574,7 +589,8 @@
         // Remove the old range that we now know has an incorrect number.
         MachineInstr *Killer = vi.Kills[0];
         unsigned Start = getMBBStartIdx(Killer->getParent());
-        unsigned End = getUseIndex(getInstructionIndex(Killer))+1;
+        unsigned End = getUseIndex(getInstructionIndex(Killer)) +
+          (IsKillAfterInstr[0]?2:1);
         DOUT << "Removing [" << Start << "," << End << "] from: ";
         interval.print(DOUT, mri_); DOUT << "\n";
         interval.removeRange(Start, End);
Index: lib/CodeGen/RegAllocLocal.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/CodeGen/RegAllocLocal.cpp,v
retrieving revision 1.99
diff -u -r1.99 RegAllocLocal.cpp
--- lib/CodeGen/RegAllocLocal.cpp	19 Dec 2006 22:41:21 -0000	1.99
+++ lib/CodeGen/RegAllocLocal.cpp	25 Jan 2007 21:20:33 -0000
@@ -687,12 +687,45 @@
       MachineOperand& MO = MI->getOperand(i);
       if (MO.isRegister() && MO.isDef() && MO.getReg() &&
           MRegisterInfo::isVirtualRegister(MO.getReg())) {
+        unsigned notTiedReg;
         unsigned DestVirtReg = MO.getReg();
-        unsigned DestPhysReg;
+        unsigned DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg);
+
+        //get "not tied" constraint information
+        int notTiedOp = MI->getInstrDescriptor()->findNotTiedToOperand(i);
+        if (notTiedOp != -1)
+          notTiedReg = MI->getOperand(notTiedOp).getReg();
+
+
+        bool violateNotTied = DestPhysReg &&
+          notTiedOp != -1 &&
+          areRegsEqual(DestPhysReg, notTiedReg);
+
+
+        // If DestPhysReg doesn't have a value or the value violates "not tied"
+        // constraint, it allocates a register. If the previously allocated
+        // DestPhysReg violates "not tied" constraint, it copies new register
+        // to previously allocated DestPhysReg.
+        if (!DestPhysReg || violateNotTied) {
+          int reservedReg = -1;
+          if (notTiedOp != -1 && isPhysRegAvailable(notTiedReg)){
+              PhysRegsUsed[notTiedReg] = 0; //mark notTiedReg as reserved
+              reservedReg = notTiedReg;
+          }
+          unsigned newReg = getReg(MBB, MI, DestVirtReg);
+
+          if (violateNotTied) {
+            //copy new register to previously allocated DestPhysReg.
+            const TargetRegisterClass *RC =
+              MF->getSSARegMap()->getRegClass(DestVirtReg);
+            RegInfo->copyRegToReg(MBB, MII, DestPhysReg, newReg, RC);
+            PhysRegsEverUsed[DestPhysReg] = true;
+          }
+          DestPhysReg = newReg;
+          if (reservedReg != -1)
+            PhysRegsUsed[reservedReg] = -1;
+        }
 
-        // If DestVirtReg already has a value, use it.
-        if (!(DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg)))
-          DestPhysReg = getReg(MBB, MI, DestVirtReg);
         PhysRegsEverUsed[DestPhysReg] = true;
         markVirtRegModified(DestVirtReg);
         MI->getOperand(i).setReg(DestPhysReg);  // Assign the output register
Index: lib/CodeGen/RegAllocSimple.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/CodeGen/RegAllocSimple.cpp,v
retrieving revision 1.82
diff -u -r1.82 RegAllocSimple.cpp
--- lib/CodeGen/RegAllocSimple.cpp	19 Dec 2006 22:41:21 -0000	1.82
+++ lib/CodeGen/RegAllocSimple.cpp	25 Jan 2007 21:20:33 -0000
@@ -198,7 +198,7 @@
         unsigned physReg = Virt2PhysRegMap[virtualReg];
         if (physReg == 0) {
           if (op.isDef()) {
-            int TiedOp = MI->getInstrDescriptor()->findTiedToSrcOperand(i);
+            int TiedOp = MI->getInstrDescriptor()->findTiedToOperand(i);
             if (TiedOp == -1) {
               physReg = getFreeReg(virtualReg);
             } else {
Index: lib/CodeGen/VirtRegMap.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/CodeGen/VirtRegMap.cpp,v
retrieving revision 1.94
diff -u -r1.94 VirtRegMap.cpp
--- lib/CodeGen/VirtRegMap.cpp	23 Jan 2007 00:59:48 -0000	1.94
+++ lib/CodeGen/VirtRegMap.cpp	25 Jan 2007 21:20:33 -0000
@@ -99,8 +99,7 @@
 
   ModRef MRInfo;
   const TargetInstrDescriptor *TID = OldMI->getInstrDescriptor();
-  if (TID->getOperandConstraint(OpNo, TOI::TIED_TO) != -1 ||
-      TID->findTiedToSrcOperand(OpNo) != -1) {
+  if (TID->findTiedToOperand(OpNo) != -1) {
     // Folded a two-address operand.
     MRInfo = isModRef;
   } else if (OldMI->getOperand(OpNo).isDef()) {
@@ -904,7 +903,7 @@
         // If this def is part of a two-address operand, make sure to execute
         // the store from the correct physical register.
         unsigned PhysReg;
-        int TiedOp = MI.getInstrDescriptor()->findTiedToSrcOperand(i);
+        int TiedOp = MI.getInstrDescriptor()->findTiedToOperand(i);
         if (TiedOp != -1)
           PhysReg = MI.getOperand(TiedOp).getReg();
         else {
Index: lib/Target/TargetInstrInfo.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/lib/Target/TargetInstrInfo.cpp,v
retrieving revision 1.26
diff -u -r1.26 TargetInstrInfo.cpp
--- lib/Target/TargetInstrInfo.cpp	8 Dec 2006 18:45:14 -0000	1.26
+++ lib/Target/TargetInstrInfo.cpp	25 Jan 2007 21:20:33 -0000
@@ -17,9 +17,13 @@
 #include "llvm/DerivedTypes.h"
 using namespace llvm;
 
-/// findTiedToSrcOperand - Returns the operand that is tied to the specified
-/// dest operand. Returns -1 if there isn't one.
-int TargetInstrDescriptor::findTiedToSrcOperand(unsigned OpNum) const {
+/// findTiedToOperand - Returns the operand that is tied to the specified
+/// operand. Returns -1 if there isn't one.
+int TargetInstrDescriptor::findTiedToOperand(unsigned OpNum) const {
+  int tiedOp = getOperandConstraint(OpNum, TOI::TIED_TO);
+  if (tiedOp != -1)
+    return tiedOp;
+
   for (unsigned i = 0, e = numOperands; i != e; ++i) {
     if (i == OpNum)
       continue;
@@ -29,6 +33,21 @@
   return -1;
 }
 
+/// findTiedToOperand - Returns the operand that is "not tied" to the
+/// specified operand. Returns -1 if there isn't one.
+int TargetInstrDescriptor::findNotTiedToOperand(unsigned OpNum) const {
+  int notTiedOp = getOperandConstraint(OpNum, TOI::NOT_TIED_TO);
+  if (notTiedOp != -1)
+    return notTiedOp;
+
+  for (unsigned i = 0, e = numOperands; i != e; ++i) {
+    if (i == OpNum)
+      continue;
+    if (getOperandConstraint(i, TOI::NOT_TIED_TO) == (int)OpNum)
+      return i;
+  }
+  return -1;
+}
 
 TargetInstrInfo::TargetInstrInfo(const TargetInstrDescriptor* Desc,
                                  unsigned numOpcodes)
Index: utils/TableGen/CodeGenTarget.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/utils/TableGen/CodeGenTarget.cpp,v
retrieving revision 1.81
diff -u -r1.81 CodeGenTarget.cpp
--- utils/TableGen/CodeGenTarget.cpp	7 Dec 2006 22:21:48 -0000	1.81
+++ utils/TableGen/CodeGenTarget.cpp	25 Jan 2007 21:20:35 -0000
@@ -20,6 +20,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Streams.h"
+#include "llvm/Target/TargetInstrInfo.h"
 #include <set>
 #include <algorithm>
 using namespace llvm;
@@ -277,35 +278,40 @@
 
 
 static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
-  // FIXME: Only supports TIED_TO for now.
-  std::string::size_type pos = CStr.find_first_of('=');
+  TOI::OperandConstraint constraint = TOI::NOT_TIED_TO;
+  std::string::size_type separatorSize = 2; //strlen("!=");
+  std::string::size_type pos = CStr.find("!=");
+  if (pos == std::string::npos) {
+    pos = CStr.find_first_of('=');
+    constraint = TOI::TIED_TO;
+    separatorSize = 1; //strlen("=");
+  }
   assert(pos != std::string::npos && "Unrecognized constraint");
   std::string Name = CStr.substr(0, pos);
 
-  // TIED_TO: $src1 = $dst
+  // TIED_TO: $src1 = $dst or $dst = $src1
+  // NOT_TIED_TO: $src1 != $dst or $dst != $src1
   std::string::size_type wpos = Name.find_first_of(" \t");
   if (wpos == std::string::npos)
     throw "Illegal format for tied-to constraint: '" + CStr + "'";
   std::string DestOpName = Name.substr(0, wpos);
   std::pair<unsigned,unsigned> DestOp = I->ParseOperandName(DestOpName, false);
 
-  Name = CStr.substr(pos+1);
+  Name = CStr.substr(pos + separatorSize);
   wpos = Name.find_first_not_of(" \t");
   if (wpos == std::string::npos)
     throw "Illegal format for tied-to constraint: '" + CStr + "'";
-    
+
   std::pair<unsigned,unsigned> SrcOp =
     I->ParseOperandName(Name.substr(wpos), false);
-  if (SrcOp > DestOp)
-    throw "Illegal tied-to operand constraint '" + CStr + "'";
-  
-  
+
   unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp);
   // Build the string for the operand.
-  std::string OpConstraint =
-    "((" + utostr(FlatOpNo) + " << 16) | (1 << TOI::TIED_TO))";
+  unsigned Pos = 16 + constraint * 4;
+  std::string OpConstraint ="((" + utostr(FlatOpNo) + " << " + utostr(Pos) +
+    ") | (1 << " + utostr(constraint) +"))";
+
 
-  
   if (!I->OperandList[DestOp.first].Constraints[DestOp.second].empty())
     throw "Operand '" + DestOpName + "' cannot have multiple constraints!";
   I->OperandList[DestOp.first].Constraints[DestOp.second] = OpConstraint;
_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Reply via email to