Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-02-08 Thread Evan Cheng
 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 -  
  
 1.204
 +++ lib/CodeGen/LiveIntervalAnalysis.cpp  5 Feb 2007 21:05:57 -
 -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.

Please update comment.

 -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);

Is this right? Aren't you in danger of modifying MO?


 -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);
  }

Is this right? I think this is adding live intervals for the spill /  
restore instruction?


 @@ -441,6 +441,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::vectorchar 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;
 +  }
 +}
 +  }

Question: is it necessary to calculate ReadLatency up front rather  
than calculated it on demand (i.e. the rest of the changes in this  
file which use ReadLatency)?

Some nit picks.

1. Please pick identifiers that are more consistent with the rest of  
the LLVM code. e.g. You'll find TID is used for TargetInstrDescriptor  
all over the place.
2. Please use getUseIndex() instead of InstrSlots::Use.
3. Please unsigned instead of char for ReadLatency to match  
getUseIndex(), etc.

// 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 +485,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 +532,7 @@
  for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) {
MachineInstr *Kill 

Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-02-06 Thread Lauro Ramos Venancio

READ_LATENCY patch for review.

Sample of use:
class RegConstraintstring C {
string Constraints = C;
}

// AI_orr - Defines a (op r, r) pattern.
class AI_orrstring 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 -	1.111
+++ include/llvm/Target/TargetInstrInfo.h	5 Feb 2007 21:05:56 -
@@ -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 -	1.204
+++ lib/CodeGen/LiveIntervalAnalysis.cpp	5 Feb 2007 21:05:57 -
@@ -441,6 +441,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::vectorchar 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 +485,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 +532,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 +592,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 

Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-02-06 Thread Lauro Ramos Venancio

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 RegConstraintstring C {
 string Constraints = C;
}

// AI_orr - Defines a (op r, r) pattern.
class AI_orrstring 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 -	1.111
+++ include/llvm/Target/TargetInstrInfo.h	6 Feb 2007 21:09:44 -
@@ -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 -	1.204
+++ lib/CodeGen/LiveIntervalAnalysis.cpp	6 Feb 2007 21:09:44 -
@@ -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::vectorchar 

Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-01-26 Thread Lauro Ramos Venancio
Hi Evan,

Tanks for your review.

 1. I think rather than adding a constraint that says a source operand
 must not be assigned the same register as another. It would be better
 if you add a constraint that says a source operand can be killed at
 issue cycle + n. The live range analysis current assumes every
 source operand read is completed at issue cycle + 0 and write back
 happens at issue cycle + 2. By changing the read latency to 2 you can
 force a source operand to conflict with a destination operand.

Currently, kill moment of a temporary is determined by the last use of
it. With the constraint proposed by you, an intermediary use could
determine kill moment of a temporary. For example, in an use (with
read latency 5) of a temporary followed by other use of it (with read
latency 0), the kill moment would be determined by first use. This
would complicate liveness algorithm. Does any backend need this
constraint?

Maybe, it would be better a constraint that changes the kill moment
from default (can kill at issue cycle + 0) to can kill after
instruction execution. What do you think?

Lauro
___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-01-26 Thread Chris Lattner
On Jan 26, 2007, at 6:09 AM, Lauro Ramos Venancio wrote:
 1. I think rather than adding a constraint that says a source operand
 must not be assigned the same register as another. It would be better
 if you add a constraint that says a source operand can be killed at
 issue cycle + n. The live range analysis current assumes every
 source operand read is completed at issue cycle + 0 and write back
 happens at issue cycle + 2. By changing the read latency to 2 you can
 force a source operand to conflict with a destination operand.

 Currently, kill moment of a temporary is determined by the last use of
 it. With the constraint proposed by you, an intermediary use could
 determine kill moment of a temporary. For example, in an use (with
 read latency 5) of a temporary followed by other use of it (with read
 latency 0), the kill moment would be determined by first use. This
 would complicate liveness algorithm. Does any backend need this
 constraint?

 Maybe, it would be better a constraint that changes the kill moment
 from default (can kill at issue cycle + 0) to can kill after
 instruction execution. What do you think?

I don't have any useful technical input to provide, but this feature  
is quite similar to the GCC  early-clobber constraint modifier:

http://gcc.gnu.org/onlinedocs/gcc/Modifiers.html#Modifiers

It would be nice if the facility we end up with is at least as  
general as it is.

-Chris
___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-01-26 Thread Evan Cheng

On Jan 26, 2007, at 6:09 AM, Lauro Ramos Venancio wrote:

 Hi Evan,

 Tanks for your review.

 1. I think rather than adding a constraint that says a source operand
 must not be assigned the same register as another. It would be better
 if you add a constraint that says a source operand can be killed at
 issue cycle + n. The live range analysis current assumes every
 source operand read is completed at issue cycle + 0 and write back
 happens at issue cycle + 2. By changing the read latency to 2 you can
 force a source operand to conflict with a destination operand.

 Currently, kill moment of a temporary is determined by the last use of
 it. With the constraint proposed by you, an intermediary use could
 determine kill moment of a temporary. For example, in an use (with
 read latency 5) of a temporary followed by other use of it (with read
 latency 0), the kill moment would be determined by first use. This
 would complicate liveness algorithm. Does any backend need this
 constraint?

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


 Maybe, it would be better a constraint that changes the kill moment
 from default (can kill at issue cycle + 0) to can kill after
 instruction execution. What do you think?

 Lauro

___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-01-26 Thread Lauro Ramos Venancio
 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?

Lauro
___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


[llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-01-26 Thread Lauro Ramos Venancio
Hi Chris,

In ARM v4/v5 specification, mul %r0, %r0, %r1 (r0 = r0*r1) is invalid,
but mul %r0, %r1, %r0 is valid. With early-clobber constraint, ARM
backend wouldn't emit the the mul %r0, %r1, %r0. We need a constraint
only for the first source register.

Lauro


2007/1/26, Chris Lattner [EMAIL PROTECTED]:
 On Jan 26, 2007, at 6:09 AM, Lauro Ramos Venancio wrote:
  1. I think rather than adding a constraint that says a source operand
  must not be assigned the same register as another. It would be better
  if you add a constraint that says a source operand can be killed at
  issue cycle + n. The live range analysis current assumes every
  source operand read is completed at issue cycle + 0 and write back
  happens at issue cycle + 2. By changing the read latency to 2 you can
  force a source operand to conflict with a destination operand.
 
  Currently, kill moment of a temporary is determined by the last use of
  it. With the constraint proposed by you, an intermediary use could
  determine kill moment of a temporary. For example, in an use (with
  read latency 5) of a temporary followed by other use of it (with read
  latency 0), the kill moment would be determined by first use. This
  would complicate liveness algorithm. Does any backend need this
  constraint?
 
  Maybe, it would be better a constraint that changes the kill moment
  from default (can kill at issue cycle + 0) to can kill after
  instruction execution. What do you think?

 I don't have any useful technical input to provide, but this feature
 is quite similar to the GCC  early-clobber constraint modifier:

 http://gcc.gnu.org/onlinedocs/gcc/Modifiers.html#Modifiers

 It would be nice if the facility we end up with is at least as
 general as it is.

 -Chris

___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-01-26 Thread Chris Lattner

On Jan 26, 2007, at 1:08 PM, Lauro Ramos Venancio wrote:

 Hi Chris,

 In ARM v4/v5 specification, mul %r0, %r0, %r1 (r0 = r0*r1) is invalid,
 but mul %r0, %r1, %r0 is valid. With early-clobber constraint, ARM
 backend wouldn't emit the the mul %r0, %r1, %r0. We need a constraint
 only for the first source register.

Yep, makes sense.  It would be nice if the mechanism you guys invent  
can *also* handle early-clobber, even if it's not a one-to-one  
mapping.  For example, use of early clobber could translate into a  
bunch of != constraints.

-Chris

___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-01-26 Thread Evan Cheng

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

___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


[llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-01-25 Thread Lauro Ramos Venancio

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

A sample of use of this constraint is following:

class RegConstraintstring C {
 string Constraints = C;
}

// AI_orr - Defines a (op r, r) pattern.
class AI_orrstring 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 -	1.110
+++ include/llvm/Target/TargetInstrInfo.h	25 Jan 2007 21:20:32 -
@@ -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 -	1.204
+++ lib/CodeGen/LiveIntervalAnalysis.cpp	25 Jan 2007 21:20:33 -
@@ -441,6 +441,20 @@
   DOUT  \t\tregister: ; DEBUG(printRegName(interval.reg));
   LiveVariables::VarInfo vi = lv_-getVarInfo(interval.reg);
 
+  std::vectorbool 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 

Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)

2007-01-25 Thread Evan Cheng
Hi Lauro,

Thanks for taking a crack at this! Your work is much appreciated.

However, I have some comments. :-)

1. I think rather than adding a constraint that says a source operand  
must not be assigned the same register as another. It would be better  
if you add a constraint that says a source operand can be killed at  
issue cycle + n. The live range analysis current assumes every  
source operand read is completed at issue cycle + 0 and write back  
happens at issue cycle + 2. By changing the read latency to 2 you can  
force a source operand to conflict with a destination operand.

2. Please write more comments. :-)

Thanks,

Evan

On Jan 25, 2007, at 1:54 PM, Lauro Ramos Venancio wrote:

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

 A sample of use of this constraint is following:

 class RegConstraintstring C {
  string Constraints = C;
 }

 // AI_orr - Defines a (op r, r) pattern.
 class AI_orrstring 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
 constraint.patch
 ___
 llvm-commits mailing list
 llvm-commits@cs.uiuc.edu
 http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits