diff options
Diffstat (limited to 'lib/Target/Sparc/SparcISelLowering.cpp')
-rw-r--r-- | lib/Target/Sparc/SparcISelLowering.cpp | 935 |
1 files changed, 540 insertions, 395 deletions
diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 5e70ffe2223c..8738bc82683d 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -18,6 +18,7 @@ #include "SparcRegisterInfo.h" #include "SparcTargetMachine.h" #include "SparcTargetObjectFile.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -31,7 +32,6 @@ #include "llvm/Support/ErrorHandling.h" using namespace llvm; - //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -184,29 +184,30 @@ static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, // callee's register window. This function translates registers to the // corresponding caller window %o register. static unsigned toCallerWindow(unsigned Reg) { - assert(SP::I0 + 7 == SP::I7 && SP::O0 + 7 == SP::O7 && "Unexpected enum"); + static_assert(SP::I0 + 7 == SP::I7 && SP::O0 + 7 == SP::O7, + "Unexpected enum"); if (Reg >= SP::I0 && Reg <= SP::I7) return Reg - SP::I0 + SP::O0; return Reg; } SDValue -SparcTargetLowering::LowerReturn(SDValue Chain, - CallingConv::ID CallConv, bool IsVarArg, +SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, - SDLoc DL, SelectionDAG &DAG) const { + const SDLoc &DL, SelectionDAG &DAG) const { if (Subtarget->is64Bit()) return LowerReturn_64(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG); return LowerReturn_32(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG); } SDValue -SparcTargetLowering::LowerReturn_32(SDValue Chain, - CallingConv::ID CallConv, bool IsVarArg, +SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, - SDLoc DL, SelectionDAG &DAG) const { + const SDLoc &DL, SelectionDAG &DAG) const { MachineFunction &MF = DAG.getMachineFunction(); // CCValAssign - represent the assignment of the return value to locations. @@ -287,11 +288,11 @@ SparcTargetLowering::LowerReturn_32(SDValue Chain, // Lower return values for the 64-bit ABI. // Return values are passed the exactly the same way as function arguments. SDValue -SparcTargetLowering::LowerReturn_64(SDValue Chain, - CallingConv::ID CallConv, bool IsVarArg, +SparcTargetLowering::LowerReturn_64(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, - SDLoc DL, SelectionDAG &DAG) const { + const SDLoc &DL, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of the return value to locations. SmallVector<CCValAssign, 16> RVLocs; @@ -363,14 +364,10 @@ SparcTargetLowering::LowerReturn_64(SDValue Chain, return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, RetOps); } -SDValue SparcTargetLowering:: -LowerFormalArguments(SDValue Chain, - CallingConv::ID CallConv, - bool IsVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - SDLoc DL, - SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const { +SDValue SparcTargetLowering::LowerFormalArguments( + SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { if (Subtarget->is64Bit()) return LowerFormalArguments_64(Chain, CallConv, IsVarArg, Ins, DL, DAG, InVals); @@ -381,14 +378,10 @@ LowerFormalArguments(SDValue Chain, /// LowerFormalArguments32 - V8 uses a very simple ABI, where all values are /// passed in either one or two GPRs, including FP values. TODO: we should /// pass FP values in FP registers for fastcc functions. -SDValue SparcTargetLowering:: -LowerFormalArguments_32(SDValue Chain, - CallingConv::ID CallConv, - bool isVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - SDLoc dl, - SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const { +SDValue SparcTargetLowering::LowerFormalArguments_32( + SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, + SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); @@ -412,9 +405,8 @@ LowerFormalArguments_32(SDValue Chain, // Get SRet from [%fp+64]. int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, 64, true); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - SDValue Arg = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, - MachinePointerInfo(), - false, false, false, 0); + SDValue Arg = + DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); InVals.push_back(Arg); continue; } @@ -435,9 +427,7 @@ LowerFormalArguments_32(SDValue Chain, int FrameIdx = MF.getFrameInfo()-> CreateFixedObject(4, StackOffset+NextVA.getLocMemOffset(),true); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, - MachinePointerInfo(), - false, false, false, 0); + LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); } else { unsigned loReg = MF.addLiveIn(NextVA.getLocReg(), &SP::IntRegsRegClass); @@ -473,16 +463,15 @@ LowerFormalArguments_32(SDValue Chain, auto PtrVT = getPointerTy(DAG.getDataLayout()); if (VA.needsCustom()) { - assert(VA.getValVT() == MVT::f64 || MVT::v2i32); + assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32); // If it is double-word aligned, just load. if (Offset % 8 == 0) { int FI = MF.getFrameInfo()->CreateFixedObject(8, Offset, true); SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); - SDValue Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, - MachinePointerInfo(), - false,false, false, 0); + SDValue Load = + DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); InVals.push_back(Load); continue; } @@ -491,17 +480,15 @@ LowerFormalArguments_32(SDValue Chain, Offset, true); SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); - SDValue HiVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, - MachinePointerInfo(), - false, false, false, 0); + SDValue HiVal = + DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); int FI2 = MF.getFrameInfo()->CreateFixedObject(4, Offset+4, true); SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT); - SDValue LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, - MachinePointerInfo(), - false, false, false, 0); + SDValue LoVal = + DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo()); if (IsLittleEndian) std::swap(LoVal, HiVal); @@ -519,9 +506,7 @@ LowerFormalArguments_32(SDValue Chain, SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); SDValue Load ; if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { - Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, - MachinePointerInfo(), - false, false, false, 0); + Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); } else if (VA.getValVT() == MVT::f128) { report_fatal_error("SPARCv8 does not handle f128 in calls; " "pass indirectly"); @@ -573,9 +558,8 @@ LowerFormalArguments_32(SDValue Chain, true); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, - MachinePointerInfo(), - false, false, 0)); + OutChains.push_back( + DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, MachinePointerInfo())); ArgOffset += 4; } @@ -589,14 +573,10 @@ LowerFormalArguments_32(SDValue Chain, } // Lower formal arguments for the 64 bit ABI. -SDValue SparcTargetLowering:: -LowerFormalArguments_64(SDValue Chain, - CallingConv::ID CallConv, - bool IsVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - SDLoc DL, - SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const { +SDValue SparcTargetLowering::LowerFormalArguments_64( + SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); // Analyze arguments according to CC_Sparc64. @@ -659,10 +639,10 @@ LowerFormalArguments_64(SDValue Chain, if (VA.isExtInLoc()) Offset += 8 - ValSize; int FI = MF.getFrameInfo()->CreateFixedObject(ValSize, Offset, true); - InVals.push_back(DAG.getLoad( - VA.getValVT(), DL, Chain, - DAG.getFrameIndex(FI, getPointerTy(MF.getDataLayout())), - MachinePointerInfo::getFixedStack(MF, FI), false, false, false, 0)); + InVals.push_back( + DAG.getLoad(VA.getValVT(), DL, Chain, + DAG.getFrameIndex(FI, getPointerTy(MF.getDataLayout())), + MachinePointerInfo::getFixedStack(MF, FI))); } if (!IsVarArg) @@ -690,9 +670,9 @@ LowerFormalArguments_64(SDValue Chain, SDValue VArg = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64); int FI = MF.getFrameInfo()->CreateFixedObject(8, ArgOffset + ArgArea, true); auto PtrVT = getPointerTy(MF.getDataLayout()); - OutChains.push_back(DAG.getStore( - Chain, DL, VArg, DAG.getFrameIndex(FI, PtrVT), - MachinePointerInfo::getFixedStack(MF, FI), false, false, 0)); + OutChains.push_back( + DAG.getStore(Chain, DL, VArg, DAG.getFrameIndex(FI, PtrVT), + MachinePointerInfo::getFixedStack(MF, FI))); } if (!OutChains.empty()) @@ -773,16 +753,22 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, unsigned Size = Flags.getByValSize(); unsigned Align = Flags.getByValAlign(); - int FI = MFI->CreateStackObject(Size, Align, false); - SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - SDValue SizeNode = DAG.getConstant(Size, dl, MVT::i32); - - Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align, - false, // isVolatile, - (Size <= 32), // AlwaysInline if size <= 32, - false, // isTailCall - MachinePointerInfo(), MachinePointerInfo()); - ByValArgs.push_back(FIPtr); + if (Size > 0U) { + int FI = MFI->CreateStackObject(Size, Align, false); + SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); + SDValue SizeNode = DAG.getConstant(Size, dl, MVT::i32); + + Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align, + false, // isVolatile, + (Size <= 32), // AlwaysInline if size <= 32, + false, // isTailCall + MachinePointerInfo(), MachinePointerInfo()); + ByValArgs.push_back(FIPtr); + } + else { + SDValue nullVal; + ByValArgs.push_back(nullVal); + } } Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, dl, true), @@ -803,8 +789,12 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; // Use local copy if it is a byval arg. - if (Flags.isByVal()) + if (Flags.isByVal()) { Arg = ByValArgs[byvalArgIdx++]; + if (!Arg) { + continue; + } + } // Promote the value if needed. switch (VA.getLocInfo()) { @@ -830,9 +820,8 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); SDValue PtrOff = DAG.getIntPtrConstant(64, dl); PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, - MachinePointerInfo(), - false, false, 0)); + MemOpChains.push_back( + DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo())); hasStructRetAttr = true; continue; } @@ -847,9 +836,8 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl); PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, - MachinePointerInfo(), - false, false, 0)); + MemOpChains.push_back( + DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo())); continue; } } @@ -884,9 +872,8 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl); PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back(DAG.getStore(Chain, dl, Part1, PtrOff, - MachinePointerInfo(), - false, false, 0)); + MemOpChains.push_back( + DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo())); } } else { unsigned Offset = VA.getLocMemOffset() + StackOffset; @@ -894,15 +881,13 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl); PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back(DAG.getStore(Chain, dl, Part0, PtrOff, - MachinePointerInfo(), - false, false, 0)); + MemOpChains.push_back( + DAG.getStore(Chain, dl, Part0, PtrOff, MachinePointerInfo())); // Store the second part. PtrOff = DAG.getIntPtrConstant(Offset + 4, dl); PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back(DAG.getStore(Chain, dl, Part1, PtrOff, - MachinePointerInfo(), - false, false, 0)); + MemOpChains.push_back( + DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo())); } continue; } @@ -926,9 +911,8 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() + StackOffset, dl); PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, - MachinePointerInfo(), - false, false, 0)); + MemOpChains.push_back( + DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo())); } @@ -953,8 +937,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, // If the callee is a GlobalAddress node (quite common, every direct call is) // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. // Likewise ExternalSymbol -> TargetExternalSymbol. - unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_) - ? SparcMCExpr::VK_Sparc_WPLT30 : 0); + unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30 : 0; if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF); else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) @@ -999,15 +982,55 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, // Copy all of the result registers out of their specified physreg. for (unsigned i = 0; i != RVLocs.size(); ++i) { - Chain = DAG.getCopyFromReg(Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), - RVLocs[i].getValVT(), InFlag).getValue(1); - InFlag = Chain.getValue(2); - InVals.push_back(Chain.getValue(0)); + if (RVLocs[i].getLocVT() == MVT::v2i32) { + SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2i32); + SDValue Lo = DAG.getCopyFromReg( + Chain, dl, toCallerWindow(RVLocs[i++].getLocReg()), MVT::i32, InFlag); + Chain = Lo.getValue(1); + InFlag = Lo.getValue(2); + Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Lo, + DAG.getConstant(0, dl, MVT::i32)); + SDValue Hi = DAG.getCopyFromReg( + Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), MVT::i32, InFlag); + Chain = Hi.getValue(1); + InFlag = Hi.getValue(2); + Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Hi, + DAG.getConstant(1, dl, MVT::i32)); + InVals.push_back(Vec); + } else { + Chain = + DAG.getCopyFromReg(Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), + RVLocs[i].getValVT(), InFlag) + .getValue(1); + InFlag = Chain.getValue(2); + InVals.push_back(Chain.getValue(0)); + } } return Chain; } +// FIXME? Maybe this could be a TableGen attribute on some registers and +// this table could be generated automatically from RegInfo. +unsigned SparcTargetLowering::getRegisterByName(const char* RegName, EVT VT, + SelectionDAG &DAG) const { + unsigned Reg = StringSwitch<unsigned>(RegName) + .Case("i0", SP::I0).Case("i1", SP::I1).Case("i2", SP::I2).Case("i3", SP::I3) + .Case("i4", SP::I4).Case("i5", SP::I5).Case("i6", SP::I6).Case("i7", SP::I7) + .Case("o0", SP::O0).Case("o1", SP::O1).Case("o2", SP::O2).Case("o3", SP::O3) + .Case("o4", SP::O4).Case("o5", SP::O5).Case("o6", SP::O6).Case("o7", SP::O7) + .Case("l0", SP::L0).Case("l1", SP::L1).Case("l2", SP::L2).Case("l3", SP::L3) + .Case("l4", SP::L4).Case("l5", SP::L5).Case("l6", SP::L6).Case("l7", SP::L7) + .Case("g0", SP::G0).Case("g1", SP::G1).Case("g2", SP::G2).Case("g3", SP::G3) + .Case("g4", SP::G4).Case("g5", SP::G5).Case("g6", SP::G6).Case("g7", SP::G7) + .Default(0); + + if (Reg) + return Reg; + + report_fatal_error("Invalid register name global variable"); +} + // This functions returns true if CalleeName is a ABI function that returns // a long double (fp128). static bool isFP128ABICall(const char *CalleeName) @@ -1131,7 +1154,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, unsigned ArgsSize = std::max(6*8u, CCInfo.getNextStackOffset()); // Keep stack frames 16-byte aligned. - ArgsSize = RoundUpToAlignment(ArgsSize, 16); + ArgsSize = alignTo(ArgsSize, 16); // Varargs calls require special treatment. if (CLI.IsVarArg) @@ -1194,16 +1217,13 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, LoPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, LoPtrOff); // Store to %sp+BIAS+128+Offset - SDValue Store = DAG.getStore(Chain, DL, Arg, HiPtrOff, - MachinePointerInfo(), - false, false, 0); + SDValue Store = + DAG.getStore(Chain, DL, Arg, HiPtrOff, MachinePointerInfo()); // Load into Reg and Reg+1 - SDValue Hi64 = DAG.getLoad(MVT::i64, DL, Store, HiPtrOff, - MachinePointerInfo(), - false, false, false, 0); - SDValue Lo64 = DAG.getLoad(MVT::i64, DL, Store, LoPtrOff, - MachinePointerInfo(), - false, false, false, 0); + SDValue Hi64 = + DAG.getLoad(MVT::i64, DL, Store, HiPtrOff, MachinePointerInfo()); + SDValue Lo64 = + DAG.getLoad(MVT::i64, DL, Store, LoPtrOff, MachinePointerInfo()); RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()), Hi64)); RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1), @@ -1242,9 +1262,8 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, Subtarget->getStackPointerBias() + 128, DL); PtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff); - MemOpChains.push_back(DAG.getStore(Chain, DL, Arg, PtrOff, - MachinePointerInfo(), - false, false, 0)); + MemOpChains.push_back( + DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo())); } // Emit all stores, make sure they occur before the call. @@ -1267,8 +1286,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, // Likewise ExternalSymbol -> TargetExternalSymbol. SDValue Callee = CLI.Callee; bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); - unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_) - ? SparcMCExpr::VK_Sparc_WPLT30 : 0); + unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30 : 0; if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, TF); else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) @@ -1375,6 +1393,14 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, // TargetLowering Implementation //===----------------------------------------------------------------------===// +TargetLowering::AtomicExpansionKind SparcTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { + if (AI->getOperation() == AtomicRMWInst::Xchg && + AI->getType()->getPrimitiveSizeInBits() == 32) + return AtomicExpansionKind::None; // Uses xchg instruction + + return AtomicExpansionKind::CmpXChg; +} + /// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC /// condition. static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { @@ -1421,7 +1447,7 @@ static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { } } -SparcTargetLowering::SparcTargetLowering(TargetMachine &TM, +SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM, const SparcSubtarget &STI) : TargetLowering(TM), Subtarget(&STI) { MVT PtrVT = MVT::getIntegerVT(8 * TM.getPointerSize()); @@ -1436,9 +1462,11 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM, // Set up the register classes. addRegisterClass(MVT::i32, &SP::IntRegsRegClass); - addRegisterClass(MVT::f32, &SP::FPRegsRegClass); - addRegisterClass(MVT::f64, &SP::DFPRegsRegClass); - addRegisterClass(MVT::f128, &SP::QFPRegsRegClass); + if (!Subtarget->useSoftFloat()) { + addRegisterClass(MVT::f32, &SP::FPRegsRegClass); + addRegisterClass(MVT::f64, &SP::DFPRegsRegClass); + addRegisterClass(MVT::f128, &SP::QFPRegsRegClass); + } if (Subtarget->is64Bit()) { addRegisterClass(MVT::i64, &SP::I64RegsRegClass); } else { @@ -1559,6 +1587,9 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM, setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); setOperationAction(ISD::SELECT_CC, MVT::f128, Custom); + setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom); + setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom); + if (Subtarget->is64Bit()) { setOperationAction(ISD::ADDC, MVT::i64, Custom); setOperationAction(ISD::ADDE, MVT::i64, Custom); @@ -1574,9 +1605,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM, setOperationAction(ISD::CTPOP, MVT::i64, Subtarget->usePopc() ? Legal : Expand); setOperationAction(ISD::CTTZ , MVT::i64, Expand); - setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand); setOperationAction(ISD::CTLZ , MVT::i64, Expand); - setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand); setOperationAction(ISD::BSWAP, MVT::i64, Expand); setOperationAction(ISD::ROTL , MVT::i64, Expand); setOperationAction(ISD::ROTR , MVT::i64, Expand); @@ -1584,15 +1613,17 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM, } // ATOMICs. - // FIXME: We insert fences for each atomics and generate sub-optimal code - // for PSO/TSO. Also, implement other atomicrmw operations. + // Atomics are supported on SparcV9. 32-bit atomics are also + // supported by some Leon SparcV8 variants. Otherwise, atomics + // are unsupported. + if (Subtarget->isV9() || Subtarget->hasLeonCasa()) + setMaxAtomicSizeInBitsSupported(64); + else + setMaxAtomicSizeInBitsSupported(0); - setInsertFencesForAtomic(true); + setMinCmpXchgSizeInBits(32); setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal); - setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, - (Subtarget->isV9() ? Legal: Expand)); - setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal); @@ -1629,9 +1660,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM, setOperationAction(ISD::FREM , MVT::f32, Expand); setOperationAction(ISD::FMA , MVT::f32, Expand); setOperationAction(ISD::CTTZ , MVT::i32, Expand); - setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); setOperationAction(ISD::CTLZ , MVT::i32, Expand); - setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); setOperationAction(ISD::ROTL , MVT::i32, Expand); setOperationAction(ISD::ROTR , MVT::i32, Expand); setOperationAction(ISD::BSWAP, MVT::i32, Expand); @@ -1730,7 +1759,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM, setOperationAction(ISD::FP_ROUND, MVT::f32, Custom); // Setup Runtime library names. - if (Subtarget->is64Bit()) { + if (Subtarget->is64Bit() && !Subtarget->useSoftFloat()) { setLibcallName(RTLIB::ADD_F128, "_Qp_add"); setLibcallName(RTLIB::SUB_F128, "_Qp_sub"); setLibcallName(RTLIB::MUL_F128, "_Qp_mul"); @@ -1748,7 +1777,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM, setLibcallName(RTLIB::FPEXT_F64_F128, "_Qp_dtoq"); setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos"); setLibcallName(RTLIB::FPROUND_F128_F64, "_Qp_qtod"); - } else { + } else if (!Subtarget->useSoftFloat()) { setLibcallName(RTLIB::ADD_F128, "_Q_add"); setLibcallName(RTLIB::SUB_F128, "_Q_sub"); setLibcallName(RTLIB::MUL_F128, "_Q_mul"); @@ -1769,35 +1798,56 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM, } } + if (Subtarget->fixAllFDIVSQRT()) { + // Promote FDIVS and FSQRTS to FDIVD and FSQRTD instructions instead as + // the former instructions generate errata on LEON processors. + setOperationAction(ISD::FDIV, MVT::f32, Promote); + setOperationAction(ISD::FSQRT, MVT::f32, Promote); + } + + if (Subtarget->replaceFMULS()) { + // Promote FMULS to FMULD instructions instead as + // the former instructions generate errata on LEON processors. + setOperationAction(ISD::FMUL, MVT::f32, Promote); + } + + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); + setMinFunctionAlignment(2); computeRegisterProperties(Subtarget->getRegisterInfo()); } +bool SparcTargetLowering::useSoftFloat() const { + return Subtarget->useSoftFloat(); +} + const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { switch ((SPISD::NodeType)Opcode) { - case SPISD::FIRST_NUMBER: break; - case SPISD::CMPICC: return "SPISD::CMPICC"; - case SPISD::CMPFCC: return "SPISD::CMPFCC"; - case SPISD::BRICC: return "SPISD::BRICC"; - case SPISD::BRXCC: return "SPISD::BRXCC"; - case SPISD::BRFCC: return "SPISD::BRFCC"; - case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; - case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC"; - case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; - case SPISD::Hi: return "SPISD::Hi"; - case SPISD::Lo: return "SPISD::Lo"; - case SPISD::FTOI: return "SPISD::FTOI"; - case SPISD::ITOF: return "SPISD::ITOF"; - case SPISD::FTOX: return "SPISD::FTOX"; - case SPISD::XTOF: return "SPISD::XTOF"; - case SPISD::CALL: return "SPISD::CALL"; - case SPISD::RET_FLAG: return "SPISD::RET_FLAG"; + case SPISD::FIRST_NUMBER: break; + case SPISD::CMPICC: return "SPISD::CMPICC"; + case SPISD::CMPFCC: return "SPISD::CMPFCC"; + case SPISD::BRICC: return "SPISD::BRICC"; + case SPISD::BRXCC: return "SPISD::BRXCC"; + case SPISD::BRFCC: return "SPISD::BRFCC"; + case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; + case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC"; + case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; + case SPISD::EH_SJLJ_SETJMP: return "SPISD::EH_SJLJ_SETJMP"; + case SPISD::EH_SJLJ_LONGJMP: return "SPISD::EH_SJLJ_LONGJMP"; + case SPISD::Hi: return "SPISD::Hi"; + case SPISD::Lo: return "SPISD::Lo"; + case SPISD::FTOI: return "SPISD::FTOI"; + case SPISD::ITOF: return "SPISD::ITOF"; + case SPISD::FTOX: return "SPISD::FTOX"; + case SPISD::XTOF: return "SPISD::XTOF"; + case SPISD::CALL: return "SPISD::CALL"; + case SPISD::RET_FLAG: return "SPISD::RET_FLAG"; case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG"; - case SPISD::FLUSHW: return "SPISD::FLUSHW"; - case SPISD::TLS_ADD: return "SPISD::TLS_ADD"; - case SPISD::TLS_LD: return "SPISD::TLS_LD"; - case SPISD::TLS_CALL: return "SPISD::TLS_CALL"; + case SPISD::FLUSHW: return "SPISD::FLUSHW"; + case SPISD::TLS_ADD: return "SPISD::TLS_ADD"; + case SPISD::TLS_LD: return "SPISD::TLS_LD"; + case SPISD::TLS_CALL: return "SPISD::TLS_CALL"; } return nullptr; } @@ -1902,8 +1952,8 @@ SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); EVT VT = getPointerTy(DAG.getDataLayout()); - // Handle PIC mode first. - if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { + // Handle PIC mode first. SPARC needs a got load for every variable! + if (isPositionIndependent()) { // This is the pic32 code model, the GOT is known to be smaller than 4GB. SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22, SparcMCExpr::VK_Sparc_GOT10, DAG); @@ -1914,8 +1964,7 @@ SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const { MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); MFI->setHasCalls(true); return DAG.getLoad(VT, DL, DAG.getEntryNode(), AbsAddr, - MachinePointerInfo::getGOT(DAG.getMachineFunction()), - false, false, false, 0); + MachinePointerInfo::getGOT(DAG.getMachineFunction())); } // This is one of the absolute code models. @@ -2004,16 +2053,15 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op, SDValue Symbol = withTargetFlags(Op, callTF, DAG); SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - SmallVector<SDValue, 4> Ops; - Ops.push_back(Chain); - Ops.push_back(Callee); - Ops.push_back(Symbol); - Ops.push_back(DAG.getRegister(SP::O0, PtrVT)); const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask( DAG.getMachineFunction(), CallingConv::C); assert(Mask && "Missing call preserved mask for calling convention"); - Ops.push_back(DAG.getRegisterMask(Mask)); - Ops.push_back(InFlag); + SDValue Ops[] = {Chain, + Callee, + Symbol, + DAG.getRegister(SP::O0, PtrVT), + DAG.getRegisterMask(Mask), + InFlag}; Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, Ops); InFlag = Chain.getValue(1); Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(1, DL, true), @@ -2068,10 +2116,10 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op, DAG.getRegister(SP::G7, PtrVT), Offset); } -SDValue -SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain, ArgListTy &Args, - SDValue Arg, SDLoc DL, - SelectionDAG &DAG) const { +SDValue SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain, + ArgListTy &Args, SDValue Arg, + const SDLoc &DL, + SelectionDAG &DAG) const { MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); EVT ArgVT = Arg.getValueType(); Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); @@ -2084,14 +2132,8 @@ SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain, ArgListTy &Args, // Create a stack object and pass the pointer to the library function. int FI = MFI->CreateStackObject(16, 8, false); SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - Chain = DAG.getStore(Chain, - DL, - Entry.Node, - FIPtr, - MachinePointerInfo(), - false, - false, - 8); + Chain = DAG.getStore(Chain, DL, Entry.Node, FIPtr, MachinePointerInfo(), + /* Alignment = */ 8); Entry.Node = FIPtr; Entry.Ty = PointerType::getUnqual(ArgTy); @@ -2136,7 +2178,7 @@ SparcTargetLowering::LowerF128Op(SDValue Op, SelectionDAG &DAG, } TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(SDLoc(Op)).setChain(Chain) - .setCallee(CallingConv::C, RetTyABI, Callee, std::move(Args), 0); + .setCallee(CallingConv::C, RetTyABI, Callee, std::move(Args)); std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI); @@ -2149,19 +2191,13 @@ SparcTargetLowering::LowerF128Op(SDValue Op, SelectionDAG &DAG, Chain = CallInfo.second; // Load RetPtr to get the return value. - return DAG.getLoad(Op.getValueType(), - SDLoc(Op), - Chain, - RetPtr, - MachinePointerInfo(), - false, false, false, 8); + return DAG.getLoad(Op.getValueType(), SDLoc(Op), Chain, RetPtr, + MachinePointerInfo(), /* Alignment = */ 8); } -SDValue -SparcTargetLowering::LowerF128Compare(SDValue LHS, SDValue RHS, - unsigned &SPCC, - SDLoc DL, - SelectionDAG &DAG) const { +SDValue SparcTargetLowering::LowerF128Compare(SDValue LHS, SDValue RHS, + unsigned &SPCC, const SDLoc &DL, + SelectionDAG &DAG) const { const char *LibCall = nullptr; bool is64Bit = Subtarget->is64Bit(); @@ -2193,7 +2229,7 @@ SparcTargetLowering::LowerF128Compare(SDValue LHS, SDValue RHS, TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(DL).setChain(Chain) - .setCallee(CallingConv::C, RetTy, Callee, std::move(Args), 0); + .setCallee(CallingConv::C, RetTy, Callee, std::move(Args)); std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI); @@ -2460,6 +2496,20 @@ static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG, DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag); } +SDValue SparcTargetLowering::LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG, + const SparcTargetLowering &TLI) const { + SDLoc DL(Op); + return DAG.getNode(SPISD::EH_SJLJ_SETJMP, DL, + DAG.getVTList(MVT::i32, MVT::Other), Op.getOperand(0), Op.getOperand(1)); + +} + +SDValue SparcTargetLowering::LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG, + const SparcTargetLowering &TLI) const { + SDLoc DL(Op); + return DAG.getNode(SPISD::EH_SJLJ_LONGJMP, DL, MVT::Other, Op.getOperand(0), Op.getOperand(1)); +} + static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, const SparcTargetLowering &TLI) { MachineFunction &MF = DAG.getMachineFunction(); @@ -2477,7 +2527,7 @@ static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, DAG.getIntPtrConstant(FuncInfo->getVarArgsFrameOffset(), DL)); const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); return DAG.getStore(Op.getOperand(0), DL, Offset, Op.getOperand(1), - MachinePointerInfo(SV), false, false, 0); + MachinePointerInfo(SV)); } static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { @@ -2488,20 +2538,19 @@ static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { EVT PtrVT = VAListPtr.getValueType(); const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); SDLoc DL(Node); - SDValue VAList = DAG.getLoad(PtrVT, DL, InChain, VAListPtr, - MachinePointerInfo(SV), false, false, false, 0); + SDValue VAList = + DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV)); // Increment the pointer, VAList, to the next vaarg. SDValue NextPtr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(VT.getSizeInBits()/8, DL)); // Store the incremented VAList to the legalized pointer. - InChain = DAG.getStore(VAList.getValue(1), DL, NextPtr, - VAListPtr, MachinePointerInfo(SV), false, false, 0); + InChain = DAG.getStore(VAList.getValue(1), DL, NextPtr, VAListPtr, + MachinePointerInfo(SV)); // Load the actual argument out of the pointer VAList. // We can't count on greater alignment than the word size. return DAG.getLoad(VT, DL, InChain, VAList, MachinePointerInfo(), - false, false, false, - std::min(PtrVT.getSizeInBits(), VT.getSizeInBits())/8); + std::min(PtrVT.getSizeInBits(), VT.getSizeInBits()) / 8); } static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, @@ -2564,8 +2613,7 @@ static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG, while (depth--) { SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, DAG.getIntPtrConstant(Offset, dl)); - FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo(), - false, false, false, 0); + FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo()); } if (Subtarget->is64Bit()) FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, @@ -2580,7 +2628,6 @@ static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, uint64_t depth = Op.getConstantOperandVal(0); return getFRAMEADDR(depth, Op, DAG, Subtarget); - } static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG, @@ -2613,30 +2660,34 @@ static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG, dl, VT, FrameAddr, DAG.getIntPtrConstant(Offset, dl)); - RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr, - MachinePointerInfo(), false, false, false, 0); + RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr, MachinePointerInfo()); return RetAddr; } -static SDValue LowerF64Op(SDValue Op, SelectionDAG &DAG, unsigned opcode) -{ - SDLoc dl(Op); - - assert(Op.getValueType() == MVT::f64 && "LowerF64Op called on non-double!"); +static SDValue LowerF64Op(SDValue SrcReg64, const SDLoc &dl, SelectionDAG &DAG, + unsigned opcode) { + assert(SrcReg64.getValueType() == MVT::f64 && "LowerF64Op called on non-double!"); assert(opcode == ISD::FNEG || opcode == ISD::FABS); // Lower fneg/fabs on f64 to fneg/fabs on f32. // fneg f64 => fneg f32:sub_even, fmov f32:sub_odd. // fabs f64 => fabs f32:sub_even, fmov f32:sub_odd. - SDValue SrcReg64 = Op.getOperand(0); + // Note: in little-endian, the floating-point value is stored in the + // registers are in the opposite order, so the subreg with the sign + // bit is the highest-numbered (odd), rather than the + // lowest-numbered (even). + SDValue Hi32 = DAG.getTargetExtractSubreg(SP::sub_even, dl, MVT::f32, SrcReg64); SDValue Lo32 = DAG.getTargetExtractSubreg(SP::sub_odd, dl, MVT::f32, SrcReg64); - Hi32 = DAG.getNode(opcode, dl, MVT::f32, Hi32); + if (DAG.getDataLayout().isLittleEndian()) + Lo32 = DAG.getNode(opcode, dl, MVT::f32, Lo32); + else + Hi32 = DAG.getNode(opcode, dl, MVT::f32, Hi32); SDValue DstReg64 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::f64), 0); @@ -2652,29 +2703,22 @@ static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG) { SDLoc dl(Op); LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode()); - assert(LdNode && LdNode->getOffset().getOpcode() == ISD::UNDEF + assert(LdNode && LdNode->getOffset().isUndef() && "Unexpected node type"); unsigned alignment = LdNode->getAlignment(); if (alignment > 8) alignment = 8; - SDValue Hi64 = DAG.getLoad(MVT::f64, - dl, - LdNode->getChain(), - LdNode->getBasePtr(), - LdNode->getPointerInfo(), - false, false, false, alignment); + SDValue Hi64 = + DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LdNode->getBasePtr(), + LdNode->getPointerInfo(), alignment); EVT addrVT = LdNode->getBasePtr().getValueType(); SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT, LdNode->getBasePtr(), DAG.getConstant(8, dl, addrVT)); - SDValue Lo64 = DAG.getLoad(MVT::f64, - dl, - LdNode->getChain(), - LoPtr, - LdNode->getPointerInfo(), - false, false, false, alignment); + SDValue Lo64 = DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LoPtr, + LdNode->getPointerInfo(), alignment); SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32); SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32); @@ -2713,7 +2757,7 @@ static SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) { SDLoc dl(Op); StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode()); - assert(StNode && StNode->getOffset().getOpcode() == ISD::UNDEF + assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type"); SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32); SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32); @@ -2734,22 +2778,15 @@ static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) { alignment = 8; SDValue OutChains[2]; - OutChains[0] = DAG.getStore(StNode->getChain(), - dl, - SDValue(Hi64, 0), - StNode->getBasePtr(), - MachinePointerInfo(), - false, false, alignment); + OutChains[0] = + DAG.getStore(StNode->getChain(), dl, SDValue(Hi64, 0), + StNode->getBasePtr(), MachinePointerInfo(), alignment); EVT addrVT = StNode->getBasePtr().getValueType(); SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT, StNode->getBasePtr(), DAG.getConstant(8, dl, addrVT)); - OutChains[1] = DAG.getStore(StNode->getChain(), - dl, - SDValue(Lo64, 0), - LoPtr, - MachinePointerInfo(), - false, false, alignment); + OutChains[1] = DAG.getStore(StNode->getChain(), dl, SDValue(Lo64, 0), LoPtr, + MachinePointerInfo(), alignment); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); } @@ -2768,8 +2805,7 @@ static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) SDValue Val = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, St->getValue()); SDValue Chain = DAG.getStore( St->getChain(), dl, Val, St->getBasePtr(), St->getPointerInfo(), - St->isVolatile(), St->isNonTemporal(), St->getAlignment(), - St->getAAInfo()); + St->isVolatile(), St->getMemOperand()->getFlags(), St->getAAInfo()); return Chain; } @@ -2780,24 +2816,35 @@ static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) { assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS) && "invalid opcode"); + SDLoc dl(Op); + if (Op.getValueType() == MVT::f64) - return LowerF64Op(Op, DAG, Op.getOpcode()); + return LowerF64Op(Op.getOperand(0), dl, DAG, Op.getOpcode()); if (Op.getValueType() != MVT::f128) return Op; // Lower fabs/fneg on f128 to fabs/fneg on f64 // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64 + // (As with LowerF64Op, on little-endian, we need to negate the odd + // subreg) - SDLoc dl(Op); SDValue SrcReg128 = Op.getOperand(0); SDValue Hi64 = DAG.getTargetExtractSubreg(SP::sub_even64, dl, MVT::f64, SrcReg128); SDValue Lo64 = DAG.getTargetExtractSubreg(SP::sub_odd64, dl, MVT::f64, SrcReg128); - if (isV9) - Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64); - else - Hi64 = LowerF64Op(Hi64, DAG, Op.getOpcode()); + + if (DAG.getDataLayout().isLittleEndian()) { + if (isV9) + Lo64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Lo64); + else + Lo64 = LowerF64Op(Lo64, dl, DAG, Op.getOpcode()); + } else { + if (isV9) + Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64); + else + Hi64 = LowerF64Op(Hi64, dl, DAG, Op.getOpcode()); + } SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::f128), 0); @@ -2906,12 +2953,25 @@ static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG, } static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) { + if (isStrongerThanMonotonic(cast<AtomicSDNode>(Op)->getOrdering())) + // Expand with a fence. + return SDValue(); + // Monotonic load/stores are legal. - if (cast<AtomicSDNode>(Op)->getOrdering() <= Monotonic) - return Op; + return Op; +} - // Otherwise, expand with a fence. - return SDValue(); +SDValue SparcTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, + SelectionDAG &DAG) const { + unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); + SDLoc dl(Op); + switch (IntNo) { + default: return SDValue(); // Don't custom lower most intrinsics. + case Intrinsic::thread_pointer: { + EVT PtrVT = getPointerTy(DAG.getDataLayout()); + return DAG.getRegister(SP::G7, PtrVT); + } + } } SDValue SparcTargetLowering:: @@ -2943,6 +3003,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const { hasHardQuad); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, *this, hasHardQuad); + case ISD::EH_SJLJ_SETJMP: return LowerEH_SJLJ_SETJMP(Op, DAG, *this); + case ISD::EH_SJLJ_LONGJMP: return LowerEH_SJLJ_LONGJMP(Op, DAG, *this); case ISD::VASTART: return LowerVASTART(Op, DAG, *this); case ISD::VAARG: return LowerVAARG(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG, @@ -2972,14 +3034,15 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this); case ISD::ATOMIC_LOAD: case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG); + case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); } } MachineBasicBlock * -SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, +SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { - switch (MI->getOpcode()) { - default: llvm_unreachable("Unknown SELECT_CC!"); + switch (MI.getOpcode()) { + default: llvm_unreachable("Unknown Custom Instruction!"); case SP::SELECT_CC_Int_ICC: case SP::SELECT_CC_FP_ICC: case SP::SELECT_CC_DFP_ICC: @@ -2990,61 +3053,21 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case SP::SELECT_CC_DFP_FCC: case SP::SELECT_CC_QFP_FCC: return expandSelectCC(MI, BB, SP::FBCOND); + case SP::EH_SJLJ_SETJMP32ri: + case SP::EH_SJLJ_SETJMP32rr: + return emitEHSjLjSetJmp(MI, BB); + case SP::EH_SJLJ_LONGJMP32rr: + case SP::EH_SJLJ_LONGJMP32ri: + return emitEHSjLjLongJmp(MI, BB); + } +} - case SP::ATOMIC_LOAD_ADD_32: - return expandAtomicRMW(MI, BB, SP::ADDrr); - case SP::ATOMIC_LOAD_ADD_64: - return expandAtomicRMW(MI, BB, SP::ADDXrr); - case SP::ATOMIC_LOAD_SUB_32: - return expandAtomicRMW(MI, BB, SP::SUBrr); - case SP::ATOMIC_LOAD_SUB_64: - return expandAtomicRMW(MI, BB, SP::SUBXrr); - case SP::ATOMIC_LOAD_AND_32: - return expandAtomicRMW(MI, BB, SP::ANDrr); - case SP::ATOMIC_LOAD_AND_64: - return expandAtomicRMW(MI, BB, SP::ANDXrr); - case SP::ATOMIC_LOAD_OR_32: - return expandAtomicRMW(MI, BB, SP::ORrr); - case SP::ATOMIC_LOAD_OR_64: - return expandAtomicRMW(MI, BB, SP::ORXrr); - case SP::ATOMIC_LOAD_XOR_32: - return expandAtomicRMW(MI, BB, SP::XORrr); - case SP::ATOMIC_LOAD_XOR_64: - return expandAtomicRMW(MI, BB, SP::XORXrr); - case SP::ATOMIC_LOAD_NAND_32: - return expandAtomicRMW(MI, BB, SP::ANDrr); - case SP::ATOMIC_LOAD_NAND_64: - return expandAtomicRMW(MI, BB, SP::ANDXrr); - - case SP::ATOMIC_SWAP_64: - return expandAtomicRMW(MI, BB, 0); - - case SP::ATOMIC_LOAD_MAX_32: - return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_G); - case SP::ATOMIC_LOAD_MAX_64: - return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_G); - case SP::ATOMIC_LOAD_MIN_32: - return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LE); - case SP::ATOMIC_LOAD_MIN_64: - return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LE); - case SP::ATOMIC_LOAD_UMAX_32: - return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_GU); - case SP::ATOMIC_LOAD_UMAX_64: - return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_GU); - case SP::ATOMIC_LOAD_UMIN_32: - return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LEU); - case SP::ATOMIC_LOAD_UMIN_64: - return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LEU); - } -} - -MachineBasicBlock* -SparcTargetLowering::expandSelectCC(MachineInstr *MI, - MachineBasicBlock *BB, +MachineBasicBlock * +SparcTargetLowering::expandSelectCC(MachineInstr &MI, MachineBasicBlock *BB, unsigned BROpcode) const { const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc dl = MI->getDebugLoc(); - unsigned CC = (SPCC::CondCodes)MI->getOperand(3).getImm(); + DebugLoc dl = MI.getDebugLoc(); + unsigned CC = (SPCC::CondCodes)MI.getOperand(3).getImm(); // To "insert" a SELECT_CC instruction, we actually have to insert the diamond // control-flow pattern. The incoming instruction knows the destination vreg @@ -3089,107 +3112,211 @@ SparcTargetLowering::expandSelectCC(MachineInstr *MI, // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] // ... BB = sinkMBB; - BuildMI(*BB, BB->begin(), dl, TII.get(SP::PHI), MI->getOperand(0).getReg()) - .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) - .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); + BuildMI(*BB, BB->begin(), dl, TII.get(SP::PHI), MI.getOperand(0).getReg()) + .addReg(MI.getOperand(2).getReg()) + .addMBB(copy0MBB) + .addReg(MI.getOperand(1).getReg()) + .addMBB(thisMBB); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } -MachineBasicBlock* -SparcTargetLowering::expandAtomicRMW(MachineInstr *MI, - MachineBasicBlock *MBB, - unsigned Opcode, - unsigned CondCode) const { - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); - DebugLoc DL = MI->getDebugLoc(); +MachineBasicBlock * +SparcTargetLowering::emitEHSjLjLongJmp(MachineInstr &MI, + MachineBasicBlock *MBB) const { + DebugLoc DL = MI.getDebugLoc(); + const TargetInstrInfo *TII = Subtarget->getInstrInfo(); + + MachineFunction *MF = MBB->getParent(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + MachineInstrBuilder MIB; + + MVT PVT = getPointerTy(MF->getDataLayout()); + unsigned RegSize = PVT.getStoreSize(); + assert(PVT == MVT::i32 && "Invalid Pointer Size!"); + + unsigned Buf = MI.getOperand(0).getReg(); + unsigned JmpLoc = MRI.createVirtualRegister(&SP::IntRegsRegClass); + + // TO DO: If we do 64-bit handling, this perhaps should be FLUSHW, not TA 3 + MIB = BuildMI(*MBB, MI, DL, TII->get(SP::TRAPri), SP::G0).addImm(3).addImm(SPCC::ICC_A); + + // Instruction to restore FP + const unsigned FP = SP::I6; + MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri)) + .addReg(FP) + .addReg(Buf) + .addImm(0); - // MI is an atomic read-modify-write instruction of the form: + // Instruction to load jmp location + MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri)) + .addReg(JmpLoc, RegState::Define) + .addReg(Buf) + .addImm(RegSize); + + // Instruction to restore SP + const unsigned SP = SP::O6; + MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri)) + .addReg(SP) + .addReg(Buf) + .addImm(2 * RegSize); + + // Instruction to restore I7 + MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri)) + .addReg(SP::I7) + .addReg(Buf, RegState::Kill) + .addImm(3 * RegSize); + + // Jump to JmpLoc + BuildMI(*MBB, MI, DL, TII->get(SP::JMPLrr)).addReg(SP::G0).addReg(JmpLoc, RegState::Kill).addReg(SP::G0); + + MI.eraseFromParent(); + return MBB; +} + +MachineBasicBlock * +SparcTargetLowering::emitEHSjLjSetJmp(MachineInstr &MI, + MachineBasicBlock *MBB) const { + DebugLoc DL = MI.getDebugLoc(); + const TargetInstrInfo *TII = Subtarget->getInstrInfo(); + + MachineFunction *MF = MBB->getParent(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + MachineInstrBuilder MIB; + + MVT PVT = getPointerTy(MF->getDataLayout()); + unsigned RegSize = PVT.getStoreSize(); + assert(PVT == MVT::i32 && "Invalid Pointer Size!"); + + unsigned DstReg = MI.getOperand(0).getReg(); + const TargetRegisterClass *RC = MRI.getRegClass(DstReg); + assert(RC->hasType(MVT::i32) && "Invalid destination!"); + unsigned mainDstReg = MRI.createVirtualRegister(RC); + unsigned restoreDstReg = MRI.createVirtualRegister(RC); + + // For v = setjmp(buf), we generate // - // rd = atomicrmw<op> addr, rs2 + // thisMBB: + // buf[0] = FP + // buf[RegSize] = restoreMBB <-- takes address of restoreMBB + // buf[RegSize * 2] = O6 + // buf[RegSize * 3] = I7 + // Ensure restoreMBB remains in the relocations list (done using a bn instruction) + // b mainMBB // - // All three operands are registers. - unsigned DestReg = MI->getOperand(0).getReg(); - unsigned AddrReg = MI->getOperand(1).getReg(); - unsigned Rs2Reg = MI->getOperand(2).getReg(); - - // SelectionDAG has already inserted memory barriers before and after MI, so - // we simply have to implement the operatiuon in terms of compare-and-swap. + // mainMBB: + // v_main = 0 + // b sinkMBB // - // %val0 = load %addr - // loop: - // %val = phi %val0, %dest - // %upd = op %val, %rs2 - // %dest = cas %addr, %val, %upd - // cmp %val, %dest - // bne loop - // done: + // restoreMBB: + // v_restore = 1 + // --fall through-- // - bool is64Bit = SP::I64RegsRegClass.hasSubClassEq(MRI.getRegClass(DestReg)); - const TargetRegisterClass *ValueRC = - is64Bit ? &SP::I64RegsRegClass : &SP::IntRegsRegClass; - unsigned Val0Reg = MRI.createVirtualRegister(ValueRC); + // sinkMBB: + // v = phi(main, restore) - BuildMI(*MBB, MI, DL, TII.get(is64Bit ? SP::LDXri : SP::LDri), Val0Reg) - .addReg(AddrReg).addImm(0); + const BasicBlock *BB = MBB->getBasicBlock(); + MachineFunction::iterator It = ++MBB->getIterator(); + MachineBasicBlock *thisMBB = MBB; + MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock(BB); + MachineBasicBlock *restoreMBB = MF->CreateMachineBasicBlock(BB); + MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(BB); - // Split the basic block MBB before MI and insert the loop block in the hole. - MachineFunction::iterator MFI = MBB->getIterator(); - const BasicBlock *LLVM_BB = MBB->getBasicBlock(); - MachineFunction *MF = MBB->getParent(); - MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *DoneMBB = MF->CreateMachineBasicBlock(LLVM_BB); - ++MFI; - MF->insert(MFI, LoopMBB); - MF->insert(MFI, DoneMBB); - - // Move MI and following instructions to DoneMBB. - DoneMBB->splice(DoneMBB->begin(), MBB, MI, MBB->end()); - DoneMBB->transferSuccessorsAndUpdatePHIs(MBB); - - // Connect the CFG again. - MBB->addSuccessor(LoopMBB); - LoopMBB->addSuccessor(LoopMBB); - LoopMBB->addSuccessor(DoneMBB); - - // Build the loop block. - unsigned ValReg = MRI.createVirtualRegister(ValueRC); - // Opcode == 0 means try to write Rs2Reg directly (ATOMIC_SWAP). - unsigned UpdReg = (Opcode ? MRI.createVirtualRegister(ValueRC) : Rs2Reg); - - BuildMI(LoopMBB, DL, TII.get(SP::PHI), ValReg) - .addReg(Val0Reg).addMBB(MBB) - .addReg(DestReg).addMBB(LoopMBB); - - if (CondCode) { - // This is one of the min/max operations. We need a CMPrr followed by a - // MOVXCC/MOVICC. - BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(Rs2Reg); - BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) - .addReg(ValReg).addReg(Rs2Reg).addImm(CondCode); - } else if (Opcode) { - BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) - .addReg(ValReg).addReg(Rs2Reg); - } - - if (MI->getOpcode() == SP::ATOMIC_LOAD_NAND_32 || - MI->getOpcode() == SP::ATOMIC_LOAD_NAND_64) { - unsigned TmpReg = UpdReg; - UpdReg = MRI.createVirtualRegister(ValueRC); - BuildMI(LoopMBB, DL, TII.get(SP::XORri), UpdReg).addReg(TmpReg).addImm(-1); - } - - BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::CASXrr : SP::CASrr), DestReg) - .addReg(AddrReg).addReg(ValReg).addReg(UpdReg) - .setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); - BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(DestReg); - BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::BPXCC : SP::BCOND)) - .addMBB(LoopMBB).addImm(SPCC::ICC_NE); - - MI->eraseFromParent(); - return DoneMBB; + MF->insert(It, mainMBB); + MF->insert(It, restoreMBB); + MF->insert(It, sinkMBB); + restoreMBB->setHasAddressTaken(); + + // Transfer the remainder of BB and its successor edges to sinkMBB. + sinkMBB->splice(sinkMBB->begin(), MBB, + std::next(MachineBasicBlock::iterator(MI)), + MBB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(MBB); + + unsigned LabelReg = MRI.createVirtualRegister(&SP::IntRegsRegClass); + unsigned LabelReg2 = MRI.createVirtualRegister(&SP::IntRegsRegClass); + unsigned BufReg = MI.getOperand(1).getReg(); + + // Instruction to store FP + const unsigned FP = SP::I6; + MIB = BuildMI(thisMBB, DL, TII->get(SP::STri)) + .addReg(BufReg) + .addImm(0) + .addReg(FP); + + // Instructions to store jmp location + MIB = BuildMI(thisMBB, DL, TII->get(SP::SETHIi)) + .addReg(LabelReg, RegState::Define) + .addMBB(restoreMBB, SparcMCExpr::VK_Sparc_HI); + + MIB = BuildMI(thisMBB, DL, TII->get(SP::ORri)) + .addReg(LabelReg2, RegState::Define) + .addReg(LabelReg, RegState::Kill) + .addMBB(restoreMBB, SparcMCExpr::VK_Sparc_LO); + + MIB = BuildMI(thisMBB, DL, TII->get(SP::STri)) + .addReg(BufReg) + .addImm(RegSize) + .addReg(LabelReg2, RegState::Kill); + + // Instruction to store SP + const unsigned SP = SP::O6; + MIB = BuildMI(thisMBB, DL, TII->get(SP::STri)) + .addReg(BufReg) + .addImm(2 * RegSize) + .addReg(SP); + + // Instruction to store I7 + MIB = BuildMI(thisMBB, DL, TII->get(SP::STri)) + .addReg(BufReg) + .addImm(3 * RegSize) + .addReg(SP::I7); + + + // FIX ME: This next instruction ensures that the restoreMBB block address remains + // valid through optimization passes and serves no other purpose. The ICC_N ensures + // that the branch is never taken. This commented-out code here was an alternative + // attempt to achieve this which brought myriad problems. + //MIB = BuildMI(thisMBB, DL, TII->get(SP::EH_SjLj_Setup)).addMBB(restoreMBB, SparcMCExpr::VK_Sparc_None); + MIB = BuildMI(thisMBB, DL, TII->get(SP::BCOND)) + .addMBB(restoreMBB) + .addImm(SPCC::ICC_N); + + MIB = BuildMI(thisMBB, DL, TII->get(SP::BCOND)) + .addMBB(mainMBB) + .addImm(SPCC::ICC_A); + + thisMBB->addSuccessor(mainMBB); + thisMBB->addSuccessor(restoreMBB); + + + // mainMBB: + MIB = BuildMI(mainMBB, DL, TII->get(SP::ORrr)) + .addReg(mainDstReg, RegState::Define) + .addReg(SP::G0) + .addReg(SP::G0); + MIB = BuildMI(mainMBB, DL, TII->get(SP::BCOND)).addMBB(sinkMBB).addImm(SPCC::ICC_A); + + mainMBB->addSuccessor(sinkMBB); + + + // restoreMBB: + MIB = BuildMI(restoreMBB, DL, TII->get(SP::ORri)) + .addReg(restoreDstReg, RegState::Define) + .addReg(SP::G0) + .addImm(1); + //MIB = BuildMI(restoreMBB, DL, TII->get(SP::BCOND)).addMBB(sinkMBB).addImm(SPCC::ICC_A); + restoreMBB->addSuccessor(sinkMBB); + + // sinkMBB: + MIB = BuildMI(*sinkMBB, sinkMBB->begin(), DL, + TII->get(SP::PHI), DstReg) + .addReg(mainDstReg).addMBB(mainMBB) + .addReg(restoreDstReg).addMBB(restoreMBB); + + MI.eraseFromParent(); + return sinkMBB; } //===----------------------------------------------------------------------===// @@ -3202,8 +3329,11 @@ SparcTargetLowering::ConstraintType SparcTargetLowering::getConstraintType(StringRef Constraint) const { if (Constraint.size() == 1) { switch (Constraint[0]) { - default: break; - case 'r': return C_RegisterClass; + default: + break; + case 'f': + case 'r': + return C_RegisterClass; case 'I': // SIMM13 return C_Other; } @@ -3277,6 +3407,9 @@ SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, MVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { + case 'f': + return std::make_pair(0U, &SP::FPRegsRegClass); + case 'r': if (VT == MVT::v2i32) return std::make_pair(0U, &SP::IntPairRegClass); @@ -3368,10 +3501,9 @@ void SparcTargetLowering::ReplaceNodeResults(SDNode *N, SDLoc dl(N); SDValue LoadRes = DAG.getExtLoad( - Ld->getExtensionType(), dl, MVT::v2i32, - Ld->getChain(), Ld->getBasePtr(), Ld->getPointerInfo(), - MVT::v2i32, Ld->isVolatile(), Ld->isNonTemporal(), - Ld->isInvariant(), Ld->getAlignment(), Ld->getAAInfo()); + Ld->getExtensionType(), dl, MVT::v2i32, Ld->getChain(), + Ld->getBasePtr(), Ld->getPointerInfo(), MVT::v2i32, Ld->getAlignment(), + Ld->getMemOperand()->getFlags(), Ld->getAAInfo()); SDValue Res = DAG.getNode(ISD::BITCAST, dl, MVT::i64, LoadRes); Results.push_back(Res); @@ -3380,3 +3512,16 @@ void SparcTargetLowering::ReplaceNodeResults(SDNode *N, } } } + +// Override to enable LOAD_STACK_GUARD lowering on Linux. +bool SparcTargetLowering::useLoadStackGuardNode() const { + if (!Subtarget->isTargetLinux()) + return TargetLowering::useLoadStackGuardNode(); + return true; +} + +// Override to disable global variable loading on Linux. +void SparcTargetLowering::insertSSPDeclarations(Module &M) const { + if (!Subtarget->isTargetLinux()) + return TargetLowering::insertSSPDeclarations(M); +} |