From: Ruchira Sasanka Date: Sat, 3 Nov 2001 19:59:59 +0000 (+0000) Subject: Added code to support correct saving of %ccr across calls X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=3839e6e309d18009fe03c0e955d9aef1e9297ad5;p=oota-llvm.git Added code to support correct saving of %ccr across calls git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1111 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/SparcV9/SparcV9Instr.def b/lib/Target/SparcV9/SparcV9Instr.def index 368cc5ad76f..cf70b31b12e 100644 --- a/lib/Target/SparcV9/SparcV9Instr.def +++ b/lib/Target/SparcV9/SparcV9Instr.def @@ -38,6 +38,7 @@ // instr class flags (defined in MachineInstrInfo.h) + I(NOP, "nop", 0, -1, 0, false, 0, 1, SPARC_NONE, M_NOP_FLAG) // Synthetic SPARC assembly opcodes for setting a register to a constant. @@ -430,6 +431,11 @@ I(RETURN, "return", 2, -1, 0, false, 1, 2, SPARC_CTI, M_BRANCH_FLAG | M_RET_ I(SAVE , "save", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG) I(RESTORE, "restore", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG) +// Read and Write CCR register from/to an int reg +I(RDCCR, "rd", 2, 1, 0, false, 0, 1, SPARC_IEUN, M_INT_FLAG) +I(WRCCR, "wr", 3, 2, 0, false, 0, 1, SPARC_IEUN, M_INT_FLAG) + + // Synthetic phi operation for near-SSA form of machine code // Number of operands is variable, indicated by -1. Result is the first op. I(PHI, "", -1, 0, 0, false, 0, 0, SPARC_INV, M_DUMMY_PHI_FLAG) diff --git a/lib/Target/SparcV9/SparcV9Internals.h b/lib/Target/SparcV9/SparcV9Internals.h index 72b234f72cb..2f151b78878 100644 --- a/lib/Target/SparcV9/SparcV9Internals.h +++ b/lib/Target/SparcV9/SparcV9Internals.h @@ -254,6 +254,9 @@ class UltraSparcRegInfo : public MachineRegInfo const unsigned getCallInstNumArgs(const MachineInstr *CallMI) const; + MachineInstr * cpCCR2IntMI(const unsigned IntReg) const; + MachineInstr * cpInt2CCRMI(const unsigned IntReg) const; + public: @@ -371,9 +374,8 @@ class UltraSparcRegInfo : public MachineRegInfo return SparcFloatRegOrder::getRegName( reg - 32); else if( reg < (64+32+4) ) return SparcFloatCCRegOrder::getRegName( reg -32 - 64); - else if ( reg == 64+32+4) - return "xcc"; // only integer cc reg - + else if( reg < (64+32+4+2) ) // two names: %xcc and %ccr + return SparcIntCCRegOrder::getRegName( reg -32 - 64 - 4); else if (reg== InvalidRegNum) //****** TODO: Remove */ return "<*NoReg*>"; else diff --git a/lib/Target/SparcV9/SparcV9RegClassInfo.h b/lib/Target/SparcV9/SparcV9RegClassInfo.h index 4f91268c374..fd768157500 100644 --- a/lib/Target/SparcV9/SparcV9RegClassInfo.h +++ b/lib/Target/SparcV9/SparcV9RegClassInfo.h @@ -191,22 +191,54 @@ class SparcFloatRegClass : public MachineRegClassInfo //----------------------------------------------------------------------------- // Int CC Register Class -// Only one integer cc register is available +// Only one integer cc register is available. However, this register is +// referred to as %xcc when instructions like subcc are executed but +// referred to as %ccr (i.e., %xcc + %icc") when this register is moved +// into an integer register using RD or WR instrcutions. So, two ids are +// allocated for two names. //----------------------------------------------------------------------------- +static string const IntCCRegNames[] = + { + "xcc", "ccr" + }; + + +class SparcIntCCRegOrder{ + + public: + + enum RegsInPrefOrder { + + xcc, ccr // only one is available - see the note above + }; + + static const string getRegName(const unsigned reg) { + assert( reg < 2 ); + return IntCCRegNames[reg]; + } + + // according to Sparc 64 ABI, %ccr is volatile + inline bool isRegVolatile(const int Reg) const { return true; } + + +}; + + + class SparcIntCCRegClass : public MachineRegClassInfo { public: SparcIntCCRegClass(unsigned ID) - : MachineRegClassInfo(ID,1, 1) { } + : MachineRegClassInfo(ID, 1, 2) { } inline void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const { Node->setColor(0); // only one int cc reg is available } - // *** TODO: Check this + inline bool isRegVolatile(const int Reg) const { return true; } }; diff --git a/lib/Target/SparcV9/SparcV9RegInfo.cpp b/lib/Target/SparcV9/SparcV9RegInfo.cpp index a34a5305ae7..9c57892392e 100644 --- a/lib/Target/SparcV9/SparcV9RegInfo.cpp +++ b/lib/Target/SparcV9/SparcV9RegInfo.cpp @@ -896,7 +896,6 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(const unsigned SrcReg, switch( RegType ) { case IntRegType: - case IntCCRegType: case FloatCCRegType: MI = new MachineInstr(STX, 3); MI->SetMachineOperand(0, SrcReg, false); @@ -921,8 +920,11 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(const unsigned SrcReg, (int64_t) Offset, false); break; + case IntCCRegType: + assert( 0 && "Cannot directly store %ccr to memory"); + default: - assert(0 && "Unknow RegType"); + assert(0 && "Unknow RegType in cpReg2MemMI"); } return MI; @@ -945,7 +947,6 @@ MachineInstr * UltraSparcRegInfo::cpMem2RegMI(const unsigned SrcPtrReg, switch( RegType ) { case IntRegType: - case IntCCRegType: case FloatCCRegType: MI = new MachineInstr(LDX, 3); MI->SetMachineOperand(0, SrcPtrReg, false); @@ -971,14 +972,21 @@ MachineInstr * UltraSparcRegInfo::cpMem2RegMI(const unsigned SrcPtrReg, MI->SetMachineOperand(2, DestReg, false); break; + case IntCCRegType: + assert( 0 && "Cannot directly load into %ccr from memory"); + default: - assert(0 && "Unknow RegType"); + assert(0 && "Unknow RegType in cpMem2RegMI"); } return MI; } + + +// Following method is Not needed now + MachineInstr* UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const { MachineInstr * MI = NULL; @@ -1071,28 +1079,91 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, int StackOff = PRA.StackOffsets. getNewTmpPosOffFromFP(); - /**** TODO - Handle IntCCRegType + + MachineInstr *AdIBefCC, *AdIAftCC, *AdICpCC; + + + //---- Insert code for pushing the reg on stack ---------- + if( RegType == IntCCRegType ) { + + // Handle IntCCRegType specially since we cannot directly + // push %ccr on to the stack + + const LiveVarSet *LVSetBef = + PRA.LVI->getLiveVarSetBeforeMInst(MInst, BB); + + // get a free INTEGER register + int FreeIntReg = + PRA.getUsableRegAtMI(LR->getRegClass(), IntRegType, MInst, + LVSetBef, AdIBefCC, AdIAftCC); + // insert the instructions in reverse order since we are + // adding them to the front of InstrnsBefore + if(AdIAftCC) + (PRA.AddedInstrMap[MInst]->InstrnsBefore).push_front(AdIAftCC); + + AdICpCC = cpCCR2IntMI(FreeIntReg); + (PRA.AddedInstrMap[MInst]->InstrnsBefore).push_front(AdICpCC); + + if(AdIBefCC) + (PRA.AddedInstrMap[MInst]->InstrnsBefore).push_front(AdIBefCC); + + cerr << "\n!! Inserted caller saving (push) inst for %ccr:"; + if(AdIBefCC) cerr << "\t" << *(AdIBefCC); + cerr << "\t" << *AdICpCC; + if(AdIAftCC) cerr << "\t" << *(AdIAftCC); + + } else { + // for any other register type, just add the push inst + MachineInstr *AdIBef = + cpReg2MemMI(Reg, getStackPointer(), StackOff, RegType ); + ((PRA.AddedInstrMap[MInst])->InstrnsBefore).push_front(AdIBef); } - */ + + + //---- Insert code for popping the reg from the stack ---------- + + if( RegType == IntCCRegType ) { + + // Handle IntCCRegType specially since we cannot directly + // pop %ccr on from the stack + + // get a free INT register + int FreeIntReg = + PRA.getUsableRegAtMI(LR->getRegClass(), IntRegType, MInst, + LVSetAft, AdIBefCC, AdIAftCC); + + if(AdIBefCC) + (PRA.AddedInstrMap[MInst]->InstrnsAfter).push_back(AdIBefCC); + + AdICpCC = cpInt2CCRMI(FreeIntReg); + (PRA.AddedInstrMap[MInst]->InstrnsAfter).push_back(AdICpCC); - MachineInstr *AdIBef = - cpReg2MemMI(Reg, getStackPointer(), StackOff, RegType ); + if(AdIAftCC) + (PRA.AddedInstrMap[MInst]->InstrnsAfter).push_back(AdIAftCC); + + cerr << "\n!! Inserted caller saving (pop) inst for %ccr:"; + if(AdIBefCC) cerr << "\t" << *(AdIBefCC); + cerr << "\t" << *AdICpCC; + if(AdIAftCC) cerr << "\t" << *(AdIAftCC); + + } else { + // for any other register type, just add the pop inst + MachineInstr *AdIAft = + cpMem2RegMI(getStackPointer(), StackOff, Reg, RegType ); - MachineInstr *AdIAft = - cpMem2RegMI(getStackPointer(), StackOff, Reg, RegType ); + ((PRA.AddedInstrMap[MInst])->InstrnsAfter).push_back(AdIAft); - ((PRA.AddedInstrMap[MInst])->InstrnsBefore).push_front(AdIBef); - ((PRA.AddedInstrMap[MInst])->InstrnsAfter).push_back(AdIAft); + } PushedRegSet.insert( Reg ); - if(DEBUG_RA) { - cerr << "\nFor callee save call inst:" << *MInst; + if(1) { + cerr << "\nFor call inst:" << *MInst; cerr << "\n -inserted caller saving instrs:\n\t "; - cerr << *AdIBef << "\n\t" << *AdIAft ; + cerr << *AdIBefCC << "\n\t" << *AdIAftCC ; } } // if not already pushed @@ -1106,10 +1177,36 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst, } +//--------------------------------------------------------------------------- +// Copies %ccr into an integer register. IntReg is the UNIFIED register +// number. +//--------------------------------------------------------------------------- +MachineInstr * UltraSparcRegInfo::cpCCR2IntMI(const unsigned IntReg) const { + MachineInstr * MI = NULL; + MI = new MachineInstr(RDCCR, 2); + MI->SetMachineOperand(0, SparcIntCCRegOrder::ccr, false); + MI->SetMachineOperand(1, IntReg, true); + return MI; +} + +//--------------------------------------------------------------------------- +// Copies an integer register into %ccr. IntReg is the UNIFIED register +// number. +//--------------------------------------------------------------------------- + +MachineInstr * UltraSparcRegInfo::cpInt2CCRMI(const unsigned IntReg) const { + MachineInstr * MI = NULL; + + MI = new MachineInstr(WRCCR, 3); + MI->SetMachineOperand(0, IntReg, false); + MI->SetMachineOperand(1, SparcIntRegOrder::g0, false); + MI->SetMachineOperand(2, SparcIntCCRegOrder::ccr, true); + return MI; +}