forked from OSchip/llvm-project
Major bug fix though it happened rarely (only on a compare after an
integer overflow): We need to use %icc and not %xcc for comparisons on 32-bit or smaller integer values. llvm-svn: 7111
This commit is contained in:
parent
95b36820bb
commit
d09c4c34c0
|
@ -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 << "<NULL VALUE>";
|
||||
|
|
|
@ -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<BinaryOperator>(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<BranchInst>(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.
|
||||
|
|
|
@ -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<bool> &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.
|
||||
|
|
|
@ -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<bool> &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<bool> &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;
|
||||
|
|
|
@ -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<MachineInstr*>& 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<MachineInstr*>& 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<MachineInstr*>& 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: {
|
||||
|
|
Loading…
Reference in New Issue