10b57cec5SDimitry Andric //===-- SparcISelLowering.cpp - Sparc DAG Lowering Implementation ---------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the interfaces that Sparc uses to lower LLVM code into a
100b57cec5SDimitry Andric // selection DAG.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "SparcISelLowering.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/SparcMCExpr.h"
1674626c16SDimitry Andric #include "MCTargetDesc/SparcMCTargetDesc.h"
170b57cec5SDimitry Andric #include "SparcMachineFunctionInfo.h"
180b57cec5SDimitry Andric #include "SparcRegisterInfo.h"
190b57cec5SDimitry Andric #include "SparcTargetMachine.h"
200b57cec5SDimitry Andric #include "SparcTargetObjectFile.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
220b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
29bdd1243dSDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
310b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
3274626c16SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
330b57cec5SDimitry Andric #include "llvm/IR/Function.h"
340b57cec5SDimitry Andric #include "llvm/IR/Module.h"
350b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
360b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h"
370b57cec5SDimitry Andric using namespace llvm;
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
410b57cec5SDimitry Andric // Calling Convention Implementation
420b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
430b57cec5SDimitry Andric
CC_Sparc_Assign_SRet(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)440b57cec5SDimitry Andric static bool CC_Sparc_Assign_SRet(unsigned &ValNo, MVT &ValVT,
450b57cec5SDimitry Andric MVT &LocVT, CCValAssign::LocInfo &LocInfo,
460b57cec5SDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State)
470b57cec5SDimitry Andric {
480b57cec5SDimitry Andric assert (ArgFlags.isSRet());
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric // Assign SRet argument.
510b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
520b57cec5SDimitry Andric 0,
530b57cec5SDimitry Andric LocVT, LocInfo));
540b57cec5SDimitry Andric return true;
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric
CC_Sparc_Assign_Split_64(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)570b57cec5SDimitry Andric static bool CC_Sparc_Assign_Split_64(unsigned &ValNo, MVT &ValVT,
580b57cec5SDimitry Andric MVT &LocVT, CCValAssign::LocInfo &LocInfo,
590b57cec5SDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State)
600b57cec5SDimitry Andric {
610b57cec5SDimitry Andric static const MCPhysReg RegList[] = {
620b57cec5SDimitry Andric SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
630b57cec5SDimitry Andric };
640b57cec5SDimitry Andric // Try to get first reg.
655ffd83dbSDimitry Andric if (Register Reg = State.AllocateReg(RegList)) {
660b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
670b57cec5SDimitry Andric } else {
680b57cec5SDimitry Andric // Assign whole thing in stack.
695ffd83dbSDimitry Andric State.addLoc(CCValAssign::getCustomMem(
705ffd83dbSDimitry Andric ValNo, ValVT, State.AllocateStack(8, Align(4)), LocVT, LocInfo));
710b57cec5SDimitry Andric return true;
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric // Try to get second reg.
755ffd83dbSDimitry Andric if (Register Reg = State.AllocateReg(RegList))
760b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
770b57cec5SDimitry Andric else
785ffd83dbSDimitry Andric State.addLoc(CCValAssign::getCustomMem(
795ffd83dbSDimitry Andric ValNo, ValVT, State.AllocateStack(4, Align(4)), LocVT, LocInfo));
800b57cec5SDimitry Andric return true;
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric
CC_Sparc_Assign_Ret_Split_64(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)830b57cec5SDimitry Andric static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT,
840b57cec5SDimitry Andric MVT &LocVT, CCValAssign::LocInfo &LocInfo,
850b57cec5SDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State)
860b57cec5SDimitry Andric {
870b57cec5SDimitry Andric static const MCPhysReg RegList[] = {
880b57cec5SDimitry Andric SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
890b57cec5SDimitry Andric };
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric // Try to get first reg.
925ffd83dbSDimitry Andric if (Register Reg = State.AllocateReg(RegList))
930b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
940b57cec5SDimitry Andric else
950b57cec5SDimitry Andric return false;
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric // Try to get second reg.
985ffd83dbSDimitry Andric if (Register Reg = State.AllocateReg(RegList))
990b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
1000b57cec5SDimitry Andric else
1010b57cec5SDimitry Andric return false;
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andric return true;
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric // 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)107f3fd488fSDimitry Andric static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT,
1080b57cec5SDimitry Andric MVT &LocVT, CCValAssign::LocInfo &LocInfo,
1090b57cec5SDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) {
1100b57cec5SDimitry Andric assert((LocVT == MVT::f32 || LocVT == MVT::f128
1110b57cec5SDimitry Andric || LocVT.getSizeInBits() == 64) &&
1120b57cec5SDimitry Andric "Can't handle non-64 bits locations");
1130b57cec5SDimitry Andric
1140b57cec5SDimitry Andric // Stack space is allocated for all arguments starting from [%fp+BIAS+128].
1150b57cec5SDimitry Andric unsigned size = (LocVT == MVT::f128) ? 16 : 8;
1165ffd83dbSDimitry Andric Align alignment = (LocVT == MVT::f128) ? Align(16) : Align(8);
1170b57cec5SDimitry Andric unsigned Offset = State.AllocateStack(size, alignment);
1180b57cec5SDimitry Andric unsigned Reg = 0;
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric if (LocVT == MVT::i64 && Offset < 6*8)
1210b57cec5SDimitry Andric // Promote integers to %i0-%i5.
1220b57cec5SDimitry Andric Reg = SP::I0 + Offset/8;
1230b57cec5SDimitry Andric else if (LocVT == MVT::f64 && Offset < 16*8)
1240b57cec5SDimitry Andric // Promote doubles to %d0-%d30. (Which LLVM calls D0-D15).
1250b57cec5SDimitry Andric Reg = SP::D0 + Offset/8;
1260b57cec5SDimitry Andric else if (LocVT == MVT::f32 && Offset < 16*8)
1270b57cec5SDimitry Andric // Promote floats to %f1, %f3, ...
1280b57cec5SDimitry Andric Reg = SP::F1 + Offset/4;
1290b57cec5SDimitry Andric else if (LocVT == MVT::f128 && Offset < 16*8)
1300b57cec5SDimitry Andric // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7).
1310b57cec5SDimitry Andric Reg = SP::Q0 + Offset/16;
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric // Promote to register when possible, otherwise use the stack slot.
1340b57cec5SDimitry Andric if (Reg) {
1350b57cec5SDimitry Andric State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
1360b57cec5SDimitry Andric return true;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric
139f3fd488fSDimitry Andric // Bail out if this is a return CC and we run out of registers to place
140f3fd488fSDimitry Andric // values into.
141f3fd488fSDimitry Andric if (IsReturn)
142f3fd488fSDimitry Andric return false;
143f3fd488fSDimitry Andric
1440b57cec5SDimitry Andric // This argument goes on the stack in an 8-byte slot.
1450b57cec5SDimitry Andric // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to
1460b57cec5SDimitry Andric // the right-aligned float. The first 4 bytes of the stack slot are undefined.
1470b57cec5SDimitry Andric if (LocVT == MVT::f32)
1480b57cec5SDimitry Andric Offset += 4;
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andric State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
1510b57cec5SDimitry Andric return true;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andric // Allocate a half-sized argument for the 64-bit ABI.
1550b57cec5SDimitry Andric //
1560b57cec5SDimitry Andric // 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)157f3fd488fSDimitry Andric static bool Analyze_CC_Sparc64_Half(bool IsReturn, unsigned &ValNo, MVT &ValVT,
1580b57cec5SDimitry Andric MVT &LocVT, CCValAssign::LocInfo &LocInfo,
1590b57cec5SDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) {
1600b57cec5SDimitry Andric assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations");
1615ffd83dbSDimitry Andric unsigned Offset = State.AllocateStack(4, Align(4));
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric if (LocVT == MVT::f32 && Offset < 16*8) {
1640b57cec5SDimitry Andric // Promote floats to %f0-%f31.
1650b57cec5SDimitry Andric State.addLoc(CCValAssign::getReg(ValNo, ValVT, SP::F0 + Offset/4,
1660b57cec5SDimitry Andric LocVT, LocInfo));
1670b57cec5SDimitry Andric return true;
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric
1700b57cec5SDimitry Andric if (LocVT == MVT::i32 && Offset < 6*8) {
1710b57cec5SDimitry Andric // Promote integers to %i0-%i5, using half the register.
1720b57cec5SDimitry Andric unsigned Reg = SP::I0 + Offset/8;
1730b57cec5SDimitry Andric LocVT = MVT::i64;
1740b57cec5SDimitry Andric LocInfo = CCValAssign::AExt;
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric // Set the Custom bit if this i32 goes in the high bits of a register.
1770b57cec5SDimitry Andric if (Offset % 8 == 0)
1780b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg,
1790b57cec5SDimitry Andric LocVT, LocInfo));
1800b57cec5SDimitry Andric else
1810b57cec5SDimitry Andric State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
1820b57cec5SDimitry Andric return true;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric
185f3fd488fSDimitry Andric // Bail out if this is a return CC and we run out of registers to place
186f3fd488fSDimitry Andric // values into.
187f3fd488fSDimitry Andric if (IsReturn)
188f3fd488fSDimitry Andric return false;
189f3fd488fSDimitry Andric
1900b57cec5SDimitry Andric State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
1910b57cec5SDimitry Andric return true;
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
CC_Sparc64_Full(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)194f3fd488fSDimitry Andric static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
195f3fd488fSDimitry Andric CCValAssign::LocInfo &LocInfo,
196f3fd488fSDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) {
197f3fd488fSDimitry Andric return Analyze_CC_Sparc64_Full(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
198f3fd488fSDimitry Andric State);
199f3fd488fSDimitry Andric }
200f3fd488fSDimitry Andric
CC_Sparc64_Half(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)201f3fd488fSDimitry Andric static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
202f3fd488fSDimitry Andric CCValAssign::LocInfo &LocInfo,
203f3fd488fSDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) {
204f3fd488fSDimitry Andric return Analyze_CC_Sparc64_Half(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
205f3fd488fSDimitry Andric State);
206f3fd488fSDimitry Andric }
207f3fd488fSDimitry Andric
RetCC_Sparc64_Full(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)208f3fd488fSDimitry Andric static bool RetCC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
209f3fd488fSDimitry Andric CCValAssign::LocInfo &LocInfo,
210f3fd488fSDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) {
211f3fd488fSDimitry Andric return Analyze_CC_Sparc64_Full(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
212f3fd488fSDimitry Andric State);
213f3fd488fSDimitry Andric }
214f3fd488fSDimitry Andric
RetCC_Sparc64_Half(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)215f3fd488fSDimitry Andric static bool RetCC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
216f3fd488fSDimitry Andric CCValAssign::LocInfo &LocInfo,
217f3fd488fSDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) {
218f3fd488fSDimitry Andric return Analyze_CC_Sparc64_Half(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
219f3fd488fSDimitry Andric State);
220f3fd488fSDimitry Andric }
221f3fd488fSDimitry Andric
2220b57cec5SDimitry Andric #include "SparcGenCallingConv.inc"
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric // The calling conventions in SparcCallingConv.td are described in terms of the
2250b57cec5SDimitry Andric // callee's register window. This function translates registers to the
2260b57cec5SDimitry Andric // corresponding caller window %o register.
toCallerWindow(unsigned Reg)2270b57cec5SDimitry Andric static unsigned toCallerWindow(unsigned Reg) {
2280b57cec5SDimitry Andric static_assert(SP::I0 + 7 == SP::I7 && SP::O0 + 7 == SP::O7,
2290b57cec5SDimitry Andric "Unexpected enum");
2300b57cec5SDimitry Andric if (Reg >= SP::I0 && Reg <= SP::I7)
2310b57cec5SDimitry Andric return Reg - SP::I0 + SP::O0;
2320b57cec5SDimitry Andric return Reg;
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric
CanLowerReturn(CallingConv::ID CallConv,MachineFunction & MF,bool isVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,LLVMContext & Context) const235f3fd488fSDimitry Andric bool SparcTargetLowering::CanLowerReturn(
236f3fd488fSDimitry Andric CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
237f3fd488fSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
238f3fd488fSDimitry Andric SmallVector<CCValAssign, 16> RVLocs;
239f3fd488fSDimitry Andric CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
240f3fd488fSDimitry Andric return CCInfo.CheckReturn(Outs, Subtarget->is64Bit() ? RetCC_Sparc64
241f3fd488fSDimitry Andric : RetCC_Sparc32);
242f3fd488fSDimitry Andric }
243f3fd488fSDimitry Andric
2440b57cec5SDimitry Andric SDValue
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const2450b57cec5SDimitry Andric SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
2460b57cec5SDimitry Andric bool IsVarArg,
2470b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs,
2480b57cec5SDimitry Andric const SmallVectorImpl<SDValue> &OutVals,
2490b57cec5SDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const {
2500b57cec5SDimitry Andric if (Subtarget->is64Bit())
2510b57cec5SDimitry Andric return LowerReturn_64(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG);
2520b57cec5SDimitry Andric return LowerReturn_32(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG);
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric
2550b57cec5SDimitry Andric SDValue
LowerReturn_32(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const2560b57cec5SDimitry Andric SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv,
2570b57cec5SDimitry Andric bool IsVarArg,
2580b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs,
2590b57cec5SDimitry Andric const SmallVectorImpl<SDValue> &OutVals,
2600b57cec5SDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const {
2610b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric // CCValAssign - represent the assignment of the return value to locations.
2640b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs;
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric // CCState - Info about the registers and stack slot.
2670b57cec5SDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
2680b57cec5SDimitry Andric *DAG.getContext());
2690b57cec5SDimitry Andric
2700b57cec5SDimitry Andric // Analyze return values.
2710b57cec5SDimitry Andric CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32);
2720b57cec5SDimitry Andric
27306c3fb27SDimitry Andric SDValue Glue;
2740b57cec5SDimitry Andric SmallVector<SDValue, 4> RetOps(1, Chain);
2750b57cec5SDimitry Andric // Make room for the return address offset.
2760b57cec5SDimitry Andric RetOps.push_back(SDValue());
2770b57cec5SDimitry Andric
2780b57cec5SDimitry Andric // Copy the result values into the output registers.
2790b57cec5SDimitry Andric for (unsigned i = 0, realRVLocIdx = 0;
2800b57cec5SDimitry Andric i != RVLocs.size();
2810b57cec5SDimitry Andric ++i, ++realRVLocIdx) {
2820b57cec5SDimitry Andric CCValAssign &VA = RVLocs[i];
2830b57cec5SDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!");
2840b57cec5SDimitry Andric
2850b57cec5SDimitry Andric SDValue Arg = OutVals[realRVLocIdx];
2860b57cec5SDimitry Andric
2870b57cec5SDimitry Andric if (VA.needsCustom()) {
2880b57cec5SDimitry Andric assert(VA.getLocVT() == MVT::v2i32);
2890b57cec5SDimitry Andric // Legalize ret v2i32 -> ret 2 x i32 (Basically: do what would
2900b57cec5SDimitry Andric // happen by default if this wasn't a legal type)
2910b57cec5SDimitry Andric
2920b57cec5SDimitry Andric SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32,
2930b57cec5SDimitry Andric Arg,
2940b57cec5SDimitry Andric DAG.getConstant(0, DL, getVectorIdxTy(DAG.getDataLayout())));
2950b57cec5SDimitry Andric SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32,
2960b57cec5SDimitry Andric Arg,
2970b57cec5SDimitry Andric DAG.getConstant(1, DL, getVectorIdxTy(DAG.getDataLayout())));
2980b57cec5SDimitry Andric
29906c3fb27SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part0, Glue);
30006c3fb27SDimitry Andric Glue = Chain.getValue(1);
3010b57cec5SDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3020b57cec5SDimitry Andric VA = RVLocs[++i]; // skip ahead to next loc
3030b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part1,
30406c3fb27SDimitry Andric Glue);
3050b57cec5SDimitry Andric } else
30606c3fb27SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Glue);
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andric // Guarantee that all emitted copies are stuck together with flags.
30906c3fb27SDimitry Andric Glue = Chain.getValue(1);
3100b57cec5SDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric
3130b57cec5SDimitry Andric unsigned RetAddrOffset = 8; // Call Inst + Delay Slot
3140b57cec5SDimitry Andric // If the function returns a struct, copy the SRetReturnReg to I0
3150b57cec5SDimitry Andric if (MF.getFunction().hasStructRetAttr()) {
3160b57cec5SDimitry Andric SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
3175ffd83dbSDimitry Andric Register Reg = SFI->getSRetReturnReg();
3180b57cec5SDimitry Andric if (!Reg)
3190b57cec5SDimitry Andric llvm_unreachable("sret virtual register not created in the entry block");
3200b57cec5SDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout());
3210b57cec5SDimitry Andric SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, PtrVT);
32206c3fb27SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, SP::I0, Val, Glue);
32306c3fb27SDimitry Andric Glue = Chain.getValue(1);
3240b57cec5SDimitry Andric RetOps.push_back(DAG.getRegister(SP::I0, PtrVT));
3250b57cec5SDimitry Andric RetAddrOffset = 12; // CallInst + Delay Slot + Unimp
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andric RetOps[0] = Chain; // Update chain.
3290b57cec5SDimitry Andric RetOps[1] = DAG.getConstant(RetAddrOffset, DL, MVT::i32);
3300b57cec5SDimitry Andric
33106c3fb27SDimitry Andric // Add the glue if we have it.
33206c3fb27SDimitry Andric if (Glue.getNode())
33306c3fb27SDimitry Andric RetOps.push_back(Glue);
3340b57cec5SDimitry Andric
33506c3fb27SDimitry Andric return DAG.getNode(SPISD::RET_GLUE, DL, MVT::Other, RetOps);
3360b57cec5SDimitry Andric }
3370b57cec5SDimitry Andric
3380b57cec5SDimitry Andric // Lower return values for the 64-bit ABI.
3390b57cec5SDimitry Andric // Return values are passed the exactly the same way as function arguments.
3400b57cec5SDimitry Andric SDValue
LowerReturn_64(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const3410b57cec5SDimitry Andric SparcTargetLowering::LowerReturn_64(SDValue Chain, CallingConv::ID CallConv,
3420b57cec5SDimitry Andric bool IsVarArg,
3430b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs,
3440b57cec5SDimitry Andric const SmallVectorImpl<SDValue> &OutVals,
3450b57cec5SDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const {
3460b57cec5SDimitry Andric // CCValAssign - represent the assignment of the return value to locations.
3470b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs;
3480b57cec5SDimitry Andric
3490b57cec5SDimitry Andric // CCState - Info about the registers and stack slot.
3500b57cec5SDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
3510b57cec5SDimitry Andric *DAG.getContext());
3520b57cec5SDimitry Andric
3530b57cec5SDimitry Andric // Analyze return values.
3540b57cec5SDimitry Andric CCInfo.AnalyzeReturn(Outs, RetCC_Sparc64);
3550b57cec5SDimitry Andric
35606c3fb27SDimitry Andric SDValue Glue;
3570b57cec5SDimitry Andric SmallVector<SDValue, 4> RetOps(1, Chain);
3580b57cec5SDimitry Andric
3590b57cec5SDimitry Andric // The second operand on the return instruction is the return address offset.
3600b57cec5SDimitry Andric // The return address is always %i7+8 with the 64-bit ABI.
3610b57cec5SDimitry Andric RetOps.push_back(DAG.getConstant(8, DL, MVT::i32));
3620b57cec5SDimitry Andric
3630b57cec5SDimitry Andric // Copy the result values into the output registers.
3640b57cec5SDimitry Andric for (unsigned i = 0; i != RVLocs.size(); ++i) {
3650b57cec5SDimitry Andric CCValAssign &VA = RVLocs[i];
3660b57cec5SDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!");
3670b57cec5SDimitry Andric SDValue OutVal = OutVals[i];
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andric // Integer return values must be sign or zero extended by the callee.
3700b57cec5SDimitry Andric switch (VA.getLocInfo()) {
3710b57cec5SDimitry Andric case CCValAssign::Full: break;
3720b57cec5SDimitry Andric case CCValAssign::SExt:
3730b57cec5SDimitry Andric OutVal = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), OutVal);
3740b57cec5SDimitry Andric break;
3750b57cec5SDimitry Andric case CCValAssign::ZExt:
3760b57cec5SDimitry Andric OutVal = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), OutVal);
3770b57cec5SDimitry Andric break;
3780b57cec5SDimitry Andric case CCValAssign::AExt:
3790b57cec5SDimitry Andric OutVal = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), OutVal);
3800b57cec5SDimitry Andric break;
3810b57cec5SDimitry Andric default:
3820b57cec5SDimitry Andric llvm_unreachable("Unknown loc info!");
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric
3850b57cec5SDimitry Andric // The custom bit on an i32 return value indicates that it should be passed
3860b57cec5SDimitry Andric // in the high bits of the register.
3870b57cec5SDimitry Andric if (VA.getValVT() == MVT::i32 && VA.needsCustom()) {
3880b57cec5SDimitry Andric OutVal = DAG.getNode(ISD::SHL, DL, MVT::i64, OutVal,
3890b57cec5SDimitry Andric DAG.getConstant(32, DL, MVT::i32));
3900b57cec5SDimitry Andric
3910b57cec5SDimitry Andric // The next value may go in the low bits of the same register.
3920b57cec5SDimitry Andric // Handle both at once.
3930b57cec5SDimitry Andric if (i+1 < RVLocs.size() && RVLocs[i+1].getLocReg() == VA.getLocReg()) {
3940b57cec5SDimitry Andric SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, OutVals[i+1]);
3950b57cec5SDimitry Andric OutVal = DAG.getNode(ISD::OR, DL, MVT::i64, OutVal, NV);
3960b57cec5SDimitry Andric // Skip the next value, it's already done.
3970b57cec5SDimitry Andric ++i;
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric
40106c3fb27SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVal, Glue);
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric // Guarantee that all emitted copies are stuck together with flags.
40406c3fb27SDimitry Andric Glue = Chain.getValue(1);
4050b57cec5SDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric
4080b57cec5SDimitry Andric RetOps[0] = Chain; // Update chain.
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric // Add the flag if we have it.
41106c3fb27SDimitry Andric if (Glue.getNode())
41206c3fb27SDimitry Andric RetOps.push_back(Glue);
4130b57cec5SDimitry Andric
41406c3fb27SDimitry Andric return DAG.getNode(SPISD::RET_GLUE, DL, MVT::Other, RetOps);
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const4170b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerFormalArguments(
4180b57cec5SDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
4190b57cec5SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
4200b57cec5SDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
4210b57cec5SDimitry Andric if (Subtarget->is64Bit())
4220b57cec5SDimitry Andric return LowerFormalArguments_64(Chain, CallConv, IsVarArg, Ins,
4230b57cec5SDimitry Andric DL, DAG, InVals);
4240b57cec5SDimitry Andric return LowerFormalArguments_32(Chain, CallConv, IsVarArg, Ins,
4250b57cec5SDimitry Andric DL, DAG, InVals);
4260b57cec5SDimitry Andric }
4270b57cec5SDimitry Andric
4280b57cec5SDimitry Andric /// LowerFormalArguments32 - V8 uses a very simple ABI, where all values are
4290b57cec5SDimitry Andric /// passed in either one or two GPRs, including FP values. TODO: we should
4300b57cec5SDimitry Andric /// 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) const4310b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerFormalArguments_32(
4320b57cec5SDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
4330b57cec5SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
4340b57cec5SDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
4350b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
4360b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo();
4370b57cec5SDimitry Andric SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
4380b57cec5SDimitry Andric
4390b57cec5SDimitry Andric // Assign locations to all of the incoming arguments.
4400b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs;
4410b57cec5SDimitry Andric CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
4420b57cec5SDimitry Andric *DAG.getContext());
4430b57cec5SDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32);
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric const unsigned StackOffset = 92;
4460b57cec5SDimitry Andric bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
4470b57cec5SDimitry Andric
4480b57cec5SDimitry Andric unsigned InIdx = 0;
4490b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) {
4500b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i];
4510b57cec5SDimitry Andric
4520b57cec5SDimitry Andric if (Ins[InIdx].Flags.isSRet()) {
4530b57cec5SDimitry Andric if (InIdx != 0)
4540b57cec5SDimitry Andric report_fatal_error("sparc only supports sret on the first parameter");
4550b57cec5SDimitry Andric // Get SRet from [%fp+64].
4560b57cec5SDimitry Andric int FrameIdx = MF.getFrameInfo().CreateFixedObject(4, 64, true);
4570b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
4580b57cec5SDimitry Andric SDValue Arg =
4590b57cec5SDimitry Andric DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
4600b57cec5SDimitry Andric InVals.push_back(Arg);
4610b57cec5SDimitry Andric continue;
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric
4640b57cec5SDimitry Andric if (VA.isRegLoc()) {
4650b57cec5SDimitry Andric if (VA.needsCustom()) {
4660b57cec5SDimitry Andric assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32);
4670b57cec5SDimitry Andric
4688bcb0991SDimitry Andric Register VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
4690b57cec5SDimitry Andric MF.getRegInfo().addLiveIn(VA.getLocReg(), VRegHi);
4700b57cec5SDimitry Andric SDValue HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32);
4710b57cec5SDimitry Andric
4720b57cec5SDimitry Andric assert(i+1 < e);
4730b57cec5SDimitry Andric CCValAssign &NextVA = ArgLocs[++i];
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric SDValue LoVal;
4760b57cec5SDimitry Andric if (NextVA.isMemLoc()) {
4770b57cec5SDimitry Andric int FrameIdx = MF.getFrameInfo().
4780b57cec5SDimitry Andric CreateFixedObject(4, StackOffset+NextVA.getLocMemOffset(),true);
4790b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
4800b57cec5SDimitry Andric LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
4810b57cec5SDimitry Andric } else {
4825ffd83dbSDimitry Andric Register loReg = MF.addLiveIn(NextVA.getLocReg(),
4830b57cec5SDimitry Andric &SP::IntRegsRegClass);
4840b57cec5SDimitry Andric LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32);
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andric if (IsLittleEndian)
4880b57cec5SDimitry Andric std::swap(LoVal, HiVal);
4890b57cec5SDimitry Andric
4900b57cec5SDimitry Andric SDValue WholeValue =
4910b57cec5SDimitry Andric DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
4920b57cec5SDimitry Andric WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), WholeValue);
4930b57cec5SDimitry Andric InVals.push_back(WholeValue);
4940b57cec5SDimitry Andric continue;
4950b57cec5SDimitry Andric }
4968bcb0991SDimitry Andric Register VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
4970b57cec5SDimitry Andric MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg);
4980b57cec5SDimitry Andric SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
4990b57cec5SDimitry Andric if (VA.getLocVT() == MVT::f32)
5000b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
5010b57cec5SDimitry Andric else if (VA.getLocVT() != MVT::i32) {
5020b57cec5SDimitry Andric Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
5030b57cec5SDimitry Andric DAG.getValueType(VA.getLocVT()));
5040b57cec5SDimitry Andric Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric InVals.push_back(Arg);
5070b57cec5SDimitry Andric continue;
5080b57cec5SDimitry Andric }
5090b57cec5SDimitry Andric
5100b57cec5SDimitry Andric assert(VA.isMemLoc());
5110b57cec5SDimitry Andric
5120b57cec5SDimitry Andric unsigned Offset = VA.getLocMemOffset()+StackOffset;
5130b57cec5SDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout());
5140b57cec5SDimitry Andric
5150b57cec5SDimitry Andric if (VA.needsCustom()) {
5160b57cec5SDimitry Andric assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32);
5170b57cec5SDimitry Andric // If it is double-word aligned, just load.
5180b57cec5SDimitry Andric if (Offset % 8 == 0) {
5190b57cec5SDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(8,
5200b57cec5SDimitry Andric Offset,
5210b57cec5SDimitry Andric true);
5220b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
5230b57cec5SDimitry Andric SDValue Load =
5240b57cec5SDimitry Andric DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
5250b57cec5SDimitry Andric InVals.push_back(Load);
5260b57cec5SDimitry Andric continue;
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric
5290b57cec5SDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(4,
5300b57cec5SDimitry Andric Offset,
5310b57cec5SDimitry Andric true);
5320b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
5330b57cec5SDimitry Andric SDValue HiVal =
5340b57cec5SDimitry Andric DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
5350b57cec5SDimitry Andric int FI2 = MF.getFrameInfo().CreateFixedObject(4,
5360b57cec5SDimitry Andric Offset+4,
5370b57cec5SDimitry Andric true);
5380b57cec5SDimitry Andric SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT);
5390b57cec5SDimitry Andric
5400b57cec5SDimitry Andric SDValue LoVal =
5410b57cec5SDimitry Andric DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo());
5420b57cec5SDimitry Andric
5430b57cec5SDimitry Andric if (IsLittleEndian)
5440b57cec5SDimitry Andric std::swap(LoVal, HiVal);
5450b57cec5SDimitry Andric
5460b57cec5SDimitry Andric SDValue WholeValue =
5470b57cec5SDimitry Andric DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
5480b57cec5SDimitry Andric WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue);
5490b57cec5SDimitry Andric InVals.push_back(WholeValue);
5500b57cec5SDimitry Andric continue;
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric
5530b57cec5SDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(4,
5540b57cec5SDimitry Andric Offset,
5550b57cec5SDimitry Andric true);
5560b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
5570b57cec5SDimitry Andric SDValue Load ;
5580b57cec5SDimitry Andric if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) {
5590b57cec5SDimitry Andric Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
5600b57cec5SDimitry Andric } else if (VA.getValVT() == MVT::f128) {
5610b57cec5SDimitry Andric report_fatal_error("SPARCv8 does not handle f128 in calls; "
5620b57cec5SDimitry Andric "pass indirectly");
5630b57cec5SDimitry Andric } else {
5640b57cec5SDimitry Andric // We shouldn't see any other value types here.
5650b57cec5SDimitry Andric llvm_unreachable("Unexpected ValVT encountered in frame lowering.");
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric InVals.push_back(Load);
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric
5700b57cec5SDimitry Andric if (MF.getFunction().hasStructRetAttr()) {
5710b57cec5SDimitry Andric // Copy the SRet Argument to SRetReturnReg.
5720b57cec5SDimitry Andric SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
5735ffd83dbSDimitry Andric Register Reg = SFI->getSRetReturnReg();
5740b57cec5SDimitry Andric if (!Reg) {
5750b57cec5SDimitry Andric Reg = MF.getRegInfo().createVirtualRegister(&SP::IntRegsRegClass);
5760b57cec5SDimitry Andric SFI->setSRetReturnReg(Reg);
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]);
5790b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric
5820b57cec5SDimitry Andric // Store remaining ArgRegs to the stack if this is a varargs function.
5830b57cec5SDimitry Andric if (isVarArg) {
5840b57cec5SDimitry Andric static const MCPhysReg ArgRegs[] = {
5850b57cec5SDimitry Andric SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
5860b57cec5SDimitry Andric };
5870b57cec5SDimitry Andric unsigned NumAllocated = CCInfo.getFirstUnallocated(ArgRegs);
5880b57cec5SDimitry Andric const MCPhysReg *CurArgReg = ArgRegs+NumAllocated, *ArgRegEnd = ArgRegs+6;
58906c3fb27SDimitry Andric unsigned ArgOffset = CCInfo.getStackSize();
5900b57cec5SDimitry Andric if (NumAllocated == 6)
5910b57cec5SDimitry Andric ArgOffset += StackOffset;
5920b57cec5SDimitry Andric else {
5930b57cec5SDimitry Andric assert(!ArgOffset);
5940b57cec5SDimitry Andric ArgOffset = 68+4*NumAllocated;
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric
5970b57cec5SDimitry Andric // Remember the vararg offset for the va_start implementation.
5980b57cec5SDimitry Andric FuncInfo->setVarArgsFrameOffset(ArgOffset);
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric std::vector<SDValue> OutChains;
6010b57cec5SDimitry Andric
6020b57cec5SDimitry Andric for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
6038bcb0991SDimitry Andric Register VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
6040b57cec5SDimitry Andric MF.getRegInfo().addLiveIn(*CurArgReg, VReg);
6050b57cec5SDimitry Andric SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32);
6060b57cec5SDimitry Andric
6070b57cec5SDimitry Andric int FrameIdx = MF.getFrameInfo().CreateFixedObject(4, ArgOffset,
6080b57cec5SDimitry Andric true);
6090b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
6100b57cec5SDimitry Andric
6110b57cec5SDimitry Andric OutChains.push_back(
6120b57cec5SDimitry Andric DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, MachinePointerInfo()));
6130b57cec5SDimitry Andric ArgOffset += 4;
6140b57cec5SDimitry Andric }
6150b57cec5SDimitry Andric
6160b57cec5SDimitry Andric if (!OutChains.empty()) {
6170b57cec5SDimitry Andric OutChains.push_back(Chain);
6180b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric }
6210b57cec5SDimitry Andric
6220b57cec5SDimitry Andric return Chain;
6230b57cec5SDimitry Andric }
6240b57cec5SDimitry Andric
6250b57cec5SDimitry Andric // 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) const6260b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerFormalArguments_64(
6270b57cec5SDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
6280b57cec5SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
6290b57cec5SDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
6300b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
6310b57cec5SDimitry Andric
6320b57cec5SDimitry Andric // Analyze arguments according to CC_Sparc64.
6330b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs;
6340b57cec5SDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
6350b57cec5SDimitry Andric *DAG.getContext());
6360b57cec5SDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc64);
6370b57cec5SDimitry Andric
6380b57cec5SDimitry Andric // The argument array begins at %fp+BIAS+128, after the register save area.
6390b57cec5SDimitry Andric const unsigned ArgArea = 128;
6400b57cec5SDimitry Andric
641*0fca6ea1SDimitry Andric for (const CCValAssign &VA : ArgLocs) {
6420b57cec5SDimitry Andric if (VA.isRegLoc()) {
6430b57cec5SDimitry Andric // This argument is passed in a register.
6440b57cec5SDimitry Andric // All integer register arguments are promoted by the caller to i64.
6450b57cec5SDimitry Andric
6460b57cec5SDimitry Andric // Create a virtual register for the promoted live-in value.
6475ffd83dbSDimitry Andric Register VReg = MF.addLiveIn(VA.getLocReg(),
6480b57cec5SDimitry Andric getRegClassFor(VA.getLocVT()));
6490b57cec5SDimitry Andric SDValue Arg = DAG.getCopyFromReg(Chain, DL, VReg, VA.getLocVT());
6500b57cec5SDimitry Andric
6510b57cec5SDimitry Andric // Get the high bits for i32 struct elements.
6520b57cec5SDimitry Andric if (VA.getValVT() == MVT::i32 && VA.needsCustom())
6530b57cec5SDimitry Andric Arg = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), Arg,
6540b57cec5SDimitry Andric DAG.getConstant(32, DL, MVT::i32));
6550b57cec5SDimitry Andric
6560b57cec5SDimitry Andric // The caller promoted the argument, so insert an Assert?ext SDNode so we
6570b57cec5SDimitry Andric // won't promote the value again in this function.
6580b57cec5SDimitry Andric switch (VA.getLocInfo()) {
6590b57cec5SDimitry Andric case CCValAssign::SExt:
6600b57cec5SDimitry Andric Arg = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Arg,
6610b57cec5SDimitry Andric DAG.getValueType(VA.getValVT()));
6620b57cec5SDimitry Andric break;
6630b57cec5SDimitry Andric case CCValAssign::ZExt:
6640b57cec5SDimitry Andric Arg = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Arg,
6650b57cec5SDimitry Andric DAG.getValueType(VA.getValVT()));
6660b57cec5SDimitry Andric break;
6670b57cec5SDimitry Andric default:
6680b57cec5SDimitry Andric break;
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric
6710b57cec5SDimitry Andric // Truncate the register down to the argument type.
6720b57cec5SDimitry Andric if (VA.isExtInLoc())
6730b57cec5SDimitry Andric Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg);
6740b57cec5SDimitry Andric
6750b57cec5SDimitry Andric InVals.push_back(Arg);
6760b57cec5SDimitry Andric continue;
6770b57cec5SDimitry Andric }
6780b57cec5SDimitry Andric
6790b57cec5SDimitry Andric // The registers are exhausted. This argument was passed on the stack.
6800b57cec5SDimitry Andric assert(VA.isMemLoc());
6810b57cec5SDimitry Andric // The CC_Sparc64_Full/Half functions compute stack offsets relative to the
6820b57cec5SDimitry Andric // beginning of the arguments area at %fp+BIAS+128.
6830b57cec5SDimitry Andric unsigned Offset = VA.getLocMemOffset() + ArgArea;
6840b57cec5SDimitry Andric unsigned ValSize = VA.getValVT().getSizeInBits() / 8;
6850b57cec5SDimitry Andric // Adjust offset for extended arguments, SPARC is big-endian.
6860b57cec5SDimitry Andric // The caller will have written the full slot with extended bytes, but we
6870b57cec5SDimitry Andric // prefer our own extending loads.
6880b57cec5SDimitry Andric if (VA.isExtInLoc())
6890b57cec5SDimitry Andric Offset += 8 - ValSize;
6900b57cec5SDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(ValSize, Offset, true);
6910b57cec5SDimitry Andric InVals.push_back(
6920b57cec5SDimitry Andric DAG.getLoad(VA.getValVT(), DL, Chain,
6930b57cec5SDimitry Andric DAG.getFrameIndex(FI, getPointerTy(MF.getDataLayout())),
6940b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI)));
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric
6970b57cec5SDimitry Andric if (!IsVarArg)
6980b57cec5SDimitry Andric return Chain;
6990b57cec5SDimitry Andric
7000b57cec5SDimitry Andric // This function takes variable arguments, some of which may have been passed
7010b57cec5SDimitry Andric // in registers %i0-%i5. Variable floating point arguments are never passed
7020b57cec5SDimitry Andric // in floating point registers. They go on %i0-%i5 or on the stack like
7030b57cec5SDimitry Andric // integer arguments.
7040b57cec5SDimitry Andric //
7050b57cec5SDimitry Andric // The va_start intrinsic needs to know the offset to the first variable
7060b57cec5SDimitry Andric // argument.
70706c3fb27SDimitry Andric unsigned ArgOffset = CCInfo.getStackSize();
7080b57cec5SDimitry Andric SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
7090b57cec5SDimitry Andric // Skip the 128 bytes of register save area.
7100b57cec5SDimitry Andric FuncInfo->setVarArgsFrameOffset(ArgOffset + ArgArea +
7110b57cec5SDimitry Andric Subtarget->getStackPointerBias());
7120b57cec5SDimitry Andric
7130b57cec5SDimitry Andric // Save the variable arguments that were passed in registers.
7140b57cec5SDimitry Andric // The caller is required to reserve stack space for 6 arguments regardless
7150b57cec5SDimitry Andric // of how many arguments were actually passed.
7160b57cec5SDimitry Andric SmallVector<SDValue, 8> OutChains;
7170b57cec5SDimitry Andric for (; ArgOffset < 6*8; ArgOffset += 8) {
7185ffd83dbSDimitry Andric Register VReg = MF.addLiveIn(SP::I0 + ArgOffset/8, &SP::I64RegsRegClass);
7190b57cec5SDimitry Andric SDValue VArg = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64);
7200b57cec5SDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(8, ArgOffset + ArgArea, true);
7210b57cec5SDimitry Andric auto PtrVT = getPointerTy(MF.getDataLayout());
7220b57cec5SDimitry Andric OutChains.push_back(
7230b57cec5SDimitry Andric DAG.getStore(Chain, DL, VArg, DAG.getFrameIndex(FI, PtrVT),
7240b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI)));
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric
7270b57cec5SDimitry Andric if (!OutChains.empty())
7280b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
7290b57cec5SDimitry Andric
7300b57cec5SDimitry Andric return Chain;
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric
73374626c16SDimitry Andric // Check whether any of the argument registers are reserved
isAnyArgRegReserved(const SparcRegisterInfo * TRI,const MachineFunction & MF)73474626c16SDimitry Andric static bool isAnyArgRegReserved(const SparcRegisterInfo *TRI,
73574626c16SDimitry Andric const MachineFunction &MF) {
73674626c16SDimitry Andric // The register window design means that outgoing parameters at O*
73774626c16SDimitry Andric // will appear in the callee as I*.
73874626c16SDimitry Andric // Be conservative and check both sides of the register names.
73974626c16SDimitry Andric bool Outgoing =
74074626c16SDimitry Andric llvm::any_of(SP::GPROutgoingArgRegClass, [TRI, &MF](MCPhysReg r) {
74174626c16SDimitry Andric return TRI->isReservedReg(MF, r);
74274626c16SDimitry Andric });
74374626c16SDimitry Andric bool Incoming =
74474626c16SDimitry Andric llvm::any_of(SP::GPRIncomingArgRegClass, [TRI, &MF](MCPhysReg r) {
74574626c16SDimitry Andric return TRI->isReservedReg(MF, r);
74674626c16SDimitry Andric });
74774626c16SDimitry Andric return Outgoing || Incoming;
74874626c16SDimitry Andric }
74974626c16SDimitry Andric
emitReservedArgRegCallError(const MachineFunction & MF)75074626c16SDimitry Andric static void emitReservedArgRegCallError(const MachineFunction &MF) {
75174626c16SDimitry Andric const Function &F = MF.getFunction();
75274626c16SDimitry Andric F.getContext().diagnose(DiagnosticInfoUnsupported{
75374626c16SDimitry Andric F, ("SPARC doesn't support"
75474626c16SDimitry Andric " function calls if any of the argument registers is reserved.")});
75574626c16SDimitry Andric }
75674626c16SDimitry Andric
7570b57cec5SDimitry Andric SDValue
LowerCall(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const7580b57cec5SDimitry Andric SparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
7590b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const {
7600b57cec5SDimitry Andric if (Subtarget->is64Bit())
7610b57cec5SDimitry Andric return LowerCall_64(CLI, InVals);
7620b57cec5SDimitry Andric return LowerCall_32(CLI, InVals);
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric
hasReturnsTwiceAttr(SelectionDAG & DAG,SDValue Callee,const CallBase * Call)7650b57cec5SDimitry Andric static bool hasReturnsTwiceAttr(SelectionDAG &DAG, SDValue Callee,
7665ffd83dbSDimitry Andric const CallBase *Call) {
7675ffd83dbSDimitry Andric if (Call)
7685ffd83dbSDimitry Andric return Call->hasFnAttr(Attribute::ReturnsTwice);
7690b57cec5SDimitry Andric
7700b57cec5SDimitry Andric const Function *CalleeFn = nullptr;
7710b57cec5SDimitry Andric if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
7720b57cec5SDimitry Andric CalleeFn = dyn_cast<Function>(G->getGlobal());
7730b57cec5SDimitry Andric } else if (ExternalSymbolSDNode *E =
7740b57cec5SDimitry Andric dyn_cast<ExternalSymbolSDNode>(Callee)) {
7750b57cec5SDimitry Andric const Function &Fn = DAG.getMachineFunction().getFunction();
7760b57cec5SDimitry Andric const Module *M = Fn.getParent();
7770b57cec5SDimitry Andric const char *CalleeName = E->getSymbol();
7780b57cec5SDimitry Andric CalleeFn = M->getFunction(CalleeName);
7790b57cec5SDimitry Andric }
7800b57cec5SDimitry Andric
7810b57cec5SDimitry Andric if (!CalleeFn)
7820b57cec5SDimitry Andric return false;
7830b57cec5SDimitry Andric return CalleeFn->hasFnAttribute(Attribute::ReturnsTwice);
7840b57cec5SDimitry Andric }
7850b57cec5SDimitry Andric
78681ad6265SDimitry Andric /// IsEligibleForTailCallOptimization - Check whether the call is eligible
78781ad6265SDimitry Andric /// for tail call optimization.
IsEligibleForTailCallOptimization(CCState & CCInfo,CallLoweringInfo & CLI,MachineFunction & MF) const78881ad6265SDimitry Andric bool SparcTargetLowering::IsEligibleForTailCallOptimization(
78981ad6265SDimitry Andric CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF) const {
79081ad6265SDimitry Andric
79181ad6265SDimitry Andric auto &Outs = CLI.Outs;
79281ad6265SDimitry Andric auto &Caller = MF.getFunction();
79381ad6265SDimitry Andric
79481ad6265SDimitry Andric // Do not tail call opt functions with "disable-tail-calls" attribute.
79581ad6265SDimitry Andric if (Caller.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
79681ad6265SDimitry Andric return false;
79781ad6265SDimitry Andric
79881ad6265SDimitry Andric // Do not tail call opt if the stack is used to pass parameters.
799bdd1243dSDimitry Andric // 64-bit targets have a slightly higher limit since the ABI requires
800bdd1243dSDimitry Andric // to allocate some space even when all the parameters fit inside registers.
80106c3fb27SDimitry Andric unsigned StackSizeLimit = Subtarget->is64Bit() ? 48 : 0;
80206c3fb27SDimitry Andric if (CCInfo.getStackSize() > StackSizeLimit)
80381ad6265SDimitry Andric return false;
80481ad6265SDimitry Andric
80581ad6265SDimitry Andric // Do not tail call opt if either the callee or caller returns
80681ad6265SDimitry Andric // a struct and the other does not.
80781ad6265SDimitry Andric if (!Outs.empty() && Caller.hasStructRetAttr() != Outs[0].Flags.isSRet())
80881ad6265SDimitry Andric return false;
80981ad6265SDimitry Andric
81081ad6265SDimitry Andric // Byval parameters hand the function a pointer directly into the stack area
81181ad6265SDimitry Andric // we want to reuse during a tail call.
81281ad6265SDimitry Andric for (auto &Arg : Outs)
81381ad6265SDimitry Andric if (Arg.Flags.isByVal())
81481ad6265SDimitry Andric return false;
81581ad6265SDimitry Andric
81681ad6265SDimitry Andric return true;
81781ad6265SDimitry Andric }
81881ad6265SDimitry Andric
8190b57cec5SDimitry Andric // Lower a call for the 32-bit ABI.
8200b57cec5SDimitry Andric SDValue
LowerCall_32(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const8210b57cec5SDimitry Andric SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
8220b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const {
8230b57cec5SDimitry Andric SelectionDAG &DAG = CLI.DAG;
8240b57cec5SDimitry Andric SDLoc &dl = CLI.DL;
8250b57cec5SDimitry Andric SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
8260b57cec5SDimitry Andric SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
8270b57cec5SDimitry Andric SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
8280b57cec5SDimitry Andric SDValue Chain = CLI.Chain;
8290b57cec5SDimitry Andric SDValue Callee = CLI.Callee;
8300b57cec5SDimitry Andric bool &isTailCall = CLI.IsTailCall;
8310b57cec5SDimitry Andric CallingConv::ID CallConv = CLI.CallConv;
8320b57cec5SDimitry Andric bool isVarArg = CLI.IsVarArg;
83374626c16SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
8340b57cec5SDimitry Andric
8350b57cec5SDimitry Andric // Analyze operands of the call, assigning locations to each operand.
8360b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs;
8370b57cec5SDimitry Andric CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
8380b57cec5SDimitry Andric *DAG.getContext());
8390b57cec5SDimitry Andric CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32);
8400b57cec5SDimitry Andric
84181ad6265SDimitry Andric isTailCall = isTailCall && IsEligibleForTailCallOptimization(
84281ad6265SDimitry Andric CCInfo, CLI, DAG.getMachineFunction());
84381ad6265SDimitry Andric
8440b57cec5SDimitry Andric // Get the size of the outgoing arguments stack space requirement.
84506c3fb27SDimitry Andric unsigned ArgsSize = CCInfo.getStackSize();
8460b57cec5SDimitry Andric
8470b57cec5SDimitry Andric // Keep stack frames 8-byte aligned.
8480b57cec5SDimitry Andric ArgsSize = (ArgsSize+7) & ~7;
8490b57cec5SDimitry Andric
8500b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
8510b57cec5SDimitry Andric
8520b57cec5SDimitry Andric // Create local copies for byval args.
8530b57cec5SDimitry Andric SmallVector<SDValue, 8> ByValArgs;
8540b57cec5SDimitry Andric for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
8550b57cec5SDimitry Andric ISD::ArgFlagsTy Flags = Outs[i].Flags;
8560b57cec5SDimitry Andric if (!Flags.isByVal())
8570b57cec5SDimitry Andric continue;
8580b57cec5SDimitry Andric
8590b57cec5SDimitry Andric SDValue Arg = OutVals[i];
8600b57cec5SDimitry Andric unsigned Size = Flags.getByValSize();
8615ffd83dbSDimitry Andric Align Alignment = Flags.getNonZeroByValAlign();
8620b57cec5SDimitry Andric
8630b57cec5SDimitry Andric if (Size > 0U) {
8645ffd83dbSDimitry Andric int FI = MFI.CreateStackObject(Size, Alignment, false);
8650b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
8660b57cec5SDimitry Andric SDValue SizeNode = DAG.getConstant(Size, dl, MVT::i32);
8670b57cec5SDimitry Andric
8685ffd83dbSDimitry Andric Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Alignment,
8690b57cec5SDimitry Andric false, // isVolatile,
8700b57cec5SDimitry Andric (Size <= 32), // AlwaysInline if size <= 32,
871*0fca6ea1SDimitry Andric /*CI=*/nullptr, std::nullopt, MachinePointerInfo(),
872*0fca6ea1SDimitry Andric MachinePointerInfo());
8730b57cec5SDimitry Andric ByValArgs.push_back(FIPtr);
8740b57cec5SDimitry Andric }
8750b57cec5SDimitry Andric else {
8760b57cec5SDimitry Andric SDValue nullVal;
8770b57cec5SDimitry Andric ByValArgs.push_back(nullVal);
8780b57cec5SDimitry Andric }
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric
88181ad6265SDimitry Andric assert(!isTailCall || ArgsSize == 0);
88281ad6265SDimitry Andric
88381ad6265SDimitry Andric if (!isTailCall)
8840b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, dl);
8850b57cec5SDimitry Andric
8860b57cec5SDimitry Andric SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
8870b57cec5SDimitry Andric SmallVector<SDValue, 8> MemOpChains;
8880b57cec5SDimitry Andric
8890b57cec5SDimitry Andric const unsigned StackOffset = 92;
8900b57cec5SDimitry Andric bool hasStructRetAttr = false;
8910b57cec5SDimitry Andric unsigned SRetArgSize = 0;
8920b57cec5SDimitry Andric // Walk the register/memloc assignments, inserting copies/loads.
8930b57cec5SDimitry Andric for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size();
8940b57cec5SDimitry Andric i != e;
8950b57cec5SDimitry Andric ++i, ++realArgIdx) {
8960b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i];
8970b57cec5SDimitry Andric SDValue Arg = OutVals[realArgIdx];
8980b57cec5SDimitry Andric
8990b57cec5SDimitry Andric ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags;
9000b57cec5SDimitry Andric
9010b57cec5SDimitry Andric // Use local copy if it is a byval arg.
9020b57cec5SDimitry Andric if (Flags.isByVal()) {
9030b57cec5SDimitry Andric Arg = ByValArgs[byvalArgIdx++];
9040b57cec5SDimitry Andric if (!Arg) {
9050b57cec5SDimitry Andric continue;
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric
9090b57cec5SDimitry Andric // Promote the value if needed.
9100b57cec5SDimitry Andric switch (VA.getLocInfo()) {
9110b57cec5SDimitry Andric default: llvm_unreachable("Unknown loc info!");
9120b57cec5SDimitry Andric case CCValAssign::Full: break;
9130b57cec5SDimitry Andric case CCValAssign::SExt:
9140b57cec5SDimitry Andric Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
9150b57cec5SDimitry Andric break;
9160b57cec5SDimitry Andric case CCValAssign::ZExt:
9170b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
9180b57cec5SDimitry Andric break;
9190b57cec5SDimitry Andric case CCValAssign::AExt:
9200b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
9210b57cec5SDimitry Andric break;
9220b57cec5SDimitry Andric case CCValAssign::BCvt:
9230b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), Arg);
9240b57cec5SDimitry Andric break;
9250b57cec5SDimitry Andric }
9260b57cec5SDimitry Andric
9270b57cec5SDimitry Andric if (Flags.isSRet()) {
9280b57cec5SDimitry Andric assert(VA.needsCustom());
92981ad6265SDimitry Andric
93081ad6265SDimitry Andric if (isTailCall)
93181ad6265SDimitry Andric continue;
93281ad6265SDimitry Andric
9330b57cec5SDimitry Andric // store SRet argument in %sp+64
9340b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
9350b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(64, dl);
9360b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
9370b57cec5SDimitry Andric MemOpChains.push_back(
9380b57cec5SDimitry Andric DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
9390b57cec5SDimitry Andric hasStructRetAttr = true;
9400b57cec5SDimitry Andric // sret only allowed on first argument
9410b57cec5SDimitry Andric assert(Outs[realArgIdx].OrigArgIndex == 0);
94281ad6265SDimitry Andric SRetArgSize =
94381ad6265SDimitry Andric DAG.getDataLayout().getTypeAllocSize(CLI.getArgs()[0].IndirectType);
9440b57cec5SDimitry Andric continue;
9450b57cec5SDimitry Andric }
9460b57cec5SDimitry Andric
9470b57cec5SDimitry Andric if (VA.needsCustom()) {
9480b57cec5SDimitry Andric assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32);
9490b57cec5SDimitry Andric
9500b57cec5SDimitry Andric if (VA.isMemLoc()) {
9510b57cec5SDimitry Andric unsigned Offset = VA.getLocMemOffset() + StackOffset;
9520b57cec5SDimitry Andric // if it is double-word aligned, just store.
9530b57cec5SDimitry Andric if (Offset % 8 == 0) {
9540b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
9550b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);
9560b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
9570b57cec5SDimitry Andric MemOpChains.push_back(
9580b57cec5SDimitry Andric DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
9590b57cec5SDimitry Andric continue;
9600b57cec5SDimitry Andric }
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric
9630b57cec5SDimitry Andric if (VA.getLocVT() == MVT::f64) {
9640b57cec5SDimitry Andric // Move from the float value from float registers into the
9650b57cec5SDimitry Andric // integer registers.
9660b57cec5SDimitry Andric if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Arg))
9670b57cec5SDimitry Andric Arg = bitcastConstantFPToInt(C, dl, DAG);
9680b57cec5SDimitry Andric else
9690b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, Arg);
9700b57cec5SDimitry Andric }
9710b57cec5SDimitry Andric
9720b57cec5SDimitry Andric SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32,
9730b57cec5SDimitry Andric Arg,
9740b57cec5SDimitry Andric DAG.getConstant(0, dl, getVectorIdxTy(DAG.getDataLayout())));
9750b57cec5SDimitry Andric SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32,
9760b57cec5SDimitry Andric Arg,
9770b57cec5SDimitry Andric DAG.getConstant(1, dl, getVectorIdxTy(DAG.getDataLayout())));
9780b57cec5SDimitry Andric
9790b57cec5SDimitry Andric if (VA.isRegLoc()) {
9800b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), Part0));
9810b57cec5SDimitry Andric assert(i+1 != e);
9820b57cec5SDimitry Andric CCValAssign &NextVA = ArgLocs[++i];
9830b57cec5SDimitry Andric if (NextVA.isRegLoc()) {
9840b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Part1));
9850b57cec5SDimitry Andric } else {
9860b57cec5SDimitry Andric // Store the second part in stack.
9870b57cec5SDimitry Andric unsigned Offset = NextVA.getLocMemOffset() + StackOffset;
9880b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
9890b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);
9900b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
9910b57cec5SDimitry Andric MemOpChains.push_back(
9920b57cec5SDimitry Andric DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo()));
9930b57cec5SDimitry Andric }
9940b57cec5SDimitry Andric } else {
9950b57cec5SDimitry Andric unsigned Offset = VA.getLocMemOffset() + StackOffset;
9960b57cec5SDimitry Andric // Store the first part.
9970b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
9980b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);
9990b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
10000b57cec5SDimitry Andric MemOpChains.push_back(
10010b57cec5SDimitry Andric DAG.getStore(Chain, dl, Part0, PtrOff, MachinePointerInfo()));
10020b57cec5SDimitry Andric // Store the second part.
10030b57cec5SDimitry Andric PtrOff = DAG.getIntPtrConstant(Offset + 4, dl);
10040b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
10050b57cec5SDimitry Andric MemOpChains.push_back(
10060b57cec5SDimitry Andric DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo()));
10070b57cec5SDimitry Andric }
10080b57cec5SDimitry Andric continue;
10090b57cec5SDimitry Andric }
10100b57cec5SDimitry Andric
10110b57cec5SDimitry Andric // Arguments that can be passed on register must be kept at
10120b57cec5SDimitry Andric // RegsToPass vector
10130b57cec5SDimitry Andric if (VA.isRegLoc()) {
10140b57cec5SDimitry Andric if (VA.getLocVT() != MVT::f32) {
10150b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
10160b57cec5SDimitry Andric continue;
10170b57cec5SDimitry Andric }
10180b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg);
10190b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
10200b57cec5SDimitry Andric continue;
10210b57cec5SDimitry Andric }
10220b57cec5SDimitry Andric
10230b57cec5SDimitry Andric assert(VA.isMemLoc());
10240b57cec5SDimitry Andric
10250b57cec5SDimitry Andric // Create a store off the stack pointer for this argument.
10260b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
10270b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() + StackOffset,
10280b57cec5SDimitry Andric dl);
10290b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
10300b57cec5SDimitry Andric MemOpChains.push_back(
10310b57cec5SDimitry Andric DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
10320b57cec5SDimitry Andric }
10330b57cec5SDimitry Andric
10340b57cec5SDimitry Andric
10350b57cec5SDimitry Andric // Emit all stores, make sure the occur before any copies into physregs.
10360b57cec5SDimitry Andric if (!MemOpChains.empty())
10370b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
10380b57cec5SDimitry Andric
10390b57cec5SDimitry Andric // Build a sequence of copy-to-reg nodes chained together with token
10400b57cec5SDimitry Andric // chain and flag operands which copy the outgoing args into registers.
104106c3fb27SDimitry Andric // The InGlue in necessary since all emitted instructions must be
10420b57cec5SDimitry Andric // stuck together.
104306c3fb27SDimitry Andric SDValue InGlue;
10440b57cec5SDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
104581ad6265SDimitry Andric Register Reg = RegsToPass[i].first;
104681ad6265SDimitry Andric if (!isTailCall)
104781ad6265SDimitry Andric Reg = toCallerWindow(Reg);
104806c3fb27SDimitry Andric Chain = DAG.getCopyToReg(Chain, dl, Reg, RegsToPass[i].second, InGlue);
104906c3fb27SDimitry Andric InGlue = Chain.getValue(1);
10500b57cec5SDimitry Andric }
10510b57cec5SDimitry Andric
10525ffd83dbSDimitry Andric bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CB);
10530b57cec5SDimitry Andric
10540b57cec5SDimitry Andric // If the callee is a GlobalAddress node (quite common, every direct call is)
10550b57cec5SDimitry Andric // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
10560b57cec5SDimitry Andric // Likewise ExternalSymbol -> TargetExternalSymbol.
1057e8d8bef9SDimitry Andric unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30
1058e8d8bef9SDimitry Andric : SparcMCExpr::VK_Sparc_WDISP30;
10590b57cec5SDimitry Andric if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
10600b57cec5SDimitry Andric Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF);
10610b57cec5SDimitry Andric else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
10620b57cec5SDimitry Andric Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF);
10630b57cec5SDimitry Andric
10640b57cec5SDimitry Andric // Returns a chain & a flag for retval copy to use
10650b57cec5SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
10660b57cec5SDimitry Andric SmallVector<SDValue, 8> Ops;
10670b57cec5SDimitry Andric Ops.push_back(Chain);
10680b57cec5SDimitry Andric Ops.push_back(Callee);
10690b57cec5SDimitry Andric if (hasStructRetAttr)
10700b57cec5SDimitry Andric Ops.push_back(DAG.getTargetConstant(SRetArgSize, dl, MVT::i32));
107181ad6265SDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
107281ad6265SDimitry Andric Register Reg = RegsToPass[i].first;
107381ad6265SDimitry Andric if (!isTailCall)
107481ad6265SDimitry Andric Reg = toCallerWindow(Reg);
107581ad6265SDimitry Andric Ops.push_back(DAG.getRegister(Reg, RegsToPass[i].second.getValueType()));
107681ad6265SDimitry Andric }
10770b57cec5SDimitry Andric
10780b57cec5SDimitry Andric // Add a register mask operand representing the call-preserved registers.
10790b57cec5SDimitry Andric const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo();
10800b57cec5SDimitry Andric const uint32_t *Mask =
10810b57cec5SDimitry Andric ((hasReturnsTwice)
10820b57cec5SDimitry Andric ? TRI->getRTCallPreservedMask(CallConv)
10830b57cec5SDimitry Andric : TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv));
108474626c16SDimitry Andric
108574626c16SDimitry Andric if (isAnyArgRegReserved(TRI, MF))
108674626c16SDimitry Andric emitReservedArgRegCallError(MF);
108774626c16SDimitry Andric
10880b57cec5SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention");
10890b57cec5SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask));
10900b57cec5SDimitry Andric
109106c3fb27SDimitry Andric if (InGlue.getNode())
109206c3fb27SDimitry Andric Ops.push_back(InGlue);
10930b57cec5SDimitry Andric
109481ad6265SDimitry Andric if (isTailCall) {
109581ad6265SDimitry Andric DAG.getMachineFunction().getFrameInfo().setHasTailCall();
109681ad6265SDimitry Andric return DAG.getNode(SPISD::TAIL_CALL, dl, MVT::Other, Ops);
109781ad6265SDimitry Andric }
109881ad6265SDimitry Andric
10990b57cec5SDimitry Andric Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, Ops);
110006c3fb27SDimitry Andric InGlue = Chain.getValue(1);
11010b57cec5SDimitry Andric
110206c3fb27SDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InGlue, dl);
110306c3fb27SDimitry Andric InGlue = Chain.getValue(1);
11040b57cec5SDimitry Andric
11050b57cec5SDimitry Andric // Assign locations to each value returned by this call.
11060b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs;
11070b57cec5SDimitry Andric CCState RVInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
11080b57cec5SDimitry Andric *DAG.getContext());
11090b57cec5SDimitry Andric
11100b57cec5SDimitry Andric RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32);
11110b57cec5SDimitry Andric
11120b57cec5SDimitry Andric // Copy all of the result registers out of their specified physreg.
11130b57cec5SDimitry Andric for (unsigned i = 0; i != RVLocs.size(); ++i) {
1114f3fd488fSDimitry Andric assert(RVLocs[i].isRegLoc() && "Can only return in registers!");
11150b57cec5SDimitry Andric if (RVLocs[i].getLocVT() == MVT::v2i32) {
11160b57cec5SDimitry Andric SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2i32);
11170b57cec5SDimitry Andric SDValue Lo = DAG.getCopyFromReg(
111806c3fb27SDimitry Andric Chain, dl, toCallerWindow(RVLocs[i++].getLocReg()), MVT::i32, InGlue);
11190b57cec5SDimitry Andric Chain = Lo.getValue(1);
112006c3fb27SDimitry Andric InGlue = Lo.getValue(2);
11210b57cec5SDimitry Andric Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Lo,
11220b57cec5SDimitry Andric DAG.getConstant(0, dl, MVT::i32));
11230b57cec5SDimitry Andric SDValue Hi = DAG.getCopyFromReg(
112406c3fb27SDimitry Andric Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), MVT::i32, InGlue);
11250b57cec5SDimitry Andric Chain = Hi.getValue(1);
112606c3fb27SDimitry Andric InGlue = Hi.getValue(2);
11270b57cec5SDimitry Andric Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Hi,
11280b57cec5SDimitry Andric DAG.getConstant(1, dl, MVT::i32));
11290b57cec5SDimitry Andric InVals.push_back(Vec);
11300b57cec5SDimitry Andric } else {
11310b57cec5SDimitry Andric Chain =
11320b57cec5SDimitry Andric DAG.getCopyFromReg(Chain, dl, toCallerWindow(RVLocs[i].getLocReg()),
113306c3fb27SDimitry Andric RVLocs[i].getValVT(), InGlue)
11340b57cec5SDimitry Andric .getValue(1);
113506c3fb27SDimitry Andric InGlue = Chain.getValue(2);
11360b57cec5SDimitry Andric InVals.push_back(Chain.getValue(0));
11370b57cec5SDimitry Andric }
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric
11400b57cec5SDimitry Andric return Chain;
11410b57cec5SDimitry Andric }
11420b57cec5SDimitry Andric
11430b57cec5SDimitry Andric // FIXME? Maybe this could be a TableGen attribute on some registers and
11440b57cec5SDimitry Andric // this table could be generated automatically from RegInfo.
getRegisterByName(const char * RegName,LLT VT,const MachineFunction & MF) const1145480093f4SDimitry Andric Register SparcTargetLowering::getRegisterByName(const char* RegName, LLT VT,
11468bcb0991SDimitry Andric const MachineFunction &MF) const {
11475ffd83dbSDimitry Andric Register Reg = StringSwitch<Register>(RegName)
11480b57cec5SDimitry Andric .Case("i0", SP::I0).Case("i1", SP::I1).Case("i2", SP::I2).Case("i3", SP::I3)
11490b57cec5SDimitry Andric .Case("i4", SP::I4).Case("i5", SP::I5).Case("i6", SP::I6).Case("i7", SP::I7)
11500b57cec5SDimitry Andric .Case("o0", SP::O0).Case("o1", SP::O1).Case("o2", SP::O2).Case("o3", SP::O3)
11510b57cec5SDimitry Andric .Case("o4", SP::O4).Case("o5", SP::O5).Case("o6", SP::O6).Case("o7", SP::O7)
11520b57cec5SDimitry Andric .Case("l0", SP::L0).Case("l1", SP::L1).Case("l2", SP::L2).Case("l3", SP::L3)
11530b57cec5SDimitry Andric .Case("l4", SP::L4).Case("l5", SP::L5).Case("l6", SP::L6).Case("l7", SP::L7)
11540b57cec5SDimitry Andric .Case("g0", SP::G0).Case("g1", SP::G1).Case("g2", SP::G2).Case("g3", SP::G3)
11550b57cec5SDimitry Andric .Case("g4", SP::G4).Case("g5", SP::G5).Case("g6", SP::G6).Case("g7", SP::G7)
11560b57cec5SDimitry Andric .Default(0);
11570b57cec5SDimitry Andric
115874626c16SDimitry Andric // If we're directly referencing register names
115974626c16SDimitry Andric // (e.g in GCC C extension `register int r asm("g1");`),
116074626c16SDimitry Andric // make sure that said register is in the reserve list.
116174626c16SDimitry Andric const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo();
116274626c16SDimitry Andric if (!TRI->isReservedReg(MF, Reg))
116374626c16SDimitry Andric Reg = 0;
116474626c16SDimitry Andric
11650b57cec5SDimitry Andric if (Reg)
11660b57cec5SDimitry Andric return Reg;
11670b57cec5SDimitry Andric
11680b57cec5SDimitry Andric report_fatal_error("Invalid register name global variable");
11690b57cec5SDimitry Andric }
11700b57cec5SDimitry Andric
11710b57cec5SDimitry Andric // Fixup floating point arguments in the ... part of a varargs call.
11720b57cec5SDimitry Andric //
11730b57cec5SDimitry Andric // The SPARC v9 ABI requires that floating point arguments are treated the same
11740b57cec5SDimitry Andric // as integers when calling a varargs function. This does not apply to the
11750b57cec5SDimitry Andric // fixed arguments that are part of the function's prototype.
11760b57cec5SDimitry Andric //
11770b57cec5SDimitry Andric // This function post-processes a CCValAssign array created by
11780b57cec5SDimitry Andric // AnalyzeCallOperands().
fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> & ArgLocs,ArrayRef<ISD::OutputArg> Outs)11790b57cec5SDimitry Andric static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs,
11800b57cec5SDimitry Andric ArrayRef<ISD::OutputArg> Outs) {
1181*0fca6ea1SDimitry Andric for (CCValAssign &VA : ArgLocs) {
11820b57cec5SDimitry Andric MVT ValTy = VA.getLocVT();
11830b57cec5SDimitry Andric // FIXME: What about f32 arguments? C promotes them to f64 when calling
11840b57cec5SDimitry Andric // varargs functions.
11850b57cec5SDimitry Andric if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128))
11860b57cec5SDimitry Andric continue;
11870b57cec5SDimitry Andric // The fixed arguments to a varargs function still go in FP registers.
11880b57cec5SDimitry Andric if (Outs[VA.getValNo()].IsFixed)
11890b57cec5SDimitry Andric continue;
11900b57cec5SDimitry Andric
11910b57cec5SDimitry Andric // This floating point argument should be reassigned.
11920b57cec5SDimitry Andric // Determine the offset into the argument array.
11935ffd83dbSDimitry Andric Register firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0;
11940b57cec5SDimitry Andric unsigned argSize = (ValTy == MVT::f64) ? 8 : 16;
11950b57cec5SDimitry Andric unsigned Offset = argSize * (VA.getLocReg() - firstReg);
11960b57cec5SDimitry Andric assert(Offset < 16*8 && "Offset out of range, bad register enum?");
11970b57cec5SDimitry Andric
11980b57cec5SDimitry Andric if (Offset < 6*8) {
11990b57cec5SDimitry Andric // This argument should go in %i0-%i5.
12000b57cec5SDimitry Andric unsigned IReg = SP::I0 + Offset/8;
12010b57cec5SDimitry Andric if (ValTy == MVT::f64)
12020b57cec5SDimitry Andric // Full register, just bitconvert into i64.
1203bdd1243dSDimitry Andric VA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), IReg, MVT::i64,
1204bdd1243dSDimitry Andric CCValAssign::BCvt);
12050b57cec5SDimitry Andric else {
12060b57cec5SDimitry Andric assert(ValTy == MVT::f128 && "Unexpected type!");
12070b57cec5SDimitry Andric // Full register, just bitconvert into i128 -- We will lower this into
12080b57cec5SDimitry Andric // two i64s in LowerCall_64.
1209bdd1243dSDimitry Andric VA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), IReg,
1210bdd1243dSDimitry Andric MVT::i128, CCValAssign::BCvt);
12110b57cec5SDimitry Andric }
12120b57cec5SDimitry Andric } else {
12130b57cec5SDimitry Andric // This needs to go to memory, we're out of integer registers.
1214bdd1243dSDimitry Andric VA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), Offset,
1215bdd1243dSDimitry Andric VA.getLocVT(), VA.getLocInfo());
12160b57cec5SDimitry Andric }
12170b57cec5SDimitry Andric }
12180b57cec5SDimitry Andric }
12190b57cec5SDimitry Andric
12200b57cec5SDimitry Andric // Lower a call for the 64-bit ABI.
12210b57cec5SDimitry Andric SDValue
LowerCall_64(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const12220b57cec5SDimitry Andric SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
12230b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const {
12240b57cec5SDimitry Andric SelectionDAG &DAG = CLI.DAG;
12250b57cec5SDimitry Andric SDLoc DL = CLI.DL;
12260b57cec5SDimitry Andric SDValue Chain = CLI.Chain;
12270b57cec5SDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout());
122874626c16SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
12290b57cec5SDimitry Andric
12300b57cec5SDimitry Andric // Analyze operands of the call, assigning locations to each operand.
12310b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs;
12320b57cec5SDimitry Andric CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs,
12330b57cec5SDimitry Andric *DAG.getContext());
12340b57cec5SDimitry Andric CCInfo.AnalyzeCallOperands(CLI.Outs, CC_Sparc64);
12350b57cec5SDimitry Andric
1236bdd1243dSDimitry Andric CLI.IsTailCall = CLI.IsTailCall && IsEligibleForTailCallOptimization(
1237bdd1243dSDimitry Andric CCInfo, CLI, DAG.getMachineFunction());
1238bdd1243dSDimitry Andric
12390b57cec5SDimitry Andric // Get the size of the outgoing arguments stack space requirement.
12400b57cec5SDimitry Andric // The stack offset computed by CC_Sparc64 includes all arguments.
12410b57cec5SDimitry Andric // Called functions expect 6 argument words to exist in the stack frame, used
12420b57cec5SDimitry Andric // or not.
1243bdd1243dSDimitry Andric unsigned StackReserved = 6 * 8u;
124406c3fb27SDimitry Andric unsigned ArgsSize = std::max<unsigned>(StackReserved, CCInfo.getStackSize());
12450b57cec5SDimitry Andric
12460b57cec5SDimitry Andric // Keep stack frames 16-byte aligned.
12470b57cec5SDimitry Andric ArgsSize = alignTo(ArgsSize, 16);
12480b57cec5SDimitry Andric
12490b57cec5SDimitry Andric // Varargs calls require special treatment.
12500b57cec5SDimitry Andric if (CLI.IsVarArg)
12510b57cec5SDimitry Andric fixupVariableFloatArgs(ArgLocs, CLI.Outs);
12520b57cec5SDimitry Andric
1253bdd1243dSDimitry Andric assert(!CLI.IsTailCall || ArgsSize == StackReserved);
1254bdd1243dSDimitry Andric
12550b57cec5SDimitry Andric // Adjust the stack pointer to make room for the arguments.
12560b57cec5SDimitry Andric // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls
12570b57cec5SDimitry Andric // with more than 6 arguments.
1258bdd1243dSDimitry Andric if (!CLI.IsTailCall)
12590b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL);
12600b57cec5SDimitry Andric
12610b57cec5SDimitry Andric // Collect the set of registers to pass to the function and their values.
12620b57cec5SDimitry Andric // This will be emitted as a sequence of CopyToReg nodes glued to the call
12630b57cec5SDimitry Andric // instruction.
12645ffd83dbSDimitry Andric SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
12650b57cec5SDimitry Andric
12660b57cec5SDimitry Andric // Collect chains from all the memory opeations that copy arguments to the
12670b57cec5SDimitry Andric // stack. They must follow the stack pointer adjustment above and precede the
12680b57cec5SDimitry Andric // call instruction itself.
12690b57cec5SDimitry Andric SmallVector<SDValue, 8> MemOpChains;
12700b57cec5SDimitry Andric
12710b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
12720b57cec5SDimitry Andric const CCValAssign &VA = ArgLocs[i];
12730b57cec5SDimitry Andric SDValue Arg = CLI.OutVals[i];
12740b57cec5SDimitry Andric
12750b57cec5SDimitry Andric // Promote the value if needed.
12760b57cec5SDimitry Andric switch (VA.getLocInfo()) {
12770b57cec5SDimitry Andric default:
12780b57cec5SDimitry Andric llvm_unreachable("Unknown location info!");
12790b57cec5SDimitry Andric case CCValAssign::Full:
12800b57cec5SDimitry Andric break;
12810b57cec5SDimitry Andric case CCValAssign::SExt:
12820b57cec5SDimitry Andric Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
12830b57cec5SDimitry Andric break;
12840b57cec5SDimitry Andric case CCValAssign::ZExt:
12850b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
12860b57cec5SDimitry Andric break;
12870b57cec5SDimitry Andric case CCValAssign::AExt:
12880b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
12890b57cec5SDimitry Andric break;
12900b57cec5SDimitry Andric case CCValAssign::BCvt:
12910b57cec5SDimitry Andric // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But
12920b57cec5SDimitry Andric // SPARC does not support i128 natively. Lower it into two i64, see below.
12930b57cec5SDimitry Andric if (!VA.needsCustom() || VA.getValVT() != MVT::f128
12940b57cec5SDimitry Andric || VA.getLocVT() != MVT::i128)
12950b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
12960b57cec5SDimitry Andric break;
12970b57cec5SDimitry Andric }
12980b57cec5SDimitry Andric
12990b57cec5SDimitry Andric if (VA.isRegLoc()) {
13000b57cec5SDimitry Andric if (VA.needsCustom() && VA.getValVT() == MVT::f128
13010b57cec5SDimitry Andric && VA.getLocVT() == MVT::i128) {
13020b57cec5SDimitry Andric // Store and reload into the integer register reg and reg+1.
13030b57cec5SDimitry Andric unsigned Offset = 8 * (VA.getLocReg() - SP::I0);
13040b57cec5SDimitry Andric unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128;
13050b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, PtrVT);
13060b57cec5SDimitry Andric SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset, DL);
13070b57cec5SDimitry Andric HiPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, HiPtrOff);
13080b57cec5SDimitry Andric SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8, DL);
13090b57cec5SDimitry Andric LoPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, LoPtrOff);
13100b57cec5SDimitry Andric
13110b57cec5SDimitry Andric // Store to %sp+BIAS+128+Offset
13120b57cec5SDimitry Andric SDValue Store =
13130b57cec5SDimitry Andric DAG.getStore(Chain, DL, Arg, HiPtrOff, MachinePointerInfo());
13140b57cec5SDimitry Andric // Load into Reg and Reg+1
13150b57cec5SDimitry Andric SDValue Hi64 =
13160b57cec5SDimitry Andric DAG.getLoad(MVT::i64, DL, Store, HiPtrOff, MachinePointerInfo());
13170b57cec5SDimitry Andric SDValue Lo64 =
13180b57cec5SDimitry Andric DAG.getLoad(MVT::i64, DL, Store, LoPtrOff, MachinePointerInfo());
1319bdd1243dSDimitry Andric
1320bdd1243dSDimitry Andric Register HiReg = VA.getLocReg();
1321bdd1243dSDimitry Andric Register LoReg = VA.getLocReg() + 1;
1322bdd1243dSDimitry Andric if (!CLI.IsTailCall) {
1323bdd1243dSDimitry Andric HiReg = toCallerWindow(HiReg);
1324bdd1243dSDimitry Andric LoReg = toCallerWindow(LoReg);
1325bdd1243dSDimitry Andric }
1326bdd1243dSDimitry Andric
1327bdd1243dSDimitry Andric RegsToPass.push_back(std::make_pair(HiReg, Hi64));
1328bdd1243dSDimitry Andric RegsToPass.push_back(std::make_pair(LoReg, Lo64));
13290b57cec5SDimitry Andric continue;
13300b57cec5SDimitry Andric }
13310b57cec5SDimitry Andric
13320b57cec5SDimitry Andric // The custom bit on an i32 return value indicates that it should be
13330b57cec5SDimitry Andric // passed in the high bits of the register.
13340b57cec5SDimitry Andric if (VA.getValVT() == MVT::i32 && VA.needsCustom()) {
13350b57cec5SDimitry Andric Arg = DAG.getNode(ISD::SHL, DL, MVT::i64, Arg,
13360b57cec5SDimitry Andric DAG.getConstant(32, DL, MVT::i32));
13370b57cec5SDimitry Andric
13380b57cec5SDimitry Andric // The next value may go in the low bits of the same register.
13390b57cec5SDimitry Andric // Handle both at once.
13400b57cec5SDimitry Andric if (i+1 < ArgLocs.size() && ArgLocs[i+1].isRegLoc() &&
13410b57cec5SDimitry Andric ArgLocs[i+1].getLocReg() == VA.getLocReg()) {
13420b57cec5SDimitry Andric SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64,
13430b57cec5SDimitry Andric CLI.OutVals[i+1]);
13440b57cec5SDimitry Andric Arg = DAG.getNode(ISD::OR, DL, MVT::i64, Arg, NV);
13450b57cec5SDimitry Andric // Skip the next value, it's already done.
13460b57cec5SDimitry Andric ++i;
13470b57cec5SDimitry Andric }
13480b57cec5SDimitry Andric }
1349bdd1243dSDimitry Andric
1350bdd1243dSDimitry Andric Register Reg = VA.getLocReg();
1351bdd1243dSDimitry Andric if (!CLI.IsTailCall)
1352bdd1243dSDimitry Andric Reg = toCallerWindow(Reg);
1353bdd1243dSDimitry Andric RegsToPass.push_back(std::make_pair(Reg, Arg));
13540b57cec5SDimitry Andric continue;
13550b57cec5SDimitry Andric }
13560b57cec5SDimitry Andric
13570b57cec5SDimitry Andric assert(VA.isMemLoc());
13580b57cec5SDimitry Andric
13590b57cec5SDimitry Andric // Create a store off the stack pointer for this argument.
13600b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, PtrVT);
13610b57cec5SDimitry Andric // The argument area starts at %fp+BIAS+128 in the callee frame,
13620b57cec5SDimitry Andric // %sp+BIAS+128 in ours.
13630b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() +
13640b57cec5SDimitry Andric Subtarget->getStackPointerBias() +
13650b57cec5SDimitry Andric 128, DL);
13660b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff);
13670b57cec5SDimitry Andric MemOpChains.push_back(
13680b57cec5SDimitry Andric DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo()));
13690b57cec5SDimitry Andric }
13700b57cec5SDimitry Andric
13710b57cec5SDimitry Andric // Emit all stores, make sure they occur before the call.
13720b57cec5SDimitry Andric if (!MemOpChains.empty())
13730b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
13740b57cec5SDimitry Andric
13750b57cec5SDimitry Andric // Build a sequence of CopyToReg nodes glued together with token chain and
13760b57cec5SDimitry Andric // glue operands which copy the outgoing args into registers. The InGlue is
13770b57cec5SDimitry Andric // necessary since all emitted instructions must be stuck together in order
13780b57cec5SDimitry Andric // to pass the live physical registers.
13790b57cec5SDimitry Andric SDValue InGlue;
13800b57cec5SDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
13810b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL,
13820b57cec5SDimitry Andric RegsToPass[i].first, RegsToPass[i].second, InGlue);
13830b57cec5SDimitry Andric InGlue = Chain.getValue(1);
13840b57cec5SDimitry Andric }
13850b57cec5SDimitry Andric
13860b57cec5SDimitry Andric // If the callee is a GlobalAddress node (quite common, every direct call is)
13870b57cec5SDimitry Andric // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
13880b57cec5SDimitry Andric // Likewise ExternalSymbol -> TargetExternalSymbol.
13890b57cec5SDimitry Andric SDValue Callee = CLI.Callee;
13905ffd83dbSDimitry Andric bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CB);
1391e8d8bef9SDimitry Andric unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30
1392e8d8bef9SDimitry Andric : SparcMCExpr::VK_Sparc_WDISP30;
13930b57cec5SDimitry Andric if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
13940b57cec5SDimitry Andric Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, TF);
13950b57cec5SDimitry Andric else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
13960b57cec5SDimitry Andric Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, TF);
13970b57cec5SDimitry Andric
13980b57cec5SDimitry Andric // Build the operands for the call instruction itself.
13990b57cec5SDimitry Andric SmallVector<SDValue, 8> Ops;
14000b57cec5SDimitry Andric Ops.push_back(Chain);
14010b57cec5SDimitry Andric Ops.push_back(Callee);
14020b57cec5SDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
14030b57cec5SDimitry Andric Ops.push_back(DAG.getRegister(RegsToPass[i].first,
14040b57cec5SDimitry Andric RegsToPass[i].second.getValueType()));
14050b57cec5SDimitry Andric
14060b57cec5SDimitry Andric // Add a register mask operand representing the call-preserved registers.
14070b57cec5SDimitry Andric const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo();
14080b57cec5SDimitry Andric const uint32_t *Mask =
14090b57cec5SDimitry Andric ((hasReturnsTwice) ? TRI->getRTCallPreservedMask(CLI.CallConv)
14100b57cec5SDimitry Andric : TRI->getCallPreservedMask(DAG.getMachineFunction(),
14110b57cec5SDimitry Andric CLI.CallConv));
141274626c16SDimitry Andric
141374626c16SDimitry Andric if (isAnyArgRegReserved(TRI, MF))
141474626c16SDimitry Andric emitReservedArgRegCallError(MF);
141574626c16SDimitry Andric
14160b57cec5SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention");
14170b57cec5SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask));
14180b57cec5SDimitry Andric
14190b57cec5SDimitry Andric // Make sure the CopyToReg nodes are glued to the call instruction which
14200b57cec5SDimitry Andric // consumes the registers.
14210b57cec5SDimitry Andric if (InGlue.getNode())
14220b57cec5SDimitry Andric Ops.push_back(InGlue);
14230b57cec5SDimitry Andric
14240b57cec5SDimitry Andric // Now the call itself.
1425bdd1243dSDimitry Andric if (CLI.IsTailCall) {
1426bdd1243dSDimitry Andric DAG.getMachineFunction().getFrameInfo().setHasTailCall();
1427bdd1243dSDimitry Andric return DAG.getNode(SPISD::TAIL_CALL, DL, MVT::Other, Ops);
1428bdd1243dSDimitry Andric }
14290b57cec5SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
14300b57cec5SDimitry Andric Chain = DAG.getNode(SPISD::CALL, DL, NodeTys, Ops);
14310b57cec5SDimitry Andric InGlue = Chain.getValue(1);
14320b57cec5SDimitry Andric
14330b57cec5SDimitry Andric // Revert the stack pointer immediately after the call.
1434bdd1243dSDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InGlue, DL);
14350b57cec5SDimitry Andric InGlue = Chain.getValue(1);
14360b57cec5SDimitry Andric
14370b57cec5SDimitry Andric // Now extract the return values. This is more or less the same as
14380b57cec5SDimitry Andric // LowerFormalArguments_64.
14390b57cec5SDimitry Andric
14400b57cec5SDimitry Andric // Assign locations to each value returned by this call.
14410b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs;
14420b57cec5SDimitry Andric CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs,
14430b57cec5SDimitry Andric *DAG.getContext());
14440b57cec5SDimitry Andric
14450b57cec5SDimitry Andric // Set inreg flag manually for codegen generated library calls that
14460b57cec5SDimitry Andric // return float.
14475ffd83dbSDimitry Andric if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && !CLI.CB)
14480b57cec5SDimitry Andric CLI.Ins[0].Flags.setInReg();
14490b57cec5SDimitry Andric
14500b57cec5SDimitry Andric RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64);
14510b57cec5SDimitry Andric
14520b57cec5SDimitry Andric // Copy all of the result registers out of their specified physreg.
14530b57cec5SDimitry Andric for (unsigned i = 0; i != RVLocs.size(); ++i) {
14540b57cec5SDimitry Andric CCValAssign &VA = RVLocs[i];
1455f3fd488fSDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!");
14560b57cec5SDimitry Andric unsigned Reg = toCallerWindow(VA.getLocReg());
14570b57cec5SDimitry Andric
14580b57cec5SDimitry Andric // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can
14590b57cec5SDimitry Andric // reside in the same register in the high and low bits. Reuse the
14600b57cec5SDimitry Andric // CopyFromReg previous node to avoid duplicate copies.
14610b57cec5SDimitry Andric SDValue RV;
14620b57cec5SDimitry Andric if (RegisterSDNode *SrcReg = dyn_cast<RegisterSDNode>(Chain.getOperand(1)))
14630b57cec5SDimitry Andric if (SrcReg->getReg() == Reg && Chain->getOpcode() == ISD::CopyFromReg)
14640b57cec5SDimitry Andric RV = Chain.getValue(0);
14650b57cec5SDimitry Andric
14660b57cec5SDimitry Andric // But usually we'll create a new CopyFromReg for a different register.
14670b57cec5SDimitry Andric if (!RV.getNode()) {
14680b57cec5SDimitry Andric RV = DAG.getCopyFromReg(Chain, DL, Reg, RVLocs[i].getLocVT(), InGlue);
14690b57cec5SDimitry Andric Chain = RV.getValue(1);
14700b57cec5SDimitry Andric InGlue = Chain.getValue(2);
14710b57cec5SDimitry Andric }
14720b57cec5SDimitry Andric
14730b57cec5SDimitry Andric // Get the high bits for i32 struct elements.
14740b57cec5SDimitry Andric if (VA.getValVT() == MVT::i32 && VA.needsCustom())
14750b57cec5SDimitry Andric RV = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), RV,
14760b57cec5SDimitry Andric DAG.getConstant(32, DL, MVT::i32));
14770b57cec5SDimitry Andric
14780b57cec5SDimitry Andric // The callee promoted the return value, so insert an Assert?ext SDNode so
14790b57cec5SDimitry Andric // we won't promote the value again in this function.
14800b57cec5SDimitry Andric switch (VA.getLocInfo()) {
14810b57cec5SDimitry Andric case CCValAssign::SExt:
14820b57cec5SDimitry Andric RV = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), RV,
14830b57cec5SDimitry Andric DAG.getValueType(VA.getValVT()));
14840b57cec5SDimitry Andric break;
14850b57cec5SDimitry Andric case CCValAssign::ZExt:
14860b57cec5SDimitry Andric RV = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), RV,
14870b57cec5SDimitry Andric DAG.getValueType(VA.getValVT()));
14880b57cec5SDimitry Andric break;
14890b57cec5SDimitry Andric default:
14900b57cec5SDimitry Andric break;
14910b57cec5SDimitry Andric }
14920b57cec5SDimitry Andric
14930b57cec5SDimitry Andric // Truncate the register down to the return value type.
14940b57cec5SDimitry Andric if (VA.isExtInLoc())
14950b57cec5SDimitry Andric RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV);
14960b57cec5SDimitry Andric
14970b57cec5SDimitry Andric InVals.push_back(RV);
14980b57cec5SDimitry Andric }
14990b57cec5SDimitry Andric
15000b57cec5SDimitry Andric return Chain;
15010b57cec5SDimitry Andric }
15020b57cec5SDimitry Andric
15030b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
15040b57cec5SDimitry Andric // TargetLowering Implementation
15050b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
15060b57cec5SDimitry Andric
shouldExpandAtomicRMWInIR(AtomicRMWInst * AI) const15070b57cec5SDimitry Andric TargetLowering::AtomicExpansionKind SparcTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
15080b57cec5SDimitry Andric if (AI->getOperation() == AtomicRMWInst::Xchg &&
15090b57cec5SDimitry Andric AI->getType()->getPrimitiveSizeInBits() == 32)
15100b57cec5SDimitry Andric return AtomicExpansionKind::None; // Uses xchg instruction
15110b57cec5SDimitry Andric
15120b57cec5SDimitry Andric return AtomicExpansionKind::CmpXChg;
15130b57cec5SDimitry Andric }
15140b57cec5SDimitry Andric
1515bdd1243dSDimitry Andric /// intCondCCodeToRcond - Convert a DAG integer condition code to a SPARC
1516bdd1243dSDimitry Andric /// rcond condition.
intCondCCodeToRcond(ISD::CondCode CC)1517bdd1243dSDimitry Andric static SPCC::CondCodes intCondCCodeToRcond(ISD::CondCode CC) {
1518bdd1243dSDimitry Andric switch (CC) {
1519bdd1243dSDimitry Andric default:
1520bdd1243dSDimitry Andric llvm_unreachable("Unknown/unsigned integer condition code!");
1521bdd1243dSDimitry Andric case ISD::SETEQ:
1522bdd1243dSDimitry Andric return SPCC::REG_Z;
1523bdd1243dSDimitry Andric case ISD::SETNE:
1524bdd1243dSDimitry Andric return SPCC::REG_NZ;
1525bdd1243dSDimitry Andric case ISD::SETLT:
1526bdd1243dSDimitry Andric return SPCC::REG_LZ;
1527bdd1243dSDimitry Andric case ISD::SETGT:
1528bdd1243dSDimitry Andric return SPCC::REG_GZ;
1529bdd1243dSDimitry Andric case ISD::SETLE:
1530bdd1243dSDimitry Andric return SPCC::REG_LEZ;
1531bdd1243dSDimitry Andric case ISD::SETGE:
1532bdd1243dSDimitry Andric return SPCC::REG_GEZ;
1533bdd1243dSDimitry Andric }
1534bdd1243dSDimitry Andric }
1535bdd1243dSDimitry Andric
15360b57cec5SDimitry Andric /// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC
15370b57cec5SDimitry Andric /// condition.
IntCondCCodeToICC(ISD::CondCode CC)15380b57cec5SDimitry Andric static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) {
15390b57cec5SDimitry Andric switch (CC) {
15400b57cec5SDimitry Andric default: llvm_unreachable("Unknown integer condition code!");
15410b57cec5SDimitry Andric case ISD::SETEQ: return SPCC::ICC_E;
15420b57cec5SDimitry Andric case ISD::SETNE: return SPCC::ICC_NE;
15430b57cec5SDimitry Andric case ISD::SETLT: return SPCC::ICC_L;
15440b57cec5SDimitry Andric case ISD::SETGT: return SPCC::ICC_G;
15450b57cec5SDimitry Andric case ISD::SETLE: return SPCC::ICC_LE;
15460b57cec5SDimitry Andric case ISD::SETGE: return SPCC::ICC_GE;
15470b57cec5SDimitry Andric case ISD::SETULT: return SPCC::ICC_CS;
15480b57cec5SDimitry Andric case ISD::SETULE: return SPCC::ICC_LEU;
15490b57cec5SDimitry Andric case ISD::SETUGT: return SPCC::ICC_GU;
15500b57cec5SDimitry Andric case ISD::SETUGE: return SPCC::ICC_CC;
15510b57cec5SDimitry Andric }
15520b57cec5SDimitry Andric }
15530b57cec5SDimitry Andric
15540b57cec5SDimitry Andric /// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC
15550b57cec5SDimitry Andric /// FCC condition.
FPCondCCodeToFCC(ISD::CondCode CC)15560b57cec5SDimitry Andric static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) {
15570b57cec5SDimitry Andric switch (CC) {
15580b57cec5SDimitry Andric default: llvm_unreachable("Unknown fp condition code!");
15590b57cec5SDimitry Andric case ISD::SETEQ:
15600b57cec5SDimitry Andric case ISD::SETOEQ: return SPCC::FCC_E;
15610b57cec5SDimitry Andric case ISD::SETNE:
15620b57cec5SDimitry Andric case ISD::SETUNE: return SPCC::FCC_NE;
15630b57cec5SDimitry Andric case ISD::SETLT:
15640b57cec5SDimitry Andric case ISD::SETOLT: return SPCC::FCC_L;
15650b57cec5SDimitry Andric case ISD::SETGT:
15660b57cec5SDimitry Andric case ISD::SETOGT: return SPCC::FCC_G;
15670b57cec5SDimitry Andric case ISD::SETLE:
15680b57cec5SDimitry Andric case ISD::SETOLE: return SPCC::FCC_LE;
15690b57cec5SDimitry Andric case ISD::SETGE:
15700b57cec5SDimitry Andric case ISD::SETOGE: return SPCC::FCC_GE;
15710b57cec5SDimitry Andric case ISD::SETULT: return SPCC::FCC_UL;
15720b57cec5SDimitry Andric case ISD::SETULE: return SPCC::FCC_ULE;
15730b57cec5SDimitry Andric case ISD::SETUGT: return SPCC::FCC_UG;
15740b57cec5SDimitry Andric case ISD::SETUGE: return SPCC::FCC_UGE;
15750b57cec5SDimitry Andric case ISD::SETUO: return SPCC::FCC_U;
15760b57cec5SDimitry Andric case ISD::SETO: return SPCC::FCC_O;
15770b57cec5SDimitry Andric case ISD::SETONE: return SPCC::FCC_LG;
15780b57cec5SDimitry Andric case ISD::SETUEQ: return SPCC::FCC_UE;
15790b57cec5SDimitry Andric }
15800b57cec5SDimitry Andric }
15810b57cec5SDimitry Andric
SparcTargetLowering(const TargetMachine & TM,const SparcSubtarget & STI)15820b57cec5SDimitry Andric SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
15830b57cec5SDimitry Andric const SparcSubtarget &STI)
15840b57cec5SDimitry Andric : TargetLowering(TM), Subtarget(&STI) {
158581ad6265SDimitry Andric MVT PtrVT = MVT::getIntegerVT(TM.getPointerSizeInBits(0));
15860b57cec5SDimitry Andric
15870b57cec5SDimitry Andric // Instructions which use registers as conditionals examine all the
15880b57cec5SDimitry Andric // bits (as does the pseudo SELECT_CC expansion). I don't think it
15890b57cec5SDimitry Andric // matters much whether it's ZeroOrOneBooleanContent, or
15900b57cec5SDimitry Andric // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the
15910b57cec5SDimitry Andric // former.
15920b57cec5SDimitry Andric setBooleanContents(ZeroOrOneBooleanContent);
15930b57cec5SDimitry Andric setBooleanVectorContents(ZeroOrOneBooleanContent);
15940b57cec5SDimitry Andric
15950b57cec5SDimitry Andric // Set up the register classes.
15960b57cec5SDimitry Andric addRegisterClass(MVT::i32, &SP::IntRegsRegClass);
15970b57cec5SDimitry Andric if (!Subtarget->useSoftFloat()) {
15980b57cec5SDimitry Andric addRegisterClass(MVT::f32, &SP::FPRegsRegClass);
15990b57cec5SDimitry Andric addRegisterClass(MVT::f64, &SP::DFPRegsRegClass);
16000b57cec5SDimitry Andric addRegisterClass(MVT::f128, &SP::QFPRegsRegClass);
16010b57cec5SDimitry Andric }
16020b57cec5SDimitry Andric if (Subtarget->is64Bit()) {
16030b57cec5SDimitry Andric addRegisterClass(MVT::i64, &SP::I64RegsRegClass);
16040b57cec5SDimitry Andric } else {
16050b57cec5SDimitry Andric // On 32bit sparc, we define a double-register 32bit register
16060b57cec5SDimitry Andric // class, as well. This is modeled in LLVM as a 2-vector of i32.
16070b57cec5SDimitry Andric addRegisterClass(MVT::v2i32, &SP::IntPairRegClass);
16080b57cec5SDimitry Andric
16090b57cec5SDimitry Andric // ...but almost all operations must be expanded, so set that as
16100b57cec5SDimitry Andric // the default.
16110b57cec5SDimitry Andric for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
16120b57cec5SDimitry Andric setOperationAction(Op, MVT::v2i32, Expand);
16130b57cec5SDimitry Andric }
16140b57cec5SDimitry Andric // Truncating/extending stores/loads are also not supported.
16158bcb0991SDimitry Andric for (MVT VT : MVT::integer_fixedlen_vector_valuetypes()) {
16160b57cec5SDimitry Andric setLoadExtAction(ISD::SEXTLOAD, VT, MVT::v2i32, Expand);
16170b57cec5SDimitry Andric setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::v2i32, Expand);
16180b57cec5SDimitry Andric setLoadExtAction(ISD::EXTLOAD, VT, MVT::v2i32, Expand);
16190b57cec5SDimitry Andric
16200b57cec5SDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, VT, Expand);
16210b57cec5SDimitry Andric setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, VT, Expand);
16220b57cec5SDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, VT, Expand);
16230b57cec5SDimitry Andric
16240b57cec5SDimitry Andric setTruncStoreAction(VT, MVT::v2i32, Expand);
16250b57cec5SDimitry Andric setTruncStoreAction(MVT::v2i32, VT, Expand);
16260b57cec5SDimitry Andric }
16270b57cec5SDimitry Andric // However, load and store *are* legal.
16280b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::v2i32, Legal);
16290b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::v2i32, Legal);
16300b57cec5SDimitry Andric setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Legal);
16310b57cec5SDimitry Andric setOperationAction(ISD::BUILD_VECTOR, MVT::v2i32, Legal);
16320b57cec5SDimitry Andric
16330b57cec5SDimitry Andric // And we need to promote i64 loads/stores into vector load/store
16340b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::i64, Custom);
16350b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::i64, Custom);
16360b57cec5SDimitry Andric
16370b57cec5SDimitry Andric // Sadly, this doesn't work:
16380b57cec5SDimitry Andric // AddPromotedToType(ISD::LOAD, MVT::i64, MVT::v2i32);
16390b57cec5SDimitry Andric // AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32);
16400b57cec5SDimitry Andric }
16410b57cec5SDimitry Andric
16420b57cec5SDimitry Andric // Turn FP extload into load/fpextend
16430b57cec5SDimitry Andric for (MVT VT : MVT::fp_valuetypes()) {
16445ffd83dbSDimitry Andric setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand);
16450b57cec5SDimitry Andric setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
16460b57cec5SDimitry Andric setLoadExtAction(ISD::EXTLOAD, VT, MVT::f64, Expand);
16470b57cec5SDimitry Andric }
16480b57cec5SDimitry Andric
16490b57cec5SDimitry Andric // Sparc doesn't have i1 sign extending load
16500b57cec5SDimitry Andric for (MVT VT : MVT::integer_valuetypes())
16510b57cec5SDimitry Andric setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
16520b57cec5SDimitry Andric
16530b57cec5SDimitry Andric // Turn FP truncstore into trunc + store.
16545ffd83dbSDimitry Andric setTruncStoreAction(MVT::f32, MVT::f16, Expand);
16555ffd83dbSDimitry Andric setTruncStoreAction(MVT::f64, MVT::f16, Expand);
16560b57cec5SDimitry Andric setTruncStoreAction(MVT::f64, MVT::f32, Expand);
1657fe6060f1SDimitry Andric setTruncStoreAction(MVT::f128, MVT::f16, Expand);
16580b57cec5SDimitry Andric setTruncStoreAction(MVT::f128, MVT::f32, Expand);
16590b57cec5SDimitry Andric setTruncStoreAction(MVT::f128, MVT::f64, Expand);
16600b57cec5SDimitry Andric
16610b57cec5SDimitry Andric // Custom legalize GlobalAddress nodes into LO/HI parts.
16620b57cec5SDimitry Andric setOperationAction(ISD::GlobalAddress, PtrVT, Custom);
16630b57cec5SDimitry Andric setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom);
16640b57cec5SDimitry Andric setOperationAction(ISD::ConstantPool, PtrVT, Custom);
16650b57cec5SDimitry Andric setOperationAction(ISD::BlockAddress, PtrVT, Custom);
16660b57cec5SDimitry Andric
16670b57cec5SDimitry Andric // Sparc doesn't have sext_inreg, replace them with shl/sra
16680b57cec5SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
16690b57cec5SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand);
16700b57cec5SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
16710b57cec5SDimitry Andric
16720b57cec5SDimitry Andric // Sparc has no REM or DIVREM operations.
16730b57cec5SDimitry Andric setOperationAction(ISD::UREM, MVT::i32, Expand);
16740b57cec5SDimitry Andric setOperationAction(ISD::SREM, MVT::i32, Expand);
16750b57cec5SDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
16760b57cec5SDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
16770b57cec5SDimitry Andric
16780b57cec5SDimitry Andric // ... nor does SparcV9.
16790b57cec5SDimitry Andric if (Subtarget->is64Bit()) {
16800b57cec5SDimitry Andric setOperationAction(ISD::UREM, MVT::i64, Expand);
16810b57cec5SDimitry Andric setOperationAction(ISD::SREM, MVT::i64, Expand);
16820b57cec5SDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
16830b57cec5SDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i64, Expand);
16840b57cec5SDimitry Andric }
16850b57cec5SDimitry Andric
16860b57cec5SDimitry Andric // Custom expand fp<->sint
16870b57cec5SDimitry Andric setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
16880b57cec5SDimitry Andric setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
16890b57cec5SDimitry Andric setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
16900b57cec5SDimitry Andric setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
16910b57cec5SDimitry Andric
16920b57cec5SDimitry Andric // Custom Expand fp<->uint
16930b57cec5SDimitry Andric setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
16940b57cec5SDimitry Andric setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
16950b57cec5SDimitry Andric setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
16960b57cec5SDimitry Andric setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
16970b57cec5SDimitry Andric
16985ffd83dbSDimitry Andric // Lower f16 conversion operations into library calls
16995ffd83dbSDimitry Andric setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand);
17005ffd83dbSDimitry Andric setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand);
17015ffd83dbSDimitry Andric setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand);
17025ffd83dbSDimitry Andric setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand);
1703fe6060f1SDimitry Andric setOperationAction(ISD::FP16_TO_FP, MVT::f128, Expand);
1704fe6060f1SDimitry Andric setOperationAction(ISD::FP_TO_FP16, MVT::f128, Expand);
17055ffd83dbSDimitry Andric
17060b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, MVT::f32, Expand);
17070b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, MVT::i32, Expand);
17080b57cec5SDimitry Andric
17090b57cec5SDimitry Andric // Sparc has no select or setcc: expand to SELECT_CC.
17100b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::i32, Expand);
17110b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::f32, Expand);
17120b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::f64, Expand);
17130b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::f128, Expand);
17140b57cec5SDimitry Andric
17150b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::i32, Expand);
17160b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::f32, Expand);
17170b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::f64, Expand);
17180b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::f128, Expand);
17190b57cec5SDimitry Andric
17200b57cec5SDimitry Andric // Sparc doesn't have BRCOND either, it has BR_CC.
17210b57cec5SDimitry Andric setOperationAction(ISD::BRCOND, MVT::Other, Expand);
17220b57cec5SDimitry Andric setOperationAction(ISD::BRIND, MVT::Other, Expand);
17230b57cec5SDimitry Andric setOperationAction(ISD::BR_JT, MVT::Other, Expand);
17240b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i32, Custom);
17250b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::f32, Custom);
17260b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::f64, Custom);
17270b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::f128, Custom);
17280b57cec5SDimitry Andric
17290b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
17300b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
17310b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
17320b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::f128, Custom);
17330b57cec5SDimitry Andric
17340b57cec5SDimitry Andric setOperationAction(ISD::ADDC, MVT::i32, Custom);
17350b57cec5SDimitry Andric setOperationAction(ISD::ADDE, MVT::i32, Custom);
17360b57cec5SDimitry Andric setOperationAction(ISD::SUBC, MVT::i32, Custom);
17370b57cec5SDimitry Andric setOperationAction(ISD::SUBE, MVT::i32, Custom);
17380b57cec5SDimitry Andric
17390b57cec5SDimitry Andric if (Subtarget->is64Bit()) {
17400b57cec5SDimitry Andric setOperationAction(ISD::ADDC, MVT::i64, Custom);
17410b57cec5SDimitry Andric setOperationAction(ISD::ADDE, MVT::i64, Custom);
17420b57cec5SDimitry Andric setOperationAction(ISD::SUBC, MVT::i64, Custom);
17430b57cec5SDimitry Andric setOperationAction(ISD::SUBE, MVT::i64, Custom);
17440b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, MVT::f64, Expand);
17450b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, MVT::i64, Expand);
17460b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::i64, Expand);
17470b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::i64, Expand);
17480b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i64, Custom);
17490b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
17500b57cec5SDimitry Andric
17510b57cec5SDimitry Andric setOperationAction(ISD::CTPOP, MVT::i64,
17520b57cec5SDimitry Andric Subtarget->usePopc() ? Legal : Expand);
17530b57cec5SDimitry Andric setOperationAction(ISD::CTTZ , MVT::i64, Expand);
17540b57cec5SDimitry Andric setOperationAction(ISD::CTLZ , MVT::i64, Expand);
17550b57cec5SDimitry Andric setOperationAction(ISD::BSWAP, MVT::i64, Expand);
17560b57cec5SDimitry Andric setOperationAction(ISD::ROTL , MVT::i64, Expand);
17570b57cec5SDimitry Andric setOperationAction(ISD::ROTR , MVT::i64, Expand);
17580b57cec5SDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom);
17590b57cec5SDimitry Andric }
17600b57cec5SDimitry Andric
17610b57cec5SDimitry Andric // ATOMICs.
17620b57cec5SDimitry Andric // Atomics are supported on SparcV9. 32-bit atomics are also
17630b57cec5SDimitry Andric // supported by some Leon SparcV8 variants. Otherwise, atomics
17640b57cec5SDimitry Andric // are unsupported.
1765*0fca6ea1SDimitry Andric if (Subtarget->isV9()) {
1766*0fca6ea1SDimitry Andric // TODO: we _ought_ to be able to support 64-bit atomics on 32-bit sparcv9,
1767*0fca6ea1SDimitry Andric // but it hasn't been implemented in the backend yet.
1768*0fca6ea1SDimitry Andric if (Subtarget->is64Bit())
17690b57cec5SDimitry Andric setMaxAtomicSizeInBitsSupported(64);
1770*0fca6ea1SDimitry Andric else
1771*0fca6ea1SDimitry Andric setMaxAtomicSizeInBitsSupported(32);
1772*0fca6ea1SDimitry Andric } else if (Subtarget->hasLeonCasa())
17730b57cec5SDimitry Andric setMaxAtomicSizeInBitsSupported(32);
17740b57cec5SDimitry Andric else
17750b57cec5SDimitry Andric setMaxAtomicSizeInBitsSupported(0);
17760b57cec5SDimitry Andric
17770b57cec5SDimitry Andric setMinCmpXchgSizeInBits(32);
17780b57cec5SDimitry Andric
17790b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal);
17800b57cec5SDimitry Andric
17810b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal);
17820b57cec5SDimitry Andric
17830b57cec5SDimitry Andric // Custom Lower Atomic LOAD/STORE
17840b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom);
17850b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom);
17860b57cec5SDimitry Andric
17870b57cec5SDimitry Andric if (Subtarget->is64Bit()) {
17880b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal);
17890b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Legal);
17900b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom);
17910b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom);
17920b57cec5SDimitry Andric }
17930b57cec5SDimitry Andric
17940b57cec5SDimitry Andric if (!Subtarget->isV9()) {
17950b57cec5SDimitry Andric // SparcV8 does not have FNEGD and FABSD.
17960b57cec5SDimitry Andric setOperationAction(ISD::FNEG, MVT::f64, Custom);
17970b57cec5SDimitry Andric setOperationAction(ISD::FABS, MVT::f64, Custom);
17980b57cec5SDimitry Andric }
17990b57cec5SDimitry Andric
18000b57cec5SDimitry Andric setOperationAction(ISD::FSIN , MVT::f128, Expand);
18010b57cec5SDimitry Andric setOperationAction(ISD::FCOS , MVT::f128, Expand);
18020b57cec5SDimitry Andric setOperationAction(ISD::FSINCOS, MVT::f128, Expand);
18030b57cec5SDimitry Andric setOperationAction(ISD::FREM , MVT::f128, Expand);
18040b57cec5SDimitry Andric setOperationAction(ISD::FMA , MVT::f128, Expand);
18050b57cec5SDimitry Andric setOperationAction(ISD::FSIN , MVT::f64, Expand);
18060b57cec5SDimitry Andric setOperationAction(ISD::FCOS , MVT::f64, Expand);
18070b57cec5SDimitry Andric setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
18080b57cec5SDimitry Andric setOperationAction(ISD::FREM , MVT::f64, Expand);
18090b57cec5SDimitry Andric setOperationAction(ISD::FMA , MVT::f64, Expand);
18100b57cec5SDimitry Andric setOperationAction(ISD::FSIN , MVT::f32, Expand);
18110b57cec5SDimitry Andric setOperationAction(ISD::FCOS , MVT::f32, Expand);
18120b57cec5SDimitry Andric setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
18130b57cec5SDimitry Andric setOperationAction(ISD::FREM , MVT::f32, Expand);
18140b57cec5SDimitry Andric setOperationAction(ISD::FMA , MVT::f32, Expand);
18150b57cec5SDimitry Andric setOperationAction(ISD::CTTZ , MVT::i32, Expand);
18160b57cec5SDimitry Andric setOperationAction(ISD::CTLZ , MVT::i32, Expand);
18170b57cec5SDimitry Andric setOperationAction(ISD::ROTL , MVT::i32, Expand);
18180b57cec5SDimitry Andric setOperationAction(ISD::ROTR , MVT::i32, Expand);
18190b57cec5SDimitry Andric setOperationAction(ISD::BSWAP, MVT::i32, Expand);
18200b57cec5SDimitry Andric setOperationAction(ISD::FCOPYSIGN, MVT::f128, Expand);
18210b57cec5SDimitry Andric setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
18220b57cec5SDimitry Andric setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
18230b57cec5SDimitry Andric setOperationAction(ISD::FPOW , MVT::f128, Expand);
18240b57cec5SDimitry Andric setOperationAction(ISD::FPOW , MVT::f64, Expand);
18250b57cec5SDimitry Andric setOperationAction(ISD::FPOW , MVT::f32, Expand);
18260b57cec5SDimitry Andric
18270b57cec5SDimitry Andric setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
18280b57cec5SDimitry Andric setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
18290b57cec5SDimitry Andric setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
18300b57cec5SDimitry Andric
18310b57cec5SDimitry Andric // Expands to [SU]MUL_LOHI.
18320b57cec5SDimitry Andric setOperationAction(ISD::MULHU, MVT::i32, Expand);
18330b57cec5SDimitry Andric setOperationAction(ISD::MULHS, MVT::i32, Expand);
18340b57cec5SDimitry Andric setOperationAction(ISD::MUL, MVT::i32, Expand);
18350b57cec5SDimitry Andric
18360b57cec5SDimitry Andric if (Subtarget->useSoftMulDiv()) {
18370b57cec5SDimitry Andric // .umul works for both signed and unsigned
18380b57cec5SDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
18390b57cec5SDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
18400b57cec5SDimitry Andric setLibcallName(RTLIB::MUL_I32, ".umul");
18410b57cec5SDimitry Andric
18420b57cec5SDimitry Andric setOperationAction(ISD::SDIV, MVT::i32, Expand);
18430b57cec5SDimitry Andric setLibcallName(RTLIB::SDIV_I32, ".div");
18440b57cec5SDimitry Andric
18450b57cec5SDimitry Andric setOperationAction(ISD::UDIV, MVT::i32, Expand);
18460b57cec5SDimitry Andric setLibcallName(RTLIB::UDIV_I32, ".udiv");
18470b57cec5SDimitry Andric
18480b57cec5SDimitry Andric setLibcallName(RTLIB::SREM_I32, ".rem");
18490b57cec5SDimitry Andric setLibcallName(RTLIB::UREM_I32, ".urem");
18500b57cec5SDimitry Andric }
18510b57cec5SDimitry Andric
18520b57cec5SDimitry Andric if (Subtarget->is64Bit()) {
18530b57cec5SDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
18540b57cec5SDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
18550b57cec5SDimitry Andric setOperationAction(ISD::MULHU, MVT::i64, Expand);
18560b57cec5SDimitry Andric setOperationAction(ISD::MULHS, MVT::i64, Expand);
18570b57cec5SDimitry Andric
18580b57cec5SDimitry Andric setOperationAction(ISD::UMULO, MVT::i64, Custom);
18590b57cec5SDimitry Andric setOperationAction(ISD::SMULO, MVT::i64, Custom);
18600b57cec5SDimitry Andric
18610b57cec5SDimitry Andric setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand);
18620b57cec5SDimitry Andric setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand);
18630b57cec5SDimitry Andric setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand);
18640b57cec5SDimitry Andric }
18650b57cec5SDimitry Andric
18660b57cec5SDimitry Andric // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
18670b57cec5SDimitry Andric setOperationAction(ISD::VASTART , MVT::Other, Custom);
18680b57cec5SDimitry Andric // VAARG needs to be lowered to not do unaligned accesses for doubles.
18690b57cec5SDimitry Andric setOperationAction(ISD::VAARG , MVT::Other, Custom);
18700b57cec5SDimitry Andric
18710b57cec5SDimitry Andric setOperationAction(ISD::TRAP , MVT::Other, Legal);
18720b57cec5SDimitry Andric setOperationAction(ISD::DEBUGTRAP , MVT::Other, Legal);
18730b57cec5SDimitry Andric
18740b57cec5SDimitry Andric // Use the default implementation.
18750b57cec5SDimitry Andric setOperationAction(ISD::VACOPY , MVT::Other, Expand);
18760b57cec5SDimitry Andric setOperationAction(ISD::VAEND , MVT::Other, Expand);
18770b57cec5SDimitry Andric setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
18780b57cec5SDimitry Andric setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
18790b57cec5SDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom);
18800b57cec5SDimitry Andric
18810b57cec5SDimitry Andric setStackPointerRegisterToSaveRestore(SP::O6);
18820b57cec5SDimitry Andric
18830b57cec5SDimitry Andric setOperationAction(ISD::CTPOP, MVT::i32,
18840b57cec5SDimitry Andric Subtarget->usePopc() ? Legal : Expand);
18850b57cec5SDimitry Andric
18860b57cec5SDimitry Andric if (Subtarget->isV9() && Subtarget->hasHardQuad()) {
18870b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::f128, Legal);
18880b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::f128, Legal);
18890b57cec5SDimitry Andric } else {
18900b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::f128, Custom);
18910b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::f128, Custom);
18920b57cec5SDimitry Andric }
18930b57cec5SDimitry Andric
18940b57cec5SDimitry Andric if (Subtarget->hasHardQuad()) {
18950b57cec5SDimitry Andric setOperationAction(ISD::FADD, MVT::f128, Legal);
18960b57cec5SDimitry Andric setOperationAction(ISD::FSUB, MVT::f128, Legal);
18970b57cec5SDimitry Andric setOperationAction(ISD::FMUL, MVT::f128, Legal);
18980b57cec5SDimitry Andric setOperationAction(ISD::FDIV, MVT::f128, Legal);
18990b57cec5SDimitry Andric setOperationAction(ISD::FSQRT, MVT::f128, Legal);
19000b57cec5SDimitry Andric setOperationAction(ISD::FP_EXTEND, MVT::f128, Legal);
19010b57cec5SDimitry Andric setOperationAction(ISD::FP_ROUND, MVT::f64, Legal);
19020b57cec5SDimitry Andric if (Subtarget->isV9()) {
19030b57cec5SDimitry Andric setOperationAction(ISD::FNEG, MVT::f128, Legal);
19040b57cec5SDimitry Andric setOperationAction(ISD::FABS, MVT::f128, Legal);
19050b57cec5SDimitry Andric } else {
19060b57cec5SDimitry Andric setOperationAction(ISD::FNEG, MVT::f128, Custom);
19070b57cec5SDimitry Andric setOperationAction(ISD::FABS, MVT::f128, Custom);
19080b57cec5SDimitry Andric }
19090b57cec5SDimitry Andric
19100b57cec5SDimitry Andric if (!Subtarget->is64Bit()) {
19110b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll");
19120b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull");
19130b57cec5SDimitry Andric setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq");
19140b57cec5SDimitry Andric setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq");
19150b57cec5SDimitry Andric }
19160b57cec5SDimitry Andric
19170b57cec5SDimitry Andric } else {
19180b57cec5SDimitry Andric // Custom legalize f128 operations.
19190b57cec5SDimitry Andric
19200b57cec5SDimitry Andric setOperationAction(ISD::FADD, MVT::f128, Custom);
19210b57cec5SDimitry Andric setOperationAction(ISD::FSUB, MVT::f128, Custom);
19220b57cec5SDimitry Andric setOperationAction(ISD::FMUL, MVT::f128, Custom);
19230b57cec5SDimitry Andric setOperationAction(ISD::FDIV, MVT::f128, Custom);
19240b57cec5SDimitry Andric setOperationAction(ISD::FSQRT, MVT::f128, Custom);
19250b57cec5SDimitry Andric setOperationAction(ISD::FNEG, MVT::f128, Custom);
19260b57cec5SDimitry Andric setOperationAction(ISD::FABS, MVT::f128, Custom);
19270b57cec5SDimitry Andric
19280b57cec5SDimitry Andric setOperationAction(ISD::FP_EXTEND, MVT::f128, Custom);
19290b57cec5SDimitry Andric setOperationAction(ISD::FP_ROUND, MVT::f64, Custom);
19300b57cec5SDimitry Andric setOperationAction(ISD::FP_ROUND, MVT::f32, Custom);
19310b57cec5SDimitry Andric
19320b57cec5SDimitry Andric // Setup Runtime library names.
19330b57cec5SDimitry Andric if (Subtarget->is64Bit() && !Subtarget->useSoftFloat()) {
19340b57cec5SDimitry Andric setLibcallName(RTLIB::ADD_F128, "_Qp_add");
19350b57cec5SDimitry Andric setLibcallName(RTLIB::SUB_F128, "_Qp_sub");
19360b57cec5SDimitry Andric setLibcallName(RTLIB::MUL_F128, "_Qp_mul");
19370b57cec5SDimitry Andric setLibcallName(RTLIB::DIV_F128, "_Qp_div");
19380b57cec5SDimitry Andric setLibcallName(RTLIB::SQRT_F128, "_Qp_sqrt");
19390b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Qp_qtoi");
19400b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Qp_qtoui");
19410b57cec5SDimitry Andric setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Qp_itoq");
19420b57cec5SDimitry Andric setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Qp_uitoq");
19430b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Qp_qtox");
19440b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Qp_qtoux");
19450b57cec5SDimitry Andric setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Qp_xtoq");
19460b57cec5SDimitry Andric setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Qp_uxtoq");
19470b57cec5SDimitry Andric setLibcallName(RTLIB::FPEXT_F32_F128, "_Qp_stoq");
19480b57cec5SDimitry Andric setLibcallName(RTLIB::FPEXT_F64_F128, "_Qp_dtoq");
19490b57cec5SDimitry Andric setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos");
19500b57cec5SDimitry Andric setLibcallName(RTLIB::FPROUND_F128_F64, "_Qp_qtod");
19510b57cec5SDimitry Andric } else if (!Subtarget->useSoftFloat()) {
19520b57cec5SDimitry Andric setLibcallName(RTLIB::ADD_F128, "_Q_add");
19530b57cec5SDimitry Andric setLibcallName(RTLIB::SUB_F128, "_Q_sub");
19540b57cec5SDimitry Andric setLibcallName(RTLIB::MUL_F128, "_Q_mul");
19550b57cec5SDimitry Andric setLibcallName(RTLIB::DIV_F128, "_Q_div");
19560b57cec5SDimitry Andric setLibcallName(RTLIB::SQRT_F128, "_Q_sqrt");
19570b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Q_qtoi");
19580b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Q_qtou");
19590b57cec5SDimitry Andric setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Q_itoq");
19600b57cec5SDimitry Andric setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Q_utoq");
19610b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll");
19620b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull");
19630b57cec5SDimitry Andric setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq");
19640b57cec5SDimitry Andric setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq");
19650b57cec5SDimitry Andric setLibcallName(RTLIB::FPEXT_F32_F128, "_Q_stoq");
19660b57cec5SDimitry Andric setLibcallName(RTLIB::FPEXT_F64_F128, "_Q_dtoq");
19670b57cec5SDimitry Andric setLibcallName(RTLIB::FPROUND_F128_F32, "_Q_qtos");
19680b57cec5SDimitry Andric setLibcallName(RTLIB::FPROUND_F128_F64, "_Q_qtod");
19690b57cec5SDimitry Andric }
19700b57cec5SDimitry Andric }
19710b57cec5SDimitry Andric
19720b57cec5SDimitry Andric if (Subtarget->fixAllFDIVSQRT()) {
19730b57cec5SDimitry Andric // Promote FDIVS and FSQRTS to FDIVD and FSQRTD instructions instead as
19740b57cec5SDimitry Andric // the former instructions generate errata on LEON processors.
19750b57cec5SDimitry Andric setOperationAction(ISD::FDIV, MVT::f32, Promote);
19760b57cec5SDimitry Andric setOperationAction(ISD::FSQRT, MVT::f32, Promote);
19770b57cec5SDimitry Andric }
19780b57cec5SDimitry Andric
19790b57cec5SDimitry Andric if (Subtarget->hasNoFMULS()) {
19800b57cec5SDimitry Andric setOperationAction(ISD::FMUL, MVT::f32, Promote);
19810b57cec5SDimitry Andric }
19820b57cec5SDimitry Andric
19830b57cec5SDimitry Andric // Custom combine bitcast between f64 and v2i32
19840b57cec5SDimitry Andric if (!Subtarget->is64Bit())
19850b57cec5SDimitry Andric setTargetDAGCombine(ISD::BITCAST);
19860b57cec5SDimitry Andric
19870b57cec5SDimitry Andric if (Subtarget->hasLeonCycleCounter())
19880b57cec5SDimitry Andric setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
19890b57cec5SDimitry Andric
19900b57cec5SDimitry Andric setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
19910b57cec5SDimitry Andric
19928bcb0991SDimitry Andric setMinFunctionAlignment(Align(4));
19930b57cec5SDimitry Andric
19940b57cec5SDimitry Andric computeRegisterProperties(Subtarget->getRegisterInfo());
19950b57cec5SDimitry Andric }
19960b57cec5SDimitry Andric
useSoftFloat() const19970b57cec5SDimitry Andric bool SparcTargetLowering::useSoftFloat() const {
19980b57cec5SDimitry Andric return Subtarget->useSoftFloat();
19990b57cec5SDimitry Andric }
20000b57cec5SDimitry Andric
getTargetNodeName(unsigned Opcode) const20010b57cec5SDimitry Andric const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
20020b57cec5SDimitry Andric switch ((SPISD::NodeType)Opcode) {
20030b57cec5SDimitry Andric case SPISD::FIRST_NUMBER: break;
20040b57cec5SDimitry Andric case SPISD::CMPICC: return "SPISD::CMPICC";
20050b57cec5SDimitry Andric case SPISD::CMPFCC: return "SPISD::CMPFCC";
2006bdd1243dSDimitry Andric case SPISD::CMPFCC_V9:
2007bdd1243dSDimitry Andric return "SPISD::CMPFCC_V9";
20080b57cec5SDimitry Andric case SPISD::BRICC: return "SPISD::BRICC";
2009bdd1243dSDimitry Andric case SPISD::BPICC:
2010bdd1243dSDimitry Andric return "SPISD::BPICC";
2011bdd1243dSDimitry Andric case SPISD::BPXCC:
2012bdd1243dSDimitry Andric return "SPISD::BPXCC";
20130b57cec5SDimitry Andric case SPISD::BRFCC: return "SPISD::BRFCC";
2014bdd1243dSDimitry Andric case SPISD::BRFCC_V9:
2015bdd1243dSDimitry Andric return "SPISD::BRFCC_V9";
201606c3fb27SDimitry Andric case SPISD::BR_REG:
201706c3fb27SDimitry Andric return "SPISD::BR_REG";
20180b57cec5SDimitry Andric case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC";
20190b57cec5SDimitry Andric case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC";
20200b57cec5SDimitry Andric case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC";
2021bdd1243dSDimitry Andric case SPISD::SELECT_REG:
2022bdd1243dSDimitry Andric return "SPISD::SELECT_REG";
20230b57cec5SDimitry Andric case SPISD::Hi: return "SPISD::Hi";
20240b57cec5SDimitry Andric case SPISD::Lo: return "SPISD::Lo";
20250b57cec5SDimitry Andric case SPISD::FTOI: return "SPISD::FTOI";
20260b57cec5SDimitry Andric case SPISD::ITOF: return "SPISD::ITOF";
20270b57cec5SDimitry Andric case SPISD::FTOX: return "SPISD::FTOX";
20280b57cec5SDimitry Andric case SPISD::XTOF: return "SPISD::XTOF";
20290b57cec5SDimitry Andric case SPISD::CALL: return "SPISD::CALL";
203006c3fb27SDimitry Andric case SPISD::RET_GLUE: return "SPISD::RET_GLUE";
20310b57cec5SDimitry Andric case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG";
20320b57cec5SDimitry Andric case SPISD::FLUSHW: return "SPISD::FLUSHW";
20330b57cec5SDimitry Andric case SPISD::TLS_ADD: return "SPISD::TLS_ADD";
20340b57cec5SDimitry Andric case SPISD::TLS_LD: return "SPISD::TLS_LD";
20350b57cec5SDimitry Andric case SPISD::TLS_CALL: return "SPISD::TLS_CALL";
203681ad6265SDimitry Andric case SPISD::TAIL_CALL: return "SPISD::TAIL_CALL";
203781ad6265SDimitry Andric case SPISD::LOAD_GDOP: return "SPISD::LOAD_GDOP";
20380b57cec5SDimitry Andric }
20390b57cec5SDimitry Andric return nullptr;
20400b57cec5SDimitry Andric }
20410b57cec5SDimitry Andric
getSetCCResultType(const DataLayout &,LLVMContext &,EVT VT) const20420b57cec5SDimitry Andric EVT SparcTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &,
20430b57cec5SDimitry Andric EVT VT) const {
20440b57cec5SDimitry Andric if (!VT.isVector())
20450b57cec5SDimitry Andric return MVT::i32;
20460b57cec5SDimitry Andric return VT.changeVectorElementTypeToInteger();
20470b57cec5SDimitry Andric }
20480b57cec5SDimitry Andric
20490b57cec5SDimitry Andric /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to
20500b57cec5SDimitry Andric /// be zero. Op is expected to be a target specific node. Used by DAG
20510b57cec5SDimitry Andric /// combiner.
computeKnownBitsForTargetNode(const SDValue Op,KnownBits & Known,const APInt & DemandedElts,const SelectionDAG & DAG,unsigned Depth) const20520b57cec5SDimitry Andric void SparcTargetLowering::computeKnownBitsForTargetNode
20530b57cec5SDimitry Andric (const SDValue Op,
20540b57cec5SDimitry Andric KnownBits &Known,
20550b57cec5SDimitry Andric const APInt &DemandedElts,
20560b57cec5SDimitry Andric const SelectionDAG &DAG,
20570b57cec5SDimitry Andric unsigned Depth) const {
20580b57cec5SDimitry Andric KnownBits Known2;
20590b57cec5SDimitry Andric Known.resetAll();
20600b57cec5SDimitry Andric
20610b57cec5SDimitry Andric switch (Op.getOpcode()) {
20620b57cec5SDimitry Andric default: break;
20630b57cec5SDimitry Andric case SPISD::SELECT_ICC:
20640b57cec5SDimitry Andric case SPISD::SELECT_XCC:
20650b57cec5SDimitry Andric case SPISD::SELECT_FCC:
20660b57cec5SDimitry Andric Known = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
20670b57cec5SDimitry Andric Known2 = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
20680b57cec5SDimitry Andric
20690b57cec5SDimitry Andric // Only known if known in both the LHS and RHS.
207006c3fb27SDimitry Andric Known = Known.intersectWith(Known2);
20710b57cec5SDimitry Andric break;
20720b57cec5SDimitry Andric }
20730b57cec5SDimitry Andric }
20740b57cec5SDimitry Andric
20750b57cec5SDimitry Andric // Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so
20760b57cec5SDimitry Andric // 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)20770b57cec5SDimitry Andric static void LookThroughSetCC(SDValue &LHS, SDValue &RHS,
20780b57cec5SDimitry Andric ISD::CondCode CC, unsigned &SPCC) {
2079bdd1243dSDimitry Andric if (isNullConstant(RHS) && CC == ISD::SETNE &&
20800b57cec5SDimitry Andric (((LHS.getOpcode() == SPISD::SELECT_ICC ||
20810b57cec5SDimitry Andric LHS.getOpcode() == SPISD::SELECT_XCC) &&
20820b57cec5SDimitry Andric LHS.getOperand(3).getOpcode() == SPISD::CMPICC) ||
20830b57cec5SDimitry Andric (LHS.getOpcode() == SPISD::SELECT_FCC &&
2084bdd1243dSDimitry Andric (LHS.getOperand(3).getOpcode() == SPISD::CMPFCC ||
2085bdd1243dSDimitry Andric LHS.getOperand(3).getOpcode() == SPISD::CMPFCC_V9))) &&
2086bdd1243dSDimitry Andric isOneConstant(LHS.getOperand(0)) && isNullConstant(LHS.getOperand(1))) {
20870b57cec5SDimitry Andric SDValue CMPCC = LHS.getOperand(3);
2088647cbc5dSDimitry Andric SPCC = LHS.getConstantOperandVal(2);
20890b57cec5SDimitry Andric LHS = CMPCC.getOperand(0);
20900b57cec5SDimitry Andric RHS = CMPCC.getOperand(1);
20910b57cec5SDimitry Andric }
20920b57cec5SDimitry Andric }
20930b57cec5SDimitry Andric
20940b57cec5SDimitry Andric // Convert to a target node and set target flags.
withTargetFlags(SDValue Op,unsigned TF,SelectionDAG & DAG) const20950b57cec5SDimitry Andric SDValue SparcTargetLowering::withTargetFlags(SDValue Op, unsigned TF,
20960b57cec5SDimitry Andric SelectionDAG &DAG) const {
20970b57cec5SDimitry Andric if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op))
20980b57cec5SDimitry Andric return DAG.getTargetGlobalAddress(GA->getGlobal(),
20990b57cec5SDimitry Andric SDLoc(GA),
21000b57cec5SDimitry Andric GA->getValueType(0),
21010b57cec5SDimitry Andric GA->getOffset(), TF);
21020b57cec5SDimitry Andric
21030b57cec5SDimitry Andric if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op))
21045ffd83dbSDimitry Andric return DAG.getTargetConstantPool(CP->getConstVal(), CP->getValueType(0),
21055ffd83dbSDimitry Andric CP->getAlign(), CP->getOffset(), TF);
21060b57cec5SDimitry Andric
21070b57cec5SDimitry Andric if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op))
21080b57cec5SDimitry Andric return DAG.getTargetBlockAddress(BA->getBlockAddress(),
21090b57cec5SDimitry Andric Op.getValueType(),
21100b57cec5SDimitry Andric 0,
21110b57cec5SDimitry Andric TF);
21120b57cec5SDimitry Andric
21130b57cec5SDimitry Andric if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op))
21140b57cec5SDimitry Andric return DAG.getTargetExternalSymbol(ES->getSymbol(),
21150b57cec5SDimitry Andric ES->getValueType(0), TF);
21160b57cec5SDimitry Andric
21170b57cec5SDimitry Andric llvm_unreachable("Unhandled address SDNode");
21180b57cec5SDimitry Andric }
21190b57cec5SDimitry Andric
21200b57cec5SDimitry Andric // Split Op into high and low parts according to HiTF and LoTF.
21210b57cec5SDimitry Andric // Return an ADD node combining the parts.
makeHiLoPair(SDValue Op,unsigned HiTF,unsigned LoTF,SelectionDAG & DAG) const21220b57cec5SDimitry Andric SDValue SparcTargetLowering::makeHiLoPair(SDValue Op,
21230b57cec5SDimitry Andric unsigned HiTF, unsigned LoTF,
21240b57cec5SDimitry Andric SelectionDAG &DAG) const {
21250b57cec5SDimitry Andric SDLoc DL(Op);
21260b57cec5SDimitry Andric EVT VT = Op.getValueType();
21270b57cec5SDimitry Andric SDValue Hi = DAG.getNode(SPISD::Hi, DL, VT, withTargetFlags(Op, HiTF, DAG));
21280b57cec5SDimitry Andric SDValue Lo = DAG.getNode(SPISD::Lo, DL, VT, withTargetFlags(Op, LoTF, DAG));
21290b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo);
21300b57cec5SDimitry Andric }
21310b57cec5SDimitry Andric
21320b57cec5SDimitry Andric // Build SDNodes for producing an address from a GlobalAddress, ConstantPool,
21330b57cec5SDimitry Andric // or ExternalSymbol SDNode.
makeAddress(SDValue Op,SelectionDAG & DAG) const21340b57cec5SDimitry Andric SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const {
21350b57cec5SDimitry Andric SDLoc DL(Op);
21360b57cec5SDimitry Andric EVT VT = getPointerTy(DAG.getDataLayout());
21370b57cec5SDimitry Andric
21380b57cec5SDimitry Andric // Handle PIC mode first. SPARC needs a got load for every variable!
21390b57cec5SDimitry Andric if (isPositionIndependent()) {
21400b57cec5SDimitry Andric const Module *M = DAG.getMachineFunction().getFunction().getParent();
21410b57cec5SDimitry Andric PICLevel::Level picLevel = M->getPICLevel();
21420b57cec5SDimitry Andric SDValue Idx;
21430b57cec5SDimitry Andric
21440b57cec5SDimitry Andric if (picLevel == PICLevel::SmallPIC) {
21450b57cec5SDimitry Andric // This is the pic13 code model, the GOT is known to be smaller than 8KiB.
21460b57cec5SDimitry Andric Idx = DAG.getNode(SPISD::Lo, DL, Op.getValueType(),
21470b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_GOT13, DAG));
21480b57cec5SDimitry Andric } else {
21490b57cec5SDimitry Andric // This is the pic32 code model, the GOT is known to be smaller than 4GB.
21500b57cec5SDimitry Andric Idx = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
21510b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_GOT10, DAG);
21520b57cec5SDimitry Andric }
21530b57cec5SDimitry Andric
21540b57cec5SDimitry Andric SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT);
21550b57cec5SDimitry Andric SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Idx);
21560b57cec5SDimitry Andric // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
21570b57cec5SDimitry Andric // function has calls.
21580b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
21590b57cec5SDimitry Andric MFI.setHasCalls(true);
21600b57cec5SDimitry Andric return DAG.getLoad(VT, DL, DAG.getEntryNode(), AbsAddr,
21610b57cec5SDimitry Andric MachinePointerInfo::getGOT(DAG.getMachineFunction()));
21620b57cec5SDimitry Andric }
21630b57cec5SDimitry Andric
21640b57cec5SDimitry Andric // This is one of the absolute code models.
21650b57cec5SDimitry Andric switch(getTargetMachine().getCodeModel()) {
21660b57cec5SDimitry Andric default:
21670b57cec5SDimitry Andric llvm_unreachable("Unsupported absolute code model");
21680b57cec5SDimitry Andric case CodeModel::Small:
21690b57cec5SDimitry Andric // abs32.
21700b57cec5SDimitry Andric return makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
21710b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_LO, DAG);
21720b57cec5SDimitry Andric case CodeModel::Medium: {
21730b57cec5SDimitry Andric // abs44.
21740b57cec5SDimitry Andric SDValue H44 = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_H44,
21750b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_M44, DAG);
21760b57cec5SDimitry Andric H44 = DAG.getNode(ISD::SHL, DL, VT, H44, DAG.getConstant(12, DL, MVT::i32));
21770b57cec5SDimitry Andric SDValue L44 = withTargetFlags(Op, SparcMCExpr::VK_Sparc_L44, DAG);
21780b57cec5SDimitry Andric L44 = DAG.getNode(SPISD::Lo, DL, VT, L44);
21790b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, VT, H44, L44);
21800b57cec5SDimitry Andric }
21810b57cec5SDimitry Andric case CodeModel::Large: {
21820b57cec5SDimitry Andric // abs64.
21830b57cec5SDimitry Andric SDValue Hi = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HH,
21840b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_HM, DAG);
21850b57cec5SDimitry Andric Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, DAG.getConstant(32, DL, MVT::i32));
21860b57cec5SDimitry Andric SDValue Lo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
21870b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_LO, DAG);
21880b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo);
21890b57cec5SDimitry Andric }
21900b57cec5SDimitry Andric }
21910b57cec5SDimitry Andric }
21920b57cec5SDimitry Andric
LowerGlobalAddress(SDValue Op,SelectionDAG & DAG) const21930b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op,
21940b57cec5SDimitry Andric SelectionDAG &DAG) const {
21950b57cec5SDimitry Andric return makeAddress(Op, DAG);
21960b57cec5SDimitry Andric }
21970b57cec5SDimitry Andric
LowerConstantPool(SDValue Op,SelectionDAG & DAG) const21980b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerConstantPool(SDValue Op,
21990b57cec5SDimitry Andric SelectionDAG &DAG) const {
22000b57cec5SDimitry Andric return makeAddress(Op, DAG);
22010b57cec5SDimitry Andric }
22020b57cec5SDimitry Andric
LowerBlockAddress(SDValue Op,SelectionDAG & DAG) const22030b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerBlockAddress(SDValue Op,
22040b57cec5SDimitry Andric SelectionDAG &DAG) const {
22050b57cec5SDimitry Andric return makeAddress(Op, DAG);
22060b57cec5SDimitry Andric }
22070b57cec5SDimitry Andric
LowerGlobalTLSAddress(SDValue Op,SelectionDAG & DAG) const22080b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op,
22090b57cec5SDimitry Andric SelectionDAG &DAG) const {
22100b57cec5SDimitry Andric
22110b57cec5SDimitry Andric GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
22120b57cec5SDimitry Andric if (DAG.getTarget().useEmulatedTLS())
22130b57cec5SDimitry Andric return LowerToTLSEmulatedModel(GA, DAG);
22140b57cec5SDimitry Andric
22150b57cec5SDimitry Andric SDLoc DL(GA);
22160b57cec5SDimitry Andric const GlobalValue *GV = GA->getGlobal();
22170b57cec5SDimitry Andric EVT PtrVT = getPointerTy(DAG.getDataLayout());
22180b57cec5SDimitry Andric
22190b57cec5SDimitry Andric TLSModel::Model model = getTargetMachine().getTLSModel(GV);
22200b57cec5SDimitry Andric
22210b57cec5SDimitry Andric if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) {
22220b57cec5SDimitry Andric unsigned HiTF = ((model == TLSModel::GeneralDynamic)
22230b57cec5SDimitry Andric ? SparcMCExpr::VK_Sparc_TLS_GD_HI22
22240b57cec5SDimitry Andric : SparcMCExpr::VK_Sparc_TLS_LDM_HI22);
22250b57cec5SDimitry Andric unsigned LoTF = ((model == TLSModel::GeneralDynamic)
22260b57cec5SDimitry Andric ? SparcMCExpr::VK_Sparc_TLS_GD_LO10
22270b57cec5SDimitry Andric : SparcMCExpr::VK_Sparc_TLS_LDM_LO10);
22280b57cec5SDimitry Andric unsigned addTF = ((model == TLSModel::GeneralDynamic)
22290b57cec5SDimitry Andric ? SparcMCExpr::VK_Sparc_TLS_GD_ADD
22300b57cec5SDimitry Andric : SparcMCExpr::VK_Sparc_TLS_LDM_ADD);
22310b57cec5SDimitry Andric unsigned callTF = ((model == TLSModel::GeneralDynamic)
22320b57cec5SDimitry Andric ? SparcMCExpr::VK_Sparc_TLS_GD_CALL
22330b57cec5SDimitry Andric : SparcMCExpr::VK_Sparc_TLS_LDM_CALL);
22340b57cec5SDimitry Andric
22350b57cec5SDimitry Andric SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG);
22360b57cec5SDimitry Andric SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
22370b57cec5SDimitry Andric SDValue Argument = DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Base, HiLo,
22380b57cec5SDimitry Andric withTargetFlags(Op, addTF, DAG));
22390b57cec5SDimitry Andric
22400b57cec5SDimitry Andric SDValue Chain = DAG.getEntryNode();
224106c3fb27SDimitry Andric SDValue InGlue;
22420b57cec5SDimitry Andric
22430b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, 1, 0, DL);
224406c3fb27SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, SP::O0, Argument, InGlue);
224506c3fb27SDimitry Andric InGlue = Chain.getValue(1);
22460b57cec5SDimitry Andric SDValue Callee = DAG.getTargetExternalSymbol("__tls_get_addr", PtrVT);
22470b57cec5SDimitry Andric SDValue Symbol = withTargetFlags(Op, callTF, DAG);
22480b57cec5SDimitry Andric
22490b57cec5SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
22500b57cec5SDimitry Andric const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask(
22510b57cec5SDimitry Andric DAG.getMachineFunction(), CallingConv::C);
22520b57cec5SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention");
22530b57cec5SDimitry Andric SDValue Ops[] = {Chain,
22540b57cec5SDimitry Andric Callee,
22550b57cec5SDimitry Andric Symbol,
22560b57cec5SDimitry Andric DAG.getRegister(SP::O0, PtrVT),
22570b57cec5SDimitry Andric DAG.getRegisterMask(Mask),
225806c3fb27SDimitry Andric InGlue};
22590b57cec5SDimitry Andric Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, Ops);
226006c3fb27SDimitry Andric InGlue = Chain.getValue(1);
226106c3fb27SDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, 1, 0, InGlue, DL);
226206c3fb27SDimitry Andric InGlue = Chain.getValue(1);
226306c3fb27SDimitry Andric SDValue Ret = DAG.getCopyFromReg(Chain, DL, SP::O0, PtrVT, InGlue);
22640b57cec5SDimitry Andric
22650b57cec5SDimitry Andric if (model != TLSModel::LocalDynamic)
22660b57cec5SDimitry Andric return Ret;
22670b57cec5SDimitry Andric
22680b57cec5SDimitry Andric SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
22690b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG));
22700b57cec5SDimitry Andric SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
22710b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG));
22720b57cec5SDimitry Andric HiLo = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
22730b57cec5SDimitry Andric return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo,
22740b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG));
22750b57cec5SDimitry Andric }
22760b57cec5SDimitry Andric
22770b57cec5SDimitry Andric if (model == TLSModel::InitialExec) {
22780b57cec5SDimitry Andric unsigned ldTF = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX
22790b57cec5SDimitry Andric : SparcMCExpr::VK_Sparc_TLS_IE_LD);
22800b57cec5SDimitry Andric
22810b57cec5SDimitry Andric SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
22820b57cec5SDimitry Andric
22830b57cec5SDimitry Andric // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
22840b57cec5SDimitry Andric // function has calls.
22850b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
22860b57cec5SDimitry Andric MFI.setHasCalls(true);
22870b57cec5SDimitry Andric
22880b57cec5SDimitry Andric SDValue TGA = makeHiLoPair(Op,
22890b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_TLS_IE_HI22,
22900b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_TLS_IE_LO10, DAG);
22910b57cec5SDimitry Andric SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base, TGA);
22920b57cec5SDimitry Andric SDValue Offset = DAG.getNode(SPISD::TLS_LD,
22930b57cec5SDimitry Andric DL, PtrVT, Ptr,
22940b57cec5SDimitry Andric withTargetFlags(Op, ldTF, DAG));
22950b57cec5SDimitry Andric return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT,
22960b57cec5SDimitry Andric DAG.getRegister(SP::G7, PtrVT), Offset,
22970b57cec5SDimitry Andric withTargetFlags(Op,
22980b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG));
22990b57cec5SDimitry Andric }
23000b57cec5SDimitry Andric
23010b57cec5SDimitry Andric assert(model == TLSModel::LocalExec);
23020b57cec5SDimitry Andric SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
23030b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG));
23040b57cec5SDimitry Andric SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
23050b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG));
23060b57cec5SDimitry Andric SDValue Offset = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
23070b57cec5SDimitry Andric
23080b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, PtrVT,
23090b57cec5SDimitry Andric DAG.getRegister(SP::G7, PtrVT), Offset);
23100b57cec5SDimitry Andric }
23110b57cec5SDimitry Andric
LowerF128_LibCallArg(SDValue Chain,ArgListTy & Args,SDValue Arg,const SDLoc & DL,SelectionDAG & DAG) const23120b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain,
23130b57cec5SDimitry Andric ArgListTy &Args, SDValue Arg,
23140b57cec5SDimitry Andric const SDLoc &DL,
23150b57cec5SDimitry Andric SelectionDAG &DAG) const {
23160b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
23170b57cec5SDimitry Andric EVT ArgVT = Arg.getValueType();
23180b57cec5SDimitry Andric Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
23190b57cec5SDimitry Andric
23200b57cec5SDimitry Andric ArgListEntry Entry;
23210b57cec5SDimitry Andric Entry.Node = Arg;
23220b57cec5SDimitry Andric Entry.Ty = ArgTy;
23230b57cec5SDimitry Andric
23240b57cec5SDimitry Andric if (ArgTy->isFP128Ty()) {
23250b57cec5SDimitry Andric // Create a stack object and pass the pointer to the library function.
23265ffd83dbSDimitry Andric int FI = MFI.CreateStackObject(16, Align(8), false);
23270b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
23280b57cec5SDimitry Andric Chain = DAG.getStore(Chain, DL, Entry.Node, FIPtr, MachinePointerInfo(),
2329e8d8bef9SDimitry Andric Align(8));
23300b57cec5SDimitry Andric
23310b57cec5SDimitry Andric Entry.Node = FIPtr;
23320b57cec5SDimitry Andric Entry.Ty = PointerType::getUnqual(ArgTy);
23330b57cec5SDimitry Andric }
23340b57cec5SDimitry Andric Args.push_back(Entry);
23350b57cec5SDimitry Andric return Chain;
23360b57cec5SDimitry Andric }
23370b57cec5SDimitry Andric
23380b57cec5SDimitry Andric SDValue
LowerF128Op(SDValue Op,SelectionDAG & DAG,const char * LibFuncName,unsigned numArgs) const23390b57cec5SDimitry Andric SparcTargetLowering::LowerF128Op(SDValue Op, SelectionDAG &DAG,
23400b57cec5SDimitry Andric const char *LibFuncName,
23410b57cec5SDimitry Andric unsigned numArgs) const {
23420b57cec5SDimitry Andric
23430b57cec5SDimitry Andric ArgListTy Args;
23440b57cec5SDimitry Andric
23450b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
23460b57cec5SDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout());
23470b57cec5SDimitry Andric
23480b57cec5SDimitry Andric SDValue Callee = DAG.getExternalSymbol(LibFuncName, PtrVT);
23490b57cec5SDimitry Andric Type *RetTy = Op.getValueType().getTypeForEVT(*DAG.getContext());
23500b57cec5SDimitry Andric Type *RetTyABI = RetTy;
23510b57cec5SDimitry Andric SDValue Chain = DAG.getEntryNode();
23520b57cec5SDimitry Andric SDValue RetPtr;
23530b57cec5SDimitry Andric
23540b57cec5SDimitry Andric if (RetTy->isFP128Ty()) {
23550b57cec5SDimitry Andric // Create a Stack Object to receive the return value of type f128.
23560b57cec5SDimitry Andric ArgListEntry Entry;
23575ffd83dbSDimitry Andric int RetFI = MFI.CreateStackObject(16, Align(8), false);
23580b57cec5SDimitry Andric RetPtr = DAG.getFrameIndex(RetFI, PtrVT);
23590b57cec5SDimitry Andric Entry.Node = RetPtr;
23600b57cec5SDimitry Andric Entry.Ty = PointerType::getUnqual(RetTy);
236181ad6265SDimitry Andric if (!Subtarget->is64Bit()) {
23620b57cec5SDimitry Andric Entry.IsSRet = true;
236381ad6265SDimitry Andric Entry.IndirectType = RetTy;
236481ad6265SDimitry Andric }
23650b57cec5SDimitry Andric Entry.IsReturned = false;
23660b57cec5SDimitry Andric Args.push_back(Entry);
23670b57cec5SDimitry Andric RetTyABI = Type::getVoidTy(*DAG.getContext());
23680b57cec5SDimitry Andric }
23690b57cec5SDimitry Andric
23700b57cec5SDimitry Andric assert(Op->getNumOperands() >= numArgs && "Not enough operands!");
23710b57cec5SDimitry Andric for (unsigned i = 0, e = numArgs; i != e; ++i) {
23720b57cec5SDimitry Andric Chain = LowerF128_LibCallArg(Chain, Args, Op.getOperand(i), SDLoc(Op), DAG);
23730b57cec5SDimitry Andric }
23740b57cec5SDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG);
23750b57cec5SDimitry Andric CLI.setDebugLoc(SDLoc(Op)).setChain(Chain)
23760b57cec5SDimitry Andric .setCallee(CallingConv::C, RetTyABI, Callee, std::move(Args));
23770b57cec5SDimitry Andric
23780b57cec5SDimitry Andric std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
23790b57cec5SDimitry Andric
23800b57cec5SDimitry Andric // chain is in second result.
23810b57cec5SDimitry Andric if (RetTyABI == RetTy)
23820b57cec5SDimitry Andric return CallInfo.first;
23830b57cec5SDimitry Andric
23840b57cec5SDimitry Andric assert (RetTy->isFP128Ty() && "Unexpected return type!");
23850b57cec5SDimitry Andric
23860b57cec5SDimitry Andric Chain = CallInfo.second;
23870b57cec5SDimitry Andric
23880b57cec5SDimitry Andric // Load RetPtr to get the return value.
23890b57cec5SDimitry Andric return DAG.getLoad(Op.getValueType(), SDLoc(Op), Chain, RetPtr,
2390e8d8bef9SDimitry Andric MachinePointerInfo(), Align(8));
23910b57cec5SDimitry Andric }
23920b57cec5SDimitry Andric
LowerF128Compare(SDValue LHS,SDValue RHS,unsigned & SPCC,const SDLoc & DL,SelectionDAG & DAG) const23930b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerF128Compare(SDValue LHS, SDValue RHS,
23940b57cec5SDimitry Andric unsigned &SPCC, const SDLoc &DL,
23950b57cec5SDimitry Andric SelectionDAG &DAG) const {
23960b57cec5SDimitry Andric
23970b57cec5SDimitry Andric const char *LibCall = nullptr;
23980b57cec5SDimitry Andric bool is64Bit = Subtarget->is64Bit();
23990b57cec5SDimitry Andric switch(SPCC) {
24000b57cec5SDimitry Andric default: llvm_unreachable("Unhandled conditional code!");
24010b57cec5SDimitry Andric case SPCC::FCC_E : LibCall = is64Bit? "_Qp_feq" : "_Q_feq"; break;
24020b57cec5SDimitry Andric case SPCC::FCC_NE : LibCall = is64Bit? "_Qp_fne" : "_Q_fne"; break;
24030b57cec5SDimitry Andric case SPCC::FCC_L : LibCall = is64Bit? "_Qp_flt" : "_Q_flt"; break;
24040b57cec5SDimitry Andric case SPCC::FCC_G : LibCall = is64Bit? "_Qp_fgt" : "_Q_fgt"; break;
24050b57cec5SDimitry Andric case SPCC::FCC_LE : LibCall = is64Bit? "_Qp_fle" : "_Q_fle"; break;
24060b57cec5SDimitry Andric case SPCC::FCC_GE : LibCall = is64Bit? "_Qp_fge" : "_Q_fge"; break;
24070b57cec5SDimitry Andric case SPCC::FCC_UL :
24080b57cec5SDimitry Andric case SPCC::FCC_ULE:
24090b57cec5SDimitry Andric case SPCC::FCC_UG :
24100b57cec5SDimitry Andric case SPCC::FCC_UGE:
24110b57cec5SDimitry Andric case SPCC::FCC_U :
24120b57cec5SDimitry Andric case SPCC::FCC_O :
24130b57cec5SDimitry Andric case SPCC::FCC_LG :
24140b57cec5SDimitry Andric case SPCC::FCC_UE : LibCall = is64Bit? "_Qp_cmp" : "_Q_cmp"; break;
24150b57cec5SDimitry Andric }
24160b57cec5SDimitry Andric
24170b57cec5SDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout());
24180b57cec5SDimitry Andric SDValue Callee = DAG.getExternalSymbol(LibCall, PtrVT);
24190b57cec5SDimitry Andric Type *RetTy = Type::getInt32Ty(*DAG.getContext());
24200b57cec5SDimitry Andric ArgListTy Args;
24210b57cec5SDimitry Andric SDValue Chain = DAG.getEntryNode();
24220b57cec5SDimitry Andric Chain = LowerF128_LibCallArg(Chain, Args, LHS, DL, DAG);
24230b57cec5SDimitry Andric Chain = LowerF128_LibCallArg(Chain, Args, RHS, DL, DAG);
24240b57cec5SDimitry Andric
24250b57cec5SDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG);
24260b57cec5SDimitry Andric CLI.setDebugLoc(DL).setChain(Chain)
24270b57cec5SDimitry Andric .setCallee(CallingConv::C, RetTy, Callee, std::move(Args));
24280b57cec5SDimitry Andric
24290b57cec5SDimitry Andric std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
24300b57cec5SDimitry Andric
24310b57cec5SDimitry Andric // result is in first, and chain is in second result.
24320b57cec5SDimitry Andric SDValue Result = CallInfo.first;
24330b57cec5SDimitry Andric
24340b57cec5SDimitry Andric switch(SPCC) {
24350b57cec5SDimitry Andric default: {
24365ffd83dbSDimitry Andric SDValue RHS = DAG.getConstant(0, DL, Result.getValueType());
24370b57cec5SDimitry Andric SPCC = SPCC::ICC_NE;
24380b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24390b57cec5SDimitry Andric }
24400b57cec5SDimitry Andric case SPCC::FCC_UL : {
24418bcb0991SDimitry Andric SDValue Mask = DAG.getConstant(1, DL, Result.getValueType());
24420b57cec5SDimitry Andric Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask);
24435ffd83dbSDimitry Andric SDValue RHS = DAG.getConstant(0, DL, Result.getValueType());
24440b57cec5SDimitry Andric SPCC = SPCC::ICC_NE;
24450b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24460b57cec5SDimitry Andric }
24470b57cec5SDimitry Andric case SPCC::FCC_ULE: {
24485ffd83dbSDimitry Andric SDValue RHS = DAG.getConstant(2, DL, Result.getValueType());
24490b57cec5SDimitry Andric SPCC = SPCC::ICC_NE;
24500b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24510b57cec5SDimitry Andric }
24520b57cec5SDimitry Andric case SPCC::FCC_UG : {
24535ffd83dbSDimitry Andric SDValue RHS = DAG.getConstant(1, DL, Result.getValueType());
24540b57cec5SDimitry Andric SPCC = SPCC::ICC_G;
24550b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24560b57cec5SDimitry Andric }
24570b57cec5SDimitry Andric case SPCC::FCC_UGE: {
24585ffd83dbSDimitry Andric SDValue RHS = DAG.getConstant(1, DL, Result.getValueType());
24590b57cec5SDimitry Andric SPCC = SPCC::ICC_NE;
24600b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24610b57cec5SDimitry Andric }
24620b57cec5SDimitry Andric
24630b57cec5SDimitry Andric case SPCC::FCC_U : {
24645ffd83dbSDimitry Andric SDValue RHS = DAG.getConstant(3, DL, Result.getValueType());
24650b57cec5SDimitry Andric SPCC = SPCC::ICC_E;
24660b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24670b57cec5SDimitry Andric }
24680b57cec5SDimitry Andric case SPCC::FCC_O : {
24695ffd83dbSDimitry Andric SDValue RHS = DAG.getConstant(3, DL, Result.getValueType());
24700b57cec5SDimitry Andric SPCC = SPCC::ICC_NE;
24710b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24720b57cec5SDimitry Andric }
24730b57cec5SDimitry Andric case SPCC::FCC_LG : {
24748bcb0991SDimitry Andric SDValue Mask = DAG.getConstant(3, DL, Result.getValueType());
24750b57cec5SDimitry Andric Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask);
24765ffd83dbSDimitry Andric SDValue RHS = DAG.getConstant(0, DL, Result.getValueType());
24770b57cec5SDimitry Andric SPCC = SPCC::ICC_NE;
24780b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24790b57cec5SDimitry Andric }
24800b57cec5SDimitry Andric case SPCC::FCC_UE : {
24818bcb0991SDimitry Andric SDValue Mask = DAG.getConstant(3, DL, Result.getValueType());
24820b57cec5SDimitry Andric Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask);
24835ffd83dbSDimitry Andric SDValue RHS = DAG.getConstant(0, DL, Result.getValueType());
24840b57cec5SDimitry Andric SPCC = SPCC::ICC_E;
24850b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24860b57cec5SDimitry Andric }
24870b57cec5SDimitry Andric }
24880b57cec5SDimitry Andric }
24890b57cec5SDimitry Andric
24900b57cec5SDimitry Andric static SDValue
LowerF128_FPEXTEND(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI)24910b57cec5SDimitry Andric LowerF128_FPEXTEND(SDValue Op, SelectionDAG &DAG,
24920b57cec5SDimitry Andric const SparcTargetLowering &TLI) {
24930b57cec5SDimitry Andric
24940b57cec5SDimitry Andric if (Op.getOperand(0).getValueType() == MVT::f64)
24950b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG,
24960b57cec5SDimitry Andric TLI.getLibcallName(RTLIB::FPEXT_F64_F128), 1);
24970b57cec5SDimitry Andric
24980b57cec5SDimitry Andric if (Op.getOperand(0).getValueType() == MVT::f32)
24990b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG,
25000b57cec5SDimitry Andric TLI.getLibcallName(RTLIB::FPEXT_F32_F128), 1);
25010b57cec5SDimitry Andric
25020b57cec5SDimitry Andric llvm_unreachable("fpextend with non-float operand!");
25030b57cec5SDimitry Andric return SDValue();
25040b57cec5SDimitry Andric }
25050b57cec5SDimitry Andric
25060b57cec5SDimitry Andric static SDValue
LowerF128_FPROUND(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI)25070b57cec5SDimitry Andric LowerF128_FPROUND(SDValue Op, SelectionDAG &DAG,
25080b57cec5SDimitry Andric const SparcTargetLowering &TLI) {
25090b57cec5SDimitry Andric // FP_ROUND on f64 and f32 are legal.
25100b57cec5SDimitry Andric if (Op.getOperand(0).getValueType() != MVT::f128)
25110b57cec5SDimitry Andric return Op;
25120b57cec5SDimitry Andric
25130b57cec5SDimitry Andric if (Op.getValueType() == MVT::f64)
25140b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG,
25150b57cec5SDimitry Andric TLI.getLibcallName(RTLIB::FPROUND_F128_F64), 1);
25160b57cec5SDimitry Andric if (Op.getValueType() == MVT::f32)
25170b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG,
25180b57cec5SDimitry Andric TLI.getLibcallName(RTLIB::FPROUND_F128_F32), 1);
25190b57cec5SDimitry Andric
25200b57cec5SDimitry Andric llvm_unreachable("fpround to non-float!");
25210b57cec5SDimitry Andric return SDValue();
25220b57cec5SDimitry Andric }
25230b57cec5SDimitry Andric
LowerFP_TO_SINT(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad)25240b57cec5SDimitry Andric static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG,
25250b57cec5SDimitry Andric const SparcTargetLowering &TLI,
25260b57cec5SDimitry Andric bool hasHardQuad) {
25270b57cec5SDimitry Andric SDLoc dl(Op);
25280b57cec5SDimitry Andric EVT VT = Op.getValueType();
25290b57cec5SDimitry Andric assert(VT == MVT::i32 || VT == MVT::i64);
25300b57cec5SDimitry Andric
25310b57cec5SDimitry Andric // Expand f128 operations to fp128 abi calls.
25320b57cec5SDimitry Andric if (Op.getOperand(0).getValueType() == MVT::f128
25330b57cec5SDimitry Andric && (!hasHardQuad || !TLI.isTypeLegal(VT))) {
25340b57cec5SDimitry Andric const char *libName = TLI.getLibcallName(VT == MVT::i32
25350b57cec5SDimitry Andric ? RTLIB::FPTOSINT_F128_I32
25360b57cec5SDimitry Andric : RTLIB::FPTOSINT_F128_I64);
25370b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG, libName, 1);
25380b57cec5SDimitry Andric }
25390b57cec5SDimitry Andric
25400b57cec5SDimitry Andric // Expand if the resulting type is illegal.
25410b57cec5SDimitry Andric if (!TLI.isTypeLegal(VT))
25420b57cec5SDimitry Andric return SDValue();
25430b57cec5SDimitry Andric
25440b57cec5SDimitry Andric // Otherwise, Convert the fp value to integer in an FP register.
25450b57cec5SDimitry Andric if (VT == MVT::i32)
25460b57cec5SDimitry Andric Op = DAG.getNode(SPISD::FTOI, dl, MVT::f32, Op.getOperand(0));
25470b57cec5SDimitry Andric else
25480b57cec5SDimitry Andric Op = DAG.getNode(SPISD::FTOX, dl, MVT::f64, Op.getOperand(0));
25490b57cec5SDimitry Andric
25500b57cec5SDimitry Andric return DAG.getNode(ISD::BITCAST, dl, VT, Op);
25510b57cec5SDimitry Andric }
25520b57cec5SDimitry Andric
LowerSINT_TO_FP(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad)25530b57cec5SDimitry Andric static SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG,
25540b57cec5SDimitry Andric const SparcTargetLowering &TLI,
25550b57cec5SDimitry Andric bool hasHardQuad) {
25560b57cec5SDimitry Andric SDLoc dl(Op);
25570b57cec5SDimitry Andric EVT OpVT = Op.getOperand(0).getValueType();
25580b57cec5SDimitry Andric assert(OpVT == MVT::i32 || (OpVT == MVT::i64));
25590b57cec5SDimitry Andric
25600b57cec5SDimitry Andric EVT floatVT = (OpVT == MVT::i32) ? MVT::f32 : MVT::f64;
25610b57cec5SDimitry Andric
25620b57cec5SDimitry Andric // Expand f128 operations to fp128 ABI calls.
25630b57cec5SDimitry Andric if (Op.getValueType() == MVT::f128
25640b57cec5SDimitry Andric && (!hasHardQuad || !TLI.isTypeLegal(OpVT))) {
25650b57cec5SDimitry Andric const char *libName = TLI.getLibcallName(OpVT == MVT::i32
25660b57cec5SDimitry Andric ? RTLIB::SINTTOFP_I32_F128
25670b57cec5SDimitry Andric : RTLIB::SINTTOFP_I64_F128);
25680b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG, libName, 1);
25690b57cec5SDimitry Andric }
25700b57cec5SDimitry Andric
25710b57cec5SDimitry Andric // Expand if the operand type is illegal.
25720b57cec5SDimitry Andric if (!TLI.isTypeLegal(OpVT))
25730b57cec5SDimitry Andric return SDValue();
25740b57cec5SDimitry Andric
25750b57cec5SDimitry Andric // Otherwise, Convert the int value to FP in an FP register.
25760b57cec5SDimitry Andric SDValue Tmp = DAG.getNode(ISD::BITCAST, dl, floatVT, Op.getOperand(0));
25770b57cec5SDimitry Andric unsigned opcode = (OpVT == MVT::i32)? SPISD::ITOF : SPISD::XTOF;
25780b57cec5SDimitry Andric return DAG.getNode(opcode, dl, Op.getValueType(), Tmp);
25790b57cec5SDimitry Andric }
25800b57cec5SDimitry Andric
LowerFP_TO_UINT(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad)25810b57cec5SDimitry Andric static SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG,
25820b57cec5SDimitry Andric const SparcTargetLowering &TLI,
25830b57cec5SDimitry Andric bool hasHardQuad) {
25840b57cec5SDimitry Andric SDLoc dl(Op);
25850b57cec5SDimitry Andric EVT VT = Op.getValueType();
25860b57cec5SDimitry Andric
25870b57cec5SDimitry Andric // Expand if it does not involve f128 or the target has support for
25880b57cec5SDimitry Andric // quad floating point instructions and the resulting type is legal.
25890b57cec5SDimitry Andric if (Op.getOperand(0).getValueType() != MVT::f128 ||
25900b57cec5SDimitry Andric (hasHardQuad && TLI.isTypeLegal(VT)))
25910b57cec5SDimitry Andric return SDValue();
25920b57cec5SDimitry Andric
25930b57cec5SDimitry Andric assert(VT == MVT::i32 || VT == MVT::i64);
25940b57cec5SDimitry Andric
25950b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG,
25960b57cec5SDimitry Andric TLI.getLibcallName(VT == MVT::i32
25970b57cec5SDimitry Andric ? RTLIB::FPTOUINT_F128_I32
25980b57cec5SDimitry Andric : RTLIB::FPTOUINT_F128_I64),
25990b57cec5SDimitry Andric 1);
26000b57cec5SDimitry Andric }
26010b57cec5SDimitry Andric
LowerUINT_TO_FP(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad)26020b57cec5SDimitry Andric static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG,
26030b57cec5SDimitry Andric const SparcTargetLowering &TLI,
26040b57cec5SDimitry Andric bool hasHardQuad) {
26050b57cec5SDimitry Andric SDLoc dl(Op);
26060b57cec5SDimitry Andric EVT OpVT = Op.getOperand(0).getValueType();
26070b57cec5SDimitry Andric assert(OpVT == MVT::i32 || OpVT == MVT::i64);
26080b57cec5SDimitry Andric
26090b57cec5SDimitry Andric // Expand if it does not involve f128 or the target has support for
26100b57cec5SDimitry Andric // quad floating point instructions and the operand type is legal.
26110b57cec5SDimitry Andric if (Op.getValueType() != MVT::f128 || (hasHardQuad && TLI.isTypeLegal(OpVT)))
26120b57cec5SDimitry Andric return SDValue();
26130b57cec5SDimitry Andric
26140b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG,
26150b57cec5SDimitry Andric TLI.getLibcallName(OpVT == MVT::i32
26160b57cec5SDimitry Andric ? RTLIB::UINTTOFP_I32_F128
26170b57cec5SDimitry Andric : RTLIB::UINTTOFP_I64_F128),
26180b57cec5SDimitry Andric 1);
26190b57cec5SDimitry Andric }
26200b57cec5SDimitry Andric
LowerBR_CC(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad,bool isV9,bool is64Bit)26210b57cec5SDimitry Andric static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
2622bdd1243dSDimitry Andric const SparcTargetLowering &TLI, bool hasHardQuad,
262306c3fb27SDimitry Andric bool isV9, bool is64Bit) {
26240b57cec5SDimitry Andric SDValue Chain = Op.getOperand(0);
26250b57cec5SDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
26260b57cec5SDimitry Andric SDValue LHS = Op.getOperand(2);
26270b57cec5SDimitry Andric SDValue RHS = Op.getOperand(3);
26280b57cec5SDimitry Andric SDValue Dest = Op.getOperand(4);
26290b57cec5SDimitry Andric SDLoc dl(Op);
26300b57cec5SDimitry Andric unsigned Opc, SPCC = ~0U;
26310b57cec5SDimitry Andric
26320b57cec5SDimitry Andric // If this is a br_cc of a "setcc", and if the setcc got lowered into
26330b57cec5SDimitry Andric // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
26340b57cec5SDimitry Andric LookThroughSetCC(LHS, RHS, CC, SPCC);
2635bdd1243dSDimitry Andric assert(LHS.getValueType() == RHS.getValueType());
26360b57cec5SDimitry Andric
26370b57cec5SDimitry Andric // Get the condition flag.
26380b57cec5SDimitry Andric SDValue CompareFlag;
26390b57cec5SDimitry Andric if (LHS.getValueType().isInteger()) {
264006c3fb27SDimitry Andric // On V9 processors running in 64-bit mode, if CC compares two `i64`s
264106c3fb27SDimitry Andric // and the RHS is zero we might be able to use a specialized branch.
26425f757f3fSDimitry Andric if (is64Bit && isV9 && LHS.getValueType() == MVT::i64 &&
26435f757f3fSDimitry Andric isNullConstant(RHS) && !ISD::isUnsignedIntSetCC(CC))
264406c3fb27SDimitry Andric return DAG.getNode(SPISD::BR_REG, dl, MVT::Other, Chain, Dest,
264506c3fb27SDimitry Andric DAG.getConstant(intCondCCodeToRcond(CC), dl, MVT::i32),
264606c3fb27SDimitry Andric LHS);
264706c3fb27SDimitry Andric
26480b57cec5SDimitry Andric CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS);
26490b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
2650bdd1243dSDimitry Andric if (isV9)
26510b57cec5SDimitry Andric // 32-bit compares use the icc flags, 64-bit uses the xcc flags.
2652bdd1243dSDimitry Andric Opc = LHS.getValueType() == MVT::i32 ? SPISD::BPICC : SPISD::BPXCC;
2653bdd1243dSDimitry Andric else
2654bdd1243dSDimitry Andric // Non-v9 targets don't have xcc.
2655bdd1243dSDimitry Andric Opc = SPISD::BRICC;
26560b57cec5SDimitry Andric } else {
26570b57cec5SDimitry Andric if (!hasHardQuad && LHS.getValueType() == MVT::f128) {
26580b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
26590b57cec5SDimitry Andric CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG);
2660bdd1243dSDimitry Andric Opc = isV9 ? SPISD::BPICC : SPISD::BRICC;
26610b57cec5SDimitry Andric } else {
2662bdd1243dSDimitry Andric unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC;
2663bdd1243dSDimitry Andric CompareFlag = DAG.getNode(CmpOpc, dl, MVT::Glue, LHS, RHS);
26640b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
2665bdd1243dSDimitry Andric Opc = isV9 ? SPISD::BRFCC_V9 : SPISD::BRFCC;
26660b57cec5SDimitry Andric }
26670b57cec5SDimitry Andric }
26680b57cec5SDimitry Andric return DAG.getNode(Opc, dl, MVT::Other, Chain, Dest,
26690b57cec5SDimitry Andric DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag);
26700b57cec5SDimitry Andric }
26710b57cec5SDimitry Andric
LowerSELECT_CC(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,bool hasHardQuad,bool isV9,bool is64Bit)26720b57cec5SDimitry Andric static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2673bdd1243dSDimitry Andric const SparcTargetLowering &TLI, bool hasHardQuad,
2674bdd1243dSDimitry Andric bool isV9, bool is64Bit) {
26750b57cec5SDimitry Andric SDValue LHS = Op.getOperand(0);
26760b57cec5SDimitry Andric SDValue RHS = Op.getOperand(1);
26770b57cec5SDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
26780b57cec5SDimitry Andric SDValue TrueVal = Op.getOperand(2);
26790b57cec5SDimitry Andric SDValue FalseVal = Op.getOperand(3);
26800b57cec5SDimitry Andric SDLoc dl(Op);
26810b57cec5SDimitry Andric unsigned Opc, SPCC = ~0U;
26820b57cec5SDimitry Andric
26830b57cec5SDimitry Andric // If this is a select_cc of a "setcc", and if the setcc got lowered into
26840b57cec5SDimitry Andric // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
26850b57cec5SDimitry Andric LookThroughSetCC(LHS, RHS, CC, SPCC);
2686bdd1243dSDimitry Andric assert(LHS.getValueType() == RHS.getValueType());
26870b57cec5SDimitry Andric
26880b57cec5SDimitry Andric SDValue CompareFlag;
26890b57cec5SDimitry Andric if (LHS.getValueType().isInteger()) {
2690bdd1243dSDimitry Andric // On V9 processors running in 64-bit mode, if CC compares two `i64`s
2691bdd1243dSDimitry Andric // and the RHS is zero we might be able to use a specialized select.
2692bdd1243dSDimitry Andric // All SELECT_CC between any two scalar integer types are eligible for
2693bdd1243dSDimitry Andric // lowering to specialized instructions. Additionally, f32 and f64 types
2694bdd1243dSDimitry Andric // are also eligible, but for f128 we can only use the specialized
2695bdd1243dSDimitry Andric // instruction when we have hardquad.
2696bdd1243dSDimitry Andric EVT ValType = TrueVal.getValueType();
2697bdd1243dSDimitry Andric bool IsEligibleType = ValType.isScalarInteger() || ValType == MVT::f32 ||
2698bdd1243dSDimitry Andric ValType == MVT::f64 ||
2699bdd1243dSDimitry Andric (ValType == MVT::f128 && hasHardQuad);
2700bdd1243dSDimitry Andric if (is64Bit && isV9 && LHS.getValueType() == MVT::i64 &&
2701bdd1243dSDimitry Andric isNullConstant(RHS) && !ISD::isUnsignedIntSetCC(CC) && IsEligibleType)
2702bdd1243dSDimitry Andric return DAG.getNode(
2703bdd1243dSDimitry Andric SPISD::SELECT_REG, dl, TrueVal.getValueType(), TrueVal, FalseVal,
2704bdd1243dSDimitry Andric DAG.getConstant(intCondCCodeToRcond(CC), dl, MVT::i32), LHS);
2705bdd1243dSDimitry Andric
27060b57cec5SDimitry Andric CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS);
27070b57cec5SDimitry Andric Opc = LHS.getValueType() == MVT::i32 ?
27080b57cec5SDimitry Andric SPISD::SELECT_ICC : SPISD::SELECT_XCC;
27090b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
27100b57cec5SDimitry Andric } else {
27110b57cec5SDimitry Andric if (!hasHardQuad && LHS.getValueType() == MVT::f128) {
27120b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
27130b57cec5SDimitry Andric CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG);
27140b57cec5SDimitry Andric Opc = SPISD::SELECT_ICC;
27150b57cec5SDimitry Andric } else {
2716bdd1243dSDimitry Andric unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC;
2717bdd1243dSDimitry Andric CompareFlag = DAG.getNode(CmpOpc, dl, MVT::Glue, LHS, RHS);
27180b57cec5SDimitry Andric Opc = SPISD::SELECT_FCC;
27190b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
27200b57cec5SDimitry Andric }
27210b57cec5SDimitry Andric }
27220b57cec5SDimitry Andric return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal,
27230b57cec5SDimitry Andric DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag);
27240b57cec5SDimitry Andric }
27250b57cec5SDimitry Andric
LowerVASTART(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI)27260b57cec5SDimitry Andric static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG,
27270b57cec5SDimitry Andric const SparcTargetLowering &TLI) {
27280b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
27290b57cec5SDimitry Andric SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
27300b57cec5SDimitry Andric auto PtrVT = TLI.getPointerTy(DAG.getDataLayout());
27310b57cec5SDimitry Andric
27320b57cec5SDimitry Andric // Need frame address to find the address of VarArgsFrameIndex.
27330b57cec5SDimitry Andric MF.getFrameInfo().setFrameAddressIsTaken(true);
27340b57cec5SDimitry Andric
27350b57cec5SDimitry Andric // vastart just stores the address of the VarArgsFrameIndex slot into the
27360b57cec5SDimitry Andric // memory location argument.
27370b57cec5SDimitry Andric SDLoc DL(Op);
27380b57cec5SDimitry Andric SDValue Offset =
27390b57cec5SDimitry Andric DAG.getNode(ISD::ADD, DL, PtrVT, DAG.getRegister(SP::I6, PtrVT),
27400b57cec5SDimitry Andric DAG.getIntPtrConstant(FuncInfo->getVarArgsFrameOffset(), DL));
27410b57cec5SDimitry Andric const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
27420b57cec5SDimitry Andric return DAG.getStore(Op.getOperand(0), DL, Offset, Op.getOperand(1),
27430b57cec5SDimitry Andric MachinePointerInfo(SV));
27440b57cec5SDimitry Andric }
27450b57cec5SDimitry Andric
LowerVAARG(SDValue Op,SelectionDAG & DAG)27460b57cec5SDimitry Andric static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) {
27470b57cec5SDimitry Andric SDNode *Node = Op.getNode();
27480b57cec5SDimitry Andric EVT VT = Node->getValueType(0);
27490b57cec5SDimitry Andric SDValue InChain = Node->getOperand(0);
27500b57cec5SDimitry Andric SDValue VAListPtr = Node->getOperand(1);
27510b57cec5SDimitry Andric EVT PtrVT = VAListPtr.getValueType();
27520b57cec5SDimitry Andric const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
27530b57cec5SDimitry Andric SDLoc DL(Node);
27540b57cec5SDimitry Andric SDValue VAList =
27550b57cec5SDimitry Andric DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV));
27560b57cec5SDimitry Andric // Increment the pointer, VAList, to the next vaarg.
27570b57cec5SDimitry Andric SDValue NextPtr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
27580b57cec5SDimitry Andric DAG.getIntPtrConstant(VT.getSizeInBits()/8,
27590b57cec5SDimitry Andric DL));
27600b57cec5SDimitry Andric // Store the incremented VAList to the legalized pointer.
27610b57cec5SDimitry Andric InChain = DAG.getStore(VAList.getValue(1), DL, NextPtr, VAListPtr,
27620b57cec5SDimitry Andric MachinePointerInfo(SV));
27630b57cec5SDimitry Andric // Load the actual argument out of the pointer VAList.
27640b57cec5SDimitry Andric // We can't count on greater alignment than the word size.
2765e8d8bef9SDimitry Andric return DAG.getLoad(
2766e8d8bef9SDimitry Andric VT, DL, InChain, VAList, MachinePointerInfo(),
2767bdd1243dSDimitry Andric Align(std::min(PtrVT.getFixedSizeInBits(), VT.getFixedSizeInBits()) / 8));
27680b57cec5SDimitry Andric }
27690b57cec5SDimitry Andric
LowerDYNAMIC_STACKALLOC(SDValue Op,SelectionDAG & DAG,const SparcSubtarget * Subtarget)27700b57cec5SDimitry Andric static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG,
27710b57cec5SDimitry Andric const SparcSubtarget *Subtarget) {
27720b57cec5SDimitry Andric SDValue Chain = Op.getOperand(0); // Legalize the chain.
27730b57cec5SDimitry Andric SDValue Size = Op.getOperand(1); // Legalize the size.
27745ffd83dbSDimitry Andric MaybeAlign Alignment =
27755ffd83dbSDimitry Andric cast<ConstantSDNode>(Op.getOperand(2))->getMaybeAlignValue();
27765ffd83dbSDimitry Andric Align StackAlign = Subtarget->getFrameLowering()->getStackAlign();
27770b57cec5SDimitry Andric EVT VT = Size->getValueType(0);
27780b57cec5SDimitry Andric SDLoc dl(Op);
27790b57cec5SDimitry Andric
27800b57cec5SDimitry Andric // TODO: implement over-aligned alloca. (Note: also implies
27810b57cec5SDimitry Andric // supporting support for overaligned function frames + dynamic
27820b57cec5SDimitry Andric // allocations, at all, which currently isn't supported)
27835ffd83dbSDimitry Andric if (Alignment && *Alignment > StackAlign) {
27840b57cec5SDimitry Andric const MachineFunction &MF = DAG.getMachineFunction();
27850b57cec5SDimitry Andric report_fatal_error("Function \"" + Twine(MF.getName()) + "\": "
27860b57cec5SDimitry Andric "over-aligned dynamic alloca not supported.");
27870b57cec5SDimitry Andric }
27880b57cec5SDimitry Andric
27890b57cec5SDimitry Andric // The resultant pointer needs to be above the register spill area
27900b57cec5SDimitry Andric // at the bottom of the stack.
27910b57cec5SDimitry Andric unsigned regSpillArea;
27920b57cec5SDimitry Andric if (Subtarget->is64Bit()) {
27930b57cec5SDimitry Andric regSpillArea = 128;
27940b57cec5SDimitry Andric } else {
27950b57cec5SDimitry Andric // On Sparc32, the size of the spill area is 92. Unfortunately,
27960b57cec5SDimitry Andric // that's only 4-byte aligned, not 8-byte aligned (the stack
27970b57cec5SDimitry Andric // pointer is 8-byte aligned). So, if the user asked for an 8-byte
27980b57cec5SDimitry Andric // aligned dynamic allocation, we actually need to add 96 to the
27990b57cec5SDimitry Andric // bottom of the stack, instead of 92, to ensure 8-byte alignment.
28000b57cec5SDimitry Andric
28010b57cec5SDimitry Andric // That also means adding 4 to the size of the allocation --
28020b57cec5SDimitry Andric // before applying the 8-byte rounding. Unfortunately, we the
28030b57cec5SDimitry Andric // value we get here has already had rounding applied. So, we need
28040b57cec5SDimitry Andric // to add 8, instead, wasting a bit more memory.
28050b57cec5SDimitry Andric
28060b57cec5SDimitry Andric // Further, this only actually needs to be done if the required
28070b57cec5SDimitry Andric // alignment is > 4, but, we've lost that info by this point, too,
28080b57cec5SDimitry Andric // so we always apply it.
28090b57cec5SDimitry Andric
28100b57cec5SDimitry Andric // (An alternative approach would be to always reserve 96 bytes
28110b57cec5SDimitry Andric // instead of the required 92, but then we'd waste 4 extra bytes
28120b57cec5SDimitry Andric // in every frame, not just those with dynamic stack allocations)
28130b57cec5SDimitry Andric
28140b57cec5SDimitry Andric // TODO: modify code in SelectionDAGBuilder to make this less sad.
28150b57cec5SDimitry Andric
28160b57cec5SDimitry Andric Size = DAG.getNode(ISD::ADD, dl, VT, Size,
28170b57cec5SDimitry Andric DAG.getConstant(8, dl, VT));
28180b57cec5SDimitry Andric regSpillArea = 96;
28190b57cec5SDimitry Andric }
28200b57cec5SDimitry Andric
28210b57cec5SDimitry Andric unsigned SPReg = SP::O6;
28220b57cec5SDimitry Andric SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
28230b57cec5SDimitry Andric SDValue NewSP = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value
28240b57cec5SDimitry Andric Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); // Output chain
28250b57cec5SDimitry Andric
28260b57cec5SDimitry Andric regSpillArea += Subtarget->getStackPointerBias();
28270b57cec5SDimitry Andric
28280b57cec5SDimitry Andric SDValue NewVal = DAG.getNode(ISD::ADD, dl, VT, NewSP,
28290b57cec5SDimitry Andric DAG.getConstant(regSpillArea, dl, VT));
28300b57cec5SDimitry Andric SDValue Ops[2] = { NewVal, Chain };
28310b57cec5SDimitry Andric return DAG.getMergeValues(Ops, dl);
28320b57cec5SDimitry Andric }
28330b57cec5SDimitry Andric
28340b57cec5SDimitry Andric
getFLUSHW(SDValue Op,SelectionDAG & DAG)28350b57cec5SDimitry Andric static SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) {
28360b57cec5SDimitry Andric SDLoc dl(Op);
28370b57cec5SDimitry Andric SDValue Chain = DAG.getNode(SPISD::FLUSHW,
28380b57cec5SDimitry Andric dl, MVT::Other, DAG.getEntryNode());
28390b57cec5SDimitry Andric return Chain;
28400b57cec5SDimitry Andric }
28410b57cec5SDimitry Andric
getFRAMEADDR(uint64_t depth,SDValue Op,SelectionDAG & DAG,const SparcSubtarget * Subtarget,bool AlwaysFlush=false)28420b57cec5SDimitry Andric static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG,
28430b57cec5SDimitry Andric const SparcSubtarget *Subtarget,
28440b57cec5SDimitry Andric bool AlwaysFlush = false) {
28450b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
28460b57cec5SDimitry Andric MFI.setFrameAddressIsTaken(true);
28470b57cec5SDimitry Andric
28480b57cec5SDimitry Andric EVT VT = Op.getValueType();
28490b57cec5SDimitry Andric SDLoc dl(Op);
28500b57cec5SDimitry Andric unsigned FrameReg = SP::I6;
28510b57cec5SDimitry Andric unsigned stackBias = Subtarget->getStackPointerBias();
28520b57cec5SDimitry Andric
28530b57cec5SDimitry Andric SDValue FrameAddr;
28540b57cec5SDimitry Andric SDValue Chain;
28550b57cec5SDimitry Andric
28560b57cec5SDimitry Andric // flush first to make sure the windowed registers' values are in stack
28570b57cec5SDimitry Andric Chain = (depth || AlwaysFlush) ? getFLUSHW(Op, DAG) : DAG.getEntryNode();
28580b57cec5SDimitry Andric
28590b57cec5SDimitry Andric FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
28600b57cec5SDimitry Andric
28610b57cec5SDimitry Andric unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56;
28620b57cec5SDimitry Andric
28630b57cec5SDimitry Andric while (depth--) {
28640b57cec5SDimitry Andric SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
28650b57cec5SDimitry Andric DAG.getIntPtrConstant(Offset, dl));
28660b57cec5SDimitry Andric FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo());
28670b57cec5SDimitry Andric }
28680b57cec5SDimitry Andric if (Subtarget->is64Bit())
28690b57cec5SDimitry Andric FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
28700b57cec5SDimitry Andric DAG.getIntPtrConstant(stackBias, dl));
28710b57cec5SDimitry Andric return FrameAddr;
28720b57cec5SDimitry Andric }
28730b57cec5SDimitry Andric
28740b57cec5SDimitry Andric
LowerFRAMEADDR(SDValue Op,SelectionDAG & DAG,const SparcSubtarget * Subtarget)28750b57cec5SDimitry Andric static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG,
28760b57cec5SDimitry Andric const SparcSubtarget *Subtarget) {
28770b57cec5SDimitry Andric
28780b57cec5SDimitry Andric uint64_t depth = Op.getConstantOperandVal(0);
28790b57cec5SDimitry Andric
28800b57cec5SDimitry Andric return getFRAMEADDR(depth, Op, DAG, Subtarget);
28810b57cec5SDimitry Andric
28820b57cec5SDimitry Andric }
28830b57cec5SDimitry Andric
LowerRETURNADDR(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI,const SparcSubtarget * Subtarget)28840b57cec5SDimitry Andric static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
28850b57cec5SDimitry Andric const SparcTargetLowering &TLI,
28860b57cec5SDimitry Andric const SparcSubtarget *Subtarget) {
28870b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
28880b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
28890b57cec5SDimitry Andric MFI.setReturnAddressIsTaken(true);
28900b57cec5SDimitry Andric
28910b57cec5SDimitry Andric if (TLI.verifyReturnAddressArgumentIsConstant(Op, DAG))
28920b57cec5SDimitry Andric return SDValue();
28930b57cec5SDimitry Andric
28940b57cec5SDimitry Andric EVT VT = Op.getValueType();
28950b57cec5SDimitry Andric SDLoc dl(Op);
28960b57cec5SDimitry Andric uint64_t depth = Op.getConstantOperandVal(0);
28970b57cec5SDimitry Andric
28980b57cec5SDimitry Andric SDValue RetAddr;
28990b57cec5SDimitry Andric if (depth == 0) {
29000b57cec5SDimitry Andric auto PtrVT = TLI.getPointerTy(DAG.getDataLayout());
290104eeddc0SDimitry Andric Register RetReg = MF.addLiveIn(SP::I7, TLI.getRegClassFor(PtrVT));
29020b57cec5SDimitry Andric RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT);
29030b57cec5SDimitry Andric return RetAddr;
29040b57cec5SDimitry Andric }
29050b57cec5SDimitry Andric
29060b57cec5SDimitry Andric // Need frame address to find return address of the caller.
29070b57cec5SDimitry Andric SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget, true);
29080b57cec5SDimitry Andric
29090b57cec5SDimitry Andric unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60;
29100b57cec5SDimitry Andric SDValue Ptr = DAG.getNode(ISD::ADD,
29110b57cec5SDimitry Andric dl, VT,
29120b57cec5SDimitry Andric FrameAddr,
29130b57cec5SDimitry Andric DAG.getIntPtrConstant(Offset, dl));
29140b57cec5SDimitry Andric RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr, MachinePointerInfo());
29150b57cec5SDimitry Andric
29160b57cec5SDimitry Andric return RetAddr;
29170b57cec5SDimitry Andric }
29180b57cec5SDimitry Andric
LowerF64Op(SDValue SrcReg64,const SDLoc & dl,SelectionDAG & DAG,unsigned opcode)29190b57cec5SDimitry Andric static SDValue LowerF64Op(SDValue SrcReg64, const SDLoc &dl, SelectionDAG &DAG,
29200b57cec5SDimitry Andric unsigned opcode) {
29210b57cec5SDimitry Andric assert(SrcReg64.getValueType() == MVT::f64 && "LowerF64Op called on non-double!");
29220b57cec5SDimitry Andric assert(opcode == ISD::FNEG || opcode == ISD::FABS);
29230b57cec5SDimitry Andric
29240b57cec5SDimitry Andric // Lower fneg/fabs on f64 to fneg/fabs on f32.
29250b57cec5SDimitry Andric // fneg f64 => fneg f32:sub_even, fmov f32:sub_odd.
29260b57cec5SDimitry Andric // fabs f64 => fabs f32:sub_even, fmov f32:sub_odd.
29270b57cec5SDimitry Andric
29280b57cec5SDimitry Andric // Note: in little-endian, the floating-point value is stored in the
29290b57cec5SDimitry Andric // registers are in the opposite order, so the subreg with the sign
29300b57cec5SDimitry Andric // bit is the highest-numbered (odd), rather than the
29310b57cec5SDimitry Andric // lowest-numbered (even).
29320b57cec5SDimitry Andric
29330b57cec5SDimitry Andric SDValue Hi32 = DAG.getTargetExtractSubreg(SP::sub_even, dl, MVT::f32,
29340b57cec5SDimitry Andric SrcReg64);
29350b57cec5SDimitry Andric SDValue Lo32 = DAG.getTargetExtractSubreg(SP::sub_odd, dl, MVT::f32,
29360b57cec5SDimitry Andric SrcReg64);
29370b57cec5SDimitry Andric
29380b57cec5SDimitry Andric if (DAG.getDataLayout().isLittleEndian())
29390b57cec5SDimitry Andric Lo32 = DAG.getNode(opcode, dl, MVT::f32, Lo32);
29400b57cec5SDimitry Andric else
29410b57cec5SDimitry Andric Hi32 = DAG.getNode(opcode, dl, MVT::f32, Hi32);
29420b57cec5SDimitry Andric
29430b57cec5SDimitry Andric SDValue DstReg64 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
29440b57cec5SDimitry Andric dl, MVT::f64), 0);
29450b57cec5SDimitry Andric DstReg64 = DAG.getTargetInsertSubreg(SP::sub_even, dl, MVT::f64,
29460b57cec5SDimitry Andric DstReg64, Hi32);
29470b57cec5SDimitry Andric DstReg64 = DAG.getTargetInsertSubreg(SP::sub_odd, dl, MVT::f64,
29480b57cec5SDimitry Andric DstReg64, Lo32);
29490b57cec5SDimitry Andric return DstReg64;
29500b57cec5SDimitry Andric }
29510b57cec5SDimitry Andric
29520b57cec5SDimitry Andric // Lower a f128 load into two f64 loads.
LowerF128Load(SDValue Op,SelectionDAG & DAG)29530b57cec5SDimitry Andric static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG)
29540b57cec5SDimitry Andric {
29550b57cec5SDimitry Andric SDLoc dl(Op);
2956e8d8bef9SDimitry Andric LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode());
2957e8d8bef9SDimitry Andric assert(LdNode->getOffset().isUndef() && "Unexpected node type");
29580b57cec5SDimitry Andric
2959e8d8bef9SDimitry Andric Align Alignment = commonAlignment(LdNode->getOriginalAlign(), 8);
29600b57cec5SDimitry Andric
29610b57cec5SDimitry Andric SDValue Hi64 =
29620b57cec5SDimitry Andric DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LdNode->getBasePtr(),
2963e8d8bef9SDimitry Andric LdNode->getPointerInfo(), Alignment);
29640b57cec5SDimitry Andric EVT addrVT = LdNode->getBasePtr().getValueType();
29650b57cec5SDimitry Andric SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT,
29660b57cec5SDimitry Andric LdNode->getBasePtr(),
29670b57cec5SDimitry Andric DAG.getConstant(8, dl, addrVT));
29680b57cec5SDimitry Andric SDValue Lo64 = DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LoPtr,
2969e8d8bef9SDimitry Andric LdNode->getPointerInfo().getWithOffset(8),
2970e8d8bef9SDimitry Andric Alignment);
29710b57cec5SDimitry Andric
29720b57cec5SDimitry Andric SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32);
29730b57cec5SDimitry Andric SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32);
29740b57cec5SDimitry Andric
29750b57cec5SDimitry Andric SDNode *InFP128 = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
29760b57cec5SDimitry Andric dl, MVT::f128);
29770b57cec5SDimitry Andric InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
29780b57cec5SDimitry Andric MVT::f128,
29790b57cec5SDimitry Andric SDValue(InFP128, 0),
29800b57cec5SDimitry Andric Hi64,
29810b57cec5SDimitry Andric SubRegEven);
29820b57cec5SDimitry Andric InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
29830b57cec5SDimitry Andric MVT::f128,
29840b57cec5SDimitry Andric SDValue(InFP128, 0),
29850b57cec5SDimitry Andric Lo64,
29860b57cec5SDimitry Andric SubRegOdd);
29870b57cec5SDimitry Andric SDValue OutChains[2] = { SDValue(Hi64.getNode(), 1),
29880b57cec5SDimitry Andric SDValue(Lo64.getNode(), 1) };
29890b57cec5SDimitry Andric SDValue OutChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
29900b57cec5SDimitry Andric SDValue Ops[2] = {SDValue(InFP128,0), OutChain};
29910b57cec5SDimitry Andric return DAG.getMergeValues(Ops, dl);
29920b57cec5SDimitry Andric }
29930b57cec5SDimitry Andric
LowerLOAD(SDValue Op,SelectionDAG & DAG)29940b57cec5SDimitry Andric static SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG)
29950b57cec5SDimitry Andric {
29960b57cec5SDimitry Andric LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode());
29970b57cec5SDimitry Andric
29980b57cec5SDimitry Andric EVT MemVT = LdNode->getMemoryVT();
29990b57cec5SDimitry Andric if (MemVT == MVT::f128)
30000b57cec5SDimitry Andric return LowerF128Load(Op, DAG);
30010b57cec5SDimitry Andric
30020b57cec5SDimitry Andric return Op;
30030b57cec5SDimitry Andric }
30040b57cec5SDimitry Andric
30050b57cec5SDimitry Andric // Lower a f128 store into two f64 stores.
LowerF128Store(SDValue Op,SelectionDAG & DAG)30060b57cec5SDimitry Andric static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) {
30070b57cec5SDimitry Andric SDLoc dl(Op);
3008e8d8bef9SDimitry Andric StoreSDNode *StNode = cast<StoreSDNode>(Op.getNode());
3009e8d8bef9SDimitry Andric assert(StNode->getOffset().isUndef() && "Unexpected node type");
3010e8d8bef9SDimitry Andric
30110b57cec5SDimitry Andric SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32);
30120b57cec5SDimitry Andric SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32);
30130b57cec5SDimitry Andric
30140b57cec5SDimitry Andric SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG,
30150b57cec5SDimitry Andric dl,
30160b57cec5SDimitry Andric MVT::f64,
30170b57cec5SDimitry Andric StNode->getValue(),
30180b57cec5SDimitry Andric SubRegEven);
30190b57cec5SDimitry Andric SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG,
30200b57cec5SDimitry Andric dl,
30210b57cec5SDimitry Andric MVT::f64,
30220b57cec5SDimitry Andric StNode->getValue(),
30230b57cec5SDimitry Andric SubRegOdd);
30240b57cec5SDimitry Andric
3025e8d8bef9SDimitry Andric Align Alignment = commonAlignment(StNode->getOriginalAlign(), 8);
30260b57cec5SDimitry Andric
30270b57cec5SDimitry Andric SDValue OutChains[2];
30280b57cec5SDimitry Andric OutChains[0] =
30290b57cec5SDimitry Andric DAG.getStore(StNode->getChain(), dl, SDValue(Hi64, 0),
3030e8d8bef9SDimitry Andric StNode->getBasePtr(), StNode->getPointerInfo(),
3031e8d8bef9SDimitry Andric Alignment);
30320b57cec5SDimitry Andric EVT addrVT = StNode->getBasePtr().getValueType();
30330b57cec5SDimitry Andric SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT,
30340b57cec5SDimitry Andric StNode->getBasePtr(),
30350b57cec5SDimitry Andric DAG.getConstant(8, dl, addrVT));
30360b57cec5SDimitry Andric OutChains[1] = DAG.getStore(StNode->getChain(), dl, SDValue(Lo64, 0), LoPtr,
3037e8d8bef9SDimitry Andric StNode->getPointerInfo().getWithOffset(8),
3038e8d8bef9SDimitry Andric Alignment);
30390b57cec5SDimitry Andric return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
30400b57cec5SDimitry Andric }
30410b57cec5SDimitry Andric
LowerSTORE(SDValue Op,SelectionDAG & DAG)30420b57cec5SDimitry Andric static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG)
30430b57cec5SDimitry Andric {
30440b57cec5SDimitry Andric SDLoc dl(Op);
30450b57cec5SDimitry Andric StoreSDNode *St = cast<StoreSDNode>(Op.getNode());
30460b57cec5SDimitry Andric
30470b57cec5SDimitry Andric EVT MemVT = St->getMemoryVT();
30480b57cec5SDimitry Andric if (MemVT == MVT::f128)
30490b57cec5SDimitry Andric return LowerF128Store(Op, DAG);
30500b57cec5SDimitry Andric
30510b57cec5SDimitry Andric if (MemVT == MVT::i64) {
30520b57cec5SDimitry Andric // Custom handling for i64 stores: turn it into a bitcast and a
30530b57cec5SDimitry Andric // v2i32 store.
30540b57cec5SDimitry Andric SDValue Val = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, St->getValue());
30550b57cec5SDimitry Andric SDValue Chain = DAG.getStore(
30560b57cec5SDimitry Andric St->getChain(), dl, Val, St->getBasePtr(), St->getPointerInfo(),
3057e8d8bef9SDimitry Andric St->getOriginalAlign(), St->getMemOperand()->getFlags(),
3058e8d8bef9SDimitry Andric St->getAAInfo());
30590b57cec5SDimitry Andric return Chain;
30600b57cec5SDimitry Andric }
30610b57cec5SDimitry Andric
30620b57cec5SDimitry Andric return SDValue();
30630b57cec5SDimitry Andric }
30640b57cec5SDimitry Andric
LowerFNEGorFABS(SDValue Op,SelectionDAG & DAG,bool isV9)30650b57cec5SDimitry Andric static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
30660b57cec5SDimitry Andric assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS)
30670b57cec5SDimitry Andric && "invalid opcode");
30680b57cec5SDimitry Andric
30690b57cec5SDimitry Andric SDLoc dl(Op);
30700b57cec5SDimitry Andric
30710b57cec5SDimitry Andric if (Op.getValueType() == MVT::f64)
30720b57cec5SDimitry Andric return LowerF64Op(Op.getOperand(0), dl, DAG, Op.getOpcode());
30730b57cec5SDimitry Andric if (Op.getValueType() != MVT::f128)
30740b57cec5SDimitry Andric return Op;
30750b57cec5SDimitry Andric
30760b57cec5SDimitry Andric // Lower fabs/fneg on f128 to fabs/fneg on f64
30770b57cec5SDimitry Andric // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64
30780b57cec5SDimitry Andric // (As with LowerF64Op, on little-endian, we need to negate the odd
30790b57cec5SDimitry Andric // subreg)
30800b57cec5SDimitry Andric
30810b57cec5SDimitry Andric SDValue SrcReg128 = Op.getOperand(0);
30820b57cec5SDimitry Andric SDValue Hi64 = DAG.getTargetExtractSubreg(SP::sub_even64, dl, MVT::f64,
30830b57cec5SDimitry Andric SrcReg128);
30840b57cec5SDimitry Andric SDValue Lo64 = DAG.getTargetExtractSubreg(SP::sub_odd64, dl, MVT::f64,
30850b57cec5SDimitry Andric SrcReg128);
30860b57cec5SDimitry Andric
30870b57cec5SDimitry Andric if (DAG.getDataLayout().isLittleEndian()) {
30880b57cec5SDimitry Andric if (isV9)
30890b57cec5SDimitry Andric Lo64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Lo64);
30900b57cec5SDimitry Andric else
30910b57cec5SDimitry Andric Lo64 = LowerF64Op(Lo64, dl, DAG, Op.getOpcode());
30920b57cec5SDimitry Andric } else {
30930b57cec5SDimitry Andric if (isV9)
30940b57cec5SDimitry Andric Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64);
30950b57cec5SDimitry Andric else
30960b57cec5SDimitry Andric Hi64 = LowerF64Op(Hi64, dl, DAG, Op.getOpcode());
30970b57cec5SDimitry Andric }
30980b57cec5SDimitry Andric
30990b57cec5SDimitry Andric SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
31000b57cec5SDimitry Andric dl, MVT::f128), 0);
31010b57cec5SDimitry Andric DstReg128 = DAG.getTargetInsertSubreg(SP::sub_even64, dl, MVT::f128,
31020b57cec5SDimitry Andric DstReg128, Hi64);
31030b57cec5SDimitry Andric DstReg128 = DAG.getTargetInsertSubreg(SP::sub_odd64, dl, MVT::f128,
31040b57cec5SDimitry Andric DstReg128, Lo64);
31050b57cec5SDimitry Andric return DstReg128;
31060b57cec5SDimitry Andric }
31070b57cec5SDimitry Andric
LowerADDC_ADDE_SUBC_SUBE(SDValue Op,SelectionDAG & DAG)31080b57cec5SDimitry Andric static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) {
31090b57cec5SDimitry Andric
31100b57cec5SDimitry Andric if (Op.getValueType() != MVT::i64)
31110b57cec5SDimitry Andric return Op;
31120b57cec5SDimitry Andric
31130b57cec5SDimitry Andric SDLoc dl(Op);
31140b57cec5SDimitry Andric SDValue Src1 = Op.getOperand(0);
31150b57cec5SDimitry Andric SDValue Src1Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1);
31160b57cec5SDimitry Andric SDValue Src1Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src1,
31170b57cec5SDimitry Andric DAG.getConstant(32, dl, MVT::i64));
31180b57cec5SDimitry Andric Src1Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1Hi);
31190b57cec5SDimitry Andric
31200b57cec5SDimitry Andric SDValue Src2 = Op.getOperand(1);
31210b57cec5SDimitry Andric SDValue Src2Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2);
31220b57cec5SDimitry Andric SDValue Src2Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src2,
31230b57cec5SDimitry Andric DAG.getConstant(32, dl, MVT::i64));
31240b57cec5SDimitry Andric Src2Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2Hi);
31250b57cec5SDimitry Andric
31260b57cec5SDimitry Andric
31270b57cec5SDimitry Andric bool hasChain = false;
31280b57cec5SDimitry Andric unsigned hiOpc = Op.getOpcode();
31290b57cec5SDimitry Andric switch (Op.getOpcode()) {
31300b57cec5SDimitry Andric default: llvm_unreachable("Invalid opcode");
31310b57cec5SDimitry Andric case ISD::ADDC: hiOpc = ISD::ADDE; break;
31320b57cec5SDimitry Andric case ISD::ADDE: hasChain = true; break;
31330b57cec5SDimitry Andric case ISD::SUBC: hiOpc = ISD::SUBE; break;
31340b57cec5SDimitry Andric case ISD::SUBE: hasChain = true; break;
31350b57cec5SDimitry Andric }
31360b57cec5SDimitry Andric SDValue Lo;
31370b57cec5SDimitry Andric SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Glue);
31380b57cec5SDimitry Andric if (hasChain) {
31390b57cec5SDimitry Andric Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo,
31400b57cec5SDimitry Andric Op.getOperand(2));
31410b57cec5SDimitry Andric } else {
31420b57cec5SDimitry Andric Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo);
31430b57cec5SDimitry Andric }
31440b57cec5SDimitry Andric SDValue Hi = DAG.getNode(hiOpc, dl, VTs, Src1Hi, Src2Hi, Lo.getValue(1));
31450b57cec5SDimitry Andric SDValue Carry = Hi.getValue(1);
31460b57cec5SDimitry Andric
31470b57cec5SDimitry Andric Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Lo);
31480b57cec5SDimitry Andric Hi = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Hi);
31490b57cec5SDimitry Andric Hi = DAG.getNode(ISD::SHL, dl, MVT::i64, Hi,
31500b57cec5SDimitry Andric DAG.getConstant(32, dl, MVT::i64));
31510b57cec5SDimitry Andric
31520b57cec5SDimitry Andric SDValue Dst = DAG.getNode(ISD::OR, dl, MVT::i64, Hi, Lo);
31530b57cec5SDimitry Andric SDValue Ops[2] = { Dst, Carry };
31540b57cec5SDimitry Andric return DAG.getMergeValues(Ops, dl);
31550b57cec5SDimitry Andric }
31560b57cec5SDimitry Andric
31570b57cec5SDimitry Andric // Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode()
31580b57cec5SDimitry Andric // in LegalizeDAG.cpp except the order of arguments to the library function.
LowerUMULO_SMULO(SDValue Op,SelectionDAG & DAG,const SparcTargetLowering & TLI)31590b57cec5SDimitry Andric static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG,
31600b57cec5SDimitry Andric const SparcTargetLowering &TLI)
31610b57cec5SDimitry Andric {
31620b57cec5SDimitry Andric unsigned opcode = Op.getOpcode();
31630b57cec5SDimitry Andric assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode.");
31640b57cec5SDimitry Andric
31650b57cec5SDimitry Andric bool isSigned = (opcode == ISD::SMULO);
31660b57cec5SDimitry Andric EVT VT = MVT::i64;
31670b57cec5SDimitry Andric EVT WideVT = MVT::i128;
31680b57cec5SDimitry Andric SDLoc dl(Op);
31690b57cec5SDimitry Andric SDValue LHS = Op.getOperand(0);
31700b57cec5SDimitry Andric
31710b57cec5SDimitry Andric if (LHS.getValueType() != VT)
31720b57cec5SDimitry Andric return Op;
31730b57cec5SDimitry Andric
31740b57cec5SDimitry Andric SDValue ShiftAmt = DAG.getConstant(63, dl, VT);
31750b57cec5SDimitry Andric
31760b57cec5SDimitry Andric SDValue RHS = Op.getOperand(1);
3177349cc55cSDimitry Andric SDValue HiLHS, HiRHS;
3178349cc55cSDimitry Andric if (isSigned) {
3179349cc55cSDimitry Andric HiLHS = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt);
3180349cc55cSDimitry Andric HiRHS = DAG.getNode(ISD::SRA, dl, MVT::i64, RHS, ShiftAmt);
3181349cc55cSDimitry Andric } else {
3182349cc55cSDimitry Andric HiLHS = DAG.getConstant(0, dl, VT);
3183349cc55cSDimitry Andric HiRHS = DAG.getConstant(0, dl, MVT::i64);
3184349cc55cSDimitry Andric }
3185349cc55cSDimitry Andric
31860b57cec5SDimitry Andric SDValue Args[] = { HiLHS, LHS, HiRHS, RHS };
31870b57cec5SDimitry Andric
31888bcb0991SDimitry Andric TargetLowering::MakeLibCallOptions CallOptions;
31898bcb0991SDimitry Andric CallOptions.setSExt(isSigned);
31900b57cec5SDimitry Andric SDValue MulResult = TLI.makeLibCall(DAG,
31910b57cec5SDimitry Andric RTLIB::MUL_I128, WideVT,
31928bcb0991SDimitry Andric Args, CallOptions, dl).first;
319306c3fb27SDimitry Andric SDValue BottomHalf, TopHalf;
319406c3fb27SDimitry Andric std::tie(BottomHalf, TopHalf) = DAG.SplitScalar(MulResult, dl, VT, VT);
31950b57cec5SDimitry Andric if (isSigned) {
31960b57cec5SDimitry Andric SDValue Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, ShiftAmt);
31970b57cec5SDimitry Andric TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, Tmp1, ISD::SETNE);
31980b57cec5SDimitry Andric } else {
31990b57cec5SDimitry Andric TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, DAG.getConstant(0, dl, VT),
32000b57cec5SDimitry Andric ISD::SETNE);
32010b57cec5SDimitry Andric }
32020b57cec5SDimitry Andric // MulResult is a node with an illegal type. Because such things are not
32030b57cec5SDimitry Andric // generally permitted during this phase of legalization, ensure that
32040b57cec5SDimitry Andric // nothing is left using the node. The above EXTRACT_ELEMENT nodes should have
32050b57cec5SDimitry Andric // been folded.
32060b57cec5SDimitry Andric assert(MulResult->use_empty() && "Illegally typed node still in use!");
32070b57cec5SDimitry Andric
32080b57cec5SDimitry Andric SDValue Ops[2] = { BottomHalf, TopHalf } ;
32090b57cec5SDimitry Andric return DAG.getMergeValues(Ops, dl);
32100b57cec5SDimitry Andric }
32110b57cec5SDimitry Andric
LowerATOMIC_LOAD_STORE(SDValue Op,SelectionDAG & DAG)32120b57cec5SDimitry Andric static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) {
3213fe6060f1SDimitry Andric if (isStrongerThanMonotonic(cast<AtomicSDNode>(Op)->getSuccessOrdering())) {
32140b57cec5SDimitry Andric // Expand with a fence.
32150b57cec5SDimitry Andric return SDValue();
3216fe6060f1SDimitry Andric }
32170b57cec5SDimitry Andric
32180b57cec5SDimitry Andric // Monotonic load/stores are legal.
32190b57cec5SDimitry Andric return Op;
32200b57cec5SDimitry Andric }
32210b57cec5SDimitry Andric
LowerINTRINSIC_WO_CHAIN(SDValue Op,SelectionDAG & DAG) const32220b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
32230b57cec5SDimitry Andric SelectionDAG &DAG) const {
3224647cbc5dSDimitry Andric unsigned IntNo = Op.getConstantOperandVal(0);
32250b57cec5SDimitry Andric SDLoc dl(Op);
32260b57cec5SDimitry Andric switch (IntNo) {
32270b57cec5SDimitry Andric default: return SDValue(); // Don't custom lower most intrinsics.
32280b57cec5SDimitry Andric case Intrinsic::thread_pointer: {
32290b57cec5SDimitry Andric EVT PtrVT = getPointerTy(DAG.getDataLayout());
32300b57cec5SDimitry Andric return DAG.getRegister(SP::G7, PtrVT);
32310b57cec5SDimitry Andric }
32320b57cec5SDimitry Andric }
32330b57cec5SDimitry Andric }
32340b57cec5SDimitry Andric
32350b57cec5SDimitry Andric SDValue SparcTargetLowering::
LowerOperation(SDValue Op,SelectionDAG & DAG) const32360b57cec5SDimitry Andric LowerOperation(SDValue Op, SelectionDAG &DAG) const {
32370b57cec5SDimitry Andric
32380b57cec5SDimitry Andric bool hasHardQuad = Subtarget->hasHardQuad();
32390b57cec5SDimitry Andric bool isV9 = Subtarget->isV9();
3240bdd1243dSDimitry Andric bool is64Bit = Subtarget->is64Bit();
32410b57cec5SDimitry Andric
32420b57cec5SDimitry Andric switch (Op.getOpcode()) {
32430b57cec5SDimitry Andric default: llvm_unreachable("Should not custom lower this!");
32440b57cec5SDimitry Andric
32450b57cec5SDimitry Andric case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this,
32460b57cec5SDimitry Andric Subtarget);
32470b57cec5SDimitry Andric case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG,
32480b57cec5SDimitry Andric Subtarget);
32490b57cec5SDimitry Andric case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
32500b57cec5SDimitry Andric case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
32510b57cec5SDimitry Andric case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
32520b57cec5SDimitry Andric case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
32530b57cec5SDimitry Andric case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG, *this,
32540b57cec5SDimitry Andric hasHardQuad);
32550b57cec5SDimitry Andric case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG, *this,
32560b57cec5SDimitry Andric hasHardQuad);
32570b57cec5SDimitry Andric case ISD::FP_TO_UINT: return LowerFP_TO_UINT(Op, DAG, *this,
32580b57cec5SDimitry Andric hasHardQuad);
32590b57cec5SDimitry Andric case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG, *this,
32600b57cec5SDimitry Andric hasHardQuad);
3261bdd1243dSDimitry Andric case ISD::BR_CC:
326206c3fb27SDimitry Andric return LowerBR_CC(Op, DAG, *this, hasHardQuad, isV9, is64Bit);
3263bdd1243dSDimitry Andric case ISD::SELECT_CC:
3264bdd1243dSDimitry Andric return LowerSELECT_CC(Op, DAG, *this, hasHardQuad, isV9, is64Bit);
32650b57cec5SDimitry Andric case ISD::VASTART: return LowerVASTART(Op, DAG, *this);
32660b57cec5SDimitry Andric case ISD::VAARG: return LowerVAARG(Op, DAG);
32670b57cec5SDimitry Andric case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG,
32680b57cec5SDimitry Andric Subtarget);
32690b57cec5SDimitry Andric
32700b57cec5SDimitry Andric case ISD::LOAD: return LowerLOAD(Op, DAG);
32710b57cec5SDimitry Andric case ISD::STORE: return LowerSTORE(Op, DAG);
32720b57cec5SDimitry Andric case ISD::FADD: return LowerF128Op(Op, DAG,
32730b57cec5SDimitry Andric getLibcallName(RTLIB::ADD_F128), 2);
32740b57cec5SDimitry Andric case ISD::FSUB: return LowerF128Op(Op, DAG,
32750b57cec5SDimitry Andric getLibcallName(RTLIB::SUB_F128), 2);
32760b57cec5SDimitry Andric case ISD::FMUL: return LowerF128Op(Op, DAG,
32770b57cec5SDimitry Andric getLibcallName(RTLIB::MUL_F128), 2);
32780b57cec5SDimitry Andric case ISD::FDIV: return LowerF128Op(Op, DAG,
32790b57cec5SDimitry Andric getLibcallName(RTLIB::DIV_F128), 2);
32800b57cec5SDimitry Andric case ISD::FSQRT: return LowerF128Op(Op, DAG,
32810b57cec5SDimitry Andric getLibcallName(RTLIB::SQRT_F128),1);
32820b57cec5SDimitry Andric case ISD::FABS:
32830b57cec5SDimitry Andric case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9);
32840b57cec5SDimitry Andric case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, *this);
32850b57cec5SDimitry Andric case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, *this);
32860b57cec5SDimitry Andric case ISD::ADDC:
32870b57cec5SDimitry Andric case ISD::ADDE:
32880b57cec5SDimitry Andric case ISD::SUBC:
32890b57cec5SDimitry Andric case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
32900b57cec5SDimitry Andric case ISD::UMULO:
32910b57cec5SDimitry Andric case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this);
32920b57cec5SDimitry Andric case ISD::ATOMIC_LOAD:
32930b57cec5SDimitry Andric case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG);
32940b57cec5SDimitry Andric case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
32950b57cec5SDimitry Andric }
32960b57cec5SDimitry Andric }
32970b57cec5SDimitry Andric
bitcastConstantFPToInt(ConstantFPSDNode * C,const SDLoc & DL,SelectionDAG & DAG) const32980b57cec5SDimitry Andric SDValue SparcTargetLowering::bitcastConstantFPToInt(ConstantFPSDNode *C,
32990b57cec5SDimitry Andric const SDLoc &DL,
33000b57cec5SDimitry Andric SelectionDAG &DAG) const {
33010b57cec5SDimitry Andric APInt V = C->getValueAPF().bitcastToAPInt();
33020b57cec5SDimitry Andric SDValue Lo = DAG.getConstant(V.zextOrTrunc(32), DL, MVT::i32);
33030b57cec5SDimitry Andric SDValue Hi = DAG.getConstant(V.lshr(32).zextOrTrunc(32), DL, MVT::i32);
33040b57cec5SDimitry Andric if (DAG.getDataLayout().isLittleEndian())
33050b57cec5SDimitry Andric std::swap(Lo, Hi);
33060b57cec5SDimitry Andric return DAG.getBuildVector(MVT::v2i32, DL, {Hi, Lo});
33070b57cec5SDimitry Andric }
33080b57cec5SDimitry Andric
PerformBITCASTCombine(SDNode * N,DAGCombinerInfo & DCI) const33090b57cec5SDimitry Andric SDValue SparcTargetLowering::PerformBITCASTCombine(SDNode *N,
33100b57cec5SDimitry Andric DAGCombinerInfo &DCI) const {
33110b57cec5SDimitry Andric SDLoc dl(N);
33120b57cec5SDimitry Andric SDValue Src = N->getOperand(0);
33130b57cec5SDimitry Andric
33140b57cec5SDimitry Andric if (isa<ConstantFPSDNode>(Src) && N->getSimpleValueType(0) == MVT::v2i32 &&
33150b57cec5SDimitry Andric Src.getSimpleValueType() == MVT::f64)
33160b57cec5SDimitry Andric return bitcastConstantFPToInt(cast<ConstantFPSDNode>(Src), dl, DCI.DAG);
33170b57cec5SDimitry Andric
33180b57cec5SDimitry Andric return SDValue();
33190b57cec5SDimitry Andric }
33200b57cec5SDimitry Andric
PerformDAGCombine(SDNode * N,DAGCombinerInfo & DCI) const33210b57cec5SDimitry Andric SDValue SparcTargetLowering::PerformDAGCombine(SDNode *N,
33220b57cec5SDimitry Andric DAGCombinerInfo &DCI) const {
33230b57cec5SDimitry Andric switch (N->getOpcode()) {
33240b57cec5SDimitry Andric default:
33250b57cec5SDimitry Andric break;
33260b57cec5SDimitry Andric case ISD::BITCAST:
33270b57cec5SDimitry Andric return PerformBITCASTCombine(N, DCI);
33280b57cec5SDimitry Andric }
33290b57cec5SDimitry Andric return SDValue();
33300b57cec5SDimitry Andric }
33310b57cec5SDimitry Andric
33320b57cec5SDimitry Andric MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const33330b57cec5SDimitry Andric SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
33340b57cec5SDimitry Andric MachineBasicBlock *BB) const {
33350b57cec5SDimitry Andric switch (MI.getOpcode()) {
33360b57cec5SDimitry Andric default: llvm_unreachable("Unknown SELECT_CC!");
33370b57cec5SDimitry Andric case SP::SELECT_CC_Int_ICC:
33380b57cec5SDimitry Andric case SP::SELECT_CC_FP_ICC:
33390b57cec5SDimitry Andric case SP::SELECT_CC_DFP_ICC:
33400b57cec5SDimitry Andric case SP::SELECT_CC_QFP_ICC:
3341bdd1243dSDimitry Andric if (Subtarget->isV9())
3342bdd1243dSDimitry Andric return expandSelectCC(MI, BB, SP::BPICC);
33430b57cec5SDimitry Andric return expandSelectCC(MI, BB, SP::BCOND);
334481ad6265SDimitry Andric case SP::SELECT_CC_Int_XCC:
334581ad6265SDimitry Andric case SP::SELECT_CC_FP_XCC:
334681ad6265SDimitry Andric case SP::SELECT_CC_DFP_XCC:
334781ad6265SDimitry Andric case SP::SELECT_CC_QFP_XCC:
334881ad6265SDimitry Andric return expandSelectCC(MI, BB, SP::BPXCC);
33490b57cec5SDimitry Andric case SP::SELECT_CC_Int_FCC:
33500b57cec5SDimitry Andric case SP::SELECT_CC_FP_FCC:
33510b57cec5SDimitry Andric case SP::SELECT_CC_DFP_FCC:
33520b57cec5SDimitry Andric case SP::SELECT_CC_QFP_FCC:
3353bdd1243dSDimitry Andric if (Subtarget->isV9())
3354bdd1243dSDimitry Andric return expandSelectCC(MI, BB, SP::FBCOND_V9);
33550b57cec5SDimitry Andric return expandSelectCC(MI, BB, SP::FBCOND);
33560b57cec5SDimitry Andric }
33570b57cec5SDimitry Andric }
33580b57cec5SDimitry Andric
33590b57cec5SDimitry Andric MachineBasicBlock *
expandSelectCC(MachineInstr & MI,MachineBasicBlock * BB,unsigned BROpcode) const33600b57cec5SDimitry Andric SparcTargetLowering::expandSelectCC(MachineInstr &MI, MachineBasicBlock *BB,
33610b57cec5SDimitry Andric unsigned BROpcode) const {
33620b57cec5SDimitry Andric const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
33630b57cec5SDimitry Andric DebugLoc dl = MI.getDebugLoc();
33640b57cec5SDimitry Andric unsigned CC = (SPCC::CondCodes)MI.getOperand(3).getImm();
33650b57cec5SDimitry Andric
33660b57cec5SDimitry Andric // To "insert" a SELECT_CC instruction, we actually have to insert the
33670b57cec5SDimitry Andric // triangle control-flow pattern. The incoming instruction knows the
33680b57cec5SDimitry Andric // destination vreg to set, the condition code register to branch on, the
33690b57cec5SDimitry Andric // true/false values to select between, and the condition code for the branch.
33700b57cec5SDimitry Andric //
33710b57cec5SDimitry Andric // We produce the following control flow:
33720b57cec5SDimitry Andric // ThisMBB
33730b57cec5SDimitry Andric // | \
33740b57cec5SDimitry Andric // | IfFalseMBB
33750b57cec5SDimitry Andric // | /
33760b57cec5SDimitry Andric // SinkMBB
33770b57cec5SDimitry Andric const BasicBlock *LLVM_BB = BB->getBasicBlock();
33780b57cec5SDimitry Andric MachineFunction::iterator It = ++BB->getIterator();
33790b57cec5SDimitry Andric
33800b57cec5SDimitry Andric MachineBasicBlock *ThisMBB = BB;
33810b57cec5SDimitry Andric MachineFunction *F = BB->getParent();
33820b57cec5SDimitry Andric MachineBasicBlock *IfFalseMBB = F->CreateMachineBasicBlock(LLVM_BB);
33830b57cec5SDimitry Andric MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
33840b57cec5SDimitry Andric F->insert(It, IfFalseMBB);
33850b57cec5SDimitry Andric F->insert(It, SinkMBB);
33860b57cec5SDimitry Andric
33870b57cec5SDimitry Andric // Transfer the remainder of ThisMBB and its successor edges to SinkMBB.
33880b57cec5SDimitry Andric SinkMBB->splice(SinkMBB->begin(), ThisMBB,
33890b57cec5SDimitry Andric std::next(MachineBasicBlock::iterator(MI)), ThisMBB->end());
33900b57cec5SDimitry Andric SinkMBB->transferSuccessorsAndUpdatePHIs(ThisMBB);
33910b57cec5SDimitry Andric
33920b57cec5SDimitry Andric // Set the new successors for ThisMBB.
33930b57cec5SDimitry Andric ThisMBB->addSuccessor(IfFalseMBB);
33940b57cec5SDimitry Andric ThisMBB->addSuccessor(SinkMBB);
33950b57cec5SDimitry Andric
33960b57cec5SDimitry Andric BuildMI(ThisMBB, dl, TII.get(BROpcode))
33970b57cec5SDimitry Andric .addMBB(SinkMBB)
33980b57cec5SDimitry Andric .addImm(CC);
33990b57cec5SDimitry Andric
34000b57cec5SDimitry Andric // IfFalseMBB just falls through to SinkMBB.
34010b57cec5SDimitry Andric IfFalseMBB->addSuccessor(SinkMBB);
34020b57cec5SDimitry Andric
34030b57cec5SDimitry Andric // %Result = phi [ %TrueValue, ThisMBB ], [ %FalseValue, IfFalseMBB ]
34040b57cec5SDimitry Andric BuildMI(*SinkMBB, SinkMBB->begin(), dl, TII.get(SP::PHI),
34050b57cec5SDimitry Andric MI.getOperand(0).getReg())
34060b57cec5SDimitry Andric .addReg(MI.getOperand(1).getReg())
34070b57cec5SDimitry Andric .addMBB(ThisMBB)
34080b57cec5SDimitry Andric .addReg(MI.getOperand(2).getReg())
34090b57cec5SDimitry Andric .addMBB(IfFalseMBB);
34100b57cec5SDimitry Andric
34110b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
34120b57cec5SDimitry Andric return SinkMBB;
34130b57cec5SDimitry Andric }
34140b57cec5SDimitry Andric
34150b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
34160b57cec5SDimitry Andric // Sparc Inline Assembly Support
34170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
34180b57cec5SDimitry Andric
34190b57cec5SDimitry Andric /// getConstraintType - Given a constraint letter, return the type of
34200b57cec5SDimitry Andric /// constraint it is for this target.
34210b57cec5SDimitry Andric SparcTargetLowering::ConstraintType
getConstraintType(StringRef Constraint) const34220b57cec5SDimitry Andric SparcTargetLowering::getConstraintType(StringRef Constraint) const {
34230b57cec5SDimitry Andric if (Constraint.size() == 1) {
34240b57cec5SDimitry Andric switch (Constraint[0]) {
34250b57cec5SDimitry Andric default: break;
34260b57cec5SDimitry Andric case 'r':
34270b57cec5SDimitry Andric case 'f':
34280b57cec5SDimitry Andric case 'e':
34290b57cec5SDimitry Andric return C_RegisterClass;
34300b57cec5SDimitry Andric case 'I': // SIMM13
34310b57cec5SDimitry Andric return C_Immediate;
34320b57cec5SDimitry Andric }
34330b57cec5SDimitry Andric }
34340b57cec5SDimitry Andric
34350b57cec5SDimitry Andric return TargetLowering::getConstraintType(Constraint);
34360b57cec5SDimitry Andric }
34370b57cec5SDimitry Andric
34380b57cec5SDimitry Andric TargetLowering::ConstraintWeight SparcTargetLowering::
getSingleConstraintMatchWeight(AsmOperandInfo & info,const char * constraint) const34390b57cec5SDimitry Andric getSingleConstraintMatchWeight(AsmOperandInfo &info,
34400b57cec5SDimitry Andric const char *constraint) const {
34410b57cec5SDimitry Andric ConstraintWeight weight = CW_Invalid;
34420b57cec5SDimitry Andric Value *CallOperandVal = info.CallOperandVal;
34430b57cec5SDimitry Andric // If we don't have a value, we can't do a match,
34440b57cec5SDimitry Andric // but allow it at the lowest weight.
34450b57cec5SDimitry Andric if (!CallOperandVal)
34460b57cec5SDimitry Andric return CW_Default;
34470b57cec5SDimitry Andric
34480b57cec5SDimitry Andric // Look at the constraint type.
34490b57cec5SDimitry Andric switch (*constraint) {
34500b57cec5SDimitry Andric default:
34510b57cec5SDimitry Andric weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
34520b57cec5SDimitry Andric break;
34530b57cec5SDimitry Andric case 'I': // SIMM13
34540b57cec5SDimitry Andric if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
34550b57cec5SDimitry Andric if (isInt<13>(C->getSExtValue()))
34560b57cec5SDimitry Andric weight = CW_Constant;
34570b57cec5SDimitry Andric }
34580b57cec5SDimitry Andric break;
34590b57cec5SDimitry Andric }
34600b57cec5SDimitry Andric return weight;
34610b57cec5SDimitry Andric }
34620b57cec5SDimitry Andric
34630b57cec5SDimitry Andric /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
34640b57cec5SDimitry Andric /// vector. If it is invalid, don't add anything to Ops.
LowerAsmOperandForConstraint(SDValue Op,StringRef Constraint,std::vector<SDValue> & Ops,SelectionDAG & DAG) const34655f757f3fSDimitry Andric void SparcTargetLowering::LowerAsmOperandForConstraint(
34665f757f3fSDimitry Andric SDValue Op, StringRef Constraint, std::vector<SDValue> &Ops,
34670b57cec5SDimitry Andric SelectionDAG &DAG) const {
346804eeddc0SDimitry Andric SDValue Result;
34690b57cec5SDimitry Andric
34700b57cec5SDimitry Andric // Only support length 1 constraints for now.
34715f757f3fSDimitry Andric if (Constraint.size() > 1)
34720b57cec5SDimitry Andric return;
34730b57cec5SDimitry Andric
34740b57cec5SDimitry Andric char ConstraintLetter = Constraint[0];
34750b57cec5SDimitry Andric switch (ConstraintLetter) {
34760b57cec5SDimitry Andric default: break;
34770b57cec5SDimitry Andric case 'I':
34780b57cec5SDimitry Andric if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
34790b57cec5SDimitry Andric if (isInt<13>(C->getSExtValue())) {
34800b57cec5SDimitry Andric Result = DAG.getTargetConstant(C->getSExtValue(), SDLoc(Op),
34810b57cec5SDimitry Andric Op.getValueType());
34820b57cec5SDimitry Andric break;
34830b57cec5SDimitry Andric }
34840b57cec5SDimitry Andric return;
34850b57cec5SDimitry Andric }
34860b57cec5SDimitry Andric }
34870b57cec5SDimitry Andric
34880b57cec5SDimitry Andric if (Result.getNode()) {
34890b57cec5SDimitry Andric Ops.push_back(Result);
34900b57cec5SDimitry Andric return;
34910b57cec5SDimitry Andric }
34920b57cec5SDimitry Andric TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
34930b57cec5SDimitry Andric }
34940b57cec5SDimitry Andric
34950b57cec5SDimitry Andric std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo * TRI,StringRef Constraint,MVT VT) const34960b57cec5SDimitry Andric SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
34970b57cec5SDimitry Andric StringRef Constraint,
34980b57cec5SDimitry Andric MVT VT) const {
349981ad6265SDimitry Andric if (Constraint.empty())
350081ad6265SDimitry Andric return std::make_pair(0U, nullptr);
350181ad6265SDimitry Andric
35020b57cec5SDimitry Andric if (Constraint.size() == 1) {
35030b57cec5SDimitry Andric switch (Constraint[0]) {
35040b57cec5SDimitry Andric case 'r':
35050b57cec5SDimitry Andric if (VT == MVT::v2i32)
35060b57cec5SDimitry Andric return std::make_pair(0U, &SP::IntPairRegClass);
35070b57cec5SDimitry Andric else if (Subtarget->is64Bit())
35080b57cec5SDimitry Andric return std::make_pair(0U, &SP::I64RegsRegClass);
35090b57cec5SDimitry Andric else
35100b57cec5SDimitry Andric return std::make_pair(0U, &SP::IntRegsRegClass);
35110b57cec5SDimitry Andric case 'f':
35120b57cec5SDimitry Andric if (VT == MVT::f32 || VT == MVT::i32)
35130b57cec5SDimitry Andric return std::make_pair(0U, &SP::FPRegsRegClass);
35140b57cec5SDimitry Andric else if (VT == MVT::f64 || VT == MVT::i64)
35150b57cec5SDimitry Andric return std::make_pair(0U, &SP::LowDFPRegsRegClass);
35160b57cec5SDimitry Andric else if (VT == MVT::f128)
35170b57cec5SDimitry Andric return std::make_pair(0U, &SP::LowQFPRegsRegClass);
35180b57cec5SDimitry Andric // This will generate an error message
35190b57cec5SDimitry Andric return std::make_pair(0U, nullptr);
35200b57cec5SDimitry Andric case 'e':
35210b57cec5SDimitry Andric if (VT == MVT::f32 || VT == MVT::i32)
35220b57cec5SDimitry Andric return std::make_pair(0U, &SP::FPRegsRegClass);
35230b57cec5SDimitry Andric else if (VT == MVT::f64 || VT == MVT::i64 )
35240b57cec5SDimitry Andric return std::make_pair(0U, &SP::DFPRegsRegClass);
35250b57cec5SDimitry Andric else if (VT == MVT::f128)
35260b57cec5SDimitry Andric return std::make_pair(0U, &SP::QFPRegsRegClass);
35270b57cec5SDimitry Andric // This will generate an error message
35280b57cec5SDimitry Andric return std::make_pair(0U, nullptr);
35290b57cec5SDimitry Andric }
353081ad6265SDimitry Andric }
353181ad6265SDimitry Andric
353281ad6265SDimitry Andric if (Constraint.front() != '{')
353381ad6265SDimitry Andric return std::make_pair(0U, nullptr);
353481ad6265SDimitry Andric
353581ad6265SDimitry Andric assert(Constraint.back() == '}' && "Not a brace enclosed constraint?");
353681ad6265SDimitry Andric StringRef RegName(Constraint.data() + 1, Constraint.size() - 2);
353781ad6265SDimitry Andric if (RegName.empty())
353881ad6265SDimitry Andric return std::make_pair(0U, nullptr);
353981ad6265SDimitry Andric
354081ad6265SDimitry Andric unsigned long long RegNo;
354181ad6265SDimitry Andric // Handle numbered register aliases.
354281ad6265SDimitry Andric if (RegName[0] == 'r' &&
354381ad6265SDimitry Andric getAsUnsignedInteger(RegName.begin() + 1, 10, RegNo)) {
35440b57cec5SDimitry Andric // r0-r7 -> g0-g7
35450b57cec5SDimitry Andric // r8-r15 -> o0-o7
35460b57cec5SDimitry Andric // r16-r23 -> l0-l7
35470b57cec5SDimitry Andric // r24-r31 -> i0-i7
354881ad6265SDimitry Andric if (RegNo > 31)
354981ad6265SDimitry Andric return std::make_pair(0U, nullptr);
355081ad6265SDimitry Andric const char RegTypes[] = {'g', 'o', 'l', 'i'};
355181ad6265SDimitry Andric char RegType = RegTypes[RegNo / 8];
355281ad6265SDimitry Andric char RegIndex = '0' + (RegNo % 8);
355381ad6265SDimitry Andric char Tmp[] = {'{', RegType, RegIndex, '}', 0};
355481ad6265SDimitry Andric return getRegForInlineAsmConstraint(TRI, Tmp, VT);
35550b57cec5SDimitry Andric }
35560b57cec5SDimitry Andric
355781ad6265SDimitry Andric // Rewrite the fN constraint according to the value type if needed.
355881ad6265SDimitry Andric if (VT != MVT::f32 && VT != MVT::Other && RegName[0] == 'f' &&
355981ad6265SDimitry Andric getAsUnsignedInteger(RegName.begin() + 1, 10, RegNo)) {
356081ad6265SDimitry Andric if (VT == MVT::f64 && (RegNo % 2 == 0)) {
356181ad6265SDimitry Andric return getRegForInlineAsmConstraint(
356281ad6265SDimitry Andric TRI, StringRef("{d" + utostr(RegNo / 2) + "}"), VT);
356381ad6265SDimitry Andric } else if (VT == MVT::f128 && (RegNo % 4 == 0)) {
356481ad6265SDimitry Andric return getRegForInlineAsmConstraint(
356581ad6265SDimitry Andric TRI, StringRef("{q" + utostr(RegNo / 4) + "}"), VT);
35660b57cec5SDimitry Andric } else {
35670b57cec5SDimitry Andric return std::make_pair(0U, nullptr);
35680b57cec5SDimitry Andric }
35690b57cec5SDimitry Andric }
35700b57cec5SDimitry Andric
357181ad6265SDimitry Andric auto ResultPair =
357281ad6265SDimitry Andric TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
357381ad6265SDimitry Andric if (!ResultPair.second)
357481ad6265SDimitry Andric return std::make_pair(0U, nullptr);
357581ad6265SDimitry Andric
357681ad6265SDimitry Andric // Force the use of I64Regs over IntRegs for 64-bit values.
357781ad6265SDimitry Andric if (Subtarget->is64Bit() && VT == MVT::i64) {
357881ad6265SDimitry Andric assert(ResultPair.second == &SP::IntRegsRegClass &&
357981ad6265SDimitry Andric "Unexpected register class");
358081ad6265SDimitry Andric return std::make_pair(ResultPair.first, &SP::I64RegsRegClass);
358181ad6265SDimitry Andric }
358281ad6265SDimitry Andric
358381ad6265SDimitry Andric return ResultPair;
35840b57cec5SDimitry Andric }
35850b57cec5SDimitry Andric
35860b57cec5SDimitry Andric bool
isOffsetFoldingLegal(const GlobalAddressSDNode * GA) const35870b57cec5SDimitry Andric SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
35880b57cec5SDimitry Andric // The Sparc target isn't yet aware of offsets.
35890b57cec5SDimitry Andric return false;
35900b57cec5SDimitry Andric }
35910b57cec5SDimitry Andric
ReplaceNodeResults(SDNode * N,SmallVectorImpl<SDValue> & Results,SelectionDAG & DAG) const35920b57cec5SDimitry Andric void SparcTargetLowering::ReplaceNodeResults(SDNode *N,
35930b57cec5SDimitry Andric SmallVectorImpl<SDValue>& Results,
35940b57cec5SDimitry Andric SelectionDAG &DAG) const {
35950b57cec5SDimitry Andric
35960b57cec5SDimitry Andric SDLoc dl(N);
35970b57cec5SDimitry Andric
35980b57cec5SDimitry Andric RTLIB::Libcall libCall = RTLIB::UNKNOWN_LIBCALL;
35990b57cec5SDimitry Andric
36000b57cec5SDimitry Andric switch (N->getOpcode()) {
36010b57cec5SDimitry Andric default:
36020b57cec5SDimitry Andric llvm_unreachable("Do not know how to custom type legalize this operation!");
36030b57cec5SDimitry Andric
36040b57cec5SDimitry Andric case ISD::FP_TO_SINT:
36050b57cec5SDimitry Andric case ISD::FP_TO_UINT:
36060b57cec5SDimitry Andric // Custom lower only if it involves f128 or i64.
36070b57cec5SDimitry Andric if (N->getOperand(0).getValueType() != MVT::f128
36080b57cec5SDimitry Andric || N->getValueType(0) != MVT::i64)
36090b57cec5SDimitry Andric return;
36100b57cec5SDimitry Andric libCall = ((N->getOpcode() == ISD::FP_TO_SINT)
36110b57cec5SDimitry Andric ? RTLIB::FPTOSINT_F128_I64
36120b57cec5SDimitry Andric : RTLIB::FPTOUINT_F128_I64);
36130b57cec5SDimitry Andric
36140b57cec5SDimitry Andric Results.push_back(LowerF128Op(SDValue(N, 0),
36150b57cec5SDimitry Andric DAG,
36160b57cec5SDimitry Andric getLibcallName(libCall),
36170b57cec5SDimitry Andric 1));
36180b57cec5SDimitry Andric return;
36190b57cec5SDimitry Andric case ISD::READCYCLECOUNTER: {
36200b57cec5SDimitry Andric assert(Subtarget->hasLeonCycleCounter());
36210b57cec5SDimitry Andric SDValue Lo = DAG.getCopyFromReg(N->getOperand(0), dl, SP::ASR23, MVT::i32);
36220b57cec5SDimitry Andric SDValue Hi = DAG.getCopyFromReg(Lo, dl, SP::G0, MVT::i32);
36230b57cec5SDimitry Andric SDValue Ops[] = { Lo, Hi };
36240b57cec5SDimitry Andric SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Ops);
36250b57cec5SDimitry Andric Results.push_back(Pair);
36260b57cec5SDimitry Andric Results.push_back(N->getOperand(0));
36270b57cec5SDimitry Andric return;
36280b57cec5SDimitry Andric }
36290b57cec5SDimitry Andric case ISD::SINT_TO_FP:
36300b57cec5SDimitry Andric case ISD::UINT_TO_FP:
36310b57cec5SDimitry Andric // Custom lower only if it involves f128 or i64.
36320b57cec5SDimitry Andric if (N->getValueType(0) != MVT::f128
36330b57cec5SDimitry Andric || N->getOperand(0).getValueType() != MVT::i64)
36340b57cec5SDimitry Andric return;
36350b57cec5SDimitry Andric
36360b57cec5SDimitry Andric libCall = ((N->getOpcode() == ISD::SINT_TO_FP)
36370b57cec5SDimitry Andric ? RTLIB::SINTTOFP_I64_F128
36380b57cec5SDimitry Andric : RTLIB::UINTTOFP_I64_F128);
36390b57cec5SDimitry Andric
36400b57cec5SDimitry Andric Results.push_back(LowerF128Op(SDValue(N, 0),
36410b57cec5SDimitry Andric DAG,
36420b57cec5SDimitry Andric getLibcallName(libCall),
36430b57cec5SDimitry Andric 1));
36440b57cec5SDimitry Andric return;
36450b57cec5SDimitry Andric case ISD::LOAD: {
36460b57cec5SDimitry Andric LoadSDNode *Ld = cast<LoadSDNode>(N);
36470b57cec5SDimitry Andric // Custom handling only for i64: turn i64 load into a v2i32 load,
36480b57cec5SDimitry Andric // and a bitcast.
36490b57cec5SDimitry Andric if (Ld->getValueType(0) != MVT::i64 || Ld->getMemoryVT() != MVT::i64)
36500b57cec5SDimitry Andric return;
36510b57cec5SDimitry Andric
36520b57cec5SDimitry Andric SDLoc dl(N);
36530b57cec5SDimitry Andric SDValue LoadRes = DAG.getExtLoad(
36540b57cec5SDimitry Andric Ld->getExtensionType(), dl, MVT::v2i32, Ld->getChain(),
3655e8d8bef9SDimitry Andric Ld->getBasePtr(), Ld->getPointerInfo(), MVT::v2i32,
3656e8d8bef9SDimitry Andric Ld->getOriginalAlign(), Ld->getMemOperand()->getFlags(),
3657e8d8bef9SDimitry Andric Ld->getAAInfo());
36580b57cec5SDimitry Andric
36590b57cec5SDimitry Andric SDValue Res = DAG.getNode(ISD::BITCAST, dl, MVT::i64, LoadRes);
36600b57cec5SDimitry Andric Results.push_back(Res);
36610b57cec5SDimitry Andric Results.push_back(LoadRes.getValue(1));
36620b57cec5SDimitry Andric return;
36630b57cec5SDimitry Andric }
36640b57cec5SDimitry Andric }
36650b57cec5SDimitry Andric }
36660b57cec5SDimitry Andric
36670b57cec5SDimitry Andric // Override to enable LOAD_STACK_GUARD lowering on Linux.
useLoadStackGuardNode() const36680b57cec5SDimitry Andric bool SparcTargetLowering::useLoadStackGuardNode() const {
36690b57cec5SDimitry Andric if (!Subtarget->isTargetLinux())
36700b57cec5SDimitry Andric return TargetLowering::useLoadStackGuardNode();
36710b57cec5SDimitry Andric return true;
36720b57cec5SDimitry Andric }
36730b57cec5SDimitry Andric
36740b57cec5SDimitry Andric // Override to disable global variable loading on Linux.
insertSSPDeclarations(Module & M) const36750b57cec5SDimitry Andric void SparcTargetLowering::insertSSPDeclarations(Module &M) const {
36760b57cec5SDimitry Andric if (!Subtarget->isTargetLinux())
36770b57cec5SDimitry Andric return TargetLowering::insertSSPDeclarations(M);
36780b57cec5SDimitry Andric }
36795f757f3fSDimitry Andric
AdjustInstrPostInstrSelection(MachineInstr & MI,SDNode * Node) const36805f757f3fSDimitry Andric void SparcTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI,
36815f757f3fSDimitry Andric SDNode *Node) const {
36825f757f3fSDimitry Andric assert(MI.getOpcode() == SP::SUBCCrr || MI.getOpcode() == SP::SUBCCri);
36835f757f3fSDimitry Andric // If the result is dead, replace it with %g0.
36845f757f3fSDimitry Andric if (!Node->hasAnyUseOfValue(0))
36855f757f3fSDimitry Andric MI.getOperand(0).setReg(SP::G0);
36865f757f3fSDimitry Andric }
3687