diff --git a/llvm/lib/Target/Sparc/EmitAssembly.cpp b/llvm/lib/Target/Sparc/EmitAssembly.cpp index f66b36f9be4a..829a3b8bb312 100644 --- a/llvm/lib/Target/Sparc/EmitAssembly.cpp +++ b/llvm/lib/Target/Sparc/EmitAssembly.cpp @@ -393,12 +393,27 @@ SparcFunctionAsmPrinter::printOneOperand(const MachineOperand &mop, switch (mop.getType()) { - case MachineOperand::MO_VirtualRegister: case MachineOperand::MO_CCRegister: + { + // We need to print %icc or %xcc as %ccr for certain opcodes. + int regNum = (int)mop.getAllocatedRegNum(); + if (regNum != Target.getRegInfo().getInvalidRegNum() && + Target.getRegInfo().getRegClassIDOfReg(regNum) + == UltraSparcRegInfo::IntCCRegClassID) + { + if (opCode == V9::RDCCR || opCode == V9::WRCCRi || opCode == V9::WRCCRr) + { + toAsm << "%" << Target.getRegInfo().getMachineRegClass(UltraSparcRegInfo::IntCCRegClassID)->getRegName(SparcIntCCRegClass::ccr); + break; + } + } + // all other cases can be handled like any other register + } + + case MachineOperand::MO_VirtualRegister: case MachineOperand::MO_MachineRegister: { int regNum = (int)mop.getAllocatedRegNum(); - if (regNum == Target.getRegInfo().getInvalidRegNum()) { // better to print code with NULL registers than to die toAsm << ""; diff --git a/llvm/lib/Target/Sparc/SparcInstrSelection.cpp b/llvm/lib/Target/Sparc/SparcInstrSelection.cpp index 58c15edc29f2..abb7fbecc8d2 100644 --- a/llvm/lib/Target/Sparc/SparcInstrSelection.cpp +++ b/llvm/lib/Target/Sparc/SparcInstrSelection.cpp @@ -386,16 +386,14 @@ GetTmpForCC(Value* boolVal, const Function *F, const Type* ccType, static inline MachineOpCode ChooseBccInstruction(const InstructionNode* instrNode, - bool& isFPBranch) + const Type*& setCCType) { InstructionNode* setCCNode = (InstructionNode*) instrNode->leftChild(); assert(setCCNode->getOpLabel() == SetCCOp); BinaryOperator* setCCInstr =cast(setCCNode->getInstruction()); - const Type* setCCType = setCCInstr->getOperand(0)->getType(); + setCCType = setCCInstr->getOperand(0)->getType(); - isFPBranch = setCCType->isFloatingPoint(); // Return value: don't delete! - - if (isFPBranch) + if (setCCType->isFloatingPoint()) return ChooseBFpccInstruction(instrNode, setCCInstr); else return ChooseBpccInstruction(instrNode, setCCInstr); @@ -1604,11 +1602,11 @@ GetInstructionsByRule(InstructionNode* subtreeRoot, // TmpInstruction representing that CC. // BranchInst* brInst = cast(subtreeRoot->getInstruction()); - bool isFPBranch; - unsigned Opcode = ChooseBccInstruction(subtreeRoot, isFPBranch); + const Type* setCCType; + unsigned Opcode = ChooseBccInstruction(subtreeRoot, setCCType); Value* ccValue = GetTmpForCC(subtreeRoot->leftChild()->getValue(), brInst->getParent()->getParent(), - isFPBranch? Type::FloatTy : Type::IntTy, + setCCType, MachineCodeForInstruction::get(brInst)); M = BuildMI(Opcode, 2).addCCReg(ccValue) .addPCDisp(brInst->getSuccessor(0)); @@ -2058,7 +2056,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot, // TmpInstruction* tmpForCC = GetTmpForCC(setCCInstr, setCCInstr->getParent()->getParent(), - isFPCompare ? Type::FloatTy : Type::IntTy, + leftVal->getType(), MachineCodeForInstruction::get(setCCInstr)); if (! isFPCompare) { // Integer condition: set CC and discard result. diff --git a/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp b/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp index 63b39c162499..1640dcab6c68 100644 --- a/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp @@ -112,6 +112,47 @@ void SparcIntRegClass::colorIGNode(IGNode * Node, LR->markForSpill(); // no color found - must spill } +//----------------------------------------------------------------------------- +// Int CC Register Class - method for coloring a node in the interference graph. +// +// Algorithm: +// +// If the single int CC register is used (either as icc or xcc) +// mark the LR for spilling +// else { +// if (the LR is a 64-bit comparison) use %xcc +// else /*32-bit or smaller*/ use %icc +// } +// +// Note: The third name (%ccr) is essentially an assembly mnemonic and +// depends solely on the opcode, so the name can be chosen in EmitAssembly. +//----------------------------------------------------------------------------- +void SparcIntCCRegClass::colorIGNode(IGNode *Node, + std::vector &IsColorUsedArr) const +{ + if (IsColorUsedArr[xcc] && IsColorUsedArr[icc]) + Node->getParentLR()->markForSpill(); + else { + // Choose whether to use %xcc or %icc based on type of value compared + const LiveRange* ccLR = Node->getParentLR(); + const Type* setCCType = (* ccLR->begin())->getType(); // any Value in LR + assert(setCCType->isIntegral()); + int ccReg = (setCCType == Type::LongTy)? xcc : icc; + +#ifndef NDEBUG + // Let's just make sure values of two different types have not been + // coalesced into this LR. + for (ValueSet::const_iterator I=ccLR->begin(), E=ccLR->end(); I != E; ++I) + assert(setCCType->isIntegral() && + ((ccReg == xcc && (*I)->getType() == Type::LongTy) || + (ccReg == icc && (*I)->getType() != Type::LongTy)) + && "Comparisons needing different intCC regs coalesced in LR!"); +#endif + + Node->setColor(ccReg); // only one int cc reg is available + } +} + //----------------------------------------------------------------------------- // Float Register Class - method for coloring a node in the interference graph. diff --git a/llvm/lib/Target/Sparc/SparcRegClassInfo.h b/llvm/lib/Target/Sparc/SparcRegClassInfo.h index bc9b445d5d02..50cccb662146 100644 --- a/llvm/lib/Target/Sparc/SparcRegClassInfo.h +++ b/llvm/lib/Target/Sparc/SparcRegClassInfo.h @@ -113,29 +113,24 @@ public: //----------------------------------------------------------------------------- // Int CC Register Class // 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. +// referred to as %xcc or %icc 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, three ids are +// allocated for the three names. //----------------------------------------------------------------------------- struct SparcIntCCRegClass : public TargetRegClassInfo { SparcIntCCRegClass(unsigned ID) - : TargetRegClassInfo(ID, 1, 2) { } - - void colorIGNode(IGNode *Node, std::vector &IsColorUsedArr) const { - if (IsColorUsedArr[0]) - Node->getParentLR()->markForSpill(); - else - Node->setColor(0); // only one int cc reg is available - } + : TargetRegClassInfo(ID, 1, 3) { } + void colorIGNode(IGNode *Node, std::vector &IsColorUsedArr) const; + // according to Sparc 64 ABI, %ccr is volatile // inline bool isRegVolatile(int Reg) const { return true; } enum { - xcc, ccr // only one is available - see the note above + xcc, icc, ccr // only one is available - see the note above }; const char * const getRegName(unsigned reg) const; diff --git a/llvm/lib/Target/Sparc/SparcRegInfo.cpp b/llvm/lib/Target/Sparc/SparcRegInfo.cpp index 95bd87f95050..962b9f68d1c6 100644 --- a/llvm/lib/Target/Sparc/SparcRegInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegInfo.cpp @@ -98,11 +98,11 @@ const char * const SparcFloatRegClass::getRegName(unsigned reg) const { static const char * const IntCCRegNames[] = { - "xcc", "ccr" + "xcc", "icc", "ccr" }; const char * const SparcIntCCRegClass::getRegName(unsigned reg) const { - assert(reg < 2); + assert(reg < 3); return IntCCRegNames[reg]; } @@ -1088,15 +1088,14 @@ UltraSparcRegInfo::cpReg2RegMI(std::vector& mvec, case IntCCRegType: if (getRegType(DestReg) == IntRegType) { // copy intCC reg to int reg - // Use SrcReg+1 to get the name "%ccr" instead of "%xcc" for RDCCR - MI = BuildMI(V9::RDCCR, 2).addMReg(SrcReg+1).addMReg(DestReg,MOTy::Def); + MI = (BuildMI(V9::RDCCR, 2).addMReg(SparcIntCCRegClass::ccr). + addMReg(DestReg,MOTy::Def)); } else { // copy int reg to intCC reg - // Use DestReg+1 to get the name "%ccr" instead of "%xcc" for WRCCR assert(getRegType(SrcReg) == IntRegType && "Can only copy CC reg to/from integer reg"); - MI = BuildMI(V9::WRCCRr, 3).addMReg(SrcReg) - .addMReg(SparcIntRegClass::g0).addMReg(DestReg+1, MOTy::Def); + MI = (BuildMI(V9::WRCCRr, 3).addMReg(SrcReg).addMReg(SparcIntRegClass::g0) + .addMReg(SparcIntCCRegClass::ccr, MOTy::Def)); } break; @@ -1161,9 +1160,8 @@ UltraSparcRegInfo::cpReg2MemMI(std::vector& mvec, case IntCCRegType: assert(scratchReg >= 0 && "Need scratch reg to store %ccr to memory"); assert(getRegType(scratchReg) ==IntRegType && "Invalid scratch reg"); - - // Use SrcReg+1 to get the name "%ccr" instead of "%xcc" for RDCCR - MI = BuildMI(V9::RDCCR, 2).addMReg(SrcReg+1).addMReg(scratchReg, MOTy::Def); + MI = (BuildMI(V9::RDCCR, 2).addMReg(SparcIntCCRegClass::ccr) + .addMReg(scratchReg, MOTy::Def)); mvec.push_back(MI); cpReg2MemMI(mvec, scratchReg, DestPtrReg, Offset, IntRegType); @@ -1221,10 +1219,8 @@ UltraSparcRegInfo::cpMem2RegMI(std::vector& mvec, assert(scratchReg >= 0 && "Need scratch reg to load %ccr from memory"); assert(getRegType(scratchReg) ==IntRegType && "Invalid scratch reg"); cpMem2RegMI(mvec, SrcPtrReg, Offset, scratchReg, IntRegType); - - // Use DestReg+1 to get the name "%ccr" instead of "%xcc" for WRCCR MI = BuildMI(V9::WRCCRr, 3).addMReg(scratchReg) - .addMReg(SparcIntRegClass::g0).addMReg(DestReg+1,MOTy::Def); + .addMReg(SparcIntRegClass::g0).addMReg(SparcIntCCRegClass::ccr,MOTy::Def); break; case FloatCCRegType: {