From 321ed7be930601dbf0584dad859780803bc45a5a Mon Sep 17 00:00:00 2001 From: Ruchira Sasanka Date: Sun, 28 Oct 2001 18:12:02 +0000 Subject: [PATCH] Added spill code support; moved insertCallerSaving to SparRegInfo since we need to handle %ccr reg in a special way. llvm-svn: 990 --- llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp | 385 ++++++++++++++++++---- 1 file changed, 319 insertions(+), 66 deletions(-) diff --git a/llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp b/llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp index 780f70d7f159..3b61e1e6b781 100644 --- a/llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp +++ b/llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp @@ -1,5 +1,10 @@ #include "llvm/CodeGen/PhyRegAlloc.h" +//***TODO: There are several places we add instructions. Validate the order +// of adding these instructions. + + + cl::Enum DEBUG_RA("dregalloc", cl::NoFlags, "enable register allocation debugging information", clEnumValN(RA_DEBUG_None , "n", "disable debug output"), @@ -17,7 +22,7 @@ PhyRegAlloc::PhyRegAlloc(const Method *const M, Meth(M), TM(tm), LVI(Lvi), LRI(M, tm, RegClassList), MRI( tm.getRegInfo() ), NumOfRegClasses(MRI.getNumOfRegClasses()), - AddedInstrMap() + AddedInstrMap(), StackOffsets() { // **TODO: use an actual reserved color list @@ -27,6 +32,9 @@ PhyRegAlloc::PhyRegAlloc(const Method *const M, for( unsigned int rc=0; rc < NumOfRegClasses; rc++) RegClassList.push_back( new RegClass(M, MRI.getMachineRegClass(rc), RCL) ); + // **TODO: Init to the correct value. Also reset this to the correct + // value at the start of each instruction. Need a way to track max used + int curOffset4TmpSpills =0 ; } //---------------------------------------------------------------------------- @@ -261,29 +269,6 @@ void PhyRegAlloc::buildInterferenceGraphs() } } // for all machine instructions in BB - - -#if 0 - - // go thru LLVM instructions in the basic block and record all CALL - // instructions and Return instructions in the CallInstrList - // This is done because since there are no reverse pointers in machine - // instructions to find the llvm instruction, when we encounter a call - // or a return whose args must be specailly colored (e.g., %o's for args) - BasicBlock::const_iterator InstIt = (*BBI)->begin(); - - for( ; InstIt != (*BBI)->end() ; ++ InstIt) { - unsigned OpCode = (*InstIt)->getOpcode(); - - if( OpCode == Instruction::Call ) - CallInstrList.push_back( *InstIt ); - - else if( OpCode == Instruction::Ret ) - RetInstrList.push_back( *InstIt ); - } - -#endif - } // for all BBs in method @@ -328,6 +313,8 @@ void PhyRegAlloc::addInterferencesForArgs() +#if 0 + //---------------------------------------------------------------------------- // This method inserts caller saving/restoring instructons before/after // a call machine instruction. @@ -339,7 +326,8 @@ void PhyRegAlloc::insertCallerSavingCode(const MachineInstr *MInst, { // assert( (TM.getInstrInfo()).isCall( MInst->getOpCode() ) ); - int StackOff = -8; // ****TODO : Change + StackOffsets.resetTmpPos(); + hash_set PushedRegSet; // Now find the LR of the return value of the call @@ -399,18 +387,29 @@ void PhyRegAlloc::insertCallerSavingCode(const MachineInstr *MInst, // Now get two instructions - to push on stack and pop from stack // and add them to InstrnsBefore and InstrnsAfter of the // call instruction + + int StackOff = StackOffsets.getNewTmpPosOffFromSP(); + + /**** TODO + + if( RegType == SaveViaIntReg) { + + int FreeIntReg = getFreedIntReg(......) + + + } + */ MachineInstr *AdIBef = - MRI.cpReg2MemMI(Reg, MRI.getFramePointer(), StackOff, RegType ); + MRI.cpReg2MemMI(Reg, MRI.getStackPointer(), StackOff, RegType ); MachineInstr *AdIAft = - MRI.cpMem2RegMI(MRI.getFramePointer(), StackOff, Reg, RegType ); + MRI.cpMem2RegMI(MRI.getStackPointer(), StackOff, Reg, RegType ); ((AddedInstrMap[MInst])->InstrnsBefore).push_front(AdIBef); ((AddedInstrMap[MInst])->InstrnsAfter).push_back(AdIAft); PushedRegSet.insert( Reg ); - StackOff -= 8; // ****TODO: Correct ?????? if(DEBUG_RA) { cerr << "\nFor callee save call inst:" << *MInst; @@ -429,6 +428,8 @@ void PhyRegAlloc::insertCallerSavingCode(const MachineInstr *MInst, } +#endif + //---------------------------------------------------------------------------- // This method is called after register allocation is complete to set the @@ -455,7 +456,7 @@ void PhyRegAlloc::updateMachineCode() // if this machine instr is call, insert caller saving code if( (TM.getInstrInfo()).isCall( MInst->getOpCode()) ) - insertCallerSavingCode(MInst, *BBI ); + MRI.insertCallerSavingCode(MInst, *BBI, *this ); // If there are instructions to be added, *before* this machine // instruction, add them now. @@ -481,7 +482,9 @@ void PhyRegAlloc::updateMachineCode() } - + // reset the stack offset for temporary variables since we may + // need that to spill + StackOffsets.resetTmpPos(); //for(MachineInstr::val_op_const_iterator OpI(MInst);!OpI.done();++OpI) { @@ -502,7 +505,7 @@ void PhyRegAlloc::updateMachineCode() } assert( Val && "Value is NULL"); - const LiveRange *const LR = LRI.getLiveRangeForValue(Val); + LiveRange *const LR = LRI.getLiveRangeForValue(Val); if ( !LR ) { @@ -518,45 +521,24 @@ void PhyRegAlloc::updateMachineCode() if( Op.getAllocatedRegNum() == -1) Op.setRegForValue( MRI.getInvalidRegNum()); -#if 0 - if( ((Val->getType())->isLabelType()) || - (Val->getValueType() == Value::ConstantVal) ) - ; // do nothing - - // The return address is not explicitly defined within a - // method. So, it is not colored by usual algorithm. In that case - // color it here. - - //else if (TM.getInstrInfo().isCall(MInst->getOpCode())) - //Op.setRegForValue( MRI.getCallAddressReg() ); - - //TM.getInstrInfo().isReturn(MInst->getOpCode()) - else if(TM.getInstrInfo().isReturn(MInst->getOpCode()) ) { - if (DEBUG_RA) cout << endl << "RETURN found" << endl; - Op.setRegForValue( MRI.getReturnAddressReg() ); - - } - - if (Val->getValueType() == Value::InstructionVal) - { - if( DEBUG_RA ) { - cout << "!Warning: No LiveRange for: "; - printValue( Val); cout << " Type: " << Val->getValueType(); - cout << " RegVal=" << Op.getAllocatedRegNum() << endl; - } - } - -#endif continue; } unsigned RCID = (LR->getRegClass())->getID(); - Op.setRegForValue( MRI.getUnifiedRegNum(RCID, LR->getColor()) ); + if( LR->hasColor() ) { + Op.setRegForValue( MRI.getUnifiedRegNum(RCID, LR->getColor()) ); + } + else { - int RegNum = MRI.getUnifiedRegNum(RCID, LR->getColor()); + // LR did NOT receive a color (register). Now, insert spill code + // for spilled opeands in this machine instruction + assert(0 && "LR must be spilled"); + // insertCode4SpilledLR(LR, MInst, *BBI, OpNum ); + + } } } // for each operand @@ -619,8 +601,247 @@ void PhyRegAlloc::updateMachineCode() } + +#if 0 + + +//---------------------------------------------------------------------------- +// This method inserts spill code for AN operand whose LR was spilled. +// This method may be called several times for a single machine instruction +// if it contains many spilled operands. Each time it is called, it finds +// a register which is not live at that instruction and also which is not +// 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, + const MachineInstr *MInst, + const BasisBlock *BB, + const unsigned OpNum) { + + MachineOperand& Op = MInst->getOperand(OpNum); + bool isDef = MInst->operandIsDefined(OpNum); + unsigned RegType = MRI.getRegType( LR ); + int SpillOff = LR->getSpillOffFromFP(); + RegClass *RC = LR->getRegClass(); + const LiveVarSet *LVSetBef = LVI->getLiveVarSetBeforeMInst(MInst, BB); + int TmpOff = StackOffsets.getNewTmpPosOffFromSP(); + MachineInstr *MIBef, *AdIMid, *MIAft; + int TmpReg; + + TmpReg = getUsableRegAtMI(RC, RegType, MInst,LVSetBef, MIBef, MIAft); + TmpReg = getUnifiedRegNum( RC->getID(), TmpReg ); + + + if( !isDef ) { + + // for a USE, we have to load the value of LR from stack to a TmpReg + // and use the TmpReg as one operand of instruction + + // actual loading instruction + AdIMid = MRI.cpMem2RegMI(MRI.getFramePointer(), SpillOff, TmpReg, RegType); + + if( MIBef ) + ((AddedInstrMap[MInst])->InstrnsBefore).push_back(MIBef); + + ((AddedInstrMap[MInst])->InstrnsBefore).push_back(AdiMid); + + if( MIAft) + ((AddedInstrMap[MInst])->InstrnsAfter).push_front(MIAft); + + + } + else { // if this is a Def + + // for a DEF, we have to store the value produced by this instruction + // on the stack position allocated for this LR + + // actual storing instruction + AdIMid = MRI.cpReg2MemMI(TmpReg, MRI.getFramePointer(), SpillOff, RegType); + + if( MIBef ) + ((AddedInstrMap[MInst])->InstrnsBefore).push_back(MIBef); + + ((AddedInstrMap[MInst])->InstrnsBefore).push_back(AdiMid); + + if( MIAft) + ((AddedInstrMap[MInst])->InstrnsAfter).push_front(MIAft); + + } // if !DEF + + + Op.setRegForValue( TmpReg ); // set the opearnd + + +} + + +//---------------------------------------------------------------------------- +// We can use the following method to get a temporary register to be used +// BEFORE any given machine instruction. If there is a register available, +// this method will simply return that register and set MIBef = MIAft = NULL. +// Otherwise, it will return a register and MIAft and MIBef will contain +// two instructions used to free up this returned register. +//---------------------------------------------------------------------------- + +int PhyRegAlloc::getUsableRegAtMI(const RegClass *RC, + const int RegType, + const MachineInstr *MInst, + const LiveVarSet *LVSetBef, + MachineInstr *MIBef, + MachineInstr *MIAft) { + + int Reg = getUnusedRegAtMI(RC, MInst, LVSetBef); + + if( Reg != -1) { + // we found an unused register, so we can simply used + MIBef = MIAft = NULL; + } + else { + // we couldn't find an unused register. Generate code to ree up a reg by + // saving it on stack and restoring after the instruction + + Reg = getRegNotUsedByThisInst(RC, MInst); + MIBef = cpReg2MemMI(Reg, MRI.getFramePointer(), TmpOff, RegType ); + MIAft = cpMem2RegMI(MEI.getFramePointer(), TmpOff, Reg, RegType ); + } + + return Reg; +} + +//---------------------------------------------------------------------------- +// This method is called to get a new unused register that can be used to +// accomodate a spilled value. +// This method may be called several times for a single machine instruction +// if it contains many spilled operands. Each time it is called, it finds +// a register which is not live at that instruction and also which is not +// used by other spilled operands of the same instruction. +//---------------------------------------------------------------------------- +int PhyRegAlloc::getUnusedRegAtMI(const RegClass *RC, + const MachineInstr *MInst, + const LiveVarSet *LVSetBef) { + + unsigned NumAvailRegs = RC->getNumOfAvailRegs(); + + bool *IsColorUsedArr = RC->getIsColorUsedArr(); + + for(unsigned i=0; i < NumAvailRegs; i++); + IsColorUsedArr[i] = false; + + LiveVarSet::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 + 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 ) + if( LRofLV->hasColor() ) + IsColorUsedArr[ LRofLV->getColor() ] = true; + } + + // 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. + + setRegsUsedByThisInst(RC, MInst); + + unsigned c; // find first unused color + for( c=0; c < NumAvailRegs; c++) + if( ! IsColorUsedArr[ c ] ) break; + + if(c < NumAvailRegs) + return c; + else + return -1; + + +} + + +#endif + +//---------------------------------------------------------------------------- +// This method modifies the IsColorUsedArr of the register class passed to it. +// It sets the bits corresponding to the registers used by this machine +// instructions. Explicit operands are set. +//---------------------------------------------------------------------------- +void PhyRegAlloc::setRegsUsedByThisInst(RegClass *RC, + const MachineInstr *MInst ) { + + bool *IsColorUsedArr = RC->getIsColorUsedArr(); + + for(unsigned OpNum=0; OpNum < MInst->getNumOperands(); ++OpNum) { + + const MachineOperand& Op = MInst->getOperand(OpNum); + + if( Op.getOperandType() == MachineOperand::MO_VirtualRegister || + Op.getOperandType() == MachineOperand::MO_CCRegister) { + + const Value *const Val = Op.getVRegValue(); + + if( !Val ) + if( MRI.getRegClassIDOfValue( Val )== RC->getID() ) { + int Reg; + if( (Reg=Op.getAllocatedRegNum()) != -1) + IsColorUsedArr[ Reg ] = true; + + } + } + } + + // If there are implicit references, mark them as well + + for(unsigned z=0; z < MInst->getNumImplicitRefs(); z++) { + + LiveRange *const LRofImpRef = + LRI.getLiveRangeForValue( MInst->getImplicitRef(z) ); + + if( LRofImpRef ) + if( LRofImpRef->hasColor() ) + IsColorUsedArr[ LRofImpRef->getColor() ] = true; + } + + + +} + + + +//---------------------------------------------------------------------------- +// Get any other register in a register class, other than what is used +// by operands of a machine instruction. +//---------------------------------------------------------------------------- +int PhyRegAlloc::getRegNotUsedByThisInst(RegClass *RC, + const MachineInstr *MInst) { + + bool *IsColorUsedArr = RC->getIsColorUsedArr(); + unsigned NumAvailRegs = RC->getNumOfAvailRegs(); + + + for(unsigned i=0; i < NumAvailRegs ; i++) + IsColorUsedArr[i] = false; + + setRegsUsedByThisInst(RC, MInst); + + unsigned c; // find first unused color + for( c=0; c < RC->getNumOfAvailRegs(); c++) + if( ! IsColorUsedArr[ c ] ) break; + + if(c < NumAvailRegs) + return c; + else + assert( 0 && "FATAL: No free register could be found in reg class!!"); + +} + + + + + //---------------------------------------------------------------------------- -// // If there are delay slots for an instruction, the instructions // added after it must really go after the delayed instruction(s). // So, we move the InstrAfter of that instruction to the @@ -775,8 +996,12 @@ void PhyRegAlloc::colorCallRetArgs() AddedInstrMap[ CRMI ] = AI; } + // Tmp stack poistions are needed by some calls that have spilled args + // So reset it before we call each such method + StackOffsets.resetTmpPos(); + if( (TM.getInstrInfo()).isCall( OpCode ) ) - MRI.colorCallArgs( CRMI, LRI, AI ); + MRI.colorCallArgs( CRMI, LRI, AI, *this ); else if ( (TM.getInstrInfo()).isReturn(OpCode) ) MRI.colorRetValue( CRMI, LRI, AI ); @@ -829,7 +1054,7 @@ void PhyRegAlloc::printLabel(const Value *const Val) void PhyRegAlloc::markUnusableSugColors() { - if(DEBUG_RA ) cout << "Creating LR lists ..." << endl; + if(DEBUG_RA ) cout << "\nmarking unusable suggested colors ..." << endl; // hash map iterator LiveRangeMapType::const_iterator HMI = (LRI.getLiveRangeMap())->begin(); @@ -858,8 +1083,34 @@ void PhyRegAlloc::markUnusableSugColors() +//---------------------------------------------------------------------------- +// The following method will set the stack offsets of the live ranges that +// are decided to be spillled. This must be called just after coloring the +// LRs using the graph coloring algo. For each live range that is spilled, +// this method allocate a new spill position on the stack. +//---------------------------------------------------------------------------- +void PhyRegAlloc::allocateStackSpace4SpilledLRs() +{ + if(DEBUG_RA ) cout << "\nsetting LR stack offsets ..." << endl; + // hash map iterator + LiveRangeMapType::const_iterator HMI = (LRI.getLiveRangeMap())->begin(); + LiveRangeMapType::const_iterator HMIEnd = (LRI.getLiveRangeMap())->end(); + + for( ; HMI != HMIEnd ; ++HMI ) { + + if( (*HMI).first ) { + LiveRange *L = (*HMI).second; // get the LiveRange + if(L) + if( ! L->hasColor() ) + L->setSpillOffFromFP( StackOffsets.getNewSpillOffFromFP() ); + } + } // for all LR's in hash map + + StackOffsets.setEndOfSpillRegion(); + +} @@ -919,6 +1170,9 @@ void PhyRegAlloc::allocateRegisters() for( unsigned int rc=0; rc < NumOfRegClasses ; rc++) RegClassList[ rc ]->colorAllRegs(); + // Atter grpah coloring, if some LRs did not receive a color (i.e, spilled) + // a poistion for such spilled LRs + allocateStackSpace4SpilledLRs(); // color incoming args and call args colorIncomingArgs(); @@ -934,4 +1188,3 @@ void PhyRegAlloc::allocateRegisters() -