aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Sparc/SparcISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Sparc/SparcISelLowering.cpp')
-rw-r--r--lib/Target/Sparc/SparcISelLowering.cpp935
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);
+}