diff --git a/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp b/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp index c774f935e63..d8682e0b5ae 100644 --- a/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp +++ b/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp @@ -12,6 +12,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegInfo.h" #include "llvm/Function.h" #include "Support/SetOperations.h" using std::cerr; @@ -354,7 +355,8 @@ void LiveRangeInfo::coalesceLRs() if (LROfUse == LROfDef) // nothing to merge if they are same continue; - if (MRI.getRegType(LROfDef) == MRI.getRegType(LROfUse)) { + if (MRI.getRegTypeForLR(LROfDef) == + MRI.getRegTypeForLR(LROfUse)) { // If the two RegTypes are the same if (!RCOfDef->getInterference(LROfDef, LROfUse) ) { diff --git a/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp b/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp index 7cacd656073..f08e21fb933 100644 --- a/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp +++ b/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp @@ -18,6 +18,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegInfo.h" #include "llvm/Function.h" #include "llvm/Type.h" #include "llvm/iOther.h" @@ -87,8 +88,8 @@ PhyRegAlloc::PhyRegAlloc(Function *F, const TargetMachine& tm, // create each RegisterClass and put in RegClassList // for (unsigned rc=0; rc != NumOfRegClasses; rc++) - RegClassList.push_back(new RegClass(F, MRI.getMachineRegClass(rc), - &ResColList)); + RegClassList.push_back(new RegClass(F, &tm.getRegInfo(), + MRI.getMachineRegClass(rc))); } @@ -488,7 +489,6 @@ AppendInstructions(std::vector &IAft, } } - void PhyRegAlloc::updateInstruction(MachineInstr* MInst, BasicBlock* BB) { unsigned Opcode = MInst->getOpCode(); @@ -521,21 +521,16 @@ void PhyRegAlloc::updateInstruction(MachineInstr* MInst, BasicBlock* BB) // as a sanity check. OperandsColoredMap[MInst] = true; - // Now insert special instructions (if necessary) for call/return - // instructions. Do this before inserting spill code since some - // registers must be used by outgoing call arguments or the return value - // of a call, and spill code should not use those registers. + // Now insert caller-saving code before/after the call. + // Do this before inserting spill code since some registers must be + // used by save/restore and spill code should not use those registers. // - if (TM.getInstrInfo().isCall(Opcode) || - TM.getInstrInfo().isReturn(Opcode)) { + if (TM.getInstrInfo().isCall(Opcode)) { AddedInstrns &AI = AddedInstrMap[MInst]; - - if (TM.getInstrInfo().isCall(Opcode)) - MRI.colorCallArgs(MInst, LRI, &AI, *this, BB); - else if (TM.getInstrInfo().isReturn(Opcode)) - MRI.colorRetValue(MInst, LRI, &AI); + MRI.insertCallerSavingCode(AI.InstrnsBefore, AI.InstrnsAfter, + MInst, BB, *this); } - + // Now insert spill code for remaining operands not allocated to // registers. This must be done even for call return instructions // since those are not handled by the special code above. @@ -573,7 +568,7 @@ void PhyRegAlloc::updateMachineCode() // Also, fix operands of call/return instructions. // for (MachineBasicBlock::iterator MII = MBB.begin(); MII != MBB.end(); ++MII) - if (!TM.getInstrInfo().isDummyPhiInstr((*MII)->getOpCode())) // ignore Phis + if (!TM.getInstrInfo().isDummyPhiInstr((*MII)->getOpCode()))// ignore Phis updateInstruction(*MII, MBB.getBasicBlock()); // Now, move code out of delay slots of branches and returns if needed. @@ -644,34 +639,46 @@ void PhyRegAlloc::updateMachineCode() // Finally iterate over all instructions in BB and insert before/after // - for (MachineBasicBlock::iterator MII = MBB.begin(); - MII != MBB.end(); ++MII) { - + for (MachineBasicBlock::iterator MII=MBB.begin(); MII != MBB.end(); ++MII) { MachineInstr *MInst = *MII; - unsigned Opcode = MInst->getOpCode(); - + // do not process Phis - if (TM.getInstrInfo().isDummyPhiInstr(Opcode)) + if (TM.getInstrInfo().isDummyPhiInstr(MInst->getOpCode())) continue; - // Now add instructions that the register allocator inserts before/after - // this machine instructions (done only for calls/rets/incoming args) - // We do this here, to ensure that spill for an instruction is inserted - // closest as possible to an instruction (see above insertCode4Spill...) - - // If there are instructions to be added, *before* this machine - // instruction, add them now. - // + // if there are any added instructions... if (AddedInstrMap.count(MInst)) { - PrependInstructions(AddedInstrMap[MInst].InstrnsBefore, MBB, MII,""); - } - - // If there are instructions to be added *after* this machine - // instruction, add them now. All cases with delay slots have been - // c - if (!AddedInstrMap[MInst].InstrnsAfter.empty()) { - AppendInstructions(AddedInstrMap[MInst].InstrnsAfter, MBB, MII,""); - } + AddedInstrns &CallAI = AddedInstrMap[MInst]; + +#ifndef NDEBUG + // Temporary sanity checking code to detect whether the same machine + // instruction is ever inserted twice before/after a call. + // I suspect this is happening but am not sure. --Vikram, 7/1/03. + // + std::set instrsSeen; + for (int i = 0, N = CallAI.InstrnsBefore.size(); i < N; ++i) { + assert(instrsSeen.count(CallAI.InstrnsBefore[i]) == 0 && + "Duplicate machine instruction in InstrnsBefore!"); + instrsSeen.insert(CallAI.InstrnsBefore[i]); + } + for (int i = 0, N = CallAI.InstrnsAfter.size(); i < N; ++i) { + assert(instrsSeen.count(CallAI.InstrnsAfter[i]) == 0 && + "Duplicate machine instruction in InstrnsBefore/After!"); + instrsSeen.insert(CallAI.InstrnsAfter[i]); + } +#endif + + // Now add the instructions before/after this MI. + // We do this here to ensure that spill for an instruction is inserted + // as close as possible to an instruction (see above insertCode4Spill) + // + if (! CallAI.InstrnsBefore.empty()) + PrependInstructions(CallAI.InstrnsBefore, MBB, MII,""); + + if (! CallAI.InstrnsAfter.empty()) + AppendInstructions(CallAI.InstrnsAfter, MBB, MII,""); + + } // if there are any added instructions } // for each machine instruction } @@ -687,6 +694,7 @@ void PhyRegAlloc::updateMachineCode() // used by other spilled operands of the same instruction. Then it uses // this register temporarily to accomodate the spilled value. //---------------------------------------------------------------------------- + void PhyRegAlloc::insertCode4SpilledLR(const LiveRange *LR, MachineInstr *MInst, const BasicBlock *BB, @@ -700,7 +708,7 @@ void PhyRegAlloc::insertCode4SpilledLR(const LiveRange *LR, MachineOperand& Op = MInst->getOperand(OpNum); bool isDef = Op.opIsDefOnly(); bool isDefAndUse = Op.opIsDefAndUse(); - unsigned RegType = MRI.getRegType(LR); + unsigned RegType = MRI.getRegTypeForLR(LR); int SpillOff = LR->getSpillOffFromFP(); RegClass *RC = LR->getRegClass(); const ValueSet &LVSetBef = LVI->getLiveVarSetBeforeMInst(MInst, BB); @@ -793,7 +801,7 @@ int PhyRegAlloc::getUsableUniRegAtMI(const int RegType, RegClass* RC = getRegClassByID(MRI.getRegClassIDOfRegType(RegType)); - int RegU = getUnusedUniRegAtMI(RC, MInst, LVSetBef); + int RegU = getUnusedUniRegAtMI(RC, RegType, MInst, LVSetBef); if (RegU == -1) { // we couldn't find an unused register. Generate code to free up a reg by @@ -801,7 +809,7 @@ int PhyRegAlloc::getUsableUniRegAtMI(const int RegType, int TmpOff = MF.getInfo()->pushTempValue(MRI.getSpilledRegSize(RegType)); - RegU = getUniRegNotUsedByThisInst(RC, MInst); + RegU = getUniRegNotUsedByThisInst(RC, RegType, MInst); // Check if we need a scratch register to copy this register to memory. int scratchRegType = -1; @@ -841,40 +849,37 @@ int PhyRegAlloc::getUsableUniRegAtMI(const int RegType, //---------------------------------------------------------------------------- int PhyRegAlloc::getUnusedUniRegAtMI(RegClass *RC, - const MachineInstr *MInst, - const ValueSet *LVSetBef) { - - unsigned NumAvailRegs = RC->getNumOfAvailRegs(); + const int RegType, + const MachineInstr *MInst, + const ValueSet *LVSetBef) { - std::vector &IsColorUsedArr = RC->getIsColorUsedArr(); + RC->clearColorsUsed(); // Reset array - for (unsigned i=0; i < NumAvailRegs; i++) // Reset array - IsColorUsedArr[i] = false; - ValueSet::const_iterator LIt = LVSetBef->begin(); // for each live var in live variable set after machine inst for ( ; LIt != LVSetBef->end(); ++LIt) { - // get the live range corresponding to live var + // get the live range corresponding to live var, and its RegClass LiveRange *const LRofLV = LRI.getLiveRangeForValue(*LIt ); // LR can be null if it is a const since a const // doesn't have a dominating def - see Assumptions above - if (LRofLV && LRofLV->getRegClass() == RC && LRofLV->hasColor() ) - IsColorUsedArr[ LRofLV->getColor() ] = true; + if (LRofLV && LRofLV->getRegClass() == RC && LRofLV->hasColor()) + RC->markColorsUsed(LRofLV->getColor(), + MRI.getRegTypeForLR(LRofLV), RegType); } // It is possible that one operand of this MInst was already spilled // and it received some register temporarily. If that's the case, // it is recorded in machine operand. We must skip such registers. // - setRelRegsUsedByThisInst(RC, MInst); + setRelRegsUsedByThisInst(RC, RegType, MInst); + + int unusedReg = RC->getUnusedColor(RegType); // find first unused color + if (unusedReg >= 0) + return MRI.getUnifiedRegNum(RC->getID(), unusedReg); - for (unsigned c=0; c < NumAvailRegs; c++) // find first unused color - if (!IsColorUsedArr[c]) - return MRI.getUnifiedRegNum(RC->getID(), c); - return -1; } @@ -884,22 +889,18 @@ int PhyRegAlloc::getUnusedUniRegAtMI(RegClass *RC, // by operands of a machine instruction. Returns the unified reg number. //---------------------------------------------------------------------------- int PhyRegAlloc::getUniRegNotUsedByThisInst(RegClass *RC, + const int RegType, const MachineInstr *MInst) { + RC->clearColorsUsed(); - vector &IsColorUsedArr = RC->getIsColorUsedArr(); - unsigned NumAvailRegs = RC->getNumOfAvailRegs(); + setRelRegsUsedByThisInst(RC, RegType, MInst); - for (unsigned i=0; i < NumAvailRegs ; i++) // Reset array - IsColorUsedArr[i] = false; + // find the first unused color + int unusedReg = RC->getUnusedColor(RegType); + assert(unusedReg >= 0 && + "FATAL: No free register could be found in reg class!!"); - setRelRegsUsedByThisInst(RC, MInst); - - for (unsigned c=0; c < RC->getNumOfAvailRegs(); c++)// find first unused color - if (!IsColorUsedArr[c]) - return MRI.getUnifiedRegNum(RC->getID(), c); - - assert(0 && "FATAL: No free register could be found in reg class!!"); - return 0; + return MRI.getUnifiedRegNum(RC->getID(), unusedReg); } @@ -908,30 +909,26 @@ int PhyRegAlloc::getUniRegNotUsedByThisInst(RegClass *RC, // It sets the bits corresponding to the registers used by this machine // instructions. Both explicit and implicit operands are set. //---------------------------------------------------------------------------- + void PhyRegAlloc::setRelRegsUsedByThisInst(RegClass *RC, + const int RegType, const MachineInstr *MInst ) { assert(OperandsColoredMap[MInst] == true && "Illegal to call setRelRegsUsedByThisInst() until colored operands " "are marked for an instruction."); - vector &IsColorUsedArr = RC->getIsColorUsedArr(); - // Add the registers already marked as used by the instruction. // This should include any scratch registers that are used to save // values across the instruction (e.g., for saving state register values). const std::set ®sUsed = MInst->getRegsUsed(); - for (std::set::iterator I=regsUsed.begin(), E=regsUsed.end(); I != E; ++I) + for (std::set::iterator I=regsUsed.begin(),E=regsUsed.end(); I != E; ++I) { int i = *I; unsigned classId = 0; int classRegNum = MRI.getClassRegNum(i, classId); if (RC->getID() == classId) - { - assert(classRegNum < (int) IsColorUsedArr.size() && - "Illegal register number for this reg class?"); - IsColorUsedArr[classRegNum] = true; - } + RC->markColorsUsed(classRegNum, RegType, RegType); } // If there are implicit references, mark their allocated regs as well @@ -941,7 +938,8 @@ void PhyRegAlloc::setRelRegsUsedByThisInst(RegClass *RC, LRofImpRef = LRI.getLiveRangeForValue(MInst->getImplicitRef(z))) if (LRofImpRef->hasColor()) // this implicit reference is in a LR that received a color - IsColorUsedArr[LRofImpRef->getColor()] = true; + RC->markColorsUsed(LRofImpRef->getColor(), + MRI.getRegTypeForLR(LRofImpRef), RegType); } diff --git a/lib/CodeGen/RegAlloc/RegClass.cpp b/lib/CodeGen/RegAlloc/RegClass.cpp index ba03449ca65..6e461fea428 100644 --- a/lib/CodeGen/RegAlloc/RegClass.cpp +++ b/lib/CodeGen/RegAlloc/RegClass.cpp @@ -7,6 +7,7 @@ #include "RegClass.h" #include "RegAllocCommon.h" #include "llvm/CodeGen/IGNode.h" +#include "llvm/Target/TargetRegInfo.h" using std::cerr; //---------------------------------------------------------------------------- @@ -14,14 +15,15 @@ using std::cerr; // createInterferenceGraph() above. //---------------------------------------------------------------------------- RegClass::RegClass(const Function *M, - const TargetRegClassInfo *Mrc, - const ReservedColorListType *RCL) - : Meth(M), MRC(Mrc), RegClassID( Mrc->getRegClassID() ), - IG(this), IGNodeStack(), ReservedColorList(RCL) { + const TargetRegInfo *_MRI_, + const TargetRegClassInfo *_MRC_) + : Meth(M), MRI(_MRI_), MRC(_MRC_), + RegClassID( _MRC_->getRegClassID() ), + IG(this), IGNodeStack() { if( DEBUG_RA >= RA_DEBUG_Interference) cerr << "Created Reg Class: " << RegClassID << "\n"; - IsColorUsedArr.resize(Mrc->getNumOfAllRegs()); + IsColorUsedArr.resize(MRC->getNumOfAllRegs()); } @@ -133,7 +135,7 @@ bool RegClass::pushUnconstrainedIGNodes() if( IGNode->isOnStack() ) continue; // if the degree of IGNode is lower - if( (unsigned) IGNode->getCurDegree() < MRC->getNumOfAvailRegs() ) { + if( (unsigned) IGNode->getCurDegree() < MRC->getNumOfAvailRegs()) { IGNodeStack.push( IGNode ); // push IGNode on to the stack IGNode->pushOnStack(); // set OnStack and dec deg of neighs @@ -205,17 +207,8 @@ void RegClass::colorIGNode(IGNode *const Node) if( ! Node->hasColor() ) { // not colored as an arg etc. - // init all elements of to IsColorUsedAr false; - // - for (unsigned i=0; i < MRC->getNumOfAllRegs(); i++) - IsColorUsedArr[i] = false; - - // init all reserved_regs to true - we can't use them - // - for( unsigned i=0; i < ReservedColorList->size() ; i++) { - IsColorUsedArr[(*ReservedColorList)[i]] = true; - } + clearColorsUsed(); // initialize all colors used by neighbors of this node to true LiveRange *LR = Node->getParentLR(); @@ -224,15 +217,22 @@ void RegClass::colorIGNode(IGNode *const Node) IGNode *NeighIGNode = Node->getAdjIGNode(n); LiveRange *NeighLR = NeighIGNode->getParentLR(); - if (NeighLR->hasColor()) { // if has a color - IsColorUsedArr[NeighLR->getColor()] = true; // mark color as used - } else if (NeighLR->hasSuggestedColor() && - NeighLR->isSuggestedColorUsable()) { - // this color is suggested for the neighbour, so don't use it - IsColorUsedArr[NeighLR->getSuggestedColor()] = true; - } + // Don't use a color if it is in use by the neighbour, + // or is suggested for use by the neighbour, + // markColorsUsed() should be given the color and the reg type for + // LR, not for NeighLR, because it should mark registers used based on + // the type we are looking for, not on the regType for the neighbour. + if (NeighLR->hasColor()) + this->markColorsUsed(NeighLR->getColor(), + MRI->getRegTypeForLR(NeighLR), + MRI->getRegTypeForLR(LR)); // use LR, not NeighLR + else if (NeighLR->hasSuggestedColor() && + NeighLR->isSuggestedColorUsable()) + this->markColorsUsed(NeighLR->getSuggestedColor(), + MRI->getRegTypeForLR(NeighLR), + MRI->getRegTypeForLR(LR)); // use LR, not NeighLR } - + // call the target specific code for coloring // MRC->colorIGNode(Node, IsColorUsedArr); diff --git a/lib/CodeGen/RegAlloc/RegClass.h b/lib/CodeGen/RegAlloc/RegClass.h index 7e1eb6590df..aa5b29da385 100644 --- a/lib/CodeGen/RegAlloc/RegClass.h +++ b/lib/CodeGen/RegAlloc/RegClass.h @@ -13,8 +13,6 @@ #include class TargetRegClassInfo; -typedef std::vector ReservedColorListType; - //----------------------------------------------------------------------------- // Class RegClass @@ -35,18 +33,14 @@ typedef std::vector ReservedColorListType; //----------------------------------------------------------------------------- class RegClass { const Function *const Meth; // Function we are working on - const TargetRegClassInfo *const MRC; // corresponding MRC + const TargetRegInfo *MRI; // Machine register information + const TargetRegClassInfo *const MRC; // Machine reg. class for this RegClass const unsigned RegClassID; // my int ID InterferenceGraph IG; // Interference graph - constructed by // buildInterferenceGraph std::stack IGNodeStack; // the stack used for coloring - // ReservedColorList - for passing registers that are pre-allocated and cannot - // be used by the register allocator for this function. - // - const ReservedColorListType *const ReservedColorList; - // IsColorUsedArr - An array used for coloring each node. This array must be // of size MRC->getNumOfAllRegs(). Allocated once in the constructor for // efficiency. @@ -65,12 +59,24 @@ class RegClass { void colorIGNode(IGNode *const Node); + // This directly marks the colors used by a particular register number + // within the register class. External users should use the public + // versions of this function below. + inline void markColorUsed(unsigned classRegNum) { + assert(classRegNum < IsColorUsedArr.size() && "Invalid register used?"); + IsColorUsedArr[classRegNum] = true; + } + + inline bool isColorUsed(unsigned regNum) const { + assert(regNum < IsColorUsedArr.size() && "Invalid register used?"); + return IsColorUsedArr[regNum]; + } public: RegClass(const Function *M, - const TargetRegClassInfo *MRC, - const ReservedColorListType *RCL = 0); + const TargetRegInfo *_MRI_, + const TargetRegClassInfo *_MRC_); inline void createInterferenceGraph() { IG.createGraph(); } @@ -78,6 +84,8 @@ class RegClass { inline const unsigned getID() const { return RegClassID; } + inline const TargetRegClassInfo* getTargetRegClass() const { return MRC; } + // main method called for coloring regs // void colorAllRegs(); @@ -105,8 +113,18 @@ class RegClass { { IG.mergeIGNodesOfLRs(LR1, LR2); } - inline std::vector &getIsColorUsedArr() { return IsColorUsedArr; } - + inline void clearColorsUsed() { + IsColorUsedArr.clear(); + IsColorUsedArr.resize(MRC->getNumOfAllRegs()); + } + inline void markColorsUsed(unsigned ClassRegNum, + int UserRegType, + int RegTypeWanted) { + MRC->markColorsUsed(ClassRegNum, UserRegType, RegTypeWanted,IsColorUsedArr); + } + inline int getUnusedColor(int machineRegType) const { + return MRC->findUnusedColor(machineRegType, IsColorUsedArr); + } void printIGNodeList() const; void printIG(); diff --git a/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp b/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp index c774f935e63..d8682e0b5ae 100644 --- a/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp +++ b/lib/Target/SparcV9/RegAlloc/LiveRangeInfo.cpp @@ -12,6 +12,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegInfo.h" #include "llvm/Function.h" #include "Support/SetOperations.h" using std::cerr; @@ -354,7 +355,8 @@ void LiveRangeInfo::coalesceLRs() if (LROfUse == LROfDef) // nothing to merge if they are same continue; - if (MRI.getRegType(LROfDef) == MRI.getRegType(LROfUse)) { + if (MRI.getRegTypeForLR(LROfDef) == + MRI.getRegTypeForLR(LROfUse)) { // If the two RegTypes are the same if (!RCOfDef->getInterference(LROfDef, LROfUse) ) { diff --git a/lib/Target/SparcV9/RegAlloc/PhyRegAlloc.cpp b/lib/Target/SparcV9/RegAlloc/PhyRegAlloc.cpp index 7cacd656073..f08e21fb933 100644 --- a/lib/Target/SparcV9/RegAlloc/PhyRegAlloc.cpp +++ b/lib/Target/SparcV9/RegAlloc/PhyRegAlloc.cpp @@ -18,6 +18,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegInfo.h" #include "llvm/Function.h" #include "llvm/Type.h" #include "llvm/iOther.h" @@ -87,8 +88,8 @@ PhyRegAlloc::PhyRegAlloc(Function *F, const TargetMachine& tm, // create each RegisterClass and put in RegClassList // for (unsigned rc=0; rc != NumOfRegClasses; rc++) - RegClassList.push_back(new RegClass(F, MRI.getMachineRegClass(rc), - &ResColList)); + RegClassList.push_back(new RegClass(F, &tm.getRegInfo(), + MRI.getMachineRegClass(rc))); } @@ -488,7 +489,6 @@ AppendInstructions(std::vector &IAft, } } - void PhyRegAlloc::updateInstruction(MachineInstr* MInst, BasicBlock* BB) { unsigned Opcode = MInst->getOpCode(); @@ -521,21 +521,16 @@ void PhyRegAlloc::updateInstruction(MachineInstr* MInst, BasicBlock* BB) // as a sanity check. OperandsColoredMap[MInst] = true; - // Now insert special instructions (if necessary) for call/return - // instructions. Do this before inserting spill code since some - // registers must be used by outgoing call arguments or the return value - // of a call, and spill code should not use those registers. + // Now insert caller-saving code before/after the call. + // Do this before inserting spill code since some registers must be + // used by save/restore and spill code should not use those registers. // - if (TM.getInstrInfo().isCall(Opcode) || - TM.getInstrInfo().isReturn(Opcode)) { + if (TM.getInstrInfo().isCall(Opcode)) { AddedInstrns &AI = AddedInstrMap[MInst]; - - if (TM.getInstrInfo().isCall(Opcode)) - MRI.colorCallArgs(MInst, LRI, &AI, *this, BB); - else if (TM.getInstrInfo().isReturn(Opcode)) - MRI.colorRetValue(MInst, LRI, &AI); + MRI.insertCallerSavingCode(AI.InstrnsBefore, AI.InstrnsAfter, + MInst, BB, *this); } - + // Now insert spill code for remaining operands not allocated to // registers. This must be done even for call return instructions // since those are not handled by the special code above. @@ -573,7 +568,7 @@ void PhyRegAlloc::updateMachineCode() // Also, fix operands of call/return instructions. // for (MachineBasicBlock::iterator MII = MBB.begin(); MII != MBB.end(); ++MII) - if (!TM.getInstrInfo().isDummyPhiInstr((*MII)->getOpCode())) // ignore Phis + if (!TM.getInstrInfo().isDummyPhiInstr((*MII)->getOpCode()))// ignore Phis updateInstruction(*MII, MBB.getBasicBlock()); // Now, move code out of delay slots of branches and returns if needed. @@ -644,34 +639,46 @@ void PhyRegAlloc::updateMachineCode() // Finally iterate over all instructions in BB and insert before/after // - for (MachineBasicBlock::iterator MII = MBB.begin(); - MII != MBB.end(); ++MII) { - + for (MachineBasicBlock::iterator MII=MBB.begin(); MII != MBB.end(); ++MII) { MachineInstr *MInst = *MII; - unsigned Opcode = MInst->getOpCode(); - + // do not process Phis - if (TM.getInstrInfo().isDummyPhiInstr(Opcode)) + if (TM.getInstrInfo().isDummyPhiInstr(MInst->getOpCode())) continue; - // Now add instructions that the register allocator inserts before/after - // this machine instructions (done only for calls/rets/incoming args) - // We do this here, to ensure that spill for an instruction is inserted - // closest as possible to an instruction (see above insertCode4Spill...) - - // If there are instructions to be added, *before* this machine - // instruction, add them now. - // + // if there are any added instructions... if (AddedInstrMap.count(MInst)) { - PrependInstructions(AddedInstrMap[MInst].InstrnsBefore, MBB, MII,""); - } - - // If there are instructions to be added *after* this machine - // instruction, add them now. All cases with delay slots have been - // c - if (!AddedInstrMap[MInst].InstrnsAfter.empty()) { - AppendInstructions(AddedInstrMap[MInst].InstrnsAfter, MBB, MII,""); - } + AddedInstrns &CallAI = AddedInstrMap[MInst]; + +#ifndef NDEBUG + // Temporary sanity checking code to detect whether the same machine + // instruction is ever inserted twice before/after a call. + // I suspect this is happening but am not sure. --Vikram, 7/1/03. + // + std::set instrsSeen; + for (int i = 0, N = CallAI.InstrnsBefore.size(); i < N; ++i) { + assert(instrsSeen.count(CallAI.InstrnsBefore[i]) == 0 && + "Duplicate machine instruction in InstrnsBefore!"); + instrsSeen.insert(CallAI.InstrnsBefore[i]); + } + for (int i = 0, N = CallAI.InstrnsAfter.size(); i < N; ++i) { + assert(instrsSeen.count(CallAI.InstrnsAfter[i]) == 0 && + "Duplicate machine instruction in InstrnsBefore/After!"); + instrsSeen.insert(CallAI.InstrnsAfter[i]); + } +#endif + + // Now add the instructions before/after this MI. + // We do this here to ensure that spill for an instruction is inserted + // as close as possible to an instruction (see above insertCode4Spill) + // + if (! CallAI.InstrnsBefore.empty()) + PrependInstructions(CallAI.InstrnsBefore, MBB, MII,""); + + if (! CallAI.InstrnsAfter.empty()) + AppendInstructions(CallAI.InstrnsAfter, MBB, MII,""); + + } // if there are any added instructions } // for each machine instruction } @@ -687,6 +694,7 @@ void PhyRegAlloc::updateMachineCode() // used by other spilled operands of the same instruction. Then it uses // this register temporarily to accomodate the spilled value. //---------------------------------------------------------------------------- + void PhyRegAlloc::insertCode4SpilledLR(const LiveRange *LR, MachineInstr *MInst, const BasicBlock *BB, @@ -700,7 +708,7 @@ void PhyRegAlloc::insertCode4SpilledLR(const LiveRange *LR, MachineOperand& Op = MInst->getOperand(OpNum); bool isDef = Op.opIsDefOnly(); bool isDefAndUse = Op.opIsDefAndUse(); - unsigned RegType = MRI.getRegType(LR); + unsigned RegType = MRI.getRegTypeForLR(LR); int SpillOff = LR->getSpillOffFromFP(); RegClass *RC = LR->getRegClass(); const ValueSet &LVSetBef = LVI->getLiveVarSetBeforeMInst(MInst, BB); @@ -793,7 +801,7 @@ int PhyRegAlloc::getUsableUniRegAtMI(const int RegType, RegClass* RC = getRegClassByID(MRI.getRegClassIDOfRegType(RegType)); - int RegU = getUnusedUniRegAtMI(RC, MInst, LVSetBef); + int RegU = getUnusedUniRegAtMI(RC, RegType, MInst, LVSetBef); if (RegU == -1) { // we couldn't find an unused register. Generate code to free up a reg by @@ -801,7 +809,7 @@ int PhyRegAlloc::getUsableUniRegAtMI(const int RegType, int TmpOff = MF.getInfo()->pushTempValue(MRI.getSpilledRegSize(RegType)); - RegU = getUniRegNotUsedByThisInst(RC, MInst); + RegU = getUniRegNotUsedByThisInst(RC, RegType, MInst); // Check if we need a scratch register to copy this register to memory. int scratchRegType = -1; @@ -841,40 +849,37 @@ int PhyRegAlloc::getUsableUniRegAtMI(const int RegType, //---------------------------------------------------------------------------- int PhyRegAlloc::getUnusedUniRegAtMI(RegClass *RC, - const MachineInstr *MInst, - const ValueSet *LVSetBef) { - - unsigned NumAvailRegs = RC->getNumOfAvailRegs(); + const int RegType, + const MachineInstr *MInst, + const ValueSet *LVSetBef) { - std::vector &IsColorUsedArr = RC->getIsColorUsedArr(); + RC->clearColorsUsed(); // Reset array - for (unsigned i=0; i < NumAvailRegs; i++) // Reset array - IsColorUsedArr[i] = false; - ValueSet::const_iterator LIt = LVSetBef->begin(); // for each live var in live variable set after machine inst for ( ; LIt != LVSetBef->end(); ++LIt) { - // get the live range corresponding to live var + // get the live range corresponding to live var, and its RegClass LiveRange *const LRofLV = LRI.getLiveRangeForValue(*LIt ); // LR can be null if it is a const since a const // doesn't have a dominating def - see Assumptions above - if (LRofLV && LRofLV->getRegClass() == RC && LRofLV->hasColor() ) - IsColorUsedArr[ LRofLV->getColor() ] = true; + if (LRofLV && LRofLV->getRegClass() == RC && LRofLV->hasColor()) + RC->markColorsUsed(LRofLV->getColor(), + MRI.getRegTypeForLR(LRofLV), RegType); } // It is possible that one operand of this MInst was already spilled // and it received some register temporarily. If that's the case, // it is recorded in machine operand. We must skip such registers. // - setRelRegsUsedByThisInst(RC, MInst); + setRelRegsUsedByThisInst(RC, RegType, MInst); + + int unusedReg = RC->getUnusedColor(RegType); // find first unused color + if (unusedReg >= 0) + return MRI.getUnifiedRegNum(RC->getID(), unusedReg); - for (unsigned c=0; c < NumAvailRegs; c++) // find first unused color - if (!IsColorUsedArr[c]) - return MRI.getUnifiedRegNum(RC->getID(), c); - return -1; } @@ -884,22 +889,18 @@ int PhyRegAlloc::getUnusedUniRegAtMI(RegClass *RC, // by operands of a machine instruction. Returns the unified reg number. //---------------------------------------------------------------------------- int PhyRegAlloc::getUniRegNotUsedByThisInst(RegClass *RC, + const int RegType, const MachineInstr *MInst) { + RC->clearColorsUsed(); - vector &IsColorUsedArr = RC->getIsColorUsedArr(); - unsigned NumAvailRegs = RC->getNumOfAvailRegs(); + setRelRegsUsedByThisInst(RC, RegType, MInst); - for (unsigned i=0; i < NumAvailRegs ; i++) // Reset array - IsColorUsedArr[i] = false; + // find the first unused color + int unusedReg = RC->getUnusedColor(RegType); + assert(unusedReg >= 0 && + "FATAL: No free register could be found in reg class!!"); - setRelRegsUsedByThisInst(RC, MInst); - - for (unsigned c=0; c < RC->getNumOfAvailRegs(); c++)// find first unused color - if (!IsColorUsedArr[c]) - return MRI.getUnifiedRegNum(RC->getID(), c); - - assert(0 && "FATAL: No free register could be found in reg class!!"); - return 0; + return MRI.getUnifiedRegNum(RC->getID(), unusedReg); } @@ -908,30 +909,26 @@ int PhyRegAlloc::getUniRegNotUsedByThisInst(RegClass *RC, // It sets the bits corresponding to the registers used by this machine // instructions. Both explicit and implicit operands are set. //---------------------------------------------------------------------------- + void PhyRegAlloc::setRelRegsUsedByThisInst(RegClass *RC, + const int RegType, const MachineInstr *MInst ) { assert(OperandsColoredMap[MInst] == true && "Illegal to call setRelRegsUsedByThisInst() until colored operands " "are marked for an instruction."); - vector &IsColorUsedArr = RC->getIsColorUsedArr(); - // Add the registers already marked as used by the instruction. // This should include any scratch registers that are used to save // values across the instruction (e.g., for saving state register values). const std::set ®sUsed = MInst->getRegsUsed(); - for (std::set::iterator I=regsUsed.begin(), E=regsUsed.end(); I != E; ++I) + for (std::set::iterator I=regsUsed.begin(),E=regsUsed.end(); I != E; ++I) { int i = *I; unsigned classId = 0; int classRegNum = MRI.getClassRegNum(i, classId); if (RC->getID() == classId) - { - assert(classRegNum < (int) IsColorUsedArr.size() && - "Illegal register number for this reg class?"); - IsColorUsedArr[classRegNum] = true; - } + RC->markColorsUsed(classRegNum, RegType, RegType); } // If there are implicit references, mark their allocated regs as well @@ -941,7 +938,8 @@ void PhyRegAlloc::setRelRegsUsedByThisInst(RegClass *RC, LRofImpRef = LRI.getLiveRangeForValue(MInst->getImplicitRef(z))) if (LRofImpRef->hasColor()) // this implicit reference is in a LR that received a color - IsColorUsedArr[LRofImpRef->getColor()] = true; + RC->markColorsUsed(LRofImpRef->getColor(), + MRI.getRegTypeForLR(LRofImpRef), RegType); } diff --git a/lib/Target/SparcV9/RegAlloc/RegClass.cpp b/lib/Target/SparcV9/RegAlloc/RegClass.cpp index ba03449ca65..6e461fea428 100644 --- a/lib/Target/SparcV9/RegAlloc/RegClass.cpp +++ b/lib/Target/SparcV9/RegAlloc/RegClass.cpp @@ -7,6 +7,7 @@ #include "RegClass.h" #include "RegAllocCommon.h" #include "llvm/CodeGen/IGNode.h" +#include "llvm/Target/TargetRegInfo.h" using std::cerr; //---------------------------------------------------------------------------- @@ -14,14 +15,15 @@ using std::cerr; // createInterferenceGraph() above. //---------------------------------------------------------------------------- RegClass::RegClass(const Function *M, - const TargetRegClassInfo *Mrc, - const ReservedColorListType *RCL) - : Meth(M), MRC(Mrc), RegClassID( Mrc->getRegClassID() ), - IG(this), IGNodeStack(), ReservedColorList(RCL) { + const TargetRegInfo *_MRI_, + const TargetRegClassInfo *_MRC_) + : Meth(M), MRI(_MRI_), MRC(_MRC_), + RegClassID( _MRC_->getRegClassID() ), + IG(this), IGNodeStack() { if( DEBUG_RA >= RA_DEBUG_Interference) cerr << "Created Reg Class: " << RegClassID << "\n"; - IsColorUsedArr.resize(Mrc->getNumOfAllRegs()); + IsColorUsedArr.resize(MRC->getNumOfAllRegs()); } @@ -133,7 +135,7 @@ bool RegClass::pushUnconstrainedIGNodes() if( IGNode->isOnStack() ) continue; // if the degree of IGNode is lower - if( (unsigned) IGNode->getCurDegree() < MRC->getNumOfAvailRegs() ) { + if( (unsigned) IGNode->getCurDegree() < MRC->getNumOfAvailRegs()) { IGNodeStack.push( IGNode ); // push IGNode on to the stack IGNode->pushOnStack(); // set OnStack and dec deg of neighs @@ -205,17 +207,8 @@ void RegClass::colorIGNode(IGNode *const Node) if( ! Node->hasColor() ) { // not colored as an arg etc. - // init all elements of to IsColorUsedAr false; - // - for (unsigned i=0; i < MRC->getNumOfAllRegs(); i++) - IsColorUsedArr[i] = false; - - // init all reserved_regs to true - we can't use them - // - for( unsigned i=0; i < ReservedColorList->size() ; i++) { - IsColorUsedArr[(*ReservedColorList)[i]] = true; - } + clearColorsUsed(); // initialize all colors used by neighbors of this node to true LiveRange *LR = Node->getParentLR(); @@ -224,15 +217,22 @@ void RegClass::colorIGNode(IGNode *const Node) IGNode *NeighIGNode = Node->getAdjIGNode(n); LiveRange *NeighLR = NeighIGNode->getParentLR(); - if (NeighLR->hasColor()) { // if has a color - IsColorUsedArr[NeighLR->getColor()] = true; // mark color as used - } else if (NeighLR->hasSuggestedColor() && - NeighLR->isSuggestedColorUsable()) { - // this color is suggested for the neighbour, so don't use it - IsColorUsedArr[NeighLR->getSuggestedColor()] = true; - } + // Don't use a color if it is in use by the neighbour, + // or is suggested for use by the neighbour, + // markColorsUsed() should be given the color and the reg type for + // LR, not for NeighLR, because it should mark registers used based on + // the type we are looking for, not on the regType for the neighbour. + if (NeighLR->hasColor()) + this->markColorsUsed(NeighLR->getColor(), + MRI->getRegTypeForLR(NeighLR), + MRI->getRegTypeForLR(LR)); // use LR, not NeighLR + else if (NeighLR->hasSuggestedColor() && + NeighLR->isSuggestedColorUsable()) + this->markColorsUsed(NeighLR->getSuggestedColor(), + MRI->getRegTypeForLR(NeighLR), + MRI->getRegTypeForLR(LR)); // use LR, not NeighLR } - + // call the target specific code for coloring // MRC->colorIGNode(Node, IsColorUsedArr); diff --git a/lib/Target/SparcV9/RegAlloc/RegClass.h b/lib/Target/SparcV9/RegAlloc/RegClass.h index 7e1eb6590df..aa5b29da385 100644 --- a/lib/Target/SparcV9/RegAlloc/RegClass.h +++ b/lib/Target/SparcV9/RegAlloc/RegClass.h @@ -13,8 +13,6 @@ #include class TargetRegClassInfo; -typedef std::vector ReservedColorListType; - //----------------------------------------------------------------------------- // Class RegClass @@ -35,18 +33,14 @@ typedef std::vector ReservedColorListType; //----------------------------------------------------------------------------- class RegClass { const Function *const Meth; // Function we are working on - const TargetRegClassInfo *const MRC; // corresponding MRC + const TargetRegInfo *MRI; // Machine register information + const TargetRegClassInfo *const MRC; // Machine reg. class for this RegClass const unsigned RegClassID; // my int ID InterferenceGraph IG; // Interference graph - constructed by // buildInterferenceGraph std::stack IGNodeStack; // the stack used for coloring - // ReservedColorList - for passing registers that are pre-allocated and cannot - // be used by the register allocator for this function. - // - const ReservedColorListType *const ReservedColorList; - // IsColorUsedArr - An array used for coloring each node. This array must be // of size MRC->getNumOfAllRegs(). Allocated once in the constructor for // efficiency. @@ -65,12 +59,24 @@ class RegClass { void colorIGNode(IGNode *const Node); + // This directly marks the colors used by a particular register number + // within the register class. External users should use the public + // versions of this function below. + inline void markColorUsed(unsigned classRegNum) { + assert(classRegNum < IsColorUsedArr.size() && "Invalid register used?"); + IsColorUsedArr[classRegNum] = true; + } + + inline bool isColorUsed(unsigned regNum) const { + assert(regNum < IsColorUsedArr.size() && "Invalid register used?"); + return IsColorUsedArr[regNum]; + } public: RegClass(const Function *M, - const TargetRegClassInfo *MRC, - const ReservedColorListType *RCL = 0); + const TargetRegInfo *_MRI_, + const TargetRegClassInfo *_MRC_); inline void createInterferenceGraph() { IG.createGraph(); } @@ -78,6 +84,8 @@ class RegClass { inline const unsigned getID() const { return RegClassID; } + inline const TargetRegClassInfo* getTargetRegClass() const { return MRC; } + // main method called for coloring regs // void colorAllRegs(); @@ -105,8 +113,18 @@ class RegClass { { IG.mergeIGNodesOfLRs(LR1, LR2); } - inline std::vector &getIsColorUsedArr() { return IsColorUsedArr; } - + inline void clearColorsUsed() { + IsColorUsedArr.clear(); + IsColorUsedArr.resize(MRC->getNumOfAllRegs()); + } + inline void markColorsUsed(unsigned ClassRegNum, + int UserRegType, + int RegTypeWanted) { + MRC->markColorsUsed(ClassRegNum, UserRegType, RegTypeWanted,IsColorUsedArr); + } + inline int getUnusedColor(int machineRegType) const { + return MRC->findUnusedColor(machineRegType, IsColorUsedArr); + } void printIGNodeList() const; void printIG();