Re: [llvm-commits] [patch] Intruction Constraint DestReg!=SrcReg (for review)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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