mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-12 15:51:35 +00:00
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. llvm-svn: 13423
This commit is contained in:
parent
58fd2b0e4a
commit
7cc5d0f106
@ -313,22 +313,44 @@ void V8ISel::visitCastInst(CastInst &I) {
|
|||||||
unsigned oldTyClass = getClassB (oldTy);
|
unsigned oldTyClass = getClassB (oldTy);
|
||||||
unsigned newTyClass = getClassB (newTy);
|
unsigned newTyClass = getClassB (newTy);
|
||||||
|
|
||||||
if (oldTyClass < cLong && newTyClass < cLong && oldTyClass >= newTyClass) {
|
if (oldTyClass < cLong && newTyClass < cLong) {
|
||||||
// Emit a reg->reg copy to do a equal-size or non-narrowing cast,
|
if (oldTyClass >= newTyClass) {
|
||||||
// and do sign/zero extension (necessary if we change signedness).
|
// Emit a reg->reg copy to do a equal-size or narrowing cast,
|
||||||
unsigned TempReg1 = makeAnotherReg (newTy);
|
// and do sign/zero extension (necessary if we change signedness).
|
||||||
unsigned TempReg2 = makeAnotherReg (newTy);
|
unsigned TmpReg1 = makeAnotherReg (newTy);
|
||||||
BuildMI (BB, V8::ORrr, 2, TempReg1).addReg (V8::G0).addReg (SrcReg);
|
unsigned TmpReg2 = makeAnotherReg (newTy);
|
||||||
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
|
BuildMI (BB, V8::ORrr, 2, TmpReg1).addReg (V8::G0).addReg (SrcReg);
|
||||||
BuildMI (BB, V8::SLLri, 2, TempReg2).addZImm (shiftWidth).addReg (TempReg1);
|
unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
|
||||||
if (newTy->isSigned ()) { // sign-extend with SRA
|
BuildMI (BB, V8::SLLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
|
||||||
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg (TempReg2);
|
if (newTy->isSigned ()) { // sign-extend with SRA
|
||||||
} else { // zero-extend with SRL
|
BuildMI(BB, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
|
||||||
BuildMI(BB, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg (TempReg2);
|
} 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 {
|
} else {
|
||||||
std::cerr << "Casts w/ long, fp, double, or widening still unsupported: "
|
std::cerr << "Casts w/ long, fp, double still unsupported: " << I;
|
||||||
<< I;
|
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -635,33 +657,53 @@ void V8ISel::visitSetCondInst(Instruction &I) {
|
|||||||
unsigned Op0Reg = getReg (I.getOperand (0));
|
unsigned Op0Reg = getReg (I.getOperand (0));
|
||||||
unsigned Op1Reg = getReg (I.getOperand (1));
|
unsigned Op1Reg = getReg (I.getOperand (1));
|
||||||
unsigned DestReg = getReg (I);
|
unsigned DestReg = getReg (I);
|
||||||
|
const Type *Ty = I.getOperand (0)->getType ();
|
||||||
|
|
||||||
// Compare the two values.
|
// Compare the two values.
|
||||||
BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
|
BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
|
||||||
|
|
||||||
// Put 0 into a register.
|
unsigned BranchIdx;
|
||||||
//unsigned ZeroReg = makeAnotheRReg(Type::IntTy);
|
|
||||||
//BuildMI(BB, V8::ORri, 2, ZeroReg).addReg(V8::G0).addReg(V8::G0);
|
|
||||||
|
|
||||||
unsigned Opcode;
|
|
||||||
switch (I.getOpcode()) {
|
switch (I.getOpcode()) {
|
||||||
default: assert(0 && "Unknown setcc instruction!");
|
default: assert(0 && "Unknown setcc instruction!");
|
||||||
case Instruction::SetEQ:
|
case Instruction::SetEQ: BranchIdx = 0; break;
|
||||||
case Instruction::SetNE:
|
case Instruction::SetNE: BranchIdx = 1; break;
|
||||||
case Instruction::SetLT:
|
case Instruction::SetLT: BranchIdx = 2; break;
|
||||||
case Instruction::SetGT:
|
case Instruction::SetGT: BranchIdx = 3; break;
|
||||||
case Instruction::SetLE:
|
case Instruction::SetLE: BranchIdx = 4; break;
|
||||||
case Instruction::SetGE:
|
case Instruction::SetGE: BranchIdx = 5; break;
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
static unsigned OpcodeTab[12] = {
|
||||||
// FIXME: We need either conditional moves like the V9 has (e.g. movge), or we
|
// LLVM SparcV8
|
||||||
// need to be able to turn a single LLVM basic block into multiple machine
|
// unsigned signed
|
||||||
// code basic blocks. For now, it probably makes sense to emit Sparc V9
|
V8::BE, V8::BE, // seteq = be be
|
||||||
// instructions until the code generator is upgraded. Note that this should
|
V8::BNE, V8::BNE, // setne = bne bne
|
||||||
// only happen when the setcc cannot be folded into the branch, but this needs
|
V8::BCS, V8::BL, // setlt = bcs bl
|
||||||
// to be handled correctly!
|
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);
|
visitInstruction(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user