The read_latency.patch is incomplete. I forgot to deal with spill live
intervals.

Lauro

2007/2/6, Lauro Ramos Venancio <[EMAIL PROTECTED]>:
READ_LATENCY patch for review.

Sample of use:
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<"$a lat 2">;


Lauro

2007/1/26, Evan Cheng <[EMAIL PROTECTED]>:
>
> On Jan 26, 2007, at 1:07 PM, Lauro Ramos Venancio wrote:
>
> >> The facility does that have to be that general. There are 4 cycles
> >> between every two instructions.  See LiveIntervalAnalysis:
> >>
> >>      struct InstrSlots {
> >>        enum {
> >>          LOAD  = 0,
> >>          USE   = 1,
> >>          DEF   = 2,
> >>          STORE = 3,
> >>          NUM   = 4
> >>        };
> >>      };
> >>
> >> We can restrict the constraint range to 1 - 3. This ensures the last
> >> use is always the kill while retaining its flexibility.
> >>
> >> Evan
> >
> > I will try to implement this. Do you have any suggestion for
> > constraint name and syntax?
>
> I don't have any great ideas. Perhaps READ_LATENCY for constraint and
> something like
>
> $src +lat 2
>
> for syntax?
>
> Feel free to choose something else if you have better ideas.
>
> Thanks,
>
> Evan
>
> >
> > Lauro
>
>


Index: include/llvm/Target/TargetInstrInfo.h
===================================================================
RCS file: /var/cvs/llvm/llvm/include/llvm/Target/TargetInstrInfo.h,v
retrieving revision 1.111
diff -u -r1.111 TargetInstrInfo.h
--- include/llvm/Target/TargetInstrInfo.h	26 Jan 2007 14:34:51 -0000	1.111
+++ include/llvm/Target/TargetInstrInfo.h	6 Feb 2007 21:09:44 -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 read_latency for now.
   enum OperandConstraint {
-    TIED_TO = 0  // Must be allocated the same register as.
+    TIED_TO = 0,  // Must be allocated the same register as.
+    READ_LATENCY  // Number of cycles needed for read operand.
   };
 }
 
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	6 Feb 2007 21:09:44 -0000
@@ -354,15 +354,26 @@
             //
             // Keep track of whether we replace a use and/or def so that we can
             // create the spill interval with the appropriate range. 
-            mop.setReg(NewVReg);
-            
-            bool HasUse = mop.isUse();
-            bool HasDef = mop.isDef();
-            for (unsigned j = i+1, e = MI->getNumOperands(); j != e; ++j) {
+
+            bool HasUse = false;
+            bool HasDef = false;
+            int ReadLatency = InstrSlots::USE; //default read latency
+            for (unsigned j = i, e = MI->getNumOperands(); j != e; ++j) {
               if (MI->getOperand(j).isReg() &&
                   MI->getOperand(j).getReg() == li.reg) {
                 MI->getOperand(j).setReg(NewVReg);
-                HasUse |= MI->getOperand(j).isUse();
+
+                if (MI->getOperand(j).isUse()) {
+                  HasUse = true;
+                  //get the greatest read latency
+                  if (!MI->getOperand(j).isImplicit()){
+                    int read_latency = MI->getInstrDescriptor()->
+                      getOperandConstraint(j,TOI::READ_LATENCY);
+                    if (read_latency != -1 && read_latency > ReadLatency)
+                      ReadLatency = read_latency;
+                  }
+                }
+
                 HasDef |= MI->getOperand(j).isDef();
               }
             }
@@ -376,16 +387,16 @@
             // the spill weight is now infinity as it
             // cannot be spilled again
             nI.weight = HUGE_VALF;
-
+            unsigned ValNum = nI.getNextValue(~0U, 0);
             if (HasUse) {
-              LiveRange LR(getLoadIndex(index), getUseIndex(index),
-                           nI.getNextValue(~0U, 0));
+              LiveRange LR(getLoadIndex(index),
+                           getBaseIndex(index) + ReadLatency + 1, ValNum);
               DOUT << " +" << LR;
               nI.addRange(LR);
             }
             if (HasDef) {
               LiveRange LR(getDefIndex(index), getStoreIndex(index),
-                           nI.getNextValue(~0U, 0));
+                           ValNum);
               DOUT << " +" << LR;
               nI.addRange(LR);
             }
@@ -441,6 +452,24 @@
   DOUT << "\t\tregister: "; DEBUG(printRegName(interval.reg));
   LiveVariables::VarInfo& vi = lv_->getVarInfo(interval.reg);
 
+  // For each kill, get the greatest read latency of the virtual register.
+  std::vector<char> ReadLatency(vi.Kills.size());
+  for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i){
+    const TargetInstrDescriptor *instrDescriptor =
+      vi.Kills[i]->getInstrDescriptor();
+    ReadLatency[i] = InstrSlots::USE; //default read latency
+    //find the operands that use the virtual register
+    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)) {
+        int read_latency =
+          instrDescriptor->getOperandConstraint(j, TOI::READ_LATENCY);
+        if (read_latency != -1 && read_latency > ReadLatency[i])
+          ReadLatency[i] = (char) read_latency;
+      }
+    }
+  }
+
   // 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,7 +496,7 @@
       // FIXME: what about dead vars?
       unsigned killIdx;
       if (vi.Kills[0] != mi)
-        killIdx = getUseIndex(getInstructionIndex(vi.Kills[0]))+1;
+        killIdx = getInstructionIndex(vi.Kills[0]) + ReadLatency[0] + 1;
       else
         killIdx = defIndex+1;
 
@@ -514,7 +543,7 @@
     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,
+                   getInstructionIndex(Kill)+ ReadLatency[i] + 1,
                    ValNum);
       interval.addRange(LR);
       DOUT << " +" << LR;
@@ -574,7 +603,7 @@
         // 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 = getInstructionIndex(Killer) + ReadLatency[0] + 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.100
diff -u -r1.100 RegAllocLocal.cpp
--- lib/CodeGen/RegAllocLocal.cpp	1 Feb 2007 05:31:50 -0000	1.100
+++ lib/CodeGen/RegAllocLocal.cpp	6 Feb 2007 21:09:45 -0000
@@ -567,10 +567,20 @@
     }
 
     SmallVector<unsigned, 8> Kills;
+    SmallVector<char, 8> ReadLatency;
     for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
       MachineOperand& MO = MI->getOperand(i);
-      if (MO.isRegister() && MO.isKill())
+      if (MO.isRegister() && MO.isKill()){
         Kills.push_back(MO.getReg());
+        int read_latency = 1;
+        //we can't call getOperandConstraint on a implicit MO
+        if (!MO.isImplicit()) {
+          read_latency = TID.getOperandConstraint(i,TOI::READ_LATENCY);
+          if (read_latency == -1)
+            read_latency = 1;
+        }
+        ReadLatency.push_back((char)read_latency);
+      }
     }
 
     // Get the used operands into registers.  This has the potential to spill
@@ -591,6 +601,7 @@
     // value, freeing the register being used, so it doesn't need to be
     // spilled to memory.
     //
+    SmallVector<unsigned, 8> PostponedRegRemove;
     for (unsigned i = 0, e = Kills.size(); i != e; ++i) {
       unsigned VirtReg = Kills[i];
       unsigned PhysReg = VirtReg;
@@ -606,16 +617,21 @@
       }
 
       if (PhysReg) {
-        DOUT << "  Last use of " << RegInfo->getName(PhysReg)
-             << "[%reg" << VirtReg <<"], removing it from live set\n";
-        removePhysReg(PhysReg);
-        for (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg);
-             *AliasSet; ++AliasSet) {
-          if (PhysRegsUsed[*AliasSet] != -2) {
-            DOUT  << "  Last use of "
-                  << RegInfo->getName(*AliasSet)
-                  << "[%reg" << VirtReg <<"], removing it from live set\n";
-            removePhysReg(*AliasSet);
+        if (ReadLatency[i] > 1) {
+          //postpone the reg remove from live set.
+          PostponedRegRemove.push_back(PhysReg);
+        } else {
+          DOUT << "  Last use of " << RegInfo->getName(PhysReg)
+               << "[%reg" << VirtReg <<"], removing it from live set\n"; 
+          removePhysReg(PhysReg);
+          for (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg);
+               *AliasSet; ++AliasSet) {
+            if (PhysRegsUsed[*AliasSet] != -2) {
+              DOUT  << "  Last use of "
+                    << RegInfo->getName(*AliasSet)
+                    << "[%reg" << VirtReg <<"], removing it from live set\n";
+              removePhysReg(*AliasSet);
+            }
           }
         }
       }
@@ -731,7 +747,24 @@
         }
       }
     }
-    
+
+    //Do postponed reg removes from live set
+    for (unsigned i = 0, e = PostponedRegRemove.size(); i != e; ++i) {
+      DOUT << "  Last use of " << RegInfo->getName(PostponedRegRemove[i])
+           <<", removing it from live set (postponed)\n";
+      removePhysReg(PostponedRegRemove[i]);
+      for (const unsigned *AliasSet =
+             RegInfo->getAliasSet(PostponedRegRemove[i]);
+           *AliasSet; ++AliasSet) {
+        if (PhysRegsUsed[*AliasSet] != -2) {
+          DOUT  << "  Last use of "
+                << RegInfo->getName(*AliasSet)
+                <<", removing it from live set (postponed)\n";
+          removePhysReg(*AliasSet);
+        }
+      }
+    }
+
     // Finally, if this is a noop copy instruction, zap it.
     unsigned SrcReg, DstReg;
     if (TII.isMoveInstr(*MI, SrcReg, DstReg) && SrcReg == DstReg) {
Index: utils/TableGen/CodeGenTarget.cpp
===================================================================
RCS file: /var/cvs/llvm/llvm/utils/TableGen/CodeGenTarget.cpp,v
retrieving revision 1.82
diff -u -r1.82 CodeGenTarget.cpp
--- utils/TableGen/CodeGenTarget.cpp	26 Jan 2007 17:29:20 -0000	1.82
+++ utils/TableGen/CodeGenTarget.cpp	6 Feb 2007 21:09:46 -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;
@@ -284,38 +285,61 @@
 
 
 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('=');
-  assert(pos != std::string::npos && "Unrecognized constraint");
-  std::string Name = CStr.substr(0, pos);
-
-  // TIED_TO: $src1 = $dst
-  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);
-  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);
+  std::pair<unsigned,unsigned> Operand;
+  unsigned ConstraintValue;
+  TOI::OperandConstraint Constraint;
+  std::string::size_type pos;
+
+  if ((pos = CStr.find_first_of('=')) != std::string::npos) {
+    //TIED_TO Constraint
+    Constraint = TOI::TIED_TO;
+    std::string Name = CStr.substr(0, pos);
+    // TIED_TO: $src1 = $dst
+    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);
+    Operand = I->ParseOperandName(DestOpName, false);
+
+    Name = CStr.substr(pos+1);
+    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 > Operand)
+      throw "Illegal tied-to operand constraint '" + CStr + "'";
+    ConstraintValue = I->getFlattenedOperandNumber(SrcOp);
+
+  } else if ((pos = CStr.find("lat")) != std::string::npos) {
+    //READ_LATENCY Constraint
+    Constraint = TOI::READ_LATENCY;
+
+    //get read latency operand
+    std::string Name = CStr.substr(0, pos);
+    std::string::size_type wpos = Name.find_first_of(" \t");
+    if (wpos == std::string::npos)
+      throw "Illegal format for read-latency constraint: '" + CStr + "'";
+    std::string OpName = Name.substr(0, wpos);
+    Operand = I->ParseOperandName(OpName, false);
+
+    //get read latancy value
+    Name = CStr.substr(pos+3);
+    sscanf(Name.c_str(),"%u",&ConstraintValue);
+    if (ConstraintValue <= 0 || ConstraintValue > 3)
+      throw "Invalid read latency value: '" + CStr + "'";
+  } else {
+    throw "Unrecognized constraint";
+  }
+
   // Build the string for the operand.
-  std::string OpConstraint =
-    "((" + utostr(FlatOpNo) + " << 16) | (1 << TOI::TIED_TO))";
+  std::string OpConstraint ="((" + utostr(ConstraintValue) + " << " +
+    utostr(16 + Constraint * 4) + ") | (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;
+  if (!I->OperandList[Operand.first].Constraints[Operand.second].empty())
+    throw "Operands cannot have multiple constraints.";
+  I->OperandList[Operand.first].Constraints[Operand.second] = OpConstraint;
 }
 
 static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) {
_______________________________________________
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Reply via email to