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:
Vikram S. Adve 2003-07-06 20:13:59 +00:00
parent 95b36820bb
commit d09c4c34c0
5 changed files with 82 additions and 37 deletions

View File

@ -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>";

View File

@ -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.

View File

@ -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.

View File

@ -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;

View File

@ -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: {