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