* cFP class split into cFP32 and cFP64

* Fn args passed in registers are now recorded as used by the call instruction
`-> asm printer updated to not print out those registers with the call instr
* Stack frame layout in prolog/epilog fixed, spills and vararg fns now work
* float/double to signed int codegen now correct
* various single precision float codegen bugs fixed
* const integer multiply codegen fixed
* select and setcc blocks inserted into the correct place in machine CFG
* load of integer constant code optimized

All of Shootout tests now work.  Great thanks to Nate Begeman for the patch!


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15014 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Misha Brukman 2004-07-20 00:41:46 +00:00
parent 4771288fe3
commit 7e898c3e04
2 changed files with 466 additions and 444 deletions

View File

@ -35,7 +35,7 @@ namespace {
/// PPC Representation.
///
enum TypeClass {
cByte, cShort, cInt, cFP, cLong
cByte, cShort, cInt, cFP32, cFP64, cLong
};
}
@ -52,11 +52,11 @@ static inline TypeClass getClass(const Type *Ty) {
case Type::UIntTyID:
case Type::PointerTyID: return cInt; // Ints and pointers are class #2
case Type::FloatTyID:
case Type::DoubleTyID: return cFP; // Floating Point is #3
case Type::FloatTyID: return cFP32; // Single float is #3
case Type::DoubleTyID: return cFP64; // Double Point is #4
case Type::LongTyID:
case Type::ULongTyID: return cLong; // Longs are class #4
case Type::ULongTyID: return cLong; // Longs are class #5
default:
assert(0 && "Invalid type to getClass!");
return cByte; // not reached
@ -80,8 +80,9 @@ namespace {
std::map<Value*, unsigned> RegMap; // Mapping between Values and SSA Regs
// External functions used in the Module
Function *fmodFn, *__moddi3Fn, *__divdi3Fn, *__umoddi3Fn, *__udivdi3Fn,
*__fixdfdiFn, *__floatdisfFn, *__floatdidfFn, *mallocFn, *freeFn;
Function *fmodfFn, *fmodFn, *__moddi3Fn, *__divdi3Fn, *__umoddi3Fn,
*__udivdi3Fn, *__fixsfdiFn, *__fixdfdiFn, *__floatdisfFn, *__floatdidfFn,
*mallocFn, *freeFn;
// MBBMap - Mapping between LLVM BB -> Machine BB
std::map<const BasicBlock*, MachineBasicBlock*> MBBMap;
@ -99,6 +100,8 @@ namespace {
Type *l = Type::LongTy;
Type *ul = Type::ULongTy;
Type *voidPtr = PointerType::get(Type::SByteTy);
// float fmodf(float, float);
fmodfFn = M.getOrInsertFunction("fmodf", f, f, f, 0);
// double fmod(double, double);
fmodFn = M.getOrInsertFunction("fmod", d, d, d, 0);
// long __moddi3(long, long);
@ -109,6 +112,8 @@ namespace {
__umoddi3Fn = M.getOrInsertFunction("__umoddi3", ul, ul, ul, 0);
// unsigned long __udivdi3(unsigned long, unsigned long);
__udivdi3Fn = M.getOrInsertFunction("__udivdi3", ul, ul, ul, 0);
// long __fixsfdi(float)
__fixdfdiFn = M.getOrInsertFunction("__fixsfdi", l, f, 0);
// long __fixdfdi(double)
__fixdfdiFn = M.getOrInsertFunction("__fixdfdi", l, d, 0);
// float __floatdisf(long)
@ -465,13 +470,29 @@ void ISel::copyConstantToRegister(MachineBasicBlock *MBB,
if (Class == cLong) {
// Copy the value into the register pair.
uint64_t Val = cast<ConstantInt>(C)->getRawValue();
unsigned hiTmp = makeAnotherReg(Type::IntTy);
unsigned loTmp = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC32::LIS, 1, loTmp).addImm(Val >> 48);
BuildMI(*MBB, IP, PPC32::ORI, 2, R).addReg(loTmp)
.addImm((Val >> 32) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::LIS, 1, hiTmp).addImm((Val >> 16) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::ORI, 2, R+1).addReg(hiTmp).addImm(Val & 0xFFFF);
if (Val < (1ULL << 16)) {
BuildMI(*MBB, IP, PPC32::LI, 1, R).addImm(Val & 0xFFFF);
BuildMI(*MBB, IP, PPC32::LI, 1, R+1).addImm(0);
} else if (Val < (1ULL << 32)) {
unsigned Temp = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC32::LIS, 1, Temp).addImm((Val >> 16) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::ORI, 2, R).addReg(Temp).addImm(Val & 0xFFFF);
BuildMI(*MBB, IP, PPC32::LI, 1, R+1).addImm(0);
} else if (Val < (1ULL << 48)) {
unsigned Temp = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC32::LIS, 1, Temp).addImm((Val >> 16) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::ORI, 2, R).addReg(Temp).addImm(Val & 0xFFFF);
BuildMI(*MBB, IP, PPC32::LI, 1, R+1).addImm((Val >> 32) & 0xFFFF);
} else {
unsigned TempLo = makeAnotherReg(Type::IntTy);
unsigned TempHi = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC32::LIS, 1, TempLo).addImm((Val >> 16) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::ORI, 2, R).addReg(TempLo).addImm(Val & 0xFFFF);
BuildMI(*MBB, IP, PPC32::LIS, 1, TempHi).addImm((Val >> 48) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::ORI, 2, R+1).addReg(TempHi)
.addImm((Val >> 32) & 0xFFFF);
}
return;
}
@ -613,32 +634,40 @@ void ISel::LoadArgumentsToVirtualRegs(Function &Fn) {
GPR_idx++;
}
break;
case cFP:
if (ArgLive) {
unsigned Opcode;
if (I->getType() == Type::FloatTy) {
Opcode = PPC32::LFS;
FI = MFI->CreateFixedObject(4, ArgOffset);
} else {
Opcode = PPC32::LFD;
FI = MFI->CreateFixedObject(8, ArgOffset);
}
case cFP32:
if (ArgLive) {
FI = MFI->CreateFixedObject(4, ArgOffset);
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::IMPLICIT_DEF, 0, FPR[FPR_idx]);
BuildMI(BB, PPC32::FMR, 1, Reg).addReg(FPR[FPR_idx]);
FPR_remaining--;
FPR_idx++;
} else {
addFrameReference(BuildMI(BB, Opcode, 2, Reg), FI);
addFrameReference(BuildMI(BB, PPC32::LFS, 2, Reg), FI);
}
}
if (I->getType() == Type::DoubleTy) {
ArgOffset += 4; // doubles require 4 additional bytes
if (GPR_remaining > 0) {
GPR_remaining--; // uses up 2 GPRs
GPR_idx++;
break;
case cFP64:
if (ArgLive) {
FI = MFI->CreateFixedObject(8, ArgOffset);
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::IMPLICIT_DEF, 0, FPR[FPR_idx]);
BuildMI(BB, PPC32::FMR, 1, Reg).addReg(FPR[FPR_idx]);
FPR_remaining--;
FPR_idx++;
} else {
addFrameReference(BuildMI(BB, PPC32::LFD, 2, Reg), FI);
}
}
// doubles require 4 additional bytes and use 2 GPRs of param space
ArgOffset += 4;
if (GPR_remaining > 0) {
GPR_remaining--;
GPR_idx++;
}
break;
default:
assert(0 && "Unhandled argument type!");
@ -917,7 +946,8 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
PPC32::CR0).addReg(Op0r).addReg(Op1r);
break;
case cFP:
case cFP32:
case cFP64:
emitUCOM(MBB, IP, Op0r, Op1r);
break;
@ -966,8 +996,6 @@ void ISel::visitSetCondInst(SetCondInst &I) {
if (canFoldSetCCIntoBranchOrSelect(&I))
return;
unsigned Op0Reg = getReg(I.getOperand(0));
unsigned Op1Reg = getReg(I.getOperand(1));
unsigned DestReg = getReg(I);
unsigned OpNum = I.getOpcode();
const Type *Ty = I.getOperand (0)->getType();
@ -977,6 +1005,9 @@ void ISel::visitSetCondInst(SetCondInst &I) {
unsigned Opcode = getPPCOpcodeForSetCCNumber(OpNum);
MachineBasicBlock *thisMBB = BB;
const BasicBlock *LLVM_BB = BB->getBasicBlock();
ilist<MachineBasicBlock>::iterator It = BB;
++It;
// thisMBB:
// ...
// cmpTY cr0, r1, r2
@ -987,10 +1018,10 @@ void ISel::visitSetCondInst(SetCondInst &I) {
// if we could insert other, non-terminator instructions after the
// bCC. But MBB->getFirstTerminator() can't understand this.
MachineBasicBlock *copy1MBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(copy1MBB);
F->getBasicBlockList().insert(It, copy1MBB);
BuildMI(BB, Opcode, 2).addReg(PPC32::CR0).addMBB(copy1MBB);
MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(copy0MBB);
F->getBasicBlockList().insert(It, copy0MBB);
BuildMI(BB, PPC32::B, 1).addMBB(copy0MBB);
// Update machine-CFG edges
BB->addSuccessor(copy1MBB);
@ -1003,7 +1034,7 @@ void ISel::visitSetCondInst(SetCondInst &I) {
unsigned FalseValue = makeAnotherReg(I.getType());
BuildMI(BB, PPC32::LI, 1, FalseValue).addImm(0);
MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(sinkMBB);
F->getBasicBlockList().insert(It, sinkMBB);
BuildMI(BB, PPC32::B, 1).addMBB(sinkMBB);
// Update machine-CFG edges
BB->addSuccessor(sinkMBB);
@ -1047,29 +1078,10 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
Value *Cond, Value *TrueVal, Value *FalseVal,
unsigned DestReg) {
unsigned SelectClass = getClassB(TrueVal->getType());
unsigned Opcode;
/*
unsigned TrueReg = getReg(TrueVal, MBB, IP);
unsigned FalseReg = getReg(FalseVal, MBB, IP);
if (TrueReg == FalseReg) {
if (SelectClass == cFP) {
BuildMI(*MBB, IP, PPC32::FMR, 1, DestReg).addReg(TrueReg);
} else {
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(TrueReg).addReg(TrueReg);
}
if (SelectClass == cLong)
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(TrueReg+1)
.addReg(TrueReg+1);
return;
}
*/
// See if we can fold the setcc into the select instruction, or if we have
// to get the register of the Cond value
unsigned Opcode;
if (SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(Cond)) {
// We successfully folded the setcc into the select instruction.
@ -1092,15 +1104,17 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
MachineBasicBlock *thisMBB = BB;
const BasicBlock *LLVM_BB = BB->getBasicBlock();
ilist<MachineBasicBlock>::iterator It = BB;
++It;
// FIXME: we wouldn't need copy0MBB (we could fold it into thisMBB)
// if we could insert other, non-terminator instructions after the
// bCC. But MBB->getFirstTerminator() can't understand this.
MachineBasicBlock *copy1MBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(copy1MBB);
F->getBasicBlockList().insert(It, copy1MBB);
BuildMI(BB, Opcode, 2).addReg(PPC32::CR0).addMBB(copy1MBB);
MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(copy0MBB);
F->getBasicBlockList().insert(It, copy0MBB);
BuildMI(BB, PPC32::B, 1).addMBB(copy0MBB);
// Update machine-CFG edges
BB->addSuccessor(copy1MBB);
@ -1115,7 +1129,7 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
BB = copy0MBB;
unsigned FalseValue = getReg(FalseVal, BB, BB->begin());
MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(sinkMBB);
F->getBasicBlockList().insert(It, sinkMBB);
BuildMI(BB, PPC32::B, 1).addMBB(sinkMBB);
// Update machine-CFG edges
BB->addSuccessor(sinkMBB);
@ -1211,7 +1225,8 @@ void ISel::visitReturnInst(ReturnInst &I) {
case cInt:
promote32(PPC32::R3, ValueRecord(RetVal));
break;
case cFP: { // Floats & Doubles: Return in f1
case cFP32:
case cFP64: { // Floats & Doubles: Return in f1
unsigned RetReg = getReg(RetVal);
BuildMI(BB, PPC32::FMR, 1, PPC32::F1).addReg(RetReg);
break;
@ -1329,8 +1344,10 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
NumBytes += 4; break;
case cLong:
NumBytes += 8; break;
case cFP:
NumBytes += Args[i].Ty == Type::FloatTy ? 4 : 8;
case cFP32:
NumBytes += 4; break;
case cFP64:
NumBytes += 8; break;
break;
default: assert(0 && "Unknown class!");
}
@ -1339,7 +1356,8 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
BuildMI(BB, PPC32::ADJCALLSTACKDOWN, 1).addImm(NumBytes);
// Arguments go on the stack in reverse order, as specified by the ABI.
unsigned ArgOffset = 0;
// Offset to the paramater area on the stack is 24.
unsigned ArgOffset = 24;
int GPR_remaining = 8, FPR_remaining = 13;
unsigned GPR_idx = 0, FPR_idx = 0;
static const unsigned GPR[] = {
@ -1365,6 +1383,7 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
if (GPR_remaining > 0) {
BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx]).addReg(ArgReg)
.addReg(ArgReg);
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
} else {
BuildMI(BB, PPC32::STW, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
@ -1377,6 +1396,7 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
if (GPR_remaining > 0) {
BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx]).addReg(ArgReg)
.addReg(ArgReg);
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
} else {
BuildMI(BB, PPC32::STW, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
@ -1389,8 +1409,10 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
if (GPR_remaining > 1) {
BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx]).addReg(ArgReg)
.addReg(ArgReg);
BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx + 1]).addReg(ArgReg+1)
BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx+1]).addReg(ArgReg+1)
.addReg(ArgReg+1);
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
CallMI->addRegOperand(GPR[GPR_idx+1], MachineOperand::Use);
} else {
BuildMI(BB, PPC32::STW, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
@ -1402,70 +1424,63 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
GPR_remaining -= 1; // uses up 2 GPRs
GPR_idx += 1;
break;
case cFP:
case cFP32:
ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
if (Args[i].Ty == Type::FloatTy) {
assert(!isVarArg && "Cannot pass floats to vararg functions!");
// Reg or stack?
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
FPR_remaining--;
FPR_idx++;
} else {
// Reg or stack?
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
CallMI->addRegOperand(FPR[FPR_idx], MachineOperand::Use);
FPR_remaining--;
FPR_idx++;
// If this is a vararg function, and there are GPRs left, also
// pass the float in an int. Otherwise, put it on the stack.
if (isVarArg) {
BuildMI(BB, PPC32::STFS, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
.addReg(PPC32::R1);
if (GPR_remaining > 0) {
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx])
.addImm(ArgOffset).addReg(ArgReg);
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
}
}
} else {
assert(Args[i].Ty == Type::DoubleTy && "Unknown FP type!");
// Reg or stack?
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
FPR_remaining--;
FPR_idx++;
// For vararg functions, must pass doubles via int regs as well
if (isVarArg) {
Value *Val = Args[i].Val;
if (ConstantFP *CFP = dyn_cast<ConstantFP>(Val)) {
union DU {
double FVal;
struct {
uint32_t hi32;
uint32_t lo32;
} UVal;
} U;
U.FVal = CFP->getValue();
if (GPR_remaining > 0) {
Constant *hi32 = minUConstantForValue(U.UVal.hi32);
copyConstantToRegister(BB, BB->end(), hi32, GPR[GPR_idx]);
}
if (GPR_remaining > 1) {
Constant *lo32 = minUConstantForValue(U.UVal.lo32);
copyConstantToRegister(BB, BB->end(), lo32, GPR[GPR_idx+1]);
}
} else {
// Since this is not a constant, we must load it into int regs
// via memory
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
if (GPR_remaining > 0)
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx]).addImm(ArgOffset)
.addReg(PPC32::R1);
if (GPR_remaining > 1)
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx+1])
.addImm(ArgOffset+4).addReg(PPC32::R1);
}
}
} else {
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
}
ArgOffset += 4; // 8 byte entry, not 4.
GPR_remaining--; // uses up 2 GPRs
GPR_idx++;
BuildMI(BB, PPC32::STFS, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
}
break;
case cFP64:
ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
// Reg or stack?
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
CallMI->addRegOperand(FPR[FPR_idx], MachineOperand::Use);
FPR_remaining--;
FPR_idx++;
// For vararg functions, must pass doubles via int regs as well
if (isVarArg) {
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
if (GPR_remaining > 1) {
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx]).addImm(ArgOffset)
.addReg(PPC32::R1);
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx+1])
.addImm(ArgOffset+4).addReg(PPC32::R1);
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
CallMI->addRegOperand(GPR[GPR_idx+1], MachineOperand::Use);
}
}
} else {
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
}
// Doubles use 8 bytes, and 2 GPRs worth of param space
ArgOffset += 4;
GPR_remaining--;
GPR_idx++;
break;
default: assert(0 && "Unknown class!");
}
ArgOffset += 4;
@ -1491,7 +1506,8 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
// Integral results are in r3
BuildMI(BB, PPC32::OR, 2, Ret.Reg).addReg(PPC32::R3).addReg(PPC32::R3);
break;
case cFP: // Floating-point return values live in f1
case cFP32: // Floating-point return values live in f1
case cFP64:
BuildMI(BB, PPC32::FMR, 1, Ret.Reg).addReg(PPC32::F1);
break;
case cLong: // Long values are in r3:r4
@ -1519,8 +1535,8 @@ void ISel::visitCallInst(CallInst &CI) {
TheCall = BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(F, true);
} else { // Emit an indirect call through the CTR
unsigned Reg = getReg(CI.getCalledValue());
BuildMI(BB, PPC32::MTSPR, 2).addZImm(9).addReg(Reg);
TheCall = BuildMI(PPC32::CALLindirect, 1).addZImm(20).addZImm(0);
BuildMI(BB, PPC32::MTCTR, 1).addReg(Reg);
TheCall = BuildMI(PPC32::CALLindirect, 2).addZImm(20).addZImm(0);
}
std::vector<ValueRecord> Args;
@ -1766,7 +1782,7 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
PPC32::ADDE, PPC32::SUBFE, PPC32::AND, PPC32::OR, PPC32::XOR
};
if (Class == cFP) {
if (Class == cFP32 || Class == cFP64) {
assert(OperatorClass < 2 && "No logical ops for FP!");
emitBinaryFPOperation(MBB, IP, Op0, Op1, OperatorClass, DestReg);
return;
@ -1859,9 +1875,9 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
// with 0xFFFFFFFF00000000 -> noop, etc.
BuildMI(*MBB, IP, BottomTab[OperatorClass], 2, DestReg).addReg(Op0r)
.addImm(Op1r);
.addReg(Op1r);
BuildMI(*MBB, IP, TopTab[OperatorClass], 2, DestReg+1).addReg(Op0r+1)
.addImm(Op1r+1);
.addReg(Op1r+1);
return;
}
@ -1873,9 +1889,9 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(Op0r).addReg(Op1r);
} else {
BuildMI(*MBB, IP, BottomTab[OperatorClass], 2, DestReg).addReg(Op0r)
.addImm(Op1r);
.addReg(Op1r);
BuildMI(*MBB, IP, TopTab[OperatorClass], 2, DestReg+1).addReg(Op0r+1)
.addImm(Op1r+1);
.addReg(Op1r+1);
}
return;
}
@ -1950,18 +1966,11 @@ void ISel::doMultiplyConst(MachineBasicBlock *MBB,
}
// Most general case, emit a normal multiply...
unsigned TmpReg1 = makeAnotherReg(Type::IntTy);
unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
unsigned TmpReg3 = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC32::LIS, 1, TmpReg1).addImm(ConstRHS >> 16);
BuildMI(*MBB, IP, PPC32::RLWINM, 4, TmpReg2).addReg(TmpReg1)
.addImm(16).addImm(0).addImm(15);
BuildMI(*MBB, IP, PPC32::ORI, 2, TmpReg3).addReg(TmpReg2)
.addImm(ConstRHS & 0xFFFF);
// Emit a MUL to multiply the register holding the index by
// elementSize, putting the result in OffsetReg.
doMultiply(MBB, IP, DestReg, DestTy, op0Reg, TmpReg3);
unsigned TmpReg = makeAnotherReg(Type::IntTy);
Constant *C = ConstantUInt::get(Type::UIntTy, ConstRHS);
copyConstantToRegister(MBB, IP, C, TmpReg);
doMultiply(MBB, IP, DestReg, DestTy, op0Reg, TmpReg);
}
void ISel::visitMul(BinaryOperator &I) {
@ -1993,7 +2002,8 @@ void ISel::emitMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
doMultiply(&BB, IP, DestReg, Op1->getType(), Op0Reg, Op1Reg);
}
return;
case cFP:
case cFP32:
case cFP64:
emitBinaryFPOperation(MBB, IP, Op0, Op1, 2, DestReg);
return;
case cLong:
@ -2098,11 +2108,30 @@ void ISel::emitDivRemOperation(MachineBasicBlock *BB,
const Type *Ty = Op0->getType();
unsigned Class = getClass(Ty);
switch (Class) {
case cFP: // Floating point divide
case cFP32:
if (isDiv) {
// Floating point divide...
emitBinaryFPOperation(BB, IP, Op0, Op1, 3, ResultReg);
return;
} else { // Floating point remainder...
} else {
// Floating point remainder via fmodf(float x, float y);
unsigned Op0Reg = getReg(Op0, BB, IP);
unsigned Op1Reg = getReg(Op1, BB, IP);
MachineInstr *TheCall =
BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(fmodfFn, true);
std::vector<ValueRecord> Args;
Args.push_back(ValueRecord(Op0Reg, Type::FloatTy));
Args.push_back(ValueRecord(Op1Reg, Type::FloatTy));
doCall(ValueRecord(ResultReg, Type::FloatTy), TheCall, Args, false);
}
return;
case cFP64:
if (isDiv) {
// Floating point divide...
emitBinaryFPOperation(BB, IP, Op0, Op1, 3, ResultReg);
return;
} else {
// Floating point remainder via fmod(double x, double y);
unsigned Op0Reg = getReg(Op0, BB, IP);
unsigned Op1Reg = getReg(Op1, BB, IP);
MachineInstr *TheCall =
@ -2114,7 +2143,7 @@ void ISel::emitDivRemOperation(MachineBasicBlock *BB,
}
return;
case cLong: {
static Function* const Funcs[] =
static Function* const Funcs[] =
{ __moddi3Fn, __divdi3Fn, __umoddi3Fn, __udivdi3Fn };
unsigned Op0Reg = getReg(Op0, BB, IP);
unsigned Op1Reg = getReg(Op1, BB, IP);
@ -2453,14 +2482,14 @@ void ISel::visitCastInst(CastInst &CI) {
/// emitCastOperation - Common code shared between visitCastInst and constant
/// expression cast support.
///
void ISel::emitCastOperation(MachineBasicBlock *BB,
void ISel::emitCastOperation(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP,
Value *Src, const Type *DestTy,
unsigned DestReg) {
const Type *SrcTy = Src->getType();
unsigned SrcClass = getClassB(SrcTy);
unsigned DestClass = getClassB(DestTy);
unsigned SrcReg = getReg(Src, BB, IP);
unsigned SrcReg = getReg(Src, MBB, IP);
// Implement casts to bool by using compare on the operand followed by set if
// not zero on the result.
@ -2470,29 +2499,21 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
case cShort:
case cInt: {
unsigned TmpReg = makeAnotherReg(Type::IntTy);
BuildMI(*BB, IP, PPC32::ADDIC, 2, TmpReg).addReg(SrcReg).addImm(-1);
BuildMI(*BB, IP, PPC32::SUBFE, 2, DestReg).addReg(TmpReg).addReg(SrcReg);
BuildMI(*MBB, IP, PPC32::ADDIC, 2, TmpReg).addReg(SrcReg).addImm(-1);
BuildMI(*MBB, IP, PPC32::SUBFE, 2, DestReg).addReg(TmpReg).addReg(SrcReg);
break;
}
case cLong: {
unsigned TmpReg = makeAnotherReg(Type::IntTy);
unsigned SrcReg2 = makeAnotherReg(Type::IntTy);
BuildMI(*BB, IP, PPC32::OR, 2, SrcReg2).addReg(SrcReg).addReg(SrcReg+1);
BuildMI(*BB, IP, PPC32::ADDIC, 2, TmpReg).addReg(SrcReg2).addImm(-1);
BuildMI(*BB, IP, PPC32::SUBFE, 2, DestReg).addReg(TmpReg).addReg(SrcReg2);
BuildMI(*MBB, IP, PPC32::OR, 2, SrcReg2).addReg(SrcReg).addReg(SrcReg+1);
BuildMI(*MBB, IP, PPC32::ADDIC, 2, TmpReg).addReg(SrcReg2).addImm(-1);
BuildMI(*MBB, IP, PPC32::SUBFE, 2, DestReg).addReg(TmpReg).addReg(SrcReg2);
break;
}
case cFP:
// FIXME
// Load -0.0
// Compare
// move to CR1
// Negate -0.0
// Compare
// CROR
// MFCR
// Left-align
// SRA ?
case cFP32:
case cFP64:
// FSEL perhaps?
std::cerr << "Cast fp-to-bool not implemented!";
abort();
}
@ -2503,21 +2524,12 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
// getClass) by using a register-to-register move.
if (SrcClass == DestClass) {
if (SrcClass <= cInt) {
BuildMI(*BB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
} else if (SrcClass == cFP && SrcTy == DestTy) {
BuildMI(*BB, IP, PPC32::FMR, 1, DestReg).addReg(SrcReg);
} else if (SrcClass == cFP) {
if (SrcTy == Type::FloatTy) { // float -> double
assert(DestTy == Type::DoubleTy && "Unknown cFP member!");
BuildMI(*BB, IP, PPC32::FMR, 1, DestReg).addReg(SrcReg);
} else { // double -> float
assert(SrcTy == Type::DoubleTy && DestTy == Type::FloatTy &&
"Unknown cFP member!");
BuildMI(*BB, IP, PPC32::FRSP, 1, DestReg).addReg(SrcReg);
}
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
} else if (SrcClass == cFP32 || SrcClass == cFP64) {
BuildMI(*MBB, IP, PPC32::FMR, 1, DestReg).addReg(SrcReg);
} else if (SrcClass == cLong) {
BuildMI(*BB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
BuildMI(*BB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg+1)
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg+1)
.addReg(SrcReg+1);
} else {
assert(0 && "Cannot handle this type of cast instruction!");
@ -2525,7 +2537,19 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
}
return;
}
// Handle cast of Float -> Double
if (SrcClass == cFP32 && DestClass == cFP64) {
BuildMI(*MBB, IP, PPC32::FMR, 1, DestReg).addReg(SrcReg);
return;
}
// Handle cast of Double -> Float
if (SrcClass == cFP64 && DestClass == cFP32) {
BuildMI(*MBB, IP, PPC32::FRSP, 1, DestReg).addReg(SrcReg);
return;
}
// Handle cast of SMALLER int to LARGER int using a move with sign extension
// or zero extension, depending on whether the source type was signed.
if (SrcClass <= cInt && (DestClass <= cInt || DestClass == cLong) &&
@ -2578,46 +2602,23 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
}
// Handle casts from integer to floating point now...
if (DestClass == cFP) {
if (DestClass == cFP32 || DestClass == cFP64) {
// Emit a library call for long to float conversion
if (SrcClass == cLong) {
std::vector<ValueRecord> Args;
Args.push_back(ValueRecord(SrcReg, SrcTy));
Function *floatFn = (SrcTy==Type::FloatTy) ? __floatdisfFn : __floatdidfFn;
Function *floatFn = (DestClass == cFP32) ? __floatdisfFn : __floatdidfFn;
MachineInstr *TheCall =
BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(floatFn, true);
doCall(ValueRecord(DestReg, DestTy), TheCall, Args, false);
return;
}
unsigned TmpReg = makeAnotherReg(Type::IntTy);
switch (SrcTy->getTypeID()) {
case Type::BoolTyID:
case Type::SByteTyID:
BuildMI(*BB, IP, PPC32::EXTSB, 1, TmpReg).addReg(SrcReg);
break;
case Type::UByteTyID:
BuildMI(*BB, IP, PPC32::RLWINM, 4, TmpReg).addReg(SrcReg).addZImm(0)
.addImm(24).addImm(31);
break;
case Type::ShortTyID:
BuildMI(*BB, IP, PPC32::EXTSB, 1, TmpReg).addReg(SrcReg);
break;
case Type::UShortTyID:
BuildMI(*BB, IP, PPC32::RLWINM, 4, TmpReg).addReg(SrcReg).addZImm(0)
.addImm(16).addImm(31);
break;
case Type::IntTyID:
BuildMI(*BB, IP, PPC32::OR, 2, TmpReg).addReg(SrcReg).addReg(SrcReg);
break;
case Type::UIntTyID:
BuildMI(*BB, IP, PPC32::OR, 2, TmpReg).addReg(SrcReg).addReg(SrcReg);
break;
default: // No promotion needed...
break;
}
// Make sure we're dealing with a full 32 bits
unsigned TmpReg = makeAnotherReg(Type::IntTy);
promote32(TmpReg, ValueRecord(SrcReg, SrcTy));
SrcReg = TmpReg;
// Spill the integer to memory and reload it from there.
@ -2669,34 +2670,44 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
}
// Handle casts from floating point to integer now...
if (SrcClass == cFP) {
if (SrcClass == cFP32 || SrcClass == cFP64) {
// emit library call
if (DestClass == cLong) {
std::vector<ValueRecord> Args;
Args.push_back(ValueRecord(SrcReg, SrcTy));
Function *floatFn = (DestClass == cFP32) ? __fixsfdiFn : __fixdfdiFn;
MachineInstr *TheCall =
BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(__fixdfdiFn, true);
BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(floatFn, true);
doCall(ValueRecord(DestReg, DestTy), TheCall, Args, false);
return;
}
int ValueFrameIdx =
F->getFrameInfo()->CreateStackObject(Type::DoubleTy, TM.getTargetData());
F->getFrameInfo()->CreateStackObject(SrcTy, TM.getTargetData());
// load into 32 bit value, and then truncate as necessary
// FIXME: This is wrong for unsigned dest types
//if (DestTy->isSigned()) {
if (DestTy->isSigned()) {
unsigned LoadOp = (DestClass == cShort) ? PPC32::LHA : PPC32::LWZ;
unsigned TempReg = makeAnotherReg(Type::DoubleTy);
// Convert to integer in the FP reg and store it to a stack slot
BuildMI(*BB, IP, PPC32::FCTIWZ, 1, TempReg).addReg(SrcReg);
addFrameReference(BuildMI(*BB, IP, PPC32::STFD, 3)
.addReg(TempReg), ValueFrameIdx);
addFrameReference(BuildMI(*BB, IP, PPC32::LWZ, 2, DestReg),
ValueFrameIdx+4);
//} else {
//}
// FIXME: Truncate return value
// There is no load signed byte opcode, so we must emit a sign extend
if (DestClass == cByte) {
unsigned TempReg2 = makeAnotherReg(DestTy);
addFrameReference(BuildMI(*BB, IP, LoadOp, 2, TempReg2),
ValueFrameIdx+4);
BuildMI(*MBB, IP, PPC32::EXTSB, DestReg).addReg(TempReg2);
} else {
addFrameReference(BuildMI(*BB, IP, LoadOp, 2, DestReg),
ValueFrameIdx+4);
}
} else {
std::cerr << "Cast fp-to-unsigned not implemented!";
abort();
}
return;
}
@ -2851,8 +2862,8 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
// Emit an ADD to add OffsetReg to the basePtr.
unsigned Reg = makeAnotherReg(Type::UIntTy);
BuildMI(*MBB, IP, PPC32::ADD, 2, TargetReg).addReg(Reg).addReg(OffsetReg);
BuildMI(*MBB, IP, PPC32::ADD,2,TargetReg).addReg(Reg).addReg(OffsetReg);
// Step to the first instruction of the multiply.
if (BeforeIt == MBB->end())
IP = MBB->begin();

View File

@ -35,7 +35,7 @@ namespace {
/// PPC Representation.
///
enum TypeClass {
cByte, cShort, cInt, cFP, cLong
cByte, cShort, cInt, cFP32, cFP64, cLong
};
}
@ -52,11 +52,11 @@ static inline TypeClass getClass(const Type *Ty) {
case Type::UIntTyID:
case Type::PointerTyID: return cInt; // Ints and pointers are class #2
case Type::FloatTyID:
case Type::DoubleTyID: return cFP; // Floating Point is #3
case Type::FloatTyID: return cFP32; // Single float is #3
case Type::DoubleTyID: return cFP64; // Double Point is #4
case Type::LongTyID:
case Type::ULongTyID: return cLong; // Longs are class #4
case Type::ULongTyID: return cLong; // Longs are class #5
default:
assert(0 && "Invalid type to getClass!");
return cByte; // not reached
@ -80,8 +80,9 @@ namespace {
std::map<Value*, unsigned> RegMap; // Mapping between Values and SSA Regs
// External functions used in the Module
Function *fmodFn, *__moddi3Fn, *__divdi3Fn, *__umoddi3Fn, *__udivdi3Fn,
*__fixdfdiFn, *__floatdisfFn, *__floatdidfFn, *mallocFn, *freeFn;
Function *fmodfFn, *fmodFn, *__moddi3Fn, *__divdi3Fn, *__umoddi3Fn,
*__udivdi3Fn, *__fixsfdiFn, *__fixdfdiFn, *__floatdisfFn, *__floatdidfFn,
*mallocFn, *freeFn;
// MBBMap - Mapping between LLVM BB -> Machine BB
std::map<const BasicBlock*, MachineBasicBlock*> MBBMap;
@ -99,6 +100,8 @@ namespace {
Type *l = Type::LongTy;
Type *ul = Type::ULongTy;
Type *voidPtr = PointerType::get(Type::SByteTy);
// float fmodf(float, float);
fmodfFn = M.getOrInsertFunction("fmodf", f, f, f, 0);
// double fmod(double, double);
fmodFn = M.getOrInsertFunction("fmod", d, d, d, 0);
// long __moddi3(long, long);
@ -109,6 +112,8 @@ namespace {
__umoddi3Fn = M.getOrInsertFunction("__umoddi3", ul, ul, ul, 0);
// unsigned long __udivdi3(unsigned long, unsigned long);
__udivdi3Fn = M.getOrInsertFunction("__udivdi3", ul, ul, ul, 0);
// long __fixsfdi(float)
__fixdfdiFn = M.getOrInsertFunction("__fixsfdi", l, f, 0);
// long __fixdfdi(double)
__fixdfdiFn = M.getOrInsertFunction("__fixdfdi", l, d, 0);
// float __floatdisf(long)
@ -465,13 +470,29 @@ void ISel::copyConstantToRegister(MachineBasicBlock *MBB,
if (Class == cLong) {
// Copy the value into the register pair.
uint64_t Val = cast<ConstantInt>(C)->getRawValue();
unsigned hiTmp = makeAnotherReg(Type::IntTy);
unsigned loTmp = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC32::LIS, 1, loTmp).addImm(Val >> 48);
BuildMI(*MBB, IP, PPC32::ORI, 2, R).addReg(loTmp)
.addImm((Val >> 32) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::LIS, 1, hiTmp).addImm((Val >> 16) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::ORI, 2, R+1).addReg(hiTmp).addImm(Val & 0xFFFF);
if (Val < (1ULL << 16)) {
BuildMI(*MBB, IP, PPC32::LI, 1, R).addImm(Val & 0xFFFF);
BuildMI(*MBB, IP, PPC32::LI, 1, R+1).addImm(0);
} else if (Val < (1ULL << 32)) {
unsigned Temp = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC32::LIS, 1, Temp).addImm((Val >> 16) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::ORI, 2, R).addReg(Temp).addImm(Val & 0xFFFF);
BuildMI(*MBB, IP, PPC32::LI, 1, R+1).addImm(0);
} else if (Val < (1ULL << 48)) {
unsigned Temp = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC32::LIS, 1, Temp).addImm((Val >> 16) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::ORI, 2, R).addReg(Temp).addImm(Val & 0xFFFF);
BuildMI(*MBB, IP, PPC32::LI, 1, R+1).addImm((Val >> 32) & 0xFFFF);
} else {
unsigned TempLo = makeAnotherReg(Type::IntTy);
unsigned TempHi = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC32::LIS, 1, TempLo).addImm((Val >> 16) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::ORI, 2, R).addReg(TempLo).addImm(Val & 0xFFFF);
BuildMI(*MBB, IP, PPC32::LIS, 1, TempHi).addImm((Val >> 48) & 0xFFFF);
BuildMI(*MBB, IP, PPC32::ORI, 2, R+1).addReg(TempHi)
.addImm((Val >> 32) & 0xFFFF);
}
return;
}
@ -613,32 +634,40 @@ void ISel::LoadArgumentsToVirtualRegs(Function &Fn) {
GPR_idx++;
}
break;
case cFP:
if (ArgLive) {
unsigned Opcode;
if (I->getType() == Type::FloatTy) {
Opcode = PPC32::LFS;
FI = MFI->CreateFixedObject(4, ArgOffset);
} else {
Opcode = PPC32::LFD;
FI = MFI->CreateFixedObject(8, ArgOffset);
}
case cFP32:
if (ArgLive) {
FI = MFI->CreateFixedObject(4, ArgOffset);
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::IMPLICIT_DEF, 0, FPR[FPR_idx]);
BuildMI(BB, PPC32::FMR, 1, Reg).addReg(FPR[FPR_idx]);
FPR_remaining--;
FPR_idx++;
} else {
addFrameReference(BuildMI(BB, Opcode, 2, Reg), FI);
addFrameReference(BuildMI(BB, PPC32::LFS, 2, Reg), FI);
}
}
if (I->getType() == Type::DoubleTy) {
ArgOffset += 4; // doubles require 4 additional bytes
if (GPR_remaining > 0) {
GPR_remaining--; // uses up 2 GPRs
GPR_idx++;
break;
case cFP64:
if (ArgLive) {
FI = MFI->CreateFixedObject(8, ArgOffset);
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::IMPLICIT_DEF, 0, FPR[FPR_idx]);
BuildMI(BB, PPC32::FMR, 1, Reg).addReg(FPR[FPR_idx]);
FPR_remaining--;
FPR_idx++;
} else {
addFrameReference(BuildMI(BB, PPC32::LFD, 2, Reg), FI);
}
}
// doubles require 4 additional bytes and use 2 GPRs of param space
ArgOffset += 4;
if (GPR_remaining > 0) {
GPR_remaining--;
GPR_idx++;
}
break;
default:
assert(0 && "Unhandled argument type!");
@ -917,7 +946,8 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
PPC32::CR0).addReg(Op0r).addReg(Op1r);
break;
case cFP:
case cFP32:
case cFP64:
emitUCOM(MBB, IP, Op0r, Op1r);
break;
@ -966,8 +996,6 @@ void ISel::visitSetCondInst(SetCondInst &I) {
if (canFoldSetCCIntoBranchOrSelect(&I))
return;
unsigned Op0Reg = getReg(I.getOperand(0));
unsigned Op1Reg = getReg(I.getOperand(1));
unsigned DestReg = getReg(I);
unsigned OpNum = I.getOpcode();
const Type *Ty = I.getOperand (0)->getType();
@ -977,6 +1005,9 @@ void ISel::visitSetCondInst(SetCondInst &I) {
unsigned Opcode = getPPCOpcodeForSetCCNumber(OpNum);
MachineBasicBlock *thisMBB = BB;
const BasicBlock *LLVM_BB = BB->getBasicBlock();
ilist<MachineBasicBlock>::iterator It = BB;
++It;
// thisMBB:
// ...
// cmpTY cr0, r1, r2
@ -987,10 +1018,10 @@ void ISel::visitSetCondInst(SetCondInst &I) {
// if we could insert other, non-terminator instructions after the
// bCC. But MBB->getFirstTerminator() can't understand this.
MachineBasicBlock *copy1MBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(copy1MBB);
F->getBasicBlockList().insert(It, copy1MBB);
BuildMI(BB, Opcode, 2).addReg(PPC32::CR0).addMBB(copy1MBB);
MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(copy0MBB);
F->getBasicBlockList().insert(It, copy0MBB);
BuildMI(BB, PPC32::B, 1).addMBB(copy0MBB);
// Update machine-CFG edges
BB->addSuccessor(copy1MBB);
@ -1003,7 +1034,7 @@ void ISel::visitSetCondInst(SetCondInst &I) {
unsigned FalseValue = makeAnotherReg(I.getType());
BuildMI(BB, PPC32::LI, 1, FalseValue).addImm(0);
MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(sinkMBB);
F->getBasicBlockList().insert(It, sinkMBB);
BuildMI(BB, PPC32::B, 1).addMBB(sinkMBB);
// Update machine-CFG edges
BB->addSuccessor(sinkMBB);
@ -1047,29 +1078,10 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
Value *Cond, Value *TrueVal, Value *FalseVal,
unsigned DestReg) {
unsigned SelectClass = getClassB(TrueVal->getType());
unsigned Opcode;
/*
unsigned TrueReg = getReg(TrueVal, MBB, IP);
unsigned FalseReg = getReg(FalseVal, MBB, IP);
if (TrueReg == FalseReg) {
if (SelectClass == cFP) {
BuildMI(*MBB, IP, PPC32::FMR, 1, DestReg).addReg(TrueReg);
} else {
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(TrueReg).addReg(TrueReg);
}
if (SelectClass == cLong)
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(TrueReg+1)
.addReg(TrueReg+1);
return;
}
*/
// See if we can fold the setcc into the select instruction, or if we have
// to get the register of the Cond value
unsigned Opcode;
if (SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(Cond)) {
// We successfully folded the setcc into the select instruction.
@ -1092,15 +1104,17 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
MachineBasicBlock *thisMBB = BB;
const BasicBlock *LLVM_BB = BB->getBasicBlock();
ilist<MachineBasicBlock>::iterator It = BB;
++It;
// FIXME: we wouldn't need copy0MBB (we could fold it into thisMBB)
// if we could insert other, non-terminator instructions after the
// bCC. But MBB->getFirstTerminator() can't understand this.
MachineBasicBlock *copy1MBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(copy1MBB);
F->getBasicBlockList().insert(It, copy1MBB);
BuildMI(BB, Opcode, 2).addReg(PPC32::CR0).addMBB(copy1MBB);
MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(copy0MBB);
F->getBasicBlockList().insert(It, copy0MBB);
BuildMI(BB, PPC32::B, 1).addMBB(copy0MBB);
// Update machine-CFG edges
BB->addSuccessor(copy1MBB);
@ -1115,7 +1129,7 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
BB = copy0MBB;
unsigned FalseValue = getReg(FalseVal, BB, BB->begin());
MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
F->getBasicBlockList().push_back(sinkMBB);
F->getBasicBlockList().insert(It, sinkMBB);
BuildMI(BB, PPC32::B, 1).addMBB(sinkMBB);
// Update machine-CFG edges
BB->addSuccessor(sinkMBB);
@ -1211,7 +1225,8 @@ void ISel::visitReturnInst(ReturnInst &I) {
case cInt:
promote32(PPC32::R3, ValueRecord(RetVal));
break;
case cFP: { // Floats & Doubles: Return in f1
case cFP32:
case cFP64: { // Floats & Doubles: Return in f1
unsigned RetReg = getReg(RetVal);
BuildMI(BB, PPC32::FMR, 1, PPC32::F1).addReg(RetReg);
break;
@ -1329,8 +1344,10 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
NumBytes += 4; break;
case cLong:
NumBytes += 8; break;
case cFP:
NumBytes += Args[i].Ty == Type::FloatTy ? 4 : 8;
case cFP32:
NumBytes += 4; break;
case cFP64:
NumBytes += 8; break;
break;
default: assert(0 && "Unknown class!");
}
@ -1339,7 +1356,8 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
BuildMI(BB, PPC32::ADJCALLSTACKDOWN, 1).addImm(NumBytes);
// Arguments go on the stack in reverse order, as specified by the ABI.
unsigned ArgOffset = 0;
// Offset to the paramater area on the stack is 24.
unsigned ArgOffset = 24;
int GPR_remaining = 8, FPR_remaining = 13;
unsigned GPR_idx = 0, FPR_idx = 0;
static const unsigned GPR[] = {
@ -1365,6 +1383,7 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
if (GPR_remaining > 0) {
BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx]).addReg(ArgReg)
.addReg(ArgReg);
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
} else {
BuildMI(BB, PPC32::STW, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
@ -1377,6 +1396,7 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
if (GPR_remaining > 0) {
BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx]).addReg(ArgReg)
.addReg(ArgReg);
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
} else {
BuildMI(BB, PPC32::STW, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
@ -1389,8 +1409,10 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
if (GPR_remaining > 1) {
BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx]).addReg(ArgReg)
.addReg(ArgReg);
BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx + 1]).addReg(ArgReg+1)
BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx+1]).addReg(ArgReg+1)
.addReg(ArgReg+1);
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
CallMI->addRegOperand(GPR[GPR_idx+1], MachineOperand::Use);
} else {
BuildMI(BB, PPC32::STW, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
@ -1402,70 +1424,63 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
GPR_remaining -= 1; // uses up 2 GPRs
GPR_idx += 1;
break;
case cFP:
case cFP32:
ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
if (Args[i].Ty == Type::FloatTy) {
assert(!isVarArg && "Cannot pass floats to vararg functions!");
// Reg or stack?
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
FPR_remaining--;
FPR_idx++;
} else {
// Reg or stack?
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
CallMI->addRegOperand(FPR[FPR_idx], MachineOperand::Use);
FPR_remaining--;
FPR_idx++;
// If this is a vararg function, and there are GPRs left, also
// pass the float in an int. Otherwise, put it on the stack.
if (isVarArg) {
BuildMI(BB, PPC32::STFS, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
.addReg(PPC32::R1);
if (GPR_remaining > 0) {
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx])
.addImm(ArgOffset).addReg(ArgReg);
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
}
}
} else {
assert(Args[i].Ty == Type::DoubleTy && "Unknown FP type!");
// Reg or stack?
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
FPR_remaining--;
FPR_idx++;
// For vararg functions, must pass doubles via int regs as well
if (isVarArg) {
Value *Val = Args[i].Val;
if (ConstantFP *CFP = dyn_cast<ConstantFP>(Val)) {
union DU {
double FVal;
struct {
uint32_t hi32;
uint32_t lo32;
} UVal;
} U;
U.FVal = CFP->getValue();
if (GPR_remaining > 0) {
Constant *hi32 = minUConstantForValue(U.UVal.hi32);
copyConstantToRegister(BB, BB->end(), hi32, GPR[GPR_idx]);
}
if (GPR_remaining > 1) {
Constant *lo32 = minUConstantForValue(U.UVal.lo32);
copyConstantToRegister(BB, BB->end(), lo32, GPR[GPR_idx+1]);
}
} else {
// Since this is not a constant, we must load it into int regs
// via memory
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
if (GPR_remaining > 0)
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx]).addImm(ArgOffset)
.addReg(PPC32::R1);
if (GPR_remaining > 1)
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx+1])
.addImm(ArgOffset+4).addReg(PPC32::R1);
}
}
} else {
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
}
ArgOffset += 4; // 8 byte entry, not 4.
GPR_remaining--; // uses up 2 GPRs
GPR_idx++;
BuildMI(BB, PPC32::STFS, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
}
break;
case cFP64:
ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
// Reg or stack?
if (FPR_remaining > 0) {
BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
CallMI->addRegOperand(FPR[FPR_idx], MachineOperand::Use);
FPR_remaining--;
FPR_idx++;
// For vararg functions, must pass doubles via int regs as well
if (isVarArg) {
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
if (GPR_remaining > 1) {
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx]).addImm(ArgOffset)
.addReg(PPC32::R1);
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx+1])
.addImm(ArgOffset+4).addReg(PPC32::R1);
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
CallMI->addRegOperand(GPR[GPR_idx+1], MachineOperand::Use);
}
}
} else {
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addImm(ArgOffset)
.addReg(PPC32::R1);
}
// Doubles use 8 bytes, and 2 GPRs worth of param space
ArgOffset += 4;
GPR_remaining--;
GPR_idx++;
break;
default: assert(0 && "Unknown class!");
}
ArgOffset += 4;
@ -1491,7 +1506,8 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
// Integral results are in r3
BuildMI(BB, PPC32::OR, 2, Ret.Reg).addReg(PPC32::R3).addReg(PPC32::R3);
break;
case cFP: // Floating-point return values live in f1
case cFP32: // Floating-point return values live in f1
case cFP64:
BuildMI(BB, PPC32::FMR, 1, Ret.Reg).addReg(PPC32::F1);
break;
case cLong: // Long values are in r3:r4
@ -1519,8 +1535,8 @@ void ISel::visitCallInst(CallInst &CI) {
TheCall = BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(F, true);
} else { // Emit an indirect call through the CTR
unsigned Reg = getReg(CI.getCalledValue());
BuildMI(BB, PPC32::MTSPR, 2).addZImm(9).addReg(Reg);
TheCall = BuildMI(PPC32::CALLindirect, 1).addZImm(20).addZImm(0);
BuildMI(BB, PPC32::MTCTR, 1).addReg(Reg);
TheCall = BuildMI(PPC32::CALLindirect, 2).addZImm(20).addZImm(0);
}
std::vector<ValueRecord> Args;
@ -1766,7 +1782,7 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
PPC32::ADDE, PPC32::SUBFE, PPC32::AND, PPC32::OR, PPC32::XOR
};
if (Class == cFP) {
if (Class == cFP32 || Class == cFP64) {
assert(OperatorClass < 2 && "No logical ops for FP!");
emitBinaryFPOperation(MBB, IP, Op0, Op1, OperatorClass, DestReg);
return;
@ -1859,9 +1875,9 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
// with 0xFFFFFFFF00000000 -> noop, etc.
BuildMI(*MBB, IP, BottomTab[OperatorClass], 2, DestReg).addReg(Op0r)
.addImm(Op1r);
.addReg(Op1r);
BuildMI(*MBB, IP, TopTab[OperatorClass], 2, DestReg+1).addReg(Op0r+1)
.addImm(Op1r+1);
.addReg(Op1r+1);
return;
}
@ -1873,9 +1889,9 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(Op0r).addReg(Op1r);
} else {
BuildMI(*MBB, IP, BottomTab[OperatorClass], 2, DestReg).addReg(Op0r)
.addImm(Op1r);
.addReg(Op1r);
BuildMI(*MBB, IP, TopTab[OperatorClass], 2, DestReg+1).addReg(Op0r+1)
.addImm(Op1r+1);
.addReg(Op1r+1);
}
return;
}
@ -1950,18 +1966,11 @@ void ISel::doMultiplyConst(MachineBasicBlock *MBB,
}
// Most general case, emit a normal multiply...
unsigned TmpReg1 = makeAnotherReg(Type::IntTy);
unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
unsigned TmpReg3 = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC32::LIS, 1, TmpReg1).addImm(ConstRHS >> 16);
BuildMI(*MBB, IP, PPC32::RLWINM, 4, TmpReg2).addReg(TmpReg1)
.addImm(16).addImm(0).addImm(15);
BuildMI(*MBB, IP, PPC32::ORI, 2, TmpReg3).addReg(TmpReg2)
.addImm(ConstRHS & 0xFFFF);
// Emit a MUL to multiply the register holding the index by
// elementSize, putting the result in OffsetReg.
doMultiply(MBB, IP, DestReg, DestTy, op0Reg, TmpReg3);
unsigned TmpReg = makeAnotherReg(Type::IntTy);
Constant *C = ConstantUInt::get(Type::UIntTy, ConstRHS);
copyConstantToRegister(MBB, IP, C, TmpReg);
doMultiply(MBB, IP, DestReg, DestTy, op0Reg, TmpReg);
}
void ISel::visitMul(BinaryOperator &I) {
@ -1993,7 +2002,8 @@ void ISel::emitMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
doMultiply(&BB, IP, DestReg, Op1->getType(), Op0Reg, Op1Reg);
}
return;
case cFP:
case cFP32:
case cFP64:
emitBinaryFPOperation(MBB, IP, Op0, Op1, 2, DestReg);
return;
case cLong:
@ -2098,11 +2108,30 @@ void ISel::emitDivRemOperation(MachineBasicBlock *BB,
const Type *Ty = Op0->getType();
unsigned Class = getClass(Ty);
switch (Class) {
case cFP: // Floating point divide
case cFP32:
if (isDiv) {
// Floating point divide...
emitBinaryFPOperation(BB, IP, Op0, Op1, 3, ResultReg);
return;
} else { // Floating point remainder...
} else {
// Floating point remainder via fmodf(float x, float y);
unsigned Op0Reg = getReg(Op0, BB, IP);
unsigned Op1Reg = getReg(Op1, BB, IP);
MachineInstr *TheCall =
BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(fmodfFn, true);
std::vector<ValueRecord> Args;
Args.push_back(ValueRecord(Op0Reg, Type::FloatTy));
Args.push_back(ValueRecord(Op1Reg, Type::FloatTy));
doCall(ValueRecord(ResultReg, Type::FloatTy), TheCall, Args, false);
}
return;
case cFP64:
if (isDiv) {
// Floating point divide...
emitBinaryFPOperation(BB, IP, Op0, Op1, 3, ResultReg);
return;
} else {
// Floating point remainder via fmod(double x, double y);
unsigned Op0Reg = getReg(Op0, BB, IP);
unsigned Op1Reg = getReg(Op1, BB, IP);
MachineInstr *TheCall =
@ -2114,7 +2143,7 @@ void ISel::emitDivRemOperation(MachineBasicBlock *BB,
}
return;
case cLong: {
static Function* const Funcs[] =
static Function* const Funcs[] =
{ __moddi3Fn, __divdi3Fn, __umoddi3Fn, __udivdi3Fn };
unsigned Op0Reg = getReg(Op0, BB, IP);
unsigned Op1Reg = getReg(Op1, BB, IP);
@ -2453,14 +2482,14 @@ void ISel::visitCastInst(CastInst &CI) {
/// emitCastOperation - Common code shared between visitCastInst and constant
/// expression cast support.
///
void ISel::emitCastOperation(MachineBasicBlock *BB,
void ISel::emitCastOperation(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP,
Value *Src, const Type *DestTy,
unsigned DestReg) {
const Type *SrcTy = Src->getType();
unsigned SrcClass = getClassB(SrcTy);
unsigned DestClass = getClassB(DestTy);
unsigned SrcReg = getReg(Src, BB, IP);
unsigned SrcReg = getReg(Src, MBB, IP);
// Implement casts to bool by using compare on the operand followed by set if
// not zero on the result.
@ -2470,29 +2499,21 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
case cShort:
case cInt: {
unsigned TmpReg = makeAnotherReg(Type::IntTy);
BuildMI(*BB, IP, PPC32::ADDIC, 2, TmpReg).addReg(SrcReg).addImm(-1);
BuildMI(*BB, IP, PPC32::SUBFE, 2, DestReg).addReg(TmpReg).addReg(SrcReg);
BuildMI(*MBB, IP, PPC32::ADDIC, 2, TmpReg).addReg(SrcReg).addImm(-1);
BuildMI(*MBB, IP, PPC32::SUBFE, 2, DestReg).addReg(TmpReg).addReg(SrcReg);
break;
}
case cLong: {
unsigned TmpReg = makeAnotherReg(Type::IntTy);
unsigned SrcReg2 = makeAnotherReg(Type::IntTy);
BuildMI(*BB, IP, PPC32::OR, 2, SrcReg2).addReg(SrcReg).addReg(SrcReg+1);
BuildMI(*BB, IP, PPC32::ADDIC, 2, TmpReg).addReg(SrcReg2).addImm(-1);
BuildMI(*BB, IP, PPC32::SUBFE, 2, DestReg).addReg(TmpReg).addReg(SrcReg2);
BuildMI(*MBB, IP, PPC32::OR, 2, SrcReg2).addReg(SrcReg).addReg(SrcReg+1);
BuildMI(*MBB, IP, PPC32::ADDIC, 2, TmpReg).addReg(SrcReg2).addImm(-1);
BuildMI(*MBB, IP, PPC32::SUBFE, 2, DestReg).addReg(TmpReg).addReg(SrcReg2);
break;
}
case cFP:
// FIXME
// Load -0.0
// Compare
// move to CR1
// Negate -0.0
// Compare
// CROR
// MFCR
// Left-align
// SRA ?
case cFP32:
case cFP64:
// FSEL perhaps?
std::cerr << "Cast fp-to-bool not implemented!";
abort();
}
@ -2503,21 +2524,12 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
// getClass) by using a register-to-register move.
if (SrcClass == DestClass) {
if (SrcClass <= cInt) {
BuildMI(*BB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
} else if (SrcClass == cFP && SrcTy == DestTy) {
BuildMI(*BB, IP, PPC32::FMR, 1, DestReg).addReg(SrcReg);
} else if (SrcClass == cFP) {
if (SrcTy == Type::FloatTy) { // float -> double
assert(DestTy == Type::DoubleTy && "Unknown cFP member!");
BuildMI(*BB, IP, PPC32::FMR, 1, DestReg).addReg(SrcReg);
} else { // double -> float
assert(SrcTy == Type::DoubleTy && DestTy == Type::FloatTy &&
"Unknown cFP member!");
BuildMI(*BB, IP, PPC32::FRSP, 1, DestReg).addReg(SrcReg);
}
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
} else if (SrcClass == cFP32 || SrcClass == cFP64) {
BuildMI(*MBB, IP, PPC32::FMR, 1, DestReg).addReg(SrcReg);
} else if (SrcClass == cLong) {
BuildMI(*BB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
BuildMI(*BB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg+1)
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg+1)
.addReg(SrcReg+1);
} else {
assert(0 && "Cannot handle this type of cast instruction!");
@ -2525,7 +2537,19 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
}
return;
}
// Handle cast of Float -> Double
if (SrcClass == cFP32 && DestClass == cFP64) {
BuildMI(*MBB, IP, PPC32::FMR, 1, DestReg).addReg(SrcReg);
return;
}
// Handle cast of Double -> Float
if (SrcClass == cFP64 && DestClass == cFP32) {
BuildMI(*MBB, IP, PPC32::FRSP, 1, DestReg).addReg(SrcReg);
return;
}
// Handle cast of SMALLER int to LARGER int using a move with sign extension
// or zero extension, depending on whether the source type was signed.
if (SrcClass <= cInt && (DestClass <= cInt || DestClass == cLong) &&
@ -2578,46 +2602,23 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
}
// Handle casts from integer to floating point now...
if (DestClass == cFP) {
if (DestClass == cFP32 || DestClass == cFP64) {
// Emit a library call for long to float conversion
if (SrcClass == cLong) {
std::vector<ValueRecord> Args;
Args.push_back(ValueRecord(SrcReg, SrcTy));
Function *floatFn = (SrcTy==Type::FloatTy) ? __floatdisfFn : __floatdidfFn;
Function *floatFn = (DestClass == cFP32) ? __floatdisfFn : __floatdidfFn;
MachineInstr *TheCall =
BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(floatFn, true);
doCall(ValueRecord(DestReg, DestTy), TheCall, Args, false);
return;
}
unsigned TmpReg = makeAnotherReg(Type::IntTy);
switch (SrcTy->getTypeID()) {
case Type::BoolTyID:
case Type::SByteTyID:
BuildMI(*BB, IP, PPC32::EXTSB, 1, TmpReg).addReg(SrcReg);
break;
case Type::UByteTyID:
BuildMI(*BB, IP, PPC32::RLWINM, 4, TmpReg).addReg(SrcReg).addZImm(0)
.addImm(24).addImm(31);
break;
case Type::ShortTyID:
BuildMI(*BB, IP, PPC32::EXTSB, 1, TmpReg).addReg(SrcReg);
break;
case Type::UShortTyID:
BuildMI(*BB, IP, PPC32::RLWINM, 4, TmpReg).addReg(SrcReg).addZImm(0)
.addImm(16).addImm(31);
break;
case Type::IntTyID:
BuildMI(*BB, IP, PPC32::OR, 2, TmpReg).addReg(SrcReg).addReg(SrcReg);
break;
case Type::UIntTyID:
BuildMI(*BB, IP, PPC32::OR, 2, TmpReg).addReg(SrcReg).addReg(SrcReg);
break;
default: // No promotion needed...
break;
}
// Make sure we're dealing with a full 32 bits
unsigned TmpReg = makeAnotherReg(Type::IntTy);
promote32(TmpReg, ValueRecord(SrcReg, SrcTy));
SrcReg = TmpReg;
// Spill the integer to memory and reload it from there.
@ -2669,34 +2670,44 @@ void ISel::emitCastOperation(MachineBasicBlock *BB,
}
// Handle casts from floating point to integer now...
if (SrcClass == cFP) {
if (SrcClass == cFP32 || SrcClass == cFP64) {
// emit library call
if (DestClass == cLong) {
std::vector<ValueRecord> Args;
Args.push_back(ValueRecord(SrcReg, SrcTy));
Function *floatFn = (DestClass == cFP32) ? __fixsfdiFn : __fixdfdiFn;
MachineInstr *TheCall =
BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(__fixdfdiFn, true);
BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(floatFn, true);
doCall(ValueRecord(DestReg, DestTy), TheCall, Args, false);
return;
}
int ValueFrameIdx =
F->getFrameInfo()->CreateStackObject(Type::DoubleTy, TM.getTargetData());
F->getFrameInfo()->CreateStackObject(SrcTy, TM.getTargetData());
// load into 32 bit value, and then truncate as necessary
// FIXME: This is wrong for unsigned dest types
//if (DestTy->isSigned()) {
if (DestTy->isSigned()) {
unsigned LoadOp = (DestClass == cShort) ? PPC32::LHA : PPC32::LWZ;
unsigned TempReg = makeAnotherReg(Type::DoubleTy);
// Convert to integer in the FP reg and store it to a stack slot
BuildMI(*BB, IP, PPC32::FCTIWZ, 1, TempReg).addReg(SrcReg);
addFrameReference(BuildMI(*BB, IP, PPC32::STFD, 3)
.addReg(TempReg), ValueFrameIdx);
addFrameReference(BuildMI(*BB, IP, PPC32::LWZ, 2, DestReg),
ValueFrameIdx+4);
//} else {
//}
// FIXME: Truncate return value
// There is no load signed byte opcode, so we must emit a sign extend
if (DestClass == cByte) {
unsigned TempReg2 = makeAnotherReg(DestTy);
addFrameReference(BuildMI(*BB, IP, LoadOp, 2, TempReg2),
ValueFrameIdx+4);
BuildMI(*MBB, IP, PPC32::EXTSB, DestReg).addReg(TempReg2);
} else {
addFrameReference(BuildMI(*BB, IP, LoadOp, 2, DestReg),
ValueFrameIdx+4);
}
} else {
std::cerr << "Cast fp-to-unsigned not implemented!";
abort();
}
return;
}
@ -2851,8 +2862,8 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
// Emit an ADD to add OffsetReg to the basePtr.
unsigned Reg = makeAnotherReg(Type::UIntTy);
BuildMI(*MBB, IP, PPC32::ADD, 2, TargetReg).addReg(Reg).addReg(OffsetReg);
BuildMI(*MBB, IP, PPC32::ADD,2,TargetReg).addReg(Reg).addReg(OffsetReg);
// Step to the first instruction of the multiply.
if (BeforeIt == MBB->end())
IP = MBB->begin();