Add support for widening integral casts.

Flesh out the SetCC support... which currently ends in a little bit
of unfinished code (which is probably completely hilarious) for
generating the condition value splitting the basic block up into 4
blocks, like this (clearly a better API is needed for this!):

       BB
   cond. branch
     /         /          R1=1    R2=0
     \      /
      \    /
    R=phi(R1,R2)

Other minor edits.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13423 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Brian Gaeke 2004-05-08 06:36:14 +00:00
parent 59dbff714c
commit 429022bf83
4 changed files with 304 additions and 136 deletions

View File

@ -313,22 +313,44 @@ void V8ISel::visitCastInst(CastInst &I) {
unsigned oldTyClass = getClassB (oldTy);
unsigned newTyClass = getClassB (newTy);
if (oldTyClass < cLong && newTyClass < cLong && oldTyClass >= newTyClass) {
// Emit a reg->reg copy to do a equal-size or non-narrowing cast,
// and do sign/zero extension (necessary if we change signedness).
unsigned TempReg1 = makeAnotherReg (newTy);
unsigned TempReg2 = makeAnotherReg (newTy);
BuildMI (BB, V8::ORrr, 2, TempReg1).addReg (V8::G0).addReg (SrcReg);
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TempReg2).addZImm (shiftWidth).addReg (TempReg1);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg (TempReg2);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg (TempReg2);
if (oldTyClass < cLong && newTyClass < cLong) {
if (oldTyClass >= newTyClass) {
// Emit a reg->reg copy to do a equal-size or narrowing cast,
// and do sign/zero extension (necessary if we change signedness).
unsigned TmpReg1 = makeAnotherReg (newTy);
unsigned TmpReg2 = makeAnotherReg (newTy);
BuildMI (BB, V8::ORrr, 2, TmpReg1).addReg (V8::G0).addReg (SrcReg);
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
}
} else {
unsigned TmpReg1 = makeAnotherReg (oldTy);
unsigned TmpReg2 = makeAnotherReg (newTy);
unsigned TmpReg3 = makeAnotherReg (newTy);
// Widening integer cast. Make sure it's fully sign/zero-extended
// wrt the input type, then make sure it's fully sign/zero-extended wrt
// the output type. Kind of stupid, but simple...
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (oldTy));
BuildMI (BB, V8::SLLri, 2, TmpReg1).addZImm (shiftWidth).addReg(SrcReg);
if (oldTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
}
shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TmpReg3).addZImm (shiftWidth).addReg(TmpReg2);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
}
}
} else {
std::cerr << "Casts w/ long, fp, double, or widening still unsupported: "
<< I;
std::cerr << "Casts w/ long, fp, double still unsupported: " << I;
abort ();
}
}
@ -635,33 +657,53 @@ void V8ISel::visitSetCondInst(Instruction &I) {
unsigned Op0Reg = getReg (I.getOperand (0));
unsigned Op1Reg = getReg (I.getOperand (1));
unsigned DestReg = getReg (I);
const Type *Ty = I.getOperand (0)->getType ();
// Compare the two values.
BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
// Put 0 into a register.
//unsigned ZeroReg = makeAnotheRReg(Type::IntTy);
//BuildMI(BB, V8::ORri, 2, ZeroReg).addReg(V8::G0).addReg(V8::G0);
unsigned Opcode;
unsigned BranchIdx;
switch (I.getOpcode()) {
default: assert(0 && "Unknown setcc instruction!");
case Instruction::SetEQ:
case Instruction::SetNE:
case Instruction::SetLT:
case Instruction::SetGT:
case Instruction::SetLE:
case Instruction::SetGE:
;
case Instruction::SetEQ: BranchIdx = 0; break;
case Instruction::SetNE: BranchIdx = 1; break;
case Instruction::SetLT: BranchIdx = 2; break;
case Instruction::SetGT: BranchIdx = 3; break;
case Instruction::SetLE: BranchIdx = 4; break;
case Instruction::SetGE: BranchIdx = 5; break;
}
// FIXME: We need either conditional moves like the V9 has (e.g. movge), or we
// need to be able to turn a single LLVM basic block into multiple machine
// code basic blocks. For now, it probably makes sense to emit Sparc V9
// instructions until the code generator is upgraded. Note that this should
// only happen when the setcc cannot be folded into the branch, but this needs
// to be handled correctly!
static unsigned OpcodeTab[12] = {
// LLVM SparcV8
// unsigned signed
V8::BE, V8::BE, // seteq = be be
V8::BNE, V8::BNE, // setne = bne bne
V8::BCS, V8::BL, // setlt = bcs bl
V8::BGU, V8::BG, // setgt = bgu bg
V8::BLEU, V8::BLE, // setle = bleu ble
V8::BCC, V8::BGE // setge = bcc bge
};
unsigned Opcode = OpcodeTab[BranchIdx + (Ty->isSigned() ? 1 : 0)];
MachineBasicBlock *Copy1MBB, *Copy0MBB, *CopyCondMBB;
MachineBasicBlock::iterator IP;
#if 0
// Cond. Branch from BB --> either Copy1MBB or Copy0MBB --> CopyCondMBB
// Then once we're done with the SetCC, BB = CopyCondMBB.
BasicBlock *LLVM_BB = BB.getBasicBlock ();
unsigned Cond0Reg = makeAnotherReg (I.getType ());
unsigned Cond1Reg = makeAnotherReg (I.getType ());
F->getBasicBlockList ().push_back (Copy1MBB = new MachineBasicBlock (LLVM_BB));
F->getBasicBlockList ().push_back (Copy0MBB = new MachineBasicBlock (LLVM_BB));
F->getBasicBlockList ().push_back (CopyCondMBB = new MachineBasicBlock (LLVM_BB));
BuildMI (BB, Opcode, 1).addMBB (Copy1MBB);
BuildMI (BB, V8::BA, 1).addMBB (Copy0MBB);
IP = Copy1MBB->begin ();
BuildMI (*Copy1MBB, IP, V8::ORri, 2, Cond1Reg).addZImm (1).addReg (V8::G0);
BuildMI (*Copy1MBB, IP, V8::BA, 1).addMBB (CopyCondMBB);
IP = Copy0MBB->begin ();
BuildMI (*Copy0MBB, IP, V8::ORri, 2, Cond0Reg).addZImm (0).addReg (V8::G0);
BuildMI (*Copy0MBB, IP, V8::BA, 1).addMBB (CopyCondMBB);
// What should go in CopyCondMBB: PHI, then OR to copy cond. reg to DestReg
#endif
visitInstruction(I);
}

View File

@ -313,22 +313,44 @@ void V8ISel::visitCastInst(CastInst &I) {
unsigned oldTyClass = getClassB (oldTy);
unsigned newTyClass = getClassB (newTy);
if (oldTyClass < cLong && newTyClass < cLong && oldTyClass >= newTyClass) {
// Emit a reg->reg copy to do a equal-size or non-narrowing cast,
// and do sign/zero extension (necessary if we change signedness).
unsigned TempReg1 = makeAnotherReg (newTy);
unsigned TempReg2 = makeAnotherReg (newTy);
BuildMI (BB, V8::ORrr, 2, TempReg1).addReg (V8::G0).addReg (SrcReg);
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TempReg2).addZImm (shiftWidth).addReg (TempReg1);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg (TempReg2);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg (TempReg2);
if (oldTyClass < cLong && newTyClass < cLong) {
if (oldTyClass >= newTyClass) {
// Emit a reg->reg copy to do a equal-size or narrowing cast,
// and do sign/zero extension (necessary if we change signedness).
unsigned TmpReg1 = makeAnotherReg (newTy);
unsigned TmpReg2 = makeAnotherReg (newTy);
BuildMI (BB, V8::ORrr, 2, TmpReg1).addReg (V8::G0).addReg (SrcReg);
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
}
} else {
unsigned TmpReg1 = makeAnotherReg (oldTy);
unsigned TmpReg2 = makeAnotherReg (newTy);
unsigned TmpReg3 = makeAnotherReg (newTy);
// Widening integer cast. Make sure it's fully sign/zero-extended
// wrt the input type, then make sure it's fully sign/zero-extended wrt
// the output type. Kind of stupid, but simple...
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (oldTy));
BuildMI (BB, V8::SLLri, 2, TmpReg1).addZImm (shiftWidth).addReg(SrcReg);
if (oldTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
}
shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TmpReg3).addZImm (shiftWidth).addReg(TmpReg2);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
}
}
} else {
std::cerr << "Casts w/ long, fp, double, or widening still unsupported: "
<< I;
std::cerr << "Casts w/ long, fp, double still unsupported: " << I;
abort ();
}
}
@ -635,33 +657,53 @@ void V8ISel::visitSetCondInst(Instruction &I) {
unsigned Op0Reg = getReg (I.getOperand (0));
unsigned Op1Reg = getReg (I.getOperand (1));
unsigned DestReg = getReg (I);
const Type *Ty = I.getOperand (0)->getType ();
// Compare the two values.
BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
// Put 0 into a register.
//unsigned ZeroReg = makeAnotheRReg(Type::IntTy);
//BuildMI(BB, V8::ORri, 2, ZeroReg).addReg(V8::G0).addReg(V8::G0);
unsigned Opcode;
unsigned BranchIdx;
switch (I.getOpcode()) {
default: assert(0 && "Unknown setcc instruction!");
case Instruction::SetEQ:
case Instruction::SetNE:
case Instruction::SetLT:
case Instruction::SetGT:
case Instruction::SetLE:
case Instruction::SetGE:
;
case Instruction::SetEQ: BranchIdx = 0; break;
case Instruction::SetNE: BranchIdx = 1; break;
case Instruction::SetLT: BranchIdx = 2; break;
case Instruction::SetGT: BranchIdx = 3; break;
case Instruction::SetLE: BranchIdx = 4; break;
case Instruction::SetGE: BranchIdx = 5; break;
}
// FIXME: We need either conditional moves like the V9 has (e.g. movge), or we
// need to be able to turn a single LLVM basic block into multiple machine
// code basic blocks. For now, it probably makes sense to emit Sparc V9
// instructions until the code generator is upgraded. Note that this should
// only happen when the setcc cannot be folded into the branch, but this needs
// to be handled correctly!
static unsigned OpcodeTab[12] = {
// LLVM SparcV8
// unsigned signed
V8::BE, V8::BE, // seteq = be be
V8::BNE, V8::BNE, // setne = bne bne
V8::BCS, V8::BL, // setlt = bcs bl
V8::BGU, V8::BG, // setgt = bgu bg
V8::BLEU, V8::BLE, // setle = bleu ble
V8::BCC, V8::BGE // setge = bcc bge
};
unsigned Opcode = OpcodeTab[BranchIdx + (Ty->isSigned() ? 1 : 0)];
MachineBasicBlock *Copy1MBB, *Copy0MBB, *CopyCondMBB;
MachineBasicBlock::iterator IP;
#if 0
// Cond. Branch from BB --> either Copy1MBB or Copy0MBB --> CopyCondMBB
// Then once we're done with the SetCC, BB = CopyCondMBB.
BasicBlock *LLVM_BB = BB.getBasicBlock ();
unsigned Cond0Reg = makeAnotherReg (I.getType ());
unsigned Cond1Reg = makeAnotherReg (I.getType ());
F->getBasicBlockList ().push_back (Copy1MBB = new MachineBasicBlock (LLVM_BB));
F->getBasicBlockList ().push_back (Copy0MBB = new MachineBasicBlock (LLVM_BB));
F->getBasicBlockList ().push_back (CopyCondMBB = new MachineBasicBlock (LLVM_BB));
BuildMI (BB, Opcode, 1).addMBB (Copy1MBB);
BuildMI (BB, V8::BA, 1).addMBB (Copy0MBB);
IP = Copy1MBB->begin ();
BuildMI (*Copy1MBB, IP, V8::ORri, 2, Cond1Reg).addZImm (1).addReg (V8::G0);
BuildMI (*Copy1MBB, IP, V8::BA, 1).addMBB (CopyCondMBB);
IP = Copy0MBB->begin ();
BuildMI (*Copy0MBB, IP, V8::ORri, 2, Cond0Reg).addZImm (0).addReg (V8::G0);
BuildMI (*Copy0MBB, IP, V8::BA, 1).addMBB (CopyCondMBB);
// What should go in CopyCondMBB: PHI, then OR to copy cond. reg to DestReg
#endif
visitInstruction(I);
}

View File

@ -313,22 +313,44 @@ void V8ISel::visitCastInst(CastInst &I) {
unsigned oldTyClass = getClassB (oldTy);
unsigned newTyClass = getClassB (newTy);
if (oldTyClass < cLong && newTyClass < cLong && oldTyClass >= newTyClass) {
// Emit a reg->reg copy to do a equal-size or non-narrowing cast,
// and do sign/zero extension (necessary if we change signedness).
unsigned TempReg1 = makeAnotherReg (newTy);
unsigned TempReg2 = makeAnotherReg (newTy);
BuildMI (BB, V8::ORrr, 2, TempReg1).addReg (V8::G0).addReg (SrcReg);
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TempReg2).addZImm (shiftWidth).addReg (TempReg1);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg (TempReg2);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg (TempReg2);
if (oldTyClass < cLong && newTyClass < cLong) {
if (oldTyClass >= newTyClass) {
// Emit a reg->reg copy to do a equal-size or narrowing cast,
// and do sign/zero extension (necessary if we change signedness).
unsigned TmpReg1 = makeAnotherReg (newTy);
unsigned TmpReg2 = makeAnotherReg (newTy);
BuildMI (BB, V8::ORrr, 2, TmpReg1).addReg (V8::G0).addReg (SrcReg);
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
}
} else {
unsigned TmpReg1 = makeAnotherReg (oldTy);
unsigned TmpReg2 = makeAnotherReg (newTy);
unsigned TmpReg3 = makeAnotherReg (newTy);
// Widening integer cast. Make sure it's fully sign/zero-extended
// wrt the input type, then make sure it's fully sign/zero-extended wrt
// the output type. Kind of stupid, but simple...
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (oldTy));
BuildMI (BB, V8::SLLri, 2, TmpReg1).addZImm (shiftWidth).addReg(SrcReg);
if (oldTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
}
shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TmpReg3).addZImm (shiftWidth).addReg(TmpReg2);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
}
}
} else {
std::cerr << "Casts w/ long, fp, double, or widening still unsupported: "
<< I;
std::cerr << "Casts w/ long, fp, double still unsupported: " << I;
abort ();
}
}
@ -635,33 +657,53 @@ void V8ISel::visitSetCondInst(Instruction &I) {
unsigned Op0Reg = getReg (I.getOperand (0));
unsigned Op1Reg = getReg (I.getOperand (1));
unsigned DestReg = getReg (I);
const Type *Ty = I.getOperand (0)->getType ();
// Compare the two values.
BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
// Put 0 into a register.
//unsigned ZeroReg = makeAnotheRReg(Type::IntTy);
//BuildMI(BB, V8::ORri, 2, ZeroReg).addReg(V8::G0).addReg(V8::G0);
unsigned Opcode;
unsigned BranchIdx;
switch (I.getOpcode()) {
default: assert(0 && "Unknown setcc instruction!");
case Instruction::SetEQ:
case Instruction::SetNE:
case Instruction::SetLT:
case Instruction::SetGT:
case Instruction::SetLE:
case Instruction::SetGE:
;
case Instruction::SetEQ: BranchIdx = 0; break;
case Instruction::SetNE: BranchIdx = 1; break;
case Instruction::SetLT: BranchIdx = 2; break;
case Instruction::SetGT: BranchIdx = 3; break;
case Instruction::SetLE: BranchIdx = 4; break;
case Instruction::SetGE: BranchIdx = 5; break;
}
// FIXME: We need either conditional moves like the V9 has (e.g. movge), or we
// need to be able to turn a single LLVM basic block into multiple machine
// code basic blocks. For now, it probably makes sense to emit Sparc V9
// instructions until the code generator is upgraded. Note that this should
// only happen when the setcc cannot be folded into the branch, but this needs
// to be handled correctly!
static unsigned OpcodeTab[12] = {
// LLVM SparcV8
// unsigned signed
V8::BE, V8::BE, // seteq = be be
V8::BNE, V8::BNE, // setne = bne bne
V8::BCS, V8::BL, // setlt = bcs bl
V8::BGU, V8::BG, // setgt = bgu bg
V8::BLEU, V8::BLE, // setle = bleu ble
V8::BCC, V8::BGE // setge = bcc bge
};
unsigned Opcode = OpcodeTab[BranchIdx + (Ty->isSigned() ? 1 : 0)];
MachineBasicBlock *Copy1MBB, *Copy0MBB, *CopyCondMBB;
MachineBasicBlock::iterator IP;
#if 0
// Cond. Branch from BB --> either Copy1MBB or Copy0MBB --> CopyCondMBB
// Then once we're done with the SetCC, BB = CopyCondMBB.
BasicBlock *LLVM_BB = BB.getBasicBlock ();
unsigned Cond0Reg = makeAnotherReg (I.getType ());
unsigned Cond1Reg = makeAnotherReg (I.getType ());
F->getBasicBlockList ().push_back (Copy1MBB = new MachineBasicBlock (LLVM_BB));
F->getBasicBlockList ().push_back (Copy0MBB = new MachineBasicBlock (LLVM_BB));
F->getBasicBlockList ().push_back (CopyCondMBB = new MachineBasicBlock (LLVM_BB));
BuildMI (BB, Opcode, 1).addMBB (Copy1MBB);
BuildMI (BB, V8::BA, 1).addMBB (Copy0MBB);
IP = Copy1MBB->begin ();
BuildMI (*Copy1MBB, IP, V8::ORri, 2, Cond1Reg).addZImm (1).addReg (V8::G0);
BuildMI (*Copy1MBB, IP, V8::BA, 1).addMBB (CopyCondMBB);
IP = Copy0MBB->begin ();
BuildMI (*Copy0MBB, IP, V8::ORri, 2, Cond0Reg).addZImm (0).addReg (V8::G0);
BuildMI (*Copy0MBB, IP, V8::BA, 1).addMBB (CopyCondMBB);
// What should go in CopyCondMBB: PHI, then OR to copy cond. reg to DestReg
#endif
visitInstruction(I);
}

View File

@ -313,22 +313,44 @@ void V8ISel::visitCastInst(CastInst &I) {
unsigned oldTyClass = getClassB (oldTy);
unsigned newTyClass = getClassB (newTy);
if (oldTyClass < cLong && newTyClass < cLong && oldTyClass >= newTyClass) {
// Emit a reg->reg copy to do a equal-size or non-narrowing cast,
// and do sign/zero extension (necessary if we change signedness).
unsigned TempReg1 = makeAnotherReg (newTy);
unsigned TempReg2 = makeAnotherReg (newTy);
BuildMI (BB, V8::ORrr, 2, TempReg1).addReg (V8::G0).addReg (SrcReg);
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TempReg2).addZImm (shiftWidth).addReg (TempReg1);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg (TempReg2);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg (TempReg2);
if (oldTyClass < cLong && newTyClass < cLong) {
if (oldTyClass >= newTyClass) {
// Emit a reg->reg copy to do a equal-size or narrowing cast,
// and do sign/zero extension (necessary if we change signedness).
unsigned TmpReg1 = makeAnotherReg (newTy);
unsigned TmpReg2 = makeAnotherReg (newTy);
BuildMI (BB, V8::ORrr, 2, TmpReg1).addReg (V8::G0).addReg (SrcReg);
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
}
} else {
unsigned TmpReg1 = makeAnotherReg (oldTy);
unsigned TmpReg2 = makeAnotherReg (newTy);
unsigned TmpReg3 = makeAnotherReg (newTy);
// Widening integer cast. Make sure it's fully sign/zero-extended
// wrt the input type, then make sure it's fully sign/zero-extended wrt
// the output type. Kind of stupid, but simple...
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (oldTy));
BuildMI (BB, V8::SLLri, 2, TmpReg1).addZImm (shiftWidth).addReg(SrcReg);
if (oldTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
}
shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
BuildMI (BB, V8::SLLri, 2, TmpReg3).addZImm (shiftWidth).addReg(TmpReg2);
if (newTy->isSigned ()) { // sign-extend with SRA
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
} else { // zero-extend with SRL
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
}
}
} else {
std::cerr << "Casts w/ long, fp, double, or widening still unsupported: "
<< I;
std::cerr << "Casts w/ long, fp, double still unsupported: " << I;
abort ();
}
}
@ -635,33 +657,53 @@ void V8ISel::visitSetCondInst(Instruction &I) {
unsigned Op0Reg = getReg (I.getOperand (0));
unsigned Op1Reg = getReg (I.getOperand (1));
unsigned DestReg = getReg (I);
const Type *Ty = I.getOperand (0)->getType ();
// Compare the two values.
BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
// Put 0 into a register.
//unsigned ZeroReg = makeAnotheRReg(Type::IntTy);
//BuildMI(BB, V8::ORri, 2, ZeroReg).addReg(V8::G0).addReg(V8::G0);
unsigned Opcode;
unsigned BranchIdx;
switch (I.getOpcode()) {
default: assert(0 && "Unknown setcc instruction!");
case Instruction::SetEQ:
case Instruction::SetNE:
case Instruction::SetLT:
case Instruction::SetGT:
case Instruction::SetLE:
case Instruction::SetGE:
;
case Instruction::SetEQ: BranchIdx = 0; break;
case Instruction::SetNE: BranchIdx = 1; break;
case Instruction::SetLT: BranchIdx = 2; break;
case Instruction::SetGT: BranchIdx = 3; break;
case Instruction::SetLE: BranchIdx = 4; break;
case Instruction::SetGE: BranchIdx = 5; break;
}
// FIXME: We need either conditional moves like the V9 has (e.g. movge), or we
// need to be able to turn a single LLVM basic block into multiple machine
// code basic blocks. For now, it probably makes sense to emit Sparc V9
// instructions until the code generator is upgraded. Note that this should
// only happen when the setcc cannot be folded into the branch, but this needs
// to be handled correctly!
static unsigned OpcodeTab[12] = {
// LLVM SparcV8
// unsigned signed
V8::BE, V8::BE, // seteq = be be
V8::BNE, V8::BNE, // setne = bne bne
V8::BCS, V8::BL, // setlt = bcs bl
V8::BGU, V8::BG, // setgt = bgu bg
V8::BLEU, V8::BLE, // setle = bleu ble
V8::BCC, V8::BGE // setge = bcc bge
};
unsigned Opcode = OpcodeTab[BranchIdx + (Ty->isSigned() ? 1 : 0)];
MachineBasicBlock *Copy1MBB, *Copy0MBB, *CopyCondMBB;
MachineBasicBlock::iterator IP;
#if 0
// Cond. Branch from BB --> either Copy1MBB or Copy0MBB --> CopyCondMBB
// Then once we're done with the SetCC, BB = CopyCondMBB.
BasicBlock *LLVM_BB = BB.getBasicBlock ();
unsigned Cond0Reg = makeAnotherReg (I.getType ());
unsigned Cond1Reg = makeAnotherReg (I.getType ());
F->getBasicBlockList ().push_back (Copy1MBB = new MachineBasicBlock (LLVM_BB));
F->getBasicBlockList ().push_back (Copy0MBB = new MachineBasicBlock (LLVM_BB));
F->getBasicBlockList ().push_back (CopyCondMBB = new MachineBasicBlock (LLVM_BB));
BuildMI (BB, Opcode, 1).addMBB (Copy1MBB);
BuildMI (BB, V8::BA, 1).addMBB (Copy0MBB);
IP = Copy1MBB->begin ();
BuildMI (*Copy1MBB, IP, V8::ORri, 2, Cond1Reg).addZImm (1).addReg (V8::G0);
BuildMI (*Copy1MBB, IP, V8::BA, 1).addMBB (CopyCondMBB);
IP = Copy0MBB->begin ();
BuildMI (*Copy0MBB, IP, V8::ORri, 2, Cond0Reg).addZImm (0).addReg (V8::G0);
BuildMI (*Copy0MBB, IP, V8::BA, 1).addMBB (CopyCondMBB);
// What should go in CopyCondMBB: PHI, then OR to copy cond. reg to DestReg
#endif
visitInstruction(I);
}