#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/ADT/Statistic.h"
setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand);
setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand);
+ setShiftAmountFlavor(Extend); // shl X, 32 == 0
addLegalFPImmediate(+0.0); // Necessary for FSEL
addLegalFPImmediate(-0.0); //
// We need to load the argument to a virtual register if we determined above
// that we ran out of physical registers of the appropriate type
if (needsLoad) {
+ unsigned SubregOffset = 0;
+ if (ObjectVT == MVT::i8 || ObjectVT == MVT::i1) SubregOffset = 3;
+ if (ObjectVT == MVT::i16) SubregOffset = 2;
int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
+ FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN,
+ DAG.getConstant(SubregOffset, MVT::i32));
argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN);
}
// If the function takes variable number of arguments, make a frame index for
// the start of the first vararg value... for expansion of llvm.va_start.
- if (F.isVarArg())
+ if (F.isVarArg()) {
VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset);
+ SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32);
+ // If this function is vararg, store any remaining integer argument regs
+ // to their spots on the stack so that they may be loaded by deferencing the
+ // result of va_next.
+ std::vector<SDOperand> MemOps;
+ for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) {
+ BuildMI(&BB, PPC::IMPLICIT_DEF, 0, GPR[GPR_idx]);
+ SDOperand Val = DAG.getCopyFromReg(GPR[GPR_idx], MVT::i32, DAG.getRoot());
+ SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
+ Val, FIN);
+ MemOps.push_back(Store);
+ // Increment the address by four for the next argument to store
+ SDOperand PtrOff = DAG.getConstant(4, getPointerTy());
+ FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, PtrOff);
+ }
+ DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps));
+ }
return ArgValues;
}
unsigned ArgOffset = 24;
unsigned GPR_remaining = 8;
unsigned FPR_remaining = 13;
- unsigned GPR_idx = 0, FPR_idx = 0;
- static const unsigned GPR[] = {
- PPC::R3, PPC::R4, PPC::R5, PPC::R6,
- PPC::R7, PPC::R8, PPC::R9, PPC::R10,
- };
- static const unsigned FPR[] = {
- PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
- PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13
- };
std::vector<SDOperand> MemOps;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
// FALL THROUGH
case MVT::i32:
if (GPR_remaining > 0) {
- args_to_use.push_back(DAG.getCopyToReg(Chain, Args[i].first,
- GPR[GPR_idx]));
+ args_to_use.push_back(Args[i].first);
--GPR_remaining;
- ++GPR_idx;
} else {
MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
Args[i].first, PtrOff));
Args[i].first, DAG.getConstant(1, MVT::i32));
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
Args[i].first, DAG.getConstant(0, MVT::i32));
- args_to_use.push_back(DAG.getCopyToReg(Chain, Hi, GPR[GPR_idx]));
+ args_to_use.push_back(Hi);
--GPR_remaining;
- ++GPR_idx;
if (GPR_remaining > 0) {
- args_to_use.push_back(DAG.getCopyToReg(Chain, Lo, GPR[GPR_idx]));
+ args_to_use.push_back(Lo);
--GPR_remaining;
- ++GPR_idx;
} else {
SDOperand ConstFour = DAG.getConstant(4, getPointerTy());
PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour);
case MVT::f32:
case MVT::f64:
if (FPR_remaining > 0) {
+ args_to_use.push_back(Args[i].first);
+ --FPR_remaining;
if (isVarArg) {
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Chain,
Args[i].first, PtrOff);
if (GPR_remaining > 0) {
SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff);
MemOps.push_back(Load);
- args_to_use.push_back(DAG.getCopyToReg(Load, Load,
- GPR[GPR_idx]));
+ args_to_use.push_back(Load);
+ --GPR_remaining;
}
- if (GPR_remaining > 1 && MVT::f64 == ArgVT) {
+ if (GPR_remaining > 0 && MVT::f64 == ArgVT) {
SDOperand ConstFour = DAG.getConstant(4, getPointerTy());
PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour);
SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff);
MemOps.push_back(Load);
- args_to_use.push_back(DAG.getCopyToReg(Load, Load,
- GPR[GPR_idx+1]));
+ args_to_use.push_back(Load);
+ --GPR_remaining;
+ }
+ } else {
+ // If we have any FPRs remaining, we may also have GPRs remaining.
+ // Args passed in FPRs consume either 1 (f32) or 2 (f64) available
+ // GPRs.
+ if (GPR_remaining > 0) {
+ args_to_use.push_back(DAG.getNode(ISD::UNDEF, MVT::i32));
+ --GPR_remaining;
+ }
+ if (GPR_remaining > 0 && MVT::f64 == ArgVT) {
+ args_to_use.push_back(DAG.getNode(ISD::UNDEF, MVT::i32));
+ --GPR_remaining;
}
- }
- args_to_use.push_back(DAG.getCopyToReg(Chain, Args[i].first,
- FPR[FPR_idx]));
- --FPR_remaining;
- ++FPR_idx;
- // If we have any FPRs remaining, we may also have GPRs remaining.
- // Args passed in FPRs consume either 1 (f32) or 2 (f64) available
- // GPRs.
- if (GPR_remaining > 0) {
- --GPR_remaining;
- ++GPR_idx;
- }
- if (GPR_remaining > 0 && MVT::f64 == ArgVT) {
- --GPR_remaining;
- ++GPR_idx;
}
} else {
MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
}
namespace {
-
+Statistic<>NotLogic("ppc-codegen", "Number of inverted logical ops");
+Statistic<>FusedFP("ppc-codegen", "Number of fused fp operations");
//===--------------------------------------------------------------------===//
/// ISel - PPC32 specific code to select PPC32 machine instructions for
/// SelectionDAG operations.
void SelectBranchCC(SDOperand N);
};
+/// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It
+/// returns zero when the input is not exactly a power of two.
+static unsigned ExactLog2(unsigned Val) {
+ if (Val == 0 || (Val & (Val-1))) return 0;
+ unsigned Count = 0;
+ while (Val != 1) {
+ Val >>= 1;
+ ++Count;
+ }
+ return Count;
+}
+
/// canUseAsImmediateForOpcode - This method returns a value indicating whether
/// the ConstantSDNode N can be used as an immediate to Opcode. The return
/// values are either 0, 1 or 2. 0 indicates that either N is not a
if ((v & 0x0000FFFF) == 0) { Imm = v >> 16; return 2; }
break;
case ISD::MUL:
+ case ISD::SUB:
if (v <= 32767 && v >= -32768) { Imm = v & 0xFFFF; return 1; }
break;
case ISD::SETCC:
if (U && (v >= 0 && v <= 65535)) { Imm = v & 0xFFFF; return 1; }
if (!U && (v <= 32767 && v >= -32768)) { Imm = v & 0xFFFF; return 1; }
break;
+ case ISD::SDIV:
+ if (0 != ExactLog2(v)) { Imm = ExactLog2(v); return 1; }
+ break;
}
return 0;
}
.addMBB(copy0MBB).addReg(TrueValue).addMBB(thisMBB);
return Result;
}
+
+ case ISD::FNEG:
+ if (!NoExcessFPPrecision &&
+ ISD::ADD == N.getOperand(0).getOpcode() &&
+ N.getOperand(0).Val->hasOneUse() &&
+ ISD::MUL == N.getOperand(0).getOperand(0).getOpcode() &&
+ N.getOperand(0).getOperand(0).Val->hasOneUse()) {
+ ++FusedFP; // Statistic
+ Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(1));
+ Tmp3 = SelectExpr(N.getOperand(0).getOperand(1));
+ Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS;
+ BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
+ } else if (!NoExcessFPPrecision &&
+ ISD::SUB == N.getOperand(0).getOpcode() &&
+ N.getOperand(0).Val->hasOneUse() &&
+ ISD::MUL == N.getOperand(0).getOperand(0).getOpcode() &&
+ N.getOperand(0).getOperand(0).Val->hasOneUse()) {
+ ++FusedFP; // Statistic
+ Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(1));
+ Tmp3 = SelectExpr(N.getOperand(0).getOperand(1));
+ Opc = DestType == MVT::f64 ? PPC::FNMSUB : PPC::FNMSUBS;
+ BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
+ } else if (ISD::FABS == N.getOperand(0).getOpcode()) {
+ Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+ BuildMI(BB, PPC::FNABS, 1, Result).addReg(Tmp1);
+ } else {
+ Tmp1 = SelectExpr(N.getOperand(0));
+ BuildMI(BB, PPC::FNEG, 1, Result).addReg(Tmp1);
+ }
+ return Result;
+ case ISD::FABS:
+ Tmp1 = SelectExpr(N.getOperand(0));
+ BuildMI(BB, PPC::FABS, 1, Result).addReg(Tmp1);
+ return Result;
+
case ISD::FP_ROUND:
assert (DestType == MVT::f32 &&
N.getOperand(0).getValueType() == MVT::f64 &&
return Result;
}
- case ISD::MUL:
case ISD::ADD:
+ if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::MUL &&
+ N.getOperand(0).Val->hasOneUse()) {
+ ++FusedFP; // Statistic
+ Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
+ Tmp3 = SelectExpr(N.getOperand(1));
+ Opc = DestType == MVT::f64 ? PPC::FMADD : PPC::FMADDS;
+ BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
+ return Result;
+ }
+ Opc = DestType == MVT::f64 ? PPC::FADD : PPC::FADDS;
+ Tmp1 = SelectExpr(N.getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(1));
+ BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
+ return Result;
+
case ISD::SUB:
+ if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::MUL &&
+ N.getOperand(0).Val->hasOneUse()) {
+ ++FusedFP; // Statistic
+ Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
+ Tmp3 = SelectExpr(N.getOperand(1));
+ Opc = DestType == MVT::f64 ? PPC::FMSUB : PPC::FMSUBS;
+ BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
+ return Result;
+ }
+ Opc = DestType == MVT::f64 ? PPC::FSUB : PPC::FSUBS;
+ Tmp1 = SelectExpr(N.getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(1));
+ BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
+ return Result;
+
+ case ISD::MUL:
case ISD::SDIV:
switch( opcode ) {
case ISD::MUL: Opc = DestType == MVT::f64 ? PPC::FMUL : PPC::FMULS; break;
- case ISD::ADD: Opc = DestType == MVT::f64 ? PPC::FADD : PPC::FADDS; break;
- case ISD::SUB: Opc = DestType == MVT::f64 ? PPC::FSUB : PPC::FSUBS; break;
case ISD::SDIV: Opc = DestType == MVT::f64 ? PPC::FDIV : PPC::FDIVS; break;
};
Tmp1 = SelectExpr(N.getOperand(0));
unsigned &Reg = ExprMap[N];
if (Reg) return Reg;
- if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::ADD_PARTS &&
- N.getOpcode() != ISD::SUB_PARTS)
+ switch (N.getOpcode()) {
+ default:
Reg = Result = (N.getValueType() != MVT::Other) ?
- MakeReg(N.getValueType()) : 1;
- else {
+ MakeReg(N.getValueType()) : 1;
+ break;
+ case ISD::CALL:
// If this is a call instruction, make sure to prepare ALL of the result
// values as well as the chain.
- if (N.getOpcode() == ISD::CALL) {
- if (Node->getNumValues() == 1)
- Reg = Result = 1; // Void call, just a chain.
- else {
- Result = MakeReg(Node->getValueType(0));
- ExprMap[N.getValue(0)] = Result;
- for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
- ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
- ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
- }
- } else {
+ if (Node->getNumValues() == 1)
+ Reg = Result = 1; // Void call, just a chain.
+ else {
Result = MakeReg(Node->getValueType(0));
ExprMap[N.getValue(0)] = Result;
- for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i)
+ for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
+ ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
}
+ break;
+ case ISD::ADD_PARTS:
+ case ISD::SUB_PARTS:
+ case ISD::SHL_PARTS:
+ case ISD::SRL_PARTS:
+ case ISD::SRA_PARTS:
+ Result = MakeReg(Node->getValueType(0));
+ ExprMap[N.getValue(0)] = Result;
+ for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i)
+ ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
+ break;
}
+ if (ISD::CopyFromReg == opcode)
+ DestType = N.getValue(0).getValueType();
+
if (DestType == MVT::f64 || DestType == MVT::f32)
- if (ISD::LOAD != opcode && ISD::EXTLOAD != opcode)
+ if (ISD::LOAD != opcode && ISD::EXTLOAD != opcode && ISD::UNDEF != opcode)
return SelectExprFP(N, Result);
switch (opcode) {
default:
Node->dump();
assert(0 && "Node not handled!\n");
-
+ case ISD::UNDEF:
+ BuildMI(BB, PPC::IMPLICIT_DEF, 0, Result);
+ return Result;
case ISD::DYNAMIC_STACKALLOC:
// Generate both result values. FIXME: Need a better commment here?
if (Result != 1)
}
case ISD::CALL: {
+ unsigned GPR_idx = 0, FPR_idx = 0;
+ static const unsigned GPR[] = {
+ PPC::R3, PPC::R4, PPC::R5, PPC::R6,
+ PPC::R7, PPC::R8, PPC::R9, PPC::R10,
+ };
+ static const unsigned FPR[] = {
+ PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
+ PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13
+ };
+
// Lower the chain for this call.
Select(N.getOperand(0));
ExprMap[N.getValue(Node->getNumValues()-1)] = 1;
- for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
- Select(N.getOperand(i));
-
+ MachineInstr *CallMI;
// Emit the correct call instruction based on the type of symbol called.
if (GlobalAddressSDNode *GASD =
dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) {
- BuildMI(BB, PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(), true);
+ CallMI = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(),
+ true);
} else if (ExternalSymbolSDNode *ESSDN =
dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) {
- BuildMI(BB, PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(), true);
+ CallMI = BuildMI(PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(),
+ true);
} else {
Tmp1 = SelectExpr(N.getOperand(1));
BuildMI(BB, PPC::OR, 2, PPC::R12).addReg(Tmp1).addReg(Tmp1);
BuildMI(BB, PPC::MTCTR, 1).addReg(PPC::R12);
- BuildMI(BB, PPC::CALLindirect, 3).addImm(20).addImm(0).addReg(PPC::R12);
+ CallMI = BuildMI(PPC::CALLindirect, 3).addImm(20).addImm(0)
+ .addReg(PPC::R12);
+ }
+
+ // Load the register args to virtual regs
+ std::vector<unsigned> ArgVR;
+ for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
+ ArgVR.push_back(SelectExpr(N.getOperand(i)));
+
+ // Copy the virtual registers into the appropriate argument register
+ for(int i = 0, e = ArgVR.size(); i < e; ++i) {
+ switch(N.getOperand(i+2).getValueType()) {
+ default: Node->dump(); assert(0 && "Unknown value type for call");
+ case MVT::i1:
+ case MVT::i8:
+ case MVT::i16:
+ case MVT::i32:
+ assert(GPR_idx < 8 && "Too many int args");
+ if (N.getOperand(i+2).getOpcode() != ISD::UNDEF) {
+ BuildMI(BB, PPC::OR,2,GPR[GPR_idx]).addReg(ArgVR[i]).addReg(ArgVR[i]);
+ CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
+ }
+ ++GPR_idx;
+ break;
+ case MVT::f64:
+ case MVT::f32:
+ assert(FPR_idx < 13 && "Too many fp args");
+ BuildMI(BB, PPC::FMR, 1, FPR[FPR_idx]).addReg(ArgVR[i]);
+ CallMI->addRegOperand(FPR[FPR_idx], MachineOperand::Use);
+ ++FPR_idx;
+ break;
+ }
}
+
+ // Put the call instruction in the correct place in the MachineBasicBlock
+ BB->push_back(CallMI);
switch (Node->getValueType(0)) {
default: assert(0 && "Unknown value type for call result!");
case MVT::i8:
case MVT::i16:
case MVT::i32:
- BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R3).addReg(PPC::R3);
- if (Node->getValueType(1) == MVT::i32)
- BuildMI(BB, PPC::OR, 2, Result+1).addReg(PPC::R4).addReg(PPC::R4);
+ if (Node->getValueType(1) == MVT::i32) {
+ BuildMI(BB, PPC::OR, 2, Result+1).addReg(PPC::R3).addReg(PPC::R3);
+ BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R4).addReg(PPC::R4);
+ } else {
+ BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R3).addReg(PPC::R3);
+ }
break;
case MVT::f32:
case MVT::f64:
case ISD::AND:
case ISD::OR:
- case ISD::XOR:
- assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
Tmp1 = SelectExpr(N.getOperand(0));
switch(canUseAsImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
default: assert(0 && "unhandled result code");
switch (opcode) {
case ISD::AND: Opc = PPC::AND; break;
case ISD::OR: Opc = PPC::OR; break;
- case ISD::XOR: Opc = PPC::XOR; break;
}
BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
break;
switch (opcode) {
case ISD::AND: Opc = PPC::ANDIo; break;
case ISD::OR: Opc = PPC::ORI; break;
- case ISD::XOR: Opc = PPC::XORI; break;
}
BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
break;
switch (opcode) {
case ISD::AND: Opc = PPC::ANDISo; break;
case ISD::OR: Opc = PPC::ORIS; break;
- case ISD::XOR: Opc = PPC::XORIS; break;
}
BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
break;
}
return Result;
- case ISD::SUB:
- assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
+ case ISD::XOR: {
+ // Check for EQV: xor, (xor a, -1), b
+ if (N.getOperand(0).getOpcode() == ISD::XOR &&
+ N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
+ cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->isAllOnesValue()) {
+ ++NotLogic;
+ Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(1));
+ BuildMI(BB, PPC::EQV, 2, Result).addReg(Tmp1).addReg(Tmp2);
+ return Result;
+ }
+ // Check for NOT, NOR, and NAND: xor (copy, or, and), -1
+ if (N.getOperand(1).getOpcode() == ISD::Constant &&
+ cast<ConstantSDNode>(N.getOperand(1))->isAllOnesValue()) {
+ ++NotLogic;
+ switch(N.getOperand(0).getOpcode()) {
+ case ISD::OR:
+ Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
+ BuildMI(BB, PPC::NOR, 2, Result).addReg(Tmp1).addReg(Tmp2);
+ break;
+ case ISD::AND:
+ Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
+ BuildMI(BB, PPC::NAND, 2, Result).addReg(Tmp1).addReg(Tmp2);
+ break;
+ default:
+ Tmp1 = SelectExpr(N.getOperand(0));
+ BuildMI(BB, PPC::NOR, 2, Result).addReg(Tmp1).addReg(Tmp1);
+ break;
+ }
+ return Result;
+ }
Tmp1 = SelectExpr(N.getOperand(0));
+ switch(canUseAsImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
+ default: assert(0 && "unhandled result code");
+ case 0: // No immediate
+ Tmp2 = SelectExpr(N.getOperand(1));
+ BuildMI(BB, PPC::XOR, 2, Result).addReg(Tmp1).addReg(Tmp2);
+ break;
+ case 1: // Low immediate
+ BuildMI(BB, PPC::XORI, 2, Result).addReg(Tmp1).addImm(Tmp2);
+ break;
+ case 2: // Shifted immediate
+ BuildMI(BB, PPC::XORIS, 2, Result).addReg(Tmp1).addImm(Tmp2);
+ break;
+ }
+ return Result;
+ }
+
+ case ISD::SUB:
Tmp2 = SelectExpr(N.getOperand(1));
- BuildMI(BB, PPC::SUBF, 2, Result).addReg(Tmp2).addReg(Tmp1);
+ if (1 == canUseAsImmediateForOpcode(N.getOperand(0), opcode, Tmp1))
+ BuildMI(BB, PPC::SUBFIC, 2, Result).addReg(Tmp2).addSImm(Tmp1);
+ else {
+ Tmp1 = SelectExpr(N.getOperand(0));
+ BuildMI(BB, PPC::SUBF, 2, Result).addReg(Tmp2).addReg(Tmp1);
+ }
return Result;
case ISD::MUL:
- assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
Tmp1 = SelectExpr(N.getOperand(0));
if (1 == canUseAsImmediateForOpcode(N.getOperand(1), opcode, Tmp2))
BuildMI(BB, PPC::MULLI, 2, Result).addReg(Tmp1).addSImm(Tmp2);
case ISD::SDIV:
case ISD::UDIV:
- assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
+ if (1 == canUseAsImmediateForOpcode(N.getOperand(1), opcode, Tmp3)) {
+ Tmp1 = MakeReg(MVT::i32);
+ Tmp2 = SelectExpr(N.getOperand(0));
+ BuildMI(BB, PPC::SRAWI, 2, Tmp1).addReg(Tmp2).addImm(Tmp3);
+ BuildMI(BB, PPC::ADDZE, 1, Result).addReg(Tmp1);
+ return Result;
+ }
Tmp1 = SelectExpr(N.getOperand(0));
Tmp2 = SelectExpr(N.getOperand(1));
Opc = (ISD::UDIV == opcode) ? PPC::DIVWU : PPC::DIVW;
case ISD::UREM:
case ISD::SREM: {
- assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
Tmp1 = SelectExpr(N.getOperand(0));
Tmp2 = SelectExpr(N.getOperand(1));
Tmp3 = MakeReg(MVT::i32);
for (unsigned i = 0, e = N.getNumOperands(); i != e; ++i)
InVals.push_back(SelectExpr(N.getOperand(i)));
if (N.getOpcode() == ISD::ADD_PARTS) {
- BuildMI(BB, PPC::ADDC, 2, Result+1).addReg(InVals[0]).addReg(InVals[2]);
- BuildMI(BB, PPC::ADDE, 2, Result).addReg(InVals[1]).addReg(InVals[3]);
+ BuildMI(BB, PPC::ADDC, 2, Result).addReg(InVals[0]).addReg(InVals[2]);
+ BuildMI(BB, PPC::ADDE, 2, Result+1).addReg(InVals[1]).addReg(InVals[3]);
} else {
- BuildMI(BB, PPC::SUBFC, 2, Result+1).addReg(InVals[2]).addReg(InVals[0]);
- BuildMI(BB, PPC::SUBFE, 2, Result).addReg(InVals[3]).addReg(InVals[1]);
+ BuildMI(BB, PPC::SUBFC, 2, Result).addReg(InVals[2]).addReg(InVals[0]);
+ BuildMI(BB, PPC::SUBFE, 2, Result+1).addReg(InVals[3]).addReg(InVals[1]);
+ }
+ return Result+N.ResNo;
+ }
+
+ case ISD::SHL_PARTS:
+ case ISD::SRA_PARTS:
+ case ISD::SRL_PARTS: {
+ assert(N.getNumOperands() == 3 && N.getValueType() == MVT::i32 &&
+ "Not an i64 shift!");
+ unsigned ShiftOpLo = SelectExpr(N.getOperand(0));
+ unsigned ShiftOpHi = SelectExpr(N.getOperand(1));
+ unsigned SHReg = SelectExpr(N.getOperand(2));
+ Tmp1 = MakeReg(MVT::i32);
+ Tmp2 = MakeReg(MVT::i32);
+ Tmp3 = MakeReg(MVT::i32);
+ unsigned Tmp4 = MakeReg(MVT::i32);
+ unsigned Tmp5 = MakeReg(MVT::i32);
+ unsigned Tmp6 = MakeReg(MVT::i32);
+ BuildMI(BB, PPC::SUBFIC, 2, Tmp1).addReg(SHReg).addSImm(32);
+ if (ISD::SHL_PARTS == opcode) {
+ BuildMI(BB, PPC::SLW, 2, Tmp2).addReg(ShiftOpHi).addReg(SHReg);
+ BuildMI(BB, PPC::SRW, 2, Tmp3).addReg(ShiftOpLo).addReg(Tmp1);
+ BuildMI(BB, PPC::OR, 2, Tmp4).addReg(Tmp2).addReg(Tmp3);
+ BuildMI(BB, PPC::ADDI, 2, Tmp5).addReg(SHReg).addSImm(-32);
+ BuildMI(BB, PPC::SLW, 2, Tmp6).addReg(ShiftOpLo).addReg(Tmp5);
+ BuildMI(BB, PPC::OR, 2, Result+1).addReg(Tmp4).addReg(Tmp6);
+ BuildMI(BB, PPC::SLW, 2, Result).addReg(ShiftOpLo).addReg(SHReg);
+ } else if (ISD::SRL_PARTS == opcode) {
+ BuildMI(BB, PPC::SRW, 2, Tmp2).addReg(ShiftOpLo).addReg(SHReg);
+ BuildMI(BB, PPC::SLW, 2, Tmp3).addReg(ShiftOpHi).addReg(Tmp1);
+ BuildMI(BB, PPC::OR, 2, Tmp4).addReg(Tmp2).addReg(Tmp3);
+ BuildMI(BB, PPC::ADDI, 2, Tmp5).addReg(SHReg).addSImm(-32);
+ BuildMI(BB, PPC::SRW, 2, Tmp6).addReg(ShiftOpHi).addReg(Tmp5);
+ BuildMI(BB, PPC::OR, 2, Result).addReg(Tmp4).addReg(Tmp6);
+ BuildMI(BB, PPC::SRW, 2, Result+1).addReg(ShiftOpHi).addReg(SHReg);
+ } else {
+ MachineBasicBlock *TmpMBB = new MachineBasicBlock(BB->getBasicBlock());
+ MachineBasicBlock *PhiMBB = new MachineBasicBlock(BB->getBasicBlock());
+ MachineBasicBlock *OldMBB = BB;
+ MachineFunction *F = BB->getParent();
+ ilist<MachineBasicBlock>::iterator It = BB; ++It;
+ F->getBasicBlockList().insert(It, TmpMBB);
+ F->getBasicBlockList().insert(It, PhiMBB);
+ BB->addSuccessor(TmpMBB);
+ BB->addSuccessor(PhiMBB);
+ BuildMI(BB, PPC::SRW, 2, Tmp2).addReg(ShiftOpLo).addReg(SHReg);
+ BuildMI(BB, PPC::SLW, 2, Tmp3).addReg(ShiftOpHi).addReg(Tmp1);
+ BuildMI(BB, PPC::OR, 2, Tmp4).addReg(Tmp2).addReg(Tmp3);
+ BuildMI(BB, PPC::ADDICo, 2, Tmp5).addReg(SHReg).addSImm(-32);
+ BuildMI(BB, PPC::SRAW, 2, Tmp6).addReg(ShiftOpHi).addReg(Tmp5);
+ BuildMI(BB, PPC::SRAW, 2, Result+1).addReg(ShiftOpHi).addReg(SHReg);
+ BuildMI(BB, PPC::BLE, 2).addReg(PPC::CR0).addMBB(PhiMBB);
+ // Select correct least significant half if the shift amount > 32
+ BB = TmpMBB;
+ unsigned Tmp7 = MakeReg(MVT::i32);
+ BuildMI(BB, PPC::OR, 2, Tmp7).addReg(Tmp6).addReg(Tmp6);
+ TmpMBB->addSuccessor(PhiMBB);
+ BB = PhiMBB;
+ BuildMI(BB, PPC::PHI, 4, Result).addReg(Tmp4).addMBB(OldMBB)
+ .addReg(Tmp7).addMBB(TmpMBB);
}
return Result+N.ResNo;
}
Select(N.getOperand(0));
Tmp1 = SelectExpr(N.getOperand(1));
Tmp2 = SelectExpr(N.getOperand(2));
- BuildMI(BB, PPC::OR, 2, PPC::R3).addReg(Tmp1).addReg(Tmp1);
- BuildMI(BB, PPC::OR, 2, PPC::R4).addReg(Tmp2).addReg(Tmp2);
+ BuildMI(BB, PPC::OR, 2, PPC::R3).addReg(Tmp2).addReg(Tmp2);
+ BuildMI(BB, PPC::OR, 2, PPC::R4).addReg(Tmp1).addReg(Tmp1);
break;
case 2:
Select(N.getOperand(0));