xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Sparc/SparcISelLowering.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
160b57cec5SDimitry Andric #include "SparcMachineFunctionInfo.h"
170b57cec5SDimitry Andric #include "SparcRegisterInfo.h"
180b57cec5SDimitry Andric #include "SparcTargetMachine.h"
190b57cec5SDimitry Andric #include "SparcTargetObjectFile.h"
200b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
28*bdd1243dSDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
300b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
310b57cec5SDimitry Andric #include "llvm/IR/Function.h"
320b57cec5SDimitry Andric #include "llvm/IR/Module.h"
330b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
340b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h"
350b57cec5SDimitry Andric using namespace llvm;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
390b57cec5SDimitry Andric // Calling Convention Implementation
400b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric static bool CC_Sparc_Assign_SRet(unsigned &ValNo, MVT &ValVT,
430b57cec5SDimitry Andric                                  MVT &LocVT, CCValAssign::LocInfo &LocInfo,
440b57cec5SDimitry Andric                                  ISD::ArgFlagsTy &ArgFlags, CCState &State)
450b57cec5SDimitry Andric {
460b57cec5SDimitry Andric   assert (ArgFlags.isSRet());
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   // Assign SRet argument.
490b57cec5SDimitry Andric   State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
500b57cec5SDimitry Andric                                          0,
510b57cec5SDimitry Andric                                          LocVT, LocInfo));
520b57cec5SDimitry Andric   return true;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric static bool CC_Sparc_Assign_Split_64(unsigned &ValNo, MVT &ValVT,
560b57cec5SDimitry Andric                                      MVT &LocVT, CCValAssign::LocInfo &LocInfo,
570b57cec5SDimitry Andric                                      ISD::ArgFlagsTy &ArgFlags, CCState &State)
580b57cec5SDimitry Andric {
590b57cec5SDimitry Andric   static const MCPhysReg RegList[] = {
600b57cec5SDimitry Andric     SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
610b57cec5SDimitry Andric   };
620b57cec5SDimitry Andric   // Try to get first reg.
635ffd83dbSDimitry Andric   if (Register Reg = State.AllocateReg(RegList)) {
640b57cec5SDimitry Andric     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
650b57cec5SDimitry Andric   } else {
660b57cec5SDimitry Andric     // Assign whole thing in stack.
675ffd83dbSDimitry Andric     State.addLoc(CCValAssign::getCustomMem(
685ffd83dbSDimitry Andric         ValNo, ValVT, State.AllocateStack(8, Align(4)), LocVT, LocInfo));
690b57cec5SDimitry Andric     return true;
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   // Try to get second reg.
735ffd83dbSDimitry Andric   if (Register Reg = State.AllocateReg(RegList))
740b57cec5SDimitry Andric     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
750b57cec5SDimitry Andric   else
765ffd83dbSDimitry Andric     State.addLoc(CCValAssign::getCustomMem(
775ffd83dbSDimitry Andric         ValNo, ValVT, State.AllocateStack(4, Align(4)), LocVT, LocInfo));
780b57cec5SDimitry Andric   return true;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT,
820b57cec5SDimitry Andric                                          MVT &LocVT, CCValAssign::LocInfo &LocInfo,
830b57cec5SDimitry Andric                                          ISD::ArgFlagsTy &ArgFlags, CCState &State)
840b57cec5SDimitry Andric {
850b57cec5SDimitry Andric   static const MCPhysReg RegList[] = {
860b57cec5SDimitry Andric     SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
870b57cec5SDimitry Andric   };
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   // Try to get first reg.
905ffd83dbSDimitry Andric   if (Register Reg = State.AllocateReg(RegList))
910b57cec5SDimitry Andric     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
920b57cec5SDimitry Andric   else
930b57cec5SDimitry Andric     return false;
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // Try to get second reg.
965ffd83dbSDimitry Andric   if (Register Reg = State.AllocateReg(RegList))
970b57cec5SDimitry Andric     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
980b57cec5SDimitry Andric   else
990b57cec5SDimitry Andric     return false;
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   return true;
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric // Allocate a full-sized argument for the 64-bit ABI.
105f3fd488fSDimitry Andric static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT,
1060b57cec5SDimitry Andric                                     MVT &LocVT, CCValAssign::LocInfo &LocInfo,
1070b57cec5SDimitry Andric                                     ISD::ArgFlagsTy &ArgFlags, CCState &State) {
1080b57cec5SDimitry Andric   assert((LocVT == MVT::f32 || LocVT == MVT::f128
1090b57cec5SDimitry Andric           || LocVT.getSizeInBits() == 64) &&
1100b57cec5SDimitry Andric          "Can't handle non-64 bits locations");
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   // Stack space is allocated for all arguments starting from [%fp+BIAS+128].
1130b57cec5SDimitry Andric   unsigned size      = (LocVT == MVT::f128) ? 16 : 8;
1145ffd83dbSDimitry Andric   Align alignment = (LocVT == MVT::f128) ? Align(16) : Align(8);
1150b57cec5SDimitry Andric   unsigned Offset = State.AllocateStack(size, alignment);
1160b57cec5SDimitry Andric   unsigned Reg = 0;
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   if (LocVT == MVT::i64 && Offset < 6*8)
1190b57cec5SDimitry Andric     // Promote integers to %i0-%i5.
1200b57cec5SDimitry Andric     Reg = SP::I0 + Offset/8;
1210b57cec5SDimitry Andric   else if (LocVT == MVT::f64 && Offset < 16*8)
1220b57cec5SDimitry Andric     // Promote doubles to %d0-%d30. (Which LLVM calls D0-D15).
1230b57cec5SDimitry Andric     Reg = SP::D0 + Offset/8;
1240b57cec5SDimitry Andric   else if (LocVT == MVT::f32 && Offset < 16*8)
1250b57cec5SDimitry Andric     // Promote floats to %f1, %f3, ...
1260b57cec5SDimitry Andric     Reg = SP::F1 + Offset/4;
1270b57cec5SDimitry Andric   else if (LocVT == MVT::f128 && Offset < 16*8)
1280b57cec5SDimitry Andric     // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7).
1290b57cec5SDimitry Andric     Reg = SP::Q0 + Offset/16;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   // Promote to register when possible, otherwise use the stack slot.
1320b57cec5SDimitry Andric   if (Reg) {
1330b57cec5SDimitry Andric     State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
1340b57cec5SDimitry Andric     return true;
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric 
137f3fd488fSDimitry Andric   // Bail out if this is a return CC and we run out of registers to place
138f3fd488fSDimitry Andric   // values into.
139f3fd488fSDimitry Andric   if (IsReturn)
140f3fd488fSDimitry Andric     return false;
141f3fd488fSDimitry Andric 
1420b57cec5SDimitry Andric   // This argument goes on the stack in an 8-byte slot.
1430b57cec5SDimitry Andric   // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to
1440b57cec5SDimitry Andric   // the right-aligned float. The first 4 bytes of the stack slot are undefined.
1450b57cec5SDimitry Andric   if (LocVT == MVT::f32)
1460b57cec5SDimitry Andric     Offset += 4;
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
1490b57cec5SDimitry Andric   return true;
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric // Allocate a half-sized argument for the 64-bit ABI.
1530b57cec5SDimitry Andric //
1540b57cec5SDimitry Andric // This is used when passing { float, int } structs by value in registers.
155f3fd488fSDimitry Andric static bool Analyze_CC_Sparc64_Half(bool IsReturn, unsigned &ValNo, MVT &ValVT,
1560b57cec5SDimitry Andric                                     MVT &LocVT, CCValAssign::LocInfo &LocInfo,
1570b57cec5SDimitry Andric                                     ISD::ArgFlagsTy &ArgFlags, CCState &State) {
1580b57cec5SDimitry Andric   assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations");
1595ffd83dbSDimitry Andric   unsigned Offset = State.AllocateStack(4, Align(4));
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   if (LocVT == MVT::f32 && Offset < 16*8) {
1620b57cec5SDimitry Andric     // Promote floats to %f0-%f31.
1630b57cec5SDimitry Andric     State.addLoc(CCValAssign::getReg(ValNo, ValVT, SP::F0 + Offset/4,
1640b57cec5SDimitry Andric                                      LocVT, LocInfo));
1650b57cec5SDimitry Andric     return true;
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   if (LocVT == MVT::i32 && Offset < 6*8) {
1690b57cec5SDimitry Andric     // Promote integers to %i0-%i5, using half the register.
1700b57cec5SDimitry Andric     unsigned Reg = SP::I0 + Offset/8;
1710b57cec5SDimitry Andric     LocVT = MVT::i64;
1720b57cec5SDimitry Andric     LocInfo = CCValAssign::AExt;
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric     // Set the Custom bit if this i32 goes in the high bits of a register.
1750b57cec5SDimitry Andric     if (Offset % 8 == 0)
1760b57cec5SDimitry Andric       State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg,
1770b57cec5SDimitry Andric                                              LocVT, LocInfo));
1780b57cec5SDimitry Andric     else
1790b57cec5SDimitry Andric       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
1800b57cec5SDimitry Andric     return true;
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
183f3fd488fSDimitry Andric   // Bail out if this is a return CC and we run out of registers to place
184f3fd488fSDimitry Andric   // values into.
185f3fd488fSDimitry Andric   if (IsReturn)
186f3fd488fSDimitry Andric     return false;
187f3fd488fSDimitry Andric 
1880b57cec5SDimitry Andric   State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
1890b57cec5SDimitry Andric   return true;
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric 
192f3fd488fSDimitry Andric static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
193f3fd488fSDimitry Andric                             CCValAssign::LocInfo &LocInfo,
194f3fd488fSDimitry Andric                             ISD::ArgFlagsTy &ArgFlags, CCState &State) {
195f3fd488fSDimitry Andric   return Analyze_CC_Sparc64_Full(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
196f3fd488fSDimitry Andric                                  State);
197f3fd488fSDimitry Andric }
198f3fd488fSDimitry Andric 
199f3fd488fSDimitry Andric static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
200f3fd488fSDimitry Andric                             CCValAssign::LocInfo &LocInfo,
201f3fd488fSDimitry Andric                             ISD::ArgFlagsTy &ArgFlags, CCState &State) {
202f3fd488fSDimitry Andric   return Analyze_CC_Sparc64_Half(false, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
203f3fd488fSDimitry Andric                                  State);
204f3fd488fSDimitry Andric }
205f3fd488fSDimitry Andric 
206f3fd488fSDimitry Andric static bool RetCC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
207f3fd488fSDimitry Andric                                CCValAssign::LocInfo &LocInfo,
208f3fd488fSDimitry Andric                                ISD::ArgFlagsTy &ArgFlags, CCState &State) {
209f3fd488fSDimitry Andric   return Analyze_CC_Sparc64_Full(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
210f3fd488fSDimitry Andric                                  State);
211f3fd488fSDimitry Andric }
212f3fd488fSDimitry Andric 
213f3fd488fSDimitry Andric static bool RetCC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
214f3fd488fSDimitry Andric                                CCValAssign::LocInfo &LocInfo,
215f3fd488fSDimitry Andric                                ISD::ArgFlagsTy &ArgFlags, CCState &State) {
216f3fd488fSDimitry Andric   return Analyze_CC_Sparc64_Half(true, ValNo, ValVT, LocVT, LocInfo, ArgFlags,
217f3fd488fSDimitry Andric                                  State);
218f3fd488fSDimitry Andric }
219f3fd488fSDimitry Andric 
2200b57cec5SDimitry Andric #include "SparcGenCallingConv.inc"
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric // The calling conventions in SparcCallingConv.td are described in terms of the
2230b57cec5SDimitry Andric // callee's register window. This function translates registers to the
2240b57cec5SDimitry Andric // corresponding caller window %o register.
2250b57cec5SDimitry Andric static unsigned toCallerWindow(unsigned Reg) {
2260b57cec5SDimitry Andric   static_assert(SP::I0 + 7 == SP::I7 && SP::O0 + 7 == SP::O7,
2270b57cec5SDimitry Andric                 "Unexpected enum");
2280b57cec5SDimitry Andric   if (Reg >= SP::I0 && Reg <= SP::I7)
2290b57cec5SDimitry Andric     return Reg - SP::I0 + SP::O0;
2300b57cec5SDimitry Andric   return Reg;
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric 
233f3fd488fSDimitry Andric bool SparcTargetLowering::CanLowerReturn(
234f3fd488fSDimitry Andric     CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
235f3fd488fSDimitry Andric     const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
236f3fd488fSDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
237f3fd488fSDimitry Andric   CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
238f3fd488fSDimitry Andric   return CCInfo.CheckReturn(Outs, Subtarget->is64Bit() ? RetCC_Sparc64
239f3fd488fSDimitry Andric                                                        : RetCC_Sparc32);
240f3fd488fSDimitry Andric }
241f3fd488fSDimitry Andric 
2420b57cec5SDimitry Andric SDValue
2430b57cec5SDimitry Andric SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
2440b57cec5SDimitry Andric                                  bool IsVarArg,
2450b57cec5SDimitry Andric                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
2460b57cec5SDimitry Andric                                  const SmallVectorImpl<SDValue> &OutVals,
2470b57cec5SDimitry Andric                                  const SDLoc &DL, SelectionDAG &DAG) const {
2480b57cec5SDimitry Andric   if (Subtarget->is64Bit())
2490b57cec5SDimitry Andric     return LowerReturn_64(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG);
2500b57cec5SDimitry Andric   return LowerReturn_32(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG);
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric SDValue
2540b57cec5SDimitry Andric SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv,
2550b57cec5SDimitry Andric                                     bool IsVarArg,
2560b57cec5SDimitry Andric                                     const SmallVectorImpl<ISD::OutputArg> &Outs,
2570b57cec5SDimitry Andric                                     const SmallVectorImpl<SDValue> &OutVals,
2580b57cec5SDimitry Andric                                     const SDLoc &DL, SelectionDAG &DAG) const {
2590b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   // CCValAssign - represent the assignment of the return value to locations.
2620b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   // CCState - Info about the registers and stack slot.
2650b57cec5SDimitry Andric   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
2660b57cec5SDimitry Andric                  *DAG.getContext());
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   // Analyze return values.
2690b57cec5SDimitry Andric   CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32);
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   SDValue Flag;
2720b57cec5SDimitry Andric   SmallVector<SDValue, 4> RetOps(1, Chain);
2730b57cec5SDimitry Andric   // Make room for the return address offset.
2740b57cec5SDimitry Andric   RetOps.push_back(SDValue());
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   // Copy the result values into the output registers.
2770b57cec5SDimitry Andric   for (unsigned i = 0, realRVLocIdx = 0;
2780b57cec5SDimitry Andric        i != RVLocs.size();
2790b57cec5SDimitry Andric        ++i, ++realRVLocIdx) {
2800b57cec5SDimitry Andric     CCValAssign &VA = RVLocs[i];
2810b57cec5SDimitry Andric     assert(VA.isRegLoc() && "Can only return in registers!");
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric     SDValue Arg = OutVals[realRVLocIdx];
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric     if (VA.needsCustom()) {
2860b57cec5SDimitry Andric       assert(VA.getLocVT() == MVT::v2i32);
2870b57cec5SDimitry Andric       // Legalize ret v2i32 -> ret 2 x i32 (Basically: do what would
2880b57cec5SDimitry Andric       // happen by default if this wasn't a legal type)
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric       SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32,
2910b57cec5SDimitry Andric                                   Arg,
2920b57cec5SDimitry Andric                                   DAG.getConstant(0, DL, getVectorIdxTy(DAG.getDataLayout())));
2930b57cec5SDimitry Andric       SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32,
2940b57cec5SDimitry Andric                                   Arg,
2950b57cec5SDimitry Andric                                   DAG.getConstant(1, DL, getVectorIdxTy(DAG.getDataLayout())));
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric       Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part0, Flag);
2980b57cec5SDimitry Andric       Flag = Chain.getValue(1);
2990b57cec5SDimitry Andric       RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3000b57cec5SDimitry Andric       VA = RVLocs[++i]; // skip ahead to next loc
3010b57cec5SDimitry Andric       Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part1,
3020b57cec5SDimitry Andric                                Flag);
3030b57cec5SDimitry Andric     } else
3040b57cec5SDimitry Andric       Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Flag);
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric     // Guarantee that all emitted copies are stuck together with flags.
3070b57cec5SDimitry Andric     Flag = Chain.getValue(1);
3080b57cec5SDimitry Andric     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3090b57cec5SDimitry Andric   }
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   unsigned RetAddrOffset = 8; // Call Inst + Delay Slot
3120b57cec5SDimitry Andric   // If the function returns a struct, copy the SRetReturnReg to I0
3130b57cec5SDimitry Andric   if (MF.getFunction().hasStructRetAttr()) {
3140b57cec5SDimitry Andric     SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
3155ffd83dbSDimitry Andric     Register Reg = SFI->getSRetReturnReg();
3160b57cec5SDimitry Andric     if (!Reg)
3170b57cec5SDimitry Andric       llvm_unreachable("sret virtual register not created in the entry block");
3180b57cec5SDimitry Andric     auto PtrVT = getPointerTy(DAG.getDataLayout());
3190b57cec5SDimitry Andric     SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, PtrVT);
3200b57cec5SDimitry Andric     Chain = DAG.getCopyToReg(Chain, DL, SP::I0, Val, Flag);
3210b57cec5SDimitry Andric     Flag = Chain.getValue(1);
3220b57cec5SDimitry Andric     RetOps.push_back(DAG.getRegister(SP::I0, PtrVT));
3230b57cec5SDimitry Andric     RetAddrOffset = 12; // CallInst + Delay Slot + Unimp
3240b57cec5SDimitry Andric   }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   RetOps[0] = Chain;  // Update chain.
3270b57cec5SDimitry Andric   RetOps[1] = DAG.getConstant(RetAddrOffset, DL, MVT::i32);
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   // Add the flag if we have it.
3300b57cec5SDimitry Andric   if (Flag.getNode())
3310b57cec5SDimitry Andric     RetOps.push_back(Flag);
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, RetOps);
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric // Lower return values for the 64-bit ABI.
3370b57cec5SDimitry Andric // Return values are passed the exactly the same way as function arguments.
3380b57cec5SDimitry Andric SDValue
3390b57cec5SDimitry Andric SparcTargetLowering::LowerReturn_64(SDValue Chain, CallingConv::ID CallConv,
3400b57cec5SDimitry Andric                                     bool IsVarArg,
3410b57cec5SDimitry Andric                                     const SmallVectorImpl<ISD::OutputArg> &Outs,
3420b57cec5SDimitry Andric                                     const SmallVectorImpl<SDValue> &OutVals,
3430b57cec5SDimitry Andric                                     const SDLoc &DL, SelectionDAG &DAG) const {
3440b57cec5SDimitry Andric   // CCValAssign - represent the assignment of the return value to locations.
3450b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   // CCState - Info about the registers and stack slot.
3480b57cec5SDimitry Andric   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
3490b57cec5SDimitry Andric                  *DAG.getContext());
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   // Analyze return values.
3520b57cec5SDimitry Andric   CCInfo.AnalyzeReturn(Outs, RetCC_Sparc64);
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   SDValue Flag;
3550b57cec5SDimitry Andric   SmallVector<SDValue, 4> RetOps(1, Chain);
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   // The second operand on the return instruction is the return address offset.
3580b57cec5SDimitry Andric   // The return address is always %i7+8 with the 64-bit ABI.
3590b57cec5SDimitry Andric   RetOps.push_back(DAG.getConstant(8, DL, MVT::i32));
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   // Copy the result values into the output registers.
3620b57cec5SDimitry Andric   for (unsigned i = 0; i != RVLocs.size(); ++i) {
3630b57cec5SDimitry Andric     CCValAssign &VA = RVLocs[i];
3640b57cec5SDimitry Andric     assert(VA.isRegLoc() && "Can only return in registers!");
3650b57cec5SDimitry Andric     SDValue OutVal = OutVals[i];
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric     // Integer return values must be sign or zero extended by the callee.
3680b57cec5SDimitry Andric     switch (VA.getLocInfo()) {
3690b57cec5SDimitry Andric     case CCValAssign::Full: break;
3700b57cec5SDimitry Andric     case CCValAssign::SExt:
3710b57cec5SDimitry Andric       OutVal = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), OutVal);
3720b57cec5SDimitry Andric       break;
3730b57cec5SDimitry Andric     case CCValAssign::ZExt:
3740b57cec5SDimitry Andric       OutVal = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), OutVal);
3750b57cec5SDimitry Andric       break;
3760b57cec5SDimitry Andric     case CCValAssign::AExt:
3770b57cec5SDimitry Andric       OutVal = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), OutVal);
3780b57cec5SDimitry Andric       break;
3790b57cec5SDimitry Andric     default:
3800b57cec5SDimitry Andric       llvm_unreachable("Unknown loc info!");
3810b57cec5SDimitry Andric     }
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric     // The custom bit on an i32 return value indicates that it should be passed
3840b57cec5SDimitry Andric     // in the high bits of the register.
3850b57cec5SDimitry Andric     if (VA.getValVT() == MVT::i32 && VA.needsCustom()) {
3860b57cec5SDimitry Andric       OutVal = DAG.getNode(ISD::SHL, DL, MVT::i64, OutVal,
3870b57cec5SDimitry Andric                            DAG.getConstant(32, DL, MVT::i32));
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric       // The next value may go in the low bits of the same register.
3900b57cec5SDimitry Andric       // Handle both at once.
3910b57cec5SDimitry Andric       if (i+1 < RVLocs.size() && RVLocs[i+1].getLocReg() == VA.getLocReg()) {
3920b57cec5SDimitry Andric         SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, OutVals[i+1]);
3930b57cec5SDimitry Andric         OutVal = DAG.getNode(ISD::OR, DL, MVT::i64, OutVal, NV);
3940b57cec5SDimitry Andric         // Skip the next value, it's already done.
3950b57cec5SDimitry Andric         ++i;
3960b57cec5SDimitry Andric       }
3970b57cec5SDimitry Andric     }
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric     Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVal, Flag);
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric     // Guarantee that all emitted copies are stuck together with flags.
4020b57cec5SDimitry Andric     Flag = Chain.getValue(1);
4030b57cec5SDimitry Andric     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
4040b57cec5SDimitry Andric   }
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric   RetOps[0] = Chain;  // Update chain.
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   // Add the flag if we have it.
4090b57cec5SDimitry Andric   if (Flag.getNode())
4100b57cec5SDimitry Andric     RetOps.push_back(Flag);
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, RetOps);
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerFormalArguments(
4160b57cec5SDimitry Andric     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
4170b57cec5SDimitry Andric     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
4180b57cec5SDimitry Andric     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
4190b57cec5SDimitry Andric   if (Subtarget->is64Bit())
4200b57cec5SDimitry Andric     return LowerFormalArguments_64(Chain, CallConv, IsVarArg, Ins,
4210b57cec5SDimitry Andric                                    DL, DAG, InVals);
4220b57cec5SDimitry Andric   return LowerFormalArguments_32(Chain, CallConv, IsVarArg, Ins,
4230b57cec5SDimitry Andric                                  DL, DAG, InVals);
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric /// LowerFormalArguments32 - V8 uses a very simple ABI, where all values are
4270b57cec5SDimitry Andric /// passed in either one or two GPRs, including FP values.  TODO: we should
4280b57cec5SDimitry Andric /// pass FP values in FP registers for fastcc functions.
4290b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerFormalArguments_32(
4300b57cec5SDimitry Andric     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
4310b57cec5SDimitry Andric     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
4320b57cec5SDimitry Andric     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
4330b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
4340b57cec5SDimitry Andric   MachineRegisterInfo &RegInfo = MF.getRegInfo();
4350b57cec5SDimitry Andric   SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   // Assign locations to all of the incoming arguments.
4380b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
4390b57cec5SDimitry Andric   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
4400b57cec5SDimitry Andric                  *DAG.getContext());
4410b57cec5SDimitry Andric   CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32);
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   const unsigned StackOffset = 92;
4440b57cec5SDimitry Andric   bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   unsigned InIdx = 0;
4470b57cec5SDimitry Andric   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) {
4480b57cec5SDimitry Andric     CCValAssign &VA = ArgLocs[i];
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric     if (Ins[InIdx].Flags.isSRet()) {
4510b57cec5SDimitry Andric       if (InIdx != 0)
4520b57cec5SDimitry Andric         report_fatal_error("sparc only supports sret on the first parameter");
4530b57cec5SDimitry Andric       // Get SRet from [%fp+64].
4540b57cec5SDimitry Andric       int FrameIdx = MF.getFrameInfo().CreateFixedObject(4, 64, true);
4550b57cec5SDimitry Andric       SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
4560b57cec5SDimitry Andric       SDValue Arg =
4570b57cec5SDimitry Andric           DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
4580b57cec5SDimitry Andric       InVals.push_back(Arg);
4590b57cec5SDimitry Andric       continue;
4600b57cec5SDimitry Andric     }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric     if (VA.isRegLoc()) {
4630b57cec5SDimitry Andric       if (VA.needsCustom()) {
4640b57cec5SDimitry Andric         assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32);
4650b57cec5SDimitry Andric 
4668bcb0991SDimitry Andric         Register VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
4670b57cec5SDimitry Andric         MF.getRegInfo().addLiveIn(VA.getLocReg(), VRegHi);
4680b57cec5SDimitry Andric         SDValue HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32);
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric         assert(i+1 < e);
4710b57cec5SDimitry Andric         CCValAssign &NextVA = ArgLocs[++i];
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric         SDValue LoVal;
4740b57cec5SDimitry Andric         if (NextVA.isMemLoc()) {
4750b57cec5SDimitry Andric           int FrameIdx = MF.getFrameInfo().
4760b57cec5SDimitry Andric             CreateFixedObject(4, StackOffset+NextVA.getLocMemOffset(),true);
4770b57cec5SDimitry Andric           SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
4780b57cec5SDimitry Andric           LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
4790b57cec5SDimitry Andric         } else {
4805ffd83dbSDimitry Andric           Register loReg = MF.addLiveIn(NextVA.getLocReg(),
4810b57cec5SDimitry Andric                                         &SP::IntRegsRegClass);
4820b57cec5SDimitry Andric           LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32);
4830b57cec5SDimitry Andric         }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric         if (IsLittleEndian)
4860b57cec5SDimitry Andric           std::swap(LoVal, HiVal);
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric         SDValue WholeValue =
4890b57cec5SDimitry Andric           DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
4900b57cec5SDimitry Andric         WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), WholeValue);
4910b57cec5SDimitry Andric         InVals.push_back(WholeValue);
4920b57cec5SDimitry Andric         continue;
4930b57cec5SDimitry Andric       }
4948bcb0991SDimitry Andric       Register VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
4950b57cec5SDimitry Andric       MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg);
4960b57cec5SDimitry Andric       SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
4970b57cec5SDimitry Andric       if (VA.getLocVT() == MVT::f32)
4980b57cec5SDimitry Andric         Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
4990b57cec5SDimitry Andric       else if (VA.getLocVT() != MVT::i32) {
5000b57cec5SDimitry Andric         Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
5010b57cec5SDimitry Andric                           DAG.getValueType(VA.getLocVT()));
5020b57cec5SDimitry Andric         Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
5030b57cec5SDimitry Andric       }
5040b57cec5SDimitry Andric       InVals.push_back(Arg);
5050b57cec5SDimitry Andric       continue;
5060b57cec5SDimitry Andric     }
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric     assert(VA.isMemLoc());
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric     unsigned Offset = VA.getLocMemOffset()+StackOffset;
5110b57cec5SDimitry Andric     auto PtrVT = getPointerTy(DAG.getDataLayout());
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric     if (VA.needsCustom()) {
5140b57cec5SDimitry Andric       assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32);
5150b57cec5SDimitry Andric       // If it is double-word aligned, just load.
5160b57cec5SDimitry Andric       if (Offset % 8 == 0) {
5170b57cec5SDimitry Andric         int FI = MF.getFrameInfo().CreateFixedObject(8,
5180b57cec5SDimitry Andric                                                      Offset,
5190b57cec5SDimitry Andric                                                      true);
5200b57cec5SDimitry Andric         SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
5210b57cec5SDimitry Andric         SDValue Load =
5220b57cec5SDimitry Andric             DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
5230b57cec5SDimitry Andric         InVals.push_back(Load);
5240b57cec5SDimitry Andric         continue;
5250b57cec5SDimitry Andric       }
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric       int FI = MF.getFrameInfo().CreateFixedObject(4,
5280b57cec5SDimitry Andric                                                    Offset,
5290b57cec5SDimitry Andric                                                    true);
5300b57cec5SDimitry Andric       SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
5310b57cec5SDimitry Andric       SDValue HiVal =
5320b57cec5SDimitry Andric           DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo());
5330b57cec5SDimitry Andric       int FI2 = MF.getFrameInfo().CreateFixedObject(4,
5340b57cec5SDimitry Andric                                                     Offset+4,
5350b57cec5SDimitry Andric                                                     true);
5360b57cec5SDimitry Andric       SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT);
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric       SDValue LoVal =
5390b57cec5SDimitry Andric           DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo());
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric       if (IsLittleEndian)
5420b57cec5SDimitry Andric         std::swap(LoVal, HiVal);
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric       SDValue WholeValue =
5450b57cec5SDimitry Andric         DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
5460b57cec5SDimitry Andric       WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue);
5470b57cec5SDimitry Andric       InVals.push_back(WholeValue);
5480b57cec5SDimitry Andric       continue;
5490b57cec5SDimitry Andric     }
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric     int FI = MF.getFrameInfo().CreateFixedObject(4,
5520b57cec5SDimitry Andric                                                  Offset,
5530b57cec5SDimitry Andric                                                  true);
5540b57cec5SDimitry Andric     SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
5550b57cec5SDimitry Andric     SDValue Load ;
5560b57cec5SDimitry Andric     if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) {
5570b57cec5SDimitry Andric       Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
5580b57cec5SDimitry Andric     } else if (VA.getValVT() == MVT::f128) {
5590b57cec5SDimitry Andric       report_fatal_error("SPARCv8 does not handle f128 in calls; "
5600b57cec5SDimitry Andric                          "pass indirectly");
5610b57cec5SDimitry Andric     } else {
5620b57cec5SDimitry Andric       // We shouldn't see any other value types here.
5630b57cec5SDimitry Andric       llvm_unreachable("Unexpected ValVT encountered in frame lowering.");
5640b57cec5SDimitry Andric     }
5650b57cec5SDimitry Andric     InVals.push_back(Load);
5660b57cec5SDimitry Andric   }
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   if (MF.getFunction().hasStructRetAttr()) {
5690b57cec5SDimitry Andric     // Copy the SRet Argument to SRetReturnReg.
5700b57cec5SDimitry Andric     SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
5715ffd83dbSDimitry Andric     Register Reg = SFI->getSRetReturnReg();
5720b57cec5SDimitry Andric     if (!Reg) {
5730b57cec5SDimitry Andric       Reg = MF.getRegInfo().createVirtualRegister(&SP::IntRegsRegClass);
5740b57cec5SDimitry Andric       SFI->setSRetReturnReg(Reg);
5750b57cec5SDimitry Andric     }
5760b57cec5SDimitry Andric     SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]);
5770b57cec5SDimitry Andric     Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);
5780b57cec5SDimitry Andric   }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   // Store remaining ArgRegs to the stack if this is a varargs function.
5810b57cec5SDimitry Andric   if (isVarArg) {
5820b57cec5SDimitry Andric     static const MCPhysReg ArgRegs[] = {
5830b57cec5SDimitry Andric       SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
5840b57cec5SDimitry Andric     };
5850b57cec5SDimitry Andric     unsigned NumAllocated = CCInfo.getFirstUnallocated(ArgRegs);
5860b57cec5SDimitry Andric     const MCPhysReg *CurArgReg = ArgRegs+NumAllocated, *ArgRegEnd = ArgRegs+6;
5870b57cec5SDimitry Andric     unsigned ArgOffset = CCInfo.getNextStackOffset();
5880b57cec5SDimitry Andric     if (NumAllocated == 6)
5890b57cec5SDimitry Andric       ArgOffset += StackOffset;
5900b57cec5SDimitry Andric     else {
5910b57cec5SDimitry Andric       assert(!ArgOffset);
5920b57cec5SDimitry Andric       ArgOffset = 68+4*NumAllocated;
5930b57cec5SDimitry Andric     }
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric     // Remember the vararg offset for the va_start implementation.
5960b57cec5SDimitry Andric     FuncInfo->setVarArgsFrameOffset(ArgOffset);
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric     std::vector<SDValue> OutChains;
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric     for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
6018bcb0991SDimitry Andric       Register VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
6020b57cec5SDimitry Andric       MF.getRegInfo().addLiveIn(*CurArgReg, VReg);
6030b57cec5SDimitry Andric       SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32);
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric       int FrameIdx = MF.getFrameInfo().CreateFixedObject(4, ArgOffset,
6060b57cec5SDimitry Andric                                                          true);
6070b57cec5SDimitry Andric       SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric       OutChains.push_back(
6100b57cec5SDimitry Andric           DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, MachinePointerInfo()));
6110b57cec5SDimitry Andric       ArgOffset += 4;
6120b57cec5SDimitry Andric     }
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric     if (!OutChains.empty()) {
6150b57cec5SDimitry Andric       OutChains.push_back(Chain);
6160b57cec5SDimitry Andric       Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
6170b57cec5SDimitry Andric     }
6180b57cec5SDimitry Andric   }
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric   return Chain;
6210b57cec5SDimitry Andric }
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric // Lower formal arguments for the 64 bit ABI.
6240b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerFormalArguments_64(
6250b57cec5SDimitry Andric     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
6260b57cec5SDimitry Andric     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
6270b57cec5SDimitry Andric     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
6280b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric   // Analyze arguments according to CC_Sparc64.
6310b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
6320b57cec5SDimitry Andric   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
6330b57cec5SDimitry Andric                  *DAG.getContext());
6340b57cec5SDimitry Andric   CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc64);
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   // The argument array begins at %fp+BIAS+128, after the register save area.
6370b57cec5SDimitry Andric   const unsigned ArgArea = 128;
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
6400b57cec5SDimitry Andric     CCValAssign &VA = ArgLocs[i];
6410b57cec5SDimitry Andric     if (VA.isRegLoc()) {
6420b57cec5SDimitry Andric       // This argument is passed in a register.
6430b57cec5SDimitry Andric       // All integer register arguments are promoted by the caller to i64.
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric       // Create a virtual register for the promoted live-in value.
6465ffd83dbSDimitry Andric       Register VReg = MF.addLiveIn(VA.getLocReg(),
6470b57cec5SDimitry Andric                                    getRegClassFor(VA.getLocVT()));
6480b57cec5SDimitry Andric       SDValue Arg = DAG.getCopyFromReg(Chain, DL, VReg, VA.getLocVT());
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric       // Get the high bits for i32 struct elements.
6510b57cec5SDimitry Andric       if (VA.getValVT() == MVT::i32 && VA.needsCustom())
6520b57cec5SDimitry Andric         Arg = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), Arg,
6530b57cec5SDimitry Andric                           DAG.getConstant(32, DL, MVT::i32));
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric       // The caller promoted the argument, so insert an Assert?ext SDNode so we
6560b57cec5SDimitry Andric       // won't promote the value again in this function.
6570b57cec5SDimitry Andric       switch (VA.getLocInfo()) {
6580b57cec5SDimitry Andric       case CCValAssign::SExt:
6590b57cec5SDimitry Andric         Arg = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Arg,
6600b57cec5SDimitry Andric                           DAG.getValueType(VA.getValVT()));
6610b57cec5SDimitry Andric         break;
6620b57cec5SDimitry Andric       case CCValAssign::ZExt:
6630b57cec5SDimitry Andric         Arg = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Arg,
6640b57cec5SDimitry Andric                           DAG.getValueType(VA.getValVT()));
6650b57cec5SDimitry Andric         break;
6660b57cec5SDimitry Andric       default:
6670b57cec5SDimitry Andric         break;
6680b57cec5SDimitry Andric       }
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric       // Truncate the register down to the argument type.
6710b57cec5SDimitry Andric       if (VA.isExtInLoc())
6720b57cec5SDimitry Andric         Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg);
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric       InVals.push_back(Arg);
6750b57cec5SDimitry Andric       continue;
6760b57cec5SDimitry Andric     }
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric     // The registers are exhausted. This argument was passed on the stack.
6790b57cec5SDimitry Andric     assert(VA.isMemLoc());
6800b57cec5SDimitry Andric     // The CC_Sparc64_Full/Half functions compute stack offsets relative to the
6810b57cec5SDimitry Andric     // beginning of the arguments area at %fp+BIAS+128.
6820b57cec5SDimitry Andric     unsigned Offset = VA.getLocMemOffset() + ArgArea;
6830b57cec5SDimitry Andric     unsigned ValSize = VA.getValVT().getSizeInBits() / 8;
6840b57cec5SDimitry Andric     // Adjust offset for extended arguments, SPARC is big-endian.
6850b57cec5SDimitry Andric     // The caller will have written the full slot with extended bytes, but we
6860b57cec5SDimitry Andric     // prefer our own extending loads.
6870b57cec5SDimitry Andric     if (VA.isExtInLoc())
6880b57cec5SDimitry Andric       Offset += 8 - ValSize;
6890b57cec5SDimitry Andric     int FI = MF.getFrameInfo().CreateFixedObject(ValSize, Offset, true);
6900b57cec5SDimitry Andric     InVals.push_back(
6910b57cec5SDimitry Andric         DAG.getLoad(VA.getValVT(), DL, Chain,
6920b57cec5SDimitry Andric                     DAG.getFrameIndex(FI, getPointerTy(MF.getDataLayout())),
6930b57cec5SDimitry Andric                     MachinePointerInfo::getFixedStack(MF, FI)));
6940b57cec5SDimitry Andric   }
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric   if (!IsVarArg)
6970b57cec5SDimitry Andric     return Chain;
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric   // This function takes variable arguments, some of which may have been passed
7000b57cec5SDimitry Andric   // in registers %i0-%i5. Variable floating point arguments are never passed
7010b57cec5SDimitry Andric   // in floating point registers. They go on %i0-%i5 or on the stack like
7020b57cec5SDimitry Andric   // integer arguments.
7030b57cec5SDimitry Andric   //
7040b57cec5SDimitry Andric   // The va_start intrinsic needs to know the offset to the first variable
7050b57cec5SDimitry Andric   // argument.
7060b57cec5SDimitry Andric   unsigned ArgOffset = CCInfo.getNextStackOffset();
7070b57cec5SDimitry Andric   SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
7080b57cec5SDimitry Andric   // Skip the 128 bytes of register save area.
7090b57cec5SDimitry Andric   FuncInfo->setVarArgsFrameOffset(ArgOffset + ArgArea +
7100b57cec5SDimitry Andric                                   Subtarget->getStackPointerBias());
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric   // Save the variable arguments that were passed in registers.
7130b57cec5SDimitry Andric   // The caller is required to reserve stack space for 6 arguments regardless
7140b57cec5SDimitry Andric   // of how many arguments were actually passed.
7150b57cec5SDimitry Andric   SmallVector<SDValue, 8> OutChains;
7160b57cec5SDimitry Andric   for (; ArgOffset < 6*8; ArgOffset += 8) {
7175ffd83dbSDimitry Andric     Register VReg = MF.addLiveIn(SP::I0 + ArgOffset/8, &SP::I64RegsRegClass);
7180b57cec5SDimitry Andric     SDValue VArg = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64);
7190b57cec5SDimitry Andric     int FI = MF.getFrameInfo().CreateFixedObject(8, ArgOffset + ArgArea, true);
7200b57cec5SDimitry Andric     auto PtrVT = getPointerTy(MF.getDataLayout());
7210b57cec5SDimitry Andric     OutChains.push_back(
7220b57cec5SDimitry Andric         DAG.getStore(Chain, DL, VArg, DAG.getFrameIndex(FI, PtrVT),
7230b57cec5SDimitry Andric                      MachinePointerInfo::getFixedStack(MF, FI)));
7240b57cec5SDimitry Andric   }
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric   if (!OutChains.empty())
7270b57cec5SDimitry Andric     Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   return Chain;
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric SDValue
7330b57cec5SDimitry Andric SparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
7340b57cec5SDimitry Andric                                SmallVectorImpl<SDValue> &InVals) const {
7350b57cec5SDimitry Andric   if (Subtarget->is64Bit())
7360b57cec5SDimitry Andric     return LowerCall_64(CLI, InVals);
7370b57cec5SDimitry Andric   return LowerCall_32(CLI, InVals);
7380b57cec5SDimitry Andric }
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric static bool hasReturnsTwiceAttr(SelectionDAG &DAG, SDValue Callee,
7415ffd83dbSDimitry Andric                                 const CallBase *Call) {
7425ffd83dbSDimitry Andric   if (Call)
7435ffd83dbSDimitry Andric     return Call->hasFnAttr(Attribute::ReturnsTwice);
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric   const Function *CalleeFn = nullptr;
7460b57cec5SDimitry Andric   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
7470b57cec5SDimitry Andric     CalleeFn = dyn_cast<Function>(G->getGlobal());
7480b57cec5SDimitry Andric   } else if (ExternalSymbolSDNode *E =
7490b57cec5SDimitry Andric              dyn_cast<ExternalSymbolSDNode>(Callee)) {
7500b57cec5SDimitry Andric     const Function &Fn = DAG.getMachineFunction().getFunction();
7510b57cec5SDimitry Andric     const Module *M = Fn.getParent();
7520b57cec5SDimitry Andric     const char *CalleeName = E->getSymbol();
7530b57cec5SDimitry Andric     CalleeFn = M->getFunction(CalleeName);
7540b57cec5SDimitry Andric   }
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric   if (!CalleeFn)
7570b57cec5SDimitry Andric     return false;
7580b57cec5SDimitry Andric   return CalleeFn->hasFnAttribute(Attribute::ReturnsTwice);
7590b57cec5SDimitry Andric }
7600b57cec5SDimitry Andric 
76181ad6265SDimitry Andric /// IsEligibleForTailCallOptimization - Check whether the call is eligible
76281ad6265SDimitry Andric /// for tail call optimization.
76381ad6265SDimitry Andric bool SparcTargetLowering::IsEligibleForTailCallOptimization(
76481ad6265SDimitry Andric     CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF) const {
76581ad6265SDimitry Andric 
76681ad6265SDimitry Andric   auto &Outs = CLI.Outs;
76781ad6265SDimitry Andric   auto &Caller = MF.getFunction();
76881ad6265SDimitry Andric 
76981ad6265SDimitry Andric   // Do not tail call opt functions with "disable-tail-calls" attribute.
77081ad6265SDimitry Andric   if (Caller.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
77181ad6265SDimitry Andric     return false;
77281ad6265SDimitry Andric 
77381ad6265SDimitry Andric   // Do not tail call opt if the stack is used to pass parameters.
774*bdd1243dSDimitry Andric   // 64-bit targets have a slightly higher limit since the ABI requires
775*bdd1243dSDimitry Andric   // to allocate some space even when all the parameters fit inside registers.
776*bdd1243dSDimitry Andric   unsigned StackOffsetLimit = Subtarget->is64Bit() ? 48 : 0;
777*bdd1243dSDimitry Andric   if (CCInfo.getNextStackOffset() > StackOffsetLimit)
77881ad6265SDimitry Andric     return false;
77981ad6265SDimitry Andric 
78081ad6265SDimitry Andric   // Do not tail call opt if either the callee or caller returns
78181ad6265SDimitry Andric   // a struct and the other does not.
78281ad6265SDimitry Andric   if (!Outs.empty() && Caller.hasStructRetAttr() != Outs[0].Flags.isSRet())
78381ad6265SDimitry Andric     return false;
78481ad6265SDimitry Andric 
78581ad6265SDimitry Andric   // Byval parameters hand the function a pointer directly into the stack area
78681ad6265SDimitry Andric   // we want to reuse during a tail call.
78781ad6265SDimitry Andric   for (auto &Arg : Outs)
78881ad6265SDimitry Andric     if (Arg.Flags.isByVal())
78981ad6265SDimitry Andric       return false;
79081ad6265SDimitry Andric 
79181ad6265SDimitry Andric   return true;
79281ad6265SDimitry Andric }
79381ad6265SDimitry Andric 
7940b57cec5SDimitry Andric // Lower a call for the 32-bit ABI.
7950b57cec5SDimitry Andric SDValue
7960b57cec5SDimitry Andric SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
7970b57cec5SDimitry Andric                                   SmallVectorImpl<SDValue> &InVals) const {
7980b57cec5SDimitry Andric   SelectionDAG &DAG                     = CLI.DAG;
7990b57cec5SDimitry Andric   SDLoc &dl                             = CLI.DL;
8000b57cec5SDimitry Andric   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
8010b57cec5SDimitry Andric   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
8020b57cec5SDimitry Andric   SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
8030b57cec5SDimitry Andric   SDValue Chain                         = CLI.Chain;
8040b57cec5SDimitry Andric   SDValue Callee                        = CLI.Callee;
8050b57cec5SDimitry Andric   bool &isTailCall                      = CLI.IsTailCall;
8060b57cec5SDimitry Andric   CallingConv::ID CallConv              = CLI.CallConv;
8070b57cec5SDimitry Andric   bool isVarArg                         = CLI.IsVarArg;
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric   // Analyze operands of the call, assigning locations to each operand.
8100b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
8110b57cec5SDimitry Andric   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
8120b57cec5SDimitry Andric                  *DAG.getContext());
8130b57cec5SDimitry Andric   CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32);
8140b57cec5SDimitry Andric 
81581ad6265SDimitry Andric   isTailCall = isTailCall && IsEligibleForTailCallOptimization(
81681ad6265SDimitry Andric                                  CCInfo, CLI, DAG.getMachineFunction());
81781ad6265SDimitry Andric 
8180b57cec5SDimitry Andric   // Get the size of the outgoing arguments stack space requirement.
8190b57cec5SDimitry Andric   unsigned ArgsSize = CCInfo.getNextStackOffset();
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric   // Keep stack frames 8-byte aligned.
8220b57cec5SDimitry Andric   ArgsSize = (ArgsSize+7) & ~7;
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric   MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric   // Create local copies for byval args.
8270b57cec5SDimitry Andric   SmallVector<SDValue, 8> ByValArgs;
8280b57cec5SDimitry Andric   for (unsigned i = 0,  e = Outs.size(); i != e; ++i) {
8290b57cec5SDimitry Andric     ISD::ArgFlagsTy Flags = Outs[i].Flags;
8300b57cec5SDimitry Andric     if (!Flags.isByVal())
8310b57cec5SDimitry Andric       continue;
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric     SDValue Arg = OutVals[i];
8340b57cec5SDimitry Andric     unsigned Size = Flags.getByValSize();
8355ffd83dbSDimitry Andric     Align Alignment = Flags.getNonZeroByValAlign();
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric     if (Size > 0U) {
8385ffd83dbSDimitry Andric       int FI = MFI.CreateStackObject(Size, Alignment, false);
8390b57cec5SDimitry Andric       SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
8400b57cec5SDimitry Andric       SDValue SizeNode = DAG.getConstant(Size, dl, MVT::i32);
8410b57cec5SDimitry Andric 
8425ffd83dbSDimitry Andric       Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Alignment,
8430b57cec5SDimitry Andric                             false,        // isVolatile,
8440b57cec5SDimitry Andric                             (Size <= 32), // AlwaysInline if size <= 32,
8450b57cec5SDimitry Andric                             false,        // isTailCall
8460b57cec5SDimitry Andric                             MachinePointerInfo(), MachinePointerInfo());
8470b57cec5SDimitry Andric       ByValArgs.push_back(FIPtr);
8480b57cec5SDimitry Andric     }
8490b57cec5SDimitry Andric     else {
8500b57cec5SDimitry Andric       SDValue nullVal;
8510b57cec5SDimitry Andric       ByValArgs.push_back(nullVal);
8520b57cec5SDimitry Andric     }
8530b57cec5SDimitry Andric   }
8540b57cec5SDimitry Andric 
85581ad6265SDimitry Andric   assert(!isTailCall || ArgsSize == 0);
85681ad6265SDimitry Andric 
85781ad6265SDimitry Andric   if (!isTailCall)
8580b57cec5SDimitry Andric     Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, dl);
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric   SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
8610b57cec5SDimitry Andric   SmallVector<SDValue, 8> MemOpChains;
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric   const unsigned StackOffset = 92;
8640b57cec5SDimitry Andric   bool hasStructRetAttr = false;
8650b57cec5SDimitry Andric   unsigned SRetArgSize = 0;
8660b57cec5SDimitry Andric   // Walk the register/memloc assignments, inserting copies/loads.
8670b57cec5SDimitry Andric   for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size();
8680b57cec5SDimitry Andric        i != e;
8690b57cec5SDimitry Andric        ++i, ++realArgIdx) {
8700b57cec5SDimitry Andric     CCValAssign &VA = ArgLocs[i];
8710b57cec5SDimitry Andric     SDValue Arg = OutVals[realArgIdx];
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric     ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags;
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric     // Use local copy if it is a byval arg.
8760b57cec5SDimitry Andric     if (Flags.isByVal()) {
8770b57cec5SDimitry Andric       Arg = ByValArgs[byvalArgIdx++];
8780b57cec5SDimitry Andric       if (!Arg) {
8790b57cec5SDimitry Andric         continue;
8800b57cec5SDimitry Andric       }
8810b57cec5SDimitry Andric     }
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric     // Promote the value if needed.
8840b57cec5SDimitry Andric     switch (VA.getLocInfo()) {
8850b57cec5SDimitry Andric     default: llvm_unreachable("Unknown loc info!");
8860b57cec5SDimitry Andric     case CCValAssign::Full: break;
8870b57cec5SDimitry Andric     case CCValAssign::SExt:
8880b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
8890b57cec5SDimitry Andric       break;
8900b57cec5SDimitry Andric     case CCValAssign::ZExt:
8910b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
8920b57cec5SDimitry Andric       break;
8930b57cec5SDimitry Andric     case CCValAssign::AExt:
8940b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
8950b57cec5SDimitry Andric       break;
8960b57cec5SDimitry Andric     case CCValAssign::BCvt:
8970b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), Arg);
8980b57cec5SDimitry Andric       break;
8990b57cec5SDimitry Andric     }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric     if (Flags.isSRet()) {
9020b57cec5SDimitry Andric       assert(VA.needsCustom());
90381ad6265SDimitry Andric 
90481ad6265SDimitry Andric       if (isTailCall)
90581ad6265SDimitry Andric         continue;
90681ad6265SDimitry Andric 
9070b57cec5SDimitry Andric       // store SRet argument in %sp+64
9080b57cec5SDimitry Andric       SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
9090b57cec5SDimitry Andric       SDValue PtrOff = DAG.getIntPtrConstant(64, dl);
9100b57cec5SDimitry Andric       PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
9110b57cec5SDimitry Andric       MemOpChains.push_back(
9120b57cec5SDimitry Andric           DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
9130b57cec5SDimitry Andric       hasStructRetAttr = true;
9140b57cec5SDimitry Andric       // sret only allowed on first argument
9150b57cec5SDimitry Andric       assert(Outs[realArgIdx].OrigArgIndex == 0);
91681ad6265SDimitry Andric       SRetArgSize =
91781ad6265SDimitry Andric           DAG.getDataLayout().getTypeAllocSize(CLI.getArgs()[0].IndirectType);
9180b57cec5SDimitry Andric       continue;
9190b57cec5SDimitry Andric     }
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric     if (VA.needsCustom()) {
9220b57cec5SDimitry Andric       assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32);
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric       if (VA.isMemLoc()) {
9250b57cec5SDimitry Andric         unsigned Offset = VA.getLocMemOffset() + StackOffset;
9260b57cec5SDimitry Andric         // if it is double-word aligned, just store.
9270b57cec5SDimitry Andric         if (Offset % 8 == 0) {
9280b57cec5SDimitry Andric           SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
9290b57cec5SDimitry Andric           SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);
9300b57cec5SDimitry Andric           PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
9310b57cec5SDimitry Andric           MemOpChains.push_back(
9320b57cec5SDimitry Andric               DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
9330b57cec5SDimitry Andric           continue;
9340b57cec5SDimitry Andric         }
9350b57cec5SDimitry Andric       }
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric       if (VA.getLocVT() == MVT::f64) {
9380b57cec5SDimitry Andric         // Move from the float value from float registers into the
9390b57cec5SDimitry Andric         // integer registers.
9400b57cec5SDimitry Andric         if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Arg))
9410b57cec5SDimitry Andric           Arg = bitcastConstantFPToInt(C, dl, DAG);
9420b57cec5SDimitry Andric         else
9430b57cec5SDimitry Andric           Arg = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, Arg);
9440b57cec5SDimitry Andric       }
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric       SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32,
9470b57cec5SDimitry Andric                                   Arg,
9480b57cec5SDimitry Andric                                   DAG.getConstant(0, dl, getVectorIdxTy(DAG.getDataLayout())));
9490b57cec5SDimitry Andric       SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32,
9500b57cec5SDimitry Andric                                   Arg,
9510b57cec5SDimitry Andric                                   DAG.getConstant(1, dl, getVectorIdxTy(DAG.getDataLayout())));
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric       if (VA.isRegLoc()) {
9540b57cec5SDimitry Andric         RegsToPass.push_back(std::make_pair(VA.getLocReg(), Part0));
9550b57cec5SDimitry Andric         assert(i+1 != e);
9560b57cec5SDimitry Andric         CCValAssign &NextVA = ArgLocs[++i];
9570b57cec5SDimitry Andric         if (NextVA.isRegLoc()) {
9580b57cec5SDimitry Andric           RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Part1));
9590b57cec5SDimitry Andric         } else {
9600b57cec5SDimitry Andric           // Store the second part in stack.
9610b57cec5SDimitry Andric           unsigned Offset = NextVA.getLocMemOffset() + StackOffset;
9620b57cec5SDimitry Andric           SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
9630b57cec5SDimitry Andric           SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);
9640b57cec5SDimitry Andric           PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
9650b57cec5SDimitry Andric           MemOpChains.push_back(
9660b57cec5SDimitry Andric               DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo()));
9670b57cec5SDimitry Andric         }
9680b57cec5SDimitry Andric       } else {
9690b57cec5SDimitry Andric         unsigned Offset = VA.getLocMemOffset() + StackOffset;
9700b57cec5SDimitry Andric         // Store the first part.
9710b57cec5SDimitry Andric         SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
9720b57cec5SDimitry Andric         SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl);
9730b57cec5SDimitry Andric         PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
9740b57cec5SDimitry Andric         MemOpChains.push_back(
9750b57cec5SDimitry Andric             DAG.getStore(Chain, dl, Part0, PtrOff, MachinePointerInfo()));
9760b57cec5SDimitry Andric         // Store the second part.
9770b57cec5SDimitry Andric         PtrOff = DAG.getIntPtrConstant(Offset + 4, dl);
9780b57cec5SDimitry Andric         PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
9790b57cec5SDimitry Andric         MemOpChains.push_back(
9800b57cec5SDimitry Andric             DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo()));
9810b57cec5SDimitry Andric       }
9820b57cec5SDimitry Andric       continue;
9830b57cec5SDimitry Andric     }
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric     // Arguments that can be passed on register must be kept at
9860b57cec5SDimitry Andric     // RegsToPass vector
9870b57cec5SDimitry Andric     if (VA.isRegLoc()) {
9880b57cec5SDimitry Andric       if (VA.getLocVT() != MVT::f32) {
9890b57cec5SDimitry Andric         RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
9900b57cec5SDimitry Andric         continue;
9910b57cec5SDimitry Andric       }
9920b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg);
9930b57cec5SDimitry Andric       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
9940b57cec5SDimitry Andric       continue;
9950b57cec5SDimitry Andric     }
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric     assert(VA.isMemLoc());
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric     // Create a store off the stack pointer for this argument.
10000b57cec5SDimitry Andric     SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
10010b57cec5SDimitry Andric     SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() + StackOffset,
10020b57cec5SDimitry Andric                                            dl);
10030b57cec5SDimitry Andric     PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
10040b57cec5SDimitry Andric     MemOpChains.push_back(
10050b57cec5SDimitry Andric         DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()));
10060b57cec5SDimitry Andric   }
10070b57cec5SDimitry Andric 
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   // Emit all stores, make sure the occur before any copies into physregs.
10100b57cec5SDimitry Andric   if (!MemOpChains.empty())
10110b57cec5SDimitry Andric     Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric   // Build a sequence of copy-to-reg nodes chained together with token
10140b57cec5SDimitry Andric   // chain and flag operands which copy the outgoing args into registers.
10150b57cec5SDimitry Andric   // The InFlag in necessary since all emitted instructions must be
10160b57cec5SDimitry Andric   // stuck together.
10170b57cec5SDimitry Andric   SDValue InFlag;
10180b57cec5SDimitry Andric   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
101981ad6265SDimitry Andric     Register Reg = RegsToPass[i].first;
102081ad6265SDimitry Andric     if (!isTailCall)
102181ad6265SDimitry Andric       Reg = toCallerWindow(Reg);
10220b57cec5SDimitry Andric     Chain = DAG.getCopyToReg(Chain, dl, Reg, RegsToPass[i].second, InFlag);
10230b57cec5SDimitry Andric     InFlag = Chain.getValue(1);
10240b57cec5SDimitry Andric   }
10250b57cec5SDimitry Andric 
10265ffd83dbSDimitry Andric   bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CB);
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric   // If the callee is a GlobalAddress node (quite common, every direct call is)
10290b57cec5SDimitry Andric   // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
10300b57cec5SDimitry Andric   // Likewise ExternalSymbol -> TargetExternalSymbol.
1031e8d8bef9SDimitry Andric   unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30
1032e8d8bef9SDimitry Andric                                         : SparcMCExpr::VK_Sparc_WDISP30;
10330b57cec5SDimitry Andric   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
10340b57cec5SDimitry Andric     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF);
10350b57cec5SDimitry Andric   else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
10360b57cec5SDimitry Andric     Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF);
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric   // Returns a chain & a flag for retval copy to use
10390b57cec5SDimitry Andric   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
10400b57cec5SDimitry Andric   SmallVector<SDValue, 8> Ops;
10410b57cec5SDimitry Andric   Ops.push_back(Chain);
10420b57cec5SDimitry Andric   Ops.push_back(Callee);
10430b57cec5SDimitry Andric   if (hasStructRetAttr)
10440b57cec5SDimitry Andric     Ops.push_back(DAG.getTargetConstant(SRetArgSize, dl, MVT::i32));
104581ad6265SDimitry Andric   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
104681ad6265SDimitry Andric     Register Reg = RegsToPass[i].first;
104781ad6265SDimitry Andric     if (!isTailCall)
104881ad6265SDimitry Andric       Reg = toCallerWindow(Reg);
104981ad6265SDimitry Andric     Ops.push_back(DAG.getRegister(Reg, RegsToPass[i].second.getValueType()));
105081ad6265SDimitry Andric   }
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric   // Add a register mask operand representing the call-preserved registers.
10530b57cec5SDimitry Andric   const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo();
10540b57cec5SDimitry Andric   const uint32_t *Mask =
10550b57cec5SDimitry Andric       ((hasReturnsTwice)
10560b57cec5SDimitry Andric            ? TRI->getRTCallPreservedMask(CallConv)
10570b57cec5SDimitry Andric            : TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv));
10580b57cec5SDimitry Andric   assert(Mask && "Missing call preserved mask for calling convention");
10590b57cec5SDimitry Andric   Ops.push_back(DAG.getRegisterMask(Mask));
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric   if (InFlag.getNode())
10620b57cec5SDimitry Andric     Ops.push_back(InFlag);
10630b57cec5SDimitry Andric 
106481ad6265SDimitry Andric   if (isTailCall) {
106581ad6265SDimitry Andric     DAG.getMachineFunction().getFrameInfo().setHasTailCall();
106681ad6265SDimitry Andric     return DAG.getNode(SPISD::TAIL_CALL, dl, MVT::Other, Ops);
106781ad6265SDimitry Andric   }
106881ad6265SDimitry Andric 
10690b57cec5SDimitry Andric   Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, Ops);
10700b57cec5SDimitry Andric   InFlag = Chain.getValue(1);
10710b57cec5SDimitry Andric 
1072*bdd1243dSDimitry Andric   Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InFlag, dl);
10730b57cec5SDimitry Andric   InFlag = Chain.getValue(1);
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric   // Assign locations to each value returned by this call.
10760b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
10770b57cec5SDimitry Andric   CCState RVInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
10780b57cec5SDimitry Andric                  *DAG.getContext());
10790b57cec5SDimitry Andric 
10800b57cec5SDimitry Andric   RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32);
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric   // Copy all of the result registers out of their specified physreg.
10830b57cec5SDimitry Andric   for (unsigned i = 0; i != RVLocs.size(); ++i) {
1084f3fd488fSDimitry Andric     assert(RVLocs[i].isRegLoc() && "Can only return in registers!");
10850b57cec5SDimitry Andric     if (RVLocs[i].getLocVT() == MVT::v2i32) {
10860b57cec5SDimitry Andric       SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2i32);
10870b57cec5SDimitry Andric       SDValue Lo = DAG.getCopyFromReg(
10880b57cec5SDimitry Andric           Chain, dl, toCallerWindow(RVLocs[i++].getLocReg()), MVT::i32, InFlag);
10890b57cec5SDimitry Andric       Chain = Lo.getValue(1);
10900b57cec5SDimitry Andric       InFlag = Lo.getValue(2);
10910b57cec5SDimitry Andric       Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Lo,
10920b57cec5SDimitry Andric                         DAG.getConstant(0, dl, MVT::i32));
10930b57cec5SDimitry Andric       SDValue Hi = DAG.getCopyFromReg(
10940b57cec5SDimitry Andric           Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), MVT::i32, InFlag);
10950b57cec5SDimitry Andric       Chain = Hi.getValue(1);
10960b57cec5SDimitry Andric       InFlag = Hi.getValue(2);
10970b57cec5SDimitry Andric       Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Hi,
10980b57cec5SDimitry Andric                         DAG.getConstant(1, dl, MVT::i32));
10990b57cec5SDimitry Andric       InVals.push_back(Vec);
11000b57cec5SDimitry Andric     } else {
11010b57cec5SDimitry Andric       Chain =
11020b57cec5SDimitry Andric           DAG.getCopyFromReg(Chain, dl, toCallerWindow(RVLocs[i].getLocReg()),
11030b57cec5SDimitry Andric                              RVLocs[i].getValVT(), InFlag)
11040b57cec5SDimitry Andric               .getValue(1);
11050b57cec5SDimitry Andric       InFlag = Chain.getValue(2);
11060b57cec5SDimitry Andric       InVals.push_back(Chain.getValue(0));
11070b57cec5SDimitry Andric     }
11080b57cec5SDimitry Andric   }
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric   return Chain;
11110b57cec5SDimitry Andric }
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric // FIXME? Maybe this could be a TableGen attribute on some registers and
11140b57cec5SDimitry Andric // this table could be generated automatically from RegInfo.
1115480093f4SDimitry Andric Register SparcTargetLowering::getRegisterByName(const char* RegName, LLT VT,
11168bcb0991SDimitry Andric                                                 const MachineFunction &MF) const {
11175ffd83dbSDimitry Andric   Register Reg = StringSwitch<Register>(RegName)
11180b57cec5SDimitry Andric     .Case("i0", SP::I0).Case("i1", SP::I1).Case("i2", SP::I2).Case("i3", SP::I3)
11190b57cec5SDimitry Andric     .Case("i4", SP::I4).Case("i5", SP::I5).Case("i6", SP::I6).Case("i7", SP::I7)
11200b57cec5SDimitry Andric     .Case("o0", SP::O0).Case("o1", SP::O1).Case("o2", SP::O2).Case("o3", SP::O3)
11210b57cec5SDimitry Andric     .Case("o4", SP::O4).Case("o5", SP::O5).Case("o6", SP::O6).Case("o7", SP::O7)
11220b57cec5SDimitry Andric     .Case("l0", SP::L0).Case("l1", SP::L1).Case("l2", SP::L2).Case("l3", SP::L3)
11230b57cec5SDimitry Andric     .Case("l4", SP::L4).Case("l5", SP::L5).Case("l6", SP::L6).Case("l7", SP::L7)
11240b57cec5SDimitry Andric     .Case("g0", SP::G0).Case("g1", SP::G1).Case("g2", SP::G2).Case("g3", SP::G3)
11250b57cec5SDimitry Andric     .Case("g4", SP::G4).Case("g5", SP::G5).Case("g6", SP::G6).Case("g7", SP::G7)
11260b57cec5SDimitry Andric     .Default(0);
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric   if (Reg)
11290b57cec5SDimitry Andric     return Reg;
11300b57cec5SDimitry Andric 
11310b57cec5SDimitry Andric   report_fatal_error("Invalid register name global variable");
11320b57cec5SDimitry Andric }
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric // Fixup floating point arguments in the ... part of a varargs call.
11350b57cec5SDimitry Andric //
11360b57cec5SDimitry Andric // The SPARC v9 ABI requires that floating point arguments are treated the same
11370b57cec5SDimitry Andric // as integers when calling a varargs function. This does not apply to the
11380b57cec5SDimitry Andric // fixed arguments that are part of the function's prototype.
11390b57cec5SDimitry Andric //
11400b57cec5SDimitry Andric // This function post-processes a CCValAssign array created by
11410b57cec5SDimitry Andric // AnalyzeCallOperands().
11420b57cec5SDimitry Andric static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs,
11430b57cec5SDimitry Andric                                    ArrayRef<ISD::OutputArg> Outs) {
11440b57cec5SDimitry Andric   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1145*bdd1243dSDimitry Andric     CCValAssign &VA = ArgLocs[i];
11460b57cec5SDimitry Andric     MVT ValTy = VA.getLocVT();
11470b57cec5SDimitry Andric     // FIXME: What about f32 arguments? C promotes them to f64 when calling
11480b57cec5SDimitry Andric     // varargs functions.
11490b57cec5SDimitry Andric     if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128))
11500b57cec5SDimitry Andric       continue;
11510b57cec5SDimitry Andric     // The fixed arguments to a varargs function still go in FP registers.
11520b57cec5SDimitry Andric     if (Outs[VA.getValNo()].IsFixed)
11530b57cec5SDimitry Andric       continue;
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric     // This floating point argument should be reassigned.
11560b57cec5SDimitry Andric     // Determine the offset into the argument array.
11575ffd83dbSDimitry Andric     Register firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0;
11580b57cec5SDimitry Andric     unsigned argSize  = (ValTy == MVT::f64) ? 8 : 16;
11590b57cec5SDimitry Andric     unsigned Offset = argSize * (VA.getLocReg() - firstReg);
11600b57cec5SDimitry Andric     assert(Offset < 16*8 && "Offset out of range, bad register enum?");
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric     if (Offset < 6*8) {
11630b57cec5SDimitry Andric       // This argument should go in %i0-%i5.
11640b57cec5SDimitry Andric       unsigned IReg = SP::I0 + Offset/8;
11650b57cec5SDimitry Andric       if (ValTy == MVT::f64)
11660b57cec5SDimitry Andric         // Full register, just bitconvert into i64.
1167*bdd1243dSDimitry Andric         VA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), IReg, MVT::i64,
1168*bdd1243dSDimitry Andric                                  CCValAssign::BCvt);
11690b57cec5SDimitry Andric       else {
11700b57cec5SDimitry Andric         assert(ValTy == MVT::f128 && "Unexpected type!");
11710b57cec5SDimitry Andric         // Full register, just bitconvert into i128 -- We will lower this into
11720b57cec5SDimitry Andric         // two i64s in LowerCall_64.
1173*bdd1243dSDimitry Andric         VA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), IReg,
1174*bdd1243dSDimitry Andric                                        MVT::i128, CCValAssign::BCvt);
11750b57cec5SDimitry Andric       }
11760b57cec5SDimitry Andric     } else {
11770b57cec5SDimitry Andric       // This needs to go to memory, we're out of integer registers.
1178*bdd1243dSDimitry Andric       VA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), Offset,
1179*bdd1243dSDimitry Andric                                VA.getLocVT(), VA.getLocInfo());
11800b57cec5SDimitry Andric     }
11810b57cec5SDimitry Andric   }
11820b57cec5SDimitry Andric }
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric // Lower a call for the 64-bit ABI.
11850b57cec5SDimitry Andric SDValue
11860b57cec5SDimitry Andric SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
11870b57cec5SDimitry Andric                                   SmallVectorImpl<SDValue> &InVals) const {
11880b57cec5SDimitry Andric   SelectionDAG &DAG = CLI.DAG;
11890b57cec5SDimitry Andric   SDLoc DL = CLI.DL;
11900b57cec5SDimitry Andric   SDValue Chain = CLI.Chain;
11910b57cec5SDimitry Andric   auto PtrVT = getPointerTy(DAG.getDataLayout());
11920b57cec5SDimitry Andric 
11930b57cec5SDimitry Andric   // Analyze operands of the call, assigning locations to each operand.
11940b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
11950b57cec5SDimitry Andric   CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs,
11960b57cec5SDimitry Andric                  *DAG.getContext());
11970b57cec5SDimitry Andric   CCInfo.AnalyzeCallOperands(CLI.Outs, CC_Sparc64);
11980b57cec5SDimitry Andric 
1199*bdd1243dSDimitry Andric   CLI.IsTailCall = CLI.IsTailCall && IsEligibleForTailCallOptimization(
1200*bdd1243dSDimitry Andric                                          CCInfo, CLI, DAG.getMachineFunction());
1201*bdd1243dSDimitry Andric 
12020b57cec5SDimitry Andric   // Get the size of the outgoing arguments stack space requirement.
12030b57cec5SDimitry Andric   // The stack offset computed by CC_Sparc64 includes all arguments.
12040b57cec5SDimitry Andric   // Called functions expect 6 argument words to exist in the stack frame, used
12050b57cec5SDimitry Andric   // or not.
1206*bdd1243dSDimitry Andric   unsigned StackReserved = 6 * 8u;
1207*bdd1243dSDimitry Andric   unsigned ArgsSize = std::max(StackReserved, CCInfo.getNextStackOffset());
12080b57cec5SDimitry Andric 
12090b57cec5SDimitry Andric   // Keep stack frames 16-byte aligned.
12100b57cec5SDimitry Andric   ArgsSize = alignTo(ArgsSize, 16);
12110b57cec5SDimitry Andric 
12120b57cec5SDimitry Andric   // Varargs calls require special treatment.
12130b57cec5SDimitry Andric   if (CLI.IsVarArg)
12140b57cec5SDimitry Andric     fixupVariableFloatArgs(ArgLocs, CLI.Outs);
12150b57cec5SDimitry Andric 
1216*bdd1243dSDimitry Andric   assert(!CLI.IsTailCall || ArgsSize == StackReserved);
1217*bdd1243dSDimitry Andric 
12180b57cec5SDimitry Andric   // Adjust the stack pointer to make room for the arguments.
12190b57cec5SDimitry Andric   // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls
12200b57cec5SDimitry Andric   // with more than 6 arguments.
1221*bdd1243dSDimitry Andric   if (!CLI.IsTailCall)
12220b57cec5SDimitry Andric     Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL);
12230b57cec5SDimitry Andric 
12240b57cec5SDimitry Andric   // Collect the set of registers to pass to the function and their values.
12250b57cec5SDimitry Andric   // This will be emitted as a sequence of CopyToReg nodes glued to the call
12260b57cec5SDimitry Andric   // instruction.
12275ffd83dbSDimitry Andric   SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric   // Collect chains from all the memory opeations that copy arguments to the
12300b57cec5SDimitry Andric   // stack. They must follow the stack pointer adjustment above and precede the
12310b57cec5SDimitry Andric   // call instruction itself.
12320b57cec5SDimitry Andric   SmallVector<SDValue, 8> MemOpChains;
12330b57cec5SDimitry Andric 
12340b57cec5SDimitry Andric   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
12350b57cec5SDimitry Andric     const CCValAssign &VA = ArgLocs[i];
12360b57cec5SDimitry Andric     SDValue Arg = CLI.OutVals[i];
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric     // Promote the value if needed.
12390b57cec5SDimitry Andric     switch (VA.getLocInfo()) {
12400b57cec5SDimitry Andric     default:
12410b57cec5SDimitry Andric       llvm_unreachable("Unknown location info!");
12420b57cec5SDimitry Andric     case CCValAssign::Full:
12430b57cec5SDimitry Andric       break;
12440b57cec5SDimitry Andric     case CCValAssign::SExt:
12450b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
12460b57cec5SDimitry Andric       break;
12470b57cec5SDimitry Andric     case CCValAssign::ZExt:
12480b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
12490b57cec5SDimitry Andric       break;
12500b57cec5SDimitry Andric     case CCValAssign::AExt:
12510b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
12520b57cec5SDimitry Andric       break;
12530b57cec5SDimitry Andric     case CCValAssign::BCvt:
12540b57cec5SDimitry Andric       // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But
12550b57cec5SDimitry Andric       // SPARC does not support i128 natively. Lower it into two i64, see below.
12560b57cec5SDimitry Andric       if (!VA.needsCustom() || VA.getValVT() != MVT::f128
12570b57cec5SDimitry Andric           || VA.getLocVT() != MVT::i128)
12580b57cec5SDimitry Andric         Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
12590b57cec5SDimitry Andric       break;
12600b57cec5SDimitry Andric     }
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric     if (VA.isRegLoc()) {
12630b57cec5SDimitry Andric       if (VA.needsCustom() && VA.getValVT() == MVT::f128
12640b57cec5SDimitry Andric           && VA.getLocVT() == MVT::i128) {
12650b57cec5SDimitry Andric         // Store and reload into the integer register reg and reg+1.
12660b57cec5SDimitry Andric         unsigned Offset = 8 * (VA.getLocReg() - SP::I0);
12670b57cec5SDimitry Andric         unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128;
12680b57cec5SDimitry Andric         SDValue StackPtr = DAG.getRegister(SP::O6, PtrVT);
12690b57cec5SDimitry Andric         SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset, DL);
12700b57cec5SDimitry Andric         HiPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, HiPtrOff);
12710b57cec5SDimitry Andric         SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8, DL);
12720b57cec5SDimitry Andric         LoPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, LoPtrOff);
12730b57cec5SDimitry Andric 
12740b57cec5SDimitry Andric         // Store to %sp+BIAS+128+Offset
12750b57cec5SDimitry Andric         SDValue Store =
12760b57cec5SDimitry Andric             DAG.getStore(Chain, DL, Arg, HiPtrOff, MachinePointerInfo());
12770b57cec5SDimitry Andric         // Load into Reg and Reg+1
12780b57cec5SDimitry Andric         SDValue Hi64 =
12790b57cec5SDimitry Andric             DAG.getLoad(MVT::i64, DL, Store, HiPtrOff, MachinePointerInfo());
12800b57cec5SDimitry Andric         SDValue Lo64 =
12810b57cec5SDimitry Andric             DAG.getLoad(MVT::i64, DL, Store, LoPtrOff, MachinePointerInfo());
1282*bdd1243dSDimitry Andric 
1283*bdd1243dSDimitry Andric         Register HiReg = VA.getLocReg();
1284*bdd1243dSDimitry Andric         Register LoReg = VA.getLocReg() + 1;
1285*bdd1243dSDimitry Andric         if (!CLI.IsTailCall) {
1286*bdd1243dSDimitry Andric           HiReg = toCallerWindow(HiReg);
1287*bdd1243dSDimitry Andric           LoReg = toCallerWindow(LoReg);
1288*bdd1243dSDimitry Andric         }
1289*bdd1243dSDimitry Andric 
1290*bdd1243dSDimitry Andric         RegsToPass.push_back(std::make_pair(HiReg, Hi64));
1291*bdd1243dSDimitry Andric         RegsToPass.push_back(std::make_pair(LoReg, Lo64));
12920b57cec5SDimitry Andric         continue;
12930b57cec5SDimitry Andric       }
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric       // The custom bit on an i32 return value indicates that it should be
12960b57cec5SDimitry Andric       // passed in the high bits of the register.
12970b57cec5SDimitry Andric       if (VA.getValVT() == MVT::i32 && VA.needsCustom()) {
12980b57cec5SDimitry Andric         Arg = DAG.getNode(ISD::SHL, DL, MVT::i64, Arg,
12990b57cec5SDimitry Andric                           DAG.getConstant(32, DL, MVT::i32));
13000b57cec5SDimitry Andric 
13010b57cec5SDimitry Andric         // The next value may go in the low bits of the same register.
13020b57cec5SDimitry Andric         // Handle both at once.
13030b57cec5SDimitry Andric         if (i+1 < ArgLocs.size() && ArgLocs[i+1].isRegLoc() &&
13040b57cec5SDimitry Andric             ArgLocs[i+1].getLocReg() == VA.getLocReg()) {
13050b57cec5SDimitry Andric           SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64,
13060b57cec5SDimitry Andric                                    CLI.OutVals[i+1]);
13070b57cec5SDimitry Andric           Arg = DAG.getNode(ISD::OR, DL, MVT::i64, Arg, NV);
13080b57cec5SDimitry Andric           // Skip the next value, it's already done.
13090b57cec5SDimitry Andric           ++i;
13100b57cec5SDimitry Andric         }
13110b57cec5SDimitry Andric       }
1312*bdd1243dSDimitry Andric 
1313*bdd1243dSDimitry Andric       Register Reg = VA.getLocReg();
1314*bdd1243dSDimitry Andric       if (!CLI.IsTailCall)
1315*bdd1243dSDimitry Andric         Reg = toCallerWindow(Reg);
1316*bdd1243dSDimitry Andric       RegsToPass.push_back(std::make_pair(Reg, Arg));
13170b57cec5SDimitry Andric       continue;
13180b57cec5SDimitry Andric     }
13190b57cec5SDimitry Andric 
13200b57cec5SDimitry Andric     assert(VA.isMemLoc());
13210b57cec5SDimitry Andric 
13220b57cec5SDimitry Andric     // Create a store off the stack pointer for this argument.
13230b57cec5SDimitry Andric     SDValue StackPtr = DAG.getRegister(SP::O6, PtrVT);
13240b57cec5SDimitry Andric     // The argument area starts at %fp+BIAS+128 in the callee frame,
13250b57cec5SDimitry Andric     // %sp+BIAS+128 in ours.
13260b57cec5SDimitry Andric     SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() +
13270b57cec5SDimitry Andric                                            Subtarget->getStackPointerBias() +
13280b57cec5SDimitry Andric                                            128, DL);
13290b57cec5SDimitry Andric     PtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff);
13300b57cec5SDimitry Andric     MemOpChains.push_back(
13310b57cec5SDimitry Andric         DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo()));
13320b57cec5SDimitry Andric   }
13330b57cec5SDimitry Andric 
13340b57cec5SDimitry Andric   // Emit all stores, make sure they occur before the call.
13350b57cec5SDimitry Andric   if (!MemOpChains.empty())
13360b57cec5SDimitry Andric     Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric   // Build a sequence of CopyToReg nodes glued together with token chain and
13390b57cec5SDimitry Andric   // glue operands which copy the outgoing args into registers. The InGlue is
13400b57cec5SDimitry Andric   // necessary since all emitted instructions must be stuck together in order
13410b57cec5SDimitry Andric   // to pass the live physical registers.
13420b57cec5SDimitry Andric   SDValue InGlue;
13430b57cec5SDimitry Andric   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
13440b57cec5SDimitry Andric     Chain = DAG.getCopyToReg(Chain, DL,
13450b57cec5SDimitry Andric                              RegsToPass[i].first, RegsToPass[i].second, InGlue);
13460b57cec5SDimitry Andric     InGlue = Chain.getValue(1);
13470b57cec5SDimitry Andric   }
13480b57cec5SDimitry Andric 
13490b57cec5SDimitry Andric   // If the callee is a GlobalAddress node (quite common, every direct call is)
13500b57cec5SDimitry Andric   // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
13510b57cec5SDimitry Andric   // Likewise ExternalSymbol -> TargetExternalSymbol.
13520b57cec5SDimitry Andric   SDValue Callee = CLI.Callee;
13535ffd83dbSDimitry Andric   bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CB);
1354e8d8bef9SDimitry Andric   unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30
1355e8d8bef9SDimitry Andric                                         : SparcMCExpr::VK_Sparc_WDISP30;
13560b57cec5SDimitry Andric   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
13570b57cec5SDimitry Andric     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, TF);
13580b57cec5SDimitry Andric   else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
13590b57cec5SDimitry Andric     Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, TF);
13600b57cec5SDimitry Andric 
13610b57cec5SDimitry Andric   // Build the operands for the call instruction itself.
13620b57cec5SDimitry Andric   SmallVector<SDValue, 8> Ops;
13630b57cec5SDimitry Andric   Ops.push_back(Chain);
13640b57cec5SDimitry Andric   Ops.push_back(Callee);
13650b57cec5SDimitry Andric   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
13660b57cec5SDimitry Andric     Ops.push_back(DAG.getRegister(RegsToPass[i].first,
13670b57cec5SDimitry Andric                                   RegsToPass[i].second.getValueType()));
13680b57cec5SDimitry Andric 
13690b57cec5SDimitry Andric   // Add a register mask operand representing the call-preserved registers.
13700b57cec5SDimitry Andric   const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo();
13710b57cec5SDimitry Andric   const uint32_t *Mask =
13720b57cec5SDimitry Andric       ((hasReturnsTwice) ? TRI->getRTCallPreservedMask(CLI.CallConv)
13730b57cec5SDimitry Andric                          : TRI->getCallPreservedMask(DAG.getMachineFunction(),
13740b57cec5SDimitry Andric                                                      CLI.CallConv));
13750b57cec5SDimitry Andric   assert(Mask && "Missing call preserved mask for calling convention");
13760b57cec5SDimitry Andric   Ops.push_back(DAG.getRegisterMask(Mask));
13770b57cec5SDimitry Andric 
13780b57cec5SDimitry Andric   // Make sure the CopyToReg nodes are glued to the call instruction which
13790b57cec5SDimitry Andric   // consumes the registers.
13800b57cec5SDimitry Andric   if (InGlue.getNode())
13810b57cec5SDimitry Andric     Ops.push_back(InGlue);
13820b57cec5SDimitry Andric 
13830b57cec5SDimitry Andric   // Now the call itself.
1384*bdd1243dSDimitry Andric   if (CLI.IsTailCall) {
1385*bdd1243dSDimitry Andric     DAG.getMachineFunction().getFrameInfo().setHasTailCall();
1386*bdd1243dSDimitry Andric     return DAG.getNode(SPISD::TAIL_CALL, DL, MVT::Other, Ops);
1387*bdd1243dSDimitry Andric   }
13880b57cec5SDimitry Andric   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
13890b57cec5SDimitry Andric   Chain = DAG.getNode(SPISD::CALL, DL, NodeTys, Ops);
13900b57cec5SDimitry Andric   InGlue = Chain.getValue(1);
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric   // Revert the stack pointer immediately after the call.
1393*bdd1243dSDimitry Andric   Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InGlue, DL);
13940b57cec5SDimitry Andric   InGlue = Chain.getValue(1);
13950b57cec5SDimitry Andric 
13960b57cec5SDimitry Andric   // Now extract the return values. This is more or less the same as
13970b57cec5SDimitry Andric   // LowerFormalArguments_64.
13980b57cec5SDimitry Andric 
13990b57cec5SDimitry Andric   // Assign locations to each value returned by this call.
14000b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
14010b57cec5SDimitry Andric   CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs,
14020b57cec5SDimitry Andric                  *DAG.getContext());
14030b57cec5SDimitry Andric 
14040b57cec5SDimitry Andric   // Set inreg flag manually for codegen generated library calls that
14050b57cec5SDimitry Andric   // return float.
14065ffd83dbSDimitry Andric   if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && !CLI.CB)
14070b57cec5SDimitry Andric     CLI.Ins[0].Flags.setInReg();
14080b57cec5SDimitry Andric 
14090b57cec5SDimitry Andric   RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64);
14100b57cec5SDimitry Andric 
14110b57cec5SDimitry Andric   // Copy all of the result registers out of their specified physreg.
14120b57cec5SDimitry Andric   for (unsigned i = 0; i != RVLocs.size(); ++i) {
14130b57cec5SDimitry Andric     CCValAssign &VA = RVLocs[i];
1414f3fd488fSDimitry Andric     assert(VA.isRegLoc() && "Can only return in registers!");
14150b57cec5SDimitry Andric     unsigned Reg = toCallerWindow(VA.getLocReg());
14160b57cec5SDimitry Andric 
14170b57cec5SDimitry Andric     // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can
14180b57cec5SDimitry Andric     // reside in the same register in the high and low bits. Reuse the
14190b57cec5SDimitry Andric     // CopyFromReg previous node to avoid duplicate copies.
14200b57cec5SDimitry Andric     SDValue RV;
14210b57cec5SDimitry Andric     if (RegisterSDNode *SrcReg = dyn_cast<RegisterSDNode>(Chain.getOperand(1)))
14220b57cec5SDimitry Andric       if (SrcReg->getReg() == Reg && Chain->getOpcode() == ISD::CopyFromReg)
14230b57cec5SDimitry Andric         RV = Chain.getValue(0);
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric     // But usually we'll create a new CopyFromReg for a different register.
14260b57cec5SDimitry Andric     if (!RV.getNode()) {
14270b57cec5SDimitry Andric       RV = DAG.getCopyFromReg(Chain, DL, Reg, RVLocs[i].getLocVT(), InGlue);
14280b57cec5SDimitry Andric       Chain = RV.getValue(1);
14290b57cec5SDimitry Andric       InGlue = Chain.getValue(2);
14300b57cec5SDimitry Andric     }
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric     // Get the high bits for i32 struct elements.
14330b57cec5SDimitry Andric     if (VA.getValVT() == MVT::i32 && VA.needsCustom())
14340b57cec5SDimitry Andric       RV = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), RV,
14350b57cec5SDimitry Andric                        DAG.getConstant(32, DL, MVT::i32));
14360b57cec5SDimitry Andric 
14370b57cec5SDimitry Andric     // The callee promoted the return value, so insert an Assert?ext SDNode so
14380b57cec5SDimitry Andric     // we won't promote the value again in this function.
14390b57cec5SDimitry Andric     switch (VA.getLocInfo()) {
14400b57cec5SDimitry Andric     case CCValAssign::SExt:
14410b57cec5SDimitry Andric       RV = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), RV,
14420b57cec5SDimitry Andric                        DAG.getValueType(VA.getValVT()));
14430b57cec5SDimitry Andric       break;
14440b57cec5SDimitry Andric     case CCValAssign::ZExt:
14450b57cec5SDimitry Andric       RV = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), RV,
14460b57cec5SDimitry Andric                        DAG.getValueType(VA.getValVT()));
14470b57cec5SDimitry Andric       break;
14480b57cec5SDimitry Andric     default:
14490b57cec5SDimitry Andric       break;
14500b57cec5SDimitry Andric     }
14510b57cec5SDimitry Andric 
14520b57cec5SDimitry Andric     // Truncate the register down to the return value type.
14530b57cec5SDimitry Andric     if (VA.isExtInLoc())
14540b57cec5SDimitry Andric       RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV);
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric     InVals.push_back(RV);
14570b57cec5SDimitry Andric   }
14580b57cec5SDimitry Andric 
14590b57cec5SDimitry Andric   return Chain;
14600b57cec5SDimitry Andric }
14610b57cec5SDimitry Andric 
14620b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14630b57cec5SDimitry Andric // TargetLowering Implementation
14640b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14650b57cec5SDimitry Andric 
14660b57cec5SDimitry Andric TargetLowering::AtomicExpansionKind SparcTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
14670b57cec5SDimitry Andric   if (AI->getOperation() == AtomicRMWInst::Xchg &&
14680b57cec5SDimitry Andric       AI->getType()->getPrimitiveSizeInBits() == 32)
14690b57cec5SDimitry Andric     return AtomicExpansionKind::None; // Uses xchg instruction
14700b57cec5SDimitry Andric 
14710b57cec5SDimitry Andric   return AtomicExpansionKind::CmpXChg;
14720b57cec5SDimitry Andric }
14730b57cec5SDimitry Andric 
1474*bdd1243dSDimitry Andric /// intCondCCodeToRcond - Convert a DAG integer condition code to a SPARC
1475*bdd1243dSDimitry Andric /// rcond condition.
1476*bdd1243dSDimitry Andric static SPCC::CondCodes intCondCCodeToRcond(ISD::CondCode CC) {
1477*bdd1243dSDimitry Andric   switch (CC) {
1478*bdd1243dSDimitry Andric   default:
1479*bdd1243dSDimitry Andric     llvm_unreachable("Unknown/unsigned integer condition code!");
1480*bdd1243dSDimitry Andric   case ISD::SETEQ:
1481*bdd1243dSDimitry Andric     return SPCC::REG_Z;
1482*bdd1243dSDimitry Andric   case ISD::SETNE:
1483*bdd1243dSDimitry Andric     return SPCC::REG_NZ;
1484*bdd1243dSDimitry Andric   case ISD::SETLT:
1485*bdd1243dSDimitry Andric     return SPCC::REG_LZ;
1486*bdd1243dSDimitry Andric   case ISD::SETGT:
1487*bdd1243dSDimitry Andric     return SPCC::REG_GZ;
1488*bdd1243dSDimitry Andric   case ISD::SETLE:
1489*bdd1243dSDimitry Andric     return SPCC::REG_LEZ;
1490*bdd1243dSDimitry Andric   case ISD::SETGE:
1491*bdd1243dSDimitry Andric     return SPCC::REG_GEZ;
1492*bdd1243dSDimitry Andric   }
1493*bdd1243dSDimitry Andric }
1494*bdd1243dSDimitry Andric 
14950b57cec5SDimitry Andric /// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC
14960b57cec5SDimitry Andric /// condition.
14970b57cec5SDimitry Andric static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) {
14980b57cec5SDimitry Andric   switch (CC) {
14990b57cec5SDimitry Andric   default: llvm_unreachable("Unknown integer condition code!");
15000b57cec5SDimitry Andric   case ISD::SETEQ:  return SPCC::ICC_E;
15010b57cec5SDimitry Andric   case ISD::SETNE:  return SPCC::ICC_NE;
15020b57cec5SDimitry Andric   case ISD::SETLT:  return SPCC::ICC_L;
15030b57cec5SDimitry Andric   case ISD::SETGT:  return SPCC::ICC_G;
15040b57cec5SDimitry Andric   case ISD::SETLE:  return SPCC::ICC_LE;
15050b57cec5SDimitry Andric   case ISD::SETGE:  return SPCC::ICC_GE;
15060b57cec5SDimitry Andric   case ISD::SETULT: return SPCC::ICC_CS;
15070b57cec5SDimitry Andric   case ISD::SETULE: return SPCC::ICC_LEU;
15080b57cec5SDimitry Andric   case ISD::SETUGT: return SPCC::ICC_GU;
15090b57cec5SDimitry Andric   case ISD::SETUGE: return SPCC::ICC_CC;
15100b57cec5SDimitry Andric   }
15110b57cec5SDimitry Andric }
15120b57cec5SDimitry Andric 
15130b57cec5SDimitry Andric /// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC
15140b57cec5SDimitry Andric /// FCC condition.
15150b57cec5SDimitry Andric static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) {
15160b57cec5SDimitry Andric   switch (CC) {
15170b57cec5SDimitry Andric   default: llvm_unreachable("Unknown fp condition code!");
15180b57cec5SDimitry Andric   case ISD::SETEQ:
15190b57cec5SDimitry Andric   case ISD::SETOEQ: return SPCC::FCC_E;
15200b57cec5SDimitry Andric   case ISD::SETNE:
15210b57cec5SDimitry Andric   case ISD::SETUNE: return SPCC::FCC_NE;
15220b57cec5SDimitry Andric   case ISD::SETLT:
15230b57cec5SDimitry Andric   case ISD::SETOLT: return SPCC::FCC_L;
15240b57cec5SDimitry Andric   case ISD::SETGT:
15250b57cec5SDimitry Andric   case ISD::SETOGT: return SPCC::FCC_G;
15260b57cec5SDimitry Andric   case ISD::SETLE:
15270b57cec5SDimitry Andric   case ISD::SETOLE: return SPCC::FCC_LE;
15280b57cec5SDimitry Andric   case ISD::SETGE:
15290b57cec5SDimitry Andric   case ISD::SETOGE: return SPCC::FCC_GE;
15300b57cec5SDimitry Andric   case ISD::SETULT: return SPCC::FCC_UL;
15310b57cec5SDimitry Andric   case ISD::SETULE: return SPCC::FCC_ULE;
15320b57cec5SDimitry Andric   case ISD::SETUGT: return SPCC::FCC_UG;
15330b57cec5SDimitry Andric   case ISD::SETUGE: return SPCC::FCC_UGE;
15340b57cec5SDimitry Andric   case ISD::SETUO:  return SPCC::FCC_U;
15350b57cec5SDimitry Andric   case ISD::SETO:   return SPCC::FCC_O;
15360b57cec5SDimitry Andric   case ISD::SETONE: return SPCC::FCC_LG;
15370b57cec5SDimitry Andric   case ISD::SETUEQ: return SPCC::FCC_UE;
15380b57cec5SDimitry Andric   }
15390b57cec5SDimitry Andric }
15400b57cec5SDimitry Andric 
15410b57cec5SDimitry Andric SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
15420b57cec5SDimitry Andric                                          const SparcSubtarget &STI)
15430b57cec5SDimitry Andric     : TargetLowering(TM), Subtarget(&STI) {
154481ad6265SDimitry Andric   MVT PtrVT = MVT::getIntegerVT(TM.getPointerSizeInBits(0));
15450b57cec5SDimitry Andric 
15460b57cec5SDimitry Andric   // Instructions which use registers as conditionals examine all the
15470b57cec5SDimitry Andric   // bits (as does the pseudo SELECT_CC expansion). I don't think it
15480b57cec5SDimitry Andric   // matters much whether it's ZeroOrOneBooleanContent, or
15490b57cec5SDimitry Andric   // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the
15500b57cec5SDimitry Andric   // former.
15510b57cec5SDimitry Andric   setBooleanContents(ZeroOrOneBooleanContent);
15520b57cec5SDimitry Andric   setBooleanVectorContents(ZeroOrOneBooleanContent);
15530b57cec5SDimitry Andric 
15540b57cec5SDimitry Andric   // Set up the register classes.
15550b57cec5SDimitry Andric   addRegisterClass(MVT::i32, &SP::IntRegsRegClass);
15560b57cec5SDimitry Andric   if (!Subtarget->useSoftFloat()) {
15570b57cec5SDimitry Andric     addRegisterClass(MVT::f32, &SP::FPRegsRegClass);
15580b57cec5SDimitry Andric     addRegisterClass(MVT::f64, &SP::DFPRegsRegClass);
15590b57cec5SDimitry Andric     addRegisterClass(MVT::f128, &SP::QFPRegsRegClass);
15600b57cec5SDimitry Andric   }
15610b57cec5SDimitry Andric   if (Subtarget->is64Bit()) {
15620b57cec5SDimitry Andric     addRegisterClass(MVT::i64, &SP::I64RegsRegClass);
15630b57cec5SDimitry Andric   } else {
15640b57cec5SDimitry Andric     // On 32bit sparc, we define a double-register 32bit register
15650b57cec5SDimitry Andric     // class, as well. This is modeled in LLVM as a 2-vector of i32.
15660b57cec5SDimitry Andric     addRegisterClass(MVT::v2i32, &SP::IntPairRegClass);
15670b57cec5SDimitry Andric 
15680b57cec5SDimitry Andric     // ...but almost all operations must be expanded, so set that as
15690b57cec5SDimitry Andric     // the default.
15700b57cec5SDimitry Andric     for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
15710b57cec5SDimitry Andric       setOperationAction(Op, MVT::v2i32, Expand);
15720b57cec5SDimitry Andric     }
15730b57cec5SDimitry Andric     // Truncating/extending stores/loads are also not supported.
15748bcb0991SDimitry Andric     for (MVT VT : MVT::integer_fixedlen_vector_valuetypes()) {
15750b57cec5SDimitry Andric       setLoadExtAction(ISD::SEXTLOAD, VT, MVT::v2i32, Expand);
15760b57cec5SDimitry Andric       setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::v2i32, Expand);
15770b57cec5SDimitry Andric       setLoadExtAction(ISD::EXTLOAD, VT, MVT::v2i32, Expand);
15780b57cec5SDimitry Andric 
15790b57cec5SDimitry Andric       setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, VT, Expand);
15800b57cec5SDimitry Andric       setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, VT, Expand);
15810b57cec5SDimitry Andric       setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, VT, Expand);
15820b57cec5SDimitry Andric 
15830b57cec5SDimitry Andric       setTruncStoreAction(VT, MVT::v2i32, Expand);
15840b57cec5SDimitry Andric       setTruncStoreAction(MVT::v2i32, VT, Expand);
15850b57cec5SDimitry Andric     }
15860b57cec5SDimitry Andric     // However, load and store *are* legal.
15870b57cec5SDimitry Andric     setOperationAction(ISD::LOAD, MVT::v2i32, Legal);
15880b57cec5SDimitry Andric     setOperationAction(ISD::STORE, MVT::v2i32, Legal);
15890b57cec5SDimitry Andric     setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Legal);
15900b57cec5SDimitry Andric     setOperationAction(ISD::BUILD_VECTOR, MVT::v2i32, Legal);
15910b57cec5SDimitry Andric 
15920b57cec5SDimitry Andric     // And we need to promote i64 loads/stores into vector load/store
15930b57cec5SDimitry Andric     setOperationAction(ISD::LOAD, MVT::i64, Custom);
15940b57cec5SDimitry Andric     setOperationAction(ISD::STORE, MVT::i64, Custom);
15950b57cec5SDimitry Andric 
15960b57cec5SDimitry Andric     // Sadly, this doesn't work:
15970b57cec5SDimitry Andric     //    AddPromotedToType(ISD::LOAD, MVT::i64, MVT::v2i32);
15980b57cec5SDimitry Andric     //    AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32);
15990b57cec5SDimitry Andric   }
16000b57cec5SDimitry Andric 
16010b57cec5SDimitry Andric   // Turn FP extload into load/fpextend
16020b57cec5SDimitry Andric   for (MVT VT : MVT::fp_valuetypes()) {
16035ffd83dbSDimitry Andric     setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand);
16040b57cec5SDimitry Andric     setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
16050b57cec5SDimitry Andric     setLoadExtAction(ISD::EXTLOAD, VT, MVT::f64, Expand);
16060b57cec5SDimitry Andric   }
16070b57cec5SDimitry Andric 
16080b57cec5SDimitry Andric   // Sparc doesn't have i1 sign extending load
16090b57cec5SDimitry Andric   for (MVT VT : MVT::integer_valuetypes())
16100b57cec5SDimitry Andric     setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
16110b57cec5SDimitry Andric 
16120b57cec5SDimitry Andric   // Turn FP truncstore into trunc + store.
16135ffd83dbSDimitry Andric   setTruncStoreAction(MVT::f32, MVT::f16, Expand);
16145ffd83dbSDimitry Andric   setTruncStoreAction(MVT::f64, MVT::f16, Expand);
16150b57cec5SDimitry Andric   setTruncStoreAction(MVT::f64, MVT::f32, Expand);
1616fe6060f1SDimitry Andric   setTruncStoreAction(MVT::f128, MVT::f16, Expand);
16170b57cec5SDimitry Andric   setTruncStoreAction(MVT::f128, MVT::f32, Expand);
16180b57cec5SDimitry Andric   setTruncStoreAction(MVT::f128, MVT::f64, Expand);
16190b57cec5SDimitry Andric 
16200b57cec5SDimitry Andric   // Custom legalize GlobalAddress nodes into LO/HI parts.
16210b57cec5SDimitry Andric   setOperationAction(ISD::GlobalAddress, PtrVT, Custom);
16220b57cec5SDimitry Andric   setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom);
16230b57cec5SDimitry Andric   setOperationAction(ISD::ConstantPool, PtrVT, Custom);
16240b57cec5SDimitry Andric   setOperationAction(ISD::BlockAddress, PtrVT, Custom);
16250b57cec5SDimitry Andric 
16260b57cec5SDimitry Andric   // Sparc doesn't have sext_inreg, replace them with shl/sra
16270b57cec5SDimitry Andric   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
16280b57cec5SDimitry Andric   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand);
16290b57cec5SDimitry Andric   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
16300b57cec5SDimitry Andric 
16310b57cec5SDimitry Andric   // Sparc has no REM or DIVREM operations.
16320b57cec5SDimitry Andric   setOperationAction(ISD::UREM, MVT::i32, Expand);
16330b57cec5SDimitry Andric   setOperationAction(ISD::SREM, MVT::i32, Expand);
16340b57cec5SDimitry Andric   setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
16350b57cec5SDimitry Andric   setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
16360b57cec5SDimitry Andric 
16370b57cec5SDimitry Andric   // ... nor does SparcV9.
16380b57cec5SDimitry Andric   if (Subtarget->is64Bit()) {
16390b57cec5SDimitry Andric     setOperationAction(ISD::UREM, MVT::i64, Expand);
16400b57cec5SDimitry Andric     setOperationAction(ISD::SREM, MVT::i64, Expand);
16410b57cec5SDimitry Andric     setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
16420b57cec5SDimitry Andric     setOperationAction(ISD::UDIVREM, MVT::i64, Expand);
16430b57cec5SDimitry Andric   }
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric   // Custom expand fp<->sint
16460b57cec5SDimitry Andric   setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
16470b57cec5SDimitry Andric   setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
16480b57cec5SDimitry Andric   setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
16490b57cec5SDimitry Andric   setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
16500b57cec5SDimitry Andric 
16510b57cec5SDimitry Andric   // Custom Expand fp<->uint
16520b57cec5SDimitry Andric   setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
16530b57cec5SDimitry Andric   setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
16540b57cec5SDimitry Andric   setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
16550b57cec5SDimitry Andric   setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
16560b57cec5SDimitry Andric 
16575ffd83dbSDimitry Andric   // Lower f16 conversion operations into library calls
16585ffd83dbSDimitry Andric   setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand);
16595ffd83dbSDimitry Andric   setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand);
16605ffd83dbSDimitry Andric   setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand);
16615ffd83dbSDimitry Andric   setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand);
1662fe6060f1SDimitry Andric   setOperationAction(ISD::FP16_TO_FP, MVT::f128, Expand);
1663fe6060f1SDimitry Andric   setOperationAction(ISD::FP_TO_FP16, MVT::f128, Expand);
16645ffd83dbSDimitry Andric 
16650b57cec5SDimitry Andric   setOperationAction(ISD::BITCAST, MVT::f32, Expand);
16660b57cec5SDimitry Andric   setOperationAction(ISD::BITCAST, MVT::i32, Expand);
16670b57cec5SDimitry Andric 
16680b57cec5SDimitry Andric   // Sparc has no select or setcc: expand to SELECT_CC.
16690b57cec5SDimitry Andric   setOperationAction(ISD::SELECT, MVT::i32, Expand);
16700b57cec5SDimitry Andric   setOperationAction(ISD::SELECT, MVT::f32, Expand);
16710b57cec5SDimitry Andric   setOperationAction(ISD::SELECT, MVT::f64, Expand);
16720b57cec5SDimitry Andric   setOperationAction(ISD::SELECT, MVT::f128, Expand);
16730b57cec5SDimitry Andric 
16740b57cec5SDimitry Andric   setOperationAction(ISD::SETCC, MVT::i32, Expand);
16750b57cec5SDimitry Andric   setOperationAction(ISD::SETCC, MVT::f32, Expand);
16760b57cec5SDimitry Andric   setOperationAction(ISD::SETCC, MVT::f64, Expand);
16770b57cec5SDimitry Andric   setOperationAction(ISD::SETCC, MVT::f128, Expand);
16780b57cec5SDimitry Andric 
16790b57cec5SDimitry Andric   // Sparc doesn't have BRCOND either, it has BR_CC.
16800b57cec5SDimitry Andric   setOperationAction(ISD::BRCOND, MVT::Other, Expand);
16810b57cec5SDimitry Andric   setOperationAction(ISD::BRIND, MVT::Other, Expand);
16820b57cec5SDimitry Andric   setOperationAction(ISD::BR_JT, MVT::Other, Expand);
16830b57cec5SDimitry Andric   setOperationAction(ISD::BR_CC, MVT::i32, Custom);
16840b57cec5SDimitry Andric   setOperationAction(ISD::BR_CC, MVT::f32, Custom);
16850b57cec5SDimitry Andric   setOperationAction(ISD::BR_CC, MVT::f64, Custom);
16860b57cec5SDimitry Andric   setOperationAction(ISD::BR_CC, MVT::f128, Custom);
16870b57cec5SDimitry Andric 
16880b57cec5SDimitry Andric   setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
16890b57cec5SDimitry Andric   setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
16900b57cec5SDimitry Andric   setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
16910b57cec5SDimitry Andric   setOperationAction(ISD::SELECT_CC, MVT::f128, Custom);
16920b57cec5SDimitry Andric 
16930b57cec5SDimitry Andric   setOperationAction(ISD::ADDC, MVT::i32, Custom);
16940b57cec5SDimitry Andric   setOperationAction(ISD::ADDE, MVT::i32, Custom);
16950b57cec5SDimitry Andric   setOperationAction(ISD::SUBC, MVT::i32, Custom);
16960b57cec5SDimitry Andric   setOperationAction(ISD::SUBE, MVT::i32, Custom);
16970b57cec5SDimitry Andric 
16980b57cec5SDimitry Andric   if (Subtarget->is64Bit()) {
16990b57cec5SDimitry Andric     setOperationAction(ISD::ADDC, MVT::i64, Custom);
17000b57cec5SDimitry Andric     setOperationAction(ISD::ADDE, MVT::i64, Custom);
17010b57cec5SDimitry Andric     setOperationAction(ISD::SUBC, MVT::i64, Custom);
17020b57cec5SDimitry Andric     setOperationAction(ISD::SUBE, MVT::i64, Custom);
17030b57cec5SDimitry Andric     setOperationAction(ISD::BITCAST, MVT::f64, Expand);
17040b57cec5SDimitry Andric     setOperationAction(ISD::BITCAST, MVT::i64, Expand);
17050b57cec5SDimitry Andric     setOperationAction(ISD::SELECT, MVT::i64, Expand);
17060b57cec5SDimitry Andric     setOperationAction(ISD::SETCC, MVT::i64, Expand);
17070b57cec5SDimitry Andric     setOperationAction(ISD::BR_CC, MVT::i64, Custom);
17080b57cec5SDimitry Andric     setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric     setOperationAction(ISD::CTPOP, MVT::i64,
17110b57cec5SDimitry Andric                        Subtarget->usePopc() ? Legal : Expand);
17120b57cec5SDimitry Andric     setOperationAction(ISD::CTTZ , MVT::i64, Expand);
17130b57cec5SDimitry Andric     setOperationAction(ISD::CTLZ , MVT::i64, Expand);
17140b57cec5SDimitry Andric     setOperationAction(ISD::BSWAP, MVT::i64, Expand);
17150b57cec5SDimitry Andric     setOperationAction(ISD::ROTL , MVT::i64, Expand);
17160b57cec5SDimitry Andric     setOperationAction(ISD::ROTR , MVT::i64, Expand);
17170b57cec5SDimitry Andric     setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom);
17180b57cec5SDimitry Andric   }
17190b57cec5SDimitry Andric 
17200b57cec5SDimitry Andric   // ATOMICs.
17210b57cec5SDimitry Andric   // Atomics are supported on SparcV9. 32-bit atomics are also
17220b57cec5SDimitry Andric   // supported by some Leon SparcV8 variants. Otherwise, atomics
17230b57cec5SDimitry Andric   // are unsupported.
17240b57cec5SDimitry Andric   if (Subtarget->isV9())
17250b57cec5SDimitry Andric     setMaxAtomicSizeInBitsSupported(64);
17260b57cec5SDimitry Andric   else if (Subtarget->hasLeonCasa())
17270b57cec5SDimitry Andric     setMaxAtomicSizeInBitsSupported(32);
17280b57cec5SDimitry Andric   else
17290b57cec5SDimitry Andric     setMaxAtomicSizeInBitsSupported(0);
17300b57cec5SDimitry Andric 
17310b57cec5SDimitry Andric   setMinCmpXchgSizeInBits(32);
17320b57cec5SDimitry Andric 
17330b57cec5SDimitry Andric   setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal);
17340b57cec5SDimitry Andric 
17350b57cec5SDimitry Andric   setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal);
17360b57cec5SDimitry Andric 
17370b57cec5SDimitry Andric   // Custom Lower Atomic LOAD/STORE
17380b57cec5SDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom);
17390b57cec5SDimitry Andric   setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom);
17400b57cec5SDimitry Andric 
17410b57cec5SDimitry Andric   if (Subtarget->is64Bit()) {
17420b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal);
17430b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Legal);
17440b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom);
17450b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom);
17460b57cec5SDimitry Andric   }
17470b57cec5SDimitry Andric 
17480b57cec5SDimitry Andric   if (!Subtarget->is64Bit()) {
17490b57cec5SDimitry Andric     // These libcalls are not available in 32-bit.
1750349cc55cSDimitry Andric     setLibcallName(RTLIB::MULO_I64, nullptr);
17510b57cec5SDimitry Andric     setLibcallName(RTLIB::SHL_I128, nullptr);
17520b57cec5SDimitry Andric     setLibcallName(RTLIB::SRL_I128, nullptr);
17530b57cec5SDimitry Andric     setLibcallName(RTLIB::SRA_I128, nullptr);
17540b57cec5SDimitry Andric   }
17550b57cec5SDimitry Andric 
1756349cc55cSDimitry Andric   setLibcallName(RTLIB::MULO_I128, nullptr);
1757349cc55cSDimitry Andric 
17580b57cec5SDimitry Andric   if (!Subtarget->isV9()) {
17590b57cec5SDimitry Andric     // SparcV8 does not have FNEGD and FABSD.
17600b57cec5SDimitry Andric     setOperationAction(ISD::FNEG, MVT::f64, Custom);
17610b57cec5SDimitry Andric     setOperationAction(ISD::FABS, MVT::f64, Custom);
17620b57cec5SDimitry Andric   }
17630b57cec5SDimitry Andric 
17640b57cec5SDimitry Andric   setOperationAction(ISD::FSIN , MVT::f128, Expand);
17650b57cec5SDimitry Andric   setOperationAction(ISD::FCOS , MVT::f128, Expand);
17660b57cec5SDimitry Andric   setOperationAction(ISD::FSINCOS, MVT::f128, Expand);
17670b57cec5SDimitry Andric   setOperationAction(ISD::FREM , MVT::f128, Expand);
17680b57cec5SDimitry Andric   setOperationAction(ISD::FMA  , MVT::f128, Expand);
17690b57cec5SDimitry Andric   setOperationAction(ISD::FSIN , MVT::f64, Expand);
17700b57cec5SDimitry Andric   setOperationAction(ISD::FCOS , MVT::f64, Expand);
17710b57cec5SDimitry Andric   setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
17720b57cec5SDimitry Andric   setOperationAction(ISD::FREM , MVT::f64, Expand);
17730b57cec5SDimitry Andric   setOperationAction(ISD::FMA  , MVT::f64, Expand);
17740b57cec5SDimitry Andric   setOperationAction(ISD::FSIN , MVT::f32, Expand);
17750b57cec5SDimitry Andric   setOperationAction(ISD::FCOS , MVT::f32, Expand);
17760b57cec5SDimitry Andric   setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
17770b57cec5SDimitry Andric   setOperationAction(ISD::FREM , MVT::f32, Expand);
17780b57cec5SDimitry Andric   setOperationAction(ISD::FMA  , MVT::f32, Expand);
17790b57cec5SDimitry Andric   setOperationAction(ISD::CTTZ , MVT::i32, Expand);
17800b57cec5SDimitry Andric   setOperationAction(ISD::CTLZ , MVT::i32, Expand);
17810b57cec5SDimitry Andric   setOperationAction(ISD::ROTL , MVT::i32, Expand);
17820b57cec5SDimitry Andric   setOperationAction(ISD::ROTR , MVT::i32, Expand);
17830b57cec5SDimitry Andric   setOperationAction(ISD::BSWAP, MVT::i32, Expand);
17840b57cec5SDimitry Andric   setOperationAction(ISD::FCOPYSIGN, MVT::f128, Expand);
17850b57cec5SDimitry Andric   setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
17860b57cec5SDimitry Andric   setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
17870b57cec5SDimitry Andric   setOperationAction(ISD::FPOW , MVT::f128, Expand);
17880b57cec5SDimitry Andric   setOperationAction(ISD::FPOW , MVT::f64, Expand);
17890b57cec5SDimitry Andric   setOperationAction(ISD::FPOW , MVT::f32, Expand);
17900b57cec5SDimitry Andric 
17910b57cec5SDimitry Andric   setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
17920b57cec5SDimitry Andric   setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
17930b57cec5SDimitry Andric   setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
17940b57cec5SDimitry Andric 
17950b57cec5SDimitry Andric   // Expands to [SU]MUL_LOHI.
17960b57cec5SDimitry Andric   setOperationAction(ISD::MULHU,     MVT::i32, Expand);
17970b57cec5SDimitry Andric   setOperationAction(ISD::MULHS,     MVT::i32, Expand);
17980b57cec5SDimitry Andric   setOperationAction(ISD::MUL,       MVT::i32, Expand);
17990b57cec5SDimitry Andric 
18000b57cec5SDimitry Andric   if (Subtarget->useSoftMulDiv()) {
18010b57cec5SDimitry Andric     // .umul works for both signed and unsigned
18020b57cec5SDimitry Andric     setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
18030b57cec5SDimitry Andric     setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
18040b57cec5SDimitry Andric     setLibcallName(RTLIB::MUL_I32, ".umul");
18050b57cec5SDimitry Andric 
18060b57cec5SDimitry Andric     setOperationAction(ISD::SDIV, MVT::i32, Expand);
18070b57cec5SDimitry Andric     setLibcallName(RTLIB::SDIV_I32, ".div");
18080b57cec5SDimitry Andric 
18090b57cec5SDimitry Andric     setOperationAction(ISD::UDIV, MVT::i32, Expand);
18100b57cec5SDimitry Andric     setLibcallName(RTLIB::UDIV_I32, ".udiv");
18110b57cec5SDimitry Andric 
18120b57cec5SDimitry Andric     setLibcallName(RTLIB::SREM_I32, ".rem");
18130b57cec5SDimitry Andric     setLibcallName(RTLIB::UREM_I32, ".urem");
18140b57cec5SDimitry Andric   }
18150b57cec5SDimitry Andric 
18160b57cec5SDimitry Andric   if (Subtarget->is64Bit()) {
18170b57cec5SDimitry Andric     setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
18180b57cec5SDimitry Andric     setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
18190b57cec5SDimitry Andric     setOperationAction(ISD::MULHU,     MVT::i64, Expand);
18200b57cec5SDimitry Andric     setOperationAction(ISD::MULHS,     MVT::i64, Expand);
18210b57cec5SDimitry Andric 
18220b57cec5SDimitry Andric     setOperationAction(ISD::UMULO,     MVT::i64, Custom);
18230b57cec5SDimitry Andric     setOperationAction(ISD::SMULO,     MVT::i64, Custom);
18240b57cec5SDimitry Andric 
18250b57cec5SDimitry Andric     setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand);
18260b57cec5SDimitry Andric     setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand);
18270b57cec5SDimitry Andric     setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand);
18280b57cec5SDimitry Andric   }
18290b57cec5SDimitry Andric 
18300b57cec5SDimitry Andric   // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
18310b57cec5SDimitry Andric   setOperationAction(ISD::VASTART           , MVT::Other, Custom);
18320b57cec5SDimitry Andric   // VAARG needs to be lowered to not do unaligned accesses for doubles.
18330b57cec5SDimitry Andric   setOperationAction(ISD::VAARG             , MVT::Other, Custom);
18340b57cec5SDimitry Andric 
18350b57cec5SDimitry Andric   setOperationAction(ISD::TRAP              , MVT::Other, Legal);
18360b57cec5SDimitry Andric   setOperationAction(ISD::DEBUGTRAP         , MVT::Other, Legal);
18370b57cec5SDimitry Andric 
18380b57cec5SDimitry Andric   // Use the default implementation.
18390b57cec5SDimitry Andric   setOperationAction(ISD::VACOPY            , MVT::Other, Expand);
18400b57cec5SDimitry Andric   setOperationAction(ISD::VAEND             , MVT::Other, Expand);
18410b57cec5SDimitry Andric   setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand);
18420b57cec5SDimitry Andric   setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);
18430b57cec5SDimitry Andric   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom);
18440b57cec5SDimitry Andric 
18450b57cec5SDimitry Andric   setStackPointerRegisterToSaveRestore(SP::O6);
18460b57cec5SDimitry Andric 
18470b57cec5SDimitry Andric   setOperationAction(ISD::CTPOP, MVT::i32,
18480b57cec5SDimitry Andric                      Subtarget->usePopc() ? Legal : Expand);
18490b57cec5SDimitry Andric 
18500b57cec5SDimitry Andric   if (Subtarget->isV9() && Subtarget->hasHardQuad()) {
18510b57cec5SDimitry Andric     setOperationAction(ISD::LOAD, MVT::f128, Legal);
18520b57cec5SDimitry Andric     setOperationAction(ISD::STORE, MVT::f128, Legal);
18530b57cec5SDimitry Andric   } else {
18540b57cec5SDimitry Andric     setOperationAction(ISD::LOAD, MVT::f128, Custom);
18550b57cec5SDimitry Andric     setOperationAction(ISD::STORE, MVT::f128, Custom);
18560b57cec5SDimitry Andric   }
18570b57cec5SDimitry Andric 
18580b57cec5SDimitry Andric   if (Subtarget->hasHardQuad()) {
18590b57cec5SDimitry Andric     setOperationAction(ISD::FADD,  MVT::f128, Legal);
18600b57cec5SDimitry Andric     setOperationAction(ISD::FSUB,  MVT::f128, Legal);
18610b57cec5SDimitry Andric     setOperationAction(ISD::FMUL,  MVT::f128, Legal);
18620b57cec5SDimitry Andric     setOperationAction(ISD::FDIV,  MVT::f128, Legal);
18630b57cec5SDimitry Andric     setOperationAction(ISD::FSQRT, MVT::f128, Legal);
18640b57cec5SDimitry Andric     setOperationAction(ISD::FP_EXTEND, MVT::f128, Legal);
18650b57cec5SDimitry Andric     setOperationAction(ISD::FP_ROUND,  MVT::f64, Legal);
18660b57cec5SDimitry Andric     if (Subtarget->isV9()) {
18670b57cec5SDimitry Andric       setOperationAction(ISD::FNEG, MVT::f128, Legal);
18680b57cec5SDimitry Andric       setOperationAction(ISD::FABS, MVT::f128, Legal);
18690b57cec5SDimitry Andric     } else {
18700b57cec5SDimitry Andric       setOperationAction(ISD::FNEG, MVT::f128, Custom);
18710b57cec5SDimitry Andric       setOperationAction(ISD::FABS, MVT::f128, Custom);
18720b57cec5SDimitry Andric     }
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric     if (!Subtarget->is64Bit()) {
18750b57cec5SDimitry Andric       setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll");
18760b57cec5SDimitry Andric       setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull");
18770b57cec5SDimitry Andric       setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq");
18780b57cec5SDimitry Andric       setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq");
18790b57cec5SDimitry Andric     }
18800b57cec5SDimitry Andric 
18810b57cec5SDimitry Andric   } else {
18820b57cec5SDimitry Andric     // Custom legalize f128 operations.
18830b57cec5SDimitry Andric 
18840b57cec5SDimitry Andric     setOperationAction(ISD::FADD,  MVT::f128, Custom);
18850b57cec5SDimitry Andric     setOperationAction(ISD::FSUB,  MVT::f128, Custom);
18860b57cec5SDimitry Andric     setOperationAction(ISD::FMUL,  MVT::f128, Custom);
18870b57cec5SDimitry Andric     setOperationAction(ISD::FDIV,  MVT::f128, Custom);
18880b57cec5SDimitry Andric     setOperationAction(ISD::FSQRT, MVT::f128, Custom);
18890b57cec5SDimitry Andric     setOperationAction(ISD::FNEG,  MVT::f128, Custom);
18900b57cec5SDimitry Andric     setOperationAction(ISD::FABS,  MVT::f128, Custom);
18910b57cec5SDimitry Andric 
18920b57cec5SDimitry Andric     setOperationAction(ISD::FP_EXTEND, MVT::f128, Custom);
18930b57cec5SDimitry Andric     setOperationAction(ISD::FP_ROUND,  MVT::f64, Custom);
18940b57cec5SDimitry Andric     setOperationAction(ISD::FP_ROUND,  MVT::f32, Custom);
18950b57cec5SDimitry Andric 
18960b57cec5SDimitry Andric     // Setup Runtime library names.
18970b57cec5SDimitry Andric     if (Subtarget->is64Bit() && !Subtarget->useSoftFloat()) {
18980b57cec5SDimitry Andric       setLibcallName(RTLIB::ADD_F128,  "_Qp_add");
18990b57cec5SDimitry Andric       setLibcallName(RTLIB::SUB_F128,  "_Qp_sub");
19000b57cec5SDimitry Andric       setLibcallName(RTLIB::MUL_F128,  "_Qp_mul");
19010b57cec5SDimitry Andric       setLibcallName(RTLIB::DIV_F128,  "_Qp_div");
19020b57cec5SDimitry Andric       setLibcallName(RTLIB::SQRT_F128, "_Qp_sqrt");
19030b57cec5SDimitry Andric       setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Qp_qtoi");
19040b57cec5SDimitry Andric       setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Qp_qtoui");
19050b57cec5SDimitry Andric       setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Qp_itoq");
19060b57cec5SDimitry Andric       setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Qp_uitoq");
19070b57cec5SDimitry Andric       setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Qp_qtox");
19080b57cec5SDimitry Andric       setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Qp_qtoux");
19090b57cec5SDimitry Andric       setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Qp_xtoq");
19100b57cec5SDimitry Andric       setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Qp_uxtoq");
19110b57cec5SDimitry Andric       setLibcallName(RTLIB::FPEXT_F32_F128, "_Qp_stoq");
19120b57cec5SDimitry Andric       setLibcallName(RTLIB::FPEXT_F64_F128, "_Qp_dtoq");
19130b57cec5SDimitry Andric       setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos");
19140b57cec5SDimitry Andric       setLibcallName(RTLIB::FPROUND_F128_F64, "_Qp_qtod");
19150b57cec5SDimitry Andric     } else if (!Subtarget->useSoftFloat()) {
19160b57cec5SDimitry Andric       setLibcallName(RTLIB::ADD_F128,  "_Q_add");
19170b57cec5SDimitry Andric       setLibcallName(RTLIB::SUB_F128,  "_Q_sub");
19180b57cec5SDimitry Andric       setLibcallName(RTLIB::MUL_F128,  "_Q_mul");
19190b57cec5SDimitry Andric       setLibcallName(RTLIB::DIV_F128,  "_Q_div");
19200b57cec5SDimitry Andric       setLibcallName(RTLIB::SQRT_F128, "_Q_sqrt");
19210b57cec5SDimitry Andric       setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Q_qtoi");
19220b57cec5SDimitry Andric       setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Q_qtou");
19230b57cec5SDimitry Andric       setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Q_itoq");
19240b57cec5SDimitry Andric       setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Q_utoq");
19250b57cec5SDimitry Andric       setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll");
19260b57cec5SDimitry Andric       setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull");
19270b57cec5SDimitry Andric       setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq");
19280b57cec5SDimitry Andric       setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq");
19290b57cec5SDimitry Andric       setLibcallName(RTLIB::FPEXT_F32_F128, "_Q_stoq");
19300b57cec5SDimitry Andric       setLibcallName(RTLIB::FPEXT_F64_F128, "_Q_dtoq");
19310b57cec5SDimitry Andric       setLibcallName(RTLIB::FPROUND_F128_F32, "_Q_qtos");
19320b57cec5SDimitry Andric       setLibcallName(RTLIB::FPROUND_F128_F64, "_Q_qtod");
19330b57cec5SDimitry Andric     }
19340b57cec5SDimitry Andric   }
19350b57cec5SDimitry Andric 
19360b57cec5SDimitry Andric   if (Subtarget->fixAllFDIVSQRT()) {
19370b57cec5SDimitry Andric     // Promote FDIVS and FSQRTS to FDIVD and FSQRTD instructions instead as
19380b57cec5SDimitry Andric     // the former instructions generate errata on LEON processors.
19390b57cec5SDimitry Andric     setOperationAction(ISD::FDIV, MVT::f32, Promote);
19400b57cec5SDimitry Andric     setOperationAction(ISD::FSQRT, MVT::f32, Promote);
19410b57cec5SDimitry Andric   }
19420b57cec5SDimitry Andric 
19430b57cec5SDimitry Andric   if (Subtarget->hasNoFMULS()) {
19440b57cec5SDimitry Andric     setOperationAction(ISD::FMUL, MVT::f32, Promote);
19450b57cec5SDimitry Andric   }
19460b57cec5SDimitry Andric 
19470b57cec5SDimitry Andric   // Custom combine bitcast between f64 and v2i32
19480b57cec5SDimitry Andric   if (!Subtarget->is64Bit())
19490b57cec5SDimitry Andric     setTargetDAGCombine(ISD::BITCAST);
19500b57cec5SDimitry Andric 
19510b57cec5SDimitry Andric   if (Subtarget->hasLeonCycleCounter())
19520b57cec5SDimitry Andric     setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
19530b57cec5SDimitry Andric 
19540b57cec5SDimitry Andric   setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
19550b57cec5SDimitry Andric 
19568bcb0991SDimitry Andric   setMinFunctionAlignment(Align(4));
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric   computeRegisterProperties(Subtarget->getRegisterInfo());
19590b57cec5SDimitry Andric }
19600b57cec5SDimitry Andric 
19610b57cec5SDimitry Andric bool SparcTargetLowering::useSoftFloat() const {
19620b57cec5SDimitry Andric   return Subtarget->useSoftFloat();
19630b57cec5SDimitry Andric }
19640b57cec5SDimitry Andric 
19650b57cec5SDimitry Andric const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
19660b57cec5SDimitry Andric   switch ((SPISD::NodeType)Opcode) {
19670b57cec5SDimitry Andric   case SPISD::FIRST_NUMBER:    break;
19680b57cec5SDimitry Andric   case SPISD::CMPICC:          return "SPISD::CMPICC";
19690b57cec5SDimitry Andric   case SPISD::CMPFCC:          return "SPISD::CMPFCC";
1970*bdd1243dSDimitry Andric   case SPISD::CMPFCC_V9:
1971*bdd1243dSDimitry Andric     return "SPISD::CMPFCC_V9";
19720b57cec5SDimitry Andric   case SPISD::BRICC:           return "SPISD::BRICC";
1973*bdd1243dSDimitry Andric   case SPISD::BPICC:
1974*bdd1243dSDimitry Andric     return "SPISD::BPICC";
1975*bdd1243dSDimitry Andric   case SPISD::BPXCC:
1976*bdd1243dSDimitry Andric     return "SPISD::BPXCC";
19770b57cec5SDimitry Andric   case SPISD::BRFCC:           return "SPISD::BRFCC";
1978*bdd1243dSDimitry Andric   case SPISD::BRFCC_V9:
1979*bdd1243dSDimitry Andric     return "SPISD::BRFCC_V9";
19800b57cec5SDimitry Andric   case SPISD::SELECT_ICC:      return "SPISD::SELECT_ICC";
19810b57cec5SDimitry Andric   case SPISD::SELECT_XCC:      return "SPISD::SELECT_XCC";
19820b57cec5SDimitry Andric   case SPISD::SELECT_FCC:      return "SPISD::SELECT_FCC";
1983*bdd1243dSDimitry Andric   case SPISD::SELECT_REG:
1984*bdd1243dSDimitry Andric     return "SPISD::SELECT_REG";
19850b57cec5SDimitry Andric   case SPISD::Hi:              return "SPISD::Hi";
19860b57cec5SDimitry Andric   case SPISD::Lo:              return "SPISD::Lo";
19870b57cec5SDimitry Andric   case SPISD::FTOI:            return "SPISD::FTOI";
19880b57cec5SDimitry Andric   case SPISD::ITOF:            return "SPISD::ITOF";
19890b57cec5SDimitry Andric   case SPISD::FTOX:            return "SPISD::FTOX";
19900b57cec5SDimitry Andric   case SPISD::XTOF:            return "SPISD::XTOF";
19910b57cec5SDimitry Andric   case SPISD::CALL:            return "SPISD::CALL";
19920b57cec5SDimitry Andric   case SPISD::RET_FLAG:        return "SPISD::RET_FLAG";
19930b57cec5SDimitry Andric   case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG";
19940b57cec5SDimitry Andric   case SPISD::FLUSHW:          return "SPISD::FLUSHW";
19950b57cec5SDimitry Andric   case SPISD::TLS_ADD:         return "SPISD::TLS_ADD";
19960b57cec5SDimitry Andric   case SPISD::TLS_LD:          return "SPISD::TLS_LD";
19970b57cec5SDimitry Andric   case SPISD::TLS_CALL:        return "SPISD::TLS_CALL";
199881ad6265SDimitry Andric   case SPISD::TAIL_CALL:       return "SPISD::TAIL_CALL";
199981ad6265SDimitry Andric   case SPISD::LOAD_GDOP:       return "SPISD::LOAD_GDOP";
20000b57cec5SDimitry Andric   }
20010b57cec5SDimitry Andric   return nullptr;
20020b57cec5SDimitry Andric }
20030b57cec5SDimitry Andric 
20040b57cec5SDimitry Andric EVT SparcTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &,
20050b57cec5SDimitry Andric                                             EVT VT) const {
20060b57cec5SDimitry Andric   if (!VT.isVector())
20070b57cec5SDimitry Andric     return MVT::i32;
20080b57cec5SDimitry Andric   return VT.changeVectorElementTypeToInteger();
20090b57cec5SDimitry Andric }
20100b57cec5SDimitry Andric 
20110b57cec5SDimitry Andric /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to
20120b57cec5SDimitry Andric /// be zero. Op is expected to be a target specific node. Used by DAG
20130b57cec5SDimitry Andric /// combiner.
20140b57cec5SDimitry Andric void SparcTargetLowering::computeKnownBitsForTargetNode
20150b57cec5SDimitry Andric                                 (const SDValue Op,
20160b57cec5SDimitry Andric                                  KnownBits &Known,
20170b57cec5SDimitry Andric                                  const APInt &DemandedElts,
20180b57cec5SDimitry Andric                                  const SelectionDAG &DAG,
20190b57cec5SDimitry Andric                                  unsigned Depth) const {
20200b57cec5SDimitry Andric   KnownBits Known2;
20210b57cec5SDimitry Andric   Known.resetAll();
20220b57cec5SDimitry Andric 
20230b57cec5SDimitry Andric   switch (Op.getOpcode()) {
20240b57cec5SDimitry Andric   default: break;
20250b57cec5SDimitry Andric   case SPISD::SELECT_ICC:
20260b57cec5SDimitry Andric   case SPISD::SELECT_XCC:
20270b57cec5SDimitry Andric   case SPISD::SELECT_FCC:
20280b57cec5SDimitry Andric     Known = DAG.computeKnownBits(Op.getOperand(1), Depth + 1);
20290b57cec5SDimitry Andric     Known2 = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
20300b57cec5SDimitry Andric 
20310b57cec5SDimitry Andric     // Only known if known in both the LHS and RHS.
2032e8d8bef9SDimitry Andric     Known = KnownBits::commonBits(Known, Known2);
20330b57cec5SDimitry Andric     break;
20340b57cec5SDimitry Andric   }
20350b57cec5SDimitry Andric }
20360b57cec5SDimitry Andric 
20370b57cec5SDimitry Andric // Look at LHS/RHS/CC and see if they are a lowered setcc instruction.  If so
20380b57cec5SDimitry Andric // set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition.
20390b57cec5SDimitry Andric static void LookThroughSetCC(SDValue &LHS, SDValue &RHS,
20400b57cec5SDimitry Andric                              ISD::CondCode CC, unsigned &SPCC) {
2041*bdd1243dSDimitry Andric   if (isNullConstant(RHS) && CC == ISD::SETNE &&
20420b57cec5SDimitry Andric       (((LHS.getOpcode() == SPISD::SELECT_ICC ||
20430b57cec5SDimitry Andric          LHS.getOpcode() == SPISD::SELECT_XCC) &&
20440b57cec5SDimitry Andric         LHS.getOperand(3).getOpcode() == SPISD::CMPICC) ||
20450b57cec5SDimitry Andric        (LHS.getOpcode() == SPISD::SELECT_FCC &&
2046*bdd1243dSDimitry Andric         (LHS.getOperand(3).getOpcode() == SPISD::CMPFCC ||
2047*bdd1243dSDimitry Andric          LHS.getOperand(3).getOpcode() == SPISD::CMPFCC_V9))) &&
2048*bdd1243dSDimitry Andric       isOneConstant(LHS.getOperand(0)) && isNullConstant(LHS.getOperand(1))) {
20490b57cec5SDimitry Andric     SDValue CMPCC = LHS.getOperand(3);
20500b57cec5SDimitry Andric     SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue();
20510b57cec5SDimitry Andric     LHS = CMPCC.getOperand(0);
20520b57cec5SDimitry Andric     RHS = CMPCC.getOperand(1);
20530b57cec5SDimitry Andric   }
20540b57cec5SDimitry Andric }
20550b57cec5SDimitry Andric 
20560b57cec5SDimitry Andric // Convert to a target node and set target flags.
20570b57cec5SDimitry Andric SDValue SparcTargetLowering::withTargetFlags(SDValue Op, unsigned TF,
20580b57cec5SDimitry Andric                                              SelectionDAG &DAG) const {
20590b57cec5SDimitry Andric   if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op))
20600b57cec5SDimitry Andric     return DAG.getTargetGlobalAddress(GA->getGlobal(),
20610b57cec5SDimitry Andric                                       SDLoc(GA),
20620b57cec5SDimitry Andric                                       GA->getValueType(0),
20630b57cec5SDimitry Andric                                       GA->getOffset(), TF);
20640b57cec5SDimitry Andric 
20650b57cec5SDimitry Andric   if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op))
20665ffd83dbSDimitry Andric     return DAG.getTargetConstantPool(CP->getConstVal(), CP->getValueType(0),
20675ffd83dbSDimitry Andric                                      CP->getAlign(), CP->getOffset(), TF);
20680b57cec5SDimitry Andric 
20690b57cec5SDimitry Andric   if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op))
20700b57cec5SDimitry Andric     return DAG.getTargetBlockAddress(BA->getBlockAddress(),
20710b57cec5SDimitry Andric                                      Op.getValueType(),
20720b57cec5SDimitry Andric                                      0,
20730b57cec5SDimitry Andric                                      TF);
20740b57cec5SDimitry Andric 
20750b57cec5SDimitry Andric   if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op))
20760b57cec5SDimitry Andric     return DAG.getTargetExternalSymbol(ES->getSymbol(),
20770b57cec5SDimitry Andric                                        ES->getValueType(0), TF);
20780b57cec5SDimitry Andric 
20790b57cec5SDimitry Andric   llvm_unreachable("Unhandled address SDNode");
20800b57cec5SDimitry Andric }
20810b57cec5SDimitry Andric 
20820b57cec5SDimitry Andric // Split Op into high and low parts according to HiTF and LoTF.
20830b57cec5SDimitry Andric // Return an ADD node combining the parts.
20840b57cec5SDimitry Andric SDValue SparcTargetLowering::makeHiLoPair(SDValue Op,
20850b57cec5SDimitry Andric                                           unsigned HiTF, unsigned LoTF,
20860b57cec5SDimitry Andric                                           SelectionDAG &DAG) const {
20870b57cec5SDimitry Andric   SDLoc DL(Op);
20880b57cec5SDimitry Andric   EVT VT = Op.getValueType();
20890b57cec5SDimitry Andric   SDValue Hi = DAG.getNode(SPISD::Hi, DL, VT, withTargetFlags(Op, HiTF, DAG));
20900b57cec5SDimitry Andric   SDValue Lo = DAG.getNode(SPISD::Lo, DL, VT, withTargetFlags(Op, LoTF, DAG));
20910b57cec5SDimitry Andric   return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo);
20920b57cec5SDimitry Andric }
20930b57cec5SDimitry Andric 
20940b57cec5SDimitry Andric // Build SDNodes for producing an address from a GlobalAddress, ConstantPool,
20950b57cec5SDimitry Andric // or ExternalSymbol SDNode.
20960b57cec5SDimitry Andric SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const {
20970b57cec5SDimitry Andric   SDLoc DL(Op);
20980b57cec5SDimitry Andric   EVT VT = getPointerTy(DAG.getDataLayout());
20990b57cec5SDimitry Andric 
21000b57cec5SDimitry Andric   // Handle PIC mode first. SPARC needs a got load for every variable!
21010b57cec5SDimitry Andric   if (isPositionIndependent()) {
21020b57cec5SDimitry Andric     const Module *M = DAG.getMachineFunction().getFunction().getParent();
21030b57cec5SDimitry Andric     PICLevel::Level picLevel = M->getPICLevel();
21040b57cec5SDimitry Andric     SDValue Idx;
21050b57cec5SDimitry Andric 
21060b57cec5SDimitry Andric     if (picLevel == PICLevel::SmallPIC) {
21070b57cec5SDimitry Andric       // This is the pic13 code model, the GOT is known to be smaller than 8KiB.
21080b57cec5SDimitry Andric       Idx = DAG.getNode(SPISD::Lo, DL, Op.getValueType(),
21090b57cec5SDimitry Andric                         withTargetFlags(Op, SparcMCExpr::VK_Sparc_GOT13, DAG));
21100b57cec5SDimitry Andric     } else {
21110b57cec5SDimitry Andric       // This is the pic32 code model, the GOT is known to be smaller than 4GB.
21120b57cec5SDimitry Andric       Idx = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
21130b57cec5SDimitry Andric                          SparcMCExpr::VK_Sparc_GOT10, DAG);
21140b57cec5SDimitry Andric     }
21150b57cec5SDimitry Andric 
21160b57cec5SDimitry Andric     SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT);
21170b57cec5SDimitry Andric     SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Idx);
21180b57cec5SDimitry Andric     // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
21190b57cec5SDimitry Andric     // function has calls.
21200b57cec5SDimitry Andric     MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
21210b57cec5SDimitry Andric     MFI.setHasCalls(true);
21220b57cec5SDimitry Andric     return DAG.getLoad(VT, DL, DAG.getEntryNode(), AbsAddr,
21230b57cec5SDimitry Andric                        MachinePointerInfo::getGOT(DAG.getMachineFunction()));
21240b57cec5SDimitry Andric   }
21250b57cec5SDimitry Andric 
21260b57cec5SDimitry Andric   // This is one of the absolute code models.
21270b57cec5SDimitry Andric   switch(getTargetMachine().getCodeModel()) {
21280b57cec5SDimitry Andric   default:
21290b57cec5SDimitry Andric     llvm_unreachable("Unsupported absolute code model");
21300b57cec5SDimitry Andric   case CodeModel::Small:
21310b57cec5SDimitry Andric     // abs32.
21320b57cec5SDimitry Andric     return makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
21330b57cec5SDimitry Andric                         SparcMCExpr::VK_Sparc_LO, DAG);
21340b57cec5SDimitry Andric   case CodeModel::Medium: {
21350b57cec5SDimitry Andric     // abs44.
21360b57cec5SDimitry Andric     SDValue H44 = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_H44,
21370b57cec5SDimitry Andric                                SparcMCExpr::VK_Sparc_M44, DAG);
21380b57cec5SDimitry Andric     H44 = DAG.getNode(ISD::SHL, DL, VT, H44, DAG.getConstant(12, DL, MVT::i32));
21390b57cec5SDimitry Andric     SDValue L44 = withTargetFlags(Op, SparcMCExpr::VK_Sparc_L44, DAG);
21400b57cec5SDimitry Andric     L44 = DAG.getNode(SPISD::Lo, DL, VT, L44);
21410b57cec5SDimitry Andric     return DAG.getNode(ISD::ADD, DL, VT, H44, L44);
21420b57cec5SDimitry Andric   }
21430b57cec5SDimitry Andric   case CodeModel::Large: {
21440b57cec5SDimitry Andric     // abs64.
21450b57cec5SDimitry Andric     SDValue Hi = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HH,
21460b57cec5SDimitry Andric                               SparcMCExpr::VK_Sparc_HM, DAG);
21470b57cec5SDimitry Andric     Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, DAG.getConstant(32, DL, MVT::i32));
21480b57cec5SDimitry Andric     SDValue Lo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
21490b57cec5SDimitry Andric                               SparcMCExpr::VK_Sparc_LO, DAG);
21500b57cec5SDimitry Andric     return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo);
21510b57cec5SDimitry Andric   }
21520b57cec5SDimitry Andric   }
21530b57cec5SDimitry Andric }
21540b57cec5SDimitry Andric 
21550b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op,
21560b57cec5SDimitry Andric                                                 SelectionDAG &DAG) const {
21570b57cec5SDimitry Andric   return makeAddress(Op, DAG);
21580b57cec5SDimitry Andric }
21590b57cec5SDimitry Andric 
21600b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerConstantPool(SDValue Op,
21610b57cec5SDimitry Andric                                                SelectionDAG &DAG) const {
21620b57cec5SDimitry Andric   return makeAddress(Op, DAG);
21630b57cec5SDimitry Andric }
21640b57cec5SDimitry Andric 
21650b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerBlockAddress(SDValue Op,
21660b57cec5SDimitry Andric                                                SelectionDAG &DAG) const {
21670b57cec5SDimitry Andric   return makeAddress(Op, DAG);
21680b57cec5SDimitry Andric }
21690b57cec5SDimitry Andric 
21700b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op,
21710b57cec5SDimitry Andric                                                    SelectionDAG &DAG) const {
21720b57cec5SDimitry Andric 
21730b57cec5SDimitry Andric   GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
21740b57cec5SDimitry Andric   if (DAG.getTarget().useEmulatedTLS())
21750b57cec5SDimitry Andric     return LowerToTLSEmulatedModel(GA, DAG);
21760b57cec5SDimitry Andric 
21770b57cec5SDimitry Andric   SDLoc DL(GA);
21780b57cec5SDimitry Andric   const GlobalValue *GV = GA->getGlobal();
21790b57cec5SDimitry Andric   EVT PtrVT = getPointerTy(DAG.getDataLayout());
21800b57cec5SDimitry Andric 
21810b57cec5SDimitry Andric   TLSModel::Model model = getTargetMachine().getTLSModel(GV);
21820b57cec5SDimitry Andric 
21830b57cec5SDimitry Andric   if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) {
21840b57cec5SDimitry Andric     unsigned HiTF = ((model == TLSModel::GeneralDynamic)
21850b57cec5SDimitry Andric                      ? SparcMCExpr::VK_Sparc_TLS_GD_HI22
21860b57cec5SDimitry Andric                      : SparcMCExpr::VK_Sparc_TLS_LDM_HI22);
21870b57cec5SDimitry Andric     unsigned LoTF = ((model == TLSModel::GeneralDynamic)
21880b57cec5SDimitry Andric                      ? SparcMCExpr::VK_Sparc_TLS_GD_LO10
21890b57cec5SDimitry Andric                      : SparcMCExpr::VK_Sparc_TLS_LDM_LO10);
21900b57cec5SDimitry Andric     unsigned addTF = ((model == TLSModel::GeneralDynamic)
21910b57cec5SDimitry Andric                       ? SparcMCExpr::VK_Sparc_TLS_GD_ADD
21920b57cec5SDimitry Andric                       : SparcMCExpr::VK_Sparc_TLS_LDM_ADD);
21930b57cec5SDimitry Andric     unsigned callTF = ((model == TLSModel::GeneralDynamic)
21940b57cec5SDimitry Andric                        ? SparcMCExpr::VK_Sparc_TLS_GD_CALL
21950b57cec5SDimitry Andric                        : SparcMCExpr::VK_Sparc_TLS_LDM_CALL);
21960b57cec5SDimitry Andric 
21970b57cec5SDimitry Andric     SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG);
21980b57cec5SDimitry Andric     SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
21990b57cec5SDimitry Andric     SDValue Argument = DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Base, HiLo,
22000b57cec5SDimitry Andric                                withTargetFlags(Op, addTF, DAG));
22010b57cec5SDimitry Andric 
22020b57cec5SDimitry Andric     SDValue Chain = DAG.getEntryNode();
22030b57cec5SDimitry Andric     SDValue InFlag;
22040b57cec5SDimitry Andric 
22050b57cec5SDimitry Andric     Chain = DAG.getCALLSEQ_START(Chain, 1, 0, DL);
22060b57cec5SDimitry Andric     Chain = DAG.getCopyToReg(Chain, DL, SP::O0, Argument, InFlag);
22070b57cec5SDimitry Andric     InFlag = Chain.getValue(1);
22080b57cec5SDimitry Andric     SDValue Callee = DAG.getTargetExternalSymbol("__tls_get_addr", PtrVT);
22090b57cec5SDimitry Andric     SDValue Symbol = withTargetFlags(Op, callTF, DAG);
22100b57cec5SDimitry Andric 
22110b57cec5SDimitry Andric     SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
22120b57cec5SDimitry Andric     const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask(
22130b57cec5SDimitry Andric         DAG.getMachineFunction(), CallingConv::C);
22140b57cec5SDimitry Andric     assert(Mask && "Missing call preserved mask for calling convention");
22150b57cec5SDimitry Andric     SDValue Ops[] = {Chain,
22160b57cec5SDimitry Andric                      Callee,
22170b57cec5SDimitry Andric                      Symbol,
22180b57cec5SDimitry Andric                      DAG.getRegister(SP::O0, PtrVT),
22190b57cec5SDimitry Andric                      DAG.getRegisterMask(Mask),
22200b57cec5SDimitry Andric                      InFlag};
22210b57cec5SDimitry Andric     Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, Ops);
22220b57cec5SDimitry Andric     InFlag = Chain.getValue(1);
2223*bdd1243dSDimitry Andric     Chain = DAG.getCALLSEQ_END(Chain, 1, 0, InFlag, DL);
22240b57cec5SDimitry Andric     InFlag = Chain.getValue(1);
22250b57cec5SDimitry Andric     SDValue Ret = DAG.getCopyFromReg(Chain, DL, SP::O0, PtrVT, InFlag);
22260b57cec5SDimitry Andric 
22270b57cec5SDimitry Andric     if (model != TLSModel::LocalDynamic)
22280b57cec5SDimitry Andric       return Ret;
22290b57cec5SDimitry Andric 
22300b57cec5SDimitry Andric     SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
22310b57cec5SDimitry Andric                  withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG));
22320b57cec5SDimitry Andric     SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
22330b57cec5SDimitry Andric                  withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG));
22340b57cec5SDimitry Andric     HiLo =  DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
22350b57cec5SDimitry Andric     return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo,
22360b57cec5SDimitry Andric                    withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG));
22370b57cec5SDimitry Andric   }
22380b57cec5SDimitry Andric 
22390b57cec5SDimitry Andric   if (model == TLSModel::InitialExec) {
22400b57cec5SDimitry Andric     unsigned ldTF     = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX
22410b57cec5SDimitry Andric                          : SparcMCExpr::VK_Sparc_TLS_IE_LD);
22420b57cec5SDimitry Andric 
22430b57cec5SDimitry Andric     SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
22440b57cec5SDimitry Andric 
22450b57cec5SDimitry Andric     // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
22460b57cec5SDimitry Andric     // function has calls.
22470b57cec5SDimitry Andric     MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
22480b57cec5SDimitry Andric     MFI.setHasCalls(true);
22490b57cec5SDimitry Andric 
22500b57cec5SDimitry Andric     SDValue TGA = makeHiLoPair(Op,
22510b57cec5SDimitry Andric                                SparcMCExpr::VK_Sparc_TLS_IE_HI22,
22520b57cec5SDimitry Andric                                SparcMCExpr::VK_Sparc_TLS_IE_LO10, DAG);
22530b57cec5SDimitry Andric     SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base, TGA);
22540b57cec5SDimitry Andric     SDValue Offset = DAG.getNode(SPISD::TLS_LD,
22550b57cec5SDimitry Andric                                  DL, PtrVT, Ptr,
22560b57cec5SDimitry Andric                                  withTargetFlags(Op, ldTF, DAG));
22570b57cec5SDimitry Andric     return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT,
22580b57cec5SDimitry Andric                        DAG.getRegister(SP::G7, PtrVT), Offset,
22590b57cec5SDimitry Andric                        withTargetFlags(Op,
22600b57cec5SDimitry Andric                                        SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG));
22610b57cec5SDimitry Andric   }
22620b57cec5SDimitry Andric 
22630b57cec5SDimitry Andric   assert(model == TLSModel::LocalExec);
22640b57cec5SDimitry Andric   SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
22650b57cec5SDimitry Andric                   withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG));
22660b57cec5SDimitry Andric   SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
22670b57cec5SDimitry Andric                   withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG));
22680b57cec5SDimitry Andric   SDValue Offset =  DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
22690b57cec5SDimitry Andric 
22700b57cec5SDimitry Andric   return DAG.getNode(ISD::ADD, DL, PtrVT,
22710b57cec5SDimitry Andric                      DAG.getRegister(SP::G7, PtrVT), Offset);
22720b57cec5SDimitry Andric }
22730b57cec5SDimitry Andric 
22740b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain,
22750b57cec5SDimitry Andric                                                   ArgListTy &Args, SDValue Arg,
22760b57cec5SDimitry Andric                                                   const SDLoc &DL,
22770b57cec5SDimitry Andric                                                   SelectionDAG &DAG) const {
22780b57cec5SDimitry Andric   MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
22790b57cec5SDimitry Andric   EVT ArgVT = Arg.getValueType();
22800b57cec5SDimitry Andric   Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
22810b57cec5SDimitry Andric 
22820b57cec5SDimitry Andric   ArgListEntry Entry;
22830b57cec5SDimitry Andric   Entry.Node = Arg;
22840b57cec5SDimitry Andric   Entry.Ty   = ArgTy;
22850b57cec5SDimitry Andric 
22860b57cec5SDimitry Andric   if (ArgTy->isFP128Ty()) {
22870b57cec5SDimitry Andric     // Create a stack object and pass the pointer to the library function.
22885ffd83dbSDimitry Andric     int FI = MFI.CreateStackObject(16, Align(8), false);
22890b57cec5SDimitry Andric     SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
22900b57cec5SDimitry Andric     Chain = DAG.getStore(Chain, DL, Entry.Node, FIPtr, MachinePointerInfo(),
2291e8d8bef9SDimitry Andric                          Align(8));
22920b57cec5SDimitry Andric 
22930b57cec5SDimitry Andric     Entry.Node = FIPtr;
22940b57cec5SDimitry Andric     Entry.Ty   = PointerType::getUnqual(ArgTy);
22950b57cec5SDimitry Andric   }
22960b57cec5SDimitry Andric   Args.push_back(Entry);
22970b57cec5SDimitry Andric   return Chain;
22980b57cec5SDimitry Andric }
22990b57cec5SDimitry Andric 
23000b57cec5SDimitry Andric SDValue
23010b57cec5SDimitry Andric SparcTargetLowering::LowerF128Op(SDValue Op, SelectionDAG &DAG,
23020b57cec5SDimitry Andric                                  const char *LibFuncName,
23030b57cec5SDimitry Andric                                  unsigned numArgs) const {
23040b57cec5SDimitry Andric 
23050b57cec5SDimitry Andric   ArgListTy Args;
23060b57cec5SDimitry Andric 
23070b57cec5SDimitry Andric   MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
23080b57cec5SDimitry Andric   auto PtrVT = getPointerTy(DAG.getDataLayout());
23090b57cec5SDimitry Andric 
23100b57cec5SDimitry Andric   SDValue Callee = DAG.getExternalSymbol(LibFuncName, PtrVT);
23110b57cec5SDimitry Andric   Type *RetTy = Op.getValueType().getTypeForEVT(*DAG.getContext());
23120b57cec5SDimitry Andric   Type *RetTyABI = RetTy;
23130b57cec5SDimitry Andric   SDValue Chain = DAG.getEntryNode();
23140b57cec5SDimitry Andric   SDValue RetPtr;
23150b57cec5SDimitry Andric 
23160b57cec5SDimitry Andric   if (RetTy->isFP128Ty()) {
23170b57cec5SDimitry Andric     // Create a Stack Object to receive the return value of type f128.
23180b57cec5SDimitry Andric     ArgListEntry Entry;
23195ffd83dbSDimitry Andric     int RetFI = MFI.CreateStackObject(16, Align(8), false);
23200b57cec5SDimitry Andric     RetPtr = DAG.getFrameIndex(RetFI, PtrVT);
23210b57cec5SDimitry Andric     Entry.Node = RetPtr;
23220b57cec5SDimitry Andric     Entry.Ty   = PointerType::getUnqual(RetTy);
232381ad6265SDimitry Andric     if (!Subtarget->is64Bit()) {
23240b57cec5SDimitry Andric       Entry.IsSRet = true;
232581ad6265SDimitry Andric       Entry.IndirectType = RetTy;
232681ad6265SDimitry Andric     }
23270b57cec5SDimitry Andric     Entry.IsReturned = false;
23280b57cec5SDimitry Andric     Args.push_back(Entry);
23290b57cec5SDimitry Andric     RetTyABI = Type::getVoidTy(*DAG.getContext());
23300b57cec5SDimitry Andric   }
23310b57cec5SDimitry Andric 
23320b57cec5SDimitry Andric   assert(Op->getNumOperands() >= numArgs && "Not enough operands!");
23330b57cec5SDimitry Andric   for (unsigned i = 0, e = numArgs; i != e; ++i) {
23340b57cec5SDimitry Andric     Chain = LowerF128_LibCallArg(Chain, Args, Op.getOperand(i), SDLoc(Op), DAG);
23350b57cec5SDimitry Andric   }
23360b57cec5SDimitry Andric   TargetLowering::CallLoweringInfo CLI(DAG);
23370b57cec5SDimitry Andric   CLI.setDebugLoc(SDLoc(Op)).setChain(Chain)
23380b57cec5SDimitry Andric     .setCallee(CallingConv::C, RetTyABI, Callee, std::move(Args));
23390b57cec5SDimitry Andric 
23400b57cec5SDimitry Andric   std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
23410b57cec5SDimitry Andric 
23420b57cec5SDimitry Andric   // chain is in second result.
23430b57cec5SDimitry Andric   if (RetTyABI == RetTy)
23440b57cec5SDimitry Andric     return CallInfo.first;
23450b57cec5SDimitry Andric 
23460b57cec5SDimitry Andric   assert (RetTy->isFP128Ty() && "Unexpected return type!");
23470b57cec5SDimitry Andric 
23480b57cec5SDimitry Andric   Chain = CallInfo.second;
23490b57cec5SDimitry Andric 
23500b57cec5SDimitry Andric   // Load RetPtr to get the return value.
23510b57cec5SDimitry Andric   return DAG.getLoad(Op.getValueType(), SDLoc(Op), Chain, RetPtr,
2352e8d8bef9SDimitry Andric                      MachinePointerInfo(), Align(8));
23530b57cec5SDimitry Andric }
23540b57cec5SDimitry Andric 
23550b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerF128Compare(SDValue LHS, SDValue RHS,
23560b57cec5SDimitry Andric                                               unsigned &SPCC, const SDLoc &DL,
23570b57cec5SDimitry Andric                                               SelectionDAG &DAG) const {
23580b57cec5SDimitry Andric 
23590b57cec5SDimitry Andric   const char *LibCall = nullptr;
23600b57cec5SDimitry Andric   bool is64Bit = Subtarget->is64Bit();
23610b57cec5SDimitry Andric   switch(SPCC) {
23620b57cec5SDimitry Andric   default: llvm_unreachable("Unhandled conditional code!");
23630b57cec5SDimitry Andric   case SPCC::FCC_E  : LibCall = is64Bit? "_Qp_feq" : "_Q_feq"; break;
23640b57cec5SDimitry Andric   case SPCC::FCC_NE : LibCall = is64Bit? "_Qp_fne" : "_Q_fne"; break;
23650b57cec5SDimitry Andric   case SPCC::FCC_L  : LibCall = is64Bit? "_Qp_flt" : "_Q_flt"; break;
23660b57cec5SDimitry Andric   case SPCC::FCC_G  : LibCall = is64Bit? "_Qp_fgt" : "_Q_fgt"; break;
23670b57cec5SDimitry Andric   case SPCC::FCC_LE : LibCall = is64Bit? "_Qp_fle" : "_Q_fle"; break;
23680b57cec5SDimitry Andric   case SPCC::FCC_GE : LibCall = is64Bit? "_Qp_fge" : "_Q_fge"; break;
23690b57cec5SDimitry Andric   case SPCC::FCC_UL :
23700b57cec5SDimitry Andric   case SPCC::FCC_ULE:
23710b57cec5SDimitry Andric   case SPCC::FCC_UG :
23720b57cec5SDimitry Andric   case SPCC::FCC_UGE:
23730b57cec5SDimitry Andric   case SPCC::FCC_U  :
23740b57cec5SDimitry Andric   case SPCC::FCC_O  :
23750b57cec5SDimitry Andric   case SPCC::FCC_LG :
23760b57cec5SDimitry Andric   case SPCC::FCC_UE : LibCall = is64Bit? "_Qp_cmp" : "_Q_cmp"; break;
23770b57cec5SDimitry Andric   }
23780b57cec5SDimitry Andric 
23790b57cec5SDimitry Andric   auto PtrVT = getPointerTy(DAG.getDataLayout());
23800b57cec5SDimitry Andric   SDValue Callee = DAG.getExternalSymbol(LibCall, PtrVT);
23810b57cec5SDimitry Andric   Type *RetTy = Type::getInt32Ty(*DAG.getContext());
23820b57cec5SDimitry Andric   ArgListTy Args;
23830b57cec5SDimitry Andric   SDValue Chain = DAG.getEntryNode();
23840b57cec5SDimitry Andric   Chain = LowerF128_LibCallArg(Chain, Args, LHS, DL, DAG);
23850b57cec5SDimitry Andric   Chain = LowerF128_LibCallArg(Chain, Args, RHS, DL, DAG);
23860b57cec5SDimitry Andric 
23870b57cec5SDimitry Andric   TargetLowering::CallLoweringInfo CLI(DAG);
23880b57cec5SDimitry Andric   CLI.setDebugLoc(DL).setChain(Chain)
23890b57cec5SDimitry Andric     .setCallee(CallingConv::C, RetTy, Callee, std::move(Args));
23900b57cec5SDimitry Andric 
23910b57cec5SDimitry Andric   std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
23920b57cec5SDimitry Andric 
23930b57cec5SDimitry Andric   // result is in first, and chain is in second result.
23940b57cec5SDimitry Andric   SDValue Result =  CallInfo.first;
23950b57cec5SDimitry Andric 
23960b57cec5SDimitry Andric   switch(SPCC) {
23970b57cec5SDimitry Andric   default: {
23985ffd83dbSDimitry Andric     SDValue RHS = DAG.getConstant(0, DL, Result.getValueType());
23990b57cec5SDimitry Andric     SPCC = SPCC::ICC_NE;
24000b57cec5SDimitry Andric     return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24010b57cec5SDimitry Andric   }
24020b57cec5SDimitry Andric   case SPCC::FCC_UL : {
24038bcb0991SDimitry Andric     SDValue Mask   = DAG.getConstant(1, DL, Result.getValueType());
24040b57cec5SDimitry Andric     Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask);
24055ffd83dbSDimitry Andric     SDValue RHS    = DAG.getConstant(0, DL, Result.getValueType());
24060b57cec5SDimitry Andric     SPCC = SPCC::ICC_NE;
24070b57cec5SDimitry Andric     return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24080b57cec5SDimitry Andric   }
24090b57cec5SDimitry Andric   case SPCC::FCC_ULE: {
24105ffd83dbSDimitry Andric     SDValue RHS = DAG.getConstant(2, DL, Result.getValueType());
24110b57cec5SDimitry Andric     SPCC = SPCC::ICC_NE;
24120b57cec5SDimitry Andric     return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24130b57cec5SDimitry Andric   }
24140b57cec5SDimitry Andric   case SPCC::FCC_UG :  {
24155ffd83dbSDimitry Andric     SDValue RHS = DAG.getConstant(1, DL, Result.getValueType());
24160b57cec5SDimitry Andric     SPCC = SPCC::ICC_G;
24170b57cec5SDimitry Andric     return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24180b57cec5SDimitry Andric   }
24190b57cec5SDimitry Andric   case SPCC::FCC_UGE: {
24205ffd83dbSDimitry Andric     SDValue RHS = DAG.getConstant(1, DL, Result.getValueType());
24210b57cec5SDimitry Andric     SPCC = SPCC::ICC_NE;
24220b57cec5SDimitry Andric     return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24230b57cec5SDimitry Andric   }
24240b57cec5SDimitry Andric 
24250b57cec5SDimitry Andric   case SPCC::FCC_U  :  {
24265ffd83dbSDimitry Andric     SDValue RHS = DAG.getConstant(3, DL, Result.getValueType());
24270b57cec5SDimitry Andric     SPCC = SPCC::ICC_E;
24280b57cec5SDimitry Andric     return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24290b57cec5SDimitry Andric   }
24300b57cec5SDimitry Andric   case SPCC::FCC_O  :  {
24315ffd83dbSDimitry Andric     SDValue RHS = DAG.getConstant(3, DL, Result.getValueType());
24320b57cec5SDimitry Andric     SPCC = SPCC::ICC_NE;
24330b57cec5SDimitry Andric     return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24340b57cec5SDimitry Andric   }
24350b57cec5SDimitry Andric   case SPCC::FCC_LG :  {
24368bcb0991SDimitry Andric     SDValue Mask   = DAG.getConstant(3, DL, Result.getValueType());
24370b57cec5SDimitry Andric     Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask);
24385ffd83dbSDimitry Andric     SDValue RHS    = DAG.getConstant(0, DL, Result.getValueType());
24390b57cec5SDimitry Andric     SPCC = SPCC::ICC_NE;
24400b57cec5SDimitry Andric     return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24410b57cec5SDimitry Andric   }
24420b57cec5SDimitry Andric   case SPCC::FCC_UE : {
24438bcb0991SDimitry Andric     SDValue Mask   = DAG.getConstant(3, DL, Result.getValueType());
24440b57cec5SDimitry Andric     Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask);
24455ffd83dbSDimitry Andric     SDValue RHS    = DAG.getConstant(0, DL, Result.getValueType());
24460b57cec5SDimitry Andric     SPCC = SPCC::ICC_E;
24470b57cec5SDimitry Andric     return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS);
24480b57cec5SDimitry Andric   }
24490b57cec5SDimitry Andric   }
24500b57cec5SDimitry Andric }
24510b57cec5SDimitry Andric 
24520b57cec5SDimitry Andric static SDValue
24530b57cec5SDimitry Andric LowerF128_FPEXTEND(SDValue Op, SelectionDAG &DAG,
24540b57cec5SDimitry Andric                    const SparcTargetLowering &TLI) {
24550b57cec5SDimitry Andric 
24560b57cec5SDimitry Andric   if (Op.getOperand(0).getValueType() == MVT::f64)
24570b57cec5SDimitry Andric     return TLI.LowerF128Op(Op, DAG,
24580b57cec5SDimitry Andric                            TLI.getLibcallName(RTLIB::FPEXT_F64_F128), 1);
24590b57cec5SDimitry Andric 
24600b57cec5SDimitry Andric   if (Op.getOperand(0).getValueType() == MVT::f32)
24610b57cec5SDimitry Andric     return TLI.LowerF128Op(Op, DAG,
24620b57cec5SDimitry Andric                            TLI.getLibcallName(RTLIB::FPEXT_F32_F128), 1);
24630b57cec5SDimitry Andric 
24640b57cec5SDimitry Andric   llvm_unreachable("fpextend with non-float operand!");
24650b57cec5SDimitry Andric   return SDValue();
24660b57cec5SDimitry Andric }
24670b57cec5SDimitry Andric 
24680b57cec5SDimitry Andric static SDValue
24690b57cec5SDimitry Andric LowerF128_FPROUND(SDValue Op, SelectionDAG &DAG,
24700b57cec5SDimitry Andric                   const SparcTargetLowering &TLI) {
24710b57cec5SDimitry Andric   // FP_ROUND on f64 and f32 are legal.
24720b57cec5SDimitry Andric   if (Op.getOperand(0).getValueType() != MVT::f128)
24730b57cec5SDimitry Andric     return Op;
24740b57cec5SDimitry Andric 
24750b57cec5SDimitry Andric   if (Op.getValueType() == MVT::f64)
24760b57cec5SDimitry Andric     return TLI.LowerF128Op(Op, DAG,
24770b57cec5SDimitry Andric                            TLI.getLibcallName(RTLIB::FPROUND_F128_F64), 1);
24780b57cec5SDimitry Andric   if (Op.getValueType() == MVT::f32)
24790b57cec5SDimitry Andric     return TLI.LowerF128Op(Op, DAG,
24800b57cec5SDimitry Andric                            TLI.getLibcallName(RTLIB::FPROUND_F128_F32), 1);
24810b57cec5SDimitry Andric 
24820b57cec5SDimitry Andric   llvm_unreachable("fpround to non-float!");
24830b57cec5SDimitry Andric   return SDValue();
24840b57cec5SDimitry Andric }
24850b57cec5SDimitry Andric 
24860b57cec5SDimitry Andric static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG,
24870b57cec5SDimitry Andric                                const SparcTargetLowering &TLI,
24880b57cec5SDimitry Andric                                bool hasHardQuad) {
24890b57cec5SDimitry Andric   SDLoc dl(Op);
24900b57cec5SDimitry Andric   EVT VT = Op.getValueType();
24910b57cec5SDimitry Andric   assert(VT == MVT::i32 || VT == MVT::i64);
24920b57cec5SDimitry Andric 
24930b57cec5SDimitry Andric   // Expand f128 operations to fp128 abi calls.
24940b57cec5SDimitry Andric   if (Op.getOperand(0).getValueType() == MVT::f128
24950b57cec5SDimitry Andric       && (!hasHardQuad || !TLI.isTypeLegal(VT))) {
24960b57cec5SDimitry Andric     const char *libName = TLI.getLibcallName(VT == MVT::i32
24970b57cec5SDimitry Andric                                              ? RTLIB::FPTOSINT_F128_I32
24980b57cec5SDimitry Andric                                              : RTLIB::FPTOSINT_F128_I64);
24990b57cec5SDimitry Andric     return TLI.LowerF128Op(Op, DAG, libName, 1);
25000b57cec5SDimitry Andric   }
25010b57cec5SDimitry Andric 
25020b57cec5SDimitry Andric   // Expand if the resulting type is illegal.
25030b57cec5SDimitry Andric   if (!TLI.isTypeLegal(VT))
25040b57cec5SDimitry Andric     return SDValue();
25050b57cec5SDimitry Andric 
25060b57cec5SDimitry Andric   // Otherwise, Convert the fp value to integer in an FP register.
25070b57cec5SDimitry Andric   if (VT == MVT::i32)
25080b57cec5SDimitry Andric     Op = DAG.getNode(SPISD::FTOI, dl, MVT::f32, Op.getOperand(0));
25090b57cec5SDimitry Andric   else
25100b57cec5SDimitry Andric     Op = DAG.getNode(SPISD::FTOX, dl, MVT::f64, Op.getOperand(0));
25110b57cec5SDimitry Andric 
25120b57cec5SDimitry Andric   return DAG.getNode(ISD::BITCAST, dl, VT, Op);
25130b57cec5SDimitry Andric }
25140b57cec5SDimitry Andric 
25150b57cec5SDimitry Andric static SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG,
25160b57cec5SDimitry Andric                                const SparcTargetLowering &TLI,
25170b57cec5SDimitry Andric                                bool hasHardQuad) {
25180b57cec5SDimitry Andric   SDLoc dl(Op);
25190b57cec5SDimitry Andric   EVT OpVT = Op.getOperand(0).getValueType();
25200b57cec5SDimitry Andric   assert(OpVT == MVT::i32 || (OpVT == MVT::i64));
25210b57cec5SDimitry Andric 
25220b57cec5SDimitry Andric   EVT floatVT = (OpVT == MVT::i32) ? MVT::f32 : MVT::f64;
25230b57cec5SDimitry Andric 
25240b57cec5SDimitry Andric   // Expand f128 operations to fp128 ABI calls.
25250b57cec5SDimitry Andric   if (Op.getValueType() == MVT::f128
25260b57cec5SDimitry Andric       && (!hasHardQuad || !TLI.isTypeLegal(OpVT))) {
25270b57cec5SDimitry Andric     const char *libName = TLI.getLibcallName(OpVT == MVT::i32
25280b57cec5SDimitry Andric                                              ? RTLIB::SINTTOFP_I32_F128
25290b57cec5SDimitry Andric                                              : RTLIB::SINTTOFP_I64_F128);
25300b57cec5SDimitry Andric     return TLI.LowerF128Op(Op, DAG, libName, 1);
25310b57cec5SDimitry Andric   }
25320b57cec5SDimitry Andric 
25330b57cec5SDimitry Andric   // Expand if the operand type is illegal.
25340b57cec5SDimitry Andric   if (!TLI.isTypeLegal(OpVT))
25350b57cec5SDimitry Andric     return SDValue();
25360b57cec5SDimitry Andric 
25370b57cec5SDimitry Andric   // Otherwise, Convert the int value to FP in an FP register.
25380b57cec5SDimitry Andric   SDValue Tmp = DAG.getNode(ISD::BITCAST, dl, floatVT, Op.getOperand(0));
25390b57cec5SDimitry Andric   unsigned opcode = (OpVT == MVT::i32)? SPISD::ITOF : SPISD::XTOF;
25400b57cec5SDimitry Andric   return DAG.getNode(opcode, dl, Op.getValueType(), Tmp);
25410b57cec5SDimitry Andric }
25420b57cec5SDimitry Andric 
25430b57cec5SDimitry Andric static SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG,
25440b57cec5SDimitry Andric                                const SparcTargetLowering &TLI,
25450b57cec5SDimitry Andric                                bool hasHardQuad) {
25460b57cec5SDimitry Andric   SDLoc dl(Op);
25470b57cec5SDimitry Andric   EVT VT = Op.getValueType();
25480b57cec5SDimitry Andric 
25490b57cec5SDimitry Andric   // Expand if it does not involve f128 or the target has support for
25500b57cec5SDimitry Andric   // quad floating point instructions and the resulting type is legal.
25510b57cec5SDimitry Andric   if (Op.getOperand(0).getValueType() != MVT::f128 ||
25520b57cec5SDimitry Andric       (hasHardQuad && TLI.isTypeLegal(VT)))
25530b57cec5SDimitry Andric     return SDValue();
25540b57cec5SDimitry Andric 
25550b57cec5SDimitry Andric   assert(VT == MVT::i32 || VT == MVT::i64);
25560b57cec5SDimitry Andric 
25570b57cec5SDimitry Andric   return TLI.LowerF128Op(Op, DAG,
25580b57cec5SDimitry Andric                          TLI.getLibcallName(VT == MVT::i32
25590b57cec5SDimitry Andric                                             ? RTLIB::FPTOUINT_F128_I32
25600b57cec5SDimitry Andric                                             : RTLIB::FPTOUINT_F128_I64),
25610b57cec5SDimitry Andric                          1);
25620b57cec5SDimitry Andric }
25630b57cec5SDimitry Andric 
25640b57cec5SDimitry Andric static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG,
25650b57cec5SDimitry Andric                                const SparcTargetLowering &TLI,
25660b57cec5SDimitry Andric                                bool hasHardQuad) {
25670b57cec5SDimitry Andric   SDLoc dl(Op);
25680b57cec5SDimitry Andric   EVT OpVT = Op.getOperand(0).getValueType();
25690b57cec5SDimitry Andric   assert(OpVT == MVT::i32 || OpVT == MVT::i64);
25700b57cec5SDimitry Andric 
25710b57cec5SDimitry Andric   // Expand if it does not involve f128 or the target has support for
25720b57cec5SDimitry Andric   // quad floating point instructions and the operand type is legal.
25730b57cec5SDimitry Andric   if (Op.getValueType() != MVT::f128 || (hasHardQuad && TLI.isTypeLegal(OpVT)))
25740b57cec5SDimitry Andric     return SDValue();
25750b57cec5SDimitry Andric 
25760b57cec5SDimitry Andric   return TLI.LowerF128Op(Op, DAG,
25770b57cec5SDimitry Andric                          TLI.getLibcallName(OpVT == MVT::i32
25780b57cec5SDimitry Andric                                             ? RTLIB::UINTTOFP_I32_F128
25790b57cec5SDimitry Andric                                             : RTLIB::UINTTOFP_I64_F128),
25800b57cec5SDimitry Andric                          1);
25810b57cec5SDimitry Andric }
25820b57cec5SDimitry Andric 
25830b57cec5SDimitry Andric static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG,
2584*bdd1243dSDimitry Andric                           const SparcTargetLowering &TLI, bool hasHardQuad,
2585*bdd1243dSDimitry Andric                           bool isV9) {
25860b57cec5SDimitry Andric   SDValue Chain = Op.getOperand(0);
25870b57cec5SDimitry Andric   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
25880b57cec5SDimitry Andric   SDValue LHS = Op.getOperand(2);
25890b57cec5SDimitry Andric   SDValue RHS = Op.getOperand(3);
25900b57cec5SDimitry Andric   SDValue Dest = Op.getOperand(4);
25910b57cec5SDimitry Andric   SDLoc dl(Op);
25920b57cec5SDimitry Andric   unsigned Opc, SPCC = ~0U;
25930b57cec5SDimitry Andric 
25940b57cec5SDimitry Andric   // If this is a br_cc of a "setcc", and if the setcc got lowered into
25950b57cec5SDimitry Andric   // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
25960b57cec5SDimitry Andric   LookThroughSetCC(LHS, RHS, CC, SPCC);
2597*bdd1243dSDimitry Andric   assert(LHS.getValueType() == RHS.getValueType());
25980b57cec5SDimitry Andric 
25990b57cec5SDimitry Andric   // Get the condition flag.
26000b57cec5SDimitry Andric   SDValue CompareFlag;
26010b57cec5SDimitry Andric   if (LHS.getValueType().isInteger()) {
26020b57cec5SDimitry Andric     CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS);
26030b57cec5SDimitry Andric     if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
2604*bdd1243dSDimitry Andric     if (isV9)
26050b57cec5SDimitry Andric       // 32-bit compares use the icc flags, 64-bit uses the xcc flags.
2606*bdd1243dSDimitry Andric       Opc = LHS.getValueType() == MVT::i32 ? SPISD::BPICC : SPISD::BPXCC;
2607*bdd1243dSDimitry Andric     else
2608*bdd1243dSDimitry Andric       // Non-v9 targets don't have xcc.
2609*bdd1243dSDimitry Andric       Opc = SPISD::BRICC;
26100b57cec5SDimitry Andric   } else {
26110b57cec5SDimitry Andric     if (!hasHardQuad && LHS.getValueType() == MVT::f128) {
26120b57cec5SDimitry Andric       if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
26130b57cec5SDimitry Andric       CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG);
2614*bdd1243dSDimitry Andric       Opc = isV9 ? SPISD::BPICC : SPISD::BRICC;
26150b57cec5SDimitry Andric     } else {
2616*bdd1243dSDimitry Andric       unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC;
2617*bdd1243dSDimitry Andric       CompareFlag = DAG.getNode(CmpOpc, dl, MVT::Glue, LHS, RHS);
26180b57cec5SDimitry Andric       if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
2619*bdd1243dSDimitry Andric       Opc = isV9 ? SPISD::BRFCC_V9 : SPISD::BRFCC;
26200b57cec5SDimitry Andric     }
26210b57cec5SDimitry Andric   }
26220b57cec5SDimitry Andric   return DAG.getNode(Opc, dl, MVT::Other, Chain, Dest,
26230b57cec5SDimitry Andric                      DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag);
26240b57cec5SDimitry Andric }
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2627*bdd1243dSDimitry Andric                               const SparcTargetLowering &TLI, bool hasHardQuad,
2628*bdd1243dSDimitry Andric                               bool isV9, bool is64Bit) {
26290b57cec5SDimitry Andric   SDValue LHS = Op.getOperand(0);
26300b57cec5SDimitry Andric   SDValue RHS = Op.getOperand(1);
26310b57cec5SDimitry Andric   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
26320b57cec5SDimitry Andric   SDValue TrueVal = Op.getOperand(2);
26330b57cec5SDimitry Andric   SDValue FalseVal = Op.getOperand(3);
26340b57cec5SDimitry Andric   SDLoc dl(Op);
26350b57cec5SDimitry Andric   unsigned Opc, SPCC = ~0U;
26360b57cec5SDimitry Andric 
26370b57cec5SDimitry Andric   // If this is a select_cc of a "setcc", and if the setcc got lowered into
26380b57cec5SDimitry Andric   // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
26390b57cec5SDimitry Andric   LookThroughSetCC(LHS, RHS, CC, SPCC);
2640*bdd1243dSDimitry Andric   assert(LHS.getValueType() == RHS.getValueType());
26410b57cec5SDimitry Andric 
26420b57cec5SDimitry Andric   SDValue CompareFlag;
26430b57cec5SDimitry Andric   if (LHS.getValueType().isInteger()) {
2644*bdd1243dSDimitry Andric     // On V9 processors running in 64-bit mode, if CC compares two `i64`s
2645*bdd1243dSDimitry Andric     // and the RHS is zero we might be able to use a specialized select.
2646*bdd1243dSDimitry Andric     // All SELECT_CC between any two scalar integer types are eligible for
2647*bdd1243dSDimitry Andric     // lowering to specialized instructions. Additionally, f32 and f64 types
2648*bdd1243dSDimitry Andric     // are also eligible, but for f128 we can only use the specialized
2649*bdd1243dSDimitry Andric     // instruction when we have hardquad.
2650*bdd1243dSDimitry Andric     EVT ValType = TrueVal.getValueType();
2651*bdd1243dSDimitry Andric     bool IsEligibleType = ValType.isScalarInteger() || ValType == MVT::f32 ||
2652*bdd1243dSDimitry Andric                           ValType == MVT::f64 ||
2653*bdd1243dSDimitry Andric                           (ValType == MVT::f128 && hasHardQuad);
2654*bdd1243dSDimitry Andric     if (is64Bit && isV9 && LHS.getValueType() == MVT::i64 &&
2655*bdd1243dSDimitry Andric         isNullConstant(RHS) && !ISD::isUnsignedIntSetCC(CC) && IsEligibleType)
2656*bdd1243dSDimitry Andric       return DAG.getNode(
2657*bdd1243dSDimitry Andric           SPISD::SELECT_REG, dl, TrueVal.getValueType(), TrueVal, FalseVal,
2658*bdd1243dSDimitry Andric           DAG.getConstant(intCondCCodeToRcond(CC), dl, MVT::i32), LHS);
2659*bdd1243dSDimitry Andric 
26600b57cec5SDimitry Andric     CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS);
26610b57cec5SDimitry Andric     Opc = LHS.getValueType() == MVT::i32 ?
26620b57cec5SDimitry Andric           SPISD::SELECT_ICC : SPISD::SELECT_XCC;
26630b57cec5SDimitry Andric     if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
26640b57cec5SDimitry Andric   } else {
26650b57cec5SDimitry Andric     if (!hasHardQuad && LHS.getValueType() == MVT::f128) {
26660b57cec5SDimitry Andric       if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
26670b57cec5SDimitry Andric       CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG);
26680b57cec5SDimitry Andric       Opc = SPISD::SELECT_ICC;
26690b57cec5SDimitry Andric     } else {
2670*bdd1243dSDimitry Andric       unsigned CmpOpc = isV9 ? SPISD::CMPFCC_V9 : SPISD::CMPFCC;
2671*bdd1243dSDimitry Andric       CompareFlag = DAG.getNode(CmpOpc, dl, MVT::Glue, LHS, RHS);
26720b57cec5SDimitry Andric       Opc = SPISD::SELECT_FCC;
26730b57cec5SDimitry Andric       if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
26740b57cec5SDimitry Andric     }
26750b57cec5SDimitry Andric   }
26760b57cec5SDimitry Andric   return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal,
26770b57cec5SDimitry Andric                      DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag);
26780b57cec5SDimitry Andric }
26790b57cec5SDimitry Andric 
26800b57cec5SDimitry Andric static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG,
26810b57cec5SDimitry Andric                             const SparcTargetLowering &TLI) {
26820b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
26830b57cec5SDimitry Andric   SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
26840b57cec5SDimitry Andric   auto PtrVT = TLI.getPointerTy(DAG.getDataLayout());
26850b57cec5SDimitry Andric 
26860b57cec5SDimitry Andric   // Need frame address to find the address of VarArgsFrameIndex.
26870b57cec5SDimitry Andric   MF.getFrameInfo().setFrameAddressIsTaken(true);
26880b57cec5SDimitry Andric 
26890b57cec5SDimitry Andric   // vastart just stores the address of the VarArgsFrameIndex slot into the
26900b57cec5SDimitry Andric   // memory location argument.
26910b57cec5SDimitry Andric   SDLoc DL(Op);
26920b57cec5SDimitry Andric   SDValue Offset =
26930b57cec5SDimitry Andric       DAG.getNode(ISD::ADD, DL, PtrVT, DAG.getRegister(SP::I6, PtrVT),
26940b57cec5SDimitry Andric                   DAG.getIntPtrConstant(FuncInfo->getVarArgsFrameOffset(), DL));
26950b57cec5SDimitry Andric   const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
26960b57cec5SDimitry Andric   return DAG.getStore(Op.getOperand(0), DL, Offset, Op.getOperand(1),
26970b57cec5SDimitry Andric                       MachinePointerInfo(SV));
26980b57cec5SDimitry Andric }
26990b57cec5SDimitry Andric 
27000b57cec5SDimitry Andric static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) {
27010b57cec5SDimitry Andric   SDNode *Node = Op.getNode();
27020b57cec5SDimitry Andric   EVT VT = Node->getValueType(0);
27030b57cec5SDimitry Andric   SDValue InChain = Node->getOperand(0);
27040b57cec5SDimitry Andric   SDValue VAListPtr = Node->getOperand(1);
27050b57cec5SDimitry Andric   EVT PtrVT = VAListPtr.getValueType();
27060b57cec5SDimitry Andric   const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
27070b57cec5SDimitry Andric   SDLoc DL(Node);
27080b57cec5SDimitry Andric   SDValue VAList =
27090b57cec5SDimitry Andric       DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV));
27100b57cec5SDimitry Andric   // Increment the pointer, VAList, to the next vaarg.
27110b57cec5SDimitry Andric   SDValue NextPtr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
27120b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(VT.getSizeInBits()/8,
27130b57cec5SDimitry Andric                                                       DL));
27140b57cec5SDimitry Andric   // Store the incremented VAList to the legalized pointer.
27150b57cec5SDimitry Andric   InChain = DAG.getStore(VAList.getValue(1), DL, NextPtr, VAListPtr,
27160b57cec5SDimitry Andric                          MachinePointerInfo(SV));
27170b57cec5SDimitry Andric   // Load the actual argument out of the pointer VAList.
27180b57cec5SDimitry Andric   // We can't count on greater alignment than the word size.
2719e8d8bef9SDimitry Andric   return DAG.getLoad(
2720e8d8bef9SDimitry Andric       VT, DL, InChain, VAList, MachinePointerInfo(),
2721*bdd1243dSDimitry Andric       Align(std::min(PtrVT.getFixedSizeInBits(), VT.getFixedSizeInBits()) / 8));
27220b57cec5SDimitry Andric }
27230b57cec5SDimitry Andric 
27240b57cec5SDimitry Andric static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG,
27250b57cec5SDimitry Andric                                        const SparcSubtarget *Subtarget) {
27260b57cec5SDimitry Andric   SDValue Chain = Op.getOperand(0);  // Legalize the chain.
27270b57cec5SDimitry Andric   SDValue Size  = Op.getOperand(1);  // Legalize the size.
27285ffd83dbSDimitry Andric   MaybeAlign Alignment =
27295ffd83dbSDimitry Andric       cast<ConstantSDNode>(Op.getOperand(2))->getMaybeAlignValue();
27305ffd83dbSDimitry Andric   Align StackAlign = Subtarget->getFrameLowering()->getStackAlign();
27310b57cec5SDimitry Andric   EVT VT = Size->getValueType(0);
27320b57cec5SDimitry Andric   SDLoc dl(Op);
27330b57cec5SDimitry Andric 
27340b57cec5SDimitry Andric   // TODO: implement over-aligned alloca. (Note: also implies
27350b57cec5SDimitry Andric   // supporting support for overaligned function frames + dynamic
27360b57cec5SDimitry Andric   // allocations, at all, which currently isn't supported)
27375ffd83dbSDimitry Andric   if (Alignment && *Alignment > StackAlign) {
27380b57cec5SDimitry Andric     const MachineFunction &MF = DAG.getMachineFunction();
27390b57cec5SDimitry Andric     report_fatal_error("Function \"" + Twine(MF.getName()) + "\": "
27400b57cec5SDimitry Andric                        "over-aligned dynamic alloca not supported.");
27410b57cec5SDimitry Andric   }
27420b57cec5SDimitry Andric 
27430b57cec5SDimitry Andric   // The resultant pointer needs to be above the register spill area
27440b57cec5SDimitry Andric   // at the bottom of the stack.
27450b57cec5SDimitry Andric   unsigned regSpillArea;
27460b57cec5SDimitry Andric   if (Subtarget->is64Bit()) {
27470b57cec5SDimitry Andric     regSpillArea = 128;
27480b57cec5SDimitry Andric   } else {
27490b57cec5SDimitry Andric     // On Sparc32, the size of the spill area is 92. Unfortunately,
27500b57cec5SDimitry Andric     // that's only 4-byte aligned, not 8-byte aligned (the stack
27510b57cec5SDimitry Andric     // pointer is 8-byte aligned). So, if the user asked for an 8-byte
27520b57cec5SDimitry Andric     // aligned dynamic allocation, we actually need to add 96 to the
27530b57cec5SDimitry Andric     // bottom of the stack, instead of 92, to ensure 8-byte alignment.
27540b57cec5SDimitry Andric 
27550b57cec5SDimitry Andric     // That also means adding 4 to the size of the allocation --
27560b57cec5SDimitry Andric     // before applying the 8-byte rounding. Unfortunately, we the
27570b57cec5SDimitry Andric     // value we get here has already had rounding applied. So, we need
27580b57cec5SDimitry Andric     // to add 8, instead, wasting a bit more memory.
27590b57cec5SDimitry Andric 
27600b57cec5SDimitry Andric     // Further, this only actually needs to be done if the required
27610b57cec5SDimitry Andric     // alignment is > 4, but, we've lost that info by this point, too,
27620b57cec5SDimitry Andric     // so we always apply it.
27630b57cec5SDimitry Andric 
27640b57cec5SDimitry Andric     // (An alternative approach would be to always reserve 96 bytes
27650b57cec5SDimitry Andric     // instead of the required 92, but then we'd waste 4 extra bytes
27660b57cec5SDimitry Andric     // in every frame, not just those with dynamic stack allocations)
27670b57cec5SDimitry Andric 
27680b57cec5SDimitry Andric     // TODO: modify code in SelectionDAGBuilder to make this less sad.
27690b57cec5SDimitry Andric 
27700b57cec5SDimitry Andric     Size = DAG.getNode(ISD::ADD, dl, VT, Size,
27710b57cec5SDimitry Andric                        DAG.getConstant(8, dl, VT));
27720b57cec5SDimitry Andric     regSpillArea = 96;
27730b57cec5SDimitry Andric   }
27740b57cec5SDimitry Andric 
27750b57cec5SDimitry Andric   unsigned SPReg = SP::O6;
27760b57cec5SDimitry Andric   SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
27770b57cec5SDimitry Andric   SDValue NewSP = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value
27780b57cec5SDimitry Andric   Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP);    // Output chain
27790b57cec5SDimitry Andric 
27800b57cec5SDimitry Andric   regSpillArea += Subtarget->getStackPointerBias();
27810b57cec5SDimitry Andric 
27820b57cec5SDimitry Andric   SDValue NewVal = DAG.getNode(ISD::ADD, dl, VT, NewSP,
27830b57cec5SDimitry Andric                                DAG.getConstant(regSpillArea, dl, VT));
27840b57cec5SDimitry Andric   SDValue Ops[2] = { NewVal, Chain };
27850b57cec5SDimitry Andric   return DAG.getMergeValues(Ops, dl);
27860b57cec5SDimitry Andric }
27870b57cec5SDimitry Andric 
27880b57cec5SDimitry Andric 
27890b57cec5SDimitry Andric static SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) {
27900b57cec5SDimitry Andric   SDLoc dl(Op);
27910b57cec5SDimitry Andric   SDValue Chain = DAG.getNode(SPISD::FLUSHW,
27920b57cec5SDimitry Andric                               dl, MVT::Other, DAG.getEntryNode());
27930b57cec5SDimitry Andric   return Chain;
27940b57cec5SDimitry Andric }
27950b57cec5SDimitry Andric 
27960b57cec5SDimitry Andric static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG,
27970b57cec5SDimitry Andric                             const SparcSubtarget *Subtarget,
27980b57cec5SDimitry Andric                             bool AlwaysFlush = false) {
27990b57cec5SDimitry Andric   MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
28000b57cec5SDimitry Andric   MFI.setFrameAddressIsTaken(true);
28010b57cec5SDimitry Andric 
28020b57cec5SDimitry Andric   EVT VT = Op.getValueType();
28030b57cec5SDimitry Andric   SDLoc dl(Op);
28040b57cec5SDimitry Andric   unsigned FrameReg = SP::I6;
28050b57cec5SDimitry Andric   unsigned stackBias = Subtarget->getStackPointerBias();
28060b57cec5SDimitry Andric 
28070b57cec5SDimitry Andric   SDValue FrameAddr;
28080b57cec5SDimitry Andric   SDValue Chain;
28090b57cec5SDimitry Andric 
28100b57cec5SDimitry Andric   // flush first to make sure the windowed registers' values are in stack
28110b57cec5SDimitry Andric   Chain = (depth || AlwaysFlush) ? getFLUSHW(Op, DAG) : DAG.getEntryNode();
28120b57cec5SDimitry Andric 
28130b57cec5SDimitry Andric   FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
28140b57cec5SDimitry Andric 
28150b57cec5SDimitry Andric   unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56;
28160b57cec5SDimitry Andric 
28170b57cec5SDimitry Andric   while (depth--) {
28180b57cec5SDimitry Andric     SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
28190b57cec5SDimitry Andric                               DAG.getIntPtrConstant(Offset, dl));
28200b57cec5SDimitry Andric     FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo());
28210b57cec5SDimitry Andric   }
28220b57cec5SDimitry Andric   if (Subtarget->is64Bit())
28230b57cec5SDimitry Andric     FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
28240b57cec5SDimitry Andric                             DAG.getIntPtrConstant(stackBias, dl));
28250b57cec5SDimitry Andric   return FrameAddr;
28260b57cec5SDimitry Andric }
28270b57cec5SDimitry Andric 
28280b57cec5SDimitry Andric 
28290b57cec5SDimitry Andric static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG,
28300b57cec5SDimitry Andric                               const SparcSubtarget *Subtarget) {
28310b57cec5SDimitry Andric 
28320b57cec5SDimitry Andric   uint64_t depth = Op.getConstantOperandVal(0);
28330b57cec5SDimitry Andric 
28340b57cec5SDimitry Andric   return getFRAMEADDR(depth, Op, DAG, Subtarget);
28350b57cec5SDimitry Andric 
28360b57cec5SDimitry Andric }
28370b57cec5SDimitry Andric 
28380b57cec5SDimitry Andric static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
28390b57cec5SDimitry Andric                                const SparcTargetLowering &TLI,
28400b57cec5SDimitry Andric                                const SparcSubtarget *Subtarget) {
28410b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
28420b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
28430b57cec5SDimitry Andric   MFI.setReturnAddressIsTaken(true);
28440b57cec5SDimitry Andric 
28450b57cec5SDimitry Andric   if (TLI.verifyReturnAddressArgumentIsConstant(Op, DAG))
28460b57cec5SDimitry Andric     return SDValue();
28470b57cec5SDimitry Andric 
28480b57cec5SDimitry Andric   EVT VT = Op.getValueType();
28490b57cec5SDimitry Andric   SDLoc dl(Op);
28500b57cec5SDimitry Andric   uint64_t depth = Op.getConstantOperandVal(0);
28510b57cec5SDimitry Andric 
28520b57cec5SDimitry Andric   SDValue RetAddr;
28530b57cec5SDimitry Andric   if (depth == 0) {
28540b57cec5SDimitry Andric     auto PtrVT = TLI.getPointerTy(DAG.getDataLayout());
285504eeddc0SDimitry Andric     Register RetReg = MF.addLiveIn(SP::I7, TLI.getRegClassFor(PtrVT));
28560b57cec5SDimitry Andric     RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT);
28570b57cec5SDimitry Andric     return RetAddr;
28580b57cec5SDimitry Andric   }
28590b57cec5SDimitry Andric 
28600b57cec5SDimitry Andric   // Need frame address to find return address of the caller.
28610b57cec5SDimitry Andric   SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget, true);
28620b57cec5SDimitry Andric 
28630b57cec5SDimitry Andric   unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60;
28640b57cec5SDimitry Andric   SDValue Ptr = DAG.getNode(ISD::ADD,
28650b57cec5SDimitry Andric                             dl, VT,
28660b57cec5SDimitry Andric                             FrameAddr,
28670b57cec5SDimitry Andric                             DAG.getIntPtrConstant(Offset, dl));
28680b57cec5SDimitry Andric   RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr, MachinePointerInfo());
28690b57cec5SDimitry Andric 
28700b57cec5SDimitry Andric   return RetAddr;
28710b57cec5SDimitry Andric }
28720b57cec5SDimitry Andric 
28730b57cec5SDimitry Andric static SDValue LowerF64Op(SDValue SrcReg64, const SDLoc &dl, SelectionDAG &DAG,
28740b57cec5SDimitry Andric                           unsigned opcode) {
28750b57cec5SDimitry Andric   assert(SrcReg64.getValueType() == MVT::f64 && "LowerF64Op called on non-double!");
28760b57cec5SDimitry Andric   assert(opcode == ISD::FNEG || opcode == ISD::FABS);
28770b57cec5SDimitry Andric 
28780b57cec5SDimitry Andric   // Lower fneg/fabs on f64 to fneg/fabs on f32.
28790b57cec5SDimitry Andric   // fneg f64 => fneg f32:sub_even, fmov f32:sub_odd.
28800b57cec5SDimitry Andric   // fabs f64 => fabs f32:sub_even, fmov f32:sub_odd.
28810b57cec5SDimitry Andric 
28820b57cec5SDimitry Andric   // Note: in little-endian, the floating-point value is stored in the
28830b57cec5SDimitry Andric   // registers are in the opposite order, so the subreg with the sign
28840b57cec5SDimitry Andric   // bit is the highest-numbered (odd), rather than the
28850b57cec5SDimitry Andric   // lowest-numbered (even).
28860b57cec5SDimitry Andric 
28870b57cec5SDimitry Andric   SDValue Hi32 = DAG.getTargetExtractSubreg(SP::sub_even, dl, MVT::f32,
28880b57cec5SDimitry Andric                                             SrcReg64);
28890b57cec5SDimitry Andric   SDValue Lo32 = DAG.getTargetExtractSubreg(SP::sub_odd, dl, MVT::f32,
28900b57cec5SDimitry Andric                                             SrcReg64);
28910b57cec5SDimitry Andric 
28920b57cec5SDimitry Andric   if (DAG.getDataLayout().isLittleEndian())
28930b57cec5SDimitry Andric     Lo32 = DAG.getNode(opcode, dl, MVT::f32, Lo32);
28940b57cec5SDimitry Andric   else
28950b57cec5SDimitry Andric     Hi32 = DAG.getNode(opcode, dl, MVT::f32, Hi32);
28960b57cec5SDimitry Andric 
28970b57cec5SDimitry Andric   SDValue DstReg64 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
28980b57cec5SDimitry Andric                                                 dl, MVT::f64), 0);
28990b57cec5SDimitry Andric   DstReg64 = DAG.getTargetInsertSubreg(SP::sub_even, dl, MVT::f64,
29000b57cec5SDimitry Andric                                        DstReg64, Hi32);
29010b57cec5SDimitry Andric   DstReg64 = DAG.getTargetInsertSubreg(SP::sub_odd, dl, MVT::f64,
29020b57cec5SDimitry Andric                                        DstReg64, Lo32);
29030b57cec5SDimitry Andric   return DstReg64;
29040b57cec5SDimitry Andric }
29050b57cec5SDimitry Andric 
29060b57cec5SDimitry Andric // Lower a f128 load into two f64 loads.
29070b57cec5SDimitry Andric static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG)
29080b57cec5SDimitry Andric {
29090b57cec5SDimitry Andric   SDLoc dl(Op);
2910e8d8bef9SDimitry Andric   LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode());
2911e8d8bef9SDimitry Andric   assert(LdNode->getOffset().isUndef() && "Unexpected node type");
29120b57cec5SDimitry Andric 
2913e8d8bef9SDimitry Andric   Align Alignment = commonAlignment(LdNode->getOriginalAlign(), 8);
29140b57cec5SDimitry Andric 
29150b57cec5SDimitry Andric   SDValue Hi64 =
29160b57cec5SDimitry Andric       DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LdNode->getBasePtr(),
2917e8d8bef9SDimitry Andric                   LdNode->getPointerInfo(), Alignment);
29180b57cec5SDimitry Andric   EVT addrVT = LdNode->getBasePtr().getValueType();
29190b57cec5SDimitry Andric   SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT,
29200b57cec5SDimitry Andric                               LdNode->getBasePtr(),
29210b57cec5SDimitry Andric                               DAG.getConstant(8, dl, addrVT));
29220b57cec5SDimitry Andric   SDValue Lo64 = DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LoPtr,
2923e8d8bef9SDimitry Andric                              LdNode->getPointerInfo().getWithOffset(8),
2924e8d8bef9SDimitry Andric                              Alignment);
29250b57cec5SDimitry Andric 
29260b57cec5SDimitry Andric   SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32);
29270b57cec5SDimitry Andric   SDValue SubRegOdd  = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32);
29280b57cec5SDimitry Andric 
29290b57cec5SDimitry Andric   SDNode *InFP128 = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
29300b57cec5SDimitry Andric                                        dl, MVT::f128);
29310b57cec5SDimitry Andric   InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
29320b57cec5SDimitry Andric                                MVT::f128,
29330b57cec5SDimitry Andric                                SDValue(InFP128, 0),
29340b57cec5SDimitry Andric                                Hi64,
29350b57cec5SDimitry Andric                                SubRegEven);
29360b57cec5SDimitry Andric   InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
29370b57cec5SDimitry Andric                                MVT::f128,
29380b57cec5SDimitry Andric                                SDValue(InFP128, 0),
29390b57cec5SDimitry Andric                                Lo64,
29400b57cec5SDimitry Andric                                SubRegOdd);
29410b57cec5SDimitry Andric   SDValue OutChains[2] = { SDValue(Hi64.getNode(), 1),
29420b57cec5SDimitry Andric                            SDValue(Lo64.getNode(), 1) };
29430b57cec5SDimitry Andric   SDValue OutChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
29440b57cec5SDimitry Andric   SDValue Ops[2] = {SDValue(InFP128,0), OutChain};
29450b57cec5SDimitry Andric   return DAG.getMergeValues(Ops, dl);
29460b57cec5SDimitry Andric }
29470b57cec5SDimitry Andric 
29480b57cec5SDimitry Andric static SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG)
29490b57cec5SDimitry Andric {
29500b57cec5SDimitry Andric   LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode());
29510b57cec5SDimitry Andric 
29520b57cec5SDimitry Andric   EVT MemVT = LdNode->getMemoryVT();
29530b57cec5SDimitry Andric   if (MemVT == MVT::f128)
29540b57cec5SDimitry Andric     return LowerF128Load(Op, DAG);
29550b57cec5SDimitry Andric 
29560b57cec5SDimitry Andric   return Op;
29570b57cec5SDimitry Andric }
29580b57cec5SDimitry Andric 
29590b57cec5SDimitry Andric // Lower a f128 store into two f64 stores.
29600b57cec5SDimitry Andric static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) {
29610b57cec5SDimitry Andric   SDLoc dl(Op);
2962e8d8bef9SDimitry Andric   StoreSDNode *StNode = cast<StoreSDNode>(Op.getNode());
2963e8d8bef9SDimitry Andric   assert(StNode->getOffset().isUndef() && "Unexpected node type");
2964e8d8bef9SDimitry Andric 
29650b57cec5SDimitry Andric   SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32);
29660b57cec5SDimitry Andric   SDValue SubRegOdd  = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32);
29670b57cec5SDimitry Andric 
29680b57cec5SDimitry Andric   SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG,
29690b57cec5SDimitry Andric                                     dl,
29700b57cec5SDimitry Andric                                     MVT::f64,
29710b57cec5SDimitry Andric                                     StNode->getValue(),
29720b57cec5SDimitry Andric                                     SubRegEven);
29730b57cec5SDimitry Andric   SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG,
29740b57cec5SDimitry Andric                                     dl,
29750b57cec5SDimitry Andric                                     MVT::f64,
29760b57cec5SDimitry Andric                                     StNode->getValue(),
29770b57cec5SDimitry Andric                                     SubRegOdd);
29780b57cec5SDimitry Andric 
2979e8d8bef9SDimitry Andric   Align Alignment = commonAlignment(StNode->getOriginalAlign(), 8);
29800b57cec5SDimitry Andric 
29810b57cec5SDimitry Andric   SDValue OutChains[2];
29820b57cec5SDimitry Andric   OutChains[0] =
29830b57cec5SDimitry Andric       DAG.getStore(StNode->getChain(), dl, SDValue(Hi64, 0),
2984e8d8bef9SDimitry Andric                    StNode->getBasePtr(), StNode->getPointerInfo(),
2985e8d8bef9SDimitry Andric                    Alignment);
29860b57cec5SDimitry Andric   EVT addrVT = StNode->getBasePtr().getValueType();
29870b57cec5SDimitry Andric   SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT,
29880b57cec5SDimitry Andric                               StNode->getBasePtr(),
29890b57cec5SDimitry Andric                               DAG.getConstant(8, dl, addrVT));
29900b57cec5SDimitry Andric   OutChains[1] = DAG.getStore(StNode->getChain(), dl, SDValue(Lo64, 0), LoPtr,
2991e8d8bef9SDimitry Andric                               StNode->getPointerInfo().getWithOffset(8),
2992e8d8bef9SDimitry Andric                               Alignment);
29930b57cec5SDimitry Andric   return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
29940b57cec5SDimitry Andric }
29950b57cec5SDimitry Andric 
29960b57cec5SDimitry Andric static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG)
29970b57cec5SDimitry Andric {
29980b57cec5SDimitry Andric   SDLoc dl(Op);
29990b57cec5SDimitry Andric   StoreSDNode *St = cast<StoreSDNode>(Op.getNode());
30000b57cec5SDimitry Andric 
30010b57cec5SDimitry Andric   EVT MemVT = St->getMemoryVT();
30020b57cec5SDimitry Andric   if (MemVT == MVT::f128)
30030b57cec5SDimitry Andric     return LowerF128Store(Op, DAG);
30040b57cec5SDimitry Andric 
30050b57cec5SDimitry Andric   if (MemVT == MVT::i64) {
30060b57cec5SDimitry Andric     // Custom handling for i64 stores: turn it into a bitcast and a
30070b57cec5SDimitry Andric     // v2i32 store.
30080b57cec5SDimitry Andric     SDValue Val = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, St->getValue());
30090b57cec5SDimitry Andric     SDValue Chain = DAG.getStore(
30100b57cec5SDimitry Andric         St->getChain(), dl, Val, St->getBasePtr(), St->getPointerInfo(),
3011e8d8bef9SDimitry Andric         St->getOriginalAlign(), St->getMemOperand()->getFlags(),
3012e8d8bef9SDimitry Andric         St->getAAInfo());
30130b57cec5SDimitry Andric     return Chain;
30140b57cec5SDimitry Andric   }
30150b57cec5SDimitry Andric 
30160b57cec5SDimitry Andric   return SDValue();
30170b57cec5SDimitry Andric }
30180b57cec5SDimitry Andric 
30190b57cec5SDimitry Andric static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
30200b57cec5SDimitry Andric   assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS)
30210b57cec5SDimitry Andric          && "invalid opcode");
30220b57cec5SDimitry Andric 
30230b57cec5SDimitry Andric   SDLoc dl(Op);
30240b57cec5SDimitry Andric 
30250b57cec5SDimitry Andric   if (Op.getValueType() == MVT::f64)
30260b57cec5SDimitry Andric     return LowerF64Op(Op.getOperand(0), dl, DAG, Op.getOpcode());
30270b57cec5SDimitry Andric   if (Op.getValueType() != MVT::f128)
30280b57cec5SDimitry Andric     return Op;
30290b57cec5SDimitry Andric 
30300b57cec5SDimitry Andric   // Lower fabs/fneg on f128 to fabs/fneg on f64
30310b57cec5SDimitry Andric   // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64
30320b57cec5SDimitry Andric   // (As with LowerF64Op, on little-endian, we need to negate the odd
30330b57cec5SDimitry Andric   // subreg)
30340b57cec5SDimitry Andric 
30350b57cec5SDimitry Andric   SDValue SrcReg128 = Op.getOperand(0);
30360b57cec5SDimitry Andric   SDValue Hi64 = DAG.getTargetExtractSubreg(SP::sub_even64, dl, MVT::f64,
30370b57cec5SDimitry Andric                                             SrcReg128);
30380b57cec5SDimitry Andric   SDValue Lo64 = DAG.getTargetExtractSubreg(SP::sub_odd64, dl, MVT::f64,
30390b57cec5SDimitry Andric                                             SrcReg128);
30400b57cec5SDimitry Andric 
30410b57cec5SDimitry Andric   if (DAG.getDataLayout().isLittleEndian()) {
30420b57cec5SDimitry Andric     if (isV9)
30430b57cec5SDimitry Andric       Lo64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Lo64);
30440b57cec5SDimitry Andric     else
30450b57cec5SDimitry Andric       Lo64 = LowerF64Op(Lo64, dl, DAG, Op.getOpcode());
30460b57cec5SDimitry Andric   } else {
30470b57cec5SDimitry Andric     if (isV9)
30480b57cec5SDimitry Andric       Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64);
30490b57cec5SDimitry Andric     else
30500b57cec5SDimitry Andric       Hi64 = LowerF64Op(Hi64, dl, DAG, Op.getOpcode());
30510b57cec5SDimitry Andric   }
30520b57cec5SDimitry Andric 
30530b57cec5SDimitry Andric   SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
30540b57cec5SDimitry Andric                                                  dl, MVT::f128), 0);
30550b57cec5SDimitry Andric   DstReg128 = DAG.getTargetInsertSubreg(SP::sub_even64, dl, MVT::f128,
30560b57cec5SDimitry Andric                                         DstReg128, Hi64);
30570b57cec5SDimitry Andric   DstReg128 = DAG.getTargetInsertSubreg(SP::sub_odd64, dl, MVT::f128,
30580b57cec5SDimitry Andric                                         DstReg128, Lo64);
30590b57cec5SDimitry Andric   return DstReg128;
30600b57cec5SDimitry Andric }
30610b57cec5SDimitry Andric 
30620b57cec5SDimitry Andric static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) {
30630b57cec5SDimitry Andric 
30640b57cec5SDimitry Andric   if (Op.getValueType() != MVT::i64)
30650b57cec5SDimitry Andric     return Op;
30660b57cec5SDimitry Andric 
30670b57cec5SDimitry Andric   SDLoc dl(Op);
30680b57cec5SDimitry Andric   SDValue Src1 = Op.getOperand(0);
30690b57cec5SDimitry Andric   SDValue Src1Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1);
30700b57cec5SDimitry Andric   SDValue Src1Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src1,
30710b57cec5SDimitry Andric                                DAG.getConstant(32, dl, MVT::i64));
30720b57cec5SDimitry Andric   Src1Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1Hi);
30730b57cec5SDimitry Andric 
30740b57cec5SDimitry Andric   SDValue Src2 = Op.getOperand(1);
30750b57cec5SDimitry Andric   SDValue Src2Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2);
30760b57cec5SDimitry Andric   SDValue Src2Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src2,
30770b57cec5SDimitry Andric                                DAG.getConstant(32, dl, MVT::i64));
30780b57cec5SDimitry Andric   Src2Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2Hi);
30790b57cec5SDimitry Andric 
30800b57cec5SDimitry Andric 
30810b57cec5SDimitry Andric   bool hasChain = false;
30820b57cec5SDimitry Andric   unsigned hiOpc = Op.getOpcode();
30830b57cec5SDimitry Andric   switch (Op.getOpcode()) {
30840b57cec5SDimitry Andric   default: llvm_unreachable("Invalid opcode");
30850b57cec5SDimitry Andric   case ISD::ADDC: hiOpc = ISD::ADDE; break;
30860b57cec5SDimitry Andric   case ISD::ADDE: hasChain = true; break;
30870b57cec5SDimitry Andric   case ISD::SUBC: hiOpc = ISD::SUBE; break;
30880b57cec5SDimitry Andric   case ISD::SUBE: hasChain = true; break;
30890b57cec5SDimitry Andric   }
30900b57cec5SDimitry Andric   SDValue Lo;
30910b57cec5SDimitry Andric   SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Glue);
30920b57cec5SDimitry Andric   if (hasChain) {
30930b57cec5SDimitry Andric     Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo,
30940b57cec5SDimitry Andric                      Op.getOperand(2));
30950b57cec5SDimitry Andric   } else {
30960b57cec5SDimitry Andric     Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo);
30970b57cec5SDimitry Andric   }
30980b57cec5SDimitry Andric   SDValue Hi = DAG.getNode(hiOpc, dl, VTs, Src1Hi, Src2Hi, Lo.getValue(1));
30990b57cec5SDimitry Andric   SDValue Carry = Hi.getValue(1);
31000b57cec5SDimitry Andric 
31010b57cec5SDimitry Andric   Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Lo);
31020b57cec5SDimitry Andric   Hi = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Hi);
31030b57cec5SDimitry Andric   Hi = DAG.getNode(ISD::SHL, dl, MVT::i64, Hi,
31040b57cec5SDimitry Andric                    DAG.getConstant(32, dl, MVT::i64));
31050b57cec5SDimitry Andric 
31060b57cec5SDimitry Andric   SDValue Dst = DAG.getNode(ISD::OR, dl, MVT::i64, Hi, Lo);
31070b57cec5SDimitry Andric   SDValue Ops[2] = { Dst, Carry };
31080b57cec5SDimitry Andric   return DAG.getMergeValues(Ops, dl);
31090b57cec5SDimitry Andric }
31100b57cec5SDimitry Andric 
31110b57cec5SDimitry Andric // Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode()
31120b57cec5SDimitry Andric // in LegalizeDAG.cpp except the order of arguments to the library function.
31130b57cec5SDimitry Andric static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG,
31140b57cec5SDimitry Andric                                 const SparcTargetLowering &TLI)
31150b57cec5SDimitry Andric {
31160b57cec5SDimitry Andric   unsigned opcode = Op.getOpcode();
31170b57cec5SDimitry Andric   assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode.");
31180b57cec5SDimitry Andric 
31190b57cec5SDimitry Andric   bool isSigned = (opcode == ISD::SMULO);
31200b57cec5SDimitry Andric   EVT VT = MVT::i64;
31210b57cec5SDimitry Andric   EVT WideVT = MVT::i128;
31220b57cec5SDimitry Andric   SDLoc dl(Op);
31230b57cec5SDimitry Andric   SDValue LHS = Op.getOperand(0);
31240b57cec5SDimitry Andric 
31250b57cec5SDimitry Andric   if (LHS.getValueType() != VT)
31260b57cec5SDimitry Andric     return Op;
31270b57cec5SDimitry Andric 
31280b57cec5SDimitry Andric   SDValue ShiftAmt = DAG.getConstant(63, dl, VT);
31290b57cec5SDimitry Andric 
31300b57cec5SDimitry Andric   SDValue RHS = Op.getOperand(1);
3131349cc55cSDimitry Andric   SDValue HiLHS, HiRHS;
3132349cc55cSDimitry Andric   if (isSigned) {
3133349cc55cSDimitry Andric     HiLHS = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt);
3134349cc55cSDimitry Andric     HiRHS = DAG.getNode(ISD::SRA, dl, MVT::i64, RHS, ShiftAmt);
3135349cc55cSDimitry Andric   } else {
3136349cc55cSDimitry Andric     HiLHS = DAG.getConstant(0, dl, VT);
3137349cc55cSDimitry Andric     HiRHS = DAG.getConstant(0, dl, MVT::i64);
3138349cc55cSDimitry Andric   }
3139349cc55cSDimitry Andric 
31400b57cec5SDimitry Andric   SDValue Args[] = { HiLHS, LHS, HiRHS, RHS };
31410b57cec5SDimitry Andric 
31428bcb0991SDimitry Andric   TargetLowering::MakeLibCallOptions CallOptions;
31438bcb0991SDimitry Andric   CallOptions.setSExt(isSigned);
31440b57cec5SDimitry Andric   SDValue MulResult = TLI.makeLibCall(DAG,
31450b57cec5SDimitry Andric                                       RTLIB::MUL_I128, WideVT,
31468bcb0991SDimitry Andric                                       Args, CallOptions, dl).first;
31470b57cec5SDimitry Andric   SDValue BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,
31480b57cec5SDimitry Andric                                    MulResult, DAG.getIntPtrConstant(0, dl));
31490b57cec5SDimitry Andric   SDValue TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,
31500b57cec5SDimitry Andric                                 MulResult, DAG.getIntPtrConstant(1, dl));
31510b57cec5SDimitry Andric   if (isSigned) {
31520b57cec5SDimitry Andric     SDValue Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, ShiftAmt);
31530b57cec5SDimitry Andric     TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, Tmp1, ISD::SETNE);
31540b57cec5SDimitry Andric   } else {
31550b57cec5SDimitry Andric     TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, DAG.getConstant(0, dl, VT),
31560b57cec5SDimitry Andric                            ISD::SETNE);
31570b57cec5SDimitry Andric   }
31580b57cec5SDimitry Andric   // MulResult is a node with an illegal type. Because such things are not
31590b57cec5SDimitry Andric   // generally permitted during this phase of legalization, ensure that
31600b57cec5SDimitry Andric   // nothing is left using the node. The above EXTRACT_ELEMENT nodes should have
31610b57cec5SDimitry Andric   // been folded.
31620b57cec5SDimitry Andric   assert(MulResult->use_empty() && "Illegally typed node still in use!");
31630b57cec5SDimitry Andric 
31640b57cec5SDimitry Andric   SDValue Ops[2] = { BottomHalf, TopHalf } ;
31650b57cec5SDimitry Andric   return DAG.getMergeValues(Ops, dl);
31660b57cec5SDimitry Andric }
31670b57cec5SDimitry Andric 
31680b57cec5SDimitry Andric static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) {
3169fe6060f1SDimitry Andric   if (isStrongerThanMonotonic(cast<AtomicSDNode>(Op)->getSuccessOrdering())) {
31700b57cec5SDimitry Andric     // Expand with a fence.
31710b57cec5SDimitry Andric     return SDValue();
3172fe6060f1SDimitry Andric   }
31730b57cec5SDimitry Andric 
31740b57cec5SDimitry Andric   // Monotonic load/stores are legal.
31750b57cec5SDimitry Andric   return Op;
31760b57cec5SDimitry Andric }
31770b57cec5SDimitry Andric 
31780b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
31790b57cec5SDimitry Andric                                                      SelectionDAG &DAG) const {
31800b57cec5SDimitry Andric   unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
31810b57cec5SDimitry Andric   SDLoc dl(Op);
31820b57cec5SDimitry Andric   switch (IntNo) {
31830b57cec5SDimitry Andric   default: return SDValue();    // Don't custom lower most intrinsics.
31840b57cec5SDimitry Andric   case Intrinsic::thread_pointer: {
31850b57cec5SDimitry Andric     EVT PtrVT = getPointerTy(DAG.getDataLayout());
31860b57cec5SDimitry Andric     return DAG.getRegister(SP::G7, PtrVT);
31870b57cec5SDimitry Andric   }
31880b57cec5SDimitry Andric   }
31890b57cec5SDimitry Andric }
31900b57cec5SDimitry Andric 
31910b57cec5SDimitry Andric SDValue SparcTargetLowering::
31920b57cec5SDimitry Andric LowerOperation(SDValue Op, SelectionDAG &DAG) const {
31930b57cec5SDimitry Andric 
31940b57cec5SDimitry Andric   bool hasHardQuad = Subtarget->hasHardQuad();
31950b57cec5SDimitry Andric   bool isV9        = Subtarget->isV9();
3196*bdd1243dSDimitry Andric   bool is64Bit = Subtarget->is64Bit();
31970b57cec5SDimitry Andric 
31980b57cec5SDimitry Andric   switch (Op.getOpcode()) {
31990b57cec5SDimitry Andric   default: llvm_unreachable("Should not custom lower this!");
32000b57cec5SDimitry Andric 
32010b57cec5SDimitry Andric   case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG, *this,
32020b57cec5SDimitry Andric                                                        Subtarget);
32030b57cec5SDimitry Andric   case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG,
32040b57cec5SDimitry Andric                                                       Subtarget);
32050b57cec5SDimitry Andric   case ISD::GlobalTLSAddress:   return LowerGlobalTLSAddress(Op, DAG);
32060b57cec5SDimitry Andric   case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG);
32070b57cec5SDimitry Andric   case ISD::BlockAddress:       return LowerBlockAddress(Op, DAG);
32080b57cec5SDimitry Andric   case ISD::ConstantPool:       return LowerConstantPool(Op, DAG);
32090b57cec5SDimitry Andric   case ISD::FP_TO_SINT:         return LowerFP_TO_SINT(Op, DAG, *this,
32100b57cec5SDimitry Andric                                                        hasHardQuad);
32110b57cec5SDimitry Andric   case ISD::SINT_TO_FP:         return LowerSINT_TO_FP(Op, DAG, *this,
32120b57cec5SDimitry Andric                                                        hasHardQuad);
32130b57cec5SDimitry Andric   case ISD::FP_TO_UINT:         return LowerFP_TO_UINT(Op, DAG, *this,
32140b57cec5SDimitry Andric                                                        hasHardQuad);
32150b57cec5SDimitry Andric   case ISD::UINT_TO_FP:         return LowerUINT_TO_FP(Op, DAG, *this,
32160b57cec5SDimitry Andric                                                        hasHardQuad);
3217*bdd1243dSDimitry Andric   case ISD::BR_CC:
3218*bdd1243dSDimitry Andric     return LowerBR_CC(Op, DAG, *this, hasHardQuad, isV9);
3219*bdd1243dSDimitry Andric   case ISD::SELECT_CC:
3220*bdd1243dSDimitry Andric     return LowerSELECT_CC(Op, DAG, *this, hasHardQuad, isV9, is64Bit);
32210b57cec5SDimitry Andric   case ISD::VASTART:            return LowerVASTART(Op, DAG, *this);
32220b57cec5SDimitry Andric   case ISD::VAARG:              return LowerVAARG(Op, DAG);
32230b57cec5SDimitry Andric   case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG,
32240b57cec5SDimitry Andric                                                                Subtarget);
32250b57cec5SDimitry Andric 
32260b57cec5SDimitry Andric   case ISD::LOAD:               return LowerLOAD(Op, DAG);
32270b57cec5SDimitry Andric   case ISD::STORE:              return LowerSTORE(Op, DAG);
32280b57cec5SDimitry Andric   case ISD::FADD:               return LowerF128Op(Op, DAG,
32290b57cec5SDimitry Andric                                        getLibcallName(RTLIB::ADD_F128), 2);
32300b57cec5SDimitry Andric   case ISD::FSUB:               return LowerF128Op(Op, DAG,
32310b57cec5SDimitry Andric                                        getLibcallName(RTLIB::SUB_F128), 2);
32320b57cec5SDimitry Andric   case ISD::FMUL:               return LowerF128Op(Op, DAG,
32330b57cec5SDimitry Andric                                        getLibcallName(RTLIB::MUL_F128), 2);
32340b57cec5SDimitry Andric   case ISD::FDIV:               return LowerF128Op(Op, DAG,
32350b57cec5SDimitry Andric                                        getLibcallName(RTLIB::DIV_F128), 2);
32360b57cec5SDimitry Andric   case ISD::FSQRT:              return LowerF128Op(Op, DAG,
32370b57cec5SDimitry Andric                                        getLibcallName(RTLIB::SQRT_F128),1);
32380b57cec5SDimitry Andric   case ISD::FABS:
32390b57cec5SDimitry Andric   case ISD::FNEG:               return LowerFNEGorFABS(Op, DAG, isV9);
32400b57cec5SDimitry Andric   case ISD::FP_EXTEND:          return LowerF128_FPEXTEND(Op, DAG, *this);
32410b57cec5SDimitry Andric   case ISD::FP_ROUND:           return LowerF128_FPROUND(Op, DAG, *this);
32420b57cec5SDimitry Andric   case ISD::ADDC:
32430b57cec5SDimitry Andric   case ISD::ADDE:
32440b57cec5SDimitry Andric   case ISD::SUBC:
32450b57cec5SDimitry Andric   case ISD::SUBE:               return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
32460b57cec5SDimitry Andric   case ISD::UMULO:
32470b57cec5SDimitry Andric   case ISD::SMULO:              return LowerUMULO_SMULO(Op, DAG, *this);
32480b57cec5SDimitry Andric   case ISD::ATOMIC_LOAD:
32490b57cec5SDimitry Andric   case ISD::ATOMIC_STORE:       return LowerATOMIC_LOAD_STORE(Op, DAG);
32500b57cec5SDimitry Andric   case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
32510b57cec5SDimitry Andric   }
32520b57cec5SDimitry Andric }
32530b57cec5SDimitry Andric 
32540b57cec5SDimitry Andric SDValue SparcTargetLowering::bitcastConstantFPToInt(ConstantFPSDNode *C,
32550b57cec5SDimitry Andric                                                     const SDLoc &DL,
32560b57cec5SDimitry Andric                                                     SelectionDAG &DAG) const {
32570b57cec5SDimitry Andric   APInt V = C->getValueAPF().bitcastToAPInt();
32580b57cec5SDimitry Andric   SDValue Lo = DAG.getConstant(V.zextOrTrunc(32), DL, MVT::i32);
32590b57cec5SDimitry Andric   SDValue Hi = DAG.getConstant(V.lshr(32).zextOrTrunc(32), DL, MVT::i32);
32600b57cec5SDimitry Andric   if (DAG.getDataLayout().isLittleEndian())
32610b57cec5SDimitry Andric     std::swap(Lo, Hi);
32620b57cec5SDimitry Andric   return DAG.getBuildVector(MVT::v2i32, DL, {Hi, Lo});
32630b57cec5SDimitry Andric }
32640b57cec5SDimitry Andric 
32650b57cec5SDimitry Andric SDValue SparcTargetLowering::PerformBITCASTCombine(SDNode *N,
32660b57cec5SDimitry Andric                                                    DAGCombinerInfo &DCI) const {
32670b57cec5SDimitry Andric   SDLoc dl(N);
32680b57cec5SDimitry Andric   SDValue Src = N->getOperand(0);
32690b57cec5SDimitry Andric 
32700b57cec5SDimitry Andric   if (isa<ConstantFPSDNode>(Src) && N->getSimpleValueType(0) == MVT::v2i32 &&
32710b57cec5SDimitry Andric       Src.getSimpleValueType() == MVT::f64)
32720b57cec5SDimitry Andric     return bitcastConstantFPToInt(cast<ConstantFPSDNode>(Src), dl, DCI.DAG);
32730b57cec5SDimitry Andric 
32740b57cec5SDimitry Andric   return SDValue();
32750b57cec5SDimitry Andric }
32760b57cec5SDimitry Andric 
32770b57cec5SDimitry Andric SDValue SparcTargetLowering::PerformDAGCombine(SDNode *N,
32780b57cec5SDimitry Andric                                                DAGCombinerInfo &DCI) const {
32790b57cec5SDimitry Andric   switch (N->getOpcode()) {
32800b57cec5SDimitry Andric   default:
32810b57cec5SDimitry Andric     break;
32820b57cec5SDimitry Andric   case ISD::BITCAST:
32830b57cec5SDimitry Andric     return PerformBITCASTCombine(N, DCI);
32840b57cec5SDimitry Andric   }
32850b57cec5SDimitry Andric   return SDValue();
32860b57cec5SDimitry Andric }
32870b57cec5SDimitry Andric 
32880b57cec5SDimitry Andric MachineBasicBlock *
32890b57cec5SDimitry Andric SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
32900b57cec5SDimitry Andric                                                  MachineBasicBlock *BB) const {
32910b57cec5SDimitry Andric   switch (MI.getOpcode()) {
32920b57cec5SDimitry Andric   default: llvm_unreachable("Unknown SELECT_CC!");
32930b57cec5SDimitry Andric   case SP::SELECT_CC_Int_ICC:
32940b57cec5SDimitry Andric   case SP::SELECT_CC_FP_ICC:
32950b57cec5SDimitry Andric   case SP::SELECT_CC_DFP_ICC:
32960b57cec5SDimitry Andric   case SP::SELECT_CC_QFP_ICC:
3297*bdd1243dSDimitry Andric     if (Subtarget->isV9())
3298*bdd1243dSDimitry Andric       return expandSelectCC(MI, BB, SP::BPICC);
32990b57cec5SDimitry Andric     return expandSelectCC(MI, BB, SP::BCOND);
330081ad6265SDimitry Andric   case SP::SELECT_CC_Int_XCC:
330181ad6265SDimitry Andric   case SP::SELECT_CC_FP_XCC:
330281ad6265SDimitry Andric   case SP::SELECT_CC_DFP_XCC:
330381ad6265SDimitry Andric   case SP::SELECT_CC_QFP_XCC:
330481ad6265SDimitry Andric     return expandSelectCC(MI, BB, SP::BPXCC);
33050b57cec5SDimitry Andric   case SP::SELECT_CC_Int_FCC:
33060b57cec5SDimitry Andric   case SP::SELECT_CC_FP_FCC:
33070b57cec5SDimitry Andric   case SP::SELECT_CC_DFP_FCC:
33080b57cec5SDimitry Andric   case SP::SELECT_CC_QFP_FCC:
3309*bdd1243dSDimitry Andric     if (Subtarget->isV9())
3310*bdd1243dSDimitry Andric       return expandSelectCC(MI, BB, SP::FBCOND_V9);
33110b57cec5SDimitry Andric     return expandSelectCC(MI, BB, SP::FBCOND);
33120b57cec5SDimitry Andric   }
33130b57cec5SDimitry Andric }
33140b57cec5SDimitry Andric 
33150b57cec5SDimitry Andric MachineBasicBlock *
33160b57cec5SDimitry Andric SparcTargetLowering::expandSelectCC(MachineInstr &MI, MachineBasicBlock *BB,
33170b57cec5SDimitry Andric                                     unsigned BROpcode) const {
33180b57cec5SDimitry Andric   const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
33190b57cec5SDimitry Andric   DebugLoc dl = MI.getDebugLoc();
33200b57cec5SDimitry Andric   unsigned CC = (SPCC::CondCodes)MI.getOperand(3).getImm();
33210b57cec5SDimitry Andric 
33220b57cec5SDimitry Andric   // To "insert" a SELECT_CC instruction, we actually have to insert the
33230b57cec5SDimitry Andric   // triangle control-flow pattern. The incoming instruction knows the
33240b57cec5SDimitry Andric   // destination vreg to set, the condition code register to branch on, the
33250b57cec5SDimitry Andric   // true/false values to select between, and the condition code for the branch.
33260b57cec5SDimitry Andric   //
33270b57cec5SDimitry Andric   // We produce the following control flow:
33280b57cec5SDimitry Andric   //     ThisMBB
33290b57cec5SDimitry Andric   //     |  \
33300b57cec5SDimitry Andric   //     |  IfFalseMBB
33310b57cec5SDimitry Andric   //     | /
33320b57cec5SDimitry Andric   //    SinkMBB
33330b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = BB->getBasicBlock();
33340b57cec5SDimitry Andric   MachineFunction::iterator It = ++BB->getIterator();
33350b57cec5SDimitry Andric 
33360b57cec5SDimitry Andric   MachineBasicBlock *ThisMBB = BB;
33370b57cec5SDimitry Andric   MachineFunction *F = BB->getParent();
33380b57cec5SDimitry Andric   MachineBasicBlock *IfFalseMBB = F->CreateMachineBasicBlock(LLVM_BB);
33390b57cec5SDimitry Andric   MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
33400b57cec5SDimitry Andric   F->insert(It, IfFalseMBB);
33410b57cec5SDimitry Andric   F->insert(It, SinkMBB);
33420b57cec5SDimitry Andric 
33430b57cec5SDimitry Andric   // Transfer the remainder of ThisMBB and its successor edges to SinkMBB.
33440b57cec5SDimitry Andric   SinkMBB->splice(SinkMBB->begin(), ThisMBB,
33450b57cec5SDimitry Andric                   std::next(MachineBasicBlock::iterator(MI)), ThisMBB->end());
33460b57cec5SDimitry Andric   SinkMBB->transferSuccessorsAndUpdatePHIs(ThisMBB);
33470b57cec5SDimitry Andric 
33480b57cec5SDimitry Andric   // Set the new successors for ThisMBB.
33490b57cec5SDimitry Andric   ThisMBB->addSuccessor(IfFalseMBB);
33500b57cec5SDimitry Andric   ThisMBB->addSuccessor(SinkMBB);
33510b57cec5SDimitry Andric 
33520b57cec5SDimitry Andric   BuildMI(ThisMBB, dl, TII.get(BROpcode))
33530b57cec5SDimitry Andric     .addMBB(SinkMBB)
33540b57cec5SDimitry Andric     .addImm(CC);
33550b57cec5SDimitry Andric 
33560b57cec5SDimitry Andric   // IfFalseMBB just falls through to SinkMBB.
33570b57cec5SDimitry Andric   IfFalseMBB->addSuccessor(SinkMBB);
33580b57cec5SDimitry Andric 
33590b57cec5SDimitry Andric   // %Result = phi [ %TrueValue, ThisMBB ], [ %FalseValue, IfFalseMBB ]
33600b57cec5SDimitry Andric   BuildMI(*SinkMBB, SinkMBB->begin(), dl, TII.get(SP::PHI),
33610b57cec5SDimitry Andric           MI.getOperand(0).getReg())
33620b57cec5SDimitry Andric       .addReg(MI.getOperand(1).getReg())
33630b57cec5SDimitry Andric       .addMBB(ThisMBB)
33640b57cec5SDimitry Andric       .addReg(MI.getOperand(2).getReg())
33650b57cec5SDimitry Andric       .addMBB(IfFalseMBB);
33660b57cec5SDimitry Andric 
33670b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
33680b57cec5SDimitry Andric   return SinkMBB;
33690b57cec5SDimitry Andric }
33700b57cec5SDimitry Andric 
33710b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
33720b57cec5SDimitry Andric //                         Sparc Inline Assembly Support
33730b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
33740b57cec5SDimitry Andric 
33750b57cec5SDimitry Andric /// getConstraintType - Given a constraint letter, return the type of
33760b57cec5SDimitry Andric /// constraint it is for this target.
33770b57cec5SDimitry Andric SparcTargetLowering::ConstraintType
33780b57cec5SDimitry Andric SparcTargetLowering::getConstraintType(StringRef Constraint) const {
33790b57cec5SDimitry Andric   if (Constraint.size() == 1) {
33800b57cec5SDimitry Andric     switch (Constraint[0]) {
33810b57cec5SDimitry Andric     default:  break;
33820b57cec5SDimitry Andric     case 'r':
33830b57cec5SDimitry Andric     case 'f':
33840b57cec5SDimitry Andric     case 'e':
33850b57cec5SDimitry Andric       return C_RegisterClass;
33860b57cec5SDimitry Andric     case 'I': // SIMM13
33870b57cec5SDimitry Andric       return C_Immediate;
33880b57cec5SDimitry Andric     }
33890b57cec5SDimitry Andric   }
33900b57cec5SDimitry Andric 
33910b57cec5SDimitry Andric   return TargetLowering::getConstraintType(Constraint);
33920b57cec5SDimitry Andric }
33930b57cec5SDimitry Andric 
33940b57cec5SDimitry Andric TargetLowering::ConstraintWeight SparcTargetLowering::
33950b57cec5SDimitry Andric getSingleConstraintMatchWeight(AsmOperandInfo &info,
33960b57cec5SDimitry Andric                                const char *constraint) const {
33970b57cec5SDimitry Andric   ConstraintWeight weight = CW_Invalid;
33980b57cec5SDimitry Andric   Value *CallOperandVal = info.CallOperandVal;
33990b57cec5SDimitry Andric   // If we don't have a value, we can't do a match,
34000b57cec5SDimitry Andric   // but allow it at the lowest weight.
34010b57cec5SDimitry Andric   if (!CallOperandVal)
34020b57cec5SDimitry Andric     return CW_Default;
34030b57cec5SDimitry Andric 
34040b57cec5SDimitry Andric   // Look at the constraint type.
34050b57cec5SDimitry Andric   switch (*constraint) {
34060b57cec5SDimitry Andric   default:
34070b57cec5SDimitry Andric     weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
34080b57cec5SDimitry Andric     break;
34090b57cec5SDimitry Andric   case 'I': // SIMM13
34100b57cec5SDimitry Andric     if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
34110b57cec5SDimitry Andric       if (isInt<13>(C->getSExtValue()))
34120b57cec5SDimitry Andric         weight = CW_Constant;
34130b57cec5SDimitry Andric     }
34140b57cec5SDimitry Andric     break;
34150b57cec5SDimitry Andric   }
34160b57cec5SDimitry Andric   return weight;
34170b57cec5SDimitry Andric }
34180b57cec5SDimitry Andric 
34190b57cec5SDimitry Andric /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
34200b57cec5SDimitry Andric /// vector.  If it is invalid, don't add anything to Ops.
34210b57cec5SDimitry Andric void SparcTargetLowering::
34220b57cec5SDimitry Andric LowerAsmOperandForConstraint(SDValue Op,
34230b57cec5SDimitry Andric                              std::string &Constraint,
34240b57cec5SDimitry Andric                              std::vector<SDValue> &Ops,
34250b57cec5SDimitry Andric                              SelectionDAG &DAG) const {
342604eeddc0SDimitry Andric   SDValue Result;
34270b57cec5SDimitry Andric 
34280b57cec5SDimitry Andric   // Only support length 1 constraints for now.
34290b57cec5SDimitry Andric   if (Constraint.length() > 1)
34300b57cec5SDimitry Andric     return;
34310b57cec5SDimitry Andric 
34320b57cec5SDimitry Andric   char ConstraintLetter = Constraint[0];
34330b57cec5SDimitry Andric   switch (ConstraintLetter) {
34340b57cec5SDimitry Andric   default: break;
34350b57cec5SDimitry Andric   case 'I':
34360b57cec5SDimitry Andric     if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
34370b57cec5SDimitry Andric       if (isInt<13>(C->getSExtValue())) {
34380b57cec5SDimitry Andric         Result = DAG.getTargetConstant(C->getSExtValue(), SDLoc(Op),
34390b57cec5SDimitry Andric                                        Op.getValueType());
34400b57cec5SDimitry Andric         break;
34410b57cec5SDimitry Andric       }
34420b57cec5SDimitry Andric       return;
34430b57cec5SDimitry Andric     }
34440b57cec5SDimitry Andric   }
34450b57cec5SDimitry Andric 
34460b57cec5SDimitry Andric   if (Result.getNode()) {
34470b57cec5SDimitry Andric     Ops.push_back(Result);
34480b57cec5SDimitry Andric     return;
34490b57cec5SDimitry Andric   }
34500b57cec5SDimitry Andric   TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
34510b57cec5SDimitry Andric }
34520b57cec5SDimitry Andric 
34530b57cec5SDimitry Andric std::pair<unsigned, const TargetRegisterClass *>
34540b57cec5SDimitry Andric SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
34550b57cec5SDimitry Andric                                                   StringRef Constraint,
34560b57cec5SDimitry Andric                                                   MVT VT) const {
345781ad6265SDimitry Andric   if (Constraint.empty())
345881ad6265SDimitry Andric     return std::make_pair(0U, nullptr);
345981ad6265SDimitry Andric 
34600b57cec5SDimitry Andric   if (Constraint.size() == 1) {
34610b57cec5SDimitry Andric     switch (Constraint[0]) {
34620b57cec5SDimitry Andric     case 'r':
34630b57cec5SDimitry Andric       if (VT == MVT::v2i32)
34640b57cec5SDimitry Andric         return std::make_pair(0U, &SP::IntPairRegClass);
34650b57cec5SDimitry Andric       else if (Subtarget->is64Bit())
34660b57cec5SDimitry Andric         return std::make_pair(0U, &SP::I64RegsRegClass);
34670b57cec5SDimitry Andric       else
34680b57cec5SDimitry Andric         return std::make_pair(0U, &SP::IntRegsRegClass);
34690b57cec5SDimitry Andric     case 'f':
34700b57cec5SDimitry Andric       if (VT == MVT::f32 || VT == MVT::i32)
34710b57cec5SDimitry Andric         return std::make_pair(0U, &SP::FPRegsRegClass);
34720b57cec5SDimitry Andric       else if (VT == MVT::f64 || VT == MVT::i64)
34730b57cec5SDimitry Andric         return std::make_pair(0U, &SP::LowDFPRegsRegClass);
34740b57cec5SDimitry Andric       else if (VT == MVT::f128)
34750b57cec5SDimitry Andric         return std::make_pair(0U, &SP::LowQFPRegsRegClass);
34760b57cec5SDimitry Andric       // This will generate an error message
34770b57cec5SDimitry Andric       return std::make_pair(0U, nullptr);
34780b57cec5SDimitry Andric     case 'e':
34790b57cec5SDimitry Andric       if (VT == MVT::f32 || VT == MVT::i32)
34800b57cec5SDimitry Andric         return std::make_pair(0U, &SP::FPRegsRegClass);
34810b57cec5SDimitry Andric       else if (VT == MVT::f64 || VT == MVT::i64 )
34820b57cec5SDimitry Andric         return std::make_pair(0U, &SP::DFPRegsRegClass);
34830b57cec5SDimitry Andric       else if (VT == MVT::f128)
34840b57cec5SDimitry Andric         return std::make_pair(0U, &SP::QFPRegsRegClass);
34850b57cec5SDimitry Andric       // This will generate an error message
34860b57cec5SDimitry Andric       return std::make_pair(0U, nullptr);
34870b57cec5SDimitry Andric     }
348881ad6265SDimitry Andric   }
348981ad6265SDimitry Andric 
349081ad6265SDimitry Andric   if (Constraint.front() != '{')
349181ad6265SDimitry Andric     return std::make_pair(0U, nullptr);
349281ad6265SDimitry Andric 
349381ad6265SDimitry Andric   assert(Constraint.back() == '}' && "Not a brace enclosed constraint?");
349481ad6265SDimitry Andric   StringRef RegName(Constraint.data() + 1, Constraint.size() - 2);
349581ad6265SDimitry Andric   if (RegName.empty())
349681ad6265SDimitry Andric     return std::make_pair(0U, nullptr);
349781ad6265SDimitry Andric 
349881ad6265SDimitry Andric   unsigned long long RegNo;
349981ad6265SDimitry Andric   // Handle numbered register aliases.
350081ad6265SDimitry Andric   if (RegName[0] == 'r' &&
350181ad6265SDimitry Andric       getAsUnsignedInteger(RegName.begin() + 1, 10, RegNo)) {
35020b57cec5SDimitry Andric     // r0-r7   -> g0-g7
35030b57cec5SDimitry Andric     // r8-r15  -> o0-o7
35040b57cec5SDimitry Andric     // r16-r23 -> l0-l7
35050b57cec5SDimitry Andric     // r24-r31 -> i0-i7
350681ad6265SDimitry Andric     if (RegNo > 31)
350781ad6265SDimitry Andric       return std::make_pair(0U, nullptr);
350881ad6265SDimitry Andric     const char RegTypes[] = {'g', 'o', 'l', 'i'};
350981ad6265SDimitry Andric     char RegType = RegTypes[RegNo / 8];
351081ad6265SDimitry Andric     char RegIndex = '0' + (RegNo % 8);
351181ad6265SDimitry Andric     char Tmp[] = {'{', RegType, RegIndex, '}', 0};
351281ad6265SDimitry Andric     return getRegForInlineAsmConstraint(TRI, Tmp, VT);
35130b57cec5SDimitry Andric   }
35140b57cec5SDimitry Andric 
351581ad6265SDimitry Andric   // Rewrite the fN constraint according to the value type if needed.
351681ad6265SDimitry Andric   if (VT != MVT::f32 && VT != MVT::Other && RegName[0] == 'f' &&
351781ad6265SDimitry Andric       getAsUnsignedInteger(RegName.begin() + 1, 10, RegNo)) {
351881ad6265SDimitry Andric     if (VT == MVT::f64 && (RegNo % 2 == 0)) {
351981ad6265SDimitry Andric       return getRegForInlineAsmConstraint(
352081ad6265SDimitry Andric           TRI, StringRef("{d" + utostr(RegNo / 2) + "}"), VT);
352181ad6265SDimitry Andric     } else if (VT == MVT::f128 && (RegNo % 4 == 0)) {
352281ad6265SDimitry Andric       return getRegForInlineAsmConstraint(
352381ad6265SDimitry Andric           TRI, StringRef("{q" + utostr(RegNo / 4) + "}"), VT);
35240b57cec5SDimitry Andric     } else {
35250b57cec5SDimitry Andric       return std::make_pair(0U, nullptr);
35260b57cec5SDimitry Andric     }
35270b57cec5SDimitry Andric   }
35280b57cec5SDimitry Andric 
352981ad6265SDimitry Andric   auto ResultPair =
353081ad6265SDimitry Andric       TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
353181ad6265SDimitry Andric   if (!ResultPair.second)
353281ad6265SDimitry Andric     return std::make_pair(0U, nullptr);
353381ad6265SDimitry Andric 
353481ad6265SDimitry Andric   // Force the use of I64Regs over IntRegs for 64-bit values.
353581ad6265SDimitry Andric   if (Subtarget->is64Bit() && VT == MVT::i64) {
353681ad6265SDimitry Andric     assert(ResultPair.second == &SP::IntRegsRegClass &&
353781ad6265SDimitry Andric            "Unexpected register class");
353881ad6265SDimitry Andric     return std::make_pair(ResultPair.first, &SP::I64RegsRegClass);
353981ad6265SDimitry Andric   }
354081ad6265SDimitry Andric 
354181ad6265SDimitry Andric   return ResultPair;
35420b57cec5SDimitry Andric }
35430b57cec5SDimitry Andric 
35440b57cec5SDimitry Andric bool
35450b57cec5SDimitry Andric SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
35460b57cec5SDimitry Andric   // The Sparc target isn't yet aware of offsets.
35470b57cec5SDimitry Andric   return false;
35480b57cec5SDimitry Andric }
35490b57cec5SDimitry Andric 
35500b57cec5SDimitry Andric void SparcTargetLowering::ReplaceNodeResults(SDNode *N,
35510b57cec5SDimitry Andric                                              SmallVectorImpl<SDValue>& Results,
35520b57cec5SDimitry Andric                                              SelectionDAG &DAG) const {
35530b57cec5SDimitry Andric 
35540b57cec5SDimitry Andric   SDLoc dl(N);
35550b57cec5SDimitry Andric 
35560b57cec5SDimitry Andric   RTLIB::Libcall libCall = RTLIB::UNKNOWN_LIBCALL;
35570b57cec5SDimitry Andric 
35580b57cec5SDimitry Andric   switch (N->getOpcode()) {
35590b57cec5SDimitry Andric   default:
35600b57cec5SDimitry Andric     llvm_unreachable("Do not know how to custom type legalize this operation!");
35610b57cec5SDimitry Andric 
35620b57cec5SDimitry Andric   case ISD::FP_TO_SINT:
35630b57cec5SDimitry Andric   case ISD::FP_TO_UINT:
35640b57cec5SDimitry Andric     // Custom lower only if it involves f128 or i64.
35650b57cec5SDimitry Andric     if (N->getOperand(0).getValueType() != MVT::f128
35660b57cec5SDimitry Andric         || N->getValueType(0) != MVT::i64)
35670b57cec5SDimitry Andric       return;
35680b57cec5SDimitry Andric     libCall = ((N->getOpcode() == ISD::FP_TO_SINT)
35690b57cec5SDimitry Andric                ? RTLIB::FPTOSINT_F128_I64
35700b57cec5SDimitry Andric                : RTLIB::FPTOUINT_F128_I64);
35710b57cec5SDimitry Andric 
35720b57cec5SDimitry Andric     Results.push_back(LowerF128Op(SDValue(N, 0),
35730b57cec5SDimitry Andric                                   DAG,
35740b57cec5SDimitry Andric                                   getLibcallName(libCall),
35750b57cec5SDimitry Andric                                   1));
35760b57cec5SDimitry Andric     return;
35770b57cec5SDimitry Andric   case ISD::READCYCLECOUNTER: {
35780b57cec5SDimitry Andric     assert(Subtarget->hasLeonCycleCounter());
35790b57cec5SDimitry Andric     SDValue Lo = DAG.getCopyFromReg(N->getOperand(0), dl, SP::ASR23, MVT::i32);
35800b57cec5SDimitry Andric     SDValue Hi = DAG.getCopyFromReg(Lo, dl, SP::G0, MVT::i32);
35810b57cec5SDimitry Andric     SDValue Ops[] = { Lo, Hi };
35820b57cec5SDimitry Andric     SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Ops);
35830b57cec5SDimitry Andric     Results.push_back(Pair);
35840b57cec5SDimitry Andric     Results.push_back(N->getOperand(0));
35850b57cec5SDimitry Andric     return;
35860b57cec5SDimitry Andric   }
35870b57cec5SDimitry Andric   case ISD::SINT_TO_FP:
35880b57cec5SDimitry Andric   case ISD::UINT_TO_FP:
35890b57cec5SDimitry Andric     // Custom lower only if it involves f128 or i64.
35900b57cec5SDimitry Andric     if (N->getValueType(0) != MVT::f128
35910b57cec5SDimitry Andric         || N->getOperand(0).getValueType() != MVT::i64)
35920b57cec5SDimitry Andric       return;
35930b57cec5SDimitry Andric 
35940b57cec5SDimitry Andric     libCall = ((N->getOpcode() == ISD::SINT_TO_FP)
35950b57cec5SDimitry Andric                ? RTLIB::SINTTOFP_I64_F128
35960b57cec5SDimitry Andric                : RTLIB::UINTTOFP_I64_F128);
35970b57cec5SDimitry Andric 
35980b57cec5SDimitry Andric     Results.push_back(LowerF128Op(SDValue(N, 0),
35990b57cec5SDimitry Andric                                   DAG,
36000b57cec5SDimitry Andric                                   getLibcallName(libCall),
36010b57cec5SDimitry Andric                                   1));
36020b57cec5SDimitry Andric     return;
36030b57cec5SDimitry Andric   case ISD::LOAD: {
36040b57cec5SDimitry Andric     LoadSDNode *Ld = cast<LoadSDNode>(N);
36050b57cec5SDimitry Andric     // Custom handling only for i64: turn i64 load into a v2i32 load,
36060b57cec5SDimitry Andric     // and a bitcast.
36070b57cec5SDimitry Andric     if (Ld->getValueType(0) != MVT::i64 || Ld->getMemoryVT() != MVT::i64)
36080b57cec5SDimitry Andric       return;
36090b57cec5SDimitry Andric 
36100b57cec5SDimitry Andric     SDLoc dl(N);
36110b57cec5SDimitry Andric     SDValue LoadRes = DAG.getExtLoad(
36120b57cec5SDimitry Andric         Ld->getExtensionType(), dl, MVT::v2i32, Ld->getChain(),
3613e8d8bef9SDimitry Andric         Ld->getBasePtr(), Ld->getPointerInfo(), MVT::v2i32,
3614e8d8bef9SDimitry Andric         Ld->getOriginalAlign(), Ld->getMemOperand()->getFlags(),
3615e8d8bef9SDimitry Andric         Ld->getAAInfo());
36160b57cec5SDimitry Andric 
36170b57cec5SDimitry Andric     SDValue Res = DAG.getNode(ISD::BITCAST, dl, MVT::i64, LoadRes);
36180b57cec5SDimitry Andric     Results.push_back(Res);
36190b57cec5SDimitry Andric     Results.push_back(LoadRes.getValue(1));
36200b57cec5SDimitry Andric     return;
36210b57cec5SDimitry Andric   }
36220b57cec5SDimitry Andric   }
36230b57cec5SDimitry Andric }
36240b57cec5SDimitry Andric 
36250b57cec5SDimitry Andric // Override to enable LOAD_STACK_GUARD lowering on Linux.
36260b57cec5SDimitry Andric bool SparcTargetLowering::useLoadStackGuardNode() const {
36270b57cec5SDimitry Andric   if (!Subtarget->isTargetLinux())
36280b57cec5SDimitry Andric     return TargetLowering::useLoadStackGuardNode();
36290b57cec5SDimitry Andric   return true;
36300b57cec5SDimitry Andric }
36310b57cec5SDimitry Andric 
36320b57cec5SDimitry Andric // Override to disable global variable loading on Linux.
36330b57cec5SDimitry Andric void SparcTargetLowering::insertSSPDeclarations(Module &M) const {
36340b57cec5SDimitry Andric   if (!Subtarget->isTargetLinux())
36350b57cec5SDimitry Andric     return TargetLowering::insertSSPDeclarations(M);
36360b57cec5SDimitry Andric }
3637