mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-19 02:25:01 +00:00
* Change bool from cInt to cByte (for now)
* Don't allow negative immediates to users of unsigned immediates * Fix long compares * Support <const int>, op as a potential immediate candidate * Fix sign extension of short and byte loads * Fix and improve integer casts * Fix passing of doubles as vararg functions Patch contributed by Nate Begeman. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15109 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -65,7 +65,7 @@ static inline TypeClass getClass(const Type *Ty) {
|
|||||||
|
|
||||||
// getClassB - Just like getClass, but treat boolean values as ints.
|
// getClassB - Just like getClass, but treat boolean values as ints.
|
||||||
static inline TypeClass getClassB(const Type *Ty) {
|
static inline TypeClass getClassB(const Type *Ty) {
|
||||||
if (Ty == Type::BoolTy) return cInt;
|
if (Ty == Type::BoolTy) return cByte;
|
||||||
return getClass(Ty);
|
return getClass(Ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,6 +445,7 @@ bool ISel::canUseAsImmediateForOpcode(ConstantInt *CI, unsigned Operator)
|
|||||||
// ANDIo, ORI, and XORI take unsigned values
|
// ANDIo, ORI, and XORI take unsigned values
|
||||||
bool cond3 = (Operator >= 2)
|
bool cond3 = (Operator >= 2)
|
||||||
&& (Op1Cs = dyn_cast<ConstantSInt>(CI))
|
&& (Op1Cs = dyn_cast<ConstantSInt>(CI))
|
||||||
|
&& (Op1Cs->getValue() >= 0)
|
||||||
&& (Op1Cs->getValue() <= 32767);
|
&& (Op1Cs->getValue() <= 32767);
|
||||||
|
|
||||||
// ADDI and SUBI take SIMMs, so we have to make sure the UInt would fit
|
// ADDI and SUBI take SIMMs, so we have to make sure the UInt would fit
|
||||||
@@ -905,16 +906,14 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
|
|||||||
unsigned CR1field = (OpNum == 2 || OpNum == 3) ? 4 : 5;
|
unsigned CR1field = (OpNum == 2 || OpNum == 3) ? 4 : 5;
|
||||||
// ? cr0[lt] : cr0[gt]
|
// ? cr0[lt] : cr0[gt]
|
||||||
unsigned CR0field = (OpNum == 2 || OpNum == 5) ? 0 : 1;
|
unsigned CR0field = (OpNum == 2 || OpNum == 5) ? 0 : 1;
|
||||||
|
|
||||||
// Special case handling of: cmp R, i
|
|
||||||
if (isa<ConstantPointerNull>(Op1)) {
|
|
||||||
BuildMI(*MBB, IP, PPC32::CMPI, 2, PPC32::CR0).addReg(Op0r).addSImm(0);
|
|
||||||
} else if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
|
|
||||||
if (Class == cByte || Class == cShort || Class == cInt) {
|
|
||||||
unsigned Op1v = CI->getRawValue() & 0xFFFF;
|
|
||||||
unsigned Opcode = CompTy->isSigned() ? PPC32::CMPW : PPC32::CMPLW;
|
unsigned Opcode = CompTy->isSigned() ? PPC32::CMPW : PPC32::CMPLW;
|
||||||
unsigned OpcodeImm = CompTy->isSigned() ? PPC32::CMPWI : PPC32::CMPLWI;
|
unsigned OpcodeImm = CompTy->isSigned() ? PPC32::CMPWI : PPC32::CMPLWI;
|
||||||
|
|
||||||
|
// Special case handling of: cmp R, i
|
||||||
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
|
||||||
|
if (Class == cByte || Class == cShort || Class == cInt) {
|
||||||
|
unsigned Op1v = CI->getRawValue() & 0xFFFF;
|
||||||
|
|
||||||
// Treat compare like ADDI for the purposes of immediate suitability
|
// Treat compare like ADDI for the purposes of immediate suitability
|
||||||
if (canUseAsImmediateForOpcode(CI, 0)) {
|
if (canUseAsImmediateForOpcode(CI, 0)) {
|
||||||
BuildMI(*MBB, IP, OpcodeImm, 2, PPC32::CR0).addReg(Op0r).addSImm(Op1v);
|
BuildMI(*MBB, IP, OpcodeImm, 2, PPC32::CR0).addReg(Op0r).addSImm(Op1v);
|
||||||
@@ -949,9 +948,9 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
|
|||||||
copyConstantToRegister(MBB, IP, CI, ConstReg);
|
copyConstantToRegister(MBB, IP, CI, ConstReg);
|
||||||
|
|
||||||
// cr0 = r3 ccOpcode r5 or (r3 == r5 AND r4 ccOpcode r6)
|
// cr0 = r3 ccOpcode r5 or (r3 == r5 AND r4 ccOpcode r6)
|
||||||
BuildMI(*MBB, IP, PPC32::CMPW, 2, PPC32::CR0).addReg(Op0r)
|
BuildMI(*MBB, IP, Opcode, 2, PPC32::CR0).addReg(Op0r)
|
||||||
.addReg(ConstReg);
|
.addReg(ConstReg);
|
||||||
BuildMI(*MBB, IP, PPC32::CMPW, 2, PPC32::CR1).addReg(Op0r+1)
|
BuildMI(*MBB, IP, Opcode, 2, PPC32::CR1).addReg(Op0r+1)
|
||||||
.addReg(ConstReg+1);
|
.addReg(ConstReg+1);
|
||||||
BuildMI(*MBB, IP, PPC32::CRAND, 3).addImm(2).addImm(2).addImm(CR1field);
|
BuildMI(*MBB, IP, PPC32::CRAND, 3).addImm(2).addImm(2).addImm(CR1field);
|
||||||
BuildMI(*MBB, IP, PPC32::CROR, 3).addImm(CR0field).addImm(CR0field)
|
BuildMI(*MBB, IP, PPC32::CROR, 3).addImm(CR0field).addImm(CR0field)
|
||||||
@@ -962,7 +961,6 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned Op1r = getReg(Op1, MBB, IP);
|
unsigned Op1r = getReg(Op1, MBB, IP);
|
||||||
unsigned Opcode = CompTy->isSigned() ? PPC32::CMPW : PPC32::CMPLW;
|
|
||||||
|
|
||||||
switch (Class) {
|
switch (Class) {
|
||||||
default: assert(0 && "Unknown type class!");
|
default: assert(0 && "Unknown type class!");
|
||||||
@@ -991,10 +989,8 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
|
|||||||
unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
|
unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
|
||||||
|
|
||||||
// cr0 = r3 ccOpcode r5 or (r3 == r5 AND r4 ccOpcode r6)
|
// cr0 = r3 ccOpcode r5 or (r3 == r5 AND r4 ccOpcode r6)
|
||||||
BuildMI(*MBB, IP, PPC32::CMPW, 2, PPC32::CR0).addReg(Op0r)
|
BuildMI(*MBB, IP, Opcode, 2, PPC32::CR0).addReg(Op0r).addReg(Op1r);
|
||||||
.addReg(Op1r);
|
BuildMI(*MBB, IP, Opcode, 2, PPC32::CR1).addReg(Op0r+1).addReg(Op1r+1);
|
||||||
BuildMI(*MBB, IP, PPC32::CMPW, 2, PPC32::CR1).addReg(Op1r)
|
|
||||||
.addReg(Op1r+1);
|
|
||||||
BuildMI(*MBB, IP, PPC32::CRAND, 3).addImm(2).addImm(2).addImm(CR1field);
|
BuildMI(*MBB, IP, PPC32::CRAND, 3).addImm(2).addImm(2).addImm(CR1field);
|
||||||
BuildMI(*MBB, IP, PPC32::CROR, 3).addImm(CR0field).addImm(CR0field)
|
BuildMI(*MBB, IP, PPC32::CROR, 3).addImm(CR0field).addImm(CR0field)
|
||||||
.addImm(2);
|
.addImm(2);
|
||||||
@@ -1457,12 +1453,15 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
|
|||||||
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addSImm(ArgOffset)
|
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addSImm(ArgOffset)
|
||||||
.addReg(PPC32::R1);
|
.addReg(PPC32::R1);
|
||||||
|
|
||||||
if (GPR_remaining > 1) {
|
// Doubles can be split across reg + stack for varargs
|
||||||
|
if (GPR_remaining > 0) {
|
||||||
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx]).addSImm(ArgOffset)
|
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx]).addSImm(ArgOffset)
|
||||||
.addReg(PPC32::R1);
|
.addReg(PPC32::R1);
|
||||||
|
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
|
||||||
|
}
|
||||||
|
if (GPR_remaining > 1) {
|
||||||
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx+1])
|
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx+1])
|
||||||
.addSImm(ArgOffset+4).addReg(PPC32::R1);
|
.addSImm(ArgOffset+4).addReg(PPC32::R1);
|
||||||
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
|
|
||||||
CallMI->addRegOperand(GPR[GPR_idx+1], MachineOperand::Use);
|
CallMI->addRegOperand(GPR[GPR_idx+1], MachineOperand::Use);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1779,6 +1778,9 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
|
|||||||
static const unsigned ImmOpcodeTab[] = {
|
static const unsigned ImmOpcodeTab[] = {
|
||||||
PPC32::ADDI, PPC32::SUBI, PPC32::ANDIo, PPC32::ORI, PPC32::XORI
|
PPC32::ADDI, PPC32::SUBI, PPC32::ANDIo, PPC32::ORI, PPC32::XORI
|
||||||
};
|
};
|
||||||
|
static const unsigned RImmOpcodeTab[] = {
|
||||||
|
PPC32::ADDI, PPC32::SUBFIC, PPC32::ANDIo, PPC32::ORI, PPC32::XORI
|
||||||
|
};
|
||||||
|
|
||||||
// Otherwise, code generate the full operation with a constant.
|
// Otherwise, code generate the full operation with a constant.
|
||||||
static const unsigned BottomTab[] = {
|
static const unsigned BottomTab[] = {
|
||||||
@@ -1810,19 +1812,37 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sub 0, X -> neg X
|
// Special case: op <const int>, Reg
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
|
||||||
if (OperatorClass == 1 && CI->isNullValue()) {
|
// sub 0, X -> subfic
|
||||||
|
if (OperatorClass == 1 && canUseAsImmediateForOpcode(CI, 0)) {
|
||||||
unsigned Op1r = getReg(Op1, MBB, IP);
|
unsigned Op1r = getReg(Op1, MBB, IP);
|
||||||
|
int imm = CI->getRawValue() & 0xFFFF;
|
||||||
|
|
||||||
if (Class == cLong) {
|
if (Class == cLong) {
|
||||||
BuildMI(*MBB, IP, PPC32::SUBFIC, 2, DestReg+1).addReg(Op1r+1).addSImm(0);
|
BuildMI(*MBB, IP, PPC32::SUBFIC, 2, DestReg+1).addReg(Op1r+1)
|
||||||
|
.addSImm(imm);
|
||||||
BuildMI(*MBB, IP, PPC32::SUBFZE, 1, DestReg).addReg(Op1r);
|
BuildMI(*MBB, IP, PPC32::SUBFZE, 1, DestReg).addReg(Op1r);
|
||||||
} else {
|
} else {
|
||||||
BuildMI(*MBB, IP, PPC32::NEG, 1, DestReg).addReg(Op1r);
|
BuildMI(*MBB, IP, PPC32::SUBFIC, 2, DestReg).addReg(Op1r).addSImm(imm);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If it is easy to do, swap the operands and emit an immediate op
|
||||||
|
if (Class != cLong && OperatorClass != 1 &&
|
||||||
|
canUseAsImmediateForOpcode(CI, OperatorClass)) {
|
||||||
|
unsigned Op1r = getReg(Op1, MBB, IP);
|
||||||
|
int imm = CI->getRawValue() & 0xFFFF;
|
||||||
|
|
||||||
|
if (OperatorClass < 2)
|
||||||
|
BuildMI(*MBB, IP, RImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op1r)
|
||||||
|
.addSImm(imm);
|
||||||
|
else
|
||||||
|
BuildMI(*MBB, IP, RImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op1r)
|
||||||
|
.addZImm(imm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case: op Reg, <const int>
|
// Special case: op Reg, <const int>
|
||||||
@@ -1838,16 +1858,15 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: We're not handling ANDI right now since it could trash the CR
|
|
||||||
if (Class != cLong) {
|
if (Class != cLong) {
|
||||||
if (canUseAsImmediateForOpcode(Op1C, OperatorClass)) {
|
if (canUseAsImmediateForOpcode(Op1C, OperatorClass)) {
|
||||||
int immediate = Op1C->getRawValue() & 0xFFFF;
|
int immediate = Op1C->getRawValue() & 0xFFFF;
|
||||||
|
|
||||||
if (OperatorClass < 2)
|
if (OperatorClass < 2)
|
||||||
BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op0r)
|
BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2,DestReg).addReg(Op0r)
|
||||||
.addSImm(immediate);
|
.addSImm(immediate);
|
||||||
else
|
else
|
||||||
BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op0r)
|
BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2,DestReg).addReg(Op0r)
|
||||||
.addZImm(immediate);
|
.addZImm(immediate);
|
||||||
} else {
|
} else {
|
||||||
unsigned Op1r = getReg(Op1, MBB, IP);
|
unsigned Op1r = getReg(Op1, MBB, IP);
|
||||||
@@ -1866,6 +1885,8 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We couldn't generate an immediate variant of the op, load both halves into
|
||||||
|
// registers and emit the appropriate opcode.
|
||||||
unsigned Op0r = getReg(Op0, MBB, IP);
|
unsigned Op0r = getReg(Op0, MBB, IP);
|
||||||
unsigned Op1r = getReg(Op1, MBB, IP);
|
unsigned Op1r = getReg(Op1, MBB, IP);
|
||||||
|
|
||||||
@@ -1981,8 +2002,7 @@ void ISel::doMultiplyConst(MachineBasicBlock *MBB,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If 32 bits or less and immediate is in right range, emit mul by immediate
|
// If 32 bits or less and immediate is in right range, emit mul by immediate
|
||||||
if (Class == cByte || Class == cShort || Class == cInt)
|
if (Class == cByte || Class == cShort || Class == cInt) {
|
||||||
{
|
|
||||||
if (canUseAsImmediateForOpcode(CI, 0)) {
|
if (canUseAsImmediateForOpcode(CI, 0)) {
|
||||||
unsigned Op0r = getReg(Op0, MBB, IP);
|
unsigned Op0r = getReg(Op0, MBB, IP);
|
||||||
unsigned imm = CI->getRawValue() & 0xFFFF;
|
unsigned imm = CI->getRawValue() & 0xFFFF;
|
||||||
@@ -2237,11 +2257,13 @@ void ISel::emitShiftOperation(MachineBasicBlock *MBB,
|
|||||||
.addSImm(32);
|
.addSImm(32);
|
||||||
BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg2).addReg(SrcReg)
|
BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg2).addReg(SrcReg)
|
||||||
.addReg(ShiftAmountReg);
|
.addReg(ShiftAmountReg);
|
||||||
BuildMI(*MBB, IP, PPC32::SRW, 2, TmpReg3).addReg(SrcReg+1).addReg(TmpReg1);
|
BuildMI(*MBB, IP, PPC32::SRW, 2, TmpReg3).addReg(SrcReg+1)
|
||||||
BuildMI(*MBB, IP, PPC32::OR, 2, TmpReg4).addReg(TmpReg2).addReg(TmpReg3);
|
.addReg(TmpReg1);
|
||||||
|
BuildMI(*MBB, IP, PPC32::OR, 2,TmpReg4).addReg(TmpReg2).addReg(TmpReg3);
|
||||||
BuildMI(*MBB, IP, PPC32::ADDI, 2, TmpReg5).addReg(ShiftAmountReg)
|
BuildMI(*MBB, IP, PPC32::ADDI, 2, TmpReg5).addReg(ShiftAmountReg)
|
||||||
.addSImm(-32);
|
.addSImm(-32);
|
||||||
BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg6).addReg(SrcReg+1).addReg(TmpReg5);
|
BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg6).addReg(SrcReg+1)
|
||||||
|
.addReg(TmpReg5);
|
||||||
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(TmpReg4)
|
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(TmpReg4)
|
||||||
.addReg(TmpReg6);
|
.addReg(TmpReg6);
|
||||||
BuildMI(*MBB, IP, PPC32::SLW, 2, DestReg+1).addReg(SrcReg+1)
|
BuildMI(*MBB, IP, PPC32::SLW, 2, DestReg+1).addReg(SrcReg+1)
|
||||||
@@ -2311,10 +2333,11 @@ void ISel::visitLoadInst(LoadInst &I) {
|
|||||||
static const unsigned Opcodes[] = {
|
static const unsigned Opcodes[] = {
|
||||||
PPC32::LBZ, PPC32::LHZ, PPC32::LWZ, PPC32::LFS
|
PPC32::LBZ, PPC32::LHZ, PPC32::LWZ, PPC32::LFS
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned Class = getClassB(I.getType());
|
unsigned Class = getClassB(I.getType());
|
||||||
unsigned Opcode = Opcodes[Class];
|
unsigned Opcode = Opcodes[Class];
|
||||||
if (I.getType() == Type::DoubleTy) Opcode = PPC32::LFD;
|
if (I.getType() == Type::DoubleTy) Opcode = PPC32::LFD;
|
||||||
|
if (Class == cShort && I.getType()->isSigned()) Opcode = PPC32::LHA;
|
||||||
unsigned DestReg = getReg(I);
|
unsigned DestReg = getReg(I);
|
||||||
|
|
||||||
if (AllocaInst *AI = dyn_castFixedAlloca(I.getOperand(0))) {
|
if (AllocaInst *AI = dyn_castFixedAlloca(I.getOperand(0))) {
|
||||||
@@ -2322,6 +2345,10 @@ void ISel::visitLoadInst(LoadInst &I) {
|
|||||||
if (Class == cLong) {
|
if (Class == cLong) {
|
||||||
addFrameReference(BuildMI(BB, PPC32::LWZ, 2, DestReg), FI);
|
addFrameReference(BuildMI(BB, PPC32::LWZ, 2, DestReg), FI);
|
||||||
addFrameReference(BuildMI(BB, PPC32::LWZ, 2, DestReg+1), FI, 4);
|
addFrameReference(BuildMI(BB, PPC32::LWZ, 2, DestReg+1), FI, 4);
|
||||||
|
} else if (Class == cByte && I.getType()->isSigned()) {
|
||||||
|
unsigned TmpReg = makeAnotherReg(I.getType());
|
||||||
|
addFrameReference(BuildMI(BB, Opcode, 2, TmpReg), FI);
|
||||||
|
BuildMI(BB, PPC32::EXTSB, 1, DestReg).addReg(TmpReg);
|
||||||
} else {
|
} else {
|
||||||
addFrameReference(BuildMI(BB, Opcode, 2, DestReg), FI);
|
addFrameReference(BuildMI(BB, Opcode, 2, DestReg), FI);
|
||||||
}
|
}
|
||||||
@@ -2331,6 +2358,10 @@ void ISel::visitLoadInst(LoadInst &I) {
|
|||||||
if (Class == cLong) {
|
if (Class == cLong) {
|
||||||
BuildMI(BB, PPC32::LWZ, 2, DestReg).addSImm(0).addReg(SrcAddrReg);
|
BuildMI(BB, PPC32::LWZ, 2, DestReg).addSImm(0).addReg(SrcAddrReg);
|
||||||
BuildMI(BB, PPC32::LWZ, 2, DestReg+1).addSImm(4).addReg(SrcAddrReg);
|
BuildMI(BB, PPC32::LWZ, 2, DestReg+1).addSImm(4).addReg(SrcAddrReg);
|
||||||
|
} else if (Class == cByte && I.getType()->isSigned()) {
|
||||||
|
unsigned TmpReg = makeAnotherReg(I.getType());
|
||||||
|
BuildMI(BB, Opcode, 2, TmpReg).addSImm(0).addReg(SrcAddrReg);
|
||||||
|
BuildMI(BB, PPC32::EXTSB, 1, DestReg).addReg(TmpReg);
|
||||||
} else {
|
} else {
|
||||||
BuildMI(BB, Opcode, 2, DestReg).addSImm(0).addReg(SrcAddrReg);
|
BuildMI(BB, Opcode, 2, DestReg).addSImm(0).addReg(SrcAddrReg);
|
||||||
}
|
}
|
||||||
@@ -2430,7 +2461,7 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
|
|||||||
case cFP32:
|
case cFP32:
|
||||||
case cFP64:
|
case cFP64:
|
||||||
// FSEL perhaps?
|
// FSEL perhaps?
|
||||||
std::cerr << "Cast fp-to-bool not implemented!";
|
std::cerr << "ERROR: Cast fp-to-bool not implemented!\n";
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -2476,26 +2507,15 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
|
|||||||
++DestReg;
|
++DestReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isUnsigned = SrcTy->isUnsigned() || SrcTy == Type::BoolTy;
|
bool isUnsigned = DestTy->isUnsigned() || DestTy == Type::BoolTy;
|
||||||
if (SrcClass < cInt) {
|
|
||||||
if (isUnsigned) {
|
|
||||||
unsigned shift = (SrcClass == cByte) ? 24 : 16;
|
|
||||||
BuildMI(*BB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg).addZImm(0)
|
|
||||||
.addImm(shift).addImm(31);
|
|
||||||
} else {
|
|
||||||
BuildMI(*BB, IP, (SrcClass == cByte) ? PPC32::EXTSB : PPC32::EXTSH,
|
|
||||||
1, DestReg).addReg(SrcReg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
BuildMI(*BB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
|
BuildMI(*BB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
|
||||||
}
|
|
||||||
|
|
||||||
if (isLong) { // Handle upper 32 bits as appropriate...
|
if (isLong) { // Handle upper 32 bits as appropriate...
|
||||||
--DestReg;
|
--DestReg;
|
||||||
if (isUnsigned) // Zero out top bits...
|
if (isUnsigned) // Zero out top bits...
|
||||||
BuildMI(*BB, IP, PPC32::LI, 1, DestReg).addSImm(0);
|
BuildMI(*BB, IP, PPC32::LI, 1, DestReg).addSImm(0);
|
||||||
else // Sign extend bottom half...
|
else // Sign extend bottom half...
|
||||||
BuildMI(*BB, IP, PPC32::SRAWI, 2, DestReg).addReg(DestReg).addImm(31);
|
BuildMI(*BB, IP, PPC32::SRAWI, 2, DestReg).addReg(SrcReg).addImm(31);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2509,7 +2529,7 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
|
|||||||
// Handle cast of LARGER int to SMALLER int with a clear or sign extend
|
// Handle cast of LARGER int to SMALLER int with a clear or sign extend
|
||||||
if ((SrcClass <= cInt || SrcClass == cLong) && DestClass <= cInt
|
if ((SrcClass <= cInt || SrcClass == cLong) && DestClass <= cInt
|
||||||
&& SrcClass > DestClass) {
|
&& SrcClass > DestClass) {
|
||||||
bool isUnsigned = SrcTy->isUnsigned() || SrcTy == Type::BoolTy;
|
bool isUnsigned = DestTy->isUnsigned() || DestTy == Type::BoolTy;
|
||||||
unsigned source = (SrcClass == cLong) ? SrcReg+1 : SrcReg;
|
unsigned source = (SrcClass == cLong) ? SrcReg+1 : SrcReg;
|
||||||
|
|
||||||
if (isUnsigned) {
|
if (isUnsigned) {
|
||||||
@@ -2627,7 +2647,7 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
|
|||||||
ValueFrameIdx, 4);
|
ValueFrameIdx, 4);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Cast fp-to-unsigned not implemented!";
|
std::cerr << "ERROR: Cast fp-to-unsigned not implemented!\n";
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -2706,33 +2726,37 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
|
|||||||
MachineBasicBlock::iterator IP,
|
MachineBasicBlock::iterator IP,
|
||||||
Value *Src, User::op_iterator IdxBegin,
|
Value *Src, User::op_iterator IdxBegin,
|
||||||
User::op_iterator IdxEnd, unsigned TargetReg) {
|
User::op_iterator IdxEnd, unsigned TargetReg) {
|
||||||
const TargetData &TD = TM.getTargetData ();
|
const TargetData &TD = TM.getTargetData();
|
||||||
const Type *Ty = Src->getType ();
|
const Type *Ty = Src->getType();
|
||||||
unsigned basePtrReg = getReg (Src, MBB, IP);
|
unsigned basePtrReg = getReg(Src, MBB, IP);
|
||||||
|
|
||||||
// GEPs have zero or more indices; we must perform a struct access
|
// GEPs have zero or more indices; we must perform a struct access
|
||||||
// or array access for each one.
|
// or array access for each one.
|
||||||
for (GetElementPtrInst::op_iterator oi = IdxBegin, oe = IdxEnd; oi != oe;
|
for (GetElementPtrInst::op_iterator oi = IdxBegin, oe = IdxEnd; oi != oe;
|
||||||
++oi) {
|
++oi) {
|
||||||
Value *idx = *oi;
|
Value *idx = *oi;
|
||||||
unsigned nextBasePtrReg = makeAnotherReg (Type::UIntTy);
|
unsigned nextBasePtrReg = makeAnotherReg(Type::UIntTy);
|
||||||
if (const StructType *StTy = dyn_cast<StructType> (Ty)) {
|
if (const StructType *StTy = dyn_cast<StructType>(Ty)) {
|
||||||
// It's a struct access. idx is the index into the structure,
|
// It's a struct access. idx is the index into the structure,
|
||||||
// which names the field. Use the TargetData structure to
|
// which names the field. Use the TargetData structure to
|
||||||
// pick out what the layout of the structure is in memory.
|
// pick out what the layout of the structure is in memory.
|
||||||
// Use the (constant) structure index's value to find the
|
// Use the (constant) structure index's value to find the
|
||||||
// right byte offset from the StructLayout class's list of
|
// right byte offset from the StructLayout class's list of
|
||||||
// structure member offsets.
|
// structure member offsets.
|
||||||
unsigned fieldIndex = cast<ConstantUInt> (idx)->getValue ();
|
unsigned fieldIndex = cast<ConstantUInt>(idx)->getValue();
|
||||||
unsigned memberOffset =
|
unsigned memberOffset =
|
||||||
TD.getStructLayout (StTy)->MemberOffsets[fieldIndex];
|
TD.getStructLayout(StTy)->MemberOffsets[fieldIndex];
|
||||||
|
|
||||||
|
if (0 == memberOffset) { // No-op
|
||||||
|
nextBasePtrReg = basePtrReg;
|
||||||
|
} else {
|
||||||
// Emit an ADDI to add memberOffset to the basePtr.
|
// Emit an ADDI to add memberOffset to the basePtr.
|
||||||
BuildMI (*MBB, IP, PPC32::ADDI, 2, nextBasePtrReg).addReg(basePtrReg)
|
BuildMI (*MBB, IP, PPC32::ADDI, 2, nextBasePtrReg).addReg(basePtrReg)
|
||||||
.addSImm(memberOffset);
|
.addSImm(memberOffset);
|
||||||
// The next type is the member of the structure selected by the
|
}
|
||||||
// index.
|
// The next type is the member of the structure selected by the index.
|
||||||
Ty = StTy->getElementType (fieldIndex);
|
Ty = StTy->getElementType(fieldIndex);
|
||||||
} else if (const SequentialType *SqTy = dyn_cast<SequentialType> (Ty)) {
|
} else if (const SequentialType *SqTy = dyn_cast<SequentialType>(Ty)) {
|
||||||
// Many GEP instructions use a [cast (int/uint) to LongTy] as their
|
// Many GEP instructions use a [cast (int/uint) to LongTy] as their
|
||||||
// operand. Handle this case directly now...
|
// operand. Handle this case directly now...
|
||||||
if (CastInst *CI = dyn_cast<CastInst>(idx))
|
if (CastInst *CI = dyn_cast<CastInst>(idx))
|
||||||
@@ -2741,10 +2765,9 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
|
|||||||
idx = CI->getOperand(0);
|
idx = CI->getOperand(0);
|
||||||
|
|
||||||
Ty = SqTy->getElementType();
|
Ty = SqTy->getElementType();
|
||||||
unsigned elementSize = TD.getTypeSize (Ty);
|
unsigned elementSize = TD.getTypeSize(Ty);
|
||||||
|
|
||||||
if (idx == Constant::getNullValue(idx->getType())) {
|
if (idx == Constant::getNullValue(idx->getType())) { // No-op
|
||||||
// GEP with idx 0 is a no-op
|
|
||||||
nextBasePtrReg = basePtrReg;
|
nextBasePtrReg = basePtrReg;
|
||||||
} else if (elementSize == 1) {
|
} else if (elementSize == 1) {
|
||||||
// If the element size is 1, we don't have to multiply, just add
|
// If the element size is 1, we don't have to multiply, just add
|
||||||
@@ -2754,8 +2777,8 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
|
|||||||
} else {
|
} else {
|
||||||
// It's an array or pointer access: [ArraySize x ElementType].
|
// It's an array or pointer access: [ArraySize x ElementType].
|
||||||
// We want to add basePtrReg to (idxReg * sizeof ElementType). First, we
|
// We want to add basePtrReg to (idxReg * sizeof ElementType). First, we
|
||||||
// must find the size of the pointed-to type (Not coincidentally, the next
|
// must find the size of the pointed-to type (Not coincidentally, the
|
||||||
// type is the type of the elements in the array).
|
// next type is the type of the elements in the array).
|
||||||
unsigned OffsetReg = makeAnotherReg(idx->getType());
|
unsigned OffsetReg = makeAnotherReg(idx->getType());
|
||||||
ConstantUInt *CUI = ConstantUInt::get(Type::UIntTy, elementSize);
|
ConstantUInt *CUI = ConstantUInt::get(Type::UIntTy, elementSize);
|
||||||
doMultiplyConst(MBB, IP, OffsetReg, idx, CUI);
|
doMultiplyConst(MBB, IP, OffsetReg, idx, CUI);
|
||||||
@@ -2773,7 +2796,7 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
|
|||||||
// After we have processed all the indices, the result is left in
|
// After we have processed all the indices, the result is left in
|
||||||
// basePtrReg. Move it to the register where we were expected to
|
// basePtrReg. Move it to the register where we were expected to
|
||||||
// put the answer.
|
// put the answer.
|
||||||
BuildMI (BB, PPC32::OR, 2, TargetReg).addReg(basePtrReg).addReg(basePtrReg);
|
BuildMI(BB, PPC32::OR, 2, TargetReg).addReg(basePtrReg).addReg(basePtrReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// visitAllocaInst - If this is a fixed size alloca, allocate space from the
|
/// visitAllocaInst - If this is a fixed size alloca, allocate space from the
|
||||||
|
@@ -65,7 +65,7 @@ static inline TypeClass getClass(const Type *Ty) {
|
|||||||
|
|
||||||
// getClassB - Just like getClass, but treat boolean values as ints.
|
// getClassB - Just like getClass, but treat boolean values as ints.
|
||||||
static inline TypeClass getClassB(const Type *Ty) {
|
static inline TypeClass getClassB(const Type *Ty) {
|
||||||
if (Ty == Type::BoolTy) return cInt;
|
if (Ty == Type::BoolTy) return cByte;
|
||||||
return getClass(Ty);
|
return getClass(Ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,6 +445,7 @@ bool ISel::canUseAsImmediateForOpcode(ConstantInt *CI, unsigned Operator)
|
|||||||
// ANDIo, ORI, and XORI take unsigned values
|
// ANDIo, ORI, and XORI take unsigned values
|
||||||
bool cond3 = (Operator >= 2)
|
bool cond3 = (Operator >= 2)
|
||||||
&& (Op1Cs = dyn_cast<ConstantSInt>(CI))
|
&& (Op1Cs = dyn_cast<ConstantSInt>(CI))
|
||||||
|
&& (Op1Cs->getValue() >= 0)
|
||||||
&& (Op1Cs->getValue() <= 32767);
|
&& (Op1Cs->getValue() <= 32767);
|
||||||
|
|
||||||
// ADDI and SUBI take SIMMs, so we have to make sure the UInt would fit
|
// ADDI and SUBI take SIMMs, so we have to make sure the UInt would fit
|
||||||
@@ -905,16 +906,14 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
|
|||||||
unsigned CR1field = (OpNum == 2 || OpNum == 3) ? 4 : 5;
|
unsigned CR1field = (OpNum == 2 || OpNum == 3) ? 4 : 5;
|
||||||
// ? cr0[lt] : cr0[gt]
|
// ? cr0[lt] : cr0[gt]
|
||||||
unsigned CR0field = (OpNum == 2 || OpNum == 5) ? 0 : 1;
|
unsigned CR0field = (OpNum == 2 || OpNum == 5) ? 0 : 1;
|
||||||
|
|
||||||
// Special case handling of: cmp R, i
|
|
||||||
if (isa<ConstantPointerNull>(Op1)) {
|
|
||||||
BuildMI(*MBB, IP, PPC32::CMPI, 2, PPC32::CR0).addReg(Op0r).addSImm(0);
|
|
||||||
} else if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
|
|
||||||
if (Class == cByte || Class == cShort || Class == cInt) {
|
|
||||||
unsigned Op1v = CI->getRawValue() & 0xFFFF;
|
|
||||||
unsigned Opcode = CompTy->isSigned() ? PPC32::CMPW : PPC32::CMPLW;
|
unsigned Opcode = CompTy->isSigned() ? PPC32::CMPW : PPC32::CMPLW;
|
||||||
unsigned OpcodeImm = CompTy->isSigned() ? PPC32::CMPWI : PPC32::CMPLWI;
|
unsigned OpcodeImm = CompTy->isSigned() ? PPC32::CMPWI : PPC32::CMPLWI;
|
||||||
|
|
||||||
|
// Special case handling of: cmp R, i
|
||||||
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
|
||||||
|
if (Class == cByte || Class == cShort || Class == cInt) {
|
||||||
|
unsigned Op1v = CI->getRawValue() & 0xFFFF;
|
||||||
|
|
||||||
// Treat compare like ADDI for the purposes of immediate suitability
|
// Treat compare like ADDI for the purposes of immediate suitability
|
||||||
if (canUseAsImmediateForOpcode(CI, 0)) {
|
if (canUseAsImmediateForOpcode(CI, 0)) {
|
||||||
BuildMI(*MBB, IP, OpcodeImm, 2, PPC32::CR0).addReg(Op0r).addSImm(Op1v);
|
BuildMI(*MBB, IP, OpcodeImm, 2, PPC32::CR0).addReg(Op0r).addSImm(Op1v);
|
||||||
@@ -949,9 +948,9 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
|
|||||||
copyConstantToRegister(MBB, IP, CI, ConstReg);
|
copyConstantToRegister(MBB, IP, CI, ConstReg);
|
||||||
|
|
||||||
// cr0 = r3 ccOpcode r5 or (r3 == r5 AND r4 ccOpcode r6)
|
// cr0 = r3 ccOpcode r5 or (r3 == r5 AND r4 ccOpcode r6)
|
||||||
BuildMI(*MBB, IP, PPC32::CMPW, 2, PPC32::CR0).addReg(Op0r)
|
BuildMI(*MBB, IP, Opcode, 2, PPC32::CR0).addReg(Op0r)
|
||||||
.addReg(ConstReg);
|
.addReg(ConstReg);
|
||||||
BuildMI(*MBB, IP, PPC32::CMPW, 2, PPC32::CR1).addReg(Op0r+1)
|
BuildMI(*MBB, IP, Opcode, 2, PPC32::CR1).addReg(Op0r+1)
|
||||||
.addReg(ConstReg+1);
|
.addReg(ConstReg+1);
|
||||||
BuildMI(*MBB, IP, PPC32::CRAND, 3).addImm(2).addImm(2).addImm(CR1field);
|
BuildMI(*MBB, IP, PPC32::CRAND, 3).addImm(2).addImm(2).addImm(CR1field);
|
||||||
BuildMI(*MBB, IP, PPC32::CROR, 3).addImm(CR0field).addImm(CR0field)
|
BuildMI(*MBB, IP, PPC32::CROR, 3).addImm(CR0field).addImm(CR0field)
|
||||||
@@ -962,7 +961,6 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned Op1r = getReg(Op1, MBB, IP);
|
unsigned Op1r = getReg(Op1, MBB, IP);
|
||||||
unsigned Opcode = CompTy->isSigned() ? PPC32::CMPW : PPC32::CMPLW;
|
|
||||||
|
|
||||||
switch (Class) {
|
switch (Class) {
|
||||||
default: assert(0 && "Unknown type class!");
|
default: assert(0 && "Unknown type class!");
|
||||||
@@ -991,10 +989,8 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
|
|||||||
unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
|
unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
|
||||||
|
|
||||||
// cr0 = r3 ccOpcode r5 or (r3 == r5 AND r4 ccOpcode r6)
|
// cr0 = r3 ccOpcode r5 or (r3 == r5 AND r4 ccOpcode r6)
|
||||||
BuildMI(*MBB, IP, PPC32::CMPW, 2, PPC32::CR0).addReg(Op0r)
|
BuildMI(*MBB, IP, Opcode, 2, PPC32::CR0).addReg(Op0r).addReg(Op1r);
|
||||||
.addReg(Op1r);
|
BuildMI(*MBB, IP, Opcode, 2, PPC32::CR1).addReg(Op0r+1).addReg(Op1r+1);
|
||||||
BuildMI(*MBB, IP, PPC32::CMPW, 2, PPC32::CR1).addReg(Op1r)
|
|
||||||
.addReg(Op1r+1);
|
|
||||||
BuildMI(*MBB, IP, PPC32::CRAND, 3).addImm(2).addImm(2).addImm(CR1field);
|
BuildMI(*MBB, IP, PPC32::CRAND, 3).addImm(2).addImm(2).addImm(CR1field);
|
||||||
BuildMI(*MBB, IP, PPC32::CROR, 3).addImm(CR0field).addImm(CR0field)
|
BuildMI(*MBB, IP, PPC32::CROR, 3).addImm(CR0field).addImm(CR0field)
|
||||||
.addImm(2);
|
.addImm(2);
|
||||||
@@ -1457,12 +1453,15 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
|
|||||||
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addSImm(ArgOffset)
|
BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addSImm(ArgOffset)
|
||||||
.addReg(PPC32::R1);
|
.addReg(PPC32::R1);
|
||||||
|
|
||||||
if (GPR_remaining > 1) {
|
// Doubles can be split across reg + stack for varargs
|
||||||
|
if (GPR_remaining > 0) {
|
||||||
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx]).addSImm(ArgOffset)
|
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx]).addSImm(ArgOffset)
|
||||||
.addReg(PPC32::R1);
|
.addReg(PPC32::R1);
|
||||||
|
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
|
||||||
|
}
|
||||||
|
if (GPR_remaining > 1) {
|
||||||
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx+1])
|
BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx+1])
|
||||||
.addSImm(ArgOffset+4).addReg(PPC32::R1);
|
.addSImm(ArgOffset+4).addReg(PPC32::R1);
|
||||||
CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
|
|
||||||
CallMI->addRegOperand(GPR[GPR_idx+1], MachineOperand::Use);
|
CallMI->addRegOperand(GPR[GPR_idx+1], MachineOperand::Use);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1779,6 +1778,9 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
|
|||||||
static const unsigned ImmOpcodeTab[] = {
|
static const unsigned ImmOpcodeTab[] = {
|
||||||
PPC32::ADDI, PPC32::SUBI, PPC32::ANDIo, PPC32::ORI, PPC32::XORI
|
PPC32::ADDI, PPC32::SUBI, PPC32::ANDIo, PPC32::ORI, PPC32::XORI
|
||||||
};
|
};
|
||||||
|
static const unsigned RImmOpcodeTab[] = {
|
||||||
|
PPC32::ADDI, PPC32::SUBFIC, PPC32::ANDIo, PPC32::ORI, PPC32::XORI
|
||||||
|
};
|
||||||
|
|
||||||
// Otherwise, code generate the full operation with a constant.
|
// Otherwise, code generate the full operation with a constant.
|
||||||
static const unsigned BottomTab[] = {
|
static const unsigned BottomTab[] = {
|
||||||
@@ -1810,19 +1812,37 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sub 0, X -> neg X
|
// Special case: op <const int>, Reg
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
|
||||||
if (OperatorClass == 1 && CI->isNullValue()) {
|
// sub 0, X -> subfic
|
||||||
|
if (OperatorClass == 1 && canUseAsImmediateForOpcode(CI, 0)) {
|
||||||
unsigned Op1r = getReg(Op1, MBB, IP);
|
unsigned Op1r = getReg(Op1, MBB, IP);
|
||||||
|
int imm = CI->getRawValue() & 0xFFFF;
|
||||||
|
|
||||||
if (Class == cLong) {
|
if (Class == cLong) {
|
||||||
BuildMI(*MBB, IP, PPC32::SUBFIC, 2, DestReg+1).addReg(Op1r+1).addSImm(0);
|
BuildMI(*MBB, IP, PPC32::SUBFIC, 2, DestReg+1).addReg(Op1r+1)
|
||||||
|
.addSImm(imm);
|
||||||
BuildMI(*MBB, IP, PPC32::SUBFZE, 1, DestReg).addReg(Op1r);
|
BuildMI(*MBB, IP, PPC32::SUBFZE, 1, DestReg).addReg(Op1r);
|
||||||
} else {
|
} else {
|
||||||
BuildMI(*MBB, IP, PPC32::NEG, 1, DestReg).addReg(Op1r);
|
BuildMI(*MBB, IP, PPC32::SUBFIC, 2, DestReg).addReg(Op1r).addSImm(imm);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If it is easy to do, swap the operands and emit an immediate op
|
||||||
|
if (Class != cLong && OperatorClass != 1 &&
|
||||||
|
canUseAsImmediateForOpcode(CI, OperatorClass)) {
|
||||||
|
unsigned Op1r = getReg(Op1, MBB, IP);
|
||||||
|
int imm = CI->getRawValue() & 0xFFFF;
|
||||||
|
|
||||||
|
if (OperatorClass < 2)
|
||||||
|
BuildMI(*MBB, IP, RImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op1r)
|
||||||
|
.addSImm(imm);
|
||||||
|
else
|
||||||
|
BuildMI(*MBB, IP, RImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op1r)
|
||||||
|
.addZImm(imm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case: op Reg, <const int>
|
// Special case: op Reg, <const int>
|
||||||
@@ -1838,16 +1858,15 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: We're not handling ANDI right now since it could trash the CR
|
|
||||||
if (Class != cLong) {
|
if (Class != cLong) {
|
||||||
if (canUseAsImmediateForOpcode(Op1C, OperatorClass)) {
|
if (canUseAsImmediateForOpcode(Op1C, OperatorClass)) {
|
||||||
int immediate = Op1C->getRawValue() & 0xFFFF;
|
int immediate = Op1C->getRawValue() & 0xFFFF;
|
||||||
|
|
||||||
if (OperatorClass < 2)
|
if (OperatorClass < 2)
|
||||||
BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op0r)
|
BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2,DestReg).addReg(Op0r)
|
||||||
.addSImm(immediate);
|
.addSImm(immediate);
|
||||||
else
|
else
|
||||||
BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op0r)
|
BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2,DestReg).addReg(Op0r)
|
||||||
.addZImm(immediate);
|
.addZImm(immediate);
|
||||||
} else {
|
} else {
|
||||||
unsigned Op1r = getReg(Op1, MBB, IP);
|
unsigned Op1r = getReg(Op1, MBB, IP);
|
||||||
@@ -1866,6 +1885,8 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We couldn't generate an immediate variant of the op, load both halves into
|
||||||
|
// registers and emit the appropriate opcode.
|
||||||
unsigned Op0r = getReg(Op0, MBB, IP);
|
unsigned Op0r = getReg(Op0, MBB, IP);
|
||||||
unsigned Op1r = getReg(Op1, MBB, IP);
|
unsigned Op1r = getReg(Op1, MBB, IP);
|
||||||
|
|
||||||
@@ -1981,8 +2002,7 @@ void ISel::doMultiplyConst(MachineBasicBlock *MBB,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If 32 bits or less and immediate is in right range, emit mul by immediate
|
// If 32 bits or less and immediate is in right range, emit mul by immediate
|
||||||
if (Class == cByte || Class == cShort || Class == cInt)
|
if (Class == cByte || Class == cShort || Class == cInt) {
|
||||||
{
|
|
||||||
if (canUseAsImmediateForOpcode(CI, 0)) {
|
if (canUseAsImmediateForOpcode(CI, 0)) {
|
||||||
unsigned Op0r = getReg(Op0, MBB, IP);
|
unsigned Op0r = getReg(Op0, MBB, IP);
|
||||||
unsigned imm = CI->getRawValue() & 0xFFFF;
|
unsigned imm = CI->getRawValue() & 0xFFFF;
|
||||||
@@ -2237,11 +2257,13 @@ void ISel::emitShiftOperation(MachineBasicBlock *MBB,
|
|||||||
.addSImm(32);
|
.addSImm(32);
|
||||||
BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg2).addReg(SrcReg)
|
BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg2).addReg(SrcReg)
|
||||||
.addReg(ShiftAmountReg);
|
.addReg(ShiftAmountReg);
|
||||||
BuildMI(*MBB, IP, PPC32::SRW, 2, TmpReg3).addReg(SrcReg+1).addReg(TmpReg1);
|
BuildMI(*MBB, IP, PPC32::SRW, 2, TmpReg3).addReg(SrcReg+1)
|
||||||
BuildMI(*MBB, IP, PPC32::OR, 2, TmpReg4).addReg(TmpReg2).addReg(TmpReg3);
|
.addReg(TmpReg1);
|
||||||
|
BuildMI(*MBB, IP, PPC32::OR, 2,TmpReg4).addReg(TmpReg2).addReg(TmpReg3);
|
||||||
BuildMI(*MBB, IP, PPC32::ADDI, 2, TmpReg5).addReg(ShiftAmountReg)
|
BuildMI(*MBB, IP, PPC32::ADDI, 2, TmpReg5).addReg(ShiftAmountReg)
|
||||||
.addSImm(-32);
|
.addSImm(-32);
|
||||||
BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg6).addReg(SrcReg+1).addReg(TmpReg5);
|
BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg6).addReg(SrcReg+1)
|
||||||
|
.addReg(TmpReg5);
|
||||||
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(TmpReg4)
|
BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(TmpReg4)
|
||||||
.addReg(TmpReg6);
|
.addReg(TmpReg6);
|
||||||
BuildMI(*MBB, IP, PPC32::SLW, 2, DestReg+1).addReg(SrcReg+1)
|
BuildMI(*MBB, IP, PPC32::SLW, 2, DestReg+1).addReg(SrcReg+1)
|
||||||
@@ -2311,10 +2333,11 @@ void ISel::visitLoadInst(LoadInst &I) {
|
|||||||
static const unsigned Opcodes[] = {
|
static const unsigned Opcodes[] = {
|
||||||
PPC32::LBZ, PPC32::LHZ, PPC32::LWZ, PPC32::LFS
|
PPC32::LBZ, PPC32::LHZ, PPC32::LWZ, PPC32::LFS
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned Class = getClassB(I.getType());
|
unsigned Class = getClassB(I.getType());
|
||||||
unsigned Opcode = Opcodes[Class];
|
unsigned Opcode = Opcodes[Class];
|
||||||
if (I.getType() == Type::DoubleTy) Opcode = PPC32::LFD;
|
if (I.getType() == Type::DoubleTy) Opcode = PPC32::LFD;
|
||||||
|
if (Class == cShort && I.getType()->isSigned()) Opcode = PPC32::LHA;
|
||||||
unsigned DestReg = getReg(I);
|
unsigned DestReg = getReg(I);
|
||||||
|
|
||||||
if (AllocaInst *AI = dyn_castFixedAlloca(I.getOperand(0))) {
|
if (AllocaInst *AI = dyn_castFixedAlloca(I.getOperand(0))) {
|
||||||
@@ -2322,6 +2345,10 @@ void ISel::visitLoadInst(LoadInst &I) {
|
|||||||
if (Class == cLong) {
|
if (Class == cLong) {
|
||||||
addFrameReference(BuildMI(BB, PPC32::LWZ, 2, DestReg), FI);
|
addFrameReference(BuildMI(BB, PPC32::LWZ, 2, DestReg), FI);
|
||||||
addFrameReference(BuildMI(BB, PPC32::LWZ, 2, DestReg+1), FI, 4);
|
addFrameReference(BuildMI(BB, PPC32::LWZ, 2, DestReg+1), FI, 4);
|
||||||
|
} else if (Class == cByte && I.getType()->isSigned()) {
|
||||||
|
unsigned TmpReg = makeAnotherReg(I.getType());
|
||||||
|
addFrameReference(BuildMI(BB, Opcode, 2, TmpReg), FI);
|
||||||
|
BuildMI(BB, PPC32::EXTSB, 1, DestReg).addReg(TmpReg);
|
||||||
} else {
|
} else {
|
||||||
addFrameReference(BuildMI(BB, Opcode, 2, DestReg), FI);
|
addFrameReference(BuildMI(BB, Opcode, 2, DestReg), FI);
|
||||||
}
|
}
|
||||||
@@ -2331,6 +2358,10 @@ void ISel::visitLoadInst(LoadInst &I) {
|
|||||||
if (Class == cLong) {
|
if (Class == cLong) {
|
||||||
BuildMI(BB, PPC32::LWZ, 2, DestReg).addSImm(0).addReg(SrcAddrReg);
|
BuildMI(BB, PPC32::LWZ, 2, DestReg).addSImm(0).addReg(SrcAddrReg);
|
||||||
BuildMI(BB, PPC32::LWZ, 2, DestReg+1).addSImm(4).addReg(SrcAddrReg);
|
BuildMI(BB, PPC32::LWZ, 2, DestReg+1).addSImm(4).addReg(SrcAddrReg);
|
||||||
|
} else if (Class == cByte && I.getType()->isSigned()) {
|
||||||
|
unsigned TmpReg = makeAnotherReg(I.getType());
|
||||||
|
BuildMI(BB, Opcode, 2, TmpReg).addSImm(0).addReg(SrcAddrReg);
|
||||||
|
BuildMI(BB, PPC32::EXTSB, 1, DestReg).addReg(TmpReg);
|
||||||
} else {
|
} else {
|
||||||
BuildMI(BB, Opcode, 2, DestReg).addSImm(0).addReg(SrcAddrReg);
|
BuildMI(BB, Opcode, 2, DestReg).addSImm(0).addReg(SrcAddrReg);
|
||||||
}
|
}
|
||||||
@@ -2430,7 +2461,7 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
|
|||||||
case cFP32:
|
case cFP32:
|
||||||
case cFP64:
|
case cFP64:
|
||||||
// FSEL perhaps?
|
// FSEL perhaps?
|
||||||
std::cerr << "Cast fp-to-bool not implemented!";
|
std::cerr << "ERROR: Cast fp-to-bool not implemented!\n";
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -2476,26 +2507,15 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
|
|||||||
++DestReg;
|
++DestReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isUnsigned = SrcTy->isUnsigned() || SrcTy == Type::BoolTy;
|
bool isUnsigned = DestTy->isUnsigned() || DestTy == Type::BoolTy;
|
||||||
if (SrcClass < cInt) {
|
|
||||||
if (isUnsigned) {
|
|
||||||
unsigned shift = (SrcClass == cByte) ? 24 : 16;
|
|
||||||
BuildMI(*BB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg).addZImm(0)
|
|
||||||
.addImm(shift).addImm(31);
|
|
||||||
} else {
|
|
||||||
BuildMI(*BB, IP, (SrcClass == cByte) ? PPC32::EXTSB : PPC32::EXTSH,
|
|
||||||
1, DestReg).addReg(SrcReg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
BuildMI(*BB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
|
BuildMI(*BB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
|
||||||
}
|
|
||||||
|
|
||||||
if (isLong) { // Handle upper 32 bits as appropriate...
|
if (isLong) { // Handle upper 32 bits as appropriate...
|
||||||
--DestReg;
|
--DestReg;
|
||||||
if (isUnsigned) // Zero out top bits...
|
if (isUnsigned) // Zero out top bits...
|
||||||
BuildMI(*BB, IP, PPC32::LI, 1, DestReg).addSImm(0);
|
BuildMI(*BB, IP, PPC32::LI, 1, DestReg).addSImm(0);
|
||||||
else // Sign extend bottom half...
|
else // Sign extend bottom half...
|
||||||
BuildMI(*BB, IP, PPC32::SRAWI, 2, DestReg).addReg(DestReg).addImm(31);
|
BuildMI(*BB, IP, PPC32::SRAWI, 2, DestReg).addReg(SrcReg).addImm(31);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2509,7 +2529,7 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
|
|||||||
// Handle cast of LARGER int to SMALLER int with a clear or sign extend
|
// Handle cast of LARGER int to SMALLER int with a clear or sign extend
|
||||||
if ((SrcClass <= cInt || SrcClass == cLong) && DestClass <= cInt
|
if ((SrcClass <= cInt || SrcClass == cLong) && DestClass <= cInt
|
||||||
&& SrcClass > DestClass) {
|
&& SrcClass > DestClass) {
|
||||||
bool isUnsigned = SrcTy->isUnsigned() || SrcTy == Type::BoolTy;
|
bool isUnsigned = DestTy->isUnsigned() || DestTy == Type::BoolTy;
|
||||||
unsigned source = (SrcClass == cLong) ? SrcReg+1 : SrcReg;
|
unsigned source = (SrcClass == cLong) ? SrcReg+1 : SrcReg;
|
||||||
|
|
||||||
if (isUnsigned) {
|
if (isUnsigned) {
|
||||||
@@ -2627,7 +2647,7 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
|
|||||||
ValueFrameIdx, 4);
|
ValueFrameIdx, 4);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Cast fp-to-unsigned not implemented!";
|
std::cerr << "ERROR: Cast fp-to-unsigned not implemented!\n";
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -2706,33 +2726,37 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
|
|||||||
MachineBasicBlock::iterator IP,
|
MachineBasicBlock::iterator IP,
|
||||||
Value *Src, User::op_iterator IdxBegin,
|
Value *Src, User::op_iterator IdxBegin,
|
||||||
User::op_iterator IdxEnd, unsigned TargetReg) {
|
User::op_iterator IdxEnd, unsigned TargetReg) {
|
||||||
const TargetData &TD = TM.getTargetData ();
|
const TargetData &TD = TM.getTargetData();
|
||||||
const Type *Ty = Src->getType ();
|
const Type *Ty = Src->getType();
|
||||||
unsigned basePtrReg = getReg (Src, MBB, IP);
|
unsigned basePtrReg = getReg(Src, MBB, IP);
|
||||||
|
|
||||||
// GEPs have zero or more indices; we must perform a struct access
|
// GEPs have zero or more indices; we must perform a struct access
|
||||||
// or array access for each one.
|
// or array access for each one.
|
||||||
for (GetElementPtrInst::op_iterator oi = IdxBegin, oe = IdxEnd; oi != oe;
|
for (GetElementPtrInst::op_iterator oi = IdxBegin, oe = IdxEnd; oi != oe;
|
||||||
++oi) {
|
++oi) {
|
||||||
Value *idx = *oi;
|
Value *idx = *oi;
|
||||||
unsigned nextBasePtrReg = makeAnotherReg (Type::UIntTy);
|
unsigned nextBasePtrReg = makeAnotherReg(Type::UIntTy);
|
||||||
if (const StructType *StTy = dyn_cast<StructType> (Ty)) {
|
if (const StructType *StTy = dyn_cast<StructType>(Ty)) {
|
||||||
// It's a struct access. idx is the index into the structure,
|
// It's a struct access. idx is the index into the structure,
|
||||||
// which names the field. Use the TargetData structure to
|
// which names the field. Use the TargetData structure to
|
||||||
// pick out what the layout of the structure is in memory.
|
// pick out what the layout of the structure is in memory.
|
||||||
// Use the (constant) structure index's value to find the
|
// Use the (constant) structure index's value to find the
|
||||||
// right byte offset from the StructLayout class's list of
|
// right byte offset from the StructLayout class's list of
|
||||||
// structure member offsets.
|
// structure member offsets.
|
||||||
unsigned fieldIndex = cast<ConstantUInt> (idx)->getValue ();
|
unsigned fieldIndex = cast<ConstantUInt>(idx)->getValue();
|
||||||
unsigned memberOffset =
|
unsigned memberOffset =
|
||||||
TD.getStructLayout (StTy)->MemberOffsets[fieldIndex];
|
TD.getStructLayout(StTy)->MemberOffsets[fieldIndex];
|
||||||
|
|
||||||
|
if (0 == memberOffset) { // No-op
|
||||||
|
nextBasePtrReg = basePtrReg;
|
||||||
|
} else {
|
||||||
// Emit an ADDI to add memberOffset to the basePtr.
|
// Emit an ADDI to add memberOffset to the basePtr.
|
||||||
BuildMI (*MBB, IP, PPC32::ADDI, 2, nextBasePtrReg).addReg(basePtrReg)
|
BuildMI (*MBB, IP, PPC32::ADDI, 2, nextBasePtrReg).addReg(basePtrReg)
|
||||||
.addSImm(memberOffset);
|
.addSImm(memberOffset);
|
||||||
// The next type is the member of the structure selected by the
|
}
|
||||||
// index.
|
// The next type is the member of the structure selected by the index.
|
||||||
Ty = StTy->getElementType (fieldIndex);
|
Ty = StTy->getElementType(fieldIndex);
|
||||||
} else if (const SequentialType *SqTy = dyn_cast<SequentialType> (Ty)) {
|
} else if (const SequentialType *SqTy = dyn_cast<SequentialType>(Ty)) {
|
||||||
// Many GEP instructions use a [cast (int/uint) to LongTy] as their
|
// Many GEP instructions use a [cast (int/uint) to LongTy] as their
|
||||||
// operand. Handle this case directly now...
|
// operand. Handle this case directly now...
|
||||||
if (CastInst *CI = dyn_cast<CastInst>(idx))
|
if (CastInst *CI = dyn_cast<CastInst>(idx))
|
||||||
@@ -2741,10 +2765,9 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
|
|||||||
idx = CI->getOperand(0);
|
idx = CI->getOperand(0);
|
||||||
|
|
||||||
Ty = SqTy->getElementType();
|
Ty = SqTy->getElementType();
|
||||||
unsigned elementSize = TD.getTypeSize (Ty);
|
unsigned elementSize = TD.getTypeSize(Ty);
|
||||||
|
|
||||||
if (idx == Constant::getNullValue(idx->getType())) {
|
if (idx == Constant::getNullValue(idx->getType())) { // No-op
|
||||||
// GEP with idx 0 is a no-op
|
|
||||||
nextBasePtrReg = basePtrReg;
|
nextBasePtrReg = basePtrReg;
|
||||||
} else if (elementSize == 1) {
|
} else if (elementSize == 1) {
|
||||||
// If the element size is 1, we don't have to multiply, just add
|
// If the element size is 1, we don't have to multiply, just add
|
||||||
@@ -2754,8 +2777,8 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
|
|||||||
} else {
|
} else {
|
||||||
// It's an array or pointer access: [ArraySize x ElementType].
|
// It's an array or pointer access: [ArraySize x ElementType].
|
||||||
// We want to add basePtrReg to (idxReg * sizeof ElementType). First, we
|
// We want to add basePtrReg to (idxReg * sizeof ElementType). First, we
|
||||||
// must find the size of the pointed-to type (Not coincidentally, the next
|
// must find the size of the pointed-to type (Not coincidentally, the
|
||||||
// type is the type of the elements in the array).
|
// next type is the type of the elements in the array).
|
||||||
unsigned OffsetReg = makeAnotherReg(idx->getType());
|
unsigned OffsetReg = makeAnotherReg(idx->getType());
|
||||||
ConstantUInt *CUI = ConstantUInt::get(Type::UIntTy, elementSize);
|
ConstantUInt *CUI = ConstantUInt::get(Type::UIntTy, elementSize);
|
||||||
doMultiplyConst(MBB, IP, OffsetReg, idx, CUI);
|
doMultiplyConst(MBB, IP, OffsetReg, idx, CUI);
|
||||||
@@ -2773,7 +2796,7 @@ void ISel::emitGEPOperation(MachineBasicBlock *MBB,
|
|||||||
// After we have processed all the indices, the result is left in
|
// After we have processed all the indices, the result is left in
|
||||||
// basePtrReg. Move it to the register where we were expected to
|
// basePtrReg. Move it to the register where we were expected to
|
||||||
// put the answer.
|
// put the answer.
|
||||||
BuildMI (BB, PPC32::OR, 2, TargetReg).addReg(basePtrReg).addReg(basePtrReg);
|
BuildMI(BB, PPC32::OR, 2, TargetReg).addReg(basePtrReg).addReg(basePtrReg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// visitAllocaInst - If this is a fixed size alloca, allocate space from the
|
/// visitAllocaInst - If this is a fixed size alloca, allocate space from the
|
||||||
|
Reference in New Issue
Block a user