diff options
author | dim <dim@FreeBSD.org> | 2016-12-26 20:36:37 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2016-12-26 20:36:37 +0000 |
commit | 06210ae42d418d50d8d9365d5c9419308ae9e7ee (patch) | |
tree | ab60b4cdd6e430dda1f292a46a77ddb744723f31 /contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp | |
parent | 2dd166267f53df1c3748b4325d294b9b839de74b (diff) | |
download | FreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.zip FreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.tar.gz |
MFC r309124:
Upgrade our copies of clang, llvm, lldb, compiler-rt and libc++ to 3.9.0
release, and add lld 3.9.0. Also completely revamp the build system for
clang, llvm, lldb and their related tools.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Release notes for llvm, clang and lld are available here:
<http://llvm.org/releases/3.9.0/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.9.0/tools/clang/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.9.0/tools/lld/docs/ReleaseNotes.html>
Thanks to Ed Maste, Bryan Drewery, Andrew Turner, Antoine Brodin and Jan
Beich for their help.
Relnotes: yes
MFC r309147:
Pull in r282174 from upstream llvm trunk (by Krzysztof Parzyszek):
[PPC] Set SP after loading data from stack frame, if no red zone is
present
Follow-up to r280705: Make sure that the SP is only restored after
all data is loaded from the stack frame, if there is no red zone.
This completes the fix for
https://llvm.org/bugs/show_bug.cgi?id=26519.
Differential Revision: https://reviews.llvm.org/D24466
Reported by: Mark Millard
PR: 214433
MFC r309149:
Pull in r283060 from upstream llvm trunk (by Hal Finkel):
[PowerPC] Refactor soft-float support, and enable PPC64 soft float
This change enables soft-float for PowerPC64, and also makes
soft-float disable all vector instruction sets for both 32-bit and
64-bit modes. This latter part is necessary because the PPC backend
canonicalizes many Altivec vector types to floating-point types, and
so soft-float breaks scalarization support for many operations. Both
for embedded targets and for operating-system kernels desiring
soft-float support, it seems reasonable that disabling hardware
floating-point also disables vector instructions (embedded targets
without hardware floating point support are unlikely to have Altivec,
etc. and operating system kernels desiring not to use floating-point
registers to lower syscall cost are unlikely to want to use vector
registers either). If someone needs this to work, we'll need to
change the fact that we promote many Altivec operations to act on
v4f32. To make it possible to disable Altivec when soft-float is
enabled, hardware floating-point support needs to be expressed as a
positive feature, like the others, and not a negative feature,
because target features cannot have dependencies on the disabling of
some other feature. So +soft-float has now become -hard-float.
Fixes PR26970.
Pull in r283061 from upstream clang trunk (by Hal Finkel):
[PowerPC] Enable soft-float for PPC64, and +soft-float -> -hard-float
Enable soft-float support on PPC64, as the backend now supports it.
Also, the backend now uses -hard-float instead of +soft-float, so set
the target features accordingly.
Fixes PR26970.
Reported by: Mark Millard
PR: 214433
MFC r309212:
Add a few missed clang 3.9.0 files to OptionalObsoleteFiles.
MFC r309262:
Fix packaging for clang, lldb and lld 3.9.0
During the upgrade of clang/llvm etc to 3.9.0 in r309124, the PACKAGE
directive in the usr.bin/clang/*.mk files got dropped accidentally.
Restore it, with a few minor changes and additions:
* Correct license in clang.ucl to NCSA
* Add PACKAGE=clang for clang and most of the "ll" tools
* Put lldb in its own package
* Put lld in its own package
Reviewed by: gjb, jmallett
Differential Revision: https://reviews.freebsd.org/D8666
MFC r309656:
During the bootstrap phase, when building the minimal llvm library on
PowerPC, add lib/Support/Atomic.cpp. This is needed because upstream
llvm revision r271821 disabled the use of std::call_once, which causes
some fallback functions from Atomic.cpp to be used instead.
Reported by: Mark Millard
PR: 214902
MFC r309835:
Tentatively apply https://reviews.llvm.org/D18730 to work around gcc PR
70528 (bogus error: constructor required before non-static data member).
This should fix buildworld with the external gcc package.
Reported by: https://jenkins.freebsd.org/job/FreeBSD_HEAD_amd64_gcc/
MFC r310194:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
3.9.1 release.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Release notes for llvm, clang and lld will be available here:
<http://releases.llvm.org/3.9.1/docs/ReleaseNotes.html>
<http://releases.llvm.org/3.9.1/tools/clang/docs/ReleaseNotes.html>
<http://releases.llvm.org/3.9.1/tools/lld/docs/ReleaseNotes.html>
Relnotes: yes
Diffstat (limited to 'contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp | 935 |
1 files changed, 540 insertions, 395 deletions
diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 5e70ffe..8738bc8 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/contrib/llvm/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); +} |