109467b48Spatrick //===-- SparcISelLowering.cpp - Sparc DAG Lowering Implementation ---------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements the interfaces that Sparc uses to lower LLVM code into a
1009467b48Spatrick // selection DAG.
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick
1409467b48Spatrick #include "SparcISelLowering.h"
1509467b48Spatrick #include "MCTargetDesc/SparcMCExpr.h"
1609467b48Spatrick #include "SparcMachineFunctionInfo.h"
1709467b48Spatrick #include "SparcRegisterInfo.h"
1809467b48Spatrick #include "SparcTargetMachine.h"
1909467b48Spatrick #include "SparcTargetObjectFile.h"
2009467b48Spatrick #include "llvm/ADT/StringExtras.h"
2109467b48Spatrick #include "llvm/ADT/StringSwitch.h"
2209467b48Spatrick #include "llvm/CodeGen/CallingConvLower.h"
2309467b48Spatrick #include "llvm/CodeGen/MachineFrameInfo.h"
2409467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
2509467b48Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
2609467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
2709467b48Spatrick #include "llvm/CodeGen/SelectionDAG.h"
28*a96b3639Srobert #include "llvm/CodeGen/SelectionDAGNodes.h"
2909467b48Spatrick #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
3009467b48Spatrick #include "llvm/IR/DerivedTypes.h"
3109467b48Spatrick #include "llvm/IR/Function.h"
3209467b48Spatrick #include "llvm/IR/Module.h"
3309467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3409467b48Spatrick #include "llvm/Support/KnownBits.h"
3509467b48Spatrick using namespace llvm;
3609467b48Spatrick
3709467b48Spatrick
3809467b48Spatrick //===----------------------------------------------------------------------===//
3909467b48Spatrick // Calling Convention Implementation
4009467b48Spatrick //===----------------------------------------------------------------------===//
4109467b48Spatrick
CC_Sparc_Assign_SRet(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)4209467b48Spatrick static bool CC_Sparc_Assign_SRet(unsigned &ValNo, MVT &ValVT,
4309467b48Spatrick MVT &LocVT, CCValAssign::LocInfo &LocInfo,
4409467b48Spatrick ISD::ArgFlagsTy &ArgFlags, CCState &State)
4509467b48Spatrick {
4609467b48Spatrick assert (ArgFlags.isSRet());
4709467b48Spatrick
4809467b48Spatrick // Assign SRet argument.
4909467b48Spatrick State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
5009467b48Spatrick 0,
5109467b48Spatrick LocVT, LocInfo));
5209467b48Spatrick return true;
5309467b48Spatrick }
5409467b48Spatrick
CC_Sparc_Assign_Split_64(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)5509467b48Spatrick static bool CC_Sparc_Assign_Split_64(unsigned &ValNo, MVT &ValVT,
5609467b48Spatrick MVT &LocVT, CCValAssign::LocInfo &LocInfo,
5709467b48Spatrick ISD::ArgFlagsTy &ArgFlags, CCState &State)
5809467b48Spatrick {
5909467b48Spatrick static const MCPhysReg RegList[] = {
6009467b48Spatrick SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
6109467b48Spatrick };
6209467b48Spatrick // Try to get first reg.
63097a140dSpatrick if (Register Reg = State.AllocateReg(RegList)) {
6409467b48Spatrick State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
6509467b48Spatrick } else {
6609467b48Spatrick // Assign whole thing in stack.
67097a140dSpatrick State.addLoc(CCValAssign::getCustomMem(
68097a140dSpatrick ValNo, ValVT, State.AllocateStack(8, Align(4)), LocVT, LocInfo));
6909467b48Spatrick return true;
7009467b48Spatrick }
7109467b48Spatrick
7209467b48Spatrick // Try to get second reg.
73097a140dSpatrick if (Register Reg = State.AllocateReg(RegList))
7409467b48Spatrick State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
7509467b48Spatrick else
76097a140dSpatrick State.addLoc(CCValAssign::getCustomMem(
77097a140dSpatrick ValNo, ValVT, State.AllocateStack(4, Align(4)), LocVT, LocInfo));
7809467b48Spatrick return true;
7909467b48Spatrick }
8009467b48Spatrick
CC_Sparc_Assign_Ret_Split_64(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)8109467b48Spatrick static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT,
8209467b48Spatrick MVT &LocVT, CCValAssign::LocInfo &LocInfo,
8309467b48Spatrick ISD::ArgFlagsTy &ArgFlags, CCState &State)
8409467b48Spatrick {
8509467b48Spatrick static const MCPhysReg RegList[] = {
8609467b48Spatrick SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
8709467b48Spatrick };
8809467b48Spatrick
8909467b48Spatrick // Try to get first reg.
90097a140dSpatrick if (Register Reg = State.AllocateReg(RegList))
9109467b48Spatrick State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
9209467b48Spatrick else
9309467b48Spatrick return false;
9409467b48Spatrick
9509467b48Spatrick // Try to get second reg.
96097a140dSpatrick if (Register Reg = State.AllocateReg(RegList))
9709467b48Spatrick State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
9809467b48Spatrick else
9909467b48Spatrick return false;
10009467b48Spatrick
10109467b48Spatrick return true;
10209467b48Spatrick }
10309467b48Spatrick
10409467b48Spatrick // Allocate a full-sized argument for the 64-bit ABI.
Analyze_CC_Sparc64_Full(bool IsReturn,unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)105*a96b3639Srobert static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT,
10609467b48Spatrick MVT &LocVT, CCValAssign::LocInfo &LocInfo,
10709467b48Spatrick ISD::ArgFlagsTy &ArgFlags, CCState &State) {
10809467b48Spatrick assert((LocVT == MVT::f32 || LocVT == MVT::f128
10909467b48Spatrick || LocVT.getSizeInBits() == 64) &&
11009467b48Spatrick "Can't handle non-64 bits locations");
11109467b48Spatrick
11209467b48Spatrick // Stack space is allocated for all arguments starting from [%fp+BIAS+128].
11309467b48Spatrick unsigned size = (LocVT == MVT::f128) ? 16 : 8;
114097a140dSpatrick Align alignment = (LocVT == MVT::f128) ? Align(16) : Align(8);
11509467b48Spatrick unsigned Offset = State.AllocateStack(size, alignment);
11609467b48Spatrick unsigned Reg = 0;
11709467b48Spatrick
11809467b48Spatrick if (LocVT == MVT::i64 && Offset < 6*8)
11909467b48Spatrick // Promote integers to %i0-%i5.
12009467b48Spatrick Reg = SP::I0 + Offset/8;
12109467b48Spatrick else if (LocVT == MVT::f64 && Offset < 16*8)
12209467b48Spatrick // Promote doubles to %d0-%d30. (Which LLVM calls D0-D15).
12309467b48Spatrick Reg = SP::D0 + Offset/8;
12409467b48Spatrick else if (LocVT == MVT::f32 && Offset < 16*8)
12509467b48Spatrick // Promote floats to %f1, %f3, ...
12609467b48Spatrick Reg = SP::F1 + Offset/4;
12709467b48Spatrick else if (LocVT == MVT::f128 && Offset < 16*8)
12809467b48Spatrick // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7).
12909467b48Spatrick Reg = SP::Q0 + Offset/16;
13009467b48Spatrick
13109467b48Spatrick // Promote to register when possible, otherwise use the stack slot.
13209467b48Spatrick if (Reg) {
13309467b48Spatrick State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
13409467b48Spatrick return true;
13509467b48Spatrick }
13609467b48Spatrick
137*a96b3639Srobert // Bail out if this is a return CC and we run out of registers to place
138*a96b3639Srobert // values into.
139*a96b3639Srobert if (IsReturn)
140*a96b3639Srobert return false;
141*a96b3639Srobert
14209467b48Spatrick // This argument goes on the stack in an 8-byte slot.
14309467b48Spatrick // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to
14409467b48Spatrick // the right-aligned float. The first 4 bytes of the stack slot are undefined.
14509467b48Spatrick if (LocVT == MVT::f32)
14609467b48Spatrick Offset += 4;
14709467b48Spatrick
14809467b48Spatrick State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
14909467b48Spatrick return true;
15009467b48Spatrick }
15109467b48Spatrick
15209467b48Spatrick // Allocate a half-sized argument for the 64-bit ABI.
15309467b48Spatrick //
15409467b48Spatrick // This is used when passing { float, int } structs by value in registers.
Analyze_CC_Sparc64_Half(bool IsReturn,unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)155*a96b3639Srobert static bool Analyze_CC_Sparc64_Half(bool IsReturn, unsigned &ValNo, MVT &ValVT,
15609467b48Spatrick MVT &LocVT, CCValAssign::LocInfo &LocInfo,
15709467b48Spatrick ISD::ArgFlagsTy &ArgFlags, CCState &State) {
15809467b48Spatrick assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations");
159097a140dSpatrick unsigned Offset = State.AllocateStack(4, Align(4));
16009467b48Spatrick
16109467b48Spatrick if (LocVT == MVT::f32 && Offset < 16*8) {
16209467b48Spatrick // Promote floats to %f0-%f31.
16309467b48Spatrick State.addLoc(CCValAssign::getReg(ValNo, ValVT, SP::F0 + Offset/4,
16409467b48Spatrick LocVT, LocInfo));
16509467b48Spatrick return true;
16609467b48Spatrick }
16709467b48Spatrick
16809467b48Spatrick if (LocVT == MVT::i32 && Offset < 6*8) {
16909467b48Spatrick // Promote integers to %i0-%i5, using half the register.
17009467b48Spatrick unsigned Reg = SP::I0 + Offset/8;
17109467b48Spatrick LocVT = MVT::i64;
17209467b48Spatrick LocInfo = CCValAssign::AExt;
17309467b48Spatrick
17409467b48Spatrick // Set the Custom bit if this i32 goes in the high bits of a register.
17509467b48Spatrick if (Offset % 8 == 0)
17609467b48Spatrick State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg,
17709467b48Spatrick LocVT, LocInfo));
17809467b48Spatrick else
17909467b48Spatrick State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
18009467b48Spatrick return true;
18109467b48Spatrick }
18209467b48Spatrick
183*a96b3639Srobert // Bail out if this is a return CC and we run out of registers to place
184*a96b3639Srobert // values into.
185*a96b3639Srobert if (IsReturn)
186*a96b3639Srobert return false;
187*a96b3639Srobert
18809467b48Spatrick State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
18909467b48Spatrick return true;
19009467b48Spatrick }
19109467b48Spatrick
CC_Sparc64_Full(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)192*a96b3639Srobert static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
193*a96b3639Srobert CCValAssign::LocInfo &LocInfo,
194*a96b3639Srobert ISD::ArgFlagsTy &ArgFlags, CCState &State) {
195*a96b3639Srobert return Analyze_CC_Sparc64_Full(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
196*a96b3639Srobert State);
197*a96b3639Srobert }
198*a96b3639Srobert
CC_Sparc64_Half(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)199*a96b3639Srobert static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
200*a96b3639Srobert CCValAssign::LocInfo &LocInfo,
201*a96b3639Srobert ISD::ArgFlagsTy &ArgFlags, CCState &State) {
202*a96b3639Srobert return Analyze_CC_Sparc64_Half(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
203*a96b3639Srobert State);
204*a96b3639Srobert }
205*a96b3639Srobert
RetCC_Sparc64_Full(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)206*a96b3639Srobert static bool RetCC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
207*a96b3639Srobert CCValAssign::LocInfo &LocInfo,
208*a96b3639Srobert ISD::ArgFlagsTy &ArgFlags, CCState &State) {
209*a96b3639Srobert return Analyze_CC_Sparc64_Full(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
210*a96b3639Srobert State);
211*a96b3639Srobert }
212*a96b3639Srobert
RetCC_Sparc64_Half(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)213*a96b3639Srobert static bool RetCC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
214*a96b3639Srobert CCValAssign::LocInfo &LocInfo,
215*a96b3639Srobert ISD::ArgFlagsTy &ArgFlags, CCState &State) {
216*a96b3639Srobert return Analyze_CC_Sparc64_Half(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
217*a96b3639Srobert State);
218*a96b3639Srobert }
219*a96b3639Srobert
22009467b48Spatrick #include "SparcGenCallingConv.inc"
22109467b48Spatrick
22209467b48Spatrick // The calling conventions in SparcCallingConv.td are described in terms of the
22309467b48Spatrick // callee's register window. This function translates registers to the
22409467b48Spatrick // corresponding caller window %o register.
toCallerWindow(unsigned Reg)22509467b48Spatrick static unsigned toCallerWindow(unsigned Reg) {
22609467b48Spatrick static_assert(SP::I0 + 7 == SP::I7 && SP::O0 + 7 == SP::O7,
22709467b48Spatrick "Unexpected enum");
22809467b48Spatrick if (Reg >= SP::I0 && Reg <= SP::I7)
22909467b48Spatrick return Reg - SP::I0 + SP::O0;
23009467b48Spatrick return Reg;
23109467b48Spatrick }
23209467b48Spatrick
CanLowerReturn(CallingConv::ID CallConv,MachineFunction & MF,bool isVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,LLVMContext & Context) const233*a96b3639Srobert bool SparcTargetLowering::CanLowerReturn(
234*a96b3639Srobert CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
235*a96b3639Srobert const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
236*a96b3639Srobert SmallVector<CCValAssign, 16> RVLocs;
237*a96b3639Srobert CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
238*a96b3639Srobert return CCInfo.CheckReturn(Outs, Subtarget->is64Bit() ? RetCC_Sparc64
239*a96b3639Srobert : RetCC_Sparc32);
240*a96b3639Srobert }
241*a96b3639Srobert
24209467b48Spatrick SDValue
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const24309467b48Spatrick SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
24409467b48Spatrick bool IsVarArg,
24509467b48Spatrick const SmallVectorImpl<ISD::OutputArg> &Outs,
24609467b48Spatrick const SmallVectorImpl<SDValue> &OutVals,
24709467b48Spatrick const SDLoc &DL, SelectionDAG &DAG) const {
24809467b48Spatrick if (Subtarget->is64Bit())
24909467b48Spatrick return LowerReturn_64(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG);
25009467b48Spatrick return LowerReturn_32(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG);
25109467b48Spatrick }
25209467b48Spatrick
25309467b48Spatrick SDValue
LowerReturn_32(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const25409467b48Spatrick SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv,
25509467b48Spatrick bool IsVarArg,
25609467b48Spatrick const SmallVectorImpl<ISD::OutputArg> &Outs,
25709467b48Spatrick const SmallVectorImpl<SDValue> &OutVals,
25809467b48Spatrick const SDLoc &DL, SelectionDAG &DAG) const {
25909467b48Spatrick MachineFunction &MF = DAG.getMachineFunction();
26009467b48Spatrick
26109467b48Spatrick // CCValAssign - represent the assignment of the return value to locations.
26209467b48Spatrick SmallVector<CCValAssign, 16> RVLocs;
26309467b48Spatrick
26409467b48Spatrick // CCState - Info about the registers and stack slot.
26509467b48Spatrick CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
26609467b48Spatrick *DAG.getContext());
26709467b48Spatrick
26809467b48Spatrick // Analyze return values.
26909467b48Spatrick CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32);
27009467b48Spatrick
27109467b48Spatrick SDValue Flag;
27209467b48Spatrick SmallVector<SDValue, 4> RetOps(1, Chain);
27309467b48Spatrick // Make room for the return address offset.
27409467b48Spatrick RetOps.push_back(SDValue());
27509467b48Spatrick
27609467b48Spatrick // Copy the result values into the output registers.
27709467b48Spatrick for (unsigned i = 0, realRVLocIdx = 0;
27809467b48Spatrick i != RVLocs.size();
27909467b48Spatrick ++i, ++realRVLocIdx) {
28009467b48Spatrick CCValAssign &VA = RVLocs[i];
28109467b48Spatrick assert(VA.isRegLoc() && "Can only return in registers!");
28209467b48Spatrick
28309467b48Spatrick SDValue Arg = OutVals[realRVLocIdx];
28409467b48Spatrick
28509467b48Spatrick if (VA.needsCustom()) {
28609467b48Spatrick assert(VA.getLocVT() == MVT::v2i32);
28709467b48Spatrick // Legalize ret v2i32 -> ret 2 x i32 (Basically: do what would
28809467b48Spatrick // happen by default if this wasn't a legal type)
28909467b48Spatrick
29009467b48Spatrick SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32,
29109467b48Spatrick Arg,
29209467b48Spatrick DAG.getConstant(0, DL, getVectorIdxTy(DAG.getDataLayout())));
29309467b48Spatrick SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32,
29409467b48Spatrick Arg,
29509467b48Spatrick DAG.getConstant(1, DL, getVectorIdxTy(DAG.getDataLayout())));
29609467b48Spatrick
29709467b48Spatrick Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part0, Flag);
29809467b48Spatrick Flag = Chain.getValue(1);
29909467b48Spatrick RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
30009467b48Spatrick VA = RVLocs[++i]; // skip ahead to next loc
30109467b48Spatrick Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part1,
30209467b48Spatrick Flag);
30309467b48Spatrick } else
30409467b48Spatrick Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Flag);
30509467b48Spatrick
30609467b48Spatrick // Guarantee that all emitted copies are stuck together with flags.
30709467b48Spatrick Flag = Chain.getValue(1);
30809467b48Spatrick RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
30909467b48Spatrick }
31009467b48Spatrick
31109467b48Spatrick unsigned RetAddrOffset = 8; // Call Inst + Delay Slot
31209467b48Spatrick // If the function returns a struct, copy the SRetReturnReg to I0
31309467b48Spatrick if (MF.getFunction().hasStructRetAttr()) {
31409467b48Spatrick SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
315097a140dSpatrick Register Reg = SFI->getSRetReturnReg();
31609467b48Spatrick if (!Reg)
31709467b48Spatrick llvm_unreachable("sret virtual register not created in the entry block");
31809467b48Spatrick auto PtrVT = getPointerTy(DAG.getDataLayout());
31909467b48Spatrick SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, PtrVT);
32009467b48Spatrick Chain = DAG.getCopyToReg(Chain, DL, SP::I0, Val, Flag);
32109467b48Spatrick Flag = Chain.getValue(1);
32209467b48Spatrick RetOps.push_back(DAG.getRegister(SP::I0, PtrVT));
32309467b48Spatrick RetAddrOffset = 12; // CallInst + Delay Slot + Unimp
32409467b48Spatrick }
32509467b48Spatrick
32609467b48Spatrick RetOps[0] = Chain; // Update chain.
32709467b48Spatrick RetOps[1] = DAG.getConstant(RetAddrOffset, DL, MVT::i32);
32809467b48Spatrick
32909467b48Spatrick // Add the flag if we have it.
33009467b48Spatrick if (Flag.getNode())
33109467b48Spatrick RetOps.push_back(Flag);
33209467b48Spatrick
33309467b48Spatrick return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, RetOps);
33409467b48Spatrick }
33509467b48Spatrick
33609467b48Spatrick // Lower return values for the 64-bit ABI.
33709467b48Spatrick // Return values are passed the exactly the same way as function arguments.
33809467b48Spatrick SDValue
LowerReturn_64(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const33909467b48Spatrick SparcTargetLowering::LowerReturn_64(SDValue Chain, CallingConv::ID CallConv,
34009467b48Spatrick bool IsVarArg,
34109467b48Spatrick const SmallVectorImpl<ISD::OutputArg> &Outs,
34209467b48Spatrick const SmallVectorImpl<SDValue> &OutVals,
34309467b48Spatrick const SDLoc &DL, SelectionDAG &DAG) const {
34409467b48Spatrick // CCValAssign - represent the assignment of the return value to locations.
34509467b48Spatrick SmallVector<CCValAssign, 16> RVLocs;
34609467b48Spatrick
34709467b48Spatrick // CCState - Info about the registers and stack slot.
34809467b48Spatrick CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
34909467b48Spatrick *DAG.getContext());
35009467b48Spatrick
35109467b48Spatrick // Analyze return values.
35209467b48Spatrick CCInfo.AnalyzeReturn(Outs, RetCC_Sparc64);
35309467b48Spatrick
35409467b48Spatrick SDValue Flag;
35509467b48Spatrick SmallVector<SDValue, 4> RetOps(1, Chain);
35609467b48Spatrick
35709467b48Spatrick // The second operand on the return instruction is the return address offset.
35809467b48Spatrick // The return address is always %i7+8 with the 64-bit ABI.
35909467b48Spatrick RetOps.push_back(DAG.getConstant(8, DL, MVT::i32));
36009467b48Spatrick
36109467b48Spatrick // Copy the result values into the output registers.
36209467b48Spatrick for (unsigned i = 0; i != RVLocs.size(); ++i) {
36309467b48Spatrick CCValAssign &VA = RVLocs[i];
36409467b48Spatrick assert(VA.isRegLoc() && "Can only return in registers!");
36509467b48Spatrick SDValue OutVal = OutVals[i];
36609467b48Spatrick
36709467b48Spatrick // Integer return values must be sign or zero extended by the callee.
36809467b48Spatrick switch (VA.getLocInfo()) {
36909467b48Spatrick case CCValAssign::Full: break;
37009467b48Spatrick case CCValAssign::SExt:
37109467b48Spatrick OutVal = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), OutVal);
37209467b48Spatrick break;
37309467b48Spatrick case CCValAssign::ZExt:
37409467b48Spatrick OutVal = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), OutVal);
37509467b48Spatrick break;
37609467b48Spatrick case CCValAssign::AExt:
37709467b48Spatrick OutVal = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), OutVal);
37809467b48Spatrick break;
37909467b48Spatrick default:
38009467b48Spatrick llvm_unreachable("Unknown loc info!");
38109467b48Spatrick }
38209467b48Spatrick
38309467b48Spatrick // The custom bit on an i32 return value indicates that it should be passed
38409467b48Spatrick // in the high bits of the register.
38509467b48Spatrick if (VA.getValVT() == MVT::i32 && VA.needsCustom()) {
38609467b48Spatrick OutVal = DAG.getNode(ISD::SHL, DL, MVT::i64, OutVal,
38709467b48Spatrick DAG.getConstant(32, DL, MVT::i32));
38809467b48Spatrick
38909467b48Spatrick // The next value may go in the low bits of the same register.
39009467b48Spatrick // Handle both at once.
39109467b48Spatrick if (i+1 < RVLocs.size() && RVLocs[i+1].getLocReg() == VA.getLocReg()) {
39209467b48Spatrick SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, OutVals[i+1]);
39309467b48Spatrick OutVal = DAG.getNode(ISD::OR, DL, MVT::i64, OutVal, NV);
39409467b48Spatrick // Skip the next value, it's already done.
39509467b48Spatrick ++i;
39609467b48Spatrick }
39709467b48Spatrick }
39809467b48Spatrick
39909467b48Spatrick Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVal, Flag);
40009467b48Spatrick
40109467b48Spatrick // Guarantee that all emitted copies are stuck together with flags.
40209467b48Spatrick Flag = Chain.getValue(1);
40309467b48Spatrick RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
40409467b48Spatrick }
40509467b48Spatrick
40609467b48Spatrick RetOps[0] = Chain; // Update chain.
40709467b48Spatrick
40809467b48Spatrick // Add the flag if we have it.
40909467b48Spatrick if (Flag.getNode())
41009467b48Spatrick RetOps.push_back(Flag);
41109467b48Spatrick
41209467b48Spatrick return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, RetOps);
41309467b48Spatrick }
41409467b48Spatrick
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const41509467b48Spatrick SDValue SparcTargetLowering::LowerFormalArguments(
41609467b48Spatrick SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
41709467b48Spatrick const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
41809467b48Spatrick SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
41909467b48Spatrick if (Subtarget->is64Bit())
42009467b48Spatrick return LowerFormalArguments_64(Chain, CallConv, IsVarArg, Ins,
42109467b48Spatrick DL, DAG, InVals);
42209467b48Spatrick return LowerFormalArguments_32(Chain, CallConv, IsVarArg, Ins,
42309467b48Spatrick DL, DAG, InVals);
42409467b48Spatrick }
42509467b48Spatrick
42609467b48Spatrick /// LowerFormalArguments32 - V8 uses a very simple ABI, where all values are
42709467b48Spatrick /// passed in either one or two GPRs, including FP values. TODO: we should
42809467b48Spatrick /// pass FP values in FP registers for fastcc functions.
LowerFormalArguments_32(SDValue Chain,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & dl,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const42909467b48Spatrick SDValue SparcTargetLowering::LowerFormalArguments_32(
43009467b48Spatrick SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
43109467b48Spatrick const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
43209467b48Spatrick SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
43309467b48Spatrick MachineFunction &MF = DAG.getMachineFunction();
43409467b48Spatrick MachineRegisterInfo &RegInfo = MF.getRegInfo();
43509467b48Spatrick SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
43609467b48Spatrick
43709467b48Spatrick // Assign locations to all of the incoming arguments.
43809467b48Spatrick SmallVector<CCValAssign, 16> ArgLocs;
43909467b48Spatrick CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
44009467b48Spatrick *DAG.getContext());
44109467b48Spatrick CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32);
44209467b48Spatrick
44309467b48Spatrick const unsigned StackOffset = 92;
44409467b48Spatrick bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
44509467b48Spatrick
44609467b48Spatrick unsigned InIdx = 0;
44709467b48Spatrick for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) {
44809467b48Spatrick CCValAssign &VA = ArgLocs[i];
44909467b48Spatrick
45009467b48Spatrick if (Ins[InIdx].Flags.isSRet()) {
45109467b48Spatrick if (InIdx != 0)
45209467b48Spatrick report_fatal_error("sparc only supports sret on the first parameter");
45309467b48Spatrick // Get SRet from [%fp+64].
45409467b48Spatrick int FrameIdx = MF.getFrameInfo().CreateFixedObject(4, 64, true);
45509467b48Spatrick SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
45609467b48Spatrick SDValue Arg =
45709467b48Spatrick DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
45809467b48Spatrick InVals.push_back(Arg);
45909467b48Spatrick continue;
46009467b48Spatrick }
46109467b48Spatrick
46209467b48Spatrick if (VA.isRegLoc()) {
46309467b48Spatrick if (VA.needsCustom()) {
46409467b48Spatrick assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32);
46509467b48Spatrick
46609467b48Spatrick Register VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
46709467b48Spatrick MF.getRegInfo().addLiveIn(VA.getLocReg(), VRegHi);
46809467b48Spatrick SDValue HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32);
46909467b48Spatrick
47009467b48Spatrick assert(i+1 < e);
47109467b48Spatrick CCValAssign &NextVA = ArgLocs[++i];
47209467b48Spatrick
47309467b48Spatrick SDValue LoVal;
47409467b48Spatrick if (NextVA.isMemLoc()) {
47509467b48Spatrick int FrameIdx = MF.getFrameInfo().
47609467b48Spatrick CreateFixedObject(4, StackOffset+NextVA.getLocMemOffset(),true);
47709467b48Spatrick SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
47809467b48Spatrick LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
47909467b48Spatrick } else {
480097a140dSpatrick Register loReg = MF.addLiveIn(NextVA.getLocReg(),
48109467b48Spatrick &SP::IntRegsRegClass);
48209467b48Spatrick LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32);
48309467b48Spatrick }
48409467b48Spatrick
48509467b48Spatrick if (IsLittleEndian)
48609467b48Spatrick std::swap(LoVal, HiVal);
48709467b48Spatrick
48809467b48Spatrick SDValue WholeValue =
48909467b48Spatrick DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
49009467b48Spatrick WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), WholeValue);
49109467b48Spatrick InVals.push_back(WholeValue);
49209467b48Spatrick continue;
49309467b48Spatrick }
49409467b48Spatrick Register VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
49509467b48Spatrick MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg);
49609467b48Spatrick SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
49709467b48Spatrick if (VA.getLocVT() == MVT::f32)
49809467b48Spatrick Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
49909467b48Spatrick else if (VA.getLocVT() != MVT::i32) {
50009467b48Spatrick Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
50109467b48Spatrick DAG.getValueType(VA.getLocVT()));
50209467b48Spatrick Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
50309467b48Spatrick }
50409467b48Spatrick InVals.push_back(Arg);
50509467b48Spatrick continue;
50609467b48Spatrick }
50709467b48Spatrick
50809467b48Spatrick assert(VA.isMemLoc());
50909467b48Spatrick
51009467b48Spatrick unsigned Offset = VA.getLocMemOffset()+StackOffset;
51109467b48Spatrick auto PtrVT = getPointerTy(DAG.getDataLayout());
51209467b48Spatrick
51309467b48Spatrick if (VA.needsCustom()) {
51409467b48Spatrick assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32);
51509467b48Spatrick // If it is double-word aligned, just load.
51609467b48Spatrick if (Offset % 8 == 0) {
51709467b48Spatrick int FI = MF.getFrameInfo().CreateFixedObject(8,
51809467b48Spatrick Offset,
51909467b48Spatrick true);
52009467b48Spatrick SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
52109467b48Spatrick SDValue Load =
52209467b48Spatrick DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
52309467b48Spatrick InVals.push_back(Load);
52409467b48Spatrick continue;
52509467b48Spatrick }
52609467b48Spatrick
52709467b48Spatrick int FI = MF.getFrameInfo().CreateFixedObject(4,
52809467b48Spatrick Offset,
52909467b48Spatrick true);
53009467b48Spatrick SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
53109467b48Spatrick SDValue HiVal =
53209467b48Spatrick DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
53309467b48Spatrick int FI2 = MF.getFrameInfo().CreateFixedObject(4,
53409467b48Spatrick Offset+4,
53509467b48Spatrick true);
53609467b48Spatrick SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT);
53709467b48Spatrick
53809467b48Spatrick SDValue LoVal =
53909467b48Spatrick DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo());
54009467b48Spatrick
54109467b48Spatrick if (IsLittleEndian)
54209467b48Spatrick std::swap(LoVal, HiVal);
54309467b48Spatrick
54409467b48Spatrick SDValue WholeValue =
54509467b48Spatrick DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
54609467b48Spatrick WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue);
54709467b48Spatrick InVals.push_back(WholeValue);
54809467b48Spatrick continue;
54909467b48Spatrick }
55009467b48Spatrick
55109467b48Spatrick int FI = MF.getFrameInfo().CreateFixedObject(4,
55209467b48Spatrick Offset,
55309467b48Spatrick true);
55409467b48Spatrick SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
55509467b48Spatrick SDValue Load ;
55609467b48Spatrick if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) {
55709467b48Spatrick Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
55809467b48Spatrick } else if (VA.getValVT() == MVT::f128) {
55909467b48Spatrick report_fatal_error("SPARCv8 does not handle f128 in calls; "
56009467b48Spatrick "pass indirectly");
56109467b48Spatrick } else {
56209467b48Spatrick // We shouldn't see any other value types here.
56309467b48Spatrick llvm_unreachable("Unexpected ValVT encountered in frame lowering.");
56409467b48Spatrick }
56509467b48Spatrick InVals.push_back(Load);
56609467b48Spatrick }
56709467b48Spatrick
56809467b48Spatrick if (MF.getFunction().hasStructRetAttr()) {
56909467b48Spatrick // Copy the SRet Argument to SRetReturnReg.
57009467b48Spatrick SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
571097a140dSpatrick Register Reg = SFI->getSRetReturnReg();
57209467b48Spatrick if (!Reg) {
57309467b48Spatrick Reg = MF.getRegInfo().createVirtualRegister(&SP::IntRegsRegClass);
57409467b48Spatrick SFI->setSRetReturnReg(Reg);
57509467b48Spatrick }
57609467b48Spatrick SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]);
57709467b48Spatrick Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);
57809467b48Spatrick }
57909467b48Spatrick
58009467b48Spatrick // Store remaining ArgRegs to the stack if this is a varargs function.
58109467b48Spatrick if (isVarArg) {
58209467b48Spatrick static const MCPhysReg ArgRegs[] = {
58309467b48Spatrick SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
58409467b48Spatrick };
58509467b48Spatrick unsigned NumAllocated = CCInfo.getFirstUnallocated(ArgRegs);
58609467b48Spatrick const MCPhysReg *CurArgReg = ArgRegs+NumAllocated, *ArgRegEnd = ArgRegs+6;
58709467b48Spatrick unsigned ArgOffset = CCInfo.getNextStackOffset();
58809467b48Spatrick if (NumAllocated == 6)
58909467b48Spatrick ArgOffset += StackOffset;
59009467b48Spatrick else {
59109467b48Spatrick assert(!ArgOffset);
59209467b48Spatrick ArgOffset = 68+4*NumAllocated;
59309467b48Spatrick }
59409467b48Spatrick
59509467b48Spatrick // Remember the vararg offset for the va_start implementation.
59609467b48Spatrick FuncInfo->setVarArgsFrameOffset(ArgOffset);
59709467b48Spatrick
59809467b48Spatrick std::vector<SDValue> OutChains;
59909467b48Spatrick
60009467b48Spatrick for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
60109467b48Spatrick Register VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
60209467b48Spatrick MF.getRegInfo().addLiveIn(*CurArgReg, VReg);
60309467b48Spatrick SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32);
60409467b48Spatrick
60509467b48Spatrick int FrameIdx = MF.getFrameInfo().CreateFixedObject(4, ArgOffset,
60609467b48Spatrick true);
60709467b48Spatrick SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
60809467b48Spatrick
60909467b48Spatrick OutChains.push_back(
61009467b48Spatrick DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, MachinePointerInfo()));
61109467b48Spatrick ArgOffset += 4;
61209467b48Spatrick }
61309467b48Spatrick
61409467b48Spatrick if (!OutChains.empty()) {
61509467b48Spatrick OutChains.push_back(Chain);
61609467b48Spatrick Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
61709467b48Spatrick }
61809467b48Spatrick }
61909467b48Spatrick
62009467b48Spatrick return Chain;
62109467b48Spatrick }
62209467b48Spatrick
62309467b48Spatrick // Lower formal arguments for the 64 bit ABI.
LowerFormalArguments_64(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const62409467b48Spatrick SDValue SparcTargetLowering::LowerFormalArguments_64(
62509467b48Spatrick SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
62609467b48Spatrick const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
62709467b48Spatrick SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
62809467b48Spatrick MachineFunction &MF = DAG.getMachineFunction();
62909467b48Spatrick
63009467b48Spatrick // Analyze arguments according to CC_Sparc64.
63109467b48Spatrick SmallVector<CCValAssign, 16> ArgLocs;
63209467b48Spatrick CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
63309467b48Spatrick *DAG.getContext());
63409467b48Spatrick CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc64);
63509467b48Spatrick
63609467b48Spatrick // The argument array begins at %fp+BIAS+128, after the register save area.
63709467b48Spatrick const unsigned ArgArea = 128;
63809467b48Spatrick
63909467b48Spatrick for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
64009467b48Spatrick CCValAssign &VA = ArgLocs[i];
64109467b48Spatrick if (VA.isRegLoc()) {
64209467b48Spatrick // This argument is passed in a register.
64309467b48Spatrick // All integer register arguments are promoted by the caller to i64.
64409467b48Spatrick
64509467b48Spatrick // Create a virtual register for the promoted live-in value.
646097a140dSpatrick Register VReg = MF.addLiveIn(VA.getLocReg(),
64709467b48Spatrick getRegClassFor(VA.getLocVT()));
64809467b48Spatrick SDValue Arg = DAG.getCopyFromReg(Chain, DL, VReg, VA.getLocVT());
64909467b48Spatrick
65009467b48Spatrick // Get the high bits for i32 struct elements.
65109467b48Spatrick if (VA.getValVT() == MVT::i32 && VA.needsCustom())
65209467b48Spatrick Arg = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), Arg,
65309467b48Spatrick DAG.getConstant(32, DL, MVT::i32));
65409467b48Spatrick
65509467b48Spatrick // The caller promoted the argument, so insert an Assert?ext SDNode so we
65609467b48Spatrick // won't promote the value again in this function.
65709467b48Spatrick switch (VA.getLocInfo()) {
65809467b48Spatrick case CCValAssign::SExt:
65909467b48Spatrick Arg = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Arg,
66009467b48Spatrick DAG.getValueType(VA.getValVT()));
66109467b48Spatrick break;
66209467b48Spatrick case CCValAssign::ZExt:
66309467b48Spatrick Arg = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Arg,
66409467b48Spatrick DAG.getValueType(VA.getValVT()));
66509467b48Spatrick break;
66609467b48Spatrick default:
66709467b48Spatrick break;
66809467b48Spatrick }
66909467b48Spatrick
67009467b48Spatrick // Truncate the register down to the argument type.
67109467b48Spatrick if (VA.isExtInLoc())
67209467b48Spatrick Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg);
67309467b48Spatrick
67409467b48Spatrick InVals.push_back(Arg);
67509467b48Spatrick continue;
67609467b48Spatrick }
67709467b48Spatrick
67809467b48Spatrick // The registers are exhausted. This argument was passed on the stack.
67909467b48Spatrick assert(VA.isMemLoc());
68009467b48Spatrick // The CC_Sparc64_Full/Half functions compute stack offsets relative to the
68109467b48Spatrick // beginning of the arguments area at %fp+BIAS+128.
68209467b48Spatrick unsigned Offset = VA.getLocMemOffset() + ArgArea;
68309467b48Spatrick unsigned ValSize = VA.getValVT().getSizeInBits() / 8;
68409467b48Spatrick // Adjust offset for extended arguments, SPARC is big-endian.
68509467b48Spatrick // The caller will have written the full slot with extended bytes, but we
68609467b48Spatrick // prefer our own extending loads.
68709467b48Spatrick if (VA.isExtInLoc())
68809467b48Spatrick Offset += 8 - ValSize;
68909467b48Spatrick int FI = MF.getFrameInfo().CreateFixedObject(ValSize, Offset, true);
69009467b48Spatrick InVals.push_back(
69109467b48Spatrick DAG.getLoad(VA.getValVT(), DL, Chain,
69209467b48Spatrick DAG.getFrameIndex(FI, getPointerTy(MF.getDataLayout())),
69309467b48Spatrick MachinePointerInfo::getFixedStack(MF, FI)));
69409467b48Spatrick }
69509467b48Spatrick
69609467b48Spatrick if (!IsVarArg)
69709467b48Spatrick return Chain;
69809467b48Spatrick
69909467b48Spatrick // This function takes variable arguments, some of which may have been passed
70009467b48Spatrick // in registers %i0-%i5. Variable floating point arguments are never passed
70109467b48Spatrick // in floating point registers. They go on %i0-%i5 or on the stack like
70209467b48Spatrick // integer arguments.
70309467b48Spatrick //
70409467b48Spatrick // The va_start intrinsic needs to know the offset to the first variable
70509467b48Spatrick // argument.
70609467b48Spatrick unsigned ArgOffset = CCInfo.getNextStackOffset();
70709467b48Spatrick SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
70809467b48Spatrick // Skip the 128 bytes of register save area.
70909467b48Spatrick FuncInfo->setVarArgsFrameOffset(ArgOffset + ArgArea +
71009467b48Spatrick Subtarget->getStackPointerBias());
71109467b48Spatrick
71209467b48Spatrick // Save the variable arguments that were passed in registers.
71309467b48Spatrick // The caller is required to reserve stack space for 6 arguments regardless
71409467b48Spatrick // of how many arguments were actually passed.
71509467b48Spatrick SmallVector<SDValue, 8> OutChains;
71609467b48Spatrick for (; ArgOffset < 6*8; ArgOffset += 8) {
717097a140dSpatrick Register VReg = MF.addLiveIn(SP::I0 + ArgOffset/8, &SP::I64RegsRegClass);
71809467b48Spatrick SDValue VArg = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64);
71909467b48Spatrick int FI = MF.getFrameInfo().CreateFixedObject(8, ArgOffset + ArgArea, true);
72009467b48Spatrick auto PtrVT = getPointerTy(MF.getDataLayout());
72109467b48Spatrick OutChains.push_back(
72209467b48Spatrick DAG.getStore(Chain, DL, VArg, DAG.getFrameIndex(FI, PtrVT),
72309467b48Spatrick MachinePointerInfo::getFixedStack(MF, FI)));
72409467b48Spatrick }
72509467b48Spatrick
72609467b48Spatrick if (!OutChains.empty())
72709467b48Spatrick Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
72809467b48Spatrick
72909467b48Spatrick return Chain;
73009467b48Spatrick }
73109467b48Spatrick
73209467b48Spatrick SDValue
LowerCall(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const73309467b48Spatrick SparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
73409467b48Spatrick SmallVectorImpl<SDValue> &InVals) const {
73509467b48Spatrick if (Subtarget->is64Bit())
73609467b48Spatrick return LowerCall_64(CLI, InVals);
73709467b48Spatrick return LowerCall_32(CLI, InVals);
73809467b48Spatrick }
73909467b48Spatrick
hasReturnsTwiceAttr(SelectionDAG & DAG,SDValue Callee,const CallBase * Call)74009467b48Spatrick static bool hasReturnsTwiceAttr(SelectionDAG &DAG, SDValue Callee,
741097a140dSpatrick const CallBase *Call) {
742097a140dSpatrick if (Call)
743097a140dSpatrick return Call->hasFnAttr(Attribute::ReturnsTwice);
74409467b48Spatrick
74509467b48Spatrick const Function *CalleeFn = nullptr;
74609467b48Spatrick if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
74709467b48Spatrick CalleeFn = dyn_cast<Function>(G->getGlobal());
74809467b48Spatrick } else if (ExternalSymbolSDNode *E =
74909467b48Spatrick dyn_cast<ExternalSymbolSDNode>(Callee)) {
75009467b48Spatrick const Function &Fn = DAG.getMachineFunction().getFunction();
75109467b48Spatrick const Module *M = Fn.getParent();
75209467b48Spatrick const char *CalleeName = E->getSymbol();
75309467b48Spatrick CalleeFn = M->getFunction(CalleeName);
75409467b48Spatrick }
75509467b48Spatrick
75609467b48Spatrick if (!CalleeFn)
75709467b48Spatrick return false;
75809467b48Spatrick return CalleeFn->hasFnAttribute(Attribute::ReturnsTwice);
75909467b48Spatrick }
76009467b48Spatrick
761*a96b3639Srobert /// IsEligibleForTailCallOptimization - Check whether the call is eligible
762*a96b3639Srobert /// for tail call optimization.
IsEligibleForTailCallOptimization(CCState & CCInfo,CallLoweringInfo & CLI,MachineFunction & MF) const763*a96b3639Srobert bool SparcTargetLowering::IsEligibleForTailCallOptimization(
764*a96b3639Srobert CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF) const {
765*a96b3639Srobert
766*a96b3639Srobert auto &Outs = CLI.Outs;
767*a96b3639Srobert auto &Caller = MF.getFunction();
768*a96b3639Srobert
769*a96b3639Srobert // Do not tail call opt functions with "disable-tail-calls" attribute.
770*a96b3639Srobert if (Caller.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
771*a96b3639Srobert return false;
772*a96b3639Srobert
773*a96b3639Srobert // Do not tail call opt if the stack is used to pass parameters.
774*a96b3639Srobert // 64-bit targets have a slightly higher limit since the ABI requires
775*a96b3639Srobert // to allocate some space even when all the parameters fit inside registers.
776*a96b3639Srobert unsigned StackOffsetLimit = Subtarget->is64Bit() ? 48 : 0;
777*a96b3639Srobert if (CCInfo.getNextStackOffset() > StackOffsetLimit)
778*a96b3639Srobert return false;
779*a96b3639Srobert
780*a96b3639Srobert // Do not tail call opt if either the callee or caller returns
781*a96b3639Srobert // a struct and the other does not.
782*a96b3639Srobert if (!Outs.empty() && Caller.hasStructRetAttr() != Outs[0].Flags.isSRet())
783*a96b3639Srobert return false;
784*a96b3639Srobert
785*a96b3639Srobert // Byval parameters hand the function a pointer directly into the stack area
786*a96b3639Srobert // we want to reuse during a tail call.
787*a96b3639Srobert for (auto &Arg : Outs)
788*a96b3639Srobert if (Arg.Flags.isByVal())
789*a96b3639Srobert return false;
790*a96b3639Srobert
791*a96b3639Srobert return true;
792*a96b3639Srobert }
793*a96b3639Srobert
79409467b48Spatrick // Lower a call for the 32-bit ABI.
79509467b48Spatrick SDValue
LowerCall_32(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const79609467b48Spatrick SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
79709467b48Spatrick SmallVectorImpl<SDValue> &InVals) const {
79809467b48Spatrick SelectionDAG &DAG = CLI.DAG;
79909467b48Spatrick SDLoc &dl = CLI.DL;
80009467b48Spatrick SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
80109467b48Spatrick SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
80209467b48Spatrick SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
80309467b48Spatrick SDValue Chain = CLI.Chain;
80409467b48Spatrick SDValue Callee = CLI.Callee;
80509467b48Spatrick bool &isTailCall = CLI.IsTailCall;
80609467b48Spatrick CallingConv::ID CallConv = CLI.CallConv;
80709467b48Spatrick bool isVarArg = CLI.IsVarArg;
80809467b48Spatrick
80909467b48Spatrick // Analyze operands of the call, assigning locations to each operand.
81009467b48Spatrick SmallVector<CCValAssign, 16> ArgLocs;
81109467b48Spatrick CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
81209467b48Spatrick *DAG.getContext());
81309467b48Spatrick CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32);
81409467b48Spatrick
815*a96b3639Srobert isTailCall = isTailCall && IsEligibleForTailCallOptimization(
816*a96b3639Srobert CCInfo, CLI, DAG.getMachineFunction());
817*a96b3639Srobert
81809467b48Spatrick // Get the size of the outgoing arguments stack space requirement.
81909467b48Spatrick unsigned ArgsSize = CCInfo.getNextStackOffset();
82009467b48Spatrick
82109467b48Spatrick // Keep stack frames 8-byte aligned.
82209467b48Spatrick ArgsSize = (ArgsSize+7) & ~7;
82309467b48Spatrick
82409467b48Spatrick MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
82509467b48Spatrick
82609467b48Spatrick // Create local copies for byval args.
82709467b48Spatrick SmallVector<SDValue, 8> ByValArgs;
82809467b48Spatrick for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
82909467b48Spatrick ISD::ArgFlagsTy Flags = Outs[i].Flags;
83009467b48Spatrick if (!Flags.isByVal())
83109467b48Spatrick continue;
83209467b48Spatrick
83309467b48Spatrick SDValue Arg = OutVals[i];
83409467b48Spatrick unsigned Size = Flags.getByValSize();
835097a140dSpatrick Align Alignment = Flags.getNonZeroByValAlign();
83609467b48Spatrick
83709467b48Spatrick if (Size > 0U) {
838097a140dSpatrick int FI = MFI.CreateStackObject(Size, Alignment, false);
83909467b48Spatrick SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
84009467b48Spatrick SDValue SizeNode = DAG.getConstant(Size, dl, MVT::i32);
84109467b48Spatrick
842097a140dSpatrick Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Alignment,
84309467b48Spatrick false, // isVolatile,
84409467b48Spatrick (Size <= 32), // AlwaysInline if size <= 32,
84509467b48Spatrick false, // isTailCall
84609467b48Spatrick MachinePointerInfo(), MachinePointerInfo());
84709467b48Spatrick ByValArgs.push_back(FIPtr);
84809467b48Spatrick }
84909467b48Spatrick else {
85009467b48Spatrick SDValue nullVal;
85109467b48Spatrick ByValArgs.push_back(nullVal);
85209467b48Spatrick }
85309467b48Spatrick }
85409467b48Spatrick
855*a96b3639Srobert assert(!isTailCall || ArgsSize == 0);
856*a96b3639Srobert
857*a96b3639Srobert if (!isTailCall)
85809467b48Spatrick Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, dl);
85909467b48Spatrick
86009467b48Spatrick SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
86109467b48Spatrick SmallVector<SDValue, 8> MemOpChains;
86209467b48Spatrick
86309467b48Spatrick const unsigned StackOffset = 92;
86409467b48Spatrick bool hasStructRetAttr = false;
86509467b48Spatrick unsigned SRetArgSize = 0;
86609467b48Spatrick // Walk the register/memloc assignments, inserting copies/loads.
86709467b48Spatrick for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size();
86809467b48Spatrick i != e;
86909467b48Spatrick ++i, ++realArgIdx) {
87009467b48Spatrick CCValAssign &VA = ArgLocs[i];
87109467b48Spatrick SDValue Arg = OutVals[realArgIdx];
87209467b48Spatrick
87309467b48Spatrick ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags;
87409467b48Spatrick
87509467b48Spatrick // Use local copy if it is a byval arg.
87609467b48Spatrick if (Flags.isByVal()) {
87709467b48Spatrick Arg = ByValArgs[byvalArgIdx++];
87809467b48Spatrick if (!Arg) {
87909467b48Spatrick continue;
88009467b48Spatrick }
88109467b48Spatrick }
88209467b48Spatrick
88309467b48Spatrick // Promote the value if needed.
88409467b48Spatrick switch (VA.getLocInfo()) {
88509467b48Spatrick default: llvm_unreachable("Unknown loc info!");
88609467b48Spatrick case CCValAssign::Full: break;
88709467b48Spatrick case CCValAssign::SExt:
88809467b48Spatrick Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
88909467b48Spatrick break;
89009467b48Spatrick case CCValAssign::ZExt:
89109467b48Spatrick Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
89209467b48Spatrick break;
89309467b48Spatrick case CCValAssign::AExt:
89409467b48Spatrick Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
89509467b48Spatrick break;
89609467b48Spatrick case CCValAssign::BCvt:
89709467b48Spatrick Arg = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), Arg);
89809467b48Spatrick break;
89909467b48Spatrick }
90009467b48Spatrick
90109467b48Spatrick if (Flags.isSRet()) {
90209467b48Spatrick assert(VA.needsCustom());
903*a96b3639Srobert
904*a96b3639Srobert if (isTailCall)
905*a96b3639Srobert continue;
906*a96b3639Srobert
90709467b48Spatrick // store SRet argument in %sp+64
90809467b48Spatrick SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
90909467b48Spatrick SDValue PtrOff = DAG.getIntPtrConstant(64, dl);
91009467b48Spatrick PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
91109467b48Spatrick MemOpChains.push_back(
91209467b48Spatrick DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
91309467b48Spatrick hasStructRetAttr = true;
91409467b48Spatrick // sret only allowed on first argument
91509467b48Spatrick assert(Outs[realArgIdx].OrigArgIndex == 0);
916*a96b3639Srobert SRetArgSize =
917*a96b3639Srobert DAG.getDataLayout().getTypeAllocSize(CLI.getArgs()[0].IndirectType);
91809467b48Spatrick continue;
91909467b48Spatrick }
92009467b48Spatrick
92109467b48Spatrick if (VA.needsCustom()) {
92209467b48Spatrick assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32);
92309467b48Spatrick
92409467b48Spatrick if (VA.isMemLoc()) {
92509467b48Spatrick unsigned Offset = VA.getLocMemOffset() + StackOffset;
92609467b48Spatrick // if it is double-word aligned, just store.
92709467b48Spatrick if (Offset % 8 == 0) {
92809467b48Spatrick SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
92909467b48Spatrick SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);
93009467b48Spatrick PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
93109467b48Spatrick MemOpChains.push_back(
93209467b48Spatrick DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
93309467b48Spatrick continue;
93409467b48Spatrick }
93509467b48Spatrick }
93609467b48Spatrick
93709467b48Spatrick if (VA.getLocVT() == MVT::f64) {
93809467b48Spatrick // Move from the float value from float registers into the
93909467b48Spatrick // integer registers.
94009467b48Spatrick if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Arg))
94109467b48Spatrick Arg = bitcastConstantFPToInt(C, dl, DAG);
94209467b48Spatrick else
94309467b48Spatrick Arg = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, Arg);
94409467b48Spatrick }
94509467b48Spatrick
94609467b48Spatrick SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32,
94709467b48Spatrick Arg,
94809467b48Spatrick DAG.getConstant(0, dl, getVectorIdxTy(DAG.getDataLayout())));
94909467b48Spatrick SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32,
95009467b48Spatrick Arg,
95109467b48Spatrick DAG.getConstant(1, dl, getVectorIdxTy(DAG.getDataLayout())));
95209467b48Spatrick
95309467b48Spatrick if (VA.isRegLoc()) {
95409467b48Spatrick RegsToPass.push_back(std::make_pair(VA.getLocReg(), Part0));
95509467b48Spatrick assert(i+1 != e);
95609467b48Spatrick CCValAssign &NextVA = ArgLocs[++i];
95709467b48Spatrick if (NextVA.isRegLoc()) {
95809467b48Spatrick RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Part1));
95909467b48Spatrick } else {
96009467b48Spatrick // Store the second part in stack.
96109467b48Spatrick unsigned Offset = NextVA.getLocMemOffset() + StackOffset;
96209467b48Spatrick SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
96309467b48Spatrick SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);
96409467b48Spatrick PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
96509467b48Spatrick MemOpChains.push_back(
96609467b48Spatrick DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo()));
96709467b48Spatrick }
96809467b48Spatrick } else {
96909467b48Spatrick unsigned Offset = VA.getLocMemOffset() + StackOffset;
97009467b48Spatrick // Store the first part.
97109467b48Spatrick SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
97209467b48Spatrick SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);
97309467b48Spatrick PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
97409467b48Spatrick MemOpChains.push_back(
97509467b48Spatrick DAG.getStore(Chain, dl, Part0, PtrOff, MachinePointerInfo()));
97609467b48Spatrick // Store the second part.
97709467b48Spatrick PtrOff = DAG.getIntPtrConstant(Offset + 4, dl);
97809467b48Spatrick PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
97909467b48Spatrick MemOpChains.push_back(
98009467b48Spatrick DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo()));
98109467b48Spatrick }
98209467b48Spatrick continue;
98309467b48Spatrick }
98409467b48Spatrick
98509467b48Spatrick // Arguments that can be passed on register must be kept at
98609467b48Spatrick // RegsToPass vector
98709467b48Spatrick if (VA.isRegLoc()) {
98809467b48Spatrick if (VA.getLocVT() != MVT::f32) {
98909467b48Spatrick RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
99009467b48Spatrick continue;
99109467b48Spatrick }
99209467b48Spatrick Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg);
99309467b48Spatrick RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
99409467b48Spatrick continue;
99509467b48Spatrick }
99609467b48Spatrick
99709467b48Spatrick assert(VA.isMemLoc());
99809467b48Spatrick
99909467b48Spatrick // Create a store off the stack pointer for this argument.
100009467b48Spatrick SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
100109467b48Spatrick SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() + StackOffset,
100209467b48Spatrick dl);
100309467b48Spatrick PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
100409467b48Spatrick MemOpChains.push_back(
100509467b48Spatrick DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
100609467b48Spatrick }
100709467b48Spatrick
100809467b48Spatrick
100909467b48Spatrick // Emit all stores, make sure the occur before any copies into physregs.
101009467b48Spatrick if (!MemOpChains.empty())
101109467b48Spatrick Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
101209467b48Spatrick
101309467b48Spatrick // Build a sequence of copy-to-reg nodes chained together with token
101409467b48Spatrick // chain and flag operands which copy the outgoing args into registers.
101509467b48Spatrick // The InFlag in necessary since all emitted instructions must be
101609467b48Spatrick // stuck together.
101709467b48Spatrick SDValue InFlag;
101809467b48Spatrick for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1019*a96b3639Srobert Register Reg = RegsToPass[i].first;
1020*a96b3639Srobert if (!isTailCall)
1021*a96b3639Srobert Reg = toCallerWindow(Reg);
102209467b48Spatrick Chain = DAG.getCopyToReg(Chain, dl, Reg, RegsToPass[i].second, InFlag);
102309467b48Spatrick InFlag = Chain.getValue(1);
102409467b48Spatrick }
102509467b48Spatrick
1026097a140dSpatrick bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CB);
102709467b48Spatrick
102809467b48Spatrick // If the callee is a GlobalAddress node (quite common, every direct call is)
102909467b48Spatrick // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
103009467b48Spatrick // Likewise ExternalSymbol -> TargetExternalSymbol.
1031a0747c9fSpatrick unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30
1032a0747c9fSpatrick : SparcMCExpr::VK_Sparc_WDISP30;
103309467b48Spatrick if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
103409467b48Spatrick Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF);
103509467b48Spatrick else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
103609467b48Spatrick Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF);
103709467b48Spatrick
103809467b48Spatrick // Returns a chain & a flag for retval copy to use
103909467b48Spatrick SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
104009467b48Spatrick SmallVector<SDValue, 8> Ops;
104109467b48Spatrick Ops.push_back(Chain);
104209467b48Spatrick Ops.push_back(Callee);
104309467b48Spatrick if (hasStructRetAttr)
104409467b48Spatrick Ops.push_back(DAG.getTargetConstant(SRetArgSize, dl, MVT::i32));
1045*a96b3639Srobert for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1046*a96b3639Srobert Register Reg = RegsToPass[i].first;
1047*a96b3639Srobert if (!isTailCall)
1048*a96b3639Srobert Reg = toCallerWindow(Reg);
1049*a96b3639Srobert Ops.push_back(DAG.getRegister(Reg, RegsToPass[i].second.getValueType()));
1050*a96b3639Srobert }
105109467b48Spatrick
105209467b48Spatrick // Add a register mask operand representing the call-preserved registers.
105309467b48Spatrick const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo();
105409467b48Spatrick const uint32_t *Mask =
105509467b48Spatrick ((hasReturnsTwice)
105609467b48Spatrick ? TRI->getRTCallPreservedMask(CallConv)
105709467b48Spatrick : TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv));
105809467b48Spatrick assert(Mask && "Missing call preserved mask for calling convention");
105909467b48Spatrick Ops.push_back(DAG.getRegisterMask(Mask));
106009467b48Spatrick
106109467b48Spatrick if (InFlag.getNode())
106209467b48Spatrick Ops.push_back(InFlag);
106309467b48Spatrick
1064*a96b3639Srobert if (isTailCall) {
1065*a96b3639Srobert DAG.getMachineFunction().getFrameInfo().setHasTailCall();
1066*a96b3639Srobert return DAG.getNode(SPISD::TAIL_CALL, dl, MVT::Other, Ops);
1067*a96b3639Srobert }
1068*a96b3639Srobert
106909467b48Spatrick Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, Ops);
107009467b48Spatrick InFlag = Chain.getValue(1);
107109467b48Spatrick
1072*a96b3639Srobert Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InFlag, dl);
107309467b48Spatrick InFlag = Chain.getValue(1);
107409467b48Spatrick
107509467b48Spatrick // Assign locations to each value returned by this call.
107609467b48Spatrick SmallVector<CCValAssign, 16> RVLocs;
107709467b48Spatrick CCState RVInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
107809467b48Spatrick *DAG.getContext());
107909467b48Spatrick
108009467b48Spatrick RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32);
108109467b48Spatrick
108209467b48Spatrick // Copy all of the result registers out of their specified physreg.
108309467b48Spatrick for (unsigned i = 0; i != RVLocs.size(); ++i) {
1084*a96b3639Srobert assert(RVLocs[i].isRegLoc() && "Can only return in registers!");
108509467b48Spatrick if (RVLocs[i].getLocVT() == MVT::v2i32) {
108609467b48Spatrick SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2i32);
108709467b48Spatrick SDValue Lo = DAG.getCopyFromReg(
108809467b48Spatrick Chain, dl, toCallerWindow(RVLocs[i++].getLocReg()), MVT::i32, InFlag);
108909467b48Spatrick Chain = Lo.getValue(1);
109009467b48Spatrick InFlag = Lo.getValue(2);
109109467b48Spatrick Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Lo,
109209467b48Spatrick DAG.getConstant(0, dl, MVT::i32));
109309467b48Spatrick SDValue Hi = DAG.getCopyFromReg(
109409467b48Spatrick Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), MVT::i32, InFlag);
109509467b48Spatrick Chain = Hi.getValue(1);
109609467b48Spatrick InFlag = Hi.getValue(2);
109709467b48Spatrick Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Hi,
109809467b48Spatrick DAG.getConstant(1, dl, MVT::i32));
109909467b48Spatrick InVals.push_back(Vec);
110009467b48Spatrick } else {
110109467b48Spatrick Chain =
110209467b48Spatrick DAG.getCopyFromReg(Chain, dl, toCallerWindow(RVLocs[i].getLocReg()),
110309467b48Spatrick RVLocs[i].getValVT(), InFlag)
110409467b48Spatrick .getValue(1);
110509467b48Spatrick InFlag = Chain.getValue(2);
110609467b48Spatrick InVals.push_back(Chain.getValue(0));
110709467b48Spatrick }
110809467b48Spatrick }
110909467b48Spatrick
111009467b48Spatrick return Chain;
111109467b48Spatrick }
111209467b48Spatrick
111309467b48Spatrick // FIXME? Maybe this could be a TableGen attribute on some registers and
111409467b48Spatrick // this table could be generated automatically from RegInfo.
getRegisterByName(const char * RegName,LLT VT,const MachineFunction & MF) const111509467b48Spatrick Register SparcTargetLowering::getRegisterByName(const char* RegName, LLT VT,
111609467b48Spatrick const MachineFunction &MF) const {
1117097a140dSpatrick Register Reg = StringSwitch<Register>(RegName)
111809467b48Spatrick .Case("i0", SP::I0).Case("i1", SP::I1).Case("i2", SP::I2).Case("i3", SP::I3)
111909467b48Spatrick .Case("i4", SP::I4).Case("i5", SP::I5).Case("i6", SP::I6).Case("i7", SP::I7)
112009467b48Spatrick .Case("o0", SP::O0).Case("o1", SP::O1).Case("o2", SP::O2).Case("o3", SP::O3)
112109467b48Spatrick .Case("o4", SP::O4).Case("o5", SP::O5).Case("o6", SP::O6).Case("o7", SP::O7)
112209467b48Spatrick .Case("l0", SP::L0).Case("l1", SP::L1).Case("l2", SP::L2).Case("l3", SP::L3)
112309467b48Spatrick .Case("l4", SP::L4).Case("l5", SP::L5).Case("l6", SP::L6).Case("l7", SP::L7)
112409467b48Spatrick .Case("g0", SP::G0).Case("g1", SP::G1).Case("g2", SP::G2).Case("g3", SP::G3)
112509467b48Spatrick .Case("g4", SP::G4).Case("g5", SP::G5).Case("g6", SP::G6).Case("g7", SP::G7)
112609467b48Spatrick .Default(0);
112709467b48Spatrick
112809467b48Spatrick if (Reg)
112909467b48Spatrick return Reg;
113009467b48Spatrick
113109467b48Spatrick report_fatal_error("Invalid register name global variable");
113209467b48Spatrick }
113309467b48Spatrick
113409467b48Spatrick // Fixup floating point arguments in the ... part of a varargs call.
113509467b48Spatrick //
113609467b48Spatrick // The SPARC v9 ABI requires that floating point arguments are treated the same
113709467b48Spatrick // as integers when calling a varargs function. This does not apply to the
113809467b48Spatrick // fixed arguments that are part of the function's prototype.
113909467b48Spatrick //
114009467b48Spatrick // This function post-processes a CCValAssign array created by
114109467b48Spatrick // AnalyzeCallOperands().
fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> & ArgLocs,ArrayRef<ISD::OutputArg> Outs)114209467b48Spatrick static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs,
114309467b48Spatrick ArrayRef<ISD::OutputArg> Outs) {
114409467b48Spatrick for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1145*a96b3639Srobert CCValAssign &VA = ArgLocs[i];
114609467b48Spatrick MVT ValTy = VA.getLocVT();
114709467b48Spatrick // FIXME: What about f32 arguments? C promotes them to f64 when calling
114809467b48Spatrick // varargs functions.
114909467b48Spatrick if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128))
115009467b48Spatrick continue;
115109467b48Spatrick // The fixed arguments to a varargs function still go in FP registers.
115209467b48Spatrick if (Outs[VA.getValNo()].IsFixed)
115309467b48Spatrick continue;
115409467b48Spatrick
115509467b48Spatrick // This floating point argument should be reassigned.
115609467b48Spatrick // Determine the offset into the argument array.
1157097a140dSpatrick Register firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0;
115809467b48Spatrick unsigned argSize = (ValTy == MVT::f64) ? 8 : 16;
115909467b48Spatrick unsigned Offset = argSize * (VA.getLocReg() - firstReg);
116009467b48Spatrick assert(Offset < 16*8 && "Offset out of range, bad register enum?");
116109467b48Spatrick
116209467b48Spatrick if (Offset < 6*8) {
116309467b48Spatrick // This argument should go in %i0-%i5.
116409467b48Spatrick unsigned IReg = SP::I0 + Offset/8;
116509467b48Spatrick if (ValTy == MVT::f64)
116609467b48Spatrick // Full register, just bitconvert into i64.
1167*a96b3639Srobert VA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), IReg, MVT::i64,
1168*a96b3639Srobert CCValAssign::BCvt);
116909467b48Spatrick else {
117009467b48Spatrick assert(ValTy == MVT::f128 && "Unexpected type!");
117109467b48Spatrick // Full register, just bitconvert into i128 -- We will lower this into
117209467b48Spatrick // two i64s in LowerCall_64.
1173*a96b3639Srobert VA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), IReg,
1174*a96b3639Srobert MVT::i128, CCValAssign::BCvt);
117509467b48Spatrick }
117609467b48Spatrick } else {
117709467b48Spatrick // This needs to go to memory, we're out of integer registers.
1178*a96b3639Srobert VA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), Offset,
1179*a96b3639Srobert VA.getLocVT(), VA.getLocInfo());
118009467b48Spatrick }
118109467b48Spatrick }
118209467b48Spatrick }
118309467b48Spatrick
118409467b48Spatrick // Lower a call for the 64-bit ABI.
118509467b48Spatrick SDValue
LowerCall_64(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const118609467b48Spatrick SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
118709467b48Spatrick SmallVectorImpl<SDValue> &InVals) const {
118809467b48Spatrick SelectionDAG &DAG = CLI.DAG;
118909467b48Spatrick SDLoc DL = CLI.DL;
119009467b48Spatrick SDValue Chain = CLI.Chain;
119109467b48Spatrick auto PtrVT = getPointerTy(DAG.getDataLayout());
119209467b48Spatrick
119309467b48Spatrick // Analyze operands of the call, assigning locations to each operand.
119409467b48Spatrick SmallVector<CCValAssign, 16> ArgLocs;
119509467b48Spatrick CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs,
119609467b48Spatrick *DAG.getContext());
119709467b48Spatrick CCInfo.AnalyzeCallOperands(CLI.Outs, CC_Sparc64);
119809467b48Spatrick
1199*a96b3639Srobert CLI.IsTailCall = CLI.IsTailCall && IsEligibleForTailCallOptimization(
1200*a96b3639Srobert CCInfo, CLI, DAG.getMachineFunction());
1201*a96b3639Srobert
120209467b48Spatrick // Get the size of the outgoing arguments stack space requirement.
120309467b48Spatrick // The stack offset computed by CC_Sparc64 includes all arguments.
120409467b48Spatrick // Called functions expect 6 argument words to exist in the stack frame, used
120509467b48Spatrick // or not.
1206*a96b3639Srobert unsigned StackReserved = 6 * 8u;
1207*a96b3639Srobert unsigned ArgsSize = std::max(StackReserved, CCInfo.getNextStackOffset());
120809467b48Spatrick
120909467b48Spatrick // Keep stack frames 16-byte aligned.
121009467b48Spatrick ArgsSize = alignTo(ArgsSize, 16);
121109467b48Spatrick
121209467b48Spatrick // Varargs calls require special treatment.
121309467b48Spatrick if (CLI.IsVarArg)
121409467b48Spatrick fixupVariableFloatArgs(ArgLocs, CLI.Outs);
121509467b48Spatrick
1216*a96b3639Srobert assert(!CLI.IsTailCall || ArgsSize == StackReserved);
1217*a96b3639Srobert
121809467b48Spatrick // Adjust the stack pointer to make room for the arguments.
121909467b48Spatrick // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls
122009467b48Spatrick // with more than 6 arguments.
1221*a96b3639Srobert if (!CLI.IsTailCall)
122209467b48Spatrick Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL);
122309467b48Spatrick
122409467b48Spatrick // Collect the set of registers to pass to the function and their values.
122509467b48Spatrick // This will be emitted as a sequence of CopyToReg nodes glued to the call
122609467b48Spatrick // instruction.
1227097a140dSpatrick SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
122809467b48Spatrick
122909467b48Spatrick // Collect chains from all the memory opeations that copy arguments to the
123009467b48Spatrick // stack. They must follow the stack pointer adjustment above and precede the
123109467b48Spatrick // call instruction itself.
123209467b48Spatrick SmallVector<SDValue, 8> MemOpChains;
123309467b48Spatrick
123409467b48Spatrick for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
123509467b48Spatrick const CCValAssign &VA = ArgLocs[i];
123609467b48Spatrick SDValue Arg = CLI.OutVals[i];
123709467b48Spatrick
123809467b48Spatrick // Promote the value if needed.
123909467b48Spatrick switch (VA.getLocInfo()) {
124009467b48Spatrick default:
124109467b48Spatrick llvm_unreachable("Unknown location info!");
124209467b48Spatrick case CCValAssign::Full:
124309467b48Spatrick break;
124409467b48Spatrick case CCValAssign::SExt:
124509467b48Spatrick Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
124609467b48Spatrick break;
124709467b48Spatrick case CCValAssign::ZExt:
124809467b48Spatrick Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
124909467b48Spatrick break;
125009467b48Spatrick case CCValAssign::AExt:
125109467b48Spatrick Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
125209467b48Spatrick break;
125309467b48Spatrick case CCValAssign::BCvt:
125409467b48Spatrick // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But
125509467b48Spatrick // SPARC does not support i128 natively. Lower it into two i64, see below.
125609467b48Spatrick if (!VA.needsCustom() || VA.getValVT() != MVT::f128
125709467b48Spatrick || VA.getLocVT() != MVT::i128)
125809467b48Spatrick Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
125909467b48Spatrick break;
126009467b48Spatrick }
126109467b48Spatrick
126209467b48Spatrick if (VA.isRegLoc()) {
126309467b48Spatrick if (VA.needsCustom() && VA.getValVT() == MVT::f128
126409467b48Spatrick && VA.getLocVT() == MVT::i128) {
126509467b48Spatrick // Store and reload into the integer register reg and reg+1.
126609467b48Spatrick unsigned Offset = 8 * (VA.getLocReg() - SP::I0);
126709467b48Spatrick unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128;
126809467b48Spatrick SDValue StackPtr = DAG.getRegister(SP::O6, PtrVT);
126909467b48Spatrick SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset, DL);
127009467b48Spatrick HiPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, HiPtrOff);
127109467b48Spatrick SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8, DL);
127209467b48Spatrick LoPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, LoPtrOff);
127309467b48Spatrick
127409467b48Spatrick // Store to %sp+BIAS+128+Offset
127509467b48Spatrick SDValue Store =
127609467b48Spatrick DAG.getStore(Chain, DL, Arg, HiPtrOff, MachinePointerInfo());
127709467b48Spatrick // Load into Reg and Reg+1
127809467b48Spatrick SDValue Hi64 =
127909467b48Spatrick DAG.getLoad(MVT::i64, DL, Store, HiPtrOff, MachinePointerInfo());
128009467b48Spatrick SDValue Lo64 =
128109467b48Spatrick DAG.getLoad(MVT::i64, DL, Store, LoPtrOff, MachinePointerInfo());
1282*a96b3639Srobert
1283*a96b3639Srobert Register HiReg = VA.getLocReg();
1284*a96b3639Srobert Register LoReg = VA.getLocReg() + 1;
1285*a96b3639Srobert if (!CLI.IsTailCall) {
1286*a96b3639Srobert HiReg = toCallerWindow(HiReg);
1287*a96b3639Srobert LoReg = toCallerWindow(LoReg);
1288*a96b3639Srobert }
1289*a96b3639Srobert
1290*a96b3639Srobert RegsToPass.push_back(std::make_pair(HiReg, Hi64));
1291*a96b3639Srobert RegsToPass.push_back(std::make_pair(LoReg, Lo64));
129209467b48Spatrick continue;
129309467b48Spatrick }
129409467b48Spatrick
129509467b48Spatrick // The custom bit on an i32 return value indicates that it should be
129609467b48Spatrick // passed in the high bits of the register.
129709467b48Spatrick if (VA.getValVT() == MVT::i32 && VA.needsCustom()) {
129809467b48Spatrick Arg = DAG.getNode(ISD::SHL, DL, MVT::i64, Arg,
129909467b48Spatrick DAG.getConstant(32, DL, MVT::i32));
130009467b48Spatrick
130109467b48Spatrick // The next value may go in the low bits of the same register.
130209467b48Spatrick // Handle both at once.
130309467b48Spatrick if (i+1 < ArgLocs.size() && ArgLocs[i+1].isRegLoc() &&
130409467b48Spatrick ArgLocs[i+1].getLocReg() == VA.getLocReg()) {
130509467b48Spatrick SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64,
130609467b48Spatrick CLI.OutVals[i+1]);
130709467b48Spatrick Arg = DAG.getNode(ISD::OR, DL, MVT::i64, Arg, NV);
130809467b48Spatrick // Skip the next value, it's already done.
130909467b48Spatrick ++i;
131009467b48Spatrick }
131109467b48Spatrick }
1312*a96b3639Srobert
1313*a96b3639Srobert Register Reg = VA.getLocReg();
1314*a96b3639Srobert if (!CLI.IsTailCall)
1315*a96b3639Srobert Reg = toCallerWindow(Reg);
1316*a96b3639Srobert RegsToPass.push_back(std::make_pair(Reg, Arg));
131709467b48Spatrick continue;
131809467b48Spatrick }
131909467b48Spatrick
132009467b48Spatrick assert(VA.isMemLoc());
132109467b48Spatrick
132209467b48Spatrick // Create a store off the stack pointer for this argument.
132309467b48Spatrick SDValue StackPtr = DAG.getRegister(SP::O6, PtrVT);
132409467b48Spatrick // The argument area starts at %fp+BIAS+128 in the callee frame,
132509467b48Spatrick // %sp+BIAS+128 in ours.
132609467b48Spatrick SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() +
132709467b48Spatrick Subtarget->getStackPointerBias() +
132809467b48Spatrick 128, DL);
132909467b48Spatrick PtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff);
133009467b48Spatrick MemOpChains.push_back(
133109467b48Spatrick DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo()));
133209467b48Spatrick }
133309467b48Spatrick
133409467b48Spatrick // Emit all stores, make sure they occur before the call.
133509467b48Spatrick if (!MemOpChains.empty())
133609467b48Spatrick Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
133709467b48Spatrick
133809467b48Spatrick // Build a sequence of CopyToReg nodes glued together with token chain and
133909467b48Spatrick // glue operands which copy the outgoing args into registers. The InGlue is
134009467b48Spatrick // necessary since all emitted instructions must be stuck together in order
134109467b48Spatrick // to pass the live physical registers.
134209467b48Spatrick SDValue InGlue;
134309467b48Spatrick for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
134409467b48Spatrick Chain = DAG.getCopyToReg(Chain, DL,
134509467b48Spatrick RegsToPass[i].first, RegsToPass[i].second, InGlue);
134609467b48Spatrick InGlue = Chain.getValue(1);
134709467b48Spatrick }
134809467b48Spatrick
134909467b48Spatrick // If the callee is a GlobalAddress node (quite common, every direct call is)
135009467b48Spatrick // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
135109467b48Spatrick // Likewise ExternalSymbol -> TargetExternalSymbol.
135209467b48Spatrick SDValue Callee = CLI.Callee;
1353097a140dSpatrick bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CB);
1354a0747c9fSpatrick unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30
1355a0747c9fSpatrick : SparcMCExpr::VK_Sparc_WDISP30;
135609467b48Spatrick if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
135709467b48Spatrick Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, TF);
135809467b48Spatrick else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
135909467b48Spatrick Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, TF);
136009467b48Spatrick
136109467b48Spatrick // Build the operands for the call instruction itself.
136209467b48Spatrick SmallVector<SDValue, 8> Ops;
136309467b48Spatrick Ops.push_back(Chain);
136409467b48Spatrick Ops.push_back(Callee);
136509467b48Spatrick for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
136609467b48Spatrick Ops.push_back(DAG.getRegister(RegsToPass[i].first,
136709467b48Spatrick RegsToPass[i].second.getValueType()));
136809467b48Spatrick
136909467b48Spatrick // Add a register mask operand representing the call-preserved registers.
137009467b48Spatrick const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo();
137109467b48Spatrick const uint32_t *Mask =
137209467b48Spatrick ((hasReturnsTwice) ? TRI->getRTCallPreservedMask(CLI.CallConv)
137309467b48Spatrick : TRI->getCallPreservedMask(DAG.getMachineFunction(),
137409467b48Spatrick CLI.CallConv));
137509467b48Spatrick assert(Mask && "Missing call preserved mask for calling convention");
137609467b48Spatrick Ops.push_back(DAG.getRegisterMask(Mask));
137709467b48Spatrick
137809467b48Spatrick // Make sure the CopyToReg nodes are glued to the call instruction which
137909467b48Spatrick // consumes the registers.
138009467b48Spatrick if (InGlue.getNode())
138109467b48Spatrick Ops.push_back(InGlue);
138209467b48Spatrick
138309467b48Spatrick // Now the call itself.
1384*a96b3639Srobert if (CLI.IsTailCall) {
1385*a96b3639Srobert DAG.getMachineFunction().getFrameInfo().setHasTailCall();
1386*a96b3639Srobert return DAG.getNode(SPISD::TAIL_CALL, DL, MVT::Other, Ops);
1387*a96b3639Srobert }
138809467b48Spatrick SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
138909467b48Spatrick Chain = DAG.getNode(SPISD::CALL, DL, NodeTys, Ops);
139009467b48Spatrick InGlue = Chain.getValue(1);
139109467b48Spatrick
139209467b48Spatrick // Revert the stack pointer immediately after the call.
1393*a96b3639Srobert Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InGlue, DL);
139409467b48Spatrick InGlue = Chain.getValue(1);
139509467b48Spatrick
139609467b48Spatrick // Now extract the return values. This is more or less the same as
139709467b48Spatrick // LowerFormalArguments_64.
139809467b48Spatrick
139909467b48Spatrick // Assign locations to each value returned by this call.
140009467b48Spatrick SmallVector<CCValAssign, 16> RVLocs;
140109467b48Spatrick CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs,
140209467b48Spatrick *DAG.getContext());
140309467b48Spatrick
140409467b48Spatrick // Set inreg flag manually for codegen generated library calls that
140509467b48Spatrick // return float.
1406097a140dSpatrick if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && !CLI.CB)
140709467b48Spatrick CLI.Ins[0].Flags.setInReg();
140809467b48Spatrick
140909467b48Spatrick RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64);
141009467b48Spatrick
141109467b48Spatrick // Copy all of the result registers out of their specified physreg.
141209467b48Spatrick for (unsigned i = 0; i != RVLocs.size(); ++i) {
141309467b48Spatrick CCValAssign &VA = RVLocs[i];
1414*a96b3639Srobert assert(VA.isRegLoc() && "Can only return in registers!");
141509467b48Spatrick unsigned Reg = toCallerWindow(VA.getLocReg());
141609467b48Spatrick
141709467b48Spatrick // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can
141809467b48Spatrick // reside in the same register in the high and low bits. Reuse the
141909467b48Spatrick // CopyFromReg previous node to avoid duplicate copies.
142009467b48Spatrick SDValue RV;
142109467b48Spatrick if (RegisterSDNode *SrcReg = dyn_cast<RegisterSDNode>(Chain.getOperand(1)))
142209467b48Spatrick if (SrcReg->getReg() == Reg && Chain->getOpcode() == ISD::CopyFromReg)
142309467b48Spatrick RV = Chain.getValue(0);
142409467b48Spatrick
142509467b48Spatrick // But usually we'll create a new CopyFromReg for a different register.
142609467b48Spatrick if (!RV.getNode()) {
142709467b48Spatrick RV = DAG.getCopyFromReg(Chain, DL, Reg, RVLocs[i].getLocVT(), InGlue);
142809467b48Spatrick Chain = RV.getValue(1);
142909467b48Spatrick InGlue = Chain.getValue(2);
143009467b48Spatrick }
143109467b48Spatrick
143209467b48Spatrick // Get the high bits for i32 struct elements.
143309467b48Spatrick if (VA.getValVT() == MVT::i32 && VA.needsCustom())
143409467b48Spatrick RV = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), RV,
143509467b48Spatrick DAG.getConstant(32, DL, MVT::i32));
143609467b48Spatrick
143709467b48Spatrick // The callee promoted the return value, so insert an Assert?ext SDNode so
143809467b48Spatrick // we won't promote the value again in this function.
143909467b48Spatrick switch (VA.getLocInfo()) {
144009467b48Spatrick case CCValAssign::SExt:
144109467b48Spatrick RV = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), RV,
144209467b48Spatrick DAG.getValueType(VA.getValVT()));
144309467b48Spatrick break;
144409467b48Spatrick case CCValAssign::ZExt:
144509467b48Spatrick RV = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), RV,
144609467b48Spatrick DAG.getValueType(VA.getValVT()));
144709467b48Spatrick break;
144809467b48Spatrick default:
144909467b48Spatrick break;
145009467b48Spatrick }
145109467b48Spatrick
145209467b48Spatrick // Truncate the register down to the return value type.
145309467b48Spatrick if (VA.isExtInLoc())
145409467b48Spatrick RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV);
145509467b48Spatrick
145609467b48Spatrick InVals.push_back(RV);
145709467b48Spatrick }
145809467b48Spatrick
145909467b48Spatrick return Chain;
146009467b48Spatrick }
146109467b48Spatrick
146209467b48Spatrick //===----------------------------------------------------------------------===//
146309467b48Spatrick // TargetLowering Implementation
146409467b48Spatrick //===----------------------------------------------------------------------===//
146509467b48Spatrick
shouldExpandAtomicRMWInIR(AtomicRMWInst * AI) const146609467b48Spatrick TargetLowering::AtomicExpansionKind SparcTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
146709467b48Spatrick if (AI->getOperation() == AtomicRMWInst::Xchg &&
146809467b48Spatrick AI->getType()->getPrimitiveSizeInBits() == 32)
146909467b48Spatrick return AtomicExpansionKind::None; // Uses xchg instruction
147009467b48Spatrick
147109467b48Spatrick return AtomicExpansionKind::CmpXChg;
147209467b48Spatrick }
147309467b48Spatrick
1474*a96b3639Srobert /// intCondCCodeToRcond - Convert a DAG integer condition code to a SPARC
1475*a96b3639Srobert /// rcond condition.
intCondCCodeToRcond(ISD::CondCode CC)1476*a96b3639Srobert static SPCC::CondCodes intCondCCodeToRcond(ISD::CondCode CC) {
1477*a96b3639Srobert switch (CC) {
1478*a96b3639Srobert default:
1479*a96b3639Srobert llvm_unreachable("Unknown/unsigned integer condition code!");
1480*a96b3639Srobert case ISD::SETEQ:
1481*a96b3639Srobert return SPCC::REG_Z;
1482*a96b3639Srobert case ISD::SETNE:
1483*a96b3639Srobert return SPCC::REG_NZ;
1484*a96b3639Srobert case ISD::SETLT:
1485*a96b3639Srobert return SPCC::REG_LZ;
1486*a96b3639Srobert case ISD::SETGT:
1487*a96b3639Srobert return SPCC::REG_GZ;
1488*a96b3639Srobert case ISD::SETLE:
1489*a96b3639Srobert return SPCC::REG_LEZ;
1490*a96b3639Srobert case ISD::SETGE:
1491*a96b3639Srobert return SPCC::REG_GEZ;
1492*a96b3639Srobert }
1493*a96b3639Srobert }
1494*a96b3639Srobert
149509467b48Spatrick /// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC
149609467b48Spatrick /// condition.
IntCondCCodeToICC(ISD::CondCode CC)149709467b48Spatrick static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) {
149809467b48Spatrick switch (CC) {
149909467b48Spatrick default: llvm_unreachable("Unknown integer condition code!");
150009467b48Spatrick case ISD::SETEQ: return SPCC::ICC_E;
150109467b48Spatrick case ISD::SETNE: return SPCC::ICC_NE;
150209467b48Spatrick case ISD::SETLT: return SPCC::ICC_L;
150309467b48Spatrick case ISD::SETGT: return SPCC::ICC_G;
150409467b48Spatrick case ISD::SETLE: return SPCC::ICC_LE;
150509467b48Spatrick case ISD::SETGE: return SPCC::ICC_GE;
150609467b48Spatrick case ISD::SETULT: return SPCC::ICC_CS;
150709467b48Spatrick case ISD::SETULE: return SPCC::ICC_LEU;
150809467b48Spatrick case ISD::SETUGT: return SPCC::ICC_GU;
150909467b48Spatrick case ISD::SETUGE: return SPCC::ICC_CC;
151009467b48Spatrick }
151109467b48Spatrick }
151209467b48Spatrick
151309467b48Spatrick /// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC
151409467b48Spatrick /// FCC condition.
FPCondCCodeToFCC(ISD::CondCode CC)151509467b48Spatrick static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) {
151609467b48Spatrick switch (CC) {
151709467b48Spatrick default: llvm_unreachable("Unknown fp condition code!");
151809467b48Spatrick case ISD::SETEQ:
151909467b48Spatrick case ISD::SETOEQ: return SPCC::FCC_E;
152009467b48Spatrick case ISD::SETNE:
152109467b48Spatrick case ISD::SETUNE: return SPCC::FCC_NE;
152209467b48Spatrick case ISD::SETLT:
152309467b48Spatrick case ISD::SETOLT: return SPCC::FCC_L;
152409467b48Spatrick case ISD::SETGT:
152509467b48Spatrick case ISD::SETOGT: return SPCC::FCC_G;
152609467b48Spatrick case ISD::SETLE:
152709467b48Spatrick case ISD::SETOLE: return SPCC::FCC_LE;
152809467b48Spatrick case ISD::SETGE:
152909467b48Spatrick case ISD::SETOGE: return SPCC::FCC_GE;
153009467b48Spatrick case ISD::SETULT: return SPCC::FCC_UL;
153109467b48Spatrick case ISD::SETULE: return SPCC::FCC_ULE;
153209467b48Spatrick case ISD::SETUGT: return SPCC::FCC_UG;
153309467b48Spatrick case ISD::SETUGE: return SPCC::FCC_UGE;
153409467b48Spatrick case ISD::SETUO: return SPCC::FCC_U;
153509467b48Spatrick case ISD::SETO: return SPCC::FCC_O;
153609467b48Spatrick case ISD::SETONE: return SPCC::FCC_LG;
153709467b48Spatrick case ISD::SETUEQ: return SPCC::FCC_UE;
153809467b48Spatrick }
153909467b48Spatrick }
154009467b48Spatrick
SparcTargetLowering(const TargetMachine & TM,const SparcSubtarget & STI)154109467b48Spatrick SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
154209467b48Spatrick const SparcSubtarget &STI)
154309467b48Spatrick : TargetLowering(TM), Subtarget(&STI) {
1544*a96b3639Srobert MVT PtrVT = MVT::getIntegerVT(TM.getPointerSizeInBits(0));
154509467b48Spatrick
154609467b48Spatrick // Instructions which use registers as conditionals examine all the
154709467b48Spatrick // bits (as does the pseudo SELECT_CC expansion). I don't think it
154809467b48Spatrick // matters much whether it's ZeroOrOneBooleanContent, or
154909467b48Spatrick // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the
155009467b48Spatrick // former.
155109467b48Spatrick setBooleanContents(ZeroOrOneBooleanContent);
155209467b48Spatrick setBooleanVectorContents(ZeroOrOneBooleanContent);
155309467b48Spatrick
155409467b48Spatrick // Set up the register classes.
155509467b48Spatrick addRegisterClass(MVT::i32, &SP::IntRegsRegClass);
155609467b48Spatrick if (!Subtarget->useSoftFloat()) {
155709467b48Spatrick addRegisterClass(MVT::f32, &SP::FPRegsRegClass);
155809467b48Spatrick addRegisterClass(MVT::f64, &SP::DFPRegsRegClass);
155909467b48Spatrick addRegisterClass(MVT::f128, &SP::QFPRegsRegClass);
156009467b48Spatrick }
156109467b48Spatrick if (Subtarget->is64Bit()) {
156209467b48Spatrick addRegisterClass(MVT::i64, &SP::I64RegsRegClass);
156309467b48Spatrick } else {
156409467b48Spatrick // On 32bit sparc, we define a double-register 32bit register
156509467b48Spatrick // class, as well. This is modeled in LLVM as a 2-vector of i32.
156609467b48Spatrick addRegisterClass(MVT::v2i32, &SP::IntPairRegClass);
156709467b48Spatrick
156809467b48Spatrick // ...but almost all operations must be expanded, so set that as
156909467b48Spatrick // the default.
157009467b48Spatrick for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
157109467b48Spatrick setOperationAction(Op, MVT::v2i32, Expand);
157209467b48Spatrick }
157309467b48Spatrick // Truncating/extending stores/loads are also not supported.
157409467b48Spatrick for (MVT VT : MVT::integer_fixedlen_vector_valuetypes()) {
157509467b48Spatrick setLoadExtAction(ISD::SEXTLOAD, VT, MVT::v2i32, Expand);
157609467b48Spatrick setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::v2i32, Expand);
157709467b48Spatrick setLoadExtAction(ISD::EXTLOAD, VT, MVT::v2i32, Expand);
157809467b48Spatrick
157909467b48Spatrick setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, VT, Expand);
158009467b48Spatrick setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, VT, Expand);
158109467b48Spatrick setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, VT, Expand);
158209467b48Spatrick
158309467b48Spatrick setTruncStoreAction(VT, MVT::v2i32, Expand);
158409467b48Spatrick setTruncStoreAction(MVT::v2i32, VT, Expand);
158509467b48Spatrick }
158609467b48Spatrick // However, load and store *are* legal.
158709467b48Spatrick setOperationAction(ISD::LOAD, MVT::v2i32, Legal);
158809467b48Spatrick setOperationAction(ISD::STORE, MVT::v2i32, Legal);
158909467b48Spatrick setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Legal);
159009467b48Spatrick setOperationAction(ISD::BUILD_VECTOR, MVT::v2i32, Legal);
159109467b48Spatrick
159209467b48Spatrick // And we need to promote i64 loads/stores into vector load/store
159309467b48Spatrick setOperationAction(ISD::LOAD, MVT::i64, Custom);
159409467b48Spatrick setOperationAction(ISD::STORE, MVT::i64, Custom);
159509467b48Spatrick
159609467b48Spatrick // Sadly, this doesn't work:
159709467b48Spatrick // AddPromotedToType(ISD::LOAD, MVT::i64, MVT::v2i32);
159809467b48Spatrick // AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32);
159909467b48Spatrick }
160009467b48Spatrick
160109467b48Spatrick // Turn FP extload into load/fpextend
160209467b48Spatrick for (MVT VT : MVT::fp_valuetypes()) {
1603097a140dSpatrick setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand);
160409467b48Spatrick setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
160509467b48Spatrick setLoadExtAction(ISD::EXTLOAD, VT, MVT::f64, Expand);
160609467b48Spatrick }
160709467b48Spatrick
160809467b48Spatrick // Sparc doesn't have i1 sign extending load
160909467b48Spatrick for (MVT VT : MVT::integer_valuetypes())
161009467b48Spatrick setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
161109467b48Spatrick
161209467b48Spatrick // Turn FP truncstore into trunc + store.
1613097a140dSpatrick setTruncStoreAction(MVT::f32, MVT::f16, Expand);
1614097a140dSpatrick setTruncStoreAction(MVT::f64, MVT::f16, Expand);
161509467b48Spatrick setTruncStoreAction(MVT::f64, MVT::f32, Expand);
1616a0747c9fSpatrick setTruncStoreAction(MVT::f128, MVT::f16, Expand);
161709467b48Spatrick setTruncStoreAction(MVT::f128, MVT::f32, Expand);
161809467b48Spatrick setTruncStoreAction(MVT::f128, MVT::f64, Expand);
161909467b48Spatrick
162009467b48Spatrick // Custom legalize GlobalAddress nodes into LO/HI parts.
162109467b48Spatrick setOperationAction(ISD::GlobalAddress, PtrVT, Custom);
162209467b48Spatrick setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom);
162309467b48Spatrick setOperationAction(ISD::ConstantPool, PtrVT, Custom);
162409467b48Spatrick setOperationAction(ISD::BlockAddress, PtrVT, Custom);
162509467b48Spatrick
162609467b48Spatrick // Sparc doesn't have sext_inreg, replace them with shl/sra
162709467b48Spatrick setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
162809467b48Spatrick setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand);
162909467b48Spatrick setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
163009467b48Spatrick
163109467b48Spatrick // Sparc has no REM or DIVREM operations.
163209467b48Spatrick setOperationAction(ISD::UREM, MVT::i32, Expand);
163309467b48Spatrick setOperationAction(ISD::SREM, MVT::i32, Expand);
163409467b48Spatrick setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
163509467b48Spatrick setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
163609467b48Spatrick
163709467b48Spatrick // ... nor does SparcV9.
163809467b48Spatrick if (Subtarget->is64Bit()) {
163909467b48Spatrick setOperationAction(ISD::UREM, MVT::i64, Expand);
164009467b48Spatrick setOperationAction(ISD::SREM, MVT::i64, Expand);
164109467b48Spatrick setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
164209467b48Spatrick setOperationAction(ISD::UDIVREM, MVT::i64, Expand);
164309467b48Spatrick }
164409467b48Spatrick
164509467b48Spatrick // Custom expand fp<->sint
164609467b48Spatrick setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
164709467b48Spatrick setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
164809467b48Spatrick setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
164909467b48Spatrick setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
165009467b48Spatrick
165109467b48Spatrick // Custom Expand fp<->uint
165209467b48Spatrick setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
165309467b48Spatrick setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
165409467b48Spatrick setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
165509467b48Spatrick setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
165609467b48Spatrick
1657097a140dSpatrick // Lower f16 conversion operations into library calls
1658097a140dSpatrick setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand);
1659097a140dSpatrick setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand);
1660097a140dSpatrick setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand);
1661097a140dSpatrick setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand);
1662a0747c9fSpatrick setOperationAction(ISD::FP16_TO_FP, MVT::f128, Expand);
1663a0747c9fSpatrick setOperationAction(ISD::FP_TO_FP16, MVT::f128, Expand);
1664097a140dSpatrick
166509467b48Spatrick setOperationAction(ISD::BITCAST, MVT::f32, Expand);
166609467b48Spatrick setOperationAction(ISD::BITCAST, MVT::i32, Expand);
166709467b48Spatrick
166809467b48Spatrick // Sparc has no select or setcc: expand to SELECT_CC.
166909467b48Spatrick setOperationAction(ISD::SELECT, MVT::i32, Expand);
167009467b48Spatrick setOperationAction(ISD::SELECT, MVT::f32, Expand);
167109467b48Spatrick setOperationAction(ISD::SELECT, MVT::f64, Expand);
167209467b48Spatrick setOperationAction(ISD::SELECT, MVT::f128, Expand);
167309467b48Spatrick
167409467b48Spatrick setOperationAction(ISD::SETCC, MVT::i32, Expand);
167509467b48Spatrick setOperationAction(ISD::SETCC, MVT::f32, Expand);
167609467b48Spatrick setOperationAction(ISD::SETCC, MVT::f64, Expand);
167709467b48Spatrick setOperationAction(ISD::SETCC, MVT::f128, Expand);
167809467b48Spatrick
167909467b48Spatrick // Sparc doesn't have BRCOND either, it has BR_CC.
168009467b48Spatrick setOperationAction(ISD::BRCOND, MVT::Other, Expand);
168109467b48Spatrick setOperationAction(ISD::BRIND, MVT::Other, Expand);
168209467b48Spatrick setOperationAction(ISD::BR_JT, MVT::Other, Expand);
168309467b48Spatrick setOperationAction(ISD::BR_CC, MVT::i32, Custom);
168409467b48Spatrick setOperationAction(ISD::BR_CC, MVT::f32, Custom);
168509467b48Spatrick setOperationAction(ISD::BR_CC, MVT::f64, Custom);
168609467b48Spatrick setOperationAction(ISD::BR_CC, MVT::f128, Custom);
168709467b48Spatrick
168809467b48Spatrick setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
168909467b48Spatrick setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
169009467b48Spatrick setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
169109467b48Spatrick setOperationAction(ISD::SELECT_CC, MVT::f128, Custom);
169209467b48Spatrick
169309467b48Spatrick setOperationAction(ISD::ADDC, MVT::i32, Custom);
169409467b48Spatrick setOperationAction(ISD::ADDE, MVT::i32, Custom);
169509467b48Spatrick setOperationAction(ISD::SUBC, MVT::i32, Custom);
169609467b48Spatrick setOperationAction(ISD::SUBE, MVT::i32, Custom);
169709467b48Spatrick
169809467b48Spatrick if (Subtarget->is64Bit()) {
169909467b48Spatrick setOperationAction(ISD::ADDC, MVT::i64, Custom);
170009467b48Spatrick setOperationAction(ISD::ADDE, MVT::i64, Custom);
170109467b48Spatrick setOperationAction(ISD::SUBC, MVT::i64, Custom);
170209467b48Spatrick setOperationAction(ISD::SUBE, MVT::i64, Custom);
170309467b48Spatrick setOperationAction(ISD::BITCAST, MVT::f64, Expand);
170409467b48Spatrick setOperationAction(ISD::BITCAST, MVT::i64, Expand);
170509467b48Spatrick setOperationAction(ISD::SELECT, MVT::i64, Expand);
170609467b48Spatrick setOperationAction(ISD::SETCC, MVT::i64, Expand);
170709467b48Spatrick setOperationAction(ISD::BR_CC, MVT::i64, Custom);
170809467b48Spatrick setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
170909467b48Spatrick
171009467b48Spatrick setOperationAction(ISD::CTPOP, MVT::i64,
171109467b48Spatrick Subtarget->usePopc() ? Legal : Expand);
171209467b48Spatrick setOperationAction(ISD::CTTZ , MVT::i64, Expand);
171309467b48Spatrick setOperationAction(ISD::CTLZ , MVT::i64, Expand);
171409467b48Spatrick setOperationAction(ISD::BSWAP, MVT::i64, Expand);
171509467b48Spatrick setOperationAction(ISD::ROTL , MVT::i64, Expand);
171609467b48Spatrick setOperationAction(ISD::ROTR , MVT::i64, Expand);
171709467b48Spatrick setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom);
171809467b48Spatrick }
171909467b48Spatrick
172009467b48Spatrick // ATOMICs.
172109467b48Spatrick // Atomics are supported on SparcV9. 32-bit atomics are also
172209467b48Spatrick // supported by some Leon SparcV8 variants. Otherwise, atomics
172309467b48Spatrick // are unsupported.
172409467b48Spatrick if (Subtarget->isV9())
172509467b48Spatrick setMaxAtomicSizeInBitsSupported(64);
172609467b48Spatrick else if (Subtarget->hasLeonCasa())
172709467b48Spatrick setMaxAtomicSizeInBitsSupported(32);
172809467b48Spatrick else
172909467b48Spatrick setMaxAtomicSizeInBitsSupported(0);
173009467b48Spatrick
173109467b48Spatrick setMinCmpXchgSizeInBits(32);
173209467b48Spatrick
173309467b48Spatrick setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal);
173409467b48Spatrick
173509467b48Spatrick setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal);
173609467b48Spatrick
173709467b48Spatrick // Custom Lower Atomic LOAD/STORE
173809467b48Spatrick setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom);
173909467b48Spatrick setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom);
174009467b48Spatrick
174109467b48Spatrick if (Subtarget->is64Bit()) {
174209467b48Spatrick setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal);
174309467b48Spatrick setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Legal);
174409467b48Spatrick setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom);
174509467b48Spatrick setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom);
174609467b48Spatrick }
174709467b48Spatrick
174809467b48Spatrick if (!Subtarget->is64Bit()) {
174909467b48Spatrick // These libcalls are not available in 32-bit.
1750*a96b3639Srobert setLibcallName(RTLIB::MULO_I64, nullptr);
175109467b48Spatrick setLibcallName(RTLIB::SHL_I128, nullptr);
175209467b48Spatrick setLibcallName(RTLIB::SRL_I128, nullptr);
175309467b48Spatrick setLibcallName(RTLIB::SRA_I128, nullptr);
175409467b48Spatrick }
175509467b48Spatrick
1756*a96b3639Srobert setLibcallName(RTLIB::MULO_I128, nullptr);
1757*a96b3639Srobert
175809467b48Spatrick if (!Subtarget->isV9()) {
175909467b48Spatrick // SparcV8 does not have FNEGD and FABSD.
176009467b48Spatrick setOperationAction(ISD::FNEG, MVT::f64, Custom);
176109467b48Spatrick setOperationAction(ISD::FABS, MVT::f64, Custom);
176209467b48Spatrick }
176309467b48Spatrick
176409467b48Spatrick setOperationAction(ISD::FSIN , MVT::f128, Expand);
176509467b48Spatrick setOperationAction(ISD::FCOS , MVT::f128, Expand);
176609467b48Spatrick setOperationAction(ISD::FSINCOS, MVT::f128, Expand);
176709467b48Spatrick setOperationAction(ISD::FREM , MVT::f128, Expand);
176809467b48Spatrick setOperationAction(ISD::FMA , MVT::f128, Expand);
176909467b48Spatrick setOperationAction(ISD::FSIN , MVT::f64, Expand);
177009467b48Spatrick setOperationAction(ISD::FCOS , MVT::f64, Expand);
177109467b48Spatrick setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
177209467b48Spatrick setOperationAction(ISD::FREM , MVT::f64, Expand);
177309467b48Spatrick setOperationAction(ISD::FMA , MVT::f64, Expand);
177409467b48Spatrick setOperationAction(ISD::FSIN , MVT::f32, Expand);
177509467b48Spatrick setOperationAction(ISD::FCOS , MVT::f32, Expand);
177609467b48Spatrick setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
177709467b48Spatrick setOperationAction(ISD::FREM , MVT::f32, Expand);
177809467b48Spatrick setOperationAction(ISD::FMA , MVT::f32, Expand);
177909467b48Spatrick setOperationAction(ISD::CTTZ , MVT::i32, Expand);
178009467b48Spatrick setOperationAction(ISD::CTLZ , MVT::i32, Expand);
178109467b48Spatrick setOperationAction(ISD::ROTL , MVT::i32, Expand);
178209467b48Spatrick setOperationAction(ISD::ROTR , MVT::i32, Expand);
178309467b48Spatrick setOperationAction(ISD::BSWAP, MVT::i32, Expand);
178409467b48Spatrick setOperationAction(ISD::FCOPYSIGN, MVT::f128, Expand);
178509467b48Spatrick setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
178609467b48Spatrick setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
178709467b48Spatrick setOperationAction(ISD::FPOW , MVT::f128, Expand);
178809467b48Spatrick setOperationAction(ISD::FPOW , MVT::f64, Expand);
178909467b48Spatrick setOperationAction(ISD::FPOW , MVT::f32, Expand);
179009467b48Spatrick
179109467b48Spatrick setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
179209467b48Spatrick setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
179309467b48Spatrick setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
179409467b48Spatrick
179509467b48Spatrick // Expands to [SU]MUL_LOHI.
179609467b48Spatrick setOperationAction(ISD::MULHU, MVT::i32, Expand);
179709467b48Spatrick setOperationAction(ISD::MULHS, MVT::i32, Expand);
179809467b48Spatrick setOperationAction(ISD::MUL, MVT::i32, Expand);
179909467b48Spatrick
180009467b48Spatrick if (Subtarget->useSoftMulDiv()) {
180109467b48Spatrick // .umul works for both signed and unsigned
180209467b48Spatrick setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
180309467b48Spatrick setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
180409467b48Spatrick setLibcallName(RTLIB::MUL_I32, ".umul");
180509467b48Spatrick
180609467b48Spatrick setOperationAction(ISD::SDIV, MVT::i32, Expand);
180709467b48Spatrick setLibcallName(RTLIB::SDIV_I32, ".div");
180809467b48Spatrick
180909467b48Spatrick setOperationAction(ISD::UDIV, MVT::i32, Expand);
181009467b48Spatrick setLibcallName(RTLIB::UDIV_I32, ".udiv");
181109467b48Spatrick
181209467b48Spatrick setLibcallName(RTLIB::SREM_I32, ".rem");
181309467b48Spatrick setLibcallName(RTLIB::UREM_I32, ".urem");
181409467b48Spatrick }
181509467b48Spatrick
181609467b48Spatrick if (Subtarget->is64Bit()) {
181709467b48Spatrick setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
181809467b48Spatrick setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
181909467b48Spatrick setOperationAction(ISD::MULHU, MVT::i64, Expand);
182009467b48Spatrick setOperationAction(ISD::MULHS, MVT::i64, Expand);
182109467b48Spatrick
182209467b48Spatrick setOperationAction(ISD::UMULO, MVT::i64, Custom);
182309467b48Spatrick setOperationAction(ISD::SMULO, MVT::i64, Custom);
182409467b48Spatrick
182509467b48Spatrick setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand);
182609467b48Spatrick setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand);
182709467b48Spatrick setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand);
182809467b48Spatrick }
182909467b48Spatrick
183009467b48Spatrick // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
183109467b48Spatrick setOperationAction(ISD::VASTART , MVT::Other, Custom);
183209467b48Spatrick // VAARG needs to be lowered to not do unaligned accesses for doubles.
183309467b48Spatrick setOperationAction(ISD::VAARG , MVT::Other, Custom);
183409467b48Spatrick
183509467b48Spatrick setOperationAction(ISD::TRAP , MVT::Other, Legal);
183609467b48Spatrick setOperationAction(ISD::DEBUGTRAP , MVT::Other, Legal);
183709467b48Spatrick
183809467b48Spatrick // Use the default implementation.
183909467b48Spatrick setOperationAction(ISD::VACOPY , MVT::Other, Expand);
184009467b48Spatrick setOperationAction(ISD::VAEND , MVT::Other, Expand);
184109467b48Spatrick setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
184209467b48Spatrick setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
184309467b48Spatrick setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom);
184409467b48Spatrick
184509467b48Spatrick setStackPointerRegisterToSaveRestore(SP::O6);
184609467b48Spatrick
184709467b48Spatrick setOperationAction(ISD::CTPOP, MVT::i32,
184809467b48Spatrick Subtarget->usePopc() ? Legal : Expand);
184909467b48Spatrick
185009467b48Spatrick if (Subtarget->isV9() && Subtarget->hasHardQuad()) {
185109467b48Spatrick setOperationAction(ISD::LOAD, MVT::f128, Legal);
185209467b48Spatrick setOperationAction(ISD::STORE, MVT::f128, Legal);
185309467b48Spatrick } else {
185409467b48Spatrick setOperationAction(ISD::LOAD, MVT::f128, Custom);
185509467b48Spatrick setOperationAction(ISD::STORE, MVT::f128, Custom);
185609467b48Spatrick }
185709467b48Spatrick
185809467b48Spatrick if (Subtarget->hasHardQuad()) {
185909467b48Spatrick setOperationAction(ISD::FADD, MVT::f128, Legal);
186009467b48Spatrick setOperationAction(ISD::FSUB, MVT::f128, Legal);
186109467b48Spatrick setOperationAction(ISD::FMUL, MVT::f128, Legal);
186209467b48Spatrick setOperationAction(ISD::FDIV, MVT::f128, Legal);
186309467b48Spatrick setOperationAction(ISD::FSQRT, MVT::f128, Legal);
186409467b48Spatrick setOperationAction(ISD::FP_EXTEND, MVT::f128, Legal);
186509467b48Spatrick setOperationAction(ISD::FP_ROUND, MVT::f64, Legal);
186609467b48Spatrick if (Subtarget->isV9()) {
186709467b48Spatrick setOperationAction(ISD::FNEG, MVT::f128, Legal);
186809467b48Spatrick setOperationAction(ISD::FABS, MVT::f128, Legal);
186909467b48Spatrick } else {
187009467b48Spatrick setOperationAction(ISD::FNEG, MVT::f128, Custom);
187109467b48Spatrick setOperationAction(ISD::FABS, MVT::f128, Custom);
187209467b48Spatrick }
187309467b48Spatrick
187409467b48Spatrick if (!Subtarget->is64Bit()) {
187509467b48Spatrick setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll");
187609467b48Spatrick setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull");
187709467b48Spatrick setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq");
187809467b48Spatrick setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq");
187909467b48Spatrick }
188009467b48Spatrick
188109467b48Spatrick } else {
188209467b48Spatrick // Custom legalize f128 operations.
188309467b48Spatrick
188409467b48Spatrick setOperationAction(ISD::FADD, MVT::f128, Custom);
188509467b48Spatrick setOperationAction(ISD::FSUB, MVT::f128, Custom);
188609467b48Spatrick setOperationAction(ISD::FMUL, MVT::f128, Custom);
188709467b48Spatrick setOperationAction(ISD::FDIV, MVT::f128, Custom);
188809467b48Spatrick setOperationAction(ISD::FSQRT, MVT::f128, Custom);
188909467b48Spatrick setOperationAction(ISD::FNEG, MVT::f128, Custom);
189009467b48Spatrick setOperationAction(ISD::FABS, MVT::f128, Custom);
189109467b48Spatrick
189209467b48Spatrick setOperationAction(ISD::FP_EXTEND, MVT::f128, Custom);
189309467b48Spatrick setOperationAction(ISD::FP_ROUND, MVT::f64, Custom);
189409467b48Spatrick setOperationAction(ISD::FP_ROUND, MVT::f32, Custom);
189509467b48Spatrick
189609467b48Spatrick // Setup Runtime library names.
189709467b48Spatrick if (Subtarget->is64Bit() && !Subtarget->useSoftFloat()) {
189809467b48Spatrick setLibcallName(RTLIB::ADD_F128, "_Qp_add");
189909467b48Spatrick setLibcallName(RTLIB::SUB_F128, "_Qp_sub");
190009467b48Spatrick setLibcallName(RTLIB::MUL_F128, "_Qp_mul");
190109467b48Spatrick setLibcallName(RTLIB::DIV_F128, "_Qp_div");
190209467b48Spatrick setLibcallName(RTLIB::SQRT_F128, "_Qp_sqrt");
190309467b48Spatrick setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Qp_qtoi");
190409467b48Spatrick setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Qp_qtoui");
190509467b48Spatrick setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Qp_itoq");
190609467b48Spatrick setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Qp_uitoq");
190709467b48Spatrick setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Qp_qtox");
190809467b48Spatrick setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Qp_qtoux");
190909467b48Spatrick setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Qp_xtoq");
191009467b48Spatrick setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Qp_uxtoq");
191109467b48Spatrick setLibcallName(RTLIB::FPEXT_F32_F128, "_Qp_stoq");
191209467b48Spatrick setLibcallName(RTLIB::FPEXT_F64_F128, "_Qp_dtoq");
191309467b48Spatrick setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos");
191409467b48Spatrick setLibcallName(RTLIB::FPROUND_F128_F64, "_Qp_qtod");
191509467b48Spatrick } else if (!Subtarget->useSoftFloat()) {
191609467b48Spatrick setLibcallName(RTLIB::ADD_F128, "_Q_add");
191709467b48Spatrick setLibcallName(RTLIB::SUB_F128, "_Q_sub");
191809467b48Spatrick setLibcallName(RTLIB::MUL_F128, "_Q_mul");
191909467b48Spatrick setLibcallName(RTLIB::DIV_F128, "_Q_div");
192009467b48Spatrick setLibcallName(RTLIB::SQRT_F128, "_Q_sqrt");
192109467b48Spatrick setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Q_qtoi");
192209467b48Spatrick setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Q_qtou");
192309467b48Spatrick setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Q_itoq");
192409467b48Spatrick setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Q_utoq");
192509467b48Spatrick setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll");
192609467b48Spatrick setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull");
192709467b48Spatrick setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq");
192809467b48Spatrick setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq");
192909467b48Spatrick setLibcallName(RTLIB::FPEXT_F32_F128, "_Q_stoq");
193009467b48Spatrick setLibcallName(RTLIB::FPEXT_F64_F128, "_Q_dtoq");
193109467b48Spatrick setLibcallName(RTLIB::FPROUND_F128_F32, "_Q_qtos");
193209467b48Spatrick setLibcallName(RTLIB::FPROUND_F128_F64, "_Q_qtod");
193309467b48Spatrick }
193409467b48Spatrick }
193509467b48Spatrick
193609467b48Spatrick if (Subtarget->fixAllFDIVSQRT()) {
193709467b48Spatrick // Promote FDIVS and FSQRTS to FDIVD and FSQRTD instructions instead as
193809467b48Spatrick // the former instructions generate errata on LEON processors.
193909467b48Spatrick setOperationAction(ISD::FDIV, MVT::f32, Promote);
194009467b48Spatrick setOperationAction(ISD::FSQRT, MVT::f32, Promote);
194109467b48Spatrick }
194209467b48Spatrick
194309467b48Spatrick if (Subtarget->hasNoFMULS()) {
194409467b48Spatrick setOperationAction(ISD::FMUL, MVT::f32, Promote);
194509467b48Spatrick }
194609467b48Spatrick
194709467b48Spatrick // Custom combine bitcast between f64 and v2i32
194809467b48Spatrick if (!Subtarget->is64Bit())
194909467b48Spatrick setTargetDAGCombine(ISD::BITCAST);
195009467b48Spatrick
195109467b48Spatrick if (Subtarget->hasLeonCycleCounter())
195209467b48Spatrick setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
195309467b48Spatrick
195409467b48Spatrick setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
195509467b48Spatrick
195609467b48Spatrick setMinFunctionAlignment(Align(4));
195709467b48Spatrick
195809467b48Spatrick computeRegisterProperties(Subtarget->getRegisterInfo());
195909467b48Spatrick }
196009467b48Spatrick
useSoftFloat() const196109467b48Spatrick bool SparcTargetLowering::useSoftFloat() const {
196209467b48Spatrick return Subtarget->useSoftFloat();
196309467b48Spatrick }
196409467b48Spatrick
getTargetNodeName(unsigned Opcode) const196509467b48Spatrick const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
196609467b48Spatrick switch ((SPISD::NodeType)Opcode) {
196709467b48Spatrick case SPISD::FIRST_NUMBER: break;
196809467b48Spatrick case SPISD::CMPICC: return "SPISD::CMPICC";
196909467b48Spatrick case SPISD::CMPFCC: return "SPISD::CMPFCC";
1970*a96b3639Srobert case SPISD::CMPFCC_V9:
1971*a96b3639Srobert return "SPISD::CMPFCC_V9";
197209467b48Spatrick case SPISD::BRICC: return "SPISD::BRICC";
1973*a96b3639Srobert case SPISD::BPICC:
1974*a96b3639Srobert return "SPISD::BPICC";
1975*a96b3639Srobert case SPISD::BPXCC:
1976*a96b3639Srobert return "SPISD::BPXCC";
197709467b48Spatrick case SPISD::BRFCC: return "SPISD::BRFCC";
1978*a96b3639Srobert case SPISD::BRFCC_V9:
1979*a96b3639Srobert return "SPISD::BRFCC_V9";
198009467b48Spatrick case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC";
198109467b48Spatrick case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC";
198209467b48Spatrick case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC";
1983*a96b3639Srobert case SPISD::SELECT_REG:
1984*a96b3639Srobert return "SPISD::SELECT_REG";
198509467b48Spatrick case SPISD::Hi: return "SPISD::Hi";
198609467b48Spatrick case SPISD::Lo: return "SPISD::Lo";
198709467b48Spatrick case SPISD::FTOI: return "SPISD::FTOI";
198809467b48Spatrick case SPISD::ITOF: return "SPISD::ITOF";
198909467b48Spatrick case SPISD::FTOX: return "SPISD::FTOX";
199009467b48Spatrick case SPISD::XTOF: return "SPISD::XTOF";
199109467b48Spatrick case SPISD::CALL: return "SPISD::CALL";
199209467b48Spatrick case SPISD::RET_FLAG: return "SPISD::RET_FLAG";
199309467b48Spatrick case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG";
199409467b48Spatrick case SPISD::FLUSHW: return "SPISD::FLUSHW";
199509467b48Spatrick case SPISD::TLS_ADD: return "SPISD::TLS_ADD";
199609467b48Spatrick case SPISD::TLS_LD: return "SPISD::TLS_LD";
199709467b48Spatrick case SPISD::TLS_CALL: return "SPISD::TLS_CALL";
1998*a96b3639Srobert case SPISD::TAIL_CALL: return "SPISD::TAIL_CALL";
1999*a96b3639Srobert case SPISD::LOAD_GDOP: return "SPISD::LOAD_GDOP";
200009467b48Spatrick }
200109467b48Spatrick return nullptr;
200209467b48Spatrick }
200309467b48Spatrick
getSetCCResultType(const DataLayout &,LLVMContext &,EVT VT) const200409467b48Spatrick EVT SparcTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &,
200509467b48Spatrick EVT VT) const {
200609467b48Spatrick if (!VT.isVector())
200709467b48Spatrick return MVT::i32;
200809467b48Spatrick return VT.changeVectorElementTypeToInteger();
200909467b48Spatrick }
201009467b48Spatrick
201109467b48Spatrick /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to
201209467b48Spatrick /// be zero. Op is expected to be a target specific node. Used by DAG
201309467b48Spatrick /// combiner.
computeKnownBitsForTargetNode(const SDValue Op,KnownBits & Known,const APInt & DemandedElts,const SelectionDAG & DAG,unsigned Depth) const201409467b48Spatrick void SparcTargetLowering::computeKnownBitsForTargetNode
201509467b48Spatrick (const SDValue Op,
201609467b48Spatrick KnownBits &Known,
201709467b48Spatrick const APInt &DemandedElts,
201809467b48Spatrick const SelectionDAG &DAG,
201909467b48Spatrick unsigned Depth) const {
202009467b48Spatrick KnownBits Known2;
202109467b48Spatrick Known.resetAll();
202209467b48Spatrick
202309467b48Spatrick switch (Op.getOpcode()) {
202409467b48Spatrick default: break;
202509467b48Spatrick case SPISD::SELECT_ICC:
202609467b48Spatrick case SPISD::SELECT_XCC:
202709467b48Spatrick case SPISD::SELECT_FCC:
202809467b48Spatrick Known = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
202909467b48Spatrick Known2 = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
203009467b48Spatrick
203109467b48Spatrick // Only known if known in both the LHS and RHS.
2032a0747c9fSpatrick Known = KnownBits::commonBits(Known, Known2);
203309467b48Spatrick break;
203409467b48Spatrick }
203509467b48Spatrick }
203609467b48Spatrick
203709467b48Spatrick // Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so
203809467b48Spatrick // set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition.
LookThroughSetCC(SDValue & LHS,SDValue & RHS,ISD::CondCode CC,unsigned & SPCC)203909467b48Spatrick static void LookThroughSetCC(SDValue &LHS, SDValue &RHS,
204009467b48Spatrick ISD::CondCode CC, unsigned &SPCC) {
2041*a96b3639Srobert if (isNullConstant(RHS) && CC == ISD::SETNE &&
204209467b48Spatrick (((LHS.getOpcode() == SPISD::SELECT_ICC ||
204309467b48Spatrick LHS.getOpcode() == SPISD::SELECT_XCC) &&
204409467b48Spatrick LHS.getOperand(3).getOpcode() == SPISD::CMPICC) ||
204509467b48Spatrick (LHS.getOpcode() == SPISD::SELECT_FCC &&
2046*a96b3639Srobert (LHS.getOperand(3).getOpcode() == SPISD::CMPFCC ||
2047*a96b3639Srobert LHS.getOperand(3).getOpcode() == SPISD::CMPFCC_V9))) &&
2048*a96b3639Srobert isOneConstant(LHS.getOperand(0)) && isNullConstant(LHS.getOperand(1))) {
204909467b48Spatrick SDValue CMPCC = LHS.getOperand(3);
205009467b48Spatrick SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue();
205109467b48Spatrick LHS = CMPCC.getOperand(0);
205209467b48Spatrick RHS = CMPCC.getOperand(1);
205309467b48Spatrick }
205409467b48Spatrick }
205509467b48Spatrick
205609467b48Spatrick // Convert to a target node and set target flags.
withTargetFlags(SDValue Op,unsigned TF,SelectionDAG & DAG) const205709467b48Spatrick SDValue SparcTargetLowering::withTargetFlags(SDValue Op, unsigned TF,
205809467b48Spatrick SelectionDAG &DAG) const {
205909467b48Spatrick if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op))
206009467b48Spatrick return DAG.getTargetGlobalAddress(GA->getGlobal(),
206109467b48Spatrick SDLoc(GA),
206209467b48Spatrick GA->getValueType(0),
206309467b48Spatrick GA->getOffset(), TF);
206409467b48Spatrick
206509467b48Spatrick if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op))
2066097a140dSpatrick return DAG.getTargetConstantPool(CP->getConstVal(), CP->getValueType(0),
2067097a140dSpatrick CP->getAlign(), CP->getOffset(), TF);
206809467b48Spatrick
206909467b48Spatrick if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op))
207009467b48Spatrick return DAG.getTargetBlockAddress(BA->getBlockAddress(),
207109467b48Spatrick Op.getValueType(),
207209467b48Spatrick 0,
207309467b48Spatrick TF);
207409467b48Spatrick
207509467b48Spatrick if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op))
207609467b48Spatrick return DAG.getTargetExternalSymbol(ES->getSymbol(),
207709467b48Spatrick ES->getValueType(0), TF);
207809467b48Spatrick
207909467b48Spatrick llvm_unreachable("Unhandled address SDNode");
208009467b48Spatrick }
208109467b48Spatrick
208209467b48Spatrick // Split Op into high and low parts according to HiTF and LoTF.
208309467b48Spatrick // Return an ADD node combining the parts.
makeHiLoPair(SDValue Op,unsigned HiTF,unsigned LoTF,SelectionDAG & DAG) const208409467b48Spatrick SDValue SparcTargetLowering::makeHiLoPair(SDValue Op,
208509467b48Spatrick unsigned HiTF, unsigned LoTF,
208609467b48Spatrick SelectionDAG &DAG) const {
208709467b48Spatrick SDLoc DL(Op);
208809467b48Spatrick EVT VT = Op.getValueType();
208909467b48Spatrick SDValue Hi = DAG.getNode(SPISD::Hi, DL, VT, withTargetFlags(Op, HiTF, DAG));
209009467b48Spatrick SDValue Lo = DAG.getNode(SPISD::Lo, DL, VT, withTargetFlags(Op, LoTF, DAG));
209109467b48Spatrick return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo);
209209467b48Spatrick }
209309467b48Spatrick
209409467b48Spatrick // Build SDNodes for producing an address from a GlobalAddress, ConstantPool,
209509467b48Spatrick // or ExternalSymbol SDNode.
makeAddress(SDValue Op,SelectionDAG & DAG) const209609467b48Spatrick SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const {
209709467b48Spatrick SDLoc DL(Op);
209809467b48Spatrick EVT VT = getPointerTy(DAG.getDataLayout());
209909467b48Spatrick
210009467b48Spatrick // Handle PIC mode first. SPARC needs a got load for every variable!
210109467b48Spatrick if (isPositionIndependent()) {
210209467b48Spatrick const Module *M = DAG.getMachineFunction().getFunction().getParent();
210309467b48Spatrick PICLevel::Level picLevel = M->getPICLevel();
210409467b48Spatrick SDValue Idx;
210509467b48Spatrick
210609467b48Spatrick if (picLevel == PICLevel::SmallPIC) {
210709467b48Spatrick // This is the pic13 code model, the GOT is known to be smaller than 8KiB.
210809467b48Spatrick Idx = DAG.getNode(SPISD::Lo, DL, Op.getValueType(),
210909467b48Spatrick withTargetFlags(Op, SparcMCExpr::VK_Sparc_GOT13, DAG));
211009467b48Spatrick } else {
211109467b48Spatrick // This is the pic32 code model, the GOT is known to be smaller than 4GB.
211209467b48Spatrick Idx = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
211309467b48Spatrick SparcMCExpr::VK_Sparc_GOT10, DAG);
211409467b48Spatrick }
211509467b48Spatrick
211609467b48Spatrick SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT);
211709467b48Spatrick SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Idx);
211809467b48Spatrick // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
211909467b48Spatrick // function has calls.
212009467b48Spatrick MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
212109467b48Spatrick MFI.setHasCalls(true);
212209467b48Spatrick return DAG.getLoad(VT, DL, DAG.getEntryNode(), AbsAddr,
212309467b48Spatrick MachinePointerInfo::getGOT(DAG.getMachineFunction()));
212409467b48Spatrick }
212509467b48Spatrick
212609467b48Spatrick // This is one of the absolute code models.
212709467b48Spatrick switch(getTargetMachine().getCodeModel()) {
212809467b48Spatrick default:
212909467b48Spatrick llvm_unreachable("Unsupported absolute code model");
213009467b48Spatrick case CodeModel::Small:
213109467b48Spatrick // abs32.
213209467b48Spatrick return makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
213309467b48Spatrick SparcMCExpr::VK_Sparc_LO, DAG);
213409467b48Spatrick case CodeModel::Medium: {
213509467b48Spatrick // abs44.
213609467b48Spatrick SDValue H44 = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_H44,
213709467b48Spatrick SparcMCExpr::VK_Sparc_M44, DAG);
213809467b48Spatrick H44 = DAG.getNode(ISD::SHL, DL, VT, H44, DAG.getConstant(12, DL, MVT::i32));
213909467b48Spatrick SDValue L44 = withTargetFlags(Op, SparcMCExpr::VK_Sparc_L44, DAG);
214009467b48Spatrick L44 = DAG.getNode(SPISD::Lo, DL, VT, L44);
214109467b48Spatrick return DAG.getNode(ISD::ADD, DL, VT, H44, L44);
214209467b48Spatrick }
214309467b48Spatrick case CodeModel::Large: {
214409467b48Spatrick // abs64.
214509467b48Spatrick SDValue Hi = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HH,
214609467b48Spatrick SparcMCExpr::VK_Sparc_HM, DAG);
214709467b48Spatrick Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, DAG.getConstant(32, DL, MVT::i32));
214809467b48Spatrick SDValue Lo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
214909467b48Spatrick SparcMCExpr::VK_Sparc_LO, DAG);
215009467b48Spatrick return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo);
215109467b48Spatrick }
215209467b48Spatrick }
215309467b48Spatrick }
215409467b48Spatrick
LowerGlobalAddress(SDValue Op,SelectionDAG & DAG) const215509467b48Spatrick SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op,
215609467b48Spatrick SelectionDAG &DAG) const {
215709467b48Spatrick return makeAddress(Op, DAG);
215809467b48Spatrick }
215909467b48Spatrick
LowerConstantPool(SDValue Op,SelectionDAG & DAG) const216009467b48Spatrick SDValue SparcTargetLowering::LowerConstantPool(SDValue Op,
216109467b48Spatrick SelectionDAG &DAG) const {
216209467b48Spatrick return makeAddress(Op, DAG);
216309467b48Spatrick }
216409467b48Spatrick
LowerBlockAddress(SDValue Op,SelectionDAG & DAG) const216509467b48Spatrick SDValue SparcTargetLowering::LowerBlockAddress(SDValue Op,
216609467b48Spatrick SelectionDAG &DAG) const {
216709467b48Spatrick return makeAddress(Op, DAG);
216809467b48Spatrick }
216909467b48Spatrick
LowerGlobalTLSAddress(SDValue Op,SelectionDAG & DAG) const217009467b48Spatrick SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op,
217109467b48Spatrick SelectionDAG &DAG) const {
217209467b48Spatrick
217309467b48Spatrick GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
217409467b48Spatrick if (DAG.getTarget().useEmulatedTLS())
217509467b48Spatrick return LowerToTLSEmulatedModel(GA, DAG);
217609467b48Spatrick
217709467b48Spatrick SDLoc DL(GA);
217809467b48Spatrick const GlobalValue *GV = GA->getGlobal();
217909467b48Spatrick EVT PtrVT = getPointerTy(DAG.getDataLayout());
218009467b48Spatrick
218109467b48Spatrick TLSModel::Model model = getTargetMachine().getTLSModel(GV);
218209467b48Spatrick
218309467b48Spatrick if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) {
218409467b48Spatrick unsigned HiTF = ((model == TLSModel::GeneralDynamic)
218509467b48Spatrick ? SparcMCExpr::VK_Sparc_TLS_GD_HI22
218609467b48Spatrick : SparcMCExpr::VK_Sparc_TLS_LDM_HI22);
218709467b48Spatrick unsigned LoTF = ((model == TLSModel::GeneralDynamic)
218809467b48Spatrick ? SparcMCExpr::VK_Sparc_TLS_GD_LO10
218909467b48Spatrick : SparcMCExpr::VK_Sparc_TLS_LDM_LO10);
219009467b48Spatrick unsigned addTF = ((model == TLSModel::GeneralDynamic)
219109467b48Spatrick ? SparcMCExpr::VK_Sparc_TLS_GD_ADD
219209467b48Spatrick : SparcMCExpr::VK_Sparc_TLS_LDM_ADD);
219309467b48Spatrick unsigned callTF = ((model == TLSModel::GeneralDynamic)
219409467b48Spatrick ? SparcMCExpr::VK_Sparc_TLS_GD_CALL
219509467b48Spatrick : SparcMCExpr::VK_Sparc_TLS_LDM_CALL);
219609467b48Spatrick
219709467b48Spatrick SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG);
219809467b48Spatrick SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
219909467b48Spatrick SDValue Argument = DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Base, HiLo,
220009467b48Spatrick withTargetFlags(Op, addTF, DAG));
220109467b48Spatrick
220209467b48Spatrick SDValue Chain = DAG.getEntryNode();
220309467b48Spatrick SDValue InFlag;
220409467b48Spatrick
220509467b48Spatrick Chain = DAG.getCALLSEQ_START(Chain, 1, 0, DL);
220609467b48Spatrick Chain = DAG.getCopyToReg(Chain, DL, SP::O0, Argument, InFlag);
220709467b48Spatrick InFlag = Chain.getValue(1);
220809467b48Spatrick SDValue Callee = DAG.getTargetExternalSymbol("__tls_get_addr", PtrVT);
220909467b48Spatrick SDValue Symbol = withTargetFlags(Op, callTF, DAG);
221009467b48Spatrick
221109467b48Spatrick SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
221209467b48Spatrick const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask(
221309467b48Spatrick DAG.getMachineFunction(), CallingConv::C);
221409467b48Spatrick assert(Mask && "Missing call preserved mask for calling convention");
221509467b48Spatrick SDValue Ops[] = {Chain,
221609467b48Spatrick Callee,
221709467b48Spatrick Symbol,
221809467b48Spatrick DAG.getRegister(SP::O0, PtrVT),
221909467b48Spatrick DAG.getRegisterMask(Mask),
222009467b48Spatrick InFlag};
222109467b48Spatrick Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, Ops);
222209467b48Spatrick InFlag = Chain.getValue(1);
2223*a96b3639Srobert Chain = DAG.getCALLSEQ_END(Chain, 1, 0, InFlag, DL);
222409467b48Spatrick InFlag = Chain.getValue(1);
222509467b48Spatrick SDValue Ret = DAG.getCopyFromReg(Chain, DL, SP::O0, PtrVT, InFlag);
222609467b48Spatrick
222709467b48Spatrick if (model != TLSModel::LocalDynamic)
222809467b48Spatrick return Ret;
222909467b48Spatrick
223009467b48Spatrick SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
223109467b48Spatrick withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG));
223209467b48Spatrick SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
223309467b48Spatrick withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG));
223409467b48Spatrick HiLo = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
223509467b48Spatrick return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo,
223609467b48Spatrick withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG));
223709467b48Spatrick }
223809467b48Spatrick
223909467b48Spatrick if (model == TLSModel::InitialExec) {
224009467b48Spatrick unsigned ldTF = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX
224109467b48Spatrick : SparcMCExpr::VK_Sparc_TLS_IE_LD);
224209467b48Spatrick
224309467b48Spatrick SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
224409467b48Spatrick
224509467b48Spatrick // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
224609467b48Spatrick // function has calls.
224709467b48Spatrick MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
224809467b48Spatrick MFI.setHasCalls(true);
224909467b48Spatrick
225009467b48Spatrick SDValue TGA = makeHiLoPair(Op,
225109467b48Spatrick SparcMCExpr::VK_Sparc_TLS_IE_HI22,
225209467b48Spatrick SparcMCExpr::VK_Sparc_TLS_IE_LO10, DAG);
225309467b48Spatrick SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base, TGA);
225409467b48Spatrick SDValue Offset = DAG.getNode(SPISD::TLS_LD,
225509467b48Spatrick DL, PtrVT, Ptr,
225609467b48Spatrick withTargetFlags(Op, ldTF, DAG));
225709467b48Spatrick return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT,
225809467b48Spatrick DAG.getRegister(SP::G7, PtrVT), Offset,
225909467b48Spatrick withTargetFlags(Op,
226009467b48Spatrick SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG));
226109467b48Spatrick }
226209467b48Spatrick
226309467b48Spatrick assert(model == TLSModel::LocalExec);
226409467b48Spatrick SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
226509467b48Spatrick withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG));
226609467b48Spatrick SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
226709467b48Spatrick withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG));
226809467b48Spatrick SDValue Offset = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
226909467b48Spatrick
227009467b48Spatrick return DAG.getNode(ISD::ADD, DL, PtrVT,
227109467b48Spatrick DAG.getRegister(SP::G7, PtrVT), Offset);
227209467b48Spatrick }
227309467b48Spatrick
LowerF128_LibCallArg(SDValue Chain,ArgListTy & Args,SDValue Arg,const SDLoc & DL,SelectionDAG & DAG) const227409467b48Spatrick SDValue SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain,
227509467b48Spatrick ArgListTy &Args, SDValue Arg,
227609467b48Spatrick const SDLoc &DL,
227709467b48Spatrick SelectionDAG &DAG) const {
227809467b48Spatrick MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
227909467b48Spatrick EVT ArgVT = Arg.getValueType();
228009467b48Spatrick Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
228109467b48Spatrick
228209467b48Spatrick ArgListEntry Entry;
228309467b48Spatrick Entry.Node = Arg;
228409467b48Spatrick Entry.Ty = ArgTy;
228509467b48Spatrick
228609467b48Spatrick if (ArgTy->isFP128Ty()) {
228709467b48Spatrick // Create a stack object and pass the pointer to the library function.
2288097a140dSpatrick int FI = MFI.CreateStackObject(16, Align(8), false);
228909467b48Spatrick SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
229009467b48Spatrick Chain = DAG.getStore(Chain, DL, Entry.Node, FIPtr, MachinePointerInfo(),
2291a0747c9fSpatrick Align(8));
229209467b48Spatrick
229309467b48Spatrick Entry.Node = FIPtr;
229409467b48Spatrick Entry.Ty = PointerType::getUnqual(ArgTy);
229509467b48Spatrick }
229609467b48Spatrick Args.push_back(Entry);
229709467b48Spatrick return Chain;
229809467b48Spatrick }
229909467b48Spatrick
230009467b48Spatrick SDValue
LowerF128Op(SDValue Op,SelectionDAG & DAG,const char * LibFuncName,unsigned numArgs) const230109467b48Spatrick SparcTargetLowering::LowerF128Op(SDValue Op, SelectionDAG &DAG,
230209467b48Spatrick const char *LibFuncName,
230309467b48Spatrick unsigned numArgs) const {
230409467b48Spatrick
230509467b48Spatrick ArgListTy Args;
230609467b48Spatrick
230709467b48Spatrick MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
230809467b48Spatrick auto PtrVT = getPointerTy(DAG.getDataLayout());
230909467b48Spatrick
231009467b48Spatrick SDValue Callee = DAG.getExternalSymbol(LibFuncName, PtrVT);
231109467b48Spatrick Type *RetTy = Op.getValueType().getTypeForEVT(*DAG.getContext());
231209467b48Spatrick Type *RetTyABI = RetTy;
231309467b48Spatrick SDValue Chain = DAG.getEntryNode();
231409467b48Spatrick SDValue RetPtr;
231509467b48Spatrick
231609467b48Spatrick if (RetTy->isFP128Ty()) {
231709467b48Spatrick // Create a Stack Object to receive the return value of type f128.
231809467b48Spatrick ArgListEntry Entry;
2319097a140dSpatrick int RetFI = MFI.CreateStackObject(16, Align(8), false);
232009467b48Spatrick RetPtr = DAG.getFrameIndex(RetFI, PtrVT);
232109467b48Spatrick Entry.Node = RetPtr;
232209467b48Spatrick Entry.Ty = PointerType::getUnqual(RetTy);
2323*a96b3639Srobert if (!Subtarget->is64Bit()) {
232409467b48Spatrick Entry.IsSRet = true;
2325*a96b3639Srobert Entry.IndirectType = RetTy;
2326*a96b3639Srobert }
232709467b48Spatrick Entry.IsReturned = false;
232809467b48Spatrick Args.push_back(Entry);
232909467b48Spatrick RetTyABI = Type::getVoidTy(*DAG.getContext());
233009467b48Spatrick }
233109467b48Spatrick
233209467b48Spatrick assert(Op->getNumOperands() >= numArgs && "Not enough operands!");
233309467b48Spatrick for (unsigned i = 0, e = numArgs; i != e; ++i) {
233409467b48Spatrick Chain = LowerF128_LibCallArg(Chain, Args, Op.getOperand(i), SDLoc(Op), DAG);
233509467b48Spatrick }
233609467b48Spatrick TargetLowering::CallLoweringInfo CLI(DAG);
233709467b48Spatrick CLI.setDebugLoc(SDLoc(Op)).setChain(Chain)
233809467b48Spatrick .setCallee(CallingConv::C, RetTyABI, Callee, std::move(Args));
233909467b48Spatrick
234009467b48Spatrick std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
234109467b48Spatrick
234209467b48Spatrick // chain is in second result.
234309467b48Spatrick if (RetTyABI == RetTy)
234409467b48Spatrick return CallInfo.first;
234509467b48Spatrick
234609467b48Spatrick assert (RetTy->isFP128Ty() && "Unexpected return type!");
234709467b48Spatrick
234809467b48Spatrick Chain = CallInfo.second;
234909467b48Spatrick
235009467b48Spatrick // Load RetPtr to get the return value.
235109467b48Spatrick return DAG.getLoad(Op.getValueType(), SDLoc(Op), Chain, RetPtr,
2352a0747c9fSpatrick MachinePointerInfo(), Align(8));
235309467b48Spatrick }
235409467b48Spatrick
LowerF128Compare(SDValue LHS,SDValue RHS,unsigned & SPCC,const SDLoc & DL,SelectionDAG & DAG) const235509467b48Spatrick SDValue SparcTargetLowering::LowerF128Compare(SDValue LHS, SDValue RHS,
235609467b48Spatrick unsigned &SPCC, const SDLoc &DL,
235709467b48Spatrick SelectionDAG &DAG) const {
235809467b48Spatrick
235909467b48Spatrick const char *LibCall = nullptr;
236009467b48Spatrick bool is64Bit = Subtarget->is64Bit();
236109467b48Spatrick switch(SPCC) {
236209467b48Spatrick default: llvm_unreachable("Unhandled conditional code!");
236309467b48Spatrick case SPCC::FCC_E : LibCall = is64Bit? "_Qp_feq" : "_Q_feq"; break;
236409467b48Spatrick case SPCC::FCC_NE : LibCall = is64Bit? "_Qp_fne" : "_Q_fne"; break;
236509467b48Spatrick case SPCC::FCC_L : LibCall = is64Bit? "_Qp_flt" : "_Q_flt"; break;
236609467b48Spatrick case SPCC::FCC_G : LibCall = is64Bit? "_Qp_fgt" : "_Q_fgt"; break;
236709467b48Spatrick case SPCC::FCC_LE : LibCall = is64Bit? "_Qp_fle" : "_Q_fle"; break;
236809467b48Spatrick case SPCC::FCC_GE : LibCall = is64Bit? "_Qp_fge" : "_Q_fge"; break;
236909467b48Spatrick case SPCC::FCC_UL :
237009467b48Spatrick case SPCC::FCC_ULE:
237109467b48Spatrick case SPCC::FCC_UG :
237209467b48Spatrick case SPCC::FCC_UGE:
237309467b48Spatrick case SPCC::FCC_U :
237409467b48Spatrick case SPCC::FCC_O :
237509467b48Spatrick case SPCC::FCC_LG :
237609467b48Spatrick case SPCC::FCC_UE : LibCall = is64Bit? "_Qp_cmp" : "_Q_cmp"; break;
237709467b48Spatrick }
237809467b48Spatrick
237909467b48Spatrick auto PtrVT = getPointerTy(DAG.getDataLayout());
238009467b48Spatrick SDValue Callee = DAG.getExternalSymbol(LibCall, PtrVT);
238109467b48Spatrick Type *RetTy = Type::getInt32Ty(*DAG.getContext());
238209467b48Spatrick ArgListTy Args;
238309467b48Spatrick SDValue Chain = DAG.getEntryNode();
238409467b48Spatrick Chain = LowerF128_LibCallArg(Chain, Args, LHS, DL, DAG);
238509467b48Spatrick Chain = LowerF128_LibCallArg(Chain, Args, RHS, DL, DAG);
238609467b48Spatrick
238709467b48Spatrick TargetLowering::CallLoweringInfo CLI(DAG);
238809467b48Spatrick CLI.setDebugLoc(DL).setChain(Chain)
238909467b48Spatrick .setCallee(CallingConv::C, RetTy, Callee, std::move(Args));
239009467b48Spatrick
239109467b48Spatrick std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
239209467b48Spatrick
239309467b48Spatrick // result is in first, and chain is in second result.
239409467b48Spatrick SDValue Result = CallInfo.first;
239509467b48Spatrick
239609467b48Spatrick switch(SPCC) {
239709467b48Spatrick default: {
2398097a140dSpatrick SDValue RHS = DAG.getConstant(0, DL, Result.getValueType());
239909467b48Spatrick SPCC = SPCC::ICC_NE;
240009467b48Spatrick return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
240109467b48Spatrick }
240209467b48Spatrick case SPCC::FCC_UL : {
240309467b48Spatrick SDValue Mask = DAG.getConstant(1, DL, Result.getValueType());
240409467b48Spatrick Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask);
2405097a140dSpatrick SDValue RHS = DAG.getConstant(0, DL, Result.getValueType());
240609467b48Spatrick SPCC = SPCC::ICC_NE;
240709467b48Spatrick return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
240809467b48Spatrick }
240909467b48Spatrick case SPCC::FCC_ULE: {
2410097a140dSpatrick SDValue RHS = DAG.getConstant(2, DL, Result.getValueType());
241109467b48Spatrick SPCC = SPCC::ICC_NE;
241209467b48Spatrick return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
241309467b48Spatrick }
241409467b48Spatrick case SPCC::FCC_UG : {
2415097a140dSpatrick SDValue RHS = DAG.getConstant(1, DL, Result.getValueType());
241609467b48Spatrick SPCC = SPCC::ICC_G;
241709467b48Spatrick return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
241809467b48Spatrick }
241909467b48Spatrick case SPCC::FCC_UGE: {
2420097a140dSpatrick SDValue RHS = DAG.getConstant(1, DL, Result.getValueType());
242109467b48Spatrick SPCC = SPCC::ICC_NE;
242209467b48Spatrick return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
242309467b48Spatrick }
242409467b48Spatrick
242509467b48Spatrick case SPCC::FCC_U : {
2426097a140dSpatrick SDValue RHS = DAG.getConstant(3, DL, Result.getValueType());
242709467b48Spatrick SPCC = SPCC::ICC_E;
242809467b48Spatrick return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
242909467b48Spatrick }
243009467b48Spatrick case SPCC::FCC_O : {
2431097a140dSpatrick SDValue RHS = DAG.getConstant(3, DL, Result.getValueType());
243209467b48Spatrick SPCC = SPCC::ICC_NE;
243309467b48Spatrick return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
243409467b48Spatrick }
243509467b48Spatrick case SPCC::FCC_LG : {
243609467b48Spatrick SDValue Mask = DAG.getConstant(3, DL, Result.getValueType());
243709467b48Spatrick Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask);
2438097a140dSpatrick SDValue RHS = DAG.getConstant(0, DL, Result.getValueType());
243909467b48Spatrick SPCC = SPCC::ICC_NE;
244009467b48Spatrick return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
244109467b48Spatrick }
244209467b48Spatrick case SPCC::FCC_UE : {
244309467b48Spatrick SDValue Mask = DAG.getConstant(3, DL, Result.getValueType());
244409467b48Spatrick Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask);
2445097a140dSpatrick SDValue RHS = DAG.getConstant(0, DL, Result.getValueType());
244609467b48Spatrick SPCC = SPCC::ICC_E;
244709467b48Spatrick return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
244809467b48Spatrick }
244909467b48Spatrick }
245009467b48Spatrick }
245109467b48Spatrick
245209467b48Spatrick static SDValue
LowerF128_FPEXTEND(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI)245309467b48Spatrick LowerF128_FPEXTEND(SDValue Op, SelectionDAG &DAG,
245409467b48Spatrick const SparcTargetLowering &TLI) {
245509467b48Spatrick
245609467b48Spatrick if (Op.getOperand(0).getValueType() == MVT::f64)
245709467b48Spatrick return TLI.LowerF128Op(Op, DAG,
245809467b48Spatrick TLI.getLibcallName(RTLIB::FPEXT_F64_F128), 1);
245909467b48Spatrick
246009467b48Spatrick if (Op.getOperand(0).getValueType() == MVT::f32)
246109467b48Spatrick return TLI.LowerF128Op(Op, DAG,
246209467b48Spatrick TLI.getLibcallName(RTLIB::FPEXT_F32_F128), 1);
246309467b48Spatrick
246409467b48Spatrick llvm_unreachable("fpextend with non-float operand!");
246509467b48Spatrick return SDValue();
246609467b48Spatrick }
246709467b48Spatrick
246809467b48Spatrick static SDValue
LowerF128_FPROUND(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI)246909467b48Spatrick LowerF128_FPROUND(SDValue Op, SelectionDAG &DAG,
247009467b48Spatrick const SparcTargetLowering &TLI) {
247109467b48Spatrick // FP_ROUND on f64 and f32 are legal.
247209467b48Spatrick if (Op.getOperand(0).getValueType() != MVT::f128)
247309467b48Spatrick return Op;
247409467b48Spatrick
247509467b48Spatrick if (Op.getValueType() == MVT::f64)
247609467b48Spatrick return TLI.LowerF128Op(Op, DAG,
247709467b48Spatrick TLI.getLibcallName(RTLIB::FPROUND_F128_F64), 1);
247809467b48Spatrick if (Op.getValueType() == MVT::f32)
247909467b48Spatrick return TLI.LowerF128Op(Op, DAG,
248009467b48Spatrick TLI.getLibcallName(RTLIB::FPROUND_F128_F32), 1);
248109467b48Spatrick
248209467b48Spatrick llvm_unreachable("fpround to non-float!");
248309467b48Spatrick return SDValue();
248409467b48Spatrick }
248509467b48Spatrick
LowerFP_TO_SINT(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad)248609467b48Spatrick static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG,
248709467b48Spatrick const SparcTargetLowering &TLI,
248809467b48Spatrick bool hasHardQuad) {
248909467b48Spatrick SDLoc dl(Op);
249009467b48Spatrick EVT VT = Op.getValueType();
249109467b48Spatrick assert(VT == MVT::i32 || VT == MVT::i64);
249209467b48Spatrick
249309467b48Spatrick // Expand f128 operations to fp128 abi calls.
249409467b48Spatrick if (Op.getOperand(0).getValueType() == MVT::f128
249509467b48Spatrick && (!hasHardQuad || !TLI.isTypeLegal(VT))) {
249609467b48Spatrick const char *libName = TLI.getLibcallName(VT == MVT::i32
249709467b48Spatrick ? RTLIB::FPTOSINT_F128_I32
249809467b48Spatrick : RTLIB::FPTOSINT_F128_I64);
249909467b48Spatrick return TLI.LowerF128Op(Op, DAG, libName, 1);
250009467b48Spatrick }
250109467b48Spatrick
250209467b48Spatrick // Expand if the resulting type is illegal.
250309467b48Spatrick if (!TLI.isTypeLegal(VT))
250409467b48Spatrick return SDValue();
250509467b48Spatrick
250609467b48Spatrick // Otherwise, Convert the fp value to integer in an FP register.
250709467b48Spatrick if (VT == MVT::i32)
250809467b48Spatrick Op = DAG.getNode(SPISD::FTOI, dl, MVT::f32, Op.getOperand(0));
250909467b48Spatrick else
251009467b48Spatrick Op = DAG.getNode(SPISD::FTOX, dl, MVT::f64, Op.getOperand(0));
251109467b48Spatrick
251209467b48Spatrick return DAG.getNode(ISD::BITCAST, dl, VT, Op);
251309467b48Spatrick }
251409467b48Spatrick
LowerSINT_TO_FP(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad)251509467b48Spatrick static SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG,
251609467b48Spatrick const SparcTargetLowering &TLI,
251709467b48Spatrick bool hasHardQuad) {
251809467b48Spatrick SDLoc dl(Op);
251909467b48Spatrick EVT OpVT = Op.getOperand(0).getValueType();
252009467b48Spatrick assert(OpVT == MVT::i32 || (OpVT == MVT::i64));
252109467b48Spatrick
252209467b48Spatrick EVT floatVT = (OpVT == MVT::i32) ? MVT::f32 : MVT::f64;
252309467b48Spatrick
252409467b48Spatrick // Expand f128 operations to fp128 ABI calls.
252509467b48Spatrick if (Op.getValueType() == MVT::f128
252609467b48Spatrick && (!hasHardQuad || !TLI.isTypeLegal(OpVT))) {
252709467b48Spatrick const char *libName = TLI.getLibcallName(OpVT == MVT::i32
252809467b48Spatrick ? RTLIB::SINTTOFP_I32_F128
252909467b48Spatrick : RTLIB::SINTTOFP_I64_F128);
253009467b48Spatrick return TLI.LowerF128Op(Op, DAG, libName, 1);
253109467b48Spatrick }
253209467b48Spatrick
253309467b48Spatrick // Expand if the operand type is illegal.
253409467b48Spatrick if (!TLI.isTypeLegal(OpVT))
253509467b48Spatrick return SDValue();
253609467b48Spatrick
253709467b48Spatrick // Otherwise, Convert the int value to FP in an FP register.
253809467b48Spatrick SDValue Tmp = DAG.getNode(ISD::BITCAST, dl, floatVT, Op.getOperand(0));
253909467b48Spatrick unsigned opcode = (OpVT == MVT::i32)? SPISD::ITOF : SPISD::XTOF;
254009467b48Spatrick return DAG.getNode(opcode, dl, Op.getValueType(), Tmp);
254109467b48Spatrick }
254209467b48Spatrick
LowerFP_TO_UINT(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad)254309467b48Spatrick static SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG,
254409467b48Spatrick const SparcTargetLowering &TLI,
254509467b48Spatrick bool hasHardQuad) {
254609467b48Spatrick SDLoc dl(Op);
254709467b48Spatrick EVT VT = Op.getValueType();
254809467b48Spatrick
254909467b48Spatrick // Expand if it does not involve f128 or the target has support for
255009467b48Spatrick // quad floating point instructions and the resulting type is legal.
255109467b48Spatrick if (Op.getOperand(0).getValueType() != MVT::f128 ||
255209467b48Spatrick (hasHardQuad && TLI.isTypeLegal(VT)))
255309467b48Spatrick return SDValue();
255409467b48Spatrick
255509467b48Spatrick assert(VT == MVT::i32 || VT == MVT::i64);
255609467b48Spatrick
255709467b48Spatrick return TLI.LowerF128Op(Op, DAG,
255809467b48Spatrick TLI.getLibcallName(VT == MVT::i32
255909467b48Spatrick ? RTLIB::FPTOUINT_F128_I32
256009467b48Spatrick : RTLIB::FPTOUINT_F128_I64),
256109467b48Spatrick 1);
256209467b48Spatrick }
256309467b48Spatrick
LowerUINT_TO_FP(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad)256409467b48Spatrick static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG,
256509467b48Spatrick const SparcTargetLowering &TLI,
256609467b48Spatrick bool hasHardQuad) {
256709467b48Spatrick SDLoc dl(Op);
256809467b48Spatrick EVT OpVT = Op.getOperand(0).getValueType();
256909467b48Spatrick assert(OpVT == MVT::i32 || OpVT == MVT::i64);
257009467b48Spatrick
257109467b48Spatrick // Expand if it does not involve f128 or the target has support for
257209467b48Spatrick // quad floating point instructions and the operand type is legal.
257309467b48Spatrick if (Op.getValueType() != MVT::f128 || (hasHardQuad && TLI.isTypeLegal(OpVT)))
257409467b48Spatrick return SDValue();
257509467b48Spatrick
257609467b48Spatrick return TLI.LowerF128Op(Op, DAG,
257709467b48Spatrick TLI.getLibcallName(OpVT == MVT::i32
257809467b48Spatrick ? RTLIB::UINTTOFP_I32_F128
257909467b48Spatrick : RTLIB::UINTTOFP_I64_F128),
258009467b48Spatrick 1);
258109467b48Spatrick }
258209467b48Spatrick
LowerBR_CC(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad,bool isV9)258309467b48Spatrick static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
2584*a96b3639Srobert const SparcTargetLowering &TLI, bool hasHardQuad,
2585*a96b3639Srobert bool isV9) {
258609467b48Spatrick SDValue Chain = Op.getOperand(0);
258709467b48Spatrick ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
258809467b48Spatrick SDValue LHS = Op.getOperand(2);
258909467b48Spatrick SDValue RHS = Op.getOperand(3);
259009467b48Spatrick SDValue Dest = Op.getOperand(4);
259109467b48Spatrick SDLoc dl(Op);
259209467b48Spatrick unsigned Opc, SPCC = ~0U;
259309467b48Spatrick
259409467b48Spatrick // If this is a br_cc of a "setcc", and if the setcc got lowered into
259509467b48Spatrick // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
259609467b48Spatrick LookThroughSetCC(LHS, RHS, CC, SPCC);
2597*a96b3639Srobert assert(LHS.getValueType() == RHS.getValueType());
259809467b48Spatrick
259909467b48Spatrick // Get the condition flag.
260009467b48Spatrick SDValue CompareFlag;
260109467b48Spatrick if (LHS.getValueType().isInteger()) {
260209467b48Spatrick CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS);
260309467b48Spatrick if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
2604*a96b3639Srobert if (isV9)
260509467b48Spatrick // 32-bit compares use the icc flags, 64-bit uses the xcc flags.
2606*a96b3639Srobert Opc = LHS.getValueType() == MVT::i32 ? SPISD::BPICC : SPISD::BPXCC;
2607*a96b3639Srobert else
2608*a96b3639Srobert // Non-v9 targets don't have xcc.
2609*a96b3639Srobert Opc = SPISD::BRICC;
261009467b48Spatrick } else {
261109467b48Spatrick if (!hasHardQuad && LHS.getValueType() == MVT::f128) {
261209467b48Spatrick if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
261309467b48Spatrick CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG);
2614*a96b3639Srobert Opc = isV9 ? SPISD::BPICC : SPISD::BRICC;
261509467b48Spatrick } else {
2616*a96b3639Srobert unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC;
2617*a96b3639Srobert CompareFlag = DAG.getNode(CmpOpc, dl, MVT::Glue, LHS, RHS);
261809467b48Spatrick if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
2619*a96b3639Srobert Opc = isV9 ? SPISD::BRFCC_V9 : SPISD::BRFCC;
262009467b48Spatrick }
262109467b48Spatrick }
262209467b48Spatrick return DAG.getNode(Opc, dl, MVT::Other, Chain, Dest,
262309467b48Spatrick DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag);
262409467b48Spatrick }
262509467b48Spatrick
LowerSELECT_CC(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad,bool isV9,bool is64Bit)262609467b48Spatrick static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2627*a96b3639Srobert const SparcTargetLowering &TLI, bool hasHardQuad,
2628*a96b3639Srobert bool isV9, bool is64Bit) {
262909467b48Spatrick SDValue LHS = Op.getOperand(0);
263009467b48Spatrick SDValue RHS = Op.getOperand(1);
263109467b48Spatrick ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
263209467b48Spatrick SDValue TrueVal = Op.getOperand(2);
263309467b48Spatrick SDValue FalseVal = Op.getOperand(3);
263409467b48Spatrick SDLoc dl(Op);
263509467b48Spatrick unsigned Opc, SPCC = ~0U;
263609467b48Spatrick
263709467b48Spatrick // If this is a select_cc of a "setcc", and if the setcc got lowered into
263809467b48Spatrick // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
263909467b48Spatrick LookThroughSetCC(LHS, RHS, CC, SPCC);
2640*a96b3639Srobert assert(LHS.getValueType() == RHS.getValueType());
264109467b48Spatrick
264209467b48Spatrick SDValue CompareFlag;
264309467b48Spatrick if (LHS.getValueType().isInteger()) {
2644*a96b3639Srobert // On V9 processors running in 64-bit mode, if CC compares two `i64`s
2645*a96b3639Srobert // and the RHS is zero we might be able to use a specialized select.
2646*a96b3639Srobert // All SELECT_CC between any two scalar integer types are eligible for
2647*a96b3639Srobert // lowering to specialized instructions. Additionally, f32 and f64 types
2648*a96b3639Srobert // are also eligible, but for f128 we can only use the specialized
2649*a96b3639Srobert // instruction when we have hardquad.
2650*a96b3639Srobert EVT ValType = TrueVal.getValueType();
2651*a96b3639Srobert bool IsEligibleType = ValType.isScalarInteger() || ValType == MVT::f32 ||
2652*a96b3639Srobert ValType == MVT::f64 ||
2653*a96b3639Srobert (ValType == MVT::f128 && hasHardQuad);
2654*a96b3639Srobert if (is64Bit && isV9 && LHS.getValueType() == MVT::i64 &&
2655*a96b3639Srobert isNullConstant(RHS) && !ISD::isUnsignedIntSetCC(CC) && IsEligibleType)
2656*a96b3639Srobert return DAG.getNode(
2657*a96b3639Srobert SPISD::SELECT_REG, dl, TrueVal.getValueType(), TrueVal, FalseVal,
2658*a96b3639Srobert DAG.getConstant(intCondCCodeToRcond(CC), dl, MVT::i32), LHS);
2659*a96b3639Srobert
266009467b48Spatrick CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS);
266109467b48Spatrick Opc = LHS.getValueType() == MVT::i32 ?
266209467b48Spatrick SPISD::SELECT_ICC : SPISD::SELECT_XCC;
266309467b48Spatrick if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
266409467b48Spatrick } else {
266509467b48Spatrick if (!hasHardQuad && LHS.getValueType() == MVT::f128) {
266609467b48Spatrick if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
266709467b48Spatrick CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG);
266809467b48Spatrick Opc = SPISD::SELECT_ICC;
266909467b48Spatrick } else {
2670*a96b3639Srobert unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC;
2671*a96b3639Srobert CompareFlag = DAG.getNode(CmpOpc, dl, MVT::Glue, LHS, RHS);
267209467b48Spatrick Opc = SPISD::SELECT_FCC;
267309467b48Spatrick if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
267409467b48Spatrick }
267509467b48Spatrick }
267609467b48Spatrick return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal,
267709467b48Spatrick DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag);
267809467b48Spatrick }
267909467b48Spatrick
LowerVASTART(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI)268009467b48Spatrick static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG,
268109467b48Spatrick const SparcTargetLowering &TLI) {
268209467b48Spatrick MachineFunction &MF = DAG.getMachineFunction();
268309467b48Spatrick SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
268409467b48Spatrick auto PtrVT = TLI.getPointerTy(DAG.getDataLayout());
268509467b48Spatrick
268609467b48Spatrick // Need frame address to find the address of VarArgsFrameIndex.
268709467b48Spatrick MF.getFrameInfo().setFrameAddressIsTaken(true);
268809467b48Spatrick
268909467b48Spatrick // vastart just stores the address of the VarArgsFrameIndex slot into the
269009467b48Spatrick // memory location argument.
269109467b48Spatrick SDLoc DL(Op);
269209467b48Spatrick SDValue Offset =
269309467b48Spatrick DAG.getNode(ISD::ADD, DL, PtrVT, DAG.getRegister(SP::I6, PtrVT),
269409467b48Spatrick DAG.getIntPtrConstant(FuncInfo->getVarArgsFrameOffset(), DL));
269509467b48Spatrick const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
269609467b48Spatrick return DAG.getStore(Op.getOperand(0), DL, Offset, Op.getOperand(1),
269709467b48Spatrick MachinePointerInfo(SV));
269809467b48Spatrick }
269909467b48Spatrick
LowerVAARG(SDValue Op,SelectionDAG & DAG)270009467b48Spatrick static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) {
270109467b48Spatrick SDNode *Node = Op.getNode();
270209467b48Spatrick EVT VT = Node->getValueType(0);
270309467b48Spatrick SDValue InChain = Node->getOperand(0);
270409467b48Spatrick SDValue VAListPtr = Node->getOperand(1);
270509467b48Spatrick EVT PtrVT = VAListPtr.getValueType();
270609467b48Spatrick const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
270709467b48Spatrick SDLoc DL(Node);
270809467b48Spatrick SDValue VAList =
270909467b48Spatrick DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV));
271009467b48Spatrick // Increment the pointer, VAList, to the next vaarg.
271109467b48Spatrick SDValue NextPtr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
271209467b48Spatrick DAG.getIntPtrConstant(VT.getSizeInBits()/8,
271309467b48Spatrick DL));
271409467b48Spatrick // Store the incremented VAList to the legalized pointer.
271509467b48Spatrick InChain = DAG.getStore(VAList.getValue(1), DL, NextPtr, VAListPtr,
271609467b48Spatrick MachinePointerInfo(SV));
271709467b48Spatrick // Load the actual argument out of the pointer VAList.
271809467b48Spatrick // We can't count on greater alignment than the word size.
2719a0747c9fSpatrick return DAG.getLoad(
2720a0747c9fSpatrick VT, DL, InChain, VAList, MachinePointerInfo(),
2721*a96b3639Srobert Align(std::min(PtrVT.getFixedSizeInBits(), VT.getFixedSizeInBits()) / 8));
272209467b48Spatrick }
272309467b48Spatrick
LowerDYNAMIC_STACKALLOC(SDValue Op,SelectionDAG & DAG,const SparcSubtarget * Subtarget)272409467b48Spatrick static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG,
272509467b48Spatrick const SparcSubtarget *Subtarget) {
272609467b48Spatrick SDValue Chain = Op.getOperand(0); // Legalize the chain.
272709467b48Spatrick SDValue Size = Op.getOperand(1); // Legalize the size.
2728097a140dSpatrick MaybeAlign Alignment =
2729097a140dSpatrick cast<ConstantSDNode>(Op.getOperand(2))->getMaybeAlignValue();
2730097a140dSpatrick Align StackAlign = Subtarget->getFrameLowering()->getStackAlign();
273109467b48Spatrick EVT VT = Size->getValueType(0);
273209467b48Spatrick SDLoc dl(Op);
273309467b48Spatrick
273409467b48Spatrick // TODO: implement over-aligned alloca. (Note: also implies
273509467b48Spatrick // supporting support for overaligned function frames + dynamic
273609467b48Spatrick // allocations, at all, which currently isn't supported)
2737097a140dSpatrick if (Alignment && *Alignment > StackAlign) {
273809467b48Spatrick const MachineFunction &MF = DAG.getMachineFunction();
273909467b48Spatrick report_fatal_error("Function \"" + Twine(MF.getName()) + "\": "
274009467b48Spatrick "over-aligned dynamic alloca not supported.");
274109467b48Spatrick }
274209467b48Spatrick
274309467b48Spatrick // The resultant pointer needs to be above the register spill area
274409467b48Spatrick // at the bottom of the stack.
274509467b48Spatrick unsigned regSpillArea;
274609467b48Spatrick if (Subtarget->is64Bit()) {
274709467b48Spatrick regSpillArea = 128;
274809467b48Spatrick } else {
274909467b48Spatrick // On Sparc32, the size of the spill area is 92. Unfortunately,
275009467b48Spatrick // that's only 4-byte aligned, not 8-byte aligned (the stack
275109467b48Spatrick // pointer is 8-byte aligned). So, if the user asked for an 8-byte
275209467b48Spatrick // aligned dynamic allocation, we actually need to add 96 to the
275309467b48Spatrick // bottom of the stack, instead of 92, to ensure 8-byte alignment.
275409467b48Spatrick
275509467b48Spatrick // That also means adding 4 to the size of the allocation --
275609467b48Spatrick // before applying the 8-byte rounding. Unfortunately, we the
275709467b48Spatrick // value we get here has already had rounding applied. So, we need
275809467b48Spatrick // to add 8, instead, wasting a bit more memory.
275909467b48Spatrick
276009467b48Spatrick // Further, this only actually needs to be done if the required
276109467b48Spatrick // alignment is > 4, but, we've lost that info by this point, too,
276209467b48Spatrick // so we always apply it.
276309467b48Spatrick
276409467b48Spatrick // (An alternative approach would be to always reserve 96 bytes
276509467b48Spatrick // instead of the required 92, but then we'd waste 4 extra bytes
276609467b48Spatrick // in every frame, not just those with dynamic stack allocations)
276709467b48Spatrick
276809467b48Spatrick // TODO: modify code in SelectionDAGBuilder to make this less sad.
276909467b48Spatrick
277009467b48Spatrick Size = DAG.getNode(ISD::ADD, dl, VT, Size,
277109467b48Spatrick DAG.getConstant(8, dl, VT));
277209467b48Spatrick regSpillArea = 96;
277309467b48Spatrick }
277409467b48Spatrick
277509467b48Spatrick unsigned SPReg = SP::O6;
277609467b48Spatrick SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
277709467b48Spatrick SDValue NewSP = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value
277809467b48Spatrick Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); // Output chain
277909467b48Spatrick
278009467b48Spatrick regSpillArea += Subtarget->getStackPointerBias();
278109467b48Spatrick
278209467b48Spatrick SDValue NewVal = DAG.getNode(ISD::ADD, dl, VT, NewSP,
278309467b48Spatrick DAG.getConstant(regSpillArea, dl, VT));
278409467b48Spatrick SDValue Ops[2] = { NewVal, Chain };
278509467b48Spatrick return DAG.getMergeValues(Ops, dl);
278609467b48Spatrick }
278709467b48Spatrick
278809467b48Spatrick
getFLUSHW(SDValue Op,SelectionDAG & DAG)278909467b48Spatrick static SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) {
279009467b48Spatrick SDLoc dl(Op);
279109467b48Spatrick SDValue Chain = DAG.getNode(SPISD::FLUSHW,
279209467b48Spatrick dl, MVT::Other, DAG.getEntryNode());
279309467b48Spatrick return Chain;
279409467b48Spatrick }
279509467b48Spatrick
getFRAMEADDR(uint64_t depth,SDValue Op,SelectionDAG & DAG,const SparcSubtarget * Subtarget,bool AlwaysFlush=false)279609467b48Spatrick static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG,
279709467b48Spatrick const SparcSubtarget *Subtarget,
279809467b48Spatrick bool AlwaysFlush = false) {
279909467b48Spatrick MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
280009467b48Spatrick MFI.setFrameAddressIsTaken(true);
280109467b48Spatrick
280209467b48Spatrick EVT VT = Op.getValueType();
280309467b48Spatrick SDLoc dl(Op);
280409467b48Spatrick unsigned FrameReg = SP::I6;
280509467b48Spatrick unsigned stackBias = Subtarget->getStackPointerBias();
280609467b48Spatrick
280709467b48Spatrick SDValue FrameAddr;
280809467b48Spatrick SDValue Chain;
280909467b48Spatrick
281009467b48Spatrick // flush first to make sure the windowed registers' values are in stack
281109467b48Spatrick Chain = (depth || AlwaysFlush) ? getFLUSHW(Op, DAG) : DAG.getEntryNode();
281209467b48Spatrick
281309467b48Spatrick FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
281409467b48Spatrick
281509467b48Spatrick unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56;
281609467b48Spatrick
281709467b48Spatrick while (depth--) {
281809467b48Spatrick SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
281909467b48Spatrick DAG.getIntPtrConstant(Offset, dl));
282009467b48Spatrick FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo());
282109467b48Spatrick }
282209467b48Spatrick if (Subtarget->is64Bit())
282309467b48Spatrick FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
282409467b48Spatrick DAG.getIntPtrConstant(stackBias, dl));
282509467b48Spatrick return FrameAddr;
282609467b48Spatrick }
282709467b48Spatrick
282809467b48Spatrick
LowerFRAMEADDR(SDValue Op,SelectionDAG & DAG,const SparcSubtarget * Subtarget)282909467b48Spatrick static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG,
283009467b48Spatrick const SparcSubtarget *Subtarget) {
283109467b48Spatrick
283209467b48Spatrick uint64_t depth = Op.getConstantOperandVal(0);
283309467b48Spatrick
283409467b48Spatrick return getFRAMEADDR(depth, Op, DAG, Subtarget);
283509467b48Spatrick
283609467b48Spatrick }
283709467b48Spatrick
LowerRETURNADDR(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,const SparcSubtarget * Subtarget)283809467b48Spatrick static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
283909467b48Spatrick const SparcTargetLowering &TLI,
284009467b48Spatrick const SparcSubtarget *Subtarget) {
284109467b48Spatrick MachineFunction &MF = DAG.getMachineFunction();
284209467b48Spatrick MachineFrameInfo &MFI = MF.getFrameInfo();
284309467b48Spatrick MFI.setReturnAddressIsTaken(true);
284409467b48Spatrick
284509467b48Spatrick if (TLI.verifyReturnAddressArgumentIsConstant(Op, DAG))
284609467b48Spatrick return SDValue();
284709467b48Spatrick
284809467b48Spatrick EVT VT = Op.getValueType();
284909467b48Spatrick SDLoc dl(Op);
285009467b48Spatrick uint64_t depth = Op.getConstantOperandVal(0);
285109467b48Spatrick
285209467b48Spatrick SDValue RetAddr;
285309467b48Spatrick if (depth == 0) {
285409467b48Spatrick auto PtrVT = TLI.getPointerTy(DAG.getDataLayout());
2855*a96b3639Srobert Register RetReg = MF.addLiveIn(SP::I7, TLI.getRegClassFor(PtrVT));
285609467b48Spatrick RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT);
285709467b48Spatrick return RetAddr;
285809467b48Spatrick }
285909467b48Spatrick
286009467b48Spatrick // Need frame address to find return address of the caller.
286109467b48Spatrick SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget, true);
286209467b48Spatrick
286309467b48Spatrick unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60;
286409467b48Spatrick SDValue Ptr = DAG.getNode(ISD::ADD,
286509467b48Spatrick dl, VT,
286609467b48Spatrick FrameAddr,
286709467b48Spatrick DAG.getIntPtrConstant(Offset, dl));
286809467b48Spatrick RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr, MachinePointerInfo());
286909467b48Spatrick
287009467b48Spatrick return RetAddr;
287109467b48Spatrick }
287209467b48Spatrick
LowerF64Op(SDValue SrcReg64,const SDLoc & dl,SelectionDAG & DAG,unsigned opcode)287309467b48Spatrick static SDValue LowerF64Op(SDValue SrcReg64, const SDLoc &dl, SelectionDAG &DAG,
287409467b48Spatrick unsigned opcode) {
287509467b48Spatrick assert(SrcReg64.getValueType() == MVT::f64 && "LowerF64Op called on non-double!");
287609467b48Spatrick assert(opcode == ISD::FNEG || opcode == ISD::FABS);
287709467b48Spatrick
287809467b48Spatrick // Lower fneg/fabs on f64 to fneg/fabs on f32.
287909467b48Spatrick // fneg f64 => fneg f32:sub_even, fmov f32:sub_odd.
288009467b48Spatrick // fabs f64 => fabs f32:sub_even, fmov f32:sub_odd.
288109467b48Spatrick
288209467b48Spatrick // Note: in little-endian, the floating-point value is stored in the
288309467b48Spatrick // registers are in the opposite order, so the subreg with the sign
288409467b48Spatrick // bit is the highest-numbered (odd), rather than the
288509467b48Spatrick // lowest-numbered (even).
288609467b48Spatrick
288709467b48Spatrick SDValue Hi32 = DAG.getTargetExtractSubreg(SP::sub_even, dl, MVT::f32,
288809467b48Spatrick SrcReg64);
288909467b48Spatrick SDValue Lo32 = DAG.getTargetExtractSubreg(SP::sub_odd, dl, MVT::f32,
289009467b48Spatrick SrcReg64);
289109467b48Spatrick
289209467b48Spatrick if (DAG.getDataLayout().isLittleEndian())
289309467b48Spatrick Lo32 = DAG.getNode(opcode, dl, MVT::f32, Lo32);
289409467b48Spatrick else
289509467b48Spatrick Hi32 = DAG.getNode(opcode, dl, MVT::f32, Hi32);
289609467b48Spatrick
289709467b48Spatrick SDValue DstReg64 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
289809467b48Spatrick dl, MVT::f64), 0);
289909467b48Spatrick DstReg64 = DAG.getTargetInsertSubreg(SP::sub_even, dl, MVT::f64,
290009467b48Spatrick DstReg64, Hi32);
290109467b48Spatrick DstReg64 = DAG.getTargetInsertSubreg(SP::sub_odd, dl, MVT::f64,
290209467b48Spatrick DstReg64, Lo32);
290309467b48Spatrick return DstReg64;
290409467b48Spatrick }
290509467b48Spatrick
290609467b48Spatrick // Lower a f128 load into two f64 loads.
LowerF128Load(SDValue Op,SelectionDAG & DAG)290709467b48Spatrick static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG)
290809467b48Spatrick {
290909467b48Spatrick SDLoc dl(Op);
2910a0747c9fSpatrick LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode());
2911a0747c9fSpatrick assert(LdNode->getOffset().isUndef() && "Unexpected node type");
291209467b48Spatrick
2913a0747c9fSpatrick Align Alignment = commonAlignment(LdNode->getOriginalAlign(), 8);
291409467b48Spatrick
291509467b48Spatrick SDValue Hi64 =
291609467b48Spatrick DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LdNode->getBasePtr(),
2917a0747c9fSpatrick LdNode->getPointerInfo(), Alignment);
291809467b48Spatrick EVT addrVT = LdNode->getBasePtr().getValueType();
291909467b48Spatrick SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT,
292009467b48Spatrick LdNode->getBasePtr(),
292109467b48Spatrick DAG.getConstant(8, dl, addrVT));
292209467b48Spatrick SDValue Lo64 = DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LoPtr,
2923a0747c9fSpatrick LdNode->getPointerInfo().getWithOffset(8),
2924a0747c9fSpatrick Alignment);
292509467b48Spatrick
292609467b48Spatrick SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32);
292709467b48Spatrick SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32);
292809467b48Spatrick
292909467b48Spatrick SDNode *InFP128 = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
293009467b48Spatrick dl, MVT::f128);
293109467b48Spatrick InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
293209467b48Spatrick MVT::f128,
293309467b48Spatrick SDValue(InFP128, 0),
293409467b48Spatrick Hi64,
293509467b48Spatrick SubRegEven);
293609467b48Spatrick InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
293709467b48Spatrick MVT::f128,
293809467b48Spatrick SDValue(InFP128, 0),
293909467b48Spatrick Lo64,
294009467b48Spatrick SubRegOdd);
294109467b48Spatrick SDValue OutChains[2] = { SDValue(Hi64.getNode(), 1),
294209467b48Spatrick SDValue(Lo64.getNode(), 1) };
294309467b48Spatrick SDValue OutChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
294409467b48Spatrick SDValue Ops[2] = {SDValue(InFP128,0), OutChain};
294509467b48Spatrick return DAG.getMergeValues(Ops, dl);
294609467b48Spatrick }
294709467b48Spatrick
LowerLOAD(SDValue Op,SelectionDAG & DAG)294809467b48Spatrick static SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG)
294909467b48Spatrick {
295009467b48Spatrick LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode());
295109467b48Spatrick
295209467b48Spatrick EVT MemVT = LdNode->getMemoryVT();
295309467b48Spatrick if (MemVT == MVT::f128)
295409467b48Spatrick return LowerF128Load(Op, DAG);
295509467b48Spatrick
295609467b48Spatrick return Op;
295709467b48Spatrick }
295809467b48Spatrick
295909467b48Spatrick // Lower a f128 store into two f64 stores.
LowerF128Store(SDValue Op,SelectionDAG & DAG)296009467b48Spatrick static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) {
296109467b48Spatrick SDLoc dl(Op);
2962a0747c9fSpatrick StoreSDNode *StNode = cast<StoreSDNode>(Op.getNode());
2963a0747c9fSpatrick assert(StNode->getOffset().isUndef() && "Unexpected node type");
2964a0747c9fSpatrick
296509467b48Spatrick SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32);
296609467b48Spatrick SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32);
296709467b48Spatrick
296809467b48Spatrick SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG,
296909467b48Spatrick dl,
297009467b48Spatrick MVT::f64,
297109467b48Spatrick StNode->getValue(),
297209467b48Spatrick SubRegEven);
297309467b48Spatrick SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG,
297409467b48Spatrick dl,
297509467b48Spatrick MVT::f64,
297609467b48Spatrick StNode->getValue(),
297709467b48Spatrick SubRegOdd);
297809467b48Spatrick
2979a0747c9fSpatrick Align Alignment = commonAlignment(StNode->getOriginalAlign(), 8);
298009467b48Spatrick
298109467b48Spatrick SDValue OutChains[2];
298209467b48Spatrick OutChains[0] =
298309467b48Spatrick DAG.getStore(StNode->getChain(), dl, SDValue(Hi64, 0),
2984a0747c9fSpatrick StNode->getBasePtr(), StNode->getPointerInfo(),
2985a0747c9fSpatrick Alignment);
298609467b48Spatrick EVT addrVT = StNode->getBasePtr().getValueType();
298709467b48Spatrick SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT,
298809467b48Spatrick StNode->getBasePtr(),
298909467b48Spatrick DAG.getConstant(8, dl, addrVT));
299009467b48Spatrick OutChains[1] = DAG.getStore(StNode->getChain(), dl, SDValue(Lo64, 0), LoPtr,
2991a0747c9fSpatrick StNode->getPointerInfo().getWithOffset(8),
2992a0747c9fSpatrick Alignment);
299309467b48Spatrick return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
299409467b48Spatrick }
299509467b48Spatrick
LowerSTORE(SDValue Op,SelectionDAG & DAG)299609467b48Spatrick static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG)
299709467b48Spatrick {
299809467b48Spatrick SDLoc dl(Op);
299909467b48Spatrick StoreSDNode *St = cast<StoreSDNode>(Op.getNode());
300009467b48Spatrick
300109467b48Spatrick EVT MemVT = St->getMemoryVT();
300209467b48Spatrick if (MemVT == MVT::f128)
300309467b48Spatrick return LowerF128Store(Op, DAG);
300409467b48Spatrick
300509467b48Spatrick if (MemVT == MVT::i64) {
300609467b48Spatrick // Custom handling for i64 stores: turn it into a bitcast and a
300709467b48Spatrick // v2i32 store.
300809467b48Spatrick SDValue Val = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, St->getValue());
300909467b48Spatrick SDValue Chain = DAG.getStore(
301009467b48Spatrick St->getChain(), dl, Val, St->getBasePtr(), St->getPointerInfo(),
3011a0747c9fSpatrick St->getOriginalAlign(), St->getMemOperand()->getFlags(),
3012a0747c9fSpatrick St->getAAInfo());
301309467b48Spatrick return Chain;
301409467b48Spatrick }
301509467b48Spatrick
301609467b48Spatrick return SDValue();
301709467b48Spatrick }
301809467b48Spatrick
LowerFNEGorFABS(SDValue Op,SelectionDAG & DAG,bool isV9)301909467b48Spatrick static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
302009467b48Spatrick assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS)
302109467b48Spatrick && "invalid opcode");
302209467b48Spatrick
302309467b48Spatrick SDLoc dl(Op);
302409467b48Spatrick
302509467b48Spatrick if (Op.getValueType() == MVT::f64)
302609467b48Spatrick return LowerF64Op(Op.getOperand(0), dl, DAG, Op.getOpcode());
302709467b48Spatrick if (Op.getValueType() != MVT::f128)
302809467b48Spatrick return Op;
302909467b48Spatrick
303009467b48Spatrick // Lower fabs/fneg on f128 to fabs/fneg on f64
303109467b48Spatrick // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64
303209467b48Spatrick // (As with LowerF64Op, on little-endian, we need to negate the odd
303309467b48Spatrick // subreg)
303409467b48Spatrick
303509467b48Spatrick SDValue SrcReg128 = Op.getOperand(0);
303609467b48Spatrick SDValue Hi64 = DAG.getTargetExtractSubreg(SP::sub_even64, dl, MVT::f64,
303709467b48Spatrick SrcReg128);
303809467b48Spatrick SDValue Lo64 = DAG.getTargetExtractSubreg(SP::sub_odd64, dl, MVT::f64,
303909467b48Spatrick SrcReg128);
304009467b48Spatrick
304109467b48Spatrick if (DAG.getDataLayout().isLittleEndian()) {
304209467b48Spatrick if (isV9)
304309467b48Spatrick Lo64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Lo64);
304409467b48Spatrick else
304509467b48Spatrick Lo64 = LowerF64Op(Lo64, dl, DAG, Op.getOpcode());
304609467b48Spatrick } else {
304709467b48Spatrick if (isV9)
304809467b48Spatrick Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64);
304909467b48Spatrick else
305009467b48Spatrick Hi64 = LowerF64Op(Hi64, dl, DAG, Op.getOpcode());
305109467b48Spatrick }
305209467b48Spatrick
305309467b48Spatrick SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
305409467b48Spatrick dl, MVT::f128), 0);
305509467b48Spatrick DstReg128 = DAG.getTargetInsertSubreg(SP::sub_even64, dl, MVT::f128,
305609467b48Spatrick DstReg128, Hi64);
305709467b48Spatrick DstReg128 = DAG.getTargetInsertSubreg(SP::sub_odd64, dl, MVT::f128,
305809467b48Spatrick DstReg128, Lo64);
305909467b48Spatrick return DstReg128;
306009467b48Spatrick }
306109467b48Spatrick
LowerADDC_ADDE_SUBC_SUBE(SDValue Op,SelectionDAG & DAG)306209467b48Spatrick static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) {
306309467b48Spatrick
306409467b48Spatrick if (Op.getValueType() != MVT::i64)
306509467b48Spatrick return Op;
306609467b48Spatrick
306709467b48Spatrick SDLoc dl(Op);
306809467b48Spatrick SDValue Src1 = Op.getOperand(0);
306909467b48Spatrick SDValue Src1Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1);
307009467b48Spatrick SDValue Src1Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src1,
307109467b48Spatrick DAG.getConstant(32, dl, MVT::i64));
307209467b48Spatrick Src1Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1Hi);
307309467b48Spatrick
307409467b48Spatrick SDValue Src2 = Op.getOperand(1);
307509467b48Spatrick SDValue Src2Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2);
307609467b48Spatrick SDValue Src2Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src2,
307709467b48Spatrick DAG.getConstant(32, dl, MVT::i64));
307809467b48Spatrick Src2Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2Hi);
307909467b48Spatrick
308009467b48Spatrick
308109467b48Spatrick bool hasChain = false;
308209467b48Spatrick unsigned hiOpc = Op.getOpcode();
308309467b48Spatrick switch (Op.getOpcode()) {
308409467b48Spatrick default: llvm_unreachable("Invalid opcode");
308509467b48Spatrick case ISD::ADDC: hiOpc = ISD::ADDE; break;
308609467b48Spatrick case ISD::ADDE: hasChain = true; break;
308709467b48Spatrick case ISD::SUBC: hiOpc = ISD::SUBE; break;
308809467b48Spatrick case ISD::SUBE: hasChain = true; break;
308909467b48Spatrick }
309009467b48Spatrick SDValue Lo;
309109467b48Spatrick SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Glue);
309209467b48Spatrick if (hasChain) {
309309467b48Spatrick Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo,
309409467b48Spatrick Op.getOperand(2));
309509467b48Spatrick } else {
309609467b48Spatrick Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo);
309709467b48Spatrick }
309809467b48Spatrick SDValue Hi = DAG.getNode(hiOpc, dl, VTs, Src1Hi, Src2Hi, Lo.getValue(1));
309909467b48Spatrick SDValue Carry = Hi.getValue(1);
310009467b48Spatrick
310109467b48Spatrick Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Lo);
310209467b48Spatrick Hi = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Hi);
310309467b48Spatrick Hi = DAG.getNode(ISD::SHL, dl, MVT::i64, Hi,
310409467b48Spatrick DAG.getConstant(32, dl, MVT::i64));
310509467b48Spatrick
310609467b48Spatrick SDValue Dst = DAG.getNode(ISD::OR, dl, MVT::i64, Hi, Lo);
310709467b48Spatrick SDValue Ops[2] = { Dst, Carry };
310809467b48Spatrick return DAG.getMergeValues(Ops, dl);
310909467b48Spatrick }
311009467b48Spatrick
311109467b48Spatrick // Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode()
311209467b48Spatrick // in LegalizeDAG.cpp except the order of arguments to the library function.
LowerUMULO_SMULO(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI)311309467b48Spatrick static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG,
311409467b48Spatrick const SparcTargetLowering &TLI)
311509467b48Spatrick {
311609467b48Spatrick unsigned opcode = Op.getOpcode();
311709467b48Spatrick assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode.");
311809467b48Spatrick
311909467b48Spatrick bool isSigned = (opcode == ISD::SMULO);
312009467b48Spatrick EVT VT = MVT::i64;
312109467b48Spatrick EVT WideVT = MVT::i128;
312209467b48Spatrick SDLoc dl(Op);
312309467b48Spatrick SDValue LHS = Op.getOperand(0);
312409467b48Spatrick
312509467b48Spatrick if (LHS.getValueType() != VT)
312609467b48Spatrick return Op;
312709467b48Spatrick
312809467b48Spatrick SDValue ShiftAmt = DAG.getConstant(63, dl, VT);
312909467b48Spatrick
313009467b48Spatrick SDValue RHS = Op.getOperand(1);
3131*a96b3639Srobert SDValue HiLHS, HiRHS;
3132*a96b3639Srobert if (isSigned) {
3133*a96b3639Srobert HiLHS = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt);
3134*a96b3639Srobert HiRHS = DAG.getNode(ISD::SRA, dl, MVT::i64, RHS, ShiftAmt);
3135*a96b3639Srobert } else {
3136*a96b3639Srobert HiLHS = DAG.getConstant(0, dl, VT);
3137*a96b3639Srobert HiRHS = DAG.getConstant(0, dl, MVT::i64);
3138*a96b3639Srobert }
3139*a96b3639Srobert
314009467b48Spatrick SDValue Args[] = { HiLHS, LHS, HiRHS, RHS };
314109467b48Spatrick
314209467b48Spatrick TargetLowering::MakeLibCallOptions CallOptions;
314309467b48Spatrick CallOptions.setSExt(isSigned);
314409467b48Spatrick SDValue MulResult = TLI.makeLibCall(DAG,
314509467b48Spatrick RTLIB::MUL_I128, WideVT,
314609467b48Spatrick Args, CallOptions, dl).first;
314709467b48Spatrick SDValue BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,
314809467b48Spatrick MulResult, DAG.getIntPtrConstant(0, dl));
314909467b48Spatrick SDValue TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,
315009467b48Spatrick MulResult, DAG.getIntPtrConstant(1, dl));
315109467b48Spatrick if (isSigned) {
315209467b48Spatrick SDValue Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, ShiftAmt);
315309467b48Spatrick TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, Tmp1, ISD::SETNE);
315409467b48Spatrick } else {
315509467b48Spatrick TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, DAG.getConstant(0, dl, VT),
315609467b48Spatrick ISD::SETNE);
315709467b48Spatrick }
315809467b48Spatrick // MulResult is a node with an illegal type. Because such things are not
315909467b48Spatrick // generally permitted during this phase of legalization, ensure that
316009467b48Spatrick // nothing is left using the node. The above EXTRACT_ELEMENT nodes should have
316109467b48Spatrick // been folded.
316209467b48Spatrick assert(MulResult->use_empty() && "Illegally typed node still in use!");
316309467b48Spatrick
316409467b48Spatrick SDValue Ops[2] = { BottomHalf, TopHalf } ;
316509467b48Spatrick return DAG.getMergeValues(Ops, dl);
316609467b48Spatrick }
316709467b48Spatrick
LowerATOMIC_LOAD_STORE(SDValue Op,SelectionDAG & DAG)316809467b48Spatrick static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) {
3169a0747c9fSpatrick if (isStrongerThanMonotonic(cast<AtomicSDNode>(Op)->getSuccessOrdering())) {
317009467b48Spatrick // Expand with a fence.
317109467b48Spatrick return SDValue();
3172a0747c9fSpatrick }
317309467b48Spatrick
317409467b48Spatrick // Monotonic load/stores are legal.
317509467b48Spatrick return Op;
317609467b48Spatrick }
317709467b48Spatrick
LowerINTRINSIC_WO_CHAIN(SDValue Op,SelectionDAG & DAG) const317809467b48Spatrick SDValue SparcTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
317909467b48Spatrick SelectionDAG &DAG) const {
318009467b48Spatrick unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
318109467b48Spatrick SDLoc dl(Op);
318209467b48Spatrick switch (IntNo) {
318309467b48Spatrick default: return SDValue(); // Don't custom lower most intrinsics.
318409467b48Spatrick case Intrinsic::thread_pointer: {
318509467b48Spatrick EVT PtrVT = getPointerTy(DAG.getDataLayout());
318609467b48Spatrick return DAG.getRegister(SP::G7, PtrVT);
318709467b48Spatrick }
318809467b48Spatrick }
318909467b48Spatrick }
319009467b48Spatrick
319109467b48Spatrick SDValue SparcTargetLowering::
LowerOperation(SDValue Op,SelectionDAG & DAG) const319209467b48Spatrick LowerOperation(SDValue Op, SelectionDAG &DAG) const {
319309467b48Spatrick
319409467b48Spatrick bool hasHardQuad = Subtarget->hasHardQuad();
319509467b48Spatrick bool isV9 = Subtarget->isV9();
3196*a96b3639Srobert bool is64Bit = Subtarget->is64Bit();
319709467b48Spatrick
319809467b48Spatrick switch (Op.getOpcode()) {
319909467b48Spatrick default: llvm_unreachable("Should not custom lower this!");
320009467b48Spatrick
320109467b48Spatrick case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this,
320209467b48Spatrick Subtarget);
320309467b48Spatrick case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG,
320409467b48Spatrick Subtarget);
320509467b48Spatrick case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
320609467b48Spatrick case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
320709467b48Spatrick case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
320809467b48Spatrick case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
320909467b48Spatrick case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG, *this,
321009467b48Spatrick hasHardQuad);
321109467b48Spatrick case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG, *this,
321209467b48Spatrick hasHardQuad);
321309467b48Spatrick case ISD::FP_TO_UINT: return LowerFP_TO_UINT(Op, DAG, *this,
321409467b48Spatrick hasHardQuad);
321509467b48Spatrick case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG, *this,
321609467b48Spatrick hasHardQuad);
3217*a96b3639Srobert case ISD::BR_CC:
3218*a96b3639Srobert return LowerBR_CC(Op, DAG, *this, hasHardQuad, isV9);
3219*a96b3639Srobert case ISD::SELECT_CC:
3220*a96b3639Srobert return LowerSELECT_CC(Op, DAG, *this, hasHardQuad, isV9, is64Bit);
322109467b48Spatrick case ISD::VASTART: return LowerVASTART(Op, DAG, *this);
322209467b48Spatrick case ISD::VAARG: return LowerVAARG(Op, DAG);
322309467b48Spatrick case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG,
322409467b48Spatrick Subtarget);
322509467b48Spatrick
322609467b48Spatrick case ISD::LOAD: return LowerLOAD(Op, DAG);
322709467b48Spatrick case ISD::STORE: return LowerSTORE(Op, DAG);
322809467b48Spatrick case ISD::FADD: return LowerF128Op(Op, DAG,
322909467b48Spatrick getLibcallName(RTLIB::ADD_F128), 2);
323009467b48Spatrick case ISD::FSUB: return LowerF128Op(Op, DAG,
323109467b48Spatrick getLibcallName(RTLIB::SUB_F128), 2);
323209467b48Spatrick case ISD::FMUL: return LowerF128Op(Op, DAG,
323309467b48Spatrick getLibcallName(RTLIB::MUL_F128), 2);
323409467b48Spatrick case ISD::FDIV: return LowerF128Op(Op, DAG,
323509467b48Spatrick getLibcallName(RTLIB::DIV_F128), 2);
323609467b48Spatrick case ISD::FSQRT: return LowerF128Op(Op, DAG,
323709467b48Spatrick getLibcallName(RTLIB::SQRT_F128),1);
323809467b48Spatrick case ISD::FABS:
323909467b48Spatrick case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9);
324009467b48Spatrick case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, *this);
324109467b48Spatrick case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, *this);
324209467b48Spatrick case ISD::ADDC:
324309467b48Spatrick case ISD::ADDE:
324409467b48Spatrick case ISD::SUBC:
324509467b48Spatrick case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
324609467b48Spatrick case ISD::UMULO:
324709467b48Spatrick case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this);
324809467b48Spatrick case ISD::ATOMIC_LOAD:
324909467b48Spatrick case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG);
325009467b48Spatrick case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
325109467b48Spatrick }
325209467b48Spatrick }
325309467b48Spatrick
bitcastConstantFPToInt(ConstantFPSDNode * C,const SDLoc & DL,SelectionDAG & DAG) const325409467b48Spatrick SDValue SparcTargetLowering::bitcastConstantFPToInt(ConstantFPSDNode *C,
325509467b48Spatrick const SDLoc &DL,
325609467b48Spatrick SelectionDAG &DAG) const {
325709467b48Spatrick APInt V = C->getValueAPF().bitcastToAPInt();
325809467b48Spatrick SDValue Lo = DAG.getConstant(V.zextOrTrunc(32), DL, MVT::i32);
325909467b48Spatrick SDValue Hi = DAG.getConstant(V.lshr(32).zextOrTrunc(32), DL, MVT::i32);
326009467b48Spatrick if (DAG.getDataLayout().isLittleEndian())
326109467b48Spatrick std::swap(Lo, Hi);
326209467b48Spatrick return DAG.getBuildVector(MVT::v2i32, DL, {Hi, Lo});
326309467b48Spatrick }
326409467b48Spatrick
PerformBITCASTCombine(SDNode * N,DAGCombinerInfo & DCI) const326509467b48Spatrick SDValue SparcTargetLowering::PerformBITCASTCombine(SDNode *N,
326609467b48Spatrick DAGCombinerInfo &DCI) const {
326709467b48Spatrick SDLoc dl(N);
326809467b48Spatrick SDValue Src = N->getOperand(0);
326909467b48Spatrick
327009467b48Spatrick if (isa<ConstantFPSDNode>(Src) && N->getSimpleValueType(0) == MVT::v2i32 &&
327109467b48Spatrick Src.getSimpleValueType() == MVT::f64)
327209467b48Spatrick return bitcastConstantFPToInt(cast<ConstantFPSDNode>(Src), dl, DCI.DAG);
327309467b48Spatrick
327409467b48Spatrick return SDValue();
327509467b48Spatrick }
327609467b48Spatrick
PerformDAGCombine(SDNode * N,DAGCombinerInfo & DCI) const327709467b48Spatrick SDValue SparcTargetLowering::PerformDAGCombine(SDNode *N,
327809467b48Spatrick DAGCombinerInfo &DCI) const {
327909467b48Spatrick switch (N->getOpcode()) {
328009467b48Spatrick default:
328109467b48Spatrick break;
328209467b48Spatrick case ISD::BITCAST:
328309467b48Spatrick return PerformBITCASTCombine(N, DCI);
328409467b48Spatrick }
328509467b48Spatrick return SDValue();
328609467b48Spatrick }
328709467b48Spatrick
328809467b48Spatrick MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const328909467b48Spatrick SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
329009467b48Spatrick MachineBasicBlock *BB) const {
329109467b48Spatrick switch (MI.getOpcode()) {
329209467b48Spatrick default: llvm_unreachable("Unknown SELECT_CC!");
329309467b48Spatrick case SP::SELECT_CC_Int_ICC:
329409467b48Spatrick case SP::SELECT_CC_FP_ICC:
329509467b48Spatrick case SP::SELECT_CC_DFP_ICC:
329609467b48Spatrick case SP::SELECT_CC_QFP_ICC:
3297*a96b3639Srobert if (Subtarget->isV9())
3298*a96b3639Srobert return expandSelectCC(MI, BB, SP::BPICC);
329909467b48Spatrick return expandSelectCC(MI, BB, SP::BCOND);
3300adae0cfdSpatrick case SP::SELECT_CC_Int_XCC:
3301adae0cfdSpatrick case SP::SELECT_CC_FP_XCC:
3302adae0cfdSpatrick case SP::SELECT_CC_DFP_XCC:
3303adae0cfdSpatrick case SP::SELECT_CC_QFP_XCC:
3304adae0cfdSpatrick return expandSelectCC(MI, BB, SP::BPXCC);
330509467b48Spatrick case SP::SELECT_CC_Int_FCC:
330609467b48Spatrick case SP::SELECT_CC_FP_FCC:
330709467b48Spatrick case SP::SELECT_CC_DFP_FCC:
330809467b48Spatrick case SP::SELECT_CC_QFP_FCC:
3309*a96b3639Srobert if (Subtarget->isV9())
3310*a96b3639Srobert return expandSelectCC(MI, BB, SP::FBCOND_V9);
331109467b48Spatrick return expandSelectCC(MI, BB, SP::FBCOND);
331209467b48Spatrick }
331309467b48Spatrick }
331409467b48Spatrick
331509467b48Spatrick MachineBasicBlock *
expandSelectCC(MachineInstr & MI,MachineBasicBlock * BB,unsigned BROpcode) const331609467b48Spatrick SparcTargetLowering::expandSelectCC(MachineInstr &MI, MachineBasicBlock *BB,
331709467b48Spatrick unsigned BROpcode) const {
331809467b48Spatrick const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
331909467b48Spatrick DebugLoc dl = MI.getDebugLoc();
332009467b48Spatrick unsigned CC = (SPCC::CondCodes)MI.getOperand(3).getImm();
332109467b48Spatrick
332209467b48Spatrick // To "insert" a SELECT_CC instruction, we actually have to insert the
332309467b48Spatrick // triangle control-flow pattern. The incoming instruction knows the
332409467b48Spatrick // destination vreg to set, the condition code register to branch on, the
332509467b48Spatrick // true/false values to select between, and the condition code for the branch.
332609467b48Spatrick //
332709467b48Spatrick // We produce the following control flow:
332809467b48Spatrick // ThisMBB
332909467b48Spatrick // | \
333009467b48Spatrick // | IfFalseMBB
333109467b48Spatrick // | /
333209467b48Spatrick // SinkMBB
333309467b48Spatrick const BasicBlock *LLVM_BB = BB->getBasicBlock();
333409467b48Spatrick MachineFunction::iterator It = ++BB->getIterator();
333509467b48Spatrick
333609467b48Spatrick MachineBasicBlock *ThisMBB = BB;
333709467b48Spatrick MachineFunction *F = BB->getParent();
333809467b48Spatrick MachineBasicBlock *IfFalseMBB = F->CreateMachineBasicBlock(LLVM_BB);
333909467b48Spatrick MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
334009467b48Spatrick F->insert(It, IfFalseMBB);
334109467b48Spatrick F->insert(It, SinkMBB);
334209467b48Spatrick
334309467b48Spatrick // Transfer the remainder of ThisMBB and its successor edges to SinkMBB.
334409467b48Spatrick SinkMBB->splice(SinkMBB->begin(), ThisMBB,
334509467b48Spatrick std::next(MachineBasicBlock::iterator(MI)), ThisMBB->end());
334609467b48Spatrick SinkMBB->transferSuccessorsAndUpdatePHIs(ThisMBB);
334709467b48Spatrick
334809467b48Spatrick // Set the new successors for ThisMBB.
334909467b48Spatrick ThisMBB->addSuccessor(IfFalseMBB);
335009467b48Spatrick ThisMBB->addSuccessor(SinkMBB);
335109467b48Spatrick
335209467b48Spatrick BuildMI(ThisMBB, dl, TII.get(BROpcode))
335309467b48Spatrick .addMBB(SinkMBB)
335409467b48Spatrick .addImm(CC);
335509467b48Spatrick
335609467b48Spatrick // IfFalseMBB just falls through to SinkMBB.
335709467b48Spatrick IfFalseMBB->addSuccessor(SinkMBB);
335809467b48Spatrick
335909467b48Spatrick // %Result = phi [ %TrueValue, ThisMBB ], [ %FalseValue, IfFalseMBB ]
336009467b48Spatrick BuildMI(*SinkMBB, SinkMBB->begin(), dl, TII.get(SP::PHI),
336109467b48Spatrick MI.getOperand(0).getReg())
336209467b48Spatrick .addReg(MI.getOperand(1).getReg())
336309467b48Spatrick .addMBB(ThisMBB)
336409467b48Spatrick .addReg(MI.getOperand(2).getReg())
336509467b48Spatrick .addMBB(IfFalseMBB);
336609467b48Spatrick
336709467b48Spatrick MI.eraseFromParent(); // The pseudo instruction is gone now.
336809467b48Spatrick return SinkMBB;
336909467b48Spatrick }
337009467b48Spatrick
337109467b48Spatrick //===----------------------------------------------------------------------===//
337209467b48Spatrick // Sparc Inline Assembly Support
337309467b48Spatrick //===----------------------------------------------------------------------===//
337409467b48Spatrick
337509467b48Spatrick /// getConstraintType - Given a constraint letter, return the type of
337609467b48Spatrick /// constraint it is for this target.
337709467b48Spatrick SparcTargetLowering::ConstraintType
getConstraintType(StringRef Constraint) const337809467b48Spatrick SparcTargetLowering::getConstraintType(StringRef Constraint) const {
337909467b48Spatrick if (Constraint.size() == 1) {
338009467b48Spatrick switch (Constraint[0]) {
338109467b48Spatrick default: break;
338209467b48Spatrick case 'r':
338309467b48Spatrick case 'f':
338409467b48Spatrick case 'e':
338509467b48Spatrick return C_RegisterClass;
338609467b48Spatrick case 'I': // SIMM13
338709467b48Spatrick return C_Immediate;
338809467b48Spatrick }
338909467b48Spatrick }
339009467b48Spatrick
339109467b48Spatrick return TargetLowering::getConstraintType(Constraint);
339209467b48Spatrick }
339309467b48Spatrick
339409467b48Spatrick TargetLowering::ConstraintWeight SparcTargetLowering::
getSingleConstraintMatchWeight(AsmOperandInfo & info,const char * constraint) const339509467b48Spatrick getSingleConstraintMatchWeight(AsmOperandInfo &info,
339609467b48Spatrick const char *constraint) const {
339709467b48Spatrick ConstraintWeight weight = CW_Invalid;
339809467b48Spatrick Value *CallOperandVal = info.CallOperandVal;
339909467b48Spatrick // If we don't have a value, we can't do a match,
340009467b48Spatrick // but allow it at the lowest weight.
340109467b48Spatrick if (!CallOperandVal)
340209467b48Spatrick return CW_Default;
340309467b48Spatrick
340409467b48Spatrick // Look at the constraint type.
340509467b48Spatrick switch (*constraint) {
340609467b48Spatrick default:
340709467b48Spatrick weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
340809467b48Spatrick break;
340909467b48Spatrick case 'I': // SIMM13
341009467b48Spatrick if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
341109467b48Spatrick if (isInt<13>(C->getSExtValue()))
341209467b48Spatrick weight = CW_Constant;
341309467b48Spatrick }
341409467b48Spatrick break;
341509467b48Spatrick }
341609467b48Spatrick return weight;
341709467b48Spatrick }
341809467b48Spatrick
341909467b48Spatrick /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
342009467b48Spatrick /// vector. If it is invalid, don't add anything to Ops.
342109467b48Spatrick void SparcTargetLowering::
LowerAsmOperandForConstraint(SDValue Op,std::string & Constraint,std::vector<SDValue> & Ops,SelectionDAG & DAG) const342209467b48Spatrick LowerAsmOperandForConstraint(SDValue Op,
342309467b48Spatrick std::string &Constraint,
342409467b48Spatrick std::vector<SDValue> &Ops,
342509467b48Spatrick SelectionDAG &DAG) const {
3426*a96b3639Srobert SDValue Result;
342709467b48Spatrick
342809467b48Spatrick // Only support length 1 constraints for now.
342909467b48Spatrick if (Constraint.length() > 1)
343009467b48Spatrick return;
343109467b48Spatrick
343209467b48Spatrick char ConstraintLetter = Constraint[0];
343309467b48Spatrick switch (ConstraintLetter) {
343409467b48Spatrick default: break;
343509467b48Spatrick case 'I':
343609467b48Spatrick if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
343709467b48Spatrick if (isInt<13>(C->getSExtValue())) {
343809467b48Spatrick Result = DAG.getTargetConstant(C->getSExtValue(), SDLoc(Op),
343909467b48Spatrick Op.getValueType());
344009467b48Spatrick break;
344109467b48Spatrick }
344209467b48Spatrick return;
344309467b48Spatrick }
344409467b48Spatrick }
344509467b48Spatrick
344609467b48Spatrick if (Result.getNode()) {
344709467b48Spatrick Ops.push_back(Result);
344809467b48Spatrick return;
344909467b48Spatrick }
345009467b48Spatrick TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
345109467b48Spatrick }
345209467b48Spatrick
345309467b48Spatrick std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo * TRI,StringRef Constraint,MVT VT) const345409467b48Spatrick SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
345509467b48Spatrick StringRef Constraint,
345609467b48Spatrick MVT VT) const {
3457*a96b3639Srobert if (Constraint.empty())
3458*a96b3639Srobert return std::make_pair(0U, nullptr);
3459*a96b3639Srobert
346009467b48Spatrick if (Constraint.size() == 1) {
346109467b48Spatrick switch (Constraint[0]) {
346209467b48Spatrick case 'r':
346309467b48Spatrick if (VT == MVT::v2i32)
346409467b48Spatrick return std::make_pair(0U, &SP::IntPairRegClass);
346509467b48Spatrick else if (Subtarget->is64Bit())
346609467b48Spatrick return std::make_pair(0U, &SP::I64RegsRegClass);
346709467b48Spatrick else
346809467b48Spatrick return std::make_pair(0U, &SP::IntRegsRegClass);
346909467b48Spatrick case 'f':
347009467b48Spatrick if (VT == MVT::f32 || VT == MVT::i32)
347109467b48Spatrick return std::make_pair(0U, &SP::FPRegsRegClass);
347209467b48Spatrick else if (VT == MVT::f64 || VT == MVT::i64)
347309467b48Spatrick return std::make_pair(0U, &SP::LowDFPRegsRegClass);
347409467b48Spatrick else if (VT == MVT::f128)
347509467b48Spatrick return std::make_pair(0U, &SP::LowQFPRegsRegClass);
347609467b48Spatrick // This will generate an error message
347709467b48Spatrick return std::make_pair(0U, nullptr);
347809467b48Spatrick case 'e':
347909467b48Spatrick if (VT == MVT::f32 || VT == MVT::i32)
348009467b48Spatrick return std::make_pair(0U, &SP::FPRegsRegClass);
348109467b48Spatrick else if (VT == MVT::f64 || VT == MVT::i64 )
348209467b48Spatrick return std::make_pair(0U, &SP::DFPRegsRegClass);
348309467b48Spatrick else if (VT == MVT::f128)
348409467b48Spatrick return std::make_pair(0U, &SP::QFPRegsRegClass);
348509467b48Spatrick // This will generate an error message
348609467b48Spatrick return std::make_pair(0U, nullptr);
348709467b48Spatrick }
3488*a96b3639Srobert }
3489*a96b3639Srobert
3490*a96b3639Srobert if (Constraint.front() != '{')
3491*a96b3639Srobert return std::make_pair(0U, nullptr);
3492*a96b3639Srobert
3493*a96b3639Srobert assert(Constraint.back() == '}' && "Not a brace enclosed constraint?");
3494*a96b3639Srobert StringRef RegName(Constraint.data() + 1, Constraint.size() - 2);
3495*a96b3639Srobert if (RegName.empty())
3496*a96b3639Srobert return std::make_pair(0U, nullptr);
3497*a96b3639Srobert
3498*a96b3639Srobert unsigned long long RegNo;
3499*a96b3639Srobert // Handle numbered register aliases.
3500*a96b3639Srobert if (RegName[0] == 'r' &&
3501*a96b3639Srobert getAsUnsignedInteger(RegName.begin() + 1, 10, RegNo)) {
350209467b48Spatrick // r0-r7 -> g0-g7
350309467b48Spatrick // r8-r15 -> o0-o7
350409467b48Spatrick // r16-r23 -> l0-l7
350509467b48Spatrick // r24-r31 -> i0-i7
3506*a96b3639Srobert if (RegNo > 31)
3507*a96b3639Srobert return std::make_pair(0U, nullptr);
3508*a96b3639Srobert const char RegTypes[] = {'g', 'o', 'l', 'i'};
3509*a96b3639Srobert char RegType = RegTypes[RegNo / 8];
3510*a96b3639Srobert char RegIndex = '0' + (RegNo % 8);
3511*a96b3639Srobert char Tmp[] = {'{', RegType, RegIndex, '}', 0};
3512*a96b3639Srobert return getRegForInlineAsmConstraint(TRI, Tmp, VT);
351309467b48Spatrick }
351409467b48Spatrick
3515*a96b3639Srobert // Rewrite the fN constraint according to the value type if needed.
3516*a96b3639Srobert if (VT != MVT::f32 && VT != MVT::Other && RegName[0] == 'f' &&
3517*a96b3639Srobert getAsUnsignedInteger(RegName.begin() + 1, 10, RegNo)) {
3518*a96b3639Srobert if (VT == MVT::f64 && (RegNo % 2 == 0)) {
3519*a96b3639Srobert return getRegForInlineAsmConstraint(
3520*a96b3639Srobert TRI, StringRef("{d" + utostr(RegNo / 2) + "}"), VT);
3521*a96b3639Srobert } else if (VT == MVT::f128 && (RegNo % 4 == 0)) {
3522*a96b3639Srobert return getRegForInlineAsmConstraint(
3523*a96b3639Srobert TRI, StringRef("{q" + utostr(RegNo / 4) + "}"), VT);
352409467b48Spatrick } else {
352509467b48Spatrick return std::make_pair(0U, nullptr);
352609467b48Spatrick }
352709467b48Spatrick }
352809467b48Spatrick
3529*a96b3639Srobert auto ResultPair =
3530*a96b3639Srobert TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
3531*a96b3639Srobert if (!ResultPair.second)
3532*a96b3639Srobert return std::make_pair(0U, nullptr);
3533*a96b3639Srobert
3534*a96b3639Srobert // Force the use of I64Regs over IntRegs for 64-bit values.
3535*a96b3639Srobert if (Subtarget->is64Bit() && VT == MVT::i64) {
3536*a96b3639Srobert assert(ResultPair.second == &SP::IntRegsRegClass &&
3537*a96b3639Srobert "Unexpected register class");
3538*a96b3639Srobert return std::make_pair(ResultPair.first, &SP::I64RegsRegClass);
3539*a96b3639Srobert }
3540*a96b3639Srobert
3541*a96b3639Srobert return ResultPair;
354209467b48Spatrick }
354309467b48Spatrick
354409467b48Spatrick bool
isOffsetFoldingLegal(const GlobalAddressSDNode * GA) const354509467b48Spatrick SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
354609467b48Spatrick // The Sparc target isn't yet aware of offsets.
354709467b48Spatrick return false;
354809467b48Spatrick }
354909467b48Spatrick
ReplaceNodeResults(SDNode * N,SmallVectorImpl<SDValue> & Results,SelectionDAG & DAG) const355009467b48Spatrick void SparcTargetLowering::ReplaceNodeResults(SDNode *N,
355109467b48Spatrick SmallVectorImpl<SDValue>& Results,
355209467b48Spatrick SelectionDAG &DAG) const {
355309467b48Spatrick
355409467b48Spatrick SDLoc dl(N);
355509467b48Spatrick
355609467b48Spatrick RTLIB::Libcall libCall = RTLIB::UNKNOWN_LIBCALL;
355709467b48Spatrick
355809467b48Spatrick switch (N->getOpcode()) {
355909467b48Spatrick default:
356009467b48Spatrick llvm_unreachable("Do not know how to custom type legalize this operation!");
356109467b48Spatrick
356209467b48Spatrick case ISD::FP_TO_SINT:
356309467b48Spatrick case ISD::FP_TO_UINT:
356409467b48Spatrick // Custom lower only if it involves f128 or i64.
356509467b48Spatrick if (N->getOperand(0).getValueType() != MVT::f128
356609467b48Spatrick || N->getValueType(0) != MVT::i64)
356709467b48Spatrick return;
356809467b48Spatrick libCall = ((N->getOpcode() == ISD::FP_TO_SINT)
356909467b48Spatrick ? RTLIB::FPTOSINT_F128_I64
357009467b48Spatrick : RTLIB::FPTOUINT_F128_I64);
357109467b48Spatrick
357209467b48Spatrick Results.push_back(LowerF128Op(SDValue(N, 0),
357309467b48Spatrick DAG,
357409467b48Spatrick getLibcallName(libCall),
357509467b48Spatrick 1));
357609467b48Spatrick return;
357709467b48Spatrick case ISD::READCYCLECOUNTER: {
357809467b48Spatrick assert(Subtarget->hasLeonCycleCounter());
357909467b48Spatrick SDValue Lo = DAG.getCopyFromReg(N->getOperand(0), dl, SP::ASR23, MVT::i32);
358009467b48Spatrick SDValue Hi = DAG.getCopyFromReg(Lo, dl, SP::G0, MVT::i32);
358109467b48Spatrick SDValue Ops[] = { Lo, Hi };
358209467b48Spatrick SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Ops);
358309467b48Spatrick Results.push_back(Pair);
358409467b48Spatrick Results.push_back(N->getOperand(0));
358509467b48Spatrick return;
358609467b48Spatrick }
358709467b48Spatrick case ISD::SINT_TO_FP:
358809467b48Spatrick case ISD::UINT_TO_FP:
358909467b48Spatrick // Custom lower only if it involves f128 or i64.
359009467b48Spatrick if (N->getValueType(0) != MVT::f128
359109467b48Spatrick || N->getOperand(0).getValueType() != MVT::i64)
359209467b48Spatrick return;
359309467b48Spatrick
359409467b48Spatrick libCall = ((N->getOpcode() == ISD::SINT_TO_FP)
359509467b48Spatrick ? RTLIB::SINTTOFP_I64_F128
359609467b48Spatrick : RTLIB::UINTTOFP_I64_F128);
359709467b48Spatrick
359809467b48Spatrick Results.push_back(LowerF128Op(SDValue(N, 0),
359909467b48Spatrick DAG,
360009467b48Spatrick getLibcallName(libCall),
360109467b48Spatrick 1));
360209467b48Spatrick return;
360309467b48Spatrick case ISD::LOAD: {
360409467b48Spatrick LoadSDNode *Ld = cast<LoadSDNode>(N);
360509467b48Spatrick // Custom handling only for i64: turn i64 load into a v2i32 load,
360609467b48Spatrick // and a bitcast.
360709467b48Spatrick if (Ld->getValueType(0) != MVT::i64 || Ld->getMemoryVT() != MVT::i64)
360809467b48Spatrick return;
360909467b48Spatrick
361009467b48Spatrick SDLoc dl(N);
361109467b48Spatrick SDValue LoadRes = DAG.getExtLoad(
361209467b48Spatrick Ld->getExtensionType(), dl, MVT::v2i32, Ld->getChain(),
3613a0747c9fSpatrick Ld->getBasePtr(), Ld->getPointerInfo(), MVT::v2i32,
3614a0747c9fSpatrick Ld->getOriginalAlign(), Ld->getMemOperand()->getFlags(),
3615a0747c9fSpatrick Ld->getAAInfo());
361609467b48Spatrick
361709467b48Spatrick SDValue Res = DAG.getNode(ISD::BITCAST, dl, MVT::i64, LoadRes);
361809467b48Spatrick Results.push_back(Res);
361909467b48Spatrick Results.push_back(LoadRes.getValue(1));
362009467b48Spatrick return;
362109467b48Spatrick }
362209467b48Spatrick }
362309467b48Spatrick }
362409467b48Spatrick
362509467b48Spatrick // Override to enable LOAD_STACK_GUARD lowering on Linux.
useLoadStackGuardNode() const362609467b48Spatrick bool SparcTargetLowering::useLoadStackGuardNode() const {
362709467b48Spatrick if (!Subtarget->isTargetLinux())
362809467b48Spatrick return TargetLowering::useLoadStackGuardNode();
362909467b48Spatrick return true;
363009467b48Spatrick }
363109467b48Spatrick
363209467b48Spatrick // Override to disable global variable loading on Linux.
insertSSPDeclarations(Module & M) const363309467b48Spatrick void SparcTargetLowering::insertSSPDeclarations(Module &M) const {
363409467b48Spatrick if (!Subtarget->isTargetLinux())
363509467b48Spatrick return TargetLowering::insertSSPDeclarations(M);
363609467b48Spatrick }
3637