#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
addRegisterClass(MVT::f64, PPC::F8RCRegisterClass);
// PowerPC has an i16 but no i8 (or i1) SEXTLOAD
- setLoadXAction(ISD::SEXTLOAD, MVT::i1, Expand);
+ setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote);
setLoadXAction(ISD::SEXTLOAD, MVT::i8, Expand);
-
+
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
// PowerPC has pre-inc load and store's.
setIndexedStoreAction(ISD::PRE_INC, MVT::i32, Legal);
setIndexedStoreAction(ISD::PRE_INC, MVT::i64, Legal);
- setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
- setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
-
// Shortening conversions involving ppcf128 get expanded (2 regs -> 1 reg)
setConvertAction(MVT::ppcf128, MVT::f64, Expand);
setConvertAction(MVT::ppcf128, MVT::f32, Expand);
setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
setOperationAction(ISD::MEMSET, MVT::Other, Expand);
setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
-
+ setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+
// PowerPC has no SREM/UREM instructions
setOperationAction(ISD::SREM, MVT::i32, Expand);
setOperationAction(ISD::UREM, MVT::i32, Expand);
setOperationAction(ISD::FCOS , MVT::f32, Expand);
setOperationAction(ISD::FREM , MVT::f32, Expand);
setOperationAction(ISD::FPOW , MVT::f32, Expand);
+
+ setOperationAction(ISD::FLT_ROUNDS_, MVT::i32, Custom);
// If we're enabling GP optimizations, use hardware square root
if (!TM.getSubtarget<PPCSubtarget>().hasFSQRT()) {
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;
case PPCISD::LBRX: return "PPCISD::LBRX";
case PPCISD::STBRX: return "PPCISD::STBRX";
case PPCISD::COND_BRANCH: return "PPCISD::COND_BRANCH";
+ case PPCISD::MFFS: return "PPCISD::MFFS";
+ case PPCISD::MTFSB0: return "PPCISD::MTFSB0";
+ case PPCISD::MTFSB1: return "PPCISD::MTFSB1";
+ case PPCISD::FADDRTZ: return "PPCISD::FADDRTZ";
+ case PPCISD::MTFSF: return "PPCISD::MTFSF";
}
}
// If this is an or of disjoint bitfields, we can codegen this as an add
// (for better address arithmetic) if the LHS and RHS of the OR are provably
// disjoint.
- uint64_t LHSKnownZero, LHSKnownOne;
- uint64_t RHSKnownZero, RHSKnownOne;
- DAG.ComputeMaskedBits(N.getOperand(0), ~0U, LHSKnownZero, LHSKnownOne);
-
- if (LHSKnownZero) {
- DAG.ComputeMaskedBits(N.getOperand(1), ~0U, RHSKnownZero, RHSKnownOne);
+ APInt LHSKnownZero, LHSKnownOne;
+ APInt RHSKnownZero, RHSKnownOne;
+ DAG.ComputeMaskedBits(N.getOperand(0),
+ APInt::getAllOnesValue(N.getOperand(0)
+ .getValueSizeInBits()),
+ LHSKnownZero, LHSKnownOne);
+
+ if (LHSKnownZero.getBoolValue()) {
+ DAG.ComputeMaskedBits(N.getOperand(1),
+ 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;
// If this is an or of disjoint bitfields, we can codegen this as an add
// (for better address arithmetic) if the LHS and RHS of the OR are
// provably disjoint.
- uint64_t LHSKnownZero, LHSKnownOne;
- DAG.ComputeMaskedBits(N.getOperand(0), ~0U, LHSKnownZero, LHSKnownOne);
- if ((LHSKnownZero|~(unsigned)imm) == ~0U) {
+ APInt LHSKnownZero, LHSKnownOne;
+ DAG.ComputeMaskedBits(N.getOperand(0),
+ APInt::getAllOnesValue(32),
+ LHSKnownZero, LHSKnownOne);
+ if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) {
// If all of the bits are known zero on the LHS or RHS, the add won't
// carry.
Base = N.getOperand(0);
// If this is an or of disjoint bitfields, we can codegen this as an add
// (for better address arithmetic) if the LHS and RHS of the OR are
// provably disjoint.
- uint64_t LHSKnownZero, LHSKnownOne;
- DAG.ComputeMaskedBits(N.getOperand(0), ~0U, LHSKnownZero, LHSKnownOne);
- if ((LHSKnownZero|~(unsigned)imm) == ~0U) {
+ APInt LHSKnownZero, LHSKnownOne;
+ DAG.ComputeMaskedBits(N.getOperand(0),
+ APInt::getAllOnesValue(32),
+ LHSKnownZero, LHSKnownOne);
+ if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) {
// If all of the bits are known zero on the LHS or RHS, the add won't
// carry.
Base = N.getOperand(0);
MVT::ValueType VT;
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
Ptr = LD->getBasePtr();
- VT = LD->getLoadedVT();
+ VT = LD->getMemoryVT();
} else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
ST = ST;
Ptr = ST->getBasePtr();
- VT = ST->getStoredVT();
+ VT = ST->getMemoryVT();
} else
return false;
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
// PPC64 doesn't have lwau, but it does have lwaux. Reject preinc load of
// sext i32 to i64 when addr mode is r+i.
- if (LD->getValueType(0) == MVT::i64 && LD->getLoadedVT() == MVT::i32 &&
+ if (LD->getValueType(0) == MVT::i64 && LD->getMemoryVT() == MVT::i32 &&
LD->getExtensionType() == ISD::SEXTLOAD &&
isa<ConstantSDNode>(Offset))
return false;
// 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();
SDOperand GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset());
+ // If it's a debug information descriptor, don't mess with it.
+ if (DAG.isVerifiedDebugInfoDesc(Op))
+ return GA;
SDOperand Zero = DAG.getConstant(0, PtrVT);
const TargetMachine &TM = DAG.getTarget();
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,
// memory location argument.
MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
- SrcValueSDNode *SV = cast<SrcValueSDNode>(Op.getOperand(2));
- return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV->getValue(),
- SV->getOffset());
+ const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
+ return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV, 0);
}
// For ELF 32 ABI we follow the layout of the va_list struct.
MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
- SDOperand StackOffset = DAG.getFrameIndex(VarArgsStackOffset, PtrVT);
+ SDOperand StackOffsetFI = DAG.getFrameIndex(VarArgsStackOffset, PtrVT);
SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
- SDOperand ConstFrameOffset = DAG.getConstant(MVT::getSizeInBits(PtrVT)/8,
- PtrVT);
- SDOperand ConstStackOffset = DAG.getConstant(MVT::getSizeInBits(PtrVT)/8 - 1,
- PtrVT);
- SDOperand ConstFPROffset = DAG.getConstant(1, PtrVT);
+ uint64_t FrameOffset = MVT::getSizeInBits(PtrVT)/8;
+ SDOperand ConstFrameOffset = DAG.getConstant(FrameOffset, PtrVT);
+
+ uint64_t StackOffset = MVT::getSizeInBits(PtrVT)/8 - 1;
+ SDOperand ConstStackOffset = DAG.getConstant(StackOffset, PtrVT);
+
+ uint64_t FPROffset = 1;
+ SDOperand ConstFPROffset = DAG.getConstant(FPROffset, PtrVT);
- SrcValueSDNode *SV = cast<SrcValueSDNode>(Op.getOperand(2));
+ const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
// Store first byte : number of int regs
SDOperand firstStore = DAG.getStore(Op.getOperand(0), ArgGPR,
- Op.getOperand(1), SV->getValue(),
- SV->getOffset());
+ Op.getOperand(1), SV, 0);
+ uint64_t nextOffset = FPROffset;
SDOperand nextPtr = DAG.getNode(ISD::ADD, PtrVT, Op.getOperand(1),
ConstFPROffset);
// Store second byte : number of float regs
- SDOperand secondStore = DAG.getStore(firstStore, ArgFPR, nextPtr,
- SV->getValue(), SV->getOffset());
+ SDOperand secondStore =
+ DAG.getStore(firstStore, ArgFPR, nextPtr, SV, nextOffset);
+ nextOffset += StackOffset;
nextPtr = DAG.getNode(ISD::ADD, PtrVT, nextPtr, ConstStackOffset);
// Store second word : arguments given on stack
- SDOperand thirdStore = DAG.getStore(secondStore, StackOffset, nextPtr,
- SV->getValue(), SV->getOffset());
+ SDOperand thirdStore =
+ DAG.getStore(secondStore, StackOffsetFI, nextPtr, SV, nextOffset);
+ nextOffset += FrameOffset;
nextPtr = DAG.getNode(ISD::ADD, PtrVT, nextPtr, ConstFrameOffset);
// Store third word : arguments given in registers
- return DAG.getStore(thirdStore, FR, nextPtr, SV->getValue(),
- SV->getOffset());
+ return DAG.getStore(thirdStore, FR, nextPtr, SV, nextOffset);
}
return FPR;
}
-static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
+SDOperand PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op,
+ SelectionDAG &DAG,
int &VarArgsFrameIndex,
int &VarArgsStackOffset,
unsigned &VarArgsNumGPR,
// 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) {
+ // Double word align in ELF
+ if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2);
+ // 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;
+ // The value of the object is its address.
+ int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset);
+ SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
+ ArgValues.push_back(FIN);
+ 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:
}
// 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
+ // that we ran out of physical registers of the appropriate type.
if (needsLoad) {
- // If the argument is actually used, emit a load from the right stack
- // slot.
- if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
- int FI = MFI->CreateFixedObject(ObjSize,
- CurArgOffset + (ArgSize - ObjSize));
- SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
- ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
- } else {
- // Don't emit a dead load.
- ArgVal = DAG.getNode(ISD::UNDEF, ObjectVT);
- }
+ int FI = MFI->CreateFixedObject(ObjSize,
+ CurArgOffset + (ArgSize - ObjSize));
+ SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
+ ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
}
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;
+ if (Flags & ISD::ParamFlags::ByVal)
+ ArgSize = (Flags & ISD::ParamFlags::ByValSize) >>
+ ISD::ParamFlags::ByValSizeOffs;
ArgSize = std::max(ArgSize, 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
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:
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);
Op.getOperand(0));
// STD the extended value into the stack slot.
+ MemOperand MO(PseudoSourceValue::getFixedStack(),
+ MemOperand::MOStore, FrameIdx, 8, 8);
SDOperand Store = DAG.getNode(PPCISD::STD_32, MVT::Other,
DAG.getEntryNode(), Ext64, FIdx,
- DAG.getSrcValue(NULL));
+ DAG.getMemOperand(MO));
// Load the value as a double.
SDOperand Ld = DAG.getLoad(MVT::f64, Store, FIdx, NULL, 0);
return FP;
}
-static SDOperand LowerSHL_PARTS(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:
+ 00 Round to nearest
+ 01 Round to 0
+ 10 Round to +inf
+ 11 Round to -inf
+
+ FLT_ROUNDS, on the other hand, expects the following:
+ -1 Undefined
+ 0 Round to 0
+ 1 Round to nearest
+ 2 Round to +inf
+ 3 Round to -inf
+
+ To perform the conversion, we do:
+ ((FPSCR & 0x3) ^ ((~FPSCR & 0x3) >> 1))
+ */
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ MVT::ValueType VT = Op.getValueType();
+ MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
+ std::vector<MVT::ValueType> NodeTys;
+ SDOperand MFFSreg, InFlag;
+
+ // Save FP Control Word to register
+ NodeTys.push_back(MVT::f64); // return register
+ NodeTys.push_back(MVT::Flag); // unused in this context
+ SDOperand Chain = DAG.getNode(PPCISD::MFFS, NodeTys, &InFlag, 0);
+
+ // Save FP register to stack slot
+ int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
+ SDOperand StackSlot = DAG.getFrameIndex(SSFI, PtrVT);
+ SDOperand Store = DAG.getStore(DAG.getEntryNode(), Chain,
+ StackSlot, NULL, 0);
+
+ // Load FP Control Word from low 32 bits of stack slot.
+ SDOperand Four = DAG.getConstant(4, PtrVT);
+ SDOperand Addr = DAG.getNode(ISD::ADD, PtrVT, StackSlot, Four);
+ SDOperand CWD = DAG.getLoad(MVT::i32, Store, Addr, NULL, 0);
+
+ // Transform as necessary
+ SDOperand CWD1 =
+ DAG.getNode(ISD::AND, MVT::i32,
+ CWD, DAG.getConstant(3, MVT::i32));
+ SDOperand CWD2 =
+ DAG.getNode(ISD::SRL, MVT::i32,
+ DAG.getNode(ISD::AND, MVT::i32,
+ DAG.getNode(ISD::XOR, MVT::i32,
+ CWD, DAG.getConstant(3, MVT::i32)),
+ DAG.getConstant(3, MVT::i32)),
+ DAG.getConstant(1, MVT::i8));
+
+ SDOperand RetVal =
+ DAG.getNode(ISD::XOR, MVT::i32, CWD1, CWD2);
+
+ return DAG.getNode((MVT::getSizeInBits(VT) < 16 ?
+ ISD::TRUNCATE : ISD::ZERO_EXTEND), VT, RetVal);
+}
+
+SDOperand PPCTargetLowering::LowerSHL_PARTS(SDOperand Op, SelectionDAG &DAG) {
assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SHL!");
OutOps, 2);
}
-static SDOperand LowerSRL_PARTS(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerSRL_PARTS(SDOperand Op, SelectionDAG &DAG) {
assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRL!");
OutOps, 2);
}
-static SDOperand LowerSRA_PARTS(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerSRA_PARTS(SDOperand Op, SelectionDAG &DAG) {
assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRA!");
// 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);
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
case ISD::FP_ROUND_INREG: return LowerFP_ROUND_INREG(Op, DAG);
+ case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG);
// Lower 64-bit shifts.
case ISD::SHL_PARTS: return LowerSHL_PARTS(Op, DAG);
//===----------------------------------------------------------------------===//
MachineBasicBlock *
-PPCTargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
- MachineBasicBlock *BB) {
+PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
+ MachineBasicBlock *BB) {
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
assert((MI->getOpcode() == PPC::SELECT_CC_I4 ||
MI->getOpcode() == PPC::SELECT_CC_I8 ||
case ISD::STORE:
// Turn STORE (FP_TO_SINT F) -> STFIWX(FCTIWZ(F)).
if (TM.getSubtarget<PPCSubtarget>().hasSTFIWX() &&
+ !cast<StoreSDNode>(N)->isTruncatingStore() &&
N->getOperand(1).getOpcode() == ISD::FP_TO_SINT &&
N->getOperand(1).getValueType() == MVT::i32 &&
N->getOperand(1).getOperand(0).getValueType() != MVT::ppcf128) {
std::vector<MVT::ValueType> VTs;
VTs.push_back(MVT::i32);
VTs.push_back(MVT::Other);
- SDOperand SV = DAG.getSrcValue(LD->getSrcValue(), LD->getSrcValueOffset());
+ SDOperand MO = DAG.getMemOperand(LD->getMemOperand());
SDOperand Ops[] = {
LD->getChain(), // Chain
LD->getBasePtr(), // Ptr
- SV, // SrcValue
+ MO, // MemOperand
DAG.getValueType(N->getValueType(0)) // VT
};
SDOperand BSLoad = DAG.getNode(PPCISD::LBRX, VTs, Ops, 4);
//===----------------------------------------------------------------------===//
void PPCTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
- uint64_t Mask,
- uint64_t &KnownZero,
- uint64_t &KnownOne,
+ const APInt &Mask,
+ APInt &KnownZero,
+ APInt &KnownOne,
const SelectionDAG &DAG,
unsigned Depth) const {
- KnownZero = 0;
- KnownOne = 0;
+ KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
switch (Op.getOpcode()) {
default: break;
case PPCISD::LBRX: {