setOperationAction(ISD::MEMSET, MVT::Other, Expand);
setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+ setOperationAction(ISD::PREFETCH, MVT::Other, Expand);
// PowerPC has no SREM/UREM instructions
setOperationAction(ISD::SREM, MVT::i32, Expand);
addRegisterClass(MVT::i64, PPC::G8RCRegisterClass);
// BUILD_PAIR can't be handled natively, and should be expanded to shl/or
setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
+ // 64-bit PowerPC wants to expand i128 shifts itself.
+ setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom);
+ setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom);
+ setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom);
} else {
// 32-bit PowerPC wants to expand i64 shifts itself.
setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom);
computeRegisterProperties();
}
+/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
+/// function arguments in the caller parameter area.
+unsigned PPCTargetLowering::getByValTypeAlignment(const Type *Ty) const {
+ TargetMachine &TM = getTargetMachine();
+ // Darwin passes everything on 4 byte boundary.
+ if (TM.getSubtarget<PPCSubtarget>().isDarwin())
+ return 4;
+ // FIXME Elf TBD
+ return 4;
+}
+
const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
default: return 0;
APInt LHSKnownZero, LHSKnownOne;
APInt RHSKnownZero, RHSKnownOne;
DAG.ComputeMaskedBits(N.getOperand(0),
- APInt::getAllOnesValue(32),
+ APInt::getAllOnesValue(N.getOperand(0)
+ .getValueSizeInBits()),
LHSKnownZero, LHSKnownOne);
if (LHSKnownZero.getBoolValue()) {
DAG.ComputeMaskedBits(N.getOperand(1),
- APInt::getAllOnesValue(32),
+ APInt::getAllOnesValue(N.getOperand(1)
+ .getValueSizeInBits()),
RHSKnownZero, RHSKnownOne);
// If all of the bits are known zero on the LHS or RHS, the add won't
// carry.
- if ((LHSKnownZero | RHSKnownZero) == ~0U) {
+ if (~(LHSKnownZero | RHSKnownZero) == 0) {
Base = N.getOperand(0);
Index = N.getOperand(1);
return true;
// LowerOperation implementation
//===----------------------------------------------------------------------===//
-static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerConstantPool(SDOperand Op,
+ SelectionDAG &DAG) {
MVT::ValueType PtrVT = Op.getValueType();
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
Constant *C = CP->getConstVal();
return Lo;
}
-static SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerJumpTable(SDOperand Op, SelectionDAG &DAG) {
MVT::ValueType PtrVT = Op.getValueType();
JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
SDOperand JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
return Lo;
}
-static SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerGlobalTLSAddress(SDOperand Op,
+ SelectionDAG &DAG) {
assert(0 && "TLS not implemented for PPC.");
}
-static SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerGlobalAddress(SDOperand Op,
+ SelectionDAG &DAG) {
MVT::ValueType PtrVT = Op.getValueType();
GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
GlobalValue *GV = GSDN->getGlobal();
return DAG.getLoad(PtrVT, DAG.getEntryNode(), Lo, NULL, 0);
}
-static SDOperand LowerSETCC(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerSETCC(SDOperand Op, SelectionDAG &DAG) {
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
// If we're comparing for equality to zero, expose the fact that this is
return SDOperand();
}
-static SDOperand LowerVAARG(SDOperand Op, SelectionDAG &DAG,
+SDOperand PPCTargetLowering::LowerVAARG(SDOperand Op, SelectionDAG &DAG,
int VarArgsFrameIndex,
int VarArgsStackOffset,
unsigned VarArgsNumGPR,
assert(0 && "VAARG in ELF32 ABI not implemented yet!");
}
-static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
+SDOperand PPCTargetLowering::LowerVASTART(SDOperand Op, SelectionDAG &DAG,
int VarArgsFrameIndex,
int VarArgsStackOffset,
unsigned VarArgsNumGPR,
return FPR;
}
-static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
- int &VarArgsFrameIndex,
- int &VarArgsStackOffset,
- unsigned &VarArgsNumGPR,
- unsigned &VarArgsNumFPR,
- const PPCSubtarget &Subtarget) {
+SDOperand
+PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op,
+ SelectionDAG &DAG,
+ int &VarArgsFrameIndex,
+ int &VarArgsStackOffset,
+ unsigned &VarArgsNumGPR,
+ unsigned &VarArgsNumFPR,
+ const PPCSubtarget &Subtarget) {
// TODO: add description of PPC stack frame format, or at least some docs.
//
MachineFunction &MF = DAG.getMachineFunction();
// represented with two words (long long or double) must be copied to an
// even GPR_idx value or to an even ArgOffset value.
+ SmallVector<SDOperand, 8> MemOps;
+
for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
SDOperand ArgVal;
bool needsLoad = false;
unsigned ArgSize = ObjSize;
unsigned Flags = cast<ConstantSDNode>(Op.getOperand(ArgNo+3))->getValue();
unsigned AlignFlag = 1 << ISD::ParamFlags::OrigAlignmentOffs;
+ unsigned isByVal = Flags & ISD::ParamFlags::ByVal;
// See if next argument requires stack alignment in ELF
bool Expand = (ObjectVT == MVT::f64) || ((ArgNo + 1 < e) &&
(cast<ConstantSDNode>(Op.getOperand(ArgNo+4))->getValue() & AlignFlag) &&
(!(Flags & AlignFlag)));
unsigned CurArgOffset = ArgOffset;
+
+ // FIXME alignment for ELF may not be right
+ // FIXME the codegen can be much improved in some cases.
+ // We do not have to keep everything in memory.
+ if (isByVal) {
+ // ObjSize is the true size, ArgSize rounded up to multiple of registers.
+ ObjSize = (Flags & ISD::ParamFlags::ByValSize) >>
+ ISD::ParamFlags::ByValSizeOffs;
+ ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
+ // Double word align in ELF
+ if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2);
+ // Objects of size 1 and 2 are right justified, everything else is
+ // left justified. This means the memory address is adjusted forwards.
+ if (ObjSize==1 || ObjSize==2) {
+ CurArgOffset = CurArgOffset + (4 - ObjSize);
+ }
+ // The value of the object is its address.
+ int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset);
+ SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
+ ArgValues.push_back(FIN);
+ if (ObjSize==1 || ObjSize==2) {
+ if (GPR_idx != Num_GPR_Regs) {
+ unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
+ RegInfo.addLiveIn(GPR[GPR_idx], VReg);
+ SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
+ SDOperand Store = DAG.getTruncStore(Val.getValue(1), Val, FIN,
+ NULL, 0, ObjSize==1 ? MVT::i8 : MVT::i16 );
+ MemOps.push_back(Store);
+ ++GPR_idx;
+ if (isMachoABI) ArgOffset += PtrByteSize;
+ } else {
+ ArgOffset += PtrByteSize;
+ }
+ continue;
+ }
+ for (unsigned j = 0; j < ArgSize; j += PtrByteSize) {
+ // Store whatever pieces of the object are in registers
+ // to memory. ArgVal will be address of the beginning of
+ // the object.
+ if (GPR_idx != Num_GPR_Regs) {
+ unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
+ RegInfo.addLiveIn(GPR[GPR_idx], VReg);
+ int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset);
+ SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
+ SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
+ SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
+ MemOps.push_back(Store);
+ ++GPR_idx;
+ if (isMachoABI) ArgOffset += PtrByteSize;
+ } else {
+ ArgOffset += ArgSize - (ArgOffset-CurArgOffset);
+ break;
+ }
+ }
+ continue;
+ }
+
switch (ObjectVT) {
default: assert(0 && "Unhandled argument type!");
case MVT::i32:
- // Double word align in ELF
- if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2);
- if (GPR_idx != Num_GPR_Regs) {
- unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
- RegInfo.addLiveIn(GPR[GPR_idx], VReg);
- ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
- ++GPR_idx;
- } else {
- needsLoad = true;
- ArgSize = PtrByteSize;
+ if (!isPPC64) {
+ // Double word align in ELF
+ if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2);
+
+ if (GPR_idx != Num_GPR_Regs) {
+ unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
+ RegInfo.addLiveIn(GPR[GPR_idx], VReg);
+ ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
+ ++GPR_idx;
+ } else {
+ needsLoad = true;
+ ArgSize = PtrByteSize;
+ }
+ // Stack align in ELF
+ if (needsLoad && Expand && isELF32_ABI)
+ ArgOffset += ((ArgOffset/4) % 2) * PtrByteSize;
+ // All int arguments reserve stack space in Macho ABI.
+ if (isMachoABI || needsLoad) ArgOffset += PtrByteSize;
+ break;
}
- // Stack align in ELF
- if (needsLoad && Expand && isELF32_ABI)
- ArgOffset += ((ArgOffset/4) % 2) * PtrByteSize;
- // All int arguments reserve stack space in Macho ABI.
- if (isMachoABI || needsLoad) ArgOffset += PtrByteSize;
- break;
-
+ // FALLTHROUGH
case MVT::i64: // PPC64
if (GPR_idx != Num_GPR_Regs) {
unsigned VReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass);
RegInfo.addLiveIn(GPR[GPR_idx], VReg);
ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
+
+ if (ObjectVT == MVT::i32) {
+ // PPC64 passes i8, i16, and i32 values in i64 registers. Promote
+ // value to MVT::i64 and then truncate to the correct register size.
+ if (Flags & ISD::ParamFlags::SExt)
+ ArgVal = DAG.getNode(ISD::AssertSext, MVT::i64, ArgVal,
+ DAG.getValueType(ObjectVT));
+ else if (Flags & ISD::ParamFlags::ZExt)
+ ArgVal = DAG.getNode(ISD::AssertZext, MVT::i64, ArgVal,
+ DAG.getValueType(ObjectVT));
+
+ ArgVal = DAG.getNode(ISD::TRUNCATE, MVT::i32, ArgVal);
+ }
+
++GPR_idx;
} else {
needsLoad = true;
ArgValues.push_back(ArgVal);
}
-
+
// 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.
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
depth);
SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
- SmallVector<SDOperand, 8> MemOps;
-
// In ELF 32 ABI, the fixed integer arguments of a variadic function are
// stored to the VarArgsFrameIndex on the stack.
if (isELF32_ABI) {
FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
}
}
-
- if (!MemOps.empty())
- Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
}
+ if (!MemOps.empty())
+ Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
+
ArgValues.push_back(Root);
// Return the new list of results.
DAG.getTargetLoweringInfo().getPointerTy()).Val;
}
-
-static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG,
- const PPCSubtarget &Subtarget) {
+/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified
+/// by "Src" to address "Dst" of size "Size". Alignment information is
+/// specified by the specific parameter attribute. The copy will be passed as
+/// a byval function parameter.
+/// Sometimes what we are copying is the end of a larger object, the part that
+/// does not fit in registers.
+static SDOperand
+CreateCopyOfByValArgument(SDOperand Src, SDOperand Dst, SDOperand Chain,
+ unsigned Flags, SelectionDAG &DAG, unsigned Size) {
+ unsigned Align = 1 <<
+ ((Flags & ISD::ParamFlags::ByValAlign) >> ISD::ParamFlags::ByValAlignOffs);
+ SDOperand AlignNode = DAG.getConstant(Align, MVT::i32);
+ SDOperand SizeNode = DAG.getConstant(Size, MVT::i32);
+ SDOperand AlwaysInline = DAG.getConstant(0, MVT::i32);
+ return DAG.getMemcpy(Chain, Dst, Src, SizeNode, AlignNode, AlwaysInline);
+}
+
+SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG,
+ const PPCSubtarget &Subtarget) {
SDOperand Chain = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
SDOperand Callee = Op.getOperand(4);
// Add up all the space actually used.
for (unsigned i = 0; i != NumOps; ++i) {
+ unsigned Flags = cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
unsigned ArgSize =MVT::getSizeInBits(Op.getOperand(5+2*i).getValueType())/8;
- ArgSize = std::max(ArgSize, PtrByteSize);
+ if (Flags & ISD::ParamFlags::ByVal)
+ ArgSize = (Flags & ISD::ParamFlags::ByValSize) >>
+ ISD::ParamFlags::ByValSizeOffs;
+ ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
NumBytes += ArgSize;
}
// These operations are automatically eliminated by the prolog/epilog pass
Chain = DAG.getCALLSEQ_START(Chain,
DAG.getConstant(NumBytes, PtrVT));
+ SDOperand CallSeqStart = Chain;
// Set up a copy of the stack pointer for use loading and storing any
// arguments that may not fit in the registers available for argument
// On PPC64, promote integers to 64-bit values.
if (isPPC64 && Arg.getValueType() == MVT::i32) {
unsigned ExtOp = (Flags & 1) ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
-
Arg = DAG.getNode(ExtOp, MVT::i64, Arg);
}
-
+
+ // FIXME Elf untested, what are alignment rules?
+ // FIXME memcpy is used way more than necessary. Correctness first.
+ if (Flags & ISD::ParamFlags::ByVal) {
+ unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >>
+ ISD::ParamFlags::ByValSizeOffs;
+ if (isELF32_ABI && Expand) GPR_idx += (GPR_idx % 2);
+ if (Size==1 || Size==2) {
+ // Very small objects are passed right-justified.
+ // Everything else is passed left-justified.
+ MVT::ValueType VT = (Size==1) ? MVT::i8 : MVT::i16;
+ if (GPR_idx != NumGPRs) {
+ SDOperand Load = DAG.getExtLoad(ISD::EXTLOAD, PtrVT, Chain, Arg,
+ NULL, 0, VT);
+ MemOpChains.push_back(Load.getValue(1));
+ RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load));
+ if (isMachoABI)
+ ArgOffset += PtrByteSize;
+ } else {
+ SDOperand Const = DAG.getConstant(4 - Size, PtrOff.getValueType());
+ SDOperand AddPtr = DAG.getNode(ISD::ADD, PtrVT, PtrOff, Const);
+ SDOperand MemcpyCall = CreateCopyOfByValArgument(Arg, AddPtr,
+ CallSeqStart.Val->getOperand(0),
+ Flags, DAG, Size);
+ // This must go outside the CALLSEQ_START..END.
+ SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall,
+ CallSeqStart.Val->getOperand(1));
+ DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val);
+ Chain = CallSeqStart = NewCallSeqStart;
+ ArgOffset += PtrByteSize;
+ }
+ continue;
+ }
+ for (unsigned j=0; j<Size; j+=PtrByteSize) {
+ SDOperand Const = DAG.getConstant(j, PtrOff.getValueType());
+ SDOperand AddArg = DAG.getNode(ISD::ADD, PtrVT, Arg, Const);
+ if (GPR_idx != NumGPRs) {
+ SDOperand Load = DAG.getLoad(PtrVT, Chain, AddArg, NULL, 0);
+ MemOpChains.push_back(Load.getValue(1));
+ RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load));
+ if (isMachoABI)
+ ArgOffset += PtrByteSize;
+ } else {
+ SDOperand AddPtr = DAG.getNode(ISD::ADD, PtrVT, PtrOff, Const);
+ SDOperand MemcpyCall = CreateCopyOfByValArgument(AddArg, AddPtr,
+ CallSeqStart.Val->getOperand(0),
+ Flags, DAG, Size - j);
+ // This must go outside the CALLSEQ_START..END.
+ SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall,
+ CallSeqStart.Val->getOperand(1));
+ DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val);
+ Chain = CallSeqStart = NewCallSeqStart;
+ ArgOffset += ((Size - j + 3)/4)*4;
+ break;
+ }
+ }
+ continue;
+ }
+
switch (Arg.getValueType()) {
default: assert(0 && "Unexpected ValueType for argument!");
case MVT::i32:
NodeTys.push_back(MVT::i32);
break;
case MVT::i64:
- Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1);
- ResultVals[0] = Chain.getValue(0);
- NumResults = 1;
+ if (Op.Val->getValueType(1) == MVT::i64) {
+ Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1);
+ ResultVals[0] = Chain.getValue(0);
+ Chain = DAG.getCopyFromReg(Chain, PPC::X4, MVT::i64,
+ Chain.getValue(2)).getValue(1);
+ ResultVals[1] = Chain.getValue(0);
+ NumResults = 2;
+ NodeTys.push_back(MVT::i64);
+ } else {
+ Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1);
+ ResultVals[0] = Chain.getValue(0);
+ NumResults = 1;
+ }
NodeTys.push_back(MVT::i64);
break;
case MVT::f64:
return Res.getValue(Op.ResNo);
}
-static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG, TargetMachine &TM) {
+SDOperand PPCTargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG,
+ TargetMachine &TM) {
SmallVector<CCValAssign, 16> RVLocs;
unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Chain);
}
-static SDOperand LowerSTACKRESTORE(SDOperand Op, SelectionDAG &DAG,
+SDOperand PPCTargetLowering::LowerSTACKRESTORE(SDOperand Op, SelectionDAG &DAG,
const PPCSubtarget &Subtarget) {
// When we pop the dynamic allocation we need to restore the SP link.
return DAG.getStore(Chain, LoadLinkSP, StackPtr, NULL, 0);
}
-static SDOperand LowerDYNAMIC_STACKALLOC(SDOperand Op, SelectionDAG &DAG,
+SDOperand PPCTargetLowering::LowerDYNAMIC_STACKALLOC(SDOperand Op,
+ SelectionDAG &DAG,
const PPCSubtarget &Subtarget) {
MachineFunction &MF = DAG.getMachineFunction();
bool IsPPC64 = Subtarget.isPPC64();
/// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when
/// possible.
-static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
// Not FP? Not a fsel.
if (!MVT::isFloatingPoint(Op.getOperand(0).getValueType()) ||
!MVT::isFloatingPoint(Op.getOperand(2).getValueType()))
}
// FIXME: Split this code up when LegalizeDAGTypes lands.
-static SDOperand LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
assert(MVT::isFloatingPoint(Op.getOperand(0).getValueType()));
SDOperand Src = Op.getOperand(0);
if (Src.getValueType() == MVT::f32)
return DAG.getLoad(Op.getValueType(), Chain, FIPtr, NULL, 0);
}
-static SDOperand LowerFP_ROUND_INREG(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerFP_ROUND_INREG(SDOperand Op,
+ SelectionDAG &DAG) {
assert(Op.getValueType() == MVT::ppcf128);
SDNode *Node = Op.Val;
assert(Node->getOperand(0).getValueType() == MVT::ppcf128);
return DAG.getNode(ISD::BUILD_PAIR, Lo.getValueType(), FPreg, FPreg);
}
-static SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
if (Op.getOperand(0).getValueType() == MVT::i64) {
SDOperand Bits = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, Op.getOperand(0));
SDOperand FP = DAG.getNode(PPCISD::FCFID, MVT::f64, Bits);
return FP;
}
-static SDOperand LowerFLT_ROUNDS_(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerFLT_ROUNDS_(SDOperand Op, SelectionDAG &DAG) {
/*
The rounding mode is in bits 30:31 of FPSR, and has the following
settings:
ISD::TRUNCATE : ISD::ZERO_EXTEND), VT, RetVal);
}
-static SDOperand LowerSHL_PARTS(SDOperand Op, SelectionDAG &DAG) {
- assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
- Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SHL!");
+SDOperand PPCTargetLowering::LowerSHL_PARTS(SDOperand Op, SelectionDAG &DAG) {
+ MVT::ValueType VT = Op.getValueType();
+ unsigned BitWidth = MVT::getSizeInBits(VT);
+ assert(Op.getNumOperands() == 3 &&
+ VT == Op.getOperand(1).getValueType() &&
+ "Unexpected SHL!");
// Expand into a bunch of logical ops. Note that these ops
// depend on the PPC behavior for oversized shift amounts.
SDOperand Lo = Op.getOperand(0);
SDOperand Hi = Op.getOperand(1);
SDOperand Amt = Op.getOperand(2);
-
- SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
- DAG.getConstant(32, MVT::i32), Amt);
- SDOperand Tmp2 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Amt);
- SDOperand Tmp3 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Tmp1);
- SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
- SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
- DAG.getConstant(-32U, MVT::i32));
- SDOperand Tmp6 = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Tmp5);
- SDOperand OutHi = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6);
- SDOperand OutLo = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Amt);
+ MVT::ValueType AmtVT = Amt.getValueType();
+
+ SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT,
+ DAG.getConstant(BitWidth, AmtVT), Amt);
+ SDOperand Tmp2 = DAG.getNode(PPCISD::SHL, VT, Hi, Amt);
+ SDOperand Tmp3 = DAG.getNode(PPCISD::SRL, VT, Lo, Tmp1);
+ SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3);
+ SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt,
+ DAG.getConstant(-BitWidth, AmtVT));
+ SDOperand Tmp6 = DAG.getNode(PPCISD::SHL, VT, Lo, Tmp5);
+ SDOperand OutHi = DAG.getNode(ISD::OR, VT, Tmp4, Tmp6);
+ SDOperand OutLo = DAG.getNode(PPCISD::SHL, VT, Lo, Amt);
SDOperand OutOps[] = { OutLo, OutHi };
- return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(MVT::i32, MVT::i32),
+ return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT),
OutOps, 2);
}
-static SDOperand LowerSRL_PARTS(SDOperand Op, SelectionDAG &DAG) {
- assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
- Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRL!");
+SDOperand PPCTargetLowering::LowerSRL_PARTS(SDOperand Op, SelectionDAG &DAG) {
+ MVT::ValueType VT = Op.getValueType();
+ unsigned BitWidth = MVT::getSizeInBits(VT);
+ assert(Op.getNumOperands() == 3 &&
+ VT == Op.getOperand(1).getValueType() &&
+ "Unexpected SRL!");
- // Otherwise, expand into a bunch of logical ops. Note that these ops
+ // Expand into a bunch of logical ops. Note that these ops
// depend on the PPC behavior for oversized shift amounts.
SDOperand Lo = Op.getOperand(0);
SDOperand Hi = Op.getOperand(1);
SDOperand Amt = Op.getOperand(2);
-
- SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
- DAG.getConstant(32, MVT::i32), Amt);
- SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt);
- SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1);
- SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
- SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
- DAG.getConstant(-32U, MVT::i32));
- SDOperand Tmp6 = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Tmp5);
- SDOperand OutLo = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6);
- SDOperand OutHi = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Amt);
+ MVT::ValueType AmtVT = Amt.getValueType();
+
+ SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT,
+ DAG.getConstant(BitWidth, AmtVT), Amt);
+ SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, VT, Lo, Amt);
+ SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, VT, Hi, Tmp1);
+ SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3);
+ SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt,
+ DAG.getConstant(-BitWidth, AmtVT));
+ SDOperand Tmp6 = DAG.getNode(PPCISD::SRL, VT, Hi, Tmp5);
+ SDOperand OutLo = DAG.getNode(ISD::OR, VT, Tmp4, Tmp6);
+ SDOperand OutHi = DAG.getNode(PPCISD::SRL, VT, Hi, Amt);
SDOperand OutOps[] = { OutLo, OutHi };
- return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(MVT::i32, MVT::i32),
+ return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT),
OutOps, 2);
}
-static SDOperand LowerSRA_PARTS(SDOperand Op, SelectionDAG &DAG) {
- assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
- Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRA!");
+SDOperand PPCTargetLowering::LowerSRA_PARTS(SDOperand Op, SelectionDAG &DAG) {
+ MVT::ValueType VT = Op.getValueType();
+ unsigned BitWidth = MVT::getSizeInBits(VT);
+ assert(Op.getNumOperands() == 3 &&
+ VT == Op.getOperand(1).getValueType() &&
+ "Unexpected SRA!");
- // Otherwise, expand into a bunch of logical ops, followed by a select_cc.
+ // Expand into a bunch of logical ops, followed by a select_cc.
SDOperand Lo = Op.getOperand(0);
SDOperand Hi = Op.getOperand(1);
SDOperand Amt = Op.getOperand(2);
-
- SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
- DAG.getConstant(32, MVT::i32), Amt);
- SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt);
- SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1);
- SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
- SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
- DAG.getConstant(-32U, MVT::i32));
- SDOperand Tmp6 = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Tmp5);
- SDOperand OutHi = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Amt);
- SDOperand OutLo = DAG.getSelectCC(Tmp5, DAG.getConstant(0, MVT::i32),
+ MVT::ValueType AmtVT = Amt.getValueType();
+
+ SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT,
+ DAG.getConstant(BitWidth, AmtVT), Amt);
+ SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, VT, Lo, Amt);
+ SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, VT, Hi, Tmp1);
+ SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3);
+ SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt,
+ DAG.getConstant(-BitWidth, AmtVT));
+ SDOperand Tmp6 = DAG.getNode(PPCISD::SRA, VT, Hi, Tmp5);
+ SDOperand OutHi = DAG.getNode(PPCISD::SRA, VT, Hi, Amt);
+ SDOperand OutLo = DAG.getSelectCC(Tmp5, DAG.getConstant(0, AmtVT),
Tmp4, Tmp6, ISD::SETLE);
SDOperand OutOps[] = { OutLo, OutHi };
- return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(MVT::i32, MVT::i32),
+ return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT),
OutOps, 2);
}
// selects to a single instruction, return Op. Otherwise, if we can codegen
// this case more efficiently than a constant pool load, lower it to the
// sequence of ops that should be used.
-static SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerBUILD_VECTOR(SDOperand Op,
+ SelectionDAG &DAG) {
// If this is a vector of constants or undefs, get the bits. A bit in
// UndefBits is set if the corresponding element of the vector is an
// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
/// is a shuffle we can handle in a single instruction, return it. Otherwise,
/// return the code it can be lowered into. Worst case, it can always be
/// lowered into a vperm.
-static SDOperand LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerVECTOR_SHUFFLE(SDOperand Op,
+ SelectionDAG &DAG) {
SDOperand V1 = Op.getOperand(0);
SDOperand V2 = Op.getOperand(1);
SDOperand PermMask = Op.getOperand(2);
/// LowerINTRINSIC_WO_CHAIN - If this is an intrinsic that we want to custom
/// lower, do it, otherwise return null.
-static SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerINTRINSIC_WO_CHAIN(SDOperand Op,
+ SelectionDAG &DAG) {
// If this is a lowered altivec predicate compare, CompareOpc is set to the
// opcode number of the comparison.
int CompareOpc;
return Flags;
}
-static SDOperand LowerSCALAR_TO_VECTOR(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerSCALAR_TO_VECTOR(SDOperand Op,
+ SelectionDAG &DAG) {
// Create a stack slot that is 16-byte aligned.
MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
int FrameIdx = FrameInfo->CreateStackObject(16, 16);
return DAG.getLoad(Op.getValueType(), Store, FIdx, NULL, 0);
}
-static SDOperand LowerMUL(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerMUL(SDOperand Op, SelectionDAG &DAG) {
if (Op.getValueType() == MVT::v4i32) {
SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1);